1 /*-------------------------------------------------------------------------
2 *
3 * numeric.c
4 * An exact numeric data type for the Postgres database system
5 *
6 * Original coding 1998, Jan Wieck. Heavily revised 2003, Tom Lane.
7 *
8 * Many of the algorithmic ideas are borrowed from David M. Smith's "FM"
9 * multiple-precision math library, most recently published as Algorithm
10 * 786: Multiple-Precision Complex Arithmetic and Functions, ACM
11 * Transactions on Mathematical Software, Vol. 24, No. 4, December 1998,
12 * pages 359-367.
13 *
14 * Copyright (c) 1998-2017, PostgreSQL Global Development Group
15 *
16 * IDENTIFICATION
17 * src/backend/utils/adt/numeric.c
18 *
19 *-------------------------------------------------------------------------
20 */
21
22 #include "postgres.h"
23
24 #include <ctype.h>
25 #include <float.h>
26 #include <limits.h>
27 #include <math.h>
28
29 #include "access/hash.h"
30 #include "catalog/pg_type.h"
31 #include "funcapi.h"
32 #include "lib/hyperloglog.h"
33 #include "libpq/pqformat.h"
34 #include "miscadmin.h"
35 #include "nodes/nodeFuncs.h"
36 #include "utils/array.h"
37 #include "utils/builtins.h"
38 #include "utils/guc.h"
39 #include "utils/int8.h"
40 #include "utils/numeric.h"
41 #include "utils/sortsupport.h"
42
43 /* ----------
44 * Uncomment the following to enable compilation of dump_numeric()
45 * and dump_var() and to get a dump of any result produced by make_result().
46 * ----------
47 #define NUMERIC_DEBUG
48 */
49
50
51 /* ----------
52 * Local data types
53 *
54 * Numeric values are represented in a base-NBASE floating point format.
55 * Each "digit" ranges from 0 to NBASE-1. The type NumericDigit is signed
56 * and wide enough to store a digit. We assume that NBASE*NBASE can fit in
57 * an int. Although the purely calculational routines could handle any even
58 * NBASE that's less than sqrt(INT_MAX), in practice we are only interested
59 * in NBASE a power of ten, so that I/O conversions and decimal rounding
60 * are easy. Also, it's actually more efficient if NBASE is rather less than
61 * sqrt(INT_MAX), so that there is "headroom" for mul_var and div_var_fast to
62 * postpone processing carries.
63 *
64 * Values of NBASE other than 10000 are considered of historical interest only
65 * and are no longer supported in any sense; no mechanism exists for the client
66 * to discover the base, so every client supporting binary mode expects the
67 * base-10000 format. If you plan to change this, also note the numeric
68 * abbreviation code, which assumes NBASE=10000.
69 * ----------
70 */
71
72 #if 0
73 #define NBASE 10
74 #define HALF_NBASE 5
75 #define DEC_DIGITS 1 /* decimal digits per NBASE digit */
76 #define MUL_GUARD_DIGITS 4 /* these are measured in NBASE digits */
77 #define DIV_GUARD_DIGITS 8
78
79 typedef signed char NumericDigit;
80 #endif
81
82 #if 0
83 #define NBASE 100
84 #define HALF_NBASE 50
85 #define DEC_DIGITS 2 /* decimal digits per NBASE digit */
86 #define MUL_GUARD_DIGITS 3 /* these are measured in NBASE digits */
87 #define DIV_GUARD_DIGITS 6
88
89 typedef signed char NumericDigit;
90 #endif
91
92 #if 1
93 #define NBASE 10000
94 #define HALF_NBASE 5000
95 #define DEC_DIGITS 4 /* decimal digits per NBASE digit */
96 #define MUL_GUARD_DIGITS 2 /* these are measured in NBASE digits */
97 #define DIV_GUARD_DIGITS 4
98
99 typedef int16 NumericDigit;
100 #endif
101
102 /*
103 * The Numeric type as stored on disk.
104 *
105 * If the high bits of the first word of a NumericChoice (n_header, or
106 * n_short.n_header, or n_long.n_sign_dscale) are NUMERIC_SHORT, then the
107 * numeric follows the NumericShort format; if they are NUMERIC_POS or
108 * NUMERIC_NEG, it follows the NumericLong format. If they are NUMERIC_NAN,
109 * it is a NaN. We currently always store a NaN using just two bytes (i.e.
110 * only n_header), but previous releases used only the NumericLong format,
111 * so we might find 4-byte NaNs on disk if a database has been migrated using
112 * pg_upgrade. In either case, when the high bits indicate a NaN, the
113 * remaining bits are never examined. Currently, we always initialize these
114 * to zero, but it might be possible to use them for some other purpose in
115 * the future.
116 *
117 * In the NumericShort format, the remaining 14 bits of the header word
118 * (n_short.n_header) are allocated as follows: 1 for sign (positive or
119 * negative), 6 for dynamic scale, and 7 for weight. In practice, most
120 * commonly-encountered values can be represented this way.
121 *
122 * In the NumericLong format, the remaining 14 bits of the header word
123 * (n_long.n_sign_dscale) represent the display scale; and the weight is
124 * stored separately in n_weight.
125 *
126 * NOTE: by convention, values in the packed form have been stripped of
127 * all leading and trailing zero digits (where a "digit" is of base NBASE).
128 * In particular, if the value is zero, there will be no digits at all!
129 * The weight is arbitrary in that case, but we normally set it to zero.
130 */
131
132 struct NumericShort
133 {
134 uint16 n_header; /* Sign + display scale + weight */
135 NumericDigit n_data[FLEXIBLE_ARRAY_MEMBER]; /* Digits */
136 };
137
138 struct NumericLong
139 {
140 uint16 n_sign_dscale; /* Sign + display scale */
141 int16 n_weight; /* Weight of 1st digit */
142 NumericDigit n_data[FLEXIBLE_ARRAY_MEMBER]; /* Digits */
143 };
144
145 union NumericChoice
146 {
147 uint16 n_header; /* Header word */
148 struct NumericLong n_long; /* Long form (4-byte header) */
149 struct NumericShort n_short; /* Short form (2-byte header) */
150 };
151
152 struct NumericData
153 {
154 int32 vl_len_; /* varlena header (do not touch directly!) */
155 union NumericChoice choice; /* choice of format */
156 };
157
158
159 /*
160 * Interpretation of high bits.
161 */
162
163 #define NUMERIC_SIGN_MASK 0xC000
164 #define NUMERIC_POS 0x0000
165 #define NUMERIC_NEG 0x4000
166 #define NUMERIC_SHORT 0x8000
167 #define NUMERIC_NAN 0xC000
168
169 #define NUMERIC_FLAGBITS(n) ((n)->choice.n_header & NUMERIC_SIGN_MASK)
170 #define NUMERIC_IS_NAN(n) (NUMERIC_FLAGBITS(n) == NUMERIC_NAN)
171 #define NUMERIC_IS_SHORT(n) (NUMERIC_FLAGBITS(n) == NUMERIC_SHORT)
172
173 #define NUMERIC_HDRSZ (VARHDRSZ + sizeof(uint16) + sizeof(int16))
174 #define NUMERIC_HDRSZ_SHORT (VARHDRSZ + sizeof(uint16))
175
176 /*
177 * If the flag bits are NUMERIC_SHORT or NUMERIC_NAN, we want the short header;
178 * otherwise, we want the long one. Instead of testing against each value, we
179 * can just look at the high bit, for a slight efficiency gain.
180 */
181 #define NUMERIC_HEADER_IS_SHORT(n) (((n)->choice.n_header & 0x8000) != 0)
182 #define NUMERIC_HEADER_SIZE(n) \
183 (VARHDRSZ + sizeof(uint16) + \
184 (NUMERIC_HEADER_IS_SHORT(n) ? 0 : sizeof(int16)))
185
186 /*
187 * Short format definitions.
188 */
189
190 #define NUMERIC_SHORT_SIGN_MASK 0x2000
191 #define NUMERIC_SHORT_DSCALE_MASK 0x1F80
192 #define NUMERIC_SHORT_DSCALE_SHIFT 7
193 #define NUMERIC_SHORT_DSCALE_MAX \
194 (NUMERIC_SHORT_DSCALE_MASK >> NUMERIC_SHORT_DSCALE_SHIFT)
195 #define NUMERIC_SHORT_WEIGHT_SIGN_MASK 0x0040
196 #define NUMERIC_SHORT_WEIGHT_MASK 0x003F
197 #define NUMERIC_SHORT_WEIGHT_MAX NUMERIC_SHORT_WEIGHT_MASK
198 #define NUMERIC_SHORT_WEIGHT_MIN (-(NUMERIC_SHORT_WEIGHT_MASK+1))
199
200 /*
201 * Extract sign, display scale, weight.
202 */
203
204 #define NUMERIC_DSCALE_MASK 0x3FFF
205 #define NUMERIC_DSCALE_MAX NUMERIC_DSCALE_MASK
206
207 #define NUMERIC_SIGN(n) \
208 (NUMERIC_IS_SHORT(n) ? \
209 (((n)->choice.n_short.n_header & NUMERIC_SHORT_SIGN_MASK) ? \
210 NUMERIC_NEG : NUMERIC_POS) : NUMERIC_FLAGBITS(n))
211 #define NUMERIC_DSCALE(n) (NUMERIC_HEADER_IS_SHORT((n)) ? \
212 ((n)->choice.n_short.n_header & NUMERIC_SHORT_DSCALE_MASK) \
213 >> NUMERIC_SHORT_DSCALE_SHIFT \
214 : ((n)->choice.n_long.n_sign_dscale & NUMERIC_DSCALE_MASK))
215 #define NUMERIC_WEIGHT(n) (NUMERIC_HEADER_IS_SHORT((n)) ? \
216 (((n)->choice.n_short.n_header & NUMERIC_SHORT_WEIGHT_SIGN_MASK ? \
217 ~NUMERIC_SHORT_WEIGHT_MASK : 0) \
218 | ((n)->choice.n_short.n_header & NUMERIC_SHORT_WEIGHT_MASK)) \
219 : ((n)->choice.n_long.n_weight))
220
221 /* ----------
222 * NumericVar is the format we use for arithmetic. The digit-array part
223 * is the same as the NumericData storage format, but the header is more
224 * complex.
225 *
226 * The value represented by a NumericVar is determined by the sign, weight,
227 * ndigits, and digits[] array.
228 *
229 * Note: the first digit of a NumericVar's value is assumed to be multiplied
230 * by NBASE ** weight. Another way to say it is that there are weight+1
231 * digits before the decimal point. It is possible to have weight < 0.
232 *
233 * buf points at the physical start of the palloc'd digit buffer for the
234 * NumericVar. digits points at the first digit in actual use (the one
235 * with the specified weight). We normally leave an unused digit or two
236 * (preset to zeroes) between buf and digits, so that there is room to store
237 * a carry out of the top digit without reallocating space. We just need to
238 * decrement digits (and increment weight) to make room for the carry digit.
239 * (There is no such extra space in a numeric value stored in the database,
240 * only in a NumericVar in memory.)
241 *
242 * If buf is NULL then the digit buffer isn't actually palloc'd and should
243 * not be freed --- see the constants below for an example.
244 *
245 * dscale, or display scale, is the nominal precision expressed as number
246 * of digits after the decimal point (it must always be >= 0 at present).
247 * dscale may be more than the number of physically stored fractional digits,
248 * implying that we have suppressed storage of significant trailing zeroes.
249 * It should never be less than the number of stored digits, since that would
250 * imply hiding digits that are present. NOTE that dscale is always expressed
251 * in *decimal* digits, and so it may correspond to a fractional number of
252 * base-NBASE digits --- divide by DEC_DIGITS to convert to NBASE digits.
253 *
254 * rscale, or result scale, is the target precision for a computation.
255 * Like dscale it is expressed as number of *decimal* digits after the decimal
256 * point, and is always >= 0 at present.
257 * Note that rscale is not stored in variables --- it's figured on-the-fly
258 * from the dscales of the inputs.
259 *
260 * While we consistently use "weight" to refer to the base-NBASE weight of
261 * a numeric value, it is convenient in some scale-related calculations to
262 * make use of the base-10 weight (ie, the approximate log10 of the value).
263 * To avoid confusion, such a decimal-units weight is called a "dweight".
264 *
265 * NB: All the variable-level functions are written in a style that makes it
266 * possible to give one and the same variable as argument and destination.
267 * This is feasible because the digit buffer is separate from the variable.
268 * ----------
269 */
270 typedef struct NumericVar
271 {
272 int ndigits; /* # of digits in digits[] - can be 0! */
273 int weight; /* weight of first digit */
274 int sign; /* NUMERIC_POS, NUMERIC_NEG, or NUMERIC_NAN */
275 int dscale; /* display scale */
276 NumericDigit *buf; /* start of palloc'd space for digits[] */
277 NumericDigit *digits; /* base-NBASE digits */
278 } NumericVar;
279
280
281 /* ----------
282 * Data for generate_series
283 * ----------
284 */
285 typedef struct
286 {
287 NumericVar current;
288 NumericVar stop;
289 NumericVar step;
290 } generate_series_numeric_fctx;
291
292
293 /* ----------
294 * Sort support.
295 * ----------
296 */
297 typedef struct
298 {
299 void *buf; /* buffer for short varlenas */
300 int64 input_count; /* number of non-null values seen */
301 bool estimating; /* true if estimating cardinality */
302
303 hyperLogLogState abbr_card; /* cardinality estimator */
304 } NumericSortSupport;
305
306
307 /* ----------
308 * Fast sum accumulator.
309 *
310 * NumericSumAccum is used to implement SUM(), and other standard aggregates
311 * that track the sum of input values. It uses 32-bit integers to store the
312 * digits, instead of the normal 16-bit integers (with NBASE=10000). This
313 * way, we can safely accumulate up to NBASE - 1 values without propagating
314 * carry, before risking overflow of any of the digits. 'num_uncarried'
315 * tracks how many values have been accumulated without propagating carry.
316 *
317 * Positive and negative values are accumulated separately, in 'pos_digits'
318 * and 'neg_digits'. This is simpler and faster than deciding whether to add
319 * or subtract from the current value, for each new value (see sub_var() for
320 * the logic we avoid by doing this). Both buffers are of same size, and
321 * have the same weight and scale. In accum_sum_final(), the positive and
322 * negative sums are added together to produce the final result.
323 *
324 * When a new value has a larger ndigits or weight than the accumulator
325 * currently does, the accumulator is enlarged to accommodate the new value.
326 * We normally have one zero digit reserved for carry propagation, and that
327 * is indicated by the 'have_carry_space' flag. When accum_sum_carry() uses
328 * up the reserved digit, it clears the 'have_carry_space' flag. The next
329 * call to accum_sum_add() will enlarge the buffer, to make room for the
330 * extra digit, and set the flag again.
331 *
332 * To initialize a new accumulator, simply reset all fields to zeros.
333 *
334 * The accumulator does not handle NaNs.
335 * ----------
336 */
337 typedef struct NumericSumAccum
338 {
339 int ndigits;
340 int weight;
341 int dscale;
342 int num_uncarried;
343 bool have_carry_space;
344 int32 *pos_digits;
345 int32 *neg_digits;
346 } NumericSumAccum;
347
348
349 /*
350 * We define our own macros for packing and unpacking abbreviated-key
351 * representations for numeric values in order to avoid depending on
352 * USE_FLOAT8_BYVAL. The type of abbreviation we use is based only on
353 * the size of a datum, not the argument-passing convention for float8.
354 */
355 #define NUMERIC_ABBREV_BITS (SIZEOF_DATUM * BITS_PER_BYTE)
356 #if SIZEOF_DATUM == 8
357 #define NumericAbbrevGetDatum(X) ((Datum) SET_8_BYTES(X))
358 #define DatumGetNumericAbbrev(X) ((int64) GET_8_BYTES(X))
359 #define NUMERIC_ABBREV_NAN NumericAbbrevGetDatum(PG_INT64_MIN)
360 #else
361 #define NumericAbbrevGetDatum(X) ((Datum) SET_4_BYTES(X))
362 #define DatumGetNumericAbbrev(X) ((int32) GET_4_BYTES(X))
363 #define NUMERIC_ABBREV_NAN NumericAbbrevGetDatum(PG_INT32_MIN)
364 #endif
365
366
367 /* ----------
368 * Some preinitialized constants
369 * ----------
370 */
371 static NumericDigit const_zero_data[1] = {0};
372 static NumericVar const_zero =
373 {0, 0, NUMERIC_POS, 0, NULL, const_zero_data};
374
375 static NumericDigit const_one_data[1] = {1};
376 static NumericVar const_one =
377 {1, 0, NUMERIC_POS, 0, NULL, const_one_data};
378
379 static NumericDigit const_two_data[1] = {2};
380 static NumericVar const_two =
381 {1, 0, NUMERIC_POS, 0, NULL, const_two_data};
382
383 #if DEC_DIGITS == 4
384 static NumericDigit const_zero_point_five_data[1] = {5000};
385 #elif DEC_DIGITS == 2
386 static NumericDigit const_zero_point_five_data[1] = {50};
387 #elif DEC_DIGITS == 1
388 static NumericDigit const_zero_point_five_data[1] = {5};
389 #endif
390 static NumericVar const_zero_point_five =
391 {1, -1, NUMERIC_POS, 1, NULL, const_zero_point_five_data};
392
393 #if DEC_DIGITS == 4
394 static NumericDigit const_zero_point_nine_data[1] = {9000};
395 #elif DEC_DIGITS == 2
396 static NumericDigit const_zero_point_nine_data[1] = {90};
397 #elif DEC_DIGITS == 1
398 static NumericDigit const_zero_point_nine_data[1] = {9};
399 #endif
400 static NumericVar const_zero_point_nine =
401 {1, -1, NUMERIC_POS, 1, NULL, const_zero_point_nine_data};
402
403 #if DEC_DIGITS == 4
404 static NumericDigit const_one_point_one_data[2] = {1, 1000};
405 #elif DEC_DIGITS == 2
406 static NumericDigit const_one_point_one_data[2] = {1, 10};
407 #elif DEC_DIGITS == 1
408 static NumericDigit const_one_point_one_data[2] = {1, 1};
409 #endif
410 static NumericVar const_one_point_one =
411 {2, 0, NUMERIC_POS, 1, NULL, const_one_point_one_data};
412
413 static NumericVar const_nan =
414 {0, 0, NUMERIC_NAN, 0, NULL, NULL};
415
416 #if DEC_DIGITS == 4
417 static const int round_powers[4] = {0, 1000, 100, 10};
418 #endif
419
420
421 /* ----------
422 * Local functions
423 * ----------
424 */
425
426 #ifdef NUMERIC_DEBUG
427 static void dump_numeric(const char *str, Numeric num);
428 static void dump_var(const char *str, NumericVar *var);
429 #else
430 #define dump_numeric(s,n)
431 #define dump_var(s,v)
432 #endif
433
434 #define digitbuf_alloc(ndigits) \
435 ((NumericDigit *) palloc((ndigits) * sizeof(NumericDigit)))
436 #define digitbuf_free(buf) \
437 do { \
438 if ((buf) != NULL) \
439 pfree(buf); \
440 } while (0)
441
442 #define init_var(v) MemSetAligned(v, 0, sizeof(NumericVar))
443
444 #define NUMERIC_DIGITS(num) (NUMERIC_HEADER_IS_SHORT(num) ? \
445 (num)->choice.n_short.n_data : (num)->choice.n_long.n_data)
446 #define NUMERIC_NDIGITS(num) \
447 ((VARSIZE(num) - NUMERIC_HEADER_SIZE(num)) / sizeof(NumericDigit))
448 #define NUMERIC_CAN_BE_SHORT(scale,weight) \
449 ((scale) <= NUMERIC_SHORT_DSCALE_MAX && \
450 (weight) <= NUMERIC_SHORT_WEIGHT_MAX && \
451 (weight) >= NUMERIC_SHORT_WEIGHT_MIN)
452
453 static void alloc_var(NumericVar *var, int ndigits);
454 static void free_var(NumericVar *var);
455 static void zero_var(NumericVar *var);
456
457 static const char *set_var_from_str(const char *str, const char *cp,
458 NumericVar *dest);
459 static void set_var_from_num(Numeric value, NumericVar *dest);
460 static void init_var_from_num(Numeric num, NumericVar *dest);
461 static void set_var_from_var(NumericVar *value, NumericVar *dest);
462 static char *get_str_from_var(NumericVar *var);
463 static char *get_str_from_var_sci(NumericVar *var, int rscale);
464
465 static Numeric make_result(NumericVar *var);
466
467 static void apply_typmod(NumericVar *var, int32 typmod);
468
469 static int32 numericvar_to_int32(NumericVar *var);
470 static bool numericvar_to_int64(NumericVar *var, int64 *result);
471 static void int64_to_numericvar(int64 val, NumericVar *var);
472 #ifdef HAVE_INT128
473 static bool numericvar_to_int128(NumericVar *var, int128 *result);
474 static void int128_to_numericvar(int128 val, NumericVar *var);
475 #endif
476 static double numeric_to_double_no_overflow(Numeric num);
477 static double numericvar_to_double_no_overflow(NumericVar *var);
478
479 static Datum numeric_abbrev_convert(Datum original_datum, SortSupport ssup);
480 static bool numeric_abbrev_abort(int memtupcount, SortSupport ssup);
481 static int numeric_fast_cmp(Datum x, Datum y, SortSupport ssup);
482 static int numeric_cmp_abbrev(Datum x, Datum y, SortSupport ssup);
483
484 static Datum numeric_abbrev_convert_var(NumericVar *var, NumericSortSupport *nss);
485
486 static int cmp_numerics(Numeric num1, Numeric num2);
487 static int cmp_var(NumericVar *var1, NumericVar *var2);
488 static int cmp_var_common(const NumericDigit *var1digits, int var1ndigits,
489 int var1weight, int var1sign,
490 const NumericDigit *var2digits, int var2ndigits,
491 int var2weight, int var2sign);
492 static void add_var(NumericVar *var1, NumericVar *var2, NumericVar *result);
493 static void sub_var(NumericVar *var1, NumericVar *var2, NumericVar *result);
494 static void mul_var(NumericVar *var1, NumericVar *var2, NumericVar *result,
495 int rscale);
496 static void div_var(NumericVar *var1, NumericVar *var2, NumericVar *result,
497 int rscale, bool round);
498 static void div_var_fast(NumericVar *var1, NumericVar *var2, NumericVar *result,
499 int rscale, bool round);
500 static int select_div_scale(NumericVar *var1, NumericVar *var2);
501 static void mod_var(NumericVar *var1, NumericVar *var2, NumericVar *result);
502 static void ceil_var(NumericVar *var, NumericVar *result);
503 static void floor_var(NumericVar *var, NumericVar *result);
504
505 static void sqrt_var(NumericVar *arg, NumericVar *result, int rscale);
506 static void exp_var(NumericVar *arg, NumericVar *result, int rscale);
507 static int estimate_ln_dweight(NumericVar *var);
508 static void ln_var(NumericVar *arg, NumericVar *result, int rscale);
509 static void log_var(NumericVar *base, NumericVar *num, NumericVar *result);
510 static void power_var(NumericVar *base, NumericVar *exp, NumericVar *result);
511 static void power_var_int(NumericVar *base, int exp, NumericVar *result,
512 int rscale);
513 static void power_ten_int(int exp, NumericVar *result);
514
515 static int cmp_abs(NumericVar *var1, NumericVar *var2);
516 static int cmp_abs_common(const NumericDigit *var1digits, int var1ndigits,
517 int var1weight,
518 const NumericDigit *var2digits, int var2ndigits,
519 int var2weight);
520 static void add_abs(NumericVar *var1, NumericVar *var2, NumericVar *result);
521 static void sub_abs(NumericVar *var1, NumericVar *var2, NumericVar *result);
522 static void round_var(NumericVar *var, int rscale);
523 static void trunc_var(NumericVar *var, int rscale);
524 static void strip_var(NumericVar *var);
525 static void compute_bucket(Numeric operand, Numeric bound1, Numeric bound2,
526 NumericVar *count_var, NumericVar *result_var);
527
528 static void accum_sum_add(NumericSumAccum *accum, NumericVar *var1);
529 static void accum_sum_rescale(NumericSumAccum *accum, NumericVar *val);
530 static void accum_sum_carry(NumericSumAccum *accum);
531 static void accum_sum_reset(NumericSumAccum *accum);
532 static void accum_sum_final(NumericSumAccum *accum, NumericVar *result);
533 static void accum_sum_copy(NumericSumAccum *dst, NumericSumAccum *src);
534 static void accum_sum_combine(NumericSumAccum *accum, NumericSumAccum *accum2);
535
536
537 /* ----------------------------------------------------------------------
538 *
539 * Input-, output- and rounding-functions
540 *
541 * ----------------------------------------------------------------------
542 */
543
544
545 /*
546 * numeric_in() -
547 *
548 * Input function for numeric data type
549 */
550 Datum
numeric_in(PG_FUNCTION_ARGS)551 numeric_in(PG_FUNCTION_ARGS)
552 {
553 char *str = PG_GETARG_CSTRING(0);
554
555 #ifdef NOT_USED
556 Oid typelem = PG_GETARG_OID(1);
557 #endif
558 int32 typmod = PG_GETARG_INT32(2);
559 Numeric res;
560 const char *cp;
561
562 /* Skip leading spaces */
563 cp = str;
564 while (*cp)
565 {
566 if (!isspace((unsigned char) *cp))
567 break;
568 cp++;
569 }
570
571 /*
572 * Check for NaN
573 */
574 if (pg_strncasecmp(cp, "NaN", 3) == 0)
575 {
576 res = make_result(&const_nan);
577
578 /* Should be nothing left but spaces */
579 cp += 3;
580 while (*cp)
581 {
582 if (!isspace((unsigned char) *cp))
583 ereport(ERROR,
584 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
585 errmsg("invalid input syntax for type %s: \"%s\"",
586 "numeric", str)));
587 cp++;
588 }
589 }
590 else
591 {
592 /*
593 * Use set_var_from_str() to parse a normal numeric value
594 */
595 NumericVar value;
596
597 init_var(&value);
598
599 cp = set_var_from_str(str, cp, &value);
600
601 /*
602 * We duplicate a few lines of code here because we would like to
603 * throw any trailing-junk syntax error before any semantic error
604 * resulting from apply_typmod. We can't easily fold the two cases
605 * together because we mustn't apply apply_typmod to a NaN.
606 */
607 while (*cp)
608 {
609 if (!isspace((unsigned char) *cp))
610 ereport(ERROR,
611 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
612 errmsg("invalid input syntax for type %s: \"%s\"",
613 "numeric", str)));
614 cp++;
615 }
616
617 apply_typmod(&value, typmod);
618
619 res = make_result(&value);
620 free_var(&value);
621 }
622
623 PG_RETURN_NUMERIC(res);
624 }
625
626
627 /*
628 * numeric_out() -
629 *
630 * Output function for numeric data type
631 */
632 Datum
numeric_out(PG_FUNCTION_ARGS)633 numeric_out(PG_FUNCTION_ARGS)
634 {
635 Numeric num = PG_GETARG_NUMERIC(0);
636 NumericVar x;
637 char *str;
638
639 /*
640 * Handle NaN
641 */
642 if (NUMERIC_IS_NAN(num))
643 PG_RETURN_CSTRING(pstrdup("NaN"));
644
645 /*
646 * Get the number in the variable format.
647 */
648 init_var_from_num(num, &x);
649
650 str = get_str_from_var(&x);
651
652 PG_RETURN_CSTRING(str);
653 }
654
655 /*
656 * numeric_is_nan() -
657 *
658 * Is Numeric value a NaN?
659 */
660 bool
numeric_is_nan(Numeric num)661 numeric_is_nan(Numeric num)
662 {
663 return NUMERIC_IS_NAN(num);
664 }
665
666 /*
667 * numeric_maximum_size() -
668 *
669 * Maximum size of a numeric with given typmod, or -1 if unlimited/unknown.
670 */
671 int32
numeric_maximum_size(int32 typmod)672 numeric_maximum_size(int32 typmod)
673 {
674 int precision;
675 int numeric_digits;
676
677 if (typmod < (int32) (VARHDRSZ))
678 return -1;
679
680 /* precision (ie, max # of digits) is in upper bits of typmod */
681 precision = ((typmod - VARHDRSZ) >> 16) & 0xffff;
682
683 /*
684 * This formula computes the maximum number of NumericDigits we could need
685 * in order to store the specified number of decimal digits. Because the
686 * weight is stored as a number of NumericDigits rather than a number of
687 * decimal digits, it's possible that the first NumericDigit will contain
688 * only a single decimal digit. Thus, the first two decimal digits can
689 * require two NumericDigits to store, but it isn't until we reach
690 * DEC_DIGITS + 2 decimal digits that we potentially need a third
691 * NumericDigit.
692 */
693 numeric_digits = (precision + 2 * (DEC_DIGITS - 1)) / DEC_DIGITS;
694
695 /*
696 * In most cases, the size of a numeric will be smaller than the value
697 * computed below, because the varlena header will typically get toasted
698 * down to a single byte before being stored on disk, and it may also be
699 * possible to use a short numeric header. But our job here is to compute
700 * the worst case.
701 */
702 return NUMERIC_HDRSZ + (numeric_digits * sizeof(NumericDigit));
703 }
704
705 /*
706 * numeric_out_sci() -
707 *
708 * Output function for numeric data type in scientific notation.
709 */
710 char *
numeric_out_sci(Numeric num,int scale)711 numeric_out_sci(Numeric num, int scale)
712 {
713 NumericVar x;
714 char *str;
715
716 /*
717 * Handle NaN
718 */
719 if (NUMERIC_IS_NAN(num))
720 return pstrdup("NaN");
721
722 init_var_from_num(num, &x);
723
724 str = get_str_from_var_sci(&x, scale);
725
726 return str;
727 }
728
729 /*
730 * numeric_normalize() -
731 *
732 * Output function for numeric data type, suppressing insignificant trailing
733 * zeroes and then any trailing decimal point. The intent of this is to
734 * produce strings that are equal if and only if the input numeric values
735 * compare equal.
736 */
737 char *
numeric_normalize(Numeric num)738 numeric_normalize(Numeric num)
739 {
740 NumericVar x;
741 char *str;
742 int last;
743
744 /*
745 * Handle NaN
746 */
747 if (NUMERIC_IS_NAN(num))
748 return pstrdup("NaN");
749
750 init_var_from_num(num, &x);
751
752 str = get_str_from_var(&x);
753
754 /* If there's no decimal point, there's certainly nothing to remove. */
755 if (strchr(str, '.') != NULL)
756 {
757 /*
758 * Back up over trailing fractional zeroes. Since there is a decimal
759 * point, this loop will terminate safely.
760 */
761 last = strlen(str) - 1;
762 while (str[last] == '0')
763 last--;
764
765 /* We want to get rid of the decimal point too, if it's now last. */
766 if (str[last] == '.')
767 last--;
768
769 /* Delete whatever we backed up over. */
770 str[last + 1] = '\0';
771 }
772
773 return str;
774 }
775
776 /*
777 * numeric_recv - converts external binary format to numeric
778 *
779 * External format is a sequence of int16's:
780 * ndigits, weight, sign, dscale, NumericDigits.
781 */
782 Datum
numeric_recv(PG_FUNCTION_ARGS)783 numeric_recv(PG_FUNCTION_ARGS)
784 {
785 StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
786
787 #ifdef NOT_USED
788 Oid typelem = PG_GETARG_OID(1);
789 #endif
790 int32 typmod = PG_GETARG_INT32(2);
791 NumericVar value;
792 Numeric res;
793 int len,
794 i;
795
796 init_var(&value);
797
798 len = (uint16) pq_getmsgint(buf, sizeof(uint16));
799
800 alloc_var(&value, len);
801
802 value.weight = (int16) pq_getmsgint(buf, sizeof(int16));
803 /* we allow any int16 for weight --- OK? */
804
805 value.sign = (uint16) pq_getmsgint(buf, sizeof(uint16));
806 if (!(value.sign == NUMERIC_POS ||
807 value.sign == NUMERIC_NEG ||
808 value.sign == NUMERIC_NAN))
809 ereport(ERROR,
810 (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
811 errmsg("invalid sign in external \"numeric\" value")));
812
813 value.dscale = (uint16) pq_getmsgint(buf, sizeof(uint16));
814 if ((value.dscale & NUMERIC_DSCALE_MASK) != value.dscale)
815 ereport(ERROR,
816 (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
817 errmsg("invalid scale in external \"numeric\" value")));
818
819 for (i = 0; i < len; i++)
820 {
821 NumericDigit d = pq_getmsgint(buf, sizeof(NumericDigit));
822
823 if (d < 0 || d >= NBASE)
824 ereport(ERROR,
825 (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
826 errmsg("invalid digit in external \"numeric\" value")));
827 value.digits[i] = d;
828 }
829
830 /*
831 * If the given dscale would hide any digits, truncate those digits away.
832 * We could alternatively throw an error, but that would take a bunch of
833 * extra code (about as much as trunc_var involves), and it might cause
834 * client compatibility issues.
835 */
836 trunc_var(&value, value.dscale);
837
838 apply_typmod(&value, typmod);
839
840 res = make_result(&value);
841 free_var(&value);
842
843 PG_RETURN_NUMERIC(res);
844 }
845
846 /*
847 * numeric_send - converts numeric to binary format
848 */
849 Datum
numeric_send(PG_FUNCTION_ARGS)850 numeric_send(PG_FUNCTION_ARGS)
851 {
852 Numeric num = PG_GETARG_NUMERIC(0);
853 NumericVar x;
854 StringInfoData buf;
855 int i;
856
857 init_var_from_num(num, &x);
858
859 pq_begintypsend(&buf);
860
861 pq_sendint(&buf, x.ndigits, sizeof(int16));
862 pq_sendint(&buf, x.weight, sizeof(int16));
863 pq_sendint(&buf, x.sign, sizeof(int16));
864 pq_sendint(&buf, x.dscale, sizeof(int16));
865 for (i = 0; i < x.ndigits; i++)
866 pq_sendint(&buf, x.digits[i], sizeof(NumericDigit));
867
868 PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
869 }
870
871
872 /*
873 * numeric_transform() -
874 *
875 * Flatten calls to numeric's length coercion function that solely represent
876 * increases in allowable precision. Scale changes mutate every datum, so
877 * they are unoptimizable. Some values, e.g. 1E-1001, can only fit into an
878 * unconstrained numeric, so a change from an unconstrained numeric to any
879 * constrained numeric is also unoptimizable.
880 */
881 Datum
numeric_transform(PG_FUNCTION_ARGS)882 numeric_transform(PG_FUNCTION_ARGS)
883 {
884 FuncExpr *expr = castNode(FuncExpr, PG_GETARG_POINTER(0));
885 Node *ret = NULL;
886 Node *typmod;
887
888 Assert(list_length(expr->args) >= 2);
889
890 typmod = (Node *) lsecond(expr->args);
891
892 if (IsA(typmod, Const) &&!((Const *) typmod)->constisnull)
893 {
894 Node *source = (Node *) linitial(expr->args);
895 int32 old_typmod = exprTypmod(source);
896 int32 new_typmod = DatumGetInt32(((Const *) typmod)->constvalue);
897 int32 old_scale = (old_typmod - VARHDRSZ) & 0xffff;
898 int32 new_scale = (new_typmod - VARHDRSZ) & 0xffff;
899 int32 old_precision = (old_typmod - VARHDRSZ) >> 16 & 0xffff;
900 int32 new_precision = (new_typmod - VARHDRSZ) >> 16 & 0xffff;
901
902 /*
903 * If new_typmod < VARHDRSZ, the destination is unconstrained; that's
904 * always OK. If old_typmod >= VARHDRSZ, the source is constrained,
905 * and we're OK if the scale is unchanged and the precision is not
906 * decreasing. See further notes in function header comment.
907 */
908 if (new_typmod < (int32) VARHDRSZ ||
909 (old_typmod >= (int32) VARHDRSZ &&
910 new_scale == old_scale && new_precision >= old_precision))
911 ret = relabel_to_typmod(source, new_typmod);
912 }
913
914 PG_RETURN_POINTER(ret);
915 }
916
917 /*
918 * numeric() -
919 *
920 * This is a special function called by the Postgres database system
921 * before a value is stored in a tuple's attribute. The precision and
922 * scale of the attribute have to be applied on the value.
923 */
924 Datum
numeric(PG_FUNCTION_ARGS)925 numeric (PG_FUNCTION_ARGS)
926 {
927 Numeric num = PG_GETARG_NUMERIC(0);
928 int32 typmod = PG_GETARG_INT32(1);
929 Numeric new;
930 int32 tmp_typmod;
931 int precision;
932 int scale;
933 int ddigits;
934 int maxdigits;
935 NumericVar var;
936
937 /*
938 * Handle NaN
939 */
940 if (NUMERIC_IS_NAN(num))
941 PG_RETURN_NUMERIC(make_result(&const_nan));
942
943 /*
944 * If the value isn't a valid type modifier, simply return a copy of the
945 * input value
946 */
947 if (typmod < (int32) (VARHDRSZ))
948 {
949 new = (Numeric) palloc(VARSIZE(num));
950 memcpy(new, num, VARSIZE(num));
951 PG_RETURN_NUMERIC(new);
952 }
953
954 /*
955 * Get the precision and scale out of the typmod value
956 */
957 tmp_typmod = typmod - VARHDRSZ;
958 precision = (tmp_typmod >> 16) & 0xffff;
959 scale = tmp_typmod & 0xffff;
960 maxdigits = precision - scale;
961
962 /*
963 * If the number is certainly in bounds and due to the target scale no
964 * rounding could be necessary, just make a copy of the input and modify
965 * its scale fields, unless the larger scale forces us to abandon the
966 * short representation. (Note we assume the existing dscale is
967 * honest...)
968 */
969 ddigits = (NUMERIC_WEIGHT(num) + 1) * DEC_DIGITS;
970 if (ddigits <= maxdigits && scale >= NUMERIC_DSCALE(num)
971 && (NUMERIC_CAN_BE_SHORT(scale, NUMERIC_WEIGHT(num))
972 || !NUMERIC_IS_SHORT(num)))
973 {
974 new = (Numeric) palloc(VARSIZE(num));
975 memcpy(new, num, VARSIZE(num));
976 if (NUMERIC_IS_SHORT(num))
977 new->choice.n_short.n_header =
978 (num->choice.n_short.n_header & ~NUMERIC_SHORT_DSCALE_MASK)
979 | (scale << NUMERIC_SHORT_DSCALE_SHIFT);
980 else
981 new->choice.n_long.n_sign_dscale = NUMERIC_SIGN(new) |
982 ((uint16) scale & NUMERIC_DSCALE_MASK);
983 PG_RETURN_NUMERIC(new);
984 }
985
986 /*
987 * We really need to fiddle with things - unpack the number into a
988 * variable and let apply_typmod() do it.
989 */
990 init_var(&var);
991
992 set_var_from_num(num, &var);
993 apply_typmod(&var, typmod);
994 new = make_result(&var);
995
996 free_var(&var);
997
998 PG_RETURN_NUMERIC(new);
999 }
1000
1001 Datum
numerictypmodin(PG_FUNCTION_ARGS)1002 numerictypmodin(PG_FUNCTION_ARGS)
1003 {
1004 ArrayType *ta = PG_GETARG_ARRAYTYPE_P(0);
1005 int32 *tl;
1006 int n;
1007 int32 typmod;
1008
1009 tl = ArrayGetIntegerTypmods(ta, &n);
1010
1011 if (n == 2)
1012 {
1013 if (tl[0] < 1 || tl[0] > NUMERIC_MAX_PRECISION)
1014 ereport(ERROR,
1015 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1016 errmsg("NUMERIC precision %d must be between 1 and %d",
1017 tl[0], NUMERIC_MAX_PRECISION)));
1018 if (tl[1] < 0 || tl[1] > tl[0])
1019 ereport(ERROR,
1020 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1021 errmsg("NUMERIC scale %d must be between 0 and precision %d",
1022 tl[1], tl[0])));
1023 typmod = ((tl[0] << 16) | tl[1]) + VARHDRSZ;
1024 }
1025 else if (n == 1)
1026 {
1027 if (tl[0] < 1 || tl[0] > NUMERIC_MAX_PRECISION)
1028 ereport(ERROR,
1029 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1030 errmsg("NUMERIC precision %d must be between 1 and %d",
1031 tl[0], NUMERIC_MAX_PRECISION)));
1032 /* scale defaults to zero */
1033 typmod = (tl[0] << 16) + VARHDRSZ;
1034 }
1035 else
1036 {
1037 ereport(ERROR,
1038 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1039 errmsg("invalid NUMERIC type modifier")));
1040 typmod = 0; /* keep compiler quiet */
1041 }
1042
1043 PG_RETURN_INT32(typmod);
1044 }
1045
1046 Datum
numerictypmodout(PG_FUNCTION_ARGS)1047 numerictypmodout(PG_FUNCTION_ARGS)
1048 {
1049 int32 typmod = PG_GETARG_INT32(0);
1050 char *res = (char *) palloc(64);
1051
1052 if (typmod >= 0)
1053 snprintf(res, 64, "(%d,%d)",
1054 ((typmod - VARHDRSZ) >> 16) & 0xffff,
1055 (typmod - VARHDRSZ) & 0xffff);
1056 else
1057 *res = '\0';
1058
1059 PG_RETURN_CSTRING(res);
1060 }
1061
1062
1063 /* ----------------------------------------------------------------------
1064 *
1065 * Sign manipulation, rounding and the like
1066 *
1067 * ----------------------------------------------------------------------
1068 */
1069
1070 Datum
numeric_abs(PG_FUNCTION_ARGS)1071 numeric_abs(PG_FUNCTION_ARGS)
1072 {
1073 Numeric num = PG_GETARG_NUMERIC(0);
1074 Numeric res;
1075
1076 /*
1077 * Handle NaN
1078 */
1079 if (NUMERIC_IS_NAN(num))
1080 PG_RETURN_NUMERIC(make_result(&const_nan));
1081
1082 /*
1083 * Do it the easy way directly on the packed format
1084 */
1085 res = (Numeric) palloc(VARSIZE(num));
1086 memcpy(res, num, VARSIZE(num));
1087
1088 if (NUMERIC_IS_SHORT(num))
1089 res->choice.n_short.n_header =
1090 num->choice.n_short.n_header & ~NUMERIC_SHORT_SIGN_MASK;
1091 else
1092 res->choice.n_long.n_sign_dscale = NUMERIC_POS | NUMERIC_DSCALE(num);
1093
1094 PG_RETURN_NUMERIC(res);
1095 }
1096
1097
1098 Datum
numeric_uminus(PG_FUNCTION_ARGS)1099 numeric_uminus(PG_FUNCTION_ARGS)
1100 {
1101 Numeric num = PG_GETARG_NUMERIC(0);
1102 Numeric res;
1103
1104 /*
1105 * Handle NaN
1106 */
1107 if (NUMERIC_IS_NAN(num))
1108 PG_RETURN_NUMERIC(make_result(&const_nan));
1109
1110 /*
1111 * Do it the easy way directly on the packed format
1112 */
1113 res = (Numeric) palloc(VARSIZE(num));
1114 memcpy(res, num, VARSIZE(num));
1115
1116 /*
1117 * The packed format is known to be totally zero digit trimmed always. So
1118 * we can identify a ZERO by the fact that there are no digits at all. Do
1119 * nothing to a zero.
1120 */
1121 if (NUMERIC_NDIGITS(num) != 0)
1122 {
1123 /* Else, flip the sign */
1124 if (NUMERIC_IS_SHORT(num))
1125 res->choice.n_short.n_header =
1126 num->choice.n_short.n_header ^ NUMERIC_SHORT_SIGN_MASK;
1127 else if (NUMERIC_SIGN(num) == NUMERIC_POS)
1128 res->choice.n_long.n_sign_dscale =
1129 NUMERIC_NEG | NUMERIC_DSCALE(num);
1130 else
1131 res->choice.n_long.n_sign_dscale =
1132 NUMERIC_POS | NUMERIC_DSCALE(num);
1133 }
1134
1135 PG_RETURN_NUMERIC(res);
1136 }
1137
1138
1139 Datum
numeric_uplus(PG_FUNCTION_ARGS)1140 numeric_uplus(PG_FUNCTION_ARGS)
1141 {
1142 Numeric num = PG_GETARG_NUMERIC(0);
1143 Numeric res;
1144
1145 res = (Numeric) palloc(VARSIZE(num));
1146 memcpy(res, num, VARSIZE(num));
1147
1148 PG_RETURN_NUMERIC(res);
1149 }
1150
1151 /*
1152 * numeric_sign() -
1153 *
1154 * returns -1 if the argument is less than 0, 0 if the argument is equal
1155 * to 0, and 1 if the argument is greater than zero.
1156 */
1157 Datum
numeric_sign(PG_FUNCTION_ARGS)1158 numeric_sign(PG_FUNCTION_ARGS)
1159 {
1160 Numeric num = PG_GETARG_NUMERIC(0);
1161 Numeric res;
1162 NumericVar result;
1163
1164 /*
1165 * Handle NaN
1166 */
1167 if (NUMERIC_IS_NAN(num))
1168 PG_RETURN_NUMERIC(make_result(&const_nan));
1169
1170 init_var(&result);
1171
1172 /*
1173 * The packed format is known to be totally zero digit trimmed always. So
1174 * we can identify a ZERO by the fact that there are no digits at all.
1175 */
1176 if (NUMERIC_NDIGITS(num) == 0)
1177 set_var_from_var(&const_zero, &result);
1178 else
1179 {
1180 /*
1181 * And if there are some, we return a copy of ONE with the sign of our
1182 * argument
1183 */
1184 set_var_from_var(&const_one, &result);
1185 result.sign = NUMERIC_SIGN(num);
1186 }
1187
1188 res = make_result(&result);
1189 free_var(&result);
1190
1191 PG_RETURN_NUMERIC(res);
1192 }
1193
1194
1195 /*
1196 * numeric_round() -
1197 *
1198 * Round a value to have 'scale' digits after the decimal point.
1199 * We allow negative 'scale', implying rounding before the decimal
1200 * point --- Oracle interprets rounding that way.
1201 */
1202 Datum
numeric_round(PG_FUNCTION_ARGS)1203 numeric_round(PG_FUNCTION_ARGS)
1204 {
1205 Numeric num = PG_GETARG_NUMERIC(0);
1206 int32 scale = PG_GETARG_INT32(1);
1207 Numeric res;
1208 NumericVar arg;
1209
1210 /*
1211 * Handle NaN
1212 */
1213 if (NUMERIC_IS_NAN(num))
1214 PG_RETURN_NUMERIC(make_result(&const_nan));
1215
1216 /*
1217 * Limit the scale value to avoid possible overflow in calculations
1218 */
1219 scale = Max(scale, -NUMERIC_MAX_RESULT_SCALE);
1220 scale = Min(scale, NUMERIC_MAX_RESULT_SCALE);
1221
1222 /*
1223 * Unpack the argument and round it at the proper digit position
1224 */
1225 init_var(&arg);
1226 set_var_from_num(num, &arg);
1227
1228 round_var(&arg, scale);
1229
1230 /* We don't allow negative output dscale */
1231 if (scale < 0)
1232 arg.dscale = 0;
1233
1234 /*
1235 * Return the rounded result
1236 */
1237 res = make_result(&arg);
1238
1239 free_var(&arg);
1240 PG_RETURN_NUMERIC(res);
1241 }
1242
1243
1244 /*
1245 * numeric_trunc() -
1246 *
1247 * Truncate a value to have 'scale' digits after the decimal point.
1248 * We allow negative 'scale', implying a truncation before the decimal
1249 * point --- Oracle interprets truncation that way.
1250 */
1251 Datum
numeric_trunc(PG_FUNCTION_ARGS)1252 numeric_trunc(PG_FUNCTION_ARGS)
1253 {
1254 Numeric num = PG_GETARG_NUMERIC(0);
1255 int32 scale = PG_GETARG_INT32(1);
1256 Numeric res;
1257 NumericVar arg;
1258
1259 /*
1260 * Handle NaN
1261 */
1262 if (NUMERIC_IS_NAN(num))
1263 PG_RETURN_NUMERIC(make_result(&const_nan));
1264
1265 /*
1266 * Limit the scale value to avoid possible overflow in calculations
1267 */
1268 scale = Max(scale, -NUMERIC_MAX_RESULT_SCALE);
1269 scale = Min(scale, NUMERIC_MAX_RESULT_SCALE);
1270
1271 /*
1272 * Unpack the argument and truncate it at the proper digit position
1273 */
1274 init_var(&arg);
1275 set_var_from_num(num, &arg);
1276
1277 trunc_var(&arg, scale);
1278
1279 /* We don't allow negative output dscale */
1280 if (scale < 0)
1281 arg.dscale = 0;
1282
1283 /*
1284 * Return the truncated result
1285 */
1286 res = make_result(&arg);
1287
1288 free_var(&arg);
1289 PG_RETURN_NUMERIC(res);
1290 }
1291
1292
1293 /*
1294 * numeric_ceil() -
1295 *
1296 * Return the smallest integer greater than or equal to the argument
1297 */
1298 Datum
numeric_ceil(PG_FUNCTION_ARGS)1299 numeric_ceil(PG_FUNCTION_ARGS)
1300 {
1301 Numeric num = PG_GETARG_NUMERIC(0);
1302 Numeric res;
1303 NumericVar result;
1304
1305 if (NUMERIC_IS_NAN(num))
1306 PG_RETURN_NUMERIC(make_result(&const_nan));
1307
1308 init_var_from_num(num, &result);
1309 ceil_var(&result, &result);
1310
1311 res = make_result(&result);
1312 free_var(&result);
1313
1314 PG_RETURN_NUMERIC(res);
1315 }
1316
1317
1318 /*
1319 * numeric_floor() -
1320 *
1321 * Return the largest integer equal to or less than the argument
1322 */
1323 Datum
numeric_floor(PG_FUNCTION_ARGS)1324 numeric_floor(PG_FUNCTION_ARGS)
1325 {
1326 Numeric num = PG_GETARG_NUMERIC(0);
1327 Numeric res;
1328 NumericVar result;
1329
1330 if (NUMERIC_IS_NAN(num))
1331 PG_RETURN_NUMERIC(make_result(&const_nan));
1332
1333 init_var_from_num(num, &result);
1334 floor_var(&result, &result);
1335
1336 res = make_result(&result);
1337 free_var(&result);
1338
1339 PG_RETURN_NUMERIC(res);
1340 }
1341
1342
1343 /*
1344 * generate_series_numeric() -
1345 *
1346 * Generate series of numeric.
1347 */
1348 Datum
generate_series_numeric(PG_FUNCTION_ARGS)1349 generate_series_numeric(PG_FUNCTION_ARGS)
1350 {
1351 return generate_series_step_numeric(fcinfo);
1352 }
1353
1354 Datum
generate_series_step_numeric(PG_FUNCTION_ARGS)1355 generate_series_step_numeric(PG_FUNCTION_ARGS)
1356 {
1357 generate_series_numeric_fctx *fctx;
1358 FuncCallContext *funcctx;
1359 MemoryContext oldcontext;
1360
1361 if (SRF_IS_FIRSTCALL())
1362 {
1363 Numeric start_num = PG_GETARG_NUMERIC(0);
1364 Numeric stop_num = PG_GETARG_NUMERIC(1);
1365 NumericVar steploc = const_one;
1366
1367 /* handle NaN in start and stop values */
1368 if (NUMERIC_IS_NAN(start_num))
1369 ereport(ERROR,
1370 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1371 errmsg("start value cannot be NaN")));
1372
1373 if (NUMERIC_IS_NAN(stop_num))
1374 ereport(ERROR,
1375 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1376 errmsg("stop value cannot be NaN")));
1377
1378 /* see if we were given an explicit step size */
1379 if (PG_NARGS() == 3)
1380 {
1381 Numeric step_num = PG_GETARG_NUMERIC(2);
1382
1383 if (NUMERIC_IS_NAN(step_num))
1384 ereport(ERROR,
1385 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1386 errmsg("step size cannot be NaN")));
1387
1388 init_var_from_num(step_num, &steploc);
1389
1390 if (cmp_var(&steploc, &const_zero) == 0)
1391 ereport(ERROR,
1392 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1393 errmsg("step size cannot equal zero")));
1394 }
1395
1396 /* create a function context for cross-call persistence */
1397 funcctx = SRF_FIRSTCALL_INIT();
1398
1399 /*
1400 * Switch to memory context appropriate for multiple function calls.
1401 */
1402 oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
1403
1404 /* allocate memory for user context */
1405 fctx = (generate_series_numeric_fctx *)
1406 palloc(sizeof(generate_series_numeric_fctx));
1407
1408 /*
1409 * Use fctx to keep state from call to call. Seed current with the
1410 * original start value. We must copy the start_num and stop_num
1411 * values rather than pointing to them, since we may have detoasted
1412 * them in the per-call context.
1413 */
1414 init_var(&fctx->current);
1415 init_var(&fctx->stop);
1416 init_var(&fctx->step);
1417
1418 set_var_from_num(start_num, &fctx->current);
1419 set_var_from_num(stop_num, &fctx->stop);
1420 set_var_from_var(&steploc, &fctx->step);
1421
1422 funcctx->user_fctx = fctx;
1423 MemoryContextSwitchTo(oldcontext);
1424 }
1425
1426 /* stuff done on every call of the function */
1427 funcctx = SRF_PERCALL_SETUP();
1428
1429 /*
1430 * Get the saved state and use current state as the result of this
1431 * iteration.
1432 */
1433 fctx = funcctx->user_fctx;
1434
1435 if ((fctx->step.sign == NUMERIC_POS &&
1436 cmp_var(&fctx->current, &fctx->stop) <= 0) ||
1437 (fctx->step.sign == NUMERIC_NEG &&
1438 cmp_var(&fctx->current, &fctx->stop) >= 0))
1439 {
1440 Numeric result = make_result(&fctx->current);
1441
1442 /* switch to memory context appropriate for iteration calculation */
1443 oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
1444
1445 /* increment current in preparation for next iteration */
1446 add_var(&fctx->current, &fctx->step, &fctx->current);
1447 MemoryContextSwitchTo(oldcontext);
1448
1449 /* do when there is more left to send */
1450 SRF_RETURN_NEXT(funcctx, NumericGetDatum(result));
1451 }
1452 else
1453 /* do when there is no more left */
1454 SRF_RETURN_DONE(funcctx);
1455 }
1456
1457
1458 /*
1459 * Implements the numeric version of the width_bucket() function
1460 * defined by SQL2003. See also width_bucket_float8().
1461 *
1462 * 'bound1' and 'bound2' are the lower and upper bounds of the
1463 * histogram's range, respectively. 'count' is the number of buckets
1464 * in the histogram. width_bucket() returns an integer indicating the
1465 * bucket number that 'operand' belongs to in an equiwidth histogram
1466 * with the specified characteristics. An operand smaller than the
1467 * lower bound is assigned to bucket 0. An operand greater than the
1468 * upper bound is assigned to an additional bucket (with number
1469 * count+1). We don't allow "NaN" for any of the numeric arguments.
1470 */
1471 Datum
width_bucket_numeric(PG_FUNCTION_ARGS)1472 width_bucket_numeric(PG_FUNCTION_ARGS)
1473 {
1474 Numeric operand = PG_GETARG_NUMERIC(0);
1475 Numeric bound1 = PG_GETARG_NUMERIC(1);
1476 Numeric bound2 = PG_GETARG_NUMERIC(2);
1477 int32 count = PG_GETARG_INT32(3);
1478 NumericVar count_var;
1479 NumericVar result_var;
1480 int32 result;
1481
1482 if (count <= 0)
1483 ereport(ERROR,
1484 (errcode(ERRCODE_INVALID_ARGUMENT_FOR_WIDTH_BUCKET_FUNCTION),
1485 errmsg("count must be greater than zero")));
1486
1487 if (NUMERIC_IS_NAN(operand) ||
1488 NUMERIC_IS_NAN(bound1) ||
1489 NUMERIC_IS_NAN(bound2))
1490 ereport(ERROR,
1491 (errcode(ERRCODE_INVALID_ARGUMENT_FOR_WIDTH_BUCKET_FUNCTION),
1492 errmsg("operand, lower bound, and upper bound cannot be NaN")));
1493
1494 init_var(&result_var);
1495 init_var(&count_var);
1496
1497 /* Convert 'count' to a numeric, for ease of use later */
1498 int64_to_numericvar((int64) count, &count_var);
1499
1500 switch (cmp_numerics(bound1, bound2))
1501 {
1502 case 0:
1503 ereport(ERROR,
1504 (errcode(ERRCODE_INVALID_ARGUMENT_FOR_WIDTH_BUCKET_FUNCTION),
1505 errmsg("lower bound cannot equal upper bound")));
1506
1507 /* bound1 < bound2 */
1508 case -1:
1509 if (cmp_numerics(operand, bound1) < 0)
1510 set_var_from_var(&const_zero, &result_var);
1511 else if (cmp_numerics(operand, bound2) >= 0)
1512 add_var(&count_var, &const_one, &result_var);
1513 else
1514 compute_bucket(operand, bound1, bound2,
1515 &count_var, &result_var);
1516 break;
1517
1518 /* bound1 > bound2 */
1519 case 1:
1520 if (cmp_numerics(operand, bound1) > 0)
1521 set_var_from_var(&const_zero, &result_var);
1522 else if (cmp_numerics(operand, bound2) <= 0)
1523 add_var(&count_var, &const_one, &result_var);
1524 else
1525 compute_bucket(operand, bound1, bound2,
1526 &count_var, &result_var);
1527 break;
1528 }
1529
1530 /* if result exceeds the range of a legal int4, we ereport here */
1531 result = numericvar_to_int32(&result_var);
1532
1533 free_var(&count_var);
1534 free_var(&result_var);
1535
1536 PG_RETURN_INT32(result);
1537 }
1538
1539 /*
1540 * If 'operand' is not outside the bucket range, determine the correct
1541 * bucket for it to go. The calculations performed by this function
1542 * are derived directly from the SQL2003 spec.
1543 */
1544 static void
compute_bucket(Numeric operand,Numeric bound1,Numeric bound2,NumericVar * count_var,NumericVar * result_var)1545 compute_bucket(Numeric operand, Numeric bound1, Numeric bound2,
1546 NumericVar *count_var, NumericVar *result_var)
1547 {
1548 NumericVar bound1_var;
1549 NumericVar bound2_var;
1550 NumericVar operand_var;
1551
1552 init_var_from_num(bound1, &bound1_var);
1553 init_var_from_num(bound2, &bound2_var);
1554 init_var_from_num(operand, &operand_var);
1555
1556 if (cmp_var(&bound1_var, &bound2_var) < 0)
1557 {
1558 sub_var(&operand_var, &bound1_var, &operand_var);
1559 sub_var(&bound2_var, &bound1_var, &bound2_var);
1560 div_var(&operand_var, &bound2_var, result_var,
1561 select_div_scale(&operand_var, &bound2_var), true);
1562 }
1563 else
1564 {
1565 sub_var(&bound1_var, &operand_var, &operand_var);
1566 sub_var(&bound1_var, &bound2_var, &bound1_var);
1567 div_var(&operand_var, &bound1_var, result_var,
1568 select_div_scale(&operand_var, &bound1_var), true);
1569 }
1570
1571 mul_var(result_var, count_var, result_var,
1572 result_var->dscale + count_var->dscale);
1573 add_var(result_var, &const_one, result_var);
1574 floor_var(result_var, result_var);
1575
1576 free_var(&bound1_var);
1577 free_var(&bound2_var);
1578 free_var(&operand_var);
1579 }
1580
1581 /* ----------------------------------------------------------------------
1582 *
1583 * Comparison functions
1584 *
1585 * Note: btree indexes need these routines not to leak memory; therefore,
1586 * be careful to free working copies of toasted datums. Most places don't
1587 * need to be so careful.
1588 *
1589 * Sort support:
1590 *
1591 * We implement the sortsupport strategy routine in order to get the benefit of
1592 * abbreviation. The ordinary numeric comparison can be quite slow as a result
1593 * of palloc/pfree cycles (due to detoasting packed values for alignment);
1594 * while this could be worked on itself, the abbreviation strategy gives more
1595 * speedup in many common cases.
1596 *
1597 * Two different representations are used for the abbreviated form, one in
1598 * int32 and one in int64, whichever fits into a by-value Datum. In both cases
1599 * the representation is negated relative to the original value, because we use
1600 * the largest negative value for NaN, which sorts higher than other values. We
1601 * convert the absolute value of the numeric to a 31-bit or 63-bit positive
1602 * value, and then negate it if the original number was positive.
1603 *
1604 * We abort the abbreviation process if the abbreviation cardinality is below
1605 * 0.01% of the row count (1 per 10k non-null rows). The actual break-even
1606 * point is somewhat below that, perhaps 1 per 30k (at 1 per 100k there's a
1607 * very small penalty), but we don't want to build up too many abbreviated
1608 * values before first testing for abort, so we take the slightly pessimistic
1609 * number. We make no attempt to estimate the cardinality of the real values,
1610 * since it plays no part in the cost model here (if the abbreviation is equal,
1611 * the cost of comparing equal and unequal underlying values is comparable).
1612 * We discontinue even checking for abort (saving us the hashing overhead) if
1613 * the estimated cardinality gets to 100k; that would be enough to support many
1614 * billions of rows while doing no worse than breaking even.
1615 *
1616 * ----------------------------------------------------------------------
1617 */
1618
1619 /*
1620 * Sort support strategy routine.
1621 */
1622 Datum
numeric_sortsupport(PG_FUNCTION_ARGS)1623 numeric_sortsupport(PG_FUNCTION_ARGS)
1624 {
1625 SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0);
1626
1627 ssup->comparator = numeric_fast_cmp;
1628
1629 if (ssup->abbreviate)
1630 {
1631 NumericSortSupport *nss;
1632 MemoryContext oldcontext = MemoryContextSwitchTo(ssup->ssup_cxt);
1633
1634 nss = palloc(sizeof(NumericSortSupport));
1635
1636 /*
1637 * palloc a buffer for handling unaligned packed values in addition to
1638 * the support struct
1639 */
1640 nss->buf = palloc(VARATT_SHORT_MAX + VARHDRSZ + 1);
1641
1642 nss->input_count = 0;
1643 nss->estimating = true;
1644 initHyperLogLog(&nss->abbr_card, 10);
1645
1646 ssup->ssup_extra = nss;
1647
1648 ssup->abbrev_full_comparator = ssup->comparator;
1649 ssup->comparator = numeric_cmp_abbrev;
1650 ssup->abbrev_converter = numeric_abbrev_convert;
1651 ssup->abbrev_abort = numeric_abbrev_abort;
1652
1653 MemoryContextSwitchTo(oldcontext);
1654 }
1655
1656 PG_RETURN_VOID();
1657 }
1658
1659 /*
1660 * Abbreviate a numeric datum, handling NaNs and detoasting
1661 * (must not leak memory!)
1662 */
1663 static Datum
numeric_abbrev_convert(Datum original_datum,SortSupport ssup)1664 numeric_abbrev_convert(Datum original_datum, SortSupport ssup)
1665 {
1666 NumericSortSupport *nss = ssup->ssup_extra;
1667 void *original_varatt = PG_DETOAST_DATUM_PACKED(original_datum);
1668 Numeric value;
1669 Datum result;
1670
1671 nss->input_count += 1;
1672
1673 /*
1674 * This is to handle packed datums without needing a palloc/pfree cycle;
1675 * we keep and reuse a buffer large enough to handle any short datum.
1676 */
1677 if (VARATT_IS_SHORT(original_varatt))
1678 {
1679 void *buf = nss->buf;
1680 Size sz = VARSIZE_SHORT(original_varatt) - VARHDRSZ_SHORT;
1681
1682 Assert(sz <= VARATT_SHORT_MAX - VARHDRSZ_SHORT);
1683
1684 SET_VARSIZE(buf, VARHDRSZ + sz);
1685 memcpy(VARDATA(buf), VARDATA_SHORT(original_varatt), sz);
1686
1687 value = (Numeric) buf;
1688 }
1689 else
1690 value = (Numeric) original_varatt;
1691
1692 if (NUMERIC_IS_NAN(value))
1693 {
1694 result = NUMERIC_ABBREV_NAN;
1695 }
1696 else
1697 {
1698 NumericVar var;
1699
1700 init_var_from_num(value, &var);
1701
1702 result = numeric_abbrev_convert_var(&var, nss);
1703 }
1704
1705 /* should happen only for external/compressed toasts */
1706 if ((Pointer) original_varatt != DatumGetPointer(original_datum))
1707 pfree(original_varatt);
1708
1709 return result;
1710 }
1711
1712 /*
1713 * Consider whether to abort abbreviation.
1714 *
1715 * We pay no attention to the cardinality of the non-abbreviated data. There is
1716 * no reason to do so: unlike text, we have no fast check for equal values, so
1717 * we pay the full overhead whenever the abbreviations are equal regardless of
1718 * whether the underlying values are also equal.
1719 */
1720 static bool
numeric_abbrev_abort(int memtupcount,SortSupport ssup)1721 numeric_abbrev_abort(int memtupcount, SortSupport ssup)
1722 {
1723 NumericSortSupport *nss = ssup->ssup_extra;
1724 double abbr_card;
1725
1726 if (memtupcount < 10000 || nss->input_count < 10000 || !nss->estimating)
1727 return false;
1728
1729 abbr_card = estimateHyperLogLog(&nss->abbr_card);
1730
1731 /*
1732 * If we have >100k distinct values, then even if we were sorting many
1733 * billion rows we'd likely still break even, and the penalty of undoing
1734 * that many rows of abbrevs would probably not be worth it. Stop even
1735 * counting at that point.
1736 */
1737 if (abbr_card > 100000.0)
1738 {
1739 #ifdef TRACE_SORT
1740 if (trace_sort)
1741 elog(LOG,
1742 "numeric_abbrev: estimation ends at cardinality %f"
1743 " after " INT64_FORMAT " values (%d rows)",
1744 abbr_card, nss->input_count, memtupcount);
1745 #endif
1746 nss->estimating = false;
1747 return false;
1748 }
1749
1750 /*
1751 * Target minimum cardinality is 1 per ~10k of non-null inputs. (The
1752 * break even point is somewhere between one per 100k rows, where
1753 * abbreviation has a very slight penalty, and 1 per 10k where it wins by
1754 * a measurable percentage.) We use the relatively pessimistic 10k
1755 * threshold, and add a 0.5 row fudge factor, because it allows us to
1756 * abort earlier on genuinely pathological data where we've had exactly
1757 * one abbreviated value in the first 10k (non-null) rows.
1758 */
1759 if (abbr_card < nss->input_count / 10000.0 + 0.5)
1760 {
1761 #ifdef TRACE_SORT
1762 if (trace_sort)
1763 elog(LOG,
1764 "numeric_abbrev: aborting abbreviation at cardinality %f"
1765 " below threshold %f after " INT64_FORMAT " values (%d rows)",
1766 abbr_card, nss->input_count / 10000.0 + 0.5,
1767 nss->input_count, memtupcount);
1768 #endif
1769 return true;
1770 }
1771
1772 #ifdef TRACE_SORT
1773 if (trace_sort)
1774 elog(LOG,
1775 "numeric_abbrev: cardinality %f"
1776 " after " INT64_FORMAT " values (%d rows)",
1777 abbr_card, nss->input_count, memtupcount);
1778 #endif
1779
1780 return false;
1781 }
1782
1783 /*
1784 * Non-fmgr interface to the comparison routine to allow sortsupport to elide
1785 * the fmgr call. The saving here is small given how slow numeric comparisons
1786 * are, but it is a required part of the sort support API when abbreviations
1787 * are performed.
1788 *
1789 * Two palloc/pfree cycles could be saved here by using persistent buffers for
1790 * aligning short-varlena inputs, but this has not so far been considered to
1791 * be worth the effort.
1792 */
1793 static int
numeric_fast_cmp(Datum x,Datum y,SortSupport ssup)1794 numeric_fast_cmp(Datum x, Datum y, SortSupport ssup)
1795 {
1796 Numeric nx = DatumGetNumeric(x);
1797 Numeric ny = DatumGetNumeric(y);
1798 int result;
1799
1800 result = cmp_numerics(nx, ny);
1801
1802 if ((Pointer) nx != DatumGetPointer(x))
1803 pfree(nx);
1804 if ((Pointer) ny != DatumGetPointer(y))
1805 pfree(ny);
1806
1807 return result;
1808 }
1809
1810 /*
1811 * Compare abbreviations of values. (Abbreviations may be equal where the true
1812 * values differ, but if the abbreviations differ, they must reflect the
1813 * ordering of the true values.)
1814 */
1815 static int
numeric_cmp_abbrev(Datum x,Datum y,SortSupport ssup)1816 numeric_cmp_abbrev(Datum x, Datum y, SortSupport ssup)
1817 {
1818 /*
1819 * NOTE WELL: this is intentionally backwards, because the abbreviation is
1820 * negated relative to the original value, to handle NaN.
1821 */
1822 if (DatumGetNumericAbbrev(x) < DatumGetNumericAbbrev(y))
1823 return 1;
1824 if (DatumGetNumericAbbrev(x) > DatumGetNumericAbbrev(y))
1825 return -1;
1826 return 0;
1827 }
1828
1829 /*
1830 * Abbreviate a NumericVar according to the available bit size.
1831 *
1832 * The 31-bit value is constructed as:
1833 *
1834 * 0 + 7bits digit weight + 24 bits digit value
1835 *
1836 * where the digit weight is in single decimal digits, not digit words, and
1837 * stored in excess-44 representation[1]. The 24-bit digit value is the 7 most
1838 * significant decimal digits of the value converted to binary. Values whose
1839 * weights would fall outside the representable range are rounded off to zero
1840 * (which is also used to represent actual zeros) or to 0x7FFFFFFF (which
1841 * otherwise cannot occur). Abbreviation therefore fails to gain any advantage
1842 * where values are outside the range 10^-44 to 10^83, which is not considered
1843 * to be a serious limitation, or when values are of the same magnitude and
1844 * equal in the first 7 decimal digits, which is considered to be an
1845 * unavoidable limitation given the available bits. (Stealing three more bits
1846 * to compare another digit would narrow the range of representable weights by
1847 * a factor of 8, which starts to look like a real limiting factor.)
1848 *
1849 * (The value 44 for the excess is essentially arbitrary)
1850 *
1851 * The 63-bit value is constructed as:
1852 *
1853 * 0 + 7bits weight + 4 x 14-bit packed digit words
1854 *
1855 * The weight in this case is again stored in excess-44, but this time it is
1856 * the original weight in digit words (i.e. powers of 10000). The first four
1857 * digit words of the value (if present; trailing zeros are assumed as needed)
1858 * are packed into 14 bits each to form the rest of the value. Again,
1859 * out-of-range values are rounded off to 0 or 0x7FFFFFFFFFFFFFFF. The
1860 * representable range in this case is 10^-176 to 10^332, which is considered
1861 * to be good enough for all practical purposes, and comparison of 4 words
1862 * means that at least 13 decimal digits are compared, which is considered to
1863 * be a reasonable compromise between effectiveness and efficiency in computing
1864 * the abbreviation.
1865 *
1866 * (The value 44 for the excess is even more arbitrary here, it was chosen just
1867 * to match the value used in the 31-bit case)
1868 *
1869 * [1] - Excess-k representation means that the value is offset by adding 'k'
1870 * and then treated as unsigned, so the smallest representable value is stored
1871 * with all bits zero. This allows simple comparisons to work on the composite
1872 * value.
1873 */
1874
1875 #if NUMERIC_ABBREV_BITS == 64
1876
1877 static Datum
numeric_abbrev_convert_var(NumericVar * var,NumericSortSupport * nss)1878 numeric_abbrev_convert_var(NumericVar *var, NumericSortSupport *nss)
1879 {
1880 int ndigits = var->ndigits;
1881 int weight = var->weight;
1882 int64 result;
1883
1884 if (ndigits == 0 || weight < -44)
1885 {
1886 result = 0;
1887 }
1888 else if (weight > 83)
1889 {
1890 result = PG_INT64_MAX;
1891 }
1892 else
1893 {
1894 result = ((int64) (weight + 44) << 56);
1895
1896 switch (ndigits)
1897 {
1898 default:
1899 result |= ((int64) var->digits[3]);
1900 /* FALLTHROUGH */
1901 case 3:
1902 result |= ((int64) var->digits[2]) << 14;
1903 /* FALLTHROUGH */
1904 case 2:
1905 result |= ((int64) var->digits[1]) << 28;
1906 /* FALLTHROUGH */
1907 case 1:
1908 result |= ((int64) var->digits[0]) << 42;
1909 break;
1910 }
1911 }
1912
1913 /* the abbrev is negated relative to the original */
1914 if (var->sign == NUMERIC_POS)
1915 result = -result;
1916
1917 if (nss->estimating)
1918 {
1919 uint32 tmp = ((uint32) result
1920 ^ (uint32) ((uint64) result >> 32));
1921
1922 addHyperLogLog(&nss->abbr_card, DatumGetUInt32(hash_uint32(tmp)));
1923 }
1924
1925 return NumericAbbrevGetDatum(result);
1926 }
1927
1928 #endif /* NUMERIC_ABBREV_BITS == 64 */
1929
1930 #if NUMERIC_ABBREV_BITS == 32
1931
1932 static Datum
numeric_abbrev_convert_var(NumericVar * var,NumericSortSupport * nss)1933 numeric_abbrev_convert_var(NumericVar *var, NumericSortSupport *nss)
1934 {
1935 int ndigits = var->ndigits;
1936 int weight = var->weight;
1937 int32 result;
1938
1939 if (ndigits == 0 || weight < -11)
1940 {
1941 result = 0;
1942 }
1943 else if (weight > 20)
1944 {
1945 result = PG_INT32_MAX;
1946 }
1947 else
1948 {
1949 NumericDigit nxt1 = (ndigits > 1) ? var->digits[1] : 0;
1950
1951 weight = (weight + 11) * 4;
1952
1953 result = var->digits[0];
1954
1955 /*
1956 * "result" now has 1 to 4 nonzero decimal digits. We pack in more
1957 * digits to make 7 in total (largest we can fit in 24 bits)
1958 */
1959
1960 if (result > 999)
1961 {
1962 /* already have 4 digits, add 3 more */
1963 result = (result * 1000) + (nxt1 / 10);
1964 weight += 3;
1965 }
1966 else if (result > 99)
1967 {
1968 /* already have 3 digits, add 4 more */
1969 result = (result * 10000) + nxt1;
1970 weight += 2;
1971 }
1972 else if (result > 9)
1973 {
1974 NumericDigit nxt2 = (ndigits > 2) ? var->digits[2] : 0;
1975
1976 /* already have 2 digits, add 5 more */
1977 result = (result * 100000) + (nxt1 * 10) + (nxt2 / 1000);
1978 weight += 1;
1979 }
1980 else
1981 {
1982 NumericDigit nxt2 = (ndigits > 2) ? var->digits[2] : 0;
1983
1984 /* already have 1 digit, add 6 more */
1985 result = (result * 1000000) + (nxt1 * 100) + (nxt2 / 100);
1986 }
1987
1988 result = result | (weight << 24);
1989 }
1990
1991 /* the abbrev is negated relative to the original */
1992 if (var->sign == NUMERIC_POS)
1993 result = -result;
1994
1995 if (nss->estimating)
1996 {
1997 uint32 tmp = (uint32) result;
1998
1999 addHyperLogLog(&nss->abbr_card, DatumGetUInt32(hash_uint32(tmp)));
2000 }
2001
2002 return NumericAbbrevGetDatum(result);
2003 }
2004
2005 #endif /* NUMERIC_ABBREV_BITS == 32 */
2006
2007 /*
2008 * Ordinary (non-sortsupport) comparisons follow.
2009 */
2010
2011 Datum
numeric_cmp(PG_FUNCTION_ARGS)2012 numeric_cmp(PG_FUNCTION_ARGS)
2013 {
2014 Numeric num1 = PG_GETARG_NUMERIC(0);
2015 Numeric num2 = PG_GETARG_NUMERIC(1);
2016 int result;
2017
2018 result = cmp_numerics(num1, num2);
2019
2020 PG_FREE_IF_COPY(num1, 0);
2021 PG_FREE_IF_COPY(num2, 1);
2022
2023 PG_RETURN_INT32(result);
2024 }
2025
2026
2027 Datum
numeric_eq(PG_FUNCTION_ARGS)2028 numeric_eq(PG_FUNCTION_ARGS)
2029 {
2030 Numeric num1 = PG_GETARG_NUMERIC(0);
2031 Numeric num2 = PG_GETARG_NUMERIC(1);
2032 bool result;
2033
2034 result = cmp_numerics(num1, num2) == 0;
2035
2036 PG_FREE_IF_COPY(num1, 0);
2037 PG_FREE_IF_COPY(num2, 1);
2038
2039 PG_RETURN_BOOL(result);
2040 }
2041
2042 Datum
numeric_ne(PG_FUNCTION_ARGS)2043 numeric_ne(PG_FUNCTION_ARGS)
2044 {
2045 Numeric num1 = PG_GETARG_NUMERIC(0);
2046 Numeric num2 = PG_GETARG_NUMERIC(1);
2047 bool result;
2048
2049 result = cmp_numerics(num1, num2) != 0;
2050
2051 PG_FREE_IF_COPY(num1, 0);
2052 PG_FREE_IF_COPY(num2, 1);
2053
2054 PG_RETURN_BOOL(result);
2055 }
2056
2057 Datum
numeric_gt(PG_FUNCTION_ARGS)2058 numeric_gt(PG_FUNCTION_ARGS)
2059 {
2060 Numeric num1 = PG_GETARG_NUMERIC(0);
2061 Numeric num2 = PG_GETARG_NUMERIC(1);
2062 bool result;
2063
2064 result = cmp_numerics(num1, num2) > 0;
2065
2066 PG_FREE_IF_COPY(num1, 0);
2067 PG_FREE_IF_COPY(num2, 1);
2068
2069 PG_RETURN_BOOL(result);
2070 }
2071
2072 Datum
numeric_ge(PG_FUNCTION_ARGS)2073 numeric_ge(PG_FUNCTION_ARGS)
2074 {
2075 Numeric num1 = PG_GETARG_NUMERIC(0);
2076 Numeric num2 = PG_GETARG_NUMERIC(1);
2077 bool result;
2078
2079 result = cmp_numerics(num1, num2) >= 0;
2080
2081 PG_FREE_IF_COPY(num1, 0);
2082 PG_FREE_IF_COPY(num2, 1);
2083
2084 PG_RETURN_BOOL(result);
2085 }
2086
2087 Datum
numeric_lt(PG_FUNCTION_ARGS)2088 numeric_lt(PG_FUNCTION_ARGS)
2089 {
2090 Numeric num1 = PG_GETARG_NUMERIC(0);
2091 Numeric num2 = PG_GETARG_NUMERIC(1);
2092 bool result;
2093
2094 result = cmp_numerics(num1, num2) < 0;
2095
2096 PG_FREE_IF_COPY(num1, 0);
2097 PG_FREE_IF_COPY(num2, 1);
2098
2099 PG_RETURN_BOOL(result);
2100 }
2101
2102 Datum
numeric_le(PG_FUNCTION_ARGS)2103 numeric_le(PG_FUNCTION_ARGS)
2104 {
2105 Numeric num1 = PG_GETARG_NUMERIC(0);
2106 Numeric num2 = PG_GETARG_NUMERIC(1);
2107 bool result;
2108
2109 result = cmp_numerics(num1, num2) <= 0;
2110
2111 PG_FREE_IF_COPY(num1, 0);
2112 PG_FREE_IF_COPY(num2, 1);
2113
2114 PG_RETURN_BOOL(result);
2115 }
2116
2117 static int
cmp_numerics(Numeric num1,Numeric num2)2118 cmp_numerics(Numeric num1, Numeric num2)
2119 {
2120 int result;
2121
2122 /*
2123 * We consider all NANs to be equal and larger than any non-NAN. This is
2124 * somewhat arbitrary; the important thing is to have a consistent sort
2125 * order.
2126 */
2127 if (NUMERIC_IS_NAN(num1))
2128 {
2129 if (NUMERIC_IS_NAN(num2))
2130 result = 0; /* NAN = NAN */
2131 else
2132 result = 1; /* NAN > non-NAN */
2133 }
2134 else if (NUMERIC_IS_NAN(num2))
2135 {
2136 result = -1; /* non-NAN < NAN */
2137 }
2138 else
2139 {
2140 result = cmp_var_common(NUMERIC_DIGITS(num1), NUMERIC_NDIGITS(num1),
2141 NUMERIC_WEIGHT(num1), NUMERIC_SIGN(num1),
2142 NUMERIC_DIGITS(num2), NUMERIC_NDIGITS(num2),
2143 NUMERIC_WEIGHT(num2), NUMERIC_SIGN(num2));
2144 }
2145
2146 return result;
2147 }
2148
2149 Datum
hash_numeric(PG_FUNCTION_ARGS)2150 hash_numeric(PG_FUNCTION_ARGS)
2151 {
2152 Numeric key = PG_GETARG_NUMERIC(0);
2153 Datum digit_hash;
2154 Datum result;
2155 int weight;
2156 int start_offset;
2157 int end_offset;
2158 int i;
2159 int hash_len;
2160 NumericDigit *digits;
2161
2162 /* If it's NaN, don't try to hash the rest of the fields */
2163 if (NUMERIC_IS_NAN(key))
2164 PG_RETURN_UINT32(0);
2165
2166 weight = NUMERIC_WEIGHT(key);
2167 start_offset = 0;
2168 end_offset = 0;
2169
2170 /*
2171 * Omit any leading or trailing zeros from the input to the hash. The
2172 * numeric implementation *should* guarantee that leading and trailing
2173 * zeros are suppressed, but we're paranoid. Note that we measure the
2174 * starting and ending offsets in units of NumericDigits, not bytes.
2175 */
2176 digits = NUMERIC_DIGITS(key);
2177 for (i = 0; i < NUMERIC_NDIGITS(key); i++)
2178 {
2179 if (digits[i] != (NumericDigit) 0)
2180 break;
2181
2182 start_offset++;
2183
2184 /*
2185 * The weight is effectively the # of digits before the decimal point,
2186 * so decrement it for each leading zero we skip.
2187 */
2188 weight--;
2189 }
2190
2191 /*
2192 * If there are no non-zero digits, then the value of the number is zero,
2193 * regardless of any other fields.
2194 */
2195 if (NUMERIC_NDIGITS(key) == start_offset)
2196 PG_RETURN_UINT32(-1);
2197
2198 for (i = NUMERIC_NDIGITS(key) - 1; i >= 0; i--)
2199 {
2200 if (digits[i] != (NumericDigit) 0)
2201 break;
2202
2203 end_offset++;
2204 }
2205
2206 /* If we get here, there should be at least one non-zero digit */
2207 Assert(start_offset + end_offset < NUMERIC_NDIGITS(key));
2208
2209 /*
2210 * Note that we don't hash on the Numeric's scale, since two numerics can
2211 * compare equal but have different scales. We also don't hash on the
2212 * sign, although we could: since a sign difference implies inequality,
2213 * this shouldn't affect correctness.
2214 */
2215 hash_len = NUMERIC_NDIGITS(key) - start_offset - end_offset;
2216 digit_hash = hash_any((unsigned char *) (NUMERIC_DIGITS(key) + start_offset),
2217 hash_len * sizeof(NumericDigit));
2218
2219 /* Mix in the weight, via XOR */
2220 result = digit_hash ^ weight;
2221
2222 PG_RETURN_DATUM(result);
2223 }
2224
2225
2226 /* ----------------------------------------------------------------------
2227 *
2228 * Basic arithmetic functions
2229 *
2230 * ----------------------------------------------------------------------
2231 */
2232
2233
2234 /*
2235 * numeric_add() -
2236 *
2237 * Add two numerics
2238 */
2239 Datum
numeric_add(PG_FUNCTION_ARGS)2240 numeric_add(PG_FUNCTION_ARGS)
2241 {
2242 Numeric num1 = PG_GETARG_NUMERIC(0);
2243 Numeric num2 = PG_GETARG_NUMERIC(1);
2244 NumericVar arg1;
2245 NumericVar arg2;
2246 NumericVar result;
2247 Numeric res;
2248
2249 /*
2250 * Handle NaN
2251 */
2252 if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
2253 PG_RETURN_NUMERIC(make_result(&const_nan));
2254
2255 /*
2256 * Unpack the values, let add_var() compute the result and return it.
2257 */
2258 init_var_from_num(num1, &arg1);
2259 init_var_from_num(num2, &arg2);
2260
2261 init_var(&result);
2262 add_var(&arg1, &arg2, &result);
2263
2264 res = make_result(&result);
2265
2266 free_var(&result);
2267
2268 PG_RETURN_NUMERIC(res);
2269 }
2270
2271
2272 /*
2273 * numeric_sub() -
2274 *
2275 * Subtract one numeric from another
2276 */
2277 Datum
numeric_sub(PG_FUNCTION_ARGS)2278 numeric_sub(PG_FUNCTION_ARGS)
2279 {
2280 Numeric num1 = PG_GETARG_NUMERIC(0);
2281 Numeric num2 = PG_GETARG_NUMERIC(1);
2282 NumericVar arg1;
2283 NumericVar arg2;
2284 NumericVar result;
2285 Numeric res;
2286
2287 /*
2288 * Handle NaN
2289 */
2290 if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
2291 PG_RETURN_NUMERIC(make_result(&const_nan));
2292
2293 /*
2294 * Unpack the values, let sub_var() compute the result and return it.
2295 */
2296 init_var_from_num(num1, &arg1);
2297 init_var_from_num(num2, &arg2);
2298
2299 init_var(&result);
2300 sub_var(&arg1, &arg2, &result);
2301
2302 res = make_result(&result);
2303
2304 free_var(&result);
2305
2306 PG_RETURN_NUMERIC(res);
2307 }
2308
2309
2310 /*
2311 * numeric_mul() -
2312 *
2313 * Calculate the product of two numerics
2314 */
2315 Datum
numeric_mul(PG_FUNCTION_ARGS)2316 numeric_mul(PG_FUNCTION_ARGS)
2317 {
2318 Numeric num1 = PG_GETARG_NUMERIC(0);
2319 Numeric num2 = PG_GETARG_NUMERIC(1);
2320 NumericVar arg1;
2321 NumericVar arg2;
2322 NumericVar result;
2323 Numeric res;
2324
2325 /*
2326 * Handle NaN
2327 */
2328 if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
2329 PG_RETURN_NUMERIC(make_result(&const_nan));
2330
2331 /*
2332 * Unpack the values, let mul_var() compute the result and return it.
2333 * Unlike add_var() and sub_var(), mul_var() will round its result. In the
2334 * case of numeric_mul(), which is invoked for the * operator on numerics,
2335 * we request exact representation for the product (rscale = sum(dscale of
2336 * arg1, dscale of arg2)). If the exact result has more digits after the
2337 * decimal point than can be stored in a numeric, we round it. Rounding
2338 * after computing the exact result ensures that the final result is
2339 * correctly rounded (rounding in mul_var() using a truncated product
2340 * would not guarantee this).
2341 */
2342 init_var_from_num(num1, &arg1);
2343 init_var_from_num(num2, &arg2);
2344
2345 init_var(&result);
2346 mul_var(&arg1, &arg2, &result, arg1.dscale + arg2.dscale);
2347
2348 if (result.dscale > NUMERIC_DSCALE_MAX)
2349 round_var(&result, NUMERIC_DSCALE_MAX);
2350
2351 res = make_result(&result);
2352
2353 free_var(&result);
2354
2355 PG_RETURN_NUMERIC(res);
2356 }
2357
2358
2359 /*
2360 * numeric_div() -
2361 *
2362 * Divide one numeric into another
2363 */
2364 Datum
numeric_div(PG_FUNCTION_ARGS)2365 numeric_div(PG_FUNCTION_ARGS)
2366 {
2367 Numeric num1 = PG_GETARG_NUMERIC(0);
2368 Numeric num2 = PG_GETARG_NUMERIC(1);
2369 NumericVar arg1;
2370 NumericVar arg2;
2371 NumericVar result;
2372 Numeric res;
2373 int rscale;
2374
2375 /*
2376 * Handle NaN
2377 */
2378 if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
2379 PG_RETURN_NUMERIC(make_result(&const_nan));
2380
2381 /*
2382 * Unpack the arguments
2383 */
2384 init_var_from_num(num1, &arg1);
2385 init_var_from_num(num2, &arg2);
2386
2387 init_var(&result);
2388
2389 /*
2390 * Select scale for division result
2391 */
2392 rscale = select_div_scale(&arg1, &arg2);
2393
2394 /*
2395 * Do the divide and return the result
2396 */
2397 div_var(&arg1, &arg2, &result, rscale, true);
2398
2399 res = make_result(&result);
2400
2401 free_var(&result);
2402
2403 PG_RETURN_NUMERIC(res);
2404 }
2405
2406
2407 /*
2408 * numeric_div_trunc() -
2409 *
2410 * Divide one numeric into another, truncating the result to an integer
2411 */
2412 Datum
numeric_div_trunc(PG_FUNCTION_ARGS)2413 numeric_div_trunc(PG_FUNCTION_ARGS)
2414 {
2415 Numeric num1 = PG_GETARG_NUMERIC(0);
2416 Numeric num2 = PG_GETARG_NUMERIC(1);
2417 NumericVar arg1;
2418 NumericVar arg2;
2419 NumericVar result;
2420 Numeric res;
2421
2422 /*
2423 * Handle NaN
2424 */
2425 if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
2426 PG_RETURN_NUMERIC(make_result(&const_nan));
2427
2428 /*
2429 * Unpack the arguments
2430 */
2431 init_var_from_num(num1, &arg1);
2432 init_var_from_num(num2, &arg2);
2433
2434 init_var(&result);
2435
2436 /*
2437 * Do the divide and return the result
2438 */
2439 div_var(&arg1, &arg2, &result, 0, false);
2440
2441 res = make_result(&result);
2442
2443 free_var(&result);
2444
2445 PG_RETURN_NUMERIC(res);
2446 }
2447
2448
2449 /*
2450 * numeric_mod() -
2451 *
2452 * Calculate the modulo of two numerics
2453 */
2454 Datum
numeric_mod(PG_FUNCTION_ARGS)2455 numeric_mod(PG_FUNCTION_ARGS)
2456 {
2457 Numeric num1 = PG_GETARG_NUMERIC(0);
2458 Numeric num2 = PG_GETARG_NUMERIC(1);
2459 Numeric res;
2460 NumericVar arg1;
2461 NumericVar arg2;
2462 NumericVar result;
2463
2464 if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
2465 PG_RETURN_NUMERIC(make_result(&const_nan));
2466
2467 init_var_from_num(num1, &arg1);
2468 init_var_from_num(num2, &arg2);
2469
2470 init_var(&result);
2471
2472 mod_var(&arg1, &arg2, &result);
2473
2474 res = make_result(&result);
2475
2476 free_var(&result);
2477
2478 PG_RETURN_NUMERIC(res);
2479 }
2480
2481
2482 /*
2483 * numeric_inc() -
2484 *
2485 * Increment a number by one
2486 */
2487 Datum
numeric_inc(PG_FUNCTION_ARGS)2488 numeric_inc(PG_FUNCTION_ARGS)
2489 {
2490 Numeric num = PG_GETARG_NUMERIC(0);
2491 NumericVar arg;
2492 Numeric res;
2493
2494 /*
2495 * Handle NaN
2496 */
2497 if (NUMERIC_IS_NAN(num))
2498 PG_RETURN_NUMERIC(make_result(&const_nan));
2499
2500 /*
2501 * Compute the result and return it
2502 */
2503 init_var_from_num(num, &arg);
2504
2505 add_var(&arg, &const_one, &arg);
2506
2507 res = make_result(&arg);
2508
2509 free_var(&arg);
2510
2511 PG_RETURN_NUMERIC(res);
2512 }
2513
2514
2515 /*
2516 * numeric_smaller() -
2517 *
2518 * Return the smaller of two numbers
2519 */
2520 Datum
numeric_smaller(PG_FUNCTION_ARGS)2521 numeric_smaller(PG_FUNCTION_ARGS)
2522 {
2523 Numeric num1 = PG_GETARG_NUMERIC(0);
2524 Numeric num2 = PG_GETARG_NUMERIC(1);
2525
2526 /*
2527 * Use cmp_numerics so that this will agree with the comparison operators,
2528 * particularly as regards comparisons involving NaN.
2529 */
2530 if (cmp_numerics(num1, num2) < 0)
2531 PG_RETURN_NUMERIC(num1);
2532 else
2533 PG_RETURN_NUMERIC(num2);
2534 }
2535
2536
2537 /*
2538 * numeric_larger() -
2539 *
2540 * Return the larger of two numbers
2541 */
2542 Datum
numeric_larger(PG_FUNCTION_ARGS)2543 numeric_larger(PG_FUNCTION_ARGS)
2544 {
2545 Numeric num1 = PG_GETARG_NUMERIC(0);
2546 Numeric num2 = PG_GETARG_NUMERIC(1);
2547
2548 /*
2549 * Use cmp_numerics so that this will agree with the comparison operators,
2550 * particularly as regards comparisons involving NaN.
2551 */
2552 if (cmp_numerics(num1, num2) > 0)
2553 PG_RETURN_NUMERIC(num1);
2554 else
2555 PG_RETURN_NUMERIC(num2);
2556 }
2557
2558
2559 /* ----------------------------------------------------------------------
2560 *
2561 * Advanced math functions
2562 *
2563 * ----------------------------------------------------------------------
2564 */
2565
2566 /*
2567 * numeric_fac()
2568 *
2569 * Compute factorial
2570 */
2571 Datum
numeric_fac(PG_FUNCTION_ARGS)2572 numeric_fac(PG_FUNCTION_ARGS)
2573 {
2574 int64 num = PG_GETARG_INT64(0);
2575 Numeric res;
2576 NumericVar fact;
2577 NumericVar result;
2578
2579 if (num <= 1)
2580 {
2581 res = make_result(&const_one);
2582 PG_RETURN_NUMERIC(res);
2583 }
2584 /* Fail immediately if the result would overflow */
2585 if (num > 32177)
2586 ereport(ERROR,
2587 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
2588 errmsg("value overflows numeric format")));
2589
2590 init_var(&fact);
2591 init_var(&result);
2592
2593 int64_to_numericvar(num, &result);
2594
2595 for (num = num - 1; num > 1; num--)
2596 {
2597 /* this loop can take awhile, so allow it to be interrupted */
2598 CHECK_FOR_INTERRUPTS();
2599
2600 int64_to_numericvar(num, &fact);
2601
2602 mul_var(&result, &fact, &result, 0);
2603 }
2604
2605 res = make_result(&result);
2606
2607 free_var(&fact);
2608 free_var(&result);
2609
2610 PG_RETURN_NUMERIC(res);
2611 }
2612
2613
2614 /*
2615 * numeric_sqrt() -
2616 *
2617 * Compute the square root of a numeric.
2618 */
2619 Datum
numeric_sqrt(PG_FUNCTION_ARGS)2620 numeric_sqrt(PG_FUNCTION_ARGS)
2621 {
2622 Numeric num = PG_GETARG_NUMERIC(0);
2623 Numeric res;
2624 NumericVar arg;
2625 NumericVar result;
2626 int sweight;
2627 int rscale;
2628
2629 /*
2630 * Handle NaN
2631 */
2632 if (NUMERIC_IS_NAN(num))
2633 PG_RETURN_NUMERIC(make_result(&const_nan));
2634
2635 /*
2636 * Unpack the argument and determine the result scale. We choose a scale
2637 * to give at least NUMERIC_MIN_SIG_DIGITS significant digits; but in any
2638 * case not less than the input's dscale.
2639 */
2640 init_var_from_num(num, &arg);
2641
2642 init_var(&result);
2643
2644 /* Assume the input was normalized, so arg.weight is accurate */
2645 sweight = (arg.weight + 1) * DEC_DIGITS / 2 - 1;
2646
2647 rscale = NUMERIC_MIN_SIG_DIGITS - sweight;
2648 rscale = Max(rscale, arg.dscale);
2649 rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
2650 rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
2651
2652 /*
2653 * Let sqrt_var() do the calculation and return the result.
2654 */
2655 sqrt_var(&arg, &result, rscale);
2656
2657 res = make_result(&result);
2658
2659 free_var(&result);
2660
2661 PG_RETURN_NUMERIC(res);
2662 }
2663
2664
2665 /*
2666 * numeric_exp() -
2667 *
2668 * Raise e to the power of x
2669 */
2670 Datum
numeric_exp(PG_FUNCTION_ARGS)2671 numeric_exp(PG_FUNCTION_ARGS)
2672 {
2673 Numeric num = PG_GETARG_NUMERIC(0);
2674 Numeric res;
2675 NumericVar arg;
2676 NumericVar result;
2677 int rscale;
2678 double val;
2679
2680 /*
2681 * Handle NaN
2682 */
2683 if (NUMERIC_IS_NAN(num))
2684 PG_RETURN_NUMERIC(make_result(&const_nan));
2685
2686 /*
2687 * Unpack the argument and determine the result scale. We choose a scale
2688 * to give at least NUMERIC_MIN_SIG_DIGITS significant digits; but in any
2689 * case not less than the input's dscale.
2690 */
2691 init_var_from_num(num, &arg);
2692
2693 init_var(&result);
2694
2695 /* convert input to float8, ignoring overflow */
2696 val = numericvar_to_double_no_overflow(&arg);
2697
2698 /*
2699 * log10(result) = num * log10(e), so this is approximately the decimal
2700 * weight of the result:
2701 */
2702 val *= 0.434294481903252;
2703
2704 /* limit to something that won't cause integer overflow */
2705 val = Max(val, -NUMERIC_MAX_RESULT_SCALE);
2706 val = Min(val, NUMERIC_MAX_RESULT_SCALE);
2707
2708 rscale = NUMERIC_MIN_SIG_DIGITS - (int) val;
2709 rscale = Max(rscale, arg.dscale);
2710 rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
2711 rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
2712
2713 /*
2714 * Let exp_var() do the calculation and return the result.
2715 */
2716 exp_var(&arg, &result, rscale);
2717
2718 res = make_result(&result);
2719
2720 free_var(&result);
2721
2722 PG_RETURN_NUMERIC(res);
2723 }
2724
2725
2726 /*
2727 * numeric_ln() -
2728 *
2729 * Compute the natural logarithm of x
2730 */
2731 Datum
numeric_ln(PG_FUNCTION_ARGS)2732 numeric_ln(PG_FUNCTION_ARGS)
2733 {
2734 Numeric num = PG_GETARG_NUMERIC(0);
2735 Numeric res;
2736 NumericVar arg;
2737 NumericVar result;
2738 int ln_dweight;
2739 int rscale;
2740
2741 /*
2742 * Handle NaN
2743 */
2744 if (NUMERIC_IS_NAN(num))
2745 PG_RETURN_NUMERIC(make_result(&const_nan));
2746
2747 init_var_from_num(num, &arg);
2748 init_var(&result);
2749
2750 /* Estimated dweight of logarithm */
2751 ln_dweight = estimate_ln_dweight(&arg);
2752
2753 rscale = NUMERIC_MIN_SIG_DIGITS - ln_dweight;
2754 rscale = Max(rscale, arg.dscale);
2755 rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
2756 rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
2757
2758 ln_var(&arg, &result, rscale);
2759
2760 res = make_result(&result);
2761
2762 free_var(&result);
2763
2764 PG_RETURN_NUMERIC(res);
2765 }
2766
2767
2768 /*
2769 * numeric_log() -
2770 *
2771 * Compute the logarithm of x in a given base
2772 */
2773 Datum
numeric_log(PG_FUNCTION_ARGS)2774 numeric_log(PG_FUNCTION_ARGS)
2775 {
2776 Numeric num1 = PG_GETARG_NUMERIC(0);
2777 Numeric num2 = PG_GETARG_NUMERIC(1);
2778 Numeric res;
2779 NumericVar arg1;
2780 NumericVar arg2;
2781 NumericVar result;
2782
2783 /*
2784 * Handle NaN
2785 */
2786 if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
2787 PG_RETURN_NUMERIC(make_result(&const_nan));
2788
2789 /*
2790 * Initialize things
2791 */
2792 init_var_from_num(num1, &arg1);
2793 init_var_from_num(num2, &arg2);
2794 init_var(&result);
2795
2796 /*
2797 * Call log_var() to compute and return the result; note it handles scale
2798 * selection itself.
2799 */
2800 log_var(&arg1, &arg2, &result);
2801
2802 res = make_result(&result);
2803
2804 free_var(&result);
2805
2806 PG_RETURN_NUMERIC(res);
2807 }
2808
2809
2810 /*
2811 * numeric_power() -
2812 *
2813 * Raise b to the power of x
2814 */
2815 Datum
numeric_power(PG_FUNCTION_ARGS)2816 numeric_power(PG_FUNCTION_ARGS)
2817 {
2818 Numeric num1 = PG_GETARG_NUMERIC(0);
2819 Numeric num2 = PG_GETARG_NUMERIC(1);
2820 Numeric res;
2821 NumericVar arg1;
2822 NumericVar arg2;
2823 NumericVar arg2_trunc;
2824 NumericVar result;
2825
2826 /*
2827 * Handle NaN
2828 */
2829 if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
2830 PG_RETURN_NUMERIC(make_result(&const_nan));
2831
2832 /*
2833 * Initialize things
2834 */
2835 init_var(&arg2_trunc);
2836 init_var(&result);
2837 init_var_from_num(num1, &arg1);
2838 init_var_from_num(num2, &arg2);
2839
2840 set_var_from_var(&arg2, &arg2_trunc);
2841 trunc_var(&arg2_trunc, 0);
2842
2843 /*
2844 * The SQL spec requires that we emit a particular SQLSTATE error code for
2845 * certain error conditions. Specifically, we don't return a
2846 * divide-by-zero error code for 0 ^ -1. Raising a negative number to a
2847 * non-integer power must produce the same error code, but that case is
2848 * handled in power_var().
2849 */
2850 if (cmp_var(&arg1, &const_zero) == 0 &&
2851 cmp_var(&arg2, &const_zero) < 0)
2852 ereport(ERROR,
2853 (errcode(ERRCODE_INVALID_ARGUMENT_FOR_POWER_FUNCTION),
2854 errmsg("zero raised to a negative power is undefined")));
2855
2856 /*
2857 * Call power_var() to compute and return the result; note it handles
2858 * scale selection itself.
2859 */
2860 power_var(&arg1, &arg2, &result);
2861
2862 res = make_result(&result);
2863
2864 free_var(&result);
2865 free_var(&arg2_trunc);
2866
2867 PG_RETURN_NUMERIC(res);
2868 }
2869
2870 /*
2871 * numeric_scale() -
2872 *
2873 * Returns the scale, i.e. the count of decimal digits in the fractional part
2874 */
2875 Datum
numeric_scale(PG_FUNCTION_ARGS)2876 numeric_scale(PG_FUNCTION_ARGS)
2877 {
2878 Numeric num = PG_GETARG_NUMERIC(0);
2879
2880 if (NUMERIC_IS_NAN(num))
2881 PG_RETURN_NULL();
2882
2883 PG_RETURN_INT32(NUMERIC_DSCALE(num));
2884 }
2885
2886
2887
2888 /* ----------------------------------------------------------------------
2889 *
2890 * Type conversion functions
2891 *
2892 * ----------------------------------------------------------------------
2893 */
2894
2895
2896 Datum
int4_numeric(PG_FUNCTION_ARGS)2897 int4_numeric(PG_FUNCTION_ARGS)
2898 {
2899 int32 val = PG_GETARG_INT32(0);
2900 Numeric res;
2901 NumericVar result;
2902
2903 init_var(&result);
2904
2905 int64_to_numericvar((int64) val, &result);
2906
2907 res = make_result(&result);
2908
2909 free_var(&result);
2910
2911 PG_RETURN_NUMERIC(res);
2912 }
2913
2914
2915 Datum
numeric_int4(PG_FUNCTION_ARGS)2916 numeric_int4(PG_FUNCTION_ARGS)
2917 {
2918 Numeric num = PG_GETARG_NUMERIC(0);
2919 NumericVar x;
2920 int32 result;
2921
2922 /* XXX would it be better to return NULL? */
2923 if (NUMERIC_IS_NAN(num))
2924 ereport(ERROR,
2925 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2926 errmsg("cannot convert NaN to integer")));
2927
2928 /* Convert to variable format, then convert to int4 */
2929 init_var_from_num(num, &x);
2930 result = numericvar_to_int32(&x);
2931 PG_RETURN_INT32(result);
2932 }
2933
2934 /*
2935 * Given a NumericVar, convert it to an int32. If the NumericVar
2936 * exceeds the range of an int32, raise the appropriate error via
2937 * ereport(). The input NumericVar is *not* free'd.
2938 */
2939 static int32
numericvar_to_int32(NumericVar * var)2940 numericvar_to_int32(NumericVar *var)
2941 {
2942 int64 val;
2943
2944 if (!numericvar_to_int64(var, &val))
2945 ereport(ERROR,
2946 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
2947 errmsg("integer out of range")));
2948
2949 if (unlikely(val < PG_INT32_MIN) || unlikely(val > PG_INT32_MAX))
2950 ereport(ERROR,
2951 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
2952 errmsg("integer out of range")));
2953
2954 /* Down-convert to int4 */
2955 return (int32) val;
2956 }
2957
2958 Datum
int8_numeric(PG_FUNCTION_ARGS)2959 int8_numeric(PG_FUNCTION_ARGS)
2960 {
2961 int64 val = PG_GETARG_INT64(0);
2962 Numeric res;
2963 NumericVar result;
2964
2965 init_var(&result);
2966
2967 int64_to_numericvar(val, &result);
2968
2969 res = make_result(&result);
2970
2971 free_var(&result);
2972
2973 PG_RETURN_NUMERIC(res);
2974 }
2975
2976
2977 Datum
numeric_int8(PG_FUNCTION_ARGS)2978 numeric_int8(PG_FUNCTION_ARGS)
2979 {
2980 Numeric num = PG_GETARG_NUMERIC(0);
2981 NumericVar x;
2982 int64 result;
2983
2984 /* XXX would it be better to return NULL? */
2985 if (NUMERIC_IS_NAN(num))
2986 ereport(ERROR,
2987 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2988 errmsg("cannot convert NaN to bigint")));
2989
2990 /* Convert to variable format and thence to int8 */
2991 init_var_from_num(num, &x);
2992
2993 if (!numericvar_to_int64(&x, &result))
2994 ereport(ERROR,
2995 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
2996 errmsg("bigint out of range")));
2997
2998 PG_RETURN_INT64(result);
2999 }
3000
3001
3002 Datum
int2_numeric(PG_FUNCTION_ARGS)3003 int2_numeric(PG_FUNCTION_ARGS)
3004 {
3005 int16 val = PG_GETARG_INT16(0);
3006 Numeric res;
3007 NumericVar result;
3008
3009 init_var(&result);
3010
3011 int64_to_numericvar((int64) val, &result);
3012
3013 res = make_result(&result);
3014
3015 free_var(&result);
3016
3017 PG_RETURN_NUMERIC(res);
3018 }
3019
3020
3021 Datum
numeric_int2(PG_FUNCTION_ARGS)3022 numeric_int2(PG_FUNCTION_ARGS)
3023 {
3024 Numeric num = PG_GETARG_NUMERIC(0);
3025 NumericVar x;
3026 int64 val;
3027 int16 result;
3028
3029 /* XXX would it be better to return NULL? */
3030 if (NUMERIC_IS_NAN(num))
3031 ereport(ERROR,
3032 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3033 errmsg("cannot convert NaN to smallint")));
3034
3035 /* Convert to variable format and thence to int8 */
3036 init_var_from_num(num, &x);
3037
3038 if (!numericvar_to_int64(&x, &val))
3039 ereport(ERROR,
3040 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
3041 errmsg("smallint out of range")));
3042
3043 if (unlikely(val < PG_INT16_MIN) || unlikely(val > PG_INT16_MAX))
3044 ereport(ERROR,
3045 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
3046 errmsg("smallint out of range")));
3047
3048 /* Down-convert to int2 */
3049 result = (int16) val;
3050
3051 PG_RETURN_INT16(result);
3052 }
3053
3054
3055 Datum
float8_numeric(PG_FUNCTION_ARGS)3056 float8_numeric(PG_FUNCTION_ARGS)
3057 {
3058 float8 val = PG_GETARG_FLOAT8(0);
3059 Numeric res;
3060 NumericVar result;
3061 char buf[DBL_DIG + 100];
3062
3063 if (isnan(val))
3064 PG_RETURN_NUMERIC(make_result(&const_nan));
3065
3066 if (isinf(val))
3067 ereport(ERROR,
3068 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3069 errmsg("cannot convert infinity to numeric")));
3070
3071 snprintf(buf, sizeof(buf), "%.*g", DBL_DIG, val);
3072
3073 init_var(&result);
3074
3075 /* Assume we need not worry about leading/trailing spaces */
3076 (void) set_var_from_str(buf, buf, &result);
3077
3078 res = make_result(&result);
3079
3080 free_var(&result);
3081
3082 PG_RETURN_NUMERIC(res);
3083 }
3084
3085
3086 Datum
numeric_float8(PG_FUNCTION_ARGS)3087 numeric_float8(PG_FUNCTION_ARGS)
3088 {
3089 Numeric num = PG_GETARG_NUMERIC(0);
3090 char *tmp;
3091 Datum result;
3092
3093 if (NUMERIC_IS_NAN(num))
3094 PG_RETURN_FLOAT8(get_float8_nan());
3095
3096 tmp = DatumGetCString(DirectFunctionCall1(numeric_out,
3097 NumericGetDatum(num)));
3098
3099 result = DirectFunctionCall1(float8in, CStringGetDatum(tmp));
3100
3101 pfree(tmp);
3102
3103 PG_RETURN_DATUM(result);
3104 }
3105
3106
3107 /*
3108 * Convert numeric to float8; if out of range, return +/- HUGE_VAL
3109 *
3110 * (internal helper function, not directly callable from SQL)
3111 */
3112 Datum
numeric_float8_no_overflow(PG_FUNCTION_ARGS)3113 numeric_float8_no_overflow(PG_FUNCTION_ARGS)
3114 {
3115 Numeric num = PG_GETARG_NUMERIC(0);
3116 double val;
3117
3118 if (NUMERIC_IS_NAN(num))
3119 PG_RETURN_FLOAT8(get_float8_nan());
3120
3121 val = numeric_to_double_no_overflow(num);
3122
3123 PG_RETURN_FLOAT8(val);
3124 }
3125
3126 Datum
float4_numeric(PG_FUNCTION_ARGS)3127 float4_numeric(PG_FUNCTION_ARGS)
3128 {
3129 float4 val = PG_GETARG_FLOAT4(0);
3130 Numeric res;
3131 NumericVar result;
3132 char buf[FLT_DIG + 100];
3133
3134 if (isnan(val))
3135 PG_RETURN_NUMERIC(make_result(&const_nan));
3136
3137 if (isinf(val))
3138 ereport(ERROR,
3139 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3140 errmsg("cannot convert infinity to numeric")));
3141
3142 snprintf(buf, sizeof(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 }
3155
3156
3157 Datum
numeric_float4(PG_FUNCTION_ARGS)3158 numeric_float4(PG_FUNCTION_ARGS)
3159 {
3160 Numeric num = PG_GETARG_NUMERIC(0);
3161 char *tmp;
3162 Datum result;
3163
3164 if (NUMERIC_IS_NAN(num))
3165 PG_RETURN_FLOAT4(get_float4_nan());
3166
3167 tmp = DatumGetCString(DirectFunctionCall1(numeric_out,
3168 NumericGetDatum(num)));
3169
3170 result = DirectFunctionCall1(float4in, CStringGetDatum(tmp));
3171
3172 pfree(tmp);
3173
3174 PG_RETURN_DATUM(result);
3175 }
3176
3177
3178 /* ----------------------------------------------------------------------
3179 *
3180 * Aggregate functions
3181 *
3182 * The transition datatype for all these aggregates is declared as INTERNAL.
3183 * Actually, it's a pointer to a NumericAggState allocated in the aggregate
3184 * context. The digit buffers for the NumericVars will be there too.
3185 *
3186 * On platforms which support 128-bit integers some aggregates instead use a
3187 * 128-bit integer based transition datatype to speed up calculations.
3188 *
3189 * ----------------------------------------------------------------------
3190 */
3191
3192 typedef struct NumericAggState
3193 {
3194 bool calcSumX2; /* if true, calculate sumX2 */
3195 MemoryContext agg_context; /* context we're calculating in */
3196 int64 N; /* count of processed numbers */
3197 NumericSumAccum sumX; /* sum of processed numbers */
3198 NumericSumAccum sumX2; /* sum of squares of processed numbers */
3199 int maxScale; /* maximum scale seen so far */
3200 int64 maxScaleCount; /* number of values seen with maximum scale */
3201 int64 NaNcount; /* count of NaN values (not included in N!) */
3202 } NumericAggState;
3203
3204 /*
3205 * Prepare state data for a numeric aggregate function that needs to compute
3206 * sum, count and optionally sum of squares of the input.
3207 */
3208 static NumericAggState *
makeNumericAggState(FunctionCallInfo fcinfo,bool calcSumX2)3209 makeNumericAggState(FunctionCallInfo fcinfo, bool calcSumX2)
3210 {
3211 NumericAggState *state;
3212 MemoryContext agg_context;
3213 MemoryContext old_context;
3214
3215 if (!AggCheckCallContext(fcinfo, &agg_context))
3216 elog(ERROR, "aggregate function called in non-aggregate context");
3217
3218 old_context = MemoryContextSwitchTo(agg_context);
3219
3220 state = (NumericAggState *) palloc0(sizeof(NumericAggState));
3221 state->calcSumX2 = calcSumX2;
3222 state->agg_context = agg_context;
3223
3224 MemoryContextSwitchTo(old_context);
3225
3226 return state;
3227 }
3228
3229 /*
3230 * Like makeNumericAggState(), but allocate the state in the current memory
3231 * context.
3232 */
3233 static NumericAggState *
makeNumericAggStateCurrentContext(bool calcSumX2)3234 makeNumericAggStateCurrentContext(bool calcSumX2)
3235 {
3236 NumericAggState *state;
3237
3238 state = (NumericAggState *) palloc0(sizeof(NumericAggState));
3239 state->calcSumX2 = calcSumX2;
3240 state->agg_context = CurrentMemoryContext;
3241
3242 return state;
3243 }
3244
3245 /*
3246 * Accumulate a new input value for numeric aggregate functions.
3247 */
3248 static void
do_numeric_accum(NumericAggState * state,Numeric newval)3249 do_numeric_accum(NumericAggState *state, Numeric newval)
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 }
3297
3298 /*
3299 * Attempt to remove an input value from the aggregated state.
3300 *
3301 * If the value cannot be removed then the function will return false; the
3302 * possible reasons for failing are described below.
3303 *
3304 * If we aggregate the values 1.01 and 2 then the result will be 3.01.
3305 * If we are then asked to un-aggregate the 1.01 then we must fail as we
3306 * won't be able to tell what the new aggregated value's dscale should be.
3307 * We don't want to return 2.00 (dscale = 2), since the sum's dscale would
3308 * have been zero if we'd really aggregated only 2.
3309 *
3310 * Note: alternatively, we could count the number of inputs with each possible
3311 * dscale (up to some sane limit). Not yet clear if it's worth the trouble.
3312 */
3313 static bool
do_numeric_discard(NumericAggState * state,Numeric newval)3314 do_numeric_discard(NumericAggState *state, Numeric newval)
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 }
3397
3398 /*
3399 * Generic transition function for numeric aggregates that require sumX2.
3400 */
3401 Datum
numeric_accum(PG_FUNCTION_ARGS)3402 numeric_accum(PG_FUNCTION_ARGS)
3403 {
3404 NumericAggState *state;
3405
3406 state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
3407
3408 /* Create the state data on the first call */
3409 if (state == NULL)
3410 state = makeNumericAggState(fcinfo, true);
3411
3412 if (!PG_ARGISNULL(1))
3413 do_numeric_accum(state, PG_GETARG_NUMERIC(1));
3414
3415 PG_RETURN_POINTER(state);
3416 }
3417
3418 /*
3419 * Generic combine function for numeric aggregates which require sumX2
3420 */
3421 Datum
numeric_combine(PG_FUNCTION_ARGS)3422 numeric_combine(PG_FUNCTION_ARGS)
3423 {
3424 NumericAggState *state1;
3425 NumericAggState *state2;
3426 MemoryContext agg_context;
3427 MemoryContext old_context;
3428
3429 if (!AggCheckCallContext(fcinfo, &agg_context))
3430 elog(ERROR, "aggregate function called in non-aggregate context");
3431
3432 state1 = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
3433 state2 = PG_ARGISNULL(1) ? NULL : (NumericAggState *) PG_GETARG_POINTER(1);
3434
3435 if (state2 == NULL)
3436 PG_RETURN_POINTER(state1);
3437
3438 /* manually copy all fields from state2 to state1 */
3439 if (state1 == NULL)
3440 {
3441 old_context = MemoryContextSwitchTo(agg_context);
3442
3443 state1 = makeNumericAggStateCurrentContext(true);
3444 state1->N = state2->N;
3445 state1->NaNcount = state2->NaNcount;
3446 state1->maxScale = state2->maxScale;
3447 state1->maxScaleCount = state2->maxScaleCount;
3448
3449 accum_sum_copy(&state1->sumX, &state2->sumX);
3450 accum_sum_copy(&state1->sumX2, &state2->sumX2);
3451
3452 MemoryContextSwitchTo(old_context);
3453
3454 PG_RETURN_POINTER(state1);
3455 }
3456
3457 state1->N += state2->N;
3458 state1->NaNcount += state2->NaNcount;
3459
3460 if (state2->N > 0)
3461 {
3462 /*
3463 * These are currently only needed for moving aggregates, but let's do
3464 * the right thing anyway...
3465 */
3466 if (state2->maxScale > state1->maxScale)
3467 {
3468 state1->maxScale = state2->maxScale;
3469 state1->maxScaleCount = state2->maxScaleCount;
3470 }
3471 else if (state2->maxScale == state1->maxScale)
3472 state1->maxScaleCount += state2->maxScaleCount;
3473
3474 /* The rest of this needs to work in the aggregate context */
3475 old_context = MemoryContextSwitchTo(agg_context);
3476
3477 /* Accumulate sums */
3478 accum_sum_combine(&state1->sumX, &state2->sumX);
3479 accum_sum_combine(&state1->sumX2, &state2->sumX2);
3480
3481 MemoryContextSwitchTo(old_context);
3482 }
3483 PG_RETURN_POINTER(state1);
3484 }
3485
3486 /*
3487 * Generic transition function for numeric aggregates that don't require sumX2.
3488 */
3489 Datum
numeric_avg_accum(PG_FUNCTION_ARGS)3490 numeric_avg_accum(PG_FUNCTION_ARGS)
3491 {
3492 NumericAggState *state;
3493
3494 state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
3495
3496 /* Create the state data on the first call */
3497 if (state == NULL)
3498 state = makeNumericAggState(fcinfo, false);
3499
3500 if (!PG_ARGISNULL(1))
3501 do_numeric_accum(state, PG_GETARG_NUMERIC(1));
3502
3503 PG_RETURN_POINTER(state);
3504 }
3505
3506 /*
3507 * Combine function for numeric aggregates which don't require sumX2
3508 */
3509 Datum
numeric_avg_combine(PG_FUNCTION_ARGS)3510 numeric_avg_combine(PG_FUNCTION_ARGS)
3511 {
3512 NumericAggState *state1;
3513 NumericAggState *state2;
3514 MemoryContext agg_context;
3515 MemoryContext old_context;
3516
3517 if (!AggCheckCallContext(fcinfo, &agg_context))
3518 elog(ERROR, "aggregate function called in non-aggregate context");
3519
3520 state1 = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
3521 state2 = PG_ARGISNULL(1) ? NULL : (NumericAggState *) PG_GETARG_POINTER(1);
3522
3523 if (state2 == NULL)
3524 PG_RETURN_POINTER(state1);
3525
3526 /* manually copy all fields from state2 to state1 */
3527 if (state1 == NULL)
3528 {
3529 old_context = MemoryContextSwitchTo(agg_context);
3530
3531 state1 = makeNumericAggStateCurrentContext(false);
3532 state1->N = state2->N;
3533 state1->NaNcount = state2->NaNcount;
3534 state1->maxScale = state2->maxScale;
3535 state1->maxScaleCount = state2->maxScaleCount;
3536
3537 accum_sum_copy(&state1->sumX, &state2->sumX);
3538
3539 MemoryContextSwitchTo(old_context);
3540
3541 PG_RETURN_POINTER(state1);
3542 }
3543
3544 state1->N += state2->N;
3545 state1->NaNcount += state2->NaNcount;
3546
3547 if (state2->N > 0)
3548 {
3549 /*
3550 * These are currently only needed for moving aggregates, but let's do
3551 * the right thing anyway...
3552 */
3553 if (state2->maxScale > state1->maxScale)
3554 {
3555 state1->maxScale = state2->maxScale;
3556 state1->maxScaleCount = state2->maxScaleCount;
3557 }
3558 else if (state2->maxScale == state1->maxScale)
3559 state1->maxScaleCount += state2->maxScaleCount;
3560
3561 /* The rest of this needs to work in the aggregate context */
3562 old_context = MemoryContextSwitchTo(agg_context);
3563
3564 /* Accumulate sums */
3565 accum_sum_combine(&state1->sumX, &state2->sumX);
3566
3567 MemoryContextSwitchTo(old_context);
3568 }
3569 PG_RETURN_POINTER(state1);
3570 }
3571
3572 /*
3573 * numeric_avg_serialize
3574 * Serialize NumericAggState for numeric aggregates that don't require
3575 * sumX2.
3576 */
3577 Datum
numeric_avg_serialize(PG_FUNCTION_ARGS)3578 numeric_avg_serialize(PG_FUNCTION_ARGS)
3579 {
3580 NumericAggState *state;
3581 StringInfoData buf;
3582 Datum temp;
3583 bytea *sumX;
3584 bytea *result;
3585 NumericVar tmp_var;
3586
3587 /* Ensure we disallow calling when not in aggregate context */
3588 if (!AggCheckCallContext(fcinfo, NULL))
3589 elog(ERROR, "aggregate function called in non-aggregate context");
3590
3591 state = (NumericAggState *) PG_GETARG_POINTER(0);
3592
3593 /*
3594 * This is a little wasteful since make_result converts the NumericVar
3595 * into a Numeric and numeric_send converts it back again. Is it worth
3596 * splitting the tasks in numeric_send into separate functions to stop
3597 * this? Doing so would also remove the fmgr call overhead.
3598 */
3599 init_var(&tmp_var);
3600 accum_sum_final(&state->sumX, &tmp_var);
3601
3602 temp = DirectFunctionCall1(numeric_send,
3603 NumericGetDatum(make_result(&tmp_var)));
3604 sumX = DatumGetByteaPP(temp);
3605 free_var(&tmp_var);
3606
3607 pq_begintypsend(&buf);
3608
3609 /* N */
3610 pq_sendint64(&buf, state->N);
3611
3612 /* sumX */
3613 pq_sendbytes(&buf, VARDATA_ANY(sumX), VARSIZE_ANY_EXHDR(sumX));
3614
3615 /* maxScale */
3616 pq_sendint(&buf, state->maxScale, 4);
3617
3618 /* maxScaleCount */
3619 pq_sendint64(&buf, state->maxScaleCount);
3620
3621 /* NaNcount */
3622 pq_sendint64(&buf, state->NaNcount);
3623
3624 result = pq_endtypsend(&buf);
3625
3626 PG_RETURN_BYTEA_P(result);
3627 }
3628
3629 /*
3630 * numeric_avg_deserialize
3631 * Deserialize bytea into NumericAggState for numeric aggregates that
3632 * don't require sumX2.
3633 */
3634 Datum
numeric_avg_deserialize(PG_FUNCTION_ARGS)3635 numeric_avg_deserialize(PG_FUNCTION_ARGS)
3636 {
3637 bytea *sstate;
3638 NumericAggState *result;
3639 Datum temp;
3640 NumericVar tmp_var;
3641 StringInfoData buf;
3642
3643 if (!AggCheckCallContext(fcinfo, NULL))
3644 elog(ERROR, "aggregate function called in non-aggregate context");
3645
3646 sstate = PG_GETARG_BYTEA_PP(0);
3647
3648 /*
3649 * Copy the bytea into a StringInfo so that we can "receive" it using the
3650 * standard recv-function infrastructure.
3651 */
3652 initStringInfo(&buf);
3653 appendBinaryStringInfo(&buf,
3654 VARDATA_ANY(sstate), VARSIZE_ANY_EXHDR(sstate));
3655
3656 result = makeNumericAggStateCurrentContext(false);
3657
3658 /* N */
3659 result->N = pq_getmsgint64(&buf);
3660
3661 /* sumX */
3662 temp = DirectFunctionCall3(numeric_recv,
3663 PointerGetDatum(&buf),
3664 InvalidOid,
3665 -1);
3666 init_var_from_num(DatumGetNumeric(temp), &tmp_var);
3667 accum_sum_add(&(result->sumX), &tmp_var);
3668
3669 /* maxScale */
3670 result->maxScale = pq_getmsgint(&buf, 4);
3671
3672 /* maxScaleCount */
3673 result->maxScaleCount = pq_getmsgint64(&buf);
3674
3675 /* NaNcount */
3676 result->NaNcount = pq_getmsgint64(&buf);
3677
3678 pq_getmsgend(&buf);
3679 pfree(buf.data);
3680
3681 PG_RETURN_POINTER(result);
3682 }
3683
3684 /*
3685 * numeric_serialize
3686 * Serialization function for NumericAggState for numeric aggregates that
3687 * require sumX2.
3688 */
3689 Datum
numeric_serialize(PG_FUNCTION_ARGS)3690 numeric_serialize(PG_FUNCTION_ARGS)
3691 {
3692 NumericAggState *state;
3693 StringInfoData buf;
3694 Datum temp;
3695 bytea *sumX;
3696 NumericVar tmp_var;
3697 bytea *sumX2;
3698 bytea *result;
3699
3700 /* Ensure we disallow calling when not in aggregate context */
3701 if (!AggCheckCallContext(fcinfo, NULL))
3702 elog(ERROR, "aggregate function called in non-aggregate context");
3703
3704 state = (NumericAggState *) PG_GETARG_POINTER(0);
3705
3706 /*
3707 * This is a little wasteful since make_result converts the NumericVar
3708 * into a Numeric and numeric_send converts it back again. Is it worth
3709 * splitting the tasks in numeric_send into separate functions to stop
3710 * this? Doing so would also remove the fmgr call overhead.
3711 */
3712 init_var(&tmp_var);
3713
3714 accum_sum_final(&state->sumX, &tmp_var);
3715 temp = DirectFunctionCall1(numeric_send,
3716 NumericGetDatum(make_result(&tmp_var)));
3717 sumX = DatumGetByteaPP(temp);
3718
3719 accum_sum_final(&state->sumX2, &tmp_var);
3720 temp = DirectFunctionCall1(numeric_send,
3721 NumericGetDatum(make_result(&tmp_var)));
3722 sumX2 = DatumGetByteaPP(temp);
3723
3724 free_var(&tmp_var);
3725
3726 pq_begintypsend(&buf);
3727
3728 /* N */
3729 pq_sendint64(&buf, state->N);
3730
3731 /* sumX */
3732 pq_sendbytes(&buf, VARDATA_ANY(sumX), VARSIZE_ANY_EXHDR(sumX));
3733
3734 /* sumX2 */
3735 pq_sendbytes(&buf, VARDATA_ANY(sumX2), VARSIZE_ANY_EXHDR(sumX2));
3736
3737 /* maxScale */
3738 pq_sendint(&buf, state->maxScale, 4);
3739
3740 /* maxScaleCount */
3741 pq_sendint64(&buf, state->maxScaleCount);
3742
3743 /* NaNcount */
3744 pq_sendint64(&buf, state->NaNcount);
3745
3746 result = pq_endtypsend(&buf);
3747
3748 PG_RETURN_BYTEA_P(result);
3749 }
3750
3751 /*
3752 * numeric_deserialize
3753 * Deserialization function for NumericAggState for numeric aggregates that
3754 * require sumX2.
3755 */
3756 Datum
numeric_deserialize(PG_FUNCTION_ARGS)3757 numeric_deserialize(PG_FUNCTION_ARGS)
3758 {
3759 bytea *sstate;
3760 NumericAggState *result;
3761 Datum temp;
3762 NumericVar sumX_var;
3763 NumericVar sumX2_var;
3764 StringInfoData buf;
3765
3766 if (!AggCheckCallContext(fcinfo, NULL))
3767 elog(ERROR, "aggregate function called in non-aggregate context");
3768
3769 sstate = PG_GETARG_BYTEA_PP(0);
3770
3771 /*
3772 * Copy the bytea into a StringInfo so that we can "receive" it using the
3773 * standard recv-function infrastructure.
3774 */
3775 initStringInfo(&buf);
3776 appendBinaryStringInfo(&buf,
3777 VARDATA_ANY(sstate), VARSIZE_ANY_EXHDR(sstate));
3778
3779 result = makeNumericAggStateCurrentContext(false);
3780
3781 /* N */
3782 result->N = pq_getmsgint64(&buf);
3783
3784 /* sumX */
3785 temp = DirectFunctionCall3(numeric_recv,
3786 PointerGetDatum(&buf),
3787 InvalidOid,
3788 -1);
3789 init_var_from_num(DatumGetNumeric(temp), &sumX_var);
3790 accum_sum_add(&(result->sumX), &sumX_var);
3791
3792 /* sumX2 */
3793 temp = DirectFunctionCall3(numeric_recv,
3794 PointerGetDatum(&buf),
3795 InvalidOid,
3796 -1);
3797 init_var_from_num(DatumGetNumeric(temp), &sumX2_var);
3798 accum_sum_add(&(result->sumX2), &sumX2_var);
3799
3800 /* maxScale */
3801 result->maxScale = pq_getmsgint(&buf, 4);
3802
3803 /* maxScaleCount */
3804 result->maxScaleCount = pq_getmsgint64(&buf);
3805
3806 /* NaNcount */
3807 result->NaNcount = pq_getmsgint64(&buf);
3808
3809 pq_getmsgend(&buf);
3810 pfree(buf.data);
3811
3812 PG_RETURN_POINTER(result);
3813 }
3814
3815 /*
3816 * Generic inverse transition function for numeric aggregates
3817 * (with or without requirement for X^2).
3818 */
3819 Datum
numeric_accum_inv(PG_FUNCTION_ARGS)3820 numeric_accum_inv(PG_FUNCTION_ARGS)
3821 {
3822 NumericAggState *state;
3823
3824 state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
3825
3826 /* Should not get here with no state */
3827 if (state == NULL)
3828 elog(ERROR, "numeric_accum_inv called with NULL state");
3829
3830 if (!PG_ARGISNULL(1))
3831 {
3832 /* If we fail to perform the inverse transition, return NULL */
3833 if (!do_numeric_discard(state, PG_GETARG_NUMERIC(1)))
3834 PG_RETURN_NULL();
3835 }
3836
3837 PG_RETURN_POINTER(state);
3838 }
3839
3840
3841 /*
3842 * Integer data types in general use Numeric accumulators to share code
3843 * and avoid risk of overflow.
3844 *
3845 * However for performance reasons optimized special-purpose accumulator
3846 * routines are used when possible.
3847 *
3848 * On platforms with 128-bit integer support, the 128-bit routines will be
3849 * used when sum(X) or sum(X*X) fit into 128-bit.
3850 *
3851 * For 16 and 32 bit inputs, the N and sum(X) fit into 64-bit so the 64-bit
3852 * accumulators will be used for SUM and AVG of these data types.
3853 */
3854
3855 #ifdef HAVE_INT128
3856 typedef struct Int128AggState
3857 {
3858 bool calcSumX2; /* if true, calculate sumX2 */
3859 int64 N; /* count of processed numbers */
3860 int128 sumX; /* sum of processed numbers */
3861 int128 sumX2; /* sum of squares of processed numbers */
3862 } Int128AggState;
3863
3864 /*
3865 * Prepare state data for a 128-bit aggregate function that needs to compute
3866 * sum, count and optionally sum of squares of the input.
3867 */
3868 static Int128AggState *
makeInt128AggState(FunctionCallInfo fcinfo,bool calcSumX2)3869 makeInt128AggState(FunctionCallInfo fcinfo, bool calcSumX2)
3870 {
3871 Int128AggState *state;
3872 MemoryContext agg_context;
3873 MemoryContext old_context;
3874
3875 if (!AggCheckCallContext(fcinfo, &agg_context))
3876 elog(ERROR, "aggregate function called in non-aggregate context");
3877
3878 old_context = MemoryContextSwitchTo(agg_context);
3879
3880 state = (Int128AggState *) palloc0(sizeof(Int128AggState));
3881 state->calcSumX2 = calcSumX2;
3882
3883 MemoryContextSwitchTo(old_context);
3884
3885 return state;
3886 }
3887
3888 /*
3889 * Like makeInt128AggState(), but allocate the state in the current memory
3890 * context.
3891 */
3892 static Int128AggState *
makeInt128AggStateCurrentContext(bool calcSumX2)3893 makeInt128AggStateCurrentContext(bool calcSumX2)
3894 {
3895 Int128AggState *state;
3896
3897 state = (Int128AggState *) palloc0(sizeof(Int128AggState));
3898 state->calcSumX2 = calcSumX2;
3899
3900 return state;
3901 }
3902
3903 /*
3904 * Accumulate a new input value for 128-bit aggregate functions.
3905 */
3906 static void
do_int128_accum(Int128AggState * state,int128 newval)3907 do_int128_accum(Int128AggState *state, int128 newval)
3908 {
3909 if (state->calcSumX2)
3910 state->sumX2 += newval * newval;
3911
3912 state->sumX += newval;
3913 state->N++;
3914 }
3915
3916 /*
3917 * Remove an input value from the aggregated state.
3918 */
3919 static void
do_int128_discard(Int128AggState * state,int128 newval)3920 do_int128_discard(Int128AggState *state, int128 newval)
3921 {
3922 if (state->calcSumX2)
3923 state->sumX2 -= newval * newval;
3924
3925 state->sumX -= newval;
3926 state->N--;
3927 }
3928
3929 typedef Int128AggState PolyNumAggState;
3930 #define makePolyNumAggState makeInt128AggState
3931 #define makePolyNumAggStateCurrentContext makeInt128AggStateCurrentContext
3932 #else
3933 typedef NumericAggState PolyNumAggState;
3934 #define makePolyNumAggState makeNumericAggState
3935 #define makePolyNumAggStateCurrentContext makeNumericAggStateCurrentContext
3936 #endif
3937
3938 Datum
int2_accum(PG_FUNCTION_ARGS)3939 int2_accum(PG_FUNCTION_ARGS)
3940 {
3941 PolyNumAggState *state;
3942
3943 state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
3944
3945 /* Create the state data on the first call */
3946 if (state == NULL)
3947 state = makePolyNumAggState(fcinfo, true);
3948
3949 if (!PG_ARGISNULL(1))
3950 {
3951 #ifdef HAVE_INT128
3952 do_int128_accum(state, (int128) PG_GETARG_INT16(1));
3953 #else
3954 Numeric newval;
3955
3956 newval = DatumGetNumeric(DirectFunctionCall1(int2_numeric,
3957 PG_GETARG_DATUM(1)));
3958 do_numeric_accum(state, newval);
3959 #endif
3960 }
3961
3962 PG_RETURN_POINTER(state);
3963 }
3964
3965 Datum
int4_accum(PG_FUNCTION_ARGS)3966 int4_accum(PG_FUNCTION_ARGS)
3967 {
3968 PolyNumAggState *state;
3969
3970 state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
3971
3972 /* Create the state data on the first call */
3973 if (state == NULL)
3974 state = makePolyNumAggState(fcinfo, true);
3975
3976 if (!PG_ARGISNULL(1))
3977 {
3978 #ifdef HAVE_INT128
3979 do_int128_accum(state, (int128) PG_GETARG_INT32(1));
3980 #else
3981 Numeric newval;
3982
3983 newval = DatumGetNumeric(DirectFunctionCall1(int4_numeric,
3984 PG_GETARG_DATUM(1)));
3985 do_numeric_accum(state, newval);
3986 #endif
3987 }
3988
3989 PG_RETURN_POINTER(state);
3990 }
3991
3992 Datum
int8_accum(PG_FUNCTION_ARGS)3993 int8_accum(PG_FUNCTION_ARGS)
3994 {
3995 NumericAggState *state;
3996
3997 state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
3998
3999 /* Create the state data on the first call */
4000 if (state == NULL)
4001 state = makeNumericAggState(fcinfo, true);
4002
4003 if (!PG_ARGISNULL(1))
4004 {
4005 Numeric newval;
4006
4007 newval = DatumGetNumeric(DirectFunctionCall1(int8_numeric,
4008 PG_GETARG_DATUM(1)));
4009 do_numeric_accum(state, newval);
4010 }
4011
4012 PG_RETURN_POINTER(state);
4013 }
4014
4015 /*
4016 * Combine function for numeric aggregates which require sumX2
4017 */
4018 Datum
numeric_poly_combine(PG_FUNCTION_ARGS)4019 numeric_poly_combine(PG_FUNCTION_ARGS)
4020 {
4021 PolyNumAggState *state1;
4022 PolyNumAggState *state2;
4023 MemoryContext agg_context;
4024 MemoryContext old_context;
4025
4026 if (!AggCheckCallContext(fcinfo, &agg_context))
4027 elog(ERROR, "aggregate function called in non-aggregate context");
4028
4029 state1 = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
4030 state2 = PG_ARGISNULL(1) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(1);
4031
4032 if (state2 == NULL)
4033 PG_RETURN_POINTER(state1);
4034
4035 /* manually copy all fields from state2 to state1 */
4036 if (state1 == NULL)
4037 {
4038 old_context = MemoryContextSwitchTo(agg_context);
4039
4040 state1 = makePolyNumAggState(fcinfo, true);
4041 state1->N = state2->N;
4042
4043 #ifdef HAVE_INT128
4044 state1->sumX = state2->sumX;
4045 state1->sumX2 = state2->sumX2;
4046 #else
4047 accum_sum_copy(&state1->sumX, &state2->sumX);
4048 accum_sum_copy(&state1->sumX2, &state2->sumX2);
4049 #endif
4050
4051 MemoryContextSwitchTo(old_context);
4052
4053 PG_RETURN_POINTER(state1);
4054 }
4055
4056 if (state2->N > 0)
4057 {
4058 state1->N += state2->N;
4059
4060 #ifdef HAVE_INT128
4061 state1->sumX += state2->sumX;
4062 state1->sumX2 += state2->sumX2;
4063 #else
4064 /* The rest of this needs to work in the aggregate context */
4065 old_context = MemoryContextSwitchTo(agg_context);
4066
4067 /* Accumulate sums */
4068 accum_sum_combine(&state1->sumX, &state2->sumX);
4069 accum_sum_combine(&state1->sumX2, &state2->sumX2);
4070
4071 MemoryContextSwitchTo(old_context);
4072 #endif
4073
4074 }
4075 PG_RETURN_POINTER(state1);
4076 }
4077
4078 /*
4079 * numeric_poly_serialize
4080 * Serialize PolyNumAggState into bytea for aggregate functions which
4081 * require sumX2.
4082 */
4083 Datum
numeric_poly_serialize(PG_FUNCTION_ARGS)4084 numeric_poly_serialize(PG_FUNCTION_ARGS)
4085 {
4086 PolyNumAggState *state;
4087 StringInfoData buf;
4088 bytea *sumX;
4089 bytea *sumX2;
4090 bytea *result;
4091
4092 /* Ensure we disallow calling when not in aggregate context */
4093 if (!AggCheckCallContext(fcinfo, NULL))
4094 elog(ERROR, "aggregate function called in non-aggregate context");
4095
4096 state = (PolyNumAggState *) PG_GETARG_POINTER(0);
4097
4098 /*
4099 * If the platform supports int128 then sumX and sumX2 will be a 128 bit
4100 * integer type. Here we'll convert that into a numeric type so that the
4101 * combine state is in the same format for both int128 enabled machines
4102 * and machines which don't support that type. The logic here is that one
4103 * day we might like to send these over to another server for further
4104 * processing and we want a standard format to work with.
4105 */
4106 {
4107 Datum temp;
4108 NumericVar num;
4109
4110 init_var(&num);
4111
4112 #ifdef HAVE_INT128
4113 int128_to_numericvar(state->sumX, &num);
4114 #else
4115 accum_sum_final(&state->sumX, &num);
4116 #endif
4117 temp = DirectFunctionCall1(numeric_send,
4118 NumericGetDatum(make_result(&num)));
4119 sumX = DatumGetByteaPP(temp);
4120
4121 #ifdef HAVE_INT128
4122 int128_to_numericvar(state->sumX2, &num);
4123 #else
4124 accum_sum_final(&state->sumX2, &num);
4125 #endif
4126 temp = DirectFunctionCall1(numeric_send,
4127 NumericGetDatum(make_result(&num)));
4128 sumX2 = DatumGetByteaPP(temp);
4129
4130 free_var(&num);
4131 }
4132
4133 pq_begintypsend(&buf);
4134
4135 /* N */
4136 pq_sendint64(&buf, state->N);
4137
4138 /* sumX */
4139 pq_sendbytes(&buf, VARDATA_ANY(sumX), VARSIZE_ANY_EXHDR(sumX));
4140
4141 /* sumX2 */
4142 pq_sendbytes(&buf, VARDATA_ANY(sumX2), VARSIZE_ANY_EXHDR(sumX2));
4143
4144 result = pq_endtypsend(&buf);
4145
4146 PG_RETURN_BYTEA_P(result);
4147 }
4148
4149 /*
4150 * numeric_poly_deserialize
4151 * Deserialize PolyNumAggState from bytea for aggregate functions which
4152 * require sumX2.
4153 */
4154 Datum
numeric_poly_deserialize(PG_FUNCTION_ARGS)4155 numeric_poly_deserialize(PG_FUNCTION_ARGS)
4156 {
4157 bytea *sstate;
4158 PolyNumAggState *result;
4159 Datum sumX;
4160 NumericVar sumX_var;
4161 Datum sumX2;
4162 NumericVar sumX2_var;
4163 StringInfoData buf;
4164
4165 if (!AggCheckCallContext(fcinfo, NULL))
4166 elog(ERROR, "aggregate function called in non-aggregate context");
4167
4168 sstate = PG_GETARG_BYTEA_PP(0);
4169
4170 /*
4171 * Copy the bytea into a StringInfo so that we can "receive" it using the
4172 * standard recv-function infrastructure.
4173 */
4174 initStringInfo(&buf);
4175 appendBinaryStringInfo(&buf,
4176 VARDATA_ANY(sstate), VARSIZE_ANY_EXHDR(sstate));
4177
4178 result = makePolyNumAggStateCurrentContext(false);
4179
4180 /* N */
4181 result->N = pq_getmsgint64(&buf);
4182
4183 /* sumX */
4184 sumX = DirectFunctionCall3(numeric_recv,
4185 PointerGetDatum(&buf),
4186 InvalidOid,
4187 -1);
4188
4189 /* sumX2 */
4190 sumX2 = DirectFunctionCall3(numeric_recv,
4191 PointerGetDatum(&buf),
4192 InvalidOid,
4193 -1);
4194
4195 init_var_from_num(DatumGetNumeric(sumX), &sumX_var);
4196 #ifdef HAVE_INT128
4197 numericvar_to_int128(&sumX_var, &result->sumX);
4198 #else
4199 accum_sum_add(&result->sumX, &sumX_var);
4200 #endif
4201
4202 init_var_from_num(DatumGetNumeric(sumX2), &sumX2_var);
4203 #ifdef HAVE_INT128
4204 numericvar_to_int128(&sumX2_var, &result->sumX2);
4205 #else
4206 accum_sum_add(&result->sumX2, &sumX2_var);
4207 #endif
4208
4209 pq_getmsgend(&buf);
4210 pfree(buf.data);
4211
4212 PG_RETURN_POINTER(result);
4213 }
4214
4215 /*
4216 * Transition function for int8 input when we don't need sumX2.
4217 */
4218 Datum
int8_avg_accum(PG_FUNCTION_ARGS)4219 int8_avg_accum(PG_FUNCTION_ARGS)
4220 {
4221 PolyNumAggState *state;
4222
4223 state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
4224
4225 /* Create the state data on the first call */
4226 if (state == NULL)
4227 state = makePolyNumAggState(fcinfo, false);
4228
4229 if (!PG_ARGISNULL(1))
4230 {
4231 #ifdef HAVE_INT128
4232 do_int128_accum(state, (int128) PG_GETARG_INT64(1));
4233 #else
4234 Numeric newval;
4235
4236 newval = DatumGetNumeric(DirectFunctionCall1(int8_numeric,
4237 PG_GETARG_DATUM(1)));
4238 do_numeric_accum(state, newval);
4239 #endif
4240 }
4241
4242 PG_RETURN_POINTER(state);
4243 }
4244
4245 /*
4246 * Combine function for PolyNumAggState for aggregates which don't require
4247 * sumX2
4248 */
4249 Datum
int8_avg_combine(PG_FUNCTION_ARGS)4250 int8_avg_combine(PG_FUNCTION_ARGS)
4251 {
4252 PolyNumAggState *state1;
4253 PolyNumAggState *state2;
4254 MemoryContext agg_context;
4255 MemoryContext old_context;
4256
4257 if (!AggCheckCallContext(fcinfo, &agg_context))
4258 elog(ERROR, "aggregate function called in non-aggregate context");
4259
4260 state1 = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
4261 state2 = PG_ARGISNULL(1) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(1);
4262
4263 if (state2 == NULL)
4264 PG_RETURN_POINTER(state1);
4265
4266 /* manually copy all fields from state2 to state1 */
4267 if (state1 == NULL)
4268 {
4269 old_context = MemoryContextSwitchTo(agg_context);
4270
4271 state1 = makePolyNumAggState(fcinfo, false);
4272 state1->N = state2->N;
4273
4274 #ifdef HAVE_INT128
4275 state1->sumX = state2->sumX;
4276 #else
4277 accum_sum_copy(&state1->sumX, &state2->sumX);
4278 #endif
4279 MemoryContextSwitchTo(old_context);
4280
4281 PG_RETURN_POINTER(state1);
4282 }
4283
4284 if (state2->N > 0)
4285 {
4286 state1->N += state2->N;
4287
4288 #ifdef HAVE_INT128
4289 state1->sumX += state2->sumX;
4290 #else
4291 /* The rest of this needs to work in the aggregate context */
4292 old_context = MemoryContextSwitchTo(agg_context);
4293
4294 /* Accumulate sums */
4295 accum_sum_combine(&state1->sumX, &state2->sumX);
4296
4297 MemoryContextSwitchTo(old_context);
4298 #endif
4299
4300 }
4301 PG_RETURN_POINTER(state1);
4302 }
4303
4304 /*
4305 * int8_avg_serialize
4306 * Serialize PolyNumAggState into bytea using the standard
4307 * recv-function infrastructure.
4308 */
4309 Datum
int8_avg_serialize(PG_FUNCTION_ARGS)4310 int8_avg_serialize(PG_FUNCTION_ARGS)
4311 {
4312 PolyNumAggState *state;
4313 StringInfoData buf;
4314 bytea *sumX;
4315 bytea *result;
4316
4317 /* Ensure we disallow calling when not in aggregate context */
4318 if (!AggCheckCallContext(fcinfo, NULL))
4319 elog(ERROR, "aggregate function called in non-aggregate context");
4320
4321 state = (PolyNumAggState *) PG_GETARG_POINTER(0);
4322
4323 /*
4324 * If the platform supports int128 then sumX will be a 128 integer type.
4325 * Here we'll convert that into a numeric type so that the combine state
4326 * is in the same format for both int128 enabled machines and machines
4327 * which don't support that type. The logic here is that one day we might
4328 * like to send these over to another server for further processing and we
4329 * want a standard format to work with.
4330 */
4331 {
4332 Datum temp;
4333 NumericVar num;
4334
4335 init_var(&num);
4336
4337 #ifdef HAVE_INT128
4338 int128_to_numericvar(state->sumX, &num);
4339 #else
4340 accum_sum_final(&state->sumX, &num);
4341 #endif
4342 temp = DirectFunctionCall1(numeric_send,
4343 NumericGetDatum(make_result(&num)));
4344 sumX = DatumGetByteaPP(temp);
4345
4346 free_var(&num);
4347 }
4348
4349 pq_begintypsend(&buf);
4350
4351 /* N */
4352 pq_sendint64(&buf, state->N);
4353
4354 /* sumX */
4355 pq_sendbytes(&buf, VARDATA_ANY(sumX), VARSIZE_ANY_EXHDR(sumX));
4356
4357 result = pq_endtypsend(&buf);
4358
4359 PG_RETURN_BYTEA_P(result);
4360 }
4361
4362 /*
4363 * int8_avg_deserialize
4364 * Deserialize bytea back into PolyNumAggState.
4365 */
4366 Datum
int8_avg_deserialize(PG_FUNCTION_ARGS)4367 int8_avg_deserialize(PG_FUNCTION_ARGS)
4368 {
4369 bytea *sstate;
4370 PolyNumAggState *result;
4371 StringInfoData buf;
4372 Datum temp;
4373 NumericVar num;
4374
4375 if (!AggCheckCallContext(fcinfo, NULL))
4376 elog(ERROR, "aggregate function called in non-aggregate context");
4377
4378 sstate = PG_GETARG_BYTEA_PP(0);
4379
4380 /*
4381 * Copy the bytea into a StringInfo so that we can "receive" it using the
4382 * standard recv-function infrastructure.
4383 */
4384 initStringInfo(&buf);
4385 appendBinaryStringInfo(&buf,
4386 VARDATA_ANY(sstate), VARSIZE_ANY_EXHDR(sstate));
4387
4388 result = makePolyNumAggStateCurrentContext(false);
4389
4390 /* N */
4391 result->N = pq_getmsgint64(&buf);
4392
4393 /* sumX */
4394 temp = DirectFunctionCall3(numeric_recv,
4395 PointerGetDatum(&buf),
4396 InvalidOid,
4397 -1);
4398 init_var_from_num(DatumGetNumeric(temp), &num);
4399 #ifdef HAVE_INT128
4400 numericvar_to_int128(&num, &result->sumX);
4401 #else
4402 accum_sum_add(&result->sumX, &num);
4403 #endif
4404
4405 pq_getmsgend(&buf);
4406 pfree(buf.data);
4407
4408 PG_RETURN_POINTER(result);
4409 }
4410
4411 /*
4412 * Inverse transition functions to go with the above.
4413 */
4414
4415 Datum
int2_accum_inv(PG_FUNCTION_ARGS)4416 int2_accum_inv(PG_FUNCTION_ARGS)
4417 {
4418 PolyNumAggState *state;
4419
4420 state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
4421
4422 /* Should not get here with no state */
4423 if (state == NULL)
4424 elog(ERROR, "int2_accum_inv called with NULL state");
4425
4426 if (!PG_ARGISNULL(1))
4427 {
4428 #ifdef HAVE_INT128
4429 do_int128_discard(state, (int128) PG_GETARG_INT16(1));
4430 #else
4431 Numeric newval;
4432
4433 newval = DatumGetNumeric(DirectFunctionCall1(int2_numeric,
4434 PG_GETARG_DATUM(1)));
4435
4436 /* Should never fail, all inputs have dscale 0 */
4437 if (!do_numeric_discard(state, newval))
4438 elog(ERROR, "do_numeric_discard failed unexpectedly");
4439 #endif
4440 }
4441
4442 PG_RETURN_POINTER(state);
4443 }
4444
4445 Datum
int4_accum_inv(PG_FUNCTION_ARGS)4446 int4_accum_inv(PG_FUNCTION_ARGS)
4447 {
4448 PolyNumAggState *state;
4449
4450 state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
4451
4452 /* Should not get here with no state */
4453 if (state == NULL)
4454 elog(ERROR, "int4_accum_inv called with NULL state");
4455
4456 if (!PG_ARGISNULL(1))
4457 {
4458 #ifdef HAVE_INT128
4459 do_int128_discard(state, (int128) PG_GETARG_INT32(1));
4460 #else
4461 Numeric newval;
4462
4463 newval = DatumGetNumeric(DirectFunctionCall1(int4_numeric,
4464 PG_GETARG_DATUM(1)));
4465
4466 /* Should never fail, all inputs have dscale 0 */
4467 if (!do_numeric_discard(state, newval))
4468 elog(ERROR, "do_numeric_discard failed unexpectedly");
4469 #endif
4470 }
4471
4472 PG_RETURN_POINTER(state);
4473 }
4474
4475 Datum
int8_accum_inv(PG_FUNCTION_ARGS)4476 int8_accum_inv(PG_FUNCTION_ARGS)
4477 {
4478 NumericAggState *state;
4479
4480 state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
4481
4482 /* Should not get here with no state */
4483 if (state == NULL)
4484 elog(ERROR, "int8_accum_inv called with NULL state");
4485
4486 if (!PG_ARGISNULL(1))
4487 {
4488 Numeric newval;
4489
4490 newval = DatumGetNumeric(DirectFunctionCall1(int8_numeric,
4491 PG_GETARG_DATUM(1)));
4492
4493 /* Should never fail, all inputs have dscale 0 */
4494 if (!do_numeric_discard(state, newval))
4495 elog(ERROR, "do_numeric_discard failed unexpectedly");
4496 }
4497
4498 PG_RETURN_POINTER(state);
4499 }
4500
4501 Datum
int8_avg_accum_inv(PG_FUNCTION_ARGS)4502 int8_avg_accum_inv(PG_FUNCTION_ARGS)
4503 {
4504 PolyNumAggState *state;
4505
4506 state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
4507
4508 /* Should not get here with no state */
4509 if (state == NULL)
4510 elog(ERROR, "int8_avg_accum_inv called with NULL state");
4511
4512 if (!PG_ARGISNULL(1))
4513 {
4514 #ifdef HAVE_INT128
4515 do_int128_discard(state, (int128) PG_GETARG_INT64(1));
4516 #else
4517 Numeric newval;
4518
4519 newval = DatumGetNumeric(DirectFunctionCall1(int8_numeric,
4520 PG_GETARG_DATUM(1)));
4521
4522 /* Should never fail, all inputs have dscale 0 */
4523 if (!do_numeric_discard(state, newval))
4524 elog(ERROR, "do_numeric_discard failed unexpectedly");
4525 #endif
4526 }
4527
4528 PG_RETURN_POINTER(state);
4529 }
4530
4531 Datum
numeric_poly_sum(PG_FUNCTION_ARGS)4532 numeric_poly_sum(PG_FUNCTION_ARGS)
4533 {
4534 #ifdef HAVE_INT128
4535 PolyNumAggState *state;
4536 Numeric res;
4537 NumericVar result;
4538
4539 state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
4540
4541 /* If there were no non-null inputs, return NULL */
4542 if (state == NULL || state->N == 0)
4543 PG_RETURN_NULL();
4544
4545 init_var(&result);
4546
4547 int128_to_numericvar(state->sumX, &result);
4548
4549 res = make_result(&result);
4550
4551 free_var(&result);
4552
4553 PG_RETURN_NUMERIC(res);
4554 #else
4555 return numeric_sum(fcinfo);
4556 #endif
4557 }
4558
4559 Datum
numeric_poly_avg(PG_FUNCTION_ARGS)4560 numeric_poly_avg(PG_FUNCTION_ARGS)
4561 {
4562 #ifdef HAVE_INT128
4563 PolyNumAggState *state;
4564 NumericVar result;
4565 Datum countd,
4566 sumd;
4567
4568 state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
4569
4570 /* If there were no non-null inputs, return NULL */
4571 if (state == NULL || state->N == 0)
4572 PG_RETURN_NULL();
4573
4574 init_var(&result);
4575
4576 int128_to_numericvar(state->sumX, &result);
4577
4578 countd = DirectFunctionCall1(int8_numeric,
4579 Int64GetDatumFast(state->N));
4580 sumd = NumericGetDatum(make_result(&result));
4581
4582 free_var(&result);
4583
4584 PG_RETURN_DATUM(DirectFunctionCall2(numeric_div, sumd, countd));
4585 #else
4586 return numeric_avg(fcinfo);
4587 #endif
4588 }
4589
4590 Datum
numeric_avg(PG_FUNCTION_ARGS)4591 numeric_avg(PG_FUNCTION_ARGS)
4592 {
4593 NumericAggState *state;
4594 Datum N_datum;
4595 Datum sumX_datum;
4596 NumericVar sumX_var;
4597
4598 state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
4599
4600 /* If there were no non-null inputs, return NULL */
4601 if (state == NULL || (state->N + state->NaNcount) == 0)
4602 PG_RETURN_NULL();
4603
4604 if (state->NaNcount > 0) /* there was at least one NaN input */
4605 PG_RETURN_NUMERIC(make_result(&const_nan));
4606
4607 N_datum = DirectFunctionCall1(int8_numeric, Int64GetDatum(state->N));
4608
4609 init_var(&sumX_var);
4610 accum_sum_final(&state->sumX, &sumX_var);
4611 sumX_datum = NumericGetDatum(make_result(&sumX_var));
4612 free_var(&sumX_var);
4613
4614 PG_RETURN_DATUM(DirectFunctionCall2(numeric_div, sumX_datum, N_datum));
4615 }
4616
4617 Datum
numeric_sum(PG_FUNCTION_ARGS)4618 numeric_sum(PG_FUNCTION_ARGS)
4619 {
4620 NumericAggState *state;
4621 NumericVar sumX_var;
4622 Numeric result;
4623
4624 state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
4625
4626 /* If there were no non-null inputs, return NULL */
4627 if (state == NULL || (state->N + state->NaNcount) == 0)
4628 PG_RETURN_NULL();
4629
4630 if (state->NaNcount > 0) /* there was at least one NaN input */
4631 PG_RETURN_NUMERIC(make_result(&const_nan));
4632
4633 init_var(&sumX_var);
4634 accum_sum_final(&state->sumX, &sumX_var);
4635 result = make_result(&sumX_var);
4636 free_var(&sumX_var);
4637
4638 PG_RETURN_NUMERIC(result);
4639 }
4640
4641 /*
4642 * Workhorse routine for the standard deviance and variance
4643 * aggregates. 'state' is aggregate's transition state.
4644 * 'variance' specifies whether we should calculate the
4645 * variance or the standard deviation. 'sample' indicates whether the
4646 * caller is interested in the sample or the population
4647 * variance/stddev.
4648 *
4649 * If appropriate variance statistic is undefined for the input,
4650 * *is_null is set to true and NULL is returned.
4651 */
4652 static Numeric
numeric_stddev_internal(NumericAggState * state,bool variance,bool sample,bool * is_null)4653 numeric_stddev_internal(NumericAggState *state,
4654 bool variance, bool sample,
4655 bool *is_null)
4656 {
4657 Numeric res;
4658 NumericVar vN,
4659 vsumX,
4660 vsumX2,
4661 vNminus1;
4662 NumericVar *comp;
4663 int rscale;
4664
4665 /* Deal with empty input and NaN-input cases */
4666 if (state == NULL || (state->N + state->NaNcount) == 0)
4667 {
4668 *is_null = true;
4669 return NULL;
4670 }
4671
4672 *is_null = false;
4673
4674 if (state->NaNcount > 0)
4675 return make_result(&const_nan);
4676
4677 init_var(&vN);
4678 init_var(&vsumX);
4679 init_var(&vsumX2);
4680
4681 int64_to_numericvar(state->N, &vN);
4682 accum_sum_final(&(state->sumX), &vsumX);
4683 accum_sum_final(&(state->sumX2), &vsumX2);
4684
4685 /*
4686 * Sample stddev and variance are undefined when N <= 1; population stddev
4687 * is undefined when N == 0. Return NULL in either case.
4688 */
4689 if (sample)
4690 comp = &const_one;
4691 else
4692 comp = &const_zero;
4693
4694 if (cmp_var(&vN, comp) <= 0)
4695 {
4696 *is_null = true;
4697 return NULL;
4698 }
4699
4700 init_var(&vNminus1);
4701 sub_var(&vN, &const_one, &vNminus1);
4702
4703 /* compute rscale for mul_var calls */
4704 rscale = vsumX.dscale * 2;
4705
4706 mul_var(&vsumX, &vsumX, &vsumX, rscale); /* vsumX = sumX * sumX */
4707 mul_var(&vN, &vsumX2, &vsumX2, rscale); /* vsumX2 = N * sumX2 */
4708 sub_var(&vsumX2, &vsumX, &vsumX2); /* N * sumX2 - sumX * sumX */
4709
4710 if (cmp_var(&vsumX2, &const_zero) <= 0)
4711 {
4712 /* Watch out for roundoff error producing a negative numerator */
4713 res = make_result(&const_zero);
4714 }
4715 else
4716 {
4717 if (sample)
4718 mul_var(&vN, &vNminus1, &vNminus1, 0); /* N * (N - 1) */
4719 else
4720 mul_var(&vN, &vN, &vNminus1, 0); /* N * N */
4721 rscale = select_div_scale(&vsumX2, &vNminus1);
4722 div_var(&vsumX2, &vNminus1, &vsumX, rscale, true); /* variance */
4723 if (!variance)
4724 sqrt_var(&vsumX, &vsumX, rscale); /* stddev */
4725
4726 res = make_result(&vsumX);
4727 }
4728
4729 free_var(&vNminus1);
4730 free_var(&vsumX);
4731 free_var(&vsumX2);
4732
4733 return res;
4734 }
4735
4736 Datum
numeric_var_samp(PG_FUNCTION_ARGS)4737 numeric_var_samp(PG_FUNCTION_ARGS)
4738 {
4739 NumericAggState *state;
4740 Numeric res;
4741 bool is_null;
4742
4743 state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
4744
4745 res = numeric_stddev_internal(state, true, true, &is_null);
4746
4747 if (is_null)
4748 PG_RETURN_NULL();
4749 else
4750 PG_RETURN_NUMERIC(res);
4751 }
4752
4753 Datum
numeric_stddev_samp(PG_FUNCTION_ARGS)4754 numeric_stddev_samp(PG_FUNCTION_ARGS)
4755 {
4756 NumericAggState *state;
4757 Numeric res;
4758 bool is_null;
4759
4760 state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
4761
4762 res = numeric_stddev_internal(state, false, true, &is_null);
4763
4764 if (is_null)
4765 PG_RETURN_NULL();
4766 else
4767 PG_RETURN_NUMERIC(res);
4768 }
4769
4770 Datum
numeric_var_pop(PG_FUNCTION_ARGS)4771 numeric_var_pop(PG_FUNCTION_ARGS)
4772 {
4773 NumericAggState *state;
4774 Numeric res;
4775 bool is_null;
4776
4777 state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
4778
4779 res = numeric_stddev_internal(state, true, false, &is_null);
4780
4781 if (is_null)
4782 PG_RETURN_NULL();
4783 else
4784 PG_RETURN_NUMERIC(res);
4785 }
4786
4787 Datum
numeric_stddev_pop(PG_FUNCTION_ARGS)4788 numeric_stddev_pop(PG_FUNCTION_ARGS)
4789 {
4790 NumericAggState *state;
4791 Numeric res;
4792 bool is_null;
4793
4794 state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
4795
4796 res = numeric_stddev_internal(state, false, false, &is_null);
4797
4798 if (is_null)
4799 PG_RETURN_NULL();
4800 else
4801 PG_RETURN_NUMERIC(res);
4802 }
4803
4804 #ifdef HAVE_INT128
4805 static Numeric
numeric_poly_stddev_internal(Int128AggState * state,bool variance,bool sample,bool * is_null)4806 numeric_poly_stddev_internal(Int128AggState *state,
4807 bool variance, bool sample,
4808 bool *is_null)
4809 {
4810 NumericAggState numstate;
4811 Numeric res;
4812
4813 /* Initialize an empty agg state */
4814 memset(&numstate, 0, sizeof(NumericAggState));
4815
4816 if (state)
4817 {
4818 NumericVar tmp_var;
4819
4820 numstate.N = state->N;
4821
4822 init_var(&tmp_var);
4823
4824 int128_to_numericvar(state->sumX, &tmp_var);
4825 accum_sum_add(&numstate.sumX, &tmp_var);
4826
4827 int128_to_numericvar(state->sumX2, &tmp_var);
4828 accum_sum_add(&numstate.sumX2, &tmp_var);
4829
4830 free_var(&tmp_var);
4831 }
4832
4833 res = numeric_stddev_internal(&numstate, variance, sample, is_null);
4834
4835 if (numstate.sumX.ndigits > 0)
4836 {
4837 pfree(numstate.sumX.pos_digits);
4838 pfree(numstate.sumX.neg_digits);
4839 }
4840 if (numstate.sumX2.ndigits > 0)
4841 {
4842 pfree(numstate.sumX2.pos_digits);
4843 pfree(numstate.sumX2.neg_digits);
4844 }
4845
4846 return res;
4847 }
4848 #endif
4849
4850 Datum
numeric_poly_var_samp(PG_FUNCTION_ARGS)4851 numeric_poly_var_samp(PG_FUNCTION_ARGS)
4852 {
4853 #ifdef HAVE_INT128
4854 PolyNumAggState *state;
4855 Numeric res;
4856 bool is_null;
4857
4858 state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
4859
4860 res = numeric_poly_stddev_internal(state, true, true, &is_null);
4861
4862 if (is_null)
4863 PG_RETURN_NULL();
4864 else
4865 PG_RETURN_NUMERIC(res);
4866 #else
4867 return numeric_var_samp(fcinfo);
4868 #endif
4869 }
4870
4871 Datum
numeric_poly_stddev_samp(PG_FUNCTION_ARGS)4872 numeric_poly_stddev_samp(PG_FUNCTION_ARGS)
4873 {
4874 #ifdef HAVE_INT128
4875 PolyNumAggState *state;
4876 Numeric res;
4877 bool is_null;
4878
4879 state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
4880
4881 res = numeric_poly_stddev_internal(state, false, true, &is_null);
4882
4883 if (is_null)
4884 PG_RETURN_NULL();
4885 else
4886 PG_RETURN_NUMERIC(res);
4887 #else
4888 return numeric_stddev_samp(fcinfo);
4889 #endif
4890 }
4891
4892 Datum
numeric_poly_var_pop(PG_FUNCTION_ARGS)4893 numeric_poly_var_pop(PG_FUNCTION_ARGS)
4894 {
4895 #ifdef HAVE_INT128
4896 PolyNumAggState *state;
4897 Numeric res;
4898 bool is_null;
4899
4900 state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
4901
4902 res = numeric_poly_stddev_internal(state, true, false, &is_null);
4903
4904 if (is_null)
4905 PG_RETURN_NULL();
4906 else
4907 PG_RETURN_NUMERIC(res);
4908 #else
4909 return numeric_var_pop(fcinfo);
4910 #endif
4911 }
4912
4913 Datum
numeric_poly_stddev_pop(PG_FUNCTION_ARGS)4914 numeric_poly_stddev_pop(PG_FUNCTION_ARGS)
4915 {
4916 #ifdef HAVE_INT128
4917 PolyNumAggState *state;
4918 Numeric res;
4919 bool is_null;
4920
4921 state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
4922
4923 res = numeric_poly_stddev_internal(state, false, false, &is_null);
4924
4925 if (is_null)
4926 PG_RETURN_NULL();
4927 else
4928 PG_RETURN_NUMERIC(res);
4929 #else
4930 return numeric_stddev_pop(fcinfo);
4931 #endif
4932 }
4933
4934 /*
4935 * SUM transition functions for integer datatypes.
4936 *
4937 * To avoid overflow, we use accumulators wider than the input datatype.
4938 * A Numeric accumulator is needed for int8 input; for int4 and int2
4939 * inputs, we use int8 accumulators which should be sufficient for practical
4940 * purposes. (The latter two therefore don't really belong in this file,
4941 * but we keep them here anyway.)
4942 *
4943 * Because SQL defines the SUM() of no values to be NULL, not zero,
4944 * the initial condition of the transition data value needs to be NULL. This
4945 * means we can't rely on ExecAgg to automatically insert the first non-null
4946 * data value into the transition data: it doesn't know how to do the type
4947 * conversion. The upshot is that these routines have to be marked non-strict
4948 * and handle substitution of the first non-null input themselves.
4949 *
4950 * Note: these functions are used only in plain aggregation mode.
4951 * In moving-aggregate mode, we use intX_avg_accum and intX_avg_accum_inv.
4952 */
4953
4954 Datum
int2_sum(PG_FUNCTION_ARGS)4955 int2_sum(PG_FUNCTION_ARGS)
4956 {
4957 int64 newval;
4958
4959 if (PG_ARGISNULL(0))
4960 {
4961 /* No non-null input seen so far... */
4962 if (PG_ARGISNULL(1))
4963 PG_RETURN_NULL(); /* still no non-null */
4964 /* This is the first non-null input. */
4965 newval = (int64) PG_GETARG_INT16(1);
4966 PG_RETURN_INT64(newval);
4967 }
4968
4969 /*
4970 * If we're invoked as an aggregate, we can cheat and modify our first
4971 * parameter in-place to avoid palloc overhead. If not, we need to return
4972 * the new value of the transition variable. (If int8 is pass-by-value,
4973 * then of course this is useless as well as incorrect, so just ifdef it
4974 * out.)
4975 */
4976 #ifndef USE_FLOAT8_BYVAL /* controls int8 too */
4977 if (AggCheckCallContext(fcinfo, NULL))
4978 {
4979 int64 *oldsum = (int64 *) PG_GETARG_POINTER(0);
4980
4981 /* Leave the running sum unchanged in the new input is null */
4982 if (!PG_ARGISNULL(1))
4983 *oldsum = *oldsum + (int64) PG_GETARG_INT16(1);
4984
4985 PG_RETURN_POINTER(oldsum);
4986 }
4987 else
4988 #endif
4989 {
4990 int64 oldsum = PG_GETARG_INT64(0);
4991
4992 /* Leave sum unchanged if new input is null. */
4993 if (PG_ARGISNULL(1))
4994 PG_RETURN_INT64(oldsum);
4995
4996 /* OK to do the addition. */
4997 newval = oldsum + (int64) PG_GETARG_INT16(1);
4998
4999 PG_RETURN_INT64(newval);
5000 }
5001 }
5002
5003 Datum
int4_sum(PG_FUNCTION_ARGS)5004 int4_sum(PG_FUNCTION_ARGS)
5005 {
5006 int64 newval;
5007
5008 if (PG_ARGISNULL(0))
5009 {
5010 /* No non-null input seen so far... */
5011 if (PG_ARGISNULL(1))
5012 PG_RETURN_NULL(); /* still no non-null */
5013 /* This is the first non-null input. */
5014 newval = (int64) PG_GETARG_INT32(1);
5015 PG_RETURN_INT64(newval);
5016 }
5017
5018 /*
5019 * If we're invoked as an aggregate, we can cheat and modify our first
5020 * parameter in-place to avoid palloc overhead. If not, we need to return
5021 * the new value of the transition variable. (If int8 is pass-by-value,
5022 * then of course this is useless as well as incorrect, so just ifdef it
5023 * out.)
5024 */
5025 #ifndef USE_FLOAT8_BYVAL /* controls int8 too */
5026 if (AggCheckCallContext(fcinfo, NULL))
5027 {
5028 int64 *oldsum = (int64 *) PG_GETARG_POINTER(0);
5029
5030 /* Leave the running sum unchanged in the new input is null */
5031 if (!PG_ARGISNULL(1))
5032 *oldsum = *oldsum + (int64) PG_GETARG_INT32(1);
5033
5034 PG_RETURN_POINTER(oldsum);
5035 }
5036 else
5037 #endif
5038 {
5039 int64 oldsum = PG_GETARG_INT64(0);
5040
5041 /* Leave sum unchanged if new input is null. */
5042 if (PG_ARGISNULL(1))
5043 PG_RETURN_INT64(oldsum);
5044
5045 /* OK to do the addition. */
5046 newval = oldsum + (int64) PG_GETARG_INT32(1);
5047
5048 PG_RETURN_INT64(newval);
5049 }
5050 }
5051
5052 /*
5053 * Note: this function is obsolete, it's no longer used for SUM(int8).
5054 */
5055 Datum
int8_sum(PG_FUNCTION_ARGS)5056 int8_sum(PG_FUNCTION_ARGS)
5057 {
5058 Numeric oldsum;
5059 Datum newval;
5060
5061 if (PG_ARGISNULL(0))
5062 {
5063 /* No non-null input seen so far... */
5064 if (PG_ARGISNULL(1))
5065 PG_RETURN_NULL(); /* still no non-null */
5066 /* This is the first non-null input. */
5067 newval = DirectFunctionCall1(int8_numeric, PG_GETARG_DATUM(1));
5068 PG_RETURN_DATUM(newval);
5069 }
5070
5071 /*
5072 * Note that we cannot special-case the aggregate case here, as we do for
5073 * int2_sum and int4_sum: numeric is of variable size, so we cannot modify
5074 * our first parameter in-place.
5075 */
5076
5077 oldsum = PG_GETARG_NUMERIC(0);
5078
5079 /* Leave sum unchanged if new input is null. */
5080 if (PG_ARGISNULL(1))
5081 PG_RETURN_NUMERIC(oldsum);
5082
5083 /* OK to do the addition. */
5084 newval = DirectFunctionCall1(int8_numeric, PG_GETARG_DATUM(1));
5085
5086 PG_RETURN_DATUM(DirectFunctionCall2(numeric_add,
5087 NumericGetDatum(oldsum), newval));
5088 }
5089
5090
5091 /*
5092 * Routines for avg(int2) and avg(int4). The transition datatype
5093 * is a two-element int8 array, holding count and sum.
5094 *
5095 * These functions are also used for sum(int2) and sum(int4) when
5096 * operating in moving-aggregate mode, since for correct inverse transitions
5097 * we need to count the inputs.
5098 */
5099
5100 typedef struct Int8TransTypeData
5101 {
5102 int64 count;
5103 int64 sum;
5104 } Int8TransTypeData;
5105
5106 Datum
int2_avg_accum(PG_FUNCTION_ARGS)5107 int2_avg_accum(PG_FUNCTION_ARGS)
5108 {
5109 ArrayType *transarray;
5110 int16 newval = PG_GETARG_INT16(1);
5111 Int8TransTypeData *transdata;
5112
5113 /*
5114 * If we're invoked as an aggregate, we can cheat and modify our first
5115 * parameter in-place to reduce palloc overhead. Otherwise we need to make
5116 * a copy of it before scribbling on it.
5117 */
5118 if (AggCheckCallContext(fcinfo, NULL))
5119 transarray = PG_GETARG_ARRAYTYPE_P(0);
5120 else
5121 transarray = PG_GETARG_ARRAYTYPE_P_COPY(0);
5122
5123 if (ARR_HASNULL(transarray) ||
5124 ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
5125 elog(ERROR, "expected 2-element int8 array");
5126
5127 transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
5128 transdata->count++;
5129 transdata->sum += newval;
5130
5131 PG_RETURN_ARRAYTYPE_P(transarray);
5132 }
5133
5134 Datum
int4_avg_accum(PG_FUNCTION_ARGS)5135 int4_avg_accum(PG_FUNCTION_ARGS)
5136 {
5137 ArrayType *transarray;
5138 int32 newval = PG_GETARG_INT32(1);
5139 Int8TransTypeData *transdata;
5140
5141 /*
5142 * If we're invoked as an aggregate, we can cheat and modify our first
5143 * parameter in-place to reduce palloc overhead. Otherwise we need to make
5144 * a copy of it before scribbling on it.
5145 */
5146 if (AggCheckCallContext(fcinfo, NULL))
5147 transarray = PG_GETARG_ARRAYTYPE_P(0);
5148 else
5149 transarray = PG_GETARG_ARRAYTYPE_P_COPY(0);
5150
5151 if (ARR_HASNULL(transarray) ||
5152 ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
5153 elog(ERROR, "expected 2-element int8 array");
5154
5155 transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
5156 transdata->count++;
5157 transdata->sum += newval;
5158
5159 PG_RETURN_ARRAYTYPE_P(transarray);
5160 }
5161
5162 Datum
int4_avg_combine(PG_FUNCTION_ARGS)5163 int4_avg_combine(PG_FUNCTION_ARGS)
5164 {
5165 ArrayType *transarray1;
5166 ArrayType *transarray2;
5167 Int8TransTypeData *state1;
5168 Int8TransTypeData *state2;
5169
5170 if (!AggCheckCallContext(fcinfo, NULL))
5171 elog(ERROR, "aggregate function called in non-aggregate context");
5172
5173 transarray1 = PG_GETARG_ARRAYTYPE_P(0);
5174 transarray2 = PG_GETARG_ARRAYTYPE_P(1);
5175
5176 if (ARR_HASNULL(transarray1) ||
5177 ARR_SIZE(transarray1) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
5178 elog(ERROR, "expected 2-element int8 array");
5179
5180 if (ARR_HASNULL(transarray2) ||
5181 ARR_SIZE(transarray2) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
5182 elog(ERROR, "expected 2-element int8 array");
5183
5184 state1 = (Int8TransTypeData *) ARR_DATA_PTR(transarray1);
5185 state2 = (Int8TransTypeData *) ARR_DATA_PTR(transarray2);
5186
5187 state1->count += state2->count;
5188 state1->sum += state2->sum;
5189
5190 PG_RETURN_ARRAYTYPE_P(transarray1);
5191 }
5192
5193 Datum
int2_avg_accum_inv(PG_FUNCTION_ARGS)5194 int2_avg_accum_inv(PG_FUNCTION_ARGS)
5195 {
5196 ArrayType *transarray;
5197 int16 newval = PG_GETARG_INT16(1);
5198 Int8TransTypeData *transdata;
5199
5200 /*
5201 * If we're invoked as an aggregate, we can cheat and modify our first
5202 * parameter in-place to reduce palloc overhead. Otherwise we need to make
5203 * a copy of it before scribbling on it.
5204 */
5205 if (AggCheckCallContext(fcinfo, NULL))
5206 transarray = PG_GETARG_ARRAYTYPE_P(0);
5207 else
5208 transarray = PG_GETARG_ARRAYTYPE_P_COPY(0);
5209
5210 if (ARR_HASNULL(transarray) ||
5211 ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
5212 elog(ERROR, "expected 2-element int8 array");
5213
5214 transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
5215 transdata->count--;
5216 transdata->sum -= newval;
5217
5218 PG_RETURN_ARRAYTYPE_P(transarray);
5219 }
5220
5221 Datum
int4_avg_accum_inv(PG_FUNCTION_ARGS)5222 int4_avg_accum_inv(PG_FUNCTION_ARGS)
5223 {
5224 ArrayType *transarray;
5225 int32 newval = PG_GETARG_INT32(1);
5226 Int8TransTypeData *transdata;
5227
5228 /*
5229 * If we're invoked as an aggregate, we can cheat and modify our first
5230 * parameter in-place to reduce palloc overhead. Otherwise we need to make
5231 * a copy of it before scribbling on it.
5232 */
5233 if (AggCheckCallContext(fcinfo, NULL))
5234 transarray = PG_GETARG_ARRAYTYPE_P(0);
5235 else
5236 transarray = PG_GETARG_ARRAYTYPE_P_COPY(0);
5237
5238 if (ARR_HASNULL(transarray) ||
5239 ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
5240 elog(ERROR, "expected 2-element int8 array");
5241
5242 transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
5243 transdata->count--;
5244 transdata->sum -= newval;
5245
5246 PG_RETURN_ARRAYTYPE_P(transarray);
5247 }
5248
5249 Datum
int8_avg(PG_FUNCTION_ARGS)5250 int8_avg(PG_FUNCTION_ARGS)
5251 {
5252 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
5253 Int8TransTypeData *transdata;
5254 Datum countd,
5255 sumd;
5256
5257 if (ARR_HASNULL(transarray) ||
5258 ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
5259 elog(ERROR, "expected 2-element int8 array");
5260 transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
5261
5262 /* SQL defines AVG of no values to be NULL */
5263 if (transdata->count == 0)
5264 PG_RETURN_NULL();
5265
5266 countd = DirectFunctionCall1(int8_numeric,
5267 Int64GetDatumFast(transdata->count));
5268 sumd = DirectFunctionCall1(int8_numeric,
5269 Int64GetDatumFast(transdata->sum));
5270
5271 PG_RETURN_DATUM(DirectFunctionCall2(numeric_div, sumd, countd));
5272 }
5273
5274 /*
5275 * SUM(int2) and SUM(int4) both return int8, so we can use this
5276 * final function for both.
5277 */
5278 Datum
int2int4_sum(PG_FUNCTION_ARGS)5279 int2int4_sum(PG_FUNCTION_ARGS)
5280 {
5281 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
5282 Int8TransTypeData *transdata;
5283
5284 if (ARR_HASNULL(transarray) ||
5285 ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
5286 elog(ERROR, "expected 2-element int8 array");
5287 transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
5288
5289 /* SQL defines SUM of no values to be NULL */
5290 if (transdata->count == 0)
5291 PG_RETURN_NULL();
5292
5293 PG_RETURN_DATUM(Int64GetDatumFast(transdata->sum));
5294 }
5295
5296
5297 /* ----------------------------------------------------------------------
5298 *
5299 * Debug support
5300 *
5301 * ----------------------------------------------------------------------
5302 */
5303
5304 #ifdef NUMERIC_DEBUG
5305
5306 /*
5307 * dump_numeric() - Dump a value in the db storage format for debugging
5308 */
5309 static void
dump_numeric(const char * str,Numeric num)5310 dump_numeric(const char *str, Numeric num)
5311 {
5312 NumericDigit *digits = NUMERIC_DIGITS(num);
5313 int ndigits;
5314 int i;
5315
5316 ndigits = NUMERIC_NDIGITS(num);
5317
5318 printf("%s: NUMERIC w=%d d=%d ", str,
5319 NUMERIC_WEIGHT(num), NUMERIC_DSCALE(num));
5320 switch (NUMERIC_SIGN(num))
5321 {
5322 case NUMERIC_POS:
5323 printf("POS");
5324 break;
5325 case NUMERIC_NEG:
5326 printf("NEG");
5327 break;
5328 case NUMERIC_NAN:
5329 printf("NaN");
5330 break;
5331 default:
5332 printf("SIGN=0x%x", NUMERIC_SIGN(num));
5333 break;
5334 }
5335
5336 for (i = 0; i < ndigits; i++)
5337 printf(" %0*d", DEC_DIGITS, digits[i]);
5338 printf("\n");
5339 }
5340
5341
5342 /*
5343 * dump_var() - Dump a value in the variable format for debugging
5344 */
5345 static void
dump_var(const char * str,NumericVar * var)5346 dump_var(const char *str, NumericVar *var)
5347 {
5348 int i;
5349
5350 printf("%s: VAR w=%d d=%d ", str, var->weight, var->dscale);
5351 switch (var->sign)
5352 {
5353 case NUMERIC_POS:
5354 printf("POS");
5355 break;
5356 case NUMERIC_NEG:
5357 printf("NEG");
5358 break;
5359 case NUMERIC_NAN:
5360 printf("NaN");
5361 break;
5362 default:
5363 printf("SIGN=0x%x", var->sign);
5364 break;
5365 }
5366
5367 for (i = 0; i < var->ndigits; i++)
5368 printf(" %0*d", DEC_DIGITS, var->digits[i]);
5369
5370 printf("\n");
5371 }
5372 #endif /* NUMERIC_DEBUG */
5373
5374
5375 /* ----------------------------------------------------------------------
5376 *
5377 * Local functions follow
5378 *
5379 * In general, these do not support NaNs --- callers must eliminate
5380 * the possibility of NaN first. (make_result() is an exception.)
5381 *
5382 * ----------------------------------------------------------------------
5383 */
5384
5385
5386 /*
5387 * alloc_var() -
5388 *
5389 * Allocate a digit buffer of ndigits digits (plus a spare digit for rounding)
5390 */
5391 static void
alloc_var(NumericVar * var,int ndigits)5392 alloc_var(NumericVar *var, int ndigits)
5393 {
5394 digitbuf_free(var->buf);
5395 var->buf = digitbuf_alloc(ndigits + 1);
5396 var->buf[0] = 0; /* spare digit for rounding */
5397 var->digits = var->buf + 1;
5398 var->ndigits = ndigits;
5399 }
5400
5401
5402 /*
5403 * free_var() -
5404 *
5405 * Return the digit buffer of a variable to the free pool
5406 */
5407 static void
free_var(NumericVar * var)5408 free_var(NumericVar *var)
5409 {
5410 digitbuf_free(var->buf);
5411 var->buf = NULL;
5412 var->digits = NULL;
5413 var->sign = NUMERIC_NAN;
5414 }
5415
5416
5417 /*
5418 * zero_var() -
5419 *
5420 * Set a variable to ZERO.
5421 * Note: its dscale is not touched.
5422 */
5423 static void
zero_var(NumericVar * var)5424 zero_var(NumericVar *var)
5425 {
5426 digitbuf_free(var->buf);
5427 var->buf = NULL;
5428 var->digits = NULL;
5429 var->ndigits = 0;
5430 var->weight = 0; /* by convention; doesn't really matter */
5431 var->sign = NUMERIC_POS; /* anything but NAN... */
5432 }
5433
5434
5435 /*
5436 * set_var_from_str()
5437 *
5438 * Parse a string and put the number into a variable
5439 *
5440 * This function does not handle leading or trailing spaces, and it doesn't
5441 * accept "NaN" either. It returns the end+1 position so that caller can
5442 * check for trailing spaces/garbage if deemed necessary.
5443 *
5444 * cp is the place to actually start parsing; str is what to use in error
5445 * reports. (Typically cp would be the same except advanced over spaces.)
5446 */
5447 static const char *
set_var_from_str(const char * str,const char * cp,NumericVar * dest)5448 set_var_from_str(const char *str, const char *cp, NumericVar *dest)
5449 {
5450 bool have_dp = FALSE;
5451 int i;
5452 unsigned char *decdigits;
5453 int sign = NUMERIC_POS;
5454 int dweight = -1;
5455 int ddigits;
5456 int dscale = 0;
5457 int weight;
5458 int ndigits;
5459 int offset;
5460 NumericDigit *digits;
5461
5462 /*
5463 * We first parse the string to extract decimal digits and determine the
5464 * correct decimal weight. Then convert to NBASE representation.
5465 */
5466 switch (*cp)
5467 {
5468 case '+':
5469 sign = NUMERIC_POS;
5470 cp++;
5471 break;
5472
5473 case '-':
5474 sign = NUMERIC_NEG;
5475 cp++;
5476 break;
5477 }
5478
5479 if (*cp == '.')
5480 {
5481 have_dp = TRUE;
5482 cp++;
5483 }
5484
5485 if (!isdigit((unsigned char) *cp))
5486 ereport(ERROR,
5487 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
5488 errmsg("invalid input syntax for type %s: \"%s\"",
5489 "numeric", str)));
5490
5491 decdigits = (unsigned char *) palloc(strlen(cp) + DEC_DIGITS * 2);
5492
5493 /* leading padding for digit alignment later */
5494 memset(decdigits, 0, DEC_DIGITS);
5495 i = DEC_DIGITS;
5496
5497 while (*cp)
5498 {
5499 if (isdigit((unsigned char) *cp))
5500 {
5501 decdigits[i++] = *cp++ - '0';
5502 if (!have_dp)
5503 dweight++;
5504 else
5505 dscale++;
5506 }
5507 else if (*cp == '.')
5508 {
5509 if (have_dp)
5510 ereport(ERROR,
5511 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
5512 errmsg("invalid input syntax for type %s: \"%s\"",
5513 "numeric", str)));
5514 have_dp = TRUE;
5515 cp++;
5516 }
5517 else
5518 break;
5519 }
5520
5521 ddigits = i - DEC_DIGITS;
5522 /* trailing padding for digit alignment later */
5523 memset(decdigits + i, 0, DEC_DIGITS - 1);
5524
5525 /* Handle exponent, if any */
5526 if (*cp == 'e' || *cp == 'E')
5527 {
5528 long exponent;
5529 char *endptr;
5530
5531 cp++;
5532 exponent = strtol(cp, &endptr, 10);
5533 if (endptr == cp)
5534 ereport(ERROR,
5535 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
5536 errmsg("invalid input syntax for type %s: \"%s\"",
5537 "numeric", str)));
5538 cp = endptr;
5539
5540 /*
5541 * At this point, dweight and dscale can't be more than about
5542 * INT_MAX/2 due to the MaxAllocSize limit on string length, so
5543 * constraining the exponent similarly should be enough to prevent
5544 * integer overflow in this function. If the value is too large to
5545 * fit in storage format, make_result() will complain about it later;
5546 * for consistency use the same ereport errcode/text as make_result().
5547 */
5548 if (exponent >= INT_MAX / 2 || exponent <= -(INT_MAX / 2))
5549 ereport(ERROR,
5550 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
5551 errmsg("value overflows numeric format")));
5552 dweight += (int) exponent;
5553 dscale -= (int) exponent;
5554 if (dscale < 0)
5555 dscale = 0;
5556 }
5557
5558 /*
5559 * Okay, convert pure-decimal representation to base NBASE. First we need
5560 * to determine the converted weight and ndigits. offset is the number of
5561 * decimal zeroes to insert before the first given digit to have a
5562 * correctly aligned first NBASE digit.
5563 */
5564 if (dweight >= 0)
5565 weight = (dweight + 1 + DEC_DIGITS - 1) / DEC_DIGITS - 1;
5566 else
5567 weight = -((-dweight - 1) / DEC_DIGITS + 1);
5568 offset = (weight + 1) * DEC_DIGITS - (dweight + 1);
5569 ndigits = (ddigits + offset + DEC_DIGITS - 1) / DEC_DIGITS;
5570
5571 alloc_var(dest, ndigits);
5572 dest->sign = sign;
5573 dest->weight = weight;
5574 dest->dscale = dscale;
5575
5576 i = DEC_DIGITS - offset;
5577 digits = dest->digits;
5578
5579 while (ndigits-- > 0)
5580 {
5581 #if DEC_DIGITS == 4
5582 *digits++ = ((decdigits[i] * 10 + decdigits[i + 1]) * 10 +
5583 decdigits[i + 2]) * 10 + decdigits[i + 3];
5584 #elif DEC_DIGITS == 2
5585 *digits++ = decdigits[i] * 10 + decdigits[i + 1];
5586 #elif DEC_DIGITS == 1
5587 *digits++ = decdigits[i];
5588 #else
5589 #error unsupported NBASE
5590 #endif
5591 i += DEC_DIGITS;
5592 }
5593
5594 pfree(decdigits);
5595
5596 /* Strip any leading/trailing zeroes, and normalize weight if zero */
5597 strip_var(dest);
5598
5599 /* Return end+1 position for caller */
5600 return cp;
5601 }
5602
5603
5604 /*
5605 * set_var_from_num() -
5606 *
5607 * Convert the packed db format into a variable
5608 */
5609 static void
set_var_from_num(Numeric num,NumericVar * dest)5610 set_var_from_num(Numeric num, NumericVar *dest)
5611 {
5612 int ndigits;
5613
5614 ndigits = NUMERIC_NDIGITS(num);
5615
5616 alloc_var(dest, ndigits);
5617
5618 dest->weight = NUMERIC_WEIGHT(num);
5619 dest->sign = NUMERIC_SIGN(num);
5620 dest->dscale = NUMERIC_DSCALE(num);
5621
5622 memcpy(dest->digits, NUMERIC_DIGITS(num), ndigits * sizeof(NumericDigit));
5623 }
5624
5625
5626 /*
5627 * init_var_from_num() -
5628 *
5629 * Initialize a variable from packed db format. The digits array is not
5630 * copied, which saves some cycles when the resulting var is not modified.
5631 * Also, there's no need to call free_var(), as long as you don't assign any
5632 * other value to it (with set_var_* functions, or by using the var as the
5633 * destination of a function like add_var())
5634 *
5635 * CAUTION: Do not modify the digits buffer of a var initialized with this
5636 * function, e.g by calling round_var() or trunc_var(), as the changes will
5637 * propagate to the original Numeric! It's OK to use it as the destination
5638 * argument of one of the calculational functions, though.
5639 */
5640 static void
init_var_from_num(Numeric num,NumericVar * dest)5641 init_var_from_num(Numeric num, NumericVar *dest)
5642 {
5643 dest->ndigits = NUMERIC_NDIGITS(num);
5644 dest->weight = NUMERIC_WEIGHT(num);
5645 dest->sign = NUMERIC_SIGN(num);
5646 dest->dscale = NUMERIC_DSCALE(num);
5647 dest->digits = NUMERIC_DIGITS(num);
5648 dest->buf = NULL; /* digits array is not palloc'd */
5649 }
5650
5651
5652 /*
5653 * set_var_from_var() -
5654 *
5655 * Copy one variable into another
5656 */
5657 static void
set_var_from_var(NumericVar * value,NumericVar * dest)5658 set_var_from_var(NumericVar *value, NumericVar *dest)
5659 {
5660 NumericDigit *newbuf;
5661
5662 newbuf = digitbuf_alloc(value->ndigits + 1);
5663 newbuf[0] = 0; /* spare digit for rounding */
5664 if (value->ndigits > 0) /* else value->digits might be null */
5665 memcpy(newbuf + 1, value->digits,
5666 value->ndigits * sizeof(NumericDigit));
5667
5668 digitbuf_free(dest->buf);
5669
5670 memmove(dest, value, sizeof(NumericVar));
5671 dest->buf = newbuf;
5672 dest->digits = newbuf + 1;
5673 }
5674
5675
5676 /*
5677 * get_str_from_var() -
5678 *
5679 * Convert a var to text representation (guts of numeric_out).
5680 * The var is displayed to the number of digits indicated by its dscale.
5681 * Returns a palloc'd string.
5682 */
5683 static char *
get_str_from_var(NumericVar * var)5684 get_str_from_var(NumericVar *var)
5685 {
5686 int dscale;
5687 char *str;
5688 char *cp;
5689 char *endcp;
5690 int i;
5691 int d;
5692 NumericDigit dig;
5693
5694 #if DEC_DIGITS > 1
5695 NumericDigit d1;
5696 #endif
5697
5698 dscale = var->dscale;
5699
5700 /*
5701 * Allocate space for the result.
5702 *
5703 * i is set to the # of decimal digits before decimal point. dscale is the
5704 * # of decimal digits we will print after decimal point. We may generate
5705 * as many as DEC_DIGITS-1 excess digits at the end, and in addition we
5706 * need room for sign, decimal point, null terminator.
5707 */
5708 i = (var->weight + 1) * DEC_DIGITS;
5709 if (i <= 0)
5710 i = 1;
5711
5712 str = palloc(i + dscale + DEC_DIGITS + 2);
5713 cp = str;
5714
5715 /*
5716 * Output a dash for negative values
5717 */
5718 if (var->sign == NUMERIC_NEG)
5719 *cp++ = '-';
5720
5721 /*
5722 * Output all digits before the decimal point
5723 */
5724 if (var->weight < 0)
5725 {
5726 d = var->weight + 1;
5727 *cp++ = '0';
5728 }
5729 else
5730 {
5731 for (d = 0; d <= var->weight; d++)
5732 {
5733 dig = (d < var->ndigits) ? var->digits[d] : 0;
5734 /* In the first digit, suppress extra leading decimal zeroes */
5735 #if DEC_DIGITS == 4
5736 {
5737 bool putit = (d > 0);
5738
5739 d1 = dig / 1000;
5740 dig -= d1 * 1000;
5741 putit |= (d1 > 0);
5742 if (putit)
5743 *cp++ = d1 + '0';
5744 d1 = dig / 100;
5745 dig -= d1 * 100;
5746 putit |= (d1 > 0);
5747 if (putit)
5748 *cp++ = d1 + '0';
5749 d1 = dig / 10;
5750 dig -= d1 * 10;
5751 putit |= (d1 > 0);
5752 if (putit)
5753 *cp++ = d1 + '0';
5754 *cp++ = dig + '0';
5755 }
5756 #elif DEC_DIGITS == 2
5757 d1 = dig / 10;
5758 dig -= d1 * 10;
5759 if (d1 > 0 || d > 0)
5760 *cp++ = d1 + '0';
5761 *cp++ = dig + '0';
5762 #elif DEC_DIGITS == 1
5763 *cp++ = dig + '0';
5764 #else
5765 #error unsupported NBASE
5766 #endif
5767 }
5768 }
5769
5770 /*
5771 * If requested, output a decimal point and all the digits that follow it.
5772 * We initially put out a multiple of DEC_DIGITS digits, then truncate if
5773 * needed.
5774 */
5775 if (dscale > 0)
5776 {
5777 *cp++ = '.';
5778 endcp = cp + dscale;
5779 for (i = 0; i < dscale; d++, i += DEC_DIGITS)
5780 {
5781 dig = (d >= 0 && d < var->ndigits) ? var->digits[d] : 0;
5782 #if DEC_DIGITS == 4
5783 d1 = dig / 1000;
5784 dig -= d1 * 1000;
5785 *cp++ = d1 + '0';
5786 d1 = dig / 100;
5787 dig -= d1 * 100;
5788 *cp++ = d1 + '0';
5789 d1 = dig / 10;
5790 dig -= d1 * 10;
5791 *cp++ = d1 + '0';
5792 *cp++ = dig + '0';
5793 #elif DEC_DIGITS == 2
5794 d1 = dig / 10;
5795 dig -= d1 * 10;
5796 *cp++ = d1 + '0';
5797 *cp++ = dig + '0';
5798 #elif DEC_DIGITS == 1
5799 *cp++ = dig + '0';
5800 #else
5801 #error unsupported NBASE
5802 #endif
5803 }
5804 cp = endcp;
5805 }
5806
5807 /*
5808 * terminate the string and return it
5809 */
5810 *cp = '\0';
5811 return str;
5812 }
5813
5814 /*
5815 * get_str_from_var_sci() -
5816 *
5817 * Convert a var to a normalised scientific notation text representation.
5818 * This function does the heavy lifting for numeric_out_sci().
5819 *
5820 * This notation has the general form a * 10^b, where a is known as the
5821 * "significand" and b is known as the "exponent".
5822 *
5823 * Because we can't do superscript in ASCII (and because we want to copy
5824 * printf's behaviour) we display the exponent using E notation, with a
5825 * minimum of two exponent digits.
5826 *
5827 * For example, the value 1234 could be output as 1.2e+03.
5828 *
5829 * We assume that the exponent can fit into an int32.
5830 *
5831 * rscale is the number of decimal digits desired after the decimal point in
5832 * the output, negative values will be treated as meaning zero.
5833 *
5834 * Returns a palloc'd string.
5835 */
5836 static char *
get_str_from_var_sci(NumericVar * var,int rscale)5837 get_str_from_var_sci(NumericVar *var, int rscale)
5838 {
5839 int32 exponent;
5840 NumericVar tmp_var;
5841 size_t len;
5842 char *str;
5843 char *sig_out;
5844
5845 if (rscale < 0)
5846 rscale = 0;
5847
5848 /*
5849 * Determine the exponent of this number in normalised form.
5850 *
5851 * This is the exponent required to represent the number with only one
5852 * significant digit before the decimal place.
5853 */
5854 if (var->ndigits > 0)
5855 {
5856 exponent = (var->weight + 1) * DEC_DIGITS;
5857
5858 /*
5859 * Compensate for leading decimal zeroes in the first numeric digit by
5860 * decrementing the exponent.
5861 */
5862 exponent -= DEC_DIGITS - (int) log10(var->digits[0]);
5863 }
5864 else
5865 {
5866 /*
5867 * If var has no digits, then it must be zero.
5868 *
5869 * Zero doesn't technically have a meaningful exponent in normalised
5870 * notation, but we just display the exponent as zero for consistency
5871 * of output.
5872 */
5873 exponent = 0;
5874 }
5875
5876 /*
5877 * Divide var by 10^exponent to get the significand, rounding to rscale
5878 * decimal digits in the process.
5879 */
5880 init_var(&tmp_var);
5881
5882 power_ten_int(exponent, &tmp_var);
5883 div_var(var, &tmp_var, &tmp_var, rscale, true);
5884 sig_out = get_str_from_var(&tmp_var);
5885
5886 free_var(&tmp_var);
5887
5888 /*
5889 * Allocate space for the result.
5890 *
5891 * In addition to the significand, we need room for the exponent
5892 * decoration ("e"), the sign of the exponent, up to 10 digits for the
5893 * exponent itself, and of course the null terminator.
5894 */
5895 len = strlen(sig_out) + 13;
5896 str = palloc(len);
5897 snprintf(str, len, "%se%+03d", sig_out, exponent);
5898
5899 pfree(sig_out);
5900
5901 return str;
5902 }
5903
5904
5905 /*
5906 * make_result() -
5907 *
5908 * Create the packed db numeric format in palloc()'d memory from
5909 * a variable.
5910 */
5911 static Numeric
make_result(NumericVar * var)5912 make_result(NumericVar *var)
5913 {
5914 Numeric result;
5915 NumericDigit *digits = var->digits;
5916 int weight = var->weight;
5917 int sign = var->sign;
5918 int n;
5919 Size len;
5920
5921 if (sign == NUMERIC_NAN)
5922 {
5923 result = (Numeric) palloc(NUMERIC_HDRSZ_SHORT);
5924
5925 SET_VARSIZE(result, NUMERIC_HDRSZ_SHORT);
5926 result->choice.n_header = NUMERIC_NAN;
5927 /* the header word is all we need */
5928
5929 dump_numeric("make_result()", result);
5930 return result;
5931 }
5932
5933 n = var->ndigits;
5934
5935 /* truncate leading zeroes */
5936 while (n > 0 && *digits == 0)
5937 {
5938 digits++;
5939 weight--;
5940 n--;
5941 }
5942 /* truncate trailing zeroes */
5943 while (n > 0 && digits[n - 1] == 0)
5944 n--;
5945
5946 /* If zero result, force to weight=0 and positive sign */
5947 if (n == 0)
5948 {
5949 weight = 0;
5950 sign = NUMERIC_POS;
5951 }
5952
5953 /* Build the result */
5954 if (NUMERIC_CAN_BE_SHORT(var->dscale, weight))
5955 {
5956 len = NUMERIC_HDRSZ_SHORT + n * sizeof(NumericDigit);
5957 result = (Numeric) palloc(len);
5958 SET_VARSIZE(result, len);
5959 result->choice.n_short.n_header =
5960 (sign == NUMERIC_NEG ? (NUMERIC_SHORT | NUMERIC_SHORT_SIGN_MASK)
5961 : NUMERIC_SHORT)
5962 | (var->dscale << NUMERIC_SHORT_DSCALE_SHIFT)
5963 | (weight < 0 ? NUMERIC_SHORT_WEIGHT_SIGN_MASK : 0)
5964 | (weight & NUMERIC_SHORT_WEIGHT_MASK);
5965 }
5966 else
5967 {
5968 len = NUMERIC_HDRSZ + n * sizeof(NumericDigit);
5969 result = (Numeric) palloc(len);
5970 SET_VARSIZE(result, len);
5971 result->choice.n_long.n_sign_dscale =
5972 sign | (var->dscale & NUMERIC_DSCALE_MASK);
5973 result->choice.n_long.n_weight = weight;
5974 }
5975
5976 Assert(NUMERIC_NDIGITS(result) == n);
5977 if (n > 0)
5978 memcpy(NUMERIC_DIGITS(result), digits, n * sizeof(NumericDigit));
5979
5980 /* Check for overflow of int16 fields */
5981 if (NUMERIC_WEIGHT(result) != weight ||
5982 NUMERIC_DSCALE(result) != var->dscale)
5983 ereport(ERROR,
5984 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
5985 errmsg("value overflows numeric format")));
5986
5987 dump_numeric("make_result()", result);
5988 return result;
5989 }
5990
5991
5992 /*
5993 * apply_typmod() -
5994 *
5995 * Do bounds checking and rounding according to the attributes
5996 * typmod field.
5997 */
5998 static void
apply_typmod(NumericVar * var,int32 typmod)5999 apply_typmod(NumericVar *var, int32 typmod)
6000 {
6001 int precision;
6002 int scale;
6003 int maxdigits;
6004 int ddigits;
6005 int i;
6006
6007 /* Do nothing if we have a default typmod (-1) */
6008 if (typmod < (int32) (VARHDRSZ))
6009 return;
6010
6011 typmod -= VARHDRSZ;
6012 precision = (typmod >> 16) & 0xffff;
6013 scale = typmod & 0xffff;
6014 maxdigits = precision - scale;
6015
6016 /* Round to target scale (and set var->dscale) */
6017 round_var(var, scale);
6018
6019 /*
6020 * Check for overflow - note we can't do this before rounding, because
6021 * rounding could raise the weight. Also note that the var's weight could
6022 * be inflated by leading zeroes, which will be stripped before storage
6023 * but perhaps might not have been yet. In any case, we must recognize a
6024 * true zero, whose weight doesn't mean anything.
6025 */
6026 ddigits = (var->weight + 1) * DEC_DIGITS;
6027 if (ddigits > maxdigits)
6028 {
6029 /* Determine true weight; and check for all-zero result */
6030 for (i = 0; i < var->ndigits; i++)
6031 {
6032 NumericDigit dig = var->digits[i];
6033
6034 if (dig)
6035 {
6036 /* Adjust for any high-order decimal zero digits */
6037 #if DEC_DIGITS == 4
6038 if (dig < 10)
6039 ddigits -= 3;
6040 else if (dig < 100)
6041 ddigits -= 2;
6042 else if (dig < 1000)
6043 ddigits -= 1;
6044 #elif DEC_DIGITS == 2
6045 if (dig < 10)
6046 ddigits -= 1;
6047 #elif DEC_DIGITS == 1
6048 /* no adjustment */
6049 #else
6050 #error unsupported NBASE
6051 #endif
6052 if (ddigits > maxdigits)
6053 ereport(ERROR,
6054 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
6055 errmsg("numeric field overflow"),
6056 errdetail("A field with precision %d, scale %d must round to an absolute value less than %s%d.",
6057 precision, scale,
6058 /* Display 10^0 as 1 */
6059 maxdigits ? "10^" : "",
6060 maxdigits ? maxdigits : 1
6061 )));
6062 break;
6063 }
6064 ddigits -= DEC_DIGITS;
6065 }
6066 }
6067 }
6068
6069 /*
6070 * Convert numeric to int8, rounding if needed.
6071 *
6072 * If overflow, return FALSE (no error is raised). Return TRUE if okay.
6073 */
6074 static bool
numericvar_to_int64(NumericVar * var,int64 * result)6075 numericvar_to_int64(NumericVar *var, int64 *result)
6076 {
6077 NumericDigit *digits;
6078 int ndigits;
6079 int weight;
6080 int i;
6081 int64 val,
6082 oldval;
6083 bool neg;
6084 NumericVar rounded;
6085
6086 /* Round to nearest integer */
6087 init_var(&rounded);
6088 set_var_from_var(var, &rounded);
6089 round_var(&rounded, 0);
6090
6091 /* Check for zero input */
6092 strip_var(&rounded);
6093 ndigits = rounded.ndigits;
6094 if (ndigits == 0)
6095 {
6096 *result = 0;
6097 free_var(&rounded);
6098 return true;
6099 }
6100
6101 /*
6102 * For input like 10000000000, we must treat stripped digits as real. So
6103 * the loop assumes there are weight+1 digits before the decimal point.
6104 */
6105 weight = rounded.weight;
6106 Assert(weight >= 0 && ndigits <= weight + 1);
6107
6108 /* Construct the result */
6109 digits = rounded.digits;
6110 neg = (rounded.sign == NUMERIC_NEG);
6111 val = digits[0];
6112 for (i = 1; i <= weight; i++)
6113 {
6114 oldval = val;
6115 val *= NBASE;
6116 if (i < ndigits)
6117 val += digits[i];
6118
6119 /*
6120 * The overflow check is a bit tricky because we want to accept
6121 * INT64_MIN, which will overflow the positive accumulator. We can
6122 * detect this case easily though because INT64_MIN is the only
6123 * nonzero value for which -val == val (on a two's complement machine,
6124 * anyway).
6125 */
6126 if ((val / NBASE) != oldval) /* possible overflow? */
6127 {
6128 if (!neg || (-val) != val || val == 0 || oldval < 0)
6129 {
6130 free_var(&rounded);
6131 return false;
6132 }
6133 }
6134 }
6135
6136 free_var(&rounded);
6137
6138 *result = neg ? -val : val;
6139 return true;
6140 }
6141
6142 /*
6143 * Convert int8 value to numeric.
6144 */
6145 static void
int64_to_numericvar(int64 val,NumericVar * var)6146 int64_to_numericvar(int64 val, NumericVar *var)
6147 {
6148 uint64 uval,
6149 newuval;
6150 NumericDigit *ptr;
6151 int ndigits;
6152
6153 /* int64 can require at most 19 decimal digits; add one for safety */
6154 alloc_var(var, 20 / DEC_DIGITS);
6155 if (val < 0)
6156 {
6157 var->sign = NUMERIC_NEG;
6158 uval = -val;
6159 }
6160 else
6161 {
6162 var->sign = NUMERIC_POS;
6163 uval = val;
6164 }
6165 var->dscale = 0;
6166 if (val == 0)
6167 {
6168 var->ndigits = 0;
6169 var->weight = 0;
6170 return;
6171 }
6172 ptr = var->digits + var->ndigits;
6173 ndigits = 0;
6174 do
6175 {
6176 ptr--;
6177 ndigits++;
6178 newuval = uval / NBASE;
6179 *ptr = uval - newuval * NBASE;
6180 uval = newuval;
6181 } while (uval);
6182 var->digits = ptr;
6183 var->ndigits = ndigits;
6184 var->weight = ndigits - 1;
6185 }
6186
6187 #ifdef HAVE_INT128
6188 /*
6189 * Convert numeric to int128, rounding if needed.
6190 *
6191 * If overflow, return FALSE (no error is raised). Return TRUE if okay.
6192 */
6193 static bool
numericvar_to_int128(NumericVar * var,int128 * result)6194 numericvar_to_int128(NumericVar *var, int128 *result)
6195 {
6196 NumericDigit *digits;
6197 int ndigits;
6198 int weight;
6199 int i;
6200 int128 val,
6201 oldval;
6202 bool neg;
6203 NumericVar rounded;
6204
6205 /* Round to nearest integer */
6206 init_var(&rounded);
6207 set_var_from_var(var, &rounded);
6208 round_var(&rounded, 0);
6209
6210 /* Check for zero input */
6211 strip_var(&rounded);
6212 ndigits = rounded.ndigits;
6213 if (ndigits == 0)
6214 {
6215 *result = 0;
6216 free_var(&rounded);
6217 return true;
6218 }
6219
6220 /*
6221 * For input like 10000000000, we must treat stripped digits as real. So
6222 * the loop assumes there are weight+1 digits before the decimal point.
6223 */
6224 weight = rounded.weight;
6225 Assert(weight >= 0 && ndigits <= weight + 1);
6226
6227 /* Construct the result */
6228 digits = rounded.digits;
6229 neg = (rounded.sign == NUMERIC_NEG);
6230 val = digits[0];
6231 for (i = 1; i <= weight; i++)
6232 {
6233 oldval = val;
6234 val *= NBASE;
6235 if (i < ndigits)
6236 val += digits[i];
6237
6238 /*
6239 * The overflow check is a bit tricky because we want to accept
6240 * INT128_MIN, which will overflow the positive accumulator. We can
6241 * detect this case easily though because INT128_MIN is the only
6242 * nonzero value for which -val == val (on a two's complement machine,
6243 * anyway).
6244 */
6245 if ((val / NBASE) != oldval) /* possible overflow? */
6246 {
6247 if (!neg || (-val) != val || val == 0 || oldval < 0)
6248 {
6249 free_var(&rounded);
6250 return false;
6251 }
6252 }
6253 }
6254
6255 free_var(&rounded);
6256
6257 *result = neg ? -val : val;
6258 return true;
6259 }
6260
6261 /*
6262 * Convert 128 bit integer to numeric.
6263 */
6264 static void
int128_to_numericvar(int128 val,NumericVar * var)6265 int128_to_numericvar(int128 val, NumericVar *var)
6266 {
6267 uint128 uval,
6268 newuval;
6269 NumericDigit *ptr;
6270 int ndigits;
6271
6272 /* int128 can require at most 39 decimal digits; add one for safety */
6273 alloc_var(var, 40 / DEC_DIGITS);
6274 if (val < 0)
6275 {
6276 var->sign = NUMERIC_NEG;
6277 uval = -val;
6278 }
6279 else
6280 {
6281 var->sign = NUMERIC_POS;
6282 uval = val;
6283 }
6284 var->dscale = 0;
6285 if (val == 0)
6286 {
6287 var->ndigits = 0;
6288 var->weight = 0;
6289 return;
6290 }
6291 ptr = var->digits + var->ndigits;
6292 ndigits = 0;
6293 do
6294 {
6295 ptr--;
6296 ndigits++;
6297 newuval = uval / NBASE;
6298 *ptr = uval - newuval * NBASE;
6299 uval = newuval;
6300 } while (uval);
6301 var->digits = ptr;
6302 var->ndigits = ndigits;
6303 var->weight = ndigits - 1;
6304 }
6305 #endif
6306
6307 /*
6308 * Convert numeric to float8; if out of range, return +/- HUGE_VAL
6309 */
6310 static double
numeric_to_double_no_overflow(Numeric num)6311 numeric_to_double_no_overflow(Numeric num)
6312 {
6313 char *tmp;
6314 double val;
6315 char *endptr;
6316
6317 tmp = DatumGetCString(DirectFunctionCall1(numeric_out,
6318 NumericGetDatum(num)));
6319
6320 /* unlike float8in, we ignore ERANGE from strtod */
6321 val = strtod(tmp, &endptr);
6322 if (*endptr != '\0')
6323 {
6324 /* shouldn't happen ... */
6325 ereport(ERROR,
6326 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
6327 errmsg("invalid input syntax for type %s: \"%s\"",
6328 "double precision", tmp)));
6329 }
6330
6331 pfree(tmp);
6332
6333 return val;
6334 }
6335
6336 /* As above, but work from a NumericVar */
6337 static double
numericvar_to_double_no_overflow(NumericVar * var)6338 numericvar_to_double_no_overflow(NumericVar *var)
6339 {
6340 char *tmp;
6341 double val;
6342 char *endptr;
6343
6344 tmp = get_str_from_var(var);
6345
6346 /* unlike float8in, we ignore ERANGE from strtod */
6347 val = strtod(tmp, &endptr);
6348 if (*endptr != '\0')
6349 {
6350 /* shouldn't happen ... */
6351 ereport(ERROR,
6352 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
6353 errmsg("invalid input syntax for type %s: \"%s\"",
6354 "double precision", tmp)));
6355 }
6356
6357 pfree(tmp);
6358
6359 return val;
6360 }
6361
6362
6363 /*
6364 * cmp_var() -
6365 *
6366 * Compare two values on variable level. We assume zeroes have been
6367 * truncated to no digits.
6368 */
6369 static int
cmp_var(NumericVar * var1,NumericVar * var2)6370 cmp_var(NumericVar *var1, NumericVar *var2)
6371 {
6372 return cmp_var_common(var1->digits, var1->ndigits,
6373 var1->weight, var1->sign,
6374 var2->digits, var2->ndigits,
6375 var2->weight, var2->sign);
6376 }
6377
6378 /*
6379 * cmp_var_common() -
6380 *
6381 * Main routine of cmp_var(). This function can be used by both
6382 * NumericVar and Numeric.
6383 */
6384 static int
cmp_var_common(const NumericDigit * var1digits,int var1ndigits,int var1weight,int var1sign,const NumericDigit * var2digits,int var2ndigits,int var2weight,int var2sign)6385 cmp_var_common(const NumericDigit *var1digits, int var1ndigits,
6386 int var1weight, int var1sign,
6387 const NumericDigit *var2digits, int var2ndigits,
6388 int var2weight, int var2sign)
6389 {
6390 if (var1ndigits == 0)
6391 {
6392 if (var2ndigits == 0)
6393 return 0;
6394 if (var2sign == NUMERIC_NEG)
6395 return 1;
6396 return -1;
6397 }
6398 if (var2ndigits == 0)
6399 {
6400 if (var1sign == NUMERIC_POS)
6401 return 1;
6402 return -1;
6403 }
6404
6405 if (var1sign == NUMERIC_POS)
6406 {
6407 if (var2sign == NUMERIC_NEG)
6408 return 1;
6409 return cmp_abs_common(var1digits, var1ndigits, var1weight,
6410 var2digits, var2ndigits, var2weight);
6411 }
6412
6413 if (var2sign == NUMERIC_POS)
6414 return -1;
6415
6416 return cmp_abs_common(var2digits, var2ndigits, var2weight,
6417 var1digits, var1ndigits, var1weight);
6418 }
6419
6420
6421 /*
6422 * add_var() -
6423 *
6424 * Full version of add functionality on variable level (handling signs).
6425 * result might point to one of the operands too without danger.
6426 */
6427 static void
add_var(NumericVar * var1,NumericVar * var2,NumericVar * result)6428 add_var(NumericVar *var1, NumericVar *var2, NumericVar *result)
6429 {
6430 /*
6431 * Decide on the signs of the two variables what to do
6432 */
6433 if (var1->sign == NUMERIC_POS)
6434 {
6435 if (var2->sign == NUMERIC_POS)
6436 {
6437 /*
6438 * Both are positive result = +(ABS(var1) + ABS(var2))
6439 */
6440 add_abs(var1, var2, result);
6441 result->sign = NUMERIC_POS;
6442 }
6443 else
6444 {
6445 /*
6446 * var1 is positive, var2 is negative Must compare absolute values
6447 */
6448 switch (cmp_abs(var1, var2))
6449 {
6450 case 0:
6451 /* ----------
6452 * ABS(var1) == ABS(var2)
6453 * result = ZERO
6454 * ----------
6455 */
6456 zero_var(result);
6457 result->dscale = Max(var1->dscale, var2->dscale);
6458 break;
6459
6460 case 1:
6461 /* ----------
6462 * ABS(var1) > ABS(var2)
6463 * result = +(ABS(var1) - ABS(var2))
6464 * ----------
6465 */
6466 sub_abs(var1, var2, result);
6467 result->sign = NUMERIC_POS;
6468 break;
6469
6470 case -1:
6471 /* ----------
6472 * ABS(var1) < ABS(var2)
6473 * result = -(ABS(var2) - ABS(var1))
6474 * ----------
6475 */
6476 sub_abs(var2, var1, result);
6477 result->sign = NUMERIC_NEG;
6478 break;
6479 }
6480 }
6481 }
6482 else
6483 {
6484 if (var2->sign == NUMERIC_POS)
6485 {
6486 /* ----------
6487 * var1 is negative, var2 is positive
6488 * Must compare absolute values
6489 * ----------
6490 */
6491 switch (cmp_abs(var1, var2))
6492 {
6493 case 0:
6494 /* ----------
6495 * ABS(var1) == ABS(var2)
6496 * result = ZERO
6497 * ----------
6498 */
6499 zero_var(result);
6500 result->dscale = Max(var1->dscale, var2->dscale);
6501 break;
6502
6503 case 1:
6504 /* ----------
6505 * ABS(var1) > ABS(var2)
6506 * result = -(ABS(var1) - ABS(var2))
6507 * ----------
6508 */
6509 sub_abs(var1, var2, result);
6510 result->sign = NUMERIC_NEG;
6511 break;
6512
6513 case -1:
6514 /* ----------
6515 * ABS(var1) < ABS(var2)
6516 * result = +(ABS(var2) - ABS(var1))
6517 * ----------
6518 */
6519 sub_abs(var2, var1, result);
6520 result->sign = NUMERIC_POS;
6521 break;
6522 }
6523 }
6524 else
6525 {
6526 /* ----------
6527 * Both are negative
6528 * result = -(ABS(var1) + ABS(var2))
6529 * ----------
6530 */
6531 add_abs(var1, var2, result);
6532 result->sign = NUMERIC_NEG;
6533 }
6534 }
6535 }
6536
6537
6538 /*
6539 * sub_var() -
6540 *
6541 * Full version of sub functionality on variable level (handling signs).
6542 * result might point to one of the operands too without danger.
6543 */
6544 static void
sub_var(NumericVar * var1,NumericVar * var2,NumericVar * result)6545 sub_var(NumericVar *var1, NumericVar *var2, NumericVar *result)
6546 {
6547 /*
6548 * Decide on the signs of the two variables what to do
6549 */
6550 if (var1->sign == NUMERIC_POS)
6551 {
6552 if (var2->sign == NUMERIC_NEG)
6553 {
6554 /* ----------
6555 * var1 is positive, var2 is negative
6556 * result = +(ABS(var1) + ABS(var2))
6557 * ----------
6558 */
6559 add_abs(var1, var2, result);
6560 result->sign = NUMERIC_POS;
6561 }
6562 else
6563 {
6564 /* ----------
6565 * Both are positive
6566 * Must compare absolute values
6567 * ----------
6568 */
6569 switch (cmp_abs(var1, var2))
6570 {
6571 case 0:
6572 /* ----------
6573 * ABS(var1) == ABS(var2)
6574 * result = ZERO
6575 * ----------
6576 */
6577 zero_var(result);
6578 result->dscale = Max(var1->dscale, var2->dscale);
6579 break;
6580
6581 case 1:
6582 /* ----------
6583 * ABS(var1) > ABS(var2)
6584 * result = +(ABS(var1) - ABS(var2))
6585 * ----------
6586 */
6587 sub_abs(var1, var2, result);
6588 result->sign = NUMERIC_POS;
6589 break;
6590
6591 case -1:
6592 /* ----------
6593 * ABS(var1) < ABS(var2)
6594 * result = -(ABS(var2) - ABS(var1))
6595 * ----------
6596 */
6597 sub_abs(var2, var1, result);
6598 result->sign = NUMERIC_NEG;
6599 break;
6600 }
6601 }
6602 }
6603 else
6604 {
6605 if (var2->sign == NUMERIC_NEG)
6606 {
6607 /* ----------
6608 * Both are negative
6609 * Must compare absolute values
6610 * ----------
6611 */
6612 switch (cmp_abs(var1, var2))
6613 {
6614 case 0:
6615 /* ----------
6616 * ABS(var1) == ABS(var2)
6617 * result = ZERO
6618 * ----------
6619 */
6620 zero_var(result);
6621 result->dscale = Max(var1->dscale, var2->dscale);
6622 break;
6623
6624 case 1:
6625 /* ----------
6626 * ABS(var1) > ABS(var2)
6627 * result = -(ABS(var1) - ABS(var2))
6628 * ----------
6629 */
6630 sub_abs(var1, var2, result);
6631 result->sign = NUMERIC_NEG;
6632 break;
6633
6634 case -1:
6635 /* ----------
6636 * ABS(var1) < ABS(var2)
6637 * result = +(ABS(var2) - ABS(var1))
6638 * ----------
6639 */
6640 sub_abs(var2, var1, result);
6641 result->sign = NUMERIC_POS;
6642 break;
6643 }
6644 }
6645 else
6646 {
6647 /* ----------
6648 * var1 is negative, var2 is positive
6649 * result = -(ABS(var1) + ABS(var2))
6650 * ----------
6651 */
6652 add_abs(var1, var2, result);
6653 result->sign = NUMERIC_NEG;
6654 }
6655 }
6656 }
6657
6658
6659 /*
6660 * mul_var() -
6661 *
6662 * Multiplication on variable level. Product of var1 * var2 is stored
6663 * in result. Result is rounded to no more than rscale fractional digits.
6664 */
6665 static void
mul_var(NumericVar * var1,NumericVar * var2,NumericVar * result,int rscale)6666 mul_var(NumericVar *var1, NumericVar *var2, NumericVar *result,
6667 int rscale)
6668 {
6669 int res_ndigits;
6670 int res_sign;
6671 int res_weight;
6672 int maxdigits;
6673 int *dig;
6674 int carry;
6675 int maxdig;
6676 int newdig;
6677 int var1ndigits;
6678 int var2ndigits;
6679 NumericDigit *var1digits;
6680 NumericDigit *var2digits;
6681 NumericDigit *res_digits;
6682 int i,
6683 i1,
6684 i2;
6685
6686 /*
6687 * Arrange for var1 to be the shorter of the two numbers. This improves
6688 * performance because the inner multiplication loop is much simpler than
6689 * the outer loop, so it's better to have a smaller number of iterations
6690 * of the outer loop. This also reduces the number of times that the
6691 * accumulator array needs to be normalized.
6692 */
6693 if (var1->ndigits > var2->ndigits)
6694 {
6695 NumericVar *tmp = var1;
6696
6697 var1 = var2;
6698 var2 = tmp;
6699 }
6700
6701 /* copy these values into local vars for speed in inner loop */
6702 var1ndigits = var1->ndigits;
6703 var2ndigits = var2->ndigits;
6704 var1digits = var1->digits;
6705 var2digits = var2->digits;
6706
6707 if (var1ndigits == 0 || var2ndigits == 0)
6708 {
6709 /* one or both inputs is zero; so is result */
6710 zero_var(result);
6711 result->dscale = rscale;
6712 return;
6713 }
6714
6715 /* Determine result sign and (maximum possible) weight */
6716 if (var1->sign == var2->sign)
6717 res_sign = NUMERIC_POS;
6718 else
6719 res_sign = NUMERIC_NEG;
6720 res_weight = var1->weight + var2->weight + 2;
6721
6722 /*
6723 * Determine the number of result digits to compute. If the exact result
6724 * would have more than rscale fractional digits, truncate the computation
6725 * with MUL_GUARD_DIGITS guard digits, i.e., ignore input digits that
6726 * would only contribute to the right of that. (This will give the exact
6727 * rounded-to-rscale answer unless carries out of the ignored positions
6728 * would have propagated through more than MUL_GUARD_DIGITS digits.)
6729 *
6730 * Note: an exact computation could not produce more than var1ndigits +
6731 * var2ndigits digits, but we allocate one extra output digit in case
6732 * rscale-driven rounding produces a carry out of the highest exact digit.
6733 */
6734 res_ndigits = var1ndigits + var2ndigits + 1;
6735 maxdigits = res_weight + 1 + (rscale + DEC_DIGITS - 1) / DEC_DIGITS +
6736 MUL_GUARD_DIGITS;
6737 res_ndigits = Min(res_ndigits, maxdigits);
6738
6739 if (res_ndigits < 3)
6740 {
6741 /* All input digits will be ignored; so result is zero */
6742 zero_var(result);
6743 result->dscale = rscale;
6744 return;
6745 }
6746
6747 /*
6748 * We do the arithmetic in an array "dig[]" of signed int's. Since
6749 * INT_MAX is noticeably larger than NBASE*NBASE, this gives us headroom
6750 * to avoid normalizing carries immediately.
6751 *
6752 * maxdig tracks the maximum possible value of any dig[] entry; when this
6753 * threatens to exceed INT_MAX, we take the time to propagate carries.
6754 * Furthermore, we need to ensure that overflow doesn't occur during the
6755 * carry propagation passes either. The carry values could be as much as
6756 * INT_MAX/NBASE, so really we must normalize when digits threaten to
6757 * exceed INT_MAX - INT_MAX/NBASE.
6758 *
6759 * To avoid overflow in maxdig itself, it actually represents the max
6760 * possible value divided by NBASE-1, ie, at the top of the loop it is
6761 * known that no dig[] entry exceeds maxdig * (NBASE-1).
6762 */
6763 dig = (int *) palloc0(res_ndigits * sizeof(int));
6764 maxdig = 0;
6765
6766 /*
6767 * The least significant digits of var1 should be ignored if they don't
6768 * contribute directly to the first res_ndigits digits of the result that
6769 * we are computing.
6770 *
6771 * Digit i1 of var1 and digit i2 of var2 are multiplied and added to digit
6772 * i1+i2+2 of the accumulator array, so we need only consider digits of
6773 * var1 for which i1 <= res_ndigits - 3.
6774 */
6775 for (i1 = Min(var1ndigits - 1, res_ndigits - 3); i1 >= 0; i1--)
6776 {
6777 int var1digit = var1digits[i1];
6778
6779 if (var1digit == 0)
6780 continue;
6781
6782 /* Time to normalize? */
6783 maxdig += var1digit;
6784 if (maxdig > (INT_MAX - INT_MAX / NBASE) / (NBASE - 1))
6785 {
6786 /* Yes, do it */
6787 carry = 0;
6788 for (i = res_ndigits - 1; i >= 0; i--)
6789 {
6790 newdig = dig[i] + carry;
6791 if (newdig >= NBASE)
6792 {
6793 carry = newdig / NBASE;
6794 newdig -= carry * NBASE;
6795 }
6796 else
6797 carry = 0;
6798 dig[i] = newdig;
6799 }
6800 Assert(carry == 0);
6801 /* Reset maxdig to indicate new worst-case */
6802 maxdig = 1 + var1digit;
6803 }
6804
6805 /*
6806 * Add the appropriate multiple of var2 into the accumulator.
6807 *
6808 * As above, digits of var2 can be ignored if they don't contribute,
6809 * so we only include digits for which i1+i2+2 <= res_ndigits - 1.
6810 */
6811 for (i2 = Min(var2ndigits - 1, res_ndigits - i1 - 3), i = i1 + i2 + 2;
6812 i2 >= 0; i2--)
6813 dig[i--] += var1digit * var2digits[i2];
6814 }
6815
6816 /*
6817 * Now we do a final carry propagation pass to normalize the result, which
6818 * we combine with storing the result digits into the output. Note that
6819 * this is still done at full precision w/guard digits.
6820 */
6821 alloc_var(result, res_ndigits);
6822 res_digits = result->digits;
6823 carry = 0;
6824 for (i = res_ndigits - 1; i >= 0; i--)
6825 {
6826 newdig = dig[i] + carry;
6827 if (newdig >= NBASE)
6828 {
6829 carry = newdig / NBASE;
6830 newdig -= carry * NBASE;
6831 }
6832 else
6833 carry = 0;
6834 res_digits[i] = newdig;
6835 }
6836 Assert(carry == 0);
6837
6838 pfree(dig);
6839
6840 /*
6841 * Finally, round the result to the requested precision.
6842 */
6843 result->weight = res_weight;
6844 result->sign = res_sign;
6845
6846 /* Round to target rscale (and set result->dscale) */
6847 round_var(result, rscale);
6848
6849 /* Strip leading and trailing zeroes */
6850 strip_var(result);
6851 }
6852
6853
6854 /*
6855 * div_var() -
6856 *
6857 * Division on variable level. Quotient of var1 / var2 is stored in result.
6858 * The quotient is figured to exactly rscale fractional digits.
6859 * If round is true, it is rounded at the rscale'th digit; if false, it
6860 * is truncated (towards zero) at that digit.
6861 */
6862 static void
div_var(NumericVar * var1,NumericVar * var2,NumericVar * result,int rscale,bool round)6863 div_var(NumericVar *var1, NumericVar *var2, NumericVar *result,
6864 int rscale, bool round)
6865 {
6866 int div_ndigits;
6867 int res_ndigits;
6868 int res_sign;
6869 int res_weight;
6870 int carry;
6871 int borrow;
6872 int divisor1;
6873 int divisor2;
6874 NumericDigit *dividend;
6875 NumericDigit *divisor;
6876 NumericDigit *res_digits;
6877 int i;
6878 int j;
6879
6880 /* copy these values into local vars for speed in inner loop */
6881 int var1ndigits = var1->ndigits;
6882 int var2ndigits = var2->ndigits;
6883
6884 /*
6885 * First of all division by zero check; we must not be handed an
6886 * unnormalized divisor.
6887 */
6888 if (var2ndigits == 0 || var2->digits[0] == 0)
6889 ereport(ERROR,
6890 (errcode(ERRCODE_DIVISION_BY_ZERO),
6891 errmsg("division by zero")));
6892
6893 /*
6894 * Now result zero check
6895 */
6896 if (var1ndigits == 0)
6897 {
6898 zero_var(result);
6899 result->dscale = rscale;
6900 return;
6901 }
6902
6903 /*
6904 * Determine the result sign, weight and number of digits to calculate.
6905 * The weight figured here is correct if the emitted quotient has no
6906 * leading zero digits; otherwise strip_var() will fix things up.
6907 */
6908 if (var1->sign == var2->sign)
6909 res_sign = NUMERIC_POS;
6910 else
6911 res_sign = NUMERIC_NEG;
6912 res_weight = var1->weight - var2->weight;
6913 /* The number of accurate result digits we need to produce: */
6914 res_ndigits = res_weight + 1 + (rscale + DEC_DIGITS - 1) / DEC_DIGITS;
6915 /* ... but always at least 1 */
6916 res_ndigits = Max(res_ndigits, 1);
6917 /* If rounding needed, figure one more digit to ensure correct result */
6918 if (round)
6919 res_ndigits++;
6920
6921 /*
6922 * The working dividend normally requires res_ndigits + var2ndigits
6923 * digits, but make it at least var1ndigits so we can load all of var1
6924 * into it. (There will be an additional digit dividend[0] in the
6925 * dividend space, but for consistency with Knuth's notation we don't
6926 * count that in div_ndigits.)
6927 */
6928 div_ndigits = res_ndigits + var2ndigits;
6929 div_ndigits = Max(div_ndigits, var1ndigits);
6930
6931 /*
6932 * We need a workspace with room for the working dividend (div_ndigits+1
6933 * digits) plus room for the possibly-normalized divisor (var2ndigits
6934 * digits). It is convenient also to have a zero at divisor[0] with the
6935 * actual divisor data in divisor[1 .. var2ndigits]. Transferring the
6936 * digits into the workspace also allows us to realloc the result (which
6937 * might be the same as either input var) before we begin the main loop.
6938 * Note that we use palloc0 to ensure that divisor[0], dividend[0], and
6939 * any additional dividend positions beyond var1ndigits, start out 0.
6940 */
6941 dividend = (NumericDigit *)
6942 palloc0((div_ndigits + var2ndigits + 2) * sizeof(NumericDigit));
6943 divisor = dividend + (div_ndigits + 1);
6944 memcpy(dividend + 1, var1->digits, var1ndigits * sizeof(NumericDigit));
6945 memcpy(divisor + 1, var2->digits, var2ndigits * sizeof(NumericDigit));
6946
6947 /*
6948 * Now we can realloc the result to hold the generated quotient digits.
6949 */
6950 alloc_var(result, res_ndigits);
6951 res_digits = result->digits;
6952
6953 if (var2ndigits == 1)
6954 {
6955 /*
6956 * If there's only a single divisor digit, we can use a fast path (cf.
6957 * Knuth section 4.3.1 exercise 16).
6958 */
6959 divisor1 = divisor[1];
6960 carry = 0;
6961 for (i = 0; i < res_ndigits; i++)
6962 {
6963 carry = carry * NBASE + dividend[i + 1];
6964 res_digits[i] = carry / divisor1;
6965 carry = carry % divisor1;
6966 }
6967 }
6968 else
6969 {
6970 /*
6971 * The full multiple-place algorithm is taken from Knuth volume 2,
6972 * Algorithm 4.3.1D.
6973 *
6974 * We need the first divisor digit to be >= NBASE/2. If it isn't,
6975 * make it so by scaling up both the divisor and dividend by the
6976 * factor "d". (The reason for allocating dividend[0] above is to
6977 * leave room for possible carry here.)
6978 */
6979 if (divisor[1] < HALF_NBASE)
6980 {
6981 int d = NBASE / (divisor[1] + 1);
6982
6983 carry = 0;
6984 for (i = var2ndigits; i > 0; i--)
6985 {
6986 carry += divisor[i] * d;
6987 divisor[i] = carry % NBASE;
6988 carry = carry / NBASE;
6989 }
6990 Assert(carry == 0);
6991 carry = 0;
6992 /* at this point only var1ndigits of dividend can be nonzero */
6993 for (i = var1ndigits; i >= 0; i--)
6994 {
6995 carry += dividend[i] * d;
6996 dividend[i] = carry % NBASE;
6997 carry = carry / NBASE;
6998 }
6999 Assert(carry == 0);
7000 Assert(divisor[1] >= HALF_NBASE);
7001 }
7002 /* First 2 divisor digits are used repeatedly in main loop */
7003 divisor1 = divisor[1];
7004 divisor2 = divisor[2];
7005
7006 /*
7007 * Begin the main loop. Each iteration of this loop produces the j'th
7008 * quotient digit by dividing dividend[j .. j + var2ndigits] by the
7009 * divisor; this is essentially the same as the common manual
7010 * procedure for long division.
7011 */
7012 for (j = 0; j < res_ndigits; j++)
7013 {
7014 /* Estimate quotient digit from the first two dividend digits */
7015 int next2digits = dividend[j] * NBASE + dividend[j + 1];
7016 int qhat;
7017
7018 /*
7019 * If next2digits are 0, then quotient digit must be 0 and there's
7020 * no need to adjust the working dividend. It's worth testing
7021 * here to fall out ASAP when processing trailing zeroes in a
7022 * dividend.
7023 */
7024 if (next2digits == 0)
7025 {
7026 res_digits[j] = 0;
7027 continue;
7028 }
7029
7030 if (dividend[j] == divisor1)
7031 qhat = NBASE - 1;
7032 else
7033 qhat = next2digits / divisor1;
7034
7035 /*
7036 * Adjust quotient digit if it's too large. Knuth proves that
7037 * after this step, the quotient digit will be either correct or
7038 * just one too large. (Note: it's OK to use dividend[j+2] here
7039 * because we know the divisor length is at least 2.)
7040 */
7041 while (divisor2 * qhat >
7042 (next2digits - qhat * divisor1) * NBASE + dividend[j + 2])
7043 qhat--;
7044
7045 /* As above, need do nothing more when quotient digit is 0 */
7046 if (qhat > 0)
7047 {
7048 /*
7049 * Multiply the divisor by qhat, and subtract that from the
7050 * working dividend. "carry" tracks the multiplication,
7051 * "borrow" the subtraction (could we fold these together?)
7052 */
7053 carry = 0;
7054 borrow = 0;
7055 for (i = var2ndigits; i >= 0; i--)
7056 {
7057 carry += divisor[i] * qhat;
7058 borrow -= carry % NBASE;
7059 carry = carry / NBASE;
7060 borrow += dividend[j + i];
7061 if (borrow < 0)
7062 {
7063 dividend[j + i] = borrow + NBASE;
7064 borrow = -1;
7065 }
7066 else
7067 {
7068 dividend[j + i] = borrow;
7069 borrow = 0;
7070 }
7071 }
7072 Assert(carry == 0);
7073
7074 /*
7075 * If we got a borrow out of the top dividend digit, then
7076 * indeed qhat was one too large. Fix it, and add back the
7077 * divisor to correct the working dividend. (Knuth proves
7078 * that this will occur only about 3/NBASE of the time; hence,
7079 * it's a good idea to test this code with small NBASE to be
7080 * sure this section gets exercised.)
7081 */
7082 if (borrow)
7083 {
7084 qhat--;
7085 carry = 0;
7086 for (i = var2ndigits; i >= 0; i--)
7087 {
7088 carry += dividend[j + i] + divisor[i];
7089 if (carry >= NBASE)
7090 {
7091 dividend[j + i] = carry - NBASE;
7092 carry = 1;
7093 }
7094 else
7095 {
7096 dividend[j + i] = carry;
7097 carry = 0;
7098 }
7099 }
7100 /* A carry should occur here to cancel the borrow above */
7101 Assert(carry == 1);
7102 }
7103 }
7104
7105 /* And we're done with this quotient digit */
7106 res_digits[j] = qhat;
7107 }
7108 }
7109
7110 pfree(dividend);
7111
7112 /*
7113 * Finally, round or truncate the result to the requested precision.
7114 */
7115 result->weight = res_weight;
7116 result->sign = res_sign;
7117
7118 /* Round or truncate to target rscale (and set result->dscale) */
7119 if (round)
7120 round_var(result, rscale);
7121 else
7122 trunc_var(result, rscale);
7123
7124 /* Strip leading and trailing zeroes */
7125 strip_var(result);
7126 }
7127
7128
7129 /*
7130 * div_var_fast() -
7131 *
7132 * This has the same API as div_var, but is implemented using the division
7133 * algorithm from the "FM" library, rather than Knuth's schoolbook-division
7134 * approach. This is significantly faster but can produce inaccurate
7135 * results, because it sometimes has to propagate rounding to the left,
7136 * and so we can never be entirely sure that we know the requested digits
7137 * exactly. We compute DIV_GUARD_DIGITS extra digits, but there is
7138 * no certainty that that's enough. We use this only in the transcendental
7139 * function calculation routines, where everything is approximate anyway.
7140 *
7141 * Although we provide a "round" argument for consistency with div_var,
7142 * it is unwise to use this function with round=false. In truncation mode
7143 * it is possible to get a result with no significant digits, for example
7144 * with rscale=0 we might compute 0.99999... and truncate that to 0 when
7145 * the correct answer is 1.
7146 */
7147 static void
div_var_fast(NumericVar * var1,NumericVar * var2,NumericVar * result,int rscale,bool round)7148 div_var_fast(NumericVar *var1, NumericVar *var2, NumericVar *result,
7149 int rscale, bool round)
7150 {
7151 int div_ndigits;
7152 int res_sign;
7153 int res_weight;
7154 int *div;
7155 int qdigit;
7156 int carry;
7157 int maxdiv;
7158 int newdig;
7159 NumericDigit *res_digits;
7160 double fdividend,
7161 fdivisor,
7162 fdivisorinverse,
7163 fquotient;
7164 int qi;
7165 int i;
7166
7167 /* copy these values into local vars for speed in inner loop */
7168 int var1ndigits = var1->ndigits;
7169 int var2ndigits = var2->ndigits;
7170 NumericDigit *var1digits = var1->digits;
7171 NumericDigit *var2digits = var2->digits;
7172
7173 /*
7174 * First of all division by zero check; we must not be handed an
7175 * unnormalized divisor.
7176 */
7177 if (var2ndigits == 0 || var2digits[0] == 0)
7178 ereport(ERROR,
7179 (errcode(ERRCODE_DIVISION_BY_ZERO),
7180 errmsg("division by zero")));
7181
7182 /*
7183 * Now result zero check
7184 */
7185 if (var1ndigits == 0)
7186 {
7187 zero_var(result);
7188 result->dscale = rscale;
7189 return;
7190 }
7191
7192 /*
7193 * Determine the result sign, weight and number of digits to calculate
7194 */
7195 if (var1->sign == var2->sign)
7196 res_sign = NUMERIC_POS;
7197 else
7198 res_sign = NUMERIC_NEG;
7199 res_weight = var1->weight - var2->weight + 1;
7200 /* The number of accurate result digits we need to produce: */
7201 div_ndigits = res_weight + 1 + (rscale + DEC_DIGITS - 1) / DEC_DIGITS;
7202 /* Add guard digits for roundoff error */
7203 div_ndigits += DIV_GUARD_DIGITS;
7204 if (div_ndigits < DIV_GUARD_DIGITS)
7205 div_ndigits = DIV_GUARD_DIGITS;
7206 /* Must be at least var1ndigits, too, to simplify data-loading loop */
7207 if (div_ndigits < var1ndigits)
7208 div_ndigits = var1ndigits;
7209
7210 /*
7211 * We do the arithmetic in an array "div[]" of signed int's. Since
7212 * INT_MAX is noticeably larger than NBASE*NBASE, this gives us headroom
7213 * to avoid normalizing carries immediately.
7214 *
7215 * We start with div[] containing one zero digit followed by the
7216 * dividend's digits (plus appended zeroes to reach the desired precision
7217 * including guard digits). Each step of the main loop computes an
7218 * (approximate) quotient digit and stores it into div[], removing one
7219 * position of dividend space. A final pass of carry propagation takes
7220 * care of any mistaken quotient digits.
7221 */
7222 div = (int *) palloc0((div_ndigits + 1) * sizeof(int));
7223 for (i = 0; i < var1ndigits; i++)
7224 div[i + 1] = var1digits[i];
7225
7226 /*
7227 * We estimate each quotient digit using floating-point arithmetic, taking
7228 * the first four digits of the (current) dividend and divisor. This must
7229 * be float to avoid overflow. The quotient digits will generally be off
7230 * by no more than one from the exact answer.
7231 */
7232 fdivisor = (double) var2digits[0];
7233 for (i = 1; i < 4; i++)
7234 {
7235 fdivisor *= NBASE;
7236 if (i < var2ndigits)
7237 fdivisor += (double) var2digits[i];
7238 }
7239 fdivisorinverse = 1.0 / fdivisor;
7240
7241 /*
7242 * maxdiv tracks the maximum possible absolute value of any div[] entry;
7243 * when this threatens to exceed INT_MAX, we take the time to propagate
7244 * carries. Furthermore, we need to ensure that overflow doesn't occur
7245 * during the carry propagation passes either. The carry values may have
7246 * an absolute value as high as INT_MAX/NBASE + 1, so really we must
7247 * normalize when digits threaten to exceed INT_MAX - INT_MAX/NBASE - 1.
7248 *
7249 * To avoid overflow in maxdiv itself, it represents the max absolute
7250 * value divided by NBASE-1, ie, at the top of the loop it is known that
7251 * no div[] entry has an absolute value exceeding maxdiv * (NBASE-1).
7252 *
7253 * Actually, though, that holds good only for div[] entries after div[qi];
7254 * the adjustment done at the bottom of the loop may cause div[qi + 1] to
7255 * exceed the maxdiv limit, so that div[qi] in the next iteration is
7256 * beyond the limit. This does not cause problems, as explained below.
7257 */
7258 maxdiv = 1;
7259
7260 /*
7261 * Outer loop computes next quotient digit, which will go into div[qi]
7262 */
7263 for (qi = 0; qi < div_ndigits; qi++)
7264 {
7265 /* Approximate the current dividend value */
7266 fdividend = (double) div[qi];
7267 for (i = 1; i < 4; i++)
7268 {
7269 fdividend *= NBASE;
7270 if (qi + i <= div_ndigits)
7271 fdividend += (double) div[qi + i];
7272 }
7273 /* Compute the (approximate) quotient digit */
7274 fquotient = fdividend * fdivisorinverse;
7275 qdigit = (fquotient >= 0.0) ? ((int) fquotient) :
7276 (((int) fquotient) - 1); /* truncate towards -infinity */
7277
7278 if (qdigit != 0)
7279 {
7280 /* Do we need to normalize now? */
7281 maxdiv += Abs(qdigit);
7282 if (maxdiv > (INT_MAX - INT_MAX / NBASE - 1) / (NBASE - 1))
7283 {
7284 /* Yes, do it */
7285 carry = 0;
7286 for (i = div_ndigits; i > qi; i--)
7287 {
7288 newdig = div[i] + carry;
7289 if (newdig < 0)
7290 {
7291 carry = -((-newdig - 1) / NBASE) - 1;
7292 newdig -= carry * NBASE;
7293 }
7294 else if (newdig >= NBASE)
7295 {
7296 carry = newdig / NBASE;
7297 newdig -= carry * NBASE;
7298 }
7299 else
7300 carry = 0;
7301 div[i] = newdig;
7302 }
7303 newdig = div[qi] + carry;
7304 div[qi] = newdig;
7305
7306 /*
7307 * All the div[] digits except possibly div[qi] are now in the
7308 * range 0..NBASE-1. We do not need to consider div[qi] in
7309 * the maxdiv value anymore, so we can reset maxdiv to 1.
7310 */
7311 maxdiv = 1;
7312
7313 /*
7314 * Recompute the quotient digit since new info may have
7315 * propagated into the top four dividend digits
7316 */
7317 fdividend = (double) div[qi];
7318 for (i = 1; i < 4; i++)
7319 {
7320 fdividend *= NBASE;
7321 if (qi + i <= div_ndigits)
7322 fdividend += (double) div[qi + i];
7323 }
7324 /* Compute the (approximate) quotient digit */
7325 fquotient = fdividend * fdivisorinverse;
7326 qdigit = (fquotient >= 0.0) ? ((int) fquotient) :
7327 (((int) fquotient) - 1); /* truncate towards -infinity */
7328 maxdiv += Abs(qdigit);
7329 }
7330
7331 /*
7332 * Subtract off the appropriate multiple of the divisor.
7333 *
7334 * The digits beyond div[qi] cannot overflow, because we know they
7335 * will fall within the maxdiv limit. As for div[qi] itself, note
7336 * that qdigit is approximately trunc(div[qi] / vardigits[0]),
7337 * which would make the new value simply div[qi] mod vardigits[0].
7338 * The lower-order terms in qdigit can change this result by not
7339 * more than about twice INT_MAX/NBASE, so overflow is impossible.
7340 */
7341 if (qdigit != 0)
7342 {
7343 int istop = Min(var2ndigits, div_ndigits - qi + 1);
7344
7345 for (i = 0; i < istop; i++)
7346 div[qi + i] -= qdigit * var2digits[i];
7347 }
7348 }
7349
7350 /*
7351 * The dividend digit we are about to replace might still be nonzero.
7352 * Fold it into the next digit position.
7353 *
7354 * There is no risk of overflow here, although proving that requires
7355 * some care. Much as with the argument for div[qi] not overflowing,
7356 * if we consider the first two terms in the numerator and denominator
7357 * of qdigit, we can see that the final value of div[qi + 1] will be
7358 * approximately a remainder mod (vardigits[0]*NBASE + vardigits[1]).
7359 * Accounting for the lower-order terms is a bit complicated but ends
7360 * up adding not much more than INT_MAX/NBASE to the possible range.
7361 * Thus, div[qi + 1] cannot overflow here, and in its role as div[qi]
7362 * in the next loop iteration, it can't be large enough to cause
7363 * overflow in the carry propagation step (if any), either.
7364 *
7365 * But having said that: div[qi] can be more than INT_MAX/NBASE, as
7366 * noted above, which means that the product div[qi] * NBASE *can*
7367 * overflow. When that happens, adding it to div[qi + 1] will always
7368 * cause a canceling overflow so that the end result is correct. We
7369 * could avoid the intermediate overflow by doing the multiplication
7370 * and addition in int64 arithmetic, but so far there appears no need.
7371 */
7372 div[qi + 1] += div[qi] * NBASE;
7373
7374 div[qi] = qdigit;
7375 }
7376
7377 /*
7378 * Approximate and store the last quotient digit (div[div_ndigits])
7379 */
7380 fdividend = (double) div[qi];
7381 for (i = 1; i < 4; i++)
7382 fdividend *= NBASE;
7383 fquotient = fdividend * fdivisorinverse;
7384 qdigit = (fquotient >= 0.0) ? ((int) fquotient) :
7385 (((int) fquotient) - 1); /* truncate towards -infinity */
7386 div[qi] = qdigit;
7387
7388 /*
7389 * Because the quotient digits might be off by one, some of them might be
7390 * -1 or NBASE at this point. The represented value is correct in a
7391 * mathematical sense, but it doesn't look right. We do a final carry
7392 * propagation pass to normalize the digits, which we combine with storing
7393 * the result digits into the output. Note that this is still done at
7394 * full precision w/guard digits.
7395 */
7396 alloc_var(result, div_ndigits + 1);
7397 res_digits = result->digits;
7398 carry = 0;
7399 for (i = div_ndigits; i >= 0; i--)
7400 {
7401 newdig = div[i] + carry;
7402 if (newdig < 0)
7403 {
7404 carry = -((-newdig - 1) / NBASE) - 1;
7405 newdig -= carry * NBASE;
7406 }
7407 else if (newdig >= NBASE)
7408 {
7409 carry = newdig / NBASE;
7410 newdig -= carry * NBASE;
7411 }
7412 else
7413 carry = 0;
7414 res_digits[i] = newdig;
7415 }
7416 Assert(carry == 0);
7417
7418 pfree(div);
7419
7420 /*
7421 * Finally, round the result to the requested precision.
7422 */
7423 result->weight = res_weight;
7424 result->sign = res_sign;
7425
7426 /* Round to target rscale (and set result->dscale) */
7427 if (round)
7428 round_var(result, rscale);
7429 else
7430 trunc_var(result, rscale);
7431
7432 /* Strip leading and trailing zeroes */
7433 strip_var(result);
7434 }
7435
7436
7437 /*
7438 * Default scale selection for division
7439 *
7440 * Returns the appropriate result scale for the division result.
7441 */
7442 static int
select_div_scale(NumericVar * var1,NumericVar * var2)7443 select_div_scale(NumericVar *var1, NumericVar *var2)
7444 {
7445 int weight1,
7446 weight2,
7447 qweight,
7448 i;
7449 NumericDigit firstdigit1,
7450 firstdigit2;
7451 int rscale;
7452
7453 /*
7454 * The result scale of a division isn't specified in any SQL standard. For
7455 * PostgreSQL we select a result scale that will give at least
7456 * NUMERIC_MIN_SIG_DIGITS significant digits, so that numeric gives a
7457 * result no less accurate than float8; but use a scale not less than
7458 * either input's display scale.
7459 */
7460
7461 /* Get the actual (normalized) weight and first digit of each input */
7462
7463 weight1 = 0; /* values to use if var1 is zero */
7464 firstdigit1 = 0;
7465 for (i = 0; i < var1->ndigits; i++)
7466 {
7467 firstdigit1 = var1->digits[i];
7468 if (firstdigit1 != 0)
7469 {
7470 weight1 = var1->weight - i;
7471 break;
7472 }
7473 }
7474
7475 weight2 = 0; /* values to use if var2 is zero */
7476 firstdigit2 = 0;
7477 for (i = 0; i < var2->ndigits; i++)
7478 {
7479 firstdigit2 = var2->digits[i];
7480 if (firstdigit2 != 0)
7481 {
7482 weight2 = var2->weight - i;
7483 break;
7484 }
7485 }
7486
7487 /*
7488 * Estimate weight of quotient. If the two first digits are equal, we
7489 * can't be sure, but assume that var1 is less than var2.
7490 */
7491 qweight = weight1 - weight2;
7492 if (firstdigit1 <= firstdigit2)
7493 qweight--;
7494
7495 /* Select result scale */
7496 rscale = NUMERIC_MIN_SIG_DIGITS - qweight * DEC_DIGITS;
7497 rscale = Max(rscale, var1->dscale);
7498 rscale = Max(rscale, var2->dscale);
7499 rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
7500 rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
7501
7502 return rscale;
7503 }
7504
7505
7506 /*
7507 * mod_var() -
7508 *
7509 * Calculate the modulo of two numerics at variable level
7510 */
7511 static void
mod_var(NumericVar * var1,NumericVar * var2,NumericVar * result)7512 mod_var(NumericVar *var1, NumericVar *var2, NumericVar *result)
7513 {
7514 NumericVar tmp;
7515
7516 init_var(&tmp);
7517
7518 /* ---------
7519 * We do this using the equation
7520 * mod(x,y) = x - trunc(x/y)*y
7521 * div_var can be persuaded to give us trunc(x/y) directly.
7522 * ----------
7523 */
7524 div_var(var1, var2, &tmp, 0, false);
7525
7526 mul_var(var2, &tmp, &tmp, var2->dscale);
7527
7528 sub_var(var1, &tmp, result);
7529
7530 free_var(&tmp);
7531 }
7532
7533
7534 /*
7535 * ceil_var() -
7536 *
7537 * Return the smallest integer greater than or equal to the argument
7538 * on variable level
7539 */
7540 static void
ceil_var(NumericVar * var,NumericVar * result)7541 ceil_var(NumericVar *var, NumericVar *result)
7542 {
7543 NumericVar tmp;
7544
7545 init_var(&tmp);
7546 set_var_from_var(var, &tmp);
7547
7548 trunc_var(&tmp, 0);
7549
7550 if (var->sign == NUMERIC_POS && cmp_var(var, &tmp) != 0)
7551 add_var(&tmp, &const_one, &tmp);
7552
7553 set_var_from_var(&tmp, result);
7554 free_var(&tmp);
7555 }
7556
7557
7558 /*
7559 * floor_var() -
7560 *
7561 * Return the largest integer equal to or less than the argument
7562 * on variable level
7563 */
7564 static void
floor_var(NumericVar * var,NumericVar * result)7565 floor_var(NumericVar *var, NumericVar *result)
7566 {
7567 NumericVar tmp;
7568
7569 init_var(&tmp);
7570 set_var_from_var(var, &tmp);
7571
7572 trunc_var(&tmp, 0);
7573
7574 if (var->sign == NUMERIC_NEG && cmp_var(var, &tmp) != 0)
7575 sub_var(&tmp, &const_one, &tmp);
7576
7577 set_var_from_var(&tmp, result);
7578 free_var(&tmp);
7579 }
7580
7581
7582 /*
7583 * sqrt_var() -
7584 *
7585 * Compute the square root of x using Newton's algorithm
7586 */
7587 static void
sqrt_var(NumericVar * arg,NumericVar * result,int rscale)7588 sqrt_var(NumericVar *arg, NumericVar *result, int rscale)
7589 {
7590 NumericVar tmp_arg;
7591 NumericVar tmp_val;
7592 NumericVar last_val;
7593 int local_rscale;
7594 int stat;
7595
7596 local_rscale = rscale + 8;
7597
7598 stat = cmp_var(arg, &const_zero);
7599 if (stat == 0)
7600 {
7601 zero_var(result);
7602 result->dscale = rscale;
7603 return;
7604 }
7605
7606 /*
7607 * SQL2003 defines sqrt() in terms of power, so we need to emit the right
7608 * SQLSTATE error code if the operand is negative.
7609 */
7610 if (stat < 0)
7611 ereport(ERROR,
7612 (errcode(ERRCODE_INVALID_ARGUMENT_FOR_POWER_FUNCTION),
7613 errmsg("cannot take square root of a negative number")));
7614
7615 init_var(&tmp_arg);
7616 init_var(&tmp_val);
7617 init_var(&last_val);
7618
7619 /* Copy arg in case it is the same var as result */
7620 set_var_from_var(arg, &tmp_arg);
7621
7622 /*
7623 * Initialize the result to the first guess
7624 */
7625 alloc_var(result, 1);
7626 result->digits[0] = tmp_arg.digits[0] / 2;
7627 if (result->digits[0] == 0)
7628 result->digits[0] = 1;
7629 result->weight = tmp_arg.weight / 2;
7630 result->sign = NUMERIC_POS;
7631
7632 set_var_from_var(result, &last_val);
7633
7634 for (;;)
7635 {
7636 div_var_fast(&tmp_arg, result, &tmp_val, local_rscale, true);
7637
7638 add_var(result, &tmp_val, result);
7639 mul_var(result, &const_zero_point_five, result, local_rscale);
7640
7641 if (cmp_var(&last_val, result) == 0)
7642 break;
7643 set_var_from_var(result, &last_val);
7644 }
7645
7646 free_var(&last_val);
7647 free_var(&tmp_val);
7648 free_var(&tmp_arg);
7649
7650 /* Round to requested precision */
7651 round_var(result, rscale);
7652 }
7653
7654
7655 /*
7656 * exp_var() -
7657 *
7658 * Raise e to the power of x, computed to rscale fractional digits
7659 */
7660 static void
exp_var(NumericVar * arg,NumericVar * result,int rscale)7661 exp_var(NumericVar *arg, NumericVar *result, int rscale)
7662 {
7663 NumericVar x;
7664 NumericVar elem;
7665 NumericVar ni;
7666 double val;
7667 int dweight;
7668 int ndiv2;
7669 int sig_digits;
7670 int local_rscale;
7671
7672 init_var(&x);
7673 init_var(&elem);
7674 init_var(&ni);
7675
7676 set_var_from_var(arg, &x);
7677
7678 /*
7679 * Estimate the dweight of the result using floating point arithmetic, so
7680 * that we can choose an appropriate local rscale for the calculation.
7681 */
7682 val = numericvar_to_double_no_overflow(&x);
7683
7684 /* Guard against overflow/underflow */
7685 /* If you change this limit, see also power_var()'s limit */
7686 if (Abs(val) >= NUMERIC_MAX_RESULT_SCALE * 3)
7687 {
7688 if (val > 0)
7689 ereport(ERROR,
7690 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
7691 errmsg("value overflows numeric format")));
7692 zero_var(result);
7693 result->dscale = rscale;
7694 return;
7695 }
7696
7697 /* decimal weight = log10(e^x) = x * log10(e) */
7698 dweight = (int) (val * 0.434294481903252);
7699
7700 /*
7701 * Reduce x to the range -0.01 <= x <= 0.01 (approximately) by dividing by
7702 * 2^n, to improve the convergence rate of the Taylor series.
7703 */
7704 if (Abs(val) > 0.01)
7705 {
7706 NumericVar tmp;
7707
7708 init_var(&tmp);
7709 set_var_from_var(&const_two, &tmp);
7710
7711 ndiv2 = 1;
7712 val /= 2;
7713
7714 while (Abs(val) > 0.01)
7715 {
7716 ndiv2++;
7717 val /= 2;
7718 add_var(&tmp, &tmp, &tmp);
7719 }
7720
7721 local_rscale = x.dscale + ndiv2;
7722 div_var_fast(&x, &tmp, &x, local_rscale, true);
7723
7724 free_var(&tmp);
7725 }
7726 else
7727 ndiv2 = 0;
7728
7729 /*
7730 * Set the scale for the Taylor series expansion. The final result has
7731 * (dweight + rscale + 1) significant digits. In addition, we have to
7732 * raise the Taylor series result to the power 2^ndiv2, which introduces
7733 * an error of up to around log10(2^ndiv2) digits, so work with this many
7734 * extra digits of precision (plus a few more for good measure).
7735 */
7736 sig_digits = 1 + dweight + rscale + (int) (ndiv2 * 0.301029995663981);
7737 sig_digits = Max(sig_digits, 0) + 8;
7738
7739 local_rscale = sig_digits - 1;
7740
7741 /*
7742 * Use the Taylor series
7743 *
7744 * exp(x) = 1 + x + x^2/2! + x^3/3! + ...
7745 *
7746 * Given the limited range of x, this should converge reasonably quickly.
7747 * We run the series until the terms fall below the local_rscale limit.
7748 */
7749 add_var(&const_one, &x, result);
7750
7751 mul_var(&x, &x, &elem, local_rscale);
7752 set_var_from_var(&const_two, &ni);
7753 div_var_fast(&elem, &ni, &elem, local_rscale, true);
7754
7755 while (elem.ndigits != 0)
7756 {
7757 add_var(result, &elem, result);
7758
7759 mul_var(&elem, &x, &elem, local_rscale);
7760 add_var(&ni, &const_one, &ni);
7761 div_var_fast(&elem, &ni, &elem, local_rscale, true);
7762 }
7763
7764 /*
7765 * Compensate for the argument range reduction. Since the weight of the
7766 * result doubles with each multiplication, we can reduce the local rscale
7767 * as we proceed.
7768 */
7769 while (ndiv2-- > 0)
7770 {
7771 local_rscale = sig_digits - result->weight * 2 * DEC_DIGITS;
7772 local_rscale = Max(local_rscale, NUMERIC_MIN_DISPLAY_SCALE);
7773 mul_var(result, result, result, local_rscale);
7774 }
7775
7776 /* Round to requested rscale */
7777 round_var(result, rscale);
7778
7779 free_var(&x);
7780 free_var(&elem);
7781 free_var(&ni);
7782 }
7783
7784
7785 /*
7786 * Estimate the dweight of the most significant decimal digit of the natural
7787 * logarithm of a number.
7788 *
7789 * Essentially, we're approximating log10(abs(ln(var))). This is used to
7790 * determine the appropriate rscale when computing natural logarithms.
7791 */
7792 static int
estimate_ln_dweight(NumericVar * var)7793 estimate_ln_dweight(NumericVar *var)
7794 {
7795 int ln_dweight;
7796
7797 if (cmp_var(var, &const_zero_point_nine) >= 0 &&
7798 cmp_var(var, &const_one_point_one) <= 0)
7799 {
7800 /*
7801 * 0.9 <= var <= 1.1
7802 *
7803 * ln(var) has a negative weight (possibly very large). To get a
7804 * reasonably accurate result, estimate it using ln(1+x) ~= x.
7805 */
7806 NumericVar x;
7807
7808 init_var(&x);
7809 sub_var(var, &const_one, &x);
7810
7811 if (x.ndigits > 0)
7812 {
7813 /* Use weight of most significant decimal digit of x */
7814 ln_dweight = x.weight * DEC_DIGITS + (int) log10(x.digits[0]);
7815 }
7816 else
7817 {
7818 /* x = 0. Since ln(1) = 0 exactly, we don't need extra digits */
7819 ln_dweight = 0;
7820 }
7821
7822 free_var(&x);
7823 }
7824 else
7825 {
7826 /*
7827 * Estimate the logarithm using the first couple of digits from the
7828 * input number. This will give an accurate result whenever the input
7829 * is not too close to 1.
7830 */
7831 if (var->ndigits > 0)
7832 {
7833 int digits;
7834 int dweight;
7835 double ln_var;
7836
7837 digits = var->digits[0];
7838 dweight = var->weight * DEC_DIGITS;
7839
7840 if (var->ndigits > 1)
7841 {
7842 digits = digits * NBASE + var->digits[1];
7843 dweight -= DEC_DIGITS;
7844 }
7845
7846 /*----------
7847 * We have var ~= digits * 10^dweight
7848 * so ln(var) ~= ln(digits) + dweight * ln(10)
7849 *----------
7850 */
7851 ln_var = log((double) digits) + dweight * 2.302585092994046;
7852 ln_dweight = (int) log10(Abs(ln_var));
7853 }
7854 else
7855 {
7856 /* Caller should fail on ln(0), but for the moment return zero */
7857 ln_dweight = 0;
7858 }
7859 }
7860
7861 return ln_dweight;
7862 }
7863
7864
7865 /*
7866 * ln_var() -
7867 *
7868 * Compute the natural log of x
7869 */
7870 static void
ln_var(NumericVar * arg,NumericVar * result,int rscale)7871 ln_var(NumericVar *arg, NumericVar *result, int rscale)
7872 {
7873 NumericVar x;
7874 NumericVar xx;
7875 NumericVar ni;
7876 NumericVar elem;
7877 NumericVar fact;
7878 int local_rscale;
7879 int cmp;
7880
7881 cmp = cmp_var(arg, &const_zero);
7882 if (cmp == 0)
7883 ereport(ERROR,
7884 (errcode(ERRCODE_INVALID_ARGUMENT_FOR_LOG),
7885 errmsg("cannot take logarithm of zero")));
7886 else if (cmp < 0)
7887 ereport(ERROR,
7888 (errcode(ERRCODE_INVALID_ARGUMENT_FOR_LOG),
7889 errmsg("cannot take logarithm of a negative number")));
7890
7891 init_var(&x);
7892 init_var(&xx);
7893 init_var(&ni);
7894 init_var(&elem);
7895 init_var(&fact);
7896
7897 set_var_from_var(arg, &x);
7898 set_var_from_var(&const_two, &fact);
7899
7900 /*
7901 * Reduce input into range 0.9 < x < 1.1 with repeated sqrt() operations.
7902 *
7903 * The final logarithm will have up to around rscale+6 significant digits.
7904 * Each sqrt() will roughly halve the weight of x, so adjust the local
7905 * rscale as we work so that we keep this many significant digits at each
7906 * step (plus a few more for good measure).
7907 */
7908 while (cmp_var(&x, &const_zero_point_nine) <= 0)
7909 {
7910 local_rscale = rscale - x.weight * DEC_DIGITS / 2 + 8;
7911 local_rscale = Max(local_rscale, NUMERIC_MIN_DISPLAY_SCALE);
7912 sqrt_var(&x, &x, local_rscale);
7913 mul_var(&fact, &const_two, &fact, 0);
7914 }
7915 while (cmp_var(&x, &const_one_point_one) >= 0)
7916 {
7917 local_rscale = rscale - x.weight * DEC_DIGITS / 2 + 8;
7918 local_rscale = Max(local_rscale, NUMERIC_MIN_DISPLAY_SCALE);
7919 sqrt_var(&x, &x, local_rscale);
7920 mul_var(&fact, &const_two, &fact, 0);
7921 }
7922
7923 /*
7924 * We use the Taylor series for 0.5 * ln((1+z)/(1-z)),
7925 *
7926 * z + z^3/3 + z^5/5 + ...
7927 *
7928 * where z = (x-1)/(x+1) is in the range (approximately) -0.053 .. 0.048
7929 * due to the above range-reduction of x.
7930 *
7931 * The convergence of this is not as fast as one would like, but is
7932 * tolerable given that z is small.
7933 */
7934 local_rscale = rscale + 8;
7935
7936 sub_var(&x, &const_one, result);
7937 add_var(&x, &const_one, &elem);
7938 div_var_fast(result, &elem, result, local_rscale, true);
7939 set_var_from_var(result, &xx);
7940 mul_var(result, result, &x, local_rscale);
7941
7942 set_var_from_var(&const_one, &ni);
7943
7944 for (;;)
7945 {
7946 add_var(&ni, &const_two, &ni);
7947 mul_var(&xx, &x, &xx, local_rscale);
7948 div_var_fast(&xx, &ni, &elem, local_rscale, true);
7949
7950 if (elem.ndigits == 0)
7951 break;
7952
7953 add_var(result, &elem, result);
7954
7955 if (elem.weight < (result->weight - local_rscale * 2 / DEC_DIGITS))
7956 break;
7957 }
7958
7959 /* Compensate for argument range reduction, round to requested rscale */
7960 mul_var(result, &fact, result, rscale);
7961
7962 free_var(&x);
7963 free_var(&xx);
7964 free_var(&ni);
7965 free_var(&elem);
7966 free_var(&fact);
7967 }
7968
7969
7970 /*
7971 * log_var() -
7972 *
7973 * Compute the logarithm of num in a given base.
7974 *
7975 * Note: this routine chooses dscale of the result.
7976 */
7977 static void
log_var(NumericVar * base,NumericVar * num,NumericVar * result)7978 log_var(NumericVar *base, NumericVar *num, NumericVar *result)
7979 {
7980 NumericVar ln_base;
7981 NumericVar ln_num;
7982 int ln_base_dweight;
7983 int ln_num_dweight;
7984 int result_dweight;
7985 int rscale;
7986 int ln_base_rscale;
7987 int ln_num_rscale;
7988
7989 init_var(&ln_base);
7990 init_var(&ln_num);
7991
7992 /* Estimated dweights of ln(base), ln(num) and the final result */
7993 ln_base_dweight = estimate_ln_dweight(base);
7994 ln_num_dweight = estimate_ln_dweight(num);
7995 result_dweight = ln_num_dweight - ln_base_dweight;
7996
7997 /*
7998 * Select the scale of the result so that it will have at least
7999 * NUMERIC_MIN_SIG_DIGITS significant digits and is not less than either
8000 * input's display scale.
8001 */
8002 rscale = NUMERIC_MIN_SIG_DIGITS - result_dweight;
8003 rscale = Max(rscale, base->dscale);
8004 rscale = Max(rscale, num->dscale);
8005 rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
8006 rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
8007
8008 /*
8009 * Set the scales for ln(base) and ln(num) so that they each have more
8010 * significant digits than the final result.
8011 */
8012 ln_base_rscale = rscale + result_dweight - ln_base_dweight + 8;
8013 ln_base_rscale = Max(ln_base_rscale, NUMERIC_MIN_DISPLAY_SCALE);
8014
8015 ln_num_rscale = rscale + result_dweight - ln_num_dweight + 8;
8016 ln_num_rscale = Max(ln_num_rscale, NUMERIC_MIN_DISPLAY_SCALE);
8017
8018 /* Form natural logarithms */
8019 ln_var(base, &ln_base, ln_base_rscale);
8020 ln_var(num, &ln_num, ln_num_rscale);
8021
8022 /* Divide and round to the required scale */
8023 div_var_fast(&ln_num, &ln_base, result, rscale, true);
8024
8025 free_var(&ln_num);
8026 free_var(&ln_base);
8027 }
8028
8029
8030 /*
8031 * power_var() -
8032 *
8033 * Raise base to the power of exp
8034 *
8035 * Note: this routine chooses dscale of the result.
8036 */
8037 static void
power_var(NumericVar * base,NumericVar * exp,NumericVar * result)8038 power_var(NumericVar *base, NumericVar *exp, NumericVar *result)
8039 {
8040 int res_sign;
8041 NumericVar abs_base;
8042 NumericVar ln_base;
8043 NumericVar ln_num;
8044 int ln_dweight;
8045 int rscale;
8046 int sig_digits;
8047 int local_rscale;
8048 double val;
8049
8050 /* If exp can be represented as an integer, use power_var_int */
8051 if (exp->ndigits == 0 || exp->ndigits <= exp->weight + 1)
8052 {
8053 /* exact integer, but does it fit in int? */
8054 int64 expval64;
8055
8056 if (numericvar_to_int64(exp, &expval64))
8057 {
8058 if (expval64 >= PG_INT32_MIN && expval64 <= PG_INT32_MAX)
8059 {
8060 /* Okay, select rscale */
8061 rscale = NUMERIC_MIN_SIG_DIGITS;
8062 rscale = Max(rscale, base->dscale);
8063 rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
8064 rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
8065
8066 power_var_int(base, (int) expval64, result, rscale);
8067 return;
8068 }
8069 }
8070 }
8071
8072 /*
8073 * This avoids log(0) for cases of 0 raised to a non-integer. 0 ^ 0 is
8074 * handled by power_var_int().
8075 */
8076 if (cmp_var(base, &const_zero) == 0)
8077 {
8078 set_var_from_var(&const_zero, result);
8079 result->dscale = NUMERIC_MIN_SIG_DIGITS; /* no need to round */
8080 return;
8081 }
8082
8083 init_var(&abs_base);
8084 init_var(&ln_base);
8085 init_var(&ln_num);
8086
8087 /*
8088 * If base is negative, insist that exp be an integer. The result is then
8089 * positive if exp is even and negative if exp is odd.
8090 */
8091 if (base->sign == NUMERIC_NEG)
8092 {
8093 /*
8094 * Check that exp is an integer. This error code is defined by the
8095 * SQL standard, and matches other errors in numeric_power().
8096 */
8097 if (exp->ndigits > 0 && exp->ndigits > exp->weight + 1)
8098 ereport(ERROR,
8099 (errcode(ERRCODE_INVALID_ARGUMENT_FOR_POWER_FUNCTION),
8100 errmsg("a negative number raised to a non-integer power yields a complex result")));
8101
8102 /* Test if exp is odd or even */
8103 if (exp->ndigits > 0 && exp->ndigits == exp->weight + 1 &&
8104 (exp->digits[exp->ndigits - 1] & 1))
8105 res_sign = NUMERIC_NEG;
8106 else
8107 res_sign = NUMERIC_POS;
8108
8109 /* Then work with abs(base) below */
8110 set_var_from_var(base, &abs_base);
8111 abs_base.sign = NUMERIC_POS;
8112 base = &abs_base;
8113 }
8114 else
8115 res_sign = NUMERIC_POS;
8116
8117 /*----------
8118 * Decide on the scale for the ln() calculation. For this we need an
8119 * estimate of the weight of the result, which we obtain by doing an
8120 * initial low-precision calculation of exp * ln(base).
8121 *
8122 * We want result = e ^ (exp * ln(base))
8123 * so result dweight = log10(result) = exp * ln(base) * log10(e)
8124 *
8125 * We also perform a crude overflow test here so that we can exit early if
8126 * the full-precision result is sure to overflow, and to guard against
8127 * integer overflow when determining the scale for the real calculation.
8128 * exp_var() supports inputs up to NUMERIC_MAX_RESULT_SCALE * 3, so the
8129 * result will overflow if exp * ln(base) >= NUMERIC_MAX_RESULT_SCALE * 3.
8130 * Since the values here are only approximations, we apply a small fuzz
8131 * factor to this overflow test and let exp_var() determine the exact
8132 * overflow threshold so that it is consistent for all inputs.
8133 *----------
8134 */
8135 ln_dweight = estimate_ln_dweight(base);
8136
8137 /*
8138 * Set the scale for the low-precision calculation, computing ln(base) to
8139 * around 8 significant digits. Note that ln_dweight may be as small as
8140 * -SHRT_MAX, so the scale may exceed NUMERIC_MAX_DISPLAY_SCALE here.
8141 */
8142 local_rscale = 8 - ln_dweight;
8143 local_rscale = Max(local_rscale, NUMERIC_MIN_DISPLAY_SCALE);
8144
8145 ln_var(base, &ln_base, local_rscale);
8146
8147 mul_var(&ln_base, exp, &ln_num, local_rscale);
8148
8149 val = numericvar_to_double_no_overflow(&ln_num);
8150
8151 /* initial overflow/underflow test with fuzz factor */
8152 if (Abs(val) > NUMERIC_MAX_RESULT_SCALE * 3.01)
8153 {
8154 if (val > 0)
8155 ereport(ERROR,
8156 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
8157 errmsg("value overflows numeric format")));
8158 zero_var(result);
8159 result->dscale = NUMERIC_MAX_DISPLAY_SCALE;
8160 return;
8161 }
8162
8163 val *= 0.434294481903252; /* approximate decimal result weight */
8164
8165 /* choose the result scale */
8166 rscale = NUMERIC_MIN_SIG_DIGITS - (int) val;
8167 rscale = Max(rscale, base->dscale);
8168 rscale = Max(rscale, exp->dscale);
8169 rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
8170 rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
8171
8172 /* significant digits required in the result */
8173 sig_digits = rscale + (int) val;
8174 sig_digits = Max(sig_digits, 0);
8175
8176 /* set the scale for the real exp * ln(base) calculation */
8177 local_rscale = sig_digits - ln_dweight + 8;
8178 local_rscale = Max(local_rscale, NUMERIC_MIN_DISPLAY_SCALE);
8179
8180 /* and do the real calculation */
8181
8182 ln_var(base, &ln_base, local_rscale);
8183
8184 mul_var(&ln_base, exp, &ln_num, local_rscale);
8185
8186 exp_var(&ln_num, result, rscale);
8187
8188 if (res_sign == NUMERIC_NEG && result->ndigits > 0)
8189 result->sign = NUMERIC_NEG;
8190
8191 free_var(&ln_num);
8192 free_var(&ln_base);
8193 free_var(&abs_base);
8194 }
8195
8196 /*
8197 * power_var_int() -
8198 *
8199 * Raise base to the power of exp, where exp is an integer.
8200 */
8201 static void
power_var_int(NumericVar * base,int exp,NumericVar * result,int rscale)8202 power_var_int(NumericVar *base, int exp, NumericVar *result, int rscale)
8203 {
8204 double f;
8205 int p;
8206 int i;
8207 int sig_digits;
8208 unsigned int mask;
8209 bool neg;
8210 NumericVar base_prod;
8211 int local_rscale;
8212
8213 /* Handle some common special cases, as well as corner cases */
8214 switch (exp)
8215 {
8216 case 0:
8217
8218 /*
8219 * While 0 ^ 0 can be either 1 or indeterminate (error), we treat
8220 * it as 1 because most programming languages do this. SQL:2003
8221 * also requires a return value of 1.
8222 * http://en.wikipedia.org/wiki/Exponentiation#Zero_to_the_zero_power
8223 */
8224 set_var_from_var(&const_one, result);
8225 result->dscale = rscale; /* no need to round */
8226 return;
8227 case 1:
8228 set_var_from_var(base, result);
8229 round_var(result, rscale);
8230 return;
8231 case -1:
8232 div_var(&const_one, base, result, rscale, true);
8233 return;
8234 case 2:
8235 mul_var(base, base, result, rscale);
8236 return;
8237 default:
8238 break;
8239 }
8240
8241 /* Handle the special case where the base is zero */
8242 if (base->ndigits == 0)
8243 {
8244 if (exp < 0)
8245 ereport(ERROR,
8246 (errcode(ERRCODE_DIVISION_BY_ZERO),
8247 errmsg("division by zero")));
8248 zero_var(result);
8249 result->dscale = rscale;
8250 return;
8251 }
8252
8253 /*
8254 * The general case repeatedly multiplies base according to the bit
8255 * pattern of exp.
8256 *
8257 * First we need to estimate the weight of the result so that we know how
8258 * many significant digits are needed.
8259 */
8260 f = base->digits[0];
8261 p = base->weight * DEC_DIGITS;
8262
8263 for (i = 1; i < base->ndigits && i * DEC_DIGITS < 16; i++)
8264 {
8265 f = f * NBASE + base->digits[i];
8266 p -= DEC_DIGITS;
8267 }
8268
8269 /*----------
8270 * We have base ~= f * 10^p
8271 * so log10(result) = log10(base^exp) ~= exp * (log10(f) + p)
8272 *----------
8273 */
8274 f = exp * (log10(f) + p);
8275
8276 /*
8277 * Apply crude overflow/underflow tests so we can exit early if the result
8278 * certainly will overflow/underflow.
8279 */
8280 if (f > 3 * SHRT_MAX * DEC_DIGITS)
8281 ereport(ERROR,
8282 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
8283 errmsg("value overflows numeric format")));
8284 if (f + 1 < -rscale || f + 1 < -NUMERIC_MAX_DISPLAY_SCALE)
8285 {
8286 zero_var(result);
8287 result->dscale = rscale;
8288 return;
8289 }
8290
8291 /*
8292 * Approximate number of significant digits in the result. Note that the
8293 * underflow test above means that this is necessarily >= 0.
8294 */
8295 sig_digits = 1 + rscale + (int) f;
8296
8297 /*
8298 * The multiplications to produce the result may introduce an error of up
8299 * to around log10(abs(exp)) digits, so work with this many extra digits
8300 * of precision (plus a few more for good measure).
8301 */
8302 sig_digits += (int) log(fabs((double) exp)) + 8;
8303
8304 /*
8305 * Now we can proceed with the multiplications.
8306 */
8307 neg = (exp < 0);
8308 mask = Abs(exp);
8309
8310 init_var(&base_prod);
8311 set_var_from_var(base, &base_prod);
8312
8313 if (mask & 1)
8314 set_var_from_var(base, result);
8315 else
8316 set_var_from_var(&const_one, result);
8317
8318 while ((mask >>= 1) > 0)
8319 {
8320 /*
8321 * Do the multiplications using rscales large enough to hold the
8322 * results to the required number of significant digits, but don't
8323 * waste time by exceeding the scales of the numbers themselves.
8324 */
8325 local_rscale = sig_digits - 2 * base_prod.weight * DEC_DIGITS;
8326 local_rscale = Min(local_rscale, 2 * base_prod.dscale);
8327 local_rscale = Max(local_rscale, NUMERIC_MIN_DISPLAY_SCALE);
8328
8329 mul_var(&base_prod, &base_prod, &base_prod, local_rscale);
8330
8331 if (mask & 1)
8332 {
8333 local_rscale = sig_digits -
8334 (base_prod.weight + result->weight) * DEC_DIGITS;
8335 local_rscale = Min(local_rscale,
8336 base_prod.dscale + result->dscale);
8337 local_rscale = Max(local_rscale, NUMERIC_MIN_DISPLAY_SCALE);
8338
8339 mul_var(&base_prod, result, result, local_rscale);
8340 }
8341
8342 /*
8343 * When abs(base) > 1, the number of digits to the left of the decimal
8344 * point in base_prod doubles at each iteration, so if exp is large we
8345 * could easily spend large amounts of time and memory space doing the
8346 * multiplications. But once the weight exceeds what will fit in
8347 * int16, the final result is guaranteed to overflow (or underflow, if
8348 * exp < 0), so we can give up before wasting too many cycles.
8349 */
8350 if (base_prod.weight > SHRT_MAX || result->weight > SHRT_MAX)
8351 {
8352 /* overflow, unless neg, in which case result should be 0 */
8353 if (!neg)
8354 ereport(ERROR,
8355 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
8356 errmsg("value overflows numeric format")));
8357 zero_var(result);
8358 neg = false;
8359 break;
8360 }
8361 }
8362
8363 free_var(&base_prod);
8364
8365 /* Compensate for input sign, and round to requested rscale */
8366 if (neg)
8367 div_var_fast(&const_one, result, result, rscale, true);
8368 else
8369 round_var(result, rscale);
8370 }
8371
8372 /*
8373 * power_ten_int() -
8374 *
8375 * Raise ten to the power of exp, where exp is an integer. Note that unlike
8376 * power_var_int(), this does no overflow/underflow checking or rounding.
8377 */
8378 static void
power_ten_int(int exp,NumericVar * result)8379 power_ten_int(int exp, NumericVar *result)
8380 {
8381 /* Construct the result directly, starting from 10^0 = 1 */
8382 set_var_from_var(&const_one, result);
8383
8384 /* Scale needed to represent the result exactly */
8385 result->dscale = exp < 0 ? -exp : 0;
8386
8387 /* Base-NBASE weight of result and remaining exponent */
8388 if (exp >= 0)
8389 result->weight = exp / DEC_DIGITS;
8390 else
8391 result->weight = (exp + 1) / DEC_DIGITS - 1;
8392
8393 exp -= result->weight * DEC_DIGITS;
8394
8395 /* Final adjustment of the result's single NBASE digit */
8396 while (exp-- > 0)
8397 result->digits[0] *= 10;
8398 }
8399
8400
8401 /* ----------------------------------------------------------------------
8402 *
8403 * Following are the lowest level functions that operate unsigned
8404 * on the variable level
8405 *
8406 * ----------------------------------------------------------------------
8407 */
8408
8409
8410 /* ----------
8411 * cmp_abs() -
8412 *
8413 * Compare the absolute values of var1 and var2
8414 * Returns: -1 for ABS(var1) < ABS(var2)
8415 * 0 for ABS(var1) == ABS(var2)
8416 * 1 for ABS(var1) > ABS(var2)
8417 * ----------
8418 */
8419 static int
cmp_abs(NumericVar * var1,NumericVar * var2)8420 cmp_abs(NumericVar *var1, NumericVar *var2)
8421 {
8422 return cmp_abs_common(var1->digits, var1->ndigits, var1->weight,
8423 var2->digits, var2->ndigits, var2->weight);
8424 }
8425
8426 /* ----------
8427 * cmp_abs_common() -
8428 *
8429 * Main routine of cmp_abs(). This function can be used by both
8430 * NumericVar and Numeric.
8431 * ----------
8432 */
8433 static int
cmp_abs_common(const NumericDigit * var1digits,int var1ndigits,int var1weight,const NumericDigit * var2digits,int var2ndigits,int var2weight)8434 cmp_abs_common(const NumericDigit *var1digits, int var1ndigits, int var1weight,
8435 const NumericDigit *var2digits, int var2ndigits, int var2weight)
8436 {
8437 int i1 = 0;
8438 int i2 = 0;
8439
8440 /* Check any digits before the first common digit */
8441
8442 while (var1weight > var2weight && i1 < var1ndigits)
8443 {
8444 if (var1digits[i1++] != 0)
8445 return 1;
8446 var1weight--;
8447 }
8448 while (var2weight > var1weight && i2 < var2ndigits)
8449 {
8450 if (var2digits[i2++] != 0)
8451 return -1;
8452 var2weight--;
8453 }
8454
8455 /* At this point, either w1 == w2 or we've run out of digits */
8456
8457 if (var1weight == var2weight)
8458 {
8459 while (i1 < var1ndigits && i2 < var2ndigits)
8460 {
8461 int stat = var1digits[i1++] - var2digits[i2++];
8462
8463 if (stat)
8464 {
8465 if (stat > 0)
8466 return 1;
8467 return -1;
8468 }
8469 }
8470 }
8471
8472 /*
8473 * At this point, we've run out of digits on one side or the other; so any
8474 * remaining nonzero digits imply that side is larger
8475 */
8476 while (i1 < var1ndigits)
8477 {
8478 if (var1digits[i1++] != 0)
8479 return 1;
8480 }
8481 while (i2 < var2ndigits)
8482 {
8483 if (var2digits[i2++] != 0)
8484 return -1;
8485 }
8486
8487 return 0;
8488 }
8489
8490
8491 /*
8492 * add_abs() -
8493 *
8494 * Add the absolute values of two variables into result.
8495 * result might point to one of the operands without danger.
8496 */
8497 static void
add_abs(NumericVar * var1,NumericVar * var2,NumericVar * result)8498 add_abs(NumericVar *var1, NumericVar *var2, NumericVar *result)
8499 {
8500 NumericDigit *res_buf;
8501 NumericDigit *res_digits;
8502 int res_ndigits;
8503 int res_weight;
8504 int res_rscale,
8505 rscale1,
8506 rscale2;
8507 int res_dscale;
8508 int i,
8509 i1,
8510 i2;
8511 int carry = 0;
8512
8513 /* copy these values into local vars for speed in inner loop */
8514 int var1ndigits = var1->ndigits;
8515 int var2ndigits = var2->ndigits;
8516 NumericDigit *var1digits = var1->digits;
8517 NumericDigit *var2digits = var2->digits;
8518
8519 res_weight = Max(var1->weight, var2->weight) + 1;
8520
8521 res_dscale = Max(var1->dscale, var2->dscale);
8522
8523 /* Note: here we are figuring rscale in base-NBASE digits */
8524 rscale1 = var1->ndigits - var1->weight - 1;
8525 rscale2 = var2->ndigits - var2->weight - 1;
8526 res_rscale = Max(rscale1, rscale2);
8527
8528 res_ndigits = res_rscale + res_weight + 1;
8529 if (res_ndigits <= 0)
8530 res_ndigits = 1;
8531
8532 res_buf = digitbuf_alloc(res_ndigits + 1);
8533 res_buf[0] = 0; /* spare digit for later rounding */
8534 res_digits = res_buf + 1;
8535
8536 i1 = res_rscale + var1->weight + 1;
8537 i2 = res_rscale + var2->weight + 1;
8538 for (i = res_ndigits - 1; i >= 0; i--)
8539 {
8540 i1--;
8541 i2--;
8542 if (i1 >= 0 && i1 < var1ndigits)
8543 carry += var1digits[i1];
8544 if (i2 >= 0 && i2 < var2ndigits)
8545 carry += var2digits[i2];
8546
8547 if (carry >= NBASE)
8548 {
8549 res_digits[i] = carry - NBASE;
8550 carry = 1;
8551 }
8552 else
8553 {
8554 res_digits[i] = carry;
8555 carry = 0;
8556 }
8557 }
8558
8559 Assert(carry == 0); /* else we failed to allow for carry out */
8560
8561 digitbuf_free(result->buf);
8562 result->ndigits = res_ndigits;
8563 result->buf = res_buf;
8564 result->digits = res_digits;
8565 result->weight = res_weight;
8566 result->dscale = res_dscale;
8567
8568 /* Remove leading/trailing zeroes */
8569 strip_var(result);
8570 }
8571
8572
8573 /*
8574 * sub_abs()
8575 *
8576 * Subtract the absolute value of var2 from the absolute value of var1
8577 * and store in result. result might point to one of the operands
8578 * without danger.
8579 *
8580 * ABS(var1) MUST BE GREATER OR EQUAL ABS(var2) !!!
8581 */
8582 static void
sub_abs(NumericVar * var1,NumericVar * var2,NumericVar * result)8583 sub_abs(NumericVar *var1, NumericVar *var2, NumericVar *result)
8584 {
8585 NumericDigit *res_buf;
8586 NumericDigit *res_digits;
8587 int res_ndigits;
8588 int res_weight;
8589 int res_rscale,
8590 rscale1,
8591 rscale2;
8592 int res_dscale;
8593 int i,
8594 i1,
8595 i2;
8596 int borrow = 0;
8597
8598 /* copy these values into local vars for speed in inner loop */
8599 int var1ndigits = var1->ndigits;
8600 int var2ndigits = var2->ndigits;
8601 NumericDigit *var1digits = var1->digits;
8602 NumericDigit *var2digits = var2->digits;
8603
8604 res_weight = var1->weight;
8605
8606 res_dscale = Max(var1->dscale, var2->dscale);
8607
8608 /* Note: here we are figuring rscale in base-NBASE digits */
8609 rscale1 = var1->ndigits - var1->weight - 1;
8610 rscale2 = var2->ndigits - var2->weight - 1;
8611 res_rscale = Max(rscale1, rscale2);
8612
8613 res_ndigits = res_rscale + res_weight + 1;
8614 if (res_ndigits <= 0)
8615 res_ndigits = 1;
8616
8617 res_buf = digitbuf_alloc(res_ndigits + 1);
8618 res_buf[0] = 0; /* spare digit for later rounding */
8619 res_digits = res_buf + 1;
8620
8621 i1 = res_rscale + var1->weight + 1;
8622 i2 = res_rscale + var2->weight + 1;
8623 for (i = res_ndigits - 1; i >= 0; i--)
8624 {
8625 i1--;
8626 i2--;
8627 if (i1 >= 0 && i1 < var1ndigits)
8628 borrow += var1digits[i1];
8629 if (i2 >= 0 && i2 < var2ndigits)
8630 borrow -= var2digits[i2];
8631
8632 if (borrow < 0)
8633 {
8634 res_digits[i] = borrow + NBASE;
8635 borrow = -1;
8636 }
8637 else
8638 {
8639 res_digits[i] = borrow;
8640 borrow = 0;
8641 }
8642 }
8643
8644 Assert(borrow == 0); /* else caller gave us var1 < var2 */
8645
8646 digitbuf_free(result->buf);
8647 result->ndigits = res_ndigits;
8648 result->buf = res_buf;
8649 result->digits = res_digits;
8650 result->weight = res_weight;
8651 result->dscale = res_dscale;
8652
8653 /* Remove leading/trailing zeroes */
8654 strip_var(result);
8655 }
8656
8657 /*
8658 * round_var
8659 *
8660 * Round the value of a variable to no more than rscale decimal digits
8661 * after the decimal point. NOTE: we allow rscale < 0 here, implying
8662 * rounding before the decimal point.
8663 */
8664 static void
round_var(NumericVar * var,int rscale)8665 round_var(NumericVar *var, int rscale)
8666 {
8667 NumericDigit *digits = var->digits;
8668 int di;
8669 int ndigits;
8670 int carry;
8671
8672 var->dscale = rscale;
8673
8674 /* decimal digits wanted */
8675 di = (var->weight + 1) * DEC_DIGITS + rscale;
8676
8677 /*
8678 * If di = 0, the value loses all digits, but could round up to 1 if its
8679 * first extra digit is >= 5. If di < 0 the result must be 0.
8680 */
8681 if (di < 0)
8682 {
8683 var->ndigits = 0;
8684 var->weight = 0;
8685 var->sign = NUMERIC_POS;
8686 }
8687 else
8688 {
8689 /* NBASE digits wanted */
8690 ndigits = (di + DEC_DIGITS - 1) / DEC_DIGITS;
8691
8692 /* 0, or number of decimal digits to keep in last NBASE digit */
8693 di %= DEC_DIGITS;
8694
8695 if (ndigits < var->ndigits ||
8696 (ndigits == var->ndigits && di > 0))
8697 {
8698 var->ndigits = ndigits;
8699
8700 #if DEC_DIGITS == 1
8701 /* di must be zero */
8702 carry = (digits[ndigits] >= HALF_NBASE) ? 1 : 0;
8703 #else
8704 if (di == 0)
8705 carry = (digits[ndigits] >= HALF_NBASE) ? 1 : 0;
8706 else
8707 {
8708 /* Must round within last NBASE digit */
8709 int extra,
8710 pow10;
8711
8712 #if DEC_DIGITS == 4
8713 pow10 = round_powers[di];
8714 #elif DEC_DIGITS == 2
8715 pow10 = 10;
8716 #else
8717 #error unsupported NBASE
8718 #endif
8719 extra = digits[--ndigits] % pow10;
8720 digits[ndigits] -= extra;
8721 carry = 0;
8722 if (extra >= pow10 / 2)
8723 {
8724 pow10 += digits[ndigits];
8725 if (pow10 >= NBASE)
8726 {
8727 pow10 -= NBASE;
8728 carry = 1;
8729 }
8730 digits[ndigits] = pow10;
8731 }
8732 }
8733 #endif
8734
8735 /* Propagate carry if needed */
8736 while (carry)
8737 {
8738 carry += digits[--ndigits];
8739 if (carry >= NBASE)
8740 {
8741 digits[ndigits] = carry - NBASE;
8742 carry = 1;
8743 }
8744 else
8745 {
8746 digits[ndigits] = carry;
8747 carry = 0;
8748 }
8749 }
8750
8751 if (ndigits < 0)
8752 {
8753 Assert(ndigits == -1); /* better not have added > 1 digit */
8754 Assert(var->digits > var->buf);
8755 var->digits--;
8756 var->ndigits++;
8757 var->weight++;
8758 }
8759 }
8760 }
8761 }
8762
8763 /*
8764 * trunc_var
8765 *
8766 * Truncate (towards zero) the value of a variable at rscale decimal digits
8767 * after the decimal point. NOTE: we allow rscale < 0 here, implying
8768 * truncation before the decimal point.
8769 */
8770 static void
trunc_var(NumericVar * var,int rscale)8771 trunc_var(NumericVar *var, int rscale)
8772 {
8773 int di;
8774 int ndigits;
8775
8776 var->dscale = rscale;
8777
8778 /* decimal digits wanted */
8779 di = (var->weight + 1) * DEC_DIGITS + rscale;
8780
8781 /*
8782 * If di <= 0, the value loses all digits.
8783 */
8784 if (di <= 0)
8785 {
8786 var->ndigits = 0;
8787 var->weight = 0;
8788 var->sign = NUMERIC_POS;
8789 }
8790 else
8791 {
8792 /* NBASE digits wanted */
8793 ndigits = (di + DEC_DIGITS - 1) / DEC_DIGITS;
8794
8795 if (ndigits <= var->ndigits)
8796 {
8797 var->ndigits = ndigits;
8798
8799 #if DEC_DIGITS == 1
8800 /* no within-digit stuff to worry about */
8801 #else
8802 /* 0, or number of decimal digits to keep in last NBASE digit */
8803 di %= DEC_DIGITS;
8804
8805 if (di > 0)
8806 {
8807 /* Must truncate within last NBASE digit */
8808 NumericDigit *digits = var->digits;
8809 int extra,
8810 pow10;
8811
8812 #if DEC_DIGITS == 4
8813 pow10 = round_powers[di];
8814 #elif DEC_DIGITS == 2
8815 pow10 = 10;
8816 #else
8817 #error unsupported NBASE
8818 #endif
8819 extra = digits[--ndigits] % pow10;
8820 digits[ndigits] -= extra;
8821 }
8822 #endif
8823 }
8824 }
8825 }
8826
8827 /*
8828 * strip_var
8829 *
8830 * Strip any leading and trailing zeroes from a numeric variable
8831 */
8832 static void
strip_var(NumericVar * var)8833 strip_var(NumericVar *var)
8834 {
8835 NumericDigit *digits = var->digits;
8836 int ndigits = var->ndigits;
8837
8838 /* Strip leading zeroes */
8839 while (ndigits > 0 && *digits == 0)
8840 {
8841 digits++;
8842 var->weight--;
8843 ndigits--;
8844 }
8845
8846 /* Strip trailing zeroes */
8847 while (ndigits > 0 && digits[ndigits - 1] == 0)
8848 ndigits--;
8849
8850 /* If it's zero, normalize the sign and weight */
8851 if (ndigits == 0)
8852 {
8853 var->sign = NUMERIC_POS;
8854 var->weight = 0;
8855 }
8856
8857 var->digits = digits;
8858 var->ndigits = ndigits;
8859 }
8860
8861
8862 /* ----------------------------------------------------------------------
8863 *
8864 * Fast sum accumulator functions
8865 *
8866 * ----------------------------------------------------------------------
8867 */
8868
8869 /*
8870 * Reset the accumulator's value to zero. The buffers to hold the digits
8871 * are not free'd.
8872 */
8873 static void
accum_sum_reset(NumericSumAccum * accum)8874 accum_sum_reset(NumericSumAccum *accum)
8875 {
8876 int i;
8877
8878 accum->dscale = 0;
8879 for (i = 0; i < accum->ndigits; i++)
8880 {
8881 accum->pos_digits[i] = 0;
8882 accum->neg_digits[i] = 0;
8883 }
8884 }
8885
8886 /*
8887 * Accumulate a new value.
8888 */
8889 static void
accum_sum_add(NumericSumAccum * accum,NumericVar * val)8890 accum_sum_add(NumericSumAccum *accum, NumericVar *val)
8891 {
8892 int32 *accum_digits;
8893 int i,
8894 val_i;
8895 int val_ndigits;
8896 NumericDigit *val_digits;
8897
8898 /*
8899 * If we have accumulated too many values since the last carry
8900 * propagation, do it now, to avoid overflowing. (We could allow more
8901 * than NBASE - 1, if we reserved two extra digits, rather than one, for
8902 * carry propagation. But even with NBASE - 1, this needs to be done so
8903 * seldom, that the performance difference is negligible.)
8904 */
8905 if (accum->num_uncarried == NBASE - 1)
8906 accum_sum_carry(accum);
8907
8908 /*
8909 * Adjust the weight or scale of the old value, so that it can accommodate
8910 * the new value.
8911 */
8912 accum_sum_rescale(accum, val);
8913
8914 /* */
8915 if (val->sign == NUMERIC_POS)
8916 accum_digits = accum->pos_digits;
8917 else
8918 accum_digits = accum->neg_digits;
8919
8920 /* copy these values into local vars for speed in loop */
8921 val_ndigits = val->ndigits;
8922 val_digits = val->digits;
8923
8924 i = accum->weight - val->weight;
8925 for (val_i = 0; val_i < val_ndigits; val_i++)
8926 {
8927 accum_digits[i] += (int32) val_digits[val_i];
8928 i++;
8929 }
8930
8931 accum->num_uncarried++;
8932 }
8933
8934 /*
8935 * Propagate carries.
8936 */
8937 static void
accum_sum_carry(NumericSumAccum * accum)8938 accum_sum_carry(NumericSumAccum *accum)
8939 {
8940 int i;
8941 int ndigits;
8942 int32 *dig;
8943 int32 carry;
8944 int32 newdig = 0;
8945
8946 /*
8947 * If no new values have been added since last carry propagation, nothing
8948 * to do.
8949 */
8950 if (accum->num_uncarried == 0)
8951 return;
8952
8953 /*
8954 * We maintain that the weight of the accumulator is always one larger
8955 * than needed to hold the current value, before carrying, to make sure
8956 * there is enough space for the possible extra digit when carry is
8957 * propagated. We cannot expand the buffer here, unless we require
8958 * callers of accum_sum_final() to switch to the right memory context.
8959 */
8960 Assert(accum->pos_digits[0] == 0 && accum->neg_digits[0] == 0);
8961
8962 ndigits = accum->ndigits;
8963
8964 /* Propagate carry in the positive sum */
8965 dig = accum->pos_digits;
8966 carry = 0;
8967 for (i = ndigits - 1; i >= 0; i--)
8968 {
8969 newdig = dig[i] + carry;
8970 if (newdig >= NBASE)
8971 {
8972 carry = newdig / NBASE;
8973 newdig -= carry * NBASE;
8974 }
8975 else
8976 carry = 0;
8977 dig[i] = newdig;
8978 }
8979 /* Did we use up the digit reserved for carry propagation? */
8980 if (newdig > 0)
8981 accum->have_carry_space = false;
8982
8983 /* And the same for the negative sum */
8984 dig = accum->neg_digits;
8985 carry = 0;
8986 for (i = ndigits - 1; i >= 0; i--)
8987 {
8988 newdig = dig[i] + carry;
8989 if (newdig >= NBASE)
8990 {
8991 carry = newdig / NBASE;
8992 newdig -= carry * NBASE;
8993 }
8994 else
8995 carry = 0;
8996 dig[i] = newdig;
8997 }
8998 if (newdig > 0)
8999 accum->have_carry_space = false;
9000
9001 accum->num_uncarried = 0;
9002 }
9003
9004 /*
9005 * Re-scale accumulator to accommodate new value.
9006 *
9007 * If the new value has more digits than the current digit buffers in the
9008 * accumulator, enlarge the buffers.
9009 */
9010 static void
accum_sum_rescale(NumericSumAccum * accum,NumericVar * val)9011 accum_sum_rescale(NumericSumAccum *accum, NumericVar *val)
9012 {
9013 int old_weight = accum->weight;
9014 int old_ndigits = accum->ndigits;
9015 int accum_ndigits;
9016 int accum_weight;
9017 int accum_rscale;
9018 int val_rscale;
9019
9020 accum_weight = old_weight;
9021 accum_ndigits = old_ndigits;
9022
9023 /*
9024 * Does the new value have a larger weight? If so, enlarge the buffers,
9025 * and shift the existing value to the new weight, by adding leading
9026 * zeros.
9027 *
9028 * We enforce that the accumulator always has a weight one larger than
9029 * needed for the inputs, so that we have space for an extra digit at the
9030 * final carry-propagation phase, if necessary.
9031 */
9032 if (val->weight >= accum_weight)
9033 {
9034 accum_weight = val->weight + 1;
9035 accum_ndigits = accum_ndigits + (accum_weight - old_weight);
9036 }
9037
9038 /*
9039 * Even though the new value is small, we might've used up the space
9040 * reserved for the carry digit in the last call to accum_sum_carry(). If
9041 * so, enlarge to make room for another one.
9042 */
9043 else if (!accum->have_carry_space)
9044 {
9045 accum_weight++;
9046 accum_ndigits++;
9047 }
9048
9049 /* Is the new value wider on the right side? */
9050 accum_rscale = accum_ndigits - accum_weight - 1;
9051 val_rscale = val->ndigits - val->weight - 1;
9052 if (val_rscale > accum_rscale)
9053 accum_ndigits = accum_ndigits + (val_rscale - accum_rscale);
9054
9055 if (accum_ndigits != old_ndigits ||
9056 accum_weight != old_weight)
9057 {
9058 int32 *new_pos_digits;
9059 int32 *new_neg_digits;
9060 int weightdiff;
9061
9062 weightdiff = accum_weight - old_weight;
9063
9064 new_pos_digits = palloc0(accum_ndigits * sizeof(int32));
9065 new_neg_digits = palloc0(accum_ndigits * sizeof(int32));
9066
9067 if (accum->pos_digits)
9068 {
9069 memcpy(&new_pos_digits[weightdiff], accum->pos_digits,
9070 old_ndigits * sizeof(int32));
9071 pfree(accum->pos_digits);
9072
9073 memcpy(&new_neg_digits[weightdiff], accum->neg_digits,
9074 old_ndigits * sizeof(int32));
9075 pfree(accum->neg_digits);
9076 }
9077
9078 accum->pos_digits = new_pos_digits;
9079 accum->neg_digits = new_neg_digits;
9080
9081 accum->weight = accum_weight;
9082 accum->ndigits = accum_ndigits;
9083
9084 Assert(accum->pos_digits[0] == 0 && accum->neg_digits[0] == 0);
9085 accum->have_carry_space = true;
9086 }
9087
9088 if (val->dscale > accum->dscale)
9089 accum->dscale = val->dscale;
9090 }
9091
9092 /*
9093 * Return the current value of the accumulator. This perform final carry
9094 * propagation, and adds together the positive and negative sums.
9095 *
9096 * Unlike all the other routines, the caller is not required to switch to
9097 * the memory context that holds the accumulator.
9098 */
9099 static void
accum_sum_final(NumericSumAccum * accum,NumericVar * result)9100 accum_sum_final(NumericSumAccum *accum, NumericVar *result)
9101 {
9102 int i;
9103 NumericVar pos_var;
9104 NumericVar neg_var;
9105
9106 if (accum->ndigits == 0)
9107 {
9108 set_var_from_var(&const_zero, result);
9109 return;
9110 }
9111
9112 /* Perform final carry */
9113 accum_sum_carry(accum);
9114
9115 /* Create NumericVars representing the positive and negative sums */
9116 init_var(&pos_var);
9117 init_var(&neg_var);
9118
9119 pos_var.ndigits = neg_var.ndigits = accum->ndigits;
9120 pos_var.weight = neg_var.weight = accum->weight;
9121 pos_var.dscale = neg_var.dscale = accum->dscale;
9122 pos_var.sign = NUMERIC_POS;
9123 neg_var.sign = NUMERIC_NEG;
9124
9125 pos_var.buf = pos_var.digits = digitbuf_alloc(accum->ndigits);
9126 neg_var.buf = neg_var.digits = digitbuf_alloc(accum->ndigits);
9127
9128 for (i = 0; i < accum->ndigits; i++)
9129 {
9130 Assert(accum->pos_digits[i] < NBASE);
9131 pos_var.digits[i] = (int16) accum->pos_digits[i];
9132
9133 Assert(accum->neg_digits[i] < NBASE);
9134 neg_var.digits[i] = (int16) accum->neg_digits[i];
9135 }
9136
9137 /* And add them together */
9138 add_var(&pos_var, &neg_var, result);
9139
9140 /* Remove leading/trailing zeroes */
9141 strip_var(result);
9142 }
9143
9144 /*
9145 * Copy an accumulator's state.
9146 *
9147 * 'dst' is assumed to be uninitialized beforehand. No attempt is made at
9148 * freeing old values.
9149 */
9150 static void
accum_sum_copy(NumericSumAccum * dst,NumericSumAccum * src)9151 accum_sum_copy(NumericSumAccum *dst, NumericSumAccum *src)
9152 {
9153 dst->pos_digits = palloc(src->ndigits * sizeof(int32));
9154 dst->neg_digits = palloc(src->ndigits * sizeof(int32));
9155
9156 memcpy(dst->pos_digits, src->pos_digits, src->ndigits * sizeof(int32));
9157 memcpy(dst->neg_digits, src->neg_digits, src->ndigits * sizeof(int32));
9158 dst->num_uncarried = src->num_uncarried;
9159 dst->ndigits = src->ndigits;
9160 dst->weight = src->weight;
9161 dst->dscale = src->dscale;
9162 }
9163
9164 /*
9165 * Add the current value of 'accum2' into 'accum'.
9166 */
9167 static void
accum_sum_combine(NumericSumAccum * accum,NumericSumAccum * accum2)9168 accum_sum_combine(NumericSumAccum *accum, NumericSumAccum *accum2)
9169 {
9170 NumericVar tmp_var;
9171
9172 init_var(&tmp_var);
9173
9174 accum_sum_final(accum2, &tmp_var);
9175 accum_sum_add(accum, &tmp_var);
9176
9177 free_var(&tmp_var);
9178 }
9179