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 NBASE_SQR   (NBASE * NBASE)
 
#define NUMERIC_SIGN_MASK   0xC000
 
#define NUMERIC_POS   0x0000
 
#define NUMERIC_NEG   0x4000
 
#define NUMERIC_SHORT   0x8000
 
#define NUMERIC_SPECIAL   0xC000
 
#define NUMERIC_FLAGBITS(n)   ((n)->choice.n_header & NUMERIC_SIGN_MASK)
 
#define NUMERIC_IS_SHORT(n)   (NUMERIC_FLAGBITS(n) == NUMERIC_SHORT)
 
#define NUMERIC_IS_SPECIAL(n)   (NUMERIC_FLAGBITS(n) == NUMERIC_SPECIAL)
 
#define NUMERIC_HDRSZ   (VARHDRSZ + sizeof(uint16) + sizeof(int16))
 
#define NUMERIC_HDRSZ_SHORT   (VARHDRSZ + sizeof(uint16))
 
#define NUMERIC_HEADER_IS_SHORT(n)   (((n)->choice.n_header & 0x8000) != 0)
 
#define NUMERIC_HEADER_SIZE(n)
 
#define NUMERIC_EXT_SIGN_MASK   0xF000 /* high bits plus NaN/Inf flag bits */
 
#define NUMERIC_NAN   0xC000
 
#define NUMERIC_PINF   0xD000
 
#define NUMERIC_NINF   0xF000
 
#define NUMERIC_INF_SIGN_MASK   0x2000
 
#define NUMERIC_EXT_FLAGBITS(n)   ((n)->choice.n_header & NUMERIC_EXT_SIGN_MASK)
 
#define NUMERIC_IS_NAN(n)   ((n)->choice.n_header == NUMERIC_NAN)
 
#define NUMERIC_IS_PINF(n)   ((n)->choice.n_header == NUMERIC_PINF)
 
#define NUMERIC_IS_NINF(n)   ((n)->choice.n_header == NUMERIC_NINF)
 
#define NUMERIC_IS_INF(n)    (((n)->choice.n_header & ~NUMERIC_INF_SIGN_MASK) == NUMERIC_PINF)
 
#define NUMERIC_SHORT_SIGN_MASK   0x2000
 
#define NUMERIC_SHORT_DSCALE_MASK   0x1F80
 
#define NUMERIC_SHORT_DSCALE_SHIFT   7
 
#define NUMERIC_SHORT_DSCALE_MAX    (NUMERIC_SHORT_DSCALE_MASK >> NUMERIC_SHORT_DSCALE_SHIFT)
 
#define NUMERIC_SHORT_WEIGHT_SIGN_MASK   0x0040
 
#define NUMERIC_SHORT_WEIGHT_MASK   0x003F
 
#define NUMERIC_SHORT_WEIGHT_MAX   NUMERIC_SHORT_WEIGHT_MASK
 
#define NUMERIC_SHORT_WEIGHT_MIN   (-(NUMERIC_SHORT_WEIGHT_MASK+1))
 
#define NUMERIC_DSCALE_MASK   0x3FFF
 
#define NUMERIC_DSCALE_MAX   NUMERIC_DSCALE_MASK
 
#define NUMERIC_SIGN(n)
 
#define NUMERIC_DSCALE(n)
 
#define NUMERIC_WEIGHT(n)
 
#define NUMERIC_WEIGHT_MAX   PG_INT16_MAX
 
#define NUMERIC_ABBREV_BITS   (SIZEOF_DATUM * BITS_PER_BYTE)
 
#define NumericAbbrevGetDatum(X)   ((Datum) (X))
 
#define DatumGetNumericAbbrev(X)   ((int32) (X))
 
#define NUMERIC_ABBREV_NAN   NumericAbbrevGetDatum(PG_INT32_MIN)
 
#define NUMERIC_ABBREV_PINF   NumericAbbrevGetDatum(-PG_INT32_MAX)
 
#define NUMERIC_ABBREV_NINF   NumericAbbrevGetDatum(PG_INT32_MAX)
 
#define dump_numeric(s, n)
 
#define dump_var(s, v)
 
#define digitbuf_alloc(ndigits)    ((NumericDigit *) palloc((ndigits) * sizeof(NumericDigit)))
 
#define digitbuf_free(buf)
 
#define init_var(v)   memset(v, 0, sizeof(NumericVar))
 
#define NUMERIC_DIGITS(num)
 
#define NUMERIC_NDIGITS(num)    ((VARSIZE(num) - NUMERIC_HEADER_SIZE(num)) / sizeof(NumericDigit))
 
#define NUMERIC_CAN_BE_SHORT(scale, weight)
 
#define NA_TOTAL_COUNT(na)    ((na)->N + (na)->NaNcount + (na)->pInfcount + (na)->nInfcount)
 
#define makePolyNumAggState   makeNumericAggState
 
#define makePolyNumAggStateCurrentContext   makeNumericAggStateCurrentContext
 
#define PRODSUM1(v1, i1, v2, i2)   ((v1)[(i1)] * (v2)[(i2)])
 
#define PRODSUM2(v1, i1, v2, i2)   (PRODSUM1(v1,i1,v2,i2) + (v1)[(i1)+1] * (v2)[(i2)-1])
 
#define PRODSUM3(v1, i1, v2, i2)   (PRODSUM2(v1,i1,v2,i2) + (v1)[(i1)+2] * (v2)[(i2)-2])
 
#define PRODSUM4(v1, i1, v2, i2)   (PRODSUM3(v1,i1,v2,i2) + (v1)[(i1)+3] * (v2)[(i2)-3])
 
#define PRODSUM5(v1, i1, v2, i2)   (PRODSUM4(v1,i1,v2,i2) + (v1)[(i1)+4] * (v2)[(i2)-4])
 
#define PRODSUM6(v1, i1, v2, i2)   (PRODSUM5(v1,i1,v2,i2) + (v1)[(i1)+5] * (v2)[(i2)-5])
 

Typedefs

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

Functions

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

Variables

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

Macro Definition Documentation

◆ DatumGetNumericAbbrev

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

Definition at line 412 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 485 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 487 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 481 of file numeric.c.

◆ dump_var

#define dump_var (   s,
 
)

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

◆ makePolyNumAggState

#define makePolyNumAggState   makeNumericAggState

Definition at line 5542 of file numeric.c.

◆ makePolyNumAggStateCurrentContext

#define makePolyNumAggStateCurrentContext   makeNumericAggStateCurrentContext

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

◆ NBASE

#define NBASE   10000

Definition at line 95 of file numeric.c.

◆ NBASE_SQR

#define NBASE_SQR   (NBASE * NBASE)

Definition at line 104 of file numeric.c.

◆ NUMERIC_ABBREV_BITS

#define NUMERIC_ABBREV_BITS   (SIZEOF_DATUM * BITS_PER_BYTE)

Definition at line 403 of file numeric.c.

◆ NUMERIC_ABBREV_NAN

#define NUMERIC_ABBREV_NAN   NumericAbbrevGetDatum(PG_INT32_MIN)

Definition at line 413 of file numeric.c.

◆ NUMERIC_ABBREV_NINF

#define NUMERIC_ABBREV_NINF   NumericAbbrevGetDatum(PG_INT32_MAX)

Definition at line 415 of file numeric.c.

◆ NUMERIC_ABBREV_PINF

#define NUMERIC_ABBREV_PINF   NumericAbbrevGetDatum(-PG_INT32_MAX)

Definition at line 414 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:218
#define NUMERIC_SHORT_WEIGHT_MIN
Definition: numeric.c:223
#define NUMERIC_SHORT_WEIGHT_MAX
Definition: numeric.c:222
static int scale
Definition: pgbench.c:181

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

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

Definition at line 244 of file numeric.c.

◆ NUMERIC_DSCALE_MASK

#define NUMERIC_DSCALE_MASK   0x3FFF

Definition at line 235 of file numeric.c.

◆ NUMERIC_DSCALE_MAX

#define NUMERIC_DSCALE_MAX   NUMERIC_DSCALE_MASK

Definition at line 236 of file numeric.c.

◆ NUMERIC_EXT_FLAGBITS

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

Definition at line 204 of file numeric.c.

◆ NUMERIC_EXT_SIGN_MASK

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

Definition at line 198 of file numeric.c.

◆ NUMERIC_FLAGBITS

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

Definition at line 172 of file numeric.c.

◆ NUMERIC_HDRSZ

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

Definition at line 176 of file numeric.c.

◆ NUMERIC_HDRSZ_SHORT

#define NUMERIC_HDRSZ_SHORT   (VARHDRSZ + sizeof(uint16))

Definition at line 177 of file numeric.c.

◆ NUMERIC_HEADER_IS_SHORT

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

Definition at line 184 of file numeric.c.

◆ NUMERIC_HEADER_SIZE

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

Definition at line 185 of file numeric.c.

◆ NUMERIC_INF_SIGN_MASK

#define NUMERIC_INF_SIGN_MASK   0x2000

Definition at line 202 of file numeric.c.

◆ NUMERIC_IS_INF

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

Definition at line 208 of file numeric.c.

◆ NUMERIC_IS_NAN

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

Definition at line 205 of file numeric.c.

◆ NUMERIC_IS_NINF

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

Definition at line 207 of file numeric.c.

◆ NUMERIC_IS_PINF

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

Definition at line 206 of file numeric.c.

◆ NUMERIC_IS_SHORT

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

Definition at line 173 of file numeric.c.

◆ NUMERIC_IS_SPECIAL

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

Definition at line 174 of file numeric.c.

◆ NUMERIC_NAN

#define NUMERIC_NAN   0xC000

Definition at line 199 of file numeric.c.

◆ NUMERIC_NDIGITS

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

Definition at line 497 of file numeric.c.

◆ NUMERIC_NEG

#define NUMERIC_NEG   0x4000

Definition at line 168 of file numeric.c.

◆ NUMERIC_NINF

#define NUMERIC_NINF   0xF000

Definition at line 201 of file numeric.c.

◆ NUMERIC_PINF

#define NUMERIC_PINF   0xD000

Definition at line 200 of file numeric.c.

◆ NUMERIC_POS

#define NUMERIC_POS   0x0000

Definition at line 167 of file numeric.c.

◆ NUMERIC_SHORT

#define NUMERIC_SHORT   0x8000

Definition at line 169 of file numeric.c.

◆ NUMERIC_SHORT_DSCALE_MASK

#define NUMERIC_SHORT_DSCALE_MASK   0x1F80

Definition at line 216 of file numeric.c.

◆ NUMERIC_SHORT_DSCALE_MAX

#define NUMERIC_SHORT_DSCALE_MAX    (NUMERIC_SHORT_DSCALE_MASK >> NUMERIC_SHORT_DSCALE_SHIFT)

Definition at line 218 of file numeric.c.

◆ NUMERIC_SHORT_DSCALE_SHIFT

#define NUMERIC_SHORT_DSCALE_SHIFT   7

Definition at line 217 of file numeric.c.

◆ NUMERIC_SHORT_SIGN_MASK

#define NUMERIC_SHORT_SIGN_MASK   0x2000

Definition at line 215 of file numeric.c.

◆ NUMERIC_SHORT_WEIGHT_MASK

#define NUMERIC_SHORT_WEIGHT_MASK   0x003F

Definition at line 221 of file numeric.c.

◆ NUMERIC_SHORT_WEIGHT_MAX

#define NUMERIC_SHORT_WEIGHT_MAX   NUMERIC_SHORT_WEIGHT_MASK

Definition at line 222 of file numeric.c.

◆ NUMERIC_SHORT_WEIGHT_MIN

#define NUMERIC_SHORT_WEIGHT_MIN   (-(NUMERIC_SHORT_WEIGHT_MASK+1))

Definition at line 223 of file numeric.c.

◆ NUMERIC_SHORT_WEIGHT_SIGN_MASK

#define NUMERIC_SHORT_WEIGHT_SIGN_MASK   0x0040

Definition at line 220 of file numeric.c.

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

Definition at line 238 of file numeric.c.

◆ NUMERIC_SIGN_MASK

#define NUMERIC_SIGN_MASK   0xC000

Definition at line 166 of file numeric.c.

◆ NUMERIC_SPECIAL

#define NUMERIC_SPECIAL   0xC000

Definition at line 170 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:221
#define NUMERIC_SHORT_WEIGHT_SIGN_MASK
Definition: numeric.c:220

Definition at line 248 of file numeric.c.

◆ NUMERIC_WEIGHT_MAX

#define NUMERIC_WEIGHT_MAX   PG_INT16_MAX

Definition at line 259 of file numeric.c.

◆ NumericAbbrevGetDatum

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

Definition at line 411 of file numeric.c.

◆ PRODSUM1

#define PRODSUM1 (   v1,
  i1,
  v2,
  i2 
)    ((v1)[(i1)] * (v2)[(i2)])

◆ PRODSUM2

#define PRODSUM2 (   v1,
  i1,
  v2,
  i2 
)    (PRODSUM1(v1,i1,v2,i2) + (v1)[(i1)+1] * (v2)[(i2)-1])

◆ PRODSUM3

#define PRODSUM3 (   v1,
  i1,
  v2,
  i2 
)    (PRODSUM2(v1,i1,v2,i2) + (v1)[(i1)+2] * (v2)[(i2)-2])

◆ PRODSUM4

#define PRODSUM4 (   v1,
  i1,
  v2,
  i2 
)    (PRODSUM3(v1,i1,v2,i2) + (v1)[(i1)+3] * (v2)[(i2)-3])

◆ PRODSUM5

#define PRODSUM5 (   v1,
  i1,
  v2,
  i2 
)    (PRODSUM4(v1,i1,v2,i2) + (v1)[(i1)+4] * (v2)[(i2)-4])

◆ PRODSUM6

#define PRODSUM6 (   v1,
  i1,
  v2,
  i2 
)    (PRODSUM5(v1,i1,v2,i2) + (v1)[(i1)+5] * (v2)[(i2)-5])

Typedef Documentation

◆ Int8TransTypeData

◆ NumericAggState

◆ NumericDigit

Definition at line 101 of file numeric.c.

◆ NumericSumAccum

◆ NumericVar

typedef struct NumericVar NumericVar

◆ PolyNumAggState

Definition at line 5541 of file numeric.c.

Function Documentation

◆ accum_sum_add()

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

Definition at line 12212 of file numeric.c.

12213 {
12214  int32 *accum_digits;
12215  int i,
12216  val_i;
12217  int val_ndigits;
12218  NumericDigit *val_digits;
12219 
12220  /*
12221  * If we have accumulated too many values since the last carry
12222  * propagation, do it now, to avoid overflowing. (We could allow more
12223  * than NBASE - 1, if we reserved two extra digits, rather than one, for
12224  * carry propagation. But even with NBASE - 1, this needs to be done so
12225  * seldom, that the performance difference is negligible.)
12226  */
12227  if (accum->num_uncarried == NBASE - 1)
12228  accum_sum_carry(accum);
12229 
12230  /*
12231  * Adjust the weight or scale of the old value, so that it can accommodate
12232  * the new value.
12233  */
12234  accum_sum_rescale(accum, val);
12235 
12236  /* */
12237  if (val->sign == NUMERIC_POS)
12238  accum_digits = accum->pos_digits;
12239  else
12240  accum_digits = accum->neg_digits;
12241 
12242  /* copy these values into local vars for speed in loop */
12243  val_ndigits = val->ndigits;
12244  val_digits = val->digits;
12245 
12246  i = accum->weight - val->weight;
12247  for (val_i = 0; val_i < val_ndigits; val_i++)
12248  {
12249  accum_digits[i] += (int32) val_digits[val_i];
12250  i++;
12251  }
12252 
12253  accum->num_uncarried++;
12254 }
static void accum_sum_carry(NumericSumAccum *accum)
Definition: numeric.c:12260
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:12333
signed int int32
Definition: c.h:496
long val
Definition: informix.c:689
int i
Definition: isn.c:73
int32 * pos_digits
Definition: numeric.c:386
int num_uncarried
Definition: numeric.c:384
int32 * neg_digits
Definition: numeric.c:387

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

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

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

12491 {
12492  NumericVar tmp_var;
12493 
12494  init_var(&tmp_var);
12495 
12496  accum_sum_final(accum2, &tmp_var);
12497  accum_sum_add(accum, &tmp_var);
12498 
12499  free_var(&tmp_var);
12500 }
static void accum_sum_final(NumericSumAccum *accum, NumericVar *result)
Definition: numeric.c:12422
static void free_var(NumericVar *var)
Definition: numeric.c:6966
static void accum_sum_add(NumericSumAccum *accum, const NumericVar *val)
Definition: numeric.c:12212
#define init_var(v)
Definition: numeric.c:493

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

12474 {
12475  dst->pos_digits = palloc(src->ndigits * sizeof(int32));
12476  dst->neg_digits = palloc(src->ndigits * sizeof(int32));
12477 
12478  memcpy(dst->pos_digits, src->pos_digits, src->ndigits * sizeof(int32));
12479  memcpy(dst->neg_digits, src->neg_digits, src->ndigits * sizeof(int32));
12480  dst->num_uncarried = src->num_uncarried;
12481  dst->ndigits = src->ndigits;
12482  dst->weight = src->weight;
12483  dst->dscale = src->dscale;
12484 }
void * palloc(Size size)
Definition: mcxt.c:1317

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

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

◆ accum_sum_final()

static void accum_sum_final ( NumericSumAccum accum,
NumericVar result 
)
static

Definition at line 12422 of file numeric.c.

12423 {
12424  int i;
12425  NumericVar pos_var;
12426  NumericVar neg_var;
12427 
12428  if (accum->ndigits == 0)
12429  {
12430  set_var_from_var(&const_zero, result);
12431  return;
12432  }
12433 
12434  /* Perform final carry */
12435  accum_sum_carry(accum);
12436 
12437  /* Create NumericVars representing the positive and negative sums */
12438  init_var(&pos_var);
12439  init_var(&neg_var);
12440 
12441  pos_var.ndigits = neg_var.ndigits = accum->ndigits;
12442  pos_var.weight = neg_var.weight = accum->weight;
12443  pos_var.dscale = neg_var.dscale = accum->dscale;
12444  pos_var.sign = NUMERIC_POS;
12445  neg_var.sign = NUMERIC_NEG;
12446 
12447  pos_var.buf = pos_var.digits = digitbuf_alloc(accum->ndigits);
12448  neg_var.buf = neg_var.digits = digitbuf_alloc(accum->ndigits);
12449 
12450  for (i = 0; i < accum->ndigits; i++)
12451  {
12452  Assert(accum->pos_digits[i] < NBASE);
12453  pos_var.digits[i] = (int16) accum->pos_digits[i];
12454 
12455  Assert(accum->neg_digits[i] < NBASE);
12456  neg_var.digits[i] = (int16) accum->neg_digits[i];
12457  }
12458 
12459  /* And add them together */
12460  add_var(&pos_var, &neg_var, result);
12461 
12462  /* Remove leading/trailing zeroes */
12463  strip_var(result);
12464 }
static void add_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition: numeric.c:8428
#define NUMERIC_NEG
Definition: numeric.c:168
#define digitbuf_alloc(ndigits)
Definition: numeric.c:485
static const NumericVar const_zero
Definition: numeric.c:424
static void set_var_from_var(const NumericVar *value, NumericVar *dest)
Definition: numeric.c:7465
static void strip_var(NumericVar *var)
Definition: numeric.c:12155
int ndigits
Definition: numeric.c:314
NumericDigit * digits
Definition: numeric.c:319
int dscale
Definition: numeric.c:317
int sign
Definition: numeric.c:316
NumericDigit * buf
Definition: numeric.c:318
int weight
Definition: numeric.c:315

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

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

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

Referenced by accum_sum_add().

◆ accum_sum_reset()

static void accum_sum_reset ( NumericSumAccum accum)
static

Definition at line 12196 of file numeric.c.

12197 {
12198  int i;
12199 
12200  accum->dscale = 0;
12201  for (i = 0; i < accum->ndigits; i++)
12202  {
12203  accum->pos_digits[i] = 0;
12204  accum->neg_digits[i] = 0;
12205  }
12206 }

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

11821 {
11822  NumericDigit *res_buf;
11823  NumericDigit *res_digits;
11824  int res_ndigits;
11825  int res_weight;
11826  int res_rscale,
11827  rscale1,
11828  rscale2;
11829  int res_dscale;
11830  int i,
11831  i1,
11832  i2;
11833  int carry = 0;
11834 
11835  /* copy these values into local vars for speed in inner loop */
11836  int var1ndigits = var1->ndigits;
11837  int var2ndigits = var2->ndigits;
11838  NumericDigit *var1digits = var1->digits;
11839  NumericDigit *var2digits = var2->digits;
11840 
11841  res_weight = Max(var1->weight, var2->weight) + 1;
11842 
11843  res_dscale = Max(var1->dscale, var2->dscale);
11844 
11845  /* Note: here we are figuring rscale in base-NBASE digits */
11846  rscale1 = var1->ndigits - var1->weight - 1;
11847  rscale2 = var2->ndigits - var2->weight - 1;
11848  res_rscale = Max(rscale1, rscale2);
11849 
11850  res_ndigits = res_rscale + res_weight + 1;
11851  if (res_ndigits <= 0)
11852  res_ndigits = 1;
11853 
11854  res_buf = digitbuf_alloc(res_ndigits + 1);
11855  res_buf[0] = 0; /* spare digit for later rounding */
11856  res_digits = res_buf + 1;
11857 
11858  i1 = res_rscale + var1->weight + 1;
11859  i2 = res_rscale + var2->weight + 1;
11860  for (i = res_ndigits - 1; i >= 0; i--)
11861  {
11862  i1--;
11863  i2--;
11864  if (i1 >= 0 && i1 < var1ndigits)
11865  carry += var1digits[i1];
11866  if (i2 >= 0 && i2 < var2ndigits)
11867  carry += var2digits[i2];
11868 
11869  if (carry >= NBASE)
11870  {
11871  res_digits[i] = carry - NBASE;
11872  carry = 1;
11873  }
11874  else
11875  {
11876  res_digits[i] = carry;
11877  carry = 0;
11878  }
11879  }
11880 
11881  Assert(carry == 0); /* else we failed to allow for carry out */
11882 
11883  digitbuf_free(result->buf);
11884  result->ndigits = res_ndigits;
11885  result->buf = res_buf;
11886  result->digits = res_digits;
11887  result->weight = res_weight;
11888  result->dscale = res_dscale;
11889 
11890  /* Remove leading/trailing zeroes */
11891  strip_var(result);
11892 }
#define digitbuf_free(buf)
Definition: numeric.c:487
#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 8428 of file numeric.c.

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

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

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

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

Referenced by div_var(), 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 7904 of file numeric.c.

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

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

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

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

10182 {
10183  NumericVar tmp;
10184 
10185  init_var(&tmp);
10186  set_var_from_var(var, &tmp);
10187 
10188  trunc_var(&tmp, 0);
10189 
10190  if (var->sign == NUMERIC_POS && cmp_var(var, &tmp) != 0)
10191  add_var(&tmp, &const_one, &tmp);
10192 
10193  set_var_from_var(&tmp, result);
10194  free_var(&tmp);
10195 }
static void trunc_var(NumericVar *var, int rscale)
Definition: numeric.c:12093
static int cmp_var(const NumericVar *var1, const NumericVar *var2)
Definition: numeric.c:8370
static const NumericVar const_one
Definition: numeric.c:428

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

11743 {
11744  return cmp_abs_common(var1->digits, var1->ndigits, var1->weight,
11745  var2->digits, var2->ndigits, var2->weight);
11746 }
static int cmp_abs_common(const NumericDigit *var1digits, int var1ndigits, int var1weight, const NumericDigit *var2digits, int var2ndigits, int var2weight)
Definition: numeric.c:11756

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

11758 {
11759  int i1 = 0;
11760  int i2 = 0;
11761 
11762  /* Check any digits before the first common digit */
11763 
11764  while (var1weight > var2weight && i1 < var1ndigits)
11765  {
11766  if (var1digits[i1++] != 0)
11767  return 1;
11768  var1weight--;
11769  }
11770  while (var2weight > var1weight && i2 < var2ndigits)
11771  {
11772  if (var2digits[i2++] != 0)
11773  return -1;
11774  var2weight--;
11775  }
11776 
11777  /* At this point, either w1 == w2 or we've run out of digits */
11778 
11779  if (var1weight == var2weight)
11780  {
11781  while (i1 < var1ndigits && i2 < var2ndigits)
11782  {
11783  int stat = var1digits[i1++] - var2digits[i2++];
11784 
11785  if (stat)
11786  {
11787  if (stat > 0)
11788  return 1;
11789  return -1;
11790  }
11791  }
11792  }
11793 
11794  /*
11795  * At this point, we've run out of digits on one side or the other; so any
11796  * remaining nonzero digits imply that side is larger
11797  */
11798  while (i1 < var1ndigits)
11799  {
11800  if (var1digits[i1++] != 0)
11801  return 1;
11802  }
11803  while (i2 < var2ndigits)
11804  {
11805  if (var2digits[i2++] != 0)
11806  return -1;
11807  }
11808 
11809  return 0;
11810 }

Referenced by cmp_abs(), and cmp_var_common().

◆ cmp_numerics()

static int cmp_numerics ( Numeric  num1,
Numeric  num2 
)
static

Definition at line 2502 of file numeric.c.

2503 {
2504  int result;
2505 
2506  /*
2507  * We consider all NANs to be equal and larger than any non-NAN (including
2508  * Infinity). This is somewhat arbitrary; the important thing is to have
2509  * a consistent sort order.
2510  */
2511  if (NUMERIC_IS_SPECIAL(num1))
2512  {
2513  if (NUMERIC_IS_NAN(num1))
2514  {
2515  if (NUMERIC_IS_NAN(num2))
2516  result = 0; /* NAN = NAN */
2517  else
2518  result = 1; /* NAN > non-NAN */
2519  }
2520  else if (NUMERIC_IS_PINF(num1))
2521  {
2522  if (NUMERIC_IS_NAN(num2))
2523  result = -1; /* PINF < NAN */
2524  else if (NUMERIC_IS_PINF(num2))
2525  result = 0; /* PINF = PINF */
2526  else
2527  result = 1; /* PINF > anything else */
2528  }
2529  else /* num1 must be NINF */
2530  {
2531  if (NUMERIC_IS_NINF(num2))
2532  result = 0; /* NINF = NINF */
2533  else
2534  result = -1; /* NINF < anything else */
2535  }
2536  }
2537  else if (NUMERIC_IS_SPECIAL(num2))
2538  {
2539  if (NUMERIC_IS_NINF(num2))
2540  result = 1; /* normal > NINF */
2541  else
2542  result = -1; /* normal < NAN or PINF */
2543  }
2544  else
2545  {
2546  result = cmp_var_common(NUMERIC_DIGITS(num1), NUMERIC_NDIGITS(num1),
2547  NUMERIC_WEIGHT(num1), NUMERIC_SIGN(num1),
2548  NUMERIC_DIGITS(num2), NUMERIC_NDIGITS(num2),
2549  NUMERIC_WEIGHT(num2), NUMERIC_SIGN(num2));
2550  }
2551 
2552  return result;
2553 }
#define NUMERIC_SIGN(n)
Definition: numeric.c:238
#define NUMERIC_IS_PINF(n)
Definition: numeric.c:206
#define NUMERIC_IS_NINF(n)
Definition: numeric.c:207
#define NUMERIC_WEIGHT(n)
Definition: numeric.c:248
#define NUMERIC_DIGITS(num)
Definition: numeric.c:495
#define NUMERIC_NDIGITS(num)
Definition: numeric.c:497
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:8385

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

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

References cmp_abs_common(), NUMERIC_NEG, and NUMERIC_POS.

Referenced by cmp_numerics(), and cmp_var().

◆ compute_bucket()

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

Definition at line 1933 of file numeric.c.

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

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

Referenced by width_bucket_numeric().

◆ div_mod_var()

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

Definition at line 10111 of file numeric.c.

10113 {
10114  NumericVar q;
10115  NumericVar r;
10116 
10117  init_var(&q);
10118  init_var(&r);
10119 
10120  /*
10121  * Use div_var() with exact = false to get an initial estimate for the
10122  * integer quotient (truncated towards zero). This might be slightly
10123  * inaccurate, but we correct it below.
10124  */
10125  div_var(var1, var2, &q, 0, false, false);
10126 
10127  /* Compute initial estimate of remainder using the quotient estimate. */
10128  mul_var(var2, &q, &r, var2->dscale);
10129  sub_var(var1, &r, &r);
10130 
10131  /*
10132  * Adjust the results if necessary --- the remainder should have the same
10133  * sign as var1, and its absolute value should be less than the absolute
10134  * value of var2.
10135  */
10136  while (r.ndigits != 0 && r.sign != var1->sign)
10137  {
10138  /* The absolute value of the quotient is too large */
10139  if (var1->sign == var2->sign)
10140  {
10141  sub_var(&q, &const_one, &q);
10142  add_var(&r, var2, &r);
10143  }
10144  else
10145  {
10146  add_var(&q, &const_one, &q);
10147  sub_var(&r, var2, &r);
10148  }
10149  }
10150 
10151  while (cmp_abs(&r, var2) >= 0)
10152  {
10153  /* The absolute value of the quotient is too small */
10154  if (var1->sign == var2->sign)
10155  {
10156  add_var(&q, &const_one, &q);
10157  sub_var(&r, var2, &r);
10158  }
10159  else
10160  {
10161  sub_var(&q, &const_one, &q);
10162  add_var(&r, var2, &r);
10163  }
10164  }
10165 
10166  set_var_from_var(&q, quot);
10167  set_var_from_var(&r, rem);
10168 
10169  free_var(&q);
10170  free_var(&r);
10171 }

References add_var(), cmp_abs(), const_one, div_var(), 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,
bool  exact 
)
static

Definition at line 9244 of file numeric.c.

9246 {
9247  int var1ndigits = var1->ndigits;
9248  int var2ndigits = var2->ndigits;
9249  int res_sign;
9250  int res_weight;
9251  int res_ndigits;
9252  int var1ndigitpairs;
9253  int var2ndigitpairs;
9254  int res_ndigitpairs;
9255  int div_ndigitpairs;
9256  int64 *dividend;
9257  int32 *divisor;
9258  double fdivisor,
9259  fdivisorinverse,
9260  fdividend,
9261  fquotient;
9262  int64 maxdiv;
9263  int qi;
9264  int32 qdigit;
9265  int64 carry;
9266  int64 newdig;
9267  int64 *remainder;
9268  NumericDigit *res_digits;
9269  int i;
9270 
9271  /*
9272  * First of all division by zero check; we must not be handed an
9273  * unnormalized divisor.
9274  */
9275  if (var2ndigits == 0 || var2->digits[0] == 0)
9276  ereport(ERROR,
9277  (errcode(ERRCODE_DIVISION_BY_ZERO),
9278  errmsg("division by zero")));
9279 
9280  /*
9281  * If the divisor has just one or two digits, delegate to div_var_int(),
9282  * which uses fast short division.
9283  *
9284  * Similarly, on platforms with 128-bit integer support, delegate to
9285  * div_var_int64() for divisors with three or four digits.
9286  */
9287  if (var2ndigits <= 2)
9288  {
9289  int idivisor;
9290  int idivisor_weight;
9291 
9292  idivisor = var2->digits[0];
9293  idivisor_weight = var2->weight;
9294  if (var2ndigits == 2)
9295  {
9296  idivisor = idivisor * NBASE + var2->digits[1];
9297  idivisor_weight--;
9298  }
9299  if (var2->sign == NUMERIC_NEG)
9300  idivisor = -idivisor;
9301 
9302  div_var_int(var1, idivisor, idivisor_weight, result, rscale, round);
9303  return;
9304  }
9305 #ifdef HAVE_INT128
9306  if (var2ndigits <= 4)
9307  {
9308  int64 idivisor;
9309  int idivisor_weight;
9310 
9311  idivisor = var2->digits[0];
9312  idivisor_weight = var2->weight;
9313  for (i = 1; i < var2ndigits; i++)
9314  {
9315  idivisor = idivisor * NBASE + var2->digits[i];
9316  idivisor_weight--;
9317  }
9318  if (var2->sign == NUMERIC_NEG)
9319  idivisor = -idivisor;
9320 
9321  div_var_int64(var1, idivisor, idivisor_weight, result, rscale, round);
9322  return;
9323  }
9324 #endif
9325 
9326  /*
9327  * Otherwise, perform full long division.
9328  */
9329 
9330  /* Result zero check */
9331  if (var1ndigits == 0)
9332  {
9333  zero_var(result);
9334  result->dscale = rscale;
9335  return;
9336  }
9337 
9338  /*
9339  * The approximate computation can be significantly faster than the exact
9340  * one, since the working dividend is var2ndigitpairs base-NBASE^2 digits
9341  * shorter below. However, that comes with the tradeoff of computing
9342  * DIV_GUARD_DIGITS extra base-NBASE result digits. Ignoring all other
9343  * overheads, that suggests that, in theory, the approximate computation
9344  * will only be faster than the exact one when var2ndigits is greater than
9345  * 2 * (DIV_GUARD_DIGITS + 1), independent of the size of var1.
9346  *
9347  * Thus, we're better off doing an exact computation when var2 is shorter
9348  * than this. Empirically, it has been found that the exact threshold is
9349  * a little higher, due to other overheads in the outer division loop.
9350  */
9351  if (var2ndigits <= 2 * (DIV_GUARD_DIGITS + 2))
9352  exact = true;
9353 
9354  /*
9355  * Determine the result sign, weight and number of digits to calculate.
9356  * The weight figured here is correct if the emitted quotient has no
9357  * leading zero digits; otherwise strip_var() will fix things up.
9358  */
9359  if (var1->sign == var2->sign)
9360  res_sign = NUMERIC_POS;
9361  else
9362  res_sign = NUMERIC_NEG;
9363  res_weight = var1->weight - var2->weight + 1;
9364  /* The number of accurate result digits we need to produce: */
9365  res_ndigits = res_weight + 1 + (rscale + DEC_DIGITS - 1) / DEC_DIGITS;
9366  /* ... but always at least 1 */
9367  res_ndigits = Max(res_ndigits, 1);
9368  /* If rounding needed, figure one more digit to ensure correct result */
9369  if (round)
9370  res_ndigits++;
9371  /* Add guard digits for roundoff error when producing approx result */
9372  if (!exact)
9373  res_ndigits += DIV_GUARD_DIGITS;
9374 
9375  /*
9376  * The computation itself is done using base-NBASE^2 arithmetic, so we
9377  * actually process the input digits in pairs, producing a base-NBASE^2
9378  * intermediate result. This significantly improves performance, since
9379  * the computation is O(N^2) in the number of input digits, and working in
9380  * base NBASE^2 effectively halves "N".
9381  */
9382  var1ndigitpairs = (var1ndigits + 1) / 2;
9383  var2ndigitpairs = (var2ndigits + 1) / 2;
9384  res_ndigitpairs = (res_ndigits + 1) / 2;
9385  res_ndigits = 2 * res_ndigitpairs;
9386 
9387  /*
9388  * We do the arithmetic in an array "dividend[]" of signed 64-bit
9389  * integers. Since PG_INT64_MAX is much larger than NBASE^4, this gives
9390  * us a lot of headroom to avoid normalizing carries immediately.
9391  *
9392  * When performing an exact computation, the working dividend requires
9393  * res_ndigitpairs + var2ndigitpairs digits. If var1 is larger than that,
9394  * the extra digits do not contribute to the result, and are ignored.
9395  *
9396  * When performing an approximate computation, the working dividend only
9397  * requires res_ndigitpairs digits (which includes the extra guard
9398  * digits). All input digits beyond that are ignored.
9399  */
9400  if (exact)
9401  {
9402  div_ndigitpairs = res_ndigitpairs + var2ndigitpairs;
9403  var1ndigitpairs = Min(var1ndigitpairs, div_ndigitpairs);
9404  }
9405  else
9406  {
9407  div_ndigitpairs = res_ndigitpairs;
9408  var1ndigitpairs = Min(var1ndigitpairs, div_ndigitpairs);
9409  var2ndigitpairs = Min(var2ndigitpairs, div_ndigitpairs);
9410  }
9411 
9412  /*
9413  * Allocate room for the working dividend (div_ndigitpairs 64-bit digits)
9414  * plus the divisor (var2ndigitpairs 32-bit base-NBASE^2 digits).
9415  *
9416  * For convenience, we allocate one extra dividend digit, which is set to
9417  * zero and not counted in div_ndigitpairs, so that the main loop below
9418  * can safely read and write the (qi+1)'th digit in the approximate case.
9419  */
9420  dividend = (int64 *) palloc((div_ndigitpairs + 1) * sizeof(int64) +
9421  var2ndigitpairs * sizeof(int32));
9422  divisor = (int32 *) (dividend + div_ndigitpairs + 1);
9423 
9424  /* load var1 into dividend[0 .. var1ndigitpairs-1], zeroing the rest */
9425  for (i = 0; i < var1ndigitpairs - 1; i++)
9426  dividend[i] = var1->digits[2 * i] * NBASE + var1->digits[2 * i + 1];
9427 
9428  if (2 * i + 1 < var1ndigits)
9429  dividend[i] = var1->digits[2 * i] * NBASE + var1->digits[2 * i + 1];
9430  else
9431  dividend[i] = var1->digits[2 * i] * NBASE;
9432 
9433  memset(dividend + i + 1, 0, (div_ndigitpairs - i) * sizeof(int64));
9434 
9435  /* load var2 into divisor[0 .. var2ndigitpairs-1] */
9436  for (i = 0; i < var2ndigitpairs - 1; i++)
9437  divisor[i] = var2->digits[2 * i] * NBASE + var2->digits[2 * i + 1];
9438 
9439  if (2 * i + 1 < var2ndigits)
9440  divisor[i] = var2->digits[2 * i] * NBASE + var2->digits[2 * i + 1];
9441  else
9442  divisor[i] = var2->digits[2 * i] * NBASE;
9443 
9444  /*
9445  * We estimate each quotient digit using floating-point arithmetic, taking
9446  * the first 2 base-NBASE^2 digits of the (current) dividend and divisor.
9447  * This must be float to avoid overflow.
9448  *
9449  * Since the floating-point dividend and divisor use 4 base-NBASE input
9450  * digits, they include roughly 40-53 bits of information from their
9451  * respective inputs (assuming NBASE is 10000), which fits well in IEEE
9452  * double-precision variables. The relative error in the floating-point
9453  * quotient digit will then be less than around 2/NBASE^3, so the
9454  * estimated base-NBASE^2 quotient digit will typically be correct, and
9455  * should not be off by more than one from the correct value.
9456  */
9457  fdivisor = (double) divisor[0] * NBASE_SQR;
9458  if (var2ndigitpairs > 1)
9459  fdivisor += (double) divisor[1];
9460  fdivisorinverse = 1.0 / fdivisor;
9461 
9462  /*
9463  * maxdiv tracks the maximum possible absolute value of any dividend[]
9464  * entry; when this threatens to exceed PG_INT64_MAX, we take the time to
9465  * propagate carries. Furthermore, we need to ensure that overflow
9466  * doesn't occur during the carry propagation passes either. The carry
9467  * values may have an absolute value as high as PG_INT64_MAX/NBASE^2 + 1,
9468  * so really we must normalize when digits threaten to exceed PG_INT64_MAX
9469  * - PG_INT64_MAX/NBASE^2 - 1.
9470  *
9471  * To avoid overflow in maxdiv itself, it represents the max absolute
9472  * value divided by NBASE^2-1, i.e., at the top of the loop it is known
9473  * that no dividend[] entry has an absolute value exceeding maxdiv *
9474  * (NBASE^2-1).
9475  *
9476  * Actually, though, that holds good only for dividend[] entries after
9477  * dividend[qi]; the adjustment done at the bottom of the loop may cause
9478  * dividend[qi + 1] to exceed the maxdiv limit, so that dividend[qi] in
9479  * the next iteration is beyond the limit. This does not cause problems,
9480  * as explained below.
9481  */
9482  maxdiv = 1;
9483 
9484  /*
9485  * Outer loop computes next quotient digit, which goes in dividend[qi].
9486  */
9487  for (qi = 0; qi < res_ndigitpairs; qi++)
9488  {
9489  /* Approximate the current dividend value */
9490  fdividend = (double) dividend[qi] * NBASE_SQR;
9491  fdividend += (double) dividend[qi + 1];
9492 
9493  /* Compute the (approximate) quotient digit */
9494  fquotient = fdividend * fdivisorinverse;
9495  qdigit = (fquotient >= 0.0) ? ((int32) fquotient) :
9496  (((int32) fquotient) - 1); /* truncate towards -infinity */
9497 
9498  if (qdigit != 0)
9499  {
9500  /* Do we need to normalize now? */
9501  maxdiv += i64abs(qdigit);
9502  if (maxdiv > (PG_INT64_MAX - PG_INT64_MAX / NBASE_SQR - 1) / (NBASE_SQR - 1))
9503  {
9504  /*
9505  * Yes, do it. Note that if var2ndigitpairs is much smaller
9506  * than div_ndigitpairs, we can save a significant amount of
9507  * effort here by noting that we only need to normalise those
9508  * dividend[] entries touched where prior iterations
9509  * subtracted multiples of the divisor.
9510  */
9511  carry = 0;
9512  for (i = Min(qi + var2ndigitpairs - 2, div_ndigitpairs - 1); i > qi; i--)
9513  {
9514  newdig = dividend[i] + carry;
9515  if (newdig < 0)
9516  {
9517  carry = -((-newdig - 1) / NBASE_SQR) - 1;
9518  newdig -= carry * NBASE_SQR;
9519  }
9520  else if (newdig >= NBASE_SQR)
9521  {
9522  carry = newdig / NBASE_SQR;
9523  newdig -= carry * NBASE_SQR;
9524  }
9525  else
9526  carry = 0;
9527  dividend[i] = newdig;
9528  }
9529  dividend[qi] += carry;
9530 
9531  /*
9532  * All the dividend[] digits except possibly dividend[qi] are
9533  * now in the range 0..NBASE^2-1. We do not need to consider
9534  * dividend[qi] in the maxdiv value anymore, so we can reset
9535  * maxdiv to 1.
9536  */
9537  maxdiv = 1;
9538 
9539  /*
9540  * Recompute the quotient digit since new info may have
9541  * propagated into the top two dividend digits.
9542  */
9543  fdividend = (double) dividend[qi] * NBASE_SQR;
9544  fdividend += (double) dividend[qi + 1];
9545  fquotient = fdividend * fdivisorinverse;
9546  qdigit = (fquotient >= 0.0) ? ((int32) fquotient) :
9547  (((int32) fquotient) - 1); /* truncate towards -infinity */
9548 
9549  maxdiv += i64abs(qdigit);
9550  }
9551 
9552  /*
9553  * Subtract off the appropriate multiple of the divisor.
9554  *
9555  * The digits beyond dividend[qi] cannot overflow, because we know
9556  * they will fall within the maxdiv limit. As for dividend[qi]
9557  * itself, note that qdigit is approximately trunc(dividend[qi] /
9558  * divisor[0]), which would make the new value simply dividend[qi]
9559  * mod divisor[0]. The lower-order terms in qdigit can change
9560  * this result by not more than about twice PG_INT64_MAX/NBASE^2,
9561  * so overflow is impossible.
9562  *
9563  * This inner loop is the performance bottleneck for division, so
9564  * code it in the same way as the inner loop of mul_var() so that
9565  * it can be auto-vectorized.
9566  */
9567  if (qdigit != 0)
9568  {
9569  int istop = Min(var2ndigitpairs, div_ndigitpairs - qi);
9570  int64 *dividend_qi = &dividend[qi];
9571 
9572  for (i = 0; i < istop; i++)
9573  dividend_qi[i] -= (int64) qdigit * divisor[i];
9574  }
9575  }
9576 
9577  /*
9578  * The dividend digit we are about to replace might still be nonzero.
9579  * Fold it into the next digit position.
9580  *
9581  * There is no risk of overflow here, although proving that requires
9582  * some care. Much as with the argument for dividend[qi] not
9583  * overflowing, if we consider the first two terms in the numerator
9584  * and denominator of qdigit, we can see that the final value of
9585  * dividend[qi + 1] will be approximately a remainder mod
9586  * (divisor[0]*NBASE^2 + divisor[1]). Accounting for the lower-order
9587  * terms is a bit complicated but ends up adding not much more than
9588  * PG_INT64_MAX/NBASE^2 to the possible range. Thus, dividend[qi + 1]
9589  * cannot overflow here, and in its role as dividend[qi] in the next
9590  * loop iteration, it can't be large enough to cause overflow in the
9591  * carry propagation step (if any), either.
9592  *
9593  * But having said that: dividend[qi] can be more than
9594  * PG_INT64_MAX/NBASE^2, as noted above, which means that the product
9595  * dividend[qi] * NBASE^2 *can* overflow. When that happens, adding
9596  * it to dividend[qi + 1] will always cause a canceling overflow so
9597  * that the end result is correct. We could avoid the intermediate
9598  * overflow by doing the multiplication and addition using unsigned
9599  * int64 arithmetic, which is modulo 2^64, but so far there appears no
9600  * need.
9601  */
9602  dividend[qi + 1] += dividend[qi] * NBASE_SQR;
9603 
9604  dividend[qi] = qdigit;
9605  }
9606 
9607  /*
9608  * If an exact result was requested, use the remainder to correct the
9609  * approximate quotient. The remainder is in dividend[], immediately
9610  * after the quotient digits. Note, however, that although the remainder
9611  * starts at dividend[qi = res_ndigitpairs], the first digit is the result
9612  * of folding two remainder digits into one above, and the remainder
9613  * currently only occupies var2ndigitpairs - 1 digits (the last digit of
9614  * the working dividend was untouched by the computation above). Thus we
9615  * expand the remainder down by one base-NBASE^2 digit when we normalize
9616  * it, so that it completely fills the last var2ndigitpairs digits of the
9617  * dividend array.
9618  */
9619  if (exact)
9620  {
9621  /* Normalize the remainder, expanding it down by one digit */
9622  remainder = &dividend[qi];
9623  carry = 0;
9624  for (i = var2ndigitpairs - 2; i >= 0; i--)
9625  {
9626  newdig = remainder[i] + carry;
9627  if (newdig < 0)
9628  {
9629  carry = -((-newdig - 1) / NBASE_SQR) - 1;
9630  newdig -= carry * NBASE_SQR;
9631  }
9632  else if (newdig >= NBASE_SQR)
9633  {
9634  carry = newdig / NBASE_SQR;
9635  newdig -= carry * NBASE_SQR;
9636  }
9637  else
9638  carry = 0;
9639  remainder[i + 1] = newdig;
9640  }
9641  remainder[0] = carry;
9642 
9643  if (remainder[0] < 0)
9644  {
9645  /*
9646  * The remainder is negative, so the approximate quotient is too
9647  * large. Correct by reducing the quotient by one and adding the
9648  * divisor to the remainder until the remainder is positive. We
9649  * expect the quotient to be off by at most one, which has been
9650  * borne out in all testing, but not conclusively proven, so we
9651  * allow for larger corrections, just in case.
9652  */
9653  do
9654  {
9655  /* Add the divisor to the remainder */
9656  carry = 0;
9657  for (i = var2ndigitpairs - 1; i > 0; i--)
9658  {
9659  newdig = remainder[i] + divisor[i] + carry;
9660  if (newdig >= NBASE_SQR)
9661  {
9662  remainder[i] = newdig - NBASE_SQR;
9663  carry = 1;
9664  }
9665  else
9666  {
9667  remainder[i] = newdig;
9668  carry = 0;
9669  }
9670  }
9671  remainder[0] += divisor[0] + carry;
9672 
9673  /* Subtract 1 from the quotient (propagating carries later) */
9674  dividend[qi - 1]--;
9675 
9676  } while (remainder[0] < 0);
9677  }
9678  else
9679  {
9680  /*
9681  * The remainder is nonnegative. If it's greater than or equal to
9682  * the divisor, then the approximate quotient is too small and
9683  * must be corrected. As above, we don't expect to have to apply
9684  * more than one correction, but allow for it just in case.
9685  */
9686  while (true)
9687  {
9688  bool less = false;
9689 
9690  /* Is remainder < divisor? */
9691  for (i = 0; i < var2ndigitpairs; i++)
9692  {
9693  if (remainder[i] < divisor[i])
9694  {
9695  less = true;
9696  break;
9697  }
9698  if (remainder[i] > divisor[i])
9699  break; /* remainder > divisor */
9700  }
9701  if (less)
9702  break; /* quotient is correct */
9703 
9704  /* Subtract the divisor from the remainder */
9705  carry = 0;
9706  for (i = var2ndigitpairs - 1; i > 0; i--)
9707  {
9708  newdig = remainder[i] - divisor[i] + carry;
9709  if (newdig < 0)
9710  {
9711  remainder[i] = newdig + NBASE_SQR;
9712  carry = -1;
9713  }
9714  else
9715  {
9716  remainder[i] = newdig;
9717  carry = 0;
9718  }
9719  }
9720  remainder[0] = remainder[0] - divisor[0] + carry;
9721 
9722  /* Add 1 to the quotient (propagating carries later) */
9723  dividend[qi - 1]++;
9724  }
9725  }
9726  }
9727 
9728  /*
9729  * Because the quotient digits were estimates that might have been off by
9730  * one (and we didn't bother propagating carries when adjusting the
9731  * quotient above), some quotient digits might be out of range, so do a
9732  * final carry propagation pass to normalize back to base NBASE^2, and
9733  * construct the base-NBASE result digits. Note that this is still done
9734  * at full precision w/guard digits.
9735  */
9736  alloc_var(result, res_ndigits);
9737  res_digits = result->digits;
9738  carry = 0;
9739  for (i = res_ndigitpairs - 1; i >= 0; i--)
9740  {
9741  newdig = dividend[i] + carry;
9742  if (newdig < 0)
9743  {
9744  carry = -((-newdig - 1) / NBASE_SQR) - 1;
9745  newdig -= carry * NBASE_SQR;
9746  }
9747  else if (newdig >= NBASE_SQR)
9748  {
9749  carry = newdig / NBASE_SQR;
9750  newdig -= carry * NBASE_SQR;
9751  }
9752  else
9753  carry = 0;
9754  res_digits[2 * i + 1] = (NumericDigit) ((uint32) newdig % NBASE);
9755  res_digits[2 * i] = (NumericDigit) ((uint32) newdig / NBASE);
9756  }
9757  Assert(carry == 0);
9758 
9759  pfree(dividend);
9760 
9761  /*
9762  * Finally, round or truncate the result to the requested precision.
9763  */
9764  result->weight = res_weight;
9765  result->sign = res_sign;
9766 
9767  /* Round or truncate to target rscale (and set result->dscale) */
9768  if (round)
9769  round_var(result, rscale);
9770  else
9771  trunc_var(result, rscale);
9772 
9773  /* Strip leading and trailing zeroes */
9774  strip_var(result);
9775 }
static void div_var_int(const NumericVar *var, int ival, int ival_weight, NumericVar *result, int rscale, bool round)
Definition: numeric.c:9785
#define DIV_GUARD_DIGITS
Definition: numeric.c:99
#define NBASE_SQR
Definition: numeric.c:104
static void alloc_var(NumericVar *var, int ndigits)
Definition: numeric.c:6950
unsigned int uint32
Definition: c.h:506
#define PG_INT64_MAX
Definition: c.h:583
#define i64abs(i)
Definition: c.h:1298
#define ERROR
Definition: elog.h:39
#define ereport(elevel,...)
Definition: elog.h:149
#define Min(x, y)
Definition: numeric.c:14
if(TABLE==NULL||TABLE_index==NULL)
Definition: isn.c:77

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

Referenced by compute_bucket(), div_mod_var(), get_str_from_var_sci(), ln_var(), log_var(), mod_var(), numeric_div_opt_error(), numeric_div_trunc(), numeric_lcm(), numeric_stddev_internal(), 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 9785 of file numeric.c.

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

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(), exp_var(), and ln_var().

◆ do_numeric_accum()

static void do_numeric_accum ( NumericAggState state,
Numeric  newval 
)
static

Definition at line 4854 of file numeric.c.

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

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

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

7761 {
7762  Numeric res;
7763 
7764  res = (Numeric) palloc(VARSIZE(num));
7765  memcpy(res, num, VARSIZE(num));
7766  return res;
7767 }
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 10907 of file numeric.c.

10908 {
10909  int ln_dweight;
10910 
10911  /* Caller should fail on ln(negative), but for the moment return zero */
10912  if (var->sign != NUMERIC_POS)
10913  return 0;
10914 
10915  if (cmp_var(var, &const_zero_point_nine) >= 0 &&
10916  cmp_var(var, &const_one_point_one) <= 0)
10917  {
10918  /*
10919  * 0.9 <= var <= 1.1
10920  *
10921  * ln(var) has a negative weight (possibly very large). To get a
10922  * reasonably accurate result, estimate it using ln(1+x) ~= x.
10923  */
10924  NumericVar x;
10925 
10926  init_var(&x);
10927  sub_var(var, &const_one, &x);
10928 
10929  if (x.ndigits > 0)
10930  {
10931  /* Use weight of most significant decimal digit of x */
10932  ln_dweight = x.weight * DEC_DIGITS + (int) log10(x.digits[0]);
10933  }
10934  else
10935  {
10936  /* x = 0. Since ln(1) = 0 exactly, we don't need extra digits */
10937  ln_dweight = 0;
10938  }
10939 
10940  free_var(&x);
10941  }
10942  else
10943  {
10944  /*
10945  * Estimate the logarithm using the first couple of digits from the
10946  * input number. This will give an accurate result whenever the input
10947  * is not too close to 1.
10948  */
10949  if (var->ndigits > 0)
10950  {
10951  int digits;
10952  int dweight;
10953  double ln_var;
10954 
10955  digits = var->digits[0];
10956  dweight = var->weight * DEC_DIGITS;
10957 
10958  if (var->ndigits > 1)
10959  {
10960  digits = digits * NBASE + var->digits[1];
10961  dweight -= DEC_DIGITS;
10962  }
10963 
10964  /*----------
10965  * We have var ~= digits * 10^dweight
10966  * so ln(var) ~= ln(digits) + dweight * ln(10)
10967  *----------
10968  */
10969  ln_var = log((double) digits) + dweight * 2.302585092994046;
10970  ln_dweight = (int) log10(fabs(ln_var));
10971  }
10972  else
10973  {
10974  /* Caller should fail on ln(0), but for the moment return zero */
10975  ln_dweight = 0;
10976  }
10977  }
10978 
10979  return ln_dweight;
10980 }
static const NumericVar const_zero_point_nine
Definition: numeric.c:445
static const NumericVar const_one_point_one
Definition: numeric.c:455
static void ln_var(const NumericVar *arg, NumericVar *result, int rscale)
Definition: numeric.c:10989
int digits
Definition: informix.c:691
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 10778 of file numeric.c.

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

4685 {
4687  Numeric res;
4688  NumericVar result;
4689  char buf[FLT_DIG + 100];
4690  const char *endptr;
4691 
4692  if (isnan(val))
4694 
4695  if (isinf(val))
4696  {
4697  if (val < 0)
4699  else
4701  }
4702 
4703  snprintf(buf, sizeof(buf), "%.*g", FLT_DIG, val);
4704 
4705  init_var(&result);
4706 
4707  /* Assume we need not worry about leading/trailing spaces */
4708  (void) set_var_from_str(buf, buf, &result, &endptr, NULL);
4709 
4710  res = make_result(&result);
4711 
4712  free_var(&result);
4713 
4715 }
static const NumericVar const_pinf
Definition: numeric.c:461
static const NumericVar const_ninf
Definition: numeric.c:464
static bool set_var_from_str(const char *str, const char *cp, NumericVar *dest, const char **endptr, Node *escontext)
Definition: numeric.c:7009
static Numeric make_result(const NumericVar *var)
Definition: numeric.c:7888
static const NumericVar const_nan
Definition: numeric.c:458
float float4
Definition: c.h:620
#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 4590 of file numeric.c.

4591 {
4593  Numeric res;
4594  NumericVar result;
4595  char buf[DBL_DIG + 100];
4596  const char *endptr;
4597 
4598  if (isnan(val))
4600 
4601  if (isinf(val))
4602  {
4603  if (val < 0)
4605  else
4607  }
4608 
4609  snprintf(buf, sizeof(buf), "%.*g", DBL_DIG, val);
4610 
4611  init_var(&result);
4612 
4613  /* Assume we need not worry about leading/trailing spaces */
4614  (void) set_var_from_str(buf, buf, &result, &endptr, NULL);
4615 
4616  res = make_result(&result);
4617 
4618  free_var(&result);
4619 
4621 }
double float8
Definition: c.h:621
#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 10205 of file numeric.c.

10206 {
10207  NumericVar tmp;
10208 
10209  init_var(&tmp);
10210  set_var_from_var(var, &tmp);
10211 
10212  trunc_var(&tmp, 0);
10213 
10214  if (var->sign == NUMERIC_NEG && cmp_var(var, &tmp) != 0)
10215  sub_var(&tmp, &const_one, &tmp);
10216 
10217  set_var_from_var(&tmp, result);
10218  free_var(&tmp);
10219 }

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

Referenced by numeric_floor().

◆ free_var()

static void free_var ( NumericVar var)
static

Definition at line 6966 of file numeric.c.

6967 {
6968  digitbuf_free(var->buf);
6969  var->buf = NULL;
6970  var->digits = NULL;
6971  var->sign = NUMERIC_NAN;
6972 }
#define NUMERIC_NAN
Definition: numeric.c:199

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

10229 {
10230  int res_dscale;
10231  int cmp;
10232  NumericVar tmp_arg;
10233  NumericVar mod;
10234 
10235  res_dscale = Max(var1->dscale, var2->dscale);
10236 
10237  /*
10238  * Arrange for var1 to be the number with the greater absolute value.
10239  *
10240  * This would happen automatically in the loop below, but avoids an
10241  * expensive modulo operation.
10242  */
10243  cmp = cmp_abs(var1, var2);
10244  if (cmp < 0)
10245  {
10246  const NumericVar *tmp = var1;
10247 
10248  var1 = var2;
10249  var2 = tmp;
10250  }
10251 
10252  /*
10253  * Also avoid the taking the modulo if the inputs have the same absolute
10254  * value, or if the smaller input is zero.
10255  */
10256  if (cmp == 0 || var2->ndigits == 0)
10257  {
10258  set_var_from_var(var1, result);
10259  result->sign = NUMERIC_POS;
10260  result->dscale = res_dscale;
10261  return;
10262  }
10263 
10264  init_var(&tmp_arg);
10265  init_var(&mod);
10266 
10267  /* Use the Euclidean algorithm to find the GCD */
10268  set_var_from_var(var1, &tmp_arg);
10269  set_var_from_var(var2, result);
10270 
10271  for (;;)
10272  {
10273  /* this loop can take a while, so allow it to be interrupted */
10275 
10276  mod_var(&tmp_arg, result, &mod);
10277  if (mod.ndigits == 0)
10278  break;
10279  set_var_from_var(result, &tmp_arg);
10280  set_var_from_var(&mod, result);
10281  }
10282  result->sign = NUMERIC_POS;
10283  result->dscale = res_dscale;
10284 
10285  free_var(&tmp_arg);
10286  free_var(&mod);
10287 }
static void mod_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition: numeric.c:10082
#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 1702 of file numeric.c.

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

References generate_series_step_numeric().

◆ generate_series_step_numeric()

Datum generate_series_step_numeric ( PG_FUNCTION_ARGS  )

Definition at line 1708 of file numeric.c.

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

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

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

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

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

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

◆ get_str_from_var_sci()

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

Definition at line 7644 of file numeric.c.

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

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

Referenced by numeric_out_sci().

◆ hash_numeric()

Datum hash_numeric ( PG_FUNCTION_ARGS  )

Definition at line 2694 of file numeric.c.

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

2775 {
2777  uint64 seed = PG_GETARG_INT64(1);
2778  Datum digit_hash;
2779  Datum result;
2780  int weight;
2781  int start_offset;
2782  int end_offset;
2783  int i;
2784  int hash_len;
2786 
2787  /* If it's NaN or infinity, don't try to hash the rest of the fields */
2788  if (NUMERIC_IS_SPECIAL(key))
2789  PG_RETURN_UINT64(seed);
2790 
2791  weight = NUMERIC_WEIGHT(key);
2792  start_offset = 0;
2793  end_offset = 0;
2794 
2796  for (i = 0; i < NUMERIC_NDIGITS(key); i++)
2797  {
2798  if (digits[i] != (NumericDigit) 0)
2799  break;
2800 
2801  start_offset++;
2802 
2803  weight--;
2804  }
2805 
2806  if (NUMERIC_NDIGITS(key) == start_offset)
2807  PG_RETURN_UINT64(seed - 1);
2808 
2809  for (i = NUMERIC_NDIGITS(key) - 1; i >= 0; i--)
2810  {
2811  if (digits[i] != (NumericDigit) 0)
2812  break;
2813 
2814  end_offset++;
2815  }
2816 
2817  Assert(start_offset + end_offset < NUMERIC_NDIGITS(key));
2818 
2819  hash_len = NUMERIC_NDIGITS(key) - start_offset - end_offset;
2820  digit_hash = hash_any_extended((unsigned char *) (NUMERIC_DIGITS(key)
2821  + start_offset),
2822  hash_len * sizeof(NumericDigit),
2823  seed);
2824 
2825  result = UInt64GetDatum(DatumGetUInt64(digit_hash) ^ weight);
2826 
2827  PG_RETURN_DATUM(result);
2828 }
#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 2559 of file numeric.c.

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

5548 {
5550 
5551  state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
5552 
5553  /* Create the state data on the first call */
5554  if (state == NULL)
5555  state = makePolyNumAggState(fcinfo, true);
5556 
5557  if (!PG_ARGISNULL(1))
5558  {
5559 #ifdef HAVE_INT128
5560  do_int128_accum(state, (int128) PG_GETARG_INT16(1));
5561 #else
5563 #endif
5564  }
5565 
5567 }
#define makePolyNumAggState
Definition: numeric.c:5542
Numeric int64_to_numeric(int64 val)
Definition: numeric.c:4280
static void do_numeric_accum(NumericAggState *state, Numeric newval)
Definition: numeric.c:4854
#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 5971 of file numeric.c.

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

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

6655 {
6656  ArrayType *transarray;
6658  Int8TransTypeData *transdata;
6659 
6660  /*
6661  * If we're invoked as an aggregate, we can cheat and modify our first
6662  * parameter in-place to reduce palloc overhead. Otherwise we need to make
6663  * a copy of it before scribbling on it.
6664  */
6665  if (AggCheckCallContext(fcinfo, NULL))
6666  transarray = PG_GETARG_ARRAYTYPE_P(0);
6667  else
6668  transarray = PG_GETARG_ARRAYTYPE_P_COPY(0);
6669 
6670  if (ARR_HASNULL(transarray) ||
6671  ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
6672  elog(ERROR, "expected 2-element int8 array");
6673 
6674  transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
6675  transdata->count++;
6676  transdata->sum += newval;
6677 
6678  PG_RETURN_ARRAYTYPE_P(transarray);
6679 }
#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 6741 of file numeric.c.

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

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

4542 {
4543  int16 val = PG_GETARG_INT16(0);
4544 
4546 }

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

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

6825 {
6826  ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
6827  Int8TransTypeData *transdata;
6828 
6829  if (ARR_HASNULL(transarray) ||
6830  ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
6831  elog(ERROR, "expected 2-element int8 array");
6832  transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
6833 
6834  /* SQL defines SUM of no values to be NULL */
6835  if (transdata->count == 0)
6836  PG_RETURN_NULL();
6837 
6838  PG_RETURN_DATUM(Int64GetDatumFast(transdata->sum));
6839 }
#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 5570 of file numeric.c.

5571 {
5573 
5574  state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
5575 
5576  /* Create the state data on the first call */
5577  if (state == NULL)
5578  state = makePolyNumAggState(fcinfo, true);
5579 
5580  if (!PG_ARGISNULL(1))
5581  {
5582 #ifdef HAVE_INT128
5583  do_int128_accum(state, (int128) PG_GETARG_INT32(1));
5584 #else
5586 #endif
5587  }
5588 
5590 }
#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 5996 of file numeric.c.

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

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

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

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

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

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

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

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

4387 {
4388  int32 val = PG_GETARG_INT32(0);
4389 
4391 }

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

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

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

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

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

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

References alloc_var(), DEC_DIGITS, NumericVar::digits, NumericVar::dscale, NBASE, NumericVar::ndigits, NUMERIC_NEG, NUMERIC_POS, pg_abs_s64(), 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 5593 of file numeric.c.

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

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

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

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

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

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

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

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

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

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

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

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

5926 {
5927  bytea *sstate;
5928  PolyNumAggState *result;
5930  NumericVar tmp_var;
5931 
5932  if (!AggCheckCallContext(fcinfo, NULL))
5933  elog(ERROR, "aggregate function called in non-aggregate context");
5934 
5935  sstate = PG_GETARG_BYTEA_PP(0);
5936 
5937  init_var(&tmp_var);
5938 
5939  /*
5940  * Initialize a StringInfo so that we can "receive" it using the standard
5941  * recv-function infrastructure.
5942  */
5944  VARSIZE_ANY_EXHDR(sstate));
5945 
5946  result = makePolyNumAggStateCurrentContext(false);
5947 
5948  /* N */
5949  result->N = pq_getmsgint64(&buf);
5950 
5951  /* sumX */
5952  numericvar_deserialize(&buf, &tmp_var);
5953 #ifdef HAVE_INT128
5954  numericvar_to_int128(&tmp_var, &result->sumX);
5955 #else
5956  accum_sum_add(&result->sumX, &tmp_var);
5957 #endif
5958 
5959  pq_getmsgend(&buf);
5960 
5961  free_var(&tmp_var);
5962 
5963  PG_RETURN_POINTER(result);
5964 }
static void numericvar_deserialize(StringInfo buf, NumericVar *var)
Definition: numeric.c:7737
#define makePolyNumAggStateCurrentContext
Definition: numeric.c:5543
#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:678
#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 5876 of file numeric.c.

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

4475 {
4476  int64 val = PG_GETARG_INT64(0);
4477 
4479 }

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

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

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

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

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

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

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

11108 {
11109  NumericVar ln_base;
11110  NumericVar ln_num;
11111  int ln_base_dweight;
11112  int ln_num_dweight;
11113  int result_dweight;
11114  int rscale;
11115  int ln_base_rscale;
11116  int ln_num_rscale;
11117 
11118  init_var(&ln_base);
11119  init_var(&ln_num);
11120 
11121  /* Estimated dweights of ln(base), ln(num) and the final result */
11122  ln_base_dweight = estimate_ln_dweight(base);
11123  ln_num_dweight = estimate_ln_dweight(num);
11124  result_dweight = ln_num_dweight - ln_base_dweight;
11125 
11126  /*
11127  * Select the scale of the result so that it will have at least
11128  * NUMERIC_MIN_SIG_DIGITS significant digits and is not less than either
11129  * input's display scale.
11130  */
11131  rscale = NUMERIC_MIN_SIG_DIGITS - result_dweight;
11132  rscale = Max(rscale, base->dscale);
11133  rscale = Max(rscale, num->dscale);
11134  rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
11135  rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
11136 
11137  /*
11138  * Set the scales for ln(base) and ln(num) so that they each have more
11139  * significant digits than the final result.
11140  */
11141  ln_base_rscale = rscale + result_dweight - ln_base_dweight + 8;
11142  ln_base_rscale = Max(ln_base_rscale, NUMERIC_MIN_DISPLAY_SCALE);
11143 
11144  ln_num_rscale = rscale + result_dweight - ln_num_dweight + 8;
11145  ln_num_rscale = Max(ln_num_rscale, NUMERIC_MIN_DISPLAY_SCALE);
11146 
11147  /* Form natural logarithms */
11148  ln_var(base, &ln_base, ln_base_rscale);
11149  ln_var(num, &ln_num, ln_num_rscale);
11150 
11151  /* Divide and round to the required scale */
11152  div_var(&ln_num, &ln_base, result, rscale, true, false);
11153 
11154  free_var(&ln_num);
11155  free_var(&ln_base);
11156 }
static int estimate_ln_dweight(const NumericVar *var)
Definition: numeric.c:10907
#define NUMERIC_MAX_DISPLAY_SCALE
Definition: numeric.h:40
#define NUMERIC_MIN_SIG_DIGITS
Definition: numeric.h:50

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

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

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

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

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

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

4840 {
4842 
4844  state->calcSumX2 = calcSumX2;
4845  state->agg_context = CurrentMemoryContext;
4846 
4847  return state;
4848 }
MemoryContext CurrentMemoryContext
Definition: mcxt.c:143

References CurrentMemoryContext, and palloc0().

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

◆ mod_var()

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

Definition at line 10082 of file numeric.c.

10083 {
10084  NumericVar tmp;
10085 
10086  init_var(&tmp);
10087 
10088  /* ---------
10089  * We do this using the equation
10090  * mod(x,y) = x - trunc(x/y)*y
10091  * div_var can be persuaded to give us trunc(x/y) directly.
10092  * ----------
10093  */
10094  div_var(var1, var2, &tmp, 0, false, true);
10095 
10096  mul_var(var2, &tmp, &tmp, var2->dscale);
10097 
10098  sub_var(var1, &tmp, result);
10099 
10100  free_var(&tmp);
10101 }

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

8668 {
8669  int res_ndigits;
8670  int res_ndigitpairs;
8671  int res_sign;
8672  int res_weight;
8673  int pair_offset;
8674  int maxdigits;
8675  int maxdigitpairs;
8676  uint64 *dig,
8677  *dig_i1_off;
8678  uint64 maxdig;
8679  uint64 carry;
8680  uint64 newdig;
8681  int var1ndigits;
8682  int var2ndigits;
8683  int var1ndigitpairs;
8684  int var2ndigitpairs;
8685  NumericDigit *var1digits;
8686  NumericDigit *var2digits;
8687  uint32 var1digitpair;
8688  uint32 *var2digitpairs;
8689  NumericDigit *res_digits;
8690  int i,
8691  i1,
8692  i2,
8693  i2limit;
8694 
8695  /*
8696  * Arrange for var1 to be the shorter of the two numbers. This improves
8697  * performance because the inner multiplication loop is much simpler than
8698  * the outer loop, so it's better to have a smaller number of iterations
8699  * of the outer loop. This also reduces the number of times that the
8700  * accumulator array needs to be normalized.
8701  */
8702  if (var1->ndigits > var2->ndigits)
8703  {
8704  const NumericVar *tmp = var1;
8705 
8706  var1 = var2;
8707  var2 = tmp;
8708  }
8709 
8710  /* copy these values into local vars for speed in inner loop */
8711  var1ndigits = var1->ndigits;
8712  var2ndigits = var2->ndigits;
8713  var1digits = var1->digits;
8714  var2digits = var2->digits;
8715 
8716  if (var1ndigits == 0)
8717  {
8718  /* one or both inputs is zero; so is result */
8719  zero_var(result);
8720  result->dscale = rscale;
8721  return;
8722  }
8723 
8724  /*
8725  * If var1 has 1-6 digits and the exact result was requested, delegate to
8726  * mul_var_short() which uses a faster direct multiplication algorithm.
8727  */
8728  if (var1ndigits <= 6 && rscale == var1->dscale + var2->dscale)
8729  {
8730  mul_var_short(var1, var2, result);
8731  return;
8732  }
8733 
8734  /* Determine result sign */
8735  if (var1->sign == var2->sign)
8736  res_sign = NUMERIC_POS;
8737  else
8738  res_sign = NUMERIC_NEG;
8739 
8740  /*
8741  * Determine the number of result digits to compute and the (maximum
8742  * possible) result weight. If the exact result would have more than
8743  * rscale fractional digits, truncate the computation with
8744  * MUL_GUARD_DIGITS guard digits, i.e., ignore input digits that would
8745  * only contribute to the right of that. (This will give the exact
8746  * rounded-to-rscale answer unless carries out of the ignored positions
8747  * would have propagated through more than MUL_GUARD_DIGITS digits.)
8748  *
8749  * Note: an exact computation could not produce more than var1ndigits +
8750  * var2ndigits digits, but we allocate at least one extra output digit in
8751  * case rscale-driven rounding produces a carry out of the highest exact
8752  * digit.
8753  *
8754  * The computation itself is done using base-NBASE^2 arithmetic, so we
8755  * actually process the input digits in pairs, producing a base-NBASE^2
8756  * intermediate result. This significantly improves performance, since
8757  * schoolbook multiplication is O(N^2) in the number of input digits, and
8758  * working in base NBASE^2 effectively halves "N".
8759  *
8760  * Note: in a truncated computation, we must compute at least one extra
8761  * output digit to ensure that all the guard digits are fully computed.
8762  */
8763  /* digit pairs in each input */
8764  var1ndigitpairs = (var1ndigits + 1) / 2;
8765  var2ndigitpairs = (var2ndigits + 1) / 2;
8766 
8767  /* digits in exact result */
8768  res_ndigits = var1ndigits + var2ndigits;
8769 
8770  /* digit pairs in exact result with at least one extra output digit */
8771  res_ndigitpairs = res_ndigits / 2 + 1;
8772 
8773  /* pair offset to align result to end of dig[] */
8774  pair_offset = res_ndigitpairs - var1ndigitpairs - var2ndigitpairs + 1;
8775 
8776  /* maximum possible result weight (odd-length inputs shifted up below) */
8777  res_weight = var1->weight + var2->weight + 1 + 2 * res_ndigitpairs -
8778  res_ndigits - (var1ndigits & 1) - (var2ndigits & 1);
8779 
8780  /* rscale-based truncation with at least one extra output digit */
8781  maxdigits = res_weight + 1 + (rscale + DEC_DIGITS - 1) / DEC_DIGITS +
8783  maxdigitpairs = maxdigits / 2 + 1;
8784 
8785  res_ndigitpairs = Min(res_ndigitpairs, maxdigitpairs);
8786  res_ndigits = 2 * res_ndigitpairs;
8787 
8788  /*
8789  * In the computation below, digit pair i1 of var1 and digit pair i2 of
8790  * var2 are multiplied and added to digit i1+i2+pair_offset of dig[]. Thus
8791  * input digit pairs with index >= res_ndigitpairs - pair_offset don't
8792  * contribute to the result, and can be ignored.
8793  */
8794  if (res_ndigitpairs <= pair_offset)
8795  {
8796  /* All input digits will be ignored; so result is zero */
8797  zero_var(result);
8798  result->dscale = rscale;
8799  return;
8800  }
8801  var1ndigitpairs = Min(var1ndigitpairs, res_ndigitpairs - pair_offset);
8802  var2ndigitpairs = Min(var2ndigitpairs, res_ndigitpairs - pair_offset);
8803 
8804  /*
8805  * We do the arithmetic in an array "dig[]" of unsigned 64-bit integers.
8806  * Since PG_UINT64_MAX is much larger than NBASE^4, this gives us a lot of
8807  * headroom to avoid normalizing carries immediately.
8808  *
8809  * maxdig tracks the maximum possible value of any dig[] entry; when this
8810  * threatens to exceed PG_UINT64_MAX, we take the time to propagate
8811  * carries. Furthermore, we need to ensure that overflow doesn't occur
8812  * during the carry propagation passes either. The carry values could be
8813  * as much as PG_UINT64_MAX / NBASE^2, so really we must normalize when
8814  * digits threaten to exceed PG_UINT64_MAX - PG_UINT64_MAX / NBASE^2.
8815  *
8816  * To avoid overflow in maxdig itself, it actually represents the maximum
8817  * possible value divided by NBASE^2-1, i.e., at the top of the loop it is
8818  * known that no dig[] entry exceeds maxdig * (NBASE^2-1).
8819  *
8820  * The conversion of var1 to base NBASE^2 is done on the fly, as each new
8821  * digit is required. The digits of var2 are converted upfront, and
8822  * stored at the end of dig[]. To avoid loss of precision, the input
8823  * digits are aligned with the start of digit pair array, effectively
8824  * shifting them up (multiplying by NBASE) if the inputs have an odd
8825  * number of NBASE digits.
8826  */
8827  dig = (uint64 *) palloc(res_ndigitpairs * sizeof(uint64) +
8828  var2ndigitpairs * sizeof(uint32));
8829 
8830  /* convert var2 to base NBASE^2, shifting up if its length is odd */
8831  var2digitpairs = (uint32 *) (dig + res_ndigitpairs);
8832 
8833  for (i2 = 0; i2 < var2ndigitpairs - 1; i2++)
8834  var2digitpairs[i2] = var2digits[2 * i2] * NBASE + var2digits[2 * i2 + 1];
8835 
8836  if (2 * i2 + 1 < var2ndigits)
8837  var2digitpairs[i2] = var2digits[2 * i2] * NBASE + var2digits[2 * i2 + 1];
8838  else
8839  var2digitpairs[i2] = var2digits[2 * i2] * NBASE;
8840 
8841  /*
8842  * Start by multiplying var2 by the least significant contributing digit
8843  * pair from var1, storing the results at the end of dig[], and filling
8844  * the leading digits with zeros.
8845  *
8846  * The loop here is the same as the inner loop below, except that we set
8847  * the results in dig[], rather than adding to them. This is the
8848  * performance bottleneck for multiplication, so we want to keep it simple
8849  * enough so that it can be auto-vectorized. Accordingly, process the
8850  * digits left-to-right even though schoolbook multiplication would
8851  * suggest right-to-left. Since we aren't propagating carries in this
8852  * loop, the order does not matter.
8853  */
8854  i1 = var1ndigitpairs - 1;
8855  if (2 * i1 + 1 < var1ndigits)
8856  var1digitpair = var1digits[2 * i1] * NBASE + var1digits[2 * i1 + 1];
8857  else
8858  var1digitpair = var1digits[2 * i1] * NBASE;
8859  maxdig = var1digitpair;
8860 
8861  i2limit = Min(var2ndigitpairs, res_ndigitpairs - i1 - pair_offset);
8862  dig_i1_off = &dig[i1 + pair_offset];
8863 
8864  memset(dig, 0, (i1 + pair_offset) * sizeof(uint64));
8865  for (i2 = 0; i2 < i2limit; i2++)
8866  dig_i1_off[i2] = (uint64) var1digitpair * var2digitpairs[i2];
8867 
8868  /*
8869  * Next, multiply var2 by the remaining digit pairs from var1, adding the
8870  * results to dig[] at the appropriate offsets, and normalizing whenever
8871  * there is a risk of any dig[] entry overflowing.
8872  */
8873  for (i1 = i1 - 1; i1 >= 0; i1--)
8874  {
8875  var1digitpair = var1digits[2 * i1] * NBASE + var1digits[2 * i1 + 1];
8876  if (var1digitpair == 0)
8877  continue;
8878 
8879  /* Time to normalize? */
8880  maxdig += var1digitpair;
8881  if (maxdig > (PG_UINT64_MAX - PG_UINT64_MAX / NBASE_SQR) / (NBASE_SQR - 1))
8882  {
8883  /* Yes, do it (to base NBASE^2) */
8884  carry = 0;
8885  for (i = res_ndigitpairs - 1; i >= 0; i--)
8886  {
8887  newdig = dig[i] + carry;
8888  if (newdig >= NBASE_SQR)
8889  {
8890  carry = newdig / NBASE_SQR;
8891  newdig -= carry * NBASE_SQR;
8892  }
8893  else
8894  carry = 0;
8895  dig[i] = newdig;
8896  }
8897  Assert(carry == 0);
8898  /* Reset maxdig to indicate new worst-case */
8899  maxdig = 1 + var1digitpair;
8900  }
8901 
8902  /* Multiply and add */
8903  i2limit = Min(var2ndigitpairs, res_ndigitpairs - i1 - pair_offset);
8904  dig_i1_off = &dig[i1 + pair_offset];
8905 
8906  for (i2 = 0; i2 < i2limit; i2++)
8907  dig_i1_off[i2] += (uint64) var1digitpair * var2digitpairs[i2];
8908  }
8909 
8910  /*
8911  * Now we do a final carry propagation pass to normalize back to base
8912  * NBASE^2, and construct the base-NBASE result digits. Note that this is
8913  * still done at full precision w/guard digits.
8914  */
8915  alloc_var(result, res_ndigits);
8916  res_digits = result->digits;
8917  carry = 0;
8918  for (i = res_ndigitpairs - 1; i >= 0; i--)
8919  {
8920  newdig = dig[i] + carry;
8921  if (newdig >= NBASE_SQR)
8922  {
8923  carry = newdig / NBASE_SQR;
8924  newdig -= carry * NBASE_SQR;
8925  }
8926  else
8927  carry = 0;
8928  res_digits[2 * i + 1] = (NumericDigit) ((uint32) newdig % NBASE);
8929  res_digits[2 * i] = (NumericDigit) ((uint32) newdig / NBASE);
8930  }
8931  Assert(carry == 0);
8932 
8933  pfree(dig);
8934 
8935  /*
8936  * Finally, round the result to the requested precision.
8937  */
8938  result->weight = res_weight;
8939  result->sign = res_sign;
8940 
8941  /* Round to target rscale (and set result->dscale) */
8942  round_var(result, rscale);
8943 
8944  /* Strip leading and trailing zeroes */
8945  strip_var(result);
8946 }
static void mul_var_short(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition: numeric.c:8957
#define MUL_GUARD_DIGITS
Definition: numeric.c:98
#define PG_UINT64_MAX
Definition: c.h:584

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

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

◆ mul_var_short()

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

Definition at line 8957 of file numeric.c.

8959 {
8960  int var1ndigits = var1->ndigits;
8961  int var2ndigits = var2->ndigits;
8962  NumericDigit *var1digits = var1->digits;
8963  NumericDigit *var2digits = var2->digits;
8964  int res_sign;
8965  int res_weight;
8966  int res_ndigits;
8967  NumericDigit *res_buf;
8968  NumericDigit *res_digits;
8969  uint32 carry = 0;
8970  uint32 term;
8971 
8972  /* Check preconditions */
8973  Assert(var1ndigits >= 1);
8974  Assert(var1ndigits <= 6);
8975  Assert(var2ndigits >= var1ndigits);
8976 
8977  /*
8978  * Determine the result sign, weight, and number of digits to calculate.
8979  * The weight figured here is correct if the product has no leading zero
8980  * digits; otherwise strip_var() will fix things up. Note that, unlike
8981  * mul_var(), we do not need to allocate an extra output digit, because we
8982  * are not rounding here.
8983  */
8984  if (var1->sign == var2->sign)
8985  res_sign = NUMERIC_POS;
8986  else
8987  res_sign = NUMERIC_NEG;
8988  res_weight = var1->weight + var2->weight + 1;
8989  res_ndigits = var1ndigits + var2ndigits;
8990 
8991  /* Allocate result digit array */
8992  res_buf = digitbuf_alloc(res_ndigits + 1);
8993  res_buf[0] = 0; /* spare digit for later rounding */
8994  res_digits = res_buf + 1;
8995 
8996  /*
8997  * Compute the result digits in reverse, in one pass, propagating the
8998  * carry up as we go. The i'th result digit consists of the sum of the
8999  * products var1digits[i1] * var2digits[i2] for which i = i1 + i2 + 1.
9000  */
9001 #define PRODSUM1(v1,i1,v2,i2) ((v1)[(i1)] * (v2)[(i2)])
9002 #define PRODSUM2(v1,i1,v2,i2) (PRODSUM1(v1,i1,v2,i2) + (v1)[(i1)+1] * (v2)[(i2)-1])
9003 #define PRODSUM3(v1,i1,v2,i2) (PRODSUM2(v1,i1,v2,i2) + (v1)[(i1)+2] * (v2)[(i2)-2])
9004 #define PRODSUM4(v1,i1,v2,i2) (PRODSUM3(v1,i1,v2,i2) + (v1)[(i1)+3] * (v2)[(i2)-3])
9005 #define PRODSUM5(v1,i1,v2,i2) (PRODSUM4(v1,i1,v2,i2) + (v1)[(i1)+4] * (v2)[(i2)-4])
9006 #define PRODSUM6(v1,i1,v2,i2) (PRODSUM5(v1,i1,v2,i2) + (v1)[(i1)+5] * (v2)[(i2)-5])
9007 
9008  switch (var1ndigits)
9009  {
9010  case 1:
9011  /* ---------
9012  * 1-digit case:
9013  * var1ndigits = 1
9014  * var2ndigits >= 1
9015  * res_ndigits = var2ndigits + 1
9016  * ----------
9017  */
9018  for (int i = var2ndigits - 1; i >= 0; i--)
9019  {
9020  term = PRODSUM1(var1digits, 0, var2digits, i) + carry;
9021  res_digits[i + 1] = (NumericDigit) (term % NBASE);
9022  carry = term / NBASE;
9023  }
9024  res_digits[0] = (NumericDigit) carry;
9025  break;
9026 
9027  case 2:
9028  /* ---------
9029  * 2-digit case:
9030  * var1ndigits = 2
9031  * var2ndigits >= 2
9032  * res_ndigits = var2ndigits + 2
9033  * ----------
9034  */
9035  /* last result digit and carry */
9036  term = PRODSUM1(var1digits, 1, var2digits, var2ndigits - 1);
9037  res_digits[res_ndigits - 1] = (NumericDigit) (term % NBASE);
9038  carry = term / NBASE;
9039 
9040  /* remaining digits, except for the first two */
9041  for (int i = var2ndigits - 1; i >= 1; i--)
9042  {
9043  term = PRODSUM2(var1digits, 0, var2digits, i) + carry;
9044  res_digits[i + 1] = (NumericDigit) (term % NBASE);
9045  carry = term / NBASE;
9046  }
9047  break;
9048 
9049  case 3:
9050  /* ---------
9051  * 3-digit case:
9052  * var1ndigits = 3
9053  * var2ndigits >= 3
9054  * res_ndigits = var2ndigits + 3
9055  * ----------
9056  */
9057  /* last two result digits */
9058  term = PRODSUM1(var1digits, 2, var2digits, var2ndigits - 1);
9059  res_digits[res_ndigits - 1] = (NumericDigit) (term % NBASE);
9060  carry = term / NBASE;
9061 
9062  term = PRODSUM2(var1digits, 1, var2digits, var2ndigits - 1) + carry;
9063  res_digits[res_ndigits - 2] = (NumericDigit) (term % NBASE);
9064  carry = term / NBASE;
9065 
9066  /* remaining digits, except for the first three */
9067  for (int i = var2ndigits - 1; i >= 2; i--)
9068  {
9069  term = PRODSUM3(var1digits, 0, var2digits, i) + carry;
9070  res_digits[i + 1] = (NumericDigit) (term % NBASE);
9071  carry = term / NBASE;
9072  }
9073  break;
9074 
9075  case 4:
9076  /* ---------
9077  * 4-digit case:
9078  * var1ndigits = 4
9079  * var2ndigits >= 4
9080  * res_ndigits = var2ndigits + 4
9081  * ----------
9082  */
9083  /* last three result digits */
9084  term = PRODSUM1(var1digits, 3, var2digits, var2ndigits - 1);
9085  res_digits[res_ndigits - 1] = (NumericDigit) (term % NBASE);
9086  carry = term / NBASE;
9087 
9088  term = PRODSUM2(var1digits, 2, var2digits, var2ndigits - 1) + carry;
9089  res_digits[res_ndigits - 2] = (NumericDigit) (term % NBASE);
9090  carry = term / NBASE;
9091 
9092  term = PRODSUM3(var1digits, 1, var2digits, var2ndigits - 1) + carry;
9093  res_digits[res_ndigits - 3] = (NumericDigit) (term % NBASE);
9094  carry = term / NBASE;
9095 
9096  /* remaining digits, except for the first four */
9097  for (int i = var2ndigits - 1; i >= 3; i--)
9098  {
9099  term = PRODSUM4(var1digits, 0, var2digits, i) + carry;
9100  res_digits[i + 1] = (NumericDigit) (term % NBASE);
9101  carry = term / NBASE;
9102  }
9103  break;
9104 
9105  case 5:
9106  /* ---------
9107  * 5-digit case:
9108  * var1ndigits = 5
9109  * var2ndigits >= 5
9110  * res_ndigits = var2ndigits + 5
9111  * ----------
9112  */
9113  /* last four result digits */
9114  term = PRODSUM1(var1digits, 4, var2digits, var2ndigits - 1);
9115  res_digits[res_ndigits - 1] = (NumericDigit) (term % NBASE);
9116  carry = term / NBASE;
9117 
9118  term = PRODSUM2(var1digits, 3, var2digits, var2ndigits - 1) + carry;
9119  res_digits[res_ndigits - 2] = (NumericDigit) (term % NBASE);
9120  carry = term / NBASE;
9121 
9122  term = PRODSUM3(var1digits, 2, var2digits, var2ndigits - 1) + carry;
9123  res_digits[res_ndigits - 3] = (NumericDigit) (term % NBASE);
9124  carry = term / NBASE;
9125 
9126  term = PRODSUM4(var1digits, 1, var2digits, var2ndigits - 1) + carry;
9127  res_digits[res_ndigits - 4] = (NumericDigit) (term % NBASE);
9128  carry = term / NBASE;
9129 
9130  /* remaining digits, except for the first five */
9131  for (int i = var2ndigits - 1; i >= 4; i--)
9132  {
9133  term = PRODSUM5(var1digits, 0, var2digits, i) + carry;
9134  res_digits[i + 1] = (NumericDigit) (term % NBASE);
9135  carry = term / NBASE;
9136  }
9137  break;
9138 
9139  case 6:
9140  /* ---------
9141  * 6-digit case:
9142  * var1ndigits = 6
9143  * var2ndigits >= 6
9144  * res_ndigits = var2ndigits + 6
9145  * ----------
9146  */
9147  /* last five result digits */
9148  term = PRODSUM1(var1digits, 5, var2digits, var2ndigits - 1);
9149  res_digits[res_ndigits - 1] = (NumericDigit) (term % NBASE);
9150  carry = term / NBASE;
9151 
9152  term = PRODSUM2(var1digits, 4, var2digits, var2ndigits - 1) + carry;
9153  res_digits[res_ndigits - 2] = (NumericDigit) (term % NBASE);
9154  carry = term / NBASE;
9155 
9156  term = PRODSUM3(var1digits, 3, var2digits, var2ndigits - 1) + carry;
9157  res_digits[res_ndigits - 3] = (NumericDigit) (term % NBASE);
9158  carry = term / NBASE;
9159 
9160  term = PRODSUM4(var1digits, 2, var2digits, var2ndigits - 1) + carry;
9161  res_digits[res_ndigits - 4] = (NumericDigit) (term % NBASE);
9162  carry = term / NBASE;
9163 
9164  term = PRODSUM5(var1digits, 1, var2digits, var2ndigits - 1) + carry;
9165  res_digits[res_ndigits - 5] = (NumericDigit) (term % NBASE);
9166  carry = term / NBASE;
9167 
9168  /* remaining digits, except for the first six */
9169  for (int i = var2ndigits - 1; i >= 5; i--)
9170  {
9171  term = PRODSUM6(var1digits, 0, var2digits, i) + carry;
9172  res_digits[i + 1] = (NumericDigit) (term % NBASE);
9173  carry = term / NBASE;
9174  }
9175  break;
9176  }
9177 
9178  /*
9179  * Finally, for var1ndigits > 1, compute the remaining var1ndigits most
9180  * significant result digits.
9181  */
9182  switch (var1ndigits)
9183  {
9184  case 6:
9185  term = PRODSUM5(var1digits, 0, var2digits, 4) + carry;
9186  res_digits[5] = (NumericDigit) (term % NBASE);
9187  carry = term / NBASE;
9188  /* FALLTHROUGH */
9189  case 5:
9190  term = PRODSUM4(var1digits, 0, var2digits, 3) + carry;
9191  res_digits[4] = (NumericDigit) (term % NBASE);
9192  carry = term / NBASE;
9193  /* FALLTHROUGH */
9194  case 4:
9195  term = PRODSUM3(var1digits, 0, var2digits, 2) + carry;
9196  res_digits[3] = (NumericDigit) (term % NBASE);
9197  carry = term / NBASE;
9198  /* FALLTHROUGH */
9199  case 3:
9200  term = PRODSUM2(var1digits, 0, var2digits, 1) + carry;
9201  res_digits[2] = (NumericDigit) (term % NBASE);
9202  carry = term / NBASE;
9203  /* FALLTHROUGH */
9204  case 2:
9205  term = PRODSUM1(var1digits, 0, var2digits, 0) + carry;
9206  res_digits[1] = (NumericDigit) (term % NBASE);
9207  res_digits[0] = (NumericDigit) (term / NBASE);
9208  break;
9209  }
9210 
9211  /* Store the product in result */
9212  digitbuf_free(result->buf);
9213  result->ndigits = res_ndigits;
9214  result->buf = res_buf;
9215  result->digits = res_digits;
9216  result->weight = res_weight;
9217  result->sign = res_sign;
9218  result->dscale = var1->dscale + var2->dscale;
9219 
9220  /* Strip leading and trailing zeroes */
9221  strip_var(result);
9222 }
#define PRODSUM2(v1, i1, v2, i2)
#define PRODSUM3(v1, i1, v2, i2)
#define PRODSUM1(v1, i1, v2, i2)
#define PRODSUM5(v1, i1, v2, i2)
#define PRODSUM6(v1, i1, v2, i2)
#define PRODSUM4(v1, i1, v2, i2)

References Assert, NumericVar::buf, digitbuf_alloc, digitbuf_free, NumericVar::digits, NumericVar::dscale, i, NBASE, NumericVar::ndigits, NUMERIC_NEG, NUMERIC_POS, PRODSUM1, PRODSUM2, PRODSUM3, PRODSUM4, PRODSUM5, PRODSUM6, NumericVar::sign, strip_var(), and NumericVar::weight.

Referenced by mul_var().

◆ numeric()

Definition at line 1245 of file numeric.c.

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

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

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

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

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

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

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

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

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

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

2846 {
2847  Numeric num1 = PG_GETARG_NUMERIC(0);
2848  Numeric num2 = PG_GETARG_NUMERIC(1);
2849  Numeric res;
2850 
2851  res = numeric_add_opt_error(num1, num2, NULL);
2852 
2854 }
Numeric numeric_add_opt_error(Numeric num1, Numeric num2, bool *have_error)
Definition: numeric.c:2864

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

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

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

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

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

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

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

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

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

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

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

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

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

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

2201 {
2202  /*
2203  * NOTE WELL: this is intentionally backwards, because the abbreviation is
2204  * negated relative to the original value, to handle NaN/infinity cases.
2205  */
2207  return 1;
2209  return -1;
2210  return 0;
2211 }
#define DatumGetNumericAbbrev(X)
Definition: numeric.c:412
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 5037 of file numeric.c.

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

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

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

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

3122 {
3123  Numeric num1 = PG_GETARG_NUMERIC(0);
3124  Numeric num2 = PG_GETARG_NUMERIC(1);
3125  Numeric res;
3126 
3127  res = numeric_div_opt_error(num1, num2, NULL);
3128 
3130 }
Numeric numeric_div_opt_error(Numeric num1, Numeric num2, bool *have_error)
Definition: numeric.c:3141

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

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

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

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

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

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

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

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

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

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

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

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

4720 {
4721  Numeric num = PG_GETARG_NUMERIC(0);
4722  char *tmp;
4723  Datum result;
4724 
4725  if (NUMERIC_IS_SPECIAL(num))
4726  {
4727  if (NUMERIC_IS_PINF(num))
4729  else if (NUMERIC_IS_NINF(num))
4731  else
4733  }
4734 
4736  NumericGetDatum(num)));
4737 
4739 
4740  pfree(tmp);
4741 
4742  PG_RETURN_DATUM(result);
4743 }
Datum numeric_out(PG_FUNCTION_ARGS)
Definition: numeric.c:815
Datum float4in(PG_FUNCTION_ARGS)
Definition: float.c:165
static float4 get_float4_infinity(void)
Definition: float.h:74
static float4 get_float4_nan(void)
Definition: float.h:111
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:641
#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 4625 of file numeric.c.

4626 {
4627  Numeric num = PG_GETARG_NUMERIC(0);
4628  char *tmp;
4629  Datum result;
4630 
4631  if (NUMERIC_IS_SPECIAL(num))
4632  {
4633  if (NUMERIC_IS_PINF(num))
4635  else if (NUMERIC_IS_NINF(num))
4637  else
4639  }
4640 
4642  NumericGetDatum(num)));
4643 
4645 
4646  pfree(tmp);
4647 
4648  PG_RETURN_DATUM(result);
4649 }
Datum float8in(PG_FUNCTION_ARGS)
Definition: float.c:365
static float8 get_float8_infinity(void)
Definition: float.h:94
static float8 get_float8_nan(void)
Definition: float.h:123
#define PG_RETURN_FLOAT8(x)
Definition: fmgr.h:367

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

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

◆ numeric_float8_no_overflow()

Datum numeric_float8_no_overflow ( PG_FUNCTION_ARGS  )

Definition at line 4658 of file numeric.c.

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

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

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

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

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

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

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

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

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

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

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

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

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

◆ numeric_inc()

Datum numeric_inc ( PG_FUNCTION_ARGS  )

Definition at line 3434 of file numeric.c.

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

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

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

4445 {
4446  Numeric num = PG_GETARG_NUMERIC(0);
4447 
4449 }
int32 numeric_int4_opt_error(Numeric num, bool *have_error)
Definition: numeric.c:4394

References numeric_int4_opt_error(), PG_GETARG_NUMERIC, and PG_RETURN_INT32.

Referenced by jsonb_int4().

◆ numeric_int4_opt_error()

int32 numeric_int4_opt_error ( Numeric  num,
bool have_error 
)

Definition at line 4394 of file numeric.c.

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

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(), numeric_int4(), and numeric_to_char().

◆ numeric_int8()

Datum numeric_int8 ( PG_FUNCTION_ARGS  )

Definition at line 4532 of file numeric.c.

4533 {
4534  Numeric num = PG_GETARG_NUMERIC(0);
4535 
4537 }
int64 numeric_int8_opt_error(Numeric num, bool *have_error)
Definition: numeric.c:4482

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

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

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

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

References NUMERIC_IS_INF.

Referenced by executeItemOptUnwrapTarget(), and PLyNumber_ToJsonbValue().

◆ numeric_is_integral()

static bool numeric_is_integral ( Numeric  num)
static

Definition at line 872 of file numeric.c.

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

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

851 {
852  return NUMERIC_IS_NAN(num);
853 }

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

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

References cmp_numerics(), PG_GETARG_NUMERIC, and PG_RETURN_NUMERIC.

◆ numeric_lcm()

Datum numeric_lcm ( PG_FUNCTION_ARGS  )

Definition at line 3561 of file numeric.c.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

3346 {
3347  Numeric num1 = PG_GETARG_NUMERIC(0);
3348  Numeric num2 = PG_GETARG_NUMERIC(1);
3349  Numeric res;
3350 
3351  res = numeric_mod_opt_error(num1, num2, NULL);
3352 
3354 }
Numeric numeric_mod_opt_error(Numeric num1, Numeric num2, bool *have_error)
Definition: numeric.c:3365

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

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

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

3001 {
3002  Numeric num1 = PG_GETARG_NUMERIC(0);
3003  Numeric num2 = PG_GETARG_NUMERIC(1);
3004  Numeric res;
3005 
3006  res = numeric_mul_opt_error(num1, num2, NULL);
3007 
3009 }
Numeric numeric_mul_opt_error(Numeric num1, Numeric num2, bool *have_error)
Definition: numeric.c:3020

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

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

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

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

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

◆ numeric_normalize()

char* numeric_normalize ( Numeric  num)

Definition at line 1025 of file numeric.c.

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

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

Referenced by make_scalar_key().

◆ numeric_out()

Datum numeric_out ( PG_FUNCTION_ARGS  )

Definition at line 815 of file numeric.c.

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

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

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

◆ numeric_out_sci()

char* numeric_out_sci ( Numeric  num,
int  scale 
)

Definition at line 991 of file numeric.c.

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

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

Referenced by int8_to_char(), and numeric_to_char().

◆ numeric_pg_lsn()

Datum numeric_pg_lsn ( PG_FUNCTION_ARGS  )

Definition at line 4747 of file numeric.c.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

◆ numeric_scale()

Datum numeric_scale ( PG_FUNCTION_ARGS  )

Definition at line 4119 of file numeric.c.

4120 {
4121  Numeric num = PG_GETARG_NUMERIC(0);
4122 
4123  if (NUMERIC_IS_SPECIAL(num))
4124  PG_RETURN_NULL();
4125 
4127 }

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

1163 {
1164  Numeric num = PG_GETARG_NUMERIC(0);
1165  NumericVar x;
1167  int i;
1168 
1169  init_var_from_num(num, &x);
1170 
1171  pq_begintypsend(&buf);
1172 
1173  pq_sendint16(&buf, x.ndigits);
1174  pq_sendint16(&buf, x.weight);
1175  pq_sendint16(&buf, x.sign);
1176  pq_sendint16(&buf, x.dscale);
1177  for (i = 0; i < x.ndigits; i++)
1178  pq_sendint16(&buf, x.digits[i]);
1179 
1181 }
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 5311 of file numeric.c.

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

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

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

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

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

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

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

References cmp_numerics(), PG_GETARG_NUMERIC, and PG_RETURN_NUMERIC.

◆ numeric_sortsupport()

Datum numeric_sortsupport ( PG_FUNCTION_ARGS  )

Definition at line 2008 of file numeric.c.

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

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

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

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

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

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

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

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

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

2923 {
2924  Numeric num1 = PG_GETARG_NUMERIC(0);
2925  Numeric num2 = PG_GETARG_NUMERIC(1);
2926  Numeric res;
2927 
2928  res = numeric_sub_opt_error(num1, num2, NULL);
2929 
2931 }
Numeric numeric_sub_opt_error(Numeric num1, Numeric num2, bool *have_error)
Definition: numeric.c:2942

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

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

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

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

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

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

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

◆ numeric_trim_scale()

Datum numeric_trim_scale ( PG_FUNCTION_ARGS  )

Definition at line 4204 of file numeric.c.

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

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

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

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

Referenced by getArrayIndex().

◆ numeric_typmod_precision()

static int numeric_typmod_precision ( int32  typmod)
inlinestatic

Definition at line 926 of file numeric.c.

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

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

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

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

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

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

1462 {
1463  Numeric num = PG_GETARG_NUMERIC(0);
1464 
1466 }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

4458 {
4459  int64 val;
4460 
4461  if (!numericvar_to_int64(var, &val))
4462  return false;
4463 
4465  return false;
4466 
4467  /* Down-convert to int4 */
4468  *result = (int32) val;
4469 
4470  return true;
4471 }
#define PG_INT32_MAX
Definition: c.h:580
#define PG_INT32_MIN
Definition: c.h:579

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

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

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

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

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

11535 {
11536  /* Construct the result directly, starting from 10^0 = 1 */
11537  set_var_from_var(&const_one, result);
11538 
11539  /* Scale needed to represent the result exactly */
11540  result->dscale = exp < 0 ? -exp : 0;
11541 
11542  /* Base-NBASE weight of result and remaining exponent */
11543  if (exp >= 0)
11544  result->weight = exp / DEC_DIGITS;
11545  else
11546  result->weight = (exp + 1) / DEC_DIGITS - 1;
11547 
11548  exp -= result->weight * DEC_DIGITS;
11549 
11550  /* Final adjustment of the result's single NBASE digit */
11551  while (exp-- > 0)
11552  result->digits[0] *= 10;
11553 }

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

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

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

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

References const_one, DEC_DIGITS, NumericVar::digits, div_var(), NumericVar::dscale, ereport, errcode(), errmsg(), ERROR, free_var(), i, init_var, Max, Min, mul_var(), NBASE, NumericVar::ndigits, NUMERIC_MAX_DISPLAY_SCALE, NUMERIC_MIN_DISPLAY_SCALE, NUMERIC_MIN_SIG_DIGITS, NUMERIC_WEIGHT_MAX, pg_abs_s32(), 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 4225 of file numeric.c.

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

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

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

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

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

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

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

Referenced by numeric_div_opt_error(), and numeric_stddev_internal().

◆ set_var_from_non_decimal_integer_str()

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

Definition at line 7239 of file numeric.c.

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

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

Referenced by numeric_in().

◆ set_var_from_num()

static void set_var_from_num ( Numeric  num,
NumericVar dest 
)
static

Definition at line 7417 of file numeric.c.

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

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

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

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

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

◆ set_var_from_var()

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

Definition at line 7465 of file numeric.c.

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

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

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

◆ sqrt_var()

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

Definition at line 10298 of file numeric.c.

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

12156 {
12157  NumericDigit *digits = var->digits;
12158  int ndigits = var->ndigits;
12159 
12160  /* Strip leading zeroes */
12161  while (ndigits > 0 && *digits == 0)
12162  {
12163  digits++;
12164  var->weight--;
12165  ndigits--;
12166  }
12167 
12168  /* Strip trailing zeroes */
12169  while (ndigits > 0 && digits[ndigits - 1] == 0)
12170  ndigits--;
12171 
12172  /* If it's zero, normalize the sign and weight */
12173  if (ndigits == 0)
12174  {
12175  var->sign = NUMERIC_POS;
12176  var->weight = 0;
12177  }
12178 
12179  var->digits = digits;
12180  var->ndigits = ndigits;
12181 }

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

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

◆ sub_abs()

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

Definition at line 11905 of file numeric.c.

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

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

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

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

12094 {
12095  int di;
12096  int ndigits;
12097 
12098  var->dscale = rscale;
12099 
12100  /* decimal digits wanted */
12101  di = (var->weight + 1) * DEC_DIGITS + rscale;
12102 
12103  /*
12104  * If di <= 0, the value loses all digits.
12105  */
12106  if (di <= 0)
12107  {
12108  var->ndigits = 0;
12109  var->weight = 0;
12110  var->sign = NUMERIC_POS;
12111  }
12112  else
12113  {
12114  /* NBASE digits wanted */
12115  ndigits = (di + DEC_DIGITS - 1) / DEC_DIGITS;
12116 
12117  if (ndigits <= var->ndigits)
12118  {
12119  var->ndigits = ndigits;
12120 
12121 #if DEC_DIGITS == 1
12122  /* no within-digit stuff to worry about */
12123 #else
12124  /* 0, or number of decimal digits to keep in last NBASE digit */
12125  di %= DEC_DIGITS;
12126 
12127  if (di > 0)
12128  {
12129  /* Must truncate within last NBASE digit */
12130  NumericDigit *digits = var->digits;
12131  int extra,
12132  pow10;
12133 
12134 #if DEC_DIGITS == 4
12135  pow10 = round_powers[di];
12136 #elif DEC_DIGITS == 2
12137  pow10 = 10;
12138 #else
12139 #error unsupported NBASE
12140 #endif
12141  extra = digits[--ndigits] % pow10;
12142  digits[ndigits] -= extra;
12143  }
12144 #endif
12145  }
12146  }
12147 }

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_int(), floor_var(), numeric_recv(), and numeric_trunc().

◆ width_bucket_numeric()

Datum width_bucket_numeric ( PG_FUNCTION_ARGS  )

Definition at line 1845 of file numeric.c.

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

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

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

Referenced by set_var_from_non_decimal_integer_str().

◆ zero_var()

static void zero_var ( NumericVar var)
static

Definition at line 6982 of file numeric.c.

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

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

Referenced by add_var(), div_var(), 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:427

Definition at line 431 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 427 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:449

Definition at line 455 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 449 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:434

Definition at line 435 of file numeric.c.

Referenced by ln_var().

◆ const_two_data

const NumericDigit const_two_data[1] = {2}
static

Definition at line 434 of file numeric.c.

◆ const_zero

◆ const_zero_data

const NumericDigit const_zero_data[1] = {0}
static

Definition at line 423 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:439

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

◆ round_powers

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

Definition at line 468 of file numeric.c.

Referenced by round_var(), and trunc_var().