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

Go to the source code of this file.

Data Structures

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

Macros

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

Typedefs

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

Functions

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

Variables

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

Macro Definition Documentation

◆ DatumGetNumericAbbrev

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

Definition at line 403 of file numeric.c.

◆ DEC_DIGITS

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

Definition at line 97 of file numeric.c.

◆ digitbuf_alloc

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

Definition at line 476 of file numeric.c.

◆ digitbuf_free

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

Definition at line 478 of file numeric.c.

◆ DIV_GUARD_DIGITS

#define DIV_GUARD_DIGITS   4

Definition at line 99 of file numeric.c.

◆ dump_numeric

#define dump_numeric (   s,
 
)

Definition at line 472 of file numeric.c.

◆ dump_var

#define dump_var (   s,
 
)

Definition at line 473 of file numeric.c.

◆ HALF_NBASE

#define HALF_NBASE   5000

Definition at line 96 of file numeric.c.

◆ init_var

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

Definition at line 484 of file numeric.c.

◆ makePolyNumAggState

#define makePolyNumAggState   makeNumericAggState

Definition at line 5493 of file numeric.c.

◆ makePolyNumAggStateCurrentContext

#define makePolyNumAggStateCurrentContext   makeNumericAggStateCurrentContext

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

◆ NBASE

#define NBASE   10000

Definition at line 95 of file numeric.c.

◆ NUMERIC_ABBREV_BITS

#define NUMERIC_ABBREV_BITS   (SIZEOF_DATUM * BITS_PER_BYTE)

Definition at line 394 of file numeric.c.

◆ NUMERIC_ABBREV_NAN

#define NUMERIC_ABBREV_NAN   NumericAbbrevGetDatum(PG_INT32_MIN)

Definition at line 404 of file numeric.c.

◆ NUMERIC_ABBREV_NINF

#define NUMERIC_ABBREV_NINF   NumericAbbrevGetDatum(PG_INT32_MAX)

Definition at line 406 of file numeric.c.

◆ NUMERIC_ABBREV_PINF

#define NUMERIC_ABBREV_PINF   NumericAbbrevGetDatum(-PG_INT32_MAX)

Definition at line 405 of file numeric.c.

◆ NUMERIC_CAN_BE_SHORT

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

Definition at line 490 of file numeric.c.

◆ NUMERIC_DIGITS

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

Definition at line 486 of file numeric.c.

◆ NUMERIC_DSCALE

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

Definition at line 242 of file numeric.c.

◆ NUMERIC_DSCALE_MASK

#define NUMERIC_DSCALE_MASK   0x3FFF

Definition at line 233 of file numeric.c.

◆ NUMERIC_DSCALE_MAX

#define NUMERIC_DSCALE_MAX   NUMERIC_DSCALE_MASK

Definition at line 234 of file numeric.c.

◆ NUMERIC_EXT_FLAGBITS

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

Definition at line 202 of file numeric.c.

◆ NUMERIC_EXT_SIGN_MASK

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

Definition at line 196 of file numeric.c.

◆ NUMERIC_FLAGBITS

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

Definition at line 170 of file numeric.c.

◆ NUMERIC_HDRSZ

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

Definition at line 174 of file numeric.c.

◆ NUMERIC_HDRSZ_SHORT

#define NUMERIC_HDRSZ_SHORT   (VARHDRSZ + sizeof(uint16))

Definition at line 175 of file numeric.c.

◆ NUMERIC_HEADER_IS_SHORT

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

Definition at line 182 of file numeric.c.

◆ NUMERIC_HEADER_SIZE

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

Definition at line 183 of file numeric.c.

◆ NUMERIC_INF_SIGN_MASK

#define NUMERIC_INF_SIGN_MASK   0x2000

Definition at line 200 of file numeric.c.

◆ NUMERIC_IS_INF

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

Definition at line 206 of file numeric.c.

◆ NUMERIC_IS_NAN

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

Definition at line 203 of file numeric.c.

◆ NUMERIC_IS_NINF

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

Definition at line 205 of file numeric.c.

◆ NUMERIC_IS_PINF

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

Definition at line 204 of file numeric.c.

◆ NUMERIC_IS_SHORT

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

Definition at line 171 of file numeric.c.

◆ NUMERIC_IS_SPECIAL

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

Definition at line 172 of file numeric.c.

◆ NUMERIC_NAN

#define NUMERIC_NAN   0xC000

Definition at line 197 of file numeric.c.

◆ NUMERIC_NDIGITS

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

Definition at line 488 of file numeric.c.

◆ NUMERIC_NEG

#define NUMERIC_NEG   0x4000

Definition at line 166 of file numeric.c.

◆ NUMERIC_NINF

#define NUMERIC_NINF   0xF000

Definition at line 199 of file numeric.c.

◆ NUMERIC_PINF

#define NUMERIC_PINF   0xD000

Definition at line 198 of file numeric.c.

◆ NUMERIC_POS

#define NUMERIC_POS   0x0000

Definition at line 165 of file numeric.c.

◆ NUMERIC_SHORT

#define NUMERIC_SHORT   0x8000

Definition at line 167 of file numeric.c.

◆ NUMERIC_SHORT_DSCALE_MASK

#define NUMERIC_SHORT_DSCALE_MASK   0x1F80

Definition at line 214 of file numeric.c.

◆ NUMERIC_SHORT_DSCALE_MAX

#define NUMERIC_SHORT_DSCALE_MAX    (NUMERIC_SHORT_DSCALE_MASK >> NUMERIC_SHORT_DSCALE_SHIFT)

Definition at line 216 of file numeric.c.

◆ NUMERIC_SHORT_DSCALE_SHIFT

#define NUMERIC_SHORT_DSCALE_SHIFT   7

Definition at line 215 of file numeric.c.

◆ NUMERIC_SHORT_SIGN_MASK

#define NUMERIC_SHORT_SIGN_MASK   0x2000

Definition at line 213 of file numeric.c.

◆ NUMERIC_SHORT_WEIGHT_MASK

#define NUMERIC_SHORT_WEIGHT_MASK   0x003F

Definition at line 219 of file numeric.c.

◆ NUMERIC_SHORT_WEIGHT_MAX

#define NUMERIC_SHORT_WEIGHT_MAX   NUMERIC_SHORT_WEIGHT_MASK

Definition at line 220 of file numeric.c.

◆ NUMERIC_SHORT_WEIGHT_MIN

#define NUMERIC_SHORT_WEIGHT_MIN   (-(NUMERIC_SHORT_WEIGHT_MASK+1))

Definition at line 221 of file numeric.c.

◆ NUMERIC_SHORT_WEIGHT_SIGN_MASK

#define NUMERIC_SHORT_WEIGHT_SIGN_MASK   0x0040

Definition at line 218 of file numeric.c.

◆ NUMERIC_SIGN

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

Definition at line 236 of file numeric.c.

◆ NUMERIC_SIGN_MASK

#define NUMERIC_SIGN_MASK   0xC000

Definition at line 164 of file numeric.c.

◆ NUMERIC_SPECIAL

#define NUMERIC_SPECIAL   0xC000

Definition at line 168 of file numeric.c.

◆ NUMERIC_WEIGHT

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

Definition at line 246 of file numeric.c.

◆ NumericAbbrevGetDatum

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

Definition at line 402 of file numeric.c.

Typedef Documentation

◆ Int8TransTypeData

◆ NumericAggState

◆ NumericDigit

Definition at line 101 of file numeric.c.

◆ NumericSumAccum

◆ NumericVar

typedef struct NumericVar NumericVar

◆ PolyNumAggState

Definition at line 5492 of file numeric.c.

Function Documentation

◆ accum_sum_add()

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

Definition at line 11755 of file numeric.c.

11756 {
11757  int32 *accum_digits;
11758  int i,
11759  val_i;
11760  int val_ndigits;
11761  NumericDigit *val_digits;
11762 
11763  /*
11764  * If we have accumulated too many values since the last carry
11765  * propagation, do it now, to avoid overflowing. (We could allow more
11766  * than NBASE - 1, if we reserved two extra digits, rather than one, for
11767  * carry propagation. But even with NBASE - 1, this needs to be done so
11768  * seldom, that the performance difference is negligible.)
11769  */
11770  if (accum->num_uncarried == NBASE - 1)
11771  accum_sum_carry(accum);
11772 
11773  /*
11774  * Adjust the weight or scale of the old value, so that it can accommodate
11775  * the new value.
11776  */
11777  accum_sum_rescale(accum, val);
11778 
11779  /* */
11780  if (val->sign == NUMERIC_POS)
11781  accum_digits = accum->pos_digits;
11782  else
11783  accum_digits = accum->neg_digits;
11784 
11785  /* copy these values into local vars for speed in loop */
11786  val_ndigits = val->ndigits;
11787  val_digits = val->digits;
11788 
11789  i = accum->weight - val->weight;
11790  for (val_i = 0; val_i < val_ndigits; val_i++)
11791  {
11792  accum_digits[i] += (int32) val_digits[val_i];
11793  i++;
11794  }
11795 
11796  accum->num_uncarried++;
11797 }
static void accum_sum_carry(NumericSumAccum *accum)
Definition: numeric.c:11803
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:11876
signed int int32
Definition: c.h:481
long val
Definition: informix.c:664
int i
Definition: isn.c:73
int32 * pos_digits
Definition: numeric.c:377
int num_uncarried
Definition: numeric.c:375
int32 * neg_digits
Definition: numeric.c:378

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

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

◆ accum_sum_carry()

static void accum_sum_carry ( NumericSumAccum accum)
static

Definition at line 11803 of file numeric.c.

11804 {
11805  int i;
11806  int ndigits;
11807  int32 *dig;
11808  int32 carry;
11809  int32 newdig = 0;
11810 
11811  /*
11812  * If no new values have been added since last carry propagation, nothing
11813  * to do.
11814  */
11815  if (accum->num_uncarried == 0)
11816  return;
11817 
11818  /*
11819  * We maintain that the weight of the accumulator is always one larger
11820  * than needed to hold the current value, before carrying, to make sure
11821  * there is enough space for the possible extra digit when carry is
11822  * propagated. We cannot expand the buffer here, unless we require
11823  * callers of accum_sum_final() to switch to the right memory context.
11824  */
11825  Assert(accum->pos_digits[0] == 0 && accum->neg_digits[0] == 0);
11826 
11827  ndigits = accum->ndigits;
11828 
11829  /* Propagate carry in the positive sum */
11830  dig = accum->pos_digits;
11831  carry = 0;
11832  for (i = ndigits - 1; i >= 0; i--)
11833  {
11834  newdig = dig[i] + carry;
11835  if (newdig >= NBASE)
11836  {
11837  carry = newdig / NBASE;
11838  newdig -= carry * NBASE;
11839  }
11840  else
11841  carry = 0;
11842  dig[i] = newdig;
11843  }
11844  /* Did we use up the digit reserved for carry propagation? */
11845  if (newdig > 0)
11846  accum->have_carry_space = false;
11847 
11848  /* And the same for the negative sum */
11849  dig = accum->neg_digits;
11850  carry = 0;
11851  for (i = ndigits - 1; i >= 0; i--)
11852  {
11853  newdig = dig[i] + carry;
11854  if (newdig >= NBASE)
11855  {
11856  carry = newdig / NBASE;
11857  newdig -= carry * NBASE;
11858  }
11859  else
11860  carry = 0;
11861  dig[i] = newdig;
11862  }
11863  if (newdig > 0)
11864  accum->have_carry_space = false;
11865 
11866  accum->num_uncarried = 0;
11867 }
Assert(fmt[strlen(fmt) - 1] !='\n')
bool have_carry_space
Definition: numeric.c:376

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

Referenced by accum_sum_add(), and accum_sum_final().

◆ accum_sum_combine()

static void accum_sum_combine ( NumericSumAccum accum,
NumericSumAccum accum2 
)
static

Definition at line 12033 of file numeric.c.

12034 {
12035  NumericVar tmp_var;
12036 
12037  init_var(&tmp_var);
12038 
12039  accum_sum_final(accum2, &tmp_var);
12040  accum_sum_add(accum, &tmp_var);
12041 
12042  free_var(&tmp_var);
12043 }
static void accum_sum_final(NumericSumAccum *accum, NumericVar *result)
Definition: numeric.c:11965
static void free_var(NumericVar *var)
Definition: numeric.c:6917
static void accum_sum_add(NumericSumAccum *accum, const NumericVar *val)
Definition: numeric.c:11755
#define init_var(v)
Definition: numeric.c:484

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

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

◆ accum_sum_copy()

static void accum_sum_copy ( NumericSumAccum dst,
NumericSumAccum src 
)
static

Definition at line 12016 of file numeric.c.

12017 {
12018  dst->pos_digits = palloc(src->ndigits * sizeof(int32));
12019  dst->neg_digits = palloc(src->ndigits * sizeof(int32));
12020 
12021  memcpy(dst->pos_digits, src->pos_digits, src->ndigits * sizeof(int32));
12022  memcpy(dst->neg_digits, src->neg_digits, src->ndigits * sizeof(int32));
12023  dst->num_uncarried = src->num_uncarried;
12024  dst->ndigits = src->ndigits;
12025  dst->weight = src->weight;
12026  dst->dscale = src->dscale;
12027 }
void * palloc(Size size)
Definition: mcxt.c:1304

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

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

◆ accum_sum_final()

static void accum_sum_final ( NumericSumAccum accum,
NumericVar result 
)
static

Definition at line 11965 of file numeric.c.

11966 {
11967  int i;
11968  NumericVar pos_var;
11969  NumericVar neg_var;
11970 
11971  if (accum->ndigits == 0)
11972  {
11973  set_var_from_var(&const_zero, result);
11974  return;
11975  }
11976 
11977  /* Perform final carry */
11978  accum_sum_carry(accum);
11979 
11980  /* Create NumericVars representing the positive and negative sums */
11981  init_var(&pos_var);
11982  init_var(&neg_var);
11983 
11984  pos_var.ndigits = neg_var.ndigits = accum->ndigits;
11985  pos_var.weight = neg_var.weight = accum->weight;
11986  pos_var.dscale = neg_var.dscale = accum->dscale;
11987  pos_var.sign = NUMERIC_POS;
11988  neg_var.sign = NUMERIC_NEG;
11989 
11990  pos_var.buf = pos_var.digits = digitbuf_alloc(accum->ndigits);
11991  neg_var.buf = neg_var.digits = digitbuf_alloc(accum->ndigits);
11992 
11993  for (i = 0; i < accum->ndigits; i++)
11994  {
11995  Assert(accum->pos_digits[i] < NBASE);
11996  pos_var.digits[i] = (int16) accum->pos_digits[i];
11997 
11998  Assert(accum->neg_digits[i] < NBASE);
11999  neg_var.digits[i] = (int16) accum->neg_digits[i];
12000  }
12001 
12002  /* And add them together */
12003  add_var(&pos_var, &neg_var, result);
12004 
12005  /* Remove leading/trailing zeroes */
12006  strip_var(result);
12007 }
static void add_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition: numeric.c:8379
#define NUMERIC_NEG
Definition: numeric.c:166
#define digitbuf_alloc(ndigits)
Definition: numeric.c:476
static const NumericVar const_zero
Definition: numeric.c:415
static void set_var_from_var(const NumericVar *value, NumericVar *dest)
Definition: numeric.c:7416
static void strip_var(NumericVar *var)
Definition: numeric.c:11698
int ndigits
Definition: numeric.c:305
NumericDigit * digits
Definition: numeric.c:310
int dscale
Definition: numeric.c:308
int sign
Definition: numeric.c:307
NumericDigit * buf
Definition: numeric.c:309
int weight
Definition: numeric.c:306

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

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

◆ accum_sum_rescale()

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

Definition at line 11876 of file numeric.c.

11877 {
11878  int old_weight = accum->weight;
11879  int old_ndigits = accum->ndigits;
11880  int accum_ndigits;
11881  int accum_weight;
11882  int accum_rscale;
11883  int val_rscale;
11884 
11885  accum_weight = old_weight;
11886  accum_ndigits = old_ndigits;
11887 
11888  /*
11889  * Does the new value have a larger weight? If so, enlarge the buffers,
11890  * and shift the existing value to the new weight, by adding leading
11891  * zeros.
11892  *
11893  * We enforce that the accumulator always has a weight one larger than
11894  * needed for the inputs, so that we have space for an extra digit at the
11895  * final carry-propagation phase, if necessary.
11896  */
11897  if (val->weight >= accum_weight)
11898  {
11899  accum_weight = val->weight + 1;
11900  accum_ndigits = accum_ndigits + (accum_weight - old_weight);
11901  }
11902 
11903  /*
11904  * Even though the new value is small, we might've used up the space
11905  * reserved for the carry digit in the last call to accum_sum_carry(). If
11906  * so, enlarge to make room for another one.
11907  */
11908  else if (!accum->have_carry_space)
11909  {
11910  accum_weight++;
11911  accum_ndigits++;
11912  }
11913 
11914  /* Is the new value wider on the right side? */
11915  accum_rscale = accum_ndigits - accum_weight - 1;
11916  val_rscale = val->ndigits - val->weight - 1;
11917  if (val_rscale > accum_rscale)
11918  accum_ndigits = accum_ndigits + (val_rscale - accum_rscale);
11919 
11920  if (accum_ndigits != old_ndigits ||
11921  accum_weight != old_weight)
11922  {
11923  int32 *new_pos_digits;
11924  int32 *new_neg_digits;
11925  int weightdiff;
11926 
11927  weightdiff = accum_weight - old_weight;
11928 
11929  new_pos_digits = palloc0(accum_ndigits * sizeof(int32));
11930  new_neg_digits = palloc0(accum_ndigits * sizeof(int32));
11931 
11932  if (accum->pos_digits)
11933  {
11934  memcpy(&new_pos_digits[weightdiff], accum->pos_digits,
11935  old_ndigits * sizeof(int32));
11936  pfree(accum->pos_digits);
11937 
11938  memcpy(&new_neg_digits[weightdiff], accum->neg_digits,
11939  old_ndigits * sizeof(int32));
11940  pfree(accum->neg_digits);
11941  }
11942 
11943  accum->pos_digits = new_pos_digits;
11944  accum->neg_digits = new_neg_digits;
11945 
11946  accum->weight = accum_weight;
11947  accum->ndigits = accum_ndigits;
11948 
11949  Assert(accum->pos_digits[0] == 0 && accum->neg_digits[0] == 0);
11950  accum->have_carry_space = true;
11951  }
11952 
11953  if (val->dscale > accum->dscale)
11954  accum->dscale = val->dscale;
11955 }
void pfree(void *pointer)
Definition: mcxt.c:1508
void * palloc0(Size size)
Definition: mcxt.c:1334

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

Referenced by accum_sum_add().

◆ accum_sum_reset()

static void accum_sum_reset ( NumericSumAccum accum)
static

Definition at line 11739 of file numeric.c.

11740 {
11741  int i;
11742 
11743  accum->dscale = 0;
11744  for (i = 0; i < accum->ndigits; i++)
11745  {
11746  accum->pos_digits[i] = 0;
11747  accum->neg_digits[i] = 0;
11748  }
11749 }

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

11364 {
11365  NumericDigit *res_buf;
11366  NumericDigit *res_digits;
11367  int res_ndigits;
11368  int res_weight;
11369  int res_rscale,
11370  rscale1,
11371  rscale2;
11372  int res_dscale;
11373  int i,
11374  i1,
11375  i2;
11376  int carry = 0;
11377 
11378  /* copy these values into local vars for speed in inner loop */
11379  int var1ndigits = var1->ndigits;
11380  int var2ndigits = var2->ndigits;
11381  NumericDigit *var1digits = var1->digits;
11382  NumericDigit *var2digits = var2->digits;
11383 
11384  res_weight = Max(var1->weight, var2->weight) + 1;
11385 
11386  res_dscale = Max(var1->dscale, var2->dscale);
11387 
11388  /* Note: here we are figuring rscale in base-NBASE digits */
11389  rscale1 = var1->ndigits - var1->weight - 1;
11390  rscale2 = var2->ndigits - var2->weight - 1;
11391  res_rscale = Max(rscale1, rscale2);
11392 
11393  res_ndigits = res_rscale + res_weight + 1;
11394  if (res_ndigits <= 0)
11395  res_ndigits = 1;
11396 
11397  res_buf = digitbuf_alloc(res_ndigits + 1);
11398  res_buf[0] = 0; /* spare digit for later rounding */
11399  res_digits = res_buf + 1;
11400 
11401  i1 = res_rscale + var1->weight + 1;
11402  i2 = res_rscale + var2->weight + 1;
11403  for (i = res_ndigits - 1; i >= 0; i--)
11404  {
11405  i1--;
11406  i2--;
11407  if (i1 >= 0 && i1 < var1ndigits)
11408  carry += var1digits[i1];
11409  if (i2 >= 0 && i2 < var2ndigits)
11410  carry += var2digits[i2];
11411 
11412  if (carry >= NBASE)
11413  {
11414  res_digits[i] = carry - NBASE;
11415  carry = 1;
11416  }
11417  else
11418  {
11419  res_digits[i] = carry;
11420  carry = 0;
11421  }
11422  }
11423 
11424  Assert(carry == 0); /* else we failed to allow for carry out */
11425 
11426  digitbuf_free(result->buf);
11427  result->ndigits = res_ndigits;
11428  result->buf = res_buf;
11429  result->digits = res_digits;
11430  result->weight = res_weight;
11431  result->dscale = res_dscale;
11432 
11433  /* Remove leading/trailing zeroes */
11434  strip_var(result);
11435 }
#define digitbuf_free(buf)
Definition: numeric.c:478
#define Max(x, y)
Definition: numeric.c:13

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

Referenced by add_var(), and sub_var().

◆ add_var()

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

Definition at line 8379 of file numeric.c.

8380 {
8381  /*
8382  * Decide on the signs of the two variables what to do
8383  */
8384  if (var1->sign == NUMERIC_POS)
8385  {
8386  if (var2->sign == NUMERIC_POS)
8387  {
8388  /*
8389  * Both are positive result = +(ABS(var1) + ABS(var2))
8390  */
8391  add_abs(var1, var2, result);
8392  result->sign = NUMERIC_POS;
8393  }
8394  else
8395  {
8396  /*
8397  * var1 is positive, var2 is negative Must compare absolute values
8398  */
8399  switch (cmp_abs(var1, var2))
8400  {
8401  case 0:
8402  /* ----------
8403  * ABS(var1) == ABS(var2)
8404  * result = ZERO
8405  * ----------
8406  */
8407  zero_var(result);
8408  result->dscale = Max(var1->dscale, var2->dscale);
8409  break;
8410 
8411  case 1:
8412  /* ----------
8413  * ABS(var1) > ABS(var2)
8414  * result = +(ABS(var1) - ABS(var2))
8415  * ----------
8416  */
8417  sub_abs(var1, var2, result);
8418  result->sign = NUMERIC_POS;
8419  break;
8420 
8421  case -1:
8422  /* ----------
8423  * ABS(var1) < ABS(var2)
8424  * result = -(ABS(var2) - ABS(var1))
8425  * ----------
8426  */
8427  sub_abs(var2, var1, result);
8428  result->sign = NUMERIC_NEG;
8429  break;
8430  }
8431  }
8432  }
8433  else
8434  {
8435  if (var2->sign == NUMERIC_POS)
8436  {
8437  /* ----------
8438  * var1 is negative, var2 is positive
8439  * Must compare absolute values
8440  * ----------
8441  */
8442  switch (cmp_abs(var1, var2))
8443  {
8444  case 0:
8445  /* ----------
8446  * ABS(var1) == ABS(var2)
8447  * result = ZERO
8448  * ----------
8449  */
8450  zero_var(result);
8451  result->dscale = Max(var1->dscale, var2->dscale);
8452  break;
8453 
8454  case 1:
8455  /* ----------
8456  * ABS(var1) > ABS(var2)
8457  * result = -(ABS(var1) - ABS(var2))
8458  * ----------
8459  */
8460  sub_abs(var1, var2, result);
8461  result->sign = NUMERIC_NEG;
8462  break;
8463 
8464  case -1:
8465  /* ----------
8466  * ABS(var1) < ABS(var2)
8467  * result = +(ABS(var2) - ABS(var1))
8468  * ----------
8469  */
8470  sub_abs(var2, var1, result);
8471  result->sign = NUMERIC_POS;
8472  break;
8473  }
8474  }
8475  else
8476  {
8477  /* ----------
8478  * Both are negative
8479  * result = -(ABS(var1) + ABS(var2))
8480  * ----------
8481  */
8482  add_abs(var1, var2, result);
8483  result->sign = NUMERIC_NEG;
8484  }
8485  }
8486 }
static void sub_abs(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition: numeric.c:11448
static void add_abs(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition: numeric.c:11363
static void zero_var(NumericVar *var)
Definition: numeric.c:6933
static int cmp_abs(const NumericVar *var1, const NumericVar *var2)
Definition: numeric.c:11285

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

6902 {
6903  digitbuf_free(var->buf);
6904  var->buf = digitbuf_alloc(ndigits + 1);
6905  var->buf[0] = 0; /* spare digit for rounding */
6906  var->digits = var->buf + 1;
6907  var->ndigits = ndigits;
6908 }

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

Referenced by div_var(), div_var_fast(), int64_to_numericvar(), mul_var(), numeric_recv(), numericvar_deserialize(), 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 7855 of file numeric.c.

7856 {
7857  int precision;
7858  int scale;
7859  int maxdigits;
7860  int ddigits;
7861  int i;
7862 
7863  /* Do nothing if we have an invalid typmod */
7864  if (!is_valid_numeric_typmod(typmod))
7865  return true;
7866 
7867  precision = numeric_typmod_precision(typmod);
7868  scale = numeric_typmod_scale(typmod);
7869  maxdigits = precision - scale;
7870 
7871  /* Round to target scale (and set var->dscale) */
7872  round_var(var, scale);
7873 
7874  /* but don't allow var->dscale to be negative */
7875  if (var->dscale < 0)
7876  var->dscale = 0;
7877 
7878  /*
7879  * Check for overflow - note we can't do this before rounding, because
7880  * rounding could raise the weight. Also note that the var's weight could
7881  * be inflated by leading zeroes, which will be stripped before storage
7882  * but perhaps might not have been yet. In any case, we must recognize a
7883  * true zero, whose weight doesn't mean anything.
7884  */
7885  ddigits = (var->weight + 1) * DEC_DIGITS;
7886  if (ddigits > maxdigits)
7887  {
7888  /* Determine true weight; and check for all-zero result */
7889  for (i = 0; i < var->ndigits; i++)
7890  {
7891  NumericDigit dig = var->digits[i];
7892 
7893  if (dig)
7894  {
7895  /* Adjust for any high-order decimal zero digits */
7896 #if DEC_DIGITS == 4
7897  if (dig < 10)
7898  ddigits -= 3;
7899  else if (dig < 100)
7900  ddigits -= 2;
7901  else if (dig < 1000)
7902  ddigits -= 1;
7903 #elif DEC_DIGITS == 2
7904  if (dig < 10)
7905  ddigits -= 1;
7906 #elif DEC_DIGITS == 1
7907  /* no adjustment */
7908 #else
7909 #error unsupported NBASE
7910 #endif
7911  if (ddigits > maxdigits)
7912  ereturn(escontext, false,
7913  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
7914  errmsg("numeric field overflow"),
7915  errdetail("A field with precision %d, scale %d must round to an absolute value less than %s%d.",
7916  precision, scale,
7917  /* Display 10^0 as 1 */
7918  maxdigits ? "10^" : "",
7919  maxdigits ? maxdigits : 1
7920  )));
7921  break;
7922  }
7923  ddigits -= DEC_DIGITS;
7924  }
7925  }
7926 
7927  return true;
7928 }
static bool is_valid_numeric_typmod(int32 typmod)
Definition: numeric.c:905
static int numeric_typmod_scale(int32 typmod)
Definition: numeric.c:931
static int numeric_typmod_precision(int32 typmod)
Definition: numeric.c:916
static void round_var(NumericVar *var, int rscale)
Definition: numeric.c:11530
#define DEC_DIGITS
Definition: numeric.c:97
int errdetail(const char *fmt,...)
Definition: elog.c:1205
int errcode(int sqlerrcode)
Definition: elog.c:859
int errmsg(const char *fmt,...)
Definition: elog.c:1072
#define ereturn(context, dummy_value,...)
Definition: elog.h:276
int maxdigits
Definition: informix.c:665

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

7941 {
7942  int precision;
7943  int scale;
7944 
7945  Assert(NUMERIC_IS_SPECIAL(num)); /* caller error if not */
7946 
7947  /*
7948  * NaN is allowed regardless of the typmod; that's rather dubious perhaps,
7949  * but it's a longstanding behavior. Inf is rejected if we have any
7950  * typmod restriction, since an infinity shouldn't be claimed to fit in
7951  * any finite number of digits.
7952  */
7953  if (NUMERIC_IS_NAN(num))
7954  return true;
7955 
7956  /* Do nothing if we have a default typmod (-1) */
7957  if (!is_valid_numeric_typmod(typmod))
7958  return true;
7959 
7960  precision = numeric_typmod_precision(typmod);
7961  scale = numeric_typmod_scale(typmod);
7962 
7963  ereturn(escontext, false,
7964  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
7965  errmsg("numeric field overflow"),
7966  errdetail("A field with precision %d, scale %d cannot hold an infinite value.",
7967  precision, scale)));
7968 }
#define NUMERIC_IS_NAN(n)
Definition: numeric.c:203

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

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

◆ ceil_var()

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

Definition at line 9893 of file numeric.c.

9894 {
9895  NumericVar tmp;
9896 
9897  init_var(&tmp);
9898  set_var_from_var(var, &tmp);
9899 
9900  trunc_var(&tmp, 0);
9901 
9902  if (var->sign == NUMERIC_POS && cmp_var(var, &tmp) != 0)
9903  add_var(&tmp, &const_one, &tmp);
9904 
9905  set_var_from_var(&tmp, result);
9906  free_var(&tmp);
9907 }
static void trunc_var(NumericVar *var, int rscale)
Definition: numeric.c:11636
static int cmp_var(const NumericVar *var1, const NumericVar *var2)
Definition: numeric.c:8321
static const NumericVar const_one
Definition: numeric.c:419

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

Referenced by numeric_ceil().

◆ cmp_abs()

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

Definition at line 11285 of file numeric.c.

11286 {
11287  return cmp_abs_common(var1->digits, var1->ndigits, var1->weight,
11288  var2->digits, var2->ndigits, var2->weight);
11289 }
static int cmp_abs_common(const NumericDigit *var1digits, int var1ndigits, int var1weight, const NumericDigit *var2digits, int var2ndigits, int var2weight)
Definition: numeric.c:11299

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

11301 {
11302  int i1 = 0;
11303  int i2 = 0;
11304 
11305  /* Check any digits before the first common digit */
11306 
11307  while (var1weight > var2weight && i1 < var1ndigits)
11308  {
11309  if (var1digits[i1++] != 0)
11310  return 1;
11311  var1weight--;
11312  }
11313  while (var2weight > var1weight && i2 < var2ndigits)
11314  {
11315  if (var2digits[i2++] != 0)
11316  return -1;
11317  var2weight--;
11318  }
11319 
11320  /* At this point, either w1 == w2 or we've run out of digits */
11321 
11322  if (var1weight == var2weight)
11323  {
11324  while (i1 < var1ndigits && i2 < var2ndigits)
11325  {
11326  int stat = var1digits[i1++] - var2digits[i2++];
11327 
11328  if (stat)
11329  {
11330  if (stat > 0)
11331  return 1;
11332  return -1;
11333  }
11334  }
11335  }
11336 
11337  /*
11338  * At this point, we've run out of digits on one side or the other; so any
11339  * remaining nonzero digits imply that side is larger
11340  */
11341  while (i1 < var1ndigits)
11342  {
11343  if (var1digits[i1++] != 0)
11344  return 1;
11345  }
11346  while (i2 < var2ndigits)
11347  {
11348  if (var2digits[i2++] != 0)
11349  return -1;
11350  }
11351 
11352  return 0;
11353 }

Referenced by cmp_abs(), and cmp_var_common().

◆ cmp_numerics()

static int cmp_numerics ( Numeric  num1,
Numeric  num2 
)
static

Definition at line 2503 of file numeric.c.

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

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

8340 {
8341  if (var1ndigits == 0)
8342  {
8343  if (var2ndigits == 0)
8344  return 0;
8345  if (var2sign == NUMERIC_NEG)
8346  return 1;
8347  return -1;
8348  }
8349  if (var2ndigits == 0)
8350  {
8351  if (var1sign == NUMERIC_POS)
8352  return 1;
8353  return -1;
8354  }
8355 
8356  if (var1sign == NUMERIC_POS)
8357  {
8358  if (var2sign == NUMERIC_NEG)
8359  return 1;
8360  return cmp_abs_common(var1digits, var1ndigits, var1weight,
8361  var2digits, var2ndigits, var2weight);
8362  }
8363 
8364  if (var2sign == NUMERIC_POS)
8365  return -1;
8366 
8367  return cmp_abs_common(var2digits, var2ndigits, var2weight,
8368  var1digits, var1ndigits, var1weight);
8369 }

References cmp_abs_common(), NUMERIC_NEG, and NUMERIC_POS.

Referenced by cmp_numerics(), and cmp_var().

◆ compute_bucket()

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

Definition at line 1915 of file numeric.c.

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

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

Referenced by width_bucket_numeric().

◆ div_mod_var()

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

Definition at line 9823 of file numeric.c.

9825 {
9826  NumericVar q;
9827  NumericVar r;
9828 
9829  init_var(&q);
9830  init_var(&r);
9831 
9832  /*
9833  * Use div_var_fast() to get an initial estimate for the integer quotient.
9834  * This might be inaccurate (per the warning in div_var_fast's comments),
9835  * but we can correct it below.
9836  */
9837  div_var_fast(var1, var2, &q, 0, false);
9838 
9839  /* Compute initial estimate of remainder using the quotient estimate. */
9840  mul_var(var2, &q, &r, var2->dscale);
9841  sub_var(var1, &r, &r);
9842 
9843  /*
9844  * Adjust the results if necessary --- the remainder should have the same
9845  * sign as var1, and its absolute value should be less than the absolute
9846  * value of var2.
9847  */
9848  while (r.ndigits != 0 && r.sign != var1->sign)
9849  {
9850  /* The absolute value of the quotient is too large */
9851  if (var1->sign == var2->sign)
9852  {
9853  sub_var(&q, &const_one, &q);
9854  add_var(&r, var2, &r);
9855  }
9856  else
9857  {
9858  add_var(&q, &const_one, &q);
9859  sub_var(&r, var2, &r);
9860  }
9861  }
9862 
9863  while (cmp_abs(&r, var2) >= 0)
9864  {
9865  /* The absolute value of the quotient is too small */
9866  if (var1->sign == var2->sign)
9867  {
9868  add_var(&q, &const_one, &q);
9869  sub_var(&r, var2, &r);
9870  }
9871  else
9872  {
9873  sub_var(&q, &const_one, &q);
9874  add_var(&r, var2, &r);
9875  }
9876  }
9877 
9878  set_var_from_var(&q, quot);
9879  set_var_from_var(&r, rem);
9880 
9881  free_var(&q);
9882  free_var(&r);
9883 }
static void div_var_fast(const NumericVar *var1, const NumericVar *var2, NumericVar *result, int rscale, bool round)
Definition: numeric.c:9133

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

Referenced by sqrt_var().

◆ div_var()

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

Definition at line 8825 of file numeric.c.

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

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

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

◆ div_var_fast()

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

Definition at line 9133 of file numeric.c.

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

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

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

◆ div_var_int()

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

Definition at line 9497 of file numeric.c.

9499 {
9500  NumericDigit *var_digits = var->digits;
9501  int var_ndigits = var->ndigits;
9502  int res_sign;
9503  int res_weight;
9504  int res_ndigits;
9505  NumericDigit *res_buf;
9506  NumericDigit *res_digits;
9507  uint32 divisor;
9508  int i;
9509 
9510  /* Guard against division by zero */
9511  if (ival == 0)
9512  ereport(ERROR,
9513  errcode(ERRCODE_DIVISION_BY_ZERO),
9514  errmsg("division by zero"));
9515 
9516  /* Result zero check */
9517  if (var_ndigits == 0)
9518  {
9519  zero_var(result);
9520  result->dscale = rscale;
9521  return;
9522  }
9523 
9524  /*
9525  * Determine the result sign, weight and number of digits to calculate.
9526  * The weight figured here is correct if the emitted quotient has no
9527  * leading zero digits; otherwise strip_var() will fix things up.
9528  */
9529  if (var->sign == NUMERIC_POS)
9530  res_sign = ival > 0 ? NUMERIC_POS : NUMERIC_NEG;
9531  else
9532  res_sign = ival > 0 ? NUMERIC_NEG : NUMERIC_POS;
9533  res_weight = var->weight - ival_weight;
9534  /* The number of accurate result digits we need to produce: */
9535  res_ndigits = res_weight + 1 + (rscale + DEC_DIGITS - 1) / DEC_DIGITS;
9536  /* ... but always at least 1 */
9537  res_ndigits = Max(res_ndigits, 1);
9538  /* If rounding needed, figure one more digit to ensure correct result */
9539  if (round)
9540  res_ndigits++;
9541 
9542  res_buf = digitbuf_alloc(res_ndigits + 1);
9543  res_buf[0] = 0; /* spare digit for later rounding */
9544  res_digits = res_buf + 1;
9545 
9546  /*
9547  * Now compute the quotient digits. This is the short division algorithm
9548  * described in Knuth volume 2, section 4.3.1 exercise 16, except that we
9549  * allow the divisor to exceed the internal base.
9550  *
9551  * In this algorithm, the carry from one digit to the next is at most
9552  * divisor - 1. Therefore, while processing the next digit, carry may
9553  * become as large as divisor * NBASE - 1, and so it requires a 64-bit
9554  * integer if this exceeds UINT_MAX.
9555  */
9556  divisor = abs(ival);
9557 
9558  if (divisor <= UINT_MAX / NBASE)
9559  {
9560  /* carry cannot overflow 32 bits */
9561  uint32 carry = 0;
9562 
9563  for (i = 0; i < res_ndigits; i++)
9564  {
9565  carry = carry * NBASE + (i < var_ndigits ? var_digits[i] : 0);
9566  res_digits[i] = (NumericDigit) (carry / divisor);
9567  carry = carry % divisor;
9568  }
9569  }
9570  else
9571  {
9572  /* carry may exceed 32 bits */
9573  uint64 carry = 0;
9574 
9575  for (i = 0; i < res_ndigits; i++)
9576  {
9577  carry = carry * NBASE + (i < var_ndigits ? var_digits[i] : 0);
9578  res_digits[i] = (NumericDigit) (carry / divisor);
9579  carry = carry % divisor;
9580  }
9581  }
9582 
9583  /* Store the quotient in result */
9584  digitbuf_free(result->buf);
9585  result->ndigits = res_ndigits;
9586  result->buf = res_buf;
9587  result->digits = res_digits;
9588  result->weight = res_weight;
9589  result->sign = res_sign;
9590 
9591  /* Round or truncate to target rscale (and set result->dscale) */
9592  if (round)
9593  round_var(result, rscale);
9594  else
9595  trunc_var(result, rscale);
9596 
9597  /* Strip leading/trailing zeroes */
9598  strip_var(result);
9599 }
unsigned int uint32
Definition: c.h:493

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

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

◆ do_numeric_accum()

static void do_numeric_accum ( NumericAggState state,
Numeric  newval 
)
static

Definition at line 4805 of file numeric.c.

4806 {
4807  NumericVar X;
4808  NumericVar X2;
4809  MemoryContext old_context;
4810 
4811  /* Count NaN/infinity inputs separately from all else */
4813  {
4814  if (NUMERIC_IS_PINF(newval))
4815  state->pInfcount++;
4816  else if (NUMERIC_IS_NINF(newval))
4817  state->nInfcount++;
4818  else
4819  state->NaNcount++;
4820  return;
4821  }
4822 
4823  /* load processed number in short-lived context */
4825 
4826  /*
4827  * Track the highest input dscale that we've seen, to support inverse
4828  * transitions (see do_numeric_discard).
4829  */
4830  if (X.dscale > state->maxScale)
4831  {
4832  state->maxScale = X.dscale;
4833  state->maxScaleCount = 1;
4834  }
4835  else if (X.dscale == state->maxScale)
4836  state->maxScaleCount++;
4837 
4838  /* if we need X^2, calculate that in short-lived context */
4839  if (state->calcSumX2)
4840  {
4841  init_var(&X2);
4842  mul_var(&X, &X, &X2, X.dscale * 2);
4843  }
4844 
4845  /* The rest of this needs to work in the aggregate context */
4846  old_context = MemoryContextSwitchTo(state->agg_context);
4847 
4848  state->N++;
4849 
4850  /* Accumulate sums */
4851  accum_sum_add(&(state->sumX), &X);
4852 
4853  if (state->calcSumX2)
4854  accum_sum_add(&(state->sumX2), &X2);
4855 
4856  MemoryContextSwitchTo(old_context);
4857 }
#define newval
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:124
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 4875 of file numeric.c.

4876 {
4877  NumericVar X;
4878  NumericVar X2;
4879  MemoryContext old_context;
4880 
4881  /* Count NaN/infinity inputs separately from all else */
4883  {
4884  if (NUMERIC_IS_PINF(newval))
4885  state->pInfcount--;
4886  else if (NUMERIC_IS_NINF(newval))
4887  state->nInfcount--;
4888  else
4889  state->NaNcount--;
4890  return true;
4891  }
4892 
4893  /* load processed number in short-lived context */
4895 
4896  /*
4897  * state->sumX's dscale is the maximum dscale of any of the inputs.
4898  * Removing the last input with that dscale would require us to recompute
4899  * the maximum dscale of the *remaining* inputs, which we cannot do unless
4900  * no more non-NaN inputs remain at all. So we report a failure instead,
4901  * and force the aggregation to be redone from scratch.
4902  */
4903  if (X.dscale == state->maxScale)
4904  {
4905  if (state->maxScaleCount > 1 || state->maxScale == 0)
4906  {
4907  /*
4908  * Some remaining inputs have same dscale, or dscale hasn't gotten
4909  * above zero anyway
4910  */
4911  state->maxScaleCount--;
4912  }
4913  else if (state->N == 1)
4914  {
4915  /* No remaining non-NaN inputs at all, so reset maxScale */
4916  state->maxScale = 0;
4917  state->maxScaleCount = 0;
4918  }
4919  else
4920  {
4921  /* Correct new maxScale is uncertain, must fail */
4922  return false;
4923  }
4924  }
4925 
4926  /* if we need X^2, calculate that in short-lived context */
4927  if (state->calcSumX2)
4928  {
4929  init_var(&X2);
4930  mul_var(&X, &X, &X2, X.dscale * 2);
4931  }
4932 
4933  /* The rest of this needs to work in the aggregate context */
4934  old_context = MemoryContextSwitchTo(state->agg_context);
4935 
4936  if (state->N-- > 1)
4937  {
4938  /* Negate X, to subtract it from the sum */
4939  X.sign = (X.sign == NUMERIC_POS ? NUMERIC_NEG : NUMERIC_POS);
4940  accum_sum_add(&(state->sumX), &X);
4941 
4942  if (state->calcSumX2)
4943  {
4944  /* Negate X^2. X^2 is always positive */
4945  X2.sign = NUMERIC_NEG;
4946  accum_sum_add(&(state->sumX2), &X2);
4947  }
4948  }
4949  else
4950  {
4951  /* Zero the sums */
4952  Assert(state->N == 0);
4953 
4954  accum_sum_reset(&state->sumX);
4955  if (state->calcSumX2)
4956  accum_sum_reset(&state->sumX2);
4957  }
4958 
4959  MemoryContextSwitchTo(old_context);
4960 
4961  return true;
4962 }
static void accum_sum_reset(NumericSumAccum *accum)
Definition: numeric.c:11739

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

7712 {
7713  Numeric res;
7714 
7715  res = (Numeric) palloc(VARSIZE(num));
7716  memcpy(res, num, VARSIZE(num));
7717  return res;
7718 }
struct NumericData * Numeric
Definition: numeric.h:53
#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 10619 of file numeric.c.

10620 {
10621  int ln_dweight;
10622 
10623  /* Caller should fail on ln(negative), but for the moment return zero */
10624  if (var->sign != NUMERIC_POS)
10625  return 0;
10626 
10627  if (cmp_var(var, &const_zero_point_nine) >= 0 &&
10628  cmp_var(var, &const_one_point_one) <= 0)
10629  {
10630  /*
10631  * 0.9 <= var <= 1.1
10632  *
10633  * ln(var) has a negative weight (possibly very large). To get a
10634  * reasonably accurate result, estimate it using ln(1+x) ~= x.
10635  */
10636  NumericVar x;
10637 
10638  init_var(&x);
10639  sub_var(var, &const_one, &x);
10640 
10641  if (x.ndigits > 0)
10642  {
10643  /* Use weight of most significant decimal digit of x */
10644  ln_dweight = x.weight * DEC_DIGITS + (int) log10(x.digits[0]);
10645  }
10646  else
10647  {
10648  /* x = 0. Since ln(1) = 0 exactly, we don't need extra digits */
10649  ln_dweight = 0;
10650  }
10651 
10652  free_var(&x);
10653  }
10654  else
10655  {
10656  /*
10657  * Estimate the logarithm using the first couple of digits from the
10658  * input number. This will give an accurate result whenever the input
10659  * is not too close to 1.
10660  */
10661  if (var->ndigits > 0)
10662  {
10663  int digits;
10664  int dweight;
10665  double ln_var;
10666 
10667  digits = var->digits[0];
10668  dweight = var->weight * DEC_DIGITS;
10669 
10670  if (var->ndigits > 1)
10671  {
10672  digits = digits * NBASE + var->digits[1];
10673  dweight -= DEC_DIGITS;
10674  }
10675 
10676  /*----------
10677  * We have var ~= digits * 10^dweight
10678  * so ln(var) ~= ln(digits) + dweight * ln(10)
10679  *----------
10680  */
10681  ln_var = log((double) digits) + dweight * 2.302585092994046;
10682  ln_dweight = (int) log10(fabs(ln_var));
10683  }
10684  else
10685  {
10686  /* Caller should fail on ln(0), but for the moment return zero */
10687  ln_dweight = 0;
10688  }
10689  }
10690 
10691  return ln_dweight;
10692 }
static const NumericVar const_zero_point_nine
Definition: numeric.c:436
static const NumericVar const_one_point_one
Definition: numeric.c:446
static void ln_var(const NumericVar *arg, NumericVar *result, int rscale)
Definition: numeric.c:10701
int digits
Definition: informix.c:666
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 10490 of file numeric.c.

10491 {
10492  NumericVar x;
10493  NumericVar elem;
10494  int ni;
10495  double val;
10496  int dweight;
10497  int ndiv2;
10498  int sig_digits;
10499  int local_rscale;
10500 
10501  init_var(&x);
10502  init_var(&elem);
10503 
10504  set_var_from_var(arg, &x);
10505 
10506  /*
10507  * Estimate the dweight of the result using floating point arithmetic, so
10508  * that we can choose an appropriate local rscale for the calculation.
10509  */
10511 
10512  /* Guard against overflow/underflow */
10513  /* If you change this limit, see also power_var()'s limit */
10514  if (fabs(val) >= NUMERIC_MAX_RESULT_SCALE * 3)
10515  {
10516  if (val > 0)
10517  ereport(ERROR,
10518  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
10519  errmsg("value overflows numeric format")));
10520  zero_var(result);
10521  result->dscale = rscale;
10522  return;
10523  }
10524 
10525  /* decimal weight = log10(e^x) = x * log10(e) */
10526  dweight = (int) (val * 0.434294481903252);
10527 
10528  /*
10529  * Reduce x to the range -0.01 <= x <= 0.01 (approximately) by dividing by
10530  * 2^ndiv2, to improve the convergence rate of the Taylor series.
10531  *
10532  * Note that the overflow check above ensures that fabs(x) < 6000, which
10533  * means that ndiv2 <= 20 here.
10534  */
10535  if (fabs(val) > 0.01)
10536  {
10537  ndiv2 = 1;
10538  val /= 2;
10539 
10540  while (fabs(val) > 0.01)
10541  {
10542  ndiv2++;
10543  val /= 2;
10544  }
10545 
10546  local_rscale = x.dscale + ndiv2;
10547  div_var_int(&x, 1 << ndiv2, 0, &x, local_rscale, true);
10548  }
10549  else
10550  ndiv2 = 0;
10551 
10552  /*
10553  * Set the scale for the Taylor series expansion. The final result has
10554  * (dweight + rscale + 1) significant digits. In addition, we have to
10555  * raise the Taylor series result to the power 2^ndiv2, which introduces
10556  * an error of up to around log10(2^ndiv2) digits, so work with this many
10557  * extra digits of precision (plus a few more for good measure).
10558  */
10559  sig_digits = 1 + dweight + rscale + (int) (ndiv2 * 0.301029995663981);
10560  sig_digits = Max(sig_digits, 0) + 8;
10561 
10562  local_rscale = sig_digits - 1;
10563 
10564  /*
10565  * Use the Taylor series
10566  *
10567  * exp(x) = 1 + x + x^2/2! + x^3/3! + ...
10568  *
10569  * Given the limited range of x, this should converge reasonably quickly.
10570  * We run the series until the terms fall below the local_rscale limit.
10571  */
10572  add_var(&const_one, &x, result);
10573 
10574  mul_var(&x, &x, &elem, local_rscale);
10575  ni = 2;
10576  div_var_int(&elem, ni, 0, &elem, local_rscale, true);
10577 
10578  while (elem.ndigits != 0)
10579  {
10580  add_var(result, &elem, result);
10581 
10582  mul_var(&elem, &x, &elem, local_rscale);
10583  ni++;
10584  div_var_int(&elem, ni, 0, &elem, local_rscale, true);
10585  }
10586 
10587  /*
10588  * Compensate for the argument range reduction. Since the weight of the
10589  * result doubles with each multiplication, we can reduce the local rscale
10590  * as we proceed.
10591  */
10592  while (ndiv2-- > 0)
10593  {
10594  local_rscale = sig_digits - result->weight * 2 * DEC_DIGITS;
10595  local_rscale = Max(local_rscale, NUMERIC_MIN_DISPLAY_SCALE);
10596  mul_var(result, result, result, local_rscale);
10597  }
10598 
10599  /* Round to requested rscale */
10600  round_var(result, rscale);
10601 
10602  free_var(&x);
10603  free_var(&elem);
10604 }
static double numericvar_to_double_no_overflow(const NumericVar *var)
Definition: numeric.c:8289
#define NUMERIC_MAX_RESULT_SCALE
Definition: numeric.h:42
#define NUMERIC_MIN_DISPLAY_SCALE
Definition: numeric.h:40
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 4635 of file numeric.c.

4636 {
4638  Numeric res;
4639  NumericVar result;
4640  char buf[FLT_DIG + 100];
4641  const char *endptr;
4642 
4643  if (isnan(val))
4645 
4646  if (isinf(val))
4647  {
4648  if (val < 0)
4650  else
4652  }
4653 
4654  snprintf(buf, sizeof(buf), "%.*g", FLT_DIG, val);
4655 
4656  init_var(&result);
4657 
4658  /* Assume we need not worry about leading/trailing spaces */
4659  (void) set_var_from_str(buf, buf, &result, &endptr, NULL);
4660 
4661  res = make_result(&result);
4662 
4663  free_var(&result);
4664 
4666 }
static const NumericVar const_pinf
Definition: numeric.c:452
static const NumericVar const_ninf
Definition: numeric.c:455
static bool set_var_from_str(const char *str, const char *cp, NumericVar *dest, const char **endptr, Node *escontext)
Definition: numeric.c:6960
static Numeric make_result(const NumericVar *var)
Definition: numeric.c:7839
static const NumericVar const_nan
Definition: numeric.c:449
float float4
Definition: c.h:616
#define PG_GETARG_FLOAT4(n)
Definition: fmgr.h:281
#define PG_RETURN_NUMERIC(x)
Definition: numeric.h:79
#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.

◆ float8_numeric()

Datum float8_numeric ( PG_FUNCTION_ARGS  )

Definition at line 4541 of file numeric.c.

4542 {
4544  Numeric res;
4545  NumericVar result;
4546  char buf[DBL_DIG + 100];
4547  const char *endptr;
4548 
4549  if (isnan(val))
4551 
4552  if (isinf(val))
4553  {
4554  if (val < 0)
4556  else
4558  }
4559 
4560  snprintf(buf, sizeof(buf), "%.*g", DBL_DIG, val);
4561 
4562  init_var(&result);
4563 
4564  /* Assume we need not worry about leading/trailing spaces */
4565  (void) set_var_from_str(buf, buf, &result, &endptr, NULL);
4566 
4567  res = make_result(&result);
4568 
4569  free_var(&result);
4570 
4572 }
double float8
Definition: c.h:617
#define PG_GETARG_FLOAT8(n)
Definition: fmgr.h:282

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

Referenced by executeItemOptUnwrapTarget(), and SV_to_JsonbValue().

◆ floor_var()

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

Definition at line 9917 of file numeric.c.

9918 {
9919  NumericVar tmp;
9920 
9921  init_var(&tmp);
9922  set_var_from_var(var, &tmp);
9923 
9924  trunc_var(&tmp, 0);
9925 
9926  if (var->sign == NUMERIC_NEG && cmp_var(var, &tmp) != 0)
9927  sub_var(&tmp, &const_one, &tmp);
9928 
9929  set_var_from_var(&tmp, result);
9930  free_var(&tmp);
9931 }

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

Referenced by compute_bucket(), and numeric_floor().

◆ free_var()

static void free_var ( NumericVar var)
static

Definition at line 6917 of file numeric.c.

6918 {
6919  digitbuf_free(var->buf);
6920  var->buf = NULL;
6921  var->digits = NULL;
6922  var->sign = NUMERIC_NAN;
6923 }
#define NUMERIC_NAN
Definition: numeric.c:197

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

Referenced by accum_sum_combine(), ceil_var(), compute_bucket(), div_mod_var(), estimate_ln_dweight(), exp_var(), float4_numeric(), float8_numeric(), floor_var(), gcd_var(), get_str_from_var_sci(), in_range_numeric_numeric(), int64_div_fast_to_numeric(), int64_to_numeric(), int8_avg_deserialize(), int8_avg_serialize(), ln_var(), log_var(), mod_var(), numeric(), numeric_add_opt_error(), numeric_avg(), numeric_avg_deserialize(), numeric_avg_serialize(), numeric_ceil(), numeric_deserialize(), numeric_div_opt_error(), numeric_div_trunc(), numeric_exp(), numeric_fac(), numeric_floor(), numeric_gcd(), numeric_in(), numeric_inc(), numeric_lcm(), numeric_ln(), numeric_log(), numeric_min_scale(), numeric_mod_opt_error(), numeric_mul_opt_error(), numeric_poly_avg(), numeric_poly_deserialize(), numeric_poly_serialize(), numeric_poly_sum(), numeric_power(), numeric_recv(), numeric_round(), numeric_serialize(), numeric_sqrt(), numeric_stddev_internal(), numeric_sub_opt_error(), numeric_sum(), numeric_trim_scale(), numeric_trunc(), numericvar_to_int64(), numericvar_to_uint64(), power_var(), power_var_int(), 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 9940 of file numeric.c.

9941 {
9942  int res_dscale;
9943  int cmp;
9944  NumericVar tmp_arg;
9945  NumericVar mod;
9946 
9947  res_dscale = Max(var1->dscale, var2->dscale);
9948 
9949  /*
9950  * Arrange for var1 to be the number with the greater absolute value.
9951  *
9952  * This would happen automatically in the loop below, but avoids an
9953  * expensive modulo operation.
9954  */
9955  cmp = cmp_abs(var1, var2);
9956  if (cmp < 0)
9957  {
9958  const NumericVar *tmp = var1;
9959 
9960  var1 = var2;
9961  var2 = tmp;
9962  }
9963 
9964  /*
9965  * Also avoid the taking the modulo if the inputs have the same absolute
9966  * value, or if the smaller input is zero.
9967  */
9968  if (cmp == 0 || var2->ndigits == 0)
9969  {
9970  set_var_from_var(var1, result);
9971  result->sign = NUMERIC_POS;
9972  result->dscale = res_dscale;
9973  return;
9974  }
9975 
9976  init_var(&tmp_arg);
9977  init_var(&mod);
9978 
9979  /* Use the Euclidean algorithm to find the GCD */
9980  set_var_from_var(var1, &tmp_arg);
9981  set_var_from_var(var2, result);
9982 
9983  for (;;)
9984  {
9985  /* this loop can take a while, so allow it to be interrupted */
9987 
9988  mod_var(&tmp_arg, result, &mod);
9989  if (mod.ndigits == 0)
9990  break;
9991  set_var_from_var(result, &tmp_arg);
9992  set_var_from_var(&mod, result);
9993  }
9994  result->sign = NUMERIC_POS;
9995  result->dscale = res_dscale;
9996 
9997  free_var(&tmp_arg);
9998  free_var(&mod);
9999 }
static void mod_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition: numeric.c:9794
#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 1684 of file numeric.c.

1685 {
1686  return generate_series_step_numeric(fcinfo);
1687 }
Datum generate_series_step_numeric(PG_FUNCTION_ARGS)
Definition: numeric.c:1690

References generate_series_step_numeric().

◆ generate_series_step_numeric()

Datum generate_series_step_numeric ( PG_FUNCTION_ARGS  )

Definition at line 1690 of file numeric.c.

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

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

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

7443 {
7444  int dscale;
7445  char *str;
7446  char *cp;
7447  char *endcp;
7448  int i;
7449  int d;
7450  NumericDigit dig;
7451 
7452 #if DEC_DIGITS > 1
7453  NumericDigit d1;
7454 #endif
7455 
7456  dscale = var->dscale;
7457 
7458  /*
7459  * Allocate space for the result.
7460  *
7461  * i is set to the # of decimal digits before decimal point. dscale is the
7462  * # of decimal digits we will print after decimal point. We may generate
7463  * as many as DEC_DIGITS-1 excess digits at the end, and in addition we
7464  * need room for sign, decimal point, null terminator.
7465  */
7466  i = (var->weight + 1) * DEC_DIGITS;
7467  if (i <= 0)
7468  i = 1;
7469 
7470  str = palloc(i + dscale + DEC_DIGITS + 2);
7471  cp = str;
7472 
7473  /*
7474  * Output a dash for negative values
7475  */
7476  if (var->sign == NUMERIC_NEG)
7477  *cp++ = '-';
7478 
7479  /*
7480  * Output all digits before the decimal point
7481  */
7482  if (var->weight < 0)
7483  {
7484  d = var->weight + 1;
7485  *cp++ = '0';
7486  }
7487  else
7488  {
7489  for (d = 0; d <= var->weight; d++)
7490  {
7491  dig = (d < var->ndigits) ? var->digits[d] : 0;
7492  /* In the first digit, suppress extra leading decimal zeroes */
7493 #if DEC_DIGITS == 4
7494  {
7495  bool putit = (d > 0);
7496 
7497  d1 = dig / 1000;
7498  dig -= d1 * 1000;
7499  putit |= (d1 > 0);
7500  if (putit)
7501  *cp++ = d1 + '0';
7502  d1 = dig / 100;
7503  dig -= d1 * 100;
7504  putit |= (d1 > 0);
7505  if (putit)
7506  *cp++ = d1 + '0';
7507  d1 = dig / 10;
7508  dig -= d1 * 10;
7509  putit |= (d1 > 0);
7510  if (putit)
7511  *cp++ = d1 + '0';
7512  *cp++ = dig + '0';
7513  }
7514 #elif DEC_DIGITS == 2
7515  d1 = dig / 10;
7516  dig -= d1 * 10;
7517  if (d1 > 0 || d > 0)
7518  *cp++ = d1 + '0';
7519  *cp++ = dig + '0';
7520 #elif DEC_DIGITS == 1
7521  *cp++ = dig + '0';
7522 #else
7523 #error unsupported NBASE
7524 #endif
7525  }
7526  }
7527 
7528  /*
7529  * If requested, output a decimal point and all the digits that follow it.
7530  * We initially put out a multiple of DEC_DIGITS digits, then truncate if
7531  * needed.
7532  */
7533  if (dscale > 0)
7534  {
7535  *cp++ = '.';
7536  endcp = cp + dscale;
7537  for (i = 0; i < dscale; d++, i += DEC_DIGITS)
7538  {
7539  dig = (d >= 0 && d < var->ndigits) ? var->digits[d] : 0;
7540 #if DEC_DIGITS == 4
7541  d1 = dig / 1000;
7542  dig -= d1 * 1000;
7543  *cp++ = d1 + '0';
7544  d1 = dig / 100;
7545  dig -= d1 * 100;
7546  *cp++ = d1 + '0';
7547  d1 = dig / 10;
7548  dig -= d1 * 10;
7549  *cp++ = d1 + '0';
7550  *cp++ = dig + '0';
7551 #elif DEC_DIGITS == 2
7552  d1 = dig / 10;
7553  dig -= d1 * 10;
7554  *cp++ = d1 + '0';
7555  *cp++ = dig + '0';
7556 #elif DEC_DIGITS == 1
7557  *cp++ = dig + '0';
7558 #else
7559 #error unsupported NBASE
7560 #endif
7561  }
7562  cp = endcp;
7563  }
7564 
7565  /*
7566  * terminate the string and return it
7567  */
7568  *cp = '\0';
7569  return str;
7570 }
static void error(void)
Definition: sql-dyntest.c:147

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

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

◆ get_str_from_var_sci()

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

Definition at line 7595 of file numeric.c.

7596 {
7597  int32 exponent;
7598  NumericVar tmp_var;
7599  size_t len;
7600  char *str;
7601  char *sig_out;
7602 
7603  if (rscale < 0)
7604  rscale = 0;
7605 
7606  /*
7607  * Determine the exponent of this number in normalised form.
7608  *
7609  * This is the exponent required to represent the number with only one
7610  * significant digit before the decimal place.
7611  */
7612  if (var->ndigits > 0)
7613  {
7614  exponent = (var->weight + 1) * DEC_DIGITS;
7615 
7616  /*
7617  * Compensate for leading decimal zeroes in the first numeric digit by
7618  * decrementing the exponent.
7619  */
7620  exponent -= DEC_DIGITS - (int) log10(var->digits[0]);
7621  }
7622  else
7623  {
7624  /*
7625  * If var has no digits, then it must be zero.
7626  *
7627  * Zero doesn't technically have a meaningful exponent in normalised
7628  * notation, but we just display the exponent as zero for consistency
7629  * of output.
7630  */
7631  exponent = 0;
7632  }
7633 
7634  /*
7635  * Divide var by 10^exponent to get the significand, rounding to rscale
7636  * decimal digits in the process.
7637  */
7638  init_var(&tmp_var);
7639 
7640  power_ten_int(exponent, &tmp_var);
7641  div_var(var, &tmp_var, &tmp_var, rscale, true);
7642  sig_out = get_str_from_var(&tmp_var);
7643 
7644  free_var(&tmp_var);
7645 
7646  /*
7647  * Allocate space for the result.
7648  *
7649  * In addition to the significand, we need room for the exponent
7650  * decoration ("e"), the sign of the exponent, up to 10 digits for the
7651  * exponent itself, and of course the null terminator.
7652  */
7653  len = strlen(sig_out) + 13;
7654  str = palloc(len);
7655  snprintf(str, len, "%se%+03d", sig_out, exponent);
7656 
7657  pfree(sig_out);
7658 
7659  return str;
7660 }
static char * get_str_from_var(const NumericVar *var)
Definition: numeric.c:7442
static void power_ten_int(int exp, NumericVar *result)
Definition: numeric.c:11244
const void size_t len

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

Referenced by numeric_out_sci().

◆ hash_numeric()

Datum hash_numeric ( PG_FUNCTION_ARGS  )

Definition at line 2695 of file numeric.c.

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

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

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

5499 {
5501 
5502  state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
5503 
5504  /* Create the state data on the first call */
5505  if (state == NULL)
5506  state = makePolyNumAggState(fcinfo, true);
5507 
5508  if (!PG_ARGISNULL(1))
5509  {
5510 #ifdef HAVE_INT128
5511  do_int128_accum(state, (int128) PG_GETARG_INT16(1));
5512 #else
5514 #endif
5515  }
5516 
5518 }
#define makePolyNumAggState
Definition: numeric.c:5493
Numeric int64_to_numeric(int64 val)
Definition: numeric.c:4231
static void do_numeric_accum(NumericAggState *state, Numeric newval)
Definition: numeric.c:4805
#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 5922 of file numeric.c.

5923 {
5925 
5926  state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
5927 
5928  /* Should not get here with no state */
5929  if (state == NULL)
5930  elog(ERROR, "int2_accum_inv called with NULL state");
5931 
5932  if (!PG_ARGISNULL(1))
5933  {
5934 #ifdef HAVE_INT128
5935  do_int128_discard(state, (int128) PG_GETARG_INT16(1));
5936 #else
5937  /* Should never fail, all inputs have dscale 0 */
5939  elog(ERROR, "do_numeric_discard failed unexpectedly");
5940 #endif
5941  }
5942 
5944 }
static bool do_numeric_discard(NumericAggState *state, Numeric newval)
Definition: numeric.c:4875
#define elog(elevel,...)
Definition: elog.h:224

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

◆ int2_avg_accum()

Datum int2_avg_accum ( PG_FUNCTION_ARGS  )

Definition at line 6605 of file numeric.c.

6606 {
6607  ArrayType *transarray;
6609  Int8TransTypeData *transdata;
6610 
6611  /*
6612  * If we're invoked as an aggregate, we can cheat and modify our first
6613  * parameter in-place to reduce palloc overhead. Otherwise we need to make
6614  * a copy of it before scribbling on it.
6615  */
6616  if (AggCheckCallContext(fcinfo, NULL))
6617  transarray = PG_GETARG_ARRAYTYPE_P(0);
6618  else
6619  transarray = PG_GETARG_ARRAYTYPE_P_COPY(0);
6620 
6621  if (ARR_HASNULL(transarray) ||
6622  ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
6623  elog(ERROR, "expected 2-element int8 array");
6624 
6625  transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
6626  transdata->count++;
6627  transdata->sum += newval;
6628 
6629  PG_RETURN_ARRAYTYPE_P(transarray);
6630 }
#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 6692 of file numeric.c.

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

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

4493 {
4494  int16 val = PG_GETARG_INT16(0);
4495 
4497 }

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

◆ int2_sum()

Datum int2_sum ( PG_FUNCTION_ARGS  )

Definition at line 6456 of file numeric.c.

6457 {
6458  int64 newval;
6459 
6460  if (PG_ARGISNULL(0))
6461  {
6462  /* No non-null input seen so far... */
6463  if (PG_ARGISNULL(1))
6464  PG_RETURN_NULL(); /* still no non-null */
6465  /* This is the first non-null input. */
6466  newval = (int64) PG_GETARG_INT16(1);
6468  }
6469 
6470  /*
6471  * If we're invoked as an aggregate, we can cheat and modify our first
6472  * parameter in-place to avoid palloc overhead. If not, we need to return
6473  * the new value of the transition variable. (If int8 is pass-by-value,
6474  * then of course this is useless as well as incorrect, so just ifdef it
6475  * out.)
6476  */
6477 #ifndef USE_FLOAT8_BYVAL /* controls int8 too */
6478  if (AggCheckCallContext(fcinfo, NULL))
6479  {
6480  int64 *oldsum = (int64 *) PG_GETARG_POINTER(0);
6481 
6482  /* Leave the running sum unchanged in the new input is null */
6483  if (!PG_ARGISNULL(1))
6484  *oldsum = *oldsum + (int64) PG_GETARG_INT16(1);
6485 
6486  PG_RETURN_POINTER(oldsum);
6487  }
6488  else
6489 #endif
6490  {
6491  int64 oldsum = PG_GETARG_INT64(0);
6492 
6493  /* Leave sum unchanged if new input is null. */
6494  if (PG_ARGISNULL(1))
6495  PG_RETURN_INT64(oldsum);
6496 
6497  /* OK to do the addition. */
6498  newval = oldsum + (int64) PG_GETARG_INT16(1);
6499 
6501  }
6502 }
#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 6775 of file numeric.c.

6776 {
6777  ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
6778  Int8TransTypeData *transdata;
6779 
6780  if (ARR_HASNULL(transarray) ||
6781  ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
6782  elog(ERROR, "expected 2-element int8 array");
6783  transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
6784 
6785  /* SQL defines SUM of no values to be NULL */
6786  if (transdata->count == 0)
6787  PG_RETURN_NULL();
6788 
6789  PG_RETURN_DATUM(Int64GetDatumFast(transdata->sum));
6790 }
#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 5521 of file numeric.c.

5522 {
5524 
5525  state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
5526 
5527  /* Create the state data on the first call */
5528  if (state == NULL)
5529  state = makePolyNumAggState(fcinfo, true);
5530 
5531  if (!PG_ARGISNULL(1))
5532  {
5533 #ifdef HAVE_INT128
5534  do_int128_accum(state, (int128) PG_GETARG_INT32(1));
5535 #else
5537 #endif
5538  }
5539 
5541 }
#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 5947 of file numeric.c.

5948 {
5950 
5951  state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
5952 
5953  /* Should not get here with no state */
5954  if (state == NULL)
5955  elog(ERROR, "int4_accum_inv called with NULL state");
5956 
5957  if (!PG_ARGISNULL(1))
5958  {
5959 #ifdef HAVE_INT128
5960  do_int128_discard(state, (int128) PG_GETARG_INT32(1));
5961 #else
5962  /* Should never fail, all inputs have dscale 0 */
5964  elog(ERROR, "do_numeric_discard failed unexpectedly");
5965 #endif
5966  }
5967 
5969 }

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

6634 {
6635  ArrayType *transarray;
6637  Int8TransTypeData *transdata;
6638 
6639  /*
6640  * If we're invoked as an aggregate, we can cheat and modify our first
6641  * parameter in-place to reduce palloc overhead. Otherwise we need to make
6642  * a copy of it before scribbling on it.
6643  */
6644  if (AggCheckCallContext(fcinfo, NULL))
6645  transarray = PG_GETARG_ARRAYTYPE_P(0);
6646  else
6647  transarray = PG_GETARG_ARRAYTYPE_P_COPY(0);
6648 
6649  if (ARR_HASNULL(transarray) ||
6650  ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
6651  elog(ERROR, "expected 2-element int8 array");
6652 
6653  transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
6654  transdata->count++;
6655  transdata->sum += newval;
6656 
6657  PG_RETURN_ARRAYTYPE_P(transarray);
6658 }

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

6721 {
6722  ArrayType *transarray;
6724  Int8TransTypeData *transdata;
6725 
6726  /*
6727  * If we're invoked as an aggregate, we can cheat and modify our first
6728  * parameter in-place to reduce palloc overhead. Otherwise we need to make
6729  * a copy of it before scribbling on it.
6730  */
6731  if (AggCheckCallContext(fcinfo, NULL))
6732  transarray = PG_GETARG_ARRAYTYPE_P(0);
6733  else
6734  transarray = PG_GETARG_ARRAYTYPE_P_COPY(0);
6735 
6736  if (ARR_HASNULL(transarray) ||
6737  ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
6738  elog(ERROR, "expected 2-element int8 array");
6739 
6740  transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
6741  transdata->count--;
6742  transdata->sum -= newval;
6743 
6744  PG_RETURN_ARRAYTYPE_P(transarray);
6745 }

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

6662 {
6663  ArrayType *transarray1;
6664  ArrayType *transarray2;
6665  Int8TransTypeData *state1;
6666  Int8TransTypeData *state2;
6667 
6668  if (!AggCheckCallContext(fcinfo, NULL))
6669  elog(ERROR, "aggregate function called in non-aggregate context");
6670 
6671  transarray1 = PG_GETARG_ARRAYTYPE_P(0);
6672  transarray2 = PG_GETARG_ARRAYTYPE_P(1);
6673 
6674  if (ARR_HASNULL(transarray1) ||
6675  ARR_SIZE(transarray1) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
6676  elog(ERROR, "expected 2-element int8 array");
6677 
6678  if (ARR_HASNULL(transarray2) ||
6679  ARR_SIZE(transarray2) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
6680  elog(ERROR, "expected 2-element int8 array");
6681 
6682  state1 = (Int8TransTypeData *) ARR_DATA_PTR(transarray1);
6683  state2 = (Int8TransTypeData *) ARR_DATA_PTR(transarray2);
6684 
6685  state1->count += state2->count;
6686  state1->sum += state2->sum;
6687 
6688  PG_RETURN_ARRAYTYPE_P(transarray1);
6689 }

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

4338 {
4339  int32 val = PG_GETARG_INT32(0);
4340 
4342 }

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

Referenced by executeItemOptUnwrapTarget().

◆ int4_sum()

Datum int4_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_INT32(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_INT32(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_INT32(1);
6548 
6550  }
6551 }

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

4253 {
4254  Numeric res;
4255  NumericVar result;
4256  int rscale;
4257  int w;
4258  int m;
4259 
4260  init_var(&result);
4261 
4262  /* result scale */
4263  rscale = log10val2 < 0 ? 0 : log10val2;
4264 
4265  /* how much to decrease the weight by */
4266  w = log10val2 / DEC_DIGITS;
4267  /* how much is left to divide by */
4268  m = log10val2 % DEC_DIGITS;
4269  if (m < 0)
4270  {
4271  m += DEC_DIGITS;
4272  w--;
4273  }
4274 
4275  /*
4276  * If there is anything left to divide by (10^m with 0 < m < DEC_DIGITS),
4277  * multiply the dividend by 10^(DEC_DIGITS - m), and shift the weight by
4278  * one more.
4279  */
4280  if (m > 0)
4281  {
4282 #if DEC_DIGITS == 4
4283  static const int pow10[] = {1, 10, 100, 1000};
4284 #elif DEC_DIGITS == 2
4285  static const int pow10[] = {1, 10};
4286 #elif DEC_DIGITS == 1
4287  static const int pow10[] = {1};
4288 #else
4289 #error unsupported NBASE
4290 #endif
4291  int64 factor = pow10[DEC_DIGITS - m];
4292  int64 new_val1;
4293 
4294  StaticAssertDecl(lengthof(pow10) == DEC_DIGITS, "mismatch with DEC_DIGITS");
4295 
4296  if (unlikely(pg_mul_s64_overflow(val1, factor, &new_val1)))
4297  {
4298 #ifdef HAVE_INT128
4299  /* do the multiplication using 128-bit integers */
4300  int128 tmp;
4301 
4302  tmp = (int128) val1 * (int128) factor;
4303 
4304  int128_to_numericvar(tmp, &result);
4305 #else
4306  /* do the multiplication using numerics */
4307  NumericVar tmp;
4308 
4309  init_var(&tmp);
4310 
4311  int64_to_numericvar(val1, &result);
4312  int64_to_numericvar(factor, &tmp);
4313  mul_var(&result, &tmp, &result, 0);
4314 
4315  free_var(&tmp);
4316 #endif
4317  }
4318  else
4319  int64_to_numericvar(new_val1, &result);
4320 
4321  w++;
4322  }
4323  else
4324  int64_to_numericvar(val1, &result);
4325 
4326  result.weight -= w;
4327  result.dscale = rscale;
4328 
4329  res = make_result(&result);
4330 
4331  free_var(&result);
4332 
4333  return res;
4334 }
static void int64_to_numericvar(int64 val, NumericVar *var)
Definition: numeric.c:8052
#define unlikely(x)
Definition: c.h:298
#define lengthof(array)
Definition: c.h:775
#define StaticAssertDecl(condition, errmessage)
Definition: c.h:923
static bool pg_mul_s64_overflow(int64 a, int64 b, int64 *result)
Definition: int.h:219

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

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

◆ int64_to_numeric()

◆ int64_to_numericvar()

static void int64_to_numericvar ( int64  val,
NumericVar var 
)
static

Definition at line 8052 of file numeric.c.

8053 {
8054  uint64 uval,
8055  newuval;
8056  NumericDigit *ptr;
8057  int ndigits;
8058 
8059  /* int64 can require at most 19 decimal digits; add one for safety */
8060  alloc_var(var, 20 / DEC_DIGITS);
8061  if (val < 0)
8062  {
8063  var->sign = NUMERIC_NEG;
8064  uval = -val;
8065  }
8066  else
8067  {
8068  var->sign = NUMERIC_POS;
8069  uval = val;
8070  }
8071  var->dscale = 0;
8072  if (val == 0)
8073  {
8074  var->ndigits = 0;
8075  var->weight = 0;
8076  return;
8077  }
8078  ptr = var->digits + var->ndigits;
8079  ndigits = 0;
8080  do
8081  {
8082  ptr--;
8083  ndigits++;
8084  newuval = uval / NBASE;
8085  *ptr = uval - newuval * NBASE;
8086  uval = newuval;
8087  } while (uval);
8088  var->digits = ptr;
8089  var->ndigits = ndigits;
8090  var->weight = ndigits - 1;
8091 }

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

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

◆ int8_accum()

Datum int8_accum ( PG_FUNCTION_ARGS  )

Definition at line 5544 of file numeric.c.

5545 {
5547 
5548  state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
5549 
5550  /* Create the state data on the first call */
5551  if (state == NULL)
5552  state = makeNumericAggState(fcinfo, true);
5553 
5554  if (!PG_ARGISNULL(1))
5556 
5558 }
static NumericAggState * makeNumericAggState(FunctionCallInfo fcinfo, bool calcSumX2)
Definition: numeric.c:4765

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

5973 {
5975 
5976  state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
5977 
5978  /* Should not get here with no state */
5979  if (state == NULL)
5980  elog(ERROR, "int8_accum_inv called with NULL state");
5981 
5982  if (!PG_ARGISNULL(1))
5983  {
5984  /* Should never fail, all inputs have dscale 0 */
5986  elog(ERROR, "do_numeric_discard failed unexpectedly");
5987  }
5988 
5990 }

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

6749 {
6750  ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
6751  Int8TransTypeData *transdata;
6752  Datum countd,
6753  sumd;
6754 
6755  if (ARR_HASNULL(transarray) ||
6756  ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
6757  elog(ERROR, "expected 2-element int8 array");
6758  transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
6759 
6760  /* SQL defines AVG of no values to be NULL */
6761  if (transdata->count == 0)
6762  PG_RETURN_NULL();
6763 
6764  countd = NumericGetDatum(int64_to_numeric(transdata->count));
6765  sumd = NumericGetDatum(int64_to_numeric(transdata->sum));
6766 
6768 }
Datum numeric_div(PG_FUNCTION_ARGS)
Definition: numeric.c:3122
#define DirectFunctionCall2(func, arg1, arg2)
Definition: fmgr.h:644

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

◆ int8_avg_accum()

Datum int8_avg_accum ( PG_FUNCTION_ARGS  )

Definition at line 5740 of file numeric.c.

5741 {
5743 
5744  state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
5745 
5746  /* Create the state data on the first call */
5747  if (state == NULL)
5748  state = makePolyNumAggState(fcinfo, false);
5749 
5750  if (!PG_ARGISNULL(1))
5751  {
5752 #ifdef HAVE_INT128
5753  do_int128_accum(state, (int128) PG_GETARG_INT64(1));
5754 #else
5756 #endif
5757  }
5758 
5760 }

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

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

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

5768 {
5769  PolyNumAggState *state1;
5770  PolyNumAggState *state2;
5771  MemoryContext agg_context;
5772  MemoryContext old_context;
5773 
5774  if (!AggCheckCallContext(fcinfo, &agg_context))
5775  elog(ERROR, "aggregate function called in non-aggregate context");
5776 
5777  state1 = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
5778  state2 = PG_ARGISNULL(1) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(1);
5779 
5780  if (state2 == NULL)
5781  PG_RETURN_POINTER(state1);
5782 
5783  /* manually copy all fields from state2 to state1 */
5784  if (state1 == NULL)
5785  {
5786  old_context = MemoryContextSwitchTo(agg_context);
5787 
5788  state1 = makePolyNumAggState(fcinfo, false);
5789  state1->N = state2->N;
5790 
5791 #ifdef HAVE_INT128
5792  state1->sumX = state2->sumX;
5793 #else
5794  accum_sum_copy(&state1->sumX, &state2->sumX);
5795 #endif
5796  MemoryContextSwitchTo(old_context);
5797 
5798  PG_RETURN_POINTER(state1);
5799  }
5800 
5801  if (state2->N > 0)
5802  {
5803  state1->N += state2->N;
5804 
5805 #ifdef HAVE_INT128
5806  state1->sumX += state2->sumX;
5807 #else
5808  /* The rest of this needs to work in the aggregate context */
5809  old_context = MemoryContextSwitchTo(agg_context);
5810 
5811  /* Accumulate sums */
5812  accum_sum_combine(&state1->sumX, &state2->sumX);
5813 
5814  MemoryContextSwitchTo(old_context);
5815 #endif
5816 
5817  }
5818  PG_RETURN_POINTER(state1);
5819 }
static void accum_sum_combine(NumericSumAccum *accum, NumericSumAccum *accum2)
Definition: numeric.c:12033
static void accum_sum_copy(NumericSumAccum *dst, NumericSumAccum *src)
Definition: numeric.c:12016
NumericSumAccum sumX
Definition: numeric.c:4747

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

5877 {
5878  bytea *sstate;
5879  PolyNumAggState *result;
5881  NumericVar tmp_var;
5882 
5883  if (!AggCheckCallContext(fcinfo, NULL))
5884  elog(ERROR, "aggregate function called in non-aggregate context");
5885 
5886  sstate = PG_GETARG_BYTEA_PP(0);
5887 
5888  init_var(&tmp_var);
5889 
5890  /*
5891  * Initialize a StringInfo so that we can "receive" it using the standard
5892  * recv-function infrastructure.
5893  */
5895  VARSIZE_ANY_EXHDR(sstate));
5896 
5897  result = makePolyNumAggStateCurrentContext(false);
5898 
5899  /* N */
5900  result->N = pq_getmsgint64(&buf);
5901 
5902  /* sumX */
5903  numericvar_deserialize(&buf, &tmp_var);
5904 #ifdef HAVE_INT128
5905  numericvar_to_int128(&tmp_var, &result->sumX);
5906 #else
5907  accum_sum_add(&result->sumX, &tmp_var);
5908 #endif
5909 
5910  pq_getmsgend(&buf);
5911 
5912  free_var(&tmp_var);
5913 
5914  PG_RETURN_POINTER(result);
5915 }
static void numericvar_deserialize(StringInfo buf, NumericVar *var)
Definition: numeric.c:7688
#define makePolyNumAggStateCurrentContext
Definition: numeric.c:5494
#define PG_GETARG_BYTEA_PP(n)
Definition: fmgr.h:308
void pq_getmsgend(StringInfo msg)
Definition: pqformat.c:635
int64 pq_getmsgint64(StringInfo msg)
Definition: pqformat.c:453
static void initReadOnlyStringInfo(StringInfo str, char *data, int len)
Definition: stringinfo.h:130
Definition: c.h:674
#define VARDATA_ANY(PTR)
Definition: varatt.h:324
#define VARSIZE_ANY_EXHDR(PTR)
Definition: varatt.h:317

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

◆ int8_avg_serialize()

Datum int8_avg_serialize ( PG_FUNCTION_ARGS  )

Definition at line 5827 of file numeric.c.

5828 {
5831  bytea *result;
5832  NumericVar tmp_var;
5833 
5834  /* Ensure we disallow calling when not in aggregate context */
5835  if (!AggCheckCallContext(fcinfo, NULL))
5836  elog(ERROR, "aggregate function called in non-aggregate context");
5837 
5839 
5840  /*
5841  * If the platform supports int128 then sumX will be a 128 integer type.
5842  * Here we'll convert that into a numeric type so that the combine state
5843  * is in the same format for both int128 enabled machines and machines
5844  * which don't support that type. The logic here is that one day we might
5845  * like to send these over to another server for further processing and we
5846  * want a standard format to work with.
5847  */
5848 
5849  init_var(&tmp_var);
5850 
5851  pq_begintypsend(&buf);
5852 
5853  /* N */
5854  pq_sendint64(&buf, state->N);
5855 
5856  /* sumX */
5857 #ifdef HAVE_INT128
5858  int128_to_numericvar(state->sumX, &tmp_var);
5859 #else
5860  accum_sum_final(&state->sumX, &tmp_var);
5861 #endif
5862  numericvar_serialize(&buf, &tmp_var);
5863 
5864  result = pq_endtypsend(&buf);
5865 
5866  free_var(&tmp_var);
5867 
5868  PG_RETURN_BYTEA_P(result);
5869 }
static void numericvar_serialize(StringInfo buf, const NumericVar *var)
Definition: numeric.c:7672
#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 4425 of file numeric.c.

4426 {
4427  int64 val = PG_GETARG_INT64(0);
4428 
4430 }

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

Referenced by executeItemOptUnwrapTarget().

◆ int8_sum()

Datum int8_sum ( PG_FUNCTION_ARGS  )

Definition at line 6557 of file numeric.c.

6558 {
6559  Numeric oldsum;
6560 
6561  if (PG_ARGISNULL(0))
6562  {
6563  /* No non-null input seen so far... */
6564  if (PG_ARGISNULL(1))
6565  PG_RETURN_NULL(); /* still no non-null */
6566  /* This is the first non-null input. */
6568  }
6569 
6570  /*
6571  * Note that we cannot special-case the aggregate case here, as we do for
6572  * int2_sum and int4_sum: numeric is of variable size, so we cannot modify
6573  * our first parameter in-place.
6574  */
6575 
6576  oldsum = PG_GETARG_NUMERIC(0);
6577 
6578  /* Leave sum unchanged if new input is null. */
6579  if (PG_ARGISNULL(1))
6580  PG_RETURN_NUMERIC(oldsum);
6581 
6582  /* OK to do the addition. */
6584  NumericGetDatum(oldsum),
6586 }
Datum numeric_add(PG_FUNCTION_ARGS)
Definition: numeric.c:2846

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

906 {
907  return typmod >= (int32) VARHDRSZ;
908 }

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

10702 {
10703  NumericVar x;
10704  NumericVar xx;
10705  int ni;
10706  NumericVar elem;
10707  NumericVar fact;
10708  int nsqrt;
10709  int local_rscale;
10710  int cmp;
10711 
10712  cmp = cmp_var(arg, &const_zero);
10713  if (cmp == 0)
10714  ereport(ERROR,
10715  (errcode(ERRCODE_INVALID_ARGUMENT_FOR_LOG),
10716  errmsg("cannot take logarithm of zero")));
10717  else if (cmp < 0)
10718  ereport(ERROR,
10719  (errcode(ERRCODE_INVALID_ARGUMENT_FOR_LOG),
10720  errmsg("cannot take logarithm of a negative number")));
10721 
10722  init_var(&x);
10723  init_var(&xx);
10724  init_var(&elem);
10725  init_var(&fact);
10726 
10727  set_var_from_var(arg, &x);
10728  set_var_from_var(&const_two, &fact);
10729 
10730  /*
10731  * Reduce input into range 0.9 < x < 1.1 with repeated sqrt() operations.
10732  *
10733  * The final logarithm will have up to around rscale+6 significant digits.
10734  * Each sqrt() will roughly halve the weight of x, so adjust the local
10735  * rscale as we work so that we keep this many significant digits at each
10736  * step (plus a few more for good measure).
10737  *
10738  * Note that we allow local_rscale < 0 during this input reduction
10739  * process, which implies rounding before the decimal point. sqrt_var()
10740  * explicitly supports this, and it significantly reduces the work
10741  * required to reduce very large inputs to the required range. Once the
10742  * input reduction is complete, x.weight will be 0 and its display scale
10743  * will be non-negative again.
10744  */
10745  nsqrt = 0;
10746  while (cmp_var(&x, &const_zero_point_nine) <= 0)
10747  {
10748  local_rscale = rscale - x.weight * DEC_DIGITS / 2 + 8;
10749  sqrt_var(&x, &x, local_rscale);
10750  mul_var(&fact, &const_two, &fact, 0);
10751  nsqrt++;
10752  }
10753  while (cmp_var(&x, &const_one_point_one) >= 0)
10754  {
10755  local_rscale = rscale - x.weight * DEC_DIGITS / 2 + 8;
10756  sqrt_var(&x, &x, local_rscale);
10757  mul_var(&fact, &const_two, &fact, 0);
10758  nsqrt++;
10759  }
10760 
10761  /*
10762  * We use the Taylor series for 0.5 * ln((1+z)/(1-z)),
10763  *
10764  * z + z^3/3 + z^5/5 + ...
10765  *
10766  * where z = (x-1)/(x+1) is in the range (approximately) -0.053 .. 0.048
10767  * due to the above range-reduction of x.
10768  *
10769  * The convergence of this is not as fast as one would like, but is
10770  * tolerable given that z is small.
10771  *
10772  * The Taylor series result will be multiplied by 2^(nsqrt+1), which has a
10773  * decimal weight of (nsqrt+1) * log10(2), so work with this many extra
10774  * digits of precision (plus a few more for good measure).
10775  */
10776  local_rscale = rscale + (int) ((nsqrt + 1) * 0.301029995663981) + 8;
10777 
10778  sub_var(&x, &const_one, result);
10779  add_var(&x, &const_one, &elem);
10780  div_var_fast(result, &elem, result, local_rscale, true);
10781  set_var_from_var(result, &xx);
10782  mul_var(result, result, &x, local_rscale);
10783 
10784  ni = 1;
10785 
10786  for (;;)
10787  {
10788  ni += 2;
10789  mul_var(&xx, &x, &xx, local_rscale);
10790  div_var_int(&xx, ni, 0, &elem, local_rscale, true);
10791 
10792  if (elem.ndigits == 0)
10793  break;
10794 
10795  add_var(result, &elem, result);
10796 
10797  if (elem.weight < (result->weight - local_rscale * 2 / DEC_DIGITS))
10798  break;
10799  }
10800 
10801  /* Compensate for argument range reduction, round to requested rscale */
10802  mul_var(result, &fact, result, rscale);
10803 
10804  free_var(&x);
10805  free_var(&xx);
10806  free_var(&elem);
10807  free_var(&fact);
10808 }
static const NumericVar const_two
Definition: numeric.c:426
static void sqrt_var(const NumericVar *arg, NumericVar *result, int rscale)
Definition: numeric.c:10010

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

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

◆ log_var()

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

Definition at line 10819 of file numeric.c.

10820 {
10821  NumericVar ln_base;
10822  NumericVar ln_num;
10823  int ln_base_dweight;
10824  int ln_num_dweight;
10825  int result_dweight;
10826  int rscale;
10827  int ln_base_rscale;
10828  int ln_num_rscale;
10829 
10830  init_var(&ln_base);
10831  init_var(&ln_num);
10832 
10833  /* Estimated dweights of ln(base), ln(num) and the final result */
10834  ln_base_dweight = estimate_ln_dweight(base);
10835  ln_num_dweight = estimate_ln_dweight(num);
10836  result_dweight = ln_num_dweight - ln_base_dweight;
10837 
10838  /*
10839  * Select the scale of the result so that it will have at least
10840  * NUMERIC_MIN_SIG_DIGITS significant digits and is not less than either
10841  * input's display scale.
10842  */
10843  rscale = NUMERIC_MIN_SIG_DIGITS - result_dweight;
10844  rscale = Max(rscale, base->dscale);
10845  rscale = Max(rscale, num->dscale);
10846  rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
10847  rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
10848 
10849  /*
10850  * Set the scales for ln(base) and ln(num) so that they each have more
10851  * significant digits than the final result.
10852  */
10853  ln_base_rscale = rscale + result_dweight - ln_base_dweight + 8;
10854  ln_base_rscale = Max(ln_base_rscale, NUMERIC_MIN_DISPLAY_SCALE);
10855 
10856  ln_num_rscale = rscale + result_dweight - ln_num_dweight + 8;
10857  ln_num_rscale = Max(ln_num_rscale, NUMERIC_MIN_DISPLAY_SCALE);
10858 
10859  /* Form natural logarithms */
10860  ln_var(base, &ln_base, ln_base_rscale);
10861  ln_var(num, &ln_num, ln_num_rscale);
10862 
10863  /* Divide and round to the required scale */
10864  div_var_fast(&ln_num, &ln_base, result, rscale, true);
10865 
10866  free_var(&ln_num);
10867  free_var(&ln_base);
10868 }
static int estimate_ln_dweight(const NumericVar *var)
Definition: numeric.c:10619
#define NUMERIC_MAX_DISPLAY_SCALE
Definition: numeric.h:39
#define NUMERIC_MIN_SIG_DIGITS
Definition: numeric.h:49

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

Referenced by numeric_log().

◆ make_numeric_typmod()

static int32 make_numeric_typmod ( int  precision,
int  scale 
)
inlinestatic

Definition at line 896 of file numeric.c.

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

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

7731 {
7732  Numeric result;
7733  NumericDigit *digits = var->digits;
7734  int weight = var->weight;
7735  int sign = var->sign;
7736  int n;
7737  Size len;
7738 
7739  if (have_error)
7740  *have_error = false;
7741 
7743  {
7744  /*
7745  * Verify valid special value. This could be just an Assert, perhaps,
7746  * but it seems worthwhile to expend a few cycles to ensure that we
7747  * never write any nonzero reserved bits to disk.
7748  */
7749  if (!(sign == NUMERIC_NAN ||
7750  sign == NUMERIC_PINF ||
7751  sign == NUMERIC_NINF))
7752  elog(ERROR, "invalid numeric sign value 0x%x", sign);
7753 
7754  result = (Numeric) palloc(NUMERIC_HDRSZ_SHORT);
7755 
7757  result->choice.n_header = sign;
7758  /* the header word is all we need */
7759 
7760  dump_numeric("make_result()", result);
7761  return result;
7762  }
7763 
7764  n = var->ndigits;
7765 
7766  /* truncate leading zeroes */
7767  while (n > 0 && *digits == 0)
7768  {
7769  digits++;
7770  weight--;
7771  n--;
7772  }
7773  /* truncate trailing zeroes */
7774  while (n > 0 && digits[n - 1] == 0)
7775  n--;
7776 
7777  /* If zero result, force to weight=0 and positive sign */
7778  if (n == 0)
7779  {
7780  weight = 0;
7781  sign = NUMERIC_POS;
7782  }
7783 
7784  /* Build the result */
7785  if (NUMERIC_CAN_BE_SHORT(var->dscale, weight))
7786  {
7787  len = NUMERIC_HDRSZ_SHORT + n * sizeof(NumericDigit);
7788  result = (Numeric) palloc(len);
7789  SET_VARSIZE(result, len);
7790  result->choice.n_short.n_header =
7792  : NUMERIC_SHORT)
7794  | (weight < 0 ? NUMERIC_SHORT_WEIGHT_SIGN_MASK : 0)
7795  | (weight & NUMERIC_SHORT_WEIGHT_MASK);
7796  }
7797  else
7798  {
7799  len = NUMERIC_HDRSZ + n * sizeof(NumericDigit);
7800  result = (Numeric) palloc(len);
7801  SET_VARSIZE(result, len);
7802  result->choice.n_long.n_sign_dscale =
7803  sign | (var->dscale & NUMERIC_DSCALE_MASK);
7804  result->choice.n_long.n_weight = weight;
7805  }
7806 
7807  Assert(NUMERIC_NDIGITS(result) == n);
7808  if (n > 0)
7809  memcpy(NUMERIC_DIGITS(result), digits, n * sizeof(NumericDigit));
7810 
7811  /* Check for overflow of int16 fields */
7812  if (NUMERIC_WEIGHT(result) != weight ||
7813  NUMERIC_DSCALE(result) != var->dscale)
7814  {
7815  if (have_error)
7816  {
7817  *have_error = true;
7818  return NULL;
7819  }
7820  else
7821  {
7822  ereport(ERROR,
7823  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
7824  errmsg("value overflows numeric format")));
7825  }
7826  }
7827 
7828  dump_numeric("make_result()", result);
7829  return result;
7830 }
#define dump_numeric(s, n)
Definition: numeric.c:472
#define NUMERIC_CAN_BE_SHORT(scale, weight)
Definition: numeric.c:490
#define NUMERIC_HDRSZ_SHORT
Definition: numeric.c:175
#define NUMERIC_NINF
Definition: numeric.c:199
#define NUMERIC_SHORT
Definition: numeric.c:167
#define NUMERIC_HDRSZ
Definition: numeric.c:174
#define NUMERIC_SPECIAL
Definition: numeric.c:168
#define NUMERIC_SIGN_MASK
Definition: numeric.c:164
#define NUMERIC_PINF
Definition: numeric.c:198
size_t Size
Definition: c.h:592
char sign
Definition: informix.c:668
union NumericChoice choice
Definition: numeric.c:156
uint16 n_header
Definition: numeric.c:148
#define SET_VARSIZE(PTR, len)
Definition: varatt.h:305

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

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

◆ makeNumericAggState()

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

Definition at line 4765 of file numeric.c.

4766 {
4768  MemoryContext agg_context;
4769  MemoryContext old_context;
4770 
4771  if (!AggCheckCallContext(fcinfo, &agg_context))
4772  elog(ERROR, "aggregate function called in non-aggregate context");
4773 
4774  old_context = MemoryContextSwitchTo(agg_context);
4775 
4777  state->calcSumX2 = calcSumX2;
4778  state->agg_context = agg_context;
4779 
4780  MemoryContextSwitchTo(old_context);
4781 
4782  return state;
4783 }

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

4791 {
4793 
4795  state->calcSumX2 = calcSumX2;
4796  state->agg_context = CurrentMemoryContext;
4797 
4798  return state;
4799 }
MemoryContext CurrentMemoryContext
Definition: mcxt.c:131

References CurrentMemoryContext, and palloc0().

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

◆ mod_var()

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

Definition at line 9794 of file numeric.c.

9795 {
9796  NumericVar tmp;
9797 
9798  init_var(&tmp);
9799 
9800  /* ---------
9801  * We do this using the equation
9802  * mod(x,y) = x - trunc(x/y)*y
9803  * div_var can be persuaded to give us trunc(x/y) directly.
9804  * ----------
9805  */
9806  div_var(var1, var2, &tmp, 0, false);
9807 
9808  mul_var(var2, &tmp, &tmp, var2->dscale);
9809 
9810  sub_var(var1, &tmp, result);
9811 
9812  free_var(&tmp);
9813 }

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

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

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

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

◆ numeric()

Definition at line 1235 of file numeric.c.

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

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

Referenced by ecpg_set_compat_sqlda(), and ecpg_set_native_sqlda().

◆ numeric_abbrev_abort()

static bool numeric_abbrev_abort ( int  memtupcount,
SortSupport  ssup 
)
static

Definition at line 2106 of file numeric.c.

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

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

Referenced by numeric_sortsupport().

◆ numeric_abbrev_convert()

static Datum numeric_abbrev_convert ( Datum  original_datum,
SortSupport  ssup 
)
static

Definition at line 2044 of file numeric.c.

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

1383 {
1384  Numeric num = PG_GETARG_NUMERIC(0);
1385  Numeric res;
1386 
1387  /*
1388  * Do it the easy way directly on the packed format
1389  */
1390  res = duplicate_numeric(num);
1391 
1392  if (NUMERIC_IS_SHORT(num))
1393  res->choice.n_short.n_header =
1395  else if (NUMERIC_IS_SPECIAL(num))
1396  {
1397  /* This changes -Inf to Inf, and doesn't affect NaN */
1398  res->choice.n_short.n_header =
1400  }
1401  else
1402  res->choice.n_long.n_sign_dscale = NUMERIC_POS | NUMERIC_DSCALE(num);
1403 
1405 }
#define NUMERIC_INF_SIGN_MASK
Definition: numeric.c:200

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

Referenced by executeItemOptUnwrapTarget(), and numeric_absolute().

◆ numeric_accum()

Datum numeric_accum ( PG_FUNCTION_ARGS  )

Definition at line 4968 of file numeric.c.

4969 {
4971 
4972  state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
4973 
4974  /* Create the state data on the first call */
4975  if (state == NULL)
4976  state = makeNumericAggState(fcinfo, true);
4977 
4978  if (!PG_ARGISNULL(1))
4980 
4982 }

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

5380 {
5382 
5383  state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
5384 
5385  /* Should not get here with no state */
5386  if (state == NULL)
5387  elog(ERROR, "numeric_accum_inv called with NULL state");
5388 
5389  if (!PG_ARGISNULL(1))
5390  {
5391  /* If we fail to perform the inverse transition, return NULL */
5393  PG_RETURN_NULL();
5394  }
5395 
5397 }

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

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

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

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

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

6077 {
6079  Datum N_datum;
6080  Datum sumX_datum;
6081  NumericVar sumX_var;
6082 
6083  state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
6084 
6085  /* If there were no non-null inputs, return NULL */
6086  if (state == NULL || NA_TOTAL_COUNT(state) == 0)
6087  PG_RETURN_NULL();
6088 
6089  if (state->NaNcount > 0) /* there was at least one NaN input */
6091 
6092  /* adding plus and minus infinities gives NaN */
6093  if (state->pInfcount > 0 && state->nInfcount > 0)
6095  if (state->pInfcount > 0)
6097  if (state->nInfcount > 0)
6099 
6100  N_datum = NumericGetDatum(int64_to_numeric(state->N));
6101 
6102  init_var(&sumX_var);
6103  accum_sum_final(&state->sumX, &sumX_var);
6104  sumX_datum = NumericGetDatum(make_result(&sumX_var));
6105  free_var(&sumX_var);
6106 
6107  PG_RETURN_DATUM(DirectFunctionCall2(numeric_div, sumX_datum, N_datum));
6108 }
#define NA_TOTAL_COUNT(na)
Definition: numeric.c:4757

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

5061 {
5063 
5064  state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
5065 
5066  /* Create the state data on the first call */
5067  if (state == NULL)
5068  state = makeNumericAggState(fcinfo, false);
5069 
5070  if (!PG_ARGISNULL(1))
5072 
5074 }

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

5081 {
5082  NumericAggState *state1;
5083  NumericAggState *state2;
5084  MemoryContext agg_context;
5085  MemoryContext old_context;
5086 
5087  if (!AggCheckCallContext(fcinfo, &agg_context))
5088  elog(ERROR, "aggregate function called in non-aggregate context");
5089 
5090  state1 = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
5091  state2 = PG_ARGISNULL(1) ? NULL : (NumericAggState *) PG_GETARG_POINTER(1);
5092 
5093  if (state2 == NULL)
5094  PG_RETURN_POINTER(state1);
5095 
5096  /* manually copy all fields from state2 to state1 */
5097  if (state1 == NULL)
5098  {
5099  old_context = MemoryContextSwitchTo(agg_context);
5100 
5101  state1 = makeNumericAggStateCurrentContext(false);
5102  state1->N = state2->N;
5103  state1->NaNcount = state2->NaNcount;
5104  state1->pInfcount = state2->pInfcount;
5105  state1->nInfcount = state2->nInfcount;
5106  state1->maxScale = state2->maxScale;
5107  state1->maxScaleCount = state2->maxScaleCount;
5108 
5109  accum_sum_copy(&state1->sumX, &state2->sumX);
5110 
5111  MemoryContextSwitchTo(old_context);
5112 
5113  PG_RETURN_POINTER(state1);
5114  }
5115 
5116  state1->N += state2->N;
5117  state1->NaNcount += state2->NaNcount;
5118  state1->pInfcount += state2->pInfcount;
5119  state1->nInfcount += state2->nInfcount;
5120 
5121  if (state2->N > 0)
5122  {
5123  /*
5124  * These are currently only needed for moving aggregates, but let's do
5125  * the right thing anyway...
5126  */
5127  if (state2->maxScale > state1->maxScale)
5128  {
5129  state1->maxScale = state2->maxScale;
5130  state1->maxScaleCount = state2->maxScaleCount;
5131  }
5132  else if (state2->maxScale == state1->maxScale)
5133  state1->maxScaleCount += state2->maxScaleCount;
5134 
5135  /* The rest of this needs to work in the aggregate context */
5136  old_context = MemoryContextSwitchTo(agg_context);
5137 
5138  /* Accumulate sums */
5139  accum_sum_combine(&state1->sumX, &state2->sumX);
5140 
5141  MemoryContextSwitchTo(old_context);
5142  }
5143  PG_RETURN_POINTER(state1);
5144 }
static NumericAggState * makeNumericAggStateCurrentContext(bool calcSumX2)
Definition: numeric.c:4790
int64 NaNcount
Definition: numeric.c:4752
int64 nInfcount
Definition: numeric.c:4754
int64 maxScaleCount
Definition: numeric.c:4750
int64 pInfcount
Definition: numeric.c:4753

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

5205 {
5206  bytea *sstate;
5207  NumericAggState *result;
5209  NumericVar tmp_var;
5210 
5211  if (!AggCheckCallContext(fcinfo, NULL))
5212  elog(ERROR, "aggregate function called in non-aggregate context");
5213 
5214  sstate = PG_GETARG_BYTEA_PP(0);
5215 
5216  init_var(&tmp_var);
5217 
5218  /*
5219  * Initialize a StringInfo so that we can "receive" it using the standard
5220  * recv-function infrastructure.
5221  */
5223  VARSIZE_ANY_EXHDR(sstate));
5224 
5225  result = makeNumericAggStateCurrentContext(false);
5226 
5227  /* N */
5228  result->N = pq_getmsgint64(&buf);
5229 
5230  /* sumX */
5231  numericvar_deserialize(&buf, &tmp_var);
5232  accum_sum_add(&(result->sumX), &tmp_var);
5233 
5234  /* maxScale */
5235  result->maxScale = pq_getmsgint(&buf, 4);
5236 
5237  /* maxScaleCount */
5238  result->maxScaleCount = pq_getmsgint64(&buf);
5239 
5240  /* NaNcount */
5241  result->NaNcount = pq_getmsgint64(&buf);
5242 
5243  /* pInfcount */
5244  result->pInfcount = pq_getmsgint64(&buf);
5245 
5246  /* nInfcount */
5247  result->nInfcount = pq_getmsgint64(&buf);
5248 
5249  pq_getmsgend(&buf);
5250 
5251  free_var(&tmp_var);
5252 
5253  PG_RETURN_POINTER(result);
5254 }
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 5152 of file numeric.c.

5153 {
5156  bytea *result;
5157  NumericVar tmp_var;
5158 
5159  /* Ensure we disallow calling when not in aggregate context */
5160  if (!AggCheckCallContext(fcinfo, NULL))
5161  elog(ERROR, "aggregate function called in non-aggregate context");
5162 
5164 
5165  init_var(&tmp_var);
5166 
5167  pq_begintypsend(&buf);
5168 
5169  /* N */
5170  pq_sendint64(&buf, state->N);
5171 
5172  /* sumX */
5173  accum_sum_final(&state->sumX, &tmp_var);
5174  numericvar_serialize(&buf, &tmp_var);
5175 
5176  /* maxScale */
5177  pq_sendint32(&buf, state->maxScale);
5178 
5179  /* maxScaleCount */
5180  pq_sendint64(&buf, state->maxScaleCount);
5181 
5182  /* NaNcount */
5183  pq_sendint64(&buf, state->NaNcount);
5184 
5185  /* pInfcount */
5186  pq_sendint64(&buf, state->pInfcount);
5187 
5188  /* nInfcount */
5189  pq_sendint64(&buf, state->nInfcount);
5190 
5191  result = pq_endtypsend(&buf);
5192 
5193  free_var(&tmp_var);
5194 
5195  PG_RETURN_BYTEA_P(result);
5196 }
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 1628 of file numeric.c.

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

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

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

2202 {
2203  /*
2204  * NOTE WELL: this is intentionally backwards, because the abbreviation is
2205  * negated relative to the original value, to handle NaN/infinity cases.
2206  */
2208  return 1;
2210  return -1;
2211  return 0;
2212 }
#define DatumGetNumericAbbrev(X)
Definition: numeric.c:403
int y
Definition: isn.c:72

References DatumGetNumericAbbrev, x, and y.

Referenced by numeric_sortsupport().

◆ numeric_combine()

Datum numeric_combine ( PG_FUNCTION_ARGS  )

Definition at line 4988 of file numeric.c.

4989 {
4990  NumericAggState *state1;
4991  NumericAggState *state2;
4992  MemoryContext agg_context;
4993  MemoryContext old_context;
4994 
4995  if (!AggCheckCallContext(fcinfo, &agg_context))
4996  elog(ERROR, "aggregate function called in non-aggregate context");
4997 
4998  state1 = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
4999  state2 = PG_ARGISNULL(1) ? NULL : (NumericAggState *) PG_GETARG_POINTER(1);
5000 
5001  if (state2 == NULL)
5002  PG_RETURN_POINTER(state1);
5003 
5004  /* manually copy all fields from state2 to state1 */
5005  if (state1 == NULL)
5006  {
5007  old_context = MemoryContextSwitchTo(agg_context);
5008 
5009  state1 = makeNumericAggStateCurrentContext(true);
5010  state1->N = state2->N;
5011  state1->NaNcount = state2->NaNcount;
5012  state1->pInfcount = state2->pInfcount;
5013  state1->nInfcount = state2->nInfcount;
5014  state1->maxScale = state2->maxScale;
5015  state1->maxScaleCount = state2->maxScaleCount;
5016 
5017  accum_sum_copy(&state1->sumX, &state2->sumX);
5018  accum_sum_copy(&state1->sumX2, &state2->sumX2);
5019 
5020  MemoryContextSwitchTo(old_context);
5021 
5022  PG_RETURN_POINTER(state1);
5023  }
5024 
5025  state1->N += state2->N;
5026  state1->NaNcount += state2->NaNcount;
5027  state1->pInfcount += state2->pInfcount;
5028  state1->nInfcount += state2->nInfcount;
5029 
5030  if (state2->N > 0)
5031  {
5032  /*
5033  * These are currently only needed for moving aggregates, but let's do
5034  * the right thing anyway...
5035  */
5036  if (state2->maxScale > state1->maxScale)
5037  {
5038  state1->maxScale = state2->maxScale;
5039  state1->maxScaleCount = state2->maxScaleCount;
5040  }
5041  else if (state2->maxScale == state1->maxScale)
5042  state1->maxScaleCount += state2->maxScaleCount;
5043 
5044  /* The rest of this needs to work in the aggregate context */
5045  old_context = MemoryContextSwitchTo(agg_context);
5046 
5047  /* Accumulate sums */
5048  accum_sum_combine(&state1->sumX, &state2->sumX);
5049  accum_sum_combine(&state1->sumX2, &state2->sumX2);
5050 
5051  MemoryContextSwitchTo(old_context);
5052  }
5053  PG_RETURN_POINTER(state1);
5054 }
NumericSumAccum sumX2
Definition: numeric.c:4748

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

5319 {
5320  bytea *sstate;
5321  NumericAggState *result;
5323  NumericVar tmp_var;
5324 
5325  if (!AggCheckCallContext(fcinfo, NULL))
5326  elog(ERROR, "aggregate function called in non-aggregate context");
5327 
5328  sstate = PG_GETARG_BYTEA_PP(0);
5329 
5330  init_var(&tmp_var);
5331 
5332  /*
5333  * Initialize a StringInfo so that we can "receive" it using the standard
5334  * recv-function infrastructure.
5335  */
5337  VARSIZE_ANY_EXHDR(sstate));
5338 
5339  result = makeNumericAggStateCurrentContext(false);
5340 
5341  /* N */
5342  result->N = pq_getmsgint64(&buf);
5343 
5344  /* sumX */
5345  numericvar_deserialize(&buf, &tmp_var);
5346  accum_sum_add(&(result->sumX), &tmp_var);
5347 
5348  /* sumX2 */
5349  numericvar_deserialize(&buf, &tmp_var);
5350  accum_sum_add(&(result->sumX2), &tmp_var);
5351 
5352  /* maxScale */
5353  result->maxScale = pq_getmsgint(&buf, 4);
5354 
5355  /* maxScaleCount */
5356  result->maxScaleCount = pq_getmsgint64(&buf);
5357 
5358  /* NaNcount */
5359  result->NaNcount = pq_getmsgint64(&buf);
5360 
5361  /* pInfcount */
5362  result->pInfcount = pq_getmsgint64(&buf);
5363 
5364  /* nInfcount */
5365  result->nInfcount = pq_getmsgint64(&buf);
5366 
5367  pq_getmsgend(&buf);
5368 
5369  free_var(&tmp_var);
5370 
5371  PG_RETURN_POINTER(result);
5372 }

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

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

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

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

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

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

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

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

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

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

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

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

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

2180 {
2181  Numeric nx = DatumGetNumeric(x);
2182  Numeric ny = DatumGetNumeric(y);
2183  int result;
2184 
2185  result = cmp_numerics(nx, ny);
2186 
2187  if ((Pointer) nx != DatumGetPointer(x))
2188  pfree(nx);
2189  if ((Pointer) ny != DatumGetPointer(y))
2190  pfree(ny);
2191 
2192  return result;
2193 }
static Numeric DatumGetNumeric(Datum X)
Definition: numeric.h:60

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

Referenced by numeric_sortsupport().

◆ numeric_float4()

Datum numeric_float4 ( PG_FUNCTION_ARGS  )

Definition at line 4670 of file numeric.c.

4671 {
4672  Numeric num = PG_GETARG_NUMERIC(0);
4673  char *tmp;
4674  Datum result;
4675 
4676  if (NUMERIC_IS_SPECIAL(num))
4677  {
4678  if (NUMERIC_IS_PINF(num))
4680  else if (NUMERIC_IS_NINF(num))
4682  else
4684  }
4685 
4687  NumericGetDatum(num)));
4688 
4690 
4691  pfree(tmp);
4692 
4693  PG_RETURN_DATUM(result);
4694 }
Datum numeric_out(PG_FUNCTION_ARGS)
Definition: numeric.c:805
Datum float4in(PG_FUNCTION_ARGS)
Definition: float.c:163
static float4 get_float4_infinity(void)
Definition: float.h:74
static float4 get_float4_nan(void)
Definition: float.h:111
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:642
#define PG_RETURN_FLOAT4(x)
Definition: fmgr.h:366
static char * DatumGetCString(Datum X)
Definition: postgres.h:335
static Datum CStringGetDatum(const char *X)
Definition: postgres.h:350

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

Referenced by jsonb_float4().

◆ numeric_float8()

Datum numeric_float8 ( PG_FUNCTION_ARGS  )

Definition at line 4576 of file numeric.c.

4577 {
4578  Numeric num = PG_GETARG_NUMERIC(0);
4579  char *tmp;
4580  Datum result;
4581 
4582  if (NUMERIC_IS_SPECIAL(num))
4583  {
4584  if (NUMERIC_IS_PINF(num))
4586  else if (NUMERIC_IS_NINF(num))
4588  else
4590  }
4591 
4593  NumericGetDatum(num)));
4594 
4596 
4597  pfree(tmp);
4598 
4599  PG_RETURN_DATUM(result);
4600 }
Datum float8in(PG_FUNCTION_ARGS)
Definition: float.c:363
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 4609 of file numeric.c.

4610 {
4611  Numeric num = PG_GETARG_NUMERIC(0);
4612  double val;
4613 
4614  if (NUMERIC_IS_SPECIAL(num))
4615  {
4616  if (NUMERIC_IS_PINF(num))
4617  val = HUGE_VAL;
4618  else if (NUMERIC_IS_NINF(num))
4619  val = -HUGE_VAL;
4620  else
4621  val = get_float8_nan();
4622  }
4623  else
4624  {
4625  NumericVar x;
4626 
4627  init_var_from_num(num, &x);
4629  }
4630 
4632 }

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

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

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

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

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

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

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

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

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

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

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

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

◆ numeric_inc()

Datum numeric_inc ( PG_FUNCTION_ARGS  )

Definition at line 3435 of file numeric.c.

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

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

4502 {
4503  Numeric num = PG_GETARG_NUMERIC(0);
4504  NumericVar x;
4505  int64 val;
4506  int16 result;
4507 
4508  if (NUMERIC_IS_SPECIAL(num))
4509  {
4510  if (NUMERIC_IS_NAN(num))
4511  ereport(ERROR,
4512  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4513  errmsg("cannot convert NaN to %s", "smallint")));
4514  else
4515  ereport(ERROR,
4516  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4517  errmsg("cannot convert infinity to %s", "smallint")));
4518  }
4519 
4520  /* Convert to variable format and thence to int8 */
4521  init_var_from_num(num, &x);
4522 
4523  if (!numericvar_to_int64(&x, &val))
4524  ereport(ERROR,
4525  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
4526  errmsg("smallint out of range")));
4527 
4529  ereport(ERROR,
4530  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
4531  errmsg("smallint out of range")));
4532 
4533  /* Down-convert to int2 */
4534  result = (int16) val;
4535 
4536  PG_RETURN_INT16(result);
4537 }
static bool numericvar_to_int64(const NumericVar *var, int64 *result)
Definition: numeric.c:7977
#define PG_INT16_MIN
Definition: c.h:572
#define PG_INT16_MAX
Definition: c.h:573
#define PG_RETURN_INT16(x)
Definition: fmgr.h:356

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

Referenced by jsonb_int2().

◆ numeric_int4()

Datum numeric_int4 ( PG_FUNCTION_ARGS  )

Definition at line 4395 of file numeric.c.

4396 {
4397  Numeric num = PG_GETARG_NUMERIC(0);
4398 
4400 }
int32 numeric_int4_opt_error(Numeric num, bool *have_error)
Definition: numeric.c:4345

References numeric_int4_opt_error(), PG_GETARG_NUMERIC, and PG_RETURN_INT32.

Referenced by jsonb_int4(), and numeric_to_char().

◆ numeric_int4_opt_error()

int32 numeric_int4_opt_error ( Numeric  num,
bool have_error 
)

Definition at line 4345 of file numeric.c.

4346 {
4347  NumericVar x;
4348  int32 result;
4349 
4350  if (have_error)
4351  *have_error = false;
4352 
4353  if (NUMERIC_IS_SPECIAL(num))
4354  {
4355  if (have_error)
4356  {
4357  *have_error = true;
4358  return 0;
4359  }
4360  else
4361  {
4362  if (NUMERIC_IS_NAN(num))
4363  ereport(ERROR,
4364  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4365  errmsg("cannot convert NaN to %s", "integer")));
4366  else
4367  ereport(ERROR,
4368  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4369  errmsg("cannot convert infinity to %s", "integer")));
4370  }
4371  }
4372 
4373  /* Convert to variable format, then convert to int4 */
4374  init_var_from_num(num, &x);
4375 
4376  if (!numericvar_to_int32(&x, &result))
4377  {
4378  if (have_error)
4379  {
4380  *have_error = true;
4381  return 0;
4382  }
4383  else
4384  {
4385  ereport(ERROR,
4386  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
4387  errmsg("integer out of range")));
4388  }
4389  }
4390 
4391  return result;
4392 }
static bool numericvar_to_int32(const NumericVar *var, int32 *result)
Definition: numeric.c:4408

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

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

◆ numeric_int8()

Datum numeric_int8 ( PG_FUNCTION_ARGS  )

Definition at line 4483 of file numeric.c.

4484 {
4485  Numeric num = PG_GETARG_NUMERIC(0);
4486 
4488 }
int64 numeric_int8_opt_error(Numeric num, bool *have_error)
Definition: numeric.c:4433

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

4434 {
4435  NumericVar x;
4436  int64 result;
4437 
4438  if (have_error)
4439  *have_error = false;
4440 
4441  if (NUMERIC_IS_SPECIAL(num))
4442  {
4443  if (have_error)
4444  {
4445  *have_error = true;
4446  return 0;
4447  }
4448  else
4449  {
4450  if (NUMERIC_IS_NAN(num))
4451  ereport(ERROR,
4452  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4453  errmsg("cannot convert NaN to %s", "bigint")));
4454  else
4455  ereport(ERROR,
4456  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4457  errmsg("cannot convert infinity to %s", "bigint")));
4458  }
4459  }
4460 
4461  /* Convert to variable format, then convert to int8 */
4462  init_var_from_num(num, &x);
4463 
4464  if (!numericvar_to_int64(&x, &result))
4465  {
4466  if (have_error)
4467  {
4468  *have_error = true;
4469  return 0;
4470  }
4471  else
4472  {
4473  ereport(ERROR,
4474  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
4475  errmsg("bigint out of range")));
4476  }
4477  }
4478 
4479  return result;
4480 }

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

852 {
853  return NUMERIC_IS_INF(num);
854 }
#define NUMERIC_IS_INF(n)
Definition: numeric.c:206

References NUMERIC_IS_INF.

Referenced by executeItemOptUnwrapTarget(), and PLyNumber_ToJsonbValue().

◆ numeric_is_integral()

static bool numeric_is_integral ( Numeric  num)
static

Definition at line 862 of file numeric.c.

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

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

841 {
842  return NUMERIC_IS_NAN(num);
843 }

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

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

References cmp_numerics(), PG_GETARG_NUMERIC, and PG_RETURN_NUMERIC.

◆ numeric_lcm()

Datum numeric_lcm ( PG_FUNCTION_ARGS  )

Definition at line 3562 of file numeric.c.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Referenced by executeItemOptUnwrapTarget(), and numeric_mul().

◆ numeric_ne()

Datum numeric_ne ( PG_FUNCTION_ARGS  )

Definition at line 2428 of file numeric.c.

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

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

◆ numeric_normalize()

char* numeric_normalize ( Numeric  num)

Definition at line 1015 of file numeric.c.

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

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

Referenced by make_scalar_key().

◆ numeric_out()

Datum numeric_out ( PG_FUNCTION_ARGS  )

Definition at line 805 of file numeric.c.

806 {
807  Numeric num = PG_GETARG_NUMERIC(0);
808  NumericVar x;
809  char *str;
810 
811  /*
812  * Handle NaN and infinities
813  */
814  if (NUMERIC_IS_SPECIAL(num))
815  {
816  if (NUMERIC_IS_PINF(num))
817  PG_RETURN_CSTRING(pstrdup("Infinity"));
818  else if (NUMERIC_IS_NINF(num))
819  PG_RETURN_CSTRING(pstrdup("-Infinity"));
820  else
821  PG_RETURN_CSTRING(pstrdup("NaN"));
822  }
823 
824  /*
825  * Get the number in the variable format.
826  */
827  init_var_from_num(num, &x);
828 
829  str = get_str_from_var(&x);
830 
832 }
#define PG_RETURN_CSTRING(x)
Definition: fmgr.h:362

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

Referenced by executeItemOptUnwrapTarget(), iterate_jsonb_values(), jsonb_put_escaped_value(), 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 981 of file numeric.c.

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

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

Referenced by int8_to_char(), and numeric_to_char().

◆ numeric_pg_lsn()

Datum numeric_pg_lsn ( PG_FUNCTION_ARGS  )

Definition at line 4698 of file numeric.c.

4699 {
4700  Numeric num = PG_GETARG_NUMERIC(0);
4701  NumericVar x;
4702  XLogRecPtr result;
4703 
4704  if (NUMERIC_IS_SPECIAL(num))
4705  {
4706  if (NUMERIC_IS_NAN(num))
4707  ereport(ERROR,
4708  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4709  errmsg("cannot convert NaN to %s", "pg_lsn")));
4710  else
4711  ereport(ERROR,
4712  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4713  errmsg("cannot convert infinity to %s", "pg_lsn")));
4714  }
4715 
4716  /* Convert to variable format and thence to pg_lsn */
4717  init_var_from_num(num, &x);
4718 
4719  if (!numericvar_to_uint64(&x, (uint64 *) &result))
4720  ereport(ERROR,
4721  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4722  errmsg("pg_lsn out of range")));
4723 
4724  PG_RETURN_LSN(result);
4725 }
static bool numericvar_to_uint64(const NumericVar *var, uint64 *result)
Definition: numeric.c:8099
#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 6046 of file numeric.c.

6047 {
6048 #ifdef HAVE_INT128
6050  NumericVar result;
6051  Datum countd,
6052  sumd;
6053 
6054  state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
6055 
6056  /* If there were no non-null inputs, return NULL */
6057  if (state == NULL || state->N == 0)
6058  PG_RETURN_NULL();
6059 
6060  init_var(&result);
6061 
6062  int128_to_numericvar(state->sumX, &result);
6063 
6064  countd = NumericGetDatum(int64_to_numeric(state->N));
6065  sumd = NumericGetDatum(make_result(&result));
6066 
6067  free_var(&result);
6068 
6070 #else
6071  return numeric_avg(fcinfo);
6072 #endif
6073 }
Datum numeric_avg(PG_FUNCTION_ARGS)
Definition: numeric.c:6076

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

5565 {
5566  PolyNumAggState *state1;
5567  PolyNumAggState *state2;
5568  MemoryContext agg_context;
5569  MemoryContext old_context;
5570 
5571  if (!AggCheckCallContext(fcinfo, &agg_context))
5572  elog(ERROR, "aggregate function called in non-aggregate context");
5573 
5574  state1 = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
5575  state2 = PG_ARGISNULL(1) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(1);
5576 
5577  if (state2 == NULL)
5578  PG_RETURN_POINTER(state1);
5579 
5580  /* manually copy all fields from state2 to state1 */
5581  if (state1 == NULL)
5582  {
5583  old_context = MemoryContextSwitchTo(agg_context);
5584 
5585  state1 = makePolyNumAggState(fcinfo, true);
5586  state1->N = state2->N;
5587 
5588 #ifdef HAVE_INT128
5589  state1->sumX = state2->sumX;
5590  state1->sumX2 = state2->sumX2;
5591 #else
5592  accum_sum_copy(&state1->sumX, &state2->sumX);
5593  accum_sum_copy(&state1->sumX2, &state2->sumX2);
5594 #endif
5595 
5596  MemoryContextSwitchTo(old_context);
5597 
5598  PG_RETURN_POINTER(state1);
5599  }
5600 
5601  if (state2->N > 0)
5602  {
5603  state1->N += state2->N;
5604 
5605 #ifdef HAVE_INT128
5606  state1->sumX += state2->sumX;
5607  state1->sumX2 += state2->sumX2;
5608 #else
5609  /* The rest of this needs to work in the aggregate context */
5610  old_context = MemoryContextSwitchTo(agg_context);
5611 
5612  /* Accumulate sums */
5613  accum_sum_combine(&state1->sumX, &state2->sumX);
5614  accum_sum_combine(&state1->sumX2, &state2->sumX2);
5615 
5616  MemoryContextSwitchTo(old_context);
5617 #endif
5618 
5619  }
5620  PG_RETURN_POINTER(state1);
5621 }

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

5688 {
5689  bytea *sstate;
5690  PolyNumAggState *result;
5692  NumericVar tmp_var;
5693 
5694  if (!AggCheckCallContext(fcinfo, NULL))
5695  elog(ERROR, "aggregate function called in non-aggregate context");
5696 
5697  sstate = PG_GETARG_BYTEA_PP(0);
5698 
5699  init_var(&tmp_var);
5700 
5701  /*
5702  * Initialize a StringInfo so that we can "receive" it using the standard
5703  * recv-function infrastructure.
5704  */
5706  VARSIZE_ANY_EXHDR(sstate));
5707 
5708  result = makePolyNumAggStateCurrentContext(false);
5709 
5710  /* N */
5711  result->N = pq_getmsgint64(&buf);
5712 
5713  /* sumX */
5714  numericvar_deserialize(&buf, &tmp_var);
5715 #ifdef HAVE_INT128
5716  numericvar_to_int128(&tmp_var, &result->sumX);
5717 #else
5718  accum_sum_add(&result->sumX, &tmp_var);
5719 #endif
5720 
5721  /* sumX2 */
5722  numericvar_deserialize(&buf, &tmp_var);
5723 #ifdef HAVE_INT128
5724  numericvar_to_int128(&tmp_var, &result->sumX2);
5725 #else
5726  accum_sum_add(&result->sumX2, &tmp_var);
5727 #endif
5728 
5729  pq_getmsgend(&buf);
5730 
5731  free_var(&tmp_var);
5732 
5733  PG_RETURN_POINTER(result);
5734 }

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

5630 {
5633  bytea *result;
5634  NumericVar tmp_var;
5635 
5636  /* Ensure we disallow calling when not in aggregate context */
5637  if (!AggCheckCallContext(fcinfo, NULL))
5638  elog(ERROR, "aggregate function called in non-aggregate context");
5639 
5641 
5642  /*
5643  * If the platform supports int128 then sumX and sumX2 will be a 128 bit
5644  * integer type. Here we'll convert that into a numeric type so that the
5645  * combine state is in the same format for both int128 enabled machines
5646  * and machines which don't support that type. The logic here is that one
5647  * day we might like to send these over to another server for further
5648  * processing and we want a standard format to work with.
5649  */
5650 
5651  init_var(&tmp_var);
5652 
5653  pq_begintypsend(&buf);
5654 
5655  /* N */
5656  pq_sendint64(&buf, state->N);
5657 
5658  /* sumX */
5659 #ifdef HAVE_INT128
5660  int128_to_numericvar(state->sumX, &tmp_var);
5661 #else
5662  accum_sum_final(&state->sumX, &tmp_var);
5663 #endif
5664  numericvar_serialize(&buf, &tmp_var);
5665 
5666  /* sumX2 */
5667 #ifdef HAVE_INT128
5668  int128_to_numericvar(state->sumX2, &tmp_var);
5669 #else
5670  accum_sum_final(&state->sumX2, &tmp_var);
5671 #endif
5672  numericvar_serialize(&buf, &tmp_var);
5673 
5674  result = pq_endtypsend(&buf);
5675 
5676  free_var(&tmp_var);
5677 
5678  PG_RETURN_BYTEA_P(result);
5679 }

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

6416 {
6417 #ifdef HAVE_INT128
6419  Numeric res;
6420  bool is_null;
6421 
6422  state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
6423 
6424  res = numeric_poly_stddev_internal(state, false, false, &is_null);
6425 
6426  if (is_null)
6427  PG_RETURN_NULL();
6428  else
6430 #else
6431  return numeric_stddev_pop(fcinfo);
6432 #endif
6433 }
Datum numeric_stddev_pop(PG_FUNCTION_ARGS)
Definition: numeric.c:6289

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

6374 {
6375 #ifdef HAVE_INT128
6377  Numeric res;
6378  bool is_null;
6379 
6380  state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
6381 
6382  res = numeric_poly_stddev_internal(state, false, true, &is_null);
6383 
6384  if (is_null)
6385  PG_RETURN_NULL();
6386  else
6388 #else
6389  return numeric_stddev_samp(fcinfo);
6390 #endif
6391 }
Datum numeric_stddev_samp(PG_FUNCTION_ARGS)
Definition: numeric.c:6255

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

6019 {
6020 #ifdef HAVE_INT128
6022  Numeric res;
6023  NumericVar result;
6024 
6025  state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
6026 
6027  /* If there were no non-null inputs, return NULL */
6028  if (state == NULL || state->N == 0)
6029  PG_RETURN_NULL();
6030 
6031  init_var(&result);
6032 
6033  int128_to_numericvar(state->sumX, &result);
6034 
6035  res = make_result(&result);
6036 
6037  free_var(&result);
6038 
6040 #else
6041  return numeric_sum(fcinfo);
6042 #endif
6043 }
Datum numeric_sum(PG_FUNCTION_ARGS)
Definition: numeric.c:6111

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

6395 {
6396 #ifdef HAVE_INT128
6398  Numeric res;
6399  bool is_null;
6400 
6401  state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
6402 
6403  res = numeric_poly_stddev_internal(state, true, false, &is_null);
6404 
6405  if (is_null)
6406  PG_RETURN_NULL();
6407  else
6409 #else
6410  return numeric_var_pop(fcinfo);
6411 #endif
6412 }
Datum numeric_var_pop(PG_FUNCTION_ARGS)
Definition: numeric.c:6272

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

6353 {
6354 #ifdef HAVE_INT128
6356  Numeric res;
6357  bool is_null;
6358 
6359  state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
6360 
6361  res = numeric_poly_stddev_internal(state, true, true, &is_null);
6362 
6363  if (is_null)
6364  PG_RETURN_NULL();
6365  else
6367 #else
6368  return numeric_var_samp(fcinfo);
6369 #endif
6370 }
Datum numeric_var_samp(PG_FUNCTION_ARGS)
Definition: numeric.c:6238

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

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

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

Referenced by numeric_to_char(), and numeric_to_number().

◆ numeric_recv()

Datum numeric_recv ( PG_FUNCTION_ARGS  )

Definition at line 1067 of file numeric.c.

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

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

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

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

◆ numeric_scale()

Datum numeric_scale ( PG_FUNCTION_ARGS  )

Definition at line 4120 of file numeric.c.

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

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

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

5263 {
5266  bytea *result;
5267  NumericVar tmp_var;
5268 
5269  /* Ensure we disallow calling when not in aggregate context */
5270  if (!AggCheckCallContext(fcinfo, NULL))
5271  elog(ERROR, "aggregate function called in non-aggregate context");
5272 
5274 
5275  init_var(&tmp_var);
5276 
5277  pq_begintypsend(&buf);
5278 
5279  /* N */
5280  pq_sendint64(&buf, state->N);
5281 
5282  /* sumX */
5283  accum_sum_final(&state->sumX, &tmp_var);
5284  numericvar_serialize(&buf, &tmp_var);
5285 
5286  /* sumX2 */
5287  accum_sum_final(&state->sumX2, &tmp_var);
5288  numericvar_serialize(&buf, &tmp_var);
5289 
5290  /* maxScale */
5291  pq_sendint32(&buf, state->maxScale);
5292 
5293  /* maxScaleCount */
5294  pq_sendint64(&buf, state->maxScaleCount);
5295 
5296  /* NaNcount */
5297  pq_sendint64(&buf, state->NaNcount);
5298 
5299  /* pInfcount */
5300  pq_sendint64(&buf, state->pInfcount);
5301 
5302  /* nInfcount */
5303  pq_sendint64(&buf, state->nInfcount);
5304 
5305  result = pq_endtypsend(&buf);
5306 
5307  free_var(&tmp_var);
5308 
5309  PG_RETURN_BYTEA_P(result);
5310 }

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

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

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

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

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

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

References cmp_numerics(), PG_GETARG_NUMERIC, and PG_RETURN_NUMERIC.

◆ numeric_sortsupport()

Datum numeric_sortsupport ( PG_FUNCTION_ARGS  )

Definition at line 2003 of file numeric.c.

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

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

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

6157 {
6158  Numeric res;
6159  NumericVar vN,
6160  vsumX,
6161  vsumX2,
6162  vNminus1;
6163  int64 totCount;
6164  int rscale;
6165 
6166  /*
6167  * Sample stddev and variance are undefined when N <= 1; population stddev
6168  * is undefined when N == 0. Return NULL in either case (note that NaNs
6169  * and infinities count as normal inputs for this purpose).
6170  */
6171  if (state == NULL || (totCount = NA_TOTAL_COUNT(state)) == 0)
6172  {
6173  *is_null = true;
6174  return NULL;
6175  }
6176 
6177  if (sample && totCount <= 1)
6178  {
6179  *is_null = true;
6180  return NULL;
6181  }
6182 
6183  *is_null = false;
6184 
6185  /*
6186  * Deal with NaN and infinity cases. By analogy to the behavior of the
6187  * float8 functions, any infinity input produces NaN output.
6188  */
6189  if (state->NaNcount > 0 || state->pInfcount > 0 || state->nInfcount > 0)
6190  return make_result(&const_nan);
6191 
6192  /* OK, normal calculation applies */
6193  init_var(&vN);
6194  init_var(&vsumX);
6195  init_var(&vsumX2);
6196 
6197  int64_to_numericvar(state->N, &vN);
6198  accum_sum_final(&(state->sumX), &vsumX);
6199  accum_sum_final(&(state->sumX2), &vsumX2);
6200 
6201  init_var(&vNminus1);
6202  sub_var(&vN, &const_one, &vNminus1);
6203 
6204  /* compute rscale for mul_var calls */
6205  rscale = vsumX.dscale * 2;
6206 
6207  mul_var(&vsumX, &vsumX, &vsumX, rscale); /* vsumX = sumX * sumX */
6208  mul_var(&vN, &vsumX2, &vsumX2, rscale); /* vsumX2 = N * sumX2 */
6209  sub_var(&vsumX2, &vsumX, &vsumX2); /* N * sumX2 - sumX * sumX */
6210 
6211  if (cmp_var(&vsumX2, &const_zero) <= 0)
6212  {
6213  /* Watch out for roundoff error producing a negative numerator */
6215  }
6216  else
6217  {
6218  if (sample)
6219  mul_var(&vN, &vNminus1, &vNminus1, 0); /* N * (N - 1) */
6220  else
6221  mul_var(&vN, &vN, &vNminus1, 0); /* N * N */
6222  rscale = select_div_scale(&vsumX2, &vNminus1);
6223  div_var(&vsumX2, &vNminus1, &vsumX, rscale, true); /* variance */
6224  if (!variance)
6225  sqrt_var(&vsumX, &vsumX, rscale); /* stddev */
6226 
6227  res = make_result(&vsumX);
6228  }
6229 
6230  free_var(&vNminus1);
6231  free_var(&vsumX);
6232  free_var(&vsumX2);
6233 
6234  return res;
6235 }

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

6290 {
6292  Numeric res;
6293  bool is_null;
6294 
6295  state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
6296 
6297  res = numeric_stddev_internal(state, false, false, &is_null);
6298 
6299  if (is_null)
6300  PG_RETURN_NULL();
6301  else
6303 }
static Numeric numeric_stddev_internal(NumericAggState *state, bool variance, bool sample, bool *is_null)
Definition: numeric.c:6154

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

6256 {
6258  Numeric res;
6259  bool is_null;
6260 
6261  state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
6262 
6263  res = numeric_stddev_internal(state, false, true, &is_null);
6264 
6265  if (is_null)
6266  PG_RETURN_NULL();
6267  else
6269 }

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

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

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

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

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

6112 {
6114  NumericVar sumX_var;
6115  Numeric result;
6116 
6117  state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
6118 
6119  /* If there were no non-null inputs, return NULL */
6120  if (state == NULL || NA_TOTAL_COUNT(state) == 0)
6121  PG_RETURN_NULL();
6122 
6123  if (state->NaNcount > 0) /* there was at least one NaN input */
6125 
6126  /* adding plus and minus infinities gives NaN */
6127  if (state->pInfcount > 0 && state->nInfcount > 0)
6129  if (state->pInfcount > 0)
6131  if (state->nInfcount > 0)
6133 
6134  init_var(&sumX_var);
6135  accum_sum_final(&state->sumX, &sumX_var);
6136  result = make_result(&sumX_var);
6137  free_var(&sumX_var);
6138 
6139  PG_RETURN_NUMERIC(result);
6140 }

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

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

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

◆ numeric_trim_scale()

Datum numeric_trim_scale ( PG_FUNCTION_ARGS  )

Definition at line 4205 of file numeric.c.

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

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

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

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

Referenced by getArrayIndex().

◆ numeric_typmod_precision()

static int numeric_typmod_precision ( int32  typmod)
inlinestatic

Definition at line 916 of file numeric.c.

917 {
918  return ((typmod - VARHDRSZ) >> 16) & 0xffff;
919 }

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

932 {
933  return (((typmod - VARHDRSZ) & 0x7ff) ^ 1024) - 1024;
934 }

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

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

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

1452 {
1453  Numeric num = PG_GETARG_NUMERIC(0);
1454 
1456 }

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

6273 {
6275  Numeric res;
6276  bool is_null;
6277 
6278  state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
6279 
6280  res = numeric_stddev_internal(state, true, false, &is_null);
6281 
6282  if (is_null)
6283  PG_RETURN_NULL();
6284  else
6286 }

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

6239 {
6241  Numeric res;
6242  bool is_null;
6243 
6244  state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
6245 
6246  res = numeric_stddev_internal(state, true, true, &is_null);
6247 
6248  if (is_null)
6249  PG_RETURN_NULL();
6250  else
6252 }

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

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

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

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

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

7689 {
7690  int len,
7691  i;
7692 
7693  len = pq_getmsgint(buf, sizeof(int32));
7694 
7695  alloc_var(var, len); /* sets var->ndigits */
7696 
7697  var->weight = pq_getmsgint(buf, sizeof(int32));
7698  var->sign = pq_getmsgint(buf, sizeof(int32));
7699  var->dscale = pq_getmsgint(buf, sizeof(int32));
7700  for (i = 0; i < len; i++)
7701  var->digits[i] = pq_getmsgint(buf, sizeof(int16));
7702 }

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

7673 {
7674  int i;
7675 
7676  pq_sendint32(buf, var->ndigits);
7677  pq_sendint32(buf, var->weight);
7678  pq_sendint32(buf, var->sign);
7679  pq_sendint32(buf, var->dscale);
7680  for (i = 0; i < var->ndigits; i++)
7681  pq_sendint16(buf, var->digits[i]);
7682 }

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

8290 {
8291  char *tmp;
8292  double val;
8293  char *endptr;
8294 
8295  tmp = get_str_from_var(var);
8296 
8297  /* unlike float8in, we ignore ERANGE from strtod */
8298  val = strtod(tmp, &endptr);
8299  if (*endptr != '\0')
8300  {
8301  /* shouldn't happen ... */
8302  ereport(ERROR,
8303  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
8304  errmsg("invalid input syntax for type %s: \"%s\"",
8305  "double precision", tmp)));
8306  }
8307 
8308  pfree(tmp);
8309 
8310  return val;
8311 }

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

4409 {
4410  int64 val;
4411 
4412  if (!numericvar_to_int64(var, &val))
4413  return false;
4414 
4416  return false;
4417 
4418  /* Down-convert to int4 */
4419  *result = (int32) val;
4420 
4421  return true;
4422 }
#define PG_INT32_MAX
Definition: c.h:576
#define PG_INT32_MIN
Definition: c.h:575

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

Referenced by numeric_int4_opt_error(), and width_bucket_numeric().

◆ numericvar_to_int64()

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

Definition at line 7977 of file numeric.c.

7978 {
7980  int ndigits;
7981  int weight;
7982  int i;
7983  int64 val;
7984  bool neg;
7985  NumericVar rounded;
7986 
7987  /* Round to nearest integer */
7988  init_var(&rounded);
7989  set_var_from_var(var, &rounded);
7990  round_var(&rounded, 0);
7991 
7992  /* Check for zero input */
7993  strip_var(&rounded);
7994  ndigits = rounded.ndigits;
7995  if (ndigits == 0)
7996  {
7997  *result = 0;
7998  free_var(&rounded);
7999  return true;
8000  }
8001 
8002  /*
8003  * For input like 10000000000, we must treat stripped digits as real. So
8004  * the loop assumes there are weight+1 digits before the decimal point.
8005  */
8006  weight = rounded.weight;
8007  Assert(weight >= 0 && ndigits <= weight + 1);
8008 
8009  /*
8010  * Construct the result. To avoid issues with converting a value
8011  * corresponding to INT64_MIN (which can't be represented as a positive 64
8012  * bit two's complement integer), accumulate value as a negative number.
8013  */
8014  digits = rounded.digits;
8015  neg = (rounded.sign == NUMERIC_NEG);
8016  val = -digits[0];
8017  for (i = 1; i <= weight; i++)
8018  {
8020  {
8021  free_var(&rounded);
8022  return false;
8023  }
8024 
8025  if (i < ndigits)
8026  {
8028  {
8029  free_var(&rounded);
8030  return false;
8031  }
8032  }
8033  }
8034 
8035  free_var(&rounded);
8036 
8037  if (!neg)
8038  {
8039  if (unlikely(val == PG_INT64_MIN))
8040  return false;
8041  val = -val;
8042  }
8043  *result = val;
8044 
8045  return true;
8046 }
#define PG_INT64_MIN
Definition: c.h:578
static bool pg_sub_s64_overflow(int64 a, int64 b, int64 *result)
Definition: int.h:188

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

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

◆ numericvar_to_uint64()

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

Definition at line 8099 of file numeric.c.

8100 {
8102  int ndigits;
8103  int weight;
8104  int i;
8105  uint64 val;
8106  NumericVar rounded;
8107 
8108  /* Round to nearest integer */
8109  init_var(&rounded);
8110  set_var_from_var(var, &rounded);
8111  round_var(&rounded, 0);
8112 
8113  /* Check for zero input */
8114  strip_var(&rounded);
8115  ndigits = rounded.ndigits;
8116  if (ndigits == 0)
8117  {
8118  *result = 0;
8119  free_var(&rounded);
8120  return true;
8121  }
8122 
8123  /* Check for negative input */
8124  if (rounded.sign == NUMERIC_NEG)
8125  {
8126  free_var(&rounded);
8127  return false;
8128  }
8129 
8130  /*
8131  * For input like 10000000000, we must treat stripped digits as real. So
8132  * the loop assumes there are weight+1 digits before the decimal point.
8133  */
8134  weight = rounded.weight;
8135  Assert(weight >= 0 && ndigits <= weight + 1);
8136 
8137  /* Construct the result */
8138  digits = rounded.digits;
8139  val = digits[0];
8140  for (i = 1; i <= weight; i++)
8141  {
8143  {
8144  free_var(&rounded);
8145  return false;
8146  }
8147 
8148  if (i < ndigits)
8149  {
8151  {
8152  free_var(&rounded);
8153  return false;
8154  }
8155  }
8156  }
8157 
8158  free_var(&rounded);
8159 
8160  *result = val;
8161 
8162  return true;
8163 }
static bool pg_add_u64_overflow(uint64 a, uint64 b, uint64 *result)
Definition: int.h:380
static bool pg_mul_u64_overflow(uint64 a, uint64 b, uint64 *result)
Definition: int.h:414

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

Referenced by numeric_pg_lsn().

◆ power_ten_int()

static void power_ten_int ( int  exp,
NumericVar result 
)
static

Definition at line 11244 of file numeric.c.

11245 {
11246  /* Construct the result directly, starting from 10^0 = 1 */
11247  set_var_from_var(&const_one, result);
11248 
11249  /* Scale needed to represent the result exactly */
11250  result->dscale = exp < 0 ? -exp : 0;
11251 
11252  /* Base-NBASE weight of result and remaining exponent */
11253  if (exp >= 0)
11254  result->weight = exp / DEC_DIGITS;
11255  else
11256  result->weight = (exp + 1) / DEC_DIGITS - 1;
11257 
11258  exp -= result->weight * DEC_DIGITS;
11259 
11260  /* Final adjustment of the result's single NBASE digit */
11261  while (exp-- > 0)
11262  result->digits[0] *= 10;
11263 }

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

10880 {
10881  int res_sign;
10882  NumericVar abs_base;
10883  NumericVar ln_base;
10884  NumericVar ln_num;
10885  int ln_dweight;
10886  int rscale;
10887  int sig_digits;
10888  int local_rscale;
10889  double val;
10890 
10891  /* If exp can be represented as an integer, use power_var_int */
10892  if (exp->ndigits == 0 || exp->ndigits <= exp->weight + 1)
10893  {
10894  /* exact integer, but does it fit in int? */
10895  int64 expval64;
10896 
10897  if (numericvar_to_int64(exp, &expval64))
10898  {
10899  if (expval64 >= PG_INT32_MIN && expval64 <= PG_INT32_MAX)
10900  {
10901  /* Okay, use power_var_int */
10902  power_var_int(base, (int) expval64, exp->dscale, result);
10903  return;
10904  }
10905  }
10906  }
10907 
10908  /*
10909  * This avoids log(0) for cases of 0 raised to a non-integer. 0 ^ 0 is
10910  * handled by power_var_int().
10911  */
10912  if (cmp_var(base, &const_zero) == 0)
10913  {
10914  set_var_from_var(&const_zero, result);
10915  result->dscale = NUMERIC_MIN_SIG_DIGITS; /* no need to round */
10916  return;
10917  }
10918 
10919  init_var(&abs_base);
10920  init_var(&ln_base);
10921  init_var(&ln_num);
10922 
10923  /*
10924  * If base is negative, insist that exp be an integer. The result is then
10925  * positive if exp is even and negative if exp is odd.
10926  */
10927  if (base->sign == NUMERIC_NEG)
10928  {
10929  /*
10930  * Check that exp is an integer. This error code is defined by the
10931  * SQL standard, and matches other errors in numeric_power().
10932  */
10933  if (exp->ndigits > 0 && exp->ndigits > exp->weight + 1)
10934  ereport(ERROR,
10935  (errcode(ERRCODE_INVALID_ARGUMENT_FOR_POWER_FUNCTION),
10936  errmsg("a negative number raised to a non-integer power yields a complex result")));
10937 
10938  /* Test if exp is odd or even */
10939  if (exp->ndigits > 0 && exp->ndigits == exp->weight + 1 &&
10940  (exp->digits[exp->ndigits - 1] & 1))
10941  res_sign = NUMERIC_NEG;
10942  else
10943  res_sign = NUMERIC_POS;
10944 
10945  /* Then work with abs(base) below */
10946  set_var_from_var(base, &abs_base);
10947  abs_base.sign = NUMERIC_POS;
10948  base = &abs_base;
10949  }
10950  else
10951  res_sign = NUMERIC_POS;
10952 
10953  /*----------
10954  * Decide on the scale for the ln() calculation. For this we need an
10955  * estimate of the weight of the result, which we obtain by doing an
10956  * initial low-precision calculation of exp * ln(base).
10957  *
10958  * We want result = e ^ (exp * ln(base))
10959  * so result dweight = log10(result) = exp * ln(base) * log10(e)
10960  *
10961  * We also perform a crude overflow test here so that we can exit early if
10962  * the full-precision result is sure to overflow, and to guard against
10963  * integer overflow when determining the scale for the real calculation.
10964  * exp_var() supports inputs up to NUMERIC_MAX_RESULT_SCALE * 3, so the
10965  * result will overflow if exp * ln(base) >= NUMERIC_MAX_RESULT_SCALE * 3.
10966  * Since the values here are only approximations, we apply a small fuzz
10967  * factor to this overflow test and let exp_var() determine the exact
10968  * overflow threshold so that it is consistent for all inputs.
10969  *----------
10970  */
10971  ln_dweight = estimate_ln_dweight(base);
10972 
10973  /*
10974  * Set the scale for the low-precision calculation, computing ln(base) to
10975  * around 8 significant digits. Note that ln_dweight may be as small as
10976  * -SHRT_MAX, so the scale may exceed NUMERIC_MAX_DISPLAY_SCALE here.
10977  */
10978  local_rscale = 8 - ln_dweight;
10979  local_rscale = Max(local_rscale, NUMERIC_MIN_DISPLAY_SCALE);
10980 
10981  ln_var(base, &ln_base, local_rscale);
10982 
10983  mul_var(&ln_base, exp, &ln_num, local_rscale);
10984 
10986 
10987  /* initial overflow/underflow test with fuzz factor */
10988  if (fabs(val) > NUMERIC_MAX_RESULT_SCALE * 3.01)
10989  {
10990  if (val > 0)
10991  ereport(ERROR,
10992  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
10993  errmsg("value overflows numeric format")));
10994  zero_var(result);
10996  return;
10997  }
10998 
10999  val *= 0.434294481903252; /* approximate decimal result weight */
11000 
11001  /* choose the result scale */
11002  rscale = NUMERIC_MIN_SIG_DIGITS - (int) val;
11003  rscale = Max(rscale, base->dscale);
11004  rscale = Max(rscale, exp->dscale);
11005  rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
11006  rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
11007 
11008  /* significant digits required in the result */
11009  sig_digits = rscale + (int) val;
11010  sig_digits = Max(sig_digits, 0);
11011 
11012  /* set the scale for the real exp * ln(base) calculation */
11013  local_rscale = sig_digits - ln_dweight + 8;
11014  local_rscale = Max(local_rscale, NUMERIC_MIN_DISPLAY_SCALE);
11015 
11016  /* and do the real calculation */
11017 
11018  ln_var(base, &ln_base, local_rscale);
11019 
11020  mul_var(&ln_base, exp, &ln_num, local_rscale);
11021 
11022  exp_var(&ln_num, result, rscale);
11023 
11024  if (res_sign == NUMERIC_NEG && result->ndigits > 0)
11025  result->sign = NUMERIC_NEG;
11026 
11027  free_var(&ln_num);
11028  free_var(&ln_base);
11029  free_var(&abs_base);
11030 }
static void power_var_int(const NumericVar *base, int exp, int exp_dscale, NumericVar *result)
Definition: numeric.c:11040

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

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

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

Referenced by power_var().

◆ round_var()

static void round_var ( NumericVar var,
int  rscale 
)
static

Definition at line 11530 of file numeric.c.

11531 {
11532  NumericDigit *digits = var->digits;
11533  int di;
11534  int ndigits;
11535  int carry;
11536 
11537  var->dscale = rscale;
11538 
11539  /* decimal digits wanted */
11540  di = (var->weight + 1) * DEC_DIGITS + rscale;
11541 
11542  /*
11543  * If di = 0, the value loses all digits, but could round up to 1 if its
11544  * first extra digit is >= 5. If di < 0 the result must be 0.
11545  */
11546  if (di < 0)
11547  {
11548  var->ndigits = 0;
11549  var->weight = 0;
11550  var->sign = NUMERIC_POS;
11551  }
11552  else
11553  {
11554  /* NBASE digits wanted */
11555  ndigits = (di + DEC_DIGITS - 1) / DEC_DIGITS;
11556 
11557  /* 0, or number of decimal digits to keep in last NBASE digit */
11558  di %= DEC_DIGITS;
11559 
11560  if (ndigits < var->ndigits ||
11561  (ndigits == var->ndigits && di > 0))
11562  {
11563  var->ndigits = ndigits;
11564 
11565 #if DEC_DIGITS == 1
11566  /* di must be zero */
11567  carry = (digits[ndigits] >= HALF_NBASE) ? 1 : 0;
11568 #else
11569  if (di == 0)
11570  carry = (digits[ndigits] >= HALF_NBASE) ? 1 : 0;
11571  else
11572  {
11573  /* Must round within last NBASE digit */
11574  int extra,
11575  pow10;
11576 
11577 #if DEC_DIGITS == 4
11578  pow10 = round_powers[di];
11579 #elif DEC_DIGITS == 2
11580  pow10 = 10;
11581 #else
11582 #error unsupported NBASE
11583 #endif
11584  extra = digits[--ndigits] % pow10;
11585  digits[ndigits] -= extra;
11586  carry = 0;
11587  if (extra >= pow10 / 2)
11588  {
11589  pow10 += digits[ndigits];
11590  if (pow10 >= NBASE)
11591  {
11592  pow10 -= NBASE;
11593  carry = 1;
11594  }
11595  digits[ndigits] = pow10;
11596  }
11597  }
11598 #endif
11599 
11600  /* Propagate carry if needed */
11601  while (carry)
11602  {
11603  carry += digits[--ndigits];
11604  if (carry >= NBASE)
11605  {
11606  digits[ndigits] = carry - NBASE;
11607  carry = 1;
11608  }
11609  else
11610  {
11611  digits[ndigits] = carry;
11612  carry = 0;
11613  }
11614  }
11615 
11616  if (ndigits < 0)
11617  {
11618  Assert(ndigits == -1); /* better not have added > 1 digit */
11619  Assert(var->digits > var->buf);
11620  var->digits--;
11621  var->ndigits++;
11622  var->weight++;
11623  }
11624  }
11625  }
11626 }
static const int round_powers[4]
Definition: numeric.c:459

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

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

◆ select_div_scale()

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

Definition at line 9725 of file numeric.c.

9726 {
9727  int weight1,
9728  weight2,
9729  qweight,
9730  i;
9731  NumericDigit firstdigit1,
9732  firstdigit2;
9733  int rscale;
9734 
9735  /*
9736  * The result scale of a division isn't specified in any SQL standard. For
9737  * PostgreSQL we select a result scale that will give at least
9738  * NUMERIC_MIN_SIG_DIGITS significant digits, so that numeric gives a
9739  * result no less accurate than float8; but use a scale not less than
9740  * either input's display scale.
9741  */
9742 
9743  /* Get the actual (normalized) weight and first digit of each input */
9744 
9745  weight1 = 0; /* values to use if var1 is zero */
9746  firstdigit1 = 0;
9747  for (i = 0; i < var1->ndigits; i++)
9748  {
9749  firstdigit1 = var1->digits[i];
9750  if (firstdigit1 != 0)
9751  {
9752  weight1 = var1->weight - i;
9753  break;
9754  }
9755  }
9756 
9757  weight2 = 0; /* values to use if var2 is zero */
9758  firstdigit2 = 0;
9759  for (i = 0; i < var2->ndigits; i++)
9760  {
9761  firstdigit2 = var2->digits[i];
9762  if (firstdigit2 != 0)
9763  {
9764  weight2 = var2->weight - i;
9765  break;
9766  }
9767  }
9768 
9769  /*
9770  * Estimate weight of quotient. If the two first digits are equal, we
9771  * can't be sure, but assume that var1 is less than var2.
9772  */
9773  qweight = weight1 - weight2;
9774  if (firstdigit1 <= firstdigit2)
9775  qweight--;
9776 
9777  /* Select result scale */
9778  rscale = NUMERIC_MIN_SIG_DIGITS - qweight * DEC_DIGITS;
9779  rscale = Max(rscale, var1->dscale);
9780  rscale = Max(rscale, var2->dscale);
9781  rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
9782  rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
9783 
9784  return rscale;
9785 }

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

Referenced by compute_bucket(), numeric_div_opt_error(), and numeric_stddev_internal().

◆ set_var_from_non_decimal_integer_str()

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

Definition at line 7190 of file numeric.c.

7193 {
7194  const char *firstdigit = cp;
7195  int64 tmp;
7196  int64 mul;
7197  NumericVar tmp_var;
7198 
7199  init_var(&tmp_var);
7200 
7201  zero_var(dest);
7202 
7203  /*
7204  * Process input digits in groups that fit in int64. Here "tmp" is the
7205  * value of the digits in the group, and "mul" is base^n, where n is the
7206  * number of digits in the group. Thus tmp < mul, and we must start a new
7207  * group when mul * base threatens to overflow PG_INT64_MAX.
7208  */
7209  tmp = 0;
7210  mul = 1;
7211 
7212  if (base == 16)
7213  {
7214  while (*cp)
7215  {
7216  if (isxdigit((unsigned char) *cp))
7217  {
7218  if (mul > PG_INT64_MAX / 16)
7219  {
7220  /* Add the contribution from this group of digits */
7221  int64_to_numericvar(mul, &tmp_var);
7222  mul_var(dest, &tmp_var, dest, 0);
7223  int64_to_numericvar(tmp, &tmp_var);
7224  add_var(dest, &tmp_var, dest);
7225 
7226  /* Result will overflow if weight overflows int16 */
7227  if (dest->weight > SHRT_MAX)
7228  goto out_of_range;
7229 
7230  /* Begin a new group */
7231  tmp = 0;
7232  mul = 1;
7233  }
7234 
7235  tmp = tmp * 16 + xdigit_value(*cp++);
7236  mul = mul * 16;
7237  }
7238  else if (*cp == '_')
7239  {
7240  /* Underscore must be followed by more digits */
7241  cp++;
7242  if (!isxdigit((unsigned char) *cp))
7243  goto invalid_syntax;
7244  }
7245  else
7246  break;
7247  }
7248  }
7249  else if (base == 8)
7250  {
7251  while (*cp)
7252  {
7253  if (*cp >= '0' && *cp <= '7')
7254  {
7255  if (mul > PG_INT64_MAX / 8)
7256  {
7257  /* Add the contribution from this group of digits */
7258  int64_to_numericvar(mul, &tmp_var);
7259  mul_var(dest, &tmp_var, dest, 0);
7260  int64_to_numericvar(tmp, &tmp_var);
7261  add_var(dest, &tmp_var, dest);
7262 
7263  /* Result will overflow if weight overflows int16 */
7264  if (dest->weight > SHRT_MAX)
7265  goto out_of_range;
7266 
7267  /* Begin a new group */
7268  tmp = 0;
7269  mul = 1;
7270  }
7271 
7272  tmp = tmp * 8 + (*cp++ - '0');
7273  mul = mul * 8;
7274  }
7275  else if (*cp == '_')
7276  {
7277  /* Underscore must be followed by more digits */
7278  cp++;
7279  if (*cp < '0' || *cp > '7')
7280  goto invalid_syntax;
7281  }
7282  else
7283  break;
7284  }
7285  }
7286  else if (base == 2)
7287  {
7288  while (*cp)
7289  {
7290  if (*cp >= '0' && *cp <= '1')
7291  {
7292  if (mul > PG_INT64_MAX / 2)
7293  {
7294  /* Add the contribution from this group of digits */
7295  int64_to_numericvar(mul, &tmp_var);
7296  mul_var(dest, &tmp_var, dest, 0);
7297  int64_to_numericvar(tmp, &tmp_var);
7298  add_var(dest, &tmp_var, dest);
7299 
7300  /* Result will overflow if weight overflows int16 */
7301  if (dest->weight > SHRT_MAX)
7302  goto out_of_range;
7303 
7304  /* Begin a new group */
7305  tmp = 0;
7306  mul = 1;
7307  }
7308 
7309  tmp = tmp * 2 + (*cp++ - '0');
7310  mul = mul * 2;
7311  }
7312  else if (*cp == '_')
7313  {
7314  /* Underscore must be followed by more digits */
7315  cp++;
7316  if (*cp < '0' || *cp > '1')
7317  goto invalid_syntax;
7318  }
7319  else
7320  break;
7321  }
7322  }
7323  else
7324  /* Should never happen; treat as invalid input */
7325  goto invalid_syntax;
7326 
7327  /* Check that we got at least one digit */
7328  if (unlikely(cp == firstdigit))
7329  goto invalid_syntax;
7330 
7331  /* Add the contribution from the final group of digits */
7332  int64_to_numericvar(mul, &tmp_var);
7333  mul_var(dest, &tmp_var, dest, 0);
7334  int64_to_numericvar(tmp, &tmp_var);
7335  add_var(dest, &tmp_var, dest);
7336 
7337  if (dest->weight > SHRT_MAX)
7338  goto out_of_range;
7339 
7340  dest->sign = sign;
7341 
7342  free_var(&tmp_var);
7343 
7344  /* Return end+1 position for caller */
7345  *endptr = cp;
7346 
7347  return true;
7348 
7349 out_of_range:
7350  ereturn(escontext, false,
7351  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
7352  errmsg("value overflows numeric format")));
7353 
7354 invalid_syntax:
7355  ereturn(escontext, false,
7356  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
7357  errmsg("invalid input syntax for type %s: \"%s\"",
7358  "numeric", str)));
7359 }
static int xdigit_value(char dig)
Definition: numeric.c:7163
#define PG_INT64_MAX
Definition: c.h:579

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

Referenced by numeric_in().

◆ set_var_from_num()

static void set_var_from_num ( Numeric  num,
NumericVar dest 
)
static

Definition at line 7368 of file numeric.c.

7369 {
7370  int ndigits;
7371 
7372  ndigits = NUMERIC_NDIGITS(num);
7373 
7374  alloc_var(dest, ndigits);
7375 
7376  dest->weight = NUMERIC_WEIGHT(num);
7377  dest->sign = NUMERIC_SIGN(num);
7378  dest->dscale = NUMERIC_DSCALE(num);
7379 
7380  memcpy(dest->digits, NUMERIC_DIGITS(num), ndigits * sizeof(NumericDigit));
7381 }

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

6963 {
6964  bool have_dp = false;
6965  int i;
6966  unsigned char *decdigits;
6967  int sign = NUMERIC_POS;
6968  int dweight = -1;
6969  int ddigits;
6970  int dscale = 0;
6971  int weight;
6972  int ndigits;
6973  int offset;
6975 
6976  /*
6977  * We first parse the string to extract decimal digits and determine the
6978  * correct decimal weight. Then convert to NBASE representation.
6979  */
6980  switch (*cp)
6981  {
6982  case '+':
6983  sign = NUMERIC_POS;
6984  cp++;
6985  break;
6986 
6987  case '-':
6988  sign = NUMERIC_NEG;
6989  cp++;
6990  break;
6991  }
6992 
6993  if (*cp == '.')
6994  {
6995  have_dp = true;
6996  cp++;
6997  }
6998 
6999  if (!isdigit((unsigned char) *cp))
7000  goto invalid_syntax;
7001 
7002  decdigits = (unsigned char *) palloc(strlen(cp) + DEC_DIGITS * 2);
7003 
7004  /* leading padding for digit alignment later */
7005  memset(decdigits, 0, DEC_DIGITS);
7006  i = DEC_DIGITS;
7007 
7008  while (*cp)
7009  {
7010  if (isdigit((unsigned char) *cp))
7011  {
7012  decdigits[i++] = *cp++ - '0';
7013  if (!have_dp)
7014  dweight++;
7015  else
7016  dscale++;
7017  }
7018  else if (*cp == '.')
7019  {
7020  if (have_dp)
7021  goto invalid_syntax;
7022  have_dp = true;
7023  cp++;
7024  /* decimal point must not be followed by underscore */
7025  if (*cp == '_')
7026  goto invalid_syntax;
7027  }
7028  else if (*cp == '_')
7029  {
7030  /* underscore must be followed by more digits */
7031  cp++;
7032  if (!isdigit((unsigned char) *cp))
7033  goto invalid_syntax;
7034  }
7035  else
7036  break;
7037  }
7038 
7039  ddigits = i - DEC_DIGITS;
7040  /* trailing padding for digit alignment later */
7041  memset(decdigits + i, 0, DEC_DIGITS - 1);
7042 
7043  /* Handle exponent, if any */
7044  if (*cp == 'e' || *cp == 'E')
7045  {
7046  int64 exponent = 0;
7047  bool neg = false;
7048 
7049  /*
7050  * At this point, dweight and dscale can't be more than about
7051  * INT_MAX/2 due to the MaxAllocSize limit on string length, so
7052  * constraining the exponent similarly should be enough to prevent
7053  * integer overflow in this function. If the value is too large to
7054  * fit in storage format, make_result() will complain about it later;
7055  * for consistency use the same ereport errcode/text as make_result().
7056  */
7057 
7058  /* exponent sign */
7059  cp++;
7060  if (*cp == '+')
7061  cp++;
7062  else if (*cp == '-')
7063  {
7064  neg = true;
7065  cp++;
7066  }
7067 
7068  /* exponent digits */
7069  if (!isdigit((unsigned char) *cp))
7070  goto invalid_syntax;
7071 
7072  while (*cp)
7073  {
7074  if (isdigit((unsigned char) *cp))
7075  {
7076  exponent = exponent * 10 + (*cp++ - '0');
7077  if (exponent > PG_INT32_MAX / 2)
7078  goto out_of_range;
7079  }
7080  else if (*cp == '_')
7081  {
7082  /* underscore must be followed by more digits */
7083  cp++;
7084  if (!isdigit((unsigned char) *cp))
7085  goto invalid_syntax;
7086  }
7087  else
7088  break;
7089  }
7090 
7091  if (neg)
7092  exponent = -exponent;
7093 
7094  dweight += (int) exponent;
7095  dscale -= (int) exponent;
7096  if (dscale < 0)
7097  dscale = 0;
7098  }
7099 
7100  /*
7101  * Okay, convert pure-decimal representation to base NBASE. First we need
7102  * to determine the converted weight and ndigits. offset is the number of
7103  * decimal zeroes to insert before the first given digit to have a
7104  * correctly aligned first NBASE digit.
7105  */
7106  if (dweight >= 0)
7107  weight = (dweight + 1 + DEC_DIGITS - 1) / DEC_DIGITS - 1;
7108  else
7109  weight = -((-dweight - 1) / DEC_DIGITS + 1);
7110  offset = (weight + 1) * DEC_DIGITS - (dweight + 1);
7111  ndigits = (ddigits + offset + DEC_DIGITS - 1) / DEC_DIGITS;
7112 
7113  alloc_var(dest, ndigits);
7114  dest->sign = sign;
7115  dest->weight = weight;
7116  dest->dscale = dscale;
7117 
7118  i = DEC_DIGITS - offset;
7119  digits = dest->digits;
7120 
7121  while (ndigits-- > 0)
7122  {
7123 #if DEC_DIGITS == 4
7124  *digits++ = ((decdigits[i] * 10 + decdigits[i + 1]) * 10 +
7125  decdigits[i + 2]) * 10 + decdigits[i + 3];
7126 #elif DEC_DIGITS == 2
7127  *digits++ = decdigits[i] * 10 + decdigits[i + 1];
7128 #elif DEC_DIGITS == 1
7129  *digits++ = decdigits[i];
7130 #else
7131 #error unsupported NBASE
7132 #endif
7133  i += DEC_DIGITS;
7134  }
7135 
7136  pfree(decdigits);
7137 
7138  /* Strip any leading/trailing zeroes, and normalize weight if zero */
7139  strip_var(dest);
7140 
7141  /* Return end+1 position for caller */
7142  *endptr = cp;
7143 
7144  return true;
7145 
7146 out_of_range:
7147  ereturn(escontext, false,
7148  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
7149  errmsg("value overflows numeric format")));
7150 
7151 invalid_syntax:
7152  ereturn(escontext, false,
7153  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
7154  errmsg("invalid input syntax for type %s: \"%s\"",
7155  "numeric", str)));
7156 }

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

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

◆ set_var_from_var()

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

Definition at line 7416 of file numeric.c.

7417 {
7418  NumericDigit *newbuf;
7419 
7420  newbuf = digitbuf_alloc(value->ndigits + 1);
7421  newbuf[0] = 0; /* spare digit for rounding */
7422  if (value->ndigits > 0) /* else value->digits might be null */
7423  memcpy(newbuf + 1, value->digits,
7424  value->ndigits * sizeof(NumericDigit));
7425 
7426  digitbuf_free(dest->buf);
7427 
7428  memmove(dest, value, sizeof(NumericVar));
7429  dest->buf = newbuf;
7430  dest->digits = newbuf + 1;
7431 }

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

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

◆ sqrt_var()

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

Definition at line 10010 of file numeric.c.

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

11699 {
11700  NumericDigit *digits = var->digits;
11701  int ndigits = var->ndigits;
11702 
11703  /* Strip leading zeroes */
11704  while (ndigits > 0 && *digits == 0)
11705  {
11706  digits++;
11707  var->weight--;
11708  ndigits--;
11709  }
11710 
11711  /* Strip trailing zeroes */
11712  while (ndigits > 0 && digits[ndigits - 1] == 0)
11713  ndigits--;
11714 
11715  /* If it's zero, normalize the sign and weight */
11716  if (ndigits == 0)
11717  {
11718  var->sign = NUMERIC_POS;
11719  var->weight = 0;
11720  }
11721 
11722  var->digits = digits;
11723  var->ndigits = ndigits;
11724 }

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

Referenced by accum_sum_final(), add_abs(), div_var(), div_var_fast(), div_var_int(), mul_var(), numericvar_to_int64(), numericvar_to_uint64(), 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 11448 of file numeric.c.

11449 {
11450  NumericDigit *res_buf;
11451  NumericDigit *res_digits;
11452  int res_ndigits;
11453  int res_weight;
11454  int res_rscale,
11455  rscale1,
11456  rscale2;
11457  int res_dscale;
11458  int i,
11459  i1,
11460  i2;
11461  int borrow = 0;
11462 
11463  /* copy these values into local vars for speed in inner loop */
11464  int var1ndigits = var1->ndigits;
11465  int var2ndigits = var2->ndigits;
11466  NumericDigit *var1digits = var1->digits;
11467  NumericDigit *var2digits = var2->digits;
11468 
11469  res_weight = var1->weight;
11470 
11471  res_dscale = Max(var1->dscale, var2->dscale);
11472 
11473  /* Note: here we are figuring rscale in base-NBASE digits */
11474  rscale1 = var1->ndigits - var1->weight - 1;
11475  rscale2 = var2->ndigits - var2->weight - 1;
11476  res_rscale = Max(rscale1, rscale2);
11477 
11478  res_ndigits = res_rscale + res_weight + 1;
11479  if (res_ndigits <= 0)
11480  res_ndigits = 1;
11481 
11482  res_buf = digitbuf_alloc(res_ndigits + 1);
11483  res_buf[0] = 0; /* spare digit for later rounding */
11484  res_digits = res_buf + 1;
11485 
11486  i1 = res_rscale + var1->weight + 1;
11487  i2 = res_rscale + var2->weight + 1;
11488  for (i = res_ndigits - 1; i >= 0; i--)
11489  {
11490  i1--;
11491  i2--;
11492  if (i1 >= 0 && i1 < var1ndigits)
11493  borrow += var1digits[i1];
11494  if (i2 >= 0 && i2 < var2ndigits)
11495  borrow -= var2digits[i2];
11496 
11497  if (borrow < 0)
11498  {
11499  res_digits[i] = borrow + NBASE;
11500  borrow = -1;
11501  }
11502  else
11503  {
11504  res_digits[i] = borrow;
11505  borrow = 0;
11506  }
11507  }
11508 
11509  Assert(borrow == 0); /* else caller gave us var1 < var2 */
11510 
11511  digitbuf_free(result->buf);
11512  result->ndigits = res_ndigits;
11513  result->buf = res_buf;
11514  result->digits = res_digits;
11515  result->weight = res_weight;
11516  result->dscale = res_dscale;
11517 
11518  /* Remove leading/trailing zeroes */
11519  strip_var(result);
11520 }

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

8497 {
8498  /*
8499  * Decide on the signs of the two variables what to do
8500  */
8501  if (var1->sign == NUMERIC_POS)
8502  {
8503  if (var2->sign == NUMERIC_NEG)
8504  {
8505  /* ----------
8506  * var1 is positive, var2 is negative
8507  * result = +(ABS(var1) + ABS(var2))
8508  * ----------
8509  */
8510  add_abs(var1, var2, result);
8511  result->sign = NUMERIC_POS;
8512  }
8513  else
8514  {
8515  /* ----------
8516  * Both are positive
8517  * Must compare absolute values
8518  * ----------
8519  */
8520  switch (cmp_abs(var1, var2))
8521  {
8522  case 0:
8523  /* ----------
8524  * ABS(var1) == ABS(var2)
8525  * result = ZERO
8526  * ----------
8527  */
8528  zero_var(result);
8529  result->dscale = Max(var1->dscale, var2->dscale);
8530  break;
8531 
8532  case 1:
8533  /* ----------
8534  * ABS(var1) > ABS(var2)
8535  * result = +(ABS(var1) - ABS(var2))
8536  * ----------
8537  */
8538  sub_abs(var1, var2, result);
8539  result->sign = NUMERIC_POS;
8540  break;
8541 
8542  case -1:
8543  /* ----------
8544  * ABS(var1) < ABS(var2)
8545  * result = -(ABS(var2) - ABS(var1))
8546  * ----------
8547  */
8548  sub_abs(var2, var1, result);
8549  result->sign = NUMERIC_NEG;
8550  break;
8551  }
8552  }
8553  }
8554  else
8555  {
8556  if (var2->sign == NUMERIC_NEG)
8557  {
8558  /* ----------
8559  * Both are negative
8560  * Must compare absolute values
8561  * ----------
8562  */
8563  switch (cmp_abs(var1, var2))
8564  {
8565  case 0:
8566  /* ----------
8567  * ABS(var1) == ABS(var2)
8568  * result = ZERO
8569  * ----------
8570  */
8571  zero_var(result);
8572  result->dscale = Max(var1->dscale, var2->dscale);
8573  break;
8574 
8575  case 1:
8576  /* ----------
8577  * ABS(var1) > ABS(var2)
8578  * result = -(ABS(var1) - ABS(var2))
8579  * ----------
8580  */
8581  sub_abs(var1, var2, result);
8582  result->sign = NUMERIC_NEG;
8583  break;
8584 
8585  case -1:
8586  /* ----------
8587  * ABS(var1) < ABS(var2)
8588  * result = +(ABS(var2) - ABS(var1))
8589  * ----------
8590  */
8591  sub_abs(var2, var1, result);
8592  result->sign = NUMERIC_POS;
8593  break;
8594  }
8595  }
8596  else
8597  {
8598  /* ----------
8599  * var1 is negative, var2 is positive
8600  * result = -(ABS(var1) + ABS(var2))
8601  * ----------
8602  */
8603  add_abs(var1, var2, result);
8604  result->sign = NUMERIC_NEG;
8605  }
8606  }
8607 }

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

◆ trunc_var()

static void trunc_var ( NumericVar var,
int  rscale 
)
static

Definition at line 11636 of file numeric.c.

11637 {
11638  int di;
11639  int ndigits;
11640 
11641  var->dscale = rscale;
11642 
11643  /* decimal digits wanted */
11644  di = (var->weight + 1) * DEC_DIGITS + rscale;
11645 
11646  /*
11647  * If di <= 0, the value loses all digits.
11648  */
11649  if (di <= 0)
11650  {
11651  var->ndigits = 0;
11652  var->weight = 0;
11653  var->sign = NUMERIC_POS;
11654  }
11655  else
11656  {
11657  /* NBASE digits wanted */
11658  ndigits = (di + DEC_DIGITS - 1) / DEC_DIGITS;
11659 
11660  if (ndigits <= var->ndigits)
11661  {
11662  var->ndigits = ndigits;
11663 
11664 #if DEC_DIGITS == 1
11665  /* no within-digit stuff to worry about */
11666 #else
11667  /* 0, or number of decimal digits to keep in last NBASE digit */
11668  di %= DEC_DIGITS;
11669 
11670  if (di > 0)
11671  {
11672  /* Must truncate within last NBASE digit */
11673  NumericDigit *digits = var->digits;
11674  int extra,
11675  pow10;
11676 
11677 #if DEC_DIGITS == 4
11678  pow10 = round_powers[di];
11679 #elif DEC_DIGITS == 2
11680  pow10 = 10;
11681 #else
11682 #error unsupported NBASE
11683 #endif
11684  extra = digits[--ndigits] % pow10;
11685  digits[ndigits] -= extra;
11686  }
11687 #endif
11688  }
11689  }
11690 }

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

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

◆ width_bucket_numeric()

Datum width_bucket_numeric ( PG_FUNCTION_ARGS  )

Definition at line 1827 of file numeric.c.

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

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

7164 {
7165  return dig >= '0' && dig <= '9' ? dig - '0' :
7166  dig >= 'a' && dig <= 'f' ? dig - 'a' + 10 :
7167  dig >= 'A' && dig <= 'F' ? dig - 'A' + 10 : -1;
7168 }

Referenced by set_var_from_non_decimal_integer_str().

◆ zero_var()

static void zero_var ( NumericVar var)
static

Definition at line 6933 of file numeric.c.

6934 {
6935  digitbuf_free(var->buf);
6936  var->buf = NULL;
6937  var->digits = NULL;
6938  var->ndigits = 0;
6939  var->weight = 0; /* by convention; doesn't really matter */
6940  var->sign = NUMERIC_POS; /* anything but NAN... */
6941 }

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

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

Variable Documentation

◆ const_minus_one

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

Definition at line 422 of file numeric.c.

Referenced by numeric_power(), and numeric_sign().

◆ const_nan

◆ const_ninf

◆ const_one

◆ const_one_data

const NumericDigit const_one_data[1] = {1}
static

Definition at line 418 of file numeric.c.

◆ const_one_point_one

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

Definition at line 446 of file numeric.c.

Referenced by estimate_ln_dweight(), and ln_var().

◆ const_one_point_one_data

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

Definition at line 440 of file numeric.c.

◆ const_pinf

◆ const_two

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

Definition at line 426 of file numeric.c.

Referenced by ln_var().

◆ const_two_data

const NumericDigit const_two_data[1] = {2}
static

Definition at line 425 of file numeric.c.

◆ const_zero

◆ const_zero_data

const NumericDigit const_zero_data[1] = {0}
static

Definition at line 414 of file numeric.c.

◆ const_zero_point_nine

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

Definition at line 436 of file numeric.c.

Referenced by estimate_ln_dweight(), and ln_var().

◆ const_zero_point_nine_data

const NumericDigit const_zero_point_nine_data[1] = {9000}
static

Definition at line 430 of file numeric.c.

◆ round_powers

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

Definition at line 459 of file numeric.c.

Referenced by round_var(), and trunc_var().