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 "catalog/pg_type.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/int8.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_NAN   0xC000
 
#define NUMERIC_FLAGBITS(n)   ((n)->choice.n_header & NUMERIC_SIGN_MASK)
 
#define NUMERIC_IS_NAN(n)   (NUMERIC_FLAGBITS(n) == NUMERIC_NAN)
 
#define NUMERIC_IS_SHORT(n)   (NUMERIC_FLAGBITS(n) == NUMERIC_SHORT)
 
#define NUMERIC_HDRSZ   (VARHDRSZ + sizeof(uint16) + sizeof(int16))
 
#define NUMERIC_HDRSZ_SHORT   (VARHDRSZ + sizeof(uint16))
 
#define NUMERIC_HEADER_IS_SHORT(n)   (((n)->choice.n_header & 0x8000) != 0)
 
#define NUMERIC_HEADER_SIZE(n)
 
#define NUMERIC_SHORT_SIGN_MASK   0x2000
 
#define NUMERIC_SHORT_DSCALE_MASK   0x1F80
 
#define NUMERIC_SHORT_DSCALE_SHIFT   7
 
#define NUMERIC_SHORT_DSCALE_MAX   (NUMERIC_SHORT_DSCALE_MASK >> NUMERIC_SHORT_DSCALE_SHIFT)
 
#define NUMERIC_SHORT_WEIGHT_SIGN_MASK   0x0040
 
#define NUMERIC_SHORT_WEIGHT_MASK   0x003F
 
#define NUMERIC_SHORT_WEIGHT_MAX   NUMERIC_SHORT_WEIGHT_MASK
 
#define NUMERIC_SHORT_WEIGHT_MIN   (-(NUMERIC_SHORT_WEIGHT_MASK+1))
 
#define NUMERIC_DSCALE_MASK   0x3FFF
 
#define NUMERIC_SIGN(n)
 
#define NUMERIC_DSCALE(n)
 
#define NUMERIC_WEIGHT(n)
 
#define NUMERIC_ABBREV_BITS   (SIZEOF_DATUM * BITS_PER_BYTE)
 
#define NumericAbbrevGetDatum(X)   ((Datum) (X))
 
#define DatumGetNumericAbbrev(X)   ((int32) (X))
 
#define NUMERIC_ABBREV_NAN   NumericAbbrevGetDatum(PG_INT32_MIN)
 
#define dump_numeric(s, n)
 
#define dump_var(s, v)
 
#define digitbuf_alloc(ndigits)   ((NumericDigit *) palloc((ndigits) * sizeof(NumericDigit)))
 
#define digitbuf_free(buf)
 
#define init_var(v)   MemSetAligned(v, 0, sizeof(NumericVar))
 
#define NUMERIC_DIGITS(num)
 
#define NUMERIC_NDIGITS(num)   ((VARSIZE(num) - NUMERIC_HEADER_SIZE(num)) / sizeof(NumericDigit))
 
#define NUMERIC_CAN_BE_SHORT(scale, weight)
 
#define makePolyNumAggState   makeNumericAggState
 
#define makePolyNumAggStateCurrentContext   makeNumericAggStateCurrentContext
 

Typedefs

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

Functions

static void alloc_var (NumericVar *var, int ndigits)
 
static void free_var (NumericVar *var)
 
static void zero_var (NumericVar *var)
 
static const char * set_var_from_str (const char *str, const char *cp, NumericVar *dest)
 
static void set_var_from_num (Numeric value, NumericVar *dest)
 
static void init_var_from_num (Numeric num, NumericVar *dest)
 
static void set_var_from_var (const NumericVar *value, NumericVar *dest)
 
static char * get_str_from_var (const NumericVar *var)
 
static char * get_str_from_var_sci (const NumericVar *var, int rscale)
 
static Numeric make_result (const NumericVar *var)
 
static Numeric make_result_opt_error (const NumericVar *var, bool *error)
 
static void apply_typmod (NumericVar *var, int32 typmod)
 
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 numeric_to_double_no_overflow (Numeric num)
 
static double numericvar_to_double_no_overflow (const NumericVar *var)
 
static Datum numeric_abbrev_convert (Datum original_datum, SortSupport ssup)
 
static bool numeric_abbrev_abort (int memtupcount, SortSupport ssup)
 
static int numeric_fast_cmp (Datum x, Datum y, SortSupport ssup)
 
static int numeric_cmp_abbrev (Datum x, Datum y, SortSupport ssup)
 
static Datum numeric_abbrev_convert_var (const NumericVar *var, NumericSortSupport *nss)
 
static int cmp_numerics (Numeric num1, Numeric num2)
 
static int cmp_var (const NumericVar *var1, const NumericVar *var2)
 
static int cmp_var_common (const NumericDigit *var1digits, int var1ndigits, int var1weight, int var1sign, const NumericDigit *var2digits, int var2ndigits, int var2weight, int var2sign)
 
static void add_var (const NumericVar *var1, const NumericVar *var2, NumericVar *result)
 
static void sub_var (const NumericVar *var1, const NumericVar *var2, NumericVar *result)
 
static void mul_var (const NumericVar *var1, const NumericVar *var2, NumericVar *result, int rscale)
 
static void div_var (const NumericVar *var1, const NumericVar *var2, NumericVar *result, int rscale, bool round)
 
static void div_var_fast (const NumericVar *var1, const NumericVar *var2, NumericVar *result, int rscale, bool round)
 
static int select_div_scale (const NumericVar *var1, const NumericVar *var2)
 
static void mod_var (const NumericVar *var1, const NumericVar *var2, NumericVar *result)
 
static void 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, NumericVar *result, int rscale)
 
static int cmp_abs (const NumericVar *var1, const NumericVar *var2)
 
static int cmp_abs_common (const NumericDigit *var1digits, int var1ndigits, int var1weight, const NumericDigit *var2digits, int var2ndigits, int var2weight)
 
static void add_abs (const NumericVar *var1, const NumericVar *var2, NumericVar *result)
 
static void sub_abs (const NumericVar *var1, const NumericVar *var2, NumericVar *result)
 
static void round_var (NumericVar *var, int rscale)
 
static void trunc_var (NumericVar *var, int rscale)
 
static void strip_var (NumericVar *var)
 
static void compute_bucket (Numeric operand, Numeric bound1, Numeric bound2, const NumericVar *count_var, NumericVar *result_var)
 
static void accum_sum_add (NumericSumAccum *accum, const NumericVar *var1)
 
static void accum_sum_rescale (NumericSumAccum *accum, const NumericVar *val)
 
static void accum_sum_carry (NumericSumAccum *accum)
 
static void accum_sum_reset (NumericSumAccum *accum)
 
static void accum_sum_final (NumericSumAccum *accum, NumericVar *result)
 
static void accum_sum_copy (NumericSumAccum *dst, NumericSumAccum *src)
 
static void accum_sum_combine (NumericSumAccum *accum, NumericSumAccum *accum2)
 
Datum numeric_in (PG_FUNCTION_ARGS)
 
Datum numeric_out (PG_FUNCTION_ARGS)
 
bool numeric_is_nan (Numeric num)
 
int32 numeric_maximum_size (int32 typmod)
 
char * numeric_out_sci (Numeric num, int scale)
 
char * numeric_normalize (Numeric num)
 
Datum numeric_recv (PG_FUNCTION_ARGS)
 
Datum numeric_send (PG_FUNCTION_ARGS)
 
Datum numeric_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)
 
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)
 
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)
 
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)
 

Variables

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

Macro Definition Documentation

◆ DatumGetNumericAbbrev

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

Definition at line 365 of file numeric.c.

Referenced by numeric_cmp_abbrev().

◆ DEC_DIGITS

◆ digitbuf_alloc

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

Definition at line 437 of file numeric.c.

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

◆ digitbuf_free

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

Definition at line 439 of file numeric.c.

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

◆ DIV_GUARD_DIGITS

#define DIV_GUARD_DIGITS   4

Definition at line 101 of file numeric.c.

Referenced by div_var_fast().

◆ dump_numeric

#define dump_numeric (   s,
 
)

Definition at line 433 of file numeric.c.

Referenced by int2int4_sum(), and make_result_opt_error().

◆ dump_var

#define dump_var (   s,
 
)

Definition at line 434 of file numeric.c.

Referenced by int2int4_sum().

◆ HALF_NBASE

#define HALF_NBASE   5000

Definition at line 98 of file numeric.c.

Referenced by div_var(), and round_var().

◆ init_var

◆ makePolyNumAggState

#define makePolyNumAggState   makeNumericAggState

◆ makePolyNumAggStateCurrentContext

#define makePolyNumAggStateCurrentContext   makeNumericAggStateCurrentContext

Definition at line 4478 of file numeric.c.

Referenced by int8_avg_deserialize(), and numeric_poly_deserialize().

◆ MUL_GUARD_DIGITS

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

Definition at line 100 of file numeric.c.

Referenced by mul_var().

◆ NBASE

◆ NUMERIC_ABBREV_BITS

#define NUMERIC_ABBREV_BITS   (SIZEOF_DATUM * BITS_PER_BYTE)

Definition at line 358 of file numeric.c.

◆ NUMERIC_ABBREV_NAN

#define NUMERIC_ABBREV_NAN   NumericAbbrevGetDatum(PG_INT32_MIN)

Definition at line 366 of file numeric.c.

Referenced by numeric_abbrev_convert().

◆ NUMERIC_CAN_BE_SHORT

#define NUMERIC_CAN_BE_SHORT (   scale,
  weight 
)
Value:
(weight) <= NUMERIC_SHORT_WEIGHT_MAX && \
#define NUMERIC_SHORT_WEIGHT_MAX
Definition: numeric.c:201
int scale
Definition: pgbench.c:153
#define NUMERIC_SHORT_WEIGHT_MIN
Definition: numeric.c:202
#define NUMERIC_SHORT_DSCALE_MAX
Definition: numeric.c:197

Definition at line 451 of file numeric.c.

Referenced by make_result_opt_error(), and numeric().

◆ NUMERIC_DIGITS

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

Definition at line 447 of file numeric.c.

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

◆ NUMERIC_DSCALE

#define NUMERIC_DSCALE (   n)
Value:
((n)->choice.n_short.n_header & NUMERIC_SHORT_DSCALE_MASK) \
: ((n)->choice.n_long.n_sign_dscale & NUMERIC_DSCALE_MASK))
#define NUMERIC_HEADER_IS_SHORT(n)
Definition: numeric.c:185
#define NUMERIC_DSCALE_MASK
Definition: numeric.c:208
#define NUMERIC_SHORT_DSCALE_MASK
Definition: numeric.c:195
#define NUMERIC_SHORT_DSCALE_SHIFT
Definition: numeric.c:196

Definition at line 214 of file numeric.c.

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

◆ NUMERIC_DSCALE_MASK

#define NUMERIC_DSCALE_MASK   0x3FFF

Definition at line 208 of file numeric.c.

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

◆ NUMERIC_FLAGBITS

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

Definition at line 173 of file numeric.c.

◆ NUMERIC_HDRSZ

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

Definition at line 177 of file numeric.c.

Referenced by make_result_opt_error(), and numeric_maximum_size().

◆ NUMERIC_HDRSZ_SHORT

#define NUMERIC_HDRSZ_SHORT   (VARHDRSZ + sizeof(uint16))

Definition at line 178 of file numeric.c.

Referenced by make_result_opt_error().

◆ NUMERIC_HEADER_IS_SHORT

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

Definition at line 185 of file numeric.c.

◆ NUMERIC_HEADER_SIZE

#define NUMERIC_HEADER_SIZE (   n)
Value:
(VARHDRSZ + sizeof(uint16) + \
(NUMERIC_HEADER_IS_SHORT(n) ? 0 : sizeof(int16)))
signed short int16
Definition: c.h:354
#define NUMERIC_HEADER_IS_SHORT(n)
Definition: numeric.c:185
#define VARHDRSZ
Definition: c.h:561
unsigned short uint16
Definition: c.h:366

Definition at line 186 of file numeric.c.

◆ NUMERIC_IS_NAN

◆ NUMERIC_IS_SHORT

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

Definition at line 175 of file numeric.c.

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

◆ NUMERIC_NAN

#define NUMERIC_NAN   0xC000

◆ NUMERIC_NDIGITS

◆ NUMERIC_NEG

◆ NUMERIC_POS

◆ NUMERIC_SHORT

#define NUMERIC_SHORT   0x8000

Definition at line 170 of file numeric.c.

Referenced by make_result_opt_error().

◆ NUMERIC_SHORT_DSCALE_MASK

#define NUMERIC_SHORT_DSCALE_MASK   0x1F80

Definition at line 195 of file numeric.c.

Referenced by numeric().

◆ NUMERIC_SHORT_DSCALE_MAX

#define NUMERIC_SHORT_DSCALE_MAX   (NUMERIC_SHORT_DSCALE_MASK >> NUMERIC_SHORT_DSCALE_SHIFT)

Definition at line 197 of file numeric.c.

◆ NUMERIC_SHORT_DSCALE_SHIFT

#define NUMERIC_SHORT_DSCALE_SHIFT   7

Definition at line 196 of file numeric.c.

Referenced by make_result_opt_error(), and numeric().

◆ NUMERIC_SHORT_SIGN_MASK

#define NUMERIC_SHORT_SIGN_MASK   0x2000

Definition at line 194 of file numeric.c.

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

◆ NUMERIC_SHORT_WEIGHT_MASK

#define NUMERIC_SHORT_WEIGHT_MASK   0x003F

Definition at line 200 of file numeric.c.

Referenced by make_result_opt_error().

◆ NUMERIC_SHORT_WEIGHT_MAX

#define NUMERIC_SHORT_WEIGHT_MAX   NUMERIC_SHORT_WEIGHT_MASK

Definition at line 201 of file numeric.c.

◆ NUMERIC_SHORT_WEIGHT_MIN

#define NUMERIC_SHORT_WEIGHT_MIN   (-(NUMERIC_SHORT_WEIGHT_MASK+1))

Definition at line 202 of file numeric.c.

◆ NUMERIC_SHORT_WEIGHT_SIGN_MASK

#define NUMERIC_SHORT_WEIGHT_SIGN_MASK   0x0040

Definition at line 199 of file numeric.c.

Referenced by make_result_opt_error().

◆ NUMERIC_SIGN

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

Definition at line 210 of file numeric.c.

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

◆ NUMERIC_SIGN_MASK

#define NUMERIC_SIGN_MASK   0xC000

Definition at line 167 of file numeric.c.

◆ NUMERIC_WEIGHT

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

Definition at line 218 of file numeric.c.

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

◆ NumericAbbrevGetDatum

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

Definition at line 364 of file numeric.c.

Referenced by numeric_cmp_abbrev().

Typedef Documentation

◆ Int8TransTypeData

◆ NumericAggState

◆ NumericDigit

Definition at line 103 of file numeric.c.

◆ NumericSumAccum

◆ NumericVar

typedef struct NumericVar NumericVar

◆ PolyNumAggState

Definition at line 4476 of file numeric.c.

Function Documentation

◆ accum_sum_add()

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

Definition at line 10034 of file numeric.c.

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

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

10035 {
10036  int32 *accum_digits;
10037  int i,
10038  val_i;
10039  int val_ndigits;
10040  NumericDigit *val_digits;
10041 
10042  /*
10043  * If we have accumulated too many values since the last carry
10044  * propagation, do it now, to avoid overflowing. (We could allow more
10045  * than NBASE - 1, if we reserved two extra digits, rather than one, for
10046  * carry propagation. But even with NBASE - 1, this needs to be done so
10047  * seldom, that the performance difference is negligible.)
10048  */
10049  if (accum->num_uncarried == NBASE - 1)
10050  accum_sum_carry(accum);
10051 
10052  /*
10053  * Adjust the weight or scale of the old value, so that it can accommodate
10054  * the new value.
10055  */
10056  accum_sum_rescale(accum, val);
10057 
10058  /* */
10059  if (val->sign == NUMERIC_POS)
10060  accum_digits = accum->pos_digits;
10061  else
10062  accum_digits = accum->neg_digits;
10063 
10064  /* copy these values into local vars for speed in loop */
10065  val_ndigits = val->ndigits;
10066  val_digits = val->digits;
10067 
10068  i = accum->weight - val->weight;
10069  for (val_i = 0; val_i < val_ndigits; val_i++)
10070  {
10071  accum_digits[i] += (int32) val_digits[val_i];
10072  i++;
10073  }
10074 
10075  accum->num_uncarried++;
10076 }
static void accum_sum_rescale(NumericSumAccum *accum, const NumericVar *val)
Definition: numeric.c:10155
#define NUMERIC_POS
Definition: numeric.c:168
int32 * neg_digits
Definition: numeric.c:348
int num_uncarried
Definition: numeric.c:345
static void accum_sum_carry(NumericSumAccum *accum)
Definition: numeric.c:10082
signed int int32
Definition: c.h:355
int16 NumericDigit
Definition: numeric.c:103
#define NBASE
Definition: numeric.c:97
int i
int32 * pos_digits
Definition: numeric.c:347
long val
Definition: informix.c:664

◆ accum_sum_carry()

static void accum_sum_carry ( NumericSumAccum accum)
static

Definition at line 10082 of file numeric.c.

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

Referenced by accum_sum_add(), and accum_sum_final().

10083 {
10084  int i;
10085  int ndigits;
10086  int32 *dig;
10087  int32 carry;
10088  int32 newdig = 0;
10089 
10090  /*
10091  * If no new values have been added since last carry propagation, nothing
10092  * to do.
10093  */
10094  if (accum->num_uncarried == 0)
10095  return;
10096 
10097  /*
10098  * We maintain that the weight of the accumulator is always one larger
10099  * than needed to hold the current value, before carrying, to make sure
10100  * there is enough space for the possible extra digit when carry is
10101  * propagated. We cannot expand the buffer here, unless we require
10102  * callers of accum_sum_final() to switch to the right memory context.
10103  */
10104  Assert(accum->pos_digits[0] == 0 && accum->neg_digits[0] == 0);
10105 
10106  ndigits = accum->ndigits;
10107 
10108  /* Propagate carry in the positive sum */
10109  dig = accum->pos_digits;
10110  carry = 0;
10111  for (i = ndigits - 1; i >= 0; i--)
10112  {
10113  newdig = dig[i] + carry;
10114  if (newdig >= NBASE)
10115  {
10116  carry = newdig / NBASE;
10117  newdig -= carry * NBASE;
10118  }
10119  else
10120  carry = 0;
10121  dig[i] = newdig;
10122  }
10123  /* Did we use up the digit reserved for carry propagation? */
10124  if (newdig > 0)
10125  accum->have_carry_space = false;
10126 
10127  /* And the same for the negative sum */
10128  dig = accum->neg_digits;
10129  carry = 0;
10130  for (i = ndigits - 1; i >= 0; i--)
10131  {
10132  newdig = dig[i] + carry;
10133  if (newdig >= NBASE)
10134  {
10135  carry = newdig / NBASE;
10136  newdig -= carry * NBASE;
10137  }
10138  else
10139  carry = 0;
10140  dig[i] = newdig;
10141  }
10142  if (newdig > 0)
10143  accum->have_carry_space = false;
10144 
10145  accum->num_uncarried = 0;
10146 }
int32 * neg_digits
Definition: numeric.c:348
int num_uncarried
Definition: numeric.c:345
signed int int32
Definition: c.h:355
bool have_carry_space
Definition: numeric.c:346
#define NBASE
Definition: numeric.c:97
#define Assert(condition)
Definition: c.h:738
int i
int32 * pos_digits
Definition: numeric.c:347

◆ accum_sum_combine()

static void accum_sum_combine ( NumericSumAccum accum,
NumericSumAccum accum2 
)
static

Definition at line 10312 of file numeric.c.

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

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

10313 {
10314  NumericVar tmp_var;
10315 
10316  init_var(&tmp_var);
10317 
10318  accum_sum_final(accum2, &tmp_var);
10319  accum_sum_add(accum, &tmp_var);
10320 
10321  free_var(&tmp_var);
10322 }
static void accum_sum_final(NumericSumAccum *accum, NumericVar *result)
Definition: numeric.c:10244
static void accum_sum_add(NumericSumAccum *accum, const NumericVar *var1)
Definition: numeric.c:10034
static void free_var(NumericVar *var)
Definition: numeric.c:5950
#define init_var(v)
Definition: numeric.c:445

◆ accum_sum_copy()

static void accum_sum_copy ( NumericSumAccum dst,
NumericSumAccum src 
)
static

Definition at line 10295 of file numeric.c.

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

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

10296 {
10297  dst->pos_digits = palloc(src->ndigits * sizeof(int32));
10298  dst->neg_digits = palloc(src->ndigits * sizeof(int32));
10299 
10300  memcpy(dst->pos_digits, src->pos_digits, src->ndigits * sizeof(int32));
10301  memcpy(dst->neg_digits, src->neg_digits, src->ndigits * sizeof(int32));
10302  dst->num_uncarried = src->num_uncarried;
10303  dst->ndigits = src->ndigits;
10304  dst->weight = src->weight;
10305  dst->dscale = src->dscale;
10306 }
int32 * neg_digits
Definition: numeric.c:348
int num_uncarried
Definition: numeric.c:345
signed int int32
Definition: c.h:355
void * palloc(Size size)
Definition: mcxt.c:949
int32 * pos_digits
Definition: numeric.c:347

◆ accum_sum_final()

static void accum_sum_final ( NumericSumAccum accum,
NumericVar result 
)
static

Definition at line 10244 of file numeric.c.

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

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

10245 {
10246  int i;
10247  NumericVar pos_var;
10248  NumericVar neg_var;
10249 
10250  if (accum->ndigits == 0)
10251  {
10252  set_var_from_var(&const_zero, result);
10253  return;
10254  }
10255 
10256  /* Perform final carry */
10257  accum_sum_carry(accum);
10258 
10259  /* Create NumericVars representing the positive and negative sums */
10260  init_var(&pos_var);
10261  init_var(&neg_var);
10262 
10263  pos_var.ndigits = neg_var.ndigits = accum->ndigits;
10264  pos_var.weight = neg_var.weight = accum->weight;
10265  pos_var.dscale = neg_var.dscale = accum->dscale;
10266  pos_var.sign = NUMERIC_POS;
10267  neg_var.sign = NUMERIC_NEG;
10268 
10269  pos_var.buf = pos_var.digits = digitbuf_alloc(accum->ndigits);
10270  neg_var.buf = neg_var.digits = digitbuf_alloc(accum->ndigits);
10271 
10272  for (i = 0; i < accum->ndigits; i++)
10273  {
10274  Assert(accum->pos_digits[i] < NBASE);
10275  pos_var.digits[i] = (int16) accum->pos_digits[i];
10276 
10277  Assert(accum->neg_digits[i] < NBASE);
10278  neg_var.digits[i] = (int16) accum->neg_digits[i];
10279  }
10280 
10281  /* And add them together */
10282  add_var(&pos_var, &neg_var, result);
10283 
10284  /* Remove leading/trailing zeroes */
10285  strip_var(result);
10286 }
signed short int16
Definition: c.h:354
int weight
Definition: numeric.c:276
#define NUMERIC_POS
Definition: numeric.c:168
static void strip_var(NumericVar *var)
Definition: numeric.c:9977
int32 * neg_digits
Definition: numeric.c:348
#define digitbuf_alloc(ndigits)
Definition: numeric.c:437
int ndigits
Definition: numeric.c:275
static void accum_sum_carry(NumericSumAccum *accum)
Definition: numeric.c:10082
int dscale
Definition: numeric.c:278
#define NUMERIC_NEG
Definition: numeric.c:169
int sign
Definition: numeric.c:277
NumericDigit * buf
Definition: numeric.c:279
#define NBASE
Definition: numeric.c:97
static const NumericVar const_zero
Definition: numeric.c:375
#define Assert(condition)
Definition: c.h:738
NumericDigit * digits
Definition: numeric.c:280
static void add_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition: numeric.c:7084
int i
static void set_var_from_var(const NumericVar *value, NumericVar *dest)
Definition: numeric.c:6200
int32 * pos_digits
Definition: numeric.c:347
#define init_var(v)
Definition: numeric.c:445

◆ accum_sum_rescale()

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

Definition at line 10155 of file numeric.c.

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

Referenced by accum_sum_add().

10156 {
10157  int old_weight = accum->weight;
10158  int old_ndigits = accum->ndigits;
10159  int accum_ndigits;
10160  int accum_weight;
10161  int accum_rscale;
10162  int val_rscale;
10163 
10164  accum_weight = old_weight;
10165  accum_ndigits = old_ndigits;
10166 
10167  /*
10168  * Does the new value have a larger weight? If so, enlarge the buffers,
10169  * and shift the existing value to the new weight, by adding leading
10170  * zeros.
10171  *
10172  * We enforce that the accumulator always has a weight one larger than
10173  * needed for the inputs, so that we have space for an extra digit at the
10174  * final carry-propagation phase, if necessary.
10175  */
10176  if (val->weight >= accum_weight)
10177  {
10178  accum_weight = val->weight + 1;
10179  accum_ndigits = accum_ndigits + (accum_weight - old_weight);
10180  }
10181 
10182  /*
10183  * Even though the new value is small, we might've used up the space
10184  * reserved for the carry digit in the last call to accum_sum_carry(). If
10185  * so, enlarge to make room for another one.
10186  */
10187  else if (!accum->have_carry_space)
10188  {
10189  accum_weight++;
10190  accum_ndigits++;
10191  }
10192 
10193  /* Is the new value wider on the right side? */
10194  accum_rscale = accum_ndigits - accum_weight - 1;
10195  val_rscale = val->ndigits - val->weight - 1;
10196  if (val_rscale > accum_rscale)
10197  accum_ndigits = accum_ndigits + (val_rscale - accum_rscale);
10198 
10199  if (accum_ndigits != old_ndigits ||
10200  accum_weight != old_weight)
10201  {
10202  int32 *new_pos_digits;
10203  int32 *new_neg_digits;
10204  int weightdiff;
10205 
10206  weightdiff = accum_weight - old_weight;
10207 
10208  new_pos_digits = palloc0(accum_ndigits * sizeof(int32));
10209  new_neg_digits = palloc0(accum_ndigits * sizeof(int32));
10210 
10211  if (accum->pos_digits)
10212  {
10213  memcpy(&new_pos_digits[weightdiff], accum->pos_digits,
10214  old_ndigits * sizeof(int32));
10215  pfree(accum->pos_digits);
10216 
10217  memcpy(&new_neg_digits[weightdiff], accum->neg_digits,
10218  old_ndigits * sizeof(int32));
10219  pfree(accum->neg_digits);
10220  }
10221 
10222  accum->pos_digits = new_pos_digits;
10223  accum->neg_digits = new_neg_digits;
10224 
10225  accum->weight = accum_weight;
10226  accum->ndigits = accum_ndigits;
10227 
10228  Assert(accum->pos_digits[0] == 0 && accum->neg_digits[0] == 0);
10229  accum->have_carry_space = true;
10230  }
10231 
10232  if (val->dscale > accum->dscale)
10233  accum->dscale = val->dscale;
10234 }
int weight
Definition: numeric.c:276
int32 * neg_digits
Definition: numeric.c:348
int ndigits
Definition: numeric.c:275
int dscale
Definition: numeric.c:278
signed int int32
Definition: c.h:355
void pfree(void *pointer)
Definition: mcxt.c:1056
bool have_carry_space
Definition: numeric.c:346
void * palloc0(Size size)
Definition: mcxt.c:980
#define Assert(condition)
Definition: c.h:738
int32 * pos_digits
Definition: numeric.c:347

◆ accum_sum_reset()

static void accum_sum_reset ( NumericSumAccum accum)
static

Definition at line 10018 of file numeric.c.

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

Referenced by do_numeric_discard().

10019 {
10020  int i;
10021 
10022  accum->dscale = 0;
10023  for (i = 0; i < accum->ndigits; i++)
10024  {
10025  accum->pos_digits[i] = 0;
10026  accum->neg_digits[i] = 0;
10027  }
10028 }
int32 * neg_digits
Definition: numeric.c:348
int i
int32 * pos_digits
Definition: numeric.c:347

◆ add_abs()

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

Definition at line 9642 of file numeric.c.

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

Referenced by add_var(), and sub_var().

9643 {
9644  NumericDigit *res_buf;
9645  NumericDigit *res_digits;
9646  int res_ndigits;
9647  int res_weight;
9648  int res_rscale,
9649  rscale1,
9650  rscale2;
9651  int res_dscale;
9652  int i,
9653  i1,
9654  i2;
9655  int carry = 0;
9656 
9657  /* copy these values into local vars for speed in inner loop */
9658  int var1ndigits = var1->ndigits;
9659  int var2ndigits = var2->ndigits;
9660  NumericDigit *var1digits = var1->digits;
9661  NumericDigit *var2digits = var2->digits;
9662 
9663  res_weight = Max(var1->weight, var2->weight) + 1;
9664 
9665  res_dscale = Max(var1->dscale, var2->dscale);
9666 
9667  /* Note: here we are figuring rscale in base-NBASE digits */
9668  rscale1 = var1->ndigits - var1->weight - 1;
9669  rscale2 = var2->ndigits - var2->weight - 1;
9670  res_rscale = Max(rscale1, rscale2);
9671 
9672  res_ndigits = res_rscale + res_weight + 1;
9673  if (res_ndigits <= 0)
9674  res_ndigits = 1;
9675 
9676  res_buf = digitbuf_alloc(res_ndigits + 1);
9677  res_buf[0] = 0; /* spare digit for later rounding */
9678  res_digits = res_buf + 1;
9679 
9680  i1 = res_rscale + var1->weight + 1;
9681  i2 = res_rscale + var2->weight + 1;
9682  for (i = res_ndigits - 1; i >= 0; i--)
9683  {
9684  i1--;
9685  i2--;
9686  if (i1 >= 0 && i1 < var1ndigits)
9687  carry += var1digits[i1];
9688  if (i2 >= 0 && i2 < var2ndigits)
9689  carry += var2digits[i2];
9690 
9691  if (carry >= NBASE)
9692  {
9693  res_digits[i] = carry - NBASE;
9694  carry = 1;
9695  }
9696  else
9697  {
9698  res_digits[i] = carry;
9699  carry = 0;
9700  }
9701  }
9702 
9703  Assert(carry == 0); /* else we failed to allow for carry out */
9704 
9705  digitbuf_free(result->buf);
9706  result->ndigits = res_ndigits;
9707  result->buf = res_buf;
9708  result->digits = res_digits;
9709  result->weight = res_weight;
9710  result->dscale = res_dscale;
9711 
9712  /* Remove leading/trailing zeroes */
9713  strip_var(result);
9714 }
int weight
Definition: numeric.c:276
static void strip_var(NumericVar *var)
Definition: numeric.c:9977
#define digitbuf_alloc(ndigits)
Definition: numeric.c:437
int ndigits
Definition: numeric.c:275
int dscale
Definition: numeric.c:278
#define digitbuf_free(buf)
Definition: numeric.c:439
int16 NumericDigit
Definition: numeric.c:103
NumericDigit * buf
Definition: numeric.c:279
#define NBASE
Definition: numeric.c:97
#define Assert(condition)
Definition: c.h:738
NumericDigit * digits
Definition: numeric.c:280
int i
#define Max(x, y)
Definition: numeric.c:13

◆ add_var()

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

Definition at line 7084 of file numeric.c.

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

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

7085 {
7086  /*
7087  * Decide on the signs of the two variables what to do
7088  */
7089  if (var1->sign == NUMERIC_POS)
7090  {
7091  if (var2->sign == NUMERIC_POS)
7092  {
7093  /*
7094  * Both are positive result = +(ABS(var1) + ABS(var2))
7095  */
7096  add_abs(var1, var2, result);
7097  result->sign = NUMERIC_POS;
7098  }
7099  else
7100  {
7101  /*
7102  * var1 is positive, var2 is negative Must compare absolute values
7103  */
7104  switch (cmp_abs(var1, var2))
7105  {
7106  case 0:
7107  /* ----------
7108  * ABS(var1) == ABS(var2)
7109  * result = ZERO
7110  * ----------
7111  */
7112  zero_var(result);
7113  result->dscale = Max(var1->dscale, var2->dscale);
7114  break;
7115 
7116  case 1:
7117  /* ----------
7118  * ABS(var1) > ABS(var2)
7119  * result = +(ABS(var1) - ABS(var2))
7120  * ----------
7121  */
7122  sub_abs(var1, var2, result);
7123  result->sign = NUMERIC_POS;
7124  break;
7125 
7126  case -1:
7127  /* ----------
7128  * ABS(var1) < ABS(var2)
7129  * result = -(ABS(var2) - ABS(var1))
7130  * ----------
7131  */
7132  sub_abs(var2, var1, result);
7133  result->sign = NUMERIC_NEG;
7134  break;
7135  }
7136  }
7137  }
7138  else
7139  {
7140  if (var2->sign == NUMERIC_POS)
7141  {
7142  /* ----------
7143  * var1 is negative, var2 is positive
7144  * Must compare absolute values
7145  * ----------
7146  */
7147  switch (cmp_abs(var1, var2))
7148  {
7149  case 0:
7150  /* ----------
7151  * ABS(var1) == ABS(var2)
7152  * result = ZERO
7153  * ----------
7154  */
7155  zero_var(result);
7156  result->dscale = Max(var1->dscale, var2->dscale);
7157  break;
7158 
7159  case 1:
7160  /* ----------
7161  * ABS(var1) > ABS(var2)
7162  * result = -(ABS(var1) - ABS(var2))
7163  * ----------
7164  */
7165  sub_abs(var1, var2, result);
7166  result->sign = NUMERIC_NEG;
7167  break;
7168 
7169  case -1:
7170  /* ----------
7171  * ABS(var1) < ABS(var2)
7172  * result = +(ABS(var2) - ABS(var1))
7173  * ----------
7174  */
7175  sub_abs(var2, var1, result);
7176  result->sign = NUMERIC_POS;
7177  break;
7178  }
7179  }
7180  else
7181  {
7182  /* ----------
7183  * Both are negative
7184  * result = -(ABS(var1) + ABS(var2))
7185  * ----------
7186  */
7187  add_abs(var1, var2, result);
7188  result->sign = NUMERIC_NEG;
7189  }
7190  }
7191 }
static void sub_abs(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition: numeric.c:9727
static void add_abs(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition: numeric.c:9642
#define NUMERIC_POS
Definition: numeric.c:168
int dscale
Definition: numeric.c:278
#define NUMERIC_NEG
Definition: numeric.c:169
int sign
Definition: numeric.c:277
static void zero_var(NumericVar *var)
Definition: numeric.c:5966
static int cmp_abs(const NumericVar *var1, const NumericVar *var2)
Definition: numeric.c:9564
#define Max(x, y)
Definition: numeric.c:13

◆ alloc_var()

static void alloc_var ( NumericVar var,
int  ndigits 
)
static

Definition at line 5934 of file numeric.c.

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

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

5935 {
5936  digitbuf_free(var->buf);
5937  var->buf = digitbuf_alloc(ndigits + 1);
5938  var->buf[0] = 0; /* spare digit for rounding */
5939  var->digits = var->buf + 1;
5940  var->ndigits = ndigits;
5941 }
#define digitbuf_alloc(ndigits)
Definition: numeric.c:437
int ndigits
Definition: numeric.c:275
#define digitbuf_free(buf)
Definition: numeric.c:439
NumericDigit * buf
Definition: numeric.c:279
NumericDigit * digits
Definition: numeric.c:280

◆ apply_typmod()

static void apply_typmod ( NumericVar var,
int32  typmod 
)
static

Definition at line 6579 of file numeric.c.

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

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

6580 {
6581  int precision;
6582  int scale;
6583  int maxdigits;
6584  int ddigits;
6585  int i;
6586 
6587  /* Do nothing if we have a default typmod (-1) */
6588  if (typmod < (int32) (VARHDRSZ))
6589  return;
6590 
6591  typmod -= VARHDRSZ;
6592  precision = (typmod >> 16) & 0xffff;
6593  scale = typmod & 0xffff;
6594  maxdigits = precision - scale;
6595 
6596  /* Round to target scale (and set var->dscale) */
6597  round_var(var, scale);
6598 
6599  /*
6600  * Check for overflow - note we can't do this before rounding, because
6601  * rounding could raise the weight. Also note that the var's weight could
6602  * be inflated by leading zeroes, which will be stripped before storage
6603  * but perhaps might not have been yet. In any case, we must recognize a
6604  * true zero, whose weight doesn't mean anything.
6605  */
6606  ddigits = (var->weight + 1) * DEC_DIGITS;
6607  if (ddigits > maxdigits)
6608  {
6609  /* Determine true weight; and check for all-zero result */
6610  for (i = 0; i < var->ndigits; i++)
6611  {
6612  NumericDigit dig = var->digits[i];
6613 
6614  if (dig)
6615  {
6616  /* Adjust for any high-order decimal zero digits */
6617 #if DEC_DIGITS == 4
6618  if (dig < 10)
6619  ddigits -= 3;
6620  else if (dig < 100)
6621  ddigits -= 2;
6622  else if (dig < 1000)
6623  ddigits -= 1;
6624 #elif DEC_DIGITS == 2
6625  if (dig < 10)
6626  ddigits -= 1;
6627 #elif DEC_DIGITS == 1
6628  /* no adjustment */
6629 #else
6630 #error unsupported NBASE
6631 #endif
6632  if (ddigits > maxdigits)
6633  ereport(ERROR,
6634  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
6635  errmsg("numeric field overflow"),
6636  errdetail("A field with precision %d, scale %d must round to an absolute value less than %s%d.",
6637  precision, scale,
6638  /* Display 10^0 as 1 */
6639  maxdigits ? "10^" : "",
6640  maxdigits ? maxdigits : 1
6641  )));
6642  break;
6643  }
6644  ddigits -= DEC_DIGITS;
6645  }
6646  }
6647 }
static void round_var(NumericVar *var, int rscale)
Definition: numeric.c:9809
int weight
Definition: numeric.c:276
#define VARHDRSZ
Definition: c.h:561
int errcode(int sqlerrcode)
Definition: elog.c:610
int scale
Definition: pgbench.c:153
int ndigits
Definition: numeric.c:275
signed int int32
Definition: c.h:355
#define ERROR
Definition: elog.h:43
int16 NumericDigit
Definition: numeric.c:103
int errdetail(const char *fmt,...)
Definition: elog.c:957
#define ereport(elevel,...)
Definition: elog.h:144
int maxdigits
Definition: informix.c:665
NumericDigit * digits
Definition: numeric.c:280
int errmsg(const char *fmt,...)
Definition: elog.c:824
int i
#define DEC_DIGITS
Definition: numeric.c:99

◆ ceil_var()

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

Definition at line 8278 of file numeric.c.

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

Referenced by numeric_ceil().

8279 {
8280  NumericVar tmp;
8281 
8282  init_var(&tmp);
8283  set_var_from_var(var, &tmp);
8284 
8285  trunc_var(&tmp, 0);
8286 
8287  if (var->sign == NUMERIC_POS && cmp_var(var, &tmp) != 0)
8288  add_var(&tmp, &const_one, &tmp);
8289 
8290  set_var_from_var(&tmp, result);
8291  free_var(&tmp);
8292 }
static void trunc_var(NumericVar *var, int rscale)
Definition: numeric.c:9915
static const NumericVar const_one
Definition: numeric.c:379
#define NUMERIC_POS
Definition: numeric.c:168
int sign
Definition: numeric.c:277
static int cmp_var(const NumericVar *var1, const NumericVar *var2)
Definition: numeric.c:7026
static void free_var(NumericVar *var)
Definition: numeric.c:5950
static void add_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition: numeric.c:7084
static void set_var_from_var(const NumericVar *value, NumericVar *dest)
Definition: numeric.c:6200
#define init_var(v)
Definition: numeric.c:445

◆ cmp_abs()

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

Definition at line 9564 of file numeric.c.

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

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

9565 {
9566  return cmp_abs_common(var1->digits, var1->ndigits, var1->weight,
9567  var2->digits, var2->ndigits, var2->weight);
9568 }
int weight
Definition: numeric.c:276
int ndigits
Definition: numeric.c:275
NumericDigit * digits
Definition: numeric.c:280
static int cmp_abs_common(const NumericDigit *var1digits, int var1ndigits, int var1weight, const NumericDigit *var2digits, int var2ndigits, int var2weight)
Definition: numeric.c:9578

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

References stat.

Referenced by cmp_abs(), and cmp_var_common().

9580 {
9581  int i1 = 0;
9582  int i2 = 0;
9583 
9584  /* Check any digits before the first common digit */
9585 
9586  while (var1weight > var2weight && i1 < var1ndigits)
9587  {
9588  if (var1digits[i1++] != 0)
9589  return 1;
9590  var1weight--;
9591  }
9592  while (var2weight > var1weight && i2 < var2ndigits)
9593  {
9594  if (var2digits[i2++] != 0)
9595  return -1;
9596  var2weight--;
9597  }
9598 
9599  /* At this point, either w1 == w2 or we've run out of digits */
9600 
9601  if (var1weight == var2weight)
9602  {
9603  while (i1 < var1ndigits && i2 < var2ndigits)
9604  {
9605  int stat = var1digits[i1++] - var2digits[i2++];
9606 
9607  if (stat)
9608  {
9609  if (stat > 0)
9610  return 1;
9611  return -1;
9612  }
9613  }
9614  }
9615 
9616  /*
9617  * At this point, we've run out of digits on one side or the other; so any
9618  * remaining nonzero digits imply that side is larger
9619  */
9620  while (i1 < var1ndigits)
9621  {
9622  if (var1digits[i1++] != 0)
9623  return 1;
9624  }
9625  while (i2 < var2ndigits)
9626  {
9627  if (var2digits[i2++] != 0)
9628  return -1;
9629  }
9630 
9631  return 0;
9632 }
#define stat(a, b)
Definition: win32_port.h:255

◆ cmp_numerics()

static int cmp_numerics ( Numeric  num1,
Numeric  num2 
)
static

Definition at line 2148 of file numeric.c.

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

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

2149 {
2150  int result;
2151 
2152  /*
2153  * We consider all NANs to be equal and larger than any non-NAN. This is
2154  * somewhat arbitrary; the important thing is to have a consistent sort
2155  * order.
2156  */
2157  if (NUMERIC_IS_NAN(num1))
2158  {
2159  if (NUMERIC_IS_NAN(num2))
2160  result = 0; /* NAN = NAN */
2161  else
2162  result = 1; /* NAN > non-NAN */
2163  }
2164  else if (NUMERIC_IS_NAN(num2))
2165  {
2166  result = -1; /* non-NAN < NAN */
2167  }
2168  else
2169  {
2170  result = cmp_var_common(NUMERIC_DIGITS(num1), NUMERIC_NDIGITS(num1),
2171  NUMERIC_WEIGHT(num1), NUMERIC_SIGN(num1),
2172  NUMERIC_DIGITS(num2), NUMERIC_NDIGITS(num2),
2173  NUMERIC_WEIGHT(num2), NUMERIC_SIGN(num2));
2174  }
2175 
2176  return result;
2177 }
#define NUMERIC_DIGITS(num)
Definition: numeric.c:447
#define NUMERIC_SIGN(n)
Definition: numeric.c:210
#define NUMERIC_NDIGITS(num)
Definition: numeric.c:449
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:7041
#define NUMERIC_WEIGHT(n)
Definition: numeric.c:218
#define NUMERIC_IS_NAN(n)
Definition: numeric.c:174

◆ cmp_var()

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

Definition at line 7026 of file numeric.c.

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

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

7027 {
7028  return cmp_var_common(var1->digits, var1->ndigits,
7029  var1->weight, var1->sign,
7030  var2->digits, var2->ndigits,
7031  var2->weight, var2->sign);
7032 }
int weight
Definition: numeric.c:276
int ndigits
Definition: numeric.c:275
int sign
Definition: numeric.c:277
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:7041
NumericDigit * digits
Definition: numeric.c:280

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

References cmp_abs_common(), NUMERIC_NEG, and NUMERIC_POS.

Referenced by cmp_numerics(), and cmp_var().

7045 {
7046  if (var1ndigits == 0)
7047  {
7048  if (var2ndigits == 0)
7049  return 0;
7050  if (var2sign == NUMERIC_NEG)
7051  return 1;
7052  return -1;
7053  }
7054  if (var2ndigits == 0)
7055  {
7056  if (var1sign == NUMERIC_POS)
7057  return 1;
7058  return -1;
7059  }
7060 
7061  if (var1sign == NUMERIC_POS)
7062  {
7063  if (var2sign == NUMERIC_NEG)
7064  return 1;
7065  return cmp_abs_common(var1digits, var1ndigits, var1weight,
7066  var2digits, var2ndigits, var2weight);
7067  }
7068 
7069  if (var2sign == NUMERIC_POS)
7070  return -1;
7071 
7072  return cmp_abs_common(var2digits, var2ndigits, var2weight,
7073  var1digits, var1ndigits, var1weight);
7074 }
#define NUMERIC_POS
Definition: numeric.c:168
#define NUMERIC_NEG
Definition: numeric.c:169
static int cmp_abs_common(const NumericDigit *var1digits, int var1ndigits, int var1weight, const NumericDigit *var2digits, int var2ndigits, int var2weight)
Definition: numeric.c:9578

◆ compute_bucket()

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

Definition at line 1575 of file numeric.c.

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

Referenced by width_bucket_numeric().

1577 {
1578  NumericVar bound1_var;
1579  NumericVar bound2_var;
1580  NumericVar operand_var;
1581 
1582  init_var_from_num(bound1, &bound1_var);
1583  init_var_from_num(bound2, &bound2_var);
1584  init_var_from_num(operand, &operand_var);
1585 
1586  if (cmp_var(&bound1_var, &bound2_var) < 0)
1587  {
1588  sub_var(&operand_var, &bound1_var, &operand_var);
1589  sub_var(&bound2_var, &bound1_var, &bound2_var);
1590  div_var(&operand_var, &bound2_var, result_var,
1591  select_div_scale(&operand_var, &bound2_var), true);
1592  }
1593  else
1594  {
1595  sub_var(&bound1_var, &operand_var, &operand_var);
1596  sub_var(&bound1_var, &bound2_var, &bound1_var);
1597  div_var(&operand_var, &bound1_var, result_var,
1598  select_div_scale(&operand_var, &bound1_var), true);
1599  }
1600 
1601  mul_var(result_var, count_var, result_var,
1602  result_var->dscale + count_var->dscale);
1603  add_var(result_var, &const_one, result_var);
1604  floor_var(result_var, result_var);
1605 
1606  free_var(&bound1_var);
1607  free_var(&bound2_var);
1608  free_var(&operand_var);
1609 }
static const NumericVar const_one
Definition: numeric.c:379
static void div_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result, int rscale, bool round)
Definition: numeric.c:7519
int dscale
Definition: numeric.c:278
static int select_div_scale(const NumericVar *var1, const NumericVar *var2)
Definition: numeric.c:8110
static void init_var_from_num(Numeric num, NumericVar *dest)
Definition: numeric.c:6183
static int cmp_var(const NumericVar *var1, const NumericVar *var2)
Definition: numeric.c:7026
static void free_var(NumericVar *var)
Definition: numeric.c:5950
static void mul_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result, int rscale)
Definition: numeric.c:7322
static void add_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition: numeric.c:7084
static void sub_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition: numeric.c:7201
static void floor_var(const NumericVar *var, NumericVar *result)
Definition: numeric.c:8302

◆ div_mod_var()

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

Definition at line 8208 of file numeric.c.

References add_var(), cmp_abs(), 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().

8210 {
8211  NumericVar q;
8212  NumericVar r;
8213 
8214  init_var(&q);
8215  init_var(&r);
8216 
8217  /*
8218  * Use div_var_fast() to get an initial estimate for the integer quotient.
8219  * This might be inaccurate (per the warning in div_var_fast's comments),
8220  * but we can correct it below.
8221  */
8222  div_var_fast(var1, var2, &q, 0, false);
8223 
8224  /* Compute initial estimate of remainder using the quotient estimate. */
8225  mul_var(var2, &q, &r, var2->dscale);
8226  sub_var(var1, &r, &r);
8227 
8228  /*
8229  * Adjust the results if necessary --- the remainder should have the same
8230  * sign as var1, and its absolute value should be less than the absolute
8231  * value of var2.
8232  */
8233  while (r.ndigits != 0 && r.sign != var1->sign)
8234  {
8235  /* The absolute value of the quotient is too large */
8236  if (var1->sign == var2->sign)
8237  {
8238  sub_var(&q, &const_one, &q);
8239  add_var(&r, var2, &r);
8240  }
8241  else
8242  {
8243  add_var(&q, &const_one, &q);
8244  sub_var(&r, var2, &r);
8245  }
8246  }
8247 
8248  while (cmp_abs(&r, var2) >= 0)
8249  {
8250  /* The absolute value of the quotient is too small */
8251  if (var1->sign == var2->sign)
8252  {
8253  add_var(&q, &const_one, &q);
8254  sub_var(&r, var2, &r);
8255  }
8256  else
8257  {
8258  sub_var(&q, &const_one, &q);
8259  add_var(&r, var2, &r);
8260  }
8261  }
8262 
8263  set_var_from_var(&q, quot);
8264  set_var_from_var(&r, rem);
8265 
8266  free_var(&q);
8267  free_var(&r);
8268 }
static const NumericVar const_one
Definition: numeric.c:379
int ndigits
Definition: numeric.c:275
int dscale
Definition: numeric.c:278
int sign
Definition: numeric.c:277
static void div_var_fast(const NumericVar *var1, const NumericVar *var2, NumericVar *result, int rscale, bool round)
Definition: numeric.c:7804
static void free_var(NumericVar *var)
Definition: numeric.c:5950
static void mul_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result, int rscale)
Definition: numeric.c:7322
static void add_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition: numeric.c:7084
static int cmp_abs(const NumericVar *var1, const NumericVar *var2)
Definition: numeric.c:9564
static void sub_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition: numeric.c:7201
static void set_var_from_var(const NumericVar *value, NumericVar *dest)
Definition: numeric.c:6200
#define init_var(v)
Definition: numeric.c:445

◆ div_var()

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

Definition at line 7519 of file numeric.c.

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

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

7521 {
7522  int div_ndigits;
7523  int res_ndigits;
7524  int res_sign;
7525  int res_weight;
7526  int carry;
7527  int borrow;
7528  int divisor1;
7529  int divisor2;
7530  NumericDigit *dividend;
7531  NumericDigit *divisor;
7532  NumericDigit *res_digits;
7533  int i;
7534  int j;
7535 
7536  /* copy these values into local vars for speed in inner loop */
7537  int var1ndigits = var1->ndigits;
7538  int var2ndigits = var2->ndigits;
7539 
7540  /*
7541  * First of all division by zero check; we must not be handed an
7542  * unnormalized divisor.
7543  */
7544  if (var2ndigits == 0 || var2->digits[0] == 0)
7545  ereport(ERROR,
7546  (errcode(ERRCODE_DIVISION_BY_ZERO),
7547  errmsg("division by zero")));
7548 
7549  /*
7550  * Now result zero check
7551  */
7552  if (var1ndigits == 0)
7553  {
7554  zero_var(result);
7555  result->dscale = rscale;
7556  return;
7557  }
7558 
7559  /*
7560  * Determine the result sign, weight and number of digits to calculate.
7561  * The weight figured here is correct if the emitted quotient has no
7562  * leading zero digits; otherwise strip_var() will fix things up.
7563  */
7564  if (var1->sign == var2->sign)
7565  res_sign = NUMERIC_POS;
7566  else
7567  res_sign = NUMERIC_NEG;
7568  res_weight = var1->weight - var2->weight;
7569  /* The number of accurate result digits we need to produce: */
7570  res_ndigits = res_weight + 1 + (rscale + DEC_DIGITS - 1) / DEC_DIGITS;
7571  /* ... but always at least 1 */
7572  res_ndigits = Max(res_ndigits, 1);
7573  /* If rounding needed, figure one more digit to ensure correct result */
7574  if (round)
7575  res_ndigits++;
7576 
7577  /*
7578  * The working dividend normally requires res_ndigits + var2ndigits
7579  * digits, but make it at least var1ndigits so we can load all of var1
7580  * into it. (There will be an additional digit dividend[0] in the
7581  * dividend space, but for consistency with Knuth's notation we don't
7582  * count that in div_ndigits.)
7583  */
7584  div_ndigits = res_ndigits + var2ndigits;
7585  div_ndigits = Max(div_ndigits, var1ndigits);
7586 
7587  /*
7588  * We need a workspace with room for the working dividend (div_ndigits+1
7589  * digits) plus room for the possibly-normalized divisor (var2ndigits
7590  * digits). It is convenient also to have a zero at divisor[0] with the
7591  * actual divisor data in divisor[1 .. var2ndigits]. Transferring the
7592  * digits into the workspace also allows us to realloc the result (which
7593  * might be the same as either input var) before we begin the main loop.
7594  * Note that we use palloc0 to ensure that divisor[0], dividend[0], and
7595  * any additional dividend positions beyond var1ndigits, start out 0.
7596  */
7597  dividend = (NumericDigit *)
7598  palloc0((div_ndigits + var2ndigits + 2) * sizeof(NumericDigit));
7599  divisor = dividend + (div_ndigits + 1);
7600  memcpy(dividend + 1, var1->digits, var1ndigits * sizeof(NumericDigit));
7601  memcpy(divisor + 1, var2->digits, var2ndigits * sizeof(NumericDigit));
7602 
7603  /*
7604  * Now we can realloc the result to hold the generated quotient digits.
7605  */
7606  alloc_var(result, res_ndigits);
7607  res_digits = result->digits;
7608 
7609  if (var2ndigits == 1)
7610  {
7611  /*
7612  * If there's only a single divisor digit, we can use a fast path (cf.
7613  * Knuth section 4.3.1 exercise 16).
7614  */
7615  divisor1 = divisor[1];
7616  carry = 0;
7617  for (i = 0; i < res_ndigits; i++)
7618  {
7619  carry = carry * NBASE + dividend[i + 1];
7620  res_digits[i] = carry / divisor1;
7621  carry = carry % divisor1;
7622  }
7623  }
7624  else
7625  {
7626  /*
7627  * The full multiple-place algorithm is taken from Knuth volume 2,
7628  * Algorithm 4.3.1D.
7629  *
7630  * We need the first divisor digit to be >= NBASE/2. If it isn't,
7631  * make it so by scaling up both the divisor and dividend by the
7632  * factor "d". (The reason for allocating dividend[0] above is to
7633  * leave room for possible carry here.)
7634  */
7635  if (divisor[1] < HALF_NBASE)
7636  {
7637  int d = NBASE / (divisor[1] + 1);
7638 
7639  carry = 0;
7640  for (i = var2ndigits; i > 0; i--)
7641  {
7642  carry += divisor[i] * d;
7643  divisor[i] = carry % NBASE;
7644  carry = carry / NBASE;
7645  }
7646  Assert(carry == 0);
7647  carry = 0;
7648  /* at this point only var1ndigits of dividend can be nonzero */
7649  for (i = var1ndigits; i >= 0; i--)
7650  {
7651  carry += dividend[i] * d;
7652  dividend[i] = carry % NBASE;
7653  carry = carry / NBASE;
7654  }
7655  Assert(carry == 0);
7656  Assert(divisor[1] >= HALF_NBASE);
7657  }
7658  /* First 2 divisor digits are used repeatedly in main loop */
7659  divisor1 = divisor[1];
7660  divisor2 = divisor[2];
7661 
7662  /*
7663  * Begin the main loop. Each iteration of this loop produces the j'th
7664  * quotient digit by dividing dividend[j .. j + var2ndigits] by the
7665  * divisor; this is essentially the same as the common manual
7666  * procedure for long division.
7667  */
7668  for (j = 0; j < res_ndigits; j++)
7669  {
7670  /* Estimate quotient digit from the first two dividend digits */
7671  int next2digits = dividend[j] * NBASE + dividend[j + 1];
7672  int qhat;
7673 
7674  /*
7675  * If next2digits are 0, then quotient digit must be 0 and there's
7676  * no need to adjust the working dividend. It's worth testing
7677  * here to fall out ASAP when processing trailing zeroes in a
7678  * dividend.
7679  */
7680  if (next2digits == 0)
7681  {
7682  res_digits[j] = 0;
7683  continue;
7684  }
7685 
7686  if (dividend[j] == divisor1)
7687  qhat = NBASE - 1;
7688  else
7689  qhat = next2digits / divisor1;
7690 
7691  /*
7692  * Adjust quotient digit if it's too large. Knuth proves that
7693  * after this step, the quotient digit will be either correct or
7694  * just one too large. (Note: it's OK to use dividend[j+2] here
7695  * because we know the divisor length is at least 2.)
7696  */
7697  while (divisor2 * qhat >
7698  (next2digits - qhat * divisor1) * NBASE + dividend[j + 2])
7699  qhat--;
7700 
7701  /* As above, need do nothing more when quotient digit is 0 */
7702  if (qhat > 0)
7703  {
7704  /*
7705  * Multiply the divisor by qhat, and subtract that from the
7706  * working dividend. "carry" tracks the multiplication,
7707  * "borrow" the subtraction (could we fold these together?)
7708  */
7709  carry = 0;
7710  borrow = 0;
7711  for (i = var2ndigits; i >= 0; i--)
7712  {
7713  carry += divisor[i] * qhat;
7714  borrow -= carry % NBASE;
7715  carry = carry / NBASE;
7716  borrow += dividend[j + i];
7717  if (borrow < 0)
7718  {
7719  dividend[j + i] = borrow + NBASE;
7720  borrow = -1;
7721  }
7722  else
7723  {
7724  dividend[j + i] = borrow;
7725  borrow = 0;
7726  }
7727  }
7728  Assert(carry == 0);
7729 
7730  /*
7731  * If we got a borrow out of the top dividend digit, then
7732  * indeed qhat was one too large. Fix it, and add back the
7733  * divisor to correct the working dividend. (Knuth proves
7734  * that this will occur only about 3/NBASE of the time; hence,
7735  * it's a good idea to test this code with small NBASE to be
7736  * sure this section gets exercised.)
7737  */
7738  if (borrow)
7739  {
7740  qhat--;
7741  carry = 0;
7742  for (i = var2ndigits; i >= 0; i--)
7743  {
7744  carry += dividend[j + i] + divisor[i];
7745  if (carry >= NBASE)
7746  {
7747  dividend[j + i] = carry - NBASE;
7748  carry = 1;
7749  }
7750  else
7751  {
7752  dividend[j + i] = carry;
7753  carry = 0;
7754  }
7755  }
7756  /* A carry should occur here to cancel the borrow above */
7757  Assert(carry == 1);
7758  }
7759  }
7760 
7761  /* And we're done with this quotient digit */
7762  res_digits[j] = qhat;
7763  }
7764  }
7765 
7766  pfree(dividend);
7767 
7768  /*
7769  * Finally, round or truncate the result to the requested precision.
7770  */
7771  result->weight = res_weight;
7772  result->sign = res_sign;
7773 
7774  /* Round or truncate to target rscale (and set result->dscale) */
7775  if (round)
7776  round_var(result, rscale);
7777  else
7778  trunc_var(result, rscale);
7779 
7780  /* Strip leading and trailing zeroes */
7781  strip_var(result);
7782 }
static void round_var(NumericVar *var, int rscale)
Definition: numeric.c:9809
static void trunc_var(NumericVar *var, int rscale)
Definition: numeric.c:9915
int weight
Definition: numeric.c:276
#define NUMERIC_POS
Definition: numeric.c:168
static void strip_var(NumericVar *var)
Definition: numeric.c:9977
int errcode(int sqlerrcode)
Definition: elog.c:610
int ndigits
Definition: numeric.c:275
int dscale
Definition: numeric.c:278
#define NUMERIC_NEG
Definition: numeric.c:169
int sign
Definition: numeric.c:277
static void zero_var(NumericVar *var)
Definition: numeric.c:5966
void pfree(void *pointer)
Definition: mcxt.c:1056
#define ERROR
Definition: elog.h:43
int16 NumericDigit
Definition: numeric.c:103
#define HALF_NBASE
Definition: numeric.c:98
#define NBASE
Definition: numeric.c:97
void * palloc0(Size size)
Definition: mcxt.c:980
#define ereport(elevel,...)
Definition: elog.h:144
#define Assert(condition)
Definition: c.h:738
NumericDigit * digits
Definition: numeric.c:280
int errmsg(const char *fmt,...)
Definition: elog.c:824
static void alloc_var(NumericVar *var, int ndigits)
Definition: numeric.c:5934
int i
#define Max(x, y)
Definition: numeric.c:13
#define DEC_DIGITS
Definition: numeric.c:99

◆ div_var_fast()

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

Definition at line 7804 of file numeric.c.

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

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

7806 {
7807  int div_ndigits;
7808  int load_ndigits;
7809  int res_sign;
7810  int res_weight;
7811  int *div;
7812  int qdigit;
7813  int carry;
7814  int maxdiv;
7815  int newdig;
7816  NumericDigit *res_digits;
7817  double fdividend,
7818  fdivisor,
7819  fdivisorinverse,
7820  fquotient;
7821  int qi;
7822  int i;
7823 
7824  /* copy these values into local vars for speed in inner loop */
7825  int var1ndigits = var1->ndigits;
7826  int var2ndigits = var2->ndigits;
7827  NumericDigit *var1digits = var1->digits;
7828  NumericDigit *var2digits = var2->digits;
7829 
7830  /*
7831  * First of all division by zero check; we must not be handed an
7832  * unnormalized divisor.
7833  */
7834  if (var2ndigits == 0 || var2digits[0] == 0)
7835  ereport(ERROR,
7836  (errcode(ERRCODE_DIVISION_BY_ZERO),
7837  errmsg("division by zero")));
7838 
7839  /*
7840  * Now result zero check
7841  */
7842  if (var1ndigits == 0)
7843  {
7844  zero_var(result);
7845  result->dscale = rscale;
7846  return;
7847  }
7848 
7849  /*
7850  * Determine the result sign, weight and number of digits to calculate
7851  */
7852  if (var1->sign == var2->sign)
7853  res_sign = NUMERIC_POS;
7854  else
7855  res_sign = NUMERIC_NEG;
7856  res_weight = var1->weight - var2->weight + 1;
7857  /* The number of accurate result digits we need to produce: */
7858  div_ndigits = res_weight + 1 + (rscale + DEC_DIGITS - 1) / DEC_DIGITS;
7859  /* Add guard digits for roundoff error */
7860  div_ndigits += DIV_GUARD_DIGITS;
7861  if (div_ndigits < DIV_GUARD_DIGITS)
7862  div_ndigits = DIV_GUARD_DIGITS;
7863 
7864  /*
7865  * We do the arithmetic in an array "div[]" of signed int's. Since
7866  * INT_MAX is noticeably larger than NBASE*NBASE, this gives us headroom
7867  * to avoid normalizing carries immediately.
7868  *
7869  * We start with div[] containing one zero digit followed by the
7870  * dividend's digits (plus appended zeroes to reach the desired precision
7871  * including guard digits). Each step of the main loop computes an
7872  * (approximate) quotient digit and stores it into div[], removing one
7873  * position of dividend space. A final pass of carry propagation takes
7874  * care of any mistaken quotient digits.
7875  *
7876  * Note that div[] doesn't necessarily contain all of the digits from the
7877  * dividend --- the desired precision plus guard digits might be less than
7878  * the dividend's precision. This happens, for example, in the square
7879  * root algorithm, where we typically divide a 2N-digit number by an
7880  * N-digit number, and only require a result with N digits of precision.
7881  */
7882  div = (int *) palloc0((div_ndigits + 1) * sizeof(int));
7883  load_ndigits = Min(div_ndigits, var1ndigits);
7884  for (i = 0; i < load_ndigits; i++)
7885  div[i + 1] = var1digits[i];
7886 
7887  /*
7888  * We estimate each quotient digit using floating-point arithmetic, taking
7889  * the first four digits of the (current) dividend and divisor. This must
7890  * be float to avoid overflow. The quotient digits will generally be off
7891  * by no more than one from the exact answer.
7892  */
7893  fdivisor = (double) var2digits[0];
7894  for (i = 1; i < 4; i++)
7895  {
7896  fdivisor *= NBASE;
7897  if (i < var2ndigits)
7898  fdivisor += (double) var2digits[i];
7899  }
7900  fdivisorinverse = 1.0 / fdivisor;
7901 
7902  /*
7903  * maxdiv tracks the maximum possible absolute value of any div[] entry;
7904  * when this threatens to exceed INT_MAX, we take the time to propagate
7905  * carries. Furthermore, we need to ensure that overflow doesn't occur
7906  * during the carry propagation passes either. The carry values may have
7907  * an absolute value as high as INT_MAX/NBASE + 1, so really we must
7908  * normalize when digits threaten to exceed INT_MAX - INT_MAX/NBASE - 1.
7909  *
7910  * To avoid overflow in maxdiv itself, it represents the max absolute
7911  * value divided by NBASE-1, ie, at the top of the loop it is known that
7912  * no div[] entry has an absolute value exceeding maxdiv * (NBASE-1).
7913  *
7914  * Actually, though, that holds good only for div[] entries after div[qi];
7915  * the adjustment done at the bottom of the loop may cause div[qi + 1] to
7916  * exceed the maxdiv limit, so that div[qi] in the next iteration is
7917  * beyond the limit. This does not cause problems, as explained below.
7918  */
7919  maxdiv = 1;
7920 
7921  /*
7922  * Outer loop computes next quotient digit, which will go into div[qi]
7923  */
7924  for (qi = 0; qi < div_ndigits; qi++)
7925  {
7926  /* Approximate the current dividend value */
7927  fdividend = (double) div[qi];
7928  for (i = 1; i < 4; i++)
7929  {
7930  fdividend *= NBASE;
7931  if (qi + i <= div_ndigits)
7932  fdividend += (double) div[qi + i];
7933  }
7934  /* Compute the (approximate) quotient digit */
7935  fquotient = fdividend * fdivisorinverse;
7936  qdigit = (fquotient >= 0.0) ? ((int) fquotient) :
7937  (((int) fquotient) - 1); /* truncate towards -infinity */
7938 
7939  if (qdigit != 0)
7940  {
7941  /* Do we need to normalize now? */
7942  maxdiv += Abs(qdigit);
7943  if (maxdiv > (INT_MAX - INT_MAX / NBASE - 1) / (NBASE - 1))
7944  {
7945  /*
7946  * Yes, do it. Note that if var2ndigits is much smaller than
7947  * div_ndigits, we can save a significant amount of effort
7948  * here by noting that we only need to normalise those div[]
7949  * entries touched where prior iterations subtracted multiples
7950  * of the divisor.
7951  */
7952  carry = 0;
7953  for (i = Min(qi + var2ndigits - 2, div_ndigits); i > qi; i--)
7954  {
7955  newdig = div[i] + carry;
7956  if (newdig < 0)
7957  {
7958  carry = -((-newdig - 1) / NBASE) - 1;
7959  newdig -= carry * NBASE;
7960  }
7961  else if (newdig >= NBASE)
7962  {
7963  carry = newdig / NBASE;
7964  newdig -= carry * NBASE;
7965  }
7966  else
7967  carry = 0;
7968  div[i] = newdig;
7969  }
7970  newdig = div[qi] + carry;
7971  div[qi] = newdig;
7972 
7973  /*
7974  * All the div[] digits except possibly div[qi] are now in the
7975  * range 0..NBASE-1. We do not need to consider div[qi] in
7976  * the maxdiv value anymore, so we can reset maxdiv to 1.
7977  */
7978  maxdiv = 1;
7979 
7980  /*
7981  * Recompute the quotient digit since new info may have
7982  * propagated into the top four dividend digits
7983  */
7984  fdividend = (double) div[qi];
7985  for (i = 1; i < 4; i++)
7986  {
7987  fdividend *= NBASE;
7988  if (qi + i <= div_ndigits)
7989  fdividend += (double) div[qi + i];
7990  }
7991  /* Compute the (approximate) quotient digit */
7992  fquotient = fdividend * fdivisorinverse;
7993  qdigit = (fquotient >= 0.0) ? ((int) fquotient) :
7994  (((int) fquotient) - 1); /* truncate towards -infinity */
7995  maxdiv += Abs(qdigit);
7996  }
7997 
7998  /*
7999  * Subtract off the appropriate multiple of the divisor.
8000  *
8001  * The digits beyond div[qi] cannot overflow, because we know they
8002  * will fall within the maxdiv limit. As for div[qi] itself, note
8003  * that qdigit is approximately trunc(div[qi] / vardigits[0]),
8004  * which would make the new value simply div[qi] mod vardigits[0].
8005  * The lower-order terms in qdigit can change this result by not
8006  * more than about twice INT_MAX/NBASE, so overflow is impossible.
8007  */
8008  if (qdigit != 0)
8009  {
8010  int istop = Min(var2ndigits, div_ndigits - qi + 1);
8011 
8012  for (i = 0; i < istop; i++)
8013  div[qi + i] -= qdigit * var2digits[i];
8014  }
8015  }
8016 
8017  /*
8018  * The dividend digit we are about to replace might still be nonzero.
8019  * Fold it into the next digit position.
8020  *
8021  * There is no risk of overflow here, although proving that requires
8022  * some care. Much as with the argument for div[qi] not overflowing,
8023  * if we consider the first two terms in the numerator and denominator
8024  * of qdigit, we can see that the final value of div[qi + 1] will be
8025  * approximately a remainder mod (vardigits[0]*NBASE + vardigits[1]).
8026  * Accounting for the lower-order terms is a bit complicated but ends
8027  * up adding not much more than INT_MAX/NBASE to the possible range.
8028  * Thus, div[qi + 1] cannot overflow here, and in its role as div[qi]
8029  * in the next loop iteration, it can't be large enough to cause
8030  * overflow in the carry propagation step (if any), either.
8031  *
8032  * But having said that: div[qi] can be more than INT_MAX/NBASE, as
8033  * noted above, which means that the product div[qi] * NBASE *can*
8034  * overflow. When that happens, adding it to div[qi + 1] will always
8035  * cause a canceling overflow so that the end result is correct. We
8036  * could avoid the intermediate overflow by doing the multiplication
8037  * and addition in int64 arithmetic, but so far there appears no need.
8038  */
8039  div[qi + 1] += div[qi] * NBASE;
8040 
8041  div[qi] = qdigit;
8042  }
8043 
8044  /*
8045  * Approximate and store the last quotient digit (div[div_ndigits])
8046  */
8047  fdividend = (double) div[qi];
8048  for (i = 1; i < 4; i++)
8049  fdividend *= NBASE;
8050  fquotient = fdividend * fdivisorinverse;
8051  qdigit = (fquotient >= 0.0) ? ((int) fquotient) :
8052  (((int) fquotient) - 1); /* truncate towards -infinity */
8053  div[qi] = qdigit;
8054 
8055  /*
8056  * Because the quotient digits might be off by one, some of them might be
8057  * -1 or NBASE at this point. The represented value is correct in a
8058  * mathematical sense, but it doesn't look right. We do a final carry
8059  * propagation pass to normalize the digits, which we combine with storing
8060  * the result digits into the output. Note that this is still done at
8061  * full precision w/guard digits.
8062  */
8063  alloc_var(result, div_ndigits + 1);
8064  res_digits = result->digits;
8065  carry = 0;
8066  for (i = div_ndigits; i >= 0; i--)
8067  {
8068  newdig = div[i] + carry;
8069  if (newdig < 0)
8070  {
8071  carry = -((-newdig - 1) / NBASE) - 1;
8072  newdig -= carry * NBASE;
8073  }
8074  else if (newdig >= NBASE)
8075  {
8076  carry = newdig / NBASE;
8077  newdig -= carry * NBASE;
8078  }
8079  else
8080  carry = 0;
8081  res_digits[i] = newdig;
8082  }
8083  Assert(carry == 0);
8084 
8085  pfree(div);
8086 
8087  /*
8088  * Finally, round the result to the requested precision.
8089  */
8090  result->weight = res_weight;
8091  result->sign = res_sign;
8092 
8093  /* Round to target rscale (and set result->dscale) */
8094  if (round)
8095  round_var(result, rscale);
8096  else
8097  trunc_var(result, rscale);
8098 
8099  /* Strip leading and trailing zeroes */
8100  strip_var(result);
8101 }
static void round_var(NumericVar *var, int rscale)
Definition: numeric.c:9809
static void trunc_var(NumericVar *var, int rscale)
Definition: numeric.c:9915
int weight
Definition: numeric.c:276
#define NUMERIC_POS
Definition: numeric.c:168
static void strip_var(NumericVar *var)
Definition: numeric.c:9977
int errcode(int sqlerrcode)
Definition: elog.c:610
int ndigits
Definition: numeric.c:275
int dscale
Definition: numeric.c:278
#define Min(x, y)
Definition: numeric.c:14
#define Abs(x)
Definition: c.h:926
#define NUMERIC_NEG
Definition: numeric.c:169
int sign
Definition: numeric.c:277
static void zero_var(NumericVar *var)
Definition: numeric.c:5966
void pfree(void *pointer)
Definition: mcxt.c:1056
#define ERROR
Definition: elog.h:43
int16 NumericDigit
Definition: numeric.c:103
#define NBASE
Definition: numeric.c:97
void * palloc0(Size size)
Definition: mcxt.c:980
#define ereport(elevel,...)
Definition: elog.h:144
#define Assert(condition)
Definition: c.h:738
NumericDigit * digits
Definition: numeric.c:280
#define DIV_GUARD_DIGITS
Definition: numeric.c:101
int errmsg(const char *fmt,...)
Definition: elog.c:824
static void alloc_var(NumericVar *var, int ndigits)
Definition: numeric.c:5934
int i
#define DEC_DIGITS
Definition: numeric.c:99

◆ do_numeric_accum()

static void do_numeric_accum ( NumericAggState state,
Numeric  newval 
)
static

Definition at line 3792 of file numeric.c.

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

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

3793 {
3794  NumericVar X;
3795  NumericVar X2;
3796  MemoryContext old_context;
3797 
3798  /* Count NaN inputs separately from all else */
3799  if (NUMERIC_IS_NAN(newval))
3800  {
3801  state->NaNcount++;
3802  return;
3803  }
3804 
3805  /* load processed number in short-lived context */
3806  init_var_from_num(newval, &X);
3807 
3808  /*
3809  * Track the highest input dscale that we've seen, to support inverse
3810  * transitions (see do_numeric_discard).
3811  */
3812  if (X.dscale > state->maxScale)
3813  {
3814  state->maxScale = X.dscale;
3815  state->maxScaleCount = 1;
3816  }
3817  else if (X.dscale == state->maxScale)
3818  state->maxScaleCount++;
3819 
3820  /* if we need X^2, calculate that in short-lived context */
3821  if (state->calcSumX2)
3822  {
3823  init_var(&X2);
3824  mul_var(&X, &X, &X2, X.dscale * 2);
3825  }
3826 
3827  /* The rest of this needs to work in the aggregate context */
3828  old_context = MemoryContextSwitchTo(state->agg_context);
3829 
3830  state->N++;
3831 
3832  /* Accumulate sums */
3833  accum_sum_add(&(state->sumX), &X);
3834 
3835  if (state->calcSumX2)
3836  accum_sum_add(&(state->sumX2), &X2);
3837 
3838  MemoryContextSwitchTo(old_context);
3839 }
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
MemoryContext agg_context
Definition: numeric.c:3738
int dscale
Definition: numeric.c:278
static void accum_sum_add(NumericSumAccum *accum, const NumericVar *var1)
Definition: numeric.c:10034
static void init_var_from_num(Numeric num, NumericVar *dest)
Definition: numeric.c:6183
static void mul_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result, int rscale)
Definition: numeric.c:7322
NumericSumAccum sumX2
Definition: numeric.c:3741
int64 NaNcount
Definition: numeric.c:3744
int64 maxScaleCount
Definition: numeric.c:3743
#define NUMERIC_IS_NAN(n)
Definition: numeric.c:174
NumericSumAccum sumX
Definition: numeric.c:3740
#define init_var(v)
Definition: numeric.c:445

◆ do_numeric_discard()

static bool do_numeric_discard ( NumericAggState state,
Numeric  newval 
)
static

Definition at line 3857 of file numeric.c.

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

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

3858 {
3859  NumericVar X;
3860  NumericVar X2;
3861  MemoryContext old_context;
3862 
3863  /* Count NaN inputs separately from all else */
3864  if (NUMERIC_IS_NAN(newval))
3865  {
3866  state->NaNcount--;
3867  return true;
3868  }
3869 
3870  /* load processed number in short-lived context */
3871  init_var_from_num(newval, &X);
3872 
3873  /*
3874  * state->sumX's dscale is the maximum dscale of any of the inputs.
3875  * Removing the last input with that dscale would require us to recompute
3876  * the maximum dscale of the *remaining* inputs, which we cannot do unless
3877  * no more non-NaN inputs remain at all. So we report a failure instead,
3878  * and force the aggregation to be redone from scratch.
3879  */
3880  if (X.dscale == state->maxScale)
3881  {
3882  if (state->maxScaleCount > 1 || state->maxScale == 0)
3883  {
3884  /*
3885  * Some remaining inputs have same dscale, or dscale hasn't gotten
3886  * above zero anyway
3887  */
3888  state->maxScaleCount--;
3889  }
3890  else if (state->N == 1)
3891  {
3892  /* No remaining non-NaN inputs at all, so reset maxScale */
3893  state->maxScale = 0;
3894  state->maxScaleCount = 0;
3895  }
3896  else
3897  {
3898  /* Correct new maxScale is uncertain, must fail */
3899  return false;
3900  }
3901  }
3902 
3903  /* if we need X^2, calculate that in short-lived context */
3904  if (state->calcSumX2)
3905  {
3906  init_var(&X2);
3907  mul_var(&X, &X, &X2, X.dscale * 2);
3908  }
3909 
3910  /* The rest of this needs to work in the aggregate context */
3911  old_context = MemoryContextSwitchTo(state->agg_context);
3912 
3913  if (state->N-- > 1)
3914  {
3915  /* Negate X, to subtract it from the sum */
3916  X.sign = (X.sign == NUMERIC_POS ? NUMERIC_NEG : NUMERIC_POS);
3917  accum_sum_add(&(state->sumX), &X);
3918 
3919  if (state->calcSumX2)
3920  {
3921  /* Negate X^2. X^2 is always positive */
3922  X2.sign = NUMERIC_NEG;
3923  accum_sum_add(&(state->sumX2), &X2);
3924  }
3925  }
3926  else
3927  {
3928  /* Zero the sums */
3929  Assert(state->N == 0);
3930 
3931  accum_sum_reset(&state->sumX);
3932  if (state->calcSumX2)
3933  accum_sum_reset(&state->sumX2);
3934  }
3935 
3936  MemoryContextSwitchTo(old_context);
3937 
3938  return true;
3939 }
#define NUMERIC_POS
Definition: numeric.c:168
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
MemoryContext agg_context
Definition: numeric.c:3738
int dscale
Definition: numeric.c:278
#define NUMERIC_NEG
Definition: numeric.c:169
static void accum_sum_add(NumericSumAccum *accum, const NumericVar *var1)
Definition: numeric.c:10034
int sign
Definition: numeric.c:277
static void init_var_from_num(Numeric num, NumericVar *dest)
Definition: numeric.c:6183
#define Assert(condition)
Definition: c.h:738
static void mul_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result, int rscale)
Definition: numeric.c:7322
NumericSumAccum sumX2
Definition: numeric.c:3741
static void accum_sum_reset(NumericSumAccum *accum)
Definition: numeric.c:10018
int64 NaNcount
Definition: numeric.c:3744
int64 maxScaleCount
Definition: numeric.c:3743
#define NUMERIC_IS_NAN(n)
Definition: numeric.c:174
NumericSumAccum sumX
Definition: numeric.c:3740
#define init_var(v)
Definition: numeric.c:445

◆ estimate_ln_dweight()

static int estimate_ln_dweight ( const NumericVar var)
static

Definition at line 9001 of file numeric.c.

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

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

9002 {
9003  int ln_dweight;
9004 
9005  if (cmp_var(var, &const_zero_point_nine) >= 0 &&
9006  cmp_var(var, &const_one_point_one) <= 0)
9007  {
9008  /*
9009  * 0.9 <= var <= 1.1
9010  *
9011  * ln(var) has a negative weight (possibly very large). To get a
9012  * reasonably accurate result, estimate it using ln(1+x) ~= x.
9013  */
9014  NumericVar x;
9015 
9016  init_var(&x);
9017  sub_var(var, &const_one, &x);
9018 
9019  if (x.ndigits > 0)
9020  {
9021  /* Use weight of most significant decimal digit of x */
9022  ln_dweight = x.weight * DEC_DIGITS + (int) log10(x.digits[0]);
9023  }
9024  else
9025  {
9026  /* x = 0. Since ln(1) = 0 exactly, we don't need extra digits */
9027  ln_dweight = 0;
9028  }
9029 
9030  free_var(&x);
9031  }
9032  else
9033  {
9034  /*
9035  * Estimate the logarithm using the first couple of digits from the
9036  * input number. This will give an accurate result whenever the input
9037  * is not too close to 1.
9038  */
9039  if (var->ndigits > 0)
9040  {
9041  int digits;
9042  int dweight;
9043  double ln_var;
9044 
9045  digits = var->digits[0];
9046  dweight = var->weight * DEC_DIGITS;
9047 
9048  if (var->ndigits > 1)
9049  {
9050  digits = digits * NBASE + var->digits[1];
9051  dweight -= DEC_DIGITS;
9052  }
9053 
9054  /*----------
9055  * We have var ~= digits * 10^dweight
9056  * so ln(var) ~= ln(digits) + dweight * ln(10)
9057  *----------
9058  */
9059  ln_var = log((double) digits) + dweight * 2.302585092994046;
9060  ln_dweight = (int) log10(Abs(ln_var));
9061  }
9062  else
9063  {
9064  /* Caller should fail on ln(0), but for the moment return zero */
9065  ln_dweight = 0;
9066  }
9067  }
9068 
9069  return ln_dweight;
9070 }
int weight
Definition: numeric.c:276
static const NumericVar const_zero_point_nine
Definition: numeric.c:403
static const NumericVar const_one
Definition: numeric.c:379
static void ln_var(const NumericVar *arg, NumericVar *result, int rscale)
Definition: numeric.c:9079
int ndigits
Definition: numeric.c:275
#define Abs(x)
Definition: c.h:926
#define NBASE
Definition: numeric.c:97
static int cmp_var(const NumericVar *var1, const NumericVar *var2)
Definition: numeric.c:7026
static void free_var(NumericVar *var)
Definition: numeric.c:5950
NumericDigit * digits
Definition: numeric.c:280
static void sub_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition: numeric.c:7201
#define DEC_DIGITS
Definition: numeric.c:99
static const NumericVar const_one_point_one
Definition: numeric.c:413
#define init_var(v)
Definition: numeric.c:445
int digits
Definition: informix.c:666

◆ exp_var()

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

Definition at line 8875 of file numeric.c.

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

Referenced by numeric_exp(), and power_var().

8876 {
8877  NumericVar x;
8878  NumericVar elem;
8879  NumericVar ni;
8880  double val;
8881  int dweight;
8882  int ndiv2;
8883  int sig_digits;
8884  int local_rscale;
8885 
8886  init_var(&x);
8887  init_var(&elem);
8888  init_var(&ni);
8889 
8890  set_var_from_var(arg, &x);
8891 
8892  /*
8893  * Estimate the dweight of the result using floating point arithmetic, so
8894  * that we can choose an appropriate local rscale for the calculation.
8895  */
8897 
8898  /* Guard against overflow */
8899  /* If you change this limit, see also power_var()'s limit */
8900  if (Abs(val) >= NUMERIC_MAX_RESULT_SCALE * 3)
8901  ereport(ERROR,
8902  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
8903  errmsg("value overflows numeric format")));
8904 
8905  /* decimal weight = log10(e^x) = x * log10(e) */
8906  dweight = (int) (val * 0.434294481903252);
8907 
8908  /*
8909  * Reduce x to the range -0.01 <= x <= 0.01 (approximately) by dividing by
8910  * 2^n, to improve the convergence rate of the Taylor series.
8911  */
8912  if (Abs(val) > 0.01)
8913  {
8914  NumericVar tmp;
8915 
8916  init_var(&tmp);
8917  set_var_from_var(&const_two, &tmp);
8918 
8919  ndiv2 = 1;
8920  val /= 2;
8921 
8922  while (Abs(val) > 0.01)
8923  {
8924  ndiv2++;
8925  val /= 2;
8926  add_var(&tmp, &tmp, &tmp);
8927  }
8928 
8929  local_rscale = x.dscale + ndiv2;
8930  div_var_fast(&x, &tmp, &x, local_rscale, true);
8931 
8932  free_var(&tmp);
8933  }
8934  else
8935  ndiv2 = 0;
8936 
8937  /*
8938  * Set the scale for the Taylor series expansion. The final result has
8939  * (dweight + rscale + 1) significant digits. In addition, we have to
8940  * raise the Taylor series result to the power 2^ndiv2, which introduces
8941  * an error of up to around log10(2^ndiv2) digits, so work with this many
8942  * extra digits of precision (plus a few more for good measure).
8943  */
8944  sig_digits = 1 + dweight + rscale + (int) (ndiv2 * 0.301029995663981);
8945  sig_digits = Max(sig_digits, 0) + 8;
8946 
8947  local_rscale = sig_digits - 1;
8948 
8949  /*
8950  * Use the Taylor series
8951  *
8952  * exp(x) = 1 + x + x^2/2! + x^3/3! + ...
8953  *
8954  * Given the limited range of x, this should converge reasonably quickly.
8955  * We run the series until the terms fall below the local_rscale limit.
8956  */
8957  add_var(&const_one, &x, result);
8958 
8959  mul_var(&x, &x, &elem, local_rscale);
8960  set_var_from_var(&const_two, &ni);
8961  div_var_fast(&elem, &ni, &elem, local_rscale, true);
8962 
8963  while (elem.ndigits != 0)
8964  {
8965  add_var(result, &elem, result);
8966 
8967  mul_var(&elem, &x, &elem, local_rscale);
8968  add_var(&ni, &const_one, &ni);
8969  div_var_fast(&elem, &ni, &elem, local_rscale, true);
8970  }
8971 
8972  /*
8973  * Compensate for the argument range reduction. Since the weight of the
8974  * result doubles with each multiplication, we can reduce the local rscale
8975  * as we proceed.
8976  */
8977  while (ndiv2-- > 0)
8978  {
8979  local_rscale = sig_digits - result->weight * 2 * DEC_DIGITS;
8980  local_rscale = Max(local_rscale, NUMERIC_MIN_DISPLAY_SCALE);
8981  mul_var(result, result, result, local_rscale);
8982  }
8983 
8984  /* Round to requested rscale */
8985  round_var(result, rscale);
8986 
8987  free_var(&x);
8988  free_var(&elem);
8989  free_var(&ni);
8990 }
static void round_var(NumericVar *var, int rscale)
Definition: numeric.c:9809
int weight
Definition: numeric.c:276
static const NumericVar const_one
Definition: numeric.c:379
int errcode(int sqlerrcode)
Definition: elog.c:610
int ndigits
Definition: numeric.c:275
int dscale
Definition: numeric.c:278
#define Abs(x)
Definition: c.h:926
#define ERROR
Definition: elog.h:43
static double numericvar_to_double_no_overflow(const NumericVar *var)
Definition: numeric.c:6994
#define NUMERIC_MIN_DISPLAY_SCALE
Definition: numeric.h:30
#define NUMERIC_MAX_RESULT_SCALE
Definition: numeric.h:32
static void div_var_fast(const NumericVar *var1, const NumericVar *var2, NumericVar *result, int rscale, bool round)
Definition: numeric.c:7804
static void free_var(NumericVar *var)
Definition: numeric.c:5950
#define ereport(elevel,...)
Definition: elog.h:144
static const NumericVar const_two
Definition: numeric.c:383
static void mul_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result, int rscale)
Definition: numeric.c:7322
static void add_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition: numeric.c:7084
int errmsg(const char *fmt,...)
Definition: elog.c:824
#define Max(x, y)
Definition: numeric.c:13
#define DEC_DIGITS
Definition: numeric.c:99
static void set_var_from_var(const NumericVar *value, NumericVar *dest)
Definition: numeric.c:6200
long val
Definition: informix.c:664
#define init_var(v)
Definition: numeric.c:445

◆ float4_numeric()

Datum float4_numeric ( PG_FUNCTION_ARGS  )

Definition at line 3646 of file numeric.c.

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

3647 {
3649  Numeric res;
3650  NumericVar result;
3651  char buf[FLT_DIG + 100];
3652 
3653  if (isnan(val))
3655 
3656  if (isinf(val))
3657  ereport(ERROR,
3658  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3659  errmsg("cannot convert infinity to numeric")));
3660 
3661  snprintf(buf, sizeof(buf), "%.*g", FLT_DIG, val);
3662 
3663  init_var(&result);
3664 
3665  /* Assume we need not worry about leading/trailing spaces */
3666  (void) set_var_from_str(buf, buf, &result);
3667 
3668  res = make_result(&result);
3669 
3670  free_var(&result);
3671 
3672  PG_RETURN_NUMERIC(res);
3673 }
#define PG_RETURN_NUMERIC(x)
Definition: numeric.h:54
int errcode(int sqlerrcode)
Definition: elog.c:610
#define ERROR
Definition: elog.h:43
static char * buf
Definition: pg_test_fsync.c:67
#define PG_GETARG_FLOAT4(n)
Definition: fmgr.h:280
float float4
Definition: c.h:490
static void free_var(NumericVar *var)
Definition: numeric.c:5950
#define ereport(elevel,...)
Definition: elog.h:144
static const char * set_var_from_str(const char *str, const char *cp, NumericVar *dest)
Definition: numeric.c:5990
static const NumericVar const_nan
Definition: numeric.c:416
static Numeric make_result(const NumericVar *var)
Definition: numeric.c:6566
int errmsg(const char *fmt,...)
Definition: elog.c:824
#define snprintf
Definition: port.h:193
long val
Definition: informix.c:664
#define init_var(v)
Definition: numeric.c:445

◆ float8_numeric()

Datum float8_numeric ( PG_FUNCTION_ARGS  )

Definition at line 3575 of file numeric.c.

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

Referenced by executeItemOptUnwrapTarget(), and SV_to_JsonbValue().

3576 {
3578  Numeric res;
3579  NumericVar result;
3580  char buf[DBL_DIG + 100];
3581 
3582  if (isnan(val))
3584 
3585  if (isinf(val))
3586  ereport(ERROR,
3587  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3588  errmsg("cannot convert infinity to numeric")));
3589 
3590  snprintf(buf, sizeof(buf), "%.*g", DBL_DIG, val);
3591 
3592  init_var(&result);
3593 
3594  /* Assume we need not worry about leading/trailing spaces */
3595  (void) set_var_from_str(buf, buf, &result);
3596 
3597  res = make_result(&result);
3598 
3599  free_var(&result);
3600 
3601  PG_RETURN_NUMERIC(res);
3602 }
#define PG_RETURN_NUMERIC(x)
Definition: numeric.h:54
#define PG_GETARG_FLOAT8(n)
Definition: fmgr.h:281
int errcode(int sqlerrcode)
Definition: elog.c:610
#define ERROR
Definition: elog.h:43
double float8
Definition: c.h:491
static char * buf
Definition: pg_test_fsync.c:67
static void free_var(NumericVar *var)
Definition: numeric.c:5950
#define ereport(elevel,...)
Definition: elog.h:144
static const char * set_var_from_str(const char *str, const char *cp, NumericVar *dest)
Definition: numeric.c:5990
static const NumericVar const_nan
Definition: numeric.c:416
static Numeric make_result(const NumericVar *var)
Definition: numeric.c:6566
int errmsg(const char *fmt,...)
Definition: elog.c:824
#define snprintf
Definition: port.h:193
long val
Definition: informix.c:664
#define init_var(v)
Definition: numeric.c:445

◆ floor_var()

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

Definition at line 8302 of file numeric.c.

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

Referenced by compute_bucket(), and numeric_floor().

8303 {
8304  NumericVar tmp;
8305 
8306  init_var(&tmp);
8307  set_var_from_var(var, &tmp);
8308 
8309  trunc_var(&tmp, 0);
8310 
8311  if (var->sign == NUMERIC_NEG && cmp_var(var, &tmp) != 0)
8312  sub_var(&tmp, &const_one, &tmp);
8313 
8314  set_var_from_var(&tmp, result);
8315  free_var(&tmp);
8316 }
static void trunc_var(NumericVar *var, int rscale)
Definition: numeric.c:9915
static const NumericVar const_one
Definition: numeric.c:379
#define NUMERIC_NEG
Definition: numeric.c:169
int sign
Definition: numeric.c:277
static int cmp_var(const NumericVar *var1, const NumericVar *var2)
Definition: numeric.c:7026
static void free_var(NumericVar *var)
Definition: numeric.c:5950
static void sub_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition: numeric.c:7201
static void set_var_from_var(const NumericVar *value, NumericVar *dest)
Definition: numeric.c:6200
#define init_var(v)
Definition: numeric.c:445

◆ free_var()

static void free_var ( NumericVar var)
static

Definition at line 5950 of file numeric.c.

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(), int2_numeric(), int4_numeric(), int8_avg_serialize(), int8_numeric(), ln_var(), log_var(), mod_var(), numeric(), numeric_add_opt_error(), numeric_avg(), numeric_avg_serialize(), numeric_ceil(), 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_serialize(), numeric_poly_sum(), numeric_power(), numeric_recv(), numeric_round(), numeric_serialize(), numeric_sign(), numeric_sqrt(), numeric_stddev_internal(), numeric_stddev_pop(), numeric_sub_opt_error(), numeric_sum(), numeric_trim_scale(), numeric_trunc(), numericvar_to_int64(), numericvar_to_uint64(), power_var(), power_var_int(), sqrt_var(), and width_bucket_numeric().

5951 {
5952  digitbuf_free(var->buf);
5953  var->buf = NULL;
5954  var->digits = NULL;
5955  var->sign = NUMERIC_NAN;
5956 }
int sign
Definition: numeric.c:277
#define digitbuf_free(buf)
Definition: numeric.c:439
#define NUMERIC_NAN
Definition: numeric.c:171
NumericDigit * buf
Definition: numeric.c:279
NumericDigit * digits
Definition: numeric.c:280

◆ gcd_var()

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

Definition at line 8325 of file numeric.c.

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

8326 {
8327  int res_dscale;
8328  int cmp;
8329  NumericVar tmp_arg;
8330  NumericVar mod;
8331 
8332  res_dscale = Max(var1->dscale, var2->dscale);
8333 
8334  /*
8335  * Arrange for var1 to be the number with the greater absolute value.
8336  *
8337  * This would happen automatically in the loop below, but avoids an
8338  * expensive modulo operation.
8339  */
8340  cmp = cmp_abs(var1, var2);
8341  if (cmp < 0)
8342  {
8343  const NumericVar *tmp = var1;
8344 
8345  var1 = var2;
8346  var2 = tmp;
8347  }
8348 
8349  /*
8350  * Also avoid the taking the modulo if the inputs have the same absolute
8351  * value, or if the smaller input is zero.
8352  */
8353  if (cmp == 0 || var2->ndigits == 0)
8354  {
8355  set_var_from_var(var1, result);
8356  result->sign = NUMERIC_POS;
8357  result->dscale = res_dscale;
8358  return;
8359  }
8360 
8361  init_var(&tmp_arg);
8362  init_var(&mod);
8363 
8364  /* Use the Euclidean algorithm to find the GCD */
8365  set_var_from_var(var1, &tmp_arg);
8366  set_var_from_var(var2, result);
8367 
8368  for (;;)
8369  {
8370  /* this loop can take a while, so allow it to be interrupted */
8372 
8373  mod_var(&tmp_arg, result, &mod);
8374  if (mod.ndigits == 0)
8375  break;
8376  set_var_from_var(result, &tmp_arg);
8377  set_var_from_var(&mod, result);
8378  }
8379  result->sign = NUMERIC_POS;
8380  result->dscale = res_dscale;
8381 
8382  free_var(&tmp_arg);
8383  free_var(&mod);
8384 }
#define NUMERIC_POS
Definition: numeric.c:168
int ndigits
Definition: numeric.c:275
int dscale
Definition: numeric.c:278
int sign
Definition: numeric.c:277
static void mod_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition: numeric.c:8179
static void free_var(NumericVar *var)
Definition: numeric.c:5950
static int cmp_abs(const NumericVar *var1, const NumericVar *var2)
Definition: numeric.c:9564
#define Max(x, y)
Definition: numeric.c:13
static void set_var_from_var(const NumericVar *value, NumericVar *dest)
Definition: numeric.c:6200
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:99
#define init_var(v)
Definition: numeric.c:445
static int cmp(const chr *x, const chr *y, size_t len)
Definition: regc_locale.c:742

◆ generate_series_numeric()

Datum generate_series_numeric ( PG_FUNCTION_ARGS  )

Definition at line 1375 of file numeric.c.

References generate_series_step_numeric().

1376 {
1377  return generate_series_step_numeric(fcinfo);
1378 }
Datum generate_series_step_numeric(PG_FUNCTION_ARGS)
Definition: numeric.c:1381

◆ generate_series_step_numeric()

Datum generate_series_step_numeric ( PG_FUNCTION_ARGS  )

Definition at line 1381 of file numeric.c.

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

Referenced by generate_series_numeric().

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

◆ get_min_scale()

static int get_min_scale ( NumericVar var)
static

Definition at line 3287 of file numeric.c.

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

Referenced by numeric_min_scale(), and numeric_trim_scale().

3288 {
3289  int min_scale;
3290  int last_digit_pos;
3291 
3292  /*
3293  * Ordinarily, the input value will be "stripped" so that the last
3294  * NumericDigit is nonzero. But we don't want to get into an infinite
3295  * loop if it isn't, so explicitly find the last nonzero digit.
3296  */
3297  last_digit_pos = var->ndigits - 1;
3298  while (last_digit_pos >= 0 &&
3299  var->digits[last_digit_pos] == 0)
3300  last_digit_pos--;
3301 
3302  if (last_digit_pos >= 0)
3303  {
3304  /* compute min_scale assuming that last ndigit has no zeroes */
3305  min_scale = (last_digit_pos - var->weight) * DEC_DIGITS;
3306 
3307  /*
3308  * We could get a negative result if there are no digits after the
3309  * decimal point. In this case the min_scale must be zero.
3310  */
3311  if (min_scale > 0)
3312  {
3313  /*
3314  * Reduce min_scale if trailing digit(s) in last NumericDigit are
3315  * zero.
3316  */
3317  NumericDigit last_digit = var->digits[last_digit_pos];
3318 
3319  while (last_digit % 10 == 0)
3320  {
3321  min_scale--;
3322  last_digit /= 10;
3323  }
3324  }
3325  else
3326  min_scale = 0;
3327  }
3328  else
3329  min_scale = 0; /* result if input is zero */
3330 
3331  return min_scale;
3332 }
int weight
Definition: numeric.c:276
int ndigits
Definition: numeric.c:275
int16 NumericDigit
Definition: numeric.c:103
NumericDigit * digits
Definition: numeric.c:280
#define DEC_DIGITS
Definition: numeric.c:99

◆ get_str_from_var()

static char * get_str_from_var ( const NumericVar var)
static

Definition at line 6226 of file numeric.c.

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

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

6227 {
6228  int dscale;
6229  char *str;
6230  char *cp;
6231  char *endcp;
6232  int i;
6233  int d;
6234  NumericDigit dig;
6235 
6236 #if DEC_DIGITS > 1
6237  NumericDigit d1;
6238 #endif
6239 
6240  dscale = var->dscale;
6241 
6242  /*
6243  * Allocate space for the result.
6244  *
6245  * i is set to the # of decimal digits before decimal point. dscale is the
6246  * # of decimal digits we will print after decimal point. We may generate
6247  * as many as DEC_DIGITS-1 excess digits at the end, and in addition we
6248  * need room for sign, decimal point, null terminator.
6249  */
6250  i = (var->weight + 1) * DEC_DIGITS;
6251  if (i <= 0)
6252  i = 1;
6253 
6254  str = palloc(i + dscale + DEC_DIGITS + 2);
6255  cp = str;
6256 
6257  /*
6258  * Output a dash for negative values
6259  */
6260  if (var->sign == NUMERIC_NEG)
6261  *cp++ = '-';
6262 
6263  /*
6264  * Output all digits before the decimal point
6265  */
6266  if (var->weight < 0)
6267  {
6268  d = var->weight + 1;
6269  *cp++ = '0';
6270  }
6271  else
6272  {
6273  for (d = 0; d <= var->weight; d++)
6274  {
6275  dig = (d < var->ndigits) ? var->digits[d] : 0;
6276  /* In the first digit, suppress extra leading decimal zeroes */
6277 #if DEC_DIGITS == 4
6278  {
6279  bool putit = (d > 0);
6280 
6281  d1 = dig / 1000;
6282  dig -= d1 * 1000;
6283  putit |= (d1 > 0);
6284  if (putit)
6285  *cp++ = d1 + '0';
6286  d1 = dig / 100;
6287  dig -= d1 * 100;
6288  putit |= (d1 > 0);
6289  if (putit)
6290  *cp++ = d1 + '0';
6291  d1 = dig / 10;
6292  dig -= d1 * 10;
6293  putit |= (d1 > 0);
6294  if (putit)
6295  *cp++ = d1 + '0';
6296  *cp++ = dig + '0';
6297  }
6298 #elif DEC_DIGITS == 2
6299  d1 = dig / 10;
6300  dig -= d1 * 10;
6301  if (d1 > 0 || d > 0)
6302  *cp++ = d1 + '0';
6303  *cp++ = dig + '0';
6304 #elif DEC_DIGITS == 1
6305  *cp++ = dig + '0';
6306 #else
6307 #error unsupported NBASE
6308 #endif
6309  }
6310  }
6311 
6312  /*
6313  * If requested, output a decimal point and all the digits that follow it.
6314  * We initially put out a multiple of DEC_DIGITS digits, then truncate if
6315  * needed.
6316  */
6317  if (dscale > 0)
6318  {
6319  *cp++ = '.';
6320  endcp = cp + dscale;
6321  for (i = 0; i < dscale; d++, i += DEC_DIGITS)
6322  {
6323  dig = (d >= 0 && d < var->ndigits) ? var->digits[d] : 0;
6324 #if DEC_DIGITS == 4
6325  d1 = dig / 1000;
6326  dig -= d1 * 1000;
6327  *cp++ = d1 + '0';
6328  d1 = dig / 100;
6329  dig -= d1 * 100;
6330  *cp++ = d1 + '0';
6331  d1 = dig / 10;
6332  dig -= d1 * 10;
6333  *cp++ = d1 + '0';
6334  *cp++ = dig + '0';
6335 #elif DEC_DIGITS == 2
6336  d1 = dig / 10;
6337  dig -= d1 * 10;
6338  *cp++ = d1 + '0';
6339  *cp++ = dig + '0';
6340 #elif DEC_DIGITS == 1
6341  *cp++ = dig + '0';
6342 #else
6343 #error unsupported NBASE
6344 #endif
6345  }
6346  cp = endcp;
6347  }
6348 
6349  /*
6350  * terminate the string and return it
6351  */
6352  *cp = '\0';
6353  return str;
6354 }
int weight
Definition: numeric.c:276
static void error(void)
Definition: sql-dyntest.c:147
int ndigits
Definition: numeric.c:275
int dscale
Definition: numeric.c:278
#define NUMERIC_NEG
Definition: numeric.c:169
int sign
Definition: numeric.c:277
int16 NumericDigit
Definition: numeric.c:103
#define NBASE
Definition: numeric.c:97
NumericDigit * digits
Definition: numeric.c:280
void * palloc(Size size)
Definition: mcxt.c:949
int i
#define DEC_DIGITS
Definition: numeric.c:99

◆ get_str_from_var_sci()

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

Definition at line 6379 of file numeric.c.

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

Referenced by numeric_out_sci().

6380 {
6381  int32 exponent;
6382  NumericVar denominator;
6383  NumericVar significand;
6384  int denom_scale;
6385  size_t len;
6386  char *str;
6387  char *sig_out;
6388 
6389  if (rscale < 0)
6390  rscale = 0;
6391 
6392  /*
6393  * Determine the exponent of this number in normalised form.
6394  *
6395  * This is the exponent required to represent the number with only one
6396  * significant digit before the decimal place.
6397  */
6398  if (var->ndigits > 0)
6399  {
6400  exponent = (var->weight + 1) * DEC_DIGITS;
6401 
6402  /*
6403  * Compensate for leading decimal zeroes in the first numeric digit by
6404  * decrementing the exponent.
6405  */
6406  exponent -= DEC_DIGITS - (int) log10(var->digits[0]);
6407  }
6408  else
6409  {
6410  /*
6411  * If var has no digits, then it must be zero.
6412  *
6413  * Zero doesn't technically have a meaningful exponent in normalised
6414  * notation, but we just display the exponent as zero for consistency
6415  * of output.
6416  */
6417  exponent = 0;
6418  }
6419 
6420  /*
6421  * The denominator is set to 10 raised to the power of the exponent.
6422  *
6423  * We then divide var by the denominator to get the significand, rounding
6424  * to rscale decimal digits in the process.
6425  */
6426  if (exponent < 0)
6427  denom_scale = -exponent;
6428  else
6429  denom_scale = 0;
6430 
6431  init_var(&denominator);
6432  init_var(&significand);
6433 
6434  power_var_int(&const_ten, exponent, &denominator, denom_scale);
6435  div_var(var, &denominator, &significand, rscale, true);
6436  sig_out = get_str_from_var(&significand);
6437 
6438  free_var(&denominator);
6439  free_var(&significand);
6440 
6441  /*
6442  * Allocate space for the result.
6443  *
6444  * In addition to the significand, we need room for the exponent
6445  * decoration ("e"), the sign of the exponent, up to 10 digits for the
6446  * exponent itself, and of course the null terminator.
6447  */
6448  len = strlen(sig_out) + 13;
6449  str = palloc(len);
6450  snprintf(str, len, "%se%+03d", sig_out, exponent);
6451 
6452  pfree(sig_out);
6453 
6454  return str;
6455 }
int weight
Definition: numeric.c:276
int ndigits
Definition: numeric.c:275
static void div_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result, int rscale, bool round)
Definition: numeric.c:7519
signed int int32
Definition: c.h:355
void pfree(void *pointer)
Definition: mcxt.c:1056
static void power_var_int(const NumericVar *base, int exp, NumericVar *result, int rscale)
Definition: numeric.c:9374
static const NumericVar const_ten
Definition: numeric.c:388
static void free_var(NumericVar *var)
Definition: numeric.c:5950
NumericDigit * digits
Definition: numeric.c:280
void * palloc(Size size)
Definition: mcxt.c:949
static char * get_str_from_var(const NumericVar *var)
Definition: numeric.c:6226
#define DEC_DIGITS
Definition: numeric.c:99
#define snprintf
Definition: port.h:193
#define init_var(v)
Definition: numeric.c:445

◆ hash_numeric()

Datum hash_numeric ( PG_FUNCTION_ARGS  )

Definition at line 2255 of file numeric.c.

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

Referenced by JsonbHashScalarValue().

2256 {
2258  Datum digit_hash;
2259  Datum result;
2260  int weight;
2261  int start_offset;
2262  int end_offset;
2263  int i;
2264  int hash_len;
2266 
2267  /* If it's NaN, don't try to hash the rest of the fields */
2268  if (NUMERIC_IS_NAN(key))
2269  PG_RETURN_UINT32(0);
2270 
2271  weight = NUMERIC_WEIGHT(key);
2272  start_offset = 0;
2273  end_offset = 0;
2274 
2275  /*
2276  * Omit any leading or trailing zeros from the input to the hash. The
2277  * numeric implementation *should* guarantee that leading and trailing
2278  * zeros are suppressed, but we're paranoid. Note that we measure the
2279  * starting and ending offsets in units of NumericDigits, not bytes.
2280  */
2281  digits = NUMERIC_DIGITS(key);
2282  for (i = 0; i < NUMERIC_NDIGITS(key); i++)
2283  {
2284  if (digits[i] != (NumericDigit) 0)
2285  break;
2286 
2287  start_offset++;
2288 
2289  /*
2290  * The weight is effectively the # of digits before the decimal point,
2291  * so decrement it for each leading zero we skip.
2292  */
2293  weight--;
2294  }
2295 
2296  /*
2297  * If there are no non-zero digits, then the value of the number is zero,
2298  * regardless of any other fields.
2299  */
2300  if (NUMERIC_NDIGITS(key) == start_offset)
2301  PG_RETURN_UINT32(-1);
2302 
2303  for (i = NUMERIC_NDIGITS(key) - 1; i >= 0; i--)
2304  {
2305  if (digits[i] != (NumericDigit) 0)
2306  break;
2307 
2308  end_offset++;
2309  }
2310 
2311  /* If we get here, there should be at least one non-zero digit */
2312  Assert(start_offset + end_offset < NUMERIC_NDIGITS(key));
2313 
2314  /*
2315  * Note that we don't hash on the Numeric's scale, since two numerics can
2316  * compare equal but have different scales. We also don't hash on the
2317  * sign, although we could: since a sign difference implies inequality,
2318  * this shouldn't affect correctness.
2319  */
2320  hash_len = NUMERIC_NDIGITS(key) - start_offset - end_offset;
2321  digit_hash = hash_any((unsigned char *) (NUMERIC_DIGITS(key) + start_offset),
2322  hash_len * sizeof(NumericDigit));
2323 
2324  /* Mix in the weight, via XOR */
2325  result = digit_hash ^ weight;
2326 
2327  PG_RETURN_DATUM(result);
2328 }
#define PG_RETURN_UINT32(x)
Definition: fmgr.h:354
#define NUMERIC_DIGITS(num)
Definition: numeric.c:447
int16 NumericDigit
Definition: numeric.c:103
static Datum hash_any(const unsigned char *k, int keylen)
Definition: hashfn.h:31
#define NUMERIC_NDIGITS(num)
Definition: numeric.c:449
uintptr_t Datum
Definition: postgres.h:367
#define PG_RETURN_DATUM(x)
Definition: fmgr.h:352
#define NUMERIC_WEIGHT(n)
Definition: numeric.c:218
#define PG_GETARG_NUMERIC(n)
Definition: numeric.h:52
#define Assert(condition)
Definition: c.h:738
int i
#define NUMERIC_IS_NAN(n)
Definition: numeric.c:174
int digits
Definition: informix.c:666

◆ hash_numeric_extended()

Datum hash_numeric_extended ( PG_FUNCTION_ARGS  )

Definition at line 2335 of file numeric.c.

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

Referenced by JsonbHashScalarValueExtended().

2336 {
2338  uint64 seed = PG_GETARG_INT64(1);
2339  Datum digit_hash;
2340  Datum result;
2341  int weight;
2342  int start_offset;
2343  int end_offset;
2344  int i;
2345  int hash_len;
2347 
2348  if (NUMERIC_IS_NAN(key))
2349  PG_RETURN_UINT64(seed);
2350 
2351  weight = NUMERIC_WEIGHT(key);
2352  start_offset = 0;
2353  end_offset = 0;
2354 
2355  digits = NUMERIC_DIGITS(key);
2356  for (i = 0; i < NUMERIC_NDIGITS(key); i++)
2357  {
2358  if (digits[i] != (NumericDigit) 0)
2359  break;
2360 
2361  start_offset++;
2362 
2363  weight--;
2364  }
2365 
2366  if (NUMERIC_NDIGITS(key) == start_offset)
2367  PG_RETURN_UINT64(seed - 1);
2368 
2369  for (i = NUMERIC_NDIGITS(key) - 1; i >= 0; i--)
2370  {
2371  if (digits[i] != (NumericDigit) 0)
2372  break;
2373 
2374  end_offset++;
2375  }
2376 
2377  Assert(start_offset + end_offset < NUMERIC_NDIGITS(key));
2378 
2379  hash_len = NUMERIC_NDIGITS(key) - start_offset - end_offset;
2380  digit_hash = hash_any_extended((unsigned char *) (NUMERIC_DIGITS(key)
2381  + start_offset),
2382  hash_len * sizeof(NumericDigit),
2383  seed);
2384 
2385  result = UInt64GetDatum(DatumGetUInt64(digit_hash) ^ weight);
2386 
2387  PG_RETURN_DATUM(result);
2388 }
#define UInt64GetDatum(X)
Definition: postgres.h:648
static Datum hash_any_extended(const unsigned char *k, int keylen, uint64 seed)
Definition: hashfn.h:37
#define PG_RETURN_UINT64(x)
Definition: fmgr.h:367
#define NUMERIC_DIGITS(num)
Definition: numeric.c:447
int16 NumericDigit
Definition: numeric.c:103
#define NUMERIC_NDIGITS(num)
Definition: numeric.c:449
uintptr_t Datum
Definition: postgres.h:367
#define PG_RETURN_DATUM(x)
Definition: fmgr.h:352
#define DatumGetUInt64(X)
Definition: postgres.h:634
#define NUMERIC_WEIGHT(n)
Definition: numeric.c:218
#define PG_GETARG_NUMERIC(n)
Definition: numeric.h:52
#define Assert(condition)
Definition: c.h:738
int i
#define NUMERIC_IS_NAN(n)
Definition: numeric.c:174
#define PG_GETARG_INT64(n)
Definition: fmgr.h:282
int digits
Definition: informix.c:666

◆ in_range_numeric_numeric()

Datum in_range_numeric_numeric ( PG_FUNCTION_ARGS  )

Definition at line 2183 of file numeric.c.

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

2184 {
2186  Numeric base = PG_GETARG_NUMERIC(1);
2187  Numeric offset = PG_GETARG_NUMERIC(2);
2188  bool sub = PG_GETARG_BOOL(3);
2189  bool less = PG_GETARG_BOOL(4);
2190  bool result;
2191 
2192  /*
2193  * Reject negative or NaN offset. Negative is per spec, and NaN is
2194  * because appropriate semantics for that seem non-obvious.
2195  */
2196  if (NUMERIC_IS_NAN(offset) || NUMERIC_SIGN(offset) == NUMERIC_NEG)
2197  ereport(ERROR,
2198  (errcode(ERRCODE_INVALID_PRECEDING_OR_FOLLOWING_SIZE),
2199  errmsg("invalid preceding or following size in window function")));
2200 
2201  /*
2202  * Deal with cases where val and/or base is NaN, following the rule that
2203  * NaN sorts after non-NaN (cf cmp_numerics). The offset cannot affect
2204  * the conclusion.
2205  */
2206  if (NUMERIC_IS_NAN(val))
2207  {
2208  if (NUMERIC_IS_NAN(base))
2209  result = true; /* NAN = NAN */
2210  else
2211  result = !less; /* NAN > non-NAN */
2212  }
2213  else if (NUMERIC_IS_NAN(base))
2214  {
2215  result = less; /* non-NAN < NAN */
2216  }
2217  else
2218  {
2219  /*
2220  * Otherwise go ahead and compute base +/- offset. While it's
2221  * possible for this to overflow the numeric format, it's unlikely
2222  * enough that we don't take measures to prevent it.
2223  */
2224  NumericVar valv;
2225  NumericVar basev;
2226  NumericVar offsetv;
2227  NumericVar sum;
2228 
2229  init_var_from_num(val, &valv);
2230  init_var_from_num(base, &basev);
2231  init_var_from_num(offset, &offsetv);
2232  init_var(&sum);
2233 
2234  if (sub)
2235  sub_var(&basev, &offsetv, &sum);
2236  else
2237  add_var(&basev, &offsetv, &sum);
2238 
2239  if (less)
2240  result = (cmp_var(&valv, &sum) <= 0);
2241  else
2242  result = (cmp_var(&valv, &sum) >= 0);
2243 
2244  free_var(&sum);
2245  }
2246 
2247  PG_FREE_IF_COPY(val, 0);
2248  PG_FREE_IF_COPY(base, 1);
2249  PG_FREE_IF_COPY(offset, 2);
2250 
2251  PG_RETURN_BOOL(result);
2252 }
int errcode(int sqlerrcode)
Definition: elog.c:610
#define PG_GETARG_BOOL(n)
Definition: fmgr.h:274
#define NUMERIC_NEG
Definition: numeric.c:169
#define ERROR
Definition: elog.h:43
static void init_var_from_num(Numeric num, NumericVar *dest)
Definition: numeric.c:6183
#define NUMERIC_SIGN(n)
Definition: numeric.c:210
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:358
static int cmp_var(const NumericVar *var1, const NumericVar *var2)
Definition: numeric.c:7026
static void free_var(NumericVar *var)
Definition: numeric.c:5950
#define ereport(elevel,...)
Definition: elog.h:144
#define PG_GETARG_NUMERIC(n)
Definition: numeric.h:52
static void add_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition: numeric.c:7084
#define PG_FREE_IF_COPY(ptr, n)
Definition: fmgr.h:260
int errmsg(const char *fmt,...)
Definition: elog.c:824
#define NUMERIC_IS_NAN(n)
Definition: numeric.c:174
static void sub_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition: numeric.c:7201
long val
Definition: informix.c:664
#define init_var(v)
Definition: numeric.c:445

◆ init_var_from_num()

static void init_var_from_num ( Numeric  num,
NumericVar dest 
)
static

Definition at line 6183 of file numeric.c.

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

Referenced by compute_bucket(), do_numeric_accum(), do_numeric_discard(), generate_series_step_numeric(), in_range_numeric_numeric(), int8_avg_deserialize(), numeric_abbrev_convert(), numeric_add_opt_error(), numeric_avg_deserialize(), numeric_ceil(), numeric_deserialize(), numeric_div_opt_error(), numeric_div_trunc(), numeric_exp(), numeric_floor(), numeric_gcd(), numeric_inc(), numeric_int2(), numeric_int4_opt_error(), numeric_int8(), numeric_lcm(), numeric_ln(), numeric_log(), numeric_min_scale(), numeric_mod_opt_error(), numeric_mul_opt_error(), numeric_normalize(), numeric_out(), numeric_out_sci(), numeric_pg_lsn(), numeric_poly_deserialize(), numeric_power(), numeric_send(), numeric_sqrt(), numeric_sub_opt_error(), and numeric_trim_scale().

6184 {
6185  dest->ndigits = NUMERIC_NDIGITS(num);
6186  dest->weight = NUMERIC_WEIGHT(num);
6187  dest->sign = NUMERIC_SIGN(num);
6188  dest->dscale = NUMERIC_DSCALE(num);
6189  dest->digits = NUMERIC_DIGITS(num);
6190  dest->buf = NULL; /* digits array is not palloc'd */
6191 }
#define NUMERIC_DSCALE(n)
Definition: numeric.c:214
int weight
Definition: numeric.c:276
int ndigits
Definition: numeric.c:275
int dscale
Definition: numeric.c:278
int sign
Definition: numeric.c:277
#define NUMERIC_DIGITS(num)
Definition: numeric.c:447
#define NUMERIC_SIGN(n)
Definition: numeric.c:210
NumericDigit * buf
Definition: numeric.c:279
#define NUMERIC_NDIGITS(num)
Definition: numeric.c:449
#define NUMERIC_WEIGHT(n)
Definition: numeric.c:218
NumericDigit * digits
Definition: numeric.c:280

◆ int2_accum()

Datum int2_accum ( PG_FUNCTION_ARGS  )

Definition at line 4482 of file numeric.c.

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

4483 {
4485 
4486  state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
4487 
4488  /* Create the state data on the first call */
4489  if (state == NULL)
4490  state = makePolyNumAggState(fcinfo, true);
4491 
4492  if (!PG_ARGISNULL(1))
4493  {
4494 #ifdef HAVE_INT128
4495  do_int128_accum(state, (int128) PG_GETARG_INT16(1));
4496 #else
4497  Numeric newval;
4498 
4500  PG_GETARG_DATUM(1)));
4501  do_numeric_accum(state, newval);
4502 #endif
4503  }
4504 
4505  PG_RETURN_POINTER(state);
4506 }
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:360
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:268
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:276
Datum int2_numeric(PG_FUNCTION_ARGS)
Definition: numeric.c:3521
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:624
static void do_numeric_accum(NumericAggState *state, Numeric newval)
Definition: numeric.c:3792
#define PG_GETARG_INT16(n)
Definition: fmgr.h:271
#define PG_ARGISNULL(n)
Definition: fmgr.h:209
#define DatumGetNumeric(X)
Definition: numeric.h:49
Definition: regguts.h:298
#define newval
#define makePolyNumAggState
Definition: numeric.c:4477

◆ int2_accum_inv()

Datum int2_accum_inv ( PG_FUNCTION_ARGS  )

Definition at line 4959 of file numeric.c.

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

4960 {
4962 
4963  state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
4964 
4965  /* Should not get here with no state */
4966  if (state == NULL)
4967  elog(ERROR, "int2_accum_inv called with NULL state");
4968 
4969  if (!PG_ARGISNULL(1))
4970  {
4971 #ifdef HAVE_INT128
4972  do_int128_discard(state, (int128) PG_GETARG_INT16(1));
4973 #else
4974  Numeric newval;
4975 
4977  PG_GETARG_DATUM(1)));
4978 
4979  /* Should never fail, all inputs have dscale 0 */
4980  if (!do_numeric_discard(state, newval))
4981  elog(ERROR, "do_numeric_discard failed unexpectedly");
4982 #endif
4983  }
4984 
4985  PG_RETURN_POINTER(state);
4986 }
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:360
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:268
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:276
Datum int2_numeric(PG_FUNCTION_ARGS)
Definition: numeric.c:3521
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:624
static bool do_numeric_discard(NumericAggState *state, Numeric newval)
Definition: numeric.c:3857
#define ERROR
Definition: elog.h:43
#define PG_GETARG_INT16(n)
Definition: fmgr.h:271
#define PG_ARGISNULL(n)
Definition: fmgr.h:209
#define DatumGetNumeric(X)
Definition: numeric.h:49
Definition: regguts.h:298
#define newval
#define elog(elevel,...)
Definition: elog.h:214

◆ int2_avg_accum()

Datum int2_avg_accum ( PG_FUNCTION_ARGS  )

Definition at line 5649 of file numeric.c.

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

5650 {
5651  ArrayType *transarray;
5653  Int8TransTypeData *transdata;
5654 
5655  /*
5656  * If we're invoked as an aggregate, we can cheat and modify our first
5657  * parameter in-place to reduce palloc overhead. Otherwise we need to make
5658  * a copy of it before scribbling on it.
5659  */
5660  if (AggCheckCallContext(fcinfo, NULL))
5661  transarray = PG_GETARG_ARRAYTYPE_P(0);
5662  else
5663  transarray = PG_GETARG_ARRAYTYPE_P_COPY(0);
5664 
5665  if (ARR_HASNULL(transarray) ||
5666  ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
5667  elog(ERROR, "expected 2-element int8 array");
5668 
5669  transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
5670  transdata->count++;
5671  transdata->sum += newval;
5672 
5673  PG_RETURN_ARRAYTYPE_P(transarray);
5674 }
signed short int16
Definition: c.h:354
#define ARR_OVERHEAD_NONULLS(ndims)
Definition: array.h:298
#define ARR_SIZE(a)
Definition: array.h:277
#define PG_GETARG_ARRAYTYPE_P_COPY(n)
Definition: array.h:252
#define PG_GETARG_ARRAYTYPE_P(n)
Definition: array.h:251
#define ERROR
Definition: elog.h:43
#define ARR_DATA_PTR(a)
Definition: array.h:310
#define ARR_HASNULL(a)
Definition: array.h:279
#define PG_RETURN_ARRAYTYPE_P(x)
Definition: array.h:253
#define PG_GETARG_INT16(n)
Definition: fmgr.h:271
#define newval
int AggCheckCallContext(FunctionCallInfo fcinfo, MemoryContext *aggcontext)
Definition: nodeAgg.c:4697
#define elog(elevel,...)
Definition: elog.h:214

◆ int2_avg_accum_inv()

Datum int2_avg_accum_inv ( PG_FUNCTION_ARGS  )

Definition at line 5736 of file numeric.c.

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

5737 {
5738  ArrayType *transarray;
5740  Int8TransTypeData *transdata;
5741 
5742  /*
5743  * If we're invoked as an aggregate, we can cheat and modify our first
5744  * parameter in-place to reduce palloc overhead. Otherwise we need to make
5745  * a copy of it before scribbling on it.
5746  */
5747  if (AggCheckCallContext(fcinfo, NULL))
5748  transarray = PG_GETARG_ARRAYTYPE_P(0);
5749  else
5750  transarray = PG_GETARG_ARRAYTYPE_P_COPY(0);
5751 
5752  if (ARR_HASNULL(transarray) ||
5753  ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
5754  elog(ERROR, "expected 2-element int8 array");
5755 
5756  transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
5757  transdata->count--;
5758  transdata->sum -= newval;
5759 
5760  PG_RETURN_ARRAYTYPE_P(transarray);
5761 }
signed short int16
Definition: c.h:354
#define ARR_OVERHEAD_NONULLS(ndims)
Definition: array.h:298
#define ARR_SIZE(a)
Definition: array.h:277
#define PG_GETARG_ARRAYTYPE_P_COPY(n)
Definition: array.h:252
#define PG_GETARG_ARRAYTYPE_P(n)
Definition: array.h:251
#define ERROR
Definition: elog.h:43
#define ARR_DATA_PTR(a)
Definition: array.h:310
#define ARR_HASNULL(a)
Definition: array.h:279
#define PG_RETURN_ARRAYTYPE_P(x)
Definition: array.h:253
#define PG_GETARG_INT16(n)
Definition: fmgr.h:271
#define newval
int AggCheckCallContext(FunctionCallInfo fcinfo, MemoryContext *aggcontext)
Definition: nodeAgg.c:4697
#define elog(elevel,...)
Definition: elog.h:214

◆ int2_numeric()

Datum int2_numeric ( PG_FUNCTION_ARGS  )

Definition at line 3521 of file numeric.c.

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

Referenced by int2_accum(), and int2_accum_inv().

3522 {
3523  int16 val = PG_GETARG_INT16(0);
3524  Numeric res;
3525  NumericVar result;
3526 
3527  init_var(&result);
3528 
3529  int64_to_numericvar((int64) val, &result);
3530 
3531  res = make_result(&result);
3532 
3533  free_var(&result);
3534 
3535  PG_RETURN_NUMERIC(res);
3536 }
#define PG_RETURN_NUMERIC(x)
Definition: numeric.h:54
signed short int16
Definition: c.h:354
#define PG_GETARG_INT16(n)
Definition: fmgr.h:271
static void free_var(NumericVar *var)
Definition: numeric.c:5950
static Numeric make_result(const NumericVar *var)
Definition: numeric.c:6566
static void int64_to_numericvar(int64 val, NumericVar *var)
Definition: numeric.c:6730
long val
Definition: informix.c:664
#define init_var(v)
Definition: numeric.c:445

◆ int2_sum()

Datum int2_sum ( PG_FUNCTION_ARGS  )

Definition at line 5497 of file numeric.c.

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

5498 {
5499  int64 newval;
5500 
5501  if (PG_ARGISNULL(0))
5502  {
5503  /* No non-null input seen so far... */
5504  if (PG_ARGISNULL(1))
5505  PG_RETURN_NULL(); /* still no non-null */
5506  /* This is the first non-null input. */
5507  newval = (int64) PG_GETARG_INT16(1);
5508  PG_RETURN_INT64(newval);
5509  }
5510 
5511  /*
5512  * If we're invoked as an aggregate, we can cheat and modify our first
5513  * parameter in-place to avoid palloc overhead. If not, we need to return
5514  * the new value of the transition variable. (If int8 is pass-by-value,
5515  * then of course this is useless as well as incorrect, so just ifdef it
5516  * out.)
5517  */
5518 #ifndef USE_FLOAT8_BYVAL /* controls int8 too */
5519  if (AggCheckCallContext(fcinfo, NULL))
5520  {
5521  int64 *oldsum = (int64 *) PG_GETARG_POINTER(0);
5522 
5523  /* Leave the running sum unchanged in the new input is null */
5524  if (!PG_ARGISNULL(1))
5525  *oldsum = *oldsum + (int64) PG_GETARG_INT16(1);
5526 
5527  PG_RETURN_POINTER(oldsum);
5528  }
5529  else
5530 #endif
5531  {
5532  int64 oldsum = PG_GETARG_INT64(0);
5533 
5534  /* Leave sum unchanged if new input is null. */
5535  if (PG_ARGISNULL(1))
5536  PG_RETURN_INT64(oldsum);
5537 
5538  /* OK to do the addition. */
5539  newval = oldsum + (int64) PG_GETARG_INT16(1);
5540 
5541  PG_RETURN_INT64(newval);
5542  }
5543 }
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:360
#define PG_RETURN_INT64(x)
Definition: fmgr.h:366
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:276
#define PG_GETARG_INT16(n)
Definition: fmgr.h:271
#define PG_ARGISNULL(n)
Definition: fmgr.h:209
#define newval
int AggCheckCallContext(FunctionCallInfo fcinfo, MemoryContext *aggcontext)
Definition: nodeAgg.c:4697
#define PG_GETARG_INT64(n)
Definition: fmgr.h:282
#define PG_RETURN_NULL()
Definition: fmgr.h:344

◆ int2int4_sum()

Datum int2int4_sum ( PG_FUNCTION_ARGS  )

Definition at line 5821 of file numeric.c.

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

5822 {
5823  ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
5824  Int8TransTypeData *transdata;
5825 
5826  if (ARR_HASNULL(transarray) ||
5827  ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
5828  elog(ERROR, "expected 2-element int8 array");
5829  transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
5830 
5831  /* SQL defines SUM of no values to be NULL */
5832  if (transdata->count == 0)
5833  PG_RETURN_NULL();
5834 
5835  PG_RETURN_DATUM(Int64GetDatumFast(transdata->sum));
5836 }
#define ARR_OVERHEAD_NONULLS(ndims)
Definition: array.h:298
#define ARR_SIZE(a)
Definition: array.h:277
#define PG_GETARG_ARRAYTYPE_P(n)
Definition: array.h:251
#define ERROR
Definition: elog.h:43
#define ARR_DATA_PTR(a)
Definition: array.h:310
#define ARR_HASNULL(a)
Definition: array.h:279
#define PG_RETURN_DATUM(x)
Definition: fmgr.h:352
#define Int64GetDatumFast(X)
Definition: postgres.h:760
#define elog(elevel,...)
Definition: elog.h:214
#define PG_RETURN_NULL()
Definition: fmgr.h:344

◆ int4_accum()

Datum int4_accum ( PG_FUNCTION_ARGS  )

Definition at line 4509 of file numeric.c.

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

4510 {
4512 
4513  state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
4514 
4515  /* Create the state data on the first call */
4516  if (state == NULL)
4517  state = makePolyNumAggState(fcinfo, true);
4518 
4519  if (!PG_ARGISNULL(1))
4520  {
4521 #ifdef HAVE_INT128
4522  do_int128_accum(state, (int128) PG_GETARG_INT32(1));
4523 #else
4524  Numeric newval;
4525 
4527  PG_GETARG_DATUM(1)));
4528  do_numeric_accum(state, newval);
4529 #endif
4530  }
4531 
4532  PG_RETURN_POINTER(state);
4533 }
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:360
#define PG_GETARG_INT32(n)
Definition: fmgr.h:269
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:268
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:276
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:624
static void do_numeric_accum(NumericAggState *state, Numeric newval)
Definition: numeric.c:3792
Datum int4_numeric(PG_FUNCTION_ARGS)
Definition: numeric.c:3385
#define PG_ARGISNULL(n)
Definition: fmgr.h:209
#define DatumGetNumeric(X)
Definition: numeric.h:49
Definition: regguts.h:298
#define newval
#define makePolyNumAggState
Definition: numeric.c:4477

◆ int4_accum_inv()

Datum int4_accum_inv ( PG_FUNCTION_ARGS  )

Definition at line 4989 of file numeric.c.

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

4990 {
4992 
4993  state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
4994 
4995  /* Should not get here with no state */
4996  if (state == NULL)
4997  elog(ERROR, "int4_accum_inv called with NULL state");
4998 
4999  if (!PG_ARGISNULL(1))
5000  {
5001 #ifdef HAVE_INT128
5002  do_int128_discard(state, (int128) PG_GETARG_INT32(1));
5003 #else
5004  Numeric newval;
5005 
5007  PG_GETARG_DATUM(1)));
5008 
5009  /* Should never fail, all inputs have dscale 0 */
5010  if (!do_numeric_discard(state, newval))
5011  elog(ERROR, "do_numeric_discard failed unexpectedly");
5012 #endif
5013  }
5014 
5015  PG_RETURN_POINTER(state);
5016 }
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:360
#define PG_GETARG_INT32(n)
Definition: fmgr.h:269
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:268
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:276
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:624
static bool do_numeric_discard(NumericAggState *state, Numeric newval)
Definition: numeric.c:3857
#define ERROR
Definition: elog.h:43
Datum int4_numeric(PG_FUNCTION_ARGS)
Definition: numeric.c:3385
#define PG_ARGISNULL(n)
Definition: fmgr.h:209
#define DatumGetNumeric(X)
Definition: numeric.h:49
Definition: regguts.h:298
#define newval
#define elog(elevel,...)
Definition: elog.h:214

◆ int4_avg_accum()

Datum int4_avg_accum ( PG_FUNCTION_ARGS  )

Definition at line 5677 of file numeric.c.

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

5678 {
5679  ArrayType *transarray;
5681  Int8TransTypeData *transdata;
5682 
5683  /*
5684  * If we're invoked as an aggregate, we can cheat and modify our first
5685  * parameter in-place to reduce palloc overhead. Otherwise we need to make
5686  * a copy of it before scribbling on it.
5687  */
5688  if (AggCheckCallContext(fcinfo, NULL))
5689  transarray = PG_GETARG_ARRAYTYPE_P(0);
5690  else
5691  transarray = PG_GETARG_ARRAYTYPE_P_COPY(0);
5692 
5693  if (ARR_HASNULL(transarray) ||
5694  ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
5695  elog(ERROR, "expected 2-element int8 array");
5696 
5697  transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
5698  transdata->count++;
5699  transdata->sum += newval;
5700 
5701  PG_RETURN_ARRAYTYPE_P(transarray);
5702 }
#define PG_GETARG_INT32(n)
Definition: fmgr.h:269
#define ARR_OVERHEAD_NONULLS(ndims)
Definition: array.h:298
#define ARR_SIZE(a)
Definition: array.h:277
#define PG_GETARG_ARRAYTYPE_P_COPY(n)
Definition: array.h:252
signed int int32
Definition: c.h:355
#define PG_GETARG_ARRAYTYPE_P(n)
Definition: array.h:251
#define ERROR
Definition: elog.h:43
#define ARR_DATA_PTR(a)
Definition: array.h:310
#define ARR_HASNULL(a)
Definition: array.h:279
#define PG_RETURN_ARRAYTYPE_P(x)
Definition: array.h:253
#define newval
int AggCheckCallContext(FunctionCallInfo fcinfo, MemoryContext *aggcontext)
Definition: nodeAgg.c:4697
#define elog(elevel,...)
Definition: elog.h:214

◆ int4_avg_accum_inv()

Datum int4_avg_accum_inv ( PG_FUNCTION_ARGS  )

Definition at line 5764 of file numeric.c.

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

5765 {
5766  ArrayType *transarray;
5768  Int8TransTypeData *transdata;
5769 
5770  /*
5771  * If we're invoked as an aggregate, we can cheat and modify our first
5772  * parameter in-place to reduce palloc overhead. Otherwise we need to make
5773  * a copy of it before scribbling on it.
5774  */
5775  if (AggCheckCallContext(fcinfo, NULL))
5776  transarray = PG_GETARG_ARRAYTYPE_P(0);
5777  else
5778  transarray = PG_GETARG_ARRAYTYPE_P_COPY(0);
5779 
5780  if (ARR_HASNULL(transarray) ||
5781  ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
5782  elog(ERROR, "expected 2-element int8 array");
5783 
5784  transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
5785  transdata->count--;
5786  transdata->sum -= newval;
5787 
5788  PG_RETURN_ARRAYTYPE_P(transarray);
5789 }
#define PG_GETARG_INT32(n)
Definition: fmgr.h:269
#define ARR_OVERHEAD_NONULLS(ndims)
Definition: array.h:298
#define ARR_SIZE(a)
Definition: array.h:277
#define PG_GETARG_ARRAYTYPE_P_COPY(n)
Definition: array.h:252
signed int int32
Definition: c.h:355
#define PG_GETARG_ARRAYTYPE_P(n)
Definition: array.h:251
#define ERROR
Definition: elog.h:43
#define ARR_DATA_PTR(a)
Definition: array.h:310
#define ARR_HASNULL(a)
Definition: array.h:279
#define PG_RETURN_ARRAYTYPE_P(x)
Definition: array.h:253
#define newval
int AggCheckCallContext(FunctionCallInfo fcinfo, MemoryContext *aggcontext)
Definition: nodeAgg.c:4697
#define elog(elevel,...)
Definition: elog.h:214

◆ int4_avg_combine()

Datum int4_avg_combine ( PG_FUNCTION_ARGS  )

Definition at line 5705 of file numeric.c.

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

5706 {
5707  ArrayType *transarray1;
5708  ArrayType *transarray2;
5709  Int8TransTypeData *state1;
5710  Int8TransTypeData *state2;
5711 
5712  if (!AggCheckCallContext(fcinfo, NULL))
5713  elog(ERROR, "aggregate function called in non-aggregate context");
5714 
5715  transarray1 = PG_GETARG_ARRAYTYPE_P(0);
5716  transarray2 = PG_GETARG_ARRAYTYPE_P(1);
5717 
5718  if (ARR_HASNULL(transarray1) ||
5719  ARR_SIZE(transarray1) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
5720  elog(ERROR, "expected 2-element int8 array");
5721 
5722  if (ARR_HASNULL(transarray2) ||
5723  ARR_SIZE(transarray2) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
5724  elog(ERROR, "expected 2-element int8 array");
5725 
5726  state1 = (Int8TransTypeData *) ARR_DATA_PTR(transarray1);
5727  state2 = (Int8TransTypeData *) ARR_DATA_PTR(transarray2);
5728 
5729  state1->count += state2->count;
5730  state1->sum += state2->sum;
5731 
5732  PG_RETURN_ARRAYTYPE_P(transarray1);
5733 }
#define ARR_OVERHEAD_NONULLS(ndims)
Definition: array.h:298
#define ARR_SIZE(a)
Definition: array.h:277
#define PG_GETARG_ARRAYTYPE_P(n)
Definition: array.h:251
#define ERROR
Definition: elog.h:43
#define ARR_DATA_PTR(a)
Definition: array.h:310
#define ARR_HASNULL(a)
Definition: array.h:279
#define PG_RETURN_ARRAYTYPE_P(x)
Definition: array.h:253
int AggCheckCallContext(FunctionCallInfo fcinfo, MemoryContext *aggcontext)
Definition: nodeAgg.c:4697
#define elog(elevel,...)
Definition: elog.h:214

◆ int4_numeric()

Datum int4_numeric ( PG_FUNCTION_ARGS  )