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 "common/hashfn.h"
#include "common/int.h"
#include "funcapi.h"
#include "lib/hyperloglog.h"
#include "libpq/pqformat.h"
#include "miscadmin.h"
#include "nodes/nodeFuncs.h"
#include "nodes/supportnodes.h"
#include "optimizer/optimizer.h"
#include "utils/array.h"
#include "utils/builtins.h"
#include "utils/guc.h"
#include "utils/numeric.h"
#include "utils/pg_lsn.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 NBASE_SQR   (NBASE * NBASE)
 
#define NUMERIC_SIGN_MASK   0xC000
 
#define NUMERIC_POS   0x0000
 
#define NUMERIC_NEG   0x4000
 
#define NUMERIC_SHORT   0x8000
 
#define NUMERIC_SPECIAL   0xC000
 
#define NUMERIC_FLAGBITS(n)   ((n)->choice.n_header & NUMERIC_SIGN_MASK)
 
#define NUMERIC_IS_SHORT(n)   (NUMERIC_FLAGBITS(n) == NUMERIC_SHORT)
 
#define NUMERIC_IS_SPECIAL(n)   (NUMERIC_FLAGBITS(n) == NUMERIC_SPECIAL)
 
#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_EXT_SIGN_MASK   0xF000 /* high bits plus NaN/Inf flag bits */
 
#define NUMERIC_NAN   0xC000
 
#define NUMERIC_PINF   0xD000
 
#define NUMERIC_NINF   0xF000
 
#define NUMERIC_INF_SIGN_MASK   0x2000
 
#define NUMERIC_EXT_FLAGBITS(n)   ((n)->choice.n_header & NUMERIC_EXT_SIGN_MASK)
 
#define NUMERIC_IS_NAN(n)   ((n)->choice.n_header == NUMERIC_NAN)
 
#define NUMERIC_IS_PINF(n)   ((n)->choice.n_header == NUMERIC_PINF)
 
#define NUMERIC_IS_NINF(n)   ((n)->choice.n_header == NUMERIC_NINF)
 
#define NUMERIC_IS_INF(n)    (((n)->choice.n_header & ~NUMERIC_INF_SIGN_MASK) == NUMERIC_PINF)
 
#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_DSCALE_MAX   NUMERIC_DSCALE_MASK
 
#define NUMERIC_SIGN(n)
 
#define NUMERIC_DSCALE(n)
 
#define NUMERIC_WEIGHT(n)
 
#define NUMERIC_WEIGHT_MAX   PG_INT16_MAX
 
#define NUMERIC_ABBREV_BITS   (SIZEOF_DATUM * BITS_PER_BYTE)
 
#define NumericAbbrevGetDatum(X)   ((Datum) (X))
 
#define DatumGetNumericAbbrev(X)   ((int32) (X))
 
#define NUMERIC_ABBREV_NAN   NumericAbbrevGetDatum(PG_INT32_MIN)
 
#define NUMERIC_ABBREV_PINF   NumericAbbrevGetDatum(-PG_INT32_MAX)
 
#define NUMERIC_ABBREV_NINF   NumericAbbrevGetDatum(PG_INT32_MAX)
 
#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)   memset(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 NA_TOTAL_COUNT(na)    ((na)->N + (na)->NaNcount + (na)->pInfcount + (na)->nInfcount)
 
#define makePolyNumAggState   makeNumericAggState
 
#define makePolyNumAggStateCurrentContext   makeNumericAggStateCurrentContext
 
#define PRODSUM1(v1, i1, v2, i2)   ((v1)[(i1)] * (v2)[(i2)])
 
#define PRODSUM2(v1, i1, v2, i2)   (PRODSUM1(v1,i1,v2,i2) + (v1)[(i1)+1] * (v2)[(i2)-1])
 
#define PRODSUM3(v1, i1, v2, i2)   (PRODSUM2(v1,i1,v2,i2) + (v1)[(i1)+2] * (v2)[(i2)-2])
 
#define PRODSUM4(v1, i1, v2, i2)   (PRODSUM3(v1,i1,v2,i2) + (v1)[(i1)+3] * (v2)[(i2)-3])
 
#define PRODSUM5(v1, i1, v2, i2)   (PRODSUM4(v1,i1,v2,i2) + (v1)[(i1)+4] * (v2)[(i2)-4])
 
#define PRODSUM6(v1, i1, v2, i2)   (PRODSUM5(v1,i1,v2,i2) + (v1)[(i1)+5] * (v2)[(i2)-5])
 

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 bool set_var_from_str (const char *str, const char *cp, NumericVar *dest, const char **endptr, Node *escontext)
 
static bool set_var_from_non_decimal_integer_str (const char *str, const char *cp, int sign, int base, NumericVar *dest, const char **endptr, Node *escontext)
 
static void set_var_from_num (Numeric num, 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 void numericvar_serialize (StringInfo buf, const NumericVar *var)
 
static void numericvar_deserialize (StringInfo buf, NumericVar *var)
 
static Numeric duplicate_numeric (Numeric num)
 
static Numeric make_result (const NumericVar *var)
 
static Numeric make_result_opt_error (const NumericVar *var, bool *have_error)
 
static bool apply_typmod (NumericVar *var, int32 typmod, Node *escontext)
 
static bool apply_typmod_special (Numeric num, int32 typmod, Node *escontext)
 
static bool numericvar_to_int32 (const NumericVar *var, int32 *result)
 
static bool numericvar_to_int64 (const NumericVar *var, int64 *result)
 
static void int64_to_numericvar (int64 val, NumericVar *var)
 
static bool numericvar_to_uint64 (const NumericVar *var, uint64 *result)
 
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 mul_var_short (const NumericVar *var1, const NumericVar *var2, NumericVar *result)
 
static void div_var (const NumericVar *var1, const NumericVar *var2, NumericVar *result, int rscale, bool round, bool exact)
 
static void div_var_int (const NumericVar *var, int ival, int ival_weight, 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 div_mod_var (const NumericVar *var1, const NumericVar *var2, NumericVar *quot, NumericVar *rem)
 
static void ceil_var (const NumericVar *var, NumericVar *result)
 
static void floor_var (const NumericVar *var, NumericVar *result)
 
static void gcd_var (const NumericVar *var1, const NumericVar *var2, 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, int exp_dscale, NumericVar *result)
 
static void power_ten_int (int exp, NumericVar *result)
 
static void random_var (pg_prng_state *state, const NumericVar *rmin, const NumericVar *rmax, NumericVar *result)
 
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 *val)
 
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)
 
bool numeric_is_inf (Numeric num)
 
static bool numeric_is_integral (Numeric num)
 
static int32 make_numeric_typmod (int precision, int scale)
 
static bool is_valid_numeric_typmod (int32 typmod)
 
static int numeric_typmod_precision (int32 typmod)
 
static int numeric_typmod_scale (int32 typmod)
 
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_support (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)
 
static int numeric_sign_internal (Numeric num)
 
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 generate_series_numeric_support (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 in_range_numeric_numeric (PG_FUNCTION_ARGS)
 
Datum hash_numeric (PG_FUNCTION_ARGS)
 
Datum hash_numeric_extended (PG_FUNCTION_ARGS)
 
Datum numeric_add (PG_FUNCTION_ARGS)
 
Numeric numeric_add_opt_error (Numeric num1, Numeric num2, bool *have_error)
 
Datum numeric_sub (PG_FUNCTION_ARGS)
 
Numeric numeric_sub_opt_error (Numeric num1, Numeric num2, bool *have_error)
 
Datum numeric_mul (PG_FUNCTION_ARGS)
 
Numeric numeric_mul_opt_error (Numeric num1, Numeric num2, bool *have_error)
 
Datum numeric_div (PG_FUNCTION_ARGS)
 
Numeric numeric_div_opt_error (Numeric num1, Numeric num2, bool *have_error)
 
Datum numeric_div_trunc (PG_FUNCTION_ARGS)
 
Datum numeric_mod (PG_FUNCTION_ARGS)
 
Numeric numeric_mod_opt_error (Numeric num1, Numeric num2, bool *have_error)
 
Datum numeric_inc (PG_FUNCTION_ARGS)
 
Datum numeric_smaller (PG_FUNCTION_ARGS)
 
Datum numeric_larger (PG_FUNCTION_ARGS)
 
Datum numeric_gcd (PG_FUNCTION_ARGS)
 
Datum numeric_lcm (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)
 
static int get_min_scale (NumericVar *var)
 
Datum numeric_min_scale (PG_FUNCTION_ARGS)
 
Datum numeric_trim_scale (PG_FUNCTION_ARGS)
 
Numeric random_numeric (pg_prng_state *state, Numeric rmin, Numeric rmax)
 
Numeric int64_to_numeric (int64 val)
 
Numeric int64_div_fast_to_numeric (int64 val1, int log10val2)
 
Datum int4_numeric (PG_FUNCTION_ARGS)
 
int32 numeric_int4_opt_error (Numeric num, bool *have_error)
 
Datum numeric_int4 (PG_FUNCTION_ARGS)
 
Datum int8_numeric (PG_FUNCTION_ARGS)
 
int64 numeric_int8_opt_error (Numeric num, bool *have_error)
 
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)
 
Datum numeric_pg_lsn (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)
 
static int xdigit_value (char dig)
 

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 NumericVar const_minus_one
 
static const NumericDigit const_two_data [1] = {2}
 
static const NumericVar const_two
 
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 NumericVar const_pinf
 
static const NumericVar const_ninf
 
static const int round_powers [4] = {0, 1000, 100, 10}
 

Macro Definition Documentation

◆ DatumGetNumericAbbrev

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

Definition at line 413 of file numeric.c.

◆ DEC_DIGITS

#define DEC_DIGITS   4 /* decimal digits per NBASE digit */

Definition at line 98 of file numeric.c.

◆ digitbuf_alloc

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

Definition at line 486 of file numeric.c.

◆ digitbuf_free

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

Definition at line 488 of file numeric.c.

◆ DIV_GUARD_DIGITS

#define DIV_GUARD_DIGITS   4

Definition at line 100 of file numeric.c.

◆ dump_numeric

#define dump_numeric (   s,
 
)

Definition at line 482 of file numeric.c.

◆ dump_var

#define dump_var (   s,
 
)

Definition at line 483 of file numeric.c.

◆ HALF_NBASE

#define HALF_NBASE   5000

Definition at line 97 of file numeric.c.

◆ init_var

#define init_var (   v)    memset(v, 0, sizeof(NumericVar))

Definition at line 494 of file numeric.c.

◆ makePolyNumAggState

#define makePolyNumAggState   makeNumericAggState

Definition at line 5663 of file numeric.c.

◆ makePolyNumAggStateCurrentContext

#define makePolyNumAggStateCurrentContext   makeNumericAggStateCurrentContext

Definition at line 5664 of file numeric.c.

◆ MUL_GUARD_DIGITS

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

Definition at line 99 of file numeric.c.

◆ NA_TOTAL_COUNT

#define NA_TOTAL_COUNT (   na)     ((na)->N + (na)->NaNcount + (na)->pInfcount + (na)->nInfcount)

Definition at line 4927 of file numeric.c.

◆ NBASE

#define NBASE   10000

Definition at line 96 of file numeric.c.

◆ NBASE_SQR

#define NBASE_SQR   (NBASE * NBASE)

Definition at line 105 of file numeric.c.

◆ NUMERIC_ABBREV_BITS

#define NUMERIC_ABBREV_BITS   (SIZEOF_DATUM * BITS_PER_BYTE)

Definition at line 404 of file numeric.c.

◆ NUMERIC_ABBREV_NAN

#define NUMERIC_ABBREV_NAN   NumericAbbrevGetDatum(PG_INT32_MIN)

Definition at line 414 of file numeric.c.

◆ NUMERIC_ABBREV_NINF

#define NUMERIC_ABBREV_NINF   NumericAbbrevGetDatum(PG_INT32_MAX)

Definition at line 416 of file numeric.c.

◆ NUMERIC_ABBREV_PINF

#define NUMERIC_ABBREV_PINF   NumericAbbrevGetDatum(-PG_INT32_MAX)

Definition at line 415 of file numeric.c.

◆ NUMERIC_CAN_BE_SHORT

#define NUMERIC_CAN_BE_SHORT (   scale,
  weight 
)
Value:
(weight) <= NUMERIC_SHORT_WEIGHT_MAX && \
#define NUMERIC_SHORT_DSCALE_MAX
Definition: numeric.c:219
#define NUMERIC_SHORT_WEIGHT_MIN
Definition: numeric.c:224
#define NUMERIC_SHORT_WEIGHT_MAX
Definition: numeric.c:223
static int scale
Definition: pgbench.c:181

Definition at line 500 of file numeric.c.

◆ 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:185

Definition at line 496 of file numeric.c.

◆ 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_DSCALE_MASK
Definition: numeric.c:236
#define NUMERIC_SHORT_DSCALE_MASK
Definition: numeric.c:217
#define NUMERIC_SHORT_DSCALE_SHIFT
Definition: numeric.c:218

Definition at line 245 of file numeric.c.

◆ NUMERIC_DSCALE_MASK

#define NUMERIC_DSCALE_MASK   0x3FFF

Definition at line 236 of file numeric.c.

◆ NUMERIC_DSCALE_MAX

#define NUMERIC_DSCALE_MAX   NUMERIC_DSCALE_MASK

Definition at line 237 of file numeric.c.

◆ NUMERIC_EXT_FLAGBITS

#define NUMERIC_EXT_FLAGBITS (   n)    ((n)->choice.n_header & NUMERIC_EXT_SIGN_MASK)

Definition at line 205 of file numeric.c.

◆ NUMERIC_EXT_SIGN_MASK

#define NUMERIC_EXT_SIGN_MASK   0xF000 /* high bits plus NaN/Inf flag bits */

Definition at line 199 of file numeric.c.

◆ NUMERIC_FLAGBITS

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

Definition at line 173 of file numeric.c.

◆ NUMERIC_HDRSZ

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

Definition at line 177 of file numeric.c.

◆ NUMERIC_HDRSZ_SHORT

#define NUMERIC_HDRSZ_SHORT   (VARHDRSZ + sizeof(uint16))

Definition at line 178 of file numeric.c.

◆ NUMERIC_HEADER_IS_SHORT

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

Definition at line 185 of file numeric.c.

◆ NUMERIC_HEADER_SIZE

#define NUMERIC_HEADER_SIZE (   n)
Value:
(VARHDRSZ + sizeof(uint16) + \
(NUMERIC_HEADER_IS_SHORT(n) ? 0 : sizeof(int16)))
unsigned short uint16
Definition: c.h:491
signed short int16
Definition: c.h:481
#define VARHDRSZ
Definition: c.h:671

Definition at line 186 of file numeric.c.

◆ NUMERIC_INF_SIGN_MASK

#define NUMERIC_INF_SIGN_MASK   0x2000

Definition at line 203 of file numeric.c.

◆ NUMERIC_IS_INF

#define NUMERIC_IS_INF (   n)     (((n)->choice.n_header & ~NUMERIC_INF_SIGN_MASK) == NUMERIC_PINF)

Definition at line 209 of file numeric.c.

◆ NUMERIC_IS_NAN

#define NUMERIC_IS_NAN (   n)    ((n)->choice.n_header == NUMERIC_NAN)

Definition at line 206 of file numeric.c.

◆ NUMERIC_IS_NINF

#define NUMERIC_IS_NINF (   n)    ((n)->choice.n_header == NUMERIC_NINF)

Definition at line 208 of file numeric.c.

◆ NUMERIC_IS_PINF

#define NUMERIC_IS_PINF (   n)    ((n)->choice.n_header == NUMERIC_PINF)

Definition at line 207 of file numeric.c.

◆ NUMERIC_IS_SHORT

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

Definition at line 174 of file numeric.c.

◆ NUMERIC_IS_SPECIAL

#define NUMERIC_IS_SPECIAL (   n)    (NUMERIC_FLAGBITS(n) == NUMERIC_SPECIAL)

Definition at line 175 of file numeric.c.

◆ NUMERIC_NAN

#define NUMERIC_NAN   0xC000

Definition at line 200 of file numeric.c.

◆ NUMERIC_NDIGITS

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

Definition at line 498 of file numeric.c.

◆ NUMERIC_NEG

#define NUMERIC_NEG   0x4000

Definition at line 169 of file numeric.c.

◆ NUMERIC_NINF

#define NUMERIC_NINF   0xF000

Definition at line 202 of file numeric.c.

◆ NUMERIC_PINF

#define NUMERIC_PINF   0xD000

Definition at line 201 of file numeric.c.

◆ NUMERIC_POS

#define NUMERIC_POS   0x0000

Definition at line 168 of file numeric.c.

◆ NUMERIC_SHORT

#define NUMERIC_SHORT   0x8000

Definition at line 170 of file numeric.c.

◆ NUMERIC_SHORT_DSCALE_MASK

#define NUMERIC_SHORT_DSCALE_MASK   0x1F80

Definition at line 217 of file numeric.c.

◆ NUMERIC_SHORT_DSCALE_MAX

#define NUMERIC_SHORT_DSCALE_MAX    (NUMERIC_SHORT_DSCALE_MASK >> NUMERIC_SHORT_DSCALE_SHIFT)

Definition at line 219 of file numeric.c.

◆ NUMERIC_SHORT_DSCALE_SHIFT

#define NUMERIC_SHORT_DSCALE_SHIFT   7

Definition at line 218 of file numeric.c.

◆ NUMERIC_SHORT_SIGN_MASK

#define NUMERIC_SHORT_SIGN_MASK   0x2000

Definition at line 216 of file numeric.c.

◆ NUMERIC_SHORT_WEIGHT_MASK

#define NUMERIC_SHORT_WEIGHT_MASK   0x003F

Definition at line 222 of file numeric.c.

◆ NUMERIC_SHORT_WEIGHT_MAX

#define NUMERIC_SHORT_WEIGHT_MAX   NUMERIC_SHORT_WEIGHT_MASK

Definition at line 223 of file numeric.c.

◆ NUMERIC_SHORT_WEIGHT_MIN

#define NUMERIC_SHORT_WEIGHT_MIN   (-(NUMERIC_SHORT_WEIGHT_MASK+1))

Definition at line 224 of file numeric.c.

◆ NUMERIC_SHORT_WEIGHT_SIGN_MASK

#define NUMERIC_SHORT_WEIGHT_SIGN_MASK   0x0040

Definition at line 221 of file numeric.c.

◆ NUMERIC_SIGN

#define NUMERIC_SIGN (   n)
Value:
(((n)->choice.n_short.n_header & NUMERIC_SHORT_SIGN_MASK) ? \
NUMERIC_NEG : NUMERIC_POS) : \
NUMERIC_EXT_FLAGBITS(n) : NUMERIC_FLAGBITS(n)))
#define NUMERIC_IS_SPECIAL(n)
Definition: numeric.c:175
#define NUMERIC_FLAGBITS(n)
Definition: numeric.c:173
#define NUMERIC_SHORT_SIGN_MASK
Definition: numeric.c:216
#define NUMERIC_IS_SHORT(n)
Definition: numeric.c:174
#define NUMERIC_POS
Definition: numeric.c:168

Definition at line 239 of file numeric.c.

◆ NUMERIC_SIGN_MASK

#define NUMERIC_SIGN_MASK   0xC000

Definition at line 167 of file numeric.c.

◆ NUMERIC_SPECIAL

#define NUMERIC_SPECIAL   0xC000

Definition at line 171 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_SHORT_WEIGHT_MASK
Definition: numeric.c:222
#define NUMERIC_SHORT_WEIGHT_SIGN_MASK
Definition: numeric.c:221

Definition at line 249 of file numeric.c.

◆ NUMERIC_WEIGHT_MAX

#define NUMERIC_WEIGHT_MAX   PG_INT16_MAX

Definition at line 260 of file numeric.c.

◆ NumericAbbrevGetDatum

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

Definition at line 412 of file numeric.c.

◆ PRODSUM1

#define PRODSUM1 (   v1,
  i1,
  v2,
  i2 
)    ((v1)[(i1)] * (v2)[(i2)])

◆ PRODSUM2

#define PRODSUM2 (   v1,
  i1,
  v2,
  i2 
)    (PRODSUM1(v1,i1,v2,i2) + (v1)[(i1)+1] * (v2)[(i2)-1])

◆ PRODSUM3

#define PRODSUM3 (   v1,
  i1,
  v2,
  i2 
)    (PRODSUM2(v1,i1,v2,i2) + (v1)[(i1)+2] * (v2)[(i2)-2])

◆ PRODSUM4

#define PRODSUM4 (   v1,
  i1,
  v2,
  i2 
)    (PRODSUM3(v1,i1,v2,i2) + (v1)[(i1)+3] * (v2)[(i2)-3])

◆ PRODSUM5

#define PRODSUM5 (   v1,
  i1,
  v2,
  i2 
)    (PRODSUM4(v1,i1,v2,i2) + (v1)[(i1)+4] * (v2)[(i2)-4])

◆ PRODSUM6

#define PRODSUM6 (   v1,
  i1,
  v2,
  i2 
)    (PRODSUM5(v1,i1,v2,i2) + (v1)[(i1)+5] * (v2)[(i2)-5])

Typedef Documentation

◆ Int8TransTypeData

◆ NumericAggState

◆ NumericDigit

Definition at line 102 of file numeric.c.

◆ NumericSumAccum

◆ NumericVar

typedef struct NumericVar NumericVar

◆ PolyNumAggState

Definition at line 5662 of file numeric.c.

Function Documentation

◆ accum_sum_add()

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

Definition at line 12333 of file numeric.c.

12334 {
12335  int32 *accum_digits;
12336  int i,
12337  val_i;
12338  int val_ndigits;
12339  NumericDigit *val_digits;
12340 
12341  /*
12342  * If we have accumulated too many values since the last carry
12343  * propagation, do it now, to avoid overflowing. (We could allow more
12344  * than NBASE - 1, if we reserved two extra digits, rather than one, for
12345  * carry propagation. But even with NBASE - 1, this needs to be done so
12346  * seldom, that the performance difference is negligible.)
12347  */
12348  if (accum->num_uncarried == NBASE - 1)
12349  accum_sum_carry(accum);
12350 
12351  /*
12352  * Adjust the weight or scale of the old value, so that it can accommodate
12353  * the new value.
12354  */
12355  accum_sum_rescale(accum, val);
12356 
12357  /* */
12358  if (val->sign == NUMERIC_POS)
12359  accum_digits = accum->pos_digits;
12360  else
12361  accum_digits = accum->neg_digits;
12362 
12363  /* copy these values into local vars for speed in loop */
12364  val_ndigits = val->ndigits;
12365  val_digits = val->digits;
12366 
12367  i = accum->weight - val->weight;
12368  for (val_i = 0; val_i < val_ndigits; val_i++)
12369  {
12370  accum_digits[i] += (int32) val_digits[val_i];
12371  i++;
12372  }
12373 
12374  accum->num_uncarried++;
12375 }
static void accum_sum_carry(NumericSumAccum *accum)
Definition: numeric.c:12381
int16 NumericDigit
Definition: numeric.c:102
#define NBASE
Definition: numeric.c:96
static void accum_sum_rescale(NumericSumAccum *accum, const NumericVar *val)
Definition: numeric.c:12454
signed int int32
Definition: c.h:482
long val
Definition: informix.c:689
int i
Definition: isn.c:72
int32 * pos_digits
Definition: numeric.c:387
int num_uncarried
Definition: numeric.c:385
int32 * neg_digits
Definition: numeric.c:388

References accum_sum_carry(), accum_sum_rescale(), i, NBASE, NumericSumAccum::neg_digits, NumericSumAccum::num_uncarried, NUMERIC_POS, NumericSumAccum::pos_digits, val, and NumericSumAccum::weight.

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

◆ accum_sum_carry()

static void accum_sum_carry ( NumericSumAccum accum)
static

Definition at line 12381 of file numeric.c.

12382 {
12383  int i;
12384  int ndigits;
12385  int32 *dig;
12386  int32 carry;
12387  int32 newdig = 0;
12388 
12389  /*
12390  * If no new values have been added since last carry propagation, nothing
12391  * to do.
12392  */
12393  if (accum->num_uncarried == 0)
12394  return;
12395 
12396  /*
12397  * We maintain that the weight of the accumulator is always one larger
12398  * than needed to hold the current value, before carrying, to make sure
12399  * there is enough space for the possible extra digit when carry is
12400  * propagated. We cannot expand the buffer here, unless we require
12401  * callers of accum_sum_final() to switch to the right memory context.
12402  */
12403  Assert(accum->pos_digits[0] == 0 && accum->neg_digits[0] == 0);
12404 
12405  ndigits = accum->ndigits;
12406 
12407  /* Propagate carry in the positive sum */
12408  dig = accum->pos_digits;
12409  carry = 0;
12410  for (i = ndigits - 1; i >= 0; i--)
12411  {
12412  newdig = dig[i] + carry;
12413  if (newdig >= NBASE)
12414  {
12415  carry = newdig / NBASE;
12416  newdig -= carry * NBASE;
12417  }
12418  else
12419  carry = 0;
12420  dig[i] = newdig;
12421  }
12422  /* Did we use up the digit reserved for carry propagation? */
12423  if (newdig > 0)
12424  accum->have_carry_space = false;
12425 
12426  /* And the same for the negative sum */
12427  dig = accum->neg_digits;
12428  carry = 0;
12429  for (i = ndigits - 1; i >= 0; i--)
12430  {
12431  newdig = dig[i] + carry;
12432  if (newdig >= NBASE)
12433  {
12434  carry = newdig / NBASE;
12435  newdig -= carry * NBASE;
12436  }
12437  else
12438  carry = 0;
12439  dig[i] = newdig;
12440  }
12441  if (newdig > 0)
12442  accum->have_carry_space = false;
12443 
12444  accum->num_uncarried = 0;
12445 }
#define Assert(condition)
Definition: c.h:837
bool have_carry_space
Definition: numeric.c:386

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().

◆ accum_sum_combine()

static void accum_sum_combine ( NumericSumAccum accum,
NumericSumAccum accum2 
)
static

Definition at line 12611 of file numeric.c.

12612 {
12613  NumericVar tmp_var;
12614 
12615  init_var(&tmp_var);
12616 
12617  accum_sum_final(accum2, &tmp_var);
12618  accum_sum_add(accum, &tmp_var);
12619 
12620  free_var(&tmp_var);
12621 }
static void accum_sum_final(NumericSumAccum *accum, NumericVar *result)
Definition: numeric.c:12543
static void free_var(NumericVar *var)
Definition: numeric.c:7087
static void accum_sum_add(NumericSumAccum *accum, const NumericVar *val)
Definition: numeric.c:12333
#define init_var(v)
Definition: numeric.c:494

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().

◆ accum_sum_copy()

static void accum_sum_copy ( NumericSumAccum dst,
NumericSumAccum src 
)
static

Definition at line 12594 of file numeric.c.

12595 {
12596  dst->pos_digits = palloc(src->ndigits * sizeof(int32));
12597  dst->neg_digits = palloc(src->ndigits * sizeof(int32));
12598 
12599  memcpy(dst->pos_digits, src->pos_digits, src->ndigits * sizeof(int32));
12600  memcpy(dst->neg_digits, src->neg_digits, src->ndigits * sizeof(int32));
12601  dst->num_uncarried = src->num_uncarried;
12602  dst->ndigits = src->ndigits;
12603  dst->weight = src->weight;
12604  dst->dscale = src->dscale;
12605 }
void * palloc(Size size)
Definition: mcxt.c:1317

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().

◆ accum_sum_final()

static void accum_sum_final ( NumericSumAccum accum,
NumericVar result 
)
static

Definition at line 12543 of file numeric.c.

12544 {
12545  int i;
12546  NumericVar pos_var;
12547  NumericVar neg_var;
12548 
12549  if (accum->ndigits == 0)
12550  {
12551  set_var_from_var(&const_zero, result);
12552  return;
12553  }
12554 
12555  /* Perform final carry */
12556  accum_sum_carry(accum);
12557 
12558  /* Create NumericVars representing the positive and negative sums */
12559  init_var(&pos_var);
12560  init_var(&neg_var);
12561 
12562  pos_var.ndigits = neg_var.ndigits = accum->ndigits;
12563  pos_var.weight = neg_var.weight = accum->weight;
12564  pos_var.dscale = neg_var.dscale = accum->dscale;
12565  pos_var.sign = NUMERIC_POS;
12566  neg_var.sign = NUMERIC_NEG;
12567 
12568  pos_var.buf = pos_var.digits = digitbuf_alloc(accum->ndigits);
12569  neg_var.buf = neg_var.digits = digitbuf_alloc(accum->ndigits);
12570 
12571  for (i = 0; i < accum->ndigits; i++)
12572  {
12573  Assert(accum->pos_digits[i] < NBASE);
12574  pos_var.digits[i] = (int16) accum->pos_digits[i];
12575 
12576  Assert(accum->neg_digits[i] < NBASE);
12577  neg_var.digits[i] = (int16) accum->neg_digits[i];
12578  }
12579 
12580  /* And add them together */
12581  add_var(&pos_var, &neg_var, result);
12582 
12583  /* Remove leading/trailing zeroes */
12584  strip_var(result);
12585 }
static void add_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition: numeric.c:8549
#define NUMERIC_NEG
Definition: numeric.c:169
#define digitbuf_alloc(ndigits)
Definition: numeric.c:486
static const NumericVar const_zero
Definition: numeric.c:425
static void set_var_from_var(const NumericVar *value, NumericVar *dest)
Definition: numeric.c:7586
static void strip_var(NumericVar *var)
Definition: numeric.c:12276
int ndigits
Definition: numeric.c:315
NumericDigit * digits
Definition: numeric.c:320
int dscale
Definition: numeric.c:318
int sign
Definition: numeric.c:317
NumericDigit * buf
Definition: numeric.c:319
int weight
Definition: numeric.c:316

References accum_sum_carry(), add_var(), Assert, NumericVar::buf, const_zero, 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().

◆ accum_sum_rescale()

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

Definition at line 12454 of file numeric.c.

12455 {
12456  int old_weight = accum->weight;
12457  int old_ndigits = accum->ndigits;
12458  int accum_ndigits;
12459  int accum_weight;
12460  int accum_rscale;
12461  int val_rscale;
12462 
12463  accum_weight = old_weight;
12464  accum_ndigits = old_ndigits;
12465 
12466  /*
12467  * Does the new value have a larger weight? If so, enlarge the buffers,
12468  * and shift the existing value to the new weight, by adding leading
12469  * zeros.
12470  *
12471  * We enforce that the accumulator always has a weight one larger than
12472  * needed for the inputs, so that we have space for an extra digit at the
12473  * final carry-propagation phase, if necessary.
12474  */
12475  if (val->weight >= accum_weight)
12476  {
12477  accum_weight = val->weight + 1;
12478  accum_ndigits = accum_ndigits + (accum_weight - old_weight);
12479  }
12480 
12481  /*
12482  * Even though the new value is small, we might've used up the space
12483  * reserved for the carry digit in the last call to accum_sum_carry(). If
12484  * so, enlarge to make room for another one.
12485  */
12486  else if (!accum->have_carry_space)
12487  {
12488  accum_weight++;
12489  accum_ndigits++;
12490  }
12491 
12492  /* Is the new value wider on the right side? */
12493  accum_rscale = accum_ndigits - accum_weight - 1;
12494  val_rscale = val->ndigits - val->weight - 1;
12495  if (val_rscale > accum_rscale)
12496  accum_ndigits = accum_ndigits + (val_rscale - accum_rscale);
12497 
12498  if (accum_ndigits != old_ndigits ||
12499  accum_weight != old_weight)
12500  {
12501  int32 *new_pos_digits;
12502  int32 *new_neg_digits;
12503  int weightdiff;
12504 
12505  weightdiff = accum_weight - old_weight;
12506 
12507  new_pos_digits = palloc0(accum_ndigits * sizeof(int32));
12508  new_neg_digits = palloc0(accum_ndigits * sizeof(int32));
12509 
12510  if (accum->pos_digits)
12511  {
12512  memcpy(&new_pos_digits[weightdiff], accum->pos_digits,
12513  old_ndigits * sizeof(int32));
12514  pfree(accum->pos_digits);
12515 
12516  memcpy(&new_neg_digits[weightdiff], accum->neg_digits,
12517  old_ndigits * sizeof(int32));
12518  pfree(accum->neg_digits);
12519  }
12520 
12521  accum->pos_digits = new_pos_digits;
12522  accum->neg_digits = new_neg_digits;
12523 
12524  accum->weight = accum_weight;
12525  accum->ndigits = accum_ndigits;
12526 
12527  Assert(accum->pos_digits[0] == 0 && accum->neg_digits[0] == 0);
12528  accum->have_carry_space = true;
12529  }
12530 
12531  if (val->dscale > accum->dscale)
12532  accum->dscale = val->dscale;
12533 }
void pfree(void *pointer)
Definition: mcxt.c:1521
void * palloc0(Size size)
Definition: mcxt.c:1347

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

Referenced by accum_sum_add().

◆ accum_sum_reset()

static void accum_sum_reset ( NumericSumAccum accum)
static

Definition at line 12317 of file numeric.c.

12318 {
12319  int i;
12320 
12321  accum->dscale = 0;
12322  for (i = 0; i < accum->ndigits; i++)
12323  {
12324  accum->pos_digits[i] = 0;
12325  accum->neg_digits[i] = 0;
12326  }
12327 }

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

Referenced by do_numeric_discard().

◆ add_abs()

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

Definition at line 11941 of file numeric.c.

11942 {
11943  NumericDigit *res_buf;
11944  NumericDigit *res_digits;
11945  int res_ndigits;
11946  int res_weight;
11947  int res_rscale,
11948  rscale1,
11949  rscale2;
11950  int res_dscale;
11951  int i,
11952  i1,
11953  i2;
11954  int carry = 0;
11955 
11956  /* copy these values into local vars for speed in inner loop */
11957  int var1ndigits = var1->ndigits;
11958  int var2ndigits = var2->ndigits;
11959  NumericDigit *var1digits = var1->digits;
11960  NumericDigit *var2digits = var2->digits;
11961 
11962  res_weight = Max(var1->weight, var2->weight) + 1;
11963 
11964  res_dscale = Max(var1->dscale, var2->dscale);
11965 
11966  /* Note: here we are figuring rscale in base-NBASE digits */
11967  rscale1 = var1->ndigits - var1->weight - 1;
11968  rscale2 = var2->ndigits - var2->weight - 1;
11969  res_rscale = Max(rscale1, rscale2);
11970 
11971  res_ndigits = res_rscale + res_weight + 1;
11972  if (res_ndigits <= 0)
11973  res_ndigits = 1;
11974 
11975  res_buf = digitbuf_alloc(res_ndigits + 1);
11976  res_buf[0] = 0; /* spare digit for later rounding */
11977  res_digits = res_buf + 1;
11978 
11979  i1 = res_rscale + var1->weight + 1;
11980  i2 = res_rscale + var2->weight + 1;
11981  for (i = res_ndigits - 1; i >= 0; i--)
11982  {
11983  i1--;
11984  i2--;
11985  if (i1 >= 0 && i1 < var1ndigits)
11986  carry += var1digits[i1];
11987  if (i2 >= 0 && i2 < var2ndigits)
11988  carry += var2digits[i2];
11989 
11990  if (carry >= NBASE)
11991  {
11992  res_digits[i] = carry - NBASE;
11993  carry = 1;
11994  }
11995  else
11996  {
11997  res_digits[i] = carry;
11998  carry = 0;
11999  }
12000  }
12001 
12002  Assert(carry == 0); /* else we failed to allow for carry out */
12003 
12004  digitbuf_free(result->buf);
12005  result->ndigits = res_ndigits;
12006  result->buf = res_buf;
12007  result->digits = res_digits;
12008  result->weight = res_weight;
12009  result->dscale = res_dscale;
12010 
12011  /* Remove leading/trailing zeroes */
12012  strip_var(result);
12013 }
#define digitbuf_free(buf)
Definition: numeric.c:488
#define Max(x, y)
Definition: numeric.c:13

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().

◆ add_var()

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

Definition at line 8549 of file numeric.c.

8550 {
8551  /*
8552  * Decide on the signs of the two variables what to do
8553  */
8554  if (var1->sign == NUMERIC_POS)
8555  {
8556  if (var2->sign == NUMERIC_POS)
8557  {
8558  /*
8559  * Both are positive result = +(ABS(var1) + ABS(var2))
8560  */
8561  add_abs(var1, var2, result);
8562  result->sign = NUMERIC_POS;
8563  }
8564  else
8565  {
8566  /*
8567  * var1 is positive, var2 is negative Must compare absolute values
8568  */
8569  switch (cmp_abs(var1, var2))
8570  {
8571  case 0:
8572  /* ----------
8573  * ABS(var1) == ABS(var2)
8574  * result = ZERO
8575  * ----------
8576  */
8577  zero_var(result);
8578  result->dscale = Max(var1->dscale, var2->dscale);
8579  break;
8580 
8581  case 1:
8582  /* ----------
8583  * ABS(var1) > ABS(var2)
8584  * result = +(ABS(var1) - ABS(var2))
8585  * ----------
8586  */
8587  sub_abs(var1, var2, result);
8588  result->sign = NUMERIC_POS;
8589  break;
8590 
8591  case -1:
8592  /* ----------
8593  * ABS(var1) < ABS(var2)
8594  * result = -(ABS(var2) - ABS(var1))
8595  * ----------
8596  */
8597  sub_abs(var2, var1, result);
8598  result->sign = NUMERIC_NEG;
8599  break;
8600  }
8601  }
8602  }
8603  else
8604  {
8605  if (var2->sign == NUMERIC_POS)
8606  {
8607  /* ----------
8608  * var1 is negative, var2 is positive
8609  * Must compare absolute values
8610  * ----------
8611  */
8612  switch (cmp_abs(var1, var2))
8613  {
8614  case 0:
8615  /* ----------
8616  * ABS(var1) == ABS(var2)
8617  * result = ZERO
8618  * ----------
8619  */
8620  zero_var(result);
8621  result->dscale = Max(var1->dscale, var2->dscale);
8622  break;
8623 
8624  case 1:
8625  /* ----------
8626  * ABS(var1) > ABS(var2)
8627  * result = -(ABS(var1) - ABS(var2))
8628  * ----------
8629  */
8630  sub_abs(var1, var2, result);
8631  result->sign = NUMERIC_NEG;
8632  break;
8633 
8634  case -1:
8635  /* ----------
8636  * ABS(var1) < ABS(var2)
8637  * result = +(ABS(var2) - ABS(var1))
8638  * ----------
8639  */
8640  sub_abs(var2, var1, result);
8641  result->sign = NUMERIC_POS;
8642  break;
8643  }
8644  }
8645  else
8646  {
8647  /* ----------
8648  * Both are negative
8649  * result = -(ABS(var1) + ABS(var2))
8650  * ----------
8651  */
8652  add_abs(var1, var2, result);
8653  result->sign = NUMERIC_NEG;
8654  }
8655  }
8656 }
static void sub_abs(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition: numeric.c:12026
static void add_abs(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition: numeric.c:11941
static void zero_var(NumericVar *var)
Definition: numeric.c:7103
static int cmp_abs(const NumericVar *var1, const NumericVar *var2)
Definition: numeric.c:11863

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(), div_mod_var(), exp_var(), generate_series_step_numeric(), in_range_numeric_numeric(), ln_var(), numeric_add_opt_error(), numeric_inc(), random_var(), set_var_from_non_decimal_integer_str(), sqrt_var(), and width_bucket_numeric().

◆ alloc_var()

static void alloc_var ( NumericVar var,
int  ndigits 
)
static

Definition at line 7071 of file numeric.c.

7072 {
7073  digitbuf_free(var->buf);
7074  var->buf = digitbuf_alloc(ndigits + 1);
7075  var->buf[0] = 0; /* spare digit for rounding */
7076  var->digits = var->buf + 1;
7077  var->ndigits = ndigits;
7078 }

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

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

◆ apply_typmod()

static bool apply_typmod ( NumericVar var,
int32  typmod,
Node escontext 
)
static

Definition at line 8025 of file numeric.c.

8026 {
8027  int precision;
8028  int scale;
8029  int maxdigits;
8030  int ddigits;
8031  int i;
8032 
8033  /* Do nothing if we have an invalid typmod */
8034  if (!is_valid_numeric_typmod(typmod))
8035  return true;
8036 
8037  precision = numeric_typmod_precision(typmod);
8038  scale = numeric_typmod_scale(typmod);
8039  maxdigits = precision - scale;
8040 
8041  /* Round to target scale (and set var->dscale) */
8042  round_var(var, scale);
8043 
8044  /* but don't allow var->dscale to be negative */
8045  if (var->dscale < 0)
8046  var->dscale = 0;
8047 
8048  /*
8049  * Check for overflow - note we can't do this before rounding, because
8050  * rounding could raise the weight. Also note that the var's weight could
8051  * be inflated by leading zeroes, which will be stripped before storage
8052  * but perhaps might not have been yet. In any case, we must recognize a
8053  * true zero, whose weight doesn't mean anything.
8054  */
8055  ddigits = (var->weight + 1) * DEC_DIGITS;
8056  if (ddigits > maxdigits)
8057  {
8058  /* Determine true weight; and check for all-zero result */
8059  for (i = 0; i < var->ndigits; i++)
8060  {
8061  NumericDigit dig = var->digits[i];
8062 
8063  if (dig)
8064  {
8065  /* Adjust for any high-order decimal zero digits */
8066 #if DEC_DIGITS == 4
8067  if (dig < 10)
8068  ddigits -= 3;
8069  else if (dig < 100)
8070  ddigits -= 2;
8071  else if (dig < 1000)
8072  ddigits -= 1;
8073 #elif DEC_DIGITS == 2
8074  if (dig < 10)
8075  ddigits -= 1;
8076 #elif DEC_DIGITS == 1
8077  /* no adjustment */
8078 #else
8079 #error unsupported NBASE
8080 #endif
8081  if (ddigits > maxdigits)
8082  ereturn(escontext, false,
8083  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
8084  errmsg("numeric field overflow"),
8085  errdetail("A field with precision %d, scale %d must round to an absolute value less than %s%d.",
8086  precision, scale,
8087  /* Display 10^0 as 1 */
8088  maxdigits ? "10^" : "",
8089  maxdigits ? maxdigits : 1
8090  )));
8091  break;
8092  }
8093  ddigits -= DEC_DIGITS;
8094  }
8095  }
8096 
8097  return true;
8098 }
static bool is_valid_numeric_typmod(int32 typmod)
Definition: numeric.c:916
static int numeric_typmod_scale(int32 typmod)
Definition: numeric.c:942
static int numeric_typmod_precision(int32 typmod)
Definition: numeric.c:927
static void round_var(NumericVar *var, int rscale)
Definition: numeric.c:12108
#define DEC_DIGITS
Definition: numeric.c:98
int errdetail(const char *fmt,...)
Definition: elog.c:1203
int errcode(int sqlerrcode)
Definition: elog.c:853
int errmsg(const char *fmt,...)
Definition: elog.c:1070
#define ereturn(context, dummy_value,...)
Definition: elog.h:277
int maxdigits
Definition: informix.c:690

References DEC_DIGITS, NumericVar::digits, NumericVar::dscale, ereturn, errcode(), errdetail(), errmsg(), i, is_valid_numeric_typmod(), maxdigits, NumericVar::ndigits, numeric_typmod_precision(), numeric_typmod_scale(), round_var(), scale, and NumericVar::weight.

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

◆ apply_typmod_special()

static bool apply_typmod_special ( Numeric  num,
int32  typmod,
Node escontext 
)
static

Definition at line 8110 of file numeric.c.

8111 {
8112  int precision;
8113  int scale;
8114 
8115  Assert(NUMERIC_IS_SPECIAL(num)); /* caller error if not */
8116 
8117  /*
8118  * NaN is allowed regardless of the typmod; that's rather dubious perhaps,
8119  * but it's a longstanding behavior. Inf is rejected if we have any
8120  * typmod restriction, since an infinity shouldn't be claimed to fit in
8121  * any finite number of digits.
8122  */
8123  if (NUMERIC_IS_NAN(num))
8124  return true;
8125 
8126  /* Do nothing if we have a default typmod (-1) */
8127  if (!is_valid_numeric_typmod(typmod))
8128  return true;
8129 
8130  precision = numeric_typmod_precision(typmod);
8131  scale = numeric_typmod_scale(typmod);
8132 
8133  ereturn(escontext, false,
8134  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
8135  errmsg("numeric field overflow"),
8136  errdetail("A field with precision %d, scale %d cannot hold an infinite value.",
8137  precision, scale)));
8138 }
#define NUMERIC_IS_NAN(n)
Definition: numeric.c:206

References Assert, ereturn, errcode(), errdetail(), errmsg(), is_valid_numeric_typmod(), NUMERIC_IS_NAN, NUMERIC_IS_SPECIAL, numeric_typmod_precision(), numeric_typmod_scale(), and scale.

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

◆ ceil_var()

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

Definition at line 10302 of file numeric.c.

10303 {
10304  NumericVar tmp;
10305 
10306  init_var(&tmp);
10307  set_var_from_var(var, &tmp);
10308 
10309  trunc_var(&tmp, 0);
10310 
10311  if (var->sign == NUMERIC_POS && cmp_var(var, &tmp) != 0)
10312  add_var(&tmp, &const_one, &tmp);
10313 
10314  set_var_from_var(&tmp, result);
10315  free_var(&tmp);
10316 }
static void trunc_var(NumericVar *var, int rscale)
Definition: numeric.c:12214
static int cmp_var(const NumericVar *var1, const NumericVar *var2)
Definition: numeric.c:8491
static const NumericVar const_one
Definition: numeric.c:429

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

Referenced by numeric_ceil().

◆ cmp_abs()

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

Definition at line 11863 of file numeric.c.

11864 {
11865  return cmp_abs_common(var1->digits, var1->ndigits, var1->weight,
11866  var2->digits, var2->ndigits, var2->weight);
11867 }
static int cmp_abs_common(const NumericDigit *var1digits, int var1ndigits, int var1weight, const NumericDigit *var2digits, int var2ndigits, int var2weight)
Definition: numeric.c:11877

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

Referenced by add_var(), div_mod_var(), gcd_var(), and sub_var().

◆ 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 11877 of file numeric.c.

11879 {
11880  int i1 = 0;
11881  int i2 = 0;
11882 
11883  /* Check any digits before the first common digit */
11884 
11885  while (var1weight > var2weight && i1 < var1ndigits)
11886  {
11887  if (var1digits[i1++] != 0)
11888  return 1;
11889  var1weight--;
11890  }
11891  while (var2weight > var1weight && i2 < var2ndigits)
11892  {
11893  if (var2digits[i2++] != 0)
11894  return -1;
11895  var2weight--;
11896  }
11897 
11898  /* At this point, either w1 == w2 or we've run out of digits */
11899 
11900  if (var1weight == var2weight)
11901  {
11902  while (i1 < var1ndigits && i2 < var2ndigits)
11903  {
11904  int stat = var1digits[i1++] - var2digits[i2++];
11905 
11906  if (stat)
11907  {
11908  if (stat > 0)
11909  return 1;
11910  return -1;
11911  }
11912  }
11913  }
11914 
11915  /*
11916  * At this point, we've run out of digits on one side or the other; so any
11917  * remaining nonzero digits imply that side is larger
11918  */
11919  while (i1 < var1ndigits)
11920  {
11921  if (var1digits[i1++] != 0)
11922  return 1;
11923  }
11924  while (i2 < var2ndigits)
11925  {
11926  if (var2digits[i2++] != 0)
11927  return -1;
11928  }
11929 
11930  return 0;
11931 }

Referenced by cmp_abs(), and cmp_var_common().

◆ cmp_numerics()

static int cmp_numerics ( Numeric  num1,
Numeric  num2 
)
static

Definition at line 2623 of file numeric.c.

2624 {
2625  int result;
2626 
2627  /*
2628  * We consider all NANs to be equal and larger than any non-NAN (including
2629  * Infinity). This is somewhat arbitrary; the important thing is to have
2630  * a consistent sort order.
2631  */
2632  if (NUMERIC_IS_SPECIAL(num1))
2633  {
2634  if (NUMERIC_IS_NAN(num1))
2635  {
2636  if (NUMERIC_IS_NAN(num2))
2637  result = 0; /* NAN = NAN */
2638  else
2639  result = 1; /* NAN > non-NAN */
2640  }
2641  else if (NUMERIC_IS_PINF(num1))
2642  {
2643  if (NUMERIC_IS_NAN(num2))
2644  result = -1; /* PINF < NAN */
2645  else if (NUMERIC_IS_PINF(num2))
2646  result = 0; /* PINF = PINF */
2647  else
2648  result = 1; /* PINF > anything else */
2649  }
2650  else /* num1 must be NINF */
2651  {
2652  if (NUMERIC_IS_NINF(num2))
2653  result = 0; /* NINF = NINF */
2654  else
2655  result = -1; /* NINF < anything else */
2656  }
2657  }
2658  else if (NUMERIC_IS_SPECIAL(num2))
2659  {
2660  if (NUMERIC_IS_NINF(num2))
2661  result = 1; /* normal > NINF */
2662  else
2663  result = -1; /* normal < NAN or PINF */
2664  }
2665  else
2666  {
2667  result = cmp_var_common(NUMERIC_DIGITS(num1), NUMERIC_NDIGITS(num1),
2668  NUMERIC_WEIGHT(num1), NUMERIC_SIGN(num1),
2669  NUMERIC_DIGITS(num2), NUMERIC_NDIGITS(num2),
2670  NUMERIC_WEIGHT(num2), NUMERIC_SIGN(num2));
2671  }
2672 
2673  return result;
2674 }
#define NUMERIC_SIGN(n)
Definition: numeric.c:239
#define NUMERIC_IS_PINF(n)
Definition: numeric.c:207
#define NUMERIC_IS_NINF(n)
Definition: numeric.c:208
#define NUMERIC_WEIGHT(n)
Definition: numeric.c:249
#define NUMERIC_DIGITS(num)
Definition: numeric.c:496
#define NUMERIC_NDIGITS(num)
Definition: numeric.c:498
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:8506

References cmp_var_common(), NUMERIC_DIGITS, NUMERIC_IS_NAN, NUMERIC_IS_NINF, NUMERIC_IS_PINF, NUMERIC_IS_SPECIAL, 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().

◆ cmp_var()

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

◆ 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 8506 of file numeric.c.

8510 {
8511  if (var1ndigits == 0)
8512  {
8513  if (var2ndigits == 0)
8514  return 0;
8515  if (var2sign == NUMERIC_NEG)
8516  return 1;
8517  return -1;
8518  }
8519  if (var2ndigits == 0)
8520  {
8521  if (var1sign == NUMERIC_POS)
8522  return 1;
8523  return -1;
8524  }
8525 
8526  if (var1sign == NUMERIC_POS)
8527  {
8528  if (var2sign == NUMERIC_NEG)
8529  return 1;
8530  return cmp_abs_common(var1digits, var1ndigits, var1weight,
8531  var2digits, var2ndigits, var2weight);
8532  }
8533 
8534  if (var2sign == NUMERIC_POS)
8535  return -1;
8536 
8537  return cmp_abs_common(var2digits, var2ndigits, var2weight,
8538  var1digits, var1ndigits, var1weight);
8539 }

References cmp_abs_common(), NUMERIC_NEG, and NUMERIC_POS.

Referenced by cmp_numerics(), and cmp_var().

◆ compute_bucket()

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

Definition at line 2054 of file numeric.c.

2056 {
2057  NumericVar bound1_var;
2058  NumericVar bound2_var;
2059  NumericVar operand_var;
2060 
2061  init_var_from_num(bound1, &bound1_var);
2062  init_var_from_num(bound2, &bound2_var);
2063  init_var_from_num(operand, &operand_var);
2064 
2065  /*
2066  * Per spec, bound1 is inclusive and bound2 is exclusive, and so we have
2067  * bound1 <= operand < bound2 or bound1 >= operand > bound2. Either way,
2068  * the result is ((operand - bound1) * count) / (bound2 - bound1) + 1,
2069  * where the quotient is computed using floor division (i.e., division to
2070  * zero decimal places with truncation), which guarantees that the result
2071  * is in the range [1, count]. Reversing the bounds doesn't affect the
2072  * computation, because the signs cancel out when dividing.
2073  */
2074  sub_var(&operand_var, &bound1_var, &operand_var);
2075  sub_var(&bound2_var, &bound1_var, &bound2_var);
2076 
2077  mul_var(&operand_var, count_var, &operand_var,
2078  operand_var.dscale + count_var->dscale);
2079  div_var(&operand_var, &bound2_var, result_var, 0, false, true);
2080  add_var(result_var, &const_one, result_var);
2081 
2082  free_var(&bound1_var);
2083  free_var(&bound2_var);
2084  free_var(&operand_var);
2085 }
static void sub_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition: numeric.c:8666
static void init_var_from_num(Numeric num, NumericVar *dest)
Definition: numeric.c:7569
static void mul_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result, int rscale)
Definition: numeric.c:8787
static void div_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result, int rscale, bool round, bool exact)
Definition: numeric.c:9365

References add_var(), const_one, div_var(), NumericVar::dscale, free_var(), init_var_from_num(), mul_var(), and sub_var().

Referenced by width_bucket_numeric().

◆ div_mod_var()

static void div_mod_var ( const NumericVar var1,
const NumericVar var2,
NumericVar quot,
NumericVar rem 
)
static

Definition at line 10232 of file numeric.c.

10234 {
10235  NumericVar q;
10236  NumericVar r;
10237 
10238  init_var(&q);
10239  init_var(&r);
10240 
10241  /*
10242  * Use div_var() with exact = false to get an initial estimate for the
10243  * integer quotient (truncated towards zero). This might be slightly
10244  * inaccurate, but we correct it below.
10245  */
10246  div_var(var1, var2, &q, 0, false, false);
10247 
10248  /* Compute initial estimate of remainder using the quotient estimate. */
10249  mul_var(var2, &q, &r, var2->dscale);
10250  sub_var(var1, &r, &r);
10251 
10252  /*
10253  * Adjust the results if necessary --- the remainder should have the same
10254  * sign as var1, and its absolute value should be less than the absolute
10255  * value of var2.
10256  */
10257  while (r.ndigits != 0 && r.sign != var1->sign)
10258  {
10259  /* The absolute value of the quotient is too large */
10260  if (var1->sign == var2->sign)
10261  {
10262  sub_var(&q, &const_one, &q);
10263  add_var(&r, var2, &r);
10264  }
10265  else
10266  {
10267  add_var(&q, &const_one, &q);
10268  sub_var(&r, var2, &r);
10269  }
10270  }
10271 
10272  while (cmp_abs(&r, var2) >= 0)
10273  {
10274  /* The absolute value of the quotient is too small */
10275  if (var1->sign == var2->sign)
10276  {
10277  add_var(&q, &const_one, &q);
10278  sub_var(&r, var2, &r);
10279  }
10280  else
10281  {
10282  sub_var(&q, &const_one, &q);
10283  add_var(&r, var2, &r);
10284  }
10285  }
10286 
10287  set_var_from_var(&q, quot);
10288  set_var_from_var(&r, rem);
10289 
10290  free_var(&q);
10291  free_var(&r);
10292 }

References add_var(), cmp_abs(), const_one, div_var(), NumericVar::dscale, free_var(), init_var, mul_var(), NumericVar::ndigits, set_var_from_var(), NumericVar::sign, and sub_var().

Referenced by sqrt_var().

◆ div_var()

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

Definition at line 9365 of file numeric.c.

9367 {
9368  int var1ndigits = var1->ndigits;
9369  int var2ndigits = var2->ndigits;
9370  int res_sign;
9371  int res_weight;
9372  int res_ndigits;
9373  int var1ndigitpairs;
9374  int var2ndigitpairs;
9375  int res_ndigitpairs;
9376  int div_ndigitpairs;
9377  int64 *dividend;
9378  int32 *divisor;
9379  double fdivisor,
9380  fdivisorinverse,
9381  fdividend,
9382  fquotient;
9383  int64 maxdiv;
9384  int qi;
9385  int32 qdigit;
9386  int64 carry;
9387  int64 newdig;
9388  int64 *remainder;
9389  NumericDigit *res_digits;
9390  int i;
9391 
9392  /*
9393  * First of all division by zero check; we must not be handed an
9394  * unnormalized divisor.
9395  */
9396  if (var2ndigits == 0 || var2->digits[0] == 0)
9397  ereport(ERROR,
9398  (errcode(ERRCODE_DIVISION_BY_ZERO),
9399  errmsg("division by zero")));
9400 
9401  /*
9402  * If the divisor has just one or two digits, delegate to div_var_int(),
9403  * which uses fast short division.
9404  *
9405  * Similarly, on platforms with 128-bit integer support, delegate to
9406  * div_var_int64() for divisors with three or four digits.
9407  */
9408  if (var2ndigits <= 2)
9409  {
9410  int idivisor;
9411  int idivisor_weight;
9412 
9413  idivisor = var2->digits[0];
9414  idivisor_weight = var2->weight;
9415  if (var2ndigits == 2)
9416  {
9417  idivisor = idivisor * NBASE + var2->digits[1];
9418  idivisor_weight--;
9419  }
9420  if (var2->sign == NUMERIC_NEG)
9421  idivisor = -idivisor;
9422 
9423  div_var_int(var1, idivisor, idivisor_weight, result, rscale, round);
9424  return;
9425  }
9426 #ifdef HAVE_INT128
9427  if (var2ndigits <= 4)
9428  {
9429  int64 idivisor;
9430  int idivisor_weight;
9431 
9432  idivisor = var2->digits[0];
9433  idivisor_weight = var2->weight;
9434  for (i = 1; i < var2ndigits; i++)
9435  {
9436  idivisor = idivisor * NBASE + var2->digits[i];
9437  idivisor_weight--;
9438  }
9439  if (var2->sign == NUMERIC_NEG)
9440  idivisor = -idivisor;
9441 
9442  div_var_int64(var1, idivisor, idivisor_weight, result, rscale, round);
9443  return;
9444  }
9445 #endif
9446 
9447  /*
9448  * Otherwise, perform full long division.
9449  */
9450 
9451  /* Result zero check */
9452  if (var1ndigits == 0)
9453  {
9454  zero_var(result);
9455  result->dscale = rscale;
9456  return;
9457  }
9458 
9459  /*
9460  * The approximate computation can be significantly faster than the exact
9461  * one, since the working dividend is var2ndigitpairs base-NBASE^2 digits
9462  * shorter below. However, that comes with the tradeoff of computing
9463  * DIV_GUARD_DIGITS extra base-NBASE result digits. Ignoring all other
9464  * overheads, that suggests that, in theory, the approximate computation
9465  * will only be faster than the exact one when var2ndigits is greater than
9466  * 2 * (DIV_GUARD_DIGITS + 1), independent of the size of var1.
9467  *
9468  * Thus, we're better off doing an exact computation when var2 is shorter
9469  * than this. Empirically, it has been found that the exact threshold is
9470  * a little higher, due to other overheads in the outer division loop.
9471  */
9472  if (var2ndigits <= 2 * (DIV_GUARD_DIGITS + 2))
9473  exact = true;
9474 
9475  /*
9476  * Determine the result sign, weight and number of digits to calculate.
9477  * The weight figured here is correct if the emitted quotient has no
9478  * leading zero digits; otherwise strip_var() will fix things up.
9479  */
9480  if (var1->sign == var2->sign)
9481  res_sign = NUMERIC_POS;
9482  else
9483  res_sign = NUMERIC_NEG;
9484  res_weight = var1->weight - var2->weight + 1;
9485  /* The number of accurate result digits we need to produce: */
9486  res_ndigits = res_weight + 1 + (rscale + DEC_DIGITS - 1) / DEC_DIGITS;
9487  /* ... but always at least 1 */
9488  res_ndigits = Max(res_ndigits, 1);
9489  /* If rounding needed, figure one more digit to ensure correct result */
9490  if (round)
9491  res_ndigits++;
9492  /* Add guard digits for roundoff error when producing approx result */
9493  if (!exact)
9494  res_ndigits += DIV_GUARD_DIGITS;
9495 
9496  /*
9497  * The computation itself is done using base-NBASE^2 arithmetic, so we
9498  * actually process the input digits in pairs, producing a base-NBASE^2
9499  * intermediate result. This significantly improves performance, since
9500  * the computation is O(N^2) in the number of input digits, and working in
9501  * base NBASE^2 effectively halves "N".
9502  */
9503  var1ndigitpairs = (var1ndigits + 1) / 2;
9504  var2ndigitpairs = (var2ndigits + 1) / 2;
9505  res_ndigitpairs = (res_ndigits + 1) / 2;
9506  res_ndigits = 2 * res_ndigitpairs;
9507 
9508  /*
9509  * We do the arithmetic in an array "dividend[]" of signed 64-bit
9510  * integers. Since PG_INT64_MAX is much larger than NBASE^4, this gives
9511  * us a lot of headroom to avoid normalizing carries immediately.
9512  *
9513  * When performing an exact computation, the working dividend requires
9514  * res_ndigitpairs + var2ndigitpairs digits. If var1 is larger than that,
9515  * the extra digits do not contribute to the result, and are ignored.
9516  *
9517  * When performing an approximate computation, the working dividend only
9518  * requires res_ndigitpairs digits (which includes the extra guard
9519  * digits). All input digits beyond that are ignored.
9520  */
9521  if (exact)
9522  {
9523  div_ndigitpairs = res_ndigitpairs + var2ndigitpairs;
9524  var1ndigitpairs = Min(var1ndigitpairs, div_ndigitpairs);
9525  }
9526  else
9527  {
9528  div_ndigitpairs = res_ndigitpairs;
9529  var1ndigitpairs = Min(var1ndigitpairs, div_ndigitpairs);
9530  var2ndigitpairs = Min(var2ndigitpairs, div_ndigitpairs);
9531  }
9532 
9533  /*
9534  * Allocate room for the working dividend (div_ndigitpairs 64-bit digits)
9535  * plus the divisor (var2ndigitpairs 32-bit base-NBASE^2 digits).
9536  *
9537  * For convenience, we allocate one extra dividend digit, which is set to
9538  * zero and not counted in div_ndigitpairs, so that the main loop below
9539  * can safely read and write the (qi+1)'th digit in the approximate case.
9540  */
9541  dividend = (int64 *) palloc((div_ndigitpairs + 1) * sizeof(int64) +
9542  var2ndigitpairs * sizeof(int32));
9543  divisor = (int32 *) (dividend + div_ndigitpairs + 1);
9544 
9545  /* load var1 into dividend[0 .. var1ndigitpairs-1], zeroing the rest */
9546  for (i = 0; i < var1ndigitpairs - 1; i++)
9547  dividend[i] = var1->digits[2 * i] * NBASE + var1->digits[2 * i + 1];
9548 
9549  if (2 * i + 1 < var1ndigits)
9550  dividend[i] = var1->digits[2 * i] * NBASE + var1->digits[2 * i + 1];
9551  else
9552  dividend[i] = var1->digits[2 * i] * NBASE;
9553 
9554  memset(dividend + i + 1, 0, (div_ndigitpairs - i) * sizeof(int64));
9555 
9556  /* load var2 into divisor[0 .. var2ndigitpairs-1] */
9557  for (i = 0; i < var2ndigitpairs - 1; i++)
9558  divisor[i] = var2->digits[2 * i] * NBASE + var2->digits[2 * i + 1];
9559 
9560  if (2 * i + 1 < var2ndigits)
9561  divisor[i] = var2->digits[2 * i] * NBASE + var2->digits[2 * i + 1];
9562  else
9563  divisor[i] = var2->digits[2 * i] * NBASE;
9564 
9565  /*
9566  * We estimate each quotient digit using floating-point arithmetic, taking
9567  * the first 2 base-NBASE^2 digits of the (current) dividend and divisor.
9568  * This must be float to avoid overflow.
9569  *
9570  * Since the floating-point dividend and divisor use 4 base-NBASE input
9571  * digits, they include roughly 40-53 bits of information from their
9572  * respective inputs (assuming NBASE is 10000), which fits well in IEEE
9573  * double-precision variables. The relative error in the floating-point
9574  * quotient digit will then be less than around 2/NBASE^3, so the
9575  * estimated base-NBASE^2 quotient digit will typically be correct, and
9576  * should not be off by more than one from the correct value.
9577  */
9578  fdivisor = (double) divisor[0] * NBASE_SQR;
9579  if (var2ndigitpairs > 1)
9580  fdivisor += (double) divisor[1];
9581  fdivisorinverse = 1.0 / fdivisor;
9582 
9583  /*
9584  * maxdiv tracks the maximum possible absolute value of any dividend[]
9585  * entry; when this threatens to exceed PG_INT64_MAX, we take the time to
9586  * propagate carries. Furthermore, we need to ensure that overflow
9587  * doesn't occur during the carry propagation passes either. The carry
9588  * values may have an absolute value as high as PG_INT64_MAX/NBASE^2 + 1,
9589  * so really we must normalize when digits threaten to exceed PG_INT64_MAX
9590  * - PG_INT64_MAX/NBASE^2 - 1.
9591  *
9592  * To avoid overflow in maxdiv itself, it represents the max absolute
9593  * value divided by NBASE^2-1, i.e., at the top of the loop it is known
9594  * that no dividend[] entry has an absolute value exceeding maxdiv *
9595  * (NBASE^2-1).
9596  *
9597  * Actually, though, that holds good only for dividend[] entries after
9598  * dividend[qi]; the adjustment done at the bottom of the loop may cause
9599  * dividend[qi + 1] to exceed the maxdiv limit, so that dividend[qi] in
9600  * the next iteration is beyond the limit. This does not cause problems,
9601  * as explained below.
9602  */
9603  maxdiv = 1;
9604 
9605  /*
9606  * Outer loop computes next quotient digit, which goes in dividend[qi].
9607  */
9608  for (qi = 0; qi < res_ndigitpairs; qi++)
9609  {
9610  /* Approximate the current dividend value */
9611  fdividend = (double) dividend[qi] * NBASE_SQR;
9612  fdividend += (double) dividend[qi + 1];
9613 
9614  /* Compute the (approximate) quotient digit */
9615  fquotient = fdividend * fdivisorinverse;
9616  qdigit = (fquotient >= 0.0) ? ((int32) fquotient) :
9617  (((int32) fquotient) - 1); /* truncate towards -infinity */
9618 
9619  if (qdigit != 0)
9620  {
9621  /* Do we need to normalize now? */
9622  maxdiv += i64abs(qdigit);
9623  if (maxdiv > (PG_INT64_MAX - PG_INT64_MAX / NBASE_SQR - 1) / (NBASE_SQR - 1))
9624  {
9625  /*
9626  * Yes, do it. Note that if var2ndigitpairs is much smaller
9627  * than div_ndigitpairs, we can save a significant amount of
9628  * effort here by noting that we only need to normalise those
9629  * dividend[] entries touched where prior iterations
9630  * subtracted multiples of the divisor.
9631  */
9632  carry = 0;
9633  for (i = Min(qi + var2ndigitpairs - 2, div_ndigitpairs - 1); i > qi; i--)
9634  {
9635  newdig = dividend[i] + carry;
9636  if (newdig < 0)
9637  {
9638  carry = -((-newdig - 1) / NBASE_SQR) - 1;
9639  newdig -= carry * NBASE_SQR;
9640  }
9641  else if (newdig >= NBASE_SQR)
9642  {
9643  carry = newdig / NBASE_SQR;
9644  newdig -= carry * NBASE_SQR;
9645  }
9646  else
9647  carry = 0;
9648  dividend[i] = newdig;
9649  }
9650  dividend[qi] += carry;
9651 
9652  /*
9653  * All the dividend[] digits except possibly dividend[qi] are
9654  * now in the range 0..NBASE^2-1. We do not need to consider
9655  * dividend[qi] in the maxdiv value anymore, so we can reset
9656  * maxdiv to 1.
9657  */
9658  maxdiv = 1;
9659 
9660  /*
9661  * Recompute the quotient digit since new info may have
9662  * propagated into the top two dividend digits.
9663  */
9664  fdividend = (double) dividend[qi] * NBASE_SQR;
9665  fdividend += (double) dividend[qi + 1];
9666  fquotient = fdividend * fdivisorinverse;
9667  qdigit = (fquotient >= 0.0) ? ((int32) fquotient) :
9668  (((int32) fquotient) - 1); /* truncate towards -infinity */
9669 
9670  maxdiv += i64abs(qdigit);
9671  }
9672 
9673  /*
9674  * Subtract off the appropriate multiple of the divisor.
9675  *
9676  * The digits beyond dividend[qi] cannot overflow, because we know
9677  * they will fall within the maxdiv limit. As for dividend[qi]
9678  * itself, note that qdigit is approximately trunc(dividend[qi] /
9679  * divisor[0]), which would make the new value simply dividend[qi]
9680  * mod divisor[0]. The lower-order terms in qdigit can change
9681  * this result by not more than about twice PG_INT64_MAX/NBASE^2,
9682  * so overflow is impossible.
9683  *
9684  * This inner loop is the performance bottleneck for division, so
9685  * code it in the same way as the inner loop of mul_var() so that
9686  * it can be auto-vectorized.
9687  */
9688  if (qdigit != 0)
9689  {
9690  int istop = Min(var2ndigitpairs, div_ndigitpairs - qi);
9691  int64 *dividend_qi = &dividend[qi];
9692 
9693  for (i = 0; i < istop; i++)
9694  dividend_qi[i] -= (int64) qdigit * divisor[i];
9695  }
9696  }
9697 
9698  /*
9699  * The dividend digit we are about to replace might still be nonzero.
9700  * Fold it into the next digit position.
9701  *
9702  * There is no risk of overflow here, although proving that requires
9703  * some care. Much as with the argument for dividend[qi] not
9704  * overflowing, if we consider the first two terms in the numerator
9705  * and denominator of qdigit, we can see that the final value of
9706  * dividend[qi + 1] will be approximately a remainder mod
9707  * (divisor[0]*NBASE^2 + divisor[1]). Accounting for the lower-order
9708  * terms is a bit complicated but ends up adding not much more than
9709  * PG_INT64_MAX/NBASE^2 to the possible range. Thus, dividend[qi + 1]
9710  * cannot overflow here, and in its role as dividend[qi] in the next
9711  * loop iteration, it can't be large enough to cause overflow in the
9712  * carry propagation step (if any), either.
9713  *
9714  * But having said that: dividend[qi] can be more than
9715  * PG_INT64_MAX/NBASE^2, as noted above, which means that the product
9716  * dividend[qi] * NBASE^2 *can* overflow. When that happens, adding
9717  * it to dividend[qi + 1] will always cause a canceling overflow so
9718  * that the end result is correct. We could avoid the intermediate
9719  * overflow by doing the multiplication and addition using unsigned
9720  * int64 arithmetic, which is modulo 2^64, but so far there appears no
9721  * need.
9722  */
9723  dividend[qi + 1] += dividend[qi] * NBASE_SQR;
9724 
9725  dividend[qi] = qdigit;
9726  }
9727 
9728  /*
9729  * If an exact result was requested, use the remainder to correct the
9730  * approximate quotient. The remainder is in dividend[], immediately
9731  * after the quotient digits. Note, however, that although the remainder
9732  * starts at dividend[qi = res_ndigitpairs], the first digit is the result
9733  * of folding two remainder digits into one above, and the remainder
9734  * currently only occupies var2ndigitpairs - 1 digits (the last digit of
9735  * the working dividend was untouched by the computation above). Thus we
9736  * expand the remainder down by one base-NBASE^2 digit when we normalize
9737  * it, so that it completely fills the last var2ndigitpairs digits of the
9738  * dividend array.
9739  */
9740  if (exact)
9741  {
9742  /* Normalize the remainder, expanding it down by one digit */
9743  remainder = &dividend[qi];
9744  carry = 0;
9745  for (i = var2ndigitpairs - 2; i >= 0; i--)
9746  {
9747  newdig = remainder[i] + carry;
9748  if (newdig < 0)
9749  {
9750  carry = -((-newdig - 1) / NBASE_SQR) - 1;
9751  newdig -= carry * NBASE_SQR;
9752  }
9753  else if (newdig >= NBASE_SQR)
9754  {
9755  carry = newdig / NBASE_SQR;
9756  newdig -= carry * NBASE_SQR;
9757  }
9758  else
9759  carry = 0;
9760  remainder[i + 1] = newdig;
9761  }
9762  remainder[0] = carry;
9763 
9764  if (remainder[0] < 0)
9765  {
9766  /*
9767  * The remainder is negative, so the approximate quotient is too
9768  * large. Correct by reducing the quotient by one and adding the
9769  * divisor to the remainder until the remainder is positive. We
9770  * expect the quotient to be off by at most one, which has been
9771  * borne out in all testing, but not conclusively proven, so we
9772  * allow for larger corrections, just in case.
9773  */
9774  do
9775  {
9776  /* Add the divisor to the remainder */
9777  carry = 0;
9778  for (i = var2ndigitpairs - 1; i > 0; i--)
9779  {
9780  newdig = remainder[i] + divisor[i] + carry;
9781  if (newdig >= NBASE_SQR)
9782  {
9783  remainder[i] = newdig - NBASE_SQR;
9784  carry = 1;
9785  }
9786  else
9787  {
9788  remainder[i] = newdig;
9789  carry = 0;
9790  }
9791  }
9792  remainder[0] += divisor[0] + carry;
9793 
9794  /* Subtract 1 from the quotient (propagating carries later) */
9795  dividend[qi - 1]--;
9796 
9797  } while (remainder[0] < 0);
9798  }
9799  else
9800  {
9801  /*
9802  * The remainder is nonnegative. If it's greater than or equal to
9803  * the divisor, then the approximate quotient is too small and
9804  * must be corrected. As above, we don't expect to have to apply
9805  * more than one correction, but allow for it just in case.
9806  */
9807  while (true)
9808  {
9809  bool less = false;
9810 
9811  /* Is remainder < divisor? */
9812  for (i = 0; i < var2ndigitpairs; i++)
9813  {
9814  if (remainder[i] < divisor[i])
9815  {
9816  less = true;
9817  break;
9818  }
9819  if (remainder[i] > divisor[i])
9820  break; /* remainder > divisor */
9821  }
9822  if (less)
9823  break; /* quotient is correct */
9824 
9825  /* Subtract the divisor from the remainder */
9826  carry = 0;
9827  for (i = var2ndigitpairs - 1; i > 0; i--)
9828  {
9829  newdig = remainder[i] - divisor[i] + carry;
9830  if (newdig < 0)
9831  {
9832  remainder[i] = newdig + NBASE_SQR;
9833  carry = -1;
9834  }
9835  else
9836  {
9837  remainder[i] = newdig;
9838  carry = 0;
9839  }
9840  }
9841  remainder[0] = remainder[0] - divisor[0] + carry;
9842 
9843  /* Add 1 to the quotient (propagating carries later) */
9844  dividend[qi - 1]++;
9845  }
9846  }
9847  }
9848 
9849  /*
9850  * Because the quotient digits were estimates that might have been off by
9851  * one (and we didn't bother propagating carries when adjusting the
9852  * quotient above), some quotient digits might be out of range, so do a
9853  * final carry propagation pass to normalize back to base NBASE^2, and
9854  * construct the base-NBASE result digits. Note that this is still done
9855  * at full precision w/guard digits.
9856  */
9857  alloc_var(result, res_ndigits);
9858  res_digits = result->digits;
9859  carry = 0;
9860  for (i = res_ndigitpairs - 1; i >= 0; i--)
9861  {
9862  newdig = dividend[i] + carry;
9863  if (newdig < 0)
9864  {
9865  carry = -((-newdig - 1) / NBASE_SQR) - 1;
9866  newdig -= carry * NBASE_SQR;
9867  }
9868  else if (newdig >= NBASE_SQR)
9869  {
9870  carry = newdig / NBASE_SQR;
9871  newdig -= carry * NBASE_SQR;
9872  }
9873  else
9874  carry = 0;
9875  res_digits[2 * i + 1] = (NumericDigit) ((uint32) newdig % NBASE);
9876  res_digits[2 * i] = (NumericDigit) ((uint32) newdig / NBASE);
9877  }
9878  Assert(carry == 0);
9879 
9880  pfree(dividend);
9881 
9882  /*
9883  * Finally, round or truncate the result to the requested precision.
9884  */
9885  result->weight = res_weight;
9886  result->sign = res_sign;
9887 
9888  /* Round or truncate to target rscale (and set result->dscale) */
9889  if (round)
9890  round_var(result, rscale);
9891  else
9892  trunc_var(result, rscale);
9893 
9894  /* Strip leading and trailing zeroes */
9895  strip_var(result);
9896 }
static void div_var_int(const NumericVar *var, int ival, int ival_weight, NumericVar *result, int rscale, bool round)
Definition: numeric.c:9906
#define DIV_GUARD_DIGITS
Definition: numeric.c:100
#define NBASE_SQR
Definition: numeric.c:105
static void alloc_var(NumericVar *var, int ndigits)
Definition: numeric.c:7071
unsigned int uint32
Definition: c.h:492
#define PG_INT64_MAX
Definition: c.h:571
#define i64abs(i)
Definition: c.h:1286
#define ERROR
Definition: elog.h:39
#define ereport(elevel,...)
Definition: elog.h:149
#define Min(x, y)
Definition: numeric.c:14
if(TABLE==NULL||TABLE_index==NULL)
Definition: isn.c:76

References alloc_var(), Assert, DEC_DIGITS, NumericVar::digits, DIV_GUARD_DIGITS, div_var_int(), NumericVar::dscale, ereport, errcode(), errmsg(), ERROR, i, i64abs, if(), Max, Min, NBASE, NBASE_SQR, NumericVar::ndigits, NUMERIC_NEG, NUMERIC_POS, palloc(), pfree(), PG_INT64_MAX, round_var(), NumericVar::sign, strip_var(), trunc_var(), NumericVar::weight, and zero_var().

Referenced by compute_bucket(), div_mod_var(), generate_series_numeric_support(), get_str_from_var_sci(), ln_var(), log_var(), mod_var(), numeric_div_opt_error(), numeric_div_trunc(), numeric_lcm(), numeric_stddev_internal(), and power_var_int().

◆ div_var_int()

static void div_var_int ( const NumericVar var,
int  ival,
int  ival_weight,
NumericVar result,
int  rscale,
bool  round 
)
static

Definition at line 9906 of file numeric.c.

9908 {
9909  NumericDigit *var_digits = var->digits;
9910  int var_ndigits = var->ndigits;
9911  int res_sign;
9912  int res_weight;
9913  int res_ndigits;
9914  NumericDigit *res_buf;
9915  NumericDigit *res_digits;
9916  uint32 divisor;
9917  int i;
9918 
9919  /* Guard against division by zero */
9920  if (ival == 0)
9921  ereport(ERROR,
9922  errcode(ERRCODE_DIVISION_BY_ZERO),
9923  errmsg("division by zero"));
9924 
9925  /* Result zero check */
9926  if (var_ndigits == 0)
9927  {
9928  zero_var(result);
9929  result->dscale = rscale;
9930  return;
9931  }
9932 
9933  /*
9934  * Determine the result sign, weight and number of digits to calculate.
9935  * The weight figured here is correct if the emitted quotient has no
9936  * leading zero digits; otherwise strip_var() will fix things up.
9937  */
9938  if (var->sign == NUMERIC_POS)
9939  res_sign = ival > 0 ? NUMERIC_POS : NUMERIC_NEG;
9940  else
9941  res_sign = ival > 0 ? NUMERIC_NEG : NUMERIC_POS;
9942  res_weight = var->weight - ival_weight;
9943  /* The number of accurate result digits we need to produce: */
9944  res_ndigits = res_weight + 1 + (rscale + DEC_DIGITS - 1) / DEC_DIGITS;
9945  /* ... but always at least 1 */
9946  res_ndigits = Max(res_ndigits, 1);
9947  /* If rounding needed, figure one more digit to ensure correct result */
9948  if (round)
9949  res_ndigits++;
9950 
9951  res_buf = digitbuf_alloc(res_ndigits + 1);
9952  res_buf[0] = 0; /* spare digit for later rounding */
9953  res_digits = res_buf + 1;
9954 
9955  /*
9956  * Now compute the quotient digits. This is the short division algorithm
9957  * described in Knuth volume 2, section 4.3.1 exercise 16, except that we
9958  * allow the divisor to exceed the internal base.
9959  *
9960  * In this algorithm, the carry from one digit to the next is at most
9961  * divisor - 1. Therefore, while processing the next digit, carry may
9962  * become as large as divisor * NBASE - 1, and so it requires a 64-bit
9963  * integer if this exceeds UINT_MAX.
9964  */
9965  divisor = abs(ival);
9966 
9967  if (divisor <= UINT_MAX / NBASE)
9968  {
9969  /* carry cannot overflow 32 bits */
9970  uint32 carry = 0;
9971 
9972  for (i = 0; i < res_ndigits; i++)
9973  {
9974  carry = carry * NBASE + (i < var_ndigits ? var_digits[i] : 0);
9975  res_digits[i] = (NumericDigit) (carry / divisor);
9976  carry = carry % divisor;
9977  }
9978  }
9979  else
9980  {
9981  /* carry may exceed 32 bits */
9982  uint64 carry = 0;
9983 
9984  for (i = 0; i < res_ndigits; i++)
9985  {
9986  carry = carry * NBASE + (i < var_ndigits ? var_digits[i] : 0);
9987  res_digits[i] = (NumericDigit) (carry / divisor);
9988  carry = carry % divisor;
9989  }
9990  }
9991 
9992  /* Store the quotient in result */
9993  digitbuf_free(result->buf);
9994  result->ndigits = res_ndigits;
9995  result->buf = res_buf;
9996  result->digits = res_digits;
9997  result->weight = res_weight;
9998  result->sign = res_sign;
9999 
10000  /* Round or truncate to target rscale (and set result->dscale) */
10001  if (round)
10002  round_var(result, rscale);
10003  else
10004  trunc_var(result, rscale);
10005 
10006  /* Strip leading/trailing zeroes */
10007  strip_var(result);
10008 }

References NumericVar::buf, DEC_DIGITS, digitbuf_alloc, digitbuf_free, NumericVar::digits, NumericVar::dscale, ereport, errcode(), errmsg(), ERROR, i, Max, NBASE, NumericVar::ndigits, NUMERIC_NEG, NUMERIC_POS, round_var(), NumericVar::sign, strip_var(), trunc_var(), NumericVar::weight, and zero_var().

Referenced by div_var(), exp_var(), and ln_var().

◆ do_numeric_accum()

static void do_numeric_accum ( NumericAggState state,
Numeric  newval 
)
static

Definition at line 4975 of file numeric.c.

4976 {
4977  NumericVar X;
4978  NumericVar X2;
4979  MemoryContext old_context;
4980 
4981  /* Count NaN/infinity inputs separately from all else */
4983  {
4984  if (NUMERIC_IS_PINF(newval))
4985  state->pInfcount++;
4986  else if (NUMERIC_IS_NINF(newval))
4987  state->nInfcount++;
4988  else
4989  state->NaNcount++;
4990  return;
4991  }
4992 
4993  /* load processed number in short-lived context */
4995 
4996  /*
4997  * Track the highest input dscale that we've seen, to support inverse
4998  * transitions (see do_numeric_discard).
4999  */
5000  if (X.dscale > state->maxScale)
5001  {
5002  state->maxScale = X.dscale;
5003  state->maxScaleCount = 1;
5004  }
5005  else if (X.dscale == state->maxScale)
5006  state->maxScaleCount++;
5007 
5008  /* if we need X^2, calculate that in short-lived context */
5009  if (state->calcSumX2)
5010  {
5011  init_var(&X2);
5012  mul_var(&X, &X, &X2, X.dscale * 2);
5013  }
5014 
5015  /* The rest of this needs to work in the aggregate context */
5016  old_context = MemoryContextSwitchTo(state->agg_context);
5017 
5018  state->N++;
5019 
5020  /* Accumulate sums */
5021  accum_sum_add(&(state->sumX), &X);
5022 
5023  if (state->calcSumX2)
5024  accum_sum_add(&(state->sumX2), &X2);
5025 
5026  MemoryContextSwitchTo(old_context);
5027 }
#define newval
MemoryContextSwitchTo(old_ctx)
Definition: regguts.h:323

References accum_sum_add(), NumericVar::dscale, init_var, init_var_from_num(), MemoryContextSwitchTo(), mul_var(), newval, NUMERIC_IS_NINF, NUMERIC_IS_PINF, and NUMERIC_IS_SPECIAL.

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

◆ do_numeric_discard()

static bool do_numeric_discard ( NumericAggState state,
Numeric  newval 
)
static

Definition at line 5045 of file numeric.c.

5046 {
5047  NumericVar X;
5048  NumericVar X2;
5049  MemoryContext old_context;
5050 
5051  /* Count NaN/infinity inputs separately from all else */
5053  {
5054  if (NUMERIC_IS_PINF(newval))
5055  state->pInfcount--;
5056  else if (NUMERIC_IS_NINF(newval))
5057  state->nInfcount--;
5058  else
5059  state->NaNcount--;
5060  return true;
5061  }
5062 
5063  /* load processed number in short-lived context */
5065 
5066  /*
5067  * state->sumX's dscale is the maximum dscale of any of the inputs.
5068  * Removing the last input with that dscale would require us to recompute
5069  * the maximum dscale of the *remaining* inputs, which we cannot do unless
5070  * no more non-NaN inputs remain at all. So we report a failure instead,
5071  * and force the aggregation to be redone from scratch.
5072  */
5073  if (X.dscale == state->maxScale)
5074  {
5075  if (state->maxScaleCount > 1 || state->maxScale == 0)
5076  {
5077  /*
5078  * Some remaining inputs have same dscale, or dscale hasn't gotten
5079  * above zero anyway
5080  */
5081  state->maxScaleCount--;
5082  }
5083  else if (state->N == 1)
5084  {
5085  /* No remaining non-NaN inputs at all, so reset maxScale */
5086  state->maxScale = 0;
5087  state->maxScaleCount = 0;
5088  }
5089  else
5090  {
5091  /* Correct new maxScale is uncertain, must fail */
5092  return false;
5093  }
5094  }
5095 
5096  /* if we need X^2, calculate that in short-lived context */
5097  if (state->calcSumX2)
5098  {
5099  init_var(&X2);
5100  mul_var(&X, &X, &X2, X.dscale * 2);
5101  }
5102 
5103  /* The rest of this needs to work in the aggregate context */
5104  old_context = MemoryContextSwitchTo(state->agg_context);
5105 
5106  if (state->N-- > 1)
5107  {
5108  /* Negate X, to subtract it from the sum */
5109  X.sign = (X.sign == NUMERIC_POS ? NUMERIC_NEG : NUMERIC_POS);
5110  accum_sum_add(&(state->sumX), &X);
5111 
5112  if (state->calcSumX2)
5113  {
5114  /* Negate X^2. X^2 is always positive */
5115  X2.sign = NUMERIC_NEG;
5116  accum_sum_add(&(state->sumX2), &X2);
5117  }
5118  }
5119  else
5120  {
5121  /* Zero the sums */
5122  Assert(state->N == 0);
5123 
5124  accum_sum_reset(&state->sumX);
5125  if (state->calcSumX2)
5126  accum_sum_reset(&state->sumX2);
5127  }
5128 
5129  MemoryContextSwitchTo(old_context);
5130 
5131  return true;
5132 }
static void accum_sum_reset(NumericSumAccum *accum)
Definition: numeric.c:12317

References accum_sum_add(), accum_sum_reset(), Assert, NumericVar::dscale, init_var, init_var_from_num(), MemoryContextSwitchTo(), mul_var(), newval, NUMERIC_IS_NINF, NUMERIC_IS_PINF, NUMERIC_IS_SPECIAL, NUMERIC_NEG, NUMERIC_POS, and NumericVar::sign.

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

◆ duplicate_numeric()

static Numeric duplicate_numeric ( Numeric  num)
static

Definition at line 7881 of file numeric.c.

7882 {
7883  Numeric res;
7884 
7885  res = (Numeric) palloc(VARSIZE(num));
7886  memcpy(res, num, VARSIZE(num));
7887  return res;
7888 }
struct NumericData * Numeric
Definition: numeric.h:54
#define VARSIZE(PTR)
Definition: varatt.h:279

References palloc(), res, and VARSIZE.

Referenced by numeric(), numeric_abs(), numeric_ceil(), numeric_exp(), numeric_floor(), numeric_inc(), numeric_ln(), numeric_mod_opt_error(), numeric_round(), numeric_sqrt(), numeric_trim_scale(), numeric_trunc(), numeric_uminus(), and numeric_uplus().

◆ estimate_ln_dweight()

static int estimate_ln_dweight ( const NumericVar var)
static

Definition at line 11028 of file numeric.c.

11029 {
11030  int ln_dweight;
11031 
11032  /* Caller should fail on ln(negative), but for the moment return zero */
11033  if (var->sign != NUMERIC_POS)
11034  return 0;
11035 
11036  if (cmp_var(var, &const_zero_point_nine) >= 0 &&
11037  cmp_var(var, &const_one_point_one) <= 0)
11038  {
11039  /*
11040  * 0.9 <= var <= 1.1
11041  *
11042  * ln(var) has a negative weight (possibly very large). To get a
11043  * reasonably accurate result, estimate it using ln(1+x) ~= x.
11044  */
11045  NumericVar x;
11046 
11047  init_var(&x);
11048  sub_var(var, &const_one, &x);
11049 
11050  if (x.ndigits > 0)
11051  {
11052  /* Use weight of most significant decimal digit of x */
11053  ln_dweight = x.weight * DEC_DIGITS + (int) log10(x.digits[0]);
11054  }
11055  else
11056  {
11057  /* x = 0. Since ln(1) = 0 exactly, we don't need extra digits */
11058  ln_dweight = 0;
11059  }
11060 
11061  free_var(&x);
11062  }
11063  else
11064  {
11065  /*
11066  * Estimate the logarithm using the first couple of digits from the
11067  * input number. This will give an accurate result whenever the input
11068  * is not too close to 1.
11069  */
11070  if (var->ndigits > 0)
11071  {
11072  int digits;
11073  int dweight;
11074  double ln_var;
11075 
11076  digits = var->digits[0];
11077  dweight = var->weight * DEC_DIGITS;
11078 
11079  if (var->ndigits > 1)
11080  {
11081  digits = digits * NBASE + var->digits[1];
11082  dweight -= DEC_DIGITS;
11083  }
11084 
11085  /*----------
11086  * We have var ~= digits * 10^dweight
11087  * so ln(var) ~= ln(digits) + dweight * ln(10)
11088  *----------
11089  */
11090  ln_var = log((double) digits) + dweight * 2.302585092994046;
11091  ln_dweight = (int) log10(fabs(ln_var));
11092  }
11093  else
11094  {
11095  /* Caller should fail on ln(0), but for the moment return zero */
11096  ln_dweight = 0;
11097  }
11098  }
11099 
11100  return ln_dweight;
11101 }
static const NumericVar const_zero_point_nine
Definition: numeric.c:446
static const NumericVar const_one_point_one
Definition: numeric.c:456
static void ln_var(const NumericVar *arg, NumericVar *result, int rscale)
Definition: numeric.c:11110
int digits
Definition: informix.c:691
int x
Definition: isn.c:70

References cmp_var(), const_one, const_one_point_one, const_zero_point_nine, DEC_DIGITS, NumericVar::digits, digits, free_var(), init_var, ln_var(), NBASE, NumericVar::ndigits, NUMERIC_POS, NumericVar::sign, sub_var(), NumericVar::weight, and x.

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

◆ exp_var()

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

Definition at line 10899 of file numeric.c.

10900 {
10901  NumericVar x;
10902  NumericVar elem;
10903  int ni;
10904  double val;
10905  int dweight;
10906  int ndiv2;
10907  int sig_digits;
10908  int local_rscale;
10909 
10910  init_var(&x);
10911  init_var(&elem);
10912 
10913  set_var_from_var(arg, &x);
10914 
10915  /*
10916  * Estimate the dweight of the result using floating point arithmetic, so
10917  * that we can choose an appropriate local rscale for the calculation.
10918  */
10920 
10921  /* Guard against overflow/underflow */
10922  /* If you change this limit, see also power_var()'s limit */
10923  if (fabs(val) >= NUMERIC_MAX_RESULT_SCALE * 3)
10924  {
10925  if (val > 0)
10926  ereport(ERROR,
10927  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
10928  errmsg("value overflows numeric format")));
10929  zero_var(result);
10930  result->dscale = rscale;
10931  return;
10932  }
10933 
10934  /* decimal weight = log10(e^x) = x * log10(e) */
10935  dweight = (int) (val * 0.434294481903252);
10936 
10937  /*
10938  * Reduce x to the range -0.01 <= x <= 0.01 (approximately) by dividing by
10939  * 2^ndiv2, to improve the convergence rate of the Taylor series.
10940  *
10941  * Note that the overflow check above ensures that fabs(x) < 6000, which
10942  * means that ndiv2 <= 20 here.
10943  */
10944  if (fabs(val) > 0.01)
10945  {
10946  ndiv2 = 1;
10947  val /= 2;
10948 
10949  while (fabs(val) > 0.01)
10950  {
10951  ndiv2++;
10952  val /= 2;
10953  }
10954 
10955  local_rscale = x.dscale + ndiv2;
10956  div_var_int(&x, 1 << ndiv2, 0, &x, local_rscale, true);
10957  }
10958  else
10959  ndiv2 = 0;
10960 
10961  /*
10962  * Set the scale for the Taylor series expansion. The final result has
10963  * (dweight + rscale + 1) significant digits. In addition, we have to
10964  * raise the Taylor series result to the power 2^ndiv2, which introduces
10965  * an error of up to around log10(2^ndiv2) digits, so work with this many
10966  * extra digits of precision (plus a few more for good measure).
10967  */
10968  sig_digits = 1 + dweight + rscale + (int) (ndiv2 * 0.301029995663981);
10969  sig_digits = Max(sig_digits, 0) + 8;
10970 
10971  local_rscale = sig_digits - 1;
10972 
10973  /*
10974  * Use the Taylor series
10975  *
10976  * exp(x) = 1 + x + x^2/2! + x^3/3! + ...
10977  *
10978  * Given the limited range of x, this should converge reasonably quickly.
10979  * We run the series until the terms fall below the local_rscale limit.
10980  */
10981  add_var(&const_one, &x, result);
10982 
10983  mul_var(&x, &x, &elem, local_rscale);
10984  ni = 2;
10985  div_var_int(&elem, ni, 0, &elem, local_rscale, true);
10986 
10987  while (elem.ndigits != 0)
10988  {
10989  add_var(result, &elem, result);
10990 
10991  mul_var(&elem, &x, &elem, local_rscale);
10992  ni++;
10993  div_var_int(&elem, ni, 0, &elem, local_rscale, true);
10994  }
10995 
10996  /*
10997  * Compensate for the argument range reduction. Since the weight of the
10998  * result doubles with each multiplication, we can reduce the local rscale
10999  * as we proceed.
11000  */
11001  while (ndiv2-- > 0)
11002  {
11003  local_rscale = sig_digits - result->weight * 2 * DEC_DIGITS;
11004  local_rscale = Max(local_rscale, NUMERIC_MIN_DISPLAY_SCALE);
11005  mul_var(result, result, result, local_rscale);
11006  }
11007 
11008  /* Round to requested rscale */
11009  round_var(result, rscale);
11010 
11011  free_var(&x);
11012  free_var(&elem);
11013 }
static double numericvar_to_double_no_overflow(const NumericVar *var)
Definition: numeric.c:8459
#define NUMERIC_MAX_RESULT_SCALE
Definition: numeric.h:43
#define NUMERIC_MIN_DISPLAY_SCALE
Definition: numeric.h:41
void * arg

References add_var(), arg, const_one, DEC_DIGITS, div_var_int(), 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, NumericVar::weight, x, and zero_var().

Referenced by numeric_exp(), and power_var().

◆ float4_numeric()

Datum float4_numeric ( PG_FUNCTION_ARGS  )

Definition at line 4805 of file numeric.c.

4806 {
4808  Numeric res;
4809  NumericVar result;
4810  char buf[FLT_DIG + 100];
4811  const char *endptr;
4812 
4813  if (isnan(val))
4815 
4816  if (isinf(val))
4817  {
4818  if (val < 0)
4820  else
4822  }
4823 
4824  snprintf(buf, sizeof(buf), "%.*g", FLT_DIG, val);
4825 
4826  init_var(&result);
4827 
4828  /* Assume we need not worry about leading/trailing spaces */
4829  (void) set_var_from_str(buf, buf, &result, &endptr, NULL);
4830 
4831  res = make_result(&result);
4832 
4833  free_var(&result);
4834 
4836 }
static const NumericVar const_pinf
Definition: numeric.c:462
static const NumericVar const_ninf
Definition: numeric.c:465
static bool set_var_from_str(const char *str, const char *cp, NumericVar *dest, const char **endptr, Node *escontext)
Definition: numeric.c:7130
static Numeric make_result(const NumericVar *var)
Definition: numeric.c:8009
static const NumericVar const_nan
Definition: numeric.c:459
float float4
Definition: c.h:608
#define PG_GETARG_FLOAT4(n)
Definition: fmgr.h:281
#define PG_RETURN_NUMERIC(x)
Definition: numeric.h:80
#define snprintf
Definition: port.h:238

References buf, const_nan, const_ninf, const_pinf, free_var(), init_var, make_result(), PG_GETARG_FLOAT4, PG_RETURN_NUMERIC, res, set_var_from_str(), snprintf, and val.

Referenced by JsonItemFromDatum().

◆ float8_numeric()

Datum float8_numeric ( PG_FUNCTION_ARGS  )

Definition at line 4711 of file numeric.c.

4712 {
4714  Numeric res;
4715  NumericVar result;
4716  char buf[DBL_DIG + 100];
4717  const char *endptr;
4718 
4719  if (isnan(val))
4721 
4722  if (isinf(val))
4723  {
4724  if (val < 0)
4726  else
4728  }
4729 
4730  snprintf(buf, sizeof(buf), "%.*g", DBL_DIG, val);
4731 
4732  init_var(&result);
4733 
4734  /* Assume we need not worry about leading/trailing spaces */
4735  (void) set_var_from_str(buf, buf, &result, &endptr, NULL);
4736 
4737  res = make_result(&result);
4738 
4739  free_var(&result);
4740 
4742 }
double float8
Definition: c.h:609
#define PG_GETARG_FLOAT8(n)
Definition: fmgr.h:282

References buf, const_nan, const_ninf, const_pinf, free_var(), init_var, make_result(), PG_GETARG_FLOAT8, PG_RETURN_NUMERIC, res, set_var_from_str(), snprintf, and val.

Referenced by executeItemOptUnwrapTarget(), JsonItemFromDatum(), and SV_to_JsonbValue().

◆ floor_var()

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

Definition at line 10326 of file numeric.c.

10327 {
10328  NumericVar tmp;
10329 
10330  init_var(&tmp);
10331  set_var_from_var(var, &tmp);
10332 
10333  trunc_var(&tmp, 0);
10334 
10335  if (var->sign == NUMERIC_NEG && cmp_var(var, &tmp) != 0)
10336  sub_var(&tmp, &const_one, &tmp);
10337 
10338  set_var_from_var(&tmp, result);
10339  free_var(&tmp);
10340 }

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

Referenced by numeric_floor().

◆ free_var()

static void free_var ( NumericVar var)
static

Definition at line 7087 of file numeric.c.

7088 {
7089  digitbuf_free(var->buf);
7090  var->buf = NULL;
7091  var->digits = NULL;
7092  var->sign = NUMERIC_NAN;
7093 }
#define NUMERIC_NAN
Definition: numeric.c:200

References NumericVar::buf, digitbuf_free, NumericVar::digits, NUMERIC_NAN, and NumericVar::sign.

Referenced by accum_sum_combine(), ceil_var(), compute_bucket(), div_mod_var(), estimate_ln_dweight(), exp_var(), float4_numeric(), float8_numeric(), floor_var(), gcd_var(), generate_series_numeric_support(), get_str_from_var_sci(), in_range_numeric_numeric(), int64_div_fast_to_numeric(), int64_to_numeric(), int8_avg_deserialize(), int8_avg_serialize(), ln_var(), log_var(), mod_var(), numeric(), numeric_add_opt_error(), numeric_avg(), numeric_avg_deserialize(), numeric_avg_serialize(), numeric_ceil(), numeric_deserialize(), numeric_div_opt_error(), numeric_div_trunc(), numeric_exp(), numeric_fac(), numeric_floor(), numeric_gcd(), numeric_in(), numeric_inc(), numeric_lcm(), numeric_ln(), numeric_log(), numeric_min_scale(), numeric_mod_opt_error(), numeric_mul_opt_error(), numeric_poly_avg(), numeric_poly_deserialize(), numeric_poly_serialize(), numeric_poly_sum(), numeric_power(), numeric_recv(), numeric_round(), numeric_serialize(), numeric_sqrt(), numeric_stddev_internal(), numeric_sub_opt_error(), numeric_sum(), numeric_trim_scale(), numeric_trunc(), numericvar_to_int64(), numericvar_to_uint64(), power_var(), power_var_int(), random_numeric(), random_var(), set_var_from_non_decimal_integer_str(), sqrt_var(), and width_bucket_numeric().

◆ gcd_var()

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

Definition at line 10349 of file numeric.c.

10350 {
10351  int res_dscale;
10352  int cmp;
10353  NumericVar tmp_arg;
10354  NumericVar mod;
10355 
10356  res_dscale = Max(var1->dscale, var2->dscale);
10357 
10358  /*
10359  * Arrange for var1 to be the number with the greater absolute value.
10360  *
10361  * This would happen automatically in the loop below, but avoids an
10362  * expensive modulo operation.
10363  */
10364  cmp = cmp_abs(var1, var2);
10365  if (cmp < 0)
10366  {
10367  const NumericVar *tmp = var1;
10368 
10369  var1 = var2;
10370  var2 = tmp;
10371  }
10372 
10373  /*
10374  * Also avoid the taking the modulo if the inputs have the same absolute
10375  * value, or if the smaller input is zero.
10376  */
10377  if (cmp == 0 || var2->ndigits == 0)
10378  {
10379  set_var_from_var(var1, result);
10380  result->sign = NUMERIC_POS;
10381  result->dscale = res_dscale;
10382  return;
10383  }
10384 
10385  init_var(&tmp_arg);
10386  init_var(&mod);
10387 
10388  /* Use the Euclidean algorithm to find the GCD */
10389  set_var_from_var(var1, &tmp_arg);
10390  set_var_from_var(var2, result);
10391 
10392  for (;;)
10393  {
10394  /* this loop can take a while, so allow it to be interrupted */
10396 
10397  mod_var(&tmp_arg, result, &mod);
10398  if (mod.ndigits == 0)
10399  break;
10400  set_var_from_var(result, &tmp_arg);
10401  set_var_from_var(&mod, result);
10402  }
10403  result->sign = NUMERIC_POS;
10404  result->dscale = res_dscale;
10405 
10406  free_var(&tmp_arg);
10407  free_var(&mod);
10408 }
static void mod_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition: numeric.c:10203
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:122
static int cmp(const chr *x, const chr *y, size_t len)
Definition: regc_locale.c:743

References CHECK_FOR_INTERRUPTS, cmp(), cmp_abs(), NumericVar::dscale, free_var(), init_var, Max, mod_var(), NumericVar::ndigits, NUMERIC_POS, set_var_from_var(), and NumericVar::sign.

Referenced by numeric_gcd(), and numeric_lcm().

◆ generate_series_numeric()

Datum generate_series_numeric ( PG_FUNCTION_ARGS  )

Definition at line 1703 of file numeric.c.

1704 {
1705  return generate_series_step_numeric(fcinfo);
1706 }
Datum generate_series_step_numeric(PG_FUNCTION_ARGS)
Definition: numeric.c:1709

References generate_series_step_numeric().

◆ generate_series_numeric_support()

Datum generate_series_numeric_support ( PG_FUNCTION_ARGS  )

Definition at line 1835 of file numeric.c.

1836 {
1837  Node *rawreq = (Node *) PG_GETARG_POINTER(0);
1838  Node *ret = NULL;
1839 
1840  if (IsA(rawreq, SupportRequestRows))
1841  {
1842  /* Try to estimate the number of rows returned */
1843  SupportRequestRows *req = (SupportRequestRows *) rawreq;
1844 
1845  if (is_funcclause(req->node)) /* be paranoid */
1846  {
1847  List *args = ((FuncExpr *) req->node)->args;
1848  Node *arg1,
1849  *arg2,
1850  *arg3;
1851 
1852  /* We can use estimated argument values here */
1854  arg2 = estimate_expression_value(req->root, lsecond(args));
1855  if (list_length(args) >= 3)
1856  arg3 = estimate_expression_value(req->root, lthird(args));
1857  else
1858  arg3 = NULL;
1859 
1860  /*
1861  * If any argument is constant NULL, we can safely assume that
1862  * zero rows are returned. Otherwise, if they're all non-NULL
1863  * constants, we can calculate the number of rows that will be
1864  * returned.
1865  */
1866  if ((IsA(arg1, Const) &&
1867  ((Const *) arg1)->constisnull) ||
1868  (IsA(arg2, Const) &&
1869  ((Const *) arg2)->constisnull) ||
1870  (arg3 != NULL && IsA(arg3, Const) &&
1871  ((Const *) arg3)->constisnull))
1872  {
1873  req->rows = 0;
1874  ret = (Node *) req;
1875  }
1876  else if (IsA(arg1, Const) &&
1877  IsA(arg2, Const) &&
1878  (arg3 == NULL || IsA(arg3, Const)))
1879  {
1880  Numeric start_num;
1881  Numeric stop_num;
1882  NumericVar step = const_one;
1883 
1884  /*
1885  * If any argument is NaN or infinity, generate_series() will
1886  * error out, so we needn't produce an estimate.
1887  */
1888  start_num = DatumGetNumeric(((Const *) arg1)->constvalue);
1889  stop_num = DatumGetNumeric(((Const *) arg2)->constvalue);
1890 
1891  if (NUMERIC_IS_SPECIAL(start_num) ||
1892  NUMERIC_IS_SPECIAL(stop_num))
1893  PG_RETURN_POINTER(NULL);
1894 
1895  if (arg3)
1896  {
1897  Numeric step_num;
1898 
1899  step_num = DatumGetNumeric(((Const *) arg3)->constvalue);
1900 
1901  if (NUMERIC_IS_SPECIAL(step_num))
1902  PG_RETURN_POINTER(NULL);
1903 
1904  init_var_from_num(step_num, &step);
1905  }
1906 
1907  /*
1908  * The number of rows that will be returned is given by
1909  * floor((stop - start) / step) + 1, if the sign of step
1910  * matches the sign of stop - start. Otherwise, no rows will
1911  * be returned.
1912  */
1913  if (cmp_var(&step, &const_zero) != 0)
1914  {
1915  NumericVar start;
1916  NumericVar stop;
1917  NumericVar res;
1918 
1919  init_var_from_num(start_num, &start);
1920  init_var_from_num(stop_num, &stop);
1921 
1922  init_var(&res);
1923  sub_var(&stop, &start, &res);
1924 
1925  if (step.sign != res.sign)
1926  {
1927  /* no rows will be returned */
1928  req->rows = 0;
1929  ret = (Node *) req;
1930  }
1931  else
1932  {
1933  if (arg3)
1934  div_var(&res, &step, &res, 0, false, false);
1935  else
1936  trunc_var(&res, 0); /* step = 1 */
1937 
1939  ret = (Node *) req;
1940  }
1941 
1942  free_var(&res);
1943  }
1944  }
1945  }
1946  }
1947 
1948  PG_RETURN_POINTER(ret);
1949 }
Node * estimate_expression_value(PlannerInfo *root, Node *node)
Definition: clauses.c:2394
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:276
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:361
return str start
static bool is_funcclause(const void *clause)
Definition: nodeFuncs.h:69
#define IsA(nodeptr, _type_)
Definition: nodes.h:158
static Numeric DatumGetNumeric(Datum X)
Definition: numeric.h:61
static int list_length(const List *l)
Definition: pg_list.h:152
#define lthird(l)
Definition: pg_list.h:188
#define linitial(l)
Definition: pg_list.h:178
#define lsecond(l)
Definition: pg_list.h:183
Definition: pg_list.h:54
Definition: nodes.h:129
struct PlannerInfo * root
Definition: supportnodes.h:163

References generate_unaccent_rules::args, cmp_var(), const_one, const_zero, DatumGetNumeric(), div_var(), estimate_expression_value(), free_var(), init_var, init_var_from_num(), is_funcclause(), IsA, linitial, list_length(), lsecond, lthird, SupportRequestRows::node, NUMERIC_IS_SPECIAL, numericvar_to_double_no_overflow(), PG_GETARG_POINTER, PG_RETURN_POINTER, res, SupportRequestRows::root, SupportRequestRows::rows, NumericVar::sign, start, sub_var(), and trunc_var().

◆ generate_series_step_numeric()

Datum generate_series_step_numeric ( PG_FUNCTION_ARGS  )

Definition at line 1709 of file numeric.c.

1710 {
1712  FuncCallContext *funcctx;
1713  MemoryContext oldcontext;
1714 
1715  if (SRF_IS_FIRSTCALL())
1716  {
1717  Numeric start_num = PG_GETARG_NUMERIC(0);
1718  Numeric stop_num = PG_GETARG_NUMERIC(1);
1719  NumericVar steploc = const_one;
1720 
1721  /* Reject NaN and infinities in start and stop values */
1722  if (NUMERIC_IS_SPECIAL(start_num))
1723  {
1724  if (NUMERIC_IS_NAN(start_num))
1725  ereport(ERROR,
1726  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1727  errmsg("start value cannot be NaN")));
1728  else
1729  ereport(ERROR,
1730  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1731  errmsg("start value cannot be infinity")));
1732  }
1733  if (NUMERIC_IS_SPECIAL(stop_num))
1734  {
1735  if (NUMERIC_IS_NAN(stop_num))
1736  ereport(ERROR,
1737  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1738  errmsg("stop value cannot be NaN")));
1739  else
1740  ereport(ERROR,
1741  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1742  errmsg("stop value cannot be infinity")));
1743  }
1744 
1745  /* see if we were given an explicit step size */
1746  if (PG_NARGS() == 3)
1747  {
1748  Numeric step_num = PG_GETARG_NUMERIC(2);
1749 
1750  if (NUMERIC_IS_SPECIAL(step_num))
1751  {
1752  if (NUMERIC_IS_NAN(step_num))
1753  ereport(ERROR,
1754  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1755  errmsg("step size cannot be NaN")));
1756  else
1757  ereport(ERROR,
1758  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1759  errmsg("step size cannot be infinity")));
1760  }
1761 
1762  init_var_from_num(step_num, &steploc);
1763 
1764  if (cmp_var(&steploc, &const_zero) == 0)
1765  ereport(ERROR,
1766  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1767  errmsg("step size cannot equal zero")));
1768  }
1769 
1770  /* create a function context for cross-call persistence */
1771  funcctx = SRF_FIRSTCALL_INIT();
1772 
1773  /*
1774  * Switch to memory context appropriate for multiple function calls.
1775  */
1776  oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
1777 
1778  /* allocate memory for user context */
1779  fctx = (generate_series_numeric_fctx *)
1781 
1782  /*
1783  * Use fctx to keep state from call to call. Seed current with the
1784  * original start value. We must copy the start_num and stop_num
1785  * values rather than pointing to them, since we may have detoasted
1786  * them in the per-call context.
1787  */
1788  init_var(&fctx->current);
1789  init_var(&fctx->stop);
1790  init_var(&fctx->step);
1791 
1792  set_var_from_num(start_num, &fctx->current);
1793  set_var_from_num(stop_num, &fctx->stop);
1794  set_var_from_var(&steploc, &fctx->step);
1795 
1796  funcctx->user_fctx = fctx;
1797  MemoryContextSwitchTo(oldcontext);
1798  }
1799 
1800  /* stuff done on every call of the function */
1801  funcctx = SRF_PERCALL_SETUP();
1802 
1803  /*
1804  * Get the saved state and use current state as the result of this
1805  * iteration.
1806  */
1807  fctx = funcctx->user_fctx;
1808 
1809  if ((fctx->step.sign == NUMERIC_POS &&
1810  cmp_var(&fctx->current, &fctx->stop) <= 0) ||
1811  (fctx->step.sign == NUMERIC_NEG &&
1812  cmp_var(&fctx->current, &fctx->stop) >= 0))
1813  {
1814  Numeric result = make_result(&fctx->current);
1815 
1816  /* switch to memory context appropriate for iteration calculation */
1817  oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
1818 
1819  /* increment current in preparation for next iteration */
1820  add_var(&fctx->current, &fctx->step, &fctx->current);
1821  MemoryContextSwitchTo(oldcontext);
1822 
1823  /* do when there is more left to send */
1824  SRF_RETURN_NEXT(funcctx, NumericGetDatum(result));
1825  }
1826  else
1827  /* do when there is no more left */
1828  SRF_RETURN_DONE(funcctx);
1829 }
static void set_var_from_num(Numeric num, NumericVar *dest)
Definition: numeric.c:7538
#define PG_NARGS()
Definition: fmgr.h:203
#define SRF_IS_FIRSTCALL()
Definition: funcapi.h:304
#define SRF_PERCALL_SETUP()
Definition: funcapi.h:308
#define SRF_RETURN_NEXT(_funcctx, _result)
Definition: funcapi.h:310
#define SRF_FIRSTCALL_INIT()
Definition: funcapi.h:306
#define SRF_RETURN_DONE(_funcctx)
Definition: funcapi.h:328
#define PG_GETARG_NUMERIC(n)
Definition: numeric.h:78
static Datum NumericGetDatum(Numeric X)
Definition: numeric.h:73
void * user_fctx
Definition: funcapi.h:82
MemoryContext multi_call_memory_ctx
Definition: funcapi.h:101

References add_var(), cmp_var(), const_one, const_zero, 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_IS_SPECIAL, 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().

◆ get_min_scale()

static int get_min_scale ( NumericVar var)
static

Definition at line 4254 of file numeric.c.

4255 {
4256  int min_scale;
4257  int last_digit_pos;
4258 
4259  /*
4260  * Ordinarily, the input value will be "stripped" so that the last
4261  * NumericDigit is nonzero. But we don't want to get into an infinite
4262  * loop if it isn't, so explicitly find the last nonzero digit.
4263  */
4264  last_digit_pos = var->ndigits - 1;
4265  while (last_digit_pos >= 0 &&
4266  var->digits[last_digit_pos] == 0)
4267  last_digit_pos--;
4268 
4269  if (last_digit_pos >= 0)
4270  {
4271  /* compute min_scale assuming that last ndigit has no zeroes */
4272  min_scale = (last_digit_pos - var->weight) * DEC_DIGITS;
4273 
4274  /*
4275  * We could get a negative result if there are no digits after the
4276  * decimal point. In this case the min_scale must be zero.
4277  */
4278  if (min_scale > 0)
4279  {
4280  /*
4281  * Reduce min_scale if trailing digit(s) in last NumericDigit are
4282  * zero.
4283  */
4284  NumericDigit last_digit = var->digits[last_digit_pos];
4285 
4286  while (last_digit % 10 == 0)
4287  {
4288  min_scale--;
4289  last_digit /= 10;
4290  }
4291  }
4292  else
4293  min_scale = 0;
4294  }
4295  else
4296  min_scale = 0; /* result if input is zero */
4297 
4298  return min_scale;
4299 }

References DEC_DIGITS, NumericVar::digits, NumericVar::ndigits, and NumericVar::weight.

Referenced by numeric_min_scale(), and numeric_trim_scale().

◆ get_str_from_var()

static char * get_str_from_var ( const NumericVar var)
static

Definition at line 7612 of file numeric.c.

7613 {
7614  int dscale;
7615  char *str;
7616  char *cp;
7617  char *endcp;
7618  int i;
7619  int d;
7620  NumericDigit dig;
7621 
7622 #if DEC_DIGITS > 1
7623  NumericDigit d1;
7624 #endif
7625 
7626  dscale = var->dscale;
7627 
7628  /*
7629  * Allocate space for the result.
7630  *
7631  * i is set to the # of decimal digits before decimal point. dscale is the
7632  * # of decimal digits we will print after decimal point. We may generate
7633  * as many as DEC_DIGITS-1 excess digits at the end, and in addition we
7634  * need room for sign, decimal point, null terminator.
7635  */
7636  i = (var->weight + 1) * DEC_DIGITS;
7637  if (i <= 0)
7638  i = 1;
7639 
7640  str = palloc(i + dscale + DEC_DIGITS + 2);
7641  cp = str;
7642 
7643  /*
7644  * Output a dash for negative values
7645  */
7646  if (var->sign == NUMERIC_NEG)
7647  *cp++ = '-';
7648 
7649  /*
7650  * Output all digits before the decimal point
7651  */
7652  if (var->weight < 0)
7653  {
7654  d = var->weight + 1;
7655  *cp++ = '0';
7656  }
7657  else
7658  {
7659  for (d = 0; d <= var->weight; d++)
7660  {
7661  dig = (d < var->ndigits) ? var->digits[d] : 0;
7662  /* In the first digit, suppress extra leading decimal zeroes */
7663 #if DEC_DIGITS == 4
7664  {
7665  bool putit = (d > 0);
7666 
7667  d1 = dig / 1000;
7668  dig -= d1 * 1000;
7669  putit |= (d1 > 0);
7670  if (putit)
7671  *cp++ = d1 + '0';
7672  d1 = dig / 100;
7673  dig -= d1 * 100;
7674  putit |= (d1 > 0);
7675  if (putit)
7676  *cp++ = d1 + '0';
7677  d1 = dig / 10;
7678  dig -= d1 * 10;
7679  putit |= (d1 > 0);
7680  if (putit)
7681  *cp++ = d1 + '0';
7682  *cp++ = dig + '0';
7683  }
7684 #elif DEC_DIGITS == 2
7685  d1 = dig / 10;
7686  dig -= d1 * 10;
7687  if (d1 > 0 || d > 0)
7688  *cp++ = d1 + '0';
7689  *cp++ = dig + '0';
7690 #elif DEC_DIGITS == 1
7691  *cp++ = dig + '0';
7692 #else
7693 #error unsupported NBASE
7694 #endif
7695  }
7696  }
7697 
7698  /*
7699  * If requested, output a decimal point and all the digits that follow it.
7700  * We initially put out a multiple of DEC_DIGITS digits, then truncate if
7701  * needed.
7702  */
7703  if (dscale > 0)
7704  {
7705  *cp++ = '.';
7706  endcp = cp + dscale;
7707  for (i = 0; i < dscale; d++, i += DEC_DIGITS)
7708  {
7709  dig = (d >= 0 && d < var->ndigits) ? var->digits[d] : 0;
7710 #if DEC_DIGITS == 4
7711  d1 = dig / 1000;
7712  dig -= d1 * 1000;
7713  *cp++ = d1 + '0';
7714  d1 = dig / 100;
7715  dig -= d1 * 100;
7716  *cp++ = d1 + '0';
7717  d1 = dig / 10;
7718  dig -= d1 * 10;
7719  *cp++ = d1 + '0';
7720  *cp++ = dig + '0';
7721 #elif DEC_DIGITS == 2
7722  d1 = dig / 10;
7723  dig -= d1 * 10;
7724  *cp++ = d1 + '0';
7725  *cp++ = dig + '0';
7726 #elif DEC_DIGITS == 1
7727  *cp++ = dig + '0';
7728 #else
7729 #error unsupported NBASE
7730 #endif
7731  }
7732  cp = endcp;
7733  }
7734 
7735  /*
7736  * terminate the string and return it
7737  */
7738  *cp = '\0';
7739  return str;
7740 }
const char * str
static void error(void)
Definition: sql-dyntest.c:147

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

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

◆ get_str_from_var_sci()

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

Definition at line 7765 of file numeric.c.

7766 {
7767  int32 exponent;
7768  NumericVar tmp_var;
7769  size_t len;
7770  char *str;
7771  char *sig_out;
7772 
7773  if (rscale < 0)
7774  rscale = 0;
7775 
7776  /*
7777  * Determine the exponent of this number in normalised form.
7778  *
7779  * This is the exponent required to represent the number with only one
7780  * significant digit before the decimal place.
7781  */
7782  if (var->ndigits > 0)
7783  {
7784  exponent = (var->weight + 1) * DEC_DIGITS;
7785 
7786  /*
7787  * Compensate for leading decimal zeroes in the first numeric digit by
7788  * decrementing the exponent.
7789  */
7790  exponent -= DEC_DIGITS - (int) log10(var->digits[0]);
7791  }
7792  else
7793  {
7794  /*
7795  * If var has no digits, then it must be zero.
7796  *
7797  * Zero doesn't technically have a meaningful exponent in normalised
7798  * notation, but we just display the exponent as zero for consistency
7799  * of output.
7800  */
7801  exponent = 0;
7802  }
7803 
7804  /*
7805  * Divide var by 10^exponent to get the significand, rounding to rscale
7806  * decimal digits in the process.
7807  */
7808  init_var(&tmp_var);
7809 
7810  power_ten_int(exponent, &tmp_var);
7811  div_var(var, &tmp_var, &tmp_var, rscale, true, true);
7812  sig_out = get_str_from_var(&tmp_var);
7813 
7814  free_var(&tmp_var);
7815 
7816  /*
7817  * Allocate space for the result.
7818  *
7819  * In addition to the significand, we need room for the exponent
7820  * decoration ("e"), the sign of the exponent, up to 10 digits for the
7821  * exponent itself, and of course the null terminator.
7822  */
7823  len = strlen(sig_out) + 13;
7824  str = palloc(len);
7825  snprintf(str, len, "%se%+03d", sig_out, exponent);
7826 
7827  pfree(sig_out);
7828 
7829  return str;
7830 }
static char * get_str_from_var(const NumericVar *var)
Definition: numeric.c:7612
static void power_ten_int(int exp, NumericVar *result)
Definition: numeric.c:11655
const void size_t len

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

Referenced by numeric_out_sci().

◆ hash_numeric()

Datum hash_numeric ( PG_FUNCTION_ARGS  )

Definition at line 2815 of file numeric.c.

2816 {
2818  Datum digit_hash;
2819  Datum result;
2820  int weight;
2821  int start_offset;
2822  int end_offset;
2823  int i;
2824  int hash_len;
2826 
2827  /* If it's NaN or infinity, don't try to hash the rest of the fields */
2828  if (NUMERIC_IS_SPECIAL(key))
2829  PG_RETURN_UINT32(0);
2830 
2831  weight = NUMERIC_WEIGHT(key);
2832  start_offset = 0;
2833  end_offset = 0;
2834 
2835  /*
2836  * Omit any leading or trailing zeros from the input to the hash. The
2837  * numeric implementation *should* guarantee that leading and trailing
2838  * zeros are suppressed, but we're paranoid. Note that we measure the
2839  * starting and ending offsets in units of NumericDigits, not bytes.
2840  */
2842  for (i = 0; i < NUMERIC_NDIGITS(key); i++)
2843  {
2844  if (digits[i] != (NumericDigit) 0)
2845  break;
2846 
2847  start_offset++;
2848 
2849  /*
2850  * The weight is effectively the # of digits before the decimal point,
2851  * so decrement it for each leading zero we skip.
2852  */
2853  weight--;
2854  }
2855 
2856  /*
2857  * If there are no non-zero digits, then the value of the number is zero,
2858  * regardless of any other fields.
2859  */
2860  if (NUMERIC_NDIGITS(key) == start_offset)
2861  PG_RETURN_UINT32(-1);
2862 
2863  for (i = NUMERIC_NDIGITS(key) - 1; i >= 0; i--)
2864  {
2865  if (digits[i] != (NumericDigit) 0)
2866  break;
2867 
2868  end_offset++;
2869  }
2870 
2871  /* If we get here, there should be at least one non-zero digit */
2872  Assert(start_offset + end_offset < NUMERIC_NDIGITS(key));
2873 
2874  /*
2875  * Note that we don't hash on the Numeric's scale, since two numerics can
2876  * compare equal but have different scales. We also don't hash on the
2877  * sign, although we could: since a sign difference implies inequality,
2878  * this shouldn't affect correctness.
2879  */
2880  hash_len = NUMERIC_NDIGITS(key) - start_offset - end_offset;
2881  digit_hash = hash_any((unsigned char *) (NUMERIC_DIGITS(key) + start_offset),
2882  hash_len * sizeof(NumericDigit));
2883 
2884  /* Mix in the weight, via XOR */
2885  result = digit_hash ^ weight;
2886 
2887  PG_RETURN_DATUM(result);
2888 }
#define PG_RETURN_UINT32(x)
Definition: fmgr.h:355
#define PG_RETURN_DATUM(x)
Definition: fmgr.h:353
static Datum hash_any(const unsigned char *k, int keylen)
Definition: hashfn.h:31
uintptr_t Datum
Definition: postgres.h:64

References Assert, digits, hash_any(), i, sort-test::key, NUMERIC_DIGITS, NUMERIC_IS_SPECIAL, NUMERIC_NDIGITS, NUMERIC_WEIGHT, PG_GETARG_NUMERIC, PG_RETURN_DATUM, and PG_RETURN_UINT32.

Referenced by JsonbHashScalarValue().

◆ hash_numeric_extended()

Datum hash_numeric_extended ( PG_FUNCTION_ARGS  )

Definition at line 2895 of file numeric.c.

2896 {
2898  uint64 seed = PG_GETARG_INT64(1);
2899  Datum digit_hash;
2900  Datum result;
2901  int weight;
2902  int start_offset;
2903  int end_offset;
2904  int i;
2905  int hash_len;
2907 
2908  /* If it's NaN or infinity, don't try to hash the rest of the fields */
2909  if (NUMERIC_IS_SPECIAL(key))
2910  PG_RETURN_UINT64(seed);
2911 
2912  weight = NUMERIC_WEIGHT(key);
2913  start_offset = 0;
2914  end_offset = 0;
2915 
2917  for (i = 0; i < NUMERIC_NDIGITS(key); i++)
2918  {
2919  if (digits[i] != (NumericDigit) 0)
2920  break;
2921 
2922  start_offset++;
2923 
2924  weight--;
2925  }
2926 
2927  if (NUMERIC_NDIGITS(key) == start_offset)
2928  PG_RETURN_UINT64(seed - 1);
2929 
2930  for (i = NUMERIC_NDIGITS(key) - 1; i >= 0; i--)
2931  {
2932  if (digits[i] != (NumericDigit) 0)
2933  break;
2934 
2935  end_offset++;
2936  }
2937 
2938  Assert(start_offset + end_offset < NUMERIC_NDIGITS(key));
2939 
2940  hash_len = NUMERIC_NDIGITS(key) - start_offset - end_offset;
2941  digit_hash = hash_any_extended((unsigned char *) (NUMERIC_DIGITS(key)
2942  + start_offset),
2943  hash_len * sizeof(NumericDigit),
2944  seed);
2945 
2946  result = UInt64GetDatum(DatumGetUInt64(digit_hash) ^ weight);
2947 
2948  PG_RETURN_DATUM(result);
2949 }
#define PG_GETARG_INT64(n)
Definition: fmgr.h:283
#define PG_RETURN_UINT64(x)
Definition: fmgr.h:369
static Datum hash_any_extended(const unsigned char *k, int keylen, uint64 seed)
Definition: hashfn.h:37
static uint64 DatumGetUInt64(Datum X)
Definition: postgres.h:419
static Datum UInt64GetDatum(uint64 X)
Definition: postgres.h:436

References Assert, DatumGetUInt64(), digits, hash_any_extended(), i, sort-test::key, NUMERIC_DIGITS, NUMERIC_IS_SPECIAL, NUMERIC_NDIGITS, NUMERIC_WEIGHT, PG_GETARG_INT64, PG_GETARG_NUMERIC, PG_RETURN_DATUM, PG_RETURN_UINT64, and UInt64GetDatum().

Referenced by JsonbHashScalarValueExtended().

◆ in_range_numeric_numeric()

Datum in_range_numeric_numeric ( PG_FUNCTION_ARGS  )

Definition at line 2680 of file numeric.c.

2681 {
2683  Numeric base = PG_GETARG_NUMERIC(1);
2684  Numeric offset = PG_GETARG_NUMERIC(2);
2685  bool sub = PG_GETARG_BOOL(3);
2686  bool less = PG_GETARG_BOOL(4);
2687  bool result;
2688 
2689  /*
2690  * Reject negative (including -Inf) or NaN offset. Negative is per spec,
2691  * and NaN is because appropriate semantics for that seem non-obvious.
2692  */
2693  if (NUMERIC_IS_NAN(offset) ||
2694  NUMERIC_IS_NINF(offset) ||
2695  NUMERIC_SIGN(offset) == NUMERIC_NEG)
2696  ereport(ERROR,
2697  (errcode(ERRCODE_INVALID_PRECEDING_OR_FOLLOWING_SIZE),
2698  errmsg("invalid preceding or following size in window function")));
2699 
2700  /*
2701  * Deal with cases where val and/or base is NaN, following the rule that
2702  * NaN sorts after non-NaN (cf cmp_numerics). The offset cannot affect
2703  * the conclusion.
2704  */
2705  if (NUMERIC_IS_NAN(val))
2706  {
2707  if (NUMERIC_IS_NAN(base))
2708  result = true; /* NAN = NAN */
2709  else
2710  result = !less; /* NAN > non-NAN */
2711  }
2712  else if (NUMERIC_IS_NAN(base))
2713  {
2714  result = less; /* non-NAN < NAN */
2715  }
2716 
2717  /*
2718  * Deal with infinite offset (necessarily +Inf, at this point).
2719  */
2720  else if (NUMERIC_IS_SPECIAL(offset))
2721  {
2722  Assert(NUMERIC_IS_PINF(offset));
2723  if (sub ? NUMERIC_IS_PINF(base) : NUMERIC_IS_NINF(base))
2724  {
2725  /*
2726  * base +/- offset would produce NaN, so return true for any val
2727  * (see in_range_float8_float8() for reasoning).
2728  */
2729  result = true;
2730  }
2731  else if (sub)
2732  {
2733  /* base - offset must be -inf */
2734  if (less)
2735  result = NUMERIC_IS_NINF(val); /* only -inf is <= sum */
2736  else
2737  result = true; /* any val is >= sum */
2738  }
2739  else
2740  {
2741  /* base + offset must be +inf */
2742  if (less)
2743  result = true; /* any val is <= sum */
2744  else
2745  result = NUMERIC_IS_PINF(val); /* only +inf is >= sum */
2746  }
2747  }
2748 
2749  /*
2750  * Deal with cases where val and/or base is infinite. The offset, being
2751  * now known finite, cannot affect the conclusion.
2752  */
2753  else if (NUMERIC_IS_SPECIAL(val))
2754  {
2755  if (NUMERIC_IS_PINF(val))
2756  {
2757  if (NUMERIC_IS_PINF(base))
2758  result = true; /* PINF = PINF */
2759  else
2760  result = !less; /* PINF > any other non-NAN */
2761  }
2762  else /* val must be NINF */
2763  {
2764  if (NUMERIC_IS_NINF(base))
2765  result = true; /* NINF = NINF */
2766  else
2767  result = less; /* NINF < anything else */
2768  }
2769  }
2770  else if (NUMERIC_IS_SPECIAL(base))
2771  {
2772  if (NUMERIC_IS_NINF(base))
2773  result = !less; /* normal > NINF */
2774  else
2775  result = less; /* normal < PINF */
2776  }
2777  else
2778  {
2779  /*
2780  * Otherwise go ahead and compute base +/- offset. While it's
2781  * possible for this to overflow the numeric format, it's unlikely
2782  * enough that we don't take measures to prevent it.
2783  */
2784  NumericVar valv;
2785  NumericVar basev;
2786  NumericVar offsetv;
2787  NumericVar sum;
2788 
2789  init_var_from_num(val, &valv);
2790  init_var_from_num(base, &basev);
2791  init_var_from_num(offset, &offsetv);
2792  init_var(&sum);
2793 
2794  if (sub)
2795  sub_var(&basev, &offsetv, &sum);
2796  else
2797  add_var(&basev, &offsetv, &sum);
2798 
2799  if (less)
2800  result = (cmp_var(&valv, &sum) <= 0);
2801  else
2802  result = (cmp_var(&valv, &sum) >= 0);
2803 
2804  free_var(&sum);
2805  }
2806 
2807  PG_FREE_IF_COPY(val, 0);
2808  PG_FREE_IF_COPY(base, 1);
2809  PG_FREE_IF_COPY(offset, 2);
2810 
2811  PG_RETURN_BOOL(result);
2812 }
#define PG_FREE_IF_COPY(ptr, n)
Definition: fmgr.h:260
#define PG_GETARG_BOOL(n)
Definition: fmgr.h:274
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:359

References add_var(), Assert, cmp_var(), ereport, errcode(), errmsg(), ERROR, free_var(), init_var, init_var_from_num(), NUMERIC_IS_NAN, NUMERIC_IS_NINF, NUMERIC_IS_PINF, NUMERIC_IS_SPECIAL, NUMERIC_NEG, NUMERIC_SIGN, PG_FREE_IF_COPY, PG_GETARG_BOOL, PG_GETARG_NUMERIC, PG_RETURN_BOOL, sub_var(), and val.

◆ init_var_from_num()

◆ int2_accum()

Datum int2_accum ( PG_FUNCTION_ARGS  )

Definition at line 5668 of file numeric.c.

5669 {
5671 
5672  state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
5673 
5674  /* Create the state data on the first call */
5675  if (state == NULL)
5676  state = makePolyNumAggState(fcinfo, true);
5677 
5678  if (!PG_ARGISNULL(1))
5679  {
5680 #ifdef HAVE_INT128
5681  do_int128_accum(state, (int128) PG_GETARG_INT16(1));
5682 #else
5684 #endif
5685  }
5686 
5688 }
#define makePolyNumAggState
Definition: numeric.c:5663
Numeric int64_to_numeric(int64 val)
Definition: numeric.c:4401
static void do_numeric_accum(NumericAggState *state, Numeric newval)
Definition: numeric.c:4975
#define PG_ARGISNULL(n)
Definition: fmgr.h:209
#define PG_GETARG_INT16(n)
Definition: fmgr.h:271

References do_numeric_accum(), int64_to_numeric(), makePolyNumAggState, PG_ARGISNULL, PG_GETARG_INT16, PG_GETARG_POINTER, and PG_RETURN_POINTER.

◆ int2_accum_inv()

Datum int2_accum_inv ( PG_FUNCTION_ARGS  )

Definition at line 6092 of file numeric.c.

6093 {
6095 
6096  state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
6097 
6098  /* Should not get here with no state */
6099  if (state == NULL)
6100  elog(ERROR, "int2_accum_inv called with NULL state");
6101 
6102  if (!PG_ARGISNULL(1))
6103  {
6104 #ifdef HAVE_INT128
6105  do_int128_discard(state, (int128) PG_GETARG_INT16(1));
6106 #else
6107  /* Should never fail, all inputs have dscale 0 */
6109  elog(ERROR, "do_numeric_discard failed unexpectedly");
6110 #endif
6111  }
6112 
6114 }
static bool do_numeric_discard(NumericAggState *state, Numeric newval)
Definition: numeric.c:5045
#define elog(elevel,...)
Definition: elog.h:225

References do_numeric_discard(), elog, ERROR, int64_to_numeric(), PG_ARGISNULL, PG_GETARG_INT16, PG_GETARG_POINTER, and PG_RETURN_POINTER.

◆ int2_avg_accum()

Datum int2_avg_accum ( PG_FUNCTION_ARGS  )

Definition at line 6775 of file numeric.c.

6776 {
6777  ArrayType *transarray;
6779  Int8TransTypeData *transdata;
6780 
6781  /*
6782  * If we're invoked as an aggregate, we can cheat and modify our first
6783  * parameter in-place to reduce palloc overhead. Otherwise we need to make
6784  * a copy of it before scribbling on it.
6785  */
6786  if (AggCheckCallContext(fcinfo, NULL))
6787  transarray = PG_GETARG_ARRAYTYPE_P(0);
6788  else
6789  transarray = PG_GETARG_ARRAYTYPE_P_COPY(0);
6790 
6791  if (ARR_HASNULL(transarray) ||
6792  ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
6793  elog(ERROR, "expected 2-element int8 array");
6794 
6795  transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
6796  transdata->count++;
6797  transdata->sum += newval;
6798 
6799  PG_RETURN_ARRAYTYPE_P(transarray);
6800 }
#define PG_GETARG_ARRAYTYPE_P_COPY(n)
Definition: array.h:264
#define PG_GETARG_ARRAYTYPE_P(n)
Definition: array.h:263
#define ARR_DATA_PTR(a)
Definition: array.h:322
#define PG_RETURN_ARRAYTYPE_P(x)
Definition: array.h:265
#define ARR_SIZE(a)
Definition: array.h:289
#define ARR_OVERHEAD_NONULLS(ndims)
Definition: array.h:310
#define ARR_HASNULL(a)
Definition: array.h:291
int AggCheckCallContext(FunctionCallInfo fcinfo, MemoryContext *aggcontext)
Definition: nodeAgg.c:4510

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.

◆ int2_avg_accum_inv()

Datum int2_avg_accum_inv ( PG_FUNCTION_ARGS  )

Definition at line 6862 of file numeric.c.

6863 {
6864  ArrayType *transarray;
6866  Int8TransTypeData *transdata;
6867 
6868  /*
6869  * If we're invoked as an aggregate, we can cheat and modify our first
6870  * parameter in-place to reduce palloc overhead. Otherwise we need to make
6871  * a copy of it before scribbling on it.
6872  */
6873  if (AggCheckCallContext(fcinfo, NULL))
6874  transarray = PG_GETARG_ARRAYTYPE_P(0);
6875  else
6876  transarray = PG_GETARG_ARRAYTYPE_P_COPY(0);
6877 
6878  if (ARR_HASNULL(transarray) ||
6879  ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
6880  elog(ERROR, "expected 2-element int8 array");
6881 
6882  transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
6883  transdata->count--;
6884  transdata->sum -= newval;
6885 
6886  PG_RETURN_ARRAYTYPE_P(transarray);
6887 }

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.

◆ int2_numeric()

Datum int2_numeric ( PG_FUNCTION_ARGS  )

Definition at line 4662 of file numeric.c.

4663 {
4664  int16 val = PG_GETARG_INT16(0);
4665 
4667 }

References int64_to_numeric(), PG_GETARG_INT16, PG_RETURN_NUMERIC, and val.

Referenced by JsonItemFromDatum().

◆ int2_sum()

Datum int2_sum ( PG_FUNCTION_ARGS  )

Definition at line 6626 of file numeric.c.

6627 {
6628  int64 newval;
6629 
6630  if (PG_ARGISNULL(0))
6631  {
6632  /* No non-null input seen so far... */
6633  if (PG_ARGISNULL(1))
6634  PG_RETURN_NULL(); /* still no non-null */
6635  /* This is the first non-null input. */
6636  newval = (int64) PG_GETARG_INT16(1);
6638  }
6639 
6640  /*
6641  * If we're invoked as an aggregate, we can cheat and modify our first
6642  * parameter in-place to avoid palloc overhead. If not, we need to return
6643  * the new value of the transition variable. (If int8 is pass-by-value,
6644  * then of course this is useless as well as incorrect, so just ifdef it
6645  * out.)
6646  */
6647 #ifndef USE_FLOAT8_BYVAL /* controls int8 too */
6648  if (AggCheckCallContext(fcinfo, NULL))
6649  {
6650  int64 *oldsum = (int64 *) PG_GETARG_POINTER(0);
6651 
6652  /* Leave the running sum unchanged in the new input is null */
6653  if (!PG_ARGISNULL(1))
6654  *oldsum = *oldsum + (int64) PG_GETARG_INT16(1);
6655 
6656  PG_RETURN_POINTER(oldsum);
6657  }
6658  else
6659 #endif
6660  {
6661  int64 oldsum = PG_GETARG_INT64(0);
6662 
6663  /* Leave sum unchanged if new input is null. */
6664  if (PG_ARGISNULL(1))
6665  PG_RETURN_INT64(oldsum);
6666 
6667  /* OK to do the addition. */
6668  newval = oldsum + (int64) PG_GETARG_INT16(1);
6669 
6671  }
6672 }
#define PG_RETURN_INT64(x)
Definition: fmgr.h:368
#define PG_RETURN_NULL()
Definition: fmgr.h:345

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

◆ int2int4_sum()

Datum int2int4_sum ( PG_FUNCTION_ARGS  )

Definition at line 6945 of file numeric.c.

6946 {
6947  ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
6948  Int8TransTypeData *transdata;
6949 
6950  if (ARR_HASNULL(transarray) ||
6951  ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
6952  elog(ERROR, "expected 2-element int8 array");
6953  transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
6954 
6955  /* SQL defines SUM of no values to be NULL */
6956  if (transdata->count == 0)
6957  PG_RETURN_NULL();
6958 
6959  PG_RETURN_DATUM(Int64GetDatumFast(transdata->sum));
6960 }
#define Int64GetDatumFast(X)
Definition: postgres.h:554

References ARR_DATA_PTR, ARR_HASNULL, ARR_OVERHEAD_NONULLS, ARR_SIZE, Int8TransTypeData::count, elog, ERROR, Int64GetDatumFast, PG_GETARG_ARRAYTYPE_P, PG_RETURN_DATUM, PG_RETURN_NULL, and Int8TransTypeData::sum.

◆ int4_accum()

Datum int4_accum ( PG_FUNCTION_ARGS  )

Definition at line 5691 of file numeric.c.

5692 {
5694 
5695  state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
5696 
5697  /* Create the state data on the first call */
5698  if (state == NULL)
5699  state = makePolyNumAggState(fcinfo, true);
5700 
5701  if (!PG_ARGISNULL(1))
5702  {
5703 #ifdef HAVE_INT128
5704  do_int128_accum(state, (int128) PG_GETARG_INT32(1));
5705 #else
5707 #endif
5708  }
5709 
5711 }
#define PG_GETARG_INT32(n)
Definition: fmgr.h:269

References do_numeric_accum(), int64_to_numeric(), makePolyNumAggState, PG_ARGISNULL, PG_GETARG_INT32, PG_GETARG_POINTER, and PG_RETURN_POINTER.

◆ int4_accum_inv()

Datum int4_accum_inv ( PG_FUNCTION_ARGS  )

Definition at line 6117 of file numeric.c.

6118 {
6120 
6121  state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
6122 
6123  /* Should not get here with no state */
6124  if (state == NULL)
6125  elog(ERROR, "int4_accum_inv called with NULL state");
6126 
6127  if (!PG_ARGISNULL(1))
6128  {
6129 #ifdef HAVE_INT128
6130  do_int128_discard(state, (int128) PG_GETARG_INT32(1));
6131 #else
6132  /* Should never fail, all inputs have dscale 0 */
6134  elog(ERROR, "do_numeric_discard failed unexpectedly");
6135 #endif
6136  }
6137 
6139 }

References do_numeric_discard(), elog, ERROR, int64_to_numeric(), PG_ARGISNULL, PG_GETARG_INT32, PG_GETARG_POINTER, and PG_RETURN_POINTER.

◆ int4_avg_accum()

Datum int4_avg_accum ( PG_FUNCTION_ARGS  )

Definition at line 6803 of file numeric.c.

6804 {
6805  ArrayType *transarray;
6807  Int8TransTypeData *transdata;
6808 
6809  /*
6810  * If we're invoked as an aggregate, we can cheat and modify our first
6811  * parameter in-place to reduce palloc overhead. Otherwise we need to make
6812  * a copy of it before scribbling on it.
6813  */
6814  if (AggCheckCallContext(fcinfo, NULL))
6815  transarray = PG_GETARG_ARRAYTYPE_P(0);
6816  else
6817  transarray = PG_GETARG_ARRAYTYPE_P_COPY(0);
6818 
6819  if (ARR_HASNULL(transarray) ||
6820  ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
6821  elog(ERROR, "expected 2-element int8 array");
6822 
6823  transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
6824  transdata->count++;
6825  transdata->sum += newval;
6826 
6827  PG_RETURN_ARRAYTYPE_P(transarray);
6828 }

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.

◆ int4_avg_accum_inv()

Datum int4_avg_accum_inv ( PG_FUNCTION_ARGS  )

Definition at line 6890 of file numeric.c.

6891 {
6892  ArrayType *transarray;
6894  Int8TransTypeData *transdata;
6895 
6896  /*
6897  * If we're invoked as an aggregate, we can cheat and modify our first
6898  * parameter in-place to reduce palloc overhead. Otherwise we need to make
6899  * a copy of it before scribbling on it.
6900  */
6901  if (AggCheckCallContext(fcinfo, NULL))
6902  transarray = PG_GETARG_ARRAYTYPE_P(0);
6903  else
6904  transarray = PG_GETARG_ARRAYTYPE_P_COPY(0);
6905 
6906  if (ARR_HASNULL(transarray) ||
6907  ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
6908  elog(ERROR, "expected 2-element int8 array");
6909 
6910  transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
6911  transdata->count--;
6912  transdata->sum -= newval;
6913 
6914  PG_RETURN_ARRAYTYPE_P(transarray);
6915 }

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.

◆ int4_avg_combine()

Datum int4_avg_combine ( PG_FUNCTION_ARGS  )

Definition at line 6831 of file numeric.c.

6832 {
6833  ArrayType *transarray1;
6834  ArrayType *transarray2;
6835  Int8TransTypeData *state1;
6836  Int8TransTypeData *state2;
6837 
6838  if (!AggCheckCallContext(fcinfo, NULL))
6839  elog(ERROR, "aggregate function called in non-aggregate context");
6840 
6841  transarray1 = PG_GETARG_ARRAYTYPE_P(0);
6842  transarray2 = PG_GETARG_ARRAYTYPE_P(1);
6843 
6844  if (ARR_HASNULL(transarray1) ||
6845  ARR_SIZE(transarray1) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
6846  elog(ERROR, "expected 2-element int8 array");
6847 
6848  if (ARR_HASNULL(transarray2) ||
6849  ARR_SIZE(transarray2) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
6850  elog(ERROR, "expected 2-element int8 array");
6851 
6852  state1 = (Int8TransTypeData *) ARR_DATA_PTR(transarray1);
6853  state2 = (Int8TransTypeData *) ARR_DATA_PTR(transarray2);
6854 
6855  state1->count += state2->count;
6856  state1->sum += state2->sum;
6857 
6858  PG_RETURN_ARRAYTYPE_P(transarray1);
6859 }

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.

◆ int4_numeric()

Datum int4_numeric ( PG_FUNCTION_ARGS  )

Definition at line 4507 of file numeric.c.

4508 {
4509  int32 val = PG_GETARG_INT32(0);
4510 
4512 }

References int64_to_numeric(), PG_GETARG_INT32, PG_RETURN_NUMERIC, and val.

Referenced by executeItemOptUnwrapTarget(), and JsonItemFromDatum().

◆ int4_sum()

Datum int4_sum ( PG_FUNCTION_ARGS  )

Definition at line 6675 of file numeric.c.

6676 {
6677  int64 newval;
6678 
6679  if (PG_ARGISNULL(0))
6680  {
6681  /* No non-null input seen so far... */
6682  if (PG_ARGISNULL(1))
6683  PG_RETURN_NULL(); /* still no non-null */
6684  /* This is the first non-null input. */
6685  newval = (int64) PG_GETARG_INT32(1);
6687  }
6688 
6689  /*
6690  * If we're invoked as an aggregate, we can cheat and modify our first
6691  * parameter in-place to avoid palloc overhead. If not, we need to return
6692  * the new value of the transition variable. (If int8 is pass-by-value,
6693  * then of course this is useless as well as incorrect, so just ifdef it
6694  * out.)
6695  */
6696 #ifndef USE_FLOAT8_BYVAL /* controls int8 too */
6697  if (AggCheckCallContext(fcinfo, NULL))
6698  {
6699  int64 *oldsum = (int64 *) PG_GETARG_POINTER(0);
6700 
6701  /* Leave the running sum unchanged in the new input is null */
6702  if (!PG_ARGISNULL(1))
6703  *oldsum = *oldsum + (int64) PG_GETARG_INT32(1);
6704 
6705  PG_RETURN_POINTER(oldsum);
6706  }
6707  else
6708 #endif
6709  {
6710  int64 oldsum = PG_GETARG_INT64(0);
6711 
6712  /* Leave sum unchanged if new input is null. */
6713  if (PG_ARGISNULL(1))
6714  PG_RETURN_INT64(oldsum);
6715 
6716  /* OK to do the addition. */
6717  newval = oldsum + (int64) PG_GETARG_INT32(1);
6718 
6720  }
6721 }

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

◆ int64_div_fast_to_numeric()

Numeric int64_div_fast_to_numeric ( int64  val1,
int  log10val2 
)

Definition at line 4422 of file numeric.c.

4423 {
4424  Numeric res;
4425  NumericVar result;
4426  int rscale;
4427  int w;
4428  int m;
4429 
4430  init_var(&result);
4431 
4432  /* result scale */
4433  rscale = log10val2 < 0 ? 0 : log10val2;
4434 
4435  /* how much to decrease the weight by */
4436  w = log10val2 / DEC_DIGITS;
4437  /* how much is left to divide by */
4438  m = log10val2 % DEC_DIGITS;
4439  if (m < 0)
4440  {
4441  m += DEC_DIGITS;
4442  w--;
4443  }
4444 
4445  /*
4446  * If there is anything left to divide by (10^m with 0 < m < DEC_DIGITS),
4447  * multiply the dividend by 10^(DEC_DIGITS - m), and shift the weight by
4448  * one more.
4449  */
4450  if (m > 0)
4451  {
4452 #if DEC_DIGITS == 4
4453  static const int pow10[] = {1, 10, 100, 1000};
4454 #elif DEC_DIGITS == 2
4455  static const int pow10[] = {1, 10};
4456 #elif DEC_DIGITS == 1
4457  static const int pow10[] = {1};
4458 #else
4459 #error unsupported NBASE
4460 #endif
4461  int64 factor = pow10[DEC_DIGITS - m];
4462  int64 new_val1;
4463 
4464  StaticAssertDecl(lengthof(pow10) == DEC_DIGITS, "mismatch with DEC_DIGITS");
4465 
4466  if (unlikely(pg_mul_s64_overflow(val1, factor, &new_val1)))
4467  {
4468 #ifdef HAVE_INT128
4469  /* do the multiplication using 128-bit integers */
4470  int128 tmp;
4471 
4472  tmp = (int128) val1 * (int128) factor;
4473 
4474  int128_to_numericvar(tmp, &result);
4475 #else
4476  /* do the multiplication using numerics */
4477  NumericVar tmp;
4478 
4479  init_var(&tmp);
4480 
4481  int64_to_numericvar(val1, &result);
4482  int64_to_numericvar(factor, &tmp);
4483  mul_var(&result, &tmp, &result, 0);
4484 
4485  free_var(&tmp);
4486 #endif
4487  }
4488  else
4489  int64_to_numericvar(new_val1, &result);
4490 
4491  w++;
4492  }
4493  else
4494  int64_to_numericvar(val1, &result);
4495 
4496  result.weight -= w;
4497  result.dscale = rscale;
4498 
4499  res = make_result(&result);
4500 
4501  free_var(&result);
4502 
4503  return res;
4504 }
static void int64_to_numericvar(int64 val, NumericVar *var)
Definition: numeric.c:8222
#define unlikely(x)
Definition: c.h:326
#define lengthof(array)
Definition: c.h:767
#define StaticAssertDecl(condition, errmessage)
Definition: c.h:915
static bool pg_mul_s64_overflow(int64 a, int64 b, int64 *result)
Definition: int.h:261

References DEC_DIGITS, NumericVar::dscale, free_var(), init_var, int64_to_numericvar(), lengthof, make_result(), mul_var(), pg_mul_s64_overflow(), res, StaticAssertDecl, unlikely, and NumericVar::weight.

Referenced by interval_part_common(), time_part_common(), timestamp_part_common(), timestamptz_part_common(), and timetz_part_common().

◆ int64_to_numeric()

◆ int64_to_numericvar()

static void int64_to_numericvar ( int64  val,
NumericVar var 
)
static

Definition at line 8222 of file numeric.c.

8223 {
8224  uint64 uval,
8225  newuval;
8226  NumericDigit *ptr;
8227  int ndigits;
8228 
8229  /* int64 can require at most 19 decimal digits; add one for safety */
8230  alloc_var(var, 20 / DEC_DIGITS);
8231  if (val < 0)
8232  {
8233  var->sign = NUMERIC_NEG;
8234  uval = pg_abs_s64(val);
8235  }
8236  else
8237  {
8238  var->sign = NUMERIC_POS;
8239  uval = val;
8240  }
8241  var->dscale = 0;
8242  if (val == 0)
8243  {
8244  var->ndigits = 0;
8245  var->weight = 0;
8246  return;
8247  }
8248  ptr = var->digits + var->ndigits;
8249  ndigits = 0;
8250  do
8251  {
8252  ptr--;
8253  ndigits++;
8254  newuval = uval / NBASE;
8255  *ptr = uval - newuval * NBASE;
8256  uval = newuval;
8257  } while (uval);
8258  var->digits = ptr;
8259  var->ndigits = ndigits;
8260  var->weight = ndigits - 1;
8261 }
static uint64 pg_abs_s64(int64 a)
Definition: int.h:304

References alloc_var(), DEC_DIGITS, NumericVar::digits, NumericVar::dscale, NBASE, NumericVar::ndigits, NUMERIC_NEG, NUMERIC_POS, pg_abs_s64(), NumericVar::sign, val, and NumericVar::weight.

Referenced by int64_div_fast_to_numeric(), int64_to_numeric(), numeric_fac(), numeric_stddev_internal(), set_var_from_non_decimal_integer_str(), sqrt_var(), and width_bucket_numeric().

◆ int8_accum()

Datum int8_accum ( PG_FUNCTION_ARGS  )

Definition at line 5714 of file numeric.c.

5715 {
5717 
5718  state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
5719 
5720  /* Create the state data on the first call */
5721  if (state == NULL)
5722  state = makeNumericAggState(fcinfo, true);
5723 
5724  if (!PG_ARGISNULL(1))
5726 
5728 }
static NumericAggState * makeNumericAggState(FunctionCallInfo fcinfo, bool calcSumX2)
Definition: numeric.c:4935

References do_numeric_accum(), int64_to_numeric(), makeNumericAggState(), PG_ARGISNULL, PG_GETARG_INT64, PG_GETARG_POINTER, and PG_RETURN_POINTER.

◆ int8_accum_inv()

Datum int8_accum_inv ( PG_FUNCTION_ARGS  )

Definition at line 6142 of file numeric.c.

6143 {
6145 
6146  state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
6147 
6148  /* Should not get here with no state */
6149  if (state == NULL)
6150  elog(ERROR, "int8_accum_inv called with NULL state");
6151 
6152  if (!PG_ARGISNULL(1))
6153  {
6154  /* Should never fail, all inputs have dscale 0 */
6156  elog(ERROR, "do_numeric_discard failed unexpectedly");
6157  }
6158 
6160 }

References do_numeric_discard(), elog, ERROR, int64_to_numeric(), PG_ARGISNULL, PG_GETARG_INT64, PG_GETARG_POINTER, and PG_RETURN_POINTER.

◆ int8_avg()

Datum int8_avg ( PG_FUNCTION_ARGS  )

Definition at line 6918 of file numeric.c.

6919 {
6920  ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
6921  Int8TransTypeData *transdata;
6922  Datum countd,
6923  sumd;
6924 
6925  if (ARR_HASNULL(transarray) ||
6926  ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
6927  elog(ERROR, "expected 2-element int8 array");
6928  transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
6929 
6930  /* SQL defines AVG of no values to be NULL */
6931  if (transdata->count == 0)
6932  PG_RETURN_NULL();
6933 
6934  countd = NumericGetDatum(int64_to_numeric(transdata->count));
6935  sumd = NumericGetDatum(int64_to_numeric(transdata->sum));
6936 
6938 }
Datum numeric_div(PG_FUNCTION_ARGS)
Definition: numeric.c:3242
#define DirectFunctionCall2(func, arg1, arg2)
Definition: fmgr.h:643

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

◆ int8_avg_accum()

Datum int8_avg_accum ( PG_FUNCTION_ARGS  )

Definition at line 5910 of file numeric.c.

5911 {
5913 
5914  state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
5915 
5916  /* Create the state data on the first call */
5917  if (state == NULL)
5918  state = makePolyNumAggState(fcinfo, false);
5919 
5920  if (!PG_ARGISNULL(1))
5921  {
5922 #ifdef HAVE_INT128
5923  do_int128_accum(state, (int128) PG_GETARG_INT64(1));
5924 #else
5926 #endif
5927  }
5928 
5930 }

References do_numeric_accum(), int64_to_numeric(), makePolyNumAggState, PG_ARGISNULL, PG_GETARG_INT64, PG_GETARG_POINTER, and PG_RETURN_POINTER.

◆ int8_avg_accum_inv()

Datum int8_avg_accum_inv ( PG_FUNCTION_ARGS  )

Definition at line 6163 of file numeric.c.

6164 {
6166 
6167  state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
6168 
6169  /* Should not get here with no state */
6170  if (state == NULL)
6171  elog(ERROR, "int8_avg_accum_inv called with NULL state");
6172 
6173  if (!PG_ARGISNULL(1))
6174  {
6175 #ifdef HAVE_INT128
6176  do_int128_discard(state, (int128) PG_GETARG_INT64(1));
6177 #else
6178  /* Should never fail, all inputs have dscale 0 */
6180  elog(ERROR, "do_numeric_discard failed unexpectedly");
6181 #endif
6182  }
6183 
6185 }

References do_numeric_discard(), elog, ERROR, int64_to_numeric(), PG_ARGISNULL, PG_GETARG_INT64, PG_GETARG_POINTER, and PG_RETURN_POINTER.

◆ int8_avg_combine()

Datum int8_avg_combine ( PG_FUNCTION_ARGS  )

Definition at line 5937 of file numeric.c.

5938 {
5939  PolyNumAggState *state1;
5940  PolyNumAggState *state2;
5941  MemoryContext agg_context;
5942  MemoryContext old_context;
5943 
5944  if (!AggCheckCallContext(fcinfo, &agg_context))
5945  elog(ERROR, "aggregate function called in non-aggregate context");
5946 
5947  state1 = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
5948  state2 = PG_ARGISNULL(1) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(1);
5949 
5950  if (state2 == NULL)
5951  PG_RETURN_POINTER(state1);
5952 
5953  /* manually copy all fields from state2 to state1 */
5954  if (state1 == NULL)
5955  {
5956  old_context = MemoryContextSwitchTo(agg_context);
5957 
5958  state1 = makePolyNumAggState(fcinfo, false);
5959  state1->N = state2->N;
5960