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 119884 : numeric_in(PG_FUNCTION_ARGS)
638 : {
639 119884 : char *str = PG_GETARG_CSTRING(0);
640 : #ifdef NOT_USED
641 : Oid typelem = PG_GETARG_OID(1);
642 : #endif
643 119884 : int32 typmod = PG_GETARG_INT32(2);
644 119884 : Node *escontext = fcinfo->context;
645 : Numeric res;
646 : const char *cp;
647 : const char *numstart;
648 : int sign;
649 :
650 : /* Skip leading spaces */
651 119884 : cp = str;
652 120274 : while (*cp)
653 : {
654 120262 : if (!isspace((unsigned char) *cp))
655 119872 : break;
656 390 : 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 119884 : numstart = cp;
665 119884 : sign = NUMERIC_POS;
666 :
667 119884 : if (*cp == '+')
668 48 : cp++;
669 119836 : else if (*cp == '-')
670 : {
671 3744 : sign = NUMERIC_NEG;
672 3744 : 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 119884 : 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 1776 : if (pg_strncasecmp(numstart, "NaN", 3) == 0)
689 : {
690 592 : res = make_result(&const_nan);
691 592 : cp = numstart + 3;
692 : }
693 1184 : else if (pg_strncasecmp(cp, "Infinity", 8) == 0)
694 : {
695 492 : res = make_result(sign == NUMERIC_POS ? &const_pinf : &const_ninf);
696 492 : cp += 8;
697 : }
698 692 : 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 104 : 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 1714 : while (*cp)
714 : {
715 42 : if (!isspace((unsigned char) *cp))
716 0 : goto invalid_syntax;
717 42 : cp++;
718 : }
719 :
720 1672 : 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 118108 : 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 118108 : if (cp[0] == '0')
740 : {
741 36380 : 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 36224 : default:
756 36224 : base = 10;
757 : }
758 : }
759 : else
760 81728 : base = 10;
761 :
762 : /* Parse the rest of the number and apply the sign */
763 118108 : if (base == 10)
764 : {
765 117952 : if (!set_var_from_str(str, cp, &value, &cp, escontext))
766 42 : PG_RETURN_NULL();
767 117904 : 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 118120 : while (*cp)
781 : {
782 150 : if (!isspace((unsigned char) *cp))
783 72 : goto invalid_syntax;
784 78 : cp++;
785 : }
786 :
787 117970 : if (!apply_typmod(&value, typmod, escontext))
788 24 : PG_RETURN_NULL();
789 :
790 117946 : res = make_result_opt_error(&value, &have_error);
791 :
792 117946 : 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 117928 : free_var(&value);
798 : }
799 :
800 119600 : PG_RETURN_NUMERIC(res);
801 :
802 176 : invalid_syntax:
803 176 : 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 789298 : numeric_out(PG_FUNCTION_ARGS)
817 : {
818 789298 : Numeric num = PG_GETARG_NUMERIC(0);
819 : NumericVar x;
820 : char *str;
821 :
822 : /*
823 : * Handle NaN and infinities
824 : */
825 789298 : if (NUMERIC_IS_SPECIAL(num))
826 : {
827 3604 : if (NUMERIC_IS_PINF(num))
828 1040 : PG_RETURN_CSTRING(pstrdup("Infinity"));
829 2564 : else if (NUMERIC_IS_NINF(num))
830 658 : PG_RETURN_CSTRING(pstrdup("-Infinity"));
831 : else
832 1906 : PG_RETURN_CSTRING(pstrdup("NaN"));
833 : }
834 :
835 : /*
836 : * Get the number in the variable format.
837 : */
838 785694 : init_var_from_num(num, &x);
839 :
840 785694 : str = get_str_from_var(&x);
841 :
842 785694 : PG_RETURN_CSTRING(str);
843 : }
844 :
845 : /*
846 : * numeric_is_nan() -
847 : *
848 : * Is Numeric value a NaN?
849 : */
850 : bool
851 13670 : numeric_is_nan(Numeric num)
852 : {
853 13670 : 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 1890 : make_numeric_typmod(int precision, int scale)
908 : {
909 1890 : 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 143192 : is_valid_numeric_typmod(int32 typmod)
917 : {
918 143192 : 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 24292 : numeric_typmod_precision(int32 typmod)
928 : {
929 24292 : 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 17128 : numeric_typmod_scale(int32 typmod)
943 : {
944 17128 : 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 7164 : numeric_maximum_size(int32 typmod)
954 : {
955 : int precision;
956 : int numeric_digits;
957 :
958 7164 : if (!is_valid_numeric_typmod(typmod))
959 0 : return -1;
960 :
961 : /* precision (ie, max # of digits) is in upper bits of typmod */
962 7164 : 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 7164 : 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 7164 : 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 12966 : numeric_normalize(Numeric num)
1027 : {
1028 : NumericVar x;
1029 : char *str;
1030 : int last;
1031 :
1032 : /*
1033 : * Handle NaN and infinities
1034 : */
1035 12966 : 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 12966 : init_var_from_num(num, &x);
1046 :
1047 12966 : str = get_str_from_var(&x);
1048 :
1049 : /* If there's no decimal point, there's certainly nothing to remove. */
1050 12966 : 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 12966 : 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 11790 : numeric (PG_FUNCTION_ARGS)
1247 : {
1248 11790 : Numeric num = PG_GETARG_NUMERIC(0);
1249 11790 : 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 11790 : 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 11580 : 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 11580 : precision = numeric_typmod_precision(typmod);
1279 11580 : scale = numeric_typmod_scale(typmod);
1280 11580 : maxdigits = precision - scale;
1281 :
1282 : /* The target display scale is non-negative */
1283 11580 : 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 11580 : ddigits = (NUMERIC_WEIGHT(num) + 1) * DEC_DIGITS;
1293 11580 : 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 4446 : init_var(&var);
1313 :
1314 4446 : set_var_from_num(num, &var);
1315 4446 : (void) apply_typmod(&var, typmod, NULL);
1316 4386 : new = make_result(&var);
1317 :
1318 4386 : free_var(&var);
1319 :
1320 4386 : PG_RETURN_NUMERIC(new);
1321 : }
1322 :
1323 : Datum
1324 1932 : numerictypmodin(PG_FUNCTION_ARGS)
1325 : {
1326 1932 : ArrayType *ta = PG_GETARG_ARRAYTYPE_P(0);
1327 : int32 *tl;
1328 : int n;
1329 : int32 typmod;
1330 :
1331 1932 : tl = ArrayGetIntegerTypmods(ta, &n);
1332 :
1333 1932 : if (n == 2)
1334 : {
1335 1912 : 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 1894 : 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 1882 : 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 1890 : PG_RETURN_INT32(typmod);
1366 : }
1367 :
1368 : Datum
1369 376 : numerictypmodout(PG_FUNCTION_ARGS)
1370 : {
1371 376 : int32 typmod = PG_GETARG_INT32(0);
1372 376 : char *res = (char *) palloc(64);
1373 :
1374 376 : if (is_valid_numeric_typmod(typmod))
1375 376 : snprintf(res, 64, "(%d,%d)",
1376 : numeric_typmod_precision(typmod),
1377 : numeric_typmod_scale(typmod));
1378 : else
1379 0 : *res = '\0';
1380 :
1381 376 : 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 372 : generate_series_numeric(PG_FUNCTION_ARGS)
1704 : {
1705 372 : return generate_series_step_numeric(fcinfo);
1706 : }
1707 :
1708 : Datum
1709 822 : generate_series_step_numeric(PG_FUNCTION_ARGS)
1710 : {
1711 : generate_series_numeric_fctx *fctx;
1712 : FuncCallContext *funcctx;
1713 : MemoryContext oldcontext;
1714 :
1715 822 : if (SRF_IS_FIRSTCALL())
1716 : {
1717 162 : Numeric start_num = PG_GETARG_NUMERIC(0);
1718 162 : Numeric stop_num = PG_GETARG_NUMERIC(1);
1719 162 : NumericVar steploc = const_one;
1720 :
1721 : /* Reject NaN and infinities in start and stop values */
1722 162 : 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 150 : 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 138 : 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 120 : funcctx = SRF_FIRSTCALL_INIT();
1772 :
1773 : /*
1774 : * Switch to memory context appropriate for multiple function calls.
1775 : */
1776 120 : oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
1777 :
1778 : /* allocate memory for user context */
1779 : fctx = (generate_series_numeric_fctx *)
1780 120 : 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 120 : init_var(&fctx->current);
1789 120 : init_var(&fctx->stop);
1790 120 : init_var(&fctx->step);
1791 :
1792 120 : set_var_from_num(start_num, &fctx->current);
1793 120 : set_var_from_num(stop_num, &fctx->stop);
1794 120 : set_var_from_var(&steploc, &fctx->step);
1795 :
1796 120 : funcctx->user_fctx = fctx;
1797 120 : MemoryContextSwitchTo(oldcontext);
1798 : }
1799 :
1800 : /* stuff done on every call of the function */
1801 780 : funcctx = SRF_PERCALL_SETUP();
1802 :
1803 : /*
1804 : * Get the saved state and use current state as the result of this
1805 : * iteration.
1806 : */
1807 780 : fctx = funcctx->user_fctx;
1808 :
1809 1380 : if ((fctx->step.sign == NUMERIC_POS &&
1810 600 : cmp_var(&fctx->current, &fctx->stop) <= 0) ||
1811 468 : (fctx->step.sign == NUMERIC_NEG &&
1812 180 : cmp_var(&fctx->current, &fctx->stop) >= 0))
1813 : {
1814 660 : Numeric result = make_result(&fctx->current);
1815 :
1816 : /* switch to memory context appropriate for iteration calculation */
1817 660 : oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
1818 :
1819 : /* increment current in preparation for next iteration */
1820 660 : add_var(&fctx->current, &fctx->step, &fctx->current);
1821 660 : MemoryContextSwitchTo(oldcontext);
1822 :
1823 : /* do when there is more left to send */
1824 660 : SRF_RETURN_NEXT(funcctx, NumericGetDatum(result));
1825 : }
1826 : else
1827 : /* do when there is no more left */
1828 120 : SRF_RETURN_DONE(funcctx);
1829 : }
1830 :
1831 : /*
1832 : * Planner support function for generate_series(numeric, numeric [, numeric])
1833 : */
1834 : Datum
1835 450 : generate_series_numeric_support(PG_FUNCTION_ARGS)
1836 : {
1837 450 : Node *rawreq = (Node *) PG_GETARG_POINTER(0);
1838 450 : Node *ret = NULL;
1839 :
1840 450 : if (IsA(rawreq, SupportRequestRows))
1841 : {
1842 : /* Try to estimate the number of rows returned */
1843 144 : SupportRequestRows *req = (SupportRequestRows *) rawreq;
1844 :
1845 144 : if (is_funcclause(req->node)) /* be paranoid */
1846 : {
1847 144 : List *args = ((FuncExpr *) req->node)->args;
1848 : Node *arg1,
1849 : *arg2,
1850 : *arg3;
1851 :
1852 : /* We can use estimated argument values here */
1853 144 : arg1 = estimate_expression_value(req->root, linitial(args));
1854 144 : arg2 = estimate_expression_value(req->root, lsecond(args));
1855 144 : if (list_length(args) >= 3)
1856 102 : arg3 = estimate_expression_value(req->root, lthird(args));
1857 : else
1858 42 : 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 144 : if ((IsA(arg1, Const) &&
1867 138 : ((Const *) arg1)->constisnull) ||
1868 144 : (IsA(arg2, Const) &&
1869 144 : ((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 144 : else if (IsA(arg1, Const) &&
1877 138 : IsA(arg2, Const) &&
1878 102 : (arg3 == NULL || IsA(arg3, Const)))
1879 : {
1880 : Numeric start_num;
1881 : Numeric stop_num;
1882 126 : 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 126 : start_num = DatumGetNumeric(((Const *) arg1)->constvalue);
1889 126 : stop_num = DatumGetNumeric(((Const *) arg2)->constvalue);
1890 :
1891 126 : if (NUMERIC_IS_SPECIAL(start_num) ||
1892 108 : NUMERIC_IS_SPECIAL(stop_num))
1893 48 : PG_RETURN_POINTER(NULL);
1894 :
1895 96 : 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 78 : if (cmp_var(&step, &const_zero) != 0)
1914 : {
1915 : NumericVar start;
1916 : NumericVar stop;
1917 : NumericVar res;
1918 :
1919 66 : init_var_from_num(start_num, &start);
1920 66 : init_var_from_num(stop_num, &stop);
1921 :
1922 66 : init_var(&res);
1923 66 : sub_var(&stop, &start, &res);
1924 :
1925 66 : 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 60 : if (arg3)
1934 30 : div_var(&res, &step, &res, 0, false, false);
1935 : else
1936 30 : trunc_var(&res, 0); /* step = 1 */
1937 :
1938 60 : req->rows = numericvar_to_double_no_overflow(&res) + 1;
1939 60 : ret = (Node *) req;
1940 : }
1941 :
1942 66 : free_var(&res);
1943 : }
1944 : }
1945 : }
1946 : }
1947 :
1948 402 : 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 the
1962 : * upper bound is assigned to an additional bucket (with number
1963 : * count+1). We don't allow "NaN" for any of the numeric arguments.
1964 : */
1965 : Datum
1966 780 : width_bucket_numeric(PG_FUNCTION_ARGS)
1967 : {
1968 780 : Numeric operand = PG_GETARG_NUMERIC(0);
1969 780 : Numeric bound1 = PG_GETARG_NUMERIC(1);
1970 780 : Numeric bound2 = PG_GETARG_NUMERIC(2);
1971 780 : int32 count = PG_GETARG_INT32(3);
1972 : NumericVar count_var;
1973 : NumericVar result_var;
1974 : int32 result;
1975 :
1976 780 : if (count <= 0)
1977 12 : ereport(ERROR,
1978 : (errcode(ERRCODE_INVALID_ARGUMENT_FOR_WIDTH_BUCKET_FUNCTION),
1979 : errmsg("count must be greater than zero")));
1980 :
1981 768 : if (NUMERIC_IS_SPECIAL(operand) ||
1982 750 : NUMERIC_IS_SPECIAL(bound1) ||
1983 744 : NUMERIC_IS_SPECIAL(bound2))
1984 : {
1985 36 : if (NUMERIC_IS_NAN(operand) ||
1986 30 : NUMERIC_IS_NAN(bound1) ||
1987 30 : NUMERIC_IS_NAN(bound2))
1988 6 : ereport(ERROR,
1989 : (errcode(ERRCODE_INVALID_ARGUMENT_FOR_WIDTH_BUCKET_FUNCTION),
1990 : errmsg("operand, lower bound, and upper bound cannot be NaN")));
1991 : /* We allow "operand" to be infinite; cmp_numerics will cope */
1992 30 : if (NUMERIC_IS_INF(bound1) || NUMERIC_IS_INF(bound2))
1993 18 : ereport(ERROR,
1994 : (errcode(ERRCODE_INVALID_ARGUMENT_FOR_WIDTH_BUCKET_FUNCTION),
1995 : errmsg("lower and upper bounds must be finite")));
1996 : }
1997 :
1998 744 : init_var(&result_var);
1999 744 : init_var(&count_var);
2000 :
2001 : /* Convert 'count' to a numeric, for ease of use later */
2002 744 : int64_to_numericvar((int64) count, &count_var);
2003 :
2004 744 : switch (cmp_numerics(bound1, bound2))
2005 : {
2006 6 : case 0:
2007 6 : ereport(ERROR,
2008 : (errcode(ERRCODE_INVALID_ARGUMENT_FOR_WIDTH_BUCKET_FUNCTION),
2009 : errmsg("lower bound cannot equal upper bound")));
2010 : break;
2011 :
2012 : /* bound1 < bound2 */
2013 546 : case -1:
2014 546 : if (cmp_numerics(operand, bound1) < 0)
2015 114 : set_var_from_var(&const_zero, &result_var);
2016 432 : else if (cmp_numerics(operand, bound2) >= 0)
2017 108 : add_var(&count_var, &const_one, &result_var);
2018 : else
2019 324 : compute_bucket(operand, bound1, bound2, &count_var,
2020 : &result_var);
2021 546 : break;
2022 :
2023 : /* bound1 > bound2 */
2024 192 : case 1:
2025 192 : if (cmp_numerics(operand, bound1) > 0)
2026 12 : set_var_from_var(&const_zero, &result_var);
2027 180 : else if (cmp_numerics(operand, bound2) <= 0)
2028 24 : add_var(&count_var, &const_one, &result_var);
2029 : else
2030 156 : compute_bucket(operand, bound1, bound2, &count_var,
2031 : &result_var);
2032 192 : break;
2033 : }
2034 :
2035 : /* if result exceeds the range of a legal int4, we ereport here */
2036 738 : if (!numericvar_to_int32(&result_var, &result))
2037 0 : ereport(ERROR,
2038 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
2039 : errmsg("integer out of range")));
2040 :
2041 738 : free_var(&count_var);
2042 738 : free_var(&result_var);
2043 :
2044 738 : PG_RETURN_INT32(result);
2045 : }
2046 :
2047 : /*
2048 : * 'operand' is inside the bucket range, so determine the correct
2049 : * bucket for it to go in. The calculations performed by this function
2050 : * are derived directly from the SQL2003 spec. Note however that we
2051 : * multiply by count before dividing, to avoid unnecessary roundoff error.
2052 : */
2053 : static void
2054 480 : compute_bucket(Numeric operand, Numeric bound1, Numeric bound2,
2055 : const NumericVar *count_var, NumericVar *result_var)
2056 : {
2057 : NumericVar bound1_var;
2058 : NumericVar bound2_var;
2059 : NumericVar operand_var;
2060 :
2061 480 : init_var_from_num(bound1, &bound1_var);
2062 480 : init_var_from_num(bound2, &bound2_var);
2063 480 : init_var_from_num(operand, &operand_var);
2064 :
2065 : /*
2066 : * Per spec, bound1 is inclusive and bound2 is exclusive, and so we have
2067 : * bound1 <= operand < bound2 or bound1 >= operand > bound2. Either way,
2068 : * the result is ((operand - bound1) * count) / (bound2 - bound1) + 1,
2069 : * where the quotient is computed using floor division (i.e., division to
2070 : * zero decimal places with truncation), which guarantees that the result
2071 : * is in the range [1, count]. Reversing the bounds doesn't affect the
2072 : * computation, because the signs cancel out when dividing.
2073 : */
2074 480 : sub_var(&operand_var, &bound1_var, &operand_var);
2075 480 : sub_var(&bound2_var, &bound1_var, &bound2_var);
2076 :
2077 480 : mul_var(&operand_var, count_var, &operand_var,
2078 480 : operand_var.dscale + count_var->dscale);
2079 480 : div_var(&operand_var, &bound2_var, result_var, 0, false, true);
2080 480 : add_var(result_var, &const_one, result_var);
2081 :
2082 480 : free_var(&bound1_var);
2083 480 : free_var(&bound2_var);
2084 480 : free_var(&operand_var);
2085 480 : }
2086 :
2087 : /* ----------------------------------------------------------------------
2088 : *
2089 : * Comparison functions
2090 : *
2091 : * Note: btree indexes need these routines not to leak memory; therefore,
2092 : * be careful to free working copies of toasted datums. Most places don't
2093 : * need to be so careful.
2094 : *
2095 : * Sort support:
2096 : *
2097 : * We implement the sortsupport strategy routine in order to get the benefit of
2098 : * abbreviation. The ordinary numeric comparison can be quite slow as a result
2099 : * of palloc/pfree cycles (due to detoasting packed values for alignment);
2100 : * while this could be worked on itself, the abbreviation strategy gives more
2101 : * speedup in many common cases.
2102 : *
2103 : * Two different representations are used for the abbreviated form, one in
2104 : * int32 and one in int64, whichever fits into a by-value Datum. In both cases
2105 : * the representation is negated relative to the original value, because we use
2106 : * the largest negative value for NaN, which sorts higher than other values. We
2107 : * convert the absolute value of the numeric to a 31-bit or 63-bit positive
2108 : * value, and then negate it if the original number was positive.
2109 : *
2110 : * We abort the abbreviation process if the abbreviation cardinality is below
2111 : * 0.01% of the row count (1 per 10k non-null rows). The actual break-even
2112 : * point is somewhat below that, perhaps 1 per 30k (at 1 per 100k there's a
2113 : * very small penalty), but we don't want to build up too many abbreviated
2114 : * values before first testing for abort, so we take the slightly pessimistic
2115 : * number. We make no attempt to estimate the cardinality of the real values,
2116 : * since it plays no part in the cost model here (if the abbreviation is equal,
2117 : * the cost of comparing equal and unequal underlying values is comparable).
2118 : * We discontinue even checking for abort (saving us the hashing overhead) if
2119 : * the estimated cardinality gets to 100k; that would be enough to support many
2120 : * billions of rows while doing no worse than breaking even.
2121 : *
2122 : * ----------------------------------------------------------------------
2123 : */
2124 :
2125 : /*
2126 : * Sort support strategy routine.
2127 : */
2128 : Datum
2129 986 : numeric_sortsupport(PG_FUNCTION_ARGS)
2130 : {
2131 986 : SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0);
2132 :
2133 986 : ssup->comparator = numeric_fast_cmp;
2134 :
2135 986 : if (ssup->abbreviate)
2136 : {
2137 : NumericSortSupport *nss;
2138 250 : MemoryContext oldcontext = MemoryContextSwitchTo(ssup->ssup_cxt);
2139 :
2140 250 : nss = palloc(sizeof(NumericSortSupport));
2141 :
2142 : /*
2143 : * palloc a buffer for handling unaligned packed values in addition to
2144 : * the support struct
2145 : */
2146 250 : nss->buf = palloc(VARATT_SHORT_MAX + VARHDRSZ + 1);
2147 :
2148 250 : nss->input_count = 0;
2149 250 : nss->estimating = true;
2150 250 : initHyperLogLog(&nss->abbr_card, 10);
2151 :
2152 250 : ssup->ssup_extra = nss;
2153 :
2154 250 : ssup->abbrev_full_comparator = ssup->comparator;
2155 250 : ssup->comparator = numeric_cmp_abbrev;
2156 250 : ssup->abbrev_converter = numeric_abbrev_convert;
2157 250 : ssup->abbrev_abort = numeric_abbrev_abort;
2158 :
2159 250 : MemoryContextSwitchTo(oldcontext);
2160 : }
2161 :
2162 986 : PG_RETURN_VOID();
2163 : }
2164 :
2165 : /*
2166 : * Abbreviate a numeric datum, handling NaNs and detoasting
2167 : * (must not leak memory!)
2168 : */
2169 : static Datum
2170 19132 : numeric_abbrev_convert(Datum original_datum, SortSupport ssup)
2171 : {
2172 19132 : NumericSortSupport *nss = ssup->ssup_extra;
2173 19132 : void *original_varatt = PG_DETOAST_DATUM_PACKED(original_datum);
2174 : Numeric value;
2175 : Datum result;
2176 :
2177 19132 : nss->input_count += 1;
2178 :
2179 : /*
2180 : * This is to handle packed datums without needing a palloc/pfree cycle;
2181 : * we keep and reuse a buffer large enough to handle any short datum.
2182 : */
2183 19132 : if (VARATT_IS_SHORT(original_varatt))
2184 : {
2185 1026 : void *buf = nss->buf;
2186 1026 : Size sz = VARSIZE_SHORT(original_varatt) - VARHDRSZ_SHORT;
2187 :
2188 : Assert(sz <= VARATT_SHORT_MAX - VARHDRSZ_SHORT);
2189 :
2190 1026 : SET_VARSIZE(buf, VARHDRSZ + sz);
2191 1026 : memcpy(VARDATA(buf), VARDATA_SHORT(original_varatt), sz);
2192 :
2193 1026 : value = (Numeric) buf;
2194 : }
2195 : else
2196 18106 : value = (Numeric) original_varatt;
2197 :
2198 19132 : if (NUMERIC_IS_SPECIAL(value))
2199 : {
2200 150 : if (NUMERIC_IS_PINF(value))
2201 48 : result = NUMERIC_ABBREV_PINF;
2202 102 : else if (NUMERIC_IS_NINF(value))
2203 48 : result = NUMERIC_ABBREV_NINF;
2204 : else
2205 54 : result = NUMERIC_ABBREV_NAN;
2206 : }
2207 : else
2208 : {
2209 : NumericVar var;
2210 :
2211 18982 : init_var_from_num(value, &var);
2212 :
2213 18982 : result = numeric_abbrev_convert_var(&var, nss);
2214 : }
2215 :
2216 : /* should happen only for external/compressed toasts */
2217 19132 : if ((Pointer) original_varatt != DatumGetPointer(original_datum))
2218 0 : pfree(original_varatt);
2219 :
2220 19132 : return result;
2221 : }
2222 :
2223 : /*
2224 : * Consider whether to abort abbreviation.
2225 : *
2226 : * We pay no attention to the cardinality of the non-abbreviated data. There is
2227 : * no reason to do so: unlike text, we have no fast check for equal values, so
2228 : * we pay the full overhead whenever the abbreviations are equal regardless of
2229 : * whether the underlying values are also equal.
2230 : */
2231 : static bool
2232 144 : numeric_abbrev_abort(int memtupcount, SortSupport ssup)
2233 : {
2234 144 : NumericSortSupport *nss = ssup->ssup_extra;
2235 : double abbr_card;
2236 :
2237 144 : if (memtupcount < 10000 || nss->input_count < 10000 || !nss->estimating)
2238 144 : return false;
2239 :
2240 0 : abbr_card = estimateHyperLogLog(&nss->abbr_card);
2241 :
2242 : /*
2243 : * If we have >100k distinct values, then even if we were sorting many
2244 : * billion rows we'd likely still break even, and the penalty of undoing
2245 : * that many rows of abbrevs would probably not be worth it. Stop even
2246 : * counting at that point.
2247 : */
2248 0 : if (abbr_card > 100000.0)
2249 : {
2250 0 : if (trace_sort)
2251 0 : elog(LOG,
2252 : "numeric_abbrev: estimation ends at cardinality %f"
2253 : " after " INT64_FORMAT " values (%d rows)",
2254 : abbr_card, nss->input_count, memtupcount);
2255 0 : nss->estimating = false;
2256 0 : return false;
2257 : }
2258 :
2259 : /*
2260 : * Target minimum cardinality is 1 per ~10k of non-null inputs. (The
2261 : * break even point is somewhere between one per 100k rows, where
2262 : * abbreviation has a very slight penalty, and 1 per 10k where it wins by
2263 : * a measurable percentage.) We use the relatively pessimistic 10k
2264 : * threshold, and add a 0.5 row fudge factor, because it allows us to
2265 : * abort earlier on genuinely pathological data where we've had exactly
2266 : * one abbreviated value in the first 10k (non-null) rows.
2267 : */
2268 0 : if (abbr_card < nss->input_count / 10000.0 + 0.5)
2269 : {
2270 0 : if (trace_sort)
2271 0 : elog(LOG,
2272 : "numeric_abbrev: aborting abbreviation at cardinality %f"
2273 : " below threshold %f after " INT64_FORMAT " values (%d rows)",
2274 : abbr_card, nss->input_count / 10000.0 + 0.5,
2275 : nss->input_count, memtupcount);
2276 0 : return true;
2277 : }
2278 :
2279 0 : if (trace_sort)
2280 0 : elog(LOG,
2281 : "numeric_abbrev: cardinality %f"
2282 : " after " INT64_FORMAT " values (%d rows)",
2283 : abbr_card, nss->input_count, memtupcount);
2284 :
2285 0 : return false;
2286 : }
2287 :
2288 : /*
2289 : * Non-fmgr interface to the comparison routine to allow sortsupport to elide
2290 : * the fmgr call. The saving here is small given how slow numeric comparisons
2291 : * are, but it is a required part of the sort support API when abbreviations
2292 : * are performed.
2293 : *
2294 : * Two palloc/pfree cycles could be saved here by using persistent buffers for
2295 : * aligning short-varlena inputs, but this has not so far been considered to
2296 : * be worth the effort.
2297 : */
2298 : static int
2299 4556306 : numeric_fast_cmp(Datum x, Datum y, SortSupport ssup)
2300 : {
2301 4556306 : Numeric nx = DatumGetNumeric(x);
2302 4556306 : Numeric ny = DatumGetNumeric(y);
2303 : int result;
2304 :
2305 4556306 : result = cmp_numerics(nx, ny);
2306 :
2307 4556306 : if ((Pointer) nx != DatumGetPointer(x))
2308 172830 : pfree(nx);
2309 4556306 : if ((Pointer) ny != DatumGetPointer(y))
2310 172824 : pfree(ny);
2311 :
2312 4556306 : return result;
2313 : }
2314 :
2315 : /*
2316 : * Compare abbreviations of values. (Abbreviations may be equal where the true
2317 : * values differ, but if the abbreviations differ, they must reflect the
2318 : * ordering of the true values.)
2319 : */
2320 : static int
2321 188956 : numeric_cmp_abbrev(Datum x, Datum y, SortSupport ssup)
2322 : {
2323 : /*
2324 : * NOTE WELL: this is intentionally backwards, because the abbreviation is
2325 : * negated relative to the original value, to handle NaN/infinity cases.
2326 : */
2327 188956 : if (DatumGetNumericAbbrev(x) < DatumGetNumericAbbrev(y))
2328 99290 : return 1;
2329 89666 : if (DatumGetNumericAbbrev(x) > DatumGetNumericAbbrev(y))
2330 89432 : return -1;
2331 234 : return 0;
2332 : }
2333 :
2334 : /*
2335 : * Abbreviate a NumericVar according to the available bit size.
2336 : *
2337 : * The 31-bit value is constructed as:
2338 : *
2339 : * 0 + 7bits digit weight + 24 bits digit value
2340 : *
2341 : * where the digit weight is in single decimal digits, not digit words, and
2342 : * stored in excess-44 representation[1]. The 24-bit digit value is the 7 most
2343 : * significant decimal digits of the value converted to binary. Values whose
2344 : * weights would fall outside the representable range are rounded off to zero
2345 : * (which is also used to represent actual zeros) or to 0x7FFFFFFF (which
2346 : * otherwise cannot occur). Abbreviation therefore fails to gain any advantage
2347 : * where values are outside the range 10^-44 to 10^83, which is not considered
2348 : * to be a serious limitation, or when values are of the same magnitude and
2349 : * equal in the first 7 decimal digits, which is considered to be an
2350 : * unavoidable limitation given the available bits. (Stealing three more bits
2351 : * to compare another digit would narrow the range of representable weights by
2352 : * a factor of 8, which starts to look like a real limiting factor.)
2353 : *
2354 : * (The value 44 for the excess is essentially arbitrary)
2355 : *
2356 : * The 63-bit value is constructed as:
2357 : *
2358 : * 0 + 7bits weight + 4 x 14-bit packed digit words
2359 : *
2360 : * The weight in this case is again stored in excess-44, but this time it is
2361 : * the original weight in digit words (i.e. powers of 10000). The first four
2362 : * digit words of the value (if present; trailing zeros are assumed as needed)
2363 : * are packed into 14 bits each to form the rest of the value. Again,
2364 : * out-of-range values are rounded off to 0 or 0x7FFFFFFFFFFFFFFF. The
2365 : * representable range in this case is 10^-176 to 10^332, which is considered
2366 : * to be good enough for all practical purposes, and comparison of 4 words
2367 : * means that at least 13 decimal digits are compared, which is considered to
2368 : * be a reasonable compromise between effectiveness and efficiency in computing
2369 : * the abbreviation.
2370 : *
2371 : * (The value 44 for the excess is even more arbitrary here, it was chosen just
2372 : * to match the value used in the 31-bit case)
2373 : *
2374 : * [1] - Excess-k representation means that the value is offset by adding 'k'
2375 : * and then treated as unsigned, so the smallest representable value is stored
2376 : * with all bits zero. This allows simple comparisons to work on the composite
2377 : * value.
2378 : */
2379 :
2380 : #if NUMERIC_ABBREV_BITS == 64
2381 :
2382 : static Datum
2383 18982 : numeric_abbrev_convert_var(const NumericVar *var, NumericSortSupport *nss)
2384 : {
2385 18982 : int ndigits = var->ndigits;
2386 18982 : int weight = var->weight;
2387 : int64 result;
2388 :
2389 18982 : if (ndigits == 0 || weight < -44)
2390 : {
2391 52 : result = 0;
2392 : }
2393 18930 : else if (weight > 83)
2394 : {
2395 12 : result = PG_INT64_MAX;
2396 : }
2397 : else
2398 : {
2399 18918 : result = ((int64) (weight + 44) << 56);
2400 :
2401 18918 : switch (ndigits)
2402 : {
2403 0 : default:
2404 0 : result |= ((int64) var->digits[3]);
2405 : /* FALLTHROUGH */
2406 6208 : case 3:
2407 6208 : result |= ((int64) var->digits[2]) << 14;
2408 : /* FALLTHROUGH */
2409 18292 : case 2:
2410 18292 : result |= ((int64) var->digits[1]) << 28;
2411 : /* FALLTHROUGH */
2412 18918 : case 1:
2413 18918 : result |= ((int64) var->digits[0]) << 42;
2414 18918 : break;
2415 : }
2416 : }
2417 :
2418 : /* the abbrev is negated relative to the original */
2419 18982 : if (var->sign == NUMERIC_POS)
2420 18884 : result = -result;
2421 :
2422 18982 : if (nss->estimating)
2423 : {
2424 18982 : uint32 tmp = ((uint32) result
2425 18982 : ^ (uint32) ((uint64) result >> 32));
2426 :
2427 18982 : addHyperLogLog(&nss->abbr_card, DatumGetUInt32(hash_uint32(tmp)));
2428 : }
2429 :
2430 18982 : return NumericAbbrevGetDatum(result);
2431 : }
2432 :
2433 : #endif /* NUMERIC_ABBREV_BITS == 64 */
2434 :
2435 : #if NUMERIC_ABBREV_BITS == 32
2436 :
2437 : static Datum
2438 : numeric_abbrev_convert_var(const NumericVar *var, NumericSortSupport *nss)
2439 : {
2440 : int ndigits = var->ndigits;
2441 : int weight = var->weight;
2442 : int32 result;
2443 :
2444 : if (ndigits == 0 || weight < -11)
2445 : {
2446 : result = 0;
2447 : }
2448 : else if (weight > 20)
2449 : {
2450 : result = PG_INT32_MAX;
2451 : }
2452 : else
2453 : {
2454 : NumericDigit nxt1 = (ndigits > 1) ? var->digits[1] : 0;
2455 :
2456 : weight = (weight + 11) * 4;
2457 :
2458 : result = var->digits[0];
2459 :
2460 : /*
2461 : * "result" now has 1 to 4 nonzero decimal digits. We pack in more
2462 : * digits to make 7 in total (largest we can fit in 24 bits)
2463 : */
2464 :
2465 : if (result > 999)
2466 : {
2467 : /* already have 4 digits, add 3 more */
2468 : result = (result * 1000) + (nxt1 / 10);
2469 : weight += 3;
2470 : }
2471 : else if (result > 99)
2472 : {
2473 : /* already have 3 digits, add 4 more */
2474 : result = (result * 10000) + nxt1;
2475 : weight += 2;
2476 : }
2477 : else if (result > 9)
2478 : {
2479 : NumericDigit nxt2 = (ndigits > 2) ? var->digits[2] : 0;
2480 :
2481 : /* already have 2 digits, add 5 more */
2482 : result = (result * 100000) + (nxt1 * 10) + (nxt2 / 1000);
2483 : weight += 1;
2484 : }
2485 : else
2486 : {
2487 : NumericDigit nxt2 = (ndigits > 2) ? var->digits[2] : 0;
2488 :
2489 : /* already have 1 digit, add 6 more */
2490 : result = (result * 1000000) + (nxt1 * 100) + (nxt2 / 100);
2491 : }
2492 :
2493 : result = result | (weight << 24);
2494 : }
2495 :
2496 : /* the abbrev is negated relative to the original */
2497 : if (var->sign == NUMERIC_POS)
2498 : result = -result;
2499 :
2500 : if (nss->estimating)
2501 : {
2502 : uint32 tmp = (uint32) result;
2503 :
2504 : addHyperLogLog(&nss->abbr_card, DatumGetUInt32(hash_uint32(tmp)));
2505 : }
2506 :
2507 : return NumericAbbrevGetDatum(result);
2508 : }
2509 :
2510 : #endif /* NUMERIC_ABBREV_BITS == 32 */
2511 :
2512 : /*
2513 : * Ordinary (non-sortsupport) comparisons follow.
2514 : */
2515 :
2516 : Datum
2517 767094 : numeric_cmp(PG_FUNCTION_ARGS)
2518 : {
2519 767094 : Numeric num1 = PG_GETARG_NUMERIC(0);
2520 767094 : Numeric num2 = PG_GETARG_NUMERIC(1);
2521 : int result;
2522 :
2523 767094 : result = cmp_numerics(num1, num2);
2524 :
2525 767094 : PG_FREE_IF_COPY(num1, 0);
2526 767094 : PG_FREE_IF_COPY(num2, 1);
2527 :
2528 767094 : PG_RETURN_INT32(result);
2529 : }
2530 :
2531 :
2532 : Datum
2533 626076 : numeric_eq(PG_FUNCTION_ARGS)
2534 : {
2535 626076 : Numeric num1 = PG_GETARG_NUMERIC(0);
2536 626076 : Numeric num2 = PG_GETARG_NUMERIC(1);
2537 : bool result;
2538 :
2539 626076 : result = cmp_numerics(num1, num2) == 0;
2540 :
2541 626076 : PG_FREE_IF_COPY(num1, 0);
2542 626076 : PG_FREE_IF_COPY(num2, 1);
2543 :
2544 626076 : PG_RETURN_BOOL(result);
2545 : }
2546 :
2547 : Datum
2548 5376 : numeric_ne(PG_FUNCTION_ARGS)
2549 : {
2550 5376 : Numeric num1 = PG_GETARG_NUMERIC(0);
2551 5376 : Numeric num2 = PG_GETARG_NUMERIC(1);
2552 : bool result;
2553 :
2554 5376 : result = cmp_numerics(num1, num2) != 0;
2555 :
2556 5376 : PG_FREE_IF_COPY(num1, 0);
2557 5376 : PG_FREE_IF_COPY(num2, 1);
2558 :
2559 5376 : PG_RETURN_BOOL(result);
2560 : }
2561 :
2562 : Datum
2563 61448 : numeric_gt(PG_FUNCTION_ARGS)
2564 : {
2565 61448 : Numeric num1 = PG_GETARG_NUMERIC(0);
2566 61448 : Numeric num2 = PG_GETARG_NUMERIC(1);
2567 : bool result;
2568 :
2569 61448 : result = cmp_numerics(num1, num2) > 0;
2570 :
2571 61448 : PG_FREE_IF_COPY(num1, 0);
2572 61448 : PG_FREE_IF_COPY(num2, 1);
2573 :
2574 61448 : PG_RETURN_BOOL(result);
2575 : }
2576 :
2577 : Datum
2578 16744 : numeric_ge(PG_FUNCTION_ARGS)
2579 : {
2580 16744 : Numeric num1 = PG_GETARG_NUMERIC(0);
2581 16744 : Numeric num2 = PG_GETARG_NUMERIC(1);
2582 : bool result;
2583 :
2584 16744 : result = cmp_numerics(num1, num2) >= 0;
2585 :
2586 16744 : PG_FREE_IF_COPY(num1, 0);
2587 16744 : PG_FREE_IF_COPY(num2, 1);
2588 :
2589 16744 : PG_RETURN_BOOL(result);
2590 : }
2591 :
2592 : Datum
2593 52544 : numeric_lt(PG_FUNCTION_ARGS)
2594 : {
2595 52544 : Numeric num1 = PG_GETARG_NUMERIC(0);
2596 52544 : Numeric num2 = PG_GETARG_NUMERIC(1);
2597 : bool result;
2598 :
2599 52544 : result = cmp_numerics(num1, num2) < 0;
2600 :
2601 52544 : PG_FREE_IF_COPY(num1, 0);
2602 52544 : PG_FREE_IF_COPY(num2, 1);
2603 :
2604 52544 : PG_RETURN_BOOL(result);
2605 : }
2606 :
2607 : Datum
2608 15488 : numeric_le(PG_FUNCTION_ARGS)
2609 : {
2610 15488 : Numeric num1 = PG_GETARG_NUMERIC(0);
2611 15488 : Numeric num2 = PG_GETARG_NUMERIC(1);
2612 : bool result;
2613 :
2614 15488 : result = cmp_numerics(num1, num2) <= 0;
2615 :
2616 15488 : PG_FREE_IF_COPY(num1, 0);
2617 15488 : PG_FREE_IF_COPY(num2, 1);
2618 :
2619 15488 : PG_RETURN_BOOL(result);
2620 : }
2621 :
2622 : static int
2623 6122598 : cmp_numerics(Numeric num1, Numeric num2)
2624 : {
2625 : int result;
2626 :
2627 : /*
2628 : * We consider all NANs to be equal and larger than any non-NAN (including
2629 : * Infinity). This is somewhat arbitrary; the important thing is to have
2630 : * a consistent sort order.
2631 : */
2632 6122598 : if (NUMERIC_IS_SPECIAL(num1))
2633 : {
2634 9052 : if (NUMERIC_IS_NAN(num1))
2635 : {
2636 8962 : if (NUMERIC_IS_NAN(num2))
2637 1178 : result = 0; /* NAN = NAN */
2638 : else
2639 7784 : result = 1; /* NAN > non-NAN */
2640 : }
2641 90 : else if (NUMERIC_IS_PINF(num1))
2642 : {
2643 72 : if (NUMERIC_IS_NAN(num2))
2644 0 : result = -1; /* PINF < NAN */
2645 72 : else if (NUMERIC_IS_PINF(num2))
2646 6 : result = 0; /* PINF = PINF */
2647 : else
2648 66 : result = 1; /* PINF > anything else */
2649 : }
2650 : else /* num1 must be NINF */
2651 : {
2652 18 : if (NUMERIC_IS_NINF(num2))
2653 6 : result = 0; /* NINF = NINF */
2654 : else
2655 12 : result = -1; /* NINF < anything else */
2656 : }
2657 : }
2658 6113546 : else if (NUMERIC_IS_SPECIAL(num2))
2659 : {
2660 11256 : if (NUMERIC_IS_NINF(num2))
2661 12 : result = 1; /* normal > NINF */
2662 : else
2663 11244 : result = -1; /* normal < NAN or PINF */
2664 : }
2665 : else
2666 : {
2667 12205750 : result = cmp_var_common(NUMERIC_DIGITS(num1), NUMERIC_NDIGITS(num1),
2668 6102654 : NUMERIC_WEIGHT(num1), NUMERIC_SIGN(num1),
2669 6102290 : NUMERIC_DIGITS(num2), NUMERIC_NDIGITS(num2),
2670 6103096 : NUMERIC_WEIGHT(num2), NUMERIC_SIGN(num2));
2671 : }
2672 :
2673 6122598 : return result;
2674 : }
2675 :
2676 : /*
2677 : * in_range support function for numeric.
2678 : */
2679 : Datum
2680 1152 : in_range_numeric_numeric(PG_FUNCTION_ARGS)
2681 : {
2682 1152 : Numeric val = PG_GETARG_NUMERIC(0);
2683 1152 : Numeric base = PG_GETARG_NUMERIC(1);
2684 1152 : Numeric offset = PG_GETARG_NUMERIC(2);
2685 1152 : bool sub = PG_GETARG_BOOL(3);
2686 1152 : bool less = PG_GETARG_BOOL(4);
2687 : bool result;
2688 :
2689 : /*
2690 : * Reject negative (including -Inf) or NaN offset. Negative is per spec,
2691 : * and NaN is because appropriate semantics for that seem non-obvious.
2692 : */
2693 1152 : if (NUMERIC_IS_NAN(offset) ||
2694 1146 : NUMERIC_IS_NINF(offset) ||
2695 1146 : NUMERIC_SIGN(offset) == NUMERIC_NEG)
2696 6 : ereport(ERROR,
2697 : (errcode(ERRCODE_INVALID_PRECEDING_OR_FOLLOWING_SIZE),
2698 : errmsg("invalid preceding or following size in window function")));
2699 :
2700 : /*
2701 : * Deal with cases where val and/or base is NaN, following the rule that
2702 : * NaN sorts after non-NaN (cf cmp_numerics). The offset cannot affect
2703 : * the conclusion.
2704 : */
2705 1146 : if (NUMERIC_IS_NAN(val))
2706 : {
2707 186 : if (NUMERIC_IS_NAN(base))
2708 60 : result = true; /* NAN = NAN */
2709 : else
2710 126 : result = !less; /* NAN > non-NAN */
2711 : }
2712 960 : else if (NUMERIC_IS_NAN(base))
2713 : {
2714 126 : result = less; /* non-NAN < NAN */
2715 : }
2716 :
2717 : /*
2718 : * Deal with infinite offset (necessarily +Inf, at this point).
2719 : */
2720 834 : else if (NUMERIC_IS_SPECIAL(offset))
2721 : {
2722 : Assert(NUMERIC_IS_PINF(offset));
2723 420 : if (sub ? NUMERIC_IS_PINF(base) : NUMERIC_IS_NINF(base))
2724 : {
2725 : /*
2726 : * base +/- offset would produce NaN, so return true for any val
2727 : * (see in_range_float8_float8() for reasoning).
2728 : */
2729 174 : result = true;
2730 : }
2731 246 : else if (sub)
2732 : {
2733 : /* base - offset must be -inf */
2734 150 : if (less)
2735 54 : result = NUMERIC_IS_NINF(val); /* only -inf is <= sum */
2736 : else
2737 96 : result = true; /* any val is >= sum */
2738 : }
2739 : else
2740 : {
2741 : /* base + offset must be +inf */
2742 96 : if (less)
2743 0 : result = true; /* any val is <= sum */
2744 : else
2745 96 : result = NUMERIC_IS_PINF(val); /* only +inf is >= sum */
2746 : }
2747 : }
2748 :
2749 : /*
2750 : * Deal with cases where val and/or base is infinite. The offset, being
2751 : * now known finite, cannot affect the conclusion.
2752 : */
2753 414 : else if (NUMERIC_IS_SPECIAL(val))
2754 : {
2755 78 : if (NUMERIC_IS_PINF(val))
2756 : {
2757 36 : if (NUMERIC_IS_PINF(base))
2758 24 : result = true; /* PINF = PINF */
2759 : else
2760 12 : result = !less; /* PINF > any other non-NAN */
2761 : }
2762 : else /* val must be NINF */
2763 : {
2764 42 : if (NUMERIC_IS_NINF(base))
2765 30 : result = true; /* NINF = NINF */
2766 : else
2767 12 : result = less; /* NINF < anything else */
2768 : }
2769 : }
2770 336 : else if (NUMERIC_IS_SPECIAL(base))
2771 : {
2772 24 : if (NUMERIC_IS_NINF(base))
2773 12 : result = !less; /* normal > NINF */
2774 : else
2775 12 : result = less; /* normal < PINF */
2776 : }
2777 : else
2778 : {
2779 : /*
2780 : * Otherwise go ahead and compute base +/- offset. While it's
2781 : * possible for this to overflow the numeric format, it's unlikely
2782 : * enough that we don't take measures to prevent it.
2783 : */
2784 : NumericVar valv;
2785 : NumericVar basev;
2786 : NumericVar offsetv;
2787 : NumericVar sum;
2788 :
2789 312 : init_var_from_num(val, &valv);
2790 312 : init_var_from_num(base, &basev);
2791 312 : init_var_from_num(offset, &offsetv);
2792 312 : init_var(&sum);
2793 :
2794 312 : if (sub)
2795 156 : sub_var(&basev, &offsetv, &sum);
2796 : else
2797 156 : add_var(&basev, &offsetv, &sum);
2798 :
2799 312 : if (less)
2800 156 : result = (cmp_var(&valv, &sum) <= 0);
2801 : else
2802 156 : result = (cmp_var(&valv, &sum) >= 0);
2803 :
2804 312 : free_var(&sum);
2805 : }
2806 :
2807 1146 : PG_FREE_IF_COPY(val, 0);
2808 1146 : PG_FREE_IF_COPY(base, 1);
2809 1146 : PG_FREE_IF_COPY(offset, 2);
2810 :
2811 1146 : PG_RETURN_BOOL(result);
2812 : }
2813 :
2814 : Datum
2815 607516 : hash_numeric(PG_FUNCTION_ARGS)
2816 : {
2817 607516 : Numeric key = PG_GETARG_NUMERIC(0);
2818 : Datum digit_hash;
2819 : Datum result;
2820 : int weight;
2821 : int start_offset;
2822 : int end_offset;
2823 : int i;
2824 : int hash_len;
2825 : NumericDigit *digits;
2826 :
2827 : /* If it's NaN or infinity, don't try to hash the rest of the fields */
2828 607516 : if (NUMERIC_IS_SPECIAL(key))
2829 0 : PG_RETURN_UINT32(0);
2830 :
2831 607516 : weight = NUMERIC_WEIGHT(key);
2832 607516 : start_offset = 0;
2833 607516 : end_offset = 0;
2834 :
2835 : /*
2836 : * Omit any leading or trailing zeros from the input to the hash. The
2837 : * numeric implementation *should* guarantee that leading and trailing
2838 : * zeros are suppressed, but we're paranoid. Note that we measure the
2839 : * starting and ending offsets in units of NumericDigits, not bytes.
2840 : */
2841 607516 : digits = NUMERIC_DIGITS(key);
2842 607516 : for (i = 0; i < NUMERIC_NDIGITS(key); i++)
2843 : {
2844 605888 : if (digits[i] != (NumericDigit) 0)
2845 605888 : break;
2846 :
2847 0 : start_offset++;
2848 :
2849 : /*
2850 : * The weight is effectively the # of digits before the decimal point,
2851 : * so decrement it for each leading zero we skip.
2852 : */
2853 0 : weight--;
2854 : }
2855 :
2856 : /*
2857 : * If there are no non-zero digits, then the value of the number is zero,
2858 : * regardless of any other fields.
2859 : */
2860 607516 : if (NUMERIC_NDIGITS(key) == start_offset)
2861 1628 : PG_RETURN_UINT32(-1);
2862 :
2863 605888 : for (i = NUMERIC_NDIGITS(key) - 1; i >= 0; i--)
2864 : {
2865 605888 : if (digits[i] != (NumericDigit) 0)
2866 605888 : break;
2867 :
2868 0 : end_offset++;
2869 : }
2870 :
2871 : /* If we get here, there should be at least one non-zero digit */
2872 : Assert(start_offset + end_offset < NUMERIC_NDIGITS(key));
2873 :
2874 : /*
2875 : * Note that we don't hash on the Numeric's scale, since two numerics can
2876 : * compare equal but have different scales. We also don't hash on the
2877 : * sign, although we could: since a sign difference implies inequality,
2878 : * this shouldn't affect correctness.
2879 : */
2880 605888 : hash_len = NUMERIC_NDIGITS(key) - start_offset - end_offset;
2881 605888 : digit_hash = hash_any((unsigned char *) (NUMERIC_DIGITS(key) + start_offset),
2882 : hash_len * sizeof(NumericDigit));
2883 :
2884 : /* Mix in the weight, via XOR */
2885 605888 : result = digit_hash ^ weight;
2886 :
2887 605888 : PG_RETURN_DATUM(result);
2888 : }
2889 :
2890 : /*
2891 : * Returns 64-bit value by hashing a value to a 64-bit value, with a seed.
2892 : * Otherwise, similar to hash_numeric.
2893 : */
2894 : Datum
2895 84 : hash_numeric_extended(PG_FUNCTION_ARGS)
2896 : {
2897 84 : Numeric key = PG_GETARG_NUMERIC(0);
2898 84 : uint64 seed = PG_GETARG_INT64(1);
2899 : Datum digit_hash;
2900 : Datum result;
2901 : int weight;
2902 : int start_offset;
2903 : int end_offset;
2904 : int i;
2905 : int hash_len;
2906 : NumericDigit *digits;
2907 :
2908 : /* If it's NaN or infinity, don't try to hash the rest of the fields */
2909 84 : if (NUMERIC_IS_SPECIAL(key))
2910 0 : PG_RETURN_UINT64(seed);
2911 :
2912 84 : weight = NUMERIC_WEIGHT(key);
2913 84 : start_offset = 0;
2914 84 : end_offset = 0;
2915 :
2916 84 : digits = NUMERIC_DIGITS(key);
2917 84 : for (i = 0; i < NUMERIC_NDIGITS(key); i++)
2918 : {
2919 72 : if (digits[i] != (NumericDigit) 0)
2920 72 : break;
2921 :
2922 0 : start_offset++;
2923 :
2924 0 : weight--;
2925 : }
2926 :
2927 84 : if (NUMERIC_NDIGITS(key) == start_offset)
2928 12 : PG_RETURN_UINT64(seed - 1);
2929 :
2930 72 : for (i = NUMERIC_NDIGITS(key) - 1; i >= 0; i--)
2931 : {
2932 72 : if (digits[i] != (NumericDigit) 0)
2933 72 : break;
2934 :
2935 0 : end_offset++;
2936 : }
2937 :
2938 : Assert(start_offset + end_offset < NUMERIC_NDIGITS(key));
2939 :
2940 72 : hash_len = NUMERIC_NDIGITS(key) - start_offset - end_offset;
2941 72 : digit_hash = hash_any_extended((unsigned char *) (NUMERIC_DIGITS(key)
2942 72 : + start_offset),
2943 : hash_len * sizeof(NumericDigit),
2944 : seed);
2945 :
2946 72 : result = UInt64GetDatum(DatumGetUInt64(digit_hash) ^ weight);
2947 :
2948 72 : PG_RETURN_DATUM(result);
2949 : }
2950 :
2951 :
2952 : /* ----------------------------------------------------------------------
2953 : *
2954 : * Basic arithmetic functions
2955 : *
2956 : * ----------------------------------------------------------------------
2957 : */
2958 :
2959 :
2960 : /*
2961 : * numeric_add() -
2962 : *
2963 : * Add two numerics
2964 : */
2965 : Datum
2966 252118 : numeric_add(PG_FUNCTION_ARGS)
2967 : {
2968 252118 : Numeric num1 = PG_GETARG_NUMERIC(0);
2969 252118 : Numeric num2 = PG_GETARG_NUMERIC(1);
2970 : Numeric res;
2971 :
2972 252118 : res = numeric_add_opt_error(num1, num2, NULL);
2973 :
2974 252118 : PG_RETURN_NUMERIC(res);
2975 : }
2976 :
2977 : /*
2978 : * numeric_add_opt_error() -
2979 : *
2980 : * Internal version of numeric_add(). If "*have_error" flag is provided,
2981 : * on error it's set to true, NULL returned. This is helpful when caller
2982 : * need to handle errors by itself.
2983 : */
2984 : Numeric
2985 253156 : numeric_add_opt_error(Numeric num1, Numeric num2, bool *have_error)
2986 : {
2987 : NumericVar arg1;
2988 : NumericVar arg2;
2989 : NumericVar result;
2990 : Numeric res;
2991 :
2992 : /*
2993 : * Handle NaN and infinities
2994 : */
2995 253156 : if (NUMERIC_IS_SPECIAL(num1) || NUMERIC_IS_SPECIAL(num2))
2996 : {
2997 198 : if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
2998 78 : return make_result(&const_nan);
2999 120 : if (NUMERIC_IS_PINF(num1))
3000 : {
3001 36 : if (NUMERIC_IS_NINF(num2))
3002 6 : return make_result(&const_nan); /* Inf + -Inf */
3003 : else
3004 30 : return make_result(&const_pinf);
3005 : }
3006 84 : if (NUMERIC_IS_NINF(num1))
3007 : {
3008 36 : if (NUMERIC_IS_PINF(num2))
3009 6 : return make_result(&const_nan); /* -Inf + Inf */
3010 : else
3011 30 : return make_result(&const_ninf);
3012 : }
3013 : /* by here, num1 must be finite, so num2 is not */
3014 48 : if (NUMERIC_IS_PINF(num2))
3015 24 : return make_result(&const_pinf);
3016 : Assert(NUMERIC_IS_NINF(num2));
3017 24 : return make_result(&const_ninf);
3018 : }
3019 :
3020 : /*
3021 : * Unpack the values, let add_var() compute the result and return it.
3022 : */
3023 252958 : init_var_from_num(num1, &arg1);
3024 252958 : init_var_from_num(num2, &arg2);
3025 :
3026 252958 : init_var(&result);
3027 252958 : add_var(&arg1, &arg2, &result);
3028 :
3029 252958 : res = make_result_opt_error(&result, have_error);
3030 :
3031 252958 : free_var(&result);
3032 :
3033 252958 : return res;
3034 : }
3035 :
3036 :
3037 : /*
3038 : * numeric_sub() -
3039 : *
3040 : * Subtract one numeric from another
3041 : */
3042 : Datum
3043 91856 : numeric_sub(PG_FUNCTION_ARGS)
3044 : {
3045 91856 : Numeric num1 = PG_GETARG_NUMERIC(0);
3046 91856 : Numeric num2 = PG_GETARG_NUMERIC(1);
3047 : Numeric res;
3048 :
3049 91856 : res = numeric_sub_opt_error(num1, num2, NULL);
3050 :
3051 91856 : PG_RETURN_NUMERIC(res);
3052 : }
3053 :
3054 :
3055 : /*
3056 : * numeric_sub_opt_error() -
3057 : *
3058 : * Internal version of numeric_sub(). If "*have_error" flag is provided,
3059 : * on error it's set to true, NULL returned. This is helpful when caller
3060 : * need to handle errors by itself.
3061 : */
3062 : Numeric
3063 92006 : numeric_sub_opt_error(Numeric num1, Numeric num2, bool *have_error)
3064 : {
3065 : NumericVar arg1;
3066 : NumericVar arg2;
3067 : NumericVar result;
3068 : Numeric res;
3069 :
3070 : /*
3071 : * Handle NaN and infinities
3072 : */
3073 92006 : if (NUMERIC_IS_SPECIAL(num1) || NUMERIC_IS_SPECIAL(num2))
3074 : {
3075 2440 : if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
3076 2320 : return make_result(&const_nan);
3077 120 : if (NUMERIC_IS_PINF(num1))
3078 : {
3079 36 : if (NUMERIC_IS_PINF(num2))
3080 6 : return make_result(&const_nan); /* Inf - Inf */
3081 : else
3082 30 : return make_result(&const_pinf);
3083 : }
3084 84 : if (NUMERIC_IS_NINF(num1))
3085 : {
3086 36 : if (NUMERIC_IS_NINF(num2))
3087 6 : return make_result(&const_nan); /* -Inf - -Inf */
3088 : else
3089 30 : return make_result(&const_ninf);
3090 : }
3091 : /* by here, num1 must be finite, so num2 is not */
3092 48 : if (NUMERIC_IS_PINF(num2))
3093 24 : return make_result(&const_ninf);
3094 : Assert(NUMERIC_IS_NINF(num2));
3095 24 : return make_result(&const_pinf);
3096 : }
3097 :
3098 : /*
3099 : * Unpack the values, let sub_var() compute the result and return it.
3100 : */
3101 89566 : init_var_from_num(num1, &arg1);
3102 89566 : init_var_from_num(num2, &arg2);
3103 :
3104 89566 : init_var(&result);
3105 89566 : sub_var(&arg1, &arg2, &result);
3106 :
3107 89566 : res = make_result_opt_error(&result, have_error);
3108 :
3109 89566 : free_var(&result);
3110 :
3111 89566 : return res;
3112 : }
3113 :
3114 :
3115 : /*
3116 : * numeric_mul() -
3117 : *
3118 : * Calculate the product of two numerics
3119 : */
3120 : Datum
3121 489704 : numeric_mul(PG_FUNCTION_ARGS)
3122 : {
3123 489704 : Numeric num1 = PG_GETARG_NUMERIC(0);
3124 489704 : Numeric num2 = PG_GETARG_NUMERIC(1);
3125 : Numeric res;
3126 :
3127 489704 : res = numeric_mul_opt_error(num1, num2, NULL);
3128 :
3129 489704 : PG_RETURN_NUMERIC(res);
3130 : }
3131 :
3132 :
3133 : /*
3134 : * numeric_mul_opt_error() -
3135 : *
3136 : * Internal version of numeric_mul(). If "*have_error" flag is provided,
3137 : * on error it's set to true, NULL returned. This is helpful when caller
3138 : * need to handle errors by itself.
3139 : */
3140 : Numeric
3141 489740 : numeric_mul_opt_error(Numeric num1, Numeric num2, bool *have_error)
3142 : {
3143 : NumericVar arg1;
3144 : NumericVar arg2;
3145 : NumericVar result;
3146 : Numeric res;
3147 :
3148 : /*
3149 : * Handle NaN and infinities
3150 : */
3151 489740 : if (NUMERIC_IS_SPECIAL(num1) || NUMERIC_IS_SPECIAL(num2))
3152 : {
3153 198 : if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
3154 78 : return make_result(&const_nan);
3155 120 : if (NUMERIC_IS_PINF(num1))
3156 : {
3157 36 : switch (numeric_sign_internal(num2))
3158 : {
3159 6 : case 0:
3160 6 : return make_result(&const_nan); /* Inf * 0 */
3161 18 : case 1:
3162 18 : return make_result(&const_pinf);
3163 12 : case -1:
3164 12 : return make_result(&const_ninf);
3165 : }
3166 : Assert(false);
3167 : }
3168 84 : if (NUMERIC_IS_NINF(num1))
3169 : {
3170 36 : switch (numeric_sign_internal(num2))
3171 : {
3172 6 : case 0:
3173 6 : return make_result(&const_nan); /* -Inf * 0 */
3174 18 : case 1:
3175 18 : return make_result(&const_ninf);
3176 12 : case -1:
3177 12 : return make_result(&const_pinf);
3178 : }
3179 : Assert(false);
3180 : }
3181 : /* by here, num1 must be finite, so num2 is not */
3182 48 : if (NUMERIC_IS_PINF(num2))
3183 : {
3184 24 : switch (numeric_sign_internal(num1))
3185 : {
3186 6 : case 0:
3187 6 : return make_result(&const_nan); /* 0 * Inf */
3188 12 : case 1:
3189 12 : return make_result(&const_pinf);
3190 6 : case -1:
3191 6 : return make_result(&const_ninf);
3192 : }
3193 : Assert(false);
3194 : }
3195 : Assert(NUMERIC_IS_NINF(num2));
3196 24 : switch (numeric_sign_internal(num1))
3197 : {
3198 6 : case 0:
3199 6 : return make_result(&const_nan); /* 0 * -Inf */
3200 12 : case 1:
3201 12 : return make_result(&const_ninf);
3202 6 : case -1:
3203 6 : return make_result(&const_pinf);
3204 : }
3205 : Assert(false);
3206 : }
3207 :
3208 : /*
3209 : * Unpack the values, let mul_var() compute the result and return it.
3210 : * Unlike add_var() and sub_var(), mul_var() will round its result. In the
3211 : * case of numeric_mul(), which is invoked for the * operator on numerics,
3212 : * we request exact representation for the product (rscale = sum(dscale of
3213 : * arg1, dscale of arg2)). If the exact result has more digits after the
3214 : * decimal point than can be stored in a numeric, we round it. Rounding
3215 : * after computing the exact result ensures that the final result is
3216 : * correctly rounded (rounding in mul_var() using a truncated product
3217 : * would not guarantee this).
3218 : */
3219 489542 : init_var_from_num(num1, &arg1);
3220 489542 : init_var_from_num(num2, &arg2);
3221 :
3222 489542 : init_var(&result);
3223 489542 : mul_var(&arg1, &arg2, &result, arg1.dscale + arg2.dscale);
3224 :
3225 489542 : if (result.dscale > NUMERIC_DSCALE_MAX)
3226 6 : round_var(&result, NUMERIC_DSCALE_MAX);
3227 :
3228 489542 : res = make_result_opt_error(&result, have_error);
3229 :
3230 489542 : free_var(&result);
3231 :
3232 489542 : return res;
3233 : }
3234 :
3235 :
3236 : /*
3237 : * numeric_div() -
3238 : *
3239 : * Divide one numeric into another
3240 : */
3241 : Datum
3242 151050 : numeric_div(PG_FUNCTION_ARGS)
3243 : {
3244 151050 : Numeric num1 = PG_GETARG_NUMERIC(0);
3245 151050 : Numeric num2 = PG_GETARG_NUMERIC(1);
3246 : Numeric res;
3247 :
3248 151050 : res = numeric_div_opt_error(num1, num2, NULL);
3249 :
3250 151018 : PG_RETURN_NUMERIC(res);
3251 : }
3252 :
3253 :
3254 : /*
3255 : * numeric_div_opt_error() -
3256 : *
3257 : * Internal version of numeric_div(). If "*have_error" flag is provided,
3258 : * on error it's set to true, NULL returned. This is helpful when caller
3259 : * need to handle errors by itself.
3260 : */
3261 : Numeric
3262 151890 : numeric_div_opt_error(Numeric num1, Numeric num2, bool *have_error)
3263 : {
3264 : NumericVar arg1;
3265 : NumericVar arg2;
3266 : NumericVar result;
3267 : Numeric res;
3268 : int rscale;
3269 :
3270 151890 : if (have_error)
3271 48 : *have_error = false;
3272 :
3273 : /*
3274 : * Handle NaN and infinities
3275 : */
3276 151890 : if (NUMERIC_IS_SPECIAL(num1) || NUMERIC_IS_SPECIAL(num2))
3277 : {
3278 198 : if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
3279 78 : return make_result(&const_nan);
3280 120 : if (NUMERIC_IS_PINF(num1))
3281 : {
3282 36 : if (NUMERIC_IS_SPECIAL(num2))
3283 12 : return make_result(&const_nan); /* Inf / [-]Inf */
3284 24 : switch (numeric_sign_internal(num2))
3285 : {
3286 6 : case 0:
3287 6 : if (have_error)
3288 : {
3289 0 : *have_error = true;
3290 0 : return NULL;
3291 : }
3292 6 : ereport(ERROR,
3293 : (errcode(ERRCODE_DIVISION_BY_ZERO),
3294 : errmsg("division by zero")));
3295 : break;
3296 12 : case 1:
3297 12 : return make_result(&const_pinf);
3298 6 : case -1:
3299 6 : return make_result(&const_ninf);
3300 : }
3301 84 : Assert(false);
3302 : }
3303 84 : if (NUMERIC_IS_NINF(num1))
3304 : {
3305 36 : if (NUMERIC_IS_SPECIAL(num2))
3306 12 : return make_result(&const_nan); /* -Inf / [-]Inf */
3307 24 : switch (numeric_sign_internal(num2))
3308 : {
3309 6 : case 0:
3310 6 : if (have_error)
3311 : {
3312 0 : *have_error = true;
3313 0 : return NULL;
3314 : }
3315 6 : ereport(ERROR,
3316 : (errcode(ERRCODE_DIVISION_BY_ZERO),
3317 : errmsg("division by zero")));
3318 : break;
3319 12 : case 1:
3320 12 : return make_result(&const_ninf);
3321 6 : case -1:
3322 6 : return make_result(&const_pinf);
3323 : }
3324 48 : Assert(false);
3325 : }
3326 : /* by here, num1 must be finite, so num2 is not */
3327 :
3328 : /*
3329 : * POSIX would have us return zero or minus zero if num1 is zero, and
3330 : * otherwise throw an underflow error. But the numeric type doesn't
3331 : * really do underflow, so let's just return zero.
3332 : */
3333 48 : return make_result(&const_zero);
3334 : }
3335 :
3336 : /*
3337 : * Unpack the arguments
3338 : */
3339 151692 : init_var_from_num(num1, &arg1);
3340 151692 : init_var_from_num(num2, &arg2);
3341 :
3342 151692 : init_var(&result);
3343 :
3344 : /*
3345 : * Select scale for division result
3346 : */
3347 151692 : rscale = select_div_scale(&arg1, &arg2);
3348 :
3349 : /*
3350 : * If "have_error" is provided, check for division by zero here
3351 : */
3352 151692 : if (have_error && (arg2.ndigits == 0 || arg2.digits[0] == 0))
3353 : {
3354 12 : *have_error = true;
3355 12 : return NULL;
3356 : }
3357 :
3358 : /*
3359 : * Do the divide and return the result
3360 : */
3361 151680 : div_var(&arg1, &arg2, &result, rscale, true, true);
3362 :
3363 151642 : res = make_result_opt_error(&result, have_error);
3364 :
3365 151642 : free_var(&result);
3366 :
3367 151642 : return res;
3368 : }
3369 :
3370 :
3371 : /*
3372 : * numeric_div_trunc() -
3373 : *
3374 : * Divide one numeric into another, truncating the result to an integer
3375 : */
3376 : Datum
3377 1218 : numeric_div_trunc(PG_FUNCTION_ARGS)
3378 : {
3379 1218 : Numeric num1 = PG_GETARG_NUMERIC(0);
3380 1218 : Numeric num2 = PG_GETARG_NUMERIC(1);
3381 : NumericVar arg1;
3382 : NumericVar arg2;
3383 : NumericVar result;
3384 : Numeric res;
3385 :
3386 : /*
3387 : * Handle NaN and infinities
3388 : */
3389 1218 : if (NUMERIC_IS_SPECIAL(num1) || NUMERIC_IS_SPECIAL(num2))
3390 : {
3391 198 : if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
3392 78 : PG_RETURN_NUMERIC(make_result(&const_nan));
3393 120 : if (NUMERIC_IS_PINF(num1))
3394 : {
3395 36 : if (NUMERIC_IS_SPECIAL(num2))
3396 12 : PG_RETURN_NUMERIC(make_result(&const_nan)); /* Inf / [-]Inf */
3397 24 : switch (numeric_sign_internal(num2))
3398 : {
3399 6 : case 0:
3400 6 : ereport(ERROR,
3401 : (errcode(ERRCODE_DIVISION_BY_ZERO),
3402 : errmsg("division by zero")));
3403 : break;
3404 12 : case 1:
3405 12 : PG_RETURN_NUMERIC(make_result(&const_pinf));
3406 6 : case -1:
3407 6 : PG_RETURN_NUMERIC(make_result(&const_ninf));
3408 : }
3409 84 : Assert(false);
3410 : }
3411 84 : if (NUMERIC_IS_NINF(num1))
3412 : {
3413 36 : if (NUMERIC_IS_SPECIAL(num2))
3414 12 : PG_RETURN_NUMERIC(make_result(&const_nan)); /* -Inf / [-]Inf */
3415 24 : switch (numeric_sign_internal(num2))
3416 : {
3417 6 : case 0:
3418 6 : ereport(ERROR,
3419 : (errcode(ERRCODE_DIVISION_BY_ZERO),
3420 : errmsg("division by zero")));
3421 : break;
3422 12 : case 1:
3423 12 : PG_RETURN_NUMERIC(make_result(&const_ninf));
3424 6 : case -1:
3425 6 : PG_RETURN_NUMERIC(make_result(&const_pinf));
3426 : }
3427 48 : Assert(false);
3428 : }
3429 : /* by here, num1 must be finite, so num2 is not */
3430 :
3431 : /*
3432 : * POSIX would have us return zero or minus zero if num1 is zero, and
3433 : * otherwise throw an underflow error. But the numeric type doesn't
3434 : * really do underflow, so let's just return zero.
3435 : */
3436 48 : PG_RETURN_NUMERIC(make_result(&const_zero));
3437 : }
3438 :
3439 : /*
3440 : * Unpack the arguments
3441 : */
3442 1020 : init_var_from_num(num1, &arg1);
3443 1020 : init_var_from_num(num2, &arg2);
3444 :
3445 1020 : init_var(&result);
3446 :
3447 : /*
3448 : * Do the divide and return the result
3449 : */
3450 1020 : div_var(&arg1, &arg2, &result, 0, false, true);
3451 :
3452 1014 : res = make_result(&result);
3453 :
3454 1014 : free_var(&result);
3455 :
3456 1014 : PG_RETURN_NUMERIC(res);
3457 : }
3458 :
3459 :
3460 : /*
3461 : * numeric_mod() -
3462 : *
3463 : * Calculate the modulo of two numerics
3464 : */
3465 : Datum
3466 53402 : numeric_mod(PG_FUNCTION_ARGS)
3467 : {
3468 53402 : Numeric num1 = PG_GETARG_NUMERIC(0);
3469 53402 : Numeric num2 = PG_GETARG_NUMERIC(1);
3470 : Numeric res;
3471 :
3472 53402 : res = numeric_mod_opt_error(num1, num2, NULL);
3473 :
3474 53384 : PG_RETURN_NUMERIC(res);
3475 : }
3476 :
3477 :
3478 : /*
3479 : * numeric_mod_opt_error() -
3480 : *
3481 : * Internal version of numeric_mod(). If "*have_error" flag is provided,
3482 : * on error it's set to true, NULL returned. This is helpful when caller
3483 : * need to handle errors by itself.
3484 : */
3485 : Numeric
3486 53414 : numeric_mod_opt_error(Numeric num1, Numeric num2, bool *have_error)
3487 : {
3488 : Numeric res;
3489 : NumericVar arg1;
3490 : NumericVar arg2;
3491 : NumericVar result;
3492 :
3493 53414 : if (have_error)
3494 0 : *have_error = false;
3495 :
3496 : /*
3497 : * Handle NaN and infinities. We follow POSIX fmod() on this, except that
3498 : * POSIX treats x-is-infinite and y-is-zero identically, raising EDOM and
3499 : * returning NaN. We choose to throw error only for y-is-zero.
3500 : */
3501 53414 : if (NUMERIC_IS_SPECIAL(num1) || NUMERIC_IS_SPECIAL(num2))
3502 : {
3503 198 : if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
3504 78 : return make_result(&const_nan);
3505 120 : if (NUMERIC_IS_INF(num1))
3506 : {
3507 72 : if (numeric_sign_internal(num2) == 0)
3508 : {
3509 12 : if (have_error)
3510 : {
3511 0 : *have_error = true;
3512 0 : return NULL;
3513 : }
3514 12 : ereport(ERROR,
3515 : (errcode(ERRCODE_DIVISION_BY_ZERO),
3516 : errmsg("division by zero")));
3517 : }
3518 : /* Inf % any nonzero = NaN */
3519 60 : return make_result(&const_nan);
3520 : }
3521 : /* num2 must be [-]Inf; result is num1 regardless of sign of num2 */
3522 48 : return duplicate_numeric(num1);
3523 : }
3524 :
3525 53216 : init_var_from_num(num1, &arg1);
3526 53216 : init_var_from_num(num2, &arg2);
3527 :
3528 53216 : init_var(&result);
3529 :
3530 : /*
3531 : * If "have_error" is provided, check for division by zero here
3532 : */
3533 53216 : if (have_error && (arg2.ndigits == 0 || arg2.digits[0] == 0))
3534 : {
3535 0 : *have_error = true;
3536 0 : return NULL;
3537 : }
3538 :
3539 53216 : mod_var(&arg1, &arg2, &result);
3540 :
3541 53204 : res = make_result_opt_error(&result, NULL);
3542 :
3543 53204 : free_var(&result);
3544 :
3545 53204 : return res;
3546 : }
3547 :
3548 :
3549 : /*
3550 : * numeric_inc() -
3551 : *
3552 : * Increment a number by one
3553 : */
3554 : Datum
3555 48 : numeric_inc(PG_FUNCTION_ARGS)
3556 : {
3557 48 : Numeric num = PG_GETARG_NUMERIC(0);
3558 : NumericVar arg;
3559 : Numeric res;
3560 :
3561 : /*
3562 : * Handle NaN and infinities
3563 : */
3564 48 : if (NUMERIC_IS_SPECIAL(num))
3565 18 : PG_RETURN_NUMERIC(duplicate_numeric(num));
3566 :
3567 : /*
3568 : * Compute the result and return it
3569 : */
3570 30 : init_var_from_num(num, &arg);
3571 :
3572 30 : add_var(&arg, &const_one, &arg);
3573 :
3574 30 : res = make_result(&arg);
3575 :
3576 30 : free_var(&arg);
3577 :
3578 30 : PG_RETURN_NUMERIC(res);
3579 : }
3580 :
3581 :
3582 : /*
3583 : * numeric_smaller() -
3584 : *
3585 : * Return the smaller of two numbers
3586 : */
3587 : Datum
3588 798 : numeric_smaller(PG_FUNCTION_ARGS)
3589 : {
3590 798 : Numeric num1 = PG_GETARG_NUMERIC(0);
3591 798 : Numeric num2 = PG_GETARG_NUMERIC(1);
3592 :
3593 : /*
3594 : * Use cmp_numerics so that this will agree with the comparison operators,
3595 : * particularly as regards comparisons involving NaN.
3596 : */
3597 798 : if (cmp_numerics(num1, num2) < 0)
3598 640 : PG_RETURN_NUMERIC(num1);
3599 : else
3600 158 : PG_RETURN_NUMERIC(num2);
3601 : }
3602 :
3603 :
3604 : /*
3605 : * numeric_larger() -
3606 : *
3607 : * Return the larger of two numbers
3608 : */
3609 : Datum
3610 18630 : numeric_larger(PG_FUNCTION_ARGS)
3611 : {
3612 18630 : Numeric num1 = PG_GETARG_NUMERIC(0);
3613 18630 : Numeric num2 = PG_GETARG_NUMERIC(1);
3614 :
3615 : /*
3616 : * Use cmp_numerics so that this will agree with the comparison operators,
3617 : * particularly as regards comparisons involving NaN.
3618 : */
3619 18630 : if (cmp_numerics(num1, num2) > 0)
3620 18078 : PG_RETURN_NUMERIC(num1);
3621 : else
3622 552 : PG_RETURN_NUMERIC(num2);
3623 : }
3624 :
3625 :
3626 : /* ----------------------------------------------------------------------
3627 : *
3628 : * Advanced math functions
3629 : *
3630 : * ----------------------------------------------------------------------
3631 : */
3632 :
3633 : /*
3634 : * numeric_gcd() -
3635 : *
3636 : * Calculate the greatest common divisor of two numerics
3637 : */
3638 : Datum
3639 216 : numeric_gcd(PG_FUNCTION_ARGS)
3640 : {
3641 216 : Numeric num1 = PG_GETARG_NUMERIC(0);
3642 216 : Numeric num2 = PG_GETARG_NUMERIC(1);
3643 : NumericVar arg1;
3644 : NumericVar arg2;
3645 : NumericVar result;
3646 : Numeric res;
3647 :
3648 : /*
3649 : * Handle NaN and infinities: we consider the result to be NaN in all such
3650 : * cases.
3651 : */
3652 216 : if (NUMERIC_IS_SPECIAL(num1) || NUMERIC_IS_SPECIAL(num2))
3653 96 : PG_RETURN_NUMERIC(make_result(&const_nan));
3654 :
3655 : /*
3656 : * Unpack the arguments
3657 : */
3658 120 : init_var_from_num(num1, &arg1);
3659 120 : init_var_from_num(num2, &arg2);
3660 :
3661 120 : init_var(&result);
3662 :
3663 : /*
3664 : * Find the GCD and return the result
3665 : */
3666 120 : gcd_var(&arg1, &arg2, &result);
3667 :
3668 120 : res = make_result(&result);
3669 :
3670 120 : free_var(&result);
3671 :
3672 120 : PG_RETURN_NUMERIC(res);
3673 : }
3674 :
3675 :
3676 : /*
3677 : * numeric_lcm() -
3678 : *
3679 : * Calculate the least common multiple of two numerics
3680 : */
3681 : Datum
3682 246 : numeric_lcm(PG_FUNCTION_ARGS)
3683 : {
3684 246 : Numeric num1 = PG_GETARG_NUMERIC(0);
3685 246 : Numeric num2 = PG_GETARG_NUMERIC(1);
3686 : NumericVar arg1;
3687 : NumericVar arg2;
3688 : NumericVar result;
3689 : Numeric res;
3690 :
3691 : /*
3692 : * Handle NaN and infinities: we consider the result to be NaN in all such
3693 : * cases.
3694 : */
3695 246 : if (NUMERIC_IS_SPECIAL(num1) || NUMERIC_IS_SPECIAL(num2))
3696 96 : PG_RETURN_NUMERIC(make_result(&const_nan));
3697 :
3698 : /*
3699 : * Unpack the arguments
3700 : */
3701 150 : init_var_from_num(num1, &arg1);
3702 150 : init_var_from_num(num2, &arg2);
3703 :
3704 150 : init_var(&result);
3705 :
3706 : /*
3707 : * Compute the result using lcm(x, y) = abs(x / gcd(x, y) * y), returning
3708 : * zero if either input is zero.
3709 : *
3710 : * Note that the division is guaranteed to be exact, returning an integer
3711 : * result, so the LCM is an integral multiple of both x and y. A display
3712 : * scale of Min(x.dscale, y.dscale) would be sufficient to represent it,
3713 : * but as with other numeric functions, we choose to return a result whose
3714 : * display scale is no smaller than either input.
3715 : */
3716 150 : if (arg1.ndigits == 0 || arg2.ndigits == 0)
3717 48 : set_var_from_var(&const_zero, &result);
3718 : else
3719 : {
3720 102 : gcd_var(&arg1, &arg2, &result);
3721 102 : div_var(&arg1, &result, &result, 0, false, true);
3722 102 : mul_var(&arg2, &result, &result, arg2.dscale);
3723 102 : result.sign = NUMERIC_POS;
3724 : }
3725 :
3726 150 : result.dscale = Max(arg1.dscale, arg2.dscale);
3727 :
3728 150 : res = make_result(&result);
3729 :
3730 144 : free_var(&result);
3731 :
3732 144 : PG_RETURN_NUMERIC(res);
3733 : }
3734 :
3735 :
3736 : /*
3737 : * numeric_fac()
3738 : *
3739 : * Compute factorial
3740 : */
3741 : Datum
3742 42 : numeric_fac(PG_FUNCTION_ARGS)
3743 : {
3744 42 : int64 num = PG_GETARG_INT64(0);
3745 : Numeric res;
3746 : NumericVar fact;
3747 : NumericVar result;
3748 :
3749 42 : if (num < 0)
3750 6 : ereport(ERROR,
3751 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
3752 : errmsg("factorial of a negative number is undefined")));
3753 36 : if (num <= 1)
3754 : {
3755 6 : res = make_result(&const_one);
3756 6 : PG_RETURN_NUMERIC(res);
3757 : }
3758 : /* Fail immediately if the result would overflow */
3759 30 : if (num > 32177)
3760 6 : ereport(ERROR,
3761 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
3762 : errmsg("value overflows numeric format")));
3763 :
3764 24 : init_var(&fact);
3765 24 : init_var(&result);
3766 :
3767 24 : int64_to_numericvar(num, &result);
3768 :
3769 294 : for (num = num - 1; num > 1; num--)
3770 : {
3771 : /* this loop can take awhile, so allow it to be interrupted */
3772 270 : CHECK_FOR_INTERRUPTS();
3773 :
3774 270 : int64_to_numericvar(num, &fact);
3775 :
3776 270 : mul_var(&result, &fact, &result, 0);
3777 : }
3778 :
3779 24 : res = make_result(&result);
3780 :
3781 24 : free_var(&fact);
3782 24 : free_var(&result);
3783 :
3784 24 : PG_RETURN_NUMERIC(res);
3785 : }
3786 :
3787 :
3788 : /*
3789 : * numeric_sqrt() -
3790 : *
3791 : * Compute the square root of a numeric.
3792 : */
3793 : Datum
3794 150 : numeric_sqrt(PG_FUNCTION_ARGS)
3795 : {
3796 150 : Numeric num = PG_GETARG_NUMERIC(0);
3797 : Numeric res;
3798 : NumericVar arg;
3799 : NumericVar result;
3800 : int sweight;
3801 : int rscale;
3802 :
3803 : /*
3804 : * Handle NaN and infinities
3805 : */
3806 150 : if (NUMERIC_IS_SPECIAL(num))
3807 : {
3808 : /* error should match that in sqrt_var() */
3809 18 : if (NUMERIC_IS_NINF(num))
3810 6 : ereport(ERROR,
3811 : (errcode(ERRCODE_INVALID_ARGUMENT_FOR_POWER_FUNCTION),
3812 : errmsg("cannot take square root of a negative number")));
3813 : /* For NAN or PINF, just duplicate the input */
3814 12 : PG_RETURN_NUMERIC(duplicate_numeric(num));
3815 : }
3816 :
3817 : /*
3818 : * Unpack the argument and determine the result scale. We choose a scale
3819 : * to give at least NUMERIC_MIN_SIG_DIGITS significant digits; but in any
3820 : * case not less than the input's dscale.
3821 : */
3822 132 : init_var_from_num(num, &arg);
3823 :
3824 132 : init_var(&result);
3825 :
3826 : /*
3827 : * Assume the input was normalized, so arg.weight is accurate. The result
3828 : * then has at least sweight = floor(arg.weight * DEC_DIGITS / 2 + 1)
3829 : * digits before the decimal point. When DEC_DIGITS is even, we can save
3830 : * a few cycles, since the division is exact and there is no need to round
3831 : * towards negative infinity.
3832 : */
3833 : #if DEC_DIGITS == ((DEC_DIGITS / 2) * 2)
3834 132 : sweight = arg.weight * DEC_DIGITS / 2 + 1;
3835 : #else
3836 : if (arg.weight >= 0)
3837 : sweight = arg.weight * DEC_DIGITS / 2 + 1;
3838 : else
3839 : sweight = 1 - (1 - arg.weight * DEC_DIGITS) / 2;
3840 : #endif
3841 :
3842 132 : rscale = NUMERIC_MIN_SIG_DIGITS - sweight;
3843 132 : rscale = Max(rscale, arg.dscale);
3844 132 : rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
3845 132 : rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
3846 :
3847 : /*
3848 : * Let sqrt_var() do the calculation and return the result.
3849 : */
3850 132 : sqrt_var(&arg, &result, rscale);
3851 :
3852 126 : res = make_result(&result);
3853 :
3854 126 : free_var(&result);
3855 :
3856 126 : PG_RETURN_NUMERIC(res);
3857 : }
3858 :
3859 :
3860 : /*
3861 : * numeric_exp() -
3862 : *
3863 : * Raise e to the power of x
3864 : */
3865 : Datum
3866 78 : numeric_exp(PG_FUNCTION_ARGS)
3867 : {
3868 78 : Numeric num = PG_GETARG_NUMERIC(0);
3869 : Numeric res;
3870 : NumericVar arg;
3871 : NumericVar result;
3872 : int rscale;
3873 : double val;
3874 :
3875 : /*
3876 : * Handle NaN and infinities
3877 : */
3878 78 : if (NUMERIC_IS_SPECIAL(num))
3879 : {
3880 : /* Per POSIX, exp(-Inf) is zero */
3881 18 : if (NUMERIC_IS_NINF(num))
3882 6 : PG_RETURN_NUMERIC(make_result(&const_zero));
3883 : /* For NAN or PINF, just duplicate the input */
3884 12 : PG_RETURN_NUMERIC(duplicate_numeric(num));
3885 : }
3886 :
3887 : /*
3888 : * Unpack the argument and determine the result scale. We choose a scale
3889 : * to give at least NUMERIC_MIN_SIG_DIGITS significant digits; but in any
3890 : * case not less than the input's dscale.
3891 : */
3892 60 : init_var_from_num(num, &arg);
3893 :
3894 60 : init_var(&result);
3895 :
3896 : /* convert input to float8, ignoring overflow */
3897 60 : val = numericvar_to_double_no_overflow(&arg);
3898 :
3899 : /*
3900 : * log10(result) = num * log10(e), so this is approximately the decimal
3901 : * weight of the result:
3902 : */
3903 60 : val *= 0.434294481903252;
3904 :
3905 : /* limit to something that won't cause integer overflow */
3906 60 : val = Max(val, -NUMERIC_MAX_RESULT_SCALE);
3907 60 : val = Min(val, NUMERIC_MAX_RESULT_SCALE);
3908 :
3909 60 : rscale = NUMERIC_MIN_SIG_DIGITS - (int) val;
3910 60 : rscale = Max(rscale, arg.dscale);
3911 60 : rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
3912 60 : rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
3913 :
3914 : /*
3915 : * Let exp_var() do the calculation and return the result.
3916 : */
3917 60 : exp_var(&arg, &result, rscale);
3918 :
3919 60 : res = make_result(&result);
3920 :
3921 60 : free_var(&result);
3922 :
3923 60 : PG_RETURN_NUMERIC(res);
3924 : }
3925 :
3926 :
3927 : /*
3928 : * numeric_ln() -
3929 : *
3930 : * Compute the natural logarithm of x
3931 : */
3932 : Datum
3933 198 : numeric_ln(PG_FUNCTION_ARGS)
3934 : {
3935 198 : Numeric num = PG_GETARG_NUMERIC(0);
3936 : Numeric res;
3937 : NumericVar arg;
3938 : NumericVar result;
3939 : int ln_dweight;
3940 : int rscale;
3941 :
3942 : /*
3943 : * Handle NaN and infinities
3944 : */
3945 198 : if (NUMERIC_IS_SPECIAL(num))
3946 : {
3947 18 : if (NUMERIC_IS_NINF(num))
3948 6 : ereport(ERROR,
3949 : (errcode(ERRCODE_INVALID_ARGUMENT_FOR_LOG),
3950 : errmsg("cannot take logarithm of a negative number")));
3951 : /* For NAN or PINF, just duplicate the input */
3952 12 : PG_RETURN_NUMERIC(duplicate_numeric(num));
3953 : }
3954 :
3955 180 : init_var_from_num(num, &arg);
3956 180 : init_var(&result);
3957 :
3958 : /* Estimated dweight of logarithm */
3959 180 : ln_dweight = estimate_ln_dweight(&arg);
3960 :
3961 180 : rscale = NUMERIC_MIN_SIG_DIGITS - ln_dweight;
3962 180 : rscale = Max(rscale, arg.dscale);
3963 180 : rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
3964 180 : rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
3965 :
3966 180 : ln_var(&arg, &result, rscale);
3967 :
3968 156 : res = make_result(&result);
3969 :
3970 156 : free_var(&result);
3971 :
3972 156 : PG_RETURN_NUMERIC(res);
3973 : }
3974 :
3975 :
3976 : /*
3977 : * numeric_log() -
3978 : *
3979 : * Compute the logarithm of x in a given base
3980 : */
3981 : Datum
3982 342 : numeric_log(PG_FUNCTION_ARGS)
3983 : {
3984 342 : Numeric num1 = PG_GETARG_NUMERIC(0);
3985 342 : Numeric num2 = PG_GETARG_NUMERIC(1);
3986 : Numeric res;
3987 : NumericVar arg1;
3988 : NumericVar arg2;
3989 : NumericVar result;
3990 :
3991 : /*
3992 : * Handle NaN and infinities
3993 : */
3994 342 : if (NUMERIC_IS_SPECIAL(num1) || NUMERIC_IS_SPECIAL(num2))
3995 : {
3996 : int sign1,
3997 : sign2;
3998 :
3999 126 : if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
4000 54 : PG_RETURN_NUMERIC(make_result(&const_nan));
4001 : /* fail on negative inputs including -Inf, as log_var would */
4002 72 : sign1 = numeric_sign_internal(num1);
4003 72 : sign2 = numeric_sign_internal(num2);
4004 72 : if (sign1 < 0 || sign2 < 0)
4005 24 : ereport(ERROR,
4006 : (errcode(ERRCODE_INVALID_ARGUMENT_FOR_LOG),
4007 : errmsg("cannot take logarithm of a negative number")));
4008 : /* fail on zero inputs, as log_var would */
4009 48 : if (sign1 == 0 || sign2 == 0)
4010 6 : ereport(ERROR,
4011 : (errcode(ERRCODE_INVALID_ARGUMENT_FOR_LOG),
4012 : errmsg("cannot take logarithm of zero")));
4013 42 : if (NUMERIC_IS_PINF(num1))
4014 : {
4015 : /* log(Inf, Inf) reduces to Inf/Inf, so it's NaN */
4016 18 : if (NUMERIC_IS_PINF(num2))
4017 6 : PG_RETURN_NUMERIC(make_result(&const_nan));
4018 : /* log(Inf, finite-positive) is zero (we don't throw underflow) */
4019 12 : PG_RETURN_NUMERIC(make_result(&const_zero));
4020 : }
4021 : Assert(NUMERIC_IS_PINF(num2));
4022 : /* log(finite-positive, Inf) is Inf */
4023 24 : PG_RETURN_NUMERIC(make_result(&const_pinf));
4024 : }
4025 :
4026 : /*
4027 : * Initialize things
4028 : */
4029 216 : init_var_from_num(num1, &arg1);
4030 216 : init_var_from_num(num2, &arg2);
4031 216 : init_var(&result);
4032 :
4033 : /*
4034 : * Call log_var() to compute and return the result; note it handles scale
4035 : * selection itself.
4036 : */
4037 216 : log_var(&arg1, &arg2, &result);
4038 :
4039 156 : res = make_result(&result);
4040 :
4041 156 : free_var(&result);
4042 :
4043 156 : PG_RETURN_NUMERIC(res);
4044 : }
4045 :
4046 :
4047 : /*
4048 : * numeric_power() -
4049 : *
4050 : * Raise x to the power of y
4051 : */
4052 : Datum
4053 1644 : numeric_power(PG_FUNCTION_ARGS)
4054 : {
4055 1644 : Numeric num1 = PG_GETARG_NUMERIC(0);
4056 1644 : Numeric num2 = PG_GETARG_NUMERIC(1);
4057 : Numeric res;
4058 : NumericVar arg1;
4059 : NumericVar arg2;
4060 : NumericVar result;
4061 : int sign1,
4062 : sign2;
4063 :
4064 : /*
4065 : * Handle NaN and infinities
4066 : */
4067 1644 : if (NUMERIC_IS_SPECIAL(num1) || NUMERIC_IS_SPECIAL(num2))
4068 : {
4069 : /*
4070 : * We follow the POSIX spec for pow(3), which says that NaN ^ 0 = 1,
4071 : * and 1 ^ NaN = 1, while all other cases with NaN inputs yield NaN
4072 : * (with no error).
4073 : */
4074 234 : if (NUMERIC_IS_NAN(num1))
4075 : {
4076 54 : if (!NUMERIC_IS_SPECIAL(num2))
4077 : {
4078 36 : init_var_from_num(num2, &arg2);
4079 36 : if (cmp_var(&arg2, &const_zero) == 0)
4080 12 : PG_RETURN_NUMERIC(make_result(&const_one));
4081 : }
4082 42 : PG_RETURN_NUMERIC(make_result(&const_nan));
4083 : }
4084 180 : if (NUMERIC_IS_NAN(num2))
4085 : {
4086 42 : if (!NUMERIC_IS_SPECIAL(num1))
4087 : {
4088 36 : init_var_from_num(num1, &arg1);
4089 36 : if (cmp_var(&arg1, &const_one) == 0)
4090 12 : PG_RETURN_NUMERIC(make_result(&const_one));
4091 : }
4092 30 : PG_RETURN_NUMERIC(make_result(&const_nan));
4093 : }
4094 : /* At least one input is infinite, but error rules still apply */
4095 138 : sign1 = numeric_sign_internal(num1);
4096 138 : sign2 = numeric_sign_internal(num2);
4097 138 : if (sign1 == 0 && sign2 < 0)
4098 6 : ereport(ERROR,
4099 : (errcode(ERRCODE_INVALID_ARGUMENT_FOR_POWER_FUNCTION),
4100 : errmsg("zero raised to a negative power is undefined")));
4101 132 : if (sign1 < 0 && !numeric_is_integral(num2))
4102 6 : ereport(ERROR,
4103 : (errcode(ERRCODE_INVALID_ARGUMENT_FOR_POWER_FUNCTION),
4104 : errmsg("a negative number raised to a non-integer power yields a complex result")));
4105 :
4106 : /*
4107 : * POSIX gives this series of rules for pow(3) with infinite inputs:
4108 : *
4109 : * For any value of y, if x is +1, 1.0 shall be returned.
4110 : */
4111 126 : if (!NUMERIC_IS_SPECIAL(num1))
4112 : {
4113 42 : init_var_from_num(num1, &arg1);
4114 42 : if (cmp_var(&arg1, &const_one) == 0)
4115 6 : PG_RETURN_NUMERIC(make_result(&const_one));
4116 : }
4117 :
4118 : /*
4119 : * For any value of x, if y is [-]0, 1.0 shall be returned.
4120 : */
4121 120 : if (sign2 == 0)
4122 12 : PG_RETURN_NUMERIC(make_result(&const_one));
4123 :
4124 : /*
4125 : * For any odd integer value of y > 0, if x is [-]0, [-]0 shall be
4126 : * returned. For y > 0 and not an odd integer, if x is [-]0, +0 shall
4127 : * be returned. (Since we don't deal in minus zero, we need not
4128 : * distinguish these two cases.)
4129 : */
4130 108 : if (sign1 == 0 && sign2 > 0)
4131 6 : PG_RETURN_NUMERIC(make_result(&const_zero));
4132 :
4133 : /*
4134 : * If x is -1, and y is [-]Inf, 1.0 shall be returned.
4135 : *
4136 : * For |x| < 1, if y is -Inf, +Inf 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, +0 shall be returned.
4141 : *
4142 : * For |x| > 1, if y is +Inf, +Inf shall be returned.
4143 : */
4144 102 : if (NUMERIC_IS_INF(num2))
4145 : {
4146 : bool abs_x_gt_one;
4147 :
4148 54 : if (NUMERIC_IS_SPECIAL(num1))
4149 24 : abs_x_gt_one = true; /* x is either Inf or -Inf */
4150 : else
4151 : {
4152 30 : init_var_from_num(num1, &arg1);
4153 30 : if (cmp_var(&arg1, &const_minus_one) == 0)
4154 6 : PG_RETURN_NUMERIC(make_result(&const_one));
4155 24 : arg1.sign = NUMERIC_POS; /* now arg1 = abs(x) */
4156 24 : abs_x_gt_one = (cmp_var(&arg1, &const_one) > 0);
4157 : }
4158 48 : if (abs_x_gt_one == (sign2 > 0))
4159 30 : PG_RETURN_NUMERIC(make_result(&const_pinf));
4160 : else
4161 18 : PG_RETURN_NUMERIC(make_result(&const_zero));
4162 : }
4163 :
4164 : /*
4165 : * For y < 0, if x is +Inf, +0 shall be returned.
4166 : *
4167 : * For y > 0, if x is +Inf, +Inf shall be returned.
4168 : */
4169 48 : if (NUMERIC_IS_PINF(num1))
4170 : {
4171 24 : if (sign2 > 0)
4172 18 : PG_RETURN_NUMERIC(make_result(&const_pinf));
4173 : else
4174 6 : PG_RETURN_NUMERIC(make_result(&const_zero));
4175 : }
4176 :
4177 : Assert(NUMERIC_IS_NINF(num1));
4178 :
4179 : /*
4180 : * For y an odd integer < 0, if x is -Inf, -0 shall be returned. For
4181 : * y < 0 and not an odd integer, if x is -Inf, +0 shall be returned.
4182 : * (Again, we need not distinguish these two cases.)
4183 : */
4184 24 : if (sign2 < 0)
4185 12 : PG_RETURN_NUMERIC(make_result(&const_zero));
4186 :
4187 : /*
4188 : * For y an odd integer > 0, if x is -Inf, -Inf shall be returned. For
4189 : * y > 0 and not an odd integer, if x is -Inf, +Inf shall be returned.
4190 : */
4191 12 : init_var_from_num(num2, &arg2);
4192 12 : if (arg2.ndigits > 0 && arg2.ndigits == arg2.weight + 1 &&
4193 12 : (arg2.digits[arg2.ndigits - 1] & 1))
4194 6 : PG_RETURN_NUMERIC(make_result(&const_ninf));
4195 : else
4196 6 : PG_RETURN_NUMERIC(make_result(&const_pinf));
4197 : }
4198 :
4199 : /*
4200 : * The SQL spec requires that we emit a particular SQLSTATE error code for
4201 : * certain error conditions. Specifically, we don't return a
4202 : * divide-by-zero error code for 0 ^ -1. Raising a negative number to a
4203 : * non-integer power must produce the same error code, but that case is
4204 : * handled in power_var().
4205 : */
4206 1410 : sign1 = numeric_sign_internal(num1);
4207 1410 : sign2 = numeric_sign_internal(num2);
4208 :
4209 1410 : if (sign1 == 0 && sign2 < 0)
4210 12 : ereport(ERROR,
4211 : (errcode(ERRCODE_INVALID_ARGUMENT_FOR_POWER_FUNCTION),
4212 : errmsg("zero raised to a negative power is undefined")));
4213 :
4214 : /*
4215 : * Initialize things
4216 : */
4217 1398 : init_var(&result);
4218 1398 : init_var_from_num(num1, &arg1);
4219 1398 : init_var_from_num(num2, &arg2);
4220 :
4221 : /*
4222 : * Call power_var() to compute and return the result; note it handles
4223 : * scale selection itself.
4224 : */
4225 1398 : power_var(&arg1, &arg2, &result);
4226 :
4227 1368 : res = make_result(&result);
4228 :
4229 1368 : free_var(&result);
4230 :
4231 1368 : PG_RETURN_NUMERIC(res);
4232 : }
4233 :
4234 : /*
4235 : * numeric_scale() -
4236 : *
4237 : * Returns the scale, i.e. the count of decimal digits in the fractional part
4238 : */
4239 : Datum
4240 108 : numeric_scale(PG_FUNCTION_ARGS)
4241 : {
4242 108 : Numeric num = PG_GETARG_NUMERIC(0);
4243 :
4244 108 : if (NUMERIC_IS_SPECIAL(num))
4245 18 : PG_RETURN_NULL();
4246 :
4247 90 : PG_RETURN_INT32(NUMERIC_DSCALE(num));
4248 : }
4249 :
4250 : /*
4251 : * Calculate minimum scale for value.
4252 : */
4253 : static int
4254 372 : get_min_scale(NumericVar *var)
4255 : {
4256 : int min_scale;
4257 : int last_digit_pos;
4258 :
4259 : /*
4260 : * Ordinarily, the input value will be "stripped" so that the last
4261 : * NumericDigit is nonzero. But we don't want to get into an infinite
4262 : * loop if it isn't, so explicitly find the last nonzero digit.
4263 : */
4264 372 : last_digit_pos = var->ndigits - 1;
4265 372 : while (last_digit_pos >= 0 &&
4266 342 : var->digits[last_digit_pos] == 0)
4267 0 : last_digit_pos--;
4268 :
4269 372 : if (last_digit_pos >= 0)
4270 : {
4271 : /* compute min_scale assuming that last ndigit has no zeroes */
4272 342 : min_scale = (last_digit_pos - var->weight) * DEC_DIGITS;
4273 :
4274 : /*
4275 : * We could get a negative result if there are no digits after the
4276 : * decimal point. In this case the min_scale must be zero.
4277 : */
4278 342 : if (min_scale > 0)
4279 : {
4280 : /*
4281 : * Reduce min_scale if trailing digit(s) in last NumericDigit are
4282 : * zero.
4283 : */
4284 186 : NumericDigit last_digit = var->digits[last_digit_pos];
4285 :
4286 498 : while (last_digit % 10 == 0)
4287 : {
4288 312 : min_scale--;
4289 312 : last_digit /= 10;
4290 : }
4291 : }
4292 : else
4293 156 : min_scale = 0;
4294 : }
4295 : else
4296 30 : min_scale = 0; /* result if input is zero */
4297 :
4298 372 : return min_scale;
4299 : }
4300 :
4301 : /*
4302 : * Returns minimum scale required to represent supplied value without loss.
4303 : */
4304 : Datum
4305 72 : numeric_min_scale(PG_FUNCTION_ARGS)
4306 : {
4307 72 : Numeric num = PG_GETARG_NUMERIC(0);
4308 : NumericVar arg;
4309 : int min_scale;
4310 :
4311 72 : if (NUMERIC_IS_SPECIAL(num))
4312 12 : PG_RETURN_NULL();
4313 :
4314 60 : init_var_from_num(num, &arg);
4315 60 : min_scale = get_min_scale(&arg);
4316 60 : free_var(&arg);
4317 :
4318 60 : PG_RETURN_INT32(min_scale);
4319 : }
4320 :
4321 : /*
4322 : * Reduce scale of numeric value to represent supplied value without loss.
4323 : */
4324 : Datum
4325 324 : numeric_trim_scale(PG_FUNCTION_ARGS)
4326 : {
4327 324 : Numeric num = PG_GETARG_NUMERIC(0);
4328 : Numeric res;
4329 : NumericVar result;
4330 :
4331 324 : if (NUMERIC_IS_SPECIAL(num))
4332 12 : PG_RETURN_NUMERIC(duplicate_numeric(num));
4333 :
4334 312 : init_var_from_num(num, &result);
4335 312 : result.dscale = get_min_scale(&result);
4336 312 : res = make_result(&result);
4337 312 : free_var(&result);
4338 :
4339 312 : PG_RETURN_NUMERIC(res);
4340 : }
4341 :
4342 : /*
4343 : * Return a random numeric value in the range [rmin, rmax].
4344 : */
4345 : Numeric
4346 33462 : random_numeric(pg_prng_state *state, Numeric rmin, Numeric rmax)
4347 : {
4348 : NumericVar rmin_var;
4349 : NumericVar rmax_var;
4350 : NumericVar result;
4351 : Numeric res;
4352 :
4353 : /* Range bounds must not be NaN/infinity */
4354 33462 : if (NUMERIC_IS_SPECIAL(rmin))
4355 : {
4356 12 : if (NUMERIC_IS_NAN(rmin))
4357 6 : ereport(ERROR,
4358 : errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4359 : errmsg("lower bound cannot be NaN"));
4360 : else
4361 6 : ereport(ERROR,
4362 : errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4363 : errmsg("lower bound cannot be infinity"));
4364 : }
4365 33450 : if (NUMERIC_IS_SPECIAL(rmax))
4366 : {
4367 12 : if (NUMERIC_IS_NAN(rmax))
4368 6 : ereport(ERROR,
4369 : errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4370 : errmsg("upper bound cannot be NaN"));
4371 : else
4372 6 : ereport(ERROR,
4373 : errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4374 : errmsg("upper bound cannot be infinity"));
4375 : }
4376 :
4377 : /* Return a random value in the range [rmin, rmax] */
4378 33438 : init_var_from_num(rmin, &rmin_var);
4379 33438 : init_var_from_num(rmax, &rmax_var);
4380 :
4381 33438 : init_var(&result);
4382 :
4383 33438 : random_var(state, &rmin_var, &rmax_var, &result);
4384 :
4385 33432 : res = make_result(&result);
4386 :
4387 33432 : free_var(&result);
4388 :
4389 33432 : return res;
4390 : }
4391 :
4392 :
4393 : /* ----------------------------------------------------------------------
4394 : *
4395 : * Type conversion functions
4396 : *
4397 : * ----------------------------------------------------------------------
4398 : */
4399 :
4400 : Numeric
4401 1848780 : int64_to_numeric(int64 val)
4402 : {
4403 : Numeric res;
4404 : NumericVar result;
4405 :
4406 1848780 : init_var(&result);
4407 :
4408 1848780 : int64_to_numericvar(val, &result);
4409 :
4410 1848780 : res = make_result(&result);
4411 :
4412 1848780 : free_var(&result);
4413 :
4414 1848780 : return res;
4415 : }
4416 :
4417 : /*
4418 : * Convert val1/(10**log10val2) to numeric. This is much faster than normal
4419 : * numeric division.
4420 : */
4421 : Numeric
4422 29380 : int64_div_fast_to_numeric(int64 val1, int log10val2)
4423 : {
4424 : Numeric res;
4425 : NumericVar result;
4426 : int rscale;
4427 : int w;
4428 : int m;
4429 :
4430 29380 : init_var(&result);
4431 :
4432 : /* result scale */
4433 29380 : rscale = log10val2 < 0 ? 0 : log10val2;
4434 :
4435 : /* how much to decrease the weight by */
4436 29380 : w = log10val2 / DEC_DIGITS;
4437 : /* how much is left to divide by */
4438 29380 : m = log10val2 % DEC_DIGITS;
4439 29380 : if (m < 0)
4440 : {
4441 0 : m += DEC_DIGITS;
4442 0 : w--;
4443 : }
4444 :
4445 : /*
4446 : * If there is anything left to divide by (10^m with 0 < m < DEC_DIGITS),
4447 : * multiply the dividend by 10^(DEC_DIGITS - m), and shift the weight by
4448 : * one more.
4449 : */
4450 29380 : if (m > 0)
4451 : {
4452 : #if DEC_DIGITS == 4
4453 : static const int pow10[] = {1, 10, 100, 1000};
4454 : #elif DEC_DIGITS == 2
4455 : static const int pow10[] = {1, 10};
4456 : #elif DEC_DIGITS == 1
4457 : static const int pow10[] = {1};
4458 : #else
4459 : #error unsupported NBASE
4460 : #endif
4461 29380 : int64 factor = pow10[DEC_DIGITS - m];
4462 : int64 new_val1;
4463 :
4464 : StaticAssertDecl(lengthof(pow10) == DEC_DIGITS, "mismatch with DEC_DIGITS");
4465 :
4466 29380 : if (unlikely(pg_mul_s64_overflow(val1, factor, &new_val1)))
4467 : {
4468 : #ifdef HAVE_INT128
4469 : /* do the multiplication using 128-bit integers */
4470 : int128 tmp;
4471 :
4472 12 : tmp = (int128) val1 * (int128) factor;
4473 :
4474 12 : int128_to_numericvar(tmp, &result);
4475 : #else
4476 : /* do the multiplication using numerics */
4477 : NumericVar tmp;
4478 :
4479 : init_var(&tmp);
4480 :
4481 : int64_to_numericvar(val1, &result);
4482 : int64_to_numericvar(factor, &tmp);
4483 : mul_var(&result, &tmp, &result, 0);
4484 :
4485 : free_var(&tmp);
4486 : #endif
4487 : }
4488 : else
4489 29368 : int64_to_numericvar(new_val1, &result);
4490 :
4491 29380 : w++;
4492 : }
4493 : else
4494 0 : int64_to_numericvar(val1, &result);
4495 :
4496 29380 : result.weight -= w;
4497 29380 : result.dscale = rscale;
4498 :
4499 29380 : res = make_result(&result);
4500 :
4501 29380 : free_var(&result);
4502 :
4503 29380 : return res;
4504 : }
4505 :
4506 : Datum
4507 1530736 : int4_numeric(PG_FUNCTION_ARGS)
4508 : {
4509 1530736 : int32 val = PG_GETARG_INT32(0);
4510 :
4511 1530736 : PG_RETURN_NUMERIC(int64_to_numeric(val));
4512 : }
4513 :
4514 : int32
4515 7692 : numeric_int4_opt_error(Numeric num, bool *have_error)
4516 : {
4517 : NumericVar x;
4518 : int32 result;
4519 :
4520 7692 : if (have_error)
4521 1584 : *have_error = false;
4522 :
4523 7692 : if (NUMERIC_IS_SPECIAL(num))
4524 : {
4525 18 : if (have_error)
4526 : {
4527 0 : *have_error = true;
4528 0 : return 0;
4529 : }
4530 : else
4531 : {
4532 18 : if (NUMERIC_IS_NAN(num))
4533 6 : ereport(ERROR,
4534 : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4535 : errmsg("cannot convert NaN to %s", "integer")));
4536 : else
4537 12 : ereport(ERROR,
4538 : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4539 : errmsg("cannot convert infinity to %s", "integer")));
4540 : }
4541 : }
4542 :
4543 : /* Convert to variable format, then convert to int4 */
4544 7674 : init_var_from_num(num, &x);
4545 :
4546 7674 : if (!numericvar_to_int32(&x, &result))
4547 : {
4548 90 : if (have_error)
4549 : {
4550 78 : *have_error = true;
4551 78 : return 0;
4552 : }
4553 : else
4554 : {
4555 12 : ereport(ERROR,
4556 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
4557 : errmsg("integer out of range")));
4558 : }
4559 : }
4560 :
4561 7584 : return result;
4562 : }
4563 :
4564 : Datum
4565 6108 : numeric_int4(PG_FUNCTION_ARGS)
4566 : {
4567 6108 : Numeric num = PG_GETARG_NUMERIC(0);
4568 :
4569 6108 : PG_RETURN_INT32(numeric_int4_opt_error(num, NULL));
4570 : }
4571 :
4572 : /*
4573 : * Given a NumericVar, convert it to an int32. If the NumericVar
4574 : * exceeds the range of an int32, false is returned, otherwise true is returned.
4575 : * The input NumericVar is *not* free'd.
4576 : */
4577 : static bool
4578 8412 : numericvar_to_int32(const NumericVar *var, int32 *result)
4579 : {
4580 : int64 val;
4581 :
4582 8412 : if (!numericvar_to_int64(var, &val))
4583 6 : return false;
4584 :
4585 8406 : if (unlikely(val < PG_INT32_MIN) || unlikely(val > PG_INT32_MAX))
4586 84 : return false;
4587 :
4588 : /* Down-convert to int4 */
4589 8322 : *result = (int32) val;
4590 :
4591 8322 : return true;
4592 : }
4593 :
4594 : Datum
4595 36850 : int8_numeric(PG_FUNCTION_ARGS)
4596 : {
4597 36850 : int64 val = PG_GETARG_INT64(0);
4598 :
4599 36850 : PG_RETURN_NUMERIC(int64_to_numeric(val));
4600 : }
4601 :
4602 : int64
4603 564 : numeric_int8_opt_error(Numeric num, bool *have_error)
4604 : {
4605 : NumericVar x;
4606 : int64 result;
4607 :
4608 564 : if (have_error)
4609 48 : *have_error = false;
4610 :
4611 564 : if (NUMERIC_IS_SPECIAL(num))
4612 : {
4613 18 : if (have_error)
4614 : {
4615 0 : *have_error = true;
4616 0 : return 0;
4617 : }
4618 : else
4619 : {
4620 18 : if (NUMERIC_IS_NAN(num))
4621 6 : ereport(ERROR,
4622 : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4623 : errmsg("cannot convert NaN to %s", "bigint")));
4624 : else
4625 12 : ereport(ERROR,
4626 : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4627 : errmsg("cannot convert infinity to %s", "bigint")));
4628 : }
4629 : }
4630 :
4631 : /* Convert to variable format, then convert to int8 */
4632 546 : init_var_from_num(num, &x);
4633 :
4634 546 : if (!numericvar_to_int64(&x, &result))
4635 : {
4636 60 : if (have_error)
4637 : {
4638 12 : *have_error = true;
4639 12 : return 0;
4640 : }
4641 : else
4642 : {
4643 48 : ereport(ERROR,
4644 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
4645 : errmsg("bigint out of range")));
4646 : }
4647 : }
4648 :
4649 486 : return result;
4650 : }
4651 :
4652 : Datum
4653 516 : numeric_int8(PG_FUNCTION_ARGS)
4654 : {
4655 516 : Numeric num = PG_GETARG_NUMERIC(0);
4656 :
4657 516 : PG_RETURN_INT64(numeric_int8_opt_error(num, NULL));
4658 : }
4659 :
4660 :
4661 : Datum
4662 6 : int2_numeric(PG_FUNCTION_ARGS)
4663 : {
4664 6 : int16 val = PG_GETARG_INT16(0);
4665 :
4666 6 : PG_RETURN_NUMERIC(int64_to_numeric(val));
4667 : }
4668 :
4669 :
4670 : Datum
4671 96 : numeric_int2(PG_FUNCTION_ARGS)
4672 : {
4673 96 : Numeric num = PG_GETARG_NUMERIC(0);
4674 : NumericVar x;
4675 : int64 val;
4676 : int16 result;
4677 :
4678 96 : if (NUMERIC_IS_SPECIAL(num))
4679 : {
4680 18 : if (NUMERIC_IS_NAN(num))
4681 6 : ereport(ERROR,
4682 : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4683 : errmsg("cannot convert NaN to %s", "smallint")));
4684 : else
4685 12 : ereport(ERROR,
4686 : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4687 : errmsg("cannot convert infinity to %s", "smallint")));
4688 : }
4689 :
4690 : /* Convert to variable format and thence to int8 */
4691 78 : init_var_from_num(num, &x);
4692 :
4693 78 : if (!numericvar_to_int64(&x, &val))
4694 0 : ereport(ERROR,
4695 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
4696 : errmsg("smallint out of range")));
4697 :
4698 78 : if (unlikely(val < PG_INT16_MIN) || unlikely(val > PG_INT16_MAX))
4699 12 : ereport(ERROR,
4700 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
4701 : errmsg("smallint out of range")));
4702 :
4703 : /* Down-convert to int2 */
4704 66 : result = (int16) val;
4705 :
4706 66 : PG_RETURN_INT16(result);
4707 : }
4708 :
4709 :
4710 : Datum
4711 1074 : float8_numeric(PG_FUNCTION_ARGS)
4712 : {
4713 1074 : float8 val = PG_GETARG_FLOAT8(0);
4714 : Numeric res;
4715 : NumericVar result;
4716 : char buf[DBL_DIG + 100];
4717 : const char *endptr;
4718 :
4719 1074 : if (isnan(val))
4720 6 : PG_RETURN_NUMERIC(make_result(&const_nan));
4721 :
4722 1068 : if (isinf(val))
4723 : {
4724 12 : if (val < 0)
4725 6 : PG_RETURN_NUMERIC(make_result(&const_ninf));
4726 : else
4727 6 : PG_RETURN_NUMERIC(make_result(&const_pinf));
4728 : }
4729 :
4730 1056 : snprintf(buf, sizeof(buf), "%.*g", DBL_DIG, val);
4731 :
4732 1056 : init_var(&result);
4733 :
4734 : /* Assume we need not worry about leading/trailing spaces */
4735 1056 : (void) set_var_from_str(buf, buf, &result, &endptr, NULL);
4736 :
4737 1056 : res = make_result(&result);
4738 :
4739 1056 : free_var(&result);
4740 :
4741 1056 : PG_RETURN_NUMERIC(res);
4742 : }
4743 :
4744 :
4745 : Datum
4746 519572 : numeric_float8(PG_FUNCTION_ARGS)
4747 : {
4748 519572 : Numeric num = PG_GETARG_NUMERIC(0);
4749 : char *tmp;
4750 : Datum result;
4751 :
4752 519572 : if (NUMERIC_IS_SPECIAL(num))
4753 : {
4754 78 : if (NUMERIC_IS_PINF(num))
4755 24 : PG_RETURN_FLOAT8(get_float8_infinity());
4756 54 : else if (NUMERIC_IS_NINF(num))
4757 24 : PG_RETURN_FLOAT8(-get_float8_infinity());
4758 : else
4759 30 : PG_RETURN_FLOAT8(get_float8_nan());
4760 : }
4761 :
4762 519494 : tmp = DatumGetCString(DirectFunctionCall1(numeric_out,
4763 : NumericGetDatum(num)));
4764 :
4765 519494 : result = DirectFunctionCall1(float8in, CStringGetDatum(tmp));
4766 :
4767 519494 : pfree(tmp);
4768 :
4769 519494 : PG_RETURN_DATUM(result);
4770 : }
4771 :
4772 :
4773 : /*
4774 : * Convert numeric to float8; if out of range, return +/- HUGE_VAL
4775 : *
4776 : * (internal helper function, not directly callable from SQL)
4777 : */
4778 : Datum
4779 2880 : numeric_float8_no_overflow(PG_FUNCTION_ARGS)
4780 : {
4781 2880 : Numeric num = PG_GETARG_NUMERIC(0);
4782 : double val;
4783 :
4784 2880 : if (NUMERIC_IS_SPECIAL(num))
4785 : {
4786 0 : if (NUMERIC_IS_PINF(num))
4787 0 : val = HUGE_VAL;
4788 0 : else if (NUMERIC_IS_NINF(num))
4789 0 : val = -HUGE_VAL;
4790 : else
4791 0 : val = get_float8_nan();
4792 : }
4793 : else
4794 : {
4795 : NumericVar x;
4796 :
4797 2880 : init_var_from_num(num, &x);
4798 2880 : val = numericvar_to_double_no_overflow(&x);
4799 : }
4800 :
4801 2880 : PG_RETURN_FLOAT8(val);
4802 : }
4803 :
4804 : Datum
4805 22036 : float4_numeric(PG_FUNCTION_ARGS)
4806 : {
4807 22036 : float4 val = PG_GETARG_FLOAT4(0);
4808 : Numeric res;
4809 : NumericVar result;
4810 : char buf[FLT_DIG + 100];
4811 : const char *endptr;
4812 :
4813 22036 : if (isnan(val))
4814 6 : PG_RETURN_NUMERIC(make_result(&const_nan));
4815 :
4816 22030 : if (isinf(val))
4817 : {
4818 12 : if (val < 0)
4819 6 : PG_RETURN_NUMERIC(make_result(&const_ninf));
4820 : else
4821 6 : PG_RETURN_NUMERIC(make_result(&const_pinf));
4822 : }
4823 :
4824 22018 : snprintf(buf, sizeof(buf), "%.*g", FLT_DIG, val);
4825 :
4826 22018 : init_var(&result);
4827 :
4828 : /* Assume we need not worry about leading/trailing spaces */
4829 22018 : (void) set_var_from_str(buf, buf, &result, &endptr, NULL);
4830 :
4831 22018 : res = make_result(&result);
4832 :
4833 22018 : free_var(&result);
4834 :
4835 22018 : PG_RETURN_NUMERIC(res);
4836 : }
4837 :
4838 :
4839 : Datum
4840 2954 : numeric_float4(PG_FUNCTION_ARGS)
4841 : {
4842 2954 : Numeric num = PG_GETARG_NUMERIC(0);
4843 : char *tmp;
4844 : Datum result;
4845 :
4846 2954 : if (NUMERIC_IS_SPECIAL(num))
4847 : {
4848 78 : if (NUMERIC_IS_PINF(num))
4849 24 : PG_RETURN_FLOAT4(get_float4_infinity());
4850 54 : else if (NUMERIC_IS_NINF(num))
4851 24 : PG_RETURN_FLOAT4(-get_float4_infinity());
4852 : else
4853 30 : PG_RETURN_FLOAT4(get_float4_nan());
4854 : }
4855 :
4856 2876 : tmp = DatumGetCString(DirectFunctionCall1(numeric_out,
4857 : NumericGetDatum(num)));
4858 :
4859 2876 : result = DirectFunctionCall1(float4in, CStringGetDatum(tmp));
4860 :
4861 2876 : pfree(tmp);
4862 :
4863 2876 : PG_RETURN_DATUM(result);
4864 : }
4865 :
4866 :
4867 : Datum
4868 120 : numeric_pg_lsn(PG_FUNCTION_ARGS)
4869 : {
4870 120 : Numeric num = PG_GETARG_NUMERIC(0);
4871 : NumericVar x;
4872 : XLogRecPtr result;
4873 :
4874 120 : if (NUMERIC_IS_SPECIAL(num))
4875 : {
4876 6 : if (NUMERIC_IS_NAN(num))
4877 6 : ereport(ERROR,
4878 : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4879 : errmsg("cannot convert NaN to %s", "pg_lsn")));
4880 : else
4881 0 : ereport(ERROR,
4882 : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4883 : errmsg("cannot convert infinity to %s", "pg_lsn")));
4884 : }
4885 :
4886 : /* Convert to variable format and thence to pg_lsn */
4887 114 : init_var_from_num(num, &x);
4888 :
4889 114 : if (!numericvar_to_uint64(&x, (uint64 *) &result))
4890 24 : ereport(ERROR,
4891 : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4892 : errmsg("pg_lsn out of range")));
4893 :
4894 90 : PG_RETURN_LSN(result);
4895 : }
4896 :
4897 :
4898 : /* ----------------------------------------------------------------------
4899 : *
4900 : * Aggregate functions
4901 : *
4902 : * The transition datatype for all these aggregates is declared as INTERNAL.
4903 : * Actually, it's a pointer to a NumericAggState allocated in the aggregate
4904 : * context. The digit buffers for the NumericVars will be there too.
4905 : *
4906 : * On platforms which support 128-bit integers some aggregates instead use a
4907 : * 128-bit integer based transition datatype to speed up calculations.
4908 : *
4909 : * ----------------------------------------------------------------------
4910 : */
4911 :
4912 : typedef struct NumericAggState
4913 : {
4914 : bool calcSumX2; /* if true, calculate sumX2 */
4915 : MemoryContext agg_context; /* context we're calculating in */
4916 : int64 N; /* count of processed numbers */
4917 : NumericSumAccum sumX; /* sum of processed numbers */
4918 : NumericSumAccum sumX2; /* sum of squares of processed numbers */
4919 : int maxScale; /* maximum scale seen so far */
4920 : int64 maxScaleCount; /* number of values seen with maximum scale */
4921 : /* These counts are *not* included in N! Use NA_TOTAL_COUNT() as needed */
4922 : int64 NaNcount; /* count of NaN values */
4923 : int64 pInfcount; /* count of +Inf values */
4924 : int64 nInfcount; /* count of -Inf values */
4925 : } NumericAggState;
4926 :
4927 : #define NA_TOTAL_COUNT(na) \
4928 : ((na)->N + (na)->NaNcount + (na)->pInfcount + (na)->nInfcount)
4929 :
4930 : /*
4931 : * Prepare state data for a numeric aggregate function that needs to compute
4932 : * sum, count and optionally sum of squares of the input.
4933 : */
4934 : static NumericAggState *
4935 171116 : makeNumericAggState(FunctionCallInfo fcinfo, bool calcSumX2)
4936 : {
4937 : NumericAggState *state;
4938 : MemoryContext agg_context;
4939 : MemoryContext old_context;
4940 :
4941 171116 : if (!AggCheckCallContext(fcinfo, &agg_context))
4942 0 : elog(ERROR, "aggregate function called in non-aggregate context");
4943 :
4944 171116 : old_context = MemoryContextSwitchTo(agg_context);
4945 :
4946 171116 : state = (NumericAggState *) palloc0(sizeof(NumericAggState));
4947 171116 : state->calcSumX2 = calcSumX2;
4948 171116 : state->agg_context = agg_context;
4949 :
4950 171116 : MemoryContextSwitchTo(old_context);
4951 :
4952 171116 : return state;
4953 : }
4954 :
4955 : /*
4956 : * Like makeNumericAggState(), but allocate the state in the current memory
4957 : * context.
4958 : */
4959 : static NumericAggState *
4960 60 : makeNumericAggStateCurrentContext(bool calcSumX2)
4961 : {
4962 : NumericAggState *state;
4963 :
4964 60 : state = (NumericAggState *) palloc0(sizeof(NumericAggState));
4965 60 : state->calcSumX2 = calcSumX2;
4966 60 : state->agg_context = CurrentMemoryContext;
4967 :
4968 60 : return state;
4969 : }
4970 :
4971 : /*
4972 : * Accumulate a new input value for numeric aggregate functions.
4973 : */
4974 : static void
4975 2113552 : do_numeric_accum(NumericAggState *state, Numeric newval)
4976 : {
4977 : NumericVar X;
4978 : NumericVar X2;
4979 : MemoryContext old_context;
4980 :
4981 : /* Count NaN/infinity inputs separately from all else */
4982 2113552 : if (NUMERIC_IS_SPECIAL(newval))
4983 : {
4984 162 : if (NUMERIC_IS_PINF(newval))
4985 72 : state->pInfcount++;
4986 90 : else if (NUMERIC_IS_NINF(newval))
4987 36 : state->nInfcount++;
4988 : else
4989 54 : state->NaNcount++;
4990 162 : return;
4991 : }
4992 :
4993 : /* load processed number in short-lived context */
4994 2113390 : init_var_from_num(newval, &X);
4995 :
4996 : /*
4997 : * Track the highest input dscale that we've seen, to support inverse
4998 : * transitions (see do_numeric_discard).
4999 : */
5000 2113390 : if (X.dscale > state->maxScale)
5001 : {
5002 156 : state->maxScale = X.dscale;
5003 156 : state->maxScaleCount = 1;
5004 : }
5005 2113234 : else if (X.dscale == state->maxScale)
5006 2113198 : state->maxScaleCount++;
5007 :
5008 : /* if we need X^2, calculate that in short-lived context */
5009 2113390 : if (state->calcSumX2)
5010 : {
5011 240732 : init_var(&X2);
5012 240732 : mul_var(&X, &X, &X2, X.dscale * 2);
5013 : }
5014 :
5015 : /* The rest of this needs to work in the aggregate context */
5016 2113390 : old_context = MemoryContextSwitchTo(state->agg_context);
5017 :
5018 2113390 : state->N++;
5019 :
5020 : /* Accumulate sums */
5021 2113390 : accum_sum_add(&(state->sumX), &X);
5022 :
5023 2113390 : if (state->calcSumX2)
5024 240732 : accum_sum_add(&(state->sumX2), &X2);
5025 :
5026 2113390 : MemoryContextSwitchTo(old_context);
5027 : }
5028 :
5029 : /*
5030 : * Attempt to remove an input value from the aggregated state.
5031 : *
5032 : * If the value cannot be removed then the function will return false; the
5033 : * possible reasons for failing are described below.
5034 : *
5035 : * If we aggregate the values 1.01 and 2 then the result will be 3.01.
5036 : * If we are then asked to un-aggregate the 1.01 then we must fail as we
5037 : * won't be able to tell what the new aggregated value's dscale should be.
5038 : * We don't want to return 2.00 (dscale = 2), since the sum's dscale would
5039 : * have been zero if we'd really aggregated only 2.
5040 : *
5041 : * Note: alternatively, we could count the number of inputs with each possible
5042 : * dscale (up to some sane limit). Not yet clear if it's worth the trouble.
5043 : */
5044 : static bool
5045 342 : do_numeric_discard(NumericAggState *state, Numeric newval)
5046 : {
5047 : NumericVar X;
5048 : NumericVar X2;
5049 : MemoryContext old_context;
5050 :
5051 : /* Count NaN/infinity inputs separately from all else */
5052 342 : if (NUMERIC_IS_SPECIAL(newval))
5053 : {
5054 6 : if (NUMERIC_IS_PINF(newval))
5055 0 : state->pInfcount--;
5056 6 : else if (NUMERIC_IS_NINF(newval))
5057 0 : state->nInfcount--;
5058 : else
5059 6 : state->NaNcount--;
5060 6 : return true;
5061 : }
5062 :
5063 : /* load processed number in short-lived context */
5064 336 : init_var_from_num(newval, &X);
5065 :
5066 : /*
5067 : * state->sumX's dscale is the maximum dscale of any of the inputs.
5068 : * Removing the last input with that dscale would require us to recompute
5069 : * the maximum dscale of the *remaining* inputs, which we cannot do unless
5070 : * no more non-NaN inputs remain at all. So we report a failure instead,
5071 : * and force the aggregation to be redone from scratch.
5072 : */
5073 336 : if (X.dscale == state->maxScale)
5074 : {
5075 336 : if (state->maxScaleCount > 1 || state->maxScale == 0)
5076 : {
5077 : /*
5078 : * Some remaining inputs have same dscale, or dscale hasn't gotten
5079 : * above zero anyway
5080 : */
5081 318 : state->maxScaleCount--;
5082 : }
5083 18 : else if (state->N == 1)
5084 : {
5085 : /* No remaining non-NaN inputs at all, so reset maxScale */
5086 12 : state->maxScale = 0;
5087 12 : state->maxScaleCount = 0;
5088 : }
5089 : else
5090 : {
5091 : /* Correct new maxScale is uncertain, must fail */
5092 6 : return false;
5093 : }
5094 : }
5095 :
5096 : /* if we need X^2, calculate that in short-lived context */
5097 330 : if (state->calcSumX2)
5098 : {
5099 288 : init_var(&X2);
5100 288 : mul_var(&X, &X, &X2, X.dscale * 2);
5101 : }
5102 :
5103 : /* The rest of this needs to work in the aggregate context */
5104 330 : old_context = MemoryContextSwitchTo(state->agg_context);
5105 :
5106 330 : if (state->N-- > 1)
5107 : {
5108 : /* Negate X, to subtract it from the sum */
5109 312 : X.sign = (X.sign == NUMERIC_POS ? NUMERIC_NEG : NUMERIC_POS);
5110 312 : accum_sum_add(&(state->sumX), &X);
5111 :
5112 312 : if (state->calcSumX2)
5113 : {
5114 : /* Negate X^2. X^2 is always positive */
5115 288 : X2.sign = NUMERIC_NEG;
5116 288 : accum_sum_add(&(state->sumX2), &X2);
5117 : }
5118 : }
5119 : else
5120 : {
5121 : /* Zero the sums */
5122 : Assert(state->N == 0);
5123 :
5124 18 : accum_sum_reset(&state->sumX);
5125 18 : if (state->calcSumX2)
5126 0 : accum_sum_reset(&state->sumX2);
5127 : }
5128 :
5129 330 : MemoryContextSwitchTo(old_context);
5130 :
5131 330 : return true;
5132 : }
5133 :
5134 : /*
5135 : * Generic transition function for numeric aggregates that require sumX2.
5136 : */
5137 : Datum
5138 642 : numeric_accum(PG_FUNCTION_ARGS)
5139 : {
5140 : NumericAggState *state;
5141 :
5142 642 : state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
5143 :
5144 : /* Create the state data on the first call */
5145 642 : if (state == NULL)
5146 174 : state = makeNumericAggState(fcinfo, true);
5147 :
5148 642 : if (!PG_ARGISNULL(1))
5149 624 : do_numeric_accum(state, PG_GETARG_NUMERIC(1));
5150 :
5151 642 : PG_RETURN_POINTER(state);
5152 : }
5153 :
5154 : /*
5155 : * Generic combine function for numeric aggregates which require sumX2
5156 : */
5157 : Datum
5158 24 : numeric_combine(PG_FUNCTION_ARGS)
5159 : {
5160 : NumericAggState *state1;
5161 : NumericAggState *state2;
5162 : MemoryContext agg_context;
5163 : MemoryContext old_context;
5164 :
5165 24 : if (!AggCheckCallContext(fcinfo, &agg_context))
5166 0 : elog(ERROR, "aggregate function called in non-aggregate context");
5167 :
5168 24 : state1 = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
5169 24 : state2 = PG_ARGISNULL(1) ? NULL : (NumericAggState *) PG_GETARG_POINTER(1);
5170 :
5171 24 : if (state2 == NULL)
5172 0 : PG_RETURN_POINTER(state1);
5173 :
5174 : /* manually copy all fields from state2 to state1 */
5175 24 : if (state1 == NULL)
5176 : {
5177 18 : old_context = MemoryContextSwitchTo(agg_context);
5178 :
5179 18 : state1 = makeNumericAggStateCurrentContext(true);
5180 18 : state1->N = state2->N;
5181 18 : state1->NaNcount = state2->NaNcount;
5182 18 : state1->pInfcount = state2->pInfcount;
5183 18 : state1->nInfcount = state2->nInfcount;
5184 18 : state1->maxScale = state2->maxScale;
5185 18 : state1->maxScaleCount = state2->maxScaleCount;
5186 :
5187 18 : accum_sum_copy(&state1->sumX, &state2->sumX);
5188 18 : accum_sum_copy(&state1->sumX2, &state2->sumX2);
5189 :
5190 18 : MemoryContextSwitchTo(old_context);
5191 :
5192 18 : PG_RETURN_POINTER(state1);
5193 : }
5194 :
5195 6 : state1->N += state2->N;
5196 6 : state1->NaNcount += state2->NaNcount;
5197 6 : state1->pInfcount += state2->pInfcount;
5198 6 : state1->nInfcount += state2->nInfcount;
5199 :
5200 6 : if (state2->N > 0)
5201 : {
5202 : /*
5203 : * These are currently only needed for moving aggregates, but let's do
5204 : * the right thing anyway...
5205 : */
5206 6 : if (state2->maxScale > state1->maxScale)
5207 : {
5208 0 : state1->maxScale = state2->maxScale;
5209 0 : state1->maxScaleCount = state2->maxScaleCount;
5210 : }
5211 6 : else if (state2->maxScale == state1->maxScale)
5212 6 : state1->maxScaleCount += state2->maxScaleCount;
5213 :
5214 : /* The rest of this needs to work in the aggregate context */
5215 6 : old_context = MemoryContextSwitchTo(agg_context);
5216 :
5217 : /* Accumulate sums */
5218 6 : accum_sum_combine(&state1->sumX, &state2->sumX);
5219 6 : accum_sum_combine(&state1->sumX2, &state2->sumX2);
5220 :
5221 6 : MemoryContextSwitchTo(old_context);
5222 : }
5223 6 : PG_RETURN_POINTER(state1);
5224 : }
5225 :
5226 : /*
5227 : * Generic transition function for numeric aggregates that don't require sumX2.
5228 : */
5229 : Datum
5230 1872808 : numeric_avg_accum(PG_FUNCTION_ARGS)
5231 : {
5232 : NumericAggState *state;
5233 :
5234 1872808 : state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
5235 :
5236 : /* Create the state data on the first call */
5237 1872808 : if (state == NULL)
5238 170894 : state = makeNumericAggState(fcinfo, false);
5239 :
5240 1872808 : if (!PG_ARGISNULL(1))
5241 1872748 : do_numeric_accum(state, PG_GETARG_NUMERIC(1));
5242 :
5243 1872808 : PG_RETURN_POINTER(state);
5244 : }
5245 :
5246 : /*
5247 : * Combine function for numeric aggregates which don't require sumX2
5248 : */
5249 : Datum
5250 12 : numeric_avg_combine(PG_FUNCTION_ARGS)
5251 : {
5252 : NumericAggState *state1;
5253 : NumericAggState *state2;
5254 : MemoryContext agg_context;
5255 : MemoryContext old_context;
5256 :
5257 12 : if (!AggCheckCallContext(fcinfo, &agg_context))
5258 0 : elog(ERROR, "aggregate function called in non-aggregate context");
5259 :
5260 12 : state1 = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
5261 12 : state2 = PG_ARGISNULL(1) ? NULL : (NumericAggState *) PG_GETARG_POINTER(1);
5262 :
5263 12 : if (state2 == NULL)
5264 0 : PG_RETURN_POINTER(state1);
5265 :
5266 : /* manually copy all fields from state2 to state1 */
5267 12 : if (state1 == NULL)
5268 : {
5269 6 : old_context = MemoryContextSwitchTo(agg_context);
5270 :
5271 6 : state1 = makeNumericAggStateCurrentContext(false);
5272 6 : state1->N = state2->N;
5273 6 : state1->NaNcount = state2->NaNcount;
5274 6 : state1->pInfcount = state2->pInfcount;
5275 6 : state1->nInfcount = state2->nInfcount;
5276 6 : state1->maxScale = state2->maxScale;
5277 6 : state1->maxScaleCount = state2->maxScaleCount;
5278 :
5279 6 : accum_sum_copy(&state1->sumX, &state2->sumX);
5280 :
5281 6 : MemoryContextSwitchTo(old_context);
5282 :
5283 6 : PG_RETURN_POINTER(state1);
5284 : }
5285 :
5286 6 : state1->N += state2->N;
5287 6 : state1->NaNcount += state2->NaNcount;
5288 6 : state1->pInfcount += state2->pInfcount;
5289 6 : state1->nInfcount += state2->nInfcount;
5290 :
5291 6 : if (state2->N > 0)
5292 : {
5293 : /*
5294 : * These are currently only needed for moving aggregates, but let's do
5295 : * the right thing anyway...
5296 : */
5297 6 : if (state2->maxScale > state1->maxScale)
5298 : {
5299 0 : state1->maxScale = state2->maxScale;
5300 0 : state1->maxScaleCount = state2->maxScaleCount;
5301 : }
5302 6 : else if (state2->maxScale == state1->maxScale)
5303 6 : state1->maxScaleCount += state2->maxScaleCount;
5304 :
5305 : /* The rest of this needs to work in the aggregate context */
5306 6 : old_context = MemoryContextSwitchTo(agg_context);
5307 :
5308 : /* Accumulate sums */
5309 6 : accum_sum_combine(&state1->sumX, &state2->sumX);
5310 :
5311 6 : MemoryContextSwitchTo(old_context);
5312 : }
5313 6 : PG_RETURN_POINTER(state1);
5314 : }
5315 :
5316 : /*
5317 : * numeric_avg_serialize
5318 : * Serialize NumericAggState for numeric aggregates that don't require
5319 : * sumX2.
5320 : */
5321 : Datum
5322 12 : numeric_avg_serialize(PG_FUNCTION_ARGS)
5323 : {
5324 : NumericAggState *state;
5325 : StringInfoData buf;
5326 : bytea *result;
5327 : NumericVar tmp_var;
5328 :
5329 : /* Ensure we disallow calling when not in aggregate context */
5330 12 : if (!AggCheckCallContext(fcinfo, NULL))
5331 0 : elog(ERROR, "aggregate function called in non-aggregate context");
5332 :
5333 12 : state = (NumericAggState *) PG_GETARG_POINTER(0);
5334 :
5335 12 : init_var(&tmp_var);
5336 :
5337 12 : pq_begintypsend(&buf);
5338 :
5339 : /* N */
5340 12 : pq_sendint64(&buf, state->N);
5341 :
5342 : /* sumX */
5343 12 : accum_sum_final(&state->sumX, &tmp_var);
5344 12 : numericvar_serialize(&buf, &tmp_var);
5345 :
5346 : /* maxScale */
5347 12 : pq_sendint32(&buf, state->maxScale);
5348 :
5349 : /* maxScaleCount */
5350 12 : pq_sendint64(&buf, state->maxScaleCount);
5351 :
5352 : /* NaNcount */
5353 12 : pq_sendint64(&buf, state->NaNcount);
5354 :
5355 : /* pInfcount */
5356 12 : pq_sendint64(&buf, state->pInfcount);
5357 :
5358 : /* nInfcount */
5359 12 : pq_sendint64(&buf, state->nInfcount);
5360 :
5361 12 : result = pq_endtypsend(&buf);
5362 :
5363 12 : free_var(&tmp_var);
5364 :
5365 12 : PG_RETURN_BYTEA_P(result);
5366 : }
5367 :
5368 : /*
5369 : * numeric_avg_deserialize
5370 : * Deserialize bytea into NumericAggState for numeric aggregates that
5371 : * don't require sumX2.
5372 : */
5373 : Datum
5374 12 : numeric_avg_deserialize(PG_FUNCTION_ARGS)
5375 : {
5376 : bytea *sstate;
5377 : NumericAggState *result;
5378 : StringInfoData buf;
5379 : NumericVar tmp_var;
5380 :
5381 12 : if (!AggCheckCallContext(fcinfo, NULL))
5382 0 : elog(ERROR, "aggregate function called in non-aggregate context");
5383 :
5384 12 : sstate = PG_GETARG_BYTEA_PP(0);
5385 :
5386 12 : init_var(&tmp_var);
5387 :
5388 : /*
5389 : * Initialize a StringInfo so that we can "receive" it using the standard
5390 : * recv-function infrastructure.
5391 : */
5392 12 : initReadOnlyStringInfo(&buf, VARDATA_ANY(sstate),
5393 12 : VARSIZE_ANY_EXHDR(sstate));
5394 :
5395 12 : result = makeNumericAggStateCurrentContext(false);
5396 :
5397 : /* N */
5398 12 : result->N = pq_getmsgint64(&buf);
5399 :
5400 : /* sumX */
5401 12 : numericvar_deserialize(&buf, &tmp_var);
5402 12 : accum_sum_add(&(result->sumX), &tmp_var);
5403 :
5404 : /* maxScale */
5405 12 : result->maxScale = pq_getmsgint(&buf, 4);
5406 :
5407 : /* maxScaleCount */
5408 12 : result->maxScaleCount = pq_getmsgint64(&buf);
5409 :
5410 : /* NaNcount */
5411 12 : result->NaNcount = pq_getmsgint64(&buf);
5412 :
5413 : /* pInfcount */
5414 12 : result->pInfcount = pq_getmsgint64(&buf);
5415 :
5416 : /* nInfcount */
5417 12 : result->nInfcount = pq_getmsgint64(&buf);
5418 :
5419 12 : pq_getmsgend(&buf);
5420 :
5421 12 : free_var(&tmp_var);
5422 :
5423 12 : PG_RETURN_POINTER(result);
5424 : }
5425 :
5426 : /*
5427 : * numeric_serialize
5428 : * Serialization function for NumericAggState for numeric aggregates that
5429 : * require sumX2.
5430 : */
5431 : Datum
5432 24 : numeric_serialize(PG_FUNCTION_ARGS)
5433 : {
5434 : NumericAggState *state;
5435 : StringInfoData buf;
5436 : bytea *result;
5437 : NumericVar tmp_var;
5438 :
5439 : /* Ensure we disallow calling when not in aggregate context */
5440 24 : if (!AggCheckCallContext(fcinfo, NULL))
5441 0 : elog(ERROR, "aggregate function called in non-aggregate context");
5442 :
5443 24 : state = (NumericAggState *) PG_GETARG_POINTER(0);
5444 :
5445 24 : init_var(&tmp_var);
5446 :
5447 24 : pq_begintypsend(&buf);
5448 :
5449 : /* N */
5450 24 : pq_sendint64(&buf, state->N);
5451 :
5452 : /* sumX */
5453 24 : accum_sum_final(&state->sumX, &tmp_var);
5454 24 : numericvar_serialize(&buf, &tmp_var);
5455 :
5456 : /* sumX2 */
5457 24 : accum_sum_final(&state->sumX2, &tmp_var);
5458 24 : numericvar_serialize(&buf, &tmp_var);
5459 :
5460 : /* maxScale */
5461 24 : pq_sendint32(&buf, state->maxScale);
5462 :
5463 : /* maxScaleCount */
5464 24 : pq_sendint64(&buf, state->maxScaleCount);
5465 :
5466 : /* NaNcount */
5467 24 : pq_sendint64(&buf, state->NaNcount);
5468 :
5469 : /* pInfcount */
5470 24 : pq_sendint64(&buf, state->pInfcount);
5471 :
5472 : /* nInfcount */
5473 24 : pq_sendint64(&buf, state->nInfcount);
5474 :
5475 24 : result = pq_endtypsend(&buf);
5476 :
5477 24 : free_var(&tmp_var);
5478 :
5479 24 : PG_RETURN_BYTEA_P(result);
5480 : }
5481 :
5482 : /*
5483 : * numeric_deserialize
5484 : * Deserialization function for NumericAggState for numeric aggregates that
5485 : * require sumX2.
5486 : */
5487 : Datum
5488 24 : numeric_deserialize(PG_FUNCTION_ARGS)
5489 : {
5490 : bytea *sstate;
5491 : NumericAggState *result;
5492 : StringInfoData buf;
5493 : NumericVar tmp_var;
5494 :
5495 24 : if (!AggCheckCallContext(fcinfo, NULL))
5496 0 : elog(ERROR, "aggregate function called in non-aggregate context");
5497 :
5498 24 : sstate = PG_GETARG_BYTEA_PP(0);
5499 :
5500 24 : init_var(&tmp_var);
5501 :
5502 : /*
5503 : * Initialize a StringInfo so that we can "receive" it using the standard
5504 : * recv-function infrastructure.
5505 : */
5506 24 : initReadOnlyStringInfo(&buf, VARDATA_ANY(sstate),
5507 24 : VARSIZE_ANY_EXHDR(sstate));
5508 :
5509 24 : result = makeNumericAggStateCurrentContext(false);
5510 :
5511 : /* N */
5512 24 : result->N = pq_getmsgint64(&buf);
5513 :
5514 : /* sumX */
5515 24 : numericvar_deserialize(&buf, &tmp_var);
5516 24 : accum_sum_add(&(result->sumX), &tmp_var);
5517 :
5518 : /* sumX2 */
5519 24 : numericvar_deserialize(&buf, &tmp_var);
5520 24 : accum_sum_add(&(result->sumX2), &tmp_var);
5521 :
5522 : /* maxScale */
5523 24 : result->maxScale = pq_getmsgint(&buf, 4);
5524 :
5525 : /* maxScaleCount */
5526 24 : result->maxScaleCount = pq_getmsgint64(&buf);
5527 :
5528 : /* NaNcount */
5529 24 : result->NaNcount = pq_getmsgint64(&buf);
5530 :
5531 : /* pInfcount */
5532 24 : result->pInfcount = pq_getmsgint64(&buf);
5533 :
5534 : /* nInfcount */
5535 24 : result->nInfcount = pq_getmsgint64(&buf);
5536 :
5537 24 : pq_getmsgend(&buf);
5538 :
5539 24 : free_var(&tmp_var);
5540 :
5541 24 : PG_RETURN_POINTER(result);
5542 : }
5543 :
5544 : /*
5545 : * Generic inverse transition function for numeric aggregates
5546 : * (with or without requirement for X^2).
5547 : */
5548 : Datum
5549 228 : numeric_accum_inv(PG_FUNCTION_ARGS)
5550 : {
5551 : NumericAggState *state;
5552 :
5553 228 : state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
5554 :
5555 : /* Should not get here with no state */
5556 228 : if (state == NULL)
5557 0 : elog(ERROR, "numeric_accum_inv called with NULL state");
5558 :
5559 228 : if (!PG_ARGISNULL(1))
5560 : {
5561 : /* If we fail to perform the inverse transition, return NULL */
5562 198 : if (!do_numeric_discard(state, PG_GETARG_NUMERIC(1)))
5563 6 : PG_RETURN_NULL();
5564 : }
5565 :
5566 222 : PG_RETURN_POINTER(state);
5567 : }
5568 :
5569 :
5570 : /*
5571 : * Integer data types in general use Numeric accumulators to share code
5572 : * and avoid risk of overflow.
5573 : *
5574 : * However for performance reasons optimized special-purpose accumulator
5575 : * routines are used when possible.
5576 : *
5577 : * On platforms with 128-bit integer support, the 128-bit routines will be
5578 : * used when sum(X) or sum(X*X) fit into 128-bit.
5579 : *
5580 : * For 16 and 32 bit inputs, the N and sum(X) fit into 64-bit so the 64-bit
5581 : * accumulators will be used for SUM and AVG of these data types.
5582 : */
5583 :
5584 : #ifdef HAVE_INT128
5585 : typedef struct Int128AggState
5586 : {
5587 : bool calcSumX2; /* if true, calculate sumX2 */
5588 : int64 N; /* count of processed numbers */
5589 : int128 sumX; /* sum of processed numbers */
5590 : int128 sumX2; /* sum of squares of processed numbers */
5591 : } Int128AggState;
5592 :
5593 : /*
5594 : * Prepare state data for a 128-bit aggregate function that needs to compute
5595 : * sum, count and optionally sum of squares of the input.
5596 : */
5597 : static Int128AggState *
5598 846 : makeInt128AggState(FunctionCallInfo fcinfo, bool calcSumX2)
5599 : {
5600 : Int128AggState *state;
5601 : MemoryContext agg_context;
5602 : MemoryContext old_context;
5603 :
5604 846 : if (!AggCheckCallContext(fcinfo, &agg_context))
5605 0 : elog(ERROR, "aggregate function called in non-aggregate context");
5606 :
5607 846 : old_context = MemoryContextSwitchTo(agg_context);
5608 :
5609 846 : state = (Int128AggState *) palloc0(sizeof(Int128AggState));
5610 846 : state->calcSumX2 = calcSumX2;
5611 :
5612 846 : MemoryContextSwitchTo(old_context);
5613 :
5614 846 : return state;
5615 : }
5616 :
5617 : /*
5618 : * Like makeInt128AggState(), but allocate the state in the current memory
5619 : * context.
5620 : */
5621 : static Int128AggState *
5622 22 : makeInt128AggStateCurrentContext(bool calcSumX2)
5623 : {
5624 : Int128AggState *state;
5625 :
5626 22 : state = (Int128AggState *) palloc0(sizeof(Int128AggState));
5627 22 : state->calcSumX2 = calcSumX2;
5628 :
5629 22 : return state;
5630 : }
5631 :
5632 : /*
5633 : * Accumulate a new input value for 128-bit aggregate functions.
5634 : */
5635 : static void
5636 554190 : do_int128_accum(Int128AggState *state, int128 newval)
5637 : {
5638 554190 : if (state->calcSumX2)
5639 242360 : state->sumX2 += newval * newval;
5640 :
5641 554190 : state->sumX += newval;
5642 554190 : state->N++;
5643 554190 : }
5644 :
5645 : /*
5646 : * Remove an input value from the aggregated state.
5647 : */
5648 : static void
5649 312 : do_int128_discard(Int128AggState *state, int128 newval)
5650 : {
5651 312 : if (state->calcSumX2)
5652 288 : state->sumX2 -= newval * newval;
5653 :
5654 312 : state->sumX -= newval;
5655 312 : state->N--;
5656 312 : }
5657 :
5658 : typedef Int128AggState PolyNumAggState;
5659 : #define makePolyNumAggState makeInt128AggState
5660 : #define makePolyNumAggStateCurrentContext makeInt128AggStateCurrentContext
5661 : #else
5662 : typedef NumericAggState PolyNumAggState;
5663 : #define makePolyNumAggState makeNumericAggState
5664 : #define makePolyNumAggStateCurrentContext makeNumericAggStateCurrentContext
5665 : #endif
5666 :
5667 : Datum
5668 198 : int2_accum(PG_FUNCTION_ARGS)
5669 : {
5670 : PolyNumAggState *state;
5671 :
5672 198 : state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
5673 :
5674 : /* Create the state data on the first call */
5675 198 : if (state == NULL)
5676 36 : state = makePolyNumAggState(fcinfo, true);
5677 :
5678 198 : if (!PG_ARGISNULL(1))
5679 : {
5680 : #ifdef HAVE_INT128
5681 180 : do_int128_accum(state, (int128) PG_GETARG_INT16(1));
5682 : #else
5683 : do_numeric_accum(state, int64_to_numeric(PG_GETARG_INT16(1)));
5684 : #endif
5685 : }
5686 :
5687 198 : PG_RETURN_POINTER(state);
5688 : }
5689 :
5690 : Datum
5691 242198 : int4_accum(PG_FUNCTION_ARGS)
5692 : {
5693 : PolyNumAggState *state;
5694 :
5695 242198 : state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
5696 :
5697 : /* Create the state data on the first call */
5698 242198 : if (state == NULL)
5699 64 : state = makePolyNumAggState(fcinfo, true);
5700 :
5701 242198 : if (!PG_ARGISNULL(1))
5702 : {
5703 : #ifdef HAVE_INT128
5704 242180 : do_int128_accum(state, (int128) PG_GETARG_INT32(1));
5705 : #else
5706 : do_numeric_accum(state, int64_to_numeric(PG_GETARG_INT32(1)));
5707 : #endif
5708 : }
5709 :
5710 242198 : PG_RETURN_POINTER(state);
5711 : }
5712 :
5713 : Datum
5714 240198 : int8_accum(PG_FUNCTION_ARGS)
5715 : {
5716 : NumericAggState *state;
5717 :
5718 240198 : state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
5719 :
5720 : /* Create the state data on the first call */
5721 240198 : if (state == NULL)
5722 48 : state = makeNumericAggState(fcinfo, true);
5723 :
5724 240198 : if (!PG_ARGISNULL(1))
5725 240180 : do_numeric_accum(state, int64_to_numeric(PG_GETARG_INT64(1)));
5726 :
5727 240198 : PG_RETURN_POINTER(state);
5728 : }
5729 :
5730 : /*
5731 : * Combine function for numeric aggregates which require sumX2
5732 : */
5733 : Datum
5734 8 : numeric_poly_combine(PG_FUNCTION_ARGS)
5735 : {
5736 : PolyNumAggState *state1;
5737 : PolyNumAggState *state2;
5738 : MemoryContext agg_context;
5739 : MemoryContext old_context;
5740 :
5741 8 : if (!AggCheckCallContext(fcinfo, &agg_context))
5742 0 : elog(ERROR, "aggregate function called in non-aggregate context");
5743 :
5744 8 : state1 = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
5745 8 : state2 = PG_ARGISNULL(1) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(1);
5746 :
5747 8 : if (state2 == NULL)
5748 0 : PG_RETURN_POINTER(state1);
5749 :
5750 : /* manually copy all fields from state2 to state1 */
5751 8 : if (state1 == NULL)
5752 : {
5753 6 : old_context = MemoryContextSwitchTo(agg_context);
5754 :
5755 6 : state1 = makePolyNumAggState(fcinfo, true);
5756 6 : state1->N = state2->N;
5757 :
5758 : #ifdef HAVE_INT128
5759 6 : state1->sumX = state2->sumX;
5760 6 : state1->sumX2 = state2->sumX2;
5761 : #else
5762 : accum_sum_copy(&state1->sumX, &state2->sumX);
5763 : accum_sum_copy(&state1->sumX2, &state2->sumX2);
5764 : #endif
5765 :
5766 6 : MemoryContextSwitchTo(old_context);
5767 :
5768 6 : PG_RETURN_POINTER(state1);
5769 : }
5770 :
5771 2 : if (state2->N > 0)
5772 : {
5773 2 : state1->N += state2->N;
5774 :
5775 : #ifdef HAVE_INT128
5776 2 : state1->sumX += state2->sumX;
5777 2 : state1->sumX2 += state2->sumX2;
5778 : #else
5779 : /* The rest of this needs to work in the aggregate context */
5780 : old_context = MemoryContextSwitchTo(agg_context);
5781 :
5782 : /* Accumulate sums */
5783 : accum_sum_combine(&state1->sumX, &state2->sumX);
5784 : accum_sum_combine(&state1->sumX2, &state2->sumX2);
5785 :
5786 : MemoryContextSwitchTo(old_context);
5787 : #endif
5788 :
5789 : }
5790 2 : PG_RETURN_POINTER(state1);
5791 : }
5792 :
5793 : /*
5794 : * numeric_poly_serialize
5795 : * Serialize PolyNumAggState into bytea for aggregate functions which
5796 : * require sumX2.
5797 : */
5798 : Datum
5799 8 : numeric_poly_serialize(PG_FUNCTION_ARGS)
5800 : {
5801 : PolyNumAggState *state;
5802 : StringInfoData buf;
5803 : bytea *result;
5804 : NumericVar tmp_var;
5805 :
5806 : /* Ensure we disallow calling when not in aggregate context */
5807 8 : if (!AggCheckCallContext(fcinfo, NULL))
5808 0 : elog(ERROR, "aggregate function called in non-aggregate context");
5809 :
5810 8 : state = (PolyNumAggState *) PG_GETARG_POINTER(0);
5811 :
5812 : /*
5813 : * If the platform supports int128 then sumX and sumX2 will be a 128 bit
5814 : * integer type. Here we'll convert that into a numeric type so that the
5815 : * combine state is in the same format for both int128 enabled machines
5816 : * and machines which don't support that type. The logic here is that one
5817 : * day we might like to send these over to another server for further
5818 : * processing and we want a standard format to work with.
5819 : */
5820 :
5821 8 : init_var(&tmp_var);
5822 :
5823 8 : pq_begintypsend(&buf);
5824 :
5825 : /* N */
5826 8 : pq_sendint64(&buf, state->N);
5827 :
5828 : /* sumX */
5829 : #ifdef HAVE_INT128
5830 8 : int128_to_numericvar(state->sumX, &tmp_var);
5831 : #else
5832 : accum_sum_final(&state->sumX, &tmp_var);
5833 : #endif
5834 8 : numericvar_serialize(&buf, &tmp_var);
5835 :
5836 : /* sumX2 */
5837 : #ifdef HAVE_INT128
5838 8 : int128_to_numericvar(state->sumX2, &tmp_var);
5839 : #else
5840 : accum_sum_final(&state->sumX2, &tmp_var);
5841 : #endif
5842 8 : numericvar_serialize(&buf, &tmp_var);
5843 :
5844 8 : result = pq_endtypsend(&buf);
5845 :
5846 8 : free_var(&tmp_var);
5847 :
5848 8 : PG_RETURN_BYTEA_P(result);
5849 : }
5850 :
5851 : /*
5852 : * numeric_poly_deserialize
5853 : * Deserialize PolyNumAggState from bytea for aggregate functions which
5854 : * require sumX2.
5855 : */
5856 : Datum
5857 8 : numeric_poly_deserialize(PG_FUNCTION_ARGS)
5858 : {
5859 : bytea *sstate;
5860 : PolyNumAggState *result;
5861 : StringInfoData buf;
5862 : NumericVar tmp_var;
5863 :
5864 8 : if (!AggCheckCallContext(fcinfo, NULL))
5865 0 : elog(ERROR, "aggregate function called in non-aggregate context");
5866 :
5867 8 : sstate = PG_GETARG_BYTEA_PP(0);
5868 :
5869 8 : init_var(&tmp_var);
5870 :
5871 : /*
5872 : * Initialize a StringInfo so that we can "receive" it using the standard
5873 : * recv-function infrastructure.
5874 : */
5875 8 : initReadOnlyStringInfo(&buf, VARDATA_ANY(sstate),
5876 8 : VARSIZE_ANY_EXHDR(sstate));
5877 :
5878 8 : result = makePolyNumAggStateCurrentContext(false);
5879 :
5880 : /* N */
5881 8 : result->N = pq_getmsgint64(&buf);
5882 :
5883 : /* sumX */
5884 8 : numericvar_deserialize(&buf, &tmp_var);
5885 : #ifdef HAVE_INT128
5886 8 : numericvar_to_int128(&tmp_var, &result->sumX);
5887 : #else
5888 : accum_sum_add(&result->sumX, &tmp_var);
5889 : #endif
5890 :
5891 : /* sumX2 */
5892 8 : numericvar_deserialize(&buf, &tmp_var);
5893 : #ifdef HAVE_INT128
5894 8 : numericvar_to_int128(&tmp_var, &result->sumX2);
5895 : #else
5896 : accum_sum_add(&result->sumX2, &tmp_var);
5897 : #endif
5898 :
5899 8 : pq_getmsgend(&buf);
5900 :
5901 8 : free_var(&tmp_var);
5902 :
5903 8 : PG_RETURN_POINTER(result);
5904 : }
5905 :
5906 : /*
5907 : * Transition function for int8 input when we don't need sumX2.
5908 : */
5909 : Datum
5910 313126 : int8_avg_accum(PG_FUNCTION_ARGS)
5911 : {
5912 : PolyNumAggState *state;
5913 :
5914 313126 : state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
5915 :
5916 : /* Create the state data on the first call */
5917 313126 : if (state == NULL)
5918 728 : state = makePolyNumAggState(fcinfo, false);
5919 :
5920 313126 : if (!PG_ARGISNULL(1))
5921 : {
5922 : #ifdef HAVE_INT128
5923 311830 : do_int128_accum(state, (int128) PG_GETARG_INT64(1));
5924 : #else
5925 : do_numeric_accum(state, int64_to_numeric(PG_GETARG_INT64(1)));
5926 : #endif
5927 : }
5928 :
5929 313126 : PG_RETURN_POINTER(state);
5930 : }
5931 :
5932 : /*
5933 : * Combine function for PolyNumAggState for aggregates which don't require
5934 : * sumX2
5935 : */
5936 : Datum
5937 14 : int8_avg_combine(PG_FUNCTION_ARGS)
5938 : {
5939 : PolyNumAggState *state1;
5940 : PolyNumAggState *state2;
5941 : MemoryContext agg_context;
5942 : MemoryContext old_context;
5943 :
5944 14 : if (!AggCheckCallContext(fcinfo, &agg_context))
5945 0 : elog(ERROR, "aggregate function called in non-aggregate context");
5946 :
5947 14 : state1 = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
5948 14 : state2 = PG_ARGISNULL(1) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(1);
5949 :
5950 14 : if (state2 == NULL)
5951 0 : PG_RETURN_POINTER(state1);
5952 :
5953 : /* manually copy all fields from state2 to state1 */
5954 14 : if (state1 == NULL)
5955 : {
5956 12 : old_context = MemoryContextSwitchTo(agg_context);
5957 :
5958 12 : state1 = makePolyNumAggState(fcinfo, false);
5959 12 : state1->N = state2->N;
5960 :
5961 : #ifdef HAVE_INT128
5962 12 : state1->sumX = state2->sumX;
5963 : #else
5964 : accum_sum_copy(&state1->sumX, &state2->sumX);
5965 : #endif
5966 12 : MemoryContextSwitchTo(old_context);
5967 :
5968 12 : PG_RETURN_POINTER(state1);
5969 : }
5970 :
5971 2 : if (state2->N > 0)
5972 : {
5973 2 : state1->N += state2->N;
5974 :
5975 : #ifdef HAVE_INT128
5976 2 : state1->sumX += state2->sumX;
5977 : #else
5978 : /* The rest of this needs to work in the aggregate context */
5979 : old_context = MemoryContextSwitchTo(agg_context);
5980 :
5981 : /* Accumulate sums */
5982 : accum_sum_combine(&state1->sumX, &state2->sumX);
5983 :
5984 : MemoryContextSwitchTo(old_context);
5985 : #endif
5986 :
5987 : }
5988 2 : PG_RETURN_POINTER(state1);
5989 : }
5990 :
5991 : /*
5992 : * int8_avg_serialize
5993 : * Serialize PolyNumAggState into bytea using the standard
5994 : * recv-function infrastructure.
5995 : */
5996 : Datum
5997 14 : int8_avg_serialize(PG_FUNCTION_ARGS)
5998 : {
5999 : PolyNumAggState *state;
6000 : StringInfoData buf;
6001 : bytea *result;
6002 : NumericVar tmp_var;
6003 :
6004 : /* Ensure we disallow calling when not in aggregate context */
6005 14 : if (!AggCheckCallContext(fcinfo, NULL))
6006 0 : elog(ERROR, "aggregate function called in non-aggregate context");
6007 :
6008 14 : state = (PolyNumAggState *) PG_GETARG_POINTER(0);
6009 :
6010 : /*
6011 : * If the platform supports int128 then sumX will be a 128 integer type.
6012 : * Here we'll convert that into a numeric type so that the combine state
6013 : * is in the same format for both int128 enabled machines and machines
6014 : * which don't support that type. The logic here is that one day we might
6015 : * like to send these over to another server for further processing and we
6016 : * want a standard format to work with.
6017 : */
6018 :
6019 14 : init_var(&tmp_var);
6020 :
6021 14 : pq_begintypsend(&buf);
6022 :
6023 : /* N */
6024 14 : pq_sendint64(&buf, state->N);
6025 :
6026 : /* sumX */
6027 : #ifdef HAVE_INT128
6028 14 : int128_to_numericvar(state->sumX, &tmp_var);
6029 : #else
6030 : accum_sum_final(&state->sumX, &tmp_var);
6031 : #endif
6032 14 : numericvar_serialize(&buf, &tmp_var);
6033 :
6034 14 : result = pq_endtypsend(&buf);
6035 :
6036 14 : free_var(&tmp_var);
6037 :
6038 14 : PG_RETURN_BYTEA_P(result);
6039 : }
6040 :
6041 : /*
6042 : * int8_avg_deserialize
6043 : * Deserialize bytea back into PolyNumAggState.
6044 : */
6045 : Datum
6046 14 : int8_avg_deserialize(PG_FUNCTION_ARGS)
6047 : {
6048 : bytea *sstate;
6049 : PolyNumAggState *result;
6050 : StringInfoData buf;
6051 : NumericVar tmp_var;
6052 :
6053 14 : if (!AggCheckCallContext(fcinfo, NULL))
6054 0 : elog(ERROR, "aggregate function called in non-aggregate context");
6055 :
6056 14 : sstate = PG_GETARG_BYTEA_PP(0);
6057 :
6058 14 : init_var(&tmp_var);
6059 :
6060 : /*
6061 : * Initialize a StringInfo so that we can "receive" it using the standard
6062 : * recv-function infrastructure.
6063 : */
6064 14 : initReadOnlyStringInfo(&buf, VARDATA_ANY(sstate),
6065 14 : VARSIZE_ANY_EXHDR(sstate));
6066 :
6067 14 : result = makePolyNumAggStateCurrentContext(false);
6068 :
6069 : /* N */
6070 14 : result->N = pq_getmsgint64(&buf);
6071 :
6072 : /* sumX */
6073 14 : numericvar_deserialize(&buf, &tmp_var);
6074 : #ifdef HAVE_INT128
6075 14 : numericvar_to_int128(&tmp_var, &result->sumX);
6076 : #else
6077 : accum_sum_add(&result->sumX, &tmp_var);
6078 : #endif
6079 :
6080 14 : pq_getmsgend(&buf);
6081 :
6082 14 : free_var(&tmp_var);
6083 :
6084 14 : PG_RETURN_POINTER(result);
6085 : }
6086 :
6087 : /*
6088 : * Inverse transition functions to go with the above.
6089 : */
6090 :
6091 : Datum
6092 162 : int2_accum_inv(PG_FUNCTION_ARGS)
6093 : {
6094 : PolyNumAggState *state;
6095 :
6096 162 : state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
6097 :
6098 : /* Should not get here with no state */
6099 162 : if (state == NULL)
6100 0 : elog(ERROR, "int2_accum_inv called with NULL state");
6101 :
6102 162 : if (!PG_ARGISNULL(1))
6103 : {
6104 : #ifdef HAVE_INT128
6105 144 : do_int128_discard(state, (int128) PG_GETARG_INT16(1));
6106 : #else
6107 : /* Should never fail, all inputs have dscale 0 */
6108 : if (!do_numeric_discard(state, int64_to_numeric(PG_GETARG_INT16(1))))
6109 : elog(ERROR, "do_numeric_discard failed unexpectedly");
6110 : #endif
6111 : }
6112 :
6113 162 : PG_RETURN_POINTER(state);
6114 : }
6115 :
6116 : Datum
6117 162 : int4_accum_inv(PG_FUNCTION_ARGS)
6118 : {
6119 : PolyNumAggState *state;
6120 :
6121 162 : state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
6122 :
6123 : /* Should not get here with no state */
6124 162 : if (state == NULL)
6125 0 : elog(ERROR, "int4_accum_inv called with NULL state");
6126 :
6127 162 : if (!PG_ARGISNULL(1))
6128 : {
6129 : #ifdef HAVE_INT128
6130 144 : do_int128_discard(state, (int128) PG_GETARG_INT32(1));
6131 : #else
6132 : /* Should never fail, all inputs have dscale 0 */
6133 : if (!do_numeric_discard(state, int64_to_numeric(PG_GETARG_INT32(1))))
6134 : elog(ERROR, "do_numeric_discard failed unexpectedly");
6135 : #endif
6136 : }
6137 :
6138 162 : PG_RETURN_POINTER(state);
6139 : }
6140 :
6141 : Datum
6142 162 : int8_accum_inv(PG_FUNCTION_ARGS)
6143 : {
6144 : NumericAggState *state;
6145 :
6146 162 : state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
6147 :
6148 : /* Should not get here with no state */
6149 162 : if (state == NULL)
6150 0 : elog(ERROR, "int8_accum_inv called with NULL state");
6151 :
6152 162 : if (!PG_ARGISNULL(1))
6153 : {
6154 : /* Should never fail, all inputs have dscale 0 */
6155 144 : if (!do_numeric_discard(state, int64_to_numeric(PG_GETARG_INT64(1))))
6156 0 : elog(ERROR, "do_numeric_discard failed unexpectedly");
6157 : }
6158 :
6159 162 : PG_RETURN_POINTER(state);
6160 : }
6161 :
6162 : Datum
6163 36 : int8_avg_accum_inv(PG_FUNCTION_ARGS)
6164 : {
6165 : PolyNumAggState *state;
6166 :
6167 36 : state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
6168 :
6169 : /* Should not get here with no state */
6170 36 : if (state == NULL)
6171 0 : elog(ERROR, "int8_avg_accum_inv called with NULL state");
6172 :
6173 36 : if (!PG_ARGISNULL(1))
6174 : {
6175 : #ifdef HAVE_INT128
6176 24 : do_int128_discard(state, (int128) PG_GETARG_INT64(1));
6177 : #else
6178 : /* Should never fail, all inputs have dscale 0 */
6179 : if (!do_numeric_discard(state, int64_to_numeric(PG_GETARG_INT64(1))))
6180 : elog(ERROR, "do_numeric_discard failed unexpectedly");
6181 : #endif
6182 : }
6183 :
6184 36 : PG_RETURN_POINTER(state);
6185 : }
6186 :
6187 : Datum
6188 960 : numeric_poly_sum(PG_FUNCTION_ARGS)
6189 : {
6190 : #ifdef HAVE_INT128
6191 : PolyNumAggState *state;
6192 : Numeric res;
6193 : NumericVar result;
6194 :
6195 960 : state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
6196 :
6197 : /* If there were no non-null inputs, return NULL */
6198 960 : if (state == NULL || state->N == 0)
6199 24 : PG_RETURN_NULL();
6200 :
6201 936 : init_var(&result);
6202 :
6203 936 : int128_to_numericvar(state->sumX, &result);
6204 :
6205 936 : res = make_result(&result);
6206 :
6207 936 : free_var(&result);
6208 :
6209 936 : PG_RETURN_NUMERIC(res);
6210 : #else
6211 : return numeric_sum(fcinfo);
6212 : #endif
6213 : }
6214 :
6215 : Datum
6216 36 : numeric_poly_avg(PG_FUNCTION_ARGS)
6217 : {
6218 : #ifdef HAVE_INT128
6219 : PolyNumAggState *state;
6220 : NumericVar result;
6221 : Datum countd,
6222 : sumd;
6223 :
6224 36 : state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
6225 :
6226 : /* If there were no non-null inputs, return NULL */
6227 36 : if (state == NULL || state->N == 0)
6228 18 : PG_RETURN_NULL();
6229 :
6230 18 : init_var(&result);
6231 :
6232 18 : int128_to_numericvar(state->sumX, &result);
6233 :
6234 18 : countd = NumericGetDatum(int64_to_numeric(state->N));
6235 18 : sumd = NumericGetDatum(make_result(&result));
6236 :
6237 18 : free_var(&result);
6238 :
6239 18 : PG_RETURN_DATUM(DirectFunctionCall2(numeric_div, sumd, countd));
6240 : #else
6241 : return numeric_avg(fcinfo);
6242 : #endif
6243 : }
6244 :
6245 : Datum
6246 78 : numeric_avg(PG_FUNCTION_ARGS)
6247 : {
6248 : NumericAggState *state;
6249 : Datum N_datum;
6250 : Datum sumX_datum;
6251 : NumericVar sumX_var;
6252 :
6253 78 : state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
6254 :
6255 : /* If there were no non-null inputs, return NULL */
6256 78 : if (state == NULL || NA_TOTAL_COUNT(state) == 0)
6257 18 : PG_RETURN_NULL();
6258 :
6259 60 : if (state->NaNcount > 0) /* there was at least one NaN input */
6260 6 : PG_RETURN_NUMERIC(make_result(&const_nan));
6261 :
6262 : /* adding plus and minus infinities gives NaN */
6263 54 : if (state->pInfcount > 0 && state->nInfcount > 0)
6264 6 : PG_RETURN_NUMERIC(make_result(&const_nan));
6265 48 : if (state->pInfcount > 0)
6266 18 : PG_RETURN_NUMERIC(make_result(&const_pinf));
6267 30 : if (state->nInfcount > 0)
6268 6 : PG_RETURN_NUMERIC(make_result(&const_ninf));
6269 :
6270 24 : N_datum = NumericGetDatum(int64_to_numeric(state->N));
6271 :
6272 24 : init_var(&sumX_var);
6273 24 : accum_sum_final(&state->sumX, &sumX_var);
6274 24 : sumX_datum = NumericGetDatum(make_result(&sumX_var));
6275 24 : free_var(&sumX_var);
6276 :
6277 24 : PG_RETURN_DATUM(DirectFunctionCall2(numeric_div, sumX_datum, N_datum));
6278 : }
6279 :
6280 : Datum
6281 170906 : numeric_sum(PG_FUNCTION_ARGS)
6282 : {
6283 : NumericAggState *state;
6284 : NumericVar sumX_var;
6285 : Numeric result;
6286 :
6287 170906 : state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
6288 :
6289 : /* If there were no non-null inputs, return NULL */
6290 170906 : if (state == NULL || NA_TOTAL_COUNT(state) == 0)
6291 18 : PG_RETURN_NULL();
6292 :
6293 170888 : if (state->NaNcount > 0) /* there was at least one NaN input */
6294 18 : PG_RETURN_NUMERIC(make_result(&const_nan));
6295 :
6296 : /* adding plus and minus infinities gives NaN */
6297 170870 : if (state->pInfcount > 0 && state->nInfcount > 0)
6298 6 : PG_RETURN_NUMERIC(make_result(&const_nan));
6299 170864 : if (state->pInfcount > 0)
6300 18 : PG_RETURN_NUMERIC(make_result(&const_pinf));
6301 170846 : if (state->nInfcount > 0)
6302 6 : PG_RETURN_NUMERIC(make_result(&const_ninf));
6303 :
6304 170840 : init_var(&sumX_var);
6305 170840 : accum_sum_final(&state->sumX, &sumX_var);
6306 170840 : result = make_result(&sumX_var);
6307 170840 : free_var(&sumX_var);
6308 :
6309 170840 : PG_RETURN_NUMERIC(result);
6310 : }
6311 :
6312 : /*
6313 : * Workhorse routine for the standard deviance and variance
6314 : * aggregates. 'state' is aggregate's transition state.
6315 : * 'variance' specifies whether we should calculate the
6316 : * variance or the standard deviation. 'sample' indicates whether the
6317 : * caller is interested in the sample or the population
6318 : * variance/stddev.
6319 : *
6320 : * If appropriate variance statistic is undefined for the input,
6321 : * *is_null is set to true and NULL is returned.
6322 : */
6323 : static Numeric
6324 986 : numeric_stddev_internal(NumericAggState *state,
6325 : bool variance, bool sample,
6326 : bool *is_null)
6327 : {
6328 : Numeric res;
6329 : NumericVar vN,
6330 : vsumX,
6331 : vsumX2,
6332 : vNminus1;
6333 : int64 totCount;
6334 : int rscale;
6335 :
6336 : /*
6337 : * Sample stddev and variance are undefined when N <= 1; population stddev
6338 : * is undefined when N == 0. Return NULL in either case (note that NaNs
6339 : * and infinities count as normal inputs for this purpose).
6340 : */
6341 986 : if (state == NULL || (totCount = NA_TOTAL_COUNT(state)) == 0)
6342 : {
6343 0 : *is_null = true;
6344 0 : return NULL;
6345 : }
6346 :
6347 986 : if (sample && totCount <= 1)
6348 : {
6349 132 : *is_null = true;
6350 132 : return NULL;
6351 : }
6352 :
6353 854 : *is_null = false;
6354 :
6355 : /*
6356 : * Deal with NaN and infinity cases. By analogy to the behavior of the
6357 : * float8 functions, any infinity input produces NaN output.
6358 : */
6359 854 : if (state->NaNcount > 0 || state->pInfcount > 0 || state->nInfcount > 0)
6360 54 : return make_result(&const_nan);
6361 :
6362 : /* OK, normal calculation applies */
6363 800 : init_var(&vN);
6364 800 : init_var(&vsumX);
6365 800 : init_var(&vsumX2);
6366 :
6367 800 : int64_to_numericvar(state->N, &vN);
6368 800 : accum_sum_final(&(state->sumX), &vsumX);
6369 800 : accum_sum_final(&(state->sumX2), &vsumX2);
6370 :
6371 800 : init_var(&vNminus1);
6372 800 : sub_var(&vN, &const_one, &vNminus1);
6373 :
6374 : /* compute rscale for mul_var calls */
6375 800 : rscale = vsumX.dscale * 2;
6376 :
6377 800 : mul_var(&vsumX, &vsumX, &vsumX, rscale); /* vsumX = sumX * sumX */
6378 800 : mul_var(&vN, &vsumX2, &vsumX2, rscale); /* vsumX2 = N * sumX2 */
6379 800 : sub_var(&vsumX2, &vsumX, &vsumX2); /* N * sumX2 - sumX * sumX */
6380 :
6381 800 : if (cmp_var(&vsumX2, &const_zero) <= 0)
6382 : {
6383 : /* Watch out for roundoff error producing a negative numerator */
6384 80 : res = make_result(&const_zero);
6385 : }
6386 : else
6387 : {
6388 720 : if (sample)
6389 492 : mul_var(&vN, &vNminus1, &vNminus1, 0); /* N * (N - 1) */
6390 : else
6391 228 : mul_var(&vN, &vN, &vNminus1, 0); /* N * N */
6392 720 : rscale = select_div_scale(&vsumX2, &vNminus1);
6393 720 : div_var(&vsumX2, &vNminus1, &vsumX, rscale, true, true); /* variance */
6394 720 : if (!variance)
6395 378 : sqrt_var(&vsumX, &vsumX, rscale); /* stddev */
6396 :
6397 720 : res = make_result(&vsumX);
6398 : }
6399 :
6400 800 : free_var(&vNminus1);
6401 800 : free_var(&vsumX);
6402 800 : free_var(&vsumX2);
6403 :
6404 800 : return res;
6405 : }
6406 :
6407 : Datum
6408 180 : numeric_var_samp(PG_FUNCTION_ARGS)
6409 : {
6410 : NumericAggState *state;
6411 : Numeric res;
6412 : bool is_null;
6413 :
6414 180 : state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
6415 :
6416 180 : res = numeric_stddev_internal(state, true, true, &is_null);
6417 :
6418 180 : if (is_null)
6419 42 : PG_RETURN_NULL();
6420 : else
6421 138 : PG_RETURN_NUMERIC(res);
6422 : }
6423 :
6424 : Datum
6425 174 : numeric_stddev_samp(PG_FUNCTION_ARGS)
6426 : {
6427 : NumericAggState *state;
6428 : Numeric res;
6429 : bool is_null;
6430 :
6431 174 : state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
6432 :
6433 174 : res = numeric_stddev_internal(state, false, true, &is_null);
6434 :
6435 174 : if (is_null)
6436 42 : PG_RETURN_NULL();
6437 : else
6438 132 : PG_RETURN_NUMERIC(res);
6439 : }
6440 :
6441 : Datum
6442 114 : numeric_var_pop(PG_FUNCTION_ARGS)
6443 : {
6444 : NumericAggState *state;
6445 : Numeric res;
6446 : bool is_null;
6447 :
6448 114 : state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
6449 :
6450 114 : res = numeric_stddev_internal(state, true, false, &is_null);
6451 :
6452 114 : if (is_null)
6453 0 : PG_RETURN_NULL();
6454 : else
6455 114 : PG_RETURN_NUMERIC(res);
6456 : }
6457 :
6458 : Datum
6459 96 : numeric_stddev_pop(PG_FUNCTION_ARGS)
6460 : {
6461 : NumericAggState *state;
6462 : Numeric res;
6463 : bool is_null;
6464 :
6465 96 : state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
6466 :
6467 96 : res = numeric_stddev_internal(state, false, false, &is_null);
6468 :
6469 96 : if (is_null)
6470 0 : PG_RETURN_NULL();
6471 : else
6472 96 : PG_RETURN_NUMERIC(res);
6473 : }
6474 :
6475 : #ifdef HAVE_INT128
6476 : static Numeric
6477 422 : numeric_poly_stddev_internal(Int128AggState *state,
6478 : bool variance, bool sample,
6479 : bool *is_null)
6480 : {
6481 : NumericAggState numstate;
6482 : Numeric res;
6483 :
6484 : /* Initialize an empty agg state */
6485 422 : memset(&numstate, 0, sizeof(NumericAggState));
6486 :
6487 422 : if (state)
6488 : {
6489 : NumericVar tmp_var;
6490 :
6491 422 : numstate.N = state->N;
6492 :
6493 422 : init_var(&tmp_var);
6494 :
6495 422 : int128_to_numericvar(state->sumX, &tmp_var);
6496 422 : accum_sum_add(&numstate.sumX, &tmp_var);
6497 :
6498 422 : int128_to_numericvar(state->sumX2, &tmp_var);
6499 422 : accum_sum_add(&numstate.sumX2, &tmp_var);
6500 :
6501 422 : free_var(&tmp_var);
6502 : }
6503 :
6504 422 : res = numeric_stddev_internal(&numstate, variance, sample, is_null);
6505 :
6506 422 : if (numstate.sumX.ndigits > 0)
6507 : {
6508 422 : pfree(numstate.sumX.pos_digits);
6509 422 : pfree(numstate.sumX.neg_digits);
6510 : }
6511 422 : if (numstate.sumX2.ndigits > 0)
6512 : {
6513 422 : pfree(numstate.sumX2.pos_digits);
6514 422 : pfree(numstate.sumX2.neg_digits);
6515 : }
6516 :
6517 422 : return res;
6518 : }
6519 : #endif
6520 :
6521 : Datum
6522 126 : numeric_poly_var_samp(PG_FUNCTION_ARGS)
6523 : {
6524 : #ifdef HAVE_INT128
6525 : PolyNumAggState *state;
6526 : Numeric res;
6527 : bool is_null;
6528 :
6529 126 : state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
6530 :
6531 126 : res = numeric_poly_stddev_internal(state, true, true, &is_null);
6532 :
6533 126 : if (is_null)
6534 24 : PG_RETURN_NULL();
6535 : else
6536 102 : PG_RETURN_NUMERIC(res);
6537 : #else
6538 : return numeric_var_samp(fcinfo);
6539 : #endif
6540 : }
6541 :
6542 : Datum
6543 164 : numeric_poly_stddev_samp(PG_FUNCTION_ARGS)
6544 : {
6545 : #ifdef HAVE_INT128
6546 : PolyNumAggState *state;
6547 : Numeric res;
6548 : bool is_null;
6549 :
6550 164 : state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
6551 :
6552 164 : res = numeric_poly_stddev_internal(state, false, true, &is_null);
6553 :
6554 164 : if (is_null)
6555 24 : PG_RETURN_NULL();
6556 : else
6557 140 : PG_RETURN_NUMERIC(res);
6558 : #else
6559 : return numeric_stddev_samp(fcinfo);
6560 : #endif
6561 : }
6562 :
6563 : Datum
6564 60 : numeric_poly_var_pop(PG_FUNCTION_ARGS)
6565 : {
6566 : #ifdef HAVE_INT128
6567 : PolyNumAggState *state;
6568 : Numeric res;
6569 : bool is_null;
6570 :
6571 60 : state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
6572 :
6573 60 : res = numeric_poly_stddev_internal(state, true, false, &is_null);
6574 :
6575 60 : if (is_null)
6576 0 : PG_RETURN_NULL();
6577 : else
6578 60 : PG_RETURN_NUMERIC(res);
6579 : #else
6580 : return numeric_var_pop(fcinfo);
6581 : #endif
6582 : }
6583 :
6584 : Datum
6585 72 : numeric_poly_stddev_pop(PG_FUNCTION_ARGS)
6586 : {
6587 : #ifdef HAVE_INT128
6588 : PolyNumAggState *state;
6589 : Numeric res;
6590 : bool is_null;
6591 :
6592 72 : state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
6593 :
6594 72 : res = numeric_poly_stddev_internal(state, false, false, &is_null);
6595 :
6596 72 : if (is_null)
6597 0 : PG_RETURN_NULL();
6598 : else
6599 72 : PG_RETURN_NUMERIC(res);
6600 : #else
6601 : return numeric_stddev_pop(fcinfo);
6602 : #endif
6603 : }
6604 :
6605 : /*
6606 : * SUM transition functions for integer datatypes.
6607 : *
6608 : * To avoid overflow, we use accumulators wider than the input datatype.
6609 : * A Numeric accumulator is needed for int8 input; for int4 and int2
6610 : * inputs, we use int8 accumulators which should be sufficient for practical
6611 : * purposes. (The latter two therefore don't really belong in this file,
6612 : * but we keep them here anyway.)
6613 : *
6614 : * Because SQL defines the SUM() of no values to be NULL, not zero,
6615 : * the initial condition of the transition data value needs to be NULL. This
6616 : * means we can't rely on ExecAgg to automatically insert the first non-null
6617 : * data value into the transition data: it doesn't know how to do the type
6618 : * conversion. The upshot is that these routines have to be marked non-strict
6619 : * and handle substitution of the first non-null input themselves.
6620 : *
6621 : * Note: these functions are used only in plain aggregation mode.
6622 : * In moving-aggregate mode, we use intX_avg_accum and intX_avg_accum_inv.
6623 : */
6624 :
6625 : Datum
6626 24 : int2_sum(PG_FUNCTION_ARGS)
6627 : {
6628 : int64 newval;
6629 :
6630 24 : if (PG_ARGISNULL(0))
6631 : {
6632 : /* No non-null input seen so far... */
6633 6 : if (PG_ARGISNULL(1))
6634 0 : PG_RETURN_NULL(); /* still no non-null */
6635 : /* This is the first non-null input. */
6636 6 : newval = (int64) PG_GETARG_INT16(1);
6637 6 : PG_RETURN_INT64(newval);
6638 : }
6639 :
6640 : /*
6641 : * If we're invoked as an aggregate, we can cheat and modify our first
6642 : * parameter in-place to avoid palloc overhead. If not, we need to return
6643 : * the new value of the transition variable. (If int8 is pass-by-value,
6644 : * then of course this is useless as well as incorrect, so just ifdef it
6645 : * out.)
6646 : */
6647 : #ifndef USE_FLOAT8_BYVAL /* controls int8 too */
6648 : if (AggCheckCallContext(fcinfo, NULL))
6649 : {
6650 : int64 *oldsum = (int64 *) PG_GETARG_POINTER(0);
6651 :
6652 : /* Leave the running sum unchanged in the new input is null */
6653 : if (!PG_ARGISNULL(1))
6654 : *oldsum = *oldsum + (int64) PG_GETARG_INT16(1);
6655 :
6656 : PG_RETURN_POINTER(oldsum);
6657 : }
6658 : else
6659 : #endif
6660 : {
6661 18 : int64 oldsum = PG_GETARG_INT64(0);
6662 :
6663 : /* Leave sum unchanged if new input is null. */
6664 18 : if (PG_ARGISNULL(1))
6665 0 : PG_RETURN_INT64(oldsum);
6666 :
6667 : /* OK to do the addition. */
6668 18 : newval = oldsum + (int64) PG_GETARG_INT16(1);
6669 :
6670 18 : PG_RETURN_INT64(newval);
6671 : }
6672 : }
6673 :
6674 : Datum
6675 3692120 : int4_sum(PG_FUNCTION_ARGS)
6676 : {
6677 : int64 newval;
6678 :
6679 3692120 : if (PG_ARGISNULL(0))
6680 : {
6681 : /* No non-null input seen so far... */
6682 206562 : if (PG_ARGISNULL(1))
6683 986 : PG_RETURN_NULL(); /* still no non-null */
6684 : /* This is the first non-null input. */
6685 205576 : newval = (int64) PG_GETARG_INT32(1);
6686 205576 : PG_RETURN_INT64(newval);
6687 : }
6688 :
6689 : /*
6690 : * If we're invoked as an aggregate, we can cheat and modify our first
6691 : * parameter in-place to avoid palloc overhead. If not, we need to return
6692 : * the new value of the transition variable. (If int8 is pass-by-value,
6693 : * then of course this is useless as well as incorrect, so just ifdef it
6694 : * out.)
6695 : */
6696 : #ifndef USE_FLOAT8_BYVAL /* controls int8 too */
6697 : if (AggCheckCallContext(fcinfo, NULL))
6698 : {
6699 : int64 *oldsum = (int64 *) PG_GETARG_POINTER(0);
6700 :
6701 : /* Leave the running sum unchanged in the new input is null */
6702 : if (!PG_ARGISNULL(1))
6703 : *oldsum = *oldsum + (int64) PG_GETARG_INT32(1);
6704 :
6705 : PG_RETURN_POINTER(oldsum);
6706 : }
6707 : else
6708 : #endif
6709 : {
6710 3485558 : int64 oldsum = PG_GETARG_INT64(0);
6711 :
6712 : /* Leave sum unchanged if new input is null. */
6713 3485558 : if (PG_ARGISNULL(1))
6714 30874 : PG_RETURN_INT64(oldsum);
6715 :
6716 : /* OK to do the addition. */
6717 3454684 : newval = oldsum + (int64) PG_GETARG_INT32(1);
6718 :
6719 3454684 : PG_RETURN_INT64(newval);
6720 : }
6721 : }
6722 :
6723 : /*
6724 : * Note: this function is obsolete, it's no longer used for SUM(int8).
6725 : */
6726 : Datum
6727 0 : int8_sum(PG_FUNCTION_ARGS)
6728 : {
6729 : Numeric oldsum;
6730 :
6731 0 : if (PG_ARGISNULL(0))
6732 : {
6733 : /* No non-null input seen so far... */
6734 0 : if (PG_ARGISNULL(1))
6735 0 : PG_RETURN_NULL(); /* still no non-null */
6736 : /* This is the first non-null input. */
6737 0 : PG_RETURN_NUMERIC(int64_to_numeric(PG_GETARG_INT64(1)));
6738 : }
6739 :
6740 : /*
6741 : * Note that we cannot special-case the aggregate case here, as we do for
6742 : * int2_sum and int4_sum: numeric is of variable size, so we cannot modify
6743 : * our first parameter in-place.
6744 : */
6745 :
6746 0 : oldsum = PG_GETARG_NUMERIC(0);
6747 :
6748 : /* Leave sum unchanged if new input is null. */
6749 0 : if (PG_ARGISNULL(1))
6750 0 : PG_RETURN_NUMERIC(oldsum);
6751 :
6752 : /* OK to do the addition. */
6753 0 : PG_RETURN_DATUM(DirectFunctionCall2(numeric_add,
6754 : NumericGetDatum(oldsum),
6755 : NumericGetDatum(int64_to_numeric(PG_GETARG_INT64(1)))));
6756 : }
6757 :
6758 :
6759 : /*
6760 : * Routines for avg(int2) and avg(int4). The transition datatype
6761 : * is a two-element int8 array, holding count and sum.
6762 : *
6763 : * These functions are also used for sum(int2) and sum(int4) when
6764 : * operating in moving-aggregate mode, since for correct inverse transitions
6765 : * we need to count the inputs.
6766 : */
6767 :
6768 : typedef struct Int8TransTypeData
6769 : {
6770 : int64 count;
6771 : int64 sum;
6772 : } Int8TransTypeData;
6773 :
6774 : Datum
6775 42 : int2_avg_accum(PG_FUNCTION_ARGS)
6776 : {
6777 : ArrayType *transarray;
6778 42 : int16 newval = PG_GETARG_INT16(1);
6779 : Int8TransTypeData *transdata;
6780 :
6781 : /*
6782 : * If we're invoked as an aggregate, we can cheat and modify our first
6783 : * parameter in-place to reduce palloc overhead. Otherwise we need to make
6784 : * a copy of it before scribbling on it.
6785 : */
6786 42 : if (AggCheckCallContext(fcinfo, NULL))
6787 42 : transarray = PG_GETARG_ARRAYTYPE_P(0);
6788 : else
6789 0 : transarray = PG_GETARG_ARRAYTYPE_P_COPY(0);
6790 :
6791 42 : if (ARR_HASNULL(transarray) ||
6792 42 : ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
6793 0 : elog(ERROR, "expected 2-element int8 array");
6794 :
6795 42 : transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
6796 42 : transdata->count++;
6797 42 : transdata->sum += newval;
6798 :
6799 42 : PG_RETURN_ARRAYTYPE_P(transarray);
6800 : }
6801 :
6802 : Datum
6803 2620302 : int4_avg_accum(PG_FUNCTION_ARGS)
6804 : {
6805 : ArrayType *transarray;
6806 2620302 : int32 newval = PG_GETARG_INT32(1);
6807 : Int8TransTypeData *transdata;
6808 :
6809 : /*
6810 : * If we're invoked as an aggregate, we can cheat and modify our first
6811 : * parameter in-place to reduce palloc overhead. Otherwise we need to make
6812 : * a copy of it before scribbling on it.
6813 : */
6814 2620302 : if (AggCheckCallContext(fcinfo, NULL))
6815 2620302 : transarray = PG_GETARG_ARRAYTYPE_P(0);
6816 : else
6817 0 : transarray = PG_GETARG_ARRAYTYPE_P_COPY(0);
6818 :
6819 2620302 : if (ARR_HASNULL(transarray) ||
6820 2620302 : ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
6821 0 : elog(ERROR, "expected 2-element int8 array");
6822 :
6823 2620302 : transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
6824 2620302 : transdata->count++;
6825 2620302 : transdata->sum += newval;
6826 :
6827 2620302 : PG_RETURN_ARRAYTYPE_P(transarray);
6828 : }
6829 :
6830 : Datum
6831 3502 : int4_avg_combine(PG_FUNCTION_ARGS)
6832 : {
6833 : ArrayType *transarray1;
6834 : ArrayType *transarray2;
6835 : Int8TransTypeData *state1;
6836 : Int8TransTypeData *state2;
6837 :
6838 3502 : if (!AggCheckCallContext(fcinfo, NULL))
6839 0 : elog(ERROR, "aggregate function called in non-aggregate context");
6840 :
6841 3502 : transarray1 = PG_GETARG_ARRAYTYPE_P(0);
6842 3502 : transarray2 = PG_GETARG_ARRAYTYPE_P(1);
6843 :
6844 3502 : if (ARR_HASNULL(transarray1) ||
6845 3502 : ARR_SIZE(transarray1) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
6846 0 : elog(ERROR, "expected 2-element int8 array");
6847 :
6848 3502 : if (ARR_HASNULL(transarray2) ||
6849 3502 : ARR_SIZE(transarray2) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
6850 0 : elog(ERROR, "expected 2-element int8 array");
6851 :
6852 3502 : state1 = (Int8TransTypeData *) ARR_DATA_PTR(transarray1);
6853 3502 : state2 = (Int8TransTypeData *) ARR_DATA_PTR(transarray2);
6854 :
6855 3502 : state1->count += state2->count;
6856 3502 : state1->sum += state2->sum;
6857 :
6858 3502 : PG_RETURN_ARRAYTYPE_P(transarray1);
6859 : }
6860 :
6861 : Datum
6862 12 : int2_avg_accum_inv(PG_FUNCTION_ARGS)
6863 : {
6864 : ArrayType *transarray;
6865 12 : int16 newval = PG_GETARG_INT16(1);
6866 : Int8TransTypeData *transdata;
6867 :
6868 : /*
6869 : * If we're invoked as an aggregate, we can cheat and modify our first
6870 : * parameter in-place to reduce palloc overhead. Otherwise we need to make
6871 : * a copy of it before scribbling on it.
6872 : */
6873 12 : if (AggCheckCallContext(fcinfo, NULL))
6874 12 : transarray = PG_GETARG_ARRAYTYPE_P(0);
6875 : else
6876 0 : transarray = PG_GETARG_ARRAYTYPE_P_COPY(0);
6877 :
6878 12 : if (ARR_HASNULL(transarray) ||
6879 12 : ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
6880 0 : elog(ERROR, "expected 2-element int8 array");
6881 :
6882 12 : transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
6883 12 : transdata->count--;
6884 12 : transdata->sum -= newval;
6885 :
6886 12 : PG_RETURN_ARRAYTYPE_P(transarray);
6887 : }
6888 :
6889 : Datum
6890 1452 : int4_avg_accum_inv(PG_FUNCTION_ARGS)
6891 : {
6892 : ArrayType *transarray;
6893 1452 : int32 newval = PG_GETARG_INT32(1);
6894 : Int8TransTypeData *transdata;
6895 :
6896 : /*
6897 : * If we're invoked as an aggregate, we can cheat and modify our first
6898 : * parameter in-place to reduce palloc overhead. Otherwise we need to make
6899 : * a copy of it before scribbling on it.
6900 : */
6901 1452 : if (AggCheckCallContext(fcinfo, NULL))
6902 1452 : transarray = PG_GETARG_ARRAYTYPE_P(0);
6903 : else
6904 0 : transarray = PG_GETARG_ARRAYTYPE_P_COPY(0);
6905 :
6906 1452 : if (ARR_HASNULL(transarray) ||
6907 1452 : ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
6908 0 : elog(ERROR, "expected 2-element int8 array");
6909 :
6910 1452 : transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
6911 1452 : transdata->count--;
6912 1452 : transdata->sum -= newval;
6913 :
6914 1452 : PG_RETURN_ARRAYTYPE_P(transarray);
6915 : }
6916 :
6917 : Datum
6918 10774 : int8_avg(PG_FUNCTION_ARGS)
6919 : {
6920 10774 : ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
6921 : Int8TransTypeData *transdata;
6922 : Datum countd,
6923 : sumd;
6924 :
6925 10774 : if (ARR_HASNULL(transarray) ||
6926 10774 : ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
6927 0 : elog(ERROR, "expected 2-element int8 array");
6928 10774 : transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
6929 :
6930 : /* SQL defines AVG of no values to be NULL */
6931 10774 : if (transdata->count == 0)
6932 118 : PG_RETURN_NULL();
6933 :
6934 10656 : countd = NumericGetDatum(int64_to_numeric(transdata->count));
6935 10656 : sumd = NumericGetDatum(int64_to_numeric(transdata->sum));
6936 :
6937 10656 : PG_RETURN_DATUM(DirectFunctionCall2(numeric_div, sumd, countd));
6938 : }
6939 :
6940 : /*
6941 : * SUM(int2) and SUM(int4) both return int8, so we can use this
6942 : * final function for both.
6943 : */
6944 : Datum
6945 3834 : int2int4_sum(PG_FUNCTION_ARGS)
6946 : {
6947 3834 : ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
6948 : Int8TransTypeData *transdata;
6949 :
6950 3834 : if (ARR_HASNULL(transarray) ||
6951 3834 : ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
6952 0 : elog(ERROR, "expected 2-element int8 array");
6953 3834 : transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
6954 :
6955 : /* SQL defines SUM of no values to be NULL */
6956 3834 : if (transdata->count == 0)
6957 480 : PG_RETURN_NULL();
6958 :
6959 3354 : PG_RETURN_DATUM(Int64GetDatumFast(transdata->sum));
6960 : }
6961 :
6962 :
6963 : /* ----------------------------------------------------------------------
6964 : *
6965 : * Debug support
6966 : *
6967 : * ----------------------------------------------------------------------
6968 : */
6969 :
6970 : #ifdef NUMERIC_DEBUG
6971 :
6972 : /*
6973 : * dump_numeric() - Dump a value in the db storage format for debugging
6974 : */
6975 : static void
6976 : dump_numeric(const char *str, Numeric num)
6977 : {
6978 : NumericDigit *digits = NUMERIC_DIGITS(num);
6979 : int ndigits;
6980 : int i;
6981 :
6982 : ndigits = NUMERIC_NDIGITS(num);
6983 :
6984 : printf("%s: NUMERIC w=%d d=%d ", str,
6985 : NUMERIC_WEIGHT(num), NUMERIC_DSCALE(num));
6986 : switch (NUMERIC_SIGN(num))
6987 : {
6988 : case NUMERIC_POS:
6989 : printf("POS");
6990 : break;
6991 : case NUMERIC_NEG:
6992 : printf("NEG");
6993 : break;
6994 : case NUMERIC_NAN:
6995 : printf("NaN");
6996 : break;
6997 : case NUMERIC_PINF:
6998 : printf("Infinity");
6999 : break;
7000 : case NUMERIC_NINF:
7001 : printf("-Infinity");
7002 : break;
7003 : default:
7004 : printf("SIGN=0x%x", NUMERIC_SIGN(num));
7005 : break;
7006 : }
7007 :
7008 : for (i = 0; i < ndigits; i++)
7009 : printf(" %0*d", DEC_DIGITS, digits[i]);
7010 : printf("\n");
7011 : }
7012 :
7013 :
7014 : /*
7015 : * dump_var() - Dump a value in the variable format for debugging
7016 : */
7017 : static void
7018 : dump_var(const char *str, NumericVar *var)
7019 : {
7020 : int i;
7021 :
7022 : printf("%s: VAR w=%d d=%d ", str, var->weight, var->dscale);
7023 : switch (var->sign)
7024 : {
7025 : case NUMERIC_POS:
7026 : printf("POS");
7027 : break;
7028 : case NUMERIC_NEG:
7029 : printf("NEG");
7030 : break;
7031 : case NUMERIC_NAN:
7032 : printf("NaN");
7033 : break;
7034 : case NUMERIC_PINF:
7035 : printf("Infinity");
7036 : break;
7037 : case NUMERIC_NINF:
7038 : printf("-Infinity");
7039 : break;
7040 : default:
7041 : printf("SIGN=0x%x", var->sign);
7042 : break;
7043 : }
7044 :
7045 : for (i = 0; i < var->ndigits; i++)
7046 : printf(" %0*d", DEC_DIGITS, var->digits[i]);
7047 :
7048 : printf("\n");
7049 : }
7050 : #endif /* NUMERIC_DEBUG */
7051 :
7052 :
7053 : /* ----------------------------------------------------------------------
7054 : *
7055 : * Local functions follow
7056 : *
7057 : * In general, these do not support "special" (NaN or infinity) inputs;
7058 : * callers should handle those possibilities first.
7059 : * (There are one or two exceptions, noted in their header comments.)
7060 : *
7061 : * ----------------------------------------------------------------------
7062 : */
7063 :
7064 :
7065 : /*
7066 : * alloc_var() -
7067 : *
7068 : * Allocate a digit buffer of ndigits digits (plus a spare digit for rounding)
7069 : */
7070 : static void
7071 2116476 : alloc_var(NumericVar *var, int ndigits)
7072 : {
7073 2116476 : digitbuf_free(var->buf);
7074 2116476 : var->buf = digitbuf_alloc(ndigits + 1);
7075 2116476 : var->buf[0] = 0; /* spare digit for rounding */
7076 2116476 : var->digits = var->buf + 1;
7077 2116476 : var->ndigits = ndigits;
7078 2116476 : }
7079 :
7080 :
7081 : /*
7082 : * free_var() -
7083 : *
7084 : * Return the digit buffer of a variable to the free pool
7085 : */
7086 : static void
7087 3422116 : free_var(NumericVar *var)
7088 : {
7089 3422116 : digitbuf_free(var->buf);
7090 3422116 : var->buf = NULL;
7091 3422116 : var->digits = NULL;
7092 3422116 : var->sign = NUMERIC_NAN;
7093 3422116 : }
7094 :
7095 :
7096 : /*
7097 : * zero_var() -
7098 : *
7099 : * Set a variable to ZERO.
7100 : * Note: its dscale is not touched.
7101 : */
7102 : static void
7103 40634 : zero_var(NumericVar *var)
7104 : {
7105 40634 : digitbuf_free(var->buf);
7106 40634 : var->buf = NULL;
7107 40634 : var->digits = NULL;
7108 40634 : var->ndigits = 0;
7109 40634 : var->weight = 0; /* by convention; doesn't really matter */
7110 40634 : var->sign = NUMERIC_POS; /* anything but NAN... */
7111 40634 : }
7112 :
7113 :
7114 : /*
7115 : * set_var_from_str()
7116 : *
7117 : * Parse a string and put the number into a variable
7118 : *
7119 : * This function does not handle leading or trailing spaces. It returns
7120 : * the end+1 position parsed into *endptr, so that caller can check for
7121 : * trailing spaces/garbage if deemed necessary.
7122 : *
7123 : * cp is the place to actually start parsing; str is what to use in error
7124 : * reports. (Typically cp would be the same except advanced over spaces.)
7125 : *
7126 : * Returns true on success, false on failure (if escontext points to an
7127 : * ErrorSaveContext; otherwise errors are thrown).
7128 : */
7129 : static bool
7130 141026 : set_var_from_str(const char *str, const char *cp,
7131 : NumericVar *dest, const char **endptr,
7132 : Node *escontext)
7133 : {
7134 141026 : bool have_dp = false;
7135 : int i;
7136 : unsigned char *decdigits;
7137 141026 : int sign = NUMERIC_POS;
7138 141026 : int dweight = -1;
7139 : int ddigits;
7140 141026 : int dscale = 0;
7141 : int weight;
7142 : int ndigits;
7143 : int offset;
7144 : NumericDigit *digits;
7145 :
7146 : /*
7147 : * We first parse the string to extract decimal digits and determine the
7148 : * correct decimal weight. Then convert to NBASE representation.
7149 : */
7150 141026 : switch (*cp)
7151 : {
7152 0 : case '+':
7153 0 : sign = NUMERIC_POS;
7154 0 : cp++;
7155 0 : break;
7156 :
7157 300 : case '-':
7158 300 : sign = NUMERIC_NEG;
7159 300 : cp++;
7160 300 : break;
7161 : }
7162 :
7163 141026 : if (*cp == '.')
7164 : {
7165 384 : have_dp = true;
7166 384 : cp++;
7167 : }
7168 :
7169 141026 : if (!isdigit((unsigned char) *cp))
7170 0 : goto invalid_syntax;
7171 :
7172 141026 : decdigits = (unsigned char *) palloc(strlen(cp) + DEC_DIGITS * 2);
7173 :
7174 : /* leading padding for digit alignment later */
7175 141026 : memset(decdigits, 0, DEC_DIGITS);
7176 141026 : i = DEC_DIGITS;
7177 :
7178 608956 : while (*cp)
7179 : {
7180 469262 : if (isdigit((unsigned char) *cp))
7181 : {
7182 450546 : decdigits[i++] = *cp++ - '0';
7183 450546 : if (!have_dp)
7184 377882 : dweight++;
7185 : else
7186 72664 : dscale++;
7187 : }
7188 18716 : else if (*cp == '.')
7189 : {
7190 17222 : if (have_dp)
7191 0 : goto invalid_syntax;
7192 17222 : have_dp = true;
7193 17222 : cp++;
7194 : /* decimal point must not be followed by underscore */
7195 17222 : if (*cp == '_')
7196 6 : goto invalid_syntax;
7197 : }
7198 1494 : else if (*cp == '_')
7199 : {
7200 : /* underscore must be followed by more digits */
7201 186 : cp++;
7202 186 : if (!isdigit((unsigned char) *cp))
7203 18 : goto invalid_syntax;
7204 : }
7205 : else
7206 1308 : break;
7207 : }
7208 :
7209 141002 : ddigits = i - DEC_DIGITS;
7210 : /* trailing padding for digit alignment later */
7211 141002 : memset(decdigits + i, 0, DEC_DIGITS - 1);
7212 :
7213 : /* Handle exponent, if any */
7214 141002 : if (*cp == 'e' || *cp == 'E')
7215 : {
7216 1260 : int64 exponent = 0;
7217 1260 : bool neg = false;
7218 :
7219 : /*
7220 : * At this point, dweight and dscale can't be more than about
7221 : * INT_MAX/2 due to the MaxAllocSize limit on string length, so
7222 : * constraining the exponent similarly should be enough to prevent
7223 : * integer overflow in this function. If the value is too large to
7224 : * fit in storage format, make_result() will complain about it later;
7225 : * for consistency use the same ereport errcode/text as make_result().
7226 : */
7227 :
7228 : /* exponent sign */
7229 1260 : cp++;
7230 1260 : if (*cp == '+')
7231 154 : cp++;
7232 1106 : else if (*cp == '-')
7233 : {
7234 470 : neg = true;
7235 470 : cp++;
7236 : }
7237 :
7238 : /* exponent digits */
7239 1260 : if (!isdigit((unsigned char) *cp))
7240 6 : goto invalid_syntax;
7241 :
7242 4440 : while (*cp)
7243 : {
7244 3204 : if (isdigit((unsigned char) *cp))
7245 : {
7246 3162 : exponent = exponent * 10 + (*cp++ - '0');
7247 3162 : if (exponent > PG_INT32_MAX / 2)
7248 6 : goto out_of_range;
7249 : }
7250 42 : else if (*cp == '_')
7251 : {
7252 : /* underscore must be followed by more digits */
7253 42 : cp++;
7254 42 : if (!isdigit((unsigned char) *cp))
7255 12 : goto invalid_syntax;
7256 : }
7257 : else
7258 0 : break;
7259 : }
7260 :
7261 1236 : if (neg)
7262 470 : exponent = -exponent;
7263 :
7264 1236 : dweight += (int) exponent;
7265 1236 : dscale -= (int) exponent;
7266 1236 : if (dscale < 0)
7267 562 : dscale = 0;
7268 : }
7269 :
7270 : /*
7271 : * Okay, convert pure-decimal representation to base NBASE. First we need
7272 : * to determine the converted weight and ndigits. offset is the number of
7273 : * decimal zeroes to insert before the first given digit to have a
7274 : * correctly aligned first NBASE digit.
7275 : */
7276 140978 : if (dweight >= 0)
7277 140226 : weight = (dweight + 1 + DEC_DIGITS - 1) / DEC_DIGITS - 1;
7278 : else
7279 752 : weight = -((-dweight - 1) / DEC_DIGITS + 1);
7280 140978 : offset = (weight + 1) * DEC_DIGITS - (dweight + 1);
7281 140978 : ndigits = (ddigits + offset + DEC_DIGITS - 1) / DEC_DIGITS;
7282 :
7283 140978 : alloc_var(dest, ndigits);
7284 140978 : dest->sign = sign;
7285 140978 : dest->weight = weight;
7286 140978 : dest->dscale = dscale;
7287 :
7288 140978 : i = DEC_DIGITS - offset;
7289 140978 : digits = dest->digits;
7290 :
7291 349190 : while (ndigits-- > 0)
7292 : {
7293 : #if DEC_DIGITS == 4
7294 208212 : *digits++ = ((decdigits[i] * 10 + decdigits[i + 1]) * 10 +
7295 208212 : decdigits[i + 2]) * 10 + decdigits[i + 3];
7296 : #elif DEC_DIGITS == 2
7297 : *digits++ = decdigits[i] * 10 + decdigits[i + 1];
7298 : #elif DEC_DIGITS == 1
7299 : *digits++ = decdigits[i];
7300 : #else
7301 : #error unsupported NBASE
7302 : #endif
7303 208212 : i += DEC_DIGITS;
7304 : }
7305 :
7306 140978 : pfree(decdigits);
7307 :
7308 : /* Strip any leading/trailing zeroes, and normalize weight if zero */
7309 140978 : strip_var(dest);
7310 :
7311 : /* Return end+1 position for caller */
7312 140978 : *endptr = cp;
7313 :
7314 140978 : return true;
7315 :
7316 6 : out_of_range:
7317 6 : ereturn(escontext, false,
7318 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
7319 : errmsg("value overflows numeric format")));
7320 :
7321 42 : invalid_syntax:
7322 42 : ereturn(escontext, false,
7323 : (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
7324 : errmsg("invalid input syntax for type %s: \"%s\"",
7325 : "numeric", str)));
7326 : }
7327 :
7328 :
7329 : /*
7330 : * Return the numeric value of a single hex digit.
7331 : */
7332 : static inline int
7333 708 : xdigit_value(char dig)
7334 : {
7335 894 : return dig >= '0' && dig <= '9' ? dig - '0' :
7336 294 : dig >= 'a' && dig <= 'f' ? dig - 'a' + 10 :
7337 108 : dig >= 'A' && dig <= 'F' ? dig - 'A' + 10 : -1;
7338 : }
7339 :
7340 : /*
7341 : * set_var_from_non_decimal_integer_str()
7342 : *
7343 : * Parse a string containing a non-decimal integer
7344 : *
7345 : * This function does not handle leading or trailing spaces. It returns
7346 : * the end+1 position parsed into *endptr, so that caller can check for
7347 : * trailing spaces/garbage if deemed necessary.
7348 : *
7349 : * cp is the place to actually start parsing; str is what to use in error
7350 : * reports. The number's sign and base prefix indicator (e.g., "0x") are
7351 : * assumed to have already been parsed, so cp should point to the number's
7352 : * first digit in the base specified.
7353 : *
7354 : * base is expected to be 2, 8 or 16.
7355 : *
7356 : * Returns true on success, false on failure (if escontext points to an
7357 : * ErrorSaveContext; otherwise errors are thrown).
7358 : */
7359 : static bool
7360 156 : set_var_from_non_decimal_integer_str(const char *str, const char *cp, int sign,
7361 : int base, NumericVar *dest,
7362 : const char **endptr, Node *escontext)
7363 : {
7364 156 : const char *firstdigit = cp;
7365 : int64 tmp;
7366 : int64 mul;
7367 : NumericVar tmp_var;
7368 :
7369 156 : init_var(&tmp_var);
7370 :
7371 156 : zero_var(dest);
7372 :
7373 : /*
7374 : * Process input digits in groups that fit in int64. Here "tmp" is the
7375 : * value of the digits in the group, and "mul" is base^n, where n is the
7376 : * number of digits in the group. Thus tmp < mul, and we must start a new
7377 : * group when mul * base threatens to overflow PG_INT64_MAX.
7378 : */
7379 156 : tmp = 0;
7380 156 : mul = 1;
7381 :
7382 156 : if (base == 16)
7383 : {
7384 828 : while (*cp)
7385 : {
7386 798 : if (isxdigit((unsigned char) *cp))
7387 : {
7388 708 : if (mul > PG_INT64_MAX / 16)
7389 : {
7390 : /* Add the contribution from this group of digits */
7391 30 : int64_to_numericvar(mul, &tmp_var);
7392 30 : mul_var(dest, &tmp_var, dest, 0);
7393 30 : int64_to_numericvar(tmp, &tmp_var);
7394 30 : add_var(dest, &tmp_var, dest);
7395 :
7396 : /* Result will overflow if weight overflows int16 */
7397 30 : if (dest->weight > NUMERIC_WEIGHT_MAX)
7398 0 : goto out_of_range;
7399 :
7400 : /* Begin a new group */
7401 30 : tmp = 0;
7402 30 : mul = 1;
7403 : }
7404 :
7405 708 : tmp = tmp * 16 + xdigit_value(*cp++);
7406 708 : mul = mul * 16;
7407 : }
7408 90 : else if (*cp == '_')
7409 : {
7410 : /* Underscore must be followed by more digits */
7411 66 : cp++;
7412 66 : if (!isxdigit((unsigned char) *cp))
7413 18 : goto invalid_syntax;
7414 : }
7415 : else
7416 24 : break;
7417 : }
7418 : }
7419 84 : else if (base == 8)
7420 : {
7421 636 : while (*cp)
7422 : {
7423 606 : if (*cp >= '0' && *cp <= '7')
7424 : {
7425 558 : if (mul > PG_INT64_MAX / 8)
7426 : {
7427 : /* Add the contribution from this group of digits */
7428 18 : int64_to_numericvar(mul, &tmp_var);
7429 18 : mul_var(dest, &tmp_var, dest, 0);
7430 18 : int64_to_numericvar(tmp, &tmp_var);
7431 18 : add_var(dest, &tmp_var, dest);
7432 :
7433 : /* Result will overflow if weight overflows int16 */
7434 18 : if (dest->weight > NUMERIC_WEIGHT_MAX)
7435 0 : goto out_of_range;
7436 :
7437 : /* Begin a new group */
7438 18 : tmp = 0;
7439 18 : mul = 1;
7440 : }
7441 :
7442 558 : tmp = tmp * 8 + (*cp++ - '0');
7443 558 : mul = mul * 8;
7444 : }
7445 48 : else if (*cp == '_')
7446 : {
7447 : /* Underscore must be followed by more digits */
7448 36 : cp++;
7449 36 : if (*cp < '0' || *cp > '7')
7450 0 : goto invalid_syntax;
7451 : }
7452 : else
7453 12 : break;
7454 : }
7455 : }
7456 42 : else if (base == 2)
7457 : {
7458 1560 : while (*cp)
7459 : {
7460 1530 : if (*cp >= '0' && *cp <= '1')
7461 : {
7462 1416 : if (mul > PG_INT64_MAX / 2)
7463 : {
7464 : /* Add the contribution from this group of digits */
7465 18 : int64_to_numericvar(mul, &tmp_var);
7466 18 : mul_var(dest, &tmp_var, dest, 0);
7467 18 : int64_to_numericvar(tmp, &tmp_var);
7468 18 : add_var(dest, &tmp_var, dest);
7469 :
7470 : /* Result will overflow if weight overflows int16 */
7471 18 : if (dest->weight > NUMERIC_WEIGHT_MAX)
7472 0 : goto out_of_range;
7473 :
7474 : /* Begin a new group */
7475 18 : tmp = 0;
7476 18 : mul = 1;
7477 : }
7478 :
7479 1416 : tmp = tmp * 2 + (*cp++ - '0');
7480 1416 : mul = mul * 2;
7481 : }
7482 114 : else if (*cp == '_')
7483 : {
7484 : /* Underscore must be followed by more digits */
7485 102 : cp++;
7486 102 : if (*cp < '0' || *cp > '1')
7487 0 : goto invalid_syntax;
7488 : }
7489 : else
7490 12 : break;
7491 : }
7492 : }
7493 : else
7494 : /* Should never happen; treat as invalid input */
7495 0 : goto invalid_syntax;
7496 :
7497 : /* Check that we got at least one digit */
7498 138 : if (unlikely(cp == firstdigit))
7499 0 : goto invalid_syntax;
7500 :
7501 : /* Add the contribution from the final group of digits */
7502 138 : int64_to_numericvar(mul, &tmp_var);
7503 138 : mul_var(dest, &tmp_var, dest, 0);
7504 138 : int64_to_numericvar(tmp, &tmp_var);
7505 138 : add_var(dest, &tmp_var, dest);
7506 :
7507 138 : if (dest->weight > NUMERIC_WEIGHT_MAX)
7508 0 : goto out_of_range;
7509 :
7510 138 : dest->sign = sign;
7511 :
7512 138 : free_var(&tmp_var);
7513 :
7514 : /* Return end+1 position for caller */
7515 138 : *endptr = cp;
7516 :
7517 138 : return true;
7518 :
7519 0 : out_of_range:
7520 0 : ereturn(escontext, false,
7521 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
7522 : errmsg("value overflows numeric format")));
7523 :
7524 18 : invalid_syntax:
7525 18 : ereturn(escontext, false,
7526 : (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
7527 : errmsg("invalid input syntax for type %s: \"%s\"",
7528 : "numeric", str)));
7529 : }
7530 :
7531 :
7532 : /*
7533 : * set_var_from_num() -
7534 : *
7535 : * Convert the packed db format into a variable
7536 : */
7537 : static void
7538 12988 : set_var_from_num(Numeric num, NumericVar *dest)
7539 : {
7540 : int ndigits;
7541 :
7542 12988 : ndigits = NUMERIC_NDIGITS(num);
7543 :
7544 12988 : alloc_var(dest, ndigits);
7545 :
7546 12988 : dest->weight = NUMERIC_WEIGHT(num);
7547 12988 : dest->sign = NUMERIC_SIGN(num);
7548 12988 : dest->dscale = NUMERIC_DSCALE(num);
7549 :
7550 12988 : memcpy(dest->digits, NUMERIC_DIGITS(num), ndigits * sizeof(NumericDigit));
7551 12988 : }
7552 :
7553 :
7554 : /*
7555 : * init_var_from_num() -
7556 : *
7557 : * Initialize a variable from packed db format. The digits array is not
7558 : * copied, which saves some cycles when the resulting var is not modified.
7559 : * Also, there's no need to call free_var(), as long as you don't assign any
7560 : * other value to it (with set_var_* functions, or by using the var as the
7561 : * destination of a function like add_var())
7562 : *
7563 : * CAUTION: Do not modify the digits buffer of a var initialized with this
7564 : * function, e.g by calling round_var() or trunc_var(), as the changes will
7565 : * propagate to the original Numeric! It's OK to use it as the destination
7566 : * argument of one of the calculational functions, though.
7567 : */
7568 : static void
7569 5093484 : init_var_from_num(Numeric num, NumericVar *dest)
7570 : {
7571 5093484 : dest->ndigits = NUMERIC_NDIGITS(num);
7572 5093484 : dest->weight = NUMERIC_WEIGHT(num);
7573 5093484 : dest->sign = NUMERIC_SIGN(num);
7574 5093484 : dest->dscale = NUMERIC_DSCALE(num);
7575 5093484 : dest->digits = NUMERIC_DIGITS(num);
7576 5093484 : dest->buf = NULL; /* digits array is not palloc'd */
7577 5093484 : }
7578 :
7579 :
7580 : /*
7581 : * set_var_from_var() -
7582 : *
7583 : * Copy one variable into another
7584 : */
7585 : static void
7586 35202 : set_var_from_var(const NumericVar *value, NumericVar *dest)
7587 : {
7588 : NumericDigit *newbuf;
7589 :
7590 35202 : newbuf = digitbuf_alloc(value->ndigits + 1);
7591 35202 : newbuf[0] = 0; /* spare digit for rounding */
7592 35202 : if (value->ndigits > 0) /* else value->digits might be null */
7593 34256 : memcpy(newbuf + 1, value->digits,
7594 34256 : value->ndigits * sizeof(NumericDigit));
7595 :
7596 35202 : digitbuf_free(dest->buf);
7597 :
7598 35202 : memmove(dest, value, sizeof(NumericVar));
7599 35202 : dest->buf = newbuf;
7600 35202 : dest->digits = newbuf + 1;
7601 35202 : }
7602 :
7603 :
7604 : /*
7605 : * get_str_from_var() -
7606 : *
7607 : * Convert a var to text representation (guts of numeric_out).
7608 : * The var is displayed to the number of digits indicated by its dscale.
7609 : * Returns a palloc'd string.
7610 : */
7611 : static char *
7612 802194 : get_str_from_var(const NumericVar *var)
7613 : {
7614 : int dscale;
7615 : char *str;
7616 : char *cp;
7617 : char *endcp;
7618 : int i;
7619 : int d;
7620 : NumericDigit dig;
7621 :
7622 : #if DEC_DIGITS > 1
7623 : NumericDigit d1;
7624 : #endif
7625 :
7626 802194 : dscale = var->dscale;
7627 :
7628 : /*
7629 : * Allocate space for the result.
7630 : *
7631 : * i is set to the # of decimal digits before decimal point. dscale is the
7632 : * # of decimal digits we will print after decimal point. We may generate
7633 : * as many as DEC_DIGITS-1 excess digits at the end, and in addition we
7634 : * need room for sign, decimal point, null terminator.
7635 : */
7636 802194 : i = (var->weight + 1) * DEC_DIGITS;
7637 802194 : if (i <= 0)
7638 140434 : i = 1;
7639 :
7640 802194 : str = palloc(i + dscale + DEC_DIGITS + 2);
7641 802194 : cp = str;
7642 :
7643 : /*
7644 : * Output a dash for negative values
7645 : */
7646 802194 : if (var->sign == NUMERIC_NEG)
7647 5566 : *cp++ = '-';
7648 :
7649 : /*
7650 : * Output all digits before the decimal point
7651 : */
7652 802194 : if (var->weight < 0)
7653 : {
7654 140434 : d = var->weight + 1;
7655 140434 : *cp++ = '0';
7656 : }
7657 : else
7658 : {
7659 1429448 : for (d = 0; d <= var->weight; d++)
7660 : {
7661 767688 : dig = (d < var->ndigits) ? var->digits[d] : 0;
7662 : /* In the first digit, suppress extra leading decimal zeroes */
7663 : #if DEC_DIGITS == 4
7664 : {
7665 767688 : bool putit = (d > 0);
7666 :
7667 767688 : d1 = dig / 1000;
7668 767688 : dig -= d1 * 1000;
7669 767688 : putit |= (d1 > 0);
7670 767688 : if (putit)
7671 112858 : *cp++ = d1 + '0';
7672 767688 : d1 = dig / 100;
7673 767688 : dig -= d1 * 100;
7674 767688 : putit |= (d1 > 0);
7675 767688 : if (putit)
7676 517942 : *cp++ = d1 + '0';
7677 767688 : d1 = dig / 10;
7678 767688 : dig -= d1 * 10;
7679 767688 : putit |= (d1 > 0);
7680 767688 : if (putit)
7681 645202 : *cp++ = d1 + '0';
7682 767688 : *cp++ = dig + '0';
7683 : }
7684 : #elif DEC_DIGITS == 2
7685 : d1 = dig / 10;
7686 : dig -= d1 * 10;
7687 : if (d1 > 0 || d > 0)
7688 : *cp++ = d1 + '0';
7689 : *cp++ = dig + '0';
7690 : #elif DEC_DIGITS == 1
7691 : *cp++ = dig + '0';
7692 : #else
7693 : #error unsupported NBASE
7694 : #endif
7695 : }
7696 : }
7697 :
7698 : /*
7699 : * If requested, output a decimal point and all the digits that follow it.
7700 : * We initially put out a multiple of DEC_DIGITS digits, then truncate if
7701 : * needed.
7702 : */
7703 802194 : if (dscale > 0)
7704 : {
7705 646160 : *cp++ = '.';
7706 646160 : endcp = cp + dscale;
7707 1907382 : for (i = 0; i < dscale; d++, i += DEC_DIGITS)
7708 : {
7709 1261222 : dig = (d >= 0 && d < var->ndigits) ? var->digits[d] : 0;
7710 : #if DEC_DIGITS == 4
7711 1261222 : d1 = dig / 1000;
7712 1261222 : dig -= d1 * 1000;
7713 1261222 : *cp++ = d1 + '0';
7714 1261222 : d1 = dig / 100;
7715 1261222 : dig -= d1 * 100;
7716 1261222 : *cp++ = d1 + '0';
7717 1261222 : d1 = dig / 10;
7718 1261222 : dig -= d1 * 10;
7719 1261222 : *cp++ = d1 + '0';
7720 1261222 : *cp++ = dig + '0';
7721 : #elif DEC_DIGITS == 2
7722 : d1 = dig / 10;
7723 : dig -= d1 * 10;
7724 : *cp++ = d1 + '0';
7725 : *cp++ = dig + '0';
7726 : #elif DEC_DIGITS == 1
7727 : *cp++ = dig + '0';
7728 : #else
7729 : #error unsupported NBASE
7730 : #endif
7731 : }
7732 646160 : cp = endcp;
7733 : }
7734 :
7735 : /*
7736 : * terminate the string and return it
7737 : */
7738 802194 : *cp = '\0';
7739 802194 : return str;
7740 : }
7741 :
7742 : /*
7743 : * get_str_from_var_sci() -
7744 : *
7745 : * Convert a var to a normalised scientific notation text representation.
7746 : * This function does the heavy lifting for numeric_out_sci().
7747 : *
7748 : * This notation has the general form a * 10^b, where a is known as the
7749 : * "significand" and b is known as the "exponent".
7750 : *
7751 : * Because we can't do superscript in ASCII (and because we want to copy
7752 : * printf's behaviour) we display the exponent using E notation, with a
7753 : * minimum of two exponent digits.
7754 : *
7755 : * For example, the value 1234 could be output as 1.2e+03.
7756 : *
7757 : * We assume that the exponent can fit into an int32.
7758 : *
7759 : * rscale is the number of decimal digits desired after the decimal point in
7760 : * the output, negative values will be treated as meaning zero.
7761 : *
7762 : * Returns a palloc'd string.
7763 : */
7764 : static char *
7765 228 : get_str_from_var_sci(const NumericVar *var, int rscale)
7766 : {
7767 : int32 exponent;
7768 : NumericVar tmp_var;
7769 : size_t len;
7770 : char *str;
7771 : char *sig_out;
7772 :
7773 228 : if (rscale < 0)
7774 0 : rscale = 0;
7775 :
7776 : /*
7777 : * Determine the exponent of this number in normalised form.
7778 : *
7779 : * This is the exponent required to represent the number with only one
7780 : * significant digit before the decimal place.
7781 : */
7782 228 : if (var->ndigits > 0)
7783 : {
7784 210 : exponent = (var->weight + 1) * DEC_DIGITS;
7785 :
7786 : /*
7787 : * Compensate for leading decimal zeroes in the first numeric digit by
7788 : * decrementing the exponent.
7789 : */
7790 210 : exponent -= DEC_DIGITS - (int) log10(var->digits[0]);
7791 : }
7792 : else
7793 : {
7794 : /*
7795 : * If var has no digits, then it must be zero.
7796 : *
7797 : * Zero doesn't technically have a meaningful exponent in normalised
7798 : * notation, but we just display the exponent as zero for consistency
7799 : * of output.
7800 : */
7801 18 : exponent = 0;
7802 : }
7803 :
7804 : /*
7805 : * Divide var by 10^exponent to get the significand, rounding to rscale
7806 : * decimal digits in the process.
7807 : */
7808 228 : init_var(&tmp_var);
7809 :
7810 228 : power_ten_int(exponent, &tmp_var);
7811 228 : div_var(var, &tmp_var, &tmp_var, rscale, true, true);
7812 228 : sig_out = get_str_from_var(&tmp_var);
7813 :
7814 228 : free_var(&tmp_var);
7815 :
7816 : /*
7817 : * Allocate space for the result.
7818 : *
7819 : * In addition to the significand, we need room for the exponent
7820 : * decoration ("e"), the sign of the exponent, up to 10 digits for the
7821 : * exponent itself, and of course the null terminator.
7822 : */
7823 228 : len = strlen(sig_out) + 13;
7824 228 : str = palloc(len);
7825 228 : snprintf(str, len, "%se%+03d", sig_out, exponent);
7826 :
7827 228 : pfree(sig_out);
7828 :
7829 228 : return str;
7830 : }
7831 :
7832 :
7833 : /*
7834 : * numericvar_serialize - serialize NumericVar to binary format
7835 : *
7836 : * At variable level, no checks are performed on the weight or dscale, allowing
7837 : * us to pass around intermediate values with higher precision than supported
7838 : * by the numeric type. Note: this is incompatible with numeric_send/recv(),
7839 : * which use 16-bit integers for these fields.
7840 : */
7841 : static void
7842 90 : numericvar_serialize(StringInfo buf, const NumericVar *var)
7843 : {
7844 : int i;
7845 :
7846 90 : pq_sendint32(buf, var->ndigits);
7847 90 : pq_sendint32(buf, var->weight);
7848 90 : pq_sendint32(buf, var->sign);
7849 90 : pq_sendint32(buf, var->dscale);
7850 637768 : for (i = 0; i < var->ndigits; i++)
7851 637678 : pq_sendint16(buf, var->digits[i]);
7852 90 : }
7853 :
7854 : /*
7855 : * numericvar_deserialize - deserialize binary format to NumericVar
7856 : */
7857 : static void
7858 90 : numericvar_deserialize(StringInfo buf, NumericVar *var)
7859 : {
7860 : int len,
7861 : i;
7862 :
7863 90 : len = pq_getmsgint(buf, sizeof(int32));
7864 :
7865 90 : alloc_var(var, len); /* sets var->ndigits */
7866 :
7867 90 : var->weight = pq_getmsgint(buf, sizeof(int32));
7868 90 : var->sign = pq_getmsgint(buf, sizeof(int32));
7869 90 : var->dscale = pq_getmsgint(buf, sizeof(int32));
7870 637768 : for (i = 0; i < len; i++)
7871 637678 : var->digits[i] = pq_getmsgint(buf, sizeof(int16));
7872 90 : }
7873 :
7874 :
7875 : /*
7876 : * duplicate_numeric() - copy a packed-format Numeric
7877 : *
7878 : * This will handle NaN and Infinity cases.
7879 : */
7880 : static Numeric
7881 28496 : duplicate_numeric(Numeric num)
7882 : {
7883 : Numeric res;
7884 :
7885 28496 : res = (Numeric) palloc(VARSIZE(num));
7886 28496 : memcpy(res, num, VARSIZE(num));
7887 28496 : return res;
7888 : }
7889 :
7890 : /*
7891 : * make_result_opt_error() -
7892 : *
7893 : * Create the packed db numeric format in palloc()'d memory from
7894 : * a variable. This will handle NaN and Infinity cases.
7895 : *
7896 : * If "have_error" isn't NULL, on overflow *have_error is set to true and
7897 : * NULL is returned. This is helpful when caller needs to handle errors.
7898 : */
7899 : static Numeric
7900 3285182 : make_result_opt_error(const NumericVar *var, bool *have_error)
7901 : {
7902 : Numeric result;
7903 3285182 : NumericDigit *digits = var->digits;
7904 3285182 : int weight = var->weight;
7905 3285182 : int sign = var->sign;
7906 : int n;
7907 : Size len;
7908 :
7909 3285182 : if (have_error)
7910 118354 : *have_error = false;
7911 :
7912 3285182 : if ((sign & NUMERIC_SIGN_MASK) == NUMERIC_SPECIAL)
7913 : {
7914 : /*
7915 : * Verify valid special value. This could be just an Assert, perhaps,
7916 : * but it seems worthwhile to expend a few cycles to ensure that we
7917 : * never write any nonzero reserved bits to disk.
7918 : */
7919 5510 : if (!(sign == NUMERIC_NAN ||
7920 : sign == NUMERIC_PINF ||
7921 : sign == NUMERIC_NINF))
7922 0 : elog(ERROR, "invalid numeric sign value 0x%x", sign);
7923 :
7924 5510 : result = (Numeric) palloc(NUMERIC_HDRSZ_SHORT);
7925 :
7926 5510 : SET_VARSIZE(result, NUMERIC_HDRSZ_SHORT);
7927 5510 : result->choice.n_header = sign;
7928 : /* the header word is all we need */
7929 :
7930 : dump_numeric("make_result()", result);
7931 5510 : return result;
7932 : }
7933 :
7934 3279672 : n = var->ndigits;
7935 :
7936 : /* truncate leading zeroes */
7937 3279708 : while (n > 0 && *digits == 0)
7938 : {
7939 36 : digits++;
7940 36 : weight--;
7941 36 : n--;
7942 : }
7943 : /* truncate trailing zeroes */
7944 3365008 : while (n > 0 && digits[n - 1] == 0)
7945 85336 : n--;
7946 :
7947 : /* If zero result, force to weight=0 and positive sign */
7948 3279672 : if (n == 0)
7949 : {
7950 104334 : weight = 0;
7951 104334 : sign = NUMERIC_POS;
7952 : }
7953 :
7954 : /* Build the result */
7955 3279672 : if (NUMERIC_CAN_BE_SHORT(var->dscale, weight))
7956 : {
7957 3277644 : len = NUMERIC_HDRSZ_SHORT + n * sizeof(NumericDigit);
7958 3277644 : result = (Numeric) palloc(len);
7959 3277644 : SET_VARSIZE(result, len);
7960 3277644 : result->choice.n_short.n_header =
7961 : (sign == NUMERIC_NEG ? (NUMERIC_SHORT | NUMERIC_SHORT_SIGN_MASK)
7962 : : NUMERIC_SHORT)
7963 3277644 : | (var->dscale << NUMERIC_SHORT_DSCALE_SHIFT)
7964 3277644 : | (weight < 0 ? NUMERIC_SHORT_WEIGHT_SIGN_MASK : 0)
7965 3277644 : | (weight & NUMERIC_SHORT_WEIGHT_MASK);
7966 : }
7967 : else
7968 : {
7969 2028 : len = NUMERIC_HDRSZ + n * sizeof(NumericDigit);
7970 2028 : result = (Numeric) palloc(len);
7971 2028 : SET_VARSIZE(result, len);
7972 2028 : result->choice.n_long.n_sign_dscale =
7973 2028 : sign | (var->dscale & NUMERIC_DSCALE_MASK);
7974 2028 : result->choice.n_long.n_weight = weight;
7975 : }
7976 :
7977 : Assert(NUMERIC_NDIGITS(result) == n);
7978 3279672 : if (n > 0)
7979 3175338 : memcpy(NUMERIC_DIGITS(result), digits, n * sizeof(NumericDigit));
7980 :
7981 : /* Check for overflow of int16 fields */
7982 3279672 : if (NUMERIC_WEIGHT(result) != weight ||
7983 3279642 : NUMERIC_DSCALE(result) != var->dscale)
7984 : {
7985 30 : if (have_error)
7986 : {
7987 18 : *have_error = true;
7988 18 : return NULL;
7989 : }
7990 : else
7991 : {
7992 12 : ereport(ERROR,
7993 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
7994 : errmsg("value overflows numeric format")));
7995 : }
7996 : }
7997 :
7998 : dump_numeric("make_result()", result);
7999 3279642 : return result;
8000 : }
8001 :
8002 :
8003 : /*
8004 : * make_result() -
8005 : *
8006 : * An interface to make_result_opt_error() without "have_error" argument.
8007 : */
8008 : static Numeric
8009 2130324 : make_result(const NumericVar *var)
8010 : {
8011 2130324 : return make_result_opt_error(var, NULL);
8012 : }
8013 :
8014 :
8015 : /*
8016 : * apply_typmod() -
8017 : *
8018 : * Do bounds checking and rounding according to the specified typmod.
8019 : * Note that this is only applied to normal finite values.
8020 : *
8021 : * Returns true on success, false on failure (if escontext points to an
8022 : * ErrorSaveContext; otherwise errors are thrown).
8023 : */
8024 : static bool
8025 122518 : apply_typmod(NumericVar *var, int32 typmod, Node *escontext)
8026 : {
8027 : int precision;
8028 : int scale;
8029 : int maxdigits;
8030 : int ddigits;
8031 : int i;
8032 :
8033 : /* Do nothing if we have an invalid typmod */
8034 122518 : if (!is_valid_numeric_typmod(typmod))
8035 117820 : return true;
8036 :
8037 4698 : precision = numeric_typmod_precision(typmod);
8038 4698 : scale = numeric_typmod_scale(typmod);
8039 4698 : maxdigits = precision - scale;
8040 :
8041 : /* Round to target scale (and set var->dscale) */
8042 4698 : round_var(var, scale);
8043 :
8044 : /* but don't allow var->dscale to be negative */
8045 4698 : if (var->dscale < 0)
8046 126 : var->dscale = 0;
8047 :
8048 : /*
8049 : * Check for overflow - note we can't do this before rounding, because
8050 : * rounding could raise the weight. Also note that the var's weight could
8051 : * be inflated by leading zeroes, which will be stripped before storage
8052 : * but perhaps might not have been yet. In any case, we must recognize a
8053 : * true zero, whose weight doesn't mean anything.
8054 : */
8055 4698 : ddigits = (var->weight + 1) * DEC_DIGITS;
8056 4698 : if (ddigits > maxdigits)
8057 : {
8058 : /* Determine true weight; and check for all-zero result */
8059 410 : for (i = 0; i < var->ndigits; i++)
8060 : {
8061 394 : NumericDigit dig = var->digits[i];
8062 :
8063 394 : if (dig)
8064 : {
8065 : /* Adjust for any high-order decimal zero digits */
8066 : #if DEC_DIGITS == 4
8067 394 : if (dig < 10)
8068 252 : ddigits -= 3;
8069 142 : else if (dig < 100)
8070 72 : ddigits -= 2;
8071 70 : else if (dig < 1000)
8072 52 : ddigits -= 1;
8073 : #elif DEC_DIGITS == 2
8074 : if (dig < 10)
8075 : ddigits -= 1;
8076 : #elif DEC_DIGITS == 1
8077 : /* no adjustment */
8078 : #else
8079 : #error unsupported NBASE
8080 : #endif
8081 394 : if (ddigits > maxdigits)
8082 84 : ereturn(escontext, false,
8083 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
8084 : errmsg("numeric field overflow"),
8085 : errdetail("A field with precision %d, scale %d must round to an absolute value less than %s%d.",
8086 : precision, scale,
8087 : /* Display 10^0 as 1 */
8088 : maxdigits ? "10^" : "",
8089 : maxdigits ? maxdigits : 1
8090 : )));
8091 310 : break;
8092 : }
8093 0 : ddigits -= DEC_DIGITS;
8094 : }
8095 : }
8096 :
8097 4614 : return true;
8098 : }
8099 :
8100 : /*
8101 : * apply_typmod_special() -
8102 : *
8103 : * Do bounds checking according to the specified typmod, for an Inf or NaN.
8104 : * For convenience of most callers, the value is presented in packed form.
8105 : *
8106 : * Returns true on success, false on failure (if escontext points to an
8107 : * ErrorSaveContext; otherwise errors are thrown).
8108 : */
8109 : static bool
8110 1882 : apply_typmod_special(Numeric num, int32 typmod, Node *escontext)
8111 : {
8112 : int precision;
8113 : int scale;
8114 :
8115 : Assert(NUMERIC_IS_SPECIAL(num)); /* caller error if not */
8116 :
8117 : /*
8118 : * NaN is allowed regardless of the typmod; that's rather dubious perhaps,
8119 : * but it's a longstanding behavior. Inf is rejected if we have any
8120 : * typmod restriction, since an infinity shouldn't be claimed to fit in
8121 : * any finite number of digits.
8122 : */
8123 1882 : if (NUMERIC_IS_NAN(num))
8124 784 : return true;
8125 :
8126 : /* Do nothing if we have a default typmod (-1) */
8127 1098 : if (!is_valid_numeric_typmod(typmod))
8128 1080 : return true;
8129 :
8130 18 : precision = numeric_typmod_precision(typmod);
8131 18 : scale = numeric_typmod_scale(typmod);
8132 :
8133 18 : ereturn(escontext, false,
8134 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
8135 : errmsg("numeric field overflow"),
8136 : errdetail("A field with precision %d, scale %d cannot hold an infinite value.",
8137 : precision, scale)));
8138 : }
8139 :
8140 :
8141 : /*
8142 : * Convert numeric to int8, rounding if needed.
8143 : *
8144 : * If overflow, return false (no error is raised). Return true if okay.
8145 : */
8146 : static bool
8147 10308 : numericvar_to_int64(const NumericVar *var, int64 *result)
8148 : {
8149 : NumericDigit *digits;
8150 : int ndigits;
8151 : int weight;
8152 : int i;
8153 : int64 val;
8154 : bool neg;
8155 : NumericVar rounded;
8156 :
8157 : /* Round to nearest integer */
8158 10308 : init_var(&rounded);
8159 10308 : set_var_from_var(var, &rounded);
8160 10308 : round_var(&rounded, 0);
8161 :
8162 : /* Check for zero input */
8163 10308 : strip_var(&rounded);
8164 10308 : ndigits = rounded.ndigits;
8165 10308 : if (ndigits == 0)
8166 : {
8167 478 : *result = 0;
8168 478 : free_var(&rounded);
8169 478 : return true;
8170 : }
8171 :
8172 : /*
8173 : * For input like 10000000000, we must treat stripped digits as real. So
8174 : * the loop assumes there are weight+1 digits before the decimal point.
8175 : */
8176 9830 : weight = rounded.weight;
8177 : Assert(weight >= 0 && ndigits <= weight + 1);
8178 :
8179 : /*
8180 : * Construct the result. To avoid issues with converting a value
8181 : * corresponding to INT64_MIN (which can't be represented as a positive 64
8182 : * bit two's complement integer), accumulate value as a negative number.
8183 : */
8184 9830 : digits = rounded.digits;
8185 9830 : neg = (rounded.sign == NUMERIC_NEG);
8186 9830 : val = -digits[0];
8187 14054 : for (i = 1; i <= weight; i++)
8188 : {
8189 4272 : if (unlikely(pg_mul_s64_overflow(val, NBASE, &val)))
8190 : {
8191 30 : free_var(&rounded);
8192 30 : return false;
8193 : }
8194 :
8195 4242 : if (i < ndigits)
8196 : {
8197 3964 : if (unlikely(pg_sub_s64_overflow(val, digits[i], &val)))
8198 : {
8199 18 : free_var(&rounded);
8200 18 : return false;
8201 : }
8202 : }
8203 : }
8204 :
8205 9782 : free_var(&rounded);
8206 :
8207 9782 : if (!neg)
8208 : {
8209 8990 : if (unlikely(val == PG_INT64_MIN))
8210 24 : return false;
8211 8966 : val = -val;
8212 : }
8213 9758 : *result = val;
8214 :
8215 9758 : return true;
8216 : }
8217 :
8218 : /*
8219 : * Convert int8 value to numeric.
8220 : */
8221 : static void
8222 1880394 : int64_to_numericvar(int64 val, NumericVar *var)
8223 : {
8224 : uint64 uval,
8225 : newuval;
8226 : NumericDigit *ptr;
8227 : int ndigits;
8228 :
8229 : /* int64 can require at most 19 decimal digits; add one for safety */
8230 1880394 : alloc_var(var, 20 / DEC_DIGITS);
8231 1880394 : if (val < 0)
8232 : {
8233 1814 : var->sign = NUMERIC_NEG;
8234 1814 : uval = pg_abs_s64(val);
8235 : }
8236 : else
8237 : {
8238 1878580 : var->sign = NUMERIC_POS;
8239 1878580 : uval = val;
8240 : }
8241 1880394 : var->dscale = 0;
8242 1880394 : if (val == 0)
8243 : {
8244 35354 : var->ndigits = 0;
8245 35354 : var->weight = 0;
8246 35354 : return;
8247 : }
8248 1845040 : ptr = var->digits + var->ndigits;
8249 1845040 : ndigits = 0;
8250 : do
8251 : {
8252 2168824 : ptr--;
8253 2168824 : ndigits++;
8254 2168824 : newuval = uval / NBASE;
8255 2168824 : *ptr = uval - newuval * NBASE;
8256 2168824 : uval = newuval;
8257 2168824 : } while (uval);
8258 1845040 : var->digits = ptr;
8259 1845040 : var->ndigits = ndigits;
8260 1845040 : var->weight = ndigits - 1;
8261 : }
8262 :
8263 : /*
8264 : * Convert numeric to uint64, rounding if needed.
8265 : *
8266 : * If overflow, return false (no error is raised). Return true if okay.
8267 : */
8268 : static bool
8269 114 : numericvar_to_uint64(const NumericVar *var, uint64 *result)
8270 : {
8271 : NumericDigit *digits;
8272 : int ndigits;
8273 : int weight;
8274 : int i;
8275 : uint64 val;
8276 : NumericVar rounded;
8277 :
8278 : /* Round to nearest integer */
8279 114 : init_var(&rounded);
8280 114 : set_var_from_var(var, &rounded);
8281 114 : round_var(&rounded, 0);
8282 :
8283 : /* Check for zero input */
8284 114 : strip_var(&rounded);
8285 114 : ndigits = rounded.ndigits;
8286 114 : if (ndigits == 0)
8287 : {
8288 18 : *result = 0;
8289 18 : free_var(&rounded);
8290 18 : return true;
8291 : }
8292 :
8293 : /* Check for negative input */
8294 96 : if (rounded.sign == NUMERIC_NEG)
8295 : {
8296 12 : free_var(&rounded);
8297 12 : return false;
8298 : }
8299 :
8300 : /*
8301 : * For input like 10000000000, we must treat stripped digits as real. So
8302 : * the loop assumes there are weight+1 digits before the decimal point.
8303 : */
8304 84 : weight = rounded.weight;
8305 : Assert(weight >= 0 && ndigits <= weight + 1);
8306 :
8307 : /* Construct the result */
8308 84 : digits = rounded.digits;
8309 84 : val = digits[0];
8310 246 : for (i = 1; i <= weight; i++)
8311 : {
8312 174 : if (unlikely(pg_mul_u64_overflow(val, NBASE, &val)))
8313 : {
8314 0 : free_var(&rounded);
8315 0 : return false;
8316 : }
8317 :
8318 174 : if (i < ndigits)
8319 : {
8320 174 : if (unlikely(pg_add_u64_overflow(val, digits[i], &val)))
8321 : {
8322 12 : free_var(&rounded);
8323 12 : return false;
8324 : }
8325 : }
8326 : }
8327 :
8328 72 : free_var(&rounded);
8329 :
8330 72 : *result = val;
8331 :
8332 72 : return true;
8333 : }
8334 :
8335 : #ifdef HAVE_INT128
8336 : /*
8337 : * Convert numeric to int128, rounding if needed.
8338 : *
8339 : * If overflow, return false (no error is raised). Return true if okay.
8340 : */
8341 : static bool
8342 30 : numericvar_to_int128(const NumericVar *var, int128 *result)
8343 : {
8344 : NumericDigit *digits;
8345 : int ndigits;
8346 : int weight;
8347 : int i;
8348 : int128 val,
8349 : oldval;
8350 : bool neg;
8351 : NumericVar rounded;
8352 :
8353 : /* Round to nearest integer */
8354 30 : init_var(&rounded);
8355 30 : set_var_from_var(var, &rounded);
8356 30 : round_var(&rounded, 0);
8357 :
8358 : /* Check for zero input */
8359 30 : strip_var(&rounded);
8360 30 : ndigits = rounded.ndigits;
8361 30 : if (ndigits == 0)
8362 : {
8363 0 : *result = 0;
8364 0 : free_var(&rounded);
8365 0 : return true;
8366 : }
8367 :
8368 : /*
8369 : * For input like 10000000000, we must treat stripped digits as real. So
8370 : * the loop assumes there are weight+1 digits before the decimal point.
8371 : */
8372 30 : weight = rounded.weight;
8373 : Assert(weight >= 0 && ndigits <= weight + 1);
8374 :
8375 : /* Construct the result */
8376 30 : digits = rounded.digits;
8377 30 : neg = (rounded.sign == NUMERIC_NEG);
8378 30 : val = digits[0];
8379 86 : for (i = 1; i <= weight; i++)
8380 : {
8381 56 : oldval = val;
8382 56 : val *= NBASE;
8383 56 : if (i < ndigits)
8384 44 : val += digits[i];
8385 :
8386 : /*
8387 : * The overflow check is a bit tricky because we want to accept
8388 : * INT128_MIN, which will overflow the positive accumulator. We can
8389 : * detect this case easily though because INT128_MIN is the only
8390 : * nonzero value for which -val == val (on a two's complement machine,
8391 : * anyway).
8392 : */
8393 56 : if ((val / NBASE) != oldval) /* possible overflow? */
8394 : {
8395 0 : if (!neg || (-val) != val || val == 0 || oldval < 0)
8396 : {
8397 0 : free_var(&rounded);
8398 0 : return false;
8399 : }
8400 : }
8401 : }
8402 :
8403 30 : free_var(&rounded);
8404 :
8405 30 : *result = neg ? -val : val;
8406 30 : return true;
8407 : }
8408 :
8409 : /*
8410 : * Convert 128 bit integer to numeric.
8411 : */
8412 : static void
8413 8734 : int128_to_numericvar(int128 val, NumericVar *var)
8414 : {
8415 : uint128 uval,
8416 : newuval;
8417 : NumericDigit *ptr;
8418 : int ndigits;
8419 :
8420 : /* int128 can require at most 39 decimal digits; add one for safety */
8421 8734 : alloc_var(var, 40 / DEC_DIGITS);
8422 8734 : if (val < 0)
8423 : {
8424 0 : var->sign = NUMERIC_NEG;
8425 0 : uval = -val;
8426 : }
8427 : else
8428 : {
8429 8734 : var->sign = NUMERIC_POS;
8430 8734 : uval = val;
8431 : }
8432 8734 : var->dscale = 0;
8433 8734 : if (val == 0)
8434 : {
8435 230 : var->ndigits = 0;
8436 230 : var->weight = 0;
8437 230 : return;
8438 : }
8439 8504 : ptr = var->digits + var->ndigits;
8440 8504 : ndigits = 0;
8441 : do
8442 : {
8443 44988 : ptr--;
8444 44988 : ndigits++;
8445 44988 : newuval = uval / NBASE;
8446 44988 : *ptr = uval - newuval * NBASE;
8447 44988 : uval = newuval;
8448 44988 : } while (uval);
8449 8504 : var->digits = ptr;
8450 8504 : var->ndigits = ndigits;
8451 8504 : var->weight = ndigits - 1;
8452 : }
8453 : #endif
8454 :
8455 : /*
8456 : * Convert a NumericVar to float8; if out of range, return +/- HUGE_VAL
8457 : */
8458 : static double
8459 3306 : numericvar_to_double_no_overflow(const NumericVar *var)
8460 : {
8461 : char *tmp;
8462 : double val;
8463 : char *endptr;
8464 :
8465 3306 : tmp = get_str_from_var(var);
8466 :
8467 : /* unlike float8in, we ignore ERANGE from strtod */
8468 3306 : val = strtod(tmp, &endptr);
8469 3306 : if (*endptr != '\0')
8470 : {
8471 : /* shouldn't happen ... */
8472 0 : ereport(ERROR,
8473 : (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
8474 : errmsg("invalid input syntax for type %s: \"%s\"",
8475 : "double precision", tmp)));
8476 : }
8477 :
8478 3306 : pfree(tmp);
8479 :
8480 3306 : return val;
8481 : }
8482 :
8483 :
8484 : /*
8485 : * cmp_var() -
8486 : *
8487 : * Compare two values on variable level. We assume zeroes have been
8488 : * truncated to no digits.
8489 : */
8490 : static int
8491 50204 : cmp_var(const NumericVar *var1, const NumericVar *var2)
8492 : {
8493 100408 : return cmp_var_common(var1->digits, var1->ndigits,
8494 : var1->weight, var1->sign,
8495 50204 : var2->digits, var2->ndigits,
8496 : var2->weight, var2->sign);
8497 : }
8498 :
8499 : /*
8500 : * cmp_var_common() -
8501 : *
8502 : * Main routine of cmp_var(). This function can be used by both
8503 : * NumericVar and Numeric.
8504 : */
8505 : static int
8506 6152494 : cmp_var_common(const NumericDigit *var1digits, int var1ndigits,
8507 : int var1weight, int var1sign,
8508 : const NumericDigit *var2digits, int var2ndigits,
8509 : int var2weight, int var2sign)
8510 : {
8511 6152494 : if (var1ndigits == 0)
8512 : {
8513 185074 : if (var2ndigits == 0)
8514 156862 : return 0;
8515 28212 : if (var2sign == NUMERIC_NEG)
8516 4272 : return 1;
8517 23940 : return -1;
8518 : }
8519 5967420 : if (var2ndigits == 0)
8520 : {
8521 32266 : if (var1sign == NUMERIC_POS)
8522 25268 : return 1;
8523 6998 : return -1;
8524 : }
8525 :
8526 5935154 : if (var1sign == NUMERIC_POS)
8527 : {
8528 5846444 : if (var2sign == NUMERIC_NEG)
8529 26646 : return 1;
8530 5819798 : return cmp_abs_common(var1digits, var1ndigits, var1weight,
8531 : var2digits, var2ndigits, var2weight);
8532 : }
8533 :
8534 88710 : if (var2sign == NUMERIC_POS)
8535 28742 : return -1;
8536 :
8537 59968 : return cmp_abs_common(var2digits, var2ndigits, var2weight,
8538 : var1digits, var1ndigits, var1weight);
8539 : }
8540 :
8541 :
8542 : /*
8543 : * add_var() -
8544 : *
8545 : * Full version of add functionality on variable level (handling signs).
8546 : * result might point to one of the operands too without danger.
8547 : */
8548 : static void
8549 497968 : add_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
8550 : {
8551 : /*
8552 : * Decide on the signs of the two variables what to do
8553 : */
8554 497968 : if (var1->sign == NUMERIC_POS)
8555 : {
8556 496402 : if (var2->sign == NUMERIC_POS)
8557 : {
8558 : /*
8559 : * Both are positive result = +(ABS(var1) + ABS(var2))
8560 : */
8561 296098 : add_abs(var1, var2, result);
8562 296098 : result->sign = NUMERIC_POS;
8563 : }
8564 : else
8565 : {
8566 : /*
8567 : * var1 is positive, var2 is negative Must compare absolute values
8568 : */
8569 200304 : switch (cmp_abs(var1, var2))
8570 : {
8571 184 : case 0:
8572 : /* ----------
8573 : * ABS(var1) == ABS(var2)
8574 : * result = ZERO
8575 : * ----------
8576 : */
8577 184 : zero_var(result);
8578 184 : result->dscale = Max(var1->dscale, var2->dscale);
8579 184 : break;
8580 :
8581 186104 : case 1:
8582 : /* ----------
8583 : * ABS(var1) > ABS(var2)
8584 : * result = +(ABS(var1) - ABS(var2))
8585 : * ----------
8586 : */
8587 186104 : sub_abs(var1, var2, result);
8588 186104 : result->sign = NUMERIC_POS;
8589 186104 : break;
8590 :
8591 14016 : case -1:
8592 : /* ----------
8593 : * ABS(var1) < ABS(var2)
8594 : * result = -(ABS(var2) - ABS(var1))
8595 : * ----------
8596 : */
8597 14016 : sub_abs(var2, var1, result);
8598 14016 : result->sign = NUMERIC_NEG;
8599 14016 : break;
8600 : }
8601 496402 : }
8602 : }
8603 : else
8604 : {
8605 1566 : if (var2->sign == NUMERIC_POS)
8606 : {
8607 : /* ----------
8608 : * var1 is negative, var2 is positive
8609 : * Must compare absolute values
8610 : * ----------
8611 : */
8612 468 : switch (cmp_abs(var1, var2))
8613 : {
8614 30 : case 0:
8615 : /* ----------
8616 : * ABS(var1) == ABS(var2)
8617 : * result = ZERO
8618 : * ----------
8619 : */
8620 30 : zero_var(result);
8621 30 : result->dscale = Max(var1->dscale, var2->dscale);
8622 30 : break;
8623 :
8624 294 : case 1:
8625 : /* ----------
8626 : * ABS(var1) > ABS(var2)
8627 : * result = -(ABS(var1) - ABS(var2))
8628 : * ----------
8629 : */
8630 294 : sub_abs(var1, var2, result);
8631 294 : result->sign = NUMERIC_NEG;
8632 294 : break;
8633 :
8634 144 : case -1:
8635 : /* ----------
8636 : * ABS(var1) < ABS(var2)
8637 : * result = +(ABS(var2) - ABS(var1))
8638 : * ----------
8639 : */
8640 144 : sub_abs(var2, var1, result);
8641 144 : result->sign = NUMERIC_POS;
8642 144 : break;
8643 : }
8644 468 : }
8645 : else
8646 : {
8647 : /* ----------
8648 : * Both are negative
8649 : * result = -(ABS(var1) + ABS(var2))
8650 : * ----------
8651 : */
8652 1098 : add_abs(var1, var2, result);
8653 1098 : result->sign = NUMERIC_NEG;
8654 : }
8655 : }
8656 497968 : }
8657 :
8658 :
8659 : /*
8660 : * sub_var() -
8661 : *
8662 : * Full version of sub functionality on variable level (handling signs).
8663 : * result might point to one of the operands too without danger.
8664 : */
8665 : static void
8666 186922 : sub_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
8667 : {
8668 : /*
8669 : * Decide on the signs of the two variables what to do
8670 : */
8671 186922 : if (var1->sign == NUMERIC_POS)
8672 : {
8673 184152 : if (var2->sign == NUMERIC_NEG)
8674 : {
8675 : /* ----------
8676 : * var1 is positive, var2 is negative
8677 : * result = +(ABS(var1) + ABS(var2))
8678 : * ----------
8679 : */
8680 33052 : add_abs(var1, var2, result);
8681 33052 : result->sign = NUMERIC_POS;
8682 : }
8683 : else
8684 : {
8685 : /* ----------
8686 : * Both are positive
8687 : * Must compare absolute values
8688 : * ----------
8689 : */
8690 151100 : switch (cmp_abs(var1, var2))
8691 : {
8692 29888 : case 0:
8693 : /* ----------
8694 : * ABS(var1) == ABS(var2)
8695 : * result = ZERO
8696 : * ----------
8697 : */
8698 29888 : zero_var(result);
8699 29888 : result->dscale = Max(var1->dscale, var2->dscale);
8700 29888 : break;
8701 :
8702 107376 : case 1:
8703 : /* ----------
8704 : * ABS(var1) > ABS(var2)
8705 : * result = +(ABS(var1) - ABS(var2))
8706 : * ----------
8707 : */
8708 107376 : sub_abs(var1, var2, result);
8709 107376 : result->sign = NUMERIC_POS;
8710 107376 : break;
8711 :
8712 13836 : case -1:
8713 : /* ----------
8714 : * ABS(var1) < ABS(var2)
8715 : * result = -(ABS(var2) - ABS(var1))
8716 : * ----------
8717 : */
8718 13836 : sub_abs(var2, var1, result);
8719 13836 : result->sign = NUMERIC_NEG;
8720 13836 : break;
8721 : }
8722 184152 : }
8723 : }
8724 : else
8725 : {
8726 2770 : if (var2->sign == NUMERIC_NEG)
8727 : {
8728 : /* ----------
8729 : * Both are negative
8730 : * Must compare absolute values
8731 : * ----------
8732 : */
8733 2314 : switch (cmp_abs(var1, var2))
8734 : {
8735 166 : case 0:
8736 : /* ----------
8737 : * ABS(var1) == ABS(var2)
8738 : * result = ZERO
8739 : * ----------
8740 : */
8741 166 : zero_var(result);
8742 166 : result->dscale = Max(var1->dscale, var2->dscale);
8743 166 : break;
8744 :
8745 240 : case 1:
8746 : /* ----------
8747 : * ABS(var1) > ABS(var2)
8748 : * result = -(ABS(var1) - ABS(var2))
8749 : * ----------
8750 : */
8751 240 : sub_abs(var1, var2, result);
8752 240 : result->sign = NUMERIC_NEG;
8753 240 : break;
8754 :
8755 1908 : case -1:
8756 : /* ----------
8757 : * ABS(var1) < ABS(var2)
8758 : * result = +(ABS(var2) - ABS(var1))
8759 : * ----------
8760 : */
8761 1908 : sub_abs(var2, var1, result);
8762 1908 : result->sign = NUMERIC_POS;
8763 1908 : break;
8764 : }
8765 2314 : }
8766 : else
8767 : {
8768 : /* ----------
8769 : * var1 is negative, var2 is positive
8770 : * result = -(ABS(var1) + ABS(var2))
8771 : * ----------
8772 : */
8773 456 : add_abs(var1, var2, result);
8774 456 : result->sign = NUMERIC_NEG;
8775 : }
8776 : }
8777 186922 : }
8778 :
8779 :
8780 : /*
8781 : * mul_var() -
8782 : *
8783 : * Multiplication on variable level. Product of var1 * var2 is stored
8784 : * in result. Result is rounded to no more than rscale fractional digits.
8785 : */
8786 : static void
8787 829820 : mul_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result,
8788 : int rscale)
8789 : {
8790 : int res_ndigits;
8791 : int res_ndigitpairs;
8792 : int res_sign;
8793 : int res_weight;
8794 : int pair_offset;
8795 : int maxdigits;
8796 : int maxdigitpairs;
8797 : uint64 *dig,
8798 : *dig_i1_off;
8799 : uint64 maxdig;
8800 : uint64 carry;
8801 : uint64 newdig;
8802 : int var1ndigits;
8803 : int var2ndigits;
8804 : int var1ndigitpairs;
8805 : int var2ndigitpairs;
8806 : NumericDigit *var1digits;
8807 : NumericDigit *var2digits;
8808 : uint32 var1digitpair;
8809 : uint32 *var2digitpairs;
8810 : NumericDigit *res_digits;
8811 : int i,
8812 : i1,
8813 : i2,
8814 : i2limit;
8815 :
8816 : /*
8817 : * Arrange for var1 to be the shorter of the two numbers. This improves
8818 : * performance because the inner multiplication loop is much simpler than
8819 : * the outer loop, so it's better to have a smaller number of iterations
8820 : * of the outer loop. This also reduces the number of times that the
8821 : * accumulator array needs to be normalized.
8822 : */
8823 829820 : if (var1->ndigits > var2->ndigits)
8824 : {
8825 14064 : const NumericVar *tmp = var1;
8826 :
8827 14064 : var1 = var2;
8828 14064 : var2 = tmp;
8829 : }
8830 :
8831 : /* copy these values into local vars for speed in inner loop */
8832 829820 : var1ndigits = var1->ndigits;
8833 829820 : var2ndigits = var2->ndigits;
8834 829820 : var1digits = var1->digits;
8835 829820 : var2digits = var2->digits;
8836 :
8837 829820 : if (var1ndigits == 0)
8838 : {
8839 : /* one or both inputs is zero; so is result */
8840 1712 : zero_var(result);
8841 1712 : result->dscale = rscale;
8842 1712 : return;
8843 : }
8844 :
8845 : /*
8846 : * If var1 has 1-6 digits and the exact result was requested, delegate to
8847 : * mul_var_short() which uses a faster direct multiplication algorithm.
8848 : */
8849 828108 : if (var1ndigits <= 6 && rscale == var1->dscale + var2->dscale)
8850 : {
8851 799632 : mul_var_short(var1, var2, result);
8852 799632 : return;
8853 : }
8854 :
8855 : /* Determine result sign */
8856 28476 : if (var1->sign == var2->sign)
8857 26994 : res_sign = NUMERIC_POS;
8858 : else
8859 1482 : res_sign = NUMERIC_NEG;
8860 :
8861 : /*
8862 : * Determine the number of result digits to compute and the (maximum
8863 : * possible) result weight. If the exact result would have more than
8864 : * rscale fractional digits, truncate the computation with
8865 : * MUL_GUARD_DIGITS guard digits, i.e., ignore input digits that would
8866 : * only contribute to the right of that. (This will give the exact
8867 : * rounded-to-rscale answer unless carries out of the ignored positions
8868 : * would have propagated through more than MUL_GUARD_DIGITS digits.)
8869 : *
8870 : * Note: an exact computation could not produce more than var1ndigits +
8871 : * var2ndigits digits, but we allocate at least one extra output digit in
8872 : * case rscale-driven rounding produces a carry out of the highest exact
8873 : * digit.
8874 : *
8875 : * The computation itself is done using base-NBASE^2 arithmetic, so we
8876 : * actually process the input digits in pairs, producing a base-NBASE^2
8877 : * intermediate result. This significantly improves performance, since
8878 : * schoolbook multiplication is O(N^2) in the number of input digits, and
8879 : * working in base NBASE^2 effectively halves "N".
8880 : *
8881 : * Note: in a truncated computation, we must compute at least one extra
8882 : * output digit to ensure that all the guard digits are fully computed.
8883 : */
8884 : /* digit pairs in each input */
8885 28476 : var1ndigitpairs = (var1ndigits + 1) / 2;
8886 28476 : var2ndigitpairs = (var2ndigits + 1) / 2;
8887 :
8888 : /* digits in exact result */
8889 28476 : res_ndigits = var1ndigits + var2ndigits;
8890 :
8891 : /* digit pairs in exact result with at least one extra output digit */
8892 28476 : res_ndigitpairs = res_ndigits / 2 + 1;
8893 :
8894 : /* pair offset to align result to end of dig[] */
8895 28476 : pair_offset = res_ndigitpairs - var1ndigitpairs - var2ndigitpairs + 1;
8896 :
8897 : /* maximum possible result weight (odd-length inputs shifted up below) */
8898 28476 : res_weight = var1->weight + var2->weight + 1 + 2 * res_ndigitpairs -
8899 28476 : res_ndigits - (var1ndigits & 1) - (var2ndigits & 1);
8900 :
8901 : /* rscale-based truncation with at least one extra output digit */
8902 28476 : maxdigits = res_weight + 1 + (rscale + DEC_DIGITS - 1) / DEC_DIGITS +
8903 : MUL_GUARD_DIGITS;
8904 28476 : maxdigitpairs = maxdigits / 2 + 1;
8905 :
8906 28476 : res_ndigitpairs = Min(res_ndigitpairs, maxdigitpairs);
8907 28476 : res_ndigits = 2 * res_ndigitpairs;
8908 :
8909 : /*
8910 : * In the computation below, digit pair i1 of var1 and digit pair i2 of
8911 : * var2 are multiplied and added to digit i1+i2+pair_offset of dig[]. Thus
8912 : * input digit pairs with index >= res_ndigitpairs - pair_offset don't
8913 : * contribute to the result, and can be ignored.
8914 : */
8915 28476 : if (res_ndigitpairs <= pair_offset)
8916 : {
8917 : /* All input digits will be ignored; so result is zero */
8918 12 : zero_var(result);
8919 12 : result->dscale = rscale;
8920 12 : return;
8921 : }
8922 28464 : var1ndigitpairs = Min(var1ndigitpairs, res_ndigitpairs - pair_offset);
8923 28464 : var2ndigitpairs = Min(var2ndigitpairs, res_ndigitpairs - pair_offset);
8924 :
8925 : /*
8926 : * We do the arithmetic in an array "dig[]" of unsigned 64-bit integers.
8927 : * Since PG_UINT64_MAX is much larger than NBASE^4, this gives us a lot of
8928 : * headroom to avoid normalizing carries immediately.
8929 : *
8930 : * maxdig tracks the maximum possible value of any dig[] entry; when this
8931 : * threatens to exceed PG_UINT64_MAX, we take the time to propagate
8932 : * carries. Furthermore, we need to ensure that overflow doesn't occur
8933 : * during the carry propagation passes either. The carry values could be
8934 : * as much as PG_UINT64_MAX / NBASE^2, so really we must normalize when
8935 : * digits threaten to exceed PG_UINT64_MAX - PG_UINT64_MAX / NBASE^2.
8936 : *
8937 : * To avoid overflow in maxdig itself, it actually represents the maximum
8938 : * possible value divided by NBASE^2-1, i.e., at the top of the loop it is
8939 : * known that no dig[] entry exceeds maxdig * (NBASE^2-1).
8940 : *
8941 : * The conversion of var1 to base NBASE^2 is done on the fly, as each new
8942 : * digit is required. The digits of var2 are converted upfront, and
8943 : * stored at the end of dig[]. To avoid loss of precision, the input
8944 : * digits are aligned with the start of digit pair array, effectively
8945 : * shifting them up (multiplying by NBASE) if the inputs have an odd
8946 : * number of NBASE digits.
8947 : */
8948 28464 : dig = (uint64 *) palloc(res_ndigitpairs * sizeof(uint64) +
8949 : var2ndigitpairs * sizeof(uint32));
8950 :
8951 : /* convert var2 to base NBASE^2, shifting up if its length is odd */
8952 28464 : var2digitpairs = (uint32 *) (dig + res_ndigitpairs);
8953 :
8954 1547190 : for (i2 = 0; i2 < var2ndigitpairs - 1; i2++)
8955 1518726 : var2digitpairs[i2] = var2digits[2 * i2] * NBASE + var2digits[2 * i2 + 1];
8956 :
8957 28464 : if (2 * i2 + 1 < var2ndigits)
8958 20448 : var2digitpairs[i2] = var2digits[2 * i2] * NBASE + var2digits[2 * i2 + 1];
8959 : else
8960 8016 : var2digitpairs[i2] = var2digits[2 * i2] * NBASE;
8961 :
8962 : /*
8963 : * Start by multiplying var2 by the least significant contributing digit
8964 : * pair from var1, storing the results at the end of dig[], and filling
8965 : * the leading digits with zeros.
8966 : *
8967 : * The loop here is the same as the inner loop below, except that we set
8968 : * the results in dig[], rather than adding to them. This is the
8969 : * performance bottleneck for multiplication, so we want to keep it simple
8970 : * enough so that it can be auto-vectorized. Accordingly, process the
8971 : * digits left-to-right even though schoolbook multiplication would
8972 : * suggest right-to-left. Since we aren't propagating carries in this
8973 : * loop, the order does not matter.
8974 : */
8975 28464 : i1 = var1ndigitpairs - 1;
8976 28464 : if (2 * i1 + 1 < var1ndigits)
8977 12720 : var1digitpair = var1digits[2 * i1] * NBASE + var1digits[2 * i1 + 1];
8978 : else
8979 15744 : var1digitpair = var1digits[2 * i1] * NBASE;
8980 28464 : maxdig = var1digitpair;
8981 :
8982 28464 : i2limit = Min(var2ndigitpairs, res_ndigitpairs - i1 - pair_offset);
8983 28464 : dig_i1_off = &dig[i1 + pair_offset];
8984 :
8985 28464 : memset(dig, 0, (i1 + pair_offset) * sizeof(uint64));
8986 1376622 : for (i2 = 0; i2 < i2limit; i2++)
8987 1348158 : dig_i1_off[i2] = (uint64) var1digitpair * var2digitpairs[i2];
8988 :
8989 : /*
8990 : * Next, multiply var2 by the remaining digit pairs from var1, adding the
8991 : * results to dig[] at the appropriate offsets, and normalizing whenever
8992 : * there is a risk of any dig[] entry overflowing.
8993 : */
8994 1501710 : for (i1 = i1 - 1; i1 >= 0; i1--)
8995 : {
8996 1473246 : var1digitpair = var1digits[2 * i1] * NBASE + var1digits[2 * i1 + 1];
8997 1473246 : if (var1digitpair == 0)
8998 1179516 : continue;
8999 :
9000 : /* Time to normalize? */
9001 293730 : maxdig += var1digitpair;
9002 293730 : if (maxdig > (PG_UINT64_MAX - PG_UINT64_MAX / NBASE_SQR) / (NBASE_SQR - 1))
9003 : {
9004 : /* Yes, do it (to base NBASE^2) */
9005 30 : carry = 0;
9006 119964 : for (i = res_ndigitpairs - 1; i >= 0; i--)
9007 : {
9008 119934 : newdig = dig[i] + carry;
9009 119934 : if (newdig >= NBASE_SQR)
9010 : {
9011 115242 : carry = newdig / NBASE_SQR;
9012 115242 : newdig -= carry * NBASE_SQR;
9013 : }
9014 : else
9015 4692 : carry = 0;
9016 119934 : dig[i] = newdig;
9017 : }
9018 : Assert(carry == 0);
9019 : /* Reset maxdig to indicate new worst-case */
9020 30 : maxdig = 1 + var1digitpair;
9021 : }
9022 :
9023 : /* Multiply and add */
9024 293730 : i2limit = Min(var2ndigitpairs, res_ndigitpairs - i1 - pair_offset);
9025 293730 : dig_i1_off = &dig[i1 + pair_offset];
9026 :
9027 124047846 : for (i2 = 0; i2 < i2limit; i2++)
9028 123754116 : dig_i1_off[i2] += (uint64) var1digitpair * var2digitpairs[i2];
9029 : }
9030 :
9031 : /*
9032 : * Now we do a final carry propagation pass to normalize back to base
9033 : * NBASE^2, and construct the base-NBASE result digits. Note that this is
9034 : * still done at full precision w/guard digits.
9035 : */
9036 28464 : alloc_var(result, res_ndigits);
9037 28464 : res_digits = result->digits;
9038 28464 : carry = 0;
9039 2882922 : for (i = res_ndigitpairs - 1; i >= 0; i--)
9040 : {
9041 2854458 : newdig = dig[i] + carry;
9042 2854458 : if (newdig >= NBASE_SQR)
9043 : {
9044 406914 : carry = newdig / NBASE_SQR;
9045 406914 : newdig -= carry * NBASE_SQR;
9046 : }
9047 : else
9048 2447544 : carry = 0;
9049 2854458 : res_digits[2 * i + 1] = (NumericDigit) ((uint32) newdig % NBASE);
9050 2854458 : res_digits[2 * i] = (NumericDigit) ((uint32) newdig / NBASE);
9051 : }
9052 : Assert(carry == 0);
9053 :
9054 28464 : pfree(dig);
9055 :
9056 : /*
9057 : * Finally, round the result to the requested precision.
9058 : */
9059 28464 : result->weight = res_weight;
9060 28464 : result->sign = res_sign;
9061 :
9062 : /* Round to target rscale (and set result->dscale) */
9063 28464 : round_var(result, rscale);
9064 :
9065 : /* Strip leading and trailing zeroes */
9066 28464 : strip_var(result);
9067 : }
9068 :
9069 :
9070 : /*
9071 : * mul_var_short() -
9072 : *
9073 : * Special-case multiplication function used when var1 has 1-6 digits, var2
9074 : * has at least as many digits as var1, and the exact product var1 * var2 is
9075 : * requested.
9076 : */
9077 : static void
9078 799632 : mul_var_short(const NumericVar *var1, const NumericVar *var2,
9079 : NumericVar *result)
9080 : {
9081 799632 : int var1ndigits = var1->ndigits;
9082 799632 : int var2ndigits = var2->ndigits;
9083 799632 : NumericDigit *var1digits = var1->digits;
9084 799632 : NumericDigit *var2digits = var2->digits;
9085 : int res_sign;
9086 : int res_weight;
9087 : int res_ndigits;
9088 : NumericDigit *res_buf;
9089 : NumericDigit *res_digits;
9090 799632 : uint32 carry = 0;
9091 : uint32 term;
9092 :
9093 : /* Check preconditions */
9094 : Assert(var1ndigits >= 1);
9095 : Assert(var1ndigits <= 6);
9096 : Assert(var2ndigits >= var1ndigits);
9097 :
9098 : /*
9099 : * Determine the result sign, weight, and number of digits to calculate.
9100 : * The weight figured here is correct if the product has no leading zero
9101 : * digits; otherwise strip_var() will fix things up. Note that, unlike
9102 : * mul_var(), we do not need to allocate an extra output digit, because we
9103 : * are not rounding here.
9104 : */
9105 799632 : if (var1->sign == var2->sign)
9106 798440 : res_sign = NUMERIC_POS;
9107 : else
9108 1192 : res_sign = NUMERIC_NEG;
9109 799632 : res_weight = var1->weight + var2->weight + 1;
9110 799632 : res_ndigits = var1ndigits + var2ndigits;
9111 :
9112 : /* Allocate result digit array */
9113 799632 : res_buf = digitbuf_alloc(res_ndigits + 1);
9114 799632 : res_buf[0] = 0; /* spare digit for later rounding */
9115 799632 : res_digits = res_buf + 1;
9116 :
9117 : /*
9118 : * Compute the result digits in reverse, in one pass, propagating the
9119 : * carry up as we go. The i'th result digit consists of the sum of the
9120 : * products var1digits[i1] * var2digits[i2] for which i = i1 + i2 + 1.
9121 : */
9122 : #define PRODSUM1(v1,i1,v2,i2) ((v1)[(i1)] * (v2)[(i2)])
9123 : #define PRODSUM2(v1,i1,v2,i2) (PRODSUM1(v1,i1,v2,i2) + (v1)[(i1)+1] * (v2)[(i2)-1])
9124 : #define PRODSUM3(v1,i1,v2,i2) (PRODSUM2(v1,i1,v2,i2) + (v1)[(i1)+2] * (v2)[(i2)-2])
9125 : #define PRODSUM4(v1,i1,v2,i2) (PRODSUM3(v1,i1,v2,i2) + (v1)[(i1)+3] * (v2)[(i2)-3])
9126 : #define PRODSUM5(v1,i1,v2,i2) (PRODSUM4(v1,i1,v2,i2) + (v1)[(i1)+4] * (v2)[(i2)-4])
9127 : #define PRODSUM6(v1,i1,v2,i2) (PRODSUM5(v1,i1,v2,i2) + (v1)[(i1)+5] * (v2)[(i2)-5])
9128 :
9129 799632 : switch (var1ndigits)
9130 : {
9131 793926 : case 1:
9132 : /* ---------
9133 : * 1-digit case:
9134 : * var1ndigits = 1
9135 : * var2ndigits >= 1
9136 : * res_ndigits = var2ndigits + 1
9137 : * ----------
9138 : */
9139 2887664 : for (int i = var2ndigits - 1; i >= 0; i--)
9140 : {
9141 2093738 : term = PRODSUM1(var1digits, 0, var2digits, i) + carry;
9142 2093738 : res_digits[i + 1] = (NumericDigit) (term % NBASE);
9143 2093738 : carry = term / NBASE;
9144 : }
9145 793926 : res_digits[0] = (NumericDigit) carry;
9146 793926 : break;
9147 :
9148 756 : case 2:
9149 : /* ---------
9150 : * 2-digit case:
9151 : * var1ndigits = 2
9152 : * var2ndigits >= 2
9153 : * res_ndigits = var2ndigits + 2
9154 : * ----------
9155 : */
9156 : /* last result digit and carry */
9157 756 : term = PRODSUM1(var1digits, 1, var2digits, var2ndigits - 1);
9158 756 : res_digits[res_ndigits - 1] = (NumericDigit) (term % NBASE);
9159 756 : carry = term / NBASE;
9160 :
9161 : /* remaining digits, except for the first two */
9162 2304 : for (int i = var2ndigits - 1; i >= 1; i--)
9163 : {
9164 1548 : term = PRODSUM2(var1digits, 0, var2digits, i) + carry;
9165 1548 : res_digits[i + 1] = (NumericDigit) (term % NBASE);
9166 1548 : carry = term / NBASE;
9167 : }
9168 756 : break;
9169 :
9170 204 : case 3:
9171 : /* ---------
9172 : * 3-digit case:
9173 : * var1ndigits = 3
9174 : * var2ndigits >= 3
9175 : * res_ndigits = var2ndigits + 3
9176 : * ----------
9177 : */
9178 : /* last two result digits */
9179 204 : term = PRODSUM1(var1digits, 2, var2digits, var2ndigits - 1);
9180 204 : res_digits[res_ndigits - 1] = (NumericDigit) (term % NBASE);
9181 204 : carry = term / NBASE;
9182 :
9183 204 : term = PRODSUM2(var1digits, 1, var2digits, var2ndigits - 1) + carry;
9184 204 : res_digits[res_ndigits - 2] = (NumericDigit) (term % NBASE);
9185 204 : carry = term / NBASE;
9186 :
9187 : /* remaining digits, except for the first three */
9188 546 : for (int i = var2ndigits - 1; i >= 2; i--)
9189 : {
9190 342 : term = PRODSUM3(var1digits, 0, var2digits, i) + carry;
9191 342 : res_digits[i + 1] = (NumericDigit) (term % NBASE);
9192 342 : carry = term / NBASE;
9193 : }
9194 204 : break;
9195 :
9196 4038 : case 4:
9197 : /* ---------
9198 : * 4-digit case:
9199 : * var1ndigits = 4
9200 : * var2ndigits >= 4
9201 : * res_ndigits = var2ndigits + 4
9202 : * ----------
9203 : */
9204 : /* last three result digits */
9205 4038 : term = PRODSUM1(var1digits, 3, var2digits, var2ndigits - 1);
9206 4038 : res_digits[res_ndigits - 1] = (NumericDigit) (term % NBASE);
9207 4038 : carry = term / NBASE;
9208 :
9209 4038 : term = PRODSUM2(var1digits, 2, var2digits, var2ndigits - 1) + carry;
9210 4038 : res_digits[res_ndigits - 2] = (NumericDigit) (term % NBASE);
9211 4038 : carry = term / NBASE;
9212 :
9213 4038 : term = PRODSUM3(var1digits, 1, var2digits, var2ndigits - 1) + carry;
9214 4038 : res_digits[res_ndigits - 3] = (NumericDigit) (term % NBASE);
9215 4038 : carry = term / NBASE;
9216 :
9217 : /* remaining digits, except for the first four */
9218 11268 : for (int i = var2ndigits - 1; i >= 3; i--)
9219 : {
9220 7230 : term = PRODSUM4(var1digits, 0, var2digits, i) + carry;
9221 7230 : res_digits[i + 1] = (NumericDigit) (term % NBASE);
9222 7230 : carry = term / NBASE;
9223 : }
9224 4038 : break;
9225 :
9226 114 : case 5:
9227 : /* ---------
9228 : * 5-digit case:
9229 : * var1ndigits = 5
9230 : * var2ndigits >= 5
9231 : * res_ndigits = var2ndigits + 5
9232 : * ----------
9233 : */
9234 : /* last four result digits */
9235 114 : term = PRODSUM1(var1digits, 4, var2digits, var2ndigits - 1);
9236 114 : res_digits[res_ndigits - 1] = (NumericDigit) (term % NBASE);
9237 114 : carry = term / NBASE;
9238 :
9239 114 : term = PRODSUM2(var1digits, 3, var2digits, var2ndigits - 1) + carry;
9240 114 : res_digits[res_ndigits - 2] = (NumericDigit) (term % NBASE);
9241 114 : carry = term / NBASE;
9242 :
9243 114 : term = PRODSUM3(var1digits, 2, var2digits, var2ndigits - 1) + carry;
9244 114 : res_digits[res_ndigits - 3] = (NumericDigit) (term % NBASE);
9245 114 : carry = term / NBASE;
9246 :
9247 114 : term = PRODSUM4(var1digits, 1, var2digits, var2ndigits - 1) + carry;
9248 114 : res_digits[res_ndigits - 4] = (NumericDigit) (term % NBASE);
9249 114 : carry = term / NBASE;
9250 :
9251 : /* remaining digits, except for the first five */
9252 300 : for (int i = var2ndigits - 1; i >= 4; i--)
9253 : {
9254 186 : term = PRODSUM5(var1digits, 0, var2digits, i) + carry;
9255 186 : res_digits[i + 1] = (NumericDigit) (term % NBASE);
9256 186 : carry = term / NBASE;
9257 : }
9258 114 : break;
9259 :
9260 594 : case 6:
9261 : /* ---------
9262 : * 6-digit case:
9263 : * var1ndigits = 6
9264 : * var2ndigits >= 6
9265 : * res_ndigits = var2ndigits + 6
9266 : * ----------
9267 : */
9268 : /* last five result digits */
9269 594 : term = PRODSUM1(var1digits, 5, var2digits, var2ndigits - 1);
9270 594 : res_digits[res_ndigits - 1] = (NumericDigit) (term % NBASE);
9271 594 : carry = term / NBASE;
9272 :
9273 594 : term = PRODSUM2(var1digits, 4, var2digits, var2ndigits - 1) + carry;
9274 594 : res_digits[res_ndigits - 2] = (NumericDigit) (term % NBASE);
9275 594 : carry = term / NBASE;
9276 :
9277 594 : term = PRODSUM3(var1digits, 3, var2digits, var2ndigits - 1) + carry;
9278 594 : res_digits[res_ndigits - 3] = (NumericDigit) (term % NBASE);
9279 594 : carry = term / NBASE;
9280 :
9281 594 : term = PRODSUM4(var1digits, 2, var2digits, var2ndigits - 1) + carry;
9282 594 : res_digits[res_ndigits - 4] = (NumericDigit) (term % NBASE);
9283 594 : carry = term / NBASE;
9284 :
9285 594 : term = PRODSUM5(var1digits, 1, var2digits, var2ndigits - 1) + carry;
9286 594 : res_digits[res_ndigits - 5] = (NumericDigit) (term % NBASE);
9287 594 : carry = term / NBASE;
9288 :
9289 : /* remaining digits, except for the first six */
9290 1656 : for (int i = var2ndigits - 1; i >= 5; i--)
9291 : {
9292 1062 : term = PRODSUM6(var1digits, 0, var2digits, i) + carry;
9293 1062 : res_digits[i + 1] = (NumericDigit) (term % NBASE);
9294 1062 : carry = term / NBASE;
9295 : }
9296 594 : break;
9297 : }
9298 :
9299 : /*
9300 : * Finally, for var1ndigits > 1, compute the remaining var1ndigits most
9301 : * significant result digits.
9302 : */
9303 799632 : switch (var1ndigits)
9304 : {
9305 594 : case 6:
9306 594 : term = PRODSUM5(var1digits, 0, var2digits, 4) + carry;
9307 594 : res_digits[5] = (NumericDigit) (term % NBASE);
9308 594 : carry = term / NBASE;
9309 : /* FALLTHROUGH */
9310 708 : case 5:
9311 708 : term = PRODSUM4(var1digits, 0, var2digits, 3) + carry;
9312 708 : res_digits[4] = (NumericDigit) (term % NBASE);
9313 708 : carry = term / NBASE;
9314 : /* FALLTHROUGH */
9315 4746 : case 4:
9316 4746 : term = PRODSUM3(var1digits, 0, var2digits, 2) + carry;
9317 4746 : res_digits[3] = (NumericDigit) (term % NBASE);
9318 4746 : carry = term / NBASE;
9319 : /* FALLTHROUGH */
9320 4950 : case 3:
9321 4950 : term = PRODSUM2(var1digits, 0, var2digits, 1) + carry;
9322 4950 : res_digits[2] = (NumericDigit) (term % NBASE);
9323 4950 : carry = term / NBASE;
9324 : /* FALLTHROUGH */
9325 5706 : case 2:
9326 5706 : term = PRODSUM1(var1digits, 0, var2digits, 0) + carry;
9327 5706 : res_digits[1] = (NumericDigit) (term % NBASE);
9328 5706 : res_digits[0] = (NumericDigit) (term / NBASE);
9329 5706 : break;
9330 : }
9331 :
9332 : /* Store the product in result */
9333 799632 : digitbuf_free(result->buf);
9334 799632 : result->ndigits = res_ndigits;
9335 799632 : result->buf = res_buf;
9336 799632 : result->digits = res_digits;
9337 799632 : result->weight = res_weight;
9338 799632 : result->sign = res_sign;
9339 799632 : result->dscale = var1->dscale + var2->dscale;
9340 :
9341 : /* Strip leading and trailing zeroes */
9342 799632 : strip_var(result);
9343 799632 : }
9344 :
9345 :
9346 : /*
9347 : * div_var() -
9348 : *
9349 : * Compute the quotient var1 / var2 to rscale fractional digits.
9350 : *
9351 : * If "round" is true, the result is rounded at the rscale'th digit; if
9352 : * false, it is truncated (towards zero) at that digit.
9353 : *
9354 : * If "exact" is true, the exact result is computed to the specified rscale;
9355 : * if false, successive quotient digits are approximated up to rscale plus
9356 : * DIV_GUARD_DIGITS extra digits, ignoring all contributions from digits to
9357 : * the right of that, before rounding or truncating to the specified rscale.
9358 : * This can be significantly faster, and usually gives the same result as the
9359 : * exact computation, but it may occasionally be off by one in the final
9360 : * digit, if contributions from the ignored digits would have propagated
9361 : * through the guard digits. This is good enough for the transcendental
9362 : * functions, where small errors are acceptable.
9363 : */
9364 : static void
9365 214016 : div_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result,
9366 : int rscale, bool round, bool exact)
9367 : {
9368 214016 : int var1ndigits = var1->ndigits;
9369 214016 : int var2ndigits = var2->ndigits;
9370 : int res_sign;
9371 : int res_weight;
9372 : int res_ndigits;
9373 : int var1ndigitpairs;
9374 : int var2ndigitpairs;
9375 : int res_ndigitpairs;
9376 : int div_ndigitpairs;
9377 : int64 *dividend;
9378 : int32 *divisor;
9379 : double fdivisor,
9380 : fdivisorinverse,
9381 : fdividend,
9382 : fquotient;
9383 : int64 maxdiv;
9384 : int qi;
9385 : int32 qdigit;
9386 : int64 carry;
9387 : int64 newdig;
9388 : int64 *remainder;
9389 : NumericDigit *res_digits;
9390 : int i;
9391 :
9392 : /*
9393 : * First of all division by zero check; we must not be handed an
9394 : * unnormalized divisor.
9395 : */
9396 214016 : if (var2ndigits == 0 || var2->digits[0] == 0)
9397 62 : ereport(ERROR,
9398 : (errcode(ERRCODE_DIVISION_BY_ZERO),
9399 : errmsg("division by zero")));
9400 :
9401 : /*
9402 : * If the divisor has just one or two digits, delegate to div_var_int(),
9403 : * which uses fast short division.
9404 : *
9405 : * Similarly, on platforms with 128-bit integer support, delegate to
9406 : * div_var_int64() for divisors with three or four digits.
9407 : */
9408 213954 : if (var2ndigits <= 2)
9409 : {
9410 : int idivisor;
9411 : int idivisor_weight;
9412 :
9413 205096 : idivisor = var2->digits[0];
9414 205096 : idivisor_weight = var2->weight;
9415 205096 : if (var2ndigits == 2)
9416 : {
9417 3938 : idivisor = idivisor * NBASE + var2->digits[1];
9418 3938 : idivisor_weight--;
9419 : }
9420 205096 : if (var2->sign == NUMERIC_NEG)
9421 654 : idivisor = -idivisor;
9422 :
9423 205096 : div_var_int(var1, idivisor, idivisor_weight, result, rscale, round);
9424 205096 : return;
9425 : }
9426 : #ifdef HAVE_INT128
9427 8858 : if (var2ndigits <= 4)
9428 : {
9429 : int64 idivisor;
9430 : int idivisor_weight;
9431 :
9432 540 : idivisor = var2->digits[0];
9433 540 : idivisor_weight = var2->weight;
9434 2016 : for (i = 1; i < var2ndigits; i++)
9435 : {
9436 1476 : idivisor = idivisor * NBASE + var2->digits[i];
9437 1476 : idivisor_weight--;
9438 : }
9439 540 : if (var2->sign == NUMERIC_NEG)
9440 120 : idivisor = -idivisor;
9441 :
9442 540 : div_var_int64(var1, idivisor, idivisor_weight, result, rscale, round);
9443 540 : return;
9444 : }
9445 : #endif
9446 :
9447 : /*
9448 : * Otherwise, perform full long division.
9449 : */
9450 :
9451 : /* Result zero check */
9452 8318 : if (var1ndigits == 0)
9453 : {
9454 36 : zero_var(result);
9455 36 : result->dscale = rscale;
9456 36 : return;
9457 : }
9458 :
9459 : /*
9460 : * The approximate computation can be significantly faster than the exact
9461 : * one, since the working dividend is var2ndigitpairs base-NBASE^2 digits
9462 : * shorter below. However, that comes with the tradeoff of computing
9463 : * DIV_GUARD_DIGITS extra base-NBASE result digits. Ignoring all other
9464 : * overheads, that suggests that, in theory, the approximate computation
9465 : * will only be faster than the exact one when var2ndigits is greater than
9466 : * 2 * (DIV_GUARD_DIGITS + 1), independent of the size of var1.
9467 : *
9468 : * Thus, we're better off doing an exact computation when var2 is shorter
9469 : * than this. Empirically, it has been found that the exact threshold is
9470 : * a little higher, due to other overheads in the outer division loop.
9471 : */
9472 8282 : if (var2ndigits <= 2 * (DIV_GUARD_DIGITS + 2))
9473 6504 : exact = true;
9474 :
9475 : /*
9476 : * Determine the result sign, weight and number of digits to calculate.
9477 : * The weight figured here is correct if the emitted quotient has no
9478 : * leading zero digits; otherwise strip_var() will fix things up.
9479 : */
9480 8282 : if (var1->sign == var2->sign)
9481 8150 : res_sign = NUMERIC_POS;
9482 : else
9483 132 : res_sign = NUMERIC_NEG;
9484 8282 : res_weight = var1->weight - var2->weight + 1;
9485 : /* The number of accurate result digits we need to produce: */
9486 8282 : res_ndigits = res_weight + 1 + (rscale + DEC_DIGITS - 1) / DEC_DIGITS;
9487 : /* ... but always at least 1 */
9488 8282 : res_ndigits = Max(res_ndigits, 1);
9489 : /* If rounding needed, figure one more digit to ensure correct result */
9490 8282 : if (round)
9491 3746 : res_ndigits++;
9492 : /* Add guard digits for roundoff error when producing approx result */
9493 8282 : if (!exact)
9494 1722 : res_ndigits += DIV_GUARD_DIGITS;
9495 :
9496 : /*
9497 : * The computation itself is done using base-NBASE^2 arithmetic, so we
9498 : * actually process the input digits in pairs, producing a base-NBASE^2
9499 : * intermediate result. This significantly improves performance, since
9500 : * the computation is O(N^2) in the number of input digits, and working in
9501 : * base NBASE^2 effectively halves "N".
9502 : */
9503 8282 : var1ndigitpairs = (var1ndigits + 1) / 2;
9504 8282 : var2ndigitpairs = (var2ndigits + 1) / 2;
9505 8282 : res_ndigitpairs = (res_ndigits + 1) / 2;
9506 8282 : res_ndigits = 2 * res_ndigitpairs;
9507 :
9508 : /*
9509 : * We do the arithmetic in an array "dividend[]" of signed 64-bit
9510 : * integers. Since PG_INT64_MAX is much larger than NBASE^4, this gives
9511 : * us a lot of headroom to avoid normalizing carries immediately.
9512 : *
9513 : * When performing an exact computation, the working dividend requires
9514 : * res_ndigitpairs + var2ndigitpairs digits. If var1 is larger than that,
9515 : * the extra digits do not contribute to the result, and are ignored.
9516 : *
9517 : * When performing an approximate computation, the working dividend only
9518 : * requires res_ndigitpairs digits (which includes the extra guard
9519 : * digits). All input digits beyond that are ignored.
9520 : */
9521 8282 : if (exact)
9522 : {
9523 6560 : div_ndigitpairs = res_ndigitpairs + var2ndigitpairs;
9524 6560 : var1ndigitpairs = Min(var1ndigitpairs, div_ndigitpairs);
9525 : }
9526 : else
9527 : {
9528 1722 : div_ndigitpairs = res_ndigitpairs;
9529 1722 : var1ndigitpairs = Min(var1ndigitpairs, div_ndigitpairs);
9530 1722 : var2ndigitpairs = Min(var2ndigitpairs, div_ndigitpairs);
9531 : }
9532 :
9533 : /*
9534 : * Allocate room for the working dividend (div_ndigitpairs 64-bit digits)
9535 : * plus the divisor (var2ndigitpairs 32-bit base-NBASE^2 digits).
9536 : *
9537 : * For convenience, we allocate one extra dividend digit, which is set to
9538 : * zero and not counted in div_ndigitpairs, so that the main loop below
9539 : * can safely read and write the (qi+1)'th digit in the approximate case.
9540 : */
9541 8282 : dividend = (int64 *) palloc((div_ndigitpairs + 1) * sizeof(int64) +
9542 : var2ndigitpairs * sizeof(int32));
9543 8282 : divisor = (int32 *) (dividend + div_ndigitpairs + 1);
9544 :
9545 : /* load var1 into dividend[0 .. var1ndigitpairs-1], zeroing the rest */
9546 60596 : for (i = 0; i < var1ndigitpairs - 1; i++)
9547 52314 : dividend[i] = var1->digits[2 * i] * NBASE + var1->digits[2 * i + 1];
9548 :
9549 8282 : if (2 * i + 1 < var1ndigits)
9550 3752 : dividend[i] = var1->digits[2 * i] * NBASE + var1->digits[2 * i + 1];
9551 : else
9552 4530 : dividend[i] = var1->digits[2 * i] * NBASE;
9553 :
9554 8282 : memset(dividend + i + 1, 0, (div_ndigitpairs - i) * sizeof(int64));
9555 :
9556 : /* load var2 into divisor[0 .. var2ndigitpairs-1] */
9557 52040 : for (i = 0; i < var2ndigitpairs - 1; i++)
9558 43758 : divisor[i] = var2->digits[2 * i] * NBASE + var2->digits[2 * i + 1];
9559 :
9560 8282 : if (2 * i + 1 < var2ndigits)
9561 2970 : divisor[i] = var2->digits[2 * i] * NBASE + var2->digits[2 * i + 1];
9562 : else
9563 5312 : divisor[i] = var2->digits[2 * i] * NBASE;
9564 :
9565 : /*
9566 : * We estimate each quotient digit using floating-point arithmetic, taking
9567 : * the first 2 base-NBASE^2 digits of the (current) dividend and divisor.
9568 : * This must be float to avoid overflow.
9569 : *
9570 : * Since the floating-point dividend and divisor use 4 base-NBASE input
9571 : * digits, they include roughly 40-53 bits of information from their
9572 : * respective inputs (assuming NBASE is 10000), which fits well in IEEE
9573 : * double-precision variables. The relative error in the floating-point
9574 : * quotient digit will then be less than around 2/NBASE^3, so the
9575 : * estimated base-NBASE^2 quotient digit will typically be correct, and
9576 : * should not be off by more than one from the correct value.
9577 : */
9578 8282 : fdivisor = (double) divisor[0] * NBASE_SQR;
9579 8282 : if (var2ndigitpairs > 1)
9580 8282 : fdivisor += (double) divisor[1];
9581 8282 : fdivisorinverse = 1.0 / fdivisor;
9582 :
9583 : /*
9584 : * maxdiv tracks the maximum possible absolute value of any dividend[]
9585 : * entry; when this threatens to exceed PG_INT64_MAX, we take the time to
9586 : * propagate carries. Furthermore, we need to ensure that overflow
9587 : * doesn't occur during the carry propagation passes either. The carry
9588 : * values may have an absolute value as high as PG_INT64_MAX/NBASE^2 + 1,
9589 : * so really we must normalize when digits threaten to exceed PG_INT64_MAX
9590 : * - PG_INT64_MAX/NBASE^2 - 1.
9591 : *
9592 : * To avoid overflow in maxdiv itself, it represents the max absolute
9593 : * value divided by NBASE^2-1, i.e., at the top of the loop it is known
9594 : * that no dividend[] entry has an absolute value exceeding maxdiv *
9595 : * (NBASE^2-1).
9596 : *
9597 : * Actually, though, that holds good only for dividend[] entries after
9598 : * dividend[qi]; the adjustment done at the bottom of the loop may cause
9599 : * dividend[qi + 1] to exceed the maxdiv limit, so that dividend[qi] in
9600 : * the next iteration is beyond the limit. This does not cause problems,
9601 : * as explained below.
9602 : */
9603 8282 : maxdiv = 1;
9604 :
9605 : /*
9606 : * Outer loop computes next quotient digit, which goes in dividend[qi].
9607 : */
9608 63826 : for (qi = 0; qi < res_ndigitpairs; qi++)
9609 : {
9610 : /* Approximate the current dividend value */
9611 55544 : fdividend = (double) dividend[qi] * NBASE_SQR;
9612 55544 : fdividend += (double) dividend[qi + 1];
9613 :
9614 : /* Compute the (approximate) quotient digit */
9615 55544 : fquotient = fdividend * fdivisorinverse;
9616 55544 : qdigit = (fquotient >= 0.0) ? ((int32) fquotient) :
9617 6 : (((int32) fquotient) - 1); /* truncate towards -infinity */
9618 :
9619 55544 : if (qdigit != 0)
9620 : {
9621 : /* Do we need to normalize now? */
9622 49510 : maxdiv += i64abs(qdigit);
9623 49510 : if (maxdiv > (PG_INT64_MAX - PG_INT64_MAX / NBASE_SQR - 1) / (NBASE_SQR - 1))
9624 : {
9625 : /*
9626 : * Yes, do it. Note that if var2ndigitpairs is much smaller
9627 : * than div_ndigitpairs, we can save a significant amount of
9628 : * effort here by noting that we only need to normalise those
9629 : * dividend[] entries touched where prior iterations
9630 : * subtracted multiples of the divisor.
9631 : */
9632 6 : carry = 0;
9633 6750 : for (i = Min(qi + var2ndigitpairs - 2, div_ndigitpairs - 1); i > qi; i--)
9634 : {
9635 6744 : newdig = dividend[i] + carry;
9636 6744 : if (newdig < 0)
9637 : {
9638 6744 : carry = -((-newdig - 1) / NBASE_SQR) - 1;
9639 6744 : newdig -= carry * NBASE_SQR;
9640 : }
9641 0 : else if (newdig >= NBASE_SQR)
9642 : {
9643 0 : carry = newdig / NBASE_SQR;
9644 0 : newdig -= carry * NBASE_SQR;
9645 : }
9646 : else
9647 0 : carry = 0;
9648 6744 : dividend[i] = newdig;
9649 : }
9650 6 : dividend[qi] += carry;
9651 :
9652 : /*
9653 : * All the dividend[] digits except possibly dividend[qi] are
9654 : * now in the range 0..NBASE^2-1. We do not need to consider
9655 : * dividend[qi] in the maxdiv value anymore, so we can reset
9656 : * maxdiv to 1.
9657 : */
9658 6 : maxdiv = 1;
9659 :
9660 : /*
9661 : * Recompute the quotient digit since new info may have
9662 : * propagated into the top two dividend digits.
9663 : */
9664 6 : fdividend = (double) dividend[qi] * NBASE_SQR;
9665 6 : fdividend += (double) dividend[qi + 1];
9666 6 : fquotient = fdividend * fdivisorinverse;
9667 6 : qdigit = (fquotient >= 0.0) ? ((int32) fquotient) :
9668 0 : (((int32) fquotient) - 1); /* truncate towards -infinity */
9669 :
9670 6 : maxdiv += i64abs(qdigit);
9671 : }
9672 :
9673 : /*
9674 : * Subtract off the appropriate multiple of the divisor.
9675 : *
9676 : * The digits beyond dividend[qi] cannot overflow, because we know
9677 : * they will fall within the maxdiv limit. As for dividend[qi]
9678 : * itself, note that qdigit is approximately trunc(dividend[qi] /
9679 : * divisor[0]), which would make the new value simply dividend[qi]
9680 : * mod divisor[0]. The lower-order terms in qdigit can change
9681 : * this result by not more than about twice PG_INT64_MAX/NBASE^2,
9682 : * so overflow is impossible.
9683 : *
9684 : * This inner loop is the performance bottleneck for division, so
9685 : * code it in the same way as the inner loop of mul_var() so that
9686 : * it can be auto-vectorized.
9687 : */
9688 49510 : if (qdigit != 0)
9689 : {
9690 49510 : int istop = Min(var2ndigitpairs, div_ndigitpairs - qi);
9691 49510 : int64 *dividend_qi = ÷nd[qi];
9692 :
9693 7907282 : for (i = 0; i < istop; i++)
9694 7857772 : dividend_qi[i] -= (int64) qdigit * divisor[i];
9695 : }
9696 : }
9697 :
9698 : /*
9699 : * The dividend digit we are about to replace might still be nonzero.
9700 : * Fold it into the next digit position.
9701 : *
9702 : * There is no risk of overflow here, although proving that requires
9703 : * some care. Much as with the argument for dividend[qi] not
9704 : * overflowing, if we consider the first two terms in the numerator
9705 : * and denominator of qdigit, we can see that the final value of
9706 : * dividend[qi + 1] will be approximately a remainder mod
9707 : * (divisor[0]*NBASE^2 + divisor[1]). Accounting for the lower-order
9708 : * terms is a bit complicated but ends up adding not much more than
9709 : * PG_INT64_MAX/NBASE^2 to the possible range. Thus, dividend[qi + 1]
9710 : * cannot overflow here, and in its role as dividend[qi] in the next
9711 : * loop iteration, it can't be large enough to cause overflow in the
9712 : * carry propagation step (if any), either.
9713 : *
9714 : * But having said that: dividend[qi] can be more than
9715 : * PG_INT64_MAX/NBASE^2, as noted above, which means that the product
9716 : * dividend[qi] * NBASE^2 *can* overflow. When that happens, adding
9717 : * it to dividend[qi + 1] will always cause a canceling overflow so
9718 : * that the end result is correct. We could avoid the intermediate
9719 : * overflow by doing the multiplication and addition using unsigned
9720 : * int64 arithmetic, which is modulo 2^64, but so far there appears no
9721 : * need.
9722 : */
9723 55544 : dividend[qi + 1] += dividend[qi] * NBASE_SQR;
9724 :
9725 55544 : dividend[qi] = qdigit;
9726 : }
9727 :
9728 : /*
9729 : * If an exact result was requested, use the remainder to correct the
9730 : * approximate quotient. The remainder is in dividend[], immediately
9731 : * after the quotient digits. Note, however, that although the remainder
9732 : * starts at dividend[qi = res_ndigitpairs], the first digit is the result
9733 : * of folding two remainder digits into one above, and the remainder
9734 : * currently only occupies var2ndigitpairs - 1 digits (the last digit of
9735 : * the working dividend was untouched by the computation above). Thus we
9736 : * expand the remainder down by one base-NBASE^2 digit when we normalize
9737 : * it, so that it completely fills the last var2ndigitpairs digits of the
9738 : * dividend array.
9739 : */
9740 8282 : if (exact)
9741 : {
9742 : /* Normalize the remainder, expanding it down by one digit */
9743 6560 : remainder = ÷nd[qi];
9744 6560 : carry = 0;
9745 32414 : for (i = var2ndigitpairs - 2; i >= 0; i--)
9746 : {
9747 25854 : newdig = remainder[i] + carry;
9748 25854 : if (newdig < 0)
9749 : {
9750 19204 : carry = -((-newdig - 1) / NBASE_SQR) - 1;
9751 19204 : newdig -= carry * NBASE_SQR;
9752 : }
9753 6650 : else if (newdig >= NBASE_SQR)
9754 : {
9755 6504 : carry = newdig / NBASE_SQR;
9756 6504 : newdig -= carry * NBASE_SQR;
9757 : }
9758 : else
9759 146 : carry = 0;
9760 25854 : remainder[i + 1] = newdig;
9761 : }
9762 6560 : remainder[0] = carry;
9763 :
9764 6560 : if (remainder[0] < 0)
9765 : {
9766 : /*
9767 : * The remainder is negative, so the approximate quotient is too
9768 : * large. Correct by reducing the quotient by one and adding the
9769 : * divisor to the remainder until the remainder is positive. We
9770 : * expect the quotient to be off by at most one, which has been
9771 : * borne out in all testing, but not conclusively proven, so we
9772 : * allow for larger corrections, just in case.
9773 : */
9774 : do
9775 : {
9776 : /* Add the divisor to the remainder */
9777 26 : carry = 0;
9778 1138 : for (i = var2ndigitpairs - 1; i > 0; i--)
9779 : {
9780 1112 : newdig = remainder[i] + divisor[i] + carry;
9781 1112 : if (newdig >= NBASE_SQR)
9782 : {
9783 966 : remainder[i] = newdig - NBASE_SQR;
9784 966 : carry = 1;
9785 : }
9786 : else
9787 : {
9788 146 : remainder[i] = newdig;
9789 146 : carry = 0;
9790 : }
9791 : }
9792 26 : remainder[0] += divisor[0] + carry;
9793 :
9794 : /* Subtract 1 from the quotient (propagating carries later) */
9795 26 : dividend[qi - 1]--;
9796 :
9797 26 : } while (remainder[0] < 0);
9798 : }
9799 : else
9800 : {
9801 : /*
9802 : * The remainder is nonnegative. If it's greater than or equal to
9803 : * the divisor, then the approximate quotient is too small and
9804 : * must be corrected. As above, we don't expect to have to apply
9805 : * more than one correction, but allow for it just in case.
9806 : */
9807 : while (true)
9808 6 : {
9809 6540 : bool less = false;
9810 :
9811 : /* Is remainder < divisor? */
9812 6558 : for (i = 0; i < var2ndigitpairs; i++)
9813 : {
9814 6552 : if (remainder[i] < divisor[i])
9815 : {
9816 6534 : less = true;
9817 6534 : break;
9818 : }
9819 18 : if (remainder[i] > divisor[i])
9820 0 : break; /* remainder > divisor */
9821 : }
9822 6540 : if (less)
9823 6534 : break; /* quotient is correct */
9824 :
9825 : /* Subtract the divisor from the remainder */
9826 6 : carry = 0;
9827 18 : for (i = var2ndigitpairs - 1; i > 0; i--)
9828 : {
9829 12 : newdig = remainder[i] - divisor[i] + carry;
9830 12 : if (newdig < 0)
9831 : {
9832 0 : remainder[i] = newdig + NBASE_SQR;
9833 0 : carry = -1;
9834 : }
9835 : else
9836 : {
9837 12 : remainder[i] = newdig;
9838 12 : carry = 0;
9839 : }
9840 : }
9841 6 : remainder[0] = remainder[0] - divisor[0] + carry;
9842 :
9843 : /* Add 1 to the quotient (propagating carries later) */
9844 6 : dividend[qi - 1]++;
9845 : }
9846 : }
9847 : }
9848 :
9849 : /*
9850 : * Because the quotient digits were estimates that might have been off by
9851 : * one (and we didn't bother propagating carries when adjusting the
9852 : * quotient above), some quotient digits might be out of range, so do a
9853 : * final carry propagation pass to normalize back to base NBASE^2, and
9854 : * construct the base-NBASE result digits. Note that this is still done
9855 : * at full precision w/guard digits.
9856 : */
9857 8282 : alloc_var(result, res_ndigits);
9858 8282 : res_digits = result->digits;
9859 8282 : carry = 0;
9860 63826 : for (i = res_ndigitpairs - 1; i >= 0; i--)
9861 : {
9862 55544 : newdig = dividend[i] + carry;
9863 55544 : if (newdig < 0)
9864 : {
9865 66 : carry = -((-newdig - 1) / NBASE_SQR) - 1;
9866 66 : newdig -= carry * NBASE_SQR;
9867 : }
9868 55478 : else if (newdig >= NBASE_SQR)
9869 : {
9870 0 : carry = newdig / NBASE_SQR;
9871 0 : newdig -= carry * NBASE_SQR;
9872 : }
9873 : else
9874 55478 : carry = 0;
9875 55544 : res_digits[2 * i + 1] = (NumericDigit) ((uint32) newdig % NBASE);
9876 55544 : res_digits[2 * i] = (NumericDigit) ((uint32) newdig / NBASE);
9877 : }
9878 : Assert(carry == 0);
9879 :
9880 8282 : pfree(dividend);
9881 :
9882 : /*
9883 : * Finally, round or truncate the result to the requested precision.
9884 : */
9885 8282 : result->weight = res_weight;
9886 8282 : result->sign = res_sign;
9887 :
9888 : /* Round or truncate to target rscale (and set result->dscale) */
9889 8282 : if (round)
9890 3746 : round_var(result, rscale);
9891 : else
9892 4536 : trunc_var(result, rscale);
9893 :
9894 : /* Strip leading and trailing zeroes */
9895 8282 : strip_var(result);
9896 : }
9897 :
9898 :
9899 : /*
9900 : * div_var_int() -
9901 : *
9902 : * Divide a numeric variable by a 32-bit integer with the specified weight.
9903 : * The quotient var / (ival * NBASE^ival_weight) is stored in result.
9904 : */
9905 : static void
9906 224254 : div_var_int(const NumericVar *var, int ival, int ival_weight,
9907 : NumericVar *result, int rscale, bool round)
9908 : {
9909 224254 : NumericDigit *var_digits = var->digits;
9910 224254 : int var_ndigits = var->ndigits;
9911 : int res_sign;
9912 : int res_weight;
9913 : int res_ndigits;
9914 : NumericDigit *res_buf;
9915 : NumericDigit *res_digits;
9916 : uint32 divisor;
9917 : int i;
9918 :
9919 : /* Guard against division by zero */
9920 224254 : if (ival == 0)
9921 0 : ereport(ERROR,
9922 : errcode(ERRCODE_DIVISION_BY_ZERO),
9923 : errmsg("division by zero"));
9924 :
9925 : /* Result zero check */
9926 224254 : if (var_ndigits == 0)
9927 : {
9928 2300 : zero_var(result);
9929 2300 : result->dscale = rscale;
9930 2300 : return;
9931 : }
9932 :
9933 : /*
9934 : * Determine the result sign, weight and number of digits to calculate.
9935 : * The weight figured here is correct if the emitted quotient has no
9936 : * leading zero digits; otherwise strip_var() will fix things up.
9937 : */
9938 221954 : if (var->sign == NUMERIC_POS)
9939 218966 : res_sign = ival > 0 ? NUMERIC_POS : NUMERIC_NEG;
9940 : else
9941 2988 : res_sign = ival > 0 ? NUMERIC_NEG : NUMERIC_POS;
9942 221954 : res_weight = var->weight - ival_weight;
9943 : /* The number of accurate result digits we need to produce: */
9944 221954 : res_ndigits = res_weight + 1 + (rscale + DEC_DIGITS - 1) / DEC_DIGITS;
9945 : /* ... but always at least 1 */
9946 221954 : res_ndigits = Max(res_ndigits, 1);
9947 : /* If rounding needed, figure one more digit to ensure correct result */
9948 221954 : if (round)
9949 166626 : res_ndigits++;
9950 :
9951 221954 : res_buf = digitbuf_alloc(res_ndigits + 1);
9952 221954 : res_buf[0] = 0; /* spare digit for later rounding */
9953 221954 : res_digits = res_buf + 1;
9954 :
9955 : /*
9956 : * Now compute the quotient digits. This is the short division algorithm
9957 : * described in Knuth volume 2, section 4.3.1 exercise 16, except that we
9958 : * allow the divisor to exceed the internal base.
9959 : *
9960 : * In this algorithm, the carry from one digit to the next is at most
9961 : * divisor - 1. Therefore, while processing the next digit, carry may
9962 : * become as large as divisor * NBASE - 1, and so it requires a 64-bit
9963 : * integer if this exceeds UINT_MAX.
9964 : */
9965 221954 : divisor = abs(ival);
9966 :
9967 221954 : if (divisor <= UINT_MAX / NBASE)
9968 : {
9969 : /* carry cannot overflow 32 bits */
9970 218616 : uint32 carry = 0;
9971 :
9972 2124396 : for (i = 0; i < res_ndigits; i++)
9973 : {
9974 1905780 : carry = carry * NBASE + (i < var_ndigits ? var_digits[i] : 0);
9975 1905780 : res_digits[i] = (NumericDigit) (carry / divisor);
9976 1905780 : carry = carry % divisor;
9977 : }
9978 : }
9979 : else
9980 : {
9981 : /* carry may exceed 32 bits */
9982 3338 : uint64 carry = 0;
9983 :
9984 10680 : for (i = 0; i < res_ndigits; i++)
9985 : {
9986 7342 : carry = carry * NBASE + (i < var_ndigits ? var_digits[i] : 0);
9987 7342 : res_digits[i] = (NumericDigit) (carry / divisor);
9988 7342 : carry = carry % divisor;
9989 : }
9990 : }
9991 :
9992 : /* Store the quotient in result */
9993 221954 : digitbuf_free(result->buf);
9994 221954 : result->ndigits = res_ndigits;
9995 221954 : result->buf = res_buf;
9996 221954 : result->digits = res_digits;
9997 221954 : result->weight = res_weight;
9998 221954 : result->sign = res_sign;
9999 :
10000 : /* Round or truncate to target rscale (and set result->dscale) */
10001 221954 : if (round)
10002 166626 : round_var(result, rscale);
10003 : else
10004 55328 : trunc_var(result, rscale);
10005 :
10006 : /* Strip leading/trailing zeroes */
10007 221954 : strip_var(result);
10008 : }
10009 :
10010 :
10011 : #ifdef HAVE_INT128
10012 : /*
10013 : * div_var_int64() -
10014 : *
10015 : * Divide a numeric variable by a 64-bit integer with the specified weight.
10016 : * The quotient var / (ival * NBASE^ival_weight) is stored in result.
10017 : *
10018 : * This duplicates the logic in div_var_int(), so any changes made there
10019 : * should be made here too.
10020 : */
10021 : static void
10022 540 : div_var_int64(const NumericVar *var, int64 ival, int ival_weight,
10023 : NumericVar *result, int rscale, bool round)
10024 : {
10025 540 : NumericDigit *var_digits = var->digits;
10026 540 : int var_ndigits = var->ndigits;
10027 : int res_sign;
10028 : int res_weight;
10029 : int res_ndigits;
10030 : NumericDigit *res_buf;
10031 : NumericDigit *res_digits;
10032 : uint64 divisor;
10033 : int i;
10034 :
10035 : /* Guard against division by zero */
10036 540 : if (ival == 0)
10037 0 : ereport(ERROR,
10038 : errcode(ERRCODE_DIVISION_BY_ZERO),
10039 : errmsg("division by zero"));
10040 :
10041 : /* Result zero check */
10042 540 : if (var_ndigits == 0)
10043 : {
10044 96 : zero_var(result);
10045 96 : result->dscale = rscale;
10046 96 : return;
10047 : }
10048 :
10049 : /*
10050 : * Determine the result sign, weight and number of digits to calculate.
10051 : * The weight figured here is correct if the emitted quotient has no
10052 : * leading zero digits; otherwise strip_var() will fix things up.
10053 : */
10054 444 : if (var->sign == NUMERIC_POS)
10055 270 : res_sign = ival > 0 ? NUMERIC_POS : NUMERIC_NEG;
10056 : else
10057 174 : res_sign = ival > 0 ? NUMERIC_NEG : NUMERIC_POS;
10058 444 : res_weight = var->weight - ival_weight;
10059 : /* The number of accurate result digits we need to produce: */
10060 444 : res_ndigits = res_weight + 1 + (rscale + DEC_DIGITS - 1) / DEC_DIGITS;
10061 : /* ... but always at least 1 */
10062 444 : res_ndigits = Max(res_ndigits, 1);
10063 : /* If rounding needed, figure one more digit to ensure correct result */
10064 444 : if (round)
10065 438 : res_ndigits++;
10066 :
10067 444 : res_buf = digitbuf_alloc(res_ndigits + 1);
10068 444 : res_buf[0] = 0; /* spare digit for later rounding */
10069 444 : res_digits = res_buf + 1;
10070 :
10071 : /*
10072 : * Now compute the quotient digits. This is the short division algorithm
10073 : * described in Knuth volume 2, section 4.3.1 exercise 16, except that we
10074 : * allow the divisor to exceed the internal base.
10075 : *
10076 : * In this algorithm, the carry from one digit to the next is at most
10077 : * divisor - 1. Therefore, while processing the next digit, carry may
10078 : * become as large as divisor * NBASE - 1, and so it requires a 128-bit
10079 : * integer if this exceeds PG_UINT64_MAX.
10080 : */
10081 444 : divisor = i64abs(ival);
10082 :
10083 444 : if (divisor <= PG_UINT64_MAX / NBASE)
10084 : {
10085 : /* carry cannot overflow 64 bits */
10086 348 : uint64 carry = 0;
10087 :
10088 3542 : for (i = 0; i < res_ndigits; i++)
10089 : {
10090 3194 : carry = carry * NBASE + (i < var_ndigits ? var_digits[i] : 0);
10091 3194 : res_digits[i] = (NumericDigit) (carry / divisor);
10092 3194 : carry = carry % divisor;
10093 : }
10094 : }
10095 : else
10096 : {
10097 : /* carry may exceed 64 bits */
10098 96 : uint128 carry = 0;
10099 :
10100 1032 : for (i = 0; i < res_ndigits; i++)
10101 : {
10102 936 : carry = carry * NBASE + (i < var_ndigits ? var_digits[i] : 0);
10103 936 : res_digits[i] = (NumericDigit) (carry / divisor);
10104 936 : carry = carry % divisor;
10105 : }
10106 : }
10107 :
10108 : /* Store the quotient in result */
10109 444 : digitbuf_free(result->buf);
10110 444 : result->ndigits = res_ndigits;
10111 444 : result->buf = res_buf;
10112 444 : result->digits = res_digits;
10113 444 : result->weight = res_weight;
10114 444 : result->sign = res_sign;
10115 :
10116 : /* Round or truncate to target rscale (and set result->dscale) */
10117 444 : if (round)
10118 438 : round_var(result, rscale);
10119 : else
10120 6 : trunc_var(result, rscale);
10121 :
10122 : /* Strip leading/trailing zeroes */
10123 444 : strip_var(result);
10124 : }
10125 : #endif
10126 :
10127 :
10128 : /*
10129 : * Default scale selection for division
10130 : *
10131 : * Returns the appropriate result scale for the division result.
10132 : */
10133 : static int
10134 152412 : select_div_scale(const NumericVar *var1, const NumericVar *var2)
10135 : {
10136 : int weight1,
10137 : weight2,
10138 : qweight,
10139 : i;
10140 : NumericDigit firstdigit1,
10141 : firstdigit2;
10142 : int rscale;
10143 :
10144 : /*
10145 : * The result scale of a division isn't specified in any SQL standard. For
10146 : * PostgreSQL we select a result scale that will give at least
10147 : * NUMERIC_MIN_SIG_DIGITS significant digits, so that numeric gives a
10148 : * result no less accurate than float8; but use a scale not less than
10149 : * either input's display scale.
10150 : */
10151 :
10152 : /* Get the actual (normalized) weight and first digit of each input */
10153 :
10154 152412 : weight1 = 0; /* values to use if var1 is zero */
10155 152412 : firstdigit1 = 0;
10156 152412 : for (i = 0; i < var1->ndigits; i++)
10157 : {
10158 150712 : firstdigit1 = var1->digits[i];
10159 150712 : if (firstdigit1 != 0)
10160 : {
10161 150712 : weight1 = var1->weight - i;
10162 150712 : break;
10163 : }
10164 : }
10165 :
10166 152412 : weight2 = 0; /* values to use if var2 is zero */
10167 152412 : firstdigit2 = 0;
10168 152412 : for (i = 0; i < var2->ndigits; i++)
10169 : {
10170 152362 : firstdigit2 = var2->digits[i];
10171 152362 : if (firstdigit2 != 0)
10172 : {
10173 152362 : weight2 = var2->weight - i;
10174 152362 : break;
10175 : }
10176 : }
10177 :
10178 : /*
10179 : * Estimate weight of quotient. If the two first digits are equal, we
10180 : * can't be sure, but assume that var1 is less than var2.
10181 : */
10182 152412 : qweight = weight1 - weight2;
10183 152412 : if (firstdigit1 <= firstdigit2)
10184 135142 : qweight--;
10185 :
10186 : /* Select result scale */
10187 152412 : rscale = NUMERIC_MIN_SIG_DIGITS - qweight * DEC_DIGITS;
10188 152412 : rscale = Max(rscale, var1->dscale);
10189 152412 : rscale = Max(rscale, var2->dscale);
10190 152412 : rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
10191 152412 : rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
10192 :
10193 152412 : return rscale;
10194 : }
10195 :
10196 :
10197 : /*
10198 : * mod_var() -
10199 : *
10200 : * Calculate the modulo of two numerics at variable level
10201 : */
10202 : static void
10203 53804 : mod_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
10204 : {
10205 : NumericVar tmp;
10206 :
10207 53804 : init_var(&tmp);
10208 :
10209 : /* ---------
10210 : * We do this using the equation
10211 : * mod(x,y) = x - trunc(x/y)*y
10212 : * div_var can be persuaded to give us trunc(x/y) directly.
10213 : * ----------
10214 : */
10215 53804 : div_var(var1, var2, &tmp, 0, false, true);
10216 :
10217 53792 : mul_var(var2, &tmp, &tmp, var2->dscale);
10218 :
10219 53792 : sub_var(var1, &tmp, result);
10220 :
10221 53792 : free_var(&tmp);
10222 53792 : }
10223 :
10224 :
10225 : /*
10226 : * div_mod_var() -
10227 : *
10228 : * Calculate the truncated integer quotient and numeric remainder of two
10229 : * numeric variables. The remainder is precise to var2's dscale.
10230 : */
10231 : static void
10232 4518 : div_mod_var(const NumericVar *var1, const NumericVar *var2,
10233 : NumericVar *quot, NumericVar *rem)
10234 : {
10235 : NumericVar q;
10236 : NumericVar r;
10237 :
10238 4518 : init_var(&q);
10239 4518 : init_var(&r);
10240 :
10241 : /*
10242 : * Use div_var() with exact = false to get an initial estimate for the
10243 : * integer quotient (truncated towards zero). This might be slightly
10244 : * inaccurate, but we correct it below.
10245 : */
10246 4518 : div_var(var1, var2, &q, 0, false, false);
10247 :
10248 : /* Compute initial estimate of remainder using the quotient estimate. */
10249 4518 : mul_var(var2, &q, &r, var2->dscale);
10250 4518 : sub_var(var1, &r, &r);
10251 :
10252 : /*
10253 : * Adjust the results if necessary --- the remainder should have the same
10254 : * sign as var1, and its absolute value should be less than the absolute
10255 : * value of var2.
10256 : */
10257 4518 : while (r.ndigits != 0 && r.sign != var1->sign)
10258 : {
10259 : /* The absolute value of the quotient is too large */
10260 0 : if (var1->sign == var2->sign)
10261 : {
10262 0 : sub_var(&q, &const_one, &q);
10263 0 : add_var(&r, var2, &r);
10264 : }
10265 : else
10266 : {
10267 0 : add_var(&q, &const_one, &q);
10268 0 : sub_var(&r, var2, &r);
10269 : }
10270 : }
10271 :
10272 4518 : while (cmp_abs(&r, var2) >= 0)
10273 : {
10274 : /* The absolute value of the quotient is too small */
10275 0 : if (var1->sign == var2->sign)
10276 : {
10277 0 : add_var(&q, &const_one, &q);
10278 0 : sub_var(&r, var2, &r);
10279 : }
10280 : else
10281 : {
10282 0 : sub_var(&q, &const_one, &q);
10283 0 : add_var(&r, var2, &r);
10284 : }
10285 : }
10286 :
10287 4518 : set_var_from_var(&q, quot);
10288 4518 : set_var_from_var(&r, rem);
10289 :
10290 4518 : free_var(&q);
10291 4518 : free_var(&r);
10292 4518 : }
10293 :
10294 :
10295 : /*
10296 : * ceil_var() -
10297 : *
10298 : * Return the smallest integer greater than or equal to the argument
10299 : * on variable level
10300 : */
10301 : static void
10302 204 : ceil_var(const NumericVar *var, NumericVar *result)
10303 : {
10304 : NumericVar tmp;
10305 :
10306 204 : init_var(&tmp);
10307 204 : set_var_from_var(var, &tmp);
10308 :
10309 204 : trunc_var(&tmp, 0);
10310 :
10311 204 : if (var->sign == NUMERIC_POS && cmp_var(var, &tmp) != 0)
10312 60 : add_var(&tmp, &const_one, &tmp);
10313 :
10314 204 : set_var_from_var(&tmp, result);
10315 204 : free_var(&tmp);
10316 204 : }
10317 :
10318 :
10319 : /*
10320 : * floor_var() -
10321 : *
10322 : * Return the largest integer equal to or less than the argument
10323 : * on variable level
10324 : */
10325 : static void
10326 108 : floor_var(const NumericVar *var, NumericVar *result)
10327 : {
10328 : NumericVar tmp;
10329 :
10330 108 : init_var(&tmp);
10331 108 : set_var_from_var(var, &tmp);
10332 :
10333 108 : trunc_var(&tmp, 0);
10334 :
10335 108 : if (var->sign == NUMERIC_NEG && cmp_var(var, &tmp) != 0)
10336 30 : sub_var(&tmp, &const_one, &tmp);
10337 :
10338 108 : set_var_from_var(&tmp, result);
10339 108 : free_var(&tmp);
10340 108 : }
10341 :
10342 :
10343 : /*
10344 : * gcd_var() -
10345 : *
10346 : * Calculate the greatest common divisor of two numerics at variable level
10347 : */
10348 : static void
10349 222 : gcd_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
10350 : {
10351 : int res_dscale;
10352 : int cmp;
10353 : NumericVar tmp_arg;
10354 : NumericVar mod;
10355 :
10356 222 : res_dscale = Max(var1->dscale, var2->dscale);
10357 :
10358 : /*
10359 : * Arrange for var1 to be the number with the greater absolute value.
10360 : *
10361 : * This would happen automatically in the loop below, but avoids an
10362 : * expensive modulo operation.
10363 : */
10364 222 : cmp = cmp_abs(var1, var2);
10365 222 : if (cmp < 0)
10366 : {
10367 84 : const NumericVar *tmp = var1;
10368 :
10369 84 : var1 = var2;
10370 84 : var2 = tmp;
10371 : }
10372 :
10373 : /*
10374 : * Also avoid the taking the modulo if the inputs have the same absolute
10375 : * value, or if the smaller input is zero.
10376 : */
10377 222 : if (cmp == 0 || var2->ndigits == 0)
10378 : {
10379 72 : set_var_from_var(var1, result);
10380 72 : result->sign = NUMERIC_POS;
10381 72 : result->dscale = res_dscale;
10382 72 : return;
10383 : }
10384 :
10385 150 : init_var(&tmp_arg);
10386 150 : init_var(&mod);
10387 :
10388 : /* Use the Euclidean algorithm to find the GCD */
10389 150 : set_var_from_var(var1, &tmp_arg);
10390 150 : set_var_from_var(var2, result);
10391 :
10392 : for (;;)
10393 : {
10394 : /* this loop can take a while, so allow it to be interrupted */
10395 588 : CHECK_FOR_INTERRUPTS();
10396 :
10397 588 : mod_var(&tmp_arg, result, &mod);
10398 588 : if (mod.ndigits == 0)
10399 150 : break;
10400 438 : set_var_from_var(result, &tmp_arg);
10401 438 : set_var_from_var(&mod, result);
10402 : }
10403 150 : result->sign = NUMERIC_POS;
10404 150 : result->dscale = res_dscale;
10405 :
10406 150 : free_var(&tmp_arg);
10407 150 : free_var(&mod);
10408 : }
10409 :
10410 :
10411 : /*
10412 : * sqrt_var() -
10413 : *
10414 : * Compute the square root of x using the Karatsuba Square Root algorithm.
10415 : * NOTE: we allow rscale < 0 here, implying rounding before the decimal
10416 : * point.
10417 : */
10418 : static void
10419 4194 : sqrt_var(const NumericVar *arg, NumericVar *result, int rscale)
10420 : {
10421 : int stat;
10422 : int res_weight;
10423 : int res_ndigits;
10424 : int src_ndigits;
10425 : int step;
10426 : int ndigits[32];
10427 : int blen;
10428 : int64 arg_int64;
10429 : int src_idx;
10430 : int64 s_int64;
10431 : int64 r_int64;
10432 : NumericVar s_var;
10433 : NumericVar r_var;
10434 : NumericVar a0_var;
10435 : NumericVar a1_var;
10436 : NumericVar q_var;
10437 : NumericVar u_var;
10438 :
10439 4194 : stat = cmp_var(arg, &const_zero);
10440 4194 : if (stat == 0)
10441 : {
10442 18 : zero_var(result);
10443 18 : result->dscale = rscale;
10444 18 : return;
10445 : }
10446 :
10447 : /*
10448 : * SQL2003 defines sqrt() in terms of power, so we need to emit the right
10449 : * SQLSTATE error code if the operand is negative.
10450 : */
10451 4176 : if (stat < 0)
10452 6 : ereport(ERROR,
10453 : (errcode(ERRCODE_INVALID_ARGUMENT_FOR_POWER_FUNCTION),
10454 : errmsg("cannot take square root of a negative number")));
10455 :
10456 4170 : init_var(&s_var);
10457 4170 : init_var(&r_var);
10458 4170 : init_var(&a0_var);
10459 4170 : init_var(&a1_var);
10460 4170 : init_var(&q_var);
10461 4170 : init_var(&u_var);
10462 :
10463 : /*
10464 : * The result weight is half the input weight, rounded towards minus
10465 : * infinity --- res_weight = floor(arg->weight / 2).
10466 : */
10467 4170 : if (arg->weight >= 0)
10468 3858 : res_weight = arg->weight / 2;
10469 : else
10470 312 : res_weight = -((-arg->weight - 1) / 2 + 1);
10471 :
10472 : /*
10473 : * Number of NBASE digits to compute. To ensure correct rounding, compute
10474 : * at least 1 extra decimal digit. We explicitly allow rscale to be
10475 : * negative here, but must always compute at least 1 NBASE digit. Thus
10476 : * res_ndigits = res_weight + 1 + ceil((rscale + 1) / DEC_DIGITS) or 1.
10477 : */
10478 4170 : if (rscale + 1 >= 0)
10479 4170 : res_ndigits = res_weight + 1 + (rscale + DEC_DIGITS) / DEC_DIGITS;
10480 : else
10481 0 : res_ndigits = res_weight + 1 - (-rscale - 1) / DEC_DIGITS;
10482 4170 : res_ndigits = Max(res_ndigits, 1);
10483 :
10484 : /*
10485 : * Number of source NBASE digits logically required to produce a result
10486 : * with this precision --- every digit before the decimal point, plus 2
10487 : * for each result digit after the decimal point (or minus 2 for each
10488 : * result digit we round before the decimal point).
10489 : */
10490 4170 : src_ndigits = arg->weight + 1 + (res_ndigits - res_weight - 1) * 2;
10491 4170 : src_ndigits = Max(src_ndigits, 1);
10492 :
10493 : /* ----------
10494 : * From this point on, we treat the input and the result as integers and
10495 : * compute the integer square root and remainder using the Karatsuba
10496 : * Square Root algorithm, which may be written recursively as follows:
10497 : *
10498 : * SqrtRem(n = a3*b^3 + a2*b^2 + a1*b + a0):
10499 : * [ for some base b, and coefficients a0,a1,a2,a3 chosen so that
10500 : * 0 <= a0,a1,a2 < b and a3 >= b/4 ]
10501 : * Let (s,r) = SqrtRem(a3*b + a2)
10502 : * Let (q,u) = DivRem(r*b + a1, 2*s)
10503 : * Let s = s*b + q
10504 : * Let r = u*b + a0 - q^2
10505 : * If r < 0 Then
10506 : * Let r = r + s
10507 : * Let s = s - 1
10508 : * Let r = r + s
10509 : * Return (s,r)
10510 : *
10511 : * See "Karatsuba Square Root", Paul Zimmermann, INRIA Research Report
10512 : * RR-3805, November 1999. At the time of writing this was available
10513 : * on the net at <https://hal.inria.fr/inria-00072854>.
10514 : *
10515 : * The way to read the assumption "n = a3*b^3 + a2*b^2 + a1*b + a0" is
10516 : * "choose a base b such that n requires at least four base-b digits to
10517 : * express; then those digits are a3,a2,a1,a0, with a3 possibly larger
10518 : * than b". For optimal performance, b should have approximately a
10519 : * quarter the number of digits in the input, so that the outer square
10520 : * root computes roughly twice as many digits as the inner one. For
10521 : * simplicity, we choose b = NBASE^blen, an integer power of NBASE.
10522 : *
10523 : * We implement the algorithm iteratively rather than recursively, to
10524 : * allow the working variables to be reused. With this approach, each
10525 : * digit of the input is read precisely once --- src_idx tracks the number
10526 : * of input digits used so far.
10527 : *
10528 : * The array ndigits[] holds the number of NBASE digits of the input that
10529 : * will have been used at the end of each iteration, which roughly doubles
10530 : * each time. Note that the array elements are stored in reverse order,
10531 : * so if the final iteration requires src_ndigits = 37 input digits, the
10532 : * array will contain [37,19,11,7,5,3], and we would start by computing
10533 : * the square root of the 3 most significant NBASE digits.
10534 : *
10535 : * In each iteration, we choose blen to be the largest integer for which
10536 : * the input number has a3 >= b/4, when written in the form above. In
10537 : * general, this means blen = src_ndigits / 4 (truncated), but if
10538 : * src_ndigits is a multiple of 4, that might lead to the coefficient a3
10539 : * being less than b/4 (if the first input digit is less than NBASE/4), in
10540 : * which case we choose blen = src_ndigits / 4 - 1. The number of digits
10541 : * in the inner square root is then src_ndigits - 2*blen. So, for
10542 : * example, if we have src_ndigits = 26 initially, the array ndigits[]
10543 : * will be either [26,14,8,4] or [26,14,8,6,4], depending on the size of
10544 : * the first input digit.
10545 : *
10546 : * Additionally, we can put an upper bound on the number of steps required
10547 : * as follows --- suppose that the number of source digits is an n-bit
10548 : * number in the range [2^(n-1), 2^n-1], then blen will be in the range
10549 : * [2^(n-3)-1, 2^(n-2)-1] and the number of digits in the inner square
10550 : * root will be in the range [2^(n-2), 2^(n-1)+1]. In the next step, blen
10551 : * will be in the range [2^(n-4)-1, 2^(n-3)] and the number of digits in
10552 : * the next inner square root will be in the range [2^(n-3), 2^(n-2)+1].
10553 : * This pattern repeats, and in the worst case the array ndigits[] will
10554 : * contain [2^n-1, 2^(n-1)+1, 2^(n-2)+1, ... 9, 5, 3], and the computation
10555 : * will require n steps. Therefore, since all digit array sizes are
10556 : * signed 32-bit integers, the number of steps required is guaranteed to
10557 : * be less than 32.
10558 : * ----------
10559 : */
10560 4170 : step = 0;
10561 19962 : while ((ndigits[step] = src_ndigits) > 4)
10562 : {
10563 : /* Choose b so that a3 >= b/4, as described above */
10564 15792 : blen = src_ndigits / 4;
10565 15792 : if (blen * 4 == src_ndigits && arg->digits[0] < NBASE / 4)
10566 324 : blen--;
10567 :
10568 : /* Number of digits in the next step (inner square root) */
10569 15792 : src_ndigits -= 2 * blen;
10570 15792 : step++;
10571 : }
10572 :
10573 : /*
10574 : * First iteration (innermost square root and remainder):
10575 : *
10576 : * Here src_ndigits <= 4, and the input fits in an int64. Its square root
10577 : * has at most 9 decimal digits, so estimate it using double precision
10578 : * arithmetic, which will in fact almost certainly return the correct
10579 : * result with no further correction required.
10580 : */
10581 4170 : arg_int64 = arg->digits[0];
10582 13314 : for (src_idx = 1; src_idx < src_ndigits; src_idx++)
10583 : {
10584 9144 : arg_int64 *= NBASE;
10585 9144 : if (src_idx < arg->ndigits)
10586 7686 : arg_int64 += arg->digits[src_idx];
10587 : }
10588 :
10589 4170 : s_int64 = (int64) sqrt((double) arg_int64);
10590 4170 : r_int64 = arg_int64 - s_int64 * s_int64;
10591 :
10592 : /*
10593 : * Use Newton's method to correct the result, if necessary.
10594 : *
10595 : * This uses integer division with truncation to compute the truncated
10596 : * integer square root by iterating using the formula x -> (x + n/x) / 2.
10597 : * This is known to converge to isqrt(n), unless n+1 is a perfect square.
10598 : * If n+1 is a perfect square, the sequence will oscillate between the two
10599 : * values isqrt(n) and isqrt(n)+1, so we can be assured of convergence by
10600 : * checking the remainder.
10601 : */
10602 4170 : while (r_int64 < 0 || r_int64 > 2 * s_int64)
10603 : {
10604 0 : s_int64 = (s_int64 + arg_int64 / s_int64) / 2;
10605 0 : r_int64 = arg_int64 - s_int64 * s_int64;
10606 : }
10607 :
10608 : /*
10609 : * Iterations with src_ndigits <= 8:
10610 : *
10611 : * The next 1 or 2 iterations compute larger (outer) square roots with
10612 : * src_ndigits <= 8, so the result still fits in an int64 (even though the
10613 : * input no longer does) and we can continue to compute using int64
10614 : * variables to avoid more expensive numeric computations.
10615 : *
10616 : * It is fairly easy to see that there is no risk of the intermediate
10617 : * values below overflowing 64-bit integers. In the worst case, the
10618 : * previous iteration will have computed a 3-digit square root (of a
10619 : * 6-digit input less than NBASE^6 / 4), so at the start of this
10620 : * iteration, s will be less than NBASE^3 / 2 = 10^12 / 2, and r will be
10621 : * less than 10^12. In this case, blen will be 1, so numer will be less
10622 : * than 10^17, and denom will be less than 10^12 (and hence u will also be
10623 : * less than 10^12). Finally, since q^2 = u*b + a0 - r, we can also be
10624 : * sure that q^2 < 10^17. Therefore all these quantities fit comfortably
10625 : * in 64-bit integers.
10626 : */
10627 4170 : step--;
10628 10566 : while (step >= 0 && (src_ndigits = ndigits[step]) <= 8)
10629 : {
10630 : int b;
10631 : int a0;
10632 : int a1;
10633 : int i;
10634 : int64 numer;
10635 : int64 denom;
10636 : int64 q;
10637 : int64 u;
10638 :
10639 6396 : blen = (src_ndigits - src_idx) / 2;
10640 :
10641 : /* Extract a1 and a0, and compute b */
10642 6396 : a0 = 0;
10643 6396 : a1 = 0;
10644 6396 : b = 1;
10645 :
10646 12936 : for (i = 0; i < blen; i++, src_idx++)
10647 : {
10648 6540 : b *= NBASE;
10649 6540 : a1 *= NBASE;
10650 6540 : if (src_idx < arg->ndigits)
10651 4800 : a1 += arg->digits[src_idx];
10652 : }
10653 :
10654 12936 : for (i = 0; i < blen; i++, src_idx++)
10655 : {
10656 6540 : a0 *= NBASE;
10657 6540 : if (src_idx < arg->ndigits)
10658 4644 : a0 += arg->digits[src_idx];
10659 : }
10660 :
10661 : /* Compute (q,u) = DivRem(r*b + a1, 2*s) */
10662 6396 : numer = r_int64 * b + a1;
10663 6396 : denom = 2 * s_int64;
10664 6396 : q = numer / denom;
10665 6396 : u = numer - q * denom;
10666 :
10667 : /* Compute s = s*b + q and r = u*b + a0 - q^2 */
10668 6396 : s_int64 = s_int64 * b + q;
10669 6396 : r_int64 = u * b + a0 - q * q;
10670 :
10671 6396 : if (r_int64 < 0)
10672 : {
10673 : /* s is too large by 1; set r += s, s--, r += s */
10674 210 : r_int64 += s_int64;
10675 210 : s_int64--;
10676 210 : r_int64 += s_int64;
10677 : }
10678 :
10679 : Assert(src_idx == src_ndigits); /* All input digits consumed */
10680 6396 : step--;
10681 : }
10682 :
10683 : /*
10684 : * On platforms with 128-bit integer support, we can further delay the
10685 : * need to use numeric variables.
10686 : */
10687 : #ifdef HAVE_INT128
10688 4170 : if (step >= 0)
10689 : {
10690 : int128 s_int128;
10691 : int128 r_int128;
10692 :
10693 4170 : s_int128 = s_int64;
10694 4170 : r_int128 = r_int64;
10695 :
10696 : /*
10697 : * Iterations with src_ndigits <= 16:
10698 : *
10699 : * The result fits in an int128 (even though the input doesn't) so we
10700 : * use int128 variables to avoid more expensive numeric computations.
10701 : */
10702 9048 : while (step >= 0 && (src_ndigits = ndigits[step]) <= 16)
10703 : {
10704 : int64 b;
10705 : int64 a0;
10706 : int64 a1;
10707 : int64 i;
10708 : int128 numer;
10709 : int128 denom;
10710 : int128 q;
10711 : int128 u;
10712 :
10713 4878 : blen = (src_ndigits - src_idx) / 2;
10714 :
10715 : /* Extract a1 and a0, and compute b */
10716 4878 : a0 = 0;
10717 4878 : a1 = 0;
10718 4878 : b = 1;
10719 :
10720 16080 : for (i = 0; i < blen; i++, src_idx++)
10721 : {
10722 11202 : b *= NBASE;
10723 11202 : a1 *= NBASE;
10724 11202 : if (src_idx < arg->ndigits)
10725 6606 : a1 += arg->digits[src_idx];
10726 : }
10727 :
10728 16080 : for (i = 0; i < blen; i++, src_idx++)
10729 : {
10730 11202 : a0 *= NBASE;
10731 11202 : if (src_idx < arg->ndigits)
10732 4470 : a0 += arg->digits[src_idx];
10733 : }
10734 :
10735 : /* Compute (q,u) = DivRem(r*b + a1, 2*s) */
10736 4878 : numer = r_int128 * b + a1;
10737 4878 : denom = 2 * s_int128;
10738 4878 : q = numer / denom;
10739 4878 : u = numer - q * denom;
10740 :
10741 : /* Compute s = s*b + q and r = u*b + a0 - q^2 */
10742 4878 : s_int128 = s_int128 * b + q;
10743 4878 : r_int128 = u * b + a0 - q * q;
10744 :
10745 4878 : if (r_int128 < 0)
10746 : {
10747 : /* s is too large by 1; set r += s, s--, r += s */
10748 192 : r_int128 += s_int128;
10749 192 : s_int128--;
10750 192 : r_int128 += s_int128;
10751 : }
10752 :
10753 : Assert(src_idx == src_ndigits); /* All input digits consumed */
10754 4878 : step--;
10755 : }
10756 :
10757 : /*
10758 : * All remaining iterations require numeric variables. Convert the
10759 : * integer values to NumericVar and continue. Note that in the final
10760 : * iteration we don't need the remainder, so we can save a few cycles
10761 : * there by not fully computing it.
10762 : */
10763 4170 : int128_to_numericvar(s_int128, &s_var);
10764 4170 : if (step >= 0)
10765 2724 : int128_to_numericvar(r_int128, &r_var);
10766 : }
10767 : else
10768 : {
10769 0 : int64_to_numericvar(s_int64, &s_var);
10770 : /* step < 0, so we certainly don't need r */
10771 : }
10772 : #else /* !HAVE_INT128 */
10773 : int64_to_numericvar(s_int64, &s_var);
10774 : if (step >= 0)
10775 : int64_to_numericvar(r_int64, &r_var);
10776 : #endif /* HAVE_INT128 */
10777 :
10778 : /*
10779 : * The remaining iterations with src_ndigits > 8 (or 16, if have int128)
10780 : * use numeric variables.
10781 : */
10782 8688 : while (step >= 0)
10783 : {
10784 : int tmp_len;
10785 :
10786 4518 : src_ndigits = ndigits[step];
10787 4518 : blen = (src_ndigits - src_idx) / 2;
10788 :
10789 : /* Extract a1 and a0 */
10790 4518 : if (src_idx < arg->ndigits)
10791 : {
10792 1512 : tmp_len = Min(blen, arg->ndigits - src_idx);
10793 1512 : alloc_var(&a1_var, tmp_len);
10794 1512 : memcpy(a1_var.digits, arg->digits + src_idx,
10795 : tmp_len * sizeof(NumericDigit));
10796 1512 : a1_var.weight = blen - 1;
10797 1512 : a1_var.sign = NUMERIC_POS;
10798 1512 : a1_var.dscale = 0;
10799 1512 : strip_var(&a1_var);
10800 : }
10801 : else
10802 : {
10803 3006 : zero_var(&a1_var);
10804 3006 : a1_var.dscale = 0;
10805 : }
10806 4518 : src_idx += blen;
10807 :
10808 4518 : if (src_idx < arg->ndigits)
10809 : {
10810 1512 : tmp_len = Min(blen, arg->ndigits - src_idx);
10811 1512 : alloc_var(&a0_var, tmp_len);
10812 1512 : memcpy(a0_var.digits, arg->digits + src_idx,
10813 : tmp_len * sizeof(NumericDigit));
10814 1512 : a0_var.weight = blen - 1;
10815 1512 : a0_var.sign = NUMERIC_POS;
10816 1512 : a0_var.dscale = 0;
10817 1512 : strip_var(&a0_var);
10818 : }
10819 : else
10820 : {
10821 3006 : zero_var(&a0_var);
10822 3006 : a0_var.dscale = 0;
10823 : }
10824 4518 : src_idx += blen;
10825 :
10826 : /* Compute (q,u) = DivRem(r*b + a1, 2*s) */
10827 4518 : set_var_from_var(&r_var, &q_var);
10828 4518 : q_var.weight += blen;
10829 4518 : add_var(&q_var, &a1_var, &q_var);
10830 4518 : add_var(&s_var, &s_var, &u_var);
10831 4518 : div_mod_var(&q_var, &u_var, &q_var, &u_var);
10832 :
10833 : /* Compute s = s*b + q */
10834 4518 : s_var.weight += blen;
10835 4518 : add_var(&s_var, &q_var, &s_var);
10836 :
10837 : /*
10838 : * Compute r = u*b + a0 - q^2.
10839 : *
10840 : * In the final iteration, we don't actually need r; we just need to
10841 : * know whether it is negative, so that we know whether to adjust s.
10842 : * So instead of the final subtraction we can just compare.
10843 : */
10844 4518 : u_var.weight += blen;
10845 4518 : add_var(&u_var, &a0_var, &u_var);
10846 4518 : mul_var(&q_var, &q_var, &q_var, 0);
10847 :
10848 4518 : if (step > 0)
10849 : {
10850 : /* Need r for later iterations */
10851 1794 : sub_var(&u_var, &q_var, &r_var);
10852 1794 : if (r_var.sign == NUMERIC_NEG)
10853 : {
10854 : /* s is too large by 1; set r += s, s--, r += s */
10855 120 : add_var(&r_var, &s_var, &r_var);
10856 120 : sub_var(&s_var, &const_one, &s_var);
10857 120 : add_var(&r_var, &s_var, &r_var);
10858 : }
10859 : }
10860 : else
10861 : {
10862 : /* Don't need r anymore, except to test if s is too large by 1 */
10863 2724 : if (cmp_var(&u_var, &q_var) < 0)
10864 36 : sub_var(&s_var, &const_one, &s_var);
10865 : }
10866 :
10867 : Assert(src_idx == src_ndigits); /* All input digits consumed */
10868 4518 : step--;
10869 : }
10870 :
10871 : /*
10872 : * Construct the final result, rounding it to the requested precision.
10873 : */
10874 4170 : set_var_from_var(&s_var, result);
10875 4170 : result->weight = res_weight;
10876 4170 : result->sign = NUMERIC_POS;
10877 :
10878 : /* Round to target rscale (and set result->dscale) */
10879 4170 : round_var(result, rscale);
10880 :
10881 : /* Strip leading and trailing zeroes */
10882 4170 : strip_var(result);
10883 :
10884 4170 : free_var(&s_var);
10885 4170 : free_var(&r_var);
10886 4170 : free_var(&a0_var);
10887 4170 : free_var(&a1_var);
10888 4170 : free_var(&q_var);
10889 4170 : free_var(&u_var);
10890 : }
10891 :
10892 :
10893 : /*
10894 : * exp_var() -
10895 : *
10896 : * Raise e to the power of x, computed to rscale fractional digits
10897 : */
10898 : static void
10899 180 : exp_var(const NumericVar *arg, NumericVar *result, int rscale)
10900 : {
10901 : NumericVar x;
10902 : NumericVar elem;
10903 : int ni;
10904 : double val;
10905 : int dweight;
10906 : int ndiv2;
10907 : int sig_digits;
10908 : int local_rscale;
10909 :
10910 180 : init_var(&x);
10911 180 : init_var(&elem);
10912 :
10913 180 : set_var_from_var(arg, &x);
10914 :
10915 : /*
10916 : * Estimate the dweight of the result using floating point arithmetic, so
10917 : * that we can choose an appropriate local rscale for the calculation.
10918 : */
10919 180 : val = numericvar_to_double_no_overflow(&x);
10920 :
10921 : /* Guard against overflow/underflow */
10922 : /* If you change this limit, see also power_var()'s limit */
10923 180 : if (fabs(val) >= NUMERIC_MAX_RESULT_SCALE * 3)
10924 : {
10925 6 : if (val > 0)
10926 0 : ereport(ERROR,
10927 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
10928 : errmsg("value overflows numeric format")));
10929 6 : zero_var(result);
10930 6 : result->dscale = rscale;
10931 6 : return;
10932 : }
10933 :
10934 : /* decimal weight = log10(e^x) = x * log10(e) */
10935 174 : dweight = (int) (val * 0.434294481903252);
10936 :
10937 : /*
10938 : * Reduce x to the range -0.01 <= x <= 0.01 (approximately) by dividing by
10939 : * 2^ndiv2, to improve the convergence rate of the Taylor series.
10940 : *
10941 : * Note that the overflow check above ensures that fabs(x) < 6000, which
10942 : * means that ndiv2 <= 20 here.
10943 : */
10944 174 : if (fabs(val) > 0.01)
10945 : {
10946 144 : ndiv2 = 1;
10947 144 : val /= 2;
10948 :
10949 1818 : while (fabs(val) > 0.01)
10950 : {
10951 1674 : ndiv2++;
10952 1674 : val /= 2;
10953 : }
10954 :
10955 144 : local_rscale = x.dscale + ndiv2;
10956 144 : div_var_int(&x, 1 << ndiv2, 0, &x, local_rscale, true);
10957 : }
10958 : else
10959 30 : ndiv2 = 0;
10960 :
10961 : /*
10962 : * Set the scale for the Taylor series expansion. The final result has
10963 : * (dweight + rscale + 1) significant digits. In addition, we have to
10964 : * raise the Taylor series result to the power 2^ndiv2, which introduces
10965 : * an error of up to around log10(2^ndiv2) digits, so work with this many
10966 : * extra digits of precision (plus a few more for good measure).
10967 : */
10968 174 : sig_digits = 1 + dweight + rscale + (int) (ndiv2 * 0.301029995663981);
10969 174 : sig_digits = Max(sig_digits, 0) + 8;
10970 :
10971 174 : local_rscale = sig_digits - 1;
10972 :
10973 : /*
10974 : * Use the Taylor series
10975 : *
10976 : * exp(x) = 1 + x + x^2/2! + x^3/3! + ...
10977 : *
10978 : * Given the limited range of x, this should converge reasonably quickly.
10979 : * We run the series until the terms fall below the local_rscale limit.
10980 : */
10981 174 : add_var(&const_one, &x, result);
10982 :
10983 174 : mul_var(&x, &x, &elem, local_rscale);
10984 174 : ni = 2;
10985 174 : div_var_int(&elem, ni, 0, &elem, local_rscale, true);
10986 :
10987 4992 : while (elem.ndigits != 0)
10988 : {
10989 4818 : add_var(result, &elem, result);
10990 :
10991 4818 : mul_var(&elem, &x, &elem, local_rscale);
10992 4818 : ni++;
10993 4818 : div_var_int(&elem, ni, 0, &elem, local_rscale, true);
10994 : }
10995 :
10996 : /*
10997 : * Compensate for the argument range reduction. Since the weight of the
10998 : * result doubles with each multiplication, we can reduce the local rscale
10999 : * as we proceed.
11000 : */
11001 1992 : while (ndiv2-- > 0)
11002 : {
11003 1818 : local_rscale = sig_digits - result->weight * 2 * DEC_DIGITS;
11004 1818 : local_rscale = Max(local_rscale, NUMERIC_MIN_DISPLAY_SCALE);
11005 1818 : mul_var(result, result, result, local_rscale);
11006 : }
11007 :
11008 : /* Round to requested rscale */
11009 174 : round_var(result, rscale);
11010 :
11011 174 : free_var(&x);
11012 174 : free_var(&elem);
11013 : }
11014 :
11015 :
11016 : /*
11017 : * Estimate the dweight of the most significant decimal digit of the natural
11018 : * logarithm of a number.
11019 : *
11020 : * Essentially, we're approximating log10(abs(ln(var))). This is used to
11021 : * determine the appropriate rscale when computing natural logarithms.
11022 : *
11023 : * Note: many callers call this before range-checking the input. Therefore,
11024 : * we must be robust against values that are invalid to apply ln() to.
11025 : * We don't wish to throw an error here, so just return zero in such cases.
11026 : */
11027 : static int
11028 738 : estimate_ln_dweight(const NumericVar *var)
11029 : {
11030 : int ln_dweight;
11031 :
11032 : /* Caller should fail on ln(negative), but for the moment return zero */
11033 738 : if (var->sign != NUMERIC_POS)
11034 42 : return 0;
11035 :
11036 1314 : if (cmp_var(var, &const_zero_point_nine) >= 0 &&
11037 618 : cmp_var(var, &const_one_point_one) <= 0)
11038 90 : {
11039 : /*
11040 : * 0.9 <= var <= 1.1
11041 : *
11042 : * ln(var) has a negative weight (possibly very large). To get a
11043 : * reasonably accurate result, estimate it using ln(1+x) ~= x.
11044 : */
11045 : NumericVar x;
11046 :
11047 90 : init_var(&x);
11048 90 : sub_var(var, &const_one, &x);
11049 :
11050 90 : if (x.ndigits > 0)
11051 : {
11052 : /* Use weight of most significant decimal digit of x */
11053 42 : ln_dweight = x.weight * DEC_DIGITS + (int) log10(x.digits[0]);
11054 : }
11055 : else
11056 : {
11057 : /* x = 0. Since ln(1) = 0 exactly, we don't need extra digits */
11058 48 : ln_dweight = 0;
11059 : }
11060 :
11061 90 : free_var(&x);
11062 : }
11063 : else
11064 : {
11065 : /*
11066 : * Estimate the logarithm using the first couple of digits from the
11067 : * input number. This will give an accurate result whenever the input
11068 : * is not too close to 1.
11069 : */
11070 606 : if (var->ndigits > 0)
11071 : {
11072 : int digits;
11073 : int dweight;
11074 : double ln_var;
11075 :
11076 564 : digits = var->digits[0];
11077 564 : dweight = var->weight * DEC_DIGITS;
11078 :
11079 564 : if (var->ndigits > 1)
11080 : {
11081 342 : digits = digits * NBASE + var->digits[1];
11082 342 : dweight -= DEC_DIGITS;
11083 : }
11084 :
11085 : /*----------
11086 : * We have var ~= digits * 10^dweight
11087 : * so ln(var) ~= ln(digits) + dweight * ln(10)
11088 : *----------
11089 : */
11090 564 : ln_var = log((double) digits) + dweight * 2.302585092994046;
11091 564 : ln_dweight = (int) log10(fabs(ln_var));
11092 : }
11093 : else
11094 : {
11095 : /* Caller should fail on ln(0), but for the moment return zero */
11096 42 : ln_dweight = 0;
11097 : }
11098 : }
11099 :
11100 696 : return ln_dweight;
11101 : }
11102 :
11103 :
11104 : /*
11105 : * ln_var() -
11106 : *
11107 : * Compute the natural log of x
11108 : */
11109 : static void
11110 834 : ln_var(const NumericVar *arg, NumericVar *result, int rscale)
11111 : {
11112 : NumericVar x;
11113 : NumericVar xx;
11114 : int ni;
11115 : NumericVar elem;
11116 : NumericVar fact;
11117 : int nsqrt;
11118 : int local_rscale;
11119 : int cmp;
11120 :
11121 834 : cmp = cmp_var(arg, &const_zero);
11122 834 : if (cmp == 0)
11123 42 : ereport(ERROR,
11124 : (errcode(ERRCODE_INVALID_ARGUMENT_FOR_LOG),
11125 : errmsg("cannot take logarithm of zero")));
11126 792 : else if (cmp < 0)
11127 36 : ereport(ERROR,
11128 : (errcode(ERRCODE_INVALID_ARGUMENT_FOR_LOG),
11129 : errmsg("cannot take logarithm of a negative number")));
11130 :
11131 756 : init_var(&x);
11132 756 : init_var(&xx);
11133 756 : init_var(&elem);
11134 756 : init_var(&fact);
11135 :
11136 756 : set_var_from_var(arg, &x);
11137 756 : set_var_from_var(&const_two, &fact);
11138 :
11139 : /*
11140 : * Reduce input into range 0.9 < x < 1.1 with repeated sqrt() operations.
11141 : *
11142 : * The final logarithm will have up to around rscale+6 significant digits.
11143 : * Each sqrt() will roughly halve the weight of x, so adjust the local
11144 : * rscale as we work so that we keep this many significant digits at each
11145 : * step (plus a few more for good measure).
11146 : *
11147 : * Note that we allow local_rscale < 0 during this input reduction
11148 : * process, which implies rounding before the decimal point. sqrt_var()
11149 : * explicitly supports this, and it significantly reduces the work
11150 : * required to reduce very large inputs to the required range. Once the
11151 : * input reduction is complete, x.weight will be 0 and its display scale
11152 : * will be non-negative again.
11153 : */
11154 756 : nsqrt = 0;
11155 1068 : while (cmp_var(&x, &const_zero_point_nine) <= 0)
11156 : {
11157 312 : local_rscale = rscale - x.weight * DEC_DIGITS / 2 + 8;
11158 312 : sqrt_var(&x, &x, local_rscale);
11159 312 : mul_var(&fact, &const_two, &fact, 0);
11160 312 : nsqrt++;
11161 : }
11162 4128 : while (cmp_var(&x, &const_one_point_one) >= 0)
11163 : {
11164 3372 : local_rscale = rscale - x.weight * DEC_DIGITS / 2 + 8;
11165 3372 : sqrt_var(&x, &x, local_rscale);
11166 3372 : mul_var(&fact, &const_two, &fact, 0);
11167 3372 : nsqrt++;
11168 : }
11169 :
11170 : /*
11171 : * We use the Taylor series for 0.5 * ln((1+z)/(1-z)),
11172 : *
11173 : * z + z^3/3 + z^5/5 + ...
11174 : *
11175 : * where z = (x-1)/(x+1) is in the range (approximately) -0.053 .. 0.048
11176 : * due to the above range-reduction of x.
11177 : *
11178 : * The convergence of this is not as fast as one would like, but is
11179 : * tolerable given that z is small.
11180 : *
11181 : * The Taylor series result will be multiplied by 2^(nsqrt+1), which has a
11182 : * decimal weight of (nsqrt+1) * log10(2), so work with this many extra
11183 : * digits of precision (plus a few more for good measure).
11184 : */
11185 756 : local_rscale = rscale + (int) ((nsqrt + 1) * 0.301029995663981) + 8;
11186 :
11187 756 : sub_var(&x, &const_one, result);
11188 756 : add_var(&x, &const_one, &elem);
11189 756 : div_var(result, &elem, result, local_rscale, true, false);
11190 756 : set_var_from_var(result, &xx);
11191 756 : mul_var(result, result, &x, local_rscale);
11192 :
11193 756 : ni = 1;
11194 :
11195 : for (;;)
11196 : {
11197 14022 : ni += 2;
11198 14022 : mul_var(&xx, &x, &xx, local_rscale);
11199 14022 : div_var_int(&xx, ni, 0, &elem, local_rscale, true);
11200 :
11201 14022 : if (elem.ndigits == 0)
11202 756 : break;
11203 :
11204 13266 : add_var(result, &elem, result);
11205 :
11206 13266 : if (elem.weight < (result->weight - local_rscale * 2 / DEC_DIGITS))
11207 0 : break;
11208 : }
11209 :
11210 : /* Compensate for argument range reduction, round to requested rscale */
11211 756 : mul_var(result, &fact, result, rscale);
11212 :
11213 756 : free_var(&x);
11214 756 : free_var(&xx);
11215 756 : free_var(&elem);
11216 756 : free_var(&fact);
11217 756 : }
11218 :
11219 :
11220 : /*
11221 : * log_var() -
11222 : *
11223 : * Compute the logarithm of num in a given base.
11224 : *
11225 : * Note: this routine chooses dscale of the result.
11226 : */
11227 : static void
11228 216 : log_var(const NumericVar *base, const NumericVar *num, NumericVar *result)
11229 : {
11230 : NumericVar ln_base;
11231 : NumericVar ln_num;
11232 : int ln_base_dweight;
11233 : int ln_num_dweight;
11234 : int result_dweight;
11235 : int rscale;
11236 : int ln_base_rscale;
11237 : int ln_num_rscale;
11238 :
11239 216 : init_var(&ln_base);
11240 216 : init_var(&ln_num);
11241 :
11242 : /* Estimated dweights of ln(base), ln(num) and the final result */
11243 216 : ln_base_dweight = estimate_ln_dweight(base);
11244 216 : ln_num_dweight = estimate_ln_dweight(num);
11245 216 : result_dweight = ln_num_dweight - ln_base_dweight;
11246 :
11247 : /*
11248 : * Select the scale of the result so that it will have at least
11249 : * NUMERIC_MIN_SIG_DIGITS significant digits and is not less than either
11250 : * input's display scale.
11251 : */
11252 216 : rscale = NUMERIC_MIN_SIG_DIGITS - result_dweight;
11253 216 : rscale = Max(rscale, base->dscale);
11254 216 : rscale = Max(rscale, num->dscale);
11255 216 : rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
11256 216 : rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
11257 :
11258 : /*
11259 : * Set the scales for ln(base) and ln(num) so that they each have more
11260 : * significant digits than the final result.
11261 : */
11262 216 : ln_base_rscale = rscale + result_dweight - ln_base_dweight + 8;
11263 216 : ln_base_rscale = Max(ln_base_rscale, NUMERIC_MIN_DISPLAY_SCALE);
11264 :
11265 216 : ln_num_rscale = rscale + result_dweight - ln_num_dweight + 8;
11266 216 : ln_num_rscale = Max(ln_num_rscale, NUMERIC_MIN_DISPLAY_SCALE);
11267 :
11268 : /* Form natural logarithms */
11269 216 : ln_var(base, &ln_base, ln_base_rscale);
11270 192 : ln_var(num, &ln_num, ln_num_rscale);
11271 :
11272 : /* Divide and round to the required scale */
11273 162 : div_var(&ln_num, &ln_base, result, rscale, true, false);
11274 :
11275 156 : free_var(&ln_num);
11276 156 : free_var(&ln_base);
11277 156 : }
11278 :
11279 :
11280 : /*
11281 : * power_var() -
11282 : *
11283 : * Raise base to the power of exp
11284 : *
11285 : * Note: this routine chooses dscale of the result.
11286 : */
11287 : static void
11288 1398 : power_var(const NumericVar *base, const NumericVar *exp, NumericVar *result)
11289 : {
11290 : int res_sign;
11291 : NumericVar abs_base;
11292 : NumericVar ln_base;
11293 : NumericVar ln_num;
11294 : int ln_dweight;
11295 : int rscale;
11296 : int sig_digits;
11297 : int local_rscale;
11298 : double val;
11299 :
11300 : /* If exp can be represented as an integer, use power_var_int */
11301 1398 : if (exp->ndigits == 0 || exp->ndigits <= exp->weight + 1)
11302 : {
11303 : /* exact integer, but does it fit in int? */
11304 : int64 expval64;
11305 :
11306 1272 : if (numericvar_to_int64(exp, &expval64))
11307 : {
11308 1266 : if (expval64 >= PG_INT32_MIN && expval64 <= PG_INT32_MAX)
11309 : {
11310 : /* Okay, use power_var_int */
11311 1236 : power_var_int(base, (int) expval64, exp->dscale, result);
11312 1224 : return;
11313 : }
11314 : }
11315 : }
11316 :
11317 : /*
11318 : * This avoids log(0) for cases of 0 raised to a non-integer. 0 ^ 0 is
11319 : * handled by power_var_int().
11320 : */
11321 162 : if (cmp_var(base, &const_zero) == 0)
11322 : {
11323 18 : set_var_from_var(&const_zero, result);
11324 18 : result->dscale = NUMERIC_MIN_SIG_DIGITS; /* no need to round */
11325 18 : return;
11326 : }
11327 :
11328 144 : init_var(&abs_base);
11329 144 : init_var(&ln_base);
11330 144 : init_var(&ln_num);
11331 :
11332 : /*
11333 : * If base is negative, insist that exp be an integer. The result is then
11334 : * positive if exp is even and negative if exp is odd.
11335 : */
11336 144 : if (base->sign == NUMERIC_NEG)
11337 : {
11338 : /*
11339 : * Check that exp is an integer. This error code is defined by the
11340 : * SQL standard, and matches other errors in numeric_power().
11341 : */
11342 36 : if (exp->ndigits > 0 && exp->ndigits > exp->weight + 1)
11343 18 : ereport(ERROR,
11344 : (errcode(ERRCODE_INVALID_ARGUMENT_FOR_POWER_FUNCTION),
11345 : errmsg("a negative number raised to a non-integer power yields a complex result")));
11346 :
11347 : /* Test if exp is odd or even */
11348 18 : if (exp->ndigits > 0 && exp->ndigits == exp->weight + 1 &&
11349 12 : (exp->digits[exp->ndigits - 1] & 1))
11350 6 : res_sign = NUMERIC_NEG;
11351 : else
11352 12 : res_sign = NUMERIC_POS;
11353 :
11354 : /* Then work with abs(base) below */
11355 18 : set_var_from_var(base, &abs_base);
11356 18 : abs_base.sign = NUMERIC_POS;
11357 18 : base = &abs_base;
11358 : }
11359 : else
11360 108 : res_sign = NUMERIC_POS;
11361 :
11362 : /*----------
11363 : * Decide on the scale for the ln() calculation. For this we need an
11364 : * estimate of the weight of the result, which we obtain by doing an
11365 : * initial low-precision calculation of exp * ln(base).
11366 : *
11367 : * We want result = e ^ (exp * ln(base))
11368 : * so result dweight = log10(result) = exp * ln(base) * log10(e)
11369 : *
11370 : * We also perform a crude overflow test here so that we can exit early if
11371 : * the full-precision result is sure to overflow, and to guard against
11372 : * integer overflow when determining the scale for the real calculation.
11373 : * exp_var() supports inputs up to NUMERIC_MAX_RESULT_SCALE * 3, so the
11374 : * result will overflow if exp * ln(base) >= NUMERIC_MAX_RESULT_SCALE * 3.
11375 : * Since the values here are only approximations, we apply a small fuzz
11376 : * factor to this overflow test and let exp_var() determine the exact
11377 : * overflow threshold so that it is consistent for all inputs.
11378 : *----------
11379 : */
11380 126 : ln_dweight = estimate_ln_dweight(base);
11381 :
11382 : /*
11383 : * Set the scale for the low-precision calculation, computing ln(base) to
11384 : * around 8 significant digits. Note that ln_dweight may be as small as
11385 : * -NUMERIC_DSCALE_MAX, so the scale may exceed NUMERIC_MAX_DISPLAY_SCALE
11386 : * here.
11387 : */
11388 126 : local_rscale = 8 - ln_dweight;
11389 126 : local_rscale = Max(local_rscale, NUMERIC_MIN_DISPLAY_SCALE);
11390 :
11391 126 : ln_var(base, &ln_base, local_rscale);
11392 :
11393 126 : mul_var(&ln_base, exp, &ln_num, local_rscale);
11394 :
11395 126 : val = numericvar_to_double_no_overflow(&ln_num);
11396 :
11397 : /* initial overflow/underflow test with fuzz factor */
11398 126 : if (fabs(val) > NUMERIC_MAX_RESULT_SCALE * 3.01)
11399 : {
11400 6 : if (val > 0)
11401 0 : ereport(ERROR,
11402 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
11403 : errmsg("value overflows numeric format")));
11404 6 : zero_var(result);
11405 6 : result->dscale = NUMERIC_MAX_DISPLAY_SCALE;
11406 6 : return;
11407 : }
11408 :
11409 120 : val *= 0.434294481903252; /* approximate decimal result weight */
11410 :
11411 : /* choose the result scale */
11412 120 : rscale = NUMERIC_MIN_SIG_DIGITS - (int) val;
11413 120 : rscale = Max(rscale, base->dscale);
11414 120 : rscale = Max(rscale, exp->dscale);
11415 120 : rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
11416 120 : rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
11417 :
11418 : /* significant digits required in the result */
11419 120 : sig_digits = rscale + (int) val;
11420 120 : sig_digits = Max(sig_digits, 0);
11421 :
11422 : /* set the scale for the real exp * ln(base) calculation */
11423 120 : local_rscale = sig_digits - ln_dweight + 8;
11424 120 : local_rscale = Max(local_rscale, NUMERIC_MIN_DISPLAY_SCALE);
11425 :
11426 : /* and do the real calculation */
11427 :
11428 120 : ln_var(base, &ln_base, local_rscale);
11429 :
11430 120 : mul_var(&ln_base, exp, &ln_num, local_rscale);
11431 :
11432 120 : exp_var(&ln_num, result, rscale);
11433 :
11434 120 : if (res_sign == NUMERIC_NEG && result->ndigits > 0)
11435 6 : result->sign = NUMERIC_NEG;
11436 :
11437 120 : free_var(&ln_num);
11438 120 : free_var(&ln_base);
11439 120 : free_var(&abs_base);
11440 : }
11441 :
11442 : /*
11443 : * power_var_int() -
11444 : *
11445 : * Raise base to the power of exp, where exp is an integer.
11446 : *
11447 : * Note: this routine chooses dscale of the result.
11448 : */
11449 : static void
11450 1236 : power_var_int(const NumericVar *base, int exp, int exp_dscale,
11451 : NumericVar *result)
11452 : {
11453 : double f;
11454 : int p;
11455 : int i;
11456 : int rscale;
11457 : int sig_digits;
11458 : unsigned int mask;
11459 : bool neg;
11460 : NumericVar base_prod;
11461 : int local_rscale;
11462 :
11463 : /*
11464 : * Choose the result scale. For this we need an estimate of the decimal
11465 : * weight of the result, which we obtain by approximating using double
11466 : * precision arithmetic.
11467 : *
11468 : * We also perform crude overflow/underflow tests here so that we can exit
11469 : * early if the result is sure to overflow/underflow, and to guard against
11470 : * integer overflow when choosing the result scale.
11471 : */
11472 1236 : if (base->ndigits != 0)
11473 : {
11474 : /*----------
11475 : * Choose f (double) and p (int) such that base ~= f * 10^p.
11476 : * Then log10(result) = log10(base^exp) ~= exp * (log10(f) + p).
11477 : *----------
11478 : */
11479 1206 : f = base->digits[0];
11480 1206 : p = base->weight * DEC_DIGITS;
11481 :
11482 1290 : for (i = 1; i < base->ndigits && i * DEC_DIGITS < 16; i++)
11483 : {
11484 84 : f = f * NBASE + base->digits[i];
11485 84 : p -= DEC_DIGITS;
11486 : }
11487 :
11488 1206 : f = exp * (log10(f) + p); /* approximate decimal result weight */
11489 : }
11490 : else
11491 30 : f = 0; /* result is 0 or 1 (weight 0), or error */
11492 :
11493 : /* overflow/underflow tests with fuzz factors */
11494 1236 : if (f > (NUMERIC_WEIGHT_MAX + 1) * DEC_DIGITS)
11495 12 : ereport(ERROR,
11496 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
11497 : errmsg("value overflows numeric format")));
11498 1224 : if (f + 1 < -NUMERIC_MAX_DISPLAY_SCALE)
11499 : {
11500 12 : zero_var(result);
11501 12 : result->dscale = NUMERIC_MAX_DISPLAY_SCALE;
11502 216 : return;
11503 : }
11504 :
11505 : /*
11506 : * Choose the result scale in the same way as power_var(), so it has at
11507 : * least NUMERIC_MIN_SIG_DIGITS significant digits and is not less than
11508 : * either input's display scale.
11509 : */
11510 1212 : rscale = NUMERIC_MIN_SIG_DIGITS - (int) f;
11511 1212 : rscale = Max(rscale, base->dscale);
11512 1212 : rscale = Max(rscale, exp_dscale);
11513 1212 : rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
11514 1212 : rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
11515 :
11516 : /* Handle some common special cases, as well as corner cases */
11517 1212 : switch (exp)
11518 : {
11519 72 : case 0:
11520 :
11521 : /*
11522 : * While 0 ^ 0 can be either 1 or indeterminate (error), we treat
11523 : * it as 1 because most programming languages do this. SQL:2003
11524 : * also requires a return value of 1.
11525 : * https://en.wikipedia.org/wiki/Exponentiation#Zero_to_the_zero_power
11526 : */
11527 72 : set_var_from_var(&const_one, result);
11528 72 : result->dscale = rscale; /* no need to round */
11529 72 : return;
11530 48 : case 1:
11531 48 : set_var_from_var(base, result);
11532 48 : round_var(result, rscale);
11533 48 : return;
11534 30 : case -1:
11535 30 : div_var(&const_one, base, result, rscale, true, true);
11536 30 : return;
11537 54 : case 2:
11538 54 : mul_var(base, base, result, rscale);
11539 54 : return;
11540 1008 : default:
11541 1008 : break;
11542 : }
11543 :
11544 : /* Handle the special case where the base is zero */
11545 1008 : if (base->ndigits == 0)
11546 : {
11547 0 : if (exp < 0)
11548 0 : ereport(ERROR,
11549 : (errcode(ERRCODE_DIVISION_BY_ZERO),
11550 : errmsg("division by zero")));
11551 0 : zero_var(result);
11552 0 : result->dscale = rscale;
11553 0 : return;
11554 : }
11555 :
11556 : /*
11557 : * The general case repeatedly multiplies base according to the bit
11558 : * pattern of exp.
11559 : *
11560 : * The local rscale used for each multiplication is varied to keep a fixed
11561 : * number of significant digits, sufficient to give the required result
11562 : * scale.
11563 : */
11564 :
11565 : /*
11566 : * Approximate number of significant digits in the result. Note that the
11567 : * underflow test above, together with the choice of rscale, ensures that
11568 : * this approximation is necessarily > 0.
11569 : */
11570 1008 : sig_digits = 1 + rscale + (int) f;
11571 :
11572 : /*
11573 : * The multiplications to produce the result may introduce an error of up
11574 : * to around log10(abs(exp)) digits, so work with this many extra digits
11575 : * of precision (plus a few more for good measure).
11576 : */
11577 1008 : sig_digits += (int) log(fabs((double) exp)) + 8;
11578 :
11579 : /*
11580 : * Now we can proceed with the multiplications.
11581 : */
11582 1008 : neg = (exp < 0);
11583 1008 : mask = pg_abs_s32(exp);
11584 :
11585 1008 : init_var(&base_prod);
11586 1008 : set_var_from_var(base, &base_prod);
11587 :
11588 1008 : if (mask & 1)
11589 498 : set_var_from_var(base, result);
11590 : else
11591 510 : set_var_from_var(&const_one, result);
11592 :
11593 5076 : while ((mask >>= 1) > 0)
11594 : {
11595 : /*
11596 : * Do the multiplications using rscales large enough to hold the
11597 : * results to the required number of significant digits, but don't
11598 : * waste time by exceeding the scales of the numbers themselves.
11599 : */
11600 4068 : local_rscale = sig_digits - 2 * base_prod.weight * DEC_DIGITS;
11601 4068 : local_rscale = Min(local_rscale, 2 * base_prod.dscale);
11602 4068 : local_rscale = Max(local_rscale, NUMERIC_MIN_DISPLAY_SCALE);
11603 :
11604 4068 : mul_var(&base_prod, &base_prod, &base_prod, local_rscale);
11605 :
11606 4068 : if (mask & 1)
11607 : {
11608 2658 : local_rscale = sig_digits -
11609 2658 : (base_prod.weight + result->weight) * DEC_DIGITS;
11610 2658 : local_rscale = Min(local_rscale,
11611 : base_prod.dscale + result->dscale);
11612 2658 : local_rscale = Max(local_rscale, NUMERIC_MIN_DISPLAY_SCALE);
11613 :
11614 2658 : mul_var(&base_prod, result, result, local_rscale);
11615 : }
11616 :
11617 : /*
11618 : * When abs(base) > 1, the number of digits to the left of the decimal
11619 : * point in base_prod doubles at each iteration, so if exp is large we
11620 : * could easily spend large amounts of time and memory space doing the
11621 : * multiplications. But once the weight exceeds what will fit in
11622 : * int16, the final result is guaranteed to overflow (or underflow, if
11623 : * exp < 0), so we can give up before wasting too many cycles.
11624 : */
11625 4068 : if (base_prod.weight > NUMERIC_WEIGHT_MAX ||
11626 4068 : result->weight > NUMERIC_WEIGHT_MAX)
11627 : {
11628 : /* overflow, unless neg, in which case result should be 0 */
11629 0 : if (!neg)
11630 0 : ereport(ERROR,
11631 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
11632 : errmsg("value overflows numeric format")));
11633 0 : zero_var(result);
11634 0 : neg = false;
11635 0 : break;
11636 : }
11637 : }
11638 :
11639 1008 : free_var(&base_prod);
11640 :
11641 : /* Compensate for input sign, and round to requested rscale */
11642 1008 : if (neg)
11643 486 : div_var(&const_one, result, result, rscale, true, false);
11644 : else
11645 522 : round_var(result, rscale);
11646 : }
11647 :
11648 : /*
11649 : * power_ten_int() -
11650 : *
11651 : * Raise ten to the power of exp, where exp is an integer. Note that unlike
11652 : * power_var_int(), this does no overflow/underflow checking or rounding.
11653 : */
11654 : static void
11655 228 : power_ten_int(int exp, NumericVar *result)
11656 : {
11657 : /* Construct the result directly, starting from 10^0 = 1 */
11658 228 : set_var_from_var(&const_one, result);
11659 :
11660 : /* Scale needed to represent the result exactly */
11661 228 : result->dscale = exp < 0 ? -exp : 0;
11662 :
11663 : /* Base-NBASE weight of result and remaining exponent */
11664 228 : if (exp >= 0)
11665 162 : result->weight = exp / DEC_DIGITS;
11666 : else
11667 66 : result->weight = (exp + 1) / DEC_DIGITS - 1;
11668 :
11669 228 : exp -= result->weight * DEC_DIGITS;
11670 :
11671 : /* Final adjustment of the result's single NBASE digit */
11672 594 : while (exp-- > 0)
11673 366 : result->digits[0] *= 10;
11674 228 : }
11675 :
11676 : /*
11677 : * random_var() - return a random value in the range [rmin, rmax].
11678 : */
11679 : static void
11680 33438 : random_var(pg_prng_state *state, const NumericVar *rmin,
11681 : const NumericVar *rmax, NumericVar *result)
11682 : {
11683 : int rscale;
11684 : NumericVar rlen;
11685 : int res_ndigits;
11686 : int n;
11687 : int pow10;
11688 : int i;
11689 : uint64 rlen64;
11690 : int rlen64_ndigits;
11691 :
11692 33438 : rscale = Max(rmin->dscale, rmax->dscale);
11693 :
11694 : /* Compute rlen = rmax - rmin and check the range bounds */
11695 33438 : init_var(&rlen);
11696 33438 : sub_var(rmax, rmin, &rlen);
11697 :
11698 33438 : if (rlen.sign == NUMERIC_NEG)
11699 6 : ereport(ERROR,
11700 : errcode(ERRCODE_INVALID_PARAMETER_VALUE),
11701 : errmsg("lower bound must be less than or equal to upper bound"));
11702 :
11703 : /* Special case for an empty range */
11704 33432 : if (rlen.ndigits == 0)
11705 : {
11706 12 : set_var_from_var(rmin, result);
11707 12 : result->dscale = rscale;
11708 12 : free_var(&rlen);
11709 12 : return;
11710 : }
11711 :
11712 : /*
11713 : * Otherwise, select a random value in the range [0, rlen = rmax - rmin],
11714 : * and shift it to the required range by adding rmin.
11715 : */
11716 :
11717 : /* Required result digits */
11718 33420 : res_ndigits = rlen.weight + 1 + (rscale + DEC_DIGITS - 1) / DEC_DIGITS;
11719 :
11720 : /*
11721 : * To get the required rscale, the final result digit must be a multiple
11722 : * of pow10 = 10^n, where n = (-rscale) mod DEC_DIGITS.
11723 : */
11724 33420 : n = ((rscale + DEC_DIGITS - 1) / DEC_DIGITS) * DEC_DIGITS - rscale;
11725 33420 : pow10 = 1;
11726 87900 : for (i = 0; i < n; i++)
11727 54480 : pow10 *= 10;
11728 :
11729 : /*
11730 : * To choose a random value uniformly from the range [0, rlen], we choose
11731 : * from the slightly larger range [0, rlen2], where rlen2 is formed from
11732 : * rlen by copying the first 4 NBASE digits, and setting all remaining
11733 : * decimal digits to "9".
11734 : *
11735 : * Without loss of generality, we can ignore the weight of rlen2 and treat
11736 : * it as a pure integer for the purposes of this discussion. The process
11737 : * above gives rlen2 + 1 = rlen64 * 10^N, for some integer N, where rlen64
11738 : * is a 64-bit integer formed from the first 4 NBASE digits copied from
11739 : * rlen. Since this trivially factors into smaller pieces that fit in
11740 : * 64-bit integers, the task of choosing a random value uniformly from the
11741 : * rlen2 + 1 possible values in [0, rlen2] is much simpler.
11742 : *
11743 : * If the random value selected is too large, it is rejected, and we try
11744 : * again until we get a result <= rlen, ensuring that the overall result
11745 : * is uniform (no particular value is any more likely than any other).
11746 : *
11747 : * Since rlen64 holds 4 NBASE digits from rlen, it contains at least
11748 : * DEC_DIGITS * 3 + 1 decimal digits (i.e., at least 13 decimal digits,
11749 : * when DEC_DIGITS is 4). Therefore the probability of needing to reject
11750 : * the value chosen and retry is less than 1e-13.
11751 : */
11752 33420 : rlen64 = (uint64) rlen.digits[0];
11753 33420 : rlen64_ndigits = 1;
11754 76212 : while (rlen64_ndigits < res_ndigits && rlen64_ndigits < 4)
11755 : {
11756 42792 : rlen64 *= NBASE;
11757 42792 : if (rlen64_ndigits < rlen.ndigits)
11758 6612 : rlen64 += rlen.digits[rlen64_ndigits];
11759 42792 : rlen64_ndigits++;
11760 : }
11761 :
11762 : /* Loop until we get a result <= rlen */
11763 : do
11764 : {
11765 : NumericDigit *res_digits;
11766 : uint64 rand;
11767 : int whole_ndigits;
11768 :
11769 33420 : alloc_var(result, res_ndigits);
11770 33420 : result->sign = NUMERIC_POS;
11771 33420 : result->weight = rlen.weight;
11772 33420 : result->dscale = rscale;
11773 33420 : res_digits = result->digits;
11774 :
11775 : /*
11776 : * Set the first rlen64_ndigits using a random value in [0, rlen64].
11777 : *
11778 : * If this is the whole result, and rscale is not a multiple of
11779 : * DEC_DIGITS (pow10 from above is not 1), then we need this to be a
11780 : * multiple of pow10.
11781 : */
11782 33420 : if (rlen64_ndigits == res_ndigits && pow10 != 1)
11783 21132 : rand = pg_prng_uint64_range(state, 0, rlen64 / pow10) * pow10;
11784 : else
11785 12288 : rand = pg_prng_uint64_range(state, 0, rlen64);
11786 :
11787 109632 : for (i = rlen64_ndigits - 1; i >= 0; i--)
11788 : {
11789 76212 : res_digits[i] = (NumericDigit) (rand % NBASE);
11790 76212 : rand = rand / NBASE;
11791 : }
11792 :
11793 : /*
11794 : * Set the remaining digits to random values in range [0, NBASE),
11795 : * noting that the last digit needs to be a multiple of pow10.
11796 : */
11797 33420 : whole_ndigits = res_ndigits;
11798 33420 : if (pow10 != 1)
11799 33210 : whole_ndigits--;
11800 :
11801 : /* Set whole digits in groups of 4 for best performance */
11802 33420 : i = rlen64_ndigits;
11803 33480 : while (i < whole_ndigits - 3)
11804 : {
11805 60 : rand = pg_prng_uint64_range(state, 0,
11806 : (uint64) NBASE * NBASE * NBASE * NBASE - 1);
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 % NBASE);
11812 60 : rand = rand / NBASE;
11813 60 : res_digits[i++] = (NumericDigit) rand;
11814 : }
11815 :
11816 : /* Remaining whole digits */
11817 33630 : while (i < whole_ndigits)
11818 : {
11819 210 : rand = pg_prng_uint64_range(state, 0, NBASE - 1);
11820 210 : res_digits[i++] = (NumericDigit) rand;
11821 : }
11822 :
11823 : /* Final partial digit (multiple of pow10) */
11824 33420 : if (i < res_ndigits)
11825 : {
11826 12078 : rand = pg_prng_uint64_range(state, 0, NBASE / pow10 - 1) * pow10;
11827 12078 : res_digits[i] = (NumericDigit) rand;
11828 : }
11829 :
11830 : /* Remove leading/trailing zeroes */
11831 33420 : strip_var(result);
11832 :
11833 : /* If result > rlen, try again */
11834 :
11835 33420 : } while (cmp_var(result, &rlen) > 0);
11836 :
11837 : /* Offset the result to the required range */
11838 33420 : add_var(result, rmin, result);
11839 :
11840 33420 : free_var(&rlen);
11841 : }
11842 :
11843 :
11844 : /* ----------------------------------------------------------------------
11845 : *
11846 : * Following are the lowest level functions that operate unsigned
11847 : * on the variable level
11848 : *
11849 : * ----------------------------------------------------------------------
11850 : */
11851 :
11852 :
11853 : /* ----------
11854 : * cmp_abs() -
11855 : *
11856 : * Compare the absolute values of var1 and var2
11857 : * Returns: -1 for ABS(var1) < ABS(var2)
11858 : * 0 for ABS(var1) == ABS(var2)
11859 : * 1 for ABS(var1) > ABS(var2)
11860 : * ----------
11861 : */
11862 : static int
11863 358926 : cmp_abs(const NumericVar *var1, const NumericVar *var2)
11864 : {
11865 717852 : return cmp_abs_common(var1->digits, var1->ndigits, var1->weight,
11866 358926 : var2->digits, var2->ndigits, var2->weight);
11867 : }
11868 :
11869 : /* ----------
11870 : * cmp_abs_common() -
11871 : *
11872 : * Main routine of cmp_abs(). This function can be used by both
11873 : * NumericVar and Numeric.
11874 : * ----------
11875 : */
11876 : static int
11877 6238692 : cmp_abs_common(const NumericDigit *var1digits, int var1ndigits, int var1weight,
11878 : const NumericDigit *var2digits, int var2ndigits, int var2weight)
11879 : {
11880 6238692 : int i1 = 0;
11881 6238692 : int i2 = 0;
11882 :
11883 : /* Check any digits before the first common digit */
11884 :
11885 6238692 : while (var1weight > var2weight && i1 < var1ndigits)
11886 : {
11887 29018 : if (var1digits[i1++] != 0)
11888 29018 : return 1;
11889 0 : var1weight--;
11890 : }
11891 6209674 : while (var2weight > var1weight && i2 < var2ndigits)
11892 : {
11893 32756 : if (var2digits[i2++] != 0)
11894 32756 : return -1;
11895 0 : var2weight--;
11896 : }
11897 :
11898 : /* At this point, either w1 == w2 or we've run out of digits */
11899 :
11900 6176918 : if (var1weight == var2weight)
11901 : {
11902 11499820 : while (i1 < var1ndigits && i2 < var2ndigits)
11903 : {
11904 7757012 : int stat = var1digits[i1++] - var2digits[i2++];
11905 :
11906 7757012 : if (stat)
11907 : {
11908 2427700 : if (stat > 0)
11909 1606040 : return 1;
11910 821660 : return -1;
11911 : }
11912 : }
11913 : }
11914 :
11915 : /*
11916 : * At this point, we've run out of digits on one side or the other; so any
11917 : * remaining nonzero digits imply that side is larger
11918 : */
11919 3749518 : while (i1 < var1ndigits)
11920 : {
11921 8268 : if (var1digits[i1++] != 0)
11922 7968 : return 1;
11923 : }
11924 3741502 : while (i2 < var2ndigits)
11925 : {
11926 1192 : if (var2digits[i2++] != 0)
11927 940 : return -1;
11928 : }
11929 :
11930 3740310 : return 0;
11931 : }
11932 :
11933 :
11934 : /*
11935 : * add_abs() -
11936 : *
11937 : * Add the absolute values of two variables into result.
11938 : * result might point to one of the operands without danger.
11939 : */
11940 : static void
11941 330704 : add_abs(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
11942 : {
11943 : NumericDigit *res_buf;
11944 : NumericDigit *res_digits;
11945 : int res_ndigits;
11946 : int res_weight;
11947 : int res_rscale,
11948 : rscale1,
11949 : rscale2;
11950 : int res_dscale;
11951 : int i,
11952 : i1,
11953 : i2;
11954 330704 : int carry = 0;
11955 :
11956 : /* copy these values into local vars for speed in inner loop */
11957 330704 : int var1ndigits = var1->ndigits;
11958 330704 : int var2ndigits = var2->ndigits;
11959 330704 : NumericDigit *var1digits = var1->digits;
11960 330704 : NumericDigit *var2digits = var2->digits;
11961 :
11962 330704 : res_weight = Max(var1->weight, var2->weight) + 1;
11963 :
11964 330704 : res_dscale = Max(var1->dscale, var2->dscale);
11965 :
11966 : /* Note: here we are figuring rscale in base-NBASE digits */
11967 330704 : rscale1 = var1->ndigits - var1->weight - 1;
11968 330704 : rscale2 = var2->ndigits - var2->weight - 1;
11969 330704 : res_rscale = Max(rscale1, rscale2);
11970 :
11971 330704 : res_ndigits = res_rscale + res_weight + 1;
11972 330704 : if (res_ndigits <= 0)
11973 0 : res_ndigits = 1;
11974 :
11975 330704 : res_buf = digitbuf_alloc(res_ndigits + 1);
11976 330704 : res_buf[0] = 0; /* spare digit for later rounding */
11977 330704 : res_digits = res_buf + 1;
11978 :
11979 330704 : i1 = res_rscale + var1->weight + 1;
11980 330704 : i2 = res_rscale + var2->weight + 1;
11981 3314500 : for (i = res_ndigits - 1; i >= 0; i--)
11982 : {
11983 2983796 : i1--;
11984 2983796 : i2--;
11985 2983796 : if (i1 >= 0 && i1 < var1ndigits)
11986 1316942 : carry += var1digits[i1];
11987 2983796 : if (i2 >= 0 && i2 < var2ndigits)
11988 1037256 : carry += var2digits[i2];
11989 :
11990 2983796 : if (carry >= NBASE)
11991 : {
11992 233830 : res_digits[i] = carry - NBASE;
11993 233830 : carry = 1;
11994 : }
11995 : else
11996 : {
11997 2749966 : res_digits[i] = carry;
11998 2749966 : carry = 0;
11999 : }
12000 : }
12001 :
12002 : Assert(carry == 0); /* else we failed to allow for carry out */
12003 :
12004 330704 : digitbuf_free(result->buf);
12005 330704 : result->ndigits = res_ndigits;
12006 330704 : result->buf = res_buf;
12007 330704 : result->digits = res_digits;
12008 330704 : result->weight = res_weight;
12009 330704 : result->dscale = res_dscale;
12010 :
12011 : /* Remove leading/trailing zeroes */
12012 330704 : strip_var(result);
12013 330704 : }
12014 :
12015 :
12016 : /*
12017 : * sub_abs()
12018 : *
12019 : * Subtract the absolute value of var2 from the absolute value of var1
12020 : * and store in result. result might point to one of the operands
12021 : * without danger.
12022 : *
12023 : * ABS(var1) MUST BE GREATER OR EQUAL ABS(var2) !!!
12024 : */
12025 : static void
12026 323918 : sub_abs(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
12027 : {
12028 : NumericDigit *res_buf;
12029 : NumericDigit *res_digits;
12030 : int res_ndigits;
12031 : int res_weight;
12032 : int res_rscale,
12033 : rscale1,
12034 : rscale2;
12035 : int res_dscale;
12036 : int i,
12037 : i1,
12038 : i2;
12039 323918 : int borrow = 0;
12040 :
12041 : /* copy these values into local vars for speed in inner loop */
12042 323918 : int var1ndigits = var1->ndigits;
12043 323918 : int var2ndigits = var2->ndigits;
12044 323918 : NumericDigit *var1digits = var1->digits;
12045 323918 : NumericDigit *var2digits = var2->digits;
12046 :
12047 323918 : res_weight = var1->weight;
12048 :
12049 323918 : res_dscale = Max(var1->dscale, var2->dscale);
12050 :
12051 : /* Note: here we are figuring rscale in base-NBASE digits */
12052 323918 : rscale1 = var1->ndigits - var1->weight - 1;
12053 323918 : rscale2 = var2->ndigits - var2->weight - 1;
12054 323918 : res_rscale = Max(rscale1, rscale2);
12055 :
12056 323918 : res_ndigits = res_rscale + res_weight + 1;
12057 323918 : if (res_ndigits <= 0)
12058 0 : res_ndigits = 1;
12059 :
12060 323918 : res_buf = digitbuf_alloc(res_ndigits + 1);
12061 323918 : res_buf[0] = 0; /* spare digit for later rounding */
12062 323918 : res_digits = res_buf + 1;
12063 :
12064 323918 : i1 = res_rscale + var1->weight + 1;
12065 323918 : i2 = res_rscale + var2->weight + 1;
12066 4567962 : for (i = res_ndigits - 1; i >= 0; i--)
12067 : {
12068 4244044 : i1--;
12069 4244044 : i2--;
12070 4244044 : if (i1 >= 0 && i1 < var1ndigits)
12071 3824288 : borrow += var1digits[i1];
12072 4244044 : if (i2 >= 0 && i2 < var2ndigits)
12073 3726238 : borrow -= var2digits[i2];
12074 :
12075 4244044 : if (borrow < 0)
12076 : {
12077 466620 : res_digits[i] = borrow + NBASE;
12078 466620 : borrow = -1;
12079 : }
12080 : else
12081 : {
12082 3777424 : res_digits[i] = borrow;
12083 3777424 : borrow = 0;
12084 : }
12085 : }
12086 :
12087 : Assert(borrow == 0); /* else caller gave us var1 < var2 */
12088 :
12089 323918 : digitbuf_free(result->buf);
12090 323918 : result->ndigits = res_ndigits;
12091 323918 : result->buf = res_buf;
12092 323918 : result->digits = res_digits;
12093 323918 : result->weight = res_weight;
12094 323918 : result->dscale = res_dscale;
12095 :
12096 : /* Remove leading/trailing zeroes */
12097 323918 : strip_var(result);
12098 323918 : }
12099 :
12100 : /*
12101 : * round_var
12102 : *
12103 : * Round the value of a variable to no more than rscale decimal digits
12104 : * after the decimal point. NOTE: we allow rscale < 0 here, implying
12105 : * rounding before the decimal point.
12106 : */
12107 : static void
12108 227056 : round_var(NumericVar *var, int rscale)
12109 : {
12110 227056 : NumericDigit *digits = var->digits;
12111 : int di;
12112 : int ndigits;
12113 : int carry;
12114 :
12115 227056 : var->dscale = rscale;
12116 :
12117 : /* decimal digits wanted */
12118 227056 : di = (var->weight + 1) * DEC_DIGITS + rscale;
12119 :
12120 : /*
12121 : * If di = 0, the value loses all digits, but could round up to 1 if its
12122 : * first extra digit is >= 5. If di < 0 the result must be 0.
12123 : */
12124 227056 : if (di < 0)
12125 : {
12126 104 : var->ndigits = 0;
12127 104 : var->weight = 0;
12128 104 : var->sign = NUMERIC_POS;
12129 : }
12130 : else
12131 : {
12132 : /* NBASE digits wanted */
12133 226952 : ndigits = (di + DEC_DIGITS - 1) / DEC_DIGITS;
12134 :
12135 : /* 0, or number of decimal digits to keep in last NBASE digit */
12136 226952 : di %= DEC_DIGITS;
12137 :
12138 226952 : if (ndigits < var->ndigits ||
12139 21374 : (ndigits == var->ndigits && di > 0))
12140 : {
12141 208770 : var->ndigits = ndigits;
12142 :
12143 : #if DEC_DIGITS == 1
12144 : /* di must be zero */
12145 : carry = (digits[ndigits] >= HALF_NBASE) ? 1 : 0;
12146 : #else
12147 208770 : if (di == 0)
12148 167084 : carry = (digits[ndigits] >= HALF_NBASE) ? 1 : 0;
12149 : else
12150 : {
12151 : /* Must round within last NBASE digit */
12152 : int extra,
12153 : pow10;
12154 :
12155 : #if DEC_DIGITS == 4
12156 41686 : pow10 = round_powers[di];
12157 : #elif DEC_DIGITS == 2
12158 : pow10 = 10;
12159 : #else
12160 : #error unsupported NBASE
12161 : #endif
12162 41686 : extra = digits[--ndigits] % pow10;
12163 41686 : digits[ndigits] -= extra;
12164 41686 : carry = 0;
12165 41686 : if (extra >= pow10 / 2)
12166 : {
12167 19486 : pow10 += digits[ndigits];
12168 19486 : if (pow10 >= NBASE)
12169 : {
12170 812 : pow10 -= NBASE;
12171 812 : carry = 1;
12172 : }
12173 19486 : digits[ndigits] = pow10;
12174 : }
12175 : }
12176 : #endif
12177 :
12178 : /* Propagate carry if needed */
12179 243886 : while (carry)
12180 : {
12181 35116 : carry += digits[--ndigits];
12182 35116 : if (carry >= NBASE)
12183 : {
12184 24726 : digits[ndigits] = carry - NBASE;
12185 24726 : carry = 1;
12186 : }
12187 : else
12188 : {
12189 10390 : digits[ndigits] = carry;
12190 10390 : carry = 0;
12191 : }
12192 : }
12193 :
12194 208770 : if (ndigits < 0)
12195 : {
12196 : Assert(ndigits == -1); /* better not have added > 1 digit */
12197 : Assert(var->digits > var->buf);
12198 96 : var->digits--;
12199 96 : var->ndigits++;
12200 96 : var->weight++;
12201 : }
12202 : }
12203 : }
12204 227056 : }
12205 :
12206 : /*
12207 : * trunc_var
12208 : *
12209 : * Truncate (towards zero) the value of a variable at rscale decimal digits
12210 : * after the decimal point. NOTE: we allow rscale < 0 here, implying
12211 : * truncation before the decimal point.
12212 : */
12213 : static void
12214 60904 : trunc_var(NumericVar *var, int rscale)
12215 : {
12216 : int di;
12217 : int ndigits;
12218 :
12219 60904 : var->dscale = rscale;
12220 :
12221 : /* decimal digits wanted */
12222 60904 : di = (var->weight + 1) * DEC_DIGITS + rscale;
12223 :
12224 : /*
12225 : * If di <= 0, the value loses all digits.
12226 : */
12227 60904 : if (di <= 0)
12228 : {
12229 90 : var->ndigits = 0;
12230 90 : var->weight = 0;
12231 90 : var->sign = NUMERIC_POS;
12232 : }
12233 : else
12234 : {
12235 : /* NBASE digits wanted */
12236 60814 : ndigits = (di + DEC_DIGITS - 1) / DEC_DIGITS;
12237 :
12238 60814 : if (ndigits <= var->ndigits)
12239 : {
12240 60544 : var->ndigits = ndigits;
12241 :
12242 : #if DEC_DIGITS == 1
12243 : /* no within-digit stuff to worry about */
12244 : #else
12245 : /* 0, or number of decimal digits to keep in last NBASE digit */
12246 60544 : di %= DEC_DIGITS;
12247 :
12248 60544 : if (di > 0)
12249 : {
12250 : /* Must truncate within last NBASE digit */
12251 106 : NumericDigit *digits = var->digits;
12252 : int extra,
12253 : pow10;
12254 :
12255 : #if DEC_DIGITS == 4
12256 106 : pow10 = round_powers[di];
12257 : #elif DEC_DIGITS == 2
12258 : pow10 = 10;
12259 : #else
12260 : #error unsupported NBASE
12261 : #endif
12262 106 : extra = digits[--ndigits] % pow10;
12263 106 : digits[ndigits] -= extra;
12264 : }
12265 : #endif
12266 : }
12267 : }
12268 60904 : }
12269 :
12270 : /*
12271 : * strip_var
12272 : *
12273 : * Strip any leading and trailing zeroes from a numeric variable
12274 : */
12275 : static void
12276 2077984 : strip_var(NumericVar *var)
12277 : {
12278 2077984 : NumericDigit *digits = var->digits;
12279 2077984 : int ndigits = var->ndigits;
12280 :
12281 : /* Strip leading zeroes */
12282 3942288 : while (ndigits > 0 && *digits == 0)
12283 : {
12284 1864304 : digits++;
12285 1864304 : var->weight--;
12286 1864304 : ndigits--;
12287 : }
12288 :
12289 : /* Strip trailing zeroes */
12290 2750000 : while (ndigits > 0 && digits[ndigits - 1] == 0)
12291 672016 : ndigits--;
12292 :
12293 : /* If it's zero, normalize the sign and weight */
12294 2077984 : if (ndigits == 0)
12295 : {
12296 36236 : var->sign = NUMERIC_POS;
12297 36236 : var->weight = 0;
12298 : }
12299 :
12300 2077984 : var->digits = digits;
12301 2077984 : var->ndigits = ndigits;
12302 2077984 : }
12303 :
12304 :
12305 : /* ----------------------------------------------------------------------
12306 : *
12307 : * Fast sum accumulator functions
12308 : *
12309 : * ----------------------------------------------------------------------
12310 : */
12311 :
12312 : /*
12313 : * Reset the accumulator's value to zero. The buffers to hold the digits
12314 : * are not free'd.
12315 : */
12316 : static void
12317 18 : accum_sum_reset(NumericSumAccum *accum)
12318 : {
12319 : int i;
12320 :
12321 18 : accum->dscale = 0;
12322 66 : for (i = 0; i < accum->ndigits; i++)
12323 : {
12324 48 : accum->pos_digits[i] = 0;
12325 48 : accum->neg_digits[i] = 0;
12326 : }
12327 18 : }
12328 :
12329 : /*
12330 : * Accumulate a new value.
12331 : */
12332 : static void
12333 2355644 : accum_sum_add(NumericSumAccum *accum, const NumericVar *val)
12334 : {
12335 : int32 *accum_digits;
12336 : int i,
12337 : val_i;
12338 : int val_ndigits;
12339 : NumericDigit *val_digits;
12340 :
12341 : /*
12342 : * If we have accumulated too many values since the last carry
12343 : * propagation, do it now, to avoid overflowing. (We could allow more
12344 : * than NBASE - 1, if we reserved two extra digits, rather than one, for
12345 : * carry propagation. But even with NBASE - 1, this needs to be done so
12346 : * seldom, that the performance difference is negligible.)
12347 : */
12348 2355644 : if (accum->num_uncarried == NBASE - 1)
12349 174 : accum_sum_carry(accum);
12350 :
12351 : /*
12352 : * Adjust the weight or scale of the old value, so that it can accommodate
12353 : * the new value.
12354 : */
12355 2355644 : accum_sum_rescale(accum, val);
12356 :
12357 : /* */
12358 2355644 : if (val->sign == NUMERIC_POS)
12359 1754966 : accum_digits = accum->pos_digits;
12360 : else
12361 600678 : accum_digits = accum->neg_digits;
12362 :
12363 : /* copy these values into local vars for speed in loop */
12364 2355644 : val_ndigits = val->ndigits;
12365 2355644 : val_digits = val->digits;
12366 :
12367 2355644 : i = accum->weight - val->weight;
12368 11889762 : for (val_i = 0; val_i < val_ndigits; val_i++)
12369 : {
12370 9534118 : accum_digits[i] += (int32) val_digits[val_i];
12371 9534118 : i++;
12372 : }
12373 :
12374 2355644 : accum->num_uncarried++;
12375 2355644 : }
12376 :
12377 : /*
12378 : * Propagate carries.
12379 : */
12380 : static void
12381 172716 : accum_sum_carry(NumericSumAccum *accum)
12382 : {
12383 : int i;
12384 : int ndigits;
12385 : int32 *dig;
12386 : int32 carry;
12387 172716 : int32 newdig = 0;
12388 :
12389 : /*
12390 : * If no new values have been added since last carry propagation, nothing
12391 : * to do.
12392 : */
12393 172716 : if (accum->num_uncarried == 0)
12394 72 : return;
12395 :
12396 : /*
12397 : * We maintain that the weight of the accumulator is always one larger
12398 : * than needed to hold the current value, before carrying, to make sure
12399 : * there is enough space for the possible extra digit when carry is
12400 : * propagated. We cannot expand the buffer here, unless we require
12401 : * callers of accum_sum_final() to switch to the right memory context.
12402 : */
12403 : Assert(accum->pos_digits[0] == 0 && accum->neg_digits[0] == 0);
12404 :
12405 172644 : ndigits = accum->ndigits;
12406 :
12407 : /* Propagate carry in the positive sum */
12408 172644 : dig = accum->pos_digits;
12409 172644 : carry = 0;
12410 2605390 : for (i = ndigits - 1; i >= 0; i--)
12411 : {
12412 2432746 : newdig = dig[i] + carry;
12413 2432746 : if (newdig >= NBASE)
12414 : {
12415 110790 : carry = newdig / NBASE;
12416 110790 : newdig -= carry * NBASE;
12417 : }
12418 : else
12419 2321956 : carry = 0;
12420 2432746 : dig[i] = newdig;
12421 : }
12422 : /* Did we use up the digit reserved for carry propagation? */
12423 172644 : if (newdig > 0)
12424 2618 : accum->have_carry_space = false;
12425 :
12426 : /* And the same for the negative sum */
12427 172644 : dig = accum->neg_digits;
12428 172644 : carry = 0;
12429 2605390 : for (i = ndigits - 1; i >= 0; i--)
12430 : {
12431 2432746 : newdig = dig[i] + carry;
12432 2432746 : if (newdig >= NBASE)
12433 : {
12434 198 : carry = newdig / NBASE;
12435 198 : newdig -= carry * NBASE;
12436 : }
12437 : else
12438 2432548 : carry = 0;
12439 2432746 : dig[i] = newdig;
12440 : }
12441 172644 : if (newdig > 0)
12442 30 : accum->have_carry_space = false;
12443 :
12444 172644 : accum->num_uncarried = 0;
12445 : }
12446 :
12447 : /*
12448 : * Re-scale accumulator to accommodate new value.
12449 : *
12450 : * If the new value has more digits than the current digit buffers in the
12451 : * accumulator, enlarge the buffers.
12452 : */
12453 : static void
12454 2355644 : accum_sum_rescale(NumericSumAccum *accum, const NumericVar *val)
12455 : {
12456 2355644 : int old_weight = accum->weight;
12457 2355644 : int old_ndigits = accum->ndigits;
12458 : int accum_ndigits;
12459 : int accum_weight;
12460 : int accum_rscale;
12461 : int val_rscale;
12462 :
12463 2355644 : accum_weight = old_weight;
12464 2355644 : accum_ndigits = old_ndigits;
12465 :
12466 : /*
12467 : * Does the new value have a larger weight? If so, enlarge the buffers,
12468 : * and shift the existing value to the new weight, by adding leading
12469 : * zeros.
12470 : *
12471 : * We enforce that the accumulator always has a weight one larger than
12472 : * needed for the inputs, so that we have space for an extra digit at the
12473 : * final carry-propagation phase, if necessary.
12474 : */
12475 2355644 : if (val->weight >= accum_weight)
12476 : {
12477 262178 : accum_weight = val->weight + 1;
12478 262178 : accum_ndigits = accum_ndigits + (accum_weight - old_weight);
12479 : }
12480 :
12481 : /*
12482 : * Even though the new value is small, we might've used up the space
12483 : * reserved for the carry digit in the last call to accum_sum_carry(). If
12484 : * so, enlarge to make room for another one.
12485 : */
12486 2093466 : else if (!accum->have_carry_space)
12487 : {
12488 68 : accum_weight++;
12489 68 : accum_ndigits++;
12490 : }
12491 :
12492 : /* Is the new value wider on the right side? */
12493 2355644 : accum_rscale = accum_ndigits - accum_weight - 1;
12494 2355644 : val_rscale = val->ndigits - val->weight - 1;
12495 2355644 : if (val_rscale > accum_rscale)
12496 172186 : accum_ndigits = accum_ndigits + (val_rscale - accum_rscale);
12497 :
12498 2355644 : if (accum_ndigits != old_ndigits ||
12499 : accum_weight != old_weight)
12500 : {
12501 : int32 *new_pos_digits;
12502 : int32 *new_neg_digits;
12503 : int weightdiff;
12504 :
12505 262510 : weightdiff = accum_weight - old_weight;
12506 :
12507 262510 : new_pos_digits = palloc0(accum_ndigits * sizeof(int32));
12508 262510 : new_neg_digits = palloc0(accum_ndigits * sizeof(int32));
12509 :
12510 262510 : if (accum->pos_digits)
12511 : {
12512 90394 : memcpy(&new_pos_digits[weightdiff], accum->pos_digits,
12513 : old_ndigits * sizeof(int32));
12514 90394 : pfree(accum->pos_digits);
12515 :
12516 90394 : memcpy(&new_neg_digits[weightdiff], accum->neg_digits,
12517 : old_ndigits * sizeof(int32));
12518 90394 : pfree(accum->neg_digits);
12519 : }
12520 :
12521 262510 : accum->pos_digits = new_pos_digits;
12522 262510 : accum->neg_digits = new_neg_digits;
12523 :
12524 262510 : accum->weight = accum_weight;
12525 262510 : accum->ndigits = accum_ndigits;
12526 :
12527 : Assert(accum->pos_digits[0] == 0 && accum->neg_digits[0] == 0);
12528 262510 : accum->have_carry_space = true;
12529 : }
12530 :
12531 2355644 : if (val->dscale > accum->dscale)
12532 300 : accum->dscale = val->dscale;
12533 2355644 : }
12534 :
12535 : /*
12536 : * Return the current value of the accumulator. This perform final carry
12537 : * propagation, and adds together the positive and negative sums.
12538 : *
12539 : * Unlike all the other routines, the caller is not required to switch to
12540 : * the memory context that holds the accumulator.
12541 : */
12542 : static void
12543 172542 : accum_sum_final(NumericSumAccum *accum, NumericVar *result)
12544 : {
12545 : int i;
12546 : NumericVar pos_var;
12547 : NumericVar neg_var;
12548 :
12549 172542 : if (accum->ndigits == 0)
12550 : {
12551 0 : set_var_from_var(&const_zero, result);
12552 0 : return;
12553 : }
12554 :
12555 : /* Perform final carry */
12556 172542 : accum_sum_carry(accum);
12557 :
12558 : /* Create NumericVars representing the positive and negative sums */
12559 172542 : init_var(&pos_var);
12560 172542 : init_var(&neg_var);
12561 :
12562 172542 : pos_var.ndigits = neg_var.ndigits = accum->ndigits;
12563 172542 : pos_var.weight = neg_var.weight = accum->weight;
12564 172542 : pos_var.dscale = neg_var.dscale = accum->dscale;
12565 172542 : pos_var.sign = NUMERIC_POS;
12566 172542 : neg_var.sign = NUMERIC_NEG;
12567 :
12568 172542 : pos_var.buf = pos_var.digits = digitbuf_alloc(accum->ndigits);
12569 172542 : neg_var.buf = neg_var.digits = digitbuf_alloc(accum->ndigits);
12570 :
12571 2604874 : for (i = 0; i < accum->ndigits; i++)
12572 : {
12573 : Assert(accum->pos_digits[i] < NBASE);
12574 2432332 : pos_var.digits[i] = (int16) accum->pos_digits[i];
12575 :
12576 : Assert(accum->neg_digits[i] < NBASE);
12577 2432332 : neg_var.digits[i] = (int16) accum->neg_digits[i];
12578 : }
12579 :
12580 : /* And add them together */
12581 172542 : add_var(&pos_var, &neg_var, result);
12582 :
12583 : /* Remove leading/trailing zeroes */
12584 172542 : strip_var(result);
12585 : }
12586 :
12587 : /*
12588 : * Copy an accumulator's state.
12589 : *
12590 : * 'dst' is assumed to be uninitialized beforehand. No attempt is made at
12591 : * freeing old values.
12592 : */
12593 : static void
12594 42 : accum_sum_copy(NumericSumAccum *dst, NumericSumAccum *src)
12595 : {
12596 42 : dst->pos_digits = palloc(src->ndigits * sizeof(int32));
12597 42 : dst->neg_digits = palloc(src->ndigits * sizeof(int32));
12598 :
12599 42 : memcpy(dst->pos_digits, src->pos_digits, src->ndigits * sizeof(int32));
12600 42 : memcpy(dst->neg_digits, src->neg_digits, src->ndigits * sizeof(int32));
12601 42 : dst->num_uncarried = src->num_uncarried;
12602 42 : dst->ndigits = src->ndigits;
12603 42 : dst->weight = src->weight;
12604 42 : dst->dscale = src->dscale;
12605 42 : }
12606 :
12607 : /*
12608 : * Add the current value of 'accum2' into 'accum'.
12609 : */
12610 : static void
12611 18 : accum_sum_combine(NumericSumAccum *accum, NumericSumAccum *accum2)
12612 : {
12613 : NumericVar tmp_var;
12614 :
12615 18 : init_var(&tmp_var);
12616 :
12617 18 : accum_sum_final(accum2, &tmp_var);
12618 18 : accum_sum_add(accum, &tmp_var);
12619 :
12620 18 : free_var(&tmp_var);
12621 18 : }
|