PostgreSQL Source Code  git master
numeric.c File Reference
#include "postgres.h"
#include <ctype.h>
#include <float.h>
#include <limits.h>
#include <math.h>
#include "catalog/pg_type.h"
#include "common/hashfn.h"
#include "common/int.h"
#include "funcapi.h"
#include "lib/hyperloglog.h"
#include "libpq/pqformat.h"
#include "miscadmin.h"
#include "nodes/nodeFuncs.h"
#include "nodes/supportnodes.h"
#include "utils/array.h"
#include "utils/builtins.h"
#include "utils/guc.h"
#include "utils/int8.h"
#include "utils/numeric.h"
#include "utils/pg_lsn.h"
#include "utils/sortsupport.h"
Include dependency graph for numeric.c:

Go to the source code of this file.

Data Structures

struct  NumericShort
 
struct  NumericLong
 
union  NumericChoice
 
struct  NumericData
 
struct  NumericVar
 
struct  generate_series_numeric_fctx
 
struct  NumericSortSupport
 
struct  NumericSumAccum
 
struct  NumericAggState
 
struct  Int8TransTypeData
 

Macros

#define NBASE   10000
 
#define HALF_NBASE   5000
 
#define DEC_DIGITS   4 /* decimal digits per NBASE digit */
 
#define MUL_GUARD_DIGITS   2 /* these are measured in NBASE digits */
 
#define DIV_GUARD_DIGITS   4
 
#define NUMERIC_SIGN_MASK   0xC000
 
#define NUMERIC_POS   0x0000
 
#define NUMERIC_NEG   0x4000
 
#define NUMERIC_SHORT   0x8000
 
#define NUMERIC_SPECIAL   0xC000
 
#define NUMERIC_FLAGBITS(n)   ((n)->choice.n_header & NUMERIC_SIGN_MASK)
 
#define NUMERIC_IS_SHORT(n)   (NUMERIC_FLAGBITS(n) == NUMERIC_SHORT)
 
#define NUMERIC_IS_SPECIAL(n)   (NUMERIC_FLAGBITS(n) == NUMERIC_SPECIAL)
 
#define NUMERIC_HDRSZ   (VARHDRSZ + sizeof(uint16) + sizeof(int16))
 
#define NUMERIC_HDRSZ_SHORT   (VARHDRSZ + sizeof(uint16))
 
#define NUMERIC_HEADER_IS_SHORT(n)   (((n)->choice.n_header & 0x8000) != 0)
 
#define NUMERIC_HEADER_SIZE(n)
 
#define NUMERIC_EXT_SIGN_MASK   0xF000 /* high bits plus NaN/Inf flag bits */
 
#define NUMERIC_NAN   0xC000
 
#define NUMERIC_PINF   0xD000
 
#define NUMERIC_NINF   0xF000
 
#define NUMERIC_INF_SIGN_MASK   0x2000
 
#define NUMERIC_EXT_FLAGBITS(n)   ((n)->choice.n_header & NUMERIC_EXT_SIGN_MASK)
 
#define NUMERIC_IS_NAN(n)   ((n)->choice.n_header == NUMERIC_NAN)
 
#define NUMERIC_IS_PINF(n)   ((n)->choice.n_header == NUMERIC_PINF)
 
#define NUMERIC_IS_NINF(n)   ((n)->choice.n_header == NUMERIC_NINF)
 
#define NUMERIC_IS_INF(n)   (((n)->choice.n_header & ~NUMERIC_INF_SIGN_MASK) == NUMERIC_PINF)
 
#define NUMERIC_SHORT_SIGN_MASK   0x2000
 
#define NUMERIC_SHORT_DSCALE_MASK   0x1F80
 
#define NUMERIC_SHORT_DSCALE_SHIFT   7
 
#define NUMERIC_SHORT_DSCALE_MAX   (NUMERIC_SHORT_DSCALE_MASK >> NUMERIC_SHORT_DSCALE_SHIFT)
 
#define NUMERIC_SHORT_WEIGHT_SIGN_MASK   0x0040
 
#define NUMERIC_SHORT_WEIGHT_MASK   0x003F
 
#define NUMERIC_SHORT_WEIGHT_MAX   NUMERIC_SHORT_WEIGHT_MASK
 
#define NUMERIC_SHORT_WEIGHT_MIN   (-(NUMERIC_SHORT_WEIGHT_MASK+1))
 
#define NUMERIC_DSCALE_MASK   0x3FFF
 
#define NUMERIC_DSCALE_MAX   NUMERIC_DSCALE_MASK
 
#define NUMERIC_SIGN(n)
 
#define NUMERIC_DSCALE(n)
 
#define NUMERIC_WEIGHT(n)
 
#define NUMERIC_ABBREV_BITS   (SIZEOF_DATUM * BITS_PER_BYTE)
 
#define NumericAbbrevGetDatum(X)   ((Datum) (X))
 
#define DatumGetNumericAbbrev(X)   ((int32) (X))
 
#define NUMERIC_ABBREV_NAN   NumericAbbrevGetDatum(PG_INT32_MIN)
 
#define NUMERIC_ABBREV_PINF   NumericAbbrevGetDatum(-PG_INT32_MAX)
 
#define NUMERIC_ABBREV_NINF   NumericAbbrevGetDatum(PG_INT32_MAX)
 
#define dump_numeric(s, n)
 
#define dump_var(s, v)
 
#define digitbuf_alloc(ndigits)   ((NumericDigit *) palloc((ndigits) * sizeof(NumericDigit)))
 
#define digitbuf_free(buf)
 
#define init_var(v)   memset(v, 0, sizeof(NumericVar))
 
#define NUMERIC_DIGITS(num)
 
#define NUMERIC_NDIGITS(num)   ((VARSIZE(num) - NUMERIC_HEADER_SIZE(num)) / sizeof(NumericDigit))
 
#define NUMERIC_CAN_BE_SHORT(scale, weight)
 
#define NA_TOTAL_COUNT(na)   ((na)->N + (na)->NaNcount + (na)->pInfcount + (na)->nInfcount)
 
#define makePolyNumAggState   makeNumericAggState
 
#define makePolyNumAggStateCurrentContext   makeNumericAggStateCurrentContext
 

Typedefs

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

Functions

static void alloc_var (NumericVar *var, int ndigits)
 
static void free_var (NumericVar *var)
 
static void zero_var (NumericVar *var)
 
static 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 void numericvar_serialize (StringInfo buf, const NumericVar *var)
 
static void numericvar_deserialize (StringInfo buf, NumericVar *var)
 
static Numeric duplicate_numeric (Numeric num)
 
static Numeric make_result (const NumericVar *var)
 
static Numeric make_result_opt_error (const NumericVar *var, bool *error)
 
static void apply_typmod (NumericVar *var, int32 typmod)
 
static void apply_typmod_special (Numeric num, int32 typmod)
 
static bool numericvar_to_int32 (const NumericVar *var, int32 *result)
 
static bool numericvar_to_int64 (const NumericVar *var, int64 *result)
 
static void int64_to_numericvar (int64 val, NumericVar *var)
 
static bool numericvar_to_uint64 (const NumericVar *var, uint64 *result)
 
static double 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 void power_ten_int (int exp, NumericVar *result)
 
static int cmp_abs (const NumericVar *var1, const NumericVar *var2)
 
static int cmp_abs_common (const NumericDigit *var1digits, int var1ndigits, int var1weight, const NumericDigit *var2digits, int var2ndigits, int var2weight)
 
static void add_abs (const NumericVar *var1, const NumericVar *var2, NumericVar *result)
 
static void sub_abs (const NumericVar *var1, const NumericVar *var2, NumericVar *result)
 
static void round_var (NumericVar *var, int rscale)
 
static void trunc_var (NumericVar *var, int rscale)
 
static void strip_var (NumericVar *var)
 
static void compute_bucket (Numeric operand, Numeric bound1, Numeric bound2, const NumericVar *count_var, bool reversed_bounds, NumericVar *result_var)
 
static void accum_sum_add (NumericSumAccum *accum, const NumericVar *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)
 
bool numeric_is_inf (Numeric num)
 
static bool numeric_is_integral (Numeric num)
 
static int32 make_numeric_typmod (int precision, int scale)
 
static bool is_valid_numeric_typmod (int32 typmod)
 
static int numeric_typmod_precision (int32 typmod)
 
static int numeric_typmod_scale (int32 typmod)
 
int32 numeric_maximum_size (int32 typmod)
 
char * numeric_out_sci (Numeric num, int scale)
 
char * numeric_normalize (Numeric num)
 
Datum numeric_recv (PG_FUNCTION_ARGS)
 
Datum numeric_send (PG_FUNCTION_ARGS)
 
Datum numeric_support (PG_FUNCTION_ARGS)
 
Datum numeric (PG_FUNCTION_ARGS)
 
Datum numerictypmodin (PG_FUNCTION_ARGS)
 
Datum numerictypmodout (PG_FUNCTION_ARGS)
 
Datum numeric_abs (PG_FUNCTION_ARGS)
 
Datum numeric_uminus (PG_FUNCTION_ARGS)
 
Datum numeric_uplus (PG_FUNCTION_ARGS)
 
static int numeric_sign_internal (Numeric num)
 
Datum numeric_sign (PG_FUNCTION_ARGS)
 
Datum numeric_round (PG_FUNCTION_ARGS)
 
Datum numeric_trunc (PG_FUNCTION_ARGS)
 
Datum numeric_ceil (PG_FUNCTION_ARGS)
 
Datum numeric_floor (PG_FUNCTION_ARGS)
 
Datum generate_series_numeric (PG_FUNCTION_ARGS)
 
Datum generate_series_step_numeric (PG_FUNCTION_ARGS)
 
Datum width_bucket_numeric (PG_FUNCTION_ARGS)
 
Datum numeric_sortsupport (PG_FUNCTION_ARGS)
 
Datum numeric_cmp (PG_FUNCTION_ARGS)
 
Datum numeric_eq (PG_FUNCTION_ARGS)
 
Datum numeric_ne (PG_FUNCTION_ARGS)
 
Datum numeric_gt (PG_FUNCTION_ARGS)
 
Datum numeric_ge (PG_FUNCTION_ARGS)
 
Datum numeric_lt (PG_FUNCTION_ARGS)
 
Datum numeric_le (PG_FUNCTION_ARGS)
 
Datum in_range_numeric_numeric (PG_FUNCTION_ARGS)
 
Datum hash_numeric (PG_FUNCTION_ARGS)
 
Datum hash_numeric_extended (PG_FUNCTION_ARGS)
 
Datum numeric_add (PG_FUNCTION_ARGS)
 
Numeric numeric_add_opt_error (Numeric num1, Numeric num2, bool *have_error)
 
Datum numeric_sub (PG_FUNCTION_ARGS)
 
Numeric numeric_sub_opt_error (Numeric num1, Numeric num2, bool *have_error)
 
Datum numeric_mul (PG_FUNCTION_ARGS)
 
Numeric numeric_mul_opt_error (Numeric num1, Numeric num2, bool *have_error)
 
Datum numeric_div (PG_FUNCTION_ARGS)
 
Numeric numeric_div_opt_error (Numeric num1, Numeric num2, bool *have_error)
 
Datum numeric_div_trunc (PG_FUNCTION_ARGS)
 
Datum numeric_mod (PG_FUNCTION_ARGS)
 
Numeric numeric_mod_opt_error (Numeric num1, Numeric num2, bool *have_error)
 
Datum numeric_inc (PG_FUNCTION_ARGS)
 
Datum numeric_smaller (PG_FUNCTION_ARGS)
 
Datum numeric_larger (PG_FUNCTION_ARGS)
 
Datum numeric_gcd (PG_FUNCTION_ARGS)
 
Datum numeric_lcm (PG_FUNCTION_ARGS)
 
Datum numeric_fac (PG_FUNCTION_ARGS)
 
Datum numeric_sqrt (PG_FUNCTION_ARGS)
 
Datum numeric_exp (PG_FUNCTION_ARGS)
 
Datum numeric_ln (PG_FUNCTION_ARGS)
 
Datum numeric_log (PG_FUNCTION_ARGS)
 
Datum numeric_power (PG_FUNCTION_ARGS)
 
Datum numeric_scale (PG_FUNCTION_ARGS)
 
static int get_min_scale (NumericVar *var)
 
Datum numeric_min_scale (PG_FUNCTION_ARGS)
 
Datum numeric_trim_scale (PG_FUNCTION_ARGS)
 
Numeric int64_to_numeric (int64 val)
 
Numeric int64_div_fast_to_numeric (int64 val1, int log10val2)
 
Datum int4_numeric (PG_FUNCTION_ARGS)
 
int32 numeric_int4_opt_error (Numeric num, bool *have_error)
 
Datum numeric_int4 (PG_FUNCTION_ARGS)
 
Datum int8_numeric (PG_FUNCTION_ARGS)
 
Datum numeric_int8 (PG_FUNCTION_ARGS)
 
Datum int2_numeric (PG_FUNCTION_ARGS)
 
Datum numeric_int2 (PG_FUNCTION_ARGS)
 
Datum float8_numeric (PG_FUNCTION_ARGS)
 
Datum numeric_float8 (PG_FUNCTION_ARGS)
 
Datum numeric_float8_no_overflow (PG_FUNCTION_ARGS)
 
Datum float4_numeric (PG_FUNCTION_ARGS)
 
Datum numeric_float4 (PG_FUNCTION_ARGS)
 
Datum numeric_pg_lsn (PG_FUNCTION_ARGS)
 
static NumericAggStatemakeNumericAggState (FunctionCallInfo fcinfo, bool calcSumX2)
 
static NumericAggStatemakeNumericAggStateCurrentContext (bool calcSumX2)
 
static void do_numeric_accum (NumericAggState *state, Numeric newval)
 
static bool do_numeric_discard (NumericAggState *state, Numeric newval)
 
Datum numeric_accum (PG_FUNCTION_ARGS)
 
Datum numeric_combine (PG_FUNCTION_ARGS)
 
Datum numeric_avg_accum (PG_FUNCTION_ARGS)
 
Datum numeric_avg_combine (PG_FUNCTION_ARGS)
 
Datum numeric_avg_serialize (PG_FUNCTION_ARGS)
 
Datum numeric_avg_deserialize (PG_FUNCTION_ARGS)
 
Datum numeric_serialize (PG_FUNCTION_ARGS)
 
Datum numeric_deserialize (PG_FUNCTION_ARGS)
 
Datum numeric_accum_inv (PG_FUNCTION_ARGS)
 
Datum int2_accum (PG_FUNCTION_ARGS)
 
Datum int4_accum (PG_FUNCTION_ARGS)
 
Datum int8_accum (PG_FUNCTION_ARGS)
 
Datum numeric_poly_combine (PG_FUNCTION_ARGS)
 
Datum numeric_poly_serialize (PG_FUNCTION_ARGS)
 
Datum numeric_poly_deserialize (PG_FUNCTION_ARGS)
 
Datum int8_avg_accum (PG_FUNCTION_ARGS)
 
Datum int8_avg_combine (PG_FUNCTION_ARGS)
 
Datum int8_avg_serialize (PG_FUNCTION_ARGS)
 
Datum int8_avg_deserialize (PG_FUNCTION_ARGS)
 
Datum int2_accum_inv (PG_FUNCTION_ARGS)
 
Datum int4_accum_inv (PG_FUNCTION_ARGS)
 
Datum int8_accum_inv (PG_FUNCTION_ARGS)
 
Datum int8_avg_accum_inv (PG_FUNCTION_ARGS)
 
Datum numeric_poly_sum (PG_FUNCTION_ARGS)
 
Datum numeric_poly_avg (PG_FUNCTION_ARGS)
 
Datum numeric_avg (PG_FUNCTION_ARGS)
 
Datum numeric_sum (PG_FUNCTION_ARGS)
 
static Numeric numeric_stddev_internal (NumericAggState *state, bool variance, bool sample, bool *is_null)
 
Datum numeric_var_samp (PG_FUNCTION_ARGS)
 
Datum numeric_stddev_samp (PG_FUNCTION_ARGS)
 
Datum numeric_var_pop (PG_FUNCTION_ARGS)
 
Datum numeric_stddev_pop (PG_FUNCTION_ARGS)
 
Datum numeric_poly_var_samp (PG_FUNCTION_ARGS)
 
Datum numeric_poly_stddev_samp (PG_FUNCTION_ARGS)
 
Datum numeric_poly_var_pop (PG_FUNCTION_ARGS)
 
Datum numeric_poly_stddev_pop (PG_FUNCTION_ARGS)
 
Datum int2_sum (PG_FUNCTION_ARGS)
 
Datum int4_sum (PG_FUNCTION_ARGS)
 
Datum int8_sum (PG_FUNCTION_ARGS)
 
Datum int2_avg_accum (PG_FUNCTION_ARGS)
 
Datum int4_avg_accum (PG_FUNCTION_ARGS)
 
Datum int4_avg_combine (PG_FUNCTION_ARGS)
 
Datum int2_avg_accum_inv (PG_FUNCTION_ARGS)
 
Datum int4_avg_accum_inv (PG_FUNCTION_ARGS)
 
Datum int8_avg (PG_FUNCTION_ARGS)
 
Datum int2int4_sum (PG_FUNCTION_ARGS)
 

Variables

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

Macro Definition Documentation

◆ DatumGetNumericAbbrev

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

Definition at line 405 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 478 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:68

Definition at line 480 of file numeric.c.

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

◆ DIV_GUARD_DIGITS

#define DIV_GUARD_DIGITS   4

Definition at line 101 of file numeric.c.

Referenced by div_var_fast().

◆ dump_numeric

#define dump_numeric (   s,
 
)

Definition at line 474 of file numeric.c.

Referenced by int2int4_sum(), and make_result_opt_error().

◆ dump_var

#define dump_var (   s,
 
)

Definition at line 475 of file numeric.c.

Referenced by int2int4_sum().

◆ HALF_NBASE

#define HALF_NBASE   5000

Definition at line 98 of file numeric.c.

Referenced by div_var(), and round_var().

◆ init_var

◆ makePolyNumAggState

#define makePolyNumAggState   makeNumericAggState

◆ makePolyNumAggStateCurrentContext

#define makePolyNumAggStateCurrentContext   makeNumericAggStateCurrentContext

Definition at line 5346 of file numeric.c.

Referenced by int8_avg_deserialize(), and numeric_poly_deserialize().

◆ MUL_GUARD_DIGITS

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

Definition at line 100 of file numeric.c.

Referenced by mul_var().

◆ NA_TOTAL_COUNT

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

Definition at line 4605 of file numeric.c.

Referenced by numeric_avg(), numeric_stddev_internal(), and numeric_sum().

◆ NBASE

◆ NUMERIC_ABBREV_BITS

#define NUMERIC_ABBREV_BITS   (SIZEOF_DATUM * BITS_PER_BYTE)

Definition at line 396 of file numeric.c.

◆ NUMERIC_ABBREV_NAN

#define NUMERIC_ABBREV_NAN   NumericAbbrevGetDatum(PG_INT32_MIN)

Definition at line 406 of file numeric.c.

Referenced by numeric_abbrev_convert().

◆ NUMERIC_ABBREV_NINF

#define NUMERIC_ABBREV_NINF   NumericAbbrevGetDatum(PG_INT32_MAX)

Definition at line 408 of file numeric.c.

Referenced by numeric_abbrev_convert().

◆ NUMERIC_ABBREV_PINF

#define NUMERIC_ABBREV_PINF   NumericAbbrevGetDatum(-PG_INT32_MAX)

Definition at line 407 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:222
int scale
Definition: pgbench.c:191
#define NUMERIC_SHORT_WEIGHT_MIN
Definition: numeric.c:223
#define NUMERIC_SHORT_DSCALE_MAX
Definition: numeric.c:218

Definition at line 492 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 488 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:235
#define NUMERIC_SHORT_DSCALE_MASK
Definition: numeric.c:216
#define NUMERIC_SHORT_DSCALE_SHIFT
Definition: numeric.c:217

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

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

◆ NUMERIC_DSCALE_MAX

#define NUMERIC_DSCALE_MAX   NUMERIC_DSCALE_MASK

Definition at line 236 of file numeric.c.

Referenced by numeric_mul_opt_error().

◆ NUMERIC_EXT_FLAGBITS

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

Definition at line 204 of file numeric.c.

◆ NUMERIC_EXT_SIGN_MASK

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

Definition at line 198 of file numeric.c.

◆ 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:428
#define NUMERIC_HEADER_IS_SHORT(n)
Definition: numeric.c:184
#define VARHDRSZ
Definition: c.h:627
unsigned short uint16
Definition: c.h:440

Definition at line 185 of file numeric.c.

◆ NUMERIC_INF_SIGN_MASK

#define NUMERIC_INF_SIGN_MASK   0x2000

Definition at line 202 of file numeric.c.

Referenced by numeric_abs(), and numeric_uminus().

◆ NUMERIC_IS_INF

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

◆ NUMERIC_IS_NAN

◆ NUMERIC_IS_NINF

◆ NUMERIC_IS_PINF

◆ NUMERIC_IS_SHORT

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

Definition at line 173 of file numeric.c.

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

◆ NUMERIC_IS_SPECIAL

◆ NUMERIC_NAN

#define NUMERIC_NAN   0xC000

◆ NUMERIC_NDIGITS

◆ NUMERIC_NEG

◆ NUMERIC_NINF

#define NUMERIC_NINF   0xF000

Definition at line 201 of file numeric.c.

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

◆ NUMERIC_PINF

#define NUMERIC_PINF   0xD000

Definition at line 200 of file numeric.c.

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

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

◆ NUMERIC_SHORT_DSCALE_SHIFT

#define NUMERIC_SHORT_DSCALE_SHIFT   7

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

◆ NUMERIC_SHORT_WEIGHT_MIN

#define NUMERIC_SHORT_WEIGHT_MIN   (-(NUMERIC_SHORT_WEIGHT_MASK+1))

Definition at line 223 of file numeric.c.

◆ NUMERIC_SHORT_WEIGHT_SIGN_MASK

#define NUMERIC_SHORT_WEIGHT_SIGN_MASK   0x0040

Definition at line 220 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_EXT_FLAGBITS(n) : NUMERIC_FLAGBITS(n)))
#define NUMERIC_POS
Definition: numeric.c:167
#define NUMERIC_FLAGBITS(n)
Definition: numeric.c:172
#define NUMERIC_IS_SPECIAL(n)
Definition: numeric.c:174
#define NUMERIC_SHORT_SIGN_MASK
Definition: numeric.c:215
#define NUMERIC_IS_SHORT(n)
Definition: numeric.c:173

Definition at line 238 of file numeric.c.

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

◆ NUMERIC_SIGN_MASK

#define NUMERIC_SIGN_MASK   0xC000

Definition at line 166 of file numeric.c.

Referenced by make_result_opt_error().

◆ NUMERIC_SPECIAL

#define NUMERIC_SPECIAL   0xC000

Definition at line 170 of file numeric.c.

Referenced by make_result_opt_error().

◆ 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:220
#define NUMERIC_SHORT_WEIGHT_MASK
Definition: numeric.c:221

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

Referenced by numeric_cmp_abbrev().

Typedef Documentation

◆ Int8TransTypeData

◆ NumericAggState

◆ NumericDigit

Definition at line 103 of file numeric.c.

◆ NumericSumAccum

◆ NumericVar

typedef struct NumericVar NumericVar

◆ PolyNumAggState

Definition at line 5344 of file numeric.c.

Function Documentation

◆ accum_sum_add()

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

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

11023 {
11024  int32 *accum_digits;
11025  int i,
11026  val_i;
11027  int val_ndigits;
11028  NumericDigit *val_digits;
11029 
11030  /*
11031  * If we have accumulated too many values since the last carry
11032  * propagation, do it now, to avoid overflowing. (We could allow more
11033  * than NBASE - 1, if we reserved two extra digits, rather than one, for
11034  * carry propagation. But even with NBASE - 1, this needs to be done so
11035  * seldom, that the performance difference is negligible.)
11036  */
11037  if (accum->num_uncarried == NBASE - 1)
11038  accum_sum_carry(accum);
11039 
11040  /*
11041  * Adjust the weight or scale of the old value, so that it can accommodate
11042  * the new value.
11043  */
11044  accum_sum_rescale(accum, val);
11045 
11046  /* */
11047  if (val->sign == NUMERIC_POS)
11048  accum_digits = accum->pos_digits;
11049  else
11050  accum_digits = accum->neg_digits;
11051 
11052  /* copy these values into local vars for speed in loop */
11053  val_ndigits = val->ndigits;
11054  val_digits = val->digits;
11055 
11056  i = accum->weight - val->weight;
11057  for (val_i = 0; val_i < val_ndigits; val_i++)
11058  {
11059  accum_digits[i] += (int32) val_digits[val_i];
11060  i++;
11061  }
11062 
11063  accum->num_uncarried++;
11064 }
static void accum_sum_rescale(NumericSumAccum *accum, const NumericVar *val)
Definition: numeric.c:11143
#define NUMERIC_POS
Definition: numeric.c:167
int32 * neg_digits
Definition: numeric.c:380
int num_uncarried
Definition: numeric.c:377
static void accum_sum_carry(NumericSumAccum *accum)
Definition: numeric.c:11070
signed int int32
Definition: c.h:429
int16 NumericDigit
Definition: numeric.c:103
#define NBASE
Definition: numeric.c:97
int i
int32 * pos_digits
Definition: numeric.c:379
long val
Definition: informix.c:664

◆ accum_sum_carry()

static void accum_sum_carry ( NumericSumAccum accum)
static

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

11071 {
11072  int i;
11073  int ndigits;
11074  int32 *dig;
11075  int32 carry;
11076  int32 newdig = 0;
11077 
11078  /*
11079  * If no new values have been added since last carry propagation, nothing
11080  * to do.
11081  */
11082  if (accum->num_uncarried == 0)
11083  return;
11084 
11085  /*
11086  * We maintain that the weight of the accumulator is always one larger
11087  * than needed to hold the current value, before carrying, to make sure
11088  * there is enough space for the possible extra digit when carry is
11089  * propagated. We cannot expand the buffer here, unless we require
11090  * callers of accum_sum_final() to switch to the right memory context.
11091  */
11092  Assert(accum->pos_digits[0] == 0 && accum->neg_digits[0] == 0);
11093 
11094  ndigits = accum->ndigits;
11095 
11096  /* Propagate carry in the positive sum */
11097  dig = accum->pos_digits;
11098  carry = 0;
11099  for (i = ndigits - 1; i >= 0; i--)
11100  {
11101  newdig = dig[i] + carry;
11102  if (newdig >= NBASE)
11103  {
11104  carry = newdig / NBASE;
11105  newdig -= carry * NBASE;
11106  }
11107  else
11108  carry = 0;
11109  dig[i] = newdig;
11110  }
11111  /* Did we use up the digit reserved for carry propagation? */
11112  if (newdig > 0)
11113  accum->have_carry_space = false;
11114 
11115  /* And the same for the negative sum */
11116  dig = accum->neg_digits;
11117  carry = 0;
11118  for (i = ndigits - 1; i >= 0; i--)
11119  {
11120  newdig = dig[i] + carry;
11121  if (newdig >= NBASE)
11122  {
11123  carry = newdig / NBASE;
11124  newdig -= carry * NBASE;
11125  }
11126  else
11127  carry = 0;
11128  dig[i] = newdig;
11129  }
11130  if (newdig > 0)
11131  accum->have_carry_space = false;
11132 
11133  accum->num_uncarried = 0;
11134 }
int32 * neg_digits
Definition: numeric.c:380
int num_uncarried
Definition: numeric.c:377
signed int int32
Definition: c.h:429
bool have_carry_space
Definition: numeric.c:378
#define NBASE
Definition: numeric.c:97
#define Assert(condition)
Definition: c.h:804
int i
int32 * pos_digits
Definition: numeric.c:379

◆ accum_sum_combine()

static void accum_sum_combine ( NumericSumAccum accum,
NumericSumAccum accum2 
)
static

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

11301 {
11302  NumericVar tmp_var;
11303 
11304  init_var(&tmp_var);
11305 
11306  accum_sum_final(accum2, &tmp_var);
11307  accum_sum_add(accum, &tmp_var);
11308 
11309  free_var(&tmp_var);
11310 }
static void accum_sum_final(NumericSumAccum *accum, NumericVar *result)
Definition: numeric.c:11232
static void accum_sum_add(NumericSumAccum *accum, const NumericVar *var1)
Definition: numeric.c:11022
static void free_var(NumericVar *var)
Definition: numeric.c:6773
#define init_var(v)
Definition: numeric.c:486

◆ accum_sum_copy()

static void accum_sum_copy ( NumericSumAccum dst,
NumericSumAccum src 
)
static

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

11284 {
11285  dst->pos_digits = palloc(src->ndigits * sizeof(int32));
11286  dst->neg_digits = palloc(src->ndigits * sizeof(int32));
11287 
11288  memcpy(dst->pos_digits, src->pos_digits, src->ndigits * sizeof(int32));
11289  memcpy(dst->neg_digits, src->neg_digits, src->ndigits * sizeof(int32));
11290  dst->num_uncarried = src->num_uncarried;
11291  dst->ndigits = src->ndigits;
11292  dst->weight = src->weight;
11293  dst->dscale = src->dscale;
11294 }
int32 * neg_digits
Definition: numeric.c:380
int num_uncarried
Definition: numeric.c:377
signed int int32
Definition: c.h:429
void * palloc(Size size)
Definition: mcxt.c:1062
int32 * pos_digits
Definition: numeric.c:379

◆ accum_sum_final()

static void accum_sum_final ( NumericSumAccum accum,
NumericVar result 
)
static

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

11233 {
11234  int i;
11235  NumericVar pos_var;
11236  NumericVar neg_var;
11237 
11238  if (accum->ndigits == 0)
11239  {
11240  set_var_from_var(&const_zero, result);
11241  return;
11242  }
11243 
11244  /* Perform final carry */
11245  accum_sum_carry(accum);
11246 
11247  /* Create NumericVars representing the positive and negative sums */
11248  init_var(&pos_var);
11249  init_var(&neg_var);
11250 
11251  pos_var.ndigits = neg_var.ndigits = accum->ndigits;
11252  pos_var.weight = neg_var.weight = accum->weight;
11253  pos_var.dscale = neg_var.dscale = accum->dscale;
11254  pos_var.sign = NUMERIC_POS;
11255  neg_var.sign = NUMERIC_NEG;
11256 
11257  pos_var.buf = pos_var.digits = digitbuf_alloc(accum->ndigits);
11258  neg_var.buf = neg_var.digits = digitbuf_alloc(accum->ndigits);
11259 
11260  for (i = 0; i < accum->ndigits; i++)
11261  {
11262  Assert(accum->pos_digits[i] < NBASE);
11263  pos_var.digits[i] = (int16) accum->pos_digits[i];
11264 
11265  Assert(accum->neg_digits[i] < NBASE);
11266  neg_var.digits[i] = (int16) accum->neg_digits[i];
11267  }
11268 
11269  /* And add them together */
11270  add_var(&pos_var, &neg_var, result);
11271 
11272  /* Remove leading/trailing zeroes */
11273  strip_var(result);
11274 }
signed short int16
Definition: c.h:428
int weight
Definition: numeric.c:308
#define NUMERIC_POS
Definition: numeric.c:167
static void strip_var(NumericVar *var)
Definition: numeric.c:10965
int32 * neg_digits
Definition: numeric.c:380
#define digitbuf_alloc(ndigits)
Definition: numeric.c:478
int ndigits
Definition: numeric.c:307
static void accum_sum_carry(NumericSumAccum *accum)
Definition: numeric.c:11070
int dscale
Definition: numeric.c:310
#define NUMERIC_NEG
Definition: numeric.c:168
int sign
Definition: numeric.c:309
NumericDigit * buf
Definition: numeric.c:311
#define NBASE
Definition: numeric.c:97
static const NumericVar const_zero
Definition: numeric.c:417
#define Assert(condition)
Definition: c.h:804
NumericDigit * digits
Definition: numeric.c:312
static void add_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition: numeric.c:7978
int i
static void set_var_from_var(const NumericVar *value, NumericVar *dest)
Definition: numeric.c:7023
int32 * pos_digits
Definition: numeric.c:379
#define init_var(v)
Definition: numeric.c:486

◆ accum_sum_rescale()

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

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

11144 {
11145  int old_weight = accum->weight;
11146  int old_ndigits = accum->ndigits;
11147  int accum_ndigits;
11148  int accum_weight;
11149  int accum_rscale;
11150  int val_rscale;
11151 
11152  accum_weight = old_weight;
11153  accum_ndigits = old_ndigits;
11154 
11155  /*
11156  * Does the new value have a larger weight? If so, enlarge the buffers,
11157  * and shift the existing value to the new weight, by adding leading
11158  * zeros.
11159  *
11160  * We enforce that the accumulator always has a weight one larger than
11161  * needed for the inputs, so that we have space for an extra digit at the
11162  * final carry-propagation phase, if necessary.
11163  */
11164  if (val->weight >= accum_weight)
11165  {
11166  accum_weight = val->weight + 1;
11167  accum_ndigits = accum_ndigits + (accum_weight - old_weight);
11168  }
11169 
11170  /*
11171  * Even though the new value is small, we might've used up the space
11172  * reserved for the carry digit in the last call to accum_sum_carry(). If
11173  * so, enlarge to make room for another one.
11174  */
11175  else if (!accum->have_carry_space)
11176  {
11177  accum_weight++;
11178  accum_ndigits++;
11179  }
11180 
11181  /* Is the new value wider on the right side? */
11182  accum_rscale = accum_ndigits - accum_weight - 1;
11183  val_rscale = val->ndigits - val->weight - 1;
11184  if (val_rscale > accum_rscale)
11185  accum_ndigits = accum_ndigits + (val_rscale - accum_rscale);
11186 
11187  if (accum_ndigits != old_ndigits ||
11188  accum_weight != old_weight)
11189  {
11190  int32 *new_pos_digits;
11191  int32 *new_neg_digits;
11192  int weightdiff;
11193 
11194  weightdiff = accum_weight - old_weight;
11195 
11196  new_pos_digits = palloc0(accum_ndigits * sizeof(int32));
11197  new_neg_digits = palloc0(accum_ndigits * sizeof(int32));
11198 
11199  if (accum->pos_digits)
11200  {
11201  memcpy(&new_pos_digits[weightdiff], accum->pos_digits,
11202  old_ndigits * sizeof(int32));
11203  pfree(accum->pos_digits);
11204 
11205  memcpy(&new_neg_digits[weightdiff], accum->neg_digits,
11206  old_ndigits * sizeof(int32));
11207  pfree(accum->neg_digits);
11208  }
11209 
11210  accum->pos_digits = new_pos_digits;
11211  accum->neg_digits = new_neg_digits;
11212 
11213  accum->weight = accum_weight;
11214  accum->ndigits = accum_ndigits;
11215 
11216  Assert(accum->pos_digits[0] == 0 && accum->neg_digits[0] == 0);
11217  accum->have_carry_space = true;
11218  }
11219 
11220  if (val->dscale > accum->dscale)
11221  accum->dscale = val->dscale;
11222 }
int weight
Definition: numeric.c:308
int32 * neg_digits
Definition: numeric.c:380
int ndigits
Definition: numeric.c:307
int dscale
Definition: numeric.c:310
signed int int32
Definition: c.h:429
void pfree(void *pointer)
Definition: mcxt.c:1169
bool have_carry_space
Definition: numeric.c:378
void * palloc0(Size size)
Definition: mcxt.c:1093
#define Assert(condition)
Definition: c.h:804
int32 * pos_digits
Definition: numeric.c:379

◆ accum_sum_reset()

static void accum_sum_reset ( NumericSumAccum accum)
static

Definition at line 11006 of file numeric.c.

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

Referenced by do_numeric_discard().

11007 {
11008  int i;
11009 
11010  accum->dscale = 0;
11011  for (i = 0; i < accum->ndigits; i++)
11012  {
11013  accum->pos_digits[i] = 0;
11014  accum->neg_digits[i] = 0;
11015  }
11016 }
int32 * neg_digits
Definition: numeric.c:380
int i
int32 * pos_digits
Definition: numeric.c:379

◆ add_abs()

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

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

10631 {
10632  NumericDigit *res_buf;
10633  NumericDigit *res_digits;
10634  int res_ndigits;
10635  int res_weight;
10636  int res_rscale,
10637  rscale1,
10638  rscale2;
10639  int res_dscale;
10640  int i,
10641  i1,
10642  i2;
10643  int carry = 0;
10644 
10645  /* copy these values into local vars for speed in inner loop */
10646  int var1ndigits = var1->ndigits;
10647  int var2ndigits = var2->ndigits;
10648  NumericDigit *var1digits = var1->digits;
10649  NumericDigit *var2digits = var2->digits;
10650 
10651  res_weight = Max(var1->weight, var2->weight) + 1;
10652 
10653  res_dscale = Max(var1->dscale, var2->dscale);
10654 
10655  /* Note: here we are figuring rscale in base-NBASE digits */
10656  rscale1 = var1->ndigits - var1->weight - 1;
10657  rscale2 = var2->ndigits - var2->weight - 1;
10658  res_rscale = Max(rscale1, rscale2);
10659 
10660  res_ndigits = res_rscale + res_weight + 1;
10661  if (res_ndigits <= 0)
10662  res_ndigits = 1;
10663 
10664  res_buf = digitbuf_alloc(res_ndigits + 1);
10665  res_buf[0] = 0; /* spare digit for later rounding */
10666  res_digits = res_buf + 1;
10667 
10668  i1 = res_rscale + var1->weight + 1;
10669  i2 = res_rscale + var2->weight + 1;
10670  for (i = res_ndigits - 1; i >= 0; i--)
10671  {
10672  i1--;
10673  i2--;
10674  if (i1 >= 0 && i1 < var1ndigits)
10675  carry += var1digits[i1];
10676  if (i2 >= 0 && i2 < var2ndigits)
10677  carry += var2digits[i2];
10678 
10679  if (carry >= NBASE)
10680  {
10681  res_digits[i] = carry - NBASE;
10682  carry = 1;
10683  }
10684  else
10685  {
10686  res_digits[i] = carry;
10687  carry = 0;
10688  }
10689  }
10690 
10691  Assert(carry == 0); /* else we failed to allow for carry out */
10692 
10693  digitbuf_free(result->buf);
10694  result->ndigits = res_ndigits;
10695  result->buf = res_buf;
10696  result->digits = res_digits;
10697  result->weight = res_weight;
10698  result->dscale = res_dscale;
10699 
10700  /* Remove leading/trailing zeroes */
10701  strip_var(result);
10702 }
int weight
Definition: numeric.c:308
static void strip_var(NumericVar *var)
Definition: numeric.c:10965
#define digitbuf_alloc(ndigits)
Definition: numeric.c:478
int ndigits
Definition: numeric.c:307
int dscale
Definition: numeric.c:310
#define digitbuf_free(buf)
Definition: numeric.c:480
int16 NumericDigit
Definition: numeric.c:103
NumericDigit * buf
Definition: numeric.c:311
#define NBASE
Definition: numeric.c:97
#define Assert(condition)
Definition: c.h:804
NumericDigit * digits
Definition: numeric.c:312
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 7978 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().

7979 {
7980  /*
7981  * Decide on the signs of the two variables what to do
7982  */
7983  if (var1->sign == NUMERIC_POS)
7984  {
7985  if (var2->sign == NUMERIC_POS)
7986  {
7987  /*
7988  * Both are positive result = +(ABS(var1) + ABS(var2))
7989  */
7990  add_abs(var1, var2, result);
7991  result->sign = NUMERIC_POS;
7992  }
7993  else
7994  {
7995  /*
7996  * var1 is positive, var2 is negative Must compare absolute values
7997  */
7998  switch (cmp_abs(var1, var2))
7999  {
8000  case 0:
8001  /* ----------
8002  * ABS(var1) == ABS(var2)
8003  * result = ZERO
8004  * ----------
8005  */
8006  zero_var(result);
8007  result->dscale = Max(var1->dscale, var2->dscale);
8008  break;
8009 
8010  case 1:
8011  /* ----------
8012  * ABS(var1) > ABS(var2)
8013  * result = +(ABS(var1) - ABS(var2))
8014  * ----------
8015  */
8016  sub_abs(var1, var2, result);
8017  result->sign = NUMERIC_POS;
8018  break;
8019 
8020  case -1:
8021  /* ----------
8022  * ABS(var1) < ABS(var2)
8023  * result = -(ABS(var2) - ABS(var1))
8024  * ----------
8025  */
8026  sub_abs(var2, var1, result);
8027  result->sign = NUMERIC_NEG;
8028  break;
8029  }
8030  }
8031  }
8032  else
8033  {
8034  if (var2->sign == NUMERIC_POS)
8035  {
8036  /* ----------
8037  * var1 is negative, var2 is positive
8038  * Must compare absolute values
8039  * ----------
8040  */
8041  switch (cmp_abs(var1, var2))
8042  {
8043  case 0:
8044  /* ----------
8045  * ABS(var1) == ABS(var2)
8046  * result = ZERO
8047  * ----------
8048  */
8049  zero_var(result);
8050  result->dscale = Max(var1->dscale, var2->dscale);
8051  break;
8052 
8053  case 1:
8054  /* ----------
8055  * ABS(var1) > ABS(var2)
8056  * result = -(ABS(var1) - ABS(var2))
8057  * ----------
8058  */
8059  sub_abs(var1, var2, result);
8060  result->sign = NUMERIC_NEG;
8061  break;
8062 
8063  case -1:
8064  /* ----------
8065  * ABS(var1) < ABS(var2)
8066  * result = +(ABS(var2) - ABS(var1))
8067  * ----------
8068  */
8069  sub_abs(var2, var1, result);
8070  result->sign = NUMERIC_POS;
8071  break;
8072  }
8073  }
8074  else
8075  {
8076  /* ----------
8077  * Both are negative
8078  * result = -(ABS(var1) + ABS(var2))
8079  * ----------
8080  */
8081  add_abs(var1, var2, result);
8082  result->sign = NUMERIC_NEG;
8083  }
8084  }
8085 }
static void sub_abs(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition: numeric.c:10715
static void add_abs(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition: numeric.c:10630
#define NUMERIC_POS
Definition: numeric.c:167
int dscale
Definition: numeric.c:310
#define NUMERIC_NEG
Definition: numeric.c:168
int sign
Definition: numeric.c:309
static void zero_var(NumericVar *var)
Definition: numeric.c:6789
static int cmp_abs(const NumericVar *var1, const NumericVar *var2)
Definition: numeric.c:10552
#define Max(x, y)
Definition: numeric.c:13

◆ alloc_var()

static void alloc_var ( NumericVar var,
int  ndigits 
)
static

Definition at line 6757 of file numeric.c.

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

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

6758 {
6759  digitbuf_free(var->buf);
6760  var->buf = digitbuf_alloc(ndigits + 1);
6761  var->buf[0] = 0; /* spare digit for rounding */
6762  var->digits = var->buf + 1;
6763  var->ndigits = ndigits;
6764 }
#define digitbuf_alloc(ndigits)
Definition: numeric.c:478
int ndigits
Definition: numeric.c:307
#define digitbuf_free(buf)
Definition: numeric.c:480
NumericDigit * buf
Definition: numeric.c:311
NumericDigit * digits
Definition: numeric.c:312

◆ apply_typmod()

static void apply_typmod ( NumericVar var,
int32  typmod 
)
static

Definition at line 7459 of file numeric.c.

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

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

7460 {
7461  int precision;
7462  int scale;
7463  int maxdigits;
7464  int ddigits;
7465  int i;
7466 
7467  /* Do nothing if we have an invalid typmod */
7468  if (!is_valid_numeric_typmod(typmod))
7469  return;
7470 
7471  precision = numeric_typmod_precision(typmod);
7472  scale = numeric_typmod_scale(typmod);
7473  maxdigits = precision - scale;
7474 
7475  /* Round to target scale (and set var->dscale) */
7476  round_var(var, scale);
7477 
7478  /* but don't allow var->dscale to be negative */
7479  if (var->dscale < 0)
7480  var->dscale = 0;
7481 
7482  /*
7483  * Check for overflow - note we can't do this before rounding, because
7484  * rounding could raise the weight. Also note that the var's weight could
7485  * be inflated by leading zeroes, which will be stripped before storage
7486  * but perhaps might not have been yet. In any case, we must recognize a
7487  * true zero, whose weight doesn't mean anything.
7488  */
7489  ddigits = (var->weight + 1) * DEC_DIGITS;
7490  if (ddigits > maxdigits)
7491  {
7492  /* Determine true weight; and check for all-zero result */
7493  for (i = 0; i < var->ndigits; i++)
7494  {
7495  NumericDigit dig = var->digits[i];
7496 
7497  if (dig)
7498  {
7499  /* Adjust for any high-order decimal zero digits */
7500 #if DEC_DIGITS == 4
7501  if (dig < 10)
7502  ddigits -= 3;
7503  else if (dig < 100)
7504  ddigits -= 2;
7505  else if (dig < 1000)
7506  ddigits -= 1;
7507 #elif DEC_DIGITS == 2
7508  if (dig < 10)
7509  ddigits -= 1;
7510 #elif DEC_DIGITS == 1
7511  /* no adjustment */
7512 #else
7513 #error unsupported NBASE
7514 #endif
7515  if (ddigits > maxdigits)
7516  ereport(ERROR,
7517  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
7518  errmsg("numeric field overflow"),
7519  errdetail("A field with precision %d, scale %d must round to an absolute value less than %s%d.",
7520  precision, scale,
7521  /* Display 10^0 as 1 */
7522  maxdigits ? "10^" : "",
7523  maxdigits ? maxdigits : 1
7524  )));
7525  break;
7526  }
7527  ddigits -= DEC_DIGITS;
7528  }
7529  }
7530 }
static void round_var(NumericVar *var, int rscale)
Definition: numeric.c:10797
int weight
Definition: numeric.c:308
int errcode(int sqlerrcode)
Definition: elog.c:698
int scale
Definition: pgbench.c:191
int ndigits
Definition: numeric.c:307
int dscale
Definition: numeric.c:310
static bool is_valid_numeric_typmod(int32 typmod)
Definition: numeric.c:834
#define ERROR
Definition: elog.h:46
int16 NumericDigit
Definition: numeric.c:103
int errdetail(const char *fmt,...)
Definition: elog.c:1042
static int numeric_typmod_scale(int32 typmod)
Definition: numeric.c:860
#define ereport(elevel,...)
Definition: elog.h:157
int maxdigits
Definition: informix.c:665
NumericDigit * digits
Definition: numeric.c:312
int errmsg(const char *fmt,...)
Definition: elog.c:909
int i
#define DEC_DIGITS
Definition: numeric.c:99
static int numeric_typmod_precision(int32 typmod)
Definition: numeric.c:845

◆ apply_typmod_special()

static void apply_typmod_special ( Numeric  num,
int32  typmod 
)
static

Definition at line 7539 of file numeric.c.

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

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

7540 {
7541  int precision;
7542  int scale;
7543 
7544  Assert(NUMERIC_IS_SPECIAL(num)); /* caller error if not */
7545 
7546  /*
7547  * NaN is allowed regardless of the typmod; that's rather dubious perhaps,
7548  * but it's a longstanding behavior. Inf is rejected if we have any
7549  * typmod restriction, since an infinity shouldn't be claimed to fit in
7550  * any finite number of digits.
7551  */
7552  if (NUMERIC_IS_NAN(num))
7553  return;
7554 
7555  /* Do nothing if we have a default typmod (-1) */
7556  if (!is_valid_numeric_typmod(typmod))
7557  return;
7558 
7559  precision = numeric_typmod_precision(typmod);
7560  scale = numeric_typmod_scale(typmod);
7561 
7562  ereport(ERROR,
7563  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
7564  errmsg("numeric field overflow"),
7565  errdetail("A field with precision %d, scale %d cannot hold an infinite value.",
7566  precision, scale)));
7567 }
int errcode(int sqlerrcode)
Definition: elog.c:698
int scale
Definition: pgbench.c:191
static bool is_valid_numeric_typmod(int32 typmod)
Definition: numeric.c:834
#define NUMERIC_IS_SPECIAL(n)
Definition: numeric.c:174
#define ERROR
Definition: elog.h:46
int errdetail(const char *fmt,...)
Definition: elog.c:1042
static int numeric_typmod_scale(int32 typmod)
Definition: numeric.c:860
#define ereport(elevel,...)
Definition: elog.h:157
#define Assert(condition)
Definition: c.h:804
int errmsg(const char *fmt,...)
Definition: elog.c:909
#define NUMERIC_IS_NAN(n)
Definition: numeric.c:205
static int numeric_typmod_precision(int32 typmod)
Definition: numeric.c:845

◆ ceil_var()

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

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

9184 {
9185  NumericVar tmp;
9186 
9187  init_var(&tmp);
9188  set_var_from_var(var, &tmp);
9189 
9190  trunc_var(&tmp, 0);
9191 
9192  if (var->sign == NUMERIC_POS && cmp_var(var, &tmp) != 0)
9193  add_var(&tmp, &const_one, &tmp);
9194 
9195  set_var_from_var(&tmp, result);
9196  free_var(&tmp);
9197 }
static void trunc_var(NumericVar *var, int rscale)
Definition: numeric.c:10903
static const NumericVar const_one
Definition: numeric.c:421
#define NUMERIC_POS
Definition: numeric.c:167
int sign
Definition: numeric.c:309
static int cmp_var(const NumericVar *var1, const NumericVar *var2)
Definition: numeric.c:7920
static void free_var(NumericVar *var)
Definition: numeric.c:6773
static void add_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition: numeric.c:7978
static void set_var_from_var(const NumericVar *value, NumericVar *dest)
Definition: numeric.c:7023
#define init_var(v)
Definition: numeric.c:486

◆ cmp_abs()

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

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

10553 {
10554  return cmp_abs_common(var1->digits, var1->ndigits, var1->weight,
10555  var2->digits, var2->ndigits, var2->weight);
10556 }
int weight
Definition: numeric.c:308
int ndigits
Definition: numeric.c:307
NumericDigit * digits
Definition: numeric.c:312
static int cmp_abs_common(const NumericDigit *var1digits, int var1ndigits, int var1weight, const NumericDigit *var2digits, int var2ndigits, int var2weight)
Definition: numeric.c:10566

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

Referenced by cmp_abs(), and cmp_var_common().

10568 {
10569  int i1 = 0;
10570  int i2 = 0;
10571 
10572  /* Check any digits before the first common digit */
10573 
10574  while (var1weight > var2weight && i1 < var1ndigits)
10575  {
10576  if (var1digits[i1++] != 0)
10577  return 1;
10578  var1weight--;
10579  }
10580  while (var2weight > var1weight && i2 < var2ndigits)
10581  {
10582  if (var2digits[i2++] != 0)
10583  return -1;
10584  var2weight--;
10585  }
10586 
10587  /* At this point, either w1 == w2 or we've run out of digits */
10588 
10589  if (var1weight == var2weight)
10590  {
10591  while (i1 < var1ndigits && i2 < var2ndigits)
10592  {
10593  int stat = var1digits[i1++] - var2digits[i2++];
10594 
10595  if (stat)
10596  {
10597  if (stat > 0)
10598  return 1;
10599  return -1;
10600  }
10601  }
10602  }
10603 
10604  /*
10605  * At this point, we've run out of digits on one side or the other; so any
10606  * remaining nonzero digits imply that side is larger
10607  */
10608  while (i1 < var1ndigits)
10609  {
10610  if (var1digits[i1++] != 0)
10611  return 1;
10612  }
10613  while (i2 < var2ndigits)
10614  {
10615  if (var2digits[i2++] != 0)
10616  return -1;
10617  }
10618 
10619  return 0;
10620 }

◆ cmp_numerics()

static int cmp_numerics ( Numeric  num1,
Numeric  num2 
)
static

Definition at line 2421 of file numeric.c.

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

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

2422 {
2423  int result;
2424 
2425  /*
2426  * We consider all NANs to be equal and larger than any non-NAN (including
2427  * Infinity). This is somewhat arbitrary; the important thing is to have
2428  * a consistent sort order.
2429  */
2430  if (NUMERIC_IS_SPECIAL(num1))
2431  {
2432  if (NUMERIC_IS_NAN(num1))
2433  {
2434  if (NUMERIC_IS_NAN(num2))
2435  result = 0; /* NAN = NAN */
2436  else
2437  result = 1; /* NAN > non-NAN */
2438  }
2439  else if (NUMERIC_IS_PINF(num1))
2440  {
2441  if (NUMERIC_IS_NAN(num2))
2442  result = -1; /* PINF < NAN */
2443  else if (NUMERIC_IS_PINF(num2))
2444  result = 0; /* PINF = PINF */
2445  else
2446  result = 1; /* PINF > anything else */
2447  }
2448  else /* num1 must be NINF */
2449  {
2450  if (NUMERIC_IS_NINF(num2))
2451  result = 0; /* NINF = NINF */
2452  else
2453  result = -1; /* NINF < anything else */
2454  }
2455  }
2456  else if (NUMERIC_IS_SPECIAL(num2))
2457  {
2458  if (NUMERIC_IS_NINF(num2))
2459  result = 1; /* normal > NINF */
2460  else
2461  result = -1; /* normal < NAN or PINF */
2462  }
2463  else
2464  {
2465  result = cmp_var_common(NUMERIC_DIGITS(num1), NUMERIC_NDIGITS(num1),
2466  NUMERIC_WEIGHT(num1), NUMERIC_SIGN(num1),
2467  NUMERIC_DIGITS(num2), NUMERIC_NDIGITS(num2),
2468  NUMERIC_WEIGHT(num2), NUMERIC_SIGN(num2));
2469  }
2470 
2471  return result;
2472 }
#define NUMERIC_IS_SPECIAL(n)
Definition: numeric.c:174
#define NUMERIC_DIGITS(num)
Definition: numeric.c:488
#define NUMERIC_IS_PINF(n)
Definition: numeric.c:206
#define NUMERIC_SIGN(n)
Definition: numeric.c:238
#define NUMERIC_NDIGITS(num)
Definition: numeric.c:490
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:7935
#define NUMERIC_WEIGHT(n)
Definition: numeric.c:248
#define NUMERIC_IS_NINF(n)
Definition: numeric.c:207
#define NUMERIC_IS_NAN(n)
Definition: numeric.c:205

◆ cmp_var()

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

Definition at line 7920 of file numeric.c.

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

Referenced by ceil_var(), 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().

7921 {
7922  return cmp_var_common(var1->digits, var1->ndigits,
7923  var1->weight, var1->sign,
7924  var2->digits, var2->ndigits,
7925  var2->weight, var2->sign);
7926 }
int weight
Definition: numeric.c:308
int ndigits
Definition: numeric.c:307
int sign
Definition: numeric.c:309
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:7935
NumericDigit * digits
Definition: numeric.c:312

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

References cmp_abs_common(), NUMERIC_NEG, and NUMERIC_POS.

Referenced by cmp_numerics(), and cmp_var().

7939 {
7940  if (var1ndigits == 0)
7941  {
7942  if (var2ndigits == 0)
7943  return 0;
7944  if (var2sign == NUMERIC_NEG)
7945  return 1;
7946  return -1;
7947  }
7948  if (var2ndigits == 0)
7949  {
7950  if (var1sign == NUMERIC_POS)
7951  return 1;
7952  return -1;
7953  }
7954 
7955  if (var1sign == NUMERIC_POS)
7956  {
7957  if (var2sign == NUMERIC_NEG)
7958  return 1;
7959  return cmp_abs_common(var1digits, var1ndigits, var1weight,
7960  var2digits, var2ndigits, var2weight);
7961  }
7962 
7963  if (var2sign == NUMERIC_POS)
7964  return -1;
7965 
7966  return cmp_abs_common(var2digits, var2ndigits, var2weight,
7967  var1digits, var1ndigits, var1weight);
7968 }
#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:10566

◆ compute_bucket()

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

Definition at line 1844 of file numeric.c.

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

1847 {
1848  NumericVar bound1_var;
1849  NumericVar bound2_var;
1850  NumericVar operand_var;
1851 
1852  init_var_from_num(bound1, &bound1_var);
1853  init_var_from_num(bound2, &bound2_var);
1854  init_var_from_num(operand, &operand_var);
1855 
1856  if (!reversed_bounds)
1857  {
1858  sub_var(&operand_var, &bound1_var, &operand_var);
1859  sub_var(&bound2_var, &bound1_var, &bound2_var);
1860  }
1861  else
1862  {
1863  sub_var(&bound1_var, &operand_var, &operand_var);
1864  sub_var(&bound1_var, &bound2_var, &bound2_var);
1865  }
1866 
1867  mul_var(&operand_var, count_var, &operand_var,
1868  operand_var.dscale + count_var->dscale);
1869  div_var(&operand_var, &bound2_var, result_var,
1870  select_div_scale(&operand_var, &bound2_var), true);
1871  add_var(result_var, &const_one, result_var);
1872  floor_var(result_var, result_var);
1873 
1874  free_var(&bound1_var);
1875  free_var(&bound2_var);
1876  free_var(&operand_var);
1877 }
static const NumericVar const_one
Definition: numeric.c:421
static void div_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result, int rscale, bool round)
Definition: numeric.c:8424
int dscale
Definition: numeric.c:310
static int select_div_scale(const NumericVar *var1, const NumericVar *var2)
Definition: numeric.c:9015
static void init_var_from_num(Numeric num, NumericVar *dest)
Definition: numeric.c:7006
static void free_var(NumericVar *var)
Definition: numeric.c:6773
static void mul_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result, int rscale)
Definition: numeric.c:8216
static void add_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition: numeric.c:7978
static void sub_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition: numeric.c:8095
static void floor_var(const NumericVar *var, NumericVar *result)
Definition: numeric.c:9207

◆ div_mod_var()

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

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

9115 {
9116  NumericVar q;
9117  NumericVar r;
9118 
9119  init_var(&q);
9120  init_var(&r);
9121 
9122  /*
9123  * Use div_var_fast() to get an initial estimate for the integer quotient.
9124  * This might be inaccurate (per the warning in div_var_fast's comments),
9125  * but we can correct it below.
9126  */
9127  div_var_fast(var1, var2, &q, 0, false);
9128 
9129  /* Compute initial estimate of remainder using the quotient estimate. */
9130  mul_var(var2, &q, &r, var2->dscale);
9131  sub_var(var1, &r, &r);
9132 
9133  /*
9134  * Adjust the results if necessary --- the remainder should have the same
9135  * sign as var1, and its absolute value should be less than the absolute
9136  * value of var2.
9137  */
9138  while (r.ndigits != 0 && r.sign != var1->sign)
9139  {
9140  /* The absolute value of the quotient is too large */
9141  if (var1->sign == var2->sign)
9142  {
9143  sub_var(&q, &const_one, &q);
9144  add_var(&r, var2, &r);
9145  }
9146  else
9147  {
9148  add_var(&q, &const_one, &q);
9149  sub_var(&r, var2, &r);
9150  }
9151  }
9152 
9153  while (cmp_abs(&r, var2) >= 0)
9154  {
9155  /* The absolute value of the quotient is too small */
9156  if (var1->sign == var2->sign)
9157  {
9158  add_var(&q, &const_one, &q);
9159  sub_var(&r, var2, &r);
9160  }
9161  else
9162  {
9163  sub_var(&q, &const_one, &q);
9164  add_var(&r, var2, &r);
9165  }
9166  }
9167 
9168  set_var_from_var(&q, quot);
9169  set_var_from_var(&r, rem);
9170 
9171  free_var(&q);
9172  free_var(&r);
9173 }
static const NumericVar const_one
Definition: numeric.c:421
int ndigits
Definition: numeric.c:307
int dscale
Definition: numeric.c:310
int sign
Definition: numeric.c:309
static void div_var_fast(const NumericVar *var1, const NumericVar *var2, NumericVar *result, int rscale, bool round)
Definition: numeric.c:8709
static void free_var(NumericVar *var)
Definition: numeric.c:6773
static void mul_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result, int rscale)
Definition: numeric.c:8216
static void add_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition: numeric.c:7978
static int cmp_abs(const NumericVar *var1, const NumericVar *var2)
Definition: numeric.c:10552
static void sub_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition: numeric.c:8095
static void set_var_from_var(const NumericVar *value, NumericVar *dest)
Definition: numeric.c:7023
#define init_var(v)
Definition: numeric.c:486

◆ div_var()

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

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

8426 {
8427  int div_ndigits;
8428  int res_ndigits;
8429  int res_sign;
8430  int res_weight;
8431  int carry;
8432  int borrow;
8433  int divisor1;
8434  int divisor2;
8435  NumericDigit *dividend;
8436  NumericDigit *divisor;
8437  NumericDigit *res_digits;
8438  int i;
8439  int j;
8440 
8441  /* copy these values into local vars for speed in inner loop */
8442  int var1ndigits = var1->ndigits;
8443  int var2ndigits = var2->ndigits;
8444 
8445  /*
8446  * First of all division by zero check; we must not be handed an
8447  * unnormalized divisor.
8448  */
8449  if (var2ndigits == 0 || var2->digits[0] == 0)
8450  ereport(ERROR,
8451  (errcode(ERRCODE_DIVISION_BY_ZERO),
8452  errmsg("division by zero")));
8453 
8454  /*
8455  * Now result zero check
8456  */
8457  if (var1ndigits == 0)
8458  {
8459  zero_var(result);
8460  result->dscale = rscale;
8461  return;
8462  }
8463 
8464  /*
8465  * Determine the result sign, weight and number of digits to calculate.
8466  * The weight figured here is correct if the emitted quotient has no
8467  * leading zero digits; otherwise strip_var() will fix things up.
8468  */
8469  if (var1->sign == var2->sign)
8470  res_sign = NUMERIC_POS;
8471  else
8472  res_sign = NUMERIC_NEG;
8473  res_weight = var1->weight - var2->weight;
8474  /* The number of accurate result digits we need to produce: */
8475  res_ndigits = res_weight + 1 + (rscale + DEC_DIGITS - 1) / DEC_DIGITS;
8476  /* ... but always at least 1 */
8477  res_ndigits = Max(res_ndigits, 1);
8478  /* If rounding needed, figure one more digit to ensure correct result */
8479  if (round)
8480  res_ndigits++;
8481 
8482  /*
8483  * The working dividend normally requires res_ndigits + var2ndigits
8484  * digits, but make it at least var1ndigits so we can load all of var1
8485  * into it. (There will be an additional digit dividend[0] in the
8486  * dividend space, but for consistency with Knuth's notation we don't
8487  * count that in div_ndigits.)
8488  */
8489  div_ndigits = res_ndigits + var2ndigits;
8490  div_ndigits = Max(div_ndigits, var1ndigits);
8491 
8492  /*
8493  * We need a workspace with room for the working dividend (div_ndigits+1
8494  * digits) plus room for the possibly-normalized divisor (var2ndigits
8495  * digits). It is convenient also to have a zero at divisor[0] with the
8496  * actual divisor data in divisor[1 .. var2ndigits]. Transferring the
8497  * digits into the workspace also allows us to realloc the result (which
8498  * might be the same as either input var) before we begin the main loop.
8499  * Note that we use palloc0 to ensure that divisor[0], dividend[0], and
8500  * any additional dividend positions beyond var1ndigits, start out 0.
8501  */
8502  dividend = (NumericDigit *)
8503  palloc0((div_ndigits + var2ndigits + 2) * sizeof(NumericDigit));
8504  divisor = dividend + (div_ndigits + 1);
8505  memcpy(dividend + 1, var1->digits, var1ndigits * sizeof(NumericDigit));
8506  memcpy(divisor + 1, var2->digits, var2ndigits * sizeof(NumericDigit));
8507 
8508  /*
8509  * Now we can realloc the result to hold the generated quotient digits.
8510  */
8511  alloc_var(result, res_ndigits);
8512  res_digits = result->digits;
8513 
8514  if (var2ndigits == 1)
8515  {
8516  /*
8517  * If there's only a single divisor digit, we can use a fast path (cf.
8518  * Knuth section 4.3.1 exercise 16).
8519  */
8520  divisor1 = divisor[1];
8521  carry = 0;
8522  for (i = 0; i < res_ndigits; i++)
8523  {
8524  carry = carry * NBASE + dividend[i + 1];
8525  res_digits[i] = carry / divisor1;
8526  carry = carry % divisor1;
8527  }
8528  }
8529  else
8530  {
8531  /*
8532  * The full multiple-place algorithm is taken from Knuth volume 2,
8533  * Algorithm 4.3.1D.
8534  *
8535  * We need the first divisor digit to be >= NBASE/2. If it isn't,
8536  * make it so by scaling up both the divisor and dividend by the
8537  * factor "d". (The reason for allocating dividend[0] above is to
8538  * leave room for possible carry here.)
8539  */
8540  if (divisor[1] < HALF_NBASE)
8541  {
8542  int d = NBASE / (divisor[1] + 1);
8543 
8544  carry = 0;
8545  for (i = var2ndigits; i > 0; i--)
8546  {
8547  carry += divisor[i] * d;
8548  divisor[i] = carry % NBASE;
8549  carry = carry / NBASE;
8550  }
8551  Assert(carry == 0);
8552  carry = 0;
8553  /* at this point only var1ndigits of dividend can be nonzero */
8554  for (i = var1ndigits; i >= 0; i--)
8555  {
8556  carry += dividend[i] * d;
8557  dividend[i] = carry % NBASE;
8558  carry = carry / NBASE;
8559  }
8560  Assert(carry == 0);
8561  Assert(divisor[1] >= HALF_NBASE);
8562  }
8563  /* First 2 divisor digits are used repeatedly in main loop */
8564  divisor1 = divisor[1];
8565  divisor2 = divisor[2];
8566 
8567  /*
8568  * Begin the main loop. Each iteration of this loop produces the j'th
8569  * quotient digit by dividing dividend[j .. j + var2ndigits] by the
8570  * divisor; this is essentially the same as the common manual
8571  * procedure for long division.
8572  */
8573  for (j = 0; j < res_ndigits; j++)
8574  {
8575  /* Estimate quotient digit from the first two dividend digits */
8576  int next2digits = dividend[j] * NBASE + dividend[j + 1];
8577  int qhat;
8578 
8579  /*
8580  * If next2digits are 0, then quotient digit must be 0 and there's
8581  * no need to adjust the working dividend. It's worth testing
8582  * here to fall out ASAP when processing trailing zeroes in a
8583  * dividend.
8584  */
8585  if (next2digits == 0)
8586  {
8587  res_digits[j] = 0;
8588  continue;
8589  }
8590 
8591  if (dividend[j] == divisor1)
8592  qhat = NBASE - 1;
8593  else
8594  qhat = next2digits / divisor1;
8595 
8596  /*
8597  * Adjust quotient digit if it's too large. Knuth proves that
8598  * after this step, the quotient digit will be either correct or
8599  * just one too large. (Note: it's OK to use dividend[j+2] here
8600  * because we know the divisor length is at least 2.)
8601  */
8602  while (divisor2 * qhat >
8603  (next2digits - qhat * divisor1) * NBASE + dividend[j + 2])
8604  qhat--;
8605 
8606  /* As above, need do nothing more when quotient digit is 0 */
8607  if (qhat > 0)
8608  {
8609  /*
8610  * Multiply the divisor by qhat, and subtract that from the
8611  * working dividend. "carry" tracks the multiplication,
8612  * "borrow" the subtraction (could we fold these together?)
8613  */
8614  carry = 0;
8615  borrow = 0;
8616  for (i = var2ndigits; i >= 0; i--)
8617  {
8618  carry += divisor[i] * qhat;
8619  borrow -= carry % NBASE;
8620  carry = carry / NBASE;
8621  borrow += dividend[j + i];
8622  if (borrow < 0)
8623  {
8624  dividend[j + i] = borrow + NBASE;
8625  borrow = -1;
8626  }
8627  else
8628  {
8629  dividend[j + i] = borrow;
8630  borrow = 0;
8631  }
8632  }
8633  Assert(carry == 0);
8634 
8635  /*
8636  * If we got a borrow out of the top dividend digit, then
8637  * indeed qhat was one too large. Fix it, and add back the
8638  * divisor to correct the working dividend. (Knuth proves
8639  * that this will occur only about 3/NBASE of the time; hence,
8640  * it's a good idea to test this code with small NBASE to be
8641  * sure this section gets exercised.)
8642  */
8643  if (borrow)
8644  {
8645  qhat--;
8646  carry = 0;
8647  for (i = var2ndigits; i >= 0; i--)
8648  {
8649  carry += dividend[j + i] + divisor[i];
8650  if (carry >= NBASE)
8651  {
8652  dividend[j + i] = carry - NBASE;
8653  carry = 1;
8654  }
8655  else
8656  {
8657  dividend[j + i] = carry;
8658  carry = 0;
8659  }
8660  }
8661  /* A carry should occur here to cancel the borrow above */
8662  Assert(carry == 1);
8663  }
8664  }
8665 
8666  /* And we're done with this quotient digit */
8667  res_digits[j] = qhat;
8668  }
8669  }
8670 
8671  pfree(dividend);
8672 
8673  /*
8674  * Finally, round or truncate the result to the requested precision.
8675  */
8676  result->weight = res_weight;
8677  result->sign = res_sign;
8678 
8679  /* Round or truncate to target rscale (and set result->dscale) */
8680  if (round)
8681  round_var(result, rscale);
8682  else
8683  trunc_var(result, rscale);
8684 
8685  /* Strip leading and trailing zeroes */
8686  strip_var(result);
8687 }
static void round_var(NumericVar *var, int rscale)
Definition: numeric.c:10797
static void trunc_var(NumericVar *var, int rscale)
Definition: numeric.c:10903
int weight
Definition: numeric.c:308
#define NUMERIC_POS
Definition: numeric.c:167
static void strip_var(NumericVar *var)
Definition: numeric.c:10965
int errcode(int sqlerrcode)
Definition: elog.c:698
int ndigits
Definition: numeric.c:307
int dscale
Definition: numeric.c:310
#define NUMERIC_NEG
Definition: numeric.c:168
int sign
Definition: numeric.c:309
static void zero_var(NumericVar *var)
Definition: numeric.c:6789
void pfree(void *pointer)
Definition: mcxt.c:1169
#define ERROR
Definition: elog.h:46
int16 NumericDigit
Definition: numeric.c:103
#define HALF_NBASE
Definition: numeric.c:98
#define NBASE
Definition: numeric.c:97
void * palloc0(Size size)
Definition: mcxt.c:1093
#define ereport(elevel,...)
Definition: elog.h:157
#define Assert(condition)
Definition: c.h:804
NumericDigit * digits
Definition: numeric.c:312
int errmsg(const char *fmt,...)
Definition: elog.c:909
static void alloc_var(NumericVar *var, int ndigits)
Definition: numeric.c:6757
int i
#define Max(x, y)
Definition: numeric.c:13
#define DEC_DIGITS
Definition: numeric.c:99

◆ div_var_fast()

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

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

8711 {
8712  int div_ndigits;
8713  int load_ndigits;
8714  int res_sign;
8715  int res_weight;
8716  int *div;
8717  int qdigit;
8718  int carry;
8719  int maxdiv;
8720  int newdig;
8721  NumericDigit *res_digits;
8722  double fdividend,
8723  fdivisor,
8724  fdivisorinverse,
8725  fquotient;
8726  int qi;
8727  int i;
8728 
8729  /* copy these values into local vars for speed in inner loop */
8730  int var1ndigits = var1->ndigits;
8731  int var2ndigits = var2->ndigits;
8732  NumericDigit *var1digits = var1->digits;
8733  NumericDigit *var2digits = var2->digits;
8734 
8735  /*
8736  * First of all division by zero check; we must not be handed an
8737  * unnormalized divisor.
8738  */
8739  if (var2ndigits == 0 || var2digits[0] == 0)
8740  ereport(ERROR,
8741  (errcode(ERRCODE_DIVISION_BY_ZERO),
8742  errmsg("division by zero")));
8743 
8744  /*
8745  * Now result zero check
8746  */
8747  if (var1ndigits == 0)
8748  {
8749  zero_var(result);
8750  result->dscale = rscale;
8751  return;
8752  }
8753 
8754  /*
8755  * Determine the result sign, weight and number of digits to calculate
8756  */
8757  if (var1->sign == var2->sign)
8758  res_sign = NUMERIC_POS;
8759  else
8760  res_sign = NUMERIC_NEG;
8761  res_weight = var1->weight - var2->weight + 1;
8762  /* The number of accurate result digits we need to produce: */
8763  div_ndigits = res_weight + 1 + (rscale + DEC_DIGITS - 1) / DEC_DIGITS;
8764  /* Add guard digits for roundoff error */
8765  div_ndigits += DIV_GUARD_DIGITS;
8766  if (div_ndigits < DIV_GUARD_DIGITS)
8767  div_ndigits = DIV_GUARD_DIGITS;
8768 
8769  /*
8770  * We do the arithmetic in an array "div[]" of signed int's. Since
8771  * INT_MAX is noticeably larger than NBASE*NBASE, this gives us headroom
8772  * to avoid normalizing carries immediately.
8773  *
8774  * We start with div[] containing one zero digit followed by the
8775  * dividend's digits (plus appended zeroes to reach the desired precision
8776  * including guard digits). Each step of the main loop computes an
8777  * (approximate) quotient digit and stores it into div[], removing one
8778  * position of dividend space. A final pass of carry propagation takes
8779  * care of any mistaken quotient digits.
8780  *
8781  * Note that div[] doesn't necessarily contain all of the digits from the
8782  * dividend --- the desired precision plus guard digits might be less than
8783  * the dividend's precision. This happens, for example, in the square
8784  * root algorithm, where we typically divide a 2N-digit number by an
8785  * N-digit number, and only require a result with N digits of precision.
8786  */
8787  div = (int *) palloc0((div_ndigits + 1) * sizeof(int));
8788  load_ndigits = Min(div_ndigits, var1ndigits);
8789  for (i = 0; i < load_ndigits; i++)
8790  div[i + 1] = var1digits[i];
8791 
8792  /*
8793  * We estimate each quotient digit using floating-point arithmetic, taking
8794  * the first four digits of the (current) dividend and divisor. This must
8795  * be float to avoid overflow. The quotient digits will generally be off
8796  * by no more than one from the exact answer.
8797  */
8798  fdivisor = (double) var2digits[0];
8799  for (i = 1; i < 4; i++)
8800  {
8801  fdivisor *= NBASE;
8802  if (i < var2ndigits)
8803  fdivisor += (double) var2digits[i];
8804  }
8805  fdivisorinverse = 1.0 / fdivisor;
8806 
8807  /*
8808  * maxdiv tracks the maximum possible absolute value of any div[] entry;
8809  * when this threatens to exceed INT_MAX, we take the time to propagate
8810  * carries. Furthermore, we need to ensure that overflow doesn't occur
8811  * during the carry propagation passes either. The carry values may have
8812  * an absolute value as high as INT_MAX/NBASE + 1, so really we must
8813  * normalize when digits threaten to exceed INT_MAX - INT_MAX/NBASE - 1.
8814  *
8815  * To avoid overflow in maxdiv itself, it represents the max absolute
8816  * value divided by NBASE-1, ie, at the top of the loop it is known that
8817  * no div[] entry has an absolute value exceeding maxdiv * (NBASE-1).
8818  *
8819  * Actually, though, that holds good only for div[] entries after div[qi];
8820  * the adjustment done at the bottom of the loop may cause div[qi + 1] to
8821  * exceed the maxdiv limit, so that div[qi] in the next iteration is
8822  * beyond the limit. This does not cause problems, as explained below.
8823  */
8824  maxdiv = 1;
8825 
8826  /*
8827  * Outer loop computes next quotient digit, which will go into div[qi]
8828  */
8829  for (qi = 0; qi < div_ndigits; qi++)
8830  {
8831  /* Approximate the current dividend value */
8832  fdividend = (double) div[qi];
8833  for (i = 1; i < 4; i++)
8834  {
8835  fdividend *= NBASE;
8836  if (qi + i <= div_ndigits)
8837  fdividend += (double) div[qi + i];
8838  }
8839  /* Compute the (approximate) quotient digit */
8840  fquotient = fdividend * fdivisorinverse;
8841  qdigit = (fquotient >= 0.0) ? ((int) fquotient) :
8842  (((int) fquotient) - 1); /* truncate towards -infinity */
8843 
8844  if (qdigit != 0)
8845  {
8846  /* Do we need to normalize now? */
8847  maxdiv += Abs(qdigit);
8848  if (maxdiv > (INT_MAX - INT_MAX / NBASE - 1) / (NBASE - 1))
8849  {
8850  /*
8851  * Yes, do it. Note that if var2ndigits is much smaller than
8852  * div_ndigits, we can save a significant amount of effort
8853  * here by noting that we only need to normalise those div[]
8854  * entries touched where prior iterations subtracted multiples
8855  * of the divisor.
8856  */
8857  carry = 0;
8858  for (i = Min(qi + var2ndigits - 2, div_ndigits); i > qi; i--)
8859  {
8860  newdig = div[i] + carry;
8861  if (newdig < 0)
8862  {
8863  carry = -((-newdig - 1) / NBASE) - 1;
8864  newdig -= carry * NBASE;
8865  }
8866  else if (newdig >= NBASE)
8867  {
8868  carry = newdig / NBASE;
8869  newdig -= carry * NBASE;
8870  }
8871  else
8872  carry = 0;
8873  div[i] = newdig;
8874  }
8875  newdig = div[qi] + carry;
8876  div[qi] = newdig;
8877 
8878  /*
8879  * All the div[] digits except possibly div[qi] are now in the
8880  * range 0..NBASE-1. We do not need to consider div[qi] in
8881  * the maxdiv value anymore, so we can reset maxdiv to 1.
8882  */
8883  maxdiv = 1;
8884 
8885  /*
8886  * Recompute the quotient digit since new info may have
8887  * propagated into the top four dividend digits
8888  */
8889  fdividend = (double) div[qi];
8890  for (i = 1; i < 4; i++)
8891  {
8892  fdividend *= NBASE;
8893  if (qi + i <= div_ndigits)
8894  fdividend += (double) div[qi + i];
8895  }
8896  /* Compute the (approximate) quotient digit */
8897  fquotient = fdividend * fdivisorinverse;
8898  qdigit = (fquotient >= 0.0) ? ((int) fquotient) :
8899  (((int) fquotient) - 1); /* truncate towards -infinity */
8900  maxdiv += Abs(qdigit);
8901  }
8902 
8903  /*
8904  * Subtract off the appropriate multiple of the divisor.
8905  *
8906  * The digits beyond div[qi] cannot overflow, because we know they
8907  * will fall within the maxdiv limit. As for div[qi] itself, note
8908  * that qdigit is approximately trunc(div[qi] / vardigits[0]),
8909  * which would make the new value simply div[qi] mod vardigits[0].
8910  * The lower-order terms in qdigit can change this result by not
8911  * more than about twice INT_MAX/NBASE, so overflow is impossible.
8912  */
8913  if (qdigit != 0)
8914  {
8915  int istop = Min(var2ndigits, div_ndigits - qi + 1);
8916 
8917  for (i = 0; i < istop; i++)
8918  div[qi + i] -= qdigit * var2digits[i];
8919  }
8920  }
8921 
8922  /*
8923  * The dividend digit we are about to replace might still be nonzero.
8924  * Fold it into the next digit position.
8925  *
8926  * There is no risk of overflow here, although proving that requires
8927  * some care. Much as with the argument for div[qi] not overflowing,
8928  * if we consider the first two terms in the numerator and denominator
8929  * of qdigit, we can see that the final value of div[qi + 1] will be
8930  * approximately a remainder mod (vardigits[0]*NBASE + vardigits[1]).
8931  * Accounting for the lower-order terms is a bit complicated but ends
8932  * up adding not much more than INT_MAX/NBASE to the possible range.
8933  * Thus, div[qi + 1] cannot overflow here, and in its role as div[qi]
8934  * in the next loop iteration, it can't be large enough to cause
8935  * overflow in the carry propagation step (if any), either.
8936  *
8937  * But having said that: div[qi] can be more than INT_MAX/NBASE, as
8938  * noted above, which means that the product div[qi] * NBASE *can*
8939  * overflow. When that happens, adding it to div[qi + 1] will always
8940  * cause a canceling overflow so that the end result is correct. We
8941  * could avoid the intermediate overflow by doing the multiplication
8942  * and addition in int64 arithmetic, but so far there appears no need.
8943  */
8944  div[qi + 1] += div[qi] * NBASE;
8945 
8946  div[qi] = qdigit;
8947  }
8948 
8949  /*
8950  * Approximate and store the last quotient digit (div[div_ndigits])
8951  */
8952  fdividend = (double) div[qi];
8953  for (i = 1; i < 4; i++)
8954  fdividend *= NBASE;
8955  fquotient = fdividend * fdivisorinverse;
8956  qdigit = (fquotient >= 0.0) ? ((int) fquotient) :
8957  (((int) fquotient) - 1); /* truncate towards -infinity */
8958  div[qi] = qdigit;
8959 
8960  /*
8961  * Because the quotient digits might be off by one, some of them might be
8962  * -1 or NBASE at this point. The represented value is correct in a
8963  * mathematical sense, but it doesn't look right. We do a final carry
8964  * propagation pass to normalize the digits, which we combine with storing
8965  * the result digits into the output. Note that this is still done at
8966  * full precision w/guard digits.
8967  */
8968  alloc_var(result, div_ndigits + 1);
8969  res_digits = result->digits;
8970  carry = 0;
8971  for (i = div_ndigits; i >= 0; i--)
8972  {
8973  newdig = div[i] + carry;
8974  if (newdig < 0)
8975  {
8976  carry = -((-newdig - 1) / NBASE) - 1;
8977  newdig -= carry * NBASE;
8978  }
8979  else if (newdig >= NBASE)
8980  {
8981  carry = newdig / NBASE;
8982  newdig -= carry * NBASE;
8983  }
8984  else
8985  carry = 0;
8986  res_digits[i] = newdig;
8987  }
8988  Assert(carry == 0);
8989 
8990  pfree(div);
8991 
8992  /*
8993  * Finally, round the result to the requested precision.
8994  */
8995  result->weight = res_weight;
8996  result->sign = res_sign;
8997 
8998  /* Round to target rscale (and set result->dscale) */
8999  if (round)
9000  round_var(result, rscale);
9001  else
9002  trunc_var(result, rscale);
9003 
9004  /* Strip leading and trailing zeroes */
9005  strip_var(result);
9006 }
static void round_var(NumericVar *var, int rscale)
Definition: numeric.c:10797
static void trunc_var(NumericVar *var, int rscale)
Definition: numeric.c:10903
int weight
Definition: numeric.c:308
#define NUMERIC_POS
Definition: numeric.c:167
static void strip_var(NumericVar *var)
Definition: numeric.c:10965
int errcode(int sqlerrcode)
Definition: elog.c:698
int ndigits
Definition: numeric.c:307
int dscale
Definition: numeric.c:310
#define Min(x, y)
Definition: numeric.c:14
#define Abs(x)
Definition: c.h:992
#define NUMERIC_NEG
Definition: numeric.c:168
int sign
Definition: numeric.c:309
static void zero_var(NumericVar *var)
Definition: numeric.c:6789
void pfree(void *pointer)
Definition: mcxt.c:1169
#define ERROR
Definition: elog.h:46
int16 NumericDigit
Definition: numeric.c:103
#define NBASE
Definition: numeric.c:97
void * palloc0(Size size)
Definition: mcxt.c:1093
#define ereport(elevel,...)
Definition: elog.h:157
#define Assert(condition)
Definition: c.h:804
NumericDigit * digits
Definition: numeric.c:312
#define DIV_GUARD_DIGITS
Definition: numeric.c:101
int errmsg(const char *fmt,...)
Definition: elog.c:909
static void alloc_var(NumericVar *var, int ndigits)
Definition: numeric.c:6757
int i
#define DEC_DIGITS
Definition: numeric.c:99

◆ do_numeric_accum()

static void do_numeric_accum ( NumericAggState state,
Numeric  newval 
)
static

Definition at line 4653 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, NumericAggState::nInfcount, NUMERIC_IS_NINF, NUMERIC_IS_PINF, NUMERIC_IS_SPECIAL, NumericAggState::pInfcount, NumericAggState::sumX, and NumericAggState::sumX2.

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

4654 {
4655  NumericVar X;
4656  NumericVar X2;
4657  MemoryContext old_context;
4658 
4659  /* Count NaN/infinity inputs separately from all else */
4660  if (NUMERIC_IS_SPECIAL(newval))
4661  {
4662  if (NUMERIC_IS_PINF(newval))
4663  state->pInfcount++;
4664  else if (NUMERIC_IS_NINF(newval))
4665  state->nInfcount++;
4666  else
4667  state->NaNcount++;
4668  return;
4669  }
4670 
4671  /* load processed number in short-lived context */
4672  init_var_from_num(newval, &X);
4673 
4674  /*
4675  * Track the highest input dscale that we've seen, to support inverse
4676  * transitions (see do_numeric_discard).
4677  */
4678  if (X.dscale > state->maxScale)
4679  {
4680  state->maxScale = X.dscale;
4681  state->maxScaleCount = 1;
4682  }
4683  else if (X.dscale == state->maxScale)
4684  state->maxScaleCount++;
4685 
4686  /* if we need X^2, calculate that in short-lived context */
4687  if (state->calcSumX2)
4688  {
4689  init_var(&X2);
4690  mul_var(&X, &X, &X2, X.dscale * 2);
4691  }
4692 
4693  /* The rest of this needs to work in the aggregate context */
4694  old_context = MemoryContextSwitchTo(state->agg_context);
4695 
4696  state->N++;
4697 
4698  /* Accumulate sums */
4699  accum_sum_add(&(state->sumX), &X);
4700 
4701  if (state->calcSumX2)
4702  accum_sum_add(&(state->sumX2), &X2);
4703 
4704  MemoryContextSwitchTo(old_context);
4705 }
int64 nInfcount
Definition: numeric.c:4602
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
MemoryContext agg_context
Definition: numeric.c:4593
int dscale
Definition: numeric.c:310
#define NUMERIC_IS_SPECIAL(n)
Definition: numeric.c:174
static void accum_sum_add(NumericSumAccum *accum, const NumericVar *var1)
Definition: numeric.c:11022
#define NUMERIC_IS_PINF(n)
Definition: numeric.c:206
static void init_var_from_num(Numeric num, NumericVar *dest)
Definition: numeric.c:7006
static void mul_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result, int rscale)
Definition: numeric.c:8216
#define NUMERIC_IS_NINF(n)
Definition: numeric.c:207
NumericSumAccum sumX2
Definition: numeric.c:4596
int64 pInfcount
Definition: numeric.c:4601
int64 NaNcount
Definition: numeric.c:4600
int64 maxScaleCount
Definition: numeric.c:4598
NumericSumAccum sumX
Definition: numeric.c:4595
#define init_var(v)
Definition: numeric.c:486

◆ do_numeric_discard()

static bool do_numeric_discard ( NumericAggState state,
Numeric  newval 
)
static

Definition at line 4723 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, NumericAggState::nInfcount, NUMERIC_IS_NINF, NUMERIC_IS_PINF, NUMERIC_IS_SPECIAL, NUMERIC_NEG, NUMERIC_POS, NumericAggState::pInfcount, 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().

4724 {
4725  NumericVar X;
4726  NumericVar X2;
4727  MemoryContext old_context;
4728 
4729  /* Count NaN/infinity inputs separately from all else */
4730  if (NUMERIC_IS_SPECIAL(newval))
4731  {
4732  if (NUMERIC_IS_PINF(newval))
4733  state->pInfcount--;
4734  else if (NUMERIC_IS_NINF(newval))
4735  state->nInfcount--;
4736  else
4737  state->NaNcount--;
4738  return true;
4739  }
4740 
4741  /* load processed number in short-lived context */
4742  init_var_from_num(newval, &X);
4743 
4744  /*
4745  * state->sumX's dscale is the maximum dscale of any of the inputs.
4746  * Removing the last input with that dscale would require us to recompute
4747  * the maximum dscale of the *remaining* inputs, which we cannot do unless
4748  * no more non-NaN inputs remain at all. So we report a failure instead,
4749  * and force the aggregation to be redone from scratch.
4750  */
4751  if (X.dscale == state->maxScale)
4752  {
4753  if (state->maxScaleCount > 1 || state->maxScale == 0)
4754  {
4755  /*
4756  * Some remaining inputs have same dscale, or dscale hasn't gotten
4757  * above zero anyway
4758  */
4759  state->maxScaleCount--;
4760  }
4761  else if (state->N == 1)
4762  {
4763  /* No remaining non-NaN inputs at all, so reset maxScale */
4764  state->maxScale = 0;
4765  state->maxScaleCount = 0;
4766  }
4767  else
4768  {
4769  /* Correct new maxScale is uncertain, must fail */
4770  return false;
4771  }
4772  }
4773 
4774  /* if we need X^2, calculate that in short-lived context */
4775  if (state->calcSumX2)
4776  {
4777  init_var(&X2);
4778  mul_var(&X, &X, &X2, X.dscale * 2);
4779  }
4780 
4781  /* The rest of this needs to work in the aggregate context */
4782  old_context = MemoryContextSwitchTo(state->agg_context);
4783 
4784  if (state->N-- > 1)
4785  {
4786  /* Negate X, to subtract it from the sum */
4787  X.sign = (X.sign == NUMERIC_POS ? NUMERIC_NEG : NUMERIC_POS);
4788  accum_sum_add(&(state->sumX), &X);
4789 
4790  if (state->calcSumX2)
4791  {
4792  /* Negate X^2. X^2 is always positive */
4793  X2.sign = NUMERIC_NEG;
4794  accum_sum_add(&(state->sumX2), &X2);
4795  }
4796  }
4797  else
4798  {
4799  /* Zero the sums */
4800  Assert(state->N == 0);
4801 
4802  accum_sum_reset(&state->sumX);
4803  if (state->calcSumX2)
4804  accum_sum_reset(&state->sumX2);
4805  }
4806 
4807  MemoryContextSwitchTo(old_context);
4808 
4809  return true;
4810 }
int64 nInfcount
Definition: numeric.c:4602
#define NUMERIC_POS
Definition: numeric.c:167
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
MemoryContext agg_context
Definition: numeric.c:4593
int dscale
Definition: numeric.c:310
#define NUMERIC_IS_SPECIAL(n)
Definition: numeric.c:174
#define NUMERIC_NEG
Definition: numeric.c:168
static void accum_sum_add(NumericSumAccum *accum, const NumericVar *var1)
Definition: numeric.c:11022
int sign
Definition: numeric.c:309
#define NUMERIC_IS_PINF(n)
Definition: numeric.c:206
static void init_var_from_num(Numeric num, NumericVar *dest)
Definition: numeric.c:7006
#define Assert(condition)
Definition: c.h:804
static void mul_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result, int rscale)
Definition: numeric.c:8216
#define NUMERIC_IS_NINF(n)
Definition: numeric.c:207
NumericSumAccum sumX2
Definition: numeric.c:4596
static void accum_sum_reset(NumericSumAccum *accum)
Definition: numeric.c:11006
int64 pInfcount
Definition: numeric.c:4601
int64 NaNcount
Definition: numeric.c:4600
int64 maxScaleCount
Definition: numeric.c:4598
NumericSumAccum sumX
Definition: numeric.c:4595
#define init_var(v)
Definition: numeric.c:486

◆ duplicate_numeric()

static Numeric duplicate_numeric ( Numeric  num)
static

Definition at line 7318 of file numeric.c.

References palloc(), and VARSIZE.

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

7319 {
7320  Numeric res;
7321 
7322  res = (Numeric) palloc(VARSIZE(num));
7323  memcpy(res, num, VARSIZE(num));
7324  return res;
7325 }
#define VARSIZE(PTR)
Definition: postgres.h:316
struct NumericData * Numeric
Definition: numeric.h:53
void * palloc(Size size)
Definition: mcxt.c:1062

◆ estimate_ln_dweight()

static int estimate_ln_dweight ( const NumericVar var)
static

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

9913 {
9914  int ln_dweight;
9915 
9916  if (cmp_var(var, &const_zero_point_nine) >= 0 &&
9917  cmp_var(var, &const_one_point_one) <= 0)
9918  {
9919  /*
9920  * 0.9 <= var <= 1.1
9921  *
9922  * ln(var) has a negative weight (possibly very large). To get a
9923  * reasonably accurate result, estimate it using ln(1+x) ~= x.
9924  */
9925  NumericVar x;
9926 
9927  init_var(&x);
9928  sub_var(var, &const_one, &x);
9929 
9930  if (x.ndigits > 0)
9931  {
9932  /* Use weight of most significant decimal digit of x */
9933  ln_dweight = x.weight * DEC_DIGITS + (int) log10(x.digits[0]);
9934  }
9935  else
9936  {
9937  /* x = 0. Since ln(1) = 0 exactly, we don't need extra digits */
9938  ln_dweight = 0;
9939  }
9940 
9941  free_var(&x);
9942  }
9943  else
9944  {
9945  /*
9946  * Estimate the logarithm using the first couple of digits from the
9947  * input number. This will give an accurate result whenever the input
9948  * is not too close to 1.
9949  */
9950  if (var->ndigits > 0)
9951  {
9952  int digits;
9953  int dweight;
9954  double ln_var;
9955 
9956  digits = var->digits[0];
9957  dweight = var->weight * DEC_DIGITS;
9958 
9959  if (var->ndigits > 1)
9960  {
9961  digits = digits * NBASE + var->digits[1];
9962  dweight -= DEC_DIGITS;
9963  }
9964 
9965  /*----------
9966  * We have var ~= digits * 10^dweight
9967  * so ln(var) ~= ln(digits) + dweight * ln(10)
9968  *----------
9969  */
9970  ln_var = log((double) digits) + dweight * 2.302585092994046;
9971  ln_dweight = (int) log10(Abs(ln_var));
9972  }
9973  else
9974  {
9975  /* Caller should fail on ln(0), but for the moment return zero */
9976  ln_dweight = 0;
9977  }
9978  }
9979 
9980  return ln_dweight;
9981 }
int weight
Definition: numeric.c:308
static const NumericVar const_zero_point_nine
Definition: numeric.c:438
static const NumericVar const_one
Definition: numeric.c:421
static void ln_var(const NumericVar *arg, NumericVar *result, int rscale)
Definition: numeric.c:9990
int ndigits
Definition: numeric.c:307
#define Abs(x)
Definition: c.h:992
#define NBASE
Definition: numeric.c:97
static int cmp_var(const NumericVar *var1, const NumericVar *var2)
Definition: numeric.c:7920
static void free_var(NumericVar *var)
Definition: numeric.c:6773
NumericDigit * digits
Definition: numeric.c:312
static void sub_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition: numeric.c:8095
#define DEC_DIGITS
Definition: numeric.c:99
static const NumericVar const_one_point_one
Definition: numeric.c:448
#define init_var(v)
Definition: numeric.c:486
int digits
Definition: informix.c:666

◆ exp_var()

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

Definition at line 9780 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, NumericVar::weight, and zero_var().

Referenced by numeric_exp(), and power_var().

9781 {
9782  NumericVar x;
9783  NumericVar elem;
9784  NumericVar ni;
9785  double val;
9786  int dweight;
9787  int ndiv2;
9788  int sig_digits;
9789  int local_rscale;
9790 
9791  init_var(&x);
9792  init_var(&elem);
9793  init_var(&ni);
9794 
9795  set_var_from_var(arg, &x);
9796 
9797  /*
9798  * Estimate the dweight of the result using floating point arithmetic, so
9799  * that we can choose an appropriate local rscale for the calculation.
9800  */
9802 
9803  /* Guard against overflow/underflow */
9804  /* If you change this limit, see also power_var()'s limit */
9805  if (Abs(val) >= NUMERIC_MAX_RESULT_SCALE * 3)
9806  {
9807  if (val > 0)
9808  ereport(ERROR,
9809  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
9810  errmsg("value overflows numeric format")));
9811  zero_var(result);
9812  result->dscale = rscale;
9813  return;
9814  }
9815 
9816  /* decimal weight = log10(e^x) = x * log10(e) */
9817  dweight = (int) (val * 0.434294481903252);
9818 
9819  /*
9820  * Reduce x to the range -0.01 <= x <= 0.01 (approximately) by dividing by
9821  * 2^n, to improve the convergence rate of the Taylor series.
9822  */
9823  if (Abs(val) > 0.01)
9824  {
9825  NumericVar tmp;
9826 
9827  init_var(&tmp);
9828  set_var_from_var(&const_two, &tmp);
9829 
9830  ndiv2 = 1;
9831  val /= 2;
9832 
9833  while (Abs(val) > 0.01)
9834  {
9835  ndiv2++;
9836  val /= 2;
9837  add_var(&tmp, &tmp, &tmp);
9838  }
9839 
9840  local_rscale = x.dscale + ndiv2;
9841  div_var_fast(&x, &tmp, &x, local_rscale, true);
9842 
9843  free_var(&tmp);
9844  }
9845  else
9846  ndiv2 = 0;
9847 
9848  /*
9849  * Set the scale for the Taylor series expansion. The final result has
9850  * (dweight + rscale + 1) significant digits. In addition, we have to
9851  * raise the Taylor series result to the power 2^ndiv2, which introduces
9852  * an error of up to around log10(2^ndiv2) digits, so work with this many
9853  * extra digits of precision (plus a few more for good measure).
9854  */
9855  sig_digits = 1 + dweight + rscale + (int) (ndiv2 * 0.301029995663981);
9856  sig_digits = Max(sig_digits, 0) + 8;
9857 
9858  local_rscale = sig_digits - 1;
9859 
9860  /*
9861  * Use the Taylor series
9862  *
9863  * exp(x) = 1 + x + x^2/2! + x^3/3! + ...
9864  *
9865  * Given the limited range of x, this should converge reasonably quickly.
9866  * We run the series until the terms fall below the local_rscale limit.
9867  */
9868  add_var(&const_one, &x, result);
9869 
9870  mul_var(&x, &x, &elem, local_rscale);
9871  set_var_from_var(&const_two, &ni);
9872  div_var_fast(&elem, &ni, &elem, local_rscale, true);
9873 
9874  while (elem.ndigits != 0)
9875  {
9876  add_var(result, &elem, result);
9877 
9878  mul_var(&elem, &x, &elem, local_rscale);
9879  add_var(&ni, &const_one, &ni);
9880  div_var_fast(&elem, &ni, &elem, local_rscale, true);
9881  }
9882 
9883  /*
9884  * Compensate for the argument range reduction. Since the weight of the
9885  * result doubles with each multiplication, we can reduce the local rscale
9886  * as we proceed.
9887  */
9888  while (ndiv2-- > 0)
9889  {
9890  local_rscale = sig_digits - result->weight * 2 * DEC_DIGITS;
9891  local_rscale = Max(local_rscale, NUMERIC_MIN_DISPLAY_SCALE);
9892  mul_var(result, result, result, local_rscale);
9893  }
9894 
9895  /* Round to requested rscale */
9896  round_var(result, rscale);
9897 
9898  free_var(&x);
9899  free_var(&elem);
9900  free_var(&ni);
9901 }
static void round_var(NumericVar *var, int rscale)
Definition: numeric.c:10797
int weight
Definition: numeric.c:308
static const NumericVar const_one
Definition: numeric.c:421
int errcode(int sqlerrcode)
Definition: elog.c:698
int ndigits
Definition: numeric.c:307
int dscale
Definition: numeric.c:310
#define Abs(x)
Definition: c.h:992
static void zero_var(NumericVar *var)
Definition: numeric.c:6789
#define ERROR
Definition: elog.h:46
static double numericvar_to_double_no_overflow(const NumericVar *var)
Definition: numeric.c:7888
#define NUMERIC_MIN_DISPLAY_SCALE
Definition: numeric.h:40
#define NUMERIC_MAX_RESULT_SCALE
Definition: numeric.h:42
static void div_var_fast(const NumericVar *var1, const NumericVar *var2, NumericVar *result, int rscale, bool round)
Definition: numeric.c:8709
static void free_var(NumericVar *var)
Definition: numeric.c:6773
#define ereport(elevel,...)
Definition: elog.h:157
static const NumericVar const_two
Definition: numeric.c:428
static void mul_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result, int rscale)
Definition: numeric.c:8216
static void add_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition: numeric.c:7978
int errmsg(const char *fmt,...)
Definition: elog.c:909
#define Max(x, y)
Definition: numeric.c:13
#define DEC_DIGITS
Definition: numeric.c:99
static void set_var_from_var(const NumericVar *value, NumericVar *dest)
Definition: numeric.c:7023
long val
Definition: informix.c:664
#define init_var(v)
Definition: numeric.c:486

◆ float4_numeric()

Datum float4_numeric ( PG_FUNCTION_ARGS  )

Definition at line 4484 of file numeric.c.

References buf, free_var(), init_var, make_result(), PG_GETARG_FLOAT4, PG_RETURN_NUMERIC, set_var_from_str(), snprintf, and val.

4485 {
4487  Numeric res;
4488  NumericVar result;
4489  char buf[FLT_DIG + 100];
4490 
4491  if (isnan(val))
4493 
4494  if (isinf(val))
4495  {
4496  if (val < 0)
4498  else
4500  }
4501 
4502  snprintf(buf, sizeof(buf), "%.*g", FLT_DIG, val);
4503 
4504  init_var(&result);
4505 
4506  /* Assume we need not worry about leading/trailing spaces */
4507  (void) set_var_from_str(buf, buf, &result);
4508 
4509  res = make_result(&result);
4510 
4511  free_var(&result);
4512 
4513  PG_RETURN_NUMERIC(res);
4514 }
#define PG_RETURN_NUMERIC(x)
Definition: numeric.h:64
static char * buf
Definition: pg_test_fsync.c:68
static const NumericVar const_ninf
Definition: numeric.c:457
#define PG_GETARG_FLOAT4(n)
Definition: fmgr.h:281
float float4
Definition: c.h:564
static void free_var(NumericVar *var)
Definition: numeric.c:6773
static const NumericVar const_pinf
Definition: numeric.c:454
static const char * set_var_from_str(const char *str, const char *cp, NumericVar *dest)
Definition: numeric.c:6813
static const NumericVar const_nan
Definition: numeric.c:451
static Numeric make_result(const NumericVar *var)
Definition: numeric.c:7446
#define snprintf
Definition: port.h:217
long val
Definition: informix.c:664
#define init_var(v)
Definition: numeric.c:486

◆ float8_numeric()

Datum float8_numeric ( PG_FUNCTION_ARGS  )

Definition at line 4391 of file numeric.c.

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

4392 {
4394  Numeric res;
4395  NumericVar result;
4396  char buf[DBL_DIG + 100];
4397 
4398  if (isnan(val))
4400 
4401  if (isinf(val))
4402  {
4403  if (val < 0)
4405  else
4407  }
4408 
4409  snprintf(buf, sizeof(buf), "%.*g", DBL_DIG, val);
4410 
4411  init_var(&result);
4412 
4413  /* Assume we need not worry about leading/trailing spaces */
4414  (void) set_var_from_str(buf, buf, &result);
4415 
4416  res = make_result(&result);
4417 
4418  free_var(&result);
4419 
4420  PG_RETURN_NUMERIC(res);
4421 }
#define PG_RETURN_NUMERIC(x)
Definition: numeric.h:64
#define PG_GETARG_FLOAT8(n)
Definition: fmgr.h:282
double float8
Definition: c.h:565
static char * buf
Definition: pg_test_fsync.c:68
static const NumericVar const_ninf
Definition: numeric.c:457
static void free_var(NumericVar *var)
Definition: numeric.c:6773
static const NumericVar const_pinf
Definition: numeric.c:454
static const char * set_var_from_str(const char *str, const char *cp, NumericVar *dest)
Definition: numeric.c:6813
static const NumericVar const_nan
Definition: numeric.c:451
static Numeric make_result(const NumericVar *var)
Definition: numeric.c:7446
#define snprintf
Definition: port.h:217
long val
Definition: informix.c:664
#define init_var(v)
Definition: numeric.c:486

◆ floor_var()

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

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

9208 {
9209  NumericVar tmp;
9210 
9211  init_var(&tmp);
9212  set_var_from_var(var, &tmp);
9213 
9214  trunc_var(&tmp, 0);
9215 
9216  if (var->sign == NUMERIC_NEG && cmp_var(var, &tmp) != 0)
9217  sub_var(&tmp, &const_one, &tmp);
9218 
9219  set_var_from_var(&tmp, result);
9220  free_var(&tmp);
9221 }
static void trunc_var(NumericVar *var, int rscale)
Definition: numeric.c:10903
static const NumericVar const_one
Definition: numeric.c:421
#define NUMERIC_NEG
Definition: numeric.c:168
int sign
Definition: numeric.c:309
static int cmp_var(const NumericVar *var1, const NumericVar *var2)
Definition: numeric.c:7920
static void free_var(NumericVar *var)
Definition: numeric.c:6773
static void sub_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition: numeric.c:8095
static void set_var_from_var(const NumericVar *value, NumericVar *dest)
Definition: numeric.c:7023
#define init_var(v)
Definition: numeric.c:486

◆ free_var()

static void free_var ( NumericVar var)
static

Definition at line 6773 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(), int64_div_fast_to_numeric(), int64_to_numeric(), int8_avg_deserialize(), int8_avg_serialize(), ln_var(), log_var(), mod_var(), numeric(), numeric_add_opt_error(), numeric_avg(), numeric_avg_deserialize(), numeric_avg_serialize(), numeric_ceil(), numeric_deserialize(), numeric_div_opt_error(), numeric_div_trunc(), numeric_exp(), numeric_fac(), numeric_floor(), numeric_gcd(), numeric_in(), numeric_inc(), numeric_lcm(), numeric_ln(), numeric_log(), numeric_min_scale(), numeric_mod_opt_error(), numeric_mul_opt_error(), numeric_poly_avg(), numeric_poly_deserialize(), numeric_poly_serialize(), numeric_poly_sum(), numeric_power(), numeric_recv(), numeric_round(), numeric_serialize(), numeric_sqrt(), numeric_stddev_internal(), numeric_stddev_pop(), numeric_sub_opt_error(), numeric_sum(), numeric_trim_scale(), numeric_trunc(), numericvar_to_int64(), numericvar_to_uint64(), power_var(), power_var_int(), sqrt_var(), and width_bucket_numeric().

6774 {
6775  digitbuf_free(var->buf);
6776  var->buf = NULL;
6777  var->digits = NULL;
6778  var->sign = NUMERIC_NAN;
6779 }
int sign
Definition: numeric.c:309
#define digitbuf_free(buf)
Definition: numeric.c:480
#define NUMERIC_NAN
Definition: numeric.c:199
NumericDigit * buf
Definition: numeric.c:311
NumericDigit * digits
Definition: numeric.c:312

◆ gcd_var()

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

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

9231 {
9232  int res_dscale;
9233  int cmp;
9234  NumericVar tmp_arg;
9235  NumericVar mod;
9236 
9237  res_dscale = Max(var1->dscale, var2->dscale);
9238 
9239  /*
9240  * Arrange for var1 to be the number with the greater absolute value.
9241  *
9242  * This would happen automatically in the loop below, but avoids an
9243  * expensive modulo operation.
9244  */
9245  cmp = cmp_abs(var1, var2);
9246  if (cmp < 0)
9247  {
9248  const NumericVar *tmp = var1;
9249 
9250  var1 = var2;
9251  var2 = tmp;
9252  }
9253 
9254  /*
9255  * Also avoid the taking the modulo if the inputs have the same absolute
9256  * value, or if the smaller input is zero.
9257  */
9258  if (cmp == 0 || var2->ndigits == 0)
9259  {
9260  set_var_from_var(var1, result);
9261  result->sign = NUMERIC_POS;
9262  result->dscale = res_dscale;
9263  return;
9264  }
9265 
9266  init_var(&tmp_arg);
9267  init_var(&mod);
9268 
9269  /* Use the Euclidean algorithm to find the GCD */
9270  set_var_from_var(var1, &tmp_arg);
9271  set_var_from_var(var2, result);
9272 
9273  for (;;)
9274  {
9275  /* this loop can take a while, so allow it to be interrupted */
9277 
9278  mod_var(&tmp_arg, result, &mod);
9279  if (mod.ndigits == 0)
9280  break;
9281  set_var_from_var(result, &tmp_arg);
9282  set_var_from_var(&mod, result);
9283  }
9284  result->sign = NUMERIC_POS;
9285  result->dscale = res_dscale;
9286 
9287  free_var(&tmp_arg);
9288  free_var(&mod);
9289 }
#define NUMERIC_POS
Definition: numeric.c:167
int ndigits
Definition: numeric.c:307
int dscale
Definition: numeric.c:310
int sign
Definition: numeric.c:309
static void mod_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition: numeric.c:9084
static void free_var(NumericVar *var)
Definition: numeric.c:6773
static int cmp_abs(const NumericVar *var1, const NumericVar *var2)
Definition: numeric.c:10552
#define Max(x, y)
Definition: numeric.c:13
static void set_var_from_var(const NumericVar *value, NumericVar *dest)
Definition: numeric.c:7023
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:120
#define init_var(v)
Definition: numeric.c:486
static int cmp(const chr *x, const chr *y, size_t len)
Definition: regc_locale.c:747

◆ generate_series_numeric()

Datum generate_series_numeric ( PG_FUNCTION_ARGS  )

Definition at line 1613 of file numeric.c.

References generate_series_step_numeric().

1614 {
1615  return generate_series_step_numeric(fcinfo);
1616 }
Datum generate_series_step_numeric(PG_FUNCTION_ARGS)
Definition: numeric.c:1619

◆ generate_series_step_numeric()

Datum generate_series_step_numeric ( PG_FUNCTION_ARGS  )

Definition at line 1619 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_IS_SPECIAL, NUMERIC_NEG, NUMERIC_POS, NumericGetDatum, palloc(), PG_GETARG_NUMERIC, PG_NARGS, set_var_from_num(), set_var_from_var(), NumericVar::sign, SRF_FIRSTCALL_INIT, SRF_IS_FIRSTCALL, SRF_PERCALL_SETUP, SRF_RETURN_DONE, SRF_RETURN_NEXT, generate_series_numeric_fctx::step, generate_series_numeric_fctx::stop, and FuncCallContext::user_fctx.

Referenced by generate_series_numeric().

1620 {
1622  FuncCallContext *funcctx;
1623  MemoryContext oldcontext;
1624 
1625  if (SRF_IS_FIRSTCALL())
1626  {
1627  Numeric start_num = PG_GETARG_NUMERIC(0);
1628  Numeric stop_num = PG_GETARG_NUMERIC(1);
1629  NumericVar steploc = const_one;
1630 
1631  /* Reject NaN and infinities in start and stop values */
1632  if (NUMERIC_IS_SPECIAL(start_num))
1633  {
1634  if (NUMERIC_IS_NAN(start_num))
1635  ereport(ERROR,
1636  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1637  errmsg("start value cannot be NaN")));
1638  else
1639  ereport(ERROR,
1640  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1641  errmsg("start value cannot be infinity")));
1642  }
1643  if (NUMERIC_IS_SPECIAL(stop_num))
1644  {
1645  if (NUMERIC_IS_NAN(stop_num))
1646  ereport(ERROR,
1647  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1648  errmsg("stop value cannot be NaN")));
1649  else
1650  ereport(ERROR,
1651  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1652  errmsg("stop value cannot be infinity")));
1653  }
1654 
1655  /* see if we were given an explicit step size */
1656  if (PG_NARGS() == 3)
1657  {
1658  Numeric step_num = PG_GETARG_NUMERIC(2);
1659 
1660  if (NUMERIC_IS_SPECIAL(step_num))
1661  {
1662  if (NUMERIC_IS_NAN(step_num))
1663  ereport(ERROR,
1664  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1665  errmsg("step size cannot be NaN")));
1666  else
1667  ereport(ERROR,
1668  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1669  errmsg("step size cannot be infinity")));
1670  }
1671 
1672  init_var_from_num(step_num, &steploc);
1673 
1674  if (cmp_var(&steploc, &const_zero) == 0)
1675  ereport(ERROR,
1676  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1677  errmsg("step size cannot equal zero")));
1678  }
1679 
1680  /* create a function context for cross-call persistence */
1681  funcctx = SRF_FIRSTCALL_INIT();
1682 
1683  /*
1684  * Switch to memory context appropriate for multiple function calls.
1685  */
1686  oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
1687 
1688  /* allocate memory for user context */
1689  fctx = (generate_series_numeric_fctx *)
1691 
1692  /*
1693  * Use fctx to keep state from call to call. Seed current with the
1694  * original start value. We must copy the start_num and stop_num
1695  * values rather than pointing to them, since we may have detoasted
1696  * them in the per-call context.
1697  */
1698  init_var(&fctx->current);
1699  init_var(&fctx->stop);
1700  init_var(&fctx->step);
1701 
1702  set_var_from_num(start_num, &fctx->current);
1703  set_var_from_num(stop_num, &fctx->stop);
1704  set_var_from_var(&steploc, &fctx->step);
1705 
1706  funcctx->user_fctx = fctx;
1707  MemoryContextSwitchTo(oldcontext);
1708  }
1709 
1710  /* stuff done on every call of the function */
1711  funcctx = SRF_PERCALL_SETUP();
1712 
1713  /*
1714  * Get the saved state and use current state as the result of this
1715  * iteration.
1716  */
1717  fctx = funcctx->user_fctx;
1718 
1719  if ((fctx->step.sign == NUMERIC_POS &&
1720  cmp_var(&fctx->current, &fctx->stop) <= 0) ||
1721  (fctx->step.sign == NUMERIC_NEG &&
1722  cmp_var(&fctx->current, &fctx->stop) >= 0))
1723  {
1724  Numeric result = make_result(&fctx->current);
1725 
1726  /* switch to memory context appropriate for iteration calculation */
1727  oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
1728 
1729  /* increment current in preparation for next iteration */
1730  add_var(&fctx->current, &fctx->step, &fctx->current);
1731  MemoryContextSwitchTo(oldcontext);
1732 
1733  /* do when there is more left to send */
1734  SRF_RETURN_NEXT(funcctx, NumericGetDatum(result));
1735  }
1736  else
1737  /* do when there is no more left */
1738  SRF_RETURN_DONE(funcctx);
1739 }
#define SRF_IS_FIRSTCALL()
Definition: funcapi.h:293
static const NumericVar const_one
Definition: numeric.c:421
#define NumericGetDatum(X)
Definition: numeric.h:61
#define NUMERIC_POS
Definition: numeric.c:167
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
int errcode(int sqlerrcode)
Definition: elog.c:698
#define SRF_PERCALL_SETUP()
Definition: funcapi.h:297
#define SRF_RETURN_NEXT(_funcctx, _result)
Definition: funcapi.h:299
#define NUMERIC_IS_SPECIAL(n)
Definition: numeric.c:174
#define NUMERIC_NEG
Definition: numeric.c:168
int sign
Definition: numeric.c:309
#define ERROR
Definition: elog.h:46
static void init_var_from_num(Numeric num, NumericVar *dest)
Definition: numeric.c:7006
static const NumericVar const_zero
Definition: numeric.c:417
static int cmp_var(const NumericVar *var1, const NumericVar *var2)
Definition: numeric.c:7920
#define ereport(elevel,...)
Definition: elog.h:157
#define PG_GETARG_NUMERIC(n)
Definition: numeric.h:62
static void set_var_from_num(Numeric value, NumericVar *dest)
Definition: numeric.c:6975
MemoryContext multi_call_memory_ctx
Definition: funcapi.h:101
static void add_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition: numeric.c:7978
#define PG_NARGS()
Definition: fmgr.h:203
static Numeric make_result(const NumericVar *var)
Definition: numeric.c:7446
void * user_fctx
Definition: funcapi.h:82
void * palloc(Size size)
Definition: mcxt.c:1062
int errmsg(const char *fmt,...)
Definition: elog.c:909
#define NUMERIC_IS_NAN(n)
Definition: numeric.c:205
static void set_var_from_var(const NumericVar *value, NumericVar *dest)
Definition: numeric.c:7023
#define init_var(v)
Definition: numeric.c:486
#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 4039 of file numeric.c.

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

Referenced by numeric_min_scale(), and numeric_trim_scale().

4040 {
4041  int min_scale;
4042  int last_digit_pos;
4043 
4044  /*
4045  * Ordinarily, the input value will be "stripped" so that the last
4046  * NumericDigit is nonzero. But we don't want to get into an infinite
4047  * loop if it isn't, so explicitly find the last nonzero digit.
4048  */
4049  last_digit_pos = var->ndigits - 1;
4050  while (last_digit_pos >= 0 &&
4051  var->digits[last_digit_pos] == 0)
4052  last_digit_pos--;
4053 
4054  if (last_digit_pos >= 0)
4055  {
4056  /* compute min_scale assuming that last ndigit has no zeroes */
4057  min_scale = (last_digit_pos - var->weight) * DEC_DIGITS;
4058 
4059  /*
4060  * We could get a negative result if there are no digits after the
4061  * decimal point. In this case the min_scale must be zero.
4062  */
4063  if (min_scale > 0)
4064  {
4065  /*
4066  * Reduce min_scale if trailing digit(s) in last NumericDigit are
4067  * zero.
4068  */
4069  NumericDigit last_digit = var->digits[last_digit_pos];
4070 
4071  while (last_digit % 10 == 0)
4072  {
4073  min_scale--;
4074  last_digit /= 10;
4075  }
4076  }
4077  else
4078  min_scale = 0;
4079  }
4080  else
4081  min_scale = 0; /* result if input is zero */
4082 
4083  return min_scale;
4084 }
int weight
Definition: numeric.c:308
int ndigits
Definition: numeric.c:307
int16 NumericDigit
Definition: numeric.c:103
NumericDigit * digits
Definition: numeric.c:312
#define DEC_DIGITS
Definition: numeric.c:99

◆ get_str_from_var()

static char * get_str_from_var ( const NumericVar var)
static

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

7050 {
7051  int dscale;
7052  char *str;
7053  char *cp;
7054  char *endcp;
7055  int i;
7056  int d;
7057  NumericDigit dig;
7058 
7059 #if DEC_DIGITS > 1
7060  NumericDigit d1;
7061 #endif
7062 
7063  dscale = var->dscale;
7064 
7065  /*
7066  * Allocate space for the result.
7067  *
7068  * i is set to the # of decimal digits before decimal point. dscale is the
7069  * # of decimal digits we will print after decimal point. We may generate
7070  * as many as DEC_DIGITS-1 excess digits at the end, and in addition we
7071  * need room for sign, decimal point, null terminator.
7072  */
7073  i = (var->weight + 1) * DEC_DIGITS;
7074  if (i <= 0)
7075  i = 1;
7076 
7077  str = palloc(i + dscale + DEC_DIGITS + 2);
7078  cp = str;
7079 
7080  /*
7081  * Output a dash for negative values
7082  */
7083  if (var->sign == NUMERIC_NEG)
7084  *cp++ = '-';
7085 
7086  /*
7087  * Output all digits before the decimal point
7088  */
7089  if (var->weight < 0)
7090  {
7091  d = var->weight + 1;
7092  *cp++ = '0';
7093  }
7094  else
7095  {
7096  for (d = 0; d <= var->weight; d++)
7097  {
7098  dig = (d < var->ndigits) ? var->digits[d] : 0;
7099  /* In the first digit, suppress extra leading decimal zeroes */
7100 #if DEC_DIGITS == 4
7101  {
7102  bool putit = (d > 0);
7103 
7104  d1 = dig / 1000;
7105  dig -= d1 * 1000;
7106  putit |= (d1 > 0);
7107  if (putit)
7108  *cp++ = d1 + '0';
7109  d1 = dig / 100;
7110  dig -= d1 * 100;
7111  putit |= (d1 > 0);
7112  if (putit)
7113  *cp++ = d1 + '0';
7114  d1 = dig / 10;
7115  dig -= d1 * 10;
7116  putit |= (d1 > 0);
7117  if (putit)
7118  *cp++ = d1 + '0';
7119  *cp++ = dig + '0';
7120  }
7121 #elif DEC_DIGITS == 2
7122  d1 = dig / 10;
7123  dig -= d1 * 10;
7124  if (d1 > 0 || d > 0)
7125  *cp++ = d1 + '0';
7126  *cp++ = dig + '0';
7127 #elif DEC_DIGITS == 1
7128  *cp++ = dig + '0';
7129 #else
7130 #error unsupported NBASE
7131 #endif
7132  }
7133  }
7134 
7135  /*
7136  * If requested, output a decimal point and all the digits that follow it.
7137  * We initially put out a multiple of DEC_DIGITS digits, then truncate if
7138  * needed.
7139  */
7140  if (dscale > 0)
7141  {
7142  *cp++ = '.';
7143  endcp = cp + dscale;
7144  for (i = 0; i < dscale; d++, i += DEC_DIGITS)
7145  {
7146  dig = (d >= 0 && d < var->ndigits) ? var->digits[d] : 0;
7147 #if DEC_DIGITS == 4
7148  d1 = dig / 1000;
7149  dig -= d1 * 1000;
7150  *cp++ = d1 + '0';
7151  d1 = dig / 100;
7152  dig -= d1 * 100;
7153  *cp++ = d1 + '0';
7154  d1 = dig / 10;
7155  dig -= d1 * 10;
7156  *cp++ = d1 + '0';
7157  *cp++ = dig + '0';
7158 #elif DEC_DIGITS == 2
7159  d1 = dig / 10;
7160  dig -= d1 * 10;
7161  *cp++ = d1 + '0';
7162  *cp++ = dig + '0';
7163 #elif DEC_DIGITS == 1
7164  *cp++ = dig + '0';
7165 #else
7166 #error unsupported NBASE
7167 #endif
7168  }
7169  cp = endcp;
7170  }
7171 
7172  /*
7173  * terminate the string and return it
7174  */
7175  *cp = '\0';
7176  return str;
7177 }
int weight
Definition: numeric.c:308
static void error(void)
Definition: sql-dyntest.c:147
int ndigits
Definition: numeric.c:307
int dscale
Definition: numeric.c:310
#define NUMERIC_NEG
Definition: numeric.c:168
int sign
Definition: numeric.c:309
int16 NumericDigit
Definition: numeric.c:103
#define NBASE
Definition: numeric.c:97
NumericDigit * digits
Definition: numeric.c:312
void * palloc(Size size)
Definition: mcxt.c:1062
int i
#define DEC_DIGITS
Definition: numeric.c:99

◆ get_str_from_var_sci()

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

Definition at line 7202 of file numeric.c.

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

Referenced by numeric_out_sci().

7203 {
7204  int32 exponent;
7205  NumericVar tmp_var;
7206  size_t len;
7207  char *str;
7208  char *sig_out;
7209 
7210  if (rscale < 0)
7211  rscale = 0;
7212 
7213  /*
7214  * Determine the exponent of this number in normalised form.
7215  *
7216  * This is the exponent required to represent the number with only one
7217  * significant digit before the decimal place.
7218  */
7219  if (var->ndigits > 0)
7220  {
7221  exponent = (var->weight + 1) * DEC_DIGITS;
7222 
7223  /*
7224  * Compensate for leading decimal zeroes in the first numeric digit by
7225  * decrementing the exponent.
7226  */
7227  exponent -= DEC_DIGITS - (int) log10(var->digits[0]);
7228  }
7229  else
7230  {
7231  /*
7232  * If var has no digits, then it must be zero.
7233  *
7234  * Zero doesn't technically have a meaningful exponent in normalised
7235  * notation, but we just display the exponent as zero for consistency
7236  * of output.
7237  */
7238  exponent = 0;
7239  }
7240 
7241  /*
7242  * Divide var by 10^exponent to get the significand, rounding to rscale
7243  * decimal digits in the process.
7244  */
7245  init_var(&tmp_var);
7246 
7247  power_ten_int(exponent, &tmp_var);
7248  div_var(var, &tmp_var, &tmp_var, rscale, true);
7249  sig_out = get_str_from_var(&tmp_var);
7250 
7251  free_var(&tmp_var);
7252 
7253  /*
7254  * Allocate space for the result.
7255  *
7256  * In addition to the significand, we need room for the exponent
7257  * decoration ("e"), the sign of the exponent, up to 10 digits for the
7258  * exponent itself, and of course the null terminator.
7259  */
7260  len = strlen(sig_out) + 13;
7261  str = palloc(len);
7262  snprintf(str, len, "%se%+03d", sig_out, exponent);
7263 
7264  pfree(sig_out);
7265 
7266  return str;
7267 }
int weight
Definition: numeric.c:308
int ndigits
Definition: numeric.c:307
static void div_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result, int rscale, bool round)
Definition: numeric.c:8424
signed int int32
Definition: c.h:429
void pfree(void *pointer)
Definition: mcxt.c:1169
static void free_var(NumericVar *var)
Definition: numeric.c:6773
NumericDigit * digits
Definition: numeric.c:312
static void power_ten_int(int exp, NumericVar *result)
Definition: numeric.c:10511
void * palloc(Size size)
Definition: mcxt.c:1062
static char * get_str_from_var(const NumericVar *var)
Definition: numeric.c:7049
#define DEC_DIGITS
Definition: numeric.c:99
#define snprintf
Definition: port.h:217
#define init_var(v)
Definition: numeric.c:486

◆ hash_numeric()

Datum hash_numeric ( PG_FUNCTION_ARGS  )

Definition at line 2613 of file numeric.c.

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

Referenced by JsonbHashScalarValue().

2614 {
2616  Datum digit_hash;
2617  Datum result;
2618  int weight;
2619  int start_offset;
2620  int end_offset;
2621  int i;
2622  int hash_len;
2624 
2625  /* If it's NaN or infinity, don't try to hash the rest of the fields */
2626  if (NUMERIC_IS_SPECIAL(key))
2627  PG_RETURN_UINT32(0);
2628 
2629  weight = NUMERIC_WEIGHT(key);
2630  start_offset = 0;
2631  end_offset = 0;
2632 
2633  /*
2634  * Omit any leading or trailing zeros from the input to the hash. The
2635  * numeric implementation *should* guarantee that leading and trailing
2636  * zeros are suppressed, but we're paranoid. Note that we measure the
2637  * starting and ending offsets in units of NumericDigits, not bytes.
2638  */
2639  digits = NUMERIC_DIGITS(key);
2640  for (i = 0; i < NUMERIC_NDIGITS(key); i++)
2641  {
2642  if (digits[i] != (NumericDigit) 0)
2643  break;
2644 
2645  start_offset++;
2646 
2647  /*
2648  * The weight is effectively the # of digits before the decimal point,
2649  * so decrement it for each leading zero we skip.
2650  */
2651  weight--;
2652  }
2653 
2654  /*
2655  * If there are no non-zero digits, then the value of the number is zero,
2656  * regardless of any other fields.
2657  */
2658  if (NUMERIC_NDIGITS(key) == start_offset)
2659  PG_RETURN_UINT32(-1);
2660 
2661  for (i = NUMERIC_NDIGITS(key) - 1; i >= 0; i--)
2662  {
2663  if (digits[i] != (NumericDigit) 0)
2664  break;
2665 
2666  end_offset++;
2667  }
2668 
2669  /* If we get here, there should be at least one non-zero digit */
2670  Assert(start_offset + end_offset < NUMERIC_NDIGITS(key));
2671 
2672  /*
2673  * Note that we don't hash on the Numeric's scale, since two numerics can
2674  * compare equal but have different scales. We also don't hash on the
2675  * sign, although we could: since a sign difference implies inequality,
2676  * this shouldn't affect correctness.
2677  */
2678  hash_len = NUMERIC_NDIGITS(key) - start_offset - end_offset;
2679  digit_hash = hash_any((unsigned char *) (NUMERIC_DIGITS(key) + start_offset),
2680  hash_len * sizeof(NumericDigit));
2681 
2682  /* Mix in the weight, via XOR */
2683  result = digit_hash ^ weight;
2684 
2685  PG_RETURN_DATUM(result);
2686 }
#define PG_RETURN_UINT32(x)
Definition: fmgr.h:355
#define NUMERIC_IS_SPECIAL(n)
Definition: numeric.c:174
#define NUMERIC_DIGITS(num)
Definition: numeric.c:488
int16 NumericDigit
Definition: numeric.c:103
static Datum hash_any(const unsigned char *k, int keylen)
Definition: hashfn.h:31
#define NUMERIC_NDIGITS(num)
Definition: numeric.c:490
uintptr_t Datum
Definition: postgres.h:411
#define PG_RETURN_DATUM(x)
Definition: fmgr.h:353
#define NUMERIC_WEIGHT(n)
Definition: numeric.c:248
#define PG_GETARG_NUMERIC(n)
Definition: numeric.h:62
#define Assert(condition)
Definition: c.h:804
int i
int digits
Definition: informix.c:666

◆ hash_numeric_extended()

Datum hash_numeric_extended ( PG_FUNCTION_ARGS  )

Definition at line 2693 of file numeric.c.

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

Referenced by JsonbHashScalarValueExtended().

2694 {
2696  uint64 seed = PG_GETARG_INT64(1);
2697  Datum digit_hash;
2698  Datum result;
2699  int weight;
2700  int start_offset;
2701  int end_offset;
2702  int i;
2703  int hash_len;
2705 
2706  /* If it's NaN or infinity, don't try to hash the rest of the fields */
2707  if (NUMERIC_IS_SPECIAL(key))
2708  PG_RETURN_UINT64(seed);
2709 
2710  weight = NUMERIC_WEIGHT(key);
2711  start_offset = 0;
2712  end_offset = 0;
2713 
2714  digits = NUMERIC_DIGITS(key);
2715  for (i = 0; i < NUMERIC_NDIGITS(key); i++)
2716  {
2717  if (digits[i] != (NumericDigit) 0)
2718  break;
2719 
2720  start_offset++;
2721 
2722  weight--;
2723  }
2724 
2725  if (NUMERIC_NDIGITS(key) == start_offset)
2726  PG_RETURN_UINT64(seed - 1);
2727 
2728  for (i = NUMERIC_NDIGITS(key) - 1; i >= 0; i--)
2729  {
2730  if (digits[i] != (NumericDigit) 0)
2731  break;
2732 
2733  end_offset++;
2734  }
2735 
2736  Assert(start_offset + end_offset < NUMERIC_NDIGITS(key));
2737 
2738  hash_len = NUMERIC_NDIGITS(key) - start_offset - end_offset;
2739  digit_hash = hash_any_extended((unsigned char *) (NUMERIC_DIGITS(key)
2740  + start_offset),
2741  hash_len * sizeof(NumericDigit),
2742  seed);
2743 
2744  result = UInt64GetDatum(DatumGetUInt64(digit_hash) ^ weight);
2745 
2746  PG_RETURN_DATUM(result);
2747 }
#define UInt64GetDatum(X)
Definition: postgres.h:692
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:369
#define NUMERIC_IS_SPECIAL(n)
Definition: numeric.c:174
#define NUMERIC_DIGITS(num)
Definition: numeric.c:488
int16 NumericDigit
Definition: numeric.c:103
#define NUMERIC_NDIGITS(num)
Definition: numeric.c:490
uintptr_t Datum
Definition: postgres.h:411
#define PG_RETURN_DATUM(x)
Definition: fmgr.h:353
#define DatumGetUInt64(X)
Definition: postgres.h:678
#define NUMERIC_WEIGHT(n)
Definition: numeric.c:248
#define PG_GETARG_NUMERIC(n)
Definition: numeric.h:62
#define Assert(condition)
Definition: c.h:804
int i
#define PG_GETARG_INT64(n)
Definition: fmgr.h:283
int digits
Definition: informix.c:666

◆ in_range_numeric_numeric()

Datum in_range_numeric_numeric ( PG_FUNCTION_ARGS  )

Definition at line 2478 of file numeric.c.

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

2479 {
2481  Numeric base = PG_GETARG_NUMERIC(1);
2482  Numeric offset = PG_GETARG_NUMERIC(2);
2483  bool sub = PG_GETARG_BOOL(3);
2484  bool less = PG_GETARG_BOOL(4);
2485  bool result;
2486 
2487  /*
2488  * Reject negative (including -Inf) or NaN offset. Negative is per spec,
2489  * and NaN is because appropriate semantics for that seem non-obvious.
2490  */
2491  if (NUMERIC_IS_NAN(offset) ||
2492  NUMERIC_IS_NINF(offset) ||
2493  NUMERIC_SIGN(offset) == NUMERIC_NEG)
2494  ereport(ERROR,
2495  (errcode(ERRCODE_INVALID_PRECEDING_OR_FOLLOWING_SIZE),
2496  errmsg("invalid preceding or following size in window function")));
2497 
2498  /*
2499  * Deal with cases where val and/or base is NaN, following the rule that
2500  * NaN sorts after non-NaN (cf cmp_numerics). The offset cannot affect
2501  * the conclusion.
2502  */
2503  if (NUMERIC_IS_NAN(val))
2504  {
2505  if (NUMERIC_IS_NAN(base))
2506  result = true; /* NAN = NAN */
2507  else
2508  result = !less; /* NAN > non-NAN */
2509  }
2510  else if (NUMERIC_IS_NAN(base))
2511  {
2512  result = less; /* non-NAN < NAN */
2513  }
2514 
2515  /*
2516  * Deal with infinite offset (necessarily +Inf, at this point).
2517  */
2518  else if (NUMERIC_IS_SPECIAL(offset))
2519  {
2520  Assert(NUMERIC_IS_PINF(offset));
2521  if (sub ? NUMERIC_IS_PINF(base) : NUMERIC_IS_NINF(base))
2522  {
2523  /*
2524  * base +/- offset would produce NaN, so return true for any val
2525  * (see in_range_float8_float8() for reasoning).
2526  */
2527  result = true;
2528  }
2529  else if (sub)
2530  {
2531  /* base - offset must be -inf */
2532  if (less)
2533  result = NUMERIC_IS_NINF(val); /* only -inf is <= sum */
2534  else
2535  result = true; /* any val is >= sum */
2536  }
2537  else
2538  {
2539  /* base + offset must be +inf */
2540  if (less)
2541  result = true; /* any val is <= sum */
2542  else
2543  result = NUMERIC_IS_PINF(val); /* only +inf is >= sum */
2544  }
2545  }
2546 
2547  /*
2548  * Deal with cases where val and/or base is infinite. The offset, being
2549  * now known finite, cannot affect the conclusion.
2550  */
2551  else if (NUMERIC_IS_SPECIAL(val))
2552  {
2553  if (NUMERIC_IS_PINF(val))
2554  {
2555  if (NUMERIC_IS_PINF(base))
2556  result = true; /* PINF = PINF */
2557  else
2558  result = !less; /* PINF > any other non-NAN */
2559  }
2560  else /* val must be NINF */
2561  {
2562  if (NUMERIC_IS_NINF(base))
2563  result = true; /* NINF = NINF */
2564  else
2565  result = less; /* NINF < anything else */
2566  }
2567  }
2568  else if (NUMERIC_IS_SPECIAL(base))
2569  {
2570  if (NUMERIC_IS_NINF(base))
2571  result = !less; /* normal > NINF */
2572  else
2573  result = less; /* normal < PINF */
2574  }
2575  else
2576  {
2577  /*
2578  * Otherwise go ahead and compute base +/- offset. While it's
2579  * possible for this to overflow the numeric format, it's unlikely
2580  * enough that we don't take measures to prevent it.
2581  */
2582  NumericVar valv;
2583  NumericVar basev;
2584  NumericVar offsetv;
2585  NumericVar sum;
2586 
2587  init_var_from_num(val, &valv);
2588  init_var_from_num(base, &basev);
2589  init_var_from_num(offset, &offsetv);
2590  init_var(&sum);
2591 
2592  if (sub)
2593  sub_var(&basev, &offsetv, &sum);
2594  else
2595  add_var(&basev, &offsetv, &sum);
2596 
2597  if (less)
2598  result = (cmp_var(&valv, &sum) <= 0);
2599  else
2600  result = (cmp_var(&valv, &sum) >= 0);
2601 
2602  free_var(&sum);
2603  }
2604 
2605  PG_FREE_IF_COPY(val, 0);
2606  PG_FREE_IF_COPY(base, 1);
2607  PG_FREE_IF_COPY(offset, 2);
2608 
2609  PG_RETURN_BOOL(result);
2610 }
int errcode(int sqlerrcode)
Definition: elog.c:698
#define PG_GETARG_BOOL(n)
Definition: fmgr.h:274
#define NUMERIC_IS_SPECIAL(n)
Definition: numeric.c:174
#define NUMERIC_NEG
Definition: numeric.c:168
#define ERROR
Definition: elog.h:46
#define NUMERIC_IS_PINF(n)
Definition: numeric.c:206
static void init_var_from_num(Numeric num, NumericVar *dest)
Definition: numeric.c:7006
#define NUMERIC_SIGN(n)
Definition: numeric.c:238
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:359
static int cmp_var(const NumericVar *var1, const NumericVar *var2)
Definition: numeric.c:7920
static void free_var(NumericVar *var)
Definition: numeric.c:6773
#define ereport(elevel,...)
Definition: elog.h:157
#define PG_GETARG_NUMERIC(n)
Definition: numeric.h:62
#define Assert(condition)
Definition: c.h:804
static void add_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition: numeric.c:7978
#define PG_FREE_IF_COPY(ptr, n)
Definition: fmgr.h:260
#define NUMERIC_IS_NINF(n)
Definition: numeric.c:207
int errmsg(const char *fmt,...)
Definition: elog.c:909
#define NUMERIC_IS_NAN(n)
Definition: numeric.c:205
static void sub_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition: numeric.c:8095
long val
Definition: informix.c:664
#define init_var(v)
Definition: numeric.c:486

◆ init_var_from_num()

static void init_var_from_num ( Numeric  num,
NumericVar dest 
)
static

Definition at line 7006 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(), numeric_abbrev_convert(), numeric_add_opt_error(), numeric_ceil(), numeric_div_opt_error(), numeric_div_trunc(), numeric_exp(), numeric_float8_no_overflow(), numeric_floor(), numeric_gcd(), numeric_inc(), numeric_int2(), numeric_int4_opt_error(), numeric_int8(), numeric_is_integral(), numeric_lcm(), numeric_ln(), numeric_log(), numeric_min_scale(), numeric_mod_opt_error(), numeric_mul_opt_error(), numeric_normalize(), numeric_out(), numeric_out_sci(), numeric_pg_lsn(), numeric_power(), numeric_send(), numeric_sqrt(), numeric_sub_opt_error(), and numeric_trim_scale().

7007 {
7008  dest->ndigits = NUMERIC_NDIGITS(num);
7009  dest->weight = NUMERIC_WEIGHT(num);
7010  dest->sign = NUMERIC_SIGN(num);
7011  dest->dscale = NUMERIC_DSCALE(num);
7012  dest->digits = NUMERIC_DIGITS(num);
7013  dest->buf = NULL; /* digits array is not palloc'd */
7014 }
#define NUMERIC_DSCALE(n)
Definition: numeric.c:244
int weight
Definition: numeric.c:308
int ndigits
Definition: numeric.c:307
int dscale
Definition: numeric.c:310
int sign
Definition: numeric.c:309
#define NUMERIC_DIGITS(num)
Definition: numeric.c:488
#define NUMERIC_SIGN(n)
Definition: numeric.c:238
NumericDigit * buf
Definition: numeric.c:311
#define NUMERIC_NDIGITS(num)
Definition: numeric.c:490
#define NUMERIC_WEIGHT(n)
Definition: numeric.c:248
NumericDigit * digits
Definition: numeric.c:312

◆ int2_accum()

Datum int2_accum ( PG_FUNCTION_ARGS  )

Definition at line 5350 of file numeric.c.

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

5351 {
5353 
5354  state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
5355 
5356  /* Create the state data on the first call */
5357  if (state == NULL)
5358  state = makePolyNumAggState(fcinfo, true);
5359 
5360  if (!PG_ARGISNULL(1))
5361  {
5362 #ifdef HAVE_INT128
5363  do_int128_accum(state, (int128) PG_GETARG_INT16(1));
5364 #else
5366 #endif
5367  }
5368 
5369  PG_RETURN_POINTER(state);
5370 }
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:361
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:276
static void do_numeric_accum(NumericAggState *state, Numeric newval)
Definition: numeric.c:4653
Numeric int64_to_numeric(int64 val)
Definition: numeric.c:4136
#define PG_GETARG_INT16(n)
Definition: fmgr.h:271
#define PG_ARGISNULL(n)
Definition: fmgr.h:209
Definition: regguts.h:317
#define makePolyNumAggState
Definition: numeric.c:5345

◆ int2_accum_inv()

Datum int2_accum_inv ( PG_FUNCTION_ARGS  )

Definition at line 5778 of file numeric.c.

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

5779 {
5781 
5782  state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
5783 
5784  /* Should not get here with no state */
5785  if (state == NULL)
5786  elog(ERROR, "int2_accum_inv called with NULL state");
5787 
5788  if (!PG_ARGISNULL(1))
5789  {
5790 #ifdef HAVE_INT128
5791  do_int128_discard(state, (int128) PG_GETARG_INT16(1));
5792 #else
5793  /* Should never fail, all inputs have dscale 0 */
5795  elog(ERROR, "do_numeric_discard failed unexpectedly");
5796 #endif
5797  }
5798 
5799  PG_RETURN_POINTER(state);
5800 }
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:361
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:276
static bool do_numeric_discard(NumericAggState *state, Numeric newval)
Definition: numeric.c:4723
#define ERROR
Definition: elog.h:46
Numeric int64_to_numeric(int64 val)
Definition: numeric.c:4136
#define PG_GETARG_INT16(n)
Definition: fmgr.h:271
#define PG_ARGISNULL(n)
Definition: fmgr.h:209
Definition: regguts.h:317
#define elog(elevel,...)
Definition: elog.h:232

◆ int2_avg_accum()

Datum int2_avg_accum ( PG_FUNCTION_ARGS  )

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

6462 {
6463  ArrayType *transarray;
6465  Int8TransTypeData *transdata;
6466 
6467  /*
6468  * If we're invoked as an aggregate, we can cheat and modify our first
6469  * parameter in-place to reduce palloc overhead. Otherwise we need to make
6470  * a copy of it before scribbling on it.
6471  */
6472  if (AggCheckCallContext(fcinfo, NULL))
6473  transarray = PG_GETARG_ARRAYTYPE_P(0);
6474  else
6475  transarray = PG_GETARG_ARRAYTYPE_P_COPY(0);
6476 
6477  if (ARR_HASNULL(transarray) ||
6478  ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
6479  elog(ERROR, "expected 2-element int8 array");
6480 
6481  transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
6482  transdata->count++;
6483  transdata->sum += newval;
6484 
6485  PG_RETURN_ARRAYTYPE_P(transarray);
6486 }
signed short int16
Definition: c.h:428
#define ARR_OVERHEAD_NONULLS(ndims)
Definition: array.h:303
#define ARR_SIZE(a)
Definition: array.h:282
#define PG_GETARG_ARRAYTYPE_P_COPY(n)
Definition: array.h:257
#define PG_GETARG_ARRAYTYPE_P(n)
Definition: array.h:256
#define ERROR
Definition: elog.h:46
#define ARR_DATA_PTR(a)
Definition: array.h:315
#define ARR_HASNULL(a)
Definition: array.h:284
#define PG_RETURN_ARRAYTYPE_P(x)
Definition: array.h:258
#define PG_GETARG_INT16(n)
Definition: fmgr.h:271
#define newval
int AggCheckCallContext(FunctionCallInfo fcinfo, MemoryContext *aggcontext)
Definition: nodeAgg.c:4495
#define elog(elevel,...)
Definition: elog.h:232

◆ int2_avg_accum_inv()

Datum int2_avg_accum_inv ( PG_FUNCTION_ARGS  )

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

6549 {
6550  ArrayType *transarray;
6552  Int8TransTypeData *transdata;
6553 
6554  /*
6555  * If we're invoked as an aggregate, we can cheat and modify our first
6556  * parameter in-place to reduce palloc overhead. Otherwise we need to make
6557  * a copy of it before scribbling on it.
6558  */
6559  if (AggCheckCallContext(fcinfo, NULL))
6560  transarray = PG_GETARG_ARRAYTYPE_P(0);
6561  else
6562  transarray = PG_GETARG_ARRAYTYPE_P_COPY(0);
6563 
6564  if (ARR_HASNULL(transarray) ||
6565  ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
6566  elog(ERROR, "expected 2-element int8 array");
6567 
6568  transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
6569  transdata->count--;
6570  transdata->sum -= newval;
6571 
6572  PG_RETURN_ARRAYTYPE_P(transarray);
6573 }
signed short int16
Definition: c.h:428
#define ARR_OVERHEAD_NONULLS(ndims)
Definition: array.h:303
#define ARR_SIZE(a)
Definition: array.h:282
#define PG_GETARG_ARRAYTYPE_P_COPY(n)
Definition: array.h:257
#define PG_GETARG_ARRAYTYPE_P(n)
Definition: array.h:256
#define ERROR
Definition: elog.h:46
#define ARR_DATA_PTR(a)
Definition: array.h:315
#define ARR_HASNULL(a)
Definition: array.h:284
#define PG_RETURN_ARRAYTYPE_P(x)
Definition: array.h:258
#define PG_GETARG_INT16(n)
Definition: fmgr.h:271
#define newval
int AggCheckCallContext(FunctionCallInfo fcinfo, MemoryContext *aggcontext)
Definition: nodeAgg.c:4495
#define elog(elevel,...)
Definition: elog.h:232

◆ int2_numeric()

Datum int2_numeric ( PG_FUNCTION_ARGS  )

Definition at line 4342 of file numeric.c.

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

4343 {
4344  int16 val = PG_GETARG_INT16(0);
4345 
4347 }
#define PG_RETURN_NUMERIC(x)
Definition: numeric.h:64
signed short int16
Definition: c.h:428
Numeric int64_to_numeric(int64 val)
Definition: numeric.c:4136
#define PG_GETARG_INT16(n)
Definition: fmgr.h:271
long val
Definition: informix.c:664

◆ int2_sum()

Datum int2_sum ( PG_FUNCTION_ARGS  )

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

6313 {
6314  int64 newval;
6315 
6316  if (PG_ARGISNULL(0))
6317  {
6318  /* No non-null input seen so far... */
6319  if (PG_ARGISNULL(1))
6320  PG_RETURN_NULL(); /* still no non-null */
6321  /* This is the first non-null input. */
6322  newval = (int64) PG_GETARG_INT16(1);
6323  PG_RETURN_INT64(newval);
6324  }
6325 
6326  /*
6327  * If we're invoked as an aggregate, we can cheat and modify our first
6328  * parameter in-place to avoid palloc overhead. If not, we need to return
6329  * the new value of the transition variable. (If int8 is pass-by-value,
6330  * then of course this is useless as well as incorrect, so just ifdef it
6331  * out.)
6332  */
6333 #ifndef USE_FLOAT8_BYVAL /* controls int8 too */
6334  if (AggCheckCallContext(fcinfo, NULL))
6335  {
6336  int64 *oldsum = (int64 *) PG_GETARG_POINTER(0);
6337 
6338  /* Leave the running sum unchanged in the new input is null */
6339  if (!PG_ARGISNULL(1))
6340  *oldsum = *oldsum + (int64) PG_GETARG_INT16(1);
6341 
6342  PG_RETURN_POINTER(oldsum);
6343  }
6344  else
6345 #endif
6346  {
6347  int64 oldsum = PG_GETARG_INT64(0);
6348 
6349  /* Leave sum unchanged if new input is null. */
6350  if (PG_ARGISNULL(1))
6351  PG_RETURN_INT64(oldsum);
6352 
6353  /* OK to do the addition. */
6354  newval = oldsum + (int64) PG_GETARG_INT16(1);
6355 
6356  PG_RETURN_INT64(newval);
6357  }
6358 }
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:361
#define PG_RETURN_INT64(x)
Definition: fmgr.h:368
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:276
#define PG_GETARG_INT16(n)
Definition: fmgr.h:271
#define PG_ARGISNULL(n)
Definition: fmgr.h:209
#define newval
int AggCheckCallContext(FunctionCallInfo fcinfo, MemoryContext *aggcontext)
Definition: nodeAgg.c:4495
#define PG_GETARG_INT64(n)
Definition: fmgr.h:283
#define PG_RETURN_NULL()
Definition: