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/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 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)
 
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 364 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 436 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 438 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 100 of file numeric.c.

Referenced by div_var_fast().

◆ dump_numeric

#define dump_numeric (   s,
 
)

Definition at line 432 of file numeric.c.

Referenced by int2int4_sum(), and make_result_opt_error().

◆ dump_var

#define dump_var (   s,
 
)

Definition at line 433 of file numeric.c.

Referenced by int2int4_sum().

◆ HALF_NBASE

#define HALF_NBASE   5000

Definition at line 97 of file numeric.c.

Referenced by div_var(), and round_var().

◆ init_var

◆ makePolyNumAggState

#define makePolyNumAggState   makeNumericAggState

◆ makePolyNumAggStateCurrentContext

#define makePolyNumAggStateCurrentContext   makeNumericAggStateCurrentContext

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

Referenced by mul_var().

◆ NBASE

◆ NUMERIC_ABBREV_BITS

#define NUMERIC_ABBREV_BITS   (SIZEOF_DATUM * BITS_PER_BYTE)

Definition at line 357 of file numeric.c.

◆ NUMERIC_ABBREV_NAN

#define NUMERIC_ABBREV_NAN   NumericAbbrevGetDatum(PG_INT32_MIN)

Definition at line 365 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:200
int scale
Definition: pgbench.c:153
#define NUMERIC_SHORT_WEIGHT_MIN
Definition: numeric.c:201
#define NUMERIC_SHORT_DSCALE_MAX
Definition: numeric.c:196

Definition at line 450 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:184

Definition at line 446 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:184
#define NUMERIC_DSCALE_MASK
Definition: numeric.c:207
#define NUMERIC_SHORT_DSCALE_MASK
Definition: numeric.c:194
#define NUMERIC_SHORT_DSCALE_SHIFT
Definition: numeric.c:195

Definition at line 213 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 207 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 172 of file numeric.c.

◆ NUMERIC_HDRSZ

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

Definition at line 176 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 177 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 184 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:184
#define VARHDRSZ
Definition: c.h:561
unsigned short uint16
Definition: c.h:366

Definition at line 185 of file numeric.c.

◆ NUMERIC_IS_NAN

◆ NUMERIC_IS_SHORT

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

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

Referenced by make_result_opt_error().

◆ NUMERIC_SHORT_DSCALE_MASK

#define NUMERIC_SHORT_DSCALE_MASK   0x1F80

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

◆ NUMERIC_SHORT_DSCALE_SHIFT

#define NUMERIC_SHORT_DSCALE_SHIFT   7

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

◆ NUMERIC_SHORT_WEIGHT_MIN

#define NUMERIC_SHORT_WEIGHT_MIN   (-(NUMERIC_SHORT_WEIGHT_MASK+1))

Definition at line 201 of file numeric.c.

◆ NUMERIC_SHORT_WEIGHT_SIGN_MASK

#define NUMERIC_SHORT_WEIGHT_SIGN_MASK   0x0040

Definition at line 198 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:167
#define NUMERIC_FLAGBITS(n)
Definition: numeric.c:172
#define NUMERIC_SHORT_SIGN_MASK
Definition: numeric.c:193
#define NUMERIC_IS_SHORT(n)
Definition: numeric.c:174

Definition at line 209 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 166 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:184
#define NUMERIC_SHORT_WEIGHT_SIGN_MASK
Definition: numeric.c:198
#define NUMERIC_SHORT_WEIGHT_MASK
Definition: numeric.c:199

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

Referenced by numeric_cmp_abbrev().

Typedef Documentation

◆ Int8TransTypeData

◆ NumericAggState

◆ NumericDigit

Definition at line 102 of file numeric.c.

◆ NumericSumAccum

◆ NumericVar

typedef struct NumericVar NumericVar

◆ PolyNumAggState

Definition at line 4446 of file numeric.c.

Function Documentation

◆ accum_sum_add()

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

Definition at line 9933 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().

9934 {
9935  int32 *accum_digits;
9936  int i,
9937  val_i;
9938  int val_ndigits;
9939  NumericDigit *val_digits;
9940 
9941  /*
9942  * If we have accumulated too many values since the last carry
9943  * propagation, do it now, to avoid overflowing. (We could allow more
9944  * than NBASE - 1, if we reserved two extra digits, rather than one, for
9945  * carry propagation. But even with NBASE - 1, this needs to be done so
9946  * seldom, that the performance difference is negligible.)
9947  */
9948  if (accum->num_uncarried == NBASE - 1)
9949  accum_sum_carry(accum);
9950 
9951  /*
9952  * Adjust the weight or scale of the old value, so that it can accommodate
9953  * the new value.
9954  */
9955  accum_sum_rescale(accum, val);
9956 
9957  /* */
9958  if (val->sign == NUMERIC_POS)
9959  accum_digits = accum->pos_digits;
9960  else
9961  accum_digits = accum->neg_digits;
9962 
9963  /* copy these values into local vars for speed in loop */
9964  val_ndigits = val->ndigits;
9965  val_digits = val->digits;
9966 
9967  i = accum->weight - val->weight;
9968  for (val_i = 0; val_i < val_ndigits; val_i++)
9969  {
9970  accum_digits[i] += (int32) val_digits[val_i];
9971  i++;
9972  }
9973 
9974  accum->num_uncarried++;
9975 }
static void accum_sum_rescale(NumericSumAccum *accum, const NumericVar *val)
Definition: numeric.c:10054
#define NUMERIC_POS
Definition: numeric.c:167
int32 * neg_digits
Definition: numeric.c:347
int num_uncarried
Definition: numeric.c:344
static void accum_sum_carry(NumericSumAccum *accum)
Definition: numeric.c:9981
signed int int32
Definition: c.h:355
int16 NumericDigit
Definition: numeric.c:102
#define NBASE
Definition: numeric.c:96
int i
int32 * pos_digits
Definition: numeric.c:346
long val
Definition: informix.c:664

◆ accum_sum_carry()

static void accum_sum_carry ( NumericSumAccum accum)
static

Definition at line 9981 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().

9982 {
9983  int i;
9984  int ndigits;
9985  int32 *dig;
9986  int32 carry;
9987  int32 newdig = 0;
9988 
9989  /*
9990  * If no new values have been added since last carry propagation, nothing
9991  * to do.
9992  */
9993  if (accum->num_uncarried == 0)
9994  return;
9995 
9996  /*
9997  * We maintain that the weight of the accumulator is always one larger
9998  * than needed to hold the current value, before carrying, to make sure
9999  * there is enough space for the possible extra digit when carry is
10000  * propagated. We cannot expand the buffer here, unless we require
10001  * callers of accum_sum_final() to switch to the right memory context.
10002  */
10003  Assert(accum->pos_digits[0] == 0 && accum->neg_digits[0] == 0);
10004 
10005  ndigits = accum->ndigits;
10006 
10007  /* Propagate carry in the positive sum */
10008  dig = accum->pos_digits;
10009  carry = 0;
10010  for (i = ndigits - 1; i >= 0; i--)
10011  {
10012  newdig = dig[i] + carry;
10013  if (newdig >= NBASE)
10014  {
10015  carry = newdig / NBASE;
10016  newdig -= carry * NBASE;
10017  }
10018  else
10019  carry = 0;
10020  dig[i] = newdig;
10021  }
10022  /* Did we use up the digit reserved for carry propagation? */
10023  if (newdig > 0)
10024  accum->have_carry_space = false;
10025 
10026  /* And the same for the negative sum */
10027  dig = accum->neg_digits;
10028  carry = 0;
10029  for (i = ndigits - 1; i >= 0; i--)
10030  {
10031  newdig = dig[i] + carry;
10032  if (newdig >= NBASE)
10033  {
10034  carry = newdig / NBASE;
10035  newdig -= carry * NBASE;
10036  }
10037  else
10038  carry = 0;
10039  dig[i] = newdig;
10040  }
10041  if (newdig > 0)
10042  accum->have_carry_space = false;
10043 
10044  accum->num_uncarried = 0;
10045 }
int32 * neg_digits
Definition: numeric.c:347
int num_uncarried
Definition: numeric.c:344
signed int int32
Definition: c.h:355
bool have_carry_space
Definition: numeric.c:345
#define NBASE
Definition: numeric.c:96
#define Assert(condition)
Definition: c.h:738
int i
int32 * pos_digits
Definition: numeric.c:346

◆ accum_sum_combine()

static void accum_sum_combine ( NumericSumAccum accum,
NumericSumAccum accum2 
)
static

Definition at line 10211 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().

10212 {
10213  NumericVar tmp_var;
10214 
10215  init_var(&tmp_var);
10216 
10217  accum_sum_final(accum2, &tmp_var);
10218  accum_sum_add(accum, &tmp_var);
10219 
10220  free_var(&tmp_var);
10221 }
static void accum_sum_final(NumericSumAccum *accum, NumericVar *result)
Definition: numeric.c:10143
static void accum_sum_add(NumericSumAccum *accum, const NumericVar *var1)
Definition: numeric.c:9933
static void free_var(NumericVar *var)
Definition: numeric.c:5921
#define init_var(v)
Definition: numeric.c:444

◆ accum_sum_copy()

static void accum_sum_copy ( NumericSumAccum dst,
NumericSumAccum src 
)
static

Definition at line 10194 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().

10195 {
10196  dst->pos_digits = palloc(src->ndigits * sizeof(int32));
10197  dst->neg_digits = palloc(src->ndigits * sizeof(int32));
10198 
10199  memcpy(dst->pos_digits, src->pos_digits, src->ndigits * sizeof(int32));
10200  memcpy(dst->neg_digits, src->neg_digits, src->ndigits * sizeof(int32));
10201  dst->num_uncarried = src->num_uncarried;
10202  dst->ndigits = src->ndigits;
10203  dst->weight = src->weight;
10204  dst->dscale = src->dscale;
10205 }
int32 * neg_digits
Definition: numeric.c:347
int num_uncarried
Definition: numeric.c:344
signed int int32
Definition: c.h:355
void * palloc(Size size)
Definition: mcxt.c:949
int32 * pos_digits
Definition: numeric.c:346

◆ accum_sum_final()

static void accum_sum_final ( NumericSumAccum accum,
NumericVar result 
)
static

Definition at line 10143 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().

10144 {
10145  int i;
10146  NumericVar pos_var;
10147  NumericVar neg_var;
10148 
10149  if (accum->ndigits == 0)
10150  {
10151  set_var_from_var(&const_zero, result);
10152  return;
10153  }
10154 
10155  /* Perform final carry */
10156  accum_sum_carry(accum);
10157 
10158  /* Create NumericVars representing the positive and negative sums */
10159  init_var(&pos_var);
10160  init_var(&neg_var);
10161 
10162  pos_var.ndigits = neg_var.ndigits = accum->ndigits;
10163  pos_var.weight = neg_var.weight = accum->weight;
10164  pos_var.dscale = neg_var.dscale = accum->dscale;
10165  pos_var.sign = NUMERIC_POS;
10166  neg_var.sign = NUMERIC_NEG;
10167 
10168  pos_var.buf = pos_var.digits = digitbuf_alloc(accum->ndigits);
10169  neg_var.buf = neg_var.digits = digitbuf_alloc(accum->ndigits);
10170 
10171  for (i = 0; i < accum->ndigits; i++)
10172  {
10173  Assert(accum->pos_digits[i] < NBASE);
10174  pos_var.digits[i] = (int16) accum->pos_digits[i];
10175 
10176  Assert(accum->neg_digits[i] < NBASE);
10177  neg_var.digits[i] = (int16) accum->neg_digits[i];
10178  }
10179 
10180  /* And add them together */
10181  add_var(&pos_var, &neg_var, result);
10182 
10183  /* Remove leading/trailing zeroes */
10184  strip_var(result);
10185 }
signed short int16
Definition: c.h:354
int weight
Definition: numeric.c:275
#define NUMERIC_POS
Definition: numeric.c:167
static void strip_var(NumericVar *var)
Definition: numeric.c:9876
int32 * neg_digits
Definition: numeric.c:347
#define digitbuf_alloc(ndigits)
Definition: numeric.c:436
int ndigits
Definition: numeric.c:274
static void accum_sum_carry(NumericSumAccum *accum)
Definition: numeric.c:9981
int dscale
Definition: numeric.c:277
#define NUMERIC_NEG
Definition: numeric.c:168
int sign
Definition: numeric.c:276
NumericDigit * buf
Definition: numeric.c:278
#define NBASE
Definition: numeric.c:96
static const NumericVar const_zero
Definition: numeric.c:374
#define Assert(condition)
Definition: c.h:738
NumericDigit * digits
Definition: numeric.c:279
static void add_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition: numeric.c:6983
int i
static void set_var_from_var(const NumericVar *value, NumericVar *dest)
Definition: numeric.c:6171
int32 * pos_digits
Definition: numeric.c:346
#define init_var(v)
Definition: numeric.c:444

◆ accum_sum_rescale()

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

Definition at line 10054 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().

10055 {
10056  int old_weight = accum->weight;
10057  int old_ndigits = accum->ndigits;
10058  int accum_ndigits;
10059  int accum_weight;
10060  int accum_rscale;
10061  int val_rscale;
10062 
10063  accum_weight = old_weight;
10064  accum_ndigits = old_ndigits;
10065 
10066  /*
10067  * Does the new value have a larger weight? If so, enlarge the buffers,
10068  * and shift the existing value to the new weight, by adding leading
10069  * zeros.
10070  *
10071  * We enforce that the accumulator always has a weight one larger than
10072  * needed for the inputs, so that we have space for an extra digit at the
10073  * final carry-propagation phase, if necessary.
10074  */
10075  if (val->weight >= accum_weight)
10076  {
10077  accum_weight = val->weight + 1;
10078  accum_ndigits = accum_ndigits + (accum_weight - old_weight);
10079  }
10080 
10081  /*
10082  * Even though the new value is small, we might've used up the space
10083  * reserved for the carry digit in the last call to accum_sum_carry(). If
10084  * so, enlarge to make room for another one.
10085  */
10086  else if (!accum->have_carry_space)
10087  {
10088  accum_weight++;
10089  accum_ndigits++;
10090  }
10091 
10092  /* Is the new value wider on the right side? */
10093  accum_rscale = accum_ndigits - accum_weight - 1;
10094  val_rscale = val->ndigits - val->weight - 1;
10095  if (val_rscale > accum_rscale)
10096  accum_ndigits = accum_ndigits + (val_rscale - accum_rscale);
10097 
10098  if (accum_ndigits != old_ndigits ||
10099  accum_weight != old_weight)
10100  {
10101  int32 *new_pos_digits;
10102  int32 *new_neg_digits;
10103  int weightdiff;
10104 
10105  weightdiff = accum_weight - old_weight;
10106 
10107  new_pos_digits = palloc0(accum_ndigits * sizeof(int32));
10108  new_neg_digits = palloc0(accum_ndigits * sizeof(int32));
10109 
10110  if (accum->pos_digits)
10111  {
10112  memcpy(&new_pos_digits[weightdiff], accum->pos_digits,
10113  old_ndigits * sizeof(int32));
10114  pfree(accum->pos_digits);
10115 
10116  memcpy(&new_neg_digits[weightdiff], accum->neg_digits,
10117  old_ndigits * sizeof(int32));
10118  pfree(accum->neg_digits);
10119  }
10120 
10121  accum->pos_digits = new_pos_digits;
10122  accum->neg_digits = new_neg_digits;
10123 
10124  accum->weight = accum_weight;
10125  accum->ndigits = accum_ndigits;
10126 
10127  Assert(accum->pos_digits[0] == 0 && accum->neg_digits[0] == 0);
10128  accum->have_carry_space = true;
10129  }
10130 
10131  if (val->dscale > accum->dscale)
10132  accum->dscale = val->dscale;
10133 }
int weight
Definition: numeric.c:275
int32 * neg_digits
Definition: numeric.c:347
int ndigits
Definition: numeric.c:274
int dscale
Definition: numeric.c:277
signed int int32
Definition: c.h:355
void pfree(void *pointer)
Definition: mcxt.c:1056
bool have_carry_space
Definition: numeric.c:345
void * palloc0(Size size)
Definition: mcxt.c:980
#define Assert(condition)
Definition: c.h:738
int32 * pos_digits
Definition: numeric.c:346

◆ accum_sum_reset()

static void accum_sum_reset ( NumericSumAccum accum)
static

Definition at line 9917 of file numeric.c.

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

Referenced by do_numeric_discard().

9918 {
9919  int i;
9920 
9921  accum->dscale = 0;
9922  for (i = 0; i < accum->ndigits; i++)
9923  {
9924  accum->pos_digits[i] = 0;
9925  accum->neg_digits[i] = 0;
9926  }
9927 }
int32 * neg_digits
Definition: numeric.c:347
int i
int32 * pos_digits
Definition: numeric.c:346

◆ add_abs()

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

Definition at line 9541 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().

9542 {
9543  NumericDigit *res_buf;
9544  NumericDigit *res_digits;
9545  int res_ndigits;
9546  int res_weight;
9547  int res_rscale,
9548  rscale1,
9549  rscale2;
9550  int res_dscale;
9551  int i,
9552  i1,
9553  i2;
9554  int carry = 0;
9555 
9556  /* copy these values into local vars for speed in inner loop */
9557  int var1ndigits = var1->ndigits;
9558  int var2ndigits = var2->ndigits;
9559  NumericDigit *var1digits = var1->digits;
9560  NumericDigit *var2digits = var2->digits;
9561 
9562  res_weight = Max(var1->weight, var2->weight) + 1;
9563 
9564  res_dscale = Max(var1->dscale, var2->dscale);
9565 
9566  /* Note: here we are figuring rscale in base-NBASE digits */
9567  rscale1 = var1->ndigits - var1->weight - 1;
9568  rscale2 = var2->ndigits - var2->weight - 1;
9569  res_rscale = Max(rscale1, rscale2);
9570 
9571  res_ndigits = res_rscale + res_weight + 1;
9572  if (res_ndigits <= 0)
9573  res_ndigits = 1;
9574 
9575  res_buf = digitbuf_alloc(res_ndigits + 1);
9576  res_buf[0] = 0; /* spare digit for later rounding */
9577  res_digits = res_buf + 1;
9578 
9579  i1 = res_rscale + var1->weight + 1;
9580  i2 = res_rscale + var2->weight + 1;
9581  for (i = res_ndigits - 1; i >= 0; i--)
9582  {
9583  i1--;
9584  i2--;
9585  if (i1 >= 0 && i1 < var1ndigits)
9586  carry += var1digits[i1];
9587  if (i2 >= 0 && i2 < var2ndigits)
9588  carry += var2digits[i2];
9589 
9590  if (carry >= NBASE)
9591  {
9592  res_digits[i] = carry - NBASE;
9593  carry = 1;
9594  }
9595  else
9596  {
9597  res_digits[i] = carry;
9598  carry = 0;
9599  }
9600  }
9601 
9602  Assert(carry == 0); /* else we failed to allow for carry out */
9603 
9604  digitbuf_free(result->buf);
9605  result->ndigits = res_ndigits;
9606  result->buf = res_buf;
9607  result->digits = res_digits;
9608  result->weight = res_weight;
9609  result->dscale = res_dscale;
9610 
9611  /* Remove leading/trailing zeroes */
9612  strip_var(result);
9613 }
int weight
Definition: numeric.c:275
static void strip_var(NumericVar *var)
Definition: numeric.c:9876
#define digitbuf_alloc(ndigits)
Definition: numeric.c:436
int ndigits
Definition: numeric.c:274
int dscale
Definition: numeric.c:277
#define digitbuf_free(buf)
Definition: numeric.c:438
int16 NumericDigit
Definition: numeric.c:102
NumericDigit * buf
Definition: numeric.c:278
#define NBASE
Definition: numeric.c:96
#define Assert(condition)
Definition: c.h:738
NumericDigit * digits
Definition: numeric.c:279
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 6983 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().

6984 {
6985  /*
6986  * Decide on the signs of the two variables what to do
6987  */
6988  if (var1->sign == NUMERIC_POS)
6989  {
6990  if (var2->sign == NUMERIC_POS)
6991  {
6992  /*
6993  * Both are positive result = +(ABS(var1) + ABS(var2))
6994  */
6995  add_abs(var1, var2, result);
6996  result->sign = NUMERIC_POS;
6997  }
6998  else
6999  {
7000  /*
7001  * var1 is positive, var2 is negative Must compare absolute values
7002  */
7003  switch (cmp_abs(var1, var2))
7004  {
7005  case 0:
7006  /* ----------
7007  * ABS(var1) == ABS(var2)
7008  * result = ZERO
7009  * ----------
7010  */
7011  zero_var(result);
7012  result->dscale = Max(var1->dscale, var2->dscale);
7013  break;
7014 
7015  case 1:
7016  /* ----------
7017  * ABS(var1) > ABS(var2)
7018  * result = +(ABS(var1) - ABS(var2))
7019  * ----------
7020  */
7021  sub_abs(var1, var2, result);
7022  result->sign = NUMERIC_POS;
7023  break;
7024 
7025  case -1:
7026  /* ----------
7027  * ABS(var1) < ABS(var2)
7028  * result = -(ABS(var2) - ABS(var1))
7029  * ----------
7030  */
7031  sub_abs(var2, var1, result);
7032  result->sign = NUMERIC_NEG;
7033  break;
7034  }
7035  }
7036  }
7037  else
7038  {
7039  if (var2->sign == NUMERIC_POS)
7040  {
7041  /* ----------
7042  * var1 is negative, var2 is positive
7043  * Must compare absolute values
7044  * ----------
7045  */
7046  switch (cmp_abs(var1, var2))
7047  {
7048  case 0:
7049  /* ----------
7050  * ABS(var1) == ABS(var2)
7051  * result = ZERO
7052  * ----------
7053  */
7054  zero_var(result);
7055  result->dscale = Max(var1->dscale, var2->dscale);
7056  break;
7057 
7058  case 1:
7059  /* ----------
7060  * ABS(var1) > ABS(var2)
7061  * result = -(ABS(var1) - ABS(var2))
7062  * ----------
7063  */
7064  sub_abs(var1, var2, result);
7065  result->sign = NUMERIC_NEG;
7066  break;
7067 
7068  case -1:
7069  /* ----------
7070  * ABS(var1) < ABS(var2)
7071  * result = +(ABS(var2) - ABS(var1))
7072  * ----------
7073  */
7074  sub_abs(var2, var1, result);
7075  result->sign = NUMERIC_POS;
7076  break;
7077  }
7078  }
7079  else
7080  {
7081  /* ----------
7082  * Both are negative
7083  * result = -(ABS(var1) + ABS(var2))
7084  * ----------
7085  */
7086  add_abs(var1, var2, result);
7087  result->sign = NUMERIC_NEG;
7088  }
7089  }
7090 }
static void sub_abs(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition: numeric.c:9626
static void add_abs(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition: numeric.c:9541
#define NUMERIC_POS
Definition: numeric.c:167
int dscale
Definition: numeric.c:277
#define NUMERIC_NEG
Definition: numeric.c:168
int sign
Definition: numeric.c:276
static void zero_var(NumericVar *var)
Definition: numeric.c:5937
static int cmp_abs(const NumericVar *var1, const NumericVar *var2)
Definition: numeric.c:9463
#define Max(x, y)
Definition: numeric.c:13

◆ alloc_var()

static void alloc_var ( NumericVar var,
int  ndigits 
)
static

Definition at line 5905 of file numeric.c.

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

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

5906 {
5907  digitbuf_free(var->buf);
5908  var->buf = digitbuf_alloc(ndigits + 1);
5909  var->buf[0] = 0; /* spare digit for rounding */
5910  var->digits = var->buf + 1;
5911  var->ndigits = ndigits;
5912 }
#define digitbuf_alloc(ndigits)
Definition: numeric.c:436
int ndigits
Definition: numeric.c:274
#define digitbuf_free(buf)
Definition: numeric.c:438
NumericDigit * buf
Definition: numeric.c:278
NumericDigit * digits
Definition: numeric.c:279

◆ apply_typmod()

static void apply_typmod ( NumericVar var,
int32  typmod 
)
static

Definition at line 6550 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().

6551 {
6552  int precision;
6553  int scale;
6554  int maxdigits;
6555  int ddigits;
6556  int i;
6557 
6558  /* Do nothing if we have a default typmod (-1) */
6559  if (typmod < (int32) (VARHDRSZ))
6560  return;
6561 
6562  typmod -= VARHDRSZ;
6563  precision = (typmod >> 16) & 0xffff;
6564  scale = typmod & 0xffff;
6565  maxdigits = precision - scale;
6566 
6567  /* Round to target scale (and set var->dscale) */
6568  round_var(var, scale);
6569 
6570  /*
6571  * Check for overflow - note we can't do this before rounding, because
6572  * rounding could raise the weight. Also note that the var's weight could
6573  * be inflated by leading zeroes, which will be stripped before storage
6574  * but perhaps might not have been yet. In any case, we must recognize a
6575  * true zero, whose weight doesn't mean anything.
6576  */
6577  ddigits = (var->weight + 1) * DEC_DIGITS;
6578  if (ddigits > maxdigits)
6579  {
6580  /* Determine true weight; and check for all-zero result */
6581  for (i = 0; i < var->ndigits; i++)
6582  {
6583  NumericDigit dig = var->digits[i];
6584 
6585  if (dig)
6586  {
6587  /* Adjust for any high-order decimal zero digits */
6588 #if DEC_DIGITS == 4
6589  if (dig < 10)
6590  ddigits -= 3;
6591  else if (dig < 100)
6592  ddigits -= 2;
6593  else if (dig < 1000)
6594  ddigits -= 1;
6595 #elif DEC_DIGITS == 2
6596  if (dig < 10)
6597  ddigits -= 1;
6598 #elif DEC_DIGITS == 1
6599  /* no adjustment */
6600 #else
6601 #error unsupported NBASE
6602 #endif
6603  if (ddigits > maxdigits)
6604  ereport(ERROR,
6605  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
6606  errmsg("numeric field overflow"),
6607  errdetail("A field with precision %d, scale %d must round to an absolute value less than %s%d.",
6608  precision, scale,
6609  /* Display 10^0 as 1 */
6610  maxdigits ? "10^" : "",
6611  maxdigits ? maxdigits : 1
6612  )));
6613  break;
6614  }
6615  ddigits -= DEC_DIGITS;
6616  }
6617  }
6618 }
static void round_var(NumericVar *var, int rscale)
Definition: numeric.c:9708
int weight
Definition: numeric.c:275
#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:274
signed int int32
Definition: c.h:355
#define ERROR
Definition: elog.h:43
int16 NumericDigit
Definition: numeric.c:102
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:279
int errmsg(const char *fmt,...)
Definition: elog.c:824
int i
#define DEC_DIGITS
Definition: numeric.c:98

◆ ceil_var()

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

Definition at line 8177 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().

8178 {
8179  NumericVar tmp;
8180 
8181  init_var(&tmp);
8182  set_var_from_var(var, &tmp);
8183 
8184  trunc_var(&tmp, 0);
8185 
8186  if (var->sign == NUMERIC_POS && cmp_var(var, &tmp) != 0)
8187  add_var(&tmp, &const_one, &tmp);
8188 
8189  set_var_from_var(&tmp, result);
8190  free_var(&tmp);
8191 }
static void trunc_var(NumericVar *var, int rscale)
Definition: numeric.c:9814
static const NumericVar const_one
Definition: numeric.c:378
#define NUMERIC_POS
Definition: numeric.c:167
int sign
Definition: numeric.c:276
static int cmp_var(const NumericVar *var1, const NumericVar *var2)
Definition: numeric.c:6925
static void free_var(NumericVar *var)
Definition: numeric.c:5921
static void add_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition: numeric.c:6983
static void set_var_from_var(const NumericVar *value, NumericVar *dest)
Definition: numeric.c:6171
#define init_var(v)
Definition: numeric.c:444

◆ cmp_abs()

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

Definition at line 9463 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().

9464 {
9465  return cmp_abs_common(var1->digits, var1->ndigits, var1->weight,
9466  var2->digits, var2->ndigits, var2->weight);
9467 }
int weight
Definition: numeric.c:275
int ndigits
Definition: numeric.c:274
NumericDigit * digits
Definition: numeric.c:279
static int cmp_abs_common(const NumericDigit *var1digits, int var1ndigits, int var1weight, const NumericDigit *var2digits, int var2ndigits, int var2weight)
Definition: numeric.c:9477

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

References stat.

Referenced by cmp_abs(), and cmp_var_common().

9479 {
9480  int i1 = 0;
9481  int i2 = 0;
9482 
9483  /* Check any digits before the first common digit */
9484 
9485  while (var1weight > var2weight && i1 < var1ndigits)
9486  {
9487  if (var1digits[i1++] != 0)
9488  return 1;
9489  var1weight--;
9490  }
9491  while (var2weight > var1weight && i2 < var2ndigits)
9492  {
9493  if (var2digits[i2++] != 0)
9494  return -1;
9495  var2weight--;
9496  }
9497 
9498  /* At this point, either w1 == w2 or we've run out of digits */
9499 
9500  if (var1weight == var2weight)
9501  {
9502  while (i1 < var1ndigits && i2 < var2ndigits)
9503  {
9504  int stat = var1digits[i1++] - var2digits[i2++];
9505 
9506  if (stat)
9507  {
9508  if (stat > 0)
9509  return 1;
9510  return -1;
9511  }
9512  }
9513  }
9514 
9515  /*
9516  * At this point, we've run out of digits on one side or the other; so any
9517  * remaining nonzero digits imply that side is larger
9518  */
9519  while (i1 < var1ndigits)
9520  {
9521  if (var1digits[i1++] != 0)
9522  return 1;
9523  }
9524  while (i2 < var2ndigits)
9525  {
9526  if (var2digits[i2++] != 0)
9527  return -1;
9528  }
9529 
9530  return 0;
9531 }
#define stat(a, b)
Definition: win32_port.h:255

◆ cmp_numerics()

static int cmp_numerics ( Numeric  num1,
Numeric  num2 
)
static

Definition at line 2146 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().

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

◆ cmp_var()

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

Definition at line 6925 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().

6926 {
6927  return cmp_var_common(var1->digits, var1->ndigits,
6928  var1->weight, var1->sign,
6929  var2->digits, var2->ndigits,
6930  var2->weight, var2->sign);
6931 }
int weight
Definition: numeric.c:275
int ndigits
Definition: numeric.c:274
int sign
Definition: numeric.c:276
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:6940
NumericDigit * digits
Definition: numeric.c:279

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

References cmp_abs_common(), NUMERIC_NEG, and NUMERIC_POS.

Referenced by cmp_numerics(), and cmp_var().

6944 {
6945  if (var1ndigits == 0)
6946  {
6947  if (var2ndigits == 0)
6948  return 0;
6949  if (var2sign == NUMERIC_NEG)
6950  return 1;
6951  return -1;
6952  }
6953  if (var2ndigits == 0)
6954  {
6955  if (var1sign == NUMERIC_POS)
6956  return 1;
6957  return -1;
6958  }
6959 
6960  if (var1sign == NUMERIC_POS)
6961  {
6962  if (var2sign == NUMERIC_NEG)
6963  return 1;
6964  return cmp_abs_common(var1digits, var1ndigits, var1weight,
6965  var2digits, var2ndigits, var2weight);
6966  }
6967 
6968  if (var2sign == NUMERIC_POS)
6969  return -1;
6970 
6971  return cmp_abs_common(var2digits, var2ndigits, var2weight,
6972  var1digits, var1ndigits, var1weight);
6973 }
#define NUMERIC_POS
Definition: numeric.c:167
#define NUMERIC_NEG
Definition: numeric.c:168
static int cmp_abs_common(const NumericDigit *var1digits, int var1ndigits, int var1weight, const NumericDigit *var2digits, int var2ndigits, int var2weight)
Definition: numeric.c:9477

◆ compute_bucket()

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

Definition at line 1573 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().

1575 {
1576  NumericVar bound1_var;
1577  NumericVar bound2_var;
1578  NumericVar operand_var;
1579 
1580  init_var_from_num(bound1, &bound1_var);
1581  init_var_from_num(bound2, &bound2_var);
1582  init_var_from_num(operand, &operand_var);
1583 
1584  if (cmp_var(&bound1_var, &bound2_var) < 0)
1585  {
1586  sub_var(&operand_var, &bound1_var, &operand_var);
1587  sub_var(&bound2_var, &bound1_var, &bound2_var);
1588  div_var(&operand_var, &bound2_var, result_var,
1589  select_div_scale(&operand_var, &bound2_var), true);
1590  }
1591  else
1592  {
1593  sub_var(&bound1_var, &operand_var, &operand_var);
1594  sub_var(&bound1_var, &bound2_var, &bound1_var);
1595  div_var(&operand_var, &bound1_var, result_var,
1596  select_div_scale(&operand_var, &bound1_var), true);
1597  }
1598 
1599  mul_var(result_var, count_var, result_var,
1600  result_var->dscale + count_var->dscale);
1601  add_var(result_var, &const_one, result_var);
1602  floor_var(result_var, result_var);
1603 
1604  free_var(&bound1_var);
1605  free_var(&bound2_var);
1606  free_var(&operand_var);
1607 }
static const NumericVar const_one
Definition: numeric.c:378
static void div_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result, int rscale, bool round)
Definition: numeric.c:7418
int dscale
Definition: numeric.c:277
static int select_div_scale(const NumericVar *var1, const NumericVar *var2)
Definition: numeric.c:8009
static void init_var_from_num(Numeric num, NumericVar *dest)
Definition: numeric.c:6154
static int cmp_var(const NumericVar *var1, const NumericVar *var2)
Definition: numeric.c:6925
static void free_var(NumericVar *var)
Definition: numeric.c:5921
static void mul_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result, int rscale)
Definition: numeric.c:7221
static void add_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition: numeric.c:6983
static void sub_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition: numeric.c:7100
static void floor_var(const NumericVar *var, NumericVar *result)
Definition: numeric.c:8201

◆ div_mod_var()

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

Definition at line 8107 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().

8109 {
8110  NumericVar q;
8111  NumericVar r;
8112 
8113  init_var(&q);
8114  init_var(&r);
8115 
8116  /*
8117  * Use div_var_fast() to get an initial estimate for the integer quotient.
8118  * This might be inaccurate (per the warning in div_var_fast's comments),
8119  * but we can correct it below.
8120  */
8121  div_var_fast(var1, var2, &q, 0, false);
8122 
8123  /* Compute initial estimate of remainder using the quotient estimate. */
8124  mul_var(var2, &q, &r, var2->dscale);
8125  sub_var(var1, &r, &r);
8126 
8127  /*
8128  * Adjust the results if necessary --- the remainder should have the same
8129  * sign as var1, and its absolute value should be less than the absolute
8130  * value of var2.
8131  */
8132  while (r.ndigits != 0 && r.sign != var1->sign)
8133  {
8134  /* The absolute value of the quotient is too large */
8135  if (var1->sign == var2->sign)
8136  {
8137  sub_var(&q, &const_one, &q);
8138  add_var(&r, var2, &r);
8139  }
8140  else
8141  {
8142  add_var(&q, &const_one, &q);
8143  sub_var(&r, var2, &r);
8144  }
8145  }
8146 
8147  while (cmp_abs(&r, var2) >= 0)
8148  {
8149  /* The absolute value of the quotient is too small */
8150  if (var1->sign == var2->sign)
8151  {
8152  add_var(&q, &const_one, &q);
8153  sub_var(&r, var2, &r);
8154  }
8155  else
8156  {
8157  sub_var(&q, &const_one, &q);
8158  add_var(&r, var2, &r);
8159  }
8160  }
8161 
8162  set_var_from_var(&q, quot);
8163  set_var_from_var(&r, rem);
8164 
8165  free_var(&q);
8166  free_var(&r);
8167 }
static const NumericVar const_one
Definition: numeric.c:378
int ndigits
Definition: numeric.c:274
int dscale
Definition: numeric.c:277
int sign
Definition: numeric.c:276
static void div_var_fast(const NumericVar *var1, const NumericVar *var2, NumericVar *result, int rscale, bool round)
Definition: numeric.c:7703
static void free_var(NumericVar *var)
Definition: numeric.c:5921
static void mul_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result, int rscale)
Definition: numeric.c:7221
static void add_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition: numeric.c:6983
static int cmp_abs(const NumericVar *var1, const NumericVar *var2)
Definition: numeric.c:9463
static void sub_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition: numeric.c:7100
static void set_var_from_var(const NumericVar *value, NumericVar *dest)
Definition: numeric.c:6171
#define init_var(v)
Definition: numeric.c:444

◆ div_var()

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

Definition at line 7418 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().

7420 {
7421  int div_ndigits;
7422  int res_ndigits;
7423  int res_sign;
7424  int res_weight;
7425  int carry;
7426  int borrow;
7427  int divisor1;
7428  int divisor2;
7429  NumericDigit *dividend;
7430  NumericDigit *divisor;
7431  NumericDigit *res_digits;
7432  int i;
7433  int j;
7434 
7435  /* copy these values into local vars for speed in inner loop */
7436  int var1ndigits = var1->ndigits;
7437  int var2ndigits = var2->ndigits;
7438 
7439  /*
7440  * First of all division by zero check; we must not be handed an
7441  * unnormalized divisor.
7442  */
7443  if (var2ndigits == 0 || var2->digits[0] == 0)
7444  ereport(ERROR,
7445  (errcode(ERRCODE_DIVISION_BY_ZERO),
7446  errmsg("division by zero")));
7447 
7448  /*
7449  * Now result zero check
7450  */
7451  if (var1ndigits == 0)
7452  {
7453  zero_var(result);
7454  result->dscale = rscale;
7455  return;
7456  }
7457 
7458  /*
7459  * Determine the result sign, weight and number of digits to calculate.
7460  * The weight figured here is correct if the emitted quotient has no
7461  * leading zero digits; otherwise strip_var() will fix things up.
7462  */
7463  if (var1->sign == var2->sign)
7464  res_sign = NUMERIC_POS;
7465  else
7466  res_sign = NUMERIC_NEG;
7467  res_weight = var1->weight - var2->weight;
7468  /* The number of accurate result digits we need to produce: */
7469  res_ndigits = res_weight + 1 + (rscale + DEC_DIGITS - 1) / DEC_DIGITS;
7470  /* ... but always at least 1 */
7471  res_ndigits = Max(res_ndigits, 1);
7472  /* If rounding needed, figure one more digit to ensure correct result */
7473  if (round)
7474  res_ndigits++;
7475 
7476  /*
7477  * The working dividend normally requires res_ndigits + var2ndigits
7478  * digits, but make it at least var1ndigits so we can load all of var1
7479  * into it. (There will be an additional digit dividend[0] in the
7480  * dividend space, but for consistency with Knuth's notation we don't
7481  * count that in div_ndigits.)
7482  */
7483  div_ndigits = res_ndigits + var2ndigits;
7484  div_ndigits = Max(div_ndigits, var1ndigits);
7485 
7486  /*
7487  * We need a workspace with room for the working dividend (div_ndigits+1
7488  * digits) plus room for the possibly-normalized divisor (var2ndigits
7489  * digits). It is convenient also to have a zero at divisor[0] with the
7490  * actual divisor data in divisor[1 .. var2ndigits]. Transferring the
7491  * digits into the workspace also allows us to realloc the result (which
7492  * might be the same as either input var) before we begin the main loop.
7493  * Note that we use palloc0 to ensure that divisor[0], dividend[0], and
7494  * any additional dividend positions beyond var1ndigits, start out 0.
7495  */
7496  dividend = (NumericDigit *)
7497  palloc0((div_ndigits + var2ndigits + 2) * sizeof(NumericDigit));
7498  divisor = dividend + (div_ndigits + 1);
7499  memcpy(dividend + 1, var1->digits, var1ndigits * sizeof(NumericDigit));
7500  memcpy(divisor + 1, var2->digits, var2ndigits * sizeof(NumericDigit));
7501 
7502  /*
7503  * Now we can realloc the result to hold the generated quotient digits.
7504  */
7505  alloc_var(result, res_ndigits);
7506  res_digits = result->digits;
7507 
7508  if (var2ndigits == 1)
7509  {
7510  /*
7511  * If there's only a single divisor digit, we can use a fast path (cf.
7512  * Knuth section 4.3.1 exercise 16).
7513  */
7514  divisor1 = divisor[1];
7515  carry = 0;
7516  for (i = 0; i < res_ndigits; i++)
7517  {
7518  carry = carry * NBASE + dividend[i + 1];
7519  res_digits[i] = carry / divisor1;
7520  carry = carry % divisor1;
7521  }
7522  }
7523  else
7524  {
7525  /*
7526  * The full multiple-place algorithm is taken from Knuth volume 2,
7527  * Algorithm 4.3.1D.
7528  *
7529  * We need the first divisor digit to be >= NBASE/2. If it isn't,
7530  * make it so by scaling up both the divisor and dividend by the
7531  * factor "d". (The reason for allocating dividend[0] above is to
7532  * leave room for possible carry here.)
7533  */
7534  if (divisor[1] < HALF_NBASE)
7535  {
7536  int d = NBASE / (divisor[1] + 1);
7537 
7538  carry = 0;
7539  for (i = var2ndigits; i > 0; i--)
7540  {
7541  carry += divisor[i] * d;
7542  divisor[i] = carry % NBASE;
7543  carry = carry / NBASE;
7544  }
7545  Assert(carry == 0);
7546  carry = 0;
7547  /* at this point only var1ndigits of dividend can be nonzero */
7548  for (i = var1ndigits; i >= 0; i--)
7549  {
7550  carry += dividend[i] * d;
7551  dividend[i] = carry % NBASE;
7552  carry = carry / NBASE;
7553  }
7554  Assert(carry == 0);
7555  Assert(divisor[1] >= HALF_NBASE);
7556  }
7557  /* First 2 divisor digits are used repeatedly in main loop */
7558  divisor1 = divisor[1];
7559  divisor2 = divisor[2];
7560 
7561  /*
7562  * Begin the main loop. Each iteration of this loop produces the j'th
7563  * quotient digit by dividing dividend[j .. j + var2ndigits] by the
7564  * divisor; this is essentially the same as the common manual
7565  * procedure for long division.
7566  */
7567  for (j = 0; j < res_ndigits; j++)
7568  {
7569  /* Estimate quotient digit from the first two dividend digits */
7570  int next2digits = dividend[j] * NBASE + dividend[j + 1];
7571  int qhat;
7572 
7573  /*
7574  * If next2digits are 0, then quotient digit must be 0 and there's
7575  * no need to adjust the working dividend. It's worth testing
7576  * here to fall out ASAP when processing trailing zeroes in a
7577  * dividend.
7578  */
7579  if (next2digits == 0)
7580  {
7581  res_digits[j] = 0;
7582  continue;
7583  }
7584 
7585  if (dividend[j] == divisor1)
7586  qhat = NBASE - 1;
7587  else
7588  qhat = next2digits / divisor1;
7589 
7590  /*
7591  * Adjust quotient digit if it's too large. Knuth proves that
7592  * after this step, the quotient digit will be either correct or
7593  * just one too large. (Note: it's OK to use dividend[j+2] here
7594  * because we know the divisor length is at least 2.)
7595  */
7596  while (divisor2 * qhat >
7597  (next2digits - qhat * divisor1) * NBASE + dividend[j + 2])
7598  qhat--;
7599 
7600  /* As above, need do nothing more when quotient digit is 0 */
7601  if (qhat > 0)
7602  {
7603  /*
7604  * Multiply the divisor by qhat, and subtract that from the
7605  * working dividend. "carry" tracks the multiplication,
7606  * "borrow" the subtraction (could we fold these together?)
7607  */
7608  carry = 0;
7609  borrow = 0;
7610  for (i = var2ndigits; i >= 0; i--)
7611  {
7612  carry += divisor[i] * qhat;
7613  borrow -= carry % NBASE;
7614  carry = carry / NBASE;
7615  borrow += dividend[j + i];
7616  if (borrow < 0)
7617  {
7618  dividend[j + i] = borrow + NBASE;
7619  borrow = -1;
7620  }
7621  else
7622  {
7623  dividend[j + i] = borrow;
7624  borrow = 0;
7625  }
7626  }
7627  Assert(carry == 0);
7628 
7629  /*
7630  * If we got a borrow out of the top dividend digit, then
7631  * indeed qhat was one too large. Fix it, and add back the
7632  * divisor to correct the working dividend. (Knuth proves
7633  * that this will occur only about 3/NBASE of the time; hence,
7634  * it's a good idea to test this code with small NBASE to be
7635  * sure this section gets exercised.)
7636  */
7637  if (borrow)
7638  {
7639  qhat--;
7640  carry = 0;
7641  for (i = var2ndigits; i >= 0; i--)
7642  {
7643  carry += dividend[j + i] + divisor[i];
7644  if (carry >= NBASE)
7645  {
7646  dividend[j + i] = carry - NBASE;
7647  carry = 1;
7648  }
7649  else
7650  {
7651  dividend[j + i] = carry;
7652  carry = 0;
7653  }
7654  }
7655  /* A carry should occur here to cancel the borrow above */
7656  Assert(carry == 1);
7657  }
7658  }
7659 
7660  /* And we're done with this quotient digit */
7661  res_digits[j] = qhat;
7662  }
7663  }
7664 
7665  pfree(dividend);
7666 
7667  /*
7668  * Finally, round or truncate the result to the requested precision.
7669  */
7670  result->weight = res_weight;
7671  result->sign = res_sign;
7672 
7673  /* Round or truncate to target rscale (and set result->dscale) */
7674  if (round)
7675  round_var(result, rscale);
7676  else
7677  trunc_var(result, rscale);
7678 
7679  /* Strip leading and trailing zeroes */
7680  strip_var(result);
7681 }
static void round_var(NumericVar *var, int rscale)
Definition: numeric.c:9708
static void trunc_var(NumericVar *var, int rscale)
Definition: numeric.c:9814
int weight
Definition: numeric.c:275
#define NUMERIC_POS
Definition: numeric.c:167
static void strip_var(NumericVar *var)
Definition: numeric.c:9876
int errcode(int sqlerrcode)
Definition: elog.c:610
int ndigits
Definition: numeric.c:274
int dscale
Definition: numeric.c:277
#define NUMERIC_NEG
Definition: numeric.c:168
int sign
Definition: numeric.c:276
static void zero_var(NumericVar *var)
Definition: numeric.c:5937
void pfree(void *pointer)
Definition: mcxt.c:1056
#define ERROR
Definition: elog.h:43
int16 NumericDigit
Definition: numeric.c:102
#define HALF_NBASE
Definition: numeric.c:97
#define NBASE
Definition: numeric.c:96
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:279
int errmsg(const char *fmt,...)
Definition: elog.c:824
static void alloc_var(NumericVar *var, int ndigits)
Definition: numeric.c:5905
int i
#define Max(x, y)
Definition: numeric.c:13
#define DEC_DIGITS
Definition: numeric.c:98

◆ div_var_fast()

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

Definition at line 7703 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().

7705 {
7706  int div_ndigits;
7707  int load_ndigits;
7708  int res_sign;
7709  int res_weight;
7710  int *div;
7711  int qdigit;
7712  int carry;
7713  int maxdiv;
7714  int newdig;
7715  NumericDigit *res_digits;
7716  double fdividend,
7717  fdivisor,
7718  fdivisorinverse,
7719  fquotient;
7720  int qi;
7721  int i;
7722 
7723  /* copy these values into local vars for speed in inner loop */
7724  int var1ndigits = var1->ndigits;
7725  int var2ndigits = var2->ndigits;
7726  NumericDigit *var1digits = var1->digits;
7727  NumericDigit *var2digits = var2->digits;
7728 
7729  /*
7730  * First of all division by zero check; we must not be handed an
7731  * unnormalized divisor.
7732  */
7733  if (var2ndigits == 0 || var2digits[0] == 0)
7734  ereport(ERROR,
7735  (errcode(ERRCODE_DIVISION_BY_ZERO),
7736  errmsg("division by zero")));
7737 
7738  /*
7739  * Now result zero check
7740  */
7741  if (var1ndigits == 0)
7742  {
7743  zero_var(result);
7744  result->dscale = rscale;
7745  return;
7746  }
7747 
7748  /*
7749  * Determine the result sign, weight and number of digits to calculate
7750  */
7751  if (var1->sign == var2->sign)
7752  res_sign = NUMERIC_POS;
7753  else
7754  res_sign = NUMERIC_NEG;
7755  res_weight = var1->weight - var2->weight + 1;
7756  /* The number of accurate result digits we need to produce: */
7757  div_ndigits = res_weight + 1 + (rscale + DEC_DIGITS - 1) / DEC_DIGITS;
7758  /* Add guard digits for roundoff error */
7759  div_ndigits += DIV_GUARD_DIGITS;
7760  if (div_ndigits < DIV_GUARD_DIGITS)
7761  div_ndigits = DIV_GUARD_DIGITS;
7762 
7763  /*
7764  * We do the arithmetic in an array "div[]" of signed int's. Since
7765  * INT_MAX is noticeably larger than NBASE*NBASE, this gives us headroom
7766  * to avoid normalizing carries immediately.
7767  *
7768  * We start with div[] containing one zero digit followed by the
7769  * dividend's digits (plus appended zeroes to reach the desired precision
7770  * including guard digits). Each step of the main loop computes an
7771  * (approximate) quotient digit and stores it into div[], removing one
7772  * position of dividend space. A final pass of carry propagation takes
7773  * care of any mistaken quotient digits.
7774  *
7775  * Note that div[] doesn't necessarily contain all of the digits from the
7776  * dividend --- the desired precision plus guard digits might be less than
7777  * the dividend's precision. This happens, for example, in the square
7778  * root algorithm, where we typically divide a 2N-digit number by an
7779  * N-digit number, and only require a result with N digits of precision.
7780  */
7781  div = (int *) palloc0((div_ndigits + 1) * sizeof(int));
7782  load_ndigits = Min(div_ndigits, var1ndigits);
7783  for (i = 0; i < load_ndigits; i++)
7784  div[i + 1] = var1digits[i];
7785 
7786  /*
7787  * We estimate each quotient digit using floating-point arithmetic, taking
7788  * the first four digits of the (current) dividend and divisor. This must
7789  * be float to avoid overflow. The quotient digits will generally be off
7790  * by no more than one from the exact answer.
7791  */
7792  fdivisor = (double) var2digits[0];
7793  for (i = 1; i < 4; i++)
7794  {
7795  fdivisor *= NBASE;
7796  if (i < var2ndigits)
7797  fdivisor += (double) var2digits[i];
7798  }
7799  fdivisorinverse = 1.0 / fdivisor;
7800 
7801  /*
7802  * maxdiv tracks the maximum possible absolute value of any div[] entry;
7803  * when this threatens to exceed INT_MAX, we take the time to propagate
7804  * carries. Furthermore, we need to ensure that overflow doesn't occur
7805  * during the carry propagation passes either. The carry values may have
7806  * an absolute value as high as INT_MAX/NBASE + 1, so really we must
7807  * normalize when digits threaten to exceed INT_MAX - INT_MAX/NBASE - 1.
7808  *
7809  * To avoid overflow in maxdiv itself, it represents the max absolute
7810  * value divided by NBASE-1, ie, at the top of the loop it is known that
7811  * no div[] entry has an absolute value exceeding maxdiv * (NBASE-1).
7812  *
7813  * Actually, though, that holds good only for div[] entries after div[qi];
7814  * the adjustment done at the bottom of the loop may cause div[qi + 1] to
7815  * exceed the maxdiv limit, so that div[qi] in the next iteration is
7816  * beyond the limit. This does not cause problems, as explained below.
7817  */
7818  maxdiv = 1;
7819 
7820  /*
7821  * Outer loop computes next quotient digit, which will go into div[qi]
7822  */
7823  for (qi = 0; qi < div_ndigits; qi++)
7824  {
7825  /* Approximate the current dividend value */
7826  fdividend = (double) div[qi];
7827  for (i = 1; i < 4; i++)
7828  {
7829  fdividend *= NBASE;
7830  if (qi + i <= div_ndigits)
7831  fdividend += (double) div[qi + i];
7832  }
7833  /* Compute the (approximate) quotient digit */
7834  fquotient = fdividend * fdivisorinverse;
7835  qdigit = (fquotient >= 0.0) ? ((int) fquotient) :
7836  (((int) fquotient) - 1); /* truncate towards -infinity */
7837 
7838  if (qdigit != 0)
7839  {
7840  /* Do we need to normalize now? */
7841  maxdiv += Abs(qdigit);
7842  if (maxdiv > (INT_MAX - INT_MAX / NBASE - 1) / (NBASE - 1))
7843  {
7844  /*
7845  * Yes, do it. Note that if var2ndigits is much smaller than
7846  * div_ndigits, we can save a significant amount of effort
7847  * here by noting that we only need to normalise those div[]
7848  * entries touched where prior iterations subtracted multiples
7849  * of the divisor.
7850  */
7851  carry = 0;
7852  for (i = Min(qi + var2ndigits - 2, div_ndigits); i > qi; i--)
7853  {
7854  newdig = div[i] + carry;
7855  if (newdig < 0)
7856  {
7857  carry = -((-newdig - 1) / NBASE) - 1;
7858  newdig -= carry * NBASE;
7859  }
7860  else if (newdig >= NBASE)
7861  {
7862  carry = newdig / NBASE;
7863  newdig -= carry * NBASE;
7864  }
7865  else
7866  carry = 0;
7867  div[i] = newdig;
7868  }
7869  newdig = div[qi] + carry;
7870  div[qi] = newdig;
7871 
7872  /*
7873  * All the div[] digits except possibly div[qi] are now in the
7874  * range 0..NBASE-1. We do not need to consider div[qi] in
7875  * the maxdiv value anymore, so we can reset maxdiv to 1.
7876  */
7877  maxdiv = 1;
7878 
7879  /*
7880  * Recompute the quotient digit since new info may have
7881  * propagated into the top four dividend digits
7882  */
7883  fdividend = (double) div[qi];
7884  for (i = 1; i < 4; i++)
7885  {
7886  fdividend *= NBASE;
7887  if (qi + i <= div_ndigits)
7888  fdividend += (double) div[qi + i];
7889  }
7890  /* Compute the (approximate) quotient digit */
7891  fquotient = fdividend * fdivisorinverse;
7892  qdigit = (fquotient >= 0.0) ? ((int) fquotient) :
7893  (((int) fquotient) - 1); /* truncate towards -infinity */
7894  maxdiv += Abs(qdigit);
7895  }
7896 
7897  /*
7898  * Subtract off the appropriate multiple of the divisor.
7899  *
7900  * The digits beyond div[qi] cannot overflow, because we know they
7901  * will fall within the maxdiv limit. As for div[qi] itself, note
7902  * that qdigit is approximately trunc(div[qi] / vardigits[0]),
7903  * which would make the new value simply div[qi] mod vardigits[0].
7904  * The lower-order terms in qdigit can change this result by not
7905  * more than about twice INT_MAX/NBASE, so overflow is impossible.
7906  */
7907  if (qdigit != 0)
7908  {
7909  int istop = Min(var2ndigits, div_ndigits - qi + 1);
7910 
7911  for (i = 0; i < istop; i++)
7912  div[qi + i] -= qdigit * var2digits[i];
7913  }
7914  }
7915 
7916  /*
7917  * The dividend digit we are about to replace might still be nonzero.
7918  * Fold it into the next digit position.
7919  *
7920  * There is no risk of overflow here, although proving that requires
7921  * some care. Much as with the argument for div[qi] not overflowing,
7922  * if we consider the first two terms in the numerator and denominator
7923  * of qdigit, we can see that the final value of div[qi + 1] will be
7924  * approximately a remainder mod (vardigits[0]*NBASE + vardigits[1]).
7925  * Accounting for the lower-order terms is a bit complicated but ends
7926  * up adding not much more than INT_MAX/NBASE to the possible range.
7927  * Thus, div[qi + 1] cannot overflow here, and in its role as div[qi]
7928  * in the next loop iteration, it can't be large enough to cause
7929  * overflow in the carry propagation step (if any), either.
7930  *
7931  * But having said that: div[qi] can be more than INT_MAX/NBASE, as
7932  * noted above, which means that the product div[qi] * NBASE *can*
7933  * overflow. When that happens, adding it to div[qi + 1] will always
7934  * cause a canceling overflow so that the end result is correct. We
7935  * could avoid the intermediate overflow by doing the multiplication
7936  * and addition in int64 arithmetic, but so far there appears no need.
7937  */
7938  div[qi + 1] += div[qi] * NBASE;
7939 
7940  div[qi] = qdigit;
7941  }
7942 
7943  /*
7944  * Approximate and store the last quotient digit (div[div_ndigits])
7945  */
7946  fdividend = (double) div[qi];
7947  for (i = 1; i < 4; i++)
7948  fdividend *= NBASE;
7949  fquotient = fdividend * fdivisorinverse;
7950  qdigit = (fquotient >= 0.0) ? ((int) fquotient) :
7951  (((int) fquotient) - 1); /* truncate towards -infinity */
7952  div[qi] = qdigit;
7953 
7954  /*
7955  * Because the quotient digits might be off by one, some of them might be
7956  * -1 or NBASE at this point. The represented value is correct in a
7957  * mathematical sense, but it doesn't look right. We do a final carry
7958  * propagation pass to normalize the digits, which we combine with storing
7959  * the result digits into the output. Note that this is still done at
7960  * full precision w/guard digits.
7961  */
7962  alloc_var(result, div_ndigits + 1);
7963  res_digits = result->digits;
7964  carry = 0;
7965  for (i = div_ndigits; i >= 0; i--)
7966  {
7967  newdig = div[i] + carry;
7968  if (newdig < 0)
7969  {
7970  carry = -((-newdig - 1) / NBASE) - 1;
7971  newdig -= carry * NBASE;
7972  }
7973  else if (newdig >= NBASE)
7974  {
7975  carry = newdig / NBASE;
7976  newdig -= carry * NBASE;
7977  }
7978  else
7979  carry = 0;
7980  res_digits[i] = newdig;
7981  }
7982  Assert(carry == 0);
7983 
7984  pfree(div);
7985 
7986  /*
7987  * Finally, round the result to the requested precision.
7988  */
7989  result->weight = res_weight;
7990  result->sign = res_sign;
7991 
7992  /* Round to target rscale (and set result->dscale) */
7993  if (round)
7994  round_var(result, rscale);
7995  else
7996  trunc_var(result, rscale);
7997 
7998  /* Strip leading and trailing zeroes */
7999  strip_var(result);
8000 }
static void round_var(NumericVar *var, int rscale)
Definition: numeric.c:9708
static void trunc_var(NumericVar *var, int rscale)
Definition: numeric.c:9814
int weight
Definition: numeric.c:275
#define NUMERIC_POS
Definition: numeric.c:167
static void strip_var(NumericVar *var)
Definition: numeric.c:9876
int errcode(int sqlerrcode)
Definition: elog.c:610
int ndigits
Definition: numeric.c:274
int dscale
Definition: numeric.c:277
#define Min(x, y)
Definition: numeric.c:14
#define Abs(x)
Definition: c.h:926
#define NUMERIC_NEG
Definition: numeric.c:168
int sign
Definition: numeric.c:276
static void zero_var(NumericVar *var)
Definition: numeric.c:5937
void pfree(void *pointer)
Definition: mcxt.c:1056
#define ERROR
Definition: elog.h:43
int16 NumericDigit
Definition: numeric.c:102
#define NBASE
Definition: numeric.c:96
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:279
#define DIV_GUARD_DIGITS
Definition: numeric.c:100
int errmsg(const char *fmt,...)
Definition: elog.c:824
static void alloc_var(NumericVar *var, int ndigits)
Definition: numeric.c:5905
int i
#define DEC_DIGITS
Definition: numeric.c:98

◆ do_numeric_accum()

static void do_numeric_accum ( NumericAggState state,
Numeric  newval 
)
static

Definition at line 3762 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().

3763 {
3764  NumericVar X;
3765  NumericVar X2;
3766  MemoryContext old_context;
3767 
3768  /* Count NaN inputs separately from all else */
3769  if (NUMERIC_IS_NAN(newval))
3770  {
3771  state->NaNcount++;
3772  return;
3773  }
3774 
3775  /* load processed number in short-lived context */
3776  init_var_from_num(newval, &X);
3777 
3778  /*
3779  * Track the highest input dscale that we've seen, to support inverse
3780  * transitions (see do_numeric_discard).
3781  */
3782  if (X.dscale > state->maxScale)
3783  {
3784  state->maxScale = X.dscale;
3785  state->maxScaleCount = 1;
3786  }
3787  else if (X.dscale == state->maxScale)
3788  state->maxScaleCount++;
3789 
3790  /* if we need X^2, calculate that in short-lived context */
3791  if (state->calcSumX2)
3792  {
3793  init_var(&X2);
3794  mul_var(&X, &X, &X2, X.dscale * 2);
3795  }
3796 
3797  /* The rest of this needs to work in the aggregate context */
3798  old_context = MemoryContextSwitchTo(state->agg_context);
3799 
3800  state->N++;
3801 
3802  /* Accumulate sums */
3803  accum_sum_add(&(state->sumX), &X);
3804 
3805  if (state->calcSumX2)
3806  accum_sum_add(&(state->sumX2), &X2);
3807 
3808  MemoryContextSwitchTo(old_context);
3809 }
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
MemoryContext agg_context
Definition: numeric.c:3708
int dscale
Definition: numeric.c:277
static void accum_sum_add(NumericSumAccum *accum, const NumericVar *var1)
Definition: numeric.c:9933
static void init_var_from_num(Numeric num, NumericVar *dest)
Definition: numeric.c:6154
static void mul_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result, int rscale)
Definition: numeric.c:7221
NumericSumAccum sumX2
Definition: numeric.c:3711
int64 NaNcount
Definition: numeric.c:3714
int64 maxScaleCount
Definition: numeric.c:3713
#define NUMERIC_IS_NAN(n)
Definition: numeric.c:173
NumericSumAccum sumX
Definition: numeric.c:3710
#define init_var(v)
Definition: numeric.c:444

◆ do_numeric_discard()

static bool do_numeric_discard ( NumericAggState state,
Numeric  newval 
)
static

Definition at line 3827 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().

3828 {
3829  NumericVar X;
3830  NumericVar X2;
3831  MemoryContext old_context;
3832 
3833  /* Count NaN inputs separately from all else */
3834  if (NUMERIC_IS_NAN(newval))
3835  {
3836  state->NaNcount--;
3837  return true;
3838  }
3839 
3840  /* load processed number in short-lived context */
3841  init_var_from_num(newval, &X);
3842 
3843  /*
3844  * state->sumX's dscale is the maximum dscale of any of the inputs.
3845  * Removing the last input with that dscale would require us to recompute
3846  * the maximum dscale of the *remaining* inputs, which we cannot do unless
3847  * no more non-NaN inputs remain at all. So we report a failure instead,
3848  * and force the aggregation to be redone from scratch.
3849  */
3850  if (X.dscale == state->maxScale)
3851  {
3852  if (state->maxScaleCount > 1 || state->maxScale == 0)
3853  {
3854  /*
3855  * Some remaining inputs have same dscale, or dscale hasn't gotten
3856  * above zero anyway
3857  */
3858  state->maxScaleCount--;
3859  }
3860  else if (state->N == 1)
3861  {
3862  /* No remaining non-NaN inputs at all, so reset maxScale */
3863  state->maxScale = 0;
3864  state->maxScaleCount = 0;
3865  }
3866  else
3867  {
3868  /* Correct new maxScale is uncertain, must fail */
3869  return false;
3870  }
3871  }
3872 
3873  /* if we need X^2, calculate that in short-lived context */
3874  if (state->calcSumX2)
3875  {
3876  init_var(&X2);
3877  mul_var(&X, &X, &X2, X.dscale * 2);
3878  }
3879 
3880  /* The rest of this needs to work in the aggregate context */
3881  old_context = MemoryContextSwitchTo(state->agg_context);
3882 
3883  if (state->N-- > 1)
3884  {
3885  /* Negate X, to subtract it from the sum */
3886  X.sign = (X.sign == NUMERIC_POS ? NUMERIC_NEG : NUMERIC_POS);
3887  accum_sum_add(&(state->sumX), &X);
3888 
3889  if (state->calcSumX2)
3890  {
3891  /* Negate X^2. X^2 is always positive */
3892  X2.sign = NUMERIC_NEG;
3893  accum_sum_add(&(state->sumX2), &X2);
3894  }
3895  }
3896  else
3897  {
3898  /* Zero the sums */
3899  Assert(state->N == 0);
3900 
3901  accum_sum_reset(&state->sumX);
3902  if (state->calcSumX2)
3903  accum_sum_reset(&state->sumX2);
3904  }
3905 
3906  MemoryContextSwitchTo(old_context);
3907 
3908  return true;
3909 }
#define NUMERIC_POS
Definition: numeric.c:167
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
MemoryContext agg_context
Definition: numeric.c:3708
int dscale
Definition: numeric.c:277
#define NUMERIC_NEG
Definition: numeric.c:168
static void accum_sum_add(NumericSumAccum *accum, const NumericVar *var1)
Definition: numeric.c:9933
int sign
Definition: numeric.c:276
static void init_var_from_num(Numeric num, NumericVar *dest)
Definition: numeric.c:6154
#define Assert(condition)
Definition: c.h:738
static void mul_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result, int rscale)
Definition: numeric.c:7221
NumericSumAccum sumX2
Definition: numeric.c:3711
static void accum_sum_reset(NumericSumAccum *accum)
Definition: numeric.c:9917
int64 NaNcount
Definition: numeric.c:3714
int64 maxScaleCount
Definition: numeric.c:3713
#define NUMERIC_IS_NAN(n)
Definition: numeric.c:173
NumericSumAccum sumX
Definition: numeric.c:3710
#define init_var(v)
Definition: numeric.c:444

◆ estimate_ln_dweight()

static int estimate_ln_dweight ( const NumericVar var)
static

Definition at line 8900 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().

8901 {
8902  int ln_dweight;
8903 
8904  if (cmp_var(var, &const_zero_point_nine) >= 0 &&
8905  cmp_var(var, &const_one_point_one) <= 0)
8906  {
8907  /*
8908  * 0.9 <= var <= 1.1
8909  *
8910  * ln(var) has a negative weight (possibly very large). To get a
8911  * reasonably accurate result, estimate it using ln(1+x) ~= x.
8912  */
8913  NumericVar x;
8914 
8915  init_var(&x);
8916  sub_var(var, &const_one, &x);
8917 
8918  if (x.ndigits > 0)
8919  {
8920  /* Use weight of most significant decimal digit of x */
8921  ln_dweight = x.weight * DEC_DIGITS + (int) log10(x.digits[0]);
8922  }
8923  else
8924  {
8925  /* x = 0. Since ln(1) = 0 exactly, we don't need extra digits */
8926  ln_dweight = 0;
8927  }
8928 
8929  free_var(&x);
8930  }
8931  else
8932  {
8933  /*
8934  * Estimate the logarithm using the first couple of digits from the
8935  * input number. This will give an accurate result whenever the input
8936  * is not too close to 1.
8937  */
8938  if (var->ndigits > 0)
8939  {
8940  int digits;
8941  int dweight;
8942  double ln_var;
8943 
8944  digits = var->digits[0];
8945  dweight = var->weight * DEC_DIGITS;
8946 
8947  if (var->ndigits > 1)
8948  {
8949  digits = digits * NBASE + var->digits[1];
8950  dweight -= DEC_DIGITS;
8951  }
8952 
8953  /*----------
8954  * We have var ~= digits * 10^dweight
8955  * so ln(var) ~= ln(digits) + dweight * ln(10)
8956  *----------
8957  */
8958  ln_var = log((double) digits) + dweight * 2.302585092994046;
8959  ln_dweight = (int) log10(Abs(ln_var));
8960  }
8961  else
8962  {
8963  /* Caller should fail on ln(0), but for the moment return zero */
8964  ln_dweight = 0;
8965  }
8966  }
8967 
8968  return ln_dweight;
8969 }
int weight
Definition: numeric.c:275
static const NumericVar const_zero_point_nine
Definition: numeric.c:402
static const NumericVar const_one
Definition: numeric.c:378
static void ln_var(const NumericVar *arg, NumericVar *result, int rscale)
Definition: numeric.c:8978
int ndigits
Definition: numeric.c:274
#define Abs(x)
Definition: c.h:926
#define NBASE
Definition: numeric.c:96
static int cmp_var(const NumericVar *var1, const NumericVar *var2)
Definition: numeric.c:6925
static void free_var(NumericVar *var)
Definition: numeric.c:5921
NumericDigit * digits
Definition: numeric.c:279
static void sub_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition: numeric.c:7100
#define DEC_DIGITS
Definition: numeric.c:98
static const NumericVar const_one_point_one
Definition: numeric.c:412
#define init_var(v)
Definition: numeric.c:444
int digits
Definition: informix.c:666

◆ exp_var()

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

Definition at line 8774 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().

8775 {
8776  NumericVar x;
8777  NumericVar elem;
8778  NumericVar ni;
8779  double val;
8780  int dweight;
8781  int ndiv2;
8782  int sig_digits;
8783  int local_rscale;
8784 
8785  init_var(&x);
8786  init_var(&elem);
8787  init_var(&ni);
8788 
8789  set_var_from_var(arg, &x);
8790 
8791  /*
8792  * Estimate the dweight of the result using floating point arithmetic, so
8793  * that we can choose an appropriate local rscale for the calculation.
8794  */
8796 
8797  /* Guard against overflow */
8798  /* If you change this limit, see also power_var()'s limit */
8799  if (Abs(val) >= NUMERIC_MAX_RESULT_SCALE * 3)
8800  ereport(ERROR,
8801  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
8802  errmsg("value overflows numeric format")));
8803 
8804  /* decimal weight = log10(e^x) = x * log10(e) */
8805  dweight = (int) (val * 0.434294481903252);
8806 
8807  /*
8808  * Reduce x to the range -0.01 <= x <= 0.01 (approximately) by dividing by
8809  * 2^n, to improve the convergence rate of the Taylor series.
8810  */
8811  if (Abs(val) > 0.01)
8812  {
8813  NumericVar tmp;
8814 
8815  init_var(&tmp);
8816  set_var_from_var(&const_two, &tmp);
8817 
8818  ndiv2 = 1;
8819  val /= 2;
8820 
8821  while (Abs(val) > 0.01)
8822  {
8823  ndiv2++;
8824  val /= 2;
8825  add_var(&tmp, &tmp, &tmp);
8826  }
8827 
8828  local_rscale = x.dscale + ndiv2;
8829  div_var_fast(&x, &tmp, &x, local_rscale, true);
8830 
8831  free_var(&tmp);
8832  }
8833  else
8834  ndiv2 = 0;
8835 
8836  /*
8837  * Set the scale for the Taylor series expansion. The final result has
8838  * (dweight + rscale + 1) significant digits. In addition, we have to
8839  * raise the Taylor series result to the power 2^ndiv2, which introduces
8840  * an error of up to around log10(2^ndiv2) digits, so work with this many
8841  * extra digits of precision (plus a few more for good measure).
8842  */
8843  sig_digits = 1 + dweight + rscale + (int) (ndiv2 * 0.301029995663981);
8844  sig_digits = Max(sig_digits, 0) + 8;
8845 
8846  local_rscale = sig_digits - 1;
8847 
8848  /*
8849  * Use the Taylor series
8850  *
8851  * exp(x) = 1 + x + x^2/2! + x^3/3! + ...
8852  *
8853  * Given the limited range of x, this should converge reasonably quickly.
8854  * We run the series until the terms fall below the local_rscale limit.
8855  */
8856  add_var(&const_one, &x, result);
8857 
8858  mul_var(&x, &x, &elem, local_rscale);
8859  set_var_from_var(&const_two, &ni);
8860  div_var_fast(&elem, &ni, &elem, local_rscale, true);
8861 
8862  while (elem.ndigits != 0)
8863  {
8864  add_var(result, &elem, result);
8865 
8866  mul_var(&elem, &x, &elem, local_rscale);
8867  add_var(&ni, &const_one, &ni);
8868  div_var_fast(&elem, &ni, &elem, local_rscale, true);
8869  }
8870 
8871  /*
8872  * Compensate for the argument range reduction. Since the weight of the
8873  * result doubles with each multiplication, we can reduce the local rscale
8874  * as we proceed.
8875  */
8876  while (ndiv2-- > 0)
8877  {
8878  local_rscale = sig_digits - result->weight * 2 * DEC_DIGITS;
8879  local_rscale = Max(local_rscale, NUMERIC_MIN_DISPLAY_SCALE);
8880  mul_var(result, result, result, local_rscale);
8881  }
8882 
8883  /* Round to requested rscale */
8884  round_var(result, rscale);
8885 
8886  free_var(&x);
8887  free_var(&elem);
8888  free_var(&ni);
8889 }
static void round_var(NumericVar *var, int rscale)
Definition: numeric.c:9708
int weight
Definition: numeric.c:275
static const NumericVar const_one
Definition: numeric.c:378
int errcode(int sqlerrcode)
Definition: elog.c:610
int ndigits
Definition: numeric.c:274
int dscale
Definition: numeric.c:277
#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:6893
#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:7703
static void free_var(NumericVar *var)
Definition: numeric.c:5921
#define ereport(elevel,...)
Definition: elog.h:144
static const NumericVar const_two
Definition: numeric.c:382
static void mul_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result, int rscale)
Definition: numeric.c:7221
static void add_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition: numeric.c:6983
int errmsg(const char *fmt,...)
Definition: elog.c:824
#define Max(x, y)
Definition: numeric.c:13
#define DEC_DIGITS
Definition: numeric.c:98
static void set_var_from_var(const NumericVar *value, NumericVar *dest)
Definition: numeric.c:6171
long val
Definition: informix.c:664
#define init_var(v)
Definition: numeric.c:444

◆ float4_numeric()

Datum float4_numeric ( PG_FUNCTION_ARGS  )

Definition at line 3640 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.

3641 {
3643  Numeric res;
3644  NumericVar result;
3645  char buf[FLT_DIG + 100];
3646 
3647  if (isnan(val))
3649 
3650  if (isinf(val))
3651  ereport(ERROR,
3652  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3653  errmsg("cannot convert infinity to numeric")));
3654 
3655  snprintf(buf, sizeof(buf), "%.*g", FLT_DIG, val);
3656 
3657  init_var(&result);
3658 
3659  /* Assume we need not worry about leading/trailing spaces */
3660  (void) set_var_from_str(buf, buf, &result);
3661 
3662  res = make_result(&result);
3663 
3664  free_var(&result);
3665 
3666  PG_RETURN_NUMERIC(res);
3667 }
#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:275
float float4
Definition: c.h:490
static void free_var(NumericVar *var)
Definition: numeric.c:5921
#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:5961
static const NumericVar const_nan
Definition: numeric.c:415
static Numeric make_result(const NumericVar *var)
Definition: numeric.c:6537
int errmsg(const char *fmt,...)
Definition: elog.c:824
#define snprintf
Definition: port.h:192
long val
Definition: informix.c:664
#define init_var(v)
Definition: numeric.c:444

◆ float8_numeric()

Datum float8_numeric ( PG_FUNCTION_ARGS  )

Definition at line 3569 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().

3570 {
3572  Numeric res;
3573  NumericVar result;
3574  char buf[DBL_DIG + 100];
3575 
3576  if (isnan(val))
3578 
3579  if (isinf(val))
3580  ereport(ERROR,
3581  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3582  errmsg("cannot convert infinity to numeric")));
3583 
3584  snprintf(buf, sizeof(buf), "%.*g", DBL_DIG, val);
3585 
3586  init_var(&result);
3587 
3588  /* Assume we need not worry about leading/trailing spaces */
3589  (void) set_var_from_str(buf, buf, &result);
3590 
3591  res = make_result(&result);
3592 
3593  free_var(&result);
3594 
3595  PG_RETURN_NUMERIC(res);
3596 }
#define PG_RETURN_NUMERIC(x)
Definition: numeric.h:54
#define PG_GETARG_FLOAT8(n)
Definition: fmgr.h:276
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:5921
#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:5961
static const NumericVar const_nan
Definition: numeric.c:415
static Numeric make_result(const NumericVar *var)
Definition: numeric.c:6537
int errmsg(const char *fmt,...)
Definition: elog.c:824
#define snprintf
Definition: port.h:192
long val
Definition: informix.c:664
#define init_var(v)
Definition: numeric.c:444

◆ floor_var()

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

Definition at line 8201 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().

8202 {
8203  NumericVar tmp;
8204 
8205  init_var(&tmp);
8206  set_var_from_var(var, &tmp);
8207 
8208  trunc_var(&tmp, 0);
8209 
8210  if (var->sign == NUMERIC_NEG && cmp_var(var, &tmp) != 0)
8211  sub_var(&tmp, &const_one, &tmp);
8212 
8213  set_var_from_var(&tmp, result);
8214  free_var(&tmp);
8215 }
static void trunc_var(NumericVar *var, int rscale)
Definition: numeric.c:9814
static const NumericVar const_one
Definition: numeric.c:378
#define NUMERIC_NEG
Definition: numeric.c:168
int sign
Definition: numeric.c:276
static int cmp_var(const NumericVar *var1, const NumericVar *var2)
Definition: numeric.c:6925
static void free_var(NumericVar *var)
Definition: numeric.c:5921
static void sub_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition: numeric.c:7100
static void set_var_from_var(const NumericVar *value, NumericVar *dest)
Definition: numeric.c:6171
#define init_var(v)
Definition: numeric.c:444

◆ free_var()

static void free_var ( NumericVar var)
static

Definition at line 5921 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(), int64_to_numericvar(), 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(), power_var(), power_var_int(), sqrt_var(), and width_bucket_numeric().

5922 {
5923  digitbuf_free(var->buf);
5924  var->buf = NULL;
5925  var->digits = NULL;
5926  var->sign = NUMERIC_NAN;
5927 }
int sign
Definition: numeric.c:276
#define digitbuf_free(buf)
Definition: numeric.c:438
#define NUMERIC_NAN
Definition: numeric.c:170
NumericDigit * buf
Definition: numeric.c:278
NumericDigit * digits
Definition: numeric.c:279

◆ gcd_var()

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

Definition at line 8224 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().

8225 {
8226  int res_dscale;
8227  int cmp;
8228  NumericVar tmp_arg;
8229  NumericVar mod;
8230 
8231  res_dscale = Max(var1->dscale, var2->dscale);
8232 
8233  /*
8234  * Arrange for var1 to be the number with the greater absolute value.
8235  *
8236  * This would happen automatically in the loop below, but avoids an
8237  * expensive modulo operation.
8238  */
8239  cmp = cmp_abs(var1, var2);
8240  if (cmp < 0)
8241  {
8242  const NumericVar *tmp = var1;
8243 
8244  var1 = var2;
8245  var2 = tmp;
8246  }
8247 
8248  /*
8249  * Also avoid the taking the modulo if the inputs have the same absolute
8250  * value, or if the smaller input is zero.
8251  */
8252  if (cmp == 0 || var2->ndigits == 0)
8253  {
8254  set_var_from_var(var1, result);
8255  result->sign = NUMERIC_POS;
8256  result->dscale = res_dscale;
8257  return;
8258  }
8259 
8260  init_var(&tmp_arg);
8261  init_var(&mod);
8262 
8263  /* Use the Euclidean algorithm to find the GCD */
8264  set_var_from_var(var1, &tmp_arg);
8265  set_var_from_var(var2, result);
8266 
8267  for (;;)
8268  {
8269  /* this loop can take a while, so allow it to be interrupted */
8271 
8272  mod_var(&tmp_arg, result, &mod);
8273  if (mod.ndigits == 0)
8274  break;
8275  set_var_from_var(result, &tmp_arg);
8276  set_var_from_var(&mod, result);
8277  }
8278  result->sign = NUMERIC_POS;
8279  result->dscale = res_dscale;
8280 
8281  free_var(&tmp_arg);
8282  free_var(&mod);
8283 }
#define NUMERIC_POS
Definition: numeric.c:167
int ndigits
Definition: numeric.c:274
int dscale
Definition: numeric.c:277
int sign
Definition: numeric.c:276
static void mod_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition: numeric.c:8078
static void free_var(NumericVar *var)
Definition: numeric.c:5921
static int cmp_abs(const NumericVar *var1, const NumericVar *var2)
Definition: numeric.c:9463
#define Max(x, y)
Definition: numeric.c:13
static void set_var_from_var(const NumericVar *value, NumericVar *dest)
Definition: numeric.c:6171
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:99
#define init_var(v)
Definition: numeric.c:444
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 1373 of file numeric.c.

References generate_series_step_numeric().

1374 {
1375  return generate_series_step_numeric(fcinfo);
1376 }
Datum generate_series_step_numeric(PG_FUNCTION_ARGS)
Definition: numeric.c:1379

◆ generate_series_step_numeric()

Datum generate_series_step_numeric ( PG_FUNCTION_ARGS  )

Definition at line 1379 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().

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

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

Referenced by numeric_min_scale(), and numeric_trim_scale().

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

◆ get_str_from_var()

static char * get_str_from_var ( const NumericVar var)
static

Definition at line 6197 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().

6198 {
6199  int dscale;
6200  char *str;
6201  char *cp;
6202  char *endcp;
6203  int i;
6204  int d;
6205  NumericDigit dig;
6206 
6207 #if DEC_DIGITS > 1
6208  NumericDigit d1;
6209 #endif
6210 
6211  dscale = var->dscale;
6212 
6213  /*
6214  * Allocate space for the result.
6215  *
6216  * i is set to the # of decimal digits before decimal point. dscale is the
6217  * # of decimal digits we will print after decimal point. We may generate
6218  * as many as DEC_DIGITS-1 excess digits at the end, and in addition we
6219  * need room for sign, decimal point, null terminator.
6220  */
6221  i = (var->weight + 1) * DEC_DIGITS;
6222  if (i <= 0)
6223  i = 1;
6224 
6225  str = palloc(i + dscale + DEC_DIGITS + 2);
6226  cp = str;
6227 
6228  /*
6229  * Output a dash for negative values
6230  */
6231  if (var->sign == NUMERIC_NEG)
6232  *cp++ = '-';
6233 
6234  /*
6235  * Output all digits before the decimal point
6236  */
6237  if (var->weight < 0)
6238  {
6239  d = var->weight + 1;
6240  *cp++ = '0';
6241  }
6242  else
6243  {
6244  for (d = 0; d <= var->weight; d++)
6245  {
6246  dig = (d < var->ndigits) ? var->digits[d] : 0;
6247  /* In the first digit, suppress extra leading decimal zeroes */
6248 #if DEC_DIGITS == 4
6249  {
6250  bool putit = (d > 0);
6251 
6252  d1 = dig / 1000;
6253  dig -= d1 * 1000;
6254  putit |= (d1 > 0);
6255  if (putit)
6256  *cp++ = d1 + '0';
6257  d1 = dig / 100;
6258  dig -= d1 * 100;
6259  putit |= (d1 > 0);
6260  if (putit)
6261  *cp++ = d1 + '0';
6262  d1 = dig / 10;
6263  dig -= d1 * 10;
6264  putit |= (d1 > 0);
6265  if (putit)
6266  *cp++ = d1 + '0';
6267  *cp++ = dig + '0';
6268  }
6269 #elif DEC_DIGITS == 2
6270  d1 = dig / 10;
6271  dig -= d1 * 10;
6272  if (d1 > 0 || d > 0)
6273  *cp++ = d1 + '0';
6274  *cp++ = dig + '0';
6275 #elif DEC_DIGITS == 1
6276  *cp++ = dig + '0';
6277 #else
6278 #error unsupported NBASE
6279 #endif
6280  }
6281  }
6282 
6283  /*
6284  * If requested, output a decimal point and all the digits that follow it.
6285  * We initially put out a multiple of DEC_DIGITS digits, then truncate if
6286  * needed.
6287  */
6288  if (dscale > 0)
6289  {
6290  *cp++ = '.';
6291  endcp = cp + dscale;
6292  for (i = 0; i < dscale; d++, i += DEC_DIGITS)
6293  {
6294  dig = (d >= 0 && d < var->ndigits) ? var->digits[d] : 0;
6295 #if DEC_DIGITS == 4
6296  d1 = dig / 1000;
6297  dig -= d1 * 1000;
6298  *cp++ = d1 + '0';
6299  d1 = dig / 100;
6300  dig -= d1 * 100;
6301  *cp++ = d1 + '0';
6302  d1 = dig / 10;
6303  dig -= d1 * 10;
6304  *cp++ = d1 + '0';
6305  *cp++ = dig + '0';
6306 #elif DEC_DIGITS == 2
6307  d1 = dig / 10;
6308  dig -= d1 * 10;
6309  *cp++ = d1 + '0';
6310  *cp++ = dig + '0';
6311 #elif DEC_DIGITS == 1
6312  *cp++ = dig + '0';
6313 #else
6314 #error unsupported NBASE
6315 #endif
6316  }
6317  cp = endcp;
6318  }
6319 
6320  /*
6321  * terminate the string and return it
6322  */
6323  *cp = '\0';
6324  return str;
6325 }
int weight
Definition: numeric.c:275
static void error(void)
Definition: sql-dyntest.c:147
int ndigits
Definition: numeric.c:274
int dscale
Definition: numeric.c:277
#define NUMERIC_NEG
Definition: numeric.c:168
int sign
Definition: numeric.c:276
int16 NumericDigit
Definition: numeric.c:102
#define NBASE
Definition: numeric.c:96
NumericDigit * digits
Definition: numeric.c:279
void * palloc(Size size)
Definition: mcxt.c:949
int i
#define DEC_DIGITS
Definition: numeric.c:98

◆ get_str_from_var_sci()

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

Definition at line 6350 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().

6351 {
6352  int32 exponent;
6353  NumericVar denominator;
6354  NumericVar significand;
6355  int denom_scale;
6356  size_t len;
6357  char *str;
6358  char *sig_out;
6359 
6360  if (rscale < 0)
6361  rscale = 0;
6362 
6363  /*
6364  * Determine the exponent of this number in normalised form.
6365  *
6366  * This is the exponent required to represent the number with only one
6367  * significant digit before the decimal place.
6368  */
6369  if (var->ndigits > 0)
6370  {
6371  exponent = (var->weight + 1) * DEC_DIGITS;
6372 
6373  /*
6374  * Compensate for leading decimal zeroes in the first numeric digit by
6375  * decrementing the exponent.
6376  */
6377  exponent -= DEC_DIGITS - (int) log10(var->digits[0]);
6378  }
6379  else
6380  {
6381  /*
6382  * If var has no digits, then it must be zero.
6383  *
6384  * Zero doesn't technically have a meaningful exponent in normalised
6385  * notation, but we just display the exponent as zero for consistency
6386  * of output.
6387  */
6388  exponent = 0;
6389  }
6390 
6391  /*
6392  * The denominator is set to 10 raised to the power of the exponent.
6393  *
6394  * We then divide var by the denominator to get the significand, rounding
6395  * to rscale decimal digits in the process.
6396  */
6397  if (exponent < 0)
6398  denom_scale = -exponent;
6399  else
6400  denom_scale = 0;
6401 
6402  init_var(&denominator);
6403  init_var(&significand);
6404 
6405  power_var_int(&const_ten, exponent, &denominator, denom_scale);
6406  div_var(var, &denominator, &significand, rscale, true);
6407  sig_out = get_str_from_var(&significand);
6408 
6409  free_var(&denominator);
6410  free_var(&significand);
6411 
6412  /*
6413  * Allocate space for the result.
6414  *
6415  * In addition to the significand, we need room for the exponent
6416  * decoration ("e"), the sign of the exponent, up to 10 digits for the
6417  * exponent itself, and of course the null terminator.
6418  */
6419  len = strlen(sig_out) + 13;
6420  str = palloc(len);
6421  snprintf(str, len, "%se%+03d", sig_out, exponent);
6422 
6423  pfree(sig_out);
6424 
6425  return str;
6426 }
int weight
Definition: numeric.c:275
int ndigits
Definition: numeric.c:274
static void div_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result, int rscale, bool round)
Definition: numeric.c:7418
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:9273
static const NumericVar const_ten
Definition: numeric.c:387
static void free_var(NumericVar *var)
Definition: numeric.c:5921
NumericDigit * digits
Definition: numeric.c:279
void * palloc(Size size)
Definition: mcxt.c:949
static char * get_str_from_var(const NumericVar *var)
Definition: numeric.c:6197
#define DEC_DIGITS
Definition: numeric.c:98
#define snprintf
Definition: port.h:192
#define init_var(v)
Definition: numeric.c:444

◆ hash_numeric()

Datum hash_numeric ( PG_FUNCTION_ARGS  )

Definition at line 2253 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().

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

◆ hash_numeric_extended()

Datum hash_numeric_extended ( PG_FUNCTION_ARGS  )

Definition at line 2333 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().

2334 {
2336  uint64 seed = PG_GETARG_INT64(1);
2337  Datum digit_hash;
2338  Datum result;
2339  int weight;
2340  int start_offset;
2341  int end_offset;
2342  int i;
2343  int hash_len;
2345 
2346  if (NUMERIC_IS_NAN(key))
2347  PG_RETURN_UINT64(seed);
2348 
2349  weight = NUMERIC_WEIGHT(key);
2350  start_offset = 0;
2351  end_offset = 0;
2352 
2353  digits = NUMERIC_DIGITS(key);
2354  for (i = 0; i < NUMERIC_NDIGITS(key); i++)
2355  {
2356  if (digits[i] != (NumericDigit) 0)
2357  break;
2358 
2359  start_offset++;
2360 
2361  weight--;
2362  }
2363 
2364  if (NUMERIC_NDIGITS(key) == start_offset)
2365  PG_RETURN_UINT64(seed - 1);
2366 
2367  for (i = NUMERIC_NDIGITS(key) - 1; i >= 0; i--)
2368  {
2369  if (digits[i] != (NumericDigit) 0)
2370  break;
2371 
2372  end_offset++;
2373  }
2374 
2375  Assert(start_offset + end_offset < NUMERIC_NDIGITS(key));
2376 
2377  hash_len = NUMERIC_NDIGITS(key) - start_offset - end_offset;
2378  digit_hash = hash_any_extended((unsigned char *) (NUMERIC_DIGITS(key)
2379  + start_offset),
2380  hash_len * sizeof(NumericDigit),
2381  seed);
2382 
2383  result = UInt64GetDatum(DatumGetUInt64(digit_hash) ^ weight);
2384 
2385  PG_RETURN_DATUM(result);
2386 }
#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:362
#define NUMERIC_DIGITS(num)
Definition: numeric.c:446
int16 NumericDigit
Definition: numeric.c:102
#define NUMERIC_NDIGITS(num)
Definition: numeric.c:448
uintptr_t Datum
Definition: postgres.h:367
#define PG_RETURN_DATUM(x)
Definition: fmgr.h:347
#define DatumGetUInt64(X)
Definition: postgres.h:634
#define NUMERIC_WEIGHT(n)
Definition: numeric.c:217
#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:173
#define PG_GETARG_INT64(n)
Definition: fmgr.h:277
int digits
Definition: informix.c:666

◆ in_range_numeric_numeric()

Datum in_range_numeric_numeric ( PG_FUNCTION_ARGS  )

Definition at line 2181 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.

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

◆ init_var_from_num()

static void init_var_from_num ( Numeric  num,
NumericVar dest 
)
static

Definition at line 6154 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_poly_deserialize(), numeric_power(), numeric_send(), numeric_sqrt(), numeric_sub_opt_error(), and numeric_trim_scale().

6155 {
6156  dest->ndigits = NUMERIC_NDIGITS(num);
6157  dest->weight = NUMERIC_WEIGHT(num);
6158  dest->sign = NUMERIC_SIGN(num);
6159  dest->dscale = NUMERIC_DSCALE(num);
6160  dest->digits = NUMERIC_DIGITS(num);
6161  dest->buf = NULL; /* digits array is not palloc'd */
6162 }
#define NUMERIC_DSCALE(n)
Definition: numeric.c:213
int weight
Definition: numeric.c:275
int ndigits
Definition: numeric.c:274
int dscale
Definition: numeric.c:277
int sign
Definition: numeric.c:276
#define NUMERIC_DIGITS(num)
Definition: numeric.c:446
#define NUMERIC_SIGN(n)
Definition: numeric.c:209
NumericDigit * buf
Definition: numeric.c:278
#define NUMERIC_NDIGITS(num)
Definition: numeric.c:448
#define NUMERIC_WEIGHT(n)
Definition: numeric.c:217
NumericDigit * digits
Definition: numeric.c:279

◆ int2_accum()

Datum int2_accum ( PG_FUNCTION_ARGS  )

Definition at line 4452 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.

4453 {
4455 
4456  state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
4457 
4458  /* Create the state data on the first call */
4459  if (state == NULL)
4460  state = makePolyNumAggState(fcinfo, true);
4461 
4462  if (!PG_ARGISNULL(1))
4463  {
4464 #ifdef HAVE_INT128
4465  do_int128_accum(state, (int128) PG_GETARG_INT16(1));
4466 #else
4467  Numeric newval;
4468 
4470  PG_GETARG_DATUM(1)));
4471  do_numeric_accum(state, newval);
4472 #endif
4473  }
4474 
4475  PG_RETURN_POINTER(state);
4476 }
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:355
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:263
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:271
Datum int2_numeric(PG_FUNCTION_ARGS)
Definition: numeric.c:3515
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:619
static void do_numeric_accum(NumericAggState *state, Numeric newval)
Definition: numeric.c:3762
#define PG_GETARG_INT16(n)
Definition: fmgr.h:266
#define PG_ARGISNULL(n)
Definition: fmgr.h:204
#define DatumGetNumeric(X)
Definition: numeric.h:49
Definition: regguts.h:298
#define newval
#define makePolyNumAggState
Definition: numeric.c:4447

◆ int2_accum_inv()

Datum int2_accum_inv ( PG_FUNCTION_ARGS  )

Definition at line 4929 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.

4930 {
4932 
4933  state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
4934 
4935  /* Should not get here with no state */
4936  if (state == NULL)
4937  elog(ERROR, "int2_accum_inv called with NULL state");
4938 
4939  if (!PG_ARGISNULL(1))
4940  {
4941 #ifdef HAVE_INT128
4942  do_int128_discard(state, (int128) PG_GETARG_INT16(1));
4943 #else
4944  Numeric newval;
4945 
4947  PG_GETARG_DATUM(1)));
4948 
4949  /* Should never fail, all inputs have dscale 0 */
4950  if (!do_numeric_discard(state, newval))
4951  elog(ERROR, "do_numeric_discard failed unexpectedly");
4952 #endif
4953  }
4954 
4955  PG_RETURN_POINTER(state);
4956 }
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:355
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:263
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:271
Datum int2_numeric(PG_FUNCTION_ARGS)
Definition: numeric.c:3515
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:619
static bool do_numeric_discard(NumericAggState *state, Numeric newval)
Definition: numeric.c:3827
#define ERROR
Definition: elog.h:43
#define PG_GETARG_INT16(n)
Definition: fmgr.h:266
#define PG_ARGISNULL(n)
Definition: fmgr.h:204
#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 5620 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.

5621 {
5622  ArrayType *transarray;
5624  Int8TransTypeData *transdata;
5625 
5626  /*
5627  * If we're invoked as an aggregate, we can cheat and modify our first
5628  * parameter in-place to reduce palloc overhead. Otherwise we need to make
5629  * a copy of it before scribbling on it.
5630  */
5631  if (AggCheckCallContext(fcinfo, NULL))
5632  transarray = PG_GETARG_ARRAYTYPE_P(0);
5633  else
5634  transarray = PG_GETARG_ARRAYTYPE_P_COPY(0);
5635 
5636  if (ARR_HASNULL(transarray) ||
5637  ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
5638  elog(ERROR, "expected 2-element int8 array");
5639 
5640  transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
5641  transdata->count++;
5642  transdata->sum += newval;
5643 
5644  PG_RETURN_ARRAYTYPE_P(transarray);
5645 }
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:266
#define newval
int AggCheckCallContext(FunctionCallInfo fcinfo, MemoryContext *aggcontext)
Definition: nodeAgg.c:4661
#define elog(elevel,...)
Definition: elog.h:214

◆ int2_avg_accum_inv()

Datum int2_avg_accum_inv ( PG_FUNCTION_ARGS  )

Definition at line 5707 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.

5708 {
5709  ArrayType *transarray;
5711  Int8TransTypeData *transdata;
5712 
5713  /*
5714  * If we're invoked as an aggregate, we can cheat and modify our first
5715  * parameter in-place to reduce palloc overhead. Otherwise we need to make
5716  * a copy of it before scribbling on it.
5717  */
5718  if (AggCheckCallContext(fcinfo, NULL))
5719  transarray = PG_GETARG_ARRAYTYPE_P(0);
5720  else
5721  transarray = PG_GETARG_ARRAYTYPE_P_COPY(0);
5722 
5723  if (ARR_HASNULL(transarray) ||
5724  ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
5725  elog(ERROR, "expected 2-element int8 array");
5726 
5727  transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
5728  transdata->count--;
5729  transdata->sum -= newval;
5730 
5731  PG_RETURN_ARRAYTYPE_P(transarray);
5732 }
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:266
#define newval
int AggCheckCallContext(FunctionCallInfo fcinfo, MemoryContext *aggcontext)
Definition: nodeAgg.c:4661
#define elog(elevel,...)
Definition: elog.h:214

◆ int2_numeric()

Datum int2_numeric ( PG_FUNCTION_ARGS  )

Definition at line 3515 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().

3516 {
3517  int16 val = PG_GETARG_INT16(0);
3518  Numeric res;
3519  NumericVar result;
3520 
3521  init_var(&result);
3522 
3523  int64_to_numericvar((int64) val, &result);
3524 
3525  res = make_result(&result);
3526 
3527  free_var(&result);
3528 
3529  PG_RETURN_NUMERIC(res);
3530 }
#define PG_RETURN_NUMERIC(x)
Definition: numeric.h:54
signed short int16
Definition: c.h:354
#define PG_GETARG_INT16(n)
Definition: fmgr.h:266
static void free_var(NumericVar *var)
Definition: numeric.c:5921
static Numeric make_result(const NumericVar *var)
Definition: numeric.c:6537
static void int64_to_numericvar(int64 val, NumericVar *var)
Definition: numeric.c:6701
long val
Definition: informix.c:664
#define init_var(v)
Definition: numeric.c:444

◆ int2_sum()

Datum int2_sum ( PG_FUNCTION_ARGS  )

Definition at line 5468 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.

5469 {
5470  int64 newval;
5471 
5472  if (PG_ARGISNULL(0))
5473  {
5474  /* No non-null input seen so far... */
5475  if (PG_ARGISNULL(1))
5476  PG_RETURN_NULL(); /* still no non-null */
5477  /* This is the first non-null input. */
5478  newval = (int64) PG_GETARG_INT16(1);
5479  PG_RETURN_INT64(newval);
5480  }
5481 
5482  /*
5483  * If we're invoked as an aggregate, we can cheat and modify our first
5484  * parameter in-place to avoid palloc overhead. If not, we need to return
5485  * the new value of the transition variable. (If int8 is pass-by-value,
5486  * then of course this is useless as well as incorrect, so just ifdef it
5487  * out.)
5488  */
5489 #ifndef USE_FLOAT8_BYVAL /* controls int8 too */
5490  if (AggCheckCallContext(fcinfo, NULL))
5491  {
5492  int64 *oldsum = (int64 *) PG_GETARG_POINTER(0);
5493 
5494  /* Leave the running sum unchanged in the new input is null */
5495  if (!PG_ARGISNULL(1))
5496  *oldsum = *oldsum + (int64) PG_GETARG_INT16(1);
5497 
5498  PG_RETURN_POINTER(oldsum);
5499  }
5500  else
5501 #endif
5502  {
5503  int64 oldsum = PG_GETARG_INT64(0);
5504 
5505  /* Leave sum unchanged if new input is null. */
5506  if (PG_ARGISNULL(1))
5507  PG_RETURN_INT64(oldsum);
5508 
5509  /* OK to do the addition. */
5510  newval = oldsum + (int64) PG_GETARG_INT16(1);
5511 
5512  PG_RETURN_INT64(newval);
5513  }
5514 }
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:355
#define PG_RETURN_INT64(x)
Definition: fmgr.h:361
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:271
#define PG_GETARG_INT16(n)
Definition: fmgr.h:266
#define PG_ARGISNULL(n)
Definition: fmgr.h:204
#define newval
int AggCheckCallContext(FunctionCallInfo fcinfo, MemoryContext *aggcontext)
Definition: nodeAgg.c:4661
#define PG_GETARG_INT64(n)
Definition: fmgr.h:277
#define PG_RETURN_NULL()
Definition: fmgr.h:339

◆ int2int4_sum()

Datum int2int4_sum ( PG_FUNCTION_ARGS  )

Definition at line 5792 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.

5793 {
5794  ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
5795  Int8TransTypeData *transdata;
5796 
5797  if (ARR_HASNULL(transarray) ||
5798  ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
5799  elog(ERROR, "expected 2-element int8 array");
5800  transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
5801 
5802  /* SQL defines SUM of no values to be NULL */
5803  if (transdata->count == 0)
5804  PG_RETURN_NULL();
5805 
5806  PG_RETURN_DATUM(Int64GetDatumFast(transdata->sum));
5807 }
#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:347
#define Int64GetDatumFast(X)
Definition: postgres.h:760
#define elog(elevel,...)
Definition: elog.h:214
#define PG_RETURN_NULL()
Definition: fmgr.h:339

◆ int4_accum()

Datum int4_accum ( PG_FUNCTION_ARGS  )

Definition at line 4479 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.

4480 {
4482 
4483  state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
4484 
4485  /* Create the state data on the first call */
4486  if (state == NULL)
4487  state = makePolyNumAggState(fcinfo, true);
4488 
4489  if (!PG_ARGISNULL(1))
4490  {
4491 #ifdef HAVE_INT128
4492  do_int128_accum(state, (int128) PG_GETARG_INT32(1));
4493 #else
4494  Numeric newval;
4495 
4497  PG_GETARG_DATUM(1)));
4498  do_numeric_accum(state, newval);
4499 #endif
4500  }
4501 
4502  PG_RETURN_POINTER(state);
4503 }
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:355
#define PG_GETARG_INT32(n)
Definition: fmgr.h:264
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:263
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:271
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:619
static void do_numeric_accum(NumericAggState *state, Numeric newval)
Definition: numeric.c:3762
Datum int4_numeric(PG_FUNCTION_ARGS)
Definition: numeric.c:3379
#define PG_ARGISNULL(n)
Definition: fmgr.h:204
#define DatumGetNumeric(X)
Definition: numeric.h:49
Definition: regguts.h:298
#define newval
#define makePolyNumAggState
Definition: numeric.c:4447

◆ int4_accum_inv()

Datum int4_accum_inv ( PG_FUNCTION_ARGS  )

Definition at line 4959 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.

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, "int4_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_INT32(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:355
#define PG_GETARG_INT32(n)
Definition: fmgr.h:264
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:263
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:271
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:619
static bool do_numeric_discard(NumericAggState *state, Numeric newval)
Definition: numeric.c:3827
#define ERROR
Definition: elog.h:43
Datum int4_numeric(PG_FUNCTION_ARGS)
Definition: numeric.c:3379
#define PG_ARGISNULL(n)
Definition: fmgr.h:204
#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 5648 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.

5649 {
5650  ArrayType *transarray;
5652  Int8TransTypeData *transdata;
5653 
5654  /*
5655  * If we're invoked as an aggregate, we can cheat and modify our first
5656  * parameter in-place to reduce palloc overhead. Otherwise we need to make
5657  * a copy of it before scribbling on it.
5658  */
5659  if (AggCheckCallContext(fcinfo, NULL))
5660  transarray = PG_GETARG_ARRAYTYPE_P(0);
5661  else
5662  transarray = PG_GETARG_ARRAYTYPE_P_COPY(0);
5663 
5664  if (ARR_HASNULL(transarray) ||
5665  ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
5666  elog(ERROR, "expected 2-element int8 array");
5667 
5668  transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
5669  transdata->count++;
5670  transdata->sum += newval;
5671 
5672  PG_RETURN_ARRAYTYPE_P(transarray);
5673 }
#define PG_GETARG_INT32(n)
Definition: fmgr.h:264
#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:4661
#define elog(elevel,...)
Definition: elog.h:214

◆ int4_avg_accum_inv()

Datum int4_avg_accum_inv ( PG_FUNCTION_ARGS  )

Definition at line 5735 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.

5736 {
5737  ArrayType *transarray;
5739  Int8TransTypeData *transdata;
5740 
5741  /*
5742  * If we're invoked as an aggregate, we can cheat and modify our first
5743  * parameter in-place to reduce palloc overhead. Otherwise we need to make
5744  * a copy of it before scribbling on it.
5745  */
5746  if (AggCheckCallContext(fcinfo, NULL))
5747  transarray = PG_GETARG_ARRAYTYPE_P(0);
5748  else
5749  transarray = PG_GETARG_ARRAYTYPE_P_COPY(0);
5750 
5751  if (ARR_HASNULL(transarray) ||
5752  ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
5753  elog(ERROR, "expected 2-element int8 array");
5754 
5755  transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
5756  transdata->count--;
5757  transdata->sum -= newval;
5758 
5759  PG_RETURN_ARRAYTYPE_P(transarray);
5760 }
#define PG_GETARG_INT32(n)
Definition: fmgr.h:264
#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:4661
#define elog(elevel,...)
Definition: elog.h:214

◆ int4_avg_combine()

Datum int4_avg_combine ( PG_FUNCTION_ARGS  )

Definition at line 5676 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.

5677 {
5678  ArrayType *transarray1;
5679  ArrayType *transarray2;
5680  Int8TransTypeData *state1;
5681  Int8TransTypeData *state2;
5682 
5683  if (!AggCheckCallContext(fcinfo, NULL))
5684  elog(ERROR, "aggregate function called in non-aggregate context");
5685 
5686  transarray1 = PG_GETARG_ARRAYTYPE_P(0);
5687  transarray2 = PG_GETARG_ARRAYTYPE_P(1);
5688 
5689  if (ARR_HASNULL(transarray1) ||
5690  ARR_SIZE(transarray1) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
5691  elog(ERROR, "expected 2-element int8 array");
5692 
5693  if (ARR_HASNULL(transarray2) ||
5694  ARR_SIZE(transarray2) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
5695  elog(ERROR, "expected 2-element int8 array");
5696 
5697  state1 = (Int8TransTypeData *) ARR_DATA_PTR(transarray1);
5698  state2 = (Int8TransTypeData *) ARR_DATA_PTR(transarray2);
5699 
5700  state1->count += state2->count;
5701  state1->sum += state2->sum;
5702 
5703  PG_RETURN_ARRAYTYPE_P(transarray1);
5704 }
#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:4661
#define elog(elevel,...)
Definition: elog.h:214

◆ int4_numeric()

Datum int4_numeric ( PG_FUNCTION_ARGS  )

Definition at line 3379 of file numeric.c.

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

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

3380 {
3381  int32 val = PG_GETARG_INT32(0);
3382  Numeric res;
3383  NumericVar result;
3384 
3385  init_var(&result);
3386 
3387  int64_to_numericvar((int64) val, &result);
3388 
3389  res = make_result(&result);
3390 
3391  free_var(&result);
3392 
3393  PG_RETURN_NUMERIC(res);
3394 }
#define PG_RETURN_NUMERIC(x)
Definition: numeric.h:54
#define PG_GETARG_INT32(n)
Definition: fmgr.h:264