PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
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 (NumericVar *value, NumericVar *dest)
 
static char * get_str_from_var (NumericVar *var)
 
static char * get_str_from_var_sci (NumericVar *var, int rscale)
 
static Numeric make_result (NumericVar *var)
 
static void apply_typmod (NumericVar *var, int32 typmod)
 
static int32 numericvar_to_int32 (NumericVar *var)
 
static bool numericvar_to_int64 (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 (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 (NumericVar *var, NumericSortSupport *nss)
 
static int cmp_numerics (Numeric num1, Numeric num2)
 
static int cmp_var (NumericVar *var1, 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 (NumericVar *var1, NumericVar *var2, NumericVar *result)
 
static void sub_var (NumericVar *var1, NumericVar *var2, NumericVar *result)
 
static void mul_var (NumericVar *var1, NumericVar *var2, NumericVar *result, int rscale)
 
static void div_var (NumericVar *var1, NumericVar *var2, NumericVar *result, int rscale, bool round)
 
static void div_var_fast (NumericVar *var1, NumericVar *var2, NumericVar *result, int rscale, bool round)
 
static int select_div_scale (NumericVar *var1, NumericVar *var2)
 
static void mod_var (NumericVar *var1, NumericVar *var2, NumericVar *result)
 
static void ceil_var (NumericVar *var, NumericVar *result)
 
static void floor_var (NumericVar *var, NumericVar *result)
 
static void sqrt_var (NumericVar *arg, NumericVar *result, int rscale)
 
static void exp_var (NumericVar *arg, NumericVar *result, int rscale)
 
static int estimate_ln_dweight (NumericVar *var)
 
static void ln_var (NumericVar *arg, NumericVar *result, int rscale)
 
static void log_var (NumericVar *base, NumericVar *num, NumericVar *result)
 
static void power_var (NumericVar *base, NumericVar *exp, NumericVar *result)
 
static void power_var_int (NumericVar *base, int exp, NumericVar *result, int rscale)
 
static int cmp_abs (NumericVar *var1, 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 (NumericVar *var1, NumericVar *var2, NumericVar *result)
 
static void sub_abs (NumericVar *var1, 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, NumericVar *count_var, NumericVar *result_var)
 
static void accum_sum_add (NumericSumAccum *accum, NumericVar *var1)
 
static void accum_sum_rescale (NumericSumAccum *accum, 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 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 NumericDigit const_zero_data [1] = {0}
 
static NumericVar const_zero
 
static NumericDigit const_one_data [1] = {1}
 
static NumericVar const_one
 
static NumericDigit const_two_data [1] = {2}
 
static NumericVar const_two
 
static NumericDigit const_ten_data [1] = {10}
 
static NumericVar const_ten
 
static NumericDigit const_zero_point_five_data [1] = {5000}
 
static NumericVar const_zero_point_five
 
static NumericDigit const_zero_point_nine_data [1] = {9000}
 
static NumericVar const_zero_point_nine
 
static NumericDigit const_one_point_one_data [2] = {1, 1000}
 
static NumericVar const_one_point_one
 
static NumericVar const_nan
 
static const int round_powers [4] = {0, 1000, 100, 10}
 

Macro Definition Documentation

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

Definition at line 361 of file numeric.c.

Referenced by numeric_cmp_abbrev().

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

#define digitbuf_free (   buf)
Value:
do { \
if ((buf) != NULL) \
} while (0)
void pfree(void *pointer)
Definition: mcxt.c:992
static char * buf
Definition: pg_test_fsync.c:65
#define NULL
Definition: c.h:226

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

#define DIV_GUARD_DIGITS   4

Definition at line 97 of file numeric.c.

Referenced by div_var_fast().

#define dump_numeric (   s,
 
)

Definition at line 439 of file numeric.c.

Referenced by make_result().

#define dump_var (   s,
 
)

Definition at line 440 of file numeric.c.

#define HALF_NBASE   5000

Definition at line 94 of file numeric.c.

Referenced by div_var(), and round_var().

#define makePolyNumAggState   makeNumericAggState
#define makePolyNumAggStateCurrentContext   makeNumericAggStateCurrentContext

Definition at line 3933 of file numeric.c.

Referenced by int8_avg_deserialize(), and numeric_poly_deserialize().

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

Definition at line 96 of file numeric.c.

Referenced by mul_var().

#define NUMERIC_ABBREV_BITS   (SIZEOF_DATUM * BITS_PER_BYTE)

Definition at line 354 of file numeric.c.

#define NUMERIC_ABBREV_NAN   NumericAbbrevGetDatum(PG_INT32_MIN)

Definition at line 362 of file numeric.c.

Referenced by numeric_abbrev_convert().

#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:106
#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().

#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(), init_var_from_num(), make_result(), and set_var_from_num().

#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(), make_result(), numeric(), numeric_abs(), numeric_scale(), numeric_uminus(), and set_var_from_num().

#define NUMERIC_DSCALE_MASK   0x3FFF

Definition at line 204 of file numeric.c.

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

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

Definition at line 169 of file numeric.c.

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

Definition at line 173 of file numeric.c.

Referenced by make_result(), and numeric_maximum_size().

#define NUMERIC_HDRSZ_SHORT   (VARHDRSZ + sizeof(uint16))

Definition at line 174 of file numeric.c.

Referenced by make_result().

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

Definition at line 181 of file numeric.c.

#define NUMERIC_HEADER_SIZE (   n)
Value:
(VARHDRSZ + sizeof(uint16) + \
(NUMERIC_HEADER_IS_SHORT(n) ? 0 : sizeof(int16)))
signed short int16
Definition: c.h:252
#define NUMERIC_HEADER_IS_SHORT(n)
Definition: numeric.c:181
#define VARHDRSZ
Definition: c.h:441
unsigned short uint16
Definition: c.h:264

Definition at line 182 of file numeric.c.

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

#define NUMERIC_NAN   0xC000

Definition at line 167 of file numeric.c.

Referenced by free_var(), get_str_from_var(), main(), make_result(), numeric_recv(), and set_var_from_str().

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

Definition at line 166 of file numeric.c.

Referenced by make_result().

#define NUMERIC_SHORT_DSCALE_MASK   0x1F80

Definition at line 191 of file numeric.c.

Referenced by numeric().

#define NUMERIC_SHORT_DSCALE_MAX   (NUMERIC_SHORT_DSCALE_MASK >> NUMERIC_SHORT_DSCALE_SHIFT)

Definition at line 193 of file numeric.c.

#define NUMERIC_SHORT_DSCALE_SHIFT   7

Definition at line 192 of file numeric.c.

Referenced by make_result(), and numeric().

#define NUMERIC_SHORT_SIGN_MASK   0x2000

Definition at line 190 of file numeric.c.

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

#define NUMERIC_SHORT_WEIGHT_MASK   0x003F

Definition at line 196 of file numeric.c.

Referenced by make_result().

#define NUMERIC_SHORT_WEIGHT_MAX   NUMERIC_SHORT_WEIGHT_MASK

Definition at line 197 of file numeric.c.

#define NUMERIC_SHORT_WEIGHT_MIN   (-(NUMERIC_SHORT_WEIGHT_MASK+1))

Definition at line 198 of file numeric.c.

#define NUMERIC_SHORT_WEIGHT_SIGN_MASK   0x0040

Definition at line 195 of file numeric.c.

Referenced by make_result().

#define NUMERIC_SIGN (   n)
Value:
(((n)->choice.n_short.n_header & NUMERIC_SHORT_SIGN_MASK) ? \
#define NUMERIC_POS
Definition: numeric.c:164
#define NUMERIC_FLAGBITS(n)
Definition: numeric.c:169
#define NUMERIC_NEG
Definition: numeric.c:165
#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(), numeric(), numeric_sign(), numeric_uminus(), and set_var_from_num().

#define NUMERIC_SIGN_MASK   0xC000

Definition at line 163 of file numeric.c.

#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(), init_var_from_num(), make_result(), numeric(), and set_var_from_num().

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

Definition at line 360 of file numeric.c.

Typedef Documentation

Definition at line 99 of file numeric.c.

Definition at line 3931 of file numeric.c.

Function Documentation

static void accum_sum_add ( NumericSumAccum accum,
NumericVar var1 
)
static

Definition at line 8815 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(), and numeric_poly_deserialize().

8816 {
8817  int32 *accum_digits;
8818  int i,
8819  val_i;
8820  int val_ndigits;
8821  NumericDigit *val_digits;
8822 
8823  /*
8824  * If we have accumulated too many values since the last carry
8825  * propagation, do it now, to avoid overflowing. (We could allow more
8826  * than NBASE - 1, if we reserved two extra digits, rather than one, for
8827  * carry propagation. But even with NBASE - 1, this needs to be done so
8828  * seldom, that the performance difference is negligible.)
8829  */
8830  if (accum->num_uncarried == NBASE - 1)
8831  accum_sum_carry(accum);
8832 
8833  /*
8834  * Adjust the weight or scale of the old value, so that it can accommodate
8835  * the new value.
8836  */
8837  accum_sum_rescale(accum, val);
8838 
8839  /* */
8840  if (val->sign == NUMERIC_POS)
8841  accum_digits = accum->pos_digits;
8842  else
8843  accum_digits = accum->neg_digits;
8844 
8845  /* copy these values into local vars for speed in loop */
8846  val_ndigits = val->ndigits;
8847  val_digits = val->digits;
8848 
8849  i = accum->weight - val->weight;
8850  for (val_i = 0; val_i < val_ndigits; val_i++)
8851  {
8852  accum_digits[i] += (int32) val_digits[val_i];
8853  i++;
8854  }
8855 
8856  accum->num_uncarried++;
8857 }
static void accum_sum_rescale(NumericSumAccum *accum, NumericVar *val)
Definition: numeric.c:8936
#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:8863
signed int int32
Definition: c.h:253
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
static void accum_sum_carry ( NumericSumAccum accum)
static

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

8864 {
8865  int i;
8866  int ndigits;
8867  int32 *dig;
8868  int32 carry;
8869  int32 newdig = 0;
8870 
8871  /*
8872  * If no new values have been added since last carry propagation, nothing
8873  * to do.
8874  */
8875  if (accum->num_uncarried == 0)
8876  return;
8877 
8878  /*
8879  * We maintain that the weight of the accumulator is always one larger
8880  * than needed to hold the current value, before carrying, to make sure
8881  * there is enough space for the possible extra digit when carry is
8882  * propagated. We cannot expand the buffer here, unless we require
8883  * callers of accum_sum_final() to switch to the right memory context.
8884  */
8885  Assert(accum->pos_digits[0] == 0 && accum->neg_digits[0] == 0);
8886 
8887  ndigits = accum->ndigits;
8888 
8889  /* Propagate carry in the positive sum */
8890  dig = accum->pos_digits;
8891  carry = 0;
8892  for (i = ndigits - 1; i >= 0; i--)
8893  {
8894  newdig = dig[i] + carry;
8895  if (newdig >= NBASE)
8896  {
8897  carry = newdig / NBASE;
8898  newdig -= carry * NBASE;
8899  }
8900  else
8901  carry = 0;
8902  dig[i] = newdig;
8903  }
8904  /* Did we use up the digit reserved for carry propagation? */
8905  if (newdig > 0)
8906  accum->have_carry_space = false;
8907 
8908  /* And the same for the negative sum */
8909  dig = accum->neg_digits;
8910  carry = 0;
8911  for (i = ndigits - 1; i >= 0; i--)
8912  {
8913  newdig = dig[i] + carry;
8914  if (newdig >= NBASE)
8915  {
8916  carry = newdig / NBASE;
8917  newdig -= carry * NBASE;
8918  }
8919  else
8920  carry = 0;
8921  dig[i] = newdig;
8922  }
8923  if (newdig > 0)
8924  accum->have_carry_space = false;
8925 
8926  accum->num_uncarried = 0;
8927 }
int32 * neg_digits
Definition: numeric.c:344
int num_uncarried
Definition: numeric.c:341
signed int int32
Definition: c.h:253
bool have_carry_space
Definition: numeric.c:342
#define NBASE
Definition: numeric.c:93
#define Assert(condition)
Definition: c.h:671
int i
int32 * pos_digits
Definition: numeric.c:343
static void accum_sum_combine ( NumericSumAccum accum,
NumericSumAccum accum2 
)
static

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

9094 {
9095  NumericVar tmp_var;
9096 
9097  init_var(&tmp_var);
9098 
9099  accum_sum_final(accum2, &tmp_var);
9100  accum_sum_add(accum, &tmp_var);
9101 
9102  free_var(&tmp_var);
9103 }
static void accum_sum_final(NumericSumAccum *accum, NumericVar *result)
Definition: numeric.c:9025
static void free_var(NumericVar *var)
Definition: numeric.c:5404
static void accum_sum_add(NumericSumAccum *accum, NumericVar *var1)
Definition: numeric.c:8815
#define init_var(v)
Definition: numeric.c:451
static void accum_sum_copy ( NumericSumAccum dst,
NumericSumAccum src 
)
static

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

9077 {
9078  dst->pos_digits = palloc(src->ndigits * sizeof(int32));
9079  dst->neg_digits = palloc(src->ndigits * sizeof(int32));
9080 
9081  memcpy(dst->pos_digits, src->pos_digits, src->ndigits * sizeof(int32));
9082  memcpy(dst->neg_digits, src->neg_digits, src->ndigits * sizeof(int32));
9083  dst->num_uncarried = src->num_uncarried;
9084  dst->ndigits = src->ndigits;
9085  dst->weight = src->weight;
9086  dst->dscale = src->dscale;
9087 }
int32 * neg_digits
Definition: numeric.c:344
int num_uncarried
Definition: numeric.c:341
signed int int32
Definition: c.h:253
void * palloc(Size size)
Definition: mcxt.c:891
int32 * pos_digits
Definition: numeric.c:343
static void accum_sum_final ( NumericSumAccum accum,
NumericVar result 
)
static

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

9026 {
9027  int i;
9028  NumericVar pos_var;
9029  NumericVar neg_var;
9030 
9031  if (accum->ndigits == 0)
9032  {
9033  set_var_from_var(&const_zero, result);
9034  return;
9035  }
9036 
9037  /* Perform final carry */
9038  accum_sum_carry(accum);
9039 
9040  /* Create NumericVars representing the positive and negative sums */
9041  init_var(&pos_var);
9042  init_var(&neg_var);
9043 
9044  pos_var.ndigits = neg_var.ndigits = accum->ndigits;
9045  pos_var.weight = neg_var.weight = accum->weight;
9046  pos_var.dscale = neg_var.dscale = accum->dscale;
9047  pos_var.sign = NUMERIC_POS;
9048  neg_var.sign = NUMERIC_NEG;
9049 
9050  pos_var.buf = pos_var.digits = digitbuf_alloc(accum->ndigits);
9051  neg_var.buf = neg_var.digits = digitbuf_alloc(accum->ndigits);
9052 
9053  for (i = 0; i < accum->ndigits; i++)
9054  {
9055  Assert(accum->pos_digits[i] < NBASE);
9056  pos_var.digits[i] = (int16) accum->pos_digits[i];
9057 
9058  Assert(accum->neg_digits[i] < NBASE);
9059  neg_var.digits[i] = (int16) accum->neg_digits[i];
9060  }
9061 
9062  /* And add them together */
9063  add_var(&pos_var, &neg_var, result);
9064 
9065  /* Remove leading/trailing zeroes */
9066  strip_var(result);
9067 }
signed short int16
Definition: c.h:252
int weight
Definition: numeric.c:272
#define NUMERIC_POS
Definition: numeric.c:164
static void strip_var(NumericVar *var)
Definition: numeric.c:8758
int32 * neg_digits
Definition: numeric.c:344
#define digitbuf_alloc(ndigits)
Definition: numeric.c:443
static void add_var(NumericVar *var1, NumericVar *var2, NumericVar *result)
Definition: numeric.c:6435
int ndigits
Definition: numeric.c:271
static void accum_sum_carry(NumericSumAccum *accum)
Definition: numeric.c:8863
static void set_var_from_var(NumericVar *value, NumericVar *dest)
Definition: numeric.c:5654
int dscale
Definition: numeric.c:274
static NumericVar const_zero
Definition: numeric.c:371
#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
#define Assert(condition)
Definition: c.h:671
NumericDigit * digits
Definition: numeric.c:276
int i
int32 * pos_digits
Definition: numeric.c:343
#define init_var(v)
Definition: numeric.c:451
static void accum_sum_rescale ( NumericSumAccum accum,
NumericVar val 
)
static

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

8937 {
8938  int old_weight = accum->weight;
8939  int old_ndigits = accum->ndigits;
8940  int accum_ndigits;
8941  int accum_weight;
8942  int accum_rscale;
8943  int val_rscale;
8944 
8945  accum_weight = old_weight;
8946  accum_ndigits = old_ndigits;
8947 
8948  /*
8949  * Does the new value have a larger weight? If so, enlarge the buffers,
8950  * and shift the existing value to the new weight, by adding leading
8951  * zeros.
8952  *
8953  * We enforce that the accumulator always has a weight one larger than
8954  * needed for the inputs, so that we have space for an extra digit at the
8955  * final carry-propagation phase, if necessary.
8956  */
8957  if (val->weight >= accum_weight)
8958  {
8959  accum_weight = val->weight + 1;
8960  accum_ndigits = accum_ndigits + (accum_weight - old_weight);
8961  }
8962 
8963  /*
8964  * Even though the new value is small, we might've used up the space
8965  * reserved for the carry digit in the last call to accum_sum_carry(). If
8966  * so, enlarge to make room for another one.
8967  */
8968  else if (!accum->have_carry_space)
8969  {
8970  accum_weight++;
8971  accum_ndigits++;
8972  }
8973 
8974  /* Is the new value wider on the right side? */
8975  accum_rscale = accum_ndigits - accum_weight - 1;
8976  val_rscale = val->ndigits - val->weight - 1;
8977  if (val_rscale > accum_rscale)
8978  accum_ndigits = accum_ndigits + (val_rscale - accum_rscale);
8979 
8980  if (accum_ndigits != old_ndigits ||
8981  accum_weight != old_weight)
8982  {
8983  int32 *new_pos_digits;
8984  int32 *new_neg_digits;
8985  int weightdiff;
8986 
8987  weightdiff = accum_weight - old_weight;
8988 
8989  new_pos_digits = palloc0(accum_ndigits * sizeof(int32));
8990  new_neg_digits = palloc0(accum_ndigits * sizeof(int32));
8991 
8992  if (accum->pos_digits)
8993  {
8994  memcpy(&new_pos_digits[weightdiff], accum->pos_digits,
8995  old_ndigits * sizeof(int32));
8996  pfree(accum->pos_digits);
8997 
8998  memcpy(&new_neg_digits[weightdiff], accum->neg_digits,
8999  old_ndigits * sizeof(int32));
9000  pfree(accum->neg_digits);
9001  }
9002 
9003  accum->pos_digits = new_pos_digits;
9004  accum->neg_digits = new_neg_digits;
9005 
9006  accum->weight = accum_weight;
9007  accum->ndigits = accum_ndigits;
9008 
9009  Assert(accum->pos_digits[0] == 0 && accum->neg_digits[0] == 0);
9010  accum->have_carry_space = true;
9011  }
9012 
9013  if (val->dscale > accum->dscale)
9014  accum->dscale = val->dscale;
9015 }
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:253
void pfree(void *pointer)
Definition: mcxt.c:992
bool have_carry_space
Definition: numeric.c:342
void * palloc0(Size size)
Definition: mcxt.c:920
#define Assert(condition)
Definition: c.h:671
int32 * pos_digits
Definition: numeric.c:343
static void accum_sum_reset ( NumericSumAccum accum)
static

Definition at line 8799 of file numeric.c.

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

Referenced by do_numeric_discard().

8800 {
8801  int i;
8802 
8803  accum->dscale = 0;
8804  for (i = 0; i < accum->ndigits; i++)
8805  {
8806  accum->pos_digits[i] = 0;
8807  accum->neg_digits[i] = 0;
8808  }
8809 }
int32 * neg_digits
Definition: numeric.c:344
int i
int32 * pos_digits
Definition: numeric.c:343
static void add_abs ( NumericVar var1,
NumericVar var2,
NumericVar result 
)
static

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

8424 {
8425  NumericDigit *res_buf;
8426  NumericDigit *res_digits;
8427  int res_ndigits;
8428  int res_weight;
8429  int res_rscale,
8430  rscale1,
8431  rscale2;
8432  int res_dscale;
8433  int i,
8434  i1,
8435  i2;
8436  int carry = 0;
8437 
8438  /* copy these values into local vars for speed in inner loop */
8439  int var1ndigits = var1->ndigits;
8440  int var2ndigits = var2->ndigits;
8441  NumericDigit *var1digits = var1->digits;
8442  NumericDigit *var2digits = var2->digits;
8443 
8444  res_weight = Max(var1->weight, var2->weight) + 1;
8445 
8446  res_dscale = Max(var1->dscale, var2->dscale);
8447 
8448  /* Note: here we are figuring rscale in base-NBASE digits */
8449  rscale1 = var1->ndigits - var1->weight - 1;
8450  rscale2 = var2->ndigits - var2->weight - 1;
8451  res_rscale = Max(rscale1, rscale2);
8452 
8453  res_ndigits = res_rscale + res_weight + 1;
8454  if (res_ndigits <= 0)
8455  res_ndigits = 1;
8456 
8457  res_buf = digitbuf_alloc(res_ndigits + 1);
8458  res_buf[0] = 0; /* spare digit for later rounding */
8459  res_digits = res_buf + 1;
8460 
8461  i1 = res_rscale + var1->weight + 1;
8462  i2 = res_rscale + var2->weight + 1;
8463  for (i = res_ndigits - 1; i >= 0; i--)
8464  {
8465  i1--;
8466  i2--;
8467  if (i1 >= 0 && i1 < var1ndigits)
8468  carry += var1digits[i1];
8469  if (i2 >= 0 && i2 < var2ndigits)
8470  carry += var2digits[i2];
8471 
8472  if (carry >= NBASE)
8473  {
8474  res_digits[i] = carry - NBASE;
8475  carry = 1;
8476  }
8477  else
8478  {
8479  res_digits[i] = carry;
8480  carry = 0;
8481  }
8482  }
8483 
8484  Assert(carry == 0); /* else we failed to allow for carry out */
8485 
8486  digitbuf_free(result->buf);
8487  result->ndigits = res_ndigits;
8488  result->buf = res_buf;
8489  result->digits = res_digits;
8490  result->weight = res_weight;
8491  result->dscale = res_dscale;
8492 
8493  /* Remove leading/trailing zeroes */
8494  strip_var(result);
8495 }
int weight
Definition: numeric.c:272
static void strip_var(NumericVar *var)
Definition: numeric.c:8758
#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:671
NumericDigit * digits
Definition: numeric.c:276
int i
#define Max(x, y)
Definition: numeric.c:11
static void add_var ( NumericVar var1,
NumericVar var2,
NumericVar result 
)
static

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

6436 {
6437  /*
6438  * Decide on the signs of the two variables what to do
6439  */
6440  if (var1->sign == NUMERIC_POS)
6441  {
6442  if (var2->sign == NUMERIC_POS)
6443  {
6444  /*
6445  * Both are positive result = +(ABS(var1) + ABS(var2))
6446  */
6447  add_abs(var1, var2, result);
6448  result->sign = NUMERIC_POS;
6449  }
6450  else
6451  {
6452  /*
6453  * var1 is positive, var2 is negative Must compare absolute values
6454  */
6455  switch (cmp_abs(var1, var2))
6456  {
6457  case 0:
6458  /* ----------
6459  * ABS(var1) == ABS(var2)
6460  * result = ZERO
6461  * ----------
6462  */
6463  zero_var(result);
6464  result->dscale = Max(var1->dscale, var2->dscale);
6465  break;
6466 
6467  case 1:
6468  /* ----------
6469  * ABS(var1) > ABS(var2)
6470  * result = +(ABS(var1) - ABS(var2))
6471  * ----------
6472  */
6473  sub_abs(var1, var2, result);
6474  result->sign = NUMERIC_POS;
6475  break;
6476 
6477  case -1:
6478  /* ----------
6479  * ABS(var1) < ABS(var2)
6480  * result = -(ABS(var2) - ABS(var1))
6481  * ----------
6482  */
6483  sub_abs(var2, var1, result);
6484  result->sign = NUMERIC_NEG;
6485  break;
6486  }
6487  }
6488  }
6489  else
6490  {
6491  if (var2->sign == NUMERIC_POS)
6492  {
6493  /* ----------
6494  * var1 is negative, var2 is positive
6495  * Must compare absolute values
6496  * ----------
6497  */
6498  switch (cmp_abs(var1, var2))
6499  {
6500  case 0:
6501  /* ----------
6502  * ABS(var1) == ABS(var2)
6503  * result = ZERO
6504  * ----------
6505  */
6506  zero_var(result);
6507  result->dscale = Max(var1->dscale, var2->dscale);
6508  break;
6509 
6510  case 1:
6511  /* ----------
6512  * ABS(var1) > ABS(var2)
6513  * result = -(ABS(var1) - ABS(var2))
6514  * ----------
6515  */
6516  sub_abs(var1, var2, result);
6517  result->sign = NUMERIC_NEG;
6518  break;
6519 
6520  case -1:
6521  /* ----------
6522  * ABS(var1) < ABS(var2)
6523  * result = +(ABS(var2) - ABS(var1))
6524  * ----------
6525  */
6526  sub_abs(var2, var1, result);
6527  result->sign = NUMERIC_POS;
6528  break;
6529  }
6530  }
6531  else
6532  {
6533  /* ----------
6534  * Both are negative
6535  * result = -(ABS(var1) + ABS(var2))
6536  * ----------
6537  */
6538  add_abs(var1, var2, result);
6539  result->sign = NUMERIC_NEG;
6540  }
6541  }
6542 }
#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:5420
static void sub_abs(NumericVar *var1, NumericVar *var2, NumericVar *result)
Definition: numeric.c:8508
static int cmp_abs(NumericVar *var1, NumericVar *var2)
Definition: numeric.c:8345
static void add_abs(NumericVar *var1, NumericVar *var2, NumericVar *result)
Definition: numeric.c:8423
#define Max(x, y)
Definition: numeric.c:11
static void alloc_var ( NumericVar var,
int  ndigits 
)
static

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

5389 {
5390  digitbuf_free(var->buf);
5391  var->buf = digitbuf_alloc(ndigits + 1);
5392  var->buf[0] = 0; /* spare digit for rounding */
5393  var->digits = var->buf + 1;
5394  var->ndigits = ndigits;
5395 }
#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
static void apply_typmod ( NumericVar var,
int32  typmod 
)
static

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

6007 {
6008  int precision;
6009  int scale;
6010  int maxdigits;
6011  int ddigits;
6012  int i;
6013 
6014  /* Do nothing if we have a default typmod (-1) */
6015  if (typmod < (int32) (VARHDRSZ))
6016  return;
6017 
6018  typmod -= VARHDRSZ;
6019  precision = (typmod >> 16) & 0xffff;
6020  scale = typmod & 0xffff;
6021  maxdigits = precision - scale;
6022 
6023  /* Round to target scale (and set var->dscale) */
6024  round_var(var, scale);
6025 
6026  /*
6027  * Check for overflow - note we can't do this before rounding, because
6028  * rounding could raise the weight. Also note that the var's weight could
6029  * be inflated by leading zeroes, which will be stripped before storage
6030  * but perhaps might not have been yet. In any case, we must recognize a
6031  * true zero, whose weight doesn't mean anything.
6032  */
6033  ddigits = (var->weight + 1) * DEC_DIGITS;
6034  if (ddigits > maxdigits)
6035  {
6036  /* Determine true weight; and check for all-zero result */
6037  for (i = 0; i < var->ndigits; i++)
6038  {
6039  NumericDigit dig = var->digits[i];
6040 
6041  if (dig)
6042  {
6043  /* Adjust for any high-order decimal zero digits */
6044 #if DEC_DIGITS == 4
6045  if (dig < 10)
6046  ddigits -= 3;
6047  else if (dig < 100)
6048  ddigits -= 2;
6049  else if (dig < 1000)
6050  ddigits -= 1;
6051 #elif DEC_DIGITS == 2
6052  if (dig < 10)
6053  ddigits -= 1;
6054 #elif DEC_DIGITS == 1
6055  /* no adjustment */
6056 #else
6057 #error unsupported NBASE
6058 #endif
6059  if (ddigits > maxdigits)
6060  ereport(ERROR,
6061  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
6062  errmsg("numeric field overflow"),
6063  errdetail("A field with precision %d, scale %d must round to an absolute value less than %s%d.",
6064  precision, scale,
6065  /* Display 10^0 as 1 */
6066  maxdigits ? "10^" : "",
6067  maxdigits ? maxdigits : 1
6068  )));
6069  break;
6070  }
6071  ddigits -= DEC_DIGITS;
6072  }
6073  }
6074 }
static void round_var(NumericVar *var, int rscale)
Definition: numeric.c:8590
int weight
Definition: numeric.c:272
#define VARHDRSZ
Definition: c.h:441
int errcode(int sqlerrcode)
Definition: elog.c:575
int scale
Definition: pgbench.c:106
int ndigits
Definition: numeric.c:271
signed int int32
Definition: c.h:253
#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
static void ceil_var ( NumericVar var,
NumericVar result 
)
static

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

7549 {
7550  NumericVar tmp;
7551 
7552  init_var(&tmp);
7553  set_var_from_var(var, &tmp);
7554 
7555  trunc_var(&tmp, 0);
7556 
7557  if (var->sign == NUMERIC_POS && cmp_var(var, &tmp) != 0)
7558  add_var(&tmp, &const_one, &tmp);
7559 
7560  set_var_from_var(&tmp, result);
7561  free_var(&tmp);
7562 }
static void trunc_var(NumericVar *var, int rscale)
Definition: numeric.c:8696
static int cmp_var(NumericVar *var1, NumericVar *var2)
Definition: numeric.c:6377
static NumericVar const_one
Definition: numeric.c:375
#define NUMERIC_POS
Definition: numeric.c:164
static void add_var(NumericVar *var1, NumericVar *var2, NumericVar *result)
Definition: numeric.c:6435
static void set_var_from_var(NumericVar *value, NumericVar *dest)
Definition: numeric.c:5654
int sign
Definition: numeric.c:273
static void free_var(NumericVar *var)
Definition: numeric.c:5404
#define init_var(v)
Definition: numeric.c:451
static int cmp_abs ( NumericVar var1,
NumericVar var2 
)
static

Definition at line 8345 of file numeric.c.

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

Referenced by add_var(), and sub_var().

8346 {
8347  return cmp_abs_common(var1->digits, var1->ndigits, var1->weight,
8348  var2->digits, var2->ndigits, var2->weight);
8349 }
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:8359
static int cmp_abs_common ( const NumericDigit var1digits,
int  var1ndigits,
int  var1weight,
const NumericDigit var2digits,
int  var2ndigits,
int  var2weight 
)
static

Definition at line 8359 of file numeric.c.

Referenced by cmp_abs(), and cmp_var_common().

8361 {
8362  int i1 = 0;
8363  int i2 = 0;
8364 
8365  /* Check any digits before the first common digit */
8366 
8367  while (var1weight > var2weight && i1 < var1ndigits)
8368  {
8369  if (var1digits[i1++] != 0)
8370  return 1;
8371  var1weight--;
8372  }
8373  while (var2weight > var1weight && i2 < var2ndigits)
8374  {
8375  if (var2digits[i2++] != 0)
8376  return -1;
8377  var2weight--;
8378  }
8379 
8380  /* At this point, either w1 == w2 or we've run out of digits */
8381 
8382  if (var1weight == var2weight)
8383  {
8384  while (i1 < var1ndigits && i2 < var2ndigits)
8385  {
8386  int stat = var1digits[i1++] - var2digits[i2++];
8387 
8388  if (stat)
8389  {
8390  if (stat > 0)
8391  return 1;
8392  return -1;
8393  }
8394  }
8395  }
8396 
8397  /*
8398  * At this point, we've run out of digits on one side or the other; so any
8399  * remaining nonzero digits imply that side is larger
8400  */
8401  while (i1 < var1ndigits)
8402  {
8403  if (var1digits[i1++] != 0)
8404  return 1;
8405  }
8406  while (i2 < var2ndigits)
8407  {
8408  if (var2digits[i2++] != 0)
8409  return -1;
8410  }
8411 
8412  return 0;
8413 }
static int cmp_numerics ( Numeric  num1,
Numeric  num2 
)
static

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

2127 {
2128  int result;
2129 
2130  /*
2131  * We consider all NANs to be equal and larger than any non-NAN. This is
2132  * somewhat arbitrary; the important thing is to have a consistent sort
2133  * order.
2134  */
2135  if (NUMERIC_IS_NAN(num1))
2136  {
2137  if (NUMERIC_IS_NAN(num2))
2138  result = 0; /* NAN = NAN */
2139  else
2140  result = 1; /* NAN > non-NAN */
2141  }
2142  else if (NUMERIC_IS_NAN(num2))
2143  {
2144  result = -1; /* non-NAN < NAN */
2145  }
2146  else
2147  {
2148  result = cmp_var_common(NUMERIC_DIGITS(num1), NUMERIC_NDIGITS(num1),
2149  NUMERIC_WEIGHT(num1), NUMERIC_SIGN(num1),
2150  NUMERIC_DIGITS(num2), NUMERIC_NDIGITS(num2),
2151  NUMERIC_WEIGHT(num2), NUMERIC_SIGN(num2));
2152  }
2153 
2154  return result;
2155 }
#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:6392
#define NUMERIC_WEIGHT(n)
Definition: numeric.c:214
#define NUMERIC_IS_NAN(n)
Definition: numeric.c:170
static int cmp_var ( NumericVar var1,
NumericVar var2 
)
static

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

6378 {
6379  return cmp_var_common(var1->digits, var1->ndigits,
6380  var1->weight, var1->sign,
6381  var2->digits, var2->ndigits,
6382  var2->weight, var2->sign);
6383 }
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:6392
NumericDigit * digits
Definition: numeric.c:276
static int cmp_var_common ( const NumericDigit var1digits,
int  var1ndigits,
int  var1weight,
int  var1sign,
const NumericDigit var2digits,
int  var2ndigits,
int  var2weight,
int  var2sign 
)
static

Definition at line 6392 of file numeric.c.

References cmp_abs_common(), NUMERIC_NEG, and NUMERIC_POS.

Referenced by cmp_numerics(), and cmp_var().

6396 {
6397  if (var1ndigits == 0)
6398  {
6399  if (var2ndigits == 0)
6400  return 0;
6401  if (var2sign == NUMERIC_NEG)
6402  return 1;
6403  return -1;
6404  }
6405  if (var2ndigits == 0)
6406  {
6407  if (var1sign == NUMERIC_POS)
6408  return 1;
6409  return -1;
6410  }
6411 
6412  if (var1sign == NUMERIC_POS)
6413  {
6414  if (var2sign == NUMERIC_NEG)
6415  return 1;
6416  return cmp_abs_common(var1digits, var1ndigits, var1weight,
6417  var2digits, var2ndigits, var2weight);
6418  }
6419 
6420  if (var2sign == NUMERIC_POS)
6421  return -1;
6422 
6423  return cmp_abs_common(var2digits, var2ndigits, var2weight,
6424  var1digits, var1ndigits, var1weight);
6425 }
#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:8359
static void compute_bucket ( Numeric  operand,
Numeric  bound1,
Numeric  bound2,
NumericVar count_var,
NumericVar result_var 
)
static

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

1555 {
1556  NumericVar bound1_var;
1557  NumericVar bound2_var;
1558  NumericVar operand_var;
1559 
1560  init_var_from_num(bound1, &bound1_var);
1561  init_var_from_num(bound2, &bound2_var);
1562  init_var_from_num(operand, &operand_var);
1563 
1564  if (cmp_var(&bound1_var, &bound2_var) < 0)
1565  {
1566  sub_var(&operand_var, &bound1_var, &operand_var);
1567  sub_var(&bound2_var, &bound1_var, &bound2_var);
1568  div_var(&operand_var, &bound2_var, result_var,
1569  select_div_scale(&operand_var, &bound2_var), true);
1570  }
1571  else
1572  {
1573  sub_var(&bound1_var, &operand_var, &operand_var);
1574  sub_var(&bound1_var, &bound2_var, &bound1_var);
1575  div_var(&operand_var, &bound1_var, result_var,
1576  select_div_scale(&operand_var, &bound1_var), true);
1577  }
1578 
1579  mul_var(result_var, count_var, result_var,
1580  result_var->dscale + count_var->dscale);
1581  add_var(result_var, &const_one, result_var);
1582  floor_var(result_var, result_var);
1583 
1584  free_var(&bound1_var);
1585  free_var(&bound2_var);
1586  free_var(&operand_var);
1587 }
static int cmp_var(NumericVar *var1, NumericVar *var2)
Definition: numeric.c:6377
static NumericVar const_one
Definition: numeric.c:375
static int select_div_scale(NumericVar *var1, NumericVar *var2)
Definition: numeric.c:7450
static void add_var(NumericVar *var1, NumericVar *var2, NumericVar *result)
Definition: numeric.c:6435
static void div_var(NumericVar *var1, NumericVar *var2, NumericVar *result, int rscale, bool round)
Definition: numeric.c:6870
int dscale
Definition: numeric.c:274
static void init_var_from_num(Numeric num, NumericVar *dest)
Definition: numeric.c:5637
static void floor_var(NumericVar *var, NumericVar *result)
Definition: numeric.c:7572
static void mul_var(NumericVar *var1, NumericVar *var2, NumericVar *result, int rscale)
Definition: numeric.c:6673
static void free_var(NumericVar *var)
Definition: numeric.c:5404
static void sub_var(NumericVar *var1, NumericVar *var2, NumericVar *result)
Definition: numeric.c:6552
static void div_var ( NumericVar var1,
NumericVar var2,
NumericVar result,
int  rscale,
bool  round 
)
static

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

6872 {
6873  int div_ndigits;
6874  int res_ndigits;
6875  int res_sign;
6876  int res_weight;
6877  int carry;
6878  int borrow;
6879  int divisor1;
6880  int divisor2;
6881  NumericDigit *dividend;
6882  NumericDigit *divisor;
6883  NumericDigit *res_digits;
6884  int i;
6885  int j;
6886 
6887  /* copy these values into local vars for speed in inner loop */
6888  int var1ndigits = var1->ndigits;
6889  int var2ndigits = var2->ndigits;
6890 
6891  /*
6892  * First of all division by zero check; we must not be handed an
6893  * unnormalized divisor.
6894  */
6895  if (var2ndigits == 0 || var2->digits[0] == 0)
6896  ereport(ERROR,
6897  (errcode(ERRCODE_DIVISION_BY_ZERO),
6898  errmsg("division by zero")));
6899 
6900  /*
6901  * Now result zero check
6902  */
6903  if (var1ndigits == 0)
6904  {
6905  zero_var(result);
6906  result->dscale = rscale;
6907  return;
6908  }
6909 
6910  /*
6911  * Determine the result sign, weight and number of digits to calculate.
6912  * The weight figured here is correct if the emitted quotient has no
6913  * leading zero digits; otherwise strip_var() will fix things up.
6914  */
6915  if (var1->sign == var2->sign)
6916  res_sign = NUMERIC_POS;
6917  else
6918  res_sign = NUMERIC_NEG;
6919  res_weight = var1->weight - var2->weight;
6920  /* The number of accurate result digits we need to produce: */
6921  res_ndigits = res_weight + 1 + (rscale + DEC_DIGITS - 1) / DEC_DIGITS;
6922  /* ... but always at least 1 */
6923  res_ndigits = Max(res_ndigits, 1);
6924  /* If rounding needed, figure one more digit to ensure correct result */
6925  if (round)
6926  res_ndigits++;
6927 
6928  /*
6929  * The working dividend normally requires res_ndigits + var2ndigits
6930  * digits, but make it at least var1ndigits so we can load all of var1
6931  * into it. (There will be an additional digit dividend[0] in the
6932  * dividend space, but for consistency with Knuth's notation we don't
6933  * count that in div_ndigits.)
6934  */
6935  div_ndigits = res_ndigits + var2ndigits;
6936  div_ndigits = Max(div_ndigits, var1ndigits);
6937 
6938  /*
6939  * We need a workspace with room for the working dividend (div_ndigits+1
6940  * digits) plus room for the possibly-normalized divisor (var2ndigits
6941  * digits). It is convenient also to have a zero at divisor[0] with the
6942  * actual divisor data in divisor[1 .. var2ndigits]. Transferring the
6943  * digits into the workspace also allows us to realloc the result (which
6944  * might be the same as either input var) before we begin the main loop.
6945  * Note that we use palloc0 to ensure that divisor[0], dividend[0], and
6946  * any additional dividend positions beyond var1ndigits, start out 0.
6947  */
6948  dividend = (NumericDigit *)
6949  palloc0((div_ndigits + var2ndigits + 2) * sizeof(NumericDigit));
6950  divisor = dividend + (div_ndigits + 1);
6951  memcpy(dividend + 1, var1->digits, var1ndigits * sizeof(NumericDigit));
6952  memcpy(divisor + 1, var2->digits, var2ndigits * sizeof(NumericDigit));
6953 
6954  /*
6955  * Now we can realloc the result to hold the generated quotient digits.
6956  */
6957  alloc_var(result, res_ndigits);
6958  res_digits = result->digits;
6959 
6960  if (var2ndigits == 1)
6961  {
6962  /*
6963  * If there's only a single divisor digit, we can use a fast path (cf.
6964  * Knuth section 4.3.1 exercise 16).
6965  */
6966  divisor1 = divisor[1];
6967  carry = 0;
6968  for (i = 0; i < res_ndigits; i++)
6969  {
6970  carry = carry * NBASE + dividend[i + 1];
6971  res_digits[i] = carry / divisor1;
6972  carry = carry % divisor1;
6973  }
6974  }
6975  else
6976  {
6977  /*
6978  * The full multiple-place algorithm is taken from Knuth volume 2,
6979  * Algorithm 4.3.1D.
6980  *
6981  * We need the first divisor digit to be >= NBASE/2. If it isn't,
6982  * make it so by scaling up both the divisor and dividend by the
6983  * factor "d". (The reason for allocating dividend[0] above is to
6984  * leave room for possible carry here.)
6985  */
6986  if (divisor[1] < HALF_NBASE)
6987  {
6988  int d = NBASE / (divisor[1] + 1);
6989 
6990  carry = 0;
6991  for (i = var2ndigits; i > 0; i--)
6992  {
6993  carry += divisor[i] * d;
6994  divisor[i] = carry % NBASE;
6995  carry = carry / NBASE;
6996  }
6997  Assert(carry == 0);
6998  carry = 0;
6999  /* at this point only var1ndigits of dividend can be nonzero */
7000  for (i = var1ndigits; i >= 0; i--)
7001  {
7002  carry += dividend[i] * d;
7003  dividend[i] = carry % NBASE;
7004  carry = carry / NBASE;
7005  }
7006  Assert(carry == 0);
7007  Assert(divisor[1] >= HALF_NBASE);
7008  }
7009  /* First 2 divisor digits are used repeatedly in main loop */
7010  divisor1 = divisor[1];
7011  divisor2 = divisor[2];
7012 
7013  /*
7014  * Begin the main loop. Each iteration of this loop produces the j'th
7015  * quotient digit by dividing dividend[j .. j + var2ndigits] by the
7016  * divisor; this is essentially the same as the common manual
7017  * procedure for long division.
7018  */
7019  for (j = 0; j < res_ndigits; j++)
7020  {
7021  /* Estimate quotient digit from the first two dividend digits */
7022  int next2digits = dividend[j] * NBASE + dividend[j + 1];
7023  int qhat;
7024 
7025  /*
7026  * If next2digits are 0, then quotient digit must be 0 and there's
7027  * no need to adjust the working dividend. It's worth testing
7028  * here to fall out ASAP when processing trailing zeroes in a
7029  * dividend.
7030  */
7031  if (next2digits == 0)
7032  {
7033  res_digits[j] = 0;
7034  continue;
7035  }
7036 
7037  if (dividend[j] == divisor1)
7038  qhat = NBASE - 1;
7039  else
7040  qhat = next2digits / divisor1;
7041 
7042  /*
7043  * Adjust quotient digit if it's too large. Knuth proves that
7044  * after this step, the quotient digit will be either correct or
7045  * just one too large. (Note: it's OK to use dividend[j+2] here
7046  * because we know the divisor length is at least 2.)
7047  */
7048  while (divisor2 * qhat >
7049  (next2digits - qhat * divisor1) * NBASE + dividend[j + 2])
7050  qhat--;
7051 
7052  /* As above, need do nothing more when quotient digit is 0 */
7053  if (qhat > 0)
7054  {
7055  /*
7056  * Multiply the divisor by qhat, and subtract that from the
7057  * working dividend. "carry" tracks the multiplication,
7058  * "borrow" the subtraction (could we fold these together?)
7059  */
7060  carry = 0;
7061  borrow = 0;
7062  for (i = var2ndigits; i >= 0; i--)
7063  {
7064  carry += divisor[i] * qhat;
7065  borrow -= carry % NBASE;
7066  carry = carry / NBASE;
7067  borrow += dividend[j + i];
7068  if (borrow < 0)
7069  {
7070  dividend[j + i] = borrow + NBASE;
7071  borrow = -1;
7072  }
7073  else
7074  {
7075  dividend[j + i] = borrow;
7076  borrow = 0;
7077  }
7078  }
7079  Assert(carry == 0);
7080 
7081  /*
7082  * If we got a borrow out of the top dividend digit, then
7083  * indeed qhat was one too large. Fix it, and add back the
7084  * divisor to correct the working dividend. (Knuth proves
7085  * that this will occur only about 3/NBASE of the time; hence,
7086  * it's a good idea to test this code with small NBASE to be
7087  * sure this section gets exercised.)
7088  */
7089  if (borrow)
7090  {
7091  qhat--;
7092  carry = 0;
7093  for (i = var2ndigits; i >= 0; i--)
7094  {
7095  carry += dividend[j + i] + divisor[i];
7096  if (carry >= NBASE)
7097  {
7098  dividend[j + i] = carry - NBASE;
7099  carry = 1;
7100  }
7101  else
7102  {
7103  dividend[j + i] = carry;
7104  carry = 0;
7105  }
7106  }
7107  /* A carry should occur here to cancel the borrow above */
7108  Assert(carry == 1);
7109  }
7110  }
7111 
7112  /* And we're done with this quotient digit */
7113  res_digits[j] = qhat;
7114  }
7115  }
7116 
7117  pfree(dividend);
7118 
7119  /*
7120  * Finally, round or truncate the result to the requested precision.
7121  */
7122  result->weight = res_weight;
7123  result->sign = res_sign;
7124 
7125  /* Round or truncate to target rscale (and set result->dscale) */
7126  if (round)
7127  round_var(result, rscale);
7128  else
7129  trunc_var(result, rscale);
7130 
7131  /* Strip leading and trailing zeroes */
7132  strip_var(result);
7133 }
static void round_var(NumericVar *var, int rscale)
Definition: numeric.c:8590
static void trunc_var(NumericVar *var, int rscale)
Definition: numeric.c:8696
int weight
Definition: numeric.c:272
#define NUMERIC_POS
Definition: numeric.c:164
static void strip_var(NumericVar *var)
Definition: numeric.c:8758
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:5420
void pfree(void *pointer)
Definition: mcxt.c:992
#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:920
#define Assert(condition)
Definition: c.h:671
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:5388
int i
#define Max(x, y)
Definition: numeric.c:11
#define DEC_DIGITS
Definition: numeric.c:95
static void div_var_fast ( NumericVar var1,
NumericVar var2,
NumericVar result,
int  rscale,
bool  round 
)
static

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

7157 {
7158  int div_ndigits;
7159  int res_sign;
7160  int res_weight;
7161  int *div;
7162  int qdigit;
7163  int carry;
7164  int maxdiv;
7165  int newdig;
7166  NumericDigit *res_digits;
7167  double fdividend,
7168  fdivisor,
7169  fdivisorinverse,
7170  fquotient;
7171  int qi;
7172  int i;
7173 
7174  /* copy these values into local vars for speed in inner loop */
7175  int var1ndigits = var1->ndigits;
7176  int var2ndigits = var2->ndigits;
7177  NumericDigit *var1digits = var1->digits;
7178  NumericDigit *var2digits = var2->digits;
7179 
7180  /*
7181  * First of all division by zero check; we must not be handed an
7182  * unnormalized divisor.
7183  */
7184  if (var2ndigits == 0 || var2digits[0] == 0)
7185  ereport(ERROR,
7186  (errcode(ERRCODE_DIVISION_BY_ZERO),
7187  errmsg("division by zero")));
7188 
7189  /*
7190  * Now result zero check
7191  */
7192  if (var1ndigits == 0)
7193  {
7194  zero_var(result);
7195  result->dscale = rscale;
7196  return;
7197  }
7198 
7199  /*
7200  * Determine the result sign, weight and number of digits to calculate
7201  */
7202  if (var1->sign == var2->sign)
7203  res_sign = NUMERIC_POS;
7204  else
7205  res_sign = NUMERIC_NEG;
7206  res_weight = var1->weight - var2->weight + 1;
7207  /* The number of accurate result digits we need to produce: */
7208  div_ndigits = res_weight + 1 + (rscale + DEC_DIGITS - 1) / DEC_DIGITS;
7209  /* Add guard digits for roundoff error */
7210  div_ndigits += DIV_GUARD_DIGITS;
7211  if (div_ndigits < DIV_GUARD_DIGITS)
7212  div_ndigits = DIV_GUARD_DIGITS;
7213  /* Must be at least var1ndigits, too, to simplify data-loading loop */
7214  if (div_ndigits < var1ndigits)
7215  div_ndigits = var1ndigits;
7216 
7217  /*
7218  * We do the arithmetic in an array "div[]" of signed int's. Since
7219  * INT_MAX is noticeably larger than NBASE*NBASE, this gives us headroom
7220  * to avoid normalizing carries immediately.
7221  *
7222  * We start with div[] containing one zero digit followed by the
7223  * dividend's digits (plus appended zeroes to reach the desired precision
7224  * including guard digits). Each step of the main loop computes an
7225  * (approximate) quotient digit and stores it into div[], removing one
7226  * position of dividend space. A final pass of carry propagation takes
7227  * care of any mistaken quotient digits.
7228  */
7229  div = (int *) palloc0((div_ndigits + 1) * sizeof(int));
7230  for (i = 0; i < var1ndigits; i++)
7231  div[i + 1] = var1digits[i];
7232 
7233  /*
7234  * We estimate each quotient digit using floating-point arithmetic, taking
7235  * the first four digits of the (current) dividend and divisor. This must
7236  * be float to avoid overflow. The quotient digits will generally be off
7237  * by no more than one from the exact answer.
7238  */
7239  fdivisor = (double) var2digits[0];
7240  for (i = 1; i < 4; i++)
7241  {
7242  fdivisor *= NBASE;
7243  if (i < var2ndigits)
7244  fdivisor += (double) var2digits[i];
7245  }
7246  fdivisorinverse = 1.0 / fdivisor;
7247 
7248  /*
7249  * maxdiv tracks the maximum possible absolute value of any div[] entry;
7250  * when this threatens to exceed INT_MAX, we take the time to propagate
7251  * carries. Furthermore, we need to ensure that overflow doesn't occur
7252  * during the carry propagation passes either. The carry values may have
7253  * an absolute value as high as INT_MAX/NBASE + 1, so really we must
7254  * normalize when digits threaten to exceed INT_MAX - INT_MAX/NBASE - 1.
7255  *
7256  * To avoid overflow in maxdiv itself, it represents the max absolute
7257  * value divided by NBASE-1, ie, at the top of the loop it is known that
7258  * no div[] entry has an absolute value exceeding maxdiv * (NBASE-1).
7259  *
7260  * Actually, though, that holds good only for div[] entries after div[qi];
7261  * the adjustment done at the bottom of the loop may cause div[qi + 1] to
7262  * exceed the maxdiv limit, so that div[qi] in the next iteration is
7263  * beyond the limit. This does not cause problems, as explained below.
7264  */
7265  maxdiv = 1;
7266 
7267  /*
7268  * Outer loop computes next quotient digit, which will go into div[qi]
7269  */
7270  for (qi = 0; qi < div_ndigits; qi++)
7271  {
7272  /* Approximate the current dividend value */
7273  fdividend = (double) div[qi];
7274  for (i = 1; i < 4; i++)
7275  {
7276  fdividend *= NBASE;
7277  if (qi + i <= div_ndigits)
7278  fdividend += (double) div[qi + i];
7279  }
7280  /* Compute the (approximate) quotient digit */
7281  fquotient = fdividend * fdivisorinverse;
7282  qdigit = (fquotient >= 0.0) ? ((int) fquotient) :
7283  (((int) fquotient) - 1); /* truncate towards -infinity */
7284 
7285  if (qdigit != 0)
7286  {
7287  /* Do we need to normalize now? */
7288  maxdiv += Abs(qdigit);
7289  if (maxdiv > (INT_MAX - INT_MAX / NBASE - 1) / (NBASE - 1))
7290  {
7291  /* Yes, do it */
7292  carry = 0;
7293  for (i = div_ndigits; i > qi; i--)
7294  {
7295  newdig = div[i] + carry;
7296  if (newdig < 0)
7297  {
7298  carry = -((-newdig - 1) / NBASE) - 1;
7299  newdig -= carry * NBASE;
7300  }
7301  else if (newdig >= NBASE)
7302  {
7303  carry = newdig / NBASE;
7304  newdig -= carry * NBASE;
7305  }
7306  else
7307  carry = 0;
7308  div[i] = newdig;
7309  }
7310  newdig = div[qi] + carry;
7311  div[qi] = newdig;
7312 
7313  /*
7314  * All the div[] digits except possibly div[qi] are now in the
7315  * range 0..NBASE-1. We do not need to consider div[qi] in
7316  * the maxdiv value anymore, so we can reset maxdiv to 1.
7317  */
7318  maxdiv = 1;
7319 
7320  /*
7321  * Recompute the quotient digit since new info may have
7322  * propagated into the top four dividend digits
7323  */
7324  fdividend = (double) div[qi];
7325  for (i = 1; i < 4; i++)
7326  {
7327  fdividend *= NBASE;
7328  if (qi + i <= div_ndigits)
7329  fdividend += (double) div[qi + i];
7330  }
7331  /* Compute the (approximate) quotient digit */
7332  fquotient = fdividend * fdivisorinverse;
7333  qdigit = (fquotient >= 0.0) ? ((int) fquotient) :
7334  (((int) fquotient) - 1); /* truncate towards -infinity */
7335  maxdiv += Abs(qdigit);
7336  }
7337 
7338  /*
7339  * Subtract off the appropriate multiple of the divisor.
7340  *
7341  * The digits beyond div[qi] cannot overflow, because we know they
7342  * will fall within the maxdiv limit. As for div[qi] itself, note
7343  * that qdigit is approximately trunc(div[qi] / vardigits[0]),
7344  * which would make the new value simply div[qi] mod vardigits[0].
7345  * The lower-order terms in qdigit can change this result by not
7346  * more than about twice INT_MAX/NBASE, so overflow is impossible.
7347  */
7348  if (qdigit != 0)
7349  {
7350  int istop = Min(var2ndigits, div_ndigits - qi + 1);
7351 
7352  for (i = 0; i < istop; i++)
7353  div[qi + i] -= qdigit * var2digits[i];
7354  }
7355  }
7356 
7357  /*
7358  * The dividend digit we are about to replace might still be nonzero.
7359  * Fold it into the next digit position.
7360  *
7361  * There is no risk of overflow here, although proving that requires
7362  * some care. Much as with the argument for div[qi] not overflowing,
7363  * if we consider the first two terms in the numerator and denominator
7364  * of qdigit, we can see that the final value of div[qi + 1] will be
7365  * approximately a remainder mod (vardigits[0]*NBASE + vardigits[1]).
7366  * Accounting for the lower-order terms is a bit complicated but ends
7367  * up adding not much more than INT_MAX/NBASE to the possible range.
7368  * Thus, div[qi + 1] cannot overflow here, and in its role as div[qi]
7369  * in the next loop iteration, it can't be large enough to cause
7370  * overflow in the carry propagation step (if any), either.
7371  *
7372  * But having said that: div[qi] can be more than INT_MAX/NBASE, as
7373  * noted above, which means that the product div[qi] * NBASE *can*
7374  * overflow. When that happens, adding it to div[qi + 1] will always
7375  * cause a canceling overflow so that the end result is correct. We
7376  * could avoid the intermediate overflow by doing the multiplication
7377  * and addition in int64 arithmetic, but so far there appears no need.
7378  */
7379  div[qi + 1] += div[qi] * NBASE;
7380 
7381  div[qi] = qdigit;
7382  }
7383 
7384  /*
7385  * Approximate and store the last quotient digit (div[div_ndigits])
7386  */
7387  fdividend = (double) div[qi];
7388  for (i = 1; i < 4; i++)
7389  fdividend *= NBASE;
7390  fquotient = fdividend * fdivisorinverse;
7391  qdigit = (fquotient >= 0.0) ? ((int) fquotient) :
7392  (((int) fquotient) - 1); /* truncate towards -infinity */
7393  div[qi] = qdigit;
7394 
7395  /*
7396  * Because the quotient digits might be off by one, some of them might be
7397  * -1 or NBASE at this point. The represented value is correct in a
7398  * mathematical sense, but it doesn't look right. We do a final carry
7399  * propagation pass to normalize the digits, which we combine with storing
7400  * the result digits into the output. Note that this is still done at
7401  * full precision w/guard digits.
7402  */
7403  alloc_var(result, div_ndigits + 1);
7404  res_digits = result->digits;
7405  carry = 0;
7406  for (i = div_ndigits; i >= 0; i--)
7407  {
7408  newdig = div[i] + carry;
7409  if (newdig < 0)
7410  {
7411  carry = -((-newdig - 1) / NBASE) - 1;
7412  newdig -= carry * NBASE;
7413  }
7414  else if (newdig >= NBASE)
7415  {
7416  carry = newdig / NBASE;
7417  newdig -= carry * NBASE;
7418  }
7419  else
7420  carry = 0;
7421  res_digits[i] = newdig;
7422  }
7423  Assert(carry == 0);
7424 
7425  pfree(div);
7426 
7427  /*
7428  * Finally, round the result to the requested precision.
7429  */
7430  result->weight = res_weight;
7431  result->sign = res_sign;
7432 
7433  /* Round to target rscale (and set result->dscale) */
7434  if (round)
7435  round_var(result, rscale);
7436  else
7437  trunc_var(result, rscale);
7438 
7439  /* Strip leading and trailing zeroes */
7440  strip_var(result);
7441 }
static void round_var(NumericVar *var, int rscale)
Definition: numeric.c:8590
static void trunc_var(NumericVar *var, int rscale)
Definition: numeric.c:8696
int weight
Definition: numeric.c:272
#define NUMERIC_POS
Definition: numeric.c:164
static void strip_var(NumericVar *var)
Definition: numeric.c:8758
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:5420
void pfree(void *pointer)
Definition: mcxt.c:992
#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:920
#define Assert(condition)
Definition: c.h:671
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:5388
int i
#define DEC_DIGITS
Definition: numeric.c:95
static void do_numeric_accum ( NumericAggState state,
Numeric  newval 
)
static

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

3250 {
3251  NumericVar X;
3252  NumericVar X2;
3253  MemoryContext old_context;
3254 
3255  /* Count NaN inputs separately from all else */
3256  if (NUMERIC_IS_NAN(newval))
3257  {
3258  state->NaNcount++;
3259  return;
3260  }
3261 
3262  /* load processed number in short-lived context */
3263  init_var_from_num(newval, &X);
3264 
3265  /*
3266  * Track the highest input dscale that we've seen, to support inverse
3267  * transitions (see do_numeric_discard).
3268  */
3269  if (X.dscale > state->maxScale)
3270  {
3271  state->maxScale = X.dscale;
3272  state->maxScaleCount = 1;
3273  }
3274  else if (X.dscale == state->maxScale)
3275  state->maxScaleCount++;
3276 
3277  /* if we need X^2, calculate that in short-lived context */
3278  if (state->calcSumX2)
3279  {
3280  init_var(&X2);
3281  mul_var(&X, &X, &X2, X.dscale * 2);
3282  }
3283 
3284  /* The rest of this needs to work in the aggregate context */
3285  old_context = MemoryContextSwitchTo(state->agg_context);
3286 
3287  state->N++;
3288 
3289  /* Accumulate sums */
3290  accum_sum_add(&(state->sumX), &X);
3291 
3292  if (state->calcSumX2)
3293  accum_sum_add(&(state->sumX2), &X2);
3294 
3295  MemoryContextSwitchTo(old_context);
3296 }
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
MemoryContext agg_context
Definition: numeric.c:3195
int dscale
Definition: numeric.c:274
static void init_var_from_num(Numeric num, NumericVar *dest)
Definition: numeric.c:5637
static void mul_var(NumericVar *var1, NumericVar *var2, NumericVar *result, int rscale)
Definition: numeric.c:6673
static void accum_sum_add(NumericSumAccum *accum, NumericVar *var1)
Definition: numeric.c:8815
NumericSumAccum sumX2
Definition: numeric.c:3198
int64 NaNcount
Definition: numeric.c:3201
int64 maxScaleCount
Definition: numeric.c:3200
#define NUMERIC_IS_NAN(n)
Definition: numeric.c:170
NumericSumAccum sumX
Definition: numeric.c:3197
#define init_var(v)
Definition: numeric.c:451
static bool do_numeric_discard ( NumericAggState state,
Numeric  newval 
)
static

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

3315 {
3316  NumericVar X;
3317  NumericVar X2;
3318  MemoryContext old_context;
3319 
3320  /* Count NaN inputs separately from all else */
3321  if (NUMERIC_IS_NAN(newval))
3322  {
3323  state->NaNcount--;
3324  return true;
3325  }
3326 
3327  /* load processed number in short-lived context */
3328  init_var_from_num(newval, &X);
3329 
3330  /*
3331  * state->sumX's dscale is the maximum dscale of any of the inputs.
3332  * Removing the last input with that dscale would require us to recompute
3333  * the maximum dscale of the *remaining* inputs, which we cannot do unless
3334  * no more non-NaN inputs remain at all. So we report a failure instead,
3335  * and force the aggregation to be redone from scratch.
3336  */
3337  if (X.dscale == state->maxScale)
3338  {
3339  if (state->maxScaleCount > 1 || state->maxScale == 0)
3340  {
3341  /*
3342  * Some remaining inputs have same dscale, or dscale hasn't gotten
3343  * above zero anyway
3344  */
3345  state->maxScaleCount--;
3346  }
3347  else if (state->N == 1)
3348  {
3349  /* No remaining non-NaN inputs at all, so reset maxScale */
3350  state->maxScale = 0;
3351  state->maxScaleCount = 0;
3352  }
3353  else
3354  {
3355  /* Correct new maxScale is uncertain, must fail */
3356  return false;
3357  }
3358  }
3359 
3360  /* if we need X^2, calculate that in short-lived context */
3361  if (state->calcSumX2)
3362  {
3363  init_var(&X2);
3364  mul_var(&X, &X, &X2, X.dscale * 2);
3365  }
3366 
3367  /* The rest of this needs to work in the aggregate context */
3368  old_context = MemoryContextSwitchTo(state->agg_context);
3369 
3370  if (state->N-- > 1)
3371  {
3372  /* Negate X, to subtract it from the sum */
3373  X.sign = (X.sign == NUMERIC_POS ? NUMERIC_NEG : NUMERIC_POS);
3374  accum_sum_add(&(state->sumX), &X);
3375 
3376  if (state->calcSumX2)
3377  {
3378  /* Negate X^2. X^2 is always positive */
3379  X2.sign = NUMERIC_NEG;
3380  accum_sum_add(&(state->sumX2), &X2);
3381  }
3382  }
3383  else
3384  {
3385  /* Zero the sums */
3386  Assert(state->N == 0);
3387 
3388  accum_sum_reset(&state->sumX);
3389  if (state->calcSumX2)
3390  accum_sum_reset(&state->sumX2);
3391  }
3392 
3393  MemoryContextSwitchTo(old_context);
3394 
3395  return true;
3396 }
#define NUMERIC_POS
Definition: numeric.c:164
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
MemoryContext agg_context
Definition: numeric.c:3195
int dscale
Definition: numeric.c:274
#define NUMERIC_NEG
Definition: numeric.c:165
int sign
Definition: numeric.c:273
static void init_var_from_num(Numeric num, NumericVar *dest)
Definition: numeric.c:5637
static void mul_var(NumericVar *var1, NumericVar *var2, NumericVar *result, int rscale)
Definition: numeric.c:6673
#define Assert(condition)
Definition: c.h:671
static void accum_sum_add(NumericSumAccum *accum, NumericVar *var1)
Definition: numeric.c:8815
NumericSumAccum sumX2
Definition: numeric.c:3198
static void accum_sum_reset(NumericSumAccum *accum)
Definition: numeric.c:8799
int64 NaNcount
Definition: numeric.c:3201
int64 maxScaleCount
Definition: numeric.c:3200
#define NUMERIC_IS_NAN(n)
Definition: numeric.c:170
NumericSumAccum sumX
Definition: numeric.c:3197
#define init_var(v)
Definition: numeric.c:451
static int estimate_ln_dweight ( NumericVar var)
static

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

7795 {
7796  int ln_dweight;
7797 
7798  if (cmp_var(var, &const_zero_point_nine) >= 0 &&
7799  cmp_var(var, &const_one_point_one) <= 0)
7800  {
7801  /*
7802  * 0.9 <= var <= 1.1
7803  *
7804  * ln(var) has a negative weight (possibly very large). To get a
7805  * reasonably accurate result, estimate it using ln(1+x) ~= x.
7806  */
7807  NumericVar x;
7808 
7809  init_var(&x);
7810  sub_var(var, &const_one, &x);
7811 
7812  if (x.ndigits > 0)
7813  {
7814  /* Use weight of most significant decimal digit of x */
7815  ln_dweight = x.weight * DEC_DIGITS + (int) log10(x.digits[0]);
7816  }
7817  else
7818  {
7819  /* x = 0. Since ln(1) = 0 exactly, we don't need extra digits */
7820  ln_dweight = 0;
7821  }
7822 
7823  free_var(&x);
7824  }
7825  else
7826  {
7827  /*
7828  * Estimate the logarithm using the first couple of digits from the
7829  * input number. This will give an accurate result whenever the input
7830  * is not too close to 1.
7831  */
7832  if (var->ndigits > 0)
7833  {
7834  int digits;
7835  int dweight;
7836  double ln_var;
7837 
7838  digits = var->digits[0];
7839  dweight = var->weight * DEC_DIGITS;
7840 
7841  if (var->ndigits > 1)
7842  {
7843  digits = digits * NBASE + var->digits[1];
7844  dweight -= DEC_DIGITS;
7845  }
7846 
7847  /*----------
7848  * We have var ~= digits * 10^dweight
7849  * so ln(var) ~= ln(digits) + dweight * ln(10)
7850  *----------
7851  */
7852  ln_var = log((double) digits) + dweight * 2.302585092994046;
7853  ln_dweight = (int) log10(Abs(ln_var));
7854  }
7855  else
7856  {
7857  /* Caller should fail on ln(0), but for the moment return zero */
7858  ln_dweight = 0;
7859  }
7860  }
7861 
7862  return ln_dweight;
7863 }
static int cmp_var(NumericVar *var1, NumericVar *var2)
Definition: numeric.c:6377
int weight
Definition: numeric.c:272
static NumericVar const_one
Definition: numeric.c:375
static NumericVar const_zero_point_nine
Definition: numeric.c:409
int ndigits
Definition: numeric.c:271
static void ln_var(NumericVar *arg, NumericVar *result, int rscale)
Definition: numeric.c:7872
#define Abs(x)
Definition: c.h:808
static NumericVar const_one_point_one
Definition: numeric.c:419
#define NBASE
Definition: numeric.c:93
static void free_var(NumericVar *var)
Definition: numeric.c:5404
NumericDigit * digits
Definition: numeric.c:276
#define DEC_DIGITS
Definition: numeric.c:95
#define init_var(v)
Definition: numeric.c:451
static void sub_var(NumericVar *var1, NumericVar *var2, NumericVar *result)
Definition: numeric.c:6552
int digits
Definition: informix.c:691
static void exp_var ( NumericVar arg,
NumericVar result,
int  rscale 
)
static

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

7669 {
7670  NumericVar x;
7671  NumericVar elem;
7672  NumericVar ni;
7673  double val;
7674  int dweight;
7675  int ndiv2;
7676  int sig_digits;
7677  int local_rscale;
7678 
7679  init_var(&x);
7680  init_var(&elem);
7681  init_var(&ni);
7682 
7683  set_var_from_var(arg, &x);
7684 
7685  /*
7686  * Estimate the dweight of the result using floating point arithmetic, so
7687  * that we can choose an appropriate local rscale for the calculation.
7688  */
7690 
7691  /* Guard against overflow */
7692  /* If you change this limit, see also power_var()'s limit */
7693  if (Abs(val) >= NUMERIC_MAX_RESULT_SCALE * 3)
7694  ereport(ERROR,
7695  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
7696  errmsg("value overflows numeric format")));
7697 
7698  /* decimal weight = log10(e^x) = x * log10(e) */
7699  dweight = (int) (val * 0.434294481903252);
7700 
7701  /*
7702  * Reduce x to the range -0.01 <= x <= 0.01 (approximately) by dividing by
7703  * 2^n, to improve the convergence rate of the Taylor series.
7704  */
7705  if (Abs(val) > 0.01)
7706  {
7707  NumericVar tmp;
7708 
7709  init_var(&tmp);
7710  set_var_from_var(&const_two, &tmp);
7711 
7712  ndiv2 = 1;
7713  val /= 2;
7714 
7715  while (Abs(val) > 0.01)
7716  {
7717  ndiv2++;
7718  val /= 2;
7719  add_var(&tmp, &tmp, &tmp);
7720  }
7721 
7722  local_rscale = x.dscale + ndiv2;
7723  div_var_fast(&x, &tmp, &x, local_rscale, true);
7724 
7725  free_var(&tmp);
7726  }
7727  else
7728  ndiv2 = 0;
7729 
7730  /*
7731  * Set the scale for the Taylor series expansion. The final result has
7732  * (dweight + rscale + 1) significant digits. In addition, we have to
7733  * raise the Taylor series result to the power 2^ndiv2, which introduces
7734  * an error of up to around log10(2^ndiv2) digits, so work with this many
7735  * extra digits of precision (plus a few more for good measure).
7736  */
7737  sig_digits = 1 + dweight + rscale + (int) (ndiv2 * 0.301029995663981);
7738  sig_digits = Max(sig_digits, 0) + 8;
7739 
7740  local_rscale = sig_digits - 1;
7741 
7742  /*
7743  * Use the Taylor series
7744  *
7745  * exp(x) = 1 + x + x^2/2! + x^3/3! + ...
7746  *
7747  * Given the limited range of x, this should converge reasonably quickly.
7748  * We run the series until the terms fall below the local_rscale limit.
7749  */
7750  add_var(&const_one, &x, result);
7751 
7752  mul_var(&x, &x, &elem, local_rscale);
7753  set_var_from_var(&const_two, &ni);
7754  div_var_fast(&elem, &ni, &elem, local_rscale, true);
7755 
7756  while (elem.ndigits != 0)
7757  {
7758  add_var(result, &elem, result);
7759 
7760  mul_var(&elem, &x, &elem, local_rscale);
7761  add_var(&ni, &const_one, &ni);
7762  div_var_fast(&elem, &ni, &elem, local_rscale, true);
7763  }
7764 
7765  /*
7766  * Compensate for the argument range reduction. Since the weight of the
7767  * result doubles with each multiplication, we can reduce the local rscale
7768  * as we proceed.
7769  */
7770  while (ndiv2-- > 0)
7771  {
7772  local_rscale = sig_digits - result->weight * 2 * DEC_DIGITS;
7773  local_rscale = Max(local_rscale, NUMERIC_MIN_DISPLAY_SCALE);
7774  mul_var(result, result, result, local_rscale);
7775  }
7776 
7777  /* Round to requested rscale */
7778  round_var(result, rscale);
7779 
7780  free_var(&x);
7781  free_var(&elem);
7782  free_var(&ni);
7783 }
static void round_var(NumericVar *var, int rscale)
Definition: numeric.c:8590
int weight
Definition: numeric.c:272
static NumericVar const_one
Definition: numeric.c:375
int errcode(int sqlerrcode)
Definition: elog.c:575
static double numericvar_to_double_no_overflow(NumericVar *var)
Definition: numeric.c:6345
static void add_var(NumericVar *var1, NumericVar *var2, NumericVar *result)
Definition: numeric.c:6435
int ndigits
Definition: numeric.c:271
static void set_var_from_var(NumericVar *value, NumericVar *dest)
Definition: numeric.c:5654
int dscale
Definition: numeric.c:274
static NumericVar const_two
Definition: numeric.c:379
#define Abs(x)
Definition: c.h:808
#define ERROR
Definition: elog.h:43
#define NUMERIC_MIN_DISPLAY_SCALE
Definition: numeric.h:30
#define NUMERIC_MAX_RESULT_SCALE
Definition: numeric.h:32
#define ereport(elevel, rest)
Definition: elog.h:122
static void mul_var(NumericVar *var1, NumericVar *var2, NumericVar *result, int rscale)
Definition: numeric.c:6673
static void free_var(NumericVar *var)
Definition: numeric.c:5404
static void div_var_fast(NumericVar *var1, NumericVar *var2, NumericVar *result, int rscale, bool round)
Definition: numeric.c:7155
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define Max(x, y)
Definition: numeric.c:11
#define DEC_DIGITS
Definition: numeric.c:95
long val
Definition: informix.c:689
#define init_var(v)
Definition: numeric.c:451
Datum float4_numeric ( PG_FUNCTION_ARGS  )

Definition at line 3132 of file numeric.c.

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

3133 {
3135  Numeric res;
3136  NumericVar result;
3137  char buf[FLT_DIG + 100];
3138 
3139  if (isnan(val))
3141 
3142  sprintf(buf, "%.*g", FLT_DIG, val);
3143 
3144  init_var(&result);
3145 
3146  /* Assume we need not worry about leading/trailing spaces */
3147  (void) set_var_from_str(buf, buf, &result);
3148 
3149  res = make_result(&result);
3150 
3151  free_var(&result);
3152 
3153  PG_RETURN_NUMERIC(res);
3154 }
#define PG_RETURN_NUMERIC(x)
Definition: numeric.h:54
static NumericVar const_nan
Definition: numeric.c:422
static char * buf
Definition: pg_test_fsync.c:65
static Numeric make_result(NumericVar *var)
Definition: numeric.c:5919
#define PG_GETARG_FLOAT4(n)
Definition: fmgr.h:236
float float4
Definition: c.h:377
static void free_var(NumericVar *var)
Definition: numeric.c:5404
static const char * set_var_from_str(const char *str, const char *cp, NumericVar *dest)
Definition: numeric.c:5444
long val
Definition: informix.c:689
#define init_var(v)
Definition: numeric.c:451
Datum float8_numeric ( PG_FUNCTION_ARGS  )

Definition at line 3066 of file numeric.c.

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

3067 {
3069  Numeric res;
3070  NumericVar result;
3071  char buf[DBL_DIG + 100];
3072 
3073  if (isnan(val))
3075 
3076  sprintf(buf, "%.*g", DBL_DIG, val);
3077 
3078  init_var(&result);
3079 
3080  /* Assume we need not worry about leading/trailing spaces */
3081  (void) set_var_from_str(buf, buf, &result);
3082 
3083  res = make_result(&result);
3084 
3085  free_var(&result);
3086 
3087  PG_RETURN_NUMERIC(res);
3088 }
#define PG_RETURN_NUMERIC(x)
Definition: numeric.h:54
#define PG_GETARG_FLOAT8(n)
Definition: fmgr.h:237
static NumericVar const_nan
Definition: numeric.c:422
double float8
Definition: c.h:378
static char * buf
Definition: pg_test_fsync.c:65
static Numeric make_result(NumericVar *var)
Definition: numeric.c:5919
static void free_var(NumericVar *var)
Definition: numeric.c:5404
static const char * set_var_from_str(const char *str, const char *cp, NumericVar *dest)
Definition: numeric.c:5444
long val
Definition: informix.c:689
#define init_var(v)
Definition: numeric.c:451
static void floor_var ( NumericVar var,
NumericVar result 
)
static

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

7573 {
7574  NumericVar tmp;
7575 
7576  init_var(&tmp);
7577  set_var_from_var(var, &tmp);
7578 
7579  trunc_var(&tmp, 0);
7580 
7581  if (var->sign == NUMERIC_NEG && cmp_var(var, &tmp) != 0)
7582  sub_var(&tmp, &const_one, &tmp);
7583 
7584  set_var_from_var(&tmp, result);
7585  free_var(&tmp);
7586 }
static void trunc_var(NumericVar *var, int rscale)
Definition: numeric.c:8696
static int cmp_var(NumericVar *var1, NumericVar *var2)
Definition: numeric.c:6377
static NumericVar const_one
Definition: numeric.c:375
static void set_var_from_var(NumericVar *value, NumericVar *dest)
Definition: numeric.c:5654
#define NUMERIC_NEG
Definition: numeric.c:165
int sign
Definition: numeric.c:273
static void free_var(NumericVar *var)
Definition: numeric.c:5404
#define init_var(v)
Definition: numeric.c:451
static void sub_var(NumericVar *var1, NumericVar *var2, NumericVar *result)
Definition: numeric.c:6552
static void free_var ( NumericVar var)
static
Datum generate_series_numeric ( PG_FUNCTION_ARGS  )

Definition at line 1357 of file numeric.c.

References generate_series_step_numeric().

1358 {
1359  return generate_series_step_numeric(fcinfo);
1360 }
Datum generate_series_step_numeric(PG_FUNCTION_ARGS)
Definition: numeric.c:1363
Datum generate_series_step_numeric ( PG_FUNCTION_ARGS  )

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

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

Definition at line 5680 of file numeric.c.

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

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

5681 {
5682  int dscale;
5683  char *str;
5684  char *cp;
5685  char *endcp;
5686  int i;
5687  int d;
5688  NumericDigit dig;
5689 
5690 #if DEC_DIGITS > 1
5691  NumericDigit d1;
5692 #endif
5693 
5694  dscale = var->dscale;
5695 
5696  /*
5697  * Allocate space for the result.
5698  *
5699  * i is set to the # of decimal digits before decimal point. dscale is the
5700  * # of decimal digits we will print after decimal point. We may generate
5701  * as many as DEC_DIGITS-1 excess digits at the end, and in addition we
5702  * need room for sign, decimal point, null terminator.
5703  */
5704  i = (var->weight + 1) * DEC_DIGITS;
5705  if (i <= 0)
5706  i = 1;
5707 
5708  str = palloc(i + dscale + DEC_DIGITS + 2);
5709  cp = str;
5710 
5711  /*
5712  * Output a dash for negative values
5713  */
5714  if (var->sign == NUMERIC_NEG)
5715  *cp++ = '-';
5716 
5717  /*
5718  * Output all digits before the decimal point
5719  */
5720  if (var->weight < 0)
5721  {
5722  d = var->weight + 1;
5723  *cp++ = '0';
5724  }
5725  else
5726  {
5727  for (d = 0; d <= var->weight; d++)
5728  {
5729  dig = (d < var->ndigits) ? var->digits[d] : 0;
5730  /* In the first digit, suppress extra leading decimal zeroes */
5731 #if DEC_DIGITS == 4
5732  {
5733  bool putit = (d > 0);
5734 
5735  d1 = dig / 1000;
5736  dig -= d1 * 1000;
5737  putit |= (d1 > 0);
5738  if (putit)
5739  *cp++ = d1 + '0';
5740  d1 = dig / 100;
5741  dig -= d1 * 100;
5742  putit |= (d1 > 0);
5743  if (putit)
5744  *cp++ = d1 + '0';
5745  d1 = dig / 10;
5746  dig -= d1 * 10;
5747  putit |= (d1 > 0);
5748  if (putit)
5749  *cp++ = d1 + '0';
5750  *cp++ = dig + '0';
5751  }
5752 #elif DEC_DIGITS == 2
5753  d1 = dig / 10;
5754  dig -= d1 * 10;
5755  if (d1 > 0 || d > 0)
5756  *cp++ = d1 + '0';
5757  *cp++ = dig + '0';
5758 #elif DEC_DIGITS == 1
5759  *cp++ = dig + '0';
5760 #else
5761 #error unsupported NBASE
5762 #endif
5763  }
5764  }
5765 
5766  /*
5767  * If requested, output a decimal point and all the digits that follow it.
5768  * We initially put out a multiple of DEC_DIGITS digits, then truncate if
5769  * needed.
5770  */
5771  if (dscale > 0)
5772  {
5773  *cp++ = '.';
5774  endcp = cp + dscale;
5775  for (i = 0; i < dscale; d++, i += DEC_DIGITS)
5776  {
5777  dig = (d >= 0 && d < var->ndigits) ? var->digits[d] : 0;
5778 #if DEC_DIGITS == 4
5779  d1 = dig / 1000;
5780  dig -= d1 * 1000;
5781  *cp++ = d1 + '0';
5782  d1 = dig / 100;
5783  dig -= d1 * 100;
5784  *cp++ = d1 + '0';
5785  d1 = dig / 10;
5786  dig -= d1 * 10;
5787  *cp++ = d1 + '0';
5788  *cp++ = dig + '0';
5789 #elif DEC_DIGITS == 2
5790  d1 = dig / 10;
5791  dig -= d1 * 10;
5792  *cp++ = d1 + '0';
5793  *cp++ = dig + '0';
5794 #elif DEC_DIGITS == 1
5795  *cp++ = dig + '0';
5796 #else
5797 #error unsupported NBASE
5798 #endif
5799  }
5800  cp = endcp;
5801  }
5802 
5803  /*
5804  * terminate the string and return it
5805  */
5806  *cp = '\0';
5807  return str;
5808 }
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:891
int i
#define DEC_DIGITS
Definition: numeric.c:95
static char * get_str_from_var_sci ( NumericVar var,
int  rscale 
)
static

Definition at line 5833 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(), and NumericVar::weight.

Referenced by numeric_out_sci().

5834 {
5835  int32 exponent;
5836  NumericVar denominator;
5837  NumericVar significand;
5838  int denom_scale;
5839  size_t len;
5840  char *str;
5841  char *sig_out;
5842 
5843  if (rscale < 0)
5844  rscale = 0;
5845 
5846  /*
5847  * Determine the exponent of this number in normalised form.
5848  *
5849  * This is the exponent required to represent the number with only one
5850  * significant digit before the decimal place.
5851  */
5852  if (var->ndigits > 0)
5853  {
5854  exponent = (var->weight + 1) * DEC_DIGITS;
5855 
5856  /*
5857  * Compensate for leading decimal zeroes in the first numeric digit by
5858  * decrementing the exponent.
5859  */
5860  exponent -= DEC_DIGITS - (int) log10(var->digits[0]);
5861  }
5862  else
5863  {
5864  /*
5865  * If var has no digits, then it must be zero.
5866  *
5867  * Zero doesn't technically have a meaningful exponent in normalised
5868  * notation, but we just display the exponent as zero for consistency
5869  * of output.
5870  */
5871  exponent = 0;
5872  }
5873 
5874  /*
5875  * The denominator is set to 10 raised to the power of the exponent.
5876  *
5877  * We then divide var by the denominator to get the significand, rounding
5878  * to rscale decimal digits in the process.
5879  */
5880  if (exponent < 0)
5881  denom_scale = -exponent;
5882  else
5883  denom_scale = 0;
5884 
5885  init_var(&denominator);
5886  init_var(&significand);
5887 
5888  power_var_int(&const_ten, exponent, &denominator, denom_scale);
5889  div_var(var, &denominator, &significand, rscale, true);
5890  sig_out = get_str_from_var(&significand);
5891 
5892  free_var(&denominator);
5893  free_var(&significand);
5894 
5895  /*
5896  * Allocate space for the result.
5897  *
5898  * In addition to the significand, we need room for the exponent
5899  * decoration ("e"), the sign of the exponent, up to 10 digits for the
5900  * exponent itself, and of course the null terminator.
5901  */
5902  len = strlen(sig_out) + 13;
5903  str = palloc(len);
5904  snprintf(str, len, "%se%+03d", sig_out, exponent);
5905 
5906  pfree(sig_out);
5907 
5908  return str;
5909 }
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(NumericVar *var1, NumericVar *var2, NumericVar *result, int rscale, bool round)
Definition: numeric.c:6870
signed int int32
Definition: c.h:253
void pfree(void *pointer)
Definition: mcxt.c:992
static void power_var_int(NumericVar *base, int exp, NumericVar *result, int rscale)
Definition: numeric.c:8154
static char * get_str_from_var(NumericVar *var)
Definition: numeric.c:5680
static void free_var(NumericVar *var)
Definition: numeric.c:5404
NumericDigit * digits
Definition: numeric.c:276
static NumericVar const_ten
Definition: numeric.c:384
void * palloc(Size size)
Definition: mcxt.c:891
#define DEC_DIGITS
Definition: numeric.c:95
#define init_var(v)
Definition: numeric.c:451
Datum hash_numeric ( PG_FUNCTION_ARGS  )

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

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

Definition at line 5637 of file numeric.c.

References NumericVar::buf, NumericVar::digits, NumericVar::dscale, NumericVar::ndigits, NULL, 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().

5638 {
5639  dest->ndigits = NUMERIC_NDIGITS(num);
5640  dest->weight = NUMERIC_WEIGHT(num);
5641  dest->sign = NUMERIC_SIGN(num);
5642  dest->dscale = NUMERIC_DSCALE(num);
5643  dest->digits = NUMERIC_DIGITS(num);
5644  dest->buf = NULL; /* digits array is not palloc'd */
5645 }
#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
#define NULL
Definition: c.h:226
NumericDigit * digits
Definition: numeric.c:276
Datum int2_accum ( PG_FUNCTION_ARGS  )

Definition at line 3937 of file numeric.c.

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

3938 {
3940 
3941  state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
3942 
3943  /* Create the state data on the first call */
3944  if (state == NULL)
3945  state = makePolyNumAggState(fcinfo, true);
3946 
3947  if (!PG_ARGISNULL(1))
3948  {
3949 #ifdef HAVE_INT128
3950  do_int128_accum(state, (int128) PG_GETARG_INT16(1));
3951 #else
3952  Numeric newval;
3953 
3955  PG_GETARG_DATUM(1)));
3956  do_numeric_accum(state, newval);
3957 #endif
3958  }
3959 
3960  PG_RETURN_POINTER(state);
3961 }
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:305
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:224
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:232
Datum int2_numeric(PG_FUNCTION_ARGS)
Definition: numeric.c:3012
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:555
static void do_numeric_accum(NumericAggState *state, Numeric newval)
Definition: numeric.c:3249
#define PG_GETARG_INT16(n)
Definition: fmgr.h:227
#define PG_ARGISNULL(n)
Definition: fmgr.h:166
#define DatumGetNumeric(X)
Definition: numeric.h:49
#define NULL
Definition: c.h:226
Definition: regguts.h:298
#define newval
#define makePolyNumAggState
Definition: numeric.c:3932
Datum int2_accum_inv ( PG_FUNCTION_ARGS  )

Definition at line 4412 of file numeric.c.

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

4413 {
4415 
4416  state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
4417 
4418  /* Should not get here with no state */
4419  if (state == NULL)
4420  elog(ERROR, "int2_accum_inv called with NULL state");
4421 
4422  if (!PG_ARGISNULL(1))
4423  {
4424 #ifdef HAVE_INT128
4425  do_int128_discard(state, (int128) PG_GETARG_INT16(1));
4426 #else
4427  Numeric newval;
4428 
4430  PG_GETARG_DATUM(1)));
4431 
4432  /* Should never fail, all inputs have dscale 0 */
4433  if (!do_numeric_discard(state, newval))
4434  elog(ERROR, "do_numeric_discard failed unexpectedly");
4435 #endif
4436  }
4437 
4438  PG_RETURN_POINTER(state);
4439 }
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:305
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:224
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:232
Datum int2_numeric(PG_FUNCTION_ARGS)
Definition: numeric.c:3012
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:555
static bool do_numeric_discard(NumericAggState *state, Numeric newval)
Definition: numeric.c:3314
#define ERROR
Definition: elog.h:43
#define PG_GETARG_INT16(n)
Definition: fmgr.h:227
#define PG_ARGISNULL(n)
Definition: fmgr.h:166
#define DatumGetNumeric(X)
Definition: numeric.h:49
#define NULL
Definition: c.h:226
Definition: regguts.h:298
#define newval
#define elog
Definition: elog.h:219
Datum int2_avg_accum ( PG_FUNCTION_ARGS  )

Definition at line 5103 of file numeric.c.

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

5104 {
5105  ArrayType *transarray;
5107  Int8TransTypeData *transdata;
5108 
5109  /*
5110  * If we're invoked as an aggregate, we can cheat and modify our first
5111  * parameter in-place to reduce palloc overhead. Otherwise we need to make
5112  * a copy of it before scribbling on it.
5113  */
5114  if (AggCheckCallContext(fcinfo, NULL))
5115  transarray = PG_GETARG_ARRAYTYPE_P(0);
5116  else
5117  transarray = PG_GETARG_ARRAYTYPE_P_COPY(0);
5118 
5119  if (ARR_HASNULL(transarray) ||
5120  ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
5121  elog(ERROR, "expected 2-element int8 array");
5122 
5123  transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
5124  transdata->count++;
5125  transdata->sum += newval;
5126 
5127  PG_RETURN_ARRAYTYPE_P(transarray);
5128 }
signed short int16
Definition: c.h:252
#define ARR_OVERHEAD_NONULLS(ndims)
Definition: array.h:291
#define ARR_SIZE(a)
Definition: array.h:270
#define PG_GETARG_ARRAYTYPE_P_COPY(n)
Definition: array.h:245
#define PG_GETARG_ARRAYTYPE_P(n)
Definition: array.h:244
#define ERROR
Definition: elog.h:43
#define ARR_DATA_PTR(a)
Definition: array.h:303
#define ARR_HASNULL(a)
Definition: array.h:272
#define PG_RETURN_ARRAYTYPE_P(x)
Definition: array.h:246
#define PG_GETARG_INT16(n)
Definition: fmgr.h:227
#define NULL
Definition: c.h:226
#define newval
int AggCheckCallContext(FunctionCallInfo fcinfo, MemoryContext *aggcontext)
Definition: nodeAgg.c:3660
#define elog
Definition: elog.h:219
Datum int2_avg_accum_inv ( PG_FUNCTION_ARGS  )

Definition at line 5190 of file numeric.c.

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

5191 {
5192  ArrayType *transarray;
5194  Int8TransTypeData *transdata;
5195 
5196  /*
5197  * If we're invoked as an aggregate, we can cheat and modify our first
5198  * parameter in-place to reduce palloc overhead. Otherwise we need to make
5199  * a copy of it before scribbling on it.
5200  */
5201  if (AggCheckCallContext(fcinfo, NULL))
5202  transarray = PG_GETARG_ARRAYTYPE_P(0);
5203  else
5204  transarray = PG_GETARG_ARRAYTYPE_P_COPY(0);
5205 
5206  if (ARR_HASNULL(transarray) ||
5207  ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
5208  elog(ERROR, "expected 2-element int8 array");
5209 
5210  transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
5211  transdata->count--;
5212  transdata->sum -= newval;
5213 
5214  PG_RETURN_ARRAYTYPE_P(transarray);
5215 }
signed short int16
Definition: c.h:252
#define ARR_OVERHEAD_NONULLS(ndims)
Definition: array.h:291
#define ARR_SIZE(a)
Definition: array.h:270
#define PG_GETARG_ARRAYTYPE_P_COPY(n)
Definition: array.h:245
#define PG_GETARG_ARRAYTYPE_P(n)
Definition: array.h:244
#define ERROR
Definition: elog.h:43
#define ARR_DATA_PTR(a)
Definition: array.h:303
#define ARR_HASNULL(a)
Definition: array.h:272
#define PG_RETURN_ARRAYTYPE_P(x)
Definition: array.h:246
#define PG_GETARG_INT16(n)
Definition: fmgr.h:227
#define NULL
Definition: c.h:226
#define newval
int AggCheckCallContext(FunctionCallInfo fcinfo, MemoryContext *aggcontext)
Definition: nodeAgg.c:3660
#define elog
Definition: elog.h:219
Datum int2_numeric ( PG_FUNCTION_ARGS  )

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

3013 {
3014  int16 val = PG_GETARG_INT16(0);
3015  Numeric res;
3016  NumericVar result;
3017 
3018  init_var(&result);
3019 
3020  int64_to_numericvar((int64) val, &result);
3021 
3022  res = make_result(&result);
3023 
3024  free_var(&result);
3025 
3026  PG_RETURN_NUMERIC(res);
3027 }
#define PG_RETURN_NUMERIC(x)
Definition: numeric.h:54
signed short int16
Definition: c.h:252
static Numeric make_result(NumericVar *var)
Definition: numeric.c:5919
#define PG_GETARG_INT16(n)
Definition: fmgr.h:227
static void free_var(NumericVar *var)
Definition: numeric.c:5404
static void int64_to_numericvar(int64 val, NumericVar *var)
Definition: numeric.c:6153
long val
Definition: informix.c:689
#define init_var(v)
Definition: numeric.c:451
Datum int2_sum ( PG_FUNCTION_ARGS  )

Definition at line 4951 of file numeric.c.

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

4952 {
4953  int64 newval;
4954 
4955  if (PG_ARGISNULL(0))
4956  {
4957  /* No non-null input seen so far... */
4958  if (PG_ARGISNULL(1))
4959  PG_RETURN_NULL(); /* still no non-null */
4960  /* This is the first non-null input. */
4961  newval = (int64) PG_GETARG_INT16(1);
4962  PG_RETURN_INT64(newval);
4963  }
4964 
4965  /*
4966  * If we're invoked as an aggregate, we can cheat and modify our first
4967  * parameter in-place to avoid palloc overhead. If not, we need to return
4968  * the new value of the transition variable. (If int8 is pass-by-value,
4969  * then of course this is useless as well as incorrect, so just ifdef it
4970  * out.)
4971  */
4972 #ifndef USE_FLOAT8_BYVAL /* controls int8 too */
4973  if (AggCheckCallContext(fcinfo, NULL))
4974  {
4975  int64 *oldsum = (int64 *) PG_GETARG_POINTER(0);
4976 
4977  /* Leave the running sum unchanged in the new input is null */
4978  if (!PG_ARGISNULL(1))
4979  *oldsum = *oldsum + (int64) PG_GETARG_INT16(1);
4980 
4981  PG_RETURN_POINTER(oldsum);
4982  }
4983  else
4984 #endif
4985  {
4986  int64 oldsum = PG_GETARG_INT64(0);
4987 
4988  /* Leave sum unchanged if new input is null. */
4989  if (PG_ARGISNULL(1))
4990  PG_RETURN_INT64(oldsum);
4991 
4992  /* OK to do the addition. */
4993  newval = oldsum + (int64) PG_GETARG_INT16(1);
4994 
4995  PG_RETURN_INT64(newval);
4996  }
4997 }
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:305
#define PG_RETURN_INT64(x)
Definition: fmgr.h:311
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:232
#define PG_GETARG_INT16(n)
Definition: fmgr.h:227
#define PG_ARGISNULL(n)
Definition: fmgr.h:166
#define NULL
Definition: c.h:226
#define newval
int AggCheckCallContext(FunctionCallInfo fcinfo, MemoryContext *aggcontext)
Definition: nodeAgg.c:3660
#define PG_GETARG_INT64(n)
Definition: fmgr.h:238
#define PG_RETURN_NULL()
Definition: fmgr.h:289
Datum int2int4_sum ( PG_FUNCTION_ARGS  )

Definition at line 5275 of file numeric.c.

References ARR_DATA_PTR, ARR_HASNULL, ARR_OVERHEAD_NONULLS, ARR_SIZE, Int8TransTypeData::count, elog, ERROR, Int64GetDatumFast, PG_GETARG_ARRAYTYPE_P, PG_RETURN_DATUM, PG_RETURN_NULL, and Int8TransTypeData::sum.

5276 {
5277  ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
5278  Int8TransTypeData *transdata;
5279 
5280  if (ARR_HASNULL(transarray) ||
5281  ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
5282  elog(ERROR, "expected 2-element int8 array");
5283  transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
5284 
5285  /* SQL defines SUM of no values to be NULL */
5286  if (transdata->count == 0)
5287  PG_RETURN_NULL();
5288 
5289  PG_RETURN_DATUM(Int64GetDatumFast(transdata->sum));
5290 }
#define ARR_OVERHEAD_NONULLS(ndims)
Definition: array.h:291
#define ARR_SIZE(a)
Definition: array.h:270
#define PG_GETARG_ARRAYTYPE_P(n)
Definition: array.h:244
#define ERROR
Definition: elog.h:43
#define ARR_DATA_PTR(a)
Definition: array.h:303
#define ARR_HASNULL(a)
Definition: array.h:272
#define PG_RETURN_DATUM(x)
Definition: fmgr.h:297
#define Int64GetDatumFast(X)
Definition: postgres.h:783
#define elog
Definition: elog.h:219
#define PG_RETURN_NULL()
Definition: fmgr.h:289
Datum int4_accum ( PG_FUNCTION_ARGS  )

Definition at line 3964 of file numeric.c.

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

3965 {
3967 
3968  state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
3969 
3970  /* Create the state data on the first call */
3971  if (state == NULL)
3972  state = makePolyNumAggState(fcinfo, true);
3973 
3974  if (!PG_ARGISNULL(1))
3975  {
3976 #ifdef HAVE_INT128
3977  do_int128_accum(state, (int128) PG_GETARG_INT32(1));
3978 #else
3979  Numeric newval;
3980 
3982  PG_GETARG_DATUM(1)));
3983  do_numeric_accum(state, newval);
3984 #endif
3985  }
3986 
3987  PG_RETURN_POINTER(state);
3988 }
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:305
#define PG_GETARG_INT32(n)
Definition: fmgr.h:225
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:224
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:232
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:555
static void do_numeric_accum(NumericAggState *state, Numeric newval)
Definition: numeric.c:3249
Datum int4_numeric(PG_FUNCTION_ARGS)
Definition: numeric.c:2902
#define PG_ARGISNULL(n)
Definition: fmgr.h:166
#define DatumGetNumeric(X)
Definition: numeric.h:49
#define NULL
Definition: c.h:226
Definition: regguts.h:298
#define newval
#define makePolyNumAggState
Definition: numeric.c:3932
Datum int4_accum_inv ( PG_FUNCTION_ARGS  )

Definition at line 4442 of file numeric.c.

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

4443 {
4445 
4446  state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
4447 
4448  /* Should not get here with no state */
4449  if (state == NULL)
4450  elog(ERROR, "int4_accum_inv called with NULL state");
4451 
4452  if (!PG_ARGISNULL(1))
4453  {
4454 #ifdef HAVE_INT128
4455  do_int128_discard(state, (int128) PG_GETARG_INT32(1));
4456 #else
4457  Numeric newval;
4458 
4460  PG_GETARG_DATUM(1)));
4461 
4462  /* Should never fail, all inputs have dscale 0 */
4463  if (!do_numeric_discard(state, newval))
4464  elog(ERROR, "do_numeric_discard failed unexpectedly");
4465 #endif
4466  }
4467 
4468  PG_RETURN_POINTER(state);
4469 }
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:305
#define PG_GETARG_INT32(n)
Definition: fmgr.h:225
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:224
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:232
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:555
static bool do_numeric_discard(NumericAggState *state, Numeric newval)
Definition: numeric.c:3314
#define ERROR
Definition: elog.h:43
Datum int4_numeric(PG_FUNCTION_ARGS)
Definition: numeric.c:2902
#define PG_ARGISNULL(n)
Definition: fmgr.h:166
#define DatumGetNumeric(X)
Definition: numeric.h:49
#define NULL
Definition: c.h:226
Definition: regguts.h:298
#define newval
#define elog
Definition: elog.h:219
Datum int4_avg_accum ( PG_FUNCTION_ARGS  )

Definition at line 5131 of file numeric.c.

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

5132 {
5133  ArrayType *transarray;
5135  Int8TransTypeData *transdata;
5136 
5137  /*
5138  * If we're invoked as an aggregate, we can cheat and modify our first
5139  * parameter in-place to reduce palloc overhead. Otherwise we need to make
5140  * a copy of it before scribbling on it.
5141  */
5142  if (AggCheckCallContext(fcinfo, NULL))
5143  transarray = PG_GETARG_ARRAYTYPE_P(0);
5144  else
5145  transarray = PG_GETARG_ARRAYTYPE_P_COPY(0);
5146 
5147  if (ARR_HASNULL(transarray) ||
5148  ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
5149  elog(ERROR, "expected 2-element int8 array");
5150 
5151  transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
5152  transdata->count++;
5153  transdata->sum += newval;
5154 
5155  PG_RETURN_ARRAYTYPE_P(transarray);
5156 }
#define PG_GETARG_INT32(n)
Definition: fmgr.h:225
#define ARR_OVERHEAD_NONULLS(ndims)
Definition: array.h:291
#define ARR_SIZE(a)
Definition: array.h:270
#define PG_GETARG_ARRAYTYPE_P_COPY(n)
Definition: array.h:245
signed int int32
Definition: c.h:253
#define PG_GETARG_ARRAYTYPE_P(n)
Definition: array.h:244
#define ERROR
Definition: elog.h:43
#define ARR_DATA_PTR(a)
Definition: array.h:303
#define ARR_HASNULL(a)
Definition: array.h:272
#define PG_RETURN_ARRAYTYPE_P(x)
Definition: array.h:246
#define NULL
Definition: c.h:226
#define newval
int AggCheckCallContext(FunctionCallInfo fcinfo, MemoryContext *aggcontext)
Definition: nodeAgg.c:3660
#define elog
Definition: elog.h:219
Datum int4_avg_accum_inv ( PG_FUNCTION_ARGS  )

Definition at line 5218 of file numeric.c.

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

5219 {
5220  ArrayType *transarray;
5222  Int8TransTypeData *transdata;
5223 
5224  /*
5225  * If we're invoked as an aggregate, we can cheat and modify our first
5226  * parameter in-place to reduce palloc overhead. Otherwise we need to make
5227  * a copy of it before scribbling on it.
5228  */
5229  if (AggCheckCallContext(fcinfo, NULL))
5230  transarray = PG_GETARG_ARRAYTYPE_P(0);
5231  else
5232  transarray = PG_GETARG_ARRAYTYPE_P_COPY(0);
5233 
5234  if (ARR_HASNULL(transarray) ||
5235  ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
5236  elog(ERROR, "expected 2-element int8 array");
5237 
5238  transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
5239  transdata->count--;
5240  transdata->sum -= newval;
5241 
5242  PG_RETURN_ARRAYTYPE_P(transarray);
5243 }
#define PG_GETARG_INT32(n)
Definition: fmgr.h:225
#define ARR_OVERHEAD_NONULLS(ndims)
Definition: array.h:291
#define ARR_SIZE(a)
Definition: array.h:270
#define PG_GETARG_ARRAYTYPE_P_COPY(n)
Definition: array.h:245
signed int int32
Definition: c.h:253
#define PG_GETARG_ARRAYTYPE_P(n)
Definition: array.h:244
#define ERROR
Definition: elog.h:43
#define ARR_DATA_PTR(a)
Definition: array.h:303
#define ARR_HASNULL(a)
Definition: array.h:272
#define PG_RETURN_ARRAYTYPE_P(x)
Definition: array.h:246
#define NULL
Definition: c.h:226
#define newval
int AggCheckCallContext(FunctionCallInfo fcinfo, MemoryContext *aggcontext)
Definition: nodeAgg.c:3660
#define elog
Definition: elog.h:219
Datum int4_avg_combine ( PG_FUNCTION_ARGS  )

Definition at line 5159 of file numeric.c.

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

5160 {
5161  ArrayType *transarray1;
5162  ArrayType *transarray2;
5163  Int8TransTypeData *state1;
5164  Int8TransTypeData *state2;
5165 
5166  if (!AggCheckCallContext(fcinfo, NULL))
5167  elog(ERROR, "aggregate function called in non-aggregate context");
5168 
5169  transarray1 = PG_GETARG_ARRAYTYPE_P(0);
5170  transarray2 = PG_GETARG_ARRAYTYPE_P(1);
5171 
5172  if (ARR_HASNULL(transarray1) ||
5173  ARR_SIZE(transarray1) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
5174  elog(ERROR, "expected 2-element int8 array");
5175 
5176  if (ARR_HASNULL(transarray2) ||
5177  ARR_SIZE(transarray2) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
5178  elog(ERROR, "expected 2-element int8 array");
5179 
5180  state1 = (Int8TransTypeData *) ARR_DATA_PTR(transarray1);
5181  state2 = (Int8TransTypeData *) ARR_DATA_PTR(transarray2);
5182 
5183  state1->count += state2->count;
5184  state1->sum += state2->sum;
5185 
5186  PG_RETURN_ARRAYTYPE_P(transarray1);
5187 }
#define ARR_OVERHEAD_NONULLS(ndims)
Definition: array.h:291
#define ARR_SIZE(a)
Definition: array.h:270
#define PG_GETARG_ARRAYTYPE_P(n)
Definition: array.h:244
#define ERROR
Definition: elog.h:43
#define ARR_DATA_PTR(a)
Definition: array.h:303
#define ARR_HASNULL(a)
Definition: array.h:272
#define PG_RETURN_ARRAYTYPE_P(x)
Definition: array.h:246
#define NULL
Definition: c.h:226
int AggCheckCallContext(FunctionCallInfo fcinfo, MemoryContext *aggcontext)
Definition: nodeAgg.c:3660
#define elog
Definition: elog.h:219
Datum int4_numeric ( PG_FUNCTION_ARGS  )

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

2903 {
2904  int32 val = PG_GETARG_INT32(0);
2905  Numeric res;
2906  NumericVar result;
2907 
2908  init_var(&result);
2909 
2910  int64_to_numericvar((int64) val, &result);
2911 
2912  res = make_result(&result);
2913 
2914  free_var(&result);
2915 
2916  PG_RETURN_NUMERIC(res);
2917 }
#define PG_RETURN_NUMERIC(x)
Definition: numeric.h:54
#define PG_GETARG_INT32(n)
Definition: fmgr.h:225
signed int int32
Definition: c.h:253
static Numeric make_result(NumericVar *var)
Definition: numeric.c:5919
static void free_var(NumericVar *var)
Definition: numeric.c:5404
static void int64_to_numericvar(int64 val, NumericVar *var)
Definition: numeric.c:6153
long val
Definition: informix.c:689
#define init_var(v)
Definition: numeric.c:451
Datum int4_sum ( PG_FUNCTION_ARGS  )

Definition at line 5000 of file numeric.c.

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

5001 {
5002  int64 newval;
5003 
5004  if (PG_ARGISNULL(0))
5005  {
5006  /* No non-null input seen so far... */
5007  if (PG_ARGISNULL(1))
5008  PG_RETURN_NULL(); /* still no non-null */
5009  /* This is the first non-null input. */
5010  newval = (int64) PG_GETARG_INT32(1);
5011  PG_RETURN_INT64(newval);
5012  }
5013 
5014  /*
5015  * If we're invoked as an aggregate, we can cheat and modify our first
5016  * parameter in-place to avoid palloc overhead. If not, we need to return
5017  * the new value of the transition variable. (If int8 is pass-by-value,
5018  * then of course this is useless as well as incorrect, so just ifdef it
5019  * out.)
5020  */
5021 #ifndef USE_FLOAT8_BYVAL /* controls int8 too */
5022  if (AggCheckCallContext(fcinfo, NULL))
5023  {
5024  int64 *oldsum = (int64 *) PG_GETARG_POINTER(0);
5025 
5026  /* Leave the running sum unchanged in the new input is null */
5027  if (!PG_ARGISNULL(1))
5028  *oldsum = *oldsum + (int64) PG_GETARG_INT32(1);
5029 
5030  PG_RETURN_POINTER(oldsum);
5031  }
5032  else
5033 #endif
5034  {
5035  int64 oldsum = PG_GETARG_INT64(0);
5036 
5037  /* Leave sum unchanged if new input is null. */
5038  if (PG_ARGISNULL(1))
5039  PG_RETURN_INT64(oldsum);
5040 
5041  /* OK to do the addition. */
5042  newval = oldsum + (int64) PG_GETARG_INT32(1);
5043 
5044  PG_RETURN_INT64(newval);
5045  }
5046 }
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:305
#define PG_GETARG_INT32(n)
Definition: fmgr.h:225
#define PG_RETURN_INT64(x)
Definition: fmgr.h:311
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:232
#define PG_ARGISNULL(n)
Definition: fmgr.h:166
#define NULL
Definition: c.h:226
#define newval
int AggCheckCallContext(FunctionCallInfo fcinfo, MemoryContext *aggcontext)
Definition: nodeAgg.c:3660
#define PG_GETARG_INT64(n)
Definition: fmgr.h:238
#define PG_RETURN_NULL()
Definition: fmgr.h:289
static void int64_to_numericvar ( int64  val,
NumericVar var 
)
static

Definition at line 6153 of file numeric.c.

References alloc_var(), DEC_DIGITS, NumericVar::digits, NumericVar::dscale, NBASE, NumericVar::ndigits, NUMERIC_NEG, NUMERIC_POS, NumericVar::sign, val, and NumericVar::weight.

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

6154 {
6155  uint64 uval,
6156  newuval;
6157  NumericDigit *ptr;
6158  int ndigits;
6159 
6160  /* int64 can require at most 19 decimal digits; add one for safety */
6161  alloc_var(var, 20 / DEC_DIGITS);
6162  if (val < 0)
6163  {
6164  var->sign = NUMERIC_NEG;
6165  uval = -val;
6166  }
6167  else
6168  {
6169  var->sign = NUMERIC_POS;
6170  uval = val;
6171  }
6172  var->dscale = 0;
6173  if (val == 0)
6174  {
6175  var->ndigits = 0;
6176  var->weight = 0;
6177  return;
6178  }
6179  ptr = var->digits + var->ndigits;
6180  ndigits = 0;
6181  do
6182  {
6183  ptr--;
6184  ndigits++;
6185  newuval = uval / NBASE;
6186  *ptr = uval - newuval * NBASE;
6187  uval = newuval;
6188  } while (uval);
6189  var->digits = ptr;
6190  var->ndigits = ndigits;
6191  var->weight = ndigits - 1;
6192 }
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:5388
#define DEC_DIGITS
Definition: numeric.c:95
long val
Definition: informix.c:689
Datum int8_accum ( PG_FUNCTION_ARGS  )

Definition at line 3991 of file numeric.c.

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

3992 {
3994 
3995  state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
3996 
3997  /* Create the state data on the first call */
3998  if (state == NULL)
3999  state = makeNumericAggState(fcinfo, true);
4000 
4001  if (!PG_ARGISNULL(1))
4002  {
4003  Numeric newval;
4004 
4006  PG_GETARG_DATUM(1)));
4007  do_numeric_accum(state, newval);
4008  }
4009 
4010  PG_RETURN_POINTER(state);
4011 }
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:305
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:224
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:232
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:555
Datum int8_numeric(PG_FUNCTION_ARGS)
Definition: numeric.c:2968
static NumericAggState * makeNumericAggState(FunctionCallInfo fcinfo, bool calcSumX2)
Definition: numeric.c:3209
static void do_numeric_accum(NumericAggState *state, Numeric newval)
Definition: numeric.c:3249
#define PG_ARGISNULL(n)
Definition: fmgr.h:166
#define DatumGetNumeric(X)
Definition: numeric.h:49
#define NULL
Definition: c.h:226
Definition: regguts.h:298
#define newval
Datum int8_accum_inv ( PG_FUNCTION_ARGS  )

Definition at line 4472 of file numeric.c.

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

4473 {
4475 
4476  state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
4477 
4478  /* Should not get here with no state */
4479  if (state == NULL)
4480  elog(ERROR, "int8_accum_inv called with NULL state");
4481 
4482  if (!PG_ARGISNULL(1))
4483  {
4484  Numeric newval;
4485 
4487  PG_GETARG_DATUM(1)));
4488 
4489  /* Should never fail, all inputs have dscale 0 */
4490  if (!do_numeric_discard(state, newval))
4491  elog(ERROR, "do_numeric_discard failed unexpectedly");
4492  }
4493 
4494  PG_RETURN_POINTER(state);
4495 }
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:305
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:224
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:232
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:555
static bool do_numeric_discard(NumericAggState *state, Numeric newval)
Definition: numeric.c:3314
Datum int8_numeric(PG_FUNCTION_ARGS)
Definition: numeric.c:2968
#define ERROR
Definition: elog.h:43
#define PG_ARGISNULL(n)
Definition: fmgr.h:166
#define DatumGetNumeric(X)
Definition: numeric.h:49
#define NULL
Definition: c.h:226
Definition: regguts.h:298
#define newval
#define elog
Definition: elog.h:219
Datum int8_avg ( PG_FUNCTION_ARGS  )

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

5247 {
5248  ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
5249  Int8TransTypeData *transdata;
5250  Datum countd,
5251  sumd;
5252 
5253  if (ARR_HASNULL(transarray) ||
5254  ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
5255  elog(ERROR, "expected 2-element int8 array");
5256  transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
5257 
5258  /* SQL defines AVG of no values to be NULL */
5259  if (transdata->count == 0)
5260  PG_RETURN_NULL();
5261 
5263  Int64GetDatumFast(transdata->count));
5265  Int64GetDatumFast(transdata->sum));
5266 
5268 }
#define ARR_OVERHEAD_NONULLS(ndims)
Definition: array.h:291
#define ARR_SIZE(a)
Definition: array.h:270
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:555
Datum int8_numeric(PG_FUNCTION_ARGS)
Definition: numeric.c:2968
Datum numeric_div(PG_FUNCTION_ARGS)
Definition: numeric.c:2366
#define PG_GETARG_ARRAYTYPE_P(n)
Definition: array.h:244
#define ERROR
Definition: elog.h:43
#define ARR_DATA_PTR(a)
Definition: array.h:303
#define ARR_HASNULL(a)
Definition: array.h:272
uintptr_t Datum
Definition: postgres.h:374
#define PG_RETURN_DATUM(x)
Definition: fmgr.h:297
#define Int64GetDatumFast(X)
Definition: postgres.h:783
#define elog
Definition: elog.h:219
#define DirectFunctionCall2(func, arg1, arg2)
Definition: fmgr.h:557
#define PG_RETURN_NULL()
Definition: fmgr.h:289
Datum int8_avg_accum ( PG_FUNCTION_ARGS  )

Definition at line 4216 of file numeric.c.

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

4217 {
4219 
4220  state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
4221 
4222  /* Create the state data on the first call */
4223  if (state == NULL)
4224  state = makePolyNumAggState(fcinfo, false);
4225 
4226  if (!PG_ARGISNULL(1))
4227  {
4228 #ifdef HAVE_INT128
4229  do_int128_accum(state, (int128) PG_GETARG_INT64(1));
4230 #else
4231  Numeric newval;
4232 
4234  PG_GETARG_DATUM(1)));
4235  do_numeric_accum(state, newval);
4236 #endif
4237  }
4238 
4239  PG_RETURN_POINTER(state);
4240 }
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:305
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:224
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:232
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:555
Datum int8_numeric(PG_FUNCTION_ARGS)
Definition: numeric.c:2968
static void do_numeric_accum(NumericAggState *state, Numeric newval)
Definition: numeric.c:3249
#define PG_ARGISNULL(n)
Definition: fmgr.h:166
#define DatumGetNumeric(X)
Definition: numeric.h:49
#define NULL
Definition: c.h:226
Definition: regguts.h:298
#define newval
#define PG_GETARG_INT64(n)
Definition: fmgr.h:238
#define makePolyNumAggState
Definition: numeric.c:3932
Datum int8_avg_accum_inv ( PG_FUNCTION_ARGS  )

Definition at line 4498 of file numeric.c.

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

4499 {
4501 
4502  state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
4503 
4504  /* Should not get here with no state */
4505  if (state == NULL)
4506  elog(ERROR, "int8_avg_accum_inv called with NULL state");
4507 
4508  if (!PG_ARGISNULL(1))
4509  {
4510 #ifdef HAVE_INT128
4511  do_int128_discard(state, (int128) PG_GETARG_INT64(1));
4512 #else
4513  Numeric newval;
4514 
4516  PG_GETARG_DATUM(1)));
4517 
4518  /* Should never fail, all inputs have dscale 0 */
4519  if (!do_numeric_discard(state, newval))
4520  elog(ERROR, "do_numeric_discard failed unexpectedly");
4521 #endif
4522  }
4523 
4524  PG_RETURN_POINTER(state);
4525 }
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:305
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:224
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:232
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:555
static bool do_numeric_discard(NumericAggState *state, Numeric newval)
Definition: numeric.c:3314
Datum int8_numeric(PG_FUNCTION_ARGS)
Definition: numeric.c:2968
#define ERROR
Definition: elog.h:43
#define PG_ARGISNULL(n)
Definition: fmgr.h:166
#define DatumGetNumeric(X)
Definition: numeric.h:49
#define NULL
Definition: c.h:226
Definition: regguts.h:298
#define newval
#define elog
Definition: elog.h:219
#define PG_GETARG_INT64(n)
Definition: fmgr.h:238
Datum int8_avg_combine ( PG_FUNCTION_ARGS  )

Definition at line 4247 of file numeric.c.

References accum_sum_combine(), accum_sum_copy(), AggCheckCallContext(), elog, ERROR, makePolyNumAggState, MemoryContextSwitchTo(), NumericAggState::N, NULL, PG_ARGISNULL, PG_GETARG_POINTER, PG_RETURN_POINTER, and NumericAggState::sumX.

4248 {
4249  PolyNumAggState *state1;
4250  PolyNumAggState *state2;
4251  MemoryContext agg_context;
4252  MemoryContext old_context;
4253 
4254  if (!AggCheckCallContext(fcinfo, &agg_context))
4255  elog(ERROR, "aggregate function called in non-aggregate context");
4256 
4257  state1 = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
4258  state2 = PG_ARGISNULL(1) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(1);
4259 
4260  if (state2 == NULL)
4261  PG_RETURN_POINTER(state1);
4262 
4263  /* manually copy all fields from state2 to state1 */
4264  if (state1 == NULL)
4265  {
4266  old_context = MemoryContextSwitchTo(agg_context);
4267 
4268  state1 = makePolyNumAggState(fcinfo, false);
4269  state1->N = state2->N;
4270 
4271 #ifdef HAVE_INT128
4272  state1->sumX = state2->sumX;
4273 #else
4274  accum_sum_copy(&state1->sumX, &state2->sumX);
4275 #endif
4276  MemoryContextSwitchTo(old_context);
4277 
4278  PG_RETURN_POINTER(state1);
4279  }
4280 
4281  if (state2->N > 0)
4282  {
4283  state1->N += state2->N;
4284 
4285 #ifdef HAVE_INT128
4286  state1->sumX += state2->sumX;
4287 #else
4288  /* The rest of this needs to work in the aggregate context */
4289  old_context = MemoryContextSwitchTo(agg_context);
4290 
4291  /* Accumulate sums */
4292  accum_sum_combine(&state1->sumX, &state2->sumX);
4293 
4294  MemoryContextSwitchTo(old_context);
4295 #endif
4296 
4297  }
4298  PG_RETURN_POINTER(state1);
4299 }
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:305
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:232
#define ERROR
Definition: elog.h:43
static void accum_sum_copy(NumericSumAccum *dst, NumericSumAccum *src)
Definition: numeric.c:9076
#define PG_ARGISNULL(n)
Definition: fmgr.h:166
#define NULL
Definition: c.h:226
static void accum_sum_combine(NumericSumAccum *accum, NumericSumAccum *accum2)
Definition: numeric.c:9093
int AggCheckCallContext(FunctionCallInfo fcinfo, MemoryContext *aggcontext)
Definition: nodeAgg.c:3660
#define elog
Definition: elog.h:219
NumericSumAccum sumX
Definition: numeric.c:3197
#define makePolyNumAggState
Definition: numeric.c:3932
Datum int8_avg_deserialize ( PG_FUNCTION_ARGS  )

Definition at line 4364 of file numeric.c.

References accum_sum_add(), AggCheckCallContext(), appendBinaryStringInfo(), buf, StringInfoData::data, DatumGetNumeric, DirectFunctionCall3, elog, ERROR, init_var_from_num(), initStringInfo(), InvalidOid, makePolyNumAggStateCurrentContext, NumericAggState::N, NULL, numeric_recv(), pfree(), PG_GETARG_BYTEA_P, PG_RETURN_POINTER, PointerGetDatum, pq_getmsgend(), pq_getmsgint64(), NumericAggState::sumX, VARDATA, VARHDRSZ, and VARSIZE.

4365 {
4366  bytea *sstate;
4367  PolyNumAggState *result;
4369  Datum temp;
4370  NumericVar num;
4371 
4372  if (!AggCheckCallContext(fcinfo, NULL))
4373  elog(ERROR, "aggregate function called in non-aggregate context");
4374 
4375  sstate = PG_GETARG_BYTEA_P(0);
4376 
4377  /*
4378  * Copy the bytea into a StringInfo so that we can "receive" it using the
4379  * standard recv-function infrastructure.
4380  */
4381  initStringInfo(&buf);
4382  appendBinaryStringInfo(&buf, VARDATA(sstate), VARSIZE(sstate) - VARHDRSZ);
4383 
4384  result = makePolyNumAggStateCurrentContext(false);
4385 
4386  /* N */
4387  result->N = pq_getmsgint64(&buf);
4388 
4389  /* sumX */
4391  PointerGetDatum(&buf),
4392  InvalidOid,
4393  -1);
4394  init_var_from_num(DatumGetNumeric(temp), &num);
4395 #ifdef HAVE_INT128
4396  numericvar_to_int128(&num, &result->sumX);
4397 #else
4398  accum_sum_add(&result->sumX, &num);
4399 #endif
4400 
4401  pq_getmsgend(&buf);
4402  pfree(buf.data);
4403 
4404  PG_RETURN_POINTER(result);
4405 }
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:305
#define VARDATA(PTR)
Definition: postgres.h:305
#define VARSIZE(PTR)
Definition: postgres.h:306
#define PointerGetDatum(X)
Definition: postgres.h:564
#define VARHDRSZ
Definition: c.h:441
#define PG_GETARG_BYTEA_P(n)
Definition: fmgr.h:267
void pfree(void *pointer)
Definition: mcxt.c:992
#define makePolyNumAggStateCurrentContext
Definition: numeric.c:3933
#define ERROR
Definition: elog.h:43
static void init_var_from_num(Numeric num, NumericVar *dest)
Definition: numeric.c:5637
static char * buf
Definition: pg_test_fsync.c:65
#define DirectFunctionCall3(func, arg1, arg2, arg3)
Definition: fmgr.h:559
void initStringInfo(StringInfo str)
Definition: stringinfo.c:65
uintptr_t Datum
Definition: postgres.h:374