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

Go to the source code of this file.

Data Structures

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

Macros

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

Typedefs

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

Functions

static void alloc_var (NumericVar *var, int ndigits)
 
static void free_var (NumericVar *var)
 
static void zero_var (NumericVar *var)
 
static const char * set_var_from_str (const char *str, const char *cp, NumericVar *dest)
 
static void set_var_from_num (Numeric value, NumericVar *dest)
 
static void init_var_from_num (Numeric num, NumericVar *dest)
 
static void set_var_from_var (const NumericVar *value, NumericVar *dest)
 
static char * get_str_from_var (const NumericVar *var)
 
static char * get_str_from_var_sci (const NumericVar *var, int rscale)
 
static Numeric duplicate_numeric (Numeric num)
 
static Numeric make_result (const NumericVar *var)
 
static Numeric make_result_opt_error (const NumericVar *var, bool *error)
 
static void apply_typmod (NumericVar *var, int32 typmod)
 
static void apply_typmod_special (Numeric num, int32 typmod)
 
static bool numericvar_to_int32 (const NumericVar *var, int32 *result)
 
static bool numericvar_to_int64 (const NumericVar *var, int64 *result)
 
static void int64_to_numericvar (int64 val, NumericVar *var)
 
static bool numericvar_to_uint64 (const NumericVar *var, uint64 *result)
 
static double numericvar_to_double_no_overflow (const NumericVar *var)
 
static Datum numeric_abbrev_convert (Datum original_datum, SortSupport ssup)
 
static bool numeric_abbrev_abort (int memtupcount, SortSupport ssup)
 
static int numeric_fast_cmp (Datum x, Datum y, SortSupport ssup)
 
static int numeric_cmp_abbrev (Datum x, Datum y, SortSupport ssup)
 
static Datum numeric_abbrev_convert_var (const NumericVar *var, NumericSortSupport *nss)
 
static int cmp_numerics (Numeric num1, Numeric num2)
 
static int cmp_var (const NumericVar *var1, const NumericVar *var2)
 
static int cmp_var_common (const NumericDigit *var1digits, int var1ndigits, int var1weight, int var1sign, const NumericDigit *var2digits, int var2ndigits, int var2weight, int var2sign)
 
static void add_var (const NumericVar *var1, const NumericVar *var2, NumericVar *result)
 
static void sub_var (const NumericVar *var1, const NumericVar *var2, NumericVar *result)
 
static void mul_var (const NumericVar *var1, const NumericVar *var2, NumericVar *result, int rscale)
 
static void div_var (const NumericVar *var1, const NumericVar *var2, NumericVar *result, int rscale, bool round)
 
static void div_var_fast (const NumericVar *var1, const NumericVar *var2, NumericVar *result, int rscale, bool round)
 
static 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, NumericVar *result, int rscale)
 
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 *var1)
 
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)
 
int32 numeric_maximum_size (int32 typmod)
 
char * numeric_out_sci (Numeric num, int scale)
 
char * numeric_normalize (Numeric num)
 
Datum numeric_recv (PG_FUNCTION_ARGS)
 
Datum numeric_send (PG_FUNCTION_ARGS)
 
Datum numeric_support (PG_FUNCTION_ARGS)
 
Datum numeric (PG_FUNCTION_ARGS)
 
Datum numerictypmodin (PG_FUNCTION_ARGS)
 
Datum numerictypmodout (PG_FUNCTION_ARGS)
 
Datum numeric_abs (PG_FUNCTION_ARGS)
 
Datum numeric_uminus (PG_FUNCTION_ARGS)
 
Datum numeric_uplus (PG_FUNCTION_ARGS)
 
static int numeric_sign_internal (Numeric num)
 
Datum numeric_sign (PG_FUNCTION_ARGS)
 
Datum numeric_round (PG_FUNCTION_ARGS)
 
Datum numeric_trunc (PG_FUNCTION_ARGS)
 
Datum numeric_ceil (PG_FUNCTION_ARGS)
 
Datum numeric_floor (PG_FUNCTION_ARGS)
 
Datum generate_series_numeric (PG_FUNCTION_ARGS)
 
Datum generate_series_step_numeric (PG_FUNCTION_ARGS)
 
Datum width_bucket_numeric (PG_FUNCTION_ARGS)
 
Datum numeric_sortsupport (PG_FUNCTION_ARGS)
 
Datum numeric_cmp (PG_FUNCTION_ARGS)
 
Datum numeric_eq (PG_FUNCTION_ARGS)
 
Datum numeric_ne (PG_FUNCTION_ARGS)
 
Datum numeric_gt (PG_FUNCTION_ARGS)
 
Datum numeric_ge (PG_FUNCTION_ARGS)
 
Datum numeric_lt (PG_FUNCTION_ARGS)
 
Datum numeric_le (PG_FUNCTION_ARGS)
 
Datum in_range_numeric_numeric (PG_FUNCTION_ARGS)
 
Datum hash_numeric (PG_FUNCTION_ARGS)
 
Datum hash_numeric_extended (PG_FUNCTION_ARGS)
 
Datum numeric_add (PG_FUNCTION_ARGS)
 
Numeric numeric_add_opt_error (Numeric num1, Numeric num2, bool *have_error)
 
Datum numeric_sub (PG_FUNCTION_ARGS)
 
Numeric numeric_sub_opt_error (Numeric num1, Numeric num2, bool *have_error)
 
Datum numeric_mul (PG_FUNCTION_ARGS)
 
Numeric numeric_mul_opt_error (Numeric num1, Numeric num2, bool *have_error)
 
Datum numeric_div (PG_FUNCTION_ARGS)
 
Numeric numeric_div_opt_error (Numeric num1, Numeric num2, bool *have_error)
 
Datum numeric_div_trunc (PG_FUNCTION_ARGS)
 
Datum numeric_mod (PG_FUNCTION_ARGS)
 
Numeric numeric_mod_opt_error (Numeric num1, Numeric num2, bool *have_error)
 
Datum numeric_inc (PG_FUNCTION_ARGS)
 
Datum numeric_smaller (PG_FUNCTION_ARGS)
 
Datum numeric_larger (PG_FUNCTION_ARGS)
 
Datum numeric_gcd (PG_FUNCTION_ARGS)
 
Datum numeric_lcm (PG_FUNCTION_ARGS)
 
Datum numeric_fac (PG_FUNCTION_ARGS)
 
Datum numeric_sqrt (PG_FUNCTION_ARGS)
 
Datum numeric_exp (PG_FUNCTION_ARGS)
 
Datum numeric_ln (PG_FUNCTION_ARGS)
 
Datum numeric_log (PG_FUNCTION_ARGS)
 
Datum numeric_power (PG_FUNCTION_ARGS)
 
Datum numeric_scale (PG_FUNCTION_ARGS)
 
static int get_min_scale (NumericVar *var)
 
Datum numeric_min_scale (PG_FUNCTION_ARGS)
 
Datum numeric_trim_scale (PG_FUNCTION_ARGS)
 
Numeric int64_to_numeric (int64 val)
 
Datum int4_numeric (PG_FUNCTION_ARGS)
 
int32 numeric_int4_opt_error (Numeric num, bool *have_error)
 
Datum numeric_int4 (PG_FUNCTION_ARGS)
 
Datum int8_numeric (PG_FUNCTION_ARGS)
 
Datum numeric_int8 (PG_FUNCTION_ARGS)
 
Datum int2_numeric (PG_FUNCTION_ARGS)
 
Datum numeric_int2 (PG_FUNCTION_ARGS)
 
Datum float8_numeric (PG_FUNCTION_ARGS)
 
Datum numeric_float8 (PG_FUNCTION_ARGS)
 
Datum numeric_float8_no_overflow (PG_FUNCTION_ARGS)
 
Datum float4_numeric (PG_FUNCTION_ARGS)
 
Datum numeric_float4 (PG_FUNCTION_ARGS)
 
Datum numeric_pg_lsn (PG_FUNCTION_ARGS)
 
static NumericAggStatemakeNumericAggState (FunctionCallInfo fcinfo, bool calcSumX2)
 
static NumericAggStatemakeNumericAggStateCurrentContext (bool calcSumX2)
 
static void do_numeric_accum (NumericAggState *state, Numeric newval)
 
static bool do_numeric_discard (NumericAggState *state, Numeric newval)
 
Datum numeric_accum (PG_FUNCTION_ARGS)
 
Datum numeric_combine (PG_FUNCTION_ARGS)
 
Datum numeric_avg_accum (PG_FUNCTION_ARGS)
 
Datum numeric_avg_combine (PG_FUNCTION_ARGS)
 
Datum numeric_avg_serialize (PG_FUNCTION_ARGS)
 
Datum numeric_avg_deserialize (PG_FUNCTION_ARGS)
 
Datum numeric_serialize (PG_FUNCTION_ARGS)
 
Datum numeric_deserialize (PG_FUNCTION_ARGS)
 
Datum numeric_accum_inv (PG_FUNCTION_ARGS)
 
Datum int2_accum (PG_FUNCTION_ARGS)
 
Datum int4_accum (PG_FUNCTION_ARGS)
 
Datum int8_accum (PG_FUNCTION_ARGS)
 
Datum numeric_poly_combine (PG_FUNCTION_ARGS)
 
Datum numeric_poly_serialize (PG_FUNCTION_ARGS)
 
Datum numeric_poly_deserialize (PG_FUNCTION_ARGS)
 
Datum int8_avg_accum (PG_FUNCTION_ARGS)
 
Datum int8_avg_combine (PG_FUNCTION_ARGS)
 
Datum int8_avg_serialize (PG_FUNCTION_ARGS)
 
Datum int8_avg_deserialize (PG_FUNCTION_ARGS)
 
Datum int2_accum_inv (PG_FUNCTION_ARGS)
 
Datum int4_accum_inv (PG_FUNCTION_ARGS)
 
Datum int8_accum_inv (PG_FUNCTION_ARGS)
 
Datum int8_avg_accum_inv (PG_FUNCTION_ARGS)
 
Datum numeric_poly_sum (PG_FUNCTION_ARGS)
 
Datum numeric_poly_avg (PG_FUNCTION_ARGS)
 
Datum numeric_avg (PG_FUNCTION_ARGS)
 
Datum numeric_sum (PG_FUNCTION_ARGS)
 
static Numeric numeric_stddev_internal (NumericAggState *state, bool variance, bool sample, bool *is_null)
 
Datum numeric_var_samp (PG_FUNCTION_ARGS)
 
Datum numeric_stddev_samp (PG_FUNCTION_ARGS)
 
Datum numeric_var_pop (PG_FUNCTION_ARGS)
 
Datum numeric_stddev_pop (PG_FUNCTION_ARGS)
 
Datum numeric_poly_var_samp (PG_FUNCTION_ARGS)
 
Datum numeric_poly_stddev_samp (PG_FUNCTION_ARGS)
 
Datum numeric_poly_var_pop (PG_FUNCTION_ARGS)
 
Datum numeric_poly_stddev_pop (PG_FUNCTION_ARGS)
 
Datum int2_sum (PG_FUNCTION_ARGS)
 
Datum int4_sum (PG_FUNCTION_ARGS)
 
Datum int8_sum (PG_FUNCTION_ARGS)
 
Datum int2_avg_accum (PG_FUNCTION_ARGS)
 
Datum int4_avg_accum (PG_FUNCTION_ARGS)
 
Datum int4_avg_combine (PG_FUNCTION_ARGS)
 
Datum int2_avg_accum_inv (PG_FUNCTION_ARGS)
 
Datum int4_avg_accum_inv (PG_FUNCTION_ARGS)
 
Datum int8_avg (PG_FUNCTION_ARGS)
 
Datum int2int4_sum (PG_FUNCTION_ARGS)
 

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_ten_data [1] = {10}
 
static const NumericVar const_ten
 
static const NumericDigit const_zero_point_nine_data [1] = {9000}
 
static const NumericVar const_zero_point_nine
 
static const NumericDigit const_one_point_one_data [2] = {1, 1000}
 
static const NumericVar const_one_point_one
 
static const NumericVar const_nan
 
static const NumericVar const_pinf
 
static const NumericVar const_ninf
 
static const int round_powers [4] = {0, 1000, 100, 10}
 

Macro Definition Documentation

◆ DatumGetNumericAbbrev

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

Definition at line 404 of file numeric.c.

Referenced by numeric_cmp_abbrev().

◆ DEC_DIGITS

◆ digitbuf_alloc

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

Definition at line 487 of file numeric.c.

Referenced by accum_sum_final(), add_abs(), alloc_var(), set_var_from_var(), and sub_abs().

◆ digitbuf_free

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

Definition at line 489 of file numeric.c.

Referenced by add_abs(), alloc_var(), free_var(), set_var_from_var(), sub_abs(), and zero_var().

◆ DIV_GUARD_DIGITS

#define DIV_GUARD_DIGITS   4

Definition at line 101 of file numeric.c.

Referenced by div_var_fast().

◆ dump_numeric

#define dump_numeric (   s,
 
)

Definition at line 483 of file numeric.c.

Referenced by int2int4_sum(), and make_result_opt_error().

◆ dump_var

#define dump_var (   s,
 
)

Definition at line 484 of file numeric.c.

Referenced by int2int4_sum().

◆ HALF_NBASE

#define HALF_NBASE   5000

Definition at line 98 of file numeric.c.

Referenced by div_var(), and round_var().

◆ init_var

◆ makePolyNumAggState

#define makePolyNumAggState   makeNumericAggState

◆ makePolyNumAggStateCurrentContext

#define makePolyNumAggStateCurrentContext   makeNumericAggStateCurrentContext

Definition at line 5260 of file numeric.c.

Referenced by int8_avg_deserialize(), and numeric_poly_deserialize().

◆ MUL_GUARD_DIGITS

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

Definition at line 100 of file numeric.c.

Referenced by mul_var().

◆ NA_TOTAL_COUNT

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

Definition at line 4484 of file numeric.c.

Referenced by numeric_avg(), numeric_stddev_internal(), and numeric_sum().

◆ NBASE

◆ NUMERIC_ABBREV_BITS

#define NUMERIC_ABBREV_BITS   (SIZEOF_DATUM * BITS_PER_BYTE)

Definition at line 395 of file numeric.c.

◆ NUMERIC_ABBREV_NAN

#define NUMERIC_ABBREV_NAN   NumericAbbrevGetDatum(PG_INT32_MIN)

Definition at line 405 of file numeric.c.

Referenced by numeric_abbrev_convert().

◆ NUMERIC_ABBREV_NINF

#define NUMERIC_ABBREV_NINF   NumericAbbrevGetDatum(PG_INT32_MAX)

Definition at line 407 of file numeric.c.

Referenced by numeric_abbrev_convert().

◆ NUMERIC_ABBREV_PINF

#define NUMERIC_ABBREV_PINF   NumericAbbrevGetDatum(-PG_INT32_MAX)

Definition at line 406 of file numeric.c.

Referenced by numeric_abbrev_convert().

◆ NUMERIC_CAN_BE_SHORT

#define NUMERIC_CAN_BE_SHORT (   scale,
  weight 
)
Value:
(weight) <= NUMERIC_SHORT_WEIGHT_MAX && \
#define NUMERIC_SHORT_WEIGHT_MAX
Definition: numeric.c:222
int scale
Definition: pgbench.c:154
#define NUMERIC_SHORT_WEIGHT_MIN
Definition: numeric.c:223
#define NUMERIC_SHORT_DSCALE_MAX
Definition: numeric.c:218

Definition at line 501 of file numeric.c.

Referenced by make_result_opt_error(), and numeric().

◆ NUMERIC_DIGITS

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

Definition at line 497 of file numeric.c.

Referenced by cmp_numerics(), hash_numeric(), hash_numeric_extended(), init_var_from_num(), int2int4_sum(), make_result_opt_error(), and set_var_from_num().

◆ 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_HEADER_IS_SHORT(n)
Definition: numeric.c:184
#define NUMERIC_DSCALE_MASK
Definition: numeric.c:235
#define NUMERIC_SHORT_DSCALE_MASK
Definition: numeric.c:216
#define NUMERIC_SHORT_DSCALE_SHIFT
Definition: numeric.c:217

Definition at line 243 of file numeric.c.

Referenced by init_var_from_num(), int2int4_sum(), make_result_opt_error(), numeric(), numeric_abs(), numeric_scale(), numeric_uminus(), and set_var_from_num().

◆ NUMERIC_DSCALE_MASK

#define NUMERIC_DSCALE_MASK   0x3FFF

Definition at line 235 of file numeric.c.

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

◆ NUMERIC_EXT_FLAGBITS

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

Definition at line 204 of file numeric.c.

◆ NUMERIC_EXT_SIGN_MASK

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

Definition at line 198 of file numeric.c.

◆ NUMERIC_FLAGBITS

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

Definition at line 172 of file numeric.c.

◆ NUMERIC_HDRSZ

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

Definition at line 176 of file numeric.c.

Referenced by make_result_opt_error(), and numeric_maximum_size().

◆ NUMERIC_HDRSZ_SHORT

#define NUMERIC_HDRSZ_SHORT   (VARHDRSZ + sizeof(uint16))

Definition at line 177 of file numeric.c.

Referenced by make_result_opt_error().

◆ NUMERIC_HEADER_IS_SHORT

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

Definition at line 184 of file numeric.c.

◆ NUMERIC_HEADER_SIZE

#define NUMERIC_HEADER_SIZE (   n)
Value:
(VARHDRSZ + sizeof(uint16) + \
(NUMERIC_HEADER_IS_SHORT(n) ? 0 : sizeof(int16)))
signed short int16
Definition: c.h:361
#define NUMERIC_HEADER_IS_SHORT(n)
Definition: numeric.c:184
#define VARHDRSZ
Definition: c.h:568
unsigned short uint16
Definition: c.h:373

Definition at line 185 of file numeric.c.

◆ NUMERIC_INF_SIGN_MASK

#define NUMERIC_INF_SIGN_MASK   0x2000

Definition at line 202 of file numeric.c.

Referenced by numeric_abs(), and numeric_uminus().

◆ NUMERIC_IS_INF

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

Definition at line 208 of file numeric.c.

Referenced by numeric_is_inf(), numeric_mod_opt_error(), and numeric_power().

◆ NUMERIC_IS_NAN

◆ NUMERIC_IS_NINF

◆ NUMERIC_IS_PINF

◆ NUMERIC_IS_SHORT

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

Definition at line 173 of file numeric.c.

Referenced by numeric(), numeric_abs(), and numeric_uminus().

◆ NUMERIC_IS_SPECIAL

◆ NUMERIC_NAN

#define NUMERIC_NAN   0xC000

◆ NUMERIC_NDIGITS

◆ NUMERIC_NEG

◆ NUMERIC_NINF

#define NUMERIC_NINF   0xF000

Definition at line 201 of file numeric.c.

Referenced by int2int4_sum(), make_result_opt_error(), and numeric_recv().

◆ NUMERIC_PINF

#define NUMERIC_PINF   0xD000

Definition at line 200 of file numeric.c.

Referenced by int2int4_sum(), make_result_opt_error(), and numeric_recv().

◆ NUMERIC_POS

◆ NUMERIC_SHORT

#define NUMERIC_SHORT   0x8000

Definition at line 169 of file numeric.c.

Referenced by make_result_opt_error().

◆ NUMERIC_SHORT_DSCALE_MASK

#define NUMERIC_SHORT_DSCALE_MASK   0x1F80

Definition at line 216 of file numeric.c.

Referenced by numeric().

◆ NUMERIC_SHORT_DSCALE_MAX

#define NUMERIC_SHORT_DSCALE_MAX   (NUMERIC_SHORT_DSCALE_MASK >> NUMERIC_SHORT_DSCALE_SHIFT)

Definition at line 218 of file numeric.c.

◆ NUMERIC_SHORT_DSCALE_SHIFT

#define NUMERIC_SHORT_DSCALE_SHIFT   7

Definition at line 217 of file numeric.c.

Referenced by make_result_opt_error(), and numeric().

◆ NUMERIC_SHORT_SIGN_MASK

#define NUMERIC_SHORT_SIGN_MASK   0x2000

Definition at line 215 of file numeric.c.

Referenced by make_result_opt_error(), numeric_abs(), and numeric_uminus().

◆ NUMERIC_SHORT_WEIGHT_MASK

#define NUMERIC_SHORT_WEIGHT_MASK   0x003F

Definition at line 221 of file numeric.c.

Referenced by make_result_opt_error().

◆ NUMERIC_SHORT_WEIGHT_MAX

#define NUMERIC_SHORT_WEIGHT_MAX   NUMERIC_SHORT_WEIGHT_MASK

Definition at line 222 of file numeric.c.

◆ NUMERIC_SHORT_WEIGHT_MIN

#define NUMERIC_SHORT_WEIGHT_MIN   (-(NUMERIC_SHORT_WEIGHT_MASK+1))

Definition at line 223 of file numeric.c.

◆ NUMERIC_SHORT_WEIGHT_SIGN_MASK

#define NUMERIC_SHORT_WEIGHT_SIGN_MASK   0x0040

Definition at line 220 of file numeric.c.

Referenced by make_result_opt_error().

◆ NUMERIC_SIGN

#define NUMERIC_SIGN (   n)
Value:
(((n)->choice.n_short.n_header & NUMERIC_SHORT_SIGN_MASK) ? \
NUMERIC_NEG : NUMERIC_POS) : \
NUMERIC_EXT_FLAGBITS(n) : NUMERIC_FLAGBITS(n)))
#define NUMERIC_POS
Definition: numeric.c:167
#define NUMERIC_FLAGBITS(n)
Definition: numeric.c:172
#define NUMERIC_IS_SPECIAL(n)
Definition: numeric.c:174
#define NUMERIC_SHORT_SIGN_MASK
Definition: numeric.c:215
#define NUMERIC_IS_SHORT(n)
Definition: numeric.c:173

Definition at line 237 of file numeric.c.

Referenced by cmp_numerics(), in_range_numeric_numeric(), init_var_from_num(), int2int4_sum(), numeric(), numeric_sign_internal(), numeric_uminus(), and set_var_from_num().

◆ NUMERIC_SIGN_MASK

#define NUMERIC_SIGN_MASK   0xC000

Definition at line 166 of file numeric.c.

Referenced by make_result_opt_error().

◆ NUMERIC_SPECIAL

#define NUMERIC_SPECIAL   0xC000

Definition at line 170 of file numeric.c.

Referenced by make_result_opt_error().

◆ 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_HEADER_IS_SHORT(n)
Definition: numeric.c:184
#define NUMERIC_SHORT_WEIGHT_SIGN_MASK
Definition: numeric.c:220
#define NUMERIC_SHORT_WEIGHT_MASK
Definition: numeric.c:221

Definition at line 247 of file numeric.c.

Referenced by cmp_numerics(), hash_numeric(), hash_numeric_extended(), init_var_from_num(), int2int4_sum(), make_result_opt_error(), numeric(), and set_var_from_num().

◆ NumericAbbrevGetDatum

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

Definition at line 403 of file numeric.c.

Referenced by numeric_cmp_abbrev().

Typedef Documentation

◆ Int8TransTypeData

◆ NumericAggState

◆ NumericDigit

Definition at line 103 of file numeric.c.

◆ NumericSumAccum

◆ NumericVar

typedef struct NumericVar NumericVar

◆ PolyNumAggState

Definition at line 5258 of file numeric.c.

Function Documentation

◆ accum_sum_add()

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

Definition at line 10851 of file numeric.c.

References accum_sum_carry(), accum_sum_rescale(), NumericVar::digits, i, NBASE, NumericVar::ndigits, NumericSumAccum::neg_digits, NumericSumAccum::num_uncarried, NUMERIC_POS, NumericSumAccum::pos_digits, NumericVar::sign, NumericVar::weight, and NumericSumAccum::weight.

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

10852 {
10853  int32 *accum_digits;
10854  int i,
10855  val_i;
10856  int val_ndigits;
10857  NumericDigit *val_digits;
10858 
10859  /*
10860  * If we have accumulated too many values since the last carry
10861  * propagation, do it now, to avoid overflowing. (We could allow more
10862  * than NBASE - 1, if we reserved two extra digits, rather than one, for
10863  * carry propagation. But even with NBASE - 1, this needs to be done so
10864  * seldom, that the performance difference is negligible.)
10865  */
10866  if (accum->num_uncarried == NBASE - 1)
10867  accum_sum_carry(accum);
10868 
10869  /*
10870  * Adjust the weight or scale of the old value, so that it can accommodate
10871  * the new value.
10872  */
10873  accum_sum_rescale(accum, val);
10874 
10875  /* */
10876  if (val->sign == NUMERIC_POS)
10877  accum_digits = accum->pos_digits;
10878  else
10879  accum_digits = accum->neg_digits;
10880 
10881  /* copy these values into local vars for speed in loop */
10882  val_ndigits = val->ndigits;
10883  val_digits = val->digits;
10884 
10885  i = accum->weight - val->weight;
10886  for (val_i = 0; val_i < val_ndigits; val_i++)
10887  {
10888  accum_digits[i] += (int32) val_digits[val_i];
10889  i++;
10890  }
10891 
10892  accum->num_uncarried++;
10893 }
static void accum_sum_rescale(NumericSumAccum *accum, const NumericVar *val)
Definition: numeric.c:10972
#define NUMERIC_POS
Definition: numeric.c:167
int32 * neg_digits
Definition: numeric.c:379
int num_uncarried
Definition: numeric.c:376
static void accum_sum_carry(NumericSumAccum *accum)
Definition: numeric.c:10899
signed int int32
Definition: c.h:362
int16 NumericDigit
Definition: numeric.c:103
#define NBASE
Definition: numeric.c:97
int i
int32 * pos_digits
Definition: numeric.c:378
long val
Definition: informix.c:664

◆ accum_sum_carry()

static void accum_sum_carry ( NumericSumAccum accum)
static

Definition at line 10899 of file numeric.c.

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

Referenced by accum_sum_add(), and accum_sum_final().

10900 {
10901  int i;
10902  int ndigits;
10903  int32 *dig;
10904  int32 carry;
10905  int32 newdig = 0;
10906 
10907  /*
10908  * If no new values have been added since last carry propagation, nothing
10909  * to do.
10910  */
10911  if (accum->num_uncarried == 0)
10912  return;
10913 
10914  /*
10915  * We maintain that the weight of the accumulator is always one larger
10916  * than needed to hold the current value, before carrying, to make sure
10917  * there is enough space for the possible extra digit when carry is
10918  * propagated. We cannot expand the buffer here, unless we require
10919  * callers of accum_sum_final() to switch to the right memory context.
10920  */
10921  Assert(accum->pos_digits[0] == 0 && accum->neg_digits[0] == 0);
10922 
10923  ndigits = accum->ndigits;
10924 
10925  /* Propagate carry in the positive sum */
10926  dig = accum->pos_digits;
10927  carry = 0;
10928  for (i = ndigits - 1; i >= 0; i--)
10929  {
10930  newdig = dig[i] + carry;
10931  if (newdig >= NBASE)
10932  {
10933  carry = newdig / NBASE;
10934  newdig -= carry * NBASE;
10935  }
10936  else
10937  carry = 0;
10938  dig[i] = newdig;
10939  }
10940  /* Did we use up the digit reserved for carry propagation? */
10941  if (newdig > 0)
10942  accum->have_carry_space = false;
10943 
10944  /* And the same for the negative sum */
10945  dig = accum->neg_digits;
10946  carry = 0;
10947  for (i = ndigits - 1; i >= 0; i--)
10948  {
10949  newdig = dig[i] + carry;
10950  if (newdig >= NBASE)
10951  {
10952  carry = newdig / NBASE;
10953  newdig -= carry * NBASE;
10954  }
10955  else
10956  carry = 0;
10957  dig[i] = newdig;
10958  }
10959  if (newdig > 0)
10960  accum->have_carry_space = false;
10961 
10962  accum->num_uncarried = 0;
10963 }
int32 * neg_digits
Definition: numeric.c:379
int num_uncarried
Definition: numeric.c:376
signed int int32
Definition: c.h:362
bool have_carry_space
Definition: numeric.c:377
#define NBASE
Definition: numeric.c:97
#define Assert(condition)
Definition: c.h:745
int i
int32 * pos_digits
Definition: numeric.c:378

◆ accum_sum_combine()

static void accum_sum_combine ( NumericSumAccum accum,
NumericSumAccum accum2 
)
static

Definition at line 11129 of file numeric.c.

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

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

11130 {
11131  NumericVar tmp_var;
11132 
11133  init_var(&tmp_var);
11134 
11135  accum_sum_final(accum2, &tmp_var);
11136  accum_sum_add(accum, &tmp_var);
11137 
11138  free_var(&tmp_var);
11139 }
static void accum_sum_final(NumericSumAccum *accum, NumericVar *result)
Definition: numeric.c:11061
static void accum_sum_add(NumericSumAccum *accum, const NumericVar *var1)
Definition: numeric.c:10851
static void free_var(NumericVar *var)
Definition: numeric.c:6718
#define init_var(v)
Definition: numeric.c:495

◆ accum_sum_copy()

static void accum_sum_copy ( NumericSumAccum dst,
NumericSumAccum src 
)
static

Definition at line 11112 of file numeric.c.

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

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

11113 {
11114  dst->pos_digits = palloc(src->ndigits * sizeof(int32));
11115  dst->neg_digits = palloc(src->ndigits * sizeof(int32));
11116 
11117  memcpy(dst->pos_digits, src->pos_digits, src->ndigits * sizeof(int32));
11118  memcpy(dst->neg_digits, src->neg_digits, src->ndigits * sizeof(int32));
11119  dst->num_uncarried = src->num_uncarried;
11120  dst->ndigits = src->ndigits;
11121  dst->weight = src->weight;
11122  dst->dscale = src->dscale;
11123 }
int32 * neg_digits
Definition: numeric.c:379
int num_uncarried
Definition: numeric.c:376
signed int int32
Definition: c.h:362
void * palloc(Size size)
Definition: mcxt.c:950
int32 * pos_digits
Definition: numeric.c:378

◆ accum_sum_final()

static void accum_sum_final ( NumericSumAccum accum,
NumericVar result 
)
static

Definition at line 11061 of file numeric.c.

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

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

11062 {
11063  int i;
11064  NumericVar pos_var;
11065  NumericVar neg_var;
11066 
11067  if (accum->ndigits == 0)
11068  {
11069  set_var_from_var(&const_zero, result);
11070  return;
11071  }
11072 
11073  /* Perform final carry */
11074  accum_sum_carry(accum);
11075 
11076  /* Create NumericVars representing the positive and negative sums */
11077  init_var(&pos_var);
11078  init_var(&neg_var);
11079 
11080  pos_var.ndigits = neg_var.ndigits = accum->ndigits;
11081  pos_var.weight = neg_var.weight = accum->weight;
11082  pos_var.dscale = neg_var.dscale = accum->dscale;
11083  pos_var.sign = NUMERIC_POS;
11084  neg_var.sign = NUMERIC_NEG;
11085 
11086  pos_var.buf = pos_var.digits = digitbuf_alloc(accum->ndigits);
11087  neg_var.buf = neg_var.digits = digitbuf_alloc(accum->ndigits);
11088 
11089  for (i = 0; i < accum->ndigits; i++)
11090  {
11091  Assert(accum->pos_digits[i] < NBASE);
11092  pos_var.digits[i] = (int16) accum->pos_digits[i];
11093 
11094  Assert(accum->neg_digits[i] < NBASE);
11095  neg_var.digits[i] = (int16) accum->neg_digits[i];
11096  }
11097 
11098  /* And add them together */
11099  add_var(&pos_var, &neg_var, result);
11100 
11101  /* Remove leading/trailing zeroes */
11102  strip_var(result);
11103 }
signed short int16
Definition: c.h:361
int weight
Definition: numeric.c:307
#define NUMERIC_POS
Definition: numeric.c:167
static void strip_var(NumericVar *var)
Definition: numeric.c:10794
int32 * neg_digits
Definition: numeric.c:379
#define digitbuf_alloc(ndigits)
Definition: numeric.c:487
int ndigits
Definition: numeric.c:306
static void accum_sum_carry(NumericSumAccum *accum)
Definition: numeric.c:10899
int dscale
Definition: numeric.c:309
#define NUMERIC_NEG
Definition: numeric.c:168
int sign
Definition: numeric.c:308
NumericDigit * buf
Definition: numeric.c:310
#define NBASE
Definition: numeric.c:97
static const NumericVar const_zero
Definition: numeric.c:416
#define Assert(condition)
Definition: c.h:745
NumericDigit * digits
Definition: numeric.c:311
static void add_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition: numeric.c:7890
int i
static void set_var_from_var(const NumericVar *value, NumericVar *dest)
Definition: numeric.c:6968
int32 * pos_digits
Definition: numeric.c:378
#define init_var(v)
Definition: numeric.c:495

◆ accum_sum_rescale()

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

Definition at line 10972 of file numeric.c.

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

Referenced by accum_sum_add().

10973 {
10974  int old_weight = accum->weight;
10975  int old_ndigits = accum->ndigits;
10976  int accum_ndigits;
10977  int accum_weight;
10978  int accum_rscale;
10979  int val_rscale;
10980 
10981  accum_weight = old_weight;
10982  accum_ndigits = old_ndigits;
10983 
10984  /*
10985  * Does the new value have a larger weight? If so, enlarge the buffers,
10986  * and shift the existing value to the new weight, by adding leading
10987  * zeros.
10988  *
10989  * We enforce that the accumulator always has a weight one larger than
10990  * needed for the inputs, so that we have space for an extra digit at the
10991  * final carry-propagation phase, if necessary.
10992  */
10993  if (val->weight >= accum_weight)
10994  {
10995  accum_weight = val->weight + 1;
10996  accum_ndigits = accum_ndigits + (accum_weight - old_weight);
10997  }
10998 
10999  /*
11000  * Even though the new value is small, we might've used up the space
11001  * reserved for the carry digit in the last call to accum_sum_carry(). If
11002  * so, enlarge to make room for another one.
11003  */
11004  else if (!accum->have_carry_space)
11005  {
11006  accum_weight++;
11007  accum_ndigits++;
11008  }
11009 
11010  /* Is the new value wider on the right side? */
11011  accum_rscale = accum_ndigits - accum_weight - 1;
11012  val_rscale = val->ndigits - val->weight - 1;
11013  if (val_rscale > accum_rscale)
11014  accum_ndigits = accum_ndigits + (val_rscale - accum_rscale);
11015 
11016  if (accum_ndigits != old_ndigits ||
11017  accum_weight != old_weight)
11018  {
11019  int32 *new_pos_digits;
11020  int32 *new_neg_digits;
11021  int weightdiff;
11022 
11023  weightdiff = accum_weight - old_weight;
11024 
11025  new_pos_digits = palloc0(accum_ndigits * sizeof(int32));
11026  new_neg_digits = palloc0(accum_ndigits * sizeof(int32));
11027 
11028  if (accum->pos_digits)
11029  {
11030  memcpy(&new_pos_digits[weightdiff], accum->pos_digits,
11031  old_ndigits * sizeof(int32));
11032  pfree(accum->pos_digits);
11033 
11034  memcpy(&new_neg_digits[weightdiff], accum->neg_digits,
11035  old_ndigits * sizeof(int32));
11036  pfree(accum->neg_digits);
11037  }
11038 
11039  accum->pos_digits = new_pos_digits;
11040  accum->neg_digits = new_neg_digits;
11041 
11042  accum->weight = accum_weight;
11043  accum->ndigits = accum_ndigits;
11044 
11045  Assert(accum->pos_digits[0] == 0 && accum->neg_digits[0] == 0);
11046  accum->have_carry_space = true;
11047  }
11048 
11049  if (val->dscale > accum->dscale)
11050  accum->dscale = val->dscale;
11051 }
int weight
Definition: numeric.c:307
int32 * neg_digits
Definition: numeric.c:379
int ndigits
Definition: numeric.c:306
int dscale
Definition: numeric.c:309
signed int int32
Definition: c.h:362
void pfree(void *pointer)
Definition: mcxt.c:1057
bool have_carry_space
Definition: numeric.c:377
void * palloc0(Size size)
Definition: mcxt.c:981
#define Assert(condition)
Definition: c.h:745
int32 * pos_digits
Definition: numeric.c:378

◆ accum_sum_reset()

static void accum_sum_reset ( NumericSumAccum accum)
static

Definition at line 10835 of file numeric.c.

References NumericSumAccum::dscale, i, NumericSumAccum::ndigits, NumericSumAccum::neg_digits, and NumericSumAccum::pos_digits.

Referenced by do_numeric_discard().

10836 {
10837  int i;
10838 
10839  accum->dscale = 0;
10840  for (i = 0; i < accum->ndigits; i++)
10841  {
10842  accum->pos_digits[i] = 0;
10843  accum->neg_digits[i] = 0;
10844  }
10845 }
int32 * neg_digits
Definition: numeric.c:379
int i
int32 * pos_digits
Definition: numeric.c:378

◆ add_abs()

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

Definition at line 10459 of file numeric.c.

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

Referenced by add_var(), and sub_var().

10460 {
10461  NumericDigit *res_buf;
10462  NumericDigit *res_digits;
10463  int res_ndigits;
10464  int res_weight;
10465  int res_rscale,
10466  rscale1,
10467  rscale2;
10468  int res_dscale;
10469  int i,
10470  i1,
10471  i2;
10472  int carry = 0;
10473 
10474  /* copy these values into local vars for speed in inner loop */
10475  int var1ndigits = var1->ndigits;
10476  int var2ndigits = var2->ndigits;
10477  NumericDigit *var1digits = var1->digits;
10478  NumericDigit *var2digits = var2->digits;
10479 
10480  res_weight = Max(var1->weight, var2->weight) + 1;
10481 
10482  res_dscale = Max(var1->dscale, var2->dscale);
10483 
10484  /* Note: here we are figuring rscale in base-NBASE digits */
10485  rscale1 = var1->ndigits - var1->weight - 1;
10486  rscale2 = var2->ndigits - var2->weight - 1;
10487  res_rscale = Max(rscale1, rscale2);
10488 
10489  res_ndigits = res_rscale + res_weight + 1;
10490  if (res_ndigits <= 0)
10491  res_ndigits = 1;
10492 
10493  res_buf = digitbuf_alloc(res_ndigits + 1);
10494  res_buf[0] = 0; /* spare digit for later rounding */
10495  res_digits = res_buf + 1;
10496 
10497  i1 = res_rscale + var1->weight + 1;
10498  i2 = res_rscale + var2->weight + 1;
10499  for (i = res_ndigits - 1; i >= 0; i--)
10500  {
10501  i1--;
10502  i2--;
10503  if (i1 >= 0 && i1 < var1ndigits)
10504  carry += var1digits[i1];
10505  if (i2 >= 0 && i2 < var2ndigits)
10506  carry += var2digits[i2];
10507 
10508  if (carry >= NBASE)
10509  {
10510  res_digits[i] = carry - NBASE;
10511  carry = 1;
10512  }
10513  else
10514  {
10515  res_digits[i] = carry;
10516  carry = 0;
10517  }
10518  }
10519 
10520  Assert(carry == 0); /* else we failed to allow for carry out */
10521 
10522  digitbuf_free(result->buf);
10523  result->ndigits = res_ndigits;
10524  result->buf = res_buf;
10525  result->digits = res_digits;
10526  result->weight = res_weight;
10527  result->dscale = res_dscale;
10528 
10529  /* Remove leading/trailing zeroes */
10530  strip_var(result);
10531 }
int weight
Definition: numeric.c:307
static void strip_var(NumericVar *var)
Definition: numeric.c:10794
#define digitbuf_alloc(ndigits)
Definition: numeric.c:487
int ndigits
Definition: numeric.c:306
int dscale
Definition: numeric.c:309
#define digitbuf_free(buf)
Definition: numeric.c:489
int16 NumericDigit
Definition: numeric.c:103
NumericDigit * buf
Definition: numeric.c:310
#define NBASE
Definition: numeric.c:97
#define Assert(condition)
Definition: c.h:745
NumericDigit * digits
Definition: numeric.c:311
int i
#define Max(x, y)
Definition: numeric.c:13

◆ add_var()

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

Definition at line 7890 of file numeric.c.

References add_abs(), cmp_abs(), NumericVar::dscale, Max, NUMERIC_NEG, NUMERIC_POS, NumericVar::sign, sub_abs(), and zero_var().

Referenced by accum_sum_final(), ceil_var(), compute_bucket(), div_mod_var(), exp_var(), generate_series_step_numeric(), in_range_numeric_numeric(), ln_var(), numeric_add_opt_error(), numeric_inc(), sqrt_var(), and width_bucket_numeric().

7891 {
7892  /*
7893  * Decide on the signs of the two variables what to do
7894  */
7895  if (var1->sign == NUMERIC_POS)
7896  {
7897  if (var2->sign == NUMERIC_POS)
7898  {
7899  /*
7900  * Both are positive result = +(ABS(var1) + ABS(var2))
7901  */
7902  add_abs(var1, var2, result);
7903  result->sign = NUMERIC_POS;
7904  }
7905  else
7906  {
7907  /*
7908  * var1 is positive, var2 is negative Must compare absolute values
7909  */
7910  switch (cmp_abs(var1, var2))
7911  {
7912  case 0:
7913  /* ----------
7914  * ABS(var1) == ABS(var2)
7915  * result = ZERO
7916  * ----------
7917  */
7918  zero_var(result);
7919  result->dscale = Max(var1->dscale, var2->dscale);
7920  break;
7921 
7922  case 1:
7923  /* ----------
7924  * ABS(var1) > ABS(var2)
7925  * result = +(ABS(var1) - ABS(var2))
7926  * ----------
7927  */
7928  sub_abs(var1, var2, result);
7929  result->sign = NUMERIC_POS;
7930  break;
7931 
7932  case -1:
7933  /* ----------
7934  * ABS(var1) < ABS(var2)
7935  * result = -(ABS(var2) - ABS(var1))
7936  * ----------
7937  */
7938  sub_abs(var2, var1, result);
7939  result->sign = NUMERIC_NEG;
7940  break;
7941  }
7942  }
7943  }
7944  else
7945  {
7946  if (var2->sign == NUMERIC_POS)
7947  {
7948  /* ----------
7949  * var1 is negative, var2 is positive
7950  * Must compare absolute values
7951  * ----------
7952  */
7953  switch (cmp_abs(var1, var2))
7954  {
7955  case 0:
7956  /* ----------
7957  * ABS(var1) == ABS(var2)
7958  * result = ZERO
7959  * ----------
7960  */
7961  zero_var(result);
7962  result->dscale = Max(var1->dscale, var2->dscale);
7963  break;
7964 
7965  case 1:
7966  /* ----------
7967  * ABS(var1) > ABS(var2)
7968  * result = -(ABS(var1) - ABS(var2))
7969  * ----------
7970  */
7971  sub_abs(var1, var2, result);
7972  result->sign = NUMERIC_NEG;
7973  break;
7974 
7975  case -1:
7976  /* ----------
7977  * ABS(var1) < ABS(var2)
7978  * result = +(ABS(var2) - ABS(var1))
7979  * ----------
7980  */
7981  sub_abs(var2, var1, result);
7982  result->sign = NUMERIC_POS;
7983  break;
7984  }
7985  }
7986  else
7987  {
7988  /* ----------
7989  * Both are negative
7990  * result = -(ABS(var1) + ABS(var2))
7991  * ----------
7992  */
7993  add_abs(var1, var2, result);
7994  result->sign = NUMERIC_NEG;
7995  }
7996  }
7997 }
static void sub_abs(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition: numeric.c:10544
static void add_abs(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition: numeric.c:10459
#define NUMERIC_POS
Definition: numeric.c:167
int dscale
Definition: numeric.c:309
#define NUMERIC_NEG
Definition: numeric.c:168
int sign
Definition: numeric.c:308
static void zero_var(NumericVar *var)
Definition: numeric.c:6734
static int cmp_abs(const NumericVar *var1, const NumericVar *var2)
Definition: numeric.c:10381
#define Max(x, y)
Definition: numeric.c:13

◆ alloc_var()

static void alloc_var ( NumericVar var,
int  ndigits 
)
static

Definition at line 6702 of file numeric.c.

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

Referenced by div_var(), div_var_fast(), int64_to_numericvar(), mul_var(), numeric_recv(), numericvar_to_uint64(), set_var_from_num(), set_var_from_str(), and sqrt_var().

6703 {
6704  digitbuf_free(var->buf);
6705  var->buf = digitbuf_alloc(ndigits + 1);
6706  var->buf[0] = 0; /* spare digit for rounding */
6707  var->digits = var->buf + 1;
6708  var->ndigits = ndigits;
6709 }
#define digitbuf_alloc(ndigits)
Definition: numeric.c:487
int ndigits
Definition: numeric.c:306
#define digitbuf_free(buf)
Definition: numeric.c:489
NumericDigit * buf
Definition: numeric.c:310
NumericDigit * digits
Definition: numeric.c:311

◆ apply_typmod()

static void apply_typmod ( NumericVar var,
int32  typmod 
)
static

Definition at line 7373 of file numeric.c.

References DEC_DIGITS, NumericVar::digits, ereport, errcode(), errdetail(), errmsg(), ERROR, i, maxdigits, NumericVar::ndigits, round_var(), scale, VARHDRSZ, and NumericVar::weight.

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

7374 {
7375  int precision;
7376  int scale;
7377  int maxdigits;
7378  int ddigits;
7379  int i;
7380 
7381  /* Do nothing if we have a default typmod (-1) */
7382  if (typmod < (int32) (VARHDRSZ))
7383  return;
7384 
7385  typmod -= VARHDRSZ;
7386  precision = (typmod >> 16) & 0xffff;
7387  scale = typmod & 0xffff;
7388  maxdigits = precision - scale;
7389 
7390  /* Round to target scale (and set var->dscale) */
7391  round_var(var, scale);
7392 
7393  /*
7394  * Check for overflow - note we can't do this before rounding, because
7395  * rounding could raise the weight. Also note that the var's weight could
7396  * be inflated by leading zeroes, which will be stripped before storage
7397  * but perhaps might not have been yet. In any case, we must recognize a
7398  * true zero, whose weight doesn't mean anything.
7399  */
7400  ddigits = (var->weight + 1) * DEC_DIGITS;
7401  if (ddigits > maxdigits)
7402  {
7403  /* Determine true weight; and check for all-zero result */
7404  for (i = 0; i < var->ndigits; i++)
7405  {
7406  NumericDigit dig = var->digits[i];
7407 
7408  if (dig)
7409  {
7410  /* Adjust for any high-order decimal zero digits */
7411 #if DEC_DIGITS == 4
7412  if (dig < 10)
7413  ddigits -= 3;
7414  else if (dig < 100)
7415  ddigits -= 2;
7416  else if (dig < 1000)
7417  ddigits -= 1;
7418 #elif DEC_DIGITS == 2
7419  if (dig < 10)
7420  ddigits -= 1;
7421 #elif DEC_DIGITS == 1
7422  /* no adjustment */
7423 #else
7424 #error unsupported NBASE
7425 #endif
7426  if (ddigits > maxdigits)
7427  ereport(ERROR,
7428  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
7429  errmsg("numeric field overflow"),
7430  errdetail("A field with precision %d, scale %d must round to an absolute value less than %s%d.",
7431  precision, scale,
7432  /* Display 10^0 as 1 */
7433  maxdigits ? "10^" : "",
7434  maxdigits ? maxdigits : 1
7435  )));
7436  break;
7437  }
7438  ddigits -= DEC_DIGITS;
7439  }
7440  }
7441 }
static void round_var(NumericVar *var, int rscale)
Definition: numeric.c:10626
int weight
Definition: numeric.c:307
#define VARHDRSZ
Definition: c.h:568
int errcode(int sqlerrcode)
Definition: elog.c:610
int scale
Definition: pgbench.c:154
int ndigits
Definition: numeric.c:306
signed int int32
Definition: c.h:362
#define ERROR
Definition: elog.h:43
int16 NumericDigit
Definition: numeric.c:103
int errdetail(const char *fmt,...)
Definition: elog.c:957
#define ereport(elevel,...)
Definition: elog.h:144
int maxdigits
Definition: informix.c:665
NumericDigit * digits
Definition: numeric.c:311
int errmsg(const char *fmt,...)
Definition: elog.c:824
int i
#define DEC_DIGITS
Definition: numeric.c:99

◆ apply_typmod_special()

static void apply_typmod_special ( Numeric  num,
int32  typmod 
)
static

Definition at line 7450 of file numeric.c.

References Assert, ereport, errcode(), errdetail(), errmsg(), ERROR, NUMERIC_IS_NAN, NUMERIC_IS_SPECIAL, scale, and VARHDRSZ.

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

7451 {
7452  int precision;
7453  int scale;
7454 
7455  Assert(NUMERIC_IS_SPECIAL(num)); /* caller error if not */
7456 
7457  /*
7458  * NaN is allowed regardless of the typmod; that's rather dubious perhaps,
7459  * but it's a longstanding behavior. Inf is rejected if we have any
7460  * typmod restriction, since an infinity shouldn't be claimed to fit in
7461  * any finite number of digits.
7462  */
7463  if (NUMERIC_IS_NAN(num))
7464  return;
7465 
7466  /* Do nothing if we have a default typmod (-1) */
7467  if (typmod < (int32) (VARHDRSZ))
7468  return;
7469 
7470  typmod -= VARHDRSZ;
7471  precision = (typmod >> 16) & 0xffff;
7472  scale = typmod & 0xffff;
7473 
7474  ereport(ERROR,
7475  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
7476  errmsg("numeric field overflow"),
7477  errdetail("A field with precision %d, scale %d cannot hold an infinite value.",
7478  precision, scale)));
7479 }
#define VARHDRSZ
Definition: c.h:568
int errcode(int sqlerrcode)
Definition: elog.c:610
int scale
Definition: pgbench.c:154
signed int int32
Definition: c.h:362
#define NUMERIC_IS_SPECIAL(n)
Definition: numeric.c:174
#define ERROR
Definition: elog.h:43
int errdetail(const char *fmt,...)
Definition: elog.c:957
#define ereport(elevel,...)
Definition: elog.h:144
#define Assert(condition)
Definition: c.h:745
int errmsg(const char *fmt,...)
Definition: elog.c:824
#define NUMERIC_IS_NAN(n)
Definition: numeric.c:205

◆ ceil_var()

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

Definition at line 9095 of file numeric.c.

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

Referenced by numeric_ceil().

9096 {
9097  NumericVar tmp;
9098 
9099  init_var(&tmp);
9100  set_var_from_var(var, &tmp);
9101 
9102  trunc_var(&tmp, 0);
9103 
9104  if (var->sign == NUMERIC_POS && cmp_var(var, &tmp) != 0)
9105  add_var(&tmp, &const_one, &tmp);
9106 
9107  set_var_from_var(&tmp, result);
9108  free_var(&tmp);
9109 }
static void trunc_var(NumericVar *var, int rscale)
Definition: numeric.c:10732
static const NumericVar const_one
Definition: numeric.c:420
#define NUMERIC_POS
Definition: numeric.c:167
int sign
Definition: numeric.c:308
static int cmp_var(const NumericVar *var1, const NumericVar *var2)
Definition: numeric.c:7832
static void free_var(NumericVar *var)
Definition: numeric.c:6718
static void add_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition: numeric.c:7890
static void set_var_from_var(const NumericVar *value, NumericVar *dest)
Definition: numeric.c:6968
#define init_var(v)
Definition: numeric.c:495

◆ cmp_abs()

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

Definition at line 10381 of file numeric.c.

References cmp_abs_common(), NumericVar::digits, NumericVar::ndigits, and NumericVar::weight.

Referenced by add_var(), div_mod_var(), gcd_var(), and sub_var().

10382 {
10383  return cmp_abs_common(var1->digits, var1->ndigits, var1->weight,
10384  var2->digits, var2->ndigits, var2->weight);
10385 }
int weight
Definition: numeric.c:307
int ndigits
Definition: numeric.c:306
NumericDigit * digits
Definition: numeric.c:311
static int cmp_abs_common(const NumericDigit *var1digits, int var1ndigits, int var1weight, const NumericDigit *var2digits, int var2ndigits, int var2weight)
Definition: numeric.c:10395

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

References stat.

Referenced by cmp_abs(), and cmp_var_common().

10397 {
10398  int i1 = 0;
10399  int i2 = 0;
10400 
10401  /* Check any digits before the first common digit */
10402 
10403  while (var1weight > var2weight && i1 < var1ndigits)
10404  {
10405  if (var1digits[i1++] != 0)
10406  return 1;
10407  var1weight--;
10408  }
10409  while (var2weight > var1weight && i2 < var2ndigits)
10410  {
10411  if (var2digits[i2++] != 0)
10412  return -1;
10413  var2weight--;
10414  }
10415 
10416  /* At this point, either w1 == w2 or we've run out of digits */
10417 
10418  if (var1weight == var2weight)
10419  {
10420  while (i1 < var1ndigits && i2 < var2ndigits)
10421  {
10422  int stat = var1digits[i1++] - var2digits[i2++];
10423 
10424  if (stat)
10425  {
10426  if (stat > 0)
10427  return 1;
10428  return -1;
10429  }
10430  }
10431  }
10432 
10433  /*
10434  * At this point, we've run out of digits on one side or the other; so any
10435  * remaining nonzero digits imply that side is larger
10436  */
10437  while (i1 < var1ndigits)
10438  {
10439  if (var1digits[i1++] != 0)
10440  return 1;
10441  }
10442  while (i2 < var2ndigits)
10443  {
10444  if (var2digits[i2++] != 0)
10445  return -1;
10446  }
10447 
10448  return 0;
10449 }
#define stat(a, b)
Definition: win32_port.h:255

◆ cmp_numerics()

static int cmp_numerics ( Numeric  num1,
Numeric  num2 
)
static

Definition at line 2366 of file numeric.c.

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

Referenced by numeric_cmp(), numeric_eq(), numeric_fast_cmp(), numeric_ge(), numeric_gt(), numeric_larger(), numeric_le(), numeric_lt(), numeric_ne(), numeric_smaller(), and width_bucket_numeric().

2367 {
2368  int result;
2369 
2370  /*
2371  * We consider all NANs to be equal and larger than any non-NAN (including
2372  * Infinity). This is somewhat arbitrary; the important thing is to have
2373  * a consistent sort order.
2374  */
2375  if (NUMERIC_IS_SPECIAL(num1))
2376  {
2377  if (NUMERIC_IS_NAN(num1))
2378  {
2379  if (NUMERIC_IS_NAN(num2))
2380  result = 0; /* NAN = NAN */
2381  else
2382  result = 1; /* NAN > non-NAN */
2383  }
2384  else if (NUMERIC_IS_PINF(num1))
2385  {
2386  if (NUMERIC_IS_NAN(num2))
2387  result = -1; /* PINF < NAN */
2388  else if (NUMERIC_IS_PINF(num2))
2389  result = 0; /* PINF = PINF */
2390  else
2391  result = 1; /* PINF > anything else */
2392  }
2393  else /* num1 must be NINF */
2394  {
2395  if (NUMERIC_IS_NINF(num2))
2396  result = 0; /* NINF = NINF */
2397  else
2398  result = -1; /* NINF < anything else */
2399  }
2400  }
2401  else if (NUMERIC_IS_SPECIAL(num2))
2402  {
2403  if (NUMERIC_IS_NINF(num2))
2404  result = 1; /* normal > NINF */
2405  else
2406  result = -1; /* normal < NAN or PINF */
2407  }
2408  else
2409  {
2410  result = cmp_var_common(NUMERIC_DIGITS(num1), NUMERIC_NDIGITS(num1),
2411  NUMERIC_WEIGHT(num1), NUMERIC_SIGN(num1),
2412  NUMERIC_DIGITS(num2), NUMERIC_NDIGITS(num2),
2413  NUMERIC_WEIGHT(num2), NUMERIC_SIGN(num2));
2414  }
2415 
2416  return result;
2417 }
#define NUMERIC_IS_SPECIAL(n)
Definition: numeric.c:174
#define NUMERIC_DIGITS(num)
Definition: numeric.c:497
#define NUMERIC_IS_PINF(n)
Definition: numeric.c:206
#define NUMERIC_SIGN(n)
Definition: numeric.c:237
#define NUMERIC_NDIGITS(num)
Definition: numeric.c:499
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:7847
#define NUMERIC_WEIGHT(n)
Definition: numeric.c:247
#define NUMERIC_IS_NINF(n)
Definition: numeric.c:207
#define NUMERIC_IS_NAN(n)
Definition: numeric.c:205

◆ cmp_var()

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

Definition at line 7832 of file numeric.c.

References cmp_var_common(), NumericVar::digits, NumericVar::ndigits, NumericVar::sign, and NumericVar::weight.

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

7833 {
7834  return cmp_var_common(var1->digits, var1->ndigits,
7835  var1->weight, var1->sign,
7836  var2->digits, var2->ndigits,
7837  var2->weight, var2->sign);
7838 }
int weight
Definition: numeric.c:307
int ndigits
Definition: numeric.c:306
int sign
Definition: numeric.c:308
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:7847
NumericDigit * digits
Definition: numeric.c:311

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

References cmp_abs_common(), NUMERIC_NEG, and NUMERIC_POS.

Referenced by cmp_numerics(), and cmp_var().

7851 {
7852  if (var1ndigits == 0)
7853  {
7854  if (var2ndigits == 0)
7855  return 0;
7856  if (var2sign == NUMERIC_NEG)
7857  return 1;
7858  return -1;
7859  }
7860  if (var2ndigits == 0)
7861  {
7862  if (var1sign == NUMERIC_POS)
7863  return 1;
7864  return -1;
7865  }
7866 
7867  if (var1sign == NUMERIC_POS)
7868  {
7869  if (var2sign == NUMERIC_NEG)
7870  return 1;
7871  return cmp_abs_common(var1digits, var1ndigits, var1weight,
7872  var2digits, var2ndigits, var2weight);
7873  }
7874 
7875  if (var2sign == NUMERIC_POS)
7876  return -1;
7877 
7878  return cmp_abs_common(var2digits, var2ndigits, var2weight,
7879  var1digits, var1ndigits, var1weight);
7880 }
#define NUMERIC_POS
Definition: numeric.c:167
#define NUMERIC_NEG
Definition: numeric.c:168
static int cmp_abs_common(const NumericDigit *var1digits, int var1ndigits, int var1weight, const NumericDigit *var2digits, int var2ndigits, int var2weight)
Definition: numeric.c:10395

◆ compute_bucket()

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

Definition at line 1788 of file numeric.c.

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

Referenced by width_bucket_numeric().

1790 {
1791  NumericVar bound1_var;
1792  NumericVar bound2_var;
1793  NumericVar operand_var;
1794 
1795  init_var_from_num(bound1, &bound1_var);
1796  init_var_from_num(bound2, &bound2_var);
1797  init_var_from_num(operand, &operand_var);
1798 
1799  if (cmp_var(&bound1_var, &bound2_var) < 0)
1800  {
1801  sub_var(&operand_var, &bound1_var, &operand_var);
1802  sub_var(&bound2_var, &bound1_var, &bound2_var);
1803  div_var(&operand_var, &bound2_var, result_var,
1804  select_div_scale(&operand_var, &bound2_var), true);
1805  }
1806  else
1807  {
1808  sub_var(&bound1_var, &operand_var, &operand_var);
1809  sub_var(&bound1_var, &bound2_var, &bound1_var);
1810  div_var(&operand_var, &bound1_var, result_var,
1811  select_div_scale(&operand_var, &bound1_var), true);
1812  }
1813 
1814  mul_var(result_var, count_var, result_var,
1815  result_var->dscale + count_var->dscale);
1816  add_var(result_var, &const_one, result_var);
1817  floor_var(result_var, result_var);
1818 
1819  free_var(&bound1_var);
1820  free_var(&bound2_var);
1821  free_var(&operand_var);
1822 }
static const NumericVar const_one
Definition: numeric.c:420
static void div_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result, int rscale, bool round)
Definition: numeric.c:8336
int dscale
Definition: numeric.c:309
static int select_div_scale(const NumericVar *var1, const NumericVar *var2)
Definition: numeric.c:8927
static void init_var_from_num(Numeric num, NumericVar *dest)
Definition: numeric.c:6951
static int cmp_var(const NumericVar *var1, const NumericVar *var2)
Definition: numeric.c:7832
static void free_var(NumericVar *var)
Definition: numeric.c:6718
static void mul_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result, int rscale)
Definition: numeric.c:8128
static void add_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition: numeric.c:7890
static void sub_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition: numeric.c:8007
static void floor_var(const NumericVar *var, NumericVar *result)
Definition: numeric.c:9119

◆ div_mod_var()

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

Definition at line 9025 of file numeric.c.

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

Referenced by sqrt_var().

9027 {
9028  NumericVar q;
9029  NumericVar r;
9030 
9031  init_var(&q);
9032  init_var(&r);
9033 
9034  /*
9035  * Use div_var_fast() to get an initial estimate for the integer quotient.
9036  * This might be inaccurate (per the warning in div_var_fast's comments),
9037  * but we can correct it below.
9038  */
9039  div_var_fast(var1, var2, &q, 0, false);
9040 
9041  /* Compute initial estimate of remainder using the quotient estimate. */
9042  mul_var(var2, &q, &r, var2->dscale);
9043  sub_var(var1, &r, &r);
9044 
9045  /*
9046  * Adjust the results if necessary --- the remainder should have the same
9047  * sign as var1, and its absolute value should be less than the absolute
9048  * value of var2.
9049  */
9050  while (r.ndigits != 0 && r.sign != var1->sign)
9051  {
9052  /* The absolute value of the quotient is too large */
9053  if (var1->sign == var2->sign)
9054  {
9055  sub_var(&q, &const_one, &q);
9056  add_var(&r, var2, &r);
9057  }
9058  else
9059  {
9060  add_var(&q, &const_one, &q);
9061  sub_var(&r, var2, &r);
9062  }
9063  }
9064 
9065  while (cmp_abs(&r, var2) >= 0)
9066  {
9067  /* The absolute value of the quotient is too small */
9068  if (var1->sign == var2->sign)
9069  {
9070  add_var(&q, &const_one, &q);
9071  sub_var(&r, var2, &r);
9072  }
9073  else
9074  {
9075  sub_var(&q, &const_one, &q);
9076  add_var(&r, var2, &r);
9077  }
9078  }
9079 
9080  set_var_from_var(&q, quot);
9081  set_var_from_var(&r, rem);
9082 
9083  free_var(&q);
9084  free_var(&r);
9085 }
static const NumericVar const_one
Definition: numeric.c:420
int ndigits
Definition: numeric.c:306
int dscale
Definition: numeric.c:309
int sign
Definition: numeric.c:308
static void div_var_fast(const NumericVar *var1, const NumericVar *var2, NumericVar *result, int rscale, bool round)
Definition: numeric.c:8621
static void free_var(NumericVar *var)
Definition: numeric.c:6718
static void mul_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result, int rscale)
Definition: numeric.c:8128
static void add_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition: numeric.c:7890
static int cmp_abs(const NumericVar *var1, const NumericVar *var2)
Definition: numeric.c:10381
static void sub_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition: numeric.c:8007
static void set_var_from_var(const NumericVar *value, NumericVar *dest)
Definition: numeric.c:6968
#define init_var(v)
Definition: numeric.c:495

◆ div_var()

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

Definition at line 8336 of file numeric.c.

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

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

8338 {
8339  int div_ndigits;
8340  int res_ndigits;
8341  int res_sign;
8342  int res_weight;
8343  int carry;
8344  int borrow;
8345  int divisor1;
8346  int divisor2;
8347  NumericDigit *dividend;
8348  NumericDigit *divisor;
8349  NumericDigit *res_digits;
8350  int i;
8351  int j;
8352 
8353  /* copy these values into local vars for speed in inner loop */
8354  int var1ndigits = var1->ndigits;
8355  int var2ndigits = var2->ndigits;
8356 
8357  /*
8358  * First of all division by zero check; we must not be handed an
8359  * unnormalized divisor.
8360  */
8361  if (var2ndigits == 0 || var2->digits[0] == 0)
8362  ereport(ERROR,
8363  (errcode(ERRCODE_DIVISION_BY_ZERO),
8364  errmsg("division by zero")));
8365 
8366  /*
8367  * Now result zero check
8368  */
8369  if (var1ndigits == 0)
8370  {
8371  zero_var(result);
8372  result->dscale = rscale;
8373  return;
8374  }
8375 
8376  /*
8377  * Determine the result sign, weight and number of digits to calculate.
8378  * The weight figured here is correct if the emitted quotient has no
8379  * leading zero digits; otherwise strip_var() will fix things up.
8380  */
8381  if (var1->sign == var2->sign)
8382  res_sign = NUMERIC_POS;
8383  else
8384  res_sign = NUMERIC_NEG;
8385  res_weight = var1->weight - var2->weight;
8386  /* The number of accurate result digits we need to produce: */
8387  res_ndigits = res_weight + 1 + (rscale + DEC_DIGITS - 1) / DEC_DIGITS;
8388  /* ... but always at least 1 */
8389  res_ndigits = Max(res_ndigits, 1);
8390  /* If rounding needed, figure one more digit to ensure correct result */
8391  if (round)
8392  res_ndigits++;
8393 
8394  /*
8395  * The working dividend normally requires res_ndigits + var2ndigits
8396  * digits, but make it at least var1ndigits so we can load all of var1
8397  * into it. (There will be an additional digit dividend[0] in the
8398  * dividend space, but for consistency with Knuth's notation we don't
8399  * count that in div_ndigits.)
8400  */
8401  div_ndigits = res_ndigits + var2ndigits;
8402  div_ndigits = Max(div_ndigits, var1ndigits);
8403 
8404  /*
8405  * We need a workspace with room for the working dividend (div_ndigits+1
8406  * digits) plus room for the possibly-normalized divisor (var2ndigits
8407  * digits). It is convenient also to have a zero at divisor[0] with the
8408  * actual divisor data in divisor[1 .. var2ndigits]. Transferring the
8409  * digits into the workspace also allows us to realloc the result (which
8410  * might be the same as either input var) before we begin the main loop.
8411  * Note that we use palloc0 to ensure that divisor[0], dividend[0], and
8412  * any additional dividend positions beyond var1ndigits, start out 0.
8413  */
8414  dividend = (NumericDigit *)
8415  palloc0((div_ndigits + var2ndigits + 2) * sizeof(NumericDigit));
8416  divisor = dividend + (div_ndigits + 1);
8417  memcpy(dividend + 1, var1->digits, var1ndigits * sizeof(NumericDigit));
8418  memcpy(divisor + 1, var2->digits, var2ndigits * sizeof(NumericDigit));
8419 
8420  /*
8421  * Now we can realloc the result to hold the generated quotient digits.
8422  */
8423  alloc_var(result, res_ndigits);
8424  res_digits = result->digits;
8425 
8426  if (var2ndigits == 1)
8427  {
8428  /*
8429  * If there's only a single divisor digit, we can use a fast path (cf.
8430  * Knuth section 4.3.1 exercise 16).
8431  */
8432  divisor1 = divisor[1];
8433  carry = 0;
8434  for (i = 0; i < res_ndigits; i++)
8435  {
8436  carry = carry * NBASE + dividend[i + 1];
8437  res_digits[i] = carry / divisor1;
8438  carry = carry % divisor1;
8439  }
8440  }
8441  else
8442  {
8443  /*
8444  * The full multiple-place algorithm is taken from Knuth volume 2,
8445  * Algorithm 4.3.1D.
8446  *
8447  * We need the first divisor digit to be >= NBASE/2. If it isn't,
8448  * make it so by scaling up both the divisor and dividend by the
8449  * factor "d". (The reason for allocating dividend[0] above is to
8450  * leave room for possible carry here.)
8451  */
8452  if (divisor[1] < HALF_NBASE)
8453  {
8454  int d = NBASE / (divisor[1] + 1);
8455 
8456  carry = 0;
8457  for (i = var2ndigits; i > 0; i--)
8458  {
8459  carry += divisor[i] * d;
8460  divisor[i] = carry % NBASE;
8461  carry = carry / NBASE;
8462  }
8463  Assert(carry == 0);
8464  carry = 0;
8465  /* at this point only var1ndigits of dividend can be nonzero */
8466  for (i = var1ndigits; i >= 0; i--)
8467  {
8468  carry += dividend[i] * d;
8469  dividend[i] = carry % NBASE;
8470  carry = carry / NBASE;
8471  }
8472  Assert(carry == 0);
8473  Assert(divisor[1] >= HALF_NBASE);
8474  }
8475  /* First 2 divisor digits are used repeatedly in main loop */
8476  divisor1 = divisor[1];
8477  divisor2 = divisor[2];
8478 
8479  /*
8480  * Begin the main loop. Each iteration of this loop produces the j'th
8481  * quotient digit by dividing dividend[j .. j + var2ndigits] by the
8482  * divisor; this is essentially the same as the common manual
8483  * procedure for long division.
8484  */
8485  for (j = 0; j < res_ndigits; j++)
8486  {
8487  /* Estimate quotient digit from the first two dividend digits */
8488  int next2digits = dividend[j] * NBASE + dividend[j + 1];
8489  int qhat;
8490 
8491  /*
8492  * If next2digits are 0, then quotient digit must be 0 and there's
8493  * no need to adjust the working dividend. It's worth testing
8494  * here to fall out ASAP when processing trailing zeroes in a
8495  * dividend.
8496  */
8497  if (next2digits == 0)
8498  {
8499  res_digits[j] = 0;
8500  continue;
8501  }
8502 
8503  if (dividend[j] == divisor1)
8504  qhat = NBASE - 1;
8505  else
8506  qhat = next2digits / divisor1;
8507 
8508  /*
8509  * Adjust quotient digit if it's too large. Knuth proves that
8510  * after this step, the quotient digit will be either correct or
8511  * just one too large. (Note: it's OK to use dividend[j+2] here
8512  * because we know the divisor length is at least 2.)
8513  */
8514  while (divisor2 * qhat >
8515  (next2digits - qhat * divisor1) * NBASE + dividend[j + 2])
8516  qhat--;
8517 
8518  /* As above, need do nothing more when quotient digit is 0 */
8519  if (qhat > 0)
8520  {
8521  /*
8522  * Multiply the divisor by qhat, and subtract that from the
8523  * working dividend. "carry" tracks the multiplication,
8524  * "borrow" the subtraction (could we fold these together?)
8525  */
8526  carry = 0;
8527  borrow = 0;
8528  for (i = var2ndigits; i >= 0; i--)
8529  {
8530  carry += divisor[i] * qhat;
8531  borrow -= carry % NBASE;
8532  carry = carry / NBASE;
8533  borrow += dividend[j + i];
8534  if (borrow < 0)
8535  {
8536  dividend[j + i] = borrow + NBASE;
8537  borrow = -1;
8538  }
8539  else
8540  {
8541  dividend[j + i] = borrow;
8542  borrow = 0;
8543  }
8544  }
8545  Assert(carry == 0);
8546 
8547  /*
8548  * If we got a borrow out of the top dividend digit, then
8549  * indeed qhat was one too large. Fix it, and add back the
8550  * divisor to correct the working dividend. (Knuth proves
8551  * that this will occur only about 3/NBASE of the time; hence,
8552  * it's a good idea to test this code with small NBASE to be
8553  * sure this section gets exercised.)
8554  */
8555  if (borrow)
8556  {
8557  qhat--;
8558  carry = 0;
8559  for (i = var2ndigits; i >= 0; i--)
8560  {
8561  carry += dividend[j + i] + divisor[i];
8562  if (carry >= NBASE)
8563  {
8564  dividend[j + i] = carry - NBASE;
8565  carry = 1;
8566  }
8567  else
8568  {
8569  dividend[j + i] = carry;
8570  carry = 0;
8571  }
8572  }
8573  /* A carry should occur here to cancel the borrow above */
8574  Assert(carry == 1);
8575  }
8576  }
8577 
8578  /* And we're done with this quotient digit */
8579  res_digits[j] = qhat;
8580  }
8581  }
8582 
8583  pfree(dividend);
8584 
8585  /*
8586  * Finally, round or truncate the result to the requested precision.
8587  */
8588  result->weight = res_weight;
8589  result->sign = res_sign;
8590 
8591  /* Round or truncate to target rscale (and set result->dscale) */
8592  if (round)
8593  round_var(result, rscale);
8594  else
8595  trunc_var(result, rscale);
8596 
8597  /* Strip leading and trailing zeroes */
8598  strip_var(result);
8599 }
static void round_var(NumericVar *var, int rscale)
Definition: numeric.c:10626
static void trunc_var(NumericVar *var, int rscale)
Definition: numeric.c:10732
int weight
Definition: numeric.c:307
#define NUMERIC_POS
Definition: numeric.c:167
static void strip_var(NumericVar *var)
Definition: numeric.c:10794
int errcode(int sqlerrcode)
Definition: elog.c:610
int ndigits
Definition: numeric.c:306
int dscale
Definition: numeric.c:309
#define NUMERIC_NEG
Definition: numeric.c:168
int sign
Definition: numeric.c:308
static void zero_var(NumericVar *var)
Definition: numeric.c:6734
void pfree(void *pointer)
Definition: mcxt.c:1057
#define ERROR
Definition: elog.h:43
int16 NumericDigit
Definition: numeric.c:103
#define HALF_NBASE
Definition: numeric.c:98
#define NBASE
Definition: numeric.c:97
void * palloc0(Size size)
Definition: mcxt.c:981
#define ereport(elevel,...)
Definition: elog.h:144
#define Assert(condition)
Definition: c.h:745
NumericDigit * digits
Definition: numeric.c:311
int errmsg(const char *fmt,...)
Definition: elog.c:824
static void alloc_var(NumericVar *var, int ndigits)
Definition: numeric.c:6702
int i
#define Max(x, y)
Definition: numeric.c:13
#define DEC_DIGITS
Definition: numeric.c:99

◆ div_var_fast()

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

Definition at line 8621 of file numeric.c.

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

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

8623 {
8624  int div_ndigits;
8625  int load_ndigits;
8626  int res_sign;
8627  int res_weight;
8628  int *div;
8629  int qdigit;
8630  int carry;
8631  int maxdiv;
8632  int newdig;
8633  NumericDigit *res_digits;
8634  double fdividend,
8635  fdivisor,
8636  fdivisorinverse,
8637  fquotient;
8638  int qi;
8639  int i;
8640 
8641  /* copy these values into local vars for speed in inner loop */
8642  int var1ndigits = var1->ndigits;
8643  int var2ndigits = var2->ndigits;
8644  NumericDigit *var1digits = var1->digits;
8645  NumericDigit *var2digits = var2->digits;
8646 
8647  /*
8648  * First of all division by zero check; we must not be handed an
8649  * unnormalized divisor.
8650  */
8651  if (var2ndigits == 0 || var2digits[0] == 0)
8652  ereport(ERROR,
8653  (errcode(ERRCODE_DIVISION_BY_ZERO),
8654  errmsg("division by zero")));
8655 
8656  /*
8657  * Now result zero check
8658  */
8659  if (var1ndigits == 0)
8660  {
8661  zero_var(result);
8662  result->dscale = rscale;
8663  return;
8664  }
8665 
8666  /*
8667  * Determine the result sign, weight and number of digits to calculate
8668  */
8669  if (var1->sign == var2->sign)
8670  res_sign = NUMERIC_POS;
8671  else
8672  res_sign = NUMERIC_NEG;
8673  res_weight = var1->weight - var2->weight + 1;
8674  /* The number of accurate result digits we need to produce: */
8675  div_ndigits = res_weight + 1 + (rscale + DEC_DIGITS - 1) / DEC_DIGITS;
8676  /* Add guard digits for roundoff error */
8677  div_ndigits += DIV_GUARD_DIGITS;
8678  if (div_ndigits < DIV_GUARD_DIGITS)
8679  div_ndigits = DIV_GUARD_DIGITS;
8680 
8681  /*
8682  * We do the arithmetic in an array "div[]" of signed int's. Since
8683  * INT_MAX is noticeably larger than NBASE*NBASE, this gives us headroom
8684  * to avoid normalizing carries immediately.
8685  *
8686  * We start with div[] containing one zero digit followed by the
8687  * dividend's digits (plus appended zeroes to reach the desired precision
8688  * including guard digits). Each step of the main loop computes an
8689  * (approximate) quotient digit and stores it into div[], removing one
8690  * position of dividend space. A final pass of carry propagation takes
8691  * care of any mistaken quotient digits.
8692  *
8693  * Note that div[] doesn't necessarily contain all of the digits from the
8694  * dividend --- the desired precision plus guard digits might be less than
8695  * the dividend's precision. This happens, for example, in the square
8696  * root algorithm, where we typically divide a 2N-digit number by an
8697  * N-digit number, and only require a result with N digits of precision.
8698  */
8699  div = (int *) palloc0((div_ndigits + 1) * sizeof(int));
8700  load_ndigits = Min(div_ndigits, var1ndigits);
8701  for (i = 0; i < load_ndigits; i++)
8702  div[i + 1] = var1digits[i];
8703 
8704  /*
8705  * We estimate each quotient digit using floating-point arithmetic, taking
8706  * the first four digits of the (current) dividend and divisor. This must
8707  * be float to avoid overflow. The quotient digits will generally be off
8708  * by no more than one from the exact answer.
8709  */
8710  fdivisor = (double) var2digits[0];
8711  for (i = 1; i < 4; i++)
8712  {
8713  fdivisor *= NBASE;
8714  if (i < var2ndigits)
8715  fdivisor += (double) var2digits[i];
8716  }
8717  fdivisorinverse = 1.0 / fdivisor;
8718 
8719  /*
8720  * maxdiv tracks the maximum possible absolute value of any div[] entry;
8721  * when this threatens to exceed INT_MAX, we take the time to propagate
8722  * carries. Furthermore, we need to ensure that overflow doesn't occur
8723  * during the carry propagation passes either. The carry values may have
8724  * an absolute value as high as INT_MAX/NBASE + 1, so really we must
8725  * normalize when digits threaten to exceed INT_MAX - INT_MAX/NBASE - 1.
8726  *
8727  * To avoid overflow in maxdiv itself, it represents the max absolute
8728  * value divided by NBASE-1, ie, at the top of the loop it is known that
8729  * no div[] entry has an absolute value exceeding maxdiv * (NBASE-1).
8730  *
8731  * Actually, though, that holds good only for div[] entries after div[qi];
8732  * the adjustment done at the bottom of the loop may cause div[qi + 1] to
8733  * exceed the maxdiv limit, so that div[qi] in the next iteration is
8734  * beyond the limit. This does not cause problems, as explained below.
8735  */
8736  maxdiv = 1;
8737 
8738  /*
8739  * Outer loop computes next quotient digit, which will go into div[qi]
8740  */
8741  for (qi = 0; qi < div_ndigits; qi++)
8742  {
8743  /* Approximate the current dividend value */
8744  fdividend = (double) div[qi];
8745  for (i = 1; i < 4; i++)
8746  {
8747  fdividend *= NBASE;
8748  if (qi + i <= div_ndigits)
8749  fdividend += (double) div[qi + i];
8750  }
8751  /* Compute the (approximate) quotient digit */
8752  fquotient = fdividend * fdivisorinverse;
8753  qdigit = (fquotient >= 0.0) ? ((int) fquotient) :
8754  (((int) fquotient) - 1); /* truncate towards -infinity */
8755 
8756  if (qdigit != 0)
8757  {
8758  /* Do we need to normalize now? */
8759  maxdiv += Abs(qdigit);
8760  if (maxdiv > (INT_MAX - INT_MAX / NBASE - 1) / (NBASE - 1))
8761  {
8762  /*
8763  * Yes, do it. Note that if var2ndigits is much smaller than
8764  * div_ndigits, we can save a significant amount of effort
8765  * here by noting that we only need to normalise those div[]
8766  * entries touched where prior iterations subtracted multiples
8767  * of the divisor.
8768  */
8769  carry = 0;
8770  for (i = Min(qi + var2ndigits - 2, div_ndigits); i > qi; i--)
8771  {
8772  newdig = div[i] + carry;
8773  if (newdig < 0)
8774  {
8775  carry = -((-newdig - 1) / NBASE) - 1;
8776  newdig -= carry * NBASE;
8777  }
8778  else if (newdig >= NBASE)
8779  {
8780  carry = newdig / NBASE;
8781  newdig -= carry * NBASE;
8782  }
8783  else
8784  carry = 0;
8785  div[i] = newdig;
8786  }
8787  newdig = div[qi] + carry;
8788  div[qi] = newdig;
8789 
8790  /*
8791  * All the div[] digits except possibly div[qi] are now in the
8792  * range 0..NBASE-1. We do not need to consider div[qi] in
8793  * the maxdiv value anymore, so we can reset maxdiv to 1.
8794  */
8795  maxdiv = 1;
8796 
8797  /*
8798  * Recompute the quotient digit since new info may have
8799  * propagated into the top four dividend digits
8800  */
8801  fdividend = (double) div[qi];
8802  for (i = 1; i < 4; i++)
8803  {
8804  fdividend *= NBASE;
8805  if (qi + i <= div_ndigits)
8806  fdividend += (double) div[qi + i];
8807  }
8808  /* Compute the (approximate) quotient digit */
8809  fquotient = fdividend * fdivisorinverse;
8810  qdigit = (fquotient >= 0.0) ? ((int) fquotient) :
8811  (((int) fquotient) - 1); /* truncate towards -infinity */
8812  maxdiv += Abs(qdigit);
8813  }
8814 
8815  /*
8816  * Subtract off the appropriate multiple of the divisor.
8817  *
8818  * The digits beyond div[qi] cannot overflow, because we know they
8819  * will fall within the maxdiv limit. As for div[qi] itself, note
8820  * that qdigit is approximately trunc(div[qi] / vardigits[0]),
8821  * which would make the new value simply div[qi] mod vardigits[0].
8822  * The lower-order terms in qdigit can change this result by not
8823  * more than about twice INT_MAX/NBASE, so overflow is impossible.
8824  */
8825  if (qdigit != 0)
8826  {
8827  int istop = Min(var2ndigits, div_ndigits - qi + 1);
8828 
8829  for (i = 0; i < istop; i++)
8830  div[qi + i] -= qdigit * var2digits[i];
8831  }
8832  }
8833 
8834  /*
8835  * The dividend digit we are about to replace might still be nonzero.
8836  * Fold it into the next digit position.
8837  *
8838  * There is no risk of overflow here, although proving that requires
8839  * some care. Much as with the argument for div[qi] not overflowing,
8840  * if we consider the first two terms in the numerator and denominator
8841  * of qdigit, we can see that the final value of div[qi + 1] will be
8842  * approximately a remainder mod (vardigits[0]*NBASE + vardigits[1]).
8843  * Accounting for the lower-order terms is a bit complicated but ends
8844  * up adding not much more than INT_MAX/NBASE to the possible range.
8845  * Thus, div[qi + 1] cannot overflow here, and in its role as div[qi]
8846  * in the next loop iteration, it can't be large enough to cause
8847  * overflow in the carry propagation step (if any), either.
8848  *
8849  * But having said that: div[qi] can be more than INT_MAX/NBASE, as
8850  * noted above, which means that the product div[qi] * NBASE *can*
8851  * overflow. When that happens, adding it to div[qi + 1] will always
8852  * cause a canceling overflow so that the end result is correct. We
8853  * could avoid the intermediate overflow by doing the multiplication
8854  * and addition in int64 arithmetic, but so far there appears no need.
8855  */
8856  div[qi + 1] += div[qi] * NBASE;
8857 
8858  div[qi] = qdigit;
8859  }
8860 
8861  /*
8862  * Approximate and store the last quotient digit (div[div_ndigits])
8863  */
8864  fdividend = (double) div[qi];
8865  for (i = 1; i < 4; i++)
8866  fdividend *= NBASE;
8867  fquotient = fdividend * fdivisorinverse;
8868  qdigit = (fquotient >= 0.0) ? ((int) fquotient) :
8869  (((int) fquotient) - 1); /* truncate towards -infinity */
8870  div[qi] = qdigit;
8871 
8872  /*
8873  * Because the quotient digits might be off by one, some of them might be
8874  * -1 or NBASE at this point. The represented value is correct in a
8875  * mathematical sense, but it doesn't look right. We do a final carry
8876  * propagation pass to normalize the digits, which we combine with storing
8877  * the result digits into the output. Note that this is still done at
8878  * full precision w/guard digits.
8879  */
8880  alloc_var(result, div_ndigits + 1);
8881  res_digits = result->digits;
8882  carry = 0;
8883  for (i = div_ndigits; i >= 0; i--)
8884  {
8885  newdig = div[i] + carry;
8886  if (newdig < 0)
8887  {
8888  carry = -((-newdig - 1) / NBASE) - 1;
8889  newdig -= carry * NBASE;
8890  }
8891  else if (newdig >= NBASE)
8892  {
8893  carry = newdig / NBASE;
8894  newdig -= carry * NBASE;
8895  }
8896  else
8897  carry = 0;
8898  res_digits[i] = newdig;
8899  }
8900  Assert(carry == 0);
8901 
8902  pfree(div);
8903 
8904  /*
8905  * Finally, round the result to the requested precision.
8906  */
8907  result->weight = res_weight;
8908  result->sign = res_sign;
8909 
8910  /* Round to target rscale (and set result->dscale) */
8911  if (round)
8912  round_var(result, rscale);
8913  else
8914  trunc_var(result, rscale);
8915 
8916  /* Strip leading and trailing zeroes */
8917  strip_var(result);
8918 }
static void round_var(NumericVar *var, int rscale)
Definition: numeric.c:10626
static void trunc_var(NumericVar *var, int rscale)
Definition: numeric.c:10732
int weight
Definition: numeric.c:307
#define NUMERIC_POS
Definition: numeric.c:167
static void strip_var(NumericVar *var)
Definition: numeric.c:10794
int errcode(int sqlerrcode)
Definition: elog.c:610
int ndigits
Definition: numeric.c:306
int dscale
Definition: numeric.c:309
#define Min(x, y)
Definition: numeric.c:14
#define Abs(x)
Definition: c.h:933
#define NUMERIC_NEG
Definition: numeric.c:168
int sign
Definition: numeric.c:308
static void zero_var(NumericVar *var)
Definition: numeric.c:6734
void pfree(void *pointer)
Definition: mcxt.c:1057
#define ERROR
Definition: elog.h:43
int16 NumericDigit
Definition: numeric.c:103
#define NBASE
Definition: numeric.c:97
void * palloc0(Size size)
Definition: mcxt.c:981
#define ereport(elevel,...)
Definition: elog.h:144
#define Assert(condition)
Definition: c.h:745
NumericDigit * digits
Definition: numeric.c:311
#define DIV_GUARD_DIGITS
Definition: numeric.c:101
int errmsg(const char *fmt,...)
Definition: elog.c:824
static void alloc_var(NumericVar *var, int ndigits)
Definition: numeric.c:6702
int i
#define DEC_DIGITS
Definition: numeric.c:99

◆ do_numeric_accum()

static void do_numeric_accum ( NumericAggState state,
Numeric  newval 
)
static

Definition at line 4532 of file numeric.c.

References accum_sum_add(), NumericAggState::agg_context, NumericAggState::calcSumX2, NumericVar::dscale, init_var, init_var_from_num(), NumericAggState::maxScale, NumericAggState::maxScaleCount, MemoryContextSwitchTo(), mul_var(), NumericAggState::N, NumericAggState::NaNcount, NumericAggState::nInfcount, NUMERIC_IS_NINF, NUMERIC_IS_PINF, NUMERIC_IS_SPECIAL, NumericAggState::pInfcount, NumericAggState::sumX, and NumericAggState::sumX2.

Referenced by int2_accum(), int4_accum(), int8_accum(), int8_avg_accum(), numeric_accum(), and numeric_avg_accum().

4533 {
4534  NumericVar X;
4535  NumericVar X2;
4536  MemoryContext old_context;
4537 
4538  /* Count NaN/infinity inputs separately from all else */
4539  if (NUMERIC_IS_SPECIAL(newval))
4540  {
4541  if (NUMERIC_IS_PINF(newval))
4542  state->pInfcount++;
4543  else if (NUMERIC_IS_NINF(newval))
4544  state->nInfcount++;
4545  else
4546  state->NaNcount++;
4547  return;
4548  }
4549 
4550  /* load processed number in short-lived context */
4551  init_var_from_num(newval, &X);
4552 
4553  /*
4554  * Track the highest input dscale that we've seen, to support inverse
4555  * transitions (see do_numeric_discard).
4556  */
4557  if (X.dscale > state->maxScale)
4558  {
4559  state->maxScale = X.dscale;
4560  state->maxScaleCount = 1;
4561  }
4562  else if (X.dscale == state->maxScale)
4563  state->maxScaleCount++;
4564 
4565  /* if we need X^2, calculate that in short-lived context */
4566  if (state->calcSumX2)
4567  {
4568  init_var(&X2);
4569  mul_var(&X, &X, &X2, X.dscale * 2);
4570  }
4571 
4572  /* The rest of this needs to work in the aggregate context */
4573  old_context = MemoryContextSwitchTo(state->agg_context);
4574 
4575  state->N++;
4576 
4577  /* Accumulate sums */
4578  accum_sum_add(&(state->sumX), &X);
4579 
4580  if (state->calcSumX2)
4581  accum_sum_add(&(state->sumX2), &X2);
4582 
4583  MemoryContextSwitchTo(old_context);
4584 }
int64 nInfcount
Definition: numeric.c:4481
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
MemoryContext agg_context
Definition: numeric.c:4472
int dscale
Definition: numeric.c:309
#define NUMERIC_IS_SPECIAL(n)
Definition: numeric.c:174
static void accum_sum_add(NumericSumAccum *accum, const NumericVar *var1)
Definition: numeric.c:10851
#define NUMERIC_IS_PINF(n)
Definition: numeric.c:206
static void init_var_from_num(Numeric num, NumericVar *dest)
Definition: numeric.c:6951
static void mul_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result, int rscale)
Definition: numeric.c:8128
#define NUMERIC_IS_NINF(n)
Definition: numeric.c:207
NumericSumAccum sumX2
Definition: numeric.c:4475
int64 pInfcount
Definition: numeric.c:4480
int64 NaNcount
Definition: numeric.c:4479
int64 maxScaleCount
Definition: numeric.c:4477
NumericSumAccum sumX
Definition: numeric.c:4474
#define init_var(v)
Definition: numeric.c:495

◆ do_numeric_discard()

static bool do_numeric_discard ( NumericAggState state,
Numeric  newval 
)
static

Definition at line 4602 of file numeric.c.

References accum_sum_add(), accum_sum_reset(), NumericAggState::agg_context, Assert, NumericAggState::calcSumX2, NumericVar::dscale, init_var, init_var_from_num(), NumericAggState::maxScale, NumericAggState::maxScaleCount, MemoryContextSwitchTo(), mul_var(), NumericAggState::N, NumericAggState::NaNcount, NumericAggState::nInfcount, NUMERIC_IS_NINF, NUMERIC_IS_PINF, NUMERIC_IS_SPECIAL, NUMERIC_NEG, NUMERIC_POS, NumericAggState::pInfcount, NumericVar::sign, NumericAggState::sumX, and NumericAggState::sumX2.

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

4603 {
4604  NumericVar X;
4605  NumericVar X2;
4606  MemoryContext old_context;
4607 
4608  /* Count NaN/infinity inputs separately from all else */
4609  if (NUMERIC_IS_SPECIAL(newval))
4610  {
4611  if (NUMERIC_IS_PINF(newval))
4612  state->pInfcount--;
4613  else if (NUMERIC_IS_NINF(newval))
4614  state->nInfcount--;
4615  else
4616  state->NaNcount--;
4617  return true;
4618  }
4619 
4620  /* load processed number in short-lived context */
4621  init_var_from_num(newval, &X);
4622 
4623  /*
4624  * state->sumX's dscale is the maximum dscale of any of the inputs.
4625  * Removing the last input with that dscale would require us to recompute
4626  * the maximum dscale of the *remaining* inputs, which we cannot do unless
4627  * no more non-NaN inputs remain at all. So we report a failure instead,
4628  * and force the aggregation to be redone from scratch.
4629  */
4630  if (X.dscale == state->maxScale)
4631  {
4632  if (state->maxScaleCount > 1 || state->maxScale == 0)
4633  {
4634  /*
4635  * Some remaining inputs have same dscale, or dscale hasn't gotten
4636  * above zero anyway
4637  */
4638  state->maxScaleCount--;
4639  }
4640  else if (state->N == 1)
4641  {
4642  /* No remaining non-NaN inputs at all, so reset maxScale */
4643  state->maxScale = 0;
4644  state->maxScaleCount = 0;
4645  }
4646  else
4647  {
4648  /* Correct new maxScale is uncertain, must fail */
4649  return false;
4650  }
4651  }
4652 
4653  /* if we need X^2, calculate that in short-lived context */
4654  if (state->calcSumX2)
4655  {
4656  init_var(&X2);
4657  mul_var(&X, &X, &X2, X.dscale * 2);
4658  }
4659 
4660  /* The rest of this needs to work in the aggregate context */
4661  old_context = MemoryContextSwitchTo(state->agg_context);
4662 
4663  if (state->N-- > 1)
4664  {
4665  /* Negate X, to subtract it from the sum */
4666  X.sign = (X.sign == NUMERIC_POS ? NUMERIC_NEG : NUMERIC_POS);
4667  accum_sum_add(&(state->sumX), &X);
4668 
4669  if (state->calcSumX2)
4670  {
4671  /* Negate X^2. X^2 is always positive */
4672  X2.sign = NUMERIC_NEG;
4673  accum_sum_add(&(state->sumX2), &X2);
4674  }
4675  }
4676  else
4677  {
4678  /* Zero the sums */
4679  Assert(state->N == 0);
4680 
4681  accum_sum_reset(&state->sumX);
4682  if (state->calcSumX2)
4683  accum_sum_reset(&state->sumX2);
4684  }
4685 
4686  MemoryContextSwitchTo(old_context);
4687 
4688  return true;
4689 }
int64 nInfcount
Definition: numeric.c:4481
#define NUMERIC_POS
Definition: numeric.c:167
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
MemoryContext agg_context
Definition: numeric.c:4472
int dscale
Definition: numeric.c:309
#define NUMERIC_IS_SPECIAL(n)
Definition: numeric.c:174
#define NUMERIC_NEG
Definition: numeric.c:168
static void accum_sum_add(NumericSumAccum *accum, const NumericVar *var1)
Definition: numeric.c:10851
int sign
Definition: numeric.c:308
#define NUMERIC_IS_PINF(n)
Definition: numeric.c:206
static void init_var_from_num(Numeric num, NumericVar *dest)
Definition: numeric.c:6951
#define Assert(condition)
Definition: c.h:745
static void mul_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result, int rscale)
Definition: numeric.c:8128
#define NUMERIC_IS_NINF(n)
Definition: numeric.c:207
NumericSumAccum sumX2
Definition: numeric.c:4475
static void accum_sum_reset(NumericSumAccum *accum)
Definition: numeric.c:10835
int64 pInfcount
Definition: numeric.c:4480
int64 NaNcount
Definition: numeric.c:4479
int64 maxScaleCount
Definition: numeric.c:4477
NumericSumAccum sumX
Definition: numeric.c:4474
#define init_var(v)
Definition: numeric.c:495

◆ duplicate_numeric()

static Numeric duplicate_numeric ( Numeric  num)
static

Definition at line 7232 of file numeric.c.

References palloc(), and VARSIZE.

Referenced by numeric(), numeric_abs(), numeric_ceil(), numeric_exp(), numeric_floor(), numeric_inc(), numeric_ln(), numeric_mod_opt_error(), numeric_round(), numeric_sqrt(), numeric_trim_scale(), numeric_trunc(), numeric_uminus(), and numeric_uplus().

7233 {
7234  Numeric res;
7235 
7236  res = (Numeric) palloc(VARSIZE(num));
7237  memcpy(res, num, VARSIZE(num));
7238  return res;
7239 }
#define VARSIZE(PTR)
Definition: postgres.h:303
struct NumericData * Numeric
Definition: numeric.h:43
void * palloc(Size size)
Definition: mcxt.c:950

◆ estimate_ln_dweight()

static int estimate_ln_dweight ( const NumericVar var)
static

Definition at line 9818 of file numeric.c.

References Abs, cmp_var(), DEC_DIGITS, NumericVar::digits, digits, free_var(), init_var, ln_var(), NBASE, NumericVar::ndigits, sub_var(), and NumericVar::weight.

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

9819 {
9820  int ln_dweight;
9821 
9822  if (cmp_var(var, &const_zero_point_nine) >= 0 &&
9823  cmp_var(var, &const_one_point_one) <= 0)
9824  {
9825  /*
9826  * 0.9 <= var <= 1.1
9827  *
9828  * ln(var) has a negative weight (possibly very large). To get a
9829  * reasonably accurate result, estimate it using ln(1+x) ~= x.
9830  */
9831  NumericVar x;
9832 
9833  init_var(&x);
9834  sub_var(var, &const_one, &x);
9835 
9836  if (x.ndigits > 0)
9837  {
9838  /* Use weight of most significant decimal digit of x */
9839  ln_dweight = x.weight * DEC_DIGITS + (int) log10(x.digits[0]);
9840  }
9841  else
9842  {
9843  /* x = 0. Since ln(1) = 0 exactly, we don't need extra digits */
9844  ln_dweight = 0;
9845  }
9846 
9847  free_var(&x);
9848  }
9849  else
9850  {
9851  /*
9852  * Estimate the logarithm using the first couple of digits from the
9853  * input number. This will give an accurate result whenever the input
9854  * is not too close to 1.
9855  */
9856  if (var->ndigits > 0)
9857  {
9858  int digits;
9859  int dweight;
9860  double ln_var;
9861 
9862  digits = var->digits[0];
9863  dweight = var->weight * DEC_DIGITS;
9864 
9865  if (var->ndigits > 1)
9866  {
9867  digits = digits * NBASE + var->digits[1];
9868  dweight -= DEC_DIGITS;
9869  }
9870 
9871  /*----------
9872  * We have var ~= digits * 10^dweight
9873  * so ln(var) ~= ln(digits) + dweight * ln(10)
9874  *----------
9875  */
9876  ln_var = log((double) digits) + dweight * 2.302585092994046;
9877  ln_dweight = (int) log10(Abs(ln_var));
9878  }
9879  else
9880  {
9881  /* Caller should fail on ln(0), but for the moment return zero */
9882  ln_dweight = 0;
9883  }
9884  }
9885 
9886  return ln_dweight;
9887 }
int weight
Definition: numeric.c:307
static const NumericVar const_zero_point_nine
Definition: numeric.c:447
static const NumericVar const_one
Definition: numeric.c:420
static void ln_var(const NumericVar *arg, NumericVar *result, int rscale)
Definition: numeric.c:9896
int ndigits
Definition: numeric.c:306
#define Abs(x)
Definition: c.h:933
#define NBASE
Definition: numeric.c:97
static int cmp_var(const NumericVar *var1, const NumericVar *var2)
Definition: numeric.c:7832
static void free_var(NumericVar *var)
Definition: numeric.c:6718
NumericDigit * digits
Definition: numeric.c:311
static void sub_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition: numeric.c:8007
#define DEC_DIGITS
Definition: numeric.c:99
static const NumericVar const_one_point_one
Definition: numeric.c:457
#define init_var(v)
Definition: numeric.c:495
int digits
Definition: informix.c:666

◆ exp_var()

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

Definition at line 9692 of file numeric.c.

References Abs, add_var(), DEC_DIGITS, div_var_fast(), NumericVar::dscale, ereport, errcode(), errmsg(), ERROR, free_var(), init_var, Max, mul_var(), NumericVar::ndigits, NUMERIC_MAX_RESULT_SCALE, NUMERIC_MIN_DISPLAY_SCALE, numericvar_to_double_no_overflow(), round_var(), set_var_from_var(), val, and NumericVar::weight.

Referenced by numeric_exp(), and power_var().

9693 {
9694  NumericVar x;
9695  NumericVar elem;
9696  NumericVar ni;
9697  double val;
9698  int dweight;
9699  int ndiv2;
9700  int sig_digits;
9701  int local_rscale;
9702 
9703  init_var(&x);
9704  init_var(&elem);
9705  init_var(&ni);
9706 
9707  set_var_from_var(arg, &x);
9708 
9709  /*
9710  * Estimate the dweight of the result using floating point arithmetic, so
9711  * that we can choose an appropriate local rscale for the calculation.
9712  */
9714 
9715  /* Guard against overflow */
9716  /* If you change this limit, see also power_var()'s limit */
9717  if (Abs(val) >= NUMERIC_MAX_RESULT_SCALE * 3)
9718  ereport(ERROR,
9719  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
9720  errmsg("value overflows numeric format")));
9721 
9722  /* decimal weight = log10(e^x) = x * log10(e) */
9723  dweight = (int) (val * 0.434294481903252);
9724 
9725  /*
9726  * Reduce x to the range -0.01 <= x <= 0.01 (approximately) by dividing by
9727  * 2^n, to improve the convergence rate of the Taylor series.
9728  */
9729  if (Abs(val) > 0.01)
9730  {
9731  NumericVar tmp;
9732 
9733  init_var(&tmp);
9734  set_var_from_var(&const_two, &tmp);
9735 
9736  ndiv2 = 1;
9737  val /= 2;
9738 
9739  while (Abs(val) > 0.01)
9740  {
9741  ndiv2++;
9742  val /= 2;
9743  add_var(&tmp, &tmp, &tmp);
9744  }
9745 
9746  local_rscale = x.dscale + ndiv2;
9747  div_var_fast(&x, &tmp, &x, local_rscale, true);
9748 
9749  free_var(&tmp);
9750  }
9751  else
9752  ndiv2 = 0;
9753 
9754  /*
9755  * Set the scale for the Taylor series expansion. The final result has
9756  * (dweight + rscale + 1) significant digits. In addition, we have to
9757  * raise the Taylor series result to the power 2^ndiv2, which introduces
9758  * an error of up to around log10(2^ndiv2) digits, so work with this many
9759  * extra digits of precision (plus a few more for good measure).
9760  */
9761  sig_digits = 1 + dweight + rscale + (int) (ndiv2 * 0.301029995663981);
9762  sig_digits = Max(sig_digits, 0) + 8;
9763 
9764  local_rscale = sig_digits - 1;
9765 
9766  /*
9767  * Use the Taylor series
9768  *
9769  * exp(x) = 1 + x + x^2/2! + x^3/3! + ...
9770  *
9771  * Given the limited range of x, this should converge reasonably quickly.
9772  * We run the series until the terms fall below the local_rscale limit.
9773  */
9774  add_var(&const_one, &x, result);
9775 
9776  mul_var(&x, &x, &elem, local_rscale);
9777  set_var_from_var(&const_two, &ni);
9778  div_var_fast(&elem, &ni, &elem, local_rscale, true);
9779 
9780  while (elem.ndigits != 0)
9781  {
9782  add_var(result, &elem, result);
9783 
9784  mul_var(&elem, &x, &elem, local_rscale);
9785  add_var(&ni, &const_one, &ni);
9786  div_var_fast(&elem, &ni, &elem, local_rscale, true);
9787  }
9788 
9789  /*
9790  * Compensate for the argument range reduction. Since the weight of the
9791  * result doubles with each multiplication, we can reduce the local rscale
9792  * as we proceed.
9793  */
9794  while (ndiv2-- > 0)
9795  {
9796  local_rscale = sig_digits - result->weight * 2 * DEC_DIGITS;
9797  local_rscale = Max(local_rscale, NUMERIC_MIN_DISPLAY_SCALE);
9798  mul_var(result, result, result, local_rscale);
9799  }
9800 
9801  /* Round to requested rscale */
9802  round_var(result, rscale);
9803 
9804  free_var(&x);
9805  free_var(&elem);
9806  free_var(&ni);
9807 }
static void round_var(NumericVar *var, int rscale)
Definition: numeric.c:10626
int weight
Definition: numeric.c:307
static const NumericVar const_one
Definition: numeric.c:420
int errcode(int sqlerrcode)
Definition: elog.c:610
int ndigits
Definition: numeric.c:306
int dscale
Definition: numeric.c:309
#define Abs(x)
Definition: c.h:933
#define ERROR
Definition: elog.h:43
static double numericvar_to_double_no_overflow(const NumericVar *var)
Definition: numeric.c:7800
#define NUMERIC_MIN_DISPLAY_SCALE
Definition: numeric.h:30
#define NUMERIC_MAX_RESULT_SCALE
Definition: numeric.h:32
static void div_var_fast(const NumericVar *var1, const NumericVar *var2, NumericVar *result, int rscale, bool round)
Definition: numeric.c:8621
static void free_var(NumericVar *var)
Definition: numeric.c:6718
#define ereport(elevel,...)
Definition: elog.h:144
static const NumericVar const_two
Definition: numeric.c:427
static void mul_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result, int rscale)
Definition: numeric.c:8128
static void add_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition: numeric.c:7890
int errmsg(const char *fmt,...)
Definition: elog.c:824
#define Max(x, y)
Definition: numeric.c:13
#define DEC_DIGITS
Definition: numeric.c:99
static void set_var_from_var(const NumericVar *value, NumericVar *dest)
Definition: numeric.c:6968
long val
Definition: informix.c:664
#define init_var(v)
Definition: numeric.c:495

◆ float4_numeric()

Datum float4_numeric ( PG_FUNCTION_ARGS  )

Definition at line 4363 of file numeric.c.

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

4364 {
4366  Numeric res;
4367  NumericVar result;
4368  char buf[FLT_DIG + 100];
4369 
4370  if (isnan(val))
4372 
4373  if (isinf(val))
4374  {
4375  if (val < 0)
4377  else
4379  }
4380 
4381  snprintf(buf, sizeof(buf), "%.*g", FLT_DIG, val);
4382 
4383  init_var(&result);
4384 
4385  /* Assume we need not worry about leading/trailing spaces */
4386  (void) set_var_from_str(buf, buf, &result);
4387 
4388  res = make_result(&result);
4389 
4390  free_var(&result);
4391 
4392  PG_RETURN_NUMERIC(res);
4393 }
#define PG_RETURN_NUMERIC(x)
Definition: numeric.h:54
static char * buf
Definition: pg_test_fsync.c:67
static const NumericVar const_ninf
Definition: numeric.c:466
#define PG_GETARG_FLOAT4(n)
Definition: fmgr.h:280
float float4
Definition: c.h:497
static void free_var(NumericVar *var)
Definition: numeric.c:6718
static const NumericVar const_pinf
Definition: numeric.c:463
static const char * set_var_from_str(const char *str, const char *cp, NumericVar *dest)
Definition: numeric.c:6758
static const NumericVar const_nan
Definition: numeric.c:460
static Numeric make_result(const NumericVar *var)
Definition: numeric.c:7360
#define snprintf
Definition: port.h:193
long val
Definition: informix.c:664
#define init_var(v)
Definition: numeric.c:495

◆ float8_numeric()

Datum float8_numeric ( PG_FUNCTION_ARGS  )

Definition at line 4270 of file numeric.c.

References buf, free_var(), init_var, make_result(), PG_GETARG_FLOAT8, PG_RETURN_NUMERIC, set_var_from_str(), snprintf, and val.

Referenced by executeItemOptUnwrapTarget(), and SV_to_JsonbValue().

4271 {
4273  Numeric res;
4274  NumericVar result;
4275  char buf[DBL_DIG + 100];
4276 
4277  if (isnan(val))
4279 
4280  if (isinf(val))
4281  {
4282  if (val < 0)
4284  else
4286  }
4287 
4288  snprintf(buf, sizeof(buf), "%.*g", DBL_DIG, val);
4289 
4290  init_var(&result);
4291 
4292  /* Assume we need not worry about leading/trailing spaces */
4293  (void) set_var_from_str(buf, buf, &result);
4294 
4295  res = make_result(&result);
4296 
4297  free_var(&result);
4298 
4299  PG_RETURN_NUMERIC(res);
4300 }
#define PG_RETURN_NUMERIC(x)
Definition: numeric.h:54
#define PG_GETARG_FLOAT8(n)
Definition: fmgr.h:281
double float8
Definition: c.h:498
static char * buf
Definition: pg_test_fsync.c:67
static const NumericVar const_ninf
Definition: numeric.c:466
static void free_var(NumericVar *var)
Definition: numeric.c:6718
static const NumericVar const_pinf
Definition: numeric.c:463
static const char * set_var_from_str(const char *str, const char *cp, NumericVar *dest)
Definition: numeric.c:6758
static const NumericVar const_nan
Definition: numeric.c:460
static Numeric make_result(const NumericVar *var)
Definition: numeric.c:7360
#define snprintf
Definition: port.h:193
long val
Definition: informix.c:664
#define init_var(v)
Definition: numeric.c:495

◆ floor_var()

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

Definition at line 9119 of file numeric.c.

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

Referenced by compute_bucket(), and numeric_floor().

9120 {
9121  NumericVar tmp;
9122 
9123  init_var(&tmp);
9124  set_var_from_var(var, &tmp);
9125 
9126  trunc_var(&tmp, 0);
9127 
9128  if (var->sign == NUMERIC_NEG && cmp_var(var, &tmp) != 0)
9129  sub_var(&tmp, &const_one, &tmp);
9130 
9131  set_var_from_var(&tmp, result);
9132  free_var(&tmp);
9133 }
static void trunc_var(NumericVar *var, int rscale)
Definition: numeric.c:10732
static const NumericVar const_one
Definition: numeric.c:420
#define NUMERIC_NEG
Definition: numeric.c:168
int sign
Definition: numeric.c:308
static int cmp_var(const NumericVar *var1, const NumericVar *var2)
Definition: numeric.c:7832
static void free_var(NumericVar *var)
Definition: numeric.c:6718
static void sub_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition: numeric.c:8007
static void set_var_from_var(const NumericVar *value, NumericVar *dest)
Definition: numeric.c:6968
#define init_var(v)
Definition: numeric.c:495

◆ free_var()

static void free_var ( NumericVar var)
static

Definition at line 6718 of file numeric.c.

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

Referenced by accum_sum_combine(), ceil_var(), compute_bucket(), div_mod_var(), estimate_ln_dweight(), exp_var(), float4_numeric(), float8_numeric(), floor_var(), gcd_var(), get_str_from_var_sci(), in_range_numeric_numeric(), int64_to_numeric(), int8_avg_serialize(), ln_var(), log_var(), mod_var(), numeric(), numeric_add_opt_error(), numeric_avg(), numeric_avg_serialize(), numeric_ceil(), numeric_div_opt_error(), numeric_div_trunc(), numeric_exp(), numeric_fac(), numeric_floor(), numeric_gcd(), numeric_in(), numeric_inc(), numeric_lcm(), numeric_ln(), numeric_log(), numeric_min_scale(), numeric_mod_opt_error(), numeric_mul_opt_error(), numeric_poly_avg(), numeric_poly_serialize(), numeric_poly_sum(), numeric_power(), numeric_recv(), numeric_round(), numeric_serialize(), numeric_sqrt(), numeric_stddev_internal(), numeric_stddev_pop(), numeric_sub_opt_error(), numeric_sum(), numeric_trim_scale(), numeric_trunc(), numericvar_to_int64(), numericvar_to_uint64(), power_var(), power_var_int(), sqrt_var(), and width_bucket_numeric().

6719 {
6720  digitbuf_free(var->buf);
6721  var->buf = NULL;
6722  var->digits = NULL;
6723  var->sign = NUMERIC_NAN;
6724 }
int sign
Definition: numeric.c:308
#define digitbuf_free(buf)
Definition: numeric.c:489
#define NUMERIC_NAN
Definition: numeric.c:199
NumericDigit * buf
Definition: numeric.c:310
NumericDigit * digits
Definition: numeric.c:311

◆ gcd_var()

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

Definition at line 9142 of file numeric.c.

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

Referenced by numeric_gcd(), and numeric_lcm().

9143 {
9144  int res_dscale;
9145  int cmp;
9146  NumericVar tmp_arg;
9147  NumericVar mod;
9148 
9149  res_dscale = Max(var1->dscale, var2->dscale);
9150 
9151  /*
9152  * Arrange for var1 to be the number with the greater absolute value.
9153  *
9154  * This would happen automatically in the loop below, but avoids an
9155  * expensive modulo operation.
9156  */
9157  cmp = cmp_abs(var1, var2);
9158  if (cmp < 0)
9159  {
9160  const NumericVar *tmp = var1;
9161 
9162  var1 = var2;
9163  var2 = tmp;
9164  }
9165 
9166  /*
9167  * Also avoid the taking the modulo if the inputs have the same absolute
9168  * value, or if the smaller input is zero.
9169  */
9170  if (cmp == 0 || var2->ndigits == 0)
9171  {
9172  set_var_from_var(var1, result);
9173  result->sign = NUMERIC_POS;
9174  result->dscale = res_dscale;
9175  return;
9176  }
9177 
9178  init_var(&tmp_arg);
9179  init_var(&mod);
9180 
9181  /* Use the Euclidean algorithm to find the GCD */
9182  set_var_from_var(var1, &tmp_arg);
9183  set_var_from_var(var2, result);
9184 
9185  for (;;)
9186  {
9187  /* this loop can take a while, so allow it to be interrupted */
9189 
9190  mod_var(&tmp_arg, result, &mod);
9191  if (mod.ndigits == 0)
9192  break;
9193  set_var_from_var(result, &tmp_arg);
9194  set_var_from_var(&mod, result);
9195  }
9196  result->sign = NUMERIC_POS;
9197  result->dscale = res_dscale;
9198 
9199  free_var(&tmp_arg);
9200  free_var(&mod);
9201 }
#define NUMERIC_POS
Definition: numeric.c:167
int ndigits
Definition: numeric.c:306
int dscale
Definition: numeric.c:309
int sign
Definition: numeric.c:308
static void mod_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition: numeric.c:8996
static void free_var(NumericVar *var)
Definition: numeric.c:6718
static int cmp_abs(const NumericVar *var1, const NumericVar *var2)
Definition: numeric.c:10381
#define Max(x, y)
Definition: numeric.c:13
static void set_var_from_var(const NumericVar *value, NumericVar *dest)
Definition: numeric.c:6968
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:99
#define init_var(v)
Definition: numeric.c:495
static int cmp(const chr *x, const chr *y, size_t len)
Definition: regc_locale.c:742

◆ generate_series_numeric()

Datum generate_series_numeric ( PG_FUNCTION_ARGS  )

Definition at line 1559 of file numeric.c.

References generate_series_step_numeric().

1560 {
1561  return generate_series_step_numeric(fcinfo);
1562 }
Datum generate_series_step_numeric(PG_FUNCTION_ARGS)
Definition: numeric.c:1565

◆ generate_series_step_numeric()

Datum generate_series_step_numeric ( PG_FUNCTION_ARGS  )

Definition at line 1565 of file numeric.c.

References add_var(), cmp_var(), const_one, generate_series_numeric_fctx::current, ereport, errcode(), errmsg(), ERROR, init_var, init_var_from_num(), make_result(), MemoryContextSwitchTo(), FuncCallContext::multi_call_memory_ctx, NUMERIC_IS_NAN, NUMERIC_IS_SPECIAL, NUMERIC_NEG, NUMERIC_POS, NumericGetDatum, palloc(), PG_GETARG_NUMERIC, PG_NARGS, set_var_from_num(), set_var_from_var(), NumericVar::sign, SRF_FIRSTCALL_INIT, SRF_IS_FIRSTCALL, SRF_PERCALL_SETUP, SRF_RETURN_DONE, SRF_RETURN_NEXT, generate_series_numeric_fctx::step, generate_series_numeric_fctx::stop, and FuncCallContext::user_fctx.

Referenced by generate_series_numeric().

1566 {
1568  FuncCallContext *funcctx;
1569  MemoryContext oldcontext;
1570 
1571  if (SRF_IS_FIRSTCALL())
1572  {
1573  Numeric start_num = PG_GETARG_NUMERIC(0);
1574  Numeric stop_num = PG_GETARG_NUMERIC(1);
1575  NumericVar steploc = const_one;
1576 
1577  /* Reject NaN and infinities in start and stop values */
1578  if (NUMERIC_IS_SPECIAL(start_num))
1579  {
1580  if (NUMERIC_IS_NAN(start_num))
1581  ereport(ERROR,
1582  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1583  errmsg("start value cannot be NaN")));
1584  else
1585  ereport(ERROR,
1586  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1587  errmsg("start value cannot be infinity")));
1588  }
1589  if (NUMERIC_IS_SPECIAL(stop_num))
1590  {
1591  if (NUMERIC_IS_NAN(stop_num))
1592  ereport(ERROR,
1593  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1594  errmsg("stop value cannot be NaN")));
1595  else
1596  ereport(ERROR,
1597  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1598  errmsg("stop value cannot be infinity")));
1599  }
1600 
1601  /* see if we were given an explicit step size */
1602  if (PG_NARGS() == 3)
1603  {
1604  Numeric step_num = PG_GETARG_NUMERIC(2);
1605 
1606  if (NUMERIC_IS_SPECIAL(step_num))
1607  {
1608  if (NUMERIC_IS_NAN(step_num))
1609  ereport(ERROR,
1610  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1611  errmsg("step size cannot be NaN")));
1612  else
1613  ereport(ERROR,
1614  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1615  errmsg("step size cannot be infinity")));
1616  }
1617 
1618  init_var_from_num(step_num, &steploc);
1619 
1620  if (cmp_var(&steploc, &const_zero) == 0)
1621  ereport(ERROR,
1622  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1623  errmsg("step size cannot equal zero")));
1624  }
1625 
1626  /* create a function context for cross-call persistence */
1627  funcctx = SRF_FIRSTCALL_INIT();
1628 
1629  /*
1630  * Switch to memory context appropriate for multiple function calls.
1631  */
1632  oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
1633 
1634  /* allocate memory for user context */
1635  fctx = (generate_series_numeric_fctx *)
1637 
1638  /*
1639  * Use fctx to keep state from call to call. Seed current with the
1640  * original start value. We must copy the start_num and stop_num
1641  * values rather than pointing to them, since we may have detoasted
1642  * them in the per-call context.
1643  */
1644  init_var(&fctx->current);
1645  init_var(&fctx->stop);
1646  init_var(&fctx->step);
1647 
1648  set_var_from_num(start_num, &fctx->current);
1649  set_var_from_num(stop_num, &fctx->stop);
1650  set_var_from_var(&steploc, &fctx->step);
1651 
1652  funcctx->user_fctx = fctx;
1653  MemoryContextSwitchTo(oldcontext);
1654  }
1655 
1656  /* stuff done on every call of the function */
1657  funcctx = SRF_PERCALL_SETUP();
1658 
1659  /*
1660  * Get the saved state and use current state as the result of this
1661  * iteration.
1662  */
1663  fctx = funcctx->user_fctx;
1664 
1665  if ((fctx->step.sign == NUMERIC_POS &&
1666  cmp_var(&fctx->current, &fctx->stop) <= 0) ||
1667  (fctx->step.sign == NUMERIC_NEG &&
1668  cmp_var(&fctx->current, &fctx->stop) >= 0))
1669  {
1670  Numeric result = make_result(&fctx->current);
1671 
1672  /* switch to memory context appropriate for iteration calculation */
1673  oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
1674 
1675  /* increment current in preparation for next iteration */
1676  add_var(&fctx->current, &fctx->step, &fctx->current);
1677  MemoryContextSwitchTo(oldcontext);
1678 
1679  /* do when there is more left to send */
1680  SRF_RETURN_NEXT(funcctx, NumericGetDatum(result));
1681  }
1682  else
1683  /* do when there is no more left */
1684  SRF_RETURN_DONE(funcctx);
1685 }
#define SRF_IS_FIRSTCALL()
Definition: funcapi.h:293
static const NumericVar const_one
Definition: numeric.c:420
#define NumericGetDatum(X)
Definition: numeric.h:51
#define NUMERIC_POS
Definition: numeric.c:167
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
int errcode(int sqlerrcode)
Definition: elog.c:610
#define SRF_PERCALL_SETUP()
Definition: funcapi.h:297
#define SRF_RETURN_NEXT(_funcctx, _result)
Definition: funcapi.h:299
#define NUMERIC_IS_SPECIAL(n)
Definition: numeric.c:174
#define NUMERIC_NEG
Definition: numeric.c:168
int sign
Definition: numeric.c:308
#define ERROR
Definition: elog.h:43
static void init_var_from_num(Numeric num, NumericVar *dest)
Definition: numeric.c:6951
static const NumericVar const_zero
Definition: numeric.c:416
static int cmp_var(const NumericVar *var1, const NumericVar *var2)
Definition: numeric.c:7832
#define ereport(elevel,...)
Definition: elog.h:144
#define PG_GETARG_NUMERIC(n)
Definition: numeric.h:52
static void set_var_from_num(Numeric value, NumericVar *dest)
Definition: numeric.c:6920
MemoryContext multi_call_memory_ctx
Definition: funcapi.h:101
static void add_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition: numeric.c:7890
#define PG_NARGS()
Definition: fmgr.h:203
static Numeric make_result(const NumericVar *var)
Definition: numeric.c:7360
void * user_fctx
Definition: funcapi.h:82
void * palloc(Size size)
Definition: mcxt.c:950
int errmsg(const char *fmt,...)
Definition: elog.c:824
#define NUMERIC_IS_NAN(n)
Definition: numeric.c:205
static void set_var_from_var(const NumericVar *value, NumericVar *dest)
Definition: numeric.c:6968
#define init_var(v)
Definition: numeric.c:495
#define SRF_RETURN_DONE(_funcctx)
Definition: funcapi.h:317
#define SRF_FIRSTCALL_INIT()
Definition: funcapi.h:295

◆ get_min_scale()

static int get_min_scale ( NumericVar var)
static

Definition at line 3980 of file numeric.c.

References DEC_DIGITS, NumericVar::digits, NumericVar::ndigits, and NumericVar::weight.

Referenced by numeric_min_scale(), and numeric_trim_scale().

3981 {
3982  int min_scale;
3983  int last_digit_pos;
3984 
3985  /*
3986  * Ordinarily, the input value will be "stripped" so that the last
3987  * NumericDigit is nonzero. But we don't want to get into an infinite
3988  * loop if it isn't, so explicitly find the last nonzero digit.
3989  */
3990  last_digit_pos = var->ndigits - 1;
3991  while (last_digit_pos >= 0 &&
3992  var->digits[last_digit_pos] == 0)
3993  last_digit_pos--;
3994 
3995  if (last_digit_pos >= 0)
3996  {
3997  /* compute min_scale assuming that last ndigit has no zeroes */
3998  min_scale = (last_digit_pos - var->weight) * DEC_DIGITS;
3999 
4000  /*
4001  * We could get a negative result if there are no digits after the
4002  * decimal point. In this case the min_scale must be zero.
4003  */
4004  if (min_scale > 0)
4005  {
4006  /*
4007  * Reduce min_scale if trailing digit(s) in last NumericDigit are
4008  * zero.
4009  */
4010  NumericDigit last_digit = var->digits[last_digit_pos];
4011 
4012  while (last_digit % 10 == 0)
4013  {
4014  min_scale--;
4015  last_digit /= 10;
4016  }
4017  }
4018  else
4019  min_scale = 0;
4020  }
4021  else
4022  min_scale = 0; /* result if input is zero */
4023 
4024  return min_scale;
4025 }
int weight
Definition: numeric.c:307
int ndigits
Definition: numeric.c:306
int16 NumericDigit
Definition: numeric.c:103
NumericDigit * digits
Definition: numeric.c:311
#define DEC_DIGITS
Definition: numeric.c:99

◆ get_str_from_var()

static char * get_str_from_var ( const NumericVar var)
static

Definition at line 6994 of file numeric.c.

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

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

6995 {
6996  int dscale;
6997  char *str;
6998  char *cp;
6999  char *endcp;
7000  int i;
7001  int d;
7002  NumericDigit dig;
7003 
7004 #if DEC_DIGITS > 1
7005  NumericDigit d1;
7006 #endif
7007 
7008  dscale = var->dscale;
7009 
7010  /*
7011  * Allocate space for the result.
7012  *
7013  * i is set to the # of decimal digits before decimal point. dscale is the
7014  * # of decimal digits we will print after decimal point. We may generate
7015  * as many as DEC_DIGITS-1 excess digits at the end, and in addition we
7016  * need room for sign, decimal point, null terminator.
7017  */
7018  i = (var->weight + 1) * DEC_DIGITS;
7019  if (i <= 0)
7020  i = 1;
7021 
7022  str = palloc(i + dscale + DEC_DIGITS + 2);
7023  cp = str;
7024 
7025  /*
7026  * Output a dash for negative values
7027  */
7028  if (var->sign == NUMERIC_NEG)
7029  *cp++ = '-';
7030 
7031  /*
7032  * Output all digits before the decimal point
7033  */
7034  if (var->weight < 0)
7035  {
7036  d = var->weight + 1;
7037  *cp++ = '0';
7038  }
7039  else
7040  {
7041  for (d = 0; d <= var->weight; d++)
7042  {
7043  dig = (d < var->ndigits) ? var->digits[d] : 0;
7044  /* In the first digit, suppress extra leading decimal zeroes */
7045 #if DEC_DIGITS == 4
7046  {
7047  bool putit = (d > 0);
7048 
7049  d1 = dig / 1000;
7050  dig -= d1 * 1000;
7051  putit |= (d1 > 0);
7052  if (putit)
7053  *cp++ = d1 + '0';
7054  d1 = dig / 100;
7055  dig -= d1 * 100;
7056  putit |= (d1 > 0);
7057  if (putit)
7058  *cp++ = d1 + '0';
7059  d1 = dig / 10;
7060  dig -= d1 * 10;
7061  putit |= (d1 > 0);
7062  if (putit)
7063  *cp++ = d1 + '0';
7064  *cp++ = dig + '0';
7065  }
7066 #elif DEC_DIGITS == 2
7067  d1 = dig / 10;
7068  dig -= d1 * 10;
7069  if (d1 > 0 || d > 0)
7070  *cp++ = d1 + '0';
7071  *cp++ = dig + '0';
7072 #elif DEC_DIGITS == 1
7073  *cp++ = dig + '0';
7074 #else
7075 #error unsupported NBASE
7076 #endif
7077  }
7078  }
7079 
7080  /*
7081  * If requested, output a decimal point and all the digits that follow it.
7082  * We initially put out a multiple of DEC_DIGITS digits, then truncate if
7083  * needed.
7084  */
7085  if (dscale > 0)
7086  {
7087  *cp++ = '.';
7088  endcp = cp + dscale;
7089  for (i = 0; i < dscale; d++, i += DEC_DIGITS)
7090  {
7091  dig = (d >= 0 && d < var->ndigits) ? var->digits[d] : 0;
7092 #if DEC_DIGITS == 4
7093  d1 = dig / 1000;
7094  dig -= d1 * 1000;
7095  *cp++ = d1 + '0';
7096  d1 = dig / 100;
7097  dig -= d1 * 100;
7098  *cp++ = d1 + '0';
7099  d1 = dig / 10;
7100  dig -= d1 * 10;
7101  *cp++ = d1 + '0';
7102  *cp++ = dig + '0';
7103 #elif DEC_DIGITS == 2
7104  d1 = dig / 10;
7105  dig -= d1 * 10;
7106  *cp++ = d1 + '0';
7107  *cp++ = dig + '0';
7108 #elif DEC_DIGITS == 1
7109  *cp++ = dig + '0';
7110 #else
7111 #error unsupported NBASE
7112 #endif
7113  }
7114  cp = endcp;
7115  }
7116 
7117  /*
7118  * terminate the string and return it
7119  */
7120  *cp = '\0';
7121  return str;
7122 }
int weight
Definition: numeric.c:307
static void error(void)
Definition: sql-dyntest.c:147
int ndigits
Definition: numeric.c:306
int dscale
Definition: numeric.c:309
#define NUMERIC_NEG
Definition: numeric.c:168
int sign
Definition: numeric.c:308
int16 NumericDigit
Definition: numeric.c:103
#define NBASE
Definition: numeric.c:97
NumericDigit * digits
Definition: numeric.c:311
void * palloc(Size size)
Definition: mcxt.c:950
int i
#define DEC_DIGITS
Definition: numeric.c:99

◆ get_str_from_var_sci()

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

Definition at line 7147 of file numeric.c.

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

Referenced by numeric_out_sci().

7148 {
7149  int32 exponent;
7150  NumericVar denominator;
7151  NumericVar significand;
7152  int denom_scale;
7153  size_t len;
7154  char *str;
7155  char *sig_out;
7156 
7157  if (rscale < 0)
7158  rscale = 0;
7159 
7160  /*
7161  * Determine the exponent of this number in normalised form.
7162  *
7163  * This is the exponent required to represent the number with only one
7164  * significant digit before the decimal place.
7165  */
7166  if (var->ndigits > 0)
7167  {
7168  exponent = (var->weight + 1) * DEC_DIGITS;
7169 
7170  /*
7171  * Compensate for leading decimal zeroes in the first numeric digit by
7172  * decrementing the exponent.
7173  */
7174  exponent -= DEC_DIGITS - (int) log10(var->digits[0]);
7175  }
7176  else
7177  {
7178  /*
7179  * If var has no digits, then it must be zero.
7180  *
7181  * Zero doesn't technically have a meaningful exponent in normalised
7182  * notation, but we just display the exponent as zero for consistency
7183  * of output.
7184  */
7185  exponent = 0;
7186  }
7187 
7188  /*
7189  * The denominator is set to 10 raised to the power of the exponent.
7190  *
7191  * We then divide var by the denominator to get the significand, rounding
7192  * to rscale decimal digits in the process.
7193  */
7194  if (exponent < 0)
7195  denom_scale = -exponent;
7196  else
7197  denom_scale = 0;
7198 
7199  init_var(&denominator);
7200  init_var(&significand);
7201 
7202  power_var_int(&const_ten, exponent, &denominator, denom_scale);
7203  div_var(var, &denominator, &significand, rscale, true);
7204  sig_out = get_str_from_var(&significand);
7205 
7206  free_var(&denominator);
7207  free_var(&significand);
7208 
7209  /*
7210  * Allocate space for the result.
7211  *
7212  * In addition to the significand, we need room for the exponent
7213  * decoration ("e"), the sign of the exponent, up to 10 digits for the
7214  * exponent itself, and of course the null terminator.
7215  */
7216  len = strlen(sig_out) + 13;
7217  str = palloc(len);
7218  snprintf(str, len, "%se%+03d", sig_out, exponent);
7219 
7220  pfree(sig_out);
7221 
7222  return str;
7223 }
int weight
Definition: numeric.c:307
int ndigits
Definition: numeric.c:306
static void div_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result, int rscale, bool round)
Definition: numeric.c:8336
signed int int32
Definition: c.h:362
void pfree(void *pointer)
Definition: mcxt.c:1057
static void power_var_int(const NumericVar *base, int exp, NumericVar *result, int rscale)
Definition: numeric.c:10191
static const NumericVar const_ten
Definition: numeric.c:432
static void free_var(NumericVar *var)
Definition: numeric.c:6718
NumericDigit * digits
Definition: numeric.c:311
void * palloc(Size size)
Definition: mcxt.c:950
static char * get_str_from_var(const NumericVar *var)
Definition: numeric.c:6994
#define DEC_DIGITS
Definition: numeric.c:99
#define snprintf
Definition: port.h:193
#define init_var(v)
Definition: numeric.c:495

◆ hash_numeric()

Datum hash_numeric ( PG_FUNCTION_ARGS  )

Definition at line 2558 of file numeric.c.

References Assert, digits, hash_any(), i, sort-test::key, NUMERIC_DIGITS, NUMERIC_IS_SPECIAL, NUMERIC_NDIGITS, NUMERIC_WEIGHT, PG_GETARG_NUMERIC, PG_RETURN_DATUM, and PG_RETURN_UINT32.

Referenced by JsonbHashScalarValue().

2559 {
2561  Datum digit_hash;
2562  Datum result;
2563  int weight;
2564  int start_offset;
2565  int end_offset;
2566  int i;
2567  int hash_len;
2569 
2570  /* If it's NaN or infinity, don't try to hash the rest of the fields */
2571  if (NUMERIC_IS_SPECIAL(key))
2572  PG_RETURN_UINT32(0);
2573 
2574  weight = NUMERIC_WEIGHT(key);
2575  start_offset = 0;
2576  end_offset = 0;
2577 
2578  /*
2579  * Omit any leading or trailing zeros from the input to the hash. The
2580  * numeric implementation *should* guarantee that leading and trailing
2581  * zeros are suppressed, but we're paranoid. Note that we measure the
2582  * starting and ending offsets in units of NumericDigits, not bytes.
2583  */
2584  digits = NUMERIC_DIGITS(key);
2585  for (i = 0; i < NUMERIC_NDIGITS(key); i++)
2586  {
2587  if (digits[i] != (NumericDigit) 0)
2588  break;
2589 
2590  start_offset++;
2591 
2592  /*
2593  * The weight is effectively the # of digits before the decimal point,
2594  * so decrement it for each leading zero we skip.
2595  */
2596  weight--;
2597  }
2598 
2599  /*
2600  * If there are no non-zero digits, then the value of the number is zero,
2601  * regardless of any other fields.
2602  */
2603  if (NUMERIC_NDIGITS(key) == start_offset)
2604  PG_RETURN_UINT32(-1);
2605 
2606  for (i = NUMERIC_NDIGITS(key) - 1; i >= 0; i--)
2607  {
2608  if (digits[i] != (NumericDigit) 0)
2609  break;
2610 
2611  end_offset++;
2612  }
2613 
2614  /* If we get here, there should be at least one non-zero digit */
2615  Assert(start_offset + end_offset < NUMERIC_NDIGITS(key));
2616 
2617  /*
2618  * Note that we don't hash on the Numeric's scale, since two numerics can
2619  * compare equal but have different scales. We also don't hash on the
2620  * sign, although we could: since a sign difference implies inequality,
2621  * this shouldn't affect correctness.
2622  */
2623  hash_len = NUMERIC_NDIGITS(key) - start_offset - end_offset;
2624  digit_hash = hash_any((unsigned char *) (NUMERIC_DIGITS(key) + start_offset),
2625  hash_len * sizeof(NumericDigit));
2626 
2627  /* Mix in the weight, via XOR */
2628  result = digit_hash ^ weight;
2629 
2630  PG_RETURN_DATUM(result);
2631 }
#define PG_RETURN_UINT32(x)
Definition: fmgr.h:354
#define NUMERIC_IS_SPECIAL(n)
Definition: numeric.c:174
#define NUMERIC_DIGITS(num)
Definition: numeric.c:497
int16 NumericDigit
Definition: numeric.c:103
static Datum hash_any(const unsigned char *k, int keylen)
Definition: hashfn.h:31
#define NUMERIC_NDIGITS(num)
Definition: numeric.c:499
uintptr_t Datum
Definition: postgres.h:367
#define PG_RETURN_DATUM(x)
Definition: fmgr.h:352
#define NUMERIC_WEIGHT(n)
Definition: numeric.c:247
#define PG_GETARG_NUMERIC(n)
Definition: numeric.h:52
#define Assert(condition)
Definition: c.h:745
int i
int digits
Definition: informix.c:666

◆ hash_numeric_extended()

Datum hash_numeric_extended ( PG_FUNCTION_ARGS  )

Definition at line 2638 of file numeric.c.

References Assert, DatumGetUInt64, digits, hash_any_extended(), i, sort-test::key, NUMERIC_DIGITS, NUMERIC_IS_SPECIAL, NUMERIC_NDIGITS, NUMERIC_WEIGHT, PG_GETARG_INT64, PG_GETARG_NUMERIC, PG_RETURN_DATUM, PG_RETURN_UINT64, and UInt64GetDatum.

Referenced by JsonbHashScalarValueExtended().

2639 {
2641  uint64 seed = PG_GETARG_INT64(1);
2642  Datum digit_hash;
2643  Datum result;
2644  int weight;
2645  int start_offset;
2646  int end_offset;
2647  int i;
2648  int hash_len;
2650 
2651  /* If it's NaN or infinity, don't try to hash the rest of the fields */
2652  if (NUMERIC_IS_SPECIAL(key))
2653  PG_RETURN_UINT64(seed);
2654 
2655  weight = NUMERIC_WEIGHT(key);
2656  start_offset = 0;
2657  end_offset = 0;
2658 
2659  digits = NUMERIC_DIGITS(key);
2660  for (i = 0; i < NUMERIC_NDIGITS(key); i++)
2661  {
2662  if (digits[i] != (NumericDigit) 0)
2663  break;
2664 
2665  start_offset++;
2666 
2667  weight--;
2668  }
2669 
2670  if (NUMERIC_NDIGITS(key) == start_offset)
2671  PG_RETURN_UINT64(seed - 1);
2672 
2673  for (i = NUMERIC_NDIGITS(key) - 1; i >= 0; i--)
2674  {
2675  if (digits[i] != (NumericDigit) 0)
2676  break;
2677 
2678  end_offset++;
2679  }
2680 
2681  Assert(start_offset + end_offset < NUMERIC_NDIGITS(key));
2682 
2683  hash_len = NUMERIC_NDIGITS(key) - start_offset - end_offset;
2684  digit_hash = hash_any_extended((unsigned char *) (NUMERIC_DIGITS(key)
2685  + start_offset),
2686  hash_len * sizeof(NumericDigit),
2687  seed);
2688 
2689  result = UInt64GetDatum(DatumGetUInt64(digit_hash) ^ weight);
2690 
2691  PG_RETURN_DATUM(result);
2692 }
#define UInt64GetDatum(X)
Definition: postgres.h:648
static Datum hash_any_extended(const unsigned char *k, int keylen, uint64 seed)
Definition: hashfn.h:37
#define PG_RETURN_UINT64(x)
Definition: fmgr.h:367
#define NUMERIC_IS_SPECIAL(n)
Definition: numeric.c:174
#define NUMERIC_DIGITS(num)
Definition: numeric.c:497
int16 NumericDigit
Definition: numeric.c:103
#define NUMERIC_NDIGITS(num)
Definition: numeric.c:499
uintptr_t Datum
Definition: postgres.h:367
#define PG_RETURN_DATUM(x)
Definition: fmgr.h:352
#define DatumGetUInt64(X)
Definition: postgres.h:634
#define NUMERIC_WEIGHT(n)
Definition: numeric.c:247
#define PG_GETARG_NUMERIC(n)
Definition: numeric.h:52
#define Assert(condition)
Definition: c.h:745
int i
#define PG_GETARG_INT64(n)
Definition: fmgr.h:282
int digits
Definition: informix.c:666

◆ in_range_numeric_numeric()

Datum in_range_numeric_numeric ( PG_FUNCTION_ARGS  )

Definition at line 2423 of file numeric.c.

References add_var(), Assert, cmp_var(), ereport, errcode(), errmsg(), ERROR, free_var(), init_var, init_var_from_num(), NUMERIC_IS_NAN, NUMERIC_IS_NINF, NUMERIC_IS_PINF, NUMERIC_IS_SPECIAL, NUMERIC_NEG, NUMERIC_SIGN, PG_FREE_IF_COPY, PG_GETARG_BOOL, PG_GETARG_NUMERIC, PG_RETURN_BOOL, sub_var(), and val.

2424 {
2426  Numeric base = PG_GETARG_NUMERIC(1);
2427  Numeric offset = PG_GETARG_NUMERIC(2);
2428  bool sub = PG_GETARG_BOOL(3);
2429  bool less = PG_GETARG_BOOL(4);
2430  bool result;
2431 
2432  /*
2433  * Reject negative (including -Inf) or NaN offset. Negative is per spec,
2434  * and NaN is because appropriate semantics for that seem non-obvious.
2435  */
2436  if (NUMERIC_IS_NAN(offset) ||
2437  NUMERIC_IS_NINF(offset) ||
2438  NUMERIC_SIGN(offset) == NUMERIC_NEG)
2439  ereport(ERROR,
2440  (errcode(ERRCODE_INVALID_PRECEDING_OR_FOLLOWING_SIZE),
2441  errmsg("invalid preceding or following size in window function")));
2442 
2443  /*
2444  * Deal with cases where val and/or base is NaN, following the rule that
2445  * NaN sorts after non-NaN (cf cmp_numerics). The offset cannot affect
2446  * the conclusion.
2447  */
2448  if (NUMERIC_IS_NAN(val))
2449  {
2450  if (NUMERIC_IS_NAN(base))
2451  result = true; /* NAN = NAN */
2452  else
2453  result = !less; /* NAN > non-NAN */
2454  }
2455  else if (NUMERIC_IS_NAN(base))
2456  {
2457  result = less; /* non-NAN < NAN */
2458  }
2459 
2460  /*
2461  * Deal with infinite offset (necessarily +Inf, at this point).
2462  */
2463  else if (NUMERIC_IS_SPECIAL(offset))
2464  {
2465  Assert(NUMERIC_IS_PINF(offset));
2466  if (sub ? NUMERIC_IS_PINF(base) : NUMERIC_IS_NINF(base))
2467  {
2468  /*
2469  * base +/- offset would produce NaN, so return true for any val
2470  * (see in_range_float8_float8() for reasoning).
2471  */
2472  result = true;
2473  }
2474  else if (sub)
2475  {
2476  /* base - offset must be -inf */
2477  if (less)
2478  result = NUMERIC_IS_NINF(val); /* only -inf is <= sum */
2479  else
2480  result = true; /* any val is >= sum */
2481  }
2482  else
2483  {
2484  /* base + offset must be +inf */
2485  if (less)
2486  result = true; /* any val is <= sum */
2487  else
2488  result = NUMERIC_IS_PINF(val); /* only +inf is >= sum */
2489  }
2490  }
2491 
2492  /*
2493  * Deal with cases where val and/or base is infinite. The offset, being
2494  * now known finite, cannot affect the conclusion.
2495  */
2496  else if (NUMERIC_IS_SPECIAL(val))
2497  {
2498  if (NUMERIC_IS_PINF(val))
2499  {
2500  if (NUMERIC_IS_PINF(base))
2501  result = true; /* PINF = PINF */
2502  else
2503  result = !less; /* PINF > any other non-NAN */
2504  }
2505  else /* val must be NINF */
2506  {
2507  if (NUMERIC_IS_NINF(base))
2508  result = true; /* NINF = NINF */
2509  else
2510  result = less; /* NINF < anything else */
2511  }
2512  }
2513  else if (NUMERIC_IS_SPECIAL(base))
2514  {
2515  if (NUMERIC_IS_NINF(base))
2516  result = !less; /* normal > NINF */
2517  else
2518  result = less; /* normal < PINF */
2519  }
2520  else
2521  {
2522  /*
2523  * Otherwise go ahead and compute base +/- offset. While it's
2524  * possible for this to overflow the numeric format, it's unlikely
2525  * enough that we don't take measures to prevent it.
2526  */
2527  NumericVar valv;
2528  NumericVar basev;
2529  NumericVar offsetv;
2530  NumericVar sum;
2531 
2532  init_var_from_num(val, &valv);
2533  init_var_from_num(base, &basev);
2534  init_var_from_num(offset, &offsetv);
2535  init_var(&sum);
2536 
2537  if (sub)
2538  sub_var(&basev, &offsetv, &sum);
2539  else
2540  add_var(&basev, &offsetv, &sum);
2541 
2542  if (less)
2543  result = (cmp_var(&valv, &sum) <= 0);
2544  else
2545  result = (cmp_var(&valv, &sum) >= 0);
2546 
2547  free_var(&sum);
2548  }
2549 
2550  PG_FREE_IF_COPY(val, 0);
2551  PG_FREE_IF_COPY(base, 1);
2552  PG_FREE_IF_COPY(offset, 2);
2553 
2554  PG_RETURN_BOOL(result);
2555 }
int errcode(int sqlerrcode)
Definition: elog.c:610
#define PG_GETARG_BOOL(n)
Definition: fmgr.h:274
#define NUMERIC_IS_SPECIAL(n)
Definition: numeric.c:174
#define NUMERIC_NEG
Definition: numeric.c:168
#define ERROR
Definition: elog.h:43
#define NUMERIC_IS_PINF(n)
Definition: numeric.c:206
static void init_var_from_num(Numeric num, NumericVar *dest)
Definition: numeric.c:6951
#define NUMERIC_SIGN(n)
Definition: numeric.c:237
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:358
static int cmp_var(const NumericVar *var1, const NumericVar *var2)
Definition: numeric.c:7832
static void free_var(NumericVar *var)
Definition: numeric.c:6718
#define ereport(elevel,...)
Definition: elog.h:144
#define PG_GETARG_NUMERIC(n)
Definition: numeric.h:52
#define Assert(condition)
Definition: c.h:745
static void add_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition: numeric.c:7890
#define PG_FREE_IF_COPY(ptr, n)
Definition: fmgr.h:260
#define NUMERIC_IS_NINF(n)
Definition: numeric.c:207
int errmsg(const char *fmt,...)
Definition: elog.c:824
#define NUMERIC_IS_NAN(n)
Definition: numeric.c:205
static void sub_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition: numeric.c:8007
long val
Definition: informix.c:664
#define init_var(v)
Definition: numeric.c:495

◆ init_var_from_num()

static void init_var_from_num ( Numeric  num,
NumericVar dest 
)
static

Definition at line 6951 of file numeric.c.

References NumericVar::buf, NumericVar::digits, NumericVar::dscale, NumericVar::ndigits, NUMERIC_DIGITS, NUMERIC_DSCALE, NUMERIC_NDIGITS, NUMERIC_SIGN, NUMERIC_WEIGHT, NumericVar::sign, and NumericVar::weight.

Referenced by compute_bucket(), do_numeric_accum(), do_numeric_discard(), generate_series_step_numeric(), in_range_numeric_numeric(), int8_avg_deserialize(), numeric_abbrev_convert(), numeric_add_opt_error(), numeric_avg_deserialize(), numeric_ceil(), numeric_deserialize(), numeric_div_opt_error(), numeric_div_trunc(), numeric_exp(), numeric_float8_no_overflow(), numeric_floor(), numeric_gcd(), numeric_inc(), numeric_int2(), numeric_int4_opt_error(), numeric_int8(), numeric_is_integral(), numeric_lcm(), numeric_ln(), numeric_log(), numeric_min_scale(), numeric_mod_opt_error(), numeric_mul_opt_error(), numeric_normalize(), numeric_out(), numeric_out_sci(), numeric_pg_lsn(), numeric_poly_deserialize(), numeric_power(), numeric_send(), numeric_sqrt(), numeric_sub_opt_error(), and numeric_trim_scale().

6952 {
6953  dest->ndigits = NUMERIC_NDIGITS(num);
6954  dest->weight = NUMERIC_WEIGHT(num);
6955  dest->sign = NUMERIC_SIGN(num);
6956  dest->dscale = NUMERIC_DSCALE(num);
6957  dest->digits = NUMERIC_DIGITS(num);
6958  dest->buf = NULL; /* digits array is not palloc'd */
6959 }
#define NUMERIC_DSCALE(n)
Definition: numeric.c:243
int weight
Definition: numeric.c:307
int ndigits
Definition: numeric.c:306
int dscale
Definition: numeric.c:309
int sign
Definition: numeric.c:308
#define NUMERIC_DIGITS(num)
Definition: numeric.c:497
#define NUMERIC_SIGN(n)
Definition: numeric.c:237
NumericDigit * buf
Definition: numeric.c:310
#define NUMERIC_NDIGITS(num)
Definition: numeric.c:499
#define NUMERIC_WEIGHT(n)
Definition: numeric.c:247
NumericDigit * digits
Definition: numeric.c:311

◆ int2_accum()

Datum int2_accum ( PG_FUNCTION_ARGS  )

Definition at line 5264 of file numeric.c.

References do_numeric_accum(), int64_to_numeric(), makePolyNumAggState, PG_ARGISNULL, PG_GETARG_INT16, PG_GETARG_POINTER, and PG_RETURN_POINTER.

5265 {
5267 
5268  state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
5269 
5270  /* Create the state data on the first call */
5271  if (state == NULL)
5272  state = makePolyNumAggState(fcinfo, true);
5273 
5274  if (!PG_ARGISNULL(1))
5275  {
5276 #ifdef HAVE_INT128
5277  do_int128_accum(state, (int128) PG_GETARG_INT16(1));
5278 #else
5280 #endif
5281  }
5282 
5283  PG_RETURN_POINTER(state);
5284 }
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:360
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:276
static void do_numeric_accum(NumericAggState *state, Numeric newval)
Definition: numeric.c:4532
Numeric int64_to_numeric(int64 val)
Definition: numeric.c:4077
#define PG_GETARG_INT16(n)
Definition: fmgr.h:271
#define PG_ARGISNULL(n)
Definition: fmgr.h:209
Definition: regguts.h:298
#define makePolyNumAggState
Definition: numeric.c:5259

◆ int2_accum_inv()

Datum int2_accum_inv ( PG_FUNCTION_ARGS  )

Definition at line 5723 of file numeric.c.

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

5724 {
5726 
5727  state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
5728 
5729  /* Should not get here with no state */
5730  if (state == NULL)
5731  elog(ERROR, "int2_accum_inv called with NULL state");
5732 
5733  if (!PG_ARGISNULL(1))
5734  {
5735 #ifdef HAVE_INT128
5736  do_int128_discard(state, (int128) PG_GETARG_INT16(1));
5737 #else
5738  /* Should never fail, all inputs have dscale 0 */
5740  elog(ERROR, "do_numeric_discard failed unexpectedly");
5741 #endif
5742  }
5743 
5744  PG_RETURN_POINTER(state);
5745 }
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:360
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:276
static bool do_numeric_discard(NumericAggState *state, Numeric newval)
Definition: numeric.c:4602
#define ERROR
Definition: elog.h:43
Numeric int64_to_numeric(int64 val)
Definition: numeric.c:4077
#define PG_GETARG_INT16(n)
Definition: fmgr.h:271
#define PG_ARGISNULL(n)
Definition: fmgr.h:209
Definition: regguts.h:298
#define elog(elevel,...)
Definition: elog.h:214

◆ int2_avg_accum()

Datum int2_avg_accum ( PG_FUNCTION_ARGS  )

Definition at line 6406 of file numeric.c.

References AggCheckCallContext(), ARR_DATA_PTR, ARR_HASNULL, ARR_OVERHEAD_NONULLS, ARR_SIZE, Int8TransTypeData::count, elog, ERROR, newval, PG_GETARG_ARRAYTYPE_P, PG_GETARG_ARRAYTYPE_P_COPY, PG_GETARG_INT16, PG_RETURN_ARRAYTYPE_P, and Int8TransTypeData::sum.

6407 {
6408  ArrayType *transarray;
6410  Int8TransTypeData *transdata;
6411 
6412  /*
6413  * If we're invoked as an aggregate, we can cheat and modify our first
6414  * parameter in-place to reduce palloc overhead. Otherwise we need to make
6415  * a copy of it before scribbling on it.
6416  */
6417  if (AggCheckCallContext(fcinfo, NULL))
6418  transarray = PG_GETARG_ARRAYTYPE_P(0);
6419  else
6420  transarray = PG_GETARG_ARRAYTYPE_P_COPY(0);
6421 
6422  if (ARR_HASNULL(transarray) ||
6423  ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
6424  elog(ERROR, "expected 2-element int8 array");
6425 
6426  transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
6427  transdata->count++;
6428  transdata->sum += newval;
6429 
6430  PG_RETURN_ARRAYTYPE_P(transarray);
6431 }
signed short int16
Definition: c.h:361
#define ARR_OVERHEAD_NONULLS(ndims)
Definition: array.h:298
#define ARR_SIZE(a)
Definition: array.h:277
#define PG_GETARG_ARRAYTYPE_P_COPY(n)
Definition: array.h:252
#define PG_GETARG_ARRAYTYPE_P(n)
Definition: array.h:251
#define ERROR
Definition: elog.h:43
#define ARR_DATA_PTR(a)
Definition: array.h:310
#define ARR_HASNULL(a)
Definition: array.h:279
#define PG_RETURN_ARRAYTYPE_P(x)
Definition: array.h:253
#define PG_GETARG_INT16(n)
Definition: fmgr.h:271
#define newval
int AggCheckCallContext(FunctionCallInfo fcinfo, MemoryContext *aggcontext)
Definition: nodeAgg.c:4778
#define elog(elevel,...)
Definition: elog.h:214

◆ int2_avg_accum_inv()

Datum int2_avg_accum_inv ( PG_FUNCTION_ARGS  )

Definition at line 6493 of file numeric.c.

References AggCheckCallContext(), ARR_DATA_PTR, ARR_HASNULL, ARR_OVERHEAD_NONULLS, ARR_SIZE, Int8TransTypeData::count, elog, ERROR, newval, PG_GETARG_ARRAYTYPE_P, PG_GETARG_ARRAYTYPE_P_COPY, PG_GETARG_INT16, PG_RETURN_ARRAYTYPE_P, and Int8TransTypeData::sum.

6494 {
6495  ArrayType *transarray;
6497  Int8TransTypeData *transdata;
6498 
6499  /*
6500  * If we're invoked as an aggregate, we can cheat and modify our first
6501  * parameter in-place to reduce palloc overhead. Otherwise we need to make
6502  * a copy of it before scribbling on it.
6503  */
6504  if (AggCheckCallContext(fcinfo, NULL))
6505  transarray = PG_GETARG_ARRAYTYPE_P(0);
6506  else
6507  transarray = PG_GETARG_ARRAYTYPE_P_COPY(0);
6508 
6509  if (ARR_HASNULL(transarray) ||
6510  ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
6511  elog(ERROR, "expected 2-element int8 array");
6512 
6513  transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
6514  transdata->count--;
6515  transdata->sum -= newval;
6516 
6517  PG_RETURN_ARRAYTYPE_P(transarray);
6518 }
signed short int16
Definition: c.h:361
#define ARR_OVERHEAD_NONULLS(ndims)
Definition: array.h:298
#define ARR_SIZE(a)
Definition: array.h:277
#define PG_GETARG_ARRAYTYPE_P_COPY(n)
Definition: array.h:252
#define PG_GETARG_ARRAYTYPE_P(n)
Definition: array.h:251
#define ERROR
Definition: elog.h:43
#define ARR_DATA_PTR(a)
Definition: array.h:310
#define ARR_HASNULL(a)
Definition: array.h:279
#define PG_RETURN_ARRAYTYPE_P(x)
Definition: array.h:253
#define PG_GETARG_INT16(n)
Definition: fmgr.h:271
#define newval
int AggCheckCallContext(FunctionCallInfo fcinfo, MemoryContext *aggcontext)
Definition: nodeAgg.c:4778
#define elog(elevel,...)
Definition: elog.h:214

◆ int2_numeric()

Datum int2_numeric ( PG_FUNCTION_ARGS  )

Definition at line 4220 of file numeric.c.

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

4221 {
4222  int16 val = PG_GETARG_INT16(0);
4223 
4225 }
#define PG_RETURN_NUMERIC(x)
Definition: numeric.h:54
signed short int16
Definition: c.h:361
Numeric int64_to_numeric(int64 val)
Definition: numeric.c:4077
#define PG_GETARG_INT16(n)
Definition: fmgr.h:271
long val
Definition: informix.c:664

◆ int2_sum()

Datum int2_sum ( PG_FUNCTION_ARGS  )

Definition at line 6257 of file numeric.c.

References AggCheckCallContext(), newval, PG_ARGISNULL, PG_GETARG_INT16, PG_GETARG_INT64, PG_GETARG_POINTER, PG_RETURN_INT64, PG_RETURN_NULL, and PG_RETURN_POINTER.

6258 {
6259  int64 newval;
6260 
6261  if (PG_ARGISNULL(0))
6262  {
6263  /* No non-null input seen so far... */
6264  if (PG_ARGISNULL(1))
6265  PG_RETURN_NULL(); /* still no non-null */
6266  /* This is the first non-null input. */
6267  newval = (int64) PG_GETARG_INT16(1);
6268  PG_RETURN_INT64(newval);
6269  }
6270 
6271  /*
6272  * If we're invoked as an aggregate, we can cheat and modify our first
6273  * parameter in-place to avoid palloc overhead. If not, we need to return
6274  * the new value of the transition variable. (If int8 is pass-by-value,
6275  * then of course this is useless as well as incorrect, so just ifdef it
6276  * out.)
6277  */
6278 #ifndef USE_FLOAT8_BYVAL /* controls int8 too */
6279  if (AggCheckCallContext(fcinfo, NULL))
6280  {
6281  int64 *oldsum = (int64 *) PG_GETARG_POINTER(0);
6282 
6283  /* Leave the running sum unchanged in the new input is null */
6284  if (!PG_ARGISNULL(1))
6285  *oldsum = *oldsum + (int64) PG_GETARG_INT16(1);
6286 
6287  PG_RETURN_POINTER(oldsum);
6288  }
6289  else
6290 #endif
6291  {
6292  int64 oldsum = PG_GETARG_INT64(0);
6293 
6294  /* Leave sum unchanged if new input is null. */
6295  if (PG_ARGISNULL(1))
6296  PG_RETURN_INT64(oldsum);
6297 
6298  /* OK to do the addition. */
6299  newval = oldsum + (int64) PG_GETARG_INT16(1);
6300 
6301  PG_RETURN_INT64(newval);
6302  }
6303 }
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:360
#define PG_RETURN_INT64(x)
Definition: fmgr.h:366
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:276
#define PG_GETARG_INT16(n)
Definition: fmgr.h:271
#define PG_ARGISNULL(n)
Definition: fmgr.h:209
#define newval
int AggCheckCallContext(FunctionCallInfo fcinfo, MemoryContext *aggcontext)
Definition: nodeAgg.c:4778
#define PG_GETARG_INT64(n)
Definition: fmgr.h:282
#define PG_RETURN_NULL()
Definition: fmgr.h:344

◆ int2int4_sum()

Datum int2int4_sum ( PG_FUNCTION_ARGS  )

Definition at line 6576 of file numeric.c.

References ARR_DATA_PTR, ARR_HASNULL, ARR_OVERHEAD_NONULLS, ARR_SIZE, Int8TransTypeData::count, DEC_DIGITS, NumericVar::digits, digits, NumericVar::dscale, dump_numeric, dump_var, elog, ERROR, i, Int64GetDatumFast, NumericVar::ndigits, NUMERIC_DIGITS, NUMERIC_DSCALE, NUMERIC_NAN, NUMERIC_NDIGITS, NUMERIC_NEG, NUMERIC_NINF, NUMERIC_PINF, NUMERIC_POS, NUMERIC_SIGN, NUMERIC_WEIGHT, PG_GETARG_ARRAYTYPE_P, PG_RETURN_DATUM, PG_RETURN_NULL, printf, NumericVar::sign, generate_unaccent_rules::str, Int8TransTypeData::sum, and NumericVar::weight.

6577 {
6578  ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
6579  Int8TransTypeData *transdata;
6580 
6581  if (ARR_HASNULL(transarray) ||
6582  ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
6583  elog(ERROR, "expected 2-element int8 array");
6584  transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
6585 
6586  /* SQL defines SUM of no values to be NULL */
6587  if (transdata->count == 0)
6588  PG_RETURN_NULL();
6589 
6590  PG_RETURN_DATUM(Int64GetDatumFast(transdata->sum));
6591 }