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/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/hashutils.h"
#include "utils/int8.h"
#include "utils/numeric.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_NAN   0xC000
 
#define NUMERIC_FLAGBITS(n)   ((n)->choice.n_header & NUMERIC_SIGN_MASK)
 
#define NUMERIC_IS_NAN(n)   (NUMERIC_FLAGBITS(n) == NUMERIC_NAN)
 
#define NUMERIC_IS_SHORT(n)   (NUMERIC_FLAGBITS(n) == NUMERIC_SHORT)
 
#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_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 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)   MemSetAligned(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 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 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 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 double numeric_to_double_no_overflow (Numeric num)
 
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 ceil_var (const NumericVar *var, NumericVar *result)
 
static void floor_var (const NumericVar *var, 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)
 
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)
 
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_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)
 
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)
 
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 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_five_data [1] = {5000}
 
static const NumericVar const_zero_point_five
 
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 int round_powers [4] = {0, 1000, 100, 10}
 

Macro Definition Documentation

◆ DatumGetNumericAbbrev

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

Definition at line 364 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 446 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 448 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 100 of file numeric.c.

Referenced by div_var_fast().

◆ dump_numeric

#define dump_numeric (   s,
 
)

Definition at line 442 of file numeric.c.

Referenced by int2int4_sum(), and make_result_opt_error().

◆ dump_var

#define dump_var (   s,
 
)

Definition at line 443 of file numeric.c.

Referenced by int2int4_sum().

◆ HALF_NBASE

#define HALF_NBASE   5000

Definition at line 97 of file numeric.c.

Referenced by div_var(), and round_var().

◆ init_var

◆ makePolyNumAggState

#define makePolyNumAggState   makeNumericAggState

◆ makePolyNumAggStateCurrentContext

#define makePolyNumAggStateCurrentContext   makeNumericAggStateCurrentContext

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

Referenced by mul_var().

◆ NBASE

◆ NUMERIC_ABBREV_BITS

#define NUMERIC_ABBREV_BITS   (SIZEOF_DATUM * BITS_PER_BYTE)

Definition at line 357 of file numeric.c.

◆ NUMERIC_ABBREV_NAN

#define NUMERIC_ABBREV_NAN   NumericAbbrevGetDatum(PG_INT32_MIN)

Definition at line 365 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:200
int scale
Definition: pgbench.c:154
#define NUMERIC_SHORT_WEIGHT_MIN
Definition: numeric.c:201
#define NUMERIC_SHORT_DSCALE_MAX
Definition: numeric.c:196

Definition at line 460 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 456 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:207
#define NUMERIC_SHORT_DSCALE_MASK
Definition: numeric.c:194
#define NUMERIC_SHORT_DSCALE_SHIFT
Definition: numeric.c:195

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

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

◆ 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:346
#define NUMERIC_HEADER_IS_SHORT(n)
Definition: numeric.c:184
#define VARHDRSZ
Definition: c.h:562
unsigned short uint16
Definition: c.h:358

Definition at line 185 of file numeric.c.

◆ NUMERIC_IS_NAN

◆ NUMERIC_IS_SHORT

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

Definition at line 174 of file numeric.c.

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

◆ NUMERIC_NAN

#define NUMERIC_NAN   0xC000

◆ NUMERIC_NDIGITS

◆ NUMERIC_NEG

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

◆ NUMERIC_SHORT_DSCALE_SHIFT

#define NUMERIC_SHORT_DSCALE_SHIFT   7

Definition at line 195 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 193 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 199 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 200 of file numeric.c.

◆ NUMERIC_SHORT_WEIGHT_MIN

#define NUMERIC_SHORT_WEIGHT_MIN   (-(NUMERIC_SHORT_WEIGHT_MASK+1))

Definition at line 201 of file numeric.c.

◆ NUMERIC_SHORT_WEIGHT_SIGN_MASK

#define NUMERIC_SHORT_WEIGHT_SIGN_MASK   0x0040

Definition at line 198 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_FLAGBITS(n))
#define NUMERIC_POS
Definition: numeric.c:167
#define NUMERIC_FLAGBITS(n)
Definition: numeric.c:172
#define NUMERIC_SHORT_SIGN_MASK
Definition: numeric.c:193
#define NUMERIC_IS_SHORT(n)
Definition: numeric.c:174

Definition at line 209 of file numeric.c.

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

◆ NUMERIC_SIGN_MASK

#define NUMERIC_SIGN_MASK   0xC000

Definition at line 166 of file numeric.c.

◆ NUMERIC_WEIGHT

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

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

Referenced by numeric_cmp_abbrev().

Typedef Documentation

◆ Int8TransTypeData

◆ NumericAggState

◆ NumericDigit

Definition at line 102 of file numeric.c.

◆ NumericSumAccum

◆ NumericVar

typedef struct NumericVar NumericVar

◆ PolyNumAggState

Definition at line 4260 of file numeric.c.

Function Documentation

◆ accum_sum_add()

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

Definition at line 9176 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().

9177 {
9178  int32 *accum_digits;
9179  int i,
9180  val_i;
9181  int val_ndigits;
9182  NumericDigit *val_digits;
9183 
9184  /*
9185  * If we have accumulated too many values since the last carry
9186  * propagation, do it now, to avoid overflowing. (We could allow more
9187  * than NBASE - 1, if we reserved two extra digits, rather than one, for
9188  * carry propagation. But even with NBASE - 1, this needs to be done so
9189  * seldom, that the performance difference is negligible.)
9190  */
9191  if (accum->num_uncarried == NBASE - 1)
9192  accum_sum_carry(accum);
9193 
9194  /*
9195  * Adjust the weight or scale of the old value, so that it can accommodate
9196  * the new value.
9197  */
9198  accum_sum_rescale(accum, val);
9199 
9200  /* */
9201  if (val->sign == NUMERIC_POS)
9202  accum_digits = accum->pos_digits;
9203  else
9204  accum_digits = accum->neg_digits;
9205 
9206  /* copy these values into local vars for speed in loop */
9207  val_ndigits = val->ndigits;
9208  val_digits = val->digits;
9209 
9210  i = accum->weight - val->weight;
9211  for (val_i = 0; val_i < val_ndigits; val_i++)
9212  {
9213  accum_digits[i] += (int32) val_digits[val_i];
9214  i++;
9215  }
9216 
9217  accum->num_uncarried++;
9218 }
static void accum_sum_rescale(NumericSumAccum *accum, const NumericVar *val)
Definition: numeric.c:9297
#define NUMERIC_POS
Definition: numeric.c:167
int32 * neg_digits
Definition: numeric.c:347
int num_uncarried
Definition: numeric.c:344
static void accum_sum_carry(NumericSumAccum *accum)
Definition: numeric.c:9224
signed int int32
Definition: c.h:347
int16 NumericDigit
Definition: numeric.c:102
#define NBASE
Definition: numeric.c:96
int i
int32 * pos_digits
Definition: numeric.c:346
long val
Definition: informix.c:664

◆ accum_sum_carry()

static void accum_sum_carry ( NumericSumAccum accum)
static

Definition at line 9224 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().

9225 {
9226  int i;
9227  int ndigits;
9228  int32 *dig;
9229  int32 carry;
9230  int32 newdig = 0;
9231 
9232  /*
9233  * If no new values have been added since last carry propagation, nothing
9234  * to do.
9235  */
9236  if (accum->num_uncarried == 0)
9237  return;
9238 
9239  /*
9240  * We maintain that the weight of the accumulator is always one larger
9241  * than needed to hold the current value, before carrying, to make sure
9242  * there is enough space for the possible extra digit when carry is
9243  * propagated. We cannot expand the buffer here, unless we require
9244  * callers of accum_sum_final() to switch to the right memory context.
9245  */
9246  Assert(accum->pos_digits[0] == 0 && accum->neg_digits[0] == 0);
9247 
9248  ndigits = accum->ndigits;
9249 
9250  /* Propagate carry in the positive sum */
9251  dig = accum->pos_digits;
9252  carry = 0;
9253  for (i = ndigits - 1; i >= 0; i--)
9254  {
9255  newdig = dig[i] + carry;
9256  if (newdig >= NBASE)
9257  {
9258  carry = newdig / NBASE;
9259  newdig -= carry * NBASE;
9260  }
9261  else
9262  carry = 0;
9263  dig[i] = newdig;
9264  }
9265  /* Did we use up the digit reserved for carry propagation? */
9266  if (newdig > 0)
9267  accum->have_carry_space = false;
9268 
9269  /* And the same for the negative sum */
9270  dig = accum->neg_digits;
9271  carry = 0;
9272  for (i = ndigits - 1; i >= 0; i--)
9273  {
9274  newdig = dig[i] + carry;
9275  if (newdig >= NBASE)
9276  {
9277  carry = newdig / NBASE;
9278  newdig -= carry * NBASE;
9279  }
9280  else
9281  carry = 0;
9282  dig[i] = newdig;
9283  }
9284  if (newdig > 0)
9285  accum->have_carry_space = false;
9286 
9287  accum->num_uncarried = 0;
9288 }
int32 * neg_digits
Definition: numeric.c:347
int num_uncarried
Definition: numeric.c:344
signed int int32
Definition: c.h:347
bool have_carry_space
Definition: numeric.c:345
#define NBASE
Definition: numeric.c:96
#define Assert(condition)
Definition: c.h:739
int i
int32 * pos_digits
Definition: numeric.c:346

◆ accum_sum_combine()

static void accum_sum_combine ( NumericSumAccum accum,
NumericSumAccum accum2 
)
static

Definition at line 9454 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().

9455 {
9456  NumericVar tmp_var;
9457 
9458  init_var(&tmp_var);
9459 
9460  accum_sum_final(accum2, &tmp_var);
9461  accum_sum_add(accum, &tmp_var);
9462 
9463  free_var(&tmp_var);
9464 }
static void accum_sum_final(NumericSumAccum *accum, NumericVar *result)
Definition: numeric.c:9386
static void accum_sum_add(NumericSumAccum *accum, const NumericVar *var1)
Definition: numeric.c:9176
static void free_var(NumericVar *var)
Definition: numeric.c:5735
#define init_var(v)
Definition: numeric.c:454

◆ accum_sum_copy()

static void accum_sum_copy ( NumericSumAccum dst,
NumericSumAccum src 
)
static

Definition at line 9437 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().

9438 {
9439  dst->pos_digits = palloc(src->ndigits * sizeof(int32));
9440  dst->neg_digits = palloc(src->ndigits * sizeof(int32));
9441 
9442  memcpy(dst->pos_digits, src->pos_digits, src->ndigits * sizeof(int32));
9443  memcpy(dst->neg_digits, src->neg_digits, src->ndigits * sizeof(int32));
9444  dst->num_uncarried = src->num_uncarried;
9445  dst->ndigits = src->ndigits;
9446  dst->weight = src->weight;
9447  dst->dscale = src->dscale;
9448 }
int32 * neg_digits
Definition: numeric.c:347
int num_uncarried
Definition: numeric.c:344
signed int int32
Definition: c.h:347
void * palloc(Size size)
Definition: mcxt.c:949
int32 * pos_digits
Definition: numeric.c:346

◆ accum_sum_final()

static void accum_sum_final ( NumericSumAccum accum,
NumericVar result 
)
static

Definition at line 9386 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().

9387 {
9388  int i;
9389  NumericVar pos_var;
9390  NumericVar neg_var;
9391 
9392  if (accum->ndigits == 0)
9393  {
9394  set_var_from_var(&const_zero, result);
9395  return;
9396  }
9397 
9398  /* Perform final carry */
9399  accum_sum_carry(accum);
9400 
9401  /* Create NumericVars representing the positive and negative sums */
9402  init_var(&pos_var);
9403  init_var(&neg_var);
9404 
9405  pos_var.ndigits = neg_var.ndigits = accum->ndigits;
9406  pos_var.weight = neg_var.weight = accum->weight;
9407  pos_var.dscale = neg_var.dscale = accum->dscale;
9408  pos_var.sign = NUMERIC_POS;
9409  neg_var.sign = NUMERIC_NEG;
9410 
9411  pos_var.buf = pos_var.digits = digitbuf_alloc(accum->ndigits);
9412  neg_var.buf = neg_var.digits = digitbuf_alloc(accum->ndigits);
9413 
9414  for (i = 0; i < accum->ndigits; i++)
9415  {
9416  Assert(accum->pos_digits[i] < NBASE);
9417  pos_var.digits[i] = (int16) accum->pos_digits[i];
9418 
9419  Assert(accum->neg_digits[i] < NBASE);
9420  neg_var.digits[i] = (int16) accum->neg_digits[i];
9421  }
9422 
9423  /* And add them together */
9424  add_var(&pos_var, &neg_var, result);
9425 
9426  /* Remove leading/trailing zeroes */
9427  strip_var(result);
9428 }
signed short int16
Definition: c.h:346
int weight
Definition: numeric.c:275
#define NUMERIC_POS
Definition: numeric.c:167
static void strip_var(NumericVar *var)
Definition: numeric.c:9119
int32 * neg_digits
Definition: numeric.c:347
#define digitbuf_alloc(ndigits)
Definition: numeric.c:446
int ndigits
Definition: numeric.c:274
static void accum_sum_carry(NumericSumAccum *accum)
Definition: numeric.c:9224
int dscale
Definition: numeric.c:277
#define NUMERIC_NEG
Definition: numeric.c:168
int sign
Definition: numeric.c:276
NumericDigit * buf
Definition: numeric.c:278
#define NBASE
Definition: numeric.c:96
static const NumericVar const_zero
Definition: numeric.c:374
#define Assert(condition)
Definition: c.h:739
NumericDigit * digits
Definition: numeric.c:279
static void add_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition: numeric.c:6797
int i
static void set_var_from_var(const NumericVar *value, NumericVar *dest)
Definition: numeric.c:5985
int32 * pos_digits
Definition: numeric.c:346
#define init_var(v)
Definition: numeric.c:454

◆ accum_sum_rescale()

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

Definition at line 9297 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().

9298 {
9299  int old_weight = accum->weight;
9300  int old_ndigits = accum->ndigits;
9301  int accum_ndigits;
9302  int accum_weight;
9303  int accum_rscale;
9304  int val_rscale;
9305 
9306  accum_weight = old_weight;
9307  accum_ndigits = old_ndigits;
9308 
9309  /*
9310  * Does the new value have a larger weight? If so, enlarge the buffers,
9311  * and shift the existing value to the new weight, by adding leading
9312  * zeros.
9313  *
9314  * We enforce that the accumulator always has a weight one larger than
9315  * needed for the inputs, so that we have space for an extra digit at the
9316  * final carry-propagation phase, if necessary.
9317  */
9318  if (val->weight >= accum_weight)
9319  {
9320  accum_weight = val->weight + 1;
9321  accum_ndigits = accum_ndigits + (accum_weight - old_weight);
9322  }
9323 
9324  /*
9325  * Even though the new value is small, we might've used up the space
9326  * reserved for the carry digit in the last call to accum_sum_carry(). If
9327  * so, enlarge to make room for another one.
9328  */
9329  else if (!accum->have_carry_space)
9330  {
9331  accum_weight++;
9332  accum_ndigits++;
9333  }
9334 
9335  /* Is the new value wider on the right side? */
9336  accum_rscale = accum_ndigits - accum_weight - 1;
9337  val_rscale = val->ndigits - val->weight - 1;
9338  if (val_rscale > accum_rscale)
9339  accum_ndigits = accum_ndigits + (val_rscale - accum_rscale);
9340 
9341  if (accum_ndigits != old_ndigits ||
9342  accum_weight != old_weight)
9343  {
9344  int32 *new_pos_digits;
9345  int32 *new_neg_digits;
9346  int weightdiff;
9347 
9348  weightdiff = accum_weight - old_weight;
9349 
9350  new_pos_digits = palloc0(accum_ndigits * sizeof(int32));
9351  new_neg_digits = palloc0(accum_ndigits * sizeof(int32));
9352 
9353  if (accum->pos_digits)
9354  {
9355  memcpy(&new_pos_digits[weightdiff], accum->pos_digits,
9356  old_ndigits * sizeof(int32));
9357  pfree(accum->pos_digits);
9358 
9359  memcpy(&new_neg_digits[weightdiff], accum->neg_digits,
9360  old_ndigits * sizeof(int32));
9361  pfree(accum->neg_digits);
9362  }
9363 
9364  accum->pos_digits = new_pos_digits;
9365  accum->neg_digits = new_neg_digits;
9366 
9367  accum->weight = accum_weight;
9368  accum->ndigits = accum_ndigits;
9369 
9370  Assert(accum->pos_digits[0] == 0 && accum->neg_digits[0] == 0);
9371  accum->have_carry_space = true;
9372  }
9373 
9374  if (val->dscale > accum->dscale)
9375  accum->dscale = val->dscale;
9376 }
int weight
Definition: numeric.c:275
int32 * neg_digits
Definition: numeric.c:347
int ndigits
Definition: numeric.c:274
int dscale
Definition: numeric.c:277
signed int int32
Definition: c.h:347
void pfree(void *pointer)
Definition: mcxt.c:1056
bool have_carry_space
Definition: numeric.c:345
void * palloc0(Size size)
Definition: mcxt.c:980
#define Assert(condition)
Definition: c.h:739
int32 * pos_digits
Definition: numeric.c:346

◆ accum_sum_reset()

static void accum_sum_reset ( NumericSumAccum accum)
static

Definition at line 9160 of file numeric.c.

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

Referenced by do_numeric_discard().

9161 {
9162  int i;
9163 
9164  accum->dscale = 0;
9165  for (i = 0; i < accum->ndigits; i++)
9166  {
9167  accum->pos_digits[i] = 0;
9168  accum->neg_digits[i] = 0;
9169  }
9170 }
int32 * neg_digits
Definition: numeric.c:347
int i
int32 * pos_digits
Definition: numeric.c:346

◆ add_abs()

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

Definition at line 8784 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().

8785 {
8786  NumericDigit *res_buf;
8787  NumericDigit *res_digits;
8788  int res_ndigits;
8789  int res_weight;
8790  int res_rscale,
8791  rscale1,
8792  rscale2;
8793  int res_dscale;
8794  int i,
8795  i1,
8796  i2;
8797  int carry = 0;
8798 
8799  /* copy these values into local vars for speed in inner loop */
8800  int var1ndigits = var1->ndigits;
8801  int var2ndigits = var2->ndigits;
8802  NumericDigit *var1digits = var1->digits;
8803  NumericDigit *var2digits = var2->digits;
8804 
8805  res_weight = Max(var1->weight, var2->weight) + 1;
8806 
8807  res_dscale = Max(var1->dscale, var2->dscale);
8808 
8809  /* Note: here we are figuring rscale in base-NBASE digits */
8810  rscale1 = var1->ndigits - var1->weight - 1;
8811  rscale2 = var2->ndigits - var2->weight - 1;
8812  res_rscale = Max(rscale1, rscale2);
8813 
8814  res_ndigits = res_rscale + res_weight + 1;
8815  if (res_ndigits <= 0)
8816  res_ndigits = 1;
8817 
8818  res_buf = digitbuf_alloc(res_ndigits + 1);
8819  res_buf[0] = 0; /* spare digit for later rounding */
8820  res_digits = res_buf + 1;
8821 
8822  i1 = res_rscale + var1->weight + 1;
8823  i2 = res_rscale + var2->weight + 1;
8824  for (i = res_ndigits - 1; i >= 0; i--)
8825  {
8826  i1--;
8827  i2--;
8828  if (i1 >= 0 && i1 < var1ndigits)
8829  carry += var1digits[i1];
8830  if (i2 >= 0 && i2 < var2ndigits)
8831  carry += var2digits[i2];
8832 
8833  if (carry >= NBASE)
8834  {
8835  res_digits[i] = carry - NBASE;
8836  carry = 1;
8837  }
8838  else
8839  {
8840  res_digits[i] = carry;
8841  carry = 0;
8842  }
8843  }
8844 
8845  Assert(carry == 0); /* else we failed to allow for carry out */
8846 
8847  digitbuf_free(result->buf);
8848  result->ndigits = res_ndigits;
8849  result->buf = res_buf;
8850  result->digits = res_digits;
8851  result->weight = res_weight;
8852  result->dscale = res_dscale;
8853 
8854  /* Remove leading/trailing zeroes */
8855  strip_var(result);
8856 }
int weight
Definition: numeric.c:275
static void strip_var(NumericVar *var)
Definition: numeric.c:9119
#define digitbuf_alloc(ndigits)
Definition: numeric.c:446
int ndigits
Definition: numeric.c:274
int dscale
Definition: numeric.c:277
#define digitbuf_free(buf)
Definition: numeric.c:448
int16 NumericDigit
Definition: numeric.c:102
NumericDigit * buf
Definition: numeric.c:278
#define NBASE
Definition: numeric.c:96
#define Assert(condition)
Definition: c.h:739
NumericDigit * digits
Definition: numeric.c:279
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 6797 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(), exp_var(), generate_series_step_numeric(), in_range_numeric_numeric(), ln_var(), numeric_add_opt_error(), numeric_inc(), sqrt_var(), and width_bucket_numeric().

6798 {
6799  /*
6800  * Decide on the signs of the two variables what to do
6801  */
6802  if (var1->sign == NUMERIC_POS)
6803  {
6804  if (var2->sign == NUMERIC_POS)
6805  {
6806  /*
6807  * Both are positive result = +(ABS(var1) + ABS(var2))
6808  */
6809  add_abs(var1, var2, result);
6810  result->sign = NUMERIC_POS;
6811  }
6812  else
6813  {
6814  /*
6815  * var1 is positive, var2 is negative Must compare absolute values
6816  */
6817  switch (cmp_abs(var1, var2))
6818  {
6819  case 0:
6820  /* ----------
6821  * ABS(var1) == ABS(var2)
6822  * result = ZERO
6823  * ----------
6824  */
6825  zero_var(result);
6826  result->dscale = Max(var1->dscale, var2->dscale);
6827  break;
6828 
6829  case 1:
6830  /* ----------
6831  * ABS(var1) > ABS(var2)
6832  * result = +(ABS(var1) - ABS(var2))
6833  * ----------
6834  */
6835  sub_abs(var1, var2, result);
6836  result->sign = NUMERIC_POS;
6837  break;
6838 
6839  case -1:
6840  /* ----------
6841  * ABS(var1) < ABS(var2)
6842  * result = -(ABS(var2) - ABS(var1))
6843  * ----------
6844  */
6845  sub_abs(var2, var1, result);
6846  result->sign = NUMERIC_NEG;
6847  break;
6848  }
6849  }
6850  }
6851  else
6852  {
6853  if (var2->sign == NUMERIC_POS)
6854  {
6855  /* ----------
6856  * var1 is negative, var2 is positive
6857  * Must compare absolute values
6858  * ----------
6859  */
6860  switch (cmp_abs(var1, var2))
6861  {
6862  case 0:
6863  /* ----------
6864  * ABS(var1) == ABS(var2)
6865  * result = ZERO
6866  * ----------
6867  */
6868  zero_var(result);
6869  result->dscale = Max(var1->dscale, var2->dscale);
6870  break;
6871 
6872  case 1:
6873  /* ----------
6874  * ABS(var1) > ABS(var2)
6875  * result = -(ABS(var1) - ABS(var2))
6876  * ----------
6877  */
6878  sub_abs(var1, var2, result);
6879  result->sign = NUMERIC_NEG;
6880  break;
6881 
6882  case -1:
6883  /* ----------
6884  * ABS(var1) < ABS(var2)
6885  * result = +(ABS(var2) - ABS(var1))
6886  * ----------
6887  */
6888  sub_abs(var2, var1, result);
6889  result->sign = NUMERIC_POS;
6890  break;
6891  }
6892  }
6893  else
6894  {
6895  /* ----------
6896  * Both are negative
6897  * result = -(ABS(var1) + ABS(var2))
6898  * ----------
6899  */
6900  add_abs(var1, var2, result);
6901  result->sign = NUMERIC_NEG;
6902  }
6903  }
6904 }
static void sub_abs(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition: numeric.c:8869
static void add_abs(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition: numeric.c:8784
#define NUMERIC_POS
Definition: numeric.c:167
int dscale
Definition: numeric.c:277
#define NUMERIC_NEG
Definition: numeric.c:168
int sign
Definition: numeric.c:276
static void zero_var(NumericVar *var)
Definition: numeric.c:5751
static int cmp_abs(const NumericVar *var1, const NumericVar *var2)
Definition: numeric.c:8706
#define Max(x, y)
Definition: numeric.c:13

◆ alloc_var()

static void alloc_var ( NumericVar var,
int  ndigits 
)
static

Definition at line 5719 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(), set_var_from_num(), set_var_from_str(), and sqrt_var().

5720 {
5721  digitbuf_free(var->buf);
5722  var->buf = digitbuf_alloc(ndigits + 1);
5723  var->buf[0] = 0; /* spare digit for rounding */
5724  var->digits = var->buf + 1;
5725  var->ndigits = ndigits;
5726 }
#define digitbuf_alloc(ndigits)
Definition: numeric.c:446
int ndigits
Definition: numeric.c:274
#define digitbuf_free(buf)
Definition: numeric.c:448
NumericDigit * buf
Definition: numeric.c:278
NumericDigit * digits
Definition: numeric.c:279

◆ apply_typmod()

static void apply_typmod ( NumericVar var,
int32  typmod 
)
static

Definition at line 6364 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().

6365 {
6366  int precision;
6367  int scale;
6368  int maxdigits;
6369  int ddigits;
6370  int i;
6371 
6372  /* Do nothing if we have a default typmod (-1) */
6373  if (typmod < (int32) (VARHDRSZ))
6374  return;
6375 
6376  typmod -= VARHDRSZ;
6377  precision = (typmod >> 16) & 0xffff;
6378  scale = typmod & 0xffff;
6379  maxdigits = precision - scale;
6380 
6381  /* Round to target scale (and set var->dscale) */
6382  round_var(var, scale);
6383 
6384  /*
6385  * Check for overflow - note we can't do this before rounding, because
6386  * rounding could raise the weight. Also note that the var's weight could
6387  * be inflated by leading zeroes, which will be stripped before storage
6388  * but perhaps might not have been yet. In any case, we must recognize a
6389  * true zero, whose weight doesn't mean anything.
6390  */
6391  ddigits = (var->weight + 1) * DEC_DIGITS;
6392  if (ddigits > maxdigits)
6393  {
6394  /* Determine true weight; and check for all-zero result */
6395  for (i = 0; i < var->ndigits; i++)
6396  {
6397  NumericDigit dig = var->digits[i];
6398 
6399  if (dig)
6400  {
6401  /* Adjust for any high-order decimal zero digits */
6402 #if DEC_DIGITS == 4
6403  if (dig < 10)
6404  ddigits -= 3;
6405  else if (dig < 100)
6406  ddigits -= 2;
6407  else if (dig < 1000)
6408  ddigits -= 1;
6409 #elif DEC_DIGITS == 2
6410  if (dig < 10)
6411  ddigits -= 1;
6412 #elif DEC_DIGITS == 1
6413  /* no adjustment */
6414 #else
6415 #error unsupported NBASE
6416 #endif
6417  if (ddigits > maxdigits)
6418  ereport(ERROR,
6419  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
6420  errmsg("numeric field overflow"),
6421  errdetail("A field with precision %d, scale %d must round to an absolute value less than %s%d.",
6422  precision, scale,
6423  /* Display 10^0 as 1 */
6424  maxdigits ? "10^" : "",
6425  maxdigits ? maxdigits : 1
6426  )));
6427  break;
6428  }
6429  ddigits -= DEC_DIGITS;
6430  }
6431  }
6432 }
static void round_var(NumericVar *var, int rscale)
Definition: numeric.c:8951
int weight
Definition: numeric.c:275
#define VARHDRSZ
Definition: c.h:562
int errcode(int sqlerrcode)
Definition: elog.c:608
int scale
Definition: pgbench.c:154
int ndigits
Definition: numeric.c:274
signed int int32
Definition: c.h:347
#define ERROR
Definition: elog.h:43
int16 NumericDigit
Definition: numeric.c:102
int errdetail(const char *fmt,...)
Definition: elog.c:955
#define ereport(elevel, rest)
Definition: elog.h:141
int maxdigits
Definition: informix.c:665
NumericDigit * digits
Definition: numeric.c:279
int errmsg(const char *fmt,...)
Definition: elog.c:822
int i
#define DEC_DIGITS
Definition: numeric.c:98

◆ ceil_var()

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

Definition at line 7910 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().

7911 {
7912  NumericVar tmp;
7913 
7914  init_var(&tmp);
7915  set_var_from_var(var, &tmp);
7916 
7917  trunc_var(&tmp, 0);
7918 
7919  if (var->sign == NUMERIC_POS && cmp_var(var, &tmp) != 0)
7920  add_var(&tmp, &const_one, &tmp);
7921 
7922  set_var_from_var(&tmp, result);
7923  free_var(&tmp);
7924 }
static void trunc_var(NumericVar *var, int rscale)
Definition: numeric.c:9057
static const NumericVar const_one
Definition: numeric.c:378
#define NUMERIC_POS
Definition: numeric.c:167
int sign
Definition: numeric.c:276
static int cmp_var(const NumericVar *var1, const NumericVar *var2)
Definition: numeric.c:6739
static void free_var(NumericVar *var)
Definition: numeric.c:5735
static void add_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition: numeric.c:6797
static void set_var_from_var(const NumericVar *value, NumericVar *dest)
Definition: numeric.c:5985
#define init_var(v)
Definition: numeric.c:454

◆ cmp_abs()

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

Definition at line 8706 of file numeric.c.

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

Referenced by add_var(), and sub_var().

8707 {
8708  return cmp_abs_common(var1->digits, var1->ndigits, var1->weight,
8709  var2->digits, var2->ndigits, var2->weight);
8710 }
int weight
Definition: numeric.c:275
int ndigits
Definition: numeric.c:274
NumericDigit * digits
Definition: numeric.c:279
static int cmp_abs_common(const NumericDigit *var1digits, int var1ndigits, int var1weight, const NumericDigit *var2digits, int var2ndigits, int var2weight)
Definition: numeric.c:8720

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

References stat.

Referenced by cmp_abs(), and cmp_var_common().

8722 {
8723  int i1 = 0;
8724  int i2 = 0;
8725 
8726  /* Check any digits before the first common digit */
8727 
8728  while (var1weight > var2weight && i1 < var1ndigits)
8729  {
8730  if (var1digits[i1++] != 0)
8731  return 1;
8732  var1weight--;
8733  }
8734  while (var2weight > var1weight && i2 < var2ndigits)
8735  {
8736  if (var2digits[i2++] != 0)
8737  return -1;
8738  var2weight--;
8739  }
8740 
8741  /* At this point, either w1 == w2 or we've run out of digits */
8742 
8743  if (var1weight == var2weight)
8744  {
8745  while (i1 < var1ndigits && i2 < var2ndigits)
8746  {
8747  int stat = var1digits[i1++] - var2digits[i2++];
8748 
8749  if (stat)
8750  {
8751  if (stat > 0)
8752  return 1;
8753  return -1;
8754  }
8755  }
8756  }
8757 
8758  /*
8759  * At this point, we've run out of digits on one side or the other; so any
8760  * remaining nonzero digits imply that side is larger
8761  */
8762  while (i1 < var1ndigits)
8763  {
8764  if (var1digits[i1++] != 0)
8765  return 1;
8766  }
8767  while (i2 < var2ndigits)
8768  {
8769  if (var2digits[i2++] != 0)
8770  return -1;
8771  }
8772 
8773  return 0;
8774 }
#define stat(a, b)
Definition: win32_port.h:255

◆ cmp_numerics()

static int cmp_numerics ( Numeric  num1,
Numeric  num2 
)
static

Definition at line 2152 of file numeric.c.

References cmp_var_common(), NUMERIC_DIGITS, NUMERIC_IS_NAN, 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().

2153 {
2154  int result;
2155 
2156  /*
2157  * We consider all NANs to be equal and larger than any non-NAN. This is
2158  * somewhat arbitrary; the important thing is to have a consistent sort
2159  * order.
2160  */
2161  if (NUMERIC_IS_NAN(num1))
2162  {
2163  if (NUMERIC_IS_NAN(num2))
2164  result = 0; /* NAN = NAN */
2165  else
2166  result = 1; /* NAN > non-NAN */
2167  }
2168  else if (NUMERIC_IS_NAN(num2))
2169  {
2170  result = -1; /* non-NAN < NAN */
2171  }
2172  else
2173  {
2174  result = cmp_var_common(NUMERIC_DIGITS(num1), NUMERIC_NDIGITS(num1),
2175  NUMERIC_WEIGHT(num1), NUMERIC_SIGN(num1),
2176  NUMERIC_DIGITS(num2), NUMERIC_NDIGITS(num2),
2177  NUMERIC_WEIGHT(num2), NUMERIC_SIGN(num2));
2178  }
2179 
2180  return result;
2181 }
#define NUMERIC_DIGITS(num)
Definition: numeric.c:456
#define NUMERIC_SIGN(n)
Definition: numeric.c:209
#define NUMERIC_NDIGITS(num)
Definition: numeric.c:458
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:6754
#define NUMERIC_WEIGHT(n)
Definition: numeric.c:217
#define NUMERIC_IS_NAN(n)
Definition: numeric.c:173

◆ cmp_var()

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

Definition at line 6739 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().

6740 {
6741  return cmp_var_common(var1->digits, var1->ndigits,
6742  var1->weight, var1->sign,
6743  var2->digits, var2->ndigits,
6744  var2->weight, var2->sign);
6745 }
int weight
Definition: numeric.c:275
int ndigits
Definition: numeric.c:274
int sign
Definition: numeric.c:276
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:6754
NumericDigit * digits
Definition: numeric.c:279

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

References cmp_abs_common(), NUMERIC_NEG, and NUMERIC_POS.

Referenced by cmp_numerics(), and cmp_var().

6758 {
6759  if (var1ndigits == 0)
6760  {
6761  if (var2ndigits == 0)
6762  return 0;
6763  if (var2sign == NUMERIC_NEG)
6764  return 1;
6765  return -1;
6766  }
6767  if (var2ndigits == 0)
6768  {
6769  if (var1sign == NUMERIC_POS)
6770  return 1;
6771  return -1;
6772  }
6773 
6774  if (var1sign == NUMERIC_POS)
6775  {
6776  if (var2sign == NUMERIC_NEG)
6777  return 1;
6778  return cmp_abs_common(var1digits, var1ndigits, var1weight,
6779  var2digits, var2ndigits, var2weight);
6780  }
6781 
6782  if (var2sign == NUMERIC_POS)
6783  return -1;
6784 
6785  return cmp_abs_common(var2digits, var2ndigits, var2weight,
6786  var1digits, var1ndigits, var1weight);
6787 }
#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:8720

◆ compute_bucket()

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

Definition at line 1579 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().

1581 {
1582  NumericVar bound1_var;
1583  NumericVar bound2_var;
1584  NumericVar operand_var;
1585 
1586  init_var_from_num(bound1, &bound1_var);
1587  init_var_from_num(bound2, &bound2_var);
1588  init_var_from_num(operand, &operand_var);
1589 
1590  if (cmp_var(&bound1_var, &bound2_var) < 0)
1591  {
1592  sub_var(&operand_var, &bound1_var, &operand_var);
1593  sub_var(&bound2_var, &bound1_var, &bound2_var);
1594  div_var(&operand_var, &bound2_var, result_var,
1595  select_div_scale(&operand_var, &bound2_var), true);
1596  }
1597  else
1598  {
1599  sub_var(&bound1_var, &operand_var, &operand_var);
1600  sub_var(&bound1_var, &bound2_var, &bound1_var);
1601  div_var(&operand_var, &bound1_var, result_var,
1602  select_div_scale(&operand_var, &bound1_var), true);
1603  }
1604 
1605  mul_var(result_var, count_var, result_var,
1606  result_var->dscale + count_var->dscale);
1607  add_var(result_var, &const_one, result_var);
1608  floor_var(result_var, result_var);
1609 
1610  free_var(&bound1_var);
1611  free_var(&bound2_var);
1612  free_var(&operand_var);
1613 }
static const NumericVar const_one
Definition: numeric.c:378
static void div_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result, int rscale, bool round)
Definition: numeric.c:7232
int dscale
Definition: numeric.c:277
static int select_div_scale(const NumericVar *var1, const NumericVar *var2)
Definition: numeric.c:7812
static void init_var_from_num(Numeric num, NumericVar *dest)
Definition: numeric.c:5968
static int cmp_var(const NumericVar *var1, const NumericVar *var2)
Definition: numeric.c:6739
static void free_var(NumericVar *var)
Definition: numeric.c:5735
static void mul_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result, int rscale)
Definition: numeric.c:7035
static void add_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition: numeric.c:6797
static void sub_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition: numeric.c:6914
static void floor_var(const NumericVar *var, NumericVar *result)
Definition: numeric.c:7934

◆ div_var()

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

Definition at line 7232 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_stddev_internal(), and power_var_int().

7234 {
7235  int div_ndigits;
7236  int res_ndigits;
7237  int res_sign;
7238  int res_weight;
7239  int carry;
7240  int borrow;
7241  int divisor1;
7242  int divisor2;
7243  NumericDigit *dividend;
7244  NumericDigit *divisor;
7245  NumericDigit *res_digits;
7246  int i;
7247  int j;
7248 
7249  /* copy these values into local vars for speed in inner loop */
7250  int var1ndigits = var1->ndigits;
7251  int var2ndigits = var2->ndigits;
7252 
7253  /*
7254  * First of all division by zero check; we must not be handed an
7255  * unnormalized divisor.
7256  */
7257  if (var2ndigits == 0 || var2->digits[0] == 0)
7258  ereport(ERROR,
7259  (errcode(ERRCODE_DIVISION_BY_ZERO),
7260  errmsg("division by zero")));
7261 
7262  /*
7263  * Now result zero check
7264  */
7265  if (var1ndigits == 0)
7266  {
7267  zero_var(result);
7268  result->dscale = rscale;
7269  return;
7270  }
7271 
7272  /*
7273  * Determine the result sign, weight and number of digits to calculate.
7274  * The weight figured here is correct if the emitted quotient has no
7275  * leading zero digits; otherwise strip_var() will fix things up.
7276  */
7277  if (var1->sign == var2->sign)
7278  res_sign = NUMERIC_POS;
7279  else
7280  res_sign = NUMERIC_NEG;
7281  res_weight = var1->weight - var2->weight;
7282  /* The number of accurate result digits we need to produce: */
7283  res_ndigits = res_weight + 1 + (rscale + DEC_DIGITS - 1) / DEC_DIGITS;
7284  /* ... but always at least 1 */
7285  res_ndigits = Max(res_ndigits, 1);
7286  /* If rounding needed, figure one more digit to ensure correct result */
7287  if (round)
7288  res_ndigits++;
7289 
7290  /*
7291  * The working dividend normally requires res_ndigits + var2ndigits
7292  * digits, but make it at least var1ndigits so we can load all of var1
7293  * into it. (There will be an additional digit dividend[0] in the
7294  * dividend space, but for consistency with Knuth's notation we don't
7295  * count that in div_ndigits.)
7296  */
7297  div_ndigits = res_ndigits + var2ndigits;
7298  div_ndigits = Max(div_ndigits, var1ndigits);
7299 
7300  /*
7301  * We need a workspace with room for the working dividend (div_ndigits+1
7302  * digits) plus room for the possibly-normalized divisor (var2ndigits
7303  * digits). It is convenient also to have a zero at divisor[0] with the
7304  * actual divisor data in divisor[1 .. var2ndigits]. Transferring the
7305  * digits into the workspace also allows us to realloc the result (which
7306  * might be the same as either input var) before we begin the main loop.
7307  * Note that we use palloc0 to ensure that divisor[0], dividend[0], and
7308  * any additional dividend positions beyond var1ndigits, start out 0.
7309  */
7310  dividend = (NumericDigit *)
7311  palloc0((div_ndigits + var2ndigits + 2) * sizeof(NumericDigit));
7312  divisor = dividend + (div_ndigits + 1);
7313  memcpy(dividend + 1, var1->digits, var1ndigits * sizeof(NumericDigit));
7314  memcpy(divisor + 1, var2->digits, var2ndigits * sizeof(NumericDigit));
7315 
7316  /*
7317  * Now we can realloc the result to hold the generated quotient digits.
7318  */
7319  alloc_var(result, res_ndigits);
7320  res_digits = result->digits;
7321 
7322  if (var2ndigits == 1)
7323  {
7324  /*
7325  * If there's only a single divisor digit, we can use a fast path (cf.
7326  * Knuth section 4.3.1 exercise 16).
7327  */
7328  divisor1 = divisor[1];
7329  carry = 0;
7330  for (i = 0; i < res_ndigits; i++)
7331  {
7332  carry = carry * NBASE + dividend[i + 1];
7333  res_digits[i] = carry / divisor1;
7334  carry = carry % divisor1;
7335  }
7336  }
7337  else
7338  {
7339  /*
7340  * The full multiple-place algorithm is taken from Knuth volume 2,
7341  * Algorithm 4.3.1D.
7342  *
7343  * We need the first divisor digit to be >= NBASE/2. If it isn't,
7344  * make it so by scaling up both the divisor and dividend by the
7345  * factor "d". (The reason for allocating dividend[0] above is to
7346  * leave room for possible carry here.)
7347  */
7348  if (divisor[1] < HALF_NBASE)
7349  {
7350  int d = NBASE / (divisor[1] + 1);
7351 
7352  carry = 0;
7353  for (i = var2ndigits; i > 0; i--)
7354  {
7355  carry += divisor[i] * d;
7356  divisor[i] = carry % NBASE;
7357  carry = carry / NBASE;
7358  }
7359  Assert(carry == 0);
7360  carry = 0;
7361  /* at this point only var1ndigits of dividend can be nonzero */
7362  for (i = var1ndigits; i >= 0; i--)
7363  {
7364  carry += dividend[i] * d;
7365  dividend[i] = carry % NBASE;
7366  carry = carry / NBASE;
7367  }
7368  Assert(carry == 0);
7369  Assert(divisor[1] >= HALF_NBASE);
7370  }
7371  /* First 2 divisor digits are used repeatedly in main loop */
7372  divisor1 = divisor[1];
7373  divisor2 = divisor[2];
7374 
7375  /*
7376  * Begin the main loop. Each iteration of this loop produces the j'th
7377  * quotient digit by dividing dividend[j .. j + var2ndigits] by the
7378  * divisor; this is essentially the same as the common manual
7379  * procedure for long division.
7380  */
7381  for (j = 0; j < res_ndigits; j++)
7382  {
7383  /* Estimate quotient digit from the first two dividend digits */
7384  int next2digits = dividend[j] * NBASE + dividend[j + 1];
7385  int qhat;
7386 
7387  /*
7388  * If next2digits are 0, then quotient digit must be 0 and there's
7389  * no need to adjust the working dividend. It's worth testing
7390  * here to fall out ASAP when processing trailing zeroes in a
7391  * dividend.
7392  */
7393  if (next2digits == 0)
7394  {
7395  res_digits[j] = 0;
7396  continue;
7397  }
7398 
7399  if (dividend[j] == divisor1)
7400  qhat = NBASE - 1;
7401  else
7402  qhat = next2digits / divisor1;
7403 
7404  /*
7405  * Adjust quotient digit if it's too large. Knuth proves that
7406  * after this step, the quotient digit will be either correct or
7407  * just one too large. (Note: it's OK to use dividend[j+2] here
7408  * because we know the divisor length is at least 2.)
7409  */
7410  while (divisor2 * qhat >
7411  (next2digits - qhat * divisor1) * NBASE + dividend[j + 2])
7412  qhat--;
7413 
7414  /* As above, need do nothing more when quotient digit is 0 */
7415  if (qhat > 0)
7416  {
7417  /*
7418  * Multiply the divisor by qhat, and subtract that from the
7419  * working dividend. "carry" tracks the multiplication,
7420  * "borrow" the subtraction (could we fold these together?)
7421  */
7422  carry = 0;
7423  borrow = 0;
7424  for (i = var2ndigits; i >= 0; i--)
7425  {
7426  carry += divisor[i] * qhat;
7427  borrow -= carry % NBASE;
7428  carry = carry / NBASE;
7429  borrow += dividend[j + i];
7430  if (borrow < 0)
7431  {
7432  dividend[j + i] = borrow + NBASE;
7433  borrow = -1;
7434  }
7435  else
7436  {
7437  dividend[j + i] = borrow;
7438  borrow = 0;
7439  }
7440  }
7441  Assert(carry == 0);
7442 
7443  /*
7444  * If we got a borrow out of the top dividend digit, then
7445  * indeed qhat was one too large. Fix it, and add back the
7446  * divisor to correct the working dividend. (Knuth proves
7447  * that this will occur only about 3/NBASE of the time; hence,
7448  * it's a good idea to test this code with small NBASE to be
7449  * sure this section gets exercised.)
7450  */
7451  if (borrow)
7452  {
7453  qhat--;
7454  carry = 0;
7455  for (i = var2ndigits; i >= 0; i--)
7456  {
7457  carry += dividend[j + i] + divisor[i];
7458  if (carry >= NBASE)
7459  {
7460  dividend[j + i] = carry - NBASE;
7461  carry = 1;
7462  }
7463  else
7464  {
7465  dividend[j + i] = carry;
7466  carry = 0;
7467  }
7468  }
7469  /* A carry should occur here to cancel the borrow above */
7470  Assert(carry == 1);
7471  }
7472  }
7473 
7474  /* And we're done with this quotient digit */
7475  res_digits[j] = qhat;
7476  }
7477  }
7478 
7479  pfree(dividend);
7480 
7481  /*
7482  * Finally, round or truncate the result to the requested precision.
7483  */
7484  result->weight = res_weight;
7485  result->sign = res_sign;
7486 
7487  /* Round or truncate to target rscale (and set result->dscale) */
7488  if (round)
7489  round_var(result, rscale);
7490  else
7491  trunc_var(result, rscale);
7492 
7493  /* Strip leading and trailing zeroes */
7494  strip_var(result);
7495 }
static void round_var(NumericVar *var, int rscale)
Definition: numeric.c:8951
static void trunc_var(NumericVar *var, int rscale)
Definition: numeric.c:9057
int weight
Definition: numeric.c:275
#define NUMERIC_POS
Definition: numeric.c:167
static void strip_var(NumericVar *var)
Definition: numeric.c:9119
int errcode(int sqlerrcode)
Definition: elog.c:608
int ndigits
Definition: numeric.c:274
int dscale
Definition: numeric.c:277
#define NUMERIC_NEG
Definition: numeric.c:168
int sign
Definition: numeric.c:276
static void zero_var(NumericVar *var)
Definition: numeric.c:5751
void pfree(void *pointer)
Definition: mcxt.c:1056
#define ERROR
Definition: elog.h:43
int16 NumericDigit
Definition: numeric.c:102
#define HALF_NBASE
Definition: numeric.c:97
#define ereport(elevel, rest)
Definition: elog.h:141
#define NBASE
Definition: numeric.c:96
void * palloc0(Size size)
Definition: mcxt.c:980
#define Assert(condition)
Definition: c.h:739
NumericDigit * digits
Definition: numeric.c:279
int errmsg(const char *fmt,...)
Definition: elog.c:822
static void alloc_var(NumericVar *var, int ndigits)
Definition: numeric.c:5719
int i
#define Max(x, y)
Definition: numeric.c:13
#define DEC_DIGITS
Definition: numeric.c:98

◆ div_var_fast()

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

Definition at line 7517 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 exp_var(), ln_var(), log_var(), power_var_int(), and sqrt_var().

7519 {
7520  int div_ndigits;
7521  int res_sign;
7522  int res_weight;
7523  int *div;
7524  int qdigit;
7525  int carry;
7526  int maxdiv;
7527  int newdig;
7528  NumericDigit *res_digits;
7529  double fdividend,
7530  fdivisor,
7531  fdivisorinverse,
7532  fquotient;
7533  int qi;
7534  int i;
7535 
7536  /* copy these values into local vars for speed in inner loop */
7537  int var1ndigits = var1->ndigits;
7538  int var2ndigits = var2->ndigits;
7539  NumericDigit *var1digits = var1->digits;
7540  NumericDigit *var2digits = var2->digits;
7541 
7542  /*
7543  * First of all division by zero check; we must not be handed an
7544  * unnormalized divisor.
7545  */
7546  if (var2ndigits == 0 || var2digits[0] == 0)
7547  ereport(ERROR,
7548  (errcode(ERRCODE_DIVISION_BY_ZERO),
7549  errmsg("division by zero")));
7550 
7551  /*
7552  * Now result zero check
7553  */
7554  if (var1ndigits == 0)
7555  {
7556  zero_var(result);
7557  result->dscale = rscale;
7558  return;
7559  }
7560 
7561  /*
7562  * Determine the result sign, weight and number of digits to calculate
7563  */
7564  if (var1->sign == var2->sign)
7565  res_sign = NUMERIC_POS;
7566  else
7567  res_sign = NUMERIC_NEG;
7568  res_weight = var1->weight - var2->weight + 1;
7569  /* The number of accurate result digits we need to produce: */
7570  div_ndigits = res_weight + 1 + (rscale + DEC_DIGITS - 1) / DEC_DIGITS;
7571  /* Add guard digits for roundoff error */
7572  div_ndigits += DIV_GUARD_DIGITS;
7573  if (div_ndigits < DIV_GUARD_DIGITS)
7574  div_ndigits = DIV_GUARD_DIGITS;
7575  /* Must be at least var1ndigits, too, to simplify data-loading loop */
7576  if (div_ndigits < var1ndigits)
7577  div_ndigits = var1ndigits;
7578 
7579  /*
7580  * We do the arithmetic in an array "div[]" of signed int's. Since
7581  * INT_MAX is noticeably larger than NBASE*NBASE, this gives us headroom
7582  * to avoid normalizing carries immediately.
7583  *
7584  * We start with div[] containing one zero digit followed by the
7585  * dividend's digits (plus appended zeroes to reach the desired precision
7586  * including guard digits). Each step of the main loop computes an
7587  * (approximate) quotient digit and stores it into div[], removing one
7588  * position of dividend space. A final pass of carry propagation takes
7589  * care of any mistaken quotient digits.
7590  */
7591  div = (int *) palloc0((div_ndigits + 1) * sizeof(int));
7592  for (i = 0; i < var1ndigits; i++)
7593  div[i + 1] = var1digits[i];
7594 
7595  /*
7596  * We estimate each quotient digit using floating-point arithmetic, taking
7597  * the first four digits of the (current) dividend and divisor. This must
7598  * be float to avoid overflow. The quotient digits will generally be off
7599  * by no more than one from the exact answer.
7600  */
7601  fdivisor = (double) var2digits[0];
7602  for (i = 1; i < 4; i++)
7603  {
7604  fdivisor *= NBASE;
7605  if (i < var2ndigits)
7606  fdivisor += (double) var2digits[i];
7607  }
7608  fdivisorinverse = 1.0 / fdivisor;
7609 
7610  /*
7611  * maxdiv tracks the maximum possible absolute value of any div[] entry;
7612  * when this threatens to exceed INT_MAX, we take the time to propagate
7613  * carries. Furthermore, we need to ensure that overflow doesn't occur
7614  * during the carry propagation passes either. The carry values may have
7615  * an absolute value as high as INT_MAX/NBASE + 1, so really we must
7616  * normalize when digits threaten to exceed INT_MAX - INT_MAX/NBASE - 1.
7617  *
7618  * To avoid overflow in maxdiv itself, it represents the max absolute
7619  * value divided by NBASE-1, ie, at the top of the loop it is known that
7620  * no div[] entry has an absolute value exceeding maxdiv * (NBASE-1).
7621  *
7622  * Actually, though, that holds good only for div[] entries after div[qi];
7623  * the adjustment done at the bottom of the loop may cause div[qi + 1] to
7624  * exceed the maxdiv limit, so that div[qi] in the next iteration is
7625  * beyond the limit. This does not cause problems, as explained below.
7626  */
7627  maxdiv = 1;
7628 
7629  /*
7630  * Outer loop computes next quotient digit, which will go into div[qi]
7631  */
7632  for (qi = 0; qi < div_ndigits; qi++)
7633  {
7634  /* Approximate the current dividend value */
7635  fdividend = (double) div[qi];
7636  for (i = 1; i < 4; i++)
7637  {
7638  fdividend *= NBASE;
7639  if (qi + i <= div_ndigits)
7640  fdividend += (double) div[qi + i];
7641  }
7642  /* Compute the (approximate) quotient digit */
7643  fquotient = fdividend * fdivisorinverse;
7644  qdigit = (fquotient >= 0.0) ? ((int) fquotient) :
7645  (((int) fquotient) - 1); /* truncate towards -infinity */
7646 
7647  if (qdigit != 0)
7648  {
7649  /* Do we need to normalize now? */
7650  maxdiv += Abs(qdigit);
7651  if (maxdiv > (INT_MAX - INT_MAX / NBASE - 1) / (NBASE - 1))
7652  {
7653  /* Yes, do it */
7654  carry = 0;
7655  for (i = div_ndigits; i > qi; i--)
7656  {
7657  newdig = div[i] + carry;
7658  if (newdig < 0)
7659  {
7660  carry = -((-newdig - 1) / NBASE) - 1;
7661  newdig -= carry * NBASE;
7662  }
7663  else if (newdig >= NBASE)
7664  {
7665  carry = newdig / NBASE;
7666  newdig -= carry * NBASE;
7667  }
7668  else
7669  carry = 0;
7670  div[i] = newdig;
7671  }
7672  newdig = div[qi] + carry;
7673  div[qi] = newdig;
7674 
7675  /*
7676  * All the div[] digits except possibly div[qi] are now in the
7677  * range 0..NBASE-1. We do not need to consider div[qi] in
7678  * the maxdiv value anymore, so we can reset maxdiv to 1.
7679  */
7680  maxdiv = 1;
7681 
7682  /*
7683  * Recompute the quotient digit since new info may have
7684  * propagated into the top four dividend digits
7685  */
7686  fdividend = (double) div[qi];
7687  for (i = 1; i < 4; i++)
7688  {
7689  fdividend *= NBASE;
7690  if (qi + i <= div_ndigits)
7691  fdividend += (double) div[qi + i];
7692  }
7693  /* Compute the (approximate) quotient digit */
7694  fquotient = fdividend * fdivisorinverse;
7695  qdigit = (fquotient >= 0.0) ? ((int) fquotient) :
7696  (((int) fquotient) - 1); /* truncate towards -infinity */
7697  maxdiv += Abs(qdigit);
7698  }
7699 
7700  /*
7701  * Subtract off the appropriate multiple of the divisor.
7702  *
7703  * The digits beyond div[qi] cannot overflow, because we know they
7704  * will fall within the maxdiv limit. As for div[qi] itself, note
7705  * that qdigit is approximately trunc(div[qi] / vardigits[0]),
7706  * which would make the new value simply div[qi] mod vardigits[0].
7707  * The lower-order terms in qdigit can change this result by not
7708  * more than about twice INT_MAX/NBASE, so overflow is impossible.
7709  */
7710  if (qdigit != 0)
7711  {
7712  int istop = Min(var2ndigits, div_ndigits - qi + 1);
7713 
7714  for (i = 0; i < istop; i++)
7715  div[qi + i] -= qdigit * var2digits[i];
7716  }
7717  }
7718 
7719  /*
7720  * The dividend digit we are about to replace might still be nonzero.
7721  * Fold it into the next digit position.
7722  *
7723  * There is no risk of overflow here, although proving that requires
7724  * some care. Much as with the argument for div[qi] not overflowing,
7725  * if we consider the first two terms in the numerator and denominator
7726  * of qdigit, we can see that the final value of div[qi + 1] will be
7727  * approximately a remainder mod (vardigits[0]*NBASE + vardigits[1]).
7728  * Accounting for the lower-order terms is a bit complicated but ends
7729  * up adding not much more than INT_MAX/NBASE to the possible range.
7730  * Thus, div[qi + 1] cannot overflow here, and in its role as div[qi]
7731  * in the next loop iteration, it can't be large enough to cause
7732  * overflow in the carry propagation step (if any), either.
7733  *
7734  * But having said that: div[qi] can be more than INT_MAX/NBASE, as
7735  * noted above, which means that the product div[qi] * NBASE *can*
7736  * overflow. When that happens, adding it to div[qi + 1] will always
7737  * cause a canceling overflow so that the end result is correct. We
7738  * could avoid the intermediate overflow by doing the multiplication
7739  * and addition in int64 arithmetic, but so far there appears no need.
7740  */
7741  div[qi + 1] += div[qi] * NBASE;
7742 
7743  div[qi] = qdigit;
7744  }
7745 
7746  /*
7747  * Approximate and store the last quotient digit (div[div_ndigits])
7748  */
7749  fdividend = (double) div[qi];
7750  for (i = 1; i < 4; i++)
7751  fdividend *= NBASE;
7752  fquotient = fdividend * fdivisorinverse;
7753  qdigit = (fquotient >= 0.0) ? ((int) fquotient) :
7754  (((int) fquotient) - 1); /* truncate towards -infinity */
7755  div[qi] = qdigit;
7756 
7757  /*
7758  * Because the quotient digits might be off by one, some of them might be
7759  * -1 or NBASE at this point. The represented value is correct in a
7760  * mathematical sense, but it doesn't look right. We do a final carry
7761  * propagation pass to normalize the digits, which we combine with storing
7762  * the result digits into the output. Note that this is still done at
7763  * full precision w/guard digits.
7764  */
7765  alloc_var(result, div_ndigits + 1);
7766  res_digits = result->digits;
7767  carry = 0;
7768  for (i = div_ndigits; i >= 0; i--)
7769  {
7770  newdig = div[i] + carry;
7771  if (newdig < 0)
7772  {
7773  carry = -((-newdig - 1) / NBASE) - 1;
7774  newdig -= carry * NBASE;
7775  }
7776  else if (newdig >= NBASE)
7777  {
7778  carry = newdig / NBASE;
7779  newdig -= carry * NBASE;
7780  }
7781  else
7782  carry = 0;
7783  res_digits[i] = newdig;
7784  }
7785  Assert(carry == 0);
7786 
7787  pfree(div);
7788 
7789  /*
7790  * Finally, round the result to the requested precision.
7791  */
7792  result->weight = res_weight;
7793  result->sign = res_sign;
7794 
7795  /* Round to target rscale (and set result->dscale) */
7796  if (round)
7797  round_var(result, rscale);
7798  else
7799  trunc_var(result, rscale);
7800 
7801  /* Strip leading and trailing zeroes */
7802  strip_var(result);
7803 }
static void round_var(NumericVar *var, int rscale)
Definition: numeric.c:8951
static void trunc_var(NumericVar *var, int rscale)
Definition: numeric.c:9057
int weight
Definition: numeric.c:275
#define NUMERIC_POS
Definition: numeric.c:167
static void strip_var(NumericVar *var)
Definition: numeric.c:9119
int errcode(int sqlerrcode)
Definition: elog.c:608
int ndigits
Definition: numeric.c:274
int dscale
Definition: numeric.c:277
#define Min(x, y)
Definition: numeric.c:14
#define Abs(x)
Definition: c.h:917
#define NUMERIC_NEG
Definition: numeric.c:168
int sign
Definition: numeric.c:276
static void zero_var(NumericVar *var)
Definition: numeric.c:5751
void pfree(void *pointer)
Definition: mcxt.c:1056
#define ERROR
Definition: elog.h:43
int16 NumericDigit
Definition: numeric.c:102
#define ereport(elevel, rest)
Definition: elog.h:141
#define NBASE
Definition: numeric.c:96
void * palloc0(Size size)
Definition: mcxt.c:980
#define Assert(condition)
Definition: c.h:739
NumericDigit * digits
Definition: numeric.c:279
#define DIV_GUARD_DIGITS
Definition: numeric.c:100
int errmsg(const char *fmt,...)
Definition: elog.c:822
static void alloc_var(NumericVar *var, int ndigits)
Definition: numeric.c:5719
int i
#define DEC_DIGITS
Definition: numeric.c:98

◆ do_numeric_accum()

static void do_numeric_accum ( NumericAggState state,
Numeric  newval 
)
static

Definition at line 3576 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, NUMERIC_IS_NAN, NumericAggState::sumX, and NumericAggState::sumX2.

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

3577 {
3578  NumericVar X;
3579  NumericVar X2;
3580  MemoryContext old_context;
3581 
3582  /* Count NaN inputs separately from all else */
3583  if (NUMERIC_IS_NAN(newval))
3584  {
3585  state->NaNcount++;
3586  return;
3587  }
3588 
3589  /* load processed number in short-lived context */
3590  init_var_from_num(newval, &X);
3591 
3592  /*
3593  * Track the highest input dscale that we've seen, to support inverse
3594  * transitions (see do_numeric_discard).
3595  */
3596  if (X.dscale > state->maxScale)
3597  {
3598  state->maxScale = X.dscale;
3599  state->maxScaleCount = 1;
3600  }
3601  else if (X.dscale == state->maxScale)
3602  state->maxScaleCount++;
3603 
3604  /* if we need X^2, calculate that in short-lived context */
3605  if (state->calcSumX2)
3606  {
3607  init_var(&X2);
3608  mul_var(&X, &X, &X2, X.dscale * 2);
3609  }
3610 
3611  /* The rest of this needs to work in the aggregate context */
3612  old_context = MemoryContextSwitchTo(state->agg_context);
3613 
3614  state->N++;
3615 
3616  /* Accumulate sums */
3617  accum_sum_add(&(state->sumX), &X);
3618 
3619  if (state->calcSumX2)
3620  accum_sum_add(&(state->sumX2), &X2);
3621 
3622  MemoryContextSwitchTo(old_context);
3623 }
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
MemoryContext agg_context
Definition: numeric.c:3522
int dscale
Definition: numeric.c:277
static void accum_sum_add(NumericSumAccum *accum, const NumericVar *var1)
Definition: numeric.c:9176
static void init_var_from_num(Numeric num, NumericVar *dest)
Definition: numeric.c:5968
static void mul_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result, int rscale)
Definition: numeric.c:7035
NumericSumAccum sumX2
Definition: numeric.c:3525
int64 NaNcount
Definition: numeric.c:3528
int64 maxScaleCount
Definition: numeric.c:3527
#define NUMERIC_IS_NAN(n)
Definition: numeric.c:173
NumericSumAccum sumX
Definition: numeric.c:3524
#define init_var(v)
Definition: numeric.c:454

◆ do_numeric_discard()

static bool do_numeric_discard ( NumericAggState state,
Numeric  newval 
)
static

Definition at line 3641 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, NUMERIC_IS_NAN, NUMERIC_NEG, NUMERIC_POS, 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().

3642 {
3643  NumericVar X;
3644  NumericVar X2;
3645  MemoryContext old_context;
3646 
3647  /* Count NaN inputs separately from all else */
3648  if (NUMERIC_IS_NAN(newval))
3649  {
3650  state->NaNcount--;
3651  return true;
3652  }
3653 
3654  /* load processed number in short-lived context */
3655  init_var_from_num(newval, &X);
3656 
3657  /*
3658  * state->sumX's dscale is the maximum dscale of any of the inputs.
3659  * Removing the last input with that dscale would require us to recompute
3660  * the maximum dscale of the *remaining* inputs, which we cannot do unless
3661  * no more non-NaN inputs remain at all. So we report a failure instead,
3662  * and force the aggregation to be redone from scratch.
3663  */
3664  if (X.dscale == state->maxScale)
3665  {
3666  if (state->maxScaleCount > 1 || state->maxScale == 0)
3667  {
3668  /*
3669  * Some remaining inputs have same dscale, or dscale hasn't gotten
3670  * above zero anyway
3671  */
3672  state->maxScaleCount--;
3673  }
3674  else if (state->N == 1)
3675  {
3676  /* No remaining non-NaN inputs at all, so reset maxScale */
3677  state->maxScale = 0;
3678  state->maxScaleCount = 0;
3679  }
3680  else
3681  {
3682  /* Correct new maxScale is uncertain, must fail */
3683  return false;
3684  }
3685  }
3686 
3687  /* if we need X^2, calculate that in short-lived context */
3688  if (state->calcSumX2)
3689  {
3690  init_var(&X2);
3691  mul_var(&X, &X, &X2, X.dscale * 2);
3692  }
3693 
3694  /* The rest of this needs to work in the aggregate context */
3695  old_context = MemoryContextSwitchTo(state->agg_context);
3696 
3697  if (state->N-- > 1)
3698  {
3699  /* Negate X, to subtract it from the sum */
3700  X.sign = (X.sign == NUMERIC_POS ? NUMERIC_NEG : NUMERIC_POS);
3701  accum_sum_add(&(state->sumX), &X);
3702 
3703  if (state->calcSumX2)
3704  {
3705  /* Negate X^2. X^2 is always positive */
3706  X2.sign = NUMERIC_NEG;
3707  accum_sum_add(&(state->sumX2), &X2);
3708  }
3709  }
3710  else
3711  {
3712  /* Zero the sums */
3713  Assert(state->N == 0);
3714 
3715  accum_sum_reset(&state->sumX);
3716  if (state->calcSumX2)
3717  accum_sum_reset(&state->sumX2);
3718  }
3719 
3720  MemoryContextSwitchTo(old_context);
3721 
3722  return true;
3723 }
#define NUMERIC_POS
Definition: numeric.c:167
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
MemoryContext agg_context
Definition: numeric.c:3522
int dscale
Definition: numeric.c:277
#define NUMERIC_NEG
Definition: numeric.c:168
static void accum_sum_add(NumericSumAccum *accum, const NumericVar *var1)
Definition: numeric.c:9176
int sign
Definition: numeric.c:276
static void init_var_from_num(Numeric num, NumericVar *dest)
Definition: numeric.c:5968
#define Assert(condition)
Definition: c.h:739
static void mul_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result, int rscale)
Definition: numeric.c:7035
NumericSumAccum sumX2
Definition: numeric.c:3525
static void accum_sum_reset(NumericSumAccum *accum)
Definition: numeric.c:9160
int64 NaNcount
Definition: numeric.c:3528
int64 maxScaleCount
Definition: numeric.c:3527
#define NUMERIC_IS_NAN(n)
Definition: numeric.c:173
NumericSumAccum sumX
Definition: numeric.c:3524
#define init_var(v)
Definition: numeric.c:454

◆ estimate_ln_dweight()

static int estimate_ln_dweight ( const NumericVar var)
static

Definition at line 8156 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().

8157 {
8158  int ln_dweight;
8159 
8160  if (cmp_var(var, &const_zero_point_nine) >= 0 &&
8161  cmp_var(var, &const_one_point_one) <= 0)
8162  {
8163  /*
8164  * 0.9 <= var <= 1.1
8165  *
8166  * ln(var) has a negative weight (possibly very large). To get a
8167  * reasonably accurate result, estimate it using ln(1+x) ~= x.
8168  */
8169  NumericVar x;
8170 
8171  init_var(&x);
8172  sub_var(var, &const_one, &x);
8173 
8174  if (x.ndigits > 0)
8175  {
8176  /* Use weight of most significant decimal digit of x */
8177  ln_dweight = x.weight * DEC_DIGITS + (int) log10(x.digits[0]);
8178  }
8179  else
8180  {
8181  /* x = 0. Since ln(1) = 0 exactly, we don't need extra digits */
8182  ln_dweight = 0;
8183  }
8184 
8185  free_var(&x);
8186  }
8187  else
8188  {
8189  /*
8190  * Estimate the logarithm using the first couple of digits from the
8191  * input number. This will give an accurate result whenever the input
8192  * is not too close to 1.
8193  */
8194  if (var->ndigits > 0)
8195  {
8196  int digits;
8197  int dweight;
8198  double ln_var;
8199 
8200  digits = var->digits[0];
8201  dweight = var->weight * DEC_DIGITS;
8202 
8203  if (var->ndigits > 1)
8204  {
8205  digits = digits * NBASE + var->digits[1];
8206  dweight -= DEC_DIGITS;
8207  }
8208 
8209  /*----------
8210  * We have var ~= digits * 10^dweight
8211  * so ln(var) ~= ln(digits) + dweight * ln(10)
8212  *----------
8213  */
8214  ln_var = log((double) digits) + dweight * 2.302585092994046;
8215  ln_dweight = (int) log10(Abs(ln_var));
8216  }
8217  else
8218  {
8219  /* Caller should fail on ln(0), but for the moment return zero */
8220  ln_dweight = 0;
8221  }
8222  }
8223 
8224  return ln_dweight;
8225 }
int weight
Definition: numeric.c:275
static const NumericVar const_zero_point_nine
Definition: numeric.c:412
static const NumericVar const_one
Definition: numeric.c:378
static void ln_var(const NumericVar *arg, NumericVar *result, int rscale)
Definition: numeric.c:8234
int ndigits
Definition: numeric.c:274
#define Abs(x)
Definition: c.h:917
#define NBASE
Definition: numeric.c:96
static int cmp_var(const NumericVar *var1, const NumericVar *var2)
Definition: numeric.c:6739
static void free_var(NumericVar *var)
Definition: numeric.c:5735
NumericDigit * digits
Definition: numeric.c:279
static void sub_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition: numeric.c:6914
#define DEC_DIGITS
Definition: numeric.c:98
static const NumericVar const_one_point_one
Definition: numeric.c:422
#define init_var(v)
Definition: numeric.c:454
int digits
Definition: informix.c:666

◆ exp_var()

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

Definition at line 8030 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().

8031 {
8032  NumericVar x;
8033  NumericVar elem;
8034  NumericVar ni;
8035  double val;
8036  int dweight;
8037  int ndiv2;
8038  int sig_digits;
8039  int local_rscale;
8040 
8041  init_var(&x);
8042  init_var(&elem);
8043  init_var(&ni);
8044 
8045  set_var_from_var(arg, &x);
8046 
8047  /*
8048  * Estimate the dweight of the result using floating point arithmetic, so
8049  * that we can choose an appropriate local rscale for the calculation.
8050  */
8052 
8053  /* Guard against overflow */
8054  /* If you change this limit, see also power_var()'s limit */
8055  if (Abs(val) >= NUMERIC_MAX_RESULT_SCALE * 3)
8056  ereport(ERROR,
8057  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
8058  errmsg("value overflows numeric format")));
8059 
8060  /* decimal weight = log10(e^x) = x * log10(e) */
8061  dweight = (int) (val * 0.434294481903252);
8062 
8063  /*
8064  * Reduce x to the range -0.01 <= x <= 0.01 (approximately) by dividing by
8065  * 2^n, to improve the convergence rate of the Taylor series.
8066  */
8067  if (Abs(val) > 0.01)
8068  {
8069  NumericVar tmp;
8070 
8071  init_var(&tmp);
8072  set_var_from_var(&const_two, &tmp);
8073 
8074  ndiv2 = 1;
8075  val /= 2;
8076 
8077  while (Abs(val) > 0.01)
8078  {
8079  ndiv2++;
8080  val /= 2;
8081  add_var(&tmp, &tmp, &tmp);
8082  }
8083 
8084  local_rscale = x.dscale + ndiv2;
8085  div_var_fast(&x, &tmp, &x, local_rscale, true);
8086 
8087  free_var(&tmp);
8088  }
8089  else
8090  ndiv2 = 0;
8091 
8092  /*
8093  * Set the scale for the Taylor series expansion. The final result has
8094  * (dweight + rscale + 1) significant digits. In addition, we have to
8095  * raise the Taylor series result to the power 2^ndiv2, which introduces
8096  * an error of up to around log10(2^ndiv2) digits, so work with this many
8097  * extra digits of precision (plus a few more for good measure).
8098  */
8099  sig_digits = 1 + dweight + rscale + (int) (ndiv2 * 0.301029995663981);
8100  sig_digits = Max(sig_digits, 0) + 8;
8101 
8102  local_rscale = sig_digits - 1;
8103 
8104  /*
8105  * Use the Taylor series
8106  *
8107  * exp(x) = 1 + x + x^2/2! + x^3/3! + ...
8108  *
8109  * Given the limited range of x, this should converge reasonably quickly.
8110  * We run the series until the terms fall below the local_rscale limit.
8111  */
8112  add_var(&const_one, &x, result);
8113 
8114  mul_var(&x, &x, &elem, local_rscale);
8115  set_var_from_var(&const_two, &ni);
8116  div_var_fast(&elem, &ni, &elem, local_rscale, true);
8117 
8118  while (elem.ndigits != 0)
8119  {
8120  add_var(result, &elem, result);
8121 
8122  mul_var(&elem, &x, &elem, local_rscale);
8123  add_var(&ni, &const_one, &ni);
8124  div_var_fast(&elem, &ni, &elem, local_rscale, true);
8125  }
8126 
8127  /*
8128  * Compensate for the argument range reduction. Since the weight of the
8129  * result doubles with each multiplication, we can reduce the local rscale
8130  * as we proceed.
8131  */
8132  while (ndiv2-- > 0)
8133  {
8134  local_rscale = sig_digits - result->weight * 2 * DEC_DIGITS;
8135  local_rscale = Max(local_rscale, NUMERIC_MIN_DISPLAY_SCALE);
8136  mul_var(result, result, result, local_rscale);
8137  }
8138 
8139  /* Round to requested rscale */
8140  round_var(result, rscale);
8141 
8142  free_var(&x);
8143  free_var(&elem);
8144  free_var(&ni);
8145 }
static void round_var(NumericVar *var, int rscale)
Definition: numeric.c:8951
int weight
Definition: numeric.c:275
static const NumericVar const_one
Definition: numeric.c:378
int errcode(int sqlerrcode)
Definition: elog.c:608
int ndigits
Definition: numeric.c:274
int dscale
Definition: numeric.c:277
#define Abs(x)
Definition: c.h:917
#define ERROR
Definition: elog.h:43
static double numericvar_to_double_no_overflow(const NumericVar *var)
Definition: numeric.c:6707
#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:7517
#define ereport(elevel, rest)
Definition: elog.h:141
static void free_var(NumericVar *var)
Definition: numeric.c:5735
static const NumericVar const_two
Definition: numeric.c:382
static void mul_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result, int rscale)
Definition: numeric.c:7035
static void add_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition: numeric.c:6797
int errmsg(const char *fmt,...)
Definition: elog.c:822
#define Max(x, y)
Definition: numeric.c:13
#define DEC_DIGITS
Definition: numeric.c:98
static void set_var_from_var(const NumericVar *value, NumericVar *dest)
Definition: numeric.c:5985
long val
Definition: informix.c:664
#define init_var(v)
Definition: numeric.c:454

◆ float4_numeric()

Datum float4_numeric ( PG_FUNCTION_ARGS  )

Definition at line 3454 of file numeric.c.

References buf, ereport, errcode(), errmsg(), ERROR, free_var(), init_var, isinf(), make_result(), PG_GETARG_FLOAT4, PG_RETURN_NUMERIC, set_var_from_str(), snprintf, and val.

3455 {
3457  Numeric res;
3458  NumericVar result;
3459  char buf[FLT_DIG + 100];
3460 
3461  if (isnan(val))
3463 
3464  if (isinf(val))
3465  ereport(ERROR,
3466  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3467  errmsg("cannot convert infinity to numeric")));
3468 
3469  snprintf(buf, sizeof(buf), "%.*g", FLT_DIG, val);
3470 
3471  init_var(&result);
3472 
3473  /* Assume we need not worry about leading/trailing spaces */
3474  (void) set_var_from_str(buf, buf, &result);
3475 
3476  res = make_result(&result);
3477 
3478  free_var(&result);
3479 
3480  PG_RETURN_NUMERIC(res);
3481 }
#define PG_RETURN_NUMERIC(x)
Definition: numeric.h:54
int errcode(int sqlerrcode)
Definition: elog.c:608
#define ERROR
Definition: elog.h:43
int isinf(double x)
static char * buf
Definition: pg_test_fsync.c:67
#define PG_GETARG_FLOAT4(n)
Definition: fmgr.h:275
#define ereport(elevel, rest)
Definition: elog.h:141
float float4
Definition: c.h:491
static void free_var(NumericVar *var)
Definition: numeric.c:5735
static const char * set_var_from_str(const char *str, const char *cp, NumericVar *dest)
Definition: numeric.c:5775
static const NumericVar const_nan
Definition: numeric.c:425
static Numeric make_result(const NumericVar *var)
Definition: numeric.c:6351
int errmsg(const char *fmt,...)
Definition: elog.c:822
#define snprintf
Definition: port.h:192
long val
Definition: informix.c:664
#define init_var(v)
Definition: numeric.c:454

◆ float8_numeric()

Datum float8_numeric ( PG_FUNCTION_ARGS  )

Definition at line 3383 of file numeric.c.

References buf, ereport, errcode(), errmsg(), ERROR, free_var(), init_var, isinf(), make_result(), PG_GETARG_FLOAT8, PG_RETURN_NUMERIC, set_var_from_str(), snprintf, and val.

Referenced by executeItemOptUnwrapTarget(), and SV_to_JsonbValue().

3384 {
3386  Numeric res;
3387  NumericVar result;
3388  char buf[DBL_DIG + 100];
3389 
3390  if (isnan(val))
3392 
3393  if (isinf(val))
3394  ereport(ERROR,
3395  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3396  errmsg("cannot convert infinity to numeric")));
3397 
3398  snprintf(buf, sizeof(buf), "%.*g", DBL_DIG, val);
3399 
3400  init_var(&result);
3401 
3402  /* Assume we need not worry about leading/trailing spaces */
3403  (void) set_var_from_str(buf, buf, &result);
3404 
3405  res = make_result(&result);
3406 
3407  free_var(&result);
3408 
3409  PG_RETURN_NUMERIC(res);
3410 }
#define PG_RETURN_NUMERIC(x)
Definition: numeric.h:54
#define PG_GETARG_FLOAT8(n)
Definition: fmgr.h:276
int errcode(int sqlerrcode)
Definition: elog.c:608
#define ERROR
Definition: elog.h:43
double float8
Definition: c.h:492
int isinf(double x)
static char * buf
Definition: pg_test_fsync.c:67
#define ereport(elevel, rest)
Definition: elog.h:141
static void free_var(NumericVar *var)
Definition: numeric.c:5735
static const char * set_var_from_str(const char *str, const char *cp, NumericVar *dest)
Definition: numeric.c:5775
static const NumericVar const_nan
Definition: numeric.c:425
static Numeric make_result(const NumericVar *var)
Definition: numeric.c:6351
int errmsg(const char *fmt,...)
Definition: elog.c:822
#define snprintf
Definition: port.h:192
long val
Definition: informix.c:664
#define init_var(v)
Definition: numeric.c:454

◆ floor_var()

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

Definition at line 7934 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().

7935 {
7936  NumericVar tmp;
7937 
7938  init_var(&tmp);
7939  set_var_from_var(var, &tmp);
7940 
7941  trunc_var(&tmp, 0);
7942 
7943  if (var->sign == NUMERIC_NEG && cmp_var(var, &tmp) != 0)
7944  sub_var(&tmp, &const_one, &tmp);
7945 
7946  set_var_from_var(&tmp, result);
7947  free_var(&tmp);
7948 }
static void trunc_var(NumericVar *var, int rscale)
Definition: numeric.c:9057
static const NumericVar const_one
Definition: numeric.c:378
#define NUMERIC_NEG
Definition: numeric.c:168
int sign
Definition: numeric.c:276
static int cmp_var(const NumericVar *var1, const NumericVar *var2)
Definition: numeric.c:6739
static void free_var(NumericVar *var)
Definition: numeric.c:5735
static void sub_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition: numeric.c:6914
static void set_var_from_var(const NumericVar *value, NumericVar *dest)
Definition: numeric.c:5985
#define init_var(v)
Definition: numeric.c:454

◆ free_var()

static void free_var ( NumericVar var)
static

Definition at line 5735 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(), estimate_ln_dweight(), exp_var(), float4_numeric(), float8_numeric(), floor_var(), get_str_from_var_sci(), in_range_numeric_numeric(), int2_numeric(), int4_numeric(), int64_to_numericvar(), int8_avg_serialize(), int8_numeric(), 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_in(), numeric_inc(), numeric_ln(), numeric_log(), 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_sign(), numeric_sqrt(), numeric_stddev_internal(), numeric_stddev_pop(), numeric_sub_opt_error(), numeric_sum(), numeric_trunc(), numericvar_to_int64(), power_var(), power_var_int(), sqrt_var(), and width_bucket_numeric().

5736 {
5737  digitbuf_free(var->buf);
5738  var->buf = NULL;
5739  var->digits = NULL;
5740  var->sign = NUMERIC_NAN;
5741 }
int sign
Definition: numeric.c:276
#define digitbuf_free(buf)
Definition: numeric.c:448
#define NUMERIC_NAN
Definition: numeric.c:170
NumericDigit * buf
Definition: numeric.c:278
NumericDigit * digits
Definition: numeric.c:279

◆ generate_series_numeric()

Datum generate_series_numeric ( PG_FUNCTION_ARGS  )

Definition at line 1379 of file numeric.c.

References generate_series_step_numeric().

1380 {
1381  return generate_series_step_numeric(fcinfo);
1382 }
Datum generate_series_step_numeric(PG_FUNCTION_ARGS)
Definition: numeric.c:1385

◆ generate_series_step_numeric()

Datum generate_series_step_numeric ( PG_FUNCTION_ARGS  )

Definition at line 1385 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_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().

1386 {
1388  FuncCallContext *funcctx;
1389  MemoryContext oldcontext;
1390 
1391  if (SRF_IS_FIRSTCALL())
1392  {
1393  Numeric start_num = PG_GETARG_NUMERIC(0);
1394  Numeric stop_num = PG_GETARG_NUMERIC(1);
1395  NumericVar steploc = const_one;
1396 
1397  /* handle NaN in start and stop values */
1398  if (NUMERIC_IS_NAN(start_num))
1399  ereport(ERROR,
1400  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1401  errmsg("start value cannot be NaN")));
1402 
1403  if (NUMERIC_IS_NAN(stop_num))
1404  ereport(ERROR,
1405  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1406  errmsg("stop value cannot be NaN")));
1407 
1408  /* see if we were given an explicit step size */
1409  if (PG_NARGS() == 3)
1410  {
1411  Numeric step_num = PG_GETARG_NUMERIC(2);
1412 
1413  if (NUMERIC_IS_NAN(step_num))
1414  ereport(ERROR,
1415  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1416  errmsg("step size cannot be NaN")));
1417 
1418  init_var_from_num(step_num, &steploc);
1419 
1420  if (cmp_var(&steploc, &const_zero) == 0)
1421  ereport(ERROR,
1422  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1423  errmsg("step size cannot equal zero")));
1424  }
1425 
1426  /* create a function context for cross-call persistence */
1427  funcctx = SRF_FIRSTCALL_INIT();
1428 
1429  /*
1430  * Switch to memory context appropriate for multiple function calls.
1431  */
1432  oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
1433 
1434  /* allocate memory for user context */
1435  fctx = (generate_series_numeric_fctx *)
1437 
1438  /*
1439  * Use fctx to keep state from call to call. Seed current with the
1440  * original start value. We must copy the start_num and stop_num
1441  * values rather than pointing to them, since we may have detoasted
1442  * them in the per-call context.
1443  */
1444  init_var(&fctx->current);
1445  init_var(&fctx->stop);
1446  init_var(&fctx->step);
1447 
1448  set_var_from_num(start_num, &fctx->current);
1449  set_var_from_num(stop_num, &fctx->stop);
1450  set_var_from_var(&steploc, &fctx->step);
1451 
1452  funcctx->user_fctx = fctx;
1453  MemoryContextSwitchTo(oldcontext);
1454  }
1455 
1456  /* stuff done on every call of the function */
1457  funcctx = SRF_PERCALL_SETUP();
1458 
1459  /*
1460  * Get the saved state and use current state as the result of this
1461  * iteration.
1462  */
1463  fctx = funcctx->user_fctx;
1464 
1465  if ((fctx->step.sign == NUMERIC_POS &&
1466  cmp_var(&fctx->current, &fctx->stop) <= 0) ||
1467  (fctx->step.sign == NUMERIC_NEG &&
1468  cmp_var(&fctx->current, &fctx->stop) >= 0))
1469  {
1470  Numeric result = make_result(&fctx->current);
1471 
1472  /* switch to memory context appropriate for iteration calculation */
1473  oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
1474 
1475  /* increment current in preparation for next iteration */
1476  add_var(&fctx->current, &fctx->step, &fctx->current);
1477  MemoryContextSwitchTo(oldcontext);
1478 
1479  /* do when there is more left to send */
1480  SRF_RETURN_NEXT(funcctx, NumericGetDatum(result));
1481  }
1482  else
1483  /* do when there is no more left */
1484  SRF_RETURN_DONE(funcctx);
1485 }
#define SRF_IS_FIRSTCALL()
Definition: funcapi.h:282
static const NumericVar const_one
Definition: numeric.c:378
#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:608
#define SRF_PERCALL_SETUP()
Definition: funcapi.h:286
#define SRF_RETURN_NEXT(_funcctx, _result)
Definition: funcapi.h:288
#define NUMERIC_NEG
Definition: numeric.c:168
int sign
Definition: numeric.c:276
#define ERROR
Definition: elog.h:43
static void init_var_from_num(Numeric num, NumericVar *dest)
Definition: numeric.c:5968
#define ereport(elevel, rest)
Definition: elog.h:141
static const NumericVar const_zero
Definition: numeric.c:374
static int cmp_var(const NumericVar *var1, const NumericVar *var2)
Definition: numeric.c:6739
#define PG_GETARG_NUMERIC(n)
Definition: numeric.h:52
static void set_var_from_num(Numeric value, NumericVar *dest)
Definition: numeric.c:5937
MemoryContext multi_call_memory_ctx
Definition: funcapi.h:101
static void add_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition: numeric.c:6797
#define PG_NARGS()
Definition: fmgr.h:198
static Numeric make_result(const NumericVar *var)
Definition: numeric.c:6351
void * user_fctx
Definition: funcapi.h:82
void * palloc(Size size)
Definition: mcxt.c:949
int errmsg(const char *fmt,...)
Definition: elog.c:822
#define NUMERIC_IS_NAN(n)
Definition: numeric.c:173
static void set_var_from_var(const NumericVar *value, NumericVar *dest)
Definition: numeric.c:5985
#define init_var(v)
Definition: numeric.c:454
#define SRF_RETURN_DONE(_funcctx)
Definition: funcapi.h:306
#define SRF_FIRSTCALL_INIT()
Definition: funcapi.h:284

◆ get_str_from_var()

static char * get_str_from_var ( const NumericVar var)
static

Definition at line 6011 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().

6012 {
6013  int dscale;
6014  char *str;
6015  char *cp;
6016  char *endcp;
6017  int i;
6018  int d;
6019  NumericDigit dig;
6020 
6021 #if DEC_DIGITS > 1
6022  NumericDigit d1;
6023 #endif
6024 
6025  dscale = var->dscale;
6026 
6027  /*
6028  * Allocate space for the result.
6029  *
6030  * i is set to the # of decimal digits before decimal point. dscale is the
6031  * # of decimal digits we will print after decimal point. We may generate
6032  * as many as DEC_DIGITS-1 excess digits at the end, and in addition we
6033  * need room for sign, decimal point, null terminator.
6034  */
6035  i = (var->weight + 1) * DEC_DIGITS;
6036  if (i <= 0)
6037  i = 1;
6038 
6039  str = palloc(i + dscale + DEC_DIGITS + 2);
6040  cp = str;
6041 
6042  /*
6043  * Output a dash for negative values
6044  */
6045  if (var->sign == NUMERIC_NEG)
6046  *cp++ = '-';
6047 
6048  /*
6049  * Output all digits before the decimal point
6050  */
6051  if (var->weight < 0)
6052  {
6053  d = var->weight + 1;
6054  *cp++ = '0';
6055  }
6056  else
6057  {
6058  for (d = 0; d <= var->weight; d++)
6059  {
6060  dig = (d < var->ndigits) ? var->digits[d] : 0;
6061  /* In the first digit, suppress extra leading decimal zeroes */
6062 #if DEC_DIGITS == 4
6063  {
6064  bool putit = (d > 0);
6065 
6066  d1 = dig / 1000;
6067  dig -= d1 * 1000;
6068  putit |= (d1 > 0);
6069  if (putit)
6070  *cp++ = d1 + '0';
6071  d1 = dig / 100;
6072  dig -= d1 * 100;
6073  putit |= (d1 > 0);
6074  if (putit)
6075  *cp++ = d1 + '0';
6076  d1 = dig / 10;
6077  dig -= d1 * 10;
6078  putit |= (d1 > 0);
6079  if (putit)
6080  *cp++ = d1 + '0';
6081  *cp++ = dig + '0';
6082  }
6083 #elif DEC_DIGITS == 2
6084  d1 = dig / 10;
6085  dig -= d1 * 10;
6086  if (d1 > 0 || d > 0)
6087  *cp++ = d1 + '0';
6088  *cp++ = dig + '0';
6089 #elif DEC_DIGITS == 1
6090  *cp++ = dig + '0';
6091 #else
6092 #error unsupported NBASE
6093 #endif
6094  }
6095  }
6096 
6097  /*
6098  * If requested, output a decimal point and all the digits that follow it.
6099  * We initially put out a multiple of DEC_DIGITS digits, then truncate if
6100  * needed.
6101  */
6102  if (dscale > 0)
6103  {
6104  *cp++ = '.';
6105  endcp = cp + dscale;
6106  for (i = 0; i < dscale; d++, i += DEC_DIGITS)
6107  {
6108  dig = (d >= 0 && d < var->ndigits) ? var->digits[d] : 0;
6109 #if DEC_DIGITS == 4
6110  d1 = dig / 1000;
6111  dig -= d1 * 1000;
6112  *cp++ = d1 + '0';
6113  d1 = dig / 100;
6114  dig -= d1 * 100;
6115  *cp++ = d1 + '0';
6116  d1 = dig / 10;
6117  dig -= d1 * 10;
6118  *cp++ = d1 + '0';
6119  *cp++ = dig + '0';
6120 #elif DEC_DIGITS == 2
6121  d1 = dig / 10;
6122  dig -= d1 * 10;
6123  *cp++ = d1 + '0';
6124  *cp++ = dig + '0';
6125 #elif DEC_DIGITS == 1
6126  *cp++ = dig + '0';
6127 #else
6128 #error unsupported NBASE
6129 #endif
6130  }
6131  cp = endcp;
6132  }
6133 
6134  /*
6135  * terminate the string and return it
6136  */
6137  *cp = '\0';
6138  return str;
6139 }
int weight
Definition: numeric.c:275
static void error(void)
Definition: sql-dyntest.c:147
int ndigits
Definition: numeric.c:274
int dscale
Definition: numeric.c:277
#define NUMERIC_NEG
Definition: numeric.c:168
int sign
Definition: numeric.c:276
int16 NumericDigit
Definition: numeric.c:102
#define NBASE
Definition: numeric.c:96
NumericDigit * digits
Definition: numeric.c:279
void * palloc(Size size)
Definition: mcxt.c:949
int i
#define DEC_DIGITS
Definition: numeric.c:98

◆ get_str_from_var_sci()

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

Definition at line 6164 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().

6165 {
6166  int32 exponent;
6167  NumericVar denominator;
6168  NumericVar significand;
6169  int denom_scale;
6170  size_t len;
6171  char *str;
6172  char *sig_out;
6173 
6174  if (rscale < 0)
6175  rscale = 0;
6176 
6177  /*
6178  * Determine the exponent of this number in normalised form.
6179  *
6180  * This is the exponent required to represent the number with only one
6181  * significant digit before the decimal place.
6182  */
6183  if (var->ndigits > 0)
6184  {
6185  exponent = (var->weight + 1) * DEC_DIGITS;
6186 
6187  /*
6188  * Compensate for leading decimal zeroes in the first numeric digit by
6189  * decrementing the exponent.
6190  */
6191  exponent -= DEC_DIGITS - (int) log10(var->digits[0]);
6192  }
6193  else
6194  {
6195  /*
6196  * If var has no digits, then it must be zero.
6197  *
6198  * Zero doesn't technically have a meaningful exponent in normalised
6199  * notation, but we just display the exponent as zero for consistency
6200  * of output.
6201  */
6202  exponent = 0;
6203  }
6204 
6205  /*
6206  * The denominator is set to 10 raised to the power of the exponent.
6207  *
6208  * We then divide var by the denominator to get the significand, rounding
6209  * to rscale decimal digits in the process.
6210  */
6211  if (exponent < 0)
6212  denom_scale = -exponent;
6213  else
6214  denom_scale = 0;
6215 
6216  init_var(&denominator);
6217  init_var(&significand);
6218 
6219  power_var_int(&const_ten, exponent, &denominator, denom_scale);
6220  div_var(var, &denominator, &significand, rscale, true);
6221  sig_out = get_str_from_var(&significand);
6222 
6223  free_var(&denominator);
6224  free_var(&significand);
6225 
6226  /*
6227  * Allocate space for the result.
6228  *
6229  * In addition to the significand, we need room for the exponent
6230  * decoration ("e"), the sign of the exponent, up to 10 digits for the
6231  * exponent itself, and of course the null terminator.
6232  */
6233  len = strlen(sig_out) + 13;
6234  str = palloc(len);
6235  snprintf(str, len, "%se%+03d", sig_out, exponent);
6236 
6237  pfree(sig_out);
6238 
6239  return str;
6240 }
int weight
Definition: numeric.c:275
int ndigits
Definition: numeric.c:274
static void div_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result, int rscale, bool round)
Definition: numeric.c:7232
signed int int32
Definition: c.h:347
void pfree(void *pointer)
Definition: mcxt.c:1056
static void power_var_int(const NumericVar *base, int exp, NumericVar *result, int rscale)
Definition: numeric.c:8516
static const NumericVar const_ten
Definition: numeric.c:387
static void free_var(NumericVar *var)
Definition: numeric.c:5735
NumericDigit * digits
Definition: numeric.c:279
void * palloc(Size size)
Definition: mcxt.c:949
static char * get_str_from_var(const NumericVar *var)
Definition: numeric.c:6011
#define DEC_DIGITS
Definition: numeric.c:98
#define snprintf
Definition: port.h:192
#define init_var(v)
Definition: numeric.c:454

◆ hash_numeric()

Datum hash_numeric ( PG_FUNCTION_ARGS  )

Definition at line 2259 of file numeric.c.

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

Referenced by JsonbHashScalarValue().

2260 {
2262  Datum digit_hash;
2263  Datum result;
2264  int weight;
2265  int start_offset;
2266  int end_offset;
2267  int i;
2268  int hash_len;
2270 
2271  /* If it's NaN, don't try to hash the rest of the fields */
2272  if (NUMERIC_IS_NAN(key))
2273  PG_RETURN_UINT32(0);
2274 
2275  weight = NUMERIC_WEIGHT(key);
2276  start_offset = 0;
2277  end_offset = 0;
2278 
2279  /*
2280  * Omit any leading or trailing zeros from the input to the hash. The
2281  * numeric implementation *should* guarantee that leading and trailing
2282  * zeros are suppressed, but we're paranoid. Note that we measure the
2283  * starting and ending offsets in units of NumericDigits, not bytes.
2284  */
2285  digits = NUMERIC_DIGITS(key);
2286  for (i = 0; i < NUMERIC_NDIGITS(key); i++)
2287  {
2288  if (digits[i] != (NumericDigit) 0)
2289  break;
2290 
2291  start_offset++;
2292 
2293  /*
2294  * The weight is effectively the # of digits before the decimal point,
2295  * so decrement it for each leading zero we skip.
2296  */
2297  weight--;
2298  }
2299 
2300  /*
2301  * If there are no non-zero digits, then the value of the number is zero,
2302  * regardless of any other fields.
2303  */
2304  if (NUMERIC_NDIGITS(key) == start_offset)
2305  PG_RETURN_UINT32(-1);
2306 
2307  for (i = NUMERIC_NDIGITS(key) - 1; i >= 0; i--)
2308  {
2309  if (digits[i] != (NumericDigit) 0)
2310  break;
2311 
2312  end_offset++;
2313  }
2314 
2315  /* If we get here, there should be at least one non-zero digit */
2316  Assert(start_offset + end_offset < NUMERIC_NDIGITS(key));
2317 
2318  /*
2319  * Note that we don't hash on the Numeric's scale, since two numerics can
2320  * compare equal but have different scales. We also don't hash on the
2321  * sign, although we could: since a sign difference implies inequality,
2322  * this shouldn't affect correctness.
2323  */
2324  hash_len = NUMERIC_NDIGITS(key) - start_offset - end_offset;
2325  digit_hash = hash_any((unsigned char *) (NUMERIC_DIGITS(key) + start_offset),
2326  hash_len * sizeof(NumericDigit));
2327 
2328  /* Mix in the weight, via XOR */
2329  result = digit_hash ^ weight;
2330 
2331  PG_RETURN_DATUM(result);
2332 }
Datum hash_any(const unsigned char *k, int keylen)
Definition: hashfn.c:148
#define PG_RETURN_UINT32(x)
Definition: fmgr.h:345
#define NUMERIC_DIGITS(num)
Definition: numeric.c:456
int16 NumericDigit
Definition: numeric.c:102
#define NUMERIC_NDIGITS(num)
Definition: numeric.c:458
uintptr_t Datum
Definition: postgres.h:367
#define PG_RETURN_DATUM(x)
Definition: fmgr.h:343
#define NUMERIC_WEIGHT(n)
Definition: numeric.c:217
#define PG_GETARG_NUMERIC(n)
Definition: numeric.h:52
#define Assert(condition)
Definition: c.h:739
int i
#define NUMERIC_IS_NAN(n)
Definition: numeric.c:173
int digits
Definition: informix.c:666

◆ hash_numeric_extended()

Datum hash_numeric_extended ( PG_FUNCTION_ARGS  )

Definition at line 2339 of file numeric.c.

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

Referenced by JsonbHashScalarValueExtended().

2340 {
2342  uint64 seed = PG_GETARG_INT64(1);
2343  Datum digit_hash;
2344  Datum result;
2345  int weight;
2346  int start_offset;
2347  int end_offset;
2348  int i;
2349  int hash_len;
2351 
2352  if (NUMERIC_IS_NAN(key))
2353  PG_RETURN_UINT64(seed);
2354 
2355  weight = NUMERIC_WEIGHT(key);
2356  start_offset = 0;
2357  end_offset = 0;
2358 
2359  digits = NUMERIC_DIGITS(key);
2360  for (i = 0; i < NUMERIC_NDIGITS(key); i++)
2361  {
2362  if (digits[i] != (NumericDigit) 0)
2363  break;
2364 
2365  start_offset++;
2366 
2367  weight--;
2368  }
2369 
2370  if (NUMERIC_NDIGITS(key) == start_offset)
2371  PG_RETURN_UINT64(seed - 1);
2372 
2373  for (i = NUMERIC_NDIGITS(key) - 1; i >= 0; i--)
2374  {
2375  if (digits[i] != (NumericDigit) 0)
2376  break;
2377 
2378  end_offset++;
2379  }
2380 
2381  Assert(start_offset + end_offset < NUMERIC_NDIGITS(key));
2382 
2383  hash_len = NUMERIC_NDIGITS(key) - start_offset - end_offset;
2384  digit_hash = hash_any_extended((unsigned char *) (NUMERIC_DIGITS(key)
2385  + start_offset),
2386  hash_len * sizeof(NumericDigit),
2387  seed);
2388 
2389  result = UInt64GetDatum(DatumGetUInt64(digit_hash) ^ weight);
2390 
2391  PG_RETURN_DATUM(result);
2392 }
#define UInt64GetDatum(X)
Definition: postgres.h:648
Datum hash_any_extended(const unsigned char *k, int keylen, uint64 seed)
Definition: hashfn.c:374
#define PG_RETURN_UINT64(x)
Definition: fmgr.h:358
#define NUMERIC_DIGITS(num)
Definition: numeric.c:456
int16 NumericDigit
Definition: numeric.c:102
#define NUMERIC_NDIGITS(num)
Definition: numeric.c:458
uintptr_t Datum
Definition: postgres.h:367
#define PG_RETURN_DATUM(x)
Definition: fmgr.h:343
#define DatumGetUInt64(X)
Definition: postgres.h:634
#define NUMERIC_WEIGHT(n)
Definition: numeric.c:217
#define PG_GETARG_NUMERIC(n)
Definition: numeric.h:52
#define Assert(condition)
Definition: c.h:739
int i
#define NUMERIC_IS_NAN(n)
Definition: numeric.c:173
#define PG_GETARG_INT64(n)
Definition: fmgr.h:277
int digits
Definition: informix.c:666

◆ in_range_numeric_numeric()

Datum in_range_numeric_numeric ( PG_FUNCTION_ARGS  )

Definition at line 2187 of file numeric.c.

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

2188 {
2190  Numeric base = PG_GETARG_NUMERIC(1);
2191  Numeric offset = PG_GETARG_NUMERIC(2);
2192  bool sub = PG_GETARG_BOOL(3);
2193  bool less = PG_GETARG_BOOL(4);
2194  bool result;
2195 
2196  /*
2197  * Reject negative or NaN offset. Negative is per spec, and NaN is
2198  * because appropriate semantics for that seem non-obvious.
2199  */
2200  if (NUMERIC_IS_NAN(offset) || NUMERIC_SIGN(offset) == NUMERIC_NEG)
2201  ereport(ERROR,
2202  (errcode(ERRCODE_INVALID_PRECEDING_OR_FOLLOWING_SIZE),
2203  errmsg("invalid preceding or following size in window function")));
2204 
2205  /*
2206  * Deal with cases where val and/or base is NaN, following the rule that
2207  * NaN sorts after non-NaN (cf cmp_numerics). The offset cannot affect
2208  * the conclusion.
2209  */
2210  if (NUMERIC_IS_NAN(val))
2211  {
2212  if (NUMERIC_IS_NAN(base))
2213  result = true; /* NAN = NAN */
2214  else
2215  result = !less; /* NAN > non-NAN */
2216  }
2217  else if (NUMERIC_IS_NAN(base))
2218  {
2219  result = less; /* non-NAN < NAN */
2220  }
2221  else
2222  {
2223  /*
2224  * Otherwise go ahead and compute base +/- offset. While it's
2225  * possible for this to overflow the numeric format, it's unlikely
2226  * enough that we don't take measures to prevent it.
2227  */
2228  NumericVar valv;
2229  NumericVar basev;
2230  NumericVar offsetv;
2231  NumericVar sum;
2232 
2233  init_var_from_num(val, &valv);
2234  init_var_from_num(base, &basev);
2235  init_var_from_num(offset, &offsetv);
2236  init_var(&sum);
2237 
2238  if (sub)
2239  sub_var(&basev, &offsetv, &sum);
2240  else
2241  add_var(&basev, &offsetv, &sum);
2242 
2243  if (less)
2244  result = (cmp_var(&valv, &sum) <= 0);
2245  else
2246  result = (cmp_var(&valv, &sum) >= 0);
2247 
2248  free_var(&sum);
2249  }
2250 
2251  PG_FREE_IF_COPY(val, 0);
2252  PG_FREE_IF_COPY(base, 1);
2253  PG_FREE_IF_COPY(offset, 2);
2254 
2255  PG_RETURN_BOOL(result);
2256 }
int errcode(int sqlerrcode)
Definition: elog.c:608
#define PG_GETARG_BOOL(n)
Definition: fmgr.h:269
#define NUMERIC_NEG
Definition: numeric.c:168
#define ERROR
Definition: elog.h:43
static void init_var_from_num(Numeric num, NumericVar *dest)
Definition: numeric.c:5968
#define NUMERIC_SIGN(n)
Definition: numeric.c:209
#define ereport(elevel, rest)
Definition: elog.h:141
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:349
static int cmp_var(const NumericVar *var1, const NumericVar *var2)
Definition: numeric.c:6739
static void free_var(NumericVar *var)
Definition: numeric.c:5735
#define PG_GETARG_NUMERIC(n)
Definition: numeric.h:52
static void add_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition: numeric.c:6797
#define PG_FREE_IF_COPY(ptr, n)
Definition: fmgr.h:255
int errmsg(const char *fmt,...)
Definition: elog.c:822
#define NUMERIC_IS_NAN(n)
Definition: numeric.c:173
static void sub_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition: numeric.c:6914
long val
Definition: informix.c:664
#define init_var(v)
Definition: numeric.c:454

◆ init_var_from_num()

static void init_var_from_num ( Numeric  num,
NumericVar dest 
)
static

Definition at line 5968 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_floor(), numeric_inc(), numeric_int2(), numeric_int4_opt_error(), numeric_int8(), numeric_ln(), numeric_log(), numeric_mod_opt_error(), numeric_mul_opt_error(), numeric_normalize(), numeric_out(), numeric_out_sci(), numeric_poly_deserialize(), numeric_power(), numeric_send(), numeric_sqrt(), and numeric_sub_opt_error().

5969 {
5970  dest->ndigits = NUMERIC_NDIGITS(num);
5971  dest->weight = NUMERIC_WEIGHT(num);
5972  dest->sign = NUMERIC_SIGN(num);
5973  dest->dscale = NUMERIC_DSCALE(num);
5974  dest->digits = NUMERIC_DIGITS(num);
5975  dest->buf = NULL; /* digits array is not palloc'd */
5976 }
#define NUMERIC_DSCALE(n)
Definition: numeric.c:213
int weight
Definition: numeric.c:275
int ndigits
Definition: numeric.c:274
int dscale
Definition: numeric.c:277
int sign
Definition: numeric.c:276
#define NUMERIC_DIGITS(num)
Definition: numeric.c:456
#define NUMERIC_SIGN(n)
Definition: numeric.c:209
NumericDigit * buf
Definition: numeric.c:278
#define NUMERIC_NDIGITS(num)
Definition: numeric.c:458
#define NUMERIC_WEIGHT(n)
Definition: numeric.c:217
NumericDigit * digits
Definition: numeric.c:279

◆ int2_accum()

Datum int2_accum ( PG_FUNCTION_ARGS  )

Definition at line 4266 of file numeric.c.

References DatumGetNumeric, DirectFunctionCall1, do_numeric_accum(), int2_numeric(), makePolyNumAggState, newval, PG_ARGISNULL, PG_GETARG_DATUM, PG_GETARG_INT16, PG_GETARG_POINTER, and PG_RETURN_POINTER.

4267 {
4269 
4270  state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
4271 
4272  /* Create the state data on the first call */
4273  if (state == NULL)
4274  state = makePolyNumAggState(fcinfo, true);
4275 
4276  if (!PG_ARGISNULL(1))
4277  {
4278 #ifdef HAVE_INT128
4279  do_int128_accum(state, (int128) PG_GETARG_INT16(1));
4280 #else
4281  Numeric newval;
4282 
4284  PG_GETARG_DATUM(1)));
4285  do_numeric_accum(state, newval);
4286 #endif
4287  }
4288 
4289  PG_RETURN_POINTER(state);
4290 }
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:351
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:263
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:271
Datum int2_numeric(PG_FUNCTION_ARGS)
Definition: numeric.c:3329
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:615
static void do_numeric_accum(NumericAggState *state, Numeric newval)
Definition: numeric.c:3576
#define PG_GETARG_INT16(n)
Definition: fmgr.h:266
#define PG_ARGISNULL(n)
Definition: fmgr.h:204
#define DatumGetNumeric(X)
Definition: numeric.h:49
Definition: regguts.h:298
#define newval
#define makePolyNumAggState
Definition: numeric.c:4261

◆ int2_accum_inv()

Datum int2_accum_inv ( PG_FUNCTION_ARGS  )

Definition at line 4743 of file numeric.c.

References DatumGetNumeric, DirectFunctionCall1, do_numeric_discard(), elog, ERROR, int2_numeric(), newval, PG_ARGISNULL, PG_GETARG_DATUM, PG_GETARG_INT16, PG_GETARG_POINTER, and PG_RETURN_POINTER.

4744 {
4746 
4747  state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
4748 
4749  /* Should not get here with no state */
4750  if (state == NULL)
4751  elog(ERROR, "int2_accum_inv called with NULL state");
4752 
4753  if (!PG_ARGISNULL(1))
4754  {
4755 #ifdef HAVE_INT128
4756  do_int128_discard(state, (int128) PG_GETARG_INT16(1));
4757 #else
4758  Numeric newval;
4759 
4761  PG_GETARG_DATUM(1)));
4762 
4763  /* Should never fail, all inputs have dscale 0 */
4764  if (!do_numeric_discard(state, newval))
4765  elog(ERROR, "do_numeric_discard failed unexpectedly");
4766 #endif
4767  }
4768 
4769  PG_RETURN_POINTER(state);
4770 }
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:351
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:263
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:271
Datum int2_numeric(PG_FUNCTION_ARGS)
Definition: numeric.c:3329
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:615
static bool do_numeric_discard(NumericAggState *state, Numeric newval)
Definition: numeric.c:3641
#define ERROR
Definition: elog.h:43
#define PG_GETARG_INT16(n)
Definition: fmgr.h:266
#define PG_ARGISNULL(n)
Definition: fmgr.h:204
#define DatumGetNumeric(X)
Definition: numeric.h:49
Definition: regguts.h:298
#define newval
#define elog(elevel,...)
Definition: elog.h:228

◆ int2_avg_accum()

Datum int2_avg_accum ( PG_FUNCTION_ARGS  )

Definition at line 5434 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.

5435 {
5436  ArrayType *transarray;
5438  Int8TransTypeData *transdata;
5439 
5440  /*
5441  * If we're invoked as an aggregate, we can cheat and modify our first
5442  * parameter in-place to reduce palloc overhead. Otherwise we need to make
5443  * a copy of it before scribbling on it.
5444  */
5445  if (AggCheckCallContext(fcinfo, NULL))
5446  transarray = PG_GETARG_ARRAYTYPE_P(0);
5447  else
5448  transarray = PG_GETARG_ARRAYTYPE_P_COPY(0);
5449 
5450  if (ARR_HASNULL(transarray) ||
5451  ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
5452  elog(ERROR, "expected 2-element int8 array");
5453 
5454  transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
5455  transdata->count++;
5456  transdata->sum += newval;
5457 
5458  PG_RETURN_ARRAYTYPE_P(transarray);
5459 }
signed short int16
Definition: c.h:346
#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:266
#define newval
int AggCheckCallContext(FunctionCallInfo fcinfo, MemoryContext *aggcontext)
Definition: nodeAgg.c:3571
#define elog(elevel,...)
Definition: elog.h:228

◆ int2_avg_accum_inv()

Datum int2_avg_accum_inv ( PG_FUNCTION_ARGS  )

Definition at line 5521 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.

5522 {
5523  ArrayType *transarray;
5525  Int8TransTypeData *transdata;
5526 
5527  /*
5528  * If we're invoked as an aggregate, we can cheat and modify our first
5529  * parameter in-place to reduce palloc overhead. Otherwise we need to make
5530  * a copy of it before scribbling on it.
5531  */
5532  if (AggCheckCallContext(fcinfo, NULL))
5533  transarray = PG_GETARG_ARRAYTYPE_P(0);
5534  else
5535  transarray = PG_GETARG_ARRAYTYPE_P_COPY(0);
5536 
5537  if (ARR_HASNULL(transarray) ||
5538  ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
5539  elog(ERROR, "expected 2-element int8 array");
5540 
5541  transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
5542  transdata->count--;
5543  transdata->sum -= newval;
5544 
5545  PG_RETURN_ARRAYTYPE_P(transarray);
5546 }
signed short int16
Definition: c.h:346
#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:266
#define newval
int AggCheckCallContext(FunctionCallInfo fcinfo, MemoryContext *aggcontext)
Definition: nodeAgg.c:3571
#define elog(elevel,...)
Definition: elog.h:228

◆ int2_numeric()

Datum int2_numeric ( PG_FUNCTION_ARGS  )

Definition at line 3329 of file numeric.c.

References free_var(), init_var, int64_to_numericvar(), make_result(), PG_GETARG_INT16, PG_RETURN_NUMERIC, and val.

Referenced by int2_accum(), and int2_accum_inv().

3330 {
3331  int16 val = PG_GETARG_INT16(0);
3332  Numeric res;
3333  NumericVar result;
3334 
3335  init_var(&result);
3336 
3337  int64_to_numericvar((int64) val, &result);
3338 
3339  res = make_result(&result);
3340 
3341  free_var(&result);
3342 
3343  PG_RETURN_NUMERIC(res);
3344 }
#define PG_RETURN_NUMERIC(x)
Definition: numeric.h:54
signed short int16
Definition: c.h:346
#define PG_GETARG_INT16(n)
Definition: fmgr.h:266
static void free_var(NumericVar *var)
Definition: numeric.c:5735
static Numeric make_result(const NumericVar *var)
Definition: numeric.c:6351
static void int64_to_numericvar(int64 val, NumericVar *var)
Definition: numeric.c:6515
long val
Definition: informix.c:664
#define init_var(v)
Definition: numeric.c:454

◆ int2_sum()

Datum int2_sum ( PG_FUNCTION_ARGS  )

Definition at line 5282 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.

5283 {
5284  int64 newval;
5285 
5286  if (PG_ARGISNULL(0))
5287  {
5288  /* No non-null input seen so far... */
5289  if (PG_ARGISNULL(1))
5290  PG_RETURN_NULL(); /* still no non-null */
5291  /* This is the first non-null input. */
5292  newval = (int64) PG_GETARG_INT16(1);
5293  PG_RETURN_INT64(newval);
5294  }
5295 
5296  /*
5297  * If we're invoked as an aggregate, we can cheat and modify our first
5298  * parameter in-place to avoid palloc overhead. If not, we need to return
5299  * the new value of the transition variable. (If int8 is pass-by-value,
5300  * then of course this is useless as well as incorrect, so just ifdef it
5301  * out.)
5302  */
5303 #ifndef USE_FLOAT8_BYVAL /* controls int8 too */
5304  if (AggCheckCallContext(fcinfo, NULL))
5305  {
5306  int64 *oldsum = (int64 *) PG_GETARG_POINTER(0);
5307 
5308  /* Leave the running sum unchanged in the new input is null */
5309  if (!PG_ARGISNULL(1))
5310  *oldsum = *oldsum + (int64) PG_GETARG_INT16(1);
5311 
5312  PG_RETURN_POINTER(oldsum);
5313  }
5314  else
5315 #endif
5316  {
5317  int64 oldsum = PG_GETARG_INT64(0);
5318 
5319  /* Leave sum unchanged if new input is null. */
5320  if (PG_ARGISNULL(1))
5321  PG_RETURN_INT64(oldsum);
5322 
5323  /* OK to do the addition. */
5324  newval = oldsum + (int64) PG_GETARG_INT16(1);
5325 
5326  PG_RETURN_INT64(newval);
5327  }
5328 }
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:351
#define PG_RETURN_INT64(x)
Definition: fmgr.h:357
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:271
#define PG_GETARG_INT16(n)
Definition: fmgr.h:266
#define PG_ARGISNULL(n)
Definition: fmgr.h:204
#define newval
int AggCheckCallContext(FunctionCallInfo fcinfo, MemoryContext *aggcontext)
Definition: nodeAgg.c:3571
#define PG_GETARG_INT64(n)
Definition: fmgr.h:277
#define PG_RETURN_NULL()
Definition: fmgr.h:335

◆ int2int4_sum()

Datum int2int4_sum ( PG_FUNCTION_ARGS  )

Definition at line 5606 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_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.

5607 {
5608  ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
5609  Int8TransTypeData *transdata;
5610 
5611  if (ARR_HASNULL(transarray) ||
5612  ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
5613  elog(ERROR, "expected 2-element int8 array");
5614  transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
5615 
5616  /* SQL defines SUM of no values to be NULL */
5617  if (transdata->count == 0)
5618  PG_RETURN_NULL();
5619 
5620  PG_RETURN_DATUM(Int64GetDatumFast(transdata->sum));
5621 }
#define ARR_OVERHEAD_NONULLS(ndims)
Definition: array.h:298
#define ARR_SIZE(a)
Definition: array.h:277
#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_DATUM(x)
Definition: fmgr.h:343
#define Int64GetDatumFast(X)
Definition: postgres.h:760
#define elog(elevel,...)
Definition: elog.h:228
#define PG_RETURN_NULL()
Definition: fmgr.h:335

◆ int4_accum()

Datum int4_accum ( PG_FUNCTION_ARGS  )

Definition at line 4293 of file numeric.c.

References DatumGetNumeric, DirectFunctionCall1, do_numeric_accum(), int4_numeric(), makePolyNumAggState, newval, PG_ARGISNULL, PG_GETARG_DATUM, PG_GETARG_INT32, PG_GETARG_POINTER, and PG_RETURN_POINTER.

4294 {
4296 
4297  state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
4298 
4299  /* Create the state data on the first call */
4300  if (state == NULL)
4301  state = makePolyNumAggState(fcinfo, true);
4302 
4303  if (!PG_ARGISNULL(1))
4304  {
4305 #ifdef HAVE_INT128
4306  do_int128_accum(state, (int128) PG_GETARG_INT32(1));
4307 #else
4308  Numeric newval;
4309 
4311  PG_GETARG_DATUM(1)));
4312  do_numeric_accum(state, newval);
4313 #endif
4314  }
4315 
4316  PG_RETURN_POINTER(state);
4317 }
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:351
#define PG_GETARG_INT32(n)
Definition: fmgr.h:264
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:263
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:271
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:615
static void do_numeric_accum(NumericAggState *state, Numeric newval)
Definition: numeric.c:3576
Datum int4_numeric(PG_FUNCTION_ARGS)
Definition: numeric.c:3193
#define PG_ARGISNULL(n)
Definition: fmgr.h:204
#define DatumGetNumeric(X)
Definition: numeric.h:49
Definition: regguts.h:298
#define newval
#define makePolyNumAggState
Definition: numeric.c:4261

◆ int4_accum_inv()

Datum int4_accum_inv ( PG_FUNCTION_ARGS  )

Definition at line 4773 of file numeric.c.

References DatumGetNumeric, DirectFunctionCall1, do_numeric_discard(), elog, ERROR, int4_numeric(), newval, PG_ARGISNULL, PG_GETARG_DATUM, PG_GETARG_INT32, PG_GETARG_POINTER, and PG_RETURN_POINTER.

4774 {
4776 
4777  state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
4778 
4779  /* Should not get here with no state */
4780  if (state == NULL)
4781  elog(ERROR, "int4_accum_inv called with NULL state");
4782 
4783  if (!PG_ARGISNULL(1))
4784  {
4785 #ifdef HAVE_INT128
4786  do_int128_discard(state, (int128) PG_GETARG_INT32(1));
4787 #else
4788  Numeric newval;
4789 
4791  PG_GETARG_DATUM(1)));
4792 
4793  /* Should never fail, all inputs have dscale 0 */
4794  if (!do_numeric_discard(state, newval))
4795  elog(ERROR, "do_numeric_discard failed unexpectedly");
4796 #endif
4797  }
4798 
4799  PG_RETURN_POINTER(state);
4800 }
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:351
#define PG_GETARG_INT32(n)
Definition: fmgr.h:264
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:263
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:271
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:615
static bool do_numeric_discard(NumericAggState *state, Numeric newval)
Definition: numeric.c:3641
#define ERROR
Definition: elog.h:43
Datum int4_numeric(PG_FUNCTION_ARGS)
Definition: numeric.c:3193
#define PG_ARGISNULL(n)
Definition: fmgr.h:204
#define DatumGetNumeric(X)
Definition: numeric.h:49
Definition: regguts.h:298
#define newval
#define elog(elevel,...)
Definition: elog.h:228

◆ int4_avg_accum()

Datum int4_avg_accum ( PG_FUNCTION_ARGS  )

Definition at line 5462 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_INT32, PG_RETURN_ARRAYTYPE_P, and Int8TransTypeData::sum.

5463 {
5464  ArrayType *transarray;
5466  Int8TransTypeData *transdata;
5467 
5468  /*
5469  * If we're invoked as an aggregate, we can cheat and modify our first
5470  * parameter in-place to reduce palloc overhead. Otherwise we need to make
5471  * a copy of it before scribbling on it.
5472  */
5473  if (AggCheckCallContext(fcinfo, NULL))
5474  transarray = PG_GETARG_ARRAYTYPE_P(0);
5475  else
5476  transarray = PG_GETARG_ARRAYTYPE_P_COPY(0);
5477 
5478  if (ARR_HASNULL(transarray) ||
5479  ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
5480  elog(ERROR, "expected 2-element int8 array");
5481 
5482  transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
5483  transdata->count++;
5484  transdata->sum += newval;
5485 
5486  PG_RETURN_ARRAYTYPE_P(transarray);
5487 }
#define PG_GETARG_INT32(n)
Definition: fmgr.h:264
#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
signed int int32
Definition: c.h:347
#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 newval
int AggCheckCallContext(FunctionCallInfo fcinfo, MemoryContext *aggcontext)
Definition: nodeAgg.c:3571
#define elog(elevel,...)
Definition: elog.h:228

◆ int4_avg_accum_inv()

Datum int4_avg_accum_inv ( PG_FUNCTION_ARGS  )

Definition at line 5549 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_INT32, PG_RETURN_ARRAYTYPE_P, and Int8TransTypeData::sum.

5550 {
5551  ArrayType *transarray;
5553  Int8TransTypeData *transdata;
5554 
5555  /*
5556  * If we're invoked as an aggregate, we can cheat and modify our first
5557  * parameter in-place to reduce palloc overhead. Otherwise we need to make
5558  * a copy of it before scribbling on it.
5559  */
5560  if (AggCheckCallContext(fcinfo, NULL))
5561  transarray = PG_GETARG_ARRAYTYPE_P(0);
5562  else
5563  transarray = PG_GETARG_ARRAYTYPE_P_COPY(0);
5564 
5565  if (ARR_HASNULL(transarray) ||
5566  ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
5567  elog(ERROR, "expected 2-element int8 array");
5568 
5569  transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
5570  transdata->count--;
5571  transdata->sum -= newval;
5572 
5573  PG_RETURN_ARRAYTYPE_P(transarray);
5574 }
#define PG_GETARG_INT32(n)
Definition: fmgr.h:264
#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
signed int int32
Definition: c.h:347
#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 newval
int AggCheckCallContext(FunctionCallInfo fcinfo, MemoryContext *aggcontext)
Definition: nodeAgg.c:3571
#define elog(elevel,...)
Definition: elog.h:228

◆ int4_avg_combine()

Datum int4_avg_combine ( PG_FUNCTION_ARGS  )

Definition at line 5490 of file numeric.c.

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

5491 {
5492  ArrayType *transarray1;
5493  ArrayType *transarray2;
5494  Int8TransTypeData *state1;
5495  Int8TransTypeData *state2;
5496 
5497  if (!AggCheckCallContext(fcinfo, NULL))
5498  elog(ERROR, "aggregate function called in non-aggregate context");
5499 
5500  transarray1 = PG_GETARG_ARRAYTYPE_P(0);
5501  transarray2 = PG_GETARG_ARRAYTYPE_P(1);
5502 
5503  if (ARR_HASNULL(transarray1) ||
5504  ARR_SIZE(transarray1) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
5505  elog(ERROR, "expected 2-element int8 array");
5506 
5507  if (ARR_HASNULL(transarray2) ||
5508  ARR_SIZE(transarray2) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
5509  elog(ERROR, "expected 2-element int8 array");
5510 
5511  state1 = (Int8TransTypeData *) ARR_DATA_PTR(transarray1);
5512  state2 = (Int8TransTypeData *) ARR_DATA_PTR(transarray2);
5513 
5514  state1->count += state2->count;
5515  state1->sum += state2->sum;
5516 
5517  PG_RETURN_ARRAYTYPE_P(transarray1);
5518 }
#define ARR_OVERHEAD_NONULLS(ndims)
Definition: array.h:298
#define ARR_SIZE(a)
Definition: array.h:277
#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
int AggCheckCallContext(FunctionCallInfo fcinfo, MemoryContext *aggcontext)
Definition: nodeAgg.c:3571
#define elog(elevel,...)
Definition: elog.h:228

◆ int4_numeric()

Datum int4_numeric ( PG_FUNCTION_ARGS  )

Definition at line 3193 of file numeric.c.

References free_var(), init_var, int64_to_numericvar(), make_result(), PG_GETARG_INT32, PG_RETURN_NUMERIC, and val.

Referenced by executeItemOptUnwrapTarget(), gbt_numeric_penalty(), int4_accum(), int4_accum_inv(), numeric_to_char(), and numeric_to_number().

3194 {
3195  int32 val = PG_GETARG_INT32(0);
3196  Numeric res;
3197  NumericVar result;
3198 
3199  init_var(&result);
3200 
3201  int64_to_numericvar((int64) val, &result);
3202 
3203  res = make_result(&result);
3204 
3205  free_var(&result);
3206 
3207  PG_RETURN_NUMERIC(res);
3208 }
#define PG_RETURN_NUMERIC(x)
Definition: numeric.h:54
#define PG_GETARG_INT32(n)
Definition: fmgr.h:264
signed int int32
Definition: c.h:347
static void free_var(NumericVar *var)
Definition: numeric.c:5735
static Numeric make_result(const NumericVar *var)
Definition: numeric.c:6351
static void int64_to_numericvar(int64 val, NumericVar *var)
Definition: numeric.c:6515
long val
Definition: informix.c:664
#define init_var(v)
Definition: numeric.c:454

◆ int4_sum()

Datum int4_sum ( PG_FUNCTION_ARGS  )

Definition at line 5331 of file numeric.c.

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

5332 {
5333  int64 newval;
5334 
5335  if (PG_ARGISNULL(0))
5336  {
5337  /* No non-null input seen so far... */
5338  if (PG_ARGISNULL(1))
5339  PG_RETURN_NULL(); /* still no non-null */
5340  /* This is the first non-null input. */
5341  newval = (int64) PG_GETARG_INT32(1);
5342  PG_RETURN_INT64(newval);
5343  }
5344 
5345  /*
5346  * If we're invoked as an aggregate, we can cheat and modify our first
5347  * parameter in-place to avoid palloc overhead. If not, we need to return
5348  * the new value of the transition variable. (If int8 is pass-by-value,
5349  * then of course this is useless as well as incorrect, so just ifdef it
5350  * out.)
5351  */
5352 #ifndef USE_FLOAT8_BYVAL /* controls int8 too */
5353  if (AggCheckCallContext(fcinfo, NULL))
5354  {
5355  int64 *oldsum = (int64 *) PG_GETARG_POINTER(0);
5356 
5357  /* Leave the running sum unchanged in the new input is null */
5358  if (!PG_ARGISNULL(1))
5359  *oldsum = *oldsum + (int64) PG_GETARG_INT32(1);
5360 
5361  PG_RETURN_POINTER(oldsum);
5362  }
5363  else
5364 #endif
5365  {
5366  int64 oldsum = PG_GETARG_INT64(0);
5367 
5368  /* Leave sum unchanged if new input is null. */
5369  if (PG_ARGISNULL(1))
5370  PG_RETURN_INT64(oldsum);
5371 
5372  /* OK to do the addition. */
5373  newval = oldsum + (int64) PG_GETARG_INT32(1);
5374 
5375  PG_RETURN_INT64(newval);
5376  }
5377 }
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:351
#define PG_GETARG_INT32(n)
Definition: fmgr.h:264
#define PG_RETURN_INT64(x)
Definition: fmgr.h:357
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:271
#define PG_ARGISNULL(n)
Definition: fmgr.h:204
#define newval
int AggCheckCallContext(FunctionCallInfo fcinfo, MemoryContext *aggcontext)
Definition: nodeAgg.c:3571
#define PG_GETARG_INT64(n)
Definition: fmgr.h:277
#define PG_RETURN_NULL()
Definition: fmgr.h:335

◆ int64_to_numericvar()

static void int64_to_numericvar ( int64  val,
NumericVar var 
)
static

Definition at line 6515 of file numeric.c.

References alloc_var(), Assert, DEC_DIGITS, NumericVar::digits, digits, NumericVar::dscale, free_var(), i, init_var, NBASE, NumericVar::ndigits, NUMERIC_NEG, NUMERIC_POS, round_var(), set_var_from_var(), NumericVar::sign, strip_var(), val, and NumericVar::weight.

Referenced by int2_numeric(), int4_numeric(), int8_numeric(), numeric_fac(), numeric_stddev_internal(), and width_bucket_numeric().

6516 {
6517  uint64 uval,
6518  newuval;
6519  NumericDigit *ptr;
6520  int ndigits;
6521 
6522  /* int64 can require at most 19 decimal digits; add one for safety */
6523  alloc_var(var, 20 / DEC_DIGITS);
6524  if (val < 0)
6525  {
6526  var->sign = NUMERIC_NEG;
6527  uval = -val;
6528  }
6529  else
6530  {
6531  var->sign = NUMERIC_POS;
6532  uval = val;
6533  }
6534  var->dscale = 0;
6535  if (val == 0)
6536  {
6537  var->ndigits = 0;
6538  var->weight = 0;
6539  return;
6540  }
6541  ptr = var->digits + var->ndigits;
6542  ndigits = 0;
6543  do
6544  {
6545  ptr--;
6546  ndigits++;
6547  newuval = uval / NBASE;
6548  *ptr = uval - newuval * NBASE;
6549  uval = newuval;
6550  } while (uval);
6551  var->digits = ptr;
6552  var->ndigits = ndigits;
6553  var->weight = ndigits - 1;
6554 }
int weight
Definition: numeric.c:275
#define NUMERIC_POS
Definition: numeric.c:167
int ndigits
Definition: numeric.c:274
int dscale
Definition: numeric.c:277
#define NUMERIC_NEG
Definition: numeric.c:168
int sign
Definition: numeric.c:276
int16 NumericDigit
Definition: numeric.c:102
#define NBASE
Definition: numeric.c:96
NumericDigit * digits
Definition: numeric.c:279
static void alloc_var(NumericVar *var, int ndigits)
Definition: numeric.c:5719
#define DEC_DIGITS
Definition: numeric.c:98
long val
Definition: informix.c:664

◆ int8_accum()

Datum int8_accum ( PG_FUNCTION_ARGS  )

Definition at line 4320 of file numeric.c.

References DatumGetNumeric, DirectFunctionCall1, do_numeric_accum(), int8_numeric(), makeNumericAggState(), newval, PG_ARGISNULL, PG_GETARG_DATUM, PG_GETARG_POINTER, and PG_RETURN_POINTER.

4321 {
4323 
4324  state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
4325 
4326  /* Create the state data on the first call */
4327  if (state == NULL)
4328  state = makeNumericAggState(fcinfo, true);
4329 
4330  if (!PG_ARGISNULL(1))
4331  {
4332  Numeric newval;
4333 
4335  PG_GETARG_DATUM(1)));
4336  do_numeric_accum(state, newval);
4337  }
4338 
4339  PG_RETURN_POINTER(state);
4340 }
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:351
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:263
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:271
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:615
Datum int8_numeric(PG_FUNCTION_ARGS)
Definition: numeric.c:3285
static NumericAggState * makeNumericAggState(FunctionCallInfo fcinfo, bool calcSumX2)
Definition: numeric.c:3536
static void do_numeric_accum(NumericAggState *state, Numeric newval)
Definition: numeric.c:3576
#define PG_ARGISNULL(n)
Definition: fmgr.h:204
#define DatumGetNumeric(X)
Definition: numeric.h:49
Definition: regguts.h:298
#define newval

◆ int8_accum_inv()

Datum int8_accum_inv ( PG_FUNCTION_ARGS  )

Definition at line 4803 of file numeric.c.

References DatumGetNumeric, DirectFunctionCall1, do_numeric_discard(), elog, ERROR, int8_numeric(), newval, PG_ARGISNULL, PG_GETARG_DATUM, PG_GETARG_POINTER, and PG_RETURN_POINTER.

4804 {
4806 
4807  state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
4808 
4809  /* Should not get here with no state */
4810  if (state == NULL)
4811  elog(ERROR, "int8_accum_inv called with NULL state");
4812 
4813  if (!PG_ARGISNULL(1))
4814  {
4815  Numeric newval;
4816 
4818  PG_GETARG_DATUM(1)));
4819 
4820  /* Should never fail, all inputs have dscale 0 */
4821  if (!do_numeric_discard(state, newval))
4822  elog(ERROR, "do_numeric_discard failed unexpectedly");
4823  }
4824 
4825  PG_RETURN_POINTER(state);
4826 }
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:351
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:263
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:271
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:615
static bool do_numeric_discard(NumericAggState *state, Numeric newval)
Definition: numeric.c:3641
Datum int8_numeric(PG_FUNCTION_ARGS)
Definition: numeric.c:3285
#define ERROR
Definition: elog.h:43
#define PG_ARGISNULL(n)
Definition: fmgr.h:204
#define DatumGetNumeric(X)
Definition: numeric.h:49
Definition: regguts.h:298
#define newval
#define elog(elevel,...)
Definition: elog.h:228

◆ int8_avg()

Datum int8_avg ( PG_FUNCTION_ARGS  )

Definition at line 5577 of file numeric.c.

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

5578 {
5579  ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
5580  Int8TransTypeData *transdata;
5581  Datum countd,
5582  sumd;
5583 
5584  if (ARR_HASNULL(transarray) ||
5585  ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
5586  elog(ERROR, "expected 2-element int8 array");
5587  transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
5588