Line data Source code
1 : /*-------------------------------------------------------------------------
2 : *
3 : * numeric.c
4 : * An exact numeric data type for the Postgres database system
5 : *
6 : * Original coding 1998, Jan Wieck. Heavily revised 2003, Tom Lane.
7 : *
8 : * Many of the algorithmic ideas are borrowed from David M. Smith's "FM"
9 : * multiple-precision math library, most recently published as Algorithm
10 : * 786: Multiple-Precision Complex Arithmetic and Functions, ACM
11 : * Transactions on Mathematical Software, Vol. 24, No. 4, December 1998,
12 : * pages 359-367.
13 : *
14 : * Copyright (c) 1998-2025, 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 "common/hashfn.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 "optimizer/optimizer.h"
38 : #include "utils/array.h"
39 : #include "utils/builtins.h"
40 : #include "utils/float.h"
41 : #include "utils/guc.h"
42 : #include "utils/numeric.h"
43 : #include "utils/pg_lsn.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 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 : #define NBASE_SQR (NBASE * NBASE)
106 :
107 : /*
108 : * The Numeric type as stored on disk.
109 : *
110 : * If the high bits of the first word of a NumericChoice (n_header, or
111 : * n_short.n_header, or n_long.n_sign_dscale) are NUMERIC_SHORT, then the
112 : * numeric follows the NumericShort format; if they are NUMERIC_POS or
113 : * NUMERIC_NEG, it follows the NumericLong format. If they are NUMERIC_SPECIAL,
114 : * the value is a NaN or Infinity. We currently always store SPECIAL values
115 : * using just two bytes (i.e. only n_header), but previous releases used only
116 : * the NumericLong format, so we might find 4-byte NaNs (though not infinities)
117 : * on disk if a database has been migrated using pg_upgrade. In either case,
118 : * the low-order bits of a special value's header are reserved and currently
119 : * should always be set to zero.
120 : *
121 : * In the NumericShort format, the remaining 14 bits of the header word
122 : * (n_short.n_header) are allocated as follows: 1 for sign (positive or
123 : * negative), 6 for dynamic scale, and 7 for weight. In practice, most
124 : * commonly-encountered values can be represented this way.
125 : *
126 : * In the NumericLong format, the remaining 14 bits of the header word
127 : * (n_long.n_sign_dscale) represent the display scale; and the weight is
128 : * stored separately in n_weight.
129 : *
130 : * NOTE: by convention, values in the packed form have been stripped of
131 : * all leading and trailing zero digits (where a "digit" is of base NBASE).
132 : * In particular, if the value is zero, there will be no digits at all!
133 : * The weight is arbitrary in that case, but we normally set it to zero.
134 : */
135 :
136 : struct NumericShort
137 : {
138 : uint16 n_header; /* Sign + display scale + weight */
139 : NumericDigit n_data[FLEXIBLE_ARRAY_MEMBER]; /* Digits */
140 : };
141 :
142 : struct NumericLong
143 : {
144 : uint16 n_sign_dscale; /* Sign + display scale */
145 : int16 n_weight; /* Weight of 1st digit */
146 : NumericDigit n_data[FLEXIBLE_ARRAY_MEMBER]; /* Digits */
147 : };
148 :
149 : union NumericChoice
150 : {
151 : uint16 n_header; /* Header word */
152 : struct NumericLong n_long; /* Long form (4-byte header) */
153 : struct NumericShort n_short; /* Short form (2-byte header) */
154 : };
155 :
156 : struct NumericData
157 : {
158 : int32 vl_len_; /* varlena header (do not touch directly!) */
159 : union NumericChoice choice; /* choice of format */
160 : };
161 :
162 :
163 : /*
164 : * Interpretation of high bits.
165 : */
166 :
167 : #define NUMERIC_SIGN_MASK 0xC000
168 : #define NUMERIC_POS 0x0000
169 : #define NUMERIC_NEG 0x4000
170 : #define NUMERIC_SHORT 0x8000
171 : #define NUMERIC_SPECIAL 0xC000
172 :
173 : #define NUMERIC_FLAGBITS(n) ((n)->choice.n_header & NUMERIC_SIGN_MASK)
174 : #define NUMERIC_IS_SHORT(n) (NUMERIC_FLAGBITS(n) == NUMERIC_SHORT)
175 : #define NUMERIC_IS_SPECIAL(n) (NUMERIC_FLAGBITS(n) == NUMERIC_SPECIAL)
176 :
177 : #define NUMERIC_HDRSZ (VARHDRSZ + sizeof(uint16) + sizeof(int16))
178 : #define NUMERIC_HDRSZ_SHORT (VARHDRSZ + sizeof(uint16))
179 :
180 : /*
181 : * If the flag bits are NUMERIC_SHORT or NUMERIC_SPECIAL, we want the short
182 : * header; otherwise, we want the long one. Instead of testing against each
183 : * value, we can just look at the high bit, for a slight efficiency gain.
184 : */
185 : #define NUMERIC_HEADER_IS_SHORT(n) (((n)->choice.n_header & 0x8000) != 0)
186 : #define NUMERIC_HEADER_SIZE(n) \
187 : (VARHDRSZ + sizeof(uint16) + \
188 : (NUMERIC_HEADER_IS_SHORT(n) ? 0 : sizeof(int16)))
189 :
190 : /*
191 : * Definitions for special values (NaN, positive infinity, negative infinity).
192 : *
193 : * The two bits after the NUMERIC_SPECIAL bits are 00 for NaN, 01 for positive
194 : * infinity, 11 for negative infinity. (This makes the sign bit match where
195 : * it is in a short-format value, though we make no use of that at present.)
196 : * We could mask off the remaining bits before testing the active bits, but
197 : * currently those bits must be zeroes, so masking would just add cycles.
198 : */
199 : #define NUMERIC_EXT_SIGN_MASK 0xF000 /* high bits plus NaN/Inf flag bits */
200 : #define NUMERIC_NAN 0xC000
201 : #define NUMERIC_PINF 0xD000
202 : #define NUMERIC_NINF 0xF000
203 : #define NUMERIC_INF_SIGN_MASK 0x2000
204 :
205 : #define NUMERIC_EXT_FLAGBITS(n) ((n)->choice.n_header & NUMERIC_EXT_SIGN_MASK)
206 : #define NUMERIC_IS_NAN(n) ((n)->choice.n_header == NUMERIC_NAN)
207 : #define NUMERIC_IS_PINF(n) ((n)->choice.n_header == NUMERIC_PINF)
208 : #define NUMERIC_IS_NINF(n) ((n)->choice.n_header == NUMERIC_NINF)
209 : #define NUMERIC_IS_INF(n) \
210 : (((n)->choice.n_header & ~NUMERIC_INF_SIGN_MASK) == NUMERIC_PINF)
211 :
212 : /*
213 : * Short format definitions.
214 : */
215 :
216 : #define NUMERIC_SHORT_SIGN_MASK 0x2000
217 : #define NUMERIC_SHORT_DSCALE_MASK 0x1F80
218 : #define NUMERIC_SHORT_DSCALE_SHIFT 7
219 : #define NUMERIC_SHORT_DSCALE_MAX \
220 : (NUMERIC_SHORT_DSCALE_MASK >> NUMERIC_SHORT_DSCALE_SHIFT)
221 : #define NUMERIC_SHORT_WEIGHT_SIGN_MASK 0x0040
222 : #define NUMERIC_SHORT_WEIGHT_MASK 0x003F
223 : #define NUMERIC_SHORT_WEIGHT_MAX NUMERIC_SHORT_WEIGHT_MASK
224 : #define NUMERIC_SHORT_WEIGHT_MIN (-(NUMERIC_SHORT_WEIGHT_MASK+1))
225 :
226 : /*
227 : * Extract sign, display scale, weight. These macros extract field values
228 : * suitable for the NumericVar format from the Numeric (on-disk) format.
229 : *
230 : * Note that we don't trouble to ensure that dscale and weight read as zero
231 : * for an infinity; however, that doesn't matter since we never convert
232 : * "special" numerics to NumericVar form. Only the constants defined below
233 : * (const_nan, etc) ever represent a non-finite value as a NumericVar.
234 : */
235 :
236 : #define NUMERIC_DSCALE_MASK 0x3FFF
237 : #define NUMERIC_DSCALE_MAX NUMERIC_DSCALE_MASK
238 :
239 : #define NUMERIC_SIGN(n) \
240 : (NUMERIC_IS_SHORT(n) ? \
241 : (((n)->choice.n_short.n_header & NUMERIC_SHORT_SIGN_MASK) ? \
242 : NUMERIC_NEG : NUMERIC_POS) : \
243 : (NUMERIC_IS_SPECIAL(n) ? \
244 : NUMERIC_EXT_FLAGBITS(n) : NUMERIC_FLAGBITS(n)))
245 : #define NUMERIC_DSCALE(n) (NUMERIC_HEADER_IS_SHORT((n)) ? \
246 : ((n)->choice.n_short.n_header & NUMERIC_SHORT_DSCALE_MASK) \
247 : >> NUMERIC_SHORT_DSCALE_SHIFT \
248 : : ((n)->choice.n_long.n_sign_dscale & NUMERIC_DSCALE_MASK))
249 : #define NUMERIC_WEIGHT(n) (NUMERIC_HEADER_IS_SHORT((n)) ? \
250 : (((n)->choice.n_short.n_header & NUMERIC_SHORT_WEIGHT_SIGN_MASK ? \
251 : ~NUMERIC_SHORT_WEIGHT_MASK : 0) \
252 : | ((n)->choice.n_short.n_header & NUMERIC_SHORT_WEIGHT_MASK)) \
253 : : ((n)->choice.n_long.n_weight))
254 :
255 : /*
256 : * Maximum weight of a stored Numeric value (based on the use of int16 for the
257 : * weight in NumericLong). Note that intermediate values held in NumericVar
258 : * and NumericSumAccum variables may have much larger weights.
259 : */
260 : #define NUMERIC_WEIGHT_MAX PG_INT16_MAX
261 :
262 : /* ----------
263 : * NumericVar is the format we use for arithmetic. The digit-array part
264 : * is the same as the NumericData storage format, but the header is more
265 : * complex.
266 : *
267 : * The value represented by a NumericVar is determined by the sign, weight,
268 : * ndigits, and digits[] array. If it is a "special" value (NaN or Inf)
269 : * then only the sign field matters; ndigits should be zero, and the weight
270 : * and dscale fields are ignored.
271 : *
272 : * Note: the first digit of a NumericVar's value is assumed to be multiplied
273 : * by NBASE ** weight. Another way to say it is that there are weight+1
274 : * digits before the decimal point. It is possible to have weight < 0.
275 : *
276 : * buf points at the physical start of the palloc'd digit buffer for the
277 : * NumericVar. digits points at the first digit in actual use (the one
278 : * with the specified weight). We normally leave an unused digit or two
279 : * (preset to zeroes) between buf and digits, so that there is room to store
280 : * a carry out of the top digit without reallocating space. We just need to
281 : * decrement digits (and increment weight) to make room for the carry digit.
282 : * (There is no such extra space in a numeric value stored in the database,
283 : * only in a NumericVar in memory.)
284 : *
285 : * If buf is NULL then the digit buffer isn't actually palloc'd and should
286 : * not be freed --- see the constants below for an example.
287 : *
288 : * dscale, or display scale, is the nominal precision expressed as number
289 : * of digits after the decimal point (it must always be >= 0 at present).
290 : * dscale may be more than the number of physically stored fractional digits,
291 : * implying that we have suppressed storage of significant trailing zeroes.
292 : * It should never be less than the number of stored digits, since that would
293 : * imply hiding digits that are present. NOTE that dscale is always expressed
294 : * in *decimal* digits, and so it may correspond to a fractional number of
295 : * base-NBASE digits --- divide by DEC_DIGITS to convert to NBASE digits.
296 : *
297 : * rscale, or result scale, is the target precision for a computation.
298 : * Like dscale it is expressed as number of *decimal* digits after the decimal
299 : * point, and is always >= 0 at present.
300 : * Note that rscale is not stored in variables --- it's figured on-the-fly
301 : * from the dscales of the inputs.
302 : *
303 : * While we consistently use "weight" to refer to the base-NBASE weight of
304 : * a numeric value, it is convenient in some scale-related calculations to
305 : * make use of the base-10 weight (ie, the approximate log10 of the value).
306 : * To avoid confusion, such a decimal-units weight is called a "dweight".
307 : *
308 : * NB: All the variable-level functions are written in a style that makes it
309 : * possible to give one and the same variable as argument and destination.
310 : * This is feasible because the digit buffer is separate from the variable.
311 : * ----------
312 : */
313 : typedef struct NumericVar
314 : {
315 : int ndigits; /* # of digits in digits[] - can be 0! */
316 : int weight; /* weight of first digit */
317 : int sign; /* NUMERIC_POS, _NEG, _NAN, _PINF, or _NINF */
318 : int dscale; /* display scale */
319 : NumericDigit *buf; /* start of palloc'd space for digits[] */
320 : NumericDigit *digits; /* base-NBASE digits */
321 : } NumericVar;
322 :
323 :
324 : /* ----------
325 : * Data for generate_series
326 : * ----------
327 : */
328 : typedef struct
329 : {
330 : NumericVar current;
331 : NumericVar stop;
332 : NumericVar step;
333 : } generate_series_numeric_fctx;
334 :
335 :
336 : /* ----------
337 : * Sort support.
338 : * ----------
339 : */
340 : typedef struct
341 : {
342 : void *buf; /* buffer for short varlenas */
343 : int64 input_count; /* number of non-null values seen */
344 : bool estimating; /* true if estimating cardinality */
345 :
346 : hyperLogLogState abbr_card; /* cardinality estimator */
347 : } NumericSortSupport;
348 :
349 :
350 : /* ----------
351 : * Fast sum accumulator.
352 : *
353 : * NumericSumAccum is used to implement SUM(), and other standard aggregates
354 : * that track the sum of input values. It uses 32-bit integers to store the
355 : * digits, instead of the normal 16-bit integers (with NBASE=10000). This
356 : * way, we can safely accumulate up to NBASE - 1 values without propagating
357 : * carry, before risking overflow of any of the digits. 'num_uncarried'
358 : * tracks how many values have been accumulated without propagating carry.
359 : *
360 : * Positive and negative values are accumulated separately, in 'pos_digits'
361 : * and 'neg_digits'. This is simpler and faster than deciding whether to add
362 : * or subtract from the current value, for each new value (see sub_var() for
363 : * the logic we avoid by doing this). Both buffers are of same size, and
364 : * have the same weight and scale. In accum_sum_final(), the positive and
365 : * negative sums are added together to produce the final result.
366 : *
367 : * When a new value has a larger ndigits or weight than the accumulator
368 : * currently does, the accumulator is enlarged to accommodate the new value.
369 : * We normally have one zero digit reserved for carry propagation, and that
370 : * is indicated by the 'have_carry_space' flag. When accum_sum_carry() uses
371 : * up the reserved digit, it clears the 'have_carry_space' flag. The next
372 : * call to accum_sum_add() will enlarge the buffer, to make room for the
373 : * extra digit, and set the flag again.
374 : *
375 : * To initialize a new accumulator, simply reset all fields to zeros.
376 : *
377 : * The accumulator does not handle NaNs.
378 : * ----------
379 : */
380 : typedef struct NumericSumAccum
381 : {
382 : int ndigits;
383 : int weight;
384 : int dscale;
385 : int num_uncarried;
386 : bool have_carry_space;
387 : int32 *pos_digits;
388 : int32 *neg_digits;
389 : } NumericSumAccum;
390 :
391 :
392 : /*
393 : * We define our own macros for packing and unpacking abbreviated-key
394 : * representations for numeric values in order to avoid depending on
395 : * USE_FLOAT8_BYVAL. The type of abbreviation we use is based only on
396 : * the size of a datum, not the argument-passing convention for float8.
397 : *
398 : * The range of abbreviations for finite values is from +PG_INT64/32_MAX
399 : * to -PG_INT64/32_MAX. NaN has the abbreviation PG_INT64/32_MIN, and we
400 : * define the sort ordering to make that work out properly (see further
401 : * comments below). PINF and NINF share the abbreviations of the largest
402 : * and smallest finite abbreviation classes.
403 : */
404 : #define NUMERIC_ABBREV_BITS (SIZEOF_DATUM * BITS_PER_BYTE)
405 : #if SIZEOF_DATUM == 8
406 : #define NumericAbbrevGetDatum(X) ((Datum) (X))
407 : #define DatumGetNumericAbbrev(X) ((int64) (X))
408 : #define NUMERIC_ABBREV_NAN NumericAbbrevGetDatum(PG_INT64_MIN)
409 : #define NUMERIC_ABBREV_PINF NumericAbbrevGetDatum(-PG_INT64_MAX)
410 : #define NUMERIC_ABBREV_NINF NumericAbbrevGetDatum(PG_INT64_MAX)
411 : #else
412 : #define NumericAbbrevGetDatum(X) ((Datum) (X))
413 : #define DatumGetNumericAbbrev(X) ((int32) (X))
414 : #define NUMERIC_ABBREV_NAN NumericAbbrevGetDatum(PG_INT32_MIN)
415 : #define NUMERIC_ABBREV_PINF NumericAbbrevGetDatum(-PG_INT32_MAX)
416 : #define NUMERIC_ABBREV_NINF NumericAbbrevGetDatum(PG_INT32_MAX)
417 : #endif
418 :
419 :
420 : /* ----------
421 : * Some preinitialized constants
422 : * ----------
423 : */
424 : static const NumericDigit const_zero_data[1] = {0};
425 : static const NumericVar const_zero =
426 : {0, 0, NUMERIC_POS, 0, NULL, (NumericDigit *) const_zero_data};
427 :
428 : static const NumericDigit const_one_data[1] = {1};
429 : static const NumericVar const_one =
430 : {1, 0, NUMERIC_POS, 0, NULL, (NumericDigit *) const_one_data};
431 :
432 : static const NumericVar const_minus_one =
433 : {1, 0, NUMERIC_NEG, 0, NULL, (NumericDigit *) const_one_data};
434 :
435 : static const NumericDigit const_two_data[1] = {2};
436 : static const NumericVar const_two =
437 : {1, 0, NUMERIC_POS, 0, NULL, (NumericDigit *) const_two_data};
438 :
439 : #if DEC_DIGITS == 4
440 : static const NumericDigit const_zero_point_nine_data[1] = {9000};
441 : #elif DEC_DIGITS == 2
442 : static const NumericDigit const_zero_point_nine_data[1] = {90};
443 : #elif DEC_DIGITS == 1
444 : static const NumericDigit const_zero_point_nine_data[1] = {9};
445 : #endif
446 : static const NumericVar const_zero_point_nine =
447 : {1, -1, NUMERIC_POS, 1, NULL, (NumericDigit *) const_zero_point_nine_data};
448 :
449 : #if DEC_DIGITS == 4
450 : static const NumericDigit const_one_point_one_data[2] = {1, 1000};
451 : #elif DEC_DIGITS == 2
452 : static const NumericDigit const_one_point_one_data[2] = {1, 10};
453 : #elif DEC_DIGITS == 1
454 : static const NumericDigit const_one_point_one_data[2] = {1, 1};
455 : #endif
456 : static const NumericVar const_one_point_one =
457 : {2, 0, NUMERIC_POS, 1, NULL, (NumericDigit *) const_one_point_one_data};
458 :
459 : static const NumericVar const_nan =
460 : {0, 0, NUMERIC_NAN, 0, NULL, NULL};
461 :
462 : static const NumericVar const_pinf =
463 : {0, 0, NUMERIC_PINF, 0, NULL, NULL};
464 :
465 : static const NumericVar const_ninf =
466 : {0, 0, NUMERIC_NINF, 0, NULL, NULL};
467 :
468 : #if DEC_DIGITS == 4
469 : static const int round_powers[4] = {0, 1000, 100, 10};
470 : #endif
471 :
472 :
473 : /* ----------
474 : * Local functions
475 : * ----------
476 : */
477 :
478 : #ifdef NUMERIC_DEBUG
479 : static void dump_numeric(const char *str, Numeric num);
480 : static void dump_var(const char *str, NumericVar *var);
481 : #else
482 : #define dump_numeric(s,n)
483 : #define dump_var(s,v)
484 : #endif
485 :
486 : #define digitbuf_alloc(ndigits) \
487 : ((NumericDigit *) palloc((ndigits) * sizeof(NumericDigit)))
488 : #define digitbuf_free(buf) \
489 : do { \
490 : if ((buf) != NULL) \
491 : pfree(buf); \
492 : } while (0)
493 :
494 : #define init_var(v) memset(v, 0, sizeof(NumericVar))
495 :
496 : #define NUMERIC_DIGITS(num) (NUMERIC_HEADER_IS_SHORT(num) ? \
497 : (num)->choice.n_short.n_data : (num)->choice.n_long.n_data)
498 : #define NUMERIC_NDIGITS(num) \
499 : ((VARSIZE(num) - NUMERIC_HEADER_SIZE(num)) / sizeof(NumericDigit))
500 : #define NUMERIC_CAN_BE_SHORT(scale,weight) \
501 : ((scale) <= NUMERIC_SHORT_DSCALE_MAX && \
502 : (weight) <= NUMERIC_SHORT_WEIGHT_MAX && \
503 : (weight) >= NUMERIC_SHORT_WEIGHT_MIN)
504 :
505 : static void alloc_var(NumericVar *var, int ndigits);
506 : static void free_var(NumericVar *var);
507 : static void zero_var(NumericVar *var);
508 :
509 : static bool set_var_from_str(const char *str, const char *cp,
510 : NumericVar *dest, const char **endptr,
511 : Node *escontext);
512 : static bool set_var_from_non_decimal_integer_str(const char *str,
513 : const char *cp, int sign,
514 : int base, NumericVar *dest,
515 : const char **endptr,
516 : Node *escontext);
517 : static void set_var_from_num(Numeric num, NumericVar *dest);
518 : static void init_var_from_num(Numeric num, NumericVar *dest);
519 : static void set_var_from_var(const NumericVar *value, NumericVar *dest);
520 : static char *get_str_from_var(const NumericVar *var);
521 : static char *get_str_from_var_sci(const NumericVar *var, int rscale);
522 :
523 : static void numericvar_serialize(StringInfo buf, const NumericVar *var);
524 : static void numericvar_deserialize(StringInfo buf, NumericVar *var);
525 :
526 : static Numeric duplicate_numeric(Numeric num);
527 : static Numeric make_result(const NumericVar *var);
528 : static Numeric make_result_opt_error(const NumericVar *var, bool *have_error);
529 :
530 : static bool apply_typmod(NumericVar *var, int32 typmod, Node *escontext);
531 : static bool apply_typmod_special(Numeric num, int32 typmod, Node *escontext);
532 :
533 : static bool numericvar_to_int32(const NumericVar *var, int32 *result);
534 : static bool numericvar_to_int64(const NumericVar *var, int64 *result);
535 : static void int64_to_numericvar(int64 val, NumericVar *var);
536 : static bool numericvar_to_uint64(const NumericVar *var, uint64 *result);
537 : #ifdef HAVE_INT128
538 : static bool numericvar_to_int128(const NumericVar *var, int128 *result);
539 : static void int128_to_numericvar(int128 val, NumericVar *var);
540 : #endif
541 : static double numericvar_to_double_no_overflow(const NumericVar *var);
542 :
543 : static Datum numeric_abbrev_convert(Datum original_datum, SortSupport ssup);
544 : static bool numeric_abbrev_abort(int memtupcount, SortSupport ssup);
545 : static int numeric_fast_cmp(Datum x, Datum y, SortSupport ssup);
546 : static int numeric_cmp_abbrev(Datum x, Datum y, SortSupport ssup);
547 :
548 : static Datum numeric_abbrev_convert_var(const NumericVar *var,
549 : NumericSortSupport *nss);
550 :
551 : static int cmp_numerics(Numeric num1, Numeric num2);
552 : static int cmp_var(const NumericVar *var1, const NumericVar *var2);
553 : static int cmp_var_common(const NumericDigit *var1digits, int var1ndigits,
554 : int var1weight, int var1sign,
555 : const NumericDigit *var2digits, int var2ndigits,
556 : int var2weight, int var2sign);
557 : static void add_var(const NumericVar *var1, const NumericVar *var2,
558 : NumericVar *result);
559 : static void sub_var(const NumericVar *var1, const NumericVar *var2,
560 : NumericVar *result);
561 : static void mul_var(const NumericVar *var1, const NumericVar *var2,
562 : NumericVar *result,
563 : int rscale);
564 : static void mul_var_short(const NumericVar *var1, const NumericVar *var2,
565 : NumericVar *result);
566 : static void div_var(const NumericVar *var1, const NumericVar *var2,
567 : NumericVar *result, int rscale, bool round, bool exact);
568 : static void div_var_int(const NumericVar *var, int ival, int ival_weight,
569 : NumericVar *result, int rscale, bool round);
570 : #ifdef HAVE_INT128
571 : static void div_var_int64(const NumericVar *var, int64 ival, int ival_weight,
572 : NumericVar *result, int rscale, bool round);
573 : #endif
574 : static int select_div_scale(const NumericVar *var1, const NumericVar *var2);
575 : static void mod_var(const NumericVar *var1, const NumericVar *var2,
576 : NumericVar *result);
577 : static void div_mod_var(const NumericVar *var1, const NumericVar *var2,
578 : NumericVar *quot, NumericVar *rem);
579 : static void ceil_var(const NumericVar *var, NumericVar *result);
580 : static void floor_var(const NumericVar *var, NumericVar *result);
581 :
582 : static void gcd_var(const NumericVar *var1, const NumericVar *var2,
583 : NumericVar *result);
584 : static void sqrt_var(const NumericVar *arg, NumericVar *result, int rscale);
585 : static void exp_var(const NumericVar *arg, NumericVar *result, int rscale);
586 : static int estimate_ln_dweight(const NumericVar *var);
587 : static void ln_var(const NumericVar *arg, NumericVar *result, int rscale);
588 : static void log_var(const NumericVar *base, const NumericVar *num,
589 : NumericVar *result);
590 : static void power_var(const NumericVar *base, const NumericVar *exp,
591 : NumericVar *result);
592 : static void power_var_int(const NumericVar *base, int exp, int exp_dscale,
593 : NumericVar *result);
594 : static void power_ten_int(int exp, NumericVar *result);
595 : static void random_var(pg_prng_state *state, const NumericVar *rmin,
596 : const NumericVar *rmax, NumericVar *result);
597 :
598 : static int cmp_abs(const NumericVar *var1, const NumericVar *var2);
599 : static int cmp_abs_common(const NumericDigit *var1digits, int var1ndigits,
600 : int var1weight,
601 : const NumericDigit *var2digits, int var2ndigits,
602 : int var2weight);
603 : static void add_abs(const NumericVar *var1, const NumericVar *var2,
604 : NumericVar *result);
605 : static void sub_abs(const NumericVar *var1, const NumericVar *var2,
606 : NumericVar *result);
607 : static void round_var(NumericVar *var, int rscale);
608 : static void trunc_var(NumericVar *var, int rscale);
609 : static void strip_var(NumericVar *var);
610 : static void compute_bucket(Numeric operand, Numeric bound1, Numeric bound2,
611 : const NumericVar *count_var,
612 : NumericVar *result_var);
613 :
614 : static void accum_sum_add(NumericSumAccum *accum, const NumericVar *val);
615 : static void accum_sum_rescale(NumericSumAccum *accum, const NumericVar *val);
616 : static void accum_sum_carry(NumericSumAccum *accum);
617 : static void accum_sum_reset(NumericSumAccum *accum);
618 : static void accum_sum_final(NumericSumAccum *accum, NumericVar *result);
619 : static void accum_sum_copy(NumericSumAccum *dst, NumericSumAccum *src);
620 : static void accum_sum_combine(NumericSumAccum *accum, NumericSumAccum *accum2);
621 :
622 :
623 : /* ----------------------------------------------------------------------
624 : *
625 : * Input-, output- and rounding-functions
626 : *
627 : * ----------------------------------------------------------------------
628 : */
629 :
630 :
631 : /*
632 : * numeric_in() -
633 : *
634 : * Input function for numeric data type
635 : */
636 : Datum
637 213546 : numeric_in(PG_FUNCTION_ARGS)
638 : {
639 213546 : char *str = PG_GETARG_CSTRING(0);
640 : #ifdef NOT_USED
641 : Oid typelem = PG_GETARG_OID(1);
642 : #endif
643 213546 : int32 typmod = PG_GETARG_INT32(2);
644 213546 : Node *escontext = fcinfo->context;
645 : Numeric res;
646 : const char *cp;
647 : const char *numstart;
648 : int sign;
649 :
650 : /* Skip leading spaces */
651 213546 : cp = str;
652 237966 : while (*cp)
653 : {
654 237948 : if (!isspace((unsigned char) *cp))
655 213528 : break;
656 24420 : cp++;
657 : }
658 :
659 : /*
660 : * Process the number's sign. This duplicates logic in set_var_from_str(),
661 : * but it's worth doing here, since it simplifies the handling of
662 : * infinities and non-decimal integers.
663 : */
664 213546 : numstart = cp;
665 213546 : sign = NUMERIC_POS;
666 :
667 213546 : if (*cp == '+')
668 48 : cp++;
669 213498 : else if (*cp == '-')
670 : {
671 4674 : sign = NUMERIC_NEG;
672 4674 : cp++;
673 : }
674 :
675 : /*
676 : * Check for NaN and infinities. We recognize the same strings allowed by
677 : * float8in().
678 : *
679 : * Since all other legal inputs have a digit or a decimal point after the
680 : * sign, we need only check for NaN/infinity if that's not the case.
681 : */
682 213546 : if (!isdigit((unsigned char) *cp) && *cp != '.')
683 : {
684 : /*
685 : * The number must be NaN or infinity; anything else can only be a
686 : * syntax error. Note that NaN mustn't have a sign.
687 : */
688 1874 : if (pg_strncasecmp(numstart, "NaN", 3) == 0)
689 : {
690 672 : res = make_result(&const_nan);
691 672 : cp = numstart + 3;
692 : }
693 1202 : else if (pg_strncasecmp(cp, "Infinity", 8) == 0)
694 : {
695 504 : res = make_result(sign == NUMERIC_POS ? &const_pinf : &const_ninf);
696 504 : cp += 8;
697 : }
698 698 : else if (pg_strncasecmp(cp, "inf", 3) == 0)
699 : {
700 588 : res = make_result(sign == NUMERIC_POS ? &const_pinf : &const_ninf);
701 588 : cp += 3;
702 : }
703 : else
704 110 : goto invalid_syntax;
705 :
706 : /*
707 : * Check for trailing junk; there should be nothing left but spaces.
708 : *
709 : * We intentionally do this check before applying the typmod because
710 : * we would like to throw any trailing-junk syntax error before any
711 : * semantic error resulting from apply_typmod_special().
712 : */
713 1806 : while (*cp)
714 : {
715 42 : if (!isspace((unsigned char) *cp))
716 0 : goto invalid_syntax;
717 42 : cp++;
718 : }
719 :
720 1764 : if (!apply_typmod_special(res, typmod, escontext))
721 0 : PG_RETURN_NULL();
722 : }
723 : else
724 : {
725 : /*
726 : * We have a normal numeric value, which may be a non-decimal integer
727 : * or a regular decimal number.
728 : */
729 : NumericVar value;
730 : int base;
731 : bool have_error;
732 :
733 211672 : init_var(&value);
734 :
735 : /*
736 : * Determine the number's base by looking for a non-decimal prefix
737 : * indicator ("0x", "0o", or "0b").
738 : */
739 211672 : if (cp[0] == '0')
740 : {
741 85074 : switch (cp[1])
742 : {
743 72 : case 'x':
744 : case 'X':
745 72 : base = 16;
746 72 : break;
747 42 : case 'o':
748 : case 'O':
749 42 : base = 8;
750 42 : break;
751 42 : case 'b':
752 : case 'B':
753 42 : base = 2;
754 42 : break;
755 84918 : default:
756 84918 : base = 10;
757 : }
758 : }
759 : else
760 126598 : base = 10;
761 :
762 : /* Parse the rest of the number and apply the sign */
763 211672 : if (base == 10)
764 : {
765 211516 : if (!set_var_from_str(str, cp, &value, &cp, escontext))
766 42 : PG_RETURN_NULL();
767 211468 : value.sign = sign;
768 : }
769 : else
770 : {
771 156 : if (!set_var_from_non_decimal_integer_str(str, cp + 2, sign, base,
772 : &value, &cp, escontext))
773 0 : PG_RETURN_NULL();
774 : }
775 :
776 : /*
777 : * Should be nothing left but spaces. As above, throw any typmod error
778 : * after finishing syntax check.
779 : */
780 211684 : while (*cp)
781 : {
782 150 : if (!isspace((unsigned char) *cp))
783 72 : goto invalid_syntax;
784 78 : cp++;
785 : }
786 :
787 211534 : if (!apply_typmod(&value, typmod, escontext))
788 24 : PG_RETURN_NULL();
789 :
790 211510 : res = make_result_opt_error(&value, &have_error);
791 :
792 211510 : if (have_error)
793 18 : ereturn(escontext, (Datum) 0,
794 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
795 : errmsg("value overflows numeric format")));
796 :
797 211492 : free_var(&value);
798 : }
799 :
800 213256 : PG_RETURN_NUMERIC(res);
801 :
802 182 : invalid_syntax:
803 182 : ereturn(escontext, (Datum) 0,
804 : (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
805 : errmsg("invalid input syntax for type %s: \"%s\"",
806 : "numeric", str)));
807 : }
808 :
809 :
810 : /*
811 : * numeric_out() -
812 : *
813 : * Output function for numeric data type
814 : */
815 : Datum
816 1002088 : numeric_out(PG_FUNCTION_ARGS)
817 : {
818 1002088 : Numeric num = PG_GETARG_NUMERIC(0);
819 : NumericVar x;
820 : char *str;
821 :
822 : /*
823 : * Handle NaN and infinities
824 : */
825 1002088 : if (NUMERIC_IS_SPECIAL(num))
826 : {
827 3846 : if (NUMERIC_IS_PINF(num))
828 1064 : PG_RETURN_CSTRING(pstrdup("Infinity"));
829 2782 : else if (NUMERIC_IS_NINF(num))
830 670 : PG_RETURN_CSTRING(pstrdup("-Infinity"));
831 : else
832 2112 : PG_RETURN_CSTRING(pstrdup("NaN"));
833 : }
834 :
835 : /*
836 : * Get the number in the variable format.
837 : */
838 998242 : init_var_from_num(num, &x);
839 :
840 998242 : str = get_str_from_var(&x);
841 :
842 998242 : PG_RETURN_CSTRING(str);
843 : }
844 :
845 : /*
846 : * numeric_is_nan() -
847 : *
848 : * Is Numeric value a NaN?
849 : */
850 : bool
851 7516 : numeric_is_nan(Numeric num)
852 : {
853 7516 : return NUMERIC_IS_NAN(num);
854 : }
855 :
856 : /*
857 : * numeric_is_inf() -
858 : *
859 : * Is Numeric value an infinity?
860 : */
861 : bool
862 312 : numeric_is_inf(Numeric num)
863 : {
864 312 : return NUMERIC_IS_INF(num);
865 : }
866 :
867 : /*
868 : * numeric_is_integral() -
869 : *
870 : * Is Numeric value integral?
871 : */
872 : static bool
873 66 : numeric_is_integral(Numeric num)
874 : {
875 : NumericVar arg;
876 :
877 : /* Reject NaN, but infinities are considered integral */
878 66 : if (NUMERIC_IS_SPECIAL(num))
879 : {
880 30 : if (NUMERIC_IS_NAN(num))
881 0 : return false;
882 30 : return true;
883 : }
884 :
885 : /* Integral if there are no digits to the right of the decimal point */
886 36 : init_var_from_num(num, &arg);
887 :
888 36 : return (arg.ndigits == 0 || arg.ndigits <= arg.weight + 1);
889 : }
890 :
891 : /*
892 : * make_numeric_typmod() -
893 : *
894 : * Pack numeric precision and scale values into a typmod. The upper 16 bits
895 : * are used for the precision (though actually not all these bits are needed,
896 : * since the maximum allowed precision is 1000). The lower 16 bits are for
897 : * the scale, but since the scale is constrained to the range [-1000, 1000],
898 : * we use just the lower 11 of those 16 bits, and leave the remaining 5 bits
899 : * unset, for possible future use.
900 : *
901 : * For purely historical reasons VARHDRSZ is then added to the result, thus
902 : * the unused space in the upper 16 bits is not all as freely available as it
903 : * might seem. (We can't let the result overflow to a negative int32, as
904 : * other parts of the system would interpret that as not-a-valid-typmod.)
905 : */
906 : static inline int32
907 1980 : make_numeric_typmod(int precision, int scale)
908 : {
909 1980 : return ((precision << 16) | (scale & 0x7ff)) + VARHDRSZ;
910 : }
911 :
912 : /*
913 : * Because of the offset, valid numeric typmods are at least VARHDRSZ
914 : */
915 : static inline bool
916 236830 : is_valid_numeric_typmod(int32 typmod)
917 : {
918 236830 : return typmod >= (int32) VARHDRSZ;
919 : }
920 :
921 : /*
922 : * numeric_typmod_precision() -
923 : *
924 : * Extract the precision from a numeric typmod --- see make_numeric_typmod().
925 : */
926 : static inline int
927 49816 : numeric_typmod_precision(int32 typmod)
928 : {
929 49816 : return ((typmod - VARHDRSZ) >> 16) & 0xffff;
930 : }
931 :
932 : /*
933 : * numeric_typmod_scale() -
934 : *
935 : * Extract the scale from a numeric typmod --- see make_numeric_typmod().
936 : *
937 : * Note that the scale may be negative, so we must do sign extension when
938 : * unpacking it. We do this using the bit hack (x^1024)-1024, which sign
939 : * extends an 11-bit two's complement number x.
940 : */
941 : static inline int
942 42620 : numeric_typmod_scale(int32 typmod)
943 : {
944 42620 : return (((typmod - VARHDRSZ) & 0x7ff) ^ 1024) - 1024;
945 : }
946 :
947 : /*
948 : * numeric_maximum_size() -
949 : *
950 : * Maximum size of a numeric with given typmod, or -1 if unlimited/unknown.
951 : */
952 : int32
953 7196 : numeric_maximum_size(int32 typmod)
954 : {
955 : int precision;
956 : int numeric_digits;
957 :
958 7196 : if (!is_valid_numeric_typmod(typmod))
959 0 : return -1;
960 :
961 : /* precision (ie, max # of digits) is in upper bits of typmod */
962 7196 : precision = numeric_typmod_precision(typmod);
963 :
964 : /*
965 : * This formula computes the maximum number of NumericDigits we could need
966 : * in order to store the specified number of decimal digits. Because the
967 : * weight is stored as a number of NumericDigits rather than a number of
968 : * decimal digits, it's possible that the first NumericDigit will contain
969 : * only a single decimal digit. Thus, the first two decimal digits can
970 : * require two NumericDigits to store, but it isn't until we reach
971 : * DEC_DIGITS + 2 decimal digits that we potentially need a third
972 : * NumericDigit.
973 : */
974 7196 : numeric_digits = (precision + 2 * (DEC_DIGITS - 1)) / DEC_DIGITS;
975 :
976 : /*
977 : * In most cases, the size of a numeric will be smaller than the value
978 : * computed below, because the varlena header will typically get toasted
979 : * down to a single byte before being stored on disk, and it may also be
980 : * possible to use a short numeric header. But our job here is to compute
981 : * the worst case.
982 : */
983 7196 : return NUMERIC_HDRSZ + (numeric_digits * sizeof(NumericDigit));
984 : }
985 :
986 : /*
987 : * numeric_out_sci() -
988 : *
989 : * Output function for numeric data type in scientific notation.
990 : */
991 : char *
992 246 : numeric_out_sci(Numeric num, int scale)
993 : {
994 : NumericVar x;
995 : char *str;
996 :
997 : /*
998 : * Handle NaN and infinities
999 : */
1000 246 : if (NUMERIC_IS_SPECIAL(num))
1001 : {
1002 18 : if (NUMERIC_IS_PINF(num))
1003 6 : return pstrdup("Infinity");
1004 12 : else if (NUMERIC_IS_NINF(num))
1005 6 : return pstrdup("-Infinity");
1006 : else
1007 6 : return pstrdup("NaN");
1008 : }
1009 :
1010 228 : init_var_from_num(num, &x);
1011 :
1012 228 : str = get_str_from_var_sci(&x, scale);
1013 :
1014 228 : return str;
1015 : }
1016 :
1017 : /*
1018 : * numeric_normalize() -
1019 : *
1020 : * Output function for numeric data type, suppressing insignificant trailing
1021 : * zeroes and then any trailing decimal point. The intent of this is to
1022 : * produce strings that are equal if and only if the input numeric values
1023 : * compare equal.
1024 : */
1025 : char *
1026 60086 : numeric_normalize(Numeric num)
1027 : {
1028 : NumericVar x;
1029 : char *str;
1030 : int last;
1031 :
1032 : /*
1033 : * Handle NaN and infinities
1034 : */
1035 60086 : if (NUMERIC_IS_SPECIAL(num))
1036 : {
1037 0 : if (NUMERIC_IS_PINF(num))
1038 0 : return pstrdup("Infinity");
1039 0 : else if (NUMERIC_IS_NINF(num))
1040 0 : return pstrdup("-Infinity");
1041 : else
1042 0 : return pstrdup("NaN");
1043 : }
1044 :
1045 60086 : init_var_from_num(num, &x);
1046 :
1047 60086 : str = get_str_from_var(&x);
1048 :
1049 : /* If there's no decimal point, there's certainly nothing to remove. */
1050 60086 : if (strchr(str, '.') != NULL)
1051 : {
1052 : /*
1053 : * Back up over trailing fractional zeroes. Since there is a decimal
1054 : * point, this loop will terminate safely.
1055 : */
1056 42 : last = strlen(str) - 1;
1057 84 : while (str[last] == '0')
1058 42 : last--;
1059 :
1060 : /* We want to get rid of the decimal point too, if it's now last. */
1061 42 : if (str[last] == '.')
1062 42 : last--;
1063 :
1064 : /* Delete whatever we backed up over. */
1065 42 : str[last + 1] = '\0';
1066 : }
1067 :
1068 60086 : return str;
1069 : }
1070 :
1071 : /*
1072 : * numeric_recv - converts external binary format to numeric
1073 : *
1074 : * External format is a sequence of int16's:
1075 : * ndigits, weight, sign, dscale, NumericDigits.
1076 : */
1077 : Datum
1078 102 : numeric_recv(PG_FUNCTION_ARGS)
1079 : {
1080 102 : StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
1081 :
1082 : #ifdef NOT_USED
1083 : Oid typelem = PG_GETARG_OID(1);
1084 : #endif
1085 102 : int32 typmod = PG_GETARG_INT32(2);
1086 : NumericVar value;
1087 : Numeric res;
1088 : int len,
1089 : i;
1090 :
1091 102 : init_var(&value);
1092 :
1093 102 : len = (uint16) pq_getmsgint(buf, sizeof(uint16));
1094 :
1095 102 : alloc_var(&value, len);
1096 :
1097 102 : value.weight = (int16) pq_getmsgint(buf, sizeof(int16));
1098 : /* we allow any int16 for weight --- OK? */
1099 :
1100 102 : value.sign = (uint16) pq_getmsgint(buf, sizeof(uint16));
1101 102 : if (!(value.sign == NUMERIC_POS ||
1102 0 : value.sign == NUMERIC_NEG ||
1103 0 : value.sign == NUMERIC_NAN ||
1104 0 : value.sign == NUMERIC_PINF ||
1105 0 : value.sign == NUMERIC_NINF))
1106 0 : ereport(ERROR,
1107 : (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
1108 : errmsg("invalid sign in external \"numeric\" value")));
1109 :
1110 102 : value.dscale = (uint16) pq_getmsgint(buf, sizeof(uint16));
1111 102 : if ((value.dscale & NUMERIC_DSCALE_MASK) != value.dscale)
1112 0 : ereport(ERROR,
1113 : (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
1114 : errmsg("invalid scale in external \"numeric\" value")));
1115 :
1116 274 : for (i = 0; i < len; i++)
1117 : {
1118 172 : NumericDigit d = pq_getmsgint(buf, sizeof(NumericDigit));
1119 :
1120 172 : if (d < 0 || d >= NBASE)
1121 0 : ereport(ERROR,
1122 : (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
1123 : errmsg("invalid digit in external \"numeric\" value")));
1124 172 : value.digits[i] = d;
1125 : }
1126 :
1127 : /*
1128 : * If the given dscale would hide any digits, truncate those digits away.
1129 : * We could alternatively throw an error, but that would take a bunch of
1130 : * extra code (about as much as trunc_var involves), and it might cause
1131 : * client compatibility issues. Be careful not to apply trunc_var to
1132 : * special values, as it could do the wrong thing; we don't need it
1133 : * anyway, since make_result will ignore all but the sign field.
1134 : *
1135 : * After doing that, be sure to check the typmod restriction.
1136 : */
1137 102 : if (value.sign == NUMERIC_POS ||
1138 0 : value.sign == NUMERIC_NEG)
1139 : {
1140 102 : trunc_var(&value, value.dscale);
1141 :
1142 102 : (void) apply_typmod(&value, typmod, NULL);
1143 :
1144 102 : res = make_result(&value);
1145 : }
1146 : else
1147 : {
1148 : /* apply_typmod_special wants us to make the Numeric first */
1149 0 : res = make_result(&value);
1150 :
1151 0 : (void) apply_typmod_special(res, typmod, NULL);
1152 : }
1153 :
1154 102 : free_var(&value);
1155 :
1156 102 : PG_RETURN_NUMERIC(res);
1157 : }
1158 :
1159 : /*
1160 : * numeric_send - converts numeric to binary format
1161 : */
1162 : Datum
1163 70 : numeric_send(PG_FUNCTION_ARGS)
1164 : {
1165 70 : Numeric num = PG_GETARG_NUMERIC(0);
1166 : NumericVar x;
1167 : StringInfoData buf;
1168 : int i;
1169 :
1170 70 : init_var_from_num(num, &x);
1171 :
1172 70 : pq_begintypsend(&buf);
1173 :
1174 70 : pq_sendint16(&buf, x.ndigits);
1175 70 : pq_sendint16(&buf, x.weight);
1176 70 : pq_sendint16(&buf, x.sign);
1177 70 : pq_sendint16(&buf, x.dscale);
1178 194 : for (i = 0; i < x.ndigits; i++)
1179 124 : pq_sendint16(&buf, x.digits[i]);
1180 :
1181 70 : PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
1182 : }
1183 :
1184 :
1185 : /*
1186 : * numeric_support()
1187 : *
1188 : * Planner support function for the numeric() length coercion function.
1189 : *
1190 : * Flatten calls that solely represent increases in allowable precision.
1191 : * Scale changes mutate every datum, so they are unoptimizable. Some values,
1192 : * e.g. 1E-1001, can only fit into an unconstrained numeric, so a change from
1193 : * an unconstrained numeric to any constrained numeric is also unoptimizable.
1194 : */
1195 : Datum
1196 516 : numeric_support(PG_FUNCTION_ARGS)
1197 : {
1198 516 : Node *rawreq = (Node *) PG_GETARG_POINTER(0);
1199 516 : Node *ret = NULL;
1200 :
1201 516 : if (IsA(rawreq, SupportRequestSimplify))
1202 : {
1203 228 : SupportRequestSimplify *req = (SupportRequestSimplify *) rawreq;
1204 228 : FuncExpr *expr = req->fcall;
1205 : Node *typmod;
1206 :
1207 : Assert(list_length(expr->args) >= 2);
1208 :
1209 228 : typmod = (Node *) lsecond(expr->args);
1210 :
1211 228 : if (IsA(typmod, Const) && !((Const *) typmod)->constisnull)
1212 : {
1213 228 : Node *source = (Node *) linitial(expr->args);
1214 228 : int32 old_typmod = exprTypmod(source);
1215 228 : int32 new_typmod = DatumGetInt32(((Const *) typmod)->constvalue);
1216 228 : int32 old_scale = numeric_typmod_scale(old_typmod);
1217 228 : int32 new_scale = numeric_typmod_scale(new_typmod);
1218 228 : int32 old_precision = numeric_typmod_precision(old_typmod);
1219 228 : int32 new_precision = numeric_typmod_precision(new_typmod);
1220 :
1221 : /*
1222 : * If new_typmod is invalid, the destination is unconstrained;
1223 : * that's always OK. If old_typmod is valid, the source is
1224 : * constrained, and we're OK if the scale is unchanged and the
1225 : * precision is not decreasing. See further notes in function
1226 : * header comment.
1227 : */
1228 456 : if (!is_valid_numeric_typmod(new_typmod) ||
1229 240 : (is_valid_numeric_typmod(old_typmod) &&
1230 6 : new_scale == old_scale && new_precision >= old_precision))
1231 6 : ret = relabel_to_typmod(source, new_typmod);
1232 : }
1233 : }
1234 :
1235 516 : PG_RETURN_POINTER(ret);
1236 : }
1237 :
1238 : /*
1239 : * numeric() -
1240 : *
1241 : * This is a special function called by the Postgres database system
1242 : * before a value is stored in a tuple's attribute. The precision and
1243 : * scale of the attribute have to be applied on the value.
1244 : */
1245 : Datum
1246 11730 : numeric (PG_FUNCTION_ARGS)
1247 : {
1248 11730 : Numeric num = PG_GETARG_NUMERIC(0);
1249 11730 : int32 typmod = PG_GETARG_INT32(1);
1250 : Numeric new;
1251 : int precision;
1252 : int scale;
1253 : int ddigits;
1254 : int maxdigits;
1255 : int dscale;
1256 : NumericVar var;
1257 :
1258 : /*
1259 : * Handle NaN and infinities: if apply_typmod_special doesn't complain,
1260 : * just return a copy of the input.
1261 : */
1262 11730 : if (NUMERIC_IS_SPECIAL(num))
1263 : {
1264 210 : (void) apply_typmod_special(num, typmod, NULL);
1265 192 : PG_RETURN_NUMERIC(duplicate_numeric(num));
1266 : }
1267 :
1268 : /*
1269 : * If the value isn't a valid type modifier, simply return a copy of the
1270 : * input value
1271 : */
1272 11520 : if (!is_valid_numeric_typmod(typmod))
1273 0 : PG_RETURN_NUMERIC(duplicate_numeric(num));
1274 :
1275 : /*
1276 : * Get the precision and scale out of the typmod value
1277 : */
1278 11520 : precision = numeric_typmod_precision(typmod);
1279 11520 : scale = numeric_typmod_scale(typmod);
1280 11520 : maxdigits = precision - scale;
1281 :
1282 : /* The target display scale is non-negative */
1283 11520 : dscale = Max(scale, 0);
1284 :
1285 : /*
1286 : * If the number is certainly in bounds and due to the target scale no
1287 : * rounding could be necessary, just make a copy of the input and modify
1288 : * its scale fields, unless the larger scale forces us to abandon the
1289 : * short representation. (Note we assume the existing dscale is
1290 : * honest...)
1291 : */
1292 11520 : ddigits = (NUMERIC_WEIGHT(num) + 1) * DEC_DIGITS;
1293 11520 : if (ddigits <= maxdigits && scale >= NUMERIC_DSCALE(num)
1294 7134 : && (NUMERIC_CAN_BE_SHORT(dscale, NUMERIC_WEIGHT(num))
1295 0 : || !NUMERIC_IS_SHORT(num)))
1296 : {
1297 7134 : new = duplicate_numeric(num);
1298 7134 : if (NUMERIC_IS_SHORT(num))
1299 7134 : new->choice.n_short.n_header =
1300 7134 : (num->choice.n_short.n_header & ~NUMERIC_SHORT_DSCALE_MASK)
1301 7134 : | (dscale << NUMERIC_SHORT_DSCALE_SHIFT);
1302 : else
1303 0 : new->choice.n_long.n_sign_dscale = NUMERIC_SIGN(new) |
1304 0 : ((uint16) dscale & NUMERIC_DSCALE_MASK);
1305 7134 : PG_RETURN_NUMERIC(new);
1306 : }
1307 :
1308 : /*
1309 : * We really need to fiddle with things - unpack the number into a
1310 : * variable and let apply_typmod() do it.
1311 : */
1312 4386 : init_var(&var);
1313 :
1314 4386 : set_var_from_num(num, &var);
1315 4386 : (void) apply_typmod(&var, typmod, NULL);
1316 4326 : new = make_result(&var);
1317 :
1318 4326 : free_var(&var);
1319 :
1320 4326 : PG_RETURN_NUMERIC(new);
1321 : }
1322 :
1323 : Datum
1324 2022 : numerictypmodin(PG_FUNCTION_ARGS)
1325 : {
1326 2022 : ArrayType *ta = PG_GETARG_ARRAYTYPE_P(0);
1327 : int32 *tl;
1328 : int n;
1329 : int32 typmod;
1330 :
1331 2022 : tl = ArrayGetIntegerTypmods(ta, &n);
1332 :
1333 2022 : if (n == 2)
1334 : {
1335 2002 : if (tl[0] < 1 || tl[0] > NUMERIC_MAX_PRECISION)
1336 18 : ereport(ERROR,
1337 : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1338 : errmsg("NUMERIC precision %d must be between 1 and %d",
1339 : tl[0], NUMERIC_MAX_PRECISION)));
1340 1984 : if (tl[1] < NUMERIC_MIN_SCALE || tl[1] > NUMERIC_MAX_SCALE)
1341 12 : ereport(ERROR,
1342 : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1343 : errmsg("NUMERIC scale %d must be between %d and %d",
1344 : tl[1], NUMERIC_MIN_SCALE, NUMERIC_MAX_SCALE)));
1345 1972 : typmod = make_numeric_typmod(tl[0], tl[1]);
1346 : }
1347 20 : else if (n == 1)
1348 : {
1349 8 : if (tl[0] < 1 || tl[0] > NUMERIC_MAX_PRECISION)
1350 0 : ereport(ERROR,
1351 : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1352 : errmsg("NUMERIC precision %d must be between 1 and %d",
1353 : tl[0], NUMERIC_MAX_PRECISION)));
1354 : /* scale defaults to zero */
1355 8 : typmod = make_numeric_typmod(tl[0], 0);
1356 : }
1357 : else
1358 : {
1359 12 : ereport(ERROR,
1360 : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1361 : errmsg("invalid NUMERIC type modifier")));
1362 : typmod = 0; /* keep compiler quiet */
1363 : }
1364 :
1365 1980 : PG_RETURN_INT32(typmod);
1366 : }
1367 :
1368 : Datum
1369 526 : numerictypmodout(PG_FUNCTION_ARGS)
1370 : {
1371 526 : int32 typmod = PG_GETARG_INT32(0);
1372 526 : char *res = (char *) palloc(64);
1373 :
1374 526 : if (is_valid_numeric_typmod(typmod))
1375 526 : snprintf(res, 64, "(%d,%d)",
1376 : numeric_typmod_precision(typmod),
1377 : numeric_typmod_scale(typmod));
1378 : else
1379 0 : *res = '\0';
1380 :
1381 526 : PG_RETURN_CSTRING(res);
1382 : }
1383 :
1384 :
1385 : /* ----------------------------------------------------------------------
1386 : *
1387 : * Sign manipulation, rounding and the like
1388 : *
1389 : * ----------------------------------------------------------------------
1390 : */
1391 :
1392 : Datum
1393 19506 : numeric_abs(PG_FUNCTION_ARGS)
1394 : {
1395 19506 : Numeric num = PG_GETARG_NUMERIC(0);
1396 : Numeric res;
1397 :
1398 : /*
1399 : * Do it the easy way directly on the packed format
1400 : */
1401 19506 : res = duplicate_numeric(num);
1402 :
1403 19506 : if (NUMERIC_IS_SHORT(num))
1404 19440 : res->choice.n_short.n_header =
1405 19440 : num->choice.n_short.n_header & ~NUMERIC_SHORT_SIGN_MASK;
1406 66 : else if (NUMERIC_IS_SPECIAL(num))
1407 : {
1408 : /* This changes -Inf to Inf, and doesn't affect NaN */
1409 18 : res->choice.n_short.n_header =
1410 18 : num->choice.n_short.n_header & ~NUMERIC_INF_SIGN_MASK;
1411 : }
1412 : else
1413 48 : res->choice.n_long.n_sign_dscale = NUMERIC_POS | NUMERIC_DSCALE(num);
1414 :
1415 19506 : PG_RETURN_NUMERIC(res);
1416 : }
1417 :
1418 :
1419 : Datum
1420 884 : numeric_uminus(PG_FUNCTION_ARGS)
1421 : {
1422 884 : Numeric num = PG_GETARG_NUMERIC(0);
1423 : Numeric res;
1424 :
1425 : /*
1426 : * Do it the easy way directly on the packed format
1427 : */
1428 884 : res = duplicate_numeric(num);
1429 :
1430 884 : if (NUMERIC_IS_SPECIAL(num))
1431 : {
1432 : /* Flip the sign, if it's Inf or -Inf */
1433 126 : if (!NUMERIC_IS_NAN(num))
1434 84 : res->choice.n_short.n_header =
1435 84 : num->choice.n_short.n_header ^ NUMERIC_INF_SIGN_MASK;
1436 : }
1437 :
1438 : /*
1439 : * The packed format is known to be totally zero digit trimmed always. So
1440 : * once we've eliminated specials, we can identify a zero by the fact that
1441 : * there are no digits at all. Do nothing to a zero.
1442 : */
1443 758 : else if (NUMERIC_NDIGITS(num) != 0)
1444 : {
1445 : /* Else, flip the sign */
1446 644 : if (NUMERIC_IS_SHORT(num))
1447 644 : res->choice.n_short.n_header =
1448 644 : num->choice.n_short.n_header ^ NUMERIC_SHORT_SIGN_MASK;
1449 0 : else if (NUMERIC_SIGN(num) == NUMERIC_POS)
1450 0 : res->choice.n_long.n_sign_dscale =
1451 0 : NUMERIC_NEG | NUMERIC_DSCALE(num);
1452 : else
1453 0 : res->choice.n_long.n_sign_dscale =
1454 0 : NUMERIC_POS | NUMERIC_DSCALE(num);
1455 : }
1456 :
1457 884 : PG_RETURN_NUMERIC(res);
1458 : }
1459 :
1460 :
1461 : Datum
1462 498 : numeric_uplus(PG_FUNCTION_ARGS)
1463 : {
1464 498 : Numeric num = PG_GETARG_NUMERIC(0);
1465 :
1466 498 : PG_RETURN_NUMERIC(duplicate_numeric(num));
1467 : }
1468 :
1469 :
1470 : /*
1471 : * numeric_sign_internal() -
1472 : *
1473 : * Returns -1 if the argument is less than 0, 0 if the argument is equal
1474 : * to 0, and 1 if the argument is greater than zero. Caller must have
1475 : * taken care of the NaN case, but we can handle infinities here.
1476 : */
1477 : static int
1478 3570 : numeric_sign_internal(Numeric num)
1479 : {
1480 3570 : if (NUMERIC_IS_SPECIAL(num))
1481 : {
1482 : Assert(!NUMERIC_IS_NAN(num));
1483 : /* Must be Inf or -Inf */
1484 312 : if (NUMERIC_IS_PINF(num))
1485 186 : return 1;
1486 : else
1487 126 : return -1;
1488 : }
1489 :
1490 : /*
1491 : * The packed format is known to be totally zero digit trimmed always. So
1492 : * once we've eliminated specials, we can identify a zero by the fact that
1493 : * there are no digits at all.
1494 : */
1495 3258 : else if (NUMERIC_NDIGITS(num) == 0)
1496 228 : return 0;
1497 3030 : else if (NUMERIC_SIGN(num) == NUMERIC_NEG)
1498 732 : return -1;
1499 : else
1500 2298 : return 1;
1501 : }
1502 :
1503 : /*
1504 : * numeric_sign() -
1505 : *
1506 : * returns -1 if the argument is less than 0, 0 if the argument is equal
1507 : * to 0, and 1 if the argument is greater than zero.
1508 : */
1509 : Datum
1510 48 : numeric_sign(PG_FUNCTION_ARGS)
1511 : {
1512 48 : Numeric num = PG_GETARG_NUMERIC(0);
1513 :
1514 : /*
1515 : * Handle NaN (infinities can be handled normally)
1516 : */
1517 48 : if (NUMERIC_IS_NAN(num))
1518 6 : PG_RETURN_NUMERIC(make_result(&const_nan));
1519 :
1520 42 : switch (numeric_sign_internal(num))
1521 : {
1522 6 : case 0:
1523 6 : PG_RETURN_NUMERIC(make_result(&const_zero));
1524 18 : case 1:
1525 18 : PG_RETURN_NUMERIC(make_result(&const_one));
1526 18 : case -1:
1527 18 : PG_RETURN_NUMERIC(make_result(&const_minus_one));
1528 : }
1529 :
1530 : Assert(false);
1531 0 : return (Datum) 0;
1532 : }
1533 :
1534 :
1535 : /*
1536 : * numeric_round() -
1537 : *
1538 : * Round a value to have 'scale' digits after the decimal point.
1539 : * We allow negative 'scale', implying rounding before the decimal
1540 : * point --- Oracle interprets rounding that way.
1541 : */
1542 : Datum
1543 7808 : numeric_round(PG_FUNCTION_ARGS)
1544 : {
1545 7808 : Numeric num = PG_GETARG_NUMERIC(0);
1546 7808 : int32 scale = PG_GETARG_INT32(1);
1547 : Numeric res;
1548 : NumericVar arg;
1549 :
1550 : /*
1551 : * Handle NaN and infinities
1552 : */
1553 7808 : if (NUMERIC_IS_SPECIAL(num))
1554 96 : PG_RETURN_NUMERIC(duplicate_numeric(num));
1555 :
1556 : /*
1557 : * Limit the scale value to avoid possible overflow in calculations.
1558 : *
1559 : * These limits are based on the maximum number of digits a Numeric value
1560 : * can have before and after the decimal point, but we must allow for one
1561 : * extra digit before the decimal point, in case the most significant
1562 : * digit rounds up; we must check if that causes Numeric overflow.
1563 : */
1564 7712 : scale = Max(scale, -(NUMERIC_WEIGHT_MAX + 1) * DEC_DIGITS - 1);
1565 7712 : scale = Min(scale, NUMERIC_DSCALE_MAX);
1566 :
1567 : /*
1568 : * Unpack the argument and round it at the proper digit position
1569 : */
1570 7712 : init_var(&arg);
1571 7712 : set_var_from_num(num, &arg);
1572 :
1573 7712 : round_var(&arg, scale);
1574 :
1575 : /* We don't allow negative output dscale */
1576 7712 : if (scale < 0)
1577 216 : arg.dscale = 0;
1578 :
1579 : /*
1580 : * Return the rounded result
1581 : */
1582 7712 : res = make_result(&arg);
1583 :
1584 7706 : free_var(&arg);
1585 7706 : PG_RETURN_NUMERIC(res);
1586 : }
1587 :
1588 :
1589 : /*
1590 : * numeric_trunc() -
1591 : *
1592 : * Truncate a value to have 'scale' digits after the decimal point.
1593 : * We allow negative 'scale', implying a truncation before the decimal
1594 : * point --- Oracle interprets truncation that way.
1595 : */
1596 : Datum
1597 626 : numeric_trunc(PG_FUNCTION_ARGS)
1598 : {
1599 626 : Numeric num = PG_GETARG_NUMERIC(0);
1600 626 : int32 scale = PG_GETARG_INT32(1);
1601 : Numeric res;
1602 : NumericVar arg;
1603 :
1604 : /*
1605 : * Handle NaN and infinities
1606 : */
1607 626 : if (NUMERIC_IS_SPECIAL(num))
1608 36 : PG_RETURN_NUMERIC(duplicate_numeric(num));
1609 :
1610 : /*
1611 : * Limit the scale value to avoid possible overflow in calculations.
1612 : *
1613 : * These limits are based on the maximum number of digits a Numeric value
1614 : * can have before and after the decimal point.
1615 : */
1616 590 : scale = Max(scale, -(NUMERIC_WEIGHT_MAX + 1) * DEC_DIGITS);
1617 590 : scale = Min(scale, NUMERIC_DSCALE_MAX);
1618 :
1619 : /*
1620 : * Unpack the argument and truncate it at the proper digit position
1621 : */
1622 590 : init_var(&arg);
1623 590 : set_var_from_num(num, &arg);
1624 :
1625 590 : trunc_var(&arg, scale);
1626 :
1627 : /* We don't allow negative output dscale */
1628 590 : if (scale < 0)
1629 24 : arg.dscale = 0;
1630 :
1631 : /*
1632 : * Return the truncated result
1633 : */
1634 590 : res = make_result(&arg);
1635 :
1636 590 : free_var(&arg);
1637 590 : PG_RETURN_NUMERIC(res);
1638 : }
1639 :
1640 :
1641 : /*
1642 : * numeric_ceil() -
1643 : *
1644 : * Return the smallest integer greater than or equal to the argument
1645 : */
1646 : Datum
1647 222 : numeric_ceil(PG_FUNCTION_ARGS)
1648 : {
1649 222 : Numeric num = PG_GETARG_NUMERIC(0);
1650 : Numeric res;
1651 : NumericVar result;
1652 :
1653 : /*
1654 : * Handle NaN and infinities
1655 : */
1656 222 : if (NUMERIC_IS_SPECIAL(num))
1657 18 : PG_RETURN_NUMERIC(duplicate_numeric(num));
1658 :
1659 204 : init_var_from_num(num, &result);
1660 204 : ceil_var(&result, &result);
1661 :
1662 204 : res = make_result(&result);
1663 204 : free_var(&result);
1664 :
1665 204 : PG_RETURN_NUMERIC(res);
1666 : }
1667 :
1668 :
1669 : /*
1670 : * numeric_floor() -
1671 : *
1672 : * Return the largest integer equal to or less than the argument
1673 : */
1674 : Datum
1675 126 : numeric_floor(PG_FUNCTION_ARGS)
1676 : {
1677 126 : Numeric num = PG_GETARG_NUMERIC(0);
1678 : Numeric res;
1679 : NumericVar result;
1680 :
1681 : /*
1682 : * Handle NaN and infinities
1683 : */
1684 126 : if (NUMERIC_IS_SPECIAL(num))
1685 18 : PG_RETURN_NUMERIC(duplicate_numeric(num));
1686 :
1687 108 : init_var_from_num(num, &result);
1688 108 : floor_var(&result, &result);
1689 :
1690 108 : res = make_result(&result);
1691 108 : free_var(&result);
1692 :
1693 108 : PG_RETURN_NUMERIC(res);
1694 : }
1695 :
1696 :
1697 : /*
1698 : * generate_series_numeric() -
1699 : *
1700 : * Generate series of numeric.
1701 : */
1702 : Datum
1703 120384 : generate_series_numeric(PG_FUNCTION_ARGS)
1704 : {
1705 120384 : return generate_series_step_numeric(fcinfo);
1706 : }
1707 :
1708 : Datum
1709 120834 : generate_series_step_numeric(PG_FUNCTION_ARGS)
1710 : {
1711 : generate_series_numeric_fctx *fctx;
1712 : FuncCallContext *funcctx;
1713 : MemoryContext oldcontext;
1714 :
1715 120834 : if (SRF_IS_FIRSTCALL())
1716 : {
1717 174 : Numeric start_num = PG_GETARG_NUMERIC(0);
1718 174 : Numeric stop_num = PG_GETARG_NUMERIC(1);
1719 174 : NumericVar steploc = const_one;
1720 :
1721 : /* Reject NaN and infinities in start and stop values */
1722 174 : if (NUMERIC_IS_SPECIAL(start_num))
1723 : {
1724 12 : if (NUMERIC_IS_NAN(start_num))
1725 6 : ereport(ERROR,
1726 : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1727 : errmsg("start value cannot be NaN")));
1728 : else
1729 6 : ereport(ERROR,
1730 : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1731 : errmsg("start value cannot be infinity")));
1732 : }
1733 162 : if (NUMERIC_IS_SPECIAL(stop_num))
1734 : {
1735 12 : if (NUMERIC_IS_NAN(stop_num))
1736 6 : ereport(ERROR,
1737 : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1738 : errmsg("stop value cannot be NaN")));
1739 : else
1740 6 : ereport(ERROR,
1741 : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1742 : errmsg("stop value cannot be infinity")));
1743 : }
1744 :
1745 : /* see if we were given an explicit step size */
1746 150 : if (PG_NARGS() == 3)
1747 : {
1748 72 : Numeric step_num = PG_GETARG_NUMERIC(2);
1749 :
1750 72 : if (NUMERIC_IS_SPECIAL(step_num))
1751 : {
1752 12 : if (NUMERIC_IS_NAN(step_num))
1753 6 : ereport(ERROR,
1754 : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1755 : errmsg("step size cannot be NaN")));
1756 : else
1757 6 : ereport(ERROR,
1758 : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1759 : errmsg("step size cannot be infinity")));
1760 : }
1761 :
1762 60 : init_var_from_num(step_num, &steploc);
1763 :
1764 60 : if (cmp_var(&steploc, &const_zero) == 0)
1765 6 : ereport(ERROR,
1766 : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1767 : errmsg("step size cannot equal zero")));
1768 : }
1769 :
1770 : /* create a function context for cross-call persistence */
1771 132 : funcctx = SRF_FIRSTCALL_INIT();
1772 :
1773 : /*
1774 : * Switch to memory context appropriate for multiple function calls.
1775 : */
1776 132 : oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
1777 :
1778 : /* allocate memory for user context */
1779 : fctx = (generate_series_numeric_fctx *)
1780 132 : palloc(sizeof(generate_series_numeric_fctx));
1781 :
1782 : /*
1783 : * Use fctx to keep state from call to call. Seed current with the
1784 : * original start value. We must copy the start_num and stop_num
1785 : * values rather than pointing to them, since we may have detoasted
1786 : * them in the per-call context.
1787 : */
1788 132 : init_var(&fctx->current);
1789 132 : init_var(&fctx->stop);
1790 132 : init_var(&fctx->step);
1791 :
1792 132 : set_var_from_num(start_num, &fctx->current);
1793 132 : set_var_from_num(stop_num, &fctx->stop);
1794 132 : set_var_from_var(&steploc, &fctx->step);
1795 :
1796 132 : funcctx->user_fctx = fctx;
1797 132 : MemoryContextSwitchTo(oldcontext);
1798 : }
1799 :
1800 : /* stuff done on every call of the function */
1801 120792 : funcctx = SRF_PERCALL_SETUP();
1802 :
1803 : /*
1804 : * Get the saved state and use current state as the result of this
1805 : * iteration.
1806 : */
1807 120792 : fctx = funcctx->user_fctx;
1808 :
1809 241404 : if ((fctx->step.sign == NUMERIC_POS &&
1810 120612 : cmp_var(&fctx->current, &fctx->stop) <= 0) ||
1811 480 : (fctx->step.sign == NUMERIC_NEG &&
1812 180 : cmp_var(&fctx->current, &fctx->stop) >= 0))
1813 : {
1814 120660 : Numeric result = make_result(&fctx->current);
1815 :
1816 : /* switch to memory context appropriate for iteration calculation */
1817 120660 : oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
1818 :
1819 : /* increment current in preparation for next iteration */
1820 120660 : add_var(&fctx->current, &fctx->step, &fctx->current);
1821 120660 : MemoryContextSwitchTo(oldcontext);
1822 :
1823 : /* do when there is more left to send */
1824 120660 : SRF_RETURN_NEXT(funcctx, NumericGetDatum(result));
1825 : }
1826 : else
1827 : /* do when there is no more left */
1828 132 : SRF_RETURN_DONE(funcctx);
1829 : }
1830 :
1831 : /*
1832 : * Planner support function for generate_series(numeric, numeric [, numeric])
1833 : */
1834 : Datum
1835 486 : generate_series_numeric_support(PG_FUNCTION_ARGS)
1836 : {
1837 486 : Node *rawreq = (Node *) PG_GETARG_POINTER(0);
1838 486 : Node *ret = NULL;
1839 :
1840 486 : if (IsA(rawreq, SupportRequestRows))
1841 : {
1842 : /* Try to estimate the number of rows returned */
1843 156 : SupportRequestRows *req = (SupportRequestRows *) rawreq;
1844 :
1845 156 : if (is_funcclause(req->node)) /* be paranoid */
1846 : {
1847 156 : List *args = ((FuncExpr *) req->node)->args;
1848 : Node *arg1,
1849 : *arg2,
1850 : *arg3;
1851 :
1852 : /* We can use estimated argument values here */
1853 156 : arg1 = estimate_expression_value(req->root, linitial(args));
1854 156 : arg2 = estimate_expression_value(req->root, lsecond(args));
1855 156 : if (list_length(args) >= 3)
1856 102 : arg3 = estimate_expression_value(req->root, lthird(args));
1857 : else
1858 54 : arg3 = NULL;
1859 :
1860 : /*
1861 : * If any argument is constant NULL, we can safely assume that
1862 : * zero rows are returned. Otherwise, if they're all non-NULL
1863 : * constants, we can calculate the number of rows that will be
1864 : * returned.
1865 : */
1866 156 : if ((IsA(arg1, Const) &&
1867 150 : ((Const *) arg1)->constisnull) ||
1868 156 : (IsA(arg2, Const) &&
1869 156 : ((Const *) arg2)->constisnull) ||
1870 102 : (arg3 != NULL && IsA(arg3, Const) &&
1871 96 : ((Const *) arg3)->constisnull))
1872 : {
1873 0 : req->rows = 0;
1874 0 : ret = (Node *) req;
1875 : }
1876 156 : else if (IsA(arg1, Const) &&
1877 150 : IsA(arg2, Const) &&
1878 102 : (arg3 == NULL || IsA(arg3, Const)))
1879 : {
1880 : Numeric start_num;
1881 : Numeric stop_num;
1882 138 : NumericVar step = const_one;
1883 :
1884 : /*
1885 : * If any argument is NaN or infinity, generate_series() will
1886 : * error out, so we needn't produce an estimate.
1887 : */
1888 138 : start_num = DatumGetNumeric(((Const *) arg1)->constvalue);
1889 138 : stop_num = DatumGetNumeric(((Const *) arg2)->constvalue);
1890 :
1891 138 : if (NUMERIC_IS_SPECIAL(start_num) ||
1892 120 : NUMERIC_IS_SPECIAL(stop_num))
1893 48 : PG_RETURN_POINTER(NULL);
1894 :
1895 108 : if (arg3)
1896 : {
1897 : Numeric step_num;
1898 :
1899 66 : step_num = DatumGetNumeric(((Const *) arg3)->constvalue);
1900 :
1901 66 : if (NUMERIC_IS_SPECIAL(step_num))
1902 18 : PG_RETURN_POINTER(NULL);
1903 :
1904 48 : init_var_from_num(step_num, &step);
1905 : }
1906 :
1907 : /*
1908 : * The number of rows that will be returned is given by
1909 : * floor((stop - start) / step) + 1, if the sign of step
1910 : * matches the sign of stop - start. Otherwise, no rows will
1911 : * be returned.
1912 : */
1913 90 : if (cmp_var(&step, &const_zero) != 0)
1914 : {
1915 : NumericVar start;
1916 : NumericVar stop;
1917 : NumericVar res;
1918 :
1919 78 : init_var_from_num(start_num, &start);
1920 78 : init_var_from_num(stop_num, &stop);
1921 :
1922 78 : init_var(&res);
1923 78 : sub_var(&stop, &start, &res);
1924 :
1925 78 : if (step.sign != res.sign)
1926 : {
1927 : /* no rows will be returned */
1928 6 : req->rows = 0;
1929 6 : ret = (Node *) req;
1930 : }
1931 : else
1932 : {
1933 72 : if (arg3)
1934 30 : div_var(&res, &step, &res, 0, false, false);
1935 : else
1936 42 : trunc_var(&res, 0); /* step = 1 */
1937 :
1938 72 : req->rows = numericvar_to_double_no_overflow(&res) + 1;
1939 72 : ret = (Node *) req;
1940 : }
1941 :
1942 78 : free_var(&res);
1943 : }
1944 : }
1945 : }
1946 : }
1947 :
1948 438 : PG_RETURN_POINTER(ret);
1949 : }
1950 :
1951 :
1952 : /*
1953 : * Implements the numeric version of the width_bucket() function
1954 : * defined by SQL2003. See also width_bucket_float8().
1955 : *
1956 : * 'bound1' and 'bound2' are the lower and upper bounds of the
1957 : * histogram's range, respectively. 'count' is the number of buckets
1958 : * in the histogram. width_bucket() returns an integer indicating the
1959 : * bucket number that 'operand' belongs to in an equiwidth histogram
1960 : * with the specified characteristics. An operand smaller than the
1961 : * lower bound is assigned to bucket 0. An operand greater than or equal
1962 : * to the upper bound is assigned to an additional bucket (with number
1963 : * count+1). We don't allow the histogram bounds to be NaN or +/- infinity,
1964 : * but we do allow those values for the operand (taking NaN to be larger
1965 : * than any other value, as we do in comparisons).
1966 : */
1967 : Datum
1968 786 : width_bucket_numeric(PG_FUNCTION_ARGS)
1969 : {
1970 786 : Numeric operand = PG_GETARG_NUMERIC(0);
1971 786 : Numeric bound1 = PG_GETARG_NUMERIC(1);
1972 786 : Numeric bound2 = PG_GETARG_NUMERIC(2);
1973 786 : int32 count = PG_GETARG_INT32(3);
1974 : NumericVar count_var;
1975 : NumericVar result_var;
1976 : int32 result;
1977 :
1978 786 : if (count <= 0)
1979 12 : ereport(ERROR,
1980 : (errcode(ERRCODE_INVALID_ARGUMENT_FOR_WIDTH_BUCKET_FUNCTION),
1981 : errmsg("count must be greater than zero")));
1982 :
1983 774 : if (NUMERIC_IS_SPECIAL(bound1) || NUMERIC_IS_SPECIAL(bound2))
1984 : {
1985 24 : if (NUMERIC_IS_NAN(bound1) || NUMERIC_IS_NAN(bound2))
1986 6 : ereport(ERROR,
1987 : (errcode(ERRCODE_INVALID_ARGUMENT_FOR_WIDTH_BUCKET_FUNCTION),
1988 : errmsg("lower and upper bounds cannot be NaN")));
1989 :
1990 18 : if (NUMERIC_IS_INF(bound1) || NUMERIC_IS_INF(bound2))
1991 18 : ereport(ERROR,
1992 : (errcode(ERRCODE_INVALID_ARGUMENT_FOR_WIDTH_BUCKET_FUNCTION),
1993 : errmsg("lower and upper bounds must be finite")));
1994 : }
1995 :
1996 750 : init_var(&result_var);
1997 750 : init_var(&count_var);
1998 :
1999 : /* Convert 'count' to a numeric, for ease of use later */
2000 750 : int64_to_numericvar((int64) count, &count_var);
2001 :
2002 750 : switch (cmp_numerics(bound1, bound2))
2003 : {
2004 6 : case 0:
2005 6 : ereport(ERROR,
2006 : (errcode(ERRCODE_INVALID_ARGUMENT_FOR_WIDTH_BUCKET_FUNCTION),
2007 : errmsg("lower bound cannot equal upper bound")));
2008 : break;
2009 :
2010 : /* bound1 < bound2 */
2011 552 : case -1:
2012 552 : if (cmp_numerics(operand, bound1) < 0)
2013 114 : set_var_from_var(&const_zero, &result_var);
2014 438 : else if (cmp_numerics(operand, bound2) >= 0)
2015 114 : add_var(&count_var, &const_one, &result_var);
2016 : else
2017 324 : compute_bucket(operand, bound1, bound2, &count_var,
2018 : &result_var);
2019 552 : break;
2020 :
2021 : /* bound1 > bound2 */
2022 192 : case 1:
2023 192 : if (cmp_numerics(operand, bound1) > 0)
2024 12 : set_var_from_var(&const_zero, &result_var);
2025 180 : else if (cmp_numerics(operand, bound2) <= 0)
2026 24 : add_var(&count_var, &const_one, &result_var);
2027 : else
2028 156 : compute_bucket(operand, bound1, bound2, &count_var,
2029 : &result_var);
2030 192 : break;
2031 : }
2032 :
2033 : /* if result exceeds the range of a legal int4, we ereport here */
2034 744 : if (!numericvar_to_int32(&result_var, &result))
2035 0 : ereport(ERROR,
2036 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
2037 : errmsg("integer out of range")));
2038 :
2039 744 : free_var(&count_var);
2040 744 : free_var(&result_var);
2041 :
2042 744 : PG_RETURN_INT32(result);
2043 : }
2044 :
2045 : /*
2046 : * 'operand' is inside the bucket range, so determine the correct
2047 : * bucket for it to go in. The calculations performed by this function
2048 : * are derived directly from the SQL2003 spec. Note however that we
2049 : * multiply by count before dividing, to avoid unnecessary roundoff error.
2050 : */
2051 : static void
2052 480 : compute_bucket(Numeric operand, Numeric bound1, Numeric bound2,
2053 : const NumericVar *count_var, NumericVar *result_var)
2054 : {
2055 : NumericVar bound1_var;
2056 : NumericVar bound2_var;
2057 : NumericVar operand_var;
2058 :
2059 480 : init_var_from_num(bound1, &bound1_var);
2060 480 : init_var_from_num(bound2, &bound2_var);
2061 480 : init_var_from_num(operand, &operand_var);
2062 :
2063 : /*
2064 : * Per spec, bound1 is inclusive and bound2 is exclusive, and so we have
2065 : * bound1 <= operand < bound2 or bound1 >= operand > bound2. Either way,
2066 : * the result is ((operand - bound1) * count) / (bound2 - bound1) + 1,
2067 : * where the quotient is computed using floor division (i.e., division to
2068 : * zero decimal places with truncation), which guarantees that the result
2069 : * is in the range [1, count]. Reversing the bounds doesn't affect the
2070 : * computation, because the signs cancel out when dividing.
2071 : */
2072 480 : sub_var(&operand_var, &bound1_var, &operand_var);
2073 480 : sub_var(&bound2_var, &bound1_var, &bound2_var);
2074 :
2075 480 : mul_var(&operand_var, count_var, &operand_var,
2076 480 : operand_var.dscale + count_var->dscale);
2077 480 : div_var(&operand_var, &bound2_var, result_var, 0, false, true);
2078 480 : add_var(result_var, &const_one, result_var);
2079 :
2080 480 : free_var(&bound1_var);
2081 480 : free_var(&bound2_var);
2082 480 : free_var(&operand_var);
2083 480 : }
2084 :
2085 : /* ----------------------------------------------------------------------
2086 : *
2087 : * Comparison functions
2088 : *
2089 : * Note: btree indexes need these routines not to leak memory; therefore,
2090 : * be careful to free working copies of toasted datums. Most places don't
2091 : * need to be so careful.
2092 : *
2093 : * Sort support:
2094 : *
2095 : * We implement the sortsupport strategy routine in order to get the benefit of
2096 : * abbreviation. The ordinary numeric comparison can be quite slow as a result
2097 : * of palloc/pfree cycles (due to detoasting packed values for alignment);
2098 : * while this could be worked on itself, the abbreviation strategy gives more
2099 : * speedup in many common cases.
2100 : *
2101 : * Two different representations are used for the abbreviated form, one in
2102 : * int32 and one in int64, whichever fits into a by-value Datum. In both cases
2103 : * the representation is negated relative to the original value, because we use
2104 : * the largest negative value for NaN, which sorts higher than other values. We
2105 : * convert the absolute value of the numeric to a 31-bit or 63-bit positive
2106 : * value, and then negate it if the original number was positive.
2107 : *
2108 : * We abort the abbreviation process if the abbreviation cardinality is below
2109 : * 0.01% of the row count (1 per 10k non-null rows). The actual break-even
2110 : * point is somewhat below that, perhaps 1 per 30k (at 1 per 100k there's a
2111 : * very small penalty), but we don't want to build up too many abbreviated
2112 : * values before first testing for abort, so we take the slightly pessimistic
2113 : * number. We make no attempt to estimate the cardinality of the real values,
2114 : * since it plays no part in the cost model here (if the abbreviation is equal,
2115 : * the cost of comparing equal and unequal underlying values is comparable).
2116 : * We discontinue even checking for abort (saving us the hashing overhead) if
2117 : * the estimated cardinality gets to 100k; that would be enough to support many
2118 : * billions of rows while doing no worse than breaking even.
2119 : *
2120 : * ----------------------------------------------------------------------
2121 : */
2122 :
2123 : /*
2124 : * Sort support strategy routine.
2125 : */
2126 : Datum
2127 1136 : numeric_sortsupport(PG_FUNCTION_ARGS)
2128 : {
2129 1136 : SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0);
2130 :
2131 1136 : ssup->comparator = numeric_fast_cmp;
2132 :
2133 1136 : if (ssup->abbreviate)
2134 : {
2135 : NumericSortSupport *nss;
2136 274 : MemoryContext oldcontext = MemoryContextSwitchTo(ssup->ssup_cxt);
2137 :
2138 274 : nss = palloc(sizeof(NumericSortSupport));
2139 :
2140 : /*
2141 : * palloc a buffer for handling unaligned packed values in addition to
2142 : * the support struct
2143 : */
2144 274 : nss->buf = palloc(VARATT_SHORT_MAX + VARHDRSZ + 1);
2145 :
2146 274 : nss->input_count = 0;
2147 274 : nss->estimating = true;
2148 274 : initHyperLogLog(&nss->abbr_card, 10);
2149 :
2150 274 : ssup->ssup_extra = nss;
2151 :
2152 274 : ssup->abbrev_full_comparator = ssup->comparator;
2153 274 : ssup->comparator = numeric_cmp_abbrev;
2154 274 : ssup->abbrev_converter = numeric_abbrev_convert;
2155 274 : ssup->abbrev_abort = numeric_abbrev_abort;
2156 :
2157 274 : MemoryContextSwitchTo(oldcontext);
2158 : }
2159 :
2160 1136 : PG_RETURN_VOID();
2161 : }
2162 :
2163 : /*
2164 : * Abbreviate a numeric datum, handling NaNs and detoasting
2165 : * (must not leak memory!)
2166 : */
2167 : static Datum
2168 19170 : numeric_abbrev_convert(Datum original_datum, SortSupport ssup)
2169 : {
2170 19170 : NumericSortSupport *nss = ssup->ssup_extra;
2171 19170 : void *original_varatt = PG_DETOAST_DATUM_PACKED(original_datum);
2172 : Numeric value;
2173 : Datum result;
2174 :
2175 19170 : nss->input_count += 1;
2176 :
2177 : /*
2178 : * This is to handle packed datums without needing a palloc/pfree cycle;
2179 : * we keep and reuse a buffer large enough to handle any short datum.
2180 : */
2181 19170 : if (VARATT_IS_SHORT(original_varatt))
2182 : {
2183 1028 : void *buf = nss->buf;
2184 1028 : Size sz = VARSIZE_SHORT(original_varatt) - VARHDRSZ_SHORT;
2185 :
2186 : Assert(sz <= VARATT_SHORT_MAX - VARHDRSZ_SHORT);
2187 :
2188 1028 : SET_VARSIZE(buf, VARHDRSZ + sz);
2189 1028 : memcpy(VARDATA(buf), VARDATA_SHORT(original_varatt), sz);
2190 :
2191 1028 : value = (Numeric) buf;
2192 : }
2193 : else
2194 18142 : value = (Numeric) original_varatt;
2195 :
2196 19170 : if (NUMERIC_IS_SPECIAL(value))
2197 : {
2198 150 : if (NUMERIC_IS_PINF(value))
2199 48 : result = NUMERIC_ABBREV_PINF;
2200 102 : else if (NUMERIC_IS_NINF(value))
2201 48 : result = NUMERIC_ABBREV_NINF;
2202 : else
2203 54 : result = NUMERIC_ABBREV_NAN;
2204 : }
2205 : else
2206 : {
2207 : NumericVar var;
2208 :
2209 19020 : init_var_from_num(value, &var);
2210 :
2211 19020 : result = numeric_abbrev_convert_var(&var, nss);
2212 : }
2213 :
2214 : /* should happen only for external/compressed toasts */
2215 19170 : if ((Pointer) original_varatt != DatumGetPointer(original_datum))
2216 0 : pfree(original_varatt);
2217 :
2218 19170 : return result;
2219 : }
2220 :
2221 : /*
2222 : * Consider whether to abort abbreviation.
2223 : *
2224 : * We pay no attention to the cardinality of the non-abbreviated data. There is
2225 : * no reason to do so: unlike text, we have no fast check for equal values, so
2226 : * we pay the full overhead whenever the abbreviations are equal regardless of
2227 : * whether the underlying values are also equal.
2228 : */
2229 : static bool
2230 144 : numeric_abbrev_abort(int memtupcount, SortSupport ssup)
2231 : {
2232 144 : NumericSortSupport *nss = ssup->ssup_extra;
2233 : double abbr_card;
2234 :
2235 144 : if (memtupcount < 10000 || nss->input_count < 10000 || !nss->estimating)
2236 144 : return false;
2237 :
2238 0 : abbr_card = estimateHyperLogLog(&nss->abbr_card);
2239 :
2240 : /*
2241 : * If we have >100k distinct values, then even if we were sorting many
2242 : * billion rows we'd likely still break even, and the penalty of undoing
2243 : * that many rows of abbrevs would probably not be worth it. Stop even
2244 : * counting at that point.
2245 : */
2246 0 : if (abbr_card > 100000.0)
2247 : {
2248 0 : if (trace_sort)
2249 0 : elog(LOG,
2250 : "numeric_abbrev: estimation ends at cardinality %f"
2251 : " after " INT64_FORMAT " values (%d rows)",
2252 : abbr_card, nss->input_count, memtupcount);
2253 0 : nss->estimating = false;
2254 0 : return false;
2255 : }
2256 :
2257 : /*
2258 : * Target minimum cardinality is 1 per ~10k of non-null inputs. (The
2259 : * break even point is somewhere between one per 100k rows, where
2260 : * abbreviation has a very slight penalty, and 1 per 10k where it wins by
2261 : * a measurable percentage.) We use the relatively pessimistic 10k
2262 : * threshold, and add a 0.5 row fudge factor, because it allows us to
2263 : * abort earlier on genuinely pathological data where we've had exactly
2264 : * one abbreviated value in the first 10k (non-null) rows.
2265 : */
2266 0 : if (abbr_card < nss->input_count / 10000.0 + 0.5)
2267 : {
2268 0 : if (trace_sort)
2269 0 : elog(LOG,
2270 : "numeric_abbrev: aborting abbreviation at cardinality %f"
2271 : " below threshold %f after " INT64_FORMAT " values (%d rows)",
2272 : abbr_card, nss->input_count / 10000.0 + 0.5,
2273 : nss->input_count, memtupcount);
2274 0 : return true;
2275 : }
2276 :
2277 0 : if (trace_sort)
2278 0 : elog(LOG,
2279 : "numeric_abbrev: cardinality %f"
2280 : " after " INT64_FORMAT " values (%d rows)",
2281 : abbr_card, nss->input_count, memtupcount);
2282 :
2283 0 : return false;
2284 : }
2285 :
2286 : /*
2287 : * Non-fmgr interface to the comparison routine to allow sortsupport to elide
2288 : * the fmgr call. The saving here is small given how slow numeric comparisons
2289 : * are, but it is a required part of the sort support API when abbreviations
2290 : * are performed.
2291 : *
2292 : * Two palloc/pfree cycles could be saved here by using persistent buffers for
2293 : * aligning short-varlena inputs, but this has not so far been considered to
2294 : * be worth the effort.
2295 : */
2296 : static int
2297 17839232 : numeric_fast_cmp(Datum x, Datum y, SortSupport ssup)
2298 : {
2299 17839232 : Numeric nx = DatumGetNumeric(x);
2300 17839232 : Numeric ny = DatumGetNumeric(y);
2301 : int result;
2302 :
2303 17839232 : result = cmp_numerics(nx, ny);
2304 :
2305 17839232 : if ((Pointer) nx != DatumGetPointer(x))
2306 5713648 : pfree(nx);
2307 17839232 : if ((Pointer) ny != DatumGetPointer(y))
2308 5713642 : pfree(ny);
2309 :
2310 17839232 : return result;
2311 : }
2312 :
2313 : /*
2314 : * Compare abbreviations of values. (Abbreviations may be equal where the true
2315 : * values differ, but if the abbreviations differ, they must reflect the
2316 : * ordering of the true values.)
2317 : */
2318 : static int
2319 191326 : numeric_cmp_abbrev(Datum x, Datum y, SortSupport ssup)
2320 : {
2321 : /*
2322 : * NOTE WELL: this is intentionally backwards, because the abbreviation is
2323 : * negated relative to the original value, to handle NaN/infinity cases.
2324 : */
2325 191326 : if (DatumGetNumericAbbrev(x) < DatumGetNumericAbbrev(y))
2326 99554 : return 1;
2327 91772 : if (DatumGetNumericAbbrev(x) > DatumGetNumericAbbrev(y))
2328 91540 : return -1;
2329 232 : return 0;
2330 : }
2331 :
2332 : /*
2333 : * Abbreviate a NumericVar according to the available bit size.
2334 : *
2335 : * The 31-bit value is constructed as:
2336 : *
2337 : * 0 + 7bits digit weight + 24 bits digit value
2338 : *
2339 : * where the digit weight is in single decimal digits, not digit words, and
2340 : * stored in excess-44 representation[1]. The 24-bit digit value is the 7 most
2341 : * significant decimal digits of the value converted to binary. Values whose
2342 : * weights would fall outside the representable range are rounded off to zero
2343 : * (which is also used to represent actual zeros) or to 0x7FFFFFFF (which
2344 : * otherwise cannot occur). Abbreviation therefore fails to gain any advantage
2345 : * where values are outside the range 10^-44 to 10^83, which is not considered
2346 : * to be a serious limitation, or when values are of the same magnitude and
2347 : * equal in the first 7 decimal digits, which is considered to be an
2348 : * unavoidable limitation given the available bits. (Stealing three more bits
2349 : * to compare another digit would narrow the range of representable weights by
2350 : * a factor of 8, which starts to look like a real limiting factor.)
2351 : *
2352 : * (The value 44 for the excess is essentially arbitrary)
2353 : *
2354 : * The 63-bit value is constructed as:
2355 : *
2356 : * 0 + 7bits weight + 4 x 14-bit packed digit words
2357 : *
2358 : * The weight in this case is again stored in excess-44, but this time it is
2359 : * the original weight in digit words (i.e. powers of 10000). The first four
2360 : * digit words of the value (if present; trailing zeros are assumed as needed)
2361 : * are packed into 14 bits each to form the rest of the value. Again,
2362 : * out-of-range values are rounded off to 0 or 0x7FFFFFFFFFFFFFFF. The
2363 : * representable range in this case is 10^-176 to 10^332, which is considered
2364 : * to be good enough for all practical purposes, and comparison of 4 words
2365 : * means that at least 13 decimal digits are compared, which is considered to
2366 : * be a reasonable compromise between effectiveness and efficiency in computing
2367 : * the abbreviation.
2368 : *
2369 : * (The value 44 for the excess is even more arbitrary here, it was chosen just
2370 : * to match the value used in the 31-bit case)
2371 : *
2372 : * [1] - Excess-k representation means that the value is offset by adding 'k'
2373 : * and then treated as unsigned, so the smallest representable value is stored
2374 : * with all bits zero. This allows simple comparisons to work on the composite
2375 : * value.
2376 : */
2377 :
2378 : #if NUMERIC_ABBREV_BITS == 64
2379 :
2380 : static Datum
2381 19020 : numeric_abbrev_convert_var(const NumericVar *var, NumericSortSupport *nss)
2382 : {
2383 19020 : int ndigits = var->ndigits;
2384 19020 : int weight = var->weight;
2385 : int64 result;
2386 :
2387 19020 : if (ndigits == 0 || weight < -44)
2388 : {
2389 52 : result = 0;
2390 : }
2391 18968 : else if (weight > 83)
2392 : {
2393 12 : result = PG_INT64_MAX;
2394 : }
2395 : else
2396 : {
2397 18956 : result = ((int64) (weight + 44) << 56);
2398 :
2399 18956 : switch (ndigits)
2400 : {
2401 0 : default:
2402 0 : result |= ((int64) var->digits[3]);
2403 : /* FALLTHROUGH */
2404 6206 : case 3:
2405 6206 : result |= ((int64) var->digits[2]) << 14;
2406 : /* FALLTHROUGH */
2407 18342 : case 2:
2408 18342 : result |= ((int64) var->digits[1]) << 28;
2409 : /* FALLTHROUGH */
2410 18956 : case 1:
2411 18956 : result |= ((int64) var->digits[0]) << 42;
2412 18956 : break;
2413 : }
2414 : }
2415 :
2416 : /* the abbrev is negated relative to the original */
2417 19020 : if (var->sign == NUMERIC_POS)
2418 18922 : result = -result;
2419 :
2420 19020 : if (nss->estimating)
2421 : {
2422 19020 : uint32 tmp = ((uint32) result
2423 19020 : ^ (uint32) ((uint64) result >> 32));
2424 :
2425 19020 : addHyperLogLog(&nss->abbr_card, DatumGetUInt32(hash_uint32(tmp)));
2426 : }
2427 :
2428 19020 : return NumericAbbrevGetDatum(result);
2429 : }
2430 :
2431 : #endif /* NUMERIC_ABBREV_BITS == 64 */
2432 :
2433 : #if NUMERIC_ABBREV_BITS == 32
2434 :
2435 : static Datum
2436 : numeric_abbrev_convert_var(const NumericVar *var, NumericSortSupport *nss)
2437 : {
2438 : int ndigits = var->ndigits;
2439 : int weight = var->weight;
2440 : int32 result;
2441 :
2442 : if (ndigits == 0 || weight < -11)
2443 : {
2444 : result = 0;
2445 : }
2446 : else if (weight > 20)
2447 : {
2448 : result = PG_INT32_MAX;
2449 : }
2450 : else
2451 : {
2452 : NumericDigit nxt1 = (ndigits > 1) ? var->digits[1] : 0;
2453 :
2454 : weight = (weight + 11) * 4;
2455 :
2456 : result = var->digits[0];
2457 :
2458 : /*
2459 : * "result" now has 1 to 4 nonzero decimal digits. We pack in more
2460 : * digits to make 7 in total (largest we can fit in 24 bits)
2461 : */
2462 :
2463 : if (result > 999)
2464 : {
2465 : /* already have 4 digits, add 3 more */
2466 : result = (result * 1000) + (nxt1 / 10);
2467 : weight += 3;
2468 : }
2469 : else if (result > 99)
2470 : {
2471 : /* already have 3 digits, add 4 more */
2472 : result = (result * 10000) + nxt1;
2473 : weight += 2;
2474 : }
2475 : else if (result > 9)
2476 : {
2477 : NumericDigit nxt2 = (ndigits > 2) ? var->digits[2] : 0;
2478 :
2479 : /* already have 2 digits, add 5 more */
2480 : result = (result * 100000) + (nxt1 * 10) + (nxt2 / 1000);
2481 : weight += 1;
2482 : }
2483 : else
2484 : {
2485 : NumericDigit nxt2 = (ndigits > 2) ? var->digits[2] : 0;
2486 :
2487 : /* already have 1 digit, add 6 more */
2488 : result = (result * 1000000) + (nxt1 * 100) + (nxt2 / 100);
2489 : }
2490 :
2491 : result = result | (weight << 24);
2492 : }
2493 :
2494 : /* the abbrev is negated relative to the original */
2495 : if (var->sign == NUMERIC_POS)
2496 : result = -result;
2497 :
2498 : if (nss->estimating)
2499 : {
2500 : uint32 tmp = (uint32) result;
2501 :
2502 : addHyperLogLog(&nss->abbr_card, DatumGetUInt32(hash_uint32(tmp)));
2503 : }
2504 :
2505 : return NumericAbbrevGetDatum(result);
2506 : }
2507 :
2508 : #endif /* NUMERIC_ABBREV_BITS == 32 */
2509 :
2510 : /*
2511 : * Ordinary (non-sortsupport) comparisons follow.
2512 : */
2513 :
2514 : Datum
2515 750630 : numeric_cmp(PG_FUNCTION_ARGS)
2516 : {
2517 750630 : Numeric num1 = PG_GETARG_NUMERIC(0);
2518 750630 : Numeric num2 = PG_GETARG_NUMERIC(1);
2519 : int result;
2520 :
2521 750630 : result = cmp_numerics(num1, num2);
2522 :
2523 750630 : PG_FREE_IF_COPY(num1, 0);
2524 750630 : PG_FREE_IF_COPY(num2, 1);
2525 :
2526 750630 : PG_RETURN_INT32(result);
2527 : }
2528 :
2529 :
2530 : Datum
2531 650748 : numeric_eq(PG_FUNCTION_ARGS)
2532 : {
2533 650748 : Numeric num1 = PG_GETARG_NUMERIC(0);
2534 650748 : Numeric num2 = PG_GETARG_NUMERIC(1);
2535 : bool result;
2536 :
2537 650748 : result = cmp_numerics(num1, num2) == 0;
2538 :
2539 650748 : PG_FREE_IF_COPY(num1, 0);
2540 650748 : PG_FREE_IF_COPY(num2, 1);
2541 :
2542 650748 : PG_RETURN_BOOL(result);
2543 : }
2544 :
2545 : Datum
2546 5376 : numeric_ne(PG_FUNCTION_ARGS)
2547 : {
2548 5376 : Numeric num1 = PG_GETARG_NUMERIC(0);
2549 5376 : Numeric num2 = PG_GETARG_NUMERIC(1);
2550 : bool result;
2551 :
2552 5376 : result = cmp_numerics(num1, num2) != 0;
2553 :
2554 5376 : PG_FREE_IF_COPY(num1, 0);
2555 5376 : PG_FREE_IF_COPY(num2, 1);
2556 :
2557 5376 : PG_RETURN_BOOL(result);
2558 : }
2559 :
2560 : Datum
2561 55752 : numeric_gt(PG_FUNCTION_ARGS)
2562 : {
2563 55752 : Numeric num1 = PG_GETARG_NUMERIC(0);
2564 55752 : Numeric num2 = PG_GETARG_NUMERIC(1);
2565 : bool result;
2566 :
2567 55752 : result = cmp_numerics(num1, num2) > 0;
2568 :
2569 55752 : PG_FREE_IF_COPY(num1, 0);
2570 55752 : PG_FREE_IF_COPY(num2, 1);
2571 :
2572 55752 : PG_RETURN_BOOL(result);
2573 : }
2574 :
2575 : Datum
2576 15012 : numeric_ge(PG_FUNCTION_ARGS)
2577 : {
2578 15012 : Numeric num1 = PG_GETARG_NUMERIC(0);
2579 15012 : Numeric num2 = PG_GETARG_NUMERIC(1);
2580 : bool result;
2581 :
2582 15012 : result = cmp_numerics(num1, num2) >= 0;
2583 :
2584 15012 : PG_FREE_IF_COPY(num1, 0);
2585 15012 : PG_FREE_IF_COPY(num2, 1);
2586 :
2587 15012 : PG_RETURN_BOOL(result);
2588 : }
2589 :
2590 : Datum
2591 59798 : numeric_lt(PG_FUNCTION_ARGS)
2592 : {
2593 59798 : Numeric num1 = PG_GETARG_NUMERIC(0);
2594 59798 : Numeric num2 = PG_GETARG_NUMERIC(1);
2595 : bool result;
2596 :
2597 59798 : result = cmp_numerics(num1, num2) < 0;
2598 :
2599 59798 : PG_FREE_IF_COPY(num1, 0);
2600 59798 : PG_FREE_IF_COPY(num2, 1);
2601 :
2602 59798 : PG_RETURN_BOOL(result);
2603 : }
2604 :
2605 : Datum
2606 16888 : numeric_le(PG_FUNCTION_ARGS)
2607 : {
2608 16888 : Numeric num1 = PG_GETARG_NUMERIC(0);
2609 16888 : Numeric num2 = PG_GETARG_NUMERIC(1);
2610 : bool result;
2611 :
2612 16888 : result = cmp_numerics(num1, num2) <= 0;
2613 :
2614 16888 : PG_FREE_IF_COPY(num1, 0);
2615 16888 : PG_FREE_IF_COPY(num2, 1);
2616 :
2617 16888 : PG_RETURN_BOOL(result);
2618 : }
2619 :
2620 : static int
2621 19414976 : cmp_numerics(Numeric num1, Numeric num2)
2622 : {
2623 : int result;
2624 :
2625 : /*
2626 : * We consider all NANs to be equal and larger than any non-NAN (including
2627 : * Infinity). This is somewhat arbitrary; the important thing is to have
2628 : * a consistent sort order.
2629 : */
2630 19414976 : if (NUMERIC_IS_SPECIAL(num1))
2631 : {
2632 6236 : if (NUMERIC_IS_NAN(num1))
2633 : {
2634 6146 : if (NUMERIC_IS_NAN(num2))
2635 748 : result = 0; /* NAN = NAN */
2636 : else
2637 5398 : result = 1; /* NAN > non-NAN */
2638 : }
2639 90 : else if (NUMERIC_IS_PINF(num1))
2640 : {
2641 72 : if (NUMERIC_IS_NAN(num2))
2642 0 : result = -1; /* PINF < NAN */
2643 72 : else if (NUMERIC_IS_PINF(num2))
2644 6 : result = 0; /* PINF = PINF */
2645 : else
2646 66 : result = 1; /* PINF > anything else */
2647 : }
2648 : else /* num1 must be NINF */
2649 : {
2650 18 : if (NUMERIC_IS_NINF(num2))
2651 6 : result = 0; /* NINF = NINF */
2652 : else
2653 12 : result = -1; /* NINF < anything else */
2654 : }
2655 : }
2656 19408740 : else if (NUMERIC_IS_SPECIAL(num2))
2657 : {
2658 11156 : if (NUMERIC_IS_NINF(num2))
2659 12 : result = 1; /* normal > NINF */
2660 : else
2661 11144 : result = -1; /* normal < NAN or PINF */
2662 : }
2663 : else
2664 : {
2665 38796196 : result = cmp_var_common(NUMERIC_DIGITS(num1), NUMERIC_NDIGITS(num1),
2666 19397886 : NUMERIC_WEIGHT(num1), NUMERIC_SIGN(num1),
2667 19397584 : NUMERIC_DIGITS(num2), NUMERIC_NDIGITS(num2),
2668 19398310 : NUMERIC_WEIGHT(num2), NUMERIC_SIGN(num2));
2669 : }
2670 :
2671 19414976 : return result;
2672 : }
2673 :
2674 : /*
2675 : * in_range support function for numeric.
2676 : */
2677 : Datum
2678 1152 : in_range_numeric_numeric(PG_FUNCTION_ARGS)
2679 : {
2680 1152 : Numeric val = PG_GETARG_NUMERIC(0);
2681 1152 : Numeric base = PG_GETARG_NUMERIC(1);
2682 1152 : Numeric offset = PG_GETARG_NUMERIC(2);
2683 1152 : bool sub = PG_GETARG_BOOL(3);
2684 1152 : bool less = PG_GETARG_BOOL(4);
2685 : bool result;
2686 :
2687 : /*
2688 : * Reject negative (including -Inf) or NaN offset. Negative is per spec,
2689 : * and NaN is because appropriate semantics for that seem non-obvious.
2690 : */
2691 1152 : if (NUMERIC_IS_NAN(offset) ||
2692 1146 : NUMERIC_IS_NINF(offset) ||
2693 1146 : NUMERIC_SIGN(offset) == NUMERIC_NEG)
2694 6 : ereport(ERROR,
2695 : (errcode(ERRCODE_INVALID_PRECEDING_OR_FOLLOWING_SIZE),
2696 : errmsg("invalid preceding or following size in window function")));
2697 :
2698 : /*
2699 : * Deal with cases where val and/or base is NaN, following the rule that
2700 : * NaN sorts after non-NaN (cf cmp_numerics). The offset cannot affect
2701 : * the conclusion.
2702 : */
2703 1146 : if (NUMERIC_IS_NAN(val))
2704 : {
2705 186 : if (NUMERIC_IS_NAN(base))
2706 60 : result = true; /* NAN = NAN */
2707 : else
2708 126 : result = !less; /* NAN > non-NAN */
2709 : }
2710 960 : else if (NUMERIC_IS_NAN(base))
2711 : {
2712 126 : result = less; /* non-NAN < NAN */
2713 : }
2714 :
2715 : /*
2716 : * Deal with infinite offset (necessarily +Inf, at this point).
2717 : */
2718 834 : else if (NUMERIC_IS_SPECIAL(offset))
2719 : {
2720 : Assert(NUMERIC_IS_PINF(offset));
2721 420 : if (sub ? NUMERIC_IS_PINF(base) : NUMERIC_IS_NINF(base))
2722 : {
2723 : /*
2724 : * base +/- offset would produce NaN, so return true for any val
2725 : * (see in_range_float8_float8() for reasoning).
2726 : */
2727 174 : result = true;
2728 : }
2729 246 : else if (sub)
2730 : {
2731 : /* base - offset must be -inf */
2732 150 : if (less)
2733 54 : result = NUMERIC_IS_NINF(val); /* only -inf is <= sum */
2734 : else
2735 96 : result = true; /* any val is >= sum */
2736 : }
2737 : else
2738 : {
2739 : /* base + offset must be +inf */
2740 96 : if (less)
2741 0 : result = true; /* any val is <= sum */
2742 : else
2743 96 : result = NUMERIC_IS_PINF(val); /* only +inf is >= sum */
2744 : }
2745 : }
2746 :
2747 : /*
2748 : * Deal with cases where val and/or base is infinite. The offset, being
2749 : * now known finite, cannot affect the conclusion.
2750 : */
2751 414 : else if (NUMERIC_IS_SPECIAL(val))
2752 : {
2753 78 : if (NUMERIC_IS_PINF(val))
2754 : {
2755 36 : if (NUMERIC_IS_PINF(base))
2756 24 : result = true; /* PINF = PINF */
2757 : else
2758 12 : result = !less; /* PINF > any other non-NAN */
2759 : }
2760 : else /* val must be NINF */
2761 : {
2762 42 : if (NUMERIC_IS_NINF(base))
2763 30 : result = true; /* NINF = NINF */
2764 : else
2765 12 : result = less; /* NINF < anything else */
2766 : }
2767 : }
2768 336 : else if (NUMERIC_IS_SPECIAL(base))
2769 : {
2770 24 : if (NUMERIC_IS_NINF(base))
2771 12 : result = !less; /* normal > NINF */
2772 : else
2773 12 : result = less; /* normal < PINF */
2774 : }
2775 : else
2776 : {
2777 : /*
2778 : * Otherwise go ahead and compute base +/- offset. While it's
2779 : * possible for this to overflow the numeric format, it's unlikely
2780 : * enough that we don't take measures to prevent it.
2781 : */
2782 : NumericVar valv;
2783 : NumericVar basev;
2784 : NumericVar offsetv;
2785 : NumericVar sum;
2786 :
2787 312 : init_var_from_num(val, &valv);
2788 312 : init_var_from_num(base, &basev);
2789 312 : init_var_from_num(offset, &offsetv);
2790 312 : init_var(&sum);
2791 :
2792 312 : if (sub)
2793 156 : sub_var(&basev, &offsetv, &sum);
2794 : else
2795 156 : add_var(&basev, &offsetv, &sum);
2796 :
2797 312 : if (less)
2798 156 : result = (cmp_var(&valv, &sum) <= 0);
2799 : else
2800 156 : result = (cmp_var(&valv, &sum) >= 0);
2801 :
2802 312 : free_var(&sum);
2803 : }
2804 :
2805 1146 : PG_FREE_IF_COPY(val, 0);
2806 1146 : PG_FREE_IF_COPY(base, 1);
2807 1146 : PG_FREE_IF_COPY(offset, 2);
2808 :
2809 1146 : PG_RETURN_BOOL(result);
2810 : }
2811 :
2812 : Datum
2813 607746 : hash_numeric(PG_FUNCTION_ARGS)
2814 : {
2815 607746 : Numeric key = PG_GETARG_NUMERIC(0);
2816 : Datum digit_hash;
2817 : Datum result;
2818 : int weight;
2819 : int start_offset;
2820 : int end_offset;
2821 : int i;
2822 : int hash_len;
2823 : NumericDigit *digits;
2824 :
2825 : /* If it's NaN or infinity, don't try to hash the rest of the fields */
2826 607746 : if (NUMERIC_IS_SPECIAL(key))
2827 0 : PG_RETURN_UINT32(0);
2828 :
2829 607746 : weight = NUMERIC_WEIGHT(key);
2830 607746 : start_offset = 0;
2831 607746 : end_offset = 0;
2832 :
2833 : /*
2834 : * Omit any leading or trailing zeros from the input to the hash. The
2835 : * numeric implementation *should* guarantee that leading and trailing
2836 : * zeros are suppressed, but we're paranoid. Note that we measure the
2837 : * starting and ending offsets in units of NumericDigits, not bytes.
2838 : */
2839 607746 : digits = NUMERIC_DIGITS(key);
2840 607746 : for (i = 0; i < NUMERIC_NDIGITS(key); i++)
2841 : {
2842 606124 : if (digits[i] != (NumericDigit) 0)
2843 606124 : break;
2844 :
2845 0 : start_offset++;
2846 :
2847 : /*
2848 : * The weight is effectively the # of digits before the decimal point,
2849 : * so decrement it for each leading zero we skip.
2850 : */
2851 0 : weight--;
2852 : }
2853 :
2854 : /*
2855 : * If there are no non-zero digits, then the value of the number is zero,
2856 : * regardless of any other fields.
2857 : */
2858 607746 : if (NUMERIC_NDIGITS(key) == start_offset)
2859 1622 : PG_RETURN_UINT32(-1);
2860 :
2861 606124 : for (i = NUMERIC_NDIGITS(key) - 1; i >= 0; i--)
2862 : {
2863 606124 : if (digits[i] != (NumericDigit) 0)
2864 606124 : break;
2865 :
2866 0 : end_offset++;
2867 : }
2868 :
2869 : /* If we get here, there should be at least one non-zero digit */
2870 : Assert(start_offset + end_offset < NUMERIC_NDIGITS(key));
2871 :
2872 : /*
2873 : * Note that we don't hash on the Numeric's scale, since two numerics can
2874 : * compare equal but have different scales. We also don't hash on the
2875 : * sign, although we could: since a sign difference implies inequality,
2876 : * this shouldn't affect correctness.
2877 : */
2878 606124 : hash_len = NUMERIC_NDIGITS(key) - start_offset - end_offset;
2879 606124 : digit_hash = hash_any((unsigned char *) (NUMERIC_DIGITS(key) + start_offset),
2880 : hash_len * sizeof(NumericDigit));
2881 :
2882 : /* Mix in the weight, via XOR */
2883 606124 : result = digit_hash ^ weight;
2884 :
2885 606124 : PG_RETURN_DATUM(result);
2886 : }
2887 :
2888 : /*
2889 : * Returns 64-bit value by hashing a value to a 64-bit value, with a seed.
2890 : * Otherwise, similar to hash_numeric.
2891 : */
2892 : Datum
2893 84 : hash_numeric_extended(PG_FUNCTION_ARGS)
2894 : {
2895 84 : Numeric key = PG_GETARG_NUMERIC(0);
2896 84 : uint64 seed = PG_GETARG_INT64(1);
2897 : Datum digit_hash;
2898 : Datum result;
2899 : int weight;
2900 : int start_offset;
2901 : int end_offset;
2902 : int i;
2903 : int hash_len;
2904 : NumericDigit *digits;
2905 :
2906 : /* If it's NaN or infinity, don't try to hash the rest of the fields */
2907 84 : if (NUMERIC_IS_SPECIAL(key))
2908 0 : PG_RETURN_UINT64(seed);
2909 :
2910 84 : weight = NUMERIC_WEIGHT(key);
2911 84 : start_offset = 0;
2912 84 : end_offset = 0;
2913 :
2914 84 : digits = NUMERIC_DIGITS(key);
2915 84 : for (i = 0; i < NUMERIC_NDIGITS(key); i++)
2916 : {
2917 72 : if (digits[i] != (NumericDigit) 0)
2918 72 : break;
2919 :
2920 0 : start_offset++;
2921 :
2922 0 : weight--;
2923 : }
2924 :
2925 84 : if (NUMERIC_NDIGITS(key) == start_offset)
2926 12 : PG_RETURN_UINT64(seed - 1);
2927 :
2928 72 : for (i = NUMERIC_NDIGITS(key) - 1; i >= 0; i--)
2929 : {
2930 72 : if (digits[i] != (NumericDigit) 0)
2931 72 : break;
2932 :
2933 0 : end_offset++;
2934 : }
2935 :
2936 : Assert(start_offset + end_offset < NUMERIC_NDIGITS(key));
2937 :
2938 72 : hash_len = NUMERIC_NDIGITS(key) - start_offset - end_offset;
2939 72 : digit_hash = hash_any_extended((unsigned char *) (NUMERIC_DIGITS(key)
2940 72 : + start_offset),
2941 : hash_len * sizeof(NumericDigit),
2942 : seed);
2943 :
2944 72 : result = UInt64GetDatum(DatumGetUInt64(digit_hash) ^ weight);
2945 :
2946 72 : PG_RETURN_DATUM(result);
2947 : }
2948 :
2949 :
2950 : /* ----------------------------------------------------------------------
2951 : *
2952 : * Basic arithmetic functions
2953 : *
2954 : * ----------------------------------------------------------------------
2955 : */
2956 :
2957 :
2958 : /*
2959 : * numeric_add() -
2960 : *
2961 : * Add two numerics
2962 : */
2963 : Datum
2964 252178 : numeric_add(PG_FUNCTION_ARGS)
2965 : {
2966 252178 : Numeric num1 = PG_GETARG_NUMERIC(0);
2967 252178 : Numeric num2 = PG_GETARG_NUMERIC(1);
2968 : Numeric res;
2969 :
2970 252178 : res = numeric_add_opt_error(num1, num2, NULL);
2971 :
2972 252178 : PG_RETURN_NUMERIC(res);
2973 : }
2974 :
2975 : /*
2976 : * numeric_add_opt_error() -
2977 : *
2978 : * Internal version of numeric_add(). If "*have_error" flag is provided,
2979 : * on error it's set to true, NULL returned. This is helpful when caller
2980 : * need to handle errors by itself.
2981 : */
2982 : Numeric
2983 253216 : numeric_add_opt_error(Numeric num1, Numeric num2, bool *have_error)
2984 : {
2985 : NumericVar arg1;
2986 : NumericVar arg2;
2987 : NumericVar result;
2988 : Numeric res;
2989 :
2990 : /*
2991 : * Handle NaN and infinities
2992 : */
2993 253216 : if (NUMERIC_IS_SPECIAL(num1) || NUMERIC_IS_SPECIAL(num2))
2994 : {
2995 198 : if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
2996 78 : return make_result(&const_nan);
2997 120 : if (NUMERIC_IS_PINF(num1))
2998 : {
2999 36 : if (NUMERIC_IS_NINF(num2))
3000 6 : return make_result(&const_nan); /* Inf + -Inf */
3001 : else
3002 30 : return make_result(&const_pinf);
3003 : }
3004 84 : if (NUMERIC_IS_NINF(num1))
3005 : {
3006 36 : if (NUMERIC_IS_PINF(num2))
3007 6 : return make_result(&const_nan); /* -Inf + Inf */
3008 : else
3009 30 : return make_result(&const_ninf);
3010 : }
3011 : /* by here, num1 must be finite, so num2 is not */
3012 48 : if (NUMERIC_IS_PINF(num2))
3013 24 : return make_result(&const_pinf);
3014 : Assert(NUMERIC_IS_NINF(num2));
3015 24 : return make_result(&const_ninf);
3016 : }
3017 :
3018 : /*
3019 : * Unpack the values, let add_var() compute the result and return it.
3020 : */
3021 253018 : init_var_from_num(num1, &arg1);
3022 253018 : init_var_from_num(num2, &arg2);
3023 :
3024 253018 : init_var(&result);
3025 253018 : add_var(&arg1, &arg2, &result);
3026 :
3027 253018 : res = make_result_opt_error(&result, have_error);
3028 :
3029 253018 : free_var(&result);
3030 :
3031 253018 : return res;
3032 : }
3033 :
3034 :
3035 : /*
3036 : * numeric_sub() -
3037 : *
3038 : * Subtract one numeric from another
3039 : */
3040 : Datum
3041 75764 : numeric_sub(PG_FUNCTION_ARGS)
3042 : {
3043 75764 : Numeric num1 = PG_GETARG_NUMERIC(0);
3044 75764 : Numeric num2 = PG_GETARG_NUMERIC(1);
3045 : Numeric res;
3046 :
3047 75764 : res = numeric_sub_opt_error(num1, num2, NULL);
3048 :
3049 75764 : PG_RETURN_NUMERIC(res);
3050 : }
3051 :
3052 :
3053 : /*
3054 : * numeric_sub_opt_error() -
3055 : *
3056 : * Internal version of numeric_sub(). If "*have_error" flag is provided,
3057 : * on error it's set to true, NULL returned. This is helpful when caller
3058 : * need to handle errors by itself.
3059 : */
3060 : Numeric
3061 75914 : numeric_sub_opt_error(Numeric num1, Numeric num2, bool *have_error)
3062 : {
3063 : NumericVar arg1;
3064 : NumericVar arg2;
3065 : NumericVar result;
3066 : Numeric res;
3067 :
3068 : /*
3069 : * Handle NaN and infinities
3070 : */
3071 75914 : if (NUMERIC_IS_SPECIAL(num1) || NUMERIC_IS_SPECIAL(num2))
3072 : {
3073 198 : if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
3074 78 : return make_result(&const_nan);
3075 120 : if (NUMERIC_IS_PINF(num1))
3076 : {
3077 36 : if (NUMERIC_IS_PINF(num2))
3078 6 : return make_result(&const_nan); /* Inf - Inf */
3079 : else
3080 30 : return make_result(&const_pinf);
3081 : }
3082 84 : if (NUMERIC_IS_NINF(num1))
3083 : {
3084 36 : if (NUMERIC_IS_NINF(num2))
3085 6 : return make_result(&const_nan); /* -Inf - -Inf */
3086 : else
3087 30 : return make_result(&const_ninf);
3088 : }
3089 : /* by here, num1 must be finite, so num2 is not */
3090 48 : if (NUMERIC_IS_PINF(num2))
3091 24 : return make_result(&const_ninf);
3092 : Assert(NUMERIC_IS_NINF(num2));
3093 24 : return make_result(&const_pinf);
3094 : }
3095 :
3096 : /*
3097 : * Unpack the values, let sub_var() compute the result and return it.
3098 : */
3099 75716 : init_var_from_num(num1, &arg1);
3100 75716 : init_var_from_num(num2, &arg2);
3101 :
3102 75716 : init_var(&result);
3103 75716 : sub_var(&arg1, &arg2, &result);
3104 :
3105 75716 : res = make_result_opt_error(&result, have_error);
3106 :
3107 75716 : free_var(&result);
3108 :
3109 75716 : return res;
3110 : }
3111 :
3112 :
3113 : /*
3114 : * numeric_mul() -
3115 : *
3116 : * Calculate the product of two numerics
3117 : */
3118 : Datum
3119 489704 : numeric_mul(PG_FUNCTION_ARGS)
3120 : {
3121 489704 : Numeric num1 = PG_GETARG_NUMERIC(0);
3122 489704 : Numeric num2 = PG_GETARG_NUMERIC(1);
3123 : Numeric res;
3124 :
3125 489704 : res = numeric_mul_opt_error(num1, num2, NULL);
3126 :
3127 489704 : PG_RETURN_NUMERIC(res);
3128 : }
3129 :
3130 :
3131 : /*
3132 : * numeric_mul_opt_error() -
3133 : *
3134 : * Internal version of numeric_mul(). If "*have_error" flag is provided,
3135 : * on error it's set to true, NULL returned. This is helpful when caller
3136 : * need to handle errors by itself.
3137 : */
3138 : Numeric
3139 489740 : numeric_mul_opt_error(Numeric num1, Numeric num2, bool *have_error)
3140 : {
3141 : NumericVar arg1;
3142 : NumericVar arg2;
3143 : NumericVar result;
3144 : Numeric res;
3145 :
3146 : /*
3147 : * Handle NaN and infinities
3148 : */
3149 489740 : if (NUMERIC_IS_SPECIAL(num1) || NUMERIC_IS_SPECIAL(num2))
3150 : {
3151 198 : if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
3152 78 : return make_result(&const_nan);
3153 120 : if (NUMERIC_IS_PINF(num1))
3154 : {
3155 36 : switch (numeric_sign_internal(num2))
3156 : {
3157 6 : case 0:
3158 6 : return make_result(&const_nan); /* Inf * 0 */
3159 18 : case 1:
3160 18 : return make_result(&const_pinf);
3161 12 : case -1:
3162 12 : return make_result(&const_ninf);
3163 : }
3164 : Assert(false);
3165 : }
3166 84 : if (NUMERIC_IS_NINF(num1))
3167 : {
3168 36 : switch (numeric_sign_internal(num2))
3169 : {
3170 6 : case 0:
3171 6 : return make_result(&const_nan); /* -Inf * 0 */
3172 18 : case 1:
3173 18 : return make_result(&const_ninf);
3174 12 : case -1:
3175 12 : return make_result(&const_pinf);
3176 : }
3177 : Assert(false);
3178 : }
3179 : /* by here, num1 must be finite, so num2 is not */
3180 48 : if (NUMERIC_IS_PINF(num2))
3181 : {
3182 24 : switch (numeric_sign_internal(num1))
3183 : {
3184 6 : case 0:
3185 6 : return make_result(&const_nan); /* 0 * Inf */
3186 12 : case 1:
3187 12 : return make_result(&const_pinf);
3188 6 : case -1:
3189 6 : return make_result(&const_ninf);
3190 : }
3191 : Assert(false);
3192 : }
3193 : Assert(NUMERIC_IS_NINF(num2));
3194 24 : switch (numeric_sign_internal(num1))
3195 : {
3196 6 : case 0:
3197 6 : return make_result(&const_nan); /* 0 * -Inf */
3198 12 : case 1:
3199 12 : return make_result(&const_ninf);
3200 6 : case -1:
3201 6 : return make_result(&const_pinf);
3202 : }
3203 : Assert(false);
3204 : }
3205 :
3206 : /*
3207 : * Unpack the values, let mul_var() compute the result and return it.
3208 : * Unlike add_var() and sub_var(), mul_var() will round its result. In the
3209 : * case of numeric_mul(), which is invoked for the * operator on numerics,
3210 : * we request exact representation for the product (rscale = sum(dscale of
3211 : * arg1, dscale of arg2)). If the exact result has more digits after the
3212 : * decimal point than can be stored in a numeric, we round it. Rounding
3213 : * after computing the exact result ensures that the final result is
3214 : * correctly rounded (rounding in mul_var() using a truncated product
3215 : * would not guarantee this).
3216 : */
3217 489542 : init_var_from_num(num1, &arg1);
3218 489542 : init_var_from_num(num2, &arg2);
3219 :
3220 489542 : init_var(&result);
3221 489542 : mul_var(&arg1, &arg2, &result, arg1.dscale + arg2.dscale);
3222 :
3223 489542 : if (result.dscale > NUMERIC_DSCALE_MAX)
3224 6 : round_var(&result, NUMERIC_DSCALE_MAX);
3225 :
3226 489542 : res = make_result_opt_error(&result, have_error);
3227 :
3228 489542 : free_var(&result);
3229 :
3230 489542 : return res;
3231 : }
3232 :
3233 :
3234 : /*
3235 : * numeric_div() -
3236 : *
3237 : * Divide one numeric into another
3238 : */
3239 : Datum
3240 148258 : numeric_div(PG_FUNCTION_ARGS)
3241 : {
3242 148258 : Numeric num1 = PG_GETARG_NUMERIC(0);
3243 148258 : Numeric num2 = PG_GETARG_NUMERIC(1);
3244 : Numeric res;
3245 :
3246 148258 : res = numeric_div_opt_error(num1, num2, NULL);
3247 :
3248 148226 : PG_RETURN_NUMERIC(res);
3249 : }
3250 :
3251 :
3252 : /*
3253 : * numeric_div_opt_error() -
3254 : *
3255 : * Internal version of numeric_div(). If "*have_error" flag is provided,
3256 : * on error it's set to true, NULL returned. This is helpful when caller
3257 : * need to handle errors by itself.
3258 : */
3259 : Numeric
3260 149098 : numeric_div_opt_error(Numeric num1, Numeric num2, bool *have_error)
3261 : {
3262 : NumericVar arg1;
3263 : NumericVar arg2;
3264 : NumericVar result;
3265 : Numeric res;
3266 : int rscale;
3267 :
3268 149098 : if (have_error)
3269 48 : *have_error = false;
3270 :
3271 : /*
3272 : * Handle NaN and infinities
3273 : */
3274 149098 : if (NUMERIC_IS_SPECIAL(num1) || NUMERIC_IS_SPECIAL(num2))
3275 : {
3276 198 : if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
3277 78 : return make_result(&const_nan);
3278 120 : if (NUMERIC_IS_PINF(num1))
3279 : {
3280 36 : if (NUMERIC_IS_SPECIAL(num2))
3281 12 : return make_result(&const_nan); /* Inf / [-]Inf */
3282 24 : switch (numeric_sign_internal(num2))
3283 : {
3284 6 : case 0:
3285 6 : if (have_error)
3286 : {
3287 0 : *have_error = true;
3288 0 : return NULL;
3289 : }
3290 6 : ereport(ERROR,
3291 : (errcode(ERRCODE_DIVISION_BY_ZERO),
3292 : errmsg("division by zero")));
3293 : break;
3294 12 : case 1:
3295 12 : return make_result(&const_pinf);
3296 6 : case -1:
3297 6 : return make_result(&const_ninf);
3298 : }
3299 : Assert(false);
3300 : }
3301 84 : if (NUMERIC_IS_NINF(num1))
3302 : {
3303 36 : if (NUMERIC_IS_SPECIAL(num2))
3304 12 : return make_result(&const_nan); /* -Inf / [-]Inf */
3305 24 : switch (numeric_sign_internal(num2))
3306 : {
3307 6 : case 0:
3308 6 : if (have_error)
3309 : {
3310 0 : *have_error = true;
3311 0 : return NULL;
3312 : }
3313 6 : ereport(ERROR,
3314 : (errcode(ERRCODE_DIVISION_BY_ZERO),
3315 : errmsg("division by zero")));
3316 : break;
3317 12 : case 1:
3318 12 : return make_result(&const_ninf);
3319 6 : case -1:
3320 6 : return make_result(&const_pinf);
3321 : }
3322 : Assert(false);
3323 : }
3324 : /* by here, num1 must be finite, so num2 is not */
3325 :
3326 : /*
3327 : * POSIX would have us return zero or minus zero if num1 is zero, and
3328 : * otherwise throw an underflow error. But the numeric type doesn't
3329 : * really do underflow, so let's just return zero.
3330 : */
3331 48 : return make_result(&const_zero);
3332 : }
3333 :
3334 : /*
3335 : * Unpack the arguments
3336 : */
3337 148900 : init_var_from_num(num1, &arg1);
3338 148900 : init_var_from_num(num2, &arg2);
3339 :
3340 148900 : init_var(&result);
3341 :
3342 : /*
3343 : * Select scale for division result
3344 : */
3345 148900 : rscale = select_div_scale(&arg1, &arg2);
3346 :
3347 : /*
3348 : * If "have_error" is provided, check for division by zero here
3349 : */
3350 148900 : if (have_error && (arg2.ndigits == 0 || arg2.digits[0] == 0))
3351 : {
3352 12 : *have_error = true;
3353 12 : return NULL;
3354 : }
3355 :
3356 : /*
3357 : * Do the divide and return the result
3358 : */
3359 148888 : div_var(&arg1, &arg2, &result, rscale, true, true);
3360 :
3361 148850 : res = make_result_opt_error(&result, have_error);
3362 :
3363 148850 : free_var(&result);
3364 :
3365 148850 : return res;
3366 : }
3367 :
3368 :
3369 : /*
3370 : * numeric_div_trunc() -
3371 : *
3372 : * Divide one numeric into another, truncating the result to an integer
3373 : */
3374 : Datum
3375 1218 : numeric_div_trunc(PG_FUNCTION_ARGS)
3376 : {
3377 1218 : Numeric num1 = PG_GETARG_NUMERIC(0);
3378 1218 : Numeric num2 = PG_GETARG_NUMERIC(1);
3379 : NumericVar arg1;
3380 : NumericVar arg2;
3381 : NumericVar result;
3382 : Numeric res;
3383 :
3384 : /*
3385 : * Handle NaN and infinities
3386 : */
3387 1218 : if (NUMERIC_IS_SPECIAL(num1) || NUMERIC_IS_SPECIAL(num2))
3388 : {
3389 198 : if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
3390 78 : PG_RETURN_NUMERIC(make_result(&const_nan));
3391 120 : if (NUMERIC_IS_PINF(num1))
3392 : {
3393 36 : if (NUMERIC_IS_SPECIAL(num2))
3394 12 : PG_RETURN_NUMERIC(make_result(&const_nan)); /* Inf / [-]Inf */
3395 24 : switch (numeric_sign_internal(num2))
3396 : {
3397 6 : case 0:
3398 6 : ereport(ERROR,
3399 : (errcode(ERRCODE_DIVISION_BY_ZERO),
3400 : errmsg("division by zero")));
3401 : break;
3402 12 : case 1:
3403 12 : PG_RETURN_NUMERIC(make_result(&const_pinf));
3404 6 : case -1:
3405 6 : PG_RETURN_NUMERIC(make_result(&const_ninf));
3406 : }
3407 : Assert(false);
3408 : }
3409 84 : if (NUMERIC_IS_NINF(num1))
3410 : {
3411 36 : if (NUMERIC_IS_SPECIAL(num2))
3412 12 : PG_RETURN_NUMERIC(make_result(&const_nan)); /* -Inf / [-]Inf */
3413 24 : switch (numeric_sign_internal(num2))
3414 : {
3415 6 : case 0:
3416 6 : ereport(ERROR,
3417 : (errcode(ERRCODE_DIVISION_BY_ZERO),
3418 : errmsg("division by zero")));
3419 : break;
3420 12 : case 1:
3421 12 : PG_RETURN_NUMERIC(make_result(&const_ninf));
3422 6 : case -1:
3423 6 : PG_RETURN_NUMERIC(make_result(&const_pinf));
3424 : }
3425 : Assert(false);
3426 : }
3427 : /* by here, num1 must be finite, so num2 is not */
3428 :
3429 : /*
3430 : * POSIX would have us return zero or minus zero if num1 is zero, and
3431 : * otherwise throw an underflow error. But the numeric type doesn't
3432 : * really do underflow, so let's just return zero.
3433 : */
3434 48 : PG_RETURN_NUMERIC(make_result(&const_zero));
3435 : }
3436 :
3437 : /*
3438 : * Unpack the arguments
3439 : */
3440 1020 : init_var_from_num(num1, &arg1);
3441 1020 : init_var_from_num(num2, &arg2);
3442 :
3443 1020 : init_var(&result);
3444 :
3445 : /*
3446 : * Do the divide and return the result
3447 : */
3448 1020 : div_var(&arg1, &arg2, &result, 0, false, true);
3449 :
3450 1014 : res = make_result(&result);
3451 :
3452 1014 : free_var(&result);
3453 :
3454 1014 : PG_RETURN_NUMERIC(res);
3455 : }
3456 :
3457 :
3458 : /*
3459 : * numeric_mod() -
3460 : *
3461 : * Calculate the modulo of two numerics
3462 : */
3463 : Datum
3464 413382 : numeric_mod(PG_FUNCTION_ARGS)
3465 : {
3466 413382 : Numeric num1 = PG_GETARG_NUMERIC(0);
3467 413382 : Numeric num2 = PG_GETARG_NUMERIC(1);
3468 : Numeric res;
3469 :
3470 413382 : res = numeric_mod_opt_error(num1, num2, NULL);
3471 :
3472 413364 : PG_RETURN_NUMERIC(res);
3473 : }
3474 :
3475 :
3476 : /*
3477 : * numeric_mod_opt_error() -
3478 : *
3479 : * Internal version of numeric_mod(). If "*have_error" flag is provided,
3480 : * on error it's set to true, NULL returned. This is helpful when caller
3481 : * need to handle errors by itself.
3482 : */
3483 : Numeric
3484 413394 : numeric_mod_opt_error(Numeric num1, Numeric num2, bool *have_error)
3485 : {
3486 : Numeric res;
3487 : NumericVar arg1;
3488 : NumericVar arg2;
3489 : NumericVar result;
3490 :
3491 413394 : if (have_error)
3492 0 : *have_error = false;
3493 :
3494 : /*
3495 : * Handle NaN and infinities. We follow POSIX fmod() on this, except that
3496 : * POSIX treats x-is-infinite and y-is-zero identically, raising EDOM and
3497 : * returning NaN. We choose to throw error only for y-is-zero.
3498 : */
3499 413394 : if (NUMERIC_IS_SPECIAL(num1) || NUMERIC_IS_SPECIAL(num2))
3500 : {
3501 198 : if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
3502 78 : return make_result(&const_nan);
3503 120 : if (NUMERIC_IS_INF(num1))
3504 : {
3505 72 : if (numeric_sign_internal(num2) == 0)
3506 : {
3507 12 : if (have_error)
3508 : {
3509 0 : *have_error = true;
3510 0 : return NULL;
3511 : }
3512 12 : ereport(ERROR,
3513 : (errcode(ERRCODE_DIVISION_BY_ZERO),
3514 : errmsg("division by zero")));
3515 : }
3516 : /* Inf % any nonzero = NaN */
3517 60 : return make_result(&const_nan);
3518 : }
3519 : /* num2 must be [-]Inf; result is num1 regardless of sign of num2 */
3520 48 : return duplicate_numeric(num1);
3521 : }
3522 :
3523 413196 : init_var_from_num(num1, &arg1);
3524 413196 : init_var_from_num(num2, &arg2);
3525 :
3526 413196 : init_var(&result);
3527 :
3528 : /*
3529 : * If "have_error" is provided, check for division by zero here
3530 : */
3531 413196 : if (have_error && (arg2.ndigits == 0 || arg2.digits[0] == 0))
3532 : {
3533 0 : *have_error = true;
3534 0 : return NULL;
3535 : }
3536 :
3537 413196 : mod_var(&arg1, &arg2, &result);
3538 :
3539 413184 : res = make_result_opt_error(&result, NULL);
3540 :
3541 413184 : free_var(&result);
3542 :
3543 413184 : return res;
3544 : }
3545 :
3546 :
3547 : /*
3548 : * numeric_inc() -
3549 : *
3550 : * Increment a number by one
3551 : */
3552 : Datum
3553 48 : numeric_inc(PG_FUNCTION_ARGS)
3554 : {
3555 48 : Numeric num = PG_GETARG_NUMERIC(0);
3556 : NumericVar arg;
3557 : Numeric res;
3558 :
3559 : /*
3560 : * Handle NaN and infinities
3561 : */
3562 48 : if (NUMERIC_IS_SPECIAL(num))
3563 18 : PG_RETURN_NUMERIC(duplicate_numeric(num));
3564 :
3565 : /*
3566 : * Compute the result and return it
3567 : */
3568 30 : init_var_from_num(num, &arg);
3569 :
3570 30 : add_var(&arg, &const_one, &arg);
3571 :
3572 30 : res = make_result(&arg);
3573 :
3574 30 : free_var(&arg);
3575 :
3576 30 : PG_RETURN_NUMERIC(res);
3577 : }
3578 :
3579 :
3580 : /*
3581 : * numeric_smaller() -
3582 : *
3583 : * Return the smaller of two numbers
3584 : */
3585 : Datum
3586 798 : numeric_smaller(PG_FUNCTION_ARGS)
3587 : {
3588 798 : Numeric num1 = PG_GETARG_NUMERIC(0);
3589 798 : Numeric num2 = PG_GETARG_NUMERIC(1);
3590 :
3591 : /*
3592 : * Use cmp_numerics so that this will agree with the comparison operators,
3593 : * particularly as regards comparisons involving NaN.
3594 : */
3595 798 : if (cmp_numerics(num1, num2) < 0)
3596 640 : PG_RETURN_NUMERIC(num1);
3597 : else
3598 158 : PG_RETURN_NUMERIC(num2);
3599 : }
3600 :
3601 :
3602 : /*
3603 : * numeric_larger() -
3604 : *
3605 : * Return the larger of two numbers
3606 : */
3607 : Datum
3608 18630 : numeric_larger(PG_FUNCTION_ARGS)
3609 : {
3610 18630 : Numeric num1 = PG_GETARG_NUMERIC(0);
3611 18630 : Numeric num2 = PG_GETARG_NUMERIC(1);
3612 :
3613 : /*
3614 : * Use cmp_numerics so that this will agree with the comparison operators,
3615 : * particularly as regards comparisons involving NaN.
3616 : */
3617 18630 : if (cmp_numerics(num1, num2) > 0)
3618 17602 : PG_RETURN_NUMERIC(num1);
3619 : else
3620 1028 : PG_RETURN_NUMERIC(num2);
3621 : }
3622 :
3623 :
3624 : /* ----------------------------------------------------------------------
3625 : *
3626 : * Advanced math functions
3627 : *
3628 : * ----------------------------------------------------------------------
3629 : */
3630 :
3631 : /*
3632 : * numeric_gcd() -
3633 : *
3634 : * Calculate the greatest common divisor of two numerics
3635 : */
3636 : Datum
3637 216 : numeric_gcd(PG_FUNCTION_ARGS)
3638 : {
3639 216 : Numeric num1 = PG_GETARG_NUMERIC(0);
3640 216 : Numeric num2 = PG_GETARG_NUMERIC(1);
3641 : NumericVar arg1;
3642 : NumericVar arg2;
3643 : NumericVar result;
3644 : Numeric res;
3645 :
3646 : /*
3647 : * Handle NaN and infinities: we consider the result to be NaN in all such
3648 : * cases.
3649 : */
3650 216 : if (NUMERIC_IS_SPECIAL(num1) || NUMERIC_IS_SPECIAL(num2))
3651 96 : PG_RETURN_NUMERIC(make_result(&const_nan));
3652 :
3653 : /*
3654 : * Unpack the arguments
3655 : */
3656 120 : init_var_from_num(num1, &arg1);
3657 120 : init_var_from_num(num2, &arg2);
3658 :
3659 120 : init_var(&result);
3660 :
3661 : /*
3662 : * Find the GCD and return the result
3663 : */
3664 120 : gcd_var(&arg1, &arg2, &result);
3665 :
3666 120 : res = make_result(&result);
3667 :
3668 120 : free_var(&result);
3669 :
3670 120 : PG_RETURN_NUMERIC(res);
3671 : }
3672 :
3673 :
3674 : /*
3675 : * numeric_lcm() -
3676 : *
3677 : * Calculate the least common multiple of two numerics
3678 : */
3679 : Datum
3680 246 : numeric_lcm(PG_FUNCTION_ARGS)
3681 : {
3682 246 : Numeric num1 = PG_GETARG_NUMERIC(0);
3683 246 : Numeric num2 = PG_GETARG_NUMERIC(1);
3684 : NumericVar arg1;
3685 : NumericVar arg2;
3686 : NumericVar result;
3687 : Numeric res;
3688 :
3689 : /*
3690 : * Handle NaN and infinities: we consider the result to be NaN in all such
3691 : * cases.
3692 : */
3693 246 : if (NUMERIC_IS_SPECIAL(num1) || NUMERIC_IS_SPECIAL(num2))
3694 96 : PG_RETURN_NUMERIC(make_result(&const_nan));
3695 :
3696 : /*
3697 : * Unpack the arguments
3698 : */
3699 150 : init_var_from_num(num1, &arg1);
3700 150 : init_var_from_num(num2, &arg2);
3701 :
3702 150 : init_var(&result);
3703 :
3704 : /*
3705 : * Compute the result using lcm(x, y) = abs(x / gcd(x, y) * y), returning
3706 : * zero if either input is zero.
3707 : *
3708 : * Note that the division is guaranteed to be exact, returning an integer
3709 : * result, so the LCM is an integral multiple of both x and y. A display
3710 : * scale of Min(x.dscale, y.dscale) would be sufficient to represent it,
3711 : * but as with other numeric functions, we choose to return a result whose
3712 : * display scale is no smaller than either input.
3713 : */
3714 150 : if (arg1.ndigits == 0 || arg2.ndigits == 0)
3715 48 : set_var_from_var(&const_zero, &result);
3716 : else
3717 : {
3718 102 : gcd_var(&arg1, &arg2, &result);
3719 102 : div_var(&arg1, &result, &result, 0, false, true);
3720 102 : mul_var(&arg2, &result, &result, arg2.dscale);
3721 102 : result.sign = NUMERIC_POS;
3722 : }
3723 :
3724 150 : result.dscale = Max(arg1.dscale, arg2.dscale);
3725 :
3726 150 : res = make_result(&result);
3727 :
3728 144 : free_var(&result);
3729 :
3730 144 : PG_RETURN_NUMERIC(res);
3731 : }
3732 :
3733 :
3734 : /*
3735 : * numeric_fac()
3736 : *
3737 : * Compute factorial
3738 : */
3739 : Datum
3740 42 : numeric_fac(PG_FUNCTION_ARGS)
3741 : {
3742 42 : int64 num = PG_GETARG_INT64(0);
3743 : Numeric res;
3744 : NumericVar fact;
3745 : NumericVar result;
3746 :
3747 42 : if (num < 0)
3748 6 : ereport(ERROR,
3749 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
3750 : errmsg("factorial of a negative number is undefined")));
3751 36 : if (num <= 1)
3752 : {
3753 6 : res = make_result(&const_one);
3754 6 : PG_RETURN_NUMERIC(res);
3755 : }
3756 : /* Fail immediately if the result would overflow */
3757 30 : if (num > 32177)
3758 6 : ereport(ERROR,
3759 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
3760 : errmsg("value overflows numeric format")));
3761 :
3762 24 : init_var(&fact);
3763 24 : init_var(&result);
3764 :
3765 24 : int64_to_numericvar(num, &result);
3766 :
3767 294 : for (num = num - 1; num > 1; num--)
3768 : {
3769 : /* this loop can take awhile, so allow it to be interrupted */
3770 270 : CHECK_FOR_INTERRUPTS();
3771 :
3772 270 : int64_to_numericvar(num, &fact);
3773 :
3774 270 : mul_var(&result, &fact, &result, 0);
3775 : }
3776 :
3777 24 : res = make_result(&result);
3778 :
3779 24 : free_var(&fact);
3780 24 : free_var(&result);
3781 :
3782 24 : PG_RETURN_NUMERIC(res);
3783 : }
3784 :
3785 :
3786 : /*
3787 : * numeric_sqrt() -
3788 : *
3789 : * Compute the square root of a numeric.
3790 : */
3791 : Datum
3792 150 : numeric_sqrt(PG_FUNCTION_ARGS)
3793 : {
3794 150 : Numeric num = PG_GETARG_NUMERIC(0);
3795 : Numeric res;
3796 : NumericVar arg;
3797 : NumericVar result;
3798 : int sweight;
3799 : int rscale;
3800 :
3801 : /*
3802 : * Handle NaN and infinities
3803 : */
3804 150 : if (NUMERIC_IS_SPECIAL(num))
3805 : {
3806 : /* error should match that in sqrt_var() */
3807 18 : if (NUMERIC_IS_NINF(num))
3808 6 : ereport(ERROR,
3809 : (errcode(ERRCODE_INVALID_ARGUMENT_FOR_POWER_FUNCTION),
3810 : errmsg("cannot take square root of a negative number")));
3811 : /* For NAN or PINF, just duplicate the input */
3812 12 : PG_RETURN_NUMERIC(duplicate_numeric(num));
3813 : }
3814 :
3815 : /*
3816 : * Unpack the argument and determine the result scale. We choose a scale
3817 : * to give at least NUMERIC_MIN_SIG_DIGITS significant digits; but in any
3818 : * case not less than the input's dscale.
3819 : */
3820 132 : init_var_from_num(num, &arg);
3821 :
3822 132 : init_var(&result);
3823 :
3824 : /*
3825 : * Assume the input was normalized, so arg.weight is accurate. The result
3826 : * then has at least sweight = floor(arg.weight * DEC_DIGITS / 2 + 1)
3827 : * digits before the decimal point. When DEC_DIGITS is even, we can save
3828 : * a few cycles, since the division is exact and there is no need to round
3829 : * towards negative infinity.
3830 : */
3831 : #if DEC_DIGITS == ((DEC_DIGITS / 2) * 2)
3832 132 : sweight = arg.weight * DEC_DIGITS / 2 + 1;
3833 : #else
3834 : if (arg.weight >= 0)
3835 : sweight = arg.weight * DEC_DIGITS / 2 + 1;
3836 : else
3837 : sweight = 1 - (1 - arg.weight * DEC_DIGITS) / 2;
3838 : #endif
3839 :
3840 132 : rscale = NUMERIC_MIN_SIG_DIGITS - sweight;
3841 132 : rscale = Max(rscale, arg.dscale);
3842 132 : rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
3843 132 : rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
3844 :
3845 : /*
3846 : * Let sqrt_var() do the calculation and return the result.
3847 : */
3848 132 : sqrt_var(&arg, &result, rscale);
3849 :
3850 126 : res = make_result(&result);
3851 :
3852 126 : free_var(&result);
3853 :
3854 126 : PG_RETURN_NUMERIC(res);
3855 : }
3856 :
3857 :
3858 : /*
3859 : * numeric_exp() -
3860 : *
3861 : * Raise e to the power of x
3862 : */
3863 : Datum
3864 78 : numeric_exp(PG_FUNCTION_ARGS)
3865 : {
3866 78 : Numeric num = PG_GETARG_NUMERIC(0);
3867 : Numeric res;
3868 : NumericVar arg;
3869 : NumericVar result;
3870 : int rscale;
3871 : double val;
3872 :
3873 : /*
3874 : * Handle NaN and infinities
3875 : */
3876 78 : if (NUMERIC_IS_SPECIAL(num))
3877 : {
3878 : /* Per POSIX, exp(-Inf) is zero */
3879 18 : if (NUMERIC_IS_NINF(num))
3880 6 : PG_RETURN_NUMERIC(make_result(&const_zero));
3881 : /* For NAN or PINF, just duplicate the input */
3882 12 : PG_RETURN_NUMERIC(duplicate_numeric(num));
3883 : }
3884 :
3885 : /*
3886 : * Unpack the argument and determine the result scale. We choose a scale
3887 : * to give at least NUMERIC_MIN_SIG_DIGITS significant digits; but in any
3888 : * case not less than the input's dscale.
3889 : */
3890 60 : init_var_from_num(num, &arg);
3891 :
3892 60 : init_var(&result);
3893 :
3894 : /* convert input to float8, ignoring overflow */
3895 60 : val = numericvar_to_double_no_overflow(&arg);
3896 :
3897 : /*
3898 : * log10(result) = num * log10(e), so this is approximately the decimal
3899 : * weight of the result:
3900 : */
3901 60 : val *= 0.434294481903252;
3902 :
3903 : /* limit to something that won't cause integer overflow */
3904 60 : val = Max(val, -NUMERIC_MAX_RESULT_SCALE);
3905 60 : val = Min(val, NUMERIC_MAX_RESULT_SCALE);
3906 :
3907 60 : rscale = NUMERIC_MIN_SIG_DIGITS - (int) val;
3908 60 : rscale = Max(rscale, arg.dscale);
3909 60 : rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
3910 60 : rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
3911 :
3912 : /*
3913 : * Let exp_var() do the calculation and return the result.
3914 : */
3915 60 : exp_var(&arg, &result, rscale);
3916 :
3917 60 : res = make_result(&result);
3918 :
3919 60 : free_var(&result);
3920 :
3921 60 : PG_RETURN_NUMERIC(res);
3922 : }
3923 :
3924 :
3925 : /*
3926 : * numeric_ln() -
3927 : *
3928 : * Compute the natural logarithm of x
3929 : */
3930 : Datum
3931 198 : numeric_ln(PG_FUNCTION_ARGS)
3932 : {
3933 198 : Numeric num = PG_GETARG_NUMERIC(0);
3934 : Numeric res;
3935 : NumericVar arg;
3936 : NumericVar result;
3937 : int ln_dweight;
3938 : int rscale;
3939 :
3940 : /*
3941 : * Handle NaN and infinities
3942 : */
3943 198 : if (NUMERIC_IS_SPECIAL(num))
3944 : {
3945 18 : if (NUMERIC_IS_NINF(num))
3946 6 : ereport(ERROR,
3947 : (errcode(ERRCODE_INVALID_ARGUMENT_FOR_LOG),
3948 : errmsg("cannot take logarithm of a negative number")));
3949 : /* For NAN or PINF, just duplicate the input */
3950 12 : PG_RETURN_NUMERIC(duplicate_numeric(num));
3951 : }
3952 :
3953 180 : init_var_from_num(num, &arg);
3954 180 : init_var(&result);
3955 :
3956 : /* Estimated dweight of logarithm */
3957 180 : ln_dweight = estimate_ln_dweight(&arg);
3958 :
3959 180 : rscale = NUMERIC_MIN_SIG_DIGITS - ln_dweight;
3960 180 : rscale = Max(rscale, arg.dscale);
3961 180 : rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
3962 180 : rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
3963 :
3964 180 : ln_var(&arg, &result, rscale);
3965 :
3966 156 : res = make_result(&result);
3967 :
3968 156 : free_var(&result);
3969 :
3970 156 : PG_RETURN_NUMERIC(res);
3971 : }
3972 :
3973 :
3974 : /*
3975 : * numeric_log() -
3976 : *
3977 : * Compute the logarithm of x in a given base
3978 : */
3979 : Datum
3980 342 : numeric_log(PG_FUNCTION_ARGS)
3981 : {
3982 342 : Numeric num1 = PG_GETARG_NUMERIC(0);
3983 342 : Numeric num2 = PG_GETARG_NUMERIC(1);
3984 : Numeric res;
3985 : NumericVar arg1;
3986 : NumericVar arg2;
3987 : NumericVar result;
3988 :
3989 : /*
3990 : * Handle NaN and infinities
3991 : */
3992 342 : if (NUMERIC_IS_SPECIAL(num1) || NUMERIC_IS_SPECIAL(num2))
3993 : {
3994 : int sign1,
3995 : sign2;
3996 :
3997 126 : if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
3998 54 : PG_RETURN_NUMERIC(make_result(&const_nan));
3999 : /* fail on negative inputs including -Inf, as log_var would */
4000 72 : sign1 = numeric_sign_internal(num1);
4001 72 : sign2 = numeric_sign_internal(num2);
4002 72 : if (sign1 < 0 || sign2 < 0)
4003 24 : ereport(ERROR,
4004 : (errcode(ERRCODE_INVALID_ARGUMENT_FOR_LOG),
4005 : errmsg("cannot take logarithm of a negative number")));
4006 : /* fail on zero inputs, as log_var would */
4007 48 : if (sign1 == 0 || sign2 == 0)
4008 6 : ereport(ERROR,
4009 : (errcode(ERRCODE_INVALID_ARGUMENT_FOR_LOG),
4010 : errmsg("cannot take logarithm of zero")));
4011 42 : if (NUMERIC_IS_PINF(num1))
4012 : {
4013 : /* log(Inf, Inf) reduces to Inf/Inf, so it's NaN */
4014 18 : if (NUMERIC_IS_PINF(num2))
4015 6 : PG_RETURN_NUMERIC(make_result(&const_nan));
4016 : /* log(Inf, finite-positive) is zero (we don't throw underflow) */
4017 12 : PG_RETURN_NUMERIC(make_result(&const_zero));
4018 : }
4019 : Assert(NUMERIC_IS_PINF(num2));
4020 : /* log(finite-positive, Inf) is Inf */
4021 24 : PG_RETURN_NUMERIC(make_result(&const_pinf));
4022 : }
4023 :
4024 : /*
4025 : * Initialize things
4026 : */
4027 216 : init_var_from_num(num1, &arg1);
4028 216 : init_var_from_num(num2, &arg2);
4029 216 : init_var(&result);
4030 :
4031 : /*
4032 : * Call log_var() to compute and return the result; note it handles scale
4033 : * selection itself.
4034 : */
4035 216 : log_var(&arg1, &arg2, &result);
4036 :
4037 156 : res = make_result(&result);
4038 :
4039 156 : free_var(&result);
4040 :
4041 156 : PG_RETURN_NUMERIC(res);
4042 : }
4043 :
4044 :
4045 : /*
4046 : * numeric_power() -
4047 : *
4048 : * Raise x to the power of y
4049 : */
4050 : Datum
4051 1644 : numeric_power(PG_FUNCTION_ARGS)
4052 : {
4053 1644 : Numeric num1 = PG_GETARG_NUMERIC(0);
4054 1644 : Numeric num2 = PG_GETARG_NUMERIC(1);
4055 : Numeric res;
4056 : NumericVar arg1;
4057 : NumericVar arg2;
4058 : NumericVar result;
4059 : int sign1,
4060 : sign2;
4061 :
4062 : /*
4063 : * Handle NaN and infinities
4064 : */
4065 1644 : if (NUMERIC_IS_SPECIAL(num1) || NUMERIC_IS_SPECIAL(num2))
4066 : {
4067 : /*
4068 : * We follow the POSIX spec for pow(3), which says that NaN ^ 0 = 1,
4069 : * and 1 ^ NaN = 1, while all other cases with NaN inputs yield NaN
4070 : * (with no error).
4071 : */
4072 234 : if (NUMERIC_IS_NAN(num1))
4073 : {
4074 54 : if (!NUMERIC_IS_SPECIAL(num2))
4075 : {
4076 36 : init_var_from_num(num2, &arg2);
4077 36 : if (cmp_var(&arg2, &const_zero) == 0)
4078 12 : PG_RETURN_NUMERIC(make_result(&const_one));
4079 : }
4080 42 : PG_RETURN_NUMERIC(make_result(&const_nan));
4081 : }
4082 180 : if (NUMERIC_IS_NAN(num2))
4083 : {
4084 42 : if (!NUMERIC_IS_SPECIAL(num1))
4085 : {
4086 36 : init_var_from_num(num1, &arg1);
4087 36 : if (cmp_var(&arg1, &const_one) == 0)
4088 12 : PG_RETURN_NUMERIC(make_result(&const_one));
4089 : }
4090 30 : PG_RETURN_NUMERIC(make_result(&const_nan));
4091 : }
4092 : /* At least one input is infinite, but error rules still apply */
4093 138 : sign1 = numeric_sign_internal(num1);
4094 138 : sign2 = numeric_sign_internal(num2);
4095 138 : if (sign1 == 0 && sign2 < 0)
4096 6 : ereport(ERROR,
4097 : (errcode(ERRCODE_INVALID_ARGUMENT_FOR_POWER_FUNCTION),
4098 : errmsg("zero raised to a negative power is undefined")));
4099 132 : if (sign1 < 0 && !numeric_is_integral(num2))
4100 6 : ereport(ERROR,
4101 : (errcode(ERRCODE_INVALID_ARGUMENT_FOR_POWER_FUNCTION),
4102 : errmsg("a negative number raised to a non-integer power yields a complex result")));
4103 :
4104 : /*
4105 : * POSIX gives this series of rules for pow(3) with infinite inputs:
4106 : *
4107 : * For any value of y, if x is +1, 1.0 shall be returned.
4108 : */
4109 126 : if (!NUMERIC_IS_SPECIAL(num1))
4110 : {
4111 42 : init_var_from_num(num1, &arg1);
4112 42 : if (cmp_var(&arg1, &const_one) == 0)
4113 6 : PG_RETURN_NUMERIC(make_result(&const_one));
4114 : }
4115 :
4116 : /*
4117 : * For any value of x, if y is [-]0, 1.0 shall be returned.
4118 : */
4119 120 : if (sign2 == 0)
4120 12 : PG_RETURN_NUMERIC(make_result(&const_one));
4121 :
4122 : /*
4123 : * For any odd integer value of y > 0, if x is [-]0, [-]0 shall be
4124 : * returned. For y > 0 and not an odd integer, if x is [-]0, +0 shall
4125 : * be returned. (Since we don't deal in minus zero, we need not
4126 : * distinguish these two cases.)
4127 : */
4128 108 : if (sign1 == 0 && sign2 > 0)
4129 6 : PG_RETURN_NUMERIC(make_result(&const_zero));
4130 :
4131 : /*
4132 : * If x is -1, and y is [-]Inf, 1.0 shall be returned.
4133 : *
4134 : * For |x| < 1, if y is -Inf, +Inf shall be returned.
4135 : *
4136 : * For |x| > 1, if y is -Inf, +0 shall be returned.
4137 : *
4138 : * For |x| < 1, if y is +Inf, +0 shall be returned.
4139 : *
4140 : * For |x| > 1, if y is +Inf, +Inf shall be returned.
4141 : */
4142 102 : if (NUMERIC_IS_INF(num2))
4143 : {
4144 : bool abs_x_gt_one;
4145 :
4146 54 : if (NUMERIC_IS_SPECIAL(num1))
4147 24 : abs_x_gt_one = true; /* x is either Inf or -Inf */
4148 : else
4149 : {
4150 30 : init_var_from_num(num1, &arg1);
4151 30 : if (cmp_var(&arg1, &const_minus_one) == 0)
4152 6 : PG_RETURN_NUMERIC(make_result(&const_one));
4153 24 : arg1.sign = NUMERIC_POS; /* now arg1 = abs(x) */
4154 24 : abs_x_gt_one = (cmp_var(&arg1, &const_one) > 0);
4155 : }
4156 48 : if (abs_x_gt_one == (sign2 > 0))
4157 30 : PG_RETURN_NUMERIC(make_result(&const_pinf));
4158 : else
4159 18 : PG_RETURN_NUMERIC(make_result(&const_zero));
4160 : }
4161 :
4162 : /*
4163 : * For y < 0, if x is +Inf, +0 shall be returned.
4164 : *
4165 : * For y > 0, if x is +Inf, +Inf shall be returned.
4166 : */
4167 48 : if (NUMERIC_IS_PINF(num1))
4168 : {
4169 24 : if (sign2 > 0)
4170 18 : PG_RETURN_NUMERIC(make_result(&const_pinf));
4171 : else
4172 6 : PG_RETURN_NUMERIC(make_result(&const_zero));
4173 : }
4174 :
4175 : Assert(NUMERIC_IS_NINF(num1));
4176 :
4177 : /*
4178 : * For y an odd integer < 0, if x is -Inf, -0 shall be returned. For
4179 : * y < 0 and not an odd integer, if x is -Inf, +0 shall be returned.
4180 : * (Again, we need not distinguish these two cases.)
4181 : */
4182 24 : if (sign2 < 0)
4183 12 : PG_RETURN_NUMERIC(make_result(&const_zero));
4184 :
4185 : /*
4186 : * For y an odd integer > 0, if x is -Inf, -Inf shall be returned. For
4187 : * y > 0 and not an odd integer, if x is -Inf, +Inf shall be returned.
4188 : */
4189 12 : init_var_from_num(num2, &arg2);
4190 12 : if (arg2.ndigits > 0 && arg2.ndigits == arg2.weight + 1 &&
4191 12 : (arg2.digits[arg2.ndigits - 1] & 1))
4192 6 : PG_RETURN_NUMERIC(make_result(&const_ninf));
4193 : else
4194 6 : PG_RETURN_NUMERIC(make_result(&const_pinf));
4195 : }
4196 :
4197 : /*
4198 : * The SQL spec requires that we emit a particular SQLSTATE error code for
4199 : * certain error conditions. Specifically, we don't return a
4200 : * divide-by-zero error code for 0 ^ -1. Raising a negative number to a
4201 : * non-integer power must produce the same error code, but that case is
4202 : * handled in power_var().
4203 : */
4204 1410 : sign1 = numeric_sign_internal(num1);
4205 1410 : sign2 = numeric_sign_internal(num2);
4206 :
4207 1410 : if (sign1 == 0 && sign2 < 0)
4208 12 : ereport(ERROR,
4209 : (errcode(ERRCODE_INVALID_ARGUMENT_FOR_POWER_FUNCTION),
4210 : errmsg("zero raised to a negative power is undefined")));
4211 :
4212 : /*
4213 : * Initialize things
4214 : */
4215 1398 : init_var(&result);
4216 1398 : init_var_from_num(num1, &arg1);
4217 1398 : init_var_from_num(num2, &arg2);
4218 :
4219 : /*
4220 : * Call power_var() to compute and return the result; note it handles
4221 : * scale selection itself.
4222 : */
4223 1398 : power_var(&arg1, &arg2, &result);
4224 :
4225 1368 : res = make_result(&result);
4226 :
4227 1368 : free_var(&result);
4228 :
4229 1368 : PG_RETURN_NUMERIC(res);
4230 : }
4231 :
4232 : /*
4233 : * numeric_scale() -
4234 : *
4235 : * Returns the scale, i.e. the count of decimal digits in the fractional part
4236 : */
4237 : Datum
4238 108 : numeric_scale(PG_FUNCTION_ARGS)
4239 : {
4240 108 : Numeric num = PG_GETARG_NUMERIC(0);
4241 :
4242 108 : if (NUMERIC_IS_SPECIAL(num))
4243 18 : PG_RETURN_NULL();
4244 :
4245 90 : PG_RETURN_INT32(NUMERIC_DSCALE(num));
4246 : }
4247 :
4248 : /*
4249 : * Calculate minimum scale for value.
4250 : */
4251 : static int
4252 372 : get_min_scale(NumericVar *var)
4253 : {
4254 : int min_scale;
4255 : int last_digit_pos;
4256 :
4257 : /*
4258 : * Ordinarily, the input value will be "stripped" so that the last
4259 : * NumericDigit is nonzero. But we don't want to get into an infinite
4260 : * loop if it isn't, so explicitly find the last nonzero digit.
4261 : */
4262 372 : last_digit_pos = var->ndigits - 1;
4263 372 : while (last_digit_pos >= 0 &&
4264 342 : var->digits[last_digit_pos] == 0)
4265 0 : last_digit_pos--;
4266 :
4267 372 : if (last_digit_pos >= 0)
4268 : {
4269 : /* compute min_scale assuming that last ndigit has no zeroes */
4270 342 : min_scale = (last_digit_pos - var->weight) * DEC_DIGITS;
4271 :
4272 : /*
4273 : * We could get a negative result if there are no digits after the
4274 : * decimal point. In this case the min_scale must be zero.
4275 : */
4276 342 : if (min_scale > 0)
4277 : {
4278 : /*
4279 : * Reduce min_scale if trailing digit(s) in last NumericDigit are
4280 : * zero.
4281 : */
4282 186 : NumericDigit last_digit = var->digits[last_digit_pos];
4283 :
4284 498 : while (last_digit % 10 == 0)
4285 : {
4286 312 : min_scale--;
4287 312 : last_digit /= 10;
4288 : }
4289 : }
4290 : else
4291 156 : min_scale = 0;
4292 : }
4293 : else
4294 30 : min_scale = 0; /* result if input is zero */
4295 :
4296 372 : return min_scale;
4297 : }
4298 :
4299 : /*
4300 : * Returns minimum scale required to represent supplied value without loss.
4301 : */
4302 : Datum
4303 72 : numeric_min_scale(PG_FUNCTION_ARGS)
4304 : {
4305 72 : Numeric num = PG_GETARG_NUMERIC(0);
4306 : NumericVar arg;
4307 : int min_scale;
4308 :
4309 72 : if (NUMERIC_IS_SPECIAL(num))
4310 12 : PG_RETURN_NULL();
4311 :
4312 60 : init_var_from_num(num, &arg);
4313 60 : min_scale = get_min_scale(&arg);
4314 60 : free_var(&arg);
4315 :
4316 60 : PG_RETURN_INT32(min_scale);
4317 : }
4318 :
4319 : /*
4320 : * Reduce scale of numeric value to represent supplied value without loss.
4321 : */
4322 : Datum
4323 324 : numeric_trim_scale(PG_FUNCTION_ARGS)
4324 : {
4325 324 : Numeric num = PG_GETARG_NUMERIC(0);
4326 : Numeric res;
4327 : NumericVar result;
4328 :
4329 324 : if (NUMERIC_IS_SPECIAL(num))
4330 12 : PG_RETURN_NUMERIC(duplicate_numeric(num));
4331 :
4332 312 : init_var_from_num(num, &result);
4333 312 : result.dscale = get_min_scale(&result);
4334 312 : res = make_result(&result);
4335 312 : free_var(&result);
4336 :
4337 312 : PG_RETURN_NUMERIC(res);
4338 : }
4339 :
4340 : /*
4341 : * Return a random numeric value in the range [rmin, rmax].
4342 : */
4343 : Numeric
4344 33462 : random_numeric(pg_prng_state *state, Numeric rmin, Numeric rmax)
4345 : {
4346 : NumericVar rmin_var;
4347 : NumericVar rmax_var;
4348 : NumericVar result;
4349 : Numeric res;
4350 :
4351 : /* Range bounds must not be NaN/infinity */
4352 33462 : if (NUMERIC_IS_SPECIAL(rmin))
4353 : {
4354 12 : if (NUMERIC_IS_NAN(rmin))
4355 6 : ereport(ERROR,
4356 : errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4357 : errmsg("lower bound cannot be NaN"));
4358 : else
4359 6 : ereport(ERROR,
4360 : errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4361 : errmsg("lower bound cannot be infinity"));
4362 : }
4363 33450 : if (NUMERIC_IS_SPECIAL(rmax))
4364 : {
4365 12 : if (NUMERIC_IS_NAN(rmax))
4366 6 : ereport(ERROR,
4367 : errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4368 : errmsg("upper bound cannot be NaN"));
4369 : else
4370 6 : ereport(ERROR,
4371 : errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4372 : errmsg("upper bound cannot be infinity"));
4373 : }
4374 :
4375 : /* Return a random value in the range [rmin, rmax] */
4376 33438 : init_var_from_num(rmin, &rmin_var);
4377 33438 : init_var_from_num(rmax, &rmax_var);
4378 :
4379 33438 : init_var(&result);
4380 :
4381 33438 : random_var(state, &rmin_var, &rmax_var, &result);
4382 :
4383 33432 : res = make_result(&result);
4384 :
4385 33432 : free_var(&result);
4386 :
4387 33432 : return res;
4388 : }
4389 :
4390 :
4391 : /* ----------------------------------------------------------------------
4392 : *
4393 : * Type conversion functions
4394 : *
4395 : * ----------------------------------------------------------------------
4396 : */
4397 :
4398 : Numeric
4399 1868494 : int64_to_numeric(int64 val)
4400 : {
4401 : Numeric res;
4402 : NumericVar result;
4403 :
4404 1868494 : init_var(&result);
4405 :
4406 1868494 : int64_to_numericvar(val, &result);
4407 :
4408 1868494 : res = make_result(&result);
4409 :
4410 1868494 : free_var(&result);
4411 :
4412 1868494 : return res;
4413 : }
4414 :
4415 : /*
4416 : * Convert val1/(10**log10val2) to numeric. This is much faster than normal
4417 : * numeric division.
4418 : */
4419 : Numeric
4420 29380 : int64_div_fast_to_numeric(int64 val1, int log10val2)
4421 : {
4422 : Numeric res;
4423 : NumericVar result;
4424 : int rscale;
4425 : int w;
4426 : int m;
4427 :
4428 29380 : init_var(&result);
4429 :
4430 : /* result scale */
4431 29380 : rscale = log10val2 < 0 ? 0 : log10val2;
4432 :
4433 : /* how much to decrease the weight by */
4434 29380 : w = log10val2 / DEC_DIGITS;
4435 : /* how much is left to divide by */
4436 29380 : m = log10val2 % DEC_DIGITS;
4437 29380 : if (m < 0)
4438 : {
4439 0 : m += DEC_DIGITS;
4440 0 : w--;
4441 : }
4442 :
4443 : /*
4444 : * If there is anything left to divide by (10^m with 0 < m < DEC_DIGITS),
4445 : * multiply the dividend by 10^(DEC_DIGITS - m), and shift the weight by
4446 : * one more.
4447 : */
4448 29380 : if (m > 0)
4449 : {
4450 : #if DEC_DIGITS == 4
4451 : static const int pow10[] = {1, 10, 100, 1000};
4452 : #elif DEC_DIGITS == 2
4453 : static const int pow10[] = {1, 10};
4454 : #elif DEC_DIGITS == 1
4455 : static const int pow10[] = {1};
4456 : #else
4457 : #error unsupported NBASE
4458 : #endif
4459 29380 : int64 factor = pow10[DEC_DIGITS - m];
4460 : int64 new_val1;
4461 :
4462 : StaticAssertDecl(lengthof(pow10) == DEC_DIGITS, "mismatch with DEC_DIGITS");
4463 :
4464 29380 : if (unlikely(pg_mul_s64_overflow(val1, factor, &new_val1)))
4465 : {
4466 : #ifdef HAVE_INT128
4467 : /* do the multiplication using 128-bit integers */
4468 : int128 tmp;
4469 :
4470 12 : tmp = (int128) val1 * (int128) factor;
4471 :
4472 12 : int128_to_numericvar(tmp, &result);
4473 : #else
4474 : /* do the multiplication using numerics */
4475 : NumericVar tmp;
4476 :
4477 : init_var(&tmp);
4478 :
4479 : int64_to_numericvar(val1, &result);
4480 : int64_to_numericvar(factor, &tmp);
4481 : mul_var(&result, &tmp, &result, 0);
4482 :
4483 : free_var(&tmp);
4484 : #endif
4485 : }
4486 : else
4487 29368 : int64_to_numericvar(new_val1, &result);
4488 :
4489 29380 : w++;
4490 : }
4491 : else
4492 0 : int64_to_numericvar(val1, &result);
4493 :
4494 29380 : result.weight -= w;
4495 29380 : result.dscale = rscale;
4496 :
4497 29380 : res = make_result(&result);
4498 :
4499 29380 : free_var(&result);
4500 :
4501 29380 : return res;
4502 : }
4503 :
4504 : Datum
4505 1555020 : int4_numeric(PG_FUNCTION_ARGS)
4506 : {
4507 1555020 : int32 val = PG_GETARG_INT32(0);
4508 :
4509 1555020 : PG_RETURN_NUMERIC(int64_to_numeric(val));
4510 : }
4511 :
4512 : int32
4513 7768 : numeric_int4_opt_error(Numeric num, bool *have_error)
4514 : {
4515 : NumericVar x;
4516 : int32 result;
4517 :
4518 7768 : if (have_error)
4519 1584 : *have_error = false;
4520 :
4521 7768 : if (NUMERIC_IS_SPECIAL(num))
4522 : {
4523 18 : if (have_error)
4524 : {
4525 0 : *have_error = true;
4526 0 : return 0;
4527 : }
4528 : else
4529 : {
4530 18 : if (NUMERIC_IS_NAN(num))
4531 6 : ereport(ERROR,
4532 : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4533 : errmsg("cannot convert NaN to %s", "integer")));
4534 : else
4535 12 : ereport(ERROR,
4536 : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4537 : errmsg("cannot convert infinity to %s", "integer")));
4538 : }
4539 : }
4540 :
4541 : /* Convert to variable format, then convert to int4 */
4542 7750 : init_var_from_num(num, &x);
4543 :
4544 7750 : if (!numericvar_to_int32(&x, &result))
4545 : {
4546 90 : if (have_error)
4547 : {
4548 78 : *have_error = true;
4549 78 : return 0;
4550 : }
4551 : else
4552 : {
4553 12 : ereport(ERROR,
4554 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
4555 : errmsg("integer out of range")));
4556 : }
4557 : }
4558 :
4559 7660 : return result;
4560 : }
4561 :
4562 : Datum
4563 6184 : numeric_int4(PG_FUNCTION_ARGS)
4564 : {
4565 6184 : Numeric num = PG_GETARG_NUMERIC(0);
4566 :
4567 6184 : PG_RETURN_INT32(numeric_int4_opt_error(num, NULL));
4568 : }
4569 :
4570 : /*
4571 : * Given a NumericVar, convert it to an int32. If the NumericVar
4572 : * exceeds the range of an int32, false is returned, otherwise true is returned.
4573 : * The input NumericVar is *not* free'd.
4574 : */
4575 : static bool
4576 8494 : numericvar_to_int32(const NumericVar *var, int32 *result)
4577 : {
4578 : int64 val;
4579 :
4580 8494 : if (!numericvar_to_int64(var, &val))
4581 6 : return false;
4582 :
4583 8488 : if (unlikely(val < PG_INT32_MIN) || unlikely(val > PG_INT32_MAX))
4584 84 : return false;
4585 :
4586 : /* Down-convert to int4 */
4587 8404 : *result = (int32) val;
4588 :
4589 8404 : return true;
4590 : }
4591 :
4592 : Datum
4593 36850 : int8_numeric(PG_FUNCTION_ARGS)
4594 : {
4595 36850 : int64 val = PG_GETARG_INT64(0);
4596 :
4597 36850 : PG_RETURN_NUMERIC(int64_to_numeric(val));
4598 : }
4599 :
4600 : int64
4601 570 : numeric_int8_opt_error(Numeric num, bool *have_error)
4602 : {
4603 : NumericVar x;
4604 : int64 result;
4605 :
4606 570 : if (have_error)
4607 48 : *have_error = false;
4608 :
4609 570 : if (NUMERIC_IS_SPECIAL(num))
4610 : {
4611 18 : if (have_error)
4612 : {
4613 0 : *have_error = true;
4614 0 : return 0;
4615 : }
4616 : else
4617 : {
4618 18 : if (NUMERIC_IS_NAN(num))
4619 6 : ereport(ERROR,
4620 : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4621 : errmsg("cannot convert NaN to %s", "bigint")));
4622 : else
4623 12 : ereport(ERROR,
4624 : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4625 : errmsg("cannot convert infinity to %s", "bigint")));
4626 : }
4627 : }
4628 :
4629 : /* Convert to variable format, then convert to int8 */
4630 552 : init_var_from_num(num, &x);
4631 :
4632 552 : if (!numericvar_to_int64(&x, &result))
4633 : {
4634 60 : if (have_error)
4635 : {
4636 12 : *have_error = true;
4637 12 : return 0;
4638 : }
4639 : else
4640 : {
4641 48 : ereport(ERROR,
4642 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
4643 : errmsg("bigint out of range")));
4644 : }
4645 : }
4646 :
4647 492 : return result;
4648 : }
4649 :
4650 : Datum
4651 522 : numeric_int8(PG_FUNCTION_ARGS)
4652 : {
4653 522 : Numeric num = PG_GETARG_NUMERIC(0);
4654 :
4655 522 : PG_RETURN_INT64(numeric_int8_opt_error(num, NULL));
4656 : }
4657 :
4658 :
4659 : Datum
4660 6 : int2_numeric(PG_FUNCTION_ARGS)
4661 : {
4662 6 : int16 val = PG_GETARG_INT16(0);
4663 :
4664 6 : PG_RETURN_NUMERIC(int64_to_numeric(val));
4665 : }
4666 :
4667 :
4668 : Datum
4669 102 : numeric_int2(PG_FUNCTION_ARGS)
4670 : {
4671 102 : Numeric num = PG_GETARG_NUMERIC(0);
4672 : NumericVar x;
4673 : int64 val;
4674 : int16 result;
4675 :
4676 102 : if (NUMERIC_IS_SPECIAL(num))
4677 : {
4678 18 : if (NUMERIC_IS_NAN(num))
4679 6 : ereport(ERROR,
4680 : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4681 : errmsg("cannot convert NaN to %s", "smallint")));
4682 : else
4683 12 : ereport(ERROR,
4684 : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4685 : errmsg("cannot convert infinity to %s", "smallint")));
4686 : }
4687 :
4688 : /* Convert to variable format and thence to int8 */
4689 84 : init_var_from_num(num, &x);
4690 :
4691 84 : if (!numericvar_to_int64(&x, &val))
4692 0 : ereport(ERROR,
4693 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
4694 : errmsg("smallint out of range")));
4695 :
4696 84 : if (unlikely(val < PG_INT16_MIN) || unlikely(val > PG_INT16_MAX))
4697 12 : ereport(ERROR,
4698 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
4699 : errmsg("smallint out of range")));
4700 :
4701 : /* Down-convert to int2 */
4702 72 : result = (int16) val;
4703 :
4704 72 : PG_RETURN_INT16(result);
4705 : }
4706 :
4707 :
4708 : Datum
4709 1074 : float8_numeric(PG_FUNCTION_ARGS)
4710 : {
4711 1074 : float8 val = PG_GETARG_FLOAT8(0);
4712 : Numeric res;
4713 : NumericVar result;
4714 : char buf[DBL_DIG + 100];
4715 : const char *endptr;
4716 :
4717 1074 : if (isnan(val))
4718 6 : PG_RETURN_NUMERIC(make_result(&const_nan));
4719 :
4720 1068 : if (isinf(val))
4721 : {
4722 12 : if (val < 0)
4723 6 : PG_RETURN_NUMERIC(make_result(&const_ninf));
4724 : else
4725 6 : PG_RETURN_NUMERIC(make_result(&const_pinf));
4726 : }
4727 :
4728 1056 : snprintf(buf, sizeof(buf), "%.*g", DBL_DIG, val);
4729 :
4730 1056 : init_var(&result);
4731 :
4732 : /* Assume we need not worry about leading/trailing spaces */
4733 1056 : (void) set_var_from_str(buf, buf, &result, &endptr, NULL);
4734 :
4735 1056 : res = make_result(&result);
4736 :
4737 1056 : free_var(&result);
4738 :
4739 1056 : PG_RETURN_NUMERIC(res);
4740 : }
4741 :
4742 :
4743 : Datum
4744 520158 : numeric_float8(PG_FUNCTION_ARGS)
4745 : {
4746 520158 : Numeric num = PG_GETARG_NUMERIC(0);
4747 : char *tmp;
4748 : Datum result;
4749 :
4750 520158 : if (NUMERIC_IS_SPECIAL(num))
4751 : {
4752 78 : if (NUMERIC_IS_PINF(num))
4753 24 : PG_RETURN_FLOAT8(get_float8_infinity());
4754 54 : else if (NUMERIC_IS_NINF(num))
4755 24 : PG_RETURN_FLOAT8(-get_float8_infinity());
4756 : else
4757 30 : PG_RETURN_FLOAT8(get_float8_nan());
4758 : }
4759 :
4760 520080 : tmp = DatumGetCString(DirectFunctionCall1(numeric_out,
4761 : NumericGetDatum(num)));
4762 :
4763 520080 : result = DirectFunctionCall1(float8in, CStringGetDatum(tmp));
4764 :
4765 520080 : pfree(tmp);
4766 :
4767 520080 : PG_RETURN_DATUM(result);
4768 : }
4769 :
4770 :
4771 : /*
4772 : * Convert numeric to float8; if out of range, return +/- HUGE_VAL
4773 : *
4774 : * (internal helper function, not directly callable from SQL)
4775 : */
4776 : Datum
4777 28 : numeric_float8_no_overflow(PG_FUNCTION_ARGS)
4778 : {
4779 28 : Numeric num = PG_GETARG_NUMERIC(0);
4780 : double val;
4781 :
4782 28 : if (NUMERIC_IS_SPECIAL(num))
4783 : {
4784 0 : if (NUMERIC_IS_PINF(num))
4785 0 : val = HUGE_VAL;
4786 0 : else if (NUMERIC_IS_NINF(num))
4787 0 : val = -HUGE_VAL;
4788 : else
4789 0 : val = get_float8_nan();
4790 : }
4791 : else
4792 : {
4793 : NumericVar x;
4794 :
4795 28 : init_var_from_num(num, &x);
4796 28 : val = numericvar_to_double_no_overflow(&x);
4797 : }
4798 :
4799 28 : PG_RETURN_FLOAT8(val);
4800 : }
4801 :
4802 : Datum
4803 22384 : float4_numeric(PG_FUNCTION_ARGS)
4804 : {
4805 22384 : float4 val = PG_GETARG_FLOAT4(0);
4806 : Numeric res;
4807 : NumericVar result;
4808 : char buf[FLT_DIG + 100];
4809 : const char *endptr;
4810 :
4811 22384 : if (isnan(val))
4812 6 : PG_RETURN_NUMERIC(make_result(&const_nan));
4813 :
4814 22378 : if (isinf(val))
4815 : {
4816 12 : if (val < 0)
4817 6 : PG_RETURN_NUMERIC(make_result(&const_ninf));
4818 : else
4819 6 : PG_RETURN_NUMERIC(make_result(&const_pinf));
4820 : }
4821 :
4822 22366 : snprintf(buf, sizeof(buf), "%.*g", FLT_DIG, val);
4823 :
4824 22366 : init_var(&result);
4825 :
4826 : /* Assume we need not worry about leading/trailing spaces */
4827 22366 : (void) set_var_from_str(buf, buf, &result, &endptr, NULL);
4828 :
4829 22366 : res = make_result(&result);
4830 :
4831 22366 : free_var(&result);
4832 :
4833 22366 : PG_RETURN_NUMERIC(res);
4834 : }
4835 :
4836 :
4837 : Datum
4838 2456 : numeric_float4(PG_FUNCTION_ARGS)
4839 : {
4840 2456 : Numeric num = PG_GETARG_NUMERIC(0);
4841 : char *tmp;
4842 : Datum result;
4843 :
4844 2456 : if (NUMERIC_IS_SPECIAL(num))
4845 : {
4846 78 : if (NUMERIC_IS_PINF(num))
4847 24 : PG_RETURN_FLOAT4(get_float4_infinity());
4848 54 : else if (NUMERIC_IS_NINF(num))
4849 24 : PG_RETURN_FLOAT4(-get_float4_infinity());
4850 : else
4851 30 : PG_RETURN_FLOAT4(get_float4_nan());
4852 : }
4853 :
4854 2378 : tmp = DatumGetCString(DirectFunctionCall1(numeric_out,
4855 : NumericGetDatum(num)));
4856 :
4857 2378 : result = DirectFunctionCall1(float4in, CStringGetDatum(tmp));
4858 :
4859 2378 : pfree(tmp);
4860 :
4861 2378 : PG_RETURN_DATUM(result);
4862 : }
4863 :
4864 :
4865 : Datum
4866 120 : numeric_pg_lsn(PG_FUNCTION_ARGS)
4867 : {
4868 120 : Numeric num = PG_GETARG_NUMERIC(0);
4869 : NumericVar x;
4870 : XLogRecPtr result;
4871 :
4872 120 : if (NUMERIC_IS_SPECIAL(num))
4873 : {
4874 6 : if (NUMERIC_IS_NAN(num))
4875 6 : ereport(ERROR,
4876 : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4877 : errmsg("cannot convert NaN to %s", "pg_lsn")));
4878 : else
4879 0 : ereport(ERROR,
4880 : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4881 : errmsg("cannot convert infinity to %s", "pg_lsn")));
4882 : }
4883 :
4884 : /* Convert to variable format and thence to pg_lsn */
4885 114 : init_var_from_num(num, &x);
4886 :
4887 114 : if (!numericvar_to_uint64(&x, (uint64 *) &result))
4888 24 : ereport(ERROR,
4889 : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4890 : errmsg("pg_lsn out of range")));
4891 :
4892 90 : PG_RETURN_LSN(result);
4893 : }
4894 :
4895 :
4896 : /* ----------------------------------------------------------------------
4897 : *
4898 : * Aggregate functions
4899 : *
4900 : * The transition datatype for all these aggregates is declared as INTERNAL.
4901 : * Actually, it's a pointer to a NumericAggState allocated in the aggregate
4902 : * context. The digit buffers for the NumericVars will be there too.
4903 : *
4904 : * On platforms which support 128-bit integers some aggregates instead use a
4905 : * 128-bit integer based transition datatype to speed up calculations.
4906 : *
4907 : * ----------------------------------------------------------------------
4908 : */
4909 :
4910 : typedef struct NumericAggState
4911 : {
4912 : bool calcSumX2; /* if true, calculate sumX2 */
4913 : MemoryContext agg_context; /* context we're calculating in */
4914 : int64 N; /* count of processed numbers */
4915 : NumericSumAccum sumX; /* sum of processed numbers */
4916 : NumericSumAccum sumX2; /* sum of squares of processed numbers */
4917 : int maxScale; /* maximum scale seen so far */
4918 : int64 maxScaleCount; /* number of values seen with maximum scale */
4919 : /* These counts are *not* included in N! Use NA_TOTAL_COUNT() as needed */
4920 : int64 NaNcount; /* count of NaN values */
4921 : int64 pInfcount; /* count of +Inf values */
4922 : int64 nInfcount; /* count of -Inf values */
4923 : } NumericAggState;
4924 :
4925 : #define NA_TOTAL_COUNT(na) \
4926 : ((na)->N + (na)->NaNcount + (na)->pInfcount + (na)->nInfcount)
4927 :
4928 : /*
4929 : * Prepare state data for a numeric aggregate function that needs to compute
4930 : * sum, count and optionally sum of squares of the input.
4931 : */
4932 : static NumericAggState *
4933 171164 : makeNumericAggState(FunctionCallInfo fcinfo, bool calcSumX2)
4934 : {
4935 : NumericAggState *state;
4936 : MemoryContext agg_context;
4937 : MemoryContext old_context;
4938 :
4939 171164 : if (!AggCheckCallContext(fcinfo, &agg_context))
4940 0 : elog(ERROR, "aggregate function called in non-aggregate context");
4941 :
4942 171164 : old_context = MemoryContextSwitchTo(agg_context);
4943 :
4944 171164 : state = (NumericAggState *) palloc0(sizeof(NumericAggState));
4945 171164 : state->calcSumX2 = calcSumX2;
4946 171164 : state->agg_context = agg_context;
4947 :
4948 171164 : MemoryContextSwitchTo(old_context);
4949 :
4950 171164 : return state;
4951 : }
4952 :
4953 : /*
4954 : * Like makeNumericAggState(), but allocate the state in the current memory
4955 : * context.
4956 : */
4957 : static NumericAggState *
4958 84 : makeNumericAggStateCurrentContext(bool calcSumX2)
4959 : {
4960 : NumericAggState *state;
4961 :
4962 84 : state = (NumericAggState *) palloc0(sizeof(NumericAggState));
4963 84 : state->calcSumX2 = calcSumX2;
4964 84 : state->agg_context = CurrentMemoryContext;
4965 :
4966 84 : return state;
4967 : }
4968 :
4969 : /*
4970 : * Accumulate a new input value for numeric aggregate functions.
4971 : */
4972 : static void
4973 2113606 : do_numeric_accum(NumericAggState *state, Numeric newval)
4974 : {
4975 : NumericVar X;
4976 : NumericVar X2;
4977 : MemoryContext old_context;
4978 :
4979 : /* Count NaN/infinity inputs separately from all else */
4980 2113606 : if (NUMERIC_IS_SPECIAL(newval))
4981 : {
4982 162 : if (NUMERIC_IS_PINF(newval))
4983 72 : state->pInfcount++;
4984 90 : else if (NUMERIC_IS_NINF(newval))
4985 36 : state->nInfcount++;
4986 : else
4987 54 : state->NaNcount++;
4988 162 : return;
4989 : }
4990 :
4991 : /* load processed number in short-lived context */
4992 2113444 : init_var_from_num(newval, &X);
4993 :
4994 : /*
4995 : * Track the highest input dscale that we've seen, to support inverse
4996 : * transitions (see do_numeric_discard).
4997 : */
4998 2113444 : if (X.dscale > state->maxScale)
4999 : {
5000 156 : state->maxScale = X.dscale;
5001 156 : state->maxScaleCount = 1;
5002 : }
5003 2113288 : else if (X.dscale == state->maxScale)
5004 2113252 : state->maxScaleCount++;
5005 :
5006 : /* if we need X^2, calculate that in short-lived context */
5007 2113444 : if (state->calcSumX2)
5008 : {
5009 240732 : init_var(&X2);
5010 240732 : mul_var(&X, &X, &X2, X.dscale * 2);
5011 : }
5012 :
5013 : /* The rest of this needs to work in the aggregate context */
5014 2113444 : old_context = MemoryContextSwitchTo(state->agg_context);
5015 :
5016 2113444 : state->N++;
5017 :
5018 : /* Accumulate sums */
5019 2113444 : accum_sum_add(&(state->sumX), &X);
5020 :
5021 2113444 : if (state->calcSumX2)
5022 240732 : accum_sum_add(&(state->sumX2), &X2);
5023 :
5024 2113444 : MemoryContextSwitchTo(old_context);
5025 : }
5026 :
5027 : /*
5028 : * Attempt to remove an input value from the aggregated state.
5029 : *
5030 : * If the value cannot be removed then the function will return false; the
5031 : * possible reasons for failing are described below.
5032 : *
5033 : * If we aggregate the values 1.01 and 2 then the result will be 3.01.
5034 : * If we are then asked to un-aggregate the 1.01 then we must fail as we
5035 : * won't be able to tell what the new aggregated value's dscale should be.
5036 : * We don't want to return 2.00 (dscale = 2), since the sum's dscale would
5037 : * have been zero if we'd really aggregated only 2.
5038 : *
5039 : * Note: alternatively, we could count the number of inputs with each possible
5040 : * dscale (up to some sane limit). Not yet clear if it's worth the trouble.
5041 : */
5042 : static bool
5043 342 : do_numeric_discard(NumericAggState *state, Numeric newval)
5044 : {
5045 : NumericVar X;
5046 : NumericVar X2;
5047 : MemoryContext old_context;
5048 :
5049 : /* Count NaN/infinity inputs separately from all else */
5050 342 : if (NUMERIC_IS_SPECIAL(newval))
5051 : {
5052 6 : if (NUMERIC_IS_PINF(newval))
5053 0 : state->pInfcount--;
5054 6 : else if (NUMERIC_IS_NINF(newval))
5055 0 : state->nInfcount--;
5056 : else
5057 6 : state->NaNcount--;
5058 6 : return true;
5059 : }
5060 :
5061 : /* load processed number in short-lived context */
5062 336 : init_var_from_num(newval, &X);
5063 :
5064 : /*
5065 : * state->sumX's dscale is the maximum dscale of any of the inputs.
5066 : * Removing the last input with that dscale would require us to recompute
5067 : * the maximum dscale of the *remaining* inputs, which we cannot do unless
5068 : * no more non-NaN inputs remain at all. So we report a failure instead,
5069 : * and force the aggregation to be redone from scratch.
5070 : */
5071 336 : if (X.dscale == state->maxScale)
5072 : {
5073 336 : if (state->maxScaleCount > 1 || state->maxScale == 0)
5074 : {
5075 : /*
5076 : * Some remaining inputs have same dscale, or dscale hasn't gotten
5077 : * above zero anyway
5078 : */
5079 318 : state->maxScaleCount--;
5080 : }
5081 18 : else if (state->N == 1)
5082 : {
5083 : /* No remaining non-NaN inputs at all, so reset maxScale */
5084 12 : state->maxScale = 0;
5085 12 : state->maxScaleCount = 0;
5086 : }
5087 : else
5088 : {
5089 : /* Correct new maxScale is uncertain, must fail */
5090 6 : return false;
5091 : }
5092 : }
5093 :
5094 : /* if we need X^2, calculate that in short-lived context */
5095 330 : if (state->calcSumX2)
5096 : {
5097 288 : init_var(&X2);
5098 288 : mul_var(&X, &X, &X2, X.dscale * 2);
5099 : }
5100 :
5101 : /* The rest of this needs to work in the aggregate context */
5102 330 : old_context = MemoryContextSwitchTo(state->agg_context);
5103 :
5104 330 : if (state->N-- > 1)
5105 : {
5106 : /* Negate X, to subtract it from the sum */
5107 312 : X.sign = (X.sign == NUMERIC_POS ? NUMERIC_NEG : NUMERIC_POS);
5108 312 : accum_sum_add(&(state->sumX), &X);
5109 :
5110 312 : if (state->calcSumX2)
5111 : {
5112 : /* Negate X^2. X^2 is always positive */
5113 288 : X2.sign = NUMERIC_NEG;
5114 288 : accum_sum_add(&(state->sumX2), &X2);
5115 : }
5116 : }
5117 : else
5118 : {
5119 : /* Zero the sums */
5120 : Assert(state->N == 0);
5121 :
5122 18 : accum_sum_reset(&state->sumX);
5123 18 : if (state->calcSumX2)
5124 0 : accum_sum_reset(&state->sumX2);
5125 : }
5126 :
5127 330 : MemoryContextSwitchTo(old_context);
5128 :
5129 330 : return true;
5130 : }
5131 :
5132 : /*
5133 : * Generic transition function for numeric aggregates that require sumX2.
5134 : */
5135 : Datum
5136 642 : numeric_accum(PG_FUNCTION_ARGS)
5137 : {
5138 : NumericAggState *state;
5139 :
5140 642 : state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
5141 :
5142 : /* Create the state data on the first call */
5143 642 : if (state == NULL)
5144 174 : state = makeNumericAggState(fcinfo, true);
5145 :
5146 642 : if (!PG_ARGISNULL(1))
5147 624 : do_numeric_accum(state, PG_GETARG_NUMERIC(1));
5148 :
5149 642 : PG_RETURN_POINTER(state);
5150 : }
5151 :
5152 : /*
5153 : * Generic combine function for numeric aggregates which require sumX2
5154 : */
5155 : Datum
5156 36 : numeric_combine(PG_FUNCTION_ARGS)
5157 : {
5158 : NumericAggState *state1;
5159 : NumericAggState *state2;
5160 : MemoryContext agg_context;
5161 : MemoryContext old_context;
5162 :
5163 36 : if (!AggCheckCallContext(fcinfo, &agg_context))
5164 0 : elog(ERROR, "aggregate function called in non-aggregate context");
5165 :
5166 36 : state1 = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
5167 36 : state2 = PG_ARGISNULL(1) ? NULL : (NumericAggState *) PG_GETARG_POINTER(1);
5168 :
5169 36 : if (state2 == NULL)
5170 0 : PG_RETURN_POINTER(state1);
5171 :
5172 : /* manually copy all fields from state2 to state1 */
5173 36 : if (state1 == NULL)
5174 : {
5175 18 : old_context = MemoryContextSwitchTo(agg_context);
5176 :
5177 18 : state1 = makeNumericAggStateCurrentContext(true);
5178 18 : state1->N = state2->N;
5179 18 : state1->NaNcount = state2->NaNcount;
5180 18 : state1->pInfcount = state2->pInfcount;
5181 18 : state1->nInfcount = state2->nInfcount;
5182 18 : state1->maxScale = state2->maxScale;
5183 18 : state1->maxScaleCount = state2->maxScaleCount;
5184 :
5185 18 : accum_sum_copy(&state1->sumX, &state2->sumX);
5186 18 : accum_sum_copy(&state1->sumX2, &state2->sumX2);
5187 :
5188 18 : MemoryContextSwitchTo(old_context);
5189 :
5190 18 : PG_RETURN_POINTER(state1);
5191 : }
5192 :
5193 18 : state1->N += state2->N;
5194 18 : state1->NaNcount += state2->NaNcount;
5195 18 : state1->pInfcount += state2->pInfcount;
5196 18 : state1->nInfcount += state2->nInfcount;
5197 :
5198 18 : if (state2->N > 0)
5199 : {
5200 : /*
5201 : * These are currently only needed for moving aggregates, but let's do
5202 : * the right thing anyway...
5203 : */
5204 18 : if (state2->maxScale > state1->maxScale)
5205 : {
5206 0 : state1->maxScale = state2->maxScale;
5207 0 : state1->maxScaleCount = state2->maxScaleCount;
5208 : }
5209 18 : else if (state2->maxScale == state1->maxScale)
5210 18 : state1->maxScaleCount += state2->maxScaleCount;
5211 :
5212 : /* The rest of this needs to work in the aggregate context */
5213 18 : old_context = MemoryContextSwitchTo(agg_context);
5214 :
5215 : /* Accumulate sums */
5216 18 : accum_sum_combine(&state1->sumX, &state2->sumX);
5217 18 : accum_sum_combine(&state1->sumX2, &state2->sumX2);
5218 :
5219 18 : MemoryContextSwitchTo(old_context);
5220 : }
5221 18 : PG_RETURN_POINTER(state1);
5222 : }
5223 :
5224 : /*
5225 : * Generic transition function for numeric aggregates that don't require sumX2.
5226 : */
5227 : Datum
5228 1872862 : numeric_avg_accum(PG_FUNCTION_ARGS)
5229 : {
5230 : NumericAggState *state;
5231 :
5232 1872862 : state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
5233 :
5234 : /* Create the state data on the first call */
5235 1872862 : if (state == NULL)
5236 170930 : state = makeNumericAggState(fcinfo, false);
5237 :
5238 1872862 : if (!PG_ARGISNULL(1))
5239 1872802 : do_numeric_accum(state, PG_GETARG_NUMERIC(1));
5240 :
5241 1872862 : PG_RETURN_POINTER(state);
5242 : }
5243 :
5244 : /*
5245 : * Combine function for numeric aggregates which don't require sumX2
5246 : */
5247 : Datum
5248 24 : numeric_avg_combine(PG_FUNCTION_ARGS)
5249 : {
5250 : NumericAggState *state1;
5251 : NumericAggState *state2;
5252 : MemoryContext agg_context;
5253 : MemoryContext old_context;
5254 :
5255 24 : if (!AggCheckCallContext(fcinfo, &agg_context))
5256 0 : elog(ERROR, "aggregate function called in non-aggregate context");
5257 :
5258 24 : state1 = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
5259 24 : state2 = PG_ARGISNULL(1) ? NULL : (NumericAggState *) PG_GETARG_POINTER(1);
5260 :
5261 24 : if (state2 == NULL)
5262 0 : PG_RETURN_POINTER(state1);
5263 :
5264 : /* manually copy all fields from state2 to state1 */
5265 24 : if (state1 == NULL)
5266 : {
5267 6 : old_context = MemoryContextSwitchTo(agg_context);
5268 :
5269 6 : state1 = makeNumericAggStateCurrentContext(false);
5270 6 : state1->N = state2->N;
5271 6 : state1->NaNcount = state2->NaNcount;
5272 6 : state1->pInfcount = state2->pInfcount;
5273 6 : state1->nInfcount = state2->nInfcount;
5274 6 : state1->maxScale = state2->maxScale;
5275 6 : state1->maxScaleCount = state2->maxScaleCount;
5276 :
5277 6 : accum_sum_copy(&state1->sumX, &state2->sumX);
5278 :
5279 6 : MemoryContextSwitchTo(old_context);
5280 :
5281 6 : PG_RETURN_POINTER(state1);
5282 : }
5283 :
5284 18 : state1->N += state2->N;
5285 18 : state1->NaNcount += state2->NaNcount;
5286 18 : state1->pInfcount += state2->pInfcount;
5287 18 : state1->nInfcount += state2->nInfcount;
5288 :
5289 18 : if (state2->N > 0)
5290 : {
5291 : /*
5292 : * These are currently only needed for moving aggregates, but let's do
5293 : * the right thing anyway...
5294 : */
5295 18 : if (state2->maxScale > state1->maxScale)
5296 : {
5297 0 : state1->maxScale = state2->maxScale;
5298 0 : state1->maxScaleCount = state2->maxScaleCount;
5299 : }
5300 18 : else if (state2->maxScale == state1->maxScale)
5301 18 : state1->maxScaleCount += state2->maxScaleCount;
5302 :
5303 : /* The rest of this needs to work in the aggregate context */
5304 18 : old_context = MemoryContextSwitchTo(agg_context);
5305 :
5306 : /* Accumulate sums */
5307 18 : accum_sum_combine(&state1->sumX, &state2->sumX);
5308 :
5309 18 : MemoryContextSwitchTo(old_context);
5310 : }
5311 18 : PG_RETURN_POINTER(state1);
5312 : }
5313 :
5314 : /*
5315 : * numeric_avg_serialize
5316 : * Serialize NumericAggState for numeric aggregates that don't require
5317 : * sumX2.
5318 : */
5319 : Datum
5320 24 : numeric_avg_serialize(PG_FUNCTION_ARGS)
5321 : {
5322 : NumericAggState *state;
5323 : StringInfoData buf;
5324 : bytea *result;
5325 : NumericVar tmp_var;
5326 :
5327 : /* Ensure we disallow calling when not in aggregate context */
5328 24 : if (!AggCheckCallContext(fcinfo, NULL))
5329 0 : elog(ERROR, "aggregate function called in non-aggregate context");
5330 :
5331 24 : state = (NumericAggState *) PG_GETARG_POINTER(0);
5332 :
5333 24 : init_var(&tmp_var);
5334 :
5335 24 : pq_begintypsend(&buf);
5336 :
5337 : /* N */
5338 24 : pq_sendint64(&buf, state->N);
5339 :
5340 : /* sumX */
5341 24 : accum_sum_final(&state->sumX, &tmp_var);
5342 24 : numericvar_serialize(&buf, &tmp_var);
5343 :
5344 : /* maxScale */
5345 24 : pq_sendint32(&buf, state->maxScale);
5346 :
5347 : /* maxScaleCount */
5348 24 : pq_sendint64(&buf, state->maxScaleCount);
5349 :
5350 : /* NaNcount */
5351 24 : pq_sendint64(&buf, state->NaNcount);
5352 :
5353 : /* pInfcount */
5354 24 : pq_sendint64(&buf, state->pInfcount);
5355 :
5356 : /* nInfcount */
5357 24 : pq_sendint64(&buf, state->nInfcount);
5358 :
5359 24 : result = pq_endtypsend(&buf);
5360 :
5361 24 : free_var(&tmp_var);
5362 :
5363 24 : PG_RETURN_BYTEA_P(result);
5364 : }
5365 :
5366 : /*
5367 : * numeric_avg_deserialize
5368 : * Deserialize bytea into NumericAggState for numeric aggregates that
5369 : * don't require sumX2.
5370 : */
5371 : Datum
5372 24 : numeric_avg_deserialize(PG_FUNCTION_ARGS)
5373 : {
5374 : bytea *sstate;
5375 : NumericAggState *result;
5376 : StringInfoData buf;
5377 : NumericVar tmp_var;
5378 :
5379 24 : if (!AggCheckCallContext(fcinfo, NULL))
5380 0 : elog(ERROR, "aggregate function called in non-aggregate context");
5381 :
5382 24 : sstate = PG_GETARG_BYTEA_PP(0);
5383 :
5384 24 : init_var(&tmp_var);
5385 :
5386 : /*
5387 : * Initialize a StringInfo so that we can "receive" it using the standard
5388 : * recv-function infrastructure.
5389 : */
5390 24 : initReadOnlyStringInfo(&buf, VARDATA_ANY(sstate),
5391 24 : VARSIZE_ANY_EXHDR(sstate));
5392 :
5393 24 : result = makeNumericAggStateCurrentContext(false);
5394 :
5395 : /* N */
5396 24 : result->N = pq_getmsgint64(&buf);
5397 :
5398 : /* sumX */
5399 24 : numericvar_deserialize(&buf, &tmp_var);
5400 24 : accum_sum_add(&(result->sumX), &tmp_var);
5401 :
5402 : /* maxScale */
5403 24 : result->maxScale = pq_getmsgint(&buf, 4);
5404 :
5405 : /* maxScaleCount */
5406 24 : result->maxScaleCount = pq_getmsgint64(&buf);
5407 :
5408 : /* NaNcount */
5409 24 : result->NaNcount = pq_getmsgint64(&buf);
5410 :
5411 : /* pInfcount */
5412 24 : result->pInfcount = pq_getmsgint64(&buf);
5413 :
5414 : /* nInfcount */
5415 24 : result->nInfcount = pq_getmsgint64(&buf);
5416 :
5417 24 : pq_getmsgend(&buf);
5418 :
5419 24 : free_var(&tmp_var);
5420 :
5421 24 : PG_RETURN_POINTER(result);
5422 : }
5423 :
5424 : /*
5425 : * numeric_serialize
5426 : * Serialization function for NumericAggState for numeric aggregates that
5427 : * require sumX2.
5428 : */
5429 : Datum
5430 36 : numeric_serialize(PG_FUNCTION_ARGS)
5431 : {
5432 : NumericAggState *state;
5433 : StringInfoData buf;
5434 : bytea *result;
5435 : NumericVar tmp_var;
5436 :
5437 : /* Ensure we disallow calling when not in aggregate context */
5438 36 : if (!AggCheckCallContext(fcinfo, NULL))
5439 0 : elog(ERROR, "aggregate function called in non-aggregate context");
5440 :
5441 36 : state = (NumericAggState *) PG_GETARG_POINTER(0);
5442 :
5443 36 : init_var(&tmp_var);
5444 :
5445 36 : pq_begintypsend(&buf);
5446 :
5447 : /* N */
5448 36 : pq_sendint64(&buf, state->N);
5449 :
5450 : /* sumX */
5451 36 : accum_sum_final(&state->sumX, &tmp_var);
5452 36 : numericvar_serialize(&buf, &tmp_var);
5453 :
5454 : /* sumX2 */
5455 36 : accum_sum_final(&state->sumX2, &tmp_var);
5456 36 : numericvar_serialize(&buf, &tmp_var);
5457 :
5458 : /* maxScale */
5459 36 : pq_sendint32(&buf, state->maxScale);
5460 :
5461 : /* maxScaleCount */
5462 36 : pq_sendint64(&buf, state->maxScaleCount);
5463 :
5464 : /* NaNcount */
5465 36 : pq_sendint64(&buf, state->NaNcount);
5466 :
5467 : /* pInfcount */
5468 36 : pq_sendint64(&buf, state->pInfcount);
5469 :
5470 : /* nInfcount */
5471 36 : pq_sendint64(&buf, state->nInfcount);
5472 :
5473 36 : result = pq_endtypsend(&buf);
5474 :
5475 36 : free_var(&tmp_var);
5476 :
5477 36 : PG_RETURN_BYTEA_P(result);
5478 : }
5479 :
5480 : /*
5481 : * numeric_deserialize
5482 : * Deserialization function for NumericAggState for numeric aggregates that
5483 : * require sumX2.
5484 : */
5485 : Datum
5486 36 : numeric_deserialize(PG_FUNCTION_ARGS)
5487 : {
5488 : bytea *sstate;
5489 : NumericAggState *result;
5490 : StringInfoData buf;
5491 : NumericVar tmp_var;
5492 :
5493 36 : if (!AggCheckCallContext(fcinfo, NULL))
5494 0 : elog(ERROR, "aggregate function called in non-aggregate context");
5495 :
5496 36 : sstate = PG_GETARG_BYTEA_PP(0);
5497 :
5498 36 : init_var(&tmp_var);
5499 :
5500 : /*
5501 : * Initialize a StringInfo so that we can "receive" it using the standard
5502 : * recv-function infrastructure.
5503 : */
5504 36 : initReadOnlyStringInfo(&buf, VARDATA_ANY(sstate),
5505 36 : VARSIZE_ANY_EXHDR(sstate));
5506 :
5507 36 : result = makeNumericAggStateCurrentContext(false);
5508 :
5509 : /* N */
5510 36 : result->N = pq_getmsgint64(&buf);
5511 :
5512 : /* sumX */
5513 36 : numericvar_deserialize(&buf, &tmp_var);
5514 36 : accum_sum_add(&(result->sumX), &tmp_var);
5515 :
5516 : /* sumX2 */
5517 36 : numericvar_deserialize(&buf, &tmp_var);
5518 36 : accum_sum_add(&(result->sumX2), &tmp_var);
5519 :
5520 : /* maxScale */
5521 36 : result->maxScale = pq_getmsgint(&buf, 4);
5522 :
5523 : /* maxScaleCount */
5524 36 : result->maxScaleCount = pq_getmsgint64(&buf);
5525 :
5526 : /* NaNcount */
5527 36 : result->NaNcount = pq_getmsgint64(&buf);
5528 :
5529 : /* pInfcount */
5530 36 : result->pInfcount = pq_getmsgint64(&buf);
5531 :
5532 : /* nInfcount */
5533 36 : result->nInfcount = pq_getmsgint64(&buf);
5534 :
5535 36 : pq_getmsgend(&buf);
5536 :
5537 36 : free_var(&tmp_var);
5538 :
5539 36 : PG_RETURN_POINTER(result);
5540 : }
5541 :
5542 : /*
5543 : * Generic inverse transition function for numeric aggregates
5544 : * (with or without requirement for X^2).
5545 : */
5546 : Datum
5547 228 : numeric_accum_inv(PG_FUNCTION_ARGS)
5548 : {
5549 : NumericAggState *state;
5550 :
5551 228 : state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
5552 :
5553 : /* Should not get here with no state */
5554 228 : if (state == NULL)
5555 0 : elog(ERROR, "numeric_accum_inv called with NULL state");
5556 :
5557 228 : if (!PG_ARGISNULL(1))
5558 : {
5559 : /* If we fail to perform the inverse transition, return NULL */
5560 198 : if (!do_numeric_discard(state, PG_GETARG_NUMERIC(1)))
5561 6 : PG_RETURN_NULL();
5562 : }
5563 :
5564 222 : PG_RETURN_POINTER(state);
5565 : }
5566 :
5567 :
5568 : /*
5569 : * Integer data types in general use Numeric accumulators to share code
5570 : * and avoid risk of overflow.
5571 : *
5572 : * However for performance reasons optimized special-purpose accumulator
5573 : * routines are used when possible.
5574 : *
5575 : * On platforms with 128-bit integer support, the 128-bit routines will be
5576 : * used when sum(X) or sum(X*X) fit into 128-bit.
5577 : *
5578 : * For 16 and 32 bit inputs, the N and sum(X) fit into 64-bit so the 64-bit
5579 : * accumulators will be used for SUM and AVG of these data types.
5580 : */
5581 :
5582 : #ifdef HAVE_INT128
5583 : typedef struct Int128AggState
5584 : {
5585 : bool calcSumX2; /* if true, calculate sumX2 */
5586 : int64 N; /* count of processed numbers */
5587 : int128 sumX; /* sum of processed numbers */
5588 : int128 sumX2; /* sum of squares of processed numbers */
5589 : } Int128AggState;
5590 :
5591 : /*
5592 : * Prepare state data for a 128-bit aggregate function that needs to compute
5593 : * sum, count and optionally sum of squares of the input.
5594 : */
5595 : static Int128AggState *
5596 896 : makeInt128AggState(FunctionCallInfo fcinfo, bool calcSumX2)
5597 : {
5598 : Int128AggState *state;
5599 : MemoryContext agg_context;
5600 : MemoryContext old_context;
5601 :
5602 896 : if (!AggCheckCallContext(fcinfo, &agg_context))
5603 0 : elog(ERROR, "aggregate function called in non-aggregate context");
5604 :
5605 896 : old_context = MemoryContextSwitchTo(agg_context);
5606 :
5607 896 : state = (Int128AggState *) palloc0(sizeof(Int128AggState));
5608 896 : state->calcSumX2 = calcSumX2;
5609 :
5610 896 : MemoryContextSwitchTo(old_context);
5611 :
5612 896 : return state;
5613 : }
5614 :
5615 : /*
5616 : * Like makeInt128AggState(), but allocate the state in the current memory
5617 : * context.
5618 : */
5619 : static Int128AggState *
5620 42 : makeInt128AggStateCurrentContext(bool calcSumX2)
5621 : {
5622 : Int128AggState *state;
5623 :
5624 42 : state = (Int128AggState *) palloc0(sizeof(Int128AggState));
5625 42 : state->calcSumX2 = calcSumX2;
5626 :
5627 42 : return state;
5628 : }
5629 :
5630 : /*
5631 : * Accumulate a new input value for 128-bit aggregate functions.
5632 : */
5633 : static void
5634 557178 : do_int128_accum(Int128AggState *state, int128 newval)
5635 : {
5636 557178 : if (state->calcSumX2)
5637 242360 : state->sumX2 += newval * newval;
5638 :
5639 557178 : state->sumX += newval;
5640 557178 : state->N++;
5641 557178 : }
5642 :
5643 : /*
5644 : * Remove an input value from the aggregated state.
5645 : */
5646 : static void
5647 312 : do_int128_discard(Int128AggState *state, int128 newval)
5648 : {
5649 312 : if (state->calcSumX2)
5650 288 : state->sumX2 -= newval * newval;
5651 :
5652 312 : state->sumX -= newval;
5653 312 : state->N--;
5654 312 : }
5655 :
5656 : typedef Int128AggState PolyNumAggState;
5657 : #define makePolyNumAggState makeInt128AggState
5658 : #define makePolyNumAggStateCurrentContext makeInt128AggStateCurrentContext
5659 : #else
5660 : typedef NumericAggState PolyNumAggState;
5661 : #define makePolyNumAggState makeNumericAggState
5662 : #define makePolyNumAggStateCurrentContext makeNumericAggStateCurrentContext
5663 : #endif
5664 :
5665 : Datum
5666 198 : int2_accum(PG_FUNCTION_ARGS)
5667 : {
5668 : PolyNumAggState *state;
5669 :
5670 198 : state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
5671 :
5672 : /* Create the state data on the first call */
5673 198 : if (state == NULL)
5674 36 : state = makePolyNumAggState(fcinfo, true);
5675 :
5676 198 : if (!PG_ARGISNULL(1))
5677 : {
5678 : #ifdef HAVE_INT128
5679 180 : do_int128_accum(state, (int128) PG_GETARG_INT16(1));
5680 : #else
5681 : do_numeric_accum(state, int64_to_numeric(PG_GETARG_INT16(1)));
5682 : #endif
5683 : }
5684 :
5685 198 : PG_RETURN_POINTER(state);
5686 : }
5687 :
5688 : Datum
5689 242198 : int4_accum(PG_FUNCTION_ARGS)
5690 : {
5691 : PolyNumAggState *state;
5692 :
5693 242198 : state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
5694 :
5695 : /* Create the state data on the first call */
5696 242198 : if (state == NULL)
5697 74 : state = makePolyNumAggState(fcinfo, true);
5698 :
5699 242198 : if (!PG_ARGISNULL(1))
5700 : {
5701 : #ifdef HAVE_INT128
5702 242180 : do_int128_accum(state, (int128) PG_GETARG_INT32(1));
5703 : #else
5704 : do_numeric_accum(state, int64_to_numeric(PG_GETARG_INT32(1)));
5705 : #endif
5706 : }
5707 :
5708 242198 : PG_RETURN_POINTER(state);
5709 : }
5710 :
5711 : Datum
5712 240198 : int8_accum(PG_FUNCTION_ARGS)
5713 : {
5714 : NumericAggState *state;
5715 :
5716 240198 : state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
5717 :
5718 : /* Create the state data on the first call */
5719 240198 : if (state == NULL)
5720 60 : state = makeNumericAggState(fcinfo, true);
5721 :
5722 240198 : if (!PG_ARGISNULL(1))
5723 240180 : do_numeric_accum(state, int64_to_numeric(PG_GETARG_INT64(1)));
5724 :
5725 240198 : PG_RETURN_POINTER(state);
5726 : }
5727 :
5728 : /*
5729 : * Combine function for numeric aggregates which require sumX2
5730 : */
5731 : Datum
5732 18 : numeric_poly_combine(PG_FUNCTION_ARGS)
5733 : {
5734 : PolyNumAggState *state1;
5735 : PolyNumAggState *state2;
5736 : MemoryContext agg_context;
5737 : MemoryContext old_context;
5738 :
5739 18 : if (!AggCheckCallContext(fcinfo, &agg_context))
5740 0 : elog(ERROR, "aggregate function called in non-aggregate context");
5741 :
5742 18 : state1 = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
5743 18 : state2 = PG_ARGISNULL(1) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(1);
5744 :
5745 18 : if (state2 == NULL)
5746 0 : PG_RETURN_POINTER(state1);
5747 :
5748 : /* manually copy all fields from state2 to state1 */
5749 18 : if (state1 == NULL)
5750 : {
5751 6 : old_context = MemoryContextSwitchTo(agg_context);
5752 :
5753 6 : state1 = makePolyNumAggState(fcinfo, true);
5754 6 : state1->N = state2->N;
5755 :
5756 : #ifdef HAVE_INT128
5757 6 : state1->sumX = state2->sumX;
5758 6 : state1->sumX2 = state2->sumX2;
5759 : #else
5760 : accum_sum_copy(&state1->sumX, &state2->sumX);
5761 : accum_sum_copy(&state1->sumX2, &state2->sumX2);
5762 : #endif
5763 :
5764 6 : MemoryContextSwitchTo(old_context);
5765 :
5766 6 : PG_RETURN_POINTER(state1);
5767 : }
5768 :
5769 12 : if (state2->N > 0)
5770 : {
5771 12 : state1->N += state2->N;
5772 :
5773 : #ifdef HAVE_INT128
5774 12 : state1->sumX += state2->sumX;
5775 12 : state1->sumX2 += state2->sumX2;
5776 : #else
5777 : /* The rest of this needs to work in the aggregate context */
5778 : old_context = MemoryContextSwitchTo(agg_context);
5779 :
5780 : /* Accumulate sums */
5781 : accum_sum_combine(&state1->sumX, &state2->sumX);
5782 : accum_sum_combine(&state1->sumX2, &state2->sumX2);
5783 :
5784 : MemoryContextSwitchTo(old_context);
5785 : #endif
5786 :
5787 : }
5788 12 : PG_RETURN_POINTER(state1);
5789 : }
5790 :
5791 : /*
5792 : * numeric_poly_serialize
5793 : * Serialize PolyNumAggState into bytea for aggregate functions which
5794 : * require sumX2.
5795 : */
5796 : Datum
5797 18 : numeric_poly_serialize(PG_FUNCTION_ARGS)
5798 : {
5799 : PolyNumAggState *state;
5800 : StringInfoData buf;
5801 : bytea *result;
5802 : NumericVar tmp_var;
5803 :
5804 : /* Ensure we disallow calling when not in aggregate context */
5805 18 : if (!AggCheckCallContext(fcinfo, NULL))
5806 0 : elog(ERROR, "aggregate function called in non-aggregate context");
5807 :
5808 18 : state = (PolyNumAggState *) PG_GETARG_POINTER(0);
5809 :
5810 : /*
5811 : * If the platform supports int128 then sumX and sumX2 will be a 128 bit
5812 : * integer type. Here we'll convert that into a numeric type so that the
5813 : * combine state is in the same format for both int128 enabled machines
5814 : * and machines which don't support that type. The logic here is that one
5815 : * day we might like to send these over to another server for further
5816 : * processing and we want a standard format to work with.
5817 : */
5818 :
5819 18 : init_var(&tmp_var);
5820 :
5821 18 : pq_begintypsend(&buf);
5822 :
5823 : /* N */
5824 18 : pq_sendint64(&buf, state->N);
5825 :
5826 : /* sumX */
5827 : #ifdef HAVE_INT128
5828 18 : int128_to_numericvar(state->sumX, &tmp_var);
5829 : #else
5830 : accum_sum_final(&state->sumX, &tmp_var);
5831 : #endif
5832 18 : numericvar_serialize(&buf, &tmp_var);
5833 :
5834 : /* sumX2 */
5835 : #ifdef HAVE_INT128
5836 18 : int128_to_numericvar(state->sumX2, &tmp_var);
5837 : #else
5838 : accum_sum_final(&state->sumX2, &tmp_var);
5839 : #endif
5840 18 : numericvar_serialize(&buf, &tmp_var);
5841 :
5842 18 : result = pq_endtypsend(&buf);
5843 :
5844 18 : free_var(&tmp_var);
5845 :
5846 18 : PG_RETURN_BYTEA_P(result);
5847 : }
5848 :
5849 : /*
5850 : * numeric_poly_deserialize
5851 : * Deserialize PolyNumAggState from bytea for aggregate functions which
5852 : * require sumX2.
5853 : */
5854 : Datum
5855 18 : numeric_poly_deserialize(PG_FUNCTION_ARGS)
5856 : {
5857 : bytea *sstate;
5858 : PolyNumAggState *result;
5859 : StringInfoData buf;
5860 : NumericVar tmp_var;
5861 :
5862 18 : if (!AggCheckCallContext(fcinfo, NULL))
5863 0 : elog(ERROR, "aggregate function called in non-aggregate context");
5864 :
5865 18 : sstate = PG_GETARG_BYTEA_PP(0);
5866 :
5867 18 : init_var(&tmp_var);
5868 :
5869 : /*
5870 : * Initialize a StringInfo so that we can "receive" it using the standard
5871 : * recv-function infrastructure.
5872 : */
5873 18 : initReadOnlyStringInfo(&buf, VARDATA_ANY(sstate),
5874 18 : VARSIZE_ANY_EXHDR(sstate));
5875 :
5876 18 : result = makePolyNumAggStateCurrentContext(false);
5877 :
5878 : /* N */
5879 18 : result->N = pq_getmsgint64(&buf);
5880 :
5881 : /* sumX */
5882 18 : numericvar_deserialize(&buf, &tmp_var);
5883 : #ifdef HAVE_INT128
5884 18 : numericvar_to_int128(&tmp_var, &result->sumX);
5885 : #else
5886 : accum_sum_add(&result->sumX, &tmp_var);
5887 : #endif
5888 :
5889 : /* sumX2 */
5890 18 : numericvar_deserialize(&buf, &tmp_var);
5891 : #ifdef HAVE_INT128
5892 18 : numericvar_to_int128(&tmp_var, &result->sumX2);
5893 : #else
5894 : accum_sum_add(&result->sumX2, &tmp_var);
5895 : #endif
5896 :
5897 18 : pq_getmsgend(&buf);
5898 :
5899 18 : free_var(&tmp_var);
5900 :
5901 18 : PG_RETURN_POINTER(result);
5902 : }
5903 :
5904 : /*
5905 : * Transition function for int8 input when we don't need sumX2.
5906 : */
5907 : Datum
5908 318616 : int8_avg_accum(PG_FUNCTION_ARGS)
5909 : {
5910 : PolyNumAggState *state;
5911 :
5912 318616 : state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
5913 :
5914 : /* Create the state data on the first call */
5915 318616 : if (state == NULL)
5916 768 : state = makePolyNumAggState(fcinfo, false);
5917 :
5918 318616 : if (!PG_ARGISNULL(1))
5919 : {
5920 : #ifdef HAVE_INT128
5921 314818 : do_int128_accum(state, (int128) PG_GETARG_INT64(1));
5922 : #else
5923 : do_numeric_accum(state, int64_to_numeric(PG_GETARG_INT64(1)));
5924 : #endif
5925 : }
5926 :
5927 318616 : PG_RETURN_POINTER(state);
5928 : }
5929 :
5930 : /*
5931 : * Combine function for PolyNumAggState for aggregates which don't require
5932 : * sumX2
5933 : */
5934 : Datum
5935 24 : int8_avg_combine(PG_FUNCTION_ARGS)
5936 : {
5937 : PolyNumAggState *state1;
5938 : PolyNumAggState *state2;
5939 : MemoryContext agg_context;
5940 : MemoryContext old_context;
5941 :
5942 24 : if (!AggCheckCallContext(fcinfo, &agg_context))
5943 0 : elog(ERROR, "aggregate function called in non-aggregate context");
5944 :
5945 24 : state1 = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
5946 24 : state2 = PG_ARGISNULL(1) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(1);
5947 :
5948 24 : if (state2 == NULL)
5949 0 : PG_RETURN_POINTER(state1);
5950 :
5951 : /* manually copy all fields from state2 to state1 */
5952 24 : if (state1 == NULL)
5953 : {
5954 12 : old_context = MemoryContextSwitchTo(agg_context);
5955 :
5956 12 : state1 = makePolyNumAggState(fcinfo, false);
5957 12 : state1->N = state2->N;
5958 :
5959 : #ifdef HAVE_INT128
5960 12 : state1->sumX = state2->sumX;
5961 : #else
5962 : accum_sum_copy(&state1->sumX, &state2->sumX);
5963 : #endif
5964 12 : MemoryContextSwitchTo(old_context);
5965 :
5966 12 : PG_RETURN_POINTER(state1);
5967 : }
5968 :
5969 12 : if (state2->N > 0)
5970 : {
5971 12 : state1->N += state2->N;
5972 :
5973 : #ifdef HAVE_INT128
5974 12 : state1->sumX += state2->sumX;
5975 : #else
5976 : /* The rest of this needs to work in the aggregate context */
5977 : old_context = MemoryContextSwitchTo(agg_context);
5978 :
5979 : /* Accumulate sums */
5980 : accum_sum_combine(&state1->sumX, &state2->sumX);
5981 :
5982 : MemoryContextSwitchTo(old_context);
5983 : #endif
5984 :
5985 : }
5986 12 : PG_RETURN_POINTER(state1);
5987 : }
5988 :
5989 : /*
5990 : * int8_avg_serialize
5991 : * Serialize PolyNumAggState into bytea using the standard
5992 : * recv-function infrastructure.
5993 : */
5994 : Datum
5995 24 : int8_avg_serialize(PG_FUNCTION_ARGS)
5996 : {
5997 : PolyNumAggState *state;
5998 : StringInfoData buf;
5999 : bytea *result;
6000 : NumericVar tmp_var;
6001 :
6002 : /* Ensure we disallow calling when not in aggregate context */
6003 24 : if (!AggCheckCallContext(fcinfo, NULL))
6004 0 : elog(ERROR, "aggregate function called in non-aggregate context");
6005 :
6006 24 : state = (PolyNumAggState *) PG_GETARG_POINTER(0);
6007 :
6008 : /*
6009 : * If the platform supports int128 then sumX will be a 128 integer type.
6010 : * Here we'll convert that into a numeric type so that the combine state
6011 : * is in the same format for both int128 enabled machines and machines
6012 : * which don't support that type. The logic here is that one day we might
6013 : * like to send these over to another server for further processing and we
6014 : * want a standard format to work with.
6015 : */
6016 :
6017 24 : init_var(&tmp_var);
6018 :
6019 24 : pq_begintypsend(&buf);
6020 :
6021 : /* N */
6022 24 : pq_sendint64(&buf, state->N);
6023 :
6024 : /* sumX */
6025 : #ifdef HAVE_INT128
6026 24 : int128_to_numericvar(state->sumX, &tmp_var);
6027 : #else
6028 : accum_sum_final(&state->sumX, &tmp_var);
6029 : #endif
6030 24 : numericvar_serialize(&buf, &tmp_var);
6031 :
6032 24 : result = pq_endtypsend(&buf);
6033 :
6034 24 : free_var(&tmp_var);
6035 :
6036 24 : PG_RETURN_BYTEA_P(result);
6037 : }
6038 :
6039 : /*
6040 : * int8_avg_deserialize
6041 : * Deserialize bytea back into PolyNumAggState.
6042 : */
6043 : Datum
6044 24 : int8_avg_deserialize(PG_FUNCTION_ARGS)
6045 : {
6046 : bytea *sstate;
6047 : PolyNumAggState *result;
6048 : StringInfoData buf;
6049 : NumericVar tmp_var;
6050 :
6051 24 : if (!AggCheckCallContext(fcinfo, NULL))
6052 0 : elog(ERROR, "aggregate function called in non-aggregate context");
6053 :
6054 24 : sstate = PG_GETARG_BYTEA_PP(0);
6055 :
6056 24 : init_var(&tmp_var);
6057 :
6058 : /*
6059 : * Initialize a StringInfo so that we can "receive" it using the standard
6060 : * recv-function infrastructure.
6061 : */
6062 24 : initReadOnlyStringInfo(&buf, VARDATA_ANY(sstate),
6063 24 : VARSIZE_ANY_EXHDR(sstate));
6064 :
6065 24 : result = makePolyNumAggStateCurrentContext(false);
6066 :
6067 : /* N */
6068 24 : result->N = pq_getmsgint64(&buf);
6069 :
6070 : /* sumX */
6071 24 : numericvar_deserialize(&buf, &tmp_var);
6072 : #ifdef HAVE_INT128
6073 24 : numericvar_to_int128(&tmp_var, &result->sumX);
6074 : #else
6075 : accum_sum_add(&result->sumX, &tmp_var);
6076 : #endif
6077 :
6078 24 : pq_getmsgend(&buf);
6079 :
6080 24 : free_var(&tmp_var);
6081 :
6082 24 : PG_RETURN_POINTER(result);
6083 : }
6084 :
6085 : /*
6086 : * Inverse transition functions to go with the above.
6087 : */
6088 :
6089 : Datum
6090 162 : int2_accum_inv(PG_FUNCTION_ARGS)
6091 : {
6092 : PolyNumAggState *state;
6093 :
6094 162 : state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
6095 :
6096 : /* Should not get here with no state */
6097 162 : if (state == NULL)
6098 0 : elog(ERROR, "int2_accum_inv called with NULL state");
6099 :
6100 162 : if (!PG_ARGISNULL(1))
6101 : {
6102 : #ifdef HAVE_INT128
6103 144 : do_int128_discard(state, (int128) PG_GETARG_INT16(1));
6104 : #else
6105 : /* Should never fail, all inputs have dscale 0 */
6106 : if (!do_numeric_discard(state, int64_to_numeric(PG_GETARG_INT16(1))))
6107 : elog(ERROR, "do_numeric_discard failed unexpectedly");
6108 : #endif
6109 : }
6110 :
6111 162 : PG_RETURN_POINTER(state);
6112 : }
6113 :
6114 : Datum
6115 162 : int4_accum_inv(PG_FUNCTION_ARGS)
6116 : {
6117 : PolyNumAggState *state;
6118 :
6119 162 : state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
6120 :
6121 : /* Should not get here with no state */
6122 162 : if (state == NULL)
6123 0 : elog(ERROR, "int4_accum_inv called with NULL state");
6124 :
6125 162 : if (!PG_ARGISNULL(1))
6126 : {
6127 : #ifdef HAVE_INT128
6128 144 : do_int128_discard(state, (int128) PG_GETARG_INT32(1));
6129 : #else
6130 : /* Should never fail, all inputs have dscale 0 */
6131 : if (!do_numeric_discard(state, int64_to_numeric(PG_GETARG_INT32(1))))
6132 : elog(ERROR, "do_numeric_discard failed unexpectedly");
6133 : #endif
6134 : }
6135 :
6136 162 : PG_RETURN_POINTER(state);
6137 : }
6138 :
6139 : Datum
6140 162 : int8_accum_inv(PG_FUNCTION_ARGS)
6141 : {
6142 : NumericAggState *state;
6143 :
6144 162 : state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
6145 :
6146 : /* Should not get here with no state */
6147 162 : if (state == NULL)
6148 0 : elog(ERROR, "int8_accum_inv called with NULL state");
6149 :
6150 162 : if (!PG_ARGISNULL(1))
6151 : {
6152 : /* Should never fail, all inputs have dscale 0 */
6153 144 : if (!do_numeric_discard(state, int64_to_numeric(PG_GETARG_INT64(1))))
6154 0 : elog(ERROR, "do_numeric_discard failed unexpectedly");
6155 : }
6156 :
6157 162 : PG_RETURN_POINTER(state);
6158 : }
6159 :
6160 : Datum
6161 36 : int8_avg_accum_inv(PG_FUNCTION_ARGS)
6162 : {
6163 : PolyNumAggState *state;
6164 :
6165 36 : state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
6166 :
6167 : /* Should not get here with no state */
6168 36 : if (state == NULL)
6169 0 : elog(ERROR, "int8_avg_accum_inv called with NULL state");
6170 :
6171 36 : if (!PG_ARGISNULL(1))
6172 : {
6173 : #ifdef HAVE_INT128
6174 24 : do_int128_discard(state, (int128) PG_GETARG_INT64(1));
6175 : #else
6176 : /* Should never fail, all inputs have dscale 0 */
6177 : if (!do_numeric_discard(state, int64_to_numeric(PG_GETARG_INT64(1))))
6178 : elog(ERROR, "do_numeric_discard failed unexpectedly");
6179 : #endif
6180 : }
6181 :
6182 36 : PG_RETURN_POINTER(state);
6183 : }
6184 :
6185 : Datum
6186 990 : numeric_poly_sum(PG_FUNCTION_ARGS)
6187 : {
6188 : #ifdef HAVE_INT128
6189 : PolyNumAggState *state;
6190 : Numeric res;
6191 : NumericVar result;
6192 :
6193 990 : state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
6194 :
6195 : /* If there were no non-null inputs, return NULL */
6196 990 : if (state == NULL || state->N == 0)
6197 24 : PG_RETURN_NULL();
6198 :
6199 966 : init_var(&result);
6200 :
6201 966 : int128_to_numericvar(state->sumX, &result);
6202 :
6203 966 : res = make_result(&result);
6204 :
6205 966 : free_var(&result);
6206 :
6207 966 : PG_RETURN_NUMERIC(res);
6208 : #else
6209 : return numeric_sum(fcinfo);
6210 : #endif
6211 : }
6212 :
6213 : Datum
6214 36 : numeric_poly_avg(PG_FUNCTION_ARGS)
6215 : {
6216 : #ifdef HAVE_INT128
6217 : PolyNumAggState *state;
6218 : NumericVar result;
6219 : Datum countd,
6220 : sumd;
6221 :
6222 36 : state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
6223 :
6224 : /* If there were no non-null inputs, return NULL */
6225 36 : if (state == NULL || state->N == 0)
6226 18 : PG_RETURN_NULL();
6227 :
6228 18 : init_var(&result);
6229 :
6230 18 : int128_to_numericvar(state->sumX, &result);
6231 :
6232 18 : countd = NumericGetDatum(int64_to_numeric(state->N));
6233 18 : sumd = NumericGetDatum(make_result(&result));
6234 :
6235 18 : free_var(&result);
6236 :
6237 18 : PG_RETURN_DATUM(DirectFunctionCall2(numeric_div, sumd, countd));
6238 : #else
6239 : return numeric_avg(fcinfo);
6240 : #endif
6241 : }
6242 :
6243 : Datum
6244 78 : numeric_avg(PG_FUNCTION_ARGS)
6245 : {
6246 : NumericAggState *state;
6247 : Datum N_datum;
6248 : Datum sumX_datum;
6249 : NumericVar sumX_var;
6250 :
6251 78 : state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
6252 :
6253 : /* If there were no non-null inputs, return NULL */
6254 78 : if (state == NULL || NA_TOTAL_COUNT(state) == 0)
6255 18 : PG_RETURN_NULL();
6256 :
6257 60 : if (state->NaNcount > 0) /* there was at least one NaN input */
6258 6 : PG_RETURN_NUMERIC(make_result(&const_nan));
6259 :
6260 : /* adding plus and minus infinities gives NaN */
6261 54 : if (state->pInfcount > 0 && state->nInfcount > 0)
6262 6 : PG_RETURN_NUMERIC(make_result(&const_nan));
6263 48 : if (state->pInfcount > 0)
6264 18 : PG_RETURN_NUMERIC(make_result(&const_pinf));
6265 30 : if (state->nInfcount > 0)
6266 6 : PG_RETURN_NUMERIC(make_result(&const_ninf));
6267 :
6268 24 : N_datum = NumericGetDatum(int64_to_numeric(state->N));
6269 :
6270 24 : init_var(&sumX_var);
6271 24 : accum_sum_final(&state->sumX, &sumX_var);
6272 24 : sumX_datum = NumericGetDatum(make_result(&sumX_var));
6273 24 : free_var(&sumX_var);
6274 :
6275 24 : PG_RETURN_DATUM(DirectFunctionCall2(numeric_div, sumX_datum, N_datum));
6276 : }
6277 :
6278 : Datum
6279 170930 : numeric_sum(PG_FUNCTION_ARGS)
6280 : {
6281 : NumericAggState *state;
6282 : NumericVar sumX_var;
6283 : Numeric result;
6284 :
6285 170930 : state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
6286 :
6287 : /* If there were no non-null inputs, return NULL */
6288 170930 : if (state == NULL || NA_TOTAL_COUNT(state) == 0)
6289 18 : PG_RETURN_NULL();
6290 :
6291 170912 : if (state->NaNcount > 0) /* there was at least one NaN input */
6292 18 : PG_RETURN_NUMERIC(make_result(&const_nan));
6293 :
6294 : /* adding plus and minus infinities gives NaN */
6295 170894 : if (state->pInfcount > 0 && state->nInfcount > 0)
6296 6 : PG_RETURN_NUMERIC(make_result(&const_nan));
6297 170888 : if (state->pInfcount > 0)
6298 18 : PG_RETURN_NUMERIC(make_result(&const_pinf));
6299 170870 : if (state->nInfcount > 0)
6300 6 : PG_RETURN_NUMERIC(make_result(&const_ninf));
6301 :
6302 170864 : init_var(&sumX_var);
6303 170864 : accum_sum_final(&state->sumX, &sumX_var);
6304 170864 : result = make_result(&sumX_var);
6305 170864 : free_var(&sumX_var);
6306 :
6307 170864 : PG_RETURN_NUMERIC(result);
6308 : }
6309 :
6310 : /*
6311 : * Workhorse routine for the standard deviance and variance
6312 : * aggregates. 'state' is aggregate's transition state.
6313 : * 'variance' specifies whether we should calculate the
6314 : * variance or the standard deviation. 'sample' indicates whether the
6315 : * caller is interested in the sample or the population
6316 : * variance/stddev.
6317 : *
6318 : * If appropriate variance statistic is undefined for the input,
6319 : * *is_null is set to true and NULL is returned.
6320 : */
6321 : static Numeric
6322 986 : numeric_stddev_internal(NumericAggState *state,
6323 : bool variance, bool sample,
6324 : bool *is_null)
6325 : {
6326 : Numeric res;
6327 : NumericVar vN,
6328 : vsumX,
6329 : vsumX2,
6330 : vNminus1;
6331 : int64 totCount;
6332 : int rscale;
6333 :
6334 : /*
6335 : * Sample stddev and variance are undefined when N <= 1; population stddev
6336 : * is undefined when N == 0. Return NULL in either case (note that NaNs
6337 : * and infinities count as normal inputs for this purpose).
6338 : */
6339 986 : if (state == NULL || (totCount = NA_TOTAL_COUNT(state)) == 0)
6340 : {
6341 0 : *is_null = true;
6342 0 : return NULL;
6343 : }
6344 :
6345 986 : if (sample && totCount <= 1)
6346 : {
6347 132 : *is_null = true;
6348 132 : return NULL;
6349 : }
6350 :
6351 854 : *is_null = false;
6352 :
6353 : /*
6354 : * Deal with NaN and infinity cases. By analogy to the behavior of the
6355 : * float8 functions, any infinity input produces NaN output.
6356 : */
6357 854 : if (state->NaNcount > 0 || state->pInfcount > 0 || state->nInfcount > 0)
6358 54 : return make_result(&const_nan);
6359 :
6360 : /* OK, normal calculation applies */
6361 800 : init_var(&vN);
6362 800 : init_var(&vsumX);
6363 800 : init_var(&vsumX2);
6364 :
6365 800 : int64_to_numericvar(state->N, &vN);
6366 800 : accum_sum_final(&(state->sumX), &vsumX);
6367 800 : accum_sum_final(&(state->sumX2), &vsumX2);
6368 :
6369 800 : init_var(&vNminus1);
6370 800 : sub_var(&vN, &const_one, &vNminus1);
6371 :
6372 : /* compute rscale for mul_var calls */
6373 800 : rscale = vsumX.dscale * 2;
6374 :
6375 800 : mul_var(&vsumX, &vsumX, &vsumX, rscale); /* vsumX = sumX * sumX */
6376 800 : mul_var(&vN, &vsumX2, &vsumX2, rscale); /* vsumX2 = N * sumX2 */
6377 800 : sub_var(&vsumX2, &vsumX, &vsumX2); /* N * sumX2 - sumX * sumX */
6378 :
6379 800 : if (cmp_var(&vsumX2, &const_zero) <= 0)
6380 : {
6381 : /* Watch out for roundoff error producing a negative numerator */
6382 80 : res = make_result(&const_zero);
6383 : }
6384 : else
6385 : {
6386 720 : if (sample)
6387 492 : mul_var(&vN, &vNminus1, &vNminus1, 0); /* N * (N - 1) */
6388 : else
6389 228 : mul_var(&vN, &vN, &vNminus1, 0); /* N * N */
6390 720 : rscale = select_div_scale(&vsumX2, &vNminus1);
6391 720 : div_var(&vsumX2, &vNminus1, &vsumX, rscale, true, true); /* variance */
6392 720 : if (!variance)
6393 378 : sqrt_var(&vsumX, &vsumX, rscale); /* stddev */
6394 :
6395 720 : res = make_result(&vsumX);
6396 : }
6397 :
6398 800 : free_var(&vNminus1);
6399 800 : free_var(&vsumX);
6400 800 : free_var(&vsumX2);
6401 :
6402 800 : return res;
6403 : }
6404 :
6405 : Datum
6406 180 : numeric_var_samp(PG_FUNCTION_ARGS)
6407 : {
6408 : NumericAggState *state;
6409 : Numeric res;
6410 : bool is_null;
6411 :
6412 180 : state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
6413 :
6414 180 : res = numeric_stddev_internal(state, true, true, &is_null);
6415 :
6416 180 : if (is_null)
6417 42 : PG_RETURN_NULL();
6418 : else
6419 138 : PG_RETURN_NUMERIC(res);
6420 : }
6421 :
6422 : Datum
6423 174 : numeric_stddev_samp(PG_FUNCTION_ARGS)
6424 : {
6425 : NumericAggState *state;
6426 : Numeric res;
6427 : bool is_null;
6428 :
6429 174 : state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
6430 :
6431 174 : res = numeric_stddev_internal(state, false, true, &is_null);
6432 :
6433 174 : if (is_null)
6434 42 : PG_RETURN_NULL();
6435 : else
6436 132 : PG_RETURN_NUMERIC(res);
6437 : }
6438 :
6439 : Datum
6440 114 : numeric_var_pop(PG_FUNCTION_ARGS)
6441 : {
6442 : NumericAggState *state;
6443 : Numeric res;
6444 : bool is_null;
6445 :
6446 114 : state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
6447 :
6448 114 : res = numeric_stddev_internal(state, true, false, &is_null);
6449 :
6450 114 : if (is_null)
6451 0 : PG_RETURN_NULL();
6452 : else
6453 114 : PG_RETURN_NUMERIC(res);
6454 : }
6455 :
6456 : Datum
6457 96 : numeric_stddev_pop(PG_FUNCTION_ARGS)
6458 : {
6459 : NumericAggState *state;
6460 : Numeric res;
6461 : bool is_null;
6462 :
6463 96 : state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
6464 :
6465 96 : res = numeric_stddev_internal(state, false, false, &is_null);
6466 :
6467 96 : if (is_null)
6468 0 : PG_RETURN_NULL();
6469 : else
6470 96 : PG_RETURN_NUMERIC(res);
6471 : }
6472 :
6473 : #ifdef HAVE_INT128
6474 : static Numeric
6475 422 : numeric_poly_stddev_internal(Int128AggState *state,
6476 : bool variance, bool sample,
6477 : bool *is_null)
6478 : {
6479 : NumericAggState numstate;
6480 : Numeric res;
6481 :
6482 : /* Initialize an empty agg state */
6483 422 : memset(&numstate, 0, sizeof(NumericAggState));
6484 :
6485 422 : if (state)
6486 : {
6487 : NumericVar tmp_var;
6488 :
6489 422 : numstate.N = state->N;
6490 :
6491 422 : init_var(&tmp_var);
6492 :
6493 422 : int128_to_numericvar(state->sumX, &tmp_var);
6494 422 : accum_sum_add(&numstate.sumX, &tmp_var);
6495 :
6496 422 : int128_to_numericvar(state->sumX2, &tmp_var);
6497 422 : accum_sum_add(&numstate.sumX2, &tmp_var);
6498 :
6499 422 : free_var(&tmp_var);
6500 : }
6501 :
6502 422 : res = numeric_stddev_internal(&numstate, variance, sample, is_null);
6503 :
6504 422 : if (numstate.sumX.ndigits > 0)
6505 : {
6506 422 : pfree(numstate.sumX.pos_digits);
6507 422 : pfree(numstate.sumX.neg_digits);
6508 : }
6509 422 : if (numstate.sumX2.ndigits > 0)
6510 : {
6511 422 : pfree(numstate.sumX2.pos_digits);
6512 422 : pfree(numstate.sumX2.neg_digits);
6513 : }
6514 :
6515 422 : return res;
6516 : }
6517 : #endif
6518 :
6519 : Datum
6520 126 : numeric_poly_var_samp(PG_FUNCTION_ARGS)
6521 : {
6522 : #ifdef HAVE_INT128
6523 : PolyNumAggState *state;
6524 : Numeric res;
6525 : bool is_null;
6526 :
6527 126 : state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
6528 :
6529 126 : res = numeric_poly_stddev_internal(state, true, true, &is_null);
6530 :
6531 126 : if (is_null)
6532 24 : PG_RETURN_NULL();
6533 : else
6534 102 : PG_RETURN_NUMERIC(res);
6535 : #else
6536 : return numeric_var_samp(fcinfo);
6537 : #endif
6538 : }
6539 :
6540 : Datum
6541 164 : numeric_poly_stddev_samp(PG_FUNCTION_ARGS)
6542 : {
6543 : #ifdef HAVE_INT128
6544 : PolyNumAggState *state;
6545 : Numeric res;
6546 : bool is_null;
6547 :
6548 164 : state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
6549 :
6550 164 : res = numeric_poly_stddev_internal(state, false, true, &is_null);
6551 :
6552 164 : if (is_null)
6553 24 : PG_RETURN_NULL();
6554 : else
6555 140 : PG_RETURN_NUMERIC(res);
6556 : #else
6557 : return numeric_stddev_samp(fcinfo);
6558 : #endif
6559 : }
6560 :
6561 : Datum
6562 60 : numeric_poly_var_pop(PG_FUNCTION_ARGS)
6563 : {
6564 : #ifdef HAVE_INT128
6565 : PolyNumAggState *state;
6566 : Numeric res;
6567 : bool is_null;
6568 :
6569 60 : state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
6570 :
6571 60 : res = numeric_poly_stddev_internal(state, true, false, &is_null);
6572 :
6573 60 : if (is_null)
6574 0 : PG_RETURN_NULL();
6575 : else
6576 60 : PG_RETURN_NUMERIC(res);
6577 : #else
6578 : return numeric_var_pop(fcinfo);
6579 : #endif
6580 : }
6581 :
6582 : Datum
6583 72 : numeric_poly_stddev_pop(PG_FUNCTION_ARGS)
6584 : {
6585 : #ifdef HAVE_INT128
6586 : PolyNumAggState *state;
6587 : Numeric res;
6588 : bool is_null;
6589 :
6590 72 : state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
6591 :
6592 72 : res = numeric_poly_stddev_internal(state, false, false, &is_null);
6593 :
6594 72 : if (is_null)
6595 0 : PG_RETURN_NULL();
6596 : else
6597 72 : PG_RETURN_NUMERIC(res);
6598 : #else
6599 : return numeric_stddev_pop(fcinfo);
6600 : #endif
6601 : }
6602 :
6603 : /*
6604 : * SUM transition functions for integer datatypes.
6605 : *
6606 : * To avoid overflow, we use accumulators wider than the input datatype.
6607 : * A Numeric accumulator is needed for int8 input; for int4 and int2
6608 : * inputs, we use int8 accumulators which should be sufficient for practical
6609 : * purposes. (The latter two therefore don't really belong in this file,
6610 : * but we keep them here anyway.)
6611 : *
6612 : * Because SQL defines the SUM() of no values to be NULL, not zero,
6613 : * the initial condition of the transition data value needs to be NULL. This
6614 : * means we can't rely on ExecAgg to automatically insert the first non-null
6615 : * data value into the transition data: it doesn't know how to do the type
6616 : * conversion. The upshot is that these routines have to be marked non-strict
6617 : * and handle substitution of the first non-null input themselves.
6618 : *
6619 : * Note: these functions are used only in plain aggregation mode.
6620 : * In moving-aggregate mode, we use intX_avg_accum and intX_avg_accum_inv.
6621 : */
6622 :
6623 : Datum
6624 24 : int2_sum(PG_FUNCTION_ARGS)
6625 : {
6626 : int64 newval;
6627 :
6628 24 : if (PG_ARGISNULL(0))
6629 : {
6630 : /* No non-null input seen so far... */
6631 6 : if (PG_ARGISNULL(1))
6632 0 : PG_RETURN_NULL(); /* still no non-null */
6633 : /* This is the first non-null input. */
6634 6 : newval = (int64) PG_GETARG_INT16(1);
6635 6 : PG_RETURN_INT64(newval);
6636 : }
6637 :
6638 : /*
6639 : * If we're invoked as an aggregate, we can cheat and modify our first
6640 : * parameter in-place to avoid palloc overhead. If not, we need to return
6641 : * the new value of the transition variable. (If int8 is pass-by-value,
6642 : * then of course this is useless as well as incorrect, so just ifdef it
6643 : * out.)
6644 : */
6645 : #ifndef USE_FLOAT8_BYVAL /* controls int8 too */
6646 : if (AggCheckCallContext(fcinfo, NULL))
6647 : {
6648 : int64 *oldsum = (int64 *) PG_GETARG_POINTER(0);
6649 :
6650 : /* Leave the running sum unchanged in the new input is null */
6651 : if (!PG_ARGISNULL(1))
6652 : *oldsum = *oldsum + (int64) PG_GETARG_INT16(1);
6653 :
6654 : PG_RETURN_POINTER(oldsum);
6655 : }
6656 : else
6657 : #endif
6658 : {
6659 18 : int64 oldsum = PG_GETARG_INT64(0);
6660 :
6661 : /* Leave sum unchanged if new input is null. */
6662 18 : if (PG_ARGISNULL(1))
6663 0 : PG_RETURN_INT64(oldsum);
6664 :
6665 : /* OK to do the addition. */
6666 18 : newval = oldsum + (int64) PG_GETARG_INT16(1);
6667 :
6668 18 : PG_RETURN_INT64(newval);
6669 : }
6670 : }
6671 :
6672 : Datum
6673 3698156 : int4_sum(PG_FUNCTION_ARGS)
6674 : {
6675 : int64 newval;
6676 :
6677 3698156 : if (PG_ARGISNULL(0))
6678 : {
6679 : /* No non-null input seen so far... */
6680 207218 : if (PG_ARGISNULL(1))
6681 986 : PG_RETURN_NULL(); /* still no non-null */
6682 : /* This is the first non-null input. */
6683 206232 : newval = (int64) PG_GETARG_INT32(1);
6684 206232 : PG_RETURN_INT64(newval);
6685 : }
6686 :
6687 : /*
6688 : * If we're invoked as an aggregate, we can cheat and modify our first
6689 : * parameter in-place to avoid palloc overhead. If not, we need to return
6690 : * the new value of the transition variable. (If int8 is pass-by-value,
6691 : * then of course this is useless as well as incorrect, so just ifdef it
6692 : * out.)
6693 : */
6694 : #ifndef USE_FLOAT8_BYVAL /* controls int8 too */
6695 : if (AggCheckCallContext(fcinfo, NULL))
6696 : {
6697 : int64 *oldsum = (int64 *) PG_GETARG_POINTER(0);
6698 :
6699 : /* Leave the running sum unchanged in the new input is null */
6700 : if (!PG_ARGISNULL(1))
6701 : *oldsum = *oldsum + (int64) PG_GETARG_INT32(1);
6702 :
6703 : PG_RETURN_POINTER(oldsum);
6704 : }
6705 : else
6706 : #endif
6707 : {
6708 3490938 : int64 oldsum = PG_GETARG_INT64(0);
6709 :
6710 : /* Leave sum unchanged if new input is null. */
6711 3490938 : if (PG_ARGISNULL(1))
6712 30874 : PG_RETURN_INT64(oldsum);
6713 :
6714 : /* OK to do the addition. */
6715 3460064 : newval = oldsum + (int64) PG_GETARG_INT32(1);
6716 :
6717 3460064 : PG_RETURN_INT64(newval);
6718 : }
6719 : }
6720 :
6721 : /*
6722 : * Note: this function is obsolete, it's no longer used for SUM(int8).
6723 : */
6724 : Datum
6725 0 : int8_sum(PG_FUNCTION_ARGS)
6726 : {
6727 : Numeric oldsum;
6728 :
6729 0 : if (PG_ARGISNULL(0))
6730 : {
6731 : /* No non-null input seen so far... */
6732 0 : if (PG_ARGISNULL(1))
6733 0 : PG_RETURN_NULL(); /* still no non-null */
6734 : /* This is the first non-null input. */
6735 0 : PG_RETURN_NUMERIC(int64_to_numeric(PG_GETARG_INT64(1)));
6736 : }
6737 :
6738 : /*
6739 : * Note that we cannot special-case the aggregate case here, as we do for
6740 : * int2_sum and int4_sum: numeric is of variable size, so we cannot modify
6741 : * our first parameter in-place.
6742 : */
6743 :
6744 0 : oldsum = PG_GETARG_NUMERIC(0);
6745 :
6746 : /* Leave sum unchanged if new input is null. */
6747 0 : if (PG_ARGISNULL(1))
6748 0 : PG_RETURN_NUMERIC(oldsum);
6749 :
6750 : /* OK to do the addition. */
6751 0 : PG_RETURN_DATUM(DirectFunctionCall2(numeric_add,
6752 : NumericGetDatum(oldsum),
6753 : NumericGetDatum(int64_to_numeric(PG_GETARG_INT64(1)))));
6754 : }
6755 :
6756 :
6757 : /*
6758 : * Routines for avg(int2) and avg(int4). The transition datatype
6759 : * is a two-element int8 array, holding count and sum.
6760 : *
6761 : * These functions are also used for sum(int2) and sum(int4) when
6762 : * operating in moving-aggregate mode, since for correct inverse transitions
6763 : * we need to count the inputs.
6764 : */
6765 :
6766 : typedef struct Int8TransTypeData
6767 : {
6768 : int64 count;
6769 : int64 sum;
6770 : } Int8TransTypeData;
6771 :
6772 : Datum
6773 42 : int2_avg_accum(PG_FUNCTION_ARGS)
6774 : {
6775 : ArrayType *transarray;
6776 42 : int16 newval = PG_GETARG_INT16(1);
6777 : Int8TransTypeData *transdata;
6778 :
6779 : /*
6780 : * If we're invoked as an aggregate, we can cheat and modify our first
6781 : * parameter in-place to reduce palloc overhead. Otherwise we need to make
6782 : * a copy of it before scribbling on it.
6783 : */
6784 42 : if (AggCheckCallContext(fcinfo, NULL))
6785 42 : transarray = PG_GETARG_ARRAYTYPE_P(0);
6786 : else
6787 0 : transarray = PG_GETARG_ARRAYTYPE_P_COPY(0);
6788 :
6789 42 : if (ARR_HASNULL(transarray) ||
6790 42 : ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
6791 0 : elog(ERROR, "expected 2-element int8 array");
6792 :
6793 42 : transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
6794 42 : transdata->count++;
6795 42 : transdata->sum += newval;
6796 :
6797 42 : PG_RETURN_ARRAYTYPE_P(transarray);
6798 : }
6799 :
6800 : Datum
6801 2620302 : int4_avg_accum(PG_FUNCTION_ARGS)
6802 : {
6803 : ArrayType *transarray;
6804 2620302 : int32 newval = PG_GETARG_INT32(1);
6805 : Int8TransTypeData *transdata;
6806 :
6807 : /*
6808 : * If we're invoked as an aggregate, we can cheat and modify our first
6809 : * parameter in-place to reduce palloc overhead. Otherwise we need to make
6810 : * a copy of it before scribbling on it.
6811 : */
6812 2620302 : if (AggCheckCallContext(fcinfo, NULL))
6813 2620302 : transarray = PG_GETARG_ARRAYTYPE_P(0);
6814 : else
6815 0 : transarray = PG_GETARG_ARRAYTYPE_P_COPY(0);
6816 :
6817 2620302 : if (ARR_HASNULL(transarray) ||
6818 2620302 : ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
6819 0 : elog(ERROR, "expected 2-element int8 array");
6820 :
6821 2620302 : transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
6822 2620302 : transdata->count++;
6823 2620302 : transdata->sum += newval;
6824 :
6825 2620302 : PG_RETURN_ARRAYTYPE_P(transarray);
6826 : }
6827 :
6828 : Datum
6829 4122 : int4_avg_combine(PG_FUNCTION_ARGS)
6830 : {
6831 : ArrayType *transarray1;
6832 : ArrayType *transarray2;
6833 : Int8TransTypeData *state1;
6834 : Int8TransTypeData *state2;
6835 :
6836 4122 : if (!AggCheckCallContext(fcinfo, NULL))
6837 0 : elog(ERROR, "aggregate function called in non-aggregate context");
6838 :
6839 4122 : transarray1 = PG_GETARG_ARRAYTYPE_P(0);
6840 4122 : transarray2 = PG_GETARG_ARRAYTYPE_P(1);
6841 :
6842 4122 : if (ARR_HASNULL(transarray1) ||
6843 4122 : ARR_SIZE(transarray1) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
6844 0 : elog(ERROR, "expected 2-element int8 array");
6845 :
6846 4122 : if (ARR_HASNULL(transarray2) ||
6847 4122 : ARR_SIZE(transarray2) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
6848 0 : elog(ERROR, "expected 2-element int8 array");
6849 :
6850 4122 : state1 = (Int8TransTypeData *) ARR_DATA_PTR(transarray1);
6851 4122 : state2 = (Int8TransTypeData *) ARR_DATA_PTR(transarray2);
6852 :
6853 4122 : state1->count += state2->count;
6854 4122 : state1->sum += state2->sum;
6855 :
6856 4122 : PG_RETURN_ARRAYTYPE_P(transarray1);
6857 : }
6858 :
6859 : Datum
6860 12 : int2_avg_accum_inv(PG_FUNCTION_ARGS)
6861 : {
6862 : ArrayType *transarray;
6863 12 : int16 newval = PG_GETARG_INT16(1);
6864 : Int8TransTypeData *transdata;
6865 :
6866 : /*
6867 : * If we're invoked as an aggregate, we can cheat and modify our first
6868 : * parameter in-place to reduce palloc overhead. Otherwise we need to make
6869 : * a copy of it before scribbling on it.
6870 : */
6871 12 : if (AggCheckCallContext(fcinfo, NULL))
6872 12 : transarray = PG_GETARG_ARRAYTYPE_P(0);
6873 : else
6874 0 : transarray = PG_GETARG_ARRAYTYPE_P_COPY(0);
6875 :
6876 12 : if (ARR_HASNULL(transarray) ||
6877 12 : ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
6878 0 : elog(ERROR, "expected 2-element int8 array");
6879 :
6880 12 : transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
6881 12 : transdata->count--;
6882 12 : transdata->sum -= newval;
6883 :
6884 12 : PG_RETURN_ARRAYTYPE_P(transarray);
6885 : }
6886 :
6887 : Datum
6888 1452 : int4_avg_accum_inv(PG_FUNCTION_ARGS)
6889 : {
6890 : ArrayType *transarray;
6891 1452 : int32 newval = PG_GETARG_INT32(1);
6892 : Int8TransTypeData *transdata;
6893 :
6894 : /*
6895 : * If we're invoked as an aggregate, we can cheat and modify our first
6896 : * parameter in-place to reduce palloc overhead. Otherwise we need to make
6897 : * a copy of it before scribbling on it.
6898 : */
6899 1452 : if (AggCheckCallContext(fcinfo, NULL))
6900 1452 : transarray = PG_GETARG_ARRAYTYPE_P(0);
6901 : else
6902 0 : transarray = PG_GETARG_ARRAYTYPE_P_COPY(0);
6903 :
6904 1452 : if (ARR_HASNULL(transarray) ||
6905 1452 : ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
6906 0 : elog(ERROR, "expected 2-element int8 array");
6907 :
6908 1452 : transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
6909 1452 : transdata->count--;
6910 1452 : transdata->sum -= newval;
6911 :
6912 1452 : PG_RETURN_ARRAYTYPE_P(transarray);
6913 : }
6914 :
6915 : Datum
6916 10774 : int8_avg(PG_FUNCTION_ARGS)
6917 : {
6918 10774 : ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
6919 : Int8TransTypeData *transdata;
6920 : Datum countd,
6921 : sumd;
6922 :
6923 10774 : if (ARR_HASNULL(transarray) ||
6924 10774 : ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
6925 0 : elog(ERROR, "expected 2-element int8 array");
6926 10774 : transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
6927 :
6928 : /* SQL defines AVG of no values to be NULL */
6929 10774 : if (transdata->count == 0)
6930 118 : PG_RETURN_NULL();
6931 :
6932 10656 : countd = NumericGetDatum(int64_to_numeric(transdata->count));
6933 10656 : sumd = NumericGetDatum(int64_to_numeric(transdata->sum));
6934 :
6935 10656 : PG_RETURN_DATUM(DirectFunctionCall2(numeric_div, sumd, countd));
6936 : }
6937 :
6938 : /*
6939 : * SUM(int2) and SUM(int4) both return int8, so we can use this
6940 : * final function for both.
6941 : */
6942 : Datum
6943 3834 : int2int4_sum(PG_FUNCTION_ARGS)
6944 : {
6945 3834 : ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
6946 : Int8TransTypeData *transdata;
6947 :
6948 3834 : if (ARR_HASNULL(transarray) ||
6949 3834 : ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
6950 0 : elog(ERROR, "expected 2-element int8 array");
6951 3834 : transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
6952 :
6953 : /* SQL defines SUM of no values to be NULL */
6954 3834 : if (transdata->count == 0)
6955 480 : PG_RETURN_NULL();
6956 :
6957 3354 : PG_RETURN_DATUM(Int64GetDatumFast(transdata->sum));
6958 : }
6959 :
6960 :
6961 : /* ----------------------------------------------------------------------
6962 : *
6963 : * Debug support
6964 : *
6965 : * ----------------------------------------------------------------------
6966 : */
6967 :
6968 : #ifdef NUMERIC_DEBUG
6969 :
6970 : /*
6971 : * dump_numeric() - Dump a value in the db storage format for debugging
6972 : */
6973 : static void
6974 : dump_numeric(const char *str, Numeric num)
6975 : {
6976 : NumericDigit *digits = NUMERIC_DIGITS(num);
6977 : int ndigits;
6978 : int i;
6979 :
6980 : ndigits = NUMERIC_NDIGITS(num);
6981 :
6982 : printf("%s: NUMERIC w=%d d=%d ", str,
6983 : NUMERIC_WEIGHT(num), NUMERIC_DSCALE(num));
6984 : switch (NUMERIC_SIGN(num))
6985 : {
6986 : case NUMERIC_POS:
6987 : printf("POS");
6988 : break;
6989 : case NUMERIC_NEG:
6990 : printf("NEG");
6991 : break;
6992 : case NUMERIC_NAN:
6993 : printf("NaN");
6994 : break;
6995 : case NUMERIC_PINF:
6996 : printf("Infinity");
6997 : break;
6998 : case NUMERIC_NINF:
6999 : printf("-Infinity");
7000 : break;
7001 : default:
7002 : printf("SIGN=0x%x", NUMERIC_SIGN(num));
7003 : break;
7004 : }
7005 :
7006 : for (i = 0; i < ndigits; i++)
7007 : printf(" %0*d", DEC_DIGITS, digits[i]);
7008 : printf("\n");
7009 : }
7010 :
7011 :
7012 : /*
7013 : * dump_var() - Dump a value in the variable format for debugging
7014 : */
7015 : static void
7016 : dump_var(const char *str, NumericVar *var)
7017 : {
7018 : int i;
7019 :
7020 : printf("%s: VAR w=%d d=%d ", str, var->weight, var->dscale);
7021 : switch (var->sign)
7022 : {
7023 : case NUMERIC_POS:
7024 : printf("POS");
7025 : break;
7026 : case NUMERIC_NEG:
7027 : printf("NEG");
7028 : break;
7029 : case NUMERIC_NAN:
7030 : printf("NaN");
7031 : break;
7032 : case NUMERIC_PINF:
7033 : printf("Infinity");
7034 : break;
7035 : case NUMERIC_NINF:
7036 : printf("-Infinity");
7037 : break;
7038 : default:
7039 : printf("SIGN=0x%x", var->sign);
7040 : break;
7041 : }
7042 :
7043 : for (i = 0; i < var->ndigits; i++)
7044 : printf(" %0*d", DEC_DIGITS, var->digits[i]);
7045 :
7046 : printf("\n");
7047 : }
7048 : #endif /* NUMERIC_DEBUG */
7049 :
7050 :
7051 : /* ----------------------------------------------------------------------
7052 : *
7053 : * Local functions follow
7054 : *
7055 : * In general, these do not support "special" (NaN or infinity) inputs;
7056 : * callers should handle those possibilities first.
7057 : * (There are one or two exceptions, noted in their header comments.)
7058 : *
7059 : * ----------------------------------------------------------------------
7060 : */
7061 :
7062 :
7063 : /*
7064 : * alloc_var() -
7065 : *
7066 : * Allocate a digit buffer of ndigits digits (plus a spare digit for rounding)
7067 : */
7068 : static void
7069 2227360 : alloc_var(NumericVar *var, int ndigits)
7070 : {
7071 2227360 : digitbuf_free(var->buf);
7072 2227360 : var->buf = digitbuf_alloc(ndigits + 1);
7073 2227360 : var->buf[0] = 0; /* spare digit for rounding */
7074 2227360 : var->digits = var->buf + 1;
7075 2227360 : var->ndigits = ndigits;
7076 2227360 : }
7077 :
7078 :
7079 : /*
7080 : * free_var() -
7081 : *
7082 : * Return the digit buffer of a variable to the free pool
7083 : */
7084 : static void
7085 4239388 : free_var(NumericVar *var)
7086 : {
7087 4239388 : digitbuf_free(var->buf);
7088 4239388 : var->buf = NULL;
7089 4239388 : var->digits = NULL;
7090 4239388 : var->sign = NUMERIC_NAN;
7091 4239388 : }
7092 :
7093 :
7094 : /*
7095 : * zero_var() -
7096 : *
7097 : * Set a variable to ZERO.
7098 : * Note: its dscale is not touched.
7099 : */
7100 : static void
7101 61084 : zero_var(NumericVar *var)
7102 : {
7103 61084 : digitbuf_free(var->buf);
7104 61084 : var->buf = NULL;
7105 61084 : var->digits = NULL;
7106 61084 : var->ndigits = 0;
7107 61084 : var->weight = 0; /* by convention; doesn't really matter */
7108 61084 : var->sign = NUMERIC_POS; /* anything but NAN... */
7109 61084 : }
7110 :
7111 :
7112 : /*
7113 : * set_var_from_str()
7114 : *
7115 : * Parse a string and put the number into a variable
7116 : *
7117 : * This function does not handle leading or trailing spaces. It returns
7118 : * the end+1 position parsed into *endptr, so that caller can check for
7119 : * trailing spaces/garbage if deemed necessary.
7120 : *
7121 : * cp is the place to actually start parsing; str is what to use in error
7122 : * reports. (Typically cp would be the same except advanced over spaces.)
7123 : *
7124 : * Returns true on success, false on failure (if escontext points to an
7125 : * ErrorSaveContext; otherwise errors are thrown).
7126 : */
7127 : static bool
7128 234940 : set_var_from_str(const char *str, const char *cp,
7129 : NumericVar *dest, const char **endptr,
7130 : Node *escontext)
7131 : {
7132 234940 : bool have_dp = false;
7133 : int i;
7134 : unsigned char *decdigits;
7135 234940 : int sign = NUMERIC_POS;
7136 234940 : int dweight = -1;
7137 : int ddigits;
7138 234940 : int dscale = 0;
7139 : int weight;
7140 : int ndigits;
7141 : int offset;
7142 : NumericDigit *digits;
7143 :
7144 : /*
7145 : * We first parse the string to extract decimal digits and determine the
7146 : * correct decimal weight. Then convert to NBASE representation.
7147 : */
7148 234940 : switch (*cp)
7149 : {
7150 0 : case '+':
7151 0 : sign = NUMERIC_POS;
7152 0 : cp++;
7153 0 : break;
7154 :
7155 300 : case '-':
7156 300 : sign = NUMERIC_NEG;
7157 300 : cp++;
7158 300 : break;
7159 : }
7160 :
7161 234940 : if (*cp == '.')
7162 : {
7163 382 : have_dp = true;
7164 382 : cp++;
7165 : }
7166 :
7167 234940 : if (!isdigit((unsigned char) *cp))
7168 0 : goto invalid_syntax;
7169 :
7170 234940 : decdigits = (unsigned char *) palloc(strlen(cp) + DEC_DIGITS * 2);
7171 :
7172 : /* leading padding for digit alignment later */
7173 234940 : memset(decdigits, 0, DEC_DIGITS);
7174 234940 : i = DEC_DIGITS;
7175 :
7176 1575810 : while (*cp)
7177 : {
7178 1342234 : if (isdigit((unsigned char) *cp))
7179 : {
7180 1291180 : decdigits[i++] = *cp++ - '0';
7181 1291180 : if (!have_dp)
7182 578608 : dweight++;
7183 : else
7184 712572 : dscale++;
7185 : }
7186 51054 : else if (*cp == '.')
7187 : {
7188 49528 : if (have_dp)
7189 0 : goto invalid_syntax;
7190 49528 : have_dp = true;
7191 49528 : cp++;
7192 : /* decimal point must not be followed by underscore */
7193 49528 : if (*cp == '_')
7194 6 : goto invalid_syntax;
7195 : }
7196 1526 : else if (*cp == '_')
7197 : {
7198 : /* underscore must be followed by more digits */
7199 186 : cp++;
7200 186 : if (!isdigit((unsigned char) *cp))
7201 18 : goto invalid_syntax;
7202 : }
7203 : else
7204 1340 : break;
7205 : }
7206 :
7207 234916 : ddigits = i - DEC_DIGITS;
7208 : /* trailing padding for digit alignment later */
7209 234916 : memset(decdigits + i, 0, DEC_DIGITS - 1);
7210 :
7211 : /* Handle exponent, if any */
7212 234916 : if (*cp == 'e' || *cp == 'E')
7213 : {
7214 1292 : int64 exponent = 0;
7215 1292 : bool neg = false;
7216 :
7217 : /*
7218 : * At this point, dweight and dscale can't be more than about
7219 : * INT_MAX/2 due to the MaxAllocSize limit on string length, so
7220 : * constraining the exponent similarly should be enough to prevent
7221 : * integer overflow in this function. If the value is too large to
7222 : * fit in storage format, make_result() will complain about it later;
7223 : * for consistency use the same ereport errcode/text as make_result().
7224 : */
7225 :
7226 : /* exponent sign */
7227 1292 : cp++;
7228 1292 : if (*cp == '+')
7229 154 : cp++;
7230 1138 : else if (*cp == '-')
7231 : {
7232 490 : neg = true;
7233 490 : cp++;
7234 : }
7235 :
7236 : /* exponent digits */
7237 1292 : if (!isdigit((unsigned char) *cp))
7238 6 : goto invalid_syntax;
7239 :
7240 4544 : while (*cp)
7241 : {
7242 3276 : if (isdigit((unsigned char) *cp))
7243 : {
7244 3234 : exponent = exponent * 10 + (*cp++ - '0');
7245 3234 : if (exponent > PG_INT32_MAX / 2)
7246 6 : goto out_of_range;
7247 : }
7248 42 : else if (*cp == '_')
7249 : {
7250 : /* underscore must be followed by more digits */
7251 42 : cp++;
7252 42 : if (!isdigit((unsigned char) *cp))
7253 12 : goto invalid_syntax;
7254 : }
7255 : else
7256 0 : break;
7257 : }
7258 :
7259 1268 : if (neg)
7260 490 : exponent = -exponent;
7261 :
7262 1268 : dweight += (int) exponent;
7263 1268 : dscale -= (int) exponent;
7264 1268 : if (dscale < 0)
7265 574 : dscale = 0;
7266 : }
7267 :
7268 : /*
7269 : * Okay, convert pure-decimal representation to base NBASE. First we need
7270 : * to determine the converted weight and ndigits. offset is the number of
7271 : * decimal zeroes to insert before the first given digit to have a
7272 : * correctly aligned first NBASE digit.
7273 : */
7274 234892 : if (dweight >= 0)
7275 234122 : weight = (dweight + 1 + DEC_DIGITS - 1) / DEC_DIGITS - 1;
7276 : else
7277 770 : weight = -((-dweight - 1) / DEC_DIGITS + 1);
7278 234892 : offset = (weight + 1) * DEC_DIGITS - (dweight + 1);
7279 234892 : ndigits = (ddigits + offset + DEC_DIGITS - 1) / DEC_DIGITS;
7280 :
7281 234892 : alloc_var(dest, ndigits);
7282 234892 : dest->sign = sign;
7283 234892 : dest->weight = weight;
7284 234892 : dest->dscale = dscale;
7285 :
7286 234892 : i = DEC_DIGITS - offset;
7287 234892 : digits = dest->digits;
7288 :
7289 703570 : while (ndigits-- > 0)
7290 : {
7291 : #if DEC_DIGITS == 4
7292 468678 : *digits++ = ((decdigits[i] * 10 + decdigits[i + 1]) * 10 +
7293 468678 : decdigits[i + 2]) * 10 + decdigits[i + 3];
7294 : #elif DEC_DIGITS == 2
7295 : *digits++ = decdigits[i] * 10 + decdigits[i + 1];
7296 : #elif DEC_DIGITS == 1
7297 : *digits++ = decdigits[i];
7298 : #else
7299 : #error unsupported NBASE
7300 : #endif
7301 468678 : i += DEC_DIGITS;
7302 : }
7303 :
7304 234892 : pfree(decdigits);
7305 :
7306 : /* Strip any leading/trailing zeroes, and normalize weight if zero */
7307 234892 : strip_var(dest);
7308 :
7309 : /* Return end+1 position for caller */
7310 234892 : *endptr = cp;
7311 :
7312 234892 : return true;
7313 :
7314 6 : out_of_range:
7315 6 : ereturn(escontext, false,
7316 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
7317 : errmsg("value overflows numeric format")));
7318 :
7319 42 : invalid_syntax:
7320 42 : ereturn(escontext, false,
7321 : (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
7322 : errmsg("invalid input syntax for type %s: \"%s\"",
7323 : "numeric", str)));
7324 : }
7325 :
7326 :
7327 : /*
7328 : * Return the numeric value of a single hex digit.
7329 : */
7330 : static inline int
7331 708 : xdigit_value(char dig)
7332 : {
7333 894 : return dig >= '0' && dig <= '9' ? dig - '0' :
7334 294 : dig >= 'a' && dig <= 'f' ? dig - 'a' + 10 :
7335 108 : dig >= 'A' && dig <= 'F' ? dig - 'A' + 10 : -1;
7336 : }
7337 :
7338 : /*
7339 : * set_var_from_non_decimal_integer_str()
7340 : *
7341 : * Parse a string containing a non-decimal integer
7342 : *
7343 : * This function does not handle leading or trailing spaces. It returns
7344 : * the end+1 position parsed into *endptr, so that caller can check for
7345 : * trailing spaces/garbage if deemed necessary.
7346 : *
7347 : * cp is the place to actually start parsing; str is what to use in error
7348 : * reports. The number's sign and base prefix indicator (e.g., "0x") are
7349 : * assumed to have already been parsed, so cp should point to the number's
7350 : * first digit in the base specified.
7351 : *
7352 : * base is expected to be 2, 8 or 16.
7353 : *
7354 : * Returns true on success, false on failure (if escontext points to an
7355 : * ErrorSaveContext; otherwise errors are thrown).
7356 : */
7357 : static bool
7358 156 : set_var_from_non_decimal_integer_str(const char *str, const char *cp, int sign,
7359 : int base, NumericVar *dest,
7360 : const char **endptr, Node *escontext)
7361 : {
7362 156 : const char *firstdigit = cp;
7363 : int64 tmp;
7364 : int64 mul;
7365 : NumericVar tmp_var;
7366 :
7367 156 : init_var(&tmp_var);
7368 :
7369 156 : zero_var(dest);
7370 :
7371 : /*
7372 : * Process input digits in groups that fit in int64. Here "tmp" is the
7373 : * value of the digits in the group, and "mul" is base^n, where n is the
7374 : * number of digits in the group. Thus tmp < mul, and we must start a new
7375 : * group when mul * base threatens to overflow PG_INT64_MAX.
7376 : */
7377 156 : tmp = 0;
7378 156 : mul = 1;
7379 :
7380 156 : if (base == 16)
7381 : {
7382 828 : while (*cp)
7383 : {
7384 798 : if (isxdigit((unsigned char) *cp))
7385 : {
7386 708 : if (mul > PG_INT64_MAX / 16)
7387 : {
7388 : /* Add the contribution from this group of digits */
7389 30 : int64_to_numericvar(mul, &tmp_var);
7390 30 : mul_var(dest, &tmp_var, dest, 0);
7391 30 : int64_to_numericvar(tmp, &tmp_var);
7392 30 : add_var(dest, &tmp_var, dest);
7393 :
7394 : /* Result will overflow if weight overflows int16 */
7395 30 : if (dest->weight > NUMERIC_WEIGHT_MAX)
7396 0 : goto out_of_range;
7397 :
7398 : /* Begin a new group */
7399 30 : tmp = 0;
7400 30 : mul = 1;
7401 : }
7402 :
7403 708 : tmp = tmp * 16 + xdigit_value(*cp++);
7404 708 : mul = mul * 16;
7405 : }
7406 90 : else if (*cp == '_')
7407 : {
7408 : /* Underscore must be followed by more digits */
7409 66 : cp++;
7410 66 : if (!isxdigit((unsigned char) *cp))
7411 18 : goto invalid_syntax;
7412 : }
7413 : else
7414 24 : break;
7415 : }
7416 : }
7417 84 : else if (base == 8)
7418 : {
7419 636 : while (*cp)
7420 : {
7421 606 : if (*cp >= '0' && *cp <= '7')
7422 : {
7423 558 : if (mul > PG_INT64_MAX / 8)
7424 : {
7425 : /* Add the contribution from this group of digits */
7426 18 : int64_to_numericvar(mul, &tmp_var);
7427 18 : mul_var(dest, &tmp_var, dest, 0);
7428 18 : int64_to_numericvar(tmp, &tmp_var);
7429 18 : add_var(dest, &tmp_var, dest);
7430 :
7431 : /* Result will overflow if weight overflows int16 */
7432 18 : if (dest->weight > NUMERIC_WEIGHT_MAX)
7433 0 : goto out_of_range;
7434 :
7435 : /* Begin a new group */
7436 18 : tmp = 0;
7437 18 : mul = 1;
7438 : }
7439 :
7440 558 : tmp = tmp * 8 + (*cp++ - '0');
7441 558 : mul = mul * 8;
7442 : }
7443 48 : else if (*cp == '_')
7444 : {
7445 : /* Underscore must be followed by more digits */
7446 36 : cp++;
7447 36 : if (*cp < '0' || *cp > '7')
7448 0 : goto invalid_syntax;
7449 : }
7450 : else
7451 12 : break;
7452 : }
7453 : }
7454 42 : else if (base == 2)
7455 : {
7456 1560 : while (*cp)
7457 : {
7458 1530 : if (*cp >= '0' && *cp <= '1')
7459 : {
7460 1416 : if (mul > PG_INT64_MAX / 2)
7461 : {
7462 : /* Add the contribution from this group of digits */
7463 18 : int64_to_numericvar(mul, &tmp_var);
7464 18 : mul_var(dest, &tmp_var, dest, 0);
7465 18 : int64_to_numericvar(tmp, &tmp_var);
7466 18 : add_var(dest, &tmp_var, dest);
7467 :
7468 : /* Result will overflow if weight overflows int16 */
7469 18 : if (dest->weight > NUMERIC_WEIGHT_MAX)
7470 0 : goto out_of_range;
7471 :
7472 : /* Begin a new group */
7473 18 : tmp = 0;
7474 18 : mul = 1;
7475 : }
7476 :
7477 1416 : tmp = tmp * 2 + (*cp++ - '0');
7478 1416 : mul = mul * 2;
7479 : }
7480 114 : else if (*cp == '_')
7481 : {
7482 : /* Underscore must be followed by more digits */
7483 102 : cp++;
7484 102 : if (*cp < '0' || *cp > '1')
7485 0 : goto invalid_syntax;
7486 : }
7487 : else
7488 12 : break;
7489 : }
7490 : }
7491 : else
7492 : /* Should never happen; treat as invalid input */
7493 0 : goto invalid_syntax;
7494 :
7495 : /* Check that we got at least one digit */
7496 138 : if (unlikely(cp == firstdigit))
7497 0 : goto invalid_syntax;
7498 :
7499 : /* Add the contribution from the final group of digits */
7500 138 : int64_to_numericvar(mul, &tmp_var);
7501 138 : mul_var(dest, &tmp_var, dest, 0);
7502 138 : int64_to_numericvar(tmp, &tmp_var);
7503 138 : add_var(dest, &tmp_var, dest);
7504 :
7505 138 : if (dest->weight > NUMERIC_WEIGHT_MAX)
7506 0 : goto out_of_range;
7507 :
7508 138 : dest->sign = sign;
7509 :
7510 138 : free_var(&tmp_var);
7511 :
7512 : /* Return end+1 position for caller */
7513 138 : *endptr = cp;
7514 :
7515 138 : return true;
7516 :
7517 0 : out_of_range:
7518 0 : ereturn(escontext, false,
7519 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
7520 : errmsg("value overflows numeric format")));
7521 :
7522 18 : invalid_syntax:
7523 18 : ereturn(escontext, false,
7524 : (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
7525 : errmsg("invalid input syntax for type %s: \"%s\"",
7526 : "numeric", str)));
7527 : }
7528 :
7529 :
7530 : /*
7531 : * set_var_from_num() -
7532 : *
7533 : * Convert the packed db format into a variable
7534 : */
7535 : static void
7536 12952 : set_var_from_num(Numeric num, NumericVar *dest)
7537 : {
7538 : int ndigits;
7539 :
7540 12952 : ndigits = NUMERIC_NDIGITS(num);
7541 :
7542 12952 : alloc_var(dest, ndigits);
7543 :
7544 12952 : dest->weight = NUMERIC_WEIGHT(num);
7545 12952 : dest->sign = NUMERIC_SIGN(num);
7546 12952 : dest->dscale = NUMERIC_DSCALE(num);
7547 :
7548 12952 : memcpy(dest->digits, NUMERIC_DIGITS(num), ndigits * sizeof(NumericDigit));
7549 12952 : }
7550 :
7551 :
7552 : /*
7553 : * init_var_from_num() -
7554 : *
7555 : * Initialize a variable from packed db format. The digits array is not
7556 : * copied, which saves some cycles when the resulting var is not modified.
7557 : * Also, there's no need to call free_var(), as long as you don't assign any
7558 : * other value to it (with set_var_* functions, or by using the var as the
7559 : * destination of a function like add_var())
7560 : *
7561 : * CAUTION: Do not modify the digits buffer of a var initialized with this
7562 : * function, e.g by calling round_var() or trunc_var(), as the changes will
7563 : * propagate to the original Numeric! It's OK to use it as the destination
7564 : * argument of one of the calculational functions, though.
7565 : */
7566 : static void
7567 6037300 : init_var_from_num(Numeric num, NumericVar *dest)
7568 : {
7569 6037300 : dest->ndigits = NUMERIC_NDIGITS(num);
7570 6037300 : dest->weight = NUMERIC_WEIGHT(num);
7571 6037300 : dest->sign = NUMERIC_SIGN(num);
7572 6037300 : dest->dscale = NUMERIC_DSCALE(num);
7573 6037300 : dest->digits = NUMERIC_DIGITS(num);
7574 6037300 : dest->buf = NULL; /* digits array is not palloc'd */
7575 6037300 : }
7576 :
7577 :
7578 : /*
7579 : * set_var_from_var() -
7580 : *
7581 : * Copy one variable into another
7582 : */
7583 : static void
7584 35338 : set_var_from_var(const NumericVar *value, NumericVar *dest)
7585 : {
7586 : NumericDigit *newbuf;
7587 :
7588 35338 : newbuf = digitbuf_alloc(value->ndigits + 1);
7589 35338 : newbuf[0] = 0; /* spare digit for rounding */
7590 35338 : if (value->ndigits > 0) /* else value->digits might be null */
7591 34392 : memcpy(newbuf + 1, value->digits,
7592 34392 : value->ndigits * sizeof(NumericDigit));
7593 :
7594 35338 : digitbuf_free(dest->buf);
7595 :
7596 35338 : memmove(dest, value, sizeof(NumericVar));
7597 35338 : dest->buf = newbuf;
7598 35338 : dest->digits = newbuf + 1;
7599 35338 : }
7600 :
7601 :
7602 : /*
7603 : * get_str_from_var() -
7604 : *
7605 : * Convert a var to text representation (guts of numeric_out).
7606 : * The var is displayed to the number of digits indicated by its dscale.
7607 : * Returns a palloc'd string.
7608 : */
7609 : static char *
7610 1059022 : get_str_from_var(const NumericVar *var)
7611 : {
7612 : int dscale;
7613 : char *str;
7614 : char *cp;
7615 : char *endcp;
7616 : int i;
7617 : int d;
7618 : NumericDigit dig;
7619 :
7620 : #if DEC_DIGITS > 1
7621 : NumericDigit d1;
7622 : #endif
7623 :
7624 1059022 : dscale = var->dscale;
7625 :
7626 : /*
7627 : * Allocate space for the result.
7628 : *
7629 : * i is set to the # of decimal digits before decimal point. dscale is the
7630 : * # of decimal digits we will print after decimal point. We may generate
7631 : * as many as DEC_DIGITS-1 excess digits at the end, and in addition we
7632 : * need room for sign, decimal point, null terminator.
7633 : */
7634 1059022 : i = (var->weight + 1) * DEC_DIGITS;
7635 1059022 : if (i <= 0)
7636 226722 : i = 1;
7637 :
7638 1059022 : str = palloc(i + dscale + DEC_DIGITS + 2);
7639 1059022 : cp = str;
7640 :
7641 : /*
7642 : * Output a dash for negative values
7643 : */
7644 1059022 : if (var->sign == NUMERIC_NEG)
7645 8764 : *cp++ = '-';
7646 :
7647 : /*
7648 : * Output all digits before the decimal point
7649 : */
7650 1059022 : if (var->weight < 0)
7651 : {
7652 226722 : d = var->weight + 1;
7653 226722 : *cp++ = '0';
7654 : }
7655 : else
7656 : {
7657 1776424 : for (d = 0; d <= var->weight; d++)
7658 : {
7659 944124 : dig = (d < var->ndigits) ? var->digits[d] : 0;
7660 : /* In the first digit, suppress extra leading decimal zeroes */
7661 : #if DEC_DIGITS == 4
7662 : {
7663 944124 : bool putit = (d > 0);
7664 :
7665 944124 : d1 = dig / 1000;
7666 944124 : dig -= d1 * 1000;
7667 944124 : putit |= (d1 > 0);
7668 944124 : if (putit)
7669 175794 : *cp++ = d1 + '0';
7670 944124 : d1 = dig / 100;
7671 944124 : dig -= d1 * 100;
7672 944124 : putit |= (d1 > 0);
7673 944124 : if (putit)
7674 592264 : *cp++ = d1 + '0';
7675 944124 : d1 = dig / 10;
7676 944124 : dig -= d1 * 10;
7677 944124 : putit |= (d1 > 0);
7678 944124 : if (putit)
7679 751610 : *cp++ = d1 + '0';
7680 944124 : *cp++ = dig + '0';
7681 : }
7682 : #elif DEC_DIGITS == 2
7683 : d1 = dig / 10;
7684 : dig -= d1 * 10;
7685 : if (d1 > 0 || d > 0)
7686 : *cp++ = d1 + '0';
7687 : *cp++ = dig + '0';
7688 : #elif DEC_DIGITS == 1
7689 : *cp++ = dig + '0';
7690 : #else
7691 : #error unsupported NBASE
7692 : #endif
7693 : }
7694 : }
7695 :
7696 : /*
7697 : * If requested, output a decimal point and all the digits that follow it.
7698 : * We initially put out a multiple of DEC_DIGITS digits, then truncate if
7699 : * needed.
7700 : */
7701 1059022 : if (dscale > 0)
7702 : {
7703 739796 : *cp++ = '.';
7704 739796 : endcp = cp + dscale;
7705 2471046 : for (i = 0; i < dscale; d++, i += DEC_DIGITS)
7706 : {
7707 1731250 : dig = (d >= 0 && d < var->ndigits) ? var->digits[d] : 0;
7708 : #if DEC_DIGITS == 4
7709 1731250 : d1 = dig / 1000;
7710 1731250 : dig -= d1 * 1000;
7711 1731250 : *cp++ = d1 + '0';
7712 1731250 : d1 = dig / 100;
7713 1731250 : dig -= d1 * 100;
7714 1731250 : *cp++ = d1 + '0';
7715 1731250 : d1 = dig / 10;
7716 1731250 : dig -= d1 * 10;
7717 1731250 : *cp++ = d1 + '0';
7718 1731250 : *cp++ = dig + '0';
7719 : #elif DEC_DIGITS == 2
7720 : d1 = dig / 10;
7721 : dig -= d1 * 10;
7722 : *cp++ = d1 + '0';
7723 : *cp++ = dig + '0';
7724 : #elif DEC_DIGITS == 1
7725 : *cp++ = dig + '0';
7726 : #else
7727 : #error unsupported NBASE
7728 : #endif
7729 : }
7730 739796 : cp = endcp;
7731 : }
7732 :
7733 : /*
7734 : * terminate the string and return it
7735 : */
7736 1059022 : *cp = '\0';
7737 1059022 : return str;
7738 : }
7739 :
7740 : /*
7741 : * get_str_from_var_sci() -
7742 : *
7743 : * Convert a var to a normalised scientific notation text representation.
7744 : * This function does the heavy lifting for numeric_out_sci().
7745 : *
7746 : * This notation has the general form a * 10^b, where a is known as the
7747 : * "significand" and b is known as the "exponent".
7748 : *
7749 : * Because we can't do superscript in ASCII (and because we want to copy
7750 : * printf's behaviour) we display the exponent using E notation, with a
7751 : * minimum of two exponent digits.
7752 : *
7753 : * For example, the value 1234 could be output as 1.2e+03.
7754 : *
7755 : * We assume that the exponent can fit into an int32.
7756 : *
7757 : * rscale is the number of decimal digits desired after the decimal point in
7758 : * the output, negative values will be treated as meaning zero.
7759 : *
7760 : * Returns a palloc'd string.
7761 : */
7762 : static char *
7763 228 : get_str_from_var_sci(const NumericVar *var, int rscale)
7764 : {
7765 : int32 exponent;
7766 : NumericVar tmp_var;
7767 : size_t len;
7768 : char *str;
7769 : char *sig_out;
7770 :
7771 228 : if (rscale < 0)
7772 0 : rscale = 0;
7773 :
7774 : /*
7775 : * Determine the exponent of this number in normalised form.
7776 : *
7777 : * This is the exponent required to represent the number with only one
7778 : * significant digit before the decimal place.
7779 : */
7780 228 : if (var->ndigits > 0)
7781 : {
7782 210 : exponent = (var->weight + 1) * DEC_DIGITS;
7783 :
7784 : /*
7785 : * Compensate for leading decimal zeroes in the first numeric digit by
7786 : * decrementing the exponent.
7787 : */
7788 210 : exponent -= DEC_DIGITS - (int) log10(var->digits[0]);
7789 : }
7790 : else
7791 : {
7792 : /*
7793 : * If var has no digits, then it must be zero.
7794 : *
7795 : * Zero doesn't technically have a meaningful exponent in normalised
7796 : * notation, but we just display the exponent as zero for consistency
7797 : * of output.
7798 : */
7799 18 : exponent = 0;
7800 : }
7801 :
7802 : /*
7803 : * Divide var by 10^exponent to get the significand, rounding to rscale
7804 : * decimal digits in the process.
7805 : */
7806 228 : init_var(&tmp_var);
7807 :
7808 228 : power_ten_int(exponent, &tmp_var);
7809 228 : div_var(var, &tmp_var, &tmp_var, rscale, true, true);
7810 228 : sig_out = get_str_from_var(&tmp_var);
7811 :
7812 228 : free_var(&tmp_var);
7813 :
7814 : /*
7815 : * Allocate space for the result.
7816 : *
7817 : * In addition to the significand, we need room for the exponent
7818 : * decoration ("e"), the sign of the exponent, up to 10 digits for the
7819 : * exponent itself, and of course the null terminator.
7820 : */
7821 228 : len = strlen(sig_out) + 13;
7822 228 : str = palloc(len);
7823 228 : snprintf(str, len, "%se%+03d", sig_out, exponent);
7824 :
7825 228 : pfree(sig_out);
7826 :
7827 228 : return str;
7828 : }
7829 :
7830 :
7831 : /*
7832 : * numericvar_serialize - serialize NumericVar to binary format
7833 : *
7834 : * At variable level, no checks are performed on the weight or dscale, allowing
7835 : * us to pass around intermediate values with higher precision than supported
7836 : * by the numeric type. Note: this is incompatible with numeric_send/recv(),
7837 : * which use 16-bit integers for these fields.
7838 : */
7839 : static void
7840 156 : numericvar_serialize(StringInfo buf, const NumericVar *var)
7841 : {
7842 : int i;
7843 :
7844 156 : pq_sendint32(buf, var->ndigits);
7845 156 : pq_sendint32(buf, var->weight);
7846 156 : pq_sendint32(buf, var->sign);
7847 156 : pq_sendint32(buf, var->dscale);
7848 637960 : for (i = 0; i < var->ndigits; i++)
7849 637804 : pq_sendint16(buf, var->digits[i]);
7850 156 : }
7851 :
7852 : /*
7853 : * numericvar_deserialize - deserialize binary format to NumericVar
7854 : */
7855 : static void
7856 156 : numericvar_deserialize(StringInfo buf, NumericVar *var)
7857 : {
7858 : int len,
7859 : i;
7860 :
7861 156 : len = pq_getmsgint(buf, sizeof(int32));
7862 :
7863 156 : alloc_var(var, len); /* sets var->ndigits */
7864 :
7865 156 : var->weight = pq_getmsgint(buf, sizeof(int32));
7866 156 : var->sign = pq_getmsgint(buf, sizeof(int32));
7867 156 : var->dscale = pq_getmsgint(buf, sizeof(int32));
7868 637960 : for (i = 0; i < len; i++)
7869 637804 : var->digits[i] = pq_getmsgint(buf, sizeof(int16));
7870 156 : }
7871 :
7872 :
7873 : /*
7874 : * duplicate_numeric() - copy a packed-format Numeric
7875 : *
7876 : * This will handle NaN and Infinity cases.
7877 : */
7878 : static Numeric
7879 28496 : duplicate_numeric(Numeric num)
7880 : {
7881 : Numeric res;
7882 :
7883 28496 : res = (Numeric) palloc(VARSIZE(num));
7884 28496 : memcpy(res, num, VARSIZE(num));
7885 28496 : return res;
7886 : }
7887 :
7888 : /*
7889 : * make_result_opt_error() -
7890 : *
7891 : * Create the packed db numeric format in palloc()'d memory from
7892 : * a variable. This will handle NaN and Infinity cases.
7893 : *
7894 : * If "have_error" isn't NULL, on overflow *have_error is set to true and
7895 : * NULL is returned. This is helpful when caller needs to handle errors.
7896 : */
7897 : static Numeric
7898 3860052 : make_result_opt_error(const NumericVar *var, bool *have_error)
7899 : {
7900 : Numeric result;
7901 3860052 : NumericDigit *digits = var->digits;
7902 3860052 : int weight = var->weight;
7903 3860052 : int sign = var->sign;
7904 : int n;
7905 : Size len;
7906 :
7907 3860052 : if (have_error)
7908 211920 : *have_error = false;
7909 :
7910 3860052 : if ((sign & NUMERIC_SIGN_MASK) == NUMERIC_SPECIAL)
7911 : {
7912 : /*
7913 : * Verify valid special value. This could be just an Assert, perhaps,
7914 : * but it seems worthwhile to expend a few cycles to ensure that we
7915 : * never write any nonzero reserved bits to disk.
7916 : */
7917 3360 : if (!(sign == NUMERIC_NAN ||
7918 : sign == NUMERIC_PINF ||
7919 : sign == NUMERIC_NINF))
7920 0 : elog(ERROR, "invalid numeric sign value 0x%x", sign);
7921 :
7922 3360 : result = (Numeric) palloc(NUMERIC_HDRSZ_SHORT);
7923 :
7924 3360 : SET_VARSIZE(result, NUMERIC_HDRSZ_SHORT);
7925 3360 : result->choice.n_header = sign;
7926 : /* the header word is all we need */
7927 :
7928 : dump_numeric("make_result()", result);
7929 3360 : return result;
7930 : }
7931 :
7932 3856692 : n = var->ndigits;
7933 :
7934 : /* truncate leading zeroes */
7935 3856728 : while (n > 0 && *digits == 0)
7936 : {
7937 36 : digits++;
7938 36 : weight--;
7939 36 : n--;
7940 : }
7941 : /* truncate trailing zeroes */
7942 3942028 : while (n > 0 && digits[n - 1] == 0)
7943 85336 : n--;
7944 :
7945 : /* If zero result, force to weight=0 and positive sign */
7946 3856692 : if (n == 0)
7947 : {
7948 137952 : weight = 0;
7949 137952 : sign = NUMERIC_POS;
7950 : }
7951 :
7952 : /* Build the result */
7953 3856692 : if (NUMERIC_CAN_BE_SHORT(var->dscale, weight))
7954 : {
7955 3854758 : len = NUMERIC_HDRSZ_SHORT + n * sizeof(NumericDigit);
7956 3854758 : result = (Numeric) palloc(len);
7957 3854758 : SET_VARSIZE(result, len);
7958 3854758 : result->choice.n_short.n_header =
7959 : (sign == NUMERIC_NEG ? (NUMERIC_SHORT | NUMERIC_SHORT_SIGN_MASK)
7960 : : NUMERIC_SHORT)
7961 3854758 : | (var->dscale << NUMERIC_SHORT_DSCALE_SHIFT)
7962 3854758 : | (weight < 0 ? NUMERIC_SHORT_WEIGHT_SIGN_MASK : 0)
7963 3854758 : | (weight & NUMERIC_SHORT_WEIGHT_MASK);
7964 : }
7965 : else
7966 : {
7967 1934 : len = NUMERIC_HDRSZ + n * sizeof(NumericDigit);
7968 1934 : result = (Numeric) palloc(len);
7969 1934 : SET_VARSIZE(result, len);
7970 1934 : result->choice.n_long.n_sign_dscale =
7971 1934 : sign | (var->dscale & NUMERIC_DSCALE_MASK);
7972 1934 : result->choice.n_long.n_weight = weight;
7973 : }
7974 :
7975 : Assert(NUMERIC_NDIGITS(result) == n);
7976 3856692 : if (n > 0)
7977 3718740 : memcpy(NUMERIC_DIGITS(result), digits, n * sizeof(NumericDigit));
7978 :
7979 : /* Check for overflow of int16 fields */
7980 3856692 : if (NUMERIC_WEIGHT(result) != weight ||
7981 3856662 : NUMERIC_DSCALE(result) != var->dscale)
7982 : {
7983 30 : if (have_error)
7984 : {
7985 18 : *have_error = true;
7986 18 : return NULL;
7987 : }
7988 : else
7989 : {
7990 12 : ereport(ERROR,
7991 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
7992 : errmsg("value overflows numeric format")));
7993 : }
7994 : }
7995 :
7996 : dump_numeric("make_result()", result);
7997 3856662 : return result;
7998 : }
7999 :
8000 :
8001 : /*
8002 : * make_result() -
8003 : *
8004 : * An interface to make_result_opt_error() without "have_error" argument.
8005 : */
8006 : static Numeric
8007 2268230 : make_result(const NumericVar *var)
8008 : {
8009 2268230 : return make_result_opt_error(var, NULL);
8010 : }
8011 :
8012 :
8013 : /*
8014 : * apply_typmod() -
8015 : *
8016 : * Do bounds checking and rounding according to the specified typmod.
8017 : * Note that this is only applied to normal finite values.
8018 : *
8019 : * Returns true on success, false on failure (if escontext points to an
8020 : * ErrorSaveContext; otherwise errors are thrown).
8021 : */
8022 : static bool
8023 216024 : apply_typmod(NumericVar *var, int32 typmod, Node *escontext)
8024 : {
8025 : int precision;
8026 : int scale;
8027 : int maxdigits;
8028 : int ddigits;
8029 : int i;
8030 :
8031 : /* Do nothing if we have an invalid typmod */
8032 216024 : if (!is_valid_numeric_typmod(typmod))
8033 185924 : return true;
8034 :
8035 30100 : precision = numeric_typmod_precision(typmod);
8036 30100 : scale = numeric_typmod_scale(typmod);
8037 30100 : maxdigits = precision - scale;
8038 :
8039 : /* Round to target scale (and set var->dscale) */
8040 30100 : round_var(var, scale);
8041 :
8042 : /* but don't allow var->dscale to be negative */
8043 30100 : if (var->dscale < 0)
8044 158 : var->dscale = 0;
8045 :
8046 : /*
8047 : * Check for overflow - note we can't do this before rounding, because
8048 : * rounding could raise the weight. Also note that the var's weight could
8049 : * be inflated by leading zeroes, which will be stripped before storage
8050 : * but perhaps might not have been yet. In any case, we must recognize a
8051 : * true zero, whose weight doesn't mean anything.
8052 : */
8053 30100 : ddigits = (var->weight + 1) * DEC_DIGITS;
8054 30100 : if (ddigits > maxdigits)
8055 : {
8056 : /* Determine true weight; and check for all-zero result */
8057 6458 : for (i = 0; i < var->ndigits; i++)
8058 : {
8059 6436 : NumericDigit dig = var->digits[i];
8060 :
8061 6436 : if (dig)
8062 : {
8063 : /* Adjust for any high-order decimal zero digits */
8064 : #if DEC_DIGITS == 4
8065 6436 : if (dig < 10)
8066 324 : ddigits -= 3;
8067 6112 : else if (dig < 100)
8068 632 : ddigits -= 2;
8069 5480 : else if (dig < 1000)
8070 5462 : ddigits -= 1;
8071 : #elif DEC_DIGITS == 2
8072 : if (dig < 10)
8073 : ddigits -= 1;
8074 : #elif DEC_DIGITS == 1
8075 : /* no adjustment */
8076 : #else
8077 : #error unsupported NBASE
8078 : #endif
8079 6436 : if (ddigits > maxdigits)
8080 84 : ereturn(escontext, false,
8081 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
8082 : errmsg("numeric field overflow"),
8083 : errdetail("A field with precision %d, scale %d must round to an absolute value less than %s%d.",
8084 : precision, scale,
8085 : /* Display 10^0 as 1 */
8086 : maxdigits ? "10^" : "",
8087 : maxdigits ? maxdigits : 1
8088 : )));
8089 6352 : break;
8090 : }
8091 0 : ddigits -= DEC_DIGITS;
8092 : }
8093 : }
8094 :
8095 30016 : return true;
8096 : }
8097 :
8098 : /*
8099 : * apply_typmod_special() -
8100 : *
8101 : * Do bounds checking according to the specified typmod, for an Inf or NaN.
8102 : * For convenience of most callers, the value is presented in packed form.
8103 : *
8104 : * Returns true on success, false on failure (if escontext points to an
8105 : * ErrorSaveContext; otherwise errors are thrown).
8106 : */
8107 : static bool
8108 1974 : apply_typmod_special(Numeric num, int32 typmod, Node *escontext)
8109 : {
8110 : int precision;
8111 : int scale;
8112 :
8113 : Assert(NUMERIC_IS_SPECIAL(num)); /* caller error if not */
8114 :
8115 : /*
8116 : * NaN is allowed regardless of the typmod; that's rather dubious perhaps,
8117 : * but it's a longstanding behavior. Inf is rejected if we have any
8118 : * typmod restriction, since an infinity shouldn't be claimed to fit in
8119 : * any finite number of digits.
8120 : */
8121 1974 : if (NUMERIC_IS_NAN(num))
8122 864 : return true;
8123 :
8124 : /* Do nothing if we have a default typmod (-1) */
8125 1110 : if (!is_valid_numeric_typmod(typmod))
8126 1092 : return true;
8127 :
8128 18 : precision = numeric_typmod_precision(typmod);
8129 18 : scale = numeric_typmod_scale(typmod);
8130 :
8131 18 : ereturn(escontext, false,
8132 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
8133 : errmsg("numeric field overflow"),
8134 : errdetail("A field with precision %d, scale %d cannot hold an infinite value.",
8135 : precision, scale)));
8136 : }
8137 :
8138 :
8139 : /*
8140 : * Convert numeric to int8, rounding if needed.
8141 : *
8142 : * If overflow, return false (no error is raised). Return true if okay.
8143 : */
8144 : static bool
8145 10402 : numericvar_to_int64(const NumericVar *var, int64 *result)
8146 : {
8147 : NumericDigit *digits;
8148 : int ndigits;
8149 : int weight;
8150 : int i;
8151 : int64 val;
8152 : bool neg;
8153 : NumericVar rounded;
8154 :
8155 : /* Round to nearest integer */
8156 10402 : init_var(&rounded);
8157 10402 : set_var_from_var(var, &rounded);
8158 10402 : round_var(&rounded, 0);
8159 :
8160 : /* Check for zero input */
8161 10402 : strip_var(&rounded);
8162 10402 : ndigits = rounded.ndigits;
8163 10402 : if (ndigits == 0)
8164 : {
8165 478 : *result = 0;
8166 478 : free_var(&rounded);
8167 478 : return true;
8168 : }
8169 :
8170 : /*
8171 : * For input like 10000000000, we must treat stripped digits as real. So
8172 : * the loop assumes there are weight+1 digits before the decimal point.
8173 : */
8174 9924 : weight = rounded.weight;
8175 : Assert(weight >= 0 && ndigits <= weight + 1);
8176 :
8177 : /*
8178 : * Construct the result. To avoid issues with converting a value
8179 : * corresponding to INT64_MIN (which can't be represented as a positive 64
8180 : * bit two's complement integer), accumulate value as a negative number.
8181 : */
8182 9924 : digits = rounded.digits;
8183 9924 : neg = (rounded.sign == NUMERIC_NEG);
8184 9924 : val = -digits[0];
8185 14140 : for (i = 1; i <= weight; i++)
8186 : {
8187 4264 : if (unlikely(pg_mul_s64_overflow(val, NBASE, &val)))
8188 : {
8189 30 : free_var(&rounded);
8190 30 : return false;
8191 : }
8192 :
8193 4234 : if (i < ndigits)
8194 : {
8195 3956 : if (unlikely(pg_sub_s64_overflow(val, digits[i], &val)))
8196 : {
8197 18 : free_var(&rounded);
8198 18 : return false;
8199 : }
8200 : }
8201 : }
8202 :
8203 9876 : free_var(&rounded);
8204 :
8205 9876 : if (!neg)
8206 : {
8207 9084 : if (unlikely(val == PG_INT64_MIN))
8208 24 : return false;
8209 9060 : val = -val;
8210 : }
8211 9852 : *result = val;
8212 :
8213 9852 : return true;
8214 : }
8215 :
8216 : /*
8217 : * Convert int8 value to numeric.
8218 : */
8219 : static void
8220 1900114 : int64_to_numericvar(int64 val, NumericVar *var)
8221 : {
8222 : uint64 uval,
8223 : newuval;
8224 : NumericDigit *ptr;
8225 : int ndigits;
8226 :
8227 : /* int64 can require at most 19 decimal digits; add one for safety */
8228 1900114 : alloc_var(var, 20 / DEC_DIGITS);
8229 1900114 : if (val < 0)
8230 : {
8231 1814 : var->sign = NUMERIC_NEG;
8232 1814 : uval = pg_abs_s64(val);
8233 : }
8234 : else
8235 : {
8236 1898300 : var->sign = NUMERIC_POS;
8237 1898300 : uval = val;
8238 : }
8239 1900114 : var->dscale = 0;
8240 1900114 : if (val == 0)
8241 : {
8242 30730 : var->ndigits = 0;
8243 30730 : var->weight = 0;
8244 30730 : return;
8245 : }
8246 1869384 : ptr = var->digits + var->ndigits;
8247 1869384 : ndigits = 0;
8248 : do
8249 : {
8250 2193144 : ptr--;
8251 2193144 : ndigits++;
8252 2193144 : newuval = uval / NBASE;
8253 2193144 : *ptr = uval - newuval * NBASE;
8254 2193144 : uval = newuval;
8255 2193144 : } while (uval);
8256 1869384 : var->digits = ptr;
8257 1869384 : var->ndigits = ndigits;
8258 1869384 : var->weight = ndigits - 1;
8259 : }
8260 :
8261 : /*
8262 : * Convert numeric to uint64, rounding if needed.
8263 : *
8264 : * If overflow, return false (no error is raised). Return true if okay.
8265 : */
8266 : static bool
8267 114 : numericvar_to_uint64(const NumericVar *var, uint64 *result)
8268 : {
8269 : NumericDigit *digits;
8270 : int ndigits;
8271 : int weight;
8272 : int i;
8273 : uint64 val;
8274 : NumericVar rounded;
8275 :
8276 : /* Round to nearest integer */
8277 114 : init_var(&rounded);
8278 114 : set_var_from_var(var, &rounded);
8279 114 : round_var(&rounded, 0);
8280 :
8281 : /* Check for zero input */
8282 114 : strip_var(&rounded);
8283 114 : ndigits = rounded.ndigits;
8284 114 : if (ndigits == 0)
8285 : {
8286 18 : *result = 0;
8287 18 : free_var(&rounded);
8288 18 : return true;
8289 : }
8290 :
8291 : /* Check for negative input */
8292 96 : if (rounded.sign == NUMERIC_NEG)
8293 : {
8294 12 : free_var(&rounded);
8295 12 : return false;
8296 : }
8297 :
8298 : /*
8299 : * For input like 10000000000, we must treat stripped digits as real. So
8300 : * the loop assumes there are weight+1 digits before the decimal point.
8301 : */
8302 84 : weight = rounded.weight;
8303 : Assert(weight >= 0 && ndigits <= weight + 1);
8304 :
8305 : /* Construct the result */
8306 84 : digits = rounded.digits;
8307 84 : val = digits[0];
8308 246 : for (i = 1; i <= weight; i++)
8309 : {
8310 174 : if (unlikely(pg_mul_u64_overflow(val, NBASE, &val)))
8311 : {
8312 0 : free_var(&rounded);
8313 0 : return false;
8314 : }
8315 :
8316 174 : if (i < ndigits)
8317 : {
8318 174 : if (unlikely(pg_add_u64_overflow(val, digits[i], &val)))
8319 : {
8320 12 : free_var(&rounded);
8321 12 : return false;
8322 : }
8323 : }
8324 : }
8325 :
8326 72 : free_var(&rounded);
8327 :
8328 72 : *result = val;
8329 :
8330 72 : return true;
8331 : }
8332 :
8333 : #ifdef HAVE_INT128
8334 : /*
8335 : * Convert numeric to int128, rounding if needed.
8336 : *
8337 : * If overflow, return false (no error is raised). Return true if okay.
8338 : */
8339 : static bool
8340 60 : numericvar_to_int128(const NumericVar *var, int128 *result)
8341 : {
8342 : NumericDigit *digits;
8343 : int ndigits;
8344 : int weight;
8345 : int i;
8346 : int128 val,
8347 : oldval;
8348 : bool neg;
8349 : NumericVar rounded;
8350 :
8351 : /* Round to nearest integer */
8352 60 : init_var(&rounded);
8353 60 : set_var_from_var(var, &rounded);
8354 60 : round_var(&rounded, 0);
8355 :
8356 : /* Check for zero input */
8357 60 : strip_var(&rounded);
8358 60 : ndigits = rounded.ndigits;
8359 60 : if (ndigits == 0)
8360 : {
8361 0 : *result = 0;
8362 0 : free_var(&rounded);
8363 0 : return true;
8364 : }
8365 :
8366 : /*
8367 : * For input like 10000000000, we must treat stripped digits as real. So
8368 : * the loop assumes there are weight+1 digits before the decimal point.
8369 : */
8370 60 : weight = rounded.weight;
8371 : Assert(weight >= 0 && ndigits <= weight + 1);
8372 :
8373 : /* Construct the result */
8374 60 : digits = rounded.digits;
8375 60 : neg = (rounded.sign == NUMERIC_NEG);
8376 60 : val = digits[0];
8377 142 : for (i = 1; i <= weight; i++)
8378 : {
8379 82 : oldval = val;
8380 82 : val *= NBASE;
8381 82 : if (i < ndigits)
8382 82 : val += digits[i];
8383 :
8384 : /*
8385 : * The overflow check is a bit tricky because we want to accept
8386 : * INT128_MIN, which will overflow the positive accumulator. We can
8387 : * detect this case easily though because INT128_MIN is the only
8388 : * nonzero value for which -val == val (on a two's complement machine,
8389 : * anyway).
8390 : */
8391 82 : if ((val / NBASE) != oldval) /* possible overflow? */
8392 : {
8393 0 : if (!neg || (-val) != val || val == 0 || oldval < 0)
8394 : {
8395 0 : free_var(&rounded);
8396 0 : return false;
8397 : }
8398 : }
8399 : }
8400 :
8401 60 : free_var(&rounded);
8402 :
8403 60 : *result = neg ? -val : val;
8404 60 : return true;
8405 : }
8406 :
8407 : /*
8408 : * Convert 128 bit integer to numeric.
8409 : */
8410 : static void
8411 8794 : int128_to_numericvar(int128 val, NumericVar *var)
8412 : {
8413 : uint128 uval,
8414 : newuval;
8415 : NumericDigit *ptr;
8416 : int ndigits;
8417 :
8418 : /* int128 can require at most 39 decimal digits; add one for safety */
8419 8794 : alloc_var(var, 40 / DEC_DIGITS);
8420 8794 : if (val < 0)
8421 : {
8422 0 : var->sign = NUMERIC_NEG;
8423 0 : uval = -val;
8424 : }
8425 : else
8426 : {
8427 8794 : var->sign = NUMERIC_POS;
8428 8794 : uval = val;
8429 : }
8430 8794 : var->dscale = 0;
8431 8794 : if (val == 0)
8432 : {
8433 218 : var->ndigits = 0;
8434 218 : var->weight = 0;
8435 218 : return;
8436 : }
8437 8576 : ptr = var->digits + var->ndigits;
8438 8576 : ndigits = 0;
8439 : do
8440 : {
8441 45098 : ptr--;
8442 45098 : ndigits++;
8443 45098 : newuval = uval / NBASE;
8444 45098 : *ptr = uval - newuval * NBASE;
8445 45098 : uval = newuval;
8446 45098 : } while (uval);
8447 8576 : var->digits = ptr;
8448 8576 : var->ndigits = ndigits;
8449 8576 : var->weight = ndigits - 1;
8450 : }
8451 : #endif
8452 :
8453 : /*
8454 : * Convert a NumericVar to float8; if out of range, return +/- HUGE_VAL
8455 : */
8456 : static double
8457 466 : numericvar_to_double_no_overflow(const NumericVar *var)
8458 : {
8459 : char *tmp;
8460 : double val;
8461 : char *endptr;
8462 :
8463 466 : tmp = get_str_from_var(var);
8464 :
8465 : /* unlike float8in, we ignore ERANGE from strtod */
8466 466 : val = strtod(tmp, &endptr);
8467 466 : if (*endptr != '\0')
8468 : {
8469 : /* shouldn't happen ... */
8470 0 : ereport(ERROR,
8471 : (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
8472 : errmsg("invalid input syntax for type %s: \"%s\"",
8473 : "double precision", tmp)));
8474 : }
8475 :
8476 466 : pfree(tmp);
8477 :
8478 466 : return val;
8479 : }
8480 :
8481 :
8482 : /*
8483 : * cmp_var() -
8484 : *
8485 : * Compare two values on variable level. We assume zeroes have been
8486 : * truncated to no digits.
8487 : */
8488 : static int
8489 170228 : cmp_var(const NumericVar *var1, const NumericVar *var2)
8490 : {
8491 340456 : return cmp_var_common(var1->digits, var1->ndigits,
8492 170228 : var1->weight, var1->sign,
8493 170228 : var2->digits, var2->ndigits,
8494 170228 : var2->weight, var2->sign);
8495 : }
8496 :
8497 : /*
8498 : * cmp_var_common() -
8499 : *
8500 : * Main routine of cmp_var(). This function can be used by both
8501 : * NumericVar and Numeric.
8502 : */
8503 : static int
8504 19567812 : cmp_var_common(const NumericDigit *var1digits, int var1ndigits,
8505 : int var1weight, int var1sign,
8506 : const NumericDigit *var2digits, int var2ndigits,
8507 : int var2weight, int var2sign)
8508 : {
8509 19567812 : if (var1ndigits == 0)
8510 : {
8511 534384 : if (var2ndigits == 0)
8512 436756 : return 0;
8513 97628 : if (var2sign == NUMERIC_NEG)
8514 4220 : return 1;
8515 93408 : return -1;
8516 : }
8517 19033428 : if (var2ndigits == 0)
8518 : {
8519 72346 : if (var1sign == NUMERIC_POS)
8520 65434 : return 1;
8521 6912 : return -1;
8522 : }
8523 :
8524 18961082 : if (var1sign == NUMERIC_POS)
8525 : {
8526 18879280 : if (var2sign == NUMERIC_NEG)
8527 23688 : return 1;
8528 18855592 : return cmp_abs_common(var1digits, var1ndigits, var1weight,
8529 : var2digits, var2ndigits, var2weight);
8530 : }
8531 :
8532 81802 : if (var2sign == NUMERIC_POS)
8533 23280 : return -1;
8534 :
8535 58522 : return cmp_abs_common(var2digits, var2ndigits, var2weight,
8536 : var1digits, var1ndigits, var1weight);
8537 : }
8538 :
8539 :
8540 : /*
8541 : * add_var() -
8542 : *
8543 : * Full version of add functionality on variable level (handling signs).
8544 : * result might point to one of the operands too without danger.
8545 : */
8546 : static void
8547 618130 : add_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
8548 : {
8549 : /*
8550 : * Decide on the signs of the two variables what to do
8551 : */
8552 618130 : if (var1->sign == NUMERIC_POS)
8553 : {
8554 616564 : if (var2->sign == NUMERIC_POS)
8555 : {
8556 : /*
8557 : * Both are positive result = +(ABS(var1) + ABS(var2))
8558 : */
8559 416164 : add_abs(var1, var2, result);
8560 416164 : result->sign = NUMERIC_POS;
8561 : }
8562 : else
8563 : {
8564 : /*
8565 : * var1 is positive, var2 is negative Must compare absolute values
8566 : */
8567 200400 : switch (cmp_abs(var1, var2))
8568 : {
8569 178 : case 0:
8570 : /* ----------
8571 : * ABS(var1) == ABS(var2)
8572 : * result = ZERO
8573 : * ----------
8574 : */
8575 178 : zero_var(result);
8576 178 : result->dscale = Max(var1->dscale, var2->dscale);
8577 178 : break;
8578 :
8579 186310 : case 1:
8580 : /* ----------
8581 : * ABS(var1) > ABS(var2)
8582 : * result = +(ABS(var1) - ABS(var2))
8583 : * ----------
8584 : */
8585 186310 : sub_abs(var1, var2, result);
8586 186310 : result->sign = NUMERIC_POS;
8587 186310 : break;
8588 :
8589 13912 : case -1:
8590 : /* ----------
8591 : * ABS(var1) < ABS(var2)
8592 : * result = -(ABS(var2) - ABS(var1))
8593 : * ----------
8594 : */
8595 13912 : sub_abs(var2, var1, result);
8596 13912 : result->sign = NUMERIC_NEG;
8597 13912 : break;
8598 : }
8599 : }
8600 : }
8601 : else
8602 : {
8603 1566 : if (var2->sign == NUMERIC_POS)
8604 : {
8605 : /* ----------
8606 : * var1 is negative, var2 is positive
8607 : * Must compare absolute values
8608 : * ----------
8609 : */
8610 468 : switch (cmp_abs(var1, var2))
8611 : {
8612 30 : case 0:
8613 : /* ----------
8614 : * ABS(var1) == ABS(var2)
8615 : * result = ZERO
8616 : * ----------
8617 : */
8618 30 : zero_var(result);
8619 30 : result->dscale = Max(var1->dscale, var2->dscale);
8620 30 : break;
8621 :
8622 294 : case 1:
8623 : /* ----------
8624 : * ABS(var1) > ABS(var2)
8625 : * result = -(ABS(var1) - ABS(var2))
8626 : * ----------
8627 : */
8628 294 : sub_abs(var1, var2, result);
8629 294 : result->sign = NUMERIC_NEG;
8630 294 : break;
8631 :
8632 144 : case -1:
8633 : /* ----------
8634 : * ABS(var1) < ABS(var2)
8635 : * result = +(ABS(var2) - ABS(var1))
8636 : * ----------
8637 : */
8638 144 : sub_abs(var2, var1, result);
8639 144 : result->sign = NUMERIC_POS;
8640 144 : break;
8641 : }
8642 : }
8643 : else
8644 : {
8645 : /* ----------
8646 : * Both are negative
8647 : * result = -(ABS(var1) + ABS(var2))
8648 : * ----------
8649 : */
8650 1098 : add_abs(var1, var2, result);
8651 1098 : result->sign = NUMERIC_NEG;
8652 : }
8653 : }
8654 618130 : }
8655 :
8656 :
8657 : /*
8658 : * sub_var() -
8659 : *
8660 : * Full version of sub functionality on variable level (handling signs).
8661 : * result might point to one of the operands too without danger.
8662 : */
8663 : static void
8664 533064 : sub_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
8665 : {
8666 : /*
8667 : * Decide on the signs of the two variables what to do
8668 : */
8669 533064 : if (var1->sign == NUMERIC_POS)
8670 : {
8671 532154 : if (var2->sign == NUMERIC_NEG)
8672 : {
8673 : /* ----------
8674 : * var1 is positive, var2 is negative
8675 : * result = +(ABS(var1) + ABS(var2))
8676 : * ----------
8677 : */
8678 28342 : add_abs(var1, var2, result);
8679 28342 : result->sign = NUMERIC_POS;
8680 : }
8681 : else
8682 : {
8683 : /* ----------
8684 : * Both are positive
8685 : * Must compare absolute values
8686 : * ----------
8687 : */
8688 503812 : switch (cmp_abs(var1, var2))
8689 : {
8690 49162 : case 0:
8691 : /* ----------
8692 : * ABS(var1) == ABS(var2)
8693 : * result = ZERO
8694 : * ----------
8695 : */
8696 49162 : zero_var(result);
8697 49162 : result->dscale = Max(var1->dscale, var2->dscale);
8698 49162 : break;
8699 :
8700 449834 : case 1:
8701 : /* ----------
8702 : * ABS(var1) > ABS(var2)
8703 : * result = +(ABS(var1) - ABS(var2))
8704 : * ----------
8705 : */
8706 449834 : sub_abs(var1, var2, result);
8707 449834 : result->sign = NUMERIC_POS;
8708 449834 : break;
8709 :
8710 4816 : case -1:
8711 : /* ----------
8712 : * ABS(var1) < ABS(var2)
8713 : * result = -(ABS(var2) - ABS(var1))
8714 : * ----------
8715 : */
8716 4816 : sub_abs(var2, var1, result);
8717 4816 : result->sign = NUMERIC_NEG;
8718 4816 : break;
8719 : }
8720 : }
8721 : }
8722 : else
8723 : {
8724 910 : if (var2->sign == NUMERIC_NEG)
8725 : {
8726 : /* ----------
8727 : * Both are negative
8728 : * Must compare absolute values
8729 : * ----------
8730 : */
8731 454 : switch (cmp_abs(var1, var2))
8732 : {
8733 166 : case 0:
8734 : /* ----------
8735 : * ABS(var1) == ABS(var2)
8736 : * result = ZERO
8737 : * ----------
8738 : */
8739 166 : zero_var(result);
8740 166 : result->dscale = Max(var1->dscale, var2->dscale);
8741 166 : break;
8742 :
8743 240 : case 1:
8744 : /* ----------
8745 : * ABS(var1) > ABS(var2)
8746 : * result = -(ABS(var1) - ABS(var2))
8747 : * ----------
8748 : */
8749 240 : sub_abs(var1, var2, result);
8750 240 : result->sign = NUMERIC_NEG;
8751 240 : break;
8752 :
8753 48 : case -1:
8754 : /* ----------
8755 : * ABS(var1) < ABS(var2)
8756 : * result = +(ABS(var2) - ABS(var1))
8757 : * ----------
8758 : */
8759 48 : sub_abs(var2, var1, result);
8760 48 : result->sign = NUMERIC_POS;
8761 48 : break;
8762 : }
8763 : }
8764 : else
8765 : {
8766 : /* ----------
8767 : * var1 is negative, var2 is positive
8768 : * result = -(ABS(var1) + ABS(var2))
8769 : * ----------
8770 : */
8771 456 : add_abs(var1, var2, result);
8772 456 : result->sign = NUMERIC_NEG;
8773 : }
8774 : }
8775 533064 : }
8776 :
8777 :
8778 : /*
8779 : * mul_var() -
8780 : *
8781 : * Multiplication on variable level. Product of var1 * var2 is stored
8782 : * in result. Result is rounded to no more than rscale fractional digits.
8783 : */
8784 : static void
8785 1189800 : mul_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result,
8786 : int rscale)
8787 : {
8788 : int res_ndigits;
8789 : int res_ndigitpairs;
8790 : int res_sign;
8791 : int res_weight;
8792 : int pair_offset;
8793 : int maxdigits;
8794 : int maxdigitpairs;
8795 : uint64 *dig,
8796 : *dig_i1_off;
8797 : uint64 maxdig;
8798 : uint64 carry;
8799 : uint64 newdig;
8800 : int var1ndigits;
8801 : int var2ndigits;
8802 : int var1ndigitpairs;
8803 : int var2ndigitpairs;
8804 : NumericDigit *var1digits;
8805 : NumericDigit *var2digits;
8806 : uint32 var1digitpair;
8807 : uint32 *var2digitpairs;
8808 : NumericDigit *res_digits;
8809 : int i,
8810 : i1,
8811 : i2,
8812 : i2limit;
8813 :
8814 : /*
8815 : * Arrange for var1 to be the shorter of the two numbers. This improves
8816 : * performance because the inner multiplication loop is much simpler than
8817 : * the outer loop, so it's better to have a smaller number of iterations
8818 : * of the outer loop. This also reduces the number of times that the
8819 : * accumulator array needs to be normalized.
8820 : */
8821 1189800 : if (var1->ndigits > var2->ndigits)
8822 : {
8823 15226 : const NumericVar *tmp = var1;
8824 :
8825 15226 : var1 = var2;
8826 15226 : var2 = tmp;
8827 : }
8828 :
8829 : /* copy these values into local vars for speed in inner loop */
8830 1189800 : var1ndigits = var1->ndigits;
8831 1189800 : var2ndigits = var2->ndigits;
8832 1189800 : var1digits = var1->digits;
8833 1189800 : var2digits = var2->digits;
8834 :
8835 1189800 : if (var1ndigits == 0)
8836 : {
8837 : /* one or both inputs is zero; so is result */
8838 2894 : zero_var(result);
8839 2894 : result->dscale = rscale;
8840 2894 : return;
8841 : }
8842 :
8843 : /*
8844 : * If var1 has 1-6 digits and the exact result was requested, delegate to
8845 : * mul_var_short() which uses a faster direct multiplication algorithm.
8846 : */
8847 1186906 : if (var1ndigits <= 6 && rscale == var1->dscale + var2->dscale)
8848 : {
8849 1158430 : mul_var_short(var1, var2, result);
8850 1158430 : return;
8851 : }
8852 :
8853 : /* Determine result sign */
8854 28476 : if (var1->sign == var2->sign)
8855 26994 : res_sign = NUMERIC_POS;
8856 : else
8857 1482 : res_sign = NUMERIC_NEG;
8858 :
8859 : /*
8860 : * Determine the number of result digits to compute and the (maximum
8861 : * possible) result weight. If the exact result would have more than
8862 : * rscale fractional digits, truncate the computation with
8863 : * MUL_GUARD_DIGITS guard digits, i.e., ignore input digits that would
8864 : * only contribute to the right of that. (This will give the exact
8865 : * rounded-to-rscale answer unless carries out of the ignored positions
8866 : * would have propagated through more than MUL_GUARD_DIGITS digits.)
8867 : *
8868 : * Note: an exact computation could not produce more than var1ndigits +
8869 : * var2ndigits digits, but we allocate at least one extra output digit in
8870 : * case rscale-driven rounding produces a carry out of the highest exact
8871 : * digit.
8872 : *
8873 : * The computation itself is done using base-NBASE^2 arithmetic, so we
8874 : * actually process the input digits in pairs, producing a base-NBASE^2
8875 : * intermediate result. This significantly improves performance, since
8876 : * schoolbook multiplication is O(N^2) in the number of input digits, and
8877 : * working in base NBASE^2 effectively halves "N".
8878 : *
8879 : * Note: in a truncated computation, we must compute at least one extra
8880 : * output digit to ensure that all the guard digits are fully computed.
8881 : */
8882 : /* digit pairs in each input */
8883 28476 : var1ndigitpairs = (var1ndigits + 1) / 2;
8884 28476 : var2ndigitpairs = (var2ndigits + 1) / 2;
8885 :
8886 : /* digits in exact result */
8887 28476 : res_ndigits = var1ndigits + var2ndigits;
8888 :
8889 : /* digit pairs in exact result with at least one extra output digit */
8890 28476 : res_ndigitpairs = res_ndigits / 2 + 1;
8891 :
8892 : /* pair offset to align result to end of dig[] */
8893 28476 : pair_offset = res_ndigitpairs - var1ndigitpairs - var2ndigitpairs + 1;
8894 :
8895 : /* maximum possible result weight (odd-length inputs shifted up below) */
8896 28476 : res_weight = var1->weight + var2->weight + 1 + 2 * res_ndigitpairs -
8897 28476 : res_ndigits - (var1ndigits & 1) - (var2ndigits & 1);
8898 :
8899 : /* rscale-based truncation with at least one extra output digit */
8900 28476 : maxdigits = res_weight + 1 + (rscale + DEC_DIGITS - 1) / DEC_DIGITS +
8901 : MUL_GUARD_DIGITS;
8902 28476 : maxdigitpairs = maxdigits / 2 + 1;
8903 :
8904 28476 : res_ndigitpairs = Min(res_ndigitpairs, maxdigitpairs);
8905 28476 : res_ndigits = 2 * res_ndigitpairs;
8906 :
8907 : /*
8908 : * In the computation below, digit pair i1 of var1 and digit pair i2 of
8909 : * var2 are multiplied and added to digit i1+i2+pair_offset of dig[]. Thus
8910 : * input digit pairs with index >= res_ndigitpairs - pair_offset don't
8911 : * contribute to the result, and can be ignored.
8912 : */
8913 28476 : if (res_ndigitpairs <= pair_offset)
8914 : {
8915 : /* All input digits will be ignored; so result is zero */
8916 12 : zero_var(result);
8917 12 : result->dscale = rscale;
8918 12 : return;
8919 : }
8920 28464 : var1ndigitpairs = Min(var1ndigitpairs, res_ndigitpairs - pair_offset);
8921 28464 : var2ndigitpairs = Min(var2ndigitpairs, res_ndigitpairs - pair_offset);
8922 :
8923 : /*
8924 : * We do the arithmetic in an array "dig[]" of unsigned 64-bit integers.
8925 : * Since PG_UINT64_MAX is much larger than NBASE^4, this gives us a lot of
8926 : * headroom to avoid normalizing carries immediately.
8927 : *
8928 : * maxdig tracks the maximum possible value of any dig[] entry; when this
8929 : * threatens to exceed PG_UINT64_MAX, we take the time to propagate
8930 : * carries. Furthermore, we need to ensure that overflow doesn't occur
8931 : * during the carry propagation passes either. The carry values could be
8932 : * as much as PG_UINT64_MAX / NBASE^2, so really we must normalize when
8933 : * digits threaten to exceed PG_UINT64_MAX - PG_UINT64_MAX / NBASE^2.
8934 : *
8935 : * To avoid overflow in maxdig itself, it actually represents the maximum
8936 : * possible value divided by NBASE^2-1, i.e., at the top of the loop it is
8937 : * known that no dig[] entry exceeds maxdig * (NBASE^2-1).
8938 : *
8939 : * The conversion of var1 to base NBASE^2 is done on the fly, as each new
8940 : * digit is required. The digits of var2 are converted upfront, and
8941 : * stored at the end of dig[]. To avoid loss of precision, the input
8942 : * digits are aligned with the start of digit pair array, effectively
8943 : * shifting them up (multiplying by NBASE) if the inputs have an odd
8944 : * number of NBASE digits.
8945 : */
8946 28464 : dig = (uint64 *) palloc(res_ndigitpairs * sizeof(uint64) +
8947 : var2ndigitpairs * sizeof(uint32));
8948 :
8949 : /* convert var2 to base NBASE^2, shifting up if its length is odd */
8950 28464 : var2digitpairs = (uint32 *) (dig + res_ndigitpairs);
8951 :
8952 1547190 : for (i2 = 0; i2 < var2ndigitpairs - 1; i2++)
8953 1518726 : var2digitpairs[i2] = var2digits[2 * i2] * NBASE + var2digits[2 * i2 + 1];
8954 :
8955 28464 : if (2 * i2 + 1 < var2ndigits)
8956 20448 : var2digitpairs[i2] = var2digits[2 * i2] * NBASE + var2digits[2 * i2 + 1];
8957 : else
8958 8016 : var2digitpairs[i2] = var2digits[2 * i2] * NBASE;
8959 :
8960 : /*
8961 : * Start by multiplying var2 by the least significant contributing digit
8962 : * pair from var1, storing the results at the end of dig[], and filling
8963 : * the leading digits with zeros.
8964 : *
8965 : * The loop here is the same as the inner loop below, except that we set
8966 : * the results in dig[], rather than adding to them. This is the
8967 : * performance bottleneck for multiplication, so we want to keep it simple
8968 : * enough so that it can be auto-vectorized. Accordingly, process the
8969 : * digits left-to-right even though schoolbook multiplication would
8970 : * suggest right-to-left. Since we aren't propagating carries in this
8971 : * loop, the order does not matter.
8972 : */
8973 28464 : i1 = var1ndigitpairs - 1;
8974 28464 : if (2 * i1 + 1 < var1ndigits)
8975 12720 : var1digitpair = var1digits[2 * i1] * NBASE + var1digits[2 * i1 + 1];
8976 : else
8977 15744 : var1digitpair = var1digits[2 * i1] * NBASE;
8978 28464 : maxdig = var1digitpair;
8979 :
8980 28464 : i2limit = Min(var2ndigitpairs, res_ndigitpairs - i1 - pair_offset);
8981 28464 : dig_i1_off = &dig[i1 + pair_offset];
8982 :
8983 28464 : memset(dig, 0, (i1 + pair_offset) * sizeof(uint64));
8984 1376622 : for (i2 = 0; i2 < i2limit; i2++)
8985 1348158 : dig_i1_off[i2] = (uint64) var1digitpair * var2digitpairs[i2];
8986 :
8987 : /*
8988 : * Next, multiply var2 by the remaining digit pairs from var1, adding the
8989 : * results to dig[] at the appropriate offsets, and normalizing whenever
8990 : * there is a risk of any dig[] entry overflowing.
8991 : */
8992 1501710 : for (i1 = i1 - 1; i1 >= 0; i1--)
8993 : {
8994 1473246 : var1digitpair = var1digits[2 * i1] * NBASE + var1digits[2 * i1 + 1];
8995 1473246 : if (var1digitpair == 0)
8996 1179516 : continue;
8997 :
8998 : /* Time to normalize? */
8999 293730 : maxdig += var1digitpair;
9000 293730 : if (maxdig > (PG_UINT64_MAX - PG_UINT64_MAX / NBASE_SQR) / (NBASE_SQR - 1))
9001 : {
9002 : /* Yes, do it (to base NBASE^2) */
9003 30 : carry = 0;
9004 119964 : for (i = res_ndigitpairs - 1; i >= 0; i--)
9005 : {
9006 119934 : newdig = dig[i] + carry;
9007 119934 : if (newdig >= NBASE_SQR)
9008 : {
9009 115242 : carry = newdig / NBASE_SQR;
9010 115242 : newdig -= carry * NBASE_SQR;
9011 : }
9012 : else
9013 4692 : carry = 0;
9014 119934 : dig[i] = newdig;
9015 : }
9016 : Assert(carry == 0);
9017 : /* Reset maxdig to indicate new worst-case */
9018 30 : maxdig = 1 + var1digitpair;
9019 : }
9020 :
9021 : /* Multiply and add */
9022 293730 : i2limit = Min(var2ndigitpairs, res_ndigitpairs - i1 - pair_offset);
9023 293730 : dig_i1_off = &dig[i1 + pair_offset];
9024 :
9025 124047846 : for (i2 = 0; i2 < i2limit; i2++)
9026 123754116 : dig_i1_off[i2] += (uint64) var1digitpair * var2digitpairs[i2];
9027 : }
9028 :
9029 : /*
9030 : * Now we do a final carry propagation pass to normalize back to base
9031 : * NBASE^2, and construct the base-NBASE result digits. Note that this is
9032 : * still done at full precision w/guard digits.
9033 : */
9034 28464 : alloc_var(result, res_ndigits);
9035 28464 : res_digits = result->digits;
9036 28464 : carry = 0;
9037 2882922 : for (i = res_ndigitpairs - 1; i >= 0; i--)
9038 : {
9039 2854458 : newdig = dig[i] + carry;
9040 2854458 : if (newdig >= NBASE_SQR)
9041 : {
9042 406914 : carry = newdig / NBASE_SQR;
9043 406914 : newdig -= carry * NBASE_SQR;
9044 : }
9045 : else
9046 2447544 : carry = 0;
9047 2854458 : res_digits[2 * i + 1] = (NumericDigit) ((uint32) newdig % NBASE);
9048 2854458 : res_digits[2 * i] = (NumericDigit) ((uint32) newdig / NBASE);
9049 : }
9050 : Assert(carry == 0);
9051 :
9052 28464 : pfree(dig);
9053 :
9054 : /*
9055 : * Finally, round the result to the requested precision.
9056 : */
9057 28464 : result->weight = res_weight;
9058 28464 : result->sign = res_sign;
9059 :
9060 : /* Round to target rscale (and set result->dscale) */
9061 28464 : round_var(result, rscale);
9062 :
9063 : /* Strip leading and trailing zeroes */
9064 28464 : strip_var(result);
9065 : }
9066 :
9067 :
9068 : /*
9069 : * mul_var_short() -
9070 : *
9071 : * Special-case multiplication function used when var1 has 1-6 digits, var2
9072 : * has at least as many digits as var1, and the exact product var1 * var2 is
9073 : * requested.
9074 : */
9075 : static void
9076 1158430 : mul_var_short(const NumericVar *var1, const NumericVar *var2,
9077 : NumericVar *result)
9078 : {
9079 1158430 : int var1ndigits = var1->ndigits;
9080 1158430 : int var2ndigits = var2->ndigits;
9081 1158430 : NumericDigit *var1digits = var1->digits;
9082 1158430 : NumericDigit *var2digits = var2->digits;
9083 : int res_sign;
9084 : int res_weight;
9085 : int res_ndigits;
9086 : NumericDigit *res_buf;
9087 : NumericDigit *res_digits;
9088 1158430 : uint32 carry = 0;
9089 : uint32 term;
9090 :
9091 : /* Check preconditions */
9092 : Assert(var1ndigits >= 1);
9093 : Assert(var1ndigits <= 6);
9094 : Assert(var2ndigits >= var1ndigits);
9095 :
9096 : /*
9097 : * Determine the result sign, weight, and number of digits to calculate.
9098 : * The weight figured here is correct if the product has no leading zero
9099 : * digits; otherwise strip_var() will fix things up. Note that, unlike
9100 : * mul_var(), we do not need to allocate an extra output digit, because we
9101 : * are not rounding here.
9102 : */
9103 1158430 : if (var1->sign == var2->sign)
9104 1157238 : res_sign = NUMERIC_POS;
9105 : else
9106 1192 : res_sign = NUMERIC_NEG;
9107 1158430 : res_weight = var1->weight + var2->weight + 1;
9108 1158430 : res_ndigits = var1ndigits + var2ndigits;
9109 :
9110 : /* Allocate result digit array */
9111 1158430 : res_buf = digitbuf_alloc(res_ndigits + 1);
9112 1158430 : res_buf[0] = 0; /* spare digit for later rounding */
9113 1158430 : res_digits = res_buf + 1;
9114 :
9115 : /*
9116 : * Compute the result digits in reverse, in one pass, propagating the
9117 : * carry up as we go. The i'th result digit consists of the sum of the
9118 : * products var1digits[i1] * var2digits[i2] for which i = i1 + i2 + 1.
9119 : */
9120 : #define PRODSUM1(v1,i1,v2,i2) ((v1)[(i1)] * (v2)[(i2)])
9121 : #define PRODSUM2(v1,i1,v2,i2) (PRODSUM1(v1,i1,v2,i2) + (v1)[(i1)+1] * (v2)[(i2)-1])
9122 : #define PRODSUM3(v1,i1,v2,i2) (PRODSUM2(v1,i1,v2,i2) + (v1)[(i1)+2] * (v2)[(i2)-2])
9123 : #define PRODSUM4(v1,i1,v2,i2) (PRODSUM3(v1,i1,v2,i2) + (v1)[(i1)+3] * (v2)[(i2)-3])
9124 : #define PRODSUM5(v1,i1,v2,i2) (PRODSUM4(v1,i1,v2,i2) + (v1)[(i1)+4] * (v2)[(i2)-4])
9125 : #define PRODSUM6(v1,i1,v2,i2) (PRODSUM5(v1,i1,v2,i2) + (v1)[(i1)+5] * (v2)[(i2)-5])
9126 :
9127 1158430 : switch (var1ndigits)
9128 : {
9129 1152724 : case 1:
9130 : /* ---------
9131 : * 1-digit case:
9132 : * var1ndigits = 1
9133 : * var2ndigits >= 1
9134 : * res_ndigits = var2ndigits + 1
9135 : * ----------
9136 : */
9137 3605240 : for (int i = var2ndigits - 1; i >= 0; i--)
9138 : {
9139 2452516 : term = PRODSUM1(var1digits, 0, var2digits, i) + carry;
9140 2452516 : res_digits[i + 1] = (NumericDigit) (term % NBASE);
9141 2452516 : carry = term / NBASE;
9142 : }
9143 1152724 : res_digits[0] = (NumericDigit) carry;
9144 1152724 : break;
9145 :
9146 756 : case 2:
9147 : /* ---------
9148 : * 2-digit case:
9149 : * var1ndigits = 2
9150 : * var2ndigits >= 2
9151 : * res_ndigits = var2ndigits + 2
9152 : * ----------
9153 : */
9154 : /* last result digit and carry */
9155 756 : term = PRODSUM1(var1digits, 1, var2digits, var2ndigits - 1);
9156 756 : res_digits[res_ndigits - 1] = (NumericDigit) (term % NBASE);
9157 756 : carry = term / NBASE;
9158 :
9159 : /* remaining digits, except for the first two */
9160 2304 : for (int i = var2ndigits - 1; i >= 1; i--)
9161 : {
9162 1548 : term = PRODSUM2(var1digits, 0, var2digits, i) + carry;
9163 1548 : res_digits[i + 1] = (NumericDigit) (term % NBASE);
9164 1548 : carry = term / NBASE;
9165 : }
9166 756 : break;
9167 :
9168 204 : case 3:
9169 : /* ---------
9170 : * 3-digit case:
9171 : * var1ndigits = 3
9172 : * var2ndigits >= 3
9173 : * res_ndigits = var2ndigits + 3
9174 : * ----------
9175 : */
9176 : /* last two result digits */
9177 204 : term = PRODSUM1(var1digits, 2, var2digits, var2ndigits - 1);
9178 204 : res_digits[res_ndigits - 1] = (NumericDigit) (term % NBASE);
9179 204 : carry = term / NBASE;
9180 :
9181 204 : term = PRODSUM2(var1digits, 1, var2digits, var2ndigits - 1) + carry;
9182 204 : res_digits[res_ndigits - 2] = (NumericDigit) (term % NBASE);
9183 204 : carry = term / NBASE;
9184 :
9185 : /* remaining digits, except for the first three */
9186 546 : for (int i = var2ndigits - 1; i >= 2; i--)
9187 : {
9188 342 : term = PRODSUM3(var1digits, 0, var2digits, i) + carry;
9189 342 : res_digits[i + 1] = (NumericDigit) (term % NBASE);
9190 342 : carry = term / NBASE;
9191 : }
9192 204 : break;
9193 :
9194 4038 : case 4:
9195 : /* ---------
9196 : * 4-digit case:
9197 : * var1ndigits = 4
9198 : * var2ndigits >= 4
9199 : * res_ndigits = var2ndigits + 4
9200 : * ----------
9201 : */
9202 : /* last three result digits */
9203 4038 : term = PRODSUM1(var1digits, 3, var2digits, var2ndigits - 1);
9204 4038 : res_digits[res_ndigits - 1] = (NumericDigit) (term % NBASE);
9205 4038 : carry = term / NBASE;
9206 :
9207 4038 : term = PRODSUM2(var1digits, 2, var2digits, var2ndigits - 1) + carry;
9208 4038 : res_digits[res_ndigits - 2] = (NumericDigit) (term % NBASE);
9209 4038 : carry = term / NBASE;
9210 :
9211 4038 : term = PRODSUM3(var1digits, 1, var2digits, var2ndigits - 1) + carry;
9212 4038 : res_digits[res_ndigits - 3] = (NumericDigit) (term % NBASE);
9213 4038 : carry = term / NBASE;
9214 :
9215 : /* remaining digits, except for the first four */
9216 11268 : for (int i = var2ndigits - 1; i >= 3; i--)
9217 : {
9218 7230 : term = PRODSUM4(var1digits, 0, var2digits, i) + carry;
9219 7230 : res_digits[i + 1] = (NumericDigit) (term % NBASE);
9220 7230 : carry = term / NBASE;
9221 : }
9222 4038 : break;
9223 :
9224 114 : case 5:
9225 : /* ---------
9226 : * 5-digit case:
9227 : * var1ndigits = 5
9228 : * var2ndigits >= 5
9229 : * res_ndigits = var2ndigits + 5
9230 : * ----------
9231 : */
9232 : /* last four result digits */
9233 114 : term = PRODSUM1(var1digits, 4, var2digits, var2ndigits - 1);
9234 114 : res_digits[res_ndigits - 1] = (NumericDigit) (term % NBASE);
9235 114 : carry = term / NBASE;
9236 :
9237 114 : term = PRODSUM2(var1digits, 3, var2digits, var2ndigits - 1) + carry;
9238 114 : res_digits[res_ndigits - 2] = (NumericDigit) (term % NBASE);
9239 114 : carry = term / NBASE;
9240 :
9241 114 : term = PRODSUM3(var1digits, 2, var2digits, var2ndigits - 1) + carry;
9242 114 : res_digits[res_ndigits - 3] = (NumericDigit) (term % NBASE);
9243 114 : carry = term / NBASE;
9244 :
9245 114 : term = PRODSUM4(var1digits, 1, var2digits, var2ndigits - 1) + carry;
9246 114 : res_digits[res_ndigits - 4] = (NumericDigit) (term % NBASE);
9247 114 : carry = term / NBASE;
9248 :
9249 : /* remaining digits, except for the first five */
9250 300 : for (int i = var2ndigits - 1; i >= 4; i--)
9251 : {
9252 186 : term = PRODSUM5(var1digits, 0, var2digits, i) + carry;
9253 186 : res_digits[i + 1] = (NumericDigit) (term % NBASE);
9254 186 : carry = term / NBASE;
9255 : }
9256 114 : break;
9257 :
9258 594 : case 6:
9259 : /* ---------
9260 : * 6-digit case:
9261 : * var1ndigits = 6
9262 : * var2ndigits >= 6
9263 : * res_ndigits = var2ndigits + 6
9264 : * ----------
9265 : */
9266 : /* last five result digits */
9267 594 : term = PRODSUM1(var1digits, 5, var2digits, var2ndigits - 1);
9268 594 : res_digits[res_ndigits - 1] = (NumericDigit) (term % NBASE);
9269 594 : carry = term / NBASE;
9270 :
9271 594 : term = PRODSUM2(var1digits, 4, var2digits, var2ndigits - 1) + carry;
9272 594 : res_digits[res_ndigits - 2] = (NumericDigit) (term % NBASE);
9273 594 : carry = term / NBASE;
9274 :
9275 594 : term = PRODSUM3(var1digits, 3, var2digits, var2ndigits - 1) + carry;
9276 594 : res_digits[res_ndigits - 3] = (NumericDigit) (term % NBASE);
9277 594 : carry = term / NBASE;
9278 :
9279 594 : term = PRODSUM4(var1digits, 2, var2digits, var2ndigits - 1) + carry;
9280 594 : res_digits[res_ndigits - 4] = (NumericDigit) (term % NBASE);
9281 594 : carry = term / NBASE;
9282 :
9283 594 : term = PRODSUM5(var1digits, 1, var2digits, var2ndigits - 1) + carry;
9284 594 : res_digits[res_ndigits - 5] = (NumericDigit) (term % NBASE);
9285 594 : carry = term / NBASE;
9286 :
9287 : /* remaining digits, except for the first six */
9288 1656 : for (int i = var2ndigits - 1; i >= 5; i--)
9289 : {
9290 1062 : term = PRODSUM6(var1digits, 0, var2digits, i) + carry;
9291 1062 : res_digits[i + 1] = (NumericDigit) (term % NBASE);
9292 1062 : carry = term / NBASE;
9293 : }
9294 594 : break;
9295 : }
9296 :
9297 : /*
9298 : * Finally, for var1ndigits > 1, compute the remaining var1ndigits most
9299 : * significant result digits.
9300 : */
9301 1158430 : switch (var1ndigits)
9302 : {
9303 594 : case 6:
9304 594 : term = PRODSUM5(var1digits, 0, var2digits, 4) + carry;
9305 594 : res_digits[5] = (NumericDigit) (term % NBASE);
9306 594 : carry = term / NBASE;
9307 : /* FALLTHROUGH */
9308 708 : case 5:
9309 708 : term = PRODSUM4(var1digits, 0, var2digits, 3) + carry;
9310 708 : res_digits[4] = (NumericDigit) (term % NBASE);
9311 708 : carry = term / NBASE;
9312 : /* FALLTHROUGH */
9313 4746 : case 4:
9314 4746 : term = PRODSUM3(var1digits, 0, var2digits, 2) + carry;
9315 4746 : res_digits[3] = (NumericDigit) (term % NBASE);
9316 4746 : carry = term / NBASE;
9317 : /* FALLTHROUGH */
9318 4950 : case 3:
9319 4950 : term = PRODSUM2(var1digits, 0, var2digits, 1) + carry;
9320 4950 : res_digits[2] = (NumericDigit) (term % NBASE);
9321 4950 : carry = term / NBASE;
9322 : /* FALLTHROUGH */
9323 5706 : case 2:
9324 5706 : term = PRODSUM1(var1digits, 0, var2digits, 0) + carry;
9325 5706 : res_digits[1] = (NumericDigit) (term % NBASE);
9326 5706 : res_digits[0] = (NumericDigit) (term / NBASE);
9327 5706 : break;
9328 : }
9329 :
9330 : /* Store the product in result */
9331 1158430 : digitbuf_free(result->buf);
9332 1158430 : result->ndigits = res_ndigits;
9333 1158430 : result->buf = res_buf;
9334 1158430 : result->digits = res_digits;
9335 1158430 : result->weight = res_weight;
9336 1158430 : result->sign = res_sign;
9337 1158430 : result->dscale = var1->dscale + var2->dscale;
9338 :
9339 : /* Strip leading and trailing zeroes */
9340 1158430 : strip_var(result);
9341 1158430 : }
9342 :
9343 :
9344 : /*
9345 : * div_var() -
9346 : *
9347 : * Compute the quotient var1 / var2 to rscale fractional digits.
9348 : *
9349 : * If "round" is true, the result is rounded at the rscale'th digit; if
9350 : * false, it is truncated (towards zero) at that digit.
9351 : *
9352 : * If "exact" is true, the exact result is computed to the specified rscale;
9353 : * if false, successive quotient digits are approximated up to rscale plus
9354 : * DIV_GUARD_DIGITS extra digits, ignoring all contributions from digits to
9355 : * the right of that, before rounding or truncating to the specified rscale.
9356 : * This can be significantly faster, and usually gives the same result as the
9357 : * exact computation, but it may occasionally be off by one in the final
9358 : * digit, if contributions from the ignored digits would have propagated
9359 : * through the guard digits. This is good enough for the transcendental
9360 : * functions, where small errors are acceptable.
9361 : */
9362 : static void
9363 571204 : div_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result,
9364 : int rscale, bool round, bool exact)
9365 : {
9366 571204 : int var1ndigits = var1->ndigits;
9367 571204 : int var2ndigits = var2->ndigits;
9368 : int res_sign;
9369 : int res_weight;
9370 : int res_ndigits;
9371 : int var1ndigitpairs;
9372 : int var2ndigitpairs;
9373 : int res_ndigitpairs;
9374 : int div_ndigitpairs;
9375 : int64 *dividend;
9376 : int32 *divisor;
9377 : double fdivisor,
9378 : fdivisorinverse,
9379 : fdividend,
9380 : fquotient;
9381 : int64 maxdiv;
9382 : int qi;
9383 : int32 qdigit;
9384 : int64 carry;
9385 : int64 newdig;
9386 : int64 *remainder;
9387 : NumericDigit *res_digits;
9388 : int i;
9389 :
9390 : /*
9391 : * First of all division by zero check; we must not be handed an
9392 : * unnormalized divisor.
9393 : */
9394 571204 : if (var2ndigits == 0 || var2->digits[0] == 0)
9395 62 : ereport(ERROR,
9396 : (errcode(ERRCODE_DIVISION_BY_ZERO),
9397 : errmsg("division by zero")));
9398 :
9399 : /*
9400 : * If the divisor has just one or two digits, delegate to div_var_int(),
9401 : * which uses fast short division.
9402 : *
9403 : * Similarly, on platforms with 128-bit integer support, delegate to
9404 : * div_var_int64() for divisors with three or four digits.
9405 : */
9406 571142 : if (var2ndigits <= 2)
9407 : {
9408 : int idivisor;
9409 : int idivisor_weight;
9410 :
9411 565136 : idivisor = var2->digits[0];
9412 565136 : idivisor_weight = var2->weight;
9413 565136 : if (var2ndigits == 2)
9414 : {
9415 3918 : idivisor = idivisor * NBASE + var2->digits[1];
9416 3918 : idivisor_weight--;
9417 : }
9418 565136 : if (var2->sign == NUMERIC_NEG)
9419 654 : idivisor = -idivisor;
9420 :
9421 565136 : div_var_int(var1, idivisor, idivisor_weight, result, rscale, round);
9422 565136 : return;
9423 : }
9424 : #ifdef HAVE_INT128
9425 6006 : if (var2ndigits <= 4)
9426 : {
9427 : int64 idivisor;
9428 : int idivisor_weight;
9429 :
9430 528 : idivisor = var2->digits[0];
9431 528 : idivisor_weight = var2->weight;
9432 1968 : for (i = 1; i < var2ndigits; i++)
9433 : {
9434 1440 : idivisor = idivisor * NBASE + var2->digits[i];
9435 1440 : idivisor_weight--;
9436 : }
9437 528 : if (var2->sign == NUMERIC_NEG)
9438 120 : idivisor = -idivisor;
9439 :
9440 528 : div_var_int64(var1, idivisor, idivisor_weight, result, rscale, round);
9441 528 : return;
9442 : }
9443 : #endif
9444 :
9445 : /*
9446 : * Otherwise, perform full long division.
9447 : */
9448 :
9449 : /* Result zero check */
9450 5478 : if (var1ndigits == 0)
9451 : {
9452 36 : zero_var(result);
9453 36 : result->dscale = rscale;
9454 36 : return;
9455 : }
9456 :
9457 : /*
9458 : * The approximate computation can be significantly faster than the exact
9459 : * one, since the working dividend is var2ndigitpairs base-NBASE^2 digits
9460 : * shorter below. However, that comes with the tradeoff of computing
9461 : * DIV_GUARD_DIGITS extra base-NBASE result digits. Ignoring all other
9462 : * overheads, that suggests that, in theory, the approximate computation
9463 : * will only be faster than the exact one when var2ndigits is greater than
9464 : * 2 * (DIV_GUARD_DIGITS + 1), independent of the size of var1.
9465 : *
9466 : * Thus, we're better off doing an exact computation when var2 is shorter
9467 : * than this. Empirically, it has been found that the exact threshold is
9468 : * a little higher, due to other overheads in the outer division loop.
9469 : */
9470 5442 : if (var2ndigits <= 2 * (DIV_GUARD_DIGITS + 2))
9471 3708 : exact = true;
9472 :
9473 : /*
9474 : * Determine the result sign, weight and number of digits to calculate.
9475 : * The weight figured here is correct if the emitted quotient has no
9476 : * leading zero digits; otherwise strip_var() will fix things up.
9477 : */
9478 5442 : if (var1->sign == var2->sign)
9479 5310 : res_sign = NUMERIC_POS;
9480 : else
9481 132 : res_sign = NUMERIC_NEG;
9482 5442 : res_weight = var1->weight - var2->weight + 1;
9483 : /* The number of accurate result digits we need to produce: */
9484 5442 : res_ndigits = res_weight + 1 + (rscale + DEC_DIGITS - 1) / DEC_DIGITS;
9485 : /* ... but always at least 1 */
9486 5442 : res_ndigits = Max(res_ndigits, 1);
9487 : /* If rounding needed, figure one more digit to ensure correct result */
9488 5442 : if (round)
9489 906 : res_ndigits++;
9490 : /* Add guard digits for roundoff error when producing approx result */
9491 5442 : if (!exact)
9492 1722 : res_ndigits += DIV_GUARD_DIGITS;
9493 :
9494 : /*
9495 : * The computation itself is done using base-NBASE^2 arithmetic, so we
9496 : * actually process the input digits in pairs, producing a base-NBASE^2
9497 : * intermediate result. This significantly improves performance, since
9498 : * the computation is O(N^2) in the number of input digits, and working in
9499 : * base NBASE^2 effectively halves "N".
9500 : */
9501 5442 : var1ndigitpairs = (var1ndigits + 1) / 2;
9502 5442 : var2ndigitpairs = (var2ndigits + 1) / 2;
9503 5442 : res_ndigitpairs = (res_ndigits + 1) / 2;
9504 5442 : res_ndigits = 2 * res_ndigitpairs;
9505 :
9506 : /*
9507 : * We do the arithmetic in an array "dividend[]" of signed 64-bit
9508 : * integers. Since PG_INT64_MAX is much larger than NBASE^4, this gives
9509 : * us a lot of headroom to avoid normalizing carries immediately.
9510 : *
9511 : * When performing an exact computation, the working dividend requires
9512 : * res_ndigitpairs + var2ndigitpairs digits. If var1 is larger than that,
9513 : * the extra digits do not contribute to the result, and are ignored.
9514 : *
9515 : * When performing an approximate computation, the working dividend only
9516 : * requires res_ndigitpairs digits (which includes the extra guard
9517 : * digits). All input digits beyond that are ignored.
9518 : */
9519 5442 : if (exact)
9520 : {
9521 3720 : div_ndigitpairs = res_ndigitpairs + var2ndigitpairs;
9522 3720 : var1ndigitpairs = Min(var1ndigitpairs, div_ndigitpairs);
9523 : }
9524 : else
9525 : {
9526 1722 : div_ndigitpairs = res_ndigitpairs;
9527 1722 : var1ndigitpairs = Min(var1ndigitpairs, div_ndigitpairs);
9528 1722 : var2ndigitpairs = Min(var2ndigitpairs, div_ndigitpairs);
9529 : }
9530 :
9531 : /*
9532 : * Allocate room for the working dividend (div_ndigitpairs 64-bit digits)
9533 : * plus the divisor (var2ndigitpairs 32-bit base-NBASE^2 digits).
9534 : *
9535 : * For convenience, we allocate one extra dividend digit, which is set to
9536 : * zero and not counted in div_ndigitpairs, so that the main loop below
9537 : * can safely read and write the (qi+1)'th digit in the approximate case.
9538 : */
9539 5442 : dividend = (int64 *) palloc((div_ndigitpairs + 1) * sizeof(int64) +
9540 : var2ndigitpairs * sizeof(int32));
9541 5442 : divisor = (int32 *) (dividend + div_ndigitpairs + 1);
9542 :
9543 : /* load var1 into dividend[0 .. var1ndigitpairs-1], zeroing the rest */
9544 49458 : for (i = 0; i < var1ndigitpairs - 1; i++)
9545 44016 : dividend[i] = var1->digits[2 * i] * NBASE + var1->digits[2 * i + 1];
9546 :
9547 5442 : if (2 * i + 1 < var1ndigits)
9548 3282 : dividend[i] = var1->digits[2 * i] * NBASE + var1->digits[2 * i + 1];
9549 : else
9550 2160 : dividend[i] = var1->digits[2 * i] * NBASE;
9551 :
9552 5442 : memset(dividend + i + 1, 0, (div_ndigitpairs - i) * sizeof(int64));
9553 :
9554 : /* load var2 into divisor[0 .. var2ndigitpairs-1] */
9555 39840 : for (i = 0; i < var2ndigitpairs - 1; i++)
9556 34398 : divisor[i] = var2->digits[2 * i] * NBASE + var2->digits[2 * i + 1];
9557 :
9558 5442 : if (2 * i + 1 < var2ndigits)
9559 2922 : divisor[i] = var2->digits[2 * i] * NBASE + var2->digits[2 * i + 1];
9560 : else
9561 2520 : divisor[i] = var2->digits[2 * i] * NBASE;
9562 :
9563 : /*
9564 : * We estimate each quotient digit using floating-point arithmetic, taking
9565 : * the first 2 base-NBASE^2 digits of the (current) dividend and divisor.
9566 : * This must be float to avoid overflow.
9567 : *
9568 : * Since the floating-point dividend and divisor use 4 base-NBASE input
9569 : * digits, they include roughly 40-53 bits of information from their
9570 : * respective inputs (assuming NBASE is 10000), which fits well in IEEE
9571 : * double-precision variables. The relative error in the floating-point
9572 : * quotient digit will then be less than around 2/NBASE^3, so the
9573 : * estimated base-NBASE^2 quotient digit will typically be correct, and
9574 : * should not be off by more than one from the correct value.
9575 : */
9576 5442 : fdivisor = (double) divisor[0] * NBASE_SQR;
9577 5442 : if (var2ndigitpairs > 1)
9578 5442 : fdivisor += (double) divisor[1];
9579 5442 : fdivisorinverse = 1.0 / fdivisor;
9580 :
9581 : /*
9582 : * maxdiv tracks the maximum possible absolute value of any dividend[]
9583 : * entry; when this threatens to exceed PG_INT64_MAX, we take the time to
9584 : * propagate carries. Furthermore, we need to ensure that overflow
9585 : * doesn't occur during the carry propagation passes either. The carry
9586 : * values may have an absolute value as high as PG_INT64_MAX/NBASE^2 + 1,
9587 : * so really we must normalize when digits threaten to exceed PG_INT64_MAX
9588 : * - PG_INT64_MAX/NBASE^2 - 1.
9589 : *
9590 : * To avoid overflow in maxdiv itself, it represents the max absolute
9591 : * value divided by NBASE^2-1, i.e., at the top of the loop it is known
9592 : * that no dividend[] entry has an absolute value exceeding maxdiv *
9593 : * (NBASE^2-1).
9594 : *
9595 : * Actually, though, that holds good only for dividend[] entries after
9596 : * dividend[qi]; the adjustment done at the bottom of the loop may cause
9597 : * dividend[qi + 1] to exceed the maxdiv limit, so that dividend[qi] in
9598 : * the next iteration is beyond the limit. This does not cause problems,
9599 : * as explained below.
9600 : */
9601 5442 : maxdiv = 1;
9602 :
9603 : /*
9604 : * Outer loop computes next quotient digit, which goes in dividend[qi].
9605 : */
9606 49542 : for (qi = 0; qi < res_ndigitpairs; qi++)
9607 : {
9608 : /* Approximate the current dividend value */
9609 44100 : fdividend = (double) dividend[qi] * NBASE_SQR;
9610 44100 : fdividend += (double) dividend[qi + 1];
9611 :
9612 : /* Compute the (approximate) quotient digit */
9613 44100 : fquotient = fdividend * fdivisorinverse;
9614 44100 : qdigit = (fquotient >= 0.0) ? ((int32) fquotient) :
9615 6 : (((int32) fquotient) - 1); /* truncate towards -infinity */
9616 :
9617 44100 : if (qdigit != 0)
9618 : {
9619 : /* Do we need to normalize now? */
9620 40506 : maxdiv += i64abs(qdigit);
9621 40506 : if (maxdiv > (PG_INT64_MAX - PG_INT64_MAX / NBASE_SQR - 1) / (NBASE_SQR - 1))
9622 : {
9623 : /*
9624 : * Yes, do it. Note that if var2ndigitpairs is much smaller
9625 : * than div_ndigitpairs, we can save a significant amount of
9626 : * effort here by noting that we only need to normalise those
9627 : * dividend[] entries touched where prior iterations
9628 : * subtracted multiples of the divisor.
9629 : */
9630 6 : carry = 0;
9631 6750 : for (i = Min(qi + var2ndigitpairs - 2, div_ndigitpairs - 1); i > qi; i--)
9632 : {
9633 6744 : newdig = dividend[i] + carry;
9634 6744 : if (newdig < 0)
9635 : {
9636 6744 : carry = -((-newdig - 1) / NBASE_SQR) - 1;
9637 6744 : newdig -= carry * NBASE_SQR;
9638 : }
9639 0 : else if (newdig >= NBASE_SQR)
9640 : {
9641 0 : carry = newdig / NBASE_SQR;
9642 0 : newdig -= carry * NBASE_SQR;
9643 : }
9644 : else
9645 0 : carry = 0;
9646 6744 : dividend[i] = newdig;
9647 : }
9648 6 : dividend[qi] += carry;
9649 :
9650 : /*
9651 : * All the dividend[] digits except possibly dividend[qi] are
9652 : * now in the range 0..NBASE^2-1. We do not need to consider
9653 : * dividend[qi] in the maxdiv value anymore, so we can reset
9654 : * maxdiv to 1.
9655 : */
9656 6 : maxdiv = 1;
9657 :
9658 : /*
9659 : * Recompute the quotient digit since new info may have
9660 : * propagated into the top two dividend digits.
9661 : */
9662 6 : fdividend = (double) dividend[qi] * NBASE_SQR;
9663 6 : fdividend += (double) dividend[qi + 1];
9664 6 : fquotient = fdividend * fdivisorinverse;
9665 6 : qdigit = (fquotient >= 0.0) ? ((int32) fquotient) :
9666 0 : (((int32) fquotient) - 1); /* truncate towards -infinity */
9667 :
9668 6 : maxdiv += i64abs(qdigit);
9669 : }
9670 :
9671 : /*
9672 : * Subtract off the appropriate multiple of the divisor.
9673 : *
9674 : * The digits beyond dividend[qi] cannot overflow, because we know
9675 : * they will fall within the maxdiv limit. As for dividend[qi]
9676 : * itself, note that qdigit is approximately trunc(dividend[qi] /
9677 : * divisor[0]), which would make the new value simply dividend[qi]
9678 : * mod divisor[0]. The lower-order terms in qdigit can change
9679 : * this result by not more than about twice PG_INT64_MAX/NBASE^2,
9680 : * so overflow is impossible.
9681 : *
9682 : * This inner loop is the performance bottleneck for division, so
9683 : * code it in the same way as the inner loop of mul_var() so that
9684 : * it can be auto-vectorized.
9685 : */
9686 40506 : if (qdigit != 0)
9687 : {
9688 40506 : int istop = Min(var2ndigitpairs, div_ndigitpairs - qi);
9689 40506 : int64 *dividend_qi = ÷nd[qi];
9690 :
9691 7861254 : for (i = 0; i < istop; i++)
9692 7820748 : dividend_qi[i] -= (int64) qdigit * divisor[i];
9693 : }
9694 : }
9695 :
9696 : /*
9697 : * The dividend digit we are about to replace might still be nonzero.
9698 : * Fold it into the next digit position.
9699 : *
9700 : * There is no risk of overflow here, although proving that requires
9701 : * some care. Much as with the argument for dividend[qi] not
9702 : * overflowing, if we consider the first two terms in the numerator
9703 : * and denominator of qdigit, we can see that the final value of
9704 : * dividend[qi + 1] will be approximately a remainder mod
9705 : * (divisor[0]*NBASE^2 + divisor[1]). Accounting for the lower-order
9706 : * terms is a bit complicated but ends up adding not much more than
9707 : * PG_INT64_MAX/NBASE^2 to the possible range. Thus, dividend[qi + 1]
9708 : * cannot overflow here, and in its role as dividend[qi] in the next
9709 : * loop iteration, it can't be large enough to cause overflow in the
9710 : * carry propagation step (if any), either.
9711 : *
9712 : * But having said that: dividend[qi] can be more than
9713 : * PG_INT64_MAX/NBASE^2, as noted above, which means that the product
9714 : * dividend[qi] * NBASE^2 *can* overflow. When that happens, adding
9715 : * it to dividend[qi + 1] will always cause a canceling overflow so
9716 : * that the end result is correct. We could avoid the intermediate
9717 : * overflow by doing the multiplication and addition using unsigned
9718 : * int64 arithmetic, which is modulo 2^64, but so far there appears no
9719 : * need.
9720 : */
9721 44100 : dividend[qi + 1] += dividend[qi] * NBASE_SQR;
9722 :
9723 44100 : dividend[qi] = qdigit;
9724 : }
9725 :
9726 : /*
9727 : * If an exact result was requested, use the remainder to correct the
9728 : * approximate quotient. The remainder is in dividend[], immediately
9729 : * after the quotient digits. Note, however, that although the remainder
9730 : * starts at dividend[qi = res_ndigitpairs], the first digit is the result
9731 : * of folding two remainder digits into one above, and the remainder
9732 : * currently only occupies var2ndigitpairs - 1 digits (the last digit of
9733 : * the working dividend was untouched by the computation above). Thus we
9734 : * expand the remainder down by one base-NBASE^2 digit when we normalize
9735 : * it, so that it completely fills the last var2ndigitpairs digits of the
9736 : * dividend array.
9737 : */
9738 5442 : if (exact)
9739 : {
9740 : /* Normalize the remainder, expanding it down by one digit */
9741 3720 : remainder = ÷nd[qi];
9742 3720 : carry = 0;
9743 20214 : for (i = var2ndigitpairs - 2; i >= 0; i--)
9744 : {
9745 16494 : newdig = remainder[i] + carry;
9746 16494 : if (newdig < 0)
9747 : {
9748 12732 : carry = -((-newdig - 1) / NBASE_SQR) - 1;
9749 12732 : newdig -= carry * NBASE_SQR;
9750 : }
9751 3762 : else if (newdig >= NBASE_SQR)
9752 : {
9753 3684 : carry = newdig / NBASE_SQR;
9754 3684 : newdig -= carry * NBASE_SQR;
9755 : }
9756 : else
9757 78 : carry = 0;
9758 16494 : remainder[i + 1] = newdig;
9759 : }
9760 3720 : remainder[0] = carry;
9761 :
9762 3720 : if (remainder[0] < 0)
9763 : {
9764 : /*
9765 : * The remainder is negative, so the approximate quotient is too
9766 : * large. Correct by reducing the quotient by one and adding the
9767 : * divisor to the remainder until the remainder is positive. We
9768 : * expect the quotient to be off by at most one, which has been
9769 : * borne out in all testing, but not conclusively proven, so we
9770 : * allow for larger corrections, just in case.
9771 : */
9772 : do
9773 : {
9774 : /* Add the divisor to the remainder */
9775 6 : carry = 0;
9776 78 : for (i = var2ndigitpairs - 1; i > 0; i--)
9777 : {
9778 72 : newdig = remainder[i] + divisor[i] + carry;
9779 72 : if (newdig >= NBASE_SQR)
9780 : {
9781 0 : remainder[i] = newdig - NBASE_SQR;
9782 0 : carry = 1;
9783 : }
9784 : else
9785 : {
9786 72 : remainder[i] = newdig;
9787 72 : carry = 0;
9788 : }
9789 : }
9790 6 : remainder[0] += divisor[0] + carry;
9791 :
9792 : /* Subtract 1 from the quotient (propagating carries later) */
9793 6 : dividend[qi - 1]--;
9794 :
9795 6 : } while (remainder[0] < 0);
9796 : }
9797 : else
9798 : {
9799 : /*
9800 : * The remainder is nonnegative. If it's greater than or equal to
9801 : * the divisor, then the approximate quotient is too small and
9802 : * must be corrected. As above, we don't expect to have to apply
9803 : * more than one correction, but allow for it just in case.
9804 : */
9805 : while (true)
9806 6 : {
9807 3720 : bool less = false;
9808 :
9809 : /* Is remainder < divisor? */
9810 3738 : for (i = 0; i < var2ndigitpairs; i++)
9811 : {
9812 3732 : if (remainder[i] < divisor[i])
9813 : {
9814 3714 : less = true;
9815 3714 : break;
9816 : }
9817 18 : if (remainder[i] > divisor[i])
9818 0 : break; /* remainder > divisor */
9819 : }
9820 3720 : if (less)
9821 3714 : break; /* quotient is correct */
9822 :
9823 : /* Subtract the divisor from the remainder */
9824 6 : carry = 0;
9825 18 : for (i = var2ndigitpairs - 1; i > 0; i--)
9826 : {
9827 12 : newdig = remainder[i] - divisor[i] + carry;
9828 12 : if (newdig < 0)
9829 : {
9830 0 : remainder[i] = newdig + NBASE_SQR;
9831 0 : carry = -1;
9832 : }
9833 : else
9834 : {
9835 12 : remainder[i] = newdig;
9836 12 : carry = 0;
9837 : }
9838 : }
9839 6 : remainder[0] = remainder[0] - divisor[0] + carry;
9840 :
9841 : /* Add 1 to the quotient (propagating carries later) */
9842 6 : dividend[qi - 1]++;
9843 : }
9844 : }
9845 : }
9846 :
9847 : /*
9848 : * Because the quotient digits were estimates that might have been off by
9849 : * one (and we didn't bother propagating carries when adjusting the
9850 : * quotient above), some quotient digits might be out of range, so do a
9851 : * final carry propagation pass to normalize back to base NBASE^2, and
9852 : * construct the base-NBASE result digits. Note that this is still done
9853 : * at full precision w/guard digits.
9854 : */
9855 5442 : alloc_var(result, res_ndigits);
9856 5442 : res_digits = result->digits;
9857 5442 : carry = 0;
9858 49542 : for (i = res_ndigitpairs - 1; i >= 0; i--)
9859 : {
9860 44100 : newdig = dividend[i] + carry;
9861 44100 : if (newdig < 0)
9862 : {
9863 6 : carry = -((-newdig - 1) / NBASE_SQR) - 1;
9864 6 : newdig -= carry * NBASE_SQR;
9865 : }
9866 44094 : else if (newdig >= NBASE_SQR)
9867 : {
9868 0 : carry = newdig / NBASE_SQR;
9869 0 : newdig -= carry * NBASE_SQR;
9870 : }
9871 : else
9872 44094 : carry = 0;
9873 44100 : res_digits[2 * i + 1] = (NumericDigit) ((uint32) newdig % NBASE);
9874 44100 : res_digits[2 * i] = (NumericDigit) ((uint32) newdig / NBASE);
9875 : }
9876 : Assert(carry == 0);
9877 :
9878 5442 : pfree(dividend);
9879 :
9880 : /*
9881 : * Finally, round or truncate the result to the requested precision.
9882 : */
9883 5442 : result->weight = res_weight;
9884 5442 : result->sign = res_sign;
9885 :
9886 : /* Round or truncate to target rscale (and set result->dscale) */
9887 5442 : if (round)
9888 906 : round_var(result, rscale);
9889 : else
9890 4536 : trunc_var(result, rscale);
9891 :
9892 : /* Strip leading and trailing zeroes */
9893 5442 : strip_var(result);
9894 : }
9895 :
9896 :
9897 : /*
9898 : * div_var_int() -
9899 : *
9900 : * Divide a numeric variable by a 32-bit integer with the specified weight.
9901 : * The quotient var / (ival * NBASE^ival_weight) is stored in result.
9902 : */
9903 : static void
9904 584294 : div_var_int(const NumericVar *var, int ival, int ival_weight,
9905 : NumericVar *result, int rscale, bool round)
9906 : {
9907 584294 : NumericDigit *var_digits = var->digits;
9908 584294 : int var_ndigits = var->ndigits;
9909 : int res_sign;
9910 : int res_weight;
9911 : int res_ndigits;
9912 : NumericDigit *res_buf;
9913 : NumericDigit *res_digits;
9914 : uint32 divisor;
9915 : int i;
9916 :
9917 : /* Guard against division by zero */
9918 584294 : if (ival == 0)
9919 0 : ereport(ERROR,
9920 : errcode(ERRCODE_DIVISION_BY_ZERO),
9921 : errmsg("division by zero"));
9922 :
9923 : /* Result zero check */
9924 584294 : if (var_ndigits == 0)
9925 : {
9926 2300 : zero_var(result);
9927 2300 : result->dscale = rscale;
9928 2300 : return;
9929 : }
9930 :
9931 : /*
9932 : * Determine the result sign, weight and number of digits to calculate.
9933 : * The weight figured here is correct if the emitted quotient has no
9934 : * leading zero digits; otherwise strip_var() will fix things up.
9935 : */
9936 581994 : if (var->sign == NUMERIC_POS)
9937 579006 : res_sign = ival > 0 ? NUMERIC_POS : NUMERIC_NEG;
9938 : else
9939 2988 : res_sign = ival > 0 ? NUMERIC_NEG : NUMERIC_POS;
9940 581994 : res_weight = var->weight - ival_weight;
9941 : /* The number of accurate result digits we need to produce: */
9942 581994 : res_ndigits = res_weight + 1 + (rscale + DEC_DIGITS - 1) / DEC_DIGITS;
9943 : /* ... but always at least 1 */
9944 581994 : res_ndigits = Max(res_ndigits, 1);
9945 : /* If rounding needed, figure one more digit to ensure correct result */
9946 581994 : if (round)
9947 166686 : res_ndigits++;
9948 :
9949 581994 : res_buf = digitbuf_alloc(res_ndigits + 1);
9950 581994 : res_buf[0] = 0; /* spare digit for later rounding */
9951 581994 : res_digits = res_buf + 1;
9952 :
9953 : /*
9954 : * Now compute the quotient digits. This is the short division algorithm
9955 : * described in Knuth volume 2, section 4.3.1 exercise 16, except that we
9956 : * allow the divisor to exceed the internal base.
9957 : *
9958 : * In this algorithm, the carry from one digit to the next is at most
9959 : * divisor - 1. Therefore, while processing the next digit, carry may
9960 : * become as large as divisor * NBASE - 1, and so it requires a 64-bit
9961 : * integer if this exceeds UINT_MAX.
9962 : */
9963 581994 : divisor = abs(ival);
9964 :
9965 581994 : if (divisor <= UINT_MAX / NBASE)
9966 : {
9967 : /* carry cannot overflow 32 bits */
9968 578676 : uint32 carry = 0;
9969 :
9970 2844878 : for (i = 0; i < res_ndigits; i++)
9971 : {
9972 2266202 : carry = carry * NBASE + (i < var_ndigits ? var_digits[i] : 0);
9973 2266202 : res_digits[i] = (NumericDigit) (carry / divisor);
9974 2266202 : carry = carry % divisor;
9975 : }
9976 : }
9977 : else
9978 : {
9979 : /* carry may exceed 32 bits */
9980 3318 : uint64 carry = 0;
9981 :
9982 10620 : for (i = 0; i < res_ndigits; i++)
9983 : {
9984 7302 : carry = carry * NBASE + (i < var_ndigits ? var_digits[i] : 0);
9985 7302 : res_digits[i] = (NumericDigit) (carry / divisor);
9986 7302 : carry = carry % divisor;
9987 : }
9988 : }
9989 :
9990 : /* Store the quotient in result */
9991 581994 : digitbuf_free(result->buf);
9992 581994 : result->ndigits = res_ndigits;
9993 581994 : result->buf = res_buf;
9994 581994 : result->digits = res_digits;
9995 581994 : result->weight = res_weight;
9996 581994 : result->sign = res_sign;
9997 :
9998 : /* Round or truncate to target rscale (and set result->dscale) */
9999 581994 : if (round)
10000 166686 : round_var(result, rscale);
10001 : else
10002 415308 : trunc_var(result, rscale);
10003 :
10004 : /* Strip leading/trailing zeroes */
10005 581994 : strip_var(result);
10006 : }
10007 :
10008 :
10009 : #ifdef HAVE_INT128
10010 : /*
10011 : * div_var_int64() -
10012 : *
10013 : * Divide a numeric variable by a 64-bit integer with the specified weight.
10014 : * The quotient var / (ival * NBASE^ival_weight) is stored in result.
10015 : *
10016 : * This duplicates the logic in div_var_int(), so any changes made there
10017 : * should be made here too.
10018 : */
10019 : static void
10020 528 : div_var_int64(const NumericVar *var, int64 ival, int ival_weight,
10021 : NumericVar *result, int rscale, bool round)
10022 : {
10023 528 : NumericDigit *var_digits = var->digits;
10024 528 : int var_ndigits = var->ndigits;
10025 : int res_sign;
10026 : int res_weight;
10027 : int res_ndigits;
10028 : NumericDigit *res_buf;
10029 : NumericDigit *res_digits;
10030 : uint64 divisor;
10031 : int i;
10032 :
10033 : /* Guard against division by zero */
10034 528 : if (ival == 0)
10035 0 : ereport(ERROR,
10036 : errcode(ERRCODE_DIVISION_BY_ZERO),
10037 : errmsg("division by zero"));
10038 :
10039 : /* Result zero check */
10040 528 : if (var_ndigits == 0)
10041 : {
10042 96 : zero_var(result);
10043 96 : result->dscale = rscale;
10044 96 : return;
10045 : }
10046 :
10047 : /*
10048 : * Determine the result sign, weight and number of digits to calculate.
10049 : * The weight figured here is correct if the emitted quotient has no
10050 : * leading zero digits; otherwise strip_var() will fix things up.
10051 : */
10052 432 : if (var->sign == NUMERIC_POS)
10053 258 : res_sign = ival > 0 ? NUMERIC_POS : NUMERIC_NEG;
10054 : else
10055 174 : res_sign = ival > 0 ? NUMERIC_NEG : NUMERIC_POS;
10056 432 : res_weight = var->weight - ival_weight;
10057 : /* The number of accurate result digits we need to produce: */
10058 432 : res_ndigits = res_weight + 1 + (rscale + DEC_DIGITS - 1) / DEC_DIGITS;
10059 : /* ... but always at least 1 */
10060 432 : res_ndigits = Max(res_ndigits, 1);
10061 : /* If rounding needed, figure one more digit to ensure correct result */
10062 432 : if (round)
10063 426 : res_ndigits++;
10064 :
10065 432 : res_buf = digitbuf_alloc(res_ndigits + 1);
10066 432 : res_buf[0] = 0; /* spare digit for later rounding */
10067 432 : res_digits = res_buf + 1;
10068 :
10069 : /*
10070 : * Now compute the quotient digits. This is the short division algorithm
10071 : * described in Knuth volume 2, section 4.3.1 exercise 16, except that we
10072 : * allow the divisor to exceed the internal base.
10073 : *
10074 : * In this algorithm, the carry from one digit to the next is at most
10075 : * divisor - 1. Therefore, while processing the next digit, carry may
10076 : * become as large as divisor * NBASE - 1, and so it requires a 128-bit
10077 : * integer if this exceeds PG_UINT64_MAX.
10078 : */
10079 432 : divisor = i64abs(ival);
10080 :
10081 432 : if (divisor <= PG_UINT64_MAX / NBASE)
10082 : {
10083 : /* carry cannot overflow 64 bits */
10084 336 : uint64 carry = 0;
10085 :
10086 3414 : for (i = 0; i < res_ndigits; i++)
10087 : {
10088 3078 : carry = carry * NBASE + (i < var_ndigits ? var_digits[i] : 0);
10089 3078 : res_digits[i] = (NumericDigit) (carry / divisor);
10090 3078 : carry = carry % divisor;
10091 : }
10092 : }
10093 : else
10094 : {
10095 : /* carry may exceed 64 bits */
10096 96 : uint128 carry = 0;
10097 :
10098 1032 : for (i = 0; i < res_ndigits; i++)
10099 : {
10100 936 : carry = carry * NBASE + (i < var_ndigits ? var_digits[i] : 0);
10101 936 : res_digits[i] = (NumericDigit) (carry / divisor);
10102 936 : carry = carry % divisor;
10103 : }
10104 : }
10105 :
10106 : /* Store the quotient in result */
10107 432 : digitbuf_free(result->buf);
10108 432 : result->ndigits = res_ndigits;
10109 432 : result->buf = res_buf;
10110 432 : result->digits = res_digits;
10111 432 : result->weight = res_weight;
10112 432 : result->sign = res_sign;
10113 :
10114 : /* Round or truncate to target rscale (and set result->dscale) */
10115 432 : if (round)
10116 426 : round_var(result, rscale);
10117 : else
10118 6 : trunc_var(result, rscale);
10119 :
10120 : /* Strip leading/trailing zeroes */
10121 432 : strip_var(result);
10122 : }
10123 : #endif
10124 :
10125 :
10126 : /*
10127 : * Default scale selection for division
10128 : *
10129 : * Returns the appropriate result scale for the division result.
10130 : */
10131 : static int
10132 149620 : select_div_scale(const NumericVar *var1, const NumericVar *var2)
10133 : {
10134 : int weight1,
10135 : weight2,
10136 : qweight,
10137 : i;
10138 : NumericDigit firstdigit1,
10139 : firstdigit2;
10140 : int rscale;
10141 :
10142 : /*
10143 : * The result scale of a division isn't specified in any SQL standard. For
10144 : * PostgreSQL we select a result scale that will give at least
10145 : * NUMERIC_MIN_SIG_DIGITS significant digits, so that numeric gives a
10146 : * result no less accurate than float8; but use a scale not less than
10147 : * either input's display scale.
10148 : */
10149 :
10150 : /* Get the actual (normalized) weight and first digit of each input */
10151 :
10152 149620 : weight1 = 0; /* values to use if var1 is zero */
10153 149620 : firstdigit1 = 0;
10154 149620 : for (i = 0; i < var1->ndigits; i++)
10155 : {
10156 147920 : firstdigit1 = var1->digits[i];
10157 147920 : if (firstdigit1 != 0)
10158 : {
10159 147920 : weight1 = var1->weight - i;
10160 147920 : break;
10161 : }
10162 : }
10163 :
10164 149620 : weight2 = 0; /* values to use if var2 is zero */
10165 149620 : firstdigit2 = 0;
10166 149620 : for (i = 0; i < var2->ndigits; i++)
10167 : {
10168 149570 : firstdigit2 = var2->digits[i];
10169 149570 : if (firstdigit2 != 0)
10170 : {
10171 149570 : weight2 = var2->weight - i;
10172 149570 : break;
10173 : }
10174 : }
10175 :
10176 : /*
10177 : * Estimate weight of quotient. If the two first digits are equal, we
10178 : * can't be sure, but assume that var1 is less than var2.
10179 : */
10180 149620 : qweight = weight1 - weight2;
10181 149620 : if (firstdigit1 <= firstdigit2)
10182 132760 : qweight--;
10183 :
10184 : /* Select result scale */
10185 149620 : rscale = NUMERIC_MIN_SIG_DIGITS - qweight * DEC_DIGITS;
10186 149620 : rscale = Max(rscale, var1->dscale);
10187 149620 : rscale = Max(rscale, var2->dscale);
10188 149620 : rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
10189 149620 : rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
10190 :
10191 149620 : return rscale;
10192 : }
10193 :
10194 :
10195 : /*
10196 : * mod_var() -
10197 : *
10198 : * Calculate the modulo of two numerics at variable level
10199 : */
10200 : static void
10201 413784 : mod_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
10202 : {
10203 : NumericVar tmp;
10204 :
10205 413784 : init_var(&tmp);
10206 :
10207 : /* ---------
10208 : * We do this using the equation
10209 : * mod(x,y) = x - trunc(x/y)*y
10210 : * div_var can be persuaded to give us trunc(x/y) directly.
10211 : * ----------
10212 : */
10213 413784 : div_var(var1, var2, &tmp, 0, false, true);
10214 :
10215 413772 : mul_var(var2, &tmp, &tmp, var2->dscale);
10216 :
10217 413772 : sub_var(var1, &tmp, result);
10218 :
10219 413772 : free_var(&tmp);
10220 413772 : }
10221 :
10222 :
10223 : /*
10224 : * div_mod_var() -
10225 : *
10226 : * Calculate the truncated integer quotient and numeric remainder of two
10227 : * numeric variables. The remainder is precise to var2's dscale.
10228 : */
10229 : static void
10230 4518 : div_mod_var(const NumericVar *var1, const NumericVar *var2,
10231 : NumericVar *quot, NumericVar *rem)
10232 : {
10233 : NumericVar q;
10234 : NumericVar r;
10235 :
10236 4518 : init_var(&q);
10237 4518 : init_var(&r);
10238 :
10239 : /*
10240 : * Use div_var() with exact = false to get an initial estimate for the
10241 : * integer quotient (truncated towards zero). This might be slightly
10242 : * inaccurate, but we correct it below.
10243 : */
10244 4518 : div_var(var1, var2, &q, 0, false, false);
10245 :
10246 : /* Compute initial estimate of remainder using the quotient estimate. */
10247 4518 : mul_var(var2, &q, &r, var2->dscale);
10248 4518 : sub_var(var1, &r, &r);
10249 :
10250 : /*
10251 : * Adjust the results if necessary --- the remainder should have the same
10252 : * sign as var1, and its absolute value should be less than the absolute
10253 : * value of var2.
10254 : */
10255 4518 : while (r.ndigits != 0 && r.sign != var1->sign)
10256 : {
10257 : /* The absolute value of the quotient is too large */
10258 0 : if (var1->sign == var2->sign)
10259 : {
10260 0 : sub_var(&q, &const_one, &q);
10261 0 : add_var(&r, var2, &r);
10262 : }
10263 : else
10264 : {
10265 0 : add_var(&q, &const_one, &q);
10266 0 : sub_var(&r, var2, &r);
10267 : }
10268 : }
10269 :
10270 4518 : while (cmp_abs(&r, var2) >= 0)
10271 : {
10272 : /* The absolute value of the quotient is too small */
10273 0 : if (var1->sign == var2->sign)
10274 : {
10275 0 : add_var(&q, &const_one, &q);
10276 0 : sub_var(&r, var2, &r);
10277 : }
10278 : else
10279 : {
10280 0 : sub_var(&q, &const_one, &q);
10281 0 : add_var(&r, var2, &r);
10282 : }
10283 : }
10284 :
10285 4518 : set_var_from_var(&q, quot);
10286 4518 : set_var_from_var(&r, rem);
10287 :
10288 4518 : free_var(&q);
10289 4518 : free_var(&r);
10290 4518 : }
10291 :
10292 :
10293 : /*
10294 : * ceil_var() -
10295 : *
10296 : * Return the smallest integer greater than or equal to the argument
10297 : * on variable level
10298 : */
10299 : static void
10300 204 : ceil_var(const NumericVar *var, NumericVar *result)
10301 : {
10302 : NumericVar tmp;
10303 :
10304 204 : init_var(&tmp);
10305 204 : set_var_from_var(var, &tmp);
10306 :
10307 204 : trunc_var(&tmp, 0);
10308 :
10309 204 : if (var->sign == NUMERIC_POS && cmp_var(var, &tmp) != 0)
10310 60 : add_var(&tmp, &const_one, &tmp);
10311 :
10312 204 : set_var_from_var(&tmp, result);
10313 204 : free_var(&tmp);
10314 204 : }
10315 :
10316 :
10317 : /*
10318 : * floor_var() -
10319 : *
10320 : * Return the largest integer equal to or less than the argument
10321 : * on variable level
10322 : */
10323 : static void
10324 108 : floor_var(const NumericVar *var, NumericVar *result)
10325 : {
10326 : NumericVar tmp;
10327 :
10328 108 : init_var(&tmp);
10329 108 : set_var_from_var(var, &tmp);
10330 :
10331 108 : trunc_var(&tmp, 0);
10332 :
10333 108 : if (var->sign == NUMERIC_NEG && cmp_var(var, &tmp) != 0)
10334 30 : sub_var(&tmp, &const_one, &tmp);
10335 :
10336 108 : set_var_from_var(&tmp, result);
10337 108 : free_var(&tmp);
10338 108 : }
10339 :
10340 :
10341 : /*
10342 : * gcd_var() -
10343 : *
10344 : * Calculate the greatest common divisor of two numerics at variable level
10345 : */
10346 : static void
10347 222 : gcd_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
10348 : {
10349 : int res_dscale;
10350 : int cmp;
10351 : NumericVar tmp_arg;
10352 : NumericVar mod;
10353 :
10354 222 : res_dscale = Max(var1->dscale, var2->dscale);
10355 :
10356 : /*
10357 : * Arrange for var1 to be the number with the greater absolute value.
10358 : *
10359 : * This would happen automatically in the loop below, but avoids an
10360 : * expensive modulo operation.
10361 : */
10362 222 : cmp = cmp_abs(var1, var2);
10363 222 : if (cmp < 0)
10364 : {
10365 84 : const NumericVar *tmp = var1;
10366 :
10367 84 : var1 = var2;
10368 84 : var2 = tmp;
10369 : }
10370 :
10371 : /*
10372 : * Also avoid the taking the modulo if the inputs have the same absolute
10373 : * value, or if the smaller input is zero.
10374 : */
10375 222 : if (cmp == 0 || var2->ndigits == 0)
10376 : {
10377 72 : set_var_from_var(var1, result);
10378 72 : result->sign = NUMERIC_POS;
10379 72 : result->dscale = res_dscale;
10380 72 : return;
10381 : }
10382 :
10383 150 : init_var(&tmp_arg);
10384 150 : init_var(&mod);
10385 :
10386 : /* Use the Euclidean algorithm to find the GCD */
10387 150 : set_var_from_var(var1, &tmp_arg);
10388 150 : set_var_from_var(var2, result);
10389 :
10390 : for (;;)
10391 : {
10392 : /* this loop can take a while, so allow it to be interrupted */
10393 588 : CHECK_FOR_INTERRUPTS();
10394 :
10395 588 : mod_var(&tmp_arg, result, &mod);
10396 588 : if (mod.ndigits == 0)
10397 150 : break;
10398 438 : set_var_from_var(result, &tmp_arg);
10399 438 : set_var_from_var(&mod, result);
10400 : }
10401 150 : result->sign = NUMERIC_POS;
10402 150 : result->dscale = res_dscale;
10403 :
10404 150 : free_var(&tmp_arg);
10405 150 : free_var(&mod);
10406 : }
10407 :
10408 :
10409 : /*
10410 : * sqrt_var() -
10411 : *
10412 : * Compute the square root of x using the Karatsuba Square Root algorithm.
10413 : * NOTE: we allow rscale < 0 here, implying rounding before the decimal
10414 : * point.
10415 : */
10416 : static void
10417 4194 : sqrt_var(const NumericVar *arg, NumericVar *result, int rscale)
10418 : {
10419 : int stat;
10420 : int res_weight;
10421 : int res_ndigits;
10422 : int src_ndigits;
10423 : int step;
10424 : int ndigits[32];
10425 : int blen;
10426 : int64 arg_int64;
10427 : int src_idx;
10428 : int64 s_int64;
10429 : int64 r_int64;
10430 : NumericVar s_var;
10431 : NumericVar r_var;
10432 : NumericVar a0_var;
10433 : NumericVar a1_var;
10434 : NumericVar q_var;
10435 : NumericVar u_var;
10436 :
10437 4194 : stat = cmp_var(arg, &const_zero);
10438 4194 : if (stat == 0)
10439 : {
10440 18 : zero_var(result);
10441 18 : result->dscale = rscale;
10442 18 : return;
10443 : }
10444 :
10445 : /*
10446 : * SQL2003 defines sqrt() in terms of power, so we need to emit the right
10447 : * SQLSTATE error code if the operand is negative.
10448 : */
10449 4176 : if (stat < 0)
10450 6 : ereport(ERROR,
10451 : (errcode(ERRCODE_INVALID_ARGUMENT_FOR_POWER_FUNCTION),
10452 : errmsg("cannot take square root of a negative number")));
10453 :
10454 4170 : init_var(&s_var);
10455 4170 : init_var(&r_var);
10456 4170 : init_var(&a0_var);
10457 4170 : init_var(&a1_var);
10458 4170 : init_var(&q_var);
10459 4170 : init_var(&u_var);
10460 :
10461 : /*
10462 : * The result weight is half the input weight, rounded towards minus
10463 : * infinity --- res_weight = floor(arg->weight / 2).
10464 : */
10465 4170 : if (arg->weight >= 0)
10466 3858 : res_weight = arg->weight / 2;
10467 : else
10468 312 : res_weight = -((-arg->weight - 1) / 2 + 1);
10469 :
10470 : /*
10471 : * Number of NBASE digits to compute. To ensure correct rounding, compute
10472 : * at least 1 extra decimal digit. We explicitly allow rscale to be
10473 : * negative here, but must always compute at least 1 NBASE digit. Thus
10474 : * res_ndigits = res_weight + 1 + ceil((rscale + 1) / DEC_DIGITS) or 1.
10475 : */
10476 4170 : if (rscale + 1 >= 0)
10477 4170 : res_ndigits = res_weight + 1 + (rscale + DEC_DIGITS) / DEC_DIGITS;
10478 : else
10479 0 : res_ndigits = res_weight + 1 - (-rscale - 1) / DEC_DIGITS;
10480 4170 : res_ndigits = Max(res_ndigits, 1);
10481 :
10482 : /*
10483 : * Number of source NBASE digits logically required to produce a result
10484 : * with this precision --- every digit before the decimal point, plus 2
10485 : * for each result digit after the decimal point (or minus 2 for each
10486 : * result digit we round before the decimal point).
10487 : */
10488 4170 : src_ndigits = arg->weight + 1 + (res_ndigits - res_weight - 1) * 2;
10489 4170 : src_ndigits = Max(src_ndigits, 1);
10490 :
10491 : /* ----------
10492 : * From this point on, we treat the input and the result as integers and
10493 : * compute the integer square root and remainder using the Karatsuba
10494 : * Square Root algorithm, which may be written recursively as follows:
10495 : *
10496 : * SqrtRem(n = a3*b^3 + a2*b^2 + a1*b + a0):
10497 : * [ for some base b, and coefficients a0,a1,a2,a3 chosen so that
10498 : * 0 <= a0,a1,a2 < b and a3 >= b/4 ]
10499 : * Let (s,r) = SqrtRem(a3*b + a2)
10500 : * Let (q,u) = DivRem(r*b + a1, 2*s)
10501 : * Let s = s*b + q
10502 : * Let r = u*b + a0 - q^2
10503 : * If r < 0 Then
10504 : * Let r = r + s
10505 : * Let s = s - 1
10506 : * Let r = r + s
10507 : * Return (s,r)
10508 : *
10509 : * See "Karatsuba Square Root", Paul Zimmermann, INRIA Research Report
10510 : * RR-3805, November 1999. At the time of writing this was available
10511 : * on the net at <https://hal.inria.fr/inria-00072854>.
10512 : *
10513 : * The way to read the assumption "n = a3*b^3 + a2*b^2 + a1*b + a0" is
10514 : * "choose a base b such that n requires at least four base-b digits to
10515 : * express; then those digits are a3,a2,a1,a0, with a3 possibly larger
10516 : * than b". For optimal performance, b should have approximately a
10517 : * quarter the number of digits in the input, so that the outer square
10518 : * root computes roughly twice as many digits as the inner one. For
10519 : * simplicity, we choose b = NBASE^blen, an integer power of NBASE.
10520 : *
10521 : * We implement the algorithm iteratively rather than recursively, to
10522 : * allow the working variables to be reused. With this approach, each
10523 : * digit of the input is read precisely once --- src_idx tracks the number
10524 : * of input digits used so far.
10525 : *
10526 : * The array ndigits[] holds the number of NBASE digits of the input that
10527 : * will have been used at the end of each iteration, which roughly doubles
10528 : * each time. Note that the array elements are stored in reverse order,
10529 : * so if the final iteration requires src_ndigits = 37 input digits, the
10530 : * array will contain [37,19,11,7,5,3], and we would start by computing
10531 : * the square root of the 3 most significant NBASE digits.
10532 : *
10533 : * In each iteration, we choose blen to be the largest integer for which
10534 : * the input number has a3 >= b/4, when written in the form above. In
10535 : * general, this means blen = src_ndigits / 4 (truncated), but if
10536 : * src_ndigits is a multiple of 4, that might lead to the coefficient a3
10537 : * being less than b/4 (if the first input digit is less than NBASE/4), in
10538 : * which case we choose blen = src_ndigits / 4 - 1. The number of digits
10539 : * in the inner square root is then src_ndigits - 2*blen. So, for
10540 : * example, if we have src_ndigits = 26 initially, the array ndigits[]
10541 : * will be either [26,14,8,4] or [26,14,8,6,4], depending on the size of
10542 : * the first input digit.
10543 : *
10544 : * Additionally, we can put an upper bound on the number of steps required
10545 : * as follows --- suppose that the number of source digits is an n-bit
10546 : * number in the range [2^(n-1), 2^n-1], then blen will be in the range
10547 : * [2^(n-3)-1, 2^(n-2)-1] and the number of digits in the inner square
10548 : * root will be in the range [2^(n-2), 2^(n-1)+1]. In the next step, blen
10549 : * will be in the range [2^(n-4)-1, 2^(n-3)] and the number of digits in
10550 : * the next inner square root will be in the range [2^(n-3), 2^(n-2)+1].
10551 : * This pattern repeats, and in the worst case the array ndigits[] will
10552 : * contain [2^n-1, 2^(n-1)+1, 2^(n-2)+1, ... 9, 5, 3], and the computation
10553 : * will require n steps. Therefore, since all digit array sizes are
10554 : * signed 32-bit integers, the number of steps required is guaranteed to
10555 : * be less than 32.
10556 : * ----------
10557 : */
10558 4170 : step = 0;
10559 19962 : while ((ndigits[step] = src_ndigits) > 4)
10560 : {
10561 : /* Choose b so that a3 >= b/4, as described above */
10562 15792 : blen = src_ndigits / 4;
10563 15792 : if (blen * 4 == src_ndigits && arg->digits[0] < NBASE / 4)
10564 324 : blen--;
10565 :
10566 : /* Number of digits in the next step (inner square root) */
10567 15792 : src_ndigits -= 2 * blen;
10568 15792 : step++;
10569 : }
10570 :
10571 : /*
10572 : * First iteration (innermost square root and remainder):
10573 : *
10574 : * Here src_ndigits <= 4, and the input fits in an int64. Its square root
10575 : * has at most 9 decimal digits, so estimate it using double precision
10576 : * arithmetic, which will in fact almost certainly return the correct
10577 : * result with no further correction required.
10578 : */
10579 4170 : arg_int64 = arg->digits[0];
10580 13314 : for (src_idx = 1; src_idx < src_ndigits; src_idx++)
10581 : {
10582 9144 : arg_int64 *= NBASE;
10583 9144 : if (src_idx < arg->ndigits)
10584 7686 : arg_int64 += arg->digits[src_idx];
10585 : }
10586 :
10587 4170 : s_int64 = (int64) sqrt((double) arg_int64);
10588 4170 : r_int64 = arg_int64 - s_int64 * s_int64;
10589 :
10590 : /*
10591 : * Use Newton's method to correct the result, if necessary.
10592 : *
10593 : * This uses integer division with truncation to compute the truncated
10594 : * integer square root by iterating using the formula x -> (x + n/x) / 2.
10595 : * This is known to converge to isqrt(n), unless n+1 is a perfect square.
10596 : * If n+1 is a perfect square, the sequence will oscillate between the two
10597 : * values isqrt(n) and isqrt(n)+1, so we can be assured of convergence by
10598 : * checking the remainder.
10599 : */
10600 4170 : while (r_int64 < 0 || r_int64 > 2 * s_int64)
10601 : {
10602 0 : s_int64 = (s_int64 + arg_int64 / s_int64) / 2;
10603 0 : r_int64 = arg_int64 - s_int64 * s_int64;
10604 : }
10605 :
10606 : /*
10607 : * Iterations with src_ndigits <= 8:
10608 : *
10609 : * The next 1 or 2 iterations compute larger (outer) square roots with
10610 : * src_ndigits <= 8, so the result still fits in an int64 (even though the
10611 : * input no longer does) and we can continue to compute using int64
10612 : * variables to avoid more expensive numeric computations.
10613 : *
10614 : * It is fairly easy to see that there is no risk of the intermediate
10615 : * values below overflowing 64-bit integers. In the worst case, the
10616 : * previous iteration will have computed a 3-digit square root (of a
10617 : * 6-digit input less than NBASE^6 / 4), so at the start of this
10618 : * iteration, s will be less than NBASE^3 / 2 = 10^12 / 2, and r will be
10619 : * less than 10^12. In this case, blen will be 1, so numer will be less
10620 : * than 10^17, and denom will be less than 10^12 (and hence u will also be
10621 : * less than 10^12). Finally, since q^2 = u*b + a0 - r, we can also be
10622 : * sure that q^2 < 10^17. Therefore all these quantities fit comfortably
10623 : * in 64-bit integers.
10624 : */
10625 4170 : step--;
10626 10566 : while (step >= 0 && (src_ndigits = ndigits[step]) <= 8)
10627 : {
10628 : int b;
10629 : int a0;
10630 : int a1;
10631 : int i;
10632 : int64 numer;
10633 : int64 denom;
10634 : int64 q;
10635 : int64 u;
10636 :
10637 6396 : blen = (src_ndigits - src_idx) / 2;
10638 :
10639 : /* Extract a1 and a0, and compute b */
10640 6396 : a0 = 0;
10641 6396 : a1 = 0;
10642 6396 : b = 1;
10643 :
10644 12936 : for (i = 0; i < blen; i++, src_idx++)
10645 : {
10646 6540 : b *= NBASE;
10647 6540 : a1 *= NBASE;
10648 6540 : if (src_idx < arg->ndigits)
10649 4800 : a1 += arg->digits[src_idx];
10650 : }
10651 :
10652 12936 : for (i = 0; i < blen; i++, src_idx++)
10653 : {
10654 6540 : a0 *= NBASE;
10655 6540 : if (src_idx < arg->ndigits)
10656 4644 : a0 += arg->digits[src_idx];
10657 : }
10658 :
10659 : /* Compute (q,u) = DivRem(r*b + a1, 2*s) */
10660 6396 : numer = r_int64 * b + a1;
10661 6396 : denom = 2 * s_int64;
10662 6396 : q = numer / denom;
10663 6396 : u = numer - q * denom;
10664 :
10665 : /* Compute s = s*b + q and r = u*b + a0 - q^2 */
10666 6396 : s_int64 = s_int64 * b + q;
10667 6396 : r_int64 = u * b + a0 - q * q;
10668 :
10669 6396 : if (r_int64 < 0)
10670 : {
10671 : /* s is too large by 1; set r += s, s--, r += s */
10672 210 : r_int64 += s_int64;
10673 210 : s_int64--;
10674 210 : r_int64 += s_int64;
10675 : }
10676 :
10677 : Assert(src_idx == src_ndigits); /* All input digits consumed */
10678 6396 : step--;
10679 : }
10680 :
10681 : /*
10682 : * On platforms with 128-bit integer support, we can further delay the
10683 : * need to use numeric variables.
10684 : */
10685 : #ifdef HAVE_INT128
10686 4170 : if (step >= 0)
10687 : {
10688 : int128 s_int128;
10689 : int128 r_int128;
10690 :
10691 4170 : s_int128 = s_int64;
10692 4170 : r_int128 = r_int64;
10693 :
10694 : /*
10695 : * Iterations with src_ndigits <= 16:
10696 : *
10697 : * The result fits in an int128 (even though the input doesn't) so we
10698 : * use int128 variables to avoid more expensive numeric computations.
10699 : */
10700 9048 : while (step >= 0 && (src_ndigits = ndigits[step]) <= 16)
10701 : {
10702 : int64 b;
10703 : int64 a0;
10704 : int64 a1;
10705 : int64 i;
10706 : int128 numer;
10707 : int128 denom;
10708 : int128 q;
10709 : int128 u;
10710 :
10711 4878 : blen = (src_ndigits - src_idx) / 2;
10712 :
10713 : /* Extract a1 and a0, and compute b */
10714 4878 : a0 = 0;
10715 4878 : a1 = 0;
10716 4878 : b = 1;
10717 :
10718 16080 : for (i = 0; i < blen; i++, src_idx++)
10719 : {
10720 11202 : b *= NBASE;
10721 11202 : a1 *= NBASE;
10722 11202 : if (src_idx < arg->ndigits)
10723 6606 : a1 += arg->digits[src_idx];
10724 : }
10725 :
10726 16080 : for (i = 0; i < blen; i++, src_idx++)
10727 : {
10728 11202 : a0 *= NBASE;
10729 11202 : if (src_idx < arg->ndigits)
10730 4470 : a0 += arg->digits[src_idx];
10731 : }
10732 :
10733 : /* Compute (q,u) = DivRem(r*b + a1, 2*s) */
10734 4878 : numer = r_int128 * b + a1;
10735 4878 : denom = 2 * s_int128;
10736 4878 : q = numer / denom;
10737 4878 : u = numer - q * denom;
10738 :
10739 : /* Compute s = s*b + q and r = u*b + a0 - q^2 */
10740 4878 : s_int128 = s_int128 * b + q;
10741 4878 : r_int128 = u * b + a0 - q * q;
10742 :
10743 4878 : if (r_int128 < 0)
10744 : {
10745 : /* s is too large by 1; set r += s, s--, r += s */
10746 192 : r_int128 += s_int128;
10747 192 : s_int128--;
10748 192 : r_int128 += s_int128;
10749 : }
10750 :
10751 : Assert(src_idx == src_ndigits); /* All input digits consumed */
10752 4878 : step--;
10753 : }
10754 :
10755 : /*
10756 : * All remaining iterations require numeric variables. Convert the
10757 : * integer values to NumericVar and continue. Note that in the final
10758 : * iteration we don't need the remainder, so we can save a few cycles
10759 : * there by not fully computing it.
10760 : */
10761 4170 : int128_to_numericvar(s_int128, &s_var);
10762 4170 : if (step >= 0)
10763 2724 : int128_to_numericvar(r_int128, &r_var);
10764 : }
10765 : else
10766 : {
10767 0 : int64_to_numericvar(s_int64, &s_var);
10768 : /* step < 0, so we certainly don't need r */
10769 : }
10770 : #else /* !HAVE_INT128 */
10771 : int64_to_numericvar(s_int64, &s_var);
10772 : if (step >= 0)
10773 : int64_to_numericvar(r_int64, &r_var);
10774 : #endif /* HAVE_INT128 */
10775 :
10776 : /*
10777 : * The remaining iterations with src_ndigits > 8 (or 16, if have int128)
10778 : * use numeric variables.
10779 : */
10780 8688 : while (step >= 0)
10781 : {
10782 : int tmp_len;
10783 :
10784 4518 : src_ndigits = ndigits[step];
10785 4518 : blen = (src_ndigits - src_idx) / 2;
10786 :
10787 : /* Extract a1 and a0 */
10788 4518 : if (src_idx < arg->ndigits)
10789 : {
10790 1512 : tmp_len = Min(blen, arg->ndigits - src_idx);
10791 1512 : alloc_var(&a1_var, tmp_len);
10792 1512 : memcpy(a1_var.digits, arg->digits + src_idx,
10793 : tmp_len * sizeof(NumericDigit));
10794 1512 : a1_var.weight = blen - 1;
10795 1512 : a1_var.sign = NUMERIC_POS;
10796 1512 : a1_var.dscale = 0;
10797 1512 : strip_var(&a1_var);
10798 : }
10799 : else
10800 : {
10801 3006 : zero_var(&a1_var);
10802 3006 : a1_var.dscale = 0;
10803 : }
10804 4518 : src_idx += blen;
10805 :
10806 4518 : if (src_idx < arg->ndigits)
10807 : {
10808 1512 : tmp_len = Min(blen, arg->ndigits - src_idx);
10809 1512 : alloc_var(&a0_var, tmp_len);
10810 1512 : memcpy(a0_var.digits, arg->digits + src_idx,
10811 : tmp_len * sizeof(NumericDigit));
10812 1512 : a0_var.weight = blen - 1;
10813 1512 : a0_var.sign = NUMERIC_POS;
10814 1512 : a0_var.dscale = 0;
10815 1512 : strip_var(&a0_var);
10816 : }
10817 : else
10818 : {
10819 3006 : zero_var(&a0_var);
10820 3006 : a0_var.dscale = 0;
10821 : }
10822 4518 : src_idx += blen;
10823 :
10824 : /* Compute (q,u) = DivRem(r*b + a1, 2*s) */
10825 4518 : set_var_from_var(&r_var, &q_var);
10826 4518 : q_var.weight += blen;
10827 4518 : add_var(&q_var, &a1_var, &q_var);
10828 4518 : add_var(&s_var, &s_var, &u_var);
10829 4518 : div_mod_var(&q_var, &u_var, &q_var, &u_var);
10830 :
10831 : /* Compute s = s*b + q */
10832 4518 : s_var.weight += blen;
10833 4518 : add_var(&s_var, &q_var, &s_var);
10834 :
10835 : /*
10836 : * Compute r = u*b + a0 - q^2.
10837 : *
10838 : * In the final iteration, we don't actually need r; we just need to
10839 : * know whether it is negative, so that we know whether to adjust s.
10840 : * So instead of the final subtraction we can just compare.
10841 : */
10842 4518 : u_var.weight += blen;
10843 4518 : add_var(&u_var, &a0_var, &u_var);
10844 4518 : mul_var(&q_var, &q_var, &q_var, 0);
10845 :
10846 4518 : if (step > 0)
10847 : {
10848 : /* Need r for later iterations */
10849 1794 : sub_var(&u_var, &q_var, &r_var);
10850 1794 : if (r_var.sign == NUMERIC_NEG)
10851 : {
10852 : /* s is too large by 1; set r += s, s--, r += s */
10853 120 : add_var(&r_var, &s_var, &r_var);
10854 120 : sub_var(&s_var, &const_one, &s_var);
10855 120 : add_var(&r_var, &s_var, &r_var);
10856 : }
10857 : }
10858 : else
10859 : {
10860 : /* Don't need r anymore, except to test if s is too large by 1 */
10861 2724 : if (cmp_var(&u_var, &q_var) < 0)
10862 36 : sub_var(&s_var, &const_one, &s_var);
10863 : }
10864 :
10865 : Assert(src_idx == src_ndigits); /* All input digits consumed */
10866 4518 : step--;
10867 : }
10868 :
10869 : /*
10870 : * Construct the final result, rounding it to the requested precision.
10871 : */
10872 4170 : set_var_from_var(&s_var, result);
10873 4170 : result->weight = res_weight;
10874 4170 : result->sign = NUMERIC_POS;
10875 :
10876 : /* Round to target rscale (and set result->dscale) */
10877 4170 : round_var(result, rscale);
10878 :
10879 : /* Strip leading and trailing zeroes */
10880 4170 : strip_var(result);
10881 :
10882 4170 : free_var(&s_var);
10883 4170 : free_var(&r_var);
10884 4170 : free_var(&a0_var);
10885 4170 : free_var(&a1_var);
10886 4170 : free_var(&q_var);
10887 4170 : free_var(&u_var);
10888 : }
10889 :
10890 :
10891 : /*
10892 : * exp_var() -
10893 : *
10894 : * Raise e to the power of x, computed to rscale fractional digits
10895 : */
10896 : static void
10897 180 : exp_var(const NumericVar *arg, NumericVar *result, int rscale)
10898 : {
10899 : NumericVar x;
10900 : NumericVar elem;
10901 : int ni;
10902 : double val;
10903 : int dweight;
10904 : int ndiv2;
10905 : int sig_digits;
10906 : int local_rscale;
10907 :
10908 180 : init_var(&x);
10909 180 : init_var(&elem);
10910 :
10911 180 : set_var_from_var(arg, &x);
10912 :
10913 : /*
10914 : * Estimate the dweight of the result using floating point arithmetic, so
10915 : * that we can choose an appropriate local rscale for the calculation.
10916 : */
10917 180 : val = numericvar_to_double_no_overflow(&x);
10918 :
10919 : /* Guard against overflow/underflow */
10920 : /* If you change this limit, see also power_var()'s limit */
10921 180 : if (fabs(val) >= NUMERIC_MAX_RESULT_SCALE * 3)
10922 : {
10923 6 : if (val > 0)
10924 0 : ereport(ERROR,
10925 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
10926 : errmsg("value overflows numeric format")));
10927 6 : zero_var(result);
10928 6 : result->dscale = rscale;
10929 6 : return;
10930 : }
10931 :
10932 : /* decimal weight = log10(e^x) = x * log10(e) */
10933 174 : dweight = (int) (val * 0.434294481903252);
10934 :
10935 : /*
10936 : * Reduce x to the range -0.01 <= x <= 0.01 (approximately) by dividing by
10937 : * 2^ndiv2, to improve the convergence rate of the Taylor series.
10938 : *
10939 : * Note that the overflow check above ensures that fabs(x) < 6000, which
10940 : * means that ndiv2 <= 20 here.
10941 : */
10942 174 : if (fabs(val) > 0.01)
10943 : {
10944 144 : ndiv2 = 1;
10945 144 : val /= 2;
10946 :
10947 1818 : while (fabs(val) > 0.01)
10948 : {
10949 1674 : ndiv2++;
10950 1674 : val /= 2;
10951 : }
10952 :
10953 144 : local_rscale = x.dscale + ndiv2;
10954 144 : div_var_int(&x, 1 << ndiv2, 0, &x, local_rscale, true);
10955 : }
10956 : else
10957 30 : ndiv2 = 0;
10958 :
10959 : /*
10960 : * Set the scale for the Taylor series expansion. The final result has
10961 : * (dweight + rscale + 1) significant digits. In addition, we have to
10962 : * raise the Taylor series result to the power 2^ndiv2, which introduces
10963 : * an error of up to around log10(2^ndiv2) digits, so work with this many
10964 : * extra digits of precision (plus a few more for good measure).
10965 : */
10966 174 : sig_digits = 1 + dweight + rscale + (int) (ndiv2 * 0.301029995663981);
10967 174 : sig_digits = Max(sig_digits, 0) + 8;
10968 :
10969 174 : local_rscale = sig_digits - 1;
10970 :
10971 : /*
10972 : * Use the Taylor series
10973 : *
10974 : * exp(x) = 1 + x + x^2/2! + x^3/3! + ...
10975 : *
10976 : * Given the limited range of x, this should converge reasonably quickly.
10977 : * We run the series until the terms fall below the local_rscale limit.
10978 : */
10979 174 : add_var(&const_one, &x, result);
10980 :
10981 174 : mul_var(&x, &x, &elem, local_rscale);
10982 174 : ni = 2;
10983 174 : div_var_int(&elem, ni, 0, &elem, local_rscale, true);
10984 :
10985 4992 : while (elem.ndigits != 0)
10986 : {
10987 4818 : add_var(result, &elem, result);
10988 :
10989 4818 : mul_var(&elem, &x, &elem, local_rscale);
10990 4818 : ni++;
10991 4818 : div_var_int(&elem, ni, 0, &elem, local_rscale, true);
10992 : }
10993 :
10994 : /*
10995 : * Compensate for the argument range reduction. Since the weight of the
10996 : * result doubles with each multiplication, we can reduce the local rscale
10997 : * as we proceed.
10998 : */
10999 1992 : while (ndiv2-- > 0)
11000 : {
11001 1818 : local_rscale = sig_digits - result->weight * 2 * DEC_DIGITS;
11002 1818 : local_rscale = Max(local_rscale, NUMERIC_MIN_DISPLAY_SCALE);
11003 1818 : mul_var(result, result, result, local_rscale);
11004 : }
11005 :
11006 : /* Round to requested rscale */
11007 174 : round_var(result, rscale);
11008 :
11009 174 : free_var(&x);
11010 174 : free_var(&elem);
11011 : }
11012 :
11013 :
11014 : /*
11015 : * Estimate the dweight of the most significant decimal digit of the natural
11016 : * logarithm of a number.
11017 : *
11018 : * Essentially, we're approximating log10(abs(ln(var))). This is used to
11019 : * determine the appropriate rscale when computing natural logarithms.
11020 : *
11021 : * Note: many callers call this before range-checking the input. Therefore,
11022 : * we must be robust against values that are invalid to apply ln() to.
11023 : * We don't wish to throw an error here, so just return zero in such cases.
11024 : */
11025 : static int
11026 738 : estimate_ln_dweight(const NumericVar *var)
11027 : {
11028 : int ln_dweight;
11029 :
11030 : /* Caller should fail on ln(negative), but for the moment return zero */
11031 738 : if (var->sign != NUMERIC_POS)
11032 42 : return 0;
11033 :
11034 1314 : if (cmp_var(var, &const_zero_point_nine) >= 0 &&
11035 618 : cmp_var(var, &const_one_point_one) <= 0)
11036 90 : {
11037 : /*
11038 : * 0.9 <= var <= 1.1
11039 : *
11040 : * ln(var) has a negative weight (possibly very large). To get a
11041 : * reasonably accurate result, estimate it using ln(1+x) ~= x.
11042 : */
11043 : NumericVar x;
11044 :
11045 90 : init_var(&x);
11046 90 : sub_var(var, &const_one, &x);
11047 :
11048 90 : if (x.ndigits > 0)
11049 : {
11050 : /* Use weight of most significant decimal digit of x */
11051 42 : ln_dweight = x.weight * DEC_DIGITS + (int) log10(x.digits[0]);
11052 : }
11053 : else
11054 : {
11055 : /* x = 0. Since ln(1) = 0 exactly, we don't need extra digits */
11056 48 : ln_dweight = 0;
11057 : }
11058 :
11059 90 : free_var(&x);
11060 : }
11061 : else
11062 : {
11063 : /*
11064 : * Estimate the logarithm using the first couple of digits from the
11065 : * input number. This will give an accurate result whenever the input
11066 : * is not too close to 1.
11067 : */
11068 606 : if (var->ndigits > 0)
11069 : {
11070 : int digits;
11071 : int dweight;
11072 : double ln_var;
11073 :
11074 564 : digits = var->digits[0];
11075 564 : dweight = var->weight * DEC_DIGITS;
11076 :
11077 564 : if (var->ndigits > 1)
11078 : {
11079 342 : digits = digits * NBASE + var->digits[1];
11080 342 : dweight -= DEC_DIGITS;
11081 : }
11082 :
11083 : /*----------
11084 : * We have var ~= digits * 10^dweight
11085 : * so ln(var) ~= ln(digits) + dweight * ln(10)
11086 : *----------
11087 : */
11088 564 : ln_var = log((double) digits) + dweight * 2.302585092994046;
11089 564 : ln_dweight = (int) log10(fabs(ln_var));
11090 : }
11091 : else
11092 : {
11093 : /* Caller should fail on ln(0), but for the moment return zero */
11094 42 : ln_dweight = 0;
11095 : }
11096 : }
11097 :
11098 696 : return ln_dweight;
11099 : }
11100 :
11101 :
11102 : /*
11103 : * ln_var() -
11104 : *
11105 : * Compute the natural log of x
11106 : */
11107 : static void
11108 834 : ln_var(const NumericVar *arg, NumericVar *result, int rscale)
11109 : {
11110 : NumericVar x;
11111 : NumericVar xx;
11112 : int ni;
11113 : NumericVar elem;
11114 : NumericVar fact;
11115 : int nsqrt;
11116 : int local_rscale;
11117 : int cmp;
11118 :
11119 834 : cmp = cmp_var(arg, &const_zero);
11120 834 : if (cmp == 0)
11121 42 : ereport(ERROR,
11122 : (errcode(ERRCODE_INVALID_ARGUMENT_FOR_LOG),
11123 : errmsg("cannot take logarithm of zero")));
11124 792 : else if (cmp < 0)
11125 36 : ereport(ERROR,
11126 : (errcode(ERRCODE_INVALID_ARGUMENT_FOR_LOG),
11127 : errmsg("cannot take logarithm of a negative number")));
11128 :
11129 756 : init_var(&x);
11130 756 : init_var(&xx);
11131 756 : init_var(&elem);
11132 756 : init_var(&fact);
11133 :
11134 756 : set_var_from_var(arg, &x);
11135 756 : set_var_from_var(&const_two, &fact);
11136 :
11137 : /*
11138 : * Reduce input into range 0.9 < x < 1.1 with repeated sqrt() operations.
11139 : *
11140 : * The final logarithm will have up to around rscale+6 significant digits.
11141 : * Each sqrt() will roughly halve the weight of x, so adjust the local
11142 : * rscale as we work so that we keep this many significant digits at each
11143 : * step (plus a few more for good measure).
11144 : *
11145 : * Note that we allow local_rscale < 0 during this input reduction
11146 : * process, which implies rounding before the decimal point. sqrt_var()
11147 : * explicitly supports this, and it significantly reduces the work
11148 : * required to reduce very large inputs to the required range. Once the
11149 : * input reduction is complete, x.weight will be 0 and its display scale
11150 : * will be non-negative again.
11151 : */
11152 756 : nsqrt = 0;
11153 1068 : while (cmp_var(&x, &const_zero_point_nine) <= 0)
11154 : {
11155 312 : local_rscale = rscale - x.weight * DEC_DIGITS / 2 + 8;
11156 312 : sqrt_var(&x, &x, local_rscale);
11157 312 : mul_var(&fact, &const_two, &fact, 0);
11158 312 : nsqrt++;
11159 : }
11160 4128 : while (cmp_var(&x, &const_one_point_one) >= 0)
11161 : {
11162 3372 : local_rscale = rscale - x.weight * DEC_DIGITS / 2 + 8;
11163 3372 : sqrt_var(&x, &x, local_rscale);
11164 3372 : mul_var(&fact, &const_two, &fact, 0);
11165 3372 : nsqrt++;
11166 : }
11167 :
11168 : /*
11169 : * We use the Taylor series for 0.5 * ln((1+z)/(1-z)),
11170 : *
11171 : * z + z^3/3 + z^5/5 + ...
11172 : *
11173 : * where z = (x-1)/(x+1) is in the range (approximately) -0.053 .. 0.048
11174 : * due to the above range-reduction of x.
11175 : *
11176 : * The convergence of this is not as fast as one would like, but is
11177 : * tolerable given that z is small.
11178 : *
11179 : * The Taylor series result will be multiplied by 2^(nsqrt+1), which has a
11180 : * decimal weight of (nsqrt+1) * log10(2), so work with this many extra
11181 : * digits of precision (plus a few more for good measure).
11182 : */
11183 756 : local_rscale = rscale + (int) ((nsqrt + 1) * 0.301029995663981) + 8;
11184 :
11185 756 : sub_var(&x, &const_one, result);
11186 756 : add_var(&x, &const_one, &elem);
11187 756 : div_var(result, &elem, result, local_rscale, true, false);
11188 756 : set_var_from_var(result, &xx);
11189 756 : mul_var(result, result, &x, local_rscale);
11190 :
11191 756 : ni = 1;
11192 :
11193 : for (;;)
11194 : {
11195 14022 : ni += 2;
11196 14022 : mul_var(&xx, &x, &xx, local_rscale);
11197 14022 : div_var_int(&xx, ni, 0, &elem, local_rscale, true);
11198 :
11199 14022 : if (elem.ndigits == 0)
11200 756 : break;
11201 :
11202 13266 : add_var(result, &elem, result);
11203 :
11204 13266 : if (elem.weight < (result->weight - local_rscale * 2 / DEC_DIGITS))
11205 0 : break;
11206 : }
11207 :
11208 : /* Compensate for argument range reduction, round to requested rscale */
11209 756 : mul_var(result, &fact, result, rscale);
11210 :
11211 756 : free_var(&x);
11212 756 : free_var(&xx);
11213 756 : free_var(&elem);
11214 756 : free_var(&fact);
11215 756 : }
11216 :
11217 :
11218 : /*
11219 : * log_var() -
11220 : *
11221 : * Compute the logarithm of num in a given base.
11222 : *
11223 : * Note: this routine chooses dscale of the result.
11224 : */
11225 : static void
11226 216 : log_var(const NumericVar *base, const NumericVar *num, NumericVar *result)
11227 : {
11228 : NumericVar ln_base;
11229 : NumericVar ln_num;
11230 : int ln_base_dweight;
11231 : int ln_num_dweight;
11232 : int result_dweight;
11233 : int rscale;
11234 : int ln_base_rscale;
11235 : int ln_num_rscale;
11236 :
11237 216 : init_var(&ln_base);
11238 216 : init_var(&ln_num);
11239 :
11240 : /* Estimated dweights of ln(base), ln(num) and the final result */
11241 216 : ln_base_dweight = estimate_ln_dweight(base);
11242 216 : ln_num_dweight = estimate_ln_dweight(num);
11243 216 : result_dweight = ln_num_dweight - ln_base_dweight;
11244 :
11245 : /*
11246 : * Select the scale of the result so that it will have at least
11247 : * NUMERIC_MIN_SIG_DIGITS significant digits and is not less than either
11248 : * input's display scale.
11249 : */
11250 216 : rscale = NUMERIC_MIN_SIG_DIGITS - result_dweight;
11251 216 : rscale = Max(rscale, base->dscale);
11252 216 : rscale = Max(rscale, num->dscale);
11253 216 : rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
11254 216 : rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
11255 :
11256 : /*
11257 : * Set the scales for ln(base) and ln(num) so that they each have more
11258 : * significant digits than the final result.
11259 : */
11260 216 : ln_base_rscale = rscale + result_dweight - ln_base_dweight + 8;
11261 216 : ln_base_rscale = Max(ln_base_rscale, NUMERIC_MIN_DISPLAY_SCALE);
11262 :
11263 216 : ln_num_rscale = rscale + result_dweight - ln_num_dweight + 8;
11264 216 : ln_num_rscale = Max(ln_num_rscale, NUMERIC_MIN_DISPLAY_SCALE);
11265 :
11266 : /* Form natural logarithms */
11267 216 : ln_var(base, &ln_base, ln_base_rscale);
11268 192 : ln_var(num, &ln_num, ln_num_rscale);
11269 :
11270 : /* Divide and round to the required scale */
11271 162 : div_var(&ln_num, &ln_base, result, rscale, true, false);
11272 :
11273 156 : free_var(&ln_num);
11274 156 : free_var(&ln_base);
11275 156 : }
11276 :
11277 :
11278 : /*
11279 : * power_var() -
11280 : *
11281 : * Raise base to the power of exp
11282 : *
11283 : * Note: this routine chooses dscale of the result.
11284 : */
11285 : static void
11286 1398 : power_var(const NumericVar *base, const NumericVar *exp, NumericVar *result)
11287 : {
11288 : int res_sign;
11289 : NumericVar abs_base;
11290 : NumericVar ln_base;
11291 : NumericVar ln_num;
11292 : int ln_dweight;
11293 : int rscale;
11294 : int sig_digits;
11295 : int local_rscale;
11296 : double val;
11297 :
11298 : /* If exp can be represented as an integer, use power_var_int */
11299 1398 : if (exp->ndigits == 0 || exp->ndigits <= exp->weight + 1)
11300 : {
11301 : /* exact integer, but does it fit in int? */
11302 : int64 expval64;
11303 :
11304 1272 : if (numericvar_to_int64(exp, &expval64))
11305 : {
11306 1266 : if (expval64 >= PG_INT32_MIN && expval64 <= PG_INT32_MAX)
11307 : {
11308 : /* Okay, use power_var_int */
11309 1236 : power_var_int(base, (int) expval64, exp->dscale, result);
11310 1224 : return;
11311 : }
11312 : }
11313 : }
11314 :
11315 : /*
11316 : * This avoids log(0) for cases of 0 raised to a non-integer. 0 ^ 0 is
11317 : * handled by power_var_int().
11318 : */
11319 162 : if (cmp_var(base, &const_zero) == 0)
11320 : {
11321 18 : set_var_from_var(&const_zero, result);
11322 18 : result->dscale = NUMERIC_MIN_SIG_DIGITS; /* no need to round */
11323 18 : return;
11324 : }
11325 :
11326 144 : init_var(&abs_base);
11327 144 : init_var(&ln_base);
11328 144 : init_var(&ln_num);
11329 :
11330 : /*
11331 : * If base is negative, insist that exp be an integer. The result is then
11332 : * positive if exp is even and negative if exp is odd.
11333 : */
11334 144 : if (base->sign == NUMERIC_NEG)
11335 : {
11336 : /*
11337 : * Check that exp is an integer. This error code is defined by the
11338 : * SQL standard, and matches other errors in numeric_power().
11339 : */
11340 36 : if (exp->ndigits > 0 && exp->ndigits > exp->weight + 1)
11341 18 : ereport(ERROR,
11342 : (errcode(ERRCODE_INVALID_ARGUMENT_FOR_POWER_FUNCTION),
11343 : errmsg("a negative number raised to a non-integer power yields a complex result")));
11344 :
11345 : /* Test if exp is odd or even */
11346 18 : if (exp->ndigits > 0 && exp->ndigits == exp->weight + 1 &&
11347 12 : (exp->digits[exp->ndigits - 1] & 1))
11348 6 : res_sign = NUMERIC_NEG;
11349 : else
11350 12 : res_sign = NUMERIC_POS;
11351 :
11352 : /* Then work with abs(base) below */
11353 18 : set_var_from_var(base, &abs_base);
11354 18 : abs_base.sign = NUMERIC_POS;
11355 18 : base = &abs_base;
11356 : }
11357 : else
11358 108 : res_sign = NUMERIC_POS;
11359 :
11360 : /*----------
11361 : * Decide on the scale for the ln() calculation. For this we need an
11362 : * estimate of the weight of the result, which we obtain by doing an
11363 : * initial low-precision calculation of exp * ln(base).
11364 : *
11365 : * We want result = e ^ (exp * ln(base))
11366 : * so result dweight = log10(result) = exp * ln(base) * log10(e)
11367 : *
11368 : * We also perform a crude overflow test here so that we can exit early if
11369 : * the full-precision result is sure to overflow, and to guard against
11370 : * integer overflow when determining the scale for the real calculation.
11371 : * exp_var() supports inputs up to NUMERIC_MAX_RESULT_SCALE * 3, so the
11372 : * result will overflow if exp * ln(base) >= NUMERIC_MAX_RESULT_SCALE * 3.
11373 : * Since the values here are only approximations, we apply a small fuzz
11374 : * factor to this overflow test and let exp_var() determine the exact
11375 : * overflow threshold so that it is consistent for all inputs.
11376 : *----------
11377 : */
11378 126 : ln_dweight = estimate_ln_dweight(base);
11379 :
11380 : /*
11381 : * Set the scale for the low-precision calculation, computing ln(base) to
11382 : * around 8 significant digits. Note that ln_dweight may be as small as
11383 : * -NUMERIC_DSCALE_MAX, so the scale may exceed NUMERIC_MAX_DISPLAY_SCALE
11384 : * here.
11385 : */
11386 126 : local_rscale = 8 - ln_dweight;
11387 126 : local_rscale = Max(local_rscale, NUMERIC_MIN_DISPLAY_SCALE);
11388 :
11389 126 : ln_var(base, &ln_base, local_rscale);
11390 :
11391 126 : mul_var(&ln_base, exp, &ln_num, local_rscale);
11392 :
11393 126 : val = numericvar_to_double_no_overflow(&ln_num);
11394 :
11395 : /* initial overflow/underflow test with fuzz factor */
11396 126 : if (fabs(val) > NUMERIC_MAX_RESULT_SCALE * 3.01)
11397 : {
11398 6 : if (val > 0)
11399 0 : ereport(ERROR,
11400 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
11401 : errmsg("value overflows numeric format")));
11402 6 : zero_var(result);
11403 6 : result->dscale = NUMERIC_MAX_DISPLAY_SCALE;
11404 6 : return;
11405 : }
11406 :
11407 120 : val *= 0.434294481903252; /* approximate decimal result weight */
11408 :
11409 : /* choose the result scale */
11410 120 : rscale = NUMERIC_MIN_SIG_DIGITS - (int) val;
11411 120 : rscale = Max(rscale, base->dscale);
11412 120 : rscale = Max(rscale, exp->dscale);
11413 120 : rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
11414 120 : rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
11415 :
11416 : /* significant digits required in the result */
11417 120 : sig_digits = rscale + (int) val;
11418 120 : sig_digits = Max(sig_digits, 0);
11419 :
11420 : /* set the scale for the real exp * ln(base) calculation */
11421 120 : local_rscale = sig_digits - ln_dweight + 8;
11422 120 : local_rscale = Max(local_rscale, NUMERIC_MIN_DISPLAY_SCALE);
11423 :
11424 : /* and do the real calculation */
11425 :
11426 120 : ln_var(base, &ln_base, local_rscale);
11427 :
11428 120 : mul_var(&ln_base, exp, &ln_num, local_rscale);
11429 :
11430 120 : exp_var(&ln_num, result, rscale);
11431 :
11432 120 : if (res_sign == NUMERIC_NEG && result->ndigits > 0)
11433 6 : result->sign = NUMERIC_NEG;
11434 :
11435 120 : free_var(&ln_num);
11436 120 : free_var(&ln_base);
11437 120 : free_var(&abs_base);
11438 : }
11439 :
11440 : /*
11441 : * power_var_int() -
11442 : *
11443 : * Raise base to the power of exp, where exp is an integer.
11444 : *
11445 : * Note: this routine chooses dscale of the result.
11446 : */
11447 : static void
11448 1236 : power_var_int(const NumericVar *base, int exp, int exp_dscale,
11449 : NumericVar *result)
11450 : {
11451 : double f;
11452 : int p;
11453 : int i;
11454 : int rscale;
11455 : int sig_digits;
11456 : unsigned int mask;
11457 : bool neg;
11458 : NumericVar base_prod;
11459 : int local_rscale;
11460 :
11461 : /*
11462 : * Choose the result scale. For this we need an estimate of the decimal
11463 : * weight of the result, which we obtain by approximating using double
11464 : * precision arithmetic.
11465 : *
11466 : * We also perform crude overflow/underflow tests here so that we can exit
11467 : * early if the result is sure to overflow/underflow, and to guard against
11468 : * integer overflow when choosing the result scale.
11469 : */
11470 1236 : if (base->ndigits != 0)
11471 : {
11472 : /*----------
11473 : * Choose f (double) and p (int) such that base ~= f * 10^p.
11474 : * Then log10(result) = log10(base^exp) ~= exp * (log10(f) + p).
11475 : *----------
11476 : */
11477 1206 : f = base->digits[0];
11478 1206 : p = base->weight * DEC_DIGITS;
11479 :
11480 1290 : for (i = 1; i < base->ndigits && i * DEC_DIGITS < 16; i++)
11481 : {
11482 84 : f = f * NBASE + base->digits[i];
11483 84 : p -= DEC_DIGITS;
11484 : }
11485 :
11486 1206 : f = exp * (log10(f) + p); /* approximate decimal result weight */
11487 : }
11488 : else
11489 30 : f = 0; /* result is 0 or 1 (weight 0), or error */
11490 :
11491 : /* overflow/underflow tests with fuzz factors */
11492 1236 : if (f > (NUMERIC_WEIGHT_MAX + 1) * DEC_DIGITS)
11493 12 : ereport(ERROR,
11494 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
11495 : errmsg("value overflows numeric format")));
11496 1224 : if (f + 1 < -NUMERIC_MAX_DISPLAY_SCALE)
11497 : {
11498 12 : zero_var(result);
11499 12 : result->dscale = NUMERIC_MAX_DISPLAY_SCALE;
11500 216 : return;
11501 : }
11502 :
11503 : /*
11504 : * Choose the result scale in the same way as power_var(), so it has at
11505 : * least NUMERIC_MIN_SIG_DIGITS significant digits and is not less than
11506 : * either input's display scale.
11507 : */
11508 1212 : rscale = NUMERIC_MIN_SIG_DIGITS - (int) f;
11509 1212 : rscale = Max(rscale, base->dscale);
11510 1212 : rscale = Max(rscale, exp_dscale);
11511 1212 : rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
11512 1212 : rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
11513 :
11514 : /* Handle some common special cases, as well as corner cases */
11515 1212 : switch (exp)
11516 : {
11517 72 : case 0:
11518 :
11519 : /*
11520 : * While 0 ^ 0 can be either 1 or indeterminate (error), we treat
11521 : * it as 1 because most programming languages do this. SQL:2003
11522 : * also requires a return value of 1.
11523 : * https://en.wikipedia.org/wiki/Exponentiation#Zero_to_the_zero_power
11524 : */
11525 72 : set_var_from_var(&const_one, result);
11526 72 : result->dscale = rscale; /* no need to round */
11527 72 : return;
11528 48 : case 1:
11529 48 : set_var_from_var(base, result);
11530 48 : round_var(result, rscale);
11531 48 : return;
11532 30 : case -1:
11533 30 : div_var(&const_one, base, result, rscale, true, true);
11534 30 : return;
11535 54 : case 2:
11536 54 : mul_var(base, base, result, rscale);
11537 54 : return;
11538 1008 : default:
11539 1008 : break;
11540 : }
11541 :
11542 : /* Handle the special case where the base is zero */
11543 1008 : if (base->ndigits == 0)
11544 : {
11545 0 : if (exp < 0)
11546 0 : ereport(ERROR,
11547 : (errcode(ERRCODE_DIVISION_BY_ZERO),
11548 : errmsg("division by zero")));
11549 0 : zero_var(result);
11550 0 : result->dscale = rscale;
11551 0 : return;
11552 : }
11553 :
11554 : /*
11555 : * The general case repeatedly multiplies base according to the bit
11556 : * pattern of exp.
11557 : *
11558 : * The local rscale used for each multiplication is varied to keep a fixed
11559 : * number of significant digits, sufficient to give the required result
11560 : * scale.
11561 : */
11562 :
11563 : /*
11564 : * Approximate number of significant digits in the result. Note that the
11565 : * underflow test above, together with the choice of rscale, ensures that
11566 : * this approximation is necessarily > 0.
11567 : */
11568 1008 : sig_digits = 1 + rscale + (int) f;
11569 :
11570 : /*
11571 : * The multiplications to produce the result may introduce an error of up
11572 : * to around log10(abs(exp)) digits, so work with this many extra digits
11573 : * of precision (plus a few more for good measure).
11574 : */
11575 1008 : sig_digits += (int) log(fabs((double) exp)) + 8;
11576 :
11577 : /*
11578 : * Now we can proceed with the multiplications.
11579 : */
11580 1008 : neg = (exp < 0);
11581 1008 : mask = pg_abs_s32(exp);
11582 :
11583 1008 : init_var(&base_prod);
11584 1008 : set_var_from_var(base, &base_prod);
11585 :
11586 1008 : if (mask & 1)
11587 498 : set_var_from_var(base, result);
11588 : else
11589 510 : set_var_from_var(&const_one, result);
11590 :
11591 5076 : while ((mask >>= 1) > 0)
11592 : {
11593 : /*
11594 : * Do the multiplications using rscales large enough to hold the
11595 : * results to the required number of significant digits, but don't
11596 : * waste time by exceeding the scales of the numbers themselves.
11597 : */
11598 4068 : local_rscale = sig_digits - 2 * base_prod.weight * DEC_DIGITS;
11599 4068 : local_rscale = Min(local_rscale, 2 * base_prod.dscale);
11600 4068 : local_rscale = Max(local_rscale, NUMERIC_MIN_DISPLAY_SCALE);
11601 :
11602 4068 : mul_var(&base_prod, &base_prod, &base_prod, local_rscale);
11603 :
11604 4068 : if (mask & 1)
11605 : {
11606 2658 : local_rscale = sig_digits -
11607 2658 : (base_prod.weight + result->weight) * DEC_DIGITS;
11608 2658 : local_rscale = Min(local_rscale,
11609 : base_prod.dscale + result->dscale);
11610 2658 : local_rscale = Max(local_rscale, NUMERIC_MIN_DISPLAY_SCALE);
11611 :
11612 2658 : mul_var(&base_prod, result, result, local_rscale);
11613 : }
11614 :
11615 : /*
11616 : * When abs(base) > 1, the number of digits to the left of the decimal
11617 : * point in base_prod doubles at each iteration, so if exp is large we
11618 : * could easily spend large amounts of time and memory space doing the
11619 : * multiplications. But once the weight exceeds what will fit in
11620 : * int16, the final result is guaranteed to overflow (or underflow, if
11621 : * exp < 0), so we can give up before wasting too many cycles.
11622 : */
11623 4068 : if (base_prod.weight > NUMERIC_WEIGHT_MAX ||
11624 4068 : result->weight > NUMERIC_WEIGHT_MAX)
11625 : {
11626 : /* overflow, unless neg, in which case result should be 0 */
11627 0 : if (!neg)
11628 0 : ereport(ERROR,
11629 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
11630 : errmsg("value overflows numeric format")));
11631 0 : zero_var(result);
11632 0 : neg = false;
11633 0 : break;
11634 : }
11635 : }
11636 :
11637 1008 : free_var(&base_prod);
11638 :
11639 : /* Compensate for input sign, and round to requested rscale */
11640 1008 : if (neg)
11641 486 : div_var(&const_one, result, result, rscale, true, false);
11642 : else
11643 522 : round_var(result, rscale);
11644 : }
11645 :
11646 : /*
11647 : * power_ten_int() -
11648 : *
11649 : * Raise ten to the power of exp, where exp is an integer. Note that unlike
11650 : * power_var_int(), this does no overflow/underflow checking or rounding.
11651 : */
11652 : static void
11653 228 : power_ten_int(int exp, NumericVar *result)
11654 : {
11655 : /* Construct the result directly, starting from 10^0 = 1 */
11656 228 : set_var_from_var(&const_one, result);
11657 :
11658 : /* Scale needed to represent the result exactly */
11659 228 : result->dscale = exp < 0 ? -exp : 0;
11660 :
11661 : /* Base-NBASE weight of result and remaining exponent */
11662 228 : if (exp >= 0)
11663 162 : result->weight = exp / DEC_DIGITS;
11664 : else
11665 66 : result->weight = (exp + 1) / DEC_DIGITS - 1;
11666 :
11667 228 : exp -= result->weight * DEC_DIGITS;
11668 :
11669 : /* Final adjustment of the result's single NBASE digit */
11670 594 : while (exp-- > 0)
11671 366 : result->digits[0] *= 10;
11672 228 : }
11673 :
11674 : /*
11675 : * random_var() - return a random value in the range [rmin, rmax].
11676 : */
11677 : static void
11678 33438 : random_var(pg_prng_state *state, const NumericVar *rmin,
11679 : const NumericVar *rmax, NumericVar *result)
11680 : {
11681 : int rscale;
11682 : NumericVar rlen;
11683 : int res_ndigits;
11684 : int n;
11685 : int pow10;
11686 : int i;
11687 : uint64 rlen64;
11688 : int rlen64_ndigits;
11689 :
11690 33438 : rscale = Max(rmin->dscale, rmax->dscale);
11691 :
11692 : /* Compute rlen = rmax - rmin and check the range bounds */
11693 33438 : init_var(&rlen);
11694 33438 : sub_var(rmax, rmin, &rlen);
11695 :
11696 33438 : if (rlen.sign == NUMERIC_NEG)
11697 6 : ereport(ERROR,
11698 : errcode(ERRCODE_INVALID_PARAMETER_VALUE),
11699 : errmsg("lower bound must be less than or equal to upper bound"));
11700 :
11701 : /* Special case for an empty range */
11702 33432 : if (rlen.ndigits == 0)
11703 : {
11704 12 : set_var_from_var(rmin, result);
11705 12 : result->dscale = rscale;
11706 12 : free_var(&rlen);
11707 12 : return;
11708 : }
11709 :
11710 : /*
11711 : * Otherwise, select a random value in the range [0, rlen = rmax - rmin],
11712 : * and shift it to the required range by adding rmin.
11713 : */
11714 :
11715 : /* Required result digits */
11716 33420 : res_ndigits = rlen.weight + 1 + (rscale + DEC_DIGITS - 1) / DEC_DIGITS;
11717 :
11718 : /*
11719 : * To get the required rscale, the final result digit must be a multiple
11720 : * of pow10 = 10^n, where n = (-rscale) mod DEC_DIGITS.
11721 : */
11722 33420 : n = ((rscale + DEC_DIGITS - 1) / DEC_DIGITS) * DEC_DIGITS - rscale;
11723 33420 : pow10 = 1;
11724 87900 : for (i = 0; i < n; i++)
11725 54480 : pow10 *= 10;
11726 :
11727 : /*
11728 : * To choose a random value uniformly from the range [0, rlen], we choose
11729 : * from the slightly larger range [0, rlen2], where rlen2 is formed from
11730 : * rlen by copying the first 4 NBASE digits, and setting all remaining
11731 : * decimal digits to "9".
11732 : *
11733 : * Without loss of generality, we can ignore the weight of rlen2 and treat
11734 : * it as a pure integer for the purposes of this discussion. The process
11735 : * above gives rlen2 + 1 = rlen64 * 10^N, for some integer N, where rlen64
11736 : * is a 64-bit integer formed from the first 4 NBASE digits copied from
11737 : * rlen. Since this trivially factors into smaller pieces that fit in
11738 : * 64-bit integers, the task of choosing a random value uniformly from the
11739 : * rlen2 + 1 possible values in [0, rlen2] is much simpler.
11740 : *
11741 : * If the random value selected is too large, it is rejected, and we try
11742 : * again until we get a result <= rlen, ensuring that the overall result
11743 : * is uniform (no particular value is any more likely than any other).
11744 : *
11745 : * Since rlen64 holds 4 NBASE digits from rlen, it contains at least
11746 : * DEC_DIGITS * 3 + 1 decimal digits (i.e., at least 13 decimal digits,
11747 : * when DEC_DIGITS is 4). Therefore the probability of needing to reject
11748 : * the value chosen and retry is less than 1e-13.
11749 : */
11750 33420 : rlen64 = (uint64) rlen.digits[0];
11751 33420 : rlen64_ndigits = 1;
11752 76212 : while (rlen64_ndigits < res_ndigits && rlen64_ndigits < 4)
11753 : {
11754 42792 : rlen64 *= NBASE;
11755 42792 : if (rlen64_ndigits < rlen.ndigits)
11756 6612 : rlen64 += rlen.digits[rlen64_ndigits];
11757 42792 : rlen64_ndigits++;
11758 : }
11759 :
11760 : /* Loop until we get a result <= rlen */
11761 : do
11762 : {
11763 : NumericDigit *res_digits;
11764 : uint64 rand;
11765 : int whole_ndigits;
11766 :
11767 33420 : alloc_var(result, res_ndigits);
11768 33420 : result->sign = NUMERIC_POS;
11769 33420 : result->weight = rlen.weight;
11770 33420 : result->dscale = rscale;
11771 33420 : res_digits = result->digits;
11772 :
11773 : /*
11774 : * Set the first rlen64_ndigits using a random value in [0, rlen64].
11775 : *
11776 : * If this is the whole result, and rscale is not a multiple of
11777 : * DEC_DIGITS (pow10 from above is not 1), then we need this to be a
11778 : * multiple of pow10.
11779 : */
11780 33420 : if (rlen64_ndigits == res_ndigits && pow10 != 1)
11781 21132 : rand = pg_prng_uint64_range(state, 0, rlen64 / pow10) * pow10;
11782 : else
11783 12288 : rand = pg_prng_uint64_range(state, 0, rlen64);
11784 :
11785 109632 : for (i = rlen64_ndigits - 1; i >= 0; i--)
11786 : {
11787 76212 : res_digits[i] = (NumericDigit) (rand % NBASE);
11788 76212 : rand = rand / NBASE;
11789 : }
11790 :
11791 : /*
11792 : * Set the remaining digits to random values in range [0, NBASE),
11793 : * noting that the last digit needs to be a multiple of pow10.
11794 : */
11795 33420 : whole_ndigits = res_ndigits;
11796 33420 : if (pow10 != 1)
11797 33210 : whole_ndigits--;
11798 :
11799 : /* Set whole digits in groups of 4 for best performance */
11800 33420 : i = rlen64_ndigits;
11801 33480 : while (i < whole_ndigits - 3)
11802 : {
11803 60 : rand = pg_prng_uint64_range(state, 0,
11804 : (uint64) NBASE * NBASE * NBASE * NBASE - 1);
11805 60 : res_digits[i++] = (NumericDigit) (rand % NBASE);
11806 60 : rand = rand / NBASE;
11807 60 : res_digits[i++] = (NumericDigit) (rand % NBASE);
11808 60 : rand = rand / NBASE;
11809 60 : res_digits[i++] = (NumericDigit) (rand % NBASE);
11810 60 : rand = rand / NBASE;
11811 60 : res_digits[i++] = (NumericDigit) rand;
11812 : }
11813 :
11814 : /* Remaining whole digits */
11815 33630 : while (i < whole_ndigits)
11816 : {
11817 210 : rand = pg_prng_uint64_range(state, 0, NBASE - 1);
11818 210 : res_digits[i++] = (NumericDigit) rand;
11819 : }
11820 :
11821 : /* Final partial digit (multiple of pow10) */
11822 33420 : if (i < res_ndigits)
11823 : {
11824 12078 : rand = pg_prng_uint64_range(state, 0, NBASE / pow10 - 1) * pow10;
11825 12078 : res_digits[i] = (NumericDigit) rand;
11826 : }
11827 :
11828 : /* Remove leading/trailing zeroes */
11829 33420 : strip_var(result);
11830 :
11831 : /* If result > rlen, try again */
11832 :
11833 33420 : } while (cmp_var(result, &rlen) > 0);
11834 :
11835 : /* Offset the result to the required range */
11836 33420 : add_var(result, rmin, result);
11837 :
11838 33420 : free_var(&rlen);
11839 : }
11840 :
11841 :
11842 : /* ----------------------------------------------------------------------
11843 : *
11844 : * Following are the lowest level functions that operate unsigned
11845 : * on the variable level
11846 : *
11847 : * ----------------------------------------------------------------------
11848 : */
11849 :
11850 :
11851 : /* ----------
11852 : * cmp_abs() -
11853 : *
11854 : * Compare the absolute values of var1 and var2
11855 : * Returns: -1 for ABS(var1) < ABS(var2)
11856 : * 0 for ABS(var1) == ABS(var2)
11857 : * 1 for ABS(var1) > ABS(var2)
11858 : * ----------
11859 : */
11860 : static int
11861 709874 : cmp_abs(const NumericVar *var1, const NumericVar *var2)
11862 : {
11863 1419748 : return cmp_abs_common(var1->digits, var1->ndigits, var1->weight,
11864 709874 : var2->digits, var2->ndigits, var2->weight);
11865 : }
11866 :
11867 : /* ----------
11868 : * cmp_abs_common() -
11869 : *
11870 : * Main routine of cmp_abs(). This function can be used by both
11871 : * NumericVar and Numeric.
11872 : * ----------
11873 : */
11874 : static int
11875 19623988 : cmp_abs_common(const NumericDigit *var1digits, int var1ndigits, int var1weight,
11876 : const NumericDigit *var2digits, int var2ndigits, int var2weight)
11877 : {
11878 19623988 : int i1 = 0;
11879 19623988 : int i2 = 0;
11880 :
11881 : /* Check any digits before the first common digit */
11882 :
11883 19623988 : while (var1weight > var2weight && i1 < var1ndigits)
11884 : {
11885 26072 : if (var1digits[i1++] != 0)
11886 26072 : return 1;
11887 0 : var1weight--;
11888 : }
11889 19597916 : while (var2weight > var1weight && i2 < var2ndigits)
11890 : {
11891 150948 : if (var2digits[i2++] != 0)
11892 150948 : return -1;
11893 0 : var2weight--;
11894 : }
11895 :
11896 : /* At this point, either w1 == w2 or we've run out of digits */
11897 :
11898 19446968 : if (var1weight == var2weight)
11899 : {
11900 31639184 : while (i1 < var1ndigits && i2 < var2ndigits)
11901 : {
11902 21011924 : int stat = var1digits[i1++] - var2digits[i2++];
11903 :
11904 21011924 : if (stat)
11905 : {
11906 8813358 : if (stat > 0)
11907 5298868 : return 1;
11908 3514490 : return -1;
11909 : }
11910 : }
11911 : }
11912 :
11913 : /*
11914 : * At this point, we've run out of digits on one side or the other; so any
11915 : * remaining nonzero digits imply that side is larger
11916 : */
11917 10633946 : while (i1 < var1ndigits)
11918 : {
11919 9506 : if (var1digits[i1++] != 0)
11920 9170 : return 1;
11921 : }
11922 10624764 : while (i2 < var2ndigits)
11923 : {
11924 1200 : if (var2digits[i2++] != 0)
11925 876 : return -1;
11926 : }
11927 :
11928 10623564 : return 0;
11929 : }
11930 :
11931 :
11932 : /*
11933 : * add_abs() -
11934 : *
11935 : * Add the absolute values of two variables into result.
11936 : * result might point to one of the operands without danger.
11937 : */
11938 : static void
11939 446060 : add_abs(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
11940 : {
11941 : NumericDigit *res_buf;
11942 : NumericDigit *res_digits;
11943 : int res_ndigits;
11944 : int res_weight;
11945 : int res_rscale,
11946 : rscale1,
11947 : rscale2;
11948 : int res_dscale;
11949 : int i,
11950 : i1,
11951 : i2;
11952 446060 : int carry = 0;
11953 :
11954 : /* copy these values into local vars for speed in inner loop */
11955 446060 : int var1ndigits = var1->ndigits;
11956 446060 : int var2ndigits = var2->ndigits;
11957 446060 : NumericDigit *var1digits = var1->digits;
11958 446060 : NumericDigit *var2digits = var2->digits;
11959 :
11960 446060 : res_weight = Max(var1->weight, var2->weight) + 1;
11961 :
11962 446060 : res_dscale = Max(var1->dscale, var2->dscale);
11963 :
11964 : /* Note: here we are figuring rscale in base-NBASE digits */
11965 446060 : rscale1 = var1->ndigits - var1->weight - 1;
11966 446060 : rscale2 = var2->ndigits - var2->weight - 1;
11967 446060 : res_rscale = Max(rscale1, rscale2);
11968 :
11969 446060 : res_ndigits = res_rscale + res_weight + 1;
11970 446060 : if (res_ndigits <= 0)
11971 0 : res_ndigits = 1;
11972 :
11973 446060 : res_buf = digitbuf_alloc(res_ndigits + 1);
11974 446060 : res_buf[0] = 0; /* spare digit for later rounding */
11975 446060 : res_digits = res_buf + 1;
11976 :
11977 446060 : i1 = res_rscale + var1->weight + 1;
11978 446060 : i2 = res_rscale + var2->weight + 1;
11979 3638090 : for (i = res_ndigits - 1; i >= 0; i--)
11980 : {
11981 3192030 : i1--;
11982 3192030 : i2--;
11983 3192030 : if (i1 >= 0 && i1 < var1ndigits)
11984 1416400 : carry += var1digits[i1];
11985 3192030 : if (i2 >= 0 && i2 < var2ndigits)
11986 1135906 : carry += var2digits[i2];
11987 :
11988 3192030 : if (carry >= NBASE)
11989 : {
11990 225828 : res_digits[i] = carry - NBASE;
11991 225828 : carry = 1;
11992 : }
11993 : else
11994 : {
11995 2966202 : res_digits[i] = carry;
11996 2966202 : carry = 0;
11997 : }
11998 : }
11999 :
12000 : Assert(carry == 0); /* else we failed to allow for carry out */
12001 :
12002 446060 : digitbuf_free(result->buf);
12003 446060 : result->ndigits = res_ndigits;
12004 446060 : result->buf = res_buf;
12005 446060 : result->digits = res_digits;
12006 446060 : result->weight = res_weight;
12007 446060 : result->dscale = res_dscale;
12008 :
12009 : /* Remove leading/trailing zeroes */
12010 446060 : strip_var(result);
12011 446060 : }
12012 :
12013 :
12014 : /*
12015 : * sub_abs()
12016 : *
12017 : * Subtract the absolute value of var2 from the absolute value of var1
12018 : * and store in result. result might point to one of the operands
12019 : * without danger.
12020 : *
12021 : * ABS(var1) MUST BE GREATER OR EQUAL ABS(var2) !!!
12022 : */
12023 : static void
12024 655598 : sub_abs(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
12025 : {
12026 : NumericDigit *res_buf;
12027 : NumericDigit *res_digits;
12028 : int res_ndigits;
12029 : int res_weight;
12030 : int res_rscale,
12031 : rscale1,
12032 : rscale2;
12033 : int res_dscale;
12034 : int i,
12035 : i1,
12036 : i2;
12037 655598 : int borrow = 0;
12038 :
12039 : /* copy these values into local vars for speed in inner loop */
12040 655598 : int var1ndigits = var1->ndigits;
12041 655598 : int var2ndigits = var2->ndigits;
12042 655598 : NumericDigit *var1digits = var1->digits;
12043 655598 : NumericDigit *var2digits = var2->digits;
12044 :
12045 655598 : res_weight = var1->weight;
12046 :
12047 655598 : res_dscale = Max(var1->dscale, var2->dscale);
12048 :
12049 : /* Note: here we are figuring rscale in base-NBASE digits */
12050 655598 : rscale1 = var1->ndigits - var1->weight - 1;
12051 655598 : rscale2 = var2->ndigits - var2->weight - 1;
12052 655598 : res_rscale = Max(rscale1, rscale2);
12053 :
12054 655598 : res_ndigits = res_rscale + res_weight + 1;
12055 655598 : if (res_ndigits <= 0)
12056 0 : res_ndigits = 1;
12057 :
12058 655598 : res_buf = digitbuf_alloc(res_ndigits + 1);
12059 655598 : res_buf[0] = 0; /* spare digit for later rounding */
12060 655598 : res_digits = res_buf + 1;
12061 :
12062 655598 : i1 = res_rscale + var1->weight + 1;
12063 655598 : i2 = res_rscale + var2->weight + 1;
12064 5190432 : for (i = res_ndigits - 1; i >= 0; i--)
12065 : {
12066 4534834 : i1--;
12067 4534834 : i2--;
12068 4534834 : if (i1 >= 0 && i1 < var1ndigits)
12069 4105860 : borrow += var1digits[i1];
12070 4534834 : if (i2 >= 0 && i2 < var2ndigits)
12071 4040924 : borrow -= var2digits[i2];
12072 :
12073 4534834 : if (borrow < 0)
12074 : {
12075 462378 : res_digits[i] = borrow + NBASE;
12076 462378 : borrow = -1;
12077 : }
12078 : else
12079 : {
12080 4072456 : res_digits[i] = borrow;
12081 4072456 : borrow = 0;
12082 : }
12083 : }
12084 :
12085 : Assert(borrow == 0); /* else caller gave us var1 < var2 */
12086 :
12087 655598 : digitbuf_free(result->buf);
12088 655598 : result->ndigits = res_ndigits;
12089 655598 : result->buf = res_buf;
12090 655598 : result->digits = res_digits;
12091 655598 : result->weight = res_weight;
12092 655598 : result->dscale = res_dscale;
12093 :
12094 : /* Remove leading/trailing zeroes */
12095 655598 : strip_var(result);
12096 655598 : }
12097 :
12098 : /*
12099 : * round_var
12100 : *
12101 : * Round the value of a variable to no more than rscale decimal digits
12102 : * after the decimal point. NOTE: we allow rscale < 0 here, implying
12103 : * rounding before the decimal point.
12104 : */
12105 : static void
12106 249790 : round_var(NumericVar *var, int rscale)
12107 : {
12108 249790 : NumericDigit *digits = var->digits;
12109 : int di;
12110 : int ndigits;
12111 : int carry;
12112 :
12113 249790 : var->dscale = rscale;
12114 :
12115 : /* decimal digits wanted */
12116 249790 : di = (var->weight + 1) * DEC_DIGITS + rscale;
12117 :
12118 : /*
12119 : * If di = 0, the value loses all digits, but could round up to 1 if its
12120 : * first extra digit is >= 5. If di < 0 the result must be 0.
12121 : */
12122 249790 : if (di < 0)
12123 : {
12124 106 : var->ndigits = 0;
12125 106 : var->weight = 0;
12126 106 : var->sign = NUMERIC_POS;
12127 : }
12128 : else
12129 : {
12130 : /* NBASE digits wanted */
12131 249684 : ndigits = (di + DEC_DIGITS - 1) / DEC_DIGITS;
12132 :
12133 : /* 0, or number of decimal digits to keep in last NBASE digit */
12134 249684 : di %= DEC_DIGITS;
12135 :
12136 249684 : if (ndigits < var->ndigits ||
12137 46892 : (ndigits == var->ndigits && di > 0))
12138 : {
12139 206634 : var->ndigits = ndigits;
12140 :
12141 : #if DEC_DIGITS == 1
12142 : /* di must be zero */
12143 : carry = (digits[ndigits] >= HALF_NBASE) ? 1 : 0;
12144 : #else
12145 206634 : if (di == 0)
12146 164370 : carry = (digits[ndigits] >= HALF_NBASE) ? 1 : 0;
12147 : else
12148 : {
12149 : /* Must round within last NBASE digit */
12150 : int extra,
12151 : pow10;
12152 :
12153 : #if DEC_DIGITS == 4
12154 42264 : pow10 = round_powers[di];
12155 : #elif DEC_DIGITS == 2
12156 : pow10 = 10;
12157 : #else
12158 : #error unsupported NBASE
12159 : #endif
12160 42264 : extra = digits[--ndigits] % pow10;
12161 42264 : digits[ndigits] -= extra;
12162 42264 : carry = 0;
12163 42264 : if (extra >= pow10 / 2)
12164 : {
12165 19448 : pow10 += digits[ndigits];
12166 19448 : if (pow10 >= NBASE)
12167 : {
12168 812 : pow10 -= NBASE;
12169 812 : carry = 1;
12170 : }
12171 19448 : digits[ndigits] = pow10;
12172 : }
12173 : }
12174 : #endif
12175 :
12176 : /* Propagate carry if needed */
12177 240256 : while (carry)
12178 : {
12179 33622 : carry += digits[--ndigits];
12180 33622 : if (carry >= NBASE)
12181 : {
12182 24626 : digits[ndigits] = carry - NBASE;
12183 24626 : carry = 1;
12184 : }
12185 : else
12186 : {
12187 8996 : digits[ndigits] = carry;
12188 8996 : carry = 0;
12189 : }
12190 : }
12191 :
12192 206634 : if (ndigits < 0)
12193 : {
12194 : Assert(ndigits == -1); /* better not have added > 1 digit */
12195 : Assert(var->digits > var->buf);
12196 96 : var->digits--;
12197 96 : var->ndigits++;
12198 96 : var->weight++;
12199 : }
12200 : }
12201 : }
12202 249790 : }
12203 :
12204 : /*
12205 : * trunc_var
12206 : *
12207 : * Truncate (towards zero) the value of a variable at rscale decimal digits
12208 : * after the decimal point. NOTE: we allow rscale < 0 here, implying
12209 : * truncation before the decimal point.
12210 : */
12211 : static void
12212 420896 : trunc_var(NumericVar *var, int rscale)
12213 : {
12214 : int di;
12215 : int ndigits;
12216 :
12217 420896 : var->dscale = rscale;
12218 :
12219 : /* decimal digits wanted */
12220 420896 : di = (var->weight + 1) * DEC_DIGITS + rscale;
12221 :
12222 : /*
12223 : * If di <= 0, the value loses all digits.
12224 : */
12225 420896 : if (di <= 0)
12226 : {
12227 90 : var->ndigits = 0;
12228 90 : var->weight = 0;
12229 90 : var->sign = NUMERIC_POS;
12230 : }
12231 : else
12232 : {
12233 : /* NBASE digits wanted */
12234 420806 : ndigits = (di + DEC_DIGITS - 1) / DEC_DIGITS;
12235 :
12236 420806 : if (ndigits <= var->ndigits)
12237 : {
12238 420536 : var->ndigits = ndigits;
12239 :
12240 : #if DEC_DIGITS == 1
12241 : /* no within-digit stuff to worry about */
12242 : #else
12243 : /* 0, or number of decimal digits to keep in last NBASE digit */
12244 420536 : di %= DEC_DIGITS;
12245 :
12246 420536 : if (di > 0)
12247 : {
12248 : /* Must truncate within last NBASE digit */
12249 106 : NumericDigit *digits = var->digits;
12250 : int extra,
12251 : pow10;
12252 :
12253 : #if DEC_DIGITS == 4
12254 106 : pow10 = round_powers[di];
12255 : #elif DEC_DIGITS == 2
12256 : pow10 = 10;
12257 : #else
12258 : #error unsupported NBASE
12259 : #endif
12260 106 : extra = digits[--ndigits] % pow10;
12261 106 : digits[ndigits] -= extra;
12262 : }
12263 : #endif
12264 : }
12265 : }
12266 420896 : }
12267 :
12268 : /*
12269 : * strip_var
12270 : *
12271 : * Strip any leading and trailing zeroes from a numeric variable
12272 : */
12273 : static void
12274 3335140 : strip_var(NumericVar *var)
12275 : {
12276 3335140 : NumericDigit *digits = var->digits;
12277 3335140 : int ndigits = var->ndigits;
12278 :
12279 : /* Strip leading zeroes */
12280 5719216 : while (ndigits > 0 && *digits == 0)
12281 : {
12282 2384076 : digits++;
12283 2384076 : var->weight--;
12284 2384076 : ndigits--;
12285 : }
12286 :
12287 : /* Strip trailing zeroes */
12288 4129652 : while (ndigits > 0 && digits[ndigits - 1] == 0)
12289 794512 : ndigits--;
12290 :
12291 : /* If it's zero, normalize the sign and weight */
12292 3335140 : if (ndigits == 0)
12293 : {
12294 56344 : var->sign = NUMERIC_POS;
12295 56344 : var->weight = 0;
12296 : }
12297 :
12298 3335140 : var->digits = digits;
12299 3335140 : var->ndigits = ndigits;
12300 3335140 : }
12301 :
12302 :
12303 : /* ----------------------------------------------------------------------
12304 : *
12305 : * Fast sum accumulator functions
12306 : *
12307 : * ----------------------------------------------------------------------
12308 : */
12309 :
12310 : /*
12311 : * Reset the accumulator's value to zero. The buffers to hold the digits
12312 : * are not free'd.
12313 : */
12314 : static void
12315 18 : accum_sum_reset(NumericSumAccum *accum)
12316 : {
12317 : int i;
12318 :
12319 18 : accum->dscale = 0;
12320 66 : for (i = 0; i < accum->ndigits; i++)
12321 : {
12322 48 : accum->pos_digits[i] = 0;
12323 48 : accum->neg_digits[i] = 0;
12324 : }
12325 18 : }
12326 :
12327 : /*
12328 : * Accumulate a new value.
12329 : */
12330 : static void
12331 2355770 : accum_sum_add(NumericSumAccum *accum, const NumericVar *val)
12332 : {
12333 : int32 *accum_digits;
12334 : int i,
12335 : val_i;
12336 : int val_ndigits;
12337 : NumericDigit *val_digits;
12338 :
12339 : /*
12340 : * If we have accumulated too many values since the last carry
12341 : * propagation, do it now, to avoid overflowing. (We could allow more
12342 : * than NBASE - 1, if we reserved two extra digits, rather than one, for
12343 : * carry propagation. But even with NBASE - 1, this needs to be done so
12344 : * seldom, that the performance difference is negligible.)
12345 : */
12346 2355770 : if (accum->num_uncarried == NBASE - 1)
12347 156 : accum_sum_carry(accum);
12348 :
12349 : /*
12350 : * Adjust the weight or scale of the old value, so that it can accommodate
12351 : * the new value.
12352 : */
12353 2355770 : accum_sum_rescale(accum, val);
12354 :
12355 : /* */
12356 2355770 : if (val->sign == NUMERIC_POS)
12357 1755092 : accum_digits = accum->pos_digits;
12358 : else
12359 600678 : accum_digits = accum->neg_digits;
12360 :
12361 : /* copy these values into local vars for speed in loop */
12362 2355770 : val_ndigits = val->ndigits;
12363 2355770 : val_digits = val->digits;
12364 :
12365 2355770 : i = accum->weight - val->weight;
12366 11890082 : for (val_i = 0; val_i < val_ndigits; val_i++)
12367 : {
12368 9534312 : accum_digits[i] += (int32) val_digits[val_i];
12369 9534312 : i++;
12370 : }
12371 :
12372 2355770 : accum->num_uncarried++;
12373 2355770 : }
12374 :
12375 : /*
12376 : * Propagate carries.
12377 : */
12378 : static void
12379 172794 : accum_sum_carry(NumericSumAccum *accum)
12380 : {
12381 : int i;
12382 : int ndigits;
12383 : int32 *dig;
12384 : int32 carry;
12385 172794 : int32 newdig = 0;
12386 :
12387 : /*
12388 : * If no new values have been added since last carry propagation, nothing
12389 : * to do.
12390 : */
12391 172794 : if (accum->num_uncarried == 0)
12392 72 : return;
12393 :
12394 : /*
12395 : * We maintain that the weight of the accumulator is always one larger
12396 : * than needed to hold the current value, before carrying, to make sure
12397 : * there is enough space for the possible extra digit when carry is
12398 : * propagated. We cannot expand the buffer here, unless we require
12399 : * callers of accum_sum_final() to switch to the right memory context.
12400 : */
12401 : Assert(accum->pos_digits[0] == 0 && accum->neg_digits[0] == 0);
12402 :
12403 172722 : ndigits = accum->ndigits;
12404 :
12405 : /* Propagate carry in the positive sum */
12406 172722 : dig = accum->pos_digits;
12407 172722 : carry = 0;
12408 2605642 : for (i = ndigits - 1; i >= 0; i--)
12409 : {
12410 2432920 : newdig = dig[i] + carry;
12411 2432920 : if (newdig >= NBASE)
12412 : {
12413 110814 : carry = newdig / NBASE;
12414 110814 : newdig -= carry * NBASE;
12415 : }
12416 : else
12417 2322106 : carry = 0;
12418 2432920 : dig[i] = newdig;
12419 : }
12420 : /* Did we use up the digit reserved for carry propagation? */
12421 172722 : if (newdig > 0)
12422 2640 : accum->have_carry_space = false;
12423 :
12424 : /* And the same for the negative sum */
12425 172722 : dig = accum->neg_digits;
12426 172722 : carry = 0;
12427 2605642 : for (i = ndigits - 1; i >= 0; i--)
12428 : {
12429 2432920 : newdig = dig[i] + carry;
12430 2432920 : if (newdig >= NBASE)
12431 : {
12432 198 : carry = newdig / NBASE;
12433 198 : newdig -= carry * NBASE;
12434 : }
12435 : else
12436 2432722 : carry = 0;
12437 2432920 : dig[i] = newdig;
12438 : }
12439 172722 : if (newdig > 0)
12440 30 : accum->have_carry_space = false;
12441 :
12442 172722 : accum->num_uncarried = 0;
12443 : }
12444 :
12445 : /*
12446 : * Re-scale accumulator to accommodate new value.
12447 : *
12448 : * If the new value has more digits than the current digit buffers in the
12449 : * accumulator, enlarge the buffers.
12450 : */
12451 : static void
12452 2355770 : accum_sum_rescale(NumericSumAccum *accum, const NumericVar *val)
12453 : {
12454 2355770 : int old_weight = accum->weight;
12455 2355770 : int old_ndigits = accum->ndigits;
12456 : int accum_ndigits;
12457 : int accum_weight;
12458 : int accum_rscale;
12459 : int val_rscale;
12460 :
12461 2355770 : accum_weight = old_weight;
12462 2355770 : accum_ndigits = old_ndigits;
12463 :
12464 : /*
12465 : * Does the new value have a larger weight? If so, enlarge the buffers,
12466 : * and shift the existing value to the new weight, by adding leading
12467 : * zeros.
12468 : *
12469 : * We enforce that the accumulator always has a weight one larger than
12470 : * needed for the inputs, so that we have space for an extra digit at the
12471 : * final carry-propagation phase, if necessary.
12472 : */
12473 2355770 : if (val->weight >= accum_weight)
12474 : {
12475 262260 : accum_weight = val->weight + 1;
12476 262260 : accum_ndigits = accum_ndigits + (accum_weight - old_weight);
12477 : }
12478 :
12479 : /*
12480 : * Even though the new value is small, we might've used up the space
12481 : * reserved for the carry digit in the last call to accum_sum_carry(). If
12482 : * so, enlarge to make room for another one.
12483 : */
12484 2093510 : else if (!accum->have_carry_space)
12485 : {
12486 84 : accum_weight++;
12487 84 : accum_ndigits++;
12488 : }
12489 :
12490 : /* Is the new value wider on the right side? */
12491 2355770 : accum_rscale = accum_ndigits - accum_weight - 1;
12492 2355770 : val_rscale = val->ndigits - val->weight - 1;
12493 2355770 : if (val_rscale > accum_rscale)
12494 172282 : accum_ndigits = accum_ndigits + (val_rscale - accum_rscale);
12495 :
12496 2355770 : if (accum_ndigits != old_ndigits ||
12497 : accum_weight != old_weight)
12498 : {
12499 : int32 *new_pos_digits;
12500 : int32 *new_neg_digits;
12501 : int weightdiff;
12502 :
12503 262616 : weightdiff = accum_weight - old_weight;
12504 :
12505 262616 : new_pos_digits = palloc0(accum_ndigits * sizeof(int32));
12506 262616 : new_neg_digits = palloc0(accum_ndigits * sizeof(int32));
12507 :
12508 262616 : if (accum->pos_digits)
12509 : {
12510 90404 : memcpy(&new_pos_digits[weightdiff], accum->pos_digits,
12511 : old_ndigits * sizeof(int32));
12512 90404 : pfree(accum->pos_digits);
12513 :
12514 90404 : memcpy(&new_neg_digits[weightdiff], accum->neg_digits,
12515 : old_ndigits * sizeof(int32));
12516 90404 : pfree(accum->neg_digits);
12517 : }
12518 :
12519 262616 : accum->pos_digits = new_pos_digits;
12520 262616 : accum->neg_digits = new_neg_digits;
12521 :
12522 262616 : accum->weight = accum_weight;
12523 262616 : accum->ndigits = accum_ndigits;
12524 :
12525 : Assert(accum->pos_digits[0] == 0 && accum->neg_digits[0] == 0);
12526 262616 : accum->have_carry_space = true;
12527 : }
12528 :
12529 2355770 : if (val->dscale > accum->dscale)
12530 300 : accum->dscale = val->dscale;
12531 2355770 : }
12532 :
12533 : /*
12534 : * Return the current value of the accumulator. This perform final carry
12535 : * propagation, and adds together the positive and negative sums.
12536 : *
12537 : * Unlike all the other routines, the caller is not required to switch to
12538 : * the memory context that holds the accumulator.
12539 : */
12540 : static void
12541 172638 : accum_sum_final(NumericSumAccum *accum, NumericVar *result)
12542 : {
12543 : int i;
12544 : NumericVar pos_var;
12545 : NumericVar neg_var;
12546 :
12547 172638 : if (accum->ndigits == 0)
12548 : {
12549 0 : set_var_from_var(&const_zero, result);
12550 0 : return;
12551 : }
12552 :
12553 : /* Perform final carry */
12554 172638 : accum_sum_carry(accum);
12555 :
12556 : /* Create NumericVars representing the positive and negative sums */
12557 172638 : init_var(&pos_var);
12558 172638 : init_var(&neg_var);
12559 :
12560 172638 : pos_var.ndigits = neg_var.ndigits = accum->ndigits;
12561 172638 : pos_var.weight = neg_var.weight = accum->weight;
12562 172638 : pos_var.dscale = neg_var.dscale = accum->dscale;
12563 172638 : pos_var.sign = NUMERIC_POS;
12564 172638 : neg_var.sign = NUMERIC_NEG;
12565 :
12566 172638 : pos_var.buf = pos_var.digits = digitbuf_alloc(accum->ndigits);
12567 172638 : neg_var.buf = neg_var.digits = digitbuf_alloc(accum->ndigits);
12568 :
12569 2605210 : for (i = 0; i < accum->ndigits; i++)
12570 : {
12571 : Assert(accum->pos_digits[i] < NBASE);
12572 2432572 : pos_var.digits[i] = (int16) accum->pos_digits[i];
12573 :
12574 : Assert(accum->neg_digits[i] < NBASE);
12575 2432572 : neg_var.digits[i] = (int16) accum->neg_digits[i];
12576 : }
12577 :
12578 : /* And add them together */
12579 172638 : add_var(&pos_var, &neg_var, result);
12580 :
12581 : /* Remove leading/trailing zeroes */
12582 172638 : strip_var(result);
12583 : }
12584 :
12585 : /*
12586 : * Copy an accumulator's state.
12587 : *
12588 : * 'dst' is assumed to be uninitialized beforehand. No attempt is made at
12589 : * freeing old values.
12590 : */
12591 : static void
12592 42 : accum_sum_copy(NumericSumAccum *dst, NumericSumAccum *src)
12593 : {
12594 42 : dst->pos_digits = palloc(src->ndigits * sizeof(int32));
12595 42 : dst->neg_digits = palloc(src->ndigits * sizeof(int32));
12596 :
12597 42 : memcpy(dst->pos_digits, src->pos_digits, src->ndigits * sizeof(int32));
12598 42 : memcpy(dst->neg_digits, src->neg_digits, src->ndigits * sizeof(int32));
12599 42 : dst->num_uncarried = src->num_uncarried;
12600 42 : dst->ndigits = src->ndigits;
12601 42 : dst->weight = src->weight;
12602 42 : dst->dscale = src->dscale;
12603 42 : }
12604 :
12605 : /*
12606 : * Add the current value of 'accum2' into 'accum'.
12607 : */
12608 : static void
12609 54 : accum_sum_combine(NumericSumAccum *accum, NumericSumAccum *accum2)
12610 : {
12611 : NumericVar tmp_var;
12612 :
12613 54 : init_var(&tmp_var);
12614 :
12615 54 : accum_sum_final(accum2, &tmp_var);
12616 54 : accum_sum_add(accum, &tmp_var);
12617 :
12618 54 : free_var(&tmp_var);
12619 54 : }
|