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