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 "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) SET_4_BYTES(X))
 
#define DatumGetNumericAbbrev(X)   ((int32) GET_4_BYTES(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 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) GET_4_BYTES(X))

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

Referenced by div_var_fast().

◆ dump_numeric

#define dump_numeric (   s,
 
)

Definition at line 439 of file numeric.c.

Referenced by int2int4_sum(), and make_result().

◆ dump_var

#define dump_var (   s,
 
)

Definition at line 440 of file numeric.c.

Referenced by int2int4_sum().

◆ HALF_NBASE

#define HALF_NBASE   5000

Definition at line 94 of file numeric.c.

Referenced by div_var(), and round_var().

◆ init_var

◆ makePolyNumAggState

#define makePolyNumAggState   makeNumericAggState

◆ makePolyNumAggStateCurrentContext

#define makePolyNumAggStateCurrentContext   makeNumericAggStateCurrentContext

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

Referenced by mul_var().

◆ NBASE

◆ NUMERIC_ABBREV_BITS

#define NUMERIC_ABBREV_BITS   (SIZEOF_DATUM * BITS_PER_BYTE)

Definition at line 354 of file numeric.c.

◆ NUMERIC_ABBREV_NAN

#define NUMERIC_ABBREV_NAN   NumericAbbrevGetDatum(PG_INT32_MIN)

Definition at line 362 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:197
int scale
Definition: pgbench.c:108
#define NUMERIC_SHORT_WEIGHT_MIN
Definition: numeric.c:198
#define NUMERIC_SHORT_DSCALE_MAX
Definition: numeric.c:193

Definition at line 457 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:181

Definition at line 453 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:181
#define NUMERIC_DSCALE_MASK
Definition: numeric.c:204
#define NUMERIC_SHORT_DSCALE_MASK
Definition: numeric.c:191
#define NUMERIC_SHORT_DSCALE_SHIFT
Definition: numeric.c:192

Definition at line 210 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 204 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 169 of file numeric.c.

◆ NUMERIC_HDRSZ

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

Definition at line 173 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 174 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 181 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:283
#define NUMERIC_HEADER_IS_SHORT(n)
Definition: numeric.c:181
#define VARHDRSZ
Definition: c.h:493
unsigned short uint16
Definition: c.h:295

Definition at line 182 of file numeric.c.

◆ NUMERIC_IS_NAN

◆ NUMERIC_IS_SHORT

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

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

Referenced by make_result().

◆ NUMERIC_SHORT_DSCALE_MASK

#define NUMERIC_SHORT_DSCALE_MASK   0x1F80

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

◆ NUMERIC_SHORT_DSCALE_SHIFT

#define NUMERIC_SHORT_DSCALE_SHIFT   7

Definition at line 192 of file numeric.c.

Referenced by make_result(), and numeric().

◆ NUMERIC_SHORT_SIGN_MASK

#define NUMERIC_SHORT_SIGN_MASK   0x2000

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

Referenced by make_result().

◆ NUMERIC_SHORT_WEIGHT_MAX

#define NUMERIC_SHORT_WEIGHT_MAX   NUMERIC_SHORT_WEIGHT_MASK

Definition at line 197 of file numeric.c.

◆ NUMERIC_SHORT_WEIGHT_MIN

#define NUMERIC_SHORT_WEIGHT_MIN   (-(NUMERIC_SHORT_WEIGHT_MASK+1))

Definition at line 198 of file numeric.c.

◆ NUMERIC_SHORT_WEIGHT_SIGN_MASK

#define NUMERIC_SHORT_WEIGHT_SIGN_MASK   0x0040

Definition at line 195 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:164
#define NUMERIC_FLAGBITS(n)
Definition: numeric.c:169
#define NUMERIC_SHORT_SIGN_MASK
Definition: numeric.c:190
#define NUMERIC_IS_SHORT(n)
Definition: numeric.c:171

Definition at line 206 of file numeric.c.

Referenced by cmp_numerics(), 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 163 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:181
#define NUMERIC_SHORT_WEIGHT_SIGN_MASK
Definition: numeric.c:195
#define NUMERIC_SHORT_WEIGHT_MASK
Definition: numeric.c:196

Definition at line 214 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) SET_4_BYTES(X))

Definition at line 360 of file numeric.c.

Referenced by numeric_cmp_abbrev().

Typedef Documentation

◆ Int8TransTypeData

◆ NumericAggState

◆ NumericDigit

Definition at line 99 of file numeric.c.

◆ NumericSumAccum

◆ NumericVar

◆ PolyNumAggState

Definition at line 4013 of file numeric.c.

Function Documentation

◆ accum_sum_add()

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

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

8899 {
8900  int32 *accum_digits;
8901  int i,
8902  val_i;
8903  int val_ndigits;
8904  NumericDigit *val_digits;
8905 
8906  /*
8907  * If we have accumulated too many values since the last carry
8908  * propagation, do it now, to avoid overflowing. (We could allow more
8909  * than NBASE - 1, if we reserved two extra digits, rather than one, for
8910  * carry propagation. But even with NBASE - 1, this needs to be done so
8911  * seldom, that the performance difference is negligible.)
8912  */
8913  if (accum->num_uncarried == NBASE - 1)
8914  accum_sum_carry(accum);
8915 
8916  /*
8917  * Adjust the weight or scale of the old value, so that it can accommodate
8918  * the new value.
8919  */
8920  accum_sum_rescale(accum, val);
8921 
8922  /* */
8923  if (val->sign == NUMERIC_POS)
8924  accum_digits = accum->pos_digits;
8925  else
8926  accum_digits = accum->neg_digits;
8927 
8928  /* copy these values into local vars for speed in loop */
8929  val_ndigits = val->ndigits;
8930  val_digits = val->digits;
8931 
8932  i = accum->weight - val->weight;
8933  for (val_i = 0; val_i < val_ndigits; val_i++)
8934  {
8935  accum_digits[i] += (int32) val_digits[val_i];
8936  i++;
8937  }
8938 
8939  accum->num_uncarried++;
8940 }
static void accum_sum_rescale(NumericSumAccum *accum, const NumericVar *val)
Definition: numeric.c:9019
#define NUMERIC_POS
Definition: numeric.c:164
int32 * neg_digits
Definition: numeric.c:344
int num_uncarried
Definition: numeric.c:341
static void accum_sum_carry(NumericSumAccum *accum)
Definition: numeric.c:8946
signed int int32
Definition: c.h:284
int16 NumericDigit
Definition: numeric.c:99
#define NBASE
Definition: numeric.c:93
int i
int32 * pos_digits
Definition: numeric.c:343
long val
Definition: informix.c:689

◆ accum_sum_carry()

static void accum_sum_carry ( NumericSumAccum accum)
static

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

8947 {
8948  int i;
8949  int ndigits;
8950  int32 *dig;
8951  int32 carry;
8952  int32 newdig = 0;
8953 
8954  /*
8955  * If no new values have been added since last carry propagation, nothing
8956  * to do.
8957  */
8958  if (accum->num_uncarried == 0)
8959  return;
8960 
8961  /*
8962  * We maintain that the weight of the accumulator is always one larger
8963  * than needed to hold the current value, before carrying, to make sure
8964  * there is enough space for the possible extra digit when carry is
8965  * propagated. We cannot expand the buffer here, unless we require
8966  * callers of accum_sum_final() to switch to the right memory context.
8967  */
8968  Assert(accum->pos_digits[0] == 0 && accum->neg_digits[0] == 0);
8969 
8970  ndigits = accum->ndigits;
8971 
8972  /* Propagate carry in the positive sum */
8973  dig = accum->pos_digits;
8974  carry = 0;
8975  for (i = ndigits - 1; i >= 0; i--)
8976  {
8977  newdig = dig[i] + carry;
8978  if (newdig >= NBASE)
8979  {
8980  carry = newdig / NBASE;
8981  newdig -= carry * NBASE;
8982  }
8983  else
8984  carry = 0;
8985  dig[i] = newdig;
8986  }
8987  /* Did we use up the digit reserved for carry propagation? */
8988  if (newdig > 0)
8989  accum->have_carry_space = false;
8990 
8991  /* And the same for the negative sum */
8992  dig = accum->neg_digits;
8993  carry = 0;
8994  for (i = ndigits - 1; i >= 0; i--)
8995  {
8996  newdig = dig[i] + carry;
8997  if (newdig >= NBASE)
8998  {
8999  carry = newdig / NBASE;
9000  newdig -= carry * NBASE;
9001  }
9002  else
9003  carry = 0;
9004  dig[i] = newdig;
9005  }
9006  if (newdig > 0)
9007  accum->have_carry_space = false;
9008 
9009  accum->num_uncarried = 0;
9010 }
int32 * neg_digits
Definition: numeric.c:344
int num_uncarried
Definition: numeric.c:341
signed int int32
Definition: c.h:284
bool have_carry_space
Definition: numeric.c:342
#define NBASE
Definition: numeric.c:93
#define Assert(condition)
Definition: c.h:670
int i
int32 * pos_digits
Definition: numeric.c:343

◆ accum_sum_combine()

static void accum_sum_combine ( NumericSumAccum accum,
NumericSumAccum accum2 
)
static

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

9177 {
9178  NumericVar tmp_var;
9179 
9180  init_var(&tmp_var);
9181 
9182  accum_sum_final(accum2, &tmp_var);
9183  accum_sum_add(accum, &tmp_var);
9184 
9185  free_var(&tmp_var);
9186 }
static void accum_sum_final(NumericSumAccum *accum, NumericVar *result)
Definition: numeric.c:9108
static void accum_sum_add(NumericSumAccum *accum, const NumericVar *var1)
Definition: numeric.c:8898
static void free_var(NumericVar *var)
Definition: numeric.c:5488
#define init_var(v)
Definition: numeric.c:451

◆ accum_sum_copy()

static void accum_sum_copy ( NumericSumAccum dst,
NumericSumAccum src 
)
static

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

9160 {
9161  dst->pos_digits = palloc(src->ndigits * sizeof(int32));
9162  dst->neg_digits = palloc(src->ndigits * sizeof(int32));
9163 
9164  memcpy(dst->pos_digits, src->pos_digits, src->ndigits * sizeof(int32));
9165  memcpy(dst->neg_digits, src->neg_digits, src->ndigits * sizeof(int32));
9166  dst->num_uncarried = src->num_uncarried;
9167  dst->ndigits = src->ndigits;
9168  dst->weight = src->weight;
9169  dst->dscale = src->dscale;
9170 }
int32 * neg_digits
Definition: numeric.c:344
int num_uncarried
Definition: numeric.c:341
signed int int32
Definition: c.h:284
void * palloc(Size size)
Definition: mcxt.c:848
int32 * pos_digits
Definition: numeric.c:343

◆ accum_sum_final()

static void accum_sum_final ( NumericSumAccum accum,
NumericVar result 
)
static

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

9109 {
9110  int i;
9111  NumericVar pos_var;
9112  NumericVar neg_var;
9113 
9114  if (accum->ndigits == 0)
9115  {
9116  set_var_from_var(&const_zero, result);
9117  return;
9118  }
9119 
9120  /* Perform final carry */
9121  accum_sum_carry(accum);
9122 
9123  /* Create NumericVars representing the positive and negative sums */
9124  init_var(&pos_var);
9125  init_var(&neg_var);
9126 
9127  pos_var.ndigits = neg_var.ndigits = accum->ndigits;
9128  pos_var.weight = neg_var.weight = accum->weight;
9129  pos_var.dscale = neg_var.dscale = accum->dscale;
9130  pos_var.sign = NUMERIC_POS;
9131  neg_var.sign = NUMERIC_NEG;
9132 
9133  pos_var.buf = pos_var.digits = digitbuf_alloc(accum->ndigits);
9134  neg_var.buf = neg_var.digits = digitbuf_alloc(accum->ndigits);
9135 
9136  for (i = 0; i < accum->ndigits; i++)
9137  {
9138  Assert(accum->pos_digits[i] < NBASE);
9139  pos_var.digits[i] = (int16) accum->pos_digits[i];
9140 
9141  Assert(accum->neg_digits[i] < NBASE);
9142  neg_var.digits[i] = (int16) accum->neg_digits[i];
9143  }
9144 
9145  /* And add them together */
9146  add_var(&pos_var, &neg_var, result);
9147 
9148  /* Remove leading/trailing zeroes */
9149  strip_var(result);
9150 }
signed short int16
Definition: c.h:283
int weight
Definition: numeric.c:272
#define NUMERIC_POS
Definition: numeric.c:164
static void strip_var(NumericVar *var)
Definition: numeric.c:8841
int32 * neg_digits
Definition: numeric.c:344
#define digitbuf_alloc(ndigits)
Definition: numeric.c:443
int ndigits
Definition: numeric.c:271
static void accum_sum_carry(NumericSumAccum *accum)
Definition: numeric.c:8946
int dscale
Definition: numeric.c:274
#define NUMERIC_NEG
Definition: numeric.c:165
int sign
Definition: numeric.c:273
NumericDigit * buf
Definition: numeric.c:275
#define NBASE
Definition: numeric.c:93
static const NumericVar const_zero
Definition: numeric.c:371
#define Assert(condition)
Definition: c.h:670
NumericDigit * digits
Definition: numeric.c:276
static void add_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition: numeric.c:6519
int i
static void set_var_from_var(const NumericVar *value, NumericVar *dest)
Definition: numeric.c:5738
int32 * pos_digits
Definition: numeric.c:343
#define init_var(v)
Definition: numeric.c:451

◆ accum_sum_rescale()

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

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

9020 {
9021  int old_weight = accum->weight;
9022  int old_ndigits = accum->ndigits;
9023  int accum_ndigits;
9024  int accum_weight;
9025  int accum_rscale;
9026  int val_rscale;
9027 
9028  accum_weight = old_weight;
9029  accum_ndigits = old_ndigits;
9030 
9031  /*
9032  * Does the new value have a larger weight? If so, enlarge the buffers,
9033  * and shift the existing value to the new weight, by adding leading
9034  * zeros.
9035  *
9036  * We enforce that the accumulator always has a weight one larger than
9037  * needed for the inputs, so that we have space for an extra digit at the
9038  * final carry-propagation phase, if necessary.
9039  */
9040  if (val->weight >= accum_weight)
9041  {
9042  accum_weight = val->weight + 1;
9043  accum_ndigits = accum_ndigits + (accum_weight - old_weight);
9044  }
9045 
9046  /*
9047  * Even though the new value is small, we might've used up the space
9048  * reserved for the carry digit in the last call to accum_sum_carry(). If
9049  * so, enlarge to make room for another one.
9050  */
9051  else if (!accum->have_carry_space)
9052  {
9053  accum_weight++;
9054  accum_ndigits++;
9055  }
9056 
9057  /* Is the new value wider on the right side? */
9058  accum_rscale = accum_ndigits - accum_weight - 1;
9059  val_rscale = val->ndigits - val->weight - 1;
9060  if (val_rscale > accum_rscale)
9061  accum_ndigits = accum_ndigits + (val_rscale - accum_rscale);
9062 
9063  if (accum_ndigits != old_ndigits ||
9064  accum_weight != old_weight)
9065  {
9066  int32 *new_pos_digits;
9067  int32 *new_neg_digits;
9068  int weightdiff;
9069 
9070  weightdiff = accum_weight - old_weight;
9071 
9072  new_pos_digits = palloc0(accum_ndigits * sizeof(int32));
9073  new_neg_digits = palloc0(accum_ndigits * sizeof(int32));
9074 
9075  if (accum->pos_digits)
9076  {
9077  memcpy(&new_pos_digits[weightdiff], accum->pos_digits,
9078  old_ndigits * sizeof(int32));
9079  pfree(accum->pos_digits);
9080 
9081  memcpy(&new_neg_digits[weightdiff], accum->neg_digits,
9082  old_ndigits * sizeof(int32));
9083  pfree(accum->neg_digits);
9084  }
9085 
9086  accum->pos_digits = new_pos_digits;
9087  accum->neg_digits = new_neg_digits;
9088 
9089  accum->weight = accum_weight;
9090  accum->ndigits = accum_ndigits;
9091 
9092  Assert(accum->pos_digits[0] == 0 && accum->neg_digits[0] == 0);
9093  accum->have_carry_space = true;
9094  }
9095 
9096  if (val->dscale > accum->dscale)
9097  accum->dscale = val->dscale;
9098 }
int weight
Definition: numeric.c:272
int32 * neg_digits
Definition: numeric.c:344
int ndigits
Definition: numeric.c:271
int dscale
Definition: numeric.c:274
signed int int32
Definition: c.h:284
void pfree(void *pointer)
Definition: mcxt.c:949
bool have_carry_space
Definition: numeric.c:342
void * palloc0(Size size)
Definition: mcxt.c:877
#define Assert(condition)
Definition: c.h:670
int32 * pos_digits
Definition: numeric.c:343

◆ accum_sum_reset()

static void accum_sum_reset ( NumericSumAccum accum)
static

Definition at line 8882 of file numeric.c.

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

Referenced by do_numeric_discard().

8883 {
8884  int i;
8885 
8886  accum->dscale = 0;
8887  for (i = 0; i < accum->ndigits; i++)
8888  {
8889  accum->pos_digits[i] = 0;
8890  accum->neg_digits[i] = 0;
8891  }
8892 }
int32 * neg_digits
Definition: numeric.c:344
int i
int32 * pos_digits
Definition: numeric.c:343

◆ add_abs()

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

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

8507 {
8508  NumericDigit *res_buf;
8509  NumericDigit *res_digits;
8510  int res_ndigits;
8511  int res_weight;
8512  int res_rscale,
8513  rscale1,
8514  rscale2;
8515  int res_dscale;
8516  int i,
8517  i1,
8518  i2;
8519  int carry = 0;
8520 
8521  /* copy these values into local vars for speed in inner loop */
8522  int var1ndigits = var1->ndigits;
8523  int var2ndigits = var2->ndigits;
8524  NumericDigit *var1digits = var1->digits;
8525  NumericDigit *var2digits = var2->digits;
8526 
8527  res_weight = Max(var1->weight, var2->weight) + 1;
8528 
8529  res_dscale = Max(var1->dscale, var2->dscale);
8530 
8531  /* Note: here we are figuring rscale in base-NBASE digits */
8532  rscale1 = var1->ndigits - var1->weight - 1;
8533  rscale2 = var2->ndigits - var2->weight - 1;
8534  res_rscale = Max(rscale1, rscale2);
8535 
8536  res_ndigits = res_rscale + res_weight + 1;
8537  if (res_ndigits <= 0)
8538  res_ndigits = 1;
8539 
8540  res_buf = digitbuf_alloc(res_ndigits + 1);
8541  res_buf[0] = 0; /* spare digit for later rounding */
8542  res_digits = res_buf + 1;
8543 
8544  i1 = res_rscale + var1->weight + 1;
8545  i2 = res_rscale + var2->weight + 1;
8546  for (i = res_ndigits - 1; i >= 0; i--)
8547  {
8548  i1--;
8549  i2--;
8550  if (i1 >= 0 && i1 < var1ndigits)
8551  carry += var1digits[i1];
8552  if (i2 >= 0 && i2 < var2ndigits)
8553  carry += var2digits[i2];
8554 
8555  if (carry >= NBASE)
8556  {
8557  res_digits[i] = carry - NBASE;
8558  carry = 1;
8559  }
8560  else
8561  {
8562  res_digits[i] = carry;
8563  carry = 0;
8564  }
8565  }
8566 
8567  Assert(carry == 0); /* else we failed to allow for carry out */
8568 
8569  digitbuf_free(result->buf);
8570  result->ndigits = res_ndigits;
8571  result->buf = res_buf;
8572  result->digits = res_digits;
8573  result->weight = res_weight;
8574  result->dscale = res_dscale;
8575 
8576  /* Remove leading/trailing zeroes */
8577  strip_var(result);
8578 }
int weight
Definition: numeric.c:272
static void strip_var(NumericVar *var)
Definition: numeric.c:8841
#define digitbuf_alloc(ndigits)
Definition: numeric.c:443
int ndigits
Definition: numeric.c:271
int dscale
Definition: numeric.c:274
#define digitbuf_free(buf)
Definition: numeric.c:445
int16 NumericDigit
Definition: numeric.c:99
NumericDigit * buf
Definition: numeric.c:275
#define NBASE
Definition: numeric.c:93
#define Assert(condition)
Definition: c.h:670
NumericDigit * digits
Definition: numeric.c:276
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 6519 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(), ln_var(), numeric_add(), numeric_inc(), sqrt_var(), and width_bucket_numeric().

6520 {
6521  /*
6522  * Decide on the signs of the two variables what to do
6523  */
6524  if (var1->sign == NUMERIC_POS)
6525  {
6526  if (var2->sign == NUMERIC_POS)
6527  {
6528  /*
6529  * Both are positive result = +(ABS(var1) + ABS(var2))
6530  */
6531  add_abs(var1, var2, result);
6532  result->sign = NUMERIC_POS;
6533  }
6534  else
6535  {
6536  /*
6537  * var1 is positive, var2 is negative Must compare absolute values
6538  */
6539  switch (cmp_abs(var1, var2))
6540  {
6541  case 0:
6542  /* ----------
6543  * ABS(var1) == ABS(var2)
6544  * result = ZERO
6545  * ----------
6546  */
6547  zero_var(result);
6548  result->dscale = Max(var1->dscale, var2->dscale);
6549  break;
6550 
6551  case 1:
6552  /* ----------
6553  * ABS(var1) > ABS(var2)
6554  * result = +(ABS(var1) - ABS(var2))
6555  * ----------
6556  */
6557  sub_abs(var1, var2, result);
6558  result->sign = NUMERIC_POS;
6559  break;
6560 
6561  case -1:
6562  /* ----------
6563  * ABS(var1) < ABS(var2)
6564  * result = -(ABS(var2) - ABS(var1))
6565  * ----------
6566  */
6567  sub_abs(var2, var1, result);
6568  result->sign = NUMERIC_NEG;
6569  break;
6570  }
6571  }
6572  }
6573  else
6574  {
6575  if (var2->sign == NUMERIC_POS)
6576  {
6577  /* ----------
6578  * var1 is negative, var2 is positive
6579  * Must compare absolute values
6580  * ----------
6581  */
6582  switch (cmp_abs(var1, var2))
6583  {
6584  case 0:
6585  /* ----------
6586  * ABS(var1) == ABS(var2)
6587  * result = ZERO
6588  * ----------
6589  */
6590  zero_var(result);
6591  result->dscale = Max(var1->dscale, var2->dscale);
6592  break;
6593 
6594  case 1:
6595  /* ----------
6596  * ABS(var1) > ABS(var2)
6597  * result = -(ABS(var1) - ABS(var2))
6598  * ----------
6599  */
6600  sub_abs(var1, var2, result);
6601  result->sign = NUMERIC_NEG;
6602  break;
6603 
6604  case -1:
6605  /* ----------
6606  * ABS(var1) < ABS(var2)
6607  * result = +(ABS(var2) - ABS(var1))
6608  * ----------
6609  */
6610  sub_abs(var2, var1, result);
6611  result->sign = NUMERIC_POS;
6612  break;
6613  }
6614  }
6615  else
6616  {
6617  /* ----------
6618  * Both are negative
6619  * result = -(ABS(var1) + ABS(var2))
6620  * ----------
6621  */
6622  add_abs(var1, var2, result);
6623  result->sign = NUMERIC_NEG;
6624  }
6625  }
6626 }
static void sub_abs(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition: numeric.c:8591
static void add_abs(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition: numeric.c:8506
#define NUMERIC_POS
Definition: numeric.c:164
int dscale
Definition: numeric.c:274
#define NUMERIC_NEG
Definition: numeric.c:165
int sign
Definition: numeric.c:273
static void zero_var(NumericVar *var)
Definition: numeric.c:5504
static int cmp_abs(const NumericVar *var1, const NumericVar *var2)
Definition: numeric.c:8428
#define Max(x, y)
Definition: numeric.c:11

◆ alloc_var()

static void alloc_var ( NumericVar var,
int  ndigits 
)
static

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

5473 {
5474  digitbuf_free(var->buf);
5475  var->buf = digitbuf_alloc(ndigits + 1);
5476  var->buf[0] = 0; /* spare digit for rounding */
5477  var->digits = var->buf + 1;
5478  var->ndigits = ndigits;
5479 }
#define digitbuf_alloc(ndigits)
Definition: numeric.c:443
int ndigits
Definition: numeric.c:271
#define digitbuf_free(buf)
Definition: numeric.c:445
NumericDigit * buf
Definition: numeric.c:275
NumericDigit * digits
Definition: numeric.c:276

◆ apply_typmod()

static void apply_typmod ( NumericVar var,
int32  typmod 
)
static

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

6091 {
6092  int precision;
6093  int scale;
6094  int maxdigits;
6095  int ddigits;
6096  int i;
6097 
6098  /* Do nothing if we have a default typmod (-1) */
6099  if (typmod < (int32) (VARHDRSZ))
6100  return;
6101 
6102  typmod -= VARHDRSZ;
6103  precision = (typmod >> 16) & 0xffff;
6104  scale = typmod & 0xffff;
6105  maxdigits = precision - scale;
6106 
6107  /* Round to target scale (and set var->dscale) */
6108  round_var(var, scale);
6109 
6110  /*
6111  * Check for overflow - note we can't do this before rounding, because
6112  * rounding could raise the weight. Also note that the var's weight could
6113  * be inflated by leading zeroes, which will be stripped before storage
6114  * but perhaps might not have been yet. In any case, we must recognize a
6115  * true zero, whose weight doesn't mean anything.
6116  */
6117  ddigits = (var->weight + 1) * DEC_DIGITS;
6118  if (ddigits > maxdigits)
6119  {
6120  /* Determine true weight; and check for all-zero result */
6121  for (i = 0; i < var->ndigits; i++)
6122  {
6123  NumericDigit dig = var->digits[i];
6124 
6125  if (dig)
6126  {
6127  /* Adjust for any high-order decimal zero digits */
6128 #if DEC_DIGITS == 4
6129  if (dig < 10)
6130  ddigits -= 3;
6131  else if (dig < 100)
6132  ddigits -= 2;
6133  else if (dig < 1000)
6134  ddigits -= 1;
6135 #elif DEC_DIGITS == 2
6136  if (dig < 10)
6137  ddigits -= 1;
6138 #elif DEC_DIGITS == 1
6139  /* no adjustment */
6140 #else
6141 #error unsupported NBASE
6142 #endif
6143  if (ddigits > maxdigits)
6144  ereport(ERROR,
6145  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
6146  errmsg("numeric field overflow"),
6147  errdetail("A field with precision %d, scale %d must round to an absolute value less than %s%d.",
6148  precision, scale,
6149  /* Display 10^0 as 1 */
6150  maxdigits ? "10^" : "",
6151  maxdigits ? maxdigits : 1
6152  )));
6153  break;
6154  }
6155  ddigits -= DEC_DIGITS;
6156  }
6157  }
6158 }
static void round_var(NumericVar *var, int rscale)
Definition: numeric.c:8673
int weight
Definition: numeric.c:272
#define VARHDRSZ
Definition: c.h:493
int errcode(int sqlerrcode)
Definition: elog.c:575
int scale
Definition: pgbench.c:108
int ndigits
Definition: numeric.c:271
signed int int32
Definition: c.h:284
#define ERROR
Definition: elog.h:43
int16 NumericDigit
Definition: numeric.c:99
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:276
int errmsg(const char *fmt,...)
Definition: elog.c:797
int i
#define DEC_DIGITS
Definition: numeric.c:95

◆ ceil_var()

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

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

7633 {
7634  NumericVar tmp;
7635 
7636  init_var(&tmp);
7637  set_var_from_var(var, &tmp);
7638 
7639  trunc_var(&tmp, 0);
7640 
7641  if (var->sign == NUMERIC_POS && cmp_var(var, &tmp) != 0)
7642  add_var(&tmp, &const_one, &tmp);
7643 
7644  set_var_from_var(&tmp, result);
7645  free_var(&tmp);
7646 }
static void trunc_var(NumericVar *var, int rscale)
Definition: numeric.c:8779
static const NumericVar const_one
Definition: numeric.c:375
#define NUMERIC_POS
Definition: numeric.c:164
int sign
Definition: numeric.c:273
static int cmp_var(const NumericVar *var1, const NumericVar *var2)
Definition: numeric.c:6461
static void free_var(NumericVar *var)
Definition: numeric.c:5488
static void add_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition: numeric.c:6519
static void set_var_from_var(const NumericVar *value, NumericVar *dest)
Definition: numeric.c:5738
#define init_var(v)
Definition: numeric.c:451

◆ cmp_abs()

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

Definition at line 8428 of file numeric.c.

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

Referenced by add_var(), and sub_var().

8429 {
8430  return cmp_abs_common(var1->digits, var1->ndigits, var1->weight,
8431  var2->digits, var2->ndigits, var2->weight);
8432 }
int weight
Definition: numeric.c:272
int ndigits
Definition: numeric.c:271
NumericDigit * digits
Definition: numeric.c:276
static int cmp_abs_common(const NumericDigit *var1digits, int var1ndigits, int var1weight, const NumericDigit *var2digits, int var2ndigits, int var2weight)
Definition: numeric.c:8442

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

References stat.

Referenced by cmp_abs(), and cmp_var_common().

8444 {
8445  int i1 = 0;
8446  int i2 = 0;
8447 
8448  /* Check any digits before the first common digit */
8449 
8450  while (var1weight > var2weight && i1 < var1ndigits)
8451  {
8452  if (var1digits[i1++] != 0)
8453  return 1;
8454  var1weight--;
8455  }
8456  while (var2weight > var1weight && i2 < var2ndigits)
8457  {
8458  if (var2digits[i2++] != 0)
8459  return -1;
8460  var2weight--;
8461  }
8462 
8463  /* At this point, either w1 == w2 or we've run out of digits */
8464 
8465  if (var1weight == var2weight)
8466  {
8467  while (i1 < var1ndigits && i2 < var2ndigits)
8468  {
8469  int stat = var1digits[i1++] - var2digits[i2++];
8470 
8471  if (stat)
8472  {
8473  if (stat > 0)
8474  return 1;
8475  return -1;
8476  }
8477  }
8478  }
8479 
8480  /*
8481  * At this point, we've run out of digits on one side or the other; so any
8482  * remaining nonzero digits imply that side is larger
8483  */
8484  while (i1 < var1ndigits)
8485  {
8486  if (var1digits[i1++] != 0)
8487  return 1;
8488  }
8489  while (i2 < var2ndigits)
8490  {
8491  if (var2digits[i2++] != 0)
8492  return -1;
8493  }
8494 
8495  return 0;
8496 }
#define stat(a, b)
Definition: win32_port.h:266

◆ cmp_numerics()

static int cmp_numerics ( Numeric  num1,
Numeric  num2 
)
static

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

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

◆ cmp_var()

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

Definition at line 6461 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(), ln_var(), numeric_power(), numeric_stddev_internal(), power_var(), and sqrt_var().

6462 {
6463  return cmp_var_common(var1->digits, var1->ndigits,
6464  var1->weight, var1->sign,
6465  var2->digits, var2->ndigits,
6466  var2->weight, var2->sign);
6467 }
int weight
Definition: numeric.c:272
int ndigits
Definition: numeric.c:271
int sign
Definition: numeric.c:273
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:6476
NumericDigit * digits
Definition: numeric.c:276

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

References cmp_abs_common(), NUMERIC_NEG, and NUMERIC_POS.

Referenced by cmp_numerics(), and cmp_var().

6480 {
6481  if (var1ndigits == 0)
6482  {
6483  if (var2ndigits == 0)
6484  return 0;
6485  if (var2sign == NUMERIC_NEG)
6486  return 1;
6487  return -1;
6488  }
6489  if (var2ndigits == 0)
6490  {
6491  if (var1sign == NUMERIC_POS)
6492  return 1;
6493  return -1;
6494  }
6495 
6496  if (var1sign == NUMERIC_POS)
6497  {
6498  if (var2sign == NUMERIC_NEG)
6499  return 1;
6500  return cmp_abs_common(var1digits, var1ndigits, var1weight,
6501  var2digits, var2ndigits, var2weight);
6502  }
6503 
6504  if (var2sign == NUMERIC_POS)
6505  return -1;
6506 
6507  return cmp_abs_common(var2digits, var2ndigits, var2weight,
6508  var1digits, var1ndigits, var1weight);
6509 }
#define NUMERIC_POS
Definition: numeric.c:164
#define NUMERIC_NEG
Definition: numeric.c:165
static int cmp_abs_common(const NumericDigit *var1digits, int var1ndigits, int var1weight, const NumericDigit *var2digits, int var2ndigits, int var2weight)
Definition: numeric.c:8442

◆ compute_bucket()

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

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

1565 {
1566  NumericVar bound1_var;
1567  NumericVar bound2_var;
1568  NumericVar operand_var;
1569 
1570  init_var_from_num(bound1, &bound1_var);
1571  init_var_from_num(bound2, &bound2_var);
1572  init_var_from_num(operand, &operand_var);
1573 
1574  if (cmp_var(&bound1_var, &bound2_var) < 0)
1575  {
1576  sub_var(&operand_var, &bound1_var, &operand_var);
1577  sub_var(&bound2_var, &bound1_var, &bound2_var);
1578  div_var(&operand_var, &bound2_var, result_var,
1579  select_div_scale(&operand_var, &bound2_var), true);
1580  }
1581  else
1582  {
1583  sub_var(&bound1_var, &operand_var, &operand_var);
1584  sub_var(&bound1_var, &bound2_var, &bound1_var);
1585  div_var(&operand_var, &bound1_var, result_var,
1586  select_div_scale(&operand_var, &bound1_var), true);
1587  }
1588 
1589  mul_var(result_var, count_var, result_var,
1590  result_var->dscale + count_var->dscale);
1591  add_var(result_var, &const_one, result_var);
1592  floor_var(result_var, result_var);
1593 
1594  free_var(&bound1_var);
1595  free_var(&bound2_var);
1596  free_var(&operand_var);
1597 }
static const NumericVar const_one
Definition: numeric.c:375
static void div_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result, int rscale, bool round)
Definition: numeric.c:6954
int dscale
Definition: numeric.c:274
static int select_div_scale(const NumericVar *var1, const NumericVar *var2)
Definition: numeric.c:7534
static void init_var_from_num(Numeric num, NumericVar *dest)
Definition: numeric.c:5721
static int cmp_var(const NumericVar *var1, const NumericVar *var2)
Definition: numeric.c:6461
static void free_var(NumericVar *var)
Definition: numeric.c:5488
static void mul_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result, int rscale)
Definition: numeric.c:6757
static void add_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition: numeric.c:6519
static void sub_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition: numeric.c:6636
static void floor_var(const NumericVar *var, NumericVar *result)
Definition: numeric.c:7656

◆ div_var()

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

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

6956 {
6957  int div_ndigits;
6958  int res_ndigits;
6959  int res_sign;
6960  int res_weight;
6961  int carry;
6962  int borrow;
6963  int divisor1;
6964  int divisor2;
6965  NumericDigit *dividend;
6966  NumericDigit *divisor;
6967  NumericDigit *res_digits;
6968  int i;
6969  int j;
6970 
6971  /* copy these values into local vars for speed in inner loop */
6972  int var1ndigits = var1->ndigits;
6973  int var2ndigits = var2->ndigits;
6974 
6975  /*
6976  * First of all division by zero check; we must not be handed an
6977  * unnormalized divisor.
6978  */
6979  if (var2ndigits == 0 || var2->digits[0] == 0)
6980  ereport(ERROR,
6981  (errcode(ERRCODE_DIVISION_BY_ZERO),
6982  errmsg("division by zero")));
6983 
6984  /*
6985  * Now result zero check
6986  */
6987  if (var1ndigits == 0)
6988  {
6989  zero_var(result);
6990  result->dscale = rscale;
6991  return;
6992  }
6993 
6994  /*
6995  * Determine the result sign, weight and number of digits to calculate.
6996  * The weight figured here is correct if the emitted quotient has no
6997  * leading zero digits; otherwise strip_var() will fix things up.
6998  */
6999  if (var1->sign == var2->sign)
7000  res_sign = NUMERIC_POS;
7001  else
7002  res_sign = NUMERIC_NEG;
7003  res_weight = var1->weight - var2->weight;
7004  /* The number of accurate result digits we need to produce: */
7005  res_ndigits = res_weight + 1 + (rscale + DEC_DIGITS - 1) / DEC_DIGITS;
7006  /* ... but always at least 1 */
7007  res_ndigits = Max(res_ndigits, 1);
7008  /* If rounding needed, figure one more digit to ensure correct result */
7009  if (round)
7010  res_ndigits++;
7011 
7012  /*
7013  * The working dividend normally requires res_ndigits + var2ndigits
7014  * digits, but make it at least var1ndigits so we can load all of var1
7015  * into it. (There will be an additional digit dividend[0] in the
7016  * dividend space, but for consistency with Knuth's notation we don't
7017  * count that in div_ndigits.)
7018  */
7019  div_ndigits = res_ndigits + var2ndigits;
7020  div_ndigits = Max(div_ndigits, var1ndigits);
7021 
7022  /*
7023  * We need a workspace with room for the working dividend (div_ndigits+1
7024  * digits) plus room for the possibly-normalized divisor (var2ndigits
7025  * digits). It is convenient also to have a zero at divisor[0] with the
7026  * actual divisor data in divisor[1 .. var2ndigits]. Transferring the
7027  * digits into the workspace also allows us to realloc the result (which
7028  * might be the same as either input var) before we begin the main loop.
7029  * Note that we use palloc0 to ensure that divisor[0], dividend[0], and
7030  * any additional dividend positions beyond var1ndigits, start out 0.
7031  */
7032  dividend = (NumericDigit *)
7033  palloc0((div_ndigits + var2ndigits + 2) * sizeof(NumericDigit));
7034  divisor = dividend + (div_ndigits + 1);
7035  memcpy(dividend + 1, var1->digits, var1ndigits * sizeof(NumericDigit));
7036  memcpy(divisor + 1, var2->digits, var2ndigits * sizeof(NumericDigit));
7037 
7038  /*
7039  * Now we can realloc the result to hold the generated quotient digits.
7040  */
7041  alloc_var(result, res_ndigits);
7042  res_digits = result->digits;
7043 
7044  if (var2ndigits == 1)
7045  {
7046  /*
7047  * If there's only a single divisor digit, we can use a fast path (cf.
7048  * Knuth section 4.3.1 exercise 16).
7049  */
7050  divisor1 = divisor[1];
7051  carry = 0;
7052  for (i = 0; i < res_ndigits; i++)
7053  {
7054  carry = carry * NBASE + dividend[i + 1];
7055  res_digits[i] = carry / divisor1;
7056  carry = carry % divisor1;
7057  }
7058  }
7059  else
7060  {
7061  /*
7062  * The full multiple-place algorithm is taken from Knuth volume 2,
7063  * Algorithm 4.3.1D.
7064  *
7065  * We need the first divisor digit to be >= NBASE/2. If it isn't,
7066  * make it so by scaling up both the divisor and dividend by the
7067  * factor "d". (The reason for allocating dividend[0] above is to
7068  * leave room for possible carry here.)
7069  */
7070  if (divisor[1] < HALF_NBASE)
7071  {
7072  int d = NBASE / (divisor[1] + 1);
7073 
7074  carry = 0;
7075  for (i = var2ndigits; i > 0; i--)
7076  {
7077  carry += divisor[i] * d;
7078  divisor[i] = carry % NBASE;
7079  carry = carry / NBASE;
7080  }
7081  Assert(carry == 0);
7082  carry = 0;
7083  /* at this point only var1ndigits of dividend can be nonzero */
7084  for (i = var1ndigits; i >= 0; i--)
7085  {
7086  carry += dividend[i] * d;
7087  dividend[i] = carry % NBASE;
7088  carry = carry / NBASE;
7089  }
7090  Assert(carry == 0);
7091  Assert(divisor[1] >= HALF_NBASE);
7092  }
7093  /* First 2 divisor digits are used repeatedly in main loop */
7094  divisor1 = divisor[1];
7095  divisor2 = divisor[2];
7096 
7097  /*
7098  * Begin the main loop. Each iteration of this loop produces the j'th
7099  * quotient digit by dividing dividend[j .. j + var2ndigits] by the
7100  * divisor; this is essentially the same as the common manual
7101  * procedure for long division.
7102  */
7103  for (j = 0; j < res_ndigits; j++)
7104  {
7105  /* Estimate quotient digit from the first two dividend digits */
7106  int next2digits = dividend[j] * NBASE + dividend[j + 1];
7107  int qhat;
7108 
7109  /*
7110  * If next2digits are 0, then quotient digit must be 0 and there's
7111  * no need to adjust the working dividend. It's worth testing
7112  * here to fall out ASAP when processing trailing zeroes in a
7113  * dividend.
7114  */
7115  if (next2digits == 0)
7116  {
7117  res_digits[j] = 0;
7118  continue;
7119  }
7120 
7121  if (dividend[j] == divisor1)
7122  qhat = NBASE - 1;
7123  else
7124  qhat = next2digits / divisor1;
7125 
7126  /*
7127  * Adjust quotient digit if it's too large. Knuth proves that
7128  * after this step, the quotient digit will be either correct or
7129  * just one too large. (Note: it's OK to use dividend[j+2] here
7130  * because we know the divisor length is at least 2.)
7131  */
7132  while (divisor2 * qhat >
7133  (next2digits - qhat * divisor1) * NBASE + dividend[j + 2])
7134  qhat--;
7135 
7136  /* As above, need do nothing more when quotient digit is 0 */
7137  if (qhat > 0)
7138  {
7139  /*
7140  * Multiply the divisor by qhat, and subtract that from the
7141  * working dividend. "carry" tracks the multiplication,
7142  * "borrow" the subtraction (could we fold these together?)
7143  */
7144  carry = 0;
7145  borrow = 0;
7146  for (i = var2ndigits; i >= 0; i--)
7147  {
7148  carry += divisor[i] * qhat;
7149  borrow -= carry % NBASE;
7150  carry = carry / NBASE;
7151  borrow += dividend[j + i];
7152  if (borrow < 0)
7153  {
7154  dividend[j + i] = borrow + NBASE;
7155  borrow = -1;
7156  }
7157  else
7158  {
7159  dividend[j + i] = borrow;
7160  borrow = 0;
7161  }
7162  }
7163  Assert(carry == 0);
7164 
7165  /*
7166  * If we got a borrow out of the top dividend digit, then
7167  * indeed qhat was one too large. Fix it, and add back the
7168  * divisor to correct the working dividend. (Knuth proves
7169  * that this will occur only about 3/NBASE of the time; hence,
7170  * it's a good idea to test this code with small NBASE to be
7171  * sure this section gets exercised.)
7172  */
7173  if (borrow)
7174  {
7175  qhat--;
7176  carry = 0;
7177  for (i = var2ndigits; i >= 0; i--)
7178  {
7179  carry += dividend[j + i] + divisor[i];
7180  if (carry >= NBASE)
7181  {
7182  dividend[j + i] = carry - NBASE;
7183  carry = 1;
7184  }
7185  else
7186  {
7187  dividend[j + i] = carry;
7188  carry = 0;
7189  }
7190  }
7191  /* A carry should occur here to cancel the borrow above */
7192  Assert(carry == 1);
7193  }
7194  }
7195 
7196  /* And we're done with this quotient digit */
7197  res_digits[j] = qhat;
7198  }
7199  }
7200 
7201  pfree(dividend);
7202 
7203  /*
7204  * Finally, round or truncate the result to the requested precision.
7205  */
7206  result->weight = res_weight;
7207  result->sign = res_sign;
7208 
7209  /* Round or truncate to target rscale (and set result->dscale) */
7210  if (round)
7211  round_var(result, rscale);
7212  else
7213  trunc_var(result, rscale);
7214 
7215  /* Strip leading and trailing zeroes */
7216  strip_var(result);
7217 }
static void round_var(NumericVar *var, int rscale)
Definition: numeric.c:8673
static void trunc_var(NumericVar *var, int rscale)
Definition: numeric.c:8779
int weight
Definition: numeric.c:272
#define NUMERIC_POS
Definition: numeric.c:164
static void strip_var(NumericVar *var)
Definition: numeric.c:8841
int errcode(int sqlerrcode)
Definition: elog.c:575
int ndigits
Definition: numeric.c:271
int dscale
Definition: numeric.c:274
#define NUMERIC_NEG
Definition: numeric.c:165
int sign
Definition: numeric.c:273
static void zero_var(NumericVar *var)
Definition: numeric.c:5504
void pfree(void *pointer)
Definition: mcxt.c:949
#define ERROR
Definition: elog.h:43
int16 NumericDigit
Definition: numeric.c:99
#define HALF_NBASE
Definition: numeric.c:94
#define ereport(elevel, rest)
Definition: elog.h:122
#define NBASE
Definition: numeric.c:93
void * palloc0(Size size)
Definition: mcxt.c:877
#define Assert(condition)
Definition: c.h:670
NumericDigit * digits
Definition: numeric.c:276
int errmsg(const char *fmt,...)
Definition: elog.c:797
static void alloc_var(NumericVar *var, int ndigits)
Definition: numeric.c:5472
int i
#define Max(x, y)
Definition: numeric.c:11
#define DEC_DIGITS
Definition: numeric.c:95

◆ div_var_fast()

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

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

7241 {
7242  int div_ndigits;
7243  int res_sign;
7244  int res_weight;
7245  int *div;
7246  int qdigit;
7247  int carry;
7248  int maxdiv;
7249  int newdig;
7250  NumericDigit *res_digits;
7251  double fdividend,
7252  fdivisor,
7253  fdivisorinverse,
7254  fquotient;
7255  int qi;
7256  int i;
7257 
7258  /* copy these values into local vars for speed in inner loop */
7259  int var1ndigits = var1->ndigits;
7260  int var2ndigits = var2->ndigits;
7261  NumericDigit *var1digits = var1->digits;
7262  NumericDigit *var2digits = var2->digits;
7263 
7264  /*
7265  * First of all division by zero check; we must not be handed an
7266  * unnormalized divisor.
7267  */
7268  if (var2ndigits == 0 || var2digits[0] == 0)
7269  ereport(ERROR,
7270  (errcode(ERRCODE_DIVISION_BY_ZERO),
7271  errmsg("division by zero")));
7272 
7273  /*
7274  * Now result zero check
7275  */
7276  if (var1ndigits == 0)
7277  {
7278  zero_var(result);
7279  result->dscale = rscale;
7280  return;
7281  }
7282 
7283  /*
7284  * Determine the result sign, weight and number of digits to calculate
7285  */
7286  if (var1->sign == var2->sign)
7287  res_sign = NUMERIC_POS;
7288  else
7289  res_sign = NUMERIC_NEG;
7290  res_weight = var1->weight - var2->weight + 1;
7291  /* The number of accurate result digits we need to produce: */
7292  div_ndigits = res_weight + 1 + (rscale + DEC_DIGITS - 1) / DEC_DIGITS;
7293  /* Add guard digits for roundoff error */
7294  div_ndigits += DIV_GUARD_DIGITS;
7295  if (div_ndigits < DIV_GUARD_DIGITS)
7296  div_ndigits = DIV_GUARD_DIGITS;
7297  /* Must be at least var1ndigits, too, to simplify data-loading loop */
7298  if (div_ndigits < var1ndigits)
7299  div_ndigits = var1ndigits;
7300 
7301  /*
7302  * We do the arithmetic in an array "div[]" of signed int's. Since
7303  * INT_MAX is noticeably larger than NBASE*NBASE, this gives us headroom
7304  * to avoid normalizing carries immediately.
7305  *
7306  * We start with div[] containing one zero digit followed by the
7307  * dividend's digits (plus appended zeroes to reach the desired precision
7308  * including guard digits). Each step of the main loop computes an
7309  * (approximate) quotient digit and stores it into div[], removing one
7310  * position of dividend space. A final pass of carry propagation takes
7311  * care of any mistaken quotient digits.
7312  */
7313  div = (int *) palloc0((div_ndigits + 1) * sizeof(int));
7314  for (i = 0; i < var1ndigits; i++)
7315  div[i + 1] = var1digits[i];
7316 
7317  /*
7318  * We estimate each quotient digit using floating-point arithmetic, taking
7319  * the first four digits of the (current) dividend and divisor. This must
7320  * be float to avoid overflow. The quotient digits will generally be off
7321  * by no more than one from the exact answer.
7322  */
7323  fdivisor = (double) var2digits[0];
7324  for (i = 1; i < 4; i++)
7325  {
7326  fdivisor *= NBASE;
7327  if (i < var2ndigits)
7328  fdivisor += (double) var2digits[i];
7329  }
7330  fdivisorinverse = 1.0 / fdivisor;
7331 
7332  /*
7333  * maxdiv tracks the maximum possible absolute value of any div[] entry;
7334  * when this threatens to exceed INT_MAX, we take the time to propagate
7335  * carries. Furthermore, we need to ensure that overflow doesn't occur
7336  * during the carry propagation passes either. The carry values may have
7337  * an absolute value as high as INT_MAX/NBASE + 1, so really we must
7338  * normalize when digits threaten to exceed INT_MAX - INT_MAX/NBASE - 1.
7339  *
7340  * To avoid overflow in maxdiv itself, it represents the max absolute
7341  * value divided by NBASE-1, ie, at the top of the loop it is known that
7342  * no div[] entry has an absolute value exceeding maxdiv * (NBASE-1).
7343  *
7344  * Actually, though, that holds good only for div[] entries after div[qi];
7345  * the adjustment done at the bottom of the loop may cause div[qi + 1] to
7346  * exceed the maxdiv limit, so that div[qi] in the next iteration is
7347  * beyond the limit. This does not cause problems, as explained below.
7348  */
7349  maxdiv = 1;
7350 
7351  /*
7352  * Outer loop computes next quotient digit, which will go into div[qi]
7353  */
7354  for (qi = 0; qi < div_ndigits; qi++)
7355  {
7356  /* Approximate the current dividend value */
7357  fdividend = (double) div[qi];
7358  for (i = 1; i < 4; i++)
7359  {
7360  fdividend *= NBASE;
7361  if (qi + i <= div_ndigits)
7362  fdividend += (double) div[qi + i];
7363  }
7364  /* Compute the (approximate) quotient digit */
7365  fquotient = fdividend * fdivisorinverse;
7366  qdigit = (fquotient >= 0.0) ? ((int) fquotient) :
7367  (((int) fquotient) - 1); /* truncate towards -infinity */
7368 
7369  if (qdigit != 0)
7370  {
7371  /* Do we need to normalize now? */
7372  maxdiv += Abs(qdigit);
7373  if (maxdiv > (INT_MAX - INT_MAX / NBASE - 1) / (NBASE - 1))
7374  {
7375  /* Yes, do it */
7376  carry = 0;
7377  for (i = div_ndigits; i > qi; i--)
7378  {
7379  newdig = div[i] + carry;
7380  if (newdig < 0)
7381  {
7382  carry = -((-newdig - 1) / NBASE) - 1;
7383  newdig -= carry * NBASE;
7384  }
7385  else if (newdig >= NBASE)
7386  {
7387  carry = newdig / NBASE;
7388  newdig -= carry * NBASE;
7389  }
7390  else
7391  carry = 0;
7392  div[i] = newdig;
7393  }
7394  newdig = div[qi] + carry;
7395  div[qi] = newdig;
7396 
7397  /*
7398  * All the div[] digits except possibly div[qi] are now in the
7399  * range 0..NBASE-1. We do not need to consider div[qi] in
7400  * the maxdiv value anymore, so we can reset maxdiv to 1.
7401  */
7402  maxdiv = 1;
7403 
7404  /*
7405  * Recompute the quotient digit since new info may have
7406  * propagated into the top four dividend digits
7407  */
7408  fdividend = (double) div[qi];
7409  for (i = 1; i < 4; i++)
7410  {
7411  fdividend *= NBASE;
7412  if (qi + i <= div_ndigits)
7413  fdividend += (double) div[qi + i];
7414  }
7415  /* Compute the (approximate) quotient digit */
7416  fquotient = fdividend * fdivisorinverse;
7417  qdigit = (fquotient >= 0.0) ? ((int) fquotient) :
7418  (((int) fquotient) - 1); /* truncate towards -infinity */
7419  maxdiv += Abs(qdigit);
7420  }
7421 
7422  /*
7423  * Subtract off the appropriate multiple of the divisor.
7424  *
7425  * The digits beyond div[qi] cannot overflow, because we know they
7426  * will fall within the maxdiv limit. As for div[qi] itself, note
7427  * that qdigit is approximately trunc(div[qi] / vardigits[0]),
7428  * which would make the new value simply div[qi] mod vardigits[0].
7429  * The lower-order terms in qdigit can change this result by not
7430  * more than about twice INT_MAX/NBASE, so overflow is impossible.
7431  */
7432  if (qdigit != 0)
7433  {
7434  int istop = Min(var2ndigits, div_ndigits - qi + 1);
7435 
7436  for (i = 0; i < istop; i++)
7437  div[qi + i] -= qdigit * var2digits[i];
7438  }
7439  }
7440 
7441  /*
7442  * The dividend digit we are about to replace might still be nonzero.
7443  * Fold it into the next digit position.
7444  *
7445  * There is no risk of overflow here, although proving that requires
7446  * some care. Much as with the argument for div[qi] not overflowing,
7447  * if we consider the first two terms in the numerator and denominator
7448  * of qdigit, we can see that the final value of div[qi + 1] will be
7449  * approximately a remainder mod (vardigits[0]*NBASE + vardigits[1]).
7450  * Accounting for the lower-order terms is a bit complicated but ends
7451  * up adding not much more than INT_MAX/NBASE to the possible range.
7452  * Thus, div[qi + 1] cannot overflow here, and in its role as div[qi]
7453  * in the next loop iteration, it can't be large enough to cause
7454  * overflow in the carry propagation step (if any), either.
7455  *
7456  * But having said that: div[qi] can be more than INT_MAX/NBASE, as
7457  * noted above, which means that the product div[qi] * NBASE *can*
7458  * overflow. When that happens, adding it to div[qi + 1] will always
7459  * cause a canceling overflow so that the end result is correct. We
7460  * could avoid the intermediate overflow by doing the multiplication
7461  * and addition in int64 arithmetic, but so far there appears no need.
7462  */
7463  div[qi + 1] += div[qi] * NBASE;
7464 
7465  div[qi] = qdigit;
7466  }
7467 
7468  /*
7469  * Approximate and store the last quotient digit (div[div_ndigits])
7470  */
7471  fdividend = (double) div[qi];
7472  for (i = 1; i < 4; i++)
7473  fdividend *= NBASE;
7474  fquotient = fdividend * fdivisorinverse;
7475  qdigit = (fquotient >= 0.0) ? ((int) fquotient) :
7476  (((int) fquotient) - 1); /* truncate towards -infinity */
7477  div[qi] = qdigit;
7478 
7479  /*
7480  * Because the quotient digits might be off by one, some of them might be
7481  * -1 or NBASE at this point. The represented value is correct in a
7482  * mathematical sense, but it doesn't look right. We do a final carry
7483  * propagation pass to normalize the digits, which we combine with storing
7484  * the result digits into the output. Note that this is still done at
7485  * full precision w/guard digits.
7486  */
7487  alloc_var(result, div_ndigits + 1);
7488  res_digits = result->digits;
7489  carry = 0;
7490  for (i = div_ndigits; i >= 0; i--)
7491  {
7492  newdig = div[i] + carry;
7493  if (newdig < 0)
7494  {
7495  carry = -((-newdig - 1) / NBASE) - 1;
7496  newdig -= carry * NBASE;
7497  }
7498  else if (newdig >= NBASE)
7499  {
7500  carry = newdig / NBASE;
7501  newdig -= carry * NBASE;
7502  }
7503  else
7504  carry = 0;
7505  res_digits[i] = newdig;
7506  }
7507  Assert(carry == 0);
7508 
7509  pfree(div);
7510 
7511  /*
7512  * Finally, round the result to the requested precision.
7513  */
7514  result->weight = res_weight;
7515  result->sign = res_sign;
7516 
7517  /* Round to target rscale (and set result->dscale) */
7518  if (round)
7519  round_var(result, rscale);
7520  else
7521  trunc_var(result, rscale);
7522 
7523  /* Strip leading and trailing zeroes */
7524  strip_var(result);
7525 }
static void round_var(NumericVar *var, int rscale)
Definition: numeric.c:8673
static void trunc_var(NumericVar *var, int rscale)
Definition: numeric.c:8779
int weight
Definition: numeric.c:272
#define NUMERIC_POS
Definition: numeric.c:164
static void strip_var(NumericVar *var)
Definition: numeric.c:8841
int errcode(int sqlerrcode)
Definition: elog.c:575
int ndigits
Definition: numeric.c:271
int dscale
Definition: numeric.c:274
#define Min(x, y)
Definition: numeric.c:12
#define Abs(x)
Definition: c.h:808
#define NUMERIC_NEG
Definition: numeric.c:165
int sign
Definition: numeric.c:273
static void zero_var(NumericVar *var)
Definition: numeric.c:5504
void pfree(void *pointer)
Definition: mcxt.c:949
#define ERROR
Definition: elog.h:43
int16 NumericDigit
Definition: numeric.c:99
#define ereport(elevel, rest)
Definition: elog.h:122
#define NBASE
Definition: numeric.c:93
void * palloc0(Size size)
Definition: mcxt.c:877
#define Assert(condition)
Definition: c.h:670
NumericDigit * digits
Definition: numeric.c:276
#define DIV_GUARD_DIGITS
Definition: numeric.c:97
int errmsg(const char *fmt,...)
Definition: elog.c:797
static void alloc_var(NumericVar *var, int ndigits)
Definition: numeric.c:5472
int i
#define DEC_DIGITS
Definition: numeric.c:95

◆ do_numeric_accum()

static void do_numeric_accum ( NumericAggState state,
Numeric  newval 
)
static

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

3330 {
3331  NumericVar X;
3332  NumericVar X2;
3333  MemoryContext old_context;
3334 
3335  /* Count NaN inputs separately from all else */
3336  if (NUMERIC_IS_NAN(newval))
3337  {
3338  state->NaNcount++;
3339  return;
3340  }
3341 
3342  /* load processed number in short-lived context */
3343  init_var_from_num(newval, &X);
3344 
3345  /*
3346  * Track the highest input dscale that we've seen, to support inverse
3347  * transitions (see do_numeric_discard).
3348  */
3349  if (X.dscale > state->maxScale)
3350  {
3351  state->maxScale = X.dscale;
3352  state->maxScaleCount = 1;
3353  }
3354  else if (X.dscale == state->maxScale)
3355  state->maxScaleCount++;
3356 
3357  /* if we need X^2, calculate that in short-lived context */
3358  if (state->calcSumX2)
3359  {
3360  init_var(&X2);
3361  mul_var(&X, &X, &X2, X.dscale * 2);
3362  }
3363 
3364  /* The rest of this needs to work in the aggregate context */
3365  old_context = MemoryContextSwitchTo(state->agg_context);
3366 
3367  state->N++;
3368 
3369  /* Accumulate sums */
3370  accum_sum_add(&(state->sumX), &X);
3371 
3372  if (state->calcSumX2)
3373  accum_sum_add(&(state->sumX2), &X2);
3374 
3375  MemoryContextSwitchTo(old_context);
3376 }
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
MemoryContext agg_context
Definition: numeric.c:3275
int dscale
Definition: numeric.c:274
static void accum_sum_add(NumericSumAccum *accum, const NumericVar *var1)
Definition: numeric.c:8898
static void init_var_from_num(Numeric num, NumericVar *dest)
Definition: numeric.c:5721
static void mul_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result, int rscale)
Definition: numeric.c:6757
NumericSumAccum sumX2
Definition: numeric.c:3278
int64 NaNcount
Definition: numeric.c:3281
int64 maxScaleCount
Definition: numeric.c:3280
#define NUMERIC_IS_NAN(n)
Definition: numeric.c:170
NumericSumAccum sumX
Definition: numeric.c:3277
#define init_var(v)
Definition: numeric.c:451

◆ do_numeric_discard()

static bool do_numeric_discard ( NumericAggState state,
Numeric  newval 
)
static

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

3395 {
3396  NumericVar X;
3397  NumericVar X2;
3398  MemoryContext old_context;
3399 
3400  /* Count NaN inputs separately from all else */
3401  if (NUMERIC_IS_NAN(newval))
3402  {
3403  state->NaNcount--;
3404  return true;
3405  }
3406 
3407  /* load processed number in short-lived context */
3408  init_var_from_num(newval, &X);
3409 
3410  /*
3411  * state->sumX's dscale is the maximum dscale of any of the inputs.
3412  * Removing the last input with that dscale would require us to recompute
3413  * the maximum dscale of the *remaining* inputs, which we cannot do unless
3414  * no more non-NaN inputs remain at all. So we report a failure instead,
3415  * and force the aggregation to be redone from scratch.
3416  */
3417  if (X.dscale == state->maxScale)
3418  {
3419  if (state->maxScaleCount > 1 || state->maxScale == 0)
3420  {
3421  /*
3422  * Some remaining inputs have same dscale, or dscale hasn't gotten
3423  * above zero anyway
3424  */
3425  state->maxScaleCount--;
3426  }
3427  else if (state->N == 1)
3428  {
3429  /* No remaining non-NaN inputs at all, so reset maxScale */
3430  state->maxScale = 0;
3431  state->maxScaleCount = 0;
3432  }
3433  else
3434  {
3435  /* Correct new maxScale is uncertain, must fail */
3436  return false;
3437  }
3438  }
3439 
3440  /* if we need X^2, calculate that in short-lived context */
3441  if (state->calcSumX2)
3442  {
3443  init_var(&X2);
3444  mul_var(&X, &X, &X2, X.dscale * 2);
3445  }
3446 
3447  /* The rest of this needs to work in the aggregate context */
3448  old_context = MemoryContextSwitchTo(state->agg_context);
3449 
3450  if (state->N-- > 1)
3451  {
3452  /* Negate X, to subtract it from the sum */
3453  X.sign = (X.sign == NUMERIC_POS ? NUMERIC_NEG : NUMERIC_POS);
3454  accum_sum_add(&(state->sumX), &X);
3455 
3456  if (state->calcSumX2)
3457  {
3458  /* Negate X^2. X^2 is always positive */
3459  X2.sign = NUMERIC_NEG;
3460  accum_sum_add(&(state->sumX2), &X2);
3461  }
3462  }
3463  else
3464  {
3465  /* Zero the sums */
3466  Assert(state->N == 0);
3467 
3468  accum_sum_reset(&state->sumX);
3469  if (state->calcSumX2)
3470  accum_sum_reset(&state->sumX2);
3471  }
3472 
3473  MemoryContextSwitchTo(old_context);
3474 
3475  return true;
3476 }
#define NUMERIC_POS
Definition: numeric.c:164
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
MemoryContext agg_context
Definition: numeric.c:3275
int dscale
Definition: numeric.c:274
#define NUMERIC_NEG
Definition: numeric.c:165
static void accum_sum_add(NumericSumAccum *accum, const NumericVar *var1)
Definition: numeric.c:8898
int sign
Definition: numeric.c:273
static void init_var_from_num(Numeric num, NumericVar *dest)
Definition: numeric.c:5721
#define Assert(condition)
Definition: c.h:670
static void mul_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result, int rscale)
Definition: numeric.c:6757
NumericSumAccum sumX2
Definition: numeric.c:3278
static void accum_sum_reset(NumericSumAccum *accum)
Definition: numeric.c:8882
int64 NaNcount
Definition: numeric.c:3281
int64 maxScaleCount
Definition: numeric.c:3280
#define NUMERIC_IS_NAN(n)
Definition: numeric.c:170
NumericSumAccum sumX
Definition: numeric.c:3277
#define init_var(v)
Definition: numeric.c:451

◆ estimate_ln_dweight()

static int estimate_ln_dweight ( const NumericVar var)
static

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

7879 {
7880  int ln_dweight;
7881 
7882  if (cmp_var(var, &const_zero_point_nine) >= 0 &&
7883  cmp_var(var, &const_one_point_one) <= 0)
7884  {
7885  /*
7886  * 0.9 <= var <= 1.1
7887  *
7888  * ln(var) has a negative weight (possibly very large). To get a
7889  * reasonably accurate result, estimate it using ln(1+x) ~= x.
7890  */
7891  NumericVar x;
7892 
7893  init_var(&x);
7894  sub_var(var, &const_one, &x);
7895 
7896  if (x.ndigits > 0)
7897  {
7898  /* Use weight of most significant decimal digit of x */
7899  ln_dweight = x.weight * DEC_DIGITS + (int) log10(x.digits[0]);
7900  }
7901  else
7902  {
7903  /* x = 0. Since ln(1) = 0 exactly, we don't need extra digits */
7904  ln_dweight = 0;
7905  }
7906 
7907  free_var(&x);
7908  }
7909  else
7910  {
7911  /*
7912  * Estimate the logarithm using the first couple of digits from the
7913  * input number. This will give an accurate result whenever the input
7914  * is not too close to 1.
7915  */
7916  if (var->ndigits > 0)
7917  {
7918  int digits;
7919  int dweight;
7920  double ln_var;
7921 
7922  digits = var->digits[0];
7923  dweight = var->weight * DEC_DIGITS;
7924 
7925  if (var->ndigits > 1)
7926  {
7927  digits = digits * NBASE + var->digits[1];
7928  dweight -= DEC_DIGITS;
7929  }
7930 
7931  /*----------
7932  * We have var ~= digits * 10^dweight
7933  * so ln(var) ~= ln(digits) + dweight * ln(10)
7934  *----------
7935  */
7936  ln_var = log((double) digits) + dweight * 2.302585092994046;
7937  ln_dweight = (int) log10(Abs(ln_var));
7938  }
7939  else
7940  {
7941  /* Caller should fail on ln(0), but for the moment return zero */
7942  ln_dweight = 0;
7943  }
7944  }
7945 
7946  return ln_dweight;
7947 }
int weight
Definition: numeric.c:272
static const NumericVar const_zero_point_nine
Definition: numeric.c:409
static const NumericVar const_one
Definition: numeric.c:375
static void ln_var(const NumericVar *arg, NumericVar *result, int rscale)
Definition: numeric.c:7956
int ndigits
Definition: numeric.c:271
#define Abs(x)
Definition: c.h:808
#define NBASE
Definition: numeric.c:93
static int cmp_var(const NumericVar *var1, const NumericVar *var2)
Definition: numeric.c:6461
static void free_var(NumericVar *var)
Definition: numeric.c:5488
NumericDigit * digits
Definition: numeric.c:276
static void sub_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition: numeric.c:6636
#define DEC_DIGITS
Definition: numeric.c:95
static const NumericVar const_one_point_one
Definition: numeric.c:419
#define init_var(v)
Definition: numeric.c:451
int digits
Definition: informix.c:691

◆ exp_var()

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

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

7753 {
7754  NumericVar x;
7755  NumericVar elem;
7756  NumericVar ni;
7757  double val;
7758  int dweight;
7759  int ndiv2;
7760  int sig_digits;
7761  int local_rscale;
7762 
7763  init_var(&x);
7764  init_var(&elem);
7765  init_var(&ni);
7766 
7767  set_var_from_var(arg, &x);
7768 
7769  /*
7770  * Estimate the dweight of the result using floating point arithmetic, so
7771  * that we can choose an appropriate local rscale for the calculation.
7772  */
7774 
7775  /* Guard against overflow */
7776  /* If you change this limit, see also power_var()'s limit */
7777  if (Abs(val) >= NUMERIC_MAX_RESULT_SCALE * 3)
7778  ereport(ERROR,
7779  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
7780  errmsg("value overflows numeric format")));
7781 
7782  /* decimal weight = log10(e^x) = x * log10(e) */
7783  dweight = (int) (val * 0.434294481903252);
7784 
7785  /*
7786  * Reduce x to the range -0.01 <= x <= 0.01 (approximately) by dividing by
7787  * 2^n, to improve the convergence rate of the Taylor series.
7788  */
7789  if (Abs(val) > 0.01)
7790  {
7791  NumericVar tmp;
7792 
7793  init_var(&tmp);
7794  set_var_from_var(&const_two, &tmp);
7795 
7796  ndiv2 = 1;
7797  val /= 2;
7798 
7799  while (Abs(val) > 0.01)
7800  {
7801  ndiv2++;
7802  val /= 2;
7803  add_var(&tmp, &tmp, &tmp);
7804  }
7805 
7806  local_rscale = x.dscale + ndiv2;
7807  div_var_fast(&x, &tmp, &x, local_rscale, true);
7808 
7809  free_var(&tmp);
7810  }
7811  else
7812  ndiv2 = 0;
7813 
7814  /*
7815  * Set the scale for the Taylor series expansion. The final result has
7816  * (dweight + rscale + 1) significant digits. In addition, we have to
7817  * raise the Taylor series result to the power 2^ndiv2, which introduces
7818  * an error of up to around log10(2^ndiv2) digits, so work with this many
7819  * extra digits of precision (plus a few more for good measure).
7820  */
7821  sig_digits = 1 + dweight + rscale + (int) (ndiv2 * 0.301029995663981);
7822  sig_digits = Max(sig_digits, 0) + 8;
7823 
7824  local_rscale = sig_digits - 1;
7825 
7826  /*
7827  * Use the Taylor series
7828  *
7829  * exp(x) = 1 + x + x^2/2! + x^3/3! + ...
7830  *
7831  * Given the limited range of x, this should converge reasonably quickly.
7832  * We run the series until the terms fall below the local_rscale limit.
7833  */
7834  add_var(&const_one, &x, result);
7835 
7836  mul_var(&x, &x, &elem, local_rscale);
7837  set_var_from_var(&const_two, &ni);
7838  div_var_fast(&elem, &ni, &elem, local_rscale, true);
7839 
7840  while (elem.ndigits != 0)
7841  {
7842  add_var(result, &elem, result);
7843 
7844  mul_var(&elem, &x, &elem, local_rscale);
7845  add_var(&ni, &const_one, &ni);
7846  div_var_fast(&elem, &ni, &elem, local_rscale, true);
7847  }
7848 
7849  /*
7850  * Compensate for the argument range reduction. Since the weight of the
7851  * result doubles with each multiplication, we can reduce the local rscale
7852  * as we proceed.
7853  */
7854  while (ndiv2-- > 0)
7855  {
7856  local_rscale = sig_digits - result->weight * 2 * DEC_DIGITS;
7857  local_rscale = Max(local_rscale, NUMERIC_MIN_DISPLAY_SCALE);
7858  mul_var(result, result, result, local_rscale);
7859  }
7860 
7861  /* Round to requested rscale */
7862  round_var(result, rscale);
7863 
7864  free_var(&x);
7865  free_var(&elem);
7866  free_var(&ni);
7867 }
static void round_var(NumericVar *var, int rscale)
Definition: numeric.c:8673
int weight
Definition: numeric.c:272
static const NumericVar const_one
Definition: numeric.c:375
int errcode(int sqlerrcode)
Definition: elog.c:575
int ndigits
Definition: numeric.c:271
int dscale
Definition: numeric.c:274
#define Abs(x)
Definition: c.h:808
#define ERROR
Definition: elog.h:43
static double numericvar_to_double_no_overflow(const NumericVar *var)
Definition: numeric.c:6429
#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:7239
#define ereport(elevel, rest)
Definition: elog.h:122
static void free_var(NumericVar *var)
Definition: numeric.c:5488
static const NumericVar const_two
Definition: numeric.c:379
static void mul_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result, int rscale)
Definition: numeric.c:6757
static void add_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition: numeric.c:6519
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define Max(x, y)
Definition: numeric.c:11
#define DEC_DIGITS
Definition: numeric.c:95
static void set_var_from_var(const NumericVar *value, NumericVar *dest)
Definition: numeric.c:5738
long val
Definition: informix.c:689
#define init_var(v)
Definition: numeric.c:451

◆ float4_numeric()

Datum float4_numeric ( PG_FUNCTION_ARGS  )

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

3208 {
3210  Numeric res;
3211  NumericVar result;
3212  char buf[FLT_DIG + 100];
3213 
3214  if (isnan(val))
3216 
3217  if (isinf(val))
3218  ereport(ERROR,
3219  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3220  errmsg("cannot convert infinity to numeric")));
3221 
3222  snprintf(buf, sizeof(buf), "%.*g", FLT_DIG, val);
3223 
3224  init_var(&result);
3225 
3226  /* Assume we need not worry about leading/trailing spaces */
3227  (void) set_var_from_str(buf, buf, &result);
3228 
3229  res = make_result(&result);
3230 
3231  free_var(&result);
3232 
3233  PG_RETURN_NUMERIC(res);
3234 }
#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:245
#define ereport(elevel, rest)
Definition: elog.h:122
float float4
Definition: c.h:428
static void free_var(NumericVar *var)
Definition: numeric.c:5488
static const char * set_var_from_str(const char *str, const char *cp, NumericVar *dest)
Definition: numeric.c:5528
static const NumericVar const_nan
Definition: numeric.c:422
static Numeric make_result(const NumericVar *var)
Definition: numeric.c:6003
int errmsg(const char *fmt,...)
Definition: elog.c:797
long val
Definition: informix.c:689
#define init_var(v)
Definition: numeric.c:451

◆ float8_numeric()

Datum float8_numeric ( PG_FUNCTION_ARGS  )

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

3137 {
3139  Numeric res;
3140  NumericVar result;
3141  char buf[DBL_DIG + 100];
3142 
3143  if (isnan(val))
3145 
3146  if (isinf(val))
3147  ereport(ERROR,
3148  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3149  errmsg("cannot convert infinity to numeric")));
3150 
3151  snprintf(buf, sizeof(buf), "%.*g", DBL_DIG, val);
3152 
3153  init_var(&result);
3154 
3155  /* Assume we need not worry about leading/trailing spaces */
3156  (void) set_var_from_str(buf, buf, &result);
3157 
3158  res = make_result(&result);
3159 
3160  free_var(&result);
3161 
3162  PG_RETURN_NUMERIC(res);
3163 }
#define PG_RETURN_NUMERIC(x)
Definition: numeric.h:54
#define PG_GETARG_FLOAT8(n)
Definition: fmgr.h:246
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:429
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:5488
static const char * set_var_from_str(const char *str, const char *cp, NumericVar *dest)
Definition: numeric.c:5528
static const NumericVar const_nan
Definition: numeric.c:422
static Numeric make_result(const NumericVar *var)
Definition: numeric.c:6003
int errmsg(const char *fmt,...)
Definition: elog.c:797
long val
Definition: informix.c:689
#define init_var(v)
Definition: numeric.c:451

◆ floor_var()

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

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

7657 {
7658  NumericVar tmp;
7659 
7660  init_var(&tmp);
7661  set_var_from_var(var, &tmp);
7662 
7663  trunc_var(&tmp, 0);
7664 
7665  if (var->sign == NUMERIC_NEG && cmp_var(var, &tmp) != 0)
7666  sub_var(&tmp, &const_one, &tmp);
7667 
7668  set_var_from_var(&tmp, result);
7669  free_var(&tmp);
7670 }
static void trunc_var(NumericVar *var, int rscale)
Definition: numeric.c:8779
static const NumericVar const_one
Definition: numeric.c:375
#define NUMERIC_NEG
Definition: numeric.c:165
int sign
Definition: numeric.c:273
static int cmp_var(const NumericVar *var1, const NumericVar *var2)
Definition: numeric.c:6461
static void free_var(NumericVar *var)
Definition: numeric.c:5488
static void sub_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
Definition: numeric.c:6636
static void set_var_from_var(const NumericVar *value, NumericVar *dest)
Definition: numeric.c:5738
#define init_var(v)
Definition: numeric.c:451

◆ free_var()

static void free_var ( NumericVar var)
static

◆ generate_series_numeric()

Datum generate_series_numeric ( PG_FUNCTION_ARGS  )

Definition at line 1367 of file numeric.c.

References generate_series_step_numeric().

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

◆ generate_series_step_numeric()

Datum generate_series_step_numeric ( PG_FUNCTION_ARGS  )

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

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

◆ get_str_from_var()

static char * get_str_from_var ( const NumericVar var)
static

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

5765 {
5766  int dscale;
5767  char *str;
5768  char *cp;
5769  char *endcp;
5770  int i;
5771  int d;
5772  NumericDigit dig;
5773 
5774 #if DEC_DIGITS > 1
5775  NumericDigit d1;
5776 #endif
5777 
5778  dscale = var->dscale;
5779 
5780  /*
5781  * Allocate space for the result.
5782  *
5783  * i is set to the # of decimal digits before decimal point. dscale is the
5784  * # of decimal digits we will print after decimal point. We may generate
5785  * as many as DEC_DIGITS-1 excess digits at the end, and in addition we
5786  * need room for sign, decimal point, null terminator.
5787  */
5788  i = (var->weight + 1) * DEC_DIGITS;
5789  if (i <= 0)
5790  i = 1;
5791 
5792  str = palloc(i + dscale + DEC_DIGITS + 2);
5793  cp = str;
5794 
5795  /*
5796  * Output a dash for negative values
5797  */
5798  if (var->sign == NUMERIC_NEG)
5799  *cp++ = '-';
5800 
5801  /*
5802  * Output all digits before the decimal point
5803  */
5804  if (var->weight < 0)
5805  {
5806  d = var->weight + 1;
5807  *cp++ = '0';
5808  }
5809  else
5810  {
5811  for (d = 0; d <= var->weight; d++)
5812  {
5813  dig = (d < var->ndigits) ? var->digits[d] : 0;
5814  /* In the first digit, suppress extra leading decimal zeroes */
5815 #if DEC_DIGITS == 4
5816  {
5817  bool putit = (d > 0);
5818 
5819  d1 = dig / 1000;
5820  dig -= d1 * 1000;
5821  putit |= (d1 > 0);
5822  if (putit)
5823  *cp++ = d1 + '0';
5824  d1 = dig / 100;
5825  dig -= d1 * 100;
5826  putit |= (d1 > 0);
5827  if (putit)
5828  *cp++ = d1 + '0';
5829  d1 = dig / 10;
5830  dig -= d1 * 10;
5831  putit |= (d1 > 0);
5832  if (putit)
5833  *cp++ = d1 + '0';
5834  *cp++ = dig + '0';
5835  }
5836 #elif DEC_DIGITS == 2
5837  d1 = dig / 10;
5838  dig -= d1 * 10;
5839  if (d1 > 0 || d > 0)
5840  *cp++ = d1 + '0';
5841  *cp++ = dig + '0';
5842 #elif DEC_DIGITS == 1
5843  *cp++ = dig + '0';
5844 #else
5845 #error unsupported NBASE
5846 #endif
5847  }
5848  }
5849 
5850  /*
5851  * If requested, output a decimal point and all the digits that follow it.
5852  * We initially put out a multiple of DEC_DIGITS digits, then truncate if
5853  * needed.
5854  */
5855  if (dscale > 0)
5856  {
5857  *cp++ = '.';
5858  endcp = cp + dscale;
5859  for (i = 0; i < dscale; d++, i += DEC_DIGITS)
5860  {
5861  dig = (d >= 0 && d < var->ndigits) ? var->digits[d] : 0;
5862 #if DEC_DIGITS == 4
5863  d1 = dig / 1000;
5864  dig -= d1 * 1000;
5865  *cp++ = d1 + '0';
5866  d1 = dig / 100;
5867  dig -= d1 * 100;
5868  *cp++ = d1 + '0';
5869  d1 = dig / 10;
5870  dig -= d1 * 10;
5871  *cp++ = d1 + '0';
5872  *cp++ = dig + '0';
5873 #elif DEC_DIGITS == 2
5874  d1 = dig / 10;
5875  dig -= d1 * 10;
5876  *cp++ = d1 + '0';
5877  *cp++ = dig + '0';
5878 #elif DEC_DIGITS == 1
5879  *cp++ = dig + '0';
5880 #else
5881 #error unsupported NBASE
5882 #endif
5883  }
5884  cp = endcp;
5885  }
5886 
5887  /*
5888  * terminate the string and return it
5889  */
5890  *cp = '\0';
5891  return str;
5892 }
int weight
Definition: numeric.c:272
static void error(void)
Definition: sql-dyntest.c:147
int ndigits
Definition: numeric.c:271
int dscale
Definition: numeric.c:274
#define NUMERIC_NEG
Definition: numeric.c:165
int sign
Definition: numeric.c:273
int16 NumericDigit
Definition: numeric.c:99
#define NBASE
Definition: numeric.c:93
NumericDigit * digits
Definition: numeric.c:276
void * palloc(Size size)
Definition: mcxt.c:848
int i
#define DEC_DIGITS
Definition: numeric.c:95

◆ get_str_from_var_sci()

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

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

5918 {
5919  int32 exponent;
5920  NumericVar denominator;
5921  NumericVar significand;
5922  int denom_scale;
5923  size_t len;
5924  char *str;
5925  char *sig_out;
5926 
5927  if (rscale < 0)
5928  rscale = 0;
5929 
5930  /*
5931  * Determine the exponent of this number in normalised form.
5932  *
5933  * This is the exponent required to represent the number with only one
5934  * significant digit before the decimal place.
5935  */
5936  if (var->ndigits > 0)
5937  {
5938  exponent = (var->weight + 1) * DEC_DIGITS;
5939 
5940  /*
5941  * Compensate for leading decimal zeroes in the first numeric digit by
5942  * decrementing the exponent.
5943  */
5944  exponent -= DEC_DIGITS - (int) log10(var->digits[0]);
5945  }
5946  else
5947  {
5948  /*
5949  * If var has no digits, then it must be zero.
5950  *
5951  * Zero doesn't technically have a meaningful exponent in normalised
5952  * notation, but we just display the exponent as zero for consistency
5953  * of output.
5954  */
5955  exponent = 0;
5956  }
5957 
5958  /*
5959  * The denominator is set to 10 raised to the power of the exponent.
5960  *
5961  * We then divide var by the denominator to get the significand, rounding
5962  * to rscale decimal digits in the process.
5963  */
5964  if (exponent < 0)
5965  denom_scale = -exponent;
5966  else
5967  denom_scale = 0;
5968 
5969  init_var(&denominator);
5970  init_var(&significand);
5971 
5972  power_var_int(&const_ten, exponent, &denominator, denom_scale);
5973  div_var(var, &denominator, &significand, rscale, true);
5974  sig_out = get_str_from_var(&significand);
5975 
5976  free_var(&denominator);
5977  free_var(&significand);
5978 
5979  /*
5980  * Allocate space for the result.
5981  *
5982  * In addition to the significand, we need room for the exponent
5983  * decoration ("e"), the sign of the exponent, up to 10 digits for the
5984  * exponent itself, and of course the null terminator.
5985  */
5986  len = strlen(sig_out) + 13;
5987  str = palloc(len);
5988  snprintf(str, len, "%se%+03d", sig_out, exponent);
5989 
5990  pfree(sig_out);
5991 
5992  return str;
5993 }
int weight
Definition: numeric.c:272
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
int ndigits
Definition: numeric.c:271
static void div_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result, int rscale, bool round)
Definition: numeric.c:6954
signed int int32
Definition: c.h:284
void pfree(void *pointer)
Definition: mcxt.c:949
static void power_var_int(const NumericVar *base, int exp, NumericVar *result, int rscale)
Definition: numeric.c:8238
static const NumericVar const_ten
Definition: numeric.c:384
static void free_var(NumericVar *var)
Definition: numeric.c:5488
NumericDigit * digits
Definition: numeric.c:276
void * palloc(Size size)
Definition: mcxt.c:848
static char * get_str_from_var(const NumericVar *var)
Definition: numeric.c:5764
#define DEC_DIGITS
Definition: numeric.c:95
#define init_var(v)
Definition: numeric.c:451

◆ hash_numeric()

Datum hash_numeric ( PG_FUNCTION_ARGS  )

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

2169 {
2170  Numeric key = PG_GETARG_NUMERIC(0);
2171  Datum digit_hash;
2172  Datum result;
2173  int weight;
2174  int start_offset;
2175  int end_offset;
2176  int i;
2177  int hash_len;
2179 
2180  /* If it's NaN, don't try to hash the rest of the fields */
2181  if (NUMERIC_IS_NAN(key))
2182  PG_RETURN_UINT32(0);
2183 
2184  weight = NUMERIC_WEIGHT(key);
2185  start_offset = 0;
2186  end_offset = 0;
2187 
2188  /*
2189  * Omit any leading or trailing zeros from the input to the hash. The
2190  * numeric implementation *should* guarantee that leading and trailing
2191  * zeros are suppressed, but we're paranoid. Note that we measure the
2192  * starting and ending offsets in units of NumericDigits, not bytes.
2193  */
2194  digits = NUMERIC_DIGITS(key);
2195  for (i = 0; i < NUMERIC_NDIGITS(key); i++)
2196  {
2197  if (digits[i] != (NumericDigit) 0)
2198  break;
2199 
2200  start_offset++;
2201 
2202  /*
2203  * The weight is effectively the # of digits before the decimal point,
2204  * so decrement it for each leading zero we skip.
2205  */
2206  weight--;
2207  }
2208 
2209  /*
2210  * If there are no non-zero digits, then the value of the number is zero,
2211  * regardless of any other fields.
2212  */
2213  if (NUMERIC_NDIGITS(key) == start_offset)
2214  PG_RETURN_UINT32(-1);
2215 
2216  for (i = NUMERIC_NDIGITS(key) - 1; i >= 0; i--)
2217  {
2218  if (digits[i] != (NumericDigit) 0)
2219  break;
2220 
2221  end_offset++;
2222  }
2223 
2224  /* If we get here, there should be at least one non-zero digit */
2225  Assert(start_offset + end_offset < NUMERIC_NDIGITS(key));
2226 
2227  /*
2228  * Note that we don't hash on the Numeric's scale, since two numerics can
2229  * compare equal but have different scales. We also don't hash on the
2230  * sign, although we could: since a sign difference implies inequality,
2231  * this shouldn't affect correctness.
2232  */
2233  hash_len = NUMERIC_NDIGITS(key) - start_offset - end_offset;
2234  digit_hash = hash_any((unsigned char *) (NUMERIC_DIGITS(key) + start_offset),
2235  hash_len * sizeof(NumericDigit));
2236 
2237  /* Mix in the weight, via XOR */
2238  result = digit_hash ^ weight;
2239 
2240  PG_RETURN_DATUM(result);
2241 }
#define PG_RETURN_UINT32(x)
Definition: fmgr.h:315
#define NUMERIC_DIGITS(num)
Definition: numeric.c:453
int16 NumericDigit
Definition: numeric.c:99
#define NUMERIC_NDIGITS(num)
Definition: numeric.c:455
uintptr_t Datum
Definition: postgres.h:372
#define PG_RETURN_DATUM(x)
Definition: fmgr.h:313
#define NUMERIC_WEIGHT(n)
Definition: numeric.c:214
#define PG_GETARG_NUMERIC(n)
Definition: numeric.h:52
#define Assert(condition)
Definition: c.h:670
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:170
int digits
Definition: informix.c:691

◆ hash_numeric_extended()

Datum hash_numeric_extended ( PG_FUNCTION_ARGS  )

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

2249 {
2250  Numeric key = PG_GETARG_NUMERIC(0);
2251  uint64 seed = PG_GETARG_INT64(1);
2252  Datum digit_hash;
2253  Datum result;
2254  int weight;
2255  int start_offset;
2256  int end_offset;
2257  int i;
2258  int hash_len;
2260 
2261  if (NUMERIC_IS_NAN(key))
2262  PG_RETURN_UINT64(seed);
2263 
2264  weight = NUMERIC_WEIGHT(key);
2265  start_offset = 0;
2266  end_offset = 0;
2267 
2268  digits = NUMERIC_DIGITS(key);
2269  for (i = 0; i < NUMERIC_NDIGITS(key); i++)
2270  {
2271  if (digits[i] != (NumericDigit) 0)
2272  break;
2273 
2274  start_offset++;
2275 
2276  weight--;
2277  }
2278 
2279  if (NUMERIC_NDIGITS(key) == start_offset)
2280  PG_RETURN_UINT64(seed - 1);
2281 
2282  for (i = NUMERIC_NDIGITS(key) - 1; i >= 0; i--)
2283  {
2284  if (digits[i] != (NumericDigit) 0)
2285  break;
2286 
2287  end_offset++;
2288  }
2289 
2290  Assert(start_offset + end_offset < NUMERIC_NDIGITS(key));
2291 
2292  hash_len = NUMERIC_NDIGITS(key) - start_offset - end_offset;
2293  digit_hash = hash_any_extended((unsigned char *) (NUMERIC_DIGITS(key)
2294  + start_offset),
2295  hash_len * sizeof(NumericDigit),
2296  seed);
2297 
2298  result = UInt64GetDatum(DatumGetUInt64(digit_hash) ^ weight);
2299 
2300  PG_RETURN_DATUM(result);
2301 }
#define UInt64GetDatum(X)
Definition: postgres.h:654
#define PG_RETURN_UINT64(x)
Definition: fmgr.h:328
#define NUMERIC_DIGITS(num)
Definition: numeric.c:453
int16 NumericDigit
Definition: numeric.c:99
#define NUMERIC_NDIGITS(num)
Definition: numeric.c:455
uintptr_t Datum
Definition: postgres.h:372
#define PG_RETURN_DATUM(x)
Definition: fmgr.h:313
#define DatumGetUInt64(X)
Definition: postgres.h:640
#define NUMERIC_WEIGHT(n)
Definition: numeric.c:214
#define PG_GETARG_NUMERIC(n)
Definition: numeric.h:52
#define Assert(condition)
Definition: c.h:670
int i
#define NUMERIC_IS_NAN(n)
Definition: numeric.c:170
#define PG_GETARG_INT64(n)
Definition: fmgr.h:247
Datum hash_any_extended(register const unsigned char *k, register int keylen, uint64 seed)
Definition: hashfunc.c:634
int digits
Definition: informix.c:691

◆ init_var_from_num()

static void init_var_from_num ( Numeric  num,
NumericVar dest 
)
static

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

5722 {
5723  dest->ndigits = NUMERIC_NDIGITS(num);
5724  dest->weight = NUMERIC_WEIGHT(num);
5725  dest->sign = NUMERIC_SIGN(num);
5726  dest->dscale = NUMERIC_DSCALE(num);
5727  dest->digits = NUMERIC_DIGITS(num);
5728  dest->buf = NULL; /* digits array is not palloc'd */
5729 }
#define NUMERIC_DSCALE(n)
Definition: numeric.c:210
int weight
Definition: numeric.c:272
int ndigits
Definition: numeric.c:271
int dscale
Definition: numeric.c:274
int sign
Definition: numeric.c:273
#define NUMERIC_DIGITS(num)
Definition: numeric.c:453
#define NUMERIC_SIGN(n)
Definition: numeric.c:206
NumericDigit * buf
Definition: numeric.c:275
#define NUMERIC_NDIGITS(num)
Definition: numeric.c:455
#define NUMERIC_WEIGHT(n)
Definition: numeric.c:214
NumericDigit * digits
Definition: numeric.c:276

◆ int2_accum()

Datum int2_accum ( PG_FUNCTION_ARGS  )

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

4020 {
4022 
4023  state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
4024 
4025  /* Create the state data on the first call */
4026  if (state == NULL)
4027  state = makePolyNumAggState(fcinfo, true);
4028 
4029  if (!PG_ARGISNULL(1))
4030  {
4031 #ifdef HAVE_INT128
4032  do_int128_accum(state, (int128) PG_GETARG_INT16(1));
4033 #else
4034  Numeric newval;
4035 
4037  PG_GETARG_DATUM(1)));
4038  do_numeric_accum(state, newval);
4039 #endif
4040  }
4041 
4042  PG_RETURN_POINTER(state);
4043 }
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:321
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:233
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:241
Datum int2_numeric(PG_FUNCTION_ARGS)
Definition: numeric.c:3082
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:585
static void do_numeric_accum(NumericAggState *state, Numeric newval)
Definition: numeric.c:3329
#define PG_GETARG_INT16(n)
Definition: fmgr.h:236
#define PG_ARGISNULL(n)
Definition: fmgr.h:174
#define DatumGetNumeric(X)
Definition: numeric.h:49
Definition: regguts.h:298
#define newval
#define makePolyNumAggState
Definition: numeric.c:4014

◆ int2_accum_inv()

Datum int2_accum_inv ( PG_FUNCTION_ARGS  )

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

4497 {
4499 
4500  state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
4501 
4502  /* Should not get here with no state */
4503  if (state == NULL)
4504  elog(ERROR, "int2_accum_inv called with NULL state");
4505 
4506  if (!PG_ARGISNULL(1))
4507  {
4508 #ifdef HAVE_INT128
4509  do_int128_discard(state, (int128) PG_GETARG_INT16(1));
4510 #else
4511  Numeric newval;
4512 
4514  PG_GETARG_DATUM(1)));
4515 
4516  /* Should never fail, all inputs have dscale 0 */
4517  if (!do_numeric_discard(state, newval))
4518  elog(ERROR, "do_numeric_discard failed unexpectedly");
4519 #endif
4520  }
4521 
4522  PG_RETURN_POINTER(state);
4523 }
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:321
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:233
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:241
Datum int2_numeric(PG_FUNCTION_ARGS)
Definition: numeric.c:3082
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:585
static bool do_numeric_discard(NumericAggState *state, Numeric newval)
Definition: numeric.c:3394
#define ERROR
Definition: elog.h:43
#define PG_GETARG_INT16(n)
Definition: fmgr.h:236
#define PG_ARGISNULL(n)
Definition: fmgr.h:174
#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 5187 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.

5188 {
5189  ArrayType *transarray;
5191  Int8TransTypeData *transdata;
5192 
5193  /*
5194  * If we're invoked as an aggregate, we can cheat and modify our first
5195  * parameter in-place to reduce palloc overhead. Otherwise we need to make
5196  * a copy of it before scribbling on it.
5197  */
5198  if (AggCheckCallContext(fcinfo, NULL))
5199  transarray = PG_GETARG_ARRAYTYPE_P(0);
5200  else
5201  transarray = PG_GETARG_ARRAYTYPE_P_COPY(0);
5202 
5203  if (ARR_HASNULL(transarray) ||
5204  ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
5205  elog(ERROR, "expected 2-element int8 array");
5206 
5207  transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
5208  transdata->count++;
5209  transdata->sum += newval;
5210 
5211  PG_RETURN_ARRAYTYPE_P(transarray);
5212 }
signed short int16
Definition: c.h:283
#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:236
#define newval
int AggCheckCallContext(FunctionCallInfo fcinfo, MemoryContext *aggcontext)
Definition: nodeAgg.c:4116
#define elog
Definition: elog.h:219

◆ int2_avg_accum_inv()

Datum int2_avg_accum_inv ( PG_FUNCTION_ARGS  )

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

5275 {
5276  ArrayType *transarray;
5278  Int8TransTypeData *transdata;
5279 
5280  /*
5281  * If we're invoked as an aggregate, we can cheat and modify our first
5282  * parameter in-place to reduce palloc overhead. Otherwise we need to make
5283  * a copy of it before scribbling on it.
5284  */
5285  if (AggCheckCallContext(fcinfo, NULL))
5286  transarray = PG_GETARG_ARRAYTYPE_P(0);
5287  else
5288  transarray = PG_GETARG_ARRAYTYPE_P_COPY(0);
5289 
5290  if (ARR_HASNULL(transarray) ||
5291  ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
5292  elog(ERROR, "expected 2-element int8 array");
5293 
5294  transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
5295  transdata->count--;
5296  transdata->sum -= newval;
5297 
5298  PG_RETURN_ARRAYTYPE_P(transarray);
5299 }
signed short int16
Definition: c.h:283
#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:236
#define newval
int AggCheckCallContext(FunctionCallInfo fcinfo, MemoryContext *aggcontext)
Definition: nodeAgg.c:4116
#define elog
Definition: elog.h:219

◆ int2_numeric()

Datum int2_numeric ( PG_FUNCTION_ARGS  )

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

3083 {
3084  int16 val = PG_GETARG_INT16(0);
3085  Numeric res;
3086  NumericVar result;
3087 
3088  init_var(&result);
3089 
3090  int64_to_numericvar((int64) val, &result);
3091 
3092  res = make_result(&result);
3093 
3094  free_var(&result);
3095 
3096  PG_RETURN_NUMERIC(res);
3097 }
#define PG_RETURN_NUMERIC(x)
Definition: numeric.h:54
signed short int16
Definition: c.h:283
#define PG_GETARG_INT16(n)
Definition: fmgr.h:236
static void free_var(NumericVar *var)
Definition: numeric.c:5488
static Numeric make_result(const NumericVar *var)
Definition: numeric.c:6003
static void int64_to_numericvar(int64 val, NumericVar *var)
Definition: numeric.c:6237
long val
Definition: informix.c:689
#define init_var(v)
Definition: numeric.c:451

◆ int2_sum()

Datum int2_sum ( PG_FUNCTION_ARGS  )

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

5036 {
5037  int64 newval;
5038 
5039  if (PG_ARGISNULL(0))
5040  {
5041  /* No non-null input seen so far... */
5042  if (PG_ARGISNULL(1))
5043  PG_RETURN_NULL(); /* still no non-null */
5044  /* This is the first non-null input. */
5045  newval = (int64) PG_GETARG_INT16(1);
5046  PG_RETURN_INT64(newval);
5047  }
5048 
5049  /*
5050  * If we're invoked as an aggregate, we can cheat and modify our first
5051  * parameter in-place to avoid palloc overhead. If not, we need to return
5052  * the new value of the transition variable. (If int8 is pass-by-value,
5053  * then of course this is useless as well as incorrect, so just ifdef it
5054  * out.)
5055  */
5056 #ifndef USE_FLOAT8_BYVAL /* controls int8 too */
5057  if (AggCheckCallContext(fcinfo, NULL))
5058  {
5059  int64 *oldsum = (int64 *) PG_GETARG_POINTER(0);
5060 
5061  /* Leave the running sum unchanged in the new input is null */
5062  if (!PG_ARGISNULL(1))
5063  *oldsum = *oldsum + (int64) PG_GETARG_INT16(1);
5064 
5065  PG_RETURN_POINTER(oldsum);
5066  }
5067  else
5068 #endif
5069  {
5070  int64 oldsum = PG_GETARG_INT64(0);
5071 
5072  /* Leave sum unchanged if new input is null. */
5073  if (PG_ARGISNULL(1))
5074  PG_RETURN_INT64(oldsum);
5075 
5076  /* OK to do the addition. */
5077  newval = oldsum + (int64) PG_GETARG_INT16(1);
5078 
5079  PG_RETURN_INT64(newval);
5080  }
5081 }
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:321
#define PG_RETURN_INT64(x)
Definition: fmgr.h:327
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:241
#define PG_GETARG_INT16(n)
Definition: fmgr.h:236
#define PG_ARGISNULL(n)
Definition: fmgr.h:174
#define newval
int AggCheckCallContext(FunctionCallInfo fcinfo, MemoryContext *aggcontext)
Definition: nodeAgg.c:4116
#define PG_GETARG_INT64(n)
Definition: fmgr.h:247
#define PG_RETURN_NULL()
Definition: fmgr.h:305

◆ int2int4_sum()

Datum int2int4_sum ( PG_FUNCTION_ARGS  )

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

5360 {
5361  ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
5362  Int8TransTypeData *transdata;
5363 
5364  if (ARR_HASNULL(transarray) ||
5365  ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
5366  elog(ERROR, "expected 2-element int8 array");
5367  transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
5368 
5369  /* SQL defines SUM of no values to be NULL */
5370  if (transdata->count == 0)
5371  PG_RETURN_NULL();
5372 
5373  PG_RETURN_DATUM(Int64GetDatumFast(transdata->sum));
5374 }
#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:313
#define Int64GetDatumFast(X)
Definition: postgres.h:781
#define elog
Definition: elog.h:219
#define PG_RETURN_NULL()
Definition: fmgr.h:305

◆ int4_accum()

Datum int4_accum ( PG_FUNCTION_ARGS  )

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

4047 {
4049 
4050  state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
4051 
4052  /* Create the state data on the first call */
4053  if (state == NULL)
4054  state = makePolyNumAggState(fcinfo, true);
4055 
4056  if (!PG_ARGISNULL(1))
4057  {
4058 #ifdef HAVE_INT128
4059  do_int128_accum(state, (int128) PG_GETARG_INT32(1));
4060 #else
4061  Numeric newval;
4062 
4064  PG_GETARG_DATUM(1)));
4065  do_numeric_accum(state, newval);
4066 #endif
4067  }
4068 
4069  PG_RETURN_POINTER(state);
4070 }
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:321
#define PG_GETARG_INT32(n)
Definition: fmgr.h:234
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:233
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:241
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:585
static void do_numeric_accum(NumericAggState *state, Numeric newval)
Definition: numeric.c:3329
Datum int4_numeric(PG_FUNCTION_ARGS)
Definition: numeric.c:2972
#define PG_ARGISNULL(n)
Definition: fmgr.h:174
#define DatumGetNumeric(X)
Definition: numeric.h:49
Definition: regguts.h:298
#define newval
#define makePolyNumAggState
Definition: numeric.c:4014

◆ int4_accum_inv()

Datum int4_accum_inv ( PG_FUNCTION_ARGS  )

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

4527 {
4529 
4530  state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
4531 
4532  /* Should not get here with no state */
4533  if (state == NULL)
4534  elog(ERROR, "int4_accum_inv called with NULL state");
4535 
4536  if (!PG_ARGISNULL(1))
4537  {
4538 #ifdef HAVE_INT128
4539  do_int128_discard(state, (int128) PG_GETARG_INT32(1));
4540 #else
4541  Numeric newval;
4542 
4544  PG_GETARG_DATUM(1)));
4545 
4546  /* Should never fail, all inputs have dscale 0 */
4547  if (!do_numeric_discard(state, newval))
4548  elog(ERROR, "do_numeric_discard failed unexpectedly");
4549 #endif
4550  }
4551 
4552  PG_RETURN_POINTER(state);
4553 }
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:321
#define PG_GETARG_INT32(n)
Definition: fmgr.h:234
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:233
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:241
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:585
static bool do_numeric_discard(NumericAggState *state, Numeric newval)
Definition: numeric.c:3394
#define ERROR
Definition: elog.h:43
Datum int4_numeric(PG_FUNCTION_ARGS)
Definition: numeric.c:2972
#define PG_ARGISNULL(n)
Definition: fmgr.h:174
#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 5215 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.

5216 {
5217  ArrayType *transarray;
5219  Int8TransTypeData *transdata;
5220 
5221  /*
5222  * If we're invoked as an aggregate, we can cheat and modify our first
5223  * parameter in-place to reduce palloc overhead. Otherwise we need to make
5224  * a copy of it before scribbling on it.
5225  */
5226  if (AggCheckCallContext(fcinfo, NULL))
5227  transarray = PG_GETARG_ARRAYTYPE_P(0);
5228  else
5229  transarray = PG_GETARG_ARRAYTYPE_P_COPY(0);
5230 
5231  if (ARR_HASNULL(transarray) ||
5232  ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
5233  elog(ERROR, "expected 2-element int8 array");
5234 
5235  transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
5236  transdata->count++;
5237  transdata->sum += newval;
5238 
5239  PG_RETURN_ARRAYTYPE_P(transarray);
5240 }
#define PG_GETARG_INT32(n)
Definition: fmgr.h:234
#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:284
#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:4116
#define elog
Definition: elog.h:219

◆ int4_avg_accum_inv()

Datum int4_avg_accum_inv ( PG_FUNCTION_ARGS  )

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

5303 {
5304  ArrayType *transarray;
5306  Int8TransTypeData *transdata;
5307 
5308  /*
5309  * If we're invoked as an aggregate, we can cheat and modify our first
5310  * parameter in-place to reduce palloc overhead. Otherwise we need to make
5311  * a copy of it before scribbling on it.
5312  */
5313  if (AggCheckCallContext(fcinfo, NULL))
5314  transarray = PG_GETARG_ARRAYTYPE_P(0);
5315  else
5316  transarray = PG_GETARG_ARRAYTYPE_P_COPY(0);
5317 
5318  if (ARR_HASNULL(transarray) ||
5319  ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
5320  elog(ERROR, "expected 2-element int8 array");
5321 
5322  transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
5323  transdata->count--;
5324  transdata->sum -= newval;
5325 
5326  PG_RETURN_ARRAYTYPE_P(transarray);
5327 }
#define PG_GETARG_INT32(n)
Definition: fmgr.h:234
#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:284
#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:4116
#define elog
Definition: elog.h:219

◆ int4_avg_combine()

Datum int4_avg_combine ( PG_FUNCTION_ARGS  )

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

5244 {
5245  ArrayType *transarray1;
5246  ArrayType *transarray2;
5247  Int8TransTypeData *state1;
5248  Int8TransTypeData *state2;
5249 
5250  if (!AggCheckCallContext(fcinfo, NULL))
5251  elog(ERROR, "aggregate function called in non-aggregate context");
5252 
5253  transarray1 = PG_GETARG_ARRAYTYPE_P(0);
5254  transarray2 = PG_GETARG_ARRAYTYPE_P(1);
5255 
5256  if (ARR_HASNULL(transarray1) ||
5257  ARR_SIZE(transarray1) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
5258  elog(ERROR, "expected 2-element int8 array");
5259 
5260  if (ARR_HASNULL(transarray2) ||
5261  ARR_SIZE(transarray2) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
5262  elog(ERROR, "expected 2-element int8 array");
5263 
5264  state1 = (Int8TransTypeData *) ARR_DATA_PTR(transarray1);
5265  state2 = (Int8TransTypeData *) ARR_DATA_PTR(transarray2);
5266 
5267  state1->count += state2->count;
5268  state1->sum += state2->sum;
5269 
5270  PG_RETURN_ARRAYTYPE_P(transarray1);
5271 }
#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:4116
#define elog
Definition: elog.h:219

◆ int4_numeric()

Datum int4_numeric ( PG_FUNCTION_ARGS  )

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

2973 {
2974  int32 val = PG_GETARG_INT32(0);
2975  Numeric res;
2976  NumericVar result;
2977 
2978  init_var(&result);
2979 
2980  int64_to_numericvar((int64) val, &result);
2981 
2982  res = make_result(&result);
2983 
2984  free_var(&result);
2985 
2986  PG_RETURN_NUMERIC(res);
2987 }
#define PG_RETURN_NUMERIC(x)
Definition: numeric.h:54
#define PG_GETARG_INT32(n)
Definition: fmgr.h:234
signed int int32
Definition: c.h:284
static void free_var(NumericVar *var)
Definition: numeric.c:5488
static Numeric make_result(const NumericVar *var)
Definition: numeric.c:6003
static void int64_to_numericvar(int64 val, NumericVar *var)
Definition: numeric.c:6237
long val
Definition: informix.c:689
#define init_var(v)
Definition: numeric.c:451

◆ int4_sum()

Datum int4_sum ( PG_FUNCTION_ARGS  )

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

5085 {
5086  int64 newval;
5087 
5088  if (PG_ARGISNULL(0))
5089  {
5090  /* No non-null input seen so far... */
5091  if (PG_ARGISNULL(1))
5092  PG_RETURN_NULL(); /* still no non-null */
5093  /* This is the first non-null input. */
5094  newval = (int64) PG_GETARG_INT32(1);
5095  PG_RETURN_INT64(newval);
5096  }
5097 
5098  /*
5099  * If we're invoked as an aggregate, we can cheat and modify our first
5100  * parameter in-place to avoid palloc overhead. If not, we need to return
5101  * the new value of the transition variable. (If int8 is pass-by-value,
5102  * then of course this is useless as well as incorrect, so just ifdef it
5103  * out.)
5104  */
5105 #ifndef USE_FLOAT8_BYVAL /* controls int8 too */
5106  if (AggCheckCallContext(fcinfo, NULL))
5107  {
5108  int64 *oldsum = (int64 *) PG_GETARG_POINTER(0);
5109 
5110  /* Leave the running sum unchanged in the new input is null */
5111  if (!PG_ARGISNULL(1))
5112  *oldsum = *oldsum + (int64) PG_GETARG_INT32(1);
5113 
5114  PG_RETURN_POINTER(oldsum);
5115  }
5116  else
5117 #endif
5118  {
5119  int64 oldsum = PG_GETARG_INT64(0);
5120 
5121  /* Leave sum unchanged if new input is null. */
5122  if (PG_ARGISNULL(1))
5123  PG_RETURN_INT64(oldsum);
5124 
5125  /* OK to do the addition. */
5126  newval = oldsum + (int64) PG_GETARG_INT32(1);
5127 
5128  PG_RETURN_INT64(newval);
5129  }
5130 }
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:321
#define PG_GETARG_INT32(n)
Definition: fmgr.h:234
#define PG_RETURN_INT64(x)
Definition: fmgr.h:327
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:241
#define PG_ARGISNULL(n)
Definition: fmgr.h:174
#define newval
int AggCheckCallContext(FunctionCallInfo fcinfo, MemoryContext *aggcontext)
Definition: nodeAgg.c:4116
#define PG_GETARG_INT64(n)
Definition: fmgr.h:247
#define PG_RETURN_NULL()
Definition: fmgr.h:305

◆ int64_to_numericvar()

static void int64_to_numericvar ( int64  val,
NumericVar var 
)
static

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

6238 {
6239  uint64 uval,
6240  newuval;
6241  NumericDigit *ptr;
6242  int ndigits;
6243 
6244  /* int64 can require at most 19 decimal digits; add one for safety */
6245  alloc_var(var, 20 / DEC_DIGITS);
6246  if (val < 0)
6247  {
6248  var->sign = NUMERIC_NEG;
6249  uval = -val;
6250  }
6251  else
6252  {
6253  var->sign = NUMERIC_POS;
6254  uval = val;
6255  }
6256  var->dscale = 0;
6257  if (val == 0)
6258  {
6259  var->ndigits = 0;
6260  var->weight = 0;
6261  return;
6262  }
6263  ptr = var->digits + var->ndigits;
6264  ndigits = 0;
6265  do
6266  {
6267  ptr--;
6268  ndigits++;
6269  newuval = uval / NBASE;
6270  *ptr = uval - newuval * NBASE;
6271  uval = newuval;
6272  } while (uval);
6273  var->digits = ptr;
6274  var->ndigits = ndigits;
6275  var->weight = ndigits - 1;
6276 }
int weight
Definition: numeric.c:272
#define NUMERIC_POS
Definition: numeric.c:164
int ndigits
Definition: numeric.c:271
int dscale
Definition: numeric.c:274
#define NUMERIC_NEG
Definition: numeric.c:165
int sign
Definition: numeric.c:273
int16 NumericDigit
Definition: numeric.c:99
#define NBASE
Definition: numeric.c:93
NumericDigit * digits
Definition: numeric.c:276
static void alloc_var(NumericVar *var, int ndigits)
Definition: numeric.c:5472
#define DEC_DIGITS
Definition: numeric.c:95
long val
Definition: informix.c:689

◆ int8_accum()

Datum int8_accum ( PG_FUNCTION_ARGS  )

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

4074 {
4076 
4077  state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
4078 
4079  /* Create the state data on the first call */
4080  if (state == NULL)
4081  state = makeNumericAggState(fcinfo, true);
4082 
4083  if (!PG_ARGISNULL(1))
4084  {
4085  Numeric newval;
4086 
4088  PG_GETARG_DATUM(1)));
4089  do_numeric_accum(state, newval);
4090  }
4091 
4092  PG_RETURN_POINTER(state);
4093 }
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:321
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:233
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:241
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:585
Datum int8_numeric(PG_FUNCTION_ARGS)
Definition: numeric.c:3038
static NumericAggState * makeNumericAggState(FunctionCallInfo fcinfo, bool calcSumX2)
Definition: numeric.c:3289
static void do_numeric_accum(NumericAggState *state, Numeric newval)
Definition: numeric.c:3329
#define PG_ARGISNULL(n)
Definition: fmgr.h:174
#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 4556 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.

4557 {
4559 
4560  state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
4561 
4562  /* Should not get here with no state */
4563  if (state == NULL)
4564  elog(ERROR, "int8_accum_inv called with NULL state");
4565 
4566  if (!PG_ARGISNULL(1))
4567  {
4568  Numeric newval;
4569 
4571  PG_GETARG_DATUM(1)));
4572 
4573  /* Should never fail, all inputs have dscale 0 */
4574  if (!do_numeric_discard(state, newval))
4575  elog(ERROR, "do_numeric_discard failed unexpectedly");
4576  }
4577 
4578  PG_RETURN_POINTER(state);
4579 }
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:321
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:233
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:241
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:585
static bool do_numeric_discard(NumericAggState *state, Numeric newval)
Definition: numeric.c:3394
Datum int8_numeric(PG_FUNCTION_ARGS)
Definition: numeric.c:3038
#define ERROR
Definition: elog.h:43
#define PG_ARGISNULL(n)
Definition: fmgr.h:174
#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 5330 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.

5331 {
5332  ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
5333  Int8TransTypeData *transdata;
5334  Datum countd,
5335  sumd;
5336 
5337  if (ARR_HASNULL(transarray) ||
5338  ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
5339  elog(ERROR, "expected 2-element int8 array");
5340  transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
5341 
5342  /* SQL defines AVG of no values to be NULL */
5343  if (transdata->count == 0)
5344  PG_RETURN_NULL();
5345 
5347  Int64GetDatumFast(transdata->count));
5349  Int64GetDatumFast(transdata->sum));
5350 
5352 }
#define ARR_OVERHEAD_NONULLS(ndims)
Definition: array.h:295
#define ARR_SIZE(a)
Definition: array.h:274
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:585
Datum int8_numeric(PG_FUNCTION_ARGS)
Definition: numeric.c:3038
Datum numeric_div(PG_FUNCTION_ARGS)
Definition: numeric.c:2436
#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
uintptr_t Datum
Definition: postgres.h:372
#define PG_RETURN_DATUM(x)
Definition: fmgr.h:313
#define Int64GetDatumFast(X)
Definition: postgres.h:781
#define elog
Definition: elog.h:219
#define DirectFunctionCall2(func, arg1, arg2)
Definition: fmgr.h:587
#define PG_RETURN_NULL()
Definition: fmgr.h:305

◆ int8_avg_accum()

Datum int8_avg_accum ( PG_FUNCTION_ARGS  )

Definition at line 4299 of file numeric.c.

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

4300 {
4302 
4303  state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
4304 
4305  /* Create the state data on the first call */
4306  if (state == NULL)
4307  state = makePolyNumAggState(fcinfo, false);
4308 
4309  if (!PG_ARGISNULL(1))
4310  {
4311 #ifdef HAVE_INT128
4312  do_int128_accum(state, (int128) PG_GETARG_INT64(1));
4313 #else
4314  Numeric newval;
4315 
4317  PG_GETARG_DATUM(1)));
4318  do_numeric_accum(state, newval);
4319 #endif
4320  }
4321 
4322  PG_RETURN_POINTER(state);
4323 }
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:321
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:233
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:241
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:585
Datum int8_numeric(PG_FUNCTION_ARGS)
Definition: numeric.c:3038
static void do_numeric_accum(NumericAggState *state, Numeric newval)
Definition: numeric.c:3329
#define PG_ARGISNULL(n)
Definition: fmgr.h:174
#define DatumGetNumeric(X)
Definition: numeric.h:49
Definition: regguts.h:298
#define newval
#define PG_GETARG_INT64(n)
Definition: fmgr.h:247
#define makePolyNumAggState
Definition: numeric.c:4014

◆ int8_avg_accum_inv()

Datum int8_avg_accum_inv ( PG_FUNCTION_ARGS  )

Definition at line 4582 of file numeric.c.

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

4583 {
4585 
4586  state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
4587 
4588  /* Should not get here with no state */
4589  if (state == NULL)
4590  elog(ERROR, "int8_avg_accum_inv called with NULL state");
4591 
4592  if (!PG_ARGISNULL(1))
4593  {
4594 #ifdef HAVE_INT128
4595  do_int128_discard(state, (int128) PG_GETARG_INT64(1));
4596 #else
4597  Numeric newval;
4598 
4600  PG_GETARG_DATUM(1)));
4601 
4602  /* Should never fail, all inputs have dscale 0 */
4603  if (!do_numeric_discard(state, newval))
4604  elog(ERROR, "do_numeric_discard failed unexpectedly");
4605 #endif
4606  }
4607 
4608  PG_RETURN_POINTER(state);
4609 }
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:321
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:233
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:241
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:585
static bool do_numeric_discard(NumericAggState *state, Numeric newval)
Definition: numeric.c:3394
Datum int8_numeric(PG_FUNCTION_ARGS)