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

Go to the source code of this file.

Data Structures

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

Macros

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

Typedefs

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

Functions

static void alloc_var (NumericVar *var, int ndigits)
 
static void free_var (NumericVar *var)
 
static void zero_var (NumericVar *var)
 
static bool set_var_from_str (const char *str, const char *cp, NumericVar *dest, const char **endptr, Node *escontext)
 
static bool set_var_from_non_decimal_integer_str (const char *str, const char *cp, int sign, int base, NumericVar *dest, const char **endptr, Node *escontext)
 
static void set_var_from_num (Numeric num, NumericVar *dest)
 
static void init_var_from_num (Numeric num, NumericVar *dest)
 
static void set_var_from_var (const NumericVar *value, NumericVar *dest)
 
static char * get_str_from_var (const NumericVar *var)
 
static char * get_str_from_var_sci (const NumericVar *var, int rscale)
 
static void numericvar_serialize (StringInfo buf, const NumericVar *var)
 
static void numericvar_deserialize (StringInfo buf, NumericVar *var)
 
static Numeric duplicate_numeric (Numeric num)
 
static Numeric make_result (const NumericVar *var)
 
static Numeric make_result_opt_error (const NumericVar *var, bool *have_error)
 
static bool apply_typmod (NumericVar *var, int32 typmod, Node *escontext)
 
static bool apply_typmod_special (Numeric num, int32 typmod, Node *escontext)
 
static bool numericvar_to_int32 (const NumericVar *var, int32 *result)
 
static bool numericvar_to_int64 (const NumericVar *var, int64 *result)
 
static void int64_to_numericvar (int64 val, NumericVar *var)
 
static bool numericvar_to_uint64 (const NumericVar *var, uint64 *result)
 
static double numericvar_to_double_no_overflow (const NumericVar *var)
 
static Datum numeric_abbrev_convert (Datum original_datum, SortSupport ssup)
 
static bool numeric_abbrev_abort (int memtupcount, SortSupport ssup)
 
static int numeric_fast_cmp (Datum x, Datum y, SortSupport ssup)
 
static int numeric_cmp_abbrev (Datum x, Datum y, SortSupport ssup)
 
static Datum numeric_abbrev_convert_var (const NumericVar *var, NumericSortSupport *nss)
 
static int cmp_numerics (Numeric num1, Numeric num2)
 
static int cmp_var (const NumericVar *var1, const NumericVar *var2)
 
static int cmp_var_common (const NumericDigit *var1digits, int var1ndigits, int var1weight, int var1sign, const NumericDigit *var2digits, int var2ndigits, int var2weight, int var2sign)
 
static void add_var (const NumericVar *var1, const NumericVar *var2, NumericVar *result)
 
static void sub_var (const NumericVar *var1, const NumericVar *var2, NumericVar *result)
 
static void mul_var (const NumericVar *var1, const NumericVar *var2, NumericVar *result, int rscale)
 
static void mul_var_short (const NumericVar *var1, const NumericVar *var2, NumericVar *result)
 
static void div_var (const NumericVar *var1, const NumericVar *var2, NumericVar *result, int rscale, bool round)
 
static void div_var_fast (const NumericVar *var1, const NumericVar *var2, NumericVar *result, int rscale, bool round)
 
static void div_var_int (const NumericVar *var, int ival, int ival_weight, NumericVar *result, int rscale, bool round)
 
static int select_div_scale (const NumericVar *var1, const NumericVar *var2)
 
static void mod_var (const NumericVar *var1, const NumericVar *var2, NumericVar *result)
 
static void div_mod_var (const NumericVar *var1, const NumericVar *var2, NumericVar *quot, NumericVar *rem)
 
static void ceil_var (const NumericVar *var, NumericVar *result)
 
static void floor_var (const NumericVar *var, NumericVar *result)
 
static void gcd_var (const NumericVar *var1, const NumericVar *var2, NumericVar *result)
 
static void sqrt_var (const NumericVar *arg, NumericVar *result, int rscale)
 
static void exp_var (const NumericVar *arg, NumericVar *result, int rscale)
 
static int estimate_ln_dweight (const NumericVar *var)
 
static void ln_var (const NumericVar *arg, NumericVar *result, int rscale)
 
static void log_var (const NumericVar *base, const NumericVar *num, NumericVar *result)
 
static void power_var (const NumericVar *base, const NumericVar *exp, NumericVar *result)
 
static void power_var_int (const NumericVar *base, int exp, int exp_dscale, NumericVar *result)
 
static void power_ten_int (int exp, NumericVar *result)
 
static void random_var (pg_prng_state *state, const NumericVar *rmin, const NumericVar *rmax, NumericVar *result)
 
static int cmp_abs (const NumericVar *var1, const NumericVar *var2)
 
static int cmp_abs_common (const NumericDigit *var1digits, int var1ndigits, int var1weight, const NumericDigit *var2digits, int var2ndigits, int var2weight)
 
static void add_abs (const NumericVar *var1, const NumericVar *var2, NumericVar *result)
 
static void sub_abs (const NumericVar *var1, const NumericVar *var2, NumericVar *result)
 
static void round_var (NumericVar *var, int rscale)
 
static void trunc_var (NumericVar *var, int rscale)
 
static void strip_var (NumericVar *var)
 
static void compute_bucket (Numeric operand, Numeric bound1, Numeric bound2, const NumericVar *count_var, NumericVar *result_var)
 
static void accum_sum_add (NumericSumAccum *accum, const NumericVar *val)
 
static void accum_sum_rescale (NumericSumAccum *accum, const NumericVar *val)
 
static void accum_sum_carry (NumericSumAccum *accum)
 
static void accum_sum_reset (NumericSumAccum *accum)
 
static void accum_sum_final (NumericSumAccum *accum, NumericVar *result)
 
static void accum_sum_copy (NumericSumAccum *dst, NumericSumAccum *src)
 
static void accum_sum_combine (NumericSumAccum *accum, NumericSumAccum *accum2)
 
Datum numeric_in (PG_FUNCTION_ARGS)
 
Datum numeric_out (PG_FUNCTION_ARGS)
 
bool numeric_is_nan (Numeric num)
 
bool numeric_is_inf (Numeric num)
 
static bool numeric_is_integral (Numeric num)
 
static int32 make_numeric_typmod (int precision, int scale)
 
static bool is_valid_numeric_typmod (int32 typmod)
 
static int numeric_typmod_precision (int32 typmod)
 
static int numeric_typmod_scale (int32 typmod)
 
int32 numeric_maximum_size (int32 typmod)
 
char * numeric_out_sci (Numeric num, int scale)
 
char * numeric_normalize (Numeric num)
 
Datum numeric_recv (PG_FUNCTION_ARGS)
 
Datum numeric_send (PG_FUNCTION_ARGS)
 
Datum numeric_support (PG_FUNCTION_ARGS)
 
Datum numeric (PG_FUNCTION_ARGS)
 
Datum numerictypmodin (PG_FUNCTION_ARGS)
 
Datum numerictypmodout (PG_FUNCTION_ARGS)
 
Datum numeric_abs (PG_FUNCTION_ARGS)
 
Datum numeric_uminus (PG_FUNCTION_ARGS)
 
Datum numeric_uplus (PG_FUNCTION_ARGS)
 
static int numeric_sign_internal (Numeric num)
 
Datum numeric_sign (PG_FUNCTION_ARGS)
 
Datum numeric_round (PG_FUNCTION_ARGS)
 
Datum numeric_trunc (PG_FUNCTION_ARGS)
 
Datum numeric_ceil (PG_FUNCTION_ARGS)
 
Datum numeric_floor (PG_FUNCTION_ARGS)
 
Datum generate_series_numeric (PG_FUNCTION_ARGS)
 
Datum generate_series_step_numeric (PG_FUNCTION_ARGS)
 
Datum width_bucket_numeric (PG_FUNCTION_ARGS)
 
Datum numeric_sortsupport (PG_FUNCTION_ARGS)
 
Datum numeric_cmp (PG_FUNCTION_ARGS)
 
Datum numeric_eq (PG_FUNCTION_ARGS)
 
Datum numeric_ne (PG_FUNCTION_ARGS)
 
Datum numeric_gt (PG_FUNCTION_ARGS)
 
Datum numeric_ge (PG_FUNCTION_ARGS)
 
Datum numeric_lt (PG_FUNCTION_ARGS)
 
Datum numeric_le (PG_FUNCTION_ARGS)
 
Datum in_range_numeric_numeric (PG_FUNCTION_ARGS)
 
Datum hash_numeric (PG_FUNCTION_ARGS)
 
Datum hash_numeric_extended (PG_FUNCTION_ARGS)
 
Datum numeric_add (PG_FUNCTION_ARGS)
 
Numeric numeric_add_opt_error (Numeric num1, Numeric num2, bool *have_error)
 
Datum numeric_sub (PG_FUNCTION_ARGS)
 
Numeric numeric_sub_opt_error (Numeric num1, Numeric num2, bool *have_error)
 
Datum numeric_mul (PG_FUNCTION_ARGS)
 
Numeric numeric_mul_opt_error (Numeric num1, Numeric num2, bool *have_error)
 
Datum numeric_div (PG_FUNCTION_ARGS)
 
Numeric numeric_div_opt_error (Numeric num1, Numeric num2, bool *have_error)
 
Datum numeric_div_trunc (PG_FUNCTION_ARGS)
 
Datum numeric_mod (PG_FUNCTION_ARGS)
 
Numeric numeric_mod_opt_error (Numeric num1, Numeric num2, bool *have_error)
 
Datum numeric_inc (PG_FUNCTION_ARGS)
 
Datum numeric_smaller (PG_FUNCTION_ARGS)
 
Datum numeric_larger (PG_FUNCTION_ARGS)
 
Datum numeric_gcd (PG_FUNCTION_ARGS)
 
Datum numeric_lcm (PG_FUNCTION_ARGS)
 
Datum numeric_fac (PG_FUNCTION_ARGS)
 
Datum numeric_sqrt (PG_FUNCTION_ARGS)
 
Datum numeric_exp (PG_FUNCTION_ARGS)
 
Datum numeric_ln (PG_FUNCTION_ARGS)
 
Datum numeric_log (PG_FUNCTION_ARGS)
 
Datum numeric_power (PG_FUNCTION_ARGS)
 
Datum numeric_scale (PG_FUNCTION_ARGS)
 
static int get_min_scale (NumericVar *var)
 
Datum numeric_min_scale (PG_FUNCTION_ARGS)
 
Datum numeric_trim_scale (PG_FUNCTION_ARGS)
 
Numeric random_numeric (pg_prng_state *state, Numeric rmin, Numeric rmax)
 
Numeric int64_to_numeric (int64 val)
 
Numeric int64_div_fast_to_numeric (int64 val1, int log10val2)
 
Datum int4_numeric (PG_FUNCTION_ARGS)
 
int32 numeric_int4_opt_error (Numeric num, bool *have_error)
 
Datum numeric_int4 (PG_FUNCTION_ARGS)
 
Datum int8_numeric (PG_FUNCTION_ARGS)
 
int64 numeric_int8_opt_error (Numeric num, bool *have_error)
 
Datum numeric_int8 (PG_FUNCTION_ARGS)
 
Datum int2_numeric (PG_FUNCTION_ARGS)
 
Datum numeric_int2 (PG_FUNCTION_ARGS)
 
Datum float8_numeric (PG_FUNCTION_ARGS)
 
Datum numeric_float8 (PG_FUNCTION_ARGS)
 
Datum numeric_float8_no_overflow (PG_FUNCTION_ARGS)
 
Datum float4_numeric (PG_FUNCTION_ARGS)
 
Datum numeric_float4 (PG_FUNCTION_ARGS)
 
Datum numeric_pg_lsn (PG_FUNCTION_ARGS)
 
static NumericAggStatemakeNumericAggState (FunctionCallInfo fcinfo, bool calcSumX2)
 
static NumericAggStatemakeNumericAggStateCurrentContext (bool calcSumX2)
 
static void do_numeric_accum (NumericAggState *state, Numeric newval)
 
static bool do_numeric_discard (NumericAggState *state, Numeric newval)
 
Datum numeric_accum (PG_FUNCTION_ARGS)
 
Datum numeric_combine (PG_FUNCTION_ARGS)
 
Datum numeric_avg_accum (PG_FUNCTION_ARGS)
 
Datum numeric_avg_combine (PG_FUNCTION_ARGS)
 
Datum numeric_avg_serialize (PG_FUNCTION_ARGS)
 
Datum numeric_avg_deserialize (PG_FUNCTION_ARGS)
 
Datum numeric_serialize (PG_FUNCTION_ARGS)
 
Datum numeric_deserialize (PG_FUNCTION_ARGS)
 
Datum numeric_accum_inv (PG_FUNCTION_ARGS)
 
Datum int2_accum (PG_FUNCTION_ARGS)
 
Datum int4_accum (PG_FUNCTION_ARGS)
 
Datum int8_accum (PG_FUNCTION_ARGS)
 
Datum numeric_poly_combine (PG_FUNCTION_ARGS)
 
Datum numeric_poly_serialize (PG_FUNCTION_ARGS)
 
Datum numeric_poly_deserialize (PG_FUNCTION_ARGS)
 
Datum int8_avg_accum (PG_FUNCTION_ARGS)
 
Datum int8_avg_combine (PG_FUNCTION_ARGS)
 
Datum int8_avg_serialize (PG_FUNCTION_ARGS)
 
Datum int8_avg_deserialize (PG_FUNCTION_ARGS)
 
Datum int2_accum_inv (PG_FUNCTION_ARGS)
 
Datum int4_accum_inv (PG_FUNCTION_ARGS)
 
Datum int8_accum_inv (PG_FUNCTION_ARGS)
 
Datum int8_avg_accum_inv (PG_FUNCTION_ARGS)
 
Datum numeric_poly_sum (PG_FUNCTION_ARGS)
 
Datum numeric_poly_avg (PG_FUNCTION_ARGS)
 
Datum numeric_avg (PG_FUNCTION_ARGS)
 
Datum numeric_sum (PG_FUNCTION_ARGS)
 
static Numeric numeric_stddev_internal (NumericAggState *state, bool variance, bool sample, bool *is_null)
 
Datum numeric_var_samp (PG_FUNCTION_ARGS)
 
Datum numeric_stddev_samp (PG_FUNCTION_ARGS)
 
Datum numeric_var_pop (PG_FUNCTION_ARGS)
 
Datum numeric_stddev_pop (PG_FUNCTION_ARGS)
 
Datum numeric_poly_var_samp (PG_FUNCTION_ARGS)
 
Datum numeric_poly_stddev_samp (PG_FUNCTION_ARGS)
 
Datum numeric_poly_var_pop (PG_FUNCTION_ARGS)
 
Datum numeric_poly_stddev_pop (PG_FUNCTION_ARGS)
 
Datum int2_sum (PG_FUNCTION_ARGS)
 
Datum int4_sum (PG_FUNCTION_ARGS)
 
Datum int8_sum (PG_FUNCTION_ARGS)
 
Datum int2_avg_accum (PG_FUNCTION_ARGS)
 
Datum int4_avg_accum (PG_FUNCTION_ARGS)
 
Datum int4_avg_combine (PG_FUNCTION_ARGS)
 
Datum int2_avg_accum_inv (PG_FUNCTION_ARGS)
 
Datum int4_avg_accum_inv (PG_FUNCTION_ARGS)
 
Datum int8_avg (PG_FUNCTION_ARGS)
 
Datum int2int4_sum (PG_FUNCTION_ARGS)
 
static int xdigit_value (char dig)
 

Variables

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

Macro Definition Documentation

◆ DatumGetNumericAbbrev

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

Definition at line 410 of file numeric.c.

◆ DEC_DIGITS

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

Definition at line 97 of file numeric.c.

◆ digitbuf_alloc

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

Definition at line 483 of file numeric.c.

◆ digitbuf_free

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

Definition at line 485 of file numeric.c.

◆ DIV_GUARD_DIGITS

#define DIV_GUARD_DIGITS   4

Definition at line 99 of file numeric.c.

◆ dump_numeric

#define dump_numeric (   s,
 
)

Definition at line 479 of file numeric.c.

◆ dump_var

#define dump_var (   s,
 
)

Definition at line 480 of file numeric.c.

◆ HALF_NBASE

#define HALF_NBASE   5000

Definition at line 96 of file numeric.c.

◆ init_var

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

Definition at line 491 of file numeric.c.

◆ makePolyNumAggState

#define makePolyNumAggState   makeNumericAggState

Definition at line 5549 of file numeric.c.

◆ makePolyNumAggStateCurrentContext

#define makePolyNumAggStateCurrentContext   makeNumericAggStateCurrentContext

Definition at line 5550 of file numeric.c.

◆ MUL_GUARD_DIGITS

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

Definition at line 98 of file numeric.c.

◆ NA_TOTAL_COUNT

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

Definition at line 4813 of file numeric.c.

◆ NBASE

#define NBASE   10000

Definition at line 95 of file numeric.c.

◆ NUMERIC_ABBREV_BITS

#define NUMERIC_ABBREV_BITS   (SIZEOF_DATUM * BITS_PER_BYTE)

Definition at line 401 of file numeric.c.

◆ NUMERIC_ABBREV_NAN

#define NUMERIC_ABBREV_NAN   NumericAbbrevGetDatum(PG_INT32_MIN)

Definition at line 411 of file numeric.c.

◆ NUMERIC_ABBREV_NINF

#define NUMERIC_ABBREV_NINF   NumericAbbrevGetDatum(PG_INT32_MAX)

Definition at line 413 of file numeric.c.

◆ NUMERIC_ABBREV_PINF

#define NUMERIC_ABBREV_PINF   NumericAbbrevGetDatum(-PG_INT32_MAX)

Definition at line 412 of file numeric.c.

◆ NUMERIC_CAN_BE_SHORT

#define NUMERIC_CAN_BE_SHORT (   scale,
  weight 
)
Value:
(weight) <= NUMERIC_SHORT_WEIGHT_MAX && \
#define NUMERIC_SHORT_DSCALE_MAX
Definition: numeric.c:216
#define NUMERIC_SHORT_WEIGHT_MIN
Definition: numeric.c:221
#define NUMERIC_SHORT_WEIGHT_MAX
Definition: numeric.c:220
static int scale
Definition: pgbench.c:181

Definition at line 497 of file numeric.c.

◆ NUMERIC_DIGITS

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

Definition at line 493 of file numeric.c.

◆ NUMERIC_DSCALE

#define NUMERIC_DSCALE (   n)
Value:
((n)->choice.n_short.n_header & NUMERIC_SHORT_DSCALE_MASK) \
: ((n)->choice.n_long.n_sign_dscale & NUMERIC_DSCALE_MASK))
#define NUMERIC_DSCALE_MASK
Definition: numeric.c:233
#define NUMERIC_SHORT_DSCALE_MASK
Definition: numeric.c:214
#define NUMERIC_SHORT_DSCALE_SHIFT
Definition: numeric.c:215

Definition at line 242 of file numeric.c.

◆ NUMERIC_DSCALE_MASK

#define NUMERIC_DSCALE_MASK   0x3FFF

Definition at line 233 of file numeric.c.

◆ NUMERIC_DSCALE_MAX

#define NUMERIC_DSCALE_MAX   NUMERIC_DSCALE_MASK

Definition at line 234 of file numeric.c.

◆ NUMERIC_EXT_FLAGBITS

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

Definition at line 202 of file numeric.c.

◆ NUMERIC_EXT_SIGN_MASK

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

Definition at line 196 of file numeric.c.

◆ NUMERIC_FLAGBITS

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

Definition at line 170 of file numeric.c.

◆ NUMERIC_HDRSZ

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

Definition at line 174 of file numeric.c.

◆ NUMERIC_HDRSZ_SHORT

#define NUMERIC_HDRSZ_SHORT   (VARHDRSZ + sizeof(uint16))

Definition at line 175 of file numeric.c.

◆ NUMERIC_HEADER_IS_SHORT

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

Definition at line 182 of file numeric.c.

◆ NUMERIC_HEADER_SIZE

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

Definition at line 183 of file numeric.c.

◆ NUMERIC_INF_SIGN_MASK

#define NUMERIC_INF_SIGN_MASK   0x2000

Definition at line 200 of file numeric.c.

◆ NUMERIC_IS_INF

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

Definition at line 206 of file numeric.c.

◆ NUMERIC_IS_NAN

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

Definition at line 203 of file numeric.c.

◆ NUMERIC_IS_NINF

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

Definition at line 205 of file numeric.c.

◆ NUMERIC_IS_PINF

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

Definition at line 204 of file numeric.c.

◆ NUMERIC_IS_SHORT

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

Definition at line 171 of file numeric.c.

◆ NUMERIC_IS_SPECIAL

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

Definition at line 172 of file numeric.c.

◆ NUMERIC_NAN

#define NUMERIC_NAN   0xC000

Definition at line 197 of file numeric.c.

◆ NUMERIC_NDIGITS

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

Definition at line 495 of file numeric.c.

◆ NUMERIC_NEG

#define NUMERIC_NEG   0x4000

Definition at line 166 of file numeric.c.

◆ NUMERIC_NINF

#define NUMERIC_NINF   0xF000

Definition at line 199 of file numeric.c.

◆ NUMERIC_PINF

#define NUMERIC_PINF   0xD000

Definition at line 198 of file numeric.c.

◆ NUMERIC_POS

#define NUMERIC_POS   0x0000

Definition at line 165 of file numeric.c.

◆ NUMERIC_SHORT

#define NUMERIC_SHORT   0x8000

Definition at line 167 of file numeric.c.

◆ NUMERIC_SHORT_DSCALE_MASK

#define NUMERIC_SHORT_DSCALE_MASK   0x1F80

Definition at line 214 of file numeric.c.

◆ NUMERIC_SHORT_DSCALE_MAX

#define NUMERIC_SHORT_DSCALE_MAX    (NUMERIC_SHORT_DSCALE_MASK >> NUMERIC_SHORT_DSCALE_SHIFT)

Definition at line 216 of file numeric.c.

◆ NUMERIC_SHORT_DSCALE_SHIFT

#define NUMERIC_SHORT_DSCALE_SHIFT   7

Definition at line 215 of file numeric.c.

◆ NUMERIC_SHORT_SIGN_MASK

#define NUMERIC_SHORT_SIGN_MASK   0x2000

Definition at line 213 of file numeric.c.

◆ NUMERIC_SHORT_WEIGHT_MASK

#define NUMERIC_SHORT_WEIGHT_MASK   0x003F

Definition at line 219 of file numeric.c.

◆ NUMERIC_SHORT_WEIGHT_MAX

#define NUMERIC_SHORT_WEIGHT_MAX   NUMERIC_SHORT_WEIGHT_MASK

Definition at line 220 of file numeric.c.

◆ NUMERIC_SHORT_WEIGHT_MIN

#define NUMERIC_SHORT_WEIGHT_MIN   (-(NUMERIC_SHORT_WEIGHT_MASK+1))

Definition at line 221 of file numeric.c.

◆ NUMERIC_SHORT_WEIGHT_SIGN_MASK

#define NUMERIC_SHORT_WEIGHT_SIGN_MASK   0x0040

Definition at line 218 of file numeric.c.

◆ NUMERIC_SIGN

#define NUMERIC_SIGN (   n)
Value:
(((n)->choice.n_short.n_header & NUMERIC_SHORT_SIGN_MASK) ? \
NUMERIC_NEG : NUMERIC_POS) : \
NUMERIC_EXT_FLAGBITS(n) : NUMERIC_FLAGBITS(n)))
#define NUMERIC_IS_SPECIAL(n)
Definition: numeric.c:172
#define NUMERIC_FLAGBITS(n)
Definition: numeric.c:170
#define NUMERIC_SHORT_SIGN_MASK
Definition: numeric.c:213
#define NUMERIC_IS_SHORT(n)
Definition: numeric.c:171
#define NUMERIC_POS
Definition: numeric.c:165

Definition at line 236 of file numeric.c.

◆ NUMERIC_SIGN_MASK

#define NUMERIC_SIGN_MASK   0xC000

Definition at line 164 of file numeric.c.

◆ NUMERIC_SPECIAL

#define NUMERIC_SPECIAL   0xC000

Definition at line 168 of file numeric.c.

◆ NUMERIC_WEIGHT

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

Definition at line 246 of file numeric.c.

◆ NUMERIC_WEIGHT_MAX

#define NUMERIC_WEIGHT_MAX   PG_INT16_MAX

Definition at line 257 of file numeric.c.

◆ NumericAbbrevGetDatum

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

Definition at line 409 of file numeric.c.

Typedef Documentation

◆ Int8TransTypeData

◆ NumericAggState

◆ NumericDigit

Definition at line 101 of file numeric.c.

◆ NumericSumAccum

◆ NumericVar

typedef struct NumericVar NumericVar

◆ PolyNumAggState

Definition at line 5548 of file numeric.c.

Function Documentation

◆ accum_sum_add()

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

Definition at line 12196 of file numeric.c.

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

References accum_sum_carry(), accum_sum_rescale(), i, NBASE, NumericSumAccum::neg_digits, NumericSumAccum::num_uncarried, NUMERIC_POS, NumericSumAccum::pos_digits, val, and NumericSumAccum::weight.

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

◆ accum_sum_carry()

static void accum_sum_carry ( NumericSumAccum accum)
static

Definition at line 12244 of file numeric.c.

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

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

Referenced by accum_sum_add(), and accum_sum_final().

◆ accum_sum_combine()

static void accum_sum_combine ( NumericSumAccum accum,
NumericSumAccum accum2 
)
static

Definition at line 12474 of file numeric.c.

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

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

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

◆ accum_sum_copy()

static void accum_sum_copy ( NumericSumAccum dst,
NumericSumAccum src 
)
static

Definition at line 12457 of file numeric.c.

12458 {
12459  dst->pos_digits = palloc(src->ndigits * sizeof(int32));
12460  dst->neg_digits = palloc(src->ndigits * sizeof(int32));
12461 
12462  memcpy(dst->pos_digits, src->pos_digits, src->ndigits * sizeof(int32));
12463  memcpy(dst->neg_digits, src->neg_digits, src->ndigits * sizeof(int32));
12464  dst->num_uncarried = src->num_uncarried;
12465  dst->ndigits = src->ndigits;
12466  dst->weight = src->weight;
12467  dst->dscale = src->dscale;
12468 }
void * palloc(Size size)
Definition: mcxt.c:1317

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

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

◆ accum_sum_final()

static void accum_sum_final ( NumericSumAccum accum,
NumericVar result 
)
static

Definition at line 12406 of file numeric.c.

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

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

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

◆ accum_sum_rescale()

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

Definition at line 12317 of file numeric.c.

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

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

Referenced by accum_sum_add().

◆ accum_sum_reset()

static void accum_sum_reset ( NumericSumAccum accum)
static

Definition at line 12180 of file numeric.c.

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

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

Referenced by do_numeric_discard().

◆ add_abs()

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

Definition at line 11804 of file numeric.c.

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

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

Referenced by add_var(), and sub_var().

◆ add_var()

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

Definition at line 8435 of file numeric.c.

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

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

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

◆ alloc_var()

static void alloc_var ( NumericVar var,
int  ndigits 
)
static

Definition at line 6957 of file numeric.c.

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

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

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

◆ apply_typmod()

static bool apply_typmod ( NumericVar var,
int32  typmod,
Node escontext 
)
static

Definition at line 7911 of file numeric.c.

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

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

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

◆ apply_typmod_special()

static bool apply_typmod_special ( Numeric  num,
int32  typmod,
Node escontext 
)
static

Definition at line 7996 of file numeric.c.

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

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

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

◆ ceil_var()

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

Definition at line 10165 of file numeric.c.

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

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

Referenced by numeric_ceil().

◆ cmp_abs()

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

Definition at line 11726 of file numeric.c.

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

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

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

◆ cmp_abs_common()

static int cmp_abs_common ( const NumericDigit var1digits,
int  var1ndigits,
int  var1weight,
const NumericDigit var2digits,
int  var2ndigits,
int  var2weight 
)
static

Definition at line 11740 of file numeric.c.

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

Referenced by cmp_abs(), and cmp_var_common().

◆ cmp_numerics()

static int cmp_numerics ( Numeric  num1,
Numeric  num2 
)
static

Definition at line 2509 of file numeric.c.

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

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

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

◆ cmp_var()

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

◆ cmp_var_common()

static int cmp_var_common ( const NumericDigit var1digits,
int  var1ndigits,
int  var1weight,
int  var1sign,
const NumericDigit var2digits,
int  var2ndigits,
int  var2weight,
int  var2sign 
)
static

Definition at line 8392 of file numeric.c.

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

References cmp_abs_common(), NUMERIC_NEG, and NUMERIC_POS.

Referenced by cmp_numerics(), and cmp_var().

◆ compute_bucket()

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

Definition at line 1934 of file numeric.c.

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

References add_var(), const_one, div_var(), NumericVar::dscale, free_var(), init_var_from_num(), mul_var(), and sub_var().

Referenced by width_bucket_numeric().

◆ div_mod_var()

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

Definition at line 10095 of file numeric.c.

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

References add_var(), cmp_abs(), const_one, div_var_fast(), NumericVar::dscale, free_var(), init_var, mul_var(), NumericVar::ndigits, set_var_from_var(), NumericVar::sign, and sub_var().

Referenced by sqrt_var().

◆ div_var()

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

Definition at line 9097 of file numeric.c.

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

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

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

◆ div_var_fast()

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

Definition at line 9405 of file numeric.c.

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

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

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

◆ div_var_int()

static void div_var_int ( const NumericVar var,
int  ival,
int  ival_weight,
NumericVar result,
int  rscale,
bool  round 
)
static

Definition at line 9769 of file numeric.c.

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

References NumericVar::buf, DEC_DIGITS, digitbuf_alloc, digitbuf_free, NumericVar::digits, NumericVar::dscale, ereport, errcode(), errmsg(), ERROR, i, Max, NBASE, NumericVar::ndigits, NUMERIC_NEG, NUMERIC_POS, round_var(), NumericVar::sign, strip_var(), trunc_var(), NumericVar::weight, and zero_var().

Referenced by div_var(), div_var_fast(), exp_var(), and ln_var().

◆ do_numeric_accum()

static void do_numeric_accum ( NumericAggState state,
Numeric  newval 
)
static

Definition at line 4861 of file numeric.c.

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

References accum_sum_add(), NumericVar::dscale, init_var, init_var_from_num(), MemoryContextSwitchTo(), mul_var(), newval, NUMERIC_IS_NINF, NUMERIC_IS_PINF, and NUMERIC_IS_SPECIAL.

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

◆ do_numeric_discard()

static bool do_numeric_discard ( NumericAggState state,
Numeric  newval 
)
static

Definition at line 4931 of file numeric.c.

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

References accum_sum_add(), accum_sum_reset(), Assert, NumericVar::dscale, init_var, init_var_from_num(), MemoryContextSwitchTo(), mul_var(), newval, NUMERIC_IS_NINF, NUMERIC_IS_PINF, NUMERIC_IS_SPECIAL, NUMERIC_NEG, NUMERIC_POS, and NumericVar::sign.

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

◆ duplicate_numeric()

static Numeric duplicate_numeric ( Numeric  num)
static

Definition at line 7767 of file numeric.c.

7768 {
7769  Numeric res;
7770 
7771  res = (Numeric) palloc(VARSIZE(num));
7772  memcpy(res, num, VARSIZE(num));
7773  return res;
7774 }
struct NumericData * Numeric
Definition: numeric.h:54
#define VARSIZE(PTR)
Definition: varatt.h:279

References palloc(), res, and VARSIZE.

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

◆ estimate_ln_dweight()

static int estimate_ln_dweight ( const NumericVar var)
static

Definition at line 10891 of file numeric.c.

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

References cmp_var(), const_one, const_one_point_one, const_zero_point_nine, DEC_DIGITS, NumericVar::digits, digits, free_var(), init_var, ln_var(), NBASE, NumericVar::ndigits, NUMERIC_POS, NumericVar::sign, sub_var(), NumericVar::weight, and x.

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

◆ exp_var()

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

Definition at line 10762 of file numeric.c.

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

References add_var(), arg, const_one, DEC_DIGITS, div_var_int(), NumericVar::dscale, ereport, errcode(), errmsg(), ERROR, free_var(), init_var, Max, mul_var(), NumericVar::ndigits, NUMERIC_MAX_RESULT_SCALE, NUMERIC_MIN_DISPLAY_SCALE, numericvar_to_double_no_overflow(), round_var(), set_var_from_var(), val, NumericVar::weight, x, and zero_var().

Referenced by numeric_exp(), and power_var().

◆ float4_numeric()

Datum float4_numeric ( PG_FUNCTION_ARGS  )

Definition at line 4691 of file numeric.c.

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

References buf, const_nan, const_ninf, const_pinf, free_var(), init_var, make_result(), PG_GETARG_FLOAT4, PG_RETURN_NUMERIC, res, set_var_from_str(), snprintf, and val.

Referenced by JsonItemFromDatum().

◆ float8_numeric()

Datum float8_numeric ( PG_FUNCTION_ARGS  )

Definition at line 4597 of file numeric.c.

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

References buf, const_nan, const_ninf, const_pinf, free_var(), init_var, make_result(), PG_GETARG_FLOAT8, PG_RETURN_NUMERIC, res, set_var_from_str(), snprintf, and val.

Referenced by executeItemOptUnwrapTarget(), JsonItemFromDatum(), and SV_to_JsonbValue().

◆ floor_var()

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

Definition at line 10189 of file numeric.c.

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

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

Referenced by numeric_floor().

◆ free_var()

static void free_var ( NumericVar var)
static

Definition at line 6973 of file numeric.c.

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

References NumericVar::buf, digitbuf_free, NumericVar::digits, NUMERIC_NAN, and NumericVar::sign.

Referenced by accum_sum_combine(), ceil_var(), compute_bucket(), div_mod_var(), estimate_ln_dweight(), exp_var(), float4_numeric(), float8_numeric(), floor_var(), gcd_var(), get_str_from_var_sci(), in_range_numeric_numeric(), int64_div_fast_to_numeric(), int64_to_numeric(), int8_avg_deserialize(), int8_avg_serialize(), ln_var(), log_var(), mod_var(), numeric(), numeric_add_opt_error(), numeric_avg(), numeric_avg_deserialize(), numeric_avg_serialize(), numeric_ceil(), numeric_deserialize(), numeric_div_opt_error(), numeric_div_trunc(), numeric_exp(), numeric_fac(), numeric_floor(), numeric_gcd(), numeric_in(), numeric_inc(), numeric_lcm(), numeric_ln(), numeric_log(), numeric_min_scale(), numeric_mod_opt_error(), numeric_mul_opt_error(), numeric_poly_avg(), numeric_poly_deserialize(), numeric_poly_serialize(), numeric_poly_sum(), numeric_power(), numeric_recv(), numeric_round(), numeric_serialize(), numeric_sqrt(), numeric_stddev_internal(), numeric_sub_opt_error(), numeric_sum(), numeric_trim_scale(), numeric_trunc(), numericvar_to_int64(), numericvar_to_uint64(), power_var(), power_var_int(), random_numeric(), random_var(), set_var_from_non_decimal_integer_str(), sqrt_var(), and width_bucket_numeric().

◆ gcd_var()

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

Definition at line 10212 of file numeric.c.

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

References CHECK_FOR_INTERRUPTS, cmp(), cmp_abs(), NumericVar::dscale, free_var(), init_var, Max, mod_var(), NumericVar::ndigits, NUMERIC_POS, set_var_from_var(), and NumericVar::sign.

Referenced by numeric_gcd(), and numeric_lcm().

◆ generate_series_numeric()

Datum generate_series_numeric ( PG_FUNCTION_ARGS  )

Definition at line 1703 of file numeric.c.

1704 {
1705  return generate_series_step_numeric(fcinfo);
1706 }
Datum generate_series_step_numeric(PG_FUNCTION_ARGS)
Definition: numeric.c:1709

References generate_series_step_numeric().

◆ generate_series_step_numeric()

Datum generate_series_step_numeric ( PG_FUNCTION_ARGS  )

Definition at line 1709 of file numeric.c.

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

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

Referenced by generate_series_numeric().

◆ get_min_scale()

static int get_min_scale ( NumericVar var)
static

Definition at line 4140 of file numeric.c.

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

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

Referenced by numeric_min_scale(), and numeric_trim_scale().

◆ get_str_from_var()

static char * get_str_from_var ( const NumericVar var)
static

Definition at line 7498 of file numeric.c.

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

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

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

◆ get_str_from_var_sci()

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

Definition at line 7651 of file numeric.c.

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

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

Referenced by numeric_out_sci().

◆ hash_numeric()

Datum hash_numeric ( PG_FUNCTION_ARGS  )

Definition at line 2701 of file numeric.c.

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

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

Referenced by JsonbHashScalarValue().

◆ hash_numeric_extended()

Datum hash_numeric_extended ( PG_FUNCTION_ARGS  )

Definition at line 2781 of file numeric.c.

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

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

Referenced by JsonbHashScalarValueExtended().

◆ in_range_numeric_numeric()

Datum in_range_numeric_numeric ( PG_FUNCTION_ARGS  )

Definition at line 2566 of file numeric.c.

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

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

◆ init_var_from_num()

◆ int2_accum()

Datum int2_accum ( PG_FUNCTION_ARGS  )

Definition at line 5554 of file numeric.c.

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

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

◆ int2_accum_inv()

Datum int2_accum_inv ( PG_FUNCTION_ARGS  )

Definition at line 5978 of file numeric.c.

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

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

◆ int2_avg_accum()

Datum int2_avg_accum ( PG_FUNCTION_ARGS  )

Definition at line 6661 of file numeric.c.

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

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

◆ int2_avg_accum_inv()

Datum int2_avg_accum_inv ( PG_FUNCTION_ARGS  )

Definition at line 6748 of file numeric.c.

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

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

◆ int2_numeric()

Datum int2_numeric ( PG_FUNCTION_ARGS  )

Definition at line 4548 of file numeric.c.

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

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

Referenced by JsonItemFromDatum().

◆ int2_sum()

Datum int2_sum ( PG_FUNCTION_ARGS  )

Definition at line 6512 of file numeric.c.

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

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

◆ int2int4_sum()

Datum int2int4_sum ( PG_FUNCTION_ARGS  )

Definition at line 6831 of file numeric.c.

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

References ARR_DATA_PTR, ARR_HASNULL, ARR_OVERHEAD_NONULLS, ARR_SIZE, Int8TransTypeData::count, elog, ERROR, Int64GetDatumFast, PG_GETARG_ARRAYTYPE_P, PG_RETURN_DATUM, PG_RETURN_NULL, and Int8TransTypeData::sum.

◆ int4_accum()

Datum int4_accum ( PG_FUNCTION_ARGS  )

Definition at line 5577 of file numeric.c.

5578 {
5580 
5581  state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
5582 
5583  /* Create the state data on the first call */
5584  if (state == NULL)
5585  state = makePolyNumAggState(fcinfo, true);
5586 
5587  if (!PG_ARGISNULL(1))
5588  {
5589 #ifdef HAVE_INT128
5590  do_int128_accum(state, (int128) PG_GETARG_INT32(1));
5591 #else
5593 #endif
5594  }
5595 
5597 }
#define PG_GETARG_INT32(n)
Definition: fmgr.h:269

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

◆ int4_accum_inv()

Datum int4_accum_inv ( PG_FUNCTION_ARGS  )

Definition at line 6003 of file numeric.c.

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

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

◆ int4_avg_accum()

Datum int4_avg_accum ( PG_FUNCTION_ARGS  )

Definition at line 6689 of file numeric.c.

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

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

◆ int4_avg_accum_inv()

Datum int4_avg_accum_inv ( PG_FUNCTION_ARGS  )

Definition at line 6776 of file numeric.c.

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

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

◆ int4_avg_combine()

Datum int4_avg_combine ( PG_FUNCTION_ARGS  )

Definition at line 6717 of file numeric.c.

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

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

◆ int4_numeric()

Datum int4_numeric ( PG_FUNCTION_ARGS  )

Definition at line 4393 of file numeric.c.

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

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

Referenced by executeItemOptUnwrapTarget(), and JsonItemFromDatum().

◆ int4_sum()

Datum int4_sum ( PG_FUNCTION_ARGS  )

Definition at line 6561 of file numeric.c.

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

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

◆ int64_div_fast_to_numeric()

Numeric int64_div_fast_to_numeric ( int64  val1,
int  log10val2 
)

Definition at line 4308 of file numeric.c.

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

References DEC_DIGITS, NumericVar::dscale, free_var(), init_var, int64_to_numericvar(), lengthof, make_result(), mul_var(), pg_mul_s64_overflow(), res, StaticAssertDecl, unlikely, and NumericVar::weight.

Referenced by interval_part_common(), time_part_common(), timestamp_part_common(), timestamptz_part_common(), and timetz_part_common().

◆ int64_to_numeric()

◆ int64_to_numericvar()

static void int64_to_numericvar ( int64  val,
NumericVar var 
)
static

Definition at line 8108 of file numeric.c.

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

References alloc_var(), DEC_DIGITS, NumericVar::digits, NumericVar::dscale, NBASE, NumericVar::ndigits, NUMERIC_NEG, NUMERIC_POS, NumericVar::sign, val, and NumericVar::weight.

Referenced by int64_div_fast_to_numeric(), int64_to_numeric(), numeric_fac(), numeric_stddev_internal(), set_var_from_non_decimal_integer_str(), sqrt_var(), and width_bucket_numeric().

◆ int8_accum()

Datum int8_accum ( PG_FUNCTION_ARGS  )

Definition at line 5600 of file numeric.c.

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

References do_numeric_accum(), int64_to_numeric(), makeNumericAggState(), PG_ARGISNULL, PG_GETARG_INT64, PG_GETARG_POINTER, and PG_RETURN_POINTER.

◆ int8_accum_inv()

Datum int8_accum_inv ( PG_FUNCTION_ARGS  )

Definition at line 6028 of file numeric.c.

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

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

◆ int8_avg()

Datum int8_avg ( PG_FUNCTION_ARGS  )

Definition at line 6804 of file numeric.c.

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

References ARR_DATA_PTR, ARR_HASNULL, ARR_OVERHEAD_NONULLS, ARR_SIZE, Int8TransTypeData::count, DirectFunctionCall2, elog, ERROR, int64_to_numeric(), numeric_div(), NumericGetDatum(), PG_GETARG_ARRAYTYPE_P, PG_RETURN_DATUM, PG_RETURN_NULL, and Int8TransTypeData::sum.

◆ int8_avg_accum()

Datum int8_avg_accum ( PG_FUNCTION_ARGS  )

Definition at line 5796 of file numeric.c.

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

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

◆ int8_avg_accum_inv()

Datum int8_avg_accum_inv ( PG_FUNCTION_ARGS  )

Definition at line 6049 of file numeric.c.

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

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

◆ int8_avg_combine()

Datum int8_avg_combine ( PG_FUNCTION_ARGS  )

Definition at line 5823 of file numeric.c.

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

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

◆ int8_avg_deserialize()

Datum int8_avg_deserialize ( PG_FUNCTION_ARGS  )

Definition at line 5932 of file numeric.c.

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

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

◆ int8_avg_serialize()

Datum int8_avg_serialize ( PG_FUNCTION_ARGS  )

Definition at line 5883 of file numeric.c.

5884 {
5887  bytea *result;
5888  NumericVar tmp_var;
5889 
5890  /* Ensure we disallow calling when not in aggregate context */
5891  if (!AggCheckCallContext(fcinfo, NULL))
5892  elog(ERROR, "aggregate function called in non-aggregate context");
5893 
5895 
5896  /*
5897  * If the platform supports int128 then sumX will be a 128 integer type.
5898  * Here we'll convert that into a numeric type so that the combine state
5899  * is in the same format for both int128 enabled machines and machines
5900  * which don't support that type. The logic here is that one day we might
5901  * like to send these over to another server for further processing and we
5902  * want a standard format to work with.
5903  */
5904 
5905  init_var(&tmp_var);
5906 
5907  pq_begintypsend(&buf);
5908 
5909  /* N */
5910  pq_sendint64(&buf, state->N);
5911 
5912  /* sumX */
5913 #ifdef HAVE_INT128
5914  int128_to_numericvar(state->sumX, &tmp_var);
5915 #else
5916  accum_sum_final(&state->sumX, &tmp_var);
5917 #endif
5918  numericvar_serialize(&buf, &tmp_var);
5919 
5920  result = pq_endtypsend(&buf);
5921 
5922  free_var(&tmp_var);
5923 
5924  PG_RETURN_BYTEA_P(result);
5925 }
static void numericvar_serialize(StringInfo buf, const NumericVar *var)
Definition: numeric.c:7728
#define PG_RETURN_BYTEA_P(x)
Definition: fmgr.h:371
void pq_begintypsend(StringInfo buf)
Definition: pqformat.c:326
bytea * pq_endtypsend(StringInfo buf)
Definition: pqformat.c:346
static void pq_sendint64(StringInfo buf, uint64 i)
Definition: pqformat.h:152

References accum_sum_final(), AggCheckCallContext(), buf, elog, ERROR, free_var(), init_var, numericvar_serialize(), PG_GETARG_POINTER, PG_RETURN_BYTEA_P, pq_begintypsend(), pq_endtypsend(), and pq_sendint64().

◆ int8_numeric()

Datum int8_numeric ( PG_FUNCTION_ARGS  )

Definition at line 4481 of file numeric.c.

4482 {
4483  int64 val = PG_GETARG_INT64(0);
4484 
4486 }

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

Referenced by executeItemOptUnwrapTarget(), and JsonItemFromDatum().

◆ int8_sum()

Datum int8_sum ( PG_FUNCTION_ARGS  )

Definition at line 6613 of file numeric.c.

6614 {
6615  Numeric oldsum;
6616 
6617  if (PG_ARGISNULL(0))
6618  {
6619  /* No non-null input seen so far... */
6620  if (PG_ARGISNULL(1))
6621  PG_RETURN_NULL(); /* still no non-null */
6622  /* This is the first non-null input. */
6624  }
6625 
6626  /*
6627  * Note that we cannot special-case the aggregate case here, as we do for
6628  * int2_sum and int4_sum: numeric is of variable size, so we cannot modify
6629  * our first parameter in-place.
6630  */
6631 
6632  oldsum = PG_GETARG_NUMERIC(0);
6633 
6634  /* Leave sum unchanged if new input is null. */
6635  if (PG_ARGISNULL(1))
6636  PG_RETURN_NUMERIC(oldsum);
6637 
6638  /* OK to do the addition. */
6640  NumericGetDatum(oldsum),
6642 }
Datum numeric_add(PG_FUNCTION_ARGS)
Definition: numeric.c:2852

References DirectFunctionCall2, int64_to_numeric(), numeric_add(), NumericGetDatum(), PG_ARGISNULL, PG_GETARG_INT64, PG_GETARG_NUMERIC, PG_RETURN_DATUM, PG_RETURN_NULL, and PG_RETURN_NUMERIC.

◆ is_valid_numeric_typmod()

static bool is_valid_numeric_typmod ( int32  typmod)
inlinestatic

Definition at line 916 of file numeric.c.

917 {
918  return typmod >= (int32) VARHDRSZ;
919 }

References VARHDRSZ.

Referenced by apply_typmod(), apply_typmod_special(), numeric(), numeric_maximum_size(), numeric_support(), and numerictypmodout().

◆ ln_var()

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

Definition at line 10973 of file numeric.c.

10974 {
10975  NumericVar x;
10976  NumericVar xx;
10977  int ni;
10978  NumericVar elem;
10979  NumericVar fact;
10980  int nsqrt;
10981  int local_rscale;
10982  int cmp;
10983 
10984  cmp = cmp_var(arg, &const_zero);
10985  if (cmp == 0)
10986  ereport(ERROR,
10987  (errcode(ERRCODE_INVALID_ARGUMENT_FOR_LOG),
10988  errmsg("cannot take logarithm of zero")));
10989  else if (cmp < 0)
10990  ereport(ERROR,
10991  (errcode(ERRCODE_INVALID_ARGUMENT_FOR_LOG),
10992  errmsg("cannot take logarithm of a negative number")));
10993 
10994  init_var(&x);
10995  init_var(&xx);
10996  init_var(&elem);
10997  init_var(&fact);
10998 
10999  set_var_from_var(arg, &x);
11000  set_var_from_var(&const_two, &fact);
11001 
11002  /*
11003  * Reduce input into range 0.9 < x < 1.1 with repeated sqrt() operations.
11004  *
11005  * The final logarithm will have up to around rscale+6 significant digits.
11006  * Each sqrt() will roughly halve the weight of x, so adjust the local
11007  * rscale as we work so that we keep this many significant digits at each
11008  * step (plus a few more for good measure).
11009  *
11010  * Note that we allow local_rscale < 0 during this input reduction
11011  * process, which implies rounding before the decimal point. sqrt_var()
11012  * explicitly supports this, and it significantly reduces the work
11013  * required to reduce very large inputs to the required range. Once the
11014  * input reduction is complete, x.weight will be 0 and its display scale
11015  * will be non-negative again.
11016  */
11017  nsqrt = 0;
11018  while (cmp_var(&x, &const_zero_point_nine) <= 0)
11019  {
11020  local_rscale = rscale - x.weight * DEC_DIGITS / 2 + 8;
11021  sqrt_var(&x, &x, local_rscale);
11022  mul_var(&fact, &const_two, &fact, 0);
11023  nsqrt++;
11024  }
11025  while (cmp_var(&x, &const_one_point_one) >= 0)
11026  {
11027  local_rscale = rscale - x.weight * DEC_DIGITS / 2 + 8;
11028  sqrt_var(&x, &x, local_rscale);
11029  mul_var(&fact, &const_two, &fact, 0);
11030  nsqrt++;
11031  }
11032 
11033  /*
11034  * We use the Taylor series for 0.5 * ln((1+z)/(1-z)),
11035  *
11036  * z + z^3/3 + z^5/5 + ...
11037  *
11038  * where z = (x-1)/(x+1) is in the range (approximately) -0.053 .. 0.048
11039  * due to the above range-reduction of x.
11040  *
11041  * The convergence of this is not as fast as one would like, but is
11042  * tolerable given that z is small.
11043  *
11044  * The Taylor series result will be multiplied by 2^(nsqrt+1), which has a
11045  * decimal weight of (nsqrt+1) * log10(2), so work with this many extra
11046  * digits of precision (plus a few more for good measure).
11047  */
11048  local_rscale = rscale + (int) ((nsqrt + 1) * 0.301029995663981) + 8;
11049 
11050  sub_var(&x, &const_one, result);
11051  add_var(&x, &const_one, &elem);
11052  div_var_fast(result, &elem, result, local_rscale, true);
11053  set_var_from_var(result, &xx);
11054  mul_var(result, result, &x, local_rscale);
11055 
11056  ni = 1;
11057 
11058  for (;;)
11059  {
11060  ni += 2;
11061  mul_var(&xx, &x, &xx, local_rscale);
11062  div_var_int(&xx, ni, 0, &elem, local_rscale, true);
11063 
11064  if (elem.ndigits == 0)
11065  break;
11066 
11067  add_var(result, &elem, result);
11068 
11069  if (elem.weight < (result->weight - local_rscale * 2 / DEC_DIGITS))
11070  break;
11071  }
11072 
11073  /* Compensate for argument range reduction, round to requested rscale */
11074  mul_var(result, &fact, result, rscale);
11075 
11076  free_var(&x);
11077  free_var(&xx);
11078  free_var(&elem);
11079  free_var(&fact);
11080 }
static const NumericVar const_two
Definition: numeric.c:433
static void sqrt_var(const NumericVar *arg, NumericVar *result, int rscale)
Definition: numeric.c:10282

References add_var(), arg, cmp(), cmp_var(), const_one, const_one_point_one, const_two, const_zero, const_zero_point_nine, DEC_DIGITS, div_var_fast(), div_var_int(), ereport, errcode(), errmsg(), ERROR, free_var(), init_var, mul_var(), NumericVar::ndigits, set_var_from_var(), sqrt_var(), sub_var(), NumericVar::weight, and x.

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

◆ log_var()

static void log_var ( const NumericVar base,
const NumericVar num,
NumericVar result 
)
static

Definition at line 11091 of file numeric.c.

11092 {
11093  NumericVar ln_base;
11094  NumericVar ln_num;
11095  int ln_base_dweight;
11096  int ln_num_dweight;
11097  int result_dweight;
11098  int rscale;
11099  int ln_base_rscale;
11100  int ln_num_rscale;
11101 
11102  init_var(&ln_base);
11103  init_var(&ln_num);
11104 
11105  /* Estimated dweights of ln(base), ln(num) and the final result */
11106  ln_base_dweight = estimate_ln_dweight(base);
11107  ln_num_dweight = estimate_ln_dweight(num);
11108  result_dweight = ln_num_dweight - ln_base_dweight;
11109 
11110  /*
11111  * Select the scale of the result so that it will have at least
11112  * NUMERIC_MIN_SIG_DIGITS significant digits and is not less than either
11113  * input's display scale.
11114  */
11115  rscale = NUMERIC_MIN_SIG_DIGITS - result_dweight;
11116  rscale = Max(rscale, base->dscale);
11117  rscale = Max(rscale, num->dscale);
11118  rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
11119  rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
11120 
11121  /*
11122  * Set the scales for ln(base) and ln(num) so that they each have more
11123  * significant digits than the final result.
11124  */
11125  ln_base_rscale = rscale + result_dweight - ln_base_dweight + 8;
11126  ln_base_rscale = Max(ln_base_rscale, NUMERIC_MIN_DISPLAY_SCALE);
11127 
11128  ln_num_rscale = rscale + result_dweight - ln_num_dweight + 8;
11129  ln_num_rscale = Max(ln_num_rscale, NUMERIC_MIN_DISPLAY_SCALE);
11130 
11131  /* Form natural logarithms */
11132  ln_var(base, &ln_base, ln_base_rscale);
11133  ln_var(num, &ln_num, ln_num_rscale);
11134 
11135  /* Divide and round to the required scale */
11136  div_var_fast(&ln_num, &ln_base, result, rscale, true);
11137 
11138  free_var(&ln_num);
11139  free_var(&ln_base);
11140 }
static int estimate_ln_dweight(const NumericVar *var)
Definition: numeric.c:10891
#define NUMERIC_MAX_DISPLAY_SCALE
Definition: numeric.h:40
#define NUMERIC_MIN_SIG_DIGITS
Definition: numeric.h:50

References div_var_fast(), NumericVar::dscale, estimate_ln_dweight(), free_var(), init_var, ln_var(), Max, Min, NUMERIC_MAX_DISPLAY_SCALE, NUMERIC_MIN_DISPLAY_SCALE, and NUMERIC_MIN_SIG_DIGITS.

Referenced by numeric_log().

◆ make_numeric_typmod()

static int32 make_numeric_typmod ( int  precision,
int  scale 
)
inlinestatic

Definition at line 907 of file numeric.c.

908 {
909  return ((precision << 16) | (scale & 0x7ff)) + VARHDRSZ;
910 }

References scale, and VARHDRSZ.

Referenced by numerictypmodin().

◆ make_result()

◆ make_result_opt_error()

static Numeric make_result_opt_error ( const NumericVar var,
bool have_error 
)
static

Definition at line 7786 of file numeric.c.

7787 {
7788  Numeric result;
7789  NumericDigit *digits = var->digits;
7790  int weight = var->weight;
7791  int sign = var->sign;
7792  int n;
7793  Size len;
7794 
7795  if (have_error)
7796  *have_error = false;
7797 
7799  {
7800  /*
7801  * Verify valid special value. This could be just an Assert, perhaps,
7802  * but it seems worthwhile to expend a few cycles to ensure that we
7803  * never write any nonzero reserved bits to disk.
7804  */
7805  if (!(sign == NUMERIC_NAN ||
7806  sign == NUMERIC_PINF ||
7807  sign == NUMERIC_NINF))
7808  elog(ERROR, "invalid numeric sign value 0x%x", sign);
7809 
7810  result = (Numeric) palloc(NUMERIC_HDRSZ_SHORT);
7811 
7813  result->choice.n_header = sign;
7814  /* the header word is all we need */
7815 
7816  dump_numeric("make_result()", result);
7817  return result;
7818  }
7819 
7820  n = var->ndigits;
7821 
7822  /* truncate leading zeroes */
7823  while (n > 0 && *digits == 0)
7824  {
7825  digits++;
7826  weight--;
7827  n--;
7828  }
7829  /* truncate trailing zeroes */
7830  while (n > 0 && digits[n - 1] == 0)
7831  n--;
7832 
7833  /* If zero result, force to weight=0 and positive sign */
7834  if (n == 0)
7835  {
7836  weight = 0;
7837  sign = NUMERIC_POS;
7838  }
7839 
7840  /* Build the result */
7841  if (NUMERIC_CAN_BE_SHORT(var->dscale, weight))
7842  {
7843  len = NUMERIC_HDRSZ_SHORT + n * sizeof(NumericDigit);
7844  result = (Numeric) palloc(len);
7845  SET_VARSIZE(result, len);
7846  result->choice.n_short.n_header =
7848  : NUMERIC_SHORT)
7850  | (weight < 0 ? NUMERIC_SHORT_WEIGHT_SIGN_MASK : 0)
7851  | (weight & NUMERIC_SHORT_WEIGHT_MASK);
7852  }
7853  else
7854  {
7855  len = NUMERIC_HDRSZ + n * sizeof(NumericDigit);
7856  result = (Numeric) palloc(len);
7857  SET_VARSIZE(result, len);
7858  result->choice.n_long.n_sign_dscale =
7859  sign | (var->dscale & NUMERIC_DSCALE_MASK);
7860  result->choice.n_long.n_weight = weight;
7861  }
7862 
7863  Assert(NUMERIC_NDIGITS(result) == n);
7864  if (n > 0)
7865  memcpy(NUMERIC_DIGITS(result), digits, n * sizeof(NumericDigit));
7866 
7867  /* Check for overflow of int16 fields */
7868  if (NUMERIC_WEIGHT(result) != weight ||
7869  NUMERIC_DSCALE(result) != var->dscale)
7870  {
7871  if (have_error)
7872  {
7873  *have_error = true;
7874  return NULL;
7875  }
7876  else
7877  {
7878  ereport(ERROR,
7879  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
7880  errmsg("value overflows numeric format")));
7881  }
7882  }
7883 
7884  dump_numeric("make_result()", result);
7885  return result;
7886 }
#define dump_numeric(s, n)
Definition: numeric.c:479
#define NUMERIC_CAN_BE_SHORT(scale, weight)
Definition: numeric.c:497
#define NUMERIC_HDRSZ_SHORT
Definition: numeric.c:175
#define NUMERIC_NINF
Definition: numeric.c:199
#define NUMERIC_SHORT
Definition: numeric.c:167
#define NUMERIC_HDRSZ
Definition: numeric.c:174
#define NUMERIC_SPECIAL
Definition: numeric.c:168
#define NUMERIC_SIGN_MASK
Definition: numeric.c:164
#define NUMERIC_PINF
Definition: numeric.c:198
size_t Size
Definition: c.h:605
char sign
Definition: informix.c:674
union NumericChoice choice
Definition: numeric.c:156
uint16 n_header
Definition: numeric.c:148
#define SET_VARSIZE(PTR, len)
Definition: varatt.h:305

References Assert, NumericData::choice, NumericVar::digits, digits, NumericVar::dscale, dump_numeric, elog, ereport, errcode(), errmsg(), ERROR, len, NumericChoice::n_header, NumericVar::ndigits, NUMERIC_CAN_BE_SHORT, NUMERIC_DIGITS, NUMERIC_DSCALE, NUMERIC_DSCALE_MASK, NUMERIC_HDRSZ, NUMERIC_HDRSZ_SHORT, NUMERIC_NAN, NUMERIC_NDIGITS, NUMERIC_NEG, NUMERIC_NINF, NUMERIC_PINF, NUMERIC_POS, NUMERIC_SHORT, NUMERIC_SHORT_DSCALE_SHIFT, NUMERIC_SHORT_SIGN_MASK, NUMERIC_SHORT_WEIGHT_MASK, NUMERIC_SHORT_WEIGHT_SIGN_MASK, NUMERIC_SIGN_MASK, NUMERIC_SPECIAL, NUMERIC_WEIGHT, palloc(), SET_VARSIZE, NumericVar::sign, sign, and NumericVar::weight.

Referenced by make_result(), numeric_add_opt_error(), numeric_div_opt_error(), numeric_in(), numeric_mod_opt_error(), numeric_mul_opt_error(), and numeric_sub_opt_error().

◆ makeNumericAggState()

static NumericAggState* makeNumericAggState ( FunctionCallInfo  fcinfo,
bool  calcSumX2 
)
static

Definition at line 4821 of file numeric.c.

4822 {
4824  MemoryContext agg_context;
4825  MemoryContext old_context;
4826 
4827  if (!AggCheckCallContext(fcinfo, &agg_context))
4828  elog(ERROR, "aggregate function called in non-aggregate context");
4829 
4830  old_context = MemoryContextSwitchTo(agg_context);
4831 
4833  state->calcSumX2 = calcSumX2;
4834  state->agg_context = agg_context;
4835 
4836  MemoryContextSwitchTo(old_context);
4837 
4838  return state;
4839 }

References AggCheckCallContext(), elog, ERROR, MemoryContextSwitchTo(), and palloc0().

Referenced by int8_accum(), numeric_accum(), and numeric_avg_accum().

◆ makeNumericAggStateCurrentContext()

static NumericAggState* makeNumericAggStateCurrentContext ( bool  calcSumX2)
static

Definition at line 4846 of file numeric.c.

4847 {
4849 
4851  state->calcSumX2 = calcSumX2;
4852  state->agg_context = CurrentMemoryContext;
4853 
4854  return state;
4855 }
MemoryContext CurrentMemoryContext
Definition: mcxt.c:143

References CurrentMemoryContext, and palloc0().

Referenced by numeric_avg_combine(), numeric_avg_deserialize(), numeric_combine(), and numeric_deserialize().

◆ mod_var()

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

Definition at line 10066 of file numeric.c.

10067 {
10068  NumericVar tmp;
10069 
10070  init_var(&tmp);
10071 
10072  /* ---------
10073  * We do this using the equation
10074  * mod(x,y) = x - trunc(x/y)*y
10075  * div_var can be persuaded to give us trunc(x/y) directly.
10076  * ----------
10077  */
10078  div_var(var1, var2, &tmp, 0, false);
10079 
10080  mul_var(var2, &tmp, &tmp, var2->dscale);
10081 
10082  sub_var(var1, &tmp, result);
10083 
10084  free_var(&tmp);
10085 }

References div_var(), NumericVar::dscale, free_var(), init_var, mul_var(), and sub_var().

Referenced by gcd_var(), and numeric_mod_opt_error().

◆ mul_var()

static void mul_var ( const NumericVar var1,
const NumericVar var2,
NumericVar result,
int  rscale 
)
static

Definition at line 8673 of file numeric.c.

8675 {
8676  int res_ndigits;
8677  int res_sign;
8678  int res_weight;
8679  int maxdigits;
8680  int *dig;
8681  int carry;
8682  int maxdig;
8683  int newdig;
8684  int var1ndigits;
8685  int var2ndigits;
8686  NumericDigit *var1digits;
8687  NumericDigit *var2digits;
8688  NumericDigit *res_digits;
8689  int i,
8690  i1,
8691  i2;
8692 
8693  /*
8694  * Arrange for var1 to be the shorter of the two numbers. This improves
8695  * performance because the inner multiplication loop is much simpler than
8696  * the outer loop, so it's better to have a smaller number of iterations
8697  * of the outer loop. This also reduces the number of times that the
8698  * accumulator array needs to be normalized.
8699  */
8700  if (var1->ndigits > var2->ndigits)
8701  {
8702  const NumericVar *tmp = var1;
8703 
8704  var1 = var2;
8705  var2 = tmp;
8706  }
8707 
8708  /* copy these values into local vars for speed in inner loop */
8709  var1ndigits = var1->ndigits;
8710  var2ndigits = var2->ndigits;
8711  var1digits = var1->digits;
8712  var2digits = var2->digits;
8713 
8714  if (var1ndigits == 0)
8715  {
8716  /* one or both inputs is zero; so is result */
8717  zero_var(result);
8718  result->dscale = rscale;
8719  return;
8720  }
8721 
8722  /*
8723  * If var1 has 1-4 digits and the exact result was requested, delegate to
8724  * mul_var_short() which uses a faster direct multiplication algorithm.
8725  */
8726  if (var1ndigits <= 4 && rscale == var1->dscale + var2->dscale)
8727  {
8728  mul_var_short(var1, var2, result);
8729  return;
8730  }
8731 
8732  /* Determine result sign and (maximum possible) weight */
8733  if (var1->sign == var2->sign)
8734  res_sign = NUMERIC_POS;
8735  else
8736  res_sign = NUMERIC_NEG;
8737  res_weight = var1->weight + var2->weight + 2;
8738 
8739  /*
8740  * Determine the number of result digits to compute. If the exact result
8741  * would have more than rscale fractional digits, truncate the computation
8742  * with MUL_GUARD_DIGITS guard digits, i.e., ignore input digits that
8743  * would only contribute to the right of that. (This will give the exact
8744  * rounded-to-rscale answer unless carries out of the ignored positions
8745  * would have propagated through more than MUL_GUARD_DIGITS digits.)
8746  *
8747  * Note: an exact computation could not produce more than var1ndigits +
8748  * var2ndigits digits, but we allocate one extra output digit in case
8749  * rscale-driven rounding produces a carry out of the highest exact digit.
8750  */
8751  res_ndigits = var1ndigits + var2ndigits + 1;
8752  maxdigits = res_weight + 1 + (rscale + DEC_DIGITS - 1) / DEC_DIGITS +
8754  res_ndigits = Min(res_ndigits, maxdigits);
8755 
8756  if (res_ndigits < 3)
8757  {
8758  /* All input digits will be ignored; so result is zero */
8759  zero_var(result);
8760  result->dscale = rscale;
8761  return;
8762  }
8763 
8764  /*
8765  * We do the arithmetic in an array "dig[]" of signed int's. Since
8766  * INT_MAX is noticeably larger than NBASE*NBASE, this gives us headroom
8767  * to avoid normalizing carries immediately.
8768  *
8769  * maxdig tracks the maximum possible value of any dig[] entry; when this
8770  * threatens to exceed INT_MAX, we take the time to propagate carries.
8771  * Furthermore, we need to ensure that overflow doesn't occur during the
8772  * carry propagation passes either. The carry values could be as much as
8773  * INT_MAX/NBASE, so really we must normalize when digits threaten to
8774  * exceed INT_MAX - INT_MAX/NBASE.
8775  *
8776  * To avoid overflow in maxdig itself, it actually represents the max
8777  * possible value divided by NBASE-1, ie, at the top of the loop it is
8778  * known that no dig[] entry exceeds maxdig * (NBASE-1).
8779  */
8780  dig = (int *) palloc0(res_ndigits * sizeof(int));
8781  maxdig = 0;
8782 
8783  /*
8784  * The least significant digits of var1 should be ignored if they don't
8785  * contribute directly to the first res_ndigits digits of the result that
8786  * we are computing.
8787  *
8788  * Digit i1 of var1 and digit i2 of var2 are multiplied and added to digit
8789  * i1+i2+2 of the accumulator array, so we need only consider digits of
8790  * var1 for which i1 <= res_ndigits - 3.
8791  */
8792  for (i1 = Min(var1ndigits - 1, res_ndigits - 3); i1 >= 0; i1--)
8793  {
8794  NumericDigit var1digit = var1digits[i1];
8795 
8796  if (var1digit == 0)
8797  continue;
8798 
8799  /* Time to normalize? */
8800  maxdig += var1digit;
8801  if (maxdig > (INT_MAX - INT_MAX / NBASE) / (NBASE - 1))
8802  {
8803  /* Yes, do it */
8804  carry = 0;
8805  for (i = res_ndigits - 1; i >= 0; i--)
8806  {
8807  newdig = dig[i] + carry;
8808  if (newdig >= NBASE)
8809  {
8810  carry = newdig / NBASE;
8811  newdig -= carry * NBASE;
8812  }
8813  else
8814  carry = 0;
8815  dig[i] = newdig;
8816  }
8817  Assert(carry == 0);
8818  /* Reset maxdig to indicate new worst-case */
8819  maxdig = 1 + var1digit;
8820  }
8821 
8822  /*
8823  * Add the appropriate multiple of var2 into the accumulator.
8824  *
8825  * As above, digits of var2 can be ignored if they don't contribute,
8826  * so we only include digits for which i1+i2+2 < res_ndigits.
8827  *
8828  * This inner loop is the performance bottleneck for multiplication,
8829  * so we want to keep it simple enough so that it can be
8830  * auto-vectorized. Accordingly, process the digits left-to-right
8831  * even though schoolbook multiplication would suggest right-to-left.
8832  * Since we aren't propagating carries in this loop, the order does
8833  * not matter.
8834  */
8835  {
8836  int i2limit = Min(var2ndigits, res_ndigits - i1 - 2);
8837  int *dig_i1_2 = &dig[i1 + 2];
8838 
8839  for (i2 = 0; i2 < i2limit; i2++)
8840  dig_i1_2[i2] += var1digit * var2digits[i2];
8841  }
8842  }
8843 
8844  /*
8845  * Now we do a final carry propagation pass to normalize the result, which
8846  * we combine with storing the result digits into the output. Note that
8847  * this is still done at full precision w/guard digits.
8848  */
8849  alloc_var(result, res_ndigits);
8850  res_digits = result->digits;
8851  carry = 0;
8852  for (i = res_ndigits - 1; i >= 0; i--)
8853  {
8854  newdig = dig[i] + carry;
8855  if (newdig >= NBASE)
8856  {
8857  carry = newdig / NBASE;
8858  newdig -= carry * NBASE;
8859  }
8860  else
8861  carry = 0;
8862  res_digits[i] = newdig;
8863  }
8864  Assert(carry == 0);
8865 
8866  pfree(dig);
8867 
8868  /*
8869  * Finally, round the result to the requested precision.
8870  */
8871  result->weight = res_weight;
8872  result->sign = res_sign;
8873 
8874  /* Round to target rscale (and set result->dscale) */
8875  round_var(result, rscale);
8876 
8877  /* Strip leading and trailing zeroes */
8878  strip_var(result);
8879 }
static void mul_var_short(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition: numeric.c:8890
#define MUL_GUARD_DIGITS
Definition: numeric.c:98

References alloc_var(), Assert, DEC_DIGITS, NumericVar::digits, NumericVar::dscale, i, maxdigits, Min, MUL_GUARD_DIGITS, mul_var_short(), NBASE, NumericVar::ndigits, NUMERIC_NEG, NUMERIC_POS, palloc0(), pfree(), round_var(), NumericVar::sign, strip_var(), NumericVar::weight, and zero_var().

Referenced by compute_bucket(), div_mod_var(), do_numeric_accum(), do_numeric_discard(), exp_var(), int64_div_fast_to_numeric(), ln_var(), mod_var(), numeric_fac(), numeric_lcm(), numeric_mul_opt_error(), numeric_stddev_internal(), power_var(), power_var_int(), set_var_from_non_decimal_integer_str(), and sqrt_var().

◆ mul_var_short()

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

Definition at line 8890 of file numeric.c.

8892 {
8893  int var1ndigits = var1->ndigits;
8894  int var2ndigits = var2->ndigits;
8895  NumericDigit *var1digits = var1->digits;
8896  NumericDigit *var2digits = var2->digits;
8897  int res_sign;
8898  int res_weight;
8899  int res_ndigits;
8900  NumericDigit *res_buf;
8901  NumericDigit *res_digits;
8902  uint32 carry;
8903  uint32 term;
8904 
8905  /* Check preconditions */
8906  Assert(var1ndigits >= 1);
8907  Assert(var1ndigits <= 4);
8908  Assert(var2ndigits >= var1ndigits);
8909 
8910  /*
8911  * Determine the result sign, weight, and number of digits to calculate.
8912  * The weight figured here is correct if the product has no leading zero
8913  * digits; otherwise strip_var() will fix things up. Note that, unlike
8914  * mul_var(), we do not need to allocate an extra output digit, because we
8915  * are not rounding here.
8916  */
8917  if (var1->sign == var2->sign)
8918  res_sign = NUMERIC_POS;
8919  else
8920  res_sign = NUMERIC_NEG;
8921  res_weight = var1->weight + var2->weight + 1;
8922  res_ndigits = var1ndigits + var2ndigits;
8923 
8924  /* Allocate result digit array */
8925  res_buf = digitbuf_alloc(res_ndigits + 1);
8926  res_buf[0] = 0; /* spare digit for later rounding */
8927  res_digits = res_buf + 1;
8928 
8929  /*
8930  * Compute the result digits in reverse, in one pass, propagating the
8931  * carry up as we go. The i'th result digit consists of the sum of the
8932  * products var1digits[i1] * var2digits[i2] for which i = i1 + i2 + 1.
8933  */
8934  switch (var1ndigits)
8935  {
8936  case 1:
8937  /* ---------
8938  * 1-digit case:
8939  * var1ndigits = 1
8940  * var2ndigits >= 1
8941  * res_ndigits = var2ndigits + 1
8942  * ----------
8943  */
8944  carry = 0;
8945  for (int i = res_ndigits - 2; i >= 0; i--)
8946  {
8947  term = (uint32) var1digits[0] * var2digits[i] + carry;
8948  res_digits[i + 1] = (NumericDigit) (term % NBASE);
8949  carry = term / NBASE;
8950  }
8951  res_digits[0] = (NumericDigit) carry;
8952  break;
8953 
8954  case 2:
8955  /* ---------
8956  * 2-digit case:
8957  * var1ndigits = 2
8958  * var2ndigits >= 2
8959  * res_ndigits = var2ndigits + 2
8960  * ----------
8961  */
8962  /* last result digit and carry */
8963  term = (uint32) var1digits[1] * var2digits[res_ndigits - 3];
8964  res_digits[res_ndigits - 1] = (NumericDigit) (term % NBASE);
8965  carry = term / NBASE;
8966 
8967  /* remaining digits, except for the first two */
8968  for (int i = res_ndigits - 3; i >= 1; i--)
8969  {
8970  term = (uint32) var1digits[0] * var2digits[i] +
8971  (uint32) var1digits[1] * var2digits[i - 1] + carry;
8972  res_digits[i + 1] = (NumericDigit) (term % NBASE);
8973  carry = term / NBASE;
8974  }
8975 
8976  /* first two digits */
8977  term = (uint32) var1digits[0] * var2digits[0] + carry;
8978  res_digits[1] = (NumericDigit) (term % NBASE);
8979  res_digits[0] = (NumericDigit) (term / NBASE);
8980  break;
8981 
8982  case 3:
8983  /* ---------
8984  * 3-digit case:
8985  * var1ndigits = 3
8986  * var2ndigits >= 3
8987  * res_ndigits = var2ndigits + 3
8988  * ----------
8989  */
8990  /* last two result digits */
8991  term = (uint32) var1digits[2] * var2digits[res_ndigits - 4];
8992  res_digits[res_ndigits - 1] = (NumericDigit) (term % NBASE);
8993  carry = term / NBASE;
8994 
8995  term = (uint32) var1digits[1] * var2digits[res_ndigits - 4] +
8996  (uint32) var1digits[2] * var2digits[res_ndigits - 5] + carry;
8997  res_digits[res_ndigits - 2] = (NumericDigit) (term % NBASE);
8998  carry = term / NBASE;
8999 
9000  /* remaining digits, except for the first three */
9001  for (int i = res_ndigits - 4; i >= 2; i--)
9002  {
9003  term = (uint32) var1digits[0] * var2digits[i] +
9004  (uint32) var1digits[1] * var2digits[i - 1] +
9005  (uint32) var1digits[2] * var2digits[i - 2] + carry;
9006  res_digits[i + 1] = (NumericDigit) (term % NBASE);
9007  carry = term / NBASE;
9008  }
9009 
9010  /* first three digits */
9011  term = (uint32) var1digits[0] * var2digits[1] +
9012  (uint32) var1digits[1] * var2digits[0] + carry;
9013  res_digits[2] = (NumericDigit) (term % NBASE);
9014  carry = term / NBASE;
9015 
9016  term = (uint32) var1digits[0] * var2digits[0] + carry;
9017  res_digits[1] = (NumericDigit) (term % NBASE);
9018  res_digits[0] = (NumericDigit) (term / NBASE);
9019  break;
9020 
9021  case 4:
9022  /* ---------
9023  * 4-digit case:
9024  * var1ndigits = 4
9025  * var2ndigits >= 4
9026  * res_ndigits = var2ndigits + 4
9027  * ----------
9028  */
9029  /* last three result digits */
9030  term = (uint32) var1digits[3] * var2digits[res_ndigits - 5];
9031  res_digits[res_ndigits - 1] = (NumericDigit) (term % NBASE);
9032  carry = term / NBASE;
9033 
9034  term = (uint32) var1digits[2] * var2digits[res_ndigits - 5] +
9035  (uint32) var1digits[3] * var2digits[res_ndigits - 6] + carry;
9036  res_digits[res_ndigits - 2] = (NumericDigit) (term % NBASE);
9037  carry = term / NBASE;
9038 
9039  term = (uint32) var1digits[1] * var2digits[res_ndigits - 5] +
9040  (uint32) var1digits[2] * var2digits[res_ndigits - 6] +
9041  (uint32) var1digits[3] * var2digits[res_ndigits - 7] + carry;
9042  res_digits[res_ndigits - 3] = (NumericDigit) (term % NBASE);
9043  carry = term / NBASE;
9044 
9045  /* remaining digits, except for the first four */
9046  for (int i = res_ndigits - 5; i >= 3; i--)
9047  {
9048  term = (uint32) var1digits[0] * var2digits[i] +
9049  (uint32) var1digits[1] * var2digits[i - 1] +
9050  (uint32) var1digits[2] * var2digits[i - 2] +
9051  (uint32) var1digits[3] * var2digits[i - 3] + carry;
9052  res_digits[i + 1] = (NumericDigit) (term % NBASE);
9053  carry = term / NBASE;
9054  }
9055 
9056  /* first four digits */
9057  term = (uint32) var1digits[0] * var2digits[2] +
9058  (uint32) var1digits[1] * var2digits[1] +
9059  (uint32) var1digits[2] * var2digits[0] + carry;
9060  res_digits[3] = (NumericDigit) (term % NBASE);
9061  carry = term / NBASE;
9062 
9063  term = (uint32) var1digits[0] * var2digits[1] +
9064  (uint32) var1digits[1] * var2digits[0] + carry;
9065  res_digits[2] = (NumericDigit) (term % NBASE);
9066  carry = term / NBASE;
9067 
9068  term = (uint32) var1digits[0] * var2digits[0] + carry;
9069  res_digits[1] = (NumericDigit) (term % NBASE);
9070  res_digits[0] = (NumericDigit) (term / NBASE);
9071  break;
9072  }
9073 
9074  /* Store the product in result */
9075  digitbuf_free(result->buf);
9076  result->ndigits = res_ndigits;
9077  result->buf = res_buf;
9078  result->digits = res_digits;
9079  result->weight = res_weight;
9080  result->sign = res_sign;
9081  result->dscale = var1->dscale + var2->dscale;
9082 
9083  /* Strip leading and trailing zeroes */
9084  strip_var(result);
9085 }

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

Referenced by mul_var().

◆ numeric()

Definition at line 1246 of file numeric.c.

1247 {
1248  Numeric num = PG_GETARG_NUMERIC(0);
1249  int32 typmod = PG_GETARG_INT32(1);
1250  Numeric new;
1251  int precision;
1252  int scale;
1253  int ddigits;
1254  int maxdigits;
1255  int dscale;
1256  NumericVar var;
1257 
1258  /*
1259  * Handle NaN and infinities: if apply_typmod_special doesn't complain,
1260  * just return a copy of the input.
1261  */
1262  if (NUMERIC_IS_SPECIAL(num))
1263  {
1264  (void) apply_typmod_special(num, typmod, NULL);
1266  }
1267 
1268  /*
1269  * If the value isn't a valid type modifier, simply return a copy of the
1270  * input value
1271  */
1272  if (!is_valid_numeric_typmod(typmod))
1274 
1275  /*
1276  * Get the precision and scale out of the typmod value
1277  */
1278  precision = numeric_typmod_precision(typmod);
1279  scale = numeric_typmod_scale(typmod);
1280  maxdigits = precision - scale;
1281 
1282  /* The target display scale is non-negative */
1283  dscale = Max(scale, 0);
1284 
1285  /*
1286  * If the number is certainly in bounds and due to the target scale no
1287  * rounding could be necessary, just make a copy of the input and modify
1288  * its scale fields, unless the larger scale forces us to abandon the
1289  * short representation. (Note we assume the existing dscale is
1290  * honest...)
1291  */
1292  ddigits = (NUMERIC_WEIGHT(num) + 1) * DEC_DIGITS;
1293  if (ddigits <= maxdigits && scale >= NUMERIC_DSCALE(num)
1294  && (NUMERIC_CAN_BE_SHORT(dscale, NUMERIC_WEIGHT(num))
1295  || !NUMERIC_IS_SHORT(num)))
1296  {
1297  new = duplicate_numeric(num);
1298  if (NUMERIC_IS_SHORT(num))
1299  new->choice.n_short.n_header =
1301  | (dscale << NUMERIC_SHORT_DSCALE_SHIFT);
1302  else
1303  new->choice.n_long.n_sign_dscale = NUMERIC_SIGN(new) |
1304  ((uint16) dscale & NUMERIC_DSCALE_MASK);
1305  PG_RETURN_NUMERIC(new);
1306  }
1307 
1308  /*
1309  * We really need to fiddle with things - unpack the number into a
1310  * variable and let apply_typmod() do it.
1311  */
1312  init_var(&var);
1313 
1314  set_var_from_num(num, &var);
1315  (void) apply_typmod(&var, typmod, NULL);
1316  new = make_result(&var);
1317 
1318  free_var(&var);
1319 
1320  PG_RETURN_NUMERIC(new);
1321 }
static Numeric duplicate_numeric(Numeric num)
Definition: numeric.c:7767
static bool apply_typmod_special(Numeric num, int32 typmod, Node *escontext)
Definition: numeric.c:7996
static bool apply_typmod(NumericVar *var, int32 typmod, Node *escontext)
Definition: numeric.c:7911
uint16 n_header
Definition: numeric.c:135
struct NumericShort n_short
Definition: numeric.c:150

References apply_typmod(), apply_typmod_special(), NumericData::choice, DEC_DIGITS, duplicate_numeric(), free_var(), init_var, is_valid_numeric_typmod(), make_result(), Max, maxdigits, NumericShort::n_header, NumericChoice::n_short, NUMERIC_CAN_BE_SHORT, NUMERIC_DSCALE, NUMERIC_DSCALE_MASK, NUMERIC_IS_SHORT, NUMERIC_IS_SPECIAL, NUMERIC_SHORT_DSCALE_MASK, NUMERIC_SHORT_DSCALE_SHIFT, NUMERIC_SIGN, numeric_typmod_precision(), numeric_typmod_scale(), NUMERIC_WEIGHT, PG_GETARG_INT32, PG_GETARG_NUMERIC, PG_RETURN_NUMERIC, scale, and set_var_from_num().

Referenced by ecpg_set_compat_sqlda(), and ecpg_set_native_sqlda().

◆ numeric_abbrev_abort()

static bool numeric_abbrev_abort ( int  memtupcount,
SortSupport  ssup 
)
static

Definition at line 2112 of file numeric.c.

2113 {
2114  NumericSortSupport *nss = ssup->ssup_extra;
2115  double abbr_card;
2116 
2117  if (memtupcount < 10000 || nss->input_count < 10000 || !nss->estimating)
2118  return false;
2119 
2120  abbr_card = estimateHyperLogLog(&nss->abbr_card);
2121 
2122  /*
2123  * If we have >100k distinct values, then even if we were sorting many
2124  * billion rows we'd likely still break even, and the penalty of undoing
2125  * that many rows of abbrevs would probably not be worth it. Stop even
2126  * counting at that point.
2127  */
2128  if (abbr_card > 100000.0)
2129  {
2130 #ifdef TRACE_SORT
2131  if (trace_sort)
2132  elog(LOG,
2133  "numeric_abbrev: estimation ends at cardinality %f"
2134  " after " INT64_FORMAT " values (%d rows)",
2135  abbr_card, nss->input_count, memtupcount);
2136 #endif
2137  nss->estimating = false;
2138  return false;
2139  }
2140 
2141  /*
2142  * Target minimum cardinality is 1 per ~10k of non-null inputs. (The
2143  * break even point is somewhere between one per 100k rows, where
2144  * abbreviation has a very slight penalty, and 1 per 10k where it wins by
2145  * a measurable percentage.) We use the relatively pessimistic 10k
2146  * threshold, and add a 0.5 row fudge factor, because it allows us to
2147  * abort earlier on genuinely pathological data where we've had exactly
2148  * one abbreviated value in the first 10k (non-null) rows.
2149  */
2150  if (abbr_card < nss->input_count / 10000.0 + 0.5)
2151  {
2152 #ifdef TRACE_SORT
2153  if (trace_sort)
2154  elog(LOG,
2155  "numeric_abbrev: aborting abbreviation at cardinality %f"
2156  " below threshold %f after " INT64_FORMAT " values (%d rows)",
2157  abbr_card, nss->input_count / 10000.0 + 0.5,
2158  nss->input_count, memtupcount);
2159 #endif
2160  return true;
2161  }
2162 
2163 #ifdef TRACE_SORT
2164  if (trace_sort)
2165  elog(LOG,
2166  "numeric_abbrev: cardinality %f"
2167  " after " INT64_FORMAT " values (%d rows)",
2168  abbr_card, nss->input_count, memtupcount);
2169 #endif
2170 
2171  return false;
2172 }
#define INT64_FORMAT
Definition: c.h:548
#define LOG
Definition: elog.h:31
double estimateHyperLogLog(hyperLogLogState *cState)
Definition: hyperloglog.c:186
hyperLogLogState abbr_card
Definition: numeric.c:343
void * ssup_extra
Definition: sortsupport.h:87
bool trace_sort
Definition: tuplesort.c:125

References NumericSortSupport::abbr_card, elog, estimateHyperLogLog(), NumericSortSupport::estimating, NumericSortSupport::input_count, INT64_FORMAT, LOG, SortSupportData::ssup_extra, and trace_sort.

Referenced by numeric_sortsupport().

◆ numeric_abbrev_convert()

static Datum numeric_abbrev_convert ( Datum  original_datum,
SortSupport  ssup 
)
static

Definition at line 2050 of file numeric.c.

2051 {
2052  NumericSortSupport *nss = ssup->ssup_extra;
2053  void *original_varatt = PG_DETOAST_DATUM_PACKED(original_datum);
2054  Numeric value;
2055  Datum result;
2056 
2057  nss->input_count += 1;
2058 
2059  /*
2060  * This is to handle packed datums without needing a palloc/pfree cycle;
2061  * we keep and reuse a buffer large enough to handle any short datum.
2062  */
2063  if (VARATT_IS_SHORT(original_varatt))
2064  {
2065  void *buf = nss->buf;
2066  Size sz = VARSIZE_SHORT(original_varatt) - VARHDRSZ_SHORT;
2067 
2069 
2070  SET_VARSIZE(buf, VARHDRSZ + sz);
2071  memcpy(VARDATA(buf), VARDATA_SHORT(original_varatt), sz);
2072 
2073  value = (Numeric) buf;
2074  }
2075  else
2076  value = (Numeric) original_varatt;
2077 
2079  {
2080  if (NUMERIC_IS_PINF(value))
2081  result = NUMERIC_ABBREV_PINF;
2082  else if (NUMERIC_IS_NINF(value))
2083  result = NUMERIC_ABBREV_NINF;
2084  else
2085  result = NUMERIC_ABBREV_NAN;
2086  }
2087  else
2088  {
2089  NumericVar var;
2090 
2091  init_var_from_num(value, &var);
2092 
2093  result = numeric_abbrev_convert_var(&var, nss);
2094  }
2095 
2096  /* should happen only for external/compressed toasts */
2097  if ((Pointer) original_varatt != DatumGetPointer(original_datum))
2098  pfree(original_varatt);
2099 
2100  return result;
2101 }
static Datum numeric_abbrev_convert_var(const NumericVar *var, NumericSortSupport *nss)
#define NUMERIC_ABBREV_PINF
Definition: numeric.c:412
#define NUMERIC_ABBREV_NAN
Definition: numeric.c:411
#define NUMERIC_ABBREV_NINF
Definition: numeric.c:413
char * Pointer
Definition: c.h:483
#define PG_DETOAST_DATUM_PACKED(datum)
Definition: fmgr.h:248
static struct @155 value
static Pointer DatumGetPointer(Datum X)
Definition: postgres.h:312
#define VARHDRSZ_SHORT
Definition: varatt.h:255
#define VARSIZE_SHORT(PTR)
Definition: varatt.h:281
#define VARATT_IS_SHORT(PTR)
Definition: varatt.h:302
#define VARDATA(PTR)
Definition: varatt.h:278
#define VARATT_SHORT_MAX
Definition: varatt.h:257
#define VARDATA_SHORT(PTR)
Definition: varatt.h:282

References Assert, NumericSortSupport::buf, buf, DatumGetPointer(), init_var_from_num(), NumericSortSupport::input_count, numeric_abbrev_convert_var(), NUMERIC_ABBREV_NAN, NUMERIC_ABBREV_NINF, NUMERIC_ABBREV_PINF, NUMERIC_IS_NINF, NUMERIC_IS_PINF, NUMERIC_IS_SPECIAL, pfree(), PG_DETOAST_DATUM_PACKED, SET_VARSIZE, SortSupportData::ssup_extra, value, VARATT_IS_SHORT, VARATT_SHORT_MAX, VARDATA, VARDATA_SHORT, VARHDRSZ, VARHDRSZ_SHORT, and VARSIZE_SHORT.

Referenced by numeric_sortsupport().

◆ numeric_abbrev_convert_var()

static Datum numeric_abbrev_convert_var ( const NumericVar var,
NumericSortSupport nss 
)
static

Referenced by numeric_abbrev_convert().

◆ numeric_abs()

Datum numeric_abs ( PG_FUNCTION_ARGS  )

Definition at line 1393 of file numeric.c.

1394 {
1395  Numeric num = PG_GETARG_NUMERIC(0);
1396  Numeric res;
1397 
1398  /*
1399  * Do it the easy way directly on the packed format
1400  */
1401  res = duplicate_numeric(num);
1402 
1403  if (NUMERIC_IS_SHORT(num))
1404  res->choice.n_short.n_header =
1406  else if (NUMERIC_IS_SPECIAL(num))
1407  {
1408  /* This changes -Inf to Inf, and doesn't affect NaN */
1409  res->choice.n_short.n_header =
1411  }
1412  else
1413  res->choice.n_long.n_sign_dscale = NUMERIC_POS | NUMERIC_DSCALE(num);
1414 
1416 }
#define NUMERIC_INF_SIGN_MASK
Definition: numeric.c:200

References NumericData::choice, duplicate_numeric(), NumericShort::n_header, NumericChoice::n_short, NUMERIC_DSCALE, NUMERIC_INF_SIGN_MASK, NUMERIC_IS_SHORT, NUMERIC_IS_SPECIAL, NUMERIC_POS, NUMERIC_SHORT_SIGN_MASK, PG_GETARG_NUMERIC, PG_RETURN_NUMERIC, and res.

Referenced by executeItemOptUnwrapTarget(), and numeric_absolute().

◆ numeric_accum()

Datum numeric_accum ( PG_FUNCTION_ARGS  )

Definition at line 5024 of file numeric.c.

5025 {
5027 
5028  state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
5029 
5030  /* Create the state data on the first call */
5031  if (state == NULL)
5032  state = makeNumericAggState(fcinfo, true);
5033 
5034  if (!PG_ARGISNULL(1))
5036 
5038 }

References do_numeric_accum(), makeNumericAggState(), PG_ARGISNULL, PG_GETARG_NUMERIC, PG_GETARG_POINTER, and PG_RETURN_POINTER.

◆ numeric_accum_inv()

Datum numeric_accum_inv ( PG_FUNCTION_ARGS  )

Definition at line 5435 of file numeric.c.

5436 {
5438 
5439  state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
5440 
5441  /* Should not get here with no state */
5442  if (state == NULL)
5443  elog(ERROR, "numeric_accum_inv called with NULL state");
5444 
5445  if (!PG_ARGISNULL(1))
5446  {
5447  /* If we fail to perform the inverse transition, return NULL */
5449  PG_RETURN_NULL();
5450  }
5451 
5453 }

References do_numeric_discard(), elog, ERROR, PG_ARGISNULL, PG_GETARG_NUMERIC, PG_GETARG_POINTER, PG_RETURN_NULL, and PG_RETURN_POINTER.

◆ numeric_add()

Datum numeric_add ( PG_FUNCTION_ARGS  )

Definition at line 2852 of file numeric.c.

2853 {
2854  Numeric num1 = PG_GETARG_NUMERIC(0);
2855  Numeric num2 = PG_GETARG_NUMERIC(1);
2856  Numeric res;
2857 
2858  res = numeric_add_opt_error(num1, num2, NULL);
2859 
2861 }
Numeric numeric_add_opt_error(Numeric num1, Numeric num2, bool *have_error)
Definition: numeric.c:2871

References numeric_add_opt_error(), PG_GETARG_NUMERIC, PG_RETURN_NUMERIC, and res.

Referenced by int8_sum(), numeric_half_rounded(), and pg_lsn_pli().

◆ numeric_add_opt_error()

Numeric numeric_add_opt_error ( Numeric  num1,
Numeric  num2,
bool have_error 
)

Definition at line 2871 of file numeric.c.

2872 {
2873  NumericVar arg1;
2874  NumericVar arg2;
2875  NumericVar result;
2876  Numeric res;
2877 
2878  /*
2879  * Handle NaN and infinities
2880  */
2881  if (NUMERIC_IS_SPECIAL(num1) || NUMERIC_IS_SPECIAL(num2))
2882  {
2883  if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
2884  return make_result(&const_nan);
2885  if (NUMERIC_IS_PINF(num1))
2886  {
2887  if (NUMERIC_IS_NINF(num2))
2888  return make_result(&const_nan); /* Inf + -Inf */
2889  else
2890  return make_result(&const_pinf);
2891  }
2892  if (NUMERIC_IS_NINF(num1))
2893  {
2894  if (NUMERIC_IS_PINF(num2))
2895  return make_result(&const_nan); /* -Inf + Inf */
2896  else
2897  return make_result(&const_ninf);
2898  }
2899  /* by here, num1 must be finite, so num2 is not */
2900  if (NUMERIC_IS_PINF(num2))
2901  return make_result(&const_pinf);
2902  Assert(NUMERIC_IS_NINF(num2));
2903  return make_result(&const_ninf);
2904  }
2905 
2906  /*
2907  * Unpack the values, let add_var() compute the result and return it.
2908  */
2909  init_var_from_num(num1, &arg1);
2910  init_var_from_num(num2, &arg2);
2911 
2912  init_var(&result);
2913  add_var(&arg1, &arg2, &result);
2914 
2915  res = make_result_opt_error(&result, have_error);
2916 
2917  free_var(&result);
2918 
2919  return res;
2920 }

References add_var(), Assert, const_nan, const_ninf, const_pinf, free_var(), init_var, init_var_from_num(), make_result(), make_result_opt_error(), NUMERIC_IS_NAN, NUMERIC_IS_NINF, NUMERIC_IS_PINF, NUMERIC_IS_SPECIAL, and res.

Referenced by executeItemOptUnwrapTarget(), interval_part_common(), numeric_add(), timestamp_part_common(), and timestamptz_part_common().

◆ numeric_avg()

Datum numeric_avg ( PG_FUNCTION_ARGS  )

Definition at line 6132 of file numeric.c.

6133 {
6135  Datum N_datum;
6136  Datum sumX_datum;
6137  NumericVar sumX_var;
6138 
6139  state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
6140 
6141  /* If there were no non-null inputs, return NULL */
6142  if (state == NULL || NA_TOTAL_COUNT(state) == 0)
6143  PG_RETURN_NULL();
6144 
6145  if (state->NaNcount > 0) /* there was at least one NaN input */
6147 
6148  /* adding plus and minus infinities gives NaN */
6149  if (state->pInfcount > 0 && state->nInfcount > 0)
6151  if (state->pInfcount > 0)
6153  if (state->nInfcount > 0)
6155 
6156  N_datum = NumericGetDatum(int64_to_numeric(state->N));
6157 
6158  init_var(&sumX_var);
6159  accum_sum_final(&state->sumX, &sumX_var);
6160  sumX_datum = NumericGetDatum(make_result(&sumX_var));
6161  free_var(&sumX_var);
6162 
6163  PG_RETURN_DATUM(DirectFunctionCall2(numeric_div, sumX_datum, N_datum));
6164 }
#define NA_TOTAL_COUNT(na)
Definition: numeric.c:4813

References accum_sum_final(), const_nan, const_ninf, const_pinf, DirectFunctionCall2, free_var(), init_var, int64_to_numeric(), make_result(), NA_TOTAL_COUNT, numeric_div(), NumericGetDatum(), PG_ARGISNULL, PG_GETARG_POINTER, PG_RETURN_DATUM, PG_RETURN_NULL, and PG_RETURN_NUMERIC.

Referenced by numeric_poly_avg().

◆ numeric_avg_accum()

Datum numeric_avg_accum ( PG_FUNCTION_ARGS  )

Definition at line 5116 of file numeric.c.

5117 {
5119 
5120  state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
5121 
5122  /* Create the state data on the first call */
5123  if (state == NULL)
5124  state = makeNumericAggState(fcinfo, false);
5125 
5126  if (!PG_ARGISNULL(1))
5128 
5130 }

References do_numeric_accum(), makeNumericAggState(), PG_ARGISNULL, PG_GETARG_NUMERIC, PG_GETARG_POINTER, and PG_RETURN_POINTER.

◆ numeric_avg_combine()

Datum numeric_avg_combine ( PG_FUNCTION_ARGS  )

Definition at line 5136 of file numeric.c.

5137 {
5138  NumericAggState *state1;
5139  NumericAggState *state2;
5140  MemoryContext agg_context;
5141  MemoryContext old_context;
5142 
5143  if (!AggCheckCallContext(fcinfo, &agg_context))
5144  elog(ERROR, "aggregate function called in non-aggregate context");
5145 
5146  state1 = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
5147  state2 = PG_ARGISNULL(1) ? NULL : (NumericAggState *) PG_GETARG_POINTER(1);
5148 
5149  if (state2 == NULL)
5150  PG_RETURN_POINTER(state1);
5151 
5152  /* manually copy all fields from state2 to state1 */
5153  if (state1 == NULL)
5154  {
5155  old_context = MemoryContextSwitchTo(agg_context);
5156 
5157  state1 = makeNumericAggStateCurrentContext(false);
5158  state1->N = state2->N;
5159  state1->NaNcount = state2->NaNcount;
5160  state1->pInfcount = state2->pInfcount;
5161  state1->nInfcount = state2->nInfcount;
5162  state1->maxScale = state2->maxScale;
5163  state1->maxScaleCount = state2->maxScaleCount;
5164 
5165  accum_sum_copy(&state1->sumX, &state2->sumX);
5166 
5167  MemoryContextSwitchTo(old_context);
5168 
5169  PG_RETURN_POINTER(state1);
5170  }
5171 
5172  state1->N += state2->N;
5173  state1->NaNcount += state2->NaNcount;
5174  state1->pInfcount += state2->pInfcount;
5175  state1->nInfcount += state2->nInfcount;
5176 
5177  if (state2->N > 0)
5178  {
5179  /*
5180  * These are currently only needed for moving aggregates, but let's do
5181  * the right thing anyway...
5182  */
5183  if (state2->maxScale > state1->maxScale)
5184  {
5185  state1->maxScale = state2->maxScale;
5186  state1->maxScaleCount = state2->maxScaleCount;
5187  }
5188  else if (state2->maxScale == state1->maxScale)
5189  state1->maxScaleCount += state2->maxScaleCount;
5190 
5191  /* The rest of this needs to work in the aggregate context */
5192  old_context = MemoryContextSwitchTo(agg_context);
5193 
5194  /* Accumulate sums */
5195  accum_sum_combine(&state1->sumX, &state2->sumX);
5196 
5197  MemoryContextSwitchTo(old_context);
5198  }
5199  PG_RETURN_POINTER(state1);
5200 }
static NumericAggState * makeNumericAggStateCurrentContext(bool calcSumX2)
Definition: numeric.c:4846
int64 NaNcount
Definition: numeric.c:4808
int64 nInfcount
Definition: numeric.c:4810
int64 maxScaleCount
Definition: numeric.c:4806
int64 pInfcount
Definition: numeric.c:4809

References accum_sum_combine(), accum_sum_copy(), AggCheckCallContext(), elog, ERROR, makeNumericAggStateCurrentContext(), NumericAggState::maxScale, NumericAggState::maxScaleCount, MemoryContextSwitchTo(), NumericAggState::N, NumericAggState::NaNcount, NumericAggState::nInfcount, PG_ARGISNULL, PG_GETARG_POINTER, PG_RETURN_POINTER, NumericAggState::pInfcount, and NumericAggState::sumX.

◆ numeric_avg_deserialize()

Datum numeric_avg_deserialize ( PG_FUNCTION_ARGS  )

Definition at line 5260 of file numeric.c.

5261 {
5262  bytea *sstate;
5263  NumericAggState *result;
5265  NumericVar tmp_var;
5266 
5267  if (!AggCheckCallContext(fcinfo, NULL))
5268  elog(ERROR, "aggregate function called in non-aggregate context");
5269 
5270  sstate = PG_GETARG_BYTEA_PP(0);
5271 
5272  init_var(&tmp_var);
5273 
5274  /*
5275  * Initialize a StringInfo so that we can "receive" it using the standard
5276  * recv-function infrastructure.
5277  */
5279  VARSIZE_ANY_EXHDR(sstate));
5280 
5281  result = makeNumericAggStateCurrentContext(false);
5282 
5283  /* N */
5284  result->N = pq_getmsgint64(&buf);
5285 
5286  /* sumX */
5287  numericvar_deserialize(&buf, &tmp_var);
5288  accum_sum_add(&(result->sumX), &tmp_var);
5289 
5290  /* maxScale */
5291  result->maxScale = pq_getmsgint(&buf, 4);
5292 
5293  /* maxScaleCount */
5294  result->maxScaleCount = pq_getmsgint64(&buf);
5295 
5296  /* NaNcount */
5297  result->NaNcount = pq_getmsgint64(&buf);
5298 
5299  /* pInfcount */
5300  result->pInfcount = pq_getmsgint64(&buf);
5301 
5302  /* nInfcount */
5303  result->nInfcount = pq_getmsgint64(&buf);
5304 
5305  pq_getmsgend(&buf);
5306 
5307  free_var(&tmp_var);
5308 
5309  PG_RETURN_POINTER(result);
5310 }
unsigned int pq_getmsgint(StringInfo msg, int b)
Definition: pqformat.c:415

References accum_sum_add(), AggCheckCallContext(), buf, elog, ERROR, free_var(), init_var, initReadOnlyStringInfo(), makeNumericAggStateCurrentContext(), NumericAggState::maxScale, NumericAggState::maxScaleCount, NumericAggState::N, NumericAggState::NaNcount, NumericAggState::nInfcount, numericvar_deserialize(), PG_GETARG_BYTEA_PP, PG_RETURN_POINTER, NumericAggState::pInfcount, pq_getmsgend(), pq_getmsgint(), pq_getmsgint64(), NumericAggState::sumX, VARDATA_ANY, and VARSIZE_ANY_EXHDR.

◆ numeric_avg_serialize()

Datum numeric_avg_serialize ( PG_FUNCTION_ARGS  )

Definition at line 5208 of file numeric.c.

5209 {
5212  bytea *result;
5213  NumericVar tmp_var;
5214 
5215  /* Ensure we disallow calling when not in aggregate context */
5216  if (!AggCheckCallContext(fcinfo, NULL))
5217  elog(ERROR, "aggregate function called in non-aggregate context");
5218 
5220 
5221  init_var(&tmp_var);
5222 
5223  pq_begintypsend(&buf);
5224 
5225  /* N */
5226  pq_sendint64(&buf, state->N);
5227 
5228  /* sumX */
5229  accum_sum_final(&state->sumX, &tmp_var);
5230  numericvar_serialize(&buf, &tmp_var);
5231 
5232  /* maxScale */
5233  pq_sendint32(&buf, state->maxScale);
5234 
5235  /* maxScaleCount */
5236  pq_sendint64(&buf, state->maxScaleCount);
5237 
5238  /* NaNcount */
5239  pq_sendint64(&buf, state->NaNcount);
5240 
5241  /* pInfcount */
5242  pq_sendint64(&buf, state->pInfcount);
5243 
5244  /* nInfcount */
5245  pq_sendint64(&buf, state->nInfcount);
5246 
5247  result = pq_endtypsend(&buf);
5248 
5249  free_var(&tmp_var);
5250 
5251  PG_RETURN_BYTEA_P(result);
5252 }
static void pq_sendint32(StringInfo buf, uint32 i)
Definition: pqformat.h:144

References accum_sum_final(), AggCheckCallContext(), buf, elog, ERROR, free_var(), init_var, numericvar_serialize(), PG_GETARG_POINTER, PG_RETURN_BYTEA_P, pq_begintypsend(), pq_endtypsend(), pq_sendint32(), and pq_sendint64().

◆ numeric_ceil()

Datum numeric_ceil ( PG_FUNCTION_ARGS  )

Definition at line 1647 of file numeric.c.

1648 {
1649  Numeric num = PG_GETARG_NUMERIC(0);
1650  Numeric res;
1651  NumericVar result;
1652 
1653  /*
1654  * Handle NaN and infinities
1655  */
1656  if (NUMERIC_IS_SPECIAL(num))
1658 
1659  init_var_from_num(num, &result);
1660  ceil_var(&result, &result);
1661 
1662  res = make_result(&result);
1663  free_var(&result);
1664 
1666 }
static void ceil_var(const NumericVar *var, NumericVar *result)
Definition: numeric.c:10165

References ceil_var(), duplicate_numeric(), free_var(), init_var_from_num(), make_result(), NUMERIC_IS_SPECIAL, PG_GETARG_NUMERIC, PG_RETURN_NUMERIC, and res.

Referenced by executeItemOptUnwrapTarget().

◆ numeric_cmp()

Datum numeric_cmp ( PG_FUNCTION_ARGS  )

Definition at line 2403 of file numeric.c.

2404 {
2405  Numeric num1 = PG_GETARG_NUMERIC(0);
2406  Numeric num2 = PG_GETARG_NUMERIC(1);
2407  int result;
2408 
2409  result = cmp_numerics(num1, num2);
2410 
2411  PG_FREE_IF_COPY(num1, 0);
2412  PG_FREE_IF_COPY(num2, 1);
2413 
2414  PG_RETURN_INT32(result);
2415 }
static int cmp_numerics(Numeric num1, Numeric num2)
Definition: numeric.c:2509
#define PG_RETURN_INT32(x)
Definition: fmgr.h:354

References cmp_numerics(), PG_FREE_IF_COPY, PG_GETARG_NUMERIC, and PG_RETURN_INT32.

Referenced by compareJsonbScalarValue(), compareNumeric(), gbt_numeric_cmp(), and gin_numeric_cmp().

◆ numeric_cmp_abbrev()

static int numeric_cmp_abbrev ( Datum  x,
Datum  y,
SortSupport  ssup 
)
static

Definition at line 2207 of file numeric.c.

2208 {
2209  /*
2210  * NOTE WELL: this is intentionally backwards, because the abbreviation is
2211  * negated relative to the original value, to handle NaN/infinity cases.
2212  */
2214  return 1;
2216  return -1;
2217  return 0;
2218 }
#define DatumGetNumericAbbrev(X)
Definition: numeric.c:410
int y
Definition: isn.c:72

References DatumGetNumericAbbrev, x, and y.

Referenced by numeric_sortsupport().

◆ numeric_combine()

Datum numeric_combine ( PG_FUNCTION_ARGS  )

Definition at line 5044 of file numeric.c.

5045 {
5046  NumericAggState *state1;
5047  NumericAggState *state2;
5048  MemoryContext agg_context;
5049  MemoryContext old_context;
5050 
5051  if (!AggCheckCallContext(fcinfo, &agg_context))
5052  elog(ERROR, "aggregate function called in non-aggregate context");
5053 
5054  state1 = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
5055  state2 = PG_ARGISNULL(1) ? NULL : (NumericAggState *) PG_GETARG_POINTER(1);
5056 
5057  if (state2 == NULL)
5058  PG_RETURN_POINTER(state1);
5059 
5060  /* manually copy all fields from state2 to state1 */
5061  if (state1 == NULL)
5062  {
5063  old_context = MemoryContextSwitchTo(agg_context);
5064 
5065  state1 = makeNumericAggStateCurrentContext(true);
5066  state1->N = state2->N;
5067  state1->NaNcount = state2->NaNcount;
5068  state1->pInfcount = state2->pInfcount;
5069  state1->nInfcount = state2->nInfcount;
5070  state1->maxScale = state2->maxScale;
5071  state1->maxScaleCount = state2->maxScaleCount;
5072 
5073  accum_sum_copy(&state1->sumX, &state2->sumX);
5074  accum_sum_copy(&state1->sumX2, &state2->sumX2);
5075 
5076  MemoryContextSwitchTo(old_context);
5077 
5078  PG_RETURN_POINTER(state1);
5079  }
5080 
5081  state1->N += state2->N;
5082  state1->NaNcount += state2->NaNcount;
5083  state1->pInfcount += state2->pInfcount;
5084  state1->nInfcount += state2->nInfcount;
5085 
5086  if (state2->N > 0)
5087  {
5088  /*
5089  * These are currently only needed for moving aggregates, but let's do
5090  * the right thing anyway...
5091  */
5092  if (state2->maxScale > state1->maxScale)
5093  {
5094  state1->maxScale = state2->maxScale;
5095  state1->maxScaleCount = state2->maxScaleCount;
5096  }
5097  else if (state2->maxScale == state1->maxScale)
5098  state1->maxScaleCount += state2->maxScaleCount;
5099 
5100  /* The rest of this needs to work in the aggregate context */
5101  old_context = MemoryContextSwitchTo(agg_context);
5102 
5103  /* Accumulate sums */
5104  accum_sum_combine(&state1->sumX, &state2->sumX);
5105  accum_sum_combine(&state1->sumX2, &state2->sumX2);
5106 
5107  MemoryContextSwitchTo(old_context);
5108  }
5109  PG_RETURN_POINTER(state1);
5110 }
NumericSumAccum sumX2
Definition: numeric.c:4804

References accum_sum_combine(), accum_sum_copy(), AggCheckCallContext(), elog, ERROR, makeNumericAggStateCurrentContext(), NumericAggState::maxScale, NumericAggState::maxScaleCount, MemoryContextSwitchTo(), NumericAggState::N, NumericAggState::NaNcount, NumericAggState::nInfcount, PG_ARGISNULL, PG_GETARG_POINTER, PG_RETURN_POINTER, NumericAggState::pInfcount, NumericAggState::sumX, and NumericAggState::sumX2.

◆ numeric_deserialize()

Datum numeric_deserialize ( PG_FUNCTION_ARGS  )

Definition at line 5374 of file numeric.c.

5375 {
5376  bytea *sstate;
5377  NumericAggState *result;
5379  NumericVar tmp_var;
5380 
5381  if (!AggCheckCallContext(fcinfo, NULL))
5382  elog(ERROR, "aggregate function called in non-aggregate context");
5383 
5384  sstate = PG_GETARG_BYTEA_PP(0);
5385 
5386  init_var(&tmp_var);
5387 
5388  /*
5389  * Initialize a StringInfo so that we can "receive" it using the standard
5390  * recv-function infrastructure.
5391  */
5393  VARSIZE_ANY_EXHDR(sstate));
5394 
5395  result = makeNumericAggStateCurrentContext(false);
5396 
5397  /* N */
5398  result->N = pq_getmsgint64(&buf);
5399 
5400  /* sumX */
5401  numericvar_deserialize(&buf, &tmp_var);
5402  accum_sum_add(&(result->sumX), &tmp_var);
5403 
5404  /* sumX2 */
5405  numericvar_deserialize(&buf, &tmp_var);
5406  accum_sum_add(&(result->sumX2), &tmp_var);
5407 
5408  /* maxScale */
5409  result->maxScale = pq_getmsgint(&buf, 4);
5410 
5411  /* maxScaleCount */
5412  result->maxScaleCount = pq_getmsgint64(&buf);
5413 
5414  /* NaNcount */
5415  result->NaNcount = pq_getmsgint64(&buf);
5416 
5417  /* pInfcount */
5418  result->pInfcount = pq_getmsgint64(&buf);
5419 
5420  /* nInfcount */
5421  result->nInfcount = pq_getmsgint64(&buf);
5422 
5423  pq_getmsgend(&buf);
5424 
5425  free_var(&tmp_var);
5426 
5427  PG_RETURN_POINTER(result);
5428 }

References accum_sum_add(), AggCheckCallContext(), buf, elog, ERROR, free_var(), init_var, initReadOnlyStringInfo(), makeNumericAggStateCurrentContext(), NumericAggState::maxScale, NumericAggState::maxScaleCount, NumericAggState::N, NumericAggState::NaNcount, NumericAggState::nInfcount, numericvar_deserialize(), PG_GETARG_BYTEA_PP, PG_RETURN_POINTER, NumericAggState::pInfcount, pq_getmsgend(), pq_getmsgint(), pq_getmsgint64(), NumericAggState::sumX, NumericAggState::sumX2, VARDATA_ANY, and VARSIZE_ANY_EXHDR.

◆ numeric_div()

Datum numeric_div ( PG_FUNCTION_ARGS  )

Definition at line 3128 of file numeric.c.

3129 {
3130  Numeric num1 = PG_GETARG_NUMERIC(0);
3131  Numeric num2 = PG_GETARG_NUMERIC(1);
3132  Numeric res;
3133 
3134  res = numeric_div_opt_error(num1, num2, NULL);
3135 
3137 }
Numeric numeric_div_opt_error(Numeric num1, Numeric num2, bool *have_error)
Definition: numeric.c:3148

References numeric_div_opt_error(), PG_GETARG_NUMERIC, PG_RETURN_NUMERIC, and res.

Referenced by cash_numeric(), gbt_numeric_penalty(), int8_avg(), numeric_avg(), and numeric_poly_avg().

◆ numeric_div_opt_error()

Numeric numeric_div_opt_error ( Numeric  num1,
Numeric  num2,
bool have_error 
)

Definition at line 3148 of file numeric.c.

3149 {
3150  NumericVar arg1;
3151  NumericVar arg2;
3152  NumericVar result;
3153  Numeric res;
3154  int rscale;
3155 
3156  if (have_error)
3157  *have_error = false;
3158 
3159  /*
3160  * Handle NaN and infinities
3161  */
3162  if (NUMERIC_IS_SPECIAL(num1) || NUMERIC_IS_SPECIAL(num2))
3163  {
3164  if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
3165  return make_result(&const_nan);
3166  if (NUMERIC_IS_PINF(num1))
3167  {
3168  if (NUMERIC_IS_SPECIAL(num2))
3169  return make_result(&const_nan); /* Inf / [-]Inf */
3170  switch (numeric_sign_internal(num2))
3171  {
3172  case 0:
3173  if (have_error)
3174  {
3175  *have_error = true;
3176  return NULL;
3177  }
3178  ereport(ERROR,
3179  (errcode(ERRCODE_DIVISION_BY_ZERO),
3180  errmsg("division by zero")));
3181  break;
3182  case 1:
3183  return make_result(&const_pinf);
3184  case -1:
3185  return make_result(&const_ninf);
3186  }
3187  Assert(false);
3188  }
3189  if (NUMERIC_IS_NINF(num1))
3190  {
3191  if (NUMERIC_IS_SPECIAL(num2))
3192  return make_result(&const_nan); /* -Inf / [-]Inf */
3193  switch (numeric_sign_internal(num2))
3194  {
3195  case 0:
3196  if (have_error)
3197  {
3198  *have_error = true;
3199  return NULL;
3200  }
3201  ereport(ERROR,
3202  (errcode(ERRCODE_DIVISION_BY_ZERO),
3203  errmsg("division by zero")));
3204  break;
3205  case 1:
3206  return make_result(&const_ninf);
3207  case -1:
3208  return make_result(&const_pinf);
3209  }
3210  Assert(false);
3211  }
3212  /* by here, num1 must be finite, so num2 is not */
3213 
3214  /*
3215  * POSIX would have us return zero or minus zero if num1 is zero, and
3216  * otherwise throw an underflow error. But the numeric type doesn't
3217  * really do underflow, so let's just return zero.
3218  */
3219  return make_result(&const_zero);
3220  }
3221 
3222  /*
3223  * Unpack the arguments
3224  */
3225  init_var_from_num(num1, &arg1);
3226  init_var_from_num(num2, &arg2);
3227 
3228  init_var(&result);
3229 
3230  /*
3231  * Select scale for division result
3232  */
3233  rscale = select_div_scale(&arg1, &arg2);
3234 
3235  /*
3236  * If "have_error" is provided, check for division by zero here
3237  */
3238  if (have_error && (arg2.ndigits == 0 || arg2.digits[0] == 0))
3239  {
3240  *have_error = true;
3241  return NULL;
3242  }
3243 
3244  /*
3245  * Do the divide and return the result
3246  */
3247  div_var(&arg1, &arg2, &result, rscale, true);
3248 
3249  res = make_result_opt_error(&result, have_error);
3250 
3251  free_var(&result);
3252 
3253  return res;
3254 }
static int numeric_sign_internal(Numeric num)
Definition: numeric.c:1478
static int select_div_scale(const NumericVar *var1, const NumericVar *var2)
Definition: numeric.c:9997

References Assert, const_nan, const_ninf, const_pinf, const_zero, NumericVar::digits, div_var(), ereport, errcode(), errmsg(), ERROR, free_var(), init_var, init_var_from_num(), make_result(), make_result_opt_error(), NumericVar::ndigits, NUMERIC_IS_NAN, NUMERIC_IS_NINF, NUMERIC_IS_PINF, NUMERIC_IS_SPECIAL, numeric_sign_internal(), res, and select_div_scale().

Referenced by executeItemOptUnwrapTarget(), numeric_div(), timestamp_part_common(), and timestamptz_part_common().

◆ numeric_div_trunc()

Datum numeric_div_trunc ( PG_FUNCTION_ARGS  )

Definition at line 3263 of file numeric.c.

3264 {
3265  Numeric num1 = PG_GETARG_NUMERIC(0);
3266  Numeric num2 = PG_GETARG_NUMERIC(1);
3267  NumericVar arg1;
3268  NumericVar arg2;
3269  NumericVar result;
3270  Numeric res;
3271 
3272  /*
3273  * Handle NaN and infinities
3274  */
3275  if (NUMERIC_IS_SPECIAL(num1) || NUMERIC_IS_SPECIAL(num2))
3276  {
3277  if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
3279  if (NUMERIC_IS_PINF(num1))
3280  {
3281  if (NUMERIC_IS_SPECIAL(num2))
3282  PG_RETURN_NUMERIC(make_result(&const_nan)); /* Inf / [-]Inf */
3283  switch (numeric_sign_internal(num2))
3284  {
3285  case 0:
3286  ereport(ERROR,
3287  (errcode(ERRCODE_DIVISION_BY_ZERO),
3288  errmsg("division by zero")));
3289  break;
3290  case 1:
3292  case -1:
3294  }
3295  Assert(false);
3296  }
3297  if (NUMERIC_IS_NINF(num1))
3298  {
3299  if (NUMERIC_IS_SPECIAL(num2))
3300  PG_RETURN_NUMERIC(make_result(&const_nan)); /* -Inf / [-]Inf */
3301  switch (numeric_sign_internal(num2))
3302  {
3303  case 0:
3304  ereport(ERROR,
3305  (errcode(ERRCODE_DIVISION_BY_ZERO),
3306  errmsg("division by zero")));
3307  break;
3308  case 1:
3310  case -1:
3312  }
3313  Assert(false);
3314  }
3315  /* by here, num1 must be finite, so num2 is not */
3316 
3317  /*
3318  * POSIX would have us return zero or minus zero if num1 is zero, and
3319  * otherwise throw an underflow error. But the numeric type doesn't
3320  * really do underflow, so let's just return zero.
3321  */
3323  }
3324 
3325  /*
3326  * Unpack the arguments
3327  */
3328  init_var_from_num(num1, &arg1);
3329  init_var_from_num(num2, &arg2);
3330 
3331  init_var(&result);
3332 
3333  /*
3334  * Do the divide and return the result
3335  */
3336  div_var(&arg1, &arg2, &result, 0, false);
3337 
3338  res = make_result(&result);
3339 
3340  free_var(&result);
3341 
3343 }

References Assert, const_nan, const_ninf, const_pinf, const_zero, div_var(), ereport, errcode(), errmsg(), ERROR, free_var(), init_var, init_var_from_num(), make_result(), NUMERIC_IS_NAN, NUMERIC_IS_NINF, NUMERIC_IS_PINF, NUMERIC_IS_SPECIAL, numeric_sign_internal(), PG_GETARG_NUMERIC, PG_RETURN_NUMERIC, and res.

Referenced by numeric_half_rounded(), and numeric_truncated_divide().

◆ numeric_eq()

Datum numeric_eq ( PG_FUNCTION_ARGS  )

Definition at line 2419 of file numeric.c.

2420 {
2421  Numeric num1 = PG_GETARG_NUMERIC(0);
2422  Numeric num2 = PG_GETARG_NUMERIC(1);
2423  bool result;
2424 
2425  result = cmp_numerics(num1, num2) == 0;
2426 
2427  PG_FREE_IF_COPY(num1, 0);
2428  PG_FREE_IF_COPY(num2, 1);
2429 
2430  PG_RETURN_BOOL(result);
2431 }

References cmp_numerics(), PG_FREE_IF_COPY, PG_GETARG_NUMERIC, and PG_RETURN_BOOL.

Referenced by equalsJsonbScalarValue(), and gbt_numeric_eq().

◆ numeric_exp()

Datum numeric_exp ( PG_FUNCTION_ARGS  )

Definition at line 3752 of file numeric.c.

3753 {
3754  Numeric num = PG_GETARG_NUMERIC(0);
3755  Numeric res;
3756  NumericVar arg;
3757  NumericVar result;
3758  int rscale;
3759  double val;
3760 
3761  /*
3762  * Handle NaN and infinities
3763  */
3764  if (NUMERIC_IS_SPECIAL(num))
3765  {
3766  /* Per POSIX, exp(-Inf) is zero */
3767  if (NUMERIC_IS_NINF(num))
3769  /* For NAN or PINF, just duplicate the input */
3771  }
3772 
3773  /*
3774  * Unpack the argument and determine the result scale. We choose a scale
3775  * to give at least NUMERIC_MIN_SIG_DIGITS significant digits; but in any
3776  * case not less than the input's dscale.
3777  */
3778  init_var_from_num(num, &arg);
3779 
3780  init_var(&result);
3781 
3782  /* convert input to float8, ignoring overflow */
3784 
3785  /*
3786  * log10(result) = num * log10(e), so this is approximately the decimal
3787  * weight of the result:
3788  */
3789  val *= 0.434294481903252;
3790 
3791  /* limit to something that won't cause integer overflow */
3794 
3795  rscale = NUMERIC_MIN_SIG_DIGITS - (int) val;
3796  rscale = Max(rscale, arg.dscale);
3797  rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
3798  rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
3799 
3800  /*
3801  * Let exp_var() do the calculation and return the result.
3802  */
3803  exp_var(&arg, &result, rscale);
3804 
3805  res = make_result(&result);
3806 
3807  free_var(&result);
3808 
3810 }
static void exp_var(const NumericVar *arg, NumericVar *result, int rscale)
Definition: numeric.c:10762

References arg, const_zero, duplicate_numeric(), exp_var(), free_var(), init_var, init_var_from_num(), make_result(), Max, Min, NUMERIC_IS_NINF, NUMERIC_IS_SPECIAL, NUMERIC_MAX_DISPLAY_SCALE, NUMERIC_MAX_RESULT_SCALE, NUMERIC_MIN_DISPLAY_SCALE, NUMERIC_MIN_SIG_DIGITS, numericvar_to_double_no_overflow(), PG_GETARG_NUMERIC, PG_RETURN_NUMERIC, res, and val.

◆ numeric_fac()

Datum numeric_fac ( PG_FUNCTION_ARGS  )

Definition at line 3628 of file numeric.c.

3629 {
3630  int64 num = PG_GETARG_INT64(0);
3631  Numeric res;
3632  NumericVar fact;
3633  NumericVar result;
3634 
3635  if (num < 0)
3636  ereport(ERROR,
3637  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
3638  errmsg("factorial of a negative number is undefined")));
3639  if (num <= 1)
3640  {
3643  }
3644  /* Fail immediately if the result would overflow */
3645  if (num > 32177)
3646  ereport(ERROR,
3647  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
3648  errmsg("value overflows numeric format")));
3649 
3650  init_var(&fact);
3651  init_var(&result);
3652 
3653  int64_to_numericvar(num, &result);
3654 
3655  for (num = num - 1; num > 1; num--)
3656  {
3657  /* this loop can take awhile, so allow it to be interrupted */
3659 
3660  int64_to_numericvar(num, &fact);
3661 
3662  mul_var(&result, &fact, &result, 0);
3663  }
3664 
3665  res = make_result(&result);
3666 
3667  free_var(&fact);
3668  free_var(&result);
3669 
3671 }

References CHECK_FOR_INTERRUPTS, const_one, ereport, errcode(), errmsg(), ERROR, free_var(), init_var, int64_to_numericvar(), make_result(), mul_var(), PG_GETARG_INT64, PG_RETURN_NUMERIC, and res.

◆ numeric_fast_cmp()

static int numeric_fast_cmp ( Datum  x,
Datum  y,
SortSupport  ssup 
)
static

Definition at line 2185 of file numeric.c.

2186 {
2187  Numeric nx = DatumGetNumeric(x);
2188  Numeric ny = DatumGetNumeric(y);
2189  int result;
2190 
2191  result = cmp_numerics(nx, ny);
2192 
2193  if ((Pointer) nx != DatumGetPointer(x))
2194  pfree(nx);
2195  if ((Pointer) ny != DatumGetPointer(y))
2196  pfree(ny);
2197 
2198  return result;
2199 }
static Numeric DatumGetNumeric(Datum X)
Definition: numeric.h:61

References cmp_numerics(), DatumGetNumeric(), DatumGetPointer(), pfree(), x, and y.

Referenced by numeric_sortsupport().

◆ numeric_float4()

Datum numeric_float4 ( PG_FUNCTION_ARGS  )

Definition at line 4726 of file numeric.c.

4727 {
4728  Numeric num = PG_GETARG_NUMERIC(0);
4729  char *tmp;
4730  Datum result;
4731 
4732  if (NUMERIC_IS_SPECIAL(num))
4733  {
4734  if (NUMERIC_IS_PINF(num))
4736  else if (NUMERIC_IS_NINF(num))
4738  else
4740  }
4741 
4743  NumericGetDatum(num)));
4744 
4746 
4747  pfree(tmp);
4748 
4749  PG_RETURN_DATUM(result);
4750 }
Datum numeric_out(PG_FUNCTION_ARGS)
Definition: numeric.c:816
Datum float4in(PG_FUNCTION_ARGS)
Definition: float.c:165
static float4 get_float4_infinity(void)
Definition: float.h:74
static float4 get_float4_nan(void)
Definition: float.h:111
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:642
#define PG_RETURN_FLOAT4(x)
Definition: fmgr.h:366
static char * DatumGetCString(Datum X)
Definition: postgres.h:335
static Datum CStringGetDatum(const char *X)
Definition: postgres.h:350

References CStringGetDatum(), DatumGetCString(), DirectFunctionCall1, float4in(), get_float4_infinity(), get_float4_nan(), NUMERIC_IS_NINF, NUMERIC_IS_PINF, NUMERIC_IS_SPECIAL, numeric_out(), NumericGetDatum(), pfree(), PG_GETARG_NUMERIC, PG_RETURN_DATUM, and PG_RETURN_FLOAT4.

Referenced by jsonb_float4().

◆ numeric_float8()

Datum numeric_float8 ( PG_FUNCTION_ARGS  )

Definition at line 4632 of file numeric.c.

4633 {
4634  Numeric num = PG_GETARG_NUMERIC(0);
4635  char *tmp;
4636  Datum result;
4637 
4638  if (NUMERIC_IS_SPECIAL(num))
4639  {
4640  if (NUMERIC_IS_PINF(num))
4642  else if (NUMERIC_IS_NINF(num))
4644  else
4646  }
4647 
4649  NumericGetDatum(num)));
4650 
4652 
4653  pfree(tmp);
4654 
4655  PG_RETURN_DATUM(result);
4656 }
Datum float8in(PG_FUNCTION_ARGS)
Definition: float.c:365
static float8 get_float8_infinity(void)
Definition: float.h:94
static float8 get_float8_nan(void)
Definition: float.h:123
#define PG_RETURN_FLOAT8(x)
Definition: fmgr.h:367

References CStringGetDatum(), DatumGetCString(), DirectFunctionCall1, float8in(), get_float8_infinity(), get_float8_nan(), NUMERIC_IS_NINF, NUMERIC_IS_PINF, NUMERIC_IS_SPECIAL, numeric_out(), NumericGetDatum(), pfree(), PG_GETARG_NUMERIC, PG_RETURN_DATUM, and PG_RETURN_FLOAT8.

Referenced by brin_minmax_multi_distance_numeric(), jsonb_float8(), and numrange_subdiff().

◆ numeric_float8_no_overflow()

Datum numeric_float8_no_overflow ( PG_FUNCTION_ARGS  )

Definition at line 4665 of file numeric.c.

4666 {
4667  Numeric num = PG_GETARG_NUMERIC(0);
4668  double val;
4669 
4670  if (NUMERIC_IS_SPECIAL(num))
4671  {
4672  if (NUMERIC_IS_PINF(num))
4673  val = HUGE_VAL;
4674  else if (NUMERIC_IS_NINF(num))
4675  val = -HUGE_VAL;
4676  else
4677  val = get_float8_nan();
4678  }
4679  else
4680  {
4681  NumericVar x;
4682 
4683  init_var_from_num(num, &x);
4685  }
4686 
4688 }

References get_float8_nan(), init_var_from_num(), NUMERIC_IS_NINF, NUMERIC_IS_PINF, NUMERIC_IS_SPECIAL, numericvar_to_double_no_overflow(), PG_GETARG_NUMERIC, PG_RETURN_FLOAT8, val, and x.

Referenced by convert_numeric_to_scalar(), and gbt_numeric_penalty().

◆ numeric_floor()

Datum numeric_floor ( PG_FUNCTION_ARGS  )

Definition at line 1675 of file numeric.c.

1676 {
1677  Numeric num = PG_GETARG_NUMERIC(0);
1678  Numeric res;
1679  NumericVar result;
1680 
1681  /*
1682  * Handle NaN and infinities
1683  */
1684  if (NUMERIC_IS_SPECIAL(num))
1686 
1687  init_var_from_num(num, &result);
1688  floor_var(&result, &result);
1689 
1690  res = make_result(&result);
1691  free_var(&result);
1692 
1694 }
static void floor_var(const NumericVar *var, NumericVar *result)
Definition: numeric.c:10189

References duplicate_numeric(), floor_var(), free_var(), init_var_from_num(), make_result(), NUMERIC_IS_SPECIAL, PG_GETARG_NUMERIC, PG_RETURN_NUMERIC, and res.

Referenced by executeItemOptUnwrapTarget().

◆ numeric_gcd()

Datum numeric_gcd ( PG_FUNCTION_ARGS  )

Definition at line 3525 of file numeric.c.

3526 {
3527  Numeric num1 = PG_GETARG_NUMERIC(0);
3528  Numeric num2 = PG_GETARG_NUMERIC(1);
3529  NumericVar arg1;
3530  NumericVar arg2;
3531  NumericVar result;
3532  Numeric res;
3533 
3534  /*
3535  * Handle NaN and infinities: we consider the result to be NaN in all such
3536  * cases.
3537  */
3538  if (NUMERIC_IS_SPECIAL(num1) || NUMERIC_IS_SPECIAL(num2))
3540 
3541  /*
3542  * Unpack the arguments
3543  */
3544  init_var_from_num(num1, &arg1);
3545  init_var_from_num(num2, &arg2);
3546 
3547  init_var(&result);
3548 
3549  /*
3550  * Find the GCD and return the result
3551  */
3552  gcd_var(&arg1, &arg2, &result);
3553 
3554  res = make_result(&result);
3555 
3556  free_var(&result);
3557 
3559 }
static void gcd_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition: numeric.c:10212

References const_nan, free_var(), gcd_var(), init_var, init_var_from_num(), make_result(), NUMERIC_IS_SPECIAL, PG_GETARG_NUMERIC, PG_RETURN_NUMERIC, and res.

◆ numeric_ge()

Datum numeric_ge ( PG_FUNCTION_ARGS  )

Definition at line 2464 of file numeric.c.

2465 {
2466  Numeric num1 = PG_GETARG_NUMERIC(0);
2467  Numeric num2 = PG_GETARG_NUMERIC(1);
2468  bool result;
2469 
2470  result = cmp_numerics(num1, num2) >= 0;
2471 
2472  PG_FREE_IF_COPY(num1, 0);
2473  PG_FREE_IF_COPY(num2, 1);
2474 
2475  PG_RETURN_BOOL(result);
2476 }

References cmp_numerics(), PG_FREE_IF_COPY, PG_GETARG_NUMERIC, and PG_RETURN_BOOL.

Referenced by gbt_numeric_ge(), and numeric_half_rounded().

◆ numeric_gt()

Datum numeric_gt ( PG_FUNCTION_ARGS  )

Definition at line 2449 of file numeric.c.

2450 {
2451  Numeric num1 = PG_GETARG_NUMERIC(0);
2452  Numeric num2 = PG_GETARG_NUMERIC(1);
2453  bool result;
2454 
2455  result = cmp_numerics(num1, num2) > 0;
2456 
2457  PG_FREE_IF_COPY(num1, 0);
2458  PG_FREE_IF_COPY(num2, 1);
2459 
2460  PG_RETURN_BOOL(result);
2461 }

References cmp_numerics(), PG_FREE_IF_COPY, PG_GETARG_NUMERIC, and PG_RETURN_BOOL.

Referenced by gbt_numeric_gt(), and gbt_numeric_penalty().

◆ numeric_in()

Datum numeric_in ( PG_FUNCTION_ARGS  )

Definition at line 637 of file numeric.c.

638 {
639  char *str = PG_GETARG_CSTRING(0);
640 #ifdef NOT_USED
641  Oid typelem = PG_GETARG_OID(1);
642 #endif
643  int32 typmod = PG_GETARG_INT32(2);
644  Node *escontext = fcinfo->context;
645  Numeric res;
646  const char *cp;
647  const char *numstart;
648  int sign;
649 
650  /* Skip leading spaces */
651  cp = str;
652  while (*cp)
653  {
654  if (!isspace((unsigned char) *cp))
655  break;
656  cp++;
657  }
658 
659  /*
660  * Process the number's sign. This duplicates logic in set_var_from_str(),
661  * but it's worth doing here, since it simplifies the handling of
662  * infinities and non-decimal integers.
663  */
664  numstart = cp;
665  sign = NUMERIC_POS;
666 
667  if (*cp == '+')
668  cp++;
669  else if (*cp == '-')
670  {
671  sign = NUMERIC_NEG;
672  cp++;
673  }
674 
675  /*
676  * Check for NaN and infinities. We recognize the same strings allowed by
677  * float8in().
678  *
679  * Since all other legal inputs have a digit or a decimal point after the
680  * sign, we need only check for NaN/infinity if that's not the case.
681  */
682  if (!isdigit((unsigned char) *cp) && *cp != '.')
683  {
684  /*
685  * The number must be NaN or infinity; anything else can only be a
686  * syntax error. Note that NaN mustn't have a sign.
687  */
688  if (pg_strncasecmp(numstart, "NaN", 3) == 0)
689  {
691  cp = numstart + 3;
692  }
693  else if (pg_strncasecmp(cp, "Infinity", 8) == 0)
694  {
696  cp += 8;
697  }
698  else if (pg_strncasecmp(cp, "inf", 3) == 0)
699  {
701  cp += 3;
702  }
703  else
704  goto invalid_syntax;
705 
706  /*
707  * Check for trailing junk; there should be nothing left but spaces.
708  *
709  * We intentionally do this check before applying the typmod because
710  * we would like to throw any trailing-junk syntax error before any
711  * semantic error resulting from apply_typmod_special().
712  */
713  while (*cp)
714  {
715  if (!isspace((unsigned char) *cp))
716  goto invalid_syntax;
717  cp++;
718  }
719 
720  if (!apply_typmod_special(res, typmod, escontext))
721  PG_RETURN_NULL();
722  }
723  else
724  {
725  /*
726  * We have a normal numeric value, which may be a non-decimal integer
727  * or a regular decimal number.
728  */
730  int base;
731  bool have_error;
732 
733  init_var(&value);
734 
735  /*
736  * Determine the number's base by looking for a non-decimal prefix
737  * indicator ("0x", "0o", or "0b").
738  */
739  if (cp[0] == '0')
740  {
741  switch (cp[1])
742  {
743  case 'x':
744  case 'X':
745  base = 16;
746  break;
747  case 'o':
748  case 'O':
749  base = 8;
750  break;
751  case 'b':
752  case 'B':
753  base = 2;
754  break;
755  default:
756  base = 10;
757  }
758  }
759  else
760  base = 10;
761 
762  /* Parse the rest of the number and apply the sign */
763  if (base == 10)
764  {
765  if (!set_var_from_str(str, cp, &value, &cp, escontext))
766  PG_RETURN_NULL();
767  value.sign = sign;
768  }
769  else
770  {
771  if (!set_var_from_non_decimal_integer_str(str, cp + 2, sign, base,
772  &value, &cp, escontext))
773  PG_RETURN_NULL();
774  }
775 
776  /*
777  * Should be nothing left but spaces. As above, throw any typmod error
778  * after finishing syntax check.
779  */
780  while (*cp)
781  {
782  if (!isspace((unsigned char) *cp))
783  goto invalid_syntax;
784  cp++;
785  }
786 
787  if (!apply_typmod(&value, typmod, escontext))
788  PG_RETURN_NULL();
789 
790  res = make_result_opt_error(&value, &have_error);
791 
792  if (have_error)
793  ereturn(escontext, (Datum) 0,
794  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
795  errmsg("value overflows numeric format")));
796 
797  free_var(&value);
798  }
799 
801 
802 invalid_syntax:
803  ereturn(escontext, (Datum) 0,
804  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
805  errmsg("invalid input syntax for type %s: \"%s\"",
806  "numeric", str)));
807 }
static bool set_var_from_non_decimal_integer_str(const char *str, const char *cp, int sign, int base, NumericVar *dest, const char **endptr, Node *escontext)
Definition: numeric.c:7246
#define PG_GETARG_OID(n)
Definition: fmgr.h:275
#define PG_GETARG_CSTRING(n)
Definition: fmgr.h:277
int pg_strncasecmp(const char *s1, const char *s2, size_t n)
Definition: pgstrcasecmp.c:69
unsigned int Oid
Definition: postgres_ext.h:31
Definition: nodes.h:129

References apply_typmod(), apply_typmod_special(), const_nan, const_ninf, const_pinf, ereturn, errcode(), errmsg(), free_var(), init_var, make_result(), make_result_opt_error(), NUMERIC_NEG, NUMERIC_POS, PG_GETARG_CSTRING, PG_GETARG_INT32, PG_GETARG_OID, PG_RETURN_NULL, PG_RETURN_NUMERIC, pg_strncasecmp(), res, set_var_from_non_decimal_integer_str(), set_var_from_str(), sign, str, and value.

Referenced by datum_to_jsonb_internal(), executeItemOptUnwrapTarget(), extract_date(), hstore_to_jsonb_loose(), interval_part_common(), jsonb_in_scalar(), make_const(), numeric_to_number(), pg_lsn_mi(), pg_lsn_mii(), pg_lsn_pli(), pg_size_bytes(), pg_split_walfile_name(), pg_stat_get_activity(), pg_stat_get_wal(), pg_stat_statements_internal(), PLyNumber_ToJsonbValue(), ssl_client_serial(), SV_to_JsonbValue(), timestamp_part_common(), and timestamptz_part_common().

◆ numeric_inc()

Datum numeric_inc ( PG_FUNCTION_ARGS  )

Definition at line 3441 of file numeric.c.

3442 {
3443  Numeric num = PG_GETARG_NUMERIC(0);
3444  NumericVar arg;
3445  Numeric res;
3446 
3447  /*
3448  * Handle NaN and infinities
3449  */
3450  if (NUMERIC_IS_SPECIAL(num))
3452 
3453  /*
3454  * Compute the result and return it
3455  */
3456  init_var_from_num(num, &arg);
3457 
3458  add_var(&arg, &const_one, &arg);
3459 
3460  res = make_result(&arg);
3461 
3462  free_var(&arg);
3463 
3465 }

References add_var(), arg, const_one, duplicate_numeric(), free_var(), init_var_from_num(), make_result(), NUMERIC_IS_SPECIAL, PG_GETARG_NUMERIC, PG_RETURN_NUMERIC, and res.

◆ numeric_int2()

Datum numeric_int2 ( PG_FUNCTION_ARGS  )

Definition at line 4557 of file numeric.c.

4558 {
4559  Numeric num = PG_GETARG_NUMERIC(0);
4560  NumericVar x;
4561  int64 val;
4562  int16 result;
4563 
4564  if (NUMERIC_IS_SPECIAL(num))
4565  {
4566  if (NUMERIC_IS_NAN(num))
4567  ereport(ERROR,
4568  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4569  errmsg("cannot convert NaN to %s", "smallint")));
4570  else
4571  ereport(ERROR,
4572  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4573  errmsg("cannot convert infinity to %s", "smallint")));
4574  }
4575 
4576  /* Convert to variable format and thence to int8 */
4577  init_var_from_num(num, &x);
4578 
4579  if (!numericvar_to_int64(&x, &val))
4580  ereport(ERROR,
4581  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
4582  errmsg("smallint out of range")));
4583 
4585  ereport(ERROR,
4586  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
4587  errmsg("smallint out of range")));
4588 
4589  /* Down-convert to int2 */
4590  result = (int16) val;
4591 
4592  PG_RETURN_INT16(result);
4593 }
static bool numericvar_to_int64(const NumericVar *var, int64 *result)
Definition: numeric.c:8033
#define PG_INT16_MIN
Definition: c.h:585
#define PG_INT16_MAX
Definition: c.h:586
#define PG_RETURN_INT16(x)
Definition: fmgr.h:356

References ereport, errcode(), errmsg(), ERROR, init_var_from_num(), NUMERIC_IS_NAN, NUMERIC_IS_SPECIAL, numericvar_to_int64(), PG_GETARG_NUMERIC, PG_INT16_MAX, PG_INT16_MIN, PG_RETURN_INT16, unlikely, val, and x.

Referenced by jsonb_int2().

◆ numeric_int4()

Datum numeric_int4 ( PG_FUNCTION_ARGS  )

Definition at line 4451 of file numeric.c.

4452 {
4453  Numeric num = PG_GETARG_NUMERIC(0);
4454 
4456 }
int32 numeric_int4_opt_error(Numeric num, bool *have_error)
Definition: numeric.c:4401

References numeric_int4_opt_error(), PG_GETARG_NUMERIC, and PG_RETURN_INT32.

Referenced by jsonb_int4(), and numeric_to_char().

◆ numeric_int4_opt_error()

int32 numeric_int4_opt_error ( Numeric  num,
bool have_error 
)

Definition at line 4401 of file numeric.c.

4402 {
4403  NumericVar x;
4404  int32 result;
4405 
4406  if (have_error)
4407  *have_error = false;
4408 
4409  if (NUMERIC_IS_SPECIAL(num))
4410  {
4411  if (have_error)
4412  {
4413  *have_error = true;
4414  return 0;
4415  }
4416  else
4417  {
4418  if (NUMERIC_IS_NAN(num))
4419  ereport(ERROR,
4420  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4421  errmsg("cannot convert NaN to %s", "integer")));
4422  else
4423  ereport(ERROR,
4424  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4425  errmsg("cannot convert infinity to %s", "integer")));
4426  }
4427  }
4428 
4429  /* Convert to variable format, then convert to int4 */
4430  init_var_from_num(num, &x);
4431 
4432  if (!numericvar_to_int32(&x, &result))
4433  {
4434  if (have_error)
4435  {
4436  *have_error = true;
4437  return 0;
4438  }
4439  else
4440  {
4441  ereport(ERROR,
4442  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
4443  errmsg("integer out of range")));
4444  }
4445  }
4446 
4447  return result;
4448 }
static bool numericvar_to_int32(const NumericVar *var, int32 *result)
Definition: numeric.c:4464

References ereport, errcode(), errmsg(), ERROR, init_var_from_num(), NUMERIC_IS_NAN, NUMERIC_IS_SPECIAL, numericvar_to_int32(), and x.

Referenced by executeDateTimeMethod(), executeItemOptUnwrapTarget(), getArrayIndex(), and numeric_int4().

◆ numeric_int8()

Datum numeric_int8 ( PG_FUNCTION_ARGS  )

Definition at line 4539 of file numeric.c.

4540 {
4541  Numeric num = PG_GETARG_NUMERIC(0);
4542 
4544 }
int64 numeric_int8_opt_error(Numeric num, bool *have_error)
Definition: numeric.c:4489

References numeric_int8_opt_error(), PG_GETARG_NUMERIC, and PG_RETURN_INT64.

Referenced by jsonb_int8(), numeric_cash(), and pg_size_bytes().

◆ numeric_int8_opt_error()

int64 numeric_int8_opt_error ( Numeric  num,
bool have_error 
)

Definition at line 4489 of file numeric.c.

4490 {
4491  NumericVar x;
4492  int64 result;
4493 
4494  if (have_error)
4495  *have_error = false;
4496 
4497  if (NUMERIC_IS_SPECIAL(num))
4498  {
4499  if (have_error)
4500  {
4501  *have_error = true;
4502  return 0;
4503  }
4504  else
4505  {
4506  if (NUMERIC_IS_NAN(num))
4507  ereport(ERROR,
4508  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4509  errmsg("cannot convert NaN to %s", "bigint")));
4510  else
4511  ereport(ERROR,
4512  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4513  errmsg("cannot convert infinity to %s", "bigint")));
4514  }
4515  }
4516 
4517  /* Convert to variable format, then convert to int8 */
4518  init_var_from_num(num, &x);
4519 
4520  if (!numericvar_to_int64(&x, &result))
4521  {
4522  if (have_error)
4523  {
4524  *have_error = true;
4525  return 0;
4526  }
4527  else
4528  {
4529  ereport(ERROR,
4530  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
4531  errmsg("bigint out of range")));
4532  }
4533  }
4534 
4535  return result;
4536 }

References ereport, errcode(), errmsg(), ERROR, init_var_from_num(), NUMERIC_IS_NAN, NUMERIC_IS_SPECIAL, numericvar_to_int64(), and x.

Referenced by executeItemOptUnwrapTarget(), and numeric_int8().

◆ numeric_is_inf()

bool numeric_is_inf ( Numeric  num)

Definition at line 862 of file numeric.c.

863 {
864  return NUMERIC_IS_INF(num);
865 }
#define NUMERIC_IS_INF(n)
Definition: numeric.c:206

References NUMERIC_IS_INF.

Referenced by executeItemOptUnwrapTarget(), and PLyNumber_ToJsonbValue().

◆ numeric_is_integral()

static bool numeric_is_integral ( Numeric  num)
static

Definition at line 873 of file numeric.c.

874 {
875  NumericVar arg;
876 
877  /* Reject NaN, but infinities are considered integral */
878  if (NUMERIC_IS_SPECIAL(num))
879  {
880  if (NUMERIC_IS_NAN(num))
881  return false;
882  return true;
883  }
884 
885  /* Integral if there are no digits to the right of the decimal point */
886  init_var_from_num(num, &arg);
887 
888  return (arg.ndigits == 0 || arg.ndigits <= arg.weight + 1);
889 }

References arg, init_var_from_num(), NUMERIC_IS_NAN, and NUMERIC_IS_SPECIAL.

Referenced by numeric_power().

◆ numeric_is_nan()

bool numeric_is_nan ( Numeric  num)

Definition at line 851 of file numeric.c.

852 {
853  return NUMERIC_IS_NAN(num);
854 }

References NUMERIC_IS_NAN.

Referenced by executeItemOptUnwrapTarget(), gbt_numeric_penalty(), pg_lsn_mii(), pg_lsn_pli(), and PLyNumber_ToJsonbValue().

◆ numeric_larger()

Datum numeric_larger ( PG_FUNCTION_ARGS  )

Definition at line 3496 of file numeric.c.

3497 {
3498  Numeric num1 = PG_GETARG_NUMERIC(0);
3499  Numeric num2 = PG_GETARG_NUMERIC(1);
3500 
3501  /*
3502  * Use cmp_numerics so that this will agree with the comparison operators,
3503  * particularly as regards comparisons involving NaN.
3504  */
3505  if (cmp_numerics(num1, num2) > 0)
3506  PG_RETURN_NUMERIC(num1);
3507  else
3508  PG_RETURN_NUMERIC(num2);
3509 }

References cmp_numerics(), PG_GETARG_NUMERIC, and PG_RETURN_NUMERIC.

◆ numeric_lcm()

Datum numeric_lcm ( PG_FUNCTION_ARGS  )

Definition at line 3568 of file numeric.c.

3569 {
3570  Numeric num1 = PG_GETARG_NUMERIC(0);
3571  Numeric num2 = PG_GETARG_NUMERIC(1);
3572  NumericVar arg1;
3573  NumericVar arg2;
3574  NumericVar result;
3575  Numeric res;
3576 
3577  /*
3578  * Handle NaN and infinities: we consider the result to be NaN in all such
3579  * cases.
3580  */
3581  if (NUMERIC_IS_SPECIAL(num1) || NUMERIC_IS_SPECIAL(num2))
3583 
3584  /*
3585  * Unpack the arguments
3586  */
3587  init_var_from_num(num1, &arg1);
3588  init_var_from_num(num2, &arg2);
3589 
3590  init_var(&result);
3591 
3592  /*
3593  * Compute the result using lcm(x, y) = abs(x / gcd(x, y) * y), returning
3594  * zero if either input is zero.
3595  *
3596  * Note that the division is guaranteed to be exact, returning an integer
3597  * result, so the LCM is an integral multiple of both x and y. A display
3598  * scale of Min(x.dscale, y.dscale) would be sufficient to represent it,
3599  * but as with other numeric functions, we choose to return a result whose
3600  * display scale is no smaller than either input.
3601  */
3602  if (arg1.ndigits == 0 || arg2.ndigits == 0)
3603  set_var_from_var(&const_zero, &result);
3604  else
3605  {
3606  gcd_var(&arg1, &arg2, &result);
3607  div_var(&arg1, &result, &result, 0, false);
3608  mul_var(&arg2, &result, &result, arg2.dscale);
3609  result.sign = NUMERIC_POS;
3610  }
3611 
3612  result.dscale = Max(arg1.dscale, arg2.dscale);
3613 
3614  res = make_result(&result);
3615 
3616  free_var(&result);
3617 
3619 }

References const_nan, const_zero, div_var(), NumericVar::dscale, free_var(), gcd_var(), init_var, init_var_from_num(), make_result(), Max, mul_var(), NumericVar::ndigits, NUMERIC_IS_SPECIAL, NUMERIC_POS, PG_GETARG_NUMERIC, PG_RETURN_NUMERIC, res, set_var_from_var(), and NumericVar::sign.

◆ numeric_le()

Datum numeric_le ( PG_FUNCTION_ARGS  )

Definition at line 2494 of file numeric.c.

2495 {
2496  Numeric num1 = PG_GETARG_NUMERIC(0);
2497  Numeric num2 = PG_GETARG_NUMERIC(1);
2498  bool result;
2499 
2500  result = cmp_numerics(num1, num2) <= 0;
2501 
2502  PG_FREE_IF_COPY(num1, 0);
2503  PG_FREE_IF_COPY(num2, 1);
2504 
2505  PG_RETURN_BOOL(result);
2506 }

References cmp_numerics(), PG_FREE_IF_COPY, PG_GETARG_NUMERIC, and PG_RETURN_BOOL.

Referenced by brin_minmax_multi_distance_numeric(), and gbt_numeric_le().

◆ numeric_ln()

Datum numeric_ln ( PG_FUNCTION_ARGS  )

Definition at line 3819 of file numeric.c.

3820 {
3821  Numeric num = PG_GETARG_NUMERIC(0);
3822  Numeric res;
3823  NumericVar arg;
3824  NumericVar result;
3825  int ln_dweight;
3826  int rscale;
3827 
3828  /*
3829  * Handle NaN and infinities
3830  */
3831  if (NUMERIC_IS_SPECIAL(num))
3832  {
3833  if (NUMERIC_IS_NINF(num))
3834  ereport(ERROR,
3835  (errcode(ERRCODE_INVALID_ARGUMENT_FOR_LOG),
3836  errmsg("cannot take logarithm of a negative number")));
3837  /* For NAN or PINF, just duplicate the input */
3839  }
3840 
3841  init_var_from_num(num, &arg);
3842  init_var(&result);
3843 
3844  /* Estimated dweight of logarithm */
3845  ln_dweight = estimate_ln_dweight(&arg);
3846 
3847  rscale = NUMERIC_MIN_SIG_DIGITS - ln_dweight;
3848  rscale = Max(rscale, arg.dscale);
3849  rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
3850  rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
3851 
3852  ln_var(&arg, &result, rscale);
3853 
3854  res = make_result(&result);
3855 
3856  free_var(&result);
3857 
3859 }

References arg, duplicate_numeric(), ereport, errcode(), errmsg(), ERROR, estimate_ln_dweight(), free_var(), init_var, init_var_from_num(), ln_var(), make_result(), Max, Min, NUMERIC_IS_NINF, NUMERIC_IS_SPECIAL, NUMERIC_MAX_DISPLAY_SCALE, NUMERIC_MIN_DISPLAY_SCALE, NUMERIC_MIN_SIG_DIGITS, PG_GETARG_NUMERIC, PG_RETURN_NUMERIC, and res.

◆ numeric_log()

Datum numeric_log ( PG_FUNCTION_ARGS  )

Definition at line 3868 of file numeric.c.

3869 {
3870  Numeric num1 = PG_GETARG_NUMERIC(0);
3871  Numeric num2 = PG_GETARG_NUMERIC(1);
3872  Numeric res;
3873  NumericVar arg1;
3874  NumericVar arg2;
3875  NumericVar result;
3876 
3877  /*
3878  * Handle NaN and infinities
3879  */
3880  if (NUMERIC_IS_SPECIAL(num1) || NUMERIC_IS_SPECIAL(num2))
3881  {
3882  int sign1,
3883  sign2;
3884 
3885  if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
3887  /* fail on negative inputs including -Inf, as log_var would */
3888  sign1 = numeric_sign_internal(num1);
3889  sign2 = numeric_sign_internal(num2);
3890  if (sign1 < 0 || sign2 < 0)
3891  ereport(ERROR,
3892  (errcode(ERRCODE_INVALID_ARGUMENT_FOR_LOG),
3893  errmsg("cannot take logarithm of a negative number")));
3894  /* fail on zero inputs, as log_var would */
3895  if (sign1 == 0 || sign2 == 0)
3896  ereport(ERROR,
3897  (errcode(ERRCODE_INVALID_ARGUMENT_FOR_LOG),
3898  errmsg("cannot take logarithm of zero")));
3899  if (NUMERIC_IS_PINF(num1))
3900  {
3901  /* log(Inf, Inf) reduces to Inf/Inf, so it's NaN */
3902  if (NUMERIC_IS_PINF(num2))
3904  /* log(Inf, finite-positive) is zero (we don't throw underflow) */
3906  }
3907  Assert(NUMERIC_IS_PINF(num2));
3908  /* log(finite-positive, Inf) is Inf */
3910  }
3911 
3912  /*
3913  * Initialize things
3914  */
3915  init_var_from_num(num1, &arg1);
3916  init_var_from_num(num2, &arg2);
3917  init_var(&result);
3918 
3919  /*
3920  * Call log_var() to compute and return the result; note it handles scale
3921  * selection itself.
3922  */
3923  log_var(&arg1, &arg2, &result);
3924 
3925  res = make_result(&result);
3926 
3927  free_var(&result);
3928 
3930 }
static void log_var(const NumericVar *base, const NumericVar *num, NumericVar *result)
Definition: numeric.c:11091

References Assert, const_nan, const_pinf, const_zero, ereport, errcode(), errmsg(), ERROR, free_var(), init_var, init_var_from_num(), log_var(), make_result(), NUMERIC_IS_NAN, NUMERIC_IS_PINF, NUMERIC_IS_SPECIAL, numeric_sign_internal(), PG_GETARG_NUMERIC, PG_RETURN_NUMERIC, and res.

◆ numeric_lt()

Datum numeric_lt ( PG_FUNCTION_ARGS  )

Definition at line 2479 of file numeric.c.

2480 {
2481  Numeric num1 = PG_GETARG_NUMERIC(0);
2482  Numeric num2 = PG_GETARG_NUMERIC(1);
2483  bool result;
2484 
2485  result = cmp_numerics(num1, num2) < 0;
2486 
2487  PG_FREE_IF_COPY(num1, 0);
2488  PG_FREE_IF_COPY(num2, 1);
2489 
2490  PG_RETURN_BOOL(result);
2491 }

References cmp_numerics(), PG_FREE_IF_COPY, PG_GETARG_NUMERIC, and PG_RETURN_BOOL.

Referenced by gbt_numeric_lt(), and numeric_is_less().

◆ numeric_maximum_size()

int32 numeric_maximum_size ( int32  typmod)

Definition at line 953 of file numeric.c.

954 {
955  int precision;
956  int numeric_digits;
957 
958  if (!is_valid_numeric_typmod(typmod))
959  return -1;
960 
961  /* precision (ie, max # of digits) is in upper bits of typmod */
962  precision = numeric_typmod_precision(typmod);
963 
964  /*
965  * This formula computes the maximum number of NumericDigits we could need
966  * in order to store the specified number of decimal digits. Because the
967  * weight is stored as a number of NumericDigits rather than a number of
968  * decimal digits, it's possible that the first NumericDigit will contain
969  * only a single decimal digit. Thus, the first two decimal digits can
970  * require two NumericDigits to store, but it isn't until we reach
971  * DEC_DIGITS + 2 decimal digits that we potentially need a third
972  * NumericDigit.
973  */
974  numeric_digits = (precision + 2 * (DEC_DIGITS - 1)) / DEC_DIGITS;
975 
976  /*
977  * In most cases, the size of a numeric will be smaller than the value
978  * computed below, because the varlena header will typically get toasted
979  * down to a single byte before being stored on disk, and it may also be
980  * possible to use a short numeric header. But our job here is to compute
981  * the worst case.
982  */
983  return NUMERIC_HDRSZ + (numeric_digits * sizeof(NumericDigit));
984 }

References DEC_DIGITS, is_valid_numeric_typmod(), NUMERIC_HDRSZ, and numeric_typmod_precision().

Referenced by type_maximum_size().

◆ numeric_min_scale()

Datum numeric_min_scale ( PG_FUNCTION_ARGS  )

Definition at line 4191 of file numeric.c.

4192 {
4193  Numeric num = PG_GETARG_NUMERIC(0);
4194  NumericVar arg;
4195  int min_scale;
4196 
4197  if (NUMERIC_IS_SPECIAL(num))
4198  PG_RETURN_NULL();
4199 
4200  init_var_from_num(num, &arg);
4201  min_scale = get_min_scale(&arg);
4202  free_var(&arg);
4203 
4204  PG_RETURN_INT32(min_scale);
4205 }
static int get_min_scale(NumericVar *var)
Definition: numeric.c:4140

References arg, free_var(), get_min_scale(), init_var_from_num(), NUMERIC_IS_SPECIAL, PG_GETARG_NUMERIC, PG_RETURN_INT32, and PG_RETURN_NULL.

◆ numeric_mod()

Datum numeric_mod ( PG_FUNCTION_ARGS  )

Definition at line 3352 of file numeric.c.

3353 {
3354  Numeric num1 = PG_GETARG_NUMERIC(0);
3355  Numeric num2 = PG_GETARG_NUMERIC(1);
3356  Numeric res;
3357 
3358  res = numeric_mod_opt_error(num1, num2, NULL);
3359 
3361 }
Numeric numeric_mod_opt_error(Numeric num1, Numeric num2, bool *have_error)
Definition: numeric.c:3372

References numeric_mod_opt_error(), PG_GETARG_NUMERIC, PG_RETURN_NUMERIC, and res.

◆ numeric_mod_opt_error()

Numeric numeric_mod_opt_error ( Numeric  num1,
Numeric  num2,
bool have_error 
)

Definition at line 3372 of file numeric.c.

3373 {
3374  Numeric res;
3375  NumericVar arg1;
3376  NumericVar arg2;
3377  NumericVar result;
3378 
3379  if (have_error)
3380  *have_error = false;
3381 
3382  /*
3383  * Handle NaN and infinities. We follow POSIX fmod() on this, except that
3384  * POSIX treats x-is-infinite and y-is-zero identically, raising EDOM and
3385  * returning NaN. We choose to throw error only for y-is-zero.
3386  */
3387  if (NUMERIC_IS_SPECIAL(num1) || NUMERIC_IS_SPECIAL(num2))
3388  {
3389  if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
3390  return make_result(&const_nan);
3391  if (NUMERIC_IS_INF(num1))
3392  {
3393  if (numeric_sign_internal(num2) == 0)
3394  {
3395  if (have_error)
3396  {
3397  *have_error = true;
3398  return NULL;
3399  }
3400  ereport(ERROR,
3401  (errcode(ERRCODE_DIVISION_BY_ZERO),
3402  errmsg("division by zero")));
3403  }
3404  /* Inf % any nonzero = NaN */
3405  return make_result(&const_nan);
3406  }
3407  /* num2 must be [-]Inf; result is num1 regardless of sign of num2 */
3408  return duplicate_numeric(num1);
3409  }
3410 
3411  init_var_from_num(num1, &arg1);
3412  init_var_from_num(num2, &arg2);
3413 
3414  init_var(&result);
3415 
3416  /*
3417  * If "have_error" is provided, check for division by zero here
3418  */
3419  if (have_error && (arg2.ndigits == 0 || arg2.digits[0] == 0))
3420  {
3421  *have_error = true;
3422  return NULL;
3423  }
3424 
3425  mod_var(&arg1, &arg2, &result);
3426 
3427  res = make_result_opt_error(&result, NULL);
3428 
3429  free_var(&result);
3430 
3431  return res;
3432 }

References const_nan, NumericVar::digits, duplicate_numeric(), ereport, errcode(), errmsg(), ERROR, free_var(), init_var, init_var_from_num(), make_result(), make_result_opt_error(), mod_var(), NumericVar::ndigits, NUMERIC_IS_INF, NUMERIC_IS_NAN, NUMERIC_IS_SPECIAL, numeric_sign_internal(), and res.

Referenced by executeItemOptUnwrapTarget(), and numeric_mod().

◆ numeric_mul()

Datum numeric_mul ( PG_FUNCTION_ARGS  )

Definition at line 3007 of file numeric.c.

3008 {
3009  Numeric num1 = PG_GETARG_NUMERIC(0);
3010  Numeric num2 = PG_GETARG_NUMERIC(1);
3011  Numeric res;
3012 
3013  res = numeric_mul_opt_error(num1, num2, NULL);
3014 
3016 }
Numeric numeric_mul_opt_error(Numeric num1, Numeric num2, bool *have_error)
Definition: numeric.c:3027

References numeric_mul_opt_error(), PG_GETARG_NUMERIC, PG_RETURN_NUMERIC, and res.

Referenced by numeric_cash(), numeric_to_char(), numeric_to_number(), and pg_size_bytes().

◆ numeric_mul_opt_error()

Numeric numeric_mul_opt_error ( Numeric  num1,
Numeric  num2,
bool have_error 
)

Definition at line 3027 of file numeric.c.

3028 {
3029  NumericVar arg1;
3030  NumericVar arg2;
3031  NumericVar result;
3032  Numeric res;
3033 
3034  /*
3035  * Handle NaN and infinities
3036  */
3037  if (NUMERIC_IS_SPECIAL(num1) || NUMERIC_IS_SPECIAL(num2))
3038  {
3039  if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
3040  return make_result(&const_nan);
3041  if (NUMERIC_IS_PINF(num1))
3042  {
3043  switch (numeric_sign_internal(num2))
3044  {
3045  case 0:
3046  return make_result(&const_nan); /* Inf * 0 */
3047  case 1:
3048  return make_result(&const_pinf);
3049  case -1:
3050  return make_result(&const_ninf);
3051  }
3052  Assert(false);
3053  }
3054  if (NUMERIC_IS_NINF(num1))
3055  {
3056  switch (numeric_sign_internal(num2))
3057  {
3058  case 0:
3059  return make_result(&const_nan); /* -Inf * 0 */
3060  case 1:
3061  return make_result(&const_ninf);
3062  case -1:
3063  return make_result(&const_pinf);
3064  }
3065  Assert(false);
3066  }
3067  /* by here, num1 must be finite, so num2 is not */
3068  if (NUMERIC_IS_PINF(num2))
3069  {
3070  switch (numeric_sign_internal(num1))
3071  {
3072  case 0:
3073  return make_result(&const_nan); /* 0 * Inf */
3074  case 1:
3075  return make_result(&const_pinf);
3076  case -1:
3077  return make_result(&const_ninf);
3078  }
3079  Assert(false);
3080  }
3081  Assert(NUMERIC_IS_NINF(num2));
3082  switch (numeric_sign_internal(num1))
3083  {
3084  case 0:
3085  return make_result(&const_nan); /* 0 * -Inf */
3086  case 1:
3087  return make_result(&const_ninf);
3088  case -1:
3089  return make_result(&const_pinf);
3090  }
3091  Assert(false);
3092  }
3093 
3094  /*
3095  * Unpack the values, let mul_var() compute the result and return it.
3096  * Unlike add_var() and sub_var(), mul_var() will round its result. In the
3097  * case of numeric_mul(), which is invoked for the * operator on numerics,
3098  * we request exact representation for the product (rscale = sum(dscale of
3099  * arg1, dscale of arg2)). If the exact result has more digits after the
3100  * decimal point than can be stored in a numeric, we round it. Rounding
3101  * after computing the exact result ensures that the final result is
3102  * correctly rounded (rounding in mul_var() using a truncated product
3103  * would not guarantee this).
3104  */
3105  init_var_from_num(num1, &arg1);
3106  init_var_from_num(num2, &arg2);
3107 
3108  init_var(&result);
3109  mul_var(&arg1, &arg2, &result, arg1.dscale + arg2.dscale);
3110 
3111  if (result.dscale > NUMERIC_DSCALE_MAX)
3112  round_var(&result, NUMERIC_DSCALE_MAX);
3113 
3114  res = make_result_opt_error(&result, have_error);
3115 
3116  free_var(&result);
3117 
3118  return res;
3119 }
#define NUMERIC_DSCALE_MAX
Definition: numeric.c:234

References Assert, const_nan, const_ninf, const_pinf, NumericVar::dscale, free_var(), init_var, init_var_from_num(), make_result(), make_result_opt_error(), mul_var(), NUMERIC_DSCALE_MAX, NUMERIC_IS_NAN, NUMERIC_IS_NINF, NUMERIC_IS_PINF, NUMERIC_IS_SPECIAL, numeric_sign_internal(), res, and round_var().

Referenced by executeItemOptUnwrapTarget(), and numeric_mul().

◆ numeric_ne()

Datum numeric_ne ( PG_FUNCTION_ARGS  )

Definition at line 2434 of file numeric.c.

2435 {
2436  Numeric num1 = PG_GETARG_NUMERIC(0);
2437  Numeric num2 = PG_GETARG_NUMERIC(1);
2438  bool result;
2439 
2440  result = cmp_numerics(num1, num2) != 0;
2441 
2442  PG_FREE_IF_COPY(num1, 0);
2443  PG_FREE_IF_COPY(num2, 1);
2444 
2445  PG_RETURN_BOOL(result);
2446 }

References cmp_numerics(), PG_FREE_IF_COPY, PG_GETARG_NUMERIC, and PG_RETURN_BOOL.

◆ numeric_normalize()

char* numeric_normalize ( Numeric  num)

Definition at line 1026 of file numeric.c.

1027 {
1028  NumericVar x;
1029  char *str;
1030  int last;
1031 
1032  /*
1033  * Handle NaN and infinities
1034  */
1035  if (NUMERIC_IS_SPECIAL(num))
1036  {
1037  if (NUMERIC_IS_PINF(num))
1038  return pstrdup("Infinity");
1039  else if (NUMERIC_IS_NINF(num))
1040  return pstrdup("-Infinity");
1041  else
1042  return pstrdup("NaN");
1043  }
1044 
1045  init_var_from_num(num, &x);
1046 
1047  str = get_str_from_var(&x);
1048 
1049  /* If there's no decimal point, there's certainly nothing to remove. */
1050  if (strchr(str, '.') != NULL)
1051  {
1052  /*
1053  * Back up over trailing fractional zeroes. Since there is a decimal
1054  * point, this loop will terminate safely.
1055  */
1056  last = strlen(str) - 1;
1057  while (str[last] == '0')
1058  last--;
1059 
1060  /* We want to get rid of the decimal point too, if it's now last. */
1061  if (str[last] == '.')
1062  last--;
1063 
1064  /* Delete whatever we backed up over. */
1065  str[last + 1] = '\0';
1066  }
1067 
1068  return str;
1069 }
char * pstrdup(const char *in)
Definition: mcxt.c:1696

References get_str_from_var(), init_var_from_num(), NUMERIC_IS_NINF, NUMERIC_IS_PINF, NUMERIC_IS_SPECIAL, pstrdup(), str, and x.

Referenced by make_scalar_key().

◆ numeric_out()

Datum numeric_out ( PG_FUNCTION_ARGS  )

Definition at line 816 of file numeric.c.

817 {
818  Numeric num = PG_GETARG_NUMERIC(0);
819  NumericVar x;
820  char *str;
821 
822  /*
823  * Handle NaN and infinities
824  */
825  if (NUMERIC_IS_SPECIAL(num))
826  {
827  if (NUMERIC_IS_PINF(num))
828  PG_RETURN_CSTRING(pstrdup("Infinity"));
829  else if (NUMERIC_IS_NINF(num))
830  PG_RETURN_CSTRING(pstrdup("-Infinity"));
831  else
832  PG_RETURN_CSTRING(pstrdup("NaN"));
833  }
834 
835  /*
836  * Get the number in the variable format.
837  */
838  init_var_from_num(num, &x);
839 
840  str = get_str_from_var(&x);
841 
843 }
#define PG_RETURN_CSTRING(x)
Definition: fmgr.h:362

References get_str_from_var(), init_var_from_num(), NUMERIC_IS_NINF, NUMERIC_IS_PINF, NUMERIC_IS_SPECIAL, PG_GETARG_NUMERIC, PG_RETURN_CSTRING, pstrdup(), str, and x.

Referenced by ExecGetJsonValueItemString(), executeItemOptUnwrapTarget(), iterate_jsonb_values(), jsonb_put_escaped_value(), JsonbUnquote(), JsonbValue_to_SV(), JsonbValueAsText(), numeric_float4(), numeric_float8(), numeric_to_char(), numeric_to_cstring(), PLyDecimal_FromNumeric(), PLyObject_FromJsonbValue(), populate_scalar(), and printJsonPathItem().

◆ numeric_out_sci()

char* numeric_out_sci ( Numeric  num,
int  scale 
)

Definition at line 992 of file numeric.c.

993 {
994  NumericVar x;
995  char *str;
996 
997  /*
998  * Handle NaN and infinities
999  */
1000  if (NUMERIC_IS_SPECIAL(num))
1001  {
1002  if (NUMERIC_IS_PINF(num))
1003  return pstrdup("Infinity");
1004  else if (NUMERIC_IS_NINF(num))
1005  return pstrdup("-Infinity");
1006  else
1007  return pstrdup("NaN");
1008  }
1009 
1010  init_var_from_num(num, &x);
1011 
1013 
1014  return str;
1015 }
static char * get_str_from_var_sci(const NumericVar *var, int rscale)
Definition: numeric.c:7651

References get_str_from_var_sci(), init_var_from_num(), NUMERIC_IS_NINF, NUMERIC_IS_PINF, NUMERIC_IS_SPECIAL, pstrdup(), scale, str, and x.

Referenced by int8_to_char(), and numeric_to_char().

◆ numeric_pg_lsn()

Datum numeric_pg_lsn ( PG_FUNCTION_ARGS  )

Definition at line 4754 of file numeric.c.

4755 {
4756  Numeric num = PG_GETARG_NUMERIC(0);
4757  NumericVar x;
4758  XLogRecPtr result;
4759 
4760  if (NUMERIC_IS_SPECIAL(num))
4761  {
4762  if (NUMERIC_IS_NAN(num))
4763  ereport(ERROR,
4764  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4765  errmsg("cannot convert NaN to %s", "pg_lsn")));
4766  else
4767  ereport(ERROR,
4768  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4769  errmsg("cannot convert infinity to %s", "pg_lsn")));
4770  }
4771 
4772  /* Convert to variable format and thence to pg_lsn */
4773  init_var_from_num(num, &x);
4774 
4775  if (!numericvar_to_uint64(&x, (uint64 *) &result))
4776  ereport(ERROR,
4777  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4778  errmsg("pg_lsn out of range")));
4779 
4780  PG_RETURN_LSN(result);
4781 }
static bool numericvar_to_uint64(const NumericVar *var, uint64 *result)
Definition: numeric.c:8155
#define PG_RETURN_LSN(x)
Definition: pg_lsn.h:34
uint64 XLogRecPtr
Definition: xlogdefs.h:21

References ereport, errcode(), errmsg(), ERROR, init_var_from_num(), NUMERIC_IS_NAN, NUMERIC_IS_SPECIAL, numericvar_to_uint64(), PG_GETARG_NUMERIC, PG_RETURN_LSN, and x.

Referenced by pg_lsn_mii(), and pg_lsn_pli().

◆ numeric_poly_avg()

Datum numeric_poly_avg ( PG_FUNCTION_ARGS  )

Definition at line 6102 of file numeric.c.

6103 {
6104 #ifdef HAVE_INT128
6106  NumericVar result;
6107  Datum countd,
6108  sumd;
6109 
6110  state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
6111 
6112  /* If there were no non-null inputs, return NULL */
6113  if (state == NULL || state->N == 0)
6114  PG_RETURN_NULL();
6115 
6116  init_var(&result);
6117 
6118  int128_to_numericvar(state->sumX, &result);
6119 
6120  countd = NumericGetDatum(int64_to_numeric(state->N));
6121  sumd = NumericGetDatum(make_result(&result));
6122 
6123  free_var(&result);
6124 
6126 #else
6127  return numeric_avg(fcinfo);
6128 #endif
6129 }
Datum numeric_avg(PG_FUNCTION_ARGS)
Definition: numeric.c:6132

References DirectFunctionCall2, free_var(), init_var, int64_to_numeric(), make_result(), numeric_avg(), numeric_div(), NumericGetDatum(), PG_ARGISNULL, PG_GETARG_POINTER, PG_RETURN_DATUM, and PG_RETURN_NULL.

◆ numeric_poly_combine()

Datum numeric_poly_combine ( PG_FUNCTION_ARGS  )

Definition at line 5620 of file numeric.c.

5621 {
5622  PolyNumAggState *state1;
5623  PolyNumAggState *state2;
5624  MemoryContext agg_context;
5625  MemoryContext old_context;
5626 
5627  if (!AggCheckCallContext(fcinfo, &agg_context))
5628  elog(ERROR, "aggregate function called in non-aggregate context");
5629 
5630  state1 = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
5631  state2 = PG_ARGISNULL(1) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(1);
5632 
5633  if (state2 == NULL)
5634  PG_RETURN_POINTER(state1);
5635 
5636  /* manually copy all fields from state2 to state1 */
5637  if (state1 == NULL)
5638  {
5639  old_context = MemoryContextSwitchTo(agg_context);
5640 
5641  state1 = makePolyNumAggState(fcinfo, true);
5642  state1->N = state2->N;
5643 
5644 #ifdef HAVE_INT128
5645  state1->sumX = state2->sumX;
5646  state1->sumX2 = state2->sumX2;
5647 #else
5648  accum_sum_copy(&state1->sumX, &state2->sumX);
5649  accum_sum_copy(&state1->sumX2, &state2->sumX2);
5650 #endif
5651 
5652  MemoryContextSwitchTo(old_context);
5653 
5654  PG_RETURN_POINTER(state1);
5655  }
5656 
5657  if (state2->N > 0)
5658  {
5659  state1->N += state2->N;
5660 
5661 #ifdef HAVE_INT128
5662  state1->sumX += state2->sumX;
5663  state1->sumX2 += state2->sumX2;
5664 #else
5665  /* The rest of this needs to work in the aggregate context */
5666  old_context = MemoryContextSwitchTo(agg_context);
5667 
5668  /* Accumulate sums */
5669  accum_sum_combine(&state1->sumX, &state2->sumX);
5670  accum_sum_combine(&state1->sumX2, &state2->sumX2);
5671 
5672  MemoryContextSwitchTo(old_context);
5673 #endif
5674 
5675  }
5676  PG_RETURN_POINTER(state1);
5677 }

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

◆ numeric_poly_deserialize()

Datum numeric_poly_deserialize ( PG_FUNCTION_ARGS  )

Definition at line 5743 of file numeric.c.

5744 {
5745  bytea *sstate;
5746  PolyNumAggState *result;
5748  NumericVar tmp_var;
5749 
5750  if (!AggCheckCallContext(fcinfo, NULL))
5751  elog(ERROR, "aggregate function called in non-aggregate context");
5752 
5753  sstate = PG_GETARG_BYTEA_PP(0);
5754 
5755  init_var(&tmp_var);
5756 
5757  /*
5758  * Initialize a StringInfo so that we can "receive" it using the standard
5759  * recv-function infrastructure.
5760  */
5762  VARSIZE_ANY_EXHDR(sstate));
5763 
5764  result = makePolyNumAggStateCurrentContext(false);
5765 
5766  /* N */
5767  result->N = pq_getmsgint64(&buf);
5768 
5769  /* sumX */
5770  numericvar_deserialize(&buf, &tmp_var);
5771 #ifdef HAVE_INT128
5772  numericvar_to_int128(&tmp_var, &result->sumX);
5773 #else
5774  accum_sum_add(&result->sumX, &tmp_var);
5775 #endif
5776 
5777  /* sumX2 */
5778  numericvar_deserialize(&buf, &tmp_var);
5779 #ifdef HAVE_INT128
5780  numericvar_to_int128(&tmp_var, &result->sumX2);
5781 #else
5782  accum_sum_add(&result->sumX2, &tmp_var);
5783 #endif
5784 
5785  pq_getmsgend(&buf);
5786 
5787  free_var(&tmp_var);
5788 
5789  PG_RETURN_POINTER(result);
5790 }

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

◆ numeric_poly_serialize()

Datum numeric_poly_serialize ( PG_FUNCTION_ARGS  )

Definition at line 5685 of file numeric.c.

5686 {
5689  bytea *result;
5690  NumericVar tmp_var;
5691 
5692  /* Ensure we disallow calling when not in aggregate context */
5693  if (!AggCheckCallContext(fcinfo, NULL))
5694  elog(ERROR, "aggregate function called in non-aggregate context");
5695 
5697 
5698  /*
5699  * If the platform supports int128 then sumX and sumX2 will be a 128 bit
5700  * integer type. Here we'll convert that into a numeric type so that the
5701  * combine state is in the same format for both int128 enabled machines
5702  * and machines which don't support that type. The logic here is that one
5703  * day we might like to send these over to another server for further
5704  * processing and we want a standard format to work with.
5705  */
5706 
5707  init_var(&tmp_var);
5708 
5709  pq_begintypsend(&buf);
5710 
5711  /* N */
5712  pq_sendint64(&buf, state->N);
5713 
5714  /* sumX */
5715 #ifdef HAVE_INT128
5716  int128_to_numericvar(state->sumX, &tmp_var);
5717 #else
5718  accum_sum_final(&state->sumX, &tmp_var);
5719 #endif
5720  numericvar_serialize(&buf, &tmp_var);
5721 
5722  /* sumX2 */
5723 #ifdef HAVE_INT128
5724  int128_to_numericvar(state->sumX2, &tmp_var);
5725 #else
5726  accum_sum_final(&state->sumX2, &tmp_var);
5727 #endif
5728  numericvar_serialize(&buf, &tmp_var);
5729 
5730  result = pq_endtypsend(&buf);
5731 
5732  free_var(&tmp_var);
5733 
5734  PG_RETURN_BYTEA_P(result);
5735 }

References accum_sum_final(), AggCheckCallContext(), buf, elog, ERROR, free_var(), init_var, numericvar_serialize(), PG_GETARG_POINTER, PG_RETURN_BYTEA_P, pq_begintypsend(), pq_endtypsend(), and pq_sendint64().

◆ numeric_poly_stddev_pop()

Datum numeric_poly_stddev_pop ( PG_FUNCTION_ARGS  )

Definition at line 6471 of file numeric.c.

6472 {
6473 #ifdef HAVE_INT128
6475  Numeric res;
6476  bool is_null;
6477 
6478  state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
6479 
6480  res = numeric_poly_stddev_internal(state, false, false, &is_null);
6481 
6482  if (is_null)
6483  PG_RETURN_NULL();
6484  else
6486 #else
6487  return numeric_stddev_pop(fcinfo);
6488 #endif
6489 }
Datum numeric_stddev_pop(PG_FUNCTION_ARGS)
Definition: numeric.c:6345

References numeric_stddev_pop(), PG_ARGISNULL, PG_GETARG_POINTER, PG_RETURN_NULL, PG_RETURN_NUMERIC, and res.

◆ numeric_poly_stddev_samp()

Datum numeric_poly_stddev_samp ( PG_FUNCTION_ARGS  )

Definition at line 6429 of file numeric.c.

6430 {
6431 #ifdef HAVE_INT128
6433  Numeric res;
6434  bool is_null;
6435 
6436  state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
6437 
6438  res = numeric_poly_stddev_internal(state, false, true, &is_null);
6439 
6440  if (is_null)
6441  PG_RETURN_NULL();
6442  else
6444 #else
6445  return numeric_stddev_samp(fcinfo);
6446 #endif
6447 }
Datum numeric_stddev_samp(PG_FUNCTION_ARGS)
Definition: numeric.c:6311

References numeric_stddev_samp(), PG_ARGISNULL, PG_GETARG_POINTER, PG_RETURN_NULL, PG_RETURN_NUMERIC, and res.

◆ numeric_poly_sum()

Datum numeric_poly_sum ( PG_FUNCTION_ARGS  )

Definition at line 6074 of file numeric.c.

6075 {
6076 #ifdef HAVE_INT128
6078  Numeric res;
6079  NumericVar result;
6080 
6081  state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
6082 
6083  /* If there were no non-null inputs, return NULL */
6084  if (state == NULL || state->N == 0)
6085  PG_RETURN_NULL();
6086 
6087  init_var(&result);
6088 
6089  int128_to_numericvar(state->sumX, &result);
6090 
6091  res = make_result(&result);
6092 
6093  free_var(&result);
6094 
6096 #else
6097  return numeric_sum(fcinfo);
6098 #endif
6099 }
Datum numeric_sum(PG_FUNCTION_ARGS)
Definition: numeric.c:6167

References free_var(), init_var, make_result(), numeric_sum(), PG_ARGISNULL, PG_GETARG_POINTER, PG_RETURN_NULL, PG_RETURN_NUMERIC, and res.

◆ numeric_poly_var_pop()

Datum numeric_poly_var_pop ( PG_FUNCTION_ARGS  )

Definition at line 6450 of file numeric.c.

6451 {
6452 #ifdef HAVE_INT128
6454  Numeric res;
6455  bool is_null;
6456 
6457  state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
6458 
6459  res = numeric_poly_stddev_internal(state, true, false, &is_null);
6460 
6461  if (is_null)
6462  PG_RETURN_NULL();
6463  else
6465 #else
6466  return numeric_var_pop(fcinfo);
6467 #endif
6468 }
Datum numeric_var_pop(PG_FUNCTION_ARGS)
Definition: numeric.c:6328

References numeric_var_pop(), PG_ARGISNULL, PG_GETARG_POINTER, PG_RETURN_NULL, PG_RETURN_NUMERIC, and res.

◆ numeric_poly_var_samp()

Datum numeric_poly_var_samp ( PG_FUNCTION_ARGS  )

Definition at line 6408 of file numeric.c.

6409 {
6410 #ifdef HAVE_INT128
6412  Numeric res;
6413  bool is_null;
6414 
6415  state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
6416 
6417  res = numeric_poly_stddev_internal(state, true, true, &is_null);
6418 
6419  if (is_null)
6420  PG_RETURN_NULL();
6421  else
6423 #else
6424  return numeric_var_samp(fcinfo);
6425 #endif
6426 }
Datum numeric_var_samp(PG_FUNCTION_ARGS)
Definition: numeric.c:6294

References numeric_var_samp(), PG_ARGISNULL, PG_GETARG_POINTER, PG_RETURN_NULL, PG_RETURN_NUMERIC, and res.

◆ numeric_power()

Datum numeric_power ( PG_FUNCTION_ARGS  )

Definition at line 3939 of file numeric.c.

3940 {
3941  Numeric num1 = PG_GETARG_NUMERIC(0);
3942  Numeric num2 = PG_GETARG_NUMERIC(1);
3943  Numeric res;
3944  NumericVar arg1;
3945  NumericVar arg2;
3946  NumericVar result;
3947  int sign1,
3948  sign2;
3949 
3950  /*
3951  * Handle NaN and infinities
3952  */
3953  if (NUMERIC_IS_SPECIAL(num1) || NUMERIC_IS_SPECIAL(num2))
3954  {
3955  /*
3956  * We follow the POSIX spec for pow(3), which says that NaN ^ 0 = 1,
3957  * and 1 ^ NaN = 1, while all other cases with NaN inputs yield NaN
3958  * (with no error).
3959  */
3960  if (NUMERIC_IS_NAN(num1))
3961  {
3962  if (!NUMERIC_IS_SPECIAL(num2))
3963  {
3964  init_var_from_num(num2, &arg2);
3965  if (cmp_var(&arg2, &const_zero) == 0)
3967  }
3969  }
3970  if (NUMERIC_IS_NAN(num2))
3971  {
3972  if (!NUMERIC_IS_SPECIAL(num1))
3973  {
3974  init_var_from_num(num1, &arg1);
3975  if (cmp_var(&arg1, &const_one) == 0)
3977  }
3979  }
3980  /* At least one input is infinite, but error rules still apply */
3981  sign1 = numeric_sign_internal(num1);
3982  sign2 = numeric_sign_internal(num2);
3983  if (sign1 == 0 && sign2 < 0)
3984  ereport(ERROR,
3985  (errcode(ERRCODE_INVALID_ARGUMENT_FOR_POWER_FUNCTION),
3986  errmsg("zero raised to a negative power is undefined")));
3987  if (sign1 < 0 && !numeric_is_integral(num2))
3988  ereport(ERROR,
3989  (errcode(ERRCODE_INVALID_ARGUMENT_FOR_POWER_FUNCTION),
3990  errmsg("a negative number raised to a non-integer power yields a complex result")));
3991 
3992  /*
3993  * POSIX gives this series of rules for pow(3) with infinite inputs:
3994  *
3995  * For any value of y, if x is +1, 1.0 shall be returned.
3996  */
3997  if (!NUMERIC_IS_SPECIAL(num1))
3998  {
3999  init_var_from_num(num1, &arg1);
4000  if (cmp_var(&arg1, &const_one) == 0)
4002  }
4003 
4004  /*
4005  * For any value of x, if y is [-]0, 1.0 shall be returned.
4006  */
4007  if (sign2 == 0)
4009 
4010  /*
4011  * For any odd integer value of y > 0, if x is [-]0, [-]0 shall be
4012  * returned. For y > 0 and not an odd integer, if x is [-]0, +0 shall
4013  * be returned. (Since we don't deal in minus zero, we need not
4014  * distinguish these two cases.)
4015  */
4016  if (sign1 == 0 && sign2 > 0)
4018 
4019  /*
4020  * If x is -1, and y is [-]Inf, 1.0 shall be returned.
4021  *
4022  * For |x| < 1, if y is -Inf, +Inf shall be returned.
4023  *
4024  * For |x| > 1, if y is -Inf, +0 shall be returned.
4025  *
4026  * For |x| < 1, if y is +Inf, +0 shall be returned.
4027  *
4028  * For |x| > 1, if y is +Inf, +Inf shall be returned.
4029  */
4030  if (NUMERIC_IS_INF(num2))
4031  {
4032  bool abs_x_gt_one;
4033 
4034  if (NUMERIC_IS_SPECIAL(num1))
4035  abs_x_gt_one = true; /* x is either Inf or -Inf */
4036  else
4037  {
4038  init_var_from_num(num1, &arg1);
4039  if (cmp_var(&arg1, &const_minus_one) == 0)
4041  arg1.sign = NUMERIC_POS; /* now arg1 = abs(x) */
4042  abs_x_gt_one = (cmp_var(&arg1, &const_one) > 0);
4043  }
4044  if (abs_x_gt_one == (sign2 > 0))
4046  else
4048  }
4049 
4050  /*
4051  * For y < 0, if x is +Inf, +0 shall be returned.
4052  *
4053  * For y > 0, if x is +Inf, +Inf shall be returned.
4054  */
4055  if (NUMERIC_IS_PINF(num1))
4056  {
4057  if (sign2 > 0)
4059  else
4061  }
4062 
4063  Assert(NUMERIC_IS_NINF(num1));
4064 
4065  /*
4066  * For y an odd integer < 0, if x is -Inf, -0 shall be returned. For
4067  * y < 0 and not an odd integer, if x is -Inf, +0 shall be returned.
4068  * (Again, we need not distinguish these two cases.)
4069  */
4070  if (sign2 < 0)
4072 
4073  /*
4074  * For y an odd integer > 0, if x is -Inf, -Inf shall be returned. For
4075  * y > 0 and not an odd integer, if x is -Inf, +Inf shall be returned.
4076  */
4077  init_var_from_num(num2, &arg2);
4078  if (arg2.ndigits > 0 && arg2.ndigits == arg2.weight + 1 &&
4079  (arg2.digits[arg2.ndigits - 1] & 1))
4081  else
4083  }
4084 
4085  /*
4086  * The SQL spec requires that we emit a particular SQLSTATE error code for
4087  * certain error conditions. Specifically, we don't return a
4088  * divide-by-zero error code for 0 ^ -1. Raising a negative number to a
4089  * non-integer power must produce the same error code, but that case is
4090  * handled in power_var().
4091  */
4092  sign1 = numeric_sign_internal(num1);
4093  sign2 = numeric_sign_internal(num2);
4094 
4095  if (sign1 == 0 && sign2 < 0)
4096  ereport(ERROR,
4097  (errcode(ERRCODE_INVALID_ARGUMENT_FOR_POWER_FUNCTION),
4098  errmsg("zero raised to a negative power is undefined")));
4099 
4100  /*
4101  * Initialize things
4102  */
4103  init_var(&result);
4104  init_var_from_num(num1, &arg1);
4105  init_var_from_num(num2, &arg2);
4106 
4107  /*
4108  * Call power_var() to compute and return the result; note it handles
4109  * scale selection itself.
4110  */
4111  power_var(&arg1, &arg2, &result);
4112 
4113  res = make_result(&result);
4114 
4115  free_var(&result);
4116 
4118 }
static bool numeric_is_integral(Numeric num)
Definition: numeric.c:873
static void power_var(const NumericVar *base, const NumericVar *exp, NumericVar *result)
Definition: numeric.c:11151
static const NumericVar const_minus_one
Definition: numeric.c:429

References Assert, cmp_var(), const_minus_one, const_nan, const_ninf, const_one, const_pinf, const_zero, NumericVar::digits, ereport, errcode(), errmsg(), ERROR, free_var(), init_var, init_var_from_num(), make_result(), NumericVar::ndigits, NUMERIC_IS_INF, numeric_is_integral(), NUMERIC_IS_NAN, NUMERIC_IS_NINF, NUMERIC_IS_PINF, NUMERIC_IS_SPECIAL, NUMERIC_POS, numeric_sign_internal(), PG_GETARG_NUMERIC, PG_RETURN_NUMERIC, power_var(), res, NumericVar::sign, and NumericVar::weight.

Referenced by numeric_to_char(), and numeric_to_number().

◆ numeric_recv()

Datum numeric_recv ( PG_FUNCTION_ARGS  )

Definition at line 1078 of file numeric.c.

1079 {
1081 
1082 #ifdef NOT_USED
1083  Oid typelem = PG_GETARG_OID(1);
1084 #endif
1085  int32 typmod = PG_GETARG_INT32(2);
1086  NumericVar value;
1087  Numeric res;
1088  int len,
1089  i;
1090 
1091  init_var(&value);
1092 
1093  len = (uint16) pq_getmsgint(buf, sizeof(uint16));
1094 
1095  alloc_var(&value, len);
1096 
1097  value.weight = (int16) pq_getmsgint(buf, sizeof(int16));
1098  /* we allow any int16 for weight --- OK? */
1099 
1100  value.sign = (uint16) pq_getmsgint(buf, sizeof(uint16));
1101  if (!(value.sign == NUMERIC_POS ||
1102  value.sign == NUMERIC_NEG ||
1103  value.sign == NUMERIC_NAN ||
1104  value.sign == NUMERIC_PINF ||
1105  value.sign == NUMERIC_NINF))
1106  ereport(ERROR,
1107  (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
1108  errmsg("invalid sign in external \"numeric\" value")));
1109 
1110  value.dscale = (uint16) pq_getmsgint(buf, sizeof(uint16));
1111  if ((value.dscale & NUMERIC_DSCALE_MASK) != value.dscale)
1112  ereport(ERROR,
1113  (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
1114  errmsg("invalid scale in external \"numeric\" value")));
1115 
1116  for (i = 0; i < len; i++)
1117  {
1118  NumericDigit d = pq_getmsgint(buf, sizeof(NumericDigit));
1119 
1120  if (d < 0 || d >= NBASE)
1121  ereport(ERROR,
1122  (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
1123  errmsg("invalid digit in external \"numeric\" value")));
1124  value.digits[i] = d;
1125  }
1126 
1127  /*
1128  * If the given dscale would hide any digits, truncate those digits away.
1129  * We could alternatively throw an error, but that would take a bunch of
1130  * extra code (about as much as trunc_var involves), and it might cause
1131  * client compatibility issues. Be careful not to apply trunc_var to
1132  * special values, as it could do the wrong thing; we don't need it
1133  * anyway, since make_result will ignore all but the sign field.
1134  *
1135  * After doing that, be sure to check the typmod restriction.
1136  */
1137  if (value.sign == NUMERIC_POS ||
1138  value.sign == NUMERIC_NEG)
1139  {
1140  trunc_var(&value, value.dscale);
1141 
1142  (void) apply_typmod(&value, typmod, NULL);
1143 
1144  res = make_result(&value);
1145  }
1146  else
1147  {
1148  /* apply_typmod_special wants us to make the Numeric first */
1149  res = make_result(&value);
1150 
1151  (void) apply_typmod_special(res, typmod, NULL);
1152  }
1153 
1154  free_var(&value);
1155 
1157 }
StringInfoData * StringInfo
Definition: stringinfo.h:54

References alloc_var(), apply_typmod(), apply_typmod_special(), buf, ereport, errcode(), errmsg(), ERROR, free_var(), i, init_var, len, make_result(), NBASE, NUMERIC_DSCALE_MASK, NUMERIC_NAN, NUMERIC_NEG, NUMERIC_NINF, NUMERIC_PINF, NUMERIC_POS, PG_GETARG_INT32, PG_GETARG_OID, PG_GETARG_POINTER, PG_RETURN_NUMERIC, pq_getmsgint(), res, trunc_var(), and value.

◆ numeric_round()

Datum numeric_round ( PG_FUNCTION_ARGS  )

Definition at line 1543 of file numeric.c.

1544 {
1545  Numeric num = PG_GETARG_NUMERIC(0);
1547  Numeric res;
1548  NumericVar arg;
1549 
1550  /*
1551  * Handle NaN and infinities
1552  */
1553  if (NUMERIC_IS_SPECIAL(num))
1555 
1556  /*
1557  * Limit the scale value to avoid possible overflow in calculations.
1558  *
1559  * These limits are based on the maximum number of digits a Numeric value
1560  * can have before and after the decimal point, but we must allow for one
1561  * extra digit before the decimal point, in case the most significant
1562  * digit rounds up; we must check if that causes Numeric overflow.
1563  */
1564  scale = Max(scale, -(NUMERIC_WEIGHT_MAX + 1) * DEC_DIGITS - 1);
1566 
1567  /*
1568  * Unpack the argument and round it at the proper digit position
1569  */
1570  init_var(&arg);
1571  set_var_from_num(num, &arg);
1572 
1573  round_var(&arg, scale);
1574 
1575  /* We don't allow negative output dscale */
1576  if (scale < 0)
1577  arg.dscale = 0;
1578 
1579  /*
1580  * Return the rounded result
1581  */
1582  res = make_result(&arg);
1583 
1584  free_var(&arg);
1586 }
#define NUMERIC_WEIGHT_MAX
Definition: numeric.c:257

References arg, DEC_DIGITS, duplicate_numeric(), free_var(), init_var, make_result(), Max, Min, NUMERIC_DSCALE_MAX, NUMERIC_IS_SPECIAL, NUMERIC_WEIGHT_MAX, PG_GETARG_INT32, PG_GETARG_NUMERIC, PG_RETURN_NUMERIC, res, round_var(), scale, and set_var_from_num().

Referenced by cash_numeric(), numeric_to_char(), timestamp_part_common(), and timestamptz_part_common().

◆ numeric_scale()

Datum numeric_scale ( PG_FUNCTION_ARGS  )

Definition at line 4126 of file numeric.c.

4127 {
4128  Numeric num = PG_GETARG_NUMERIC(0);
4129 
4130  if (NUMERIC_IS_SPECIAL(num))
4131  PG_RETURN_NULL();
4132 
4134 }

References NUMERIC_DSCALE, NUMERIC_IS_SPECIAL, PG_GETARG_NUMERIC, PG_RETURN_INT32, and PG_RETURN_NULL.

Referenced by cash_numeric(), and numeric_cash().

◆ numeric_send()

Datum numeric_send ( PG_FUNCTION_ARGS  )

Definition at line 1163 of file numeric.c.

1164 {
1165  Numeric num = PG_GETARG_NUMERIC(0);
1166  NumericVar x;
1168  int i;
1169 
1170  init_var_from_num(num, &x);
1171 
1172  pq_begintypsend(&buf);
1173 
1174  pq_sendint16(&buf, x.ndigits);
1175  pq_sendint16(&buf, x.weight);
1176  pq_sendint16(&buf, x.sign);
1177  pq_sendint16(&buf, x.dscale);
1178  for (i = 0; i < x.ndigits; i++)
1179  pq_sendint16(&buf, x.digits[i]);
1180 
1182 }
static void pq_sendint16(StringInfo buf, uint16 i)
Definition: pqformat.h:136

References buf, i, init_var_from_num(), PG_GETARG_NUMERIC, PG_RETURN_BYTEA_P, pq_begintypsend(), pq_endtypsend(), pq_sendint16(), and x.

◆ numeric_serialize()

Datum numeric_serialize ( PG_FUNCTION_ARGS  )

Definition at line 5318 of file numeric.c.

5319 {
5322  bytea *result;
5323  NumericVar tmp_var;
5324 
5325  /* Ensure we disallow calling when not in aggregate context */
5326  if (!AggCheckCallContext(fcinfo, NULL))
5327  elog(ERROR, "aggregate function called in non-aggregate context");
5328 
5330 
5331  init_var(&tmp_var);
5332 
5333  pq_begintypsend(&buf);
5334 
5335  /* N */
5336  pq_sendint64(&buf, state->N);
5337 
5338  /* sumX */
5339  accum_sum_final(&state->sumX, &tmp_var);
5340  numericvar_serialize(&buf, &tmp_var);
5341 
5342  /* sumX2 */
5343  accum_sum_final(&state->sumX2, &tmp_var);
5344  numericvar_serialize(&buf, &tmp_var);
5345 
5346  /* maxScale */
5347  pq_sendint32(&buf, state->maxScale);
5348 
5349  /* maxScaleCount */
5350  pq_sendint64(&buf, state->maxScaleCount);
5351 
5352  /* NaNcount */
5353  pq_sendint64(&buf, state->NaNcount);
5354 
5355  /* pInfcount */
5356  pq_sendint64(&buf, state->pInfcount);
5357 
5358  /* nInfcount */
5359  pq_sendint64(&buf, state->nInfcount);
5360 
5361  result = pq_endtypsend(&buf);
5362 
5363  free_var(&tmp_var);
5364 
5365  PG_RETURN_BYTEA_P(result);
5366 }

References accum_sum_final(), AggCheckCallContext(), buf, elog, ERROR, free_var(), init_var, numericvar_serialize(), PG_GETARG_POINTER, PG_RETURN_BYTEA_P, pq_begintypsend(), pq_endtypsend(), pq_sendint32(), and pq_sendint64().

◆ numeric_sign()

Datum numeric_sign ( PG_FUNCTION_ARGS  )

Definition at line 1510 of file numeric.c.

1511 {
1512  Numeric num = PG_GETARG_NUMERIC(0);
1513 
1514  /*
1515  * Handle NaN (infinities can be handled normally)
1516  */
1517  if (NUMERIC_IS_NAN(num))
1519 
1520  switch (numeric_sign_internal(num))
1521  {
1522  case 0:
1524  case 1:
1526  case -1:
1528  }
1529 
1530  Assert(false);
1531  return (Datum) 0;
1532 }

References Assert, const_minus_one, const_nan, const_one, const_zero, make_result(), NUMERIC_IS_NAN, numeric_sign_internal(), PG_GETARG_NUMERIC, and PG_RETURN_NUMERIC.

◆ numeric_sign_internal()

static int numeric_sign_internal ( Numeric  num)
static

Definition at line 1478 of file numeric.c.

1479 {
1480  if (NUMERIC_IS_SPECIAL(num))
1481  {
1482  Assert(!NUMERIC_IS_NAN(num));
1483  /* Must be Inf or -Inf */
1484  if (NUMERIC_IS_PINF(num))
1485  return 1;
1486  else
1487  return -1;
1488  }
1489 
1490  /*
1491  * The packed format is known to be totally zero digit trimmed always. So
1492  * once we've eliminated specials, we can identify a zero by the fact that
1493  * there are no digits at all.
1494  */
1495  else if (NUMERIC_NDIGITS(num) == 0)
1496  return 0;
1497  else if (NUMERIC_SIGN(num) == NUMERIC_NEG)
1498  return -1;
1499  else
1500  return 1;
1501 }

References Assert, NUMERIC_IS_NAN, NUMERIC_IS_PINF, NUMERIC_IS_SPECIAL, NUMERIC_NDIGITS, NUMERIC_NEG, and NUMERIC_SIGN.

Referenced by numeric_div_opt_error(), numeric_div_trunc(), numeric_log(), numeric_mod_opt_error(), numeric_mul_opt_error(), numeric_power(), and numeric_sign().

◆ numeric_smaller()

Datum numeric_smaller ( PG_FUNCTION_ARGS  )

Definition at line 3474 of file numeric.c.

3475 {
3476  Numeric num1 = PG_GETARG_NUMERIC(0);
3477  Numeric num2 = PG_GETARG_NUMERIC(1);
3478 
3479  /*
3480  * Use cmp_numerics so that this will agree with the comparison operators,
3481  * particularly as regards comparisons involving NaN.
3482  */
3483  if (cmp_numerics(num1, num2) < 0)
3484  PG_RETURN_NUMERIC(num1);
3485  else
3486  PG_RETURN_NUMERIC(num2);
3487 }

References cmp_numerics(), PG_GETARG_NUMERIC, and PG_RETURN_NUMERIC.

◆ numeric_sortsupport()

Datum numeric_sortsupport ( PG_FUNCTION_ARGS  )

Definition at line 2009 of file numeric.c.

2010 {
2012 
2013  ssup->comparator = numeric_fast_cmp;
2014 
2015  if (ssup->abbreviate)
2016  {
2017  NumericSortSupport *nss;
2018  MemoryContext oldcontext = MemoryContextSwitchTo(ssup->ssup_cxt);
2019 
2020  nss = palloc(sizeof(NumericSortSupport));
2021 
2022  /*
2023  * palloc a buffer for handling unaligned packed values in addition to
2024  * the support struct
2025  */
2026  nss->buf = palloc(VARATT_SHORT_MAX + VARHDRSZ + 1);
2027 
2028  nss->input_count = 0;
2029  nss->estimating = true;
2030  initHyperLogLog(&nss->abbr_card, 10);
2031 
2032  ssup->ssup_extra = nss;
2033 
2034  ssup->abbrev_full_comparator = ssup->comparator;
2038 
2039  MemoryContextSwitchTo(oldcontext);
2040  }
2041 
2042  PG_RETURN_VOID();
2043 }
static bool numeric_abbrev_abort(int memtupcount, SortSupport ssup)
Definition: numeric.c:2112
static Datum numeric_abbrev_convert(Datum original_datum, SortSupport ssup)
Definition: numeric.c:2050
static int numeric_fast_cmp(Datum x, Datum y, SortSupport ssup)
Definition: numeric.c:2185
static int numeric_cmp_abbrev(Datum x, Datum y, SortSupport ssup)
Definition: numeric.c:2207
#define PG_RETURN_VOID()
Definition: fmgr.h:349
void initHyperLogLog(hyperLogLogState *cState, uint8 bwidth)
Definition: hyperloglog.c:66
struct SortSupportData * SortSupport
Definition: sortsupport.h:58
int(* comparator)(Datum x, Datum y, SortSupport ssup)
Definition: sortsupport.h:106
Datum(* abbrev_converter)(Datum original, SortSupport ssup)
Definition: sortsupport.h:172
MemoryContext ssup_cxt
Definition: sortsupport.h:66
int(* abbrev_full_comparator)(Datum x, Datum y, SortSupport ssup)
Definition: sortsupport.h:191
bool(* abbrev_abort)(int memtupcount, SortSupport ssup)
Definition: sortsupport.h:182

References NumericSortSupport::abbr_card, SortSupportData::abbrev_abort, SortSupportData::abbrev_converter, SortSupportData::abbrev_full_comparator, SortSupportData::abbreviate, NumericSortSupport::buf, SortSupportData::comparator, NumericSortSupport::estimating, initHyperLogLog(), NumericSortSupport::input_count, MemoryContextSwitchTo(), numeric_abbrev_abort(), numeric_abbrev_convert(), numeric_cmp_abbrev(), numeric_fast_cmp(), palloc(), PG_GETARG_POINTER, PG_RETURN_VOID, SortSupportData::ssup_cxt, SortSupportData::ssup_extra, VARATT_SHORT_MAX, and VARHDRSZ.

◆ numeric_sqrt()

Datum numeric_sqrt ( PG_FUNCTION_ARGS  )

Definition at line 3680 of file numeric.c.

3681 {
3682  Numeric num = PG_GETARG_NUMERIC(0);
3683  Numeric res;
3684  NumericVar arg;
3685  NumericVar result;
3686  int sweight;
3687  int rscale;
3688 
3689  /*
3690  * Handle NaN and infinities
3691  */
3692  if (NUMERIC_IS_SPECIAL(num))
3693  {
3694  /* error should match that in sqrt_var() */
3695  if (NUMERIC_IS_NINF(num))
3696  ereport(ERROR,
3697  (errcode(ERRCODE_INVALID_ARGUMENT_FOR_POWER_FUNCTION),
3698  errmsg("cannot take square root of a negative number")));
3699  /* For NAN or PINF, just duplicate the input */
3701  }
3702 
3703  /*
3704  * Unpack the argument and determine the result scale. We choose a scale
3705  * to give at least NUMERIC_MIN_SIG_DIGITS significant digits; but in any
3706  * case not less than the input's dscale.
3707  */
3708  init_var_from_num(num, &arg);
3709 
3710  init_var(&result);
3711 
3712  /*
3713  * Assume the input was normalized, so arg.weight is accurate. The result
3714  * then has at least sweight = floor(arg.weight * DEC_DIGITS / 2 + 1)
3715  * digits before the decimal point. When DEC_DIGITS is even, we can save
3716  * a few cycles, since the division is exact and there is no need to round
3717  * towards negative infinity.
3718  */
3719 #if DEC_DIGITS == ((DEC_DIGITS / 2) * 2)
3720  sweight = arg.weight * DEC_DIGITS / 2 + 1;
3721 #else
3722  if (arg.weight >= 0)
3723  sweight = arg.weight * DEC_DIGITS / 2 + 1;
3724  else
3725  sweight = 1 - (1 - arg.weight * DEC_DIGITS) / 2;
3726 #endif
3727 
3728  rscale = NUMERIC_MIN_SIG_DIGITS - sweight;
3729  rscale = Max(rscale, arg.dscale);
3730  rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
3731  rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
3732 
3733  /*
3734  * Let sqrt_var() do the calculation and return the result.
3735  */
3736  sqrt_var(&arg, &result, rscale);
3737 
3738  res = make_result(&result);
3739 
3740  free_var(&result);
3741 
3743 }

References arg, DEC_DIGITS, duplicate_numeric(), ereport, errcode(), errmsg(), ERROR, free_var(), init_var, init_var_from_num(), make_result(), Max, Min, NUMERIC_IS_NINF, NUMERIC_IS_SPECIAL, NUMERIC_MAX_DISPLAY_SCALE, NUMERIC_MIN_DISPLAY_SCALE, NUMERIC_MIN_SIG_DIGITS, PG_GETARG_NUMERIC, PG_RETURN_NUMERIC, res, and sqrt_var().

◆ numeric_stddev_internal()

static Numeric numeric_stddev_internal ( NumericAggState state,
bool  variance,
bool  sample,
bool is_null 
)
static

Definition at line 6210 of file numeric.c.

6213 {
6214  Numeric res;
6215  NumericVar vN,
6216  vsumX,
6217  vsumX2,
6218  vNminus1;
6219  int64 totCount;
6220  int rscale;
6221 
6222  /*
6223  * Sample stddev and variance are undefined when N <= 1; population stddev
6224  * is undefined when N == 0. Return NULL in either case (note that NaNs
6225  * and infinities count as normal inputs for this purpose).
6226  */
6227  if (state == NULL || (totCount = NA_TOTAL_COUNT(state)) == 0)
6228  {
6229  *is_null = true;
6230  return NULL;
6231  }
6232 
6233  if (sample && totCount <= 1)
6234  {
6235  *is_null = true;
6236  return NULL;
6237  }
6238 
6239  *is_null = false;
6240 
6241  /*
6242  * Deal with NaN and infinity cases. By analogy to the behavior of the
6243  * float8 functions, any infinity input produces NaN output.
6244  */
6245  if (state->NaNcount > 0 || state->pInfcount > 0 || state->nInfcount > 0)
6246  return make_result(&const_nan);
6247 
6248  /* OK, normal calculation applies */
6249  init_var(&vN);
6250  init_var(&vsumX);
6251  init_var(&vsumX2);
6252 
6253  int64_to_numericvar(state->N, &vN);
6254  accum_sum_final(&(state->sumX), &vsumX);
6255  accum_sum_final(&(state->sumX2), &vsumX2);
6256 
6257  init_var(&vNminus1);
6258  sub_var(&vN, &const_one, &vNminus1);
6259 
6260  /* compute rscale for mul_var calls */
6261  rscale = vsumX.dscale * 2;
6262 
6263  mul_var(&vsumX, &vsumX, &vsumX, rscale); /* vsumX = sumX * sumX */
6264  mul_var(&vN, &vsumX2, &vsumX2, rscale); /* vsumX2 = N * sumX2 */
6265  sub_var(&vsumX2, &vsumX, &vsumX2); /* N * sumX2 - sumX * sumX */
6266 
6267  if (cmp_var(&vsumX2, &const_zero) <= 0)
6268  {
6269  /* Watch out for roundoff error producing a negative numerator */
6271  }
6272  else
6273  {
6274  if (sample)
6275  mul_var(&vN, &vNminus1, &vNminus1, 0); /* N * (N - 1) */
6276  else
6277  mul_var(&vN, &vN, &vNminus1, 0); /* N * N */
6278  rscale = select_div_scale(&vsumX2, &vNminus1);
6279  div_var(&vsumX2, &vNminus1, &vsumX, rscale, true); /* variance */
6280  if (!variance)
6281  sqrt_var(&vsumX, &vsumX, rscale); /* stddev */
6282 
6283  res = make_result(&vsumX);
6284  }
6285 
6286  free_var(&vNminus1);
6287  free_var(&vsumX);
6288  free_var(&vsumX2);
6289 
6290  return res;
6291 }

References accum_sum_final(), cmp_var(), const_nan, const_one, const_zero, div_var(), NumericVar::dscale, free_var(), init_var, int64_to_numericvar(), make_result(), mul_var(), NA_TOTAL_COUNT, res, select_div_scale(), sqrt_var(), and sub_var().

Referenced by numeric_stddev_pop(), numeric_stddev_samp(), numeric_var_pop(), and numeric_var_samp().

◆ numeric_stddev_pop()

Datum numeric_stddev_pop ( PG_FUNCTION_ARGS  )

Definition at line 6345 of file numeric.c.

6346 {
6348  Numeric res;
6349  bool is_null;
6350 
6351  state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
6352 
6353  res = numeric_stddev_internal(state, false, false, &is_null);
6354 
6355  if (is_null)
6356  PG_RETURN_NULL();
6357  else
6359 }
static Numeric numeric_stddev_internal(NumericAggState *state, bool variance, bool sample, bool *is_null)
Definition: numeric.c:6210

References numeric_stddev_internal(), PG_ARGISNULL, PG_GETARG_POINTER, PG_RETURN_NULL, PG_RETURN_NUMERIC, and res.

Referenced by numeric_poly_stddev_pop().

◆ numeric_stddev_samp()

Datum numeric_stddev_samp ( PG_FUNCTION_ARGS  )

Definition at line 6311 of file numeric.c.

6312 {
6314  Numeric res;
6315  bool is_null;
6316 
6317  state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
6318 
6319  res = numeric_stddev_internal(state, false, true, &is_null);
6320 
6321  if (is_null)
6322  PG_RETURN_NULL();
6323  else
6325 }

References numeric_stddev_internal(), PG_ARGISNULL, PG_GETARG_POINTER, PG_RETURN_NULL, PG_RETURN_NUMERIC, and res.

Referenced by numeric_poly_stddev_samp().

◆ numeric_sub()

Datum numeric_sub ( PG_FUNCTION_ARGS  )

Definition at line 2929 of file numeric.c.

2930 {
2931  Numeric num1 = PG_GETARG_NUMERIC(0);
2932  Numeric num2 = PG_GETARG_NUMERIC(1);
2933  Numeric res;
2934 
2935  res = numeric_sub_opt_error(num1, num2, NULL);
2936 
2938 }
Numeric numeric_sub_opt_error(Numeric num1, Numeric num2, bool *have_error)
Definition: numeric.c:2949

References numeric_sub_opt_error(), PG_GETARG_NUMERIC, PG_RETURN_NUMERIC, and res.

Referenced by brin_minmax_multi_distance_numeric(), gbt_numeric_penalty(), numeric_half_rounded(), numrange_subdiff(), and pg_lsn_mii().

◆ numeric_sub_opt_error()

Numeric numeric_sub_opt_error ( Numeric  num1,
Numeric  num2,
bool have_error 
)

Definition at line 2949 of file numeric.c.

2950 {
2951  NumericVar arg1;
2952  NumericVar arg2;
2953  NumericVar result;
2954  Numeric res;
2955 
2956  /*
2957  * Handle NaN and infinities
2958  */
2959  if (NUMERIC_IS_SPECIAL(num1) || NUMERIC_IS_SPECIAL(num2))
2960  {
2961  if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
2962  return make_result(&const_nan);
2963  if (NUMERIC_IS_PINF(num1))
2964  {
2965  if (NUMERIC_IS_PINF(num2))
2966  return make_result(&const_nan); /* Inf - Inf */
2967  else
2968  return make_result(&const_pinf);
2969  }
2970  if (NUMERIC_IS_NINF(num1))
2971  {
2972  if (NUMERIC_IS_NINF(num2))
2973  return make_result(&const_nan); /* -Inf - -Inf */
2974  else
2975  return make_result(&const_ninf);
2976  }
2977  /* by here, num1 must be finite, so num2 is not */
2978  if (NUMERIC_IS_PINF(num2))
2979  return make_result(&const_ninf);
2980  Assert(NUMERIC_IS_NINF(num2));
2981  return make_result(&const_pinf);
2982  }
2983 
2984  /*
2985  * Unpack the values, let sub_var() compute the result and return it.
2986  */
2987  init_var_from_num(num1, &arg1);
2988  init_var_from_num(num2, &arg2);
2989 
2990  init_var(&result);
2991  sub_var(&arg1, &arg2, &result);
2992 
2993  res = make_result_opt_error(&result, have_error);
2994 
2995  free_var(&result);
2996 
2997  return res;
2998 }

References Assert, const_nan, const_ninf, const_pinf, free_var(), init_var, init_var_from_num(), make_result(), make_result_opt_error(), NUMERIC_IS_NAN, NUMERIC_IS_NINF, NUMERIC_IS_PINF, NUMERIC_IS_SPECIAL, res, and sub_var().

Referenced by executeItemOptUnwrapTarget(), numeric_sub(), timestamp_part_common(), and timestamptz_part_common().

◆ numeric_sum()

Datum numeric_sum ( PG_FUNCTION_ARGS  )

Definition at line 6167 of file numeric.c.

6168 {
6170  NumericVar sumX_var;
6171  Numeric result;
6172 
6173  state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
6174 
6175  /* If there were no non-null inputs, return NULL */
6176  if (state == NULL || NA_TOTAL_COUNT(state) == 0)
6177  PG_RETURN_NULL();
6178 
6179  if (state->NaNcount > 0) /* there was at least one NaN input */
6181 
6182  /* adding plus and minus infinities gives NaN */
6183  if (state->pInfcount > 0 && state->nInfcount > 0)
6185  if (state->pInfcount > 0)
6187  if (state->nInfcount > 0)
6189 
6190  init_var(&sumX_var);
6191  accum_sum_final(&state->sumX, &sumX_var);
6192  result = make_result(&sumX_var);
6193  free_var(&sumX_var);
6194 
6195  PG_RETURN_NUMERIC(result);
6196 }

References accum_sum_final(), const_nan, const_ninf, const_pinf, free_var(), init_var, make_result(), NA_TOTAL_COUNT, PG_ARGISNULL, PG_GETARG_POINTER, PG_RETURN_NULL, and PG_RETURN_NUMERIC.

Referenced by numeric_poly_sum().

◆ numeric_support()

Datum numeric_support ( PG_FUNCTION_ARGS  )

Definition at line 1196 of file numeric.c.

1197 {
1198  Node *rawreq = (Node *) PG_GETARG_POINTER(0);
1199  Node *ret = NULL;
1200 
1201  if (IsA(rawreq, SupportRequestSimplify))
1202  {
1204  FuncExpr *expr = req->fcall;
1205  Node *typmod;
1206 
1207  Assert(list_length(expr->args) >= 2);
1208 
1209  typmod = (Node *) lsecond(expr->args);
1210 
1211  if (IsA(typmod, Const) && !((Const *) typmod)->constisnull)
1212  {
1213  Node *source = (Node *) linitial(expr->args);
1214  int32 old_typmod = exprTypmod(source);
1215  int32 new_typmod = DatumGetInt32(((Const *) typmod)->constvalue);
1216  int32 old_scale = numeric_typmod_scale(old_typmod);
1217  int32 new_scale = numeric_typmod_scale(new_typmod);
1218  int32 old_precision = numeric_typmod_precision(old_typmod);
1219  int32 new_precision = numeric_typmod_precision(new_typmod);
1220 
1221  /*
1222  * If new_typmod is invalid, the destination is unconstrained;
1223  * that's always OK. If old_typmod is valid, the source is
1224  * constrained, and we're OK if the scale is unchanged and the
1225  * precision is not decreasing. See further notes in function
1226  * header comment.
1227  */
1228  if (!is_valid_numeric_typmod(new_typmod) ||
1229  (is_valid_numeric_typmod(old_typmod) &&
1230  new_scale == old_scale && new_precision >= old_precision))
1231  ret = relabel_to_typmod(source, new_typmod);
1232  }
1233  }
1234 
1235  PG_RETURN_POINTER(ret);
1236 }
int32 exprTypmod(const Node *expr)
Definition: nodeFuncs.c:298
Node * relabel_to_typmod(Node *expr, int32 typmod)
Definition: nodeFuncs.c:684
#define IsA(nodeptr, _type_)
Definition: nodes.h:158
static int list_length(const List *l)
Definition: pg_list.h:152
#define linitial(l)
Definition: pg_list.h:178
#define lsecond(l)
Definition: pg_list.h:183
static rewind_source * source
Definition: pg_rewind.c:89
static int32 DatumGetInt32(Datum X)
Definition: postgres.h:202
List * args
Definition: primnodes.h:768

References FuncExpr::args, Assert, DatumGetInt32(), exprTypmod(), SupportRequestSimplify::fcall, is_valid_numeric_typmod(), IsA, linitial, list_length(), lsecond, numeric_typmod_precision(), numeric_typmod_scale(), PG_GETARG_POINTER, PG_RETURN_POINTER, relabel_to_typmod(), and source.

◆ numeric_trim_scale()

Datum numeric_trim_scale ( PG_FUNCTION_ARGS  )

Definition at line 4211 of file numeric.c.

4212 {
4213  Numeric num = PG_GETARG_NUMERIC(0);
4214  Numeric res;
4215  NumericVar result;
4216 
4217  if (NUMERIC_IS_SPECIAL(num))
4219 
4220  init_var_from_num(num, &result);
4221  result.dscale = get_min_scale(&result);
4222  res = make_result(&result);
4223  free_var(&result);
4224 
4226 }

References NumericVar::dscale, duplicate_numeric(), free_var(), get_min_scale(), init_var_from_num(), make_result(), NUMERIC_IS_SPECIAL, PG_GETARG_NUMERIC, PG_RETURN_NUMERIC, and res.

◆ numeric_trunc()

Datum numeric_trunc ( PG_FUNCTION_ARGS  )

Definition at line 1597 of file numeric.c.

1598 {
1599  Numeric num = PG_GETARG_NUMERIC(0);
1601  Numeric res;
1602  NumericVar arg;
1603 
1604  /*
1605  * Handle NaN and infinities
1606  */
1607  if (NUMERIC_IS_SPECIAL(num))
1609 
1610  /*
1611  * Limit the scale value to avoid possible overflow in calculations.
1612  *
1613  * These limits are based on the maximum number of digits a Numeric value
1614  * can have before and after the decimal point.
1615  */
1618 
1619  /*
1620  * Unpack the argument and truncate it at the proper digit position
1621  */
1622  init_var(&arg);
1623  set_var_from_num(num, &arg);
1624 
1625  trunc_var(&arg, scale);
1626 
1627  /* We don't allow negative output dscale */
1628  if (scale < 0)
1629  arg.dscale = 0;
1630 
1631  /*
1632  * Return the truncated result
1633  */
1634  res = make_result(&arg);
1635 
1636  free_var(&arg);
1638 }

References arg, DEC_DIGITS, duplicate_numeric(), free_var(), init_var, make_result(), Max, Min, NUMERIC_DSCALE_MAX, NUMERIC_IS_SPECIAL, NUMERIC_WEIGHT_MAX, PG_GETARG_INT32, PG_GETARG_NUMERIC, PG_RETURN_NUMERIC, res, scale, set_var_from_num(), and trunc_var().

Referenced by getArrayIndex().

◆ numeric_typmod_precision()

static int numeric_typmod_precision ( int32  typmod)
inlinestatic

Definition at line 927 of file numeric.c.

928 {
929  return ((typmod - VARHDRSZ) >> 16) & 0xffff;
930 }

References VARHDRSZ.

Referenced by apply_typmod(), apply_typmod_special(), numeric(), numeric_maximum_size(), numeric_support(), and numerictypmodout().

◆ numeric_typmod_scale()

static int numeric_typmod_scale ( int32  typmod)
inlinestatic

Definition at line 942 of file numeric.c.

943 {
944  return (((typmod - VARHDRSZ) & 0x7ff) ^ 1024) - 1024;
945 }

References VARHDRSZ.

Referenced by apply_typmod(), apply_typmod_special(), numeric(), numeric_support(), and numerictypmodout().

◆ numeric_uminus()

Datum numeric_uminus ( PG_FUNCTION_ARGS  )

Definition at line 1420 of file numeric.c.

1421 {
1422  Numeric num = PG_GETARG_NUMERIC(0);
1423  Numeric res;
1424 
1425  /*
1426  * Do it the easy way directly on the packed format
1427  */
1428  res = duplicate_numeric(num);
1429 
1430  if (NUMERIC_IS_SPECIAL(num))
1431  {
1432  /* Flip the sign, if it's Inf or -Inf */
1433  if (!NUMERIC_IS_NAN(num))
1434  res->choice.n_short.n_header =
1436  }
1437 
1438  /*
1439  * The packed format is known to be totally zero digit trimmed always. So
1440  * once we've eliminated specials, we can identify a zero by the fact that
1441  * there are no digits at all. Do nothing to a zero.
1442  */
1443  else if (NUMERIC_NDIGITS(num) != 0)
1444  {
1445  /* Else, flip the sign */
1446  if (NUMERIC_IS_SHORT(num))
1447  res->choice.n_short.n_header =
1449  else if (NUMERIC_SIGN(num) == NUMERIC_POS)
1450  res->choice.n_long.n_sign_dscale =
1451  NUMERIC_NEG | NUMERIC_DSCALE(num);
1452  else
1453  res->choice.n_long.n_sign_dscale =
1454  NUMERIC_POS | NUMERIC_DSCALE(num);
1455  }
1456 
1458 }

References NumericData::choice, duplicate_numeric(), NumericShort::n_header, NumericChoice::n_short, NUMERIC_DSCALE, NUMERIC_INF_SIGN_MASK, NUMERIC_IS_NAN, NUMERIC_IS_SHORT, NUMERIC_IS_SPECIAL, NUMERIC_NDIGITS, NUMERIC_NEG, NUMERIC_POS, NUMERIC_SHORT_SIGN_MASK, NUMERIC_SIGN, PG_GETARG_NUMERIC, PG_RETURN_NUMERIC, and res.

Referenced by executeItemOptUnwrapTarget().

◆ numeric_uplus()

Datum numeric_uplus ( PG_FUNCTION_ARGS  )

Definition at line 1462 of file numeric.c.

1463 {
1464  Numeric num = PG_GETARG_NUMERIC(0);
1465 
1467 }

References duplicate_numeric(), PG_GETARG_NUMERIC, and PG_RETURN_NUMERIC.

Referenced by jsonb_agg_transfn_worker(), and jsonb_object_agg_transfn_worker().

◆ numeric_var_pop()

Datum numeric_var_pop ( PG_FUNCTION_ARGS  )

Definition at line 6328 of file numeric.c.

6329 {
6331  Numeric res;
6332  bool is_null;
6333 
6334  state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
6335 
6336  res = numeric_stddev_internal(state, true, false, &is_null);
6337 
6338  if (is_null)
6339  PG_RETURN_NULL();
6340  else
6342 }

References numeric_stddev_internal(), PG_ARGISNULL, PG_GETARG_POINTER, PG_RETURN_NULL, PG_RETURN_NUMERIC, and res.

Referenced by numeric_poly_var_pop().

◆ numeric_var_samp()

Datum numeric_var_samp ( PG_FUNCTION_ARGS  )

Definition at line 6294 of file numeric.c.

6295 {
6297  Numeric res;
6298  bool is_null;
6299 
6300  state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
6301 
6302  res = numeric_stddev_internal(state, true, true, &is_null);
6303 
6304  if (is_null)
6305  PG_RETURN_NULL();
6306  else
6308 }

References numeric_stddev_internal(), PG_ARGISNULL, PG_GETARG_POINTER, PG_RETURN_NULL, PG_RETURN_NUMERIC, and res.

Referenced by numeric_poly_var_samp().

◆ numerictypmodin()

Datum numerictypmodin ( PG_FUNCTION_ARGS  )

Definition at line 1324 of file numeric.c.

1325 {
1327  int32 *tl;
1328  int n;
1329  int32 typmod;
1330 
1331  tl = ArrayGetIntegerTypmods(ta, &n);
1332 
1333  if (n == 2)
1334  {
1335  if (tl[0] < 1 || tl[0] > NUMERIC_MAX_PRECISION)
1336  ereport(ERROR,
1337  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1338  errmsg("NUMERIC precision %d must be between 1 and %d",
1339  tl[0], NUMERIC_MAX_PRECISION)));
1340  if (tl[1] < NUMERIC_MIN_SCALE || tl[1] > NUMERIC_MAX_SCALE)
1341  ereport(ERROR,
1342  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1343  errmsg("NUMERIC scale %d must be between %d and %d",
1345  typmod = make_numeric_typmod(tl[0], tl[1]);
1346  }
1347  else if (n == 1)
1348  {
1349  if (tl[0] < 1 || tl[0] > NUMERIC_MAX_PRECISION)
1350  ereport(ERROR,
1351  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1352  errmsg("NUMERIC precision %d must be between 1 and %d",
1353  tl[0], NUMERIC_MAX_PRECISION)));
1354  /* scale defaults to zero */
1355  typmod = make_numeric_typmod(tl[0], 0);
1356  }
1357  else
1358  {
1359  ereport(ERROR,
1360  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1361  errmsg("invalid NUMERIC type modifier")));
1362  typmod = 0; /* keep compiler quiet */
1363  }
1364 
1365  PG_RETURN_INT32(typmod);
1366 }
int32 * ArrayGetIntegerTypmods(ArrayType *arr, int *n)
Definition: arrayutils.c:233
static int32 make_numeric_typmod(int precision, int scale)
Definition: numeric.c:907
#define NUMERIC_MIN_SCALE
Definition: numeric.h:34
#define NUMERIC_MAX_PRECISION
Definition: numeric.h:32
#define NUMERIC_MAX_SCALE
Definition: numeric.h:35

References ArrayGetIntegerTypmods(), ereport, errcode(), errmsg(), ERROR, make_numeric_typmod(), NUMERIC_MAX_PRECISION, NUMERIC_MAX_SCALE, NUMERIC_MIN_SCALE, PG_GETARG_ARRAYTYPE_P, and PG_RETURN_INT32.

Referenced by executeItemOptUnwrapTarget().

◆ numerictypmodout()

Datum numerictypmodout ( PG_FUNCTION_ARGS  )

Definition at line 1369 of file numeric.c.

1370 {
1371  int32 typmod = PG_GETARG_INT32(0);
1372  char *res = (char *) palloc(64);
1373 
1374  if (is_valid_numeric_typmod(typmod))
1375  snprintf(res, 64, "(%d,%d)",
1376  numeric_typmod_precision(typmod),
1377  numeric_typmod_scale(typmod));
1378  else
1379  *res = '\0';
1380 
1382 }

References is_valid_numeric_typmod(), numeric_typmod_precision(), numeric_typmod_scale(), palloc(), PG_GETARG_INT32, PG_RETURN_CSTRING, res, and snprintf.

◆ numericvar_deserialize()

static void numericvar_deserialize ( StringInfo  buf,
NumericVar var 
)
static

Definition at line 7744 of file numeric.c.

7745 {
7746  int len,
7747  i;
7748 
7749  len = pq_getmsgint(buf, sizeof(int32));
7750 
7751  alloc_var(var, len); /* sets var->ndigits */
7752 
7753  var->weight = pq_getmsgint(buf, sizeof(int32));
7754  var->sign = pq_getmsgint(buf, sizeof(int32));
7755  var->dscale = pq_getmsgint(buf, sizeof(int32));
7756  for (i = 0; i < len; i++)
7757  var->digits[i] = pq_getmsgint(buf, sizeof(int16));
7758 }

References alloc_var(), buf, NumericVar::digits, NumericVar::dscale, i, len, pq_getmsgint(), NumericVar::sign, and NumericVar::weight.

Referenced by int8_avg_deserialize(), numeric_avg_deserialize(), numeric_deserialize(), and numeric_poly_deserialize().

◆ numericvar_serialize()

static void numericvar_serialize ( StringInfo  buf,
const NumericVar var 
)
static

Definition at line 7728 of file numeric.c.

7729 {
7730  int i;
7731 
7732  pq_sendint32(buf, var->ndigits);
7733  pq_sendint32(buf, var->weight);
7734  pq_sendint32(buf, var->sign);
7735  pq_sendint32(buf, var->dscale);
7736  for (i = 0; i < var->ndigits; i++)
7737  pq_sendint16(buf, var->digits[i]);
7738 }

References buf, NumericVar::digits, NumericVar::dscale, i, NumericVar::ndigits, pq_sendint16(), pq_sendint32(), NumericVar::sign, and NumericVar::weight.

Referenced by int8_avg_serialize(), numeric_avg_serialize(), numeric_poly_serialize(), and numeric_serialize().

◆ numericvar_to_double_no_overflow()

static double numericvar_to_double_no_overflow ( const NumericVar var)
static

Definition at line 8345 of file numeric.c.

8346 {
8347  char *tmp;
8348  double val;
8349  char *endptr;
8350 
8351  tmp = get_str_from_var(var);
8352 
8353  /* unlike float8in, we ignore ERANGE from strtod */
8354  val = strtod(tmp, &endptr);
8355  if (*endptr != '\0')
8356  {
8357  /* shouldn't happen ... */
8358  ereport(ERROR,
8359  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
8360  errmsg("invalid input syntax for type %s: \"%s\"",
8361  "double precision", tmp)));
8362  }
8363 
8364  pfree(tmp);
8365 
8366  return val;
8367 }

References ereport, errcode(), errmsg(), ERROR, get_str_from_var(), pfree(), and val.

Referenced by exp_var(), numeric_exp(), numeric_float8_no_overflow(), and power_var().

◆ numericvar_to_int32()

static bool numericvar_to_int32 ( const NumericVar var,
int32 result 
)
static

Definition at line 4464 of file numeric.c.

4465 {
4466  int64 val;
4467 
4468  if (!numericvar_to_int64(var, &val))
4469  return false;
4470 
4472  return false;
4473 
4474  /* Down-convert to int4 */
4475  *result = (int32) val;
4476 
4477  return true;
4478 }
#define PG_INT32_MAX
Definition: c.h:589
#define PG_INT32_MIN
Definition: c.h:588

References numericvar_to_int64(), PG_INT32_MAX, PG_INT32_MIN, unlikely, and val.

Referenced by numeric_int4_opt_error(), and width_bucket_numeric().

◆ numericvar_to_int64()

static bool numericvar_to_int64 ( const NumericVar var,
int64 *  result 
)
static

Definition at line 8033 of file numeric.c.

8034 {
8036  int ndigits;
8037  int weight;
8038  int i;
8039  int64 val;
8040  bool neg;
8041  NumericVar rounded;
8042 
8043  /* Round to nearest integer */
8044  init_var(&rounded);
8045  set_var_from_var(var, &rounded);
8046  round_var(&rounded, 0);
8047 
8048  /* Check for zero input */
8049  strip_var(&rounded);
8050  ndigits = rounded.ndigits;
8051  if (ndigits == 0)
8052  {
8053  *result = 0;
8054  free_var(&rounded);
8055  return true;
8056  }
8057 
8058  /*
8059  * For input like 10000000000, we must treat stripped digits as real. So
8060  * the loop assumes there are weight+1 digits before the decimal point.
8061  */
8062  weight = rounded.weight;
8063  Assert(weight >= 0 && ndigits <= weight + 1);
8064 
8065  /*
8066  * Construct the result. To avoid issues with converting a value
8067  * corresponding to INT64_MIN (which can't be represented as a positive 64
8068  * bit two's complement integer), accumulate value as a negative number.
8069  */
8070  digits = rounded.digits;
8071  neg = (rounded.sign == NUMERIC_NEG);
8072  val = -digits[0];
8073  for (i = 1; i <= weight; i++)
8074  {
8076  {
8077  free_var(&rounded);
8078  return false;
8079  }
8080 
8081  if (i < ndigits)
8082  {
8084  {
8085  free_var(&rounded);
8086  return false;
8087  }
8088  }
8089  }
8090 
8091  free_var(&rounded);
8092 
8093  if (!neg)
8094  {
8095  if (unlikely(val == PG_INT64_MIN))
8096  return false;
8097  val = -val;
8098  }
8099  *result = val;
8100 
8101  return true;
8102 }
#define PG_INT64_MIN
Definition: c.h:591
static bool pg_sub_s64_overflow(int64 a, int64 b, int64 *result)
Definition: int.h:188

References Assert, NumericVar::digits, digits, free_var(), i, init_var, NBASE, NumericVar::ndigits, NUMERIC_NEG, PG_INT64_MIN, pg_mul_s64_overflow(), pg_sub_s64_overflow(), round_var(), set_var_from_var(), NumericVar::sign, strip_var(), unlikely, val, and NumericVar::weight.

Referenced by numeric_int2(), numeric_int8_opt_error(), numericvar_to_int32(), and power_var().

◆ numericvar_to_uint64()

static bool numericvar_to_uint64 ( const NumericVar var,
uint64 *  result 
)
static

Definition at line 8155 of file numeric.c.

8156 {
8158  int ndigits;
8159  int weight;
8160  int i;
8161  uint64 val;
8162  NumericVar rounded;
8163 
8164  /* Round to nearest integer */
8165  init_var(&rounded);
8166  set_var_from_var(var, &rounded);
8167  round_var(&rounded, 0);
8168 
8169  /* Check for zero input */
8170  strip_var(&rounded);
8171  ndigits = rounded.ndigits;
8172  if (ndigits == 0)
8173  {
8174  *result = 0;
8175  free_var(&rounded);
8176  return true;
8177  }
8178 
8179  /* Check for negative input */
8180  if (rounded.sign == NUMERIC_NEG)
8181  {
8182  free_var(&rounded);
8183  return false;
8184  }
8185 
8186  /*
8187  * For input like 10000000000, we must treat stripped digits as real. So
8188  * the loop assumes there are weight+1 digits before the decimal point.
8189  */
8190  weight = rounded.weight;
8191  Assert(weight >= 0 && ndigits <= weight + 1);
8192 
8193  /* Construct the result */
8194  digits = rounded.digits;
8195  val = digits[0];
8196  for (i = 1; i <= weight; i++)
8197  {
8199  {
8200  free_var(&rounded);
8201  return false;
8202  }
8203 
8204  if (i < ndigits)
8205  {
8207  {
8208  free_var(&rounded);
8209  return false;
8210  }
8211  }
8212  }
8213 
8214  free_var(&rounded);
8215 
8216  *result = val;
8217 
8218  return true;
8219 }
static bool pg_add_u64_overflow(uint64 a, uint64 b, uint64 *result)
Definition: int.h:380
static bool pg_mul_u64_overflow(uint64 a, uint64 b, uint64 *result)
Definition: int.h:414

References Assert, NumericVar::digits, digits, free_var(), i, init_var, NBASE, NumericVar::ndigits, NUMERIC_NEG, pg_add_u64_overflow(), pg_mul_u64_overflow(), round_var(), set_var_from_var(), NumericVar::sign, strip_var(), unlikely, val, and NumericVar::weight.

Referenced by numeric_pg_lsn().

◆ power_ten_int()

static void power_ten_int ( int  exp,
NumericVar result 
)
static

Definition at line 11518 of file numeric.c.

11519 {
11520  /* Construct the result directly, starting from 10^0 = 1 */
11521  set_var_from_var(&const_one, result);
11522 
11523  /* Scale needed to represent the result exactly */
11524  result->dscale = exp < 0 ? -exp : 0;
11525 
11526  /* Base-NBASE weight of result and remaining exponent */
11527  if (exp >= 0)
11528  result->weight = exp / DEC_DIGITS;
11529  else
11530  result->weight = (exp + 1) / DEC_DIGITS - 1;
11531 
11532  exp -= result->weight * DEC_DIGITS;
11533 
11534  /* Final adjustment of the result's single NBASE digit */
11535  while (exp-- > 0)
11536  result->digits[0] *= 10;
11537 }

References const_one, DEC_DIGITS, NumericVar::digits, NumericVar::dscale, set_var_from_var(), and NumericVar::weight.

Referenced by get_str_from_var_sci().

◆ power_var()

static void power_var ( const NumericVar base,
const NumericVar exp,
NumericVar result 
)
static

Definition at line 11151 of file numeric.c.

11152 {
11153  int res_sign;
11154  NumericVar abs_base;
11155  NumericVar ln_base;
11156  NumericVar ln_num;
11157  int ln_dweight;
11158  int rscale;
11159  int sig_digits;
11160  int local_rscale;
11161  double val;
11162 
11163  /* If exp can be represented as an integer, use power_var_int */
11164  if (exp->ndigits == 0 || exp->ndigits <= exp->weight + 1)
11165  {
11166  /* exact integer, but does it fit in int? */
11167  int64 expval64;
11168 
11169  if (numericvar_to_int64(exp, &expval64))
11170  {
11171  if (expval64 >= PG_INT32_MIN && expval64 <= PG_INT32_MAX)
11172  {
11173  /* Okay, use power_var_int */
11174  power_var_int(base, (int) expval64, exp->dscale, result);
11175  return;
11176  }
11177  }
11178  }
11179 
11180  /*
11181  * This avoids log(0) for cases of 0 raised to a non-integer. 0 ^ 0 is
11182  * handled by power_var_int().
11183  */
11184  if (cmp_var(base, &const_zero) == 0)
11185  {
11186  set_var_from_var(&const_zero, result);
11187  result->dscale = NUMERIC_MIN_SIG_DIGITS; /* no need to round */
11188  return;
11189  }
11190 
11191  init_var(&abs_base);
11192  init_var(&ln_base);
11193  init_var(&ln_num);
11194 
11195  /*
11196  * If base is negative, insist that exp be an integer. The result is then
11197  * positive if exp is even and negative if exp is odd.
11198  */
11199  if (base->sign == NUMERIC_NEG)
11200  {
11201  /*
11202  * Check that exp is an integer. This error code is defined by the
11203  * SQL standard, and matches other errors in numeric_power().
11204  */
11205  if (exp->ndigits > 0 && exp->ndigits > exp->weight + 1)
11206  ereport(ERROR,
11207  (errcode(ERRCODE_INVALID_ARGUMENT_FOR_POWER_FUNCTION),
11208  errmsg("a negative number raised to a non-integer power yields a complex result")));
11209 
11210  /* Test if exp is odd or even */
11211  if (exp->ndigits > 0 && exp->ndigits == exp->weight + 1 &&
11212  (exp->digits[exp->ndigits - 1] & 1))
11213  res_sign = NUMERIC_NEG;
11214  else
11215  res_sign = NUMERIC_POS;
11216 
11217  /* Then work with abs(base) below */
11218  set_var_from_var(base, &abs_base);
11219  abs_base.sign = NUMERIC_POS;
11220  base = &abs_base;
11221  }
11222  else
11223  res_sign = NUMERIC_POS;
11224 
11225  /*----------
11226  * Decide on the scale for the ln() calculation. For this we need an
11227  * estimate of the weight of the result, which we obtain by doing an
11228  * initial low-precision calculation of exp * ln(base).
11229  *
11230  * We want result = e ^ (exp * ln(base))
11231  * so result dweight = log10(result) = exp * ln(base) * log10(e)
11232  *
11233  * We also perform a crude overflow test here so that we can exit early if
11234  * the full-precision result is sure to overflow, and to guard against
11235  * integer overflow when determining the scale for the real calculation.
11236  * exp_var() supports inputs up to NUMERIC_MAX_RESULT_SCALE * 3, so the
11237  * result will overflow if exp * ln(base) >= NUMERIC_MAX_RESULT_SCALE * 3.
11238  * Since the values here are only approximations, we apply a small fuzz
11239  * factor to this overflow test and let exp_var() determine the exact
11240  * overflow threshold so that it is consistent for all inputs.
11241  *----------
11242  */
11243  ln_dweight = estimate_ln_dweight(base);
11244 
11245  /*
11246  * Set the scale for the low-precision calculation, computing ln(base) to
11247  * around 8 significant digits. Note that ln_dweight may be as small as
11248  * -NUMERIC_DSCALE_MAX, so the scale may exceed NUMERIC_MAX_DISPLAY_SCALE
11249  * here.
11250  */
11251  local_rscale = 8 - ln_dweight;
11252  local_rscale = Max(local_rscale, NUMERIC_MIN_DISPLAY_SCALE);
11253 
11254  ln_var(base, &ln_base, local_rscale);
11255 
11256  mul_var(&ln_base, exp, &ln_num, local_rscale);
11257 
11259 
11260  /* initial overflow/underflow test with fuzz factor */
11261  if (fabs(val) > NUMERIC_MAX_RESULT_SCALE * 3.01)
11262  {
11263  if (val > 0)
11264  ereport(ERROR,
11265  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
11266  errmsg("value overflows numeric format")));
11267  zero_var(result);
11269  return;
11270  }
11271 
11272  val *= 0.434294481903252; /* approximate decimal result weight */
11273 
11274  /* choose the result scale */
11275  rscale = NUMERIC_MIN_SIG_DIGITS - (int) val;
11276  rscale = Max(rscale, base->dscale);
11277  rscale = Max(rscale, exp->dscale);
11278  rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
11279  rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
11280 
11281  /* significant digits required in the result */
11282  sig_digits = rscale + (int) val;
11283  sig_digits = Max(sig_digits, 0);
11284 
11285  /* set the scale for the real exp * ln(base) calculation */
11286  local_rscale = sig_digits - ln_dweight + 8;
11287  local_rscale = Max(local_rscale, NUMERIC_MIN_DISPLAY_SCALE);
11288 
11289  /* and do the real calculation */
11290 
11291  ln_var(base, &ln_base, local_rscale);
11292 
11293  mul_var(&ln_base, exp, &ln_num, local_rscale);
11294 
11295  exp_var(&ln_num, result, rscale);
11296 
11297  if (res_sign == NUMERIC_NEG && result->ndigits > 0)
11298  result->sign = NUMERIC_NEG;
11299 
11300  free_var(&ln_num);
11301  free_var(&ln_base);
11302  free_var(&abs_base);
11303 }
static void power_var_int(const NumericVar *base, int exp, int exp_dscale, NumericVar *result)
Definition: numeric.c:11313

References cmp_var(), const_zero, NumericVar::digits, NumericVar::dscale, ereport, errcode(), errmsg(), ERROR, estimate_ln_dweight(), exp_var(), free_var(), init_var, ln_var(), Max, Min, mul_var(), NumericVar::ndigits, NUMERIC_MAX_DISPLAY_SCALE, NUMERIC_MAX_RESULT_SCALE, NUMERIC_MIN_DISPLAY_SCALE, NUMERIC_MIN_SIG_DIGITS, NUMERIC_NEG, NUMERIC_POS, numericvar_to_double_no_overflow(), numericvar_to_int64(), PG_INT32_MAX, PG_INT32_MIN, power_var_int(), set_var_from_var(), NumericVar::sign, val, NumericVar::weight, and zero_var().

Referenced by numeric_power().

◆ power_var_int()

static void power_var_int ( const NumericVar base,
int  exp,
int  exp_dscale,
NumericVar result 
)
static

Definition at line 11313 of file numeric.c.

11315 {
11316  double f;
11317  int p;
11318  int i;
11319  int rscale;
11320  int sig_digits;
11321  unsigned int mask;
11322  bool neg;
11323  NumericVar base_prod;
11324  int local_rscale;
11325 
11326  /*
11327  * Choose the result scale. For this we need an estimate of the decimal
11328  * weight of the result, which we obtain by approximating using double
11329  * precision arithmetic.
11330  *
11331  * We also perform crude overflow/underflow tests here so that we can exit
11332  * early if the result is sure to overflow/underflow, and to guard against
11333  * integer overflow when choosing the result scale.
11334  */
11335  if (base->ndigits != 0)
11336  {
11337  /*----------
11338  * Choose f (double) and p (int) such that base ~= f * 10^p.
11339  * Then log10(result) = log10(base^exp) ~= exp * (log10(f) + p).
11340  *----------
11341  */
11342  f = base->digits[0];
11343  p = base->weight * DEC_DIGITS;
11344 
11345  for (i = 1; i < base->ndigits && i * DEC_DIGITS < 16; i++)
11346  {
11347  f = f * NBASE + base->digits[i];
11348  p -= DEC_DIGITS;
11349  }
11350 
11351  f = exp * (log10(f) + p); /* approximate decimal result weight */
11352  }
11353  else
11354  f = 0; /* result is 0 or 1 (weight 0), or error */
11355 
11356  /* overflow/underflow tests with fuzz factors */
11357  if (f > (NUMERIC_WEIGHT_MAX + 1) * DEC_DIGITS)
11358  ereport(ERROR,
11359  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
11360  errmsg("value overflows numeric format")));
11361  if (f + 1 < -NUMERIC_MAX_DISPLAY_SCALE)
11362  {
11363  zero_var(result);
11365  return;
11366  }
11367 
11368  /*
11369  * Choose the result scale in the same way as power_var(), so it has at
11370  * least NUMERIC_MIN_SIG_DIGITS significant digits and is not less than
11371  * either input's display scale.
11372  */
11373  rscale = NUMERIC_MIN_SIG_DIGITS - (int) f;
11374  rscale = Max(rscale, base->dscale);
11375  rscale = Max(rscale, exp_dscale);
11376  rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
11377  rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
11378 
11379  /* Handle some common special cases, as well as corner cases */
11380  switch (exp)
11381  {
11382  case 0:
11383 
11384  /*
11385  * While 0 ^ 0 can be either 1 or indeterminate (error), we treat
11386  * it as 1 because most programming languages do this. SQL:2003
11387  * also requires a return value of 1.
11388  * https://en.wikipedia.org/wiki/Exponentiation#Zero_to_the_zero_power
11389  */
11390  set_var_from_var(&const_one, result);
11391  result->dscale = rscale; /* no need to round */
11392  return;
11393  case 1:
11394  set_var_from_var(base, result);
11395  round_var(result, rscale);
11396  return;
11397  case -1:
11398  div_var(&const_one, base, result, rscale, true);
11399  return;
11400  case 2:
11401  mul_var(base, base, result, rscale);
11402  return;
11403  default:
11404  break;
11405  }
11406 
11407  /* Handle the special case where the base is zero */
11408  if (base->ndigits == 0)
11409  {
11410  if (exp < 0)
11411  ereport(ERROR,
11412  (errcode(ERRCODE_DIVISION_BY_ZERO),
11413  errmsg("division by zero")));
11414  zero_var(result);
11415  result->dscale = rscale;
11416  return;
11417  }
11418 
11419  /*
11420  * The general case repeatedly multiplies base according to the bit
11421  * pattern of exp.
11422  *
11423  * The local rscale used for each multiplication is varied to keep a fixed
11424  * number of significant digits, sufficient to give the required result
11425  * scale.
11426  */
11427 
11428  /*
11429  * Approximate number of significant digits in the result. Note that the
11430  * underflow test above, together with the choice of rscale, ensures that
11431  * this approximation is necessarily > 0.
11432  */
11433  sig_digits = 1 + rscale + (int) f;
11434 
11435  /*
11436  * The multiplications to produce the result may introduce an error of up
11437  * to around log10(abs(exp)) digits, so work with this many extra digits
11438  * of precision (plus a few more for good measure).
11439  */
11440  sig_digits += (int) log(fabs((double) exp)) + 8;
11441 
11442  /*
11443  * Now we can proceed with the multiplications.
11444  */
11445  neg = (exp < 0);
11446  mask = abs(exp);
11447 
11448  init_var(&base_prod);
11449  set_var_from_var(base, &base_prod);
11450 
11451  if (mask & 1)
11452  set_var_from_var(base, result);
11453  else
11454  set_var_from_var(&const_one, result);
11455 
11456  while ((mask >>= 1) > 0)
11457  {
11458  /*
11459  * Do the multiplications using rscales large enough to hold the
11460  * results to the required number of significant digits, but don't
11461  * waste time by exceeding the scales of the numbers themselves.
11462  */
11463  local_rscale = sig_digits - 2 * base_prod.weight * DEC_DIGITS;
11464  local_rscale = Min(local_rscale, 2 * base_prod.dscale);
11465  local_rscale = Max(local_rscale, NUMERIC_MIN_DISPLAY_SCALE);
11466 
11467  mul_var(&base_prod, &base_prod, &base_prod, local_rscale);
11468 
11469  if (mask & 1)
11470  {
11471  local_rscale = sig_digits -
11472  (base_prod.weight + result->weight) * DEC_DIGITS;
11473  local_rscale = Min(local_rscale,
11474  base_prod.dscale + result->dscale);
11475  local_rscale = Max(local_rscale, NUMERIC_MIN_DISPLAY_SCALE);
11476 
11477  mul_var(&base_prod, result, result, local_rscale);
11478  }
11479 
11480  /*
11481  * When abs(base) > 1, the number of digits to the left of the decimal
11482  * point in base_prod doubles at each iteration, so if exp is large we
11483  * could easily spend large amounts of time and memory space doing the
11484  * multiplications. But once the weight exceeds what will fit in
11485  * int16, the final result is guaranteed to overflow (or underflow, if
11486  * exp < 0), so we can give up before wasting too many cycles.
11487  */
11488  if (base_prod.weight > NUMERIC_WEIGHT_MAX ||
11489  result->weight > NUMERIC_WEIGHT_MAX)
11490  {
11491  /* overflow, unless neg, in which case result should be 0 */
11492  if (!neg)
11493  ereport(ERROR,
11494  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
11495  errmsg("value overflows numeric format")));
11496  zero_var(result);
11497  neg = false;
11498  break;
11499  }
11500  }
11501 
11502  free_var(&base_prod);
11503 
11504  /* Compensate for input sign, and round to requested rscale */
11505  if (neg)
11506  div_var_fast(&const_one, result, result, rscale, true);
11507  else
11508  round_var(result, rscale);
11509 }

References const_one, DEC_DIGITS, NumericVar::digits, div_var(), div_var_fast(), NumericVar::dscale, ereport, errcode(), errmsg(), ERROR, free_var(), i, init_var, Max, Min, mul_var(), NBASE, NumericVar::ndigits, NUMERIC_MAX_DISPLAY_SCALE, NUMERIC_MIN_DISPLAY_SCALE, NUMERIC_MIN_SIG_DIGITS, NUMERIC_WEIGHT_MAX, round_var(), set_var_from_var(), NumericVar::weight, and zero_var().

Referenced by power_var().

◆ random_numeric()

Numeric random_numeric ( pg_prng_state state,
Numeric  rmin,
Numeric  rmax 
)

Definition at line 4232 of file numeric.c.

4233 {
4234  NumericVar rmin_var;
4235  NumericVar rmax_var;
4236  NumericVar result;
4237  Numeric res;
4238 
4239  /* Range bounds must not be NaN/infinity */
4240  if (NUMERIC_IS_SPECIAL(rmin))
4241  {
4242  if (NUMERIC_IS_NAN(rmin))
4243  ereport(ERROR,
4244  errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4245  errmsg("lower bound cannot be NaN"));
4246  else
4247  ereport(ERROR,
4248  errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4249  errmsg("lower bound cannot be infinity"));
4250  }
4251  if (NUMERIC_IS_SPECIAL(rmax))
4252  {
4253  if (NUMERIC_IS_NAN(rmax))
4254  ereport(ERROR,
4255  errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4256  errmsg("upper bound cannot be NaN"));
4257  else
4258  ereport(ERROR,
4259  errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4260  errmsg("upper bound cannot be infinity"));
4261  }
4262 
4263  /* Return a random value in the range [rmin, rmax] */
4264  init_var_from_num(rmin, &rmin_var);
4265  init_var_from_num(rmax, &rmax_var);
4266 
4267  init_var(&result);
4268 
4269  random_var(state, &rmin_var, &rmax_var, &result);
4270 
4271  res = make_result(&result);
4272 
4273  free_var(&result);
4274 
4275  return res;
4276 }
static void random_var(pg_prng_state *state, const NumericVar *rmin, const NumericVar *rmax, NumericVar *result)
Definition: numeric.c:11543

References ereport, errcode(), errmsg(), ERROR, free_var(), init_var, init_var_from_num(), make_result(), NUMERIC_IS_NAN, NUMERIC_IS_SPECIAL, random_var(), and res.

Referenced by numeric_random().

◆ random_var()

static void random_var ( pg_prng_state state,
const NumericVar rmin,
const NumericVar rmax,
NumericVar result 
)
static

Definition at line 11543 of file numeric.c.

11545 {
11546  int rscale;
11547  NumericVar rlen;
11548  int res_ndigits;
11549  int n;
11550  int pow10;
11551  int i;
11552  uint64 rlen64;
11553  int rlen64_ndigits;
11554 
11555  rscale = Max(rmin->dscale, rmax->dscale);
11556 
11557  /* Compute rlen = rmax - rmin and check the range bounds */
11558  init_var(&rlen);
11559  sub_var(rmax, rmin, &rlen);
11560 
11561  if (rlen.sign == NUMERIC_NEG)
11562  ereport(ERROR,
11563  errcode(ERRCODE_INVALID_PARAMETER_VALUE),
11564  errmsg("lower bound must be less than or equal to upper bound"));
11565 
11566  /* Special case for an empty range */
11567  if (rlen.ndigits == 0)
11568  {
11569  set_var_from_var(rmin, result);
11570  result->dscale = rscale;
11571  free_var(&rlen);
11572  return;
11573  }
11574 
11575  /*
11576  * Otherwise, select a random value in the range [0, rlen = rmax - rmin],
11577  * and shift it to the required range by adding rmin.
11578  */
11579 
11580  /* Required result digits */
11581  res_ndigits = rlen.weight + 1 + (rscale + DEC_DIGITS - 1) / DEC_DIGITS;
11582 
11583  /*
11584  * To get the required rscale, the final result digit must be a multiple
11585  * of pow10 = 10^n, where n = (-rscale) mod DEC_DIGITS.
11586  */
11587  n = ((rscale + DEC_DIGITS - 1) / DEC_DIGITS) * DEC_DIGITS - rscale;
11588  pow10 = 1;
11589  for (i = 0; i < n; i++)
11590  pow10 *= 10;
11591 
11592  /*
11593  * To choose a random value uniformly from the range [0, rlen], we choose
11594  * from the slightly larger range [0, rlen2], where rlen2 is formed from
11595  * rlen by copying the first 4 NBASE digits, and setting all remaining
11596  * decimal digits to "9".
11597  *
11598  * Without loss of generality, we can ignore the weight of rlen2 and treat
11599  * it as a pure integer for the purposes of this discussion. The process
11600  * above gives rlen2 + 1 = rlen64 * 10^N, for some integer N, where rlen64
11601  * is a 64-bit integer formed from the first 4 NBASE digits copied from
11602  * rlen. Since this trivially factors into smaller pieces that fit in
11603  * 64-bit integers, the task of choosing a random value uniformly from the
11604  * rlen2 + 1 possible values in [0, rlen2] is much simpler.
11605  *
11606  * If the random value selected is too large, it is rejected, and we try
11607  * again until we get a result <= rlen, ensuring that the overall result
11608  * is uniform (no particular value is any more likely than any other).
11609  *
11610  * Since rlen64 holds 4 NBASE digits from rlen, it contains at least
11611  * DEC_DIGITS * 3 + 1 decimal digits (i.e., at least 13 decimal digits,
11612  * when DEC_DIGITS is 4). Therefore the probability of needing to reject
11613  * the value chosen and retry is less than 1e-13.
11614  */
11615  rlen64 = (uint64) rlen.digits[0];
11616  rlen64_ndigits = 1;
11617  while (rlen64_ndigits < res_ndigits && rlen64_ndigits < 4)
11618  {
11619  rlen64 *= NBASE;
11620  if (rlen64_ndigits < rlen.ndigits)
11621  rlen64 += rlen.digits[rlen64_ndigits];
11622  rlen64_ndigits++;
11623  }
11624 
11625  /* Loop until we get a result <= rlen */
11626  do
11627  {
11628  NumericDigit *res_digits;
11629  uint64 rand;
11630  int whole_ndigits;
11631 
11632  alloc_var(result, res_ndigits);
11633  result->sign = NUMERIC_POS;
11634  result->weight = rlen.weight;
11635  result->dscale = rscale;
11636  res_digits = result->digits;
11637 
11638  /*
11639  * Set the first rlen64_ndigits using a random value in [0, rlen64].
11640  *
11641  * If this is the whole result, and rscale is not a multiple of
11642  * DEC_DIGITS (pow10 from above is not 1), then we need this to be a
11643  * multiple of pow10.
11644  */
11645  if (rlen64_ndigits == res_ndigits && pow10 != 1)
11646  rand = pg_prng_uint64_range(state, 0, rlen64 / pow10) * pow10;
11647  else
11648  rand = pg_prng_uint64_range(state, 0, rlen64);
11649 
11650  for (i = rlen64_ndigits - 1; i >= 0; i--)
11651  {
11652  res_digits[i] = (NumericDigit) (rand % NBASE);
11653  rand = rand / NBASE;
11654  }
11655 
11656  /*
11657  * Set the remaining digits to random values in range [0, NBASE),
11658  * noting that the last digit needs to be a multiple of pow10.
11659  */
11660  whole_ndigits = res_ndigits;
11661  if (pow10 != 1)
11662  whole_ndigits--;
11663 
11664  /* Set whole digits in groups of 4 for best performance */
11665  i = rlen64_ndigits;
11666  while (i < whole_ndigits - 3)
11667  {
11668  rand = pg_prng_uint64_range(state, 0,
11669  (uint64) NBASE * NBASE * NBASE * NBASE - 1);
11670  res_digits[i++] = (NumericDigit) (rand % NBASE);
11671  rand = rand / NBASE;
11672  res_digits[i++] = (NumericDigit) (rand % NBASE);
11673  rand = rand / NBASE;
11674  res_digits[i++] = (NumericDigit) (rand % NBASE);
11675  rand = rand / NBASE;
11676  res_digits[i++] = (NumericDigit) rand;
11677  }
11678 
11679  /* Remaining whole digits */
11680  while (i < whole_ndigits)
11681  {
11682  rand = pg_prng_uint64_range(state, 0, NBASE - 1);
11683  res_digits[i++] = (NumericDigit) rand;
11684  }
11685 
11686  /* Final partial digit (multiple of pow10) */
11687  if (i < res_ndigits)
11688  {
11689  rand = pg_prng_uint64_range(state, 0, NBASE / pow10 - 1) * pow10;
11690  res_digits[i] = (NumericDigit) rand;
11691  }
11692 
11693  /* Remove leading/trailing zeroes */
11694  strip_var(result);
11695 
11696  /* If result > rlen, try again */
11697 
11698  } while (cmp_var(result, &rlen) > 0);
11699 
11700  /* Offset the result to the required range */
11701  add_var(result, rmin, result);
11702 
11703  free_var(&rlen);
11704 }
while(p+4<=pend)
uint64 pg_prng_uint64_range(pg_prng_state *state, uint64 rmin, uint64 rmax)
Definition: pg_prng.c:144

References add_var(), alloc_var(), cmp_var(), DEC_DIGITS, NumericVar::digits, NumericVar::dscale, ereport, errcode(), errmsg(), ERROR, free_var(), i, init_var, Max, NBASE, NumericVar::ndigits, NUMERIC_NEG, NUMERIC_POS, pg_prng_uint64_range(), set_var_from_var(), NumericVar::sign, strip_var(), sub_var(), NumericVar::weight, and while().

Referenced by random_numeric().

◆ round_var()

static void round_var ( NumericVar var,
int  rscale 
)
static

Definition at line 11971 of file numeric.c.

11972 {
11973  NumericDigit *digits = var->digits;
11974  int di;
11975  int ndigits;
11976  int carry;
11977 
11978  var->dscale = rscale;
11979 
11980  /* decimal digits wanted */
11981  di = (var->weight + 1) * DEC_DIGITS + rscale;
11982 
11983  /*
11984  * If di = 0, the value loses all digits, but could round up to 1 if its
11985  * first extra digit is >= 5. If di < 0 the result must be 0.
11986  */
11987  if (di < 0)
11988  {
11989  var->ndigits = 0;
11990  var->weight = 0;
11991  var->sign = NUMERIC_POS;
11992  }
11993  else
11994  {
11995  /* NBASE digits wanted */
11996  ndigits = (di + DEC_DIGITS - 1) / DEC_DIGITS;
11997 
11998  /* 0, or number of decimal digits to keep in last NBASE digit */
11999  di %= DEC_DIGITS;
12000 
12001  if (ndigits < var->ndigits ||
12002  (ndigits == var->ndigits && di > 0))
12003  {
12004  var->ndigits = ndigits;
12005 
12006 #if DEC_DIGITS == 1
12007  /* di must be zero */
12008  carry = (digits[ndigits] >= HALF_NBASE) ? 1 : 0;
12009 #else
12010  if (di == 0)
12011  carry = (digits[ndigits] >= HALF_NBASE) ? 1 : 0;
12012  else
12013  {
12014  /* Must round within last NBASE digit */
12015  int extra,
12016  pow10;
12017 
12018 #if DEC_DIGITS == 4
12019  pow10 = round_powers[di];
12020 #elif DEC_DIGITS == 2
12021  pow10 = 10;
12022 #else
12023 #error unsupported NBASE
12024 #endif
12025  extra = digits[--ndigits] % pow10;
12026  digits[ndigits] -= extra;
12027  carry = 0;
12028  if (extra >= pow10 / 2)
12029  {
12030  pow10 += digits[ndigits];
12031  if (pow10 >= NBASE)
12032  {
12033  pow10 -= NBASE;
12034  carry = 1;
12035  }
12036  digits[ndigits] = pow10;
12037  }
12038  }
12039 #endif
12040 
12041  /* Propagate carry if needed */
12042  while (carry)
12043  {
12044  carry += digits[--ndigits];
12045  if (carry >= NBASE)
12046  {
12047  digits[ndigits] = carry - NBASE;
12048  carry = 1;
12049  }
12050  else
12051  {
12052  digits[ndigits] = carry;
12053  carry = 0;
12054  }
12055  }
12056 
12057  if (ndigits < 0)
12058  {
12059  Assert(ndigits == -1); /* better not have added > 1 digit */
12060  Assert(var->digits > var->buf);
12061  var->digits--;
12062  var->ndigits++;
12063  var->weight++;
12064  }
12065  }
12066  }
12067 }
static const int round_powers[4]
Definition: numeric.c:466

References Assert, NumericVar::buf, DEC_DIGITS, NumericVar::digits, digits, NumericVar::dscale, HALF_NBASE, NBASE, NumericVar::ndigits, NUMERIC_POS, round_powers, NumericVar::sign, and NumericVar::weight.

Referenced by apply_typmod(), div_var(), div_var_fast(), div_var_int(), exp_var(), mul_var(), numeric_mul_opt_error(), numeric_round(), numericvar_to_int64(), numericvar_to_uint64(), power_var_int(), and sqrt_var().

◆ select_div_scale()

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

Definition at line 9997 of file numeric.c.

9998 {
9999  int weight1,
10000  weight2,
10001  qweight,
10002  i;
10003  NumericDigit firstdigit1,
10004  firstdigit2;
10005  int rscale;
10006 
10007  /*
10008  * The result scale of a division isn't specified in any SQL standard. For
10009  * PostgreSQL we select a result scale that will give at least
10010  * NUMERIC_MIN_SIG_DIGITS significant digits, so that numeric gives a
10011  * result no less accurate than float8; but use a scale not less than
10012  * either input's display scale.
10013  */
10014 
10015  /* Get the actual (normalized) weight and first digit of each input */
10016 
10017  weight1 = 0; /* values to use if var1 is zero */
10018  firstdigit1 = 0;
10019  for (i = 0; i < var1->ndigits; i++)
10020  {
10021  firstdigit1 = var1->digits[i];
10022  if (firstdigit1 != 0)
10023  {
10024  weight1 = var1->weight - i;
10025  break;
10026  }
10027  }
10028 
10029  weight2 = 0; /* values to use if var2 is zero */
10030  firstdigit2 = 0;
10031  for (i = 0; i < var2->ndigits; i++)
10032  {
10033  firstdigit2 = var2->digits[i];
10034  if (firstdigit2 != 0)
10035  {
10036  weight2 = var2->weight - i;
10037  break;
10038  }
10039  }
10040 
10041  /*
10042  * Estimate weight of quotient. If the two first digits are equal, we
10043  * can't be sure, but assume that var1 is less than var2.
10044  */
10045  qweight = weight1 - weight2;
10046  if (firstdigit1 <= firstdigit2)
10047  qweight--;
10048 
10049  /* Select result scale */
10050  rscale = NUMERIC_MIN_SIG_DIGITS - qweight * DEC_DIGITS;
10051  rscale = Max(rscale, var1->dscale);
10052  rscale = Max(rscale, var2->dscale);
10053  rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
10054  rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
10055 
10056  return rscale;
10057 }

References DEC_DIGITS, NumericVar::digits, NumericVar::dscale, i, Max, Min, NumericVar::ndigits, NUMERIC_MAX_DISPLAY_SCALE, NUMERIC_MIN_DISPLAY_SCALE, NUMERIC_MIN_SIG_DIGITS, and NumericVar::weight.

Referenced by numeric_div_opt_error(), and numeric_stddev_internal().

◆ set_var_from_non_decimal_integer_str()

static bool set_var_from_non_decimal_integer_str ( const char *  str,
const char *  cp,
int  sign,
int  base,
NumericVar dest,
const char **  endptr,
Node escontext 
)
static

Definition at line 7246 of file numeric.c.

7249 {
7250  const char *firstdigit = cp;
7251  int64 tmp;
7252  int64 mul;
7253  NumericVar tmp_var;
7254 
7255  init_var(&tmp_var);
7256 
7257  zero_var(dest);
7258 
7259  /*
7260  * Process input digits in groups that fit in int64. Here "tmp" is the
7261  * value of the digits in the group, and "mul" is base^n, where n is the
7262  * number of digits in the group. Thus tmp < mul, and we must start a new
7263  * group when mul * base threatens to overflow PG_INT64_MAX.
7264  */
7265  tmp = 0;
7266  mul = 1;
7267 
7268  if (base == 16)
7269  {
7270  while (*cp)
7271  {
7272  if (isxdigit((unsigned char) *cp))
7273  {
7274  if (mul > PG_INT64_MAX / 16)
7275  {
7276  /* Add the contribution from this group of digits */
7277  int64_to_numericvar(mul, &tmp_var);
7278  mul_var(dest, &tmp_var, dest, 0);
7279  int64_to_numericvar(tmp, &tmp_var);
7280  add_var(dest, &tmp_var, dest);
7281 
7282  /* Result will overflow if weight overflows int16 */
7283  if (dest->weight > NUMERIC_WEIGHT_MAX)
7284  goto out_of_range;
7285 
7286  /* Begin a new group */
7287  tmp = 0;
7288  mul = 1;
7289  }
7290 
7291  tmp = tmp * 16 + xdigit_value(*cp++);
7292  mul = mul * 16;
7293  }
7294  else if (*cp == '_')
7295  {
7296  /* Underscore must be followed by more digits */
7297  cp++;
7298  if (!isxdigit((unsigned char) *cp))
7299  goto invalid_syntax;
7300  }
7301  else
7302  break;
7303  }
7304  }
7305  else if (base == 8)
7306  {
7307  while (*cp)
7308  {
7309  if (*cp >= '0' && *cp <= '7')
7310  {
7311  if (mul > PG_INT64_MAX / 8)
7312  {
7313  /* Add the contribution from this group of digits */
7314  int64_to_numericvar(mul, &tmp_var);
7315  mul_var(dest, &tmp_var, dest, 0);
7316  int64_to_numericvar(tmp, &tmp_var);
7317  add_var(dest, &tmp_var, dest);
7318 
7319  /* Result will overflow if weight overflows int16 */
7320  if (dest->weight > NUMERIC_WEIGHT_MAX)
7321  goto out_of_range;
7322 
7323  /* Begin a new group */
7324  tmp = 0;
7325  mul = 1;
7326  }
7327 
7328  tmp = tmp * 8 + (*cp++ - '0');
7329  mul = mul * 8;
7330  }
7331  else if (*cp == '_')
7332  {
7333  /* Underscore must be followed by more digits */
7334  cp++;
7335  if (*cp < '0' || *cp > '7')
7336  goto invalid_syntax;
7337  }
7338  else
7339  break;
7340  }
7341  }
7342  else if (base == 2)
7343  {
7344  while (*cp)
7345  {
7346  if (*cp >= '0' && *cp <= '1')
7347  {
7348  if (mul > PG_INT64_MAX / 2)
7349  {
7350  /* Add the contribution from this group of digits */
7351  int64_to_numericvar(mul, &tmp_var);
7352  mul_var(dest, &tmp_var, dest, 0);
7353  int64_to_numericvar(tmp, &tmp_var);
7354  add_var(dest, &tmp_var, dest);
7355 
7356  /* Result will overflow if weight overflows int16 */
7357  if (dest->weight > NUMERIC_WEIGHT_MAX)
7358  goto out_of_range;
7359 
7360  /* Begin a new group */
7361  tmp = 0;
7362  mul = 1;
7363  }
7364 
7365  tmp = tmp * 2 + (*cp++ - '0');
7366  mul = mul * 2;
7367  }
7368  else if (*cp == '_')
7369  {
7370  /* Underscore must be followed by more digits */
7371  cp++;
7372  if (*cp < '0' || *cp > '1')
7373  goto invalid_syntax;
7374  }
7375  else
7376  break;
7377  }
7378  }
7379  else
7380  /* Should never happen; treat as invalid input */
7381  goto invalid_syntax;
7382 
7383  /* Check that we got at least one digit */
7384  if (unlikely(cp == firstdigit))
7385  goto invalid_syntax;
7386 
7387  /* Add the contribution from the final group of digits */
7388  int64_to_numericvar(mul, &tmp_var);
7389  mul_var(dest, &tmp_var, dest, 0);
7390  int64_to_numericvar(tmp, &tmp_var);
7391  add_var(dest, &tmp_var, dest);
7392 
7393  if (dest->weight > NUMERIC_WEIGHT_MAX)
7394  goto out_of_range;
7395 
7396  dest->sign = sign;
7397 
7398  free_var(&tmp_var);
7399 
7400  /* Return end+1 position for caller */
7401  *endptr = cp;
7402 
7403  return true;
7404 
7405 out_of_range:
7406  ereturn(escontext, false,
7407  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
7408  errmsg("value overflows numeric format")));
7409 
7410 invalid_syntax:
7411  ereturn(escontext, false,
7412  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
7413  errmsg("invalid input syntax for type %s: \"%s\"",
7414  "numeric", str)));
7415 }
static int xdigit_value(char dig)
Definition: numeric.c:7219
#define PG_INT64_MAX
Definition: c.h:592

References add_var(), generate_unaccent_rules::dest, ereturn, errcode(), errmsg(), free_var(), init_var, int64_to_numericvar(), mul_var(), NUMERIC_WEIGHT_MAX, PG_INT64_MAX, sign, str, unlikely, xdigit_value(), and zero_var().

Referenced by numeric_in().

◆ set_var_from_num()

static void set_var_from_num ( Numeric  num,
NumericVar dest 
)
static

Definition at line 7424 of file numeric.c.

7425 {
7426  int ndigits;
7427 
7428  ndigits = NUMERIC_NDIGITS(num);
7429 
7430  alloc_var(dest, ndigits);
7431 
7432  dest->weight = NUMERIC_WEIGHT(num);
7433  dest->sign = NUMERIC_SIGN(num);
7434  dest->dscale = NUMERIC_DSCALE(num);
7435 
7436  memcpy(dest->digits, NUMERIC_DIGITS(num), ndigits * sizeof(NumericDigit));
7437 }

References alloc_var(), generate_unaccent_rules::dest, NUMERIC_DIGITS, NUMERIC_DSCALE, NUMERIC_NDIGITS, NUMERIC_SIGN, and NUMERIC_WEIGHT.

Referenced by generate_series_step_numeric(), numeric(), numeric_round(), and numeric_trunc().

◆ set_var_from_str()

static bool set_var_from_str ( const char *  str,
const char *  cp,
NumericVar dest,
const char **  endptr,
Node escontext 
)
static

Definition at line 7016 of file numeric.c.

7019 {
7020  bool have_dp = false;
7021  int i;
7022  unsigned char *decdigits;
7023  int sign = NUMERIC_POS;
7024  int dweight = -1;
7025  int ddigits;
7026  int dscale = 0;
7027  int weight;
7028  int ndigits;
7029  int offset;
7031 
7032  /*
7033  * We first parse the string to extract decimal digits and determine the
7034  * correct decimal weight. Then convert to NBASE representation.
7035  */
7036  switch (*cp)
7037  {
7038  case '+':
7039  sign = NUMERIC_POS;
7040  cp++;
7041  break;
7042 
7043  case '-':
7044  sign = NUMERIC_NEG;
7045  cp++;
7046  break;
7047  }
7048 
7049  if (*cp == '.')
7050  {
7051  have_dp = true;
7052  cp++;
7053  }
7054 
7055  if (!isdigit((unsigned char) *cp))
7056  goto invalid_syntax;
7057 
7058  decdigits = (unsigned char *) palloc(strlen(cp) + DEC_DIGITS * 2);
7059 
7060  /* leading padding for digit alignment later */
7061  memset(decdigits, 0, DEC_DIGITS);
7062  i = DEC_DIGITS;
7063 
7064  while (*cp)
7065  {
7066  if (isdigit((unsigned char) *cp))
7067  {
7068  decdigits[i++] = *cp++ - '0';
7069  if (!have_dp)
7070  dweight++;
7071  else
7072  dscale++;
7073  }
7074  else if (*cp == '.')
7075  {
7076  if (have_dp)
7077  goto invalid_syntax;
7078  have_dp = true;
7079  cp++;
7080  /* decimal point must not be followed by underscore */
7081  if (*cp == '_')
7082  goto invalid_syntax;
7083  }
7084  else if (*cp == '_')
7085  {
7086  /* underscore must be followed by more digits */
7087  cp++;
7088  if (!isdigit((unsigned char) *cp))
7089  goto invalid_syntax;
7090  }
7091  else
7092  break;
7093  }
7094 
7095  ddigits = i - DEC_DIGITS;
7096  /* trailing padding for digit alignment later */
7097  memset(decdigits + i, 0, DEC_DIGITS - 1);
7098 
7099  /* Handle exponent, if any */
7100  if (*cp == 'e' || *cp == 'E')
7101  {
7102  int64 exponent = 0;
7103  bool neg = false;
7104 
7105  /*
7106  * At this point, dweight and dscale can't be more than about
7107  * INT_MAX/2 due to the MaxAllocSize limit on string length, so
7108  * constraining the exponent similarly should be enough to prevent
7109  * integer overflow in this function. If the value is too large to
7110  * fit in storage format, make_result() will complain about it later;
7111  * for consistency use the same ereport errcode/text as make_result().
7112  */
7113 
7114  /* exponent sign */
7115  cp++;
7116  if (*cp == '+')
7117  cp++;
7118  else if (*cp == '-')
7119  {
7120  neg = true;
7121  cp++;
7122  }
7123 
7124  /* exponent digits */
7125  if (!isdigit((unsigned char) *cp))
7126  goto invalid_syntax;
7127 
7128  while (*cp)
7129  {
7130  if (isdigit((unsigned char) *cp))
7131  {
7132  exponent = exponent * 10 + (*cp++ - '0');
7133  if (exponent > PG_INT32_MAX / 2)
7134  goto out_of_range;
7135  }
7136  else if (*cp == '_')
7137  {
7138  /* underscore must be followed by more digits */
7139  cp++;
7140  if (!isdigit((unsigned char) *cp))
7141  goto invalid_syntax;
7142  }
7143  else
7144  break;
7145  }
7146 
7147  if (neg)
7148  exponent = -exponent;
7149 
7150  dweight += (int) exponent;
7151  dscale -= (int) exponent;
7152  if (dscale < 0)
7153  dscale = 0;
7154  }
7155 
7156  /*
7157  * Okay, convert pure-decimal representation to base NBASE. First we need
7158  * to determine the converted weight and ndigits. offset is the number of
7159  * decimal zeroes to insert before the first given digit to have a
7160  * correctly aligned first NBASE digit.
7161  */
7162  if (dweight >= 0)
7163  weight = (dweight + 1 + DEC_DIGITS - 1) / DEC_DIGITS - 1;
7164  else
7165  weight = -((-dweight - 1) / DEC_DIGITS + 1);
7166  offset = (weight + 1) * DEC_DIGITS - (dweight + 1);
7167  ndigits = (ddigits + offset + DEC_DIGITS - 1) / DEC_DIGITS;
7168 
7169  alloc_var(dest, ndigits);
7170  dest->sign = sign;
7171  dest->weight = weight;
7172  dest->dscale = dscale;
7173 
7174  i = DEC_DIGITS - offset;
7175  digits = dest->digits;
7176 
7177  while (ndigits-- > 0)
7178  {
7179 #if DEC_DIGITS == 4
7180  *digits++ = ((decdigits[i] * 10 + decdigits[i + 1]) * 10 +
7181  decdigits[i + 2]) * 10 + decdigits[i + 3];
7182 #elif DEC_DIGITS == 2
7183  *digits++ = decdigits[i] * 10 + decdigits[i + 1];
7184 #elif DEC_DIGITS == 1
7185  *digits++ = decdigits[i];
7186 #else
7187 #error unsupported NBASE
7188 #endif
7189  i += DEC_DIGITS;
7190  }
7191 
7192  pfree(decdigits);
7193 
7194  /* Strip any leading/trailing zeroes, and normalize weight if zero */
7195  strip_var(dest);
7196 
7197  /* Return end+1 position for caller */
7198  *endptr = cp;
7199 
7200  return true;
7201 
7202 out_of_range:
7203  ereturn(escontext, false,
7204  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
7205  errmsg("value overflows numeric format")));
7206 
7207 invalid_syntax:
7208  ereturn(escontext, false,
7209  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
7210  errmsg("invalid input syntax for type %s: \"%s\"",
7211  "numeric", str)));
7212 }

References alloc_var(), DEC_DIGITS, generate_unaccent_rules::dest, digits, ereturn, errcode(), errmsg(), i, NUMERIC_NEG, NUMERIC_POS, palloc(), pfree(), PG_INT32_MAX, sign, str, and strip_var().

Referenced by float4_numeric(), float8_numeric(), and numeric_in().

◆ set_var_from_var()

static void set_var_from_var ( const NumericVar value,
NumericVar dest 
)
static

Definition at line 7472 of file numeric.c.

7473 {
7474  NumericDigit *newbuf;
7475 
7476  newbuf = digitbuf_alloc(value->ndigits + 1);
7477  newbuf[0] = 0; /* spare digit for rounding */
7478  if (value->ndigits > 0) /* else value->digits might be null */
7479  memcpy(newbuf + 1, value->digits,
7480  value->ndigits * sizeof(NumericDigit));
7481 
7482  digitbuf_free(dest->buf);
7483 
7484  memmove(dest, value, sizeof(NumericVar));
7485  dest->buf = newbuf;
7486  dest->digits = newbuf + 1;
7487 }

References generate_unaccent_rules::dest, digitbuf_alloc, digitbuf_free, and value.

Referenced by accum_sum_final(), ceil_var(), div_mod_var(), exp_var(), floor_var(), gcd_var(), generate_series_step_numeric(), ln_var(), numeric_lcm(), numericvar_to_int64(), numericvar_to_uint64(), power_ten_int(), power_var(), power_var_int(), random_var(), sqrt_var(), and width_bucket_numeric().

◆ sqrt_var()

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

Definition at line 10282 of file numeric.c.

10283 {
10284  int stat;
10285  int res_weight;
10286  int res_ndigits;
10287  int src_ndigits;
10288  int step;
10289  int ndigits[32];
10290  int blen;
10291  int64 arg_int64;
10292  int src_idx;
10293  int64 s_int64;
10294  int64 r_int64;
10295  NumericVar s_var;
10296  NumericVar r_var;
10297  NumericVar a0_var;
10298  NumericVar a1_var;
10299  NumericVar q_var;
10300  NumericVar u_var;
10301 
10302  stat = cmp_var(arg, &const_zero);
10303  if (stat == 0)
10304  {
10305  zero_var(result);
10306  result->dscale = rscale;
10307  return;
10308  }
10309 
10310  /*
10311  * SQL2003 defines sqrt() in terms of power, so we need to emit the right
10312  * SQLSTATE error code if the operand is negative.
10313  */
10314  if (stat < 0)
10315  ereport(ERROR,
10316  (errcode(ERRCODE_INVALID_ARGUMENT_FOR_POWER_FUNCTION),
10317  errmsg("cannot take square root of a negative number")));
10318 
10319  init_var(&s_var);
10320  init_var(&r_var);
10321  init_var(&a0_var);
10322  init_var(&a1_var);
10323  init_var(&q_var);
10324  init_var(&u_var);
10325 
10326  /*
10327  * The result weight is half the input weight, rounded towards minus
10328  * infinity --- res_weight = floor(arg->weight / 2).
10329  */
10330  if (arg->weight >= 0)
10331  res_weight = arg->weight / 2;
10332  else
10333  res_weight = -((-arg->weight - 1) / 2 + 1);
10334 
10335  /*
10336  * Number of NBASE digits to compute. To ensure correct rounding, compute
10337  * at least 1 extra decimal digit. We explicitly allow rscale to be
10338  * negative here, but must always compute at least 1 NBASE digit. Thus
10339  * res_ndigits = res_weight + 1 + ceil((rscale + 1) / DEC_DIGITS) or 1.
10340  */
10341  if (rscale + 1 >= 0)
10342  res_ndigits = res_weight + 1 + (rscale + DEC_DIGITS) / DEC_DIGITS;
10343  else
10344  res_ndigits = res_weight + 1 - (-rscale - 1) / DEC_DIGITS;
10345  res_ndigits = Max(res_ndigits, 1);
10346 
10347  /*
10348  * Number of source NBASE digits logically required to produce a result
10349  * with this precision --- every digit before the decimal point, plus 2
10350  * for each result digit after the decimal point (or minus 2 for each
10351  * result digit we round before the decimal point).
10352  */
10353  src_ndigits = arg->weight + 1 + (res_ndigits - res_weight - 1) * 2;
10354  src_ndigits = Max(src_ndigits, 1);
10355 
10356  /* ----------
10357  * From this point on, we treat the input and the result as integers and
10358  * compute the integer square root and remainder using the Karatsuba
10359  * Square Root algorithm, which may be written recursively as follows:
10360  *
10361  * SqrtRem(n = a3*b^3 + a2*b^2 + a1*b + a0):
10362  * [ for some base b, and coefficients a0,a1,a2,a3 chosen so that
10363  * 0 <= a0,a1,a2 < b and a3 >= b/4 ]
10364  * Let (s,r) = SqrtRem(a3*b + a2)
10365  * Let (q,u) = DivRem(r*b + a1, 2*s)
10366  * Let s = s*b + q
10367  * Let r = u*b + a0 - q^2
10368  * If r < 0 Then
10369  * Let r = r + s
10370  * Let s = s - 1
10371  * Let r = r + s
10372  * Return (s,r)
10373  *
10374  * See "Karatsuba Square Root", Paul Zimmermann, INRIA Research Report
10375  * RR-3805, November 1999. At the time of writing this was available
10376  * on the net at <https://hal.inria.fr/inria-00072854>.
10377  *
10378  * The way to read the assumption "n = a3*b^3 + a2*b^2 + a1*b + a0" is
10379  * "choose a base b such that n requires at least four base-b digits to
10380  * express; then those digits are a3,a2,a1,a0, with a3 possibly larger
10381  * than b". For optimal performance, b should have approximately a
10382  * quarter the number of digits in the input, so that the outer square
10383  * root computes roughly twice as many digits as the inner one. For
10384  * simplicity, we choose b = NBASE^blen, an integer power of NBASE.
10385  *
10386  * We implement the algorithm iteratively rather than recursively, to
10387  * allow the working variables to be reused. With this approach, each
10388  * digit of the input is read precisely once --- src_idx tracks the number
10389  * of input digits used so far.
10390  *
10391  * The array ndigits[] holds the number of NBASE digits of the input that
10392  * will have been used at the end of each iteration, which roughly doubles
10393  * each time. Note that the array elements are stored in reverse order,
10394  * so if the final iteration requires src_ndigits = 37 input digits, the
10395  * array will contain [37,19,11,7,5,3], and we would start by computing
10396  * the square root of the 3 most significant NBASE digits.
10397  *
10398  * In each iteration, we choose blen to be the largest integer for which
10399  * the input number has a3 >= b/4, when written in the form above. In
10400  * general, this means blen = src_ndigits / 4 (truncated), but if
10401  * src_ndigits is a multiple of 4, that might lead to the coefficient a3
10402  * being less than b/4 (if the first input digit is less than NBASE/4), in
10403  * which case we choose blen = src_ndigits / 4 - 1. The number of digits
10404  * in the inner square root is then src_ndigits - 2*blen. So, for
10405  * example, if we have src_ndigits = 26 initially, the array ndigits[]
10406  * will be either [26,14,8,4] or [26,14,8,6,4], depending on the size of
10407  * the first input digit.
10408  *
10409  * Additionally, we can put an upper bound on the number of steps required
10410  * as follows --- suppose that the number of source digits is an n-bit
10411  * number in the range [2^(n-1), 2^n-1], then blen will be in the range
10412  * [2^(n-3)-1, 2^(n-2)-1] and the number of digits in the inner square
10413  * root will be in the range [2^(n-2), 2^(n-1)+1]. In the next step, blen
10414  * will be in the range [2^(n-4)-1, 2^(n-3)] and the number of digits in
10415  * the next inner square root will be in the range [2^(n-3), 2^(n-2)+1].
10416  * This pattern repeats, and in the worst case the array ndigits[] will
10417  * contain [2^n-1, 2^(n-1)+1, 2^(n-2)+1, ... 9, 5, 3], and the computation
10418  * will require n steps. Therefore, since all digit array sizes are
10419  * signed 32-bit integers, the number of steps required is guaranteed to
10420  * be less than 32.
10421  * ----------
10422  */
10423  step = 0;
10424  while ((ndigits[step] = src_ndigits) > 4)
10425  {
10426  /* Choose b so that a3 >= b/4, as described above */
10427  blen = src_ndigits / 4;
10428  if (blen * 4 == src_ndigits && arg->digits[0] < NBASE / 4)
10429  blen--;
10430 
10431  /* Number of digits in the next step (inner square root) */
10432  src_ndigits -= 2 * blen;
10433  step++;
10434  }
10435 
10436  /*
10437  * First iteration (innermost square root and remainder):
10438  *
10439  * Here src_ndigits <= 4, and the input fits in an int64. Its square root
10440  * has at most 9 decimal digits, so estimate it using double precision
10441  * arithmetic, which will in fact almost certainly return the correct
10442  * result with no further correction required.
10443  */
10444  arg_int64 = arg->digits[0];
10445  for (src_idx = 1; src_idx < src_ndigits; src_idx++)
10446  {
10447  arg_int64 *= NBASE;
10448  if (src_idx < arg->ndigits)
10449  arg_int64 += arg->digits[src_idx];
10450  }
10451 
10452  s_int64 = (int64) sqrt((double) arg_int64);
10453  r_int64 = arg_int64 - s_int64 * s_int64;
10454 
10455  /*
10456  * Use Newton's method to correct the result, if necessary.
10457  *
10458  * This uses integer division with truncation to compute the truncated
10459  * integer square root by iterating using the formula x -> (x + n/x) / 2.
10460  * This is known to converge to isqrt(n), unless n+1 is a perfect square.
10461  * If n+1 is a perfect square, the sequence will oscillate between the two
10462  * values isqrt(n) and isqrt(n)+1, so we can be assured of convergence by
10463  * checking the remainder.
10464  */
10465  while (r_int64 < 0 || r_int64 > 2 * s_int64)
10466  {
10467  s_int64 = (s_int64 + arg_int64 / s_int64) / 2;
10468  r_int64 = arg_int64 - s_int64 * s_int64;
10469  }
10470 
10471  /*
10472  * Iterations with src_ndigits <= 8:
10473  *
10474  * The next 1 or 2 iterations compute larger (outer) square roots with
10475  * src_ndigits <= 8, so the result still fits in an int64 (even though the
10476  * input no longer does) and we can continue to compute using int64
10477  * variables to avoid more expensive numeric computations.
10478  *
10479  * It is fairly easy to see that there is no risk of the intermediate
10480  * values below overflowing 64-bit integers. In the worst case, the
10481  * previous iteration will have computed a 3-digit square root (of a
10482  * 6-digit input less than NBASE^6 / 4), so at the start of this
10483  * iteration, s will be less than NBASE^3 / 2 = 10^12 / 2, and r will be
10484  * less than 10^12. In this case, blen will be 1, so numer will be less
10485  * than 10^17, and denom will be less than 10^12 (and hence u will also be
10486  * less than 10^12). Finally, since q^2 = u*b + a0 - r, we can also be
10487  * sure that q^2 < 10^17. Therefore all these quantities fit comfortably
10488  * in 64-bit integers.
10489  */
10490  step--;
10491  while (step >= 0 && (src_ndigits = ndigits[step]) <= 8)
10492  {
10493  int b;
10494  int a0;
10495  int a1;
10496  int i;
10497  int64 numer;
10498  int64 denom;
10499  int64 q;
10500  int64 u;
10501 
10502  blen = (src_ndigits - src_idx) / 2;
10503 
10504  /* Extract a1 and a0, and compute b */
10505  a0 = 0;
10506  a1 = 0;
10507  b = 1;
10508 
10509  for (i = 0; i < blen; i++, src_idx++)
10510  {
10511  b *= NBASE;
10512  a1 *= NBASE;
10513  if (src_idx < arg->ndigits)
10514  a1 += arg->digits[src_idx];
10515  }
10516 
10517  for (i = 0; i < blen; i++, src_idx++)
10518  {
10519  a0 *= NBASE;
10520  if (src_idx < arg->ndigits)
10521  a0 += arg->digits[src_idx];
10522  }
10523 
10524  /* Compute (q,u) = DivRem(r*b + a1, 2*s) */
10525  numer = r_int64 * b + a1;
10526  denom = 2 * s_int64;
10527  q = numer / denom;
10528  u = numer - q * denom;
10529 
10530  /* Compute s = s*b + q and r = u*b + a0 - q^2 */
10531  s_int64 = s_int64 * b + q;
10532  r_int64 = u * b + a0 - q * q;
10533 
10534  if (r_int64 < 0)
10535  {
10536  /* s is too large by 1; set r += s, s--, r += s */
10537  r_int64 += s_int64;
10538  s_int64--;
10539  r_int64 += s_int64;
10540  }
10541 
10542  Assert(src_idx == src_ndigits); /* All input digits consumed */
10543  step--;
10544  }
10545 
10546  /*
10547  * On platforms with 128-bit integer support, we can further delay the
10548  * need to use numeric variables.
10549  */
10550 #ifdef HAVE_INT128
10551  if (step >= 0)
10552  {
10553  int128 s_int128;
10554  int128 r_int128;
10555 
10556  s_int128 = s_int64;
10557  r_int128 = r_int64;
10558 
10559  /*
10560  * Iterations with src_ndigits <= 16:
10561  *
10562  * The result fits in an int128 (even though the input doesn't) so we
10563  * use int128 variables to avoid more expensive numeric computations.
10564  */
10565  while (step >= 0 && (src_ndigits = ndigits[step]) <= 16)
10566  {
10567  int64 b;
10568  int64 a0;
10569  int64 a1;
10570  int64 i;
10571  int128 numer;
10572  int128 denom;
10573  int128 q;
10574  int128 u;
10575 
10576  blen = (src_ndigits - src_idx) / 2;
10577 
10578  /* Extract a1 and a0, and compute b */
10579  a0 = 0;
10580  a1 = 0;
10581  b = 1;
10582 
10583  for (i = 0; i < blen; i++, src_idx++)
10584  {
10585  b *= NBASE;
10586  a1 *= NBASE;
10587  if (src_idx < arg->ndigits)
10588  a1 += arg->digits[src_idx];
10589  }
10590 
10591  for (i = 0; i < blen; i++, src_idx++)
10592  {
10593  a0 *= NBASE;
10594  if (src_idx < arg->ndigits)
10595  a0 += arg->digits[src_idx];
10596  }
10597 
10598  /* Compute (q,u) = DivRem(r*b + a1, 2*s) */
10599  numer = r_int128 * b + a1;
10600  denom = 2 * s_int128;
10601  q = numer / denom;
10602  u = numer - q * denom;
10603 
10604  /* Compute s = s*b + q and r = u*b + a0 - q^2 */
10605  s_int128 = s_int128 * b + q;
10606  r_int128 = u * b + a0 - q * q;
10607 
10608  if (r_int128 < 0)
10609  {
10610  /* s is too large by 1; set r += s, s--, r += s */
10611  r_int128 += s_int128;
10612  s_int128--;
10613  r_int128 += s_int128;
10614  }
10615 
10616  Assert(src_idx == src_ndigits); /* All input digits consumed */
10617  step--;
10618  }
10619 
10620  /*
10621  * All remaining iterations require numeric variables. Convert the
10622  * integer values to NumericVar and continue. Note that in the final
10623  * iteration we don't need the remainder, so we can save a few cycles
10624  * there by not fully computing it.
10625  */
10626  int128_to_numericvar(s_int128, &s_var);
10627  if (step >= 0)
10628  int128_to_numericvar(r_int128, &r_var);
10629  }
10630  else
10631  {
10632  int64_to_numericvar(s_int64, &s_var);
10633  /* step < 0, so we certainly don't need r */
10634  }
10635 #else /* !HAVE_INT128 */
10636  int64_to_numericvar(s_int64, &s_var);
10637  if (step >= 0)
10638  int64_to_numericvar(r_int64, &r_var);
10639 #endif /* HAVE_INT128 */
10640 
10641  /*
10642  * The remaining iterations with src_ndigits > 8 (or 16, if have int128)
10643  * use numeric variables.
10644  */
10645  while (step >= 0)
10646  {
10647  int tmp_len;
10648 
10649  src_ndigits = ndigits[step];
10650  blen = (src_ndigits - src_idx) / 2;
10651 
10652  /* Extract a1 and a0 */
10653  if (src_idx < arg->ndigits)
10654  {
10655  tmp_len = Min(blen, arg->ndigits - src_idx);
10656  alloc_var(&a1_var, tmp_len);
10657  memcpy(a1_var.digits, arg->digits + src_idx,
10658  tmp_len * sizeof(NumericDigit));
10659  a1_var.weight = blen - 1;
10660  a1_var.sign = NUMERIC_POS;
10661  a1_var.dscale = 0;
10662  strip_var(&a1_var);
10663  }
10664  else
10665  {
10666  zero_var(&a1_var);
10667  a1_var.dscale = 0;
10668  }
10669  src_idx += blen;
10670 
10671  if (src_idx < arg->ndigits)
10672  {
10673  tmp_len = Min(blen, arg->ndigits - src_idx);
10674  alloc_var(&a0_var, tmp_len);
10675  memcpy(a0_var.digits, arg->digits + src_idx,
10676  tmp_len * sizeof(NumericDigit));
10677  a0_var.weight = blen - 1;
10678  a0_var.sign = NUMERIC_POS;
10679  a0_var.dscale = 0;
10680  strip_var(&a0_var);
10681  }
10682  else
10683  {
10684  zero_var(&a0_var);
10685  a0_var.dscale = 0;
10686  }
10687  src_idx += blen;
10688 
10689  /* Compute (q,u) = DivRem(r*b + a1, 2*s) */
10690  set_var_from_var(&r_var, &q_var);
10691  q_var.weight += blen;
10692  add_var(&q_var, &a1_var, &q_var);
10693  add_var(&s_var, &s_var, &u_var);
10694  div_mod_var(&q_var, &u_var, &q_var, &u_var);
10695 
10696  /* Compute s = s*b + q */
10697  s_var.weight += blen;
10698  add_var(&s_var, &q_var, &s_var);
10699 
10700  /*
10701  * Compute r = u*b + a0 - q^2.
10702  *
10703  * In the final iteration, we don't actually need r; we just need to
10704  * know whether it is negative, so that we know whether to adjust s.
10705  * So instead of the final subtraction we can just compare.
10706  */
10707  u_var.weight += blen;
10708  add_var(&u_var, &a0_var, &u_var);
10709  mul_var(&q_var, &q_var, &q_var, 0);
10710 
10711  if (step > 0)
10712  {
10713  /* Need r for later iterations */
10714  sub_var(&u_var, &q_var, &r_var);
10715  if (r_var.sign == NUMERIC_NEG)
10716  {
10717  /* s is too large by 1; set r += s, s--, r += s */
10718  add_var(&r_var, &s_var, &r_var);
10719  sub_var(&s_var, &const_one, &s_var);
10720  add_var(&r_var, &s_var, &r_var);
10721  }
10722  }
10723  else
10724  {
10725  /* Don't need r anymore, except to test if s is too large by 1 */
10726  if (cmp_var(&u_var, &q_var) < 0)
10727  sub_var(&s_var, &const_one, &s_var);
10728  }
10729 
10730  Assert(src_idx == src_ndigits); /* All input digits consumed */
10731  step--;
10732  }
10733 
10734  /*
10735  * Construct the final result, rounding it to the requested precision.
10736  */
10737  set_var_from_var(&s_var, result);
10738  result->weight = res_weight;
10739  result->sign = NUMERIC_POS;
10740 
10741  /* Round to target rscale (and set result->dscale) */
10742  round_var(result, rscale);
10743 
10744  /* Strip leading and trailing zeroes */
10745  strip_var(result);
10746 
10747  free_var(&s_var);
10748  free_var(&r_var);
10749  free_var(&a0_var);
10750  free_var(&a1_var);
10751  free_var(&q_var);
10752  free_var(&u_var);
10753 }
static void div_mod_var(const NumericVar *var1, const NumericVar *var2, NumericVar *quot, NumericVar *rem)
Definition: numeric.c:10095
static const FormData_pg_attribute a1
Definition: heap.c:142
int b
Definition: isn.c:70
#define stat
Definition: win32_port.h:284

References a1, add_var(), alloc_var(), arg, Assert, b, cmp_var(), const_one, const_zero, DEC_DIGITS, NumericVar::digits, div_mod_var(), NumericVar::dscale, ereport, errcode(), errmsg(), ERROR, free_var(), i, init_var, int64_to_numericvar(), Max, Min, mul_var(), NBASE, NUMERIC_NEG, NUMERIC_POS, round_var(), set_var_from_var(), NumericVar::sign, stat, strip_var(), sub_var(), NumericVar::weight, and zero_var().

Referenced by ln_var(), numeric_sqrt(), and numeric_stddev_internal().

◆ strip_var()

static void strip_var ( NumericVar var)
static

Definition at line 12139 of file numeric.c.

12140 {
12141  NumericDigit *digits = var->digits;
12142  int ndigits = var->ndigits;
12143 
12144  /* Strip leading zeroes */
12145  while (ndigits > 0 && *digits == 0)
12146  {
12147  digits++;
12148  var->weight--;
12149  ndigits--;
12150  }
12151 
12152  /* Strip trailing zeroes */
12153  while (ndigits > 0 && digits[ndigits - 1] == 0)
12154  ndigits--;
12155 
12156  /* If it's zero, normalize the sign and weight */
12157  if (ndigits == 0)
12158  {
12159  var->sign = NUMERIC_POS;
12160  var->weight = 0;
12161  }
12162 
12163  var->digits = digits;
12164  var->ndigits = ndigits;
12165 }

References NumericVar::digits, digits, NumericVar::ndigits, NUMERIC_POS, NumericVar::sign, and NumericVar::weight.

Referenced by accum_sum_final(), add_abs(), div_var(), div_var_fast(), div_var_int(), mul_var(), mul_var_short(), numericvar_to_int64(), numericvar_to_uint64(), random_var(), set_var_from_str(), sqrt_var(), and sub_abs().

◆ sub_abs()

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

Definition at line 11889 of file numeric.c.

11890 {
11891  NumericDigit *res_buf;
11892  NumericDigit *res_digits;
11893  int res_ndigits;
11894  int res_weight;
11895  int res_rscale,
11896  rscale1,
11897  rscale2;
11898  int res_dscale;
11899  int i,
11900  i1,
11901  i2;
11902  int borrow = 0;
11903 
11904  /* copy these values into local vars for speed in inner loop */
11905  int var1ndigits = var1->ndigits;
11906  int var2ndigits = var2->ndigits;
11907  NumericDigit *var1digits = var1->digits;
11908  NumericDigit *var2digits = var2->digits;
11909 
11910  res_weight = var1->weight;
11911 
11912  res_dscale = Max(var1->dscale, var2->dscale);
11913 
11914  /* Note: here we are figuring rscale in base-NBASE digits */
11915  rscale1 = var1->ndigits - var1->weight - 1;
11916  rscale2 = var2->ndigits - var2->weight - 1;
11917  res_rscale = Max(rscale1, rscale2);
11918 
11919  res_ndigits = res_rscale + res_weight + 1;
11920  if (res_ndigits <= 0)
11921  res_ndigits = 1;
11922 
11923  res_buf = digitbuf_alloc(res_ndigits + 1);
11924  res_buf[0] = 0; /* spare digit for later rounding */
11925  res_digits = res_buf + 1;
11926 
11927  i1 = res_rscale + var1->weight + 1;
11928  i2 = res_rscale + var2->weight + 1;
11929  for (i = res_ndigits - 1; i >= 0; i--)
11930  {
11931  i1--;
11932  i2--;
11933  if (i1 >= 0 && i1 < var1ndigits)
11934  borrow += var1digits[i1];
11935  if (i2 >= 0 && i2 < var2ndigits)
11936  borrow -= var2digits[i2];
11937 
11938  if (borrow < 0)
11939  {
11940  res_digits[i] = borrow + NBASE;
11941  borrow = -1;
11942  }
11943  else
11944  {
11945  res_digits[i] = borrow;
11946  borrow = 0;
11947  }
11948  }
11949 
11950  Assert(borrow == 0); /* else caller gave us var1 < var2 */
11951 
11952  digitbuf_free(result->buf);
11953  result->ndigits = res_ndigits;
11954  result->buf = res_buf;
11955  result->digits = res_digits;
11956  result->weight = res_weight;
11957  result->dscale = res_dscale;
11958 
11959  /* Remove leading/trailing zeroes */
11960  strip_var(result);
11961 }

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

◆ sub_var()

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

Definition at line 8552 of file numeric.c.

8553 {
8554  /*
8555  * Decide on the signs of the two variables what to do
8556  */
8557  if (var1->sign == NUMERIC_POS)
8558  {
8559  if (var2->sign == NUMERIC_NEG)
8560  {
8561  /* ----------
8562  * var1 is positive, var2 is negative
8563  * result = +(ABS(var1) + ABS(var2))
8564  * ----------
8565  */
8566  add_abs(var1, var2, result);
8567  result->sign = NUMERIC_POS;
8568  }
8569  else
8570  {
8571  /* ----------
8572  * Both are positive
8573  * Must compare absolute values
8574  * ----------
8575  */
8576  switch (cmp_abs(var1, var2))
8577  {
8578  case 0:
8579  /* ----------
8580  * ABS(var1) == ABS(var2)
8581  * result = ZERO
8582  * ----------
8583  */
8584  zero_var(result);
8585  result->dscale = Max(var1->dscale, var2->dscale);
8586  break;
8587 
8588  case 1:
8589  /* ----------
8590  * ABS(var1) > ABS(var2)
8591  * result = +(ABS(var1) - ABS(var2))
8592  * ----------
8593  */
8594  sub_abs(var1, var2, result);
8595  result->sign = NUMERIC_POS;
8596  break;
8597 
8598  case -1:
8599  /* ----------
8600  * ABS(var1) < ABS(var2)
8601  * result = -(ABS(var2) - ABS(var1))
8602  * ----------
8603  */
8604  sub_abs(var2, var1, result);
8605  result->sign = NUMERIC_NEG;
8606  break;
8607  }
8608  }
8609  }
8610  else
8611  {
8612  if (var2->sign == NUMERIC_NEG)
8613  {
8614  /* ----------
8615  * Both are negative
8616  * Must compare absolute values
8617  * ----------
8618  */
8619  switch (cmp_abs(var1, var2))
8620  {
8621  case 0:
8622  /* ----------
8623  * ABS(var1) == ABS(var2)
8624  * result = ZERO
8625  * ----------
8626  */
8627  zero_var(result);
8628  result->dscale = Max(var1->dscale, var2->dscale);
8629  break;
8630 
8631  case 1:
8632  /* ----------
8633  * ABS(var1) > ABS(var2)
8634  * result = -(ABS(var1) - ABS(var2))
8635  * ----------
8636  */
8637  sub_abs(var1, var2, result);
8638  result->sign = NUMERIC_NEG;
8639  break;
8640 
8641  case -1:
8642  /* ----------
8643  * ABS(var1) < ABS(var2)
8644  * result = +(ABS(var2) - ABS(var1))
8645  * ----------
8646  */
8647  sub_abs(var2, var1, result);
8648  result->sign = NUMERIC_POS;
8649  break;
8650  }
8651  }
8652  else
8653  {
8654  /* ----------
8655  * var1 is negative, var2 is positive
8656  * result = -(ABS(var1) + ABS(var2))
8657  * ----------
8658  */
8659  add_abs(var1, var2, result);
8660  result->sign = NUMERIC_NEG;
8661  }
8662  }
8663 }

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

Referenced by compute_bucket(), div_mod_var(), estimate_ln_dweight(), floor_var(), in_range_numeric_numeric(), ln_var(), mod_var(), numeric_stddev_internal(), numeric_sub_opt_error(), random_var(), and sqrt_var().

◆ trunc_var()

static void trunc_var ( NumericVar var,
int  rscale 
)
static

Definition at line 12077 of file numeric.c.

12078 {
12079  int di;
12080  int ndigits;
12081 
12082  var->dscale = rscale;
12083 
12084  /* decimal digits wanted */
12085  di = (var->weight + 1) * DEC_DIGITS + rscale;
12086 
12087  /*
12088  * If di <= 0, the value loses all digits.
12089  */
12090  if (di <= 0)
12091  {
12092  var->ndigits = 0;
12093  var->weight = 0;
12094  var->sign = NUMERIC_POS;
12095  }
12096  else
12097  {
12098  /* NBASE digits wanted */
12099  ndigits = (di + DEC_DIGITS - 1) / DEC_DIGITS;
12100 
12101  if (ndigits <= var->ndigits)
12102  {
12103  var->ndigits = ndigits;
12104 
12105 #if DEC_DIGITS == 1
12106  /* no within-digit stuff to worry about */
12107 #else
12108  /* 0, or number of decimal digits to keep in last NBASE digit */
12109  di %= DEC_DIGITS;
12110 
12111  if (di > 0)
12112  {
12113  /* Must truncate within last NBASE digit */
12114  NumericDigit *digits = var->digits;
12115  int extra,
12116  pow10;
12117 
12118 #if DEC_DIGITS == 4
12119  pow10 = round_powers[di];
12120 #elif DEC_DIGITS == 2
12121  pow10 = 10;
12122 #else
12123 #error unsupported NBASE
12124 #endif
12125  extra = digits[--ndigits] % pow10;
12126  digits[ndigits] -= extra;
12127  }
12128 #endif
12129  }
12130  }
12131 }

References DEC_DIGITS, NumericVar::digits, digits, NumericVar::dscale, NumericVar::ndigits, NUMERIC_POS, round_powers, NumericVar::sign, and NumericVar::weight.

Referenced by ceil_var(), div_var(), div_var_fast(), div_var_int(), floor_var(), numeric_recv(), and numeric_trunc().

◆ width_bucket_numeric()

Datum width_bucket_numeric ( PG_FUNCTION_ARGS  )

Definition at line 1846 of file numeric.c.

1847 {
1848  Numeric operand = PG_GETARG_NUMERIC(0);
1849  Numeric bound1 = PG_GETARG_NUMERIC(1);
1850  Numeric bound2 = PG_GETARG_NUMERIC(2);
1851  int32 count = PG_GETARG_INT32(3);
1852  NumericVar count_var;
1853  NumericVar result_var;
1854  int32 result;
1855 
1856  if (count <= 0)
1857  ereport(ERROR,
1858  (errcode(ERRCODE_INVALID_ARGUMENT_FOR_WIDTH_BUCKET_FUNCTION),
1859  errmsg("count must be greater than zero")));
1860 
1861  if (NUMERIC_IS_SPECIAL(operand) ||
1862  NUMERIC_IS_SPECIAL(bound1) ||
1863  NUMERIC_IS_SPECIAL(bound2))
1864  {
1865  if (NUMERIC_IS_NAN(operand) ||
1866  NUMERIC_IS_NAN(bound1) ||
1867  NUMERIC_IS_NAN(bound2))
1868  ereport(ERROR,
1869  (errcode(ERRCODE_INVALID_ARGUMENT_FOR_WIDTH_BUCKET_FUNCTION),
1870  errmsg("operand, lower bound, and upper bound cannot be NaN")));
1871  /* We allow "operand" to be infinite; cmp_numerics will cope */
1872  if (NUMERIC_IS_INF(bound1) || NUMERIC_IS_INF(bound2))
1873  ereport(ERROR,
1874  (errcode(ERRCODE_INVALID_ARGUMENT_FOR_WIDTH_BUCKET_FUNCTION),
1875  errmsg("lower and upper bounds must be finite")));
1876  }
1877 
1878  init_var(&result_var);
1879  init_var(&count_var);
1880 
1881  /* Convert 'count' to a numeric, for ease of use later */
1882  int64_to_numericvar((int64) count, &count_var);
1883 
1884  switch (cmp_numerics(bound1, bound2))
1885  {
1886  case 0:
1887  ereport(ERROR,
1888  (errcode(ERRCODE_INVALID_ARGUMENT_FOR_WIDTH_BUCKET_FUNCTION),
1889  errmsg("lower bound cannot equal upper bound")));
1890  break;
1891 
1892  /* bound1 < bound2 */
1893  case -1:
1894  if (cmp_numerics(operand, bound1) < 0)
1895  set_var_from_var(&const_zero, &result_var);
1896  else if (cmp_numerics(operand, bound2) >= 0)
1897  add_var(&count_var, &const_one, &result_var);
1898  else
1899  compute_bucket(operand, bound1, bound2, &count_var,
1900  &result_var);
1901  break;
1902 
1903  /* bound1 > bound2 */
1904  case 1:
1905  if (cmp_numerics(operand, bound1) > 0)
1906  set_var_from_var(&const_zero, &result_var);
1907  else if (cmp_numerics(operand, bound2) <= 0)
1908  add_var(&count_var, &const_one, &result_var);
1909  else
1910  compute_bucket(operand, bound1, bound2, &count_var,
1911  &result_var);
1912  break;
1913  }
1914 
1915  /* if result exceeds the range of a legal int4, we ereport here */
1916  if (!numericvar_to_int32(&result_var, &result))
1917  ereport(ERROR,
1918  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1919  errmsg("integer out of range")));
1920 
1921  free_var(&count_var);
1922  free_var(&result_var);
1923 
1924  PG_RETURN_INT32(result);
1925 }
static void compute_bucket(Numeric operand, Numeric bound1, Numeric bound2, const NumericVar *count_var, NumericVar *result_var)
Definition: numeric.c:1934

References add_var(), cmp_numerics(), compute_bucket(), const_one, const_zero, ereport, errcode(), errmsg(), ERROR, free_var(), init_var, int64_to_numericvar(), NUMERIC_IS_INF, NUMERIC_IS_NAN, NUMERIC_IS_SPECIAL, numericvar_to_int32(), PG_GETARG_INT32, PG_GETARG_NUMERIC, PG_RETURN_INT32, and set_var_from_var().

◆ xdigit_value()

static int xdigit_value ( char  dig)
inlinestatic

Definition at line 7219 of file numeric.c.

7220 {
7221  return dig >= '0' && dig <= '9' ? dig - '0' :
7222  dig >= 'a' && dig <= 'f' ? dig - 'a' + 10 :
7223  dig >= 'A' && dig <= 'F' ? dig - 'A' + 10 : -1;
7224 }

Referenced by set_var_from_non_decimal_integer_str().

◆ zero_var()

static void zero_var ( NumericVar var)
static

Definition at line 6989 of file numeric.c.

6990 {
6991  digitbuf_free(var->buf);
6992  var->buf = NULL;
6993  var->digits = NULL;
6994  var->ndigits = 0;
6995  var->weight = 0; /* by convention; doesn't really matter */
6996  var->sign = NUMERIC_POS; /* anything but NAN... */
6997 }

References NumericVar::buf, digitbuf_free, NumericVar::digits, NumericVar::ndigits, NUMERIC_POS, NumericVar::sign, and NumericVar::weight.

Referenced by add_var(), div_var(), div_var_fast(), div_var_int(), exp_var(), mul_var(), power_var(), power_var_int(), set_var_from_non_decimal_integer_str(), sqrt_var(), and sub_var().

Variable Documentation

◆ const_minus_one

const NumericVar const_minus_one
static
Initial value:
=
static const NumericDigit const_one_data[1]
Definition: numeric.c:425

Definition at line 429 of file numeric.c.

Referenced by numeric_power(), and numeric_sign().

◆ const_nan

◆ const_ninf

◆ const_one

◆ const_one_data

const NumericDigit const_one_data[1] = {1}
static

Definition at line 425 of file numeric.c.

◆ const_one_point_one

const NumericVar const_one_point_one
static
Initial value:
=
static const NumericDigit const_one_point_one_data[2]
Definition: numeric.c:447

Definition at line 453 of file numeric.c.

Referenced by estimate_ln_dweight(), and ln_var().

◆ const_one_point_one_data

const NumericDigit const_one_point_one_data[2] = {1, 1000}
static

Definition at line 447 of file numeric.c.

◆ const_pinf

◆ const_two

const NumericVar const_two
static
Initial value:
=
static const NumericDigit const_two_data[1]
Definition: numeric.c:432

Definition at line 433 of file numeric.c.

Referenced by ln_var().

◆ const_two_data

const NumericDigit const_two_data[1] = {2}
static

Definition at line 432 of file numeric.c.

◆ const_zero

◆ const_zero_data

const NumericDigit const_zero_data[1] = {0}
static

Definition at line 421 of file numeric.c.

◆ const_zero_point_nine

const NumericVar const_zero_point_nine
static
Initial value:
=
static const NumericDigit const_zero_point_nine_data[1]
Definition: numeric.c:437

Definition at line 443 of file numeric.c.

Referenced by estimate_ln_dweight(), and ln_var().

◆ const_zero_point_nine_data

const NumericDigit const_zero_point_nine_data[1] = {9000}
static

Definition at line 437 of file numeric.c.

◆ round_powers

const int round_powers[4] = {0, 1000, 100, 10}
static

Definition at line 466 of file numeric.c.

Referenced by round_var(), and trunc_var().