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
Definition: pg_test_fsync.c:72

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 4738 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:700
int16_t int16
Definition: c.h:536
uint16_t uint16
Definition: c.h:540

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

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

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

12125{
12126 NumericVar tmp_var;
12127
12128 init_var(&tmp_var);
12129
12130 accum_sum_final(accum2, &tmp_var);
12131 accum_sum_add(accum, &tmp_var);
12132
12133 free_var(&tmp_var);
12134}
static void accum_sum_final(NumericSumAccum *accum, NumericVar *result)
Definition: numeric.c:12056
static void free_var(NumericVar *var)
Definition: numeric.c:6700
static void accum_sum_add(NumericSumAccum *accum, const NumericVar *val)
Definition: numeric.c:11846
#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 12107 of file numeric.c.

12108{
12109 dst->pos_digits = palloc(src->ndigits * sizeof(int32));
12110 dst->neg_digits = palloc(src->ndigits * sizeof(int32));
12111
12112 memcpy(dst->pos_digits, src->pos_digits, src->ndigits * sizeof(int32));
12113 memcpy(dst->neg_digits, src->neg_digits, src->ndigits * sizeof(int32));
12114 dst->num_uncarried = src->num_uncarried;
12115 dst->ndigits = src->ndigits;
12116 dst->weight = src->weight;
12117 dst->dscale = src->dscale;
12118}
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 12056 of file numeric.c.

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

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

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

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

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

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

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

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

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

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

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

9816{
9817 NumericVar tmp;
9818
9819 init_var(&tmp);
9820 set_var_from_var(var, &tmp);
9821
9822 trunc_var(&tmp, 0);
9823
9824 if (var->sign == NUMERIC_POS && cmp_var(var, &tmp) != 0)
9825 add_var(&tmp, &const_one, &tmp);
9826
9827 set_var_from_var(&tmp, result);
9828 free_var(&tmp);
9829}
static void trunc_var(NumericVar *var, int rscale)
Definition: numeric.c:11727
static int cmp_var(const NumericVar *var1, const NumericVar *var2)
Definition: numeric.c:8004
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 11376 of file numeric.c.

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

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

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

Referenced by cmp_abs(), and cmp_var_common().

◆ cmp_numerics()

static int cmp_numerics ( Numeric  num1,
Numeric  num2 
)
static

Definition at line 2522 of file numeric.c.

2523{
2524 int result;
2525
2526 /*
2527 * We consider all NANs to be equal and larger than any non-NAN (including
2528 * Infinity). This is somewhat arbitrary; the important thing is to have
2529 * a consistent sort order.
2530 */
2531 if (NUMERIC_IS_SPECIAL(num1))
2532 {
2533 if (NUMERIC_IS_NAN(num1))
2534 {
2535 if (NUMERIC_IS_NAN(num2))
2536 result = 0; /* NAN = NAN */
2537 else
2538 result = 1; /* NAN > non-NAN */
2539 }
2540 else if (NUMERIC_IS_PINF(num1))
2541 {
2542 if (NUMERIC_IS_NAN(num2))
2543 result = -1; /* PINF < NAN */
2544 else if (NUMERIC_IS_PINF(num2))
2545 result = 0; /* PINF = PINF */
2546 else
2547 result = 1; /* PINF > anything else */
2548 }
2549 else /* num1 must be NINF */
2550 {
2551 if (NUMERIC_IS_NINF(num2))
2552 result = 0; /* NINF = NINF */
2553 else
2554 result = -1; /* NINF < anything else */
2555 }
2556 }
2557 else if (NUMERIC_IS_SPECIAL(num2))
2558 {
2559 if (NUMERIC_IS_NINF(num2))
2560 result = 1; /* normal > NINF */
2561 else
2562 result = -1; /* normal < NAN or PINF */
2563 }
2564 else
2565 {
2566 result = cmp_var_common(NUMERIC_DIGITS(num1), NUMERIC_NDIGITS(num1),
2567 NUMERIC_WEIGHT(num1), NUMERIC_SIGN(num1),
2568 NUMERIC_DIGITS(num2), NUMERIC_NDIGITS(num2),
2569 NUMERIC_WEIGHT(num2), NUMERIC_SIGN(num2));
2570 }
2571
2572 return result;
2573}
#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:8019

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

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

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

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

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

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

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

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

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

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

5449{
5450 if (state->calcSumX2)
5452
5453 int128_add_int64(&state->sumX, newval);
5454 state->N++;
5455}
#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 5461 of file numeric.c.

5462{
5463 if (state->calcSumX2)
5465
5466 int128_sub_int64(&state->sumX, newval);
5467 state->N--;
5468}
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 4786 of file numeric.c.

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

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

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

7495{
7496 Numeric res;
7497
7498 res = (Numeric) palloc(VARSIZE(num));
7499 memcpy(res, num, VARSIZE(num));
7500 return res;
7501}
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 10541 of file numeric.c.

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

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

4617{
4619 Numeric res;
4620 NumericVar result;
4621 char buf[FLT_DIG + 100];
4622 const char *endptr;
4623
4624 if (isnan(val))
4626
4627 if (isinf(val))
4628 {
4629 if (val < 0)
4631 else
4633 }
4634
4635 snprintf(buf, sizeof(buf), "%.*g", FLT_DIG, val);
4636
4637 init_var(&result);
4638
4639 /* Assume we need not worry about leading/trailing spaces */
4640 (void) set_var_from_str(buf, buf, &result, &endptr, NULL);
4641
4642 res = make_result(&result);
4643
4644 free_var(&result);
4645
4646 PG_RETURN_NUMERIC(res);
4647}
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:6743
static Numeric make_result(const NumericVar *var)
Definition: numeric.c:7606
static const NumericVar const_nan
Definition: numeric.c:451
float float4
Definition: c.h:637
#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 JsonItemFromDatum().

◆ float8_numeric()

Datum float8_numeric ( PG_FUNCTION_ARGS  )

Definition at line 4522 of file numeric.c.

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

◆ floor_var()

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

Definition at line 9839 of file numeric.c.

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

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

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

1819{
1820 Node *rawreq = (Node *) PG_GETARG_POINTER(0);
1821 Node *ret = NULL;
1822
1823 if (IsA(rawreq, SupportRequestRows))
1824 {
1825 /* Try to estimate the number of rows returned */
1826 SupportRequestRows *req = (SupportRequestRows *) rawreq;
1827
1828 if (is_funcclause(req->node)) /* be paranoid */
1829 {
1830 List *args = ((FuncExpr *) req->node)->args;
1831 Node *arg1,
1832 *arg2,
1833 *arg3;
1834
1835 /* We can use estimated argument values here */
1838 if (list_length(args) >= 3)
1840 else
1841 arg3 = NULL;
1842
1843 /*
1844 * If any argument is constant NULL, we can safely assume that
1845 * zero rows are returned. Otherwise, if they're all non-NULL
1846 * constants, we can calculate the number of rows that will be
1847 * returned.
1848 */
1849 if ((IsA(arg1, Const) &&
1850 ((Const *) arg1)->constisnull) ||
1851 (IsA(arg2, Const) &&
1852 ((Const *) arg2)->constisnull) ||
1853 (arg3 != NULL && IsA(arg3, Const) &&
1854 ((Const *) arg3)->constisnull))
1855 {
1856 req->rows = 0;
1857 ret = (Node *) req;
1858 }
1859 else if (IsA(arg1, Const) &&
1860 IsA(arg2, Const) &&
1861 (arg3 == NULL || IsA(arg3, Const)))
1862 {
1863 Numeric start_num;
1864 Numeric stop_num;
1865 NumericVar step = const_one;
1866
1867 /*
1868 * If any argument is NaN or infinity, generate_series() will
1869 * error out, so we needn't produce an estimate.
1870 */
1871 start_num = DatumGetNumeric(((Const *) arg1)->constvalue);
1872 stop_num = DatumGetNumeric(((Const *) arg2)->constvalue);
1873
1874 if (NUMERIC_IS_SPECIAL(start_num) ||
1875 NUMERIC_IS_SPECIAL(stop_num))
1876 PG_RETURN_POINTER(NULL);
1877
1878 if (arg3)
1879 {
1880 Numeric step_num;
1881
1882 step_num = DatumGetNumeric(((Const *) arg3)->constvalue);
1883
1884 if (NUMERIC_IS_SPECIAL(step_num))
1885 PG_RETURN_POINTER(NULL);
1886
1887 init_var_from_num(step_num, &step);
1888 }
1889
1890 /*
1891 * The number of rows that will be returned is given by
1892 * floor((stop - start) / step) + 1, if the sign of step
1893 * matches the sign of stop - start. Otherwise, no rows will
1894 * be returned.
1895 */
1896 if (cmp_var(&step, &const_zero) != 0)
1897 {
1899 NumericVar stop;
1900 NumericVar res;
1901
1902 init_var_from_num(start_num, &start);
1903 init_var_from_num(stop_num, &stop);
1904
1905 init_var(&res);
1906 sub_var(&stop, &start, &res);
1907
1908 if (step.sign != res.sign)
1909 {
1910 /* no rows will be returned */
1911 req->rows = 0;
1912 ret = (Node *) req;
1913 }
1914 else
1915 {
1916 if (arg3)
1917 div_var(&res, &step, &res, 0, false, false);
1918 else
1919 trunc_var(&res, 0); /* step = 1 */
1920
1921 req->rows = numericvar_to_double_no_overflow(&res) + 1;
1922 ret = (Node *) req;
1923 }
1924
1925 free_var(&res);
1926 }
1927 }
1928 }
1929 }
1930
1931 PG_RETURN_POINTER(ret);
1932}
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 */
1764
1765 /*
1766 * Use fctx to keep state from call to call. Seed current with the
1767 * original start value. We must copy the start_num and stop_num
1768 * values rather than pointing to them, since we may have detoasted
1769 * them in the per-call context.
1770 */
1771 init_var(&fctx->current);
1772 init_var(&fctx->stop);
1773 init_var(&fctx->step);
1774
1775 set_var_from_num(start_num, &fctx->current);
1776 set_var_from_num(stop_num, &fctx->stop);
1777 set_var_from_var(&steploc, &fctx->step);
1778
1779 funcctx->user_fctx = fctx;
1780 MemoryContextSwitchTo(oldcontext);
1781 }
1782
1783 /* stuff done on every call of the function */
1784 funcctx = SRF_PERCALL_SETUP();
1785
1786 /*
1787 * Get the saved state and use current state as the result of this
1788 * iteration.
1789 */
1790 fctx = funcctx->user_fctx;
1791
1792 if ((fctx->step.sign == NUMERIC_POS &&
1793 cmp_var(&fctx->current, &fctx->stop) <= 0) ||
1794 (fctx->step.sign == NUMERIC_NEG &&
1795 cmp_var(&fctx->current, &fctx->stop) >= 0))
1796 {
1797 Numeric result = make_result(&fctx->current);
1798
1799 /* switch to memory context appropriate for iteration calculation */
1800 oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
1801
1802 /* increment current in preparation for next iteration */
1803 add_var(&fctx->current, &fctx->step, &fctx->current);
1804 MemoryContextSwitchTo(oldcontext);
1805
1806 /* do when there is more left to send */
1807 SRF_RETURN_NEXT(funcctx, NumericGetDatum(result));
1808 }
1809 else
1810 /* do when there is no more left */
1811 SRF_RETURN_DONE(funcctx);
1812}
static void set_var_from_num(Numeric num, NumericVar *dest)
Definition: numeric.c:7151
#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(), 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 4113 of file numeric.c.

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

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

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

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

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

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

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

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

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

5570{
5573}
#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 7936 of file numeric.c.

7937{
7938 int sign;
7939 NumericDigit *ptr;
7940 int ndigits;
7941 int32 dig;
7942
7943 /* int128 can require at most 39 decimal digits; add one for safety */
7944 alloc_var(var, 40 / DEC_DIGITS);
7945 sign = int128_sign(val);
7946 var->sign = sign < 0 ? NUMERIC_NEG : NUMERIC_POS;
7947 var->dscale = 0;
7948 if (sign == 0)
7949 {
7950 var->ndigits = 0;
7951 var->weight = 0;
7952 return;
7953 }
7954 ptr = var->digits + var->ndigits;
7955 ndigits = 0;
7956 do
7957 {
7958 ptr--;
7959 ndigits++;
7961 *ptr = (NumericDigit) abs(dig);
7962 } while (!int128_is_zero(val));
7963 var->digits = ptr;
7964 var->ndigits = ndigits;
7965 var->weight = ndigits - 1;
7966}
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 5471 of file numeric.c.

5472{
5474
5476
5477 /* Create the state data on the first call */
5478 if (state == NULL)
5479 state = makeInt128AggState(fcinfo, true);
5480
5481 if (!PG_ARGISNULL(1))
5483
5485}
static Int128AggState * makeInt128AggState(FunctionCallInfo fcinfo, bool calcSumX2)
Definition: numeric.c:5410
static void do_int128_accum(Int128AggState *state, int64 newval)
Definition: numeric.c:5448
#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 5797 of file numeric.c.

5798{
5800
5802
5803 /* Should not get here with no state */
5804 if (state == NULL)
5805 elog(ERROR, "int2_accum_inv called with NULL state");
5806
5807 if (!PG_ARGISNULL(1))
5809
5811}
static void do_int128_discard(Int128AggState *state, int64 newval)
Definition: numeric.c:5461
#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 6388 of file numeric.c.

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

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

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

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

4474{
4476
4478}
Numeric int64_to_numeric(int64 val)
Definition: numeric.c:4260

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

6282{
6283 int64 oldsum;
6284 int64 newval;
6285
6286 if (PG_ARGISNULL(0))
6287 {
6288 /* No non-null input seen so far... */
6289 if (PG_ARGISNULL(1))
6290 PG_RETURN_NULL(); /* still no non-null */
6291 /* This is the first non-null input. */
6294 }
6295
6296 oldsum = PG_GETARG_INT64(0);
6297
6298 /* Leave sum unchanged if new input is null. */
6299 if (PG_ARGISNULL(1))
6300 PG_RETURN_INT64(oldsum);
6301
6302 /* OK to do the addition. */
6303 newval = oldsum + (int64) PG_GETARG_INT16(1);
6304
6306}
#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 6558 of file numeric.c.

6559{
6560 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
6561 Int8TransTypeData *transdata;
6562
6563 if (ARR_HASNULL(transarray) ||
6564 ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
6565 elog(ERROR, "expected 2-element int8 array");
6566 transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
6567
6568 /* SQL defines SUM of no values to be NULL */
6569 if (transdata->count == 0)
6571
6573}
#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 5488 of file numeric.c.

5489{
5491
5493
5494 /* Create the state data on the first call */
5495 if (state == NULL)
5496 state = makeInt128AggState(fcinfo, true);
5497
5498 if (!PG_ARGISNULL(1))
5500
5502}
#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 5814 of file numeric.c.

5815{
5817
5819
5820 /* Should not get here with no state */
5821 if (state == NULL)
5822 elog(ERROR, "int4_accum_inv called with NULL state");
5823
5824 if (!PG_ARGISNULL(1))
5826
5828}

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

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

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

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

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

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

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

4355{
4357
4359}

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

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

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

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

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

5506{
5508
5510
5511 /* Create the state data on the first call */
5512 if (state == NULL)
5513 state = makeNumericAggState(fcinfo, true);
5514
5515 if (!PG_ARGISNULL(1))
5517
5519}
static NumericAggState * makeNumericAggState(FunctionCallInfo fcinfo, bool calcSumX2)
Definition: numeric.c:4746
static void do_numeric_accum(NumericAggState *state, Numeric newval)
Definition: numeric.c:4786

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

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

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

6532{
6533 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
6534 Int8TransTypeData *transdata;
6535 Datum countd,
6536 sumd;
6537
6538 if (ARR_HASNULL(transarray) ||
6539 ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
6540 elog(ERROR, "expected 2-element int8 array");
6541 transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
6542
6543 /* SQL defines AVG of no values to be NULL */
6544 if (transdata->count == 0)
6546
6547 countd = NumericGetDatum(int64_to_numeric(transdata->count));
6548 sumd = NumericGetDatum(int64_to_numeric(transdata->sum));
6549
6551}
Datum numeric_div(PG_FUNCTION_ARGS)
Definition: numeric.c:3135
#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 5665 of file numeric.c.

5666{
5668
5670
5671 /* Create the state data on the first call */
5672 if (state == NULL)
5673 state = makeInt128AggState(fcinfo, false);
5674
5675 if (!PG_ARGISNULL(1))
5677
5679}

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

5853{
5855
5857
5858 /* Should not get here with no state */
5859 if (state == NULL)
5860 elog(ERROR, "int8_avg_accum_inv called with NULL state");
5861
5862 if (!PG_ARGISNULL(1))
5864
5866}

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

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

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

5762{
5763 bytea *sstate;
5764 Int128AggState *result;
5766
5767 if (!AggCheckCallContext(fcinfo, NULL))
5768 elog(ERROR, "aggregate function called in non-aggregate context");
5769
5770 sstate = PG_GETARG_BYTEA_PP(0);
5771
5772 /*
5773 * Initialize a StringInfo so that we can "receive" it using the standard
5774 * recv-function infrastructure.
5775 */
5777 VARSIZE_ANY_EXHDR(sstate));
5778
5779 result = makeInt128AggStateCurrentContext(false);
5780
5781 /* N */
5782 result->N = pq_getmsgint64(&buf);
5783
5784 /* sumX */
5785 result->sumX = int128_deserialize(&buf);
5786
5787 pq_getmsgend(&buf);
5788
5789 PG_RETURN_POINTER(result);
5790}
static INT128 int128_deserialize(StringInfo buf)
Definition: numeric.c:5579
static Int128AggState * makeInt128AggStateCurrentContext(bool calcSumX2)
Definition: numeric.c:5434
#define PG_GETARG_BYTEA_PP(n)
Definition: fmgr.h:308
void pq_getmsgend(StringInfo msg)
Definition: pqformat.c:635
static void initReadOnlyStringInfo(StringInfo str, char *data, int len)
Definition: stringinfo.h:157
Definition: c.h:695
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 5730 of file numeric.c.

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

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

4425{
4427
4429}

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

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

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

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

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

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

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

5411{
5413 MemoryContext agg_context;
5414 MemoryContext old_context;
5415
5416 if (!AggCheckCallContext(fcinfo, &agg_context))
5417 elog(ERROR, "aggregate function called in non-aggregate context");
5418
5419 old_context = MemoryContextSwitchTo(agg_context);
5420
5422 state->calcSumX2 = calcSumX2;
5423
5424 MemoryContextSwitchTo(old_context);
5425
5426 return state;
5427}

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

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

5435{
5437
5439 state->calcSumX2 = calcSumX2;
5440
5441 return state;
5442}

References palloc0().

Referenced by int8_avg_deserialize(), and numeric_poly_deserialize().

◆ makeNumericAggState()

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

Definition at line 4746 of file numeric.c.

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

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

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

◆ makeNumericAggStateCurrentContext()

static NumericAggState * makeNumericAggStateCurrentContext ( bool  calcSumX2)
static

Definition at line 4771 of file numeric.c.

4772{
4774
4776 state->calcSumX2 = calcSumX2;
4777 state->agg_context = CurrentMemoryContext;
4778
4779 return state;
4780}
MemoryContext CurrentMemoryContext
Definition: mcxt.c:160

References CurrentMemoryContext, and palloc0().

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

◆ mod_var()

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

Definition at line 9716 of file numeric.c.

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

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

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

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

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

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

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

Referenced by numeric_sortsupport().

◆ numeric_abbrev_convert()

static Datum numeric_abbrev_convert ( Datum  original_datum,
SortSupport  ssup 
)
static

Definition at line 2150 of file numeric.c.

2151{
2152 NumericSortSupport *nss = ssup->ssup_extra;
2153 void *original_varatt = PG_DETOAST_DATUM_PACKED(original_datum);
2154 Numeric value;
2155 Datum result;
2156
2157 nss->input_count += 1;
2158
2159 /*
2160 * This is to handle packed datums without needing a palloc/pfree cycle;
2161 * we keep and reuse a buffer large enough to handle any short datum.
2162 */
2163 if (VARATT_IS_SHORT(original_varatt))
2164 {
2165 void *buf = nss->buf;
2166 Size sz = VARSIZE_SHORT(original_varatt) - VARHDRSZ_SHORT;
2167
2169
2170 SET_VARSIZE(buf, VARHDRSZ + sz);
2171 memcpy(VARDATA(buf), VARDATA_SHORT(original_varatt), sz);
2172
2173 value = (Numeric) buf;
2174 }
2175 else
2176 value = (Numeric) original_varatt;
2177
2179 {
2181 result = NUMERIC_ABBREV_PINF;
2182 else if (NUMERIC_IS_NINF(value))
2183 result = NUMERIC_ABBREV_NINF;
2184 else
2185 result = NUMERIC_ABBREV_NAN;
2186 }
2187 else
2188 {
2189 NumericVar var;
2190
2191 init_var_from_num(value, &var);
2192
2193 result = numeric_abbrev_convert_var(&var, nss);
2194 }
2195
2196 /* should happen only for external/compressed toasts */
2197 if (original_varatt != DatumGetPointer(original_datum))
2198 pfree(original_varatt);
2199
2200 return result;
2201}
static Datum numeric_abbrev_convert_var(const NumericVar *var, NumericSortSupport *nss)
Definition: numeric.c:2360
#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 2360 of file numeric.c.

2361{
2362 int ndigits = var->ndigits;
2363 int weight = var->weight;
2364 int64 result;
2365
2366 if (ndigits == 0 || weight < -44)
2367 {
2368 result = 0;
2369 }
2370 else if (weight > 83)
2371 {
2372 result = PG_INT64_MAX;
2373 }
2374 else
2375 {
2376 result = ((int64) (weight + 44) << 56);
2377
2378 switch (ndigits)
2379 {
2380 default:
2381 result |= ((int64) var->digits[3]);
2382 /* FALLTHROUGH */
2383 case 3:
2384 result |= ((int64) var->digits[2]) << 14;
2385 /* FALLTHROUGH */
2386 case 2:
2387 result |= ((int64) var->digits[1]) << 28;
2388 /* FALLTHROUGH */
2389 case 1:
2390 result |= ((int64) var->digits[0]) << 42;
2391 break;
2392 }
2393 }
2394
2395 /* the abbrev is negated relative to the original */
2396 if (var->sign == NUMERIC_POS)
2397 result = -result;
2398
2399 if (nss->estimating)
2400 {
2401 uint32 tmp = ((uint32) result
2402 ^ (uint32) ((uint64) result >> 32));
2403
2405 }
2406
2407 return NumericAbbrevGetDatum(result);
2408}
#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 4949 of file numeric.c.

4950{
4952
4954
4955 /* Create the state data on the first call */
4956 if (state == NULL)
4957 state = makeNumericAggState(fcinfo, true);
4958
4959 if (!PG_ARGISNULL(1))
4961
4963}

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

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

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

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

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

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

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

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

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

5042{
5044
5046
5047 /* Create the state data on the first call */
5048 if (state == NULL)
5049 state = makeNumericAggState(fcinfo, false);
5050
5051 if (!PG_ARGISNULL(1))
5053
5055}

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

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

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

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

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

◆ numeric_avg_serialize()

Datum numeric_avg_serialize ( PG_FUNCTION_ARGS  )

Definition at line 5133 of file numeric.c.

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

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

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

2302{
2303 /*
2304 * NOTE WELL: this is intentionally backwards, because the abbreviation is
2305 * negated relative to the original value, to handle NaN/infinity cases.
2306 */
2308 return 1;
2310 return -1;
2311 return 0;
2312}
#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 4969 of file numeric.c.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Referenced by numeric_sortsupport().

◆ numeric_float4()

Datum numeric_float4 ( PG_FUNCTION_ARGS  )

Definition at line 4651 of file numeric.c.

4652{
4653 Numeric num = PG_GETARG_NUMERIC(0);
4654 char *tmp;
4655 Datum result;
4656
4657 if (NUMERIC_IS_SPECIAL(num))
4658 {
4659 if (NUMERIC_IS_PINF(num))
4661 else if (NUMERIC_IS_NINF(num))
4663 else
4665 }
4666
4668 NumericGetDatum(num)));
4669
4671
4672 pfree(tmp);
4673
4674 PG_RETURN_DATUM(result);
4675}
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 4557 of file numeric.c.

4558{
4559 Numeric num = PG_GETARG_NUMERIC(0);
4560 char *tmp;
4561 Datum result;
4562
4563 if (NUMERIC_IS_SPECIAL(num))
4564 {
4565 if (NUMERIC_IS_PINF(num))
4567 else if (NUMERIC_IS_NINF(num))
4569 else
4571 }
4572
4574 NumericGetDatum(num)));
4575
4577
4578 pfree(tmp);
4579
4580 PG_RETURN_DATUM(result);
4581}
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 4590 of file numeric.c.

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

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

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

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

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

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

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

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

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:6973
#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 3414 of file numeric.c.

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

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

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

4395{
4396 Numeric num = PG_GETARG_NUMERIC(0);
4397
4399}
int32 numeric_int4_safe(Numeric num, Node *escontext)
Definition: numeric.c:4365

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

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

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

4465{
4466 Numeric num = PG_GETARG_NUMERIC(0);
4467
4469}
int64 numeric_int8_safe(Numeric num, Node *escontext)
Definition: numeric.c:4435

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

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

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

Definition at line 834 of file numeric.c.

835{
836 return NUMERIC_IS_NAN(num);
837}

References NUMERIC_IS_NAN.

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

◆ numeric_larger()

Datum numeric_larger ( PG_FUNCTION_ARGS  )

Definition at line 3469 of file numeric.c.

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

References cmp_numerics(), PG_GETARG_NUMERIC, and PG_RETURN_NUMERIC.

◆ numeric_lcm()

Datum numeric_lcm ( PG_FUNCTION_ARGS  )

Definition at line 3541 of file numeric.c.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

6245{
6247 Numeric res;
6248 bool is_null;
6249
6251
6252 res = numeric_poly_stddev_internal(state, false, false, &is_null);
6253
6254 if (is_null)
6256 else
6257 PG_RETURN_NUMERIC(res);
6258}
static Numeric numeric_poly_stddev_internal(Int128AggState *state, bool variance, bool sample, bool *is_null)
Definition: numeric.c:6149

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

6211{
6213 Numeric res;
6214 bool is_null;
6215
6217
6218 res = numeric_poly_stddev_internal(state, false, true, &is_null);
6219
6220 if (is_null)
6222 else
6223 PG_RETURN_NUMERIC(res);
6224}

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

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

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

6228{
6230 Numeric res;
6231 bool is_null;
6232
6234
6235 res = numeric_poly_stddev_internal(state, true, false, &is_null);
6236
6237 if (is_null)
6239 else
6240 PG_RETURN_NUMERIC(res);
6241}

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

6194{
6196 Numeric res;
6197 bool is_null;
6198
6200
6201 res = numeric_poly_stddev_internal(state, true, true, &is_null);
6202
6203 if (is_null)
6205 else
6206 PG_RETURN_NUMERIC(res);
6207}

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

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

4100{
4101 Numeric num = PG_GETARG_NUMERIC(0);
4102
4103 if (NUMERIC_IS_SPECIAL(num))
4105
4107}

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

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

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

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

References cmp_numerics(), PG_GETARG_NUMERIC, and PG_RETURN_NUMERIC.

◆ numeric_sortsupport()

Datum numeric_sortsupport ( PG_FUNCTION_ARGS  )

Definition at line 2109 of file numeric.c.

2110{
2112
2114
2115 if (ssup->abbreviate)
2116 {
2117 NumericSortSupport *nss;
2118 MemoryContext oldcontext = MemoryContextSwitchTo(ssup->ssup_cxt);
2119
2120 nss = palloc(sizeof(NumericSortSupport));
2121
2122 /*
2123 * palloc a buffer for handling unaligned packed values in addition to
2124 * the support struct
2125 */
2126 nss->buf = palloc(VARATT_SHORT_MAX + VARHDRSZ + 1);
2127
2128 nss->input_count = 0;
2129 nss->estimating = true;
2130 initHyperLogLog(&nss->abbr_card, 10);
2131
2132 ssup->ssup_extra = nss;
2133
2134 ssup->abbrev_full_comparator = ssup->comparator;
2138
2139 MemoryContextSwitchTo(oldcontext);
2140 }
2141
2143}
static bool numeric_abbrev_abort(int memtupcount, SortSupport ssup)
Definition: numeric.c:2212
static Datum numeric_abbrev_convert(Datum original_datum, SortSupport ssup)
Definition: numeric.c:2150
static int numeric_fast_cmp(Datum x, Datum y, SortSupport ssup)
Definition: numeric.c:2279
static int numeric_cmp_abbrev(Datum x, Datum y, SortSupport ssup)
Definition: numeric.c:2301
#define PG_RETURN_VOID()
Definition: fmgr.h:349
void initHyperLogLog(hyperLogLogState *cState, uint8 bwidth)
Definition: hyperloglog.c:66
struct SortSupportData * SortSupport
Definition: sortsupport.h:58
int(* comparator)(Datum x, Datum y, SortSupport ssup)
Definition: sortsupport.h:106
Datum(* abbrev_converter)(Datum original, SortSupport ssup)
Definition: sortsupport.h:172
MemoryContext ssup_cxt
Definition: sortsupport.h:66
int(* abbrev_full_comparator)(Datum x, Datum y, SortSupport ssup)
Definition: sortsupport.h:191
bool(* abbrev_abort)(int memtupcount, SortSupport ssup)
Definition: sortsupport.h:182

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

◆ numeric_sqrt()

Datum numeric_sqrt ( PG_FUNCTION_ARGS  )

Definition at line 3653 of file numeric.c.

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

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

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

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

6133{
6135 Numeric res;
6136 bool is_null;
6137
6139
6140 res = numeric_stddev_internal(state, false, false, &is_null);
6141
6142 if (is_null)
6144 else
6145 PG_RETURN_NUMERIC(res);
6146}

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

6099{
6101 Numeric res;
6102 bool is_null;
6103
6105
6106 res = numeric_stddev_internal(state, false, true, &is_null);
6107
6108 if (is_null)
6110 else
6111 PG_RETURN_NUMERIC(res);
6112}

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

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

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

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

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

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

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

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

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.

Referenced by jsonb_agg_transfn_worker(), and jsonb_object_agg_transfn_worker().

◆ numeric_var_pop()

Datum numeric_var_pop ( PG_FUNCTION_ARGS  )

Definition at line 6115 of file numeric.c.

6116{
6118 Numeric res;
6119 bool is_null;
6120
6122
6123 res = numeric_stddev_internal(state, true, false, &is_null);
6124
6125 if (is_null)
6127 else
6128 PG_RETURN_NUMERIC(res);
6129}

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

6082{
6084 Numeric res;
6085 bool is_null;
6086
6088
6089 res = numeric_stddev_internal(state, true, true, &is_null);
6090
6091 if (is_null)
6093 else
6094 PG_RETURN_NUMERIC(res);
6095}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Referenced by set_var_from_non_decimal_integer_str().

◆ zero_var()

static void zero_var ( NumericVar var)
static

Definition at line 6716 of file numeric.c.

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

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