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_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 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, bool reversed_bounds, 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 403 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 476 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 478 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 472 of file numeric.c.

◆ dump_var

#define dump_var (   s,
 
)

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

◆ makePolyNumAggState

#define makePolyNumAggState   makeNumericAggState

Definition at line 5545 of file numeric.c.

◆ makePolyNumAggStateCurrentContext

#define makePolyNumAggStateCurrentContext   makeNumericAggStateCurrentContext

Definition at line 5546 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 4809 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 394 of file numeric.c.

◆ NUMERIC_ABBREV_NAN

#define NUMERIC_ABBREV_NAN   NumericAbbrevGetDatum(PG_INT32_MIN)

Definition at line 404 of file numeric.c.

◆ NUMERIC_ABBREV_NINF

#define NUMERIC_ABBREV_NINF   NumericAbbrevGetDatum(PG_INT32_MAX)

Definition at line 406 of file numeric.c.

◆ NUMERIC_ABBREV_PINF

#define NUMERIC_ABBREV_PINF   NumericAbbrevGetDatum(-PG_INT32_MAX)

Definition at line 405 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
int scale
Definition: pgbench.c:181

Definition at line 490 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 486 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 488 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.

◆ NumericAbbrevGetDatum

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

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

Function Documentation

◆ accum_sum_add()

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

Definition at line 11974 of file numeric.c.

11975 {
11976  int32 *accum_digits;
11977  int i,
11978  val_i;
11979  int val_ndigits;
11980  NumericDigit *val_digits;
11981 
11982  /*
11983  * If we have accumulated too many values since the last carry
11984  * propagation, do it now, to avoid overflowing. (We could allow more
11985  * than NBASE - 1, if we reserved two extra digits, rather than one, for
11986  * carry propagation. But even with NBASE - 1, this needs to be done so
11987  * seldom, that the performance difference is negligible.)
11988  */
11989  if (accum->num_uncarried == NBASE - 1)
11990  accum_sum_carry(accum);
11991 
11992  /*
11993  * Adjust the weight or scale of the old value, so that it can accommodate
11994  * the new value.
11995  */
11996  accum_sum_rescale(accum, val);
11997 
11998  /* */
11999  if (val->sign == NUMERIC_POS)
12000  accum_digits = accum->pos_digits;
12001  else
12002  accum_digits = accum->neg_digits;
12003 
12004  /* copy these values into local vars for speed in loop */
12005  val_ndigits = val->ndigits;
12006  val_digits = val->digits;
12007 
12008  i = accum->weight - val->weight;
12009  for (val_i = 0; val_i < val_ndigits; val_i++)
12010  {
12011  accum_digits[i] += (int32) val_digits[val_i];
12012  i++;
12013  }
12014 
12015  accum->num_uncarried++;
12016 }
static void accum_sum_carry(NumericSumAccum *accum)
Definition: numeric.c:12022
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:12095
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:377
int num_uncarried
Definition: numeric.c:375
int32 * neg_digits
Definition: numeric.c:378

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

12023 {
12024  int i;
12025  int ndigits;
12026  int32 *dig;
12027  int32 carry;
12028  int32 newdig = 0;
12029 
12030  /*
12031  * If no new values have been added since last carry propagation, nothing
12032  * to do.
12033  */
12034  if (accum->num_uncarried == 0)
12035  return;
12036 
12037  /*
12038  * We maintain that the weight of the accumulator is always one larger
12039  * than needed to hold the current value, before carrying, to make sure
12040  * there is enough space for the possible extra digit when carry is
12041  * propagated. We cannot expand the buffer here, unless we require
12042  * callers of accum_sum_final() to switch to the right memory context.
12043  */
12044  Assert(accum->pos_digits[0] == 0 && accum->neg_digits[0] == 0);
12045 
12046  ndigits = accum->ndigits;
12047 
12048  /* Propagate carry in the positive sum */
12049  dig = accum->pos_digits;
12050  carry = 0;
12051  for (i = ndigits - 1; i >= 0; i--)
12052  {
12053  newdig = dig[i] + carry;
12054  if (newdig >= NBASE)
12055  {
12056  carry = newdig / NBASE;
12057  newdig -= carry * NBASE;
12058  }
12059  else
12060  carry = 0;
12061  dig[i] = newdig;
12062  }
12063  /* Did we use up the digit reserved for carry propagation? */
12064  if (newdig > 0)
12065  accum->have_carry_space = false;
12066 
12067  /* And the same for the negative sum */
12068  dig = accum->neg_digits;
12069  carry = 0;
12070  for (i = ndigits - 1; i >= 0; i--)
12071  {
12072  newdig = dig[i] + carry;
12073  if (newdig >= NBASE)
12074  {
12075  carry = newdig / NBASE;
12076  newdig -= carry * NBASE;
12077  }
12078  else
12079  carry = 0;
12080  dig[i] = newdig;
12081  }
12082  if (newdig > 0)
12083  accum->have_carry_space = false;
12084 
12085  accum->num_uncarried = 0;
12086 }
#define Assert(condition)
Definition: c.h:858
bool have_carry_space
Definition: numeric.c:376

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

12253 {
12254  NumericVar tmp_var;
12255 
12256  init_var(&tmp_var);
12257 
12258  accum_sum_final(accum2, &tmp_var);
12259  accum_sum_add(accum, &tmp_var);
12260 
12261  free_var(&tmp_var);
12262 }
static void accum_sum_final(NumericSumAccum *accum, NumericVar *result)
Definition: numeric.c:12184
static void free_var(NumericVar *var)
Definition: numeric.c:6969
static void accum_sum_add(NumericSumAccum *accum, const NumericVar *val)
Definition: numeric.c:11974
#define init_var(v)
Definition: numeric.c:484

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

12236 {
12237  dst->pos_digits = palloc(src->ndigits * sizeof(int32));
12238  dst->neg_digits = palloc(src->ndigits * sizeof(int32));
12239 
12240  memcpy(dst->pos_digits, src->pos_digits, src->ndigits * sizeof(int32));
12241  memcpy(dst->neg_digits, src->neg_digits, src->ndigits * sizeof(int32));
12242  dst->num_uncarried = src->num_uncarried;
12243  dst->ndigits = src->ndigits;
12244  dst->weight = src->weight;
12245  dst->dscale = src->dscale;
12246 }
void * palloc(Size size)
Definition: mcxt.c:1316

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

12185 {
12186  int i;
12187  NumericVar pos_var;
12188  NumericVar neg_var;
12189 
12190  if (accum->ndigits == 0)
12191  {
12192  set_var_from_var(&const_zero, result);
12193  return;
12194  }
12195 
12196  /* Perform final carry */
12197  accum_sum_carry(accum);
12198 
12199  /* Create NumericVars representing the positive and negative sums */
12200  init_var(&pos_var);
12201  init_var(&neg_var);
12202 
12203  pos_var.ndigits = neg_var.ndigits = accum->ndigits;
12204  pos_var.weight = neg_var.weight = accum->weight;
12205  pos_var.dscale = neg_var.dscale = accum->dscale;
12206  pos_var.sign = NUMERIC_POS;
12207  neg_var.sign = NUMERIC_NEG;
12208 
12209  pos_var.buf = pos_var.digits = digitbuf_alloc(accum->ndigits);
12210  neg_var.buf = neg_var.digits = digitbuf_alloc(accum->ndigits);
12211 
12212  for (i = 0; i < accum->ndigits; i++)
12213  {
12214  Assert(accum->pos_digits[i] < NBASE);
12215  pos_var.digits[i] = (int16) accum->pos_digits[i];
12216 
12217  Assert(accum->neg_digits[i] < NBASE);
12218  neg_var.digits[i] = (int16) accum->neg_digits[i];
12219  }
12220 
12221  /* And add them together */
12222  add_var(&pos_var, &neg_var, result);
12223 
12224  /* Remove leading/trailing zeroes */
12225  strip_var(result);
12226 }
static void add_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition: numeric.c:8431
#define NUMERIC_NEG
Definition: numeric.c:166
#define digitbuf_alloc(ndigits)
Definition: numeric.c:476
static const NumericVar const_zero
Definition: numeric.c:415
static void set_var_from_var(const NumericVar *value, NumericVar *dest)
Definition: numeric.c:7468
static void strip_var(NumericVar *var)
Definition: numeric.c:11917
int ndigits
Definition: numeric.c:305
NumericDigit * digits
Definition: numeric.c:310
int dscale
Definition: numeric.c:308
int sign
Definition: numeric.c:307
NumericDigit * buf
Definition: numeric.c:309
int weight
Definition: numeric.c:306

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

12096 {
12097  int old_weight = accum->weight;
12098  int old_ndigits = accum->ndigits;
12099  int accum_ndigits;
12100  int accum_weight;
12101  int accum_rscale;
12102  int val_rscale;
12103 
12104  accum_weight = old_weight;
12105  accum_ndigits = old_ndigits;
12106 
12107  /*
12108  * Does the new value have a larger weight? If so, enlarge the buffers,
12109  * and shift the existing value to the new weight, by adding leading
12110  * zeros.
12111  *
12112  * We enforce that the accumulator always has a weight one larger than
12113  * needed for the inputs, so that we have space for an extra digit at the
12114  * final carry-propagation phase, if necessary.
12115  */
12116  if (val->weight >= accum_weight)
12117  {
12118  accum_weight = val->weight + 1;
12119  accum_ndigits = accum_ndigits + (accum_weight - old_weight);
12120  }
12121 
12122  /*
12123  * Even though the new value is small, we might've used up the space
12124  * reserved for the carry digit in the last call to accum_sum_carry(). If
12125  * so, enlarge to make room for another one.
12126  */
12127  else if (!accum->have_carry_space)
12128  {
12129  accum_weight++;
12130  accum_ndigits++;
12131  }
12132 
12133  /* Is the new value wider on the right side? */
12134  accum_rscale = accum_ndigits - accum_weight - 1;
12135  val_rscale = val->ndigits - val->weight - 1;
12136  if (val_rscale > accum_rscale)
12137  accum_ndigits = accum_ndigits + (val_rscale - accum_rscale);
12138 
12139  if (accum_ndigits != old_ndigits ||
12140  accum_weight != old_weight)
12141  {
12142  int32 *new_pos_digits;
12143  int32 *new_neg_digits;
12144  int weightdiff;
12145 
12146  weightdiff = accum_weight - old_weight;
12147 
12148  new_pos_digits = palloc0(accum_ndigits * sizeof(int32));
12149  new_neg_digits = palloc0(accum_ndigits * sizeof(int32));
12150 
12151  if (accum->pos_digits)
12152  {
12153  memcpy(&new_pos_digits[weightdiff], accum->pos_digits,
12154  old_ndigits * sizeof(int32));
12155  pfree(accum->pos_digits);
12156 
12157  memcpy(&new_neg_digits[weightdiff], accum->neg_digits,
12158  old_ndigits * sizeof(int32));
12159  pfree(accum->neg_digits);
12160  }
12161 
12162  accum->pos_digits = new_pos_digits;
12163  accum->neg_digits = new_neg_digits;
12164 
12165  accum->weight = accum_weight;
12166  accum->ndigits = accum_ndigits;
12167 
12168  Assert(accum->pos_digits[0] == 0 && accum->neg_digits[0] == 0);
12169  accum->have_carry_space = true;
12170  }
12171 
12172  if (val->dscale > accum->dscale)
12173  accum->dscale = val->dscale;
12174 }
void pfree(void *pointer)
Definition: mcxt.c:1520
void * palloc0(Size size)
Definition: mcxt.c:1346

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

11959 {
11960  int i;
11961 
11962  accum->dscale = 0;
11963  for (i = 0; i < accum->ndigits; i++)
11964  {
11965  accum->pos_digits[i] = 0;
11966  accum->neg_digits[i] = 0;
11967  }
11968 }

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

11583 {
11584  NumericDigit *res_buf;
11585  NumericDigit *res_digits;
11586  int res_ndigits;
11587  int res_weight;
11588  int res_rscale,
11589  rscale1,
11590  rscale2;
11591  int res_dscale;
11592  int i,
11593  i1,
11594  i2;
11595  int carry = 0;
11596 
11597  /* copy these values into local vars for speed in inner loop */
11598  int var1ndigits = var1->ndigits;
11599  int var2ndigits = var2->ndigits;
11600  NumericDigit *var1digits = var1->digits;
11601  NumericDigit *var2digits = var2->digits;
11602 
11603  res_weight = Max(var1->weight, var2->weight) + 1;
11604 
11605  res_dscale = Max(var1->dscale, var2->dscale);
11606 
11607  /* Note: here we are figuring rscale in base-NBASE digits */
11608  rscale1 = var1->ndigits - var1->weight - 1;
11609  rscale2 = var2->ndigits - var2->weight - 1;
11610  res_rscale = Max(rscale1, rscale2);
11611 
11612  res_ndigits = res_rscale + res_weight + 1;
11613  if (res_ndigits <= 0)
11614  res_ndigits = 1;
11615 
11616  res_buf = digitbuf_alloc(res_ndigits + 1);
11617  res_buf[0] = 0; /* spare digit for later rounding */
11618  res_digits = res_buf + 1;
11619 
11620  i1 = res_rscale + var1->weight + 1;
11621  i2 = res_rscale + var2->weight + 1;
11622  for (i = res_ndigits - 1; i >= 0; i--)
11623  {
11624  i1--;
11625  i2--;
11626  if (i1 >= 0 && i1 < var1ndigits)
11627  carry += var1digits[i1];
11628  if (i2 >= 0 && i2 < var2ndigits)
11629  carry += var2digits[i2];
11630 
11631  if (carry >= NBASE)
11632  {
11633  res_digits[i] = carry - NBASE;
11634  carry = 1;
11635  }
11636  else
11637  {
11638  res_digits[i] = carry;
11639  carry = 0;
11640  }
11641  }
11642 
11643  Assert(carry == 0); /* else we failed to allow for carry out */
11644 
11645  digitbuf_free(result->buf);
11646  result->ndigits = res_ndigits;
11647  result->buf = res_buf;
11648  result->digits = res_digits;
11649  result->weight = res_weight;
11650  result->dscale = res_dscale;
11651 
11652  /* Remove leading/trailing zeroes */
11653  strip_var(result);
11654 }
#define digitbuf_free(buf)
Definition: numeric.c:478
#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 8431 of file numeric.c.

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

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

6954 {
6955  digitbuf_free(var->buf);
6956  var->buf = digitbuf_alloc(ndigits + 1);
6957  var->buf[0] = 0; /* spare digit for rounding */
6958  var->digits = var->buf + 1;
6959  var->ndigits = ndigits;
6960 }

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

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

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

9946 {
9947  NumericVar tmp;
9948 
9949  init_var(&tmp);
9950  set_var_from_var(var, &tmp);
9951 
9952  trunc_var(&tmp, 0);
9953 
9954  if (var->sign == NUMERIC_POS && cmp_var(var, &tmp) != 0)
9955  add_var(&tmp, &const_one, &tmp);
9956 
9957  set_var_from_var(&tmp, result);
9958  free_var(&tmp);
9959 }
static void trunc_var(NumericVar *var, int rscale)
Definition: numeric.c:11855
static int cmp_var(const NumericVar *var1, const NumericVar *var2)
Definition: numeric.c:8373
static const NumericVar const_one
Definition: numeric.c:419

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

11505 {
11506  return cmp_abs_common(var1->digits, var1->ndigits, var1->weight,
11507  var2->digits, var2->ndigits, var2->weight);
11508 }
static int cmp_abs_common(const NumericDigit *var1digits, int var1ndigits, int var1weight, const NumericDigit *var2digits, int var2ndigits, int var2weight)
Definition: numeric.c:11518

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

11520 {
11521  int i1 = 0;
11522  int i2 = 0;
11523 
11524  /* Check any digits before the first common digit */
11525 
11526  while (var1weight > var2weight && i1 < var1ndigits)
11527  {
11528  if (var1digits[i1++] != 0)
11529  return 1;
11530  var1weight--;
11531  }
11532  while (var2weight > var1weight && i2 < var2ndigits)
11533  {
11534  if (var2digits[i2++] != 0)
11535  return -1;
11536  var2weight--;
11537  }
11538 
11539  /* At this point, either w1 == w2 or we've run out of digits */
11540 
11541  if (var1weight == var2weight)
11542  {
11543  while (i1 < var1ndigits && i2 < var2ndigits)
11544  {
11545  int stat = var1digits[i1++] - var2digits[i2++];
11546 
11547  if (stat)
11548  {
11549  if (stat > 0)
11550  return 1;
11551  return -1;
11552  }
11553  }
11554  }
11555 
11556  /*
11557  * At this point, we've run out of digits on one side or the other; so any
11558  * remaining nonzero digits imply that side is larger
11559  */
11560  while (i1 < var1ndigits)
11561  {
11562  if (var1digits[i1++] != 0)
11563  return 1;
11564  }
11565  while (i2 < var2ndigits)
11566  {
11567  if (var2digits[i2++] != 0)
11568  return -1;
11569  }
11570 
11571  return 0;
11572 }

Referenced by cmp_abs(), and cmp_var_common().

◆ cmp_numerics()

static int cmp_numerics ( Numeric  num1,
Numeric  num2 
)
static

Definition at line 2505 of file numeric.c.

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

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

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

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,
bool  reversed_bounds,
NumericVar result_var 
)
static

Definition at line 1917 of file numeric.c.

1920 {
1921  NumericVar bound1_var;
1922  NumericVar bound2_var;
1923  NumericVar operand_var;
1924 
1925  init_var_from_num(bound1, &bound1_var);
1926  init_var_from_num(bound2, &bound2_var);
1927  init_var_from_num(operand, &operand_var);
1928 
1929  if (!reversed_bounds)
1930  {
1931  sub_var(&operand_var, &bound1_var, &operand_var);
1932  sub_var(&bound2_var, &bound1_var, &bound2_var);
1933  }
1934  else
1935  {
1936  sub_var(&bound1_var, &operand_var, &operand_var);
1937  sub_var(&bound1_var, &bound2_var, &bound2_var);
1938  }
1939 
1940  mul_var(&operand_var, count_var, &operand_var,
1941  operand_var.dscale + count_var->dscale);
1942  div_var(&operand_var, &bound2_var, result_var,
1943  select_div_scale(&operand_var, &bound2_var), true);
1944 
1945  /*
1946  * Roundoff in the division could give us a quotient exactly equal to
1947  * "count", which is too large. Clamp so that we do not emit a result
1948  * larger than "count".
1949  */
1950  if (cmp_var(result_var, count_var) >= 0)
1951  set_var_from_var(count_var, result_var);
1952  else
1953  {
1954  add_var(result_var, &const_one, result_var);
1955  floor_var(result_var, result_var);
1956  }
1957 
1958  free_var(&bound1_var);
1959  free_var(&bound2_var);
1960  free_var(&operand_var);
1961 }
static void sub_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition: numeric.c:8548
static void floor_var(const NumericVar *var, NumericVar *result)
Definition: numeric.c:9969
static void init_var_from_num(Numeric num, NumericVar *dest)
Definition: numeric.c:7451
static void mul_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result, int rscale)
Definition: numeric.c:8669
static int select_div_scale(const NumericVar *var1, const NumericVar *var2)
Definition: numeric.c:9777
static void div_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result, int rscale, bool round)
Definition: numeric.c:8877

References add_var(), cmp_var(), const_one, div_var(), NumericVar::dscale, floor_var(), free_var(), init_var_from_num(), mul_var(), select_div_scale(), set_var_from_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 9875 of file numeric.c.

9877 {
9878  NumericVar q;
9879  NumericVar r;
9880 
9881  init_var(&q);
9882  init_var(&r);
9883 
9884  /*
9885  * Use div_var_fast() to get an initial estimate for the integer quotient.
9886  * This might be inaccurate (per the warning in div_var_fast's comments),
9887  * but we can correct it below.
9888  */
9889  div_var_fast(var1, var2, &q, 0, false);
9890 
9891  /* Compute initial estimate of remainder using the quotient estimate. */
9892  mul_var(var2, &q, &r, var2->dscale);
9893  sub_var(var1, &r, &r);
9894 
9895  /*
9896  * Adjust the results if necessary --- the remainder should have the same
9897  * sign as var1, and its absolute value should be less than the absolute
9898  * value of var2.
9899  */
9900  while (r.ndigits != 0 && r.sign != var1->sign)
9901  {
9902  /* The absolute value of the quotient is too large */
9903  if (var1->sign == var2->sign)
9904  {
9905  sub_var(&q, &const_one, &q);
9906  add_var(&r, var2, &r);
9907  }
9908  else
9909  {
9910  add_var(&q, &const_one, &q);
9911  sub_var(&r, var2, &r);
9912  }
9913  }
9914 
9915  while (cmp_abs(&r, var2) >= 0)
9916  {
9917  /* The absolute value of the quotient is too small */
9918  if (var1->sign == var2->sign)
9919  {
9920  add_var(&q, &const_one, &q);
9921  sub_var(&r, var2, &r);
9922  }
9923  else
9924  {
9925  sub_var(&q, &const_one, &q);
9926  add_var(&r, var2, &r);
9927  }
9928  }
9929 
9930  set_var_from_var(&q, quot);
9931  set_var_from_var(&r, rem);
9932 
9933  free_var(&q);
9934  free_var(&r);
9935 }
static void div_var_fast(const NumericVar *var1, const NumericVar *var2, NumericVar *result, int rscale, bool round)
Definition: numeric.c:9185

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

8879 {
8880  int div_ndigits;
8881  int res_ndigits;
8882  int res_sign;
8883  int res_weight;
8884  int carry;
8885  int borrow;
8886  int divisor1;
8887  int divisor2;
8888  NumericDigit *dividend;
8889  NumericDigit *divisor;
8890  NumericDigit *res_digits;
8891  int i;
8892  int j;
8893 
8894  /* copy these values into local vars for speed in inner loop */
8895  int var1ndigits = var1->ndigits;
8896  int var2ndigits = var2->ndigits;
8897 
8898  /*
8899  * First of all division by zero check; we must not be handed an
8900  * unnormalized divisor.
8901  */
8902  if (var2ndigits == 0 || var2->digits[0] == 0)
8903  ereport(ERROR,
8904  (errcode(ERRCODE_DIVISION_BY_ZERO),
8905  errmsg("division by zero")));
8906 
8907  /*
8908  * If the divisor has just one or two digits, delegate to div_var_int(),
8909  * which uses fast short division.
8910  *
8911  * Similarly, on platforms with 128-bit integer support, delegate to
8912  * div_var_int64() for divisors with three or four digits.
8913  */
8914  if (var2ndigits <= 2)
8915  {
8916  int idivisor;
8917  int idivisor_weight;
8918 
8919  idivisor = var2->digits[0];
8920  idivisor_weight = var2->weight;
8921  if (var2ndigits == 2)
8922  {
8923  idivisor = idivisor * NBASE + var2->digits[1];
8924  idivisor_weight--;
8925  }
8926  if (var2->sign == NUMERIC_NEG)
8927  idivisor = -idivisor;
8928 
8929  div_var_int(var1, idivisor, idivisor_weight, result, rscale, round);
8930  return;
8931  }
8932 #ifdef HAVE_INT128
8933  if (var2ndigits <= 4)
8934  {
8935  int64 idivisor;
8936  int idivisor_weight;
8937 
8938  idivisor = var2->digits[0];
8939  idivisor_weight = var2->weight;
8940  for (i = 1; i < var2ndigits; i++)
8941  {
8942  idivisor = idivisor * NBASE + var2->digits[i];
8943  idivisor_weight--;
8944  }
8945  if (var2->sign == NUMERIC_NEG)
8946  idivisor = -idivisor;
8947 
8948  div_var_int64(var1, idivisor, idivisor_weight, result, rscale, round);
8949  return;
8950  }
8951 #endif
8952 
8953  /*
8954  * Otherwise, perform full long division.
8955  */
8956 
8957  /* Result zero check */
8958  if (var1ndigits == 0)
8959  {
8960  zero_var(result);
8961  result->dscale = rscale;
8962  return;
8963  }
8964 
8965  /*
8966  * Determine the result sign, weight and number of digits to calculate.
8967  * The weight figured here is correct if the emitted quotient has no
8968  * leading zero digits; otherwise strip_var() will fix things up.
8969  */
8970  if (var1->sign == var2->sign)
8971  res_sign = NUMERIC_POS;
8972  else
8973  res_sign = NUMERIC_NEG;
8974  res_weight = var1->weight - var2->weight;
8975  /* The number of accurate result digits we need to produce: */
8976  res_ndigits = res_weight + 1 + (rscale + DEC_DIGITS - 1) / DEC_DIGITS;
8977  /* ... but always at least 1 */
8978  res_ndigits = Max(res_ndigits, 1);
8979  /* If rounding needed, figure one more digit to ensure correct result */
8980  if (round)
8981  res_ndigits++;
8982 
8983  /*
8984  * The working dividend normally requires res_ndigits + var2ndigits
8985  * digits, but make it at least var1ndigits so we can load all of var1
8986  * into it. (There will be an additional digit dividend[0] in the
8987  * dividend space, but for consistency with Knuth's notation we don't
8988  * count that in div_ndigits.)
8989  */
8990  div_ndigits = res_ndigits + var2ndigits;
8991  div_ndigits = Max(div_ndigits, var1ndigits);
8992 
8993  /*
8994  * We need a workspace with room for the working dividend (div_ndigits+1
8995  * digits) plus room for the possibly-normalized divisor (var2ndigits
8996  * digits). It is convenient also to have a zero at divisor[0] with the
8997  * actual divisor data in divisor[1 .. var2ndigits]. Transferring the
8998  * digits into the workspace also allows us to realloc the result (which
8999  * might be the same as either input var) before we begin the main loop.
9000  * Note that we use palloc0 to ensure that divisor[0], dividend[0], and
9001  * any additional dividend positions beyond var1ndigits, start out 0.
9002  */
9003  dividend = (NumericDigit *)
9004  palloc0((div_ndigits + var2ndigits + 2) * sizeof(NumericDigit));
9005  divisor = dividend + (div_ndigits + 1);
9006  memcpy(dividend + 1, var1->digits, var1ndigits * sizeof(NumericDigit));
9007  memcpy(divisor + 1, var2->digits, var2ndigits * sizeof(NumericDigit));
9008 
9009  /*
9010  * Now we can realloc the result to hold the generated quotient digits.
9011  */
9012  alloc_var(result, res_ndigits);
9013  res_digits = result->digits;
9014 
9015  /*
9016  * The full multiple-place algorithm is taken from Knuth volume 2,
9017  * Algorithm 4.3.1D.
9018  *
9019  * We need the first divisor digit to be >= NBASE/2. If it isn't, make it
9020  * so by scaling up both the divisor and dividend by the factor "d". (The
9021  * reason for allocating dividend[0] above is to leave room for possible
9022  * carry here.)
9023  */
9024  if (divisor[1] < HALF_NBASE)
9025  {
9026  int d = NBASE / (divisor[1] + 1);
9027 
9028  carry = 0;
9029  for (i = var2ndigits; i > 0; i--)
9030  {
9031  carry += divisor[i] * d;
9032  divisor[i] = carry % NBASE;
9033  carry = carry / NBASE;
9034  }
9035  Assert(carry == 0);
9036  carry = 0;
9037  /* at this point only var1ndigits of dividend can be nonzero */
9038  for (i = var1ndigits; i >= 0; i--)
9039  {
9040  carry += dividend[i] * d;
9041  dividend[i] = carry % NBASE;
9042  carry = carry / NBASE;
9043  }
9044  Assert(carry == 0);
9045  Assert(divisor[1] >= HALF_NBASE);
9046  }
9047  /* First 2 divisor digits are used repeatedly in main loop */
9048  divisor1 = divisor[1];
9049  divisor2 = divisor[2];
9050 
9051  /*
9052  * Begin the main loop. Each iteration of this loop produces the j'th
9053  * quotient digit by dividing dividend[j .. j + var2ndigits] by the
9054  * divisor; this is essentially the same as the common manual procedure
9055  * for long division.
9056  */
9057  for (j = 0; j < res_ndigits; j++)
9058  {
9059  /* Estimate quotient digit from the first two dividend digits */
9060  int next2digits = dividend[j] * NBASE + dividend[j + 1];
9061  int qhat;
9062 
9063  /*
9064  * If next2digits are 0, then quotient digit must be 0 and there's no
9065  * need to adjust the working dividend. It's worth testing here to
9066  * fall out ASAP when processing trailing zeroes in a dividend.
9067  */
9068  if (next2digits == 0)
9069  {
9070  res_digits[j] = 0;
9071  continue;
9072  }
9073 
9074  if (dividend[j] == divisor1)
9075  qhat = NBASE - 1;
9076  else
9077  qhat = next2digits / divisor1;
9078 
9079  /*
9080  * Adjust quotient digit if it's too large. Knuth proves that after
9081  * this step, the quotient digit will be either correct or just one
9082  * too large. (Note: it's OK to use dividend[j+2] here because we
9083  * know the divisor length is at least 2.)
9084  */
9085  while (divisor2 * qhat >
9086  (next2digits - qhat * divisor1) * NBASE + dividend[j + 2])
9087  qhat--;
9088 
9089  /* As above, need do nothing more when quotient digit is 0 */
9090  if (qhat > 0)
9091  {
9092  NumericDigit *dividend_j = &dividend[j];
9093 
9094  /*
9095  * Multiply the divisor by qhat, and subtract that from the
9096  * working dividend. The multiplication and subtraction are
9097  * folded together here, noting that qhat <= NBASE (since it might
9098  * be one too large), and so the intermediate result "tmp_result"
9099  * is in the range [-NBASE^2, NBASE - 1], and "borrow" is in the
9100  * range [0, NBASE].
9101  */
9102  borrow = 0;
9103  for (i = var2ndigits; i >= 0; i--)
9104  {
9105  int tmp_result;
9106 
9107  tmp_result = dividend_j[i] - borrow - divisor[i] * qhat;
9108  borrow = (NBASE - 1 - tmp_result) / NBASE;
9109  dividend_j[i] = tmp_result + borrow * NBASE;
9110  }
9111 
9112  /*
9113  * If we got a borrow out of the top dividend digit, then indeed
9114  * qhat was one too large. Fix it, and add back the divisor to
9115  * correct the working dividend. (Knuth proves that this will
9116  * occur only about 3/NBASE of the time; hence, it's a good idea
9117  * to test this code with small NBASE to be sure this section gets
9118  * exercised.)
9119  */
9120  if (borrow)
9121  {
9122  qhat--;
9123  carry = 0;
9124  for (i = var2ndigits; i >= 0; i--)
9125  {
9126  carry += dividend_j[i] + divisor[i];
9127  if (carry >= NBASE)
9128  {
9129  dividend_j[i] = carry - NBASE;
9130  carry = 1;
9131  }
9132  else
9133  {
9134  dividend_j[i] = carry;
9135  carry = 0;
9136  }
9137  }
9138  /* A carry should occur here to cancel the borrow above */
9139  Assert(carry == 1);
9140  }
9141  }
9142 
9143  /* And we're done with this quotient digit */
9144  res_digits[j] = qhat;
9145  }
9146 
9147  pfree(dividend);
9148 
9149  /*
9150  * Finally, round or truncate the result to the requested precision.
9151  */
9152  result->weight = res_weight;
9153  result->sign = res_sign;
9154 
9155  /* Round or truncate to target rscale (and set result->dscale) */
9156  if (round)
9157  round_var(result, rscale);
9158  else
9159  trunc_var(result, rscale);
9160 
9161  /* Strip leading and trailing zeroes */
9162  strip_var(result);
9163 }
static void div_var_int(const NumericVar *var, int ival, int ival_weight, NumericVar *result, int rscale, bool round)
Definition: numeric.c:9549
static void alloc_var(NumericVar *var, int ndigits)
Definition: numeric.c:6953
#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 9185 of file numeric.c.

9187 {
9188  int div_ndigits;
9189  int load_ndigits;
9190  int res_sign;
9191  int res_weight;
9192  int *div;
9193  int qdigit;
9194  int carry;
9195  int maxdiv;
9196  int newdig;
9197  NumericDigit *res_digits;
9198  double fdividend,
9199  fdivisor,
9200  fdivisorinverse,
9201  fquotient;
9202  int qi;
9203  int i;
9204 
9205  /* copy these values into local vars for speed in inner loop */
9206  int var1ndigits = var1->ndigits;
9207  int var2ndigits = var2->ndigits;
9208  NumericDigit *var1digits = var1->digits;
9209  NumericDigit *var2digits = var2->digits;
9210 
9211  /*
9212  * First of all division by zero check; we must not be handed an
9213  * unnormalized divisor.
9214  */
9215  if (var2ndigits == 0 || var2digits[0] == 0)
9216  ereport(ERROR,
9217  (errcode(ERRCODE_DIVISION_BY_ZERO),
9218  errmsg("division by zero")));
9219 
9220  /*
9221  * If the divisor has just one or two digits, delegate to div_var_int(),
9222  * which uses fast short division.
9223  *
9224  * Similarly, on platforms with 128-bit integer support, delegate to
9225  * div_var_int64() for divisors with three or four digits.
9226  */
9227  if (var2ndigits <= 2)
9228  {
9229  int idivisor;
9230  int idivisor_weight;
9231 
9232  idivisor = var2->digits[0];
9233  idivisor_weight = var2->weight;
9234  if (var2ndigits == 2)
9235  {
9236  idivisor = idivisor * NBASE + var2->digits[1];
9237  idivisor_weight--;
9238  }
9239  if (var2->sign == NUMERIC_NEG)
9240  idivisor = -idivisor;
9241 
9242  div_var_int(var1, idivisor, idivisor_weight, result, rscale, round);
9243  return;
9244  }
9245 #ifdef HAVE_INT128
9246  if (var2ndigits <= 4)
9247  {
9248  int64 idivisor;
9249  int idivisor_weight;
9250 
9251  idivisor = var2->digits[0];
9252  idivisor_weight = var2->weight;
9253  for (i = 1; i < var2ndigits; i++)
9254  {
9255  idivisor = idivisor * NBASE + var2->digits[i];
9256  idivisor_weight--;
9257  }
9258  if (var2->sign == NUMERIC_NEG)
9259  idivisor = -idivisor;
9260 
9261  div_var_int64(var1, idivisor, idivisor_weight, result, rscale, round);
9262  return;
9263  }
9264 #endif
9265 
9266  /*
9267  * Otherwise, perform full long division.
9268  */
9269 
9270  /* Result zero check */
9271  if (var1ndigits == 0)
9272  {
9273  zero_var(result);
9274  result->dscale = rscale;
9275  return;
9276  }
9277 
9278  /*
9279  * Determine the result sign, weight and number of digits to calculate
9280  */
9281  if (var1->sign == var2->sign)
9282  res_sign = NUMERIC_POS;
9283  else
9284  res_sign = NUMERIC_NEG;
9285  res_weight = var1->weight - var2->weight + 1;
9286  /* The number of accurate result digits we need to produce: */
9287  div_ndigits = res_weight + 1 + (rscale + DEC_DIGITS - 1) / DEC_DIGITS;
9288  /* Add guard digits for roundoff error */
9289  div_ndigits += DIV_GUARD_DIGITS;
9290  if (div_ndigits < DIV_GUARD_DIGITS)
9291  div_ndigits = DIV_GUARD_DIGITS;
9292 
9293  /*
9294  * We do the arithmetic in an array "div[]" of signed int's. Since
9295  * INT_MAX is noticeably larger than NBASE*NBASE, this gives us headroom
9296  * to avoid normalizing carries immediately.
9297  *
9298  * We start with div[] containing one zero digit followed by the
9299  * dividend's digits (plus appended zeroes to reach the desired precision
9300  * including guard digits). Each step of the main loop computes an
9301  * (approximate) quotient digit and stores it into div[], removing one
9302  * position of dividend space. A final pass of carry propagation takes
9303  * care of any mistaken quotient digits.
9304  *
9305  * Note that div[] doesn't necessarily contain all of the digits from the
9306  * dividend --- the desired precision plus guard digits might be less than
9307  * the dividend's precision. This happens, for example, in the square
9308  * root algorithm, where we typically divide a 2N-digit number by an
9309  * N-digit number, and only require a result with N digits of precision.
9310  */
9311  div = (int *) palloc0((div_ndigits + 1) * sizeof(int));
9312  load_ndigits = Min(div_ndigits, var1ndigits);
9313  for (i = 0; i < load_ndigits; i++)
9314  div[i + 1] = var1digits[i];
9315 
9316  /*
9317  * We estimate each quotient digit using floating-point arithmetic, taking
9318  * the first four digits of the (current) dividend and divisor. This must
9319  * be float to avoid overflow. The quotient digits will generally be off
9320  * by no more than one from the exact answer.
9321  */
9322  fdivisor = (double) var2digits[0];
9323  for (i = 1; i < 4; i++)
9324  {
9325  fdivisor *= NBASE;
9326  if (i < var2ndigits)
9327  fdivisor += (double) var2digits[i];
9328  }
9329  fdivisorinverse = 1.0 / fdivisor;
9330 
9331  /*
9332  * maxdiv tracks the maximum possible absolute value of any div[] entry;
9333  * when this threatens to exceed INT_MAX, we take the time to propagate
9334  * carries. Furthermore, we need to ensure that overflow doesn't occur
9335  * during the carry propagation passes either. The carry values may have
9336  * an absolute value as high as INT_MAX/NBASE + 1, so really we must
9337  * normalize when digits threaten to exceed INT_MAX - INT_MAX/NBASE - 1.
9338  *
9339  * To avoid overflow in maxdiv itself, it represents the max absolute
9340  * value divided by NBASE-1, ie, at the top of the loop it is known that
9341  * no div[] entry has an absolute value exceeding maxdiv * (NBASE-1).
9342  *
9343  * Actually, though, that holds good only for div[] entries after div[qi];
9344  * the adjustment done at the bottom of the loop may cause div[qi + 1] to
9345  * exceed the maxdiv limit, so that div[qi] in the next iteration is
9346  * beyond the limit. This does not cause problems, as explained below.
9347  */
9348  maxdiv = 1;
9349 
9350  /*
9351  * Outer loop computes next quotient digit, which will go into div[qi]
9352  */
9353  for (qi = 0; qi < div_ndigits; qi++)
9354  {
9355  /* Approximate the current dividend value */
9356  fdividend = (double) div[qi];
9357  for (i = 1; i < 4; i++)
9358  {
9359  fdividend *= NBASE;
9360  if (qi + i <= div_ndigits)
9361  fdividend += (double) div[qi + i];
9362  }
9363  /* Compute the (approximate) quotient digit */
9364  fquotient = fdividend * fdivisorinverse;
9365  qdigit = (fquotient >= 0.0) ? ((int) fquotient) :
9366  (((int) fquotient) - 1); /* truncate towards -infinity */
9367 
9368  if (qdigit != 0)
9369  {
9370  /* Do we need to normalize now? */
9371  maxdiv += abs(qdigit);
9372  if (maxdiv > (INT_MAX - INT_MAX / NBASE - 1) / (NBASE - 1))
9373  {
9374  /*
9375  * Yes, do it. Note that if var2ndigits is much smaller than
9376  * div_ndigits, we can save a significant amount of effort
9377  * here by noting that we only need to normalise those div[]
9378  * entries touched where prior iterations subtracted multiples
9379  * of the divisor.
9380  */
9381  carry = 0;
9382  for (i = Min(qi + var2ndigits - 2, div_ndigits); i > qi; i--)
9383  {
9384  newdig = div[i] + carry;
9385  if (newdig < 0)
9386  {
9387  carry = -((-newdig - 1) / NBASE) - 1;
9388  newdig -= carry * NBASE;
9389  }
9390  else if (newdig >= NBASE)
9391  {
9392  carry = newdig / NBASE;
9393  newdig -= carry * NBASE;
9394  }
9395  else
9396  carry = 0;
9397  div[i] = newdig;
9398  }
9399  newdig = div[qi] + carry;
9400  div[qi] = newdig;
9401 
9402  /*
9403  * All the div[] digits except possibly div[qi] are now in the
9404  * range 0..NBASE-1. We do not need to consider div[qi] in
9405  * the maxdiv value anymore, so we can reset maxdiv to 1.
9406  */
9407  maxdiv = 1;
9408 
9409  /*
9410  * Recompute the quotient digit since new info may have
9411  * propagated into the top four dividend digits
9412  */
9413  fdividend = (double) div[qi];
9414  for (i = 1; i < 4; i++)
9415  {
9416  fdividend *= NBASE;
9417  if (qi + i <= div_ndigits)
9418  fdividend += (double) div[qi + i];
9419  }
9420  /* Compute the (approximate) quotient digit */
9421  fquotient = fdividend * fdivisorinverse;
9422  qdigit = (fquotient >= 0.0) ? ((int) fquotient) :
9423  (((int) fquotient) - 1); /* truncate towards -infinity */
9424  maxdiv += abs(qdigit);
9425  }
9426 
9427  /*
9428  * Subtract off the appropriate multiple of the divisor.
9429  *
9430  * The digits beyond div[qi] cannot overflow, because we know they
9431  * will fall within the maxdiv limit. As for div[qi] itself, note
9432  * that qdigit is approximately trunc(div[qi] / vardigits[0]),
9433  * which would make the new value simply div[qi] mod vardigits[0].
9434  * The lower-order terms in qdigit can change this result by not
9435  * more than about twice INT_MAX/NBASE, so overflow is impossible.
9436  *
9437  * This inner loop is the performance bottleneck for division, so
9438  * code it in the same way as the inner loop of mul_var() so that
9439  * it can be auto-vectorized. We cast qdigit to NumericDigit
9440  * before multiplying to allow the compiler to generate more
9441  * efficient code (using 16-bit multiplication), which is safe
9442  * since we know that the quotient digit is off by at most one, so
9443  * there is no overflow risk.
9444  */
9445  if (qdigit != 0)
9446  {
9447  int istop = Min(var2ndigits, div_ndigits - qi + 1);
9448  int *div_qi = &div[qi];
9449 
9450  for (i = 0; i < istop; i++)
9451  div_qi[i] -= ((NumericDigit) qdigit) * var2digits[i];
9452  }
9453  }
9454 
9455  /*
9456  * The dividend digit we are about to replace might still be nonzero.
9457  * Fold it into the next digit position.
9458  *
9459  * There is no risk of overflow here, although proving that requires
9460  * some care. Much as with the argument for div[qi] not overflowing,
9461  * if we consider the first two terms in the numerator and denominator
9462  * of qdigit, we can see that the final value of div[qi + 1] will be
9463  * approximately a remainder mod (vardigits[0]*NBASE + vardigits[1]).
9464  * Accounting for the lower-order terms is a bit complicated but ends
9465  * up adding not much more than INT_MAX/NBASE to the possible range.
9466  * Thus, div[qi + 1] cannot overflow here, and in its role as div[qi]
9467  * in the next loop iteration, it can't be large enough to cause
9468  * overflow in the carry propagation step (if any), either.
9469  *
9470  * But having said that: div[qi] can be more than INT_MAX/NBASE, as
9471  * noted above, which means that the product div[qi] * NBASE *can*
9472  * overflow. When that happens, adding it to div[qi + 1] will always
9473  * cause a canceling overflow so that the end result is correct. We
9474  * could avoid the intermediate overflow by doing the multiplication
9475  * and addition in int64 arithmetic, but so far there appears no need.
9476  */
9477  div[qi + 1] += div[qi] * NBASE;
9478 
9479  div[qi] = qdigit;
9480  }
9481 
9482  /*
9483  * Approximate and store the last quotient digit (div[div_ndigits])
9484  */
9485  fdividend = (double) div[qi];
9486  for (i = 1; i < 4; i++)
9487  fdividend *= NBASE;
9488  fquotient = fdividend * fdivisorinverse;
9489  qdigit = (fquotient >= 0.0) ? ((int) fquotient) :
9490  (((int) fquotient) - 1); /* truncate towards -infinity */
9491  div[qi] = qdigit;
9492 
9493  /*
9494  * Because the quotient digits might be off by one, some of them might be
9495  * -1 or NBASE at this point. The represented value is correct in a
9496  * mathematical sense, but it doesn't look right. We do a final carry
9497  * propagation pass to normalize the digits, which we combine with storing
9498  * the result digits into the output. Note that this is still done at
9499  * full precision w/guard digits.
9500  */
9501  alloc_var(result, div_ndigits + 1);
9502  res_digits = result->digits;
9503  carry = 0;
9504  for (i = div_ndigits; i >= 0; i--)
9505  {
9506  newdig = div[i] + carry;
9507  if (newdig < 0)
9508  {
9509  carry = -((-newdig - 1) / NBASE) - 1;
9510  newdig -= carry * NBASE;
9511  }
9512  else if (newdig >= NBASE)
9513  {
9514  carry = newdig / NBASE;
9515  newdig -= carry * NBASE;
9516  }
9517  else
9518  carry = 0;
9519  res_digits[i] = newdig;
9520  }
9521  Assert(carry == 0);
9522 
9523  pfree(div);
9524 
9525  /*
9526  * Finally, round the result to the requested precision.
9527  */
9528  result->weight = res_weight;
9529  result->sign = res_sign;
9530 
9531  /* Round to target rscale (and set result->dscale) */
9532  if (round)
9533  round_var(result, rscale);
9534  else
9535  trunc_var(result, rscale);
9536 
9537  /* Strip leading and trailing zeroes */
9538  strip_var(result);
9539 }
#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 9549 of file numeric.c.

9551 {
9552  NumericDigit *var_digits = var->digits;
9553  int var_ndigits = var->ndigits;
9554  int res_sign;
9555  int res_weight;
9556  int res_ndigits;
9557  NumericDigit *res_buf;
9558  NumericDigit *res_digits;
9559  uint32 divisor;
9560  int i;
9561 
9562  /* Guard against division by zero */
9563  if (ival == 0)
9564  ereport(ERROR,
9565  errcode(ERRCODE_DIVISION_BY_ZERO),
9566  errmsg("division by zero"));
9567 
9568  /* Result zero check */
9569  if (var_ndigits == 0)
9570  {
9571  zero_var(result);
9572  result->dscale = rscale;
9573  return;
9574  }
9575 
9576  /*
9577  * Determine the result sign, weight and number of digits to calculate.
9578  * The weight figured here is correct if the emitted quotient has no
9579  * leading zero digits; otherwise strip_var() will fix things up.
9580  */
9581  if (var->sign == NUMERIC_POS)
9582  res_sign = ival > 0 ? NUMERIC_POS : NUMERIC_NEG;
9583  else
9584  res_sign = ival > 0 ? NUMERIC_NEG : NUMERIC_POS;
9585  res_weight = var->weight - ival_weight;
9586  /* The number of accurate result digits we need to produce: */
9587  res_ndigits = res_weight + 1 + (rscale + DEC_DIGITS - 1) / DEC_DIGITS;
9588  /* ... but always at least 1 */
9589  res_ndigits = Max(res_ndigits, 1);
9590  /* If rounding needed, figure one more digit to ensure correct result */
9591  if (round)
9592  res_ndigits++;
9593 
9594  res_buf = digitbuf_alloc(res_ndigits + 1);
9595  res_buf[0] = 0; /* spare digit for later rounding */
9596  res_digits = res_buf + 1;
9597 
9598  /*
9599  * Now compute the quotient digits. This is the short division algorithm
9600  * described in Knuth volume 2, section 4.3.1 exercise 16, except that we
9601  * allow the divisor to exceed the internal base.
9602  *
9603  * In this algorithm, the carry from one digit to the next is at most
9604  * divisor - 1. Therefore, while processing the next digit, carry may
9605  * become as large as divisor * NBASE - 1, and so it requires a 64-bit
9606  * integer if this exceeds UINT_MAX.
9607  */
9608  divisor = abs(ival);
9609 
9610  if (divisor <= UINT_MAX / NBASE)
9611  {
9612  /* carry cannot overflow 32 bits */
9613  uint32 carry = 0;
9614 
9615  for (i = 0; i < res_ndigits; i++)
9616  {
9617  carry = carry * NBASE + (i < var_ndigits ? var_digits[i] : 0);
9618  res_digits[i] = (NumericDigit) (carry / divisor);
9619  carry = carry % divisor;
9620  }
9621  }
9622  else
9623  {
9624  /* carry may exceed 32 bits */
9625  uint64 carry = 0;
9626 
9627  for (i = 0; i < res_ndigits; i++)
9628  {
9629  carry = carry * NBASE + (i < var_ndigits ? var_digits[i] : 0);
9630  res_digits[i] = (NumericDigit) (carry / divisor);
9631  carry = carry % divisor;
9632  }
9633  }
9634 
9635  /* Store the quotient in result */
9636  digitbuf_free(result->buf);
9637  result->ndigits = res_ndigits;
9638  result->buf = res_buf;
9639  result->digits = res_digits;
9640  result->weight = res_weight;
9641  result->sign = res_sign;
9642 
9643  /* Round or truncate to target rscale (and set result->dscale) */
9644  if (round)
9645  round_var(result, rscale);
9646  else
9647  trunc_var(result, rscale);
9648 
9649  /* Strip leading/trailing zeroes */
9650  strip_var(result);
9651 }
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 4857 of file numeric.c.

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

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

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

7764 {
7765  Numeric res;
7766 
7767  res = (Numeric) palloc(VARSIZE(num));
7768  memcpy(res, num, VARSIZE(num));
7769  return res;
7770 }
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 10671 of file numeric.c.

10672 {
10673  int ln_dweight;
10674 
10675  /* Caller should fail on ln(negative), but for the moment return zero */
10676  if (var->sign != NUMERIC_POS)
10677  return 0;
10678 
10679  if (cmp_var(var, &const_zero_point_nine) >= 0 &&
10680  cmp_var(var, &const_one_point_one) <= 0)
10681  {
10682  /*
10683  * 0.9 <= var <= 1.1
10684  *
10685  * ln(var) has a negative weight (possibly very large). To get a
10686  * reasonably accurate result, estimate it using ln(1+x) ~= x.
10687  */
10688  NumericVar x;
10689 
10690  init_var(&x);
10691  sub_var(var, &const_one, &x);
10692 
10693  if (x.ndigits > 0)
10694  {
10695  /* Use weight of most significant decimal digit of x */
10696  ln_dweight = x.weight * DEC_DIGITS + (int) log10(x.digits[0]);
10697  }
10698  else
10699  {
10700  /* x = 0. Since ln(1) = 0 exactly, we don't need extra digits */
10701  ln_dweight = 0;
10702  }
10703 
10704  free_var(&x);
10705  }
10706  else
10707  {
10708  /*
10709  * Estimate the logarithm using the first couple of digits from the
10710  * input number. This will give an accurate result whenever the input
10711  * is not too close to 1.
10712  */
10713  if (var->ndigits > 0)
10714  {
10715  int digits;
10716  int dweight;
10717  double ln_var;
10718 
10719  digits = var->digits[0];
10720  dweight = var->weight * DEC_DIGITS;
10721 
10722  if (var->ndigits > 1)
10723  {
10724  digits = digits * NBASE + var->digits[1];
10725  dweight -= DEC_DIGITS;
10726  }
10727 
10728  /*----------
10729  * We have var ~= digits * 10^dweight
10730  * so ln(var) ~= ln(digits) + dweight * ln(10)
10731  *----------
10732  */
10733  ln_var = log((double) digits) + dweight * 2.302585092994046;
10734  ln_dweight = (int) log10(fabs(ln_var));
10735  }
10736  else
10737  {
10738  /* Caller should fail on ln(0), but for the moment return zero */
10739  ln_dweight = 0;
10740  }
10741  }
10742 
10743  return ln_dweight;
10744 }
static const NumericVar const_zero_point_nine
Definition: numeric.c:436
static const NumericVar const_one_point_one
Definition: numeric.c:446
static void ln_var(const NumericVar *arg, NumericVar *result, int rscale)
Definition: numeric.c:10753
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 10542 of file numeric.c.

10543 {
10544  NumericVar x;
10545  NumericVar elem;
10546  int ni;
10547  double val;
10548  int dweight;
10549  int ndiv2;
10550  int sig_digits;
10551  int local_rscale;
10552 
10553  init_var(&x);
10554  init_var(&elem);
10555 
10556  set_var_from_var(arg, &x);
10557 
10558  /*
10559  * Estimate the dweight of the result using floating point arithmetic, so
10560  * that we can choose an appropriate local rscale for the calculation.
10561  */
10563 
10564  /* Guard against overflow/underflow */
10565  /* If you change this limit, see also power_var()'s limit */
10566  if (fabs(val) >= NUMERIC_MAX_RESULT_SCALE * 3)
10567  {
10568  if (val > 0)
10569  ereport(ERROR,
10570  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
10571  errmsg("value overflows numeric format")));
10572  zero_var(result);
10573  result->dscale = rscale;
10574  return;
10575  }
10576 
10577  /* decimal weight = log10(e^x) = x * log10(e) */
10578  dweight = (int) (val * 0.434294481903252);
10579 
10580  /*
10581  * Reduce x to the range -0.01 <= x <= 0.01 (approximately) by dividing by
10582  * 2^ndiv2, to improve the convergence rate of the Taylor series.
10583  *
10584  * Note that the overflow check above ensures that fabs(x) < 6000, which
10585  * means that ndiv2 <= 20 here.
10586  */
10587  if (fabs(val) > 0.01)
10588  {
10589  ndiv2 = 1;
10590  val /= 2;
10591 
10592  while (fabs(val) > 0.01)
10593  {
10594  ndiv2++;
10595  val /= 2;
10596  }
10597 
10598  local_rscale = x.dscale + ndiv2;
10599  div_var_int(&x, 1 << ndiv2, 0, &x, local_rscale, true);
10600  }
10601  else
10602  ndiv2 = 0;
10603 
10604  /*
10605  * Set the scale for the Taylor series expansion. The final result has
10606  * (dweight + rscale + 1) significant digits. In addition, we have to
10607  * raise the Taylor series result to the power 2^ndiv2, which introduces
10608  * an error of up to around log10(2^ndiv2) digits, so work with this many
10609  * extra digits of precision (plus a few more for good measure).
10610  */
10611  sig_digits = 1 + dweight + rscale + (int) (ndiv2 * 0.301029995663981);
10612  sig_digits = Max(sig_digits, 0) + 8;
10613 
10614  local_rscale = sig_digits - 1;
10615 
10616  /*
10617  * Use the Taylor series
10618  *
10619  * exp(x) = 1 + x + x^2/2! + x^3/3! + ...
10620  *
10621  * Given the limited range of x, this should converge reasonably quickly.
10622  * We run the series until the terms fall below the local_rscale limit.
10623  */
10624  add_var(&const_one, &x, result);
10625 
10626  mul_var(&x, &x, &elem, local_rscale);
10627  ni = 2;
10628  div_var_int(&elem, ni, 0, &elem, local_rscale, true);
10629 
10630  while (elem.ndigits != 0)
10631  {
10632  add_var(result, &elem, result);
10633 
10634  mul_var(&elem, &x, &elem, local_rscale);
10635  ni++;
10636  div_var_int(&elem, ni, 0, &elem, local_rscale, true);
10637  }
10638 
10639  /*
10640  * Compensate for the argument range reduction. Since the weight of the
10641  * result doubles with each multiplication, we can reduce the local rscale
10642  * as we proceed.
10643  */
10644  while (ndiv2-- > 0)
10645  {
10646  local_rscale = sig_digits - result->weight * 2 * DEC_DIGITS;
10647  local_rscale = Max(local_rscale, NUMERIC_MIN_DISPLAY_SCALE);
10648  mul_var(result, result, result, local_rscale);
10649  }
10650 
10651  /* Round to requested rscale */
10652  round_var(result, rscale);
10653 
10654  free_var(&x);
10655  free_var(&elem);
10656 }
static double numericvar_to_double_no_overflow(const NumericVar *var)
Definition: numeric.c:8341
#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 4687 of file numeric.c.

4688 {
4690  Numeric res;
4691  NumericVar result;
4692  char buf[FLT_DIG + 100];
4693  const char *endptr;
4694 
4695  if (isnan(val))
4697 
4698  if (isinf(val))
4699  {
4700  if (val < 0)
4702  else
4704  }
4705 
4706  snprintf(buf, sizeof(buf), "%.*g", FLT_DIG, val);
4707 
4708  init_var(&result);
4709 
4710  /* Assume we need not worry about leading/trailing spaces */
4711  (void) set_var_from_str(buf, buf, &result, &endptr, NULL);
4712 
4713  res = make_result(&result);
4714 
4715  free_var(&result);
4716 
4718 }
static const NumericVar const_pinf
Definition: numeric.c:452
static const NumericVar const_ninf
Definition: numeric.c:455
static bool set_var_from_str(const char *str, const char *cp, NumericVar *dest, const char **endptr, Node *escontext)
Definition: numeric.c:7012
static Numeric make_result(const NumericVar *var)
Definition: numeric.c:7891
static const NumericVar const_nan
Definition: numeric.c:449
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 4593 of file numeric.c.

4594 {
4596  Numeric res;
4597  NumericVar result;
4598  char buf[DBL_DIG + 100];
4599  const char *endptr;
4600 
4601  if (isnan(val))
4603 
4604  if (isinf(val))
4605  {
4606  if (val < 0)
4608  else
4610  }
4611 
4612  snprintf(buf, sizeof(buf), "%.*g", DBL_DIG, val);
4613 
4614  init_var(&result);
4615 
4616  /* Assume we need not worry about leading/trailing spaces */
4617  (void) set_var_from_str(buf, buf, &result, &endptr, NULL);
4618 
4619  res = make_result(&result);
4620 
4621  free_var(&result);
4622 
4624 }
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 9969 of file numeric.c.

9970 {
9971  NumericVar tmp;
9972 
9973  init_var(&tmp);
9974  set_var_from_var(var, &tmp);
9975 
9976  trunc_var(&tmp, 0);
9977 
9978  if (var->sign == NUMERIC_NEG && cmp_var(var, &tmp) != 0)
9979  sub_var(&tmp, &const_one, &tmp);
9980 
9981  set_var_from_var(&tmp, result);
9982  free_var(&tmp);
9983 }

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

Referenced by compute_bucket(), and numeric_floor().

◆ free_var()

static void free_var ( NumericVar var)
static

Definition at line 6969 of file numeric.c.

6970 {
6971  digitbuf_free(var->buf);
6972  var->buf = NULL;
6973  var->digits = NULL;
6974  var->sign = NUMERIC_NAN;
6975 }
#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 9992 of file numeric.c.

9993 {
9994  int res_dscale;
9995  int cmp;
9996  NumericVar tmp_arg;
9997  NumericVar mod;
9998 
9999  res_dscale = Max(var1->dscale, var2->dscale);
10000 
10001  /*
10002  * Arrange for var1 to be the number with the greater absolute value.
10003  *
10004  * This would happen automatically in the loop below, but avoids an
10005  * expensive modulo operation.
10006  */
10007  cmp = cmp_abs(var1, var2);
10008  if (cmp < 0)
10009  {
10010  const NumericVar *tmp = var1;
10011 
10012  var1 = var2;
10013  var2 = tmp;
10014  }
10015 
10016  /*
10017  * Also avoid the taking the modulo if the inputs have the same absolute
10018  * value, or if the smaller input is zero.
10019  */
10020  if (cmp == 0 || var2->ndigits == 0)
10021  {
10022  set_var_from_var(var1, result);
10023  result->sign = NUMERIC_POS;
10024  result->dscale = res_dscale;
10025  return;
10026  }
10027 
10028  init_var(&tmp_arg);
10029  init_var(&mod);
10030 
10031  /* Use the Euclidean algorithm to find the GCD */
10032  set_var_from_var(var1, &tmp_arg);
10033  set_var_from_var(var2, result);
10034 
10035  for (;;)
10036  {
10037  /* this loop can take a while, so allow it to be interrupted */
10039 
10040  mod_var(&tmp_arg, result, &mod);
10041  if (mod.ndigits == 0)
10042  break;
10043  set_var_from_var(result, &tmp_arg);
10044  set_var_from_var(&mod, result);
10045  }
10046  result->sign = NUMERIC_POS;
10047  result->dscale = res_dscale;
10048 
10049  free_var(&tmp_arg);
10050  free_var(&mod);
10051 }
static void mod_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition: numeric.c:9846
#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 1686 of file numeric.c.

1687 {
1688  return generate_series_step_numeric(fcinfo);
1689 }
Datum generate_series_step_numeric(PG_FUNCTION_ARGS)
Definition: numeric.c:1692

References generate_series_step_numeric().

◆ generate_series_step_numeric()

Datum generate_series_step_numeric ( PG_FUNCTION_ARGS  )

Definition at line 1692 of file numeric.c.

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

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

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

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

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

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

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

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

5551 {
5553 
5554  state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
5555 
5556  /* Create the state data on the first call */
5557  if (state == NULL)
5558  state = makePolyNumAggState(fcinfo, true);
5559 
5560  if (!PG_ARGISNULL(1))
5561  {
5562 #ifdef HAVE_INT128
5563  do_int128_accum(state, (int128) PG_GETARG_INT16(1));
5564 #else
5566 #endif
5567  }
5568 
5570 }
#define makePolyNumAggState
Definition: numeric.c:5545
Numeric int64_to_numeric(int64 val)
Definition: numeric.c:4283
static void do_numeric_accum(NumericAggState *state, Numeric newval)
Definition: numeric.c:4857
#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 5974 of file numeric.c.

5975 {
5977 
5978  state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
5979 
5980  /* Should not get here with no state */
5981  if (state == NULL)
5982  elog(ERROR, "int2_accum_inv called with NULL state");
5983 
5984  if (!PG_ARGISNULL(1))
5985  {
5986 #ifdef HAVE_INT128
5987  do_int128_discard(state, (int128) PG_GETARG_INT16(1));
5988 #else
5989  /* Should never fail, all inputs have dscale 0 */
5991  elog(ERROR, "do_numeric_discard failed unexpectedly");
5992 #endif
5993  }
5994 
5996 }
static bool do_numeric_discard(NumericAggState *state, Numeric newval)
Definition: numeric.c:4927
#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 6657 of file numeric.c.

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

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

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

4545 {
4546  int16 val = PG_GETARG_INT16(0);
4547 
4549 }

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

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

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

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

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

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

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

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

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

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

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

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

4390 {
4391  int32 val = PG_GETARG_INT32(0);
4392 
4394 }

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

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

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

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

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

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

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

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

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

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

6801 {
6802  ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
6803  Int8TransTypeData *transdata;
6804  Datum countd,
6805  sumd;
6806 
6807  if (ARR_HASNULL(transarray) ||
6808  ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
6809  elog(ERROR, "expected 2-element int8 array");
6810  transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
6811 
6812  /* SQL defines AVG of no values to be NULL */
6813  if (transdata->count == 0)
6814  PG_RETURN_NULL();
6815 
6816  countd = NumericGetDatum(int64_to_numeric(transdata->count));
6817  sumd = NumericGetDatum(int64_to_numeric(transdata->sum));
6818 
6820 }
Datum numeric_div(PG_FUNCTION_ARGS)
Definition: numeric.c:3124
#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 5792 of file numeric.c.

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

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

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

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

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

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

5929 {
5930  bytea *sstate;
5931  PolyNumAggState *result;
5933  NumericVar tmp_var;
5934 
5935  if (!AggCheckCallContext(fcinfo, NULL))
5936  elog(ERROR, "aggregate function called in non-aggregate context");
5937 
5938  sstate = PG_GETARG_BYTEA_PP(0);
5939 
5940  init_var(&tmp_var);
5941 
5942  /*
5943  * Initialize a StringInfo so that we can "receive" it using the standard
5944  * recv-function infrastructure.
5945  */
5947  VARSIZE_ANY_EXHDR(sstate));
5948 
5949  result = makePolyNumAggStateCurrentContext(false);
5950 
5951  /* N */
5952  result->N = pq_getmsgint64(&buf);
5953 
5954  /* sumX */
5955  numericvar_deserialize(&buf, &tmp_var);
5956 #ifdef HAVE_INT128
5957  numericvar_to_int128(&tmp_var, &result->sumX);
5958 #else
5959  accum_sum_add(&result->sumX, &tmp_var);
5960 #endif
5961 
5962  pq_getmsgend(&buf);
5963 
5964  free_var(&tmp_var);
5965 
5966  PG_RETURN_POINTER(result);
5967 }
static void numericvar_deserialize(StringInfo buf, NumericVar *var)
Definition: numeric.c:7740
#define makePolyNumAggStateCurrentContext
Definition: numeric.c:5546
#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(), makePol