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 "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 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
 

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)
 
static void div_var_fast (const NumericVar *var1, const NumericVar *var2, NumericVar *result, int rscale, bool round)
 
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 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 410 of file numeric.c.

◆ DEC_DIGITS

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

Definition at line 97 of file numeric.c.

◆ digitbuf_alloc

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

Definition at line 483 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:73

Definition at line 485 of file numeric.c.

◆ DIV_GUARD_DIGITS

#define DIV_GUARD_DIGITS   4

Definition at line 99 of file numeric.c.

◆ dump_numeric

#define dump_numeric (   s,
 
)

Definition at line 479 of file numeric.c.

◆ dump_var

#define dump_var (   s,
 
)

Definition at line 480 of file numeric.c.

◆ HALF_NBASE

#define HALF_NBASE   5000

Definition at line 96 of file numeric.c.

◆ init_var

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

Definition at line 491 of file numeric.c.

◆ makePolyNumAggState

#define makePolyNumAggState   makeNumericAggState

Definition at line 5549 of file numeric.c.

◆ makePolyNumAggStateCurrentContext

#define makePolyNumAggStateCurrentContext   makeNumericAggStateCurrentContext

Definition at line 5550 of file numeric.c.

◆ MUL_GUARD_DIGITS

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

Definition at line 98 of file numeric.c.

◆ NA_TOTAL_COUNT

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

Definition at line 4813 of file numeric.c.

◆ NBASE

#define NBASE   10000

Definition at line 95 of file numeric.c.

◆ NUMERIC_ABBREV_BITS

#define NUMERIC_ABBREV_BITS   (SIZEOF_DATUM * BITS_PER_BYTE)

Definition at line 401 of file numeric.c.

◆ NUMERIC_ABBREV_NAN

#define NUMERIC_ABBREV_NAN   NumericAbbrevGetDatum(PG_INT32_MIN)

Definition at line 411 of file numeric.c.

◆ NUMERIC_ABBREV_NINF

#define NUMERIC_ABBREV_NINF   NumericAbbrevGetDatum(PG_INT32_MAX)

Definition at line 413 of file numeric.c.

◆ NUMERIC_ABBREV_PINF

#define NUMERIC_ABBREV_PINF   NumericAbbrevGetDatum(-PG_INT32_MAX)

Definition at line 412 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:216
#define NUMERIC_SHORT_WEIGHT_MIN
Definition: numeric.c:221
#define NUMERIC_SHORT_WEIGHT_MAX
Definition: numeric.c:220
static int scale
Definition: pgbench.c:181

Definition at line 497 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:182

Definition at line 493 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:233
#define NUMERIC_SHORT_DSCALE_MASK
Definition: numeric.c:214
#define NUMERIC_SHORT_DSCALE_SHIFT
Definition: numeric.c:215

Definition at line 242 of file numeric.c.

◆ NUMERIC_DSCALE_MASK

#define NUMERIC_DSCALE_MASK   0x3FFF

Definition at line 233 of file numeric.c.

◆ NUMERIC_DSCALE_MAX

#define NUMERIC_DSCALE_MAX   NUMERIC_DSCALE_MASK

Definition at line 234 of file numeric.c.

◆ NUMERIC_EXT_FLAGBITS

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

Definition at line 202 of file numeric.c.

◆ NUMERIC_EXT_SIGN_MASK

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

Definition at line 196 of file numeric.c.

◆ NUMERIC_FLAGBITS

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

Definition at line 170 of file numeric.c.

◆ NUMERIC_HDRSZ

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

Definition at line 174 of file numeric.c.

◆ NUMERIC_HDRSZ_SHORT

#define NUMERIC_HDRSZ_SHORT   (VARHDRSZ + sizeof(uint16))

Definition at line 175 of file numeric.c.

◆ NUMERIC_HEADER_IS_SHORT

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

Definition at line 182 of file numeric.c.

◆ NUMERIC_HEADER_SIZE

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

Definition at line 183 of file numeric.c.

◆ NUMERIC_INF_SIGN_MASK

#define NUMERIC_INF_SIGN_MASK   0x2000

Definition at line 200 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 206 of file numeric.c.

◆ NUMERIC_IS_NAN

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

Definition at line 203 of file numeric.c.

◆ NUMERIC_IS_NINF

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

Definition at line 205 of file numeric.c.

◆ NUMERIC_IS_PINF

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

Definition at line 204 of file numeric.c.

◆ NUMERIC_IS_SHORT

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

Definition at line 171 of file numeric.c.

◆ NUMERIC_IS_SPECIAL

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

Definition at line 172 of file numeric.c.

◆ NUMERIC_NAN

#define NUMERIC_NAN   0xC000

Definition at line 197 of file numeric.c.

◆ NUMERIC_NDIGITS

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

Definition at line 495 of file numeric.c.

◆ NUMERIC_NEG

#define NUMERIC_NEG   0x4000

Definition at line 166 of file numeric.c.

◆ NUMERIC_NINF

#define NUMERIC_NINF   0xF000

Definition at line 199 of file numeric.c.

◆ NUMERIC_PINF

#define NUMERIC_PINF   0xD000

Definition at line 198 of file numeric.c.

◆ NUMERIC_POS

#define NUMERIC_POS   0x0000

Definition at line 165 of file numeric.c.

◆ NUMERIC_SHORT

#define NUMERIC_SHORT   0x8000

Definition at line 167 of file numeric.c.

◆ NUMERIC_SHORT_DSCALE_MASK

#define NUMERIC_SHORT_DSCALE_MASK   0x1F80

Definition at line 214 of file numeric.c.

◆ NUMERIC_SHORT_DSCALE_MAX

#define NUMERIC_SHORT_DSCALE_MAX    (NUMERIC_SHORT_DSCALE_MASK >> NUMERIC_SHORT_DSCALE_SHIFT)

Definition at line 216 of file numeric.c.

◆ NUMERIC_SHORT_DSCALE_SHIFT

#define NUMERIC_SHORT_DSCALE_SHIFT   7

Definition at line 215 of file numeric.c.

◆ NUMERIC_SHORT_SIGN_MASK

#define NUMERIC_SHORT_SIGN_MASK   0x2000

Definition at line 213 of file numeric.c.

◆ NUMERIC_SHORT_WEIGHT_MASK

#define NUMERIC_SHORT_WEIGHT_MASK   0x003F

Definition at line 219 of file numeric.c.

◆ NUMERIC_SHORT_WEIGHT_MAX

#define NUMERIC_SHORT_WEIGHT_MAX   NUMERIC_SHORT_WEIGHT_MASK

Definition at line 220 of file numeric.c.

◆ NUMERIC_SHORT_WEIGHT_MIN

#define NUMERIC_SHORT_WEIGHT_MIN   (-(NUMERIC_SHORT_WEIGHT_MASK+1))

Definition at line 221 of file numeric.c.

◆ NUMERIC_SHORT_WEIGHT_SIGN_MASK

#define NUMERIC_SHORT_WEIGHT_SIGN_MASK   0x0040

Definition at line 218 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:172
#define NUMERIC_FLAGBITS(n)
Definition: numeric.c:170
#define NUMERIC_SHORT_SIGN_MASK
Definition: numeric.c:213
#define NUMERIC_IS_SHORT(n)
Definition: numeric.c:171
#define NUMERIC_POS
Definition: numeric.c:165

Definition at line 236 of file numeric.c.

◆ NUMERIC_SIGN_MASK

#define NUMERIC_SIGN_MASK   0xC000

Definition at line 164 of file numeric.c.

◆ NUMERIC_SPECIAL

#define NUMERIC_SPECIAL   0xC000

Definition at line 168 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:219
#define NUMERIC_SHORT_WEIGHT_SIGN_MASK
Definition: numeric.c:218

Definition at line 246 of file numeric.c.

◆ NUMERIC_WEIGHT_MAX

#define NUMERIC_WEIGHT_MAX   PG_INT16_MAX

Definition at line 257 of file numeric.c.

◆ NumericAbbrevGetDatum

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

Definition at line 409 of file numeric.c.

Typedef Documentation

◆ Int8TransTypeData

◆ NumericAggState

◆ NumericDigit

Definition at line 101 of file numeric.c.

◆ NumericSumAccum

◆ NumericVar

typedef struct NumericVar NumericVar

◆ PolyNumAggState

Definition at line 5548 of file numeric.c.

Function Documentation

◆ accum_sum_add()

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

Definition at line 12196 of file numeric.c.

12197 {
12198  int32 *accum_digits;
12199  int i,
12200  val_i;
12201  int val_ndigits;
12202  NumericDigit *val_digits;
12203 
12204  /*
12205  * If we have accumulated too many values since the last carry
12206  * propagation, do it now, to avoid overflowing. (We could allow more
12207  * than NBASE - 1, if we reserved two extra digits, rather than one, for
12208  * carry propagation. But even with NBASE - 1, this needs to be done so
12209  * seldom, that the performance difference is negligible.)
12210  */
12211  if (accum->num_uncarried == NBASE - 1)
12212  accum_sum_carry(accum);
12213 
12214  /*
12215  * Adjust the weight or scale of the old value, so that it can accommodate
12216  * the new value.
12217  */
12218  accum_sum_rescale(accum, val);
12219 
12220  /* */
12221  if (val->sign == NUMERIC_POS)
12222  accum_digits = accum->pos_digits;
12223  else
12224  accum_digits = accum->neg_digits;
12225 
12226  /* copy these values into local vars for speed in loop */
12227  val_ndigits = val->ndigits;
12228  val_digits = val->digits;
12229 
12230  i = accum->weight - val->weight;
12231  for (val_i = 0; val_i < val_ndigits; val_i++)
12232  {
12233  accum_digits[i] += (int32) val_digits[val_i];
12234  i++;
12235  }
12236 
12237  accum->num_uncarried++;
12238 }
static void accum_sum_carry(NumericSumAccum *accum)
Definition: numeric.c:12244
int16 NumericDigit
Definition: numeric.c:101
#define NBASE
Definition: numeric.c:95
static void accum_sum_rescale(NumericSumAccum *accum, const NumericVar *val)
Definition: numeric.c:12317
signed int int32
Definition: c.h:494
long val
Definition: informix.c:670
int i
Definition: isn.c:73
int32 * pos_digits
Definition: numeric.c:384
int num_uncarried
Definition: numeric.c:382
int32 * neg_digits
Definition: numeric.c:385

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

12245 {
12246  int i;
12247  int ndigits;
12248  int32 *dig;
12249  int32 carry;
12250  int32 newdig = 0;
12251 
12252  /*
12253  * If no new values have been added since last carry propagation, nothing
12254  * to do.
12255  */
12256  if (accum->num_uncarried == 0)
12257  return;
12258 
12259  /*
12260  * We maintain that the weight of the accumulator is always one larger
12261  * than needed to hold the current value, before carrying, to make sure
12262  * there is enough space for the possible extra digit when carry is
12263  * propagated. We cannot expand the buffer here, unless we require
12264  * callers of accum_sum_final() to switch to the right memory context.
12265  */
12266  Assert(accum->pos_digits[0] == 0 && accum->neg_digits[0] == 0);
12267 
12268  ndigits = accum->ndigits;
12269 
12270  /* Propagate carry in the positive sum */
12271  dig = accum->pos_digits;
12272  carry = 0;
12273  for (i = ndigits - 1; i >= 0; i--)
12274  {
12275  newdig = dig[i] + carry;
12276  if (newdig >= NBASE)
12277  {
12278  carry = newdig / NBASE;
12279  newdig -= carry * NBASE;
12280  }
12281  else
12282  carry = 0;
12283  dig[i] = newdig;
12284  }
12285  /* Did we use up the digit reserved for carry propagation? */
12286  if (newdig > 0)
12287  accum->have_carry_space = false;
12288 
12289  /* And the same for the negative sum */
12290  dig = accum->neg_digits;
12291  carry = 0;
12292  for (i = ndigits - 1; i >= 0; i--)
12293  {
12294  newdig = dig[i] + carry;
12295  if (newdig >= NBASE)
12296  {
12297  carry = newdig / NBASE;
12298  newdig -= carry * NBASE;
12299  }
12300  else
12301  carry = 0;
12302  dig[i] = newdig;
12303  }
12304  if (newdig > 0)
12305  accum->have_carry_space = false;
12306 
12307  accum->num_uncarried = 0;
12308 }
#define Assert(condition)
Definition: c.h:858
bool have_carry_space
Definition: numeric.c:383

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

12475 {
12476  NumericVar tmp_var;
12477 
12478  init_var(&tmp_var);
12479 
12480  accum_sum_final(accum2, &tmp_var);
12481  accum_sum_add(accum, &tmp_var);
12482 
12483  free_var(&tmp_var);
12484 }
static void accum_sum_final(NumericSumAccum *accum, NumericVar *result)
Definition: numeric.c:12406
static void free_var(NumericVar *var)
Definition: numeric.c:6973
static void accum_sum_add(NumericSumAccum *accum, const NumericVar *val)
Definition: numeric.c:12196
#define init_var(v)
Definition: numeric.c:491

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

12458 {
12459  dst->pos_digits = palloc(src->ndigits * sizeof(int32));
12460  dst->neg_digits = palloc(src->ndigits * sizeof(int32));
12461 
12462  memcpy(dst->pos_digits, src->pos_digits, src->ndigits * sizeof(int32));
12463  memcpy(dst->neg_digits, src->neg_digits, src->ndigits * sizeof(int32));
12464  dst->num_uncarried = src->num_uncarried;
12465  dst->ndigits = src->ndigits;
12466  dst->weight = src->weight;
12467  dst->dscale = src->dscale;
12468 }
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 12406 of file numeric.c.

12407 {
12408  int i;
12409  NumericVar pos_var;
12410  NumericVar neg_var;
12411 
12412  if (accum->ndigits == 0)
12413  {
12414  set_var_from_var(&const_zero, result);
12415  return;
12416  }
12417 
12418  /* Perform final carry */
12419  accum_sum_carry(accum);
12420 
12421  /* Create NumericVars representing the positive and negative sums */
12422  init_var(&pos_var);
12423  init_var(&neg_var);
12424 
12425  pos_var.ndigits = neg_var.ndigits = accum->ndigits;
12426  pos_var.weight = neg_var.weight = accum->weight;
12427  pos_var.dscale = neg_var.dscale = accum->dscale;
12428  pos_var.sign = NUMERIC_POS;
12429  neg_var.sign = NUMERIC_NEG;
12430 
12431  pos_var.buf = pos_var.digits = digitbuf_alloc(accum->ndigits);
12432  neg_var.buf = neg_var.digits = digitbuf_alloc(accum->ndigits);
12433 
12434  for (i = 0; i < accum->ndigits; i++)
12435  {
12436  Assert(accum->pos_digits[i] < NBASE);
12437  pos_var.digits[i] = (int16) accum->pos_digits[i];
12438 
12439  Assert(accum->neg_digits[i] < NBASE);
12440  neg_var.digits[i] = (int16) accum->neg_digits[i];
12441  }
12442 
12443  /* And add them together */
12444  add_var(&pos_var, &neg_var, result);
12445 
12446  /* Remove leading/trailing zeroes */
12447  strip_var(result);
12448 }
static void add_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition: numeric.c:8435
#define NUMERIC_NEG
Definition: numeric.c:166
#define digitbuf_alloc(ndigits)
Definition: numeric.c:483
static const NumericVar const_zero
Definition: numeric.c:422
static void set_var_from_var(const NumericVar *value, NumericVar *dest)
Definition: numeric.c:7472
static void strip_var(NumericVar *var)
Definition: numeric.c:12139
int ndigits
Definition: numeric.c:312
NumericDigit * digits
Definition: numeric.c:317
int dscale
Definition: numeric.c:315
int sign
Definition: numeric.c:314
NumericDigit * buf
Definition: numeric.c:316
int weight
Definition: numeric.c:313

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

12318 {
12319  int old_weight = accum->weight;
12320  int old_ndigits = accum->ndigits;
12321  int accum_ndigits;
12322  int accum_weight;
12323  int accum_rscale;
12324  int val_rscale;
12325 
12326  accum_weight = old_weight;
12327  accum_ndigits = old_ndigits;
12328 
12329  /*
12330  * Does the new value have a larger weight? If so, enlarge the buffers,
12331  * and shift the existing value to the new weight, by adding leading
12332  * zeros.
12333  *
12334  * We enforce that the accumulator always has a weight one larger than
12335  * needed for the inputs, so that we have space for an extra digit at the
12336  * final carry-propagation phase, if necessary.
12337  */
12338  if (val->weight >= accum_weight)
12339  {
12340  accum_weight = val->weight + 1;
12341  accum_ndigits = accum_ndigits + (accum_weight - old_weight);
12342  }
12343 
12344  /*
12345  * Even though the new value is small, we might've used up the space
12346  * reserved for the carry digit in the last call to accum_sum_carry(). If
12347  * so, enlarge to make room for another one.
12348  */
12349  else if (!accum->have_carry_space)
12350  {
12351  accum_weight++;
12352  accum_ndigits++;
12353  }
12354 
12355  /* Is the new value wider on the right side? */
12356  accum_rscale = accum_ndigits - accum_weight - 1;
12357  val_rscale = val->ndigits - val->weight - 1;
12358  if (val_rscale > accum_rscale)
12359  accum_ndigits = accum_ndigits + (val_rscale - accum_rscale);
12360 
12361  if (accum_ndigits != old_ndigits ||
12362  accum_weight != old_weight)
12363  {
12364  int32 *new_pos_digits;
12365  int32 *new_neg_digits;
12366  int weightdiff;
12367 
12368  weightdiff = accum_weight - old_weight;
12369 
12370  new_pos_digits = palloc0(accum_ndigits * sizeof(int32));
12371  new_neg_digits = palloc0(accum_ndigits * sizeof(int32));
12372 
12373  if (accum->pos_digits)
12374  {
12375  memcpy(&new_pos_digits[weightdiff], accum->pos_digits,
12376  old_ndigits * sizeof(int32));
12377  pfree(accum->pos_digits);
12378 
12379  memcpy(&new_neg_digits[weightdiff], accum->neg_digits,
12380  old_ndigits * sizeof(int32));
12381  pfree(accum->neg_digits);
12382  }
12383 
12384  accum->pos_digits = new_pos_digits;
12385  accum->neg_digits = new_neg_digits;
12386 
12387  accum->weight = accum_weight;
12388  accum->ndigits = accum_ndigits;
12389 
12390  Assert(accum->pos_digits[0] == 0 && accum->neg_digits[0] == 0);
12391  accum->have_carry_space = true;
12392  }
12393 
12394  if (val->dscale > accum->dscale)
12395  accum->dscale = val->dscale;
12396 }
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 12180 of file numeric.c.

12181 {
12182  int i;
12183 
12184  accum->dscale = 0;
12185  for (i = 0; i < accum->ndigits; i++)
12186  {
12187  accum->pos_digits[i] = 0;
12188  accum->neg_digits[i] = 0;
12189  }
12190 }

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

11805 {
11806  NumericDigit *res_buf;
11807  NumericDigit *res_digits;
11808  int res_ndigits;
11809  int res_weight;
11810  int res_rscale,
11811  rscale1,
11812  rscale2;
11813  int res_dscale;
11814  int i,
11815  i1,
11816  i2;
11817  int carry = 0;
11818 
11819  /* copy these values into local vars for speed in inner loop */
11820  int var1ndigits = var1->ndigits;
11821  int var2ndigits = var2->ndigits;
11822  NumericDigit *var1digits = var1->digits;
11823  NumericDigit *var2digits = var2->digits;
11824 
11825  res_weight = Max(var1->weight, var2->weight) + 1;
11826 
11827  res_dscale = Max(var1->dscale, var2->dscale);
11828 
11829  /* Note: here we are figuring rscale in base-NBASE digits */
11830  rscale1 = var1->ndigits - var1->weight - 1;
11831  rscale2 = var2->ndigits - var2->weight - 1;
11832  res_rscale = Max(rscale1, rscale2);
11833 
11834  res_ndigits = res_rscale + res_weight + 1;
11835  if (res_ndigits <= 0)
11836  res_ndigits = 1;
11837 
11838  res_buf = digitbuf_alloc(res_ndigits + 1);
11839  res_buf[0] = 0; /* spare digit for later rounding */
11840  res_digits = res_buf + 1;
11841 
11842  i1 = res_rscale + var1->weight + 1;
11843  i2 = res_rscale + var2->weight + 1;
11844  for (i = res_ndigits - 1; i >= 0; i--)
11845  {
11846  i1--;
11847  i2--;
11848  if (i1 >= 0 && i1 < var1ndigits)
11849  carry += var1digits[i1];
11850  if (i2 >= 0 && i2 < var2ndigits)
11851  carry += var2digits[i2];
11852 
11853  if (carry >= NBASE)
11854  {
11855  res_digits[i] = carry - NBASE;
11856  carry = 1;
11857  }
11858  else
11859  {
11860  res_digits[i] = carry;
11861  carry = 0;
11862  }
11863  }
11864 
11865  Assert(carry == 0); /* else we failed to allow for carry out */
11866 
11867  digitbuf_free(result->buf);
11868  result->ndigits = res_ndigits;
11869  result->buf = res_buf;
11870  result->digits = res_digits;
11871  result->weight = res_weight;
11872  result->dscale = res_dscale;
11873 
11874  /* Remove leading/trailing zeroes */
11875  strip_var(result);
11876 }
#define digitbuf_free(buf)
Definition: numeric.c:485
#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 8435 of file numeric.c.

8436 {
8437  /*
8438  * Decide on the signs of the two variables what to do
8439  */
8440  if (var1->sign == NUMERIC_POS)
8441  {
8442  if (var2->sign == NUMERIC_POS)
8443  {
8444  /*
8445  * Both are positive result = +(ABS(var1) + ABS(var2))
8446  */
8447  add_abs(var1, var2, result);
8448  result->sign = NUMERIC_POS;
8449  }
8450  else
8451  {
8452  /*
8453  * var1 is positive, var2 is negative Must compare absolute values
8454  */
8455  switch (cmp_abs(var1, var2))
8456  {
8457  case 0:
8458  /* ----------
8459  * ABS(var1) == ABS(var2)
8460  * result = ZERO
8461  * ----------
8462  */
8463  zero_var(result);
8464  result->dscale = Max(var1->dscale, var2->dscale);
8465  break;
8466 
8467  case 1:
8468  /* ----------
8469  * ABS(var1) > ABS(var2)
8470  * result = +(ABS(var1) - ABS(var2))
8471  * ----------
8472  */
8473  sub_abs(var1, var2, result);
8474  result->sign = NUMERIC_POS;
8475  break;
8476 
8477  case -1:
8478  /* ----------
8479  * ABS(var1) < ABS(var2)
8480  * result = -(ABS(var2) - ABS(var1))
8481  * ----------
8482  */
8483  sub_abs(var2, var1, result);
8484  result->sign = NUMERIC_NEG;
8485  break;
8486  }
8487  }
8488  }
8489  else
8490  {
8491  if (var2->sign == NUMERIC_POS)
8492  {
8493  /* ----------
8494  * var1 is negative, var2 is positive
8495  * Must compare absolute values
8496  * ----------
8497  */
8498  switch (cmp_abs(var1, var2))
8499  {
8500  case 0:
8501  /* ----------
8502  * ABS(var1) == ABS(var2)
8503  * result = ZERO
8504  * ----------
8505  */
8506  zero_var(result);
8507  result->dscale = Max(var1->dscale, var2->dscale);
8508  break;
8509 
8510  case 1:
8511  /* ----------
8512  * ABS(var1) > ABS(var2)
8513  * result = -(ABS(var1) - ABS(var2))
8514  * ----------
8515  */
8516  sub_abs(var1, var2, result);
8517  result->sign = NUMERIC_NEG;
8518  break;
8519 
8520  case -1:
8521  /* ----------
8522  * ABS(var1) < ABS(var2)
8523  * result = +(ABS(var2) - ABS(var1))
8524  * ----------
8525  */
8526  sub_abs(var2, var1, result);
8527  result->sign = NUMERIC_POS;
8528  break;
8529  }
8530  }
8531  else
8532  {
8533  /* ----------
8534  * Both are negative
8535  * result = -(ABS(var1) + ABS(var2))
8536  * ----------
8537  */
8538  add_abs(var1, var2, result);
8539  result->sign = NUMERIC_NEG;
8540  }
8541  }
8542 }
static void sub_abs(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition: numeric.c:11889
static void add_abs(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition: numeric.c:11804
static void zero_var(NumericVar *var)
Definition: numeric.c:6989
static int cmp_abs(const NumericVar *var1, const NumericVar *var2)
Definition: numeric.c:11726

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

6958 {
6959  digitbuf_free(var->buf);
6960  var->buf = digitbuf_alloc(ndigits + 1);
6961  var->buf[0] = 0; /* spare digit for rounding */
6962  var->digits = var->buf + 1;
6963  var->ndigits = ndigits;
6964 }

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

Referenced by div_var(), div_var_fast(), int64_to_numericvar(), mul_var(), numeric_recv(), 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 7911 of file numeric.c.

7912 {
7913  int precision;
7914  int scale;
7915  int maxdigits;
7916  int ddigits;
7917  int i;
7918 
7919  /* Do nothing if we have an invalid typmod */
7920  if (!is_valid_numeric_typmod(typmod))
7921  return true;
7922 
7923  precision = numeric_typmod_precision(typmod);
7924  scale = numeric_typmod_scale(typmod);
7925  maxdigits = precision - scale;
7926 
7927  /* Round to target scale (and set var->dscale) */
7928  round_var(var, scale);
7929 
7930  /* but don't allow var->dscale to be negative */
7931  if (var->dscale < 0)
7932  var->dscale = 0;
7933 
7934  /*
7935  * Check for overflow - note we can't do this before rounding, because
7936  * rounding could raise the weight. Also note that the var's weight could
7937  * be inflated by leading zeroes, which will be stripped before storage
7938  * but perhaps might not have been yet. In any case, we must recognize a
7939  * true zero, whose weight doesn't mean anything.
7940  */
7941  ddigits = (var->weight + 1) * DEC_DIGITS;
7942  if (ddigits > maxdigits)
7943  {
7944  /* Determine true weight; and check for all-zero result */
7945  for (i = 0; i < var->ndigits; i++)
7946  {
7947  NumericDigit dig = var->digits[i];
7948 
7949  if (dig)
7950  {
7951  /* Adjust for any high-order decimal zero digits */
7952 #if DEC_DIGITS == 4
7953  if (dig < 10)
7954  ddigits -= 3;
7955  else if (dig < 100)
7956  ddigits -= 2;
7957  else if (dig < 1000)
7958  ddigits -= 1;
7959 #elif DEC_DIGITS == 2
7960  if (dig < 10)
7961  ddigits -= 1;
7962 #elif DEC_DIGITS == 1
7963  /* no adjustment */
7964 #else
7965 #error unsupported NBASE
7966 #endif
7967  if (ddigits > maxdigits)
7968  ereturn(escontext, false,
7969  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
7970  errmsg("numeric field overflow"),
7971  errdetail("A field with precision %d, scale %d must round to an absolute value less than %s%d.",
7972  precision, scale,
7973  /* Display 10^0 as 1 */
7974  maxdigits ? "10^" : "",
7975  maxdigits ? maxdigits : 1
7976  )));
7977  break;
7978  }
7979  ddigits -= DEC_DIGITS;
7980  }
7981  }
7982 
7983  return true;
7984 }
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:11971
#define DEC_DIGITS
Definition: numeric.c:97
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:276
int maxdigits
Definition: informix.c:671

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

7997 {
7998  int precision;
7999  int scale;
8000 
8001  Assert(NUMERIC_IS_SPECIAL(num)); /* caller error if not */
8002 
8003  /*
8004  * NaN is allowed regardless of the typmod; that's rather dubious perhaps,
8005  * but it's a longstanding behavior. Inf is rejected if we have any
8006  * typmod restriction, since an infinity shouldn't be claimed to fit in
8007  * any finite number of digits.
8008  */
8009  if (NUMERIC_IS_NAN(num))
8010  return true;
8011 
8012  /* Do nothing if we have a default typmod (-1) */
8013  if (!is_valid_numeric_typmod(typmod))
8014  return true;
8015 
8016  precision = numeric_typmod_precision(typmod);
8017  scale = numeric_typmod_scale(typmod);
8018 
8019  ereturn(escontext, false,
8020  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
8021  errmsg("numeric field overflow"),
8022  errdetail("A field with precision %d, scale %d cannot hold an infinite value.",
8023  precision, scale)));
8024 }
#define NUMERIC_IS_NAN(n)
Definition: numeric.c:203

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

10166 {
10167  NumericVar tmp;
10168 
10169  init_var(&tmp);
10170  set_var_from_var(var, &tmp);
10171 
10172  trunc_var(&tmp, 0);
10173 
10174  if (var->sign == NUMERIC_POS && cmp_var(var, &tmp) != 0)
10175  add_var(&tmp, &const_one, &tmp);
10176 
10177  set_var_from_var(&tmp, result);
10178  free_var(&tmp);
10179 }
static void trunc_var(NumericVar *var, int rscale)
Definition: numeric.c:12077
static int cmp_var(const NumericVar *var1, const NumericVar *var2)
Definition: numeric.c:8377
static const NumericVar const_one
Definition: numeric.c:426

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

11727 {
11728  return cmp_abs_common(var1->digits, var1->ndigits, var1->weight,
11729  var2->digits, var2->ndigits, var2->weight);
11730 }
static int cmp_abs_common(const NumericDigit *var1digits, int var1ndigits, int var1weight, const NumericDigit *var2digits, int var2ndigits, int var2weight)
Definition: numeric.c:11740

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

11742 {
11743  int i1 = 0;
11744  int i2 = 0;
11745 
11746  /* Check any digits before the first common digit */
11747 
11748  while (var1weight > var2weight && i1 < var1ndigits)
11749  {
11750  if (var1digits[i1++] != 0)
11751  return 1;
11752  var1weight--;
11753  }
11754  while (var2weight > var1weight && i2 < var2ndigits)
11755  {
11756  if (var2digits[i2++] != 0)
11757  return -1;
11758  var2weight--;
11759  }
11760 
11761  /* At this point, either w1 == w2 or we've run out of digits */
11762 
11763  if (var1weight == var2weight)
11764  {
11765  while (i1 < var1ndigits && i2 < var2ndigits)
11766  {
11767  int stat = var1digits[i1++] - var2digits[i2++];
11768 
11769  if (stat)
11770  {
11771  if (stat > 0)
11772  return 1;
11773  return -1;
11774  }
11775  }
11776  }
11777 
11778  /*
11779  * At this point, we've run out of digits on one side or the other; so any
11780  * remaining nonzero digits imply that side is larger
11781  */
11782  while (i1 < var1ndigits)
11783  {
11784  if (var1digits[i1++] != 0)
11785  return 1;
11786  }
11787  while (i2 < var2ndigits)
11788  {
11789  if (var2digits[i2++] != 0)
11790  return -1;
11791  }
11792 
11793  return 0;
11794 }

Referenced by cmp_abs(), and cmp_var_common().

◆ cmp_numerics()

static int cmp_numerics ( Numeric  num1,
Numeric  num2 
)
static

Definition at line 2509 of file numeric.c.

2510 {
2511  int result;
2512 
2513  /*
2514  * We consider all NANs to be equal and larger than any non-NAN (including
2515  * Infinity). This is somewhat arbitrary; the important thing is to have
2516  * a consistent sort order.
2517  */
2518  if (NUMERIC_IS_SPECIAL(num1))
2519  {
2520  if (NUMERIC_IS_NAN(num1))
2521  {
2522  if (NUMERIC_IS_NAN(num2))
2523  result = 0; /* NAN = NAN */
2524  else
2525  result = 1; /* NAN > non-NAN */
2526  }
2527  else if (NUMERIC_IS_PINF(num1))
2528  {
2529  if (NUMERIC_IS_NAN(num2))
2530  result = -1; /* PINF < NAN */
2531  else if (NUMERIC_IS_PINF(num2))
2532  result = 0; /* PINF = PINF */
2533  else
2534  result = 1; /* PINF > anything else */
2535  }
2536  else /* num1 must be NINF */
2537  {
2538  if (NUMERIC_IS_NINF(num2))
2539  result = 0; /* NINF = NINF */
2540  else
2541  result = -1; /* NINF < anything else */
2542  }
2543  }
2544  else if (NUMERIC_IS_SPECIAL(num2))
2545  {
2546  if (NUMERIC_IS_NINF(num2))
2547  result = 1; /* normal > NINF */
2548  else
2549  result = -1; /* normal < NAN or PINF */
2550  }
2551  else
2552  {
2553  result = cmp_var_common(NUMERIC_DIGITS(num1), NUMERIC_NDIGITS(num1),
2554  NUMERIC_WEIGHT(num1), NUMERIC_SIGN(num1),
2555  NUMERIC_DIGITS(num2), NUMERIC_NDIGITS(num2),
2556  NUMERIC_WEIGHT(num2), NUMERIC_SIGN(num2));
2557  }
2558 
2559  return result;
2560 }
#define NUMERIC_SIGN(n)
Definition: numeric.c:236
#define NUMERIC_IS_PINF(n)
Definition: numeric.c:204
#define NUMERIC_IS_NINF(n)
Definition: numeric.c:205
#define NUMERIC_WEIGHT(n)
Definition: numeric.c:246
#define NUMERIC_DIGITS(num)
Definition: numeric.c:493
#define NUMERIC_NDIGITS(num)
Definition: numeric.c:495
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:8392

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

8396 {
8397  if (var1ndigits == 0)
8398  {
8399  if (var2ndigits == 0)
8400  return 0;
8401  if (var2sign == NUMERIC_NEG)
8402  return 1;
8403  return -1;
8404  }
8405  if (var2ndigits == 0)
8406  {
8407  if (var1sign == NUMERIC_POS)
8408  return 1;
8409  return -1;
8410  }
8411 
8412  if (var1sign == NUMERIC_POS)
8413  {
8414  if (var2sign == NUMERIC_NEG)
8415  return 1;
8416  return cmp_abs_common(var1digits, var1ndigits, var1weight,
8417  var2digits, var2ndigits, var2weight);
8418  }
8419 
8420  if (var2sign == NUMERIC_POS)
8421  return -1;
8422 
8423  return cmp_abs_common(var2digits, var2ndigits, var2weight,
8424  var1digits, var1ndigits, var1weight);
8425 }

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

1936 {
1937  NumericVar bound1_var;
1938  NumericVar bound2_var;
1939  NumericVar operand_var;
1940 
1941  init_var_from_num(bound1, &bound1_var);
1942  init_var_from_num(bound2, &bound2_var);
1943  init_var_from_num(operand, &operand_var);
1944 
1945  /*
1946  * Per spec, bound1 is inclusive and bound2 is exclusive, and so we have
1947  * bound1 <= operand < bound2 or bound1 >= operand > bound2. Either way,
1948  * the result is ((operand - bound1) * count) / (bound2 - bound1) + 1,
1949  * where the quotient is computed using floor division (i.e., division to
1950  * zero decimal places with truncation), which guarantees that the result
1951  * is in the range [1, count]. Reversing the bounds doesn't affect the
1952  * computation, because the signs cancel out when dividing.
1953  */
1954  sub_var(&operand_var, &bound1_var, &operand_var);
1955  sub_var(&bound2_var, &bound1_var, &bound2_var);
1956 
1957  mul_var(&operand_var, count_var, &operand_var,
1958  operand_var.dscale + count_var->dscale);
1959  div_var(&operand_var, &bound2_var, result_var, 0, false);
1960  add_var(result_var, &const_one, result_var);
1961 
1962  free_var(&bound1_var);
1963  free_var(&bound2_var);
1964  free_var(&operand_var);
1965 }
static void sub_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition: numeric.c:8552
static void init_var_from_num(Numeric num, NumericVar *dest)
Definition: numeric.c:7455
static void mul_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result, int rscale)
Definition: numeric.c:8673
static void div_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result, int rscale, bool round)
Definition: numeric.c:9097

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

10097 {
10098  NumericVar q;
10099  NumericVar r;
10100 
10101  init_var(&q);
10102  init_var(&r);
10103 
10104  /*
10105  * Use div_var_fast() to get an initial estimate for the integer quotient.
10106  * This might be inaccurate (per the warning in div_var_fast's comments),
10107  * but we can correct it below.
10108  */
10109  div_var_fast(var1, var2, &q, 0, false);
10110 
10111  /* Compute initial estimate of remainder using the quotient estimate. */
10112  mul_var(var2, &q, &r, var2->dscale);
10113  sub_var(var1, &r, &r);
10114 
10115  /*
10116  * Adjust the results if necessary --- the remainder should have the same
10117  * sign as var1, and its absolute value should be less than the absolute
10118  * value of var2.
10119  */
10120  while (r.ndigits != 0 && r.sign != var1->sign)
10121  {
10122  /* The absolute value of the quotient is too large */
10123  if (var1->sign == var2->sign)
10124  {
10125  sub_var(&q, &const_one, &q);
10126  add_var(&r, var2, &r);
10127  }
10128  else
10129  {
10130  add_var(&q, &const_one, &q);
10131  sub_var(&r, var2, &r);
10132  }
10133  }
10134 
10135  while (cmp_abs(&r, var2) >= 0)
10136  {
10137  /* The absolute value of the quotient is too small */
10138  if (var1->sign == var2->sign)
10139  {
10140  add_var(&q, &const_one, &q);
10141  sub_var(&r, var2, &r);
10142  }
10143  else
10144  {
10145  sub_var(&q, &const_one, &q);
10146  add_var(&r, var2, &r);
10147  }
10148  }
10149 
10150  set_var_from_var(&q, quot);
10151  set_var_from_var(&r, rem);
10152 
10153  free_var(&q);
10154  free_var(&r);
10155 }
static void div_var_fast(const NumericVar *var1, const NumericVar *var2, NumericVar *result, int rscale, bool round)
Definition: numeric.c:9405

References add_var(), cmp_abs(), const_one, div_var_fast(), 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 
)
static

Definition at line 9097 of file numeric.c.

9099 {
9100  int div_ndigits;
9101  int res_ndigits;
9102  int res_sign;
9103  int res_weight;
9104  int carry;
9105  int borrow;
9106  int divisor1;
9107  int divisor2;
9108  NumericDigit *dividend;
9109  NumericDigit *divisor;
9110  NumericDigit *res_digits;
9111  int i;
9112  int j;
9113 
9114  /* copy these values into local vars for speed in inner loop */
9115  int var1ndigits = var1->ndigits;
9116  int var2ndigits = var2->ndigits;
9117 
9118  /*
9119  * First of all division by zero check; we must not be handed an
9120  * unnormalized divisor.
9121  */
9122  if (var2ndigits == 0 || var2->digits[0] == 0)
9123  ereport(ERROR,
9124  (errcode(ERRCODE_DIVISION_BY_ZERO),
9125  errmsg("division by zero")));
9126 
9127  /*
9128  * If the divisor has just one or two digits, delegate to div_var_int(),
9129  * which uses fast short division.
9130  *
9131  * Similarly, on platforms with 128-bit integer support, delegate to
9132  * div_var_int64() for divisors with three or four digits.
9133  */
9134  if (var2ndigits <= 2)
9135  {
9136  int idivisor;
9137  int idivisor_weight;
9138 
9139  idivisor = var2->digits[0];
9140  idivisor_weight = var2->weight;
9141  if (var2ndigits == 2)
9142  {
9143  idivisor = idivisor * NBASE + var2->digits[1];
9144  idivisor_weight--;
9145  }
9146  if (var2->sign == NUMERIC_NEG)
9147  idivisor = -idivisor;
9148 
9149  div_var_int(var1, idivisor, idivisor_weight, result, rscale, round);
9150  return;
9151  }
9152 #ifdef HAVE_INT128
9153  if (var2ndigits <= 4)
9154  {
9155  int64 idivisor;
9156  int idivisor_weight;
9157 
9158  idivisor = var2->digits[0];
9159  idivisor_weight = var2->weight;
9160  for (i = 1; i < var2ndigits; i++)
9161  {
9162  idivisor = idivisor * NBASE + var2->digits[i];
9163  idivisor_weight--;
9164  }
9165  if (var2->sign == NUMERIC_NEG)
9166  idivisor = -idivisor;
9167 
9168  div_var_int64(var1, idivisor, idivisor_weight, result, rscale, round);
9169  return;
9170  }
9171 #endif
9172 
9173  /*
9174  * Otherwise, perform full long division.
9175  */
9176 
9177  /* Result zero check */
9178  if (var1ndigits == 0)
9179  {
9180  zero_var(result);
9181  result->dscale = rscale;
9182  return;
9183  }
9184 
9185  /*
9186  * Determine the result sign, weight and number of digits to calculate.
9187  * The weight figured here is correct if the emitted quotient has no
9188  * leading zero digits; otherwise strip_var() will fix things up.
9189  */
9190  if (var1->sign == var2->sign)
9191  res_sign = NUMERIC_POS;
9192  else
9193  res_sign = NUMERIC_NEG;
9194  res_weight = var1->weight - var2->weight;
9195  /* The number of accurate result digits we need to produce: */
9196  res_ndigits = res_weight + 1 + (rscale + DEC_DIGITS - 1) / DEC_DIGITS;
9197  /* ... but always at least 1 */
9198  res_ndigits = Max(res_ndigits, 1);
9199  /* If rounding needed, figure one more digit to ensure correct result */
9200  if (round)
9201  res_ndigits++;
9202 
9203  /*
9204  * The working dividend normally requires res_ndigits + var2ndigits
9205  * digits, but make it at least var1ndigits so we can load all of var1
9206  * into it. (There will be an additional digit dividend[0] in the
9207  * dividend space, but for consistency with Knuth's notation we don't
9208  * count that in div_ndigits.)
9209  */
9210  div_ndigits = res_ndigits + var2ndigits;
9211  div_ndigits = Max(div_ndigits, var1ndigits);
9212 
9213  /*
9214  * We need a workspace with room for the working dividend (div_ndigits+1
9215  * digits) plus room for the possibly-normalized divisor (var2ndigits
9216  * digits). It is convenient also to have a zero at divisor[0] with the
9217  * actual divisor data in divisor[1 .. var2ndigits]. Transferring the
9218  * digits into the workspace also allows us to realloc the result (which
9219  * might be the same as either input var) before we begin the main loop.
9220  * Note that we use palloc0 to ensure that divisor[0], dividend[0], and
9221  * any additional dividend positions beyond var1ndigits, start out 0.
9222  */
9223  dividend = (NumericDigit *)
9224  palloc0((div_ndigits + var2ndigits + 2) * sizeof(NumericDigit));
9225  divisor = dividend + (div_ndigits + 1);
9226  memcpy(dividend + 1, var1->digits, var1ndigits * sizeof(NumericDigit));
9227  memcpy(divisor + 1, var2->digits, var2ndigits * sizeof(NumericDigit));
9228 
9229  /*
9230  * Now we can realloc the result to hold the generated quotient digits.
9231  */
9232  alloc_var(result, res_ndigits);
9233  res_digits = result->digits;
9234 
9235  /*
9236  * The full multiple-place algorithm is taken from Knuth volume 2,
9237  * Algorithm 4.3.1D.
9238  *
9239  * We need the first divisor digit to be >= NBASE/2. If it isn't, make it
9240  * so by scaling up both the divisor and dividend by the factor "d". (The
9241  * reason for allocating dividend[0] above is to leave room for possible
9242  * carry here.)
9243  */
9244  if (divisor[1] < HALF_NBASE)
9245  {
9246  int d = NBASE / (divisor[1] + 1);
9247 
9248  carry = 0;
9249  for (i = var2ndigits; i > 0; i--)
9250  {
9251  carry += divisor[i] * d;
9252  divisor[i] = carry % NBASE;
9253  carry = carry / NBASE;
9254  }
9255  Assert(carry == 0);
9256  carry = 0;
9257  /* at this point only var1ndigits of dividend can be nonzero */
9258  for (i = var1ndigits; i >= 0; i--)
9259  {
9260  carry += dividend[i] * d;
9261  dividend[i] = carry % NBASE;
9262  carry = carry / NBASE;
9263  }
9264  Assert(carry == 0);
9265  Assert(divisor[1] >= HALF_NBASE);
9266  }
9267  /* First 2 divisor digits are used repeatedly in main loop */
9268  divisor1 = divisor[1];
9269  divisor2 = divisor[2];
9270 
9271  /*
9272  * Begin the main loop. Each iteration of this loop produces the j'th
9273  * quotient digit by dividing dividend[j .. j + var2ndigits] by the
9274  * divisor; this is essentially the same as the common manual procedure
9275  * for long division.
9276  */
9277  for (j = 0; j < res_ndigits; j++)
9278  {
9279  /* Estimate quotient digit from the first two dividend digits */
9280  int next2digits = dividend[j] * NBASE + dividend[j + 1];
9281  int qhat;
9282 
9283  /*
9284  * If next2digits are 0, then quotient digit must be 0 and there's no
9285  * need to adjust the working dividend. It's worth testing here to
9286  * fall out ASAP when processing trailing zeroes in a dividend.
9287  */
9288  if (next2digits == 0)
9289  {
9290  res_digits[j] = 0;
9291  continue;
9292  }
9293 
9294  if (dividend[j] == divisor1)
9295  qhat = NBASE - 1;
9296  else
9297  qhat = next2digits / divisor1;
9298 
9299  /*
9300  * Adjust quotient digit if it's too large. Knuth proves that after
9301  * this step, the quotient digit will be either correct or just one
9302  * too large. (Note: it's OK to use dividend[j+2] here because we
9303  * know the divisor length is at least 2.)
9304  */
9305  while (divisor2 * qhat >
9306  (next2digits - qhat * divisor1) * NBASE + dividend[j + 2])
9307  qhat--;
9308 
9309  /* As above, need do nothing more when quotient digit is 0 */
9310  if (qhat > 0)
9311  {
9312  NumericDigit *dividend_j = &dividend[j];
9313 
9314  /*
9315  * Multiply the divisor by qhat, and subtract that from the
9316  * working dividend. The multiplication and subtraction are
9317  * folded together here, noting that qhat <= NBASE (since it might
9318  * be one too large), and so the intermediate result "tmp_result"
9319  * is in the range [-NBASE^2, NBASE - 1], and "borrow" is in the
9320  * range [0, NBASE].
9321  */
9322  borrow = 0;
9323  for (i = var2ndigits; i >= 0; i--)
9324  {
9325  int tmp_result;
9326 
9327  tmp_result = dividend_j[i] - borrow - divisor[i] * qhat;
9328  borrow = (NBASE - 1 - tmp_result) / NBASE;
9329  dividend_j[i] = tmp_result + borrow * NBASE;
9330  }
9331 
9332  /*
9333  * If we got a borrow out of the top dividend digit, then indeed
9334  * qhat was one too large. Fix it, and add back the divisor to
9335  * correct the working dividend. (Knuth proves that this will
9336  * occur only about 3/NBASE of the time; hence, it's a good idea
9337  * to test this code with small NBASE to be sure this section gets
9338  * exercised.)
9339  */
9340  if (borrow)
9341  {
9342  qhat--;
9343  carry = 0;
9344  for (i = var2ndigits; i >= 0; i--)
9345  {
9346  carry += dividend_j[i] + divisor[i];
9347  if (carry >= NBASE)
9348  {
9349  dividend_j[i] = carry - NBASE;
9350  carry = 1;
9351  }
9352  else
9353  {
9354  dividend_j[i] = carry;
9355  carry = 0;
9356  }
9357  }
9358  /* A carry should occur here to cancel the borrow above */
9359  Assert(carry == 1);
9360  }
9361  }
9362 
9363  /* And we're done with this quotient digit */
9364  res_digits[j] = qhat;
9365  }
9366 
9367  pfree(dividend);
9368 
9369  /*
9370  * Finally, round or truncate the result to the requested precision.
9371  */
9372  result->weight = res_weight;
9373  result->sign = res_sign;
9374 
9375  /* Round or truncate to target rscale (and set result->dscale) */
9376  if (round)
9377  round_var(result, rscale);
9378  else
9379  trunc_var(result, rscale);
9380 
9381  /* Strip leading and trailing zeroes */
9382  strip_var(result);
9383 }
static void div_var_int(const NumericVar *var, int ival, int ival_weight, NumericVar *result, int rscale, bool round)
Definition: numeric.c:9769
static void alloc_var(NumericVar *var, int ndigits)
Definition: numeric.c:6957
#define HALF_NBASE
Definition: numeric.c:96
#define ERROR
Definition: elog.h:39
#define ereport(elevel,...)
Definition: elog.h:149
int j
Definition: isn.c:74

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

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

◆ div_var_fast()

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

Definition at line 9405 of file numeric.c.

9407 {
9408  int div_ndigits;
9409  int load_ndigits;
9410  int res_sign;
9411  int res_weight;
9412  int *div;
9413  int qdigit;
9414  int carry;
9415  int maxdiv;
9416  int newdig;
9417  NumericDigit *res_digits;
9418  double fdividend,
9419  fdivisor,
9420  fdivisorinverse,
9421  fquotient;
9422  int qi;
9423  int i;
9424 
9425  /* copy these values into local vars for speed in inner loop */
9426  int var1ndigits = var1->ndigits;
9427  int var2ndigits = var2->ndigits;
9428  NumericDigit *var1digits = var1->digits;
9429  NumericDigit *var2digits = var2->digits;
9430 
9431  /*
9432  * First of all division by zero check; we must not be handed an
9433  * unnormalized divisor.
9434  */
9435  if (var2ndigits == 0 || var2digits[0] == 0)
9436  ereport(ERROR,
9437  (errcode(ERRCODE_DIVISION_BY_ZERO),
9438  errmsg("division by zero")));
9439 
9440  /*
9441  * If the divisor has just one or two digits, delegate to div_var_int(),
9442  * which uses fast short division.
9443  *
9444  * Similarly, on platforms with 128-bit integer support, delegate to
9445  * div_var_int64() for divisors with three or four digits.
9446  */
9447  if (var2ndigits <= 2)
9448  {
9449  int idivisor;
9450  int idivisor_weight;
9451 
9452  idivisor = var2->digits[0];
9453  idivisor_weight = var2->weight;
9454  if (var2ndigits == 2)
9455  {
9456  idivisor = idivisor * NBASE + var2->digits[1];
9457  idivisor_weight--;
9458  }
9459  if (var2->sign == NUMERIC_NEG)
9460  idivisor = -idivisor;
9461 
9462  div_var_int(var1, idivisor, idivisor_weight, result, rscale, round);
9463  return;
9464  }
9465 #ifdef HAVE_INT128
9466  if (var2ndigits <= 4)
9467  {
9468  int64 idivisor;
9469  int idivisor_weight;
9470 
9471  idivisor = var2->digits[0];
9472  idivisor_weight = var2->weight;
9473  for (i = 1; i < var2ndigits; i++)
9474  {
9475  idivisor = idivisor * NBASE + var2->digits[i];
9476  idivisor_weight--;
9477  }
9478  if (var2->sign == NUMERIC_NEG)
9479  idivisor = -idivisor;
9480 
9481  div_var_int64(var1, idivisor, idivisor_weight, result, rscale, round);
9482  return;
9483  }
9484 #endif
9485 
9486  /*
9487  * Otherwise, perform full long division.
9488  */
9489 
9490  /* Result zero check */
9491  if (var1ndigits == 0)
9492  {
9493  zero_var(result);
9494  result->dscale = rscale;
9495  return;
9496  }
9497 
9498  /*
9499  * Determine the result sign, weight and number of digits to calculate
9500  */
9501  if (var1->sign == var2->sign)
9502  res_sign = NUMERIC_POS;
9503  else
9504  res_sign = NUMERIC_NEG;
9505  res_weight = var1->weight - var2->weight + 1;
9506  /* The number of accurate result digits we need to produce: */
9507  div_ndigits = res_weight + 1 + (rscale + DEC_DIGITS - 1) / DEC_DIGITS;
9508  /* Add guard digits for roundoff error */
9509  div_ndigits += DIV_GUARD_DIGITS;
9510  if (div_ndigits < DIV_GUARD_DIGITS)
9511  div_ndigits = DIV_GUARD_DIGITS;
9512 
9513  /*
9514  * We do the arithmetic in an array "div[]" of signed int's. Since
9515  * INT_MAX is noticeably larger than NBASE*NBASE, this gives us headroom
9516  * to avoid normalizing carries immediately.
9517  *
9518  * We start with div[] containing one zero digit followed by the
9519  * dividend's digits (plus appended zeroes to reach the desired precision
9520  * including guard digits). Each step of the main loop computes an
9521  * (approximate) quotient digit and stores it into div[], removing one
9522  * position of dividend space. A final pass of carry propagation takes
9523  * care of any mistaken quotient digits.
9524  *
9525  * Note that div[] doesn't necessarily contain all of the digits from the
9526  * dividend --- the desired precision plus guard digits might be less than
9527  * the dividend's precision. This happens, for example, in the square
9528  * root algorithm, where we typically divide a 2N-digit number by an
9529  * N-digit number, and only require a result with N digits of precision.
9530  */
9531  div = (int *) palloc0((div_ndigits + 1) * sizeof(int));
9532  load_ndigits = Min(div_ndigits, var1ndigits);
9533  for (i = 0; i < load_ndigits; i++)
9534  div[i + 1] = var1digits[i];
9535 
9536  /*
9537  * We estimate each quotient digit using floating-point arithmetic, taking
9538  * the first four digits of the (current) dividend and divisor. This must
9539  * be float to avoid overflow. The quotient digits will generally be off
9540  * by no more than one from the exact answer.
9541  */
9542  fdivisor = (double) var2digits[0];
9543  for (i = 1; i < 4; i++)
9544  {
9545  fdivisor *= NBASE;
9546  if (i < var2ndigits)
9547  fdivisor += (double) var2digits[i];
9548  }
9549  fdivisorinverse = 1.0 / fdivisor;
9550 
9551  /*
9552  * maxdiv tracks the maximum possible absolute value of any div[] entry;
9553  * when this threatens to exceed INT_MAX, we take the time to propagate
9554  * carries. Furthermore, we need to ensure that overflow doesn't occur
9555  * during the carry propagation passes either. The carry values may have
9556  * an absolute value as high as INT_MAX/NBASE + 1, so really we must
9557  * normalize when digits threaten to exceed INT_MAX - INT_MAX/NBASE - 1.
9558  *
9559  * To avoid overflow in maxdiv itself, it represents the max absolute
9560  * value divided by NBASE-1, ie, at the top of the loop it is known that
9561  * no div[] entry has an absolute value exceeding maxdiv * (NBASE-1).
9562  *
9563  * Actually, though, that holds good only for div[] entries after div[qi];
9564  * the adjustment done at the bottom of the loop may cause div[qi + 1] to
9565  * exceed the maxdiv limit, so that div[qi] in the next iteration is
9566  * beyond the limit. This does not cause problems, as explained below.
9567  */
9568  maxdiv = 1;
9569 
9570  /*
9571  * Outer loop computes next quotient digit, which will go into div[qi]
9572  */
9573  for (qi = 0; qi < div_ndigits; qi++)
9574  {
9575  /* Approximate the current dividend value */
9576  fdividend = (double) div[qi];
9577  for (i = 1; i < 4; i++)
9578  {
9579  fdividend *= NBASE;
9580  if (qi + i <= div_ndigits)
9581  fdividend += (double) div[qi + i];
9582  }
9583  /* Compute the (approximate) quotient digit */
9584  fquotient = fdividend * fdivisorinverse;
9585  qdigit = (fquotient >= 0.0) ? ((int) fquotient) :
9586  (((int) fquotient) - 1); /* truncate towards -infinity */
9587 
9588  if (qdigit != 0)
9589  {
9590  /* Do we need to normalize now? */
9591  maxdiv += abs(qdigit);
9592  if (maxdiv > (INT_MAX - INT_MAX / NBASE - 1) / (NBASE - 1))
9593  {
9594  /*
9595  * Yes, do it. Note that if var2ndigits is much smaller than
9596  * div_ndigits, we can save a significant amount of effort
9597  * here by noting that we only need to normalise those div[]
9598  * entries touched where prior iterations subtracted multiples
9599  * of the divisor.
9600  */
9601  carry = 0;
9602  for (i = Min(qi + var2ndigits - 2, div_ndigits); i > qi; i--)
9603  {
9604  newdig = div[i] + carry;
9605  if (newdig < 0)
9606  {
9607  carry = -((-newdig - 1) / NBASE) - 1;
9608  newdig -= carry * NBASE;
9609  }
9610  else if (newdig >= NBASE)
9611  {
9612  carry = newdig / NBASE;
9613  newdig -= carry * NBASE;
9614  }
9615  else
9616  carry = 0;
9617  div[i] = newdig;
9618  }
9619  newdig = div[qi] + carry;
9620  div[qi] = newdig;
9621 
9622  /*
9623  * All the div[] digits except possibly div[qi] are now in the
9624  * range 0..NBASE-1. We do not need to consider div[qi] in
9625  * the maxdiv value anymore, so we can reset maxdiv to 1.
9626  */
9627  maxdiv = 1;
9628 
9629  /*
9630  * Recompute the quotient digit since new info may have
9631  * propagated into the top four dividend digits
9632  */
9633  fdividend = (double) div[qi];
9634  for (i = 1; i < 4; i++)
9635  {
9636  fdividend *= NBASE;
9637  if (qi + i <= div_ndigits)
9638  fdividend += (double) div[qi + i];
9639  }
9640  /* Compute the (approximate) quotient digit */
9641  fquotient = fdividend * fdivisorinverse;
9642  qdigit = (fquotient >= 0.0) ? ((int) fquotient) :
9643  (((int) fquotient) - 1); /* truncate towards -infinity */
9644  maxdiv += abs(qdigit);
9645  }
9646 
9647  /*
9648  * Subtract off the appropriate multiple of the divisor.
9649  *
9650  * The digits beyond div[qi] cannot overflow, because we know they
9651  * will fall within the maxdiv limit. As for div[qi] itself, note
9652  * that qdigit is approximately trunc(div[qi] / vardigits[0]),
9653  * which would make the new value simply div[qi] mod vardigits[0].
9654  * The lower-order terms in qdigit can change this result by not
9655  * more than about twice INT_MAX/NBASE, so overflow is impossible.
9656  *
9657  * This inner loop is the performance bottleneck for division, so
9658  * code it in the same way as the inner loop of mul_var() so that
9659  * it can be auto-vectorized. We cast qdigit to NumericDigit
9660  * before multiplying to allow the compiler to generate more
9661  * efficient code (using 16-bit multiplication), which is safe
9662  * since we know that the quotient digit is off by at most one, so
9663  * there is no overflow risk.
9664  */
9665  if (qdigit != 0)
9666  {
9667  int istop = Min(var2ndigits, div_ndigits - qi + 1);
9668  int *div_qi = &div[qi];
9669 
9670  for (i = 0; i < istop; i++)
9671  div_qi[i] -= ((NumericDigit) qdigit) * var2digits[i];
9672  }
9673  }
9674 
9675  /*
9676  * The dividend digit we are about to replace might still be nonzero.
9677  * Fold it into the next digit position.
9678  *
9679  * There is no risk of overflow here, although proving that requires
9680  * some care. Much as with the argument for div[qi] not overflowing,
9681  * if we consider the first two terms in the numerator and denominator
9682  * of qdigit, we can see that the final value of div[qi + 1] will be
9683  * approximately a remainder mod (vardigits[0]*NBASE + vardigits[1]).
9684  * Accounting for the lower-order terms is a bit complicated but ends
9685  * up adding not much more than INT_MAX/NBASE to the possible range.
9686  * Thus, div[qi + 1] cannot overflow here, and in its role as div[qi]
9687  * in the next loop iteration, it can't be large enough to cause
9688  * overflow in the carry propagation step (if any), either.
9689  *
9690  * But having said that: div[qi] can be more than INT_MAX/NBASE, as
9691  * noted above, which means that the product div[qi] * NBASE *can*
9692  * overflow. When that happens, adding it to div[qi + 1] will always
9693  * cause a canceling overflow so that the end result is correct. We
9694  * could avoid the intermediate overflow by doing the multiplication
9695  * and addition in int64 arithmetic, but so far there appears no need.
9696  */
9697  div[qi + 1] += div[qi] * NBASE;
9698 
9699  div[qi] = qdigit;
9700  }
9701 
9702  /*
9703  * Approximate and store the last quotient digit (div[div_ndigits])
9704  */
9705  fdividend = (double) div[qi];
9706  for (i = 1; i < 4; i++)
9707  fdividend *= NBASE;
9708  fquotient = fdividend * fdivisorinverse;
9709  qdigit = (fquotient >= 0.0) ? ((int) fquotient) :
9710  (((int) fquotient) - 1); /* truncate towards -infinity */
9711  div[qi] = qdigit;
9712 
9713  /*
9714  * Because the quotient digits might be off by one, some of them might be
9715  * -1 or NBASE at this point. The represented value is correct in a
9716  * mathematical sense, but it doesn't look right. We do a final carry
9717  * propagation pass to normalize the digits, which we combine with storing
9718  * the result digits into the output. Note that this is still done at
9719  * full precision w/guard digits.
9720  */
9721  alloc_var(result, div_ndigits + 1);
9722  res_digits = result->digits;
9723  carry = 0;
9724  for (i = div_ndigits; i >= 0; i--)
9725  {
9726  newdig = div[i] + carry;
9727  if (newdig < 0)
9728  {
9729  carry = -((-newdig - 1) / NBASE) - 1;
9730  newdig -= carry * NBASE;
9731  }
9732  else if (newdig >= NBASE)
9733  {
9734  carry = newdig / NBASE;
9735  newdig -= carry * NBASE;
9736  }
9737  else
9738  carry = 0;
9739  res_digits[i] = newdig;
9740  }
9741  Assert(carry == 0);
9742 
9743  pfree(div);
9744 
9745  /*
9746  * Finally, round the result to the requested precision.
9747  */
9748  result->weight = res_weight;
9749  result->sign = res_sign;
9750 
9751  /* Round to target rscale (and set result->dscale) */
9752  if (round)
9753  round_var(result, rscale);
9754  else
9755  trunc_var(result, rscale);
9756 
9757  /* Strip leading and trailing zeroes */
9758  strip_var(result);
9759 }
#define DIV_GUARD_DIGITS
Definition: numeric.c:99
#define Min(x, y)
Definition: numeric.c:14

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

Referenced by div_mod_var(), ln_var(), log_var(), 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 9769 of file numeric.c.

9771 {
9772  NumericDigit *var_digits = var->digits;
9773  int var_ndigits = var->ndigits;
9774  int res_sign;
9775  int res_weight;
9776  int res_ndigits;
9777  NumericDigit *res_buf;
9778  NumericDigit *res_digits;
9779  uint32 divisor;
9780  int i;
9781 
9782  /* Guard against division by zero */
9783  if (ival == 0)
9784  ereport(ERROR,
9785  errcode(ERRCODE_DIVISION_BY_ZERO),
9786  errmsg("division by zero"));
9787 
9788  /* Result zero check */
9789  if (var_ndigits == 0)
9790  {
9791  zero_var(result);
9792  result->dscale = rscale;
9793  return;
9794  }
9795 
9796  /*
9797  * Determine the result sign, weight and number of digits to calculate.
9798  * The weight figured here is correct if the emitted quotient has no
9799  * leading zero digits; otherwise strip_var() will fix things up.
9800  */
9801  if (var->sign == NUMERIC_POS)
9802  res_sign = ival > 0 ? NUMERIC_POS : NUMERIC_NEG;
9803  else
9804  res_sign = ival > 0 ? NUMERIC_NEG : NUMERIC_POS;
9805  res_weight = var->weight - ival_weight;
9806  /* The number of accurate result digits we need to produce: */
9807  res_ndigits = res_weight + 1 + (rscale + DEC_DIGITS - 1) / DEC_DIGITS;
9808  /* ... but always at least 1 */
9809  res_ndigits = Max(res_ndigits, 1);
9810  /* If rounding needed, figure one more digit to ensure correct result */
9811  if (round)
9812  res_ndigits++;
9813 
9814  res_buf = digitbuf_alloc(res_ndigits + 1);
9815  res_buf[0] = 0; /* spare digit for later rounding */
9816  res_digits = res_buf + 1;
9817 
9818  /*
9819  * Now compute the quotient digits. This is the short division algorithm
9820  * described in Knuth volume 2, section 4.3.1 exercise 16, except that we
9821  * allow the divisor to exceed the internal base.
9822  *
9823  * In this algorithm, the carry from one digit to the next is at most
9824  * divisor - 1. Therefore, while processing the next digit, carry may
9825  * become as large as divisor * NBASE - 1, and so it requires a 64-bit
9826  * integer if this exceeds UINT_MAX.
9827  */
9828  divisor = abs(ival);
9829 
9830  if (divisor <= UINT_MAX / NBASE)
9831  {
9832  /* carry cannot overflow 32 bits */
9833  uint32 carry = 0;
9834 
9835  for (i = 0; i < res_ndigits; i++)
9836  {
9837  carry = carry * NBASE + (i < var_ndigits ? var_digits[i] : 0);
9838  res_digits[i] = (NumericDigit) (carry / divisor);
9839  carry = carry % divisor;
9840  }
9841  }
9842  else
9843  {
9844  /* carry may exceed 32 bits */
9845  uint64 carry = 0;
9846 
9847  for (i = 0; i < res_ndigits; i++)
9848  {
9849  carry = carry * NBASE + (i < var_ndigits ? var_digits[i] : 0);
9850  res_digits[i] = (NumericDigit) (carry / divisor);
9851  carry = carry % divisor;
9852  }
9853  }
9854 
9855  /* Store the quotient in result */
9856  digitbuf_free(result->buf);
9857  result->ndigits = res_ndigits;
9858  result->buf = res_buf;
9859  result->digits = res_digits;
9860  result->weight = res_weight;
9861  result->sign = res_sign;
9862 
9863  /* Round or truncate to target rscale (and set result->dscale) */
9864  if (round)
9865  round_var(result, rscale);
9866  else
9867  trunc_var(result, rscale);
9868 
9869  /* Strip leading/trailing zeroes */
9870  strip_var(result);
9871 }
unsigned int uint32
Definition: c.h:506

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(), div_var_fast(), exp_var(), and ln_var().

◆ do_numeric_accum()

static void do_numeric_accum ( NumericAggState state,
Numeric  newval 
)
static

Definition at line 4861 of file numeric.c.

4862 {
4863  NumericVar X;
4864  NumericVar X2;
4865  MemoryContext old_context;
4866 
4867  /* Count NaN/infinity inputs separately from all else */
4869  {
4870  if (NUMERIC_IS_PINF(newval))
4871  state->pInfcount++;
4872  else if (NUMERIC_IS_NINF(newval))
4873  state->nInfcount++;
4874  else
4875  state->NaNcount++;
4876  return;
4877  }
4878 
4879  /* load processed number in short-lived context */
4881 
4882  /*
4883  * Track the highest input dscale that we've seen, to support inverse
4884  * transitions (see do_numeric_discard).
4885  */
4886  if (X.dscale > state->maxScale)
4887  {
4888  state->maxScale = X.dscale;
4889  state->maxScaleCount = 1;
4890  }
4891  else if (X.dscale == state->maxScale)
4892  state->maxScaleCount++;
4893 
4894  /* if we need X^2, calculate that in short-lived context */
4895  if (state->calcSumX2)
4896  {
4897  init_var(&X2);
4898  mul_var(&X, &X, &X2, X.dscale * 2);
4899  }
4900 
4901  /* The rest of this needs to work in the aggregate context */
4902  old_context = MemoryContextSwitchTo(state->agg_context);
4903 
4904  state->N++;
4905 
4906  /* Accumulate sums */
4907  accum_sum_add(&(state->sumX), &X);
4908 
4909  if (state->calcSumX2)
4910  accum_sum_add(&(state->sumX2), &X2);
4911 
4912  MemoryContextSwitchTo(old_context);
4913 }
#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 4931 of file numeric.c.

4932 {
4933  NumericVar X;
4934  NumericVar X2;
4935  MemoryContext old_context;
4936 
4937  /* Count NaN/infinity inputs separately from all else */
4939  {
4940  if (NUMERIC_IS_PINF(newval))
4941  state->pInfcount--;
4942  else if (NUMERIC_IS_NINF(newval))
4943  state->nInfcount--;
4944  else
4945  state->NaNcount--;
4946  return true;
4947  }
4948 
4949  /* load processed number in short-lived context */
4951 
4952  /*
4953  * state->sumX's dscale is the maximum dscale of any of the inputs.
4954  * Removing the last input with that dscale would require us to recompute
4955  * the maximum dscale of the *remaining* inputs, which we cannot do unless
4956  * no more non-NaN inputs remain at all. So we report a failure instead,
4957  * and force the aggregation to be redone from scratch.
4958  */
4959  if (X.dscale == state->maxScale)
4960  {
4961  if (state->maxScaleCount > 1 || state->maxScale == 0)
4962  {
4963  /*
4964  * Some remaining inputs have same dscale, or dscale hasn't gotten
4965  * above zero anyway
4966  */
4967  state->maxScaleCount--;
4968  }
4969  else if (state->N == 1)
4970  {
4971  /* No remaining non-NaN inputs at all, so reset maxScale */
4972  state->maxScale = 0;
4973  state->maxScaleCount = 0;
4974  }
4975  else
4976  {
4977  /* Correct new maxScale is uncertain, must fail */
4978  return false;
4979  }
4980  }
4981 
4982  /* if we need X^2, calculate that in short-lived context */
4983  if (state->calcSumX2)
4984  {
4985  init_var(&X2);
4986  mul_var(&X, &X, &X2, X.dscale * 2);
4987  }
4988 
4989  /* The rest of this needs to work in the aggregate context */
4990  old_context = MemoryContextSwitchTo(state->agg_context);
4991 
4992  if (state->N-- > 1)
4993  {
4994  /* Negate X, to subtract it from the sum */
4995  X.sign = (X.sign == NUMERIC_POS ? NUMERIC_NEG : NUMERIC_POS);
4996  accum_sum_add(&(state->sumX), &X);
4997 
4998  if (state->calcSumX2)
4999  {
5000  /* Negate X^2. X^2 is always positive */
5001  X2.sign = NUMERIC_NEG;
5002  accum_sum_add(&(state->sumX2), &X2);
5003  }
5004  }
5005  else
5006  {
5007  /* Zero the sums */
5008  Assert(state->N == 0);
5009 
5010  accum_sum_reset(&state->sumX);
5011  if (state->calcSumX2)
5012  accum_sum_reset(&state->sumX2);
5013  }
5014 
5015  MemoryContextSwitchTo(old_context);
5016 
5017  return true;
5018 }
static void accum_sum_reset(NumericSumAccum *accum)
Definition: numeric.c:12180

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

7768 {
7769  Numeric res;
7770 
7771  res = (Numeric) palloc(VARSIZE(num));
7772  memcpy(res, num, VARSIZE(num));
7773  return res;
7774 }
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 10891 of file numeric.c.

10892 {
10893  int ln_dweight;
10894 
10895  /* Caller should fail on ln(negative), but for the moment return zero */
10896  if (var->sign != NUMERIC_POS)
10897  return 0;
10898 
10899  if (cmp_var(var, &const_zero_point_nine) >= 0 &&
10900  cmp_var(var, &const_one_point_one) <= 0)
10901  {
10902  /*
10903  * 0.9 <= var <= 1.1
10904  *
10905  * ln(var) has a negative weight (possibly very large). To get a
10906  * reasonably accurate result, estimate it using ln(1+x) ~= x.
10907  */
10908  NumericVar x;
10909 
10910  init_var(&x);
10911  sub_var(var, &const_one, &x);
10912 
10913  if (x.ndigits > 0)
10914  {
10915  /* Use weight of most significant decimal digit of x */
10916  ln_dweight = x.weight * DEC_DIGITS + (int) log10(x.digits[0]);
10917  }
10918  else
10919  {
10920  /* x = 0. Since ln(1) = 0 exactly, we don't need extra digits */
10921  ln_dweight = 0;
10922  }
10923 
10924  free_var(&x);
10925  }
10926  else
10927  {
10928  /*
10929  * Estimate the logarithm using the first couple of digits from the
10930  * input number. This will give an accurate result whenever the input
10931  * is not too close to 1.
10932  */
10933  if (var->ndigits > 0)
10934  {
10935  int digits;
10936  int dweight;
10937  double ln_var;
10938 
10939  digits = var->digits[0];
10940  dweight = var->weight * DEC_DIGITS;
10941 
10942  if (var->ndigits > 1)
10943  {
10944  digits = digits * NBASE + var->digits[1];
10945  dweight -= DEC_DIGITS;
10946  }
10947 
10948  /*----------
10949  * We have var ~= digits * 10^dweight
10950  * so ln(var) ~= ln(digits) + dweight * ln(10)
10951  *----------
10952  */
10953  ln_var = log((double) digits) + dweight * 2.302585092994046;
10954  ln_dweight = (int) log10(fabs(ln_var));
10955  }
10956  else
10957  {
10958  /* Caller should fail on ln(0), but for the moment return zero */
10959  ln_dweight = 0;
10960  }
10961  }
10962 
10963  return ln_dweight;
10964 }
static const NumericVar const_zero_point_nine
Definition: numeric.c:443
static const NumericVar const_one_point_one
Definition: numeric.c:453
static void ln_var(const NumericVar *arg, NumericVar *result, int rscale)
Definition: numeric.c:10973
int digits
Definition: informix.c:672
int x
Definition: isn.c:71

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

10763 {
10764  NumericVar x;
10765  NumericVar elem;
10766  int ni;
10767  double val;
10768  int dweight;
10769  int ndiv2;
10770  int sig_digits;
10771  int local_rscale;
10772 
10773  init_var(&x);
10774  init_var(&elem);
10775 
10776  set_var_from_var(arg, &x);
10777 
10778  /*
10779  * Estimate the dweight of the result using floating point arithmetic, so
10780  * that we can choose an appropriate local rscale for the calculation.
10781  */
10783 
10784  /* Guard against overflow/underflow */
10785  /* If you change this limit, see also power_var()'s limit */
10786  if (fabs(val) >= NUMERIC_MAX_RESULT_SCALE * 3)
10787  {
10788  if (val > 0)
10789  ereport(ERROR,
10790  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
10791  errmsg("value overflows numeric format")));
10792  zero_var(result);
10793  result->dscale = rscale;
10794  return;
10795  }
10796 
10797  /* decimal weight = log10(e^x) = x * log10(e) */
10798  dweight = (int) (val * 0.434294481903252);
10799 
10800  /*
10801  * Reduce x to the range -0.01 <= x <= 0.01 (approximately) by dividing by
10802  * 2^ndiv2, to improve the convergence rate of the Taylor series.
10803  *
10804  * Note that the overflow check above ensures that fabs(x) < 6000, which
10805  * means that ndiv2 <= 20 here.
10806  */
10807  if (fabs(val) > 0.01)
10808  {
10809  ndiv2 = 1;
10810  val /= 2;
10811 
10812  while (fabs(val) > 0.01)
10813  {
10814  ndiv2++;
10815  val /= 2;
10816  }
10817 
10818  local_rscale = x.dscale + ndiv2;
10819  div_var_int(&x, 1 << ndiv2, 0, &x, local_rscale, true);
10820  }
10821  else
10822  ndiv2 = 0;
10823 
10824  /*
10825  * Set the scale for the Taylor series expansion. The final result has
10826  * (dweight + rscale + 1) significant digits. In addition, we have to
10827  * raise the Taylor series result to the power 2^ndiv2, which introduces
10828  * an error of up to around log10(2^ndiv2) digits, so work with this many
10829  * extra digits of precision (plus a few more for good measure).
10830  */
10831  sig_digits = 1 + dweight + rscale + (int) (ndiv2 * 0.301029995663981);
10832  sig_digits = Max(sig_digits, 0) + 8;
10833 
10834  local_rscale = sig_digits - 1;
10835 
10836  /*
10837  * Use the Taylor series
10838  *
10839  * exp(x) = 1 + x + x^2/2! + x^3/3! + ...
10840  *
10841  * Given the limited range of x, this should converge reasonably quickly.
10842  * We run the series until the terms fall below the local_rscale limit.
10843  */
10844  add_var(&const_one, &x, result);
10845 
10846  mul_var(&x, &x, &elem, local_rscale);
10847  ni = 2;
10848  div_var_int(&elem, ni, 0, &elem, local_rscale, true);
10849 
10850  while (elem.ndigits != 0)
10851  {
10852  add_var(result, &elem, result);
10853 
10854  mul_var(&elem, &x, &elem, local_rscale);
10855  ni++;
10856  div_var_int(&elem, ni, 0, &elem, local_rscale, true);
10857  }
10858 
10859  /*
10860  * Compensate for the argument range reduction. Since the weight of the
10861  * result doubles with each multiplication, we can reduce the local rscale
10862  * as we proceed.
10863  */
10864  while (ndiv2-- > 0)
10865  {
10866  local_rscale = sig_digits - result->weight * 2 * DEC_DIGITS;
10867  local_rscale = Max(local_rscale, NUMERIC_MIN_DISPLAY_SCALE);
10868  mul_var(result, result, result, local_rscale);
10869  }
10870 
10871  /* Round to requested rscale */
10872  round_var(result, rscale);
10873 
10874  free_var(&x);
10875  free_var(&elem);
10876 }
static double numericvar_to_double_no_overflow(const NumericVar *var)
Definition: numeric.c:8345
#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 4691 of file numeric.c.

4692 {
4694  Numeric res;
4695  NumericVar result;
4696  char buf[FLT_DIG + 100];
4697  const char *endptr;
4698 
4699  if (isnan(val))
4701 
4702  if (isinf(val))
4703  {
4704  if (val < 0)
4706  else
4708  }
4709 
4710  snprintf(buf, sizeof(buf), "%.*g", FLT_DIG, val);
4711 
4712  init_var(&result);
4713 
4714  /* Assume we need not worry about leading/trailing spaces */
4715  (void) set_var_from_str(buf, buf, &result, &endptr, NULL);
4716 
4717  res = make_result(&result);
4718 
4719  free_var(&result);
4720 
4722 }
static const NumericVar const_pinf
Definition: numeric.c:459
static const NumericVar const_ninf
Definition: numeric.c:462
static bool set_var_from_str(const char *str, const char *cp, NumericVar *dest, const char **endptr, Node *escontext)
Definition: numeric.c:7016
static Numeric make_result(const NumericVar *var)
Definition: numeric.c:7895
static const NumericVar const_nan
Definition: numeric.c:456
float float4
Definition: c.h:629
#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 4597 of file numeric.c.

4598 {
4600  Numeric res;
4601  NumericVar result;
4602  char buf[DBL_DIG + 100];
4603  const char *endptr;
4604 
4605  if (isnan(val))
4607 
4608  if (isinf(val))
4609  {
4610  if (val < 0)
4612  else
4614  }
4615 
4616  snprintf(buf, sizeof(buf), "%.*g", DBL_DIG, val);
4617 
4618  init_var(&result);
4619 
4620  /* Assume we need not worry about leading/trailing spaces */
4621  (void) set_var_from_str(buf, buf, &result, &endptr, NULL);
4622 
4623  res = make_result(&result);
4624 
4625  free_var(&result);
4626 
4628 }
double float8
Definition: c.h:630
#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 10189 of file numeric.c.

10190 {
10191  NumericVar tmp;
10192 
10193  init_var(&tmp);
10194  set_var_from_var(var, &tmp);
10195 
10196  trunc_var(&tmp, 0);
10197 
10198  if (var->sign == NUMERIC_NEG && cmp_var(var, &tmp) != 0)
10199  sub_var(&tmp, &const_one, &tmp);
10200 
10201  set_var_from_var(&tmp, result);
10202  free_var(&tmp);
10203 }

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

6974 {
6975  digitbuf_free(var->buf);
6976  var->buf = NULL;
6977  var->digits = NULL;
6978  var->sign = NUMERIC_NAN;
6979 }
#define NUMERIC_NAN
Definition: numeric.c:197

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(), 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 10212 of file numeric.c.

10213 {
10214  int res_dscale;
10215  int cmp;
10216  NumericVar tmp_arg;
10217  NumericVar mod;
10218 
10219  res_dscale = Max(var1->dscale, var2->dscale);
10220 
10221  /*
10222  * Arrange for var1 to be the number with the greater absolute value.
10223  *
10224  * This would happen automatically in the loop below, but avoids an
10225  * expensive modulo operation.
10226  */
10227  cmp = cmp_abs(var1, var2);
10228  if (cmp < 0)
10229  {
10230  const NumericVar *tmp = var1;
10231 
10232  var1 = var2;
10233  var2 = tmp;
10234  }
10235 
10236  /*
10237  * Also avoid the taking the modulo if the inputs have the same absolute
10238  * value, or if the smaller input is zero.
10239  */
10240  if (cmp == 0 || var2->ndigits == 0)
10241  {
10242  set_var_from_var(var1, result);
10243  result->sign = NUMERIC_POS;
10244  result->dscale = res_dscale;
10245  return;
10246  }
10247 
10248  init_var(&tmp_arg);
10249  init_var(&mod);
10250 
10251  /* Use the Euclidean algorithm to find the GCD */
10252  set_var_from_var(var1, &tmp_arg);
10253  set_var_from_var(var2, result);
10254 
10255  for (;;)
10256  {
10257  /* this loop can take a while, so allow it to be interrupted */
10259 
10260  mod_var(&tmp_arg, result, &mod);
10261  if (mod.ndigits == 0)
10262  break;
10263  set_var_from_var(result, &tmp_arg);
10264  set_var_from_var(&mod, result);
10265  }
10266  result->sign = NUMERIC_POS;
10267  result->dscale = res_dscale;
10268 
10269  free_var(&tmp_arg);
10270  free_var(&mod);
10271 }
static void mod_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition: numeric.c:10066
#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_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:7424
#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 4140 of file numeric.c.

4141 {
4142  int min_scale;
4143  int last_digit_pos;
4144 
4145  /*
4146  * Ordinarily, the input value will be "stripped" so that the last
4147  * NumericDigit is nonzero. But we don't want to get into an infinite
4148  * loop if it isn't, so explicitly find the last nonzero digit.
4149  */
4150  last_digit_pos = var->ndigits - 1;
4151  while (last_digit_pos >= 0 &&
4152  var->digits[last_digit_pos] == 0)
4153  last_digit_pos--;
4154 
4155  if (last_digit_pos >= 0)
4156  {
4157  /* compute min_scale assuming that last ndigit has no zeroes */
4158  min_scale = (last_digit_pos - var->weight) * DEC_DIGITS;
4159 
4160  /*
4161  * We could get a negative result if there are no digits after the
4162  * decimal point. In this case the min_scale must be zero.
4163  */
4164  if (min_scale > 0)
4165  {
4166  /*
4167  * Reduce min_scale if trailing digit(s) in last NumericDigit are
4168  * zero.
4169  */
4170  NumericDigit last_digit = var->digits[last_digit_pos];
4171 
4172  while (last_digit % 10 == 0)
4173  {
4174  min_scale--;
4175  last_digit /= 10;
4176  }
4177  }
4178  else
4179  min_scale = 0;
4180  }
4181  else
4182  min_scale = 0; /* result if input is zero */
4183 
4184  return min_scale;
4185 }

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

7499 {
7500  int dscale;
7501  char *str;
7502  char *cp;
7503  char *endcp;
7504  int i;
7505  int d;
7506  NumericDigit dig;
7507 
7508 #if DEC_DIGITS > 1
7509  NumericDigit d1;
7510 #endif
7511 
7512  dscale = var->dscale;
7513 
7514  /*
7515  * Allocate space for the result.
7516  *
7517  * i is set to the # of decimal digits before decimal point. dscale is the
7518  * # of decimal digits we will print after decimal point. We may generate
7519  * as many as DEC_DIGITS-1 excess digits at the end, and in addition we
7520  * need room for sign, decimal point, null terminator.
7521  */
7522  i = (var->weight + 1) * DEC_DIGITS;
7523  if (i <= 0)
7524  i = 1;
7525 
7526  str = palloc(i + dscale + DEC_DIGITS + 2);
7527  cp = str;
7528 
7529  /*
7530  * Output a dash for negative values
7531  */
7532  if (var->sign == NUMERIC_NEG)
7533  *cp++ = '-';
7534 
7535  /*
7536  * Output all digits before the decimal point
7537  */
7538  if (var->weight < 0)
7539  {
7540  d = var->weight + 1;
7541  *cp++ = '0';
7542  }
7543  else
7544  {
7545  for (d = 0; d <= var->weight; d++)
7546  {
7547  dig = (d < var->ndigits) ? var->digits[d] : 0;
7548  /* In the first digit, suppress extra leading decimal zeroes */
7549 #if DEC_DIGITS == 4
7550  {
7551  bool putit = (d > 0);
7552 
7553  d1 = dig / 1000;
7554  dig -= d1 * 1000;
7555  putit |= (d1 > 0);
7556  if (putit)
7557  *cp++ = d1 + '0';
7558  d1 = dig / 100;
7559  dig -= d1 * 100;
7560  putit |= (d1 > 0);
7561  if (putit)
7562  *cp++ = d1 + '0';
7563  d1 = dig / 10;
7564  dig -= d1 * 10;
7565  putit |= (d1 > 0);
7566  if (putit)
7567  *cp++ = d1 + '0';
7568  *cp++ = dig + '0';
7569  }
7570 #elif DEC_DIGITS == 2
7571  d1 = dig / 10;
7572  dig -= d1 * 10;
7573  if (d1 > 0 || d > 0)
7574  *cp++ = d1 + '0';
7575  *cp++ = dig + '0';
7576 #elif DEC_DIGITS == 1
7577  *cp++ = dig + '0';
7578 #else
7579 #error unsupported NBASE
7580 #endif
7581  }
7582  }
7583 
7584  /*
7585  * If requested, output a decimal point and all the digits that follow it.
7586  * We initially put out a multiple of DEC_DIGITS digits, then truncate if
7587  * needed.
7588  */
7589  if (dscale > 0)
7590  {
7591  *cp++ = '.';
7592  endcp = cp + dscale;
7593  for (i = 0; i < dscale; d++, i += DEC_DIGITS)
7594  {
7595  dig = (d >= 0 && d < var->ndigits) ? var->digits[d] : 0;
7596 #if DEC_DIGITS == 4
7597  d1 = dig / 1000;
7598  dig -= d1 * 1000;
7599  *cp++ = d1 + '0';
7600  d1 = dig / 100;
7601  dig -= d1 * 100;
7602  *cp++ = d1 + '0';
7603  d1 = dig / 10;
7604  dig -= d1 * 10;
7605  *cp++ = d1 + '0';
7606  *cp++ = dig + '0';
7607 #elif DEC_DIGITS == 2
7608  d1 = dig / 10;
7609  dig -= d1 * 10;
7610  *cp++ = d1 + '0';
7611  *cp++ = dig + '0';
7612 #elif DEC_DIGITS == 1
7613  *cp++ = dig + '0';
7614 #else
7615 #error unsupported NBASE
7616 #endif
7617  }
7618  cp = endcp;
7619  }
7620 
7621  /*
7622  * terminate the string and return it
7623  */
7624  *cp = '\0';
7625  return str;
7626 }
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 7651 of file numeric.c.

7652 {
7653  int32 exponent;
7654  NumericVar tmp_var;
7655  size_t len;
7656  char *str;
7657  char *sig_out;
7658 
7659  if (rscale < 0)
7660  rscale = 0;
7661 
7662  /*
7663  * Determine the exponent of this number in normalised form.
7664  *
7665  * This is the exponent required to represent the number with only one
7666  * significant digit before the decimal place.
7667  */
7668  if (var->ndigits > 0)
7669  {
7670  exponent = (var->weight + 1) * DEC_DIGITS;
7671 
7672  /*
7673  * Compensate for leading decimal zeroes in the first numeric digit by
7674  * decrementing the exponent.
7675  */
7676  exponent -= DEC_DIGITS - (int) log10(var->digits[0]);
7677  }
7678  else
7679  {
7680  /*
7681  * If var has no digits, then it must be zero.
7682  *
7683  * Zero doesn't technically have a meaningful exponent in normalised
7684  * notation, but we just display the exponent as zero for consistency
7685  * of output.
7686  */
7687  exponent = 0;
7688  }
7689 
7690  /*
7691  * Divide var by 10^exponent to get the significand, rounding to rscale
7692  * decimal digits in the process.
7693  */
7694  init_var(&tmp_var);
7695 
7696  power_ten_int(exponent, &tmp_var);
7697  div_var(var, &tmp_var, &tmp_var, rscale, true);
7698  sig_out = get_str_from_var(&tmp_var);
7699 
7700  free_var(&tmp_var);
7701 
7702  /*
7703  * Allocate space for the result.
7704  *
7705  * In addition to the significand, we need room for the exponent
7706  * decoration ("e"), the sign of the exponent, up to 10 digits for the
7707  * exponent itself, and of course the null terminator.
7708  */
7709  len = strlen(sig_out) + 13;
7710  str = palloc(len);
7711  snprintf(str, len, "%se%+03d", sig_out, exponent);
7712 
7713  pfree(sig_out);
7714 
7715  return str;
7716 }
static char * get_str_from_var(const NumericVar *var)
Definition: numeric.c:7498
static void power_ten_int(int exp, NumericVar *result)
Definition: numeric.c:11518
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 2701 of file numeric.c.

2702 {
2704  Datum digit_hash;
2705  Datum result;
2706  int weight;
2707  int start_offset;
2708  int end_offset;
2709  int i;
2710  int hash_len;
2712 
2713  /* If it's NaN or infinity, don't try to hash the rest of the fields */
2714  if (NUMERIC_IS_SPECIAL(key))
2715  PG_RETURN_UINT32(0);
2716 
2717  weight = NUMERIC_WEIGHT(key);
2718  start_offset = 0;
2719  end_offset = 0;
2720 
2721  /*
2722  * Omit any leading or trailing zeros from the input to the hash. The
2723  * numeric implementation *should* guarantee that leading and trailing
2724  * zeros are suppressed, but we're paranoid. Note that we measure the
2725  * starting and ending offsets in units of NumericDigits, not bytes.
2726  */
2728  for (i = 0; i < NUMERIC_NDIGITS(key); i++)
2729  {
2730  if (digits[i] != (NumericDigit) 0)
2731  break;
2732 
2733  start_offset++;
2734 
2735  /*
2736  * The weight is effectively the # of digits before the decimal point,
2737  * so decrement it for each leading zero we skip.
2738  */
2739  weight--;
2740  }
2741 
2742  /*
2743  * If there are no non-zero digits, then the value of the number is zero,
2744  * regardless of any other fields.
2745  */
2746  if (NUMERIC_NDIGITS(key) == start_offset)
2747  PG_RETURN_UINT32(-1);
2748 
2749  for (i = NUMERIC_NDIGITS(key) - 1; i >= 0; i--)
2750  {
2751  if (digits[i] != (NumericDigit) 0)
2752  break;
2753 
2754  end_offset++;
2755  }
2756 
2757  /* If we get here, there should be at least one non-zero digit */
2758  Assert(start_offset + end_offset < NUMERIC_NDIGITS(key));
2759 
2760  /*
2761  * Note that we don't hash on the Numeric's scale, since two numerics can
2762  * compare equal but have different scales. We also don't hash on the
2763  * sign, although we could: since a sign difference implies inequality,
2764  * this shouldn't affect correctness.
2765  */
2766  hash_len = NUMERIC_NDIGITS(key) - start_offset - end_offset;
2767  digit_hash = hash_any((unsigned char *) (NUMERIC_DIGITS(key) + start_offset),
2768  hash_len * sizeof(NumericDigit));
2769 
2770  /* Mix in the weight, via XOR */
2771  result = digit_hash ^ weight;
2772 
2773  PG_RETURN_DATUM(result);
2774 }
#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 2781 of file numeric.c.

2782 {
2784  uint64 seed = PG_GETARG_INT64(1);
2785  Datum digit_hash;
2786  Datum result;
2787  int weight;
2788  int start_offset;
2789  int end_offset;
2790  int i;
2791  int hash_len;
2793 
2794  /* If it's NaN or infinity, don't try to hash the rest of the fields */
2795  if (NUMERIC_IS_SPECIAL(key))
2796  PG_RETURN_UINT64(seed);
2797 
2798  weight = NUMERIC_WEIGHT(key);
2799  start_offset = 0;
2800  end_offset = 0;
2801 
2803  for (i = 0; i < NUMERIC_NDIGITS(key); i++)
2804  {
2805  if (digits[i] != (NumericDigit) 0)
2806  break;
2807 
2808  start_offset++;
2809 
2810  weight--;
2811  }
2812 
2813  if (NUMERIC_NDIGITS(key) == start_offset)
2814  PG_RETURN_UINT64(seed - 1);
2815 
2816  for (i = NUMERIC_NDIGITS(key) - 1; i >= 0; i--)
2817  {
2818  if (digits[i] != (NumericDigit) 0)
2819  break;
2820 
2821  end_offset++;
2822  }
2823 
2824  Assert(start_offset + end_offset < NUMERIC_NDIGITS(key));
2825 
2826  hash_len = NUMERIC_NDIGITS(key) - start_offset - end_offset;
2827  digit_hash = hash_any_extended((unsigned char *) (NUMERIC_DIGITS(key)
2828  + start_offset),
2829  hash_len * sizeof(NumericDigit),
2830  seed);
2831 
2832  result = UInt64GetDatum(DatumGetUInt64(digit_hash) ^ weight);
2833 
2834  PG_RETURN_DATUM(result);
2835 }
#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 2566 of file numeric.c.

2567 {
2569  Numeric base = PG_GETARG_NUMERIC(1);
2570  Numeric offset = PG_GETARG_NUMERIC(2);
2571  bool sub = PG_GETARG_BOOL(3);
2572  bool less = PG_GETARG_BOOL(4);
2573  bool result;
2574 
2575  /*
2576  * Reject negative (including -Inf) or NaN offset. Negative is per spec,
2577  * and NaN is because appropriate semantics for that seem non-obvious.
2578  */
2579  if (NUMERIC_IS_NAN(offset) ||
2580  NUMERIC_IS_NINF(offset) ||
2581  NUMERIC_SIGN(offset) == NUMERIC_NEG)
2582  ereport(ERROR,
2583  (errcode(ERRCODE_INVALID_PRECEDING_OR_FOLLOWING_SIZE),
2584  errmsg("invalid preceding or following size in window function")));
2585 
2586  /*
2587  * Deal with cases where val and/or base is NaN, following the rule that
2588  * NaN sorts after non-NaN (cf cmp_numerics). The offset cannot affect
2589  * the conclusion.
2590  */
2591  if (NUMERIC_IS_NAN(val))
2592  {
2593  if (NUMERIC_IS_NAN(base))
2594  result = true; /* NAN = NAN */
2595  else
2596  result = !less; /* NAN > non-NAN */
2597  }
2598  else if (NUMERIC_IS_NAN(base))
2599  {
2600  result = less; /* non-NAN < NAN */
2601  }
2602 
2603  /*
2604  * Deal with infinite offset (necessarily +Inf, at this point).
2605  */
2606  else if (NUMERIC_IS_SPECIAL(offset))
2607  {
2608  Assert(NUMERIC_IS_PINF(offset));
2609  if (sub ? NUMERIC_IS_PINF(base) : NUMERIC_IS_NINF(base))
2610  {
2611  /*
2612  * base +/- offset would produce NaN, so return true for any val
2613  * (see in_range_float8_float8() for reasoning).
2614  */
2615  result = true;
2616  }
2617  else if (sub)
2618  {
2619  /* base - offset must be -inf */
2620  if (less)
2621  result = NUMERIC_IS_NINF(val); /* only -inf is <= sum */
2622  else
2623  result = true; /* any val is >= sum */
2624  }
2625  else
2626  {
2627  /* base + offset must be +inf */
2628  if (less)
2629  result = true; /* any val is <= sum */
2630  else
2631  result = NUMERIC_IS_PINF(val); /* only +inf is >= sum */
2632  }
2633  }
2634 
2635  /*
2636  * Deal with cases where val and/or base is infinite. The offset, being
2637  * now known finite, cannot affect the conclusion.
2638  */
2639  else if (NUMERIC_IS_SPECIAL(val))
2640  {
2641  if (NUMERIC_IS_PINF(val))
2642  {
2643  if (NUMERIC_IS_PINF(base))
2644  result = true; /* PINF = PINF */
2645  else
2646  result = !less; /* PINF > any other non-NAN */
2647  }
2648  else /* val must be NINF */
2649  {
2650  if (NUMERIC_IS_NINF(base))
2651  result = true; /* NINF = NINF */
2652  else
2653  result = less; /* NINF < anything else */
2654  }
2655  }
2656  else if (NUMERIC_IS_SPECIAL(base))
2657  {
2658  if (NUMERIC_IS_NINF(base))
2659  result = !less; /* normal > NINF */
2660  else
2661  result = less; /* normal < PINF */
2662  }
2663  else
2664  {
2665  /*
2666  * Otherwise go ahead and compute base +/- offset. While it's
2667  * possible for this to overflow the numeric format, it's unlikely
2668  * enough that we don't take measures to prevent it.
2669  */
2670  NumericVar valv;
2671  NumericVar basev;
2672  NumericVar offsetv;
2673  NumericVar sum;
2674 
2675  init_var_from_num(val, &valv);
2676  init_var_from_num(base, &basev);
2677  init_var_from_num(offset, &offsetv);
2678  init_var(&sum);
2679 
2680  if (sub)
2681  sub_var(&basev, &offsetv, &sum);
2682  else
2683  add_var(&basev, &offsetv, &sum);
2684 
2685  if (less)
2686  result = (cmp_var(&valv, &sum) <= 0);
2687  else
2688  result = (cmp_var(&valv, &sum) >= 0);
2689 
2690  free_var(&sum);
2691  }
2692 
2693  PG_FREE_IF_COPY(val, 0);
2694  PG_FREE_IF_COPY(base, 1);
2695  PG_FREE_IF_COPY(offset, 2);
2696 
2697  PG_RETURN_BOOL(result);
2698 }
#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 5554 of file numeric.c.

5555 {
5557 
5558  state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
5559 
5560  /* Create the state data on the first call */
5561  if (state == NULL)
5562  state = makePolyNumAggState(fcinfo, true);
5563 
5564  if (!PG_ARGISNULL(1))
5565  {
5566 #ifdef HAVE_INT128
5567  do_int128_accum(state, (int128) PG_GETARG_INT16(1));
5568 #else
5570 #endif
5571  }
5572 
5574 }
#define makePolyNumAggState
Definition: numeric.c:5549
Numeric int64_to_numeric(int64 val)
Definition: numeric.c:4287
static void do_numeric_accum(NumericAggState *state, Numeric newval)
Definition: numeric.c:4861
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:276
#define PG_ARGISNULL(n)
Definition: fmgr.h:209
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:361
#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 5978 of file numeric.c.

5979 {
5981 
5982  state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
5983 
5984  /* Should not get here with no state */
5985  if (state == NULL)
5986  elog(ERROR, "int2_accum_inv called with NULL state");
5987 
5988  if (!PG_ARGISNULL(1))
5989  {
5990 #ifdef HAVE_INT128
5991  do_int128_discard(state, (int128) PG_GETARG_INT16(1));
5992 #else
5993  /* Should never fail, all inputs have dscale 0 */
5995  elog(ERROR, "do_numeric_discard failed unexpectedly");
5996 #endif
5997  }
5998 
6000 }
static bool do_numeric_discard(NumericAggState *state, Numeric newval)
Definition: numeric.c:4931
#define elog(elevel,...)
Definition: elog.h:224

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

6662 {
6663  ArrayType *transarray;
6665  Int8TransTypeData *transdata;
6666 
6667  /*
6668  * If we're invoked as an aggregate, we can cheat and modify our first
6669  * parameter in-place to reduce palloc overhead. Otherwise we need to make
6670  * a copy of it before scribbling on it.
6671  */
6672  if (AggCheckCallContext(fcinfo, NULL))
6673  transarray = PG_GETARG_ARRAYTYPE_P(0);
6674  else
6675  transarray = PG_GETARG_ARRAYTYPE_P_COPY(0);
6676 
6677  if (ARR_HASNULL(transarray) ||
6678  ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
6679  elog(ERROR, "expected 2-element int8 array");
6680 
6681  transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
6682  transdata->count++;
6683  transdata->sum += newval;
6684 
6685  PG_RETURN_ARRAYTYPE_P(transarray);
6686 }
#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:4511

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

6749 {
6750  ArrayType *transarray;
6752  Int8TransTypeData *transdata;
6753 
6754  /*
6755  * If we're invoked as an aggregate, we can cheat and modify our first
6756  * parameter in-place to reduce palloc overhead. Otherwise we need to make
6757  * a copy of it before scribbling on it.
6758  */
6759  if (AggCheckCallContext(fcinfo, NULL))
6760  transarray = PG_GETARG_ARRAYTYPE_P(0);
6761  else
6762  transarray = PG_GETARG_ARRAYTYPE_P_COPY(0);
6763 
6764  if (ARR_HASNULL(transarray) ||
6765  ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
6766  elog(ERROR, "expected 2-element int8 array");
6767 
6768  transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
6769  transdata->count--;
6770  transdata->sum -= newval;
6771 
6772  PG_RETURN_ARRAYTYPE_P(transarray);
6773 }

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

4549 {
4550  int16 val = PG_GETARG_INT16(0);
4551 
4553 }

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

6513 {
6514  int64 newval;
6515 
6516  if (PG_ARGISNULL(0))
6517  {
6518  /* No non-null input seen so far... */
6519  if (PG_ARGISNULL(1))
6520  PG_RETURN_NULL(); /* still no non-null */
6521  /* This is the first non-null input. */
6522  newval = (int64) PG_GETARG_INT16(1);
6524  }
6525 
6526  /*
6527  * If we're invoked as an aggregate, we can cheat and modify our first
6528  * parameter in-place to avoid palloc overhead. If not, we need to return
6529  * the new value of the transition variable. (If int8 is pass-by-value,
6530  * then of course this is useless as well as incorrect, so just ifdef it
6531  * out.)
6532  */
6533 #ifndef USE_FLOAT8_BYVAL /* controls int8 too */
6534  if (AggCheckCallContext(fcinfo, NULL))
6535  {
6536  int64 *oldsum = (int64 *) PG_GETARG_POINTER(0);
6537 
6538  /* Leave the running sum unchanged in the new input is null */
6539  if (!PG_ARGISNULL(1))
6540  *oldsum = *oldsum + (int64) PG_GETARG_INT16(1);
6541 
6542  PG_RETURN_POINTER(oldsum);
6543  }
6544  else
6545 #endif
6546  {
6547  int64 oldsum = PG_GETARG_INT64(0);
6548 
6549  /* Leave sum unchanged if new input is null. */
6550  if (PG_ARGISNULL(1))
6551  PG_RETURN_INT64(oldsum);
6552 
6553  /* OK to do the addition. */
6554  newval = oldsum + (int64) PG_GETARG_INT16(1);
6555 
6557  }
6558 }
#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 6831 of file numeric.c.

6832 {
6833  ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
6834  Int8TransTypeData *transdata;
6835 
6836  if (ARR_HASNULL(transarray) ||
6837  ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
6838  elog(ERROR, "expected 2-element int8 array");
6839  transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
6840 
6841  /* SQL defines SUM of no values to be NULL */
6842  if (transdata->count == 0)
6843  PG_RETURN_NULL();
6844 
6845  PG_RETURN_DATUM(Int64GetDatumFast(transdata->sum));
6846 }
#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 5577 of file numeric.c.

5578 {
5580 
5581  state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
5582 
5583  /* Create the state data on the first call */
5584  if (state == NULL)
5585  state = makePolyNumAggState(fcinfo, true);
5586 
5587  if (!PG_ARGISNULL(1))
5588  {
5589 #ifdef HAVE_INT128
5590  do_int128_accum(state, (int128) PG_GETARG_INT32(1));
5591 #else
5593 #endif
5594  }
5595 
5597 }
#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 6003 of file numeric.c.

6004 {
6006 
6007  state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
6008 
6009  /* Should not get here with no state */
6010  if (state == NULL)
6011  elog(ERROR, "int4_accum_inv called with NULL state");
6012 
6013  if (!PG_ARGISNULL(1))
6014  {
6015 #ifdef HAVE_INT128
6016  do_int128_discard(state, (int128) PG_GETARG_INT32(1));
6017 #else
6018  /* Should never fail, all inputs have dscale 0 */
6020  elog(ERROR, "do_numeric_discard failed unexpectedly");
6021 #endif
6022  }
6023 
6025 }

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

6690 {
6691  ArrayType *transarray;
6693  Int8TransTypeData *transdata;
6694 
6695  /*
6696  * If we're invoked as an aggregate, we can cheat and modify our first
6697  * parameter in-place to reduce palloc overhead. Otherwise we need to make
6698  * a copy of it before scribbling on it.
6699  */
6700  if (AggCheckCallContext(fcinfo, NULL))
6701  transarray = PG_GETARG_ARRAYTYPE_P(0);
6702  else
6703  transarray = PG_GETARG_ARRAYTYPE_P_COPY(0);
6704 
6705  if (ARR_HASNULL(transarray) ||
6706  ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
6707  elog(ERROR, "expected 2-element int8 array");
6708 
6709  transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
6710  transdata->count++;
6711  transdata->sum += newval;
6712 
6713  PG_RETURN_ARRAYTYPE_P(transarray);
6714 }

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

6777 {
6778  ArrayType *transarray;
6780  Int8TransTypeData *transdata;
6781 
6782  /*
6783  * If we're invoked as an aggregate, we can cheat and modify our first
6784  * parameter in-place to reduce palloc overhead. Otherwise we need to make
6785  * a copy of it before scribbling on it.
6786  */
6787  if (AggCheckCallContext(fcinfo, NULL))
6788  transarray = PG_GETARG_ARRAYTYPE_P(0);
6789  else
6790  transarray = PG_GETARG_ARRAYTYPE_P_COPY(0);
6791 
6792  if (ARR_HASNULL(transarray) ||
6793  ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
6794  elog(ERROR, "expected 2-element int8 array");
6795 
6796  transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
6797  transdata->count--;
6798  transdata->sum -= newval;
6799 
6800  PG_RETURN_ARRAYTYPE_P(transarray);
6801 }

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

6718 {
6719  ArrayType *transarray1;
6720  ArrayType *transarray2;
6721  Int8TransTypeData *state1;
6722  Int8TransTypeData *state2;
6723 
6724  if (!AggCheckCallContext(fcinfo, NULL))
6725  elog(ERROR, "aggregate function called in non-aggregate context");
6726 
6727  transarray1 = PG_GETARG_ARRAYTYPE_P(0);
6728  transarray2 = PG_GETARG_ARRAYTYPE_P(1);
6729 
6730  if (ARR_HASNULL(transarray1) ||
6731  ARR_SIZE(transarray1) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
6732  elog(ERROR, "expected 2-element int8 array");
6733 
6734  if (ARR_HASNULL(transarray2) ||
6735  ARR_SIZE(transarray2) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
6736  elog(ERROR, "expected 2-element int8 array");
6737 
6738  state1 = (Int8TransTypeData *) ARR_DATA_PTR(transarray1);
6739  state2 = (Int8TransTypeData *) ARR_DATA_PTR(transarray2);
6740 
6741  state1->count += state2->count;
6742  state1->sum += state2->sum;
6743 
6744  PG_RETURN_ARRAYTYPE_P(transarray1);
6745 }

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

4394 {
4395  int32 val = PG_GETARG_INT32(0);
4396 
4398 }

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

6562 {
6563  int64 newval;
6564 
6565  if (PG_ARGISNULL(0))
6566  {
6567  /* No non-null input seen so far... */
6568  if (PG_ARGISNULL(1))
6569  PG_RETURN_NULL(); /* still no non-null */
6570  /* This is the first non-null input. */
6571  newval = (int64) PG_GETARG_INT32(1);
6573  }
6574 
6575  /*
6576  * If we're invoked as an aggregate, we can cheat and modify our first
6577  * parameter in-place to avoid palloc overhead. If not, we need to return
6578  * the new value of the transition variable. (If int8 is pass-by-value,
6579  * then of course this is useless as well as incorrect, so just ifdef it
6580  * out.)
6581  */
6582 #ifndef USE_FLOAT8_BYVAL /* controls int8 too */
6583  if (AggCheckCallContext(fcinfo, NULL))
6584  {
6585  int64 *oldsum = (int64 *) PG_GETARG_POINTER(0);
6586 
6587  /* Leave the running sum unchanged in the new input is null */
6588  if (!PG_ARGISNULL(1))
6589  *oldsum = *oldsum + (int64) PG_GETARG_INT32(1);
6590 
6591  PG_RETURN_POINTER(oldsum);
6592  }
6593  else
6594 #endif
6595  {
6596  int64 oldsum = PG_GETARG_INT64(0);
6597 
6598  /* Leave sum unchanged if new input is null. */
6599  if (PG_ARGISNULL(1))
6600  PG_RETURN_INT64(oldsum);
6601 
6602  /* OK to do the addition. */
6603  newval = oldsum + (int64) PG_GETARG_INT32(1);
6604 
6606  }
6607 }

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

4309 {
4310  Numeric res;
4311  NumericVar result;
4312  int rscale;
4313  int w;
4314  int m;
4315 
4316  init_var(&result);
4317 
4318  /* result scale */
4319  rscale = log10val2 < 0 ? 0 : log10val2;
4320 
4321  /* how much to decrease the weight by */
4322  w = log10val2 / DEC_DIGITS;
4323  /* how much is left to divide by */
4324  m = log10val2 % DEC_DIGITS;
4325  if (m < 0)
4326  {
4327  m += DEC_DIGITS;
4328  w--;
4329  }
4330 
4331  /*
4332  * If there is anything left to divide by (10^m with 0 < m < DEC_DIGITS),
4333  * multiply the dividend by 10^(DEC_DIGITS - m), and shift the weight by
4334  * one more.
4335  */
4336  if (m > 0)
4337  {
4338 #if DEC_DIGITS == 4
4339  static const int pow10[] = {1, 10, 100, 1000};
4340 #elif DEC_DIGITS == 2
4341  static const int pow10[] = {1, 10};
4342 #elif DEC_DIGITS == 1
4343  static const int pow10[] = {1};
4344 #else
4345 #error unsupported NBASE
4346 #endif
4347  int64 factor = pow10[DEC_DIGITS - m];
4348  int64 new_val1;
4349 
4350  StaticAssertDecl(lengthof(pow10) == DEC_DIGITS, "mismatch with DEC_DIGITS");
4351 
4352  if (unlikely(pg_mul_s64_overflow(val1, factor, &new_val1)))
4353  {
4354 #ifdef HAVE_INT128
4355  /* do the multiplication using 128-bit integers */
4356  int128 tmp;
4357 
4358  tmp = (int128) val1 * (int128) factor;
4359 
4360  int128_to_numericvar(tmp, &result);
4361 #else
4362  /* do the multiplication using numerics */
4363  NumericVar tmp;
4364 
4365  init_var(&tmp);
4366 
4367  int64_to_numericvar(val1, &result);
4368  int64_to_numericvar(factor, &tmp);
4369  mul_var(&result, &tmp, &result, 0);
4370 
4371  free_var(&tmp);
4372 #endif
4373  }
4374  else
4375  int64_to_numericvar(new_val1, &result);
4376 
4377  w++;
4378  }
4379  else
4380  int64_to_numericvar(val1, &result);
4381 
4382  result.weight -= w;
4383  result.dscale = rscale;
4384 
4385  res = make_result(&result);
4386 
4387  free_var(&result);
4388 
4389  return res;
4390 }
static void int64_to_numericvar(int64 val, NumericVar *var)
Definition: numeric.c:8108
#define unlikely(x)
Definition: c.h:311
#define lengthof(array)
Definition: c.h:788
#define StaticAssertDecl(condition, errmessage)
Definition: c.h:936
static bool pg_mul_s64_overflow(int64 a, int64 b, int64 *result)
Definition: int.h:219

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

8109 {
8110  uint64 uval,
8111  newuval;
8112  NumericDigit *ptr;
8113  int ndigits;
8114 
8115  /* int64 can require at most 19 decimal digits; add one for safety */
8116  alloc_var(var, 20 / DEC_DIGITS);
8117  if (val < 0)
8118  {
8119  var->sign = NUMERIC_NEG;
8120  uval = -val;
8121  }
8122  else
8123  {
8124  var->sign = NUMERIC_POS;
8125  uval = val;
8126  }
8127  var->dscale = 0;
8128  if (val == 0)
8129  {
8130  var->ndigits = 0;
8131  var->weight = 0;
8132  return;
8133  }
8134  ptr = var->digits + var->ndigits;
8135  ndigits = 0;
8136  do
8137  {
8138  ptr--;
8139  ndigits++;
8140  newuval = uval / NBASE;
8141  *ptr = uval - newuval * NBASE;
8142  uval = newuval;
8143  } while (uval);
8144  var->digits = ptr;
8145  var->ndigits = ndigits;
8146  var->weight = ndigits - 1;
8147 }

References alloc_var(), DEC_DIGITS, NumericVar::digits, NumericVar::dscale, NBASE, NumericVar::ndigits, NUMERIC_NEG, NUMERIC_POS, 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 5600 of file numeric.c.

5601 {
5603 
5604  state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
5605 
5606  /* Create the state data on the first call */
5607  if (state == NULL)
5608  state = makeNumericAggState(fcinfo, true);
5609 
5610  if (!PG_ARGISNULL(1))
5612 
5614 }
static NumericAggState * makeNumericAggState(FunctionCallInfo fcinfo, bool calcSumX2)
Definition: numeric.c:4821

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

6029 {
6031 
6032  state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
6033 
6034  /* Should not get here with no state */
6035  if (state == NULL)
6036  elog(ERROR, "int8_accum_inv called with NULL state");
6037 
6038  if (!PG_ARGISNULL(1))
6039  {
6040  /* Should never fail, all inputs have dscale 0 */
6042  elog(ERROR, "do_numeric_discard failed unexpectedly");
6043  }
6044 
6046 }

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

6805 {
6806  ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
6807  Int8TransTypeData *transdata;
6808  Datum countd,
6809  sumd;
6810 
6811  if (ARR_HASNULL(transarray) ||
6812  ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
6813  elog(ERROR, "expected 2-element int8 array");
6814  transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
6815 
6816  /* SQL defines AVG of no values to be NULL */
6817  if (transdata->count == 0)
6818  PG_RETURN_NULL();
6819 
6820  countd = NumericGetDatum(int64_to_numeric(transdata->count));
6821  sumd = NumericGetDatum(int64_to_numeric(transdata->sum));
6822 
6824 }
Datum numeric_div(PG_FUNCTION_ARGS)
Definition: numeric.c:3128
#define DirectFunctionCall2(func, arg1, arg2)
Definition: fmgr.h:644

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

5797 {
5799 
5800  state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
5801 
5802  /* Create the state data on the first call */
5803  if (state == NULL)
5804  state = makePolyNumAggState(fcinfo, false);
5805 
5806  if (!PG_ARGISNULL(1))
5807  {
5808 #ifdef HAVE_INT128
5809  do_int128_accum(state, (int128) PG_GETARG_INT64(1));
5810 #else
5812 #endif
5813  }
5814 
5816 }

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

6050 {
6052 
6053  state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
6054 
6055  /* Should not get here with no state */
6056  if (state == NULL)
6057  elog(ERROR, "int8_avg_accum_inv called with NULL state");
6058 
6059  if (!PG_ARGISNULL(1))
6060  {
6061 #ifdef HAVE_INT128
6062  do_int128_discard(state, (int128) PG_GETARG_INT64(1));
6063 #else
6064  /* Should never fail, all inputs have dscale 0 */
6066  elog(ERROR, "do_numeric_discard failed unexpectedly");
6067 #endif
6068  }
6069 
6071 }

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

5824 {
5825  PolyNumAggState *state1;
5826  PolyNumAggState *state2;
5827  MemoryContext agg_context;
5828  MemoryContext old_context;
5829 
5830  if (!AggCheckCallContext(fcinfo, &agg_context))
5831  elog(ERROR, "aggregate function called in non-aggregate context");
5832 
5833  state1 = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
5834  state2 = PG_ARGISNULL(1) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(1);
5835 
5836  if (state2 == NULL)
5837  PG_RETURN_POINTER(state1);
5838 
5839  /* manually copy all fields from state2 to state1 */
5840  if (state1 == NULL)
5841  {
5842  old_context = MemoryContextSwitchTo(agg_context);
5843 
5844  state1 = makePolyNumAggState(fcinfo, false);
5845  state1->N = state2->N;
5846 
5847 #ifdef HAVE_INT128
5848  state1->sumX = state2->sumX;
5849 #else
5850  accum_sum_copy(&state1->sumX, &state2->sumX);
5851 #endif
5852  MemoryContextSwitchTo(old_context);
5853 
5854  PG_RETURN_POINTER(state1);
5855  }
5856 
5857  if (state2->N > 0)
5858  {
5859  state1->N += state2->N;
5860 
5861 #ifdef HAVE_INT128
5862  state1->sumX += state2->sumX;
5863 #else
5864  /* The rest of this needs to work in the aggregate context */
5865  old_context = MemoryContextSwitchTo(agg_context);
5866 
5867  /* Accumulate sums */
5868  accum_sum_combine(&state1->sumX, &state2->sumX);
5869 
5870  MemoryContextSwitchTo(old_context);
5871 #endif
5872 
5873  }
5874  PG_RETURN_POINTER(state1);
5875 }
static void accum_sum_combine(NumericSumAccum *accum, NumericSumAccum *accum2)
Definition: numeric.c:12474
static void accum_sum_copy(NumericSumAccum *dst, NumericSumAccum *src)
Definition: numeric.c:12457
NumericSumAccum sumX
Definition: numeric.c:4803

References accum_sum_combine(), accum_sum_copy(), AggCheckCallContext(), elog, ERROR, makePolyNumAggState, MemoryContextSwitchTo(), NumericAggState::N, PG_ARGISNULL, PG_GETARG_POINTER, PG_RETURN_POINTER, and NumericAggState::sumX.

◆ int8_avg_deserialize()

Datum int8_avg_deserialize ( PG_FUNCTION_ARGS  )

Definition at line 5932 of file numeric.c.

5933 {
5934  bytea *sstate;
5935  PolyNumAggState *result;
5937  NumericVar tmp_var;
5938 
5939  if (!AggCheckCallContext(fcinfo, NULL))
5940  elog(ERROR, "aggregate function called in non-aggregate context");
5941 
5942  sstate = PG_GETARG_BYTEA_PP(0);
5943 
5944  init_var(&tmp_var);
5945 
5946  /*
5947  * Initialize a StringInfo so that we can "receive" it using the standard
5948  * recv-function infrastructure.
5949  */
5951  VARSIZE_ANY_EXHDR(sstate));
5952 
5953  result = makePolyNumAggStateCurrentContext(false);
5954 
5955  /* N */
5956  result->N = pq_getmsgint64(&buf);
5957 
5958  /* sumX */
5959  numericvar_deserialize(&buf, &tmp_var);
5960 #ifdef HAVE_INT128
5961  numericvar_to_int128(&tmp_var, &result->sumX);
5962 #else
5963  accum_sum_add(&result->sumX, &tmp_var);
5964 #endif
5965 
5966  pq_getmsgend(&buf);
5967 
5968  free_var(&tmp_var);
5969 
5970  PG_RETURN_POINTER(result);
5971 }
static void numericvar_deserialize(StringInfo buf, NumericVar *var)
Definition: numeric.c:7744
#define makePolyNumAggStateCurrentContext
Definition: numeric.c:5550
#define PG_GETARG_BYTEA_PP(n)
Definition: fmgr.h:308
void pq_getmsgend(StringInfo msg)
Definition: pqformat.c:635
int64 pq_getmsgint64(StringInfo msg)
Definition: pqformat.c:453
static void initReadOnlyStringInfo(StringInfo str, char *data, int len)
Definition: stringinfo.h:130
Definition: c.h:687
#define VARDATA_ANY(PTR)
Definition: varatt.h:324
#define VARSIZE_ANY_EXHDR(PTR)
Definition: varatt.h:317

References accum_sum_add(), AggCheckCallContext(), buf, elog, ERROR, free_var(), init_var, initReadOnlyStringInfo(), makePolyNumAggStateCurrentContext, NumericAggState::N, numericvar_deserialize(), PG_GETARG_BYTEA_PP, PG_RETURN_POINTER, pq_getmsgend(), pq_getmsgint64(), NumericAggState::sumX, VARDATA_ANY, and VARSIZE_ANY_EXHDR.

◆ int8_avg_serialize()

Datum int8_avg_serialize ( PG_FUNCTION_ARGS  )

Definition at line 5883 of file