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