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 "common/int128.h"
#include "funcapi.h"
#include "lib/hyperloglog.h"
#include "libpq/pqformat.h"
#include "miscadmin.h"
#include "nodes/nodeFuncs.h"
#include "nodes/supportnodes.h"
#include "optimizer/optimizer.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  Int128AggState
 
struct  Int8TransTypeData
 

Macros

#define NBASE   10000
 
#define HALF_NBASE   5000
 
#define DEC_DIGITS   4 /* decimal digits per NBASE digit */
 
#define MUL_GUARD_DIGITS   2 /* these are measured in NBASE digits */
 
#define DIV_GUARD_DIGITS   4
 
#define NBASE_SQR   (NBASE * NBASE)
 
#define NUMERIC_SIGN_MASK   0xC000
 
#define NUMERIC_POS   0x0000
 
#define NUMERIC_NEG   0x4000
 
#define NUMERIC_SHORT   0x8000
 
#define NUMERIC_SPECIAL   0xC000
 
#define NUMERIC_FLAGBITS(n)   ((n)->choice.n_header & NUMERIC_SIGN_MASK)
 
#define NUMERIC_IS_SHORT(n)   (NUMERIC_FLAGBITS(n) == NUMERIC_SHORT)
 
#define NUMERIC_IS_SPECIAL(n)   (NUMERIC_FLAGBITS(n) == NUMERIC_SPECIAL)
 
#define NUMERIC_HDRSZ   (VARHDRSZ + sizeof(uint16) + sizeof(int16))
 
#define NUMERIC_HDRSZ_SHORT   (VARHDRSZ + sizeof(uint16))
 
#define NUMERIC_HEADER_IS_SHORT(n)   (((n)->choice.n_header & 0x8000) != 0)
 
#define NUMERIC_HEADER_SIZE(n)
 
#define NUMERIC_EXT_SIGN_MASK   0xF000 /* high bits plus NaN/Inf flag bits */
 
#define NUMERIC_NAN   0xC000
 
#define NUMERIC_PINF   0xD000
 
#define NUMERIC_NINF   0xF000
 
#define NUMERIC_INF_SIGN_MASK   0x2000
 
#define NUMERIC_EXT_FLAGBITS(n)   ((n)->choice.n_header & NUMERIC_EXT_SIGN_MASK)
 
#define NUMERIC_IS_NAN(n)   ((n)->choice.n_header == NUMERIC_NAN)
 
#define NUMERIC_IS_PINF(n)   ((n)->choice.n_header == NUMERIC_PINF)
 
#define NUMERIC_IS_NINF(n)   ((n)->choice.n_header == NUMERIC_NINF)
 
#define NUMERIC_IS_INF(n)    (((n)->choice.n_header & ~NUMERIC_INF_SIGN_MASK) == NUMERIC_PINF)
 
#define NUMERIC_SHORT_SIGN_MASK   0x2000
 
#define NUMERIC_SHORT_DSCALE_MASK   0x1F80
 
#define NUMERIC_SHORT_DSCALE_SHIFT   7
 
#define NUMERIC_SHORT_DSCALE_MAX    (NUMERIC_SHORT_DSCALE_MASK >> NUMERIC_SHORT_DSCALE_SHIFT)
 
#define NUMERIC_SHORT_WEIGHT_SIGN_MASK   0x0040
 
#define NUMERIC_SHORT_WEIGHT_MASK   0x003F
 
#define NUMERIC_SHORT_WEIGHT_MAX   NUMERIC_SHORT_WEIGHT_MASK
 
#define NUMERIC_SHORT_WEIGHT_MIN   (-(NUMERIC_SHORT_WEIGHT_MASK+1))
 
#define NUMERIC_DSCALE_MASK   0x3FFF
 
#define NUMERIC_DSCALE_MAX   NUMERIC_DSCALE_MASK
 
#define NUMERIC_SIGN(n)
 
#define NUMERIC_DSCALE(n)
 
#define NUMERIC_WEIGHT(n)
 
#define NUMERIC_WEIGHT_MAX   PG_INT16_MAX
 
#define NumericAbbrevGetDatum(X)   Int64GetDatum(X)
 
#define DatumGetNumericAbbrev(X)   DatumGetInt64(X)
 
#define NUMERIC_ABBREV_NAN   NumericAbbrevGetDatum(PG_INT64_MIN)
 
#define NUMERIC_ABBREV_PINF   NumericAbbrevGetDatum(-PG_INT64_MAX)
 
#define NUMERIC_ABBREV_NINF   NumericAbbrevGetDatum(PG_INT64_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 PRODSUM1(v1, i1, v2, i2)   ((v1)[(i1)] * (v2)[(i2)])
 
#define PRODSUM2(v1, i1, v2, i2)   (PRODSUM1(v1,i1,v2,i2) + (v1)[(i1)+1] * (v2)[(i2)-1])
 
#define PRODSUM3(v1, i1, v2, i2)   (PRODSUM2(v1,i1,v2,i2) + (v1)[(i1)+2] * (v2)[(i2)-2])
 
#define PRODSUM4(v1, i1, v2, i2)   (PRODSUM3(v1,i1,v2,i2) + (v1)[(i1)+3] * (v2)[(i2)-3])
 
#define PRODSUM5(v1, i1, v2, i2)   (PRODSUM4(v1,i1,v2,i2) + (v1)[(i1)+4] * (v2)[(i2)-4])
 
#define PRODSUM6(v1, i1, v2, i2)   (PRODSUM5(v1,i1,v2,i2) + (v1)[(i1)+5] * (v2)[(i2)-5])
 

Typedefs

typedef int16 NumericDigit
 
typedef struct NumericVar NumericVar
 
typedef struct NumericSumAccum NumericSumAccum
 
typedef struct NumericAggState NumericAggState
 
typedef struct Int128AggState Int128AggState
 
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_safe (const NumericVar *var, Node *escontext)
 
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 void int128_to_numericvar (INT128 val, NumericVar *var)
 
static double numericvar_to_double_no_overflow (const NumericVar *var)
 
static Datum numeric_abbrev_convert (Datum original_datum, SortSupport ssup)
 
static bool numeric_abbrev_abort (int memtupcount, SortSupport ssup)
 
static int numeric_fast_cmp (Datum x, Datum y, SortSupport ssup)
 
static int numeric_cmp_abbrev (Datum x, Datum y, SortSupport ssup)
 
static Datum numeric_abbrev_convert_var (const NumericVar *var, NumericSortSupport *nss)
 
static int cmp_numerics (Numeric num1, Numeric num2)
 
static int cmp_var (const NumericVar *var1, const NumericVar *var2)
 
static int cmp_var_common (const NumericDigit *var1digits, int var1ndigits, int var1weight, int var1sign, const NumericDigit *var2digits, int var2ndigits, int var2weight, int var2sign)
 
static void add_var (const NumericVar *var1, const NumericVar *var2, NumericVar *result)
 
static void sub_var (const NumericVar *var1, const NumericVar *var2, NumericVar *result)
 
static void mul_var (const NumericVar *var1, const NumericVar *var2, NumericVar *result, int rscale)
 
static void mul_var_short (const NumericVar *var1, const NumericVar *var2, NumericVar *result)
 
static void div_var (const NumericVar *var1, const NumericVar *var2, NumericVar *result, int rscale, bool round, bool exact)
 
static void div_var_int (const NumericVar *var, int ival, int ival_weight, NumericVar *result, int rscale, bool round)
 
static int select_div_scale (const NumericVar *var1, const NumericVar *var2)
 
static void mod_var (const NumericVar *var1, const NumericVar *var2, NumericVar *result)
 
static void div_mod_var (const NumericVar *var1, const NumericVar *var2, NumericVar *quot, NumericVar *rem)
 
static void ceil_var (const NumericVar *var, NumericVar *result)
 
static void floor_var (const NumericVar *var, NumericVar *result)
 
static void gcd_var (const NumericVar *var1, const NumericVar *var2, NumericVar *result)
 
static void sqrt_var (const NumericVar *arg, NumericVar *result, int rscale)
 
static void exp_var (const NumericVar *arg, NumericVar *result, int rscale)
 
static int estimate_ln_dweight (const NumericVar *var)
 
static void ln_var (const NumericVar *arg, NumericVar *result, int rscale)
 
static void log_var (const NumericVar *base, const NumericVar *num, NumericVar *result)
 
static void power_var (const NumericVar *base, const NumericVar *exp, NumericVar *result)
 
static void power_var_int (const NumericVar *base, int exp, int exp_dscale, NumericVar *result)
 
static void power_ten_int (int exp, NumericVar *result)
 
static void random_var (pg_prng_state *state, const NumericVar *rmin, const NumericVar *rmax, NumericVar *result)
 
static int cmp_abs (const NumericVar *var1, const NumericVar *var2)
 
static int cmp_abs_common (const NumericDigit *var1digits, int var1ndigits, int var1weight, const NumericDigit *var2digits, int var2ndigits, int var2weight)
 
static void add_abs (const NumericVar *var1, const NumericVar *var2, NumericVar *result)
 
static void sub_abs (const NumericVar *var1, const NumericVar *var2, NumericVar *result)
 
static void round_var (NumericVar *var, int rscale)
 
static void trunc_var (NumericVar *var, int rscale)
 
static void strip_var (NumericVar *var)
 
static void compute_bucket (Numeric operand, Numeric bound1, Numeric bound2, const NumericVar *count_var, NumericVar *result_var)
 
static void accum_sum_add (NumericSumAccum *accum, const NumericVar *val)
 
static void accum_sum_rescale (NumericSumAccum *accum, const NumericVar *val)
 
static void accum_sum_carry (NumericSumAccum *accum)
 
static void accum_sum_reset (NumericSumAccum *accum)
 
static void accum_sum_final (NumericSumAccum *accum, NumericVar *result)
 
static void accum_sum_copy (NumericSumAccum *dst, NumericSumAccum *src)
 
static void accum_sum_combine (NumericSumAccum *accum, NumericSumAccum *accum2)
 
Datum numeric_in (PG_FUNCTION_ARGS)
 
Datum numeric_out (PG_FUNCTION_ARGS)
 
bool numeric_is_nan (Numeric num)
 
bool numeric_is_inf (Numeric num)
 
static bool numeric_is_integral (Numeric num)
 
static int32 make_numeric_typmod (int precision, int scale)
 
static bool is_valid_numeric_typmod (int32 typmod)
 
static int numeric_typmod_precision (int32 typmod)
 
static int numeric_typmod_scale (int32 typmod)
 
int32 numeric_maximum_size (int32 typmod)
 
char * numeric_out_sci (Numeric num, int scale)
 
char * numeric_normalize (Numeric num)
 
Datum numeric_recv (PG_FUNCTION_ARGS)
 
Datum numeric_send (PG_FUNCTION_ARGS)
 
Datum numeric_support (PG_FUNCTION_ARGS)
 
Datum numeric (PG_FUNCTION_ARGS)
 
Datum numerictypmodin (PG_FUNCTION_ARGS)
 
Datum numerictypmodout (PG_FUNCTION_ARGS)
 
Datum numeric_abs (PG_FUNCTION_ARGS)
 
Datum numeric_uminus (PG_FUNCTION_ARGS)
 
Datum numeric_uplus (PG_FUNCTION_ARGS)
 
static int numeric_sign_internal (Numeric num)
 
Datum numeric_sign (PG_FUNCTION_ARGS)
 
Datum numeric_round (PG_FUNCTION_ARGS)
 
Datum numeric_trunc (PG_FUNCTION_ARGS)
 
Datum numeric_ceil (PG_FUNCTION_ARGS)
 
Datum numeric_floor (PG_FUNCTION_ARGS)
 
Datum generate_series_numeric (PG_FUNCTION_ARGS)
 
Datum generate_series_step_numeric (PG_FUNCTION_ARGS)
 
Datum generate_series_numeric_support (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_safe (Numeric num1, Numeric num2, Node *escontext)
 
Datum numeric_sub (PG_FUNCTION_ARGS)
 
Numeric numeric_sub_safe (Numeric num1, Numeric num2, Node *escontext)
 
Datum numeric_mul (PG_FUNCTION_ARGS)
 
Numeric numeric_mul_safe (Numeric num1, Numeric num2, Node *escontext)
 
Datum numeric_div (PG_FUNCTION_ARGS)
 
Numeric numeric_div_safe (Numeric num1, Numeric num2, Node *escontext)
 
Datum numeric_div_trunc (PG_FUNCTION_ARGS)
 
Datum numeric_mod (PG_FUNCTION_ARGS)
 
Numeric numeric_mod_safe (Numeric num1, Numeric num2, Node *escontext)
 
Datum numeric_inc (PG_FUNCTION_ARGS)
 
Datum numeric_smaller (PG_FUNCTION_ARGS)
 
Datum numeric_larger (PG_FUNCTION_ARGS)
 
Datum numeric_gcd (PG_FUNCTION_ARGS)
 
Datum numeric_lcm (PG_FUNCTION_ARGS)
 
Datum numeric_fac (PG_FUNCTION_ARGS)
 
Datum numeric_sqrt (PG_FUNCTION_ARGS)
 
Datum numeric_exp (PG_FUNCTION_ARGS)
 
Datum numeric_ln (PG_FUNCTION_ARGS)
 
Datum numeric_log (PG_FUNCTION_ARGS)
 
Datum numeric_power (PG_FUNCTION_ARGS)
 
Datum numeric_scale (PG_FUNCTION_ARGS)
 
static int get_min_scale (NumericVar *var)
 
Datum numeric_min_scale (PG_FUNCTION_ARGS)
 
Datum numeric_trim_scale (PG_FUNCTION_ARGS)
 
Numeric random_numeric (pg_prng_state *state, Numeric rmin, Numeric rmax)
 
Numeric int64_to_numeric (int64 val)
 
Numeric int64_div_fast_to_numeric (int64 val1, int log10val2)
 
Datum int4_numeric (PG_FUNCTION_ARGS)
 
int32 numeric_int4_safe (Numeric num, Node *escontext)
 
Datum numeric_int4 (PG_FUNCTION_ARGS)
 
Datum int8_numeric (PG_FUNCTION_ARGS)
 
int64 numeric_int8_safe (Numeric num, Node *escontext)
 
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)
 
static Int128AggStatemakeInt128AggState (FunctionCallInfo fcinfo, bool calcSumX2)
 
static Int128AggStatemakeInt128AggStateCurrentContext (bool calcSumX2)
 
static void do_int128_accum (Int128AggState *state, int64 newval)
 
static void do_int128_discard (Int128AggState *state, int64 newval)
 
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)
 
static void int128_serialize (StringInfo buf, INT128 val)
 
static INT128 int128_deserialize (StringInfo buf)
 
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)
 
static Numeric numeric_poly_stddev_internal (Int128AggState *state, bool variance, bool sample, bool *is_null)
 
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)    DatumGetInt64(X)

Definition at line 406 of file numeric.c.

◆ DEC_DIGITS

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

Definition at line 99 of file numeric.c.

◆ digitbuf_alloc

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

Definition at line 478 of file numeric.c.

◆ digitbuf_free

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

Definition at line 480 of file numeric.c.

◆ DIV_GUARD_DIGITS

#define DIV_GUARD_DIGITS   4

Definition at line 101 of file numeric.c.

◆ dump_numeric

#define dump_numeric (   s,
 
)

Definition at line 474 of file numeric.c.

◆ dump_var

#define dump_var (   s,
 
)

Definition at line 475 of file numeric.c.

◆ HALF_NBASE

#define HALF_NBASE   5000

Definition at line 98 of file numeric.c.

◆ init_var

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

Definition at line 486 of file numeric.c.

◆ MUL_GUARD_DIGITS

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

Definition at line 100 of file numeric.c.

◆ NA_TOTAL_COUNT

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

Definition at line 4737 of file numeric.c.

◆ NBASE

#define NBASE   10000

Definition at line 97 of file numeric.c.

◆ NBASE_SQR

#define NBASE_SQR   (NBASE * NBASE)

Definition at line 106 of file numeric.c.

◆ NUMERIC_ABBREV_NAN

#define NUMERIC_ABBREV_NAN   NumericAbbrevGetDatum(PG_INT64_MIN)

Definition at line 407 of file numeric.c.

◆ NUMERIC_ABBREV_NINF

#define NUMERIC_ABBREV_NINF   NumericAbbrevGetDatum(PG_INT64_MAX)

Definition at line 409 of file numeric.c.

◆ NUMERIC_ABBREV_PINF

#define NUMERIC_ABBREV_PINF   NumericAbbrevGetDatum(-PG_INT64_MAX)

Definition at line 408 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:220
#define NUMERIC_SHORT_WEIGHT_MIN
Definition: numeric.c:225
#define NUMERIC_SHORT_WEIGHT_MAX
Definition: numeric.c:224
static int scale
Definition: pgbench.c:182

Definition at line 492 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:186

Definition at line 488 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:237
#define NUMERIC_SHORT_DSCALE_MASK
Definition: numeric.c:218
#define NUMERIC_SHORT_DSCALE_SHIFT
Definition: numeric.c:219

Definition at line 246 of file numeric.c.

◆ NUMERIC_DSCALE_MASK

#define NUMERIC_DSCALE_MASK   0x3FFF

Definition at line 237 of file numeric.c.

◆ NUMERIC_DSCALE_MAX

#define NUMERIC_DSCALE_MAX   NUMERIC_DSCALE_MASK

Definition at line 238 of file numeric.c.

◆ NUMERIC_EXT_FLAGBITS

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

Definition at line 206 of file numeric.c.

◆ NUMERIC_EXT_SIGN_MASK

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

Definition at line 200 of file numeric.c.

◆ NUMERIC_FLAGBITS

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

Definition at line 174 of file numeric.c.

◆ NUMERIC_HDRSZ

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

Definition at line 178 of file numeric.c.

◆ NUMERIC_HDRSZ_SHORT

#define NUMERIC_HDRSZ_SHORT   (VARHDRSZ + sizeof(uint16))

Definition at line 179 of file numeric.c.

◆ NUMERIC_HEADER_IS_SHORT

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

Definition at line 186 of file numeric.c.

◆ NUMERIC_HEADER_SIZE

#define NUMERIC_HEADER_SIZE (   n)
Value:
(VARHDRSZ + sizeof(uint16) + \
(NUMERIC_HEADER_IS_SHORT(n) ? 0 : sizeof(int16)))
#define VARHDRSZ
Definition: c.h:711
int16_t int16
Definition: c.h:547
uint16_t uint16
Definition: c.h:551

Definition at line 187 of file numeric.c.

◆ NUMERIC_INF_SIGN_MASK

#define NUMERIC_INF_SIGN_MASK   0x2000

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

◆ NUMERIC_IS_NAN

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

Definition at line 207 of file numeric.c.

◆ NUMERIC_IS_NINF

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

Definition at line 209 of file numeric.c.

◆ NUMERIC_IS_PINF

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

Definition at line 208 of file numeric.c.

◆ NUMERIC_IS_SHORT

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

Definition at line 175 of file numeric.c.

◆ NUMERIC_IS_SPECIAL

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

Definition at line 176 of file numeric.c.

◆ NUMERIC_NAN

#define NUMERIC_NAN   0xC000

Definition at line 201 of file numeric.c.

◆ NUMERIC_NDIGITS

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

Definition at line 490 of file numeric.c.

◆ NUMERIC_NEG

#define NUMERIC_NEG   0x4000

Definition at line 170 of file numeric.c.

◆ NUMERIC_NINF

#define NUMERIC_NINF   0xF000

Definition at line 203 of file numeric.c.

◆ NUMERIC_PINF

#define NUMERIC_PINF   0xD000

Definition at line 202 of file numeric.c.

◆ NUMERIC_POS

#define NUMERIC_POS   0x0000

Definition at line 169 of file numeric.c.

◆ NUMERIC_SHORT

#define NUMERIC_SHORT   0x8000

Definition at line 171 of file numeric.c.

◆ NUMERIC_SHORT_DSCALE_MASK

#define NUMERIC_SHORT_DSCALE_MASK   0x1F80

Definition at line 218 of file numeric.c.

◆ NUMERIC_SHORT_DSCALE_MAX

#define NUMERIC_SHORT_DSCALE_MAX    (NUMERIC_SHORT_DSCALE_MASK >> NUMERIC_SHORT_DSCALE_SHIFT)

Definition at line 220 of file numeric.c.

◆ NUMERIC_SHORT_DSCALE_SHIFT

#define NUMERIC_SHORT_DSCALE_SHIFT   7

Definition at line 219 of file numeric.c.

◆ NUMERIC_SHORT_SIGN_MASK

#define NUMERIC_SHORT_SIGN_MASK   0x2000

Definition at line 217 of file numeric.c.

◆ NUMERIC_SHORT_WEIGHT_MASK

#define NUMERIC_SHORT_WEIGHT_MASK   0x003F

Definition at line 223 of file numeric.c.

◆ NUMERIC_SHORT_WEIGHT_MAX

#define NUMERIC_SHORT_WEIGHT_MAX   NUMERIC_SHORT_WEIGHT_MASK

Definition at line 224 of file numeric.c.

◆ NUMERIC_SHORT_WEIGHT_MIN

#define NUMERIC_SHORT_WEIGHT_MIN   (-(NUMERIC_SHORT_WEIGHT_MASK+1))

Definition at line 225 of file numeric.c.

◆ NUMERIC_SHORT_WEIGHT_SIGN_MASK

#define NUMERIC_SHORT_WEIGHT_SIGN_MASK   0x0040

Definition at line 222 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:176
#define NUMERIC_FLAGBITS(n)
Definition: numeric.c:174
#define NUMERIC_SHORT_SIGN_MASK
Definition: numeric.c:217
#define NUMERIC_IS_SHORT(n)
Definition: numeric.c:175
#define NUMERIC_POS
Definition: numeric.c:169

Definition at line 240 of file numeric.c.

◆ NUMERIC_SIGN_MASK

#define NUMERIC_SIGN_MASK   0xC000

Definition at line 168 of file numeric.c.

◆ NUMERIC_SPECIAL

#define NUMERIC_SPECIAL   0xC000

Definition at line 172 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:223
#define NUMERIC_SHORT_WEIGHT_SIGN_MASK
Definition: numeric.c:222

Definition at line 250 of file numeric.c.

◆ NUMERIC_WEIGHT_MAX

#define NUMERIC_WEIGHT_MAX   PG_INT16_MAX

Definition at line 261 of file numeric.c.

◆ NumericAbbrevGetDatum

#define NumericAbbrevGetDatum (   X)    Int64GetDatum(X)

Definition at line 405 of file numeric.c.

◆ PRODSUM1

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

◆ PRODSUM2

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

◆ PRODSUM3

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

◆ PRODSUM4

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

◆ PRODSUM5

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

◆ PRODSUM6

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

Typedef Documentation

◆ Int128AggState

◆ Int8TransTypeData

◆ NumericAggState

◆ NumericDigit

Definition at line 103 of file numeric.c.

◆ NumericSumAccum

◆ NumericVar

typedef struct NumericVar NumericVar

Function Documentation

◆ accum_sum_add()

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

Definition at line 11845 of file numeric.c.

11846{
11847 int32 *accum_digits;
11848 int i,
11849 val_i;
11850 int val_ndigits;
11851 NumericDigit *val_digits;
11852
11853 /*
11854 * If we have accumulated too many values since the last carry
11855 * propagation, do it now, to avoid overflowing. (We could allow more
11856 * than NBASE - 1, if we reserved two extra digits, rather than one, for
11857 * carry propagation. But even with NBASE - 1, this needs to be done so
11858 * seldom, that the performance difference is negligible.)
11859 */
11860 if (accum->num_uncarried == NBASE - 1)
11861 accum_sum_carry(accum);
11862
11863 /*
11864 * Adjust the weight or scale of the old value, so that it can accommodate
11865 * the new value.
11866 */
11867 accum_sum_rescale(accum, val);
11868
11869 /* */
11870 if (val->sign == NUMERIC_POS)
11871 accum_digits = accum->pos_digits;
11872 else
11873 accum_digits = accum->neg_digits;
11874
11875 /* copy these values into local vars for speed in loop */
11876 val_ndigits = val->ndigits;
11877 val_digits = val->digits;
11878
11879 i = accum->weight - val->weight;
11880 for (val_i = 0; val_i < val_ndigits; val_i++)
11881 {
11882 accum_digits[i] += (int32) val_digits[val_i];
11883 i++;
11884 }
11885
11886 accum->num_uncarried++;
11887}
static void accum_sum_carry(NumericSumAccum *accum)
Definition: numeric.c:11893
int16 NumericDigit
Definition: numeric.c:103
#define NBASE
Definition: numeric.c:97
static void accum_sum_rescale(NumericSumAccum *accum, const NumericVar *val)
Definition: numeric.c:11966
int32_t int32
Definition: c.h:548
long val
Definition: informix.c:689
int i
Definition: isn.c:77
int32 * pos_digits
Definition: numeric.c:388
int num_uncarried
Definition: numeric.c:386
int32 * neg_digits
Definition: numeric.c:389

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(), numeric_avg_deserialize(), numeric_deserialize(), and numeric_poly_stddev_internal().

◆ accum_sum_carry()

static void accum_sum_carry ( NumericSumAccum accum)
static

Definition at line 11893 of file numeric.c.

11894{
11895 int i;
11896 int ndigits;
11897 int32 *dig;
11898 int32 carry;
11899 int32 newdig = 0;
11900
11901 /*
11902 * If no new values have been added since last carry propagation, nothing
11903 * to do.
11904 */
11905 if (accum->num_uncarried == 0)
11906 return;
11907
11908 /*
11909 * We maintain that the weight of the accumulator is always one larger
11910 * than needed to hold the current value, before carrying, to make sure
11911 * there is enough space for the possible extra digit when carry is
11912 * propagated. We cannot expand the buffer here, unless we require
11913 * callers of accum_sum_final() to switch to the right memory context.
11914 */
11915 Assert(accum->pos_digits[0] == 0 && accum->neg_digits[0] == 0);
11916
11917 ndigits = accum->ndigits;
11918
11919 /* Propagate carry in the positive sum */
11920 dig = accum->pos_digits;
11921 carry = 0;
11922 for (i = ndigits - 1; i >= 0; i--)
11923 {
11924 newdig = dig[i] + carry;
11925 if (newdig >= NBASE)
11926 {
11927 carry = newdig / NBASE;
11928 newdig -= carry * NBASE;
11929 }
11930 else
11931 carry = 0;
11932 dig[i] = newdig;
11933 }
11934 /* Did we use up the digit reserved for carry propagation? */
11935 if (newdig > 0)
11936 accum->have_carry_space = false;
11937
11938 /* And the same for the negative sum */
11939 dig = accum->neg_digits;
11940 carry = 0;
11941 for (i = ndigits - 1; i >= 0; i--)
11942 {
11943 newdig = dig[i] + carry;
11944 if (newdig >= NBASE)
11945 {
11946 carry = newdig / NBASE;
11947 newdig -= carry * NBASE;
11948 }
11949 else
11950 carry = 0;
11951 dig[i] = newdig;
11952 }
11953 if (newdig > 0)
11954 accum->have_carry_space = false;
11955
11956 accum->num_uncarried = 0;
11957}
Assert(PointerIsAligned(start, uint64))
bool have_carry_space
Definition: numeric.c:387

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

12124{
12125 NumericVar tmp_var;
12126
12127 init_var(&tmp_var);
12128
12129 accum_sum_final(accum2, &tmp_var);
12130 accum_sum_add(accum, &tmp_var);
12131
12132 free_var(&tmp_var);
12133}
static void accum_sum_final(NumericSumAccum *accum, NumericVar *result)
Definition: numeric.c:12055
static void free_var(NumericVar *var)
Definition: numeric.c:6699
static void accum_sum_add(NumericSumAccum *accum, const NumericVar *val)
Definition: numeric.c:11845
#define init_var(v)
Definition: numeric.c:486

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

Referenced by numeric_avg_combine(), and numeric_combine().

◆ accum_sum_copy()

static void accum_sum_copy ( NumericSumAccum dst,
NumericSumAccum src 
)
static

Definition at line 12106 of file numeric.c.

12107{
12108 dst->pos_digits = palloc(src->ndigits * sizeof(int32));
12109 dst->neg_digits = palloc(src->ndigits * sizeof(int32));
12110
12111 memcpy(dst->pos_digits, src->pos_digits, src->ndigits * sizeof(int32));
12112 memcpy(dst->neg_digits, src->neg_digits, src->ndigits * sizeof(int32));
12113 dst->num_uncarried = src->num_uncarried;
12114 dst->ndigits = src->ndigits;
12115 dst->weight = src->weight;
12116 dst->dscale = src->dscale;
12117}
void * palloc(Size size)
Definition: mcxt.c:1365

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

Referenced by numeric_avg_combine(), and numeric_combine().

◆ accum_sum_final()

static void accum_sum_final ( NumericSumAccum accum,
NumericVar result 
)
static

Definition at line 12055 of file numeric.c.

12056{
12057 int i;
12058 NumericVar pos_var;
12059 NumericVar neg_var;
12060
12061 if (accum->ndigits == 0)
12062 {
12063 set_var_from_var(&const_zero, result);
12064 return;
12065 }
12066
12067 /* Perform final carry */
12068 accum_sum_carry(accum);
12069
12070 /* Create NumericVars representing the positive and negative sums */
12071 init_var(&pos_var);
12072 init_var(&neg_var);
12073
12074 pos_var.ndigits = neg_var.ndigits = accum->ndigits;
12075 pos_var.weight = neg_var.weight = accum->weight;
12076 pos_var.dscale = neg_var.dscale = accum->dscale;
12077 pos_var.sign = NUMERIC_POS;
12078 neg_var.sign = NUMERIC_NEG;
12079
12080 pos_var.buf = pos_var.digits = digitbuf_alloc(accum->ndigits);
12081 neg_var.buf = neg_var.digits = digitbuf_alloc(accum->ndigits);
12082
12083 for (i = 0; i < accum->ndigits; i++)
12084 {
12085 Assert(accum->pos_digits[i] < NBASE);
12086 pos_var.digits[i] = (int16) accum->pos_digits[i];
12087
12088 Assert(accum->neg_digits[i] < NBASE);
12089 neg_var.digits[i] = (int16) accum->neg_digits[i];
12090 }
12091
12092 /* And add them together */
12093 add_var(&pos_var, &neg_var, result);
12094
12095 /* Remove leading/trailing zeroes */
12096 strip_var(result);
12097}
static void add_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition: numeric.c:8061
#define NUMERIC_NEG
Definition: numeric.c:170
#define digitbuf_alloc(ndigits)
Definition: numeric.c:478
static const NumericVar const_zero
Definition: numeric.c:417
static void set_var_from_var(const NumericVar *value, NumericVar *dest)
Definition: numeric.c:7198
static void strip_var(NumericVar *var)
Definition: numeric.c:11788
int ndigits
Definition: numeric.c:316
NumericDigit * digits
Definition: numeric.c:321
int dscale
Definition: numeric.c:319
int sign
Definition: numeric.c:318
NumericDigit * buf
Definition: numeric.c:320
int weight
Definition: numeric.c:317

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

11967{
11968 int old_weight = accum->weight;
11969 int old_ndigits = accum->ndigits;
11970 int accum_ndigits;
11971 int accum_weight;
11972 int accum_rscale;
11973 int val_rscale;
11974
11975 accum_weight = old_weight;
11976 accum_ndigits = old_ndigits;
11977
11978 /*
11979 * Does the new value have a larger weight? If so, enlarge the buffers,
11980 * and shift the existing value to the new weight, by adding leading
11981 * zeros.
11982 *
11983 * We enforce that the accumulator always has a weight one larger than
11984 * needed for the inputs, so that we have space for an extra digit at the
11985 * final carry-propagation phase, if necessary.
11986 */
11987 if (val->weight >= accum_weight)
11988 {
11989 accum_weight = val->weight + 1;
11990 accum_ndigits = accum_ndigits + (accum_weight - old_weight);
11991 }
11992
11993 /*
11994 * Even though the new value is small, we might've used up the space
11995 * reserved for the carry digit in the last call to accum_sum_carry(). If
11996 * so, enlarge to make room for another one.
11997 */
11998 else if (!accum->have_carry_space)
11999 {
12000 accum_weight++;
12001 accum_ndigits++;
12002 }
12003
12004 /* Is the new value wider on the right side? */
12005 accum_rscale = accum_ndigits - accum_weight - 1;
12006 val_rscale = val->ndigits - val->weight - 1;
12007 if (val_rscale > accum_rscale)
12008 accum_ndigits = accum_ndigits + (val_rscale - accum_rscale);
12009
12010 if (accum_ndigits != old_ndigits ||
12011 accum_weight != old_weight)
12012 {
12013 int32 *new_pos_digits;
12014 int32 *new_neg_digits;
12015 int weightdiff;
12016
12017 weightdiff = accum_weight - old_weight;
12018
12019 new_pos_digits = palloc0(accum_ndigits * sizeof(int32));
12020 new_neg_digits = palloc0(accum_ndigits * sizeof(int32));
12021
12022 if (accum->pos_digits)
12023 {
12024 memcpy(&new_pos_digits[weightdiff], accum->pos_digits,
12025 old_ndigits * sizeof(int32));
12026 pfree(accum->pos_digits);
12027
12028 memcpy(&new_neg_digits[weightdiff], accum->neg_digits,
12029 old_ndigits * sizeof(int32));
12030 pfree(accum->neg_digits);
12031 }
12032
12033 accum->pos_digits = new_pos_digits;
12034 accum->neg_digits = new_neg_digits;
12035
12036 accum->weight = accum_weight;
12037 accum->ndigits = accum_ndigits;
12038
12039 Assert(accum->pos_digits[0] == 0 && accum->neg_digits[0] == 0);
12040 accum->have_carry_space = true;
12041 }
12042
12043 if (val->dscale > accum->dscale)
12044 accum->dscale = val->dscale;
12045}
void pfree(void *pointer)
Definition: mcxt.c:1594
void * palloc0(Size size)
Definition: mcxt.c:1395

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

11830{
11831 int i;
11832
11833 accum->dscale = 0;
11834 for (i = 0; i < accum->ndigits; i++)
11835 {
11836 accum->pos_digits[i] = 0;
11837 accum->neg_digits[i] = 0;
11838 }
11839}

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

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

8062{
8063 /*
8064 * Decide on the signs of the two variables what to do
8065 */
8066 if (var1->sign == NUMERIC_POS)
8067 {
8068 if (var2->sign == NUMERIC_POS)
8069 {
8070 /*
8071 * Both are positive result = +(ABS(var1) + ABS(var2))
8072 */
8073 add_abs(var1, var2, result);
8074 result->sign = NUMERIC_POS;
8075 }
8076 else
8077 {
8078 /*
8079 * var1 is positive, var2 is negative Must compare absolute values
8080 */
8081 switch (cmp_abs(var1, var2))
8082 {
8083 case 0:
8084 /* ----------
8085 * ABS(var1) == ABS(var2)
8086 * result = ZERO
8087 * ----------
8088 */
8089 zero_var(result);
8090 result->dscale = Max(var1->dscale, var2->dscale);
8091 break;
8092
8093 case 1:
8094 /* ----------
8095 * ABS(var1) > ABS(var2)
8096 * result = +(ABS(var1) - ABS(var2))
8097 * ----------
8098 */
8099 sub_abs(var1, var2, result);
8100 result->sign = NUMERIC_POS;
8101 break;
8102
8103 case -1:
8104 /* ----------
8105 * ABS(var1) < ABS(var2)
8106 * result = -(ABS(var2) - ABS(var1))
8107 * ----------
8108 */
8109 sub_abs(var2, var1, result);
8110 result->sign = NUMERIC_NEG;
8111 break;
8112 }
8113 }
8114 }
8115 else
8116 {
8117 if (var2->sign == NUMERIC_POS)
8118 {
8119 /* ----------
8120 * var1 is negative, var2 is positive
8121 * Must compare absolute values
8122 * ----------
8123 */
8124 switch (cmp_abs(var1, var2))
8125 {
8126 case 0:
8127 /* ----------
8128 * ABS(var1) == ABS(var2)
8129 * result = ZERO
8130 * ----------
8131 */
8132 zero_var(result);
8133 result->dscale = Max(var1->dscale, var2->dscale);
8134 break;
8135
8136 case 1:
8137 /* ----------
8138 * ABS(var1) > ABS(var2)
8139 * result = -(ABS(var1) - ABS(var2))
8140 * ----------
8141 */
8142 sub_abs(var1, var2, result);
8143 result->sign = NUMERIC_NEG;
8144 break;
8145
8146 case -1:
8147 /* ----------
8148 * ABS(var1) < ABS(var2)
8149 * result = +(ABS(var2) - ABS(var1))
8150 * ----------
8151 */
8152 sub_abs(var2, var1, result);
8153 result->sign = NUMERIC_POS;
8154 break;
8155 }
8156 }
8157 else
8158 {
8159 /* ----------
8160 * Both are negative
8161 * result = -(ABS(var1) + ABS(var2))
8162 * ----------
8163 */
8164 add_abs(var1, var2, result);
8165 result->sign = NUMERIC_NEG;
8166 }
8167 }
8168}
static void sub_abs(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition: numeric.c:11538
static void add_abs(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition: numeric.c:11453
static void zero_var(NumericVar *var)
Definition: numeric.c:6715
static int cmp_abs(const NumericVar *var1, const NumericVar *var2)
Definition: numeric.c:11375

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_safe(), numeric_inc(), random_var(), set_var_from_non_decimal_integer_str(), sqrt_var(), and width_bucket_numeric().

◆ alloc_var()

static void alloc_var ( NumericVar var,
int  ndigits 
)
static

Definition at line 6683 of file numeric.c.

6684{
6685 digitbuf_free(var->buf);
6686 var->buf = digitbuf_alloc(ndigits + 1);
6687 var->buf[0] = 0; /* spare digit for rounding */
6688 var->digits = var->buf + 1;
6689 var->ndigits = ndigits;
6690}

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

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

◆ apply_typmod()

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

Definition at line 7621 of file numeric.c.

7622{
7623 int precision;
7624 int scale;
7625 int maxdigits;
7626 int ddigits;
7627 int i;
7628
7629 /* Do nothing if we have an invalid typmod */
7630 if (!is_valid_numeric_typmod(typmod))
7631 return true;
7632
7633 precision = numeric_typmod_precision(typmod);
7634 scale = numeric_typmod_scale(typmod);
7635 maxdigits = precision - scale;
7636
7637 /* Round to target scale (and set var->dscale) */
7638 round_var(var, scale);
7639
7640 /* but don't allow var->dscale to be negative */
7641 if (var->dscale < 0)
7642 var->dscale = 0;
7643
7644 /*
7645 * Check for overflow - note we can't do this before rounding, because
7646 * rounding could raise the weight. Also note that the var's weight could
7647 * be inflated by leading zeroes, which will be stripped before storage
7648 * but perhaps might not have been yet. In any case, we must recognize a
7649 * true zero, whose weight doesn't mean anything.
7650 */
7651 ddigits = (var->weight + 1) * DEC_DIGITS;
7652 if (ddigits > maxdigits)
7653 {
7654 /* Determine true weight; and check for all-zero result */
7655 for (i = 0; i < var->ndigits; i++)
7656 {
7657 NumericDigit dig = var->digits[i];
7658
7659 if (dig)
7660 {
7661 /* Adjust for any high-order decimal zero digits */
7662#if DEC_DIGITS == 4
7663 if (dig < 10)
7664 ddigits -= 3;
7665 else if (dig < 100)
7666 ddigits -= 2;
7667 else if (dig < 1000)
7668 ddigits -= 1;
7669#elif DEC_DIGITS == 2
7670 if (dig < 10)
7671 ddigits -= 1;
7672#elif DEC_DIGITS == 1
7673 /* no adjustment */
7674#else
7675#error unsupported NBASE
7676#endif
7677 if (ddigits > maxdigits)
7678 ereturn(escontext, false,
7679 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
7680 errmsg("numeric field overflow"),
7681 errdetail("A field with precision %d, scale %d must round to an absolute value less than %s%d.",
7682 precision, scale,
7683 /* Display 10^0 as 1 */
7684 maxdigits ? "10^" : "",
7685 maxdigits ? maxdigits : 1
7686 )));
7687 break;
7688 }
7689 ddigits -= DEC_DIGITS;
7690 }
7691 }
7692
7693 return true;
7694}
static bool is_valid_numeric_typmod(int32 typmod)
Definition: numeric.c:899
static int numeric_typmod_scale(int32 typmod)
Definition: numeric.c:925
static int numeric_typmod_precision(int32 typmod)
Definition: numeric.c:910
static void round_var(NumericVar *var, int rscale)
Definition: numeric.c:11620
#define DEC_DIGITS
Definition: numeric.c:99
int errdetail(const char *fmt,...)
Definition: elog.c:1216
int errcode(int sqlerrcode)
Definition: elog.c:863
int errmsg(const char *fmt,...)
Definition: elog.c:1080
#define ereturn(context, dummy_value,...)
Definition: elog.h:278
int maxdigits
Definition: informix.c:690

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

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

◆ apply_typmod_special()

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

Definition at line 7706 of file numeric.c.

7707{
7708 int precision;
7709 int scale;
7710
7711 Assert(NUMERIC_IS_SPECIAL(num)); /* caller error if not */
7712
7713 /*
7714 * NaN is allowed regardless of the typmod; that's rather dubious perhaps,
7715 * but it's a longstanding behavior. Inf is rejected if we have any
7716 * typmod restriction, since an infinity shouldn't be claimed to fit in
7717 * any finite number of digits.
7718 */
7719 if (NUMERIC_IS_NAN(num))
7720 return true;
7721
7722 /* Do nothing if we have a default typmod (-1) */
7723 if (!is_valid_numeric_typmod(typmod))
7724 return true;
7725
7726 precision = numeric_typmod_precision(typmod);
7727 scale = numeric_typmod_scale(typmod);
7728
7729 ereturn(escontext, false,
7730 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
7731 errmsg("numeric field overflow"),
7732 errdetail("A field with precision %d, scale %d cannot hold an infinite value.",
7733 precision, scale)));
7734}
#define NUMERIC_IS_NAN(n)
Definition: numeric.c:207

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

9815{
9816 NumericVar tmp;
9817
9818 init_var(&tmp);
9819 set_var_from_var(var, &tmp);
9820
9821 trunc_var(&tmp, 0);
9822
9823 if (var->sign == NUMERIC_POS && cmp_var(var, &tmp) != 0)
9824 add_var(&tmp, &const_one, &tmp);
9825
9826 set_var_from_var(&tmp, result);
9827 free_var(&tmp);
9828}
static void trunc_var(NumericVar *var, int rscale)
Definition: numeric.c:11726
static int cmp_var(const NumericVar *var1, const NumericVar *var2)
Definition: numeric.c:8003
static const NumericVar const_one
Definition: numeric.c:421

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

11376{
11377 return cmp_abs_common(var1->digits, var1->ndigits, var1->weight,
11378 var2->digits, var2->ndigits, var2->weight);
11379}
static int cmp_abs_common(const NumericDigit *var1digits, int var1ndigits, int var1weight, const NumericDigit *var2digits, int var2ndigits, int var2weight)
Definition: numeric.c:11389

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

11391{
11392 int i1 = 0;
11393 int i2 = 0;
11394
11395 /* Check any digits before the first common digit */
11396
11397 while (var1weight > var2weight && i1 < var1ndigits)
11398 {
11399 if (var1digits[i1++] != 0)
11400 return 1;
11401 var1weight--;
11402 }
11403 while (var2weight > var1weight && i2 < var2ndigits)
11404 {
11405 if (var2digits[i2++] != 0)
11406 return -1;
11407 var2weight--;
11408 }
11409
11410 /* At this point, either w1 == w2 or we've run out of digits */
11411
11412 if (var1weight == var2weight)
11413 {
11414 while (i1 < var1ndigits && i2 < var2ndigits)
11415 {
11416 int stat = var1digits[i1++] - var2digits[i2++];
11417
11418 if (stat)
11419 {
11420 if (stat > 0)
11421 return 1;
11422 return -1;
11423 }
11424 }
11425 }
11426
11427 /*
11428 * At this point, we've run out of digits on one side or the other; so any
11429 * remaining nonzero digits imply that side is larger
11430 */
11431 while (i1 < var1ndigits)
11432 {
11433 if (var1digits[i1++] != 0)
11434 return 1;
11435 }
11436 while (i2 < var2ndigits)
11437 {
11438 if (var2digits[i2++] != 0)
11439 return -1;
11440 }
11441
11442 return 0;
11443}

Referenced by cmp_abs(), and cmp_var_common().

◆ cmp_numerics()

static int cmp_numerics ( Numeric  num1,
Numeric  num2 
)
static

Definition at line 2521 of file numeric.c.

2522{
2523 int result;
2524
2525 /*
2526 * We consider all NANs to be equal and larger than any non-NAN (including
2527 * Infinity). This is somewhat arbitrary; the important thing is to have
2528 * a consistent sort order.
2529 */
2530 if (NUMERIC_IS_SPECIAL(num1))
2531 {
2532 if (NUMERIC_IS_NAN(num1))
2533 {
2534 if (NUMERIC_IS_NAN(num2))
2535 result = 0; /* NAN = NAN */
2536 else
2537 result = 1; /* NAN > non-NAN */
2538 }
2539 else if (NUMERIC_IS_PINF(num1))
2540 {
2541 if (NUMERIC_IS_NAN(num2))
2542 result = -1; /* PINF < NAN */
2543 else if (NUMERIC_IS_PINF(num2))
2544 result = 0; /* PINF = PINF */
2545 else
2546 result = 1; /* PINF > anything else */
2547 }
2548 else /* num1 must be NINF */
2549 {
2550 if (NUMERIC_IS_NINF(num2))
2551 result = 0; /* NINF = NINF */
2552 else
2553 result = -1; /* NINF < anything else */
2554 }
2555 }
2556 else if (NUMERIC_IS_SPECIAL(num2))
2557 {
2558 if (NUMERIC_IS_NINF(num2))
2559 result = 1; /* normal > NINF */
2560 else
2561 result = -1; /* normal < NAN or PINF */
2562 }
2563 else
2564 {
2565 result = cmp_var_common(NUMERIC_DIGITS(num1), NUMERIC_NDIGITS(num1),
2566 NUMERIC_WEIGHT(num1), NUMERIC_SIGN(num1),
2567 NUMERIC_DIGITS(num2), NUMERIC_NDIGITS(num2),
2568 NUMERIC_WEIGHT(num2), NUMERIC_SIGN(num2));
2569 }
2570
2571 return result;
2572}
#define NUMERIC_SIGN(n)
Definition: numeric.c:240
#define NUMERIC_IS_PINF(n)
Definition: numeric.c:208
#define NUMERIC_IS_NINF(n)
Definition: numeric.c:209
#define NUMERIC_WEIGHT(n)
Definition: numeric.c:250
#define NUMERIC_DIGITS(num)
Definition: numeric.c:488
#define NUMERIC_NDIGITS(num)
Definition: numeric.c:490
static int cmp_var_common(const NumericDigit *var1digits, int var1ndigits, int var1weight, int var1sign, const NumericDigit *var2digits, int var2ndigits, int var2weight, int var2sign)
Definition: numeric.c:8018

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

8022{
8023 if (var1ndigits == 0)
8024 {
8025 if (var2ndigits == 0)
8026 return 0;
8027 if (var2sign == NUMERIC_NEG)
8028 return 1;
8029 return -1;
8030 }
8031 if (var2ndigits == 0)
8032 {
8033 if (var1sign == NUMERIC_POS)
8034 return 1;
8035 return -1;
8036 }
8037
8038 if (var1sign == NUMERIC_POS)
8039 {
8040 if (var2sign == NUMERIC_NEG)
8041 return 1;
8042 return cmp_abs_common(var1digits, var1ndigits, var1weight,
8043 var2digits, var2ndigits, var2weight);
8044 }
8045
8046 if (var2sign == NUMERIC_POS)
8047 return -1;
8048
8049 return cmp_abs_common(var2digits, var2ndigits, var2weight,
8050 var1digits, var1ndigits, var1weight);
8051}

References cmp_abs_common(), NUMERIC_NEG, and NUMERIC_POS.

Referenced by cmp_numerics(), and cmp_var().

◆ compute_bucket()

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

Definition at line 2034 of file numeric.c.

2036{
2037 NumericVar bound1_var;
2038 NumericVar bound2_var;
2039 NumericVar operand_var;
2040
2041 init_var_from_num(bound1, &bound1_var);
2042 init_var_from_num(bound2, &bound2_var);
2043 init_var_from_num(operand, &operand_var);
2044
2045 /*
2046 * Per spec, bound1 is inclusive and bound2 is exclusive, and so we have
2047 * bound1 <= operand < bound2 or bound1 >= operand > bound2. Either way,
2048 * the result is ((operand - bound1) * count) / (bound2 - bound1) + 1,
2049 * where the quotient is computed using floor division (i.e., division to
2050 * zero decimal places with truncation), which guarantees that the result
2051 * is in the range [1, count]. Reversing the bounds doesn't affect the
2052 * computation, because the signs cancel out when dividing.
2053 */
2054 sub_var(&operand_var, &bound1_var, &operand_var);
2055 sub_var(&bound2_var, &bound1_var, &bound2_var);
2056
2057 mul_var(&operand_var, count_var, &operand_var,
2058 operand_var.dscale + count_var->dscale);
2059 div_var(&operand_var, &bound2_var, result_var, 0, false, true);
2060 add_var(result_var, &const_one, result_var);
2061
2062 free_var(&bound1_var);
2063 free_var(&bound2_var);
2064 free_var(&operand_var);
2065}
static void sub_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition: numeric.c:8178
static void init_var_from_num(Numeric num, NumericVar *dest)
Definition: numeric.c:7181
static void mul_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result, int rscale)
Definition: numeric.c:8299
static void div_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result, int rscale, bool round, bool exact)
Definition: numeric.c:8877

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

Referenced by width_bucket_numeric().

◆ div_mod_var()

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

Definition at line 9744 of file numeric.c.

9746{
9747 NumericVar q;
9748 NumericVar r;
9749
9750 init_var(&q);
9751 init_var(&r);
9752
9753 /*
9754 * Use div_var() with exact = false to get an initial estimate for the
9755 * integer quotient (truncated towards zero). This might be slightly
9756 * inaccurate, but we correct it below.
9757 */
9758 div_var(var1, var2, &q, 0, false, false);
9759
9760 /* Compute initial estimate of remainder using the quotient estimate. */
9761 mul_var(var2, &q, &r, var2->dscale);
9762 sub_var(var1, &r, &r);
9763
9764 /*
9765 * Adjust the results if necessary --- the remainder should have the same
9766 * sign as var1, and its absolute value should be less than the absolute
9767 * value of var2.
9768 */
9769 while (r.ndigits != 0 && r.sign != var1->sign)
9770 {
9771 /* The absolute value of the quotient is too large */
9772 if (var1->sign == var2->sign)
9773 {
9774 sub_var(&q, &const_one, &q);
9775 add_var(&r, var2, &r);
9776 }
9777 else
9778 {
9779 add_var(&q, &const_one, &q);
9780 sub_var(&r, var2, &r);
9781 }
9782 }
9783
9784 while (cmp_abs(&r, var2) >= 0)
9785 {
9786 /* The absolute value of the quotient is too small */
9787 if (var1->sign == var2->sign)
9788 {
9789 add_var(&q, &const_one, &q);
9790 sub_var(&r, var2, &r);
9791 }
9792 else
9793 {
9794 sub_var(&q, &const_one, &q);
9795 add_var(&r, var2, &r);
9796 }
9797 }
9798
9799 set_var_from_var(&q, quot);
9800 set_var_from_var(&r, rem);
9801
9802 free_var(&q);
9803 free_var(&r);
9804}

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

Referenced by sqrt_var().

◆ div_var()

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

Definition at line 8877 of file numeric.c.

8879{
8880 int var1ndigits = var1->ndigits;
8881 int var2ndigits = var2->ndigits;
8882 int res_sign;
8883 int res_weight;
8884 int res_ndigits;
8885 int var1ndigitpairs;
8886 int var2ndigitpairs;
8887 int res_ndigitpairs;
8888 int div_ndigitpairs;
8889 int64 *dividend;
8890 int32 *divisor;
8891 double fdivisor,
8892 fdivisorinverse,
8893 fdividend,
8894 fquotient;
8895 int64 maxdiv;
8896 int qi;
8897 int32 qdigit;
8898 int64 carry;
8899 int64 newdig;
8901 NumericDigit *res_digits;
8902 int i;
8903
8904 /*
8905 * First of all division by zero check; we must not be handed an
8906 * unnormalized divisor.
8907 */
8908 if (var2ndigits == 0 || var2->digits[0] == 0)
8909 ereport(ERROR,
8910 (errcode(ERRCODE_DIVISION_BY_ZERO),
8911 errmsg("division by zero")));
8912
8913 /*
8914 * If the divisor has just one or two digits, delegate to div_var_int(),
8915 * which uses fast short division.
8916 *
8917 * Similarly, on platforms with 128-bit integer support, delegate to
8918 * div_var_int64() for divisors with three or four digits.
8919 */
8920 if (var2ndigits <= 2)
8921 {
8922 int idivisor;
8923 int idivisor_weight;
8924
8925 idivisor = var2->digits[0];
8926 idivisor_weight = var2->weight;
8927 if (var2ndigits == 2)
8928 {
8929 idivisor = idivisor * NBASE + var2->digits[1];
8930 idivisor_weight--;
8931 }
8932 if (var2->sign == NUMERIC_NEG)
8933 idivisor = -idivisor;
8934
8935 div_var_int(var1, idivisor, idivisor_weight, result, rscale, round);
8936 return;
8937 }
8938#ifdef HAVE_INT128
8939 if (var2ndigits <= 4)
8940 {
8941 int64 idivisor;
8942 int idivisor_weight;
8943
8944 idivisor = var2->digits[0];
8945 idivisor_weight = var2->weight;
8946 for (i = 1; i < var2ndigits; i++)
8947 {
8948 idivisor = idivisor * NBASE + var2->digits[i];
8949 idivisor_weight--;
8950 }
8951 if (var2->sign == NUMERIC_NEG)
8952 idivisor = -idivisor;
8953
8954 div_var_int64(var1, idivisor, idivisor_weight, result, rscale, round);
8955 return;
8956 }
8957#endif
8958
8959 /*
8960 * Otherwise, perform full long division.
8961 */
8962
8963 /* Result zero check */
8964 if (var1ndigits == 0)
8965 {
8966 zero_var(result);
8967 result->dscale = rscale;
8968 return;
8969 }
8970
8971 /*
8972 * The approximate computation can be significantly faster than the exact
8973 * one, since the working dividend is var2ndigitpairs base-NBASE^2 digits
8974 * shorter below. However, that comes with the tradeoff of computing
8975 * DIV_GUARD_DIGITS extra base-NBASE result digits. Ignoring all other
8976 * overheads, that suggests that, in theory, the approximate computation
8977 * will only be faster than the exact one when var2ndigits is greater than
8978 * 2 * (DIV_GUARD_DIGITS + 1), independent of the size of var1.
8979 *
8980 * Thus, we're better off doing an exact computation when var2 is shorter
8981 * than this. Empirically, it has been found that the exact threshold is
8982 * a little higher, due to other overheads in the outer division loop.
8983 */
8984 if (var2ndigits <= 2 * (DIV_GUARD_DIGITS + 2))
8985 exact = true;
8986
8987 /*
8988 * Determine the result sign, weight and number of digits to calculate.
8989 * The weight figured here is correct if the emitted quotient has no
8990 * leading zero digits; otherwise strip_var() will fix things up.
8991 */
8992 if (var1->sign == var2->sign)
8993 res_sign = NUMERIC_POS;
8994 else
8995 res_sign = NUMERIC_NEG;
8996 res_weight = var1->weight - var2->weight + 1;
8997 /* The number of accurate result digits we need to produce: */
8998 res_ndigits = res_weight + 1 + (rscale + DEC_DIGITS - 1) / DEC_DIGITS;
8999 /* ... but always at least 1 */
9000 res_ndigits = Max(res_ndigits, 1);
9001 /* If rounding needed, figure one more digit to ensure correct result */
9002 if (round)
9003 res_ndigits++;
9004 /* Add guard digits for roundoff error when producing approx result */
9005 if (!exact)
9006 res_ndigits += DIV_GUARD_DIGITS;
9007
9008 /*
9009 * The computation itself is done using base-NBASE^2 arithmetic, so we
9010 * actually process the input digits in pairs, producing a base-NBASE^2
9011 * intermediate result. This significantly improves performance, since
9012 * the computation is O(N^2) in the number of input digits, and working in
9013 * base NBASE^2 effectively halves "N".
9014 */
9015 var1ndigitpairs = (var1ndigits + 1) / 2;
9016 var2ndigitpairs = (var2ndigits + 1) / 2;
9017 res_ndigitpairs = (res_ndigits + 1) / 2;
9018 res_ndigits = 2 * res_ndigitpairs;
9019
9020 /*
9021 * We do the arithmetic in an array "dividend[]" of signed 64-bit
9022 * integers. Since PG_INT64_MAX is much larger than NBASE^4, this gives
9023 * us a lot of headroom to avoid normalizing carries immediately.
9024 *
9025 * When performing an exact computation, the working dividend requires
9026 * res_ndigitpairs + var2ndigitpairs digits. If var1 is larger than that,
9027 * the extra digits do not contribute to the result, and are ignored.
9028 *
9029 * When performing an approximate computation, the working dividend only
9030 * requires res_ndigitpairs digits (which includes the extra guard
9031 * digits). All input digits beyond that are ignored.
9032 */
9033 if (exact)
9034 {
9035 div_ndigitpairs = res_ndigitpairs + var2ndigitpairs;
9036 var1ndigitpairs = Min(var1ndigitpairs, div_ndigitpairs);
9037 }
9038 else
9039 {
9040 div_ndigitpairs = res_ndigitpairs;
9041 var1ndigitpairs = Min(var1ndigitpairs, div_ndigitpairs);
9042 var2ndigitpairs = Min(var2ndigitpairs, div_ndigitpairs);
9043 }
9044
9045 /*
9046 * Allocate room for the working dividend (div_ndigitpairs 64-bit digits)
9047 * plus the divisor (var2ndigitpairs 32-bit base-NBASE^2 digits).
9048 *
9049 * For convenience, we allocate one extra dividend digit, which is set to
9050 * zero and not counted in div_ndigitpairs, so that the main loop below
9051 * can safely read and write the (qi+1)'th digit in the approximate case.
9052 */
9053 dividend = (int64 *) palloc((div_ndigitpairs + 1) * sizeof(int64) +
9054 var2ndigitpairs * sizeof(int32));
9055 divisor = (int32 *) (dividend + div_ndigitpairs + 1);
9056
9057 /* load var1 into dividend[0 .. var1ndigitpairs-1], zeroing the rest */
9058 for (i = 0; i < var1ndigitpairs - 1; i++)
9059 dividend[i] = var1->digits[2 * i] * NBASE + var1->digits[2 * i + 1];
9060
9061 if (2 * i + 1 < var1ndigits)
9062 dividend[i] = var1->digits[2 * i] * NBASE + var1->digits[2 * i + 1];
9063 else
9064 dividend[i] = var1->digits[2 * i] * NBASE;
9065
9066 memset(dividend + i + 1, 0, (div_ndigitpairs - i) * sizeof(int64));
9067
9068 /* load var2 into divisor[0 .. var2ndigitpairs-1] */
9069 for (i = 0; i < var2ndigitpairs - 1; i++)
9070 divisor[i] = var2->digits[2 * i] * NBASE + var2->digits[2 * i + 1];
9071
9072 if (2 * i + 1 < var2ndigits)
9073 divisor[i] = var2->digits[2 * i] * NBASE + var2->digits[2 * i + 1];
9074 else
9075 divisor[i] = var2->digits[2 * i] * NBASE;
9076
9077 /*
9078 * We estimate each quotient digit using floating-point arithmetic, taking
9079 * the first 2 base-NBASE^2 digits of the (current) dividend and divisor.
9080 * This must be float to avoid overflow.
9081 *
9082 * Since the floating-point dividend and divisor use 4 base-NBASE input
9083 * digits, they include roughly 40-53 bits of information from their
9084 * respective inputs (assuming NBASE is 10000), which fits well in IEEE
9085 * double-precision variables. The relative error in the floating-point
9086 * quotient digit will then be less than around 2/NBASE^3, so the
9087 * estimated base-NBASE^2 quotient digit will typically be correct, and
9088 * should not be off by more than one from the correct value.
9089 */
9090 fdivisor = (double) divisor[0] * NBASE_SQR;
9091 if (var2ndigitpairs > 1)
9092 fdivisor += (double) divisor[1];
9093 fdivisorinverse = 1.0 / fdivisor;
9094
9095 /*
9096 * maxdiv tracks the maximum possible absolute value of any dividend[]
9097 * entry; when this threatens to exceed PG_INT64_MAX, we take the time to
9098 * propagate carries. Furthermore, we need to ensure that overflow
9099 * doesn't occur during the carry propagation passes either. The carry
9100 * values may have an absolute value as high as PG_INT64_MAX/NBASE^2 + 1,
9101 * so really we must normalize when digits threaten to exceed PG_INT64_MAX
9102 * - PG_INT64_MAX/NBASE^2 - 1.
9103 *
9104 * To avoid overflow in maxdiv itself, it represents the max absolute
9105 * value divided by NBASE^2-1, i.e., at the top of the loop it is known
9106 * that no dividend[] entry has an absolute value exceeding maxdiv *
9107 * (NBASE^2-1).
9108 *
9109 * Actually, though, that holds good only for dividend[] entries after
9110 * dividend[qi]; the adjustment done at the bottom of the loop may cause
9111 * dividend[qi + 1] to exceed the maxdiv limit, so that dividend[qi] in
9112 * the next iteration is beyond the limit. This does not cause problems,
9113 * as explained below.
9114 */
9115 maxdiv = 1;
9116
9117 /*
9118 * Outer loop computes next quotient digit, which goes in dividend[qi].
9119 */
9120 for (qi = 0; qi < res_ndigitpairs; qi++)
9121 {
9122 /* Approximate the current dividend value */
9123 fdividend = (double) dividend[qi] * NBASE_SQR;
9124 fdividend += (double) dividend[qi + 1];
9125
9126 /* Compute the (approximate) quotient digit */
9127 fquotient = fdividend * fdivisorinverse;
9128 qdigit = (fquotient >= 0.0) ? ((int32) fquotient) :
9129 (((int32) fquotient) - 1); /* truncate towards -infinity */
9130
9131 if (qdigit != 0)
9132 {
9133 /* Do we need to normalize now? */
9134 maxdiv += i64abs(qdigit);
9135 if (maxdiv > (PG_INT64_MAX - PG_INT64_MAX / NBASE_SQR - 1) / (NBASE_SQR - 1))
9136 {
9137 /*
9138 * Yes, do it. Note that if var2ndigitpairs is much smaller
9139 * than div_ndigitpairs, we can save a significant amount of
9140 * effort here by noting that we only need to normalise those
9141 * dividend[] entries touched where prior iterations
9142 * subtracted multiples of the divisor.
9143 */
9144 carry = 0;
9145 for (i = Min(qi + var2ndigitpairs - 2, div_ndigitpairs - 1); i > qi; i--)
9146 {
9147 newdig = dividend[i] + carry;
9148 if (newdig < 0)
9149 {
9150 carry = -((-newdig - 1) / NBASE_SQR) - 1;
9151 newdig -= carry * NBASE_SQR;
9152 }
9153 else if (newdig >= NBASE_SQR)
9154 {
9155 carry = newdig / NBASE_SQR;
9156 newdig -= carry * NBASE_SQR;
9157 }
9158 else
9159 carry = 0;
9160 dividend[i] = newdig;
9161 }
9162 dividend[qi] += carry;
9163
9164 /*
9165 * All the dividend[] digits except possibly dividend[qi] are
9166 * now in the range 0..NBASE^2-1. We do not need to consider
9167 * dividend[qi] in the maxdiv value anymore, so we can reset
9168 * maxdiv to 1.
9169 */
9170 maxdiv = 1;
9171
9172 /*
9173 * Recompute the quotient digit since new info may have
9174 * propagated into the top two dividend digits.
9175 */
9176 fdividend = (double) dividend[qi] * NBASE_SQR;
9177 fdividend += (double) dividend[qi + 1];
9178 fquotient = fdividend * fdivisorinverse;
9179 qdigit = (fquotient >= 0.0) ? ((int32) fquotient) :
9180 (((int32) fquotient) - 1); /* truncate towards -infinity */
9181
9182 maxdiv += i64abs(qdigit);
9183 }
9184
9185 /*
9186 * Subtract off the appropriate multiple of the divisor.
9187 *
9188 * The digits beyond dividend[qi] cannot overflow, because we know
9189 * they will fall within the maxdiv limit. As for dividend[qi]
9190 * itself, note that qdigit is approximately trunc(dividend[qi] /
9191 * divisor[0]), which would make the new value simply dividend[qi]
9192 * mod divisor[0]. The lower-order terms in qdigit can change
9193 * this result by not more than about twice PG_INT64_MAX/NBASE^2,
9194 * so overflow is impossible.
9195 *
9196 * This inner loop is the performance bottleneck for division, so
9197 * code it in the same way as the inner loop of mul_var() so that
9198 * it can be auto-vectorized.
9199 */
9200 if (qdigit != 0)
9201 {
9202 int istop = Min(var2ndigitpairs, div_ndigitpairs - qi);
9203 int64 *dividend_qi = &dividend[qi];
9204
9205 for (i = 0; i < istop; i++)
9206 dividend_qi[i] -= (int64) qdigit * divisor[i];
9207 }
9208 }
9209
9210 /*
9211 * The dividend digit we are about to replace might still be nonzero.
9212 * Fold it into the next digit position.
9213 *
9214 * There is no risk of overflow here, although proving that requires
9215 * some care. Much as with the argument for dividend[qi] not
9216 * overflowing, if we consider the first two terms in the numerator
9217 * and denominator of qdigit, we can see that the final value of
9218 * dividend[qi + 1] will be approximately a remainder mod
9219 * (divisor[0]*NBASE^2 + divisor[1]). Accounting for the lower-order
9220 * terms is a bit complicated but ends up adding not much more than
9221 * PG_INT64_MAX/NBASE^2 to the possible range. Thus, dividend[qi + 1]
9222 * cannot overflow here, and in its role as dividend[qi] in the next
9223 * loop iteration, it can't be large enough to cause overflow in the
9224 * carry propagation step (if any), either.
9225 *
9226 * But having said that: dividend[qi] can be more than
9227 * PG_INT64_MAX/NBASE^2, as noted above, which means that the product
9228 * dividend[qi] * NBASE^2 *can* overflow. When that happens, adding
9229 * it to dividend[qi + 1] will always cause a canceling overflow so
9230 * that the end result is correct. We could avoid the intermediate
9231 * overflow by doing the multiplication and addition using unsigned
9232 * int64 arithmetic, which is modulo 2^64, but so far there appears no
9233 * need.
9234 */
9235 dividend[qi + 1] += dividend[qi] * NBASE_SQR;
9236
9237 dividend[qi] = qdigit;
9238 }
9239
9240 /*
9241 * If an exact result was requested, use the remainder to correct the
9242 * approximate quotient. The remainder is in dividend[], immediately
9243 * after the quotient digits. Note, however, that although the remainder
9244 * starts at dividend[qi = res_ndigitpairs], the first digit is the result
9245 * of folding two remainder digits into one above, and the remainder
9246 * currently only occupies var2ndigitpairs - 1 digits (the last digit of
9247 * the working dividend was untouched by the computation above). Thus we
9248 * expand the remainder down by one base-NBASE^2 digit when we normalize
9249 * it, so that it completely fills the last var2ndigitpairs digits of the
9250 * dividend array.
9251 */
9252 if (exact)
9253 {
9254 /* Normalize the remainder, expanding it down by one digit */
9255 remainder = &dividend[qi];
9256 carry = 0;
9257 for (i = var2ndigitpairs - 2; i >= 0; i--)
9258 {
9259 newdig = remainder[i] + carry;
9260 if (newdig < 0)
9261 {
9262 carry = -((-newdig - 1) / NBASE_SQR) - 1;
9263 newdig -= carry * NBASE_SQR;
9264 }
9265 else if (newdig >= NBASE_SQR)
9266 {
9267 carry = newdig / NBASE_SQR;
9268 newdig -= carry * NBASE_SQR;
9269 }
9270 else
9271 carry = 0;
9272 remainder[i + 1] = newdig;
9273 }
9274 remainder[0] = carry;
9275
9276 if (remainder[0] < 0)
9277 {
9278 /*
9279 * The remainder is negative, so the approximate quotient is too
9280 * large. Correct by reducing the quotient by one and adding the
9281 * divisor to the remainder until the remainder is positive. We
9282 * expect the quotient to be off by at most one, which has been
9283 * borne out in all testing, but not conclusively proven, so we
9284 * allow for larger corrections, just in case.
9285 */
9286 do
9287 {
9288 /* Add the divisor to the remainder */
9289 carry = 0;
9290 for (i = var2ndigitpairs - 1; i > 0; i--)
9291 {
9292 newdig = remainder[i] + divisor[i] + carry;
9293 if (newdig >= NBASE_SQR)
9294 {
9295 remainder[i] = newdig - NBASE_SQR;
9296 carry = 1;
9297 }
9298 else
9299 {
9300 remainder[i] = newdig;
9301 carry = 0;
9302 }
9303 }
9304 remainder[0] += divisor[0] + carry;
9305
9306 /* Subtract 1 from the quotient (propagating carries later) */
9307 dividend[qi - 1]--;
9308
9309 } while (remainder[0] < 0);
9310 }
9311 else
9312 {
9313 /*
9314 * The remainder is nonnegative. If it's greater than or equal to
9315 * the divisor, then the approximate quotient is too small and
9316 * must be corrected. As above, we don't expect to have to apply
9317 * more than one correction, but allow for it just in case.
9318 */
9319 while (true)
9320 {
9321 bool less = false;
9322
9323 /* Is remainder < divisor? */
9324 for (i = 0; i < var2ndigitpairs; i++)
9325 {
9326 if (remainder[i] < divisor[i])
9327 {
9328 less = true;
9329 break;
9330 }
9331 if (remainder[i] > divisor[i])
9332 break; /* remainder > divisor */
9333 }
9334 if (less)
9335 break; /* quotient is correct */
9336
9337 /* Subtract the divisor from the remainder */
9338 carry = 0;
9339 for (i = var2ndigitpairs - 1; i > 0; i--)
9340 {
9341 newdig = remainder[i] - divisor[i] + carry;
9342 if (newdig < 0)
9343 {
9344 remainder[i] = newdig + NBASE_SQR;
9345 carry = -1;
9346 }
9347 else
9348 {
9349 remainder[i] = newdig;
9350 carry = 0;
9351 }
9352 }
9353 remainder[0] = remainder[0] - divisor[0] + carry;
9354
9355 /* Add 1 to the quotient (propagating carries later) */
9356 dividend[qi - 1]++;
9357 }
9358 }
9359 }
9360
9361 /*
9362 * Because the quotient digits were estimates that might have been off by
9363 * one (and we didn't bother propagating carries when adjusting the
9364 * quotient above), some quotient digits might be out of range, so do a
9365 * final carry propagation pass to normalize back to base NBASE^2, and
9366 * construct the base-NBASE result digits. Note that this is still done
9367 * at full precision w/guard digits.
9368 */
9369 alloc_var(result, res_ndigits);
9370 res_digits = result->digits;
9371 carry = 0;
9372 for (i = res_ndigitpairs - 1; i >= 0; i--)
9373 {
9374 newdig = dividend[i] + carry;
9375 if (newdig < 0)
9376 {
9377 carry = -((-newdig - 1) / NBASE_SQR) - 1;
9378 newdig -= carry * NBASE_SQR;
9379 }
9380 else if (newdig >= NBASE_SQR)
9381 {
9382 carry = newdig / NBASE_SQR;
9383 newdig -= carry * NBASE_SQR;
9384 }
9385 else
9386 carry = 0;
9387 res_digits[2 * i + 1] = (NumericDigit) ((uint32) newdig % NBASE);
9388 res_digits[2 * i] = (NumericDigit) ((uint32) newdig / NBASE);
9389 }
9390 Assert(carry == 0);
9391
9392 pfree(dividend);
9393
9394 /*
9395 * Finally, round or truncate the result to the requested precision.
9396 */
9397 result->weight = res_weight;
9398 result->sign = res_sign;
9399
9400 /* Round or truncate to target rscale (and set result->dscale) */
9401 if (round)
9402 round_var(result, rscale);
9403 else
9404 trunc_var(result, rscale);
9405
9406 /* Strip leading and trailing zeroes */
9407 strip_var(result);
9408}
static void div_var_int(const NumericVar *var, int ival, int ival_weight, NumericVar *result, int rscale, bool round)
Definition: numeric.c:9418
#define DIV_GUARD_DIGITS
Definition: numeric.c:101
#define NBASE_SQR
Definition: numeric.c:106
static void alloc_var(NumericVar *var, int ndigits)
Definition: numeric.c:6683
int64_t int64
Definition: c.h:549
#define PG_INT64_MAX
Definition: c.h:611
uint32_t uint32
Definition: c.h:552
#define ERROR
Definition: elog.h:39
#define ereport(elevel,...)
Definition: elog.h:150
size_t remainder
#define Min(x, y)
Definition: numeric.c:14
if(TABLE==NULL||TABLE_index==NULL)
Definition: isn.c:81

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

Referenced by compute_bucket(), div_mod_var(), generate_series_numeric_support(), get_str_from_var_sci(), ln_var(), log_var(), mod_var(), numeric_div_safe(), numeric_div_trunc(), numeric_lcm(), numeric_stddev_internal(), and power_var_int().

◆ div_var_int()

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

Definition at line 9418 of file numeric.c.

9420{
9421 NumericDigit *var_digits = var->digits;
9422 int var_ndigits = var->ndigits;
9423 int res_sign;
9424 int res_weight;
9425 int res_ndigits;
9426 NumericDigit *res_buf;
9427 NumericDigit *res_digits;
9428 uint32 divisor;
9429 int i;
9430
9431 /* Guard against division by zero */
9432 if (ival == 0)
9433 ereport(ERROR,
9434 errcode(ERRCODE_DIVISION_BY_ZERO),
9435 errmsg("division by zero"));
9436
9437 /* Result zero check */
9438 if (var_ndigits == 0)
9439 {
9440 zero_var(result);
9441 result->dscale = rscale;
9442 return;
9443 }
9444
9445 /*
9446 * Determine the result sign, weight and number of digits to calculate.
9447 * The weight figured here is correct if the emitted quotient has no
9448 * leading zero digits; otherwise strip_var() will fix things up.
9449 */
9450 if (var->sign == NUMERIC_POS)
9451 res_sign = ival > 0 ? NUMERIC_POS : NUMERIC_NEG;
9452 else
9453 res_sign = ival > 0 ? NUMERIC_NEG : NUMERIC_POS;
9454 res_weight = var->weight - ival_weight;
9455 /* The number of accurate result digits we need to produce: */
9456 res_ndigits = res_weight + 1 + (rscale + DEC_DIGITS - 1) / DEC_DIGITS;
9457 /* ... but always at least 1 */
9458 res_ndigits = Max(res_ndigits, 1);
9459 /* If rounding needed, figure one more digit to ensure correct result */
9460 if (round)
9461 res_ndigits++;
9462
9463 res_buf = digitbuf_alloc(res_ndigits + 1);
9464 res_buf[0] = 0; /* spare digit for later rounding */
9465 res_digits = res_buf + 1;
9466
9467 /*
9468 * Now compute the quotient digits. This is the short division algorithm
9469 * described in Knuth volume 2, section 4.3.1 exercise 16, except that we
9470 * allow the divisor to exceed the internal base.
9471 *
9472 * In this algorithm, the carry from one digit to the next is at most
9473 * divisor - 1. Therefore, while processing the next digit, carry may
9474 * become as large as divisor * NBASE - 1, and so it requires a 64-bit
9475 * integer if this exceeds UINT_MAX.
9476 */
9477 divisor = abs(ival);
9478
9479 if (divisor <= UINT_MAX / NBASE)
9480 {
9481 /* carry cannot overflow 32 bits */
9482 uint32 carry = 0;
9483
9484 for (i = 0; i < res_ndigits; i++)
9485 {
9486 carry = carry * NBASE + (i < var_ndigits ? var_digits[i] : 0);
9487 res_digits[i] = (NumericDigit) (carry / divisor);
9488 carry = carry % divisor;
9489 }
9490 }
9491 else
9492 {
9493 /* carry may exceed 32 bits */
9494 uint64 carry = 0;
9495
9496 for (i = 0; i < res_ndigits; i++)
9497 {
9498 carry = carry * NBASE + (i < var_ndigits ? var_digits[i] : 0);
9499 res_digits[i] = (NumericDigit) (carry / divisor);
9500 carry = carry % divisor;
9501 }
9502 }
9503
9504 /* Store the quotient in result */
9505 digitbuf_free(result->buf);
9506 result->ndigits = res_ndigits;
9507 result->buf = res_buf;
9508 result->digits = res_digits;
9509 result->weight = res_weight;
9510 result->sign = res_sign;
9511
9512 /* Round or truncate to target rscale (and set result->dscale) */
9513 if (round)
9514 round_var(result, rscale);
9515 else
9516 trunc_var(result, rscale);
9517
9518 /* Strip leading/trailing zeroes */
9519 strip_var(result);
9520}
uint64_t uint64
Definition: c.h:553

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

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

◆ do_int128_accum()

static void do_int128_accum ( Int128AggState state,
int64  newval 
)
static

Definition at line 5447 of file numeric.c.

5448{
5449 if (state->calcSumX2)
5451
5452 int128_add_int64(&state->sumX, newval);
5453 state->N++;
5454}
#define newval
static void int128_add_int64(INT128 *i128, int64 v)
Definition: int128.h:117
static void int128_add_int64_mul_int64(INT128 *i128, int64 x, int64 y)
Definition: int128.h:203
Definition: regguts.h:323

References int128_add_int64(), int128_add_int64_mul_int64(), and newval.

Referenced by int2_accum(), int4_accum(), and int8_avg_accum().

◆ do_int128_discard()

static void do_int128_discard ( Int128AggState state,
int64  newval 
)
static

Definition at line 5460 of file numeric.c.

5461{
5462 if (state->calcSumX2)
5464
5465 int128_sub_int64(&state->sumX, newval);
5466 state->N--;
5467}
static void int128_sub_int64_mul_int64(INT128 *i128, int64 x, int64 y)
Definition: int128.h:266
static void int128_sub_int64(INT128 *i128, int64 v)
Definition: int128.h:179

References int128_sub_int64(), int128_sub_int64_mul_int64(), and newval.

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

◆ do_numeric_accum()

static void do_numeric_accum ( NumericAggState state,
Numeric  newval 
)
static

Definition at line 4785 of file numeric.c.

4786{
4787 NumericVar X;
4788 NumericVar X2;
4789 MemoryContext old_context;
4790
4791 /* Count NaN/infinity inputs separately from all else */
4793 {
4795 state->pInfcount++;
4796 else if (NUMERIC_IS_NINF(newval))
4797 state->nInfcount++;
4798 else
4799 state->NaNcount++;
4800 return;
4801 }
4802
4803 /* load processed number in short-lived context */
4805
4806 /*
4807 * Track the highest input dscale that we've seen, to support inverse
4808 * transitions (see do_numeric_discard).
4809 */
4810 if (X.dscale > state->maxScale)
4811 {
4812 state->maxScale = X.dscale;
4813 state->maxScaleCount = 1;
4814 }
4815 else if (X.dscale == state->maxScale)
4816 state->maxScaleCount++;
4817
4818 /* if we need X^2, calculate that in short-lived context */
4819 if (state->calcSumX2)
4820 {
4821 init_var(&X2);
4822 mul_var(&X, &X, &X2, X.dscale * 2);
4823 }
4824
4825 /* The rest of this needs to work in the aggregate context */
4826 old_context = MemoryContextSwitchTo(state->agg_context);
4827
4828 state->N++;
4829
4830 /* Accumulate sums */
4831 accum_sum_add(&(state->sumX), &X);
4832
4833 if (state->calcSumX2)
4834 accum_sum_add(&(state->sumX2), &X2);
4835
4836 MemoryContextSwitchTo(old_context);
4837}
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:124

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 int8_accum(), numeric_accum(), and numeric_avg_accum().

◆ do_numeric_discard()

static bool do_numeric_discard ( NumericAggState state,
Numeric  newval 
)
static

Definition at line 4855 of file numeric.c.

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

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

◆ duplicate_numeric()

static Numeric duplicate_numeric ( Numeric  num)
static

Definition at line 7493 of file numeric.c.

7494{
7495 Numeric res;
7496
7497 res = (Numeric) palloc(VARSIZE(num));
7498 memcpy(res, num, VARSIZE(num));
7499 return res;
7500}
struct NumericData * Numeric
Definition: numeric.h:57
static Size VARSIZE(const void *PTR)
Definition: varatt.h:298

References palloc(), and VARSIZE().

Referenced by numeric(), numeric_abs(), numeric_ceil(), numeric_exp(), numeric_floor(), numeric_inc(), numeric_ln(), numeric_mod_safe(), 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 10540 of file numeric.c.

10541{
10542 int ln_dweight;
10543
10544 /* Caller should fail on ln(negative), but for the moment return zero */
10545 if (var->sign != NUMERIC_POS)
10546 return 0;
10547
10548 if (cmp_var(var, &const_zero_point_nine) >= 0 &&
10549 cmp_var(var, &const_one_point_one) <= 0)
10550 {
10551 /*
10552 * 0.9 <= var <= 1.1
10553 *
10554 * ln(var) has a negative weight (possibly very large). To get a
10555 * reasonably accurate result, estimate it using ln(1+x) ~= x.
10556 */
10557 NumericVar x;
10558
10559 init_var(&x);
10560 sub_var(var, &const_one, &x);
10561
10562 if (x.ndigits > 0)
10563 {
10564 /* Use weight of most significant decimal digit of x */
10565 ln_dweight = x.weight * DEC_DIGITS + (int) log10(x.digits[0]);
10566 }
10567 else
10568 {
10569 /* x = 0. Since ln(1) = 0 exactly, we don't need extra digits */
10570 ln_dweight = 0;
10571 }
10572
10573 free_var(&x);
10574 }
10575 else
10576 {
10577 /*
10578 * Estimate the logarithm using the first couple of digits from the
10579 * input number. This will give an accurate result whenever the input
10580 * is not too close to 1.
10581 */
10582 if (var->ndigits > 0)
10583 {
10584 int digits;
10585 int dweight;
10586 double ln_var;
10587
10588 digits = var->digits[0];
10589 dweight = var->weight * DEC_DIGITS;
10590
10591 if (var->ndigits > 1)
10592 {
10593 digits = digits * NBASE + var->digits[1];
10594 dweight -= DEC_DIGITS;
10595 }
10596
10597 /*----------
10598 * We have var ~= digits * 10^dweight
10599 * so ln(var) ~= ln(digits) + dweight * ln(10)
10600 *----------
10601 */
10602 ln_var = log((double) digits) + dweight * 2.302585092994046;
10603 ln_dweight = (int) log10(fabs(ln_var));
10604 }
10605 else
10606 {
10607 /* Caller should fail on ln(0), but for the moment return zero */
10608 ln_dweight = 0;
10609 }
10610 }
10611
10612 return ln_dweight;
10613}
static const NumericVar const_zero_point_nine
Definition: numeric.c:438
static const NumericVar const_one_point_one
Definition: numeric.c:448
static void ln_var(const NumericVar *arg, NumericVar *result, int rscale)
Definition: numeric.c:10622
int digits
Definition: informix.c:691
int x
Definition: isn.c:75

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

10412{
10413 NumericVar x;
10414 NumericVar elem;
10415 int ni;
10416 double val;
10417 int dweight;
10418 int ndiv2;
10419 int sig_digits;
10420 int local_rscale;
10421
10422 init_var(&x);
10423 init_var(&elem);
10424
10426
10427 /*
10428 * Estimate the dweight of the result using floating point arithmetic, so
10429 * that we can choose an appropriate local rscale for the calculation.
10430 */
10432
10433 /* Guard against overflow/underflow */
10434 /* If you change this limit, see also power_var()'s limit */
10435 if (fabs(val) >= NUMERIC_MAX_RESULT_SCALE * 3)
10436 {
10437 if (val > 0)
10438 ereport(ERROR,
10439 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
10440 errmsg("value overflows numeric format")));
10441 zero_var(result);
10442 result->dscale = rscale;
10443 return;
10444 }
10445
10446 /* decimal weight = log10(e^x) = x * log10(e) */
10447 dweight = (int) (val * 0.434294481903252);
10448
10449 /*
10450 * Reduce x to the range -0.01 <= x <= 0.01 (approximately) by dividing by
10451 * 2^ndiv2, to improve the convergence rate of the Taylor series.
10452 *
10453 * Note that the overflow check above ensures that fabs(x) < 6000, which
10454 * means that ndiv2 <= 20 here.
10455 */
10456 if (fabs(val) > 0.01)
10457 {
10458 ndiv2 = 1;
10459 val /= 2;
10460
10461 while (fabs(val) > 0.01)
10462 {
10463 ndiv2++;
10464 val /= 2;
10465 }
10466
10467 local_rscale = x.dscale + ndiv2;
10468 div_var_int(&x, 1 << ndiv2, 0, &x, local_rscale, true);
10469 }
10470 else
10471 ndiv2 = 0;
10472
10473 /*
10474 * Set the scale for the Taylor series expansion. The final result has
10475 * (dweight + rscale + 1) significant digits. In addition, we have to
10476 * raise the Taylor series result to the power 2^ndiv2, which introduces
10477 * an error of up to around log10(2^ndiv2) digits, so work with this many
10478 * extra digits of precision (plus a few more for good measure).
10479 */
10480 sig_digits = 1 + dweight + rscale + (int) (ndiv2 * 0.301029995663981);
10481 sig_digits = Max(sig_digits, 0) + 8;
10482
10483 local_rscale = sig_digits - 1;
10484
10485 /*
10486 * Use the Taylor series
10487 *
10488 * exp(x) = 1 + x + x^2/2! + x^3/3! + ...
10489 *
10490 * Given the limited range of x, this should converge reasonably quickly.
10491 * We run the series until the terms fall below the local_rscale limit.
10492 */
10493 add_var(&const_one, &x, result);
10494
10495 mul_var(&x, &x, &elem, local_rscale);
10496 ni = 2;
10497 div_var_int(&elem, ni, 0, &elem, local_rscale, true);
10498
10499 while (elem.ndigits != 0)
10500 {
10501 add_var(result, &elem, result);
10502
10503 mul_var(&elem, &x, &elem, local_rscale);
10504 ni++;
10505 div_var_int(&elem, ni, 0, &elem, local_rscale, true);
10506 }
10507
10508 /*
10509 * Compensate for the argument range reduction. Since the weight of the
10510 * result doubles with each multiplication, we can reduce the local rscale
10511 * as we proceed.
10512 */
10513 while (ndiv2-- > 0)
10514 {
10515 local_rscale = sig_digits - result->weight * 2 * DEC_DIGITS;
10516 local_rscale = Max(local_rscale, NUMERIC_MIN_DISPLAY_SCALE);
10517 mul_var(result, result, result, local_rscale);
10518 }
10519
10520 /* Round to requested rscale */
10521 round_var(result, rscale);
10522
10523 free_var(&x);
10524 free_var(&elem);
10525}
static double numericvar_to_double_no_overflow(const NumericVar *var)
Definition: numeric.c:7971
#define NUMERIC_MAX_RESULT_SCALE
Definition: numeric.h:46
#define NUMERIC_MIN_DISPLAY_SCALE
Definition: numeric.h:44
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 4615 of file numeric.c.

4616{
4618 Numeric res;
4619 NumericVar result;
4620 char buf[FLT_DIG + 100];
4621 const char *endptr;
4622
4623 if (isnan(val))
4625
4626 if (isinf(val))
4627 {
4628 if (val < 0)
4630 else
4632 }
4633
4634 snprintf(buf, sizeof(buf), "%.*g", FLT_DIG, val);
4635
4636 init_var(&result);
4637
4638 /* Assume we need not worry about leading/trailing spaces */
4639 (void) set_var_from_str(buf, buf, &result, &endptr, NULL);
4640
4641 res = make_result(&result);
4642
4643 free_var(&result);
4644
4645 PG_RETURN_NUMERIC(res);
4646}
static const NumericVar const_pinf
Definition: numeric.c:454
static const NumericVar const_ninf
Definition: numeric.c:457
static bool set_var_from_str(const char *str, const char *cp, NumericVar *dest, const char **endptr, Node *escontext)
Definition: numeric.c:6742
static Numeric make_result(const NumericVar *var)
Definition: numeric.c:7605
static const NumericVar const_nan
Definition: numeric.c:451
float float4
Definition: c.h:648
#define PG_GETARG_FLOAT4(n)
Definition: fmgr.h:281
#define PG_RETURN_NUMERIC(x)
Definition: numeric.h:83
#define snprintf
Definition: port.h:260

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

Referenced by datum_to_jsonb_internal(), and JsonItemFromDatum().

◆ float8_numeric()

Datum float8_numeric ( PG_FUNCTION_ARGS  )

Definition at line 4521 of file numeric.c.

4522{
4524 Numeric res;
4525 NumericVar result;
4526 char buf[DBL_DIG + 100];
4527 const char *endptr;
4528
4529 if (isnan(val))
4531
4532 if (isinf(val))
4533 {
4534 if (val < 0)
4536 else
4538 }
4539
4540 snprintf(buf, sizeof(buf), "%.*g", DBL_DIG, val);
4541
4542 init_var(&result);
4543
4544 /* Assume we need not worry about leading/trailing spaces */
4545 (void) set_var_from_str(buf, buf, &result, &endptr, NULL);
4546
4547 res = make_result(&result);
4548
4549 free_var(&result);
4550
4551 PG_RETURN_NUMERIC(res);
4552}
double float8
Definition: c.h:649
#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, set_var_from_str(), snprintf, and val.

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

◆ floor_var()

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

Definition at line 9838 of file numeric.c.

9839{
9840 NumericVar tmp;
9841
9842 init_var(&tmp);
9843 set_var_from_var(var, &tmp);
9844
9845 trunc_var(&tmp, 0);
9846
9847 if (var->sign == NUMERIC_NEG && cmp_var(var, &tmp) != 0)
9848 sub_var(&tmp, &const_one, &tmp);
9849
9850 set_var_from_var(&tmp, result);
9851 free_var(&tmp);
9852}

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

Referenced by numeric_floor().

◆ free_var()

static void free_var ( NumericVar var)
static

◆ gcd_var()

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

Definition at line 9861 of file numeric.c.

9862{
9863 int res_dscale;
9864 int cmp;
9865 NumericVar tmp_arg;
9866 NumericVar mod;
9867
9868 res_dscale = Max(var1->dscale, var2->dscale);
9869
9870 /*
9871 * Arrange for var1 to be the number with the greater absolute value.
9872 *
9873 * This would happen automatically in the loop below, but avoids an
9874 * expensive modulo operation.
9875 */
9876 cmp = cmp_abs(var1, var2);
9877 if (cmp < 0)
9878 {
9879 const NumericVar *tmp = var1;
9880
9881 var1 = var2;
9882 var2 = tmp;
9883 }
9884
9885 /*
9886 * Also avoid the taking the modulo if the inputs have the same absolute
9887 * value, or if the smaller input is zero.
9888 */
9889 if (cmp == 0 || var2->ndigits == 0)
9890 {
9891 set_var_from_var(var1, result);
9892 result->sign = NUMERIC_POS;
9893 result->dscale = res_dscale;
9894 return;
9895 }
9896
9897 init_var(&tmp_arg);
9898 init_var(&mod);
9899
9900 /* Use the Euclidean algorithm to find the GCD */
9901 set_var_from_var(var1, &tmp_arg);
9902 set_var_from_var(var2, result);
9903
9904 for (;;)
9905 {
9906 /* this loop can take a while, so allow it to be interrupted */
9908
9909 mod_var(&tmp_arg, result, &mod);
9910 if (mod.ndigits == 0)
9911 break;
9912 set_var_from_var(result, &tmp_arg);
9913 set_var_from_var(&mod, result);
9914 }
9915 result->sign = NUMERIC_POS;
9916 result->dscale = res_dscale;
9917
9918 free_var(&tmp_arg);
9919 free_var(&mod);
9920}
static void mod_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition: numeric.c:9715
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:123
static int cmp(const chr *x, const chr *y, size_t len)
Definition: regc_locale.c:743

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

Referenced by numeric_gcd(), and numeric_lcm().

◆ generate_series_numeric()

Datum generate_series_numeric ( PG_FUNCTION_ARGS  )

Definition at line 1686 of file numeric.c.

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

References generate_series_step_numeric().

◆ generate_series_numeric_support()

Datum generate_series_numeric_support ( PG_FUNCTION_ARGS  )

Definition at line 1817 of file numeric.c.

1818{
1819 Node *rawreq = (Node *) PG_GETARG_POINTER(0);
1820 Node *ret = NULL;
1821
1822 if (IsA(rawreq, SupportRequestRows))
1823 {
1824 /* Try to estimate the number of rows returned */
1825 SupportRequestRows *req = (SupportRequestRows *) rawreq;
1826
1827 if (is_funcclause(req->node)) /* be paranoid */
1828 {
1829 List *args = ((FuncExpr *) req->node)->args;
1830 Node *arg1,
1831 *arg2,
1832 *arg3;
1833
1834 /* We can use estimated argument values here */
1837 if (list_length(args) >= 3)
1839 else
1840 arg3 = NULL;
1841
1842 /*
1843 * If any argument is constant NULL, we can safely assume that
1844 * zero rows are returned. Otherwise, if they're all non-NULL
1845 * constants, we can calculate the number of rows that will be
1846 * returned.
1847 */
1848 if ((IsA(arg1, Const) &&
1849 ((Const *) arg1)->constisnull) ||
1850 (IsA(arg2, Const) &&
1851 ((Const *) arg2)->constisnull) ||
1852 (arg3 != NULL && IsA(arg3, Const) &&
1853 ((Const *) arg3)->constisnull))
1854 {
1855 req->rows = 0;
1856 ret = (Node *) req;
1857 }
1858 else if (IsA(arg1, Const) &&
1859 IsA(arg2, Const) &&
1860 (arg3 == NULL || IsA(arg3, Const)))
1861 {
1862 Numeric start_num;
1863 Numeric stop_num;
1864 NumericVar step = const_one;
1865
1866 /*
1867 * If any argument is NaN or infinity, generate_series() will
1868 * error out, so we needn't produce an estimate.
1869 */
1870 start_num = DatumGetNumeric(((Const *) arg1)->constvalue);
1871 stop_num = DatumGetNumeric(((Const *) arg2)->constvalue);
1872
1873 if (NUMERIC_IS_SPECIAL(start_num) ||
1874 NUMERIC_IS_SPECIAL(stop_num))
1875 PG_RETURN_POINTER(NULL);
1876
1877 if (arg3)
1878 {
1879 Numeric step_num;
1880
1881 step_num = DatumGetNumeric(((Const *) arg3)->constvalue);
1882
1883 if (NUMERIC_IS_SPECIAL(step_num))
1884 PG_RETURN_POINTER(NULL);
1885
1886 init_var_from_num(step_num, &step);
1887 }
1888
1889 /*
1890 * The number of rows that will be returned is given by
1891 * floor((stop - start) / step) + 1, if the sign of step
1892 * matches the sign of stop - start. Otherwise, no rows will
1893 * be returned.
1894 */
1895 if (cmp_var(&step, &const_zero) != 0)
1896 {
1898 NumericVar stop;
1899 NumericVar res;
1900
1901 init_var_from_num(start_num, &start);
1902 init_var_from_num(stop_num, &stop);
1903
1904 init_var(&res);
1905 sub_var(&stop, &start, &res);
1906
1907 if (step.sign != res.sign)
1908 {
1909 /* no rows will be returned */
1910 req->rows = 0;
1911 ret = (Node *) req;
1912 }
1913 else
1914 {
1915 if (arg3)
1916 div_var(&res, &step, &res, 0, false, false);
1917 else
1918 trunc_var(&res, 0); /* step = 1 */
1919
1920 req->rows = numericvar_to_double_no_overflow(&res) + 1;
1921 ret = (Node *) req;
1922 }
1923
1924 free_var(&res);
1925 }
1926 }
1927 }
1928 }
1929
1930 PG_RETURN_POINTER(ret);
1931}
Node * estimate_expression_value(PlannerInfo *root, Node *node)
Definition: clauses.c:2411
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:276
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:361
return str start
static bool is_funcclause(const void *clause)
Definition: nodeFuncs.h:69
#define IsA(nodeptr, _type_)
Definition: nodes.h:164
static Numeric DatumGetNumeric(Datum X)
Definition: numeric.h:64
static int list_length(const List *l)
Definition: pg_list.h:152
#define lthird(l)
Definition: pg_list.h:188
#define linitial(l)
Definition: pg_list.h:178
#define lsecond(l)
Definition: pg_list.h:183
Definition: pg_list.h:54
Definition: nodes.h:135
PlannerInfo * root
Definition: supportnodes.h:218

References generate_unaccent_rules::args, cmp_var(), const_one, const_zero, DatumGetNumeric(), div_var(), estimate_expression_value(), free_var(), init_var, init_var_from_num(), is_funcclause(), IsA, linitial, list_length(), lsecond, lthird, SupportRequestRows::node, NUMERIC_IS_SPECIAL, numericvar_to_double_no_overflow(), PG_GETARG_POINTER, PG_RETURN_POINTER, SupportRequestRows::root, SupportRequestRows::rows, NumericVar::sign, start, sub_var(), and trunc_var().

◆ generate_series_step_numeric()

Datum generate_series_step_numeric ( PG_FUNCTION_ARGS  )

Definition at line 1692 of file numeric.c.

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

4113{
4114 int min_scale;
4115 int last_digit_pos;
4116
4117 /*
4118 * Ordinarily, the input value will be "stripped" so that the last
4119 * NumericDigit is nonzero. But we don't want to get into an infinite
4120 * loop if it isn't, so explicitly find the last nonzero digit.
4121 */
4122 last_digit_pos = var->ndigits - 1;
4123 while (last_digit_pos >= 0 &&
4124 var->digits[last_digit_pos] == 0)
4125 last_digit_pos--;
4126
4127 if (last_digit_pos >= 0)
4128 {
4129 /* compute min_scale assuming that last ndigit has no zeroes */
4130 min_scale = (last_digit_pos - var->weight) * DEC_DIGITS;
4131
4132 /*
4133 * We could get a negative result if there are no digits after the
4134 * decimal point. In this case the min_scale must be zero.
4135 */
4136 if (min_scale > 0)
4137 {
4138 /*
4139 * Reduce min_scale if trailing digit(s) in last NumericDigit are
4140 * zero.
4141 */
4142 NumericDigit last_digit = var->digits[last_digit_pos];
4143
4144 while (last_digit % 10 == 0)
4145 {
4146 min_scale--;
4147 last_digit /= 10;
4148 }
4149 }
4150 else
4151 min_scale = 0;
4152 }
4153 else
4154 min_scale = 0; /* result if input is zero */
4155
4156 return min_scale;
4157}

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

7225{
7226 int dscale;
7227 char *str;
7228 char *cp;
7229 char *endcp;
7230 int i;
7231 int d;
7232 NumericDigit dig;
7233
7234#if DEC_DIGITS > 1
7235 NumericDigit d1;
7236#endif
7237
7238 dscale = var->dscale;
7239
7240 /*
7241 * Allocate space for the result.
7242 *
7243 * i is set to the # of decimal digits before decimal point. dscale is the
7244 * # of decimal digits we will print after decimal point. We may generate
7245 * as many as DEC_DIGITS-1 excess digits at the end, and in addition we
7246 * need room for sign, decimal point, null terminator.
7247 */
7248 i = (var->weight + 1) * DEC_DIGITS;
7249 if (i <= 0)
7250 i = 1;
7251
7252 str = palloc(i + dscale + DEC_DIGITS + 2);
7253 cp = str;
7254
7255 /*
7256 * Output a dash for negative values
7257 */
7258 if (var->sign == NUMERIC_NEG)
7259 *cp++ = '-';
7260
7261 /*
7262 * Output all digits before the decimal point
7263 */
7264 if (var->weight < 0)
7265 {
7266 d = var->weight + 1;
7267 *cp++ = '0';
7268 }
7269 else
7270 {
7271 for (d = 0; d <= var->weight; d++)
7272 {
7273 dig = (d < var->ndigits) ? var->digits[d] : 0;
7274 /* In the first digit, suppress extra leading decimal zeroes */
7275#if DEC_DIGITS == 4
7276 {
7277 bool putit = (d > 0);
7278
7279 d1 = dig / 1000;
7280 dig -= d1 * 1000;
7281 putit |= (d1 > 0);
7282 if (putit)
7283 *cp++ = d1 + '0';
7284 d1 = dig / 100;
7285 dig -= d1 * 100;
7286 putit |= (d1 > 0);
7287 if (putit)
7288 *cp++ = d1 + '0';
7289 d1 = dig / 10;
7290 dig -= d1 * 10;
7291 putit |= (d1 > 0);
7292 if (putit)
7293 *cp++ = d1 + '0';
7294 *cp++ = dig + '0';
7295 }
7296#elif DEC_DIGITS == 2
7297 d1 = dig / 10;
7298 dig -= d1 * 10;
7299 if (d1 > 0 || d > 0)
7300 *cp++ = d1 + '0';
7301 *cp++ = dig + '0';
7302#elif DEC_DIGITS == 1
7303 *cp++ = dig + '0';
7304#else
7305#error unsupported NBASE
7306#endif
7307 }
7308 }
7309
7310 /*
7311 * If requested, output a decimal point and all the digits that follow it.
7312 * We initially put out a multiple of DEC_DIGITS digits, then truncate if
7313 * needed.
7314 */
7315 if (dscale > 0)
7316 {
7317 *cp++ = '.';
7318 endcp = cp + dscale;
7319 for (i = 0; i < dscale; d++, i += DEC_DIGITS)
7320 {
7321 dig = (d >= 0 && d < var->ndigits) ? var->digits[d] : 0;
7322#if DEC_DIGITS == 4
7323 d1 = dig / 1000;
7324 dig -= d1 * 1000;
7325 *cp++ = d1 + '0';
7326 d1 = dig / 100;
7327 dig -= d1 * 100;
7328 *cp++ = d1 + '0';
7329 d1 = dig / 10;
7330 dig -= d1 * 10;
7331 *cp++ = d1 + '0';
7332 *cp++ = dig + '0';
7333#elif DEC_DIGITS == 2
7334 d1 = dig / 10;
7335 dig -= d1 * 10;
7336 *cp++ = d1 + '0';
7337 *cp++ = dig + '0';
7338#elif DEC_DIGITS == 1
7339 *cp++ = dig + '0';
7340#else
7341#error unsupported NBASE
7342#endif
7343 }
7344 cp = endcp;
7345 }
7346
7347 /*
7348 * terminate the string and return it
7349 */
7350 *cp = '\0';
7351 return str;
7352}
const char * str
static void error(void)
Definition: sql-dyntest.c:147

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

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

◆ get_str_from_var_sci()

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

Definition at line 7377 of file numeric.c.

7378{
7379 int32 exponent;
7380 NumericVar tmp_var;
7381 size_t len;
7382 char *str;
7383 char *sig_out;
7384
7385 if (rscale < 0)
7386 rscale = 0;
7387
7388 /*
7389 * Determine the exponent of this number in normalised form.
7390 *
7391 * This is the exponent required to represent the number with only one
7392 * significant digit before the decimal place.
7393 */
7394 if (var->ndigits > 0)
7395 {
7396 exponent = (var->weight + 1) * DEC_DIGITS;
7397
7398 /*
7399 * Compensate for leading decimal zeroes in the first numeric digit by
7400 * decrementing the exponent.
7401 */
7402 exponent -= DEC_DIGITS - (int) log10(var->digits[0]);
7403 }
7404 else
7405 {
7406 /*
7407 * If var has no digits, then it must be zero.
7408 *
7409 * Zero doesn't technically have a meaningful exponent in normalised
7410 * notation, but we just display the exponent as zero for consistency
7411 * of output.
7412 */
7413 exponent = 0;
7414 }
7415
7416 /*
7417 * Divide var by 10^exponent to get the significand, rounding to rscale
7418 * decimal digits in the process.
7419 */
7420 init_var(&tmp_var);
7421
7422 power_ten_int(exponent, &tmp_var);
7423 div_var(var, &tmp_var, &tmp_var, rscale, true, true);
7424 sig_out = get_str_from_var(&tmp_var);
7425
7426 free_var(&tmp_var);
7427
7428 /*
7429 * Allocate space for the result.
7430 *
7431 * In addition to the significand, we need room for the exponent
7432 * decoration ("e"), the sign of the exponent, up to 10 digits for the
7433 * exponent itself, and of course the null terminator.
7434 */
7435 len = strlen(sig_out) + 13;
7436 str = palloc(len);
7437 snprintf(str, len, "%se%+03d", sig_out, exponent);
7438
7439 pfree(sig_out);
7440
7441 return str;
7442}
static char * get_str_from_var(const NumericVar *var)
Definition: numeric.c:7224
static void power_ten_int(int exp, NumericVar *result)
Definition: numeric.c:11167
const void size_t len

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

Referenced by numeric_out_sci().

◆ hash_numeric()

Datum hash_numeric ( PG_FUNCTION_ARGS  )

Definition at line 2713 of file numeric.c.

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

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

2794{
2796 uint64 seed = PG_GETARG_INT64(1);
2797 Datum digit_hash;
2798 Datum result;
2799 int weight;
2800 int start_offset;
2801 int end_offset;
2802 int i;
2803 int hash_len;
2805
2806 /* If it's NaN or infinity, don't try to hash the rest of the fields */
2808 PG_RETURN_UINT64(seed);
2809
2810 weight = NUMERIC_WEIGHT(key);
2811 start_offset = 0;
2812 end_offset = 0;
2813
2815 for (i = 0; i < NUMERIC_NDIGITS(key); i++)
2816 {
2817 if (digits[i] != (NumericDigit) 0)
2818 break;
2819
2820 start_offset++;
2821
2822 weight--;
2823 }
2824
2825 if (NUMERIC_NDIGITS(key) == start_offset)
2826 PG_RETURN_UINT64(seed - 1);
2827
2828 for (i = NUMERIC_NDIGITS(key) - 1; i >= 0; i--)
2829 {
2830 if (digits[i] != (NumericDigit) 0)
2831 break;
2832
2833 end_offset++;
2834 }
2835
2836 Assert(start_offset + end_offset < NUMERIC_NDIGITS(key));
2837
2838 hash_len = NUMERIC_NDIGITS(key) - start_offset - end_offset;
2839 digit_hash = hash_any_extended((unsigned char *) (NUMERIC_DIGITS(key)
2840 + start_offset),
2841 hash_len * sizeof(NumericDigit),
2842 seed);
2843
2844 result = UInt64GetDatum(DatumGetUInt64(digit_hash) ^ weight);
2845
2846 PG_RETURN_DATUM(result);
2847}
#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:413
static Datum UInt64GetDatum(uint64 X)
Definition: postgres.h:423

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

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

◆ int128_deserialize()

static INT128 int128_deserialize ( StringInfo  buf)
inlinestatic

Definition at line 5578 of file numeric.c.

5579{
5580 int64 hi = pq_getmsgint64(buf);
5582
5583 return make_int128(hi, lo);
5584}
static INT128 make_int128(int64 hi, uint64 lo)
Definition: int128.h:75
int64 pq_getmsgint64(StringInfo msg)
Definition: pqformat.c:452

References buf, make_int128(), and pq_getmsgint64().

Referenced by int8_avg_deserialize(), and numeric_poly_deserialize().

◆ int128_serialize()

static void int128_serialize ( StringInfo  buf,
INT128  val 
)
inlinestatic

Definition at line 5568 of file numeric.c.

5569{
5572}
#define PG_INT128_HI_INT64(i128)
Definition: int128.h:65
#define PG_INT128_LO_UINT64(i128)
Definition: int128.h:66
static void pq_sendint64(StringInfo buf, uint64 i)
Definition: pqformat.h:152

References buf, PG_INT128_HI_INT64, PG_INT128_LO_UINT64, pq_sendint64(), and val.

Referenced by int8_avg_serialize(), and numeric_poly_serialize().

◆ int128_to_numericvar()

static void int128_to_numericvar ( INT128  val,
NumericVar var 
)
static

Definition at line 7935 of file numeric.c.

7936{
7937 int sign;
7938 NumericDigit *ptr;
7939 int ndigits;
7940 int32 dig;
7941
7942 /* int128 can require at most 39 decimal digits; add one for safety */
7943 alloc_var(var, 40 / DEC_DIGITS);
7944 sign = int128_sign(val);
7945 var->sign = sign < 0 ? NUMERIC_NEG : NUMERIC_POS;
7946 var->dscale = 0;
7947 if (sign == 0)
7948 {
7949 var->ndigits = 0;
7950 var->weight = 0;
7951 return;
7952 }
7953 ptr = var->digits + var->ndigits;
7954 ndigits = 0;
7955 do
7956 {
7957 ptr--;
7958 ndigits++;
7960 *ptr = (NumericDigit) abs(dig);
7961 } while (!int128_is_zero(val));
7962 var->digits = ptr;
7963 var->ndigits = ndigits;
7964 var->weight = ndigits - 1;
7965}
char sign
Definition: informix.c:693
static bool int128_is_zero(INT128 x)
Definition: int128.h:389
static int int128_sign(INT128 x)
Definition: int128.h:402
static void int128_div_mod_int32(INT128 *i128, int32 v, int32 *remainder)
Definition: int128.h:308

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

Referenced by int64_div_fast_to_numeric(), numeric_poly_avg(), numeric_poly_stddev_internal(), numeric_poly_sum(), and sqrt_var().

◆ int2_accum()

Datum int2_accum ( PG_FUNCTION_ARGS  )

Definition at line 5470 of file numeric.c.

5471{
5473
5475
5476 /* Create the state data on the first call */
5477 if (state == NULL)
5478 state = makeInt128AggState(fcinfo, true);
5479
5480 if (!PG_ARGISNULL(1))
5482
5484}
static Int128AggState * makeInt128AggState(FunctionCallInfo fcinfo, bool calcSumX2)
Definition: numeric.c:5409
static void do_int128_accum(Int128AggState *state, int64 newval)
Definition: numeric.c:5447
#define PG_ARGISNULL(n)
Definition: fmgr.h:209
#define PG_GETARG_INT16(n)
Definition: fmgr.h:271

References do_int128_accum(), makeInt128AggState(), 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 5796 of file numeric.c.

5797{
5799
5801
5802 /* Should not get here with no state */
5803 if (state == NULL)
5804 elog(ERROR, "int2_accum_inv called with NULL state");
5805
5806 if (!PG_ARGISNULL(1))
5808
5810}
static void do_int128_discard(Int128AggState *state, int64 newval)
Definition: numeric.c:5460
#define elog(elevel,...)
Definition: elog.h:226

References do_int128_discard(), elog, ERROR, 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 6387 of file numeric.c.

6388{
6389 ArrayType *transarray;
6391 Int8TransTypeData *transdata;
6392
6393 /*
6394 * If we're invoked as an aggregate, we can cheat and modify our first
6395 * parameter in-place to reduce palloc overhead. Otherwise we need to make
6396 * a copy of it before scribbling on it.
6397 */
6398 if (AggCheckCallContext(fcinfo, NULL))
6399 transarray = PG_GETARG_ARRAYTYPE_P(0);
6400 else
6401 transarray = PG_GETARG_ARRAYTYPE_P_COPY(0);
6402
6403 if (ARR_HASNULL(transarray) ||
6404 ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
6405 elog(ERROR, "expected 2-element int8 array");
6406
6407 transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
6408 transdata->count++;
6409 transdata->sum += newval;
6410
6411 PG_RETURN_ARRAYTYPE_P(transarray);
6412}
#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:4607

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

6475{
6476 ArrayType *transarray;
6478 Int8TransTypeData *transdata;
6479
6480 /*
6481 * If we're invoked as an aggregate, we can cheat and modify our first
6482 * parameter in-place to reduce palloc overhead. Otherwise we need to make
6483 * a copy of it before scribbling on it.
6484 */
6485 if (AggCheckCallContext(fcinfo, NULL))
6486 transarray = PG_GETARG_ARRAYTYPE_P(0);
6487 else
6488 transarray = PG_GETARG_ARRAYTYPE_P_COPY(0);
6489
6490 if (ARR_HASNULL(transarray) ||
6491 ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
6492 elog(ERROR, "expected 2-element int8 array");
6493
6494 transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
6495 transdata->count--;
6496 transdata->sum -= newval;
6497
6498 PG_RETURN_ARRAYTYPE_P(transarray);
6499}

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

4473{
4475
4477}
Numeric int64_to_numeric(int64 val)
Definition: numeric.c:4259

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

Referenced by JsonItemFromDatum().

◆ int2_sum()

Datum int2_sum ( PG_FUNCTION_ARGS  )

Definition at line 6280 of file numeric.c.

6281{
6282 int64 oldsum;
6283 int64 newval;
6284
6285 if (PG_ARGISNULL(0))
6286 {
6287 /* No non-null input seen so far... */
6288 if (PG_ARGISNULL(1))
6289 PG_RETURN_NULL(); /* still no non-null */
6290 /* This is the first non-null input. */
6293 }
6294
6295 oldsum = PG_GETARG_INT64(0);
6296
6297 /* Leave sum unchanged if new input is null. */
6298 if (PG_ARGISNULL(1))
6299 PG_RETURN_INT64(oldsum);
6300
6301 /* OK to do the addition. */
6302 newval = oldsum + (int64) PG_GETARG_INT16(1);
6303
6305}
#define PG_RETURN_INT64(x)
Definition: fmgr.h:368
#define PG_RETURN_NULL()
Definition: fmgr.h:345

References newval, PG_ARGISNULL, PG_GETARG_INT16, PG_GETARG_INT64, PG_RETURN_INT64, and PG_RETURN_NULL.

◆ int2int4_sum()

Datum int2int4_sum ( PG_FUNCTION_ARGS  )

Definition at line 6557 of file numeric.c.

6558{
6559 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
6560 Int8TransTypeData *transdata;
6561
6562 if (ARR_HASNULL(transarray) ||
6563 ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
6564 elog(ERROR, "expected 2-element int8 array");
6565 transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
6566
6567 /* SQL defines SUM of no values to be NULL */
6568 if (transdata->count == 0)
6570
6572}
#define Int64GetDatumFast(X)
Definition: postgres.h:515

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

5488{
5490
5492
5493 /* Create the state data on the first call */
5494 if (state == NULL)
5495 state = makeInt128AggState(fcinfo, true);
5496
5497 if (!PG_ARGISNULL(1))
5499
5501}
#define PG_GETARG_INT32(n)
Definition: fmgr.h:269

References do_int128_accum(), makeInt128AggState(), 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 5813 of file numeric.c.

5814{
5816
5818
5819 /* Should not get here with no state */
5820 if (state == NULL)
5821 elog(ERROR, "int4_accum_inv called with NULL state");
5822
5823 if (!PG_ARGISNULL(1))
5825
5827}

References do_int128_discard(), elog, ERROR, 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 6415 of file numeric.c.

6416{
6417 ArrayType *transarray;
6419 Int8TransTypeData *transdata;
6420
6421 /*
6422 * If we're invoked as an aggregate, we can cheat and modify our first
6423 * parameter in-place to reduce palloc overhead. Otherwise we need to make
6424 * a copy of it before scribbling on it.
6425 */
6426 if (AggCheckCallContext(fcinfo, NULL))
6427 transarray = PG_GETARG_ARRAYTYPE_P(0);
6428 else
6429 transarray = PG_GETARG_ARRAYTYPE_P_COPY(0);
6430
6431 if (ARR_HASNULL(transarray) ||
6432 ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
6433 elog(ERROR, "expected 2-element int8 array");
6434
6435 transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
6436 transdata->count++;
6437 transdata->sum += newval;
6438
6439 PG_RETURN_ARRAYTYPE_P(transarray);
6440}

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

6503{
6504 ArrayType *transarray;
6506 Int8TransTypeData *transdata;
6507
6508 /*
6509 * If we're invoked as an aggregate, we can cheat and modify our first
6510 * parameter in-place to reduce palloc overhead. Otherwise we need to make
6511 * a copy of it before scribbling on it.
6512 */
6513 if (AggCheckCallContext(fcinfo, NULL))
6514 transarray = PG_GETARG_ARRAYTYPE_P(0);
6515 else
6516 transarray = PG_GETARG_ARRAYTYPE_P_COPY(0);
6517
6518 if (ARR_HASNULL(transarray) ||
6519 ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
6520 elog(ERROR, "expected 2-element int8 array");
6521
6522 transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
6523 transdata->count--;
6524 transdata->sum -= newval;
6525
6526 PG_RETURN_ARRAYTYPE_P(transarray);
6527}

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

6444{
6445 ArrayType *transarray1;
6446 ArrayType *transarray2;
6447 Int8TransTypeData *state1;
6448 Int8TransTypeData *state2;
6449
6450 if (!AggCheckCallContext(fcinfo, NULL))
6451 elog(ERROR, "aggregate function called in non-aggregate context");
6452
6453 transarray1 = PG_GETARG_ARRAYTYPE_P(0);
6454 transarray2 = PG_GETARG_ARRAYTYPE_P(1);
6455
6456 if (ARR_HASNULL(transarray1) ||
6457 ARR_SIZE(transarray1) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
6458 elog(ERROR, "expected 2-element int8 array");
6459
6460 if (ARR_HASNULL(transarray2) ||
6461 ARR_SIZE(transarray2) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
6462 elog(ERROR, "expected 2-element int8 array");
6463
6464 state1 = (Int8TransTypeData *) ARR_DATA_PTR(transarray1);
6465 state2 = (Int8TransTypeData *) ARR_DATA_PTR(transarray2);
6466
6467 state1->count += state2->count;
6468 state1->sum += state2->sum;
6469
6470 PG_RETURN_ARRAYTYPE_P(transarray1);
6471}

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

4354{
4356
4358}

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

Referenced by executeItemOptUnwrapTarget(), and JsonItemFromDatum().

◆ int4_sum()

Datum int4_sum ( PG_FUNCTION_ARGS  )

Definition at line 6308 of file numeric.c.

6309{
6310 int64 oldsum;
6311 int64 newval;
6312
6313 if (PG_ARGISNULL(0))
6314 {
6315 /* No non-null input seen so far... */
6316 if (PG_ARGISNULL(1))
6317 PG_RETURN_NULL(); /* still no non-null */
6318 /* This is the first non-null input. */
6321 }
6322
6323 oldsum = PG_GETARG_INT64(0);
6324
6325 /* Leave sum unchanged if new input is null. */
6326 if (PG_ARGISNULL(1))
6327 PG_RETURN_INT64(oldsum);
6328
6329 /* OK to do the addition. */
6330 newval = oldsum + (int64) PG_GETARG_INT32(1);
6331
6333}

References newval, PG_ARGISNULL, PG_GETARG_INT32, PG_GETARG_INT64, PG_RETURN_INT64, and PG_RETURN_NULL.

◆ int64_div_fast_to_numeric()

Numeric int64_div_fast_to_numeric ( int64  val1,
int  log10val2 
)

Definition at line 4280 of file numeric.c.

4281{
4282 Numeric res;
4283 NumericVar result;
4284 int rscale;
4285 int w;
4286 int m;
4287
4288 init_var(&result);
4289
4290 /* result scale */
4291 rscale = log10val2 < 0 ? 0 : log10val2;
4292
4293 /* how much to decrease the weight by */
4294 w = log10val2 / DEC_DIGITS;
4295 /* how much is left to divide by */
4296 m = log10val2 % DEC_DIGITS;
4297 if (m < 0)
4298 {
4299 m += DEC_DIGITS;
4300 w--;
4301 }
4302
4303 /*
4304 * If there is anything left to divide by (10^m with 0 < m < DEC_DIGITS),
4305 * multiply the dividend by 10^(DEC_DIGITS - m), and shift the weight by
4306 * one more.
4307 */
4308 if (m > 0)
4309 {
4310#if DEC_DIGITS == 4
4311 static const int pow10[] = {1, 10, 100, 1000};
4312#elif DEC_DIGITS == 2
4313 static const int pow10[] = {1, 10};
4314#elif DEC_DIGITS == 1
4315 static const int pow10[] = {1};
4316#else
4317#error unsupported NBASE
4318#endif
4319 int64 factor = pow10[DEC_DIGITS - m];
4320 int64 new_val1;
4321
4322 StaticAssertDecl(lengthof(pow10) == DEC_DIGITS, "mismatch with DEC_DIGITS");
4323
4324 if (unlikely(pg_mul_s64_overflow(val1, factor, &new_val1)))
4325 {
4326 /* do the multiplication using 128-bit integers */
4327 INT128 tmp;
4328
4329 tmp = int64_to_int128(0);
4330 int128_add_int64_mul_int64(&tmp, val1, factor);
4331
4332 int128_to_numericvar(tmp, &result);
4333 }
4334 else
4335 int64_to_numericvar(new_val1, &result);
4336
4337 w++;
4338 }
4339 else
4340 int64_to_numericvar(val1, &result);
4341
4342 result.weight -= w;
4343 result.dscale = rscale;
4344
4345 res = make_result(&result);
4346
4347 free_var(&result);
4348
4349 return res;
4350}
static void int64_to_numericvar(int64 val, NumericVar *var)
Definition: numeric.c:7818
static void int128_to_numericvar(INT128 val, NumericVar *var)
Definition: numeric.c:7935
#define unlikely(x)
Definition: c.h:418
#define lengthof(array)
Definition: c.h:801
#define StaticAssertDecl(condition, errmessage)
Definition: c.h:948
static INT128 int64_to_int128(int64 v)
Definition: int128.h:450
static bool pg_mul_s64_overflow(int64 a, int64 b, int64 *result)
Definition: int.h:293
Definition: int128.h:55

References DEC_DIGITS, NumericVar::dscale, free_var(), init_var, int128_add_int64_mul_int64(), int128_to_numericvar(), int64_to_int128(), int64_to_numericvar(), lengthof, make_result(), pg_mul_s64_overflow(), 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 7818 of file numeric.c.

7819{
7820 uint64 uval,
7821 newuval;
7822 NumericDigit *ptr;
7823 int ndigits;
7824
7825 /* int64 can require at most 19 decimal digits; add one for safety */
7826 alloc_var(var, 20 / DEC_DIGITS);
7827 if (val < 0)
7828 {
7829 var->sign = NUMERIC_NEG;
7830 uval = pg_abs_s64(val);
7831 }
7832 else
7833 {
7834 var->sign = NUMERIC_POS;
7835 uval = val;
7836 }
7837 var->dscale = 0;
7838 if (val == 0)
7839 {
7840 var->ndigits = 0;
7841 var->weight = 0;
7842 return;
7843 }
7844 ptr = var->digits + var->ndigits;
7845 ndigits = 0;
7846 do
7847 {
7848 ptr--;
7849 ndigits++;
7850 newuval = uval / NBASE;
7851 *ptr = uval - newuval * NBASE;
7852 uval = newuval;
7853 } while (uval);
7854 var->digits = ptr;
7855 var->ndigits = ndigits;
7856 var->weight = ndigits - 1;
7857}
static uint64 pg_abs_s64(int64 a)
Definition: int.h:352

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

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

◆ int8_accum()

Datum int8_accum ( PG_FUNCTION_ARGS  )

Definition at line 5504 of file numeric.c.

5505{
5507
5509
5510 /* Create the state data on the first call */
5511 if (state == NULL)
5512 state = makeNumericAggState(fcinfo, true);
5513
5514 if (!PG_ARGISNULL(1))
5516
5518}
static NumericAggState * makeNumericAggState(FunctionCallInfo fcinfo, bool calcSumX2)
Definition: numeric.c:4745
static void do_numeric_accum(NumericAggState *state, Numeric newval)
Definition: numeric.c:4785

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

5831{
5833
5835
5836 /* Should not get here with no state */
5837 if (state == NULL)
5838 elog(ERROR, "int8_accum_inv called with NULL state");
5839
5840 if (!PG_ARGISNULL(1))
5841 {
5842 /* Should never fail, all inputs have dscale 0 */
5844 elog(ERROR, "do_numeric_discard failed unexpectedly");
5845 }
5846
5848}
static bool do_numeric_discard(NumericAggState *state, Numeric newval)
Definition: numeric.c:4855

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

6531{
6532 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
6533 Int8TransTypeData *transdata;
6534 Datum countd,
6535 sumd;
6536
6537 if (ARR_HASNULL(transarray) ||
6538 ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
6539 elog(ERROR, "expected 2-element int8 array");
6540 transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
6541
6542 /* SQL defines AVG of no values to be NULL */
6543 if (transdata->count == 0)
6545
6546 countd = NumericGetDatum(int64_to_numeric(transdata->count));
6547 sumd = NumericGetDatum(int64_to_numeric(transdata->sum));
6548
6550}
Datum numeric_div(PG_FUNCTION_ARGS)
Definition: numeric.c:3134
#define DirectFunctionCall2(func, arg1, arg2)
Definition: fmgr.h:684

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

5665{
5667
5669
5670 /* Create the state data on the first call */
5671 if (state == NULL)
5672 state = makeInt128AggState(fcinfo, false);
5673
5674 if (!PG_ARGISNULL(1))
5676
5678}

References do_int128_accum(), makeInt128AggState(), 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 5851 of file numeric.c.

5852{
5854
5856
5857 /* Should not get here with no state */
5858 if (state == NULL)
5859 elog(ERROR, "int8_avg_accum_inv called with NULL state");
5860
5861 if (!PG_ARGISNULL(1))
5863
5865}

References do_int128_discard(), elog, ERROR, 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 5685 of file numeric.c.

5686{
5687 Int128AggState *state1;
5688 Int128AggState *state2;
5689 MemoryContext agg_context;
5690 MemoryContext old_context;
5691
5692 if (!AggCheckCallContext(fcinfo, &agg_context))
5693 elog(ERROR, "aggregate function called in non-aggregate context");
5694
5695 state1 = PG_ARGISNULL(0) ? NULL : (Int128AggState *) PG_GETARG_POINTER(0);
5696 state2 = PG_ARGISNULL(1) ? NULL : (Int128AggState *) PG_GETARG_POINTER(1);
5697
5698 if (state2 == NULL)
5699 PG_RETURN_POINTER(state1);
5700
5701 /* manually copy all fields from state2 to state1 */
5702 if (state1 == NULL)
5703 {
5704 old_context = MemoryContextSwitchTo(agg_context);
5705
5706 state1 = makeInt128AggState(fcinfo, false);
5707 state1->N = state2->N;
5708 state1->sumX = state2->sumX;
5709
5710 MemoryContextSwitchTo(old_context);
5711
5712 PG_RETURN_POINTER(state1);
5713 }
5714
5715 if (state2->N > 0)
5716 {
5717 state1->N += state2->N;
5718 int128_add_int128(&state1->sumX, state2->sumX);
5719 }
5720 PG_RETURN_POINTER(state1);
5721}
static void int128_add_int128(INT128 *i128, INT128 v)
Definition: int128.h:144
INT128 sumX
Definition: numeric.c:5400

References AggCheckCallContext(), elog, ERROR, int128_add_int128(), makeInt128AggState(), MemoryContextSwitchTo(), Int128AggState::N, PG_ARGISNULL, PG_GETARG_POINTER, PG_RETURN_POINTER, and Int128AggState::sumX.

◆ int8_avg_deserialize()

Datum int8_avg_deserialize ( PG_FUNCTION_ARGS  )

Definition at line 5760 of file numeric.c.

5761{
5762 bytea *sstate;
5763 Int128AggState *result;
5765
5766 if (!AggCheckCallContext(fcinfo, NULL))
5767 elog(ERROR, "aggregate function called in non-aggregate context");
5768
5769 sstate = PG_GETARG_BYTEA_PP(0);
5770
5771 /*
5772 * Initialize a StringInfo so that we can "receive" it using the standard
5773 * recv-function infrastructure.
5774 */
5776 VARSIZE_ANY_EXHDR(sstate));
5777
5778 result = makeInt128AggStateCurrentContext(false);
5779
5780 /* N */
5781 result->N = pq_getmsgint64(&buf);
5782
5783 /* sumX */
5784 result->sumX = int128_deserialize(&buf);
5785
5786 pq_getmsgend(&buf);
5787
5788 PG_RETURN_POINTER(result);
5789}
static INT128 int128_deserialize(StringInfo buf)
Definition: numeric.c:5578
static Int128AggState * makeInt128AggStateCurrentContext(bool calcSumX2)
Definition: numeric.c:5433
#define PG_GETARG_BYTEA_PP(n)
Definition: fmgr.h:308
void pq_getmsgend(StringInfo msg)
Definition: pqformat.c:634
static void initReadOnlyStringInfo(StringInfo str, char *data, int len)
Definition: stringinfo.h:157
Definition: c.h:706
static Size VARSIZE_ANY_EXHDR(const void *PTR)
Definition: varatt.h:472
static char * VARDATA_ANY(const void *PTR)
Definition: varatt.h:486

References AggCheckCallContext(), buf, elog, ERROR, initReadOnlyStringInfo(), int128_deserialize(), makeInt128AggStateCurrentContext(), Int128AggState::N, PG_GETARG_BYTEA_PP, PG_RETURN_POINTER, pq_getmsgend(), pq_getmsgint64(), Int128AggState::sumX, VARDATA_ANY(), and VARSIZE_ANY_EXHDR().

◆ int8_avg_serialize()

Datum int8_avg_serialize ( PG_FUNCTION_ARGS  )

Definition at line 5729 of file numeric.c.

5730{
5733 bytea *result;
5734
5735 /* Ensure we disallow calling when not in aggregate context */
5736 if (!AggCheckCallContext(fcinfo, NULL))
5737 elog(ERROR, "aggregate function called in non-aggregate context");
5738
5740
5742
5743 /* N */
5744 pq_sendint64(&buf, state->N);
5745
5746 /* sumX */
5747 int128_serialize(&buf, state->sumX);
5748
5749 result = pq_endtypsend(&buf);
5750
5751 PG_RETURN_BYTEA_P(result);
5752}
static void int128_serialize(StringInfo buf, INT128 val)
Definition: numeric.c:5568
#define PG_RETURN_BYTEA_P(x)
Definition: fmgr.h:371
void pq_begintypsend(StringInfo buf)
Definition: pqformat.c:325
bytea * pq_endtypsend(StringInfo buf)
Definition: pqformat.c:345

References AggCheckCallContext(), buf, elog, ERROR, int128_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 4423 of file numeric.c.

4424{
4426
4428}

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

Referenced by executeItemOptUnwrapTarget(), and JsonItemFromDatum().

◆ int8_sum()

Datum int8_sum ( PG_FUNCTION_ARGS  )

Definition at line 6339 of file numeric.c.

6340{
6341 Numeric oldsum;
6342
6343 if (PG_ARGISNULL(0))
6344 {
6345 /* No non-null input seen so far... */
6346 if (PG_ARGISNULL(1))
6347 PG_RETURN_NULL(); /* still no non-null */
6348 /* This is the first non-null input. */
6350 }
6351
6352 /*
6353 * Note that we cannot special-case the aggregate case here, as we do for
6354 * int2_sum and int4_sum: numeric is of variable size, so we cannot modify
6355 * our first parameter in-place.
6356 */
6357
6358 oldsum = PG_GETARG_NUMERIC(0);
6359
6360 /* Leave sum unchanged if new input is null. */
6361 if (PG_ARGISNULL(1))
6362 PG_RETURN_NUMERIC(oldsum);
6363
6364 /* OK to do the addition. */
6366 NumericGetDatum(oldsum),
6368}
Datum numeric_add(PG_FUNCTION_ARGS)
Definition: numeric.c:2864

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

900{
901 return typmod >= (int32) VARHDRSZ;
902}

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

10623{
10624 NumericVar x;
10625 NumericVar xx;
10626 int ni;
10627 NumericVar elem;
10628 NumericVar fact;
10629 int nsqrt;
10630 int local_rscale;
10631 int cmp;
10632
10634 if (cmp == 0)
10635 ereport(ERROR,
10636 (errcode(ERRCODE_INVALID_ARGUMENT_FOR_LOG),
10637 errmsg("cannot take logarithm of zero")));
10638 else if (cmp < 0)
10639 ereport(ERROR,
10640 (errcode(ERRCODE_INVALID_ARGUMENT_FOR_LOG),
10641 errmsg("cannot take logarithm of a negative number")));
10642
10643 init_var(&x);
10644 init_var(&xx);
10645 init_var(&elem);
10646 init_var(&fact);
10647
10649 set_var_from_var(&const_two, &fact);
10650
10651 /*
10652 * Reduce input into range 0.9 < x < 1.1 with repeated sqrt() operations.
10653 *
10654 * The final logarithm will have up to around rscale+6 significant digits.
10655 * Each sqrt() will roughly halve the weight of x, so adjust the local
10656 * rscale as we work so that we keep this many significant digits at each
10657 * step (plus a few more for good measure).
10658 *
10659 * Note that we allow local_rscale < 0 during this input reduction
10660 * process, which implies rounding before the decimal point. sqrt_var()
10661 * explicitly supports this, and it significantly reduces the work
10662 * required to reduce very large inputs to the required range. Once the
10663 * input reduction is complete, x.weight will be 0 and its display scale
10664 * will be non-negative again.
10665 */
10666 nsqrt = 0;
10667 while (cmp_var(&x, &const_zero_point_nine) <= 0)
10668 {
10669 local_rscale = rscale - x.weight * DEC_DIGITS / 2 + 8;
10670 sqrt_var(&x, &x, local_rscale);
10671 mul_var(&fact, &const_two, &fact, 0);
10672 nsqrt++;
10673 }
10674 while (cmp_var(&x, &const_one_point_one) >= 0)
10675 {
10676 local_rscale = rscale - x.weight * DEC_DIGITS / 2 + 8;
10677 sqrt_var(&x, &x, local_rscale);
10678 mul_var(&fact, &const_two, &fact, 0);
10679 nsqrt++;
10680 }
10681
10682 /*
10683 * We use the Taylor series for 0.5 * ln((1+z)/(1-z)),
10684 *
10685 * z + z^3/3 + z^5/5 + ...
10686 *
10687 * where z = (x-1)/(x+1) is in the range (approximately) -0.053 .. 0.048
10688 * due to the above range-reduction of x.
10689 *
10690 * The convergence of this is not as fast as one would like, but is
10691 * tolerable given that z is small.
10692 *
10693 * The Taylor series result will be multiplied by 2^(nsqrt+1), which has a
10694 * decimal weight of (nsqrt+1) * log10(2), so work with this many extra
10695 * digits of precision (plus a few more for good measure).
10696 */
10697 local_rscale = rscale + (int) ((nsqrt + 1) * 0.301029995663981) + 8;
10698
10699 sub_var(&x, &const_one, result);
10700 add_var(&x, &const_one, &elem);
10701 div_var(result, &elem, result, local_rscale, true, false);
10702 set_var_from_var(result, &xx);
10703 mul_var(result, result, &x, local_rscale);
10704
10705 ni = 1;
10706
10707 for (;;)
10708 {
10709 ni += 2;
10710 mul_var(&xx, &x, &xx, local_rscale);
10711 div_var_int(&xx, ni, 0, &elem, local_rscale, true);
10712
10713 if (elem.ndigits == 0)
10714 break;
10715
10716 add_var(result, &elem, result);
10717
10718 if (elem.weight < (result->weight - local_rscale * 2 / DEC_DIGITS))
10719 break;
10720 }
10721
10722 /* Compensate for argument range reduction, round to requested rscale */
10723 mul_var(result, &fact, result, rscale);
10724
10725 free_var(&x);
10726 free_var(&xx);
10727 free_var(&elem);
10728 free_var(&fact);
10729}
static const NumericVar const_two
Definition: numeric.c:428
static void sqrt_var(const NumericVar *arg, NumericVar *result, int rscale)
Definition: numeric.c:9931

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

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

◆ log_var()

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

Definition at line 10740 of file numeric.c.

10741{
10742 NumericVar ln_base;
10743 NumericVar ln_num;
10744 int ln_base_dweight;
10745 int ln_num_dweight;
10746 int result_dweight;
10747 int rscale;
10748 int ln_base_rscale;
10749 int ln_num_rscale;
10750
10751 init_var(&ln_base);
10752 init_var(&ln_num);
10753
10754 /* Estimated dweights of ln(base), ln(num) and the final result */
10755 ln_base_dweight = estimate_ln_dweight(base);
10756 ln_num_dweight = estimate_ln_dweight(num);
10757 result_dweight = ln_num_dweight - ln_base_dweight;
10758
10759 /*
10760 * Select the scale of the result so that it will have at least
10761 * NUMERIC_MIN_SIG_DIGITS significant digits and is not less than either
10762 * input's display scale.
10763 */
10764 rscale = NUMERIC_MIN_SIG_DIGITS - result_dweight;
10765 rscale = Max(rscale, base->dscale);
10766 rscale = Max(rscale, num->dscale);
10767 rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
10768 rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
10769
10770 /*
10771 * Set the scales for ln(base) and ln(num) so that they each have more
10772 * significant digits than the final result.
10773 */
10774 ln_base_rscale = rscale + result_dweight - ln_base_dweight + 8;
10775 ln_base_rscale = Max(ln_base_rscale, NUMERIC_MIN_DISPLAY_SCALE);
10776
10777 ln_num_rscale = rscale + result_dweight - ln_num_dweight + 8;
10778 ln_num_rscale = Max(ln_num_rscale, NUMERIC_MIN_DISPLAY_SCALE);
10779
10780 /* Form natural logarithms */
10781 ln_var(base, &ln_base, ln_base_rscale);
10782 ln_var(num, &ln_num, ln_num_rscale);
10783
10784 /* Divide and round to the required scale */
10785 div_var(&ln_num, &ln_base, result, rscale, true, false);
10786
10787 free_var(&ln_num);
10788 free_var(&ln_base);
10789}
static int estimate_ln_dweight(const NumericVar *var)
Definition: numeric.c:10540
#define NUMERIC_MAX_DISPLAY_SCALE
Definition: numeric.h:43
#define NUMERIC_MIN_SIG_DIGITS
Definition: numeric.h:53

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

Referenced by numeric_log().

◆ make_numeric_typmod()

static int32 make_numeric_typmod ( int  precision,
int  scale 
)
inlinestatic

Definition at line 890 of file numeric.c.

891{
892 return ((precision << 16) | (scale & 0x7ff)) + VARHDRSZ;
893}

References scale, and VARHDRSZ.

Referenced by numerictypmodin().

◆ make_result()

◆ make_result_safe()

static Numeric make_result_safe ( const NumericVar var,
Node escontext 
)
static

Definition at line 7509 of file numeric.c.

7510{
7511 Numeric result;
7512 NumericDigit *digits = var->digits;
7513 int weight = var->weight;
7514 int sign = var->sign;
7515 int n;
7516 Size len;
7517
7519 {
7520 /*
7521 * Verify valid special value. This could be just an Assert, perhaps,
7522 * but it seems worthwhile to expend a few cycles to ensure that we
7523 * never write any nonzero reserved bits to disk.
7524 */
7525 if (!(sign == NUMERIC_NAN ||
7526 sign == NUMERIC_PINF ||
7527 sign == NUMERIC_NINF))
7528 elog(ERROR, "invalid numeric sign value 0x%x", sign);
7529
7531
7533 result->choice.n_header = sign;
7534 /* the header word is all we need */
7535
7536 dump_numeric("make_result()", result);
7537 return result;
7538 }
7539
7540 n = var->ndigits;
7541
7542 /* truncate leading zeroes */
7543 while (n > 0 && *digits == 0)
7544 {
7545 digits++;
7546 weight--;
7547 n--;
7548 }
7549 /* truncate trailing zeroes */
7550 while (n > 0 && digits[n - 1] == 0)
7551 n--;
7552
7553 /* If zero result, force to weight=0 and positive sign */
7554 if (n == 0)
7555 {
7556 weight = 0;
7557 sign = NUMERIC_POS;
7558 }
7559
7560 /* Build the result */
7561 if (NUMERIC_CAN_BE_SHORT(var->dscale, weight))
7562 {
7563 len = NUMERIC_HDRSZ_SHORT + n * sizeof(NumericDigit);
7564 result = (Numeric) palloc(len);
7565 SET_VARSIZE(result, len);
7566 result->choice.n_short.n_header =
7568 : NUMERIC_SHORT)
7570 | (weight < 0 ? NUMERIC_SHORT_WEIGHT_SIGN_MASK : 0)
7571 | (weight & NUMERIC_SHORT_WEIGHT_MASK);
7572 }
7573 else
7574 {
7575 len = NUMERIC_HDRSZ + n * sizeof(NumericDigit);
7576 result = (Numeric) palloc(len);
7577 SET_VARSIZE(result, len);
7578 result->choice.n_long.n_sign_dscale =
7579 sign | (var->dscale & NUMERIC_DSCALE_MASK);
7580 result->choice.n_long.n_weight = weight;
7581 }
7582
7583 Assert(NUMERIC_NDIGITS(result) == n);
7584 if (n > 0)
7585 memcpy(NUMERIC_DIGITS(result), digits, n * sizeof(NumericDigit));
7586
7587 /* Check for overflow of int16 fields */
7588 if (NUMERIC_WEIGHT(result) != weight ||
7589 NUMERIC_DSCALE(result) != var->dscale)
7590 ereturn(escontext, NULL,
7591 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
7592 errmsg("value overflows numeric format")));
7593
7594 dump_numeric("make_result()", result);
7595 return result;
7596}
#define dump_numeric(s, n)
Definition: numeric.c:474
#define NUMERIC_CAN_BE_SHORT(scale, weight)
Definition: numeric.c:492
#define NUMERIC_HDRSZ_SHORT
Definition: numeric.c:179
#define NUMERIC_NINF
Definition: numeric.c:203
#define NUMERIC_SHORT
Definition: numeric.c:171
#define NUMERIC_HDRSZ
Definition: numeric.c:178
#define NUMERIC_SPECIAL
Definition: numeric.c:172
#define NUMERIC_SIGN_MASK
Definition: numeric.c:168
#define NUMERIC_PINF
Definition: numeric.c:202
size_t Size
Definition: c.h:624
union NumericChoice choice
Definition: numeric.c:160
uint16 n_header
Definition: numeric.c:152
static void SET_VARSIZE(void *PTR, Size len)
Definition: varatt.h:432

References Assert(), NumericData::choice, NumericVar::digits, digits, NumericVar::dscale, dump_numeric, elog, ereturn, 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_safe(), numeric_div_safe(), numeric_in(), numeric_mod_safe(), numeric_mul_safe(), and numeric_sub_safe().

◆ makeInt128AggState()

static Int128AggState * makeInt128AggState ( FunctionCallInfo  fcinfo,
bool  calcSumX2 
)
static

Definition at line 5409 of file numeric.c.

5410{
5412 MemoryContext agg_context;
5413 MemoryContext old_context;
5414
5415 if (!AggCheckCallContext(fcinfo, &agg_context))
5416 elog(ERROR, "aggregate function called in non-aggregate context");
5417
5418 old_context = MemoryContextSwitchTo(agg_context);
5419
5421 state->calcSumX2 = calcSumX2;
5422
5423 MemoryContextSwitchTo(old_context);
5424
5425 return state;
5426}
#define palloc0_object(type)
Definition: fe_memutils.h:75

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

Referenced by int2_accum(), int4_accum(), int8_avg_accum(), int8_avg_combine(), and numeric_poly_combine().

◆ makeInt128AggStateCurrentContext()

static Int128AggState * makeInt128AggStateCurrentContext ( bool  calcSumX2)
static

Definition at line 5433 of file numeric.c.

5434{
5436
5438 state->calcSumX2 = calcSumX2;
5439
5440 return state;
5441}

References palloc0_object.

Referenced by int8_avg_deserialize(), and numeric_poly_deserialize().

◆ makeNumericAggState()

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

Definition at line 4745 of file numeric.c.

4746{
4748 MemoryContext agg_context;
4749 MemoryContext old_context;
4750
4751 if (!AggCheckCallContext(fcinfo, &agg_context))
4752 elog(ERROR, "aggregate function called in non-aggregate context");
4753
4754 old_context = MemoryContextSwitchTo(agg_context);
4755
4757 state->calcSumX2 = calcSumX2;
4758 state->agg_context = agg_context;
4759
4760 MemoryContextSwitchTo(old_context);
4761
4762 return state;
4763}

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

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

◆ makeNumericAggStateCurrentContext()

static NumericAggState * makeNumericAggStateCurrentContext ( bool  calcSumX2)
static

Definition at line 4770 of file numeric.c.

4771{
4773
4775 state->calcSumX2 = calcSumX2;
4776 state->agg_context = CurrentMemoryContext;
4777
4778 return state;
4779}
MemoryContext CurrentMemoryContext
Definition: mcxt.c:160

References CurrentMemoryContext, and palloc0_object.

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

9716{
9717 NumericVar tmp;
9718
9719 init_var(&tmp);
9720
9721 /* ---------
9722 * We do this using the equation
9723 * mod(x,y) = x - trunc(x/y)*y
9724 * div_var can be persuaded to give us trunc(x/y) directly.
9725 * ----------
9726 */
9727 div_var(var1, var2, &tmp, 0, false, true);
9728
9729 mul_var(var2, &tmp, &tmp, var2->dscale);
9730
9731 sub_var(var1, &tmp, result);
9732
9733 free_var(&tmp);
9734}

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

Referenced by gcd_var(), and numeric_mod_safe().

◆ mul_var()

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

Definition at line 8299 of file numeric.c.

8301{
8302 int res_ndigits;
8303 int res_ndigitpairs;
8304 int res_sign;
8305 int res_weight;
8306 int pair_offset;
8307 int maxdigits;
8308 int maxdigitpairs;
8309 uint64 *dig,
8310 *dig_i1_off;
8311 uint64 maxdig;
8312 uint64 carry;
8313 uint64 newdig;
8314 int var1ndigits;
8315 int var2ndigits;
8316 int var1ndigitpairs;
8317 int var2ndigitpairs;
8318 NumericDigit *var1digits;
8319 NumericDigit *var2digits;
8320 uint32 var1digitpair;
8321 uint32 *var2digitpairs;
8322 NumericDigit *res_digits;
8323 int i,
8324 i1,
8325 i2,
8326 i2limit;
8327
8328 /*
8329 * Arrange for var1 to be the shorter of the two numbers. This improves
8330 * performance because the inner multiplication loop is much simpler than
8331 * the outer loop, so it's better to have a smaller number of iterations
8332 * of the outer loop. This also reduces the number of times that the
8333 * accumulator array needs to be normalized.
8334 */
8335 if (var1->ndigits > var2->ndigits)
8336 {
8337 const NumericVar *tmp = var1;
8338
8339 var1 = var2;
8340 var2 = tmp;
8341 }
8342
8343 /* copy these values into local vars for speed in inner loop */
8344 var1ndigits = var1->ndigits;
8345 var2ndigits = var2->ndigits;
8346 var1digits = var1->digits;
8347 var2digits = var2->digits;
8348
8349 if (var1ndigits == 0)
8350 {
8351 /* one or both inputs is zero; so is result */
8352 zero_var(result);
8353 result->dscale = rscale;
8354 return;
8355 }
8356
8357 /*
8358 * If var1 has 1-6 digits and the exact result was requested, delegate to
8359 * mul_var_short() which uses a faster direct multiplication algorithm.
8360 */
8361 if (var1ndigits <= 6 && rscale == var1->dscale + var2->dscale)
8362 {
8363 mul_var_short(var1, var2, result);
8364 return;
8365 }
8366
8367 /* Determine result sign */
8368 if (var1->sign == var2->sign)
8369 res_sign = NUMERIC_POS;
8370 else
8371 res_sign = NUMERIC_NEG;
8372
8373 /*
8374 * Determine the number of result digits to compute and the (maximum
8375 * possible) result weight. If the exact result would have more than
8376 * rscale fractional digits, truncate the computation with
8377 * MUL_GUARD_DIGITS guard digits, i.e., ignore input digits that would
8378 * only contribute to the right of that. (This will give the exact
8379 * rounded-to-rscale answer unless carries out of the ignored positions
8380 * would have propagated through more than MUL_GUARD_DIGITS digits.)
8381 *
8382 * Note: an exact computation could not produce more than var1ndigits +
8383 * var2ndigits digits, but we allocate at least one extra output digit in
8384 * case rscale-driven rounding produces a carry out of the highest exact
8385 * digit.
8386 *
8387 * The computation itself is done using base-NBASE^2 arithmetic, so we
8388 * actually process the input digits in pairs, producing a base-NBASE^2
8389 * intermediate result. This significantly improves performance, since
8390 * schoolbook multiplication is O(N^2) in the number of input digits, and
8391 * working in base NBASE^2 effectively halves "N".
8392 *
8393 * Note: in a truncated computation, we must compute at least one extra
8394 * output digit to ensure that all the guard digits are fully computed.
8395 */
8396 /* digit pairs in each input */
8397 var1ndigitpairs = (var1ndigits + 1) / 2;
8398 var2ndigitpairs = (var2ndigits + 1) / 2;
8399
8400 /* digits in exact result */
8401 res_ndigits = var1ndigits + var2ndigits;
8402
8403 /* digit pairs in exact result with at least one extra output digit */
8404 res_ndigitpairs = res_ndigits / 2 + 1;
8405
8406 /* pair offset to align result to end of dig[] */
8407 pair_offset = res_ndigitpairs - var1ndigitpairs - var2ndigitpairs + 1;
8408
8409 /* maximum possible result weight (odd-length inputs shifted up below) */
8410 res_weight = var1->weight + var2->weight + 1 + 2 * res_ndigitpairs -
8411 res_ndigits - (var1ndigits & 1) - (var2ndigits & 1);
8412
8413 /* rscale-based truncation with at least one extra output digit */
8414 maxdigits = res_weight + 1 + (rscale + DEC_DIGITS - 1) / DEC_DIGITS +
8416 maxdigitpairs = maxdigits / 2 + 1;
8417
8418 res_ndigitpairs = Min(res_ndigitpairs, maxdigitpairs);
8419 res_ndigits = 2 * res_ndigitpairs;
8420
8421 /*
8422 * In the computation below, digit pair i1 of var1 and digit pair i2 of
8423 * var2 are multiplied and added to digit i1+i2+pair_offset of dig[]. Thus
8424 * input digit pairs with index >= res_ndigitpairs - pair_offset don't
8425 * contribute to the result, and can be ignored.
8426 */
8427 if (res_ndigitpairs <= pair_offset)
8428 {
8429 /* All input digits will be ignored; so result is zero */
8430 zero_var(result);
8431 result->dscale = rscale;
8432 return;
8433 }
8434 var1ndigitpairs = Min(var1ndigitpairs, res_ndigitpairs - pair_offset);
8435 var2ndigitpairs = Min(var2ndigitpairs, res_ndigitpairs - pair_offset);
8436
8437 /*
8438 * We do the arithmetic in an array "dig[]" of unsigned 64-bit integers.
8439 * Since PG_UINT64_MAX is much larger than NBASE^4, this gives us a lot of
8440 * headroom to avoid normalizing carries immediately.
8441 *
8442 * maxdig tracks the maximum possible value of any dig[] entry; when this
8443 * threatens to exceed PG_UINT64_MAX, we take the time to propagate
8444 * carries. Furthermore, we need to ensure that overflow doesn't occur
8445 * during the carry propagation passes either. The carry values could be
8446 * as much as PG_UINT64_MAX / NBASE^2, so really we must normalize when
8447 * digits threaten to exceed PG_UINT64_MAX - PG_UINT64_MAX / NBASE^2.
8448 *
8449 * To avoid overflow in maxdig itself, it actually represents the maximum
8450 * possible value divided by NBASE^2-1, i.e., at the top of the loop it is
8451 * known that no dig[] entry exceeds maxdig * (NBASE^2-1).
8452 *
8453 * The conversion of var1 to base NBASE^2 is done on the fly, as each new
8454 * digit is required. The digits of var2 are converted upfront, and
8455 * stored at the end of dig[]. To avoid loss of precision, the input
8456 * digits are aligned with the start of digit pair array, effectively
8457 * shifting them up (multiplying by NBASE) if the inputs have an odd
8458 * number of NBASE digits.
8459 */
8460 dig = (uint64 *) palloc(res_ndigitpairs * sizeof(uint64) +
8461 var2ndigitpairs * sizeof(uint32));
8462
8463 /* convert var2 to base NBASE^2, shifting up if its length is odd */
8464 var2digitpairs = (uint32 *) (dig + res_ndigitpairs);
8465
8466 for (i2 = 0; i2 < var2ndigitpairs - 1; i2++)
8467 var2digitpairs[i2] = var2digits[2 * i2] * NBASE + var2digits[2 * i2 + 1];
8468
8469 if (2 * i2 + 1 < var2ndigits)
8470 var2digitpairs[i2] = var2digits[2 * i2] * NBASE + var2digits[2 * i2 + 1];
8471 else
8472 var2digitpairs[i2] = var2digits[2 * i2] * NBASE;
8473
8474 /*
8475 * Start by multiplying var2 by the least significant contributing digit
8476 * pair from var1, storing the results at the end of dig[], and filling
8477 * the leading digits with zeros.
8478 *
8479 * The loop here is the same as the inner loop below, except that we set
8480 * the results in dig[], rather than adding to them. This is the
8481 * performance bottleneck for multiplication, so we want to keep it simple
8482 * enough so that it can be auto-vectorized. Accordingly, process the
8483 * digits left-to-right even though schoolbook multiplication would
8484 * suggest right-to-left. Since we aren't propagating carries in this
8485 * loop, the order does not matter.
8486 */
8487 i1 = var1ndigitpairs - 1;
8488 if (2 * i1 + 1 < var1ndigits)
8489 var1digitpair = var1digits[2 * i1] * NBASE + var1digits[2 * i1 + 1];
8490 else
8491 var1digitpair = var1digits[2 * i1] * NBASE;
8492 maxdig = var1digitpair;
8493
8494 i2limit = Min(var2ndigitpairs, res_ndigitpairs - i1 - pair_offset);
8495 dig_i1_off = &dig[i1 + pair_offset];
8496
8497 memset(dig, 0, (i1 + pair_offset) * sizeof(uint64));
8498 for (i2 = 0; i2 < i2limit; i2++)
8499 dig_i1_off[i2] = (uint64) var1digitpair * var2digitpairs[i2];
8500
8501 /*
8502 * Next, multiply var2 by the remaining digit pairs from var1, adding the
8503 * results to dig[] at the appropriate offsets, and normalizing whenever
8504 * there is a risk of any dig[] entry overflowing.
8505 */
8506 for (i1 = i1 - 1; i1 >= 0; i1--)
8507 {
8508 var1digitpair = var1digits[2 * i1] * NBASE + var1digits[2 * i1 + 1];
8509 if (var1digitpair == 0)
8510 continue;
8511
8512 /* Time to normalize? */
8513 maxdig += var1digitpair;
8514 if (maxdig > (PG_UINT64_MAX - PG_UINT64_MAX / NBASE_SQR) / (NBASE_SQR - 1))
8515 {
8516 /* Yes, do it (to base NBASE^2) */
8517 carry = 0;
8518 for (i = res_ndigitpairs - 1; i >= 0; i--)
8519 {
8520 newdig = dig[i] + carry;
8521 if (newdig >= NBASE_SQR)
8522 {
8523 carry = newdig / NBASE_SQR;
8524 newdig -= carry * NBASE_SQR;
8525 }
8526 else
8527 carry = 0;
8528 dig[i] = newdig;
8529 }
8530 Assert(carry == 0);
8531 /* Reset maxdig to indicate new worst-case */
8532 maxdig = 1 + var1digitpair;
8533 }
8534
8535 /* Multiply and add */
8536 i2limit = Min(var2ndigitpairs, res_ndigitpairs - i1 - pair_offset);
8537 dig_i1_off = &dig[i1 + pair_offset];
8538
8539 for (i2 = 0; i2 < i2limit; i2++)
8540 dig_i1_off[i2] += (uint64) var1digitpair * var2digitpairs[i2];
8541 }
8542
8543 /*
8544 * Now we do a final carry propagation pass to normalize back to base
8545 * NBASE^2, and construct the base-NBASE result digits. Note that this is
8546 * still done at full precision w/guard digits.
8547 */
8548 alloc_var(result, res_ndigits);
8549 res_digits = result->digits;
8550 carry = 0;
8551 for (i = res_ndigitpairs - 1; i >= 0; i--)
8552 {
8553 newdig = dig[i] + carry;
8554 if (newdig >= NBASE_SQR)
8555 {
8556 carry = newdig / NBASE_SQR;
8557 newdig -= carry * NBASE_SQR;
8558 }
8559 else
8560 carry = 0;
8561 res_digits[2 * i + 1] = (NumericDigit) ((uint32) newdig % NBASE);
8562 res_digits[2 * i] = (NumericDigit) ((uint32) newdig / NBASE);
8563 }
8564 Assert(carry == 0);
8565
8566 pfree(dig);
8567
8568 /*
8569 * Finally, round the result to the requested precision.
8570 */
8571 result->weight = res_weight;
8572 result->sign = res_sign;
8573
8574 /* Round to target rscale (and set result->dscale) */
8575 round_var(result, rscale);
8576
8577 /* Strip leading and trailing zeroes */
8578 strip_var(result);
8579}
static void mul_var_short(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition: numeric.c:8590
#define MUL_GUARD_DIGITS
Definition: numeric.c:100
#define PG_UINT64_MAX
Definition: c.h:612

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

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

◆ mul_var_short()

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

Definition at line 8590 of file numeric.c.

8592{
8593 int var1ndigits = var1->ndigits;
8594 int var2ndigits = var2->ndigits;
8595 NumericDigit *var1digits = var1->digits;
8596 NumericDigit *var2digits = var2->digits;
8597 int res_sign;
8598 int res_weight;
8599 int res_ndigits;
8600 NumericDigit *res_buf;
8601 NumericDigit *res_digits;
8602 uint32 carry = 0;
8603 uint32 term;
8604
8605 /* Check preconditions */
8606 Assert(var1ndigits >= 1);
8607 Assert(var1ndigits <= 6);
8608 Assert(var2ndigits >= var1ndigits);
8609
8610 /*
8611 * Determine the result sign, weight, and number of digits to calculate.
8612 * The weight figured here is correct if the product has no leading zero
8613 * digits; otherwise strip_var() will fix things up. Note that, unlike
8614 * mul_var(), we do not need to allocate an extra output digit, because we
8615 * are not rounding here.
8616 */
8617 if (var1->sign == var2->sign)
8618 res_sign = NUMERIC_POS;
8619 else
8620 res_sign = NUMERIC_NEG;
8621 res_weight = var1->weight + var2->weight + 1;
8622 res_ndigits = var1ndigits + var2ndigits;
8623
8624 /* Allocate result digit array */
8625 res_buf = digitbuf_alloc(res_ndigits + 1);
8626 res_buf[0] = 0; /* spare digit for later rounding */
8627 res_digits = res_buf + 1;
8628
8629 /*
8630 * Compute the result digits in reverse, in one pass, propagating the
8631 * carry up as we go. The i'th result digit consists of the sum of the
8632 * products var1digits[i1] * var2digits[i2] for which i = i1 + i2 + 1.
8633 */
8634#define PRODSUM1(v1,i1,v2,i2) ((v1)[(i1)] * (v2)[(i2)])
8635#define PRODSUM2(v1,i1,v2,i2) (PRODSUM1(v1,i1,v2,i2) + (v1)[(i1)+1] * (v2)[(i2)-1])
8636#define PRODSUM3(v1,i1,v2,i2) (PRODSUM2(v1,i1,v2,i2) + (v1)[(i1)+2] * (v2)[(i2)-2])
8637#define PRODSUM4(v1,i1,v2,i2) (PRODSUM3(v1,i1,v2,i2) + (v1)[(i1)+3] * (v2)[(i2)-3])
8638#define PRODSUM5(v1,i1,v2,i2) (PRODSUM4(v1,i1,v2,i2) + (v1)[(i1)+4] * (v2)[(i2)-4])
8639#define PRODSUM6(v1,i1,v2,i2) (PRODSUM5(v1,i1,v2,i2) + (v1)[(i1)+5] * (v2)[(i2)-5])
8640
8641 switch (var1ndigits)
8642 {
8643 case 1:
8644 /* ---------
8645 * 1-digit case:
8646 * var1ndigits = 1
8647 * var2ndigits >= 1
8648 * res_ndigits = var2ndigits + 1
8649 * ----------
8650 */
8651 for (int i = var2ndigits - 1; i >= 0; i--)
8652 {
8653 term = PRODSUM1(var1digits, 0, var2digits, i) + carry;
8654 res_digits[i + 1] = (NumericDigit) (term % NBASE);
8655 carry = term / NBASE;
8656 }
8657 res_digits[0] = (NumericDigit) carry;
8658 break;
8659
8660 case 2:
8661 /* ---------
8662 * 2-digit case:
8663 * var1ndigits = 2
8664 * var2ndigits >= 2
8665 * res_ndigits = var2ndigits + 2
8666 * ----------
8667 */
8668 /* last result digit and carry */
8669 term = PRODSUM1(var1digits, 1, var2digits, var2ndigits - 1);
8670 res_digits[res_ndigits - 1] = (NumericDigit) (term % NBASE);
8671 carry = term / NBASE;
8672
8673 /* remaining digits, except for the first two */
8674 for (int i = var2ndigits - 1; i >= 1; i--)
8675 {
8676 term = PRODSUM2(var1digits, 0, var2digits, i) + carry;
8677 res_digits[i + 1] = (NumericDigit) (term % NBASE);
8678 carry = term / NBASE;
8679 }
8680 break;
8681
8682 case 3:
8683 /* ---------
8684 * 3-digit case:
8685 * var1ndigits = 3
8686 * var2ndigits >= 3
8687 * res_ndigits = var2ndigits + 3
8688 * ----------
8689 */
8690 /* last two result digits */
8691 term = PRODSUM1(var1digits, 2, var2digits, var2ndigits - 1);
8692 res_digits[res_ndigits - 1] = (NumericDigit) (term % NBASE);
8693 carry = term / NBASE;
8694
8695 term = PRODSUM2(var1digits, 1, var2digits, var2ndigits - 1) + carry;
8696 res_digits[res_ndigits - 2] = (NumericDigit) (term % NBASE);
8697 carry = term / NBASE;
8698
8699 /* remaining digits, except for the first three */
8700 for (int i = var2ndigits - 1; i >= 2; i--)
8701 {
8702 term = PRODSUM3(var1digits, 0, var2digits, i) + carry;
8703 res_digits[i + 1] = (NumericDigit) (term % NBASE);
8704 carry = term / NBASE;
8705 }
8706 break;
8707
8708 case 4:
8709 /* ---------
8710 * 4-digit case:
8711 * var1ndigits = 4
8712 * var2ndigits >= 4
8713 * res_ndigits = var2ndigits + 4
8714 * ----------
8715 */
8716 /* last three result digits */
8717 term = PRODSUM1(var1digits, 3, var2digits, var2ndigits - 1);
8718 res_digits[res_ndigits - 1] = (NumericDigit) (term % NBASE);
8719 carry = term / NBASE;
8720
8721 term = PRODSUM2(var1digits, 2, var2digits, var2ndigits - 1) + carry;
8722 res_digits[res_ndigits - 2] = (NumericDigit) (term % NBASE);
8723 carry = term / NBASE;
8724
8725 term = PRODSUM3(var1digits, 1, var2digits, var2ndigits - 1) + carry;
8726 res_digits[res_ndigits - 3] = (NumericDigit) (term % NBASE);
8727 carry = term / NBASE;
8728
8729 /* remaining digits, except for the first four */
8730 for (int i = var2ndigits - 1; i >= 3; i--)
8731 {
8732 term = PRODSUM4(var1digits, 0, var2digits, i) + carry;
8733 res_digits[i + 1] = (NumericDigit) (term % NBASE);
8734 carry = term / NBASE;
8735 }
8736 break;
8737
8738 case 5:
8739 /* ---------
8740 * 5-digit case:
8741 * var1ndigits = 5
8742 * var2ndigits >= 5
8743 * res_ndigits = var2ndigits + 5
8744 * ----------
8745 */
8746 /* last four result digits */
8747 term = PRODSUM1(var1digits, 4, var2digits, var2ndigits - 1);
8748 res_digits[res_ndigits - 1] = (NumericDigit) (term % NBASE);
8749 carry = term / NBASE;
8750
8751 term = PRODSUM2(var1digits, 3, var2digits, var2ndigits - 1) + carry;
8752 res_digits[res_ndigits - 2] = (NumericDigit) (term % NBASE);
8753 carry = term / NBASE;
8754
8755 term = PRODSUM3(var1digits, 2, var2digits, var2ndigits - 1) + carry;
8756 res_digits[res_ndigits - 3] = (NumericDigit) (term % NBASE);
8757 carry = term / NBASE;
8758
8759 term = PRODSUM4(var1digits, 1, var2digits, var2ndigits - 1) + carry;
8760 res_digits[res_ndigits - 4] = (NumericDigit) (term % NBASE);
8761 carry = term / NBASE;
8762
8763 /* remaining digits, except for the first five */
8764 for (int i = var2ndigits - 1; i >= 4; i--)
8765 {
8766 term = PRODSUM5(var1digits, 0, var2digits, i) + carry;
8767 res_digits[i + 1] = (NumericDigit) (term % NBASE);
8768 carry = term / NBASE;
8769 }
8770 break;
8771
8772 case 6:
8773 /* ---------
8774 * 6-digit case:
8775 * var1ndigits = 6
8776 * var2ndigits >= 6
8777 * res_ndigits = var2ndigits + 6
8778 * ----------
8779 */
8780 /* last five result digits */
8781 term = PRODSUM1(var1digits, 5, var2digits, var2ndigits - 1);
8782 res_digits[res_ndigits - 1] = (NumericDigit) (term % NBASE);
8783 carry = term / NBASE;
8784
8785 term = PRODSUM2(var1digits, 4, var2digits, var2ndigits - 1) + carry;
8786 res_digits[res_ndigits - 2] = (NumericDigit) (term % NBASE);
8787 carry = term / NBASE;
8788
8789 term = PRODSUM3(var1digits, 3, var2digits, var2ndigits - 1) + carry;
8790 res_digits[res_ndigits - 3] = (NumericDigit) (term % NBASE);
8791 carry = term / NBASE;
8792
8793 term = PRODSUM4(var1digits, 2, var2digits, var2ndigits - 1) + carry;
8794 res_digits[res_ndigits - 4] = (NumericDigit) (term % NBASE);
8795 carry = term / NBASE;
8796
8797 term = PRODSUM5(var1digits, 1, var2digits, var2ndigits - 1) + carry;
8798 res_digits[res_ndigits - 5] = (NumericDigit) (term % NBASE);
8799 carry = term / NBASE;
8800
8801 /* remaining digits, except for the first six */
8802 for (int i = var2ndigits - 1; i >= 5; i--)
8803 {
8804 term = PRODSUM6(var1digits, 0, var2digits, i) + carry;
8805 res_digits[i + 1] = (NumericDigit) (term % NBASE);
8806 carry = term / NBASE;
8807 }
8808 break;
8809 }
8810
8811 /*
8812 * Finally, for var1ndigits > 1, compute the remaining var1ndigits most
8813 * significant result digits.
8814 */
8815 switch (var1ndigits)
8816 {
8817 case 6:
8818 term = PRODSUM5(var1digits, 0, var2digits, 4) + carry;
8819 res_digits[5] = (NumericDigit) (term % NBASE);
8820 carry = term / NBASE;
8821 /* FALLTHROUGH */
8822 case 5:
8823 term = PRODSUM4(var1digits, 0, var2digits, 3) + carry;
8824 res_digits[4] = (NumericDigit) (term % NBASE);
8825 carry = term / NBASE;
8826 /* FALLTHROUGH */
8827 case 4:
8828 term = PRODSUM3(var1digits, 0, var2digits, 2) + carry;
8829 res_digits[3] = (NumericDigit) (term % NBASE);
8830 carry = term / NBASE;
8831 /* FALLTHROUGH */
8832 case 3:
8833 term = PRODSUM2(var1digits, 0, var2digits, 1) + carry;
8834 res_digits[2] = (NumericDigit) (term % NBASE);
8835 carry = term / NBASE;
8836 /* FALLTHROUGH */
8837 case 2:
8838 term = PRODSUM1(var1digits, 0, var2digits, 0) + carry;
8839 res_digits[1] = (NumericDigit) (term % NBASE);
8840 res_digits[0] = (NumericDigit) (term / NBASE);
8841 break;
8842 }
8843
8844 /* Store the product in result */
8845 digitbuf_free(result->buf);
8846 result->ndigits = res_ndigits;
8847 result->buf = res_buf;
8848 result->digits = res_digits;
8849 result->weight = res_weight;
8850 result->sign = res_sign;
8851 result->dscale = var1->dscale + var2->dscale;
8852
8853 /* Strip leading and trailing zeroes */
8854 strip_var(result);
8855}
#define PRODSUM2(v1, i1, v2, i2)
#define PRODSUM3(v1, i1, v2, i2)
#define PRODSUM1(v1, i1, v2, i2)
#define PRODSUM5(v1, i1, v2, i2)
#define PRODSUM6(v1, i1, v2, i2)
#define PRODSUM4(v1, i1, v2, i2)

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

Referenced by mul_var().

◆ numeric()

Definition at line 1229 of file numeric.c.

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

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

2212{
2213 NumericSortSupport *nss = ssup->ssup_extra;
2214 double abbr_card;
2215
2216 if (memtupcount < 10000 || nss->input_count < 10000 || !nss->estimating)
2217 return false;
2218
2219 abbr_card = estimateHyperLogLog(&nss->abbr_card);
2220
2221 /*
2222 * If we have >100k distinct values, then even if we were sorting many
2223 * billion rows we'd likely still break even, and the penalty of undoing
2224 * that many rows of abbrevs would probably not be worth it. Stop even
2225 * counting at that point.
2226 */
2227 if (abbr_card > 100000.0)
2228 {
2229 if (trace_sort)
2230 elog(LOG,
2231 "numeric_abbrev: estimation ends at cardinality %f"
2232 " after " INT64_FORMAT " values (%d rows)",
2233 abbr_card, nss->input_count, memtupcount);
2234 nss->estimating = false;
2235 return false;
2236 }
2237
2238 /*
2239 * Target minimum cardinality is 1 per ~10k of non-null inputs. (The
2240 * break even point is somewhere between one per 100k rows, where
2241 * abbreviation has a very slight penalty, and 1 per 10k where it wins by
2242 * a measurable percentage.) We use the relatively pessimistic 10k
2243 * threshold, and add a 0.5 row fudge factor, because it allows us to
2244 * abort earlier on genuinely pathological data where we've had exactly
2245 * one abbreviated value in the first 10k (non-null) rows.
2246 */
2247 if (abbr_card < nss->input_count / 10000.0 + 0.5)
2248 {
2249 if (trace_sort)
2250 elog(LOG,
2251 "numeric_abbrev: aborting abbreviation at cardinality %f"
2252 " below threshold %f after " INT64_FORMAT " values (%d rows)",
2253 abbr_card, nss->input_count / 10000.0 + 0.5,
2254 nss->input_count, memtupcount);
2255 return true;
2256 }
2257
2258 if (trace_sort)
2259 elog(LOG,
2260 "numeric_abbrev: cardinality %f"
2261 " after " INT64_FORMAT " values (%d rows)",
2262 abbr_card, nss->input_count, memtupcount);
2263
2264 return false;
2265}
#define INT64_FORMAT
Definition: c.h:570
#define LOG
Definition: elog.h:31
double estimateHyperLogLog(hyperLogLogState *cState)
Definition: hyperloglog.c:186
hyperLogLogState abbr_card
Definition: numeric.c:347
void * ssup_extra
Definition: sortsupport.h:87
bool trace_sort
Definition: tuplesort.c:122

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

2150{
2151 NumericSortSupport *nss = ssup->ssup_extra;
2152 void *original_varatt = PG_DETOAST_DATUM_PACKED(original_datum);
2153 Numeric value;
2154 Datum result;
2155
2156 nss->input_count += 1;
2157
2158 /*
2159 * This is to handle packed datums without needing a palloc/pfree cycle;
2160 * we keep and reuse a buffer large enough to handle any short datum.
2161 */
2162 if (VARATT_IS_SHORT(original_varatt))
2163 {
2164 void *buf = nss->buf;
2165 Size sz = VARSIZE_SHORT(original_varatt) - VARHDRSZ_SHORT;
2166
2168
2169 SET_VARSIZE(buf, VARHDRSZ + sz);
2170 memcpy(VARDATA(buf), VARDATA_SHORT(original_varatt), sz);
2171
2172 value = (Numeric) buf;
2173 }
2174 else
2175 value = (Numeric) original_varatt;
2176
2178 {
2180 result = NUMERIC_ABBREV_PINF;
2181 else if (NUMERIC_IS_NINF(value))
2182 result = NUMERIC_ABBREV_NINF;
2183 else
2184 result = NUMERIC_ABBREV_NAN;
2185 }
2186 else
2187 {
2188 NumericVar var;
2189
2190 init_var_from_num(value, &var);
2191
2192 result = numeric_abbrev_convert_var(&var, nss);
2193 }
2194
2195 /* should happen only for external/compressed toasts */
2196 if (original_varatt != DatumGetPointer(original_datum))
2197 pfree(original_varatt);
2198
2199 return result;
2200}
static Datum numeric_abbrev_convert_var(const NumericVar *var, NumericSortSupport *nss)
Definition: numeric.c:2359
#define NUMERIC_ABBREV_PINF
Definition: numeric.c:408
#define NUMERIC_ABBREV_NAN
Definition: numeric.c:407
#define NUMERIC_ABBREV_NINF
Definition: numeric.c:409
#define PG_DETOAST_DATUM_PACKED(datum)
Definition: fmgr.h:248
static struct @171 value
static Pointer DatumGetPointer(Datum X)
Definition: postgres.h:322
#define VARHDRSZ_SHORT
Definition: varatt.h:278
static bool VARATT_IS_SHORT(const void *PTR)
Definition: varatt.h:403
static char * VARDATA(const void *PTR)
Definition: varatt.h:305
#define VARATT_SHORT_MAX
Definition: varatt.h:279
static char * VARDATA_SHORT(const void *PTR)
Definition: varatt.h:319
static Size VARSIZE_SHORT(const void *PTR)
Definition: varatt.h:312

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

Definition at line 2359 of file numeric.c.

2360{
2361 int ndigits = var->ndigits;
2362 int weight = var->weight;
2363 int64 result;
2364
2365 if (ndigits == 0 || weight < -44)
2366 {
2367 result = 0;
2368 }
2369 else if (weight > 83)
2370 {
2371 result = PG_INT64_MAX;
2372 }
2373 else
2374 {
2375 result = ((int64) (weight + 44) << 56);
2376
2377 switch (ndigits)
2378 {
2379 default:
2380 result |= ((int64) var->digits[3]);
2381 /* FALLTHROUGH */
2382 case 3:
2383 result |= ((int64) var->digits[2]) << 14;
2384 /* FALLTHROUGH */
2385 case 2:
2386 result |= ((int64) var->digits[1]) << 28;
2387 /* FALLTHROUGH */
2388 case 1:
2389 result |= ((int64) var->digits[0]) << 42;
2390 break;
2391 }
2392 }
2393
2394 /* the abbrev is negated relative to the original */
2395 if (var->sign == NUMERIC_POS)
2396 result = -result;
2397
2398 if (nss->estimating)
2399 {
2400 uint32 tmp = ((uint32) result
2401 ^ (uint32) ((uint64) result >> 32));
2402
2404 }
2405
2406 return NumericAbbrevGetDatum(result);
2407}
#define NumericAbbrevGetDatum(X)
Definition: numeric.c:405
static Datum hash_uint32(uint32 k)
Definition: hashfn.h:43
void addHyperLogLog(hyperLogLogState *cState, uint32 hash)
Definition: hyperloglog.c:167
static uint32 DatumGetUInt32(Datum X)
Definition: postgres.h:232

References NumericSortSupport::abbr_card, addHyperLogLog(), DatumGetUInt32(), NumericVar::digits, NumericSortSupport::estimating, hash_uint32(), NumericVar::ndigits, NUMERIC_POS, NumericAbbrevGetDatum, PG_INT64_MAX, NumericVar::sign, and NumericVar::weight.

Referenced by numeric_abbrev_convert().

◆ numeric_abs()

Datum numeric_abs ( PG_FUNCTION_ARGS  )

Definition at line 1376 of file numeric.c.

1377{
1378 Numeric num = PG_GETARG_NUMERIC(0);
1379 Numeric res;
1380
1381 /*
1382 * Do it the easy way directly on the packed format
1383 */
1384 res = duplicate_numeric(num);
1385
1386 if (NUMERIC_IS_SHORT(num))
1387 res->choice.n_short.n_header =
1388 num->choice.n_short.n_header & ~NUMERIC_SHORT_SIGN_MASK;
1389 else if (NUMERIC_IS_SPECIAL(num))
1390 {
1391 /* This changes -Inf to Inf, and doesn't affect NaN */
1392 res->choice.n_short.n_header =
1393 num->choice.n_short.n_header & ~NUMERIC_INF_SIGN_MASK;
1394 }
1395 else
1397
1398 PG_RETURN_NUMERIC(res);
1399}
uint16 n_sign_dscale
Definition: numeric.c:145
struct NumericLong n_long
Definition: numeric.c:153

References NumericData::choice, duplicate_numeric(), NumericShort::n_header, NumericChoice::n_long, NumericChoice::n_short, NumericLong::n_sign_dscale, NUMERIC_DSCALE, NUMERIC_IS_SHORT, NUMERIC_IS_SPECIAL, NUMERIC_POS, PG_GETARG_NUMERIC, and PG_RETURN_NUMERIC.

Referenced by executeItemOptUnwrapTarget(), and numeric_absolute().

◆ numeric_accum()

Datum numeric_accum ( PG_FUNCTION_ARGS  )

Definition at line 4948 of file numeric.c.

4949{
4951
4953
4954 /* Create the state data on the first call */
4955 if (state == NULL)
4956 state = makeNumericAggState(fcinfo, true);
4957
4958 if (!PG_ARGISNULL(1))
4960
4962}

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

5360{
5362
5364
5365 /* Should not get here with no state */
5366 if (state == NULL)
5367 elog(ERROR, "numeric_accum_inv called with NULL state");
5368
5369 if (!PG_ARGISNULL(1))
5370 {
5371 /* If we fail to perform the inverse transition, return NULL */
5374 }
5375
5377}

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

2865{
2866 Numeric num1 = PG_GETARG_NUMERIC(0);
2867 Numeric num2 = PG_GETARG_NUMERIC(1);
2868 Numeric res;
2869
2870 res = numeric_add_safe(num1, num2, NULL);
2871
2872 PG_RETURN_NUMERIC(res);
2873}
Numeric numeric_add_safe(Numeric num1, Numeric num2, Node *escontext)
Definition: numeric.c:2881

References numeric_add_safe(), PG_GETARG_NUMERIC, and PG_RETURN_NUMERIC.

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

◆ numeric_add_safe()

Numeric numeric_add_safe ( Numeric  num1,
Numeric  num2,
Node escontext 
)

Definition at line 2881 of file numeric.c.

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

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

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

5919{
5921 Datum N_datum;
5922 Datum sumX_datum;
5923 NumericVar sumX_var;
5924
5926
5927 /* If there were no non-null inputs, return NULL */
5928 if (state == NULL || NA_TOTAL_COUNT(state) == 0)
5930
5931 if (state->NaNcount > 0) /* there was at least one NaN input */
5933
5934 /* adding plus and minus infinities gives NaN */
5935 if (state->pInfcount > 0 && state->nInfcount > 0)
5937 if (state->pInfcount > 0)
5939 if (state->nInfcount > 0)
5941
5942 N_datum = NumericGetDatum(int64_to_numeric(state->N));
5943
5944 init_var(&sumX_var);
5945 accum_sum_final(&state->sumX, &sumX_var);
5946 sumX_datum = NumericGetDatum(make_result(&sumX_var));
5947 free_var(&sumX_var);
5948
5949 PG_RETURN_DATUM(DirectFunctionCall2(numeric_div, sumX_datum, N_datum));
5950}
#define NA_TOTAL_COUNT(na)
Definition: numeric.c:4737

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.

◆ numeric_avg_accum()

Datum numeric_avg_accum ( PG_FUNCTION_ARGS  )

Definition at line 5040 of file numeric.c.

5041{
5043
5045
5046 /* Create the state data on the first call */
5047 if (state == NULL)
5048 state = makeNumericAggState(fcinfo, false);
5049
5050 if (!PG_ARGISNULL(1))
5052
5054}

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

5061{
5062 NumericAggState *state1;
5063 NumericAggState *state2;
5064 MemoryContext agg_context;
5065 MemoryContext old_context;
5066
5067 if (!AggCheckCallContext(fcinfo, &agg_context))
5068 elog(ERROR, "aggregate function called in non-aggregate context");
5069
5070 state1 = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
5071 state2 = PG_ARGISNULL(1) ? NULL : (NumericAggState *) PG_GETARG_POINTER(1);
5072
5073 if (state2 == NULL)
5074 PG_RETURN_POINTER(state1);
5075
5076 /* manually copy all fields from state2 to state1 */
5077 if (state1 == NULL)
5078 {
5079 old_context = MemoryContextSwitchTo(agg_context);
5080
5081 state1 = makeNumericAggStateCurrentContext(false);
5082 state1->N = state2->N;
5083 state1->NaNcount = state2->NaNcount;
5084 state1->pInfcount = state2->pInfcount;
5085 state1->nInfcount = state2->nInfcount;
5086 state1->maxScale = state2->maxScale;
5087 state1->maxScaleCount = state2->maxScaleCount;
5088
5089 accum_sum_copy(&state1->sumX, &state2->sumX);
5090
5091 MemoryContextSwitchTo(old_context);
5092
5093 PG_RETURN_POINTER(state1);
5094 }
5095
5096 state1->N += state2->N;
5097 state1->NaNcount += state2->NaNcount;
5098 state1->pInfcount += state2->pInfcount;
5099 state1->nInfcount += state2->nInfcount;
5100
5101 if (state2->N > 0)
5102 {
5103 /*
5104 * These are currently only needed for moving aggregates, but let's do
5105 * the right thing anyway...
5106 */
5107 if (state2->maxScale > state1->maxScale)
5108 {
5109 state1->maxScale = state2->maxScale;
5110 state1->maxScaleCount = state2->maxScaleCount;
5111 }
5112 else if (state2->maxScale == state1->maxScale)
5113 state1->maxScaleCount += state2->maxScaleCount;
5114
5115 /* The rest of this needs to work in the aggregate context */
5116 old_context = MemoryContextSwitchTo(agg_context);
5117
5118 /* Accumulate sums */
5119 accum_sum_combine(&state1->sumX, &state2->sumX);
5120
5121 MemoryContextSwitchTo(old_context);
5122 }
5123 PG_RETURN_POINTER(state1);
5124}
static NumericAggState * makeNumericAggStateCurrentContext(bool calcSumX2)
Definition: numeric.c:4770
static void accum_sum_combine(NumericSumAccum *accum, NumericSumAccum *accum2)
Definition: numeric.c:12123
static void accum_sum_copy(NumericSumAccum *dst, NumericSumAccum *src)
Definition: numeric.c:12106
int64 NaNcount
Definition: numeric.c:4732
int64 nInfcount
Definition: numeric.c:4734
NumericSumAccum sumX
Definition: numeric.c:4727
int64 maxScaleCount
Definition: numeric.c:4730
int64 pInfcount
Definition: numeric.c:4733

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

5185{
5186 bytea *sstate;
5187 NumericAggState *result;
5189 NumericVar tmp_var;
5190
5191 if (!AggCheckCallContext(fcinfo, NULL))
5192 elog(ERROR, "aggregate function called in non-aggregate context");
5193
5194 sstate = PG_GETARG_BYTEA_PP(0);
5195
5196 init_var(&tmp_var);
5197
5198 /*
5199 * Initialize a StringInfo so that we can "receive" it using the standard
5200 * recv-function infrastructure.
5201 */
5203 VARSIZE_ANY_EXHDR(sstate));
5204
5205 result = makeNumericAggStateCurrentContext(false);
5206
5207 /* N */
5208 result->N = pq_getmsgint64(&buf);
5209
5210 /* sumX */
5211 numericvar_deserialize(&buf, &tmp_var);
5212 accum_sum_add(&(result->sumX), &tmp_var);
5213
5214 /* maxScale */
5215 result->maxScale = pq_getmsgint(&buf, 4);
5216
5217 /* maxScaleCount */
5218 result->maxScaleCount = pq_getmsgint64(&buf);
5219
5220 /* NaNcount */
5221 result->NaNcount = pq_getmsgint64(&buf);
5222
5223 /* pInfcount */
5224 result->pInfcount = pq_getmsgint64(&buf);
5225
5226 /* nInfcount */
5227 result->nInfcount = pq_getmsgint64(&buf);
5228
5229 pq_getmsgend(&buf);
5230
5231 free_var(&tmp_var);
5232
5233 PG_RETURN_POINTER(result);
5234}
static void numericvar_deserialize(StringInfo buf, NumericVar *var)
Definition: numeric.c:7470
unsigned int pq_getmsgint(StringInfo msg, int b)
Definition: pqformat.c:414

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

5133{
5136 bytea *result;
5137 NumericVar tmp_var;
5138
5139 /* Ensure we disallow calling when not in aggregate context */
5140 if (!AggCheckCallContext(fcinfo, NULL))
5141 elog(ERROR, "aggregate function called in non-aggregate context");
5142
5144
5145 init_var(&tmp_var);
5146
5148
5149 /* N */
5150 pq_sendint64(&buf, state->N);
5151
5152 /* sumX */
5153 accum_sum_final(&state->sumX, &tmp_var);
5154 numericvar_serialize(&buf, &tmp_var);
5155
5156 /* maxScale */
5157 pq_sendint32(&buf, state->maxScale);
5158
5159 /* maxScaleCount */
5160 pq_sendint64(&buf, state->maxScaleCount);
5161
5162 /* NaNcount */
5163 pq_sendint64(&buf, state->NaNcount);
5164
5165 /* pInfcount */
5166 pq_sendint64(&buf, state->pInfcount);
5167
5168 /* nInfcount */
5169 pq_sendint64(&buf, state->nInfcount);
5170
5171 result = pq_endtypsend(&buf);
5172
5173 free_var(&tmp_var);
5174
5175 PG_RETURN_BYTEA_P(result);
5176}
static void numericvar_serialize(StringInfo buf, const NumericVar *var)
Definition: numeric.c:7454
static void pq_sendint32(StringInfo buf, uint32 i)
Definition: pqformat.h:144

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

◆ numeric_ceil()

Datum numeric_ceil ( PG_FUNCTION_ARGS  )

Definition at line 1630 of file numeric.c.

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

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

Referenced by executeItemOptUnwrapTarget().

◆ numeric_cmp()

Datum numeric_cmp ( PG_FUNCTION_ARGS  )

Definition at line 2415 of file numeric.c.

2416{
2417 Numeric num1 = PG_GETARG_NUMERIC(0);
2418 Numeric num2 = PG_GETARG_NUMERIC(1);
2419 int result;
2420
2421 result = cmp_numerics(num1, num2);
2422
2423 PG_FREE_IF_COPY(num1, 0);
2424 PG_FREE_IF_COPY(num2, 1);
2425
2426 PG_RETURN_INT32(result);
2427}
static int cmp_numerics(Numeric num1, Numeric num2)
Definition: numeric.c:2521
#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(), gbt_numeric_ssup_cmp(), and gin_numeric_cmp().

◆ numeric_cmp_abbrev()

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

Definition at line 2300 of file numeric.c.

2301{
2302 /*
2303 * NOTE WELL: this is intentionally backwards, because the abbreviation is
2304 * negated relative to the original value, to handle NaN/infinity cases.
2305 */
2307 return 1;
2309 return -1;
2310 return 0;
2311}
#define DatumGetNumericAbbrev(X)
Definition: numeric.c:406
int y
Definition: isn.c:76

References DatumGetNumericAbbrev, x, and y.

Referenced by numeric_sortsupport().

◆ numeric_combine()

Datum numeric_combine ( PG_FUNCTION_ARGS  )

Definition at line 4968 of file numeric.c.

4969{
4970 NumericAggState *state1;
4971 NumericAggState *state2;
4972 MemoryContext agg_context;
4973 MemoryContext old_context;
4974
4975 if (!AggCheckCallContext(fcinfo, &agg_context))
4976 elog(ERROR, "aggregate function called in non-aggregate context");
4977
4978 state1 = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
4979 state2 = PG_ARGISNULL(1) ? NULL : (NumericAggState *) PG_GETARG_POINTER(1);
4980
4981 if (state2 == NULL)
4982 PG_RETURN_POINTER(state1);
4983
4984 /* manually copy all fields from state2 to state1 */
4985 if (state1 == NULL)
4986 {
4987 old_context = MemoryContextSwitchTo(agg_context);
4988
4989 state1 = makeNumericAggStateCurrentContext(true);
4990 state1->N = state2->N;
4991 state1->NaNcount = state2->NaNcount;
4992 state1->pInfcount = state2->pInfcount;
4993 state1->nInfcount = state2->nInfcount;
4994 state1->maxScale = state2->maxScale;
4995 state1->maxScaleCount = state2->maxScaleCount;
4996
4997 accum_sum_copy(&state1->sumX, &state2->sumX);
4998 accum_sum_copy(&state1->sumX2, &state2->sumX2);
4999
5000 MemoryContextSwitchTo(old_context);
5001
5002 PG_RETURN_POINTER(state1);
5003 }
5004
5005 state1->N += state2->N;
5006 state1->NaNcount += state2->NaNcount;
5007 state1->pInfcount += state2->pInfcount;
5008 state1->nInfcount += state2->nInfcount;
5009
5010 if (state2->N > 0)
5011 {
5012 /*
5013 * These are currently only needed for moving aggregates, but let's do
5014 * the right thing anyway...
5015 */
5016 if (state2->maxScale > state1->maxScale)
5017 {
5018 state1->maxScale = state2->maxScale;
5019 state1->maxScaleCount = state2->maxScaleCount;
5020 }
5021 else if (state2->maxScale == state1->maxScale)
5022 state1->maxScaleCount += state2->maxScaleCount;
5023
5024 /* The rest of this needs to work in the aggregate context */
5025 old_context = MemoryContextSwitchTo(agg_context);
5026
5027 /* Accumulate sums */
5028 accum_sum_combine(&state1->sumX, &state2->sumX);
5029 accum_sum_combine(&state1->sumX2, &state2->sumX2);
5030
5031 MemoryContextSwitchTo(old_context);
5032 }
5033 PG_RETURN_POINTER(state1);
5034}
NumericSumAccum sumX2
Definition: numeric.c:4728

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

5299{
5300 bytea *sstate;
5301 NumericAggState *result;
5303 NumericVar tmp_var;
5304
5305 if (!AggCheckCallContext(fcinfo, NULL))
5306 elog(ERROR, "aggregate function called in non-aggregate context");
5307
5308 sstate = PG_GETARG_BYTEA_PP(0);
5309
5310 init_var(&tmp_var);
5311
5312 /*
5313 * Initialize a StringInfo so that we can "receive" it using the standard
5314 * recv-function infrastructure.
5315 */
5317 VARSIZE_ANY_EXHDR(sstate));
5318
5319 result = makeNumericAggStateCurrentContext(false);
5320
5321 /* N */
5322 result->N = pq_getmsgint64(&buf);
5323
5324 /* sumX */
5325 numericvar_deserialize(&buf, &tmp_var);
5326 accum_sum_add(&(result->sumX), &tmp_var);
5327
5328 /* sumX2 */
5329 numericvar_deserialize(&buf, &tmp_var);
5330 accum_sum_add(&(result->sumX2), &tmp_var);
5331
5332 /* maxScale */
5333 result->maxScale = pq_getmsgint(&buf, 4);
5334
5335 /* maxScaleCount */
5336 result->maxScaleCount = pq_getmsgint64(&buf);
5337
5338 /* NaNcount */
5339 result->NaNcount = pq_getmsgint64(&buf);
5340
5341 /* pInfcount */
5342 result->pInfcount = pq_getmsgint64(&buf);
5343
5344 /* nInfcount */
5345 result->nInfcount = pq_getmsgint64(&buf);
5346
5347 pq_getmsgend(&buf);
5348
5349 free_var(&tmp_var);
5350
5351 PG_RETURN_POINTER(result);
5352}

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

3135{
3136 Numeric num1 = PG_GETARG_NUMERIC(0);
3137 Numeric num2 = PG_GETARG_NUMERIC(1);
3138 Numeric res;
3139
3140 res = numeric_div_safe(num1, num2, NULL);
3141
3142 PG_RETURN_NUMERIC(res);
3143}
Numeric numeric_div_safe(Numeric num1, Numeric num2, Node *escontext)
Definition: numeric.c:3152

References numeric_div_safe(), PG_GETARG_NUMERIC, and PG_RETURN_NUMERIC.

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

◆ numeric_div_safe()

Numeric numeric_div_safe ( Numeric  num1,
Numeric  num2,
Node escontext 
)

Definition at line 3152 of file numeric.c.

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

References Assert(), const_nan, const_ninf, const_pinf, const_zero, NumericVar::digits, div_var(), ereturn, errcode(), errmsg(), free_var(), init_var, init_var_from_num(), make_result(), make_result_safe(), NumericVar::ndigits, NUMERIC_IS_NAN, NUMERIC_IS_NINF, NUMERIC_IS_PINF, NUMERIC_IS_SPECIAL, numeric_sign_internal(), 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 3248 of file numeric.c.

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

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, and PG_RETURN_NUMERIC.

Referenced by numeric_half_rounded(), and numeric_truncated_divide().

◆ numeric_eq()

Datum numeric_eq ( PG_FUNCTION_ARGS  )

Definition at line 2431 of file numeric.c.

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

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

3725{
3726 Numeric num = PG_GETARG_NUMERIC(0);
3727 Numeric res;
3729 NumericVar result;
3730 int rscale;
3731 double val;
3732
3733 /*
3734 * Handle NaN and infinities
3735 */
3736 if (NUMERIC_IS_SPECIAL(num))
3737 {
3738 /* Per POSIX, exp(-Inf) is zero */
3739 if (NUMERIC_IS_NINF(num))
3741 /* For NAN or PINF, just duplicate the input */
3743 }
3744
3745 /*
3746 * Unpack the argument and determine the result scale. We choose a scale
3747 * to give at least NUMERIC_MIN_SIG_DIGITS significant digits; but in any
3748 * case not less than the input's dscale.
3749 */
3750 init_var_from_num(num, &arg);
3751
3752 init_var(&result);
3753
3754 /* convert input to float8, ignoring overflow */
3756
3757 /*
3758 * log10(result) = num * log10(e), so this is approximately the decimal
3759 * weight of the result:
3760 */
3761 val *= 0.434294481903252;
3762
3763 /* limit to something that won't cause integer overflow */
3766
3767 rscale = NUMERIC_MIN_SIG_DIGITS - (int) val;
3768 rscale = Max(rscale, arg.dscale);
3769 rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
3770 rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
3771
3772 /*
3773 * Let exp_var() do the calculation and return the result.
3774 */
3775 exp_var(&arg, &result, rscale);
3776
3777 res = make_result(&result);
3778
3779 free_var(&result);
3780
3781 PG_RETURN_NUMERIC(res);
3782}
static void exp_var(const NumericVar *arg, NumericVar *result, int rscale)
Definition: numeric.c:10411

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, and val.

◆ numeric_fac()

Datum numeric_fac ( PG_FUNCTION_ARGS  )

Definition at line 3600 of file numeric.c.

3601{
3602 int64 num = PG_GETARG_INT64(0);
3603 Numeric res;
3604 NumericVar fact;
3605 NumericVar result;
3606
3607 if (num < 0)
3608 ereport(ERROR,
3609 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
3610 errmsg("factorial of a negative number is undefined")));
3611 if (num <= 1)
3612 {
3613 res = make_result(&const_one);
3614 PG_RETURN_NUMERIC(res);
3615 }
3616 /* Fail immediately if the result would overflow */
3617 if (num > 32177)
3618 ereport(ERROR,
3619 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
3620 errmsg("value overflows numeric format")));
3621
3622 init_var(&fact);
3623 init_var(&result);
3624
3625 int64_to_numericvar(num, &result);
3626
3627 for (num = num - 1; num > 1; num--)
3628 {
3629 /* this loop can take awhile, so allow it to be interrupted */
3631
3632 int64_to_numericvar(num, &fact);
3633
3634 mul_var(&result, &fact, &result, 0);
3635 }
3636
3637 res = make_result(&result);
3638
3639 free_var(&fact);
3640 free_var(&result);
3641
3642 PG_RETURN_NUMERIC(res);
3643}

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

◆ numeric_fast_cmp()

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

Definition at line 2278 of file numeric.c.

2279{
2282 int result;
2283
2284 result = cmp_numerics(nx, ny);
2285
2286 if (nx != DatumGetPointer(x))
2287 pfree(nx);
2288 if (ny != DatumGetPointer(y))
2289 pfree(ny);
2290
2291 return result;
2292}

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

Referenced by numeric_sortsupport().

◆ numeric_float4()

Datum numeric_float4 ( PG_FUNCTION_ARGS  )

Definition at line 4650 of file numeric.c.

4651{
4652 Numeric num = PG_GETARG_NUMERIC(0);
4653 char *tmp;
4654 Datum result;
4655
4656 if (NUMERIC_IS_SPECIAL(num))
4657 {
4658 if (NUMERIC_IS_PINF(num))
4660 else if (NUMERIC_IS_NINF(num))
4662 else
4664 }
4665
4667 NumericGetDatum(num)));
4668
4670
4671 pfree(tmp);
4672
4673 PG_RETURN_DATUM(result);
4674}
Datum numeric_out(PG_FUNCTION_ARGS)
Definition: numeric.c:799
Datum float4in(PG_FUNCTION_ARGS)
Definition: float.c:164
static float4 get_float4_infinity(void)
Definition: float.h:58
static float4 get_float4_nan(void)
Definition: float.h:77
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:682
#define PG_RETURN_FLOAT4(x)
Definition: fmgr.h:366
static char * DatumGetCString(Datum X)
Definition: postgres.h:345
static Datum CStringGetDatum(const char *X)
Definition: postgres.h:360

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

4557{
4558 Numeric num = PG_GETARG_NUMERIC(0);
4559 char *tmp;
4560 Datum result;
4561
4562 if (NUMERIC_IS_SPECIAL(num))
4563 {
4564 if (NUMERIC_IS_PINF(num))
4566 else if (NUMERIC_IS_NINF(num))
4568 else
4570 }
4571
4573 NumericGetDatum(num)));
4574
4576
4577 pfree(tmp);
4578
4579 PG_RETURN_DATUM(result);
4580}
Datum float8in(PG_FUNCTION_ARGS)
Definition: float.c:364
static float8 get_float8_infinity(void)
Definition: float.h:65
static float8 get_float8_nan(void)
Definition: float.h:84
#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 4589 of file numeric.c.

4590{
4591 Numeric num = PG_GETARG_NUMERIC(0);
4592 double val;
4593
4594 if (NUMERIC_IS_SPECIAL(num))
4595 {
4596 if (NUMERIC_IS_PINF(num))
4597 val = HUGE_VAL;
4598 else if (NUMERIC_IS_NINF(num))
4599 val = -HUGE_VAL;
4600 else
4601 val = get_float8_nan();
4602 }
4603 else
4604 {
4605 NumericVar x;
4606
4607 init_var_from_num(num, &x);
4609 }
4610
4612}

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

Referenced by convert_numeric_to_scalar(), and gbt_numeric_penalty().

◆ numeric_floor()

Datum numeric_floor ( PG_FUNCTION_ARGS  )

Definition at line 1658 of file numeric.c.

1659{
1660 Numeric num = PG_GETARG_NUMERIC(0);
1661 Numeric res;
1662 NumericVar result;
1663
1664 /*
1665 * Handle NaN and infinities
1666 */
1667 if (NUMERIC_IS_SPECIAL(num))
1669
1670 init_var_from_num(num, &result);
1671 floor_var(&result, &result);
1672
1673 res = make_result(&result);
1674 free_var(&result);
1675
1676 PG_RETURN_NUMERIC(res);
1677}
static void floor_var(const NumericVar *var, NumericVar *result)
Definition: numeric.c:9838

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

Referenced by executeItemOptUnwrapTarget().

◆ numeric_gcd()

Datum numeric_gcd ( PG_FUNCTION_ARGS  )

Definition at line 3497 of file numeric.c.

3498{
3499 Numeric num1 = PG_GETARG_NUMERIC(0);
3500 Numeric num2 = PG_GETARG_NUMERIC(1);
3501 NumericVar arg1;
3502 NumericVar arg2;
3503 NumericVar result;
3504 Numeric res;
3505
3506 /*
3507 * Handle NaN and infinities: we consider the result to be NaN in all such
3508 * cases.
3509 */
3510 if (NUMERIC_IS_SPECIAL(num1) || NUMERIC_IS_SPECIAL(num2))
3512
3513 /*
3514 * Unpack the arguments
3515 */
3516 init_var_from_num(num1, &arg1);
3517 init_var_from_num(num2, &arg2);
3518
3519 init_var(&result);
3520
3521 /*
3522 * Find the GCD and return the result
3523 */
3524 gcd_var(&arg1, &arg2, &result);
3525
3526 res = make_result(&result);
3527
3528 free_var(&result);
3529
3530 PG_RETURN_NUMERIC(res);
3531}
static void gcd_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition: numeric.c:9861

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

◆ numeric_ge()

Datum numeric_ge ( PG_FUNCTION_ARGS  )

Definition at line 2476 of file numeric.c.

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

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

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

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;
655
656 if (*cp == '+')
657 cp++;
658 else if (*cp == '-')
659 {
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 {
679 res = make_result(&const_nan);
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))
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
721 init_var(&value);
722
723 /*
724 * Determine the number's base by looking for a non-decimal prefix
725 * indicator ("0x", "0o", or "0b").
726 */
727 if (cp[0] == '0')
728 {
729 switch (cp[1])
730 {
731 case 'x':
732 case 'X':
733 base = 16;
734 break;
735 case 'o':
736 case 'O':
737 base = 8;
738 break;
739 case 'b':
740 case 'B':
741 base = 2;
742 break;
743 default:
744 base = 10;
745 }
746 }
747 else
748 base = 10;
749
750 /* Parse the rest of the number and apply the sign */
751 if (base == 10)
752 {
753 if (!set_var_from_str(str, cp, &value, &cp, escontext))
755 value.sign = sign;
756 }
757 else
758 {
760 &value, &cp, escontext))
762 }
763
764 /*
765 * Should be nothing left but spaces. As above, throw any typmod error
766 * after finishing syntax check.
767 */
768 while (*cp)
769 {
770 if (!isspace((unsigned char) *cp))
771 goto invalid_syntax;
772 cp++;
773 }
774
775 if (!apply_typmod(&value, typmod, escontext))
777
778 res = make_result_safe(&value, escontext);
779
780 free_var(&value);
781 }
782
784
785invalid_syntax:
786 ereturn(escontext, (Datum) 0,
787 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
788 errmsg("invalid input syntax for type %s: \"%s\"",
789 "numeric", str)));
790}
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:6972
#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:65
unsigned int Oid
Definition: postgres_ext.h:32

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

Referenced by datum_to_jsonb_internal(), executeItemOptUnwrapTarget(), extract_date(), hstore_to_jsonb_loose(), interval_part_common(), jsonb_in_scalar(), make_const(), numeric_to_number(), pg_lsn_mi(), pg_lsn_mii(), pg_lsn_pli(), pg_size_bytes(), pg_split_walfile_name(), pg_stat_get_activity(), pg_stat_io_build_tuples(), pg_stat_statements_internal(), pg_stat_wal_build_tuple(), 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 3413 of file numeric.c.

3414{
3415 Numeric num = PG_GETARG_NUMERIC(0);
3417 Numeric res;
3418
3419 /*
3420 * Handle NaN and infinities
3421 */
3422 if (NUMERIC_IS_SPECIAL(num))
3424
3425 /*
3426 * Compute the result and return it
3427 */
3428 init_var_from_num(num, &arg);
3429
3430 add_var(&arg, &const_one, &arg);
3431
3432 res = make_result(&arg);
3433
3434 free_var(&arg);
3435
3436 PG_RETURN_NUMERIC(res);
3437}

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

◆ numeric_int2()

Datum numeric_int2 ( PG_FUNCTION_ARGS  )

Definition at line 4481 of file numeric.c.

4482{
4483 Numeric num = PG_GETARG_NUMERIC(0);
4484 NumericVar x;
4485 int64 val;
4486 int16 result;
4487
4488 if (NUMERIC_IS_SPECIAL(num))
4489 {
4490 if (NUMERIC_IS_NAN(num))
4491 ereport(ERROR,
4492 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4493 errmsg("cannot convert NaN to %s", "smallint")));
4494 else
4495 ereport(ERROR,
4496 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4497 errmsg("cannot convert infinity to %s", "smallint")));
4498 }
4499
4500 /* Convert to variable format and thence to int8 */
4501 init_var_from_num(num, &x);
4502
4503 if (!numericvar_to_int64(&x, &val))
4504 ereport(ERROR,
4505 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
4506 errmsg("smallint out of range")));
4507
4509 ereport(ERROR,
4510 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
4511 errmsg("smallint out of range")));
4512
4513 /* Down-convert to int2 */
4514 result = (int16) val;
4515
4516 PG_RETURN_INT16(result);
4517}
static bool numericvar_to_int64(const NumericVar *var, int64 *result)
Definition: numeric.c:7743
#define PG_INT16_MIN
Definition: c.h:604
#define PG_INT16_MAX
Definition: c.h:605
#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 4393 of file numeric.c.

4394{
4395 Numeric num = PG_GETARG_NUMERIC(0);
4396
4398}
int32 numeric_int4_safe(Numeric num, Node *escontext)
Definition: numeric.c:4364

References numeric_int4_safe(), PG_GETARG_NUMERIC, and PG_RETURN_INT32.

Referenced by jsonb_int4().

◆ numeric_int4_safe()

int32 numeric_int4_safe ( Numeric  num,
Node escontext 
)

Definition at line 4364 of file numeric.c.

4365{
4366 NumericVar x;
4367 int32 result;
4368
4369 if (NUMERIC_IS_SPECIAL(num))
4370 {
4371 if (NUMERIC_IS_NAN(num))
4372 ereturn(escontext, 0,
4373 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4374 errmsg("cannot convert NaN to %s", "integer")));
4375 else
4376 ereturn(escontext, 0,
4377 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4378 errmsg("cannot convert infinity to %s", "integer")));
4379 }
4380
4381 /* Convert to variable format, then convert to int4 */
4382 init_var_from_num(num, &x);
4383
4384 if (!numericvar_to_int32(&x, &result))
4385 ereturn(escontext, 0,
4386 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
4387 errmsg("integer out of range")));
4388
4389 return result;
4390}
static bool numericvar_to_int32(const NumericVar *var, int32 *result)
Definition: numeric.c:4406

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

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

◆ numeric_int8()

Datum numeric_int8 ( PG_FUNCTION_ARGS  )

Definition at line 4463 of file numeric.c.

4464{
4465 Numeric num = PG_GETARG_NUMERIC(0);
4466
4468}
int64 numeric_int8_safe(Numeric num, Node *escontext)
Definition: numeric.c:4434

References numeric_int8_safe(), PG_GETARG_NUMERIC, and PG_RETURN_INT64.

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

◆ numeric_int8_safe()

int64 numeric_int8_safe ( Numeric  num,
Node escontext 
)

Definition at line 4434 of file numeric.c.

4435{
4436 NumericVar x;
4437 int64 result;
4438
4439 if (NUMERIC_IS_SPECIAL(num))
4440 {
4441 if (NUMERIC_IS_NAN(num))
4442 ereturn(escontext, 0,
4443 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4444 errmsg("cannot convert NaN to %s", "bigint")));
4445 else
4446 ereturn(escontext, 0,
4447 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4448 errmsg("cannot convert infinity to %s", "bigint")));
4449 }
4450
4451 /* Convert to variable format, then convert to int8 */
4452 init_var_from_num(num, &x);
4453
4454 if (!numericvar_to_int64(&x, &result))
4455 ereturn(escontext, 0,
4456 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
4457 errmsg("bigint out of range")));
4458
4459 return result;
4460}

References ereturn, errcode(), errmsg(), 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 845 of file numeric.c.

846{
847 return NUMERIC_IS_INF(num);
848}
#define NUMERIC_IS_INF(n)
Definition: numeric.c:210

References NUMERIC_IS_INF.

Referenced by datum_to_jsonb_internal(), executeItemOptUnwrapTarget(), and PLyNumber_ToJsonbValue().

◆ numeric_is_integral()

static bool numeric_is_integral ( Numeric  num)
static

Definition at line 856 of file numeric.c.

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

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)

◆ numeric_larger()

Datum numeric_larger ( 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_lcm()

Datum numeric_lcm ( PG_FUNCTION_ARGS  )

Definition at line 3540 of file numeric.c.

3541{
3542 Numeric num1 = PG_GETARG_NUMERIC(0);
3543 Numeric num2 = PG_GETARG_NUMERIC(1);
3544 NumericVar arg1;
3545 NumericVar arg2;
3546 NumericVar result;
3547 Numeric res;
3548
3549 /*
3550 * Handle NaN and infinities: we consider the result to be NaN in all such
3551 * cases.
3552 */
3553 if (NUMERIC_IS_SPECIAL(num1) || NUMERIC_IS_SPECIAL(num2))
3555
3556 /*
3557 * Unpack the arguments
3558 */
3559 init_var_from_num(num1, &arg1);
3560 init_var_from_num(num2, &arg2);
3561
3562 init_var(&result);
3563
3564 /*
3565 * Compute the result using lcm(x, y) = abs(x / gcd(x, y) * y), returning
3566 * zero if either input is zero.
3567 *
3568 * Note that the division is guaranteed to be exact, returning an integer
3569 * result, so the LCM is an integral multiple of both x and y. A display
3570 * scale of Min(x.dscale, y.dscale) would be sufficient to represent it,
3571 * but as with other numeric functions, we choose to return a result whose
3572 * display scale is no smaller than either input.
3573 */
3574 if (arg1.ndigits == 0 || arg2.ndigits == 0)
3575 set_var_from_var(&const_zero, &result);
3576 else
3577 {
3578 gcd_var(&arg1, &arg2, &result);
3579 div_var(&arg1, &result, &result, 0, false, true);
3580 mul_var(&arg2, &result, &result, arg2.dscale);
3581 result.sign = NUMERIC_POS;
3582 }
3583
3584 result.dscale = Max(arg1.dscale, arg2.dscale);
3585
3586 res = make_result(&result);
3587
3588 free_var(&result);
3589
3590 PG_RETURN_NUMERIC(res);
3591}

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, set_var_from_var(), and NumericVar::sign.

◆ numeric_le()

Datum numeric_le ( PG_FUNCTION_ARGS  )

Definition at line 2506 of file numeric.c.

2507{
2508 Numeric num1 = PG_GETARG_NUMERIC(0);
2509 Numeric num2 = PG_GETARG_NUMERIC(1);
2510 bool result;
2511
2512 result = cmp_numerics(num1, num2) <= 0;
2513
2514 PG_FREE_IF_COPY(num1, 0);
2515 PG_FREE_IF_COPY(num2, 1);
2516
2517 PG_RETURN_BOOL(result);
2518}

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

3792{
3793 Numeric num = PG_GETARG_NUMERIC(0);
3794 Numeric res;
3796 NumericVar result;
3797 int ln_dweight;
3798 int rscale;
3799
3800 /*
3801 * Handle NaN and infinities
3802 */
3803 if (NUMERIC_IS_SPECIAL(num))
3804 {
3805 if (NUMERIC_IS_NINF(num))
3806 ereport(ERROR,
3807 (errcode(ERRCODE_INVALID_ARGUMENT_FOR_LOG),
3808 errmsg("cannot take logarithm of a negative number")));
3809 /* For NAN or PINF, just duplicate the input */
3811 }
3812
3813 init_var_from_num(num, &arg);
3814 init_var(&result);
3815
3816 /* Estimated dweight of logarithm */
3817 ln_dweight = estimate_ln_dweight(&arg);
3818
3819 rscale = NUMERIC_MIN_SIG_DIGITS - ln_dweight;
3820 rscale = Max(rscale, arg.dscale);
3821 rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
3822 rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
3823
3824 ln_var(&arg, &result, rscale);
3825
3826 res = make_result(&result);
3827
3828 free_var(&result);
3829
3830 PG_RETURN_NUMERIC(res);
3831}

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, and PG_RETURN_NUMERIC.

◆ numeric_log()

Datum numeric_log ( PG_FUNCTION_ARGS  )

Definition at line 3840 of file numeric.c.

3841{
3842 Numeric num1 = PG_GETARG_NUMERIC(0);
3843 Numeric num2 = PG_GETARG_NUMERIC(1);
3844 Numeric res;
3845 NumericVar arg1;
3846 NumericVar arg2;
3847 NumericVar result;
3848
3849 /*
3850 * Handle NaN and infinities
3851 */
3852 if (NUMERIC_IS_SPECIAL(num1) || NUMERIC_IS_SPECIAL(num2))
3853 {
3854 int sign1,
3855 sign2;
3856
3857 if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
3859 /* fail on negative inputs including -Inf, as log_var would */
3860 sign1 = numeric_sign_internal(num1);
3861 sign2 = numeric_sign_internal(num2);
3862 if (sign1 < 0 || sign2 < 0)
3863 ereport(ERROR,
3864 (errcode(ERRCODE_INVALID_ARGUMENT_FOR_LOG),
3865 errmsg("cannot take logarithm of a negative number")));
3866 /* fail on zero inputs, as log_var would */
3867 if (sign1 == 0 || sign2 == 0)
3868 ereport(ERROR,
3869 (errcode(ERRCODE_INVALID_ARGUMENT_FOR_LOG),
3870 errmsg("cannot take logarithm of zero")));
3871 if (NUMERIC_IS_PINF(num1))
3872 {
3873 /* log(Inf, Inf) reduces to Inf/Inf, so it's NaN */
3874 if (NUMERIC_IS_PINF(num2))
3876 /* log(Inf, finite-positive) is zero (we don't throw underflow) */
3878 }
3879 Assert(NUMERIC_IS_PINF(num2));
3880 /* log(finite-positive, Inf) is Inf */
3882 }
3883
3884 /*
3885 * Initialize things
3886 */
3887 init_var_from_num(num1, &arg1);
3888 init_var_from_num(num2, &arg2);
3889 init_var(&result);
3890
3891 /*
3892 * Call log_var() to compute and return the result; note it handles scale
3893 * selection itself.
3894 */
3895 log_var(&arg1, &arg2, &result);
3896
3897 res = make_result(&result);
3898
3899 free_var(&result);
3900
3901 PG_RETURN_NUMERIC(res);
3902}
static void log_var(const NumericVar *base, const NumericVar *num, NumericVar *result)
Definition: numeric.c:10740

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, and PG_RETURN_NUMERIC.

◆ numeric_lt()

Datum numeric_lt ( PG_FUNCTION_ARGS  )

Definition at line 2491 of file numeric.c.

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

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

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

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

4164{
4165 Numeric num = PG_GETARG_NUMERIC(0);
4167 int min_scale;
4168
4169 if (NUMERIC_IS_SPECIAL(num))
4171
4172 init_var_from_num(num, &arg);
4173 min_scale = get_min_scale(&arg);
4174 free_var(&arg);
4175
4176 PG_RETURN_INT32(min_scale);
4177}
static int get_min_scale(NumericVar *var)
Definition: numeric.c:4112

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

3338{
3339 Numeric num1 = PG_GETARG_NUMERIC(0);
3340 Numeric num2 = PG_GETARG_NUMERIC(1);
3341 Numeric res;
3342
3343 res = numeric_mod_safe(num1, num2, NULL);
3344
3345 PG_RETURN_NUMERIC(res);
3346}
Numeric numeric_mod_safe(Numeric num1, Numeric num2, Node *escontext)
Definition: numeric.c:3355

References numeric_mod_safe(), PG_GETARG_NUMERIC, and PG_RETURN_NUMERIC.

◆ numeric_mod_safe()

Numeric numeric_mod_safe ( Numeric  num1,
Numeric  num2,
Node escontext 
)

Definition at line 3355 of file numeric.c.

3356{
3357 Numeric res;
3358 NumericVar arg1;
3359 NumericVar arg2;
3360 NumericVar result;
3361
3362 /*
3363 * Handle NaN and infinities. We follow POSIX fmod() on this, except that
3364 * POSIX treats x-is-infinite and y-is-zero identically, raising EDOM and
3365 * returning NaN. We choose to throw error only for y-is-zero.
3366 */
3367 if (NUMERIC_IS_SPECIAL(num1) || NUMERIC_IS_SPECIAL(num2))
3368 {
3369 if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
3370 return make_result(&const_nan);
3371 if (NUMERIC_IS_INF(num1))
3372 {
3373 if (numeric_sign_internal(num2) == 0)
3374 goto division_by_zero;
3375
3376 /* Inf % any nonzero = NaN */
3377 return make_result(&const_nan);
3378 }
3379 /* num2 must be [-]Inf; result is num1 regardless of sign of num2 */
3380 return duplicate_numeric(num1);
3381 }
3382
3383 init_var_from_num(num1, &arg1);
3384 init_var_from_num(num2, &arg2);
3385
3386 init_var(&result);
3387
3388 /* Check for division by zero */
3389 if (arg2.ndigits == 0 || arg2.digits[0] == 0)
3390 goto division_by_zero;
3391
3392 mod_var(&arg1, &arg2, &result);
3393
3394 res = make_result_safe(&result, escontext);
3395
3396 free_var(&result);
3397
3398 return res;
3399
3400division_by_zero:
3401 ereturn(escontext, NULL,
3402 errcode(ERRCODE_DIVISION_BY_ZERO),
3403 errmsg("division by zero"));
3404}

References const_nan, NumericVar::digits, duplicate_numeric(), ereturn, errcode(), errmsg(), free_var(), init_var, init_var_from_num(), make_result(), make_result_safe(), mod_var(), NumericVar::ndigits, NUMERIC_IS_INF, NUMERIC_IS_NAN, NUMERIC_IS_SPECIAL, and numeric_sign_internal().

Referenced by executeItemOptUnwrapTarget(), and numeric_mod().

◆ numeric_mul()

Datum numeric_mul ( PG_FUNCTION_ARGS  )

Definition at line 3015 of file numeric.c.

3016{
3017 Numeric num1 = PG_GETARG_NUMERIC(0);
3018 Numeric num2 = PG_GETARG_NUMERIC(1);
3019 Numeric res;
3020
3021 res = numeric_mul_safe(num1, num2, NULL);
3022
3023 PG_RETURN_NUMERIC(res);
3024}
Numeric numeric_mul_safe(Numeric num1, Numeric num2, Node *escontext)
Definition: numeric.c:3033

References numeric_mul_safe(), PG_GETARG_NUMERIC, and PG_RETURN_NUMERIC.

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

◆ numeric_mul_safe()

Numeric numeric_mul_safe ( Numeric  num1,
Numeric  num2,
Node escontext 
)

Definition at line 3033 of file numeric.c.

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

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

Referenced by executeItemOptUnwrapTarget(), and numeric_mul().

◆ numeric_ne()

Datum numeric_ne ( PG_FUNCTION_ARGS  )

Definition at line 2446 of file numeric.c.

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

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

◆ numeric_normalize()

char * numeric_normalize ( Numeric  num)

Definition at line 1009 of file numeric.c.

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

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

Referenced by make_scalar_key().

◆ numeric_out()

Datum numeric_out ( PG_FUNCTION_ARGS  )

Definition at line 799 of file numeric.c.

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

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

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

◆ numeric_out_sci()

char * numeric_out_sci ( Numeric  num,
int  scale 
)

Definition at line 975 of file numeric.c.

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

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

Referenced by int8_to_char(), and numeric_to_char().

◆ numeric_pg_lsn()

Datum numeric_pg_lsn ( PG_FUNCTION_ARGS  )

Definition at line 4678 of file numeric.c.

4679{
4680 Numeric num = PG_GETARG_NUMERIC(0);
4681 NumericVar x;
4682 XLogRecPtr result;
4683
4684 if (NUMERIC_IS_SPECIAL(num))
4685 {
4686 if (NUMERIC_IS_NAN(num))
4687 ereport(ERROR,
4688 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4689 errmsg("cannot convert NaN to %s", "pg_lsn")));
4690 else
4691 ereport(ERROR,
4692 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4693 errmsg("cannot convert infinity to %s", "pg_lsn")));
4694 }
4695
4696 /* Convert to variable format and thence to pg_lsn */
4697 init_var_from_num(num, &x);
4698
4699 if (!numericvar_to_uint64(&x, (uint64 *) &result))
4700 ereport(ERROR,
4701 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4702 errmsg("pg_lsn out of range")));
4703
4704 PG_RETURN_LSN(result);
4705}
static bool numericvar_to_uint64(const NumericVar *var, uint64 *result)
Definition: numeric.c:7865
#define PG_RETURN_LSN(x)
Definition: pg_lsn.h:37
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 5892 of file numeric.c.

5893{
5895 NumericVar result;
5896 Datum countd,
5897 sumd;
5898
5900
5901 /* If there were no non-null inputs, return NULL */
5902 if (state == NULL || state->N == 0)
5904
5905 init_var(&result);
5906
5907 int128_to_numericvar(state->sumX, &result);
5908
5910 sumd = NumericGetDatum(make_result(&result));
5911
5912 free_var(&result);
5913
5915}

References DirectFunctionCall2, free_var(), init_var, int128_to_numericvar(), int64_to_numeric(), make_result(), 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 5524 of file numeric.c.

5525{
5526 Int128AggState *state1;
5527 Int128AggState *state2;
5528 MemoryContext agg_context;
5529 MemoryContext old_context;
5530
5531 if (!AggCheckCallContext(fcinfo, &agg_context))
5532 elog(ERROR, "aggregate function called in non-aggregate context");
5533
5534 state1 = PG_ARGISNULL(0) ? NULL : (Int128AggState *) PG_GETARG_POINTER(0);
5535 state2 = PG_ARGISNULL(1) ? NULL : (Int128AggState *) PG_GETARG_POINTER(1);
5536
5537 if (state2 == NULL)
5538 PG_RETURN_POINTER(state1);
5539
5540 /* manually copy all fields from state2 to state1 */
5541 if (state1 == NULL)
5542 {
5543 old_context = MemoryContextSwitchTo(agg_context);
5544
5545 state1 = makeInt128AggState(fcinfo, true);
5546 state1->N = state2->N;
5547 state1->sumX = state2->sumX;
5548 state1->sumX2 = state2->sumX2;
5549
5550 MemoryContextSwitchTo(old_context);
5551
5552 PG_RETURN_POINTER(state1);
5553 }
5554
5555 if (state2->N > 0)
5556 {
5557 state1->N += state2->N;
5558 int128_add_int128(&state1->sumX, state2->sumX);
5559 int128_add_int128(&state1->sumX2, state2->sumX2);
5560 }
5561 PG_RETURN_POINTER(state1);
5562}
INT128 sumX2
Definition: numeric.c:5401

References AggCheckCallContext(), elog, ERROR, int128_add_int128(), makeInt128AggState(), MemoryContextSwitchTo(), Int128AggState::N, PG_ARGISNULL, PG_GETARG_POINTER, PG_RETURN_POINTER, Int128AggState::sumX, and Int128AggState::sumX2.

◆ numeric_poly_deserialize()

Datum numeric_poly_deserialize ( PG_FUNCTION_ARGS  )

Definition at line 5626 of file numeric.c.

5627{
5628 bytea *sstate;
5629 Int128AggState *result;
5631
5632 if (!AggCheckCallContext(fcinfo, NULL))
5633 elog(ERROR, "aggregate function called in non-aggregate context");
5634
5635 sstate = PG_GETARG_BYTEA_PP(0);
5636
5637 /*
5638 * Initialize a StringInfo so that we can "receive" it using the standard
5639 * recv-function infrastructure.
5640 */
5642 VARSIZE_ANY_EXHDR(sstate));
5643
5644 result = makeInt128AggStateCurrentContext(false);
5645
5646 /* N */
5647 result->N = pq_getmsgint64(&buf);
5648
5649 /* sumX */
5650 result->sumX = int128_deserialize(&buf);
5651
5652 /* sumX2 */
5653 result->sumX2 = int128_deserialize(&buf);
5654
5655 pq_getmsgend(&buf);
5656
5657 PG_RETURN_POINTER(result);
5658}

References AggCheckCallContext(), buf, elog, ERROR, initReadOnlyStringInfo(), int128_deserialize(), makeInt128AggStateCurrentContext(), Int128AggState::N, PG_GETARG_BYTEA_PP, PG_RETURN_POINTER, pq_getmsgend(), pq_getmsgint64(), Int128AggState::sumX, Int128AggState::sumX2, VARDATA_ANY(), and VARSIZE_ANY_EXHDR().

◆ numeric_poly_serialize()

Datum numeric_poly_serialize ( PG_FUNCTION_ARGS  )

Definition at line 5592 of file numeric.c.

5593{
5596 bytea *result;
5597
5598 /* Ensure we disallow calling when not in aggregate context */
5599 if (!AggCheckCallContext(fcinfo, NULL))
5600 elog(ERROR, "aggregate function called in non-aggregate context");
5601
5603
5605
5606 /* N */
5607 pq_sendint64(&buf, state->N);
5608
5609 /* sumX */
5610 int128_serialize(&buf, state->sumX);
5611
5612 /* sumX2 */
5613 int128_serialize(&buf, state->sumX2);
5614
5615 result = pq_endtypsend(&buf);
5616
5617 PG_RETURN_BYTEA_P(result);
5618}

References AggCheckCallContext(), buf, elog, ERROR, int128_serialize(), PG_GETARG_POINTER, PG_RETURN_BYTEA_P, pq_begintypsend(), pq_endtypsend(), and pq_sendint64().

◆ numeric_poly_stddev_internal()

static Numeric numeric_poly_stddev_internal ( Int128AggState state,
bool  variance,
bool  sample,
bool *  is_null 
)
static

Definition at line 6148 of file numeric.c.

6151{
6152 NumericAggState numstate;
6153 Numeric res;
6154
6155 /* Initialize an empty agg state */
6156 memset(&numstate, 0, sizeof(NumericAggState));
6157
6158 if (state)
6159 {
6160 NumericVar tmp_var;
6161
6162 numstate.N = state->N;
6163
6164 init_var(&tmp_var);
6165
6166 int128_to_numericvar(state->sumX, &tmp_var);
6167 accum_sum_add(&numstate.sumX, &tmp_var);
6168
6169 int128_to_numericvar(state->sumX2, &tmp_var);
6170 accum_sum_add(&numstate.sumX2, &tmp_var);
6171
6172 free_var(&tmp_var);
6173 }
6174
6175 res = numeric_stddev_internal(&numstate, variance, sample, is_null);
6176
6177 if (numstate.sumX.ndigits > 0)
6178 {
6179 pfree(numstate.sumX.pos_digits);
6180 pfree(numstate.sumX.neg_digits);
6181 }
6182 if (numstate.sumX2.ndigits > 0)
6183 {
6184 pfree(numstate.sumX2.pos_digits);
6185 pfree(numstate.sumX2.neg_digits);
6186 }
6187
6188 return res;
6189}
static Numeric numeric_stddev_internal(NumericAggState *state, bool variance, bool sample, bool *is_null)
Definition: numeric.c:5996

References accum_sum_add(), free_var(), init_var, int128_to_numericvar(), NumericAggState::N, NumericSumAccum::ndigits, NumericSumAccum::neg_digits, numeric_stddev_internal(), pfree(), NumericSumAccum::pos_digits, NumericAggState::sumX, and NumericAggState::sumX2.

Referenced by numeric_poly_stddev_pop(), numeric_poly_stddev_samp(), numeric_poly_var_pop(), and numeric_poly_var_samp().

◆ numeric_poly_stddev_pop()

Datum numeric_poly_stddev_pop ( PG_FUNCTION_ARGS  )

Definition at line 6243 of file numeric.c.

6244{
6246 Numeric res;
6247 bool is_null;
6248
6250
6251 res = numeric_poly_stddev_internal(state, false, false, &is_null);
6252
6253 if (is_null)
6255 else
6256 PG_RETURN_NUMERIC(res);
6257}
static Numeric numeric_poly_stddev_internal(Int128AggState *state, bool variance, bool sample, bool *is_null)
Definition: numeric.c:6148

References numeric_poly_stddev_internal(), PG_ARGISNULL, PG_GETARG_POINTER, PG_RETURN_NULL, and PG_RETURN_NUMERIC.

◆ numeric_poly_stddev_samp()

Datum numeric_poly_stddev_samp ( PG_FUNCTION_ARGS  )

Definition at line 6209 of file numeric.c.

6210{
6212 Numeric res;
6213 bool is_null;
6214
6216
6217 res = numeric_poly_stddev_internal(state, false, true, &is_null);
6218
6219 if (is_null)
6221 else
6222 PG_RETURN_NUMERIC(res);
6223}

References numeric_poly_stddev_internal(), PG_ARGISNULL, PG_GETARG_POINTER, PG_RETURN_NULL, and PG_RETURN_NUMERIC.

◆ numeric_poly_sum()

Datum numeric_poly_sum ( PG_FUNCTION_ARGS  )

Definition at line 5868 of file numeric.c.

5869{
5871 Numeric res;
5872 NumericVar result;
5873
5875
5876 /* If there were no non-null inputs, return NULL */
5877 if (state == NULL || state->N == 0)
5879
5880 init_var(&result);
5881
5882 int128_to_numericvar(state->sumX, &result);
5883
5884 res = make_result(&result);
5885
5886 free_var(&result);
5887
5888 PG_RETURN_NUMERIC(res);
5889}

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

◆ numeric_poly_var_pop()

Datum numeric_poly_var_pop ( PG_FUNCTION_ARGS  )

Definition at line 6226 of file numeric.c.

6227{
6229 Numeric res;
6230 bool is_null;
6231
6233
6234 res = numeric_poly_stddev_internal(state, true, false, &is_null);
6235
6236 if (is_null)
6238 else
6239 PG_RETURN_NUMERIC(res);
6240}

References numeric_poly_stddev_internal(), PG_ARGISNULL, PG_GETARG_POINTER, PG_RETURN_NULL, and PG_RETURN_NUMERIC.

◆ numeric_poly_var_samp()

Datum numeric_poly_var_samp ( PG_FUNCTION_ARGS  )

Definition at line 6192 of file numeric.c.

6193{
6195 Numeric res;
6196 bool is_null;
6197
6199
6200 res = numeric_poly_stddev_internal(state, true, true, &is_null);
6201
6202 if (is_null)
6204 else
6205 PG_RETURN_NUMERIC(res);
6206}

References numeric_poly_stddev_internal(), PG_ARGISNULL, PG_GETARG_POINTER, PG_RETURN_NULL, and PG_RETURN_NUMERIC.

◆ numeric_power()

Datum numeric_power ( PG_FUNCTION_ARGS  )

Definition at line 3911 of file numeric.c.

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

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

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

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

◆ numeric_round()

Datum numeric_round ( PG_FUNCTION_ARGS  )

Definition at line 1526 of file numeric.c.

1527{
1528 Numeric num = PG_GETARG_NUMERIC(0);
1530 Numeric res;
1532
1533 /*
1534 * Handle NaN and infinities
1535 */
1536 if (NUMERIC_IS_SPECIAL(num))
1538
1539 /*
1540 * Limit the scale value to avoid possible overflow in calculations.
1541 *
1542 * These limits are based on the maximum number of digits a Numeric value
1543 * can have before and after the decimal point, but we must allow for one
1544 * extra digit before the decimal point, in case the most significant
1545 * digit rounds up; we must check if that causes Numeric overflow.
1546 */
1547 scale = Max(scale, -(NUMERIC_WEIGHT_MAX + 1) * DEC_DIGITS - 1);
1549
1550 /*
1551 * Unpack the argument and round it at the proper digit position
1552 */
1553 init_var(&arg);
1554 set_var_from_num(num, &arg);
1555
1556 round_var(&arg, scale);
1557
1558 /* We don't allow negative output dscale */
1559 if (scale < 0)
1560 arg.dscale = 0;
1561
1562 /*
1563 * Return the rounded result
1564 */
1565 res = make_result(&arg);
1566
1567 free_var(&arg);
1568 PG_RETURN_NUMERIC(res);
1569}
#define NUMERIC_WEIGHT_MAX
Definition: numeric.c:261

References arg, DEC_DIGITS, duplicate_numeric(), free_var(), init_var, make_result(), Max, Min, NUMERIC_DSCALE_MAX, NUMERIC_IS_SPECIAL, NUMERIC_WEIGHT_MAX, PG_GETARG_INT32, PG_GETARG_NUMERIC, PG_RETURN_NUMERIC, 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 4098 of file numeric.c.

4099{
4100 Numeric num = PG_GETARG_NUMERIC(0);
4101
4102 if (NUMERIC_IS_SPECIAL(num))
4104
4106}

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

1147{
1148 Numeric num = PG_GETARG_NUMERIC(0);
1149 NumericVar x;
1151 int i;
1152
1153 init_var_from_num(num, &x);
1154
1156
1157 pq_sendint16(&buf, x.ndigits);
1158 pq_sendint16(&buf, x.weight);
1159 pq_sendint16(&buf, x.sign);
1160 pq_sendint16(&buf, x.dscale);
1161 for (i = 0; i < x.ndigits; i++)
1162 pq_sendint16(&buf, x.digits[i]);
1163
1165}
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 5242 of file numeric.c.

5243{
5246 bytea *result;
5247 NumericVar tmp_var;
5248
5249 /* Ensure we disallow calling when not in aggregate context */
5250 if (!AggCheckCallContext(fcinfo, NULL))
5251 elog(ERROR, "aggregate function called in non-aggregate context");
5252
5254
5255 init_var(&tmp_var);
5256
5258
5259 /* N */
5260 pq_sendint64(&buf, state->N);
5261
5262 /* sumX */
5263 accum_sum_final(&state->sumX, &tmp_var);
5264 numericvar_serialize(&buf, &tmp_var);
5265
5266 /* sumX2 */
5267 accum_sum_final(&state->sumX2, &tmp_var);
5268 numericvar_serialize(&buf, &tmp_var);
5269
5270 /* maxScale */
5271 pq_sendint32(&buf, state->maxScale);
5272
5273 /* maxScaleCount */
5274 pq_sendint64(&buf, state->maxScaleCount);
5275
5276 /* NaNcount */
5277 pq_sendint64(&buf, state->NaNcount);
5278
5279 /* pInfcount */
5280 pq_sendint64(&buf, state->pInfcount);
5281
5282 /* nInfcount */
5283 pq_sendint64(&buf, state->nInfcount);
5284
5285 result = pq_endtypsend(&buf);
5286
5287 free_var(&tmp_var);
5288
5289 PG_RETURN_BYTEA_P(result);
5290}

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

1494{
1495 Numeric num = PG_GETARG_NUMERIC(0);
1496
1497 /*
1498 * Handle NaN (infinities can be handled normally)
1499 */
1500 if (NUMERIC_IS_NAN(num))
1502
1503 switch (numeric_sign_internal(num))
1504 {
1505 case 0:
1507 case 1:
1509 case -1:
1511 }
1512
1513 Assert(false);
1514 return (Datum) 0;
1515}

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

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

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

Referenced by numeric_div_safe(), numeric_div_trunc(), numeric_log(), numeric_mod_safe(), numeric_mul_safe(), numeric_power(), and numeric_sign().

◆ numeric_smaller()

Datum numeric_smaller ( PG_FUNCTION_ARGS  )

Definition at line 3446 of file numeric.c.

3447{
3448 Numeric num1 = PG_GETARG_NUMERIC(0);
3449 Numeric num2 = PG_GETARG_NUMERIC(1);
3450
3451 /*
3452 * Use cmp_numerics so that this will agree with the comparison operators,
3453 * particularly as regards comparisons involving NaN.
3454 */
3455 if (cmp_numerics(num1, num2) < 0)
3456 PG_RETURN_NUMERIC(num1);
3457 else
3458 PG_RETURN_NUMERIC(num2);
3459}

References cmp_numerics(), PG_GETARG_NUMERIC, and PG_RETURN_NUMERIC.

◆ numeric_sortsupport()

Datum numeric_sortsupport ( PG_FUNCTION_ARGS  )

Definition at line 2108 of file numeric.c.

2109{
2111
2113
2114 if (ssup->abbreviate)
2115 {
2116 NumericSortSupport *nss;
2117 MemoryContext oldcontext = MemoryContextSwitchTo(ssup->ssup_cxt);
2118
2120
2121 /*
2122 * palloc a buffer for handling unaligned packed values in addition to
2123 * the support struct
2124 */
2125 nss->buf = palloc(VARATT_SHORT_MAX + VARHDRSZ + 1);
2126
2127 nss->input_count = 0;
2128 nss->estimating = true;
2129 initHyperLogLog(&nss->abbr_card, 10);
2130
2131 ssup->ssup_extra = nss;
2132
2133 ssup->abbrev_full_comparator = ssup->comparator;
2137
2138 MemoryContextSwitchTo(oldcontext);
2139 }
2140
2142}
static bool numeric_abbrev_abort(int memtupcount, SortSupport ssup)
Definition: numeric.c:2211
static Datum numeric_abbrev_convert(Datum original_datum, SortSupport ssup)
Definition: numeric.c:2149
static int numeric_fast_cmp(Datum x, Datum y, SortSupport ssup)
Definition: numeric.c:2278
static int numeric_cmp_abbrev(Datum x, Datum y, SortSupport ssup)
Definition: numeric.c:2300
#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(), palloc_object, 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 3652 of file numeric.c.

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

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

◆ numeric_stddev_internal()

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

Definition at line 5996 of file numeric.c.

5999{
6000 Numeric res;
6001 NumericVar vN,
6002 vsumX,
6003 vsumX2,
6004 vNminus1;
6005 int64 totCount;
6006 int rscale;
6007
6008 /*
6009 * Sample stddev and variance are undefined when N <= 1; population stddev
6010 * is undefined when N == 0. Return NULL in either case (note that NaNs
6011 * and infinities count as normal inputs for this purpose).
6012 */
6013 if (state == NULL || (totCount = NA_TOTAL_COUNT(state)) == 0)
6014 {
6015 *is_null = true;
6016 return NULL;
6017 }
6018
6019 if (sample && totCount <= 1)
6020 {
6021 *is_null = true;
6022 return NULL;
6023 }
6024
6025 *is_null = false;
6026
6027 /*
6028 * Deal with NaN and infinity cases. By analogy to the behavior of the
6029 * float8 functions, any infinity input produces NaN output.
6030 */
6031 if (state->NaNcount > 0 || state->pInfcount > 0 || state->nInfcount > 0)
6032 return make_result(&const_nan);
6033
6034 /* OK, normal calculation applies */
6035 init_var(&vN);
6036 init_var(&vsumX);
6037 init_var(&vsumX2);
6038
6039 int64_to_numericvar(state->N, &vN);
6040 accum_sum_final(&(state->sumX), &vsumX);
6041 accum_sum_final(&(state->sumX2), &vsumX2);
6042
6043 init_var(&vNminus1);
6044 sub_var(&vN, &const_one, &vNminus1);
6045
6046 /* compute rscale for mul_var calls */
6047 rscale = vsumX.dscale * 2;
6048
6049 mul_var(&vsumX, &vsumX, &vsumX, rscale); /* vsumX = sumX * sumX */
6050 mul_var(&vN, &vsumX2, &vsumX2, rscale); /* vsumX2 = N * sumX2 */
6051 sub_var(&vsumX2, &vsumX, &vsumX2); /* N * sumX2 - sumX * sumX */
6052
6053 if (cmp_var(&vsumX2, &const_zero) <= 0)
6054 {
6055 /* Watch out for roundoff error producing a negative numerator */
6056 res = make_result(&const_zero);
6057 }
6058 else
6059 {
6060 if (sample)
6061 mul_var(&vN, &vNminus1, &vNminus1, 0); /* N * (N - 1) */
6062 else
6063 mul_var(&vN, &vN, &vNminus1, 0); /* N * N */
6064 rscale = select_div_scale(&vsumX2, &vNminus1);
6065 div_var(&vsumX2, &vNminus1, &vsumX, rscale, true, true); /* variance */
6066 if (!variance)
6067 sqrt_var(&vsumX, &vsumX, rscale); /* stddev */
6068
6069 res = make_result(&vsumX);
6070 }
6071
6072 free_var(&vNminus1);
6073 free_var(&vsumX);
6074 free_var(&vsumX2);
6075
6076 return res;
6077}

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

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

6132{
6134 Numeric res;
6135 bool is_null;
6136
6138
6139 res = numeric_stddev_internal(state, false, false, &is_null);
6140
6141 if (is_null)
6143 else
6144 PG_RETURN_NUMERIC(res);
6145}

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

◆ numeric_stddev_samp()

Datum numeric_stddev_samp ( PG_FUNCTION_ARGS  )

Definition at line 6097 of file numeric.c.

6098{
6100 Numeric res;
6101 bool is_null;
6102
6104
6105 res = numeric_stddev_internal(state, false, true, &is_null);
6106
6107 if (is_null)
6109 else
6110 PG_RETURN_NUMERIC(res);
6111}

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

◆ numeric_sub()

Datum numeric_sub ( PG_FUNCTION_ARGS  )

Definition at line 2939 of file numeric.c.

2940{
2941 Numeric num1 = PG_GETARG_NUMERIC(0);
2942 Numeric num2 = PG_GETARG_NUMERIC(1);
2943 Numeric res;
2944
2945 res = numeric_sub_safe(num1, num2, NULL);
2946
2947 PG_RETURN_NUMERIC(res);
2948}
Numeric numeric_sub_safe(Numeric num1, Numeric num2, Node *escontext)
Definition: numeric.c:2957

References numeric_sub_safe(), PG_GETARG_NUMERIC, and PG_RETURN_NUMERIC.

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

◆ numeric_sub_safe()

Numeric numeric_sub_safe ( Numeric  num1,
Numeric  num2,
Node escontext 
)

Definition at line 2957 of file numeric.c.

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

References Assert(), const_nan, const_ninf, const_pinf, free_var(), init_var, init_var_from_num(), make_result(), make_result_safe(), NUMERIC_IS_NAN, NUMERIC_IS_NINF, NUMERIC_IS_PINF, NUMERIC_IS_SPECIAL, 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 5953 of file numeric.c.

5954{
5956 NumericVar sumX_var;
5957 Numeric result;
5958
5960
5961 /* If there were no non-null inputs, return NULL */
5962 if (state == NULL || NA_TOTAL_COUNT(state) == 0)
5964
5965 if (state->NaNcount > 0) /* there was at least one NaN input */
5967
5968 /* adding plus and minus infinities gives NaN */
5969 if (state->pInfcount > 0 && state->nInfcount > 0)
5971 if (state->pInfcount > 0)
5973 if (state->nInfcount > 0)
5975
5976 init_var(&sumX_var);
5977 accum_sum_final(&state->sumX, &sumX_var);
5978 result = make_result(&sumX_var);
5979 free_var(&sumX_var);
5980
5981 PG_RETURN_NUMERIC(result);
5982}

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.

◆ numeric_support()

Datum numeric_support ( PG_FUNCTION_ARGS  )

Definition at line 1179 of file numeric.c.

1180{
1181 Node *rawreq = (Node *) PG_GETARG_POINTER(0);
1182 Node *ret = NULL;
1183
1184 if (IsA(rawreq, SupportRequestSimplify))
1185 {
1187 FuncExpr *expr = req->fcall;
1188 Node *typmod;
1189
1190 Assert(list_length(expr->args) >= 2);
1191
1192 typmod = (Node *) lsecond(expr->args);
1193
1194 if (IsA(typmod, Const) && !((Const *) typmod)->constisnull)
1195 {
1196 Node *source = (Node *) linitial(expr->args);
1197 int32 old_typmod = exprTypmod(source);
1198 int32 new_typmod = DatumGetInt32(((Const *) typmod)->constvalue);
1199 int32 old_scale = numeric_typmod_scale(old_typmod);
1200 int32 new_scale = numeric_typmod_scale(new_typmod);
1201 int32 old_precision = numeric_typmod_precision(old_typmod);
1202 int32 new_precision = numeric_typmod_precision(new_typmod);
1203
1204 /*
1205 * If new_typmod is invalid, the destination is unconstrained;
1206 * that's always OK. If old_typmod is valid, the source is
1207 * constrained, and we're OK if the scale is unchanged and the
1208 * precision is not decreasing. See further notes in function
1209 * header comment.
1210 */
1211 if (!is_valid_numeric_typmod(new_typmod) ||
1212 (is_valid_numeric_typmod(old_typmod) &&
1213 new_scale == old_scale && new_precision >= old_precision))
1214 ret = relabel_to_typmod(source, new_typmod);
1215 }
1216 }
1217
1218 PG_RETURN_POINTER(ret);
1219}
int32 exprTypmod(const Node *expr)
Definition: nodeFuncs.c:301
Node * relabel_to_typmod(Node *expr, int32 typmod)
Definition: nodeFuncs.c:689
static rewind_source * source
Definition: pg_rewind.c:89
static int32 DatumGetInt32(Datum X)
Definition: postgres.h:212
List * args
Definition: primnodes.h:800

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

4184{
4185 Numeric num = PG_GETARG_NUMERIC(0);
4186 Numeric res;
4187 NumericVar result;
4188
4189 if (NUMERIC_IS_SPECIAL(num))
4191
4192 init_var_from_num(num, &result);
4193 result.dscale = get_min_scale(&result);
4194 res = make_result(&result);
4195 free_var(&result);
4196
4197 PG_RETURN_NUMERIC(res);
4198}

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

◆ numeric_trunc()

Datum numeric_trunc ( PG_FUNCTION_ARGS  )

Definition at line 1580 of file numeric.c.

1581{
1582 Numeric num = PG_GETARG_NUMERIC(0);
1584 Numeric res;
1586
1587 /*
1588 * Handle NaN and infinities
1589 */
1590 if (NUMERIC_IS_SPECIAL(num))
1592
1593 /*
1594 * Limit the scale value to avoid possible overflow in calculations.
1595 *
1596 * These limits are based on the maximum number of digits a Numeric value
1597 * can have before and after the decimal point.
1598 */
1601
1602 /*
1603 * Unpack the argument and truncate it at the proper digit position
1604 */
1605 init_var(&arg);
1606 set_var_from_num(num, &arg);
1607
1608 trunc_var(&arg, scale);
1609
1610 /* We don't allow negative output dscale */
1611 if (scale < 0)
1612 arg.dscale = 0;
1613
1614 /*
1615 * Return the truncated result
1616 */
1617 res = make_result(&arg);
1618
1619 free_var(&arg);
1620 PG_RETURN_NUMERIC(res);
1621}

References arg, DEC_DIGITS, duplicate_numeric(), free_var(), init_var, make_result(), Max, Min, NUMERIC_DSCALE_MAX, NUMERIC_IS_SPECIAL, NUMERIC_WEIGHT_MAX, PG_GETARG_INT32, PG_GETARG_NUMERIC, PG_RETURN_NUMERIC, 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 910 of file numeric.c.

911{
912 return ((typmod - VARHDRSZ) >> 16) & 0xffff;
913}

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

926{
927 return (((typmod - VARHDRSZ) & 0x7ff) ^ 1024) - 1024;
928}

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

1404{
1405 Numeric num = PG_GETARG_NUMERIC(0);
1406 Numeric res;
1407
1408 /*
1409 * Do it the easy way directly on the packed format
1410 */
1411 res = duplicate_numeric(num);
1412
1413 if (NUMERIC_IS_SPECIAL(num))
1414 {
1415 /* Flip the sign, if it's Inf or -Inf */
1416 if (!NUMERIC_IS_NAN(num))
1417 res->choice.n_short.n_header =
1419 }
1420
1421 /*
1422 * The packed format is known to be totally zero digit trimmed always. So
1423 * once we've eliminated specials, we can identify a zero by the fact that
1424 * there are no digits at all. Do nothing to a zero.
1425 */
1426 else if (NUMERIC_NDIGITS(num) != 0)
1427 {
1428 /* Else, flip the sign */
1429 if (NUMERIC_IS_SHORT(num))
1430 res->choice.n_short.n_header =
1432 else if (NUMERIC_SIGN(num) == NUMERIC_POS)
1435 else
1438 }
1439
1440 PG_RETURN_NUMERIC(res);
1441}
#define NUMERIC_INF_SIGN_MASK
Definition: numeric.c:204

References NumericData::choice, duplicate_numeric(), NumericShort::n_header, NumericChoice::n_long, NumericChoice::n_short, NumericLong::n_sign_dscale, 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, and PG_RETURN_NUMERIC.

Referenced by executeItemOptUnwrapTarget().

◆ numeric_uplus()

Datum numeric_uplus ( PG_FUNCTION_ARGS  )

Definition at line 1445 of file numeric.c.

1446{
1447 Numeric num = PG_GETARG_NUMERIC(0);
1448
1450}

References duplicate_numeric(), PG_GETARG_NUMERIC, and PG_RETURN_NUMERIC.

◆ numeric_var_pop()

Datum numeric_var_pop ( PG_FUNCTION_ARGS  )

Definition at line 6114 of file numeric.c.

6115{
6117 Numeric res;
6118 bool is_null;
6119
6121
6122 res = numeric_stddev_internal(state, true, false, &is_null);
6123
6124 if (is_null)
6126 else
6127 PG_RETURN_NUMERIC(res);
6128}

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

◆ numeric_var_samp()

Datum numeric_var_samp ( PG_FUNCTION_ARGS  )

Definition at line 6080 of file numeric.c.

6081{
6083 Numeric res;
6084 bool is_null;
6085
6087
6088 res = numeric_stddev_internal(state, true, true, &is_null);
6089
6090 if (is_null)
6092 else
6093 PG_RETURN_NUMERIC(res);
6094}

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

◆ numerictypmodin()

Datum numerictypmodin ( PG_FUNCTION_ARGS  )

Definition at line 1307 of file numeric.c.

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

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

1353{
1354 int32 typmod = PG_GETARG_INT32(0);
1355 char *res = (char *) palloc(64);
1356
1357 if (is_valid_numeric_typmod(typmod))
1358 snprintf(res, 64, "(%d,%d)",
1360 numeric_typmod_scale(typmod));
1361 else
1362 *res = '\0';
1363
1364 PG_RETURN_CSTRING(res);
1365}

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

◆ numericvar_deserialize()

static void numericvar_deserialize ( StringInfo  buf,
NumericVar var 
)
static

Definition at line 7470 of file numeric.c.

7471{
7472 int len,
7473 i;
7474
7475 len = pq_getmsgint(buf, sizeof(int32));
7476
7477 alloc_var(var, len); /* sets var->ndigits */
7478
7479 var->weight = pq_getmsgint(buf, sizeof(int32));
7480 var->sign = pq_getmsgint(buf, sizeof(int32));
7481 var->dscale = pq_getmsgint(buf, sizeof(int32));
7482 for (i = 0; i < len; i++)
7483 var->digits[i] = pq_getmsgint(buf, sizeof(int16));
7484}

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

Referenced by numeric_avg_deserialize(), and numeric_deserialize().

◆ numericvar_serialize()

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

Definition at line 7454 of file numeric.c.

7455{
7456 int i;
7457
7458 pq_sendint32(buf, var->ndigits);
7459 pq_sendint32(buf, var->weight);
7460 pq_sendint32(buf, var->sign);
7461 pq_sendint32(buf, var->dscale);
7462 for (i = 0; i < var->ndigits; i++)
7463 pq_sendint16(buf, var->digits[i]);
7464}

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

Referenced by numeric_avg_serialize(), and numeric_serialize().

◆ numericvar_to_double_no_overflow()

static double numericvar_to_double_no_overflow ( const NumericVar var)
static

Definition at line 7971 of file numeric.c.

7972{
7973 char *tmp;
7974 double val;
7975 char *endptr;
7976
7977 tmp = get_str_from_var(var);
7978
7979 /* unlike float8in, we ignore ERANGE from strtod */
7980 val = strtod(tmp, &endptr);
7981 if (*endptr != '\0')
7982 {
7983 /* shouldn't happen ... */
7984 ereport(ERROR,
7985 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
7986 errmsg("invalid input syntax for type %s: \"%s\"",
7987 "double precision", tmp)));
7988 }
7989
7990 pfree(tmp);
7991
7992 return val;
7993}

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

Referenced by exp_var(), generate_series_numeric_support(), 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 4406 of file numeric.c.

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

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

Referenced by numeric_int4_safe(), and width_bucket_numeric().

◆ numericvar_to_int64()

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

Definition at line 7743 of file numeric.c.

7744{
7746 int ndigits;
7747 int weight;
7748 int i;
7749 int64 val;
7750 bool neg;
7751 NumericVar rounded;
7752
7753 /* Round to nearest integer */
7754 init_var(&rounded);
7755 set_var_from_var(var, &rounded);
7756 round_var(&rounded, 0);
7757
7758 /* Check for zero input */
7759 strip_var(&rounded);
7760 ndigits = rounded.ndigits;
7761 if (ndigits == 0)
7762 {
7763 *result = 0;
7764 free_var(&rounded);
7765 return true;
7766 }
7767
7768 /*
7769 * For input like 10000000000, we must treat stripped digits as real. So
7770 * the loop assumes there are weight+1 digits before the decimal point.
7771 */
7772 weight = rounded.weight;
7773 Assert(weight >= 0 && ndigits <= weight + 1);
7774
7775 /*
7776 * Construct the result. To avoid issues with converting a value
7777 * corresponding to INT64_MIN (which can't be represented as a positive 64
7778 * bit two's complement integer), accumulate value as a negative number.
7779 */
7780 digits = rounded.digits;
7781 neg = (rounded.sign == NUMERIC_NEG);
7782 val = -digits[0];
7783 for (i = 1; i <= weight; i++)
7784 {
7786 {
7787 free_var(&rounded);
7788 return false;
7789 }
7790
7791 if (i < ndigits)
7792 {
7794 {
7795 free_var(&rounded);
7796 return false;
7797 }
7798 }
7799 }
7800
7801 free_var(&rounded);
7802
7803 if (!neg)
7804 {
7805 if (unlikely(val == PG_INT64_MIN))
7806 return false;
7807 val = -val;
7808 }
7809 *result = val;
7810
7811 return true;
7812}
#define PG_INT64_MIN
Definition: c.h:610
static bool pg_sub_s64_overflow(int64 a, int64 b, int64 *result)
Definition: int.h:262

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_safe(), numericvar_to_int32(), and power_var().

◆ numericvar_to_uint64()

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

Definition at line 7865 of file numeric.c.

7866{
7868 int ndigits;
7869 int weight;
7870 int i;
7871 uint64 val;
7872 NumericVar rounded;
7873
7874 /* Round to nearest integer */
7875 init_var(&rounded);
7876 set_var_from_var(var, &rounded);
7877 round_var(&rounded, 0);
7878
7879 /* Check for zero input */
7880 strip_var(&rounded);
7881 ndigits = rounded.ndigits;
7882 if (ndigits == 0)
7883 {
7884 *result = 0;
7885 free_var(&rounded);
7886 return true;
7887 }
7888
7889 /* Check for negative input */
7890 if (rounded.sign == NUMERIC_NEG)
7891 {
7892 free_var(&rounded);
7893 return false;
7894 }
7895
7896 /*
7897 * For input like 10000000000, we must treat stripped digits as real. So
7898 * the loop assumes there are weight+1 digits before the decimal point.
7899 */
7900 weight = rounded.weight;
7901 Assert(weight >= 0 && ndigits <= weight + 1);
7902
7903 /* Construct the result */
7904 digits = rounded.digits;
7905 val = digits[0];
7906 for (i = 1; i <= weight; i++)
7907 {
7909 {
7910 free_var(&rounded);
7911 return false;
7912 }
7913
7914 if (i < ndigits)
7915 {
7917 {
7918 free_var(&rounded);
7919 return false;
7920 }
7921 }
7922 }
7923
7924 free_var(&rounded);
7925
7926 *result = val;
7927
7928 return true;
7929}
static bool pg_add_u64_overflow(uint64 a, uint64 b, uint64 *result)
Definition: int.h:514
static bool pg_mul_u64_overflow(uint64 a, uint64 b, uint64 *result)
Definition: int.h:548

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

11168{
11169 /* Construct the result directly, starting from 10^0 = 1 */
11170 set_var_from_var(&const_one, result);
11171
11172 /* Scale needed to represent the result exactly */
11173 result->dscale = exp < 0 ? -exp : 0;
11174
11175 /* Base-NBASE weight of result and remaining exponent */
11176 if (exp >= 0)
11177 result->weight = exp / DEC_DIGITS;
11178 else
11179 result->weight = (exp + 1) / DEC_DIGITS - 1;
11180
11181 exp -= result->weight * DEC_DIGITS;
11182
11183 /* Final adjustment of the result's single NBASE digit */
11184 while (exp-- > 0)
11185 result->digits[0] *= 10;
11186}

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

10801{
10802 int res_sign;
10803 NumericVar abs_base;
10804 NumericVar ln_base;
10805 NumericVar ln_num;
10806 int ln_dweight;
10807 int rscale;
10808 int sig_digits;
10809 int local_rscale;
10810 double val;
10811
10812 /* If exp can be represented as an integer, use power_var_int */
10813 if (exp->ndigits == 0 || exp->ndigits <= exp->weight + 1)
10814 {
10815 /* exact integer, but does it fit in int? */
10816 int64 expval64;
10817
10818 if (numericvar_to_int64(exp, &expval64))
10819 {
10820 if (expval64 >= PG_INT32_MIN && expval64 <= PG_INT32_MAX)
10821 {
10822 /* Okay, use power_var_int */
10823 power_var_int(base, (int) expval64, exp->dscale, result);
10824 return;
10825 }
10826 }
10827 }
10828
10829 /*
10830 * This avoids log(0) for cases of 0 raised to a non-integer. 0 ^ 0 is
10831 * handled by power_var_int().
10832 */
10833 if (cmp_var(base, &const_zero) == 0)
10834 {
10835 set_var_from_var(&const_zero, result);
10836 result->dscale = NUMERIC_MIN_SIG_DIGITS; /* no need to round */
10837 return;
10838 }
10839
10840 init_var(&abs_base);
10841 init_var(&ln_base);
10842 init_var(&ln_num);
10843
10844 /*
10845 * If base is negative, insist that exp be an integer. The result is then
10846 * positive if exp is even and negative if exp is odd.
10847 */
10848 if (base->sign == NUMERIC_NEG)
10849 {
10850 /*
10851 * Check that exp is an integer. This error code is defined by the
10852 * SQL standard, and matches other errors in numeric_power().
10853 */
10854 if (exp->ndigits > 0 && exp->ndigits > exp->weight + 1)
10855 ereport(ERROR,
10856 (errcode(ERRCODE_INVALID_ARGUMENT_FOR_POWER_FUNCTION),
10857 errmsg("a negative number raised to a non-integer power yields a complex result")));
10858
10859 /* Test if exp is odd or even */
10860 if (exp->ndigits > 0 && exp->ndigits == exp->weight + 1 &&
10861 (exp->digits[exp->ndigits - 1] & 1))
10862 res_sign = NUMERIC_NEG;
10863 else
10864 res_sign = NUMERIC_POS;
10865
10866 /* Then work with abs(base) below */
10867 set_var_from_var(base, &abs_base);
10868 abs_base.sign = NUMERIC_POS;
10869 base = &abs_base;
10870 }
10871 else
10872 res_sign = NUMERIC_POS;
10873
10874 /*----------
10875 * Decide on the scale for the ln() calculation. For this we need an
10876 * estimate of the weight of the result, which we obtain by doing an
10877 * initial low-precision calculation of exp * ln(base).
10878 *
10879 * We want result = e ^ (exp * ln(base))
10880 * so result dweight = log10(result) = exp * ln(base) * log10(e)
10881 *
10882 * We also perform a crude overflow test here so that we can exit early if
10883 * the full-precision result is sure to overflow, and to guard against
10884 * integer overflow when determining the scale for the real calculation.
10885 * exp_var() supports inputs up to NUMERIC_MAX_RESULT_SCALE * 3, so the
10886 * result will overflow if exp * ln(base) >= NUMERIC_MAX_RESULT_SCALE * 3.
10887 * Since the values here are only approximations, we apply a small fuzz
10888 * factor to this overflow test and let exp_var() determine the exact
10889 * overflow threshold so that it is consistent for all inputs.
10890 *----------
10891 */
10892 ln_dweight = estimate_ln_dweight(base);
10893
10894 /*
10895 * Set the scale for the low-precision calculation, computing ln(base) to
10896 * around 8 significant digits. Note that ln_dweight may be as small as
10897 * -NUMERIC_DSCALE_MAX, so the scale may exceed NUMERIC_MAX_DISPLAY_SCALE
10898 * here.
10899 */
10900 local_rscale = 8 - ln_dweight;
10901 local_rscale = Max(local_rscale, NUMERIC_MIN_DISPLAY_SCALE);
10902
10903 ln_var(base, &ln_base, local_rscale);
10904
10905 mul_var(&ln_base, exp, &ln_num, local_rscale);
10906
10908
10909 /* initial overflow/underflow test with fuzz factor */
10910 if (fabs(val) > NUMERIC_MAX_RESULT_SCALE * 3.01)
10911 {
10912 if (val > 0)
10913 ereport(ERROR,
10914 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
10915 errmsg("value overflows numeric format")));
10916 zero_var(result);
10918 return;
10919 }
10920
10921 val *= 0.434294481903252; /* approximate decimal result weight */
10922
10923 /* choose the result scale */
10924 rscale = NUMERIC_MIN_SIG_DIGITS - (int) val;
10925 rscale = Max(rscale, base->dscale);
10926 rscale = Max(rscale, exp->dscale);
10927 rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
10928 rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
10929
10930 /* significant digits required in the result */
10931 sig_digits = rscale + (int) val;
10932 sig_digits = Max(sig_digits, 0);
10933
10934 /* set the scale for the real exp * ln(base) calculation */
10935 local_rscale = sig_digits - ln_dweight + 8;
10936 local_rscale = Max(local_rscale, NUMERIC_MIN_DISPLAY_SCALE);
10937
10938 /* and do the real calculation */
10939
10940 ln_var(base, &ln_base, local_rscale);
10941
10942 mul_var(&ln_base, exp, &ln_num, local_rscale);
10943
10944 exp_var(&ln_num, result, rscale);
10945
10946 if (res_sign == NUMERIC_NEG && result->ndigits > 0)
10947 result->sign = NUMERIC_NEG;
10948
10949 free_var(&ln_num);
10950 free_var(&ln_base);
10951 free_var(&abs_base);
10952}
static void power_var_int(const NumericVar *base, int exp, int exp_dscale, NumericVar *result)
Definition: numeric.c:10962

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

10964{
10965 double f;
10966 int p;
10967 int i;
10968 int rscale;
10969 int sig_digits;
10970 unsigned int mask;
10971 bool neg;
10972 NumericVar base_prod;
10973 int local_rscale;
10974
10975 /*
10976 * Choose the result scale. For this we need an estimate of the decimal
10977 * weight of the result, which we obtain by approximating using double
10978 * precision arithmetic.
10979 *
10980 * We also perform crude overflow/underflow tests here so that we can exit
10981 * early if the result is sure to overflow/underflow, and to guard against
10982 * integer overflow when choosing the result scale.
10983 */
10984 if (base->ndigits != 0)
10985 {
10986 /*----------
10987 * Choose f (double) and p (int) such that base ~= f * 10^p.
10988 * Then log10(result) = log10(base^exp) ~= exp * (log10(f) + p).
10989 *----------
10990 */
10991 f = base->digits[0];
10992 p = base->weight * DEC_DIGITS;
10993
10994 for (i = 1; i < base->ndigits && i * DEC_DIGITS < 16; i++)
10995 {
10996 f = f * NBASE + base->digits[i];
10997 p -= DEC_DIGITS;
10998 }
10999
11000 f = exp * (log10(f) + p); /* approximate decimal result weight */
11001 }
11002 else
11003 f = 0; /* result is 0 or 1 (weight 0), or error */
11004
11005 /* overflow/underflow tests with fuzz factors */
11006 if (f > (NUMERIC_WEIGHT_MAX + 1) * DEC_DIGITS)
11007 ereport(ERROR,
11008 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
11009 errmsg("value overflows numeric format")));
11010 if (f + 1 < -NUMERIC_MAX_DISPLAY_SCALE)
11011 {
11012 zero_var(result);
11014 return;
11015 }
11016
11017 /*
11018 * Choose the result scale in the same way as power_var(), so it has at
11019 * least NUMERIC_MIN_SIG_DIGITS significant digits and is not less than
11020 * either input's display scale.
11021 */
11022 rscale = NUMERIC_MIN_SIG_DIGITS - (int) f;
11023 rscale = Max(rscale, base->dscale);
11024 rscale = Max(rscale, exp_dscale);
11025 rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
11026 rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
11027
11028 /* Handle some common special cases, as well as corner cases */
11029 switch (exp)
11030 {
11031 case 0:
11032
11033 /*
11034 * While 0 ^ 0 can be either 1 or indeterminate (error), we treat
11035 * it as 1 because most programming languages do this. SQL:2003
11036 * also requires a return value of 1.
11037 * https://en.wikipedia.org/wiki/Exponentiation#Zero_to_the_zero_power
11038 */
11039 set_var_from_var(&const_one, result);
11040 result->dscale = rscale; /* no need to round */
11041 return;
11042 case 1:
11043 set_var_from_var(base, result);
11044 round_var(result, rscale);
11045 return;
11046 case -1:
11047 div_var(&const_one, base, result, rscale, true, true);
11048 return;
11049 case 2:
11050 mul_var(base, base, result, rscale);
11051 return;
11052 default:
11053 break;
11054 }
11055
11056 /* Handle the special case where the base is zero */
11057 if (base->ndigits == 0)
11058 {
11059 if (exp < 0)
11060 ereport(ERROR,
11061 (errcode(ERRCODE_DIVISION_BY_ZERO),
11062 errmsg("division by zero")));
11063 zero_var(result);
11064 result->dscale = rscale;
11065 return;
11066 }
11067
11068 /*
11069 * The general case repeatedly multiplies base according to the bit
11070 * pattern of exp.
11071 *
11072 * The local rscale used for each multiplication is varied to keep a fixed
11073 * number of significant digits, sufficient to give the required result
11074 * scale.
11075 */
11076
11077 /*
11078 * Approximate number of significant digits in the result. Note that the
11079 * underflow test above, together with the choice of rscale, ensures that
11080 * this approximation is necessarily > 0.
11081 */
11082 sig_digits = 1 + rscale + (int) f;
11083
11084 /*
11085 * The multiplications to produce the result may introduce an error of up
11086 * to around log10(abs(exp)) digits, so work with this many extra digits
11087 * of precision (plus a few more for good measure).
11088 */
11089 sig_digits += (int) log(fabs((double) exp)) + 8;
11090
11091 /*
11092 * Now we can proceed with the multiplications.
11093 */
11094 neg = (exp < 0);
11095 mask = pg_abs_s32(exp);
11096
11097 init_var(&base_prod);
11098 set_var_from_var(base, &base_prod);
11099
11100 if (mask & 1)
11101 set_var_from_var(base, result);
11102 else
11103 set_var_from_var(&const_one, result);
11104
11105 while ((mask >>= 1) > 0)
11106 {
11107 /*
11108 * Do the multiplications using rscales large enough to hold the
11109 * results to the required number of significant digits, but don't
11110 * waste time by exceeding the scales of the numbers themselves.
11111 */
11112 local_rscale = sig_digits - 2 * base_prod.weight * DEC_DIGITS;
11113 local_rscale = Min(local_rscale, 2 * base_prod.dscale);
11114 local_rscale = Max(local_rscale, NUMERIC_MIN_DISPLAY_SCALE);
11115
11116 mul_var(&base_prod, &base_prod, &base_prod, local_rscale);
11117
11118 if (mask & 1)
11119 {
11120 local_rscale = sig_digits -
11121 (base_prod.weight + result->weight) * DEC_DIGITS;
11122 local_rscale = Min(local_rscale,
11123 base_prod.dscale + result->dscale);
11124 local_rscale = Max(local_rscale, NUMERIC_MIN_DISPLAY_SCALE);
11125
11126 mul_var(&base_prod, result, result, local_rscale);
11127 }
11128
11129 /*
11130 * When abs(base) > 1, the number of digits to the left of the decimal
11131 * point in base_prod doubles at each iteration, so if exp is large we
11132 * could easily spend large amounts of time and memory space doing the
11133 * multiplications. But once the weight exceeds what will fit in
11134 * int16, the final result is guaranteed to overflow (or underflow, if
11135 * exp < 0), so we can give up before wasting too many cycles.
11136 */
11137 if (base_prod.weight > NUMERIC_WEIGHT_MAX ||
11138 result->weight > NUMERIC_WEIGHT_MAX)
11139 {
11140 /* overflow, unless neg, in which case result should be 0 */
11141 if (!neg)
11142 ereport(ERROR,
11143 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
11144 errmsg("value overflows numeric format")));
11145 zero_var(result);
11146 neg = false;
11147 break;
11148 }
11149 }
11150
11151 free_var(&base_prod);
11152
11153 /* Compensate for input sign, and round to requested rscale */
11154 if (neg)
11155 div_var(&const_one, result, result, rscale, true, false);
11156 else
11157 round_var(result, rscale);
11158}
static uint32 pg_abs_s32(int32 a)
Definition: int.h:221

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

Referenced by power_var().

◆ random_numeric()

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

Definition at line 4204 of file numeric.c.

4205{
4206 NumericVar rmin_var;
4207 NumericVar rmax_var;
4208 NumericVar result;
4209 Numeric res;
4210
4211 /* Range bounds must not be NaN/infinity */
4212 if (NUMERIC_IS_SPECIAL(rmin))
4213 {
4214 if (NUMERIC_IS_NAN(rmin))
4215 ereport(ERROR,
4216 errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4217 errmsg("lower bound cannot be NaN"));
4218 else
4219 ereport(ERROR,
4220 errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4221 errmsg("lower bound cannot be infinity"));
4222 }
4223 if (NUMERIC_IS_SPECIAL(rmax))
4224 {
4225 if (NUMERIC_IS_NAN(rmax))
4226 ereport(ERROR,
4227 errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4228 errmsg("upper bound cannot be NaN"));
4229 else
4230 ereport(ERROR,
4231 errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4232 errmsg("upper bound cannot be infinity"));
4233 }
4234
4235 /* Return a random value in the range [rmin, rmax] */
4236 init_var_from_num(rmin, &rmin_var);
4237 init_var_from_num(rmax, &rmax_var);
4238
4239 init_var(&result);
4240
4241 random_var(state, &rmin_var, &rmax_var, &result);
4242
4243 res = make_result(&result);
4244
4245 free_var(&result);
4246
4247 return res;
4248}
static void random_var(pg_prng_state *state, const NumericVar *rmin, const NumericVar *rmax, NumericVar *result)
Definition: numeric.c:11192

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

Referenced by numeric_random().

◆ random_var()

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

Definition at line 11192 of file numeric.c.

11194{
11195 int rscale;
11196 NumericVar rlen;
11197 int res_ndigits;
11198 int n;
11199 int pow10;
11200 int i;
11201 uint64 rlen64;
11202 int rlen64_ndigits;
11203
11204 rscale = Max(rmin->dscale, rmax->dscale);
11205
11206 /* Compute rlen = rmax - rmin and check the range bounds */
11207 init_var(&rlen);
11208 sub_var(rmax, rmin, &rlen);
11209
11210 if (rlen.sign == NUMERIC_NEG)
11211 ereport(ERROR,
11212 errcode(ERRCODE_INVALID_PARAMETER_VALUE),
11213 errmsg("lower bound must be less than or equal to upper bound"));
11214
11215 /* Special case for an empty range */
11216 if (rlen.ndigits == 0)
11217 {
11218 set_var_from_var(rmin, result);
11219 result->dscale = rscale;
11220 free_var(&rlen);
11221 return;
11222 }
11223
11224 /*
11225 * Otherwise, select a random value in the range [0, rlen = rmax - rmin],
11226 * and shift it to the required range by adding rmin.
11227 */
11228
11229 /* Required result digits */
11230 res_ndigits = rlen.weight + 1 + (rscale + DEC_DIGITS - 1) / DEC_DIGITS;
11231
11232 /*
11233 * To get the required rscale, the final result digit must be a multiple
11234 * of pow10 = 10^n, where n = (-rscale) mod DEC_DIGITS.
11235 */
11236 n = ((rscale + DEC_DIGITS - 1) / DEC_DIGITS) * DEC_DIGITS - rscale;
11237 pow10 = 1;
11238 for (i = 0; i < n; i++)
11239 pow10 *= 10;
11240
11241 /*
11242 * To choose a random value uniformly from the range [0, rlen], we choose
11243 * from the slightly larger range [0, rlen2], where rlen2 is formed from
11244 * rlen by copying the first 4 NBASE digits, and setting all remaining
11245 * decimal digits to "9".
11246 *
11247 * Without loss of generality, we can ignore the weight of rlen2 and treat
11248 * it as a pure integer for the purposes of this discussion. The process
11249 * above gives rlen2 + 1 = rlen64 * 10^N, for some integer N, where rlen64
11250 * is a 64-bit integer formed from the first 4 NBASE digits copied from
11251 * rlen. Since this trivially factors into smaller pieces that fit in
11252 * 64-bit integers, the task of choosing a random value uniformly from the
11253 * rlen2 + 1 possible values in [0, rlen2] is much simpler.
11254 *
11255 * If the random value selected is too large, it is rejected, and we try
11256 * again until we get a result <= rlen, ensuring that the overall result
11257 * is uniform (no particular value is any more likely than any other).
11258 *
11259 * Since rlen64 holds 4 NBASE digits from rlen, it contains at least
11260 * DEC_DIGITS * 3 + 1 decimal digits (i.e., at least 13 decimal digits,
11261 * when DEC_DIGITS is 4). Therefore the probability of needing to reject
11262 * the value chosen and retry is less than 1e-13.
11263 */
11264 rlen64 = (uint64) rlen.digits[0];
11265 rlen64_ndigits = 1;
11266 while (rlen64_ndigits < res_ndigits && rlen64_ndigits < 4)
11267 {
11268 rlen64 *= NBASE;
11269 if (rlen64_ndigits < rlen.ndigits)
11270 rlen64 += rlen.digits[rlen64_ndigits];
11271 rlen64_ndigits++;
11272 }
11273
11274 /* Loop until we get a result <= rlen */
11275 do
11276 {
11277 NumericDigit *res_digits;
11278 uint64 rand;
11279 int whole_ndigits;
11280
11281 alloc_var(result, res_ndigits);
11282 result->sign = NUMERIC_POS;
11283 result->weight = rlen.weight;
11284 result->dscale = rscale;
11285 res_digits = result->digits;
11286
11287 /*
11288 * Set the first rlen64_ndigits using a random value in [0, rlen64].
11289 *
11290 * If this is the whole result, and rscale is not a multiple of
11291 * DEC_DIGITS (pow10 from above is not 1), then we need this to be a
11292 * multiple of pow10.
11293 */
11294 if (rlen64_ndigits == res_ndigits && pow10 != 1)
11295 rand = pg_prng_uint64_range(state, 0, rlen64 / pow10) * pow10;
11296 else
11297 rand = pg_prng_uint64_range(state, 0, rlen64);
11298
11299 for (i = rlen64_ndigits - 1; i >= 0; i--)
11300 {
11301 res_digits[i] = (NumericDigit) (rand % NBASE);
11302 rand = rand / NBASE;
11303 }
11304
11305 /*
11306 * Set the remaining digits to random values in range [0, NBASE),
11307 * noting that the last digit needs to be a multiple of pow10.
11308 */
11309 whole_ndigits = res_ndigits;
11310 if (pow10 != 1)
11311 whole_ndigits--;
11312
11313 /* Set whole digits in groups of 4 for best performance */
11314 i = rlen64_ndigits;
11315 while (i < whole_ndigits - 3)
11316 {
11317 rand = pg_prng_uint64_range(state, 0,
11318 (uint64) NBASE * NBASE * NBASE * NBASE - 1);
11319 res_digits[i++] = (NumericDigit) (rand % NBASE);
11320 rand = rand / NBASE;
11321 res_digits[i++] = (NumericDigit) (rand % NBASE);
11322 rand = rand / NBASE;
11323 res_digits[i++] = (NumericDigit) (rand % NBASE);
11324 rand = rand / NBASE;
11325 res_digits[i++] = (NumericDigit) rand;
11326 }
11327
11328 /* Remaining whole digits */
11329 while (i < whole_ndigits)
11330 {
11331 rand = pg_prng_uint64_range(state, 0, NBASE - 1);
11332 res_digits[i++] = (NumericDigit) rand;
11333 }
11334
11335 /* Final partial digit (multiple of pow10) */
11336 if (i < res_ndigits)
11337 {
11338 rand = pg_prng_uint64_range(state, 0, NBASE / pow10 - 1) * pow10;
11339 res_digits[i] = (NumericDigit) rand;
11340 }
11341
11342 /* Remove leading/trailing zeroes */
11343 strip_var(result);
11344
11345 /* If result > rlen, try again */
11346
11347 } while (cmp_var(result, &rlen) > 0);
11348
11349 /* Offset the result to the required range */
11350 add_var(result, rmin, result);
11351
11352 free_var(&rlen);
11353}
while(p+4<=pend)
uint64 pg_prng_uint64_range(pg_prng_state *state, uint64 rmin, uint64 rmax)
Definition: pg_prng.c:144

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

Referenced by random_numeric().

◆ round_var()

static void round_var ( NumericVar var,
int  rscale 
)
static

Definition at line 11620 of file numeric.c.

11621{
11622 NumericDigit *digits = var->digits;
11623 int di;
11624 int ndigits;
11625 int carry;
11626
11627 var->dscale = rscale;
11628
11629 /* decimal digits wanted */
11630 di = (var->weight + 1) * DEC_DIGITS + rscale;
11631
11632 /*
11633 * If di = 0, the value loses all digits, but could round up to 1 if its
11634 * first extra digit is >= 5. If di < 0 the result must be 0.
11635 */
11636 if (di < 0)
11637 {
11638 var->ndigits = 0;
11639 var->weight = 0;
11640 var->sign = NUMERIC_POS;
11641 }
11642 else
11643 {
11644 /* NBASE digits wanted */
11645 ndigits = (di + DEC_DIGITS - 1) / DEC_DIGITS;
11646
11647 /* 0, or number of decimal digits to keep in last NBASE digit */
11648 di %= DEC_DIGITS;
11649
11650 if (ndigits < var->ndigits ||
11651 (ndigits == var->ndigits && di > 0))
11652 {
11653 var->ndigits = ndigits;
11654
11655#if DEC_DIGITS == 1
11656 /* di must be zero */
11657 carry = (digits[ndigits] >= HALF_NBASE) ? 1 : 0;
11658#else
11659 if (di == 0)
11660 carry = (digits[ndigits] >= HALF_NBASE) ? 1 : 0;
11661 else
11662 {
11663 /* Must round within last NBASE digit */
11664 int extra,
11665 pow10;
11666
11667#if DEC_DIGITS == 4
11668 pow10 = round_powers[di];
11669#elif DEC_DIGITS == 2
11670 pow10 = 10;
11671#else
11672#error unsupported NBASE
11673#endif
11674 extra = digits[--ndigits] % pow10;
11675 digits[ndigits] -= extra;
11676 carry = 0;
11677 if (extra >= pow10 / 2)
11678 {
11679 pow10 += digits[ndigits];
11680 if (pow10 >= NBASE)
11681 {
11682 pow10 -= NBASE;
11683 carry = 1;
11684 }
11685 digits[ndigits] = pow10;
11686 }
11687 }
11688#endif
11689
11690 /* Propagate carry if needed */
11691 while (carry)
11692 {
11693 carry += digits[--ndigits];
11694 if (carry >= NBASE)
11695 {
11696 digits[ndigits] = carry - NBASE;
11697 carry = 1;
11698 }
11699 else
11700 {
11701 digits[ndigits] = carry;
11702 carry = 0;
11703 }
11704 }
11705
11706 if (ndigits < 0)
11707 {
11708 Assert(ndigits == -1); /* better not have added > 1 digit */
11709 Assert(var->digits > var->buf);
11710 var->digits--;
11711 var->ndigits++;
11712 var->weight++;
11713 }
11714 }
11715 }
11716}
static const int round_powers[4]
Definition: numeric.c:461
#define HALF_NBASE
Definition: numeric.c:98

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

Referenced by apply_typmod(), div_var(), div_var_int(), exp_var(), mul_var(), numeric_mul_safe(), 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 9646 of file numeric.c.

9647{
9648 int weight1,
9649 weight2,
9650 qweight,
9651 i;
9652 NumericDigit firstdigit1,
9653 firstdigit2;
9654 int rscale;
9655
9656 /*
9657 * The result scale of a division isn't specified in any SQL standard. For
9658 * PostgreSQL we select a result scale that will give at least
9659 * NUMERIC_MIN_SIG_DIGITS significant digits, so that numeric gives a
9660 * result no less accurate than float8; but use a scale not less than
9661 * either input's display scale.
9662 */
9663
9664 /* Get the actual (normalized) weight and first digit of each input */
9665
9666 weight1 = 0; /* values to use if var1 is zero */
9667 firstdigit1 = 0;
9668 for (i = 0; i < var1->ndigits; i++)
9669 {
9670 firstdigit1 = var1->digits[i];
9671 if (firstdigit1 != 0)
9672 {
9673 weight1 = var1->weight - i;
9674 break;
9675 }
9676 }
9677
9678 weight2 = 0; /* values to use if var2 is zero */
9679 firstdigit2 = 0;
9680 for (i = 0; i < var2->ndigits; i++)
9681 {
9682 firstdigit2 = var2->digits[i];
9683 if (firstdigit2 != 0)
9684 {
9685 weight2 = var2->weight - i;
9686 break;
9687 }
9688 }
9689
9690 /*
9691 * Estimate weight of quotient. If the two first digits are equal, we
9692 * can't be sure, but assume that var1 is less than var2.
9693 */
9694 qweight = weight1 - weight2;
9695 if (firstdigit1 <= firstdigit2)
9696 qweight--;
9697
9698 /* Select result scale */
9699 rscale = NUMERIC_MIN_SIG_DIGITS - qweight * DEC_DIGITS;
9700 rscale = Max(rscale, var1->dscale);
9701 rscale = Max(rscale, var2->dscale);
9702 rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
9703 rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
9704
9705 return rscale;
9706}

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

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

6975{
6976 const char *firstdigit = cp;
6977 int64 tmp;
6978 int64 mul;
6979 NumericVar tmp_var;
6980
6981 init_var(&tmp_var);
6982
6983 zero_var(dest);
6984
6985 /*
6986 * Process input digits in groups that fit in int64. Here "tmp" is the
6987 * value of the digits in the group, and "mul" is base^n, where n is the
6988 * number of digits in the group. Thus tmp < mul, and we must start a new
6989 * group when mul * base threatens to overflow PG_INT64_MAX.
6990 */
6991 tmp = 0;
6992 mul = 1;
6993
6994 if (base == 16)
6995 {
6996 while (*cp)
6997 {
6998 if (isxdigit((unsigned char) *cp))
6999 {
7000 if (mul > PG_INT64_MAX / 16)
7001 {
7002 /* Add the contribution from this group of digits */
7003 int64_to_numericvar(mul, &tmp_var);
7004 mul_var(dest, &tmp_var, dest, 0);
7005 int64_to_numericvar(tmp, &tmp_var);
7006 add_var(dest, &tmp_var, dest);
7007
7008 /* Result will overflow if weight overflows int16 */
7009 if (dest->weight > NUMERIC_WEIGHT_MAX)
7010 goto out_of_range;
7011
7012 /* Begin a new group */
7013 tmp = 0;
7014 mul = 1;
7015 }
7016
7017 tmp = tmp * 16 + xdigit_value(*cp++);
7018 mul = mul * 16;
7019 }
7020 else if (*cp == '_')
7021 {
7022 /* Underscore must be followed by more digits */
7023 cp++;
7024 if (!isxdigit((unsigned char) *cp))
7025 goto invalid_syntax;
7026 }
7027 else
7028 break;
7029 }
7030 }
7031 else if (base == 8)
7032 {
7033 while (*cp)
7034 {
7035 if (*cp >= '0' && *cp <= '7')
7036 {
7037 if (mul > PG_INT64_MAX / 8)
7038 {
7039 /* Add the contribution from this group of digits */
7040 int64_to_numericvar(mul, &tmp_var);
7041 mul_var(dest, &tmp_var, dest, 0);
7042 int64_to_numericvar(tmp, &tmp_var);
7043 add_var(dest, &tmp_var, dest);
7044
7045 /* Result will overflow if weight overflows int16 */
7046 if (dest->weight > NUMERIC_WEIGHT_MAX)
7047 goto out_of_range;
7048
7049 /* Begin a new group */
7050 tmp = 0;
7051 mul = 1;
7052 }
7053
7054 tmp = tmp * 8 + (*cp++ - '0');
7055 mul = mul * 8;
7056 }
7057 else if (*cp == '_')
7058 {
7059 /* Underscore must be followed by more digits */
7060 cp++;
7061 if (*cp < '0' || *cp > '7')
7062 goto invalid_syntax;
7063 }
7064 else
7065 break;
7066 }
7067 }
7068 else if (base == 2)
7069 {
7070 while (*cp)
7071 {
7072 if (*cp >= '0' && *cp <= '1')
7073 {
7074 if (mul > PG_INT64_MAX / 2)
7075 {
7076 /* Add the contribution from this group of digits */
7077 int64_to_numericvar(mul, &tmp_var);
7078 mul_var(dest, &tmp_var, dest, 0);
7079 int64_to_numericvar(tmp, &tmp_var);
7080 add_var(dest, &tmp_var, dest);
7081
7082 /* Result will overflow if weight overflows int16 */
7083 if (dest->weight > NUMERIC_WEIGHT_MAX)
7084 goto out_of_range;
7085
7086 /* Begin a new group */
7087 tmp = 0;
7088 mul = 1;
7089 }
7090
7091 tmp = tmp * 2 + (*cp++ - '0');
7092 mul = mul * 2;
7093 }
7094 else if (*cp == '_')
7095 {
7096 /* Underscore must be followed by more digits */
7097 cp++;
7098 if (*cp < '0' || *cp > '1')
7099 goto invalid_syntax;
7100 }
7101 else
7102 break;
7103 }
7104 }
7105 else
7106 /* Should never happen; treat as invalid input */
7107 goto invalid_syntax;
7108
7109 /* Check that we got at least one digit */
7110 if (unlikely(cp == firstdigit))
7111 goto invalid_syntax;
7112
7113 /* Add the contribution from the final group of digits */
7114 int64_to_numericvar(mul, &tmp_var);
7115 mul_var(dest, &tmp_var, dest, 0);
7116 int64_to_numericvar(tmp, &tmp_var);
7117 add_var(dest, &tmp_var, dest);
7118
7119 if (dest->weight > NUMERIC_WEIGHT_MAX)
7120 goto out_of_range;
7121
7122 dest->sign = sign;
7123
7124 free_var(&tmp_var);
7125
7126 /* Return end+1 position for caller */
7127 *endptr = cp;
7128
7129 return true;
7130
7131out_of_range:
7132 ereturn(escontext, false,
7133 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
7134 errmsg("value overflows numeric format")));
7135
7136invalid_syntax:
7137 ereturn(escontext, false,
7138 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
7139 errmsg("invalid input syntax for type %s: \"%s\"",
7140 "numeric", str)));
7141}
static int xdigit_value(char dig)
Definition: numeric.c:6945

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

Referenced by numeric_in().

◆ set_var_from_num()

static void set_var_from_num ( Numeric  num,
NumericVar dest 
)
static

Definition at line 7150 of file numeric.c.

7151{
7152 int ndigits;
7153
7154 ndigits = NUMERIC_NDIGITS(num);
7155
7156 alloc_var(dest, ndigits);
7157
7158 dest->weight = NUMERIC_WEIGHT(num);
7159 dest->sign = NUMERIC_SIGN(num);
7160 dest->dscale = NUMERIC_DSCALE(num);
7161
7162 memcpy(dest->digits, NUMERIC_DIGITS(num), ndigits * sizeof(NumericDigit));
7163}

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

6745{
6746 bool have_dp = false;
6747 int i;
6748 unsigned char *decdigits;
6749 int sign = NUMERIC_POS;
6750 int dweight = -1;
6751 int ddigits;
6752 int dscale = 0;
6753 int weight;
6754 int ndigits;
6755 int offset;
6757
6758 /*
6759 * We first parse the string to extract decimal digits and determine the
6760 * correct decimal weight. Then convert to NBASE representation.
6761 */
6762 switch (*cp)
6763 {
6764 case '+':
6765 sign = NUMERIC_POS;
6766 cp++;
6767 break;
6768
6769 case '-':
6770 sign = NUMERIC_NEG;
6771 cp++;
6772 break;
6773 }
6774
6775 if (*cp == '.')
6776 {
6777 have_dp = true;
6778 cp++;
6779 }
6780
6781 if (!isdigit((unsigned char) *cp))
6782 goto invalid_syntax;
6783
6784 decdigits = (unsigned char *) palloc(strlen(cp) + DEC_DIGITS * 2);
6785
6786 /* leading padding for digit alignment later */
6787 memset(decdigits, 0, DEC_DIGITS);
6788 i = DEC_DIGITS;
6789
6790 while (*cp)
6791 {
6792 if (isdigit((unsigned char) *cp))
6793 {
6794 decdigits[i++] = *cp++ - '0';
6795 if (!have_dp)
6796 dweight++;
6797 else
6798 dscale++;
6799 }
6800 else if (*cp == '.')
6801 {
6802 if (have_dp)
6803 goto invalid_syntax;
6804 have_dp = true;
6805 cp++;
6806 /* decimal point must not be followed by underscore */
6807 if (*cp == '_')
6808 goto invalid_syntax;
6809 }
6810 else if (*cp == '_')
6811 {
6812 /* underscore must be followed by more digits */
6813 cp++;
6814 if (!isdigit((unsigned char) *cp))
6815 goto invalid_syntax;
6816 }
6817 else
6818 break;
6819 }
6820
6821 ddigits = i - DEC_DIGITS;
6822 /* trailing padding for digit alignment later */
6823 memset(decdigits + i, 0, DEC_DIGITS - 1);
6824
6825 /* Handle exponent, if any */
6826 if (*cp == 'e' || *cp == 'E')
6827 {
6828 int64 exponent = 0;
6829 bool neg = false;
6830
6831 /*
6832 * At this point, dweight and dscale can't be more than about
6833 * INT_MAX/2 due to the MaxAllocSize limit on string length, so
6834 * constraining the exponent similarly should be enough to prevent
6835 * integer overflow in this function. If the value is too large to
6836 * fit in storage format, make_result() will complain about it later;
6837 * for consistency use the same ereport errcode/text as make_result().
6838 */
6839
6840 /* exponent sign */
6841 cp++;
6842 if (*cp == '+')
6843 cp++;
6844 else if (*cp == '-')
6845 {
6846 neg = true;
6847 cp++;
6848 }
6849
6850 /* exponent digits */
6851 if (!isdigit((unsigned char) *cp))
6852 goto invalid_syntax;
6853
6854 while (*cp)
6855 {
6856 if (isdigit((unsigned char) *cp))
6857 {
6858 exponent = exponent * 10 + (*cp++ - '0');
6859 if (exponent > PG_INT32_MAX / 2)
6860 goto out_of_range;
6861 }
6862 else if (*cp == '_')
6863 {
6864 /* underscore must be followed by more digits */
6865 cp++;
6866 if (!isdigit((unsigned char) *cp))
6867 goto invalid_syntax;
6868 }
6869 else
6870 break;
6871 }
6872
6873 if (neg)
6874 exponent = -exponent;
6875
6876 dweight += (int) exponent;
6877 dscale -= (int) exponent;
6878 if (dscale < 0)
6879 dscale = 0;
6880 }
6881
6882 /*
6883 * Okay, convert pure-decimal representation to base NBASE. First we need
6884 * to determine the converted weight and ndigits. offset is the number of
6885 * decimal zeroes to insert before the first given digit to have a
6886 * correctly aligned first NBASE digit.
6887 */
6888 if (dweight >= 0)
6889 weight = (dweight + 1 + DEC_DIGITS - 1) / DEC_DIGITS - 1;
6890 else
6891 weight = -((-dweight - 1) / DEC_DIGITS + 1);
6892 offset = (weight + 1) * DEC_DIGITS - (dweight + 1);
6893 ndigits = (ddigits + offset + DEC_DIGITS - 1) / DEC_DIGITS;
6894
6895 alloc_var(dest, ndigits);
6896 dest->sign = sign;
6897 dest->weight = weight;
6898 dest->dscale = dscale;
6899
6900 i = DEC_DIGITS - offset;
6901 digits = dest->digits;
6902
6903 while (ndigits-- > 0)
6904 {
6905#if DEC_DIGITS == 4
6906 *digits++ = ((decdigits[i] * 10 + decdigits[i + 1]) * 10 +
6907 decdigits[i + 2]) * 10 + decdigits[i + 3];
6908#elif DEC_DIGITS == 2
6909 *digits++ = decdigits[i] * 10 + decdigits[i + 1];
6910#elif DEC_DIGITS == 1
6911 *digits++ = decdigits[i];
6912#else
6913#error unsupported NBASE
6914#endif
6915 i += DEC_DIGITS;
6916 }
6917
6918 pfree(decdigits);
6919
6920 /* Strip any leading/trailing zeroes, and normalize weight if zero */
6921 strip_var(dest);
6922
6923 /* Return end+1 position for caller */
6924 *endptr = cp;
6925
6926 return true;
6927
6928out_of_range:
6929 ereturn(escontext, false,
6930 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
6931 errmsg("value overflows numeric format")));
6932
6933invalid_syntax:
6934 ereturn(escontext, false,
6935 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
6936 errmsg("invalid input syntax for type %s: \"%s\"",
6937 "numeric", str)));
6938}

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

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

◆ set_var_from_var()

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

Definition at line 7198 of file numeric.c.

7199{
7200 NumericDigit *newbuf;
7201
7202 newbuf = digitbuf_alloc(value->ndigits + 1);
7203 newbuf[0] = 0; /* spare digit for rounding */
7204 if (value->ndigits > 0) /* else value->digits might be null */
7205 memcpy(newbuf + 1, value->digits,
7206 value->ndigits * sizeof(NumericDigit));
7207
7208 digitbuf_free(dest->buf);
7209
7210 memmove(dest, value, sizeof(NumericVar));
7211 dest->buf = newbuf;
7212 dest->digits = newbuf + 1;
7213}

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

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

◆ sqrt_var()

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

Definition at line 9931 of file numeric.c.

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

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

11789{
11790 NumericDigit *digits = var->digits;
11791 int ndigits = var->ndigits;
11792
11793 /* Strip leading zeroes */
11794 while (ndigits > 0 && *digits == 0)
11795 {
11796 digits++;
11797 var->weight--;
11798 ndigits--;
11799 }
11800
11801 /* Strip trailing zeroes */
11802 while (ndigits > 0 && digits[ndigits - 1] == 0)
11803 ndigits--;
11804
11805 /* If it's zero, normalize the sign and weight */
11806 if (ndigits == 0)
11807 {
11808 var->sign = NUMERIC_POS;
11809 var->weight = 0;
11810 }
11811
11812 var->digits = digits;
11813 var->ndigits = ndigits;
11814}

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

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

◆ sub_abs()

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

Definition at line 11538 of file numeric.c.

11539{
11540 NumericDigit *res_buf;
11541 NumericDigit *res_digits;
11542 int res_ndigits;
11543 int res_weight;
11544 int res_rscale,
11545 rscale1,
11546 rscale2;
11547 int res_dscale;
11548 int i,
11549 i1,
11550 i2;
11551 int borrow = 0;
11552
11553 /* copy these values into local vars for speed in inner loop */
11554 int var1ndigits = var1->ndigits;
11555 int var2ndigits = var2->ndigits;
11556 NumericDigit *var1digits = var1->digits;
11557 NumericDigit *var2digits = var2->digits;
11558
11559 res_weight = var1->weight;
11560
11561 res_dscale = Max(var1->dscale, var2->dscale);
11562
11563 /* Note: here we are figuring rscale in base-NBASE digits */
11564 rscale1 = var1->ndigits - var1->weight - 1;
11565 rscale2 = var2->ndigits - var2->weight - 1;
11566 res_rscale = Max(rscale1, rscale2);
11567
11568 res_ndigits = res_rscale + res_weight + 1;
11569 if (res_ndigits <= 0)
11570 res_ndigits = 1;
11571
11572 res_buf = digitbuf_alloc(res_ndigits + 1);
11573 res_buf[0] = 0; /* spare digit for later rounding */
11574 res_digits = res_buf + 1;
11575
11576 i1 = res_rscale + var1->weight + 1;
11577 i2 = res_rscale + var2->weight + 1;
11578 for (i = res_ndigits - 1; i >= 0; i--)
11579 {
11580 i1--;
11581 i2--;
11582 if (i1 >= 0 && i1 < var1ndigits)
11583 borrow += var1digits[i1];
11584 if (i2 >= 0 && i2 < var2ndigits)
11585 borrow -= var2digits[i2];
11586
11587 if (borrow < 0)
11588 {
11589 res_digits[i] = borrow + NBASE;
11590 borrow = -1;
11591 }
11592 else
11593 {
11594 res_digits[i] = borrow;
11595 borrow = 0;
11596 }
11597 }
11598
11599 Assert(borrow == 0); /* else caller gave us var1 < var2 */
11600
11601 digitbuf_free(result->buf);
11602 result->ndigits = res_ndigits;
11603 result->buf = res_buf;
11604 result->digits = res_digits;
11605 result->weight = res_weight;
11606 result->dscale = res_dscale;
11607
11608 /* Remove leading/trailing zeroes */
11609 strip_var(result);
11610}

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

8179{
8180 /*
8181 * Decide on the signs of the two variables what to do
8182 */
8183 if (var1->sign == NUMERIC_POS)
8184 {
8185 if (var2->sign == NUMERIC_NEG)
8186 {
8187 /* ----------
8188 * var1 is positive, var2 is negative
8189 * result = +(ABS(var1) + ABS(var2))
8190 * ----------
8191 */
8192 add_abs(var1, var2, result);
8193 result->sign = NUMERIC_POS;
8194 }
8195 else
8196 {
8197 /* ----------
8198 * Both are positive
8199 * Must compare absolute values
8200 * ----------
8201 */
8202 switch (cmp_abs(var1, var2))
8203 {
8204 case 0:
8205 /* ----------
8206 * ABS(var1) == ABS(var2)
8207 * result = ZERO
8208 * ----------
8209 */
8210 zero_var(result);
8211 result->dscale = Max(var1->dscale, var2->dscale);
8212 break;
8213
8214 case 1:
8215 /* ----------
8216 * ABS(var1) > ABS(var2)
8217 * result = +(ABS(var1) - ABS(var2))
8218 * ----------
8219 */
8220 sub_abs(var1, var2, result);
8221 result->sign = NUMERIC_POS;
8222 break;
8223
8224 case -1:
8225 /* ----------
8226 * ABS(var1) < ABS(var2)
8227 * result = -(ABS(var2) - ABS(var1))
8228 * ----------
8229 */
8230 sub_abs(var2, var1, result);
8231 result->sign = NUMERIC_NEG;
8232 break;
8233 }
8234 }
8235 }
8236 else
8237 {
8238 if (var2->sign == NUMERIC_NEG)
8239 {
8240 /* ----------
8241 * Both are negative
8242 * Must compare absolute values
8243 * ----------
8244 */
8245 switch (cmp_abs(var1, var2))
8246 {
8247 case 0:
8248 /* ----------
8249 * ABS(var1) == ABS(var2)
8250 * result = ZERO
8251 * ----------
8252 */
8253 zero_var(result);
8254 result->dscale = Max(var1->dscale, var2->dscale);
8255 break;
8256
8257 case 1:
8258 /* ----------
8259 * ABS(var1) > ABS(var2)
8260 * result = -(ABS(var1) - ABS(var2))
8261 * ----------
8262 */
8263 sub_abs(var1, var2, result);
8264 result->sign = NUMERIC_NEG;
8265 break;
8266
8267 case -1:
8268 /* ----------
8269 * ABS(var1) < ABS(var2)
8270 * result = +(ABS(var2) - ABS(var1))
8271 * ----------
8272 */
8273 sub_abs(var2, var1, result);
8274 result->sign = NUMERIC_POS;
8275 break;
8276 }
8277 }
8278 else
8279 {
8280 /* ----------
8281 * var1 is negative, var2 is positive
8282 * result = -(ABS(var1) + ABS(var2))
8283 * ----------
8284 */
8285 add_abs(var1, var2, result);
8286 result->sign = NUMERIC_NEG;
8287 }
8288 }
8289}

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(), generate_series_numeric_support(), in_range_numeric_numeric(), ln_var(), mod_var(), numeric_stddev_internal(), numeric_sub_safe(), random_var(), and sqrt_var().

◆ trunc_var()

static void trunc_var ( NumericVar var,
int  rscale 
)
static

Definition at line 11726 of file numeric.c.

11727{
11728 int di;
11729 int ndigits;
11730
11731 var->dscale = rscale;
11732
11733 /* decimal digits wanted */
11734 di = (var->weight + 1) * DEC_DIGITS + rscale;
11735
11736 /*
11737 * If di <= 0, the value loses all digits.
11738 */
11739 if (di <= 0)
11740 {
11741 var->ndigits = 0;
11742 var->weight = 0;
11743 var->sign = NUMERIC_POS;
11744 }
11745 else
11746 {
11747 /* NBASE digits wanted */
11748 ndigits = (di + DEC_DIGITS - 1) / DEC_DIGITS;
11749
11750 if (ndigits <= var->ndigits)
11751 {
11752 var->ndigits = ndigits;
11753
11754#if DEC_DIGITS == 1
11755 /* no within-digit stuff to worry about */
11756#else
11757 /* 0, or number of decimal digits to keep in last NBASE digit */
11758 di %= DEC_DIGITS;
11759
11760 if (di > 0)
11761 {
11762 /* Must truncate within last NBASE digit */
11763 NumericDigit *digits = var->digits;
11764 int extra,
11765 pow10;
11766
11767#if DEC_DIGITS == 4
11768 pow10 = round_powers[di];
11769#elif DEC_DIGITS == 2
11770 pow10 = 10;
11771#else
11772#error unsupported NBASE
11773#endif
11774 extra = digits[--ndigits] % pow10;
11775 digits[ndigits] -= extra;
11776 }
11777#endif
11778 }
11779 }
11780}

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

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

◆ width_bucket_numeric()

Datum width_bucket_numeric ( PG_FUNCTION_ARGS  )

Definition at line 1950 of file numeric.c.

1951{
1952 Numeric operand = PG_GETARG_NUMERIC(0);
1953 Numeric bound1 = PG_GETARG_NUMERIC(1);
1954 Numeric bound2 = PG_GETARG_NUMERIC(2);
1955 int32 count = PG_GETARG_INT32(3);
1956 NumericVar count_var;
1957 NumericVar result_var;
1958 int32 result;
1959
1960 if (count <= 0)
1961 ereport(ERROR,
1962 (errcode(ERRCODE_INVALID_ARGUMENT_FOR_WIDTH_BUCKET_FUNCTION),
1963 errmsg("count must be greater than zero")));
1964
1965 if (NUMERIC_IS_SPECIAL(bound1) || NUMERIC_IS_SPECIAL(bound2))
1966 {
1967 if (NUMERIC_IS_NAN(bound1) || NUMERIC_IS_NAN(bound2))
1968 ereport(ERROR,
1969 (errcode(ERRCODE_INVALID_ARGUMENT_FOR_WIDTH_BUCKET_FUNCTION),
1970 errmsg("lower and upper bounds cannot be NaN")));
1971
1972 if (NUMERIC_IS_INF(bound1) || NUMERIC_IS_INF(bound2))
1973 ereport(ERROR,
1974 (errcode(ERRCODE_INVALID_ARGUMENT_FOR_WIDTH_BUCKET_FUNCTION),
1975 errmsg("lower and upper bounds must be finite")));
1976 }
1977
1978 init_var(&result_var);
1979 init_var(&count_var);
1980
1981 /* Convert 'count' to a numeric, for ease of use later */
1982 int64_to_numericvar((int64) count, &count_var);
1983
1984 switch (cmp_numerics(bound1, bound2))
1985 {
1986 case 0:
1987 ereport(ERROR,
1988 (errcode(ERRCODE_INVALID_ARGUMENT_FOR_WIDTH_BUCKET_FUNCTION),
1989 errmsg("lower bound cannot equal upper bound")));
1990 break;
1991
1992 /* bound1 < bound2 */
1993 case -1:
1994 if (cmp_numerics(operand, bound1) < 0)
1995 set_var_from_var(&const_zero, &result_var);
1996 else if (cmp_numerics(operand, bound2) >= 0)
1997 add_var(&count_var, &const_one, &result_var);
1998 else
1999 compute_bucket(operand, bound1, bound2, &count_var,
2000 &result_var);
2001 break;
2002
2003 /* bound1 > bound2 */
2004 case 1:
2005 if (cmp_numerics(operand, bound1) > 0)
2006 set_var_from_var(&const_zero, &result_var);
2007 else if (cmp_numerics(operand, bound2) <= 0)
2008 add_var(&count_var, &const_one, &result_var);
2009 else
2010 compute_bucket(operand, bound1, bound2, &count_var,
2011 &result_var);
2012 break;
2013 }
2014
2015 /* if result exceeds the range of a legal int4, we ereport here */
2016 if (!numericvar_to_int32(&result_var, &result))
2017 ereport(ERROR,
2018 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
2019 errmsg("integer out of range")));
2020
2021 free_var(&count_var);
2022 free_var(&result_var);
2023
2024 PG_RETURN_INT32(result);
2025}
static void compute_bucket(Numeric operand, Numeric bound1, Numeric bound2, const NumericVar *count_var, NumericVar *result_var)
Definition: numeric.c:2034

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

6946{
6947 return dig >= '0' && dig <= '9' ? dig - '0' :
6948 dig >= 'a' && dig <= 'f' ? dig - 'a' + 10 :
6949 dig >= 'A' && dig <= 'F' ? dig - 'A' + 10 : -1;
6950}

Referenced by set_var_from_non_decimal_integer_str().

◆ zero_var()

static void zero_var ( NumericVar var)
static

Definition at line 6715 of file numeric.c.

6716{
6717 digitbuf_free(var->buf);
6718 var->buf = NULL;
6719 var->digits = NULL;
6720 var->ndigits = 0;
6721 var->weight = 0; /* by convention; doesn't really matter */
6722 var->sign = NUMERIC_POS; /* anything but NAN... */
6723}

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

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

Variable Documentation

◆ const_minus_one

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

Definition at line 424 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 420 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:442

Definition at line 448 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 442 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:427

Definition at line 428 of file numeric.c.

Referenced by ln_var().

◆ const_two_data

const NumericDigit const_two_data[1] = {2}
static

Definition at line 427 of file numeric.c.

◆ const_zero

◆ const_zero_data

const NumericDigit const_zero_data[1] = {0}
static

Definition at line 416 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:432

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

◆ round_powers

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

Definition at line 461 of file numeric.c.

Referenced by round_var(), and trunc_var().