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

Go to the source code of this file.

Data Structures

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

Macros

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

Typedefs

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

Functions

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

Variables

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

Macro Definition Documentation

◆ DatumGetNumericAbbrev

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

Definition at line 403 of file numeric.c.

◆ DEC_DIGITS

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

Definition at line 97 of file numeric.c.

◆ digitbuf_alloc

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

Definition at line 476 of file numeric.c.

◆ digitbuf_free

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

Definition at line 478 of file numeric.c.

◆ DIV_GUARD_DIGITS

#define DIV_GUARD_DIGITS   4

Definition at line 99 of file numeric.c.

◆ dump_numeric

#define dump_numeric (   s,
 
)

Definition at line 472 of file numeric.c.

◆ dump_var

#define dump_var (   s,
 
)

Definition at line 473 of file numeric.c.

◆ HALF_NBASE

#define HALF_NBASE   5000

Definition at line 96 of file numeric.c.

◆ init_var

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

Definition at line 484 of file numeric.c.

◆ makePolyNumAggState

#define makePolyNumAggState   makeNumericAggState

Definition at line 5545 of file numeric.c.

◆ makePolyNumAggStateCurrentContext

#define makePolyNumAggStateCurrentContext   makeNumericAggStateCurrentContext

Definition at line 5546 of file numeric.c.

◆ MUL_GUARD_DIGITS

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

Definition at line 98 of file numeric.c.

◆ NA_TOTAL_COUNT

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

Definition at line 4809 of file numeric.c.

◆ NBASE

#define NBASE   10000

Definition at line 95 of file numeric.c.

◆ NUMERIC_ABBREV_BITS

#define NUMERIC_ABBREV_BITS   (SIZEOF_DATUM * BITS_PER_BYTE)

Definition at line 394 of file numeric.c.

◆ NUMERIC_ABBREV_NAN

#define NUMERIC_ABBREV_NAN   NumericAbbrevGetDatum(PG_INT32_MIN)

Definition at line 404 of file numeric.c.

◆ NUMERIC_ABBREV_NINF

#define NUMERIC_ABBREV_NINF   NumericAbbrevGetDatum(PG_INT32_MAX)

Definition at line 406 of file numeric.c.

◆ NUMERIC_ABBREV_PINF

#define NUMERIC_ABBREV_PINF   NumericAbbrevGetDatum(-PG_INT32_MAX)

Definition at line 405 of file numeric.c.

◆ NUMERIC_CAN_BE_SHORT

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

Definition at line 490 of file numeric.c.

◆ NUMERIC_DIGITS

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

Definition at line 486 of file numeric.c.

◆ NUMERIC_DSCALE

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

Definition at line 242 of file numeric.c.

◆ NUMERIC_DSCALE_MASK

#define NUMERIC_DSCALE_MASK   0x3FFF

Definition at line 233 of file numeric.c.

◆ NUMERIC_DSCALE_MAX

#define NUMERIC_DSCALE_MAX   NUMERIC_DSCALE_MASK

Definition at line 234 of file numeric.c.

◆ NUMERIC_EXT_FLAGBITS

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

Definition at line 202 of file numeric.c.

◆ NUMERIC_EXT_SIGN_MASK

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

Definition at line 196 of file numeric.c.

◆ NUMERIC_FLAGBITS

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

Definition at line 170 of file numeric.c.

◆ NUMERIC_HDRSZ

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

Definition at line 174 of file numeric.c.

◆ NUMERIC_HDRSZ_SHORT

#define NUMERIC_HDRSZ_SHORT   (VARHDRSZ + sizeof(uint16))

Definition at line 175 of file numeric.c.

◆ NUMERIC_HEADER_IS_SHORT

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

Definition at line 182 of file numeric.c.

◆ NUMERIC_HEADER_SIZE

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

Definition at line 183 of file numeric.c.

◆ NUMERIC_INF_SIGN_MASK

#define NUMERIC_INF_SIGN_MASK   0x2000

Definition at line 200 of file numeric.c.

◆ NUMERIC_IS_INF

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

Definition at line 206 of file numeric.c.

◆ NUMERIC_IS_NAN

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

Definition at line 203 of file numeric.c.

◆ NUMERIC_IS_NINF

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

Definition at line 205 of file numeric.c.

◆ NUMERIC_IS_PINF

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

Definition at line 204 of file numeric.c.

◆ NUMERIC_IS_SHORT

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

Definition at line 171 of file numeric.c.

◆ NUMERIC_IS_SPECIAL

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

Definition at line 172 of file numeric.c.

◆ NUMERIC_NAN

#define NUMERIC_NAN   0xC000

Definition at line 197 of file numeric.c.

◆ NUMERIC_NDIGITS

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

Definition at line 488 of file numeric.c.

◆ NUMERIC_NEG

#define NUMERIC_NEG   0x4000

Definition at line 166 of file numeric.c.

◆ NUMERIC_NINF

#define NUMERIC_NINF   0xF000

Definition at line 199 of file numeric.c.

◆ NUMERIC_PINF

#define NUMERIC_PINF   0xD000

Definition at line 198 of file numeric.c.

◆ NUMERIC_POS

#define NUMERIC_POS   0x0000

Definition at line 165 of file numeric.c.

◆ NUMERIC_SHORT

#define NUMERIC_SHORT   0x8000

Definition at line 167 of file numeric.c.

◆ NUMERIC_SHORT_DSCALE_MASK

#define NUMERIC_SHORT_DSCALE_MASK   0x1F80

Definition at line 214 of file numeric.c.

◆ NUMERIC_SHORT_DSCALE_MAX

#define NUMERIC_SHORT_DSCALE_MAX    (NUMERIC_SHORT_DSCALE_MASK >> NUMERIC_SHORT_DSCALE_SHIFT)

Definition at line 216 of file numeric.c.

◆ NUMERIC_SHORT_DSCALE_SHIFT

#define NUMERIC_SHORT_DSCALE_SHIFT   7

Definition at line 215 of file numeric.c.

◆ NUMERIC_SHORT_SIGN_MASK

#define NUMERIC_SHORT_SIGN_MASK   0x2000

Definition at line 213 of file numeric.c.

◆ NUMERIC_SHORT_WEIGHT_MASK

#define NUMERIC_SHORT_WEIGHT_MASK   0x003F

Definition at line 219 of file numeric.c.

◆ NUMERIC_SHORT_WEIGHT_MAX

#define NUMERIC_SHORT_WEIGHT_MAX   NUMERIC_SHORT_WEIGHT_MASK

Definition at line 220 of file numeric.c.

◆ NUMERIC_SHORT_WEIGHT_MIN

#define NUMERIC_SHORT_WEIGHT_MIN   (-(NUMERIC_SHORT_WEIGHT_MASK+1))

Definition at line 221 of file numeric.c.

◆ NUMERIC_SHORT_WEIGHT_SIGN_MASK

#define NUMERIC_SHORT_WEIGHT_SIGN_MASK   0x0040

Definition at line 218 of file numeric.c.

◆ NUMERIC_SIGN

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

Definition at line 236 of file numeric.c.

◆ NUMERIC_SIGN_MASK

#define NUMERIC_SIGN_MASK   0xC000

Definition at line 164 of file numeric.c.

◆ NUMERIC_SPECIAL

#define NUMERIC_SPECIAL   0xC000

Definition at line 168 of file numeric.c.

◆ NUMERIC_WEIGHT

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

Definition at line 246 of file numeric.c.

◆ NumericAbbrevGetDatum

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

Definition at line 402 of file numeric.c.

Typedef Documentation

◆ Int8TransTypeData

◆ NumericAggState

◆ NumericDigit

Definition at line 101 of file numeric.c.

◆ NumericSumAccum

◆ NumericVar

typedef struct NumericVar NumericVar

◆ PolyNumAggState

Definition at line 5544 of file numeric.c.

Function Documentation

◆ accum_sum_add()

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

Definition at line 11974 of file numeric.c.

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

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

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

◆ accum_sum_carry()

static void accum_sum_carry ( NumericSumAccum accum)
static

Definition at line 12022 of file numeric.c.

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

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

Referenced by accum_sum_add(), and accum_sum_final().

◆ accum_sum_combine()

static void accum_sum_combine ( NumericSumAccum accum,
NumericSumAccum accum2 
)
static

Definition at line 12252 of file numeric.c.

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

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

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

◆ accum_sum_copy()

static void accum_sum_copy ( NumericSumAccum dst,
NumericSumAccum src 
)
static

Definition at line 12235 of file numeric.c.

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

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

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

◆ accum_sum_final()

static void accum_sum_final ( NumericSumAccum accum,
NumericVar result 
)
static

Definition at line 12184 of file numeric.c.

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

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

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

◆ accum_sum_rescale()

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

Definition at line 12095 of file numeric.c.

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

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

Referenced by accum_sum_add().

◆ accum_sum_reset()

static void accum_sum_reset ( NumericSumAccum accum)
static

Definition at line 11958 of file numeric.c.

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

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

Referenced by do_numeric_discard().

◆ add_abs()

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

Definition at line 11582 of file numeric.c.

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

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

Referenced by add_var(), and sub_var().

◆ add_var()

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

Definition at line 8431 of file numeric.c.

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

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

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

◆ alloc_var()

static void alloc_var ( NumericVar var,
int  ndigits 
)
static

Definition at line 6953 of file numeric.c.

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

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

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

◆ apply_typmod()

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

Definition at line 7907 of file numeric.c.

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

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

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

◆ apply_typmod_special()

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

Definition at line 7992 of file numeric.c.

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

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

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

◆ ceil_var()

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

Definition at line 9945 of file numeric.c.

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

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

Referenced by numeric_ceil().

◆ cmp_abs()

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

Definition at line 11504 of file numeric.c.

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

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

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

◆ cmp_abs_common()

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

Definition at line 11518 of file numeric.c.

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

Referenced by cmp_abs(), and cmp_var_common().

◆ cmp_numerics()

static int cmp_numerics ( Numeric  num1,
Numeric  num2 
)
static

Definition at line 2505 of file numeric.c.

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

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

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

◆ cmp_var()

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

◆ cmp_var_common()

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

Definition at line 8388 of file numeric.c.

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

References cmp_abs_common(), NUMERIC_NEG, and NUMERIC_POS.

Referenced by cmp_numerics(), and cmp_var().

◆ compute_bucket()

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

Definition at line 1917 of file numeric.c.

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

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

Referenced by width_bucket_numeric().

◆ div_mod_var()

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

Definition at line 9875 of file numeric.c.

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

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

Referenced by sqrt_var().

◆ div_var()

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

Definition at line 8877 of file numeric.c.

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

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

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

◆ div_var_fast()

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

Definition at line 9185 of file numeric.c.

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

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

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

◆ div_var_int()

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

Definition at line 9549 of file numeric.c.

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

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

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

◆ do_numeric_accum()

static void do_numeric_accum ( NumericAggState state,
Numeric  newval 
)
static

Definition at line 4857 of file numeric.c.

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

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

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

◆ do_numeric_discard()

static bool do_numeric_discard ( NumericAggState state,
Numeric  newval 
)
static

Definition at line 4927 of file numeric.c.

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

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

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

◆ duplicate_numeric()

static Numeric duplicate_numeric ( Numeric  num)
static

Definition at line 7763 of file numeric.c.

7764 {
7765  Numeric res;
7766 
7767  res = (Numeric) palloc(VARSIZE(num));
7768  memcpy(res, num, VARSIZE(num));
7769  return res;
7770 }
struct NumericData * Numeric
Definition: numeric.h:54
#define VARSIZE(PTR)
Definition: varatt.h:279

References palloc(), res, and VARSIZE.

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

◆ estimate_ln_dweight()

static int estimate_ln_dweight ( const NumericVar var)
static

Definition at line 10671 of file numeric.c.

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

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

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

◆ exp_var()

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

Definition at line 10542 of file numeric.c.

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

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

Referenced by numeric_exp(), and power_var().

◆ float4_numeric()

Datum float4_numeric ( PG_FUNCTION_ARGS  )

Definition at line 4687 of file numeric.c.

4688 {
4690  Numeric res;
4691  NumericVar result;
4692  char buf[FLT_DIG + 100];
4693  const char *endptr;
4694 
4695  if (isnan(val))
4697 
4698  if (isinf(val))
4699  {
4700  if (val < 0)
4702  else
4704  }
4705 
4706  snprintf(buf, sizeof(buf), "%.*g", FLT_DIG, val);
4707 
4708  init_var(&result);
4709 
4710  /* Assume we need not worry about leading/trailing spaces */
4711  (void) set_var_from_str(buf, buf, &result, &endptr, NULL);
4712 
4713  res = make_result(&result);
4714 
4715  free_var(&result);
4716 
4718 }
static const NumericVar const_pinf
Definition: numeric.c:452
static const NumericVar const_ninf
Definition: numeric.c:455
static bool set_var_from_str(const char *str, const char *cp, NumericVar *dest, const char **endptr, Node *escontext)
Definition: numeric.c:7012
static Numeric make_result(const NumericVar *var)
Definition: numeric.c:7891
static const NumericVar const_nan
Definition: numeric.c:449
float float4
Definition: c.h:616
#define PG_GETARG_FLOAT4(n)
Definition: fmgr.h:281
#define PG_RETURN_NUMERIC(x)
Definition: numeric.h:80
#define snprintf
Definition: port.h:238

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

Referenced by JsonItemFromDatum().

◆ float8_numeric()

Datum float8_numeric ( PG_FUNCTION_ARGS  )

Definition at line 4593 of file numeric.c.

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

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

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

◆ floor_var()

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

Definition at line 9969 of file numeric.c.

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

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

Referenced by compute_bucket(), and numeric_floor().

◆ free_var()

static void free_var ( NumericVar var)
static

Definition at line 6969 of file numeric.c.

6970 {
6971  digitbuf_free(var->buf);
6972  var->buf = NULL;
6973  var->digits = NULL;
6974  var->sign = NUMERIC_NAN;
6975 }
#define NUMERIC_NAN
Definition: numeric.c:197

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

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

◆ gcd_var()

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

Definition at line 9992 of file numeric.c.

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

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

Referenced by numeric_gcd(), and numeric_lcm().

◆ generate_series_numeric()

Datum generate_series_numeric ( PG_FUNCTION_ARGS  )

Definition at line 1686 of file numeric.c.

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

References generate_series_step_numeric().

◆ generate_series_step_numeric()

Datum generate_series_step_numeric ( PG_FUNCTION_ARGS  )

Definition at line 1692 of file numeric.c.

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

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

Referenced by generate_series_numeric().

◆ get_min_scale()

static int get_min_scale ( NumericVar var)
static

Definition at line 4136 of file numeric.c.

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

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

Referenced by numeric_min_scale(), and numeric_trim_scale().

◆ get_str_from_var()

static char * get_str_from_var ( const NumericVar var)
static

Definition at line 7494 of file numeric.c.

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

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

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

◆ get_str_from_var_sci()

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

Definition at line 7647 of file numeric.c.

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

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

Referenced by numeric_out_sci().

◆ hash_numeric()

Datum hash_numeric ( PG_FUNCTION_ARGS  )

Definition at line 2697 of file numeric.c.

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

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

Referenced by JsonbHashScalarValue().

◆ hash_numeric_extended()

Datum hash_numeric_extended ( PG_FUNCTION_ARGS  )

Definition at line 2777 of file numeric.c.

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

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

Referenced by JsonbHashScalarValueExtended().

◆ in_range_numeric_numeric()

Datum in_range_numeric_numeric ( PG_FUNCTION_ARGS  )

Definition at line 2562 of file numeric.c.

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

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

◆ init_var_from_num()

◆ int2_accum()

Datum int2_accum ( PG_FUNCTION_ARGS  )

Definition at line 5550 of file numeric.c.

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

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

◆ int2_accum_inv()

Datum int2_accum_inv ( PG_FUNCTION_ARGS  )

Definition at line 5974 of file numeric.c.

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

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

◆ int2_avg_accum()

Datum int2_avg_accum ( PG_FUNCTION_ARGS  )

Definition at line 6657 of file numeric.c.

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

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

◆ int2_avg_accum_inv()

Datum int2_avg_accum_inv ( PG_FUNCTION_ARGS  )

Definition at line 6744 of file numeric.c.

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

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

◆ int2_numeric()

Datum int2_numeric ( PG_FUNCTION_ARGS  )

Definition at line 4544 of file numeric.c.

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

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

Referenced by JsonItemFromDatum().

◆ int2_sum()

Datum int2_sum ( PG_FUNCTION_ARGS  )

Definition at line 6508 of file numeric.c.

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

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

◆ int2int4_sum()

Datum int2int4_sum ( PG_FUNCTION_ARGS  )

Definition at line 6827 of file numeric.c.

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

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

◆ int4_accum()

Datum int4_accum ( PG_FUNCTION_ARGS  )

Definition at line 5573 of file numeric.c.

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

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

◆ int4_accum_inv()

Datum int4_accum_inv ( PG_FUNCTION_ARGS  )

Definition at line 5999 of file numeric.c.

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

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

◆ int4_avg_accum()

Datum int4_avg_accum ( PG_FUNCTION_ARGS  )

Definition at line 6685 of file numeric.c.

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

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

◆ int4_avg_accum_inv()

Datum int4_avg_accum_inv ( PG_FUNCTION_ARGS  )

Definition at line 6772 of file numeric.c.

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

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

◆ int4_avg_combine()

Datum int4_avg_combine ( PG_FUNCTION_ARGS  )

Definition at line 6713 of file numeric.c.

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

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

◆ int4_numeric()

Datum int4_numeric ( PG_FUNCTION_ARGS  )

Definition at line 4389 of file numeric.c.

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

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

Referenced by executeItemOptUnwrapTarget(), and JsonItemFromDatum().

◆ int4_sum()

Datum int4_sum ( PG_FUNCTION_ARGS  )

Definition at line 6557 of file numeric.c.

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

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

◆ int64_div_fast_to_numeric()

Numeric int64_div_fast_to_numeric ( int64  val1,
int  log10val2 
)

Definition at line 4304 of file numeric.c.

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

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

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

◆ int64_to_numeric()

◆ int64_to_numericvar()

static void int64_to_numericvar ( int64  val,
NumericVar var 
)
static

Definition at line 8104 of file numeric.c.

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

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

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

◆ int8_accum()

Datum int8_accum ( PG_FUNCTION_ARGS  )

Definition at line 5596 of file numeric.c.

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

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

◆ int8_accum_inv()

Datum int8_accum_inv ( PG_FUNCTION_ARGS  )

Definition at line 6024 of file numeric.c.

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

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

◆ int8_avg()

Datum int8_avg ( PG_FUNCTION_ARGS  )

Definition at line 6800 of file numeric.c.

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

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

◆ int8_avg_accum()

Datum int8_avg_accum ( PG_FUNCTION_ARGS  )

Definition at line 5792 of file numeric.c.

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

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

◆ int8_avg_accum_inv()

Datum int8_avg_accum_inv ( PG_FUNCTION_ARGS  )

Definition at line 6045 of file numeric.c.

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

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

◆ int8_avg_combine()

Datum int8_avg_combine ( PG_FUNCTION_ARGS  )

Definition at line 5819 of file numeric.c.

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

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

◆ int8_avg_deserialize()

Datum int8_avg_deserialize ( PG_FUNCTION_ARGS  )

Definition at line 5928 of file numeric.c.

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

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

4478 {
4479  int64 val = PG_GETARG_INT64(0);
4480 
4482 }

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

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

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

908 {
909  return typmod >= (int32) VARHDRSZ;
910 }

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

10754 {
10755  NumericVar x;
10756  NumericVar xx;
10757  int ni;
10758  NumericVar elem;
10759  NumericVar fact;
10760  int nsqrt;
10761  int local_rscale;
10762  int cmp;
10763 
10764  cmp = cmp_var(arg, &const_zero);
10765  if (cmp == 0)
10766  ereport(ERROR,
10767  (errcode(ERRCODE_INVALID_ARGUMENT_FOR_LOG),
10768  errmsg("cannot take logarithm of zero")));
10769  else if (cmp < 0)
10770  ereport(ERROR,
10771  (errcode(ERRCODE_INVALID_ARGUMENT_FOR_LOG),
10772  errmsg("cannot take logarithm of a negative number")));
10773 
10774  init_var(&x);
10775  init_var(&xx);
10776  init_var(&elem);
10777  init_var(&fact);
10778 
10779  set_var_from_var(arg, &x);
10780  set_var_from_var(&const_two, &fact);
10781 
10782  /*
10783  * Reduce input into range 0.9 < x < 1.1 with repeated sqrt() operations.
10784  *
10785  * The final logarithm will have up to around rscale+6 significant digits.
10786  * Each sqrt() will roughly halve the weight of x, so adjust the local
10787  * rscale as we work so that we keep this many significant digits at each
10788  * step (plus a few more for good measure).
10789  *
10790  * Note that we allow local_rscale < 0 during this input reduction
10791  * process, which implies rounding before the decimal point. sqrt_var()
10792  * explicitly supports this, and it significantly reduces the work
10793  * required to reduce very large inputs to the required range. Once the
10794  * input reduction is complete, x.weight will be 0 and its display scale
10795  * will be non-negative again.
10796  */
10797  nsqrt = 0;
10798  while (cmp_var(&x, &const_zero_point_nine) <= 0)
10799  {
10800  local_rscale = rscale - x.weight * DEC_DIGITS / 2 + 8;
10801  sqrt_var(&x, &x, local_rscale);
10802  mul_var(&fact, &const_two, &fact, 0);
10803  nsqrt++;
10804  }
10805  while (cmp_var(&x, &const_one_point_one) >= 0)
10806  {
10807  local_rscale = rscale - x.weight * DEC_DIGITS / 2 + 8;
10808  sqrt_var(&x, &x, local_rscale);
10809  mul_var(&fact, &const_two, &fact, 0);
10810  nsqrt++;
10811  }
10812 
10813  /*
10814  * We use the Taylor series for 0.5 * ln((1+z)/(1-z)),
10815  *
10816  * z + z^3/3 + z^5/5 + ...
10817  *
10818  * where z = (x-1)/(x+1) is in the range (approximately) -0.053 .. 0.048
10819  * due to the above range-reduction of x.
10820  *
10821  * The convergence of this is not as fast as one would like, but is
10822  * tolerable given that z is small.
10823  *
10824  * The Taylor series result will be multiplied by 2^(nsqrt+1), which has a
10825  * decimal weight of (nsqrt+1) * log10(2), so work with this many extra
10826  * digits of precision (plus a few more for good measure).
10827  */
10828  local_rscale = rscale + (int) ((nsqrt + 1) * 0.301029995663981) + 8;
10829 
10830  sub_var(&x, &const_one, result);
10831  add_var(&x, &const_one, &elem);
10832  div_var_fast(result, &elem, result, local_rscale, true);
10833  set_var_from_var(result, &xx);
10834  mul_var(result, result, &x, local_rscale);
10835 
10836  ni = 1;
10837 
10838  for (;;)
10839  {
10840  ni += 2;
10841  mul_var(&xx, &x, &xx, local_rscale);
10842  div_var_int(&xx, ni, 0, &elem, local_rscale, true);
10843 
10844  if (elem.ndigits == 0)
10845  break;
10846 
10847  add_var(result, &elem, result);
10848 
10849  if (elem.weight < (result->weight - local_rscale * 2 / DEC_DIGITS))
10850  break;
10851  }
10852 
10853  /* Compensate for argument range reduction, round to requested rscale */
10854  mul_var(result, &fact, result, rscale);
10855 
10856  free_var(&x);
10857  free_var(&xx);
10858  free_var(&elem);
10859  free_var(&fact);
10860 }
static const NumericVar const_two
Definition: numeric.c:426
static void sqrt_var(const NumericVar *arg, NumericVar *result, int rscale)
Definition: numeric.c:10062

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

10872 {
10873  NumericVar ln_base;
10874  NumericVar ln_num;
10875  int ln_base_dweight;
10876  int ln_num_dweight;
10877  int result_dweight;
10878  int rscale;
10879  int ln_base_rscale;
10880  int ln_num_rscale;
10881 
10882  init_var(&ln_base);
10883  init_var(&ln_num);
10884 
10885  /* Estimated dweights of ln(base), ln(num) and the final result */
10886  ln_base_dweight = estimate_ln_dweight(base);
10887  ln_num_dweight = estimate_ln_dweight(num);
10888  result_dweight = ln_num_dweight - ln_base_dweight;
10889 
10890  /*
10891  * Select the scale of the result so that it will have at least
10892  * NUMERIC_MIN_SIG_DIGITS significant digits and is not less than either
10893  * input's display scale.
10894  */
10895  rscale = NUMERIC_MIN_SIG_DIGITS - result_dweight;
10896  rscale = Max(rscale, base->dscale);
10897  rscale = Max(rscale, num->dscale);
10898  rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
10899  rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
10900 
10901  /*
10902  * Set the scales for ln(base) and ln(num) so that they each have more
10903  * significant digits than the final result.
10904  */
10905  ln_base_rscale = rscale + result_dweight - ln_base_dweight + 8;
10906  ln_base_rscale = Max(ln_base_rscale, NUMERIC_MIN_DISPLAY_SCALE);
10907 
10908  ln_num_rscale = rscale + result_dweight - ln_num_dweight + 8;
10909  ln_num_rscale = Max(ln_num_rscale, NUMERIC_MIN_DISPLAY_SCALE);
10910 
10911  /* Form natural logarithms */
10912  ln_var(base, &ln_base, ln_base_rscale);
10913  ln_var(num, &ln_num, ln_num_rscale);
10914 
10915  /* Divide and round to the required scale */
10916  div_var_fast(&ln_num, &ln_base, result, rscale, true);
10917 
10918  free_var(&ln_num);
10919  free_var(&ln_base);
10920 }
static int estimate_ln_dweight(const NumericVar *var)
Definition: numeric.c:10671
#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 898 of file numeric.c.

899 {
900  return ((precision << 16) | (scale & 0x7ff)) + VARHDRSZ;
901 }

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

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

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

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

4843 {
4845 
4847  state->calcSumX2 = calcSumX2;
4848  state->agg_context = CurrentMemoryContext;
4849 
4850  return state;
4851 }
MemoryContext CurrentMemoryContext
Definition: mcxt.c:131

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

9847 {
9848  NumericVar tmp;
9849 
9850  init_var(&tmp);
9851 
9852  /* ---------
9853  * We do this using the equation
9854  * mod(x,y) = x - trunc(x/y)*y
9855  * div_var can be persuaded to give us trunc(x/y) directly.
9856  * ----------
9857  */
9858  div_var(var1, var2, &tmp, 0, false);
9859 
9860  mul_var(var2, &tmp, &tmp, var2->dscale);
9861 
9862  sub_var(var1, &tmp, result);
9863 
9864  free_var(&tmp);
9865 }

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

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

References alloc_var(), Assert(), DEC_DIGITS, NumericVar::digits, NumericVar::dscale, i, maxdigits, Min, MUL_GUARD_DIGITS, 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().

◆ numeric()

Definition at line 1237 of file numeric.c.

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

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

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

2047 {
2048  NumericSortSupport *nss = ssup->ssup_extra;
2049  void *original_varatt = PG_DETOAST_DATUM_PACKED(original_datum);
2050  Numeric value;
2051  Datum result;
2052 
2053  nss->input_count += 1;
2054 
2055  /*
2056  * This is to handle packed datums without needing a palloc/pfree cycle;
2057  * we keep and reuse a buffer large enough to handle any short datum.
2058  */
2059  if (VARATT_IS_SHORT(original_varatt))
2060  {
2061  void *buf = nss->buf;
2062  Size sz = VARSIZE_SHORT(original_varatt) - VARHDRSZ_SHORT;
2063 
2065 
2066  SET_VARSIZE(buf, VARHDRSZ + sz);
2067  memcpy(VARDATA(buf), VARDATA_SHORT(original_varatt), sz);
2068 
2069  value = (Numeric) buf;
2070  }
2071  else
2072  value = (Numeric) original_varatt;
2073 
2075  {
2076  if (NUMERIC_IS_PINF(value))
2077  result = NUMERIC_ABBREV_PINF;
2078  else if (NUMERIC_IS_NINF(value))
2079  result = NUMERIC_ABBREV_NINF;
2080  else
2081  result = NUMERIC_ABBREV_NAN;
2082  }
2083  else
2084  {
2085  NumericVar var;
2086 
2087  init_var_from_num(value, &var);
2088 
2089  result = numeric_abbrev_convert_var(&var, nss);
2090  }
2091 
2092  /* should happen only for external/compressed toasts */
2093  if ((Pointer) original_varatt != DatumGetPointer(original_datum))
2094  pfree(original_varatt);
2095 
2096  return result;
2097 }
static Datum numeric_abbrev_convert_var(const NumericVar *var, NumericSortSupport *nss)
#define NUMERIC_ABBREV_PINF
Definition: numeric.c:405
#define NUMERIC_ABBREV_NAN
Definition: numeric.c:404
#define NUMERIC_ABBREV_NINF
Definition: numeric.c:406
char * Pointer
Definition: c.h:470
#define PG_DETOAST_DATUM_PACKED(datum)
Definition: fmgr.h:248
static struct @154 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 1384 of file numeric.c.

1385 {
1386  Numeric num = PG_GETARG_NUMERIC(0);
1387  Numeric res;
1388 
1389  /*
1390  * Do it the easy way directly on the packed format
1391  */
1392  res = duplicate_numeric(num);
1393 
1394  if (NUMERIC_IS_SHORT(num))
1395  res->choice.n_short.n_header =
1397  else if (NUMERIC_IS_SPECIAL(num))
1398  {
1399  /* This changes -Inf to Inf, and doesn't affect NaN */
1400  res->choice.n_short.n_header =
1402  }
1403  else
1404  res->choice.n_long.n_sign_dscale = NUMERIC_POS | NUMERIC_DSCALE(num);
1405 
1407 }
#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 5020 of file numeric.c.

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

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

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

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

2849 {
2850  Numeric num1 = PG_GETARG_NUMERIC(0);
2851  Numeric num2 = PG_GETARG_NUMERIC(1);
2852  Numeric res;
2853 
2854  res = numeric_add_opt_error(num1, num2, NULL);
2855 
2857 }
Numeric numeric_add_opt_error(Numeric num1, Numeric num2, bool *have_error)
Definition: numeric.c:2867

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

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

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

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

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

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

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

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

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

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

5205 {
5208  bytea *result;
5209  NumericVar tmp_var;
5210 
5211  /* Ensure we disallow calling when not in aggregate context */
5212  if (!AggCheckCallContext(fcinfo, NULL))
5213  elog(ERROR, "aggregate function called in non-aggregate context");
5214 
5216 
5217  init_var(&tmp_var);
5218 
5219  pq_begintypsend(&buf);
5220 
5221  /* N */
5222  pq_sendint64(&buf, state->N);
5223 
5224  /* sumX */
5225  accum_sum_final(&state->sumX, &tmp_var);
5226  numericvar_serialize(&buf, &tmp_var);
5227 
5228  /* maxScale */
5229  pq_sendint32(&buf, state->maxScale);
5230 
5231  /* maxScaleCount */
5232  pq_sendint64(&buf, state->maxScaleCount);
5233 
5234  /* NaNcount */
5235  pq_sendint64(&buf, state->NaNcount);
5236 
5237  /* pInfcount */
5238  pq_sendint64(&buf, state->pInfcount);
5239 
5240  /* nInfcount */
5241  pq_sendint64(&buf, state->nInfcount);
5242 
5243  result = pq_endtypsend(&buf);
5244 
5245  free_var(&tmp_var);
5246 
5247  PG_RETURN_BYTEA_P(result);
5248 }
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 1630 of file numeric.c.

1631 {
1632  Numeric num = PG_GETARG_NUMERIC(0);
1633  Numeric res;
1634  NumericVar result;
1635 
1636  /*
1637  * Handle NaN and infinities
1638  */
1639  if (NUMERIC_IS_SPECIAL(num))
1641 
1642  init_var_from_num(num, &result);
1643  ceil_var(&result, &result);
1644 
1645  res = make_result(&result);
1646  free_var(&result);
1647 
1649 }
static void ceil_var(const NumericVar *var, NumericVar *result)
Definition: numeric.c:9945

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

2400 {
2401  Numeric num1 = PG_GETARG_NUMERIC(0);
2402  Numeric num2 = PG_GETARG_NUMERIC(1);
2403  int result;
2404 
2405  result = cmp_numerics(num1, num2);
2406 
2407  PG_FREE_IF_COPY(num1, 0);
2408  PG_FREE_IF_COPY(num2, 1);
2409 
2410  PG_RETURN_INT32(result);
2411 }
static int cmp_numerics(Numeric num1, Numeric num2)
Definition: numeric.c:2505
#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 2203 of file numeric.c.

2204 {
2205  /*
2206  * NOTE WELL: this is intentionally backwards, because the abbreviation is
2207  * negated relative to the original value, to handle NaN/infinity cases.
2208  */
2210  return 1;
2212  return -1;
2213  return 0;
2214 }
#define DatumGetNumericAbbrev(X)
Definition: numeric.c:403
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 5040 of file numeric.c.

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

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

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

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

3125 {
3126  Numeric num1 = PG_GETARG_NUMERIC(0);
3127  Numeric num2 = PG_GETARG_NUMERIC(1);
3128  Numeric res;
3129 
3130  res = numeric_div_opt_error(num1, num2, NULL);
3131 
3133 }
Numeric numeric_div_opt_error(Numeric num1, Numeric num2, bool *have_error)
Definition: numeric.c:3144

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

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

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

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

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

2416 {
2417  Numeric num1 = PG_GETARG_NUMERIC(0);
2418  Numeric num2 = PG_GETARG_NUMERIC(1);
2419  bool result;
2420 
2421  result = cmp_numerics(num1, num2) == 0;
2422 
2423  PG_FREE_IF_COPY(num1, 0);
2424  PG_FREE_IF_COPY(num2, 1);
2425 
2426  PG_RETURN_BOOL(result);
2427 }

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

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

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

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

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

2182 {
2183  Numeric nx = DatumGetNumeric(x);
2184  Numeric ny = DatumGetNumeric(y);
2185  int result;
2186 
2187  result = cmp_numerics(nx, ny);
2188 
2189  if ((Pointer) nx != DatumGetPointer(x))
2190  pfree(nx);
2191  if ((Pointer) ny != DatumGetPointer(y))
2192  pfree(ny);
2193 
2194  return result;
2195 }
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 4722 of file numeric.c.

4723 {
4724  Numeric num = PG_GETARG_NUMERIC(0);
4725  char *tmp;
4726  Datum result;
4727 
4728  if (NUMERIC_IS_SPECIAL(num))
4729  {
4730  if (NUMERIC_IS_PINF(num))
4732  else if (NUMERIC_IS_NINF(num))
4734  else
4736  }
4737 
4739  NumericGetDatum(num)));
4740 
4742 
4743  pfree(tmp);
4744 
4745  PG_RETURN_DATUM(result);
4746 }
Datum numeric_out(PG_FUNCTION_ARGS)
Definition: numeric.c:807
Datum float4in(PG_FUNCTION_ARGS)
Definition: float.c:157
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 4628 of file numeric.c.

4629 {
4630  Numeric num = PG_GETARG_NUMERIC(0);
4631  char *tmp;
4632  Datum result;
4633 
4634  if (NUMERIC_IS_SPECIAL(num))
4635  {
4636  if (NUMERIC_IS_PINF(num))
4638  else if (NUMERIC_IS_NINF(num))
4640  else
4642  }
4643 
4645  NumericGetDatum(num)));
4646 
4648 
4649  pfree(tmp);
4650 
4651  PG_RETURN_DATUM(result);
4652 }
Datum float8in(PG_FUNCTION_ARGS)
Definition: float.c:357
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 4661 of file numeric.c.

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

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

1659 {
1660  Numeric num = PG_GETARG_NUMERIC(0);
1661  Numeric res;
1662  NumericVar result;
1663 
1664  /*
1665  * Handle NaN and infinities
1666  */
1667  if (NUMERIC_IS_SPECIAL(num))
1669 
1670  init_var_from_num(num, &result);
1671  floor_var(&result, &result);
1672 
1673  res = make_result(&result);
1674  free_var(&result);
1675 
1677 }

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

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

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

2461 {
2462  Numeric num1 = PG_GETARG_NUMERIC(0);
2463  Numeric num2 = PG_GETARG_NUMERIC(1);
2464  bool result;
2465 
2466  result = cmp_numerics(num1, num2) >= 0;
2467 
2468  PG_FREE_IF_COPY(num1, 0);
2469  PG_FREE_IF_COPY(num2, 1);
2470 
2471  PG_RETURN_BOOL(result);
2472 }

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

2446 {
2447  Numeric num1 = PG_GETARG_NUMERIC(0);
2448  Numeric num2 = PG_GETARG_NUMERIC(1);
2449  bool result;
2450 
2451  result = cmp_numerics(num1, num2) > 0;
2452 
2453  PG_FREE_IF_COPY(num1, 0);
2454  PG_FREE_IF_COPY(num2, 1);
2455 
2456  PG_RETURN_BOOL(result);
2457 }

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

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

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

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

4554 {
4555  Numeric num = PG_GETARG_NUMERIC(0);
4556  NumericVar x;
4557  int64 val;
4558  int16 result;
4559 
4560  if (NUMERIC_IS_SPECIAL(num))
4561  {
4562  if (NUMERIC_IS_NAN(num))
4563  ereport(ERROR,
4564  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4565  errmsg("cannot convert NaN to %s", "smallint")));
4566  else
4567  ereport(ERROR,
4568  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4569  errmsg("cannot convert infinity to %s", "smallint")));
4570  }
4571 
4572  /* Convert to variable format and thence to int8 */
4573  init_var_from_num(num, &x);
4574 
4575  if (!numericvar_to_int64(&x, &val))
4576  ereport(ERROR,
4577  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
4578  errmsg("smallint out of range")));
4579 
4581  ereport(ERROR,
4582  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
4583  errmsg("smallint out of range")));
4584 
4585  /* Down-convert to int2 */
4586  result = (int16) val;
4587 
4588  PG_RETURN_INT16(result);
4589 }
static bool numericvar_to_int64(const NumericVar *var, int64 *result)
Definition: numeric.c:8029
#define PG_INT16_MIN
Definition: c.h:572
#define PG_INT16_MAX
Definition: c.h:573
#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 4447 of file numeric.c.

4448 {
4449  Numeric num = PG_GETARG_NUMERIC(0);
4450 
4452 }
int32 numeric_int4_opt_error(Numeric num, bool *have_error)
Definition: numeric.c:4397

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

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

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

4536 {
4537  Numeric num = PG_GETARG_NUMERIC(0);
4538 
4540 }
int64 numeric_int8_opt_error(Numeric num, bool *have_error)
Definition: numeric.c:4485

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

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

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

854 {
855  return NUMERIC_IS_INF(num);
856 }
#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 864 of file numeric.c.

865 {
866  NumericVar arg;
867 
868  /* Reject NaN, but infinities are considered integral */
869  if (NUMERIC_IS_SPECIAL(num))
870  {
871  if (NUMERIC_IS_NAN(num))
872  return false;
873  return true;
874  }
875 
876  /* Integral if there are no digits to the right of the decimal point */
877  init_var_from_num(num, &arg);
878 
879  return (arg.ndigits == 0 || arg.ndigits <= arg.weight + 1);
880 }

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

843 {
844  return NUMERIC_IS_NAN(num);
845 }

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

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

References cmp_numerics(), PG_GETARG_NUMERIC, and PG_RETURN_NUMERIC.

◆ numeric_lcm()

Datum numeric_lcm ( PG_FUNCTION_ARGS  )

Definition at line 3564 of file numeric.c.

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

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

2491 {
2492  Numeric num1 = PG_GETARG_NUMERIC(0);
2493  Numeric num2 = PG_GETARG_NUMERIC(1);
2494  bool result;
2495 
2496  result = cmp_numerics(num1, num2) <= 0;
2497 
2498  PG_FREE_IF_COPY(num1, 0);
2499  PG_FREE_IF_COPY(num2, 1);
2500 
2501  PG_RETURN_BOOL(result);
2502 }

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

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

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

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

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

2476 {
2477  Numeric num1 = PG_GETARG_NUMERIC(0);
2478  Numeric num2 = PG_GETARG_NUMERIC(1);
2479  bool result;
2480 
2481  result = cmp_numerics(num1, num2) < 0;
2482 
2483  PG_FREE_IF_COPY(num1, 0);
2484  PG_FREE_IF_COPY(num2, 1);
2485 
2486  PG_RETURN_BOOL(result);
2487 }

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

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

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

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

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

3349 {
3350  Numeric num1 = PG_GETARG_NUMERIC(0);
3351  Numeric num2 = PG_GETARG_NUMERIC(1);
3352  Numeric res;
3353 
3354  res = numeric_mod_opt_error(num1, num2, NULL);
3355 
3357 }
Numeric numeric_mod_opt_error(Numeric num1, Numeric num2, bool *have_error)
Definition: numeric.c:3368

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

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

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

3004 {
3005  Numeric num1 = PG_GETARG_NUMERIC(0);
3006  Numeric num2 = PG_GETARG_NUMERIC(1);
3007  Numeric res;
3008 
3009  res = numeric_mul_opt_error(num1, num2, NULL);
3010 
3012 }
Numeric numeric_mul_opt_error(Numeric num1, Numeric num2, bool *have_error)
Definition: numeric.c:3023

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

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

2431 {
2432  Numeric num1 = PG_GETARG_NUMERIC(0);
2433  Numeric num2 = PG_GETARG_NUMERIC(1);
2434  bool result;
2435 
2436  result = cmp_numerics(num1, num2) != 0;
2437 
2438  PG_FREE_IF_COPY(num1, 0);
2439  PG_FREE_IF_COPY(num2, 1);
2440 
2441  PG_RETURN_BOOL(result);
2442 }

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

◆ numeric_normalize()

char* numeric_normalize ( Numeric  num)

Definition at line 1017 of file numeric.c.

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

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

Referenced by make_scalar_key().

◆ numeric_out()

Datum numeric_out ( PG_FUNCTION_ARGS  )

Definition at line 807 of file numeric.c.

808 {
809  Numeric num = PG_GETARG_NUMERIC(0);
810  NumericVar x;
811  char *str;
812 
813  /*
814  * Handle NaN and infinities
815  */
816  if (NUMERIC_IS_SPECIAL(num))
817  {
818  if (NUMERIC_IS_PINF(num))
819  PG_RETURN_CSTRING(pstrdup("Infinity"));
820  else if (NUMERIC_IS_NINF(num))
821  PG_RETURN_CSTRING(pstrdup("-Infinity"));
822  else
823  PG_RETURN_CSTRING(pstrdup("NaN"));
824  }
825 
826  /*
827  * Get the number in the variable format.
828  */
829  init_var_from_num(num, &x);
830 
831  str = get_str_from_var(&x);
832 
834 }
#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(), generate_unaccent_rules::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 983 of file numeric.c.

984 {
985  NumericVar x;
986  char *str;
987 
988  /*
989  * Handle NaN and infinities
990  */
991  if (NUMERIC_IS_SPECIAL(num))
992  {
993  if (NUMERIC_IS_PINF(num))
994  return pstrdup("Infinity");
995  else if (NUMERIC_IS_NINF(num))
996  return pstrdup("-Infinity");
997  else
998  return pstrdup("NaN");
999  }
1000 
1001  init_var_from_num(num, &x);
1002 
1004 
1005  return str;
1006 }
static char * get_str_from_var_sci(const NumericVar *var, int rscale)
Definition: numeric.c:7647

References get_str_from_var_sci(), init_var_from_num(), NUMERIC_IS_NINF, NUMERIC_IS_PINF, NUMERIC_IS_SPECIAL, pstrdup(), scale, generate_unaccent_rules::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 4750 of file numeric.c.

4751 {
4752  Numeric num = PG_GETARG_NUMERIC(0);
4753  NumericVar x;
4754  XLogRecPtr result;
4755 
4756  if (NUMERIC_IS_SPECIAL(num))
4757  {
4758  if (NUMERIC_IS_NAN(num))
4759  ereport(ERROR,
4760  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4761  errmsg("cannot convert NaN to %s", "pg_lsn")));
4762  else
4763  ereport(ERROR,
4764  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4765  errmsg("cannot convert infinity to %s", "pg_lsn")));
4766  }
4767 
4768  /* Convert to variable format and thence to pg_lsn */
4769  init_var_from_num(num, &x);
4770 
4771  if (!numericvar_to_uint64(&x, (uint64 *) &result))
4772  ereport(ERROR,
4773  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4774  errmsg("pg_lsn out of range")));
4775 
4776  PG_RETURN_LSN(result);
4777 }
static bool numericvar_to_uint64(const NumericVar *var, uint64 *result)
Definition: numeric.c:8151
#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 6098 of file numeric.c.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

1535 {
1536  Numeric num = PG_GETARG_NUMERIC(0);
1538  Numeric res;
1539  NumericVar arg;
1540 
1541  /*
1542  * Handle NaN and infinities
1543  */
1544  if (NUMERIC_IS_SPECIAL(num))
1546 
1547  /*
1548  * Limit the scale value to avoid possible overflow in calculations
1549  */
1552 
1553  /*
1554  * Unpack the argument and round it at the proper digit position
1555  */
1556  init_var(&arg);
1557  set_var_from_num(num, &arg);
1558 
1559  round_var(&arg, scale);
1560 
1561  /* We don't allow negative output dscale */
1562  if (scale < 0)
1563  arg.dscale = 0;
1564 
1565  /*
1566  * Return the rounded result
1567  */
1568  res = make_result(&arg);
1569 
1570  free_var(&arg);
1572 }

References arg, duplicate_numeric(), free_var(), init_var, make_result(), Max, Min, NUMERIC_IS_SPECIAL, NUMERIC_MAX_RESULT_SCALE, 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 4122 of file numeric.c.

4123 {
4124  Numeric num = PG_GETARG_NUMERIC(0);
4125 
4126  if (NUMERIC_IS_SPECIAL(num))
4127  PG_RETURN_NULL();
4128 
4130 }

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

1155 {
1156  Numeric num = PG_GETARG_NUMERIC(0);
1157  NumericVar x;
1159  int i;
1160 
1161  init_var_from_num(num, &x);
1162 
1163  pq_begintypsend(&buf);
1164 
1165  pq_sendint16(&buf, x.ndigits);
1166  pq_sendint16(&buf, x.weight);
1167  pq_sendint16(&buf, x.sign);
1168  pq_sendint16(&buf, x.dscale);
1169  for (i = 0; i < x.ndigits; i++)
1170  pq_sendint16(&buf, x.digits[i]);
1171 
1173 }
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 5314 of file numeric.c.

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

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

1502 {
1503  Numeric num = PG_GETARG_NUMERIC(0);
1504 
1505  /*
1506  * Handle NaN (infinities can be handled normally)
1507  */
1508  if (NUMERIC_IS_NAN(num))
1510 
1511  switch (numeric_sign_internal(num))
1512  {
1513  case 0:
1515  case 1:
1517  case -1:
1519  }
1520 
1521  Assert(false);
1522  return (Datum) 0;
1523 }

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

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

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

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

References cmp_numerics(), PG_GETARG_NUMERIC, and PG_RETURN_NUMERIC.

◆ numeric_sortsupport()

Datum numeric_sortsupport ( PG_FUNCTION_ARGS  )

Definition at line 2005 of file numeric.c.

2006 {
2008 
2009  ssup->comparator = numeric_fast_cmp;
2010 
2011  if (ssup->abbreviate)
2012  {
2013  NumericSortSupport *nss;
2014  MemoryContext oldcontext = MemoryContextSwitchTo(ssup->ssup_cxt);
2015 
2016  nss = palloc(sizeof(NumericSortSupport));
2017 
2018  /*
2019  * palloc a buffer for handling unaligned packed values in addition to
2020  * the support struct
2021  */
2022  nss->buf = palloc(VARATT_SHORT_MAX + VARHDRSZ + 1);
2023 
2024  nss->input_count = 0;
2025  nss->estimating = true;
2026  initHyperLogLog(&nss->abbr_card, 10);
2027 
2028  ssup->ssup_extra = nss;
2029 
2030  ssup->abbrev_full_comparator = ssup->comparator;
2034 
2035  MemoryContextSwitchTo(oldcontext);
2036  }
2037 
2038  PG_RETURN_VOID();
2039 }
static bool numeric_abbrev_abort(int memtupcount, SortSupport ssup)
Definition: numeric.c:2108
static Datum numeric_abbrev_convert(Datum original_datum, SortSupport ssup)
Definition: numeric.c:2046
static int numeric_fast_cmp(Datum x, Datum y, SortSupport ssup)
Definition: numeric.c:2181
static int numeric_cmp_abbrev(Datum x, Datum y, SortSupport ssup)
Definition: numeric.c:2203
#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 3676 of file numeric.c.

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

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

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

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

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

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

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

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

2926 {
2927  Numeric num1 = PG_GETARG_NUMERIC(0);
2928  Numeric num2 = PG_GETARG_NUMERIC(1);
2929  Numeric res;
2930 
2931  res = numeric_sub_opt_error(num1, num2, NULL);
2932 
2934 }
Numeric numeric_sub_opt_error(Numeric num1, Numeric num2, bool *have_error)
Definition: numeric.c:2945

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

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

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

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

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

1188 {
1189  Node *rawreq = (Node *) PG_GETARG_POINTER(0);
1190  Node *ret = NULL;
1191 
1192  if (IsA(rawreq, SupportRequestSimplify))
1193  {
1195  FuncExpr *expr = req->fcall;
1196  Node *typmod;
1197 
1198  Assert(list_length(expr->args) >= 2);
1199 
1200  typmod = (Node *) lsecond(expr->args);
1201 
1202  if (IsA(typmod, Const) && !((Const *) typmod)->constisnull)
1203  {
1204  Node *source = (Node *) linitial(expr->args);
1205  int32 old_typmod = exprTypmod(source);
1206  int32 new_typmod = DatumGetInt32(((Const *) typmod)->constvalue);
1207  int32 old_scale = numeric_typmod_scale(old_typmod);
1208  int32 new_scale = numeric_typmod_scale(new_typmod);
1209  int32 old_precision = numeric_typmod_precision(old_typmod);
1210  int32 new_precision = numeric_typmod_precision(new_typmod);
1211 
1212  /*
1213  * If new_typmod is invalid, the destination is unconstrained;
1214  * that's always OK. If old_typmod is valid, the source is
1215  * constrained, and we're OK if the scale is unchanged and the
1216  * precision is not decreasing. See further notes in function
1217  * header comment.
1218  */
1219  if (!is_valid_numeric_typmod(new_typmod) ||
1220  (is_valid_numeric_typmod(old_typmod) &&
1221  new_scale == old_scale && new_precision >= old_precision))
1222  ret = relabel_to_typmod(source, new_typmod);
1223  }
1224  }
1225 
1226  PG_RETURN_POINTER(ret);
1227 }
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:724

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

4208 {
4209  Numeric num = PG_GETARG_NUMERIC(0);
4210  Numeric res;
4211  NumericVar result;
4212 
4213  if (NUMERIC_IS_SPECIAL(num))
4215 
4216  init_var_from_num(num, &result);
4217  result.dscale = get_min_scale(&result);
4218  res = make_result(&result);
4219  free_var(&result);
4220 
4222 }

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

1584 {
1585  Numeric num = PG_GETARG_NUMERIC(0);
1587  Numeric res;
1588  NumericVar arg;
1589 
1590  /*
1591  * Handle NaN and infinities
1592  */
1593  if (NUMERIC_IS_SPECIAL(num))
1595 
1596  /*
1597  * Limit the scale value to avoid possible overflow in calculations
1598  */
1601 
1602  /*
1603  * Unpack the argument and truncate it at the proper digit position
1604  */
1605  init_var(&arg);
1606  set_var_from_num(num, &arg);
1607 
1608  trunc_var(&arg, scale);
1609 
1610  /* We don't allow negative output dscale */
1611  if (scale < 0)
1612  arg.dscale = 0;
1613 
1614  /*
1615  * Return the truncated result
1616  */
1617  res = make_result(&arg);
1618 
1619  free_var(&arg);
1621 }

References arg, duplicate_numeric(), free_var(), init_var, make_result(), Max, Min, NUMERIC_IS_SPECIAL, NUMERIC_MAX_RESULT_SCALE, 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 918 of file numeric.c.

919 {
920  return ((typmod - VARHDRSZ) >> 16) & 0xffff;
921 }

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

934 {
935  return (((typmod - VARHDRSZ) & 0x7ff) ^ 1024) - 1024;
936 }

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

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

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

1454 {
1455  Numeric num = PG_GETARG_NUMERIC(0);
1456 
1458 }

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

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

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

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

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

1316 {
1318  int32 *tl;
1319  int n;
1320  int32 typmod;
1321 
1322  tl = ArrayGetIntegerTypmods(ta, &n);
1323 
1324  if (n == 2)
1325  {
1326  if (tl[0] < 1 || tl[0] > NUMERIC_MAX_PRECISION)
1327  ereport(ERROR,
1328  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1329  errmsg("NUMERIC precision %d must be between 1 and %d",
1330  tl[0], NUMERIC_MAX_PRECISION)));
1331  if (tl[1] < NUMERIC_MIN_SCALE || tl[1] > NUMERIC_MAX_SCALE)
1332  ereport(ERROR,
1333  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1334  errmsg("NUMERIC scale %d must be between %d and %d",
1336  typmod = make_numeric_typmod(tl[0], tl[1]);
1337  }
1338  else if (n == 1)
1339  {
1340  if (tl[0] < 1 || tl[0] > NUMERIC_MAX_PRECISION)
1341  ereport(ERROR,
1342  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1343  errmsg("NUMERIC precision %d must be between 1 and %d",
1344  tl[0], NUMERIC_MAX_PRECISION)));
1345  /* scale defaults to zero */
1346  typmod = make_numeric_typmod(tl[0], 0);
1347  }
1348  else
1349  {
1350  ereport(ERROR,
1351  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1352  errmsg("invalid NUMERIC type modifier")));
1353  typmod = 0; /* keep compiler quiet */
1354  }
1355 
1356  PG_RETURN_INT32(typmod);
1357 }
int32 * ArrayGetIntegerTypmods(ArrayType *arr, int *n)
Definition: arrayutils.c:233
static int32 make_numeric_typmod(int precision, int scale)
Definition: numeric.c:898
#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 1360 of file numeric.c.

1361 {
1362  int32 typmod = PG_GETARG_INT32(0);
1363  char *res = (char *) palloc(64);
1364 
1365  if (is_valid_numeric_typmod(typmod))
1366  snprintf(res, 64, "(%d,%d)",
1367  numeric_typmod_precision(typmod),
1368  numeric_typmod_scale(typmod));
1369  else
1370  *res = '\0';
1371 
1373 }

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

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

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

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

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

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

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

4461 {
4462  int64 val;
4463 
4464  if (!numericvar_to_int64(var, &val))
4465  return false;
4466 
4468  return false;
4469 
4470  /* Down-convert to int4 */
4471  *result = (int32) val;
4472 
4473  return true;
4474 }
#define PG_INT32_MAX
Definition: c.h:576
#define PG_INT32_MIN
Definition: c.h:575

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

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

8152 {
8154  int ndigits;
8155  int weight;
8156  int i;
8157  uint64 val;
8158  NumericVar rounded;
8159 
8160  /* Round to nearest integer */
8161  init_var(&rounded);
8162  set_var_from_var(var, &rounded);
8163  round_var(&rounded, 0);
8164 
8165  /* Check for zero input */
8166  strip_var(&rounded);
8167  ndigits = rounded.ndigits;
8168  if (ndigits == 0)
8169  {
8170  *result = 0;
8171  free_var(&rounded);
8172  return true;
8173  }
8174 
8175  /* Check for negative input */
8176  if (rounded.sign == NUMERIC_NEG)
8177  {
8178  free_var(&rounded);
8179  return false;
8180  }
8181 
8182  /*
8183  * For input like 10000000000, we must treat stripped digits as real. So
8184  * the loop assumes there are weight+1 digits before the decimal point.
8185  */
8186  weight = rounded.weight;
8187  Assert(weight >= 0 && ndigits <= weight + 1);
8188 
8189  /* Construct the result */
8190  digits = rounded.digits;
8191  val = digits[0];
8192  for (i = 1; i <= weight; i++)
8193  {
8195  {
8196  free_var(&rounded);
8197  return false;
8198  }
8199 
8200  if (i < ndigits)
8201  {
8203  {
8204  free_var(&rounded);
8205  return false;
8206  }
8207  }
8208  }
8209 
8210  free_var(&rounded);
8211 
8212  *result = val;
8213 
8214  return true;
8215 }
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 11296 of file numeric.c.

11297 {
11298  /* Construct the result directly, starting from 10^0 = 1 */
11299  set_var_from_var(&const_one, result);
11300 
11301  /* Scale needed to represent the result exactly */
11302  result->dscale = exp < 0 ? -exp : 0;
11303 
11304  /* Base-NBASE weight of result and remaining exponent */
11305  if (exp >= 0)
11306  result->weight = exp / DEC_DIGITS;
11307  else
11308  result->weight = (exp + 1) / DEC_DIGITS - 1;
11309 
11310  exp -= result->weight * DEC_DIGITS;
11311 
11312  /* Final adjustment of the result's single NBASE digit */
11313  while (exp-- > 0)
11314  result->digits[0] *= 10;
11315 }

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

10932 {
10933  int res_sign;
10934  NumericVar abs_base;
10935  NumericVar ln_base;
10936  NumericVar ln_num;
10937  int ln_dweight;
10938  int rscale;
10939  int sig_digits;
10940  int local_rscale;
10941  double val;
10942 
10943  /* If exp can be represented as an integer, use power_var_int */
10944  if (exp->ndigits == 0 || exp->ndigits <= exp->weight + 1)
10945  {
10946  /* exact integer, but does it fit in int? */
10947  int64 expval64;
10948 
10949  if (numericvar_to_int64(exp, &expval64))
10950  {
10951  if (expval64 >= PG_INT32_MIN && expval64 <= PG_INT32_MAX)
10952  {
10953  /* Okay, use power_var_int */
10954  power_var_int(base, (int) expval64, exp->dscale, result);
10955  return;
10956  }
10957  }
10958  }
10959 
10960  /*
10961  * This avoids log(0) for cases of 0 raised to a non-integer. 0 ^ 0 is
10962  * handled by power_var_int().
10963  */
10964  if (cmp_var(base, &const_zero) == 0)
10965  {
10966  set_var_from_var(&const_zero, result);
10967  result->dscale = NUMERIC_MIN_SIG_DIGITS; /* no need to round */
10968  return;
10969  }
10970 
10971  init_var(&abs_base);
10972  init_var(&ln_base);
10973  init_var(&ln_num);
10974 
10975  /*
10976  * If base is negative, insist that exp be an integer. The result is then
10977  * positive if exp is even and negative if exp is odd.
10978  */
10979  if (base->sign == NUMERIC_NEG)
10980  {
10981  /*
10982  * Check that exp is an integer. This error code is defined by the
10983  * SQL standard, and matches other errors in numeric_power().
10984  */
10985  if (exp->ndigits > 0 && exp->ndigits > exp->weight + 1)
10986  ereport(ERROR,
10987  (errcode(ERRCODE_INVALID_ARGUMENT_FOR_POWER_FUNCTION),
10988  errmsg("a negative number raised to a non-integer power yields a complex result")));
10989 
10990  /* Test if exp is odd or even */
10991  if (exp->ndigits > 0 && exp->ndigits == exp->weight + 1 &&
10992  (exp->digits[exp->ndigits - 1] & 1))
10993  res_sign = NUMERIC_NEG;
10994  else
10995  res_sign = NUMERIC_POS;
10996 
10997  /* Then work with abs(base) below */
10998  set_var_from_var(base, &abs_base);
10999  abs_base.sign = NUMERIC_POS;
11000  base = &abs_base;
11001  }
11002  else
11003  res_sign = NUMERIC_POS;
11004 
11005  /*----------
11006  * Decide on the scale for the ln() calculation. For this we need an
11007  * estimate of the weight of the result, which we obtain by doing an
11008  * initial low-precision calculation of exp * ln(base).
11009  *
11010  * We want result = e ^ (exp * ln(base))
11011  * so result dweight = log10(result) = exp * ln(base) * log10(e)
11012  *
11013  * We also perform a crude overflow test here so that we can exit early if
11014  * the full-precision result is sure to overflow, and to guard against
11015  * integer overflow when determining the scale for the real calculation.
11016  * exp_var() supports inputs up to NUMERIC_MAX_RESULT_SCALE * 3, so the
11017  * result will overflow if exp * ln(base) >= NUMERIC_MAX_RESULT_SCALE * 3.
11018  * Since the values here are only approximations, we apply a small fuzz
11019  * factor to this overflow test and let exp_var() determine the exact
11020  * overflow threshold so that it is consistent for all inputs.
11021  *----------
11022  */
11023  ln_dweight = estimate_ln_dweight(base);
11024 
11025  /*
11026  * Set the scale for the low-precision calculation, computing ln(base) to
11027  * around 8 significant digits. Note that ln_dweight may be as small as
11028  * -SHRT_MAX, so the scale may exceed NUMERIC_MAX_DISPLAY_SCALE here.
11029  */
11030  local_rscale = 8 - ln_dweight;
11031  local_rscale = Max(local_rscale, NUMERIC_MIN_DISPLAY_SCALE);
11032 
11033  ln_var(base, &ln_base, local_rscale);
11034 
11035  mul_var(&ln_base, exp, &ln_num, local_rscale);
11036 
11038 
11039  /* initial overflow/underflow test with fuzz factor */
11040  if (fabs(val) > NUMERIC_MAX_RESULT_SCALE * 3.01)
11041  {
11042  if (val > 0)
11043  ereport(ERROR,
11044  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
11045  errmsg("value overflows numeric format")));
11046  zero_var(result);
11048  return;
11049  }
11050 
11051  val *= 0.434294481903252; /* approximate decimal result weight */
11052 
11053  /* choose the result scale */
11054  rscale = NUMERIC_MIN_SIG_DIGITS - (int) val;
11055  rscale = Max(rscale, base->dscale);
11056  rscale = Max(rscale, exp->dscale);
11057  rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
11058  rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
11059 
11060  /* significant digits required in the result */
11061  sig_digits = rscale + (int) val;
11062  sig_digits = Max(sig_digits, 0);
11063 
11064  /* set the scale for the real exp * ln(base) calculation */
11065  local_rscale = sig_digits - ln_dweight + 8;
11066  local_rscale = Max(local_rscale, NUMERIC_MIN_DISPLAY_SCALE);
11067 
11068  /* and do the real calculation */
11069 
11070  ln_var(base, &ln_base, local_rscale);
11071 
11072  mul_var(&ln_base, exp, &ln_num, local_rscale);
11073 
11074  exp_var(&ln_num, result, rscale);
11075 
11076  if (res_sign == NUMERIC_NEG && result->ndigits > 0)
11077  result->sign = NUMERIC_NEG;
11078 
11079  free_var(&ln_num);
11080  free_var(&ln_base);
11081  free_var(&abs_base);
11082 }
static void power_var_int(const NumericVar *base, int exp, int exp_dscale, NumericVar *result)
Definition: numeric.c:11092

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

11094 {
11095  double f;
11096  int p;
11097  int i;
11098  int rscale;
11099  int sig_digits;
11100  unsigned int mask;
11101  bool neg;
11102  NumericVar base_prod;
11103  int local_rscale;
11104 
11105  /*
11106  * Choose the result scale. For this we need an estimate of the decimal
11107  * weight of the result, which we obtain by approximating using double
11108  * precision arithmetic.
11109  *
11110  * We also perform crude overflow/underflow tests here so that we can exit
11111  * early if the result is sure to overflow/underflow, and to guard against
11112  * integer overflow when choosing the result scale.
11113  */
11114  if (base->ndigits != 0)
11115  {
11116  /*----------
11117  * Choose f (double) and p (int) such that base ~= f * 10^p.
11118  * Then log10(result) = log10(base^exp) ~= exp * (log10(f) + p).
11119  *----------
11120  */
11121  f = base->digits[0];
11122  p = base->weight * DEC_DIGITS;
11123 
11124  for (i = 1; i < base->ndigits && i * DEC_DIGITS < 16; i++)
11125  {
11126  f = f * NBASE + base->digits[i];
11127  p -= DEC_DIGITS;
11128  }
11129 
11130  f = exp * (log10(f) + p); /* approximate decimal result weight */
11131  }
11132  else
11133  f = 0; /* result is 0 or 1 (weight 0), or error */
11134 
11135  /* overflow/underflow tests with fuzz factors */
11136  if (f > (SHRT_MAX + 1) * DEC_DIGITS)
11137  ereport(ERROR,
11138  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
11139  errmsg("value overflows numeric format")));
11140  if (f + 1 < -NUMERIC_MAX_DISPLAY_SCALE)
11141  {
11142  zero_var(result);
11144  return;
11145  }
11146 
11147  /*
11148  * Choose the result scale in the same way as power_var(), so it has at
11149  * least NUMERIC_MIN_SIG_DIGITS significant digits and is not less than
11150  * either input's display scale.
11151  */
11152  rscale = NUMERIC_MIN_SIG_DIGITS - (int) f;
11153  rscale = Max(rscale, base->dscale);
11154  rscale = Max(rscale, exp_dscale);
11155  rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
11156  rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
11157 
11158  /* Handle some common special cases, as well as corner cases */
11159  switch (exp)
11160  {
11161  case 0:
11162 
11163  /*
11164  * While 0 ^ 0 can be either 1 or indeterminate (error), we treat
11165  * it as 1 because most programming languages do this. SQL:2003
11166  * also requires a return value of 1.
11167  * https://en.wikipedia.org/wiki/Exponentiation#Zero_to_the_zero_power
11168  */
11169  set_var_from_var(&const_one, result);
11170  result->dscale = rscale; /* no need to round */
11171  return;
11172  case 1:
11173  set_var_from_var(base, result);
11174  round_var(result, rscale);
11175  return;
11176  case -1:
11177  div_var(&const_one, base, result, rscale, true);
11178  return;
11179  case 2:
11180  mul_var(base, base, result, rscale);
11181  return;
11182  default:
11183  break;
11184  }
11185 
11186  /* Handle the special case where the base is zero */
11187  if (base->ndigits == 0)
11188  {
11189  if (exp < 0)
11190  ereport(ERROR,
11191  (errcode(ERRCODE_DIVISION_BY_ZERO),
11192  errmsg("division by zero")));
11193  zero_var(result);
11194  result->dscale = rscale;
11195  return;
11196  }
11197 
11198  /*
11199  * The general case repeatedly multiplies base according to the bit
11200  * pattern of exp.
11201  *
11202  * The local rscale used for each multiplication is varied to keep a fixed
11203  * number of significant digits, sufficient to give the required result
11204  * scale.
11205  */
11206 
11207  /*
11208  * Approximate number of significant digits in the result. Note that the
11209  * underflow test above, together with the choice of rscale, ensures that
11210  * this approximation is necessarily > 0.
11211  */
11212  sig_digits = 1 + rscale + (int) f;
11213 
11214  /*
11215  * The multiplications to produce the result may introduce an error of up
11216  * to around log10(abs(exp)) digits, so work with this many extra digits
11217  * of precision (plus a few more for good measure).
11218  */
11219  sig_digits += (int) log(fabs((double) exp)) + 8;
11220 
11221  /*
11222  * Now we can proceed with the multiplications.
11223  */
11224  neg = (exp < 0);
11225  mask = abs(exp);
11226 
11227  init_var(&base_prod);
11228  set_var_from_var(base, &base_prod);
11229 
11230  if (mask & 1)
11231  set_var_from_var(base, result);
11232  else
11233  set_var_from_var(&const_one, result);
11234 
11235  while ((mask >>= 1) > 0)
11236  {
11237  /*
11238  * Do the multiplications using rscales large enough to hold the
11239  * results to the required number of significant digits, but don't
11240  * waste time by exceeding the scales of the numbers themselves.
11241  */
11242  local_rscale = sig_digits - 2 * base_prod.weight * DEC_DIGITS;
11243  local_rscale = Min(local_rscale, 2 * base_prod.dscale);
11244  local_rscale = Max(local_rscale, NUMERIC_MIN_DISPLAY_SCALE);
11245 
11246  mul_var(&base_prod, &base_prod, &base_prod, local_rscale);
11247 
11248  if (mask & 1)
11249  {
11250  local_rscale = sig_digits -
11251  (base_prod.weight + result->weight) * DEC_DIGITS;
11252  local_rscale = Min(local_rscale,
11253  base_prod.dscale + result->dscale);
11254  local_rscale = Max(local_rscale, NUMERIC_MIN_DISPLAY_SCALE);
11255 
11256  mul_var(&base_prod, result, result, local_rscale);
11257  }
11258 
11259  /*
11260  * When abs(base) > 1, the number of digits to the left of the decimal
11261  * point in base_prod doubles at each iteration, so if exp is large we
11262  * could easily spend large amounts of time and memory space doing the
11263  * multiplications. But once the weight exceeds what will fit in
11264  * int16, the final result is guaranteed to overflow (or underflow, if
11265  * exp < 0), so we can give up before wasting too many cycles.
11266  */
11267  if (base_prod.weight > SHRT_MAX || result->weight > SHRT_MAX)
11268  {
11269  /* overflow, unless neg, in which case result should be 0 */
11270  if (!neg)
11271  ereport(ERROR,
11272  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
11273  errmsg("value overflows numeric format")));
11274  zero_var(result);
11275  neg = false;
11276  break;
11277  }
11278  }
11279 
11280  free_var(&base_prod);
11281 
11282  /* Compensate for input sign, and round to requested rscale */
11283  if (neg)
11284  div_var_fast(&const_one, result, result, rscale, true);
11285  else
11286  round_var(result, rscale);
11287 }

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

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

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

11323 {
11324  int rscale;
11325  NumericVar rlen;
11326  int res_ndigits;
11327  int n;
11328  int pow10;
11329  int i;
11330  uint64 rlen64;
11331  int rlen64_ndigits;
11332 
11333  rscale = Max(rmin->dscale, rmax->dscale);
11334 
11335  /* Compute rlen = rmax - rmin and check the range bounds */
11336  init_var(&rlen);
11337  sub_var(rmax, rmin, &rlen);
11338 
11339  if (rlen.sign == NUMERIC_NEG)
11340  ereport(ERROR,
11341  errcode(ERRCODE_INVALID_PARAMETER_VALUE),
11342  errmsg("lower bound must be less than or equal to upper bound"));
11343 
11344  /* Special case for an empty range */
11345  if (rlen.ndigits == 0)
11346  {
11347  set_var_from_var(rmin, result);
11348  result->dscale = rscale;
11349  free_var(&rlen);
11350  return;
11351  }
11352 
11353  /*
11354  * Otherwise, select a random value in the range [0, rlen = rmax - rmin],
11355  * and shift it to the required range by adding rmin.
11356  */
11357 
11358  /* Required result digits */
11359  res_ndigits = rlen.weight + 1 + (rscale + DEC_DIGITS - 1) / DEC_DIGITS;
11360 
11361  /*
11362  * To get the required rscale, the final result digit must be a multiple
11363  * of pow10 = 10^n, where n = (-rscale) mod DEC_DIGITS.
11364  */
11365  n = ((rscale + DEC_DIGITS - 1) / DEC_DIGITS) * DEC_DIGITS - rscale;
11366  pow10 = 1;
11367  for (i = 0; i < n; i++)
11368  pow10 *= 10;
11369 
11370  /*
11371  * To choose a random value uniformly from the range [0, rlen], we choose
11372  * from the slightly larger range [0, rlen2], where rlen2 is formed from
11373  * rlen by copying the first 4 NBASE digits, and setting all remaining
11374  * decimal digits to "9".
11375  *
11376  * Without loss of generality, we can ignore the weight of rlen2 and treat
11377  * it as a pure integer for the purposes of this discussion. The process
11378  * above gives rlen2 + 1 = rlen64 * 10^N, for some integer N, where rlen64
11379  * is a 64-bit integer formed from the first 4 NBASE digits copied from
11380  * rlen. Since this trivially factors into smaller pieces that fit in
11381  * 64-bit integers, the task of choosing a random value uniformly from the
11382  * rlen2 + 1 possible values in [0, rlen2] is much simpler.
11383  *
11384  * If the random value selected is too large, it is rejected, and we try
11385  * again until we get a result <= rlen, ensuring that the overall result
11386  * is uniform (no particular value is any more likely than any other).
11387  *
11388  * Since rlen64 holds 4 NBASE digits from rlen, it contains at least
11389  * DEC_DIGITS * 3 + 1 decimal digits (i.e., at least 13 decimal digits,
11390  * when DEC_DIGITS is 4). Therefore the probability of needing to reject
11391  * the value chosen and retry is less than 1e-13.
11392  */
11393  rlen64 = (uint64) rlen.digits[0];
11394  rlen64_ndigits = 1;
11395  while (rlen64_ndigits < res_ndigits && rlen64_ndigits < 4)
11396  {
11397  rlen64 *= NBASE;
11398  if (rlen64_ndigits < rlen.ndigits)
11399  rlen64 += rlen.digits[rlen64_ndigits];
11400  rlen64_ndigits++;
11401  }
11402 
11403  /* Loop until we get a result <= rlen */
11404  do
11405  {
11406  NumericDigit *res_digits;
11407  uint64 rand;
11408  int whole_ndigits;
11409 
11410  alloc_var(result, res_ndigits);
11411  result->sign = NUMERIC_POS;
11412  result->weight = rlen.weight;
11413  result->dscale = rscale;
11414  res_digits = result->digits;
11415 
11416  /*
11417  * Set the first rlen64_ndigits using a random value in [0, rlen64].
11418  *
11419  * If this is the whole result, and rscale is not a multiple of
11420  * DEC_DIGITS (pow10 from above is not 1), then we need this to be a
11421  * multiple of pow10.
11422  */
11423  if (rlen64_ndigits == res_ndigits && pow10 != 1)
11424  rand = pg_prng_uint64_range(state, 0, rlen64 / pow10) * pow10;
11425  else
11426  rand = pg_prng_uint64_range(state, 0, rlen64);
11427 
11428  for (i = rlen64_ndigits - 1; i >= 0; i--)
11429  {
11430  res_digits[i] = (NumericDigit) (rand % NBASE);
11431  rand = rand / NBASE;
11432  }
11433 
11434  /*
11435  * Set the remaining digits to random values in range [0, NBASE),
11436  * noting that the last digit needs to be a multiple of pow10.
11437  */
11438  whole_ndigits = res_ndigits;
11439  if (pow10 != 1)
11440  whole_ndigits--;
11441 
11442  /* Set whole digits in groups of 4 for best performance */
11443  i = rlen64_ndigits;
11444  while (i < whole_ndigits - 3)
11445  {
11446  rand = pg_prng_uint64_range(state, 0,
11447  (uint64) NBASE * NBASE * NBASE * NBASE - 1);
11448  res_digits[i++] = (NumericDigit) (rand % NBASE);
11449  rand = rand / NBASE;
11450  res_digits[i++] = (NumericDigit) (rand % NBASE);
11451  rand = rand / NBASE;
11452  res_digits[i++] = (NumericDigit) (rand % NBASE);
11453  rand = rand / NBASE;
11454  res_digits[i++] = (NumericDigit) rand;
11455  }
11456 
11457  /* Remaining whole digits */
11458  while (i < whole_ndigits)
11459  {
11460  rand = pg_prng_uint64_range(state, 0, NBASE - 1);
11461  res_digits[i++] = (NumericDigit) rand;
11462  }
11463 
11464  /* Final partial digit (multiple of pow10) */
11465  if (i < res_ndigits)
11466  {
11467  rand = pg_prng_uint64_range(state, 0, NBASE / pow10 - 1) * pow10;
11468  res_digits[i] = (NumericDigit) rand;
11469  }
11470 
11471  /* Remove leading/trailing zeroes */
11472  strip_var(result);
11473 
11474  /* If result > rlen, try again */
11475 
11476  } while (cmp_var(result, &rlen) > 0);
11477 
11478  /* Offset the result to the required range */
11479  add_var(result, rmin, result);
11480 
11481  free_var(&rlen);
11482 }
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 11749 of file numeric.c.

11750 {
11751  NumericDigit *digits = var->digits;
11752  int di;
11753  int ndigits;
11754  int carry;
11755 
11756  var->dscale = rscale;
11757 
11758  /* decimal digits wanted */
11759  di = (var->weight + 1) * DEC_DIGITS + rscale;
11760 
11761  /*
11762  * If di = 0, the value loses all digits, but could round up to 1 if its
11763  * first extra digit is >= 5. If di < 0 the result must be 0.
11764  */
11765  if (di < 0)
11766  {
11767  var->ndigits = 0;
11768  var->weight = 0;
11769  var->sign = NUMERIC_POS;
11770  }
11771  else
11772  {
11773  /* NBASE digits wanted */
11774  ndigits = (di + DEC_DIGITS - 1) / DEC_DIGITS;
11775 
11776  /* 0, or number of decimal digits to keep in last NBASE digit */
11777  di %= DEC_DIGITS;
11778 
11779  if (ndigits < var->ndigits ||
11780  (ndigits == var->ndigits && di > 0))
11781  {
11782  var->ndigits = ndigits;
11783 
11784 #if DEC_DIGITS == 1
11785  /* di must be zero */
11786  carry = (digits[ndigits] >= HALF_NBASE) ? 1 : 0;
11787 #else
11788  if (di == 0)
11789  carry = (digits[ndigits] >= HALF_NBASE) ? 1 : 0;
11790  else
11791  {
11792  /* Must round within last NBASE digit */
11793  int extra,
11794  pow10;
11795 
11796 #if DEC_DIGITS == 4
11797  pow10 = round_powers[di];
11798 #elif DEC_DIGITS == 2
11799  pow10 = 10;
11800 #else
11801 #error unsupported NBASE
11802 #endif
11803  extra = digits[--ndigits] % pow10;
11804  digits[ndigits] -= extra;
11805  carry = 0;
11806  if (extra >= pow10 / 2)
11807  {
11808  pow10 += digits[ndigits];
11809  if (pow10 >= NBASE)
11810  {
11811  pow10 -= NBASE;
11812  carry = 1;
11813  }
11814  digits[ndigits] = pow10;
11815  }
11816  }
11817 #endif
11818 
11819  /* Propagate carry if needed */
11820  while (carry)
11821  {
11822  carry += digits[--ndigits];
11823  if (carry >= NBASE)
11824  {
11825  digits[ndigits] = carry - NBASE;
11826  carry = 1;
11827  }
11828  else
11829  {
11830  digits[ndigits] = carry;
11831  carry = 0;
11832  }
11833  }
11834 
11835  if (ndigits < 0)
11836  {
11837  Assert(ndigits == -1); /* better not have added > 1 digit */
11838  Assert(var->digits > var->buf);
11839  var->digits--;
11840  var->ndigits++;
11841  var->weight++;
11842  }
11843  }
11844  }
11845 }
static const int round_powers[4]
Definition: numeric.c:459

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

9778 {
9779  int weight1,
9780  weight2,
9781  qweight,
9782  i;
9783  NumericDigit firstdigit1,
9784  firstdigit2;
9785  int rscale;
9786 
9787  /*
9788  * The result scale of a division isn't specified in any SQL standard. For
9789  * PostgreSQL we select a result scale that will give at least
9790  * NUMERIC_MIN_SIG_DIGITS significant digits, so that numeric gives a
9791  * result no less accurate than float8; but use a scale not less than
9792  * either input's display scale.
9793  */
9794 
9795  /* Get the actual (normalized) weight and first digit of each input */
9796 
9797  weight1 = 0; /* values to use if var1 is zero */
9798  firstdigit1 = 0;
9799  for (i = 0; i < var1->ndigits; i++)
9800  {
9801  firstdigit1 = var1->digits[i];
9802  if (firstdigit1 != 0)
9803  {
9804  weight1 = var1->weight - i;
9805  break;
9806  }
9807  }
9808 
9809  weight2 = 0; /* values to use if var2 is zero */
9810  firstdigit2 = 0;
9811  for (i = 0; i < var2->ndigits; i++)
9812  {
9813  firstdigit2 = var2->digits[i];
9814  if (firstdigit2 != 0)
9815  {
9816  weight2 = var2->weight - i;
9817  break;
9818  }
9819  }
9820 
9821  /*
9822  * Estimate weight of quotient. If the two first digits are equal, we
9823  * can't be sure, but assume that var1 is less than var2.
9824  */
9825  qweight = weight1 - weight2;
9826  if (firstdigit1 <= firstdigit2)
9827  qweight--;
9828 
9829  /* Select result scale */
9830  rscale = NUMERIC_MIN_SIG_DIGITS - qweight * DEC_DIGITS;
9831  rscale = Max(rscale, var1->dscale);
9832  rscale = Max(rscale, var2->dscale);
9833  rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
9834  rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
9835 
9836  return rscale;
9837 }

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 compute_bucket(), 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 7242 of file numeric.c.

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

References add_var(), generate_unaccent_rules::dest, ereturn, errcode(), errmsg(), free_var(), init_var, int64_to_numericvar(), mul_var(), PG_INT64_MAX, sign, generate_unaccent_rules::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 7420 of file numeric.c.

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

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

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

References alloc_var(), DEC_DIGITS, generate_unaccent_rules::dest, digits, ereturn, errcode(), errmsg(), i, NUMERIC_NEG, NUMERIC_POS, palloc(), pfree(), PG_INT32_MAX, sign, generate_unaccent_rules::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 7468 of file numeric.c.

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

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

Referenced by accum_sum_final(), ceil_var(), compute_bucket(), 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 10062 of file numeric.c.

10063 {
10064  int stat;
10065  int res_weight;
10066  int res_ndigits;
10067  int src_ndigits;
10068  int step;
10069  int ndigits[32];
10070  int blen;
10071  int64 arg_int64;
10072  int src_idx;
10073  int64 s_int64;
10074  int64 r_int64;
10075  NumericVar s_var;
10076  NumericVar r_var;
10077  NumericVar a0_var;
10078  NumericVar a1_var;
10079  NumericVar q_var;
10080  NumericVar u_var;
10081 
10082  stat = cmp_var(arg, &const_zero);
10083  if (stat == 0)
10084  {
10085  zero_var(result);
10086  result->dscale = rscale;
10087  return;
10088  }
10089 
10090  /*
10091  * SQL2003 defines sqrt() in terms of power, so we need to emit the right
10092  * SQLSTATE error code if the operand is negative.
10093  */
10094  if (stat < 0)
10095  ereport(ERROR,
10096  (errcode(ERRCODE_INVALID_ARGUMENT_FOR_POWER_FUNCTION),
10097  errmsg("cannot take square root of a negative number")));
10098 
10099  init_var(&s_var);
10100  init_var(&r_var);
10101  init_var(&a0_var);
10102  init_var(&a1_var);
10103  init_var(&q_var);
10104  init_var(&u_var);
10105 
10106  /*
10107  * The result weight is half the input weight, rounded towards minus
10108  * infinity --- res_weight = floor(arg->weight / 2).
10109  */
10110  if (arg->weight >= 0)
10111  res_weight = arg->weight / 2;
10112  else
10113  res_weight = -((-arg->weight - 1) / 2 + 1);
10114 
10115  /*
10116  * Number of NBASE digits to compute. To ensure correct rounding, compute
10117  * at least 1 extra decimal digit. We explicitly allow rscale to be
10118  * negative here, but must always compute at least 1 NBASE digit. Thus
10119  * res_ndigits = res_weight + 1 + ceil((rscale + 1) / DEC_DIGITS) or 1.
10120  */
10121  if (rscale + 1 >= 0)
10122  res_ndigits = res_weight + 1 + (rscale + DEC_DIGITS) / DEC_DIGITS;
10123  else
10124  res_ndigits = res_weight + 1 - (-rscale - 1) / DEC_DIGITS;
10125  res_ndigits = Max(res_ndigits, 1);
10126 
10127  /*
10128  * Number of source NBASE digits logically required to produce a result
10129  * with this precision --- every digit before the decimal point, plus 2
10130  * for each result digit after the decimal point (or minus 2 for each
10131  * result digit we round before the decimal point).
10132  */
10133  src_ndigits = arg->weight + 1 + (res_ndigits - res_weight - 1) * 2;
10134  src_ndigits = Max(src_ndigits, 1);
10135 
10136  /* ----------
10137  * From this point on, we treat the input and the result as integers and
10138  * compute the integer square root and remainder using the Karatsuba
10139  * Square Root algorithm, which may be written recursively as follows:
10140  *
10141  * SqrtRem(n = a3*b^3 + a2*b^2 + a1*b + a0):
10142  * [ for some base b, and coefficients a0,a1,a2,a3 chosen so that
10143  * 0 <= a0,a1,a2 < b and a3 >= b/4 ]
10144  * Let (s,r) = SqrtRem(a3*b + a2)
10145  * Let (q,u) = DivRem(r*b + a1, 2*s)
10146  * Let s = s*b + q
10147  * Let r = u*b + a0 - q^2
10148  * If r < 0 Then
10149  * Let r = r + s
10150  * Let s = s - 1
10151  * Let r = r + s
10152  * Return (s,r)
10153  *
10154  * See "Karatsuba Square Root", Paul Zimmermann, INRIA Research Report
10155  * RR-3805, November 1999. At the time of writing this was available
10156  * on the net at <https://hal.inria.fr/inria-00072854>.
10157  *
10158  * The way to read the assumption "n = a3*b^3 + a2*b^2 + a1*b + a0" is
10159  * "choose a base b such that n requires at least four base-b digits to
10160  * express; then those digits are a3,a2,a1,a0, with a3 possibly larger
10161  * than b". For optimal performance, b should have approximately a
10162  * quarter the number of digits in the input, so that the outer square
10163  * root computes roughly twice as many digits as the inner one. For
10164  * simplicity, we choose b = NBASE^blen, an integer power of NBASE.
10165  *
10166  * We implement the algorithm iteratively rather than recursively, to
10167  * allow the working variables to be reused. With this approach, each
10168  * digit of the input is read precisely once --- src_idx tracks the number
10169  * of input digits used so far.
10170  *
10171  * The array ndigits[] holds the number of NBASE digits of the input that
10172  * will have been used at the end of each iteration, which roughly doubles
10173  * each time. Note that the array elements are stored in reverse order,
10174  * so if the final iteration requires src_ndigits = 37 input digits, the
10175  * array will contain [37,19,11,7,5,3], and we would start by computing
10176  * the square root of the 3 most significant NBASE digits.
10177  *
10178  * In each iteration, we choose blen to be the largest integer for which
10179  * the input number has a3 >= b/4, when written in the form above. In
10180  * general, this means blen = src_ndigits / 4 (truncated), but if
10181  * src_ndigits is a multiple of 4, that might lead to the coefficient a3
10182  * being less than b/4 (if the first input digit is less than NBASE/4), in
10183  * which case we choose blen = src_ndigits / 4 - 1. The number of digits
10184  * in the inner square root is then src_ndigits - 2*blen. So, for
10185  * example, if we have src_ndigits = 26 initially, the array ndigits[]
10186  * will be either [26,14,8,4] or [26,14,8,6,4], depending on the size of
10187  * the first input digit.
10188  *
10189  * Additionally, we can put an upper bound on the number of steps required
10190  * as follows --- suppose that the number of source digits is an n-bit
10191  * number in the range [2^(n-1), 2^n-1], then blen will be in the range
10192  * [2^(n-3)-1, 2^(n-2)-1] and the number of digits in the inner square
10193  * root will be in the range [2^(n-2), 2^(n-1)+1]. In the next step, blen
10194  * will be in the range [2^(n-4)-1, 2^(n-3)] and the number of digits in
10195  * the next inner square root will be in the range [2^(n-3), 2^(n-2)+1].
10196  * This pattern repeats, and in the worst case the array ndigits[] will
10197  * contain [2^n-1, 2^(n-1)+1, 2^(n-2)+1, ... 9, 5, 3], and the computation
10198  * will require n steps. Therefore, since all digit array sizes are
10199  * signed 32-bit integers, the number of steps required is guaranteed to
10200  * be less than 32.
10201  * ----------
10202  */
10203  step = 0;
10204  while ((ndigits[step] = src_ndigits) > 4)
10205  {
10206  /* Choose b so that a3 >= b/4, as described above */
10207  blen = src_ndigits / 4;
10208  if (blen * 4 == src_ndigits && arg->digits[0] < NBASE / 4)
10209  blen--;
10210 
10211  /* Number of digits in the next step (inner square root) */
10212  src_ndigits -= 2 * blen;
10213  step++;
10214  }
10215 
10216  /*
10217  * First iteration (innermost square root and remainder):
10218  *
10219  * Here src_ndigits <= 4, and the input fits in an int64. Its square root
10220  * has at most 9 decimal digits, so estimate it using double precision
10221  * arithmetic, which will in fact almost certainly return the correct
10222  * result with no further correction required.
10223  */
10224  arg_int64 = arg->digits[0];
10225  for (src_idx = 1; src_idx < src_ndigits; src_idx++)
10226  {
10227  arg_int64 *= NBASE;
10228  if (src_idx < arg->ndigits)
10229  arg_int64 += arg->digits[src_idx];
10230  }
10231 
10232  s_int64 = (int64) sqrt((double) arg_int64);
10233  r_int64 = arg_int64 - s_int64 * s_int64;
10234 
10235  /*
10236  * Use Newton's method to correct the result, if necessary.
10237  *
10238  * This uses integer division with truncation to compute the truncated
10239  * integer square root by iterating using the formula x -> (x + n/x) / 2.
10240  * This is known to converge to isqrt(n), unless n+1 is a perfect square.
10241  * If n+1 is a perfect square, the sequence will oscillate between the two
10242  * values isqrt(n) and isqrt(n)+1, so we can be assured of convergence by
10243  * checking the remainder.
10244  */
10245  while (r_int64 < 0 || r_int64 > 2 * s_int64)
10246  {
10247  s_int64 = (s_int64 + arg_int64 / s_int64) / 2;
10248  r_int64 = arg_int64 - s_int64 * s_int64;
10249  }
10250 
10251  /*
10252  * Iterations with src_ndigits <= 8:
10253  *
10254  * The next 1 or 2 iterations compute larger (outer) square roots with
10255  * src_ndigits <= 8, so the result still fits in an int64 (even though the
10256  * input no longer does) and we can continue to compute using int64
10257  * variables to avoid more expensive numeric computations.
10258  *
10259  * It is fairly easy to see that there is no risk of the intermediate
10260  * values below overflowing 64-bit integers. In the worst case, the
10261  * previous iteration will have computed a 3-digit square root (of a
10262  * 6-digit input less than NBASE^6 / 4), so at the start of this
10263  * iteration, s will be less than NBASE^3 / 2 = 10^12 / 2, and r will be
10264  * less than 10^12. In this case, blen will be 1, so numer will be less
10265  * than 10^17, and denom will be less than 10^12 (and hence u will also be
10266  * less than 10^12). Finally, since q^2 = u*b + a0 - r, we can also be
10267  * sure that q^2 < 10^17. Therefore all these quantities fit comfortably
10268  * in 64-bit integers.
10269  */
10270  step--;
10271  while (step >= 0 && (src_ndigits = ndigits[step]) <= 8)
10272  {
10273  int b;
10274  int a0;
10275  int a1;
10276  int i;
10277  int64 numer;
10278  int64 denom;
10279  int64 q;
10280  int64 u;
10281 
10282  blen = (src_ndigits - src_idx) / 2;
10283 
10284  /* Extract a1 and a0, and compute b */
10285  a0 = 0;
10286  a1 = 0;
10287  b = 1;
10288 
10289  for (i = 0; i < blen; i++, src_idx++)
10290  {
10291  b *= NBASE;
10292  a1 *= NBASE;
10293  if (src_idx < arg->ndigits)
10294  a1 += arg->digits[src_idx];
10295  }
10296 
10297  for (i = 0; i < blen; i++, src_idx++)
10298  {
10299  a0 *= NBASE;
10300  if (src_idx < arg->ndigits)
10301  a0 += arg->digits[src_idx];
10302  }
10303 
10304  /* Compute (q,u) = DivRem(r*b + a1, 2*s) */
10305  numer = r_int64 * b + a1;
10306  denom = 2 * s_int64;
10307  q = numer / denom;
10308  u = numer - q * denom;
10309 
10310  /* Compute s = s*b + q and r = u*b + a0 - q^2 */
10311  s_int64 = s_int64 * b + q;
10312  r_int64 = u * b + a0 - q * q;
10313 
10314  if (r_int64 < 0)
10315  {
10316  /* s is too large by 1; set r += s, s--, r += s */
10317  r_int64 += s_int64;
10318  s_int64--;
10319  r_int64 += s_int64;
10320  }
10321 
10322  Assert(src_idx == src_ndigits); /* All input digits consumed */
10323  step--;
10324  }
10325 
10326  /*
10327  * On platforms with 128-bit integer support, we can further delay the
10328  * need to use numeric variables.
10329  */
10330 #ifdef HAVE_INT128
10331  if (step >= 0)
10332  {
10333  int128 s_int128;
10334  int128 r_int128;
10335 
10336  s_int128 = s_int64;
10337  r_int128 = r_int64;
10338 
10339  /*
10340  * Iterations with src_ndigits <= 16:
10341  *
10342  * The result fits in an int128 (even though the input doesn't) so we
10343  * use int128 variables to avoid more expensive numeric computations.
10344  */
10345  while (step >= 0 && (src_ndigits = ndigits[step]) <= 16)
10346  {
10347  int64 b;
10348  int64 a0;
10349  int64 a1;
10350  int64 i;
10351  int128 numer;
10352  int128 denom;
10353  int128 q;
10354  int128 u;
10355 
10356  blen = (src_ndigits - src_idx) / 2;
10357 
10358  /* Extract a1 and a0, and compute b */
10359  a0 = 0;
10360  a1 = 0;
10361  b = 1;
10362 
10363  for (i = 0; i < blen; i++, src_idx++)
10364  {
10365  b *= NBASE;
10366  a1 *= NBASE;
10367  if (src_idx < arg->ndigits)
10368  a1 += arg->digits[src_idx];
10369  }
10370 
10371  for (i = 0; i < blen; i++, src_idx++)
10372  {
10373  a0 *= NBASE;
10374  if (src_idx < arg->ndigits)
10375  a0 += arg->digits[src_idx];
10376  }
10377 
10378  /* Compute (q,u) = DivRem(r*b + a1, 2*s) */
10379  numer = r_int128 * b + a1;
10380  denom = 2 * s_int128;
10381  q = numer / denom;
10382  u = numer - q * denom;
10383 
10384  /* Compute s = s*b + q and r = u*b + a0 - q^2 */
10385  s_int128 = s_int128 * b + q;
10386  r_int128 = u * b + a0 - q * q;
10387 
10388  if (r_int128 < 0)
10389  {
10390  /* s is too large by 1; set r += s, s--, r += s */
10391  r_int128 += s_int128;
10392  s_int128--;
10393  r_int128 += s_int128;
10394  }
10395 
10396  Assert(src_idx == src_ndigits); /* All input digits consumed */
10397  step--;
10398  }
10399 
10400  /*
10401  * All remaining iterations require numeric variables. Convert the
10402  * integer values to NumericVar and continue. Note that in the final
10403  * iteration we don't need the remainder, so we can save a few cycles
10404  * there by not fully computing it.
10405  */
10406  int128_to_numericvar(s_int128, &s_var);
10407  if (step >= 0)
10408  int128_to_numericvar(r_int128, &r_var);
10409  }
10410  else
10411  {
10412  int64_to_numericvar(s_int64, &s_var);
10413  /* step < 0, so we certainly don't need r */
10414  }
10415 #else /* !HAVE_INT128 */
10416  int64_to_numericvar(s_int64, &s_var);
10417  if (step >= 0)
10418  int64_to_numericvar(r_int64, &r_var);
10419 #endif /* HAVE_INT128 */
10420 
10421  /*
10422  * The remaining iterations with src_ndigits > 8 (or 16, if have int128)
10423  * use numeric variables.
10424  */
10425  while (step >= 0)
10426  {
10427  int tmp_len;
10428 
10429  src_ndigits = ndigits[step];
10430  blen = (src_ndigits - src_idx) / 2;
10431 
10432  /* Extract a1 and a0 */
10433  if (src_idx < arg->ndigits)
10434  {
10435  tmp_len = Min(blen, arg->ndigits - src_idx);
10436  alloc_var(&a1_var, tmp_len);
10437  memcpy(a1_var.digits, arg->digits + src_idx,
10438  tmp_len * sizeof(NumericDigit));
10439  a1_var.weight = blen - 1;
10440  a1_var.sign = NUMERIC_POS;
10441  a1_var.dscale = 0;
10442  strip_var(&a1_var);
10443  }
10444  else
10445  {
10446  zero_var(&a1_var);
10447  a1_var.dscale = 0;
10448  }
10449  src_idx += blen;
10450 
10451  if (src_idx < arg->ndigits)
10452  {
10453  tmp_len = Min(blen, arg->ndigits - src_idx);
10454  alloc_var(&a0_var, tmp_len);
10455  memcpy(a0_var.digits, arg->digits + src_idx,
10456  tmp_len * sizeof(NumericDigit));
10457  a0_var.weight = blen - 1;
10458  a0_var.sign = NUMERIC_POS;
10459  a0_var.dscale = 0;
10460  strip_var(&a0_var);
10461  }
10462  else
10463  {
10464  zero_var(&a0_var);
10465  a0_var.dscale = 0;
10466  }
10467  src_idx += blen;
10468 
10469  /* Compute (q,u) = DivRem(r*b + a1, 2*s) */
10470  set_var_from_var(&r_var, &q_var);
10471  q_var.weight += blen;
10472  add_var(&q_var, &a1_var, &q_var);
10473  add_var(&s_var, &s_var, &u_var);
10474  div_mod_var(&q_var, &u_var, &q_var, &u_var);
10475 
10476  /* Compute s = s*b + q */
10477  s_var.weight += blen;
10478  add_var(&s_var, &q_var, &s_var);
10479 
10480  /*
10481  * Compute r = u*b + a0 - q^2.
10482  *
10483  * In the final iteration, we don't actually need r; we just need to
10484  * know whether it is negative, so that we know whether to adjust s.
10485  * So instead of the final subtraction we can just compare.
10486  */
10487  u_var.weight += blen;
10488  add_var(&u_var, &a0_var, &u_var);
10489  mul_var(&q_var, &q_var, &q_var, 0);
10490 
10491  if (step > 0)
10492  {
10493  /* Need r for later iterations */
10494  sub_var(&u_var, &q_var, &r_var);
10495  if (r_var.sign == NUMERIC_NEG)
10496  {
10497  /* s is too large by 1; set r += s, s--, r += s */
10498  add_var(&r_var, &s_var, &r_var);
10499  sub_var(&s_var, &const_one, &s_var);
10500  add_var(&r_var, &s_var, &r_var);
10501  }
10502  }
10503  else
10504  {
10505  /* Don't need r anymore, except to test if s is too large by 1 */
10506  if (cmp_var(&u_var, &q_var) < 0)
10507  sub_var(&s_var, &const_one, &s_var);
10508  }
10509 
10510  Assert(src_idx == src_ndigits); /* All input digits consumed */
10511  step--;
10512  }
10513 
10514  /*
10515  * Construct the final result, rounding it to the requested precision.
10516  */
10517  set_var_from_var(&s_var, result);
10518  result->weight = res_weight;
10519  result->sign = NUMERIC_POS;
10520 
10521  /* Round to target rscale (and set result->dscale) */
10522  round_var(result, rscale);
10523 
10524  /* Strip leading and trailing zeroes */
10525  strip_var(result);
10526 
10527  free_var(&s_var);
10528  free_var(&r_var);
10529  free_var(&a0_var);
10530  free_var(&a1_var);
10531  free_var(&q_var);
10532  free_var(&u_var);
10533 }
static void div_mod_var(const NumericVar *var1, const NumericVar *var2, NumericVar *quot, NumericVar *rem)
Definition: numeric.c:9875
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 11917 of file numeric.c.

11918 {
11919  NumericDigit *digits = var->digits;
11920  int ndigits = var->ndigits;
11921 
11922  /* Strip leading zeroes */
11923  while (ndigits > 0 && *digits == 0)
11924  {
11925  digits++;
11926  var->weight--;
11927  ndigits--;
11928  }
11929 
11930  /* Strip trailing zeroes */
11931  while (ndigits > 0 && digits[ndigits - 1] == 0)
11932  ndigits--;
11933 
11934  /* If it's zero, normalize the sign and weight */
11935  if (ndigits == 0)
11936  {
11937  var->sign = NUMERIC_POS;
11938  var->weight = 0;
11939  }
11940 
11941  var->digits = digits;
11942  var->ndigits = ndigits;
11943 }

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(), 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 11667 of file numeric.c.

11668 {
11669  NumericDigit *res_buf;
11670  NumericDigit *res_digits;
11671  int res_ndigits;
11672  int res_weight;
11673  int res_rscale,
11674  rscale1,
11675  rscale2;
11676  int res_dscale;
11677  int i,
11678  i1,
11679  i2;
11680  int borrow = 0;
11681 
11682  /* copy these values into local vars for speed in inner loop */
11683  int var1ndigits = var1->ndigits;
11684  int var2ndigits = var2->ndigits;
11685  NumericDigit *var1digits = var1->digits;
11686  NumericDigit *var2digits = var2->digits;
11687 
11688  res_weight = var1->weight;
11689 
11690  res_dscale = Max(var1->dscale, var2->dscale);
11691 
11692  /* Note: here we are figuring rscale in base-NBASE digits */
11693  rscale1 = var1->ndigits - var1->weight - 1;
11694  rscale2 = var2->ndigits - var2->weight - 1;
11695  res_rscale = Max(rscale1, rscale2);
11696 
11697  res_ndigits = res_rscale + res_weight + 1;
11698  if (res_ndigits <= 0)
11699  res_ndigits = 1;
11700 
11701  res_buf = digitbuf_alloc(res_ndigits + 1);
11702  res_buf[0] = 0; /* spare digit for later rounding */
11703  res_digits = res_buf + 1;
11704 
11705  i1 = res_rscale + var1->weight + 1;
11706  i2 = res_rscale + var2->weight + 1;
11707  for (i = res_ndigits - 1; i >= 0; i--)
11708  {
11709  i1--;
11710  i2--;
11711  if (i1 >= 0 && i1 < var1ndigits)
11712  borrow += var1digits[i1];
11713  if (i2 >= 0 && i2 < var2ndigits)
11714  borrow -= var2digits[i2];
11715 
11716  if (borrow < 0)
11717  {
11718  res_digits[i] = borrow + NBASE;
11719  borrow = -1;
11720  }
11721  else
11722  {
11723  res_digits[i] = borrow;
11724  borrow = 0;
11725  }
11726  }
11727 
11728  Assert(borrow == 0); /* else caller gave us var1 < var2 */
11729 
11730  digitbuf_free(result->buf);
11731  result->ndigits = res_ndigits;
11732  result->buf = res_buf;
11733  result->digits = res_digits;
11734  result->weight = res_weight;
11735  result->dscale = res_dscale;
11736 
11737  /* Remove leading/trailing zeroes */
11738  strip_var(result);
11739 }

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

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

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

11856 {
11857  int di;
11858  int ndigits;
11859 
11860  var->dscale = rscale;
11861 
11862  /* decimal digits wanted */
11863  di = (var->weight + 1) * DEC_DIGITS + rscale;
11864 
11865  /*
11866  * If di <= 0, the value loses all digits.
11867  */
11868  if (di <= 0)
11869  {
11870  var->ndigits = 0;
11871  var->weight = 0;
11872  var->sign = NUMERIC_POS;
11873  }
11874  else
11875  {
11876  /* NBASE digits wanted */
11877  ndigits = (di + DEC_DIGITS - 1) / DEC_DIGITS;
11878 
11879  if (ndigits <= var->ndigits)
11880  {
11881  var->ndigits = ndigits;
11882 
11883 #if DEC_DIGITS == 1
11884  /* no within-digit stuff to worry about */
11885 #else
11886  /* 0, or number of decimal digits to keep in last NBASE digit */
11887  di %= DEC_DIGITS;
11888 
11889  if (di > 0)
11890  {
11891  /* Must truncate within last NBASE digit */
11892  NumericDigit *digits = var->digits;
11893  int extra,
11894  pow10;
11895 
11896 #if DEC_DIGITS == 4
11897  pow10 = round_powers[di];
11898 #elif DEC_DIGITS == 2
11899  pow10 = 10;
11900 #else
11901 #error unsupported NBASE
11902 #endif
11903  extra = digits[--ndigits] % pow10;
11904  digits[ndigits] -= extra;
11905  }
11906 #endif
11907  }
11908  }
11909 }

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

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

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

7216 {
7217  return dig >= '0' && dig <= '9' ? dig - '0' :
7218  dig >= 'a' && dig <= 'f' ? dig - 'a' + 10 :
7219  dig >= 'A' && dig <= 'F' ? dig - 'A' + 10 : -1;
7220 }

Referenced by set_var_from_non_decimal_integer_str().

◆ zero_var()

static void zero_var ( NumericVar var)
static

Definition at line 6985 of file numeric.c.

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

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:418

Definition at line 422 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 418 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:440

Definition at line 446 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 440 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:425

Definition at line 426 of file numeric.c.

Referenced by ln_var().

◆ const_two_data

const NumericDigit const_two_data[1] = {2}
static

Definition at line 425 of file numeric.c.

◆ const_zero

◆ const_zero_data

const NumericDigit const_zero_data[1] = {0}
static

Definition at line 414 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:430

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

◆ round_powers

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

Definition at line 459 of file numeric.c.

Referenced by round_var(), and trunc_var().