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 "access/hash.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 "utils/array.h"
#include "utils/builtins.h"
#include "utils/guc.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 void apply_typmod (NumericVar *var, int32 typmod)
 
static int32 numericvar_to_int32 (const NumericVar *var)
 
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_transform (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)
 
Datum numeric_sub (PG_FUNCTION_ARGS)
 
Datum numeric_mul (PG_FUNCTION_ARGS)
 
Datum numeric_div (PG_FUNCTION_ARGS)
 
Datum numeric_div_trunc (PG_FUNCTION_ARGS)
 
Datum numeric_mod (PG_FUNCTION_ARGS)
 
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)
 
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 362 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 444 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 446 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 98 of file numeric.c.

Referenced by div_var_fast().

◆ dump_numeric

#define dump_numeric (   s,
 
)

Definition at line 440 of file numeric.c.

Referenced by int2int4_sum(), and make_result().

◆ dump_var

#define dump_var (   s,
 
)

Definition at line 441 of file numeric.c.

Referenced by int2int4_sum().

◆ HALF_NBASE

#define HALF_NBASE   5000

Definition at line 95 of file numeric.c.

Referenced by div_var(), and round_var().

◆ init_var

◆ makePolyNumAggState

#define makePolyNumAggState   makeNumericAggState

◆ makePolyNumAggStateCurrentContext

#define makePolyNumAggStateCurrentContext   makeNumericAggStateCurrentContext

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

Referenced by mul_var().

◆ NBASE

◆ NUMERIC_ABBREV_BITS

#define NUMERIC_ABBREV_BITS   (SIZEOF_DATUM * BITS_PER_BYTE)

Definition at line 355 of file numeric.c.

◆ NUMERIC_ABBREV_NAN

#define NUMERIC_ABBREV_NAN   NumericAbbrevGetDatum(PG_INT32_MIN)

Definition at line 363 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:198
int scale
Definition: pgbench.c:121
#define NUMERIC_SHORT_WEIGHT_MIN
Definition: numeric.c:199
#define NUMERIC_SHORT_DSCALE_MAX
Definition: numeric.c:194

Definition at line 458 of file numeric.c.

Referenced by make_result(), 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:182

Definition at line 454 of file numeric.c.

Referenced by cmp_numerics(), hash_numeric(), hash_numeric_extended(), init_var_from_num(), int2int4_sum(), make_result(), 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:182
#define NUMERIC_DSCALE_MASK
Definition: numeric.c:205
#define NUMERIC_SHORT_DSCALE_MASK
Definition: numeric.c:192
#define NUMERIC_SHORT_DSCALE_SHIFT
Definition: numeric.c:193

Definition at line 211 of file numeric.c.

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

◆ NUMERIC_DSCALE_MASK

#define NUMERIC_DSCALE_MASK   0x3FFF

Definition at line 205 of file numeric.c.

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

◆ NUMERIC_FLAGBITS

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

Definition at line 170 of file numeric.c.

◆ NUMERIC_HDRSZ

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

Definition at line 174 of file numeric.c.

Referenced by make_result(), and numeric_maximum_size().

◆ NUMERIC_HDRSZ_SHORT

#define NUMERIC_HDRSZ_SHORT   (VARHDRSZ + sizeof(uint16))

Definition at line 175 of file numeric.c.

Referenced by make_result().

◆ NUMERIC_HEADER_IS_SHORT

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

Definition at line 182 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:312
#define NUMERIC_HEADER_IS_SHORT(n)
Definition: numeric.c:182
#define VARHDRSZ
Definition: c.h:522
unsigned short uint16
Definition: c.h:324

Definition at line 183 of file numeric.c.

◆ NUMERIC_IS_NAN

◆ NUMERIC_IS_SHORT

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

Definition at line 172 of file numeric.c.

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

◆ NUMERIC_NAN

#define NUMERIC_NAN   0xC000

◆ NUMERIC_NDIGITS

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

◆ NUMERIC_NEG

◆ NUMERIC_POS

◆ NUMERIC_SHORT

#define NUMERIC_SHORT   0x8000

Definition at line 167 of file numeric.c.

Referenced by make_result().

◆ NUMERIC_SHORT_DSCALE_MASK

#define NUMERIC_SHORT_DSCALE_MASK   0x1F80

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

◆ NUMERIC_SHORT_DSCALE_SHIFT

#define NUMERIC_SHORT_DSCALE_SHIFT   7

Definition at line 193 of file numeric.c.

Referenced by make_result(), and numeric().

◆ NUMERIC_SHORT_SIGN_MASK

#define NUMERIC_SHORT_SIGN_MASK   0x2000

Definition at line 191 of file numeric.c.

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

◆ NUMERIC_SHORT_WEIGHT_MASK

#define NUMERIC_SHORT_WEIGHT_MASK   0x003F

Definition at line 197 of file numeric.c.

Referenced by make_result().

◆ NUMERIC_SHORT_WEIGHT_MAX

#define NUMERIC_SHORT_WEIGHT_MAX   NUMERIC_SHORT_WEIGHT_MASK

Definition at line 198 of file numeric.c.

◆ NUMERIC_SHORT_WEIGHT_MIN

#define NUMERIC_SHORT_WEIGHT_MIN   (-(NUMERIC_SHORT_WEIGHT_MASK+1))

Definition at line 199 of file numeric.c.

◆ NUMERIC_SHORT_WEIGHT_SIGN_MASK

#define NUMERIC_SHORT_WEIGHT_SIGN_MASK   0x0040

Definition at line 196 of file numeric.c.

Referenced by make_result().

◆ 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:165
#define NUMERIC_FLAGBITS(n)
Definition: numeric.c:170
#define NUMERIC_SHORT_SIGN_MASK
Definition: numeric.c:191
#define NUMERIC_IS_SHORT(n)
Definition: numeric.c:172

Definition at line 207 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 164 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:182
#define NUMERIC_SHORT_WEIGHT_SIGN_MASK
Definition: numeric.c:196
#define NUMERIC_SHORT_WEIGHT_MASK
Definition: numeric.c:197

Definition at line 215 of file numeric.c.

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

◆ NumericAbbrevGetDatum

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

Definition at line 361 of file numeric.c.

Referenced by numeric_cmp_abbrev().

Typedef Documentation

◆ Int8TransTypeData

◆ NumericAggState

◆ NumericDigit

Definition at line 100 of file numeric.c.

◆ NumericSumAccum

◆ NumericVar

◆ PolyNumAggState

Definition at line 4107 of file numeric.c.

Function Documentation

◆ accum_sum_add()

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

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

8997 {
8998  int32 *accum_digits;
8999  int i,
9000  val_i;
9001  int val_ndigits;
9002  NumericDigit *val_digits;
9003 
9004  /*
9005  * If we have accumulated too many values since the last carry
9006  * propagation, do it now, to avoid overflowing. (We could allow more
9007  * than NBASE - 1, if we reserved two extra digits, rather than one, for
9008  * carry propagation. But even with NBASE - 1, this needs to be done so
9009  * seldom, that the performance difference is negligible.)
9010  */
9011  if (accum->num_uncarried == NBASE - 1)
9012  accum_sum_carry(accum);
9013 
9014  /*
9015  * Adjust the weight or scale of the old value, so that it can accommodate
9016  * the new value.
9017  */
9018  accum_sum_rescale(accum, val);
9019 
9020  /* */
9021  if (val->sign == NUMERIC_POS)
9022  accum_digits = accum->pos_digits;
9023  else
9024  accum_digits = accum->neg_digits;
9025 
9026  /* copy these values into local vars for speed in loop */
9027  val_ndigits = val->ndigits;
9028  val_digits = val->digits;
9029 
9030  i = accum->weight - val->weight;
9031  for (val_i = 0; val_i < val_ndigits; val_i++)
9032  {
9033  accum_digits[i] += (int32) val_digits[val_i];
9034  i++;
9035  }
9036 
9037  accum->num_uncarried++;
9038 }
static void accum_sum_rescale(NumericSumAccum *accum, const NumericVar *val)
Definition: numeric.c:9117
#define NUMERIC_POS
Definition: numeric.c:165
int32 * neg_digits
Definition: numeric.c:345
int num_uncarried
Definition: numeric.c:342
static void accum_sum_carry(NumericSumAccum *accum)
Definition: numeric.c:9044
signed int int32
Definition: c.h:313
int16 NumericDigit
Definition: numeric.c:100
#define NBASE
Definition: numeric.c:94
int i
int32 * pos_digits
Definition: numeric.c:344
long val
Definition: informix.c:689

◆ accum_sum_carry()

static void accum_sum_carry ( NumericSumAccum accum)
static

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

9045 {
9046  int i;
9047  int ndigits;
9048  int32 *dig;
9049  int32 carry;
9050  int32 newdig = 0;
9051 
9052  /*
9053  * If no new values have been added since last carry propagation, nothing
9054  * to do.
9055  */
9056  if (accum->num_uncarried == 0)
9057  return;
9058 
9059  /*
9060  * We maintain that the weight of the accumulator is always one larger
9061  * than needed to hold the current value, before carrying, to make sure
9062  * there is enough space for the possible extra digit when carry is
9063  * propagated. We cannot expand the buffer here, unless we require
9064  * callers of accum_sum_final() to switch to the right memory context.
9065  */
9066  Assert(accum->pos_digits[0] == 0 && accum->neg_digits[0] == 0);
9067 
9068  ndigits = accum->ndigits;
9069 
9070  /* Propagate carry in the positive sum */
9071  dig = accum->pos_digits;
9072  carry = 0;
9073  for (i = ndigits - 1; i >= 0; i--)
9074  {
9075  newdig = dig[i] + carry;
9076  if (newdig >= NBASE)
9077  {
9078  carry = newdig / NBASE;
9079  newdig -= carry * NBASE;
9080  }
9081  else
9082  carry = 0;
9083  dig[i] = newdig;
9084  }
9085  /* Did we use up the digit reserved for carry propagation? */
9086  if (newdig > 0)
9087  accum->have_carry_space = false;
9088 
9089  /* And the same for the negative sum */
9090  dig = accum->neg_digits;
9091  carry = 0;
9092  for (i = ndigits - 1; i >= 0; i--)
9093  {
9094  newdig = dig[i] + carry;
9095  if (newdig >= NBASE)
9096  {
9097  carry = newdig / NBASE;
9098  newdig -= carry * NBASE;
9099  }
9100  else
9101  carry = 0;
9102  dig[i] = newdig;
9103  }
9104  if (newdig > 0)
9105  accum->have_carry_space = false;
9106 
9107  accum->num_uncarried = 0;
9108 }
int32 * neg_digits
Definition: numeric.c:345
int num_uncarried
Definition: numeric.c:342
signed int int32
Definition: c.h:313
bool have_carry_space
Definition: numeric.c:343
#define NBASE
Definition: numeric.c:94
#define Assert(condition)
Definition: c.h:699
int i
int32 * pos_digits
Definition: numeric.c:344

◆ accum_sum_combine()

static void accum_sum_combine ( NumericSumAccum accum,
NumericSumAccum accum2 
)
static

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

9275 {
9276  NumericVar tmp_var;
9277 
9278  init_var(&tmp_var);
9279 
9280  accum_sum_final(accum2, &tmp_var);
9281  accum_sum_add(accum, &tmp_var);
9282 
9283  free_var(&tmp_var);
9284 }
static void accum_sum_final(NumericSumAccum *accum, NumericVar *result)
Definition: numeric.c:9206
static void accum_sum_add(NumericSumAccum *accum, const NumericVar *var1)
Definition: numeric.c:8996
static void free_var(NumericVar *var)
Definition: numeric.c:5582
#define init_var(v)
Definition: numeric.c:452

◆ accum_sum_copy()

static void accum_sum_copy ( NumericSumAccum dst,
NumericSumAccum src 
)
static

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

9258 {
9259  dst->pos_digits = palloc(src->ndigits * sizeof(int32));
9260  dst->neg_digits = palloc(src->ndigits * sizeof(int32));
9261 
9262  memcpy(dst->pos_digits, src->pos_digits, src->ndigits * sizeof(int32));
9263  memcpy(dst->neg_digits, src->neg_digits, src->ndigits * sizeof(int32));
9264  dst->num_uncarried = src->num_uncarried;
9265  dst->ndigits = src->ndigits;
9266  dst->weight = src->weight;
9267  dst->dscale = src->dscale;
9268 }
int32 * neg_digits
Definition: numeric.c:345
int num_uncarried
Definition: numeric.c:342
signed int int32
Definition: c.h:313
void * palloc(Size size)
Definition: mcxt.c:924
int32 * pos_digits
Definition: numeric.c:344

◆ accum_sum_final()

static void accum_sum_final ( NumericSumAccum accum,
NumericVar result 
)
static

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

9207 {
9208  int i;
9209  NumericVar pos_var;
9210  NumericVar neg_var;
9211 
9212  if (accum->ndigits == 0)
9213  {
9214  set_var_from_var(&const_zero, result);
9215  return;
9216  }
9217 
9218  /* Perform final carry */
9219  accum_sum_carry(accum);
9220 
9221  /* Create NumericVars representing the positive and negative sums */
9222  init_var(&pos_var);
9223  init_var(&neg_var);
9224 
9225  pos_var.ndigits = neg_var.ndigits = accum->ndigits;
9226  pos_var.weight = neg_var.weight = accum->weight;
9227  pos_var.dscale = neg_var.dscale = accum->dscale;
9228  pos_var.sign = NUMERIC_POS;
9229  neg_var.sign = NUMERIC_NEG;
9230 
9231  pos_var.buf = pos_var.digits = digitbuf_alloc(accum->ndigits);
9232  neg_var.buf = neg_var.digits = digitbuf_alloc(accum->ndigits);
9233 
9234  for (i = 0; i < accum->ndigits; i++)
9235  {
9236  Assert(accum->pos_digits[i] < NBASE);
9237  pos_var.digits[i] = (int16) accum->pos_digits[i];
9238 
9239  Assert(accum->neg_digits[i] < NBASE);
9240  neg_var.digits[i] = (int16) accum->neg_digits[i];
9241  }
9242 
9243  /* And add them together */
9244  add_var(&pos_var, &neg_var, result);
9245 
9246  /* Remove leading/trailing zeroes */
9247  strip_var(result);
9248 }
signed short int16
Definition: c.h:312
int weight
Definition: numeric.c:273
#define NUMERIC_POS
Definition: numeric.c:165
static void strip_var(NumericVar *var)
Definition: numeric.c:8939
int32 * neg_digits
Definition: numeric.c:345
#define digitbuf_alloc(ndigits)
Definition: numeric.c:444
int ndigits
Definition: numeric.c:272
static void accum_sum_carry(NumericSumAccum *accum)
Definition: numeric.c:9044
int dscale
Definition: numeric.c:275
#define NUMERIC_NEG
Definition: numeric.c:166
int sign
Definition: numeric.c:274
NumericDigit * buf
Definition: numeric.c:276
#define NBASE
Definition: numeric.c:94
static const NumericVar const_zero
Definition: numeric.c:372
#define Assert(condition)
Definition: c.h:699
NumericDigit * digits
Definition: numeric.c:277
static void add_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition: numeric.c:6617
int i
static void set_var_from_var(const NumericVar *value, NumericVar *dest)
Definition: numeric.c:5832
int32 * pos_digits
Definition: numeric.c:344
#define init_var(v)
Definition: numeric.c:452

◆ accum_sum_rescale()

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

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

9118 {
9119  int old_weight = accum->weight;
9120  int old_ndigits = accum->ndigits;
9121  int accum_ndigits;
9122  int accum_weight;
9123  int accum_rscale;
9124  int val_rscale;
9125 
9126  accum_weight = old_weight;
9127  accum_ndigits = old_ndigits;
9128 
9129  /*
9130  * Does the new value have a larger weight? If so, enlarge the buffers,
9131  * and shift the existing value to the new weight, by adding leading
9132  * zeros.
9133  *
9134  * We enforce that the accumulator always has a weight one larger than
9135  * needed for the inputs, so that we have space for an extra digit at the
9136  * final carry-propagation phase, if necessary.
9137  */
9138  if (val->weight >= accum_weight)
9139  {
9140  accum_weight = val->weight + 1;
9141  accum_ndigits = accum_ndigits + (accum_weight - old_weight);
9142  }
9143 
9144  /*
9145  * Even though the new value is small, we might've used up the space
9146  * reserved for the carry digit in the last call to accum_sum_carry(). If
9147  * so, enlarge to make room for another one.
9148  */
9149  else if (!accum->have_carry_space)
9150  {
9151  accum_weight++;
9152  accum_ndigits++;
9153  }
9154 
9155  /* Is the new value wider on the right side? */
9156  accum_rscale = accum_ndigits - accum_weight - 1;
9157  val_rscale = val->ndigits - val->weight - 1;
9158  if (val_rscale > accum_rscale)
9159  accum_ndigits = accum_ndigits + (val_rscale - accum_rscale);
9160 
9161  if (accum_ndigits != old_ndigits ||
9162  accum_weight != old_weight)
9163  {
9164  int32 *new_pos_digits;
9165  int32 *new_neg_digits;
9166  int weightdiff;
9167 
9168  weightdiff = accum_weight - old_weight;
9169 
9170  new_pos_digits = palloc0(accum_ndigits * sizeof(int32));
9171  new_neg_digits = palloc0(accum_ndigits * sizeof(int32));
9172 
9173  if (accum->pos_digits)
9174  {
9175  memcpy(&new_pos_digits[weightdiff], accum->pos_digits,
9176  old_ndigits * sizeof(int32));
9177  pfree(accum->pos_digits);
9178 
9179  memcpy(&new_neg_digits[weightdiff], accum->neg_digits,
9180  old_ndigits * sizeof(int32));
9181  pfree(accum->neg_digits);
9182  }
9183 
9184  accum->pos_digits = new_pos_digits;
9185  accum->neg_digits = new_neg_digits;
9186 
9187  accum->weight = accum_weight;
9188  accum->ndigits = accum_ndigits;
9189 
9190  Assert(accum->pos_digits[0] == 0 && accum->neg_digits[0] == 0);
9191  accum->have_carry_space = true;
9192  }
9193 
9194  if (val->dscale > accum->dscale)
9195  accum->dscale = val->dscale;
9196 }
int weight
Definition: numeric.c:273
int32 * neg_digits
Definition: numeric.c:345
int ndigits
Definition: numeric.c:272
int dscale
Definition: numeric.c:275
signed int int32
Definition: c.h:313
void pfree(void *pointer)
Definition: mcxt.c:1031
bool have_carry_space
Definition: numeric.c:343
void * palloc0(Size size)
Definition: mcxt.c:955
#define Assert(condition)
Definition: c.h:699
int32 * pos_digits
Definition: numeric.c:344

◆ accum_sum_reset()

static void accum_sum_reset ( NumericSumAccum accum)
static

Definition at line 8980 of file numeric.c.

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

Referenced by do_numeric_discard().

8981 {
8982  int i;
8983 
8984  accum->dscale = 0;
8985  for (i = 0; i < accum->ndigits; i++)
8986  {
8987  accum->pos_digits[i] = 0;
8988  accum->neg_digits[i] = 0;
8989  }
8990 }
int32 * neg_digits
Definition: numeric.c:345
int i
int32 * pos_digits
Definition: numeric.c:344

◆ add_abs()

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

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

8605 {
8606  NumericDigit *res_buf;
8607  NumericDigit *res_digits;
8608  int res_ndigits;
8609  int res_weight;
8610  int res_rscale,
8611  rscale1,
8612  rscale2;
8613  int res_dscale;
8614  int i,
8615  i1,
8616  i2;
8617  int carry = 0;
8618 
8619  /* copy these values into local vars for speed in inner loop */
8620  int var1ndigits = var1->ndigits;
8621  int var2ndigits = var2->ndigits;
8622  NumericDigit *var1digits = var1->digits;
8623  NumericDigit *var2digits = var2->digits;
8624 
8625  res_weight = Max(var1->weight, var2->weight) + 1;
8626 
8627  res_dscale = Max(var1->dscale, var2->dscale);
8628 
8629  /* Note: here we are figuring rscale in base-NBASE digits */
8630  rscale1 = var1->ndigits - var1->weight - 1;
8631  rscale2 = var2->ndigits - var2->weight - 1;
8632  res_rscale = Max(rscale1, rscale2);
8633 
8634  res_ndigits = res_rscale + res_weight + 1;
8635  if (res_ndigits <= 0)
8636  res_ndigits = 1;
8637 
8638  res_buf = digitbuf_alloc(res_ndigits + 1);
8639  res_buf[0] = 0; /* spare digit for later rounding */
8640  res_digits = res_buf + 1;
8641 
8642  i1 = res_rscale + var1->weight + 1;
8643  i2 = res_rscale + var2->weight + 1;
8644  for (i = res_ndigits - 1; i >= 0; i--)
8645  {
8646  i1--;
8647  i2--;
8648  if (i1 >= 0 && i1 < var1ndigits)
8649  carry += var1digits[i1];
8650  if (i2 >= 0 && i2 < var2ndigits)
8651  carry += var2digits[i2];
8652 
8653  if (carry >= NBASE)
8654  {
8655  res_digits[i] = carry - NBASE;
8656  carry = 1;
8657  }
8658  else
8659  {
8660  res_digits[i] = carry;
8661  carry = 0;
8662  }
8663  }
8664 
8665  Assert(carry == 0); /* else we failed to allow for carry out */
8666 
8667  digitbuf_free(result->buf);
8668  result->ndigits = res_ndigits;
8669  result->buf = res_buf;
8670  result->digits = res_digits;
8671  result->weight = res_weight;
8672  result->dscale = res_dscale;
8673 
8674  /* Remove leading/trailing zeroes */
8675  strip_var(result);
8676 }
int weight
Definition: numeric.c:273
static void strip_var(NumericVar *var)
Definition: numeric.c:8939
#define digitbuf_alloc(ndigits)
Definition: numeric.c:444
int ndigits
Definition: numeric.c:272
int dscale
Definition: numeric.c:275
#define digitbuf_free(buf)
Definition: numeric.c:446
int16 NumericDigit
Definition: numeric.c:100
NumericDigit * buf
Definition: numeric.c:276
#define NBASE
Definition: numeric.c:94
#define Assert(condition)
Definition: c.h:699
NumericDigit * digits
Definition: numeric.c:277
int i
#define Max(x, y)
Definition: numeric.c:11

◆ add_var()

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

Definition at line 6617 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(), numeric_inc(), sqrt_var(), and width_bucket_numeric().

6618 {
6619  /*
6620  * Decide on the signs of the two variables what to do
6621  */
6622  if (var1->sign == NUMERIC_POS)
6623  {
6624  if (var2->sign == NUMERIC_POS)
6625  {
6626  /*
6627  * Both are positive result = +(ABS(var1) + ABS(var2))
6628  */
6629  add_abs(var1, var2, result);
6630  result->sign = NUMERIC_POS;
6631  }
6632  else
6633  {
6634  /*
6635  * var1 is positive, var2 is negative Must compare absolute values
6636  */
6637  switch (cmp_abs(var1, var2))
6638  {
6639  case 0:
6640  /* ----------
6641  * ABS(var1) == ABS(var2)
6642  * result = ZERO
6643  * ----------
6644  */
6645  zero_var(result);
6646  result->dscale = Max(var1->dscale, var2->dscale);
6647  break;
6648 
6649  case 1:
6650  /* ----------
6651  * ABS(var1) > ABS(var2)
6652  * result = +(ABS(var1) - ABS(var2))
6653  * ----------
6654  */
6655  sub_abs(var1, var2, result);
6656  result->sign = NUMERIC_POS;
6657  break;
6658 
6659  case -1:
6660  /* ----------
6661  * ABS(var1) < ABS(var2)
6662  * result = -(ABS(var2) - ABS(var1))
6663  * ----------
6664  */
6665  sub_abs(var2, var1, result);
6666  result->sign = NUMERIC_NEG;
6667  break;
6668  }
6669  }
6670  }
6671  else
6672  {
6673  if (var2->sign == NUMERIC_POS)
6674  {
6675  /* ----------
6676  * var1 is negative, var2 is positive
6677  * Must compare absolute values
6678  * ----------
6679  */
6680  switch (cmp_abs(var1, var2))
6681  {
6682  case 0:
6683  /* ----------
6684  * ABS(var1) == ABS(var2)
6685  * result = ZERO
6686  * ----------
6687  */
6688  zero_var(result);
6689  result->dscale = Max(var1->dscale, var2->dscale);
6690  break;
6691 
6692  case 1:
6693  /* ----------
6694  * ABS(var1) > ABS(var2)
6695  * result = -(ABS(var1) - ABS(var2))
6696  * ----------
6697  */
6698  sub_abs(var1, var2, result);
6699  result->sign = NUMERIC_NEG;
6700  break;
6701 
6702  case -1:
6703  /* ----------
6704  * ABS(var1) < ABS(var2)
6705  * result = +(ABS(var2) - ABS(var1))
6706  * ----------
6707  */
6708  sub_abs(var2, var1, result);
6709  result->sign = NUMERIC_POS;
6710  break;
6711  }
6712  }
6713  else
6714  {
6715  /* ----------
6716  * Both are negative
6717  * result = -(ABS(var1) + ABS(var2))
6718  * ----------
6719  */
6720  add_abs(var1, var2, result);
6721  result->sign = NUMERIC_NEG;
6722  }
6723  }
6724 }
static void sub_abs(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition: numeric.c:8689
static void add_abs(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition: numeric.c:8604
#define NUMERIC_POS
Definition: numeric.c:165
int dscale
Definition: numeric.c:275
#define NUMERIC_NEG
Definition: numeric.c:166
int sign
Definition: numeric.c:274
static void zero_var(NumericVar *var)
Definition: numeric.c:5598
static int cmp_abs(const NumericVar *var1, const NumericVar *var2)
Definition: numeric.c:8526
#define Max(x, y)
Definition: numeric.c:11

◆ alloc_var()

static void alloc_var ( NumericVar var,
int  ndigits 
)
static

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

5567 {
5568  digitbuf_free(var->buf);
5569  var->buf = digitbuf_alloc(ndigits + 1);
5570  var->buf[0] = 0; /* spare digit for rounding */
5571  var->digits = var->buf + 1;
5572  var->ndigits = ndigits;
5573 }
#define digitbuf_alloc(ndigits)
Definition: numeric.c:444
int ndigits
Definition: numeric.c:272
#define digitbuf_free(buf)
Definition: numeric.c:446
NumericDigit * buf
Definition: numeric.c:276
NumericDigit * digits
Definition: numeric.c:277

◆ apply_typmod()

static void apply_typmod ( NumericVar var,
int32  typmod 
)
static

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

6185 {
6186  int precision;
6187  int scale;
6188  int maxdigits;
6189  int ddigits;
6190  int i;
6191 
6192  /* Do nothing if we have a default typmod (-1) */
6193  if (typmod < (int32) (VARHDRSZ))
6194  return;
6195 
6196  typmod -= VARHDRSZ;
6197  precision = (typmod >> 16) & 0xffff;
6198  scale = typmod & 0xffff;
6199  maxdigits = precision - scale;
6200 
6201  /* Round to target scale (and set var->dscale) */
6202  round_var(var, scale);
6203 
6204  /*
6205  * Check for overflow - note we can't do this before rounding, because
6206  * rounding could raise the weight. Also note that the var's weight could
6207  * be inflated by leading zeroes, which will be stripped before storage
6208  * but perhaps might not have been yet. In any case, we must recognize a
6209  * true zero, whose weight doesn't mean anything.
6210  */
6211  ddigits = (var->weight + 1) * DEC_DIGITS;
6212  if (ddigits > maxdigits)
6213  {
6214  /* Determine true weight; and check for all-zero result */
6215  for (i = 0; i < var->ndigits; i++)
6216  {
6217  NumericDigit dig = var->digits[i];
6218 
6219  if (dig)
6220  {
6221  /* Adjust for any high-order decimal zero digits */
6222 #if DEC_DIGITS == 4
6223  if (dig < 10)
6224  ddigits -= 3;
6225  else if (dig < 100)
6226  ddigits -= 2;
6227  else if (dig < 1000)
6228  ddigits -= 1;
6229 #elif DEC_DIGITS == 2
6230  if (dig < 10)
6231  ddigits -= 1;
6232 #elif DEC_DIGITS == 1
6233  /* no adjustment */
6234 #else
6235 #error unsupported NBASE
6236 #endif
6237  if (ddigits > maxdigits)
6238  ereport(ERROR,
6239  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
6240  errmsg("numeric field overflow"),
6241  errdetail("A field with precision %d, scale %d must round to an absolute value less than %s%d.",
6242  precision, scale,
6243  /* Display 10^0 as 1 */
6244  maxdigits ? "10^" : "",
6245  maxdigits ? maxdigits : 1
6246  )));
6247  break;
6248  }
6249  ddigits -= DEC_DIGITS;
6250  }
6251  }
6252 }
static void round_var(NumericVar *var, int rscale)
Definition: numeric.c:8771
int weight
Definition: numeric.c:273
#define VARHDRSZ
Definition: c.h:522
int errcode(int sqlerrcode)
Definition: elog.c:575
int scale
Definition: pgbench.c:121
int ndigits
Definition: numeric.c:272
signed int int32
Definition: c.h:313
#define ERROR
Definition: elog.h:43
int16 NumericDigit
Definition: numeric.c:100
int errdetail(const char *fmt,...)
Definition: elog.c:873
#define ereport(elevel, rest)
Definition: elog.h:122
int maxdigits
Definition: informix.c:690
NumericDigit * digits
Definition: numeric.c:277
int errmsg(const char *fmt,...)
Definition: elog.c:797
int i
#define DEC_DIGITS
Definition: numeric.c:96

◆ ceil_var()

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

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

7731 {
7732  NumericVar tmp;
7733 
7734  init_var(&tmp);
7735  set_var_from_var(var, &tmp);
7736 
7737  trunc_var(&tmp, 0);
7738 
7739  if (var->sign == NUMERIC_POS && cmp_var(var, &tmp) != 0)
7740  add_var(&tmp, &const_one, &tmp);
7741 
7742  set_var_from_var(&tmp, result);
7743  free_var(&tmp);
7744 }
static void trunc_var(NumericVar *var, int rscale)
Definition: numeric.c:8877
static const NumericVar const_one
Definition: numeric.c:376
#define NUMERIC_POS
Definition: numeric.c:165
int sign
Definition: numeric.c:274
static int cmp_var(const NumericVar *var1, const NumericVar *var2)
Definition: numeric.c:6559
static void free_var(NumericVar *var)
Definition: numeric.c:5582
static void add_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition: numeric.c:6617
static void set_var_from_var(const NumericVar *value, NumericVar *dest)
Definition: numeric.c:5832
#define init_var(v)
Definition: numeric.c:452

◆ cmp_abs()

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

Definition at line 8526 of file numeric.c.

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

Referenced by add_var(), and sub_var().

8527 {
8528  return cmp_abs_common(var1->digits, var1->ndigits, var1->weight,
8529  var2->digits, var2->ndigits, var2->weight);
8530 }
int weight
Definition: numeric.c:273
int ndigits
Definition: numeric.c:272
NumericDigit * digits
Definition: numeric.c:277
static int cmp_abs_common(const NumericDigit *var1digits, int var1ndigits, int var1weight, const NumericDigit *var2digits, int var2ndigits, int var2weight)
Definition: numeric.c:8540

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

References stat.

Referenced by cmp_abs(), and cmp_var_common().

8542 {
8543  int i1 = 0;
8544  int i2 = 0;
8545 
8546  /* Check any digits before the first common digit */
8547 
8548  while (var1weight > var2weight && i1 < var1ndigits)
8549  {
8550  if (var1digits[i1++] != 0)
8551  return 1;
8552  var1weight--;
8553  }
8554  while (var2weight > var1weight && i2 < var2ndigits)
8555  {
8556  if (var2digits[i2++] != 0)
8557  return -1;
8558  var2weight--;
8559  }
8560 
8561  /* At this point, either w1 == w2 or we've run out of digits */
8562 
8563  if (var1weight == var2weight)
8564  {
8565  while (i1 < var1ndigits && i2 < var2ndigits)
8566  {
8567  int stat = var1digits[i1++] - var2digits[i2++];
8568 
8569  if (stat)
8570  {
8571  if (stat > 0)
8572  return 1;
8573  return -1;
8574  }
8575  }
8576  }
8577 
8578  /*
8579  * At this point, we've run out of digits on one side or the other; so any
8580  * remaining nonzero digits imply that side is larger
8581  */
8582  while (i1 < var1ndigits)
8583  {
8584  if (var1digits[i1++] != 0)
8585  return 1;
8586  }
8587  while (i2 < var2ndigits)
8588  {
8589  if (var2digits[i2++] != 0)
8590  return -1;
8591  }
8592 
8593  return 0;
8594 }
#define stat(a, b)
Definition: win32_port.h:266

◆ cmp_numerics()

static int cmp_numerics ( Numeric  num1,
Numeric  num2 
)
static

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

2139 {
2140  int result;
2141 
2142  /*
2143  * We consider all NANs to be equal and larger than any non-NAN. This is
2144  * somewhat arbitrary; the important thing is to have a consistent sort
2145  * order.
2146  */
2147  if (NUMERIC_IS_NAN(num1))
2148  {
2149  if (NUMERIC_IS_NAN(num2))
2150  result = 0; /* NAN = NAN */
2151  else
2152  result = 1; /* NAN > non-NAN */
2153  }
2154  else if (NUMERIC_IS_NAN(num2))
2155  {
2156  result = -1; /* non-NAN < NAN */
2157  }
2158  else
2159  {
2160  result = cmp_var_common(NUMERIC_DIGITS(num1), NUMERIC_NDIGITS(num1),
2161  NUMERIC_WEIGHT(num1), NUMERIC_SIGN(num1),
2162  NUMERIC_DIGITS(num2), NUMERIC_NDIGITS(num2),
2163  NUMERIC_WEIGHT(num2), NUMERIC_SIGN(num2));
2164  }
2165 
2166  return result;
2167 }
#define NUMERIC_DIGITS(num)
Definition: numeric.c:454
#define NUMERIC_SIGN(n)
Definition: numeric.c:207
#define NUMERIC_NDIGITS(num)
Definition: numeric.c:456
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:6574
#define NUMERIC_WEIGHT(n)
Definition: numeric.c:215
#define NUMERIC_IS_NAN(n)
Definition: numeric.c:171

◆ cmp_var()

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

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

6560 {
6561  return cmp_var_common(var1->digits, var1->ndigits,
6562  var1->weight, var1->sign,
6563  var2->digits, var2->ndigits,
6564  var2->weight, var2->sign);
6565 }
int weight
Definition: numeric.c:273
int ndigits
Definition: numeric.c:272
int sign
Definition: numeric.c:274
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:6574
NumericDigit * digits
Definition: numeric.c:277

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

References cmp_abs_common(), NUMERIC_NEG, and NUMERIC_POS.

Referenced by cmp_numerics(), and cmp_var().

6578 {
6579  if (var1ndigits == 0)
6580  {
6581  if (var2ndigits == 0)
6582  return 0;
6583  if (var2sign == NUMERIC_NEG)
6584  return 1;
6585  return -1;
6586  }
6587  if (var2ndigits == 0)
6588  {
6589  if (var1sign == NUMERIC_POS)
6590  return 1;
6591  return -1;
6592  }
6593 
6594  if (var1sign == NUMERIC_POS)
6595  {
6596  if (var2sign == NUMERIC_NEG)
6597  return 1;
6598  return cmp_abs_common(var1digits, var1ndigits, var1weight,
6599  var2digits, var2ndigits, var2weight);
6600  }
6601 
6602  if (var2sign == NUMERIC_POS)
6603  return -1;
6604 
6605  return cmp_abs_common(var2digits, var2ndigits, var2weight,
6606  var1digits, var1ndigits, var1weight);
6607 }
#define NUMERIC_POS
Definition: numeric.c:165
#define NUMERIC_NEG
Definition: numeric.c:166
static int cmp_abs_common(const NumericDigit *var1digits, int var1ndigits, int var1weight, const NumericDigit *var2digits, int var2ndigits, int var2weight)
Definition: numeric.c:8540

◆ compute_bucket()

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

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

1567 {
1568  NumericVar bound1_var;
1569  NumericVar bound2_var;
1570  NumericVar operand_var;
1571 
1572  init_var_from_num(bound1, &bound1_var);
1573  init_var_from_num(bound2, &bound2_var);
1574  init_var_from_num(operand, &operand_var);
1575 
1576  if (cmp_var(&bound1_var, &bound2_var) < 0)
1577  {
1578  sub_var(&operand_var, &bound1_var, &operand_var);
1579  sub_var(&bound2_var, &bound1_var, &bound2_var);
1580  div_var(&operand_var, &bound2_var, result_var,
1581  select_div_scale(&operand_var, &bound2_var), true);
1582  }
1583  else
1584  {
1585  sub_var(&bound1_var, &operand_var, &operand_var);
1586  sub_var(&bound1_var, &bound2_var, &bound1_var);
1587  div_var(&operand_var, &bound1_var, result_var,
1588  select_div_scale(&operand_var, &bound1_var), true);
1589  }
1590 
1591  mul_var(result_var, count_var, result_var,
1592  result_var->dscale + count_var->dscale);
1593  add_var(result_var, &const_one, result_var);
1594  floor_var(result_var, result_var);
1595 
1596  free_var(&bound1_var);
1597  free_var(&bound2_var);
1598  free_var(&operand_var);
1599 }
static const NumericVar const_one
Definition: numeric.c:376
static void div_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result, int rscale, bool round)
Definition: numeric.c:7052
int dscale
Definition: numeric.c:275
static int select_div_scale(const NumericVar *var1, const NumericVar *var2)
Definition: numeric.c:7632
static void init_var_from_num(Numeric num, NumericVar *dest)
Definition: numeric.c:5815
static int cmp_var(const NumericVar *var1, const NumericVar *var2)
Definition: numeric.c:6559
static void free_var(NumericVar *var)
Definition: numeric.c:5582
static void mul_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result, int rscale)
Definition: numeric.c:6855
static void add_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition: numeric.c:6617
static void sub_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition: numeric.c:6734
static void floor_var(const NumericVar *var, NumericVar *result)
Definition: numeric.c:7754

◆ div_var()

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

Definition at line 7052 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(), numeric_div_trunc(), numeric_stddev_internal(), and power_var_int().

7054 {
7055  int div_ndigits;
7056  int res_ndigits;
7057  int res_sign;
7058  int res_weight;
7059  int carry;
7060  int borrow;
7061  int divisor1;
7062  int divisor2;
7063  NumericDigit *dividend;
7064  NumericDigit *divisor;
7065  NumericDigit *res_digits;
7066  int i;
7067  int j;
7068 
7069  /* copy these values into local vars for speed in inner loop */
7070  int var1ndigits = var1->ndigits;
7071  int var2ndigits = var2->ndigits;
7072 
7073  /*
7074  * First of all division by zero check; we must not be handed an
7075  * unnormalized divisor.
7076  */
7077  if (var2ndigits == 0 || var2->digits[0] == 0)
7078  ereport(ERROR,
7079  (errcode(ERRCODE_DIVISION_BY_ZERO),
7080  errmsg("division by zero")));
7081 
7082  /*
7083  * Now result zero check
7084  */
7085  if (var1ndigits == 0)
7086  {
7087  zero_var(result);
7088  result->dscale = rscale;
7089  return;
7090  }
7091 
7092  /*
7093  * Determine the result sign, weight and number of digits to calculate.
7094  * The weight figured here is correct if the emitted quotient has no
7095  * leading zero digits; otherwise strip_var() will fix things up.
7096  */
7097  if (var1->sign == var2->sign)
7098  res_sign = NUMERIC_POS;
7099  else
7100  res_sign = NUMERIC_NEG;
7101  res_weight = var1->weight - var2->weight;
7102  /* The number of accurate result digits we need to produce: */
7103  res_ndigits = res_weight + 1 + (rscale + DEC_DIGITS - 1) / DEC_DIGITS;
7104  /* ... but always at least 1 */
7105  res_ndigits = Max(res_ndigits, 1);
7106  /* If rounding needed, figure one more digit to ensure correct result */
7107  if (round)
7108  res_ndigits++;
7109 
7110  /*
7111  * The working dividend normally requires res_ndigits + var2ndigits
7112  * digits, but make it at least var1ndigits so we can load all of var1
7113  * into it. (There will be an additional digit dividend[0] in the
7114  * dividend space, but for consistency with Knuth's notation we don't
7115  * count that in div_ndigits.)
7116  */
7117  div_ndigits = res_ndigits + var2ndigits;
7118  div_ndigits = Max(div_ndigits, var1ndigits);
7119 
7120  /*
7121  * We need a workspace with room for the working dividend (div_ndigits+1
7122  * digits) plus room for the possibly-normalized divisor (var2ndigits
7123  * digits). It is convenient also to have a zero at divisor[0] with the
7124  * actual divisor data in divisor[1 .. var2ndigits]. Transferring the
7125  * digits into the workspace also allows us to realloc the result (which
7126  * might be the same as either input var) before we begin the main loop.
7127  * Note that we use palloc0 to ensure that divisor[0], dividend[0], and
7128  * any additional dividend positions beyond var1ndigits, start out 0.
7129  */
7130  dividend = (NumericDigit *)
7131  palloc0((div_ndigits + var2ndigits + 2) * sizeof(NumericDigit));
7132  divisor = dividend + (div_ndigits + 1);
7133  memcpy(dividend + 1, var1->digits, var1ndigits * sizeof(NumericDigit));
7134  memcpy(divisor + 1, var2->digits, var2ndigits * sizeof(NumericDigit));
7135 
7136  /*
7137  * Now we can realloc the result to hold the generated quotient digits.
7138  */
7139  alloc_var(result, res_ndigits);
7140  res_digits = result->digits;
7141 
7142  if (var2ndigits == 1)
7143  {
7144  /*
7145  * If there's only a single divisor digit, we can use a fast path (cf.
7146  * Knuth section 4.3.1 exercise 16).
7147  */
7148  divisor1 = divisor[1];
7149  carry = 0;
7150  for (i = 0; i < res_ndigits; i++)
7151  {
7152  carry = carry * NBASE + dividend[i + 1];
7153  res_digits[i] = carry / divisor1;
7154  carry = carry % divisor1;
7155  }
7156  }
7157  else
7158  {
7159  /*
7160  * The full multiple-place algorithm is taken from Knuth volume 2,
7161  * Algorithm 4.3.1D.
7162  *
7163  * We need the first divisor digit to be >= NBASE/2. If it isn't,
7164  * make it so by scaling up both the divisor and dividend by the
7165  * factor "d". (The reason for allocating dividend[0] above is to
7166  * leave room for possible carry here.)
7167  */
7168  if (divisor[1] < HALF_NBASE)
7169  {
7170  int d = NBASE / (divisor[1] + 1);
7171 
7172  carry = 0;
7173  for (i = var2ndigits; i > 0; i--)
7174  {
7175  carry += divisor[i] * d;
7176  divisor[i] = carry % NBASE;
7177  carry = carry / NBASE;
7178  }
7179  Assert(carry == 0);
7180  carry = 0;
7181  /* at this point only var1ndigits of dividend can be nonzero */
7182  for (i = var1ndigits; i >= 0; i--)
7183  {
7184  carry += dividend[i] * d;
7185  dividend[i] = carry % NBASE;
7186  carry = carry / NBASE;
7187  }
7188  Assert(carry == 0);
7189  Assert(divisor[1] >= HALF_NBASE);
7190  }
7191  /* First 2 divisor digits are used repeatedly in main loop */
7192  divisor1 = divisor[1];
7193  divisor2 = divisor[2];
7194 
7195  /*
7196  * Begin the main loop. Each iteration of this loop produces the j'th
7197  * quotient digit by dividing dividend[j .. j + var2ndigits] by the
7198  * divisor; this is essentially the same as the common manual
7199  * procedure for long division.
7200  */
7201  for (j = 0; j < res_ndigits; j++)
7202  {
7203  /* Estimate quotient digit from the first two dividend digits */
7204  int next2digits = dividend[j] * NBASE + dividend[j + 1];
7205  int qhat;
7206 
7207  /*
7208  * If next2digits are 0, then quotient digit must be 0 and there's
7209  * no need to adjust the working dividend. It's worth testing
7210  * here to fall out ASAP when processing trailing zeroes in a
7211  * dividend.
7212  */
7213  if (next2digits == 0)
7214  {
7215  res_digits[j] = 0;
7216  continue;
7217  }
7218 
7219  if (dividend[j] == divisor1)
7220  qhat = NBASE - 1;
7221  else
7222  qhat = next2digits / divisor1;
7223 
7224  /*
7225  * Adjust quotient digit if it's too large. Knuth proves that
7226  * after this step, the quotient digit will be either correct or
7227  * just one too large. (Note: it's OK to use dividend[j+2] here
7228  * because we know the divisor length is at least 2.)
7229  */
7230  while (divisor2 * qhat >
7231  (next2digits - qhat * divisor1) * NBASE + dividend[j + 2])
7232  qhat--;
7233 
7234  /* As above, need do nothing more when quotient digit is 0 */
7235  if (qhat > 0)
7236  {
7237  /*
7238  * Multiply the divisor by qhat, and subtract that from the
7239  * working dividend. "carry" tracks the multiplication,
7240  * "borrow" the subtraction (could we fold these together?)
7241  */
7242  carry = 0;
7243  borrow = 0;
7244  for (i = var2ndigits; i >= 0; i--)
7245  {
7246  carry += divisor[i] * qhat;
7247  borrow -= carry % NBASE;
7248  carry = carry / NBASE;
7249  borrow += dividend[j + i];
7250  if (borrow < 0)
7251  {
7252  dividend[j + i] = borrow + NBASE;
7253  borrow = -1;
7254  }
7255  else
7256  {
7257  dividend[j + i] = borrow;
7258  borrow = 0;
7259  }
7260  }
7261  Assert(carry == 0);
7262 
7263  /*
7264  * If we got a borrow out of the top dividend digit, then
7265  * indeed qhat was one too large. Fix it, and add back the
7266  * divisor to correct the working dividend. (Knuth proves
7267  * that this will occur only about 3/NBASE of the time; hence,
7268  * it's a good idea to test this code with small NBASE to be
7269  * sure this section gets exercised.)
7270  */
7271  if (borrow)
7272  {
7273  qhat--;
7274  carry = 0;
7275  for (i = var2ndigits; i >= 0; i--)
7276  {
7277  carry += dividend[j + i] + divisor[i];
7278  if (carry >= NBASE)
7279  {
7280  dividend[j + i] = carry - NBASE;
7281  carry = 1;
7282  }
7283  else
7284  {
7285  dividend[j + i] = carry;
7286  carry = 0;
7287  }
7288  }
7289  /* A carry should occur here to cancel the borrow above */
7290  Assert(carry == 1);
7291  }
7292  }
7293 
7294  /* And we're done with this quotient digit */
7295  res_digits[j] = qhat;
7296  }
7297  }
7298 
7299  pfree(dividend);
7300 
7301  /*
7302  * Finally, round or truncate the result to the requested precision.
7303  */
7304  result->weight = res_weight;
7305  result->sign = res_sign;
7306 
7307  /* Round or truncate to target rscale (and set result->dscale) */
7308  if (round)
7309  round_var(result, rscale);
7310  else
7311  trunc_var(result, rscale);
7312 
7313  /* Strip leading and trailing zeroes */
7314  strip_var(result);
7315 }
static void round_var(NumericVar *var, int rscale)
Definition: numeric.c:8771
static void trunc_var(NumericVar *var, int rscale)
Definition: numeric.c:8877
int weight
Definition: numeric.c:273
#define NUMERIC_POS
Definition: numeric.c:165
static void strip_var(NumericVar *var)
Definition: numeric.c:8939
int errcode(int sqlerrcode)
Definition: elog.c:575
int ndigits
Definition: numeric.c:272
int dscale
Definition: numeric.c:275
#define NUMERIC_NEG
Definition: numeric.c:166
int sign
Definition: numeric.c:274
static void zero_var(NumericVar *var)
Definition: numeric.c:5598
void pfree(void *pointer)
Definition: mcxt.c:1031
#define ERROR
Definition: elog.h:43
int16 NumericDigit
Definition: numeric.c:100
#define HALF_NBASE
Definition: numeric.c:95
#define ereport(elevel, rest)
Definition: elog.h:122
#define NBASE
Definition: numeric.c:94
void * palloc0(Size size)
Definition: mcxt.c:955
#define Assert(condition)
Definition: c.h:699
NumericDigit * digits
Definition: numeric.c:277
int errmsg(const char *fmt,...)
Definition: elog.c:797
static void alloc_var(NumericVar *var, int ndigits)
Definition: numeric.c:5566
int i
#define Max(x, y)
Definition: numeric.c:11
#define DEC_DIGITS
Definition: numeric.c:96

◆ div_var_fast()

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

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

7339 {
7340  int div_ndigits;
7341  int res_sign;
7342  int res_weight;
7343  int *div;
7344  int qdigit;
7345  int carry;
7346  int maxdiv;
7347  int newdig;
7348  NumericDigit *res_digits;
7349  double fdividend,
7350  fdivisor,
7351  fdivisorinverse,
7352  fquotient;
7353  int qi;
7354  int i;
7355 
7356  /* copy these values into local vars for speed in inner loop */
7357  int var1ndigits = var1->ndigits;
7358  int var2ndigits = var2->ndigits;
7359  NumericDigit *var1digits = var1->digits;
7360  NumericDigit *var2digits = var2->digits;
7361 
7362  /*
7363  * First of all division by zero check; we must not be handed an
7364  * unnormalized divisor.
7365  */
7366  if (var2ndigits == 0 || var2digits[0] == 0)
7367  ereport(ERROR,
7368  (errcode(ERRCODE_DIVISION_BY_ZERO),
7369  errmsg("division by zero")));
7370 
7371  /*
7372  * Now result zero check
7373  */
7374  if (var1ndigits == 0)
7375  {
7376  zero_var(result);
7377  result->dscale = rscale;
7378  return;
7379  }
7380 
7381  /*
7382  * Determine the result sign, weight and number of digits to calculate
7383  */
7384  if (var1->sign == var2->sign)
7385  res_sign = NUMERIC_POS;
7386  else
7387  res_sign = NUMERIC_NEG;
7388  res_weight = var1->weight - var2->weight + 1;
7389  /* The number of accurate result digits we need to produce: */
7390  div_ndigits = res_weight + 1 + (rscale + DEC_DIGITS - 1) / DEC_DIGITS;
7391  /* Add guard digits for roundoff error */
7392  div_ndigits += DIV_GUARD_DIGITS;
7393  if (div_ndigits < DIV_GUARD_DIGITS)
7394  div_ndigits = DIV_GUARD_DIGITS;
7395  /* Must be at least var1ndigits, too, to simplify data-loading loop */
7396  if (div_ndigits < var1ndigits)
7397  div_ndigits = var1ndigits;
7398 
7399  /*
7400  * We do the arithmetic in an array "div[]" of signed int's. Since
7401  * INT_MAX is noticeably larger than NBASE*NBASE, this gives us headroom
7402  * to avoid normalizing carries immediately.
7403  *
7404  * We start with div[] containing one zero digit followed by the
7405  * dividend's digits (plus appended zeroes to reach the desired precision
7406  * including guard digits). Each step of the main loop computes an
7407  * (approximate) quotient digit and stores it into div[], removing one
7408  * position of dividend space. A final pass of carry propagation takes
7409  * care of any mistaken quotient digits.
7410  */
7411  div = (int *) palloc0((div_ndigits + 1) * sizeof(int));
7412  for (i = 0; i < var1ndigits; i++)
7413  div[i + 1] = var1digits[i];
7414 
7415  /*
7416  * We estimate each quotient digit using floating-point arithmetic, taking
7417  * the first four digits of the (current) dividend and divisor. This must
7418  * be float to avoid overflow. The quotient digits will generally be off
7419  * by no more than one from the exact answer.
7420  */
7421  fdivisor = (double) var2digits[0];
7422  for (i = 1; i < 4; i++)
7423  {
7424  fdivisor *= NBASE;
7425  if (i < var2ndigits)
7426  fdivisor += (double) var2digits[i];
7427  }
7428  fdivisorinverse = 1.0 / fdivisor;
7429 
7430  /*
7431  * maxdiv tracks the maximum possible absolute value of any div[] entry;
7432  * when this threatens to exceed INT_MAX, we take the time to propagate
7433  * carries. Furthermore, we need to ensure that overflow doesn't occur
7434  * during the carry propagation passes either. The carry values may have
7435  * an absolute value as high as INT_MAX/NBASE + 1, so really we must
7436  * normalize when digits threaten to exceed INT_MAX - INT_MAX/NBASE - 1.
7437  *
7438  * To avoid overflow in maxdiv itself, it represents the max absolute
7439  * value divided by NBASE-1, ie, at the top of the loop it is known that
7440  * no div[] entry has an absolute value exceeding maxdiv * (NBASE-1).
7441  *
7442  * Actually, though, that holds good only for div[] entries after div[qi];
7443  * the adjustment done at the bottom of the loop may cause div[qi + 1] to
7444  * exceed the maxdiv limit, so that div[qi] in the next iteration is
7445  * beyond the limit. This does not cause problems, as explained below.
7446  */
7447  maxdiv = 1;
7448 
7449  /*
7450  * Outer loop computes next quotient digit, which will go into div[qi]
7451  */
7452  for (qi = 0; qi < div_ndigits; qi++)
7453  {
7454  /* Approximate the current dividend value */
7455  fdividend = (double) div[qi];
7456  for (i = 1; i < 4; i++)
7457  {
7458  fdividend *= NBASE;
7459  if (qi + i <= div_ndigits)
7460  fdividend += (double) div[qi + i];
7461  }
7462  /* Compute the (approximate) quotient digit */
7463  fquotient = fdividend * fdivisorinverse;
7464  qdigit = (fquotient >= 0.0) ? ((int) fquotient) :
7465  (((int) fquotient) - 1); /* truncate towards -infinity */
7466 
7467  if (qdigit != 0)
7468  {
7469  /* Do we need to normalize now? */
7470  maxdiv += Abs(qdigit);
7471  if (maxdiv > (INT_MAX - INT_MAX / NBASE - 1) / (NBASE - 1))
7472  {
7473  /* Yes, do it */
7474  carry = 0;
7475  for (i = div_ndigits; i > qi; i--)
7476  {
7477  newdig = div[i] + carry;
7478  if (newdig < 0)
7479  {
7480  carry = -((-newdig - 1) / NBASE) - 1;
7481  newdig -= carry * NBASE;
7482  }
7483  else if (newdig >= NBASE)
7484  {
7485  carry = newdig / NBASE;
7486  newdig -= carry * NBASE;
7487  }
7488  else
7489  carry = 0;
7490  div[i] = newdig;
7491  }
7492  newdig = div[qi] + carry;
7493  div[qi] = newdig;
7494 
7495  /*
7496  * All the div[] digits except possibly div[qi] are now in the
7497  * range 0..NBASE-1. We do not need to consider div[qi] in
7498  * the maxdiv value anymore, so we can reset maxdiv to 1.
7499  */
7500  maxdiv = 1;
7501 
7502  /*
7503  * Recompute the quotient digit since new info may have
7504  * propagated into the top four dividend digits
7505  */
7506  fdividend = (double) div[qi];
7507  for (i = 1; i < 4; i++)
7508  {
7509  fdividend *= NBASE;
7510  if (qi + i <= div_ndigits)
7511  fdividend += (double) div[qi + i];
7512  }
7513  /* Compute the (approximate) quotient digit */
7514  fquotient = fdividend * fdivisorinverse;
7515  qdigit = (fquotient >= 0.0) ? ((int) fquotient) :
7516  (((int) fquotient) - 1); /* truncate towards -infinity */
7517  maxdiv += Abs(qdigit);
7518  }
7519 
7520  /*
7521  * Subtract off the appropriate multiple of the divisor.
7522  *
7523  * The digits beyond div[qi] cannot overflow, because we know they
7524  * will fall within the maxdiv limit. As for div[qi] itself, note
7525  * that qdigit is approximately trunc(div[qi] / vardigits[0]),
7526  * which would make the new value simply div[qi] mod vardigits[0].
7527  * The lower-order terms in qdigit can change this result by not
7528  * more than about twice INT_MAX/NBASE, so overflow is impossible.
7529  */
7530  if (qdigit != 0)
7531  {
7532  int istop = Min(var2ndigits, div_ndigits - qi + 1);
7533 
7534  for (i = 0; i < istop; i++)
7535  div[qi + i] -= qdigit * var2digits[i];
7536  }
7537  }
7538 
7539  /*
7540  * The dividend digit we are about to replace might still be nonzero.
7541  * Fold it into the next digit position.
7542  *
7543  * There is no risk of overflow here, although proving that requires
7544  * some care. Much as with the argument for div[qi] not overflowing,
7545  * if we consider the first two terms in the numerator and denominator
7546  * of qdigit, we can see that the final value of div[qi + 1] will be
7547  * approximately a remainder mod (vardigits[0]*NBASE + vardigits[1]).
7548  * Accounting for the lower-order terms is a bit complicated but ends
7549  * up adding not much more than INT_MAX/NBASE to the possible range.
7550  * Thus, div[qi + 1] cannot overflow here, and in its role as div[qi]
7551  * in the next loop iteration, it can't be large enough to cause
7552  * overflow in the carry propagation step (if any), either.
7553  *
7554  * But having said that: div[qi] can be more than INT_MAX/NBASE, as
7555  * noted above, which means that the product div[qi] * NBASE *can*
7556  * overflow. When that happens, adding it to div[qi + 1] will always
7557  * cause a canceling overflow so that the end result is correct. We
7558  * could avoid the intermediate overflow by doing the multiplication
7559  * and addition in int64 arithmetic, but so far there appears no need.
7560  */
7561  div[qi + 1] += div[qi] * NBASE;
7562 
7563  div[qi] = qdigit;
7564  }
7565 
7566  /*
7567  * Approximate and store the last quotient digit (div[div_ndigits])
7568  */
7569  fdividend = (double) div[qi];
7570  for (i = 1; i < 4; i++)
7571  fdividend *= NBASE;
7572  fquotient = fdividend * fdivisorinverse;
7573  qdigit = (fquotient >= 0.0) ? ((int) fquotient) :
7574  (((int) fquotient) - 1); /* truncate towards -infinity */
7575  div[qi] = qdigit;
7576 
7577  /*
7578  * Because the quotient digits might be off by one, some of them might be
7579  * -1 or NBASE at this point. The represented value is correct in a
7580  * mathematical sense, but it doesn't look right. We do a final carry
7581  * propagation pass to normalize the digits, which we combine with storing
7582  * the result digits into the output. Note that this is still done at
7583  * full precision w/guard digits.
7584  */
7585  alloc_var(result, div_ndigits + 1);
7586  res_digits = result->digits;
7587  carry = 0;
7588  for (i = div_ndigits; i >= 0; i--)
7589  {
7590  newdig = div[i] + carry;
7591  if (newdig < 0)
7592  {
7593  carry = -((-newdig - 1) / NBASE) - 1;
7594  newdig -= carry * NBASE;
7595  }
7596  else if (newdig >= NBASE)
7597  {
7598  carry = newdig / NBASE;
7599  newdig -= carry * NBASE;
7600  }
7601  else
7602  carry = 0;
7603  res_digits[i] = newdig;
7604  }
7605  Assert(carry == 0);
7606 
7607  pfree(div);
7608 
7609  /*
7610  * Finally, round the result to the requested precision.
7611  */
7612  result->weight = res_weight;
7613  result->sign = res_sign;
7614 
7615  /* Round to target rscale (and set result->dscale) */
7616  if (round)
7617  round_var(result, rscale);
7618  else
7619  trunc_var(result, rscale);
7620 
7621  /* Strip leading and trailing zeroes */
7622  strip_var(result);
7623 }
static void round_var(NumericVar *var, int rscale)
Definition: numeric.c:8771
static void trunc_var(NumericVar *var, int rscale)
Definition: numeric.c:8877
int weight
Definition: numeric.c:273
#define NUMERIC_POS
Definition: numeric.c:165
static void strip_var(NumericVar *var)
Definition: numeric.c:8939
int errcode(int sqlerrcode)
Definition: elog.c:575
int ndigits
Definition: numeric.c:272
int dscale
Definition: numeric.c:275
#define Min(x, y)
Definition: numeric.c:12
#define Abs(x)
Definition: c.h:863
#define NUMERIC_NEG
Definition: numeric.c:166
int sign
Definition: numeric.c:274
static void zero_var(NumericVar *var)
Definition: numeric.c:5598
void pfree(void *pointer)
Definition: mcxt.c:1031
#define ERROR
Definition: elog.h:43
int16 NumericDigit
Definition: numeric.c:100
#define ereport(elevel, rest)
Definition: elog.h:122
#define NBASE
Definition: numeric.c:94
void * palloc0(Size size)
Definition: mcxt.c:955
#define Assert(condition)
Definition: c.h:699
NumericDigit * digits
Definition: numeric.c:277
#define DIV_GUARD_DIGITS
Definition: numeric.c:98
int errmsg(const char *fmt,...)
Definition: elog.c:797
static void alloc_var(NumericVar *var, int ndigits)
Definition: numeric.c:5566
int i
#define DEC_DIGITS
Definition: numeric.c:96

◆ do_numeric_accum()

static void do_numeric_accum ( NumericAggState state,
Numeric  newval 
)
static

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

3424 {
3425  NumericVar X;
3426  NumericVar X2;
3427  MemoryContext old_context;
3428 
3429  /* Count NaN inputs separately from all else */
3430  if (NUMERIC_IS_NAN(newval))
3431  {
3432  state->NaNcount++;
3433  return;
3434  }
3435 
3436  /* load processed number in short-lived context */
3437  init_var_from_num(newval, &X);
3438 
3439  /*
3440  * Track the highest input dscale that we've seen, to support inverse
3441  * transitions (see do_numeric_discard).
3442  */
3443  if (X.dscale > state->maxScale)
3444  {
3445  state->maxScale = X.dscale;
3446  state->maxScaleCount = 1;
3447  }
3448  else if (X.dscale == state->maxScale)
3449  state->maxScaleCount++;
3450 
3451  /* if we need X^2, calculate that in short-lived context */
3452  if (state->calcSumX2)
3453  {
3454  init_var(&X2);
3455  mul_var(&X, &X, &X2, X.dscale * 2);
3456  }
3457 
3458  /* The rest of this needs to work in the aggregate context */
3459  old_context = MemoryContextSwitchTo(state->agg_context);
3460 
3461  state->N++;
3462 
3463  /* Accumulate sums */
3464  accum_sum_add(&(state->sumX), &X);
3465 
3466  if (state->calcSumX2)
3467  accum_sum_add(&(state->sumX2), &X2);
3468 
3469  MemoryContextSwitchTo(old_context);
3470 }
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
MemoryContext agg_context
Definition: numeric.c:3369
int dscale
Definition: numeric.c:275
static void accum_sum_add(NumericSumAccum *accum, const NumericVar *var1)
Definition: numeric.c:8996
static void init_var_from_num(Numeric num, NumericVar *dest)
Definition: numeric.c:5815
static void mul_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result, int rscale)
Definition: numeric.c:6855
NumericSumAccum sumX2
Definition: numeric.c:3372
int64 NaNcount
Definition: numeric.c:3375
int64 maxScaleCount
Definition: numeric.c:3374
#define NUMERIC_IS_NAN(n)
Definition: numeric.c:171
NumericSumAccum sumX
Definition: numeric.c:3371
#define init_var(v)
Definition: numeric.c:452

◆ do_numeric_discard()

static bool do_numeric_discard ( NumericAggState state,
Numeric  newval 
)
static

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

3489 {
3490  NumericVar X;
3491  NumericVar X2;
3492  MemoryContext old_context;
3493 
3494  /* Count NaN inputs separately from all else */
3495  if (NUMERIC_IS_NAN(newval))
3496  {
3497  state->NaNcount--;
3498  return true;
3499  }
3500 
3501  /* load processed number in short-lived context */
3502  init_var_from_num(newval, &X);
3503 
3504  /*
3505  * state->sumX's dscale is the maximum dscale of any of the inputs.
3506  * Removing the last input with that dscale would require us to recompute
3507  * the maximum dscale of the *remaining* inputs, which we cannot do unless
3508  * no more non-NaN inputs remain at all. So we report a failure instead,
3509  * and force the aggregation to be redone from scratch.
3510  */
3511  if (X.dscale == state->maxScale)
3512  {
3513  if (state->maxScaleCount > 1 || state->maxScale == 0)
3514  {
3515  /*
3516  * Some remaining inputs have same dscale, or dscale hasn't gotten
3517  * above zero anyway
3518  */
3519  state->maxScaleCount--;
3520  }
3521  else if (state->N == 1)
3522  {
3523  /* No remaining non-NaN inputs at all, so reset maxScale */
3524  state->maxScale = 0;
3525  state->maxScaleCount = 0;
3526  }
3527  else
3528  {
3529  /* Correct new maxScale is uncertain, must fail */
3530  return false;
3531  }
3532  }
3533 
3534  /* if we need X^2, calculate that in short-lived context */
3535  if (state->calcSumX2)
3536  {
3537  init_var(&X2);
3538  mul_var(&X, &X, &X2, X.dscale * 2);
3539  }
3540 
3541  /* The rest of this needs to work in the aggregate context */
3542  old_context = MemoryContextSwitchTo(state->agg_context);
3543 
3544  if (state->N-- > 1)
3545  {
3546  /* Negate X, to subtract it from the sum */
3547  X.sign = (X.sign == NUMERIC_POS ? NUMERIC_NEG : NUMERIC_POS);
3548  accum_sum_add(&(state->sumX), &X);
3549 
3550  if (state->calcSumX2)
3551  {
3552  /* Negate X^2. X^2 is always positive */
3553  X2.sign = NUMERIC_NEG;
3554  accum_sum_add(&(state->sumX2), &X2);
3555  }
3556  }
3557  else
3558  {
3559  /* Zero the sums */
3560  Assert(state->N == 0);
3561 
3562  accum_sum_reset(&state->sumX);
3563  if (state->calcSumX2)
3564  accum_sum_reset(&state->sumX2);
3565  }
3566 
3567  MemoryContextSwitchTo(old_context);
3568 
3569  return true;
3570 }
#define NUMERIC_POS
Definition: numeric.c:165
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
MemoryContext agg_context
Definition: numeric.c:3369
int dscale
Definition: numeric.c:275
#define NUMERIC_NEG
Definition: numeric.c:166
static void accum_sum_add(NumericSumAccum *accum, const NumericVar *var1)
Definition: numeric.c:8996
int sign
Definition: numeric.c:274
static void init_var_from_num(Numeric num, NumericVar *dest)
Definition: numeric.c:5815
#define Assert(condition)
Definition: c.h:699
static void mul_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result, int rscale)
Definition: numeric.c:6855
NumericSumAccum sumX2
Definition: numeric.c:3372
static void accum_sum_reset(NumericSumAccum *accum)
Definition: numeric.c:8980
int64 NaNcount
Definition: numeric.c:3375
int64 maxScaleCount
Definition: numeric.c:3374
#define NUMERIC_IS_NAN(n)
Definition: numeric.c:171
NumericSumAccum sumX
Definition: numeric.c:3371
#define init_var(v)
Definition: numeric.c:452

◆ estimate_ln_dweight()

static int estimate_ln_dweight ( const NumericVar var)
static

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

7977 {
7978  int ln_dweight;
7979 
7980  if (cmp_var(var, &const_zero_point_nine) >= 0 &&
7981  cmp_var(var, &const_one_point_one) <= 0)
7982  {
7983  /*
7984  * 0.9 <= var <= 1.1
7985  *
7986  * ln(var) has a negative weight (possibly very large). To get a
7987  * reasonably accurate result, estimate it using ln(1+x) ~= x.
7988  */
7989  NumericVar x;
7990 
7991  init_var(&x);
7992  sub_var(var, &const_one, &x);
7993 
7994  if (x.ndigits > 0)
7995  {
7996  /* Use weight of most significant decimal digit of x */
7997  ln_dweight = x.weight * DEC_DIGITS + (int) log10(x.digits[0]);
7998  }
7999  else
8000  {
8001  /* x = 0. Since ln(1) = 0 exactly, we don't need extra digits */
8002  ln_dweight = 0;
8003  }
8004 
8005  free_var(&x);
8006  }
8007  else
8008  {
8009  /*
8010  * Estimate the logarithm using the first couple of digits from the
8011  * input number. This will give an accurate result whenever the input
8012  * is not too close to 1.
8013  */
8014  if (var->ndigits > 0)
8015  {
8016  int digits;
8017  int dweight;
8018  double ln_var;
8019 
8020  digits = var->digits[0];
8021  dweight = var->weight * DEC_DIGITS;
8022 
8023  if (var->ndigits > 1)
8024  {
8025  digits = digits * NBASE + var->digits[1];
8026  dweight -= DEC_DIGITS;
8027  }
8028 
8029  /*----------
8030  * We have var ~= digits * 10^dweight
8031  * so ln(var) ~= ln(digits) + dweight * ln(10)
8032  *----------
8033  */
8034  ln_var = log((double) digits) + dweight * 2.302585092994046;
8035  ln_dweight = (int) log10(Abs(ln_var));
8036  }
8037  else
8038  {
8039  /* Caller should fail on ln(0), but for the moment return zero */
8040  ln_dweight = 0;
8041  }
8042  }
8043 
8044  return ln_dweight;
8045 }
int weight
Definition: numeric.c:273
static const NumericVar const_zero_point_nine
Definition: numeric.c:410
static const NumericVar const_one
Definition: numeric.c:376
static void ln_var(const NumericVar *arg, NumericVar *result, int rscale)
Definition: numeric.c:8054
int ndigits
Definition: numeric.c:272
#define Abs(x)
Definition: c.h:863
#define NBASE
Definition: numeric.c:94
static int cmp_var(const NumericVar *var1, const NumericVar *var2)
Definition: numeric.c:6559
static void free_var(NumericVar *var)
Definition: numeric.c:5582
NumericDigit * digits
Definition: numeric.c:277
static void sub_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition: numeric.c:6734
#define DEC_DIGITS
Definition: numeric.c:96
static const NumericVar const_one_point_one
Definition: numeric.c:420
#define init_var(v)
Definition: numeric.c:452
int digits
Definition: informix.c:691

◆ exp_var()

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

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

7851 {
7852  NumericVar x;
7853  NumericVar elem;
7854  NumericVar ni;
7855  double val;
7856  int dweight;
7857  int ndiv2;
7858  int sig_digits;
7859  int local_rscale;
7860 
7861  init_var(&x);
7862  init_var(&elem);
7863  init_var(&ni);
7864 
7865  set_var_from_var(arg, &x);
7866 
7867  /*
7868  * Estimate the dweight of the result using floating point arithmetic, so
7869  * that we can choose an appropriate local rscale for the calculation.
7870  */
7872 
7873  /* Guard against overflow */
7874  /* If you change this limit, see also power_var()'s limit */
7875  if (Abs(val) >= NUMERIC_MAX_RESULT_SCALE * 3)
7876  ereport(ERROR,
7877  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
7878  errmsg("value overflows numeric format")));
7879 
7880  /* decimal weight = log10(e^x) = x * log10(e) */
7881  dweight = (int) (val * 0.434294481903252);
7882 
7883  /*
7884  * Reduce x to the range -0.01 <= x <= 0.01 (approximately) by dividing by
7885  * 2^n, to improve the convergence rate of the Taylor series.
7886  */
7887  if (Abs(val) > 0.01)
7888  {
7889  NumericVar tmp;
7890 
7891  init_var(&tmp);
7892  set_var_from_var(&const_two, &tmp);
7893 
7894  ndiv2 = 1;
7895  val /= 2;
7896 
7897  while (Abs(val) > 0.01)
7898  {
7899  ndiv2++;
7900  val /= 2;
7901  add_var(&tmp, &tmp, &tmp);
7902  }
7903 
7904  local_rscale = x.dscale + ndiv2;
7905  div_var_fast(&x, &tmp, &x, local_rscale, true);
7906 
7907  free_var(&tmp);
7908  }
7909  else
7910  ndiv2 = 0;
7911 
7912  /*
7913  * Set the scale for the Taylor series expansion. The final result has
7914  * (dweight + rscale + 1) significant digits. In addition, we have to
7915  * raise the Taylor series result to the power 2^ndiv2, which introduces
7916  * an error of up to around log10(2^ndiv2) digits, so work with this many
7917  * extra digits of precision (plus a few more for good measure).
7918  */
7919  sig_digits = 1 + dweight + rscale + (int) (ndiv2 * 0.301029995663981);
7920  sig_digits = Max(sig_digits, 0) + 8;
7921 
7922  local_rscale = sig_digits - 1;
7923 
7924  /*
7925  * Use the Taylor series
7926  *
7927  * exp(x) = 1 + x + x^2/2! + x^3/3! + ...
7928  *
7929  * Given the limited range of x, this should converge reasonably quickly.
7930  * We run the series until the terms fall below the local_rscale limit.
7931  */
7932  add_var(&const_one, &x, result);
7933 
7934  mul_var(&x, &x, &elem, local_rscale);
7935  set_var_from_var(&const_two, &ni);
7936  div_var_fast(&elem, &ni, &elem, local_rscale, true);
7937 
7938  while (elem.ndigits != 0)
7939  {
7940  add_var(result, &elem, result);
7941 
7942  mul_var(&elem, &x, &elem, local_rscale);
7943  add_var(&ni, &const_one, &ni);
7944  div_var_fast(&elem, &ni, &elem, local_rscale, true);
7945  }
7946 
7947  /*
7948  * Compensate for the argument range reduction. Since the weight of the
7949  * result doubles with each multiplication, we can reduce the local rscale
7950  * as we proceed.
7951  */
7952  while (ndiv2-- > 0)
7953  {
7954  local_rscale = sig_digits - result->weight * 2 * DEC_DIGITS;
7955  local_rscale = Max(local_rscale, NUMERIC_MIN_DISPLAY_SCALE);
7956  mul_var(result, result, result, local_rscale);
7957  }
7958 
7959  /* Round to requested rscale */
7960  round_var(result, rscale);
7961 
7962  free_var(&x);
7963  free_var(&elem);
7964  free_var(&ni);
7965 }
static void round_var(NumericVar *var, int rscale)
Definition: numeric.c:8771
int weight
Definition: numeric.c:273
static const NumericVar const_one
Definition: numeric.c:376
int errcode(int sqlerrcode)
Definition: elog.c:575
int ndigits
Definition: numeric.c:272
int dscale
Definition: numeric.c:275
#define Abs(x)
Definition: c.h:863
#define ERROR
Definition: elog.h:43
static double numericvar_to_double_no_overflow(const NumericVar *var)
Definition: numeric.c:6527
#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:7337
#define ereport(elevel, rest)
Definition: elog.h:122
static void free_var(NumericVar *var)
Definition: numeric.c:5582
static const NumericVar const_two
Definition: numeric.c:380
static void mul_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result, int rscale)
Definition: numeric.c:6855
static void add_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition: numeric.c:6617
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define Max(x, y)
Definition: numeric.c:11
#define DEC_DIGITS
Definition: numeric.c:96
static void set_var_from_var(const NumericVar *value, NumericVar *dest)
Definition: numeric.c:5832
long val
Definition: informix.c:689
#define init_var(v)
Definition: numeric.c:452

◆ float4_numeric()

Datum float4_numeric ( PG_FUNCTION_ARGS  )

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

3302 {
3304  Numeric res;
3305  NumericVar result;
3306  char buf[FLT_DIG + 100];
3307 
3308  if (isnan(val))
3310 
3311  if (isinf(val))
3312  ereport(ERROR,
3313  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3314  errmsg("cannot convert infinity to numeric")));
3315 
3316  snprintf(buf, sizeof(buf), "%.*g", FLT_DIG, val);
3317 
3318  init_var(&result);
3319 
3320  /* Assume we need not worry about leading/trailing spaces */
3321  (void) set_var_from_str(buf, buf, &result);
3322 
3323  res = make_result(&result);
3324 
3325  free_var(&result);
3326 
3327  PG_RETURN_NUMERIC(res);
3328 }
#define PG_RETURN_NUMERIC(x)
Definition: numeric.h:54
int errcode(int sqlerrcode)
Definition: elog.c:575
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
#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:250
#define ereport(elevel, rest)
Definition: elog.h:122
float float4
Definition: c.h:457
static void free_var(NumericVar *var)
Definition: numeric.c:5582
static const char * set_var_from_str(const char *str, const char *cp, NumericVar *dest)
Definition: numeric.c:5622
static const NumericVar const_nan
Definition: numeric.c:423
static Numeric make_result(const NumericVar *var)
Definition: numeric.c:6097
int errmsg(const char *fmt,...)
Definition: elog.c:797
long val
Definition: informix.c:689
#define init_var(v)
Definition: numeric.c:452

◆ float8_numeric()

Datum float8_numeric ( PG_FUNCTION_ARGS  )

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

3231 {
3233  Numeric res;
3234  NumericVar result;
3235  char buf[DBL_DIG + 100];
3236 
3237  if (isnan(val))
3239 
3240  if (isinf(val))
3241  ereport(ERROR,
3242  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3243  errmsg("cannot convert infinity to numeric")));
3244 
3245  snprintf(buf, sizeof(buf), "%.*g", DBL_DIG, val);
3246 
3247  init_var(&result);
3248 
3249  /* Assume we need not worry about leading/trailing spaces */
3250  (void) set_var_from_str(buf, buf, &result);
3251 
3252  res = make_result(&result);
3253 
3254  free_var(&result);
3255 
3256  PG_RETURN_NUMERIC(res);
3257 }
#define PG_RETURN_NUMERIC(x)
Definition: numeric.h:54
#define PG_GETARG_FLOAT8(n)
Definition: fmgr.h:251
int errcode(int sqlerrcode)
Definition: elog.c:575
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
#define ERROR
Definition: elog.h:43
double float8
Definition: c.h:458
int isinf(double x)
static char * buf
Definition: pg_test_fsync.c:67
#define ereport(elevel, rest)
Definition: elog.h:122
static void free_var(NumericVar *var)
Definition: numeric.c:5582
static const char * set_var_from_str(const char *str, const char *cp, NumericVar *dest)
Definition: numeric.c:5622
static const NumericVar const_nan
Definition: numeric.c:423
static Numeric make_result(const NumericVar *var)
Definition: numeric.c:6097
int errmsg(const char *fmt,...)
Definition: elog.c:797
long val
Definition: informix.c:689
#define init_var(v)
Definition: numeric.c:452

◆ floor_var()

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

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

7755 {
7756  NumericVar tmp;
7757 
7758  init_var(&tmp);
7759  set_var_from_var(var, &tmp);
7760 
7761  trunc_var(&tmp, 0);
7762 
7763  if (var->sign == NUMERIC_NEG && cmp_var(var, &tmp) != 0)
7764  sub_var(&tmp, &const_one, &tmp);
7765 
7766  set_var_from_var(&tmp, result);
7767  free_var(&tmp);
7768 }
static void trunc_var(NumericVar *var, int rscale)
Definition: numeric.c:8877
static const NumericVar const_one
Definition: numeric.c:376
#define NUMERIC_NEG
Definition: numeric.c:166
int sign
Definition: numeric.c:274
static int cmp_var(const NumericVar *var1, const NumericVar *var2)
Definition: numeric.c:6559
static void free_var(NumericVar *var)
Definition: numeric.c:5582
static void sub_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition: numeric.c:6734
static void set_var_from_var(const NumericVar *value, NumericVar *dest)
Definition: numeric.c:5832
#define init_var(v)
Definition: numeric.c:452

◆ free_var()

static void free_var ( NumericVar var)
static

Definition at line 5582 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(), numeric_avg(), numeric_avg_serialize(), numeric_ceil(), numeric_div(), numeric_div_trunc(), numeric_exp(), numeric_fac(), numeric_floor(), numeric_in(), numeric_inc(), numeric_ln(), numeric_log(), numeric_mod(), numeric_mul(), 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(), numeric_sum(), numeric_trunc(), numericvar_to_int64(), power_var(), power_var_int(), sqrt_var(), and width_bucket_numeric().

5583 {
5584  digitbuf_free(var->buf);
5585  var->buf = NULL;
5586  var->digits = NULL;
5587  var->sign = NUMERIC_NAN;
5588 }
int sign
Definition: numeric.c:274
#define digitbuf_free(buf)
Definition: numeric.c:446
#define NUMERIC_NAN
Definition: numeric.c:168
NumericDigit * buf
Definition: numeric.c:276
NumericDigit * digits
Definition: numeric.c:277

◆ generate_series_numeric()

Datum generate_series_numeric ( PG_FUNCTION_ARGS  )

Definition at line 1368 of file numeric.c.

References generate_series_step_numeric().

1369 {
1370  return generate_series_step_numeric(fcinfo);
1371 }
Datum generate_series_step_numeric(PG_FUNCTION_ARGS)
Definition: numeric.c:1374

◆ generate_series_step_numeric()

Datum generate_series_step_numeric ( PG_FUNCTION_ARGS  )

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

1375 {
1377  FuncCallContext *funcctx;
1378  MemoryContext oldcontext;
1379 
1380  if (SRF_IS_FIRSTCALL())
1381  {
1382  Numeric start_num = PG_GETARG_NUMERIC(0);
1383  Numeric stop_num = PG_GETARG_NUMERIC(1);
1384  NumericVar steploc = const_one;
1385 
1386  /* handle NaN in start and stop values */
1387  if (NUMERIC_IS_NAN(start_num))
1388  ereport(ERROR,
1389  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1390  errmsg("start value cannot be NaN")));
1391 
1392  if (NUMERIC_IS_NAN(stop_num))
1393  ereport(ERROR,
1394  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1395  errmsg("stop value cannot be NaN")));
1396 
1397  /* see if we were given an explicit step size */
1398  if (PG_NARGS() == 3)
1399  {
1400  Numeric step_num = PG_GETARG_NUMERIC(2);
1401 
1402  if (NUMERIC_IS_NAN(step_num))
1403  ereport(ERROR,
1404  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1405  errmsg("step size cannot be NaN")));
1406 
1407  init_var_from_num(step_num, &steploc);
1408 
1409  if (cmp_var(&steploc, &const_zero) == 0)
1410  ereport(ERROR,
1411  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1412  errmsg("step size cannot equal zero")));
1413  }
1414 
1415  /* create a function context for cross-call persistence */
1416  funcctx = SRF_FIRSTCALL_INIT();
1417 
1418  /*
1419  * Switch to memory context appropriate for multiple function calls.
1420  */
1421  oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
1422 
1423  /* allocate memory for user context */
1424  fctx = (generate_series_numeric_fctx *)
1426 
1427  /*
1428  * Use fctx to keep state from call to call. Seed current with the
1429  * original start value. We must copy the start_num and stop_num
1430  * values rather than pointing to them, since we may have detoasted
1431  * them in the per-call context.
1432  */
1433  init_var(&fctx->current);
1434  init_var(&fctx->stop);
1435  init_var(&fctx->step);
1436 
1437  set_var_from_num(start_num, &fctx->current);
1438  set_var_from_num(stop_num, &fctx->stop);
1439  set_var_from_var(&steploc, &fctx->step);
1440 
1441  funcctx->user_fctx = fctx;
1442  MemoryContextSwitchTo(oldcontext);
1443  }
1444 
1445  /* stuff done on every call of the function */
1446  funcctx = SRF_PERCALL_SETUP();
1447 
1448  /*
1449  * Get the saved state and use current state as the result of this
1450  * iteration.
1451  */
1452  fctx = funcctx->user_fctx;
1453 
1454  if ((fctx->step.sign == NUMERIC_POS &&
1455  cmp_var(&fctx->current, &fctx->stop) <= 0) ||
1456  (fctx->step.sign == NUMERIC_NEG &&
1457  cmp_var(&fctx->current, &fctx->stop) >= 0))
1458  {
1459  Numeric result = make_result(&fctx->current);
1460 
1461  /* switch to memory context appropriate for iteration calculation */
1462  oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
1463 
1464  /* increment current in preparation for next iteration */
1465  add_var(&fctx->current, &fctx->step, &fctx->current);
1466  MemoryContextSwitchTo(oldcontext);
1467 
1468  /* do when there is more left to send */
1469  SRF_RETURN_NEXT(funcctx, NumericGetDatum(result));
1470  }
1471  else
1472  /* do when there is no more left */
1473  SRF_RETURN_DONE(funcctx);
1474 }
#define SRF_IS_FIRSTCALL()
Definition: funcapi.h:294
static const NumericVar const_one
Definition: numeric.c:376
#define NumericGetDatum(X)
Definition: numeric.h:51
#define NUMERIC_POS
Definition: numeric.c:165
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
int errcode(int sqlerrcode)
Definition: elog.c:575
#define SRF_PERCALL_SETUP()
Definition: funcapi.h:298
#define SRF_RETURN_NEXT(_funcctx, _result)
Definition: funcapi.h:300
#define NUMERIC_NEG
Definition: numeric.c:166
int sign
Definition: numeric.c:274
#define ERROR
Definition: elog.h:43
static void init_var_from_num(Numeric num, NumericVar *dest)
Definition: numeric.c:5815
#define ereport(elevel, rest)
Definition: elog.h:122
static const NumericVar const_zero
Definition: numeric.c:372
static int cmp_var(const NumericVar *var1, const NumericVar *var2)
Definition: numeric.c:6559
#define PG_GETARG_NUMERIC(n)
Definition: numeric.h:52
static void set_var_from_num(Numeric value, NumericVar *dest)
Definition: numeric.c:5784
MemoryContext multi_call_memory_ctx
Definition: funcapi.h:110
static void add_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition: numeric.c:6617
#define PG_NARGS()
Definition: fmgr.h:173
static Numeric make_result(const NumericVar *var)
Definition: numeric.c:6097
void * user_fctx
Definition: funcapi.h:91
void * palloc(Size size)
Definition: mcxt.c:924
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define NUMERIC_IS_NAN(n)
Definition: numeric.c:171
static void set_var_from_var(const NumericVar *value, NumericVar *dest)
Definition: numeric.c:5832
#define init_var(v)
Definition: numeric.c:452
#define SRF_RETURN_DONE(_funcctx)
Definition: funcapi.h:318
#define SRF_FIRSTCALL_INIT()
Definition: funcapi.h:296

◆ get_str_from_var()

static char * get_str_from_var ( const NumericVar var)
static

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

5859 {
5860  int dscale;
5861  char *str;
5862  char *cp;
5863  char *endcp;
5864  int i;
5865  int d;
5866  NumericDigit dig;
5867 
5868 #if DEC_DIGITS > 1
5869  NumericDigit d1;
5870 #endif
5871 
5872  dscale = var->dscale;
5873 
5874  /*
5875  * Allocate space for the result.
5876  *
5877  * i is set to the # of decimal digits before decimal point. dscale is the
5878  * # of decimal digits we will print after decimal point. We may generate
5879  * as many as DEC_DIGITS-1 excess digits at the end, and in addition we
5880  * need room for sign, decimal point, null terminator.
5881  */
5882  i = (var->weight + 1) * DEC_DIGITS;
5883  if (i <= 0)
5884  i = 1;
5885 
5886  str = palloc(i + dscale + DEC_DIGITS + 2);
5887  cp = str;
5888 
5889  /*
5890  * Output a dash for negative values
5891  */
5892  if (var->sign == NUMERIC_NEG)
5893  *cp++ = '-';
5894 
5895  /*
5896  * Output all digits before the decimal point
5897  */
5898  if (var->weight < 0)
5899  {
5900  d = var->weight + 1;
5901  *cp++ = '0';
5902  }
5903  else
5904  {
5905  for (d = 0; d <= var->weight; d++)
5906  {
5907  dig = (d < var->ndigits) ? var->digits[d] : 0;
5908  /* In the first digit, suppress extra leading decimal zeroes */
5909 #if DEC_DIGITS == 4
5910  {
5911  bool putit = (d > 0);
5912 
5913  d1 = dig / 1000;
5914  dig -= d1 * 1000;
5915  putit |= (d1 > 0);
5916  if (putit)
5917  *cp++ = d1 + '0';
5918  d1 = dig / 100;
5919  dig -= d1 * 100;
5920  putit |= (d1 > 0);
5921  if (putit)
5922  *cp++ = d1 + '0';
5923  d1 = dig / 10;
5924  dig -= d1 * 10;
5925  putit |= (d1 > 0);
5926  if (putit)
5927  *cp++ = d1 + '0';
5928  *cp++ = dig + '0';
5929  }
5930 #elif DEC_DIGITS == 2
5931  d1 = dig / 10;
5932  dig -= d1 * 10;
5933  if (d1 > 0 || d > 0)
5934  *cp++ = d1 + '0';
5935  *cp++ = dig + '0';
5936 #elif DEC_DIGITS == 1
5937  *cp++ = dig + '0';
5938 #else
5939 #error unsupported NBASE
5940 #endif
5941  }
5942  }
5943 
5944  /*
5945  * If requested, output a decimal point and all the digits that follow it.
5946  * We initially put out a multiple of DEC_DIGITS digits, then truncate if
5947  * needed.
5948  */
5949  if (dscale > 0)
5950  {
5951  *cp++ = '.';
5952  endcp = cp + dscale;
5953  for (i = 0; i < dscale; d++, i += DEC_DIGITS)
5954  {
5955  dig = (d >= 0 && d < var->ndigits) ? var->digits[d] : 0;
5956 #if DEC_DIGITS == 4
5957  d1 = dig / 1000;
5958  dig -= d1 * 1000;
5959  *cp++ = d1 + '0';
5960  d1 = dig / 100;
5961  dig -= d1 * 100;
5962  *cp++ = d1 + '0';
5963  d1 = dig / 10;
5964  dig -= d1 * 10;
5965  *cp++ = d1 + '0';
5966  *cp++ = dig + '0';
5967 #elif DEC_DIGITS == 2
5968  d1 = dig / 10;
5969  dig -= d1 * 10;
5970  *cp++ = d1 + '0';
5971  *cp++ = dig + '0';
5972 #elif DEC_DIGITS == 1
5973  *cp++ = dig + '0';
5974 #else
5975 #error unsupported NBASE
5976 #endif
5977  }
5978  cp = endcp;
5979  }
5980 
5981  /*
5982  * terminate the string and return it
5983  */
5984  *cp = '\0';
5985  return str;
5986 }
int weight
Definition: numeric.c:273
static void error(void)
Definition: sql-dyntest.c:147
int ndigits
Definition: numeric.c:272
int dscale
Definition: numeric.c:275
#define NUMERIC_NEG
Definition: numeric.c:166
int sign
Definition: numeric.c:274
int16 NumericDigit
Definition: numeric.c:100
#define NBASE
Definition: numeric.c:94
NumericDigit * digits
Definition: numeric.c:277
void * palloc(Size size)
Definition: mcxt.c:924
int i
#define DEC_DIGITS
Definition: numeric.c:96

◆ get_str_from_var_sci()

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

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

6012 {
6013  int32 exponent;
6014  NumericVar denominator;
6015  NumericVar significand;
6016  int denom_scale;
6017  size_t len;
6018  char *str;
6019  char *sig_out;
6020 
6021  if (rscale < 0)
6022  rscale = 0;
6023 
6024  /*
6025  * Determine the exponent of this number in normalised form.
6026  *
6027  * This is the exponent required to represent the number with only one
6028  * significant digit before the decimal place.
6029  */
6030  if (var->ndigits > 0)
6031  {
6032  exponent = (var->weight + 1) * DEC_DIGITS;
6033 
6034  /*
6035  * Compensate for leading decimal zeroes in the first numeric digit by
6036  * decrementing the exponent.
6037  */
6038  exponent -= DEC_DIGITS - (int) log10(var->digits[0]);
6039  }
6040  else
6041  {
6042  /*
6043  * If var has no digits, then it must be zero.
6044  *
6045  * Zero doesn't technically have a meaningful exponent in normalised
6046  * notation, but we just display the exponent as zero for consistency
6047  * of output.
6048  */
6049  exponent = 0;
6050  }
6051 
6052  /*
6053  * The denominator is set to 10 raised to the power of the exponent.
6054  *
6055  * We then divide var by the denominator to get the significand, rounding
6056  * to rscale decimal digits in the process.
6057  */
6058  if (exponent < 0)
6059  denom_scale = -exponent;
6060  else
6061  denom_scale = 0;
6062 
6063  init_var(&denominator);
6064  init_var(&significand);
6065 
6066  power_var_int(&const_ten, exponent, &denominator, denom_scale);
6067  div_var(var, &denominator, &significand, rscale, true);
6068  sig_out = get_str_from_var(&significand);
6069 
6070  free_var(&denominator);
6071  free_var(&significand);
6072 
6073  /*
6074  * Allocate space for the result.
6075  *
6076  * In addition to the significand, we need room for the exponent
6077  * decoration ("e"), the sign of the exponent, up to 10 digits for the
6078  * exponent itself, and of course the null terminator.
6079  */
6080  len = strlen(sig_out) + 13;
6081  str = palloc(len);
6082  snprintf(str, len, "%se%+03d", sig_out, exponent);
6083 
6084  pfree(sig_out);
6085 
6086  return str;
6087 }
int weight
Definition: numeric.c:273
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
int ndigits
Definition: numeric.c:272
static void div_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result, int rscale, bool round)
Definition: numeric.c:7052
signed int int32
Definition: c.h:313
void pfree(void *pointer)
Definition: mcxt.c:1031
static void power_var_int(const NumericVar *base, int exp, NumericVar *result, int rscale)
Definition: numeric.c:8336
static const NumericVar const_ten
Definition: numeric.c:385
static void free_var(NumericVar *var)
Definition: numeric.c:5582
NumericDigit * digits
Definition: numeric.c:277
void * palloc(Size size)
Definition: mcxt.c:924
static char * get_str_from_var(const NumericVar *var)
Definition: numeric.c:5858
#define DEC_DIGITS
Definition: numeric.c:96
#define init_var(v)
Definition: numeric.c:452

◆ hash_numeric()

Datum hash_numeric ( PG_FUNCTION_ARGS  )

Definition at line 2245 of file numeric.c.

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

Referenced by JsonbHashScalarValue().

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

◆ hash_numeric_extended()

Datum hash_numeric_extended ( PG_FUNCTION_ARGS  )

Definition at line 2325 of file numeric.c.

References Assert, DatumGetUInt64, digits, hash_any_extended(), i, 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().

2326 {
2327  Numeric key = PG_GETARG_NUMERIC(0);
2328  uint64 seed = PG_GETARG_INT64(1);
2329  Datum digit_hash;
2330  Datum result;
2331  int weight;
2332  int start_offset;
2333  int end_offset;
2334  int i;
2335  int hash_len;
2337 
2338  if (NUMERIC_IS_NAN(key))
2339  PG_RETURN_UINT64(seed);
2340 
2341  weight = NUMERIC_WEIGHT(key);
2342  start_offset = 0;
2343  end_offset = 0;
2344 
2345  digits = NUMERIC_DIGITS(key);
2346  for (i = 0; i < NUMERIC_NDIGITS(key); i++)
2347  {
2348  if (digits[i] != (NumericDigit) 0)
2349  break;
2350 
2351  start_offset++;
2352 
2353  weight--;
2354  }
2355 
2356  if (NUMERIC_NDIGITS(key) == start_offset)
2357  PG_RETURN_UINT64(seed - 1);
2358 
2359  for (i = NUMERIC_NDIGITS(key) - 1; i >= 0; i--)
2360  {
2361  if (digits[i] != (NumericDigit) 0)
2362  break;
2363 
2364  end_offset++;
2365  }
2366 
2367  Assert(start_offset + end_offset < NUMERIC_NDIGITS(key));
2368 
2369  hash_len = NUMERIC_NDIGITS(key) - start_offset - end_offset;
2370  digit_hash = hash_any_extended((unsigned char *) (NUMERIC_DIGITS(key)
2371  + start_offset),
2372  hash_len * sizeof(NumericDigit),
2373  seed);
2374 
2375  result = UInt64GetDatum(DatumGetUInt64(digit_hash) ^ weight);
2376 
2377  PG_RETURN_DATUM(result);
2378 }
#define UInt64GetDatum(X)
Definition: postgres.h:633
#define PG_RETURN_UINT64(x)
Definition: fmgr.h:333
#define NUMERIC_DIGITS(num)
Definition: numeric.c:454
int16 NumericDigit
Definition: numeric.c:100
#define NUMERIC_NDIGITS(num)
Definition: numeric.c:456
uintptr_t Datum
Definition: postgres.h:367
#define PG_RETURN_DATUM(x)
Definition: fmgr.h:318
#define DatumGetUInt64(X)
Definition: postgres.h:619
#define NUMERIC_WEIGHT(n)
Definition: numeric.c:215
#define PG_GETARG_NUMERIC(n)
Definition: numeric.h:52
#define Assert(condition)
Definition: c.h:699
int i
#define NUMERIC_IS_NAN(n)
Definition: numeric.c:171
#define PG_GETARG_INT64(n)
Definition: fmgr.h:252
Datum hash_any_extended(register const unsigned char *k, register int keylen, uint64 seed)
Definition: hashfunc.c:654
int digits
Definition: informix.c:691

◆ in_range_numeric_numeric()

Datum in_range_numeric_numeric ( PG_FUNCTION_ARGS  )

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

2174 {
2176  Numeric base = PG_GETARG_NUMERIC(1);
2177  Numeric offset = PG_GETARG_NUMERIC(2);
2178  bool sub = PG_GETARG_BOOL(3);
2179  bool less = PG_GETARG_BOOL(4);
2180  bool result;
2181 
2182  /*
2183  * Reject negative or NaN offset. Negative is per spec, and NaN is
2184  * because appropriate semantics for that seem non-obvious.
2185  */
2186  if (NUMERIC_IS_NAN(offset) || NUMERIC_SIGN(offset) == NUMERIC_NEG)
2187  ereport(ERROR,
2188  (errcode(ERRCODE_INVALID_PRECEDING_FOLLOWING_SIZE),
2189  errmsg("invalid preceding or following size in window function")));
2190 
2191  /*
2192  * Deal with cases where val and/or base is NaN, following the rule that
2193  * NaN sorts after non-NaN (cf cmp_numerics). The offset cannot affect
2194  * the conclusion.
2195  */
2196  if (NUMERIC_IS_NAN(val))
2197  {
2198  if (NUMERIC_IS_NAN(base))
2199  result = true; /* NAN = NAN */
2200  else
2201  result = !less; /* NAN > non-NAN */
2202  }
2203  else if (NUMERIC_IS_NAN(base))
2204  {
2205  result = less; /* non-NAN < NAN */
2206  }
2207  else
2208  {
2209  /*
2210  * Otherwise go ahead and compute base +/- offset. While it's
2211  * possible for this to overflow the numeric format, it's unlikely
2212  * enough that we don't take measures to prevent it.
2213  */
2214  NumericVar valv;
2215  NumericVar basev;
2216  NumericVar offsetv;
2217  NumericVar sum;
2218 
2219  init_var_from_num(val, &valv);
2220  init_var_from_num(base, &basev);
2221  init_var_from_num(offset, &offsetv);
2222  init_var(&sum);
2223 
2224  if (sub)
2225  sub_var(&basev, &offsetv, &sum);
2226  else
2227  add_var(&basev, &offsetv, &sum);
2228 
2229  if (less)
2230  result = (cmp_var(&valv, &sum) <= 0);
2231  else
2232  result = (cmp_var(&valv, &sum) >= 0);
2233 
2234  free_var(&sum);
2235  }
2236 
2237  PG_FREE_IF_COPY(val, 0);
2238  PG_FREE_IF_COPY(base, 1);
2239  PG_FREE_IF_COPY(offset, 2);
2240 
2241  PG_RETURN_BOOL(result);
2242 }
int errcode(int sqlerrcode)
Definition: elog.c:575
#define PG_GETARG_BOOL(n)
Definition: fmgr.h:244
#define NUMERIC_NEG
Definition: numeric.c:166
#define ERROR
Definition: elog.h:43
static void init_var_from_num(Numeric num, NumericVar *dest)
Definition: numeric.c:5815
#define NUMERIC_SIGN(n)
Definition: numeric.c:207
#define ereport(elevel, rest)
Definition: elog.h:122
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:324
static int cmp_var(const NumericVar *var1, const NumericVar *var2)
Definition: numeric.c:6559
static void free_var(NumericVar *var)
Definition: numeric.c:5582
#define PG_GETARG_NUMERIC(n)
Definition: numeric.h:52
static void add_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition: numeric.c:6617
#define PG_FREE_IF_COPY(ptr, n)
Definition: fmgr.h:230
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define NUMERIC_IS_NAN(n)
Definition: numeric.c:171
static void sub_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition: numeric.c:6734
long val
Definition: informix.c:689
#define init_var(v)
Definition: numeric.c:452

◆ init_var_from_num()

static void init_var_from_num ( Numeric  num,
NumericVar dest 
)
static

Definition at line 5815 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(), numeric_avg_deserialize(), numeric_ceil(), numeric_deserialize(), numeric_div(), numeric_div_trunc(), numeric_exp(), numeric_floor(), numeric_inc(), numeric_int2(), numeric_int4(), numeric_int8(), numeric_ln(), numeric_log(), numeric_mod(), numeric_mul(), numeric_normalize(), numeric_out(), numeric_out_sci(), numeric_poly_deserialize(), numeric_power(), numeric_send(), numeric_sqrt(), and numeric_sub().

5816 {
5817  dest->ndigits = NUMERIC_NDIGITS(num);
5818  dest->weight = NUMERIC_WEIGHT(num);
5819  dest->sign = NUMERIC_SIGN(num);
5820  dest->dscale = NUMERIC_DSCALE(num);
5821  dest->digits = NUMERIC_DIGITS(num);
5822  dest->buf = NULL; /* digits array is not palloc'd */
5823 }
#define NUMERIC_DSCALE(n)
Definition: numeric.c:211
int weight
Definition: numeric.c:273
int ndigits
Definition: numeric.c:272
int dscale
Definition: numeric.c:275
int sign
Definition: numeric.c:274
#define NUMERIC_DIGITS(num)
Definition: numeric.c:454
#define NUMERIC_SIGN(n)
Definition: numeric.c:207
NumericDigit * buf
Definition: numeric.c:276
#define NUMERIC_NDIGITS(num)
Definition: numeric.c:456
#define NUMERIC_WEIGHT(n)
Definition: numeric.c:215
NumericDigit * digits
Definition: numeric.c:277

◆ int2_accum()

Datum int2_accum ( PG_FUNCTION_ARGS  )

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

4114 {
4116 
4117  state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
4118 
4119  /* Create the state data on the first call */
4120  if (state == NULL)
4121  state = makePolyNumAggState(fcinfo, true);
4122 
4123  if (!PG_ARGISNULL(1))
4124  {
4125 #ifdef HAVE_INT128
4126  do_int128_accum(state, (int128) PG_GETARG_INT16(1));
4127 #else
4128  Numeric newval;
4129 
4131  PG_GETARG_DATUM(1)));
4132  do_numeric_accum(state, newval);
4133 #endif
4134  }
4135 
4136  PG_RETURN_POINTER(state);
4137 }
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:326
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:238
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:246
Datum int2_numeric(PG_FUNCTION_ARGS)
Definition: numeric.c:3176
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:590
static void do_numeric_accum(NumericAggState *state, Numeric newval)
Definition: numeric.c:3423
#define PG_GETARG_INT16(n)
Definition: fmgr.h:241
#define PG_ARGISNULL(n)
Definition: fmgr.h:179
#define DatumGetNumeric(X)
Definition: numeric.h:49
Definition: regguts.h:298
#define newval
#define makePolyNumAggState
Definition: numeric.c:4108

◆ int2_accum_inv()

Datum int2_accum_inv ( PG_FUNCTION_ARGS  )

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

4591 {
4593 
4594  state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
4595 
4596  /* Should not get here with no state */
4597  if (state == NULL)
4598  elog(ERROR, "int2_accum_inv called with NULL state");
4599 
4600  if (!PG_ARGISNULL(1))
4601  {
4602 #ifdef HAVE_INT128
4603  do_int128_discard(state, (int128) PG_GETARG_INT16(1));
4604 #else
4605  Numeric newval;
4606 
4608  PG_GETARG_DATUM(1)));
4609 
4610  /* Should never fail, all inputs have dscale 0 */
4611  if (!do_numeric_discard(state, newval))
4612  elog(ERROR, "do_numeric_discard failed unexpectedly");
4613 #endif
4614  }
4615 
4616  PG_RETURN_POINTER(state);
4617 }
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:326
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:238
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:246
Datum int2_numeric(PG_FUNCTION_ARGS)
Definition: numeric.c:3176
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:590
static bool do_numeric_discard(NumericAggState *state, Numeric newval)
Definition: numeric.c:3488
#define ERROR
Definition: elog.h:43
#define PG_GETARG_INT16(n)
Definition: fmgr.h:241
#define PG_ARGISNULL(n)
Definition: fmgr.h:179
#define DatumGetNumeric(X)
Definition: numeric.h:49
Definition: regguts.h:298
#define newval
#define elog
Definition: elog.h:219

◆ int2_avg_accum()

Datum int2_avg_accum ( PG_FUNCTION_ARGS  )

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

5282 {
5283  ArrayType *transarray;
5285  Int8TransTypeData *transdata;
5286 
5287  /*
5288  * If we're invoked as an aggregate, we can cheat and modify our first
5289  * parameter in-place to reduce palloc overhead. Otherwise we need to make
5290  * a copy of it before scribbling on it.
5291  */
5292  if (AggCheckCallContext(fcinfo, NULL))
5293  transarray = PG_GETARG_ARRAYTYPE_P(0);
5294  else
5295  transarray = PG_GETARG_ARRAYTYPE_P_COPY(0);
5296 
5297  if (ARR_HASNULL(transarray) ||
5298  ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
5299  elog(ERROR, "expected 2-element int8 array");
5300 
5301  transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
5302  transdata->count++;
5303  transdata->sum += newval;
5304 
5305  PG_RETURN_ARRAYTYPE_P(transarray);
5306 }
signed short int16
Definition: c.h:312
#define ARR_OVERHEAD_NONULLS(ndims)
Definition: array.h:295
#define ARR_SIZE(a)
Definition: array.h:274
#define PG_GETARG_ARRAYTYPE_P_COPY(n)
Definition: array.h:249
#define PG_GETARG_ARRAYTYPE_P(n)
Definition: array.h:248
#define ERROR
Definition: elog.h:43
#define ARR_DATA_PTR(a)
Definition: array.h:307
#define ARR_HASNULL(a)
Definition: array.h:276
#define PG_RETURN_ARRAYTYPE_P(x)
Definition: array.h:250
#define PG_GETARG_INT16(n)
Definition: fmgr.h:241
#define newval
int AggCheckCallContext(FunctionCallInfo fcinfo, MemoryContext *aggcontext)
Definition: nodeAgg.c:3492
#define elog
Definition: elog.h:219

◆ int2_avg_accum_inv()

Datum int2_avg_accum_inv ( PG_FUNCTION_ARGS  )

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

5369 {
5370  ArrayType *transarray;
5372  Int8TransTypeData *transdata;
5373 
5374  /*
5375  * If we're invoked as an aggregate, we can cheat and modify our first
5376  * parameter in-place to reduce palloc overhead. Otherwise we need to make
5377  * a copy of it before scribbling on it.
5378  */
5379  if (AggCheckCallContext(fcinfo, NULL))
5380  transarray = PG_GETARG_ARRAYTYPE_P(0);
5381  else
5382  transarray = PG_GETARG_ARRAYTYPE_P_COPY(0);
5383 
5384  if (ARR_HASNULL(transarray) ||
5385  ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
5386  elog(ERROR, "expected 2-element int8 array");
5387 
5388  transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
5389  transdata->count--;
5390  transdata->sum -= newval;
5391 
5392  PG_RETURN_ARRAYTYPE_P(transarray);
5393 }
signed short int16
Definition: c.h:312
#define ARR_OVERHEAD_NONULLS(ndims)
Definition: array.h:295
#define ARR_SIZE(a)
Definition: array.h:274
#define PG_GETARG_ARRAYTYPE_P_COPY(n)
Definition: array.h:249
#define PG_GETARG_ARRAYTYPE_P(n)
Definition: array.h:248
#define ERROR
Definition: elog.h:43
#define ARR_DATA_PTR(a)
Definition: array.h:307
#define ARR_HASNULL(a)
Definition: array.h:276
#define PG_RETURN_ARRAYTYPE_P(x)
Definition: array.h:250
#define PG_GETARG_INT16(n)
Definition: fmgr.h:241
#define newval
int AggCheckCallContext(FunctionCallInfo fcinfo, MemoryContext *aggcontext)
Definition: nodeAgg.c:3492
#define elog
Definition: elog.h:219

◆ int2_numeric()

Datum int2_numeric ( PG_FUNCTION_ARGS  )

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

3177 {
3178  int16 val = PG_GETARG_INT16(0);
3179  Numeric res;
3180  NumericVar result;
3181 
3182  init_var(&result);
3183 
3184  int64_to_numericvar((int64) val, &result);
3185 
3186  res = make_result(&result);
3187 
3188  free_var(&result);
3189 
3190  PG_RETURN_NUMERIC(res);
3191 }
#define PG_RETURN_NUMERIC(x)
Definition: numeric.h:54
signed short int16
Definition: c.h:312
#define PG_GETARG_INT16(n)
Definition: fmgr.h:241
static void free_var(NumericVar *var)
Definition: numeric.c:5582
static Numeric make_result(const NumericVar *var)
Definition: numeric.c:6097
static void int64_to_numericvar(int64 val, NumericVar *var)
Definition: numeric.c:6335
long val
Definition: informix.c:689
#define init_var(v)
Definition: numeric.c:452

◆ int2_sum()

Datum int2_sum ( PG_FUNCTION_ARGS  )

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

5130 {
5131  int64 newval;
5132 
5133  if (PG_ARGISNULL(0))
5134  {
5135  /* No non-null input seen so far... */
5136  if (PG_ARGISNULL(1))
5137  PG_RETURN_NULL(); /* still no non-null */
5138  /* This is the first non-null input. */
5139  newval = (int64) PG_GETARG_INT16(1);
5140  PG_RETURN_INT64(newval);
5141  }
5142 
5143  /*
5144  * If we're invoked as an aggregate, we can cheat and modify our first
5145  * parameter in-place to avoid palloc overhead. If not, we need to return
5146  * the new value of the transition variable. (If int8 is pass-by-value,
5147  * then of course this is useless as well as incorrect, so just ifdef it
5148  * out.)
5149  */
5150 #ifndef USE_FLOAT8_BYVAL /* controls int8 too */
5151  if (AggCheckCallContext(fcinfo, NULL))
5152  {
5153  int64 *oldsum = (int64 *) PG_GETARG_POINTER(0);
5154 
5155  /* Leave the running sum unchanged in the new input is null */
5156  if (!PG_ARGISNULL(1))
5157  *oldsum = *oldsum + (int64) PG_GETARG_INT16(1);
5158 
5159  PG_RETURN_POINTER(oldsum);
5160  }
5161  else
5162 #endif
5163  {
5164  int64 oldsum = PG_GETARG_INT64(0);
5165 
5166  /* Leave sum unchanged if new input is null. */
5167  if (PG_ARGISNULL(1))
5168  PG_RETURN_INT64(oldsum);
5169 
5170  /* OK to do the addition. */
5171  newval = oldsum + (int64) PG_GETARG_INT16(1);
5172 
5173  PG_RETURN_INT64(newval);
5174  }
5175 }
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:326
#define PG_RETURN_INT64(x)
Definition: fmgr.h:332
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:246
#define PG_GETARG_INT16(n)
Definition: fmgr.h:241
#define PG_ARGISNULL(n)
Definition: fmgr.h:179
#define newval
int AggCheckCallContext(FunctionCallInfo fcinfo, MemoryContext *aggcontext)
Definition: nodeAgg.c:3492
#define PG_GETARG_INT64(n)
Definition: fmgr.h:252
#define PG_RETURN_NULL()
Definition: fmgr.h:310

◆ int2int4_sum()

Datum int2int4_sum ( PG_FUNCTION_ARGS  )

Definition at line 5453 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, NumericVar::sign, generate_unaccent_rules::str, Int8TransTypeData::sum, and NumericVar::weight.

5454 {
5455  ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
5456  Int8TransTypeData *transdata;
5457 
5458  if (ARR_HASNULL(transarray) ||
5459  ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
5460  elog(ERROR, "expected 2-element int8 array");
5461  transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
5462 
5463  /* SQL defines SUM of no values to be NULL */
5464  if (transdata->count == 0)
5465  PG_RETURN_NULL();
5466 
5467  PG_RETURN_DATUM(Int64GetDatumFast(transdata->sum));
5468 }
#define ARR_OVERHEAD_NONULLS(ndims)
Definition: array.h:295
#define ARR_SIZE(a)
Definition: array.h:274
#define PG_GETARG_ARRAYTYPE_P(n)
Definition: array.h:248
#define ERROR
Definition: elog.h:43
#define ARR_DATA_PTR(a)
Definition: array.h:307
#define ARR_HASNULL(a)
Definition: array.h:276
#define PG_RETURN_DATUM(x)
Definition: fmgr.h:318
#define Int64GetDatumFast(X)
Definition: postgres.h:760
#define elog
Definition: elog.h:219
#define PG_RETURN_NULL()
Definition: fmgr.h:310

◆ int4_accum()

Datum int4_accum ( PG_FUNCTION_ARGS  )

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

4141 {
4143 
4144  state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
4145 
4146  /* Create the state data on the first call */
4147  if (state == NULL)
4148  state = makePolyNumAggState(fcinfo, true);
4149 
4150  if (!PG_ARGISNULL(1))
4151  {
4152 #ifdef HAVE_INT128
4153  do_int128_accum(state, (int128) PG_GETARG_INT32(1));
4154 #else
4155  Numeric newval;
4156 
4158  PG_GETARG_DATUM(1)));
4159  do_numeric_accum(state, newval);
4160 #endif
4161  }
4162 
4163  PG_RETURN_POINTER(state);
4164 }
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:326
#define PG_GETARG_INT32(n)
Definition: fmgr.h:239
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:238
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:246
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:590
static void do_numeric_accum(NumericAggState *state, Numeric newval)
Definition: numeric.c:3423
Datum int4_numeric(PG_FUNCTION_ARGS)
Definition: numeric.c:3066
#define PG_ARGISNULL(n)
Definition: fmgr.h:179
#define DatumGetNumeric(X)
Definition: numeric.h:49
Definition: regguts.h:298
#define newval
#define makePolyNumAggState
Definition: numeric.c:4108

◆ int4_accum_inv()

Datum int4_accum_inv ( PG_FUNCTION_ARGS  )

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

4621 {
4623 
4624  state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
4625 
4626  /* Should not get here with no state */
4627  if (state == NULL)
4628  elog(ERROR, "int4_accum_inv called with NULL state");
4629 
4630  if (!PG_ARGISNULL(1))
4631  {
4632 #ifdef HAVE_INT128
4633  do_int128_discard(state, (int128) PG_GETARG_INT32(1));
4634 #else
4635  Numeric newval;
4636 
4638  PG_GETARG_DATUM(1)));
4639 
4640  /* Should never fail, all inputs have dscale 0 */
4641  if (!do_numeric_discard(state, newval))
4642  elog(ERROR, "do_numeric_discard failed unexpectedly");
4643 #endif
4644  }
4645 
4646  PG_RETURN_POINTER(state);
4647 }
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:326
#define PG_GETARG_INT32(n)
Definition: fmgr.h:239
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:238
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:246
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:590
static bool do_numeric_discard(NumericAggState *state, Numeric newval)
Definition: numeric.c:3488
#define ERROR
Definition: elog.h:43
Datum int4_numeric(PG_FUNCTION_ARGS)
Definition: numeric.c:3066
#define PG_ARGISNULL(n)
Definition: fmgr.h:179
#define DatumGetNumeric(X)
Definition: numeric.h:49
Definition: regguts.h:298
#define newval
#define elog
Definition: elog.h:219

◆ int4_avg_accum()

Datum int4_avg_accum ( PG_FUNCTION_ARGS  )

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

5310 {
5311  ArrayType *transarray;
5313  Int8TransTypeData *transdata;
5314 
5315  /*
5316  * If we're invoked as an aggregate, we can cheat and modify our first
5317  * parameter in-place to reduce palloc overhead. Otherwise we need to make
5318  * a copy of it before scribbling on it.
5319  */
5320  if (AggCheckCallContext(fcinfo, NULL))
5321  transarray = PG_GETARG_ARRAYTYPE_P(0);
5322  else
5323  transarray = PG_GETARG_ARRAYTYPE_P_COPY(0);
5324 
5325  if (ARR_HASNULL(transarray) ||
5326  ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
5327  elog(ERROR, "expected 2-element int8 array");
5328 
5329  transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
5330  transdata->count++;
5331  transdata->sum += newval;
5332 
5333  PG_RETURN_ARRAYTYPE_P(transarray);
5334 }
#define PG_GETARG_INT32(n)
Definition: fmgr.h:239
#define ARR_OVERHEAD_NONULLS(ndims)
Definition: array.h:295
#define ARR_SIZE(a)
Definition: array.h:274
#define PG_GETARG_ARRAYTYPE_P_COPY(n)
Definition: array.h:249
signed int int32
Definition: c.h:313
#define PG_GETARG_ARRAYTYPE_P(n)
Definition: array.h:248
#define ERROR
Definition: elog.h:43
#define ARR_DATA_PTR(a)
Definition: array.h:307
#define ARR_HASNULL(a)
Definition: array.h:276
#define PG_RETURN_ARRAYTYPE_P(x)
Definition: array.h:250
#define newval
int AggCheckCallContext(FunctionCallInfo fcinfo, MemoryContext *aggcontext)
Definition: nodeAgg.c:3492
#define elog
Definition: elog.h:219

◆ int4_avg_accum_inv()

Datum int4_avg_accum_inv ( PG_FUNCTION_ARGS  )

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

5397 {
5398  ArrayType *transarray;
5400  Int8TransTypeData *transdata;
5401 
5402  /*
5403  * If we're invoked as an aggregate, we can cheat and modify our first
5404  * parameter in-place to reduce palloc overhead. Otherwise we need to make
5405  * a copy of it before scribbling on it.
5406  */
5407  if (AggCheckCallContext(fcinfo, NULL))
5408  transarray = PG_GETARG_ARRAYTYPE_P(0);
5409  else
5410  transarray = PG_GETARG_ARRAYTYPE_P_COPY(0);
5411 
5412  if (ARR_HASNULL(transarray) ||
5413  ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
5414  elog(ERROR, "expected 2-element int8 array");
5415 
5416  transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
5417  transdata->count--;
5418  transdata->sum -= newval;
5419 
5420  PG_RETURN_ARRAYTYPE_P(transarray);
5421 }
#define PG_GETARG_INT32(n)
Definition: fmgr.h:239
#define ARR_OVERHEAD_NONULLS(ndims)
Definition: array.h:295
#define ARR_SIZE(a)
Definition: array.h:274
#define PG_GETARG_ARRAYTYPE_P_COPY(n)
Definition: array.h:249
signed int int32
Definition: c.h:313
#define PG_GETARG_ARRAYTYPE_P(n)
Definition: array.h:248
#define ERROR
Definition: elog.h:43
#define ARR_DATA_PTR(a)
Definition: array.h:307
#define ARR_HASNULL(a)
Definition: array.h:276
#define PG_RETURN_ARRAYTYPE_P(x)
Definition: array.h:250
#define newval
int AggCheckCallContext(FunctionCallInfo fcinfo, MemoryContext *aggcontext)
Definition: nodeAgg.c:3492
#define elog
Definition: elog.h:219

◆ int4_avg_combine()

Datum int4_avg_combine ( PG_FUNCTION_ARGS  )

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

5338 {
5339  ArrayType *transarray1;
5340  ArrayType *transarray2;
5341  Int8TransTypeData *state1;
5342  Int8TransTypeData *state2;
5343 
5344  if (!AggCheckCallContext(fcinfo, NULL))
5345  elog(ERROR, "aggregate function called in non-aggregate context");
5346 
5347  transarray1 = PG_GETARG_ARRAYTYPE_P(0);
5348  transarray2 = PG_GETARG_ARRAYTYPE_P(1);
5349 
5350  if (ARR_HASNULL(transarray1) ||
5351  ARR_SIZE(transarray1) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
5352  elog(ERROR, "expected 2-element int8 array");
5353 
5354  if (ARR_HASNULL(transarray2) ||
5355  ARR_SIZE(transarray2) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
5356  elog(ERROR, "expected 2-element int8 array");
5357 
5358  state1 = (Int8TransTypeData *) ARR_DATA_PTR(transarray1);
5359  state2 = (Int8TransTypeData *) ARR_DATA_PTR(transarray2);
5360 
5361  state1->count += state2->count;
5362  state1->sum += state2->sum;
5363 
5364  PG_RETURN_ARRAYTYPE_P(transarray1);
5365 }
#define ARR_OVERHEAD_NONULLS(ndims)
Definition: array.h:295
#define ARR_SIZE(a)
Definition: array.h:274
#define PG_GETARG_ARRAYTYPE_P(n)
Definition: array.h:248
#define ERROR
Definition: elog.h:43
#define ARR_DATA_PTR(a)
Definition: array.h:307
#define ARR_HASNULL(a)
Definition: array.h:276
#define PG_RETURN_ARRAYTYPE_P(x)
Definition: array.h:250
int AggCheckCallContext(FunctionCallInfo fcinfo, MemoryContext *aggcontext)
Definition: nodeAgg.c:3492
#define elog
Definition: elog.h:219

◆ int4_numeric()

Datum int4_numeric ( PG_FUNCTION_ARGS  )

Definition at line 3066 of file numeric.c.

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

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

3067 {
3068  int32 val = PG_GETARG_INT32(0);
3069  Numeric res;
3070  NumericVar result;
3071 
3072  init_var(&result);
3073 
3074  int64_to_numericvar((int64) val, &result);
3075 
3076  res = make_result(&result);
3077 
3078  free_var(&result);
3079 
3080  PG_RETURN_NUMERIC(res);
3081 }
#define PG_RETURN_NUMERIC(x)
Definition: numeric.h:54
#define PG_GETARG_INT32(n)
Definition: fmgr.h:239
signed int int32
Definition: c.h:313
static void free_var(NumericVar *var)
Definition: numeric.c:5582
static Numeric make_result(const NumericVar *var)
Definition: numeric.c:6097
static void int64_to_numericvar(int64 val, NumericVar *var)
Definition: numeric.c:6335
long val
Definition: informix.c:689
#define init_var(v)
Definition: numeric.c:452

◆ int4_sum()

Datum int4_sum ( PG_FUNCTION_ARGS  )

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

5179 {
5180  int64 newval;
5181 
5182  if (PG_ARGISNULL(0))
5183  {
5184  /* No non-null input seen so far... */
5185  if (PG_ARGISNULL(1))
5186  PG_RETURN_NULL(); /* still no non-null */
5187  /* This is the first non-null input. */
5188  newval = (int64) PG_GETARG_INT32(1);
5189  PG_RETURN_INT64(newval);
5190  }
5191 
5192  /*
5193  * If we're invoked as an aggregate, we can cheat and modify our first
5194  * parameter in-place to avoid palloc overhead. If not, we need to return
5195  * the new value of the transition variable. (If int8 is pass-by-value,
5196  * then of course this is useless as well as incorrect, so just ifdef it
5197  * out.)
5198  */
5199 #ifndef USE_FLOAT8_BYVAL /* controls int8 too */
5200  if (AggCheckCallContext(fcinfo, NULL))
5201  {
5202  int64 *oldsum = (int64 *) PG_GETARG_POINTER(0);
5203 
5204  /* Leave the running sum unchanged in the new input is null */
5205  if (!PG_ARGISNULL(1))
5206  *oldsum = *oldsum + (int64) PG_GETARG_INT32(1);
5207 
5208  PG_RETURN_POINTER(oldsum);
5209  }
5210  else
5211 #endif
5212  {
5213  int64 oldsum = PG_GETARG_INT64(0);
5214 
5215  /* Leave sum unchanged if new input is null. */
5216  if (PG_ARGISNULL(1))
5217  PG_RETURN_INT64(oldsum);
5218 
5219  /* OK to do the addition. */
5220  newval = oldsum + (int64) PG_GETARG_INT32(1);
5221 
5222  PG_RETURN_INT64(newval);
5223  }
5224 }
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:326
#define PG_GETARG_INT32(n)
Definition: fmgr.h:239
#define PG_RETURN_INT64(x)
Definition: fmgr.h:332
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:246
#define PG_ARGISNULL(n)
Definition: fmgr.h:179
#define newval
int AggCheckCallContext(FunctionCallInfo fcinfo, MemoryContext *aggcontext)
Definition: nodeAgg.c:3492
#define PG_GETARG_INT64(n)
Definition: fmgr.h:252
#define PG_RETURN_NULL()
Definition: fmgr.h:310

◆ int64_to_numericvar()

static void int64_to_numericvar ( int64  val,
NumericVar var 
)
static

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

6336 {
6337  uint64 uval,
6338  newuval;
6339  NumericDigit *ptr;
6340  int ndigits;
6341 
6342  /* int64 can require at most 19 decimal digits; add one for safety */
6343  alloc_var(var, 20 / DEC_DIGITS);
6344  if (val < 0)
6345  {
6346  var->sign = NUMERIC_NEG;
6347  uval = -val;
6348  }
6349  else
6350  {
6351  var->sign = NUMERIC_POS;
6352  uval = val;
6353  }
6354  var->dscale = 0;
6355  if (val == 0)
6356  {
6357  var->ndigits = 0;
6358  var->weight = 0;
6359  return;
6360  }
6361  ptr = var->digits + var->ndigits;
6362  ndigits = 0;
6363  do
6364  {
6365  ptr--;
6366  ndigits++;
6367  newuval = uval / NBASE;
6368  *ptr = uval - newuval * NBASE;
6369  uval = newuval;
6370  } while (uval);
6371  var->digits = ptr;
6372  var->ndigits = ndigits;
6373  var->weight = ndigits - 1;
6374 }
int weight
Definition: numeric.c:273
#define NUMERIC_POS
Definition: numeric.c:165
int ndigits
Definition: numeric.c:272
int dscale
Definition: numeric.c:275
#define NUMERIC_NEG
Definition: numeric.c:166
int sign
Definition: numeric.c:274
int16 NumericDigit
Definition: numeric.c:100
#define NBASE
Definition: numeric.c:94
NumericDigit * digits
Definition: numeric.c:277
static void alloc_var(NumericVar *var, int ndigits)
Definition: numeric.c:5566
#define DEC_DIGITS
Definition: numeric.c:96
long val
Definition: informix.c:689

◆ int8_accum()

Datum int8_accum ( PG_FUNCTION_ARGS  )

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

4168 {
4170 
4171  state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
4172 
4173  /* Create the state data on the first call */
4174  if (state == NULL)
4175  state = makeNumericAggState(fcinfo, true);
4176 
4177  if (!PG_ARGISNULL(1))
4178  {
4179  Numeric newval;
4180 
4182  PG_GETARG_DATUM(1)));
4183  do_numeric_accum(state, newval);
4184  }
4185 
4186  PG_RETURN_POINTER(state);
4187 }
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:326
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:238
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:246
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:590
Datum int8_numeric(PG_FUNCTION_ARGS)
Definition: numeric.c:3132
static NumericAggState * makeNumericAggState(FunctionCallInfo fcinfo, bool calcSumX2)
Definition: numeric.c:3383
static void do_numeric_accum(NumericAggState *state, Numeric newval)
Definition: numeric.c:3423
#define PG_ARGISNULL(n)
Definition: fmgr.h:179
#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 4650 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.

4651 {
4653 
4654  state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
4655 
4656  /* Should not get here with no state */
4657  if (state == NULL)
4658  elog(ERROR, "int8_accum_inv called with NULL state");
4659 
4660  if (!PG_ARGISNULL(1))
4661  {
4662  Numeric newval;
4663 
4665  PG_GETARG_DATUM(1)));
4666 
4667  /* Should never fail, all inputs have dscale 0 */
4668  if (!do_numeric_discard(state, newval))
4669  elog(ERROR, "do_numeric_discard failed unexpectedly");
4670  }
4671 
4672  PG_RETURN_POINTER(state);
4673 }
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:326
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:238
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:246
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:590
static bool do_numeric_discard(NumericAggState *state, Numeric newval)
Definition: numeric.c:3488
Datum int8_numeric(PG_FUNCTION_ARGS)
Definition: numeric.c:3132
#define ERROR
Definition: elog.h:43
#define PG_ARGISNULL(n)
Definition: fmgr.h:179
#define DatumGetNumeric(X)
Definition: numeric.h:49
Definition: regguts.h:298
#define newval
#define elog
Definition: elog.h:219

◆ int8_avg()

Datum int8_avg ( PG_FUNCTION_ARGS  )

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

5425 {
5426  ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
5427  Int8TransTypeData *transdata;
5428  Datum countd,
5429  sumd;
5430 
5431  if (ARR_HASNULL(transarray) ||
5432  ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
5433  elog(ERROR, "expected 2-element int8 array");
5434  transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
5435 
5436  /* SQL defines AVG of no values to be NULL */
5437  if (transdata->count == 0)
5438  PG_RETURN_NULL();
5439 
5441  Int64GetDatumFast(transdata->count));
5443  Int64GetDatumFast(transdata->sum));
5444 
5446 }
#define ARR_OVERHEAD_NONULLS(ndims)
Definition: array.h:295
#define ARR_SIZE(a)
Definition: array.h:274
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:590
Datum int8_numeric(PG_FUNCTION_ARGS)
Definition: numeric.c:3132
Datum numeric_div(PG_FUNCTION_ARGS)
Definition: numeric.c:2513
#define PG_GETARG_ARRAYTYPE_P(n)
Definition: array.h:248
#define ERROR
Definition: elog.h:43