PostgreSQL Source Code git master
Loading...
Searching...
No Matches
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 charget_str_from_var (const NumericVar *var)
 
static charget_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)
 
charnumeric_out_sci (Numeric num, int scale)
 
charnumeric_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)
 
int32 make_numeric_typmod_safe (int32 precision, int32 scale, Node *escontext)
 
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) \
} while (0)
static char buf[DEFAULT_XLOG_SEG_SIZE]
static int fb(int x)

Definition at line 480 of file numeric.c.

481 { \
482 if ((buf) != NULL) \
483 pfree(buf); \
484 } while (0)

◆ 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 4773 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.

489 : (num)->choice.n_long.n_data)

◆ 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.

249 : ((n)->choice.n_long.n_sign_dscale & NUMERIC_DSCALE_MASK))

◆ 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:840
int16_t int16
Definition c.h:678
uint16_t uint16
Definition c.h:682

Definition at line 187 of file numeric.c.

189 : sizeof(int16)))

◆ 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) ? \
#define NUMERIC_IS_SPECIAL(n)
Definition numeric.c:176
#define NUMERIC_NEG
Definition numeric.c:170
#define NUMERIC_EXT_FLAGBITS(n)
Definition numeric.c:206
#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.

252 : 0) \
253 | ((n)->choice.n_short.n_header & NUMERIC_SHORT_WEIGHT_MASK)) \
254 : ((n)->choice.n_long.n_weight))

◆ 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

Function Documentation

◆ accum_sum_add()

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

Definition at line 11881 of file numeric.c.

11882{
11884 int i,
11885 val_i;
11886 int val_ndigits;
11888
11889 /*
11890 * If we have accumulated too many values since the last carry
11891 * propagation, do it now, to avoid overflowing. (We could allow more
11892 * than NBASE - 1, if we reserved two extra digits, rather than one, for
11893 * carry propagation. But even with NBASE - 1, this needs to be done so
11894 * seldom, that the performance difference is negligible.)
11895 */
11896 if (accum->num_uncarried == NBASE - 1)
11897 accum_sum_carry(accum);
11898
11899 /*
11900 * Adjust the weight or scale of the old value, so that it can accommodate
11901 * the new value.
11902 */
11903 accum_sum_rescale(accum, val);
11904
11905 /* */
11906 if (val->sign == NUMERIC_POS)
11907 accum_digits = accum->pos_digits;
11908 else
11909 accum_digits = accum->neg_digits;
11910
11911 /* copy these values into local vars for speed in loop */
11912 val_ndigits = val->ndigits;
11913 val_digits = val->digits;
11914
11915 i = accum->weight - val->weight;
11916 for (val_i = 0; val_i < val_ndigits; val_i++)
11917 {
11919 i++;
11920 }
11921
11922 accum->num_uncarried++;
11923}
static void accum_sum_carry(NumericSumAccum *accum)
Definition numeric.c:11929
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:12002
int32_t int32
Definition c.h:679
long val
Definition informix.c:689
int i
Definition isn.c:77
int32 * pos_digits
Definition numeric.c:388
int32 * neg_digits
Definition numeric.c:389

References accum_sum_carry(), accum_sum_rescale(), fb(), 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 11929 of file numeric.c.

11930{
11931 int i;
11932 int ndigits;
11933 int32 *dig;
11934 int32 carry;
11935 int32 newdig = 0;
11936
11937 /*
11938 * If no new values have been added since last carry propagation, nothing
11939 * to do.
11940 */
11941 if (accum->num_uncarried == 0)
11942 return;
11943
11944 /*
11945 * We maintain that the weight of the accumulator is always one larger
11946 * than needed to hold the current value, before carrying, to make sure
11947 * there is enough space for the possible extra digit when carry is
11948 * propagated. We cannot expand the buffer here, unless we require
11949 * callers of accum_sum_final() to switch to the right memory context.
11950 */
11951 Assert(accum->pos_digits[0] == 0 && accum->neg_digits[0] == 0);
11952
11953 ndigits = accum->ndigits;
11954
11955 /* Propagate carry in the positive sum */
11956 dig = accum->pos_digits;
11957 carry = 0;
11958 for (i = ndigits - 1; i >= 0; i--)
11959 {
11960 newdig = dig[i] + carry;
11961 if (newdig >= NBASE)
11962 {
11963 carry = newdig / NBASE;
11964 newdig -= carry * NBASE;
11965 }
11966 else
11967 carry = 0;
11968 dig[i] = newdig;
11969 }
11970 /* Did we use up the digit reserved for carry propagation? */
11971 if (newdig > 0)
11972 accum->have_carry_space = false;
11973
11974 /* And the same for the negative sum */
11975 dig = accum->neg_digits;
11976 carry = 0;
11977 for (i = ndigits - 1; i >= 0; i--)
11978 {
11979 newdig = dig[i] + carry;
11980 if (newdig >= NBASE)
11981 {
11982 carry = newdig / NBASE;
11983 newdig -= carry * NBASE;
11984 }
11985 else
11986 carry = 0;
11987 dig[i] = newdig;
11988 }
11989 if (newdig > 0)
11990 accum->have_carry_space = false;
11991
11992 accum->num_uncarried = 0;
11993}
#define Assert(condition)
Definition c.h:1002
bool have_carry_space
Definition numeric.c:387

References Assert, fb(), 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 12159 of file numeric.c.

12160{
12162
12163 init_var(&tmp_var);
12164
12166 accum_sum_add(accum, &tmp_var);
12167
12168 free_var(&tmp_var);
12169}
static void accum_sum_final(NumericSumAccum *accum, NumericVar *result)
Definition numeric.c:12091
static void free_var(NumericVar *var)
Definition numeric.c:6735
static void accum_sum_add(NumericSumAccum *accum, const NumericVar *val)
Definition numeric.c:11881
#define init_var(v)
Definition numeric.c:486

References accum_sum_add(), accum_sum_final(), fb(), 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 12142 of file numeric.c.

12143{
12144 dst->pos_digits = palloc(src->ndigits * sizeof(int32));
12145 dst->neg_digits = palloc(src->ndigits * sizeof(int32));
12146
12147 memcpy(dst->pos_digits, src->pos_digits, src->ndigits * sizeof(int32));
12148 memcpy(dst->neg_digits, src->neg_digits, src->ndigits * sizeof(int32));
12149 dst->num_uncarried = src->num_uncarried;
12150 dst->ndigits = src->ndigits;
12151 dst->weight = src->weight;
12152 dst->dscale = src->dscale;
12153}
memcpy(sums, checksumBaseOffsets, sizeof(checksumBaseOffsets))
void * palloc(Size size)
Definition mcxt.c:1390

References NumericSumAccum::dscale, fb(), memcpy(), 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 12091 of file numeric.c.

12092{
12093 int i;
12096
12097 if (accum->ndigits == 0)
12098 {
12100 return;
12101 }
12102
12103 /* Perform final carry */
12104 accum_sum_carry(accum);
12105
12106 /* Create NumericVars representing the positive and negative sums */
12107 init_var(&pos_var);
12108 init_var(&neg_var);
12109
12110 pos_var.ndigits = neg_var.ndigits = accum->ndigits;
12111 pos_var.weight = neg_var.weight = accum->weight;
12112 pos_var.dscale = neg_var.dscale = accum->dscale;
12113 pos_var.sign = NUMERIC_POS;
12114 neg_var.sign = NUMERIC_NEG;
12115
12116 pos_var.buf = pos_var.digits = digitbuf_alloc(accum->ndigits);
12117 neg_var.buf = neg_var.digits = digitbuf_alloc(accum->ndigits);
12118
12119 for (i = 0; i < accum->ndigits; i++)
12120 {
12121 Assert(accum->pos_digits[i] < NBASE);
12122 pos_var.digits[i] = (int16) accum->pos_digits[i];
12123
12124 Assert(accum->neg_digits[i] < NBASE);
12125 neg_var.digits[i] = (int16) accum->neg_digits[i];
12126 }
12127
12128 /* And add them together */
12130
12131 /* Remove leading/trailing zeroes */
12133}
static void add_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition numeric.c:8097
static const NumericVar const_zero
Definition numeric.c:417
static void set_var_from_var(const NumericVar *value, NumericVar *dest)
Definition numeric.c:7234
static void strip_var(NumericVar *var)
Definition numeric.c:11824
uint32 result
#define digitbuf_alloc(size)
Definition numeric.c:18

References accum_sum_carry(), add_var(), Assert, const_zero, digitbuf_alloc, NumericSumAccum::dscale, fb(), i, init_var, NBASE, NumericSumAccum::ndigits, NumericSumAccum::neg_digits, NUMERIC_NEG, NUMERIC_POS, NumericSumAccum::pos_digits, result, set_var_from_var(), strip_var(), 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 12002 of file numeric.c.

12003{
12004 int old_weight = accum->weight;
12005 int old_ndigits = accum->ndigits;
12006 int accum_ndigits;
12007 int accum_weight;
12008 int accum_rscale;
12009 int val_rscale;
12010
12013
12014 /*
12015 * Does the new value have a larger weight? If so, enlarge the buffers,
12016 * and shift the existing value to the new weight, by adding leading
12017 * zeros.
12018 *
12019 * We enforce that the accumulator always has a weight one larger than
12020 * needed for the inputs, so that we have space for an extra digit at the
12021 * final carry-propagation phase, if necessary.
12022 */
12023 if (val->weight >= accum_weight)
12024 {
12025 accum_weight = val->weight + 1;
12027 }
12028
12029 /*
12030 * Even though the new value is small, we might've used up the space
12031 * reserved for the carry digit in the last call to accum_sum_carry(). If
12032 * so, enlarge to make room for another one.
12033 */
12034 else if (!accum->have_carry_space)
12035 {
12036 accum_weight++;
12037 accum_ndigits++;
12038 }
12039
12040 /* Is the new value wider on the right side? */
12042 val_rscale = val->ndigits - val->weight - 1;
12045
12046 if (accum_ndigits != old_ndigits ||
12048 {
12051 int weightdiff;
12052
12054
12057
12058 if (accum->pos_digits)
12059 {
12061 old_ndigits * sizeof(int32));
12062 pfree(accum->pos_digits);
12063
12065 old_ndigits * sizeof(int32));
12066 pfree(accum->neg_digits);
12067 }
12068
12069 accum->pos_digits = new_pos_digits;
12070 accum->neg_digits = new_neg_digits;
12071
12072 accum->weight = accum_weight;
12073 accum->ndigits = accum_ndigits;
12074
12075 Assert(accum->pos_digits[0] == 0 && accum->neg_digits[0] == 0);
12076 accum->have_carry_space = true;
12077 }
12078
12079 if (val->dscale > accum->dscale)
12080 accum->dscale = val->dscale;
12081}
void pfree(void *pointer)
Definition mcxt.c:1619
void * palloc0(Size size)
Definition mcxt.c:1420

References Assert, NumericSumAccum::dscale, fb(), NumericSumAccum::have_carry_space, memcpy(), 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 11865 of file numeric.c.

11866{
11867 int i;
11868
11869 accum->dscale = 0;
11870 for (i = 0; i < accum->ndigits; i++)
11871 {
11872 accum->pos_digits[i] = 0;
11873 accum->neg_digits[i] = 0;
11874 }
11875}

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

11490{
11493 int res_ndigits;
11494 int res_weight;
11495 int res_rscale,
11496 rscale1,
11497 rscale2;
11498 int res_dscale;
11499 int i,
11500 i1,
11501 i2;
11502 int carry = 0;
11503
11504 /* copy these values into local vars for speed in inner loop */
11505 int var1ndigits = var1->ndigits;
11506 int var2ndigits = var2->ndigits;
11507 NumericDigit *var1digits = var1->digits;
11508 NumericDigit *var2digits = var2->digits;
11509
11510 res_weight = Max(var1->weight, var2->weight) + 1;
11511
11512 res_dscale = Max(var1->dscale, var2->dscale);
11513
11514 /* Note: here we are figuring rscale in base-NBASE digits */
11515 rscale1 = var1->ndigits - var1->weight - 1;
11516 rscale2 = var2->ndigits - var2->weight - 1;
11518
11520 if (res_ndigits <= 0)
11521 res_ndigits = 1;
11522
11524 res_buf[0] = 0; /* spare digit for later rounding */
11525 res_digits = res_buf + 1;
11526
11527 i1 = res_rscale + var1->weight + 1;
11528 i2 = res_rscale + var2->weight + 1;
11529 for (i = res_ndigits - 1; i >= 0; i--)
11530 {
11531 i1--;
11532 i2--;
11533 if (i1 >= 0 && i1 < var1ndigits)
11534 carry += var1digits[i1];
11535 if (i2 >= 0 && i2 < var2ndigits)
11536 carry += var2digits[i2];
11537
11538 if (carry >= NBASE)
11539 {
11540 res_digits[i] = carry - NBASE;
11541 carry = 1;
11542 }
11543 else
11544 {
11545 res_digits[i] = carry;
11546 carry = 0;
11547 }
11548 }
11549
11550 Assert(carry == 0); /* else we failed to allow for carry out */
11551
11552 digitbuf_free(result->buf);
11553 result->ndigits = res_ndigits;
11554 result->buf = res_buf;
11555 result->digits = res_digits;
11556 result->weight = res_weight;
11557 result->dscale = res_dscale;
11558
11559 /* Remove leading/trailing zeroes */
11561}
#define Max(x, y)
Definition c.h:1144
#define digitbuf_free(buf)
Definition numeric.c:19

References Assert, digitbuf_alloc, digitbuf_free, fb(), i, Max, NBASE, result, and strip_var().

Referenced by add_var(), PGTYPESnumeric_add(), PGTYPESnumeric_sub(), and sub_var().

◆ add_var()

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

Definition at line 8097 of file numeric.c.

8098{
8099 /*
8100 * Decide on the signs of the two variables what to do
8101 */
8102 if (var1->sign == NUMERIC_POS)
8103 {
8104 if (var2->sign == NUMERIC_POS)
8105 {
8106 /*
8107 * Both are positive result = +(ABS(var1) + ABS(var2))
8108 */
8110 result->sign = NUMERIC_POS;
8111 }
8112 else
8113 {
8114 /*
8115 * var1 is positive, var2 is negative Must compare absolute values
8116 */
8117 switch (cmp_abs(var1, var2))
8118 {
8119 case 0:
8120 /* ----------
8121 * ABS(var1) == ABS(var2)
8122 * result = ZERO
8123 * ----------
8124 */
8126 result->dscale = Max(var1->dscale, var2->dscale);
8127 break;
8128
8129 case 1:
8130 /* ----------
8131 * ABS(var1) > ABS(var2)
8132 * result = +(ABS(var1) - ABS(var2))
8133 * ----------
8134 */
8136 result->sign = NUMERIC_POS;
8137 break;
8138
8139 case -1:
8140 /* ----------
8141 * ABS(var1) < ABS(var2)
8142 * result = -(ABS(var2) - ABS(var1))
8143 * ----------
8144 */
8146 result->sign = NUMERIC_NEG;
8147 break;
8148 }
8149 }
8150 }
8151 else
8152 {
8153 if (var2->sign == NUMERIC_POS)
8154 {
8155 /* ----------
8156 * var1 is negative, var2 is positive
8157 * Must compare absolute values
8158 * ----------
8159 */
8160 switch (cmp_abs(var1, var2))
8161 {
8162 case 0:
8163 /* ----------
8164 * ABS(var1) == ABS(var2)
8165 * result = ZERO
8166 * ----------
8167 */
8169 result->dscale = Max(var1->dscale, var2->dscale);
8170 break;
8171
8172 case 1:
8173 /* ----------
8174 * ABS(var1) > ABS(var2)
8175 * result = -(ABS(var1) - ABS(var2))
8176 * ----------
8177 */
8179 result->sign = NUMERIC_NEG;
8180 break;
8181
8182 case -1:
8183 /* ----------
8184 * ABS(var1) < ABS(var2)
8185 * result = +(ABS(var2) - ABS(var1))
8186 * ----------
8187 */
8189 result->sign = NUMERIC_POS;
8190 break;
8191 }
8192 }
8193 else
8194 {
8195 /* ----------
8196 * Both are negative
8197 * result = -(ABS(var1) + ABS(var2))
8198 * ----------
8199 */
8201 result->sign = NUMERIC_NEG;
8202 }
8203 }
8204}
static void sub_abs(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition numeric.c:11574
static void add_abs(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition numeric.c:11489
static void zero_var(NumericVar *var)
Definition numeric.c:6751
static int cmp_abs(const NumericVar *var1, const NumericVar *var2)
Definition numeric.c:11411

References add_abs(), cmp_abs(), fb(), Max, NUMERIC_NEG, NUMERIC_POS, result, 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 6719 of file numeric.c.

6720{
6721 digitbuf_free(var->buf);
6722 var->buf = digitbuf_alloc(ndigits + 1);
6723 var->buf[0] = 0; /* spare digit for rounding */
6724 var->digits = var->buf + 1;
6725 var->ndigits = ndigits;
6726}
int ndigits
Definition numeric.c:316
NumericDigit * digits
Definition numeric.c:321
NumericDigit * buf
Definition numeric.c:320

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(), PGTYPESnumeric_copy(), PGTYPESnumeric_from_decimal(), PGTYPESnumeric_from_long(), PGTYPESnumeric_new(), random_var(), set_var_from_num(), set_var_from_str(), set_var_from_str(), and sqrt_var().

◆ apply_typmod()

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

Definition at line 7657 of file numeric.c.

7658{
7659 int precision;
7660 int scale;
7661 int maxdigits;
7662 int ddigits;
7663 int i;
7664
7665 /* Do nothing if we have an invalid typmod */
7666 if (!is_valid_numeric_typmod(typmod))
7667 return true;
7668
7669 precision = numeric_typmod_precision(typmod);
7670 scale = numeric_typmod_scale(typmod);
7671 maxdigits = precision - scale;
7672
7673 /* Round to target scale (and set var->dscale) */
7674 round_var(var, scale);
7675
7676 /* but don't allow var->dscale to be negative */
7677 if (var->dscale < 0)
7678 var->dscale = 0;
7679
7680 /*
7681 * Check for overflow - note we can't do this before rounding, because
7682 * rounding could raise the weight. Also note that the var's weight could
7683 * be inflated by leading zeroes, which will be stripped before storage
7684 * but perhaps might not have been yet. In any case, we must recognize a
7685 * true zero, whose weight doesn't mean anything.
7686 */
7687 ddigits = (var->weight + 1) * DEC_DIGITS;
7688 if (ddigits > maxdigits)
7689 {
7690 /* Determine true weight; and check for all-zero result */
7691 for (i = 0; i < var->ndigits; i++)
7692 {
7693 NumericDigit dig = var->digits[i];
7694
7695 if (dig)
7696 {
7697 /* Adjust for any high-order decimal zero digits */
7698#if DEC_DIGITS == 4
7699 if (dig < 10)
7700 ddigits -= 3;
7701 else if (dig < 100)
7702 ddigits -= 2;
7703 else if (dig < 1000)
7704 ddigits -= 1;
7705#elif DEC_DIGITS == 2
7706 if (dig < 10)
7707 ddigits -= 1;
7708#elif DEC_DIGITS == 1
7709 /* no adjustment */
7710#else
7711#error unsupported NBASE
7712#endif
7713 if (ddigits > maxdigits)
7714 ereturn(escontext, false,
7716 errmsg("numeric field overflow"),
7717 errdetail("A field with precision %d, scale %d must round to an absolute value less than %s%d.",
7718 precision, scale,
7719 /* Display 10^0 as 1 */
7720 maxdigits ? "10^" : "",
7721 maxdigits ? maxdigits : 1
7722 )));
7723 break;
7724 }
7726 }
7727 }
7728
7729 return true;
7730}
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:11656
#define DEC_DIGITS
Definition numeric.c:99
int errcode(int sqlerrcode)
Definition elog.c:875
#define ereturn(context, dummy_value,...)
Definition elog.h:280
int errdetail(const char *fmt,...) pg_attribute_printf(1
int maxdigits
Definition informix.c:690
static char * errmsg
int dscale
Definition numeric.c:319
int weight
Definition numeric.c:317

References DEC_DIGITS, NumericVar::digits, NumericVar::dscale, ereturn, errcode(), errdetail(), errmsg, fb(), 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 7742 of file numeric.c.

7743{
7744 int precision;
7745 int scale;
7746
7747 Assert(NUMERIC_IS_SPECIAL(num)); /* caller error if not */
7748
7749 /*
7750 * NaN is allowed regardless of the typmod; that's rather dubious perhaps,
7751 * but it's a longstanding behavior. Inf is rejected if we have any
7752 * typmod restriction, since an infinity shouldn't be claimed to fit in
7753 * any finite number of digits.
7754 */
7755 if (NUMERIC_IS_NAN(num))
7756 return true;
7757
7758 /* Do nothing if we have a default typmod (-1) */
7759 if (!is_valid_numeric_typmod(typmod))
7760 return true;
7761
7762 precision = numeric_typmod_precision(typmod);
7763 scale = numeric_typmod_scale(typmod);
7764
7765 ereturn(escontext, false,
7767 errmsg("numeric field overflow"),
7768 errdetail("A field with precision %d, scale %d cannot hold an infinite value.",
7769 precision, scale)));
7770}
#define NUMERIC_IS_NAN(n)
Definition numeric.c:207

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

9851{
9852 NumericVar tmp;
9853
9854 init_var(&tmp);
9855 set_var_from_var(var, &tmp);
9856
9857 trunc_var(&tmp, 0);
9858
9859 if (var->sign == NUMERIC_POS && cmp_var(var, &tmp) != 0)
9860 add_var(&tmp, &const_one, &tmp);
9861
9862 set_var_from_var(&tmp, result);
9863 free_var(&tmp);
9864}
static void trunc_var(NumericVar *var, int rscale)
Definition numeric.c:11762
static int cmp_var(const NumericVar *var1, const NumericVar *var2)
Definition numeric.c:8039
static const NumericVar const_one
Definition numeric.c:421

References add_var(), cmp_var(), const_one, free_var(), init_var, NUMERIC_POS, result, 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 11411 of file numeric.c.

11412{
11413 return cmp_abs_common(var1->digits, var1->ndigits, var1->weight,
11414 var2->digits, var2->ndigits, var2->weight);
11415}
static int cmp_abs_common(const NumericDigit *var1digits, int var1ndigits, int var1weight, const NumericDigit *var2digits, int var2ndigits, int var2weight)
Definition numeric.c:11425

References cmp_abs_common(), and fb().

Referenced by add_var(), div_mod_var(), gcd_var(), PGTYPESnumeric_add(), PGTYPESnumeric_cmp(), PGTYPESnumeric_div(), PGTYPESnumeric_sub(), 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 11425 of file numeric.c.

11427{
11428 int i1 = 0;
11429 int i2 = 0;
11430
11431 /* Check any digits before the first common digit */
11432
11433 while (var1weight > var2weight && i1 < var1ndigits)
11434 {
11435 if (var1digits[i1++] != 0)
11436 return 1;
11437 var1weight--;
11438 }
11439 while (var2weight > var1weight && i2 < var2ndigits)
11440 {
11441 if (var2digits[i2++] != 0)
11442 return -1;
11443 var2weight--;
11444 }
11445
11446 /* At this point, either w1 == w2 or we've run out of digits */
11447
11448 if (var1weight == var2weight)
11449 {
11450 while (i1 < var1ndigits && i2 < var2ndigits)
11451 {
11452 int stat = var1digits[i1++] - var2digits[i2++];
11453
11454 if (stat)
11455 {
11456 if (stat > 0)
11457 return 1;
11458 return -1;
11459 }
11460 }
11461 }
11462
11463 /*
11464 * At this point, we've run out of digits on one side or the other; so any
11465 * remaining nonzero digits imply that side is larger
11466 */
11467 while (i1 < var1ndigits)
11468 {
11469 if (var1digits[i1++] != 0)
11470 return 1;
11471 }
11472 while (i2 < var2ndigits)
11473 {
11474 if (var2digits[i2++] != 0)
11475 return -1;
11476 }
11477
11478 return 0;
11479}

References fb().

Referenced by cmp_abs(), and cmp_var_common().

◆ cmp_numerics()

static int cmp_numerics ( Numeric  num1,
Numeric  num2 
)
static

Definition at line 2529 of file numeric.c.

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

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

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

Definition at line 8039 of file numeric.c.

8040{
8041 return cmp_var_common(var1->digits, var1->ndigits,
8042 var1->weight, var1->sign,
8043 var2->digits, var2->ndigits,
8044 var2->weight, var2->sign);
8045}

References cmp_var_common(), and fb().

Referenced by ceil_var(), estimate_ln_dweight(), floor_var(), generate_series_numeric_support(), generate_series_step_numeric(), in_range_numeric_numeric(), ln_var(), numeric_power(), numeric_stddev_internal(), power_var(), random_var(), and sqrt_var().

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

8058{
8059 if (var1ndigits == 0)
8060 {
8061 if (var2ndigits == 0)
8062 return 0;
8063 if (var2sign == NUMERIC_NEG)
8064 return 1;
8065 return -1;
8066 }
8067 if (var2ndigits == 0)
8068 {
8069 if (var1sign == NUMERIC_POS)
8070 return 1;
8071 return -1;
8072 }
8073
8074 if (var1sign == NUMERIC_POS)
8075 {
8076 if (var2sign == NUMERIC_NEG)
8077 return 1;
8080 }
8081
8082 if (var2sign == NUMERIC_POS)
8083 return -1;
8084
8087}

References cmp_abs_common(), fb(), 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 2042 of file numeric.c.

2044{
2048
2051 init_var_from_num(operand, &operand_var);
2052
2053 /*
2054 * Per spec, bound1 is inclusive and bound2 is exclusive, and so we have
2055 * bound1 <= operand < bound2 or bound1 >= operand > bound2. Either way,
2056 * the result is ((operand - bound1) * count) / (bound2 - bound1) + 1,
2057 * where the quotient is computed using floor division (i.e., division to
2058 * zero decimal places with truncation), which guarantees that the result
2059 * is in the range [1, count]. Reversing the bounds doesn't affect the
2060 * computation, because the signs cancel out when dividing.
2061 */
2064
2066 operand_var.dscale + count_var->dscale);
2067 div_var(&operand_var, &bound2_var, result_var, 0, false, true);
2069
2073}
static void sub_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition numeric.c:8214
static void init_var_from_num(Numeric num, NumericVar *dest)
Definition numeric.c:7217
static void mul_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result, int rscale)
Definition numeric.c:8335
static void div_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result, int rscale, bool round, bool exact)
Definition numeric.c:8913

References add_var(), const_one, div_var(), fb(), 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 9780 of file numeric.c.

9782{
9783 NumericVar q;
9784 NumericVar r;
9785
9786 init_var(&q);
9787 init_var(&r);
9788
9789 /*
9790 * Use div_var() with exact = false to get an initial estimate for the
9791 * integer quotient (truncated towards zero). This might be slightly
9792 * inaccurate, but we correct it below.
9793 */
9794 div_var(var1, var2, &q, 0, false, false);
9795
9796 /* Compute initial estimate of remainder using the quotient estimate. */
9797 mul_var(var2, &q, &r, var2->dscale);
9798 sub_var(var1, &r, &r);
9799
9800 /*
9801 * Adjust the results if necessary --- the remainder should have the same
9802 * sign as var1, and its absolute value should be less than the absolute
9803 * value of var2.
9804 */
9805 while (r.ndigits != 0 && r.sign != var1->sign)
9806 {
9807 /* The absolute value of the quotient is too large */
9808 if (var1->sign == var2->sign)
9809 {
9810 sub_var(&q, &const_one, &q);
9811 add_var(&r, var2, &r);
9812 }
9813 else
9814 {
9815 add_var(&q, &const_one, &q);
9816 sub_var(&r, var2, &r);
9817 }
9818 }
9819
9820 while (cmp_abs(&r, var2) >= 0)
9821 {
9822 /* The absolute value of the quotient is too small */
9823 if (var1->sign == var2->sign)
9824 {
9825 add_var(&q, &const_one, &q);
9826 sub_var(&r, var2, &r);
9827 }
9828 else
9829 {
9830 sub_var(&q, &const_one, &q);
9831 add_var(&r, var2, &r);
9832 }
9833 }
9834
9836 set_var_from_var(&r, rem);
9837
9838 free_var(&q);
9839 free_var(&r);
9840}

References add_var(), cmp_abs(), const_one, div_var(), NumericVar::dscale, fb(), 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 8913 of file numeric.c.

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

References alloc_var(), Assert, DEC_DIGITS, DIV_GUARD_DIGITS, div_var_int(), ereport, errcode(), errmsg, ERROR, fb(), i, Max, Min, NBASE, NBASE_SQR, NUMERIC_NEG, NUMERIC_POS, palloc(), pfree(), PG_INT64_MAX, remainder, result, round_var(), strip_var(), trunc_var(), 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 9454 of file numeric.c.

9456{
9458 int var_ndigits = var->ndigits;
9459 int res_sign;
9460 int res_weight;
9461 int res_ndigits;
9465 int i;
9466
9467 /* Guard against division by zero */
9468 if (ival == 0)
9469 ereport(ERROR,
9471 errmsg("division by zero"));
9472
9473 /* Result zero check */
9474 if (var_ndigits == 0)
9475 {
9477 result->dscale = rscale;
9478 return;
9479 }
9480
9481 /*
9482 * Determine the result sign, weight and number of digits to calculate.
9483 * The weight figured here is correct if the emitted quotient has no
9484 * leading zero digits; otherwise strip_var() will fix things up.
9485 */
9486 if (var->sign == NUMERIC_POS)
9487 res_sign = ival > 0 ? NUMERIC_POS : NUMERIC_NEG;
9488 else
9489 res_sign = ival > 0 ? NUMERIC_NEG : NUMERIC_POS;
9490 res_weight = var->weight - ival_weight;
9491 /* The number of accurate result digits we need to produce: */
9492 res_ndigits = res_weight + 1 + (rscale + DEC_DIGITS - 1) / DEC_DIGITS;
9493 /* ... but always at least 1 */
9495 /* If rounding needed, figure one more digit to ensure correct result */
9496 if (round)
9497 res_ndigits++;
9498
9500 res_buf[0] = 0; /* spare digit for later rounding */
9501 res_digits = res_buf + 1;
9502
9503 /*
9504 * Now compute the quotient digits. This is the short division algorithm
9505 * described in Knuth volume 2, section 4.3.1 exercise 16, except that we
9506 * allow the divisor to exceed the internal base.
9507 *
9508 * In this algorithm, the carry from one digit to the next is at most
9509 * divisor - 1. Therefore, while processing the next digit, carry may
9510 * become as large as divisor * NBASE - 1, and so it requires a 64-bit
9511 * integer if this exceeds UINT_MAX.
9512 */
9513 divisor = abs(ival);
9514
9515 if (divisor <= UINT_MAX / NBASE)
9516 {
9517 /* carry cannot overflow 32 bits */
9518 uint32 carry = 0;
9519
9520 for (i = 0; i < res_ndigits; i++)
9521 {
9522 carry = carry * NBASE + (i < var_ndigits ? var_digits[i] : 0);
9524 carry = carry % divisor;
9525 }
9526 }
9527 else
9528 {
9529 /* carry may exceed 32 bits */
9530 uint64 carry = 0;
9531
9532 for (i = 0; i < res_ndigits; i++)
9533 {
9534 carry = carry * NBASE + (i < var_ndigits ? var_digits[i] : 0);
9536 carry = carry % divisor;
9537 }
9538 }
9539
9540 /* Store the quotient in result */
9541 digitbuf_free(result->buf);
9542 result->ndigits = res_ndigits;
9543 result->buf = res_buf;
9544 result->digits = res_digits;
9545 result->weight = res_weight;
9546 result->sign = res_sign;
9547
9548 /* Round or truncate to target rscale (and set result->dscale) */
9549 if (round)
9550 round_var(result, rscale);
9551 else
9552 trunc_var(result, rscale);
9553
9554 /* Strip leading/trailing zeroes */
9556}
uint64_t uint64
Definition c.h:684

References DEC_DIGITS, digitbuf_alloc, digitbuf_free, NumericVar::digits, ereport, errcode(), errmsg, ERROR, fb(), i, Max, NBASE, NumericVar::ndigits, NUMERIC_NEG, NUMERIC_POS, result, 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 5483 of file numeric.c.

5484{
5485 if (state->calcSumX2)
5487
5488 int128_add_int64(&state->sumX, newval);
5489 state->N++;
5490}
#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

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

5497{
5498 if (state->calcSumX2)
5500
5501 int128_sub_int64(&state->sumX, newval);
5502 state->N--;
5503}
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 4821 of file numeric.c.

4822{
4823 NumericVar X;
4824 NumericVar X2;
4826
4827 /* Count NaN/infinity inputs separately from all else */
4829 {
4831 state->pInfcount++;
4832 else if (NUMERIC_IS_NINF(newval))
4833 state->nInfcount++;
4834 else
4835 state->NaNcount++;
4836 return;
4837 }
4838
4839 /* load processed number in short-lived context */
4841
4842 /*
4843 * Track the highest input dscale that we've seen, to support inverse
4844 * transitions (see do_numeric_discard).
4845 */
4846 if (X.dscale > state->maxScale)
4847 {
4848 state->maxScale = X.dscale;
4849 state->maxScaleCount = 1;
4850 }
4851 else if (X.dscale == state->maxScale)
4852 state->maxScaleCount++;
4853
4854 /* if we need X^2, calculate that in short-lived context */
4855 if (state->calcSumX2)
4856 {
4857 init_var(&X2);
4858 mul_var(&X, &X, &X2, X.dscale * 2);
4859 }
4860
4861 /* The rest of this needs to work in the aggregate context */
4862 old_context = MemoryContextSwitchTo(state->agg_context);
4863
4864 state->N++;
4865
4866 /* Accumulate sums */
4867 accum_sum_add(&(state->sumX), &X);
4868
4869 if (state->calcSumX2)
4870 accum_sum_add(&(state->sumX2), &X2);
4871
4873}
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition palloc.h:138

References accum_sum_add(), fb(), 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 4891 of file numeric.c.

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

References accum_sum_add(), accum_sum_reset(), Assert, fb(), init_var, init_var_from_num(), MemoryContextSwitchTo(), mul_var(), newval, NUMERIC_IS_NINF, NUMERIC_IS_PINF, NUMERIC_IS_SPECIAL, NUMERIC_NEG, and NUMERIC_POS.

Referenced by int8_accum_inv(), and numeric_accum_inv().

◆ duplicate_numeric()

static Numeric duplicate_numeric ( Numeric  num)
static

Definition at line 7529 of file numeric.c.

7530{
7531 Numeric res;
7532
7533 res = (Numeric) palloc(VARSIZE(num));
7534 memcpy(res, num, VARSIZE(num));
7535 return res;
7536}
struct NumericData * Numeric
Definition numeric.h:57
static Size VARSIZE(const void *PTR)
Definition varatt.h:298

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

10577{
10578 int ln_dweight;
10579
10580 /* Caller should fail on ln(negative), but for the moment return zero */
10581 if (var->sign != NUMERIC_POS)
10582 return 0;
10583
10584 if (cmp_var(var, &const_zero_point_nine) >= 0 &&
10585 cmp_var(var, &const_one_point_one) <= 0)
10586 {
10587 /*
10588 * 0.9 <= var <= 1.1
10589 *
10590 * ln(var) has a negative weight (possibly very large). To get a
10591 * reasonably accurate result, estimate it using ln(1+x) ~= x.
10592 */
10593 NumericVar x;
10594
10595 init_var(&x);
10596 sub_var(var, &const_one, &x);
10597
10598 if (x.ndigits > 0)
10599 {
10600 /* Use weight of most significant decimal digit of x */
10601 ln_dweight = x.weight * DEC_DIGITS + (int) log10(x.digits[0]);
10602 }
10603 else
10604 {
10605 /* x = 0. Since ln(1) = 0 exactly, we don't need extra digits */
10606 ln_dweight = 0;
10607 }
10608
10609 free_var(&x);
10610 }
10611 else
10612 {
10613 /*
10614 * Estimate the logarithm using the first couple of digits from the
10615 * input number. This will give an accurate result whenever the input
10616 * is not too close to 1.
10617 */
10618 if (var->ndigits > 0)
10619 {
10620 int digits;
10621 int dweight;
10622 double ln_var;
10623
10624 digits = var->digits[0];
10625 dweight = var->weight * DEC_DIGITS;
10626
10627 if (var->ndigits > 1)
10628 {
10629 digits = digits * NBASE + var->digits[1];
10631 }
10632
10633 /*----------
10634 * We have var ~= digits * 10^dweight
10635 * so ln(var) ~= ln(digits) + dweight * ln(10)
10636 *----------
10637 */
10638 ln_var = log((double) digits) + dweight * 2.302585092994046;
10640 }
10641 else
10642 {
10643 /* Caller should fail on ln(0), but for the moment return zero */
10644 ln_dweight = 0;
10645 }
10646 }
10647
10648 return ln_dweight;
10649}
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:10658
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, fb(), 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 10447 of file numeric.c.

10448{
10449 NumericVar x;
10450 NumericVar elem;
10451 int ni;
10452 double val;
10453 int dweight;
10454 int ndiv2;
10455 int sig_digits;
10456 int local_rscale;
10457
10458 init_var(&x);
10459 init_var(&elem);
10460
10462
10463 /*
10464 * Estimate the dweight of the result using floating point arithmetic, so
10465 * that we can choose an appropriate local rscale for the calculation.
10466 */
10468
10469 /* Guard against overflow/underflow */
10470 /* If you change this limit, see also power_var()'s limit */
10471 if (fabs(val) >= NUMERIC_MAX_RESULT_SCALE * 3)
10472 {
10473 if (val > 0)
10474 ereport(ERROR,
10476 errmsg("value overflows numeric format")));
10478 result->dscale = rscale;
10479 return;
10480 }
10481
10482 /* decimal weight = log10(e^x) = x * log10(e) */
10483 dweight = (int) (val * 0.434294481903252);
10484
10485 /*
10486 * Reduce x to the range -0.01 <= x <= 0.01 (approximately) by dividing by
10487 * 2^ndiv2, to improve the convergence rate of the Taylor series.
10488 *
10489 * Note that the overflow check above ensures that fabs(x) < 6000, which
10490 * means that ndiv2 <= 20 here.
10491 */
10492 if (fabs(val) > 0.01)
10493 {
10494 ndiv2 = 1;
10495 val /= 2;
10496
10497 while (fabs(val) > 0.01)
10498 {
10499 ndiv2++;
10500 val /= 2;
10501 }
10502
10503 local_rscale = x.dscale + ndiv2;
10504 div_var_int(&x, 1 << ndiv2, 0, &x, local_rscale, true);
10505 }
10506 else
10507 ndiv2 = 0;
10508
10509 /*
10510 * Set the scale for the Taylor series expansion. The final result has
10511 * (dweight + rscale + 1) significant digits. In addition, we have to
10512 * raise the Taylor series result to the power 2^ndiv2, which introduces
10513 * an error of up to around log10(2^ndiv2) digits, so work with this many
10514 * extra digits of precision (plus a few more for good measure).
10515 */
10516 sig_digits = 1 + dweight + rscale + (int) (ndiv2 * 0.301029995663981);
10517 sig_digits = Max(sig_digits, 0) + 8;
10518
10520
10521 /*
10522 * Use the Taylor series
10523 *
10524 * exp(x) = 1 + x + x^2/2! + x^3/3! + ...
10525 *
10526 * Given the limited range of x, this should converge reasonably quickly.
10527 * We run the series until the terms fall below the local_rscale limit.
10528 */
10530
10531 mul_var(&x, &x, &elem, local_rscale);
10532 ni = 2;
10533 div_var_int(&elem, ni, 0, &elem, local_rscale, true);
10534
10535 while (elem.ndigits != 0)
10536 {
10537 add_var(result, &elem, result);
10538
10539 mul_var(&elem, &x, &elem, local_rscale);
10540 ni++;
10541 div_var_int(&elem, ni, 0, &elem, local_rscale, true);
10542 }
10543
10544 /*
10545 * Compensate for the argument range reduction. Since the weight of the
10546 * result doubles with each multiplication, we can reduce the local rscale
10547 * as we proceed.
10548 */
10549 while (ndiv2-- > 0)
10550 {
10551 local_rscale = sig_digits - result->weight * 2 * DEC_DIGITS;
10554 }
10555
10556 /* Round to requested rscale */
10557 round_var(result, rscale);
10558
10559 free_var(&x);
10560 free_var(&elem);
10561}
static double numericvar_to_double_no_overflow(const NumericVar *var)
Definition numeric.c:8007
Datum arg
Definition elog.c:1323
#define NUMERIC_MAX_RESULT_SCALE
Definition numeric.h:46
#define NUMERIC_MIN_DISPLAY_SCALE
Definition numeric.h:44

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

Referenced by numeric_exp(), and power_var().

◆ float4_numeric()

Datum float4_numeric ( PG_FUNCTION_ARGS  )

Definition at line 4643 of file numeric.c.

4644{
4646 Numeric res;
4648 char buf[FLT_DIG + 100];
4649 const char *endptr;
4650
4651 if (isnan(val))
4653
4654 if (isinf(val))
4655 {
4656 if (val < 0)
4658 else
4660 }
4661
4662 snprintf(buf, sizeof(buf), "%.*g", FLT_DIG, val);
4663
4664 init_var(&result);
4665
4666 /* Assume we need not worry about leading/trailing spaces */
4667 if (!set_var_from_str(buf, buf, &result, &endptr, fcinfo->context))
4669
4670 res = make_result(&result);
4671
4672 free_var(&result);
4673
4674 PG_RETURN_NUMERIC(res);
4675}
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:6778
static Numeric make_result(const NumericVar *var)
Definition numeric.c:7641
static const NumericVar const_nan
Definition numeric.c:451
float float4
Definition c.h:772
#define PG_RETURN_NULL()
Definition fmgr.h:346
#define PG_GETARG_FLOAT4(n)
Definition fmgr.h:282
#define PG_RETURN_NUMERIC(x)
Definition numeric.h:83
#define snprintf
Definition port.h:261

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

Referenced by datum_to_jsonb_internal(), and JsonItemFromDatum().

◆ float8_numeric()

Datum float8_numeric ( PG_FUNCTION_ARGS  )

Definition at line 4544 of file numeric.c.

4545{
4547 Numeric res;
4549 char buf[DBL_DIG + 100];
4550 const char *endptr;
4551
4552 if (isnan(val))
4554
4555 if (isinf(val))
4556 {
4557 if (val < 0)
4559 else
4561 }
4562
4563 snprintf(buf, sizeof(buf), "%.*g", DBL_DIG, val);
4564
4565 init_var(&result);
4566
4567 /* Assume we need not worry about leading/trailing spaces */
4568 if (!set_var_from_str(buf, buf, &result, &endptr, fcinfo->context))
4570
4571 res = make_result(&result);
4572
4573 free_var(&result);
4574
4575 PG_RETURN_NUMERIC(res);
4576}
double float8
Definition c.h:773
#define PG_GETARG_FLOAT8(n)
Definition fmgr.h:283

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

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

◆ floor_var()

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

Definition at line 9874 of file numeric.c.

9875{
9876 NumericVar tmp;
9877
9878 init_var(&tmp);
9879 set_var_from_var(var, &tmp);
9880
9881 trunc_var(&tmp, 0);
9882
9883 if (var->sign == NUMERIC_NEG && cmp_var(var, &tmp) != 0)
9884 sub_var(&tmp, &const_one, &tmp);
9885
9886 set_var_from_var(&tmp, result);
9887 free_var(&tmp);
9888}

References cmp_var(), const_one, free_var(), init_var, NUMERIC_NEG, result, 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 9897 of file numeric.c.

9898{
9899 int res_dscale;
9900 int cmp;
9903
9904 res_dscale = Max(var1->dscale, var2->dscale);
9905
9906 /*
9907 * Arrange for var1 to be the number with the greater absolute value.
9908 *
9909 * This would happen automatically in the loop below, but avoids an
9910 * expensive modulo operation.
9911 */
9912 cmp = cmp_abs(var1, var2);
9913 if (cmp < 0)
9914 {
9915 const NumericVar *tmp = var1;
9916
9917 var1 = var2;
9918 var2 = tmp;
9919 }
9920
9921 /*
9922 * Also avoid the taking the modulo if the inputs have the same absolute
9923 * value, or if the smaller input is zero.
9924 */
9925 if (cmp == 0 || var2->ndigits == 0)
9926 {
9928 result->sign = NUMERIC_POS;
9929 result->dscale = res_dscale;
9930 return;
9931 }
9932
9933 init_var(&tmp_arg);
9934 init_var(&mod);
9935
9936 /* Use the Euclidean algorithm to find the GCD */
9939
9940 for (;;)
9941 {
9942 /* this loop can take a while, so allow it to be interrupted */
9944
9946 if (mod.ndigits == 0)
9947 break;
9950 }
9951 result->sign = NUMERIC_POS;
9952 result->dscale = res_dscale;
9953
9954 free_var(&tmp_arg);
9955 free_var(&mod);
9956}
static void mod_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition numeric.c:9751
#define CHECK_FOR_INTERRUPTS()
Definition miscadmin.h:125
static int cmp(const chr *x, const chr *y, size_t len)

References CHECK_FOR_INTERRUPTS, cmp(), cmp_abs(), fb(), free_var(), init_var, Max, mod_var(), NUMERIC_POS, result, and set_var_from_var().

Referenced by numeric_gcd(), and numeric_lcm().

◆ generate_series_numeric()

Datum generate_series_numeric ( PG_FUNCTION_ARGS  )

Definition at line 1694 of file numeric.c.

1695{
1696 return generate_series_step_numeric(fcinfo);
1697}
Datum generate_series_step_numeric(PG_FUNCTION_ARGS)
Definition numeric.c:1700

References generate_series_step_numeric().

◆ generate_series_numeric_support()

Datum generate_series_numeric_support ( PG_FUNCTION_ARGS  )

Definition at line 1825 of file numeric.c.

1826{
1828 Node *ret = NULL;
1829
1831 {
1832 /* Try to estimate the number of rows returned */
1834
1835 if (is_funcclause(req->node)) /* be paranoid */
1836 {
1837 List *args = ((FuncExpr *) req->node)->args;
1838 Node *arg1,
1839 *arg2,
1840 *arg3;
1841
1842 /* We can use estimated argument values here */
1844 arg2 = estimate_expression_value(req->root, lsecond(args));
1845 if (list_length(args) >= 3)
1846 arg3 = estimate_expression_value(req->root, lthird(args));
1847 else
1848 arg3 = NULL;
1849
1850 /*
1851 * If any argument is constant NULL, we can safely assume that
1852 * zero rows are returned. Otherwise, if they're all non-NULL
1853 * constants, we can calculate the number of rows that will be
1854 * returned.
1855 */
1856 if ((IsA(arg1, Const) &&
1857 ((Const *) arg1)->constisnull) ||
1858 (IsA(arg2, Const) &&
1859 ((Const *) arg2)->constisnull) ||
1860 (arg3 != NULL && IsA(arg3, Const) &&
1861 ((Const *) arg3)->constisnull))
1862 {
1863 req->rows = 0;
1864 ret = (Node *) req;
1865 }
1866 else if (IsA(arg1, Const) &&
1867 IsA(arg2, Const) &&
1868 (arg3 == NULL || IsA(arg3, Const)))
1869 {
1872 NumericVar step = const_one;
1873
1874 /*
1875 * If any argument is NaN or infinity, generate_series() will
1876 * error out, so we needn't produce an estimate.
1877 */
1880
1884
1885 if (arg3)
1886 {
1888
1890
1893
1895 }
1896
1897 /*
1898 * The number of rows that will be returned is given by
1899 * floor((stop - start) / step) + 1, if the sign of step
1900 * matches the sign of stop - start. Otherwise, no rows will
1901 * be returned.
1902 */
1903 if (cmp_var(&step, &const_zero) != 0)
1904 {
1906 NumericVar stop;
1907 NumericVar res;
1908
1911
1912 init_var(&res);
1913 sub_var(&stop, &start, &res);
1914
1915 if (step.sign != res.sign)
1916 {
1917 /* no rows will be returned */
1918 req->rows = 0;
1919 ret = (Node *) req;
1920 }
1921 else
1922 {
1923 if (arg3)
1924 div_var(&res, &step, &res, 0, false, false);
1925 else
1926 trunc_var(&res, 0); /* step = 1 */
1927
1928 req->rows = numericvar_to_double_no_overflow(&res) + 1;
1929 ret = (Node *) req;
1930 }
1931
1932 free_var(&res);
1933 }
1934 }
1935 }
1936 }
1937
1938 PG_RETURN_POINTER(ret);
1939}
Node * estimate_expression_value(PlannerInfo *root, Node *node)
Definition clauses.c:2644
#define PG_GETARG_POINTER(n)
Definition fmgr.h:277
#define PG_RETURN_POINTER(x)
Definition fmgr.h:363
return str start
static bool is_funcclause(const void *clause)
Definition nodeFuncs.h:69
#define IsA(nodeptr, _type_)
Definition nodes.h:162
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:133

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

◆ generate_series_step_numeric()

Datum generate_series_step_numeric ( PG_FUNCTION_ARGS  )

Definition at line 1700 of file numeric.c.

1701{
1704 MemoryContext oldcontext;
1705
1706 if (SRF_IS_FIRSTCALL())
1707 {
1711
1712 /* Reject NaN and infinities in start and stop values */
1714 {
1716 ereport(ERROR,
1718 errmsg("start value cannot be NaN")));
1719 else
1720 ereport(ERROR,
1722 errmsg("start value cannot be infinity")));
1723 }
1725 {
1727 ereport(ERROR,
1729 errmsg("stop value cannot be NaN")));
1730 else
1731 ereport(ERROR,
1733 errmsg("stop value cannot be infinity")));
1734 }
1735
1736 /* see if we were given an explicit step size */
1737 if (PG_NARGS() == 3)
1738 {
1740
1742 {
1744 ereport(ERROR,
1746 errmsg("step size cannot be NaN")));
1747 else
1748 ereport(ERROR,
1750 errmsg("step size cannot be infinity")));
1751 }
1752
1754
1755 if (cmp_var(&steploc, &const_zero) == 0)
1756 ereport(ERROR,
1758 errmsg("step size cannot equal zero")));
1759 }
1760
1761 /* create a function context for cross-call persistence */
1763
1764 /*
1765 * Switch to memory context appropriate for multiple function calls.
1766 */
1767 oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
1768
1769 /* allocate memory for user context */
1771
1772 /*
1773 * Use fctx to keep state from call to call. Seed current with the
1774 * original start value. We must copy the start_num and stop_num
1775 * values rather than pointing to them, since we may have detoasted
1776 * them in the per-call context.
1777 */
1778 init_var(&fctx->current);
1779 init_var(&fctx->stop);
1780 init_var(&fctx->step);
1781
1782 set_var_from_num(start_num, &fctx->current);
1784 set_var_from_var(&steploc, &fctx->step);
1785
1786 funcctx->user_fctx = fctx;
1787 MemoryContextSwitchTo(oldcontext);
1788 }
1789
1790 /* stuff done on every call of the function */
1792
1793 /*
1794 * Get the saved state and use current state as the result of this
1795 * iteration.
1796 */
1797 fctx = funcctx->user_fctx;
1798
1799 if ((fctx->step.sign == NUMERIC_POS &&
1800 cmp_var(&fctx->current, &fctx->stop) <= 0) ||
1801 (fctx->step.sign == NUMERIC_NEG &&
1802 cmp_var(&fctx->current, &fctx->stop) >= 0))
1803 {
1804 Numeric result = make_result(&fctx->current);
1805
1806 /* switch to memory context appropriate for iteration calculation */
1807 oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
1808
1809 /* increment current in preparation for next iteration */
1810 add_var(&fctx->current, &fctx->step, &fctx->current);
1811 MemoryContextSwitchTo(oldcontext);
1812
1813 /* do when there is more left to send */
1815 }
1816 else
1817 /* do when there is no more left */
1819}
static void set_var_from_num(Numeric num, NumericVar *dest)
Definition numeric.c:7186
#define palloc_object(type)
Definition fe_memutils.h:89
#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

References add_var(), cmp_var(), const_one, const_zero, ereport, errcode(), errmsg, ERROR, fb(), init_var, init_var_from_num(), make_result(), MemoryContextSwitchTo(), NUMERIC_IS_NAN, NUMERIC_IS_SPECIAL, NUMERIC_NEG, NUMERIC_POS, NumericGetDatum(), palloc_object, PG_GETARG_NUMERIC, PG_NARGS, result, set_var_from_num(), set_var_from_var(), SRF_FIRSTCALL_INIT, SRF_IS_FIRSTCALL, SRF_PERCALL_SETUP, SRF_RETURN_DONE, and SRF_RETURN_NEXT.

Referenced by generate_series_numeric().

◆ get_min_scale()

static int get_min_scale ( NumericVar var)
static

Definition at line 4123 of file numeric.c.

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

References DEC_DIGITS, NumericVar::digits, fb(), 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 7260 of file numeric.c.

7261{
7262 int dscale;
7263 char *str;
7264 char *cp;
7265 char *endcp;
7266 int i;
7267 int d;
7269
7270#if DEC_DIGITS > 1
7271 NumericDigit d1;
7272#endif
7273
7274 dscale = var->dscale;
7275
7276 /*
7277 * Allocate space for the result.
7278 *
7279 * i is set to the # of decimal digits before decimal point. dscale is the
7280 * # of decimal digits we will print after decimal point. We may generate
7281 * as many as DEC_DIGITS-1 excess digits at the end, and in addition we
7282 * need room for sign, decimal point, null terminator.
7283 */
7284 i = (var->weight + 1) * DEC_DIGITS;
7285 if (i <= 0)
7286 i = 1;
7287
7288 str = palloc(i + dscale + DEC_DIGITS + 2);
7289 cp = str;
7290
7291 /*
7292 * Output a dash for negative values
7293 */
7294 if (var->sign == NUMERIC_NEG)
7295 *cp++ = '-';
7296
7297 /*
7298 * Output all digits before the decimal point
7299 */
7300 if (var->weight < 0)
7301 {
7302 d = var->weight + 1;
7303 *cp++ = '0';
7304 }
7305 else
7306 {
7307 for (d = 0; d <= var->weight; d++)
7308 {
7309 dig = (d < var->ndigits) ? var->digits[d] : 0;
7310 /* In the first digit, suppress extra leading decimal zeroes */
7311#if DEC_DIGITS == 4
7312 {
7313 bool putit = (d > 0);
7314
7315 d1 = dig / 1000;
7316 dig -= d1 * 1000;
7317 putit |= (d1 > 0);
7318 if (putit)
7319 *cp++ = d1 + '0';
7320 d1 = dig / 100;
7321 dig -= d1 * 100;
7322 putit |= (d1 > 0);
7323 if (putit)
7324 *cp++ = d1 + '0';
7325 d1 = dig / 10;
7326 dig -= d1 * 10;
7327 putit |= (d1 > 0);
7328 if (putit)
7329 *cp++ = d1 + '0';
7330 *cp++ = dig + '0';
7331 }
7332#elif DEC_DIGITS == 2
7333 d1 = dig / 10;
7334 dig -= d1 * 10;
7335 if (d1 > 0 || d > 0)
7336 *cp++ = d1 + '0';
7337 *cp++ = dig + '0';
7338#elif DEC_DIGITS == 1
7339 *cp++ = dig + '0';
7340#else
7341#error unsupported NBASE
7342#endif
7343 }
7344 }
7345
7346 /*
7347 * If requested, output a decimal point and all the digits that follow it.
7348 * We initially put out a multiple of DEC_DIGITS digits, then truncate if
7349 * needed.
7350 */
7351 if (dscale > 0)
7352 {
7353 *cp++ = '.';
7354 endcp = cp + dscale;
7355 for (i = 0; i < dscale; d++, i += DEC_DIGITS)
7356 {
7357 dig = (d >= 0 && d < var->ndigits) ? var->digits[d] : 0;
7358#if DEC_DIGITS == 4
7359 d1 = dig / 1000;
7360 dig -= d1 * 1000;
7361 *cp++ = d1 + '0';
7362 d1 = dig / 100;
7363 dig -= d1 * 100;
7364 *cp++ = d1 + '0';
7365 d1 = dig / 10;
7366 dig -= d1 * 10;
7367 *cp++ = d1 + '0';
7368 *cp++ = dig + '0';
7369#elif DEC_DIGITS == 2
7370 d1 = dig / 10;
7371 dig -= d1 * 10;
7372 *cp++ = d1 + '0';
7373 *cp++ = dig + '0';
7374#elif DEC_DIGITS == 1
7375 *cp++ = dig + '0';
7376#else
7377#error unsupported NBASE
7378#endif
7379 }
7380 cp = endcp;
7381 }
7382
7383 /*
7384 * terminate the string and return it
7385 */
7386 *cp = '\0';
7387 return str;
7388}
const char * str

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

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

◆ get_str_from_var_sci()

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

Definition at line 7413 of file numeric.c.

7414{
7415 int32 exponent;
7417 size_t len;
7418 char *str;
7419 char *sig_out;
7420
7421 if (rscale < 0)
7422 rscale = 0;
7423
7424 /*
7425 * Determine the exponent of this number in normalised form.
7426 *
7427 * This is the exponent required to represent the number with only one
7428 * significant digit before the decimal place.
7429 */
7430 if (var->ndigits > 0)
7431 {
7432 exponent = (var->weight + 1) * DEC_DIGITS;
7433
7434 /*
7435 * Compensate for leading decimal zeroes in the first numeric digit by
7436 * decrementing the exponent.
7437 */
7438 exponent -= DEC_DIGITS - (int) log10(var->digits[0]);
7439 }
7440 else
7441 {
7442 /*
7443 * If var has no digits, then it must be zero.
7444 *
7445 * Zero doesn't technically have a meaningful exponent in normalised
7446 * notation, but we just display the exponent as zero for consistency
7447 * of output.
7448 */
7449 exponent = 0;
7450 }
7451
7452 /*
7453 * Divide var by 10^exponent to get the significand, rounding to rscale
7454 * decimal digits in the process.
7455 */
7456 init_var(&tmp_var);
7457
7458 power_ten_int(exponent, &tmp_var);
7459 div_var(var, &tmp_var, &tmp_var, rscale, true, true);
7461
7462 free_var(&tmp_var);
7463
7464 /*
7465 * Allocate space for the result.
7466 *
7467 * In addition to the significand, we need room for the exponent
7468 * decoration ("e"), the sign of the exponent, up to 10 digits for the
7469 * exponent itself, and of course the null terminator.
7470 */
7471 len = strlen(sig_out) + 13;
7472 str = palloc(len);
7473 snprintf(str, len, "%se%+03d", sig_out, exponent);
7474
7475 pfree(sig_out);
7476
7477 return str;
7478}
static char * get_str_from_var(const NumericVar *var)
Definition numeric.c:7260
static void power_ten_int(int exp, NumericVar *result)
Definition numeric.c:11203
const void size_t len

References DEC_DIGITS, NumericVar::digits, div_var(), fb(), 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 2721 of file numeric.c.

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

References Assert, digits, fb(), hash_any(), i, NUMERIC_DIGITS, NUMERIC_IS_SPECIAL, NUMERIC_NDIGITS, NUMERIC_WEIGHT, PG_GETARG_NUMERIC, PG_RETURN_DATUM, PG_RETURN_UINT32, and result.

Referenced by JsonbHashScalarValue().

◆ hash_numeric_extended()

Datum hash_numeric_extended ( PG_FUNCTION_ARGS  )

Definition at line 2801 of file numeric.c.

2802{
2804 uint64 seed = PG_GETARG_INT64(1);
2806 Datum result;
2807 int weight;
2808 int start_offset;
2809 int end_offset;
2810 int i;
2811 int hash_len;
2813
2814 /* If it's NaN or infinity, don't try to hash the rest of the fields */
2815 if (NUMERIC_IS_SPECIAL(key))
2816 PG_RETURN_UINT64(seed);
2817
2818 weight = NUMERIC_WEIGHT(key);
2819 start_offset = 0;
2820 end_offset = 0;
2821
2822 digits = NUMERIC_DIGITS(key);
2823 for (i = 0; i < NUMERIC_NDIGITS(key); i++)
2824 {
2825 if (digits[i] != (NumericDigit) 0)
2826 break;
2827
2828 start_offset++;
2829
2830 weight--;
2831 }
2832
2833 if (NUMERIC_NDIGITS(key) == start_offset)
2834 PG_RETURN_UINT64(seed - 1);
2835
2836 for (i = NUMERIC_NDIGITS(key) - 1; i >= 0; i--)
2837 {
2838 if (digits[i] != (NumericDigit) 0)
2839 break;
2840
2841 end_offset++;
2842 }
2843
2845
2847 digit_hash = hash_any_extended((unsigned char *) (NUMERIC_DIGITS(key)
2848 + start_offset),
2849 hash_len * sizeof(NumericDigit),
2850 seed);
2851
2853
2855}
#define PG_GETARG_INT64(n)
Definition fmgr.h:284
#define PG_RETURN_UINT64(x)
Definition fmgr.h:371
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:436
static Datum UInt64GetDatum(uint64 X)
Definition postgres.h:446

References Assert, DatumGetUInt64(), digits, fb(), hash_any_extended(), i, NUMERIC_DIGITS, NUMERIC_IS_SPECIAL, NUMERIC_NDIGITS, NUMERIC_WEIGHT, PG_GETARG_INT64, PG_GETARG_NUMERIC, PG_RETURN_DATUM, PG_RETURN_UINT64, result, and UInt64GetDatum().

Referenced by JsonbHashScalarValueExtended().

◆ in_range_numeric_numeric()

Datum in_range_numeric_numeric ( PG_FUNCTION_ARGS  )

Definition at line 2586 of file numeric.c.

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

References add_var(), Assert, cmp_var(), ereport, errcode(), errmsg, ERROR, fb(), 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, result, sub_var(), and val.

◆ init_var_from_num()

◆ int128_deserialize()

static INT128 int128_deserialize ( StringInfo  buf)
inlinestatic

Definition at line 5614 of file numeric.c.

5615{
5616 int64 hi = pq_getmsgint64(buf);
5618
5619 return make_int128(hi, lo);
5620}
static INT128 make_int128(int64 hi, uint64 lo)
Definition int128.h:75
int64 pq_getmsgint64(StringInfo msg)
Definition pqformat.c:452

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

Referenced by int8_avg_deserialize(), and numeric_poly_deserialize().

◆ int128_serialize()

static void int128_serialize ( StringInfo  buf,
INT128  val 
)
inlinestatic

Definition at line 5604 of file numeric.c.

5605{
5608}
#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 7971 of file numeric.c.

7972{
7973 int sign;
7974 NumericDigit *ptr;
7975 int ndigits;
7976 int32 dig;
7977
7978 /* int128 can require at most 39 decimal digits; add one for safety */
7979 alloc_var(var, 40 / DEC_DIGITS);
7980 sign = int128_sign(val);
7981 var->sign = sign < 0 ? NUMERIC_NEG : NUMERIC_POS;
7982 var->dscale = 0;
7983 if (sign == 0)
7984 {
7985 var->ndigits = 0;
7986 var->weight = 0;
7987 return;
7988 }
7989 ptr = var->digits + var->ndigits;
7990 ndigits = 0;
7991 do
7992 {
7993 ptr--;
7994 ndigits++;
7996 *ptr = (NumericDigit) abs(dig);
7997 } while (!int128_is_zero(val));
7998 var->digits = ptr;
7999 var->ndigits = ndigits;
8000 var->weight = ndigits - 1;
8001}
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, fb(), 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 5506 of file numeric.c.

5507{
5509
5511
5512 /* Create the state data on the first call */
5513 if (state == NULL)
5514 state = makeInt128AggState(fcinfo, true);
5515
5516 if (!PG_ARGISNULL(1))
5518
5520}
static Int128AggState * makeInt128AggState(FunctionCallInfo fcinfo, bool calcSumX2)
Definition numeric.c:5445
static void do_int128_accum(Int128AggState *state, int64 newval)
Definition numeric.c:5483
#define PG_ARGISNULL(n)
Definition fmgr.h:209
#define PG_GETARG_INT16(n)
Definition fmgr.h:271

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

5833{
5835
5837
5838 /* Should not get here with no state */
5839 if (state == NULL)
5840 elog(ERROR, "int2_accum_inv called with NULL state");
5841
5842 if (!PG_ARGISNULL(1))
5844
5846}
static void do_int128_discard(Int128AggState *state, int64 newval)
Definition numeric.c:5496
#define elog(elevel,...)
Definition elog.h:228

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

6424{
6428
6429 /*
6430 * If we're invoked as an aggregate, we can cheat and modify our first
6431 * parameter in-place to reduce palloc overhead. Otherwise we need to make
6432 * a copy of it before scribbling on it.
6433 */
6434 if (AggCheckCallContext(fcinfo, NULL))
6436 else
6438
6439 if (ARR_HASNULL(transarray) ||
6441 elog(ERROR, "expected 2-element int8 array");
6442
6444 transdata->count++;
6445 transdata->sum += newval;
6446
6448}
#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:4609

References AggCheckCallContext(), ARR_DATA_PTR, ARR_HASNULL, ARR_OVERHEAD_NONULLS, ARR_SIZE, elog, ERROR, fb(), newval, PG_GETARG_ARRAYTYPE_P, PG_GETARG_ARRAYTYPE_P_COPY, PG_GETARG_INT16, and PG_RETURN_ARRAYTYPE_P.

◆ int2_avg_accum_inv()

Datum int2_avg_accum_inv ( PG_FUNCTION_ARGS  )

Definition at line 6510 of file numeric.c.

6511{
6515
6516 /*
6517 * If we're invoked as an aggregate, we can cheat and modify our first
6518 * parameter in-place to reduce palloc overhead. Otherwise we need to make
6519 * a copy of it before scribbling on it.
6520 */
6521 if (AggCheckCallContext(fcinfo, NULL))
6523 else
6525
6526 if (ARR_HASNULL(transarray) ||
6528 elog(ERROR, "expected 2-element int8 array");
6529
6531 transdata->count--;
6532 transdata->sum -= newval;
6533
6535}

References AggCheckCallContext(), ARR_DATA_PTR, ARR_HASNULL, ARR_OVERHEAD_NONULLS, ARR_SIZE, elog, ERROR, fb(), newval, PG_GETARG_ARRAYTYPE_P, PG_GETARG_ARRAYTYPE_P_COPY, PG_GETARG_INT16, and PG_RETURN_ARRAYTYPE_P.

◆ int2_numeric()

Datum int2_numeric ( PG_FUNCTION_ARGS  )

Definition at line 4495 of file numeric.c.

4496{
4498
4500}
Numeric int64_to_numeric(int64 val)
Definition numeric.c:4270

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

6317{
6318 int64 oldsum;
6319 int64 newval;
6320
6321 if (PG_ARGISNULL(0))
6322 {
6323 /* No non-null input seen so far... */
6324 if (PG_ARGISNULL(1))
6325 PG_RETURN_NULL(); /* still no non-null */
6326 /* This is the first non-null input. */
6329 }
6330
6332
6333 /* Leave sum unchanged if new input is null. */
6334 if (PG_ARGISNULL(1))
6336
6337 /* OK to do the addition. */
6339
6341}
#define PG_RETURN_INT64(x)
Definition fmgr.h:370

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

6594{
6597
6598 if (ARR_HASNULL(transarray) ||
6600 elog(ERROR, "expected 2-element int8 array");
6602
6603 /* SQL defines SUM of no values to be NULL */
6604 if (transdata->count == 0)
6606
6608}
#define Int64GetDatumFast(X)
Definition postgres.h:538

References ARR_DATA_PTR, ARR_HASNULL, ARR_OVERHEAD_NONULLS, ARR_SIZE, elog, ERROR, fb(), Int64GetDatumFast, PG_GETARG_ARRAYTYPE_P, PG_RETURN_DATUM, and PG_RETURN_NULL.

◆ int4_accum()

Datum int4_accum ( PG_FUNCTION_ARGS  )

Definition at line 5523 of file numeric.c.

5524{
5526
5528
5529 /* Create the state data on the first call */
5530 if (state == NULL)
5531 state = makeInt128AggState(fcinfo, true);
5532
5533 if (!PG_ARGISNULL(1))
5535
5537}
#define PG_GETARG_INT32(n)
Definition fmgr.h:269

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

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

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

6452{
6456
6457 /*
6458 * If we're invoked as an aggregate, we can cheat and modify our first
6459 * parameter in-place to reduce palloc overhead. Otherwise we need to make
6460 * a copy of it before scribbling on it.
6461 */
6462 if (AggCheckCallContext(fcinfo, NULL))
6464 else
6466
6467 if (ARR_HASNULL(transarray) ||
6469 elog(ERROR, "expected 2-element int8 array");
6470
6472 transdata->count++;
6473 transdata->sum += newval;
6474
6476}

References AggCheckCallContext(), ARR_DATA_PTR, ARR_HASNULL, ARR_OVERHEAD_NONULLS, ARR_SIZE, elog, ERROR, fb(), newval, PG_GETARG_ARRAYTYPE_P, PG_GETARG_ARRAYTYPE_P_COPY, PG_GETARG_INT32, and PG_RETURN_ARRAYTYPE_P.

◆ int4_avg_accum_inv()

Datum int4_avg_accum_inv ( PG_FUNCTION_ARGS  )

Definition at line 6538 of file numeric.c.

6539{
6543
6544 /*
6545 * If we're invoked as an aggregate, we can cheat and modify our first
6546 * parameter in-place to reduce palloc overhead. Otherwise we need to make
6547 * a copy of it before scribbling on it.
6548 */
6549 if (AggCheckCallContext(fcinfo, NULL))
6551 else
6553
6554 if (ARR_HASNULL(transarray) ||
6556 elog(ERROR, "expected 2-element int8 array");
6557
6559 transdata->count--;
6560 transdata->sum -= newval;
6561
6563}

References AggCheckCallContext(), ARR_DATA_PTR, ARR_HASNULL, ARR_OVERHEAD_NONULLS, ARR_SIZE, elog, ERROR, fb(), newval, PG_GETARG_ARRAYTYPE_P, PG_GETARG_ARRAYTYPE_P_COPY, PG_GETARG_INT32, and PG_RETURN_ARRAYTYPE_P.

◆ int4_avg_combine()

Datum int4_avg_combine ( PG_FUNCTION_ARGS  )

Definition at line 6479 of file numeric.c.

6480{
6485
6486 if (!AggCheckCallContext(fcinfo, NULL))
6487 elog(ERROR, "aggregate function called in non-aggregate context");
6488
6491
6492 if (ARR_HASNULL(transarray1) ||
6494 elog(ERROR, "expected 2-element int8 array");
6495
6496 if (ARR_HASNULL(transarray2) ||
6498 elog(ERROR, "expected 2-element int8 array");
6499
6502
6503 state1->count += state2->count;
6504 state1->sum += state2->sum;
6505
6507}

References AggCheckCallContext(), ARR_DATA_PTR, ARR_HASNULL, ARR_OVERHEAD_NONULLS, ARR_SIZE, elog, ERROR, fb(), PG_GETARG_ARRAYTYPE_P, and PG_RETURN_ARRAYTYPE_P.

◆ int4_numeric()

Datum int4_numeric ( PG_FUNCTION_ARGS  )

Definition at line 4364 of file numeric.c.

4365{
4367
4369}

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

6345{
6346 int64 oldsum;
6347 int64 newval;
6348
6349 if (PG_ARGISNULL(0))
6350 {
6351 /* No non-null input seen so far... */
6352 if (PG_ARGISNULL(1))
6353 PG_RETURN_NULL(); /* still no non-null */
6354 /* This is the first non-null input. */
6357 }
6358
6360
6361 /* Leave sum unchanged if new input is null. */
6362 if (PG_ARGISNULL(1))
6364
6365 /* OK to do the addition. */
6367
6369}

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

4292{
4293 Numeric res;
4295 int rscale;
4296 int w;
4297 int m;
4298
4299 init_var(&result);
4300
4301 /* result scale */
4302 rscale = log10val2 < 0 ? 0 : log10val2;
4303
4304 /* how much to decrease the weight by */
4305 w = log10val2 / DEC_DIGITS;
4306 /* how much is left to divide by */
4307 m = log10val2 % DEC_DIGITS;
4308 if (m < 0)
4309 {
4310 m += DEC_DIGITS;
4311 w--;
4312 }
4313
4314 /*
4315 * If there is anything left to divide by (10^m with 0 < m < DEC_DIGITS),
4316 * multiply the dividend by 10^(DEC_DIGITS - m), and shift the weight by
4317 * one more.
4318 */
4319 if (m > 0)
4320 {
4321#if DEC_DIGITS == 4
4322 static const int pow10[] = {1, 10, 100, 1000};
4323#elif DEC_DIGITS == 2
4324 static const int pow10[] = {1, 10};
4325#elif DEC_DIGITS == 1
4326 static const int pow10[] = {1};
4327#else
4328#error unsupported NBASE
4329#endif
4332
4333 StaticAssertDecl(lengthof(pow10) == DEC_DIGITS, "mismatch with DEC_DIGITS");
4334
4336 {
4337 /* do the multiplication using 128-bit integers */
4338 INT128 tmp;
4339
4340 tmp = int64_to_int128(0);
4342
4344 }
4345 else
4347
4348 w++;
4349 }
4350 else
4352
4353 result.weight -= w;
4354 result.dscale = rscale;
4355
4356 res = make_result(&result);
4357
4358 free_var(&result);
4359
4360 return res;
4361}
static void int64_to_numericvar(int64 val, NumericVar *var)
Definition numeric.c:7854
static void int128_to_numericvar(INT128 val, NumericVar *var)
Definition numeric.c:7971
#define unlikely(x)
Definition c.h:497
#define lengthof(array)
Definition c.h:932
#define StaticAssertDecl(condition, errmessage)
Definition c.h:1067
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

References DEC_DIGITS, fb(), 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(), result, StaticAssertDecl, and unlikely.

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

7855{
7856 uint64 uval,
7857 newuval;
7858 NumericDigit *ptr;
7859 int ndigits;
7860
7861 /* int64 can require at most 19 decimal digits; add one for safety */
7862 alloc_var(var, 20 / DEC_DIGITS);
7863 if (val < 0)
7864 {
7865 var->sign = NUMERIC_NEG;
7866 uval = pg_abs_s64(val);
7867 }
7868 else
7869 {
7870 var->sign = NUMERIC_POS;
7871 uval = val;
7872 }
7873 var->dscale = 0;
7874 if (val == 0)
7875 {
7876 var->ndigits = 0;
7877 var->weight = 0;
7878 return;
7879 }
7880 ptr = var->digits + var->ndigits;
7881 ndigits = 0;
7882 do
7883 {
7884 ptr--;
7885 ndigits++;
7886 newuval = uval / NBASE;
7887 *ptr = uval - newuval * NBASE;
7888 uval = newuval;
7889 } while (uval);
7890 var->digits = ptr;
7891 var->ndigits = ndigits;
7892 var->weight = ndigits - 1;
7893}
static uint64 pg_abs_s64(int64 a)
Definition int.h:352

References alloc_var(), DEC_DIGITS, NumericVar::digits, NumericVar::dscale, fb(), 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 5540 of file numeric.c.

5541{
5543
5545
5546 /* Create the state data on the first call */
5547 if (state == NULL)
5548 state = makeNumericAggState(fcinfo, true);
5549
5550 if (!PG_ARGISNULL(1))
5552
5554}
static NumericAggState * makeNumericAggState(FunctionCallInfo fcinfo, bool calcSumX2)
Definition numeric.c:4781
static void do_numeric_accum(NumericAggState *state, Numeric newval)
Definition numeric.c:4821

References do_numeric_accum(), fb(), 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 5866 of file numeric.c.

5867{
5869
5871
5872 /* Should not get here with no state */
5873 if (state == NULL)
5874 elog(ERROR, "int8_accum_inv called with NULL state");
5875
5876 if (!PG_ARGISNULL(1))
5877 {
5878 /* Should never fail, all inputs have dscale 0 */
5880 elog(ERROR, "do_numeric_discard failed unexpectedly");
5881 }
5882
5884}
static bool do_numeric_discard(NumericAggState *state, Numeric newval)
Definition numeric.c:4891

References do_numeric_discard(), elog, ERROR, fb(), 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 6566 of file numeric.c.

6567{
6570 Datum countd,
6571 sumd;
6572
6573 if (ARR_HASNULL(transarray) ||
6575 elog(ERROR, "expected 2-element int8 array");
6577
6578 /* SQL defines AVG of no values to be NULL */
6579 if (transdata->count == 0)
6581
6584
6586}
Datum numeric_div(PG_FUNCTION_ARGS)
Definition numeric.c:3145
#define DirectFunctionCall2(func, arg1, arg2)
Definition fmgr.h:690

References ARR_DATA_PTR, ARR_HASNULL, ARR_OVERHEAD_NONULLS, ARR_SIZE, DirectFunctionCall2, elog, ERROR, fb(), int64_to_numeric(), numeric_div(), NumericGetDatum(), PG_GETARG_ARRAYTYPE_P, PG_RETURN_DATUM, and PG_RETURN_NULL.

◆ int8_avg_accum()

Datum int8_avg_accum ( PG_FUNCTION_ARGS  )

Definition at line 5700 of file numeric.c.

5701{
5703
5705
5706 /* Create the state data on the first call */
5707 if (state == NULL)
5708 state = makeInt128AggState(fcinfo, false);
5709
5710 if (!PG_ARGISNULL(1))
5712
5714}

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

5888{
5890
5892
5893 /* Should not get here with no state */
5894 if (state == NULL)
5895 elog(ERROR, "int8_avg_accum_inv called with NULL state");
5896
5897 if (!PG_ARGISNULL(1))
5899
5901}

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

5722{
5725 MemoryContext agg_context;
5727
5728 if (!AggCheckCallContext(fcinfo, &agg_context))
5729 elog(ERROR, "aggregate function called in non-aggregate context");
5730
5733
5734 if (state2 == NULL)
5736
5737 /* manually copy all fields from state2 to state1 */
5738 if (state1 == NULL)
5739 {
5740 old_context = MemoryContextSwitchTo(agg_context);
5741
5742 state1 = makeInt128AggState(fcinfo, false);
5743 state1->N = state2->N;
5744 state1->sumX = state2->sumX;
5745
5747
5749 }
5750
5751 if (state2->N > 0)
5752 {
5753 state1->N += state2->N;
5754 int128_add_int128(&state1->sumX, state2->sumX);
5755 }
5757}
static void int128_add_int128(INT128 *i128, INT128 v)
Definition int128.h:144

References AggCheckCallContext(), elog, ERROR, fb(), int128_add_int128(), makeInt128AggState(), MemoryContextSwitchTo(), PG_ARGISNULL, PG_GETARG_POINTER, and PG_RETURN_POINTER.

◆ int8_avg_deserialize()

Datum int8_avg_deserialize ( PG_FUNCTION_ARGS  )

Definition at line 5796 of file numeric.c.

5797{
5798 bytea *sstate;
5801
5802 if (!AggCheckCallContext(fcinfo, NULL))
5803 elog(ERROR, "aggregate function called in non-aggregate context");
5804
5805 sstate = PG_GETARG_BYTEA_PP(0);
5806
5807 /*
5808 * Initialize a StringInfo so that we can "receive" it using the standard
5809 * recv-function infrastructure.
5810 */
5812 VARSIZE_ANY_EXHDR(sstate));
5813
5815
5816 /* N */
5817 result->N = pq_getmsgint64(&buf);
5818
5819 /* sumX */
5820 result->sumX = int128_deserialize(&buf);
5821
5822 pq_getmsgend(&buf);
5823
5825}
static INT128 int128_deserialize(StringInfo buf)
Definition numeric.c:5614
static Int128AggState * makeInt128AggStateCurrentContext(bool calcSumX2)
Definition numeric.c:5469
#define PG_GETARG_BYTEA_PP(n)
Definition fmgr.h:309
void pq_getmsgend(StringInfo msg)
Definition pqformat.c:634
static void initReadOnlyStringInfo(StringInfo str, char *data, int len)
Definition stringinfo.h:157
Definition c.h:835
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, fb(), initReadOnlyStringInfo(), int128_deserialize(), makeInt128AggStateCurrentContext(), PG_GETARG_BYTEA_PP, PG_RETURN_POINTER, pq_getmsgend(), pq_getmsgint64(), result, VARDATA_ANY(), and VARSIZE_ANY_EXHDR().

◆ int8_avg_serialize()

Datum int8_avg_serialize ( PG_FUNCTION_ARGS  )

Definition at line 5765 of file numeric.c.

5766{
5769 bytea *result;
5770
5771 /* Ensure we disallow calling when not in aggregate context */
5772 if (!AggCheckCallContext(fcinfo, NULL))
5773 elog(ERROR, "aggregate function called in non-aggregate context");
5774
5776
5778
5779 /* N */
5780 pq_sendint64(&buf, state->N);
5781
5782 /* sumX */
5783 int128_serialize(&buf, state->sumX);
5784
5786
5788}
static void int128_serialize(StringInfo buf, INT128 val)
Definition numeric.c:5604
#define PG_RETURN_BYTEA_P(x)
Definition fmgr.h:373
void pq_begintypsend(StringInfo buf)
Definition pqformat.c:325
bytea * pq_endtypsend(StringInfo buf)
Definition pqformat.c:345

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

◆ int8_numeric()

Datum int8_numeric ( PG_FUNCTION_ARGS  )

Definition at line 4440 of file numeric.c.

4441{
4443
4445}

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

6376{
6378
6379 if (PG_ARGISNULL(0))
6380 {
6381 /* No non-null input seen so far... */
6382 if (PG_ARGISNULL(1))
6383 PG_RETURN_NULL(); /* still no non-null */
6384 /* This is the first non-null input. */
6386 }
6387
6388 /*
6389 * Note that we cannot special-case the aggregate case here, as we do for
6390 * int2_sum and int4_sum: numeric is of variable size, so we cannot modify
6391 * our first parameter in-place.
6392 */
6393
6395
6396 /* Leave sum unchanged if new input is null. */
6397 if (PG_ARGISNULL(1))
6399
6400 /* OK to do the addition. */
6404}
Datum numeric_add(PG_FUNCTION_ARGS)
Definition numeric.c:2872

References DirectFunctionCall2, fb(), 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 10658 of file numeric.c.

10659{
10660 NumericVar x;
10661 NumericVar xx;
10662 int ni;
10663 NumericVar elem;
10665 int nsqrt;
10666 int local_rscale;
10667 int cmp;
10668
10670 if (cmp == 0)
10671 ereport(ERROR,
10673 errmsg("cannot take logarithm of zero")));
10674 else if (cmp < 0)
10675 ereport(ERROR,
10677 errmsg("cannot take logarithm of a negative number")));
10678
10679 init_var(&x);
10680 init_var(&xx);
10681 init_var(&elem);
10682 init_var(&fact);
10683
10686
10687 /*
10688 * Reduce input into range 0.9 < x < 1.1 with repeated sqrt() operations.
10689 *
10690 * The final logarithm will have up to around rscale+6 significant digits.
10691 * Each sqrt() will roughly halve the weight of x, so adjust the local
10692 * rscale as we work so that we keep this many significant digits at each
10693 * step (plus a few more for good measure).
10694 *
10695 * Note that we allow local_rscale < 0 during this input reduction
10696 * process, which implies rounding before the decimal point. sqrt_var()
10697 * explicitly supports this, and it significantly reduces the work
10698 * required to reduce very large inputs to the required range. Once the
10699 * input reduction is complete, x.weight will be 0 and its display scale
10700 * will be non-negative again.
10701 */
10702 nsqrt = 0;
10703 while (cmp_var(&x, &const_zero_point_nine) <= 0)
10704 {
10705 local_rscale = rscale - x.weight * DEC_DIGITS / 2 + 8;
10706 sqrt_var(&x, &x, local_rscale);
10707 mul_var(&fact, &const_two, &fact, 0);
10708 nsqrt++;
10709 }
10710 while (cmp_var(&x, &const_one_point_one) >= 0)
10711 {
10712 local_rscale = rscale - x.weight * DEC_DIGITS / 2 + 8;
10713 sqrt_var(&x, &x, local_rscale);
10714 mul_var(&fact, &const_two, &fact, 0);
10715 nsqrt++;
10716 }
10717
10718 /*
10719 * We use the Taylor series for 0.5 * ln((1+z)/(1-z)),
10720 *
10721 * z + z^3/3 + z^5/5 + ...
10722 *
10723 * where z = (x-1)/(x+1) is in the range (approximately) -0.053 .. 0.048
10724 * due to the above range-reduction of x.
10725 *
10726 * The convergence of this is not as fast as one would like, but is
10727 * tolerable given that z is small.
10728 *
10729 * The Taylor series result will be multiplied by 2^(nsqrt+1), which has a
10730 * decimal weight of (nsqrt+1) * log10(2), so work with this many extra
10731 * digits of precision (plus a few more for good measure).
10732 */
10733 local_rscale = rscale + (int) ((nsqrt + 1) * 0.301029995663981) + 8;
10734
10736 add_var(&x, &const_one, &elem);
10737 div_var(result, &elem, result, local_rscale, true, false);
10740
10741 ni = 1;
10742
10743 for (;;)
10744 {
10745 ni += 2;
10746 mul_var(&xx, &x, &xx, local_rscale);
10747 div_var_int(&xx, ni, 0, &elem, local_rscale, true);
10748
10749 if (elem.ndigits == 0)
10750 break;
10751
10752 add_var(result, &elem, result);
10753
10754 if (elem.weight < (result->weight - local_rscale * 2 / DEC_DIGITS))
10755 break;
10756 }
10757
10758 /* Compensate for argument range reduction, round to requested rscale */
10759 mul_var(result, &fact, result, rscale);
10760
10761 free_var(&x);
10762 free_var(&xx);
10763 free_var(&elem);
10764 free_var(&fact);
10765}
static const NumericVar const_two
Definition numeric.c:428
static void sqrt_var(const NumericVar *arg, NumericVar *result, int rscale)
Definition numeric.c:9967

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, fb(), free_var(), init_var, mul_var(), NumericVar::ndigits, result, 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 10776 of file numeric.c.

10777{
10780 int ln_base_dweight;
10781 int ln_num_dweight;
10782 int result_dweight;
10783 int rscale;
10784 int ln_base_rscale;
10785 int ln_num_rscale;
10786
10787 init_var(&ln_base);
10788 init_var(&ln_num);
10789
10790 /* Estimated dweights of ln(base), ln(num) and the final result */
10794
10795 /*
10796 * Select the scale of the result so that it will have at least
10797 * NUMERIC_MIN_SIG_DIGITS significant digits and is not less than either
10798 * input's display scale.
10799 */
10801 rscale = Max(rscale, base->dscale);
10802 rscale = Max(rscale, num->dscale);
10803 rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
10804 rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
10805
10806 /*
10807 * Set the scales for ln(base) and ln(num) so that they each have more
10808 * significant digits than the final result.
10809 */
10812
10815
10816 /* Form natural logarithms */
10817 ln_var(base, &ln_base, ln_base_rscale);
10818 ln_var(num, &ln_num, ln_num_rscale);
10819
10820 /* Divide and round to the required scale */
10821 div_var(&ln_num, &ln_base, result, rscale, true, false);
10822
10823 free_var(&ln_num);
10824 free_var(&ln_base);
10825}
static int estimate_ln_dweight(const NumericVar *var)
Definition numeric.c:10576
#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(), fb(), free_var(), init_var, ln_var(), Max, Min, NUMERIC_MAX_DISPLAY_SCALE, NUMERIC_MIN_DISPLAY_SCALE, NUMERIC_MIN_SIG_DIGITS, and result.

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

◆ make_numeric_typmod_safe()

int32 make_numeric_typmod_safe ( int32  precision,
int32  scale,
Node escontext 
)

Definition at line 1315 of file numeric.c.

1316{
1318 ereturn(escontext, -1,
1320 errmsg("NUMERIC precision %d must be between 1 and %d",
1321 precision, NUMERIC_MAX_PRECISION)));
1323 ereturn(escontext, -1,
1325 errmsg("NUMERIC scale %d must be between %d and %d",
1327
1328 return make_numeric_typmod(precision, scale);
1329}
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 ereturn, errcode(), errmsg, fb(), make_numeric_typmod(), NUMERIC_MAX_PRECISION, NUMERIC_MAX_SCALE, NUMERIC_MIN_SCALE, and scale.

Referenced by executeItemOptUnwrapTarget(), and numerictypmodin().

◆ make_result()

◆ make_result_safe()

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

Definition at line 7545 of file numeric.c.

7546{
7548 NumericDigit *digits = var->digits;
7549 int weight = var->weight;
7550 int sign = var->sign;
7551 int n;
7552 Size len;
7553
7555 {
7556 /*
7557 * Verify valid special value. This could be just an Assert, perhaps,
7558 * but it seems worthwhile to expend a few cycles to ensure that we
7559 * never write any nonzero reserved bits to disk.
7560 */
7561 if (!(sign == NUMERIC_NAN ||
7562 sign == NUMERIC_PINF ||
7563 sign == NUMERIC_NINF))
7564 elog(ERROR, "invalid numeric sign value 0x%x", sign);
7565
7567
7569 result->choice.n_header = sign;
7570 /* the header word is all we need */
7571
7572 dump_numeric("make_result()", result);
7573 return result;
7574 }
7575
7576 n = var->ndigits;
7577
7578 /* truncate leading zeroes */
7579 while (n > 0 && *digits == 0)
7580 {
7581 digits++;
7582 weight--;
7583 n--;
7584 }
7585 /* truncate trailing zeroes */
7586 while (n > 0 && digits[n - 1] == 0)
7587 n--;
7588
7589 /* If zero result, force to weight=0 and positive sign */
7590 if (n == 0)
7591 {
7592 weight = 0;
7593 sign = NUMERIC_POS;
7594 }
7595
7596 /* Build the result */
7597 if (NUMERIC_CAN_BE_SHORT(var->dscale, weight))
7598 {
7599 len = NUMERIC_HDRSZ_SHORT + n * sizeof(NumericDigit);
7600 result = (Numeric) palloc(len);
7602 result->choice.n_short.n_header =
7604 : NUMERIC_SHORT)
7605 | (var->dscale << NUMERIC_SHORT_DSCALE_SHIFT)
7606 | (weight < 0 ? NUMERIC_SHORT_WEIGHT_SIGN_MASK : 0)
7607 | (weight & NUMERIC_SHORT_WEIGHT_MASK);
7608 }
7609 else
7610 {
7611 len = NUMERIC_HDRSZ + n * sizeof(NumericDigit);
7612 result = (Numeric) palloc(len);
7614 result->choice.n_long.n_sign_dscale =
7615 sign | (var->dscale & NUMERIC_DSCALE_MASK);
7616 result->choice.n_long.n_weight = weight;
7617 }
7618
7620 if (n > 0)
7622
7623 /* Check for overflow of int16 fields */
7624 if (NUMERIC_WEIGHT(result) != weight ||
7625 NUMERIC_DSCALE(result) != var->dscale)
7626 ereturn(escontext, NULL,
7628 errmsg("value overflows numeric format")));
7629
7630 dump_numeric("make_result()", result);
7631 return result;
7632}
#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:748
static void SET_VARSIZE(void *PTR, Size len)
Definition varatt.h:432

References Assert, NumericVar::digits, digits, NumericVar::dscale, dump_numeric, elog, ereturn, errcode(), errmsg, ERROR, fb(), len, memcpy(), 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(), result, SET_VARSIZE(), NumericVar::sign, sign, and NumericVar::weight.

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

5446{
5448 MemoryContext agg_context;
5450
5451 if (!AggCheckCallContext(fcinfo, &agg_context))
5452 elog(ERROR, "aggregate function called in non-aggregate context");
5453
5454 old_context = MemoryContextSwitchTo(agg_context);
5455
5457 state->calcSumX2 = calcSumX2;
5458
5460
5461 return state;
5462}
#define palloc0_object(type)
Definition fe_memutils.h:90

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

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

◆ makeInt128AggStateCurrentContext()

static Int128AggState * makeInt128AggStateCurrentContext ( bool  calcSumX2)
static

Definition at line 5469 of file numeric.c.

5470{
5472
5474 state->calcSumX2 = calcSumX2;
5475
5476 return state;
5477}

References palloc0_object.

Referenced by int8_avg_deserialize(), and numeric_poly_deserialize().

◆ makeNumericAggState()

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

Definition at line 4781 of file numeric.c.

4782{
4784 MemoryContext agg_context;
4786
4787 if (!AggCheckCallContext(fcinfo, &agg_context))
4788 elog(ERROR, "aggregate function called in non-aggregate context");
4789
4790 old_context = MemoryContextSwitchTo(agg_context);
4791
4793 state->calcSumX2 = calcSumX2;
4794 state->agg_context = agg_context;
4795
4797
4798 return state;
4799}

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

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

◆ makeNumericAggStateCurrentContext()

static NumericAggState * makeNumericAggStateCurrentContext ( bool  calcSumX2)
static

Definition at line 4806 of file numeric.c.

4807{
4809
4811 state->calcSumX2 = calcSumX2;
4812 state->agg_context = CurrentMemoryContext;
4813
4814 return state;
4815}
MemoryContext CurrentMemoryContext
Definition mcxt.c:161

References CurrentMemoryContext, and palloc0_object.

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

◆ mod_var()

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

Definition at line 9751 of file numeric.c.

9752{
9753 NumericVar tmp;
9754
9755 init_var(&tmp);
9756
9757 /* ---------
9758 * We do this using the equation
9759 * mod(x,y) = x - trunc(x/y)*y
9760 * div_var can be persuaded to give us trunc(x/y) directly.
9761 * ----------
9762 */
9763 div_var(var1, var2, &tmp, 0, false, true);
9764
9765 mul_var(var2, &tmp, &tmp, var2->dscale);
9766
9767 sub_var(var1, &tmp, result);
9768
9769 free_var(&tmp);
9770}

References div_var(), NumericVar::dscale, fb(), free_var(), init_var, mul_var(), result, 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 8335 of file numeric.c.

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

References alloc_var(), Assert, DEC_DIGITS, fb(), i, maxdigits, Min, MUL_GUARD_DIGITS, mul_var_short(), NBASE, NBASE_SQR, NumericVar::ndigits, NUMERIC_NEG, NUMERIC_POS, palloc(), pfree(), PG_UINT64_MAX, result, round_var(), strip_var(), 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 8626 of file numeric.c.

8628{
8629 int var1ndigits = var1->ndigits;
8630 int var2ndigits = var2->ndigits;
8631 NumericDigit *var1digits = var1->digits;
8632 NumericDigit *var2digits = var2->digits;
8633 int res_sign;
8634 int res_weight;
8635 int res_ndigits;
8638 uint32 carry = 0;
8639 uint32 term;
8640
8641 /* Check preconditions */
8642 Assert(var1ndigits >= 1);
8643 Assert(var1ndigits <= 6);
8645
8646 /*
8647 * Determine the result sign, weight, and number of digits to calculate.
8648 * The weight figured here is correct if the product has no leading zero
8649 * digits; otherwise strip_var() will fix things up. Note that, unlike
8650 * mul_var(), we do not need to allocate an extra output digit, because we
8651 * are not rounding here.
8652 */
8653 if (var1->sign == var2->sign)
8655 else
8657 res_weight = var1->weight + var2->weight + 1;
8659
8660 /* Allocate result digit array */
8662 res_buf[0] = 0; /* spare digit for later rounding */
8663 res_digits = res_buf + 1;
8664
8665 /*
8666 * Compute the result digits in reverse, in one pass, propagating the
8667 * carry up as we go. The i'th result digit consists of the sum of the
8668 * products var1digits[i1] * var2digits[i2] for which i = i1 + i2 + 1.
8669 */
8670#define PRODSUM1(v1,i1,v2,i2) ((v1)[(i1)] * (v2)[(i2)])
8671#define PRODSUM2(v1,i1,v2,i2) (PRODSUM1(v1,i1,v2,i2) + (v1)[(i1)+1] * (v2)[(i2)-1])
8672#define PRODSUM3(v1,i1,v2,i2) (PRODSUM2(v1,i1,v2,i2) + (v1)[(i1)+2] * (v2)[(i2)-2])
8673#define PRODSUM4(v1,i1,v2,i2) (PRODSUM3(v1,i1,v2,i2) + (v1)[(i1)+3] * (v2)[(i2)-3])
8674#define PRODSUM5(v1,i1,v2,i2) (PRODSUM4(v1,i1,v2,i2) + (v1)[(i1)+4] * (v2)[(i2)-4])
8675#define PRODSUM6(v1,i1,v2,i2) (PRODSUM5(v1,i1,v2,i2) + (v1)[(i1)+5] * (v2)[(i2)-5])
8676
8677 switch (var1ndigits)
8678 {
8679 case 1:
8680 /* ---------
8681 * 1-digit case:
8682 * var1ndigits = 1
8683 * var2ndigits >= 1
8684 * res_ndigits = var2ndigits + 1
8685 * ----------
8686 */
8687 for (int i = var2ndigits - 1; i >= 0; i--)
8688 {
8690 res_digits[i + 1] = (NumericDigit) (term % NBASE);
8691 carry = term / NBASE;
8692 }
8694 break;
8695
8696 case 2:
8697 /* ---------
8698 * 2-digit case:
8699 * var1ndigits = 2
8700 * var2ndigits >= 2
8701 * res_ndigits = var2ndigits + 2
8702 * ----------
8703 */
8704 /* last result digit and carry */
8707 carry = term / NBASE;
8708
8709 /* remaining digits, except for the first two */
8710 for (int i = var2ndigits - 1; i >= 1; i--)
8711 {
8713 res_digits[i + 1] = (NumericDigit) (term % NBASE);
8714 carry = term / NBASE;
8715 }
8716 break;
8717
8718 case 3:
8719 /* ---------
8720 * 3-digit case:
8721 * var1ndigits = 3
8722 * var2ndigits >= 3
8723 * res_ndigits = var2ndigits + 3
8724 * ----------
8725 */
8726 /* last two result digits */
8729 carry = term / NBASE;
8730
8733 carry = term / NBASE;
8734
8735 /* remaining digits, except for the first three */
8736 for (int i = var2ndigits - 1; i >= 2; i--)
8737 {
8739 res_digits[i + 1] = (NumericDigit) (term % NBASE);
8740 carry = term / NBASE;
8741 }
8742 break;
8743
8744 case 4:
8745 /* ---------
8746 * 4-digit case:
8747 * var1ndigits = 4
8748 * var2ndigits >= 4
8749 * res_ndigits = var2ndigits + 4
8750 * ----------
8751 */
8752 /* last three result digits */
8755 carry = term / NBASE;
8756
8759 carry = term / NBASE;
8760
8763 carry = term / NBASE;
8764
8765 /* remaining digits, except for the first four */
8766 for (int i = var2ndigits - 1; i >= 3; i--)
8767 {
8769 res_digits[i + 1] = (NumericDigit) (term % NBASE);
8770 carry = term / NBASE;
8771 }
8772 break;
8773
8774 case 5:
8775 /* ---------
8776 * 5-digit case:
8777 * var1ndigits = 5
8778 * var2ndigits >= 5
8779 * res_ndigits = var2ndigits + 5
8780 * ----------
8781 */
8782 /* last four result digits */
8785 carry = term / NBASE;
8786
8789 carry = term / NBASE;
8790
8793 carry = term / NBASE;
8794
8797 carry = term / NBASE;
8798
8799 /* remaining digits, except for the first five */
8800 for (int i = var2ndigits - 1; i >= 4; i--)
8801 {
8803 res_digits[i + 1] = (NumericDigit) (term % NBASE);
8804 carry = term / NBASE;
8805 }
8806 break;
8807
8808 case 6:
8809 /* ---------
8810 * 6-digit case:
8811 * var1ndigits = 6
8812 * var2ndigits >= 6
8813 * res_ndigits = var2ndigits + 6
8814 * ----------
8815 */
8816 /* last five result digits */
8819 carry = term / NBASE;
8820
8823 carry = term / NBASE;
8824
8827 carry = term / NBASE;
8828
8831 carry = term / NBASE;
8832
8835 carry = term / NBASE;
8836
8837 /* remaining digits, except for the first six */
8838 for (int i = var2ndigits - 1; i >= 5; i--)
8839 {
8841 res_digits[i + 1] = (NumericDigit) (term % NBASE);
8842 carry = term / NBASE;
8843 }
8844 break;
8845 }
8846
8847 /*
8848 * Finally, for var1ndigits > 1, compute the remaining var1ndigits most
8849 * significant result digits.
8850 */
8851 switch (var1ndigits)
8852 {
8853 case 6:
8855 res_digits[5] = (NumericDigit) (term % NBASE);
8856 carry = term / NBASE;
8858 case 5:
8860 res_digits[4] = (NumericDigit) (term % NBASE);
8861 carry = term / NBASE;
8863 case 4:
8865 res_digits[3] = (NumericDigit) (term % NBASE);
8866 carry = term / NBASE;
8868 case 3:
8870 res_digits[2] = (NumericDigit) (term % NBASE);
8871 carry = term / NBASE;
8873 case 2:
8875 res_digits[1] = (NumericDigit) (term % NBASE);
8876 res_digits[0] = (NumericDigit) (term / NBASE);
8877 break;
8878 }
8879
8880 /* Store the product in result */
8881 digitbuf_free(result->buf);
8882 result->ndigits = res_ndigits;
8883 result->buf = res_buf;
8884 result->digits = res_digits;
8885 result->weight = res_weight;
8886 result->sign = res_sign;
8887 result->dscale = var1->dscale + var2->dscale;
8888
8889 /* Strip leading and trailing zeroes */
8891}
#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)
#define pg_fallthrough
Definition c.h:220

References Assert, digitbuf_alloc, digitbuf_free, fb(), i, NBASE, NUMERIC_NEG, NUMERIC_POS, pg_fallthrough, PRODSUM1, PRODSUM2, PRODSUM3, PRODSUM4, PRODSUM5, PRODSUM6, result, and strip_var().

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 if (!apply_typmod_special(num, typmod, fcinfo->context))
1250 }
1251
1252 /*
1253 * If the value isn't a valid type modifier, simply return a copy of the
1254 * input value
1255 */
1256 if (!is_valid_numeric_typmod(typmod))
1258
1259 /*
1260 * Get the precision and scale out of the typmod value
1261 */
1262 precision = numeric_typmod_precision(typmod);
1263 scale = numeric_typmod_scale(typmod);
1264 maxdigits = precision - scale;
1265
1266 /* The target display scale is non-negative */
1267 dscale = Max(scale, 0);
1268
1269 /*
1270 * If the number is certainly in bounds and due to the target scale no
1271 * rounding could be necessary, just make a copy of the input and modify
1272 * its scale fields, unless the larger scale forces us to abandon the
1273 * short representation. (Note we assume the existing dscale is
1274 * honest...)
1275 */
1276 ddigits = (NUMERIC_WEIGHT(num) + 1) * DEC_DIGITS;
1278 && (NUMERIC_CAN_BE_SHORT(dscale, NUMERIC_WEIGHT(num))
1279 || !NUMERIC_IS_SHORT(num)))
1280 {
1281 new = duplicate_numeric(num);
1282 if (NUMERIC_IS_SHORT(num))
1283 new->choice.n_short.n_header =
1285 | (dscale << NUMERIC_SHORT_DSCALE_SHIFT);
1286 else
1287 new->choice.n_long.n_sign_dscale = NUMERIC_SIGN(new) |
1288 ((uint16) dscale & NUMERIC_DSCALE_MASK);
1289 PG_RETURN_NUMERIC(new);
1290 }
1291
1292 /*
1293 * We really need to fiddle with things - unpack the number into a
1294 * variable and let apply_typmod() do it.
1295 */
1296 init_var(&var);
1297
1298 set_var_from_num(num, &var);
1299 if (!apply_typmod(&var, typmod, fcinfo->context))
1301 new = make_result_safe(&var, fcinfo->context);
1302
1303 free_var(&var);
1304
1305 PG_RETURN_NUMERIC(new);
1306}
static Numeric duplicate_numeric(Numeric num)
Definition numeric.c:7529
static bool apply_typmod_special(Numeric num, int32 typmod, Node *escontext)
Definition numeric.c:7742
static bool apply_typmod(NumericVar *var, int32 typmod, Node *escontext)
Definition numeric.c:7657
union NumericChoice choice
Definition numeric.c:160
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(), fb(), free_var(), init_var, is_valid_numeric_typmod(), make_result_safe(), 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_NULL, PG_RETURN_NUMERIC, scale, and set_var_from_num().

◆ numeric_abbrev_abort()

static bool numeric_abbrev_abort ( int  memtupcount,
SortSupport  ssup 
)
static

Definition at line 2219 of file numeric.c.

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

References elog, estimateHyperLogLog(), fb(), 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 2157 of file numeric.c.

2158{
2161 Numeric value;
2162 Datum result;
2163
2164 nss->input_count += 1;
2165
2166 /*
2167 * This is to handle packed datums without needing a palloc/pfree cycle;
2168 * we keep and reuse a buffer large enough to handle any short datum.
2169 */
2171 {
2172 void *buf = nss->buf;
2174
2176
2179
2180 value = (Numeric) buf;
2181 }
2182 else
2184
2186 {
2189 else if (NUMERIC_IS_NINF(value))
2191 else
2193 }
2194 else
2195 {
2196 NumericVar var;
2197
2198 init_var_from_num(value, &var);
2199
2201 }
2202
2203 /* should happen only for external/compressed toasts */
2206
2207 return result;
2208}
static Datum numeric_abbrev_convert_var(const NumericVar *var, NumericSortSupport *nss)
Definition numeric.c:2367
#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 @175 value
static Pointer DatumGetPointer(Datum X)
Definition postgres.h:332
#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, buf, DatumGetPointer(), fb(), init_var_from_num(), memcpy(), 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, result, 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 2367 of file numeric.c.

2368{
2369 int ndigits = var->ndigits;
2370 int weight = var->weight;
2371 int64 result;
2372
2373 if (ndigits == 0 || weight < -44)
2374 {
2375 result = 0;
2376 }
2377 else if (weight > 83)
2378 {
2380 }
2381 else
2382 {
2383 result = ((int64) (weight + 44) << 56);
2384
2385 switch (ndigits)
2386 {
2387 default:
2388 result |= ((int64) var->digits[3]);
2390 case 3:
2391 result |= ((int64) var->digits[2]) << 14;
2393 case 2:
2394 result |= ((int64) var->digits[1]) << 28;
2396 case 1:
2397 result |= ((int64) var->digits[0]) << 42;
2398 break;
2399 }
2400 }
2401
2402 /* the abbrev is negated relative to the original */
2403 if (var->sign == NUMERIC_POS)
2404 result = -result;
2405
2406 if (nss->estimating)
2407 {
2408 uint32 tmp = ((uint32) result
2409 ^ (uint32) ((uint64) result >> 32));
2410
2411 addHyperLogLog(&nss->abbr_card, DatumGetUInt32(hash_uint32(tmp)));
2412 }
2413
2415}
#define NumericAbbrevGetDatum(X)
Definition numeric.c:405
static Datum hash_uint32(uint32 k)
Definition hashfn.h:43
void addHyperLogLog(hyperLogLogState *cState, uint32 hash)
static uint32 DatumGetUInt32(Datum X)
Definition postgres.h:222

References addHyperLogLog(), DatumGetUInt32(), NumericVar::digits, fb(), hash_uint32(), NumericVar::ndigits, NUMERIC_POS, NumericAbbrevGetDatum, pg_fallthrough, PG_INT64_MAX, result, NumericVar::sign, and NumericVar::weight.

Referenced by numeric_abbrev_convert().

◆ numeric_abs()

Datum numeric_abs ( PG_FUNCTION_ARGS  )

Definition at line 1384 of file numeric.c.

1385{
1386 Numeric num = PG_GETARG_NUMERIC(0);
1387 Numeric res;
1388
1389 /*
1390 * Do it the easy way directly on the packed format
1391 */
1392 res = duplicate_numeric(num);
1393
1394 if (NUMERIC_IS_SHORT(num))
1395 res->choice.n_short.n_header =
1397 else if (NUMERIC_IS_SPECIAL(num))
1398 {
1399 /* This changes -Inf to Inf, and doesn't affect NaN */
1400 res->choice.n_short.n_header =
1402 }
1403 else
1405
1406 PG_RETURN_NUMERIC(res);
1407}
uint16 n_sign_dscale
Definition numeric.c:145
struct NumericLong n_long
Definition numeric.c:153

References NumericData::choice, duplicate_numeric(), fb(), 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 4984 of file numeric.c.

4985{
4987
4989
4990 /* Create the state data on the first call */
4991 if (state == NULL)
4992 state = makeNumericAggState(fcinfo, true);
4993
4994 if (!PG_ARGISNULL(1))
4996
4998}

References do_numeric_accum(), fb(), 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 5395 of file numeric.c.

5396{
5398
5400
5401 /* Should not get here with no state */
5402 if (state == NULL)
5403 elog(ERROR, "numeric_accum_inv called with NULL state");
5404
5405 if (!PG_ARGISNULL(1))
5406 {
5407 /* If we fail to perform the inverse transition, return NULL */
5410 }
5411
5413}

References do_numeric_discard(), elog, ERROR, fb(), 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 2872 of file numeric.c.

2873{
2876 Numeric res;
2877
2878 res = numeric_add_safe(num1, num2, NULL);
2879
2880 PG_RETURN_NUMERIC(res);
2881}
Numeric numeric_add_safe(Numeric num1, Numeric num2, Node *escontext)
Definition numeric.c:2889

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

2890{
2894 Numeric res;
2895
2896 /*
2897 * Handle NaN and infinities
2898 */
2900 {
2902 return make_result(&const_nan);
2903 if (NUMERIC_IS_PINF(num1))
2904 {
2905 if (NUMERIC_IS_NINF(num2))
2906 return make_result(&const_nan); /* Inf + -Inf */
2907 else
2908 return make_result(&const_pinf);
2909 }
2910 if (NUMERIC_IS_NINF(num1))
2911 {
2912 if (NUMERIC_IS_PINF(num2))
2913 return make_result(&const_nan); /* -Inf + Inf */
2914 else
2915 return make_result(&const_ninf);
2916 }
2917 /* by here, num1 must be finite, so num2 is not */
2918 if (NUMERIC_IS_PINF(num2))
2919 return make_result(&const_pinf);
2921 return make_result(&const_ninf);
2922 }
2923
2924 /*
2925 * Unpack the values, let add_var() compute the result and return it.
2926 */
2929
2930 init_var(&result);
2931 add_var(&arg1, &arg2, &result);
2932
2933 res = make_result_safe(&result, escontext);
2934
2935 free_var(&result);
2936
2937 return res;
2938}

References add_var(), Assert, const_nan, const_ninf, const_pinf, fb(), 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 result.

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

5955{
5957 Datum N_datum;
5960
5962
5963 /* If there were no non-null inputs, return NULL */
5964 if (state == NULL || NA_TOTAL_COUNT(state) == 0)
5966
5967 if (state->NaNcount > 0) /* there was at least one NaN input */
5969
5970 /* adding plus and minus infinities gives NaN */
5971 if (state->pInfcount > 0 && state->nInfcount > 0)
5973 if (state->pInfcount > 0)
5975 if (state->nInfcount > 0)
5977
5979
5981 accum_sum_final(&state->sumX, &sumX_var);
5984
5986}
#define NA_TOTAL_COUNT(na)
Definition numeric.c:4773

References accum_sum_final(), const_nan, const_ninf, const_pinf, DirectFunctionCall2, fb(), 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 5076 of file numeric.c.

5077{
5079
5081
5082 /* Create the state data on the first call */
5083 if (state == NULL)
5084 state = makeNumericAggState(fcinfo, false);
5085
5086 if (!PG_ARGISNULL(1))
5088
5090}

References do_numeric_accum(), fb(), 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 5096 of file numeric.c.

5097{
5100 MemoryContext agg_context;
5102
5103 if (!AggCheckCallContext(fcinfo, &agg_context))
5104 elog(ERROR, "aggregate function called in non-aggregate context");
5105
5108
5109 if (state2 == NULL)
5111
5112 /* manually copy all fields from state2 to state1 */
5113 if (state1 == NULL)
5114 {
5115 old_context = MemoryContextSwitchTo(agg_context);
5116
5118 state1->N = state2->N;
5119 state1->NaNcount = state2->NaNcount;
5120 state1->pInfcount = state2->pInfcount;
5121 state1->nInfcount = state2->nInfcount;
5122 state1->maxScale = state2->maxScale;
5123 state1->maxScaleCount = state2->maxScaleCount;
5124
5125 accum_sum_copy(&state1->sumX, &state2->sumX);
5126
5128
5130 }
5131
5132 state1->N += state2->N;
5133 state1->NaNcount += state2->NaNcount;
5134 state1->pInfcount += state2->pInfcount;
5135 state1->nInfcount += state2->nInfcount;
5136
5137 if (state2->N > 0)
5138 {
5139 /*
5140 * These are currently only needed for moving aggregates, but let's do
5141 * the right thing anyway...
5142 */
5143 if (state2->maxScale > state1->maxScale)
5144 {
5145 state1->maxScale = state2->maxScale;
5146 state1->maxScaleCount = state2->maxScaleCount;
5147 }
5148 else if (state2->maxScale == state1->maxScale)
5149 state1->maxScaleCount += state2->maxScaleCount;
5150
5151 /* The rest of this needs to work in the aggregate context */
5152 old_context = MemoryContextSwitchTo(agg_context);
5153
5154 /* Accumulate sums */
5155 accum_sum_combine(&state1->sumX, &state2->sumX);
5156
5158 }
5160}
static NumericAggState * makeNumericAggStateCurrentContext(bool calcSumX2)
Definition numeric.c:4806
static void accum_sum_combine(NumericSumAccum *accum, NumericSumAccum *accum2)
Definition numeric.c:12159
static void accum_sum_copy(NumericSumAccum *dst, NumericSumAccum *src)
Definition numeric.c:12142

References accum_sum_combine(), accum_sum_copy(), AggCheckCallContext(), elog, ERROR, fb(), makeNumericAggStateCurrentContext(), MemoryContextSwitchTo(), PG_ARGISNULL, PG_GETARG_POINTER, and PG_RETURN_POINTER.

◆ numeric_avg_deserialize()

Datum numeric_avg_deserialize ( PG_FUNCTION_ARGS  )

Definition at line 5220 of file numeric.c.

5221{
5222 bytea *sstate;
5226
5227 if (!AggCheckCallContext(fcinfo, NULL))
5228 elog(ERROR, "aggregate function called in non-aggregate context");
5229
5230 sstate = PG_GETARG_BYTEA_PP(0);
5231
5232 init_var(&tmp_var);
5233
5234 /*
5235 * Initialize a StringInfo so that we can "receive" it using the standard
5236 * recv-function infrastructure.
5237 */
5239 VARSIZE_ANY_EXHDR(sstate));
5240
5242
5243 /* N */
5244 result->N = pq_getmsgint64(&buf);
5245
5246 /* sumX */
5248 accum_sum_add(&(result->sumX), &tmp_var);
5249
5250 /* maxScale */
5251 result->maxScale = pq_getmsgint(&buf, 4);
5252
5253 /* maxScaleCount */
5254 result->maxScaleCount = pq_getmsgint64(&buf);
5255
5256 /* NaNcount */
5257 result->NaNcount = pq_getmsgint64(&buf);
5258
5259 /* pInfcount */
5260 result->pInfcount = pq_getmsgint64(&buf);
5261
5262 /* nInfcount */
5263 result->nInfcount = pq_getmsgint64(&buf);
5264
5265 pq_getmsgend(&buf);
5266
5267 free_var(&tmp_var);
5268
5270}
static void numericvar_deserialize(StringInfo buf, NumericVar *var)
Definition numeric.c:7506
unsigned int pq_getmsgint(StringInfo msg, int b)
Definition pqformat.c:414

References accum_sum_add(), AggCheckCallContext(), buf, elog, ERROR, fb(), free_var(), init_var, initReadOnlyStringInfo(), makeNumericAggStateCurrentContext(), numericvar_deserialize(), PG_GETARG_BYTEA_PP, PG_RETURN_POINTER, pq_getmsgend(), pq_getmsgint(), pq_getmsgint64(), result, VARDATA_ANY(), and VARSIZE_ANY_EXHDR().

◆ numeric_avg_serialize()

Datum numeric_avg_serialize ( PG_FUNCTION_ARGS  )

Definition at line 5168 of file numeric.c.

5169{
5172 bytea *result;
5174
5175 /* Ensure we disallow calling when not in aggregate context */
5176 if (!AggCheckCallContext(fcinfo, NULL))
5177 elog(ERROR, "aggregate function called in non-aggregate context");
5178
5180
5181 init_var(&tmp_var);
5182
5184
5185 /* N */
5186 pq_sendint64(&buf, state->N);
5187
5188 /* sumX */
5189 accum_sum_final(&state->sumX, &tmp_var);
5191
5192 /* maxScale */
5193 pq_sendint32(&buf, state->maxScale);
5194
5195 /* maxScaleCount */
5196 pq_sendint64(&buf, state->maxScaleCount);
5197
5198 /* NaNcount */
5199 pq_sendint64(&buf, state->NaNcount);
5200
5201 /* pInfcount */
5202 pq_sendint64(&buf, state->pInfcount);
5203
5204 /* nInfcount */
5205 pq_sendint64(&buf, state->nInfcount);
5206
5208
5209 free_var(&tmp_var);
5210
5212}
static void numericvar_serialize(StringInfo buf, const NumericVar *var)
Definition numeric.c:7490
static void pq_sendint32(StringInfo buf, uint32 i)
Definition pqformat.h:144

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

◆ numeric_ceil()

Datum numeric_ceil ( PG_FUNCTION_ARGS  )

Definition at line 1638 of file numeric.c.

1639{
1640 Numeric num = PG_GETARG_NUMERIC(0);
1641 Numeric res;
1643
1644 /*
1645 * Handle NaN and infinities
1646 */
1647 if (NUMERIC_IS_SPECIAL(num))
1649
1652
1653 res = make_result(&result);
1654 free_var(&result);
1655
1656 PG_RETURN_NUMERIC(res);
1657}
static void ceil_var(const NumericVar *var, NumericVar *result)
Definition numeric.c:9850

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

Referenced by executeItemOptUnwrapTarget().

◆ numeric_cmp()

Datum numeric_cmp ( PG_FUNCTION_ARGS  )

Definition at line 2423 of file numeric.c.

2424{
2427 int result;
2428
2430
2433
2435}
static int cmp_numerics(Numeric num1, Numeric num2)
Definition numeric.c:2529
#define PG_RETURN_INT32(x)
Definition fmgr.h:355

References cmp_numerics(), fb(), PG_FREE_IF_COPY, PG_GETARG_NUMERIC, PG_RETURN_INT32, and result.

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

2309{
2310 /*
2311 * NOTE WELL: this is intentionally backwards, because the abbreviation is
2312 * negated relative to the original value, to handle NaN/infinity cases.
2313 */
2315 return 1;
2317 return -1;
2318 return 0;
2319}
#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 5004 of file numeric.c.

5005{
5008 MemoryContext agg_context;
5010
5011 if (!AggCheckCallContext(fcinfo, &agg_context))
5012 elog(ERROR, "aggregate function called in non-aggregate context");
5013
5016
5017 if (state2 == NULL)
5019
5020 /* manually copy all fields from state2 to state1 */
5021 if (state1 == NULL)
5022 {
5023 old_context = MemoryContextSwitchTo(agg_context);
5024
5026 state1->N = state2->N;
5027 state1->NaNcount = state2->NaNcount;
5028 state1->pInfcount = state2->pInfcount;
5029 state1->nInfcount = state2->nInfcount;
5030 state1->maxScale = state2->maxScale;
5031 state1->maxScaleCount = state2->maxScaleCount;
5032
5033 accum_sum_copy(&state1->sumX, &state2->sumX);
5034 accum_sum_copy(&state1->sumX2, &state2->sumX2);
5035
5037
5039 }
5040
5041 state1->N += state2->N;
5042 state1->NaNcount += state2->NaNcount;
5043 state1->pInfcount += state2->pInfcount;
5044 state1->nInfcount += state2->nInfcount;
5045
5046 if (state2->N > 0)
5047 {
5048 /*
5049 * These are currently only needed for moving aggregates, but let's do
5050 * the right thing anyway...
5051 */
5052 if (state2->maxScale > state1->maxScale)
5053 {
5054 state1->maxScale = state2->maxScale;
5055 state1->maxScaleCount = state2->maxScaleCount;
5056 }
5057 else if (state2->maxScale == state1->maxScale)
5058 state1->maxScaleCount += state2->maxScaleCount;
5059
5060 /* The rest of this needs to work in the aggregate context */
5061 old_context = MemoryContextSwitchTo(agg_context);
5062
5063 /* Accumulate sums */
5064 accum_sum_combine(&state1->sumX, &state2->sumX);
5065 accum_sum_combine(&state1->sumX2, &state2->sumX2);
5066
5068 }
5070}

References accum_sum_combine(), accum_sum_copy(), AggCheckCallContext(), elog, ERROR, fb(), makeNumericAggStateCurrentContext(), MemoryContextSwitchTo(), PG_ARGISNULL, PG_GETARG_POINTER, and PG_RETURN_POINTER.

◆ numeric_deserialize()

Datum numeric_deserialize ( PG_FUNCTION_ARGS  )

Definition at line 5334 of file numeric.c.

5335{
5336 bytea *sstate;
5340
5341 if (!AggCheckCallContext(fcinfo, NULL))
5342 elog(ERROR, "aggregate function called in non-aggregate context");
5343
5344 sstate = PG_GETARG_BYTEA_PP(0);
5345
5346 init_var(&tmp_var);
5347
5348 /*
5349 * Initialize a StringInfo so that we can "receive" it using the standard
5350 * recv-function infrastructure.
5351 */
5353 VARSIZE_ANY_EXHDR(sstate));
5354
5356
5357 /* N */
5358 result->N = pq_getmsgint64(&buf);
5359
5360 /* sumX */
5362 accum_sum_add(&(result->sumX), &tmp_var);
5363
5364 /* sumX2 */
5366 accum_sum_add(&(result->sumX2), &tmp_var);
5367
5368 /* maxScale */
5369 result->maxScale = pq_getmsgint(&buf, 4);
5370
5371 /* maxScaleCount */
5372 result->maxScaleCount = pq_getmsgint64(&buf);
5373
5374 /* NaNcount */
5375 result->NaNcount = pq_getmsgint64(&buf);
5376
5377 /* pInfcount */
5378 result->pInfcount = pq_getmsgint64(&buf);
5379
5380 /* nInfcount */
5381 result->nInfcount = pq_getmsgint64(&buf);
5382
5383 pq_getmsgend(&buf);
5384
5385 free_var(&tmp_var);
5386
5388}

References accum_sum_add(), AggCheckCallContext(), buf, elog, ERROR, fb(), free_var(), init_var, initReadOnlyStringInfo(), makeNumericAggStateCurrentContext(), numericvar_deserialize(), PG_GETARG_BYTEA_PP, PG_RETURN_POINTER, pq_getmsgend(), pq_getmsgint(), pq_getmsgint64(), result, VARDATA_ANY(), and VARSIZE_ANY_EXHDR().

◆ numeric_div()

Datum numeric_div ( PG_FUNCTION_ARGS  )

Definition at line 3145 of file numeric.c.

3146{
3149 Numeric res;
3150
3151 res = numeric_div_safe(num1, num2, NULL);
3152
3153 PG_RETURN_NUMERIC(res);
3154}
Numeric numeric_div_safe(Numeric num1, Numeric num2, Node *escontext)
Definition numeric.c:3163

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

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

References Assert, const_nan, const_ninf, const_pinf, const_zero, div_var(), ereturn, errcode(), errmsg, fb(), 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, numeric_sign_internal(), result, and select_div_scale().

Referenced by executeItemOptUnwrapTarget(), numeric_div(), timestamp_part_common(), and timestamptz_part_common().

◆ numeric_div_trunc()

Datum numeric_div_trunc ( PG_FUNCTION_ARGS  )

Definition at line 3259 of file numeric.c.

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

References Assert, const_nan, const_ninf, const_pinf, const_zero, div_var(), ereport, errcode(), errmsg, ERROR, fb(), free_var(), init_var, init_var_from_num(), make_result(), NUMERIC_IS_NAN, NUMERIC_IS_NINF, NUMERIC_IS_PINF, NUMERIC_IS_SPECIAL, numeric_sign_internal(), PG_GETARG_NUMERIC, PG_RETURN_NUMERIC, and result.

Referenced by numeric_half_rounded(), and numeric_truncated_divide().

◆ numeric_eq()

Datum numeric_eq ( PG_FUNCTION_ARGS  )

Definition at line 2439 of file numeric.c.

2440{
2443 bool result;
2444
2445 result = cmp_numerics(num1, num2) == 0;
2446
2449
2451}

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

Referenced by equalsJsonbScalarValue(), and gbt_numeric_eq().

◆ numeric_exp()

Datum numeric_exp ( PG_FUNCTION_ARGS  )

Definition at line 3735 of file numeric.c.

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

References arg, const_zero, duplicate_numeric(), exp_var(), fb(), 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, result, and val.

◆ numeric_fac()

Datum numeric_fac ( PG_FUNCTION_ARGS  )

Definition at line 3611 of file numeric.c.

3612{
3613 int64 num = PG_GETARG_INT64(0);
3614 Numeric res;
3617
3618 if (num < 0)
3619 ereport(ERROR,
3621 errmsg("factorial of a negative number is undefined")));
3622 if (num <= 1)
3623 {
3624 res = make_result(&const_one);
3625 PG_RETURN_NUMERIC(res);
3626 }
3627 /* Fail immediately if the result would overflow */
3628 if (num > 32177)
3629 ereport(ERROR,
3631 errmsg("value overflows numeric format")));
3632
3633 init_var(&fact);
3634 init_var(&result);
3635
3637
3638 for (num = num - 1; num > 1; num--)
3639 {
3640 /* this loop can take awhile, so allow it to be interrupted */
3642
3644
3645 mul_var(&result, &fact, &result, 0);
3646 }
3647
3648 res = make_result(&result);
3649
3650 free_var(&fact);
3651 free_var(&result);
3652
3653 PG_RETURN_NUMERIC(res);
3654}

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

◆ numeric_fast_cmp()

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

Definition at line 2286 of file numeric.c.

2287{
2290 int result;
2291
2293
2294 if (nx != DatumGetPointer(x))
2295 pfree(nx);
2296 if (ny != DatumGetPointer(y))
2297 pfree(ny);
2298
2299 return result;
2300}

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

Referenced by numeric_sortsupport().

◆ numeric_float4()

Datum numeric_float4 ( PG_FUNCTION_ARGS  )

Definition at line 4679 of file numeric.c.

4680{
4681 Numeric num = PG_GETARG_NUMERIC(0);
4682 char *tmp;
4683 Datum result;
4684
4685 if (NUMERIC_IS_SPECIAL(num))
4686 {
4687 if (NUMERIC_IS_PINF(num))
4689 else if (NUMERIC_IS_NINF(num))
4691 else
4693 }
4694
4696 NumericGetDatum(num)));
4697
4699 InvalidOid, -1,
4700 (Node *) fcinfo->context,
4701 &result))
4702 {
4703 pfree(tmp);
4705 }
4706
4707 pfree(tmp);
4708
4710}
Datum numeric_out(PG_FUNCTION_ARGS)
Definition numeric.c:799
Datum float4in(PG_FUNCTION_ARGS)
Definition float.c:205
static float4 get_float4_infinity(void)
Definition float.h:61
static float4 get_float4_nan(void)
Definition float.h:80
bool DirectInputFunctionCallSafe(PGFunction func, char *str, Oid typioparam, int32 typmod, Node *escontext, Datum *result)
Definition fmgr.c:1641
#define DirectFunctionCall1(func, arg1)
Definition fmgr.h:688
#define PG_RETURN_FLOAT4(x)
Definition fmgr.h:368
static char * DatumGetCString(Datum X)
Definition postgres.h:365
#define InvalidOid

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

Referenced by jsonb_float4().

◆ numeric_float8()

Datum numeric_float8 ( PG_FUNCTION_ARGS  )

Definition at line 4580 of file numeric.c.

4581{
4582 Numeric num = PG_GETARG_NUMERIC(0);
4583 char *tmp;
4584 Datum result;
4585
4586 if (NUMERIC_IS_SPECIAL(num))
4587 {
4588 if (NUMERIC_IS_PINF(num))
4590 else if (NUMERIC_IS_NINF(num))
4592 else
4594 }
4595
4597 NumericGetDatum(num)));
4599 InvalidOid, -1,
4600 (Node *) fcinfo->context,
4601 &result))
4602 {
4603 pfree(tmp);
4605 }
4606
4608}
Datum float8in(PG_FUNCTION_ARGS)
Definition float.c:405
static float8 get_float8_infinity(void)
Definition float.h:68
static float8 get_float8_nan(void)
Definition float.h:87
#define PG_RETURN_FLOAT8(x)
Definition fmgr.h:369

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

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

4618{
4619 Numeric num = PG_GETARG_NUMERIC(0);
4620 double val;
4621
4622 if (NUMERIC_IS_SPECIAL(num))
4623 {
4624 if (NUMERIC_IS_PINF(num))
4625 val = HUGE_VAL;
4626 else if (NUMERIC_IS_NINF(num))
4627 val = -HUGE_VAL;
4628 else
4629 val = get_float8_nan();
4630 }
4631 else
4632 {
4633 NumericVar x;
4634
4635 init_var_from_num(num, &x);
4637 }
4638
4640}

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

1667{
1668 Numeric num = PG_GETARG_NUMERIC(0);
1669 Numeric res;
1671
1672 /*
1673 * Handle NaN and infinities
1674 */
1675 if (NUMERIC_IS_SPECIAL(num))
1677
1680
1681 res = make_result(&result);
1682 free_var(&result);
1683
1684 PG_RETURN_NUMERIC(res);
1685}
static void floor_var(const NumericVar *var, NumericVar *result)
Definition numeric.c:9874

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

Referenced by executeItemOptUnwrapTarget().

◆ numeric_gcd()

Datum numeric_gcd ( PG_FUNCTION_ARGS  )

Definition at line 3508 of file numeric.c.

3509{
3515 Numeric res;
3516
3517 /*
3518 * Handle NaN and infinities: we consider the result to be NaN in all such
3519 * cases.
3520 */
3523
3524 /*
3525 * Unpack the arguments
3526 */
3529
3530 init_var(&result);
3531
3532 /*
3533 * Find the GCD and return the result
3534 */
3535 gcd_var(&arg1, &arg2, &result);
3536
3537 res = make_result(&result);
3538
3539 free_var(&result);
3540
3541 PG_RETURN_NUMERIC(res);
3542}
static void gcd_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition numeric.c:9897

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

◆ numeric_ge()

Datum numeric_ge ( PG_FUNCTION_ARGS  )

Definition at line 2484 of file numeric.c.

2485{
2488 bool result;
2489
2490 result = cmp_numerics(num1, num2) >= 0;
2491
2494
2496}

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

Referenced by gbt_numeric_ge(), and numeric_half_rounded().

◆ numeric_gt()

Datum numeric_gt ( PG_FUNCTION_ARGS  )

Definition at line 2469 of file numeric.c.

2470{
2473 bool result;
2474
2475 result = cmp_numerics(num1, num2) > 0;
2476
2479
2481}

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

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
786 ereturn(escontext, (Datum) 0,
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:7008
#define PG_GETARG_OID(n)
Definition fmgr.h:275
#define PG_GETARG_CSTRING(n)
Definition fmgr.h:278
int pg_strncasecmp(const char *s1, const char *s2, size_t n)
unsigned int Oid

References apply_typmod(), apply_typmod_special(), const_nan, const_ninf, const_pinf, ereturn, errcode(), errmsg, fb(), 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 3424 of file numeric.c.

3425{
3426 Numeric num = PG_GETARG_NUMERIC(0);
3428 Numeric res;
3429
3430 /*
3431 * Handle NaN and infinities
3432 */
3433 if (NUMERIC_IS_SPECIAL(num))
3435
3436 /*
3437 * Compute the result and return it
3438 */
3439 init_var_from_num(num, &arg);
3440
3441 add_var(&arg, &const_one, &arg);
3442
3443 res = make_result(&arg);
3444
3445 free_var(&arg);
3446
3447 PG_RETURN_NUMERIC(res);
3448}

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

4505{
4506 Numeric num = PG_GETARG_NUMERIC(0);
4507 NumericVar x;
4508 int64 val;
4509 int16 result;
4510
4511 if (NUMERIC_IS_SPECIAL(num))
4512 {
4513 if (NUMERIC_IS_NAN(num))
4514 ereturn(fcinfo->context, (Datum) 0,
4516 errmsg("cannot convert NaN to %s", "smallint")));
4517 else
4518 ereturn(fcinfo->context, (Datum) 0,
4520 errmsg("cannot convert infinity to %s", "smallint")));
4521 }
4522
4523 /* Convert to variable format and thence to int8 */
4524 init_var_from_num(num, &x);
4525
4526 if (!numericvar_to_int64(&x, &val))
4527 ereturn(fcinfo->context, (Datum) 0,
4529 errmsg("smallint out of range")));
4530
4532 ereturn(fcinfo->context, (Datum) 0,
4534 errmsg("smallint out of range")));
4535
4536 /* Down-convert to int2 */
4537 result = (int16) val;
4538
4540}
static bool numericvar_to_int64(const NumericVar *var, int64 *result)
Definition numeric.c:7779
#define PG_INT16_MIN
Definition c.h:728
#define PG_INT16_MAX
Definition c.h:729
#define PG_RETURN_INT16(x)
Definition fmgr.h:357

References ereturn, errcode(), errmsg, fb(), 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, result, unlikely, val, and x.

Referenced by jsonb_int2().

◆ numeric_int4()

Datum numeric_int4 ( PG_FUNCTION_ARGS  )

Definition at line 4404 of file numeric.c.

4405{
4406 Numeric num = PG_GETARG_NUMERIC(0);
4407 int32 result;
4408
4409 result = numeric_int4_safe(num, fcinfo->context);
4410
4411 if (unlikely(SOFT_ERROR_OCCURRED(fcinfo->context)))
4413
4415}
int32 numeric_int4_safe(Numeric num, Node *escontext)
Definition numeric.c:4375
#define SOFT_ERROR_OCCURRED(escontext)
Definition miscnodes.h:53

References numeric_int4_safe(), PG_GETARG_NUMERIC, PG_RETURN_INT32, PG_RETURN_NULL, result, SOFT_ERROR_OCCURRED, and unlikely.

Referenced by jsonb_int4().

◆ numeric_int4_safe()

int32 numeric_int4_safe ( Numeric  num,
Node escontext 
)

Definition at line 4375 of file numeric.c.

4376{
4377 NumericVar x;
4378 int32 result;
4379
4380 if (NUMERIC_IS_SPECIAL(num))
4381 {
4382 if (NUMERIC_IS_NAN(num))
4383 ereturn(escontext, 0,
4385 errmsg("cannot convert NaN to %s", "integer")));
4386 else
4387 ereturn(escontext, 0,
4389 errmsg("cannot convert infinity to %s", "integer")));
4390 }
4391
4392 /* Convert to variable format, then convert to int4 */
4393 init_var_from_num(num, &x);
4394
4395 if (!numericvar_to_int32(&x, &result))
4396 ereturn(escontext, 0,
4398 errmsg("integer out of range")));
4399
4400 return result;
4401}
static bool numericvar_to_int32(const NumericVar *var, int32 *result)
Definition numeric.c:4423

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

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

◆ numeric_int8()

Datum numeric_int8 ( PG_FUNCTION_ARGS  )

Definition at line 4480 of file numeric.c.

4481{
4482 Numeric num = PG_GETARG_NUMERIC(0);
4483 int64 result;
4484
4485 result = numeric_int8_safe(num, fcinfo->context);
4486
4487 if (unlikely(SOFT_ERROR_OCCURRED(fcinfo->context)))
4489
4491}
int64 numeric_int8_safe(Numeric num, Node *escontext)
Definition numeric.c:4451

References numeric_int8_safe(), PG_GETARG_NUMERIC, PG_RETURN_INT64, PG_RETURN_NULL, result, SOFT_ERROR_OCCURRED, and unlikely.

Referenced by jsonb_int8(), and pg_size_bytes().

◆ numeric_int8_safe()

int64 numeric_int8_safe ( Numeric  num,
Node escontext 
)

Definition at line 4451 of file numeric.c.

4452{
4453 NumericVar x;
4454 int64 result;
4455
4456 if (NUMERIC_IS_SPECIAL(num))
4457 {
4458 if (NUMERIC_IS_NAN(num))
4459 ereturn(escontext, 0,
4461 errmsg("cannot convert NaN to %s", "bigint")));
4462 else
4463 ereturn(escontext, 0,
4465 errmsg("cannot convert infinity to %s", "bigint")));
4466 }
4467
4468 /* Convert to variable format, then convert to int8 */
4469 init_var_from_num(num, &x);
4470
4471 if (!numericvar_to_int64(&x, &result))
4472 ereturn(escontext, 0,
4474 errmsg("bigint out of range")));
4475
4476 return result;
4477}

References ereturn, errcode(), errmsg, fb(), init_var_from_num(), NUMERIC_IS_NAN, NUMERIC_IS_SPECIAL, numericvar_to_int64(), result, and x.

Referenced by executeItemOptUnwrapTarget(), numeric_cash(), and numeric_int8().

◆ numeric_is_inf()

bool numeric_is_inf ( Numeric  num)

Definition at line 845 of file numeric.c.

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

References NUMERIC_IS_INF.

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

◆ numeric_is_integral()

static bool numeric_is_integral ( Numeric  num)
static

Definition at line 856 of file numeric.c.

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

References arg, init_var_from_num(), NUMERIC_IS_NAN, and NUMERIC_IS_SPECIAL.

Referenced by numeric_power().

◆ numeric_is_nan()

bool numeric_is_nan ( Numeric  num)

◆ numeric_larger()

Datum numeric_larger ( PG_FUNCTION_ARGS  )

Definition at line 3479 of file numeric.c.

3480{
3483
3484 /*
3485 * Use cmp_numerics so that this will agree with the comparison operators,
3486 * particularly as regards comparisons involving NaN.
3487 */
3488 if (cmp_numerics(num1, num2) > 0)
3490 else
3492}

References cmp_numerics(), fb(), PG_GETARG_NUMERIC, and PG_RETURN_NUMERIC.

◆ numeric_lcm()

Datum numeric_lcm ( PG_FUNCTION_ARGS  )

Definition at line 3551 of file numeric.c.

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

References const_nan, const_zero, div_var(), fb(), free_var(), gcd_var(), init_var, init_var_from_num(), make_result(), Max, mul_var(), NUMERIC_IS_SPECIAL, NUMERIC_POS, PG_GETARG_NUMERIC, PG_RETURN_NUMERIC, result, and set_var_from_var().

◆ numeric_le()

Datum numeric_le ( PG_FUNCTION_ARGS  )

Definition at line 2514 of file numeric.c.

2515{
2518 bool result;
2519
2520 result = cmp_numerics(num1, num2) <= 0;
2521
2524
2526}

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

Referenced by brin_minmax_multi_distance_numeric(), and gbt_numeric_le().

◆ numeric_ln()

Datum numeric_ln ( PG_FUNCTION_ARGS  )

Definition at line 3802 of file numeric.c.

3803{
3804 Numeric num = PG_GETARG_NUMERIC(0);
3805 Numeric res;
3808 int ln_dweight;
3809 int rscale;
3810
3811 /*
3812 * Handle NaN and infinities
3813 */
3814 if (NUMERIC_IS_SPECIAL(num))
3815 {
3816 if (NUMERIC_IS_NINF(num))
3817 ereport(ERROR,
3819 errmsg("cannot take logarithm of a negative number")));
3820 /* For NAN or PINF, just duplicate the input */
3822 }
3823
3824 init_var_from_num(num, &arg);
3825 init_var(&result);
3826
3827 /* Estimated dweight of logarithm */
3829
3831 rscale = Max(rscale, arg.dscale);
3832 rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
3833 rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
3834
3835 ln_var(&arg, &result, rscale);
3836
3837 res = make_result(&result);
3838
3839 free_var(&result);
3840
3841 PG_RETURN_NUMERIC(res);
3842}

References arg, duplicate_numeric(), ereport, errcode(), errmsg, ERROR, estimate_ln_dweight(), fb(), free_var(), init_var, init_var_from_num(), ln_var(), make_result(), Max, Min, NUMERIC_IS_NINF, NUMERIC_IS_SPECIAL, NUMERIC_MAX_DISPLAY_SCALE, NUMERIC_MIN_DISPLAY_SCALE, NUMERIC_MIN_SIG_DIGITS, PG_GETARG_NUMERIC, PG_RETURN_NUMERIC, and result.

◆ numeric_log()

Datum numeric_log ( PG_FUNCTION_ARGS  )

Definition at line 3851 of file numeric.c.

3852{
3855 Numeric res;
3859
3860 /*
3861 * Handle NaN and infinities
3862 */
3864 {
3865 int sign1,
3866 sign2;
3867
3870 /* fail on negative inputs including -Inf, as log_var would */
3873 if (sign1 < 0 || sign2 < 0)
3874 ereport(ERROR,
3876 errmsg("cannot take logarithm of a negative number")));
3877 /* fail on zero inputs, as log_var would */
3878 if (sign1 == 0 || sign2 == 0)
3879 ereport(ERROR,
3881 errmsg("cannot take logarithm of zero")));
3882 if (NUMERIC_IS_PINF(num1))
3883 {
3884 /* log(Inf, Inf) reduces to Inf/Inf, so it's NaN */
3885 if (NUMERIC_IS_PINF(num2))
3887 /* log(Inf, finite-positive) is zero (we don't throw underflow) */
3889 }
3891 /* log(finite-positive, Inf) is Inf */
3893 }
3894
3895 /*
3896 * Initialize things
3897 */
3900 init_var(&result);
3901
3902 /*
3903 * Call log_var() to compute and return the result; note it handles scale
3904 * selection itself.
3905 */
3906 log_var(&arg1, &arg2, &result);
3907
3908 res = make_result(&result);
3909
3910 free_var(&result);
3911
3912 PG_RETURN_NUMERIC(res);
3913}
static void log_var(const NumericVar *base, const NumericVar *num, NumericVar *result)
Definition numeric.c:10776

References Assert, const_nan, const_pinf, const_zero, ereport, errcode(), errmsg, ERROR, fb(), free_var(), init_var, init_var_from_num(), log_var(), make_result(), NUMERIC_IS_NAN, NUMERIC_IS_PINF, NUMERIC_IS_SPECIAL, numeric_sign_internal(), PG_GETARG_NUMERIC, PG_RETURN_NUMERIC, and result.

◆ numeric_lt()

Datum numeric_lt ( PG_FUNCTION_ARGS  )

Definition at line 2499 of file numeric.c.

2500{
2503 bool result;
2504
2505 result = cmp_numerics(num1, num2) < 0;
2506
2509
2511}

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

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

4175{
4176 Numeric num = PG_GETARG_NUMERIC(0);
4178 int min_scale;
4179
4180 if (NUMERIC_IS_SPECIAL(num))
4182
4183 init_var_from_num(num, &arg);
4185 free_var(&arg);
4186
4188}
static int get_min_scale(NumericVar *var)
Definition numeric.c:4123

References arg, fb(), free_var(), get_min_scale(), init_var_from_num(), NUMERIC_IS_SPECIAL, PG_GETARG_NUMERIC, PG_RETURN_INT32, and PG_RETURN_NULL.

◆ numeric_mod()

Datum numeric_mod ( PG_FUNCTION_ARGS  )

Definition at line 3348 of file numeric.c.

3349{
3352 Numeric res;
3353
3354 res = numeric_mod_safe(num1, num2, NULL);
3355
3356 PG_RETURN_NUMERIC(res);
3357}
Numeric numeric_mod_safe(Numeric num1, Numeric num2, Node *escontext)
Definition numeric.c:3366

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

3367{
3368 Numeric res;
3372
3373 /*
3374 * Handle NaN and infinities. We follow POSIX fmod() on this, except that
3375 * POSIX treats x-is-infinite and y-is-zero identically, raising EDOM and
3376 * returning NaN. We choose to throw error only for y-is-zero.
3377 */
3379 {
3381 return make_result(&const_nan);
3382 if (NUMERIC_IS_INF(num1))
3383 {
3384 if (numeric_sign_internal(num2) == 0)
3385 goto division_by_zero;
3386
3387 /* Inf % any nonzero = NaN */
3388 return make_result(&const_nan);
3389 }
3390 /* num2 must be [-]Inf; result is num1 regardless of sign of num2 */
3391 return duplicate_numeric(num1);
3392 }
3393
3396
3397 init_var(&result);
3398
3399 /* Check for division by zero */
3400 if (arg2.ndigits == 0 || arg2.digits[0] == 0)
3401 goto division_by_zero;
3402
3403 mod_var(&arg1, &arg2, &result);
3404
3405 res = make_result_safe(&result, escontext);
3406
3407 free_var(&result);
3408
3409 return res;
3410
3412 ereturn(escontext, NULL,
3414 errmsg("division by zero"));
3415}

References const_nan, duplicate_numeric(), ereturn, errcode(), errmsg, fb(), free_var(), init_var, init_var_from_num(), make_result(), make_result_safe(), mod_var(), NUMERIC_IS_INF, NUMERIC_IS_NAN, NUMERIC_IS_SPECIAL, numeric_sign_internal(), and result.

Referenced by executeItemOptUnwrapTarget(), and numeric_mod().

◆ numeric_mul()

Datum numeric_mul ( PG_FUNCTION_ARGS  )

Definition at line 3023 of file numeric.c.

3024{
3027 Numeric res;
3028
3029 res = numeric_mul_safe(num1, num2, fcinfo->context);
3030
3031 if (unlikely(SOFT_ERROR_OCCURRED(fcinfo->context)))
3033
3034 PG_RETURN_NUMERIC(res);
3035}
Numeric numeric_mul_safe(Numeric num1, Numeric num2, Node *escontext)
Definition numeric.c:3044

References fb(), numeric_mul_safe(), PG_GETARG_NUMERIC, PG_RETURN_NULL, PG_RETURN_NUMERIC, SOFT_ERROR_OCCURRED, and unlikely.

Referenced by 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 3044 of file numeric.c.

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

References Assert, const_nan, const_ninf, const_pinf, fb(), 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(), result, and round_var().

Referenced by executeItemOptUnwrapTarget(), numeric_cash(), and numeric_mul().

◆ numeric_ne()

Datum numeric_ne ( PG_FUNCTION_ARGS  )

Definition at line 2454 of file numeric.c.

2455{
2458 bool result;
2459
2460 result = cmp_numerics(num1, num2) != 0;
2461
2464
2466}

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

◆ 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:1910

References fb(), 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:364

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

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

4715{
4716 Numeric num = PG_GETARG_NUMERIC(0);
4717 NumericVar x;
4719
4720 if (NUMERIC_IS_SPECIAL(num))
4721 {
4722 if (NUMERIC_IS_NAN(num))
4723 ereport(ERROR,
4725 errmsg("cannot convert NaN to %s", "pg_lsn")));
4726 else
4727 ereport(ERROR,
4729 errmsg("cannot convert infinity to %s", "pg_lsn")));
4730 }
4731
4732 /* Convert to variable format and thence to pg_lsn */
4733 init_var_from_num(num, &x);
4734
4735 if (!numericvar_to_uint64(&x, (uint64 *) &result))
4736 ereport(ERROR,
4738 errmsg("pg_lsn out of range")));
4739
4741}
static bool numericvar_to_uint64(const NumericVar *var, uint64 *result)
Definition numeric.c:7901
#define PG_RETURN_LSN(x)
Definition pg_lsn.h:37
uint64 XLogRecPtr
Definition xlogdefs.h:21

References ereport, errcode(), errmsg, ERROR, fb(), init_var_from_num(), NUMERIC_IS_NAN, NUMERIC_IS_SPECIAL, numericvar_to_uint64(), PG_GETARG_NUMERIC, PG_RETURN_LSN, result, and x.

Referenced by pg_lsn_mii(), and pg_lsn_pli().

◆ numeric_poly_avg()

Datum numeric_poly_avg ( PG_FUNCTION_ARGS  )

Definition at line 5928 of file numeric.c.

5929{
5932 Datum countd,
5933 sumd;
5934
5936
5937 /* If there were no non-null inputs, return NULL */
5938 if (state == NULL || state->N == 0)
5940
5941 init_var(&result);
5942
5944
5947
5948 free_var(&result);
5949
5951}

References DirectFunctionCall2, fb(), free_var(), init_var, int128_to_numericvar(), int64_to_numeric(), make_result(), numeric_div(), NumericGetDatum(), PG_ARGISNULL, PG_GETARG_POINTER, PG_RETURN_DATUM, PG_RETURN_NULL, and result.

◆ numeric_poly_combine()

Datum numeric_poly_combine ( PG_FUNCTION_ARGS  )

Definition at line 5560 of file numeric.c.

5561{
5564 MemoryContext agg_context;
5566
5567 if (!AggCheckCallContext(fcinfo, &agg_context))
5568 elog(ERROR, "aggregate function called in non-aggregate context");
5569
5572
5573 if (state2 == NULL)
5575
5576 /* manually copy all fields from state2 to state1 */
5577 if (state1 == NULL)
5578 {
5579 old_context = MemoryContextSwitchTo(agg_context);
5580
5581 state1 = makeInt128AggState(fcinfo, true);
5582 state1->N = state2->N;
5583 state1->sumX = state2->sumX;
5584 state1->sumX2 = state2->sumX2;
5585
5587
5589 }
5590
5591 if (state2->N > 0)
5592 {
5593 state1->N += state2->N;
5594 int128_add_int128(&state1->sumX, state2->sumX);
5595 int128_add_int128(&state1->sumX2, state2->sumX2);
5596 }
5598}

References AggCheckCallContext(), elog, ERROR, fb(), int128_add_int128(), makeInt128AggState(), MemoryContextSwitchTo(), PG_ARGISNULL, PG_GETARG_POINTER, and PG_RETURN_POINTER.

◆ numeric_poly_deserialize()

Datum numeric_poly_deserialize ( PG_FUNCTION_ARGS  )

Definition at line 5662 of file numeric.c.

5663{
5664 bytea *sstate;
5667
5668 if (!AggCheckCallContext(fcinfo, NULL))
5669 elog(ERROR, "aggregate function called in non-aggregate context");
5670
5671 sstate = PG_GETARG_BYTEA_PP(0);
5672
5673 /*
5674 * Initialize a StringInfo so that we can "receive" it using the standard
5675 * recv-function infrastructure.
5676 */
5678 VARSIZE_ANY_EXHDR(sstate));
5679
5681
5682 /* N */
5683 result->N = pq_getmsgint64(&buf);
5684
5685 /* sumX */
5686 result->sumX = int128_deserialize(&buf);
5687
5688 /* sumX2 */
5689 result->sumX2 = int128_deserialize(&buf);
5690
5691 pq_getmsgend(&buf);
5692
5694}

References AggCheckCallContext(), buf, elog, ERROR, fb(), initReadOnlyStringInfo(), int128_deserialize(), makeInt128AggStateCurrentContext(), PG_GETARG_BYTEA_PP, PG_RETURN_POINTER, pq_getmsgend(), pq_getmsgint64(), result, VARDATA_ANY(), and VARSIZE_ANY_EXHDR().

◆ numeric_poly_serialize()

Datum numeric_poly_serialize ( PG_FUNCTION_ARGS  )

Definition at line 5628 of file numeric.c.

5629{
5632 bytea *result;
5633
5634 /* Ensure we disallow calling when not in aggregate context */
5635 if (!AggCheckCallContext(fcinfo, NULL))
5636 elog(ERROR, "aggregate function called in non-aggregate context");
5637
5639
5641
5642 /* N */
5643 pq_sendint64(&buf, state->N);
5644
5645 /* sumX */
5646 int128_serialize(&buf, state->sumX);
5647
5648 /* sumX2 */
5649 int128_serialize(&buf, state->sumX2);
5650
5652
5654}

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

◆ numeric_poly_stddev_internal()

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

Definition at line 6184 of file numeric.c.

6187{
6189 Numeric res;
6190
6191 /* Initialize an empty agg state */
6192 memset(&numstate, 0, sizeof(NumericAggState));
6193
6194 if (state)
6195 {
6197
6198 numstate.N = state->N;
6199
6200 init_var(&tmp_var);
6201
6204
6206 accum_sum_add(&numstate.sumX2, &tmp_var);
6207
6208 free_var(&tmp_var);
6209 }
6210
6212
6213 if (numstate.sumX.ndigits > 0)
6214 {
6215 pfree(numstate.sumX.pos_digits);
6216 pfree(numstate.sumX.neg_digits);
6217 }
6218 if (numstate.sumX2.ndigits > 0)
6219 {
6220 pfree(numstate.sumX2.pos_digits);
6221 pfree(numstate.sumX2.neg_digits);
6222 }
6223
6224 return res;
6225}
static Numeric numeric_stddev_internal(NumericAggState *state, bool variance, bool sample, bool *is_null)
Definition numeric.c:6032

References accum_sum_add(), fb(), free_var(), init_var, int128_to_numericvar(), numeric_stddev_internal(), and pfree().

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

6280{
6282 Numeric res;
6283 bool is_null;
6284
6286
6287 res = numeric_poly_stddev_internal(state, false, false, &is_null);
6288
6289 if (is_null)
6291 else
6292 PG_RETURN_NUMERIC(res);
6293}
static Numeric numeric_poly_stddev_internal(Int128AggState *state, bool variance, bool sample, bool *is_null)
Definition numeric.c:6184

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

6246{
6248 Numeric res;
6249 bool is_null;
6250
6252
6253 res = numeric_poly_stddev_internal(state, false, true, &is_null);
6254
6255 if (is_null)
6257 else
6258 PG_RETURN_NUMERIC(res);
6259}

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

5905{
5907 Numeric res;
5909
5911
5912 /* If there were no non-null inputs, return NULL */
5913 if (state == NULL || state->N == 0)
5915
5916 init_var(&result);
5917
5919
5920 res = make_result(&result);
5921
5922 free_var(&result);
5923
5924 PG_RETURN_NUMERIC(res);
5925}

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

◆ numeric_poly_var_pop()

Datum numeric_poly_var_pop ( PG_FUNCTION_ARGS  )

Definition at line 6262 of file numeric.c.

6263{
6265 Numeric res;
6266 bool is_null;
6267
6269
6270 res = numeric_poly_stddev_internal(state, true, false, &is_null);
6271
6272 if (is_null)
6274 else
6275 PG_RETURN_NUMERIC(res);
6276}

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

6229{
6231 Numeric res;
6232 bool is_null;
6233
6235
6236 res = numeric_poly_stddev_internal(state, true, true, &is_null);
6237
6238 if (is_null)
6240 else
6241 PG_RETURN_NUMERIC(res);
6242}

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

3923{
3926 Numeric res;
3930 int sign1,
3931 sign2;
3932
3933 /*
3934 * Handle NaN and infinities
3935 */
3937 {
3938 /*
3939 * We follow the POSIX spec for pow(3), which says that NaN ^ 0 = 1,
3940 * and 1 ^ NaN = 1, while all other cases with NaN inputs yield NaN
3941 * (with no error).
3942 */
3943 if (NUMERIC_IS_NAN(num1))
3944 {
3946 {
3948 if (cmp_var(&arg2, &const_zero) == 0)
3950 }
3952 }
3953 if (NUMERIC_IS_NAN(num2))
3954 {
3956 {
3958 if (cmp_var(&arg1, &const_one) == 0)
3960 }
3962 }
3963 /* At least one input is infinite, but error rules still apply */
3966 if (sign1 == 0 && sign2 < 0)
3967 ereport(ERROR,
3969 errmsg("zero raised to a negative power is undefined")));
3970 if (sign1 < 0 && !numeric_is_integral(num2))
3971 ereport(ERROR,
3973 errmsg("a negative number raised to a non-integer power yields a complex result")));
3974
3975 /*
3976 * POSIX gives this series of rules for pow(3) with infinite inputs:
3977 *
3978 * For any value of y, if x is +1, 1.0 shall be returned.
3979 */
3981 {
3983 if (cmp_var(&arg1, &const_one) == 0)
3985 }
3986
3987 /*
3988 * For any value of x, if y is [-]0, 1.0 shall be returned.
3989 */
3990 if (sign2 == 0)
3992
3993 /*
3994 * For any odd integer value of y > 0, if x is [-]0, [-]0 shall be
3995 * returned. For y > 0 and not an odd integer, if x is [-]0, +0 shall
3996 * be returned. (Since we don't deal in minus zero, we need not
3997 * distinguish these two cases.)
3998 */
3999 if (sign1 == 0 && sign2 > 0)
4001
4002 /*
4003 * If x is -1, and y is [-]Inf, 1.0 shall be returned.
4004 *
4005 * For |x| < 1, if y is -Inf, +Inf shall be returned.
4006 *
4007 * For |x| > 1, if y is -Inf, +0 shall be returned.
4008 *
4009 * For |x| < 1, if y is +Inf, +0 shall be returned.
4010 *
4011 * For |x| > 1, if y is +Inf, +Inf shall be returned.
4012 */
4013 if (NUMERIC_IS_INF(num2))
4014 {
4015 bool abs_x_gt_one;
4016
4018 abs_x_gt_one = true; /* x is either Inf or -Inf */
4019 else
4020 {
4022 if (cmp_var(&arg1, &const_minus_one) == 0)
4024 arg1.sign = NUMERIC_POS; /* now arg1 = abs(x) */
4025 abs_x_gt_one = (cmp_var(&arg1, &const_one) > 0);
4026 }
4027 if (abs_x_gt_one == (sign2 > 0))
4029 else
4031 }
4032
4033 /*
4034 * For y < 0, if x is +Inf, +0 shall be returned.
4035 *
4036 * For y > 0, if x is +Inf, +Inf shall be returned.
4037 */
4038 if (NUMERIC_IS_PINF(num1))
4039 {
4040 if (sign2 > 0)
4042 else
4044 }
4045
4047
4048 /*
4049 * For y an odd integer < 0, if x is -Inf, -0 shall be returned. For
4050 * y < 0 and not an odd integer, if x is -Inf, +0 shall be returned.
4051 * (Again, we need not distinguish these two cases.)
4052 */
4053 if (sign2 < 0)
4055
4056 /*
4057 * For y an odd integer > 0, if x is -Inf, -Inf shall be returned. For
4058 * y > 0 and not an odd integer, if x is -Inf, +Inf shall be returned.
4059 */
4061 if (arg2.ndigits > 0 && arg2.ndigits == arg2.weight + 1 &&
4062 (arg2.digits[arg2.ndigits - 1] & 1))
4064 else
4066 }
4067
4068 /*
4069 * The SQL spec requires that we emit a particular SQLSTATE error code for
4070 * certain error conditions. Specifically, we don't return a
4071 * divide-by-zero error code for 0 ^ -1. Raising a negative number to a
4072 * non-integer power must produce the same error code, but that case is
4073 * handled in power_var().
4074 */
4077
4078 if (sign1 == 0 && sign2 < 0)
4079 ereport(ERROR,
4081 errmsg("zero raised to a negative power is undefined")));
4082
4083 /*
4084 * Initialize things
4085 */
4086 init_var(&result);
4089
4090 /*
4091 * Call power_var() to compute and return the result; note it handles
4092 * scale selection itself.
4093 */
4094 power_var(&arg1, &arg2, &result);
4095
4096 res = make_result(&result);
4097
4098 free_var(&result);
4099
4100 PG_RETURN_NUMERIC(res);
4101}
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:10836
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, ereport, errcode(), errmsg, ERROR, fb(), free_var(), init_var, init_var_from_num(), make_result(), 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(), and result.

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

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

4110{
4111 Numeric num = PG_GETARG_NUMERIC(0);
4112
4113 if (NUMERIC_IS_SPECIAL(num))
4115
4117}

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

5279{
5282 bytea *result;
5284
5285 /* Ensure we disallow calling when not in aggregate context */
5286 if (!AggCheckCallContext(fcinfo, NULL))
5287 elog(ERROR, "aggregate function called in non-aggregate context");
5288
5290
5291 init_var(&tmp_var);
5292
5294
5295 /* N */
5296 pq_sendint64(&buf, state->N);
5297
5298 /* sumX */
5299 accum_sum_final(&state->sumX, &tmp_var);
5301
5302 /* sumX2 */
5303 accum_sum_final(&state->sumX2, &tmp_var);
5305
5306 /* maxScale */
5307 pq_sendint32(&buf, state->maxScale);
5308
5309 /* maxScaleCount */
5310 pq_sendint64(&buf, state->maxScaleCount);
5311
5312 /* NaNcount */
5313 pq_sendint64(&buf, state->NaNcount);
5314
5315 /* pInfcount */
5316 pq_sendint64(&buf, state->pInfcount);
5317
5318 /* nInfcount */
5319 pq_sendint64(&buf, state->nInfcount);
5320
5322
5323 free_var(&tmp_var);
5324
5326}

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

◆ numeric_sign()

Datum numeric_sign ( PG_FUNCTION_ARGS  )

Definition at line 1501 of file numeric.c.

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

References Assert, const_minus_one, const_nan, const_one, const_zero, make_result(), NUMERIC_IS_NAN, numeric_sign_internal(), PG_GETARG_NUMERIC, and PG_RETURN_NUMERIC.

◆ numeric_sign_internal()

static int numeric_sign_internal ( Numeric  num)
static

Definition at line 1469 of file numeric.c.

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

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

Referenced by numeric_div_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 3457 of file numeric.c.

3458{
3461
3462 /*
3463 * Use cmp_numerics so that this will agree with the comparison operators,
3464 * particularly as regards comparisons involving NaN.
3465 */
3466 if (cmp_numerics(num1, num2) < 0)
3468 else
3470}

References cmp_numerics(), fb(), PG_GETARG_NUMERIC, and PG_RETURN_NUMERIC.

◆ numeric_sortsupport()

Datum numeric_sortsupport ( PG_FUNCTION_ARGS  )

Definition at line 2116 of file numeric.c.

2117{
2119
2121
2122 if (ssup->abbreviate)
2123 {
2125 MemoryContext oldcontext = MemoryContextSwitchTo(ssup->ssup_cxt);
2126
2128
2129 /*
2130 * palloc a buffer for handling unaligned packed values in addition to
2131 * the support struct
2132 */
2133 nss->buf = palloc(VARATT_SHORT_MAX + VARHDRSZ + 1);
2134
2135 nss->input_count = 0;
2136 nss->estimating = true;
2137 initHyperLogLog(&nss->abbr_card, 10);
2138
2139 ssup->ssup_extra = nss;
2140
2141 ssup->abbrev_full_comparator = ssup->comparator;
2145
2146 MemoryContextSwitchTo(oldcontext);
2147 }
2148
2150}
static bool numeric_abbrev_abort(int memtupcount, SortSupport ssup)
Definition numeric.c:2219
static Datum numeric_abbrev_convert(Datum original_datum, SortSupport ssup)
Definition numeric.c:2157
static int numeric_fast_cmp(Datum x, Datum y, SortSupport ssup)
Definition numeric.c:2286
static int numeric_cmp_abbrev(Datum x, Datum y, SortSupport ssup)
Definition numeric.c:2308
struct SortSupportData * SortSupport
Definition execnodes.h:61
#define PG_RETURN_VOID()
Definition fmgr.h:350
void initHyperLogLog(hyperLogLogState *cState, uint8 bwidth)
Definition hyperloglog.c:66
int(* comparator)(Datum x, Datum y, SortSupport ssup)
Datum(* abbrev_converter)(Datum original, SortSupport ssup)
MemoryContext ssup_cxt
Definition sortsupport.h:66
int(* abbrev_full_comparator)(Datum x, Datum y, SortSupport ssup)
bool(* abbrev_abort)(int memtupcount, SortSupport ssup)

References SortSupportData::abbrev_abort, SortSupportData::abbrev_converter, SortSupportData::abbrev_full_comparator, SortSupportData::abbreviate, SortSupportData::comparator, fb(), initHyperLogLog(), MemoryContextSwitchTo(), numeric_abbrev_abort(), numeric_abbrev_convert(), numeric_cmp_abbrev(), numeric_fast_cmp(), palloc(), palloc_object, PG_GETARG_POINTER, PG_RETURN_VOID, SortSupportData::ssup_cxt, SortSupportData::ssup_extra, VARATT_SHORT_MAX, and VARHDRSZ.

◆ numeric_sqrt()

Datum numeric_sqrt ( PG_FUNCTION_ARGS  )

Definition at line 3663 of file numeric.c.

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

References arg, DEC_DIGITS, duplicate_numeric(), ereport, errcode(), errmsg, ERROR, fb(), 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, result, and sqrt_var().

◆ numeric_stddev_internal()

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

Definition at line 6032 of file numeric.c.

6035{
6036 Numeric res;
6037 NumericVar vN,
6038 vsumX,
6039 vsumX2,
6040 vNminus1;
6042 int rscale;
6043
6044 /*
6045 * Sample stddev and variance are undefined when N <= 1; population stddev
6046 * is undefined when N == 0. Return NULL in either case (note that NaNs
6047 * and infinities count as normal inputs for this purpose).
6048 */
6049 if (state == NULL || (totCount = NA_TOTAL_COUNT(state)) == 0)
6050 {
6051 *is_null = true;
6052 return NULL;
6053 }
6054
6055 if (sample && totCount <= 1)
6056 {
6057 *is_null = true;
6058 return NULL;
6059 }
6060
6061 *is_null = false;
6062
6063 /*
6064 * Deal with NaN and infinity cases. By analogy to the behavior of the
6065 * float8 functions, any infinity input produces NaN output.
6066 */
6067 if (state->NaNcount > 0 || state->pInfcount > 0 || state->nInfcount > 0)
6068 return make_result(&const_nan);
6069
6070 /* OK, normal calculation applies */
6071 init_var(&vN);
6072 init_var(&vsumX);
6073 init_var(&vsumX2);
6074
6076 accum_sum_final(&(state->sumX), &vsumX);
6077 accum_sum_final(&(state->sumX2), &vsumX2);
6078
6081
6082 /* compute rscale for mul_var calls */
6083 rscale = vsumX.dscale * 2;
6084
6085 mul_var(&vsumX, &vsumX, &vsumX, rscale); /* vsumX = sumX * sumX */
6086 mul_var(&vN, &vsumX2, &vsumX2, rscale); /* vsumX2 = N * sumX2 */
6087 sub_var(&vsumX2, &vsumX, &vsumX2); /* N * sumX2 - sumX * sumX */
6088
6089 if (cmp_var(&vsumX2, &const_zero) <= 0)
6090 {
6091 /* Watch out for roundoff error producing a negative numerator */
6092 res = make_result(&const_zero);
6093 }
6094 else
6095 {
6096 if (sample)
6097 mul_var(&vN, &vNminus1, &vNminus1, 0); /* N * (N - 1) */
6098 else
6099 mul_var(&vN, &vN, &vNminus1, 0); /* N * N */
6100 rscale = select_div_scale(&vsumX2, &vNminus1);
6101 div_var(&vsumX2, &vNminus1, &vsumX, rscale, true, true); /* variance */
6102 if (!variance)
6103 sqrt_var(&vsumX, &vsumX, rscale); /* stddev */
6104
6105 res = make_result(&vsumX);
6106 }
6107
6109 free_var(&vsumX);
6110 free_var(&vsumX2);
6111
6112 return res;
6113}

References accum_sum_final(), cmp_var(), const_nan, const_one, const_zero, div_var(), fb(), 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 6167 of file numeric.c.

6168{
6170 Numeric res;
6171 bool is_null;
6172
6174
6175 res = numeric_stddev_internal(state, false, false, &is_null);
6176
6177 if (is_null)
6179 else
6180 PG_RETURN_NUMERIC(res);
6181}

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

6134{
6136 Numeric res;
6137 bool is_null;
6138
6140
6141 res = numeric_stddev_internal(state, false, true, &is_null);
6142
6143 if (is_null)
6145 else
6146 PG_RETURN_NUMERIC(res);
6147}

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

2948{
2951 Numeric res;
2952
2953 res = numeric_sub_safe(num1, num2, NULL);
2954
2955 PG_RETURN_NUMERIC(res);
2956}
Numeric numeric_sub_safe(Numeric num1, Numeric num2, Node *escontext)
Definition numeric.c:2965

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

2966{
2970 Numeric res;
2971
2972 /*
2973 * Handle NaN and infinities
2974 */
2976 {
2978 return make_result(&const_nan);
2979 if (NUMERIC_IS_PINF(num1))
2980 {
2981 if (NUMERIC_IS_PINF(num2))
2982 return make_result(&const_nan); /* Inf - Inf */
2983 else
2984 return make_result(&const_pinf);
2985 }
2986 if (NUMERIC_IS_NINF(num1))
2987 {
2988 if (NUMERIC_IS_NINF(num2))
2989 return make_result(&const_nan); /* -Inf - -Inf */
2990 else
2991 return make_result(&const_ninf);
2992 }
2993 /* by here, num1 must be finite, so num2 is not */
2994 if (NUMERIC_IS_PINF(num2))
2995 return make_result(&const_ninf);
2997 return make_result(&const_pinf);
2998 }
2999
3000 /*
3001 * Unpack the values, let sub_var() compute the result and return it.
3002 */
3005
3006 init_var(&result);
3007 sub_var(&arg1, &arg2, &result);
3008
3009 res = make_result_safe(&result, escontext);
3010
3011 free_var(&result);
3012
3013 return res;
3014}

References Assert, const_nan, const_ninf, const_pinf, fb(), 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, result, 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 5989 of file numeric.c.

5990{
5994
5996
5997 /* If there were no non-null inputs, return NULL */
5998 if (state == NULL || NA_TOTAL_COUNT(state) == 0)
6000
6001 if (state->NaNcount > 0) /* there was at least one NaN input */
6003
6004 /* adding plus and minus infinities gives NaN */
6005 if (state->pInfcount > 0 && state->nInfcount > 0)
6007 if (state->pInfcount > 0)
6009 if (state->nInfcount > 0)
6011
6013 accum_sum_final(&state->sumX, &sumX_var);
6016
6018}

References accum_sum_final(), const_nan, const_ninf, const_pinf, fb(), free_var(), init_var, make_result(), NA_TOTAL_COUNT, PG_ARGISNULL, PG_GETARG_POINTER, PG_RETURN_NULL, PG_RETURN_NUMERIC, and result.

◆ numeric_support()

Datum numeric_support ( PG_FUNCTION_ARGS  )

Definition at line 1179 of file numeric.c.

1180{
1182 Node *ret = NULL;
1183
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);
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 */
1215 }
1216 }
1217
1218 PG_RETURN_POINTER(ret);
1219}
int32 exprTypmod(const Node *expr)
Definition nodeFuncs.c:304
Node * relabel_to_typmod(Node *expr, int32 typmod)
Definition nodeFuncs.c:694
static rewind_source * source
Definition pg_rewind.c:89
static int32 DatumGetInt32(Datum X)
Definition postgres.h:202
List * args
Definition primnodes.h:788

References FuncExpr::args, Assert, DatumGetInt32(), exprTypmod(), fb(), 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 4194 of file numeric.c.

4195{
4196 Numeric num = PG_GETARG_NUMERIC(0);
4197 Numeric res;
4199
4200 if (NUMERIC_IS_SPECIAL(num))
4202
4204 result.dscale = get_min_scale(&result);
4205 res = make_result(&result);
4206 free_var(&result);
4207
4208 PG_RETURN_NUMERIC(res);
4209}

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

◆ numeric_trunc()

Datum numeric_trunc ( PG_FUNCTION_ARGS  )

Definition at line 1588 of file numeric.c.

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

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

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

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

References duplicate_numeric(), PG_GETARG_NUMERIC, and PG_RETURN_NUMERIC.

◆ numeric_var_pop()

Datum numeric_var_pop ( PG_FUNCTION_ARGS  )

Definition at line 6150 of file numeric.c.

6151{
6153 Numeric res;
6154 bool is_null;
6155
6157
6158 res = numeric_stddev_internal(state, true, false, &is_null);
6159
6160 if (is_null)
6162 else
6163 PG_RETURN_NUMERIC(res);
6164}

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

6117{
6119 Numeric res;
6120 bool is_null;
6121
6123
6124 res = numeric_stddev_internal(state, true, true, &is_null);
6125
6126 if (is_null)
6128 else
6129 PG_RETURN_NUMERIC(res);
6130}

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

◆ numerictypmodin()

Datum numerictypmodin ( PG_FUNCTION_ARGS  )

Definition at line 1332 of file numeric.c.

1333{
1335 int32 *tl;
1336 int n;
1337 int32 typmod;
1338
1340
1341 if (n == 2)
1342 typmod = make_numeric_typmod_safe(tl[0], tl[1], NULL);
1343 else if (n == 1)
1344 {
1345 /* scale defaults to zero */
1346 typmod = make_numeric_typmod_safe(tl[0], 0, NULL);
1347 }
1348 else
1349 {
1350 ereport(ERROR,
1352 errmsg("invalid NUMERIC type modifier")));
1353 typmod = 0; /* keep compiler quiet */
1354 }
1355
1356 PG_RETURN_INT32(typmod);
1357}
int32 * ArrayGetIntegerTypmods(ArrayType *arr, int *n)
Definition arrayutils.c:233
int32 make_numeric_typmod_safe(int32 precision, int32 scale, Node *escontext)
Definition numeric.c:1315

References ArrayGetIntegerTypmods(), ereport, errcode(), errmsg, ERROR, fb(), make_numeric_typmod_safe(), PG_GETARG_ARRAYTYPE_P, and PG_RETURN_INT32.

◆ numerictypmodout()

Datum numerictypmodout ( PG_FUNCTION_ARGS  )

Definition at line 1360 of file numeric.c.

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

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

7507{
7508 int len,
7509 i;
7510
7511 len = pq_getmsgint(buf, sizeof(int32));
7512
7513 alloc_var(var, len); /* sets var->ndigits */
7514
7515 var->weight = pq_getmsgint(buf, sizeof(int32));
7516 var->sign = pq_getmsgint(buf, sizeof(int32));
7517 var->dscale = pq_getmsgint(buf, sizeof(int32));
7518 for (i = 0; i < len; i++)
7519 var->digits[i] = pq_getmsgint(buf, sizeof(int16));
7520}

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

7491{
7492 int i;
7493
7494 pq_sendint32(buf, var->ndigits);
7495 pq_sendint32(buf, var->weight);
7496 pq_sendint32(buf, var->sign);
7497 pq_sendint32(buf, var->dscale);
7498 for (i = 0; i < var->ndigits; i++)
7499 pq_sendint16(buf, var->digits[i]);
7500}

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

8008{
8009 char *tmp;
8010 double val;
8011 char *endptr;
8012
8013 tmp = get_str_from_var(var);
8014
8015 /* unlike float8in, we ignore ERANGE from strtod */
8016 val = strtod(tmp, &endptr);
8017 if (*endptr != '\0')
8018 {
8019 /* shouldn't happen ... */
8020 ereport(ERROR,
8022 errmsg("invalid input syntax for type %s: \"%s\"",
8023 "double precision", tmp)));
8024 }
8025
8026 pfree(tmp);
8027
8028 return val;
8029}

References ereport, errcode(), errmsg, ERROR, fb(), 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 4423 of file numeric.c.

4424{
4425 int64 val;
4426
4427 if (!numericvar_to_int64(var, &val))
4428 return false;
4429
4431 return false;
4432
4433 /* Down-convert to int4 */
4434 *result = (int32) val;
4435
4436 return true;
4437}
#define PG_INT32_MAX
Definition c.h:732
#define PG_INT32_MIN
Definition c.h:731

References numericvar_to_int64(), PG_INT32_MAX, PG_INT32_MIN, result, 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 7779 of file numeric.c.

7780{
7782 int ndigits;
7783 int weight;
7784 int i;
7785 int64 val;
7786 bool neg;
7788
7789 /* Round to nearest integer */
7790 init_var(&rounded);
7792 round_var(&rounded, 0);
7793
7794 /* Check for zero input */
7796 ndigits = rounded.ndigits;
7797 if (ndigits == 0)
7798 {
7799 *result = 0;
7800 free_var(&rounded);
7801 return true;
7802 }
7803
7804 /*
7805 * For input like 10000000000, we must treat stripped digits as real. So
7806 * the loop assumes there are weight+1 digits before the decimal point.
7807 */
7808 weight = rounded.weight;
7809 Assert(weight >= 0 && ndigits <= weight + 1);
7810
7811 /*
7812 * Construct the result. To avoid issues with converting a value
7813 * corresponding to INT64_MIN (which can't be represented as a positive 64
7814 * bit two's complement integer), accumulate value as a negative number.
7815 */
7816 digits = rounded.digits;
7817 neg = (rounded.sign == NUMERIC_NEG);
7818 val = -digits[0];
7819 for (i = 1; i <= weight; i++)
7820 {
7822 {
7823 free_var(&rounded);
7824 return false;
7825 }
7826
7827 if (i < ndigits)
7828 {
7830 {
7831 free_var(&rounded);
7832 return false;
7833 }
7834 }
7835 }
7836
7837 free_var(&rounded);
7838
7839 if (!neg)
7840 {
7841 if (unlikely(val == PG_INT64_MIN))
7842 return false;
7843 val = -val;
7844 }
7845 *result = val;
7846
7847 return true;
7848}
#define PG_INT64_MIN
Definition c.h:734
static bool pg_sub_s64_overflow(int64 a, int64 b, int64 *result)
Definition int.h:262

References Assert, digits, fb(), free_var(), i, init_var, NBASE, NUMERIC_NEG, PG_INT64_MIN, pg_mul_s64_overflow(), pg_sub_s64_overflow(), result, round_var(), set_var_from_var(), strip_var(), unlikely, and val.

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

7902{
7904 int ndigits;
7905 int weight;
7906 int i;
7907 uint64 val;
7909
7910 /* Round to nearest integer */
7911 init_var(&rounded);
7913 round_var(&rounded, 0);
7914
7915 /* Check for zero input */
7917 ndigits = rounded.ndigits;
7918 if (ndigits == 0)
7919 {
7920 *result = 0;
7921 free_var(&rounded);
7922 return true;
7923 }
7924
7925 /* Check for negative input */
7926 if (rounded.sign == NUMERIC_NEG)
7927 {
7928 free_var(&rounded);
7929 return false;
7930 }
7931
7932 /*
7933 * For input like 10000000000, we must treat stripped digits as real. So
7934 * the loop assumes there are weight+1 digits before the decimal point.
7935 */
7936 weight = rounded.weight;
7937 Assert(weight >= 0 && ndigits <= weight + 1);
7938
7939 /* Construct the result */
7940 digits = rounded.digits;
7941 val = digits[0];
7942 for (i = 1; i <= weight; i++)
7943 {
7945 {
7946 free_var(&rounded);
7947 return false;
7948 }
7949
7950 if (i < ndigits)
7951 {
7953 {
7954 free_var(&rounded);
7955 return false;
7956 }
7957 }
7958 }
7959
7960 free_var(&rounded);
7961
7962 *result = val;
7963
7964 return true;
7965}
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, digits, fb(), free_var(), i, init_var, NBASE, NUMERIC_NEG, pg_add_u64_overflow(), pg_mul_u64_overflow(), result, round_var(), set_var_from_var(), strip_var(), unlikely, and val.

Referenced by numeric_pg_lsn().

◆ power_ten_int()

static void power_ten_int ( int  exp,
NumericVar result 
)
static

Definition at line 11203 of file numeric.c.

11204{
11205 /* Construct the result directly, starting from 10^0 = 1 */
11207
11208 /* Scale needed to represent the result exactly */
11209 result->dscale = exp < 0 ? -exp : 0;
11210
11211 /* Base-NBASE weight of result and remaining exponent */
11212 if (exp >= 0)
11213 result->weight = exp / DEC_DIGITS;
11214 else
11215 result->weight = (exp + 1) / DEC_DIGITS - 1;
11216
11217 exp -= result->weight * DEC_DIGITS;
11218
11219 /* Final adjustment of the result's single NBASE digit */
11220 while (exp-- > 0)
11221 result->digits[0] *= 10;
11222}

References const_one, DEC_DIGITS, fb(), result, and set_var_from_var().

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

10837{
10838 int res_sign;
10842 int ln_dweight;
10843 int rscale;
10844 int sig_digits;
10845 int local_rscale;
10846 double val;
10847
10848 /* If exp can be represented as an integer, use power_var_int */
10849 if (exp->ndigits == 0 || exp->ndigits <= exp->weight + 1)
10850 {
10851 /* exact integer, but does it fit in int? */
10853
10855 {
10857 {
10858 /* Okay, use power_var_int */
10859 power_var_int(base, (int) expval64, exp->dscale, result);
10860 return;
10861 }
10862 }
10863 }
10864
10865 /*
10866 * This avoids log(0) for cases of 0 raised to a non-integer. 0 ^ 0 is
10867 * handled by power_var_int().
10868 */
10869 if (cmp_var(base, &const_zero) == 0)
10870 {
10872 result->dscale = NUMERIC_MIN_SIG_DIGITS; /* no need to round */
10873 return;
10874 }
10875
10877 init_var(&ln_base);
10878 init_var(&ln_num);
10879
10880 /*
10881 * If base is negative, insist that exp be an integer. The result is then
10882 * positive if exp is even and negative if exp is odd.
10883 */
10884 if (base->sign == NUMERIC_NEG)
10885 {
10886 /*
10887 * Check that exp is an integer. This error code is defined by the
10888 * SQL standard, and matches other errors in numeric_power().
10889 */
10890 if (exp->ndigits > 0 && exp->ndigits > exp->weight + 1)
10891 ereport(ERROR,
10893 errmsg("a negative number raised to a non-integer power yields a complex result")));
10894
10895 /* Test if exp is odd or even */
10896 if (exp->ndigits > 0 && exp->ndigits == exp->weight + 1 &&
10897 (exp->digits[exp->ndigits - 1] & 1))
10899 else
10901
10902 /* Then work with abs(base) below */
10903 set_var_from_var(base, &abs_base);
10904 abs_base.sign = NUMERIC_POS;
10905 base = &abs_base;
10906 }
10907 else
10909
10910 /*----------
10911 * Decide on the scale for the ln() calculation. For this we need an
10912 * estimate of the weight of the result, which we obtain by doing an
10913 * initial low-precision calculation of exp * ln(base).
10914 *
10915 * We want result = e ^ (exp * ln(base))
10916 * so result dweight = log10(result) = exp * ln(base) * log10(e)
10917 *
10918 * We also perform a crude overflow test here so that we can exit early if
10919 * the full-precision result is sure to overflow, and to guard against
10920 * integer overflow when determining the scale for the real calculation.
10921 * exp_var() supports inputs up to NUMERIC_MAX_RESULT_SCALE * 3, so the
10922 * result will overflow if exp * ln(base) >= NUMERIC_MAX_RESULT_SCALE * 3.
10923 * Since the values here are only approximations, we apply a small fuzz
10924 * factor to this overflow test and let exp_var() determine the exact
10925 * overflow threshold so that it is consistent for all inputs.
10926 *----------
10927 */
10929
10930 /*
10931 * Set the scale for the low-precision calculation, computing ln(base) to
10932 * around 8 significant digits. Note that ln_dweight may be as small as
10933 * -NUMERIC_DSCALE_MAX, so the scale may exceed NUMERIC_MAX_DISPLAY_SCALE
10934 * here.
10935 */
10938
10939 ln_var(base, &ln_base, local_rscale);
10940
10942
10944
10945 /* initial overflow/underflow test with fuzz factor */
10946 if (fabs(val) > NUMERIC_MAX_RESULT_SCALE * 3.01)
10947 {
10948 if (val > 0)
10949 ereport(ERROR,
10951 errmsg("value overflows numeric format")));
10954 return;
10955 }
10956
10957 val *= 0.434294481903252; /* approximate decimal result weight */
10958
10959 /* choose the result scale */
10960 rscale = NUMERIC_MIN_SIG_DIGITS - (int) val;
10961 rscale = Max(rscale, base->dscale);
10962 rscale = Max(rscale, exp->dscale);
10963 rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
10964 rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
10965
10966 /* significant digits required in the result */
10967 sig_digits = rscale + (int) val;
10969
10970 /* set the scale for the real exp * ln(base) calculation */
10973
10974 /* and do the real calculation */
10975
10976 ln_var(base, &ln_base, local_rscale);
10977
10979
10980 exp_var(&ln_num, result, rscale);
10981
10982 if (res_sign == NUMERIC_NEG && result->ndigits > 0)
10983 result->sign = NUMERIC_NEG;
10984
10985 free_var(&ln_num);
10986 free_var(&ln_base);
10988}
static void power_var_int(const NumericVar *base, int exp, int exp_dscale, NumericVar *result)
Definition numeric.c:10998

References cmp_var(), const_zero, NumericVar::dscale, ereport, errcode(), errmsg, ERROR, estimate_ln_dweight(), exp_var(), fb(), free_var(), init_var, ln_var(), Max, Min, mul_var(), 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(), result, set_var_from_var(), NumericVar::sign, val, 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 10998 of file numeric.c.

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

4216{
4220 Numeric res;
4221
4222 /* Range bounds must not be NaN/infinity */
4224 {
4225 if (NUMERIC_IS_NAN(rmin))
4226 ereport(ERROR,
4228 errmsg("lower bound cannot be NaN"));
4229 else
4230 ereport(ERROR,
4232 errmsg("lower bound cannot be infinity"));
4233 }
4235 {
4236 if (NUMERIC_IS_NAN(rmax))
4237 ereport(ERROR,
4239 errmsg("upper bound cannot be NaN"));
4240 else
4241 ereport(ERROR,
4243 errmsg("upper bound cannot be infinity"));
4244 }
4245
4246 /* Return a random value in the range [rmin, rmax] */
4249
4250 init_var(&result);
4251
4253
4254 res = make_result(&result);
4255
4256 free_var(&result);
4257
4258 return res;
4259}
static void random_var(pg_prng_state *state, const NumericVar *rmin, const NumericVar *rmax, NumericVar *result)
Definition numeric.c:11228

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

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

11230{
11231 int rscale;
11233 int res_ndigits;
11234 int n;
11235 int pow10;
11236 int i;
11237 uint64 rlen64;
11238 int rlen64_ndigits;
11239
11240 rscale = Max(rmin->dscale, rmax->dscale);
11241
11242 /* Compute rlen = rmax - rmin and check the range bounds */
11243 init_var(&rlen);
11244 sub_var(rmax, rmin, &rlen);
11245
11246 if (rlen.sign == NUMERIC_NEG)
11247 ereport(ERROR,
11249 errmsg("lower bound must be less than or equal to upper bound"));
11250
11251 /* Special case for an empty range */
11252 if (rlen.ndigits == 0)
11253 {
11255 result->dscale = rscale;
11256 free_var(&rlen);
11257 return;
11258 }
11259
11260 /*
11261 * Otherwise, select a random value in the range [0, rlen = rmax - rmin],
11262 * and shift it to the required range by adding rmin.
11263 */
11264
11265 /* Required result digits */
11266 res_ndigits = rlen.weight + 1 + (rscale + DEC_DIGITS - 1) / DEC_DIGITS;
11267
11268 /*
11269 * To get the required rscale, the final result digit must be a multiple
11270 * of pow10 = 10^n, where n = (-rscale) mod DEC_DIGITS.
11271 */
11272 n = ((rscale + DEC_DIGITS - 1) / DEC_DIGITS) * DEC_DIGITS - rscale;
11273 pow10 = 1;
11274 for (i = 0; i < n; i++)
11275 pow10 *= 10;
11276
11277 /*
11278 * To choose a random value uniformly from the range [0, rlen], we choose
11279 * from the slightly larger range [0, rlen2], where rlen2 is formed from
11280 * rlen by copying the first 4 NBASE digits, and setting all remaining
11281 * decimal digits to "9".
11282 *
11283 * Without loss of generality, we can ignore the weight of rlen2 and treat
11284 * it as a pure integer for the purposes of this discussion. The process
11285 * above gives rlen2 + 1 = rlen64 * 10^N, for some integer N, where rlen64
11286 * is a 64-bit integer formed from the first 4 NBASE digits copied from
11287 * rlen. Since this trivially factors into smaller pieces that fit in
11288 * 64-bit integers, the task of choosing a random value uniformly from the
11289 * rlen2 + 1 possible values in [0, rlen2] is much simpler.
11290 *
11291 * If the random value selected is too large, it is rejected, and we try
11292 * again until we get a result <= rlen, ensuring that the overall result
11293 * is uniform (no particular value is any more likely than any other).
11294 *
11295 * Since rlen64 holds 4 NBASE digits from rlen, it contains at least
11296 * DEC_DIGITS * 3 + 1 decimal digits (i.e., at least 13 decimal digits,
11297 * when DEC_DIGITS is 4). Therefore the probability of needing to reject
11298 * the value chosen and retry is less than 1e-13.
11299 */
11300 rlen64 = (uint64) rlen.digits[0];
11301 rlen64_ndigits = 1;
11303 {
11304 rlen64 *= NBASE;
11305 if (rlen64_ndigits < rlen.ndigits)
11306 rlen64 += rlen.digits[rlen64_ndigits];
11308 }
11309
11310 /* Loop until we get a result <= rlen */
11311 do
11312 {
11314 uint64 rand;
11315 int whole_ndigits;
11316
11318 result->sign = NUMERIC_POS;
11319 result->weight = rlen.weight;
11320 result->dscale = rscale;
11321 res_digits = result->digits;
11322
11323 /*
11324 * Set the first rlen64_ndigits using a random value in [0, rlen64].
11325 *
11326 * If this is the whole result, and rscale is not a multiple of
11327 * DEC_DIGITS (pow10 from above is not 1), then we need this to be a
11328 * multiple of pow10.
11329 */
11330 if (rlen64_ndigits == res_ndigits && pow10 != 1)
11332 else
11334
11335 for (i = rlen64_ndigits - 1; i >= 0; i--)
11336 {
11338 rand = rand / NBASE;
11339 }
11340
11341 /*
11342 * Set the remaining digits to random values in range [0, NBASE),
11343 * noting that the last digit needs to be a multiple of pow10.
11344 */
11346 if (pow10 != 1)
11347 whole_ndigits--;
11348
11349 /* Set whole digits in groups of 4 for best performance */
11350 i = rlen64_ndigits;
11351 while (i < whole_ndigits - 3)
11352 {
11354 (uint64) NBASE * NBASE * NBASE * NBASE - 1);
11355 res_digits[i++] = (NumericDigit) (rand % NBASE);
11356 rand = rand / NBASE;
11357 res_digits[i++] = (NumericDigit) (rand % NBASE);
11358 rand = rand / NBASE;
11359 res_digits[i++] = (NumericDigit) (rand % NBASE);
11360 rand = rand / NBASE;
11362 }
11363
11364 /* Remaining whole digits */
11365 while (i < whole_ndigits)
11366 {
11369 }
11370
11371 /* Final partial digit (multiple of pow10) */
11372 if (i < res_ndigits)
11373 {
11376 }
11377
11378 /* Remove leading/trailing zeroes */
11380
11381 /* If result > rlen, try again */
11382
11383 } while (cmp_var(result, &rlen) > 0);
11384
11385 /* Offset the result to the required range */
11387
11388 free_var(&rlen);
11389}
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, ereport, errcode(), errmsg, ERROR, fb(), free_var(), i, init_var, Max, NBASE, NUMERIC_NEG, NUMERIC_POS, pg_prng_uint64_range(), result, set_var_from_var(), strip_var(), and sub_var().

Referenced by random_numeric().

◆ round_var()

static void round_var ( NumericVar var,
int  rscale 
)
static

Definition at line 11656 of file numeric.c.

11657{
11658 NumericDigit *digits = var->digits;
11659 int di;
11660 int ndigits;
11661 int carry;
11662
11663 var->dscale = rscale;
11664
11665 /* decimal digits wanted */
11666 di = (var->weight + 1) * DEC_DIGITS + rscale;
11667
11668 /*
11669 * If di = 0, the value loses all digits, but could round up to 1 if its
11670 * first extra digit is >= 5. If di < 0 the result must be 0.
11671 */
11672 if (di < 0)
11673 {
11674 var->ndigits = 0;
11675 var->weight = 0;
11676 var->sign = NUMERIC_POS;
11677 }
11678 else
11679 {
11680 /* NBASE digits wanted */
11681 ndigits = (di + DEC_DIGITS - 1) / DEC_DIGITS;
11682
11683 /* 0, or number of decimal digits to keep in last NBASE digit */
11684 di %= DEC_DIGITS;
11685
11686 if (ndigits < var->ndigits ||
11687 (ndigits == var->ndigits && di > 0))
11688 {
11689 var->ndigits = ndigits;
11690
11691#if DEC_DIGITS == 1
11692 /* di must be zero */
11693 carry = (digits[ndigits] >= HALF_NBASE) ? 1 : 0;
11694#else
11695 if (di == 0)
11696 carry = (digits[ndigits] >= HALF_NBASE) ? 1 : 0;
11697 else
11698 {
11699 /* Must round within last NBASE digit */
11700 int extra,
11701 pow10;
11702
11703#if DEC_DIGITS == 4
11705#elif DEC_DIGITS == 2
11706 pow10 = 10;
11707#else
11708#error unsupported NBASE
11709#endif
11710 extra = digits[--ndigits] % pow10;
11711 digits[ndigits] -= extra;
11712 carry = 0;
11713 if (extra >= pow10 / 2)
11714 {
11715 pow10 += digits[ndigits];
11716 if (pow10 >= NBASE)
11717 {
11718 pow10 -= NBASE;
11719 carry = 1;
11720 }
11721 digits[ndigits] = pow10;
11722 }
11723 }
11724#endif
11725
11726 /* Propagate carry if needed */
11727 while (carry)
11728 {
11729 carry += digits[--ndigits];
11730 if (carry >= NBASE)
11731 {
11732 digits[ndigits] = carry - NBASE;
11733 carry = 1;
11734 }
11735 else
11736 {
11737 digits[ndigits] = carry;
11738 carry = 0;
11739 }
11740 }
11741
11742 if (ndigits < 0)
11743 {
11744 Assert(ndigits == -1); /* better not have added > 1 digit */
11745 Assert(var->digits > var->buf);
11746 var->digits--;
11747 var->ndigits++;
11748 var->weight++;
11749 }
11750 }
11751 }
11752}
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, fb(), 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 9682 of file numeric.c.

9683{
9684 int weight1,
9685 weight2,
9686 qweight,
9687 i;
9690 int rscale;
9691
9692 /*
9693 * The result scale of a division isn't specified in any SQL standard. For
9694 * PostgreSQL we select a result scale that will give at least
9695 * NUMERIC_MIN_SIG_DIGITS significant digits, so that numeric gives a
9696 * result no less accurate than float8; but use a scale not less than
9697 * either input's display scale.
9698 */
9699
9700 /* Get the actual (normalized) weight and first digit of each input */
9701
9702 weight1 = 0; /* values to use if var1 is zero */
9703 firstdigit1 = 0;
9704 for (i = 0; i < var1->ndigits; i++)
9705 {
9706 firstdigit1 = var1->digits[i];
9707 if (firstdigit1 != 0)
9708 {
9709 weight1 = var1->weight - i;
9710 break;
9711 }
9712 }
9713
9714 weight2 = 0; /* values to use if var2 is zero */
9715 firstdigit2 = 0;
9716 for (i = 0; i < var2->ndigits; i++)
9717 {
9718 firstdigit2 = var2->digits[i];
9719 if (firstdigit2 != 0)
9720 {
9721 weight2 = var2->weight - i;
9722 break;
9723 }
9724 }
9725
9726 /*
9727 * Estimate weight of quotient. If the two first digits are equal, we
9728 * can't be sure, but assume that var1 is less than var2.
9729 */
9731 if (firstdigit1 <= firstdigit2)
9732 qweight--;
9733
9734 /* Select result scale */
9736 rscale = Max(rscale, var1->dscale);
9737 rscale = Max(rscale, var2->dscale);
9738 rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
9739 rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
9740
9741 return rscale;
9742}

References DEC_DIGITS, fb(), i, Max, Min, NUMERIC_MAX_DISPLAY_SCALE, NUMERIC_MIN_DISPLAY_SCALE, and NUMERIC_MIN_SIG_DIGITS.

Referenced by numeric_div_safe(), numeric_stddev_internal(), and PGTYPESnumeric_div().

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

7011{
7012 const char *firstdigit = cp;
7013 int64 tmp;
7014 int64 mul;
7016
7017 init_var(&tmp_var);
7018
7019 zero_var(dest);
7020
7021 /*
7022 * Process input digits in groups that fit in int64. Here "tmp" is the
7023 * value of the digits in the group, and "mul" is base^n, where n is the
7024 * number of digits in the group. Thus tmp < mul, and we must start a new
7025 * group when mul * base threatens to overflow PG_INT64_MAX.
7026 */
7027 tmp = 0;
7028 mul = 1;
7029
7030 if (base == 16)
7031 {
7032 while (*cp)
7033 {
7034 if (isxdigit((unsigned char) *cp))
7035 {
7036 if (mul > PG_INT64_MAX / 16)
7037 {
7038 /* Add the contribution from this group of digits */
7040 mul_var(dest, &tmp_var, dest, 0);
7042 add_var(dest, &tmp_var, dest);
7043
7044 /* Result will overflow if weight overflows int16 */
7045 if (dest->weight > NUMERIC_WEIGHT_MAX)
7046 goto out_of_range;
7047
7048 /* Begin a new group */
7049 tmp = 0;
7050 mul = 1;
7051 }
7052
7053 tmp = tmp * 16 + xdigit_value(*cp++);
7054 mul = mul * 16;
7055 }
7056 else if (*cp == '_')
7057 {
7058 /* Underscore must be followed by more digits */
7059 cp++;
7060 if (!isxdigit((unsigned char) *cp))
7061 goto invalid_syntax;
7062 }
7063 else
7064 break;
7065 }
7066 }
7067 else if (base == 8)
7068 {
7069 while (*cp)
7070 {
7071 if (*cp >= '0' && *cp <= '7')
7072 {
7073 if (mul > PG_INT64_MAX / 8)
7074 {
7075 /* Add the contribution from this group of digits */
7077 mul_var(dest, &tmp_var, dest, 0);
7079 add_var(dest, &tmp_var, dest);
7080
7081 /* Result will overflow if weight overflows int16 */
7082 if (dest->weight > NUMERIC_WEIGHT_MAX)
7083 goto out_of_range;
7084
7085 /* Begin a new group */
7086 tmp = 0;
7087 mul = 1;
7088 }
7089
7090 tmp = tmp * 8 + (*cp++ - '0');
7091 mul = mul * 8;
7092 }
7093 else if (*cp == '_')
7094 {
7095 /* Underscore must be followed by more digits */
7096 cp++;
7097 if (*cp < '0' || *cp > '7')
7098 goto invalid_syntax;
7099 }
7100 else
7101 break;
7102 }
7103 }
7104 else if (base == 2)
7105 {
7106 while (*cp)
7107 {
7108 if (*cp >= '0' && *cp <= '1')
7109 {
7110 if (mul > PG_INT64_MAX / 2)
7111 {
7112 /* Add the contribution from this group of digits */
7114 mul_var(dest, &tmp_var, dest, 0);
7116 add_var(dest, &tmp_var, dest);
7117
7118 /* Result will overflow if weight overflows int16 */
7119 if (dest->weight > NUMERIC_WEIGHT_MAX)
7120 goto out_of_range;
7121
7122 /* Begin a new group */
7123 tmp = 0;
7124 mul = 1;
7125 }
7126
7127 tmp = tmp * 2 + (*cp++ - '0');
7128 mul = mul * 2;
7129 }
7130 else if (*cp == '_')
7131 {
7132 /* Underscore must be followed by more digits */
7133 cp++;
7134 if (*cp < '0' || *cp > '1')
7135 goto invalid_syntax;
7136 }
7137 else
7138 break;
7139 }
7140 }
7141 else
7142 /* Should never happen; treat as invalid input */
7143 goto invalid_syntax;
7144
7145 /* Check that we got at least one digit */
7146 if (unlikely(cp == firstdigit))
7147 goto invalid_syntax;
7148
7149 /* Add the contribution from the final group of digits */
7151 mul_var(dest, &tmp_var, dest, 0);
7153 add_var(dest, &tmp_var, dest);
7154
7155 if (dest->weight > NUMERIC_WEIGHT_MAX)
7156 goto out_of_range;
7157
7158 dest->sign = sign;
7159
7160 free_var(&tmp_var);
7161
7162 /* Return end+1 position for caller */
7163 *endptr = cp;
7164
7165 return true;
7166
7168 ereturn(escontext, false,
7170 errmsg("value overflows numeric format")));
7171
7173 ereturn(escontext, false,
7175 errmsg("invalid input syntax for type %s: \"%s\"",
7176 "numeric", str)));
7177}
static int xdigit_value(char dig)
Definition numeric.c:6981

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

7187{
7188 int ndigits;
7189
7190 ndigits = NUMERIC_NDIGITS(num);
7191
7192 alloc_var(dest, ndigits);
7193
7194 dest->weight = NUMERIC_WEIGHT(num);
7195 dest->sign = NUMERIC_SIGN(num);
7196 dest->dscale = NUMERIC_DSCALE(num);
7197
7198 memcpy(dest->digits, NUMERIC_DIGITS(num), ndigits * sizeof(NumericDigit));
7199}

References alloc_var(), memcpy(), 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 6778 of file numeric.c.

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

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

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

◆ set_var_from_var()

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

Definition at line 7234 of file numeric.c.

7235{
7237
7238 newbuf = digitbuf_alloc(value->ndigits + 1);
7239 newbuf[0] = 0; /* spare digit for rounding */
7240 if (value->ndigits > 0) /* else value->digits might be null */
7241 memcpy(newbuf + 1, value->digits,
7242 value->ndigits * sizeof(NumericDigit));
7243
7244 digitbuf_free(dest->buf);
7245
7246 memmove(dest, value, sizeof(NumericVar));
7247 dest->buf = newbuf;
7248 dest->digits = newbuf + 1;
7249}

References digitbuf_alloc, digitbuf_free, fb(), memcpy(), 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 9967 of file numeric.c.

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

References a1, add_var(), alloc_var(), arg, Assert, b, cmp_var(), const_one, const_zero, DEC_DIGITS, div_mod_var(), ereport, errcode(), errmsg, ERROR, fb(), free_var(), i, init_var, int128_to_numericvar(), int64_to_numericvar(), Max, memcpy(), Min, mul_var(), NBASE, NUMERIC_NEG, NUMERIC_POS, result, round_var(), set_var_from_var(), stat, strip_var(), sub_var(), 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 11824 of file numeric.c.

11825{
11826 NumericDigit *digits = var->digits;
11827 int ndigits = var->ndigits;
11828
11829 /* Strip leading zeroes */
11830 while (ndigits > 0 && *digits == 0)
11831 {
11832 digits++;
11833 var->weight--;
11834 ndigits--;
11835 }
11836
11837 /* Strip trailing zeroes */
11838 while (ndigits > 0 && digits[ndigits - 1] == 0)
11839 ndigits--;
11840
11841 /* If it's zero, normalize the sign and weight */
11842 if (ndigits == 0)
11843 {
11844 var->sign = NUMERIC_POS;
11845 var->weight = 0;
11846 }
11847
11848 var->digits = digits;
11849 var->ndigits = ndigits;
11850}

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

11575{
11578 int res_ndigits;
11579 int res_weight;
11580 int res_rscale,
11581 rscale1,
11582 rscale2;
11583 int res_dscale;
11584 int i,
11585 i1,
11586 i2;
11587 int borrow = 0;
11588
11589 /* copy these values into local vars for speed in inner loop */
11590 int var1ndigits = var1->ndigits;
11591 int var2ndigits = var2->ndigits;
11592 NumericDigit *var1digits = var1->digits;
11593 NumericDigit *var2digits = var2->digits;
11594
11595 res_weight = var1->weight;
11596
11597 res_dscale = Max(var1->dscale, var2->dscale);
11598
11599 /* Note: here we are figuring rscale in base-NBASE digits */
11600 rscale1 = var1->ndigits - var1->weight - 1;
11601 rscale2 = var2->ndigits - var2->weight - 1;
11603
11605 if (res_ndigits <= 0)
11606 res_ndigits = 1;
11607
11609 res_buf[0] = 0; /* spare digit for later rounding */
11610 res_digits = res_buf + 1;
11611
11612 i1 = res_rscale + var1->weight + 1;
11613 i2 = res_rscale + var2->weight + 1;
11614 for (i = res_ndigits - 1; i >= 0; i--)
11615 {
11616 i1--;
11617 i2--;
11618 if (i1 >= 0 && i1 < var1ndigits)
11619 borrow += var1digits[i1];
11620 if (i2 >= 0 && i2 < var2ndigits)
11621 borrow -= var2digits[i2];
11622
11623 if (borrow < 0)
11624 {
11625 res_digits[i] = borrow + NBASE;
11626 borrow = -1;
11627 }
11628 else
11629 {
11630 res_digits[i] = borrow;
11631 borrow = 0;
11632 }
11633 }
11634
11635 Assert(borrow == 0); /* else caller gave us var1 < var2 */
11636
11637 digitbuf_free(result->buf);
11638 result->ndigits = res_ndigits;
11639 result->buf = res_buf;
11640 result->digits = res_digits;
11641 result->weight = res_weight;
11642 result->dscale = res_dscale;
11643
11644 /* Remove leading/trailing zeroes */
11646}

References Assert, digitbuf_alloc, digitbuf_free, fb(), i, Max, NBASE, result, and strip_var().

Referenced by add_var(), PGTYPESnumeric_add(), PGTYPESnumeric_div(), PGTYPESnumeric_sub(), and sub_var().

◆ sub_var()

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

Definition at line 8214 of file numeric.c.

8215{
8216 /*
8217 * Decide on the signs of the two variables what to do
8218 */
8219 if (var1->sign == NUMERIC_POS)
8220 {
8221 if (var2->sign == NUMERIC_NEG)
8222 {
8223 /* ----------
8224 * var1 is positive, var2 is negative
8225 * result = +(ABS(var1) + ABS(var2))
8226 * ----------
8227 */
8229 result->sign = NUMERIC_POS;
8230 }
8231 else
8232 {
8233 /* ----------
8234 * Both are positive
8235 * Must compare absolute values
8236 * ----------
8237 */
8238 switch (cmp_abs(var1, var2))
8239 {
8240 case 0:
8241 /* ----------
8242 * ABS(var1) == ABS(var2)
8243 * result = ZERO
8244 * ----------
8245 */
8247 result->dscale = Max(var1->dscale, var2->dscale);
8248 break;
8249
8250 case 1:
8251 /* ----------
8252 * ABS(var1) > ABS(var2)
8253 * result = +(ABS(var1) - ABS(var2))
8254 * ----------
8255 */
8257 result->sign = NUMERIC_POS;
8258 break;
8259
8260 case -1:
8261 /* ----------
8262 * ABS(var1) < ABS(var2)
8263 * result = -(ABS(var2) - ABS(var1))
8264 * ----------
8265 */
8267 result->sign = NUMERIC_NEG;
8268 break;
8269 }
8270 }
8271 }
8272 else
8273 {
8274 if (var2->sign == NUMERIC_NEG)
8275 {
8276 /* ----------
8277 * Both are negative
8278 * Must compare absolute values
8279 * ----------
8280 */
8281 switch (cmp_abs(var1, var2))
8282 {
8283 case 0:
8284 /* ----------
8285 * ABS(var1) == ABS(var2)
8286 * result = ZERO
8287 * ----------
8288 */
8290 result->dscale = Max(var1->dscale, var2->dscale);
8291 break;
8292
8293 case 1:
8294 /* ----------
8295 * ABS(var1) > ABS(var2)
8296 * result = -(ABS(var1) - ABS(var2))
8297 * ----------
8298 */
8300 result->sign = NUMERIC_NEG;
8301 break;
8302
8303 case -1:
8304 /* ----------
8305 * ABS(var1) < ABS(var2)
8306 * result = +(ABS(var2) - ABS(var1))
8307 * ----------
8308 */
8310 result->sign = NUMERIC_POS;
8311 break;
8312 }
8313 }
8314 else
8315 {
8316 /* ----------
8317 * var1 is negative, var2 is positive
8318 * result = -(ABS(var1) + ABS(var2))
8319 * ----------
8320 */
8322 result->sign = NUMERIC_NEG;
8323 }
8324 }
8325}

References add_abs(), cmp_abs(), fb(), Max, NUMERIC_NEG, NUMERIC_POS, result, 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 11762 of file numeric.c.

11763{
11764 int di;
11765 int ndigits;
11766
11767 var->dscale = rscale;
11768
11769 /* decimal digits wanted */
11770 di = (var->weight + 1) * DEC_DIGITS + rscale;
11771
11772 /*
11773 * If di <= 0, the value loses all digits.
11774 */
11775 if (di <= 0)
11776 {
11777 var->ndigits = 0;
11778 var->weight = 0;
11779 var->sign = NUMERIC_POS;
11780 }
11781 else
11782 {
11783 /* NBASE digits wanted */
11784 ndigits = (di + DEC_DIGITS - 1) / DEC_DIGITS;
11785
11786 if (ndigits <= var->ndigits)
11787 {
11788 var->ndigits = ndigits;
11789
11790#if DEC_DIGITS == 1
11791 /* no within-digit stuff to worry about */
11792#else
11793 /* 0, or number of decimal digits to keep in last NBASE digit */
11794 di %= DEC_DIGITS;
11795
11796 if (di > 0)
11797 {
11798 /* Must truncate within last NBASE digit */
11799 NumericDigit *digits = var->digits;
11800 int extra,
11801 pow10;
11802
11803#if DEC_DIGITS == 4
11805#elif DEC_DIGITS == 2
11806 pow10 = 10;
11807#else
11808#error unsupported NBASE
11809#endif
11810 extra = digits[--ndigits] % pow10;
11811 digits[ndigits] -= extra;
11812 }
11813#endif
11814 }
11815 }
11816}

References DEC_DIGITS, NumericVar::digits, digits, NumericVar::dscale, fb(), 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 1958 of file numeric.c.

1959{
1960 Numeric operand = PG_GETARG_NUMERIC(0);
1963 int32 count = PG_GETARG_INT32(3);
1966 int32 result;
1967
1968 if (count <= 0)
1969 ereport(ERROR,
1971 errmsg("count must be greater than zero")));
1972
1974 {
1976 ereport(ERROR,
1978 errmsg("lower and upper bounds cannot be NaN")));
1979
1981 ereport(ERROR,
1983 errmsg("lower and upper bounds must be finite")));
1984 }
1985
1988
1989 /* Convert 'count' to a numeric, for ease of use later */
1991
1992 switch (cmp_numerics(bound1, bound2))
1993 {
1994 case 0:
1995 ereport(ERROR,
1997 errmsg("lower bound cannot equal upper bound")));
1998 break;
1999
2000 /* bound1 < bound2 */
2001 case -1:
2002 if (cmp_numerics(operand, bound1) < 0)
2004 else if (cmp_numerics(operand, bound2) >= 0)
2006 else
2008 &result_var);
2009 break;
2010
2011 /* bound1 > bound2 */
2012 case 1:
2013 if (cmp_numerics(operand, bound1) > 0)
2015 else if (cmp_numerics(operand, bound2) <= 0)
2017 else
2019 &result_var);
2020 break;
2021 }
2022
2023 /* if result exceeds the range of a legal int4, we ereport here */
2025 ereport(ERROR,
2027 errmsg("integer out of range")));
2028
2031
2033}
static void compute_bucket(Numeric operand, Numeric bound1, Numeric bound2, const NumericVar *count_var, NumericVar *result_var)
Definition numeric.c:2042

References add_var(), cmp_numerics(), compute_bucket(), const_one, const_zero, ereport, errcode(), errmsg, ERROR, fb(), 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, result, and set_var_from_var().

◆ xdigit_value()

static int xdigit_value ( char  dig)
inlinestatic

Definition at line 6981 of file numeric.c.

6982{
6983 return dig >= '0' && dig <= '9' ? dig - '0' :
6984 dig >= 'a' && dig <= 'f' ? dig - 'a' + 10 :
6985 dig >= 'A' && dig <= 'F' ? dig - 'A' + 10 : -1;
6986}

References fb().

Referenced by set_var_from_non_decimal_integer_str().

◆ zero_var()

static void zero_var ( NumericVar var)
static

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.

420{1};

◆ 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.

442{1, 1000};

◆ 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.

427{2};

◆ const_zero

◆ const_zero_data

const NumericDigit const_zero_data[1] = {0}
static

Definition at line 416 of file numeric.c.

416{0};

◆ 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.

432{9000};

◆ round_powers

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

Definition at line 461 of file numeric.c.

461{0, 1000, 100, 10};

Referenced by round_var(), and trunc_var().