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