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-2024, 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 "utils/array.h"
38 : #include "utils/builtins.h"
39 : #include "utils/float.h"
40 : #include "utils/guc.h"
41 : #include "utils/numeric.h"
42 : #include "utils/pg_lsn.h"
43 : #include "utils/sortsupport.h"
44 :
45 : /* ----------
46 : * Uncomment the following to enable compilation of dump_numeric()
47 : * and dump_var() and to get a dump of any result produced by make_result().
48 : * ----------
49 : #define NUMERIC_DEBUG
50 : */
51 :
52 :
53 : /* ----------
54 : * Local data types
55 : *
56 : * Numeric values are represented in a base-NBASE floating point format.
57 : * Each "digit" ranges from 0 to NBASE-1. The type NumericDigit is signed
58 : * and wide enough to store a digit. We assume that NBASE*NBASE can fit in
59 : * an int. Although the purely calculational routines could handle any even
60 : * NBASE that's less than sqrt(INT_MAX), in practice we are only interested
61 : * in NBASE a power of ten, so that I/O conversions and decimal rounding
62 : * are easy. Also, it's actually more efficient if NBASE is rather less than
63 : * sqrt(INT_MAX), so that there is "headroom" for mul_var and div_var to
64 : * postpone processing carries.
65 : *
66 : * Values of NBASE other than 10000 are considered of historical interest only
67 : * and are no longer supported in any sense; no mechanism exists for the client
68 : * to discover the base, so every client supporting binary mode expects the
69 : * base-10000 format. If you plan to change this, also note the numeric
70 : * abbreviation code, which assumes NBASE=10000.
71 : * ----------
72 : */
73 :
74 : #if 0
75 : #define NBASE 10
76 : #define HALF_NBASE 5
77 : #define DEC_DIGITS 1 /* decimal digits per NBASE digit */
78 : #define MUL_GUARD_DIGITS 4 /* these are measured in NBASE digits */
79 : #define DIV_GUARD_DIGITS 8
80 :
81 : typedef signed char NumericDigit;
82 : #endif
83 :
84 : #if 0
85 : #define NBASE 100
86 : #define HALF_NBASE 50
87 : #define DEC_DIGITS 2 /* decimal digits per NBASE digit */
88 : #define MUL_GUARD_DIGITS 3 /* these are measured in NBASE digits */
89 : #define DIV_GUARD_DIGITS 6
90 :
91 : typedef signed char NumericDigit;
92 : #endif
93 :
94 : #if 1
95 : #define NBASE 10000
96 : #define HALF_NBASE 5000
97 : #define DEC_DIGITS 4 /* decimal digits per NBASE digit */
98 : #define MUL_GUARD_DIGITS 2 /* these are measured in NBASE digits */
99 : #define DIV_GUARD_DIGITS 4
100 :
101 : typedef int16 NumericDigit;
102 : #endif
103 :
104 : #define NBASE_SQR (NBASE * NBASE)
105 :
106 : /*
107 : * The Numeric type as stored on disk.
108 : *
109 : * If the high bits of the first word of a NumericChoice (n_header, or
110 : * n_short.n_header, or n_long.n_sign_dscale) are NUMERIC_SHORT, then the
111 : * numeric follows the NumericShort format; if they are NUMERIC_POS or
112 : * NUMERIC_NEG, it follows the NumericLong format. If they are NUMERIC_SPECIAL,
113 : * the value is a NaN or Infinity. We currently always store SPECIAL values
114 : * using just two bytes (i.e. only n_header), but previous releases used only
115 : * the NumericLong format, so we might find 4-byte NaNs (though not infinities)
116 : * on disk if a database has been migrated using pg_upgrade. In either case,
117 : * the low-order bits of a special value's header are reserved and currently
118 : * should always be set to zero.
119 : *
120 : * In the NumericShort format, the remaining 14 bits of the header word
121 : * (n_short.n_header) are allocated as follows: 1 for sign (positive or
122 : * negative), 6 for dynamic scale, and 7 for weight. In practice, most
123 : * commonly-encountered values can be represented this way.
124 : *
125 : * In the NumericLong format, the remaining 14 bits of the header word
126 : * (n_long.n_sign_dscale) represent the display scale; and the weight is
127 : * stored separately in n_weight.
128 : *
129 : * NOTE: by convention, values in the packed form have been stripped of
130 : * all leading and trailing zero digits (where a "digit" is of base NBASE).
131 : * In particular, if the value is zero, there will be no digits at all!
132 : * The weight is arbitrary in that case, but we normally set it to zero.
133 : */
134 :
135 : struct NumericShort
136 : {
137 : uint16 n_header; /* Sign + display scale + weight */
138 : NumericDigit n_data[FLEXIBLE_ARRAY_MEMBER]; /* Digits */
139 : };
140 :
141 : struct NumericLong
142 : {
143 : uint16 n_sign_dscale; /* Sign + display scale */
144 : int16 n_weight; /* Weight of 1st digit */
145 : NumericDigit n_data[FLEXIBLE_ARRAY_MEMBER]; /* Digits */
146 : };
147 :
148 : union NumericChoice
149 : {
150 : uint16 n_header; /* Header word */
151 : struct NumericLong n_long; /* Long form (4-byte header) */
152 : struct NumericShort n_short; /* Short form (2-byte header) */
153 : };
154 :
155 : struct NumericData
156 : {
157 : int32 vl_len_; /* varlena header (do not touch directly!) */
158 : union NumericChoice choice; /* choice of format */
159 : };
160 :
161 :
162 : /*
163 : * Interpretation of high bits.
164 : */
165 :
166 : #define NUMERIC_SIGN_MASK 0xC000
167 : #define NUMERIC_POS 0x0000
168 : #define NUMERIC_NEG 0x4000
169 : #define NUMERIC_SHORT 0x8000
170 : #define NUMERIC_SPECIAL 0xC000
171 :
172 : #define NUMERIC_FLAGBITS(n) ((n)->choice.n_header & NUMERIC_SIGN_MASK)
173 : #define NUMERIC_IS_SHORT(n) (NUMERIC_FLAGBITS(n) == NUMERIC_SHORT)
174 : #define NUMERIC_IS_SPECIAL(n) (NUMERIC_FLAGBITS(n) == NUMERIC_SPECIAL)
175 :
176 : #define NUMERIC_HDRSZ (VARHDRSZ + sizeof(uint16) + sizeof(int16))
177 : #define NUMERIC_HDRSZ_SHORT (VARHDRSZ + sizeof(uint16))
178 :
179 : /*
180 : * If the flag bits are NUMERIC_SHORT or NUMERIC_SPECIAL, we want the short
181 : * header; otherwise, we want the long one. Instead of testing against each
182 : * value, we can just look at the high bit, for a slight efficiency gain.
183 : */
184 : #define NUMERIC_HEADER_IS_SHORT(n) (((n)->choice.n_header & 0x8000) != 0)
185 : #define NUMERIC_HEADER_SIZE(n) \
186 : (VARHDRSZ + sizeof(uint16) + \
187 : (NUMERIC_HEADER_IS_SHORT(n) ? 0 : sizeof(int16)))
188 :
189 : /*
190 : * Definitions for special values (NaN, positive infinity, negative infinity).
191 : *
192 : * The two bits after the NUMERIC_SPECIAL bits are 00 for NaN, 01 for positive
193 : * infinity, 11 for negative infinity. (This makes the sign bit match where
194 : * it is in a short-format value, though we make no use of that at present.)
195 : * We could mask off the remaining bits before testing the active bits, but
196 : * currently those bits must be zeroes, so masking would just add cycles.
197 : */
198 : #define NUMERIC_EXT_SIGN_MASK 0xF000 /* high bits plus NaN/Inf flag bits */
199 : #define NUMERIC_NAN 0xC000
200 : #define NUMERIC_PINF 0xD000
201 : #define NUMERIC_NINF 0xF000
202 : #define NUMERIC_INF_SIGN_MASK 0x2000
203 :
204 : #define NUMERIC_EXT_FLAGBITS(n) ((n)->choice.n_header & NUMERIC_EXT_SIGN_MASK)
205 : #define NUMERIC_IS_NAN(n) ((n)->choice.n_header == NUMERIC_NAN)
206 : #define NUMERIC_IS_PINF(n) ((n)->choice.n_header == NUMERIC_PINF)
207 : #define NUMERIC_IS_NINF(n) ((n)->choice.n_header == NUMERIC_NINF)
208 : #define NUMERIC_IS_INF(n) \
209 : (((n)->choice.n_header & ~NUMERIC_INF_SIGN_MASK) == NUMERIC_PINF)
210 :
211 : /*
212 : * Short format definitions.
213 : */
214 :
215 : #define NUMERIC_SHORT_SIGN_MASK 0x2000
216 : #define NUMERIC_SHORT_DSCALE_MASK 0x1F80
217 : #define NUMERIC_SHORT_DSCALE_SHIFT 7
218 : #define NUMERIC_SHORT_DSCALE_MAX \
219 : (NUMERIC_SHORT_DSCALE_MASK >> NUMERIC_SHORT_DSCALE_SHIFT)
220 : #define NUMERIC_SHORT_WEIGHT_SIGN_MASK 0x0040
221 : #define NUMERIC_SHORT_WEIGHT_MASK 0x003F
222 : #define NUMERIC_SHORT_WEIGHT_MAX NUMERIC_SHORT_WEIGHT_MASK
223 : #define NUMERIC_SHORT_WEIGHT_MIN (-(NUMERIC_SHORT_WEIGHT_MASK+1))
224 :
225 : /*
226 : * Extract sign, display scale, weight. These macros extract field values
227 : * suitable for the NumericVar format from the Numeric (on-disk) format.
228 : *
229 : * Note that we don't trouble to ensure that dscale and weight read as zero
230 : * for an infinity; however, that doesn't matter since we never convert
231 : * "special" numerics to NumericVar form. Only the constants defined below
232 : * (const_nan, etc) ever represent a non-finite value as a NumericVar.
233 : */
234 :
235 : #define NUMERIC_DSCALE_MASK 0x3FFF
236 : #define NUMERIC_DSCALE_MAX NUMERIC_DSCALE_MASK
237 :
238 : #define NUMERIC_SIGN(n) \
239 : (NUMERIC_IS_SHORT(n) ? \
240 : (((n)->choice.n_short.n_header & NUMERIC_SHORT_SIGN_MASK) ? \
241 : NUMERIC_NEG : NUMERIC_POS) : \
242 : (NUMERIC_IS_SPECIAL(n) ? \
243 : NUMERIC_EXT_FLAGBITS(n) : NUMERIC_FLAGBITS(n)))
244 : #define NUMERIC_DSCALE(n) (NUMERIC_HEADER_IS_SHORT((n)) ? \
245 : ((n)->choice.n_short.n_header & NUMERIC_SHORT_DSCALE_MASK) \
246 : >> NUMERIC_SHORT_DSCALE_SHIFT \
247 : : ((n)->choice.n_long.n_sign_dscale & NUMERIC_DSCALE_MASK))
248 : #define NUMERIC_WEIGHT(n) (NUMERIC_HEADER_IS_SHORT((n)) ? \
249 : (((n)->choice.n_short.n_header & NUMERIC_SHORT_WEIGHT_SIGN_MASK ? \
250 : ~NUMERIC_SHORT_WEIGHT_MASK : 0) \
251 : | ((n)->choice.n_short.n_header & NUMERIC_SHORT_WEIGHT_MASK)) \
252 : : ((n)->choice.n_long.n_weight))
253 :
254 : /*
255 : * Maximum weight of a stored Numeric value (based on the use of int16 for the
256 : * weight in NumericLong). Note that intermediate values held in NumericVar
257 : * and NumericSumAccum variables may have much larger weights.
258 : */
259 : #define NUMERIC_WEIGHT_MAX PG_INT16_MAX
260 :
261 : /* ----------
262 : * NumericVar is the format we use for arithmetic. The digit-array part
263 : * is the same as the NumericData storage format, but the header is more
264 : * complex.
265 : *
266 : * The value represented by a NumericVar is determined by the sign, weight,
267 : * ndigits, and digits[] array. If it is a "special" value (NaN or Inf)
268 : * then only the sign field matters; ndigits should be zero, and the weight
269 : * and dscale fields are ignored.
270 : *
271 : * Note: the first digit of a NumericVar's value is assumed to be multiplied
272 : * by NBASE ** weight. Another way to say it is that there are weight+1
273 : * digits before the decimal point. It is possible to have weight < 0.
274 : *
275 : * buf points at the physical start of the palloc'd digit buffer for the
276 : * NumericVar. digits points at the first digit in actual use (the one
277 : * with the specified weight). We normally leave an unused digit or two
278 : * (preset to zeroes) between buf and digits, so that there is room to store
279 : * a carry out of the top digit without reallocating space. We just need to
280 : * decrement digits (and increment weight) to make room for the carry digit.
281 : * (There is no such extra space in a numeric value stored in the database,
282 : * only in a NumericVar in memory.)
283 : *
284 : * If buf is NULL then the digit buffer isn't actually palloc'd and should
285 : * not be freed --- see the constants below for an example.
286 : *
287 : * dscale, or display scale, is the nominal precision expressed as number
288 : * of digits after the decimal point (it must always be >= 0 at present).
289 : * dscale may be more than the number of physically stored fractional digits,
290 : * implying that we have suppressed storage of significant trailing zeroes.
291 : * It should never be less than the number of stored digits, since that would
292 : * imply hiding digits that are present. NOTE that dscale is always expressed
293 : * in *decimal* digits, and so it may correspond to a fractional number of
294 : * base-NBASE digits --- divide by DEC_DIGITS to convert to NBASE digits.
295 : *
296 : * rscale, or result scale, is the target precision for a computation.
297 : * Like dscale it is expressed as number of *decimal* digits after the decimal
298 : * point, and is always >= 0 at present.
299 : * Note that rscale is not stored in variables --- it's figured on-the-fly
300 : * from the dscales of the inputs.
301 : *
302 : * While we consistently use "weight" to refer to the base-NBASE weight of
303 : * a numeric value, it is convenient in some scale-related calculations to
304 : * make use of the base-10 weight (ie, the approximate log10 of the value).
305 : * To avoid confusion, such a decimal-units weight is called a "dweight".
306 : *
307 : * NB: All the variable-level functions are written in a style that makes it
308 : * possible to give one and the same variable as argument and destination.
309 : * This is feasible because the digit buffer is separate from the variable.
310 : * ----------
311 : */
312 : typedef struct NumericVar
313 : {
314 : int ndigits; /* # of digits in digits[] - can be 0! */
315 : int weight; /* weight of first digit */
316 : int sign; /* NUMERIC_POS, _NEG, _NAN, _PINF, or _NINF */
317 : int dscale; /* display scale */
318 : NumericDigit *buf; /* start of palloc'd space for digits[] */
319 : NumericDigit *digits; /* base-NBASE digits */
320 : } NumericVar;
321 :
322 :
323 : /* ----------
324 : * Data for generate_series
325 : * ----------
326 : */
327 : typedef struct
328 : {
329 : NumericVar current;
330 : NumericVar stop;
331 : NumericVar step;
332 : } generate_series_numeric_fctx;
333 :
334 :
335 : /* ----------
336 : * Sort support.
337 : * ----------
338 : */
339 : typedef struct
340 : {
341 : void *buf; /* buffer for short varlenas */
342 : int64 input_count; /* number of non-null values seen */
343 : bool estimating; /* true if estimating cardinality */
344 :
345 : hyperLogLogState abbr_card; /* cardinality estimator */
346 : } NumericSortSupport;
347 :
348 :
349 : /* ----------
350 : * Fast sum accumulator.
351 : *
352 : * NumericSumAccum is used to implement SUM(), and other standard aggregates
353 : * that track the sum of input values. It uses 32-bit integers to store the
354 : * digits, instead of the normal 16-bit integers (with NBASE=10000). This
355 : * way, we can safely accumulate up to NBASE - 1 values without propagating
356 : * carry, before risking overflow of any of the digits. 'num_uncarried'
357 : * tracks how many values have been accumulated without propagating carry.
358 : *
359 : * Positive and negative values are accumulated separately, in 'pos_digits'
360 : * and 'neg_digits'. This is simpler and faster than deciding whether to add
361 : * or subtract from the current value, for each new value (see sub_var() for
362 : * the logic we avoid by doing this). Both buffers are of same size, and
363 : * have the same weight and scale. In accum_sum_final(), the positive and
364 : * negative sums are added together to produce the final result.
365 : *
366 : * When a new value has a larger ndigits or weight than the accumulator
367 : * currently does, the accumulator is enlarged to accommodate the new value.
368 : * We normally have one zero digit reserved for carry propagation, and that
369 : * is indicated by the 'have_carry_space' flag. When accum_sum_carry() uses
370 : * up the reserved digit, it clears the 'have_carry_space' flag. The next
371 : * call to accum_sum_add() will enlarge the buffer, to make room for the
372 : * extra digit, and set the flag again.
373 : *
374 : * To initialize a new accumulator, simply reset all fields to zeros.
375 : *
376 : * The accumulator does not handle NaNs.
377 : * ----------
378 : */
379 : typedef struct NumericSumAccum
380 : {
381 : int ndigits;
382 : int weight;
383 : int dscale;
384 : int num_uncarried;
385 : bool have_carry_space;
386 : int32 *pos_digits;
387 : int32 *neg_digits;
388 : } NumericSumAccum;
389 :
390 :
391 : /*
392 : * We define our own macros for packing and unpacking abbreviated-key
393 : * representations for numeric values in order to avoid depending on
394 : * USE_FLOAT8_BYVAL. The type of abbreviation we use is based only on
395 : * the size of a datum, not the argument-passing convention for float8.
396 : *
397 : * The range of abbreviations for finite values is from +PG_INT64/32_MAX
398 : * to -PG_INT64/32_MAX. NaN has the abbreviation PG_INT64/32_MIN, and we
399 : * define the sort ordering to make that work out properly (see further
400 : * comments below). PINF and NINF share the abbreviations of the largest
401 : * and smallest finite abbreviation classes.
402 : */
403 : #define NUMERIC_ABBREV_BITS (SIZEOF_DATUM * BITS_PER_BYTE)
404 : #if SIZEOF_DATUM == 8
405 : #define NumericAbbrevGetDatum(X) ((Datum) (X))
406 : #define DatumGetNumericAbbrev(X) ((int64) (X))
407 : #define NUMERIC_ABBREV_NAN NumericAbbrevGetDatum(PG_INT64_MIN)
408 : #define NUMERIC_ABBREV_PINF NumericAbbrevGetDatum(-PG_INT64_MAX)
409 : #define NUMERIC_ABBREV_NINF NumericAbbrevGetDatum(PG_INT64_MAX)
410 : #else
411 : #define NumericAbbrevGetDatum(X) ((Datum) (X))
412 : #define DatumGetNumericAbbrev(X) ((int32) (X))
413 : #define NUMERIC_ABBREV_NAN NumericAbbrevGetDatum(PG_INT32_MIN)
414 : #define NUMERIC_ABBREV_PINF NumericAbbrevGetDatum(-PG_INT32_MAX)
415 : #define NUMERIC_ABBREV_NINF NumericAbbrevGetDatum(PG_INT32_MAX)
416 : #endif
417 :
418 :
419 : /* ----------
420 : * Some preinitialized constants
421 : * ----------
422 : */
423 : static const NumericDigit const_zero_data[1] = {0};
424 : static const NumericVar const_zero =
425 : {0, 0, NUMERIC_POS, 0, NULL, (NumericDigit *) const_zero_data};
426 :
427 : static const NumericDigit const_one_data[1] = {1};
428 : static const NumericVar const_one =
429 : {1, 0, NUMERIC_POS, 0, NULL, (NumericDigit *) const_one_data};
430 :
431 : static const NumericVar const_minus_one =
432 : {1, 0, NUMERIC_NEG, 0, NULL, (NumericDigit *) const_one_data};
433 :
434 : static const NumericDigit const_two_data[1] = {2};
435 : static const NumericVar const_two =
436 : {1, 0, NUMERIC_POS, 0, NULL, (NumericDigit *) const_two_data};
437 :
438 : #if DEC_DIGITS == 4
439 : static const NumericDigit const_zero_point_nine_data[1] = {9000};
440 : #elif DEC_DIGITS == 2
441 : static const NumericDigit const_zero_point_nine_data[1] = {90};
442 : #elif DEC_DIGITS == 1
443 : static const NumericDigit const_zero_point_nine_data[1] = {9};
444 : #endif
445 : static const NumericVar const_zero_point_nine =
446 : {1, -1, NUMERIC_POS, 1, NULL, (NumericDigit *) const_zero_point_nine_data};
447 :
448 : #if DEC_DIGITS == 4
449 : static const NumericDigit const_one_point_one_data[2] = {1, 1000};
450 : #elif DEC_DIGITS == 2
451 : static const NumericDigit const_one_point_one_data[2] = {1, 10};
452 : #elif DEC_DIGITS == 1
453 : static const NumericDigit const_one_point_one_data[2] = {1, 1};
454 : #endif
455 : static const NumericVar const_one_point_one =
456 : {2, 0, NUMERIC_POS, 1, NULL, (NumericDigit *) const_one_point_one_data};
457 :
458 : static const NumericVar const_nan =
459 : {0, 0, NUMERIC_NAN, 0, NULL, NULL};
460 :
461 : static const NumericVar const_pinf =
462 : {0, 0, NUMERIC_PINF, 0, NULL, NULL};
463 :
464 : static const NumericVar const_ninf =
465 : {0, 0, NUMERIC_NINF, 0, NULL, NULL};
466 :
467 : #if DEC_DIGITS == 4
468 : static const int round_powers[4] = {0, 1000, 100, 10};
469 : #endif
470 :
471 :
472 : /* ----------
473 : * Local functions
474 : * ----------
475 : */
476 :
477 : #ifdef NUMERIC_DEBUG
478 : static void dump_numeric(const char *str, Numeric num);
479 : static void dump_var(const char *str, NumericVar *var);
480 : #else
481 : #define dump_numeric(s,n)
482 : #define dump_var(s,v)
483 : #endif
484 :
485 : #define digitbuf_alloc(ndigits) \
486 : ((NumericDigit *) palloc((ndigits) * sizeof(NumericDigit)))
487 : #define digitbuf_free(buf) \
488 : do { \
489 : if ((buf) != NULL) \
490 : pfree(buf); \
491 : } while (0)
492 :
493 : #define init_var(v) memset(v, 0, sizeof(NumericVar))
494 :
495 : #define NUMERIC_DIGITS(num) (NUMERIC_HEADER_IS_SHORT(num) ? \
496 : (num)->choice.n_short.n_data : (num)->choice.n_long.n_data)
497 : #define NUMERIC_NDIGITS(num) \
498 : ((VARSIZE(num) - NUMERIC_HEADER_SIZE(num)) / sizeof(NumericDigit))
499 : #define NUMERIC_CAN_BE_SHORT(scale,weight) \
500 : ((scale) <= NUMERIC_SHORT_DSCALE_MAX && \
501 : (weight) <= NUMERIC_SHORT_WEIGHT_MAX && \
502 : (weight) >= NUMERIC_SHORT_WEIGHT_MIN)
503 :
504 : static void alloc_var(NumericVar *var, int ndigits);
505 : static void free_var(NumericVar *var);
506 : static void zero_var(NumericVar *var);
507 :
508 : static bool set_var_from_str(const char *str, const char *cp,
509 : NumericVar *dest, const char **endptr,
510 : Node *escontext);
511 : static bool set_var_from_non_decimal_integer_str(const char *str,
512 : const char *cp, int sign,
513 : int base, NumericVar *dest,
514 : const char **endptr,
515 : Node *escontext);
516 : static void set_var_from_num(Numeric num, NumericVar *dest);
517 : static void init_var_from_num(Numeric num, NumericVar *dest);
518 : static void set_var_from_var(const NumericVar *value, NumericVar *dest);
519 : static char *get_str_from_var(const NumericVar *var);
520 : static char *get_str_from_var_sci(const NumericVar *var, int rscale);
521 :
522 : static void numericvar_serialize(StringInfo buf, const NumericVar *var);
523 : static void numericvar_deserialize(StringInfo buf, NumericVar *var);
524 :
525 : static Numeric duplicate_numeric(Numeric num);
526 : static Numeric make_result(const NumericVar *var);
527 : static Numeric make_result_opt_error(const NumericVar *var, bool *have_error);
528 :
529 : static bool apply_typmod(NumericVar *var, int32 typmod, Node *escontext);
530 : static bool apply_typmod_special(Numeric num, int32 typmod, Node *escontext);
531 :
532 : static bool numericvar_to_int32(const NumericVar *var, int32 *result);
533 : static bool numericvar_to_int64(const NumericVar *var, int64 *result);
534 : static void int64_to_numericvar(int64 val, NumericVar *var);
535 : static bool numericvar_to_uint64(const NumericVar *var, uint64 *result);
536 : #ifdef HAVE_INT128
537 : static bool numericvar_to_int128(const NumericVar *var, int128 *result);
538 : static void int128_to_numericvar(int128 val, NumericVar *var);
539 : #endif
540 : static double numericvar_to_double_no_overflow(const NumericVar *var);
541 :
542 : static Datum numeric_abbrev_convert(Datum original_datum, SortSupport ssup);
543 : static bool numeric_abbrev_abort(int memtupcount, SortSupport ssup);
544 : static int numeric_fast_cmp(Datum x, Datum y, SortSupport ssup);
545 : static int numeric_cmp_abbrev(Datum x, Datum y, SortSupport ssup);
546 :
547 : static Datum numeric_abbrev_convert_var(const NumericVar *var,
548 : NumericSortSupport *nss);
549 :
550 : static int cmp_numerics(Numeric num1, Numeric num2);
551 : static int cmp_var(const NumericVar *var1, const NumericVar *var2);
552 : static int cmp_var_common(const NumericDigit *var1digits, int var1ndigits,
553 : int var1weight, int var1sign,
554 : const NumericDigit *var2digits, int var2ndigits,
555 : int var2weight, int var2sign);
556 : static void add_var(const NumericVar *var1, const NumericVar *var2,
557 : NumericVar *result);
558 : static void sub_var(const NumericVar *var1, const NumericVar *var2,
559 : NumericVar *result);
560 : static void mul_var(const NumericVar *var1, const NumericVar *var2,
561 : NumericVar *result,
562 : int rscale);
563 : static void mul_var_short(const NumericVar *var1, const NumericVar *var2,
564 : NumericVar *result);
565 : static void div_var(const NumericVar *var1, const NumericVar *var2,
566 : NumericVar *result, int rscale, bool round, bool exact);
567 : static void div_var_int(const NumericVar *var, int ival, int ival_weight,
568 : NumericVar *result, int rscale, bool round);
569 : #ifdef HAVE_INT128
570 : static void div_var_int64(const NumericVar *var, int64 ival, int ival_weight,
571 : NumericVar *result, int rscale, bool round);
572 : #endif
573 : static int select_div_scale(const NumericVar *var1, const NumericVar *var2);
574 : static void mod_var(const NumericVar *var1, const NumericVar *var2,
575 : NumericVar *result);
576 : static void div_mod_var(const NumericVar *var1, const NumericVar *var2,
577 : NumericVar *quot, NumericVar *rem);
578 : static void ceil_var(const NumericVar *var, NumericVar *result);
579 : static void floor_var(const NumericVar *var, NumericVar *result);
580 :
581 : static void gcd_var(const NumericVar *var1, const NumericVar *var2,
582 : NumericVar *result);
583 : static void sqrt_var(const NumericVar *arg, NumericVar *result, int rscale);
584 : static void exp_var(const NumericVar *arg, NumericVar *result, int rscale);
585 : static int estimate_ln_dweight(const NumericVar *var);
586 : static void ln_var(const NumericVar *arg, NumericVar *result, int rscale);
587 : static void log_var(const NumericVar *base, const NumericVar *num,
588 : NumericVar *result);
589 : static void power_var(const NumericVar *base, const NumericVar *exp,
590 : NumericVar *result);
591 : static void power_var_int(const NumericVar *base, int exp, int exp_dscale,
592 : NumericVar *result);
593 : static void power_ten_int(int exp, NumericVar *result);
594 : static void random_var(pg_prng_state *state, const NumericVar *rmin,
595 : const NumericVar *rmax, NumericVar *result);
596 :
597 : static int cmp_abs(const NumericVar *var1, const NumericVar *var2);
598 : static int cmp_abs_common(const NumericDigit *var1digits, int var1ndigits,
599 : int var1weight,
600 : const NumericDigit *var2digits, int var2ndigits,
601 : int var2weight);
602 : static void add_abs(const NumericVar *var1, const NumericVar *var2,
603 : NumericVar *result);
604 : static void sub_abs(const NumericVar *var1, const NumericVar *var2,
605 : NumericVar *result);
606 : static void round_var(NumericVar *var, int rscale);
607 : static void trunc_var(NumericVar *var, int rscale);
608 : static void strip_var(NumericVar *var);
609 : static void compute_bucket(Numeric operand, Numeric bound1, Numeric bound2,
610 : const NumericVar *count_var,
611 : NumericVar *result_var);
612 :
613 : static void accum_sum_add(NumericSumAccum *accum, const NumericVar *val);
614 : static void accum_sum_rescale(NumericSumAccum *accum, const NumericVar *val);
615 : static void accum_sum_carry(NumericSumAccum *accum);
616 : static void accum_sum_reset(NumericSumAccum *accum);
617 : static void accum_sum_final(NumericSumAccum *accum, NumericVar *result);
618 : static void accum_sum_copy(NumericSumAccum *dst, NumericSumAccum *src);
619 : static void accum_sum_combine(NumericSumAccum *accum, NumericSumAccum *accum2);
620 :
621 :
622 : /* ----------------------------------------------------------------------
623 : *
624 : * Input-, output- and rounding-functions
625 : *
626 : * ----------------------------------------------------------------------
627 : */
628 :
629 :
630 : /*
631 : * numeric_in() -
632 : *
633 : * Input function for numeric data type
634 : */
635 : Datum
636 108188 : numeric_in(PG_FUNCTION_ARGS)
637 : {
638 108188 : char *str = PG_GETARG_CSTRING(0);
639 : #ifdef NOT_USED
640 : Oid typelem = PG_GETARG_OID(1);
641 : #endif
642 108188 : int32 typmod = PG_GETARG_INT32(2);
643 108188 : Node *escontext = fcinfo->context;
644 : Numeric res;
645 : const char *cp;
646 : const char *numstart;
647 : int sign;
648 :
649 : /* Skip leading spaces */
650 108188 : cp = str;
651 108578 : while (*cp)
652 : {
653 108566 : if (!isspace((unsigned char) *cp))
654 108176 : break;
655 390 : cp++;
656 : }
657 :
658 : /*
659 : * Process the number's sign. This duplicates logic in set_var_from_str(),
660 : * but it's worth doing here, since it simplifies the handling of
661 : * infinities and non-decimal integers.
662 : */
663 108188 : numstart = cp;
664 108188 : sign = NUMERIC_POS;
665 :
666 108188 : if (*cp == '+')
667 48 : cp++;
668 108140 : else if (*cp == '-')
669 : {
670 3726 : sign = NUMERIC_NEG;
671 3726 : cp++;
672 : }
673 :
674 : /*
675 : * Check for NaN and infinities. We recognize the same strings allowed by
676 : * float8in().
677 : *
678 : * Since all other legal inputs have a digit or a decimal point after the
679 : * sign, we need only check for NaN/infinity if that's not the case.
680 : */
681 108188 : if (!isdigit((unsigned char) *cp) && *cp != '.')
682 : {
683 : /*
684 : * The number must be NaN or infinity; anything else can only be a
685 : * syntax error. Note that NaN mustn't have a sign.
686 : */
687 1758 : if (pg_strncasecmp(numstart, "NaN", 3) == 0)
688 : {
689 586 : res = make_result(&const_nan);
690 586 : cp = numstart + 3;
691 : }
692 1172 : else if (pg_strncasecmp(cp, "Infinity", 8) == 0)
693 : {
694 480 : res = make_result(sign == NUMERIC_POS ? &const_pinf : &const_ninf);
695 480 : cp += 8;
696 : }
697 692 : else if (pg_strncasecmp(cp, "inf", 3) == 0)
698 : {
699 588 : res = make_result(sign == NUMERIC_POS ? &const_pinf : &const_ninf);
700 588 : cp += 3;
701 : }
702 : else
703 104 : goto invalid_syntax;
704 :
705 : /*
706 : * Check for trailing junk; there should be nothing left but spaces.
707 : *
708 : * We intentionally do this check before applying the typmod because
709 : * we would like to throw any trailing-junk syntax error before any
710 : * semantic error resulting from apply_typmod_special().
711 : */
712 1696 : while (*cp)
713 : {
714 42 : if (!isspace((unsigned char) *cp))
715 0 : goto invalid_syntax;
716 42 : cp++;
717 : }
718 :
719 1654 : if (!apply_typmod_special(res, typmod, escontext))
720 0 : PG_RETURN_NULL();
721 : }
722 : else
723 : {
724 : /*
725 : * We have a normal numeric value, which may be a non-decimal integer
726 : * or a regular decimal number.
727 : */
728 : NumericVar value;
729 : int base;
730 : bool have_error;
731 :
732 106430 : init_var(&value);
733 :
734 : /*
735 : * Determine the number's base by looking for a non-decimal prefix
736 : * indicator ("0x", "0o", or "0b").
737 : */
738 106430 : if (cp[0] == '0')
739 : {
740 27574 : switch (cp[1])
741 : {
742 72 : case 'x':
743 : case 'X':
744 72 : base = 16;
745 72 : break;
746 42 : case 'o':
747 : case 'O':
748 42 : base = 8;
749 42 : break;
750 42 : case 'b':
751 : case 'B':
752 42 : base = 2;
753 42 : break;
754 27418 : default:
755 27418 : base = 10;
756 : }
757 : }
758 : else
759 78856 : base = 10;
760 :
761 : /* Parse the rest of the number and apply the sign */
762 106430 : if (base == 10)
763 : {
764 106274 : if (!set_var_from_str(str, cp, &value, &cp, escontext))
765 42 : PG_RETURN_NULL();
766 106226 : value.sign = sign;
767 : }
768 : else
769 : {
770 156 : if (!set_var_from_non_decimal_integer_str(str, cp + 2, sign, base,
771 : &value, &cp, escontext))
772 0 : PG_RETURN_NULL();
773 : }
774 :
775 : /*
776 : * Should be nothing left but spaces. As above, throw any typmod error
777 : * after finishing syntax check.
778 : */
779 106442 : while (*cp)
780 : {
781 150 : if (!isspace((unsigned char) *cp))
782 72 : goto invalid_syntax;
783 78 : cp++;
784 : }
785 :
786 106292 : if (!apply_typmod(&value, typmod, escontext))
787 24 : PG_RETURN_NULL();
788 :
789 106268 : res = make_result_opt_error(&value, &have_error);
790 :
791 106268 : if (have_error)
792 18 : ereturn(escontext, (Datum) 0,
793 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
794 : errmsg("value overflows numeric format")));
795 :
796 106250 : free_var(&value);
797 : }
798 :
799 107904 : PG_RETURN_NUMERIC(res);
800 :
801 176 : invalid_syntax:
802 176 : ereturn(escontext, (Datum) 0,
803 : (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
804 : errmsg("invalid input syntax for type %s: \"%s\"",
805 : "numeric", str)));
806 : }
807 :
808 :
809 : /*
810 : * numeric_out() -
811 : *
812 : * Output function for numeric data type
813 : */
814 : Datum
815 788974 : numeric_out(PG_FUNCTION_ARGS)
816 : {
817 788974 : Numeric num = PG_GETARG_NUMERIC(0);
818 : NumericVar x;
819 : char *str;
820 :
821 : /*
822 : * Handle NaN and infinities
823 : */
824 788974 : if (NUMERIC_IS_SPECIAL(num))
825 : {
826 3604 : if (NUMERIC_IS_PINF(num))
827 1040 : PG_RETURN_CSTRING(pstrdup("Infinity"));
828 2564 : else if (NUMERIC_IS_NINF(num))
829 658 : PG_RETURN_CSTRING(pstrdup("-Infinity"));
830 : else
831 1906 : PG_RETURN_CSTRING(pstrdup("NaN"));
832 : }
833 :
834 : /*
835 : * Get the number in the variable format.
836 : */
837 785370 : init_var_from_num(num, &x);
838 :
839 785370 : str = get_str_from_var(&x);
840 :
841 785370 : PG_RETURN_CSTRING(str);
842 : }
843 :
844 : /*
845 : * numeric_is_nan() -
846 : *
847 : * Is Numeric value a NaN?
848 : */
849 : bool
850 13614 : numeric_is_nan(Numeric num)
851 : {
852 13614 : return NUMERIC_IS_NAN(num);
853 : }
854 :
855 : /*
856 : * numeric_is_inf() -
857 : *
858 : * Is Numeric value an infinity?
859 : */
860 : bool
861 312 : numeric_is_inf(Numeric num)
862 : {
863 312 : return NUMERIC_IS_INF(num);
864 : }
865 :
866 : /*
867 : * numeric_is_integral() -
868 : *
869 : * Is Numeric value integral?
870 : */
871 : static bool
872 66 : numeric_is_integral(Numeric num)
873 : {
874 : NumericVar arg;
875 :
876 : /* Reject NaN, but infinities are considered integral */
877 66 : if (NUMERIC_IS_SPECIAL(num))
878 : {
879 30 : if (NUMERIC_IS_NAN(num))
880 0 : return false;
881 30 : return true;
882 : }
883 :
884 : /* Integral if there are no digits to the right of the decimal point */
885 36 : init_var_from_num(num, &arg);
886 :
887 36 : return (arg.ndigits == 0 || arg.ndigits <= arg.weight + 1);
888 : }
889 :
890 : /*
891 : * make_numeric_typmod() -
892 : *
893 : * Pack numeric precision and scale values into a typmod. The upper 16 bits
894 : * are used for the precision (though actually not all these bits are needed,
895 : * since the maximum allowed precision is 1000). The lower 16 bits are for
896 : * the scale, but since the scale is constrained to the range [-1000, 1000],
897 : * we use just the lower 11 of those 16 bits, and leave the remaining 5 bits
898 : * unset, for possible future use.
899 : *
900 : * For purely historical reasons VARHDRSZ is then added to the result, thus
901 : * the unused space in the upper 16 bits is not all as freely available as it
902 : * might seem. (We can't let the result overflow to a negative int32, as
903 : * other parts of the system would interpret that as not-a-valid-typmod.)
904 : */
905 : static inline int32
906 1890 : make_numeric_typmod(int precision, int scale)
907 : {
908 1890 : return ((precision << 16) | (scale & 0x7ff)) + VARHDRSZ;
909 : }
910 :
911 : /*
912 : * Because of the offset, valid numeric typmods are at least VARHDRSZ
913 : */
914 : static inline bool
915 131502 : is_valid_numeric_typmod(int32 typmod)
916 : {
917 131502 : return typmod >= (int32) VARHDRSZ;
918 : }
919 :
920 : /*
921 : * numeric_typmod_precision() -
922 : *
923 : * Extract the precision from a numeric typmod --- see make_numeric_typmod().
924 : */
925 : static inline int
926 24292 : numeric_typmod_precision(int32 typmod)
927 : {
928 24292 : return ((typmod - VARHDRSZ) >> 16) & 0xffff;
929 : }
930 :
931 : /*
932 : * numeric_typmod_scale() -
933 : *
934 : * Extract the scale from a numeric typmod --- see make_numeric_typmod().
935 : *
936 : * Note that the scale may be negative, so we must do sign extension when
937 : * unpacking it. We do this using the bit hack (x^1024)-1024, which sign
938 : * extends an 11-bit two's complement number x.
939 : */
940 : static inline int
941 17128 : numeric_typmod_scale(int32 typmod)
942 : {
943 17128 : return (((typmod - VARHDRSZ) & 0x7ff) ^ 1024) - 1024;
944 : }
945 :
946 : /*
947 : * numeric_maximum_size() -
948 : *
949 : * Maximum size of a numeric with given typmod, or -1 if unlimited/unknown.
950 : */
951 : int32
952 7164 : numeric_maximum_size(int32 typmod)
953 : {
954 : int precision;
955 : int numeric_digits;
956 :
957 7164 : if (!is_valid_numeric_typmod(typmod))
958 0 : return -1;
959 :
960 : /* precision (ie, max # of digits) is in upper bits of typmod */
961 7164 : precision = numeric_typmod_precision(typmod);
962 :
963 : /*
964 : * This formula computes the maximum number of NumericDigits we could need
965 : * in order to store the specified number of decimal digits. Because the
966 : * weight is stored as a number of NumericDigits rather than a number of
967 : * decimal digits, it's possible that the first NumericDigit will contain
968 : * only a single decimal digit. Thus, the first two decimal digits can
969 : * require two NumericDigits to store, but it isn't until we reach
970 : * DEC_DIGITS + 2 decimal digits that we potentially need a third
971 : * NumericDigit.
972 : */
973 7164 : numeric_digits = (precision + 2 * (DEC_DIGITS - 1)) / DEC_DIGITS;
974 :
975 : /*
976 : * In most cases, the size of a numeric will be smaller than the value
977 : * computed below, because the varlena header will typically get toasted
978 : * down to a single byte before being stored on disk, and it may also be
979 : * possible to use a short numeric header. But our job here is to compute
980 : * the worst case.
981 : */
982 7164 : return NUMERIC_HDRSZ + (numeric_digits * sizeof(NumericDigit));
983 : }
984 :
985 : /*
986 : * numeric_out_sci() -
987 : *
988 : * Output function for numeric data type in scientific notation.
989 : */
990 : char *
991 246 : numeric_out_sci(Numeric num, int scale)
992 : {
993 : NumericVar x;
994 : char *str;
995 :
996 : /*
997 : * Handle NaN and infinities
998 : */
999 246 : if (NUMERIC_IS_SPECIAL(num))
1000 : {
1001 18 : if (NUMERIC_IS_PINF(num))
1002 6 : return pstrdup("Infinity");
1003 12 : else if (NUMERIC_IS_NINF(num))
1004 6 : return pstrdup("-Infinity");
1005 : else
1006 6 : return pstrdup("NaN");
1007 : }
1008 :
1009 228 : init_var_from_num(num, &x);
1010 :
1011 228 : str = get_str_from_var_sci(&x, scale);
1012 :
1013 228 : return str;
1014 : }
1015 :
1016 : /*
1017 : * numeric_normalize() -
1018 : *
1019 : * Output function for numeric data type, suppressing insignificant trailing
1020 : * zeroes and then any trailing decimal point. The intent of this is to
1021 : * produce strings that are equal if and only if the input numeric values
1022 : * compare equal.
1023 : */
1024 : char *
1025 12966 : numeric_normalize(Numeric num)
1026 : {
1027 : NumericVar x;
1028 : char *str;
1029 : int last;
1030 :
1031 : /*
1032 : * Handle NaN and infinities
1033 : */
1034 12966 : if (NUMERIC_IS_SPECIAL(num))
1035 : {
1036 0 : if (NUMERIC_IS_PINF(num))
1037 0 : return pstrdup("Infinity");
1038 0 : else if (NUMERIC_IS_NINF(num))
1039 0 : return pstrdup("-Infinity");
1040 : else
1041 0 : return pstrdup("NaN");
1042 : }
1043 :
1044 12966 : init_var_from_num(num, &x);
1045 :
1046 12966 : str = get_str_from_var(&x);
1047 :
1048 : /* If there's no decimal point, there's certainly nothing to remove. */
1049 12966 : if (strchr(str, '.') != NULL)
1050 : {
1051 : /*
1052 : * Back up over trailing fractional zeroes. Since there is a decimal
1053 : * point, this loop will terminate safely.
1054 : */
1055 42 : last = strlen(str) - 1;
1056 84 : while (str[last] == '0')
1057 42 : last--;
1058 :
1059 : /* We want to get rid of the decimal point too, if it's now last. */
1060 42 : if (str[last] == '.')
1061 42 : last--;
1062 :
1063 : /* Delete whatever we backed up over. */
1064 42 : str[last + 1] = '\0';
1065 : }
1066 :
1067 12966 : return str;
1068 : }
1069 :
1070 : /*
1071 : * numeric_recv - converts external binary format to numeric
1072 : *
1073 : * External format is a sequence of int16's:
1074 : * ndigits, weight, sign, dscale, NumericDigits.
1075 : */
1076 : Datum
1077 102 : numeric_recv(PG_FUNCTION_ARGS)
1078 : {
1079 102 : StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
1080 :
1081 : #ifdef NOT_USED
1082 : Oid typelem = PG_GETARG_OID(1);
1083 : #endif
1084 102 : int32 typmod = PG_GETARG_INT32(2);
1085 : NumericVar value;
1086 : Numeric res;
1087 : int len,
1088 : i;
1089 :
1090 102 : init_var(&value);
1091 :
1092 102 : len = (uint16) pq_getmsgint(buf, sizeof(uint16));
1093 :
1094 102 : alloc_var(&value, len);
1095 :
1096 102 : value.weight = (int16) pq_getmsgint(buf, sizeof(int16));
1097 : /* we allow any int16 for weight --- OK? */
1098 :
1099 102 : value.sign = (uint16) pq_getmsgint(buf, sizeof(uint16));
1100 102 : if (!(value.sign == NUMERIC_POS ||
1101 0 : value.sign == NUMERIC_NEG ||
1102 0 : value.sign == NUMERIC_NAN ||
1103 0 : value.sign == NUMERIC_PINF ||
1104 0 : value.sign == NUMERIC_NINF))
1105 0 : ereport(ERROR,
1106 : (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
1107 : errmsg("invalid sign in external \"numeric\" value")));
1108 :
1109 102 : value.dscale = (uint16) pq_getmsgint(buf, sizeof(uint16));
1110 102 : if ((value.dscale & NUMERIC_DSCALE_MASK) != value.dscale)
1111 0 : ereport(ERROR,
1112 : (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
1113 : errmsg("invalid scale in external \"numeric\" value")));
1114 :
1115 274 : for (i = 0; i < len; i++)
1116 : {
1117 172 : NumericDigit d = pq_getmsgint(buf, sizeof(NumericDigit));
1118 :
1119 172 : if (d < 0 || d >= NBASE)
1120 0 : ereport(ERROR,
1121 : (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
1122 : errmsg("invalid digit in external \"numeric\" value")));
1123 172 : value.digits[i] = d;
1124 : }
1125 :
1126 : /*
1127 : * If the given dscale would hide any digits, truncate those digits away.
1128 : * We could alternatively throw an error, but that would take a bunch of
1129 : * extra code (about as much as trunc_var involves), and it might cause
1130 : * client compatibility issues. Be careful not to apply trunc_var to
1131 : * special values, as it could do the wrong thing; we don't need it
1132 : * anyway, since make_result will ignore all but the sign field.
1133 : *
1134 : * After doing that, be sure to check the typmod restriction.
1135 : */
1136 102 : if (value.sign == NUMERIC_POS ||
1137 0 : value.sign == NUMERIC_NEG)
1138 : {
1139 102 : trunc_var(&value, value.dscale);
1140 :
1141 102 : (void) apply_typmod(&value, typmod, NULL);
1142 :
1143 102 : res = make_result(&value);
1144 : }
1145 : else
1146 : {
1147 : /* apply_typmod_special wants us to make the Numeric first */
1148 0 : res = make_result(&value);
1149 :
1150 0 : (void) apply_typmod_special(res, typmod, NULL);
1151 : }
1152 :
1153 102 : free_var(&value);
1154 :
1155 102 : PG_RETURN_NUMERIC(res);
1156 : }
1157 :
1158 : /*
1159 : * numeric_send - converts numeric to binary format
1160 : */
1161 : Datum
1162 70 : numeric_send(PG_FUNCTION_ARGS)
1163 : {
1164 70 : Numeric num = PG_GETARG_NUMERIC(0);
1165 : NumericVar x;
1166 : StringInfoData buf;
1167 : int i;
1168 :
1169 70 : init_var_from_num(num, &x);
1170 :
1171 70 : pq_begintypsend(&buf);
1172 :
1173 70 : pq_sendint16(&buf, x.ndigits);
1174 70 : pq_sendint16(&buf, x.weight);
1175 70 : pq_sendint16(&buf, x.sign);
1176 70 : pq_sendint16(&buf, x.dscale);
1177 194 : for (i = 0; i < x.ndigits; i++)
1178 124 : pq_sendint16(&buf, x.digits[i]);
1179 :
1180 70 : PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
1181 : }
1182 :
1183 :
1184 : /*
1185 : * numeric_support()
1186 : *
1187 : * Planner support function for the numeric() length coercion function.
1188 : *
1189 : * Flatten calls that solely represent increases in allowable precision.
1190 : * Scale changes mutate every datum, so they are unoptimizable. Some values,
1191 : * e.g. 1E-1001, can only fit into an unconstrained numeric, so a change from
1192 : * an unconstrained numeric to any constrained numeric is also unoptimizable.
1193 : */
1194 : Datum
1195 516 : numeric_support(PG_FUNCTION_ARGS)
1196 : {
1197 516 : Node *rawreq = (Node *) PG_GETARG_POINTER(0);
1198 516 : Node *ret = NULL;
1199 :
1200 516 : if (IsA(rawreq, SupportRequestSimplify))
1201 : {
1202 228 : SupportRequestSimplify *req = (SupportRequestSimplify *) rawreq;
1203 228 : FuncExpr *expr = req->fcall;
1204 : Node *typmod;
1205 :
1206 : Assert(list_length(expr->args) >= 2);
1207 :
1208 228 : typmod = (Node *) lsecond(expr->args);
1209 :
1210 228 : if (IsA(typmod, Const) && !((Const *) typmod)->constisnull)
1211 : {
1212 228 : Node *source = (Node *) linitial(expr->args);
1213 228 : int32 old_typmod = exprTypmod(source);
1214 228 : int32 new_typmod = DatumGetInt32(((Const *) typmod)->constvalue);
1215 228 : int32 old_scale = numeric_typmod_scale(old_typmod);
1216 228 : int32 new_scale = numeric_typmod_scale(new_typmod);
1217 228 : int32 old_precision = numeric_typmod_precision(old_typmod);
1218 228 : int32 new_precision = numeric_typmod_precision(new_typmod);
1219 :
1220 : /*
1221 : * If new_typmod is invalid, the destination is unconstrained;
1222 : * that's always OK. If old_typmod is valid, the source is
1223 : * constrained, and we're OK if the scale is unchanged and the
1224 : * precision is not decreasing. See further notes in function
1225 : * header comment.
1226 : */
1227 456 : if (!is_valid_numeric_typmod(new_typmod) ||
1228 240 : (is_valid_numeric_typmod(old_typmod) &&
1229 6 : new_scale == old_scale && new_precision >= old_precision))
1230 6 : ret = relabel_to_typmod(source, new_typmod);
1231 : }
1232 : }
1233 :
1234 516 : PG_RETURN_POINTER(ret);
1235 : }
1236 :
1237 : /*
1238 : * numeric() -
1239 : *
1240 : * This is a special function called by the Postgres database system
1241 : * before a value is stored in a tuple's attribute. The precision and
1242 : * scale of the attribute have to be applied on the value.
1243 : */
1244 : Datum
1245 11790 : numeric (PG_FUNCTION_ARGS)
1246 : {
1247 11790 : Numeric num = PG_GETARG_NUMERIC(0);
1248 11790 : int32 typmod = PG_GETARG_INT32(1);
1249 : Numeric new;
1250 : int precision;
1251 : int scale;
1252 : int ddigits;
1253 : int maxdigits;
1254 : int dscale;
1255 : NumericVar var;
1256 :
1257 : /*
1258 : * Handle NaN and infinities: if apply_typmod_special doesn't complain,
1259 : * just return a copy of the input.
1260 : */
1261 11790 : if (NUMERIC_IS_SPECIAL(num))
1262 : {
1263 210 : (void) apply_typmod_special(num, typmod, NULL);
1264 192 : PG_RETURN_NUMERIC(duplicate_numeric(num));
1265 : }
1266 :
1267 : /*
1268 : * If the value isn't a valid type modifier, simply return a copy of the
1269 : * input value
1270 : */
1271 11580 : if (!is_valid_numeric_typmod(typmod))
1272 0 : PG_RETURN_NUMERIC(duplicate_numeric(num));
1273 :
1274 : /*
1275 : * Get the precision and scale out of the typmod value
1276 : */
1277 11580 : precision = numeric_typmod_precision(typmod);
1278 11580 : scale = numeric_typmod_scale(typmod);
1279 11580 : maxdigits = precision - scale;
1280 :
1281 : /* The target display scale is non-negative */
1282 11580 : dscale = Max(scale, 0);
1283 :
1284 : /*
1285 : * If the number is certainly in bounds and due to the target scale no
1286 : * rounding could be necessary, just make a copy of the input and modify
1287 : * its scale fields, unless the larger scale forces us to abandon the
1288 : * short representation. (Note we assume the existing dscale is
1289 : * honest...)
1290 : */
1291 11580 : ddigits = (NUMERIC_WEIGHT(num) + 1) * DEC_DIGITS;
1292 11580 : if (ddigits <= maxdigits && scale >= NUMERIC_DSCALE(num)
1293 7134 : && (NUMERIC_CAN_BE_SHORT(dscale, NUMERIC_WEIGHT(num))
1294 0 : || !NUMERIC_IS_SHORT(num)))
1295 : {
1296 7134 : new = duplicate_numeric(num);
1297 7134 : if (NUMERIC_IS_SHORT(num))
1298 7134 : new->choice.n_short.n_header =
1299 7134 : (num->choice.n_short.n_header & ~NUMERIC_SHORT_DSCALE_MASK)
1300 7134 : | (dscale << NUMERIC_SHORT_DSCALE_SHIFT);
1301 : else
1302 0 : new->choice.n_long.n_sign_dscale = NUMERIC_SIGN(new) |
1303 0 : ((uint16) dscale & NUMERIC_DSCALE_MASK);
1304 7134 : PG_RETURN_NUMERIC(new);
1305 : }
1306 :
1307 : /*
1308 : * We really need to fiddle with things - unpack the number into a
1309 : * variable and let apply_typmod() do it.
1310 : */
1311 4446 : init_var(&var);
1312 :
1313 4446 : set_var_from_num(num, &var);
1314 4446 : (void) apply_typmod(&var, typmod, NULL);
1315 4386 : new = make_result(&var);
1316 :
1317 4386 : free_var(&var);
1318 :
1319 4386 : PG_RETURN_NUMERIC(new);
1320 : }
1321 :
1322 : Datum
1323 1932 : numerictypmodin(PG_FUNCTION_ARGS)
1324 : {
1325 1932 : ArrayType *ta = PG_GETARG_ARRAYTYPE_P(0);
1326 : int32 *tl;
1327 : int n;
1328 : int32 typmod;
1329 :
1330 1932 : tl = ArrayGetIntegerTypmods(ta, &n);
1331 :
1332 1932 : if (n == 2)
1333 : {
1334 1912 : if (tl[0] < 1 || tl[0] > NUMERIC_MAX_PRECISION)
1335 18 : ereport(ERROR,
1336 : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1337 : errmsg("NUMERIC precision %d must be between 1 and %d",
1338 : tl[0], NUMERIC_MAX_PRECISION)));
1339 1894 : if (tl[1] < NUMERIC_MIN_SCALE || tl[1] > NUMERIC_MAX_SCALE)
1340 12 : ereport(ERROR,
1341 : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1342 : errmsg("NUMERIC scale %d must be between %d and %d",
1343 : tl[1], NUMERIC_MIN_SCALE, NUMERIC_MAX_SCALE)));
1344 1882 : typmod = make_numeric_typmod(tl[0], tl[1]);
1345 : }
1346 20 : else if (n == 1)
1347 : {
1348 8 : if (tl[0] < 1 || tl[0] > NUMERIC_MAX_PRECISION)
1349 0 : ereport(ERROR,
1350 : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1351 : errmsg("NUMERIC precision %d must be between 1 and %d",
1352 : tl[0], NUMERIC_MAX_PRECISION)));
1353 : /* scale defaults to zero */
1354 8 : typmod = make_numeric_typmod(tl[0], 0);
1355 : }
1356 : else
1357 : {
1358 12 : ereport(ERROR,
1359 : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1360 : errmsg("invalid NUMERIC type modifier")));
1361 : typmod = 0; /* keep compiler quiet */
1362 : }
1363 :
1364 1890 : PG_RETURN_INT32(typmod);
1365 : }
1366 :
1367 : Datum
1368 376 : numerictypmodout(PG_FUNCTION_ARGS)
1369 : {
1370 376 : int32 typmod = PG_GETARG_INT32(0);
1371 376 : char *res = (char *) palloc(64);
1372 :
1373 376 : if (is_valid_numeric_typmod(typmod))
1374 376 : snprintf(res, 64, "(%d,%d)",
1375 : numeric_typmod_precision(typmod),
1376 : numeric_typmod_scale(typmod));
1377 : else
1378 0 : *res = '\0';
1379 :
1380 376 : PG_RETURN_CSTRING(res);
1381 : }
1382 :
1383 :
1384 : /* ----------------------------------------------------------------------
1385 : *
1386 : * Sign manipulation, rounding and the like
1387 : *
1388 : * ----------------------------------------------------------------------
1389 : */
1390 :
1391 : Datum
1392 19506 : numeric_abs(PG_FUNCTION_ARGS)
1393 : {
1394 19506 : Numeric num = PG_GETARG_NUMERIC(0);
1395 : Numeric res;
1396 :
1397 : /*
1398 : * Do it the easy way directly on the packed format
1399 : */
1400 19506 : res = duplicate_numeric(num);
1401 :
1402 19506 : if (NUMERIC_IS_SHORT(num))
1403 19440 : res->choice.n_short.n_header =
1404 19440 : num->choice.n_short.n_header & ~NUMERIC_SHORT_SIGN_MASK;
1405 66 : else if (NUMERIC_IS_SPECIAL(num))
1406 : {
1407 : /* This changes -Inf to Inf, and doesn't affect NaN */
1408 18 : res->choice.n_short.n_header =
1409 18 : num->choice.n_short.n_header & ~NUMERIC_INF_SIGN_MASK;
1410 : }
1411 : else
1412 48 : res->choice.n_long.n_sign_dscale = NUMERIC_POS | NUMERIC_DSCALE(num);
1413 :
1414 19506 : PG_RETURN_NUMERIC(res);
1415 : }
1416 :
1417 :
1418 : Datum
1419 884 : numeric_uminus(PG_FUNCTION_ARGS)
1420 : {
1421 884 : Numeric num = PG_GETARG_NUMERIC(0);
1422 : Numeric res;
1423 :
1424 : /*
1425 : * Do it the easy way directly on the packed format
1426 : */
1427 884 : res = duplicate_numeric(num);
1428 :
1429 884 : if (NUMERIC_IS_SPECIAL(num))
1430 : {
1431 : /* Flip the sign, if it's Inf or -Inf */
1432 126 : if (!NUMERIC_IS_NAN(num))
1433 84 : res->choice.n_short.n_header =
1434 84 : num->choice.n_short.n_header ^ NUMERIC_INF_SIGN_MASK;
1435 : }
1436 :
1437 : /*
1438 : * The packed format is known to be totally zero digit trimmed always. So
1439 : * once we've eliminated specials, we can identify a zero by the fact that
1440 : * there are no digits at all. Do nothing to a zero.
1441 : */
1442 758 : else if (NUMERIC_NDIGITS(num) != 0)
1443 : {
1444 : /* Else, flip the sign */
1445 644 : if (NUMERIC_IS_SHORT(num))
1446 644 : res->choice.n_short.n_header =
1447 644 : num->choice.n_short.n_header ^ NUMERIC_SHORT_SIGN_MASK;
1448 0 : else if (NUMERIC_SIGN(num) == NUMERIC_POS)
1449 0 : res->choice.n_long.n_sign_dscale =
1450 0 : NUMERIC_NEG | NUMERIC_DSCALE(num);
1451 : else
1452 0 : res->choice.n_long.n_sign_dscale =
1453 0 : NUMERIC_POS | NUMERIC_DSCALE(num);
1454 : }
1455 :
1456 884 : PG_RETURN_NUMERIC(res);
1457 : }
1458 :
1459 :
1460 : Datum
1461 498 : numeric_uplus(PG_FUNCTION_ARGS)
1462 : {
1463 498 : Numeric num = PG_GETARG_NUMERIC(0);
1464 :
1465 498 : PG_RETURN_NUMERIC(duplicate_numeric(num));
1466 : }
1467 :
1468 :
1469 : /*
1470 : * numeric_sign_internal() -
1471 : *
1472 : * Returns -1 if the argument is less than 0, 0 if the argument is equal
1473 : * to 0, and 1 if the argument is greater than zero. Caller must have
1474 : * taken care of the NaN case, but we can handle infinities here.
1475 : */
1476 : static int
1477 3570 : numeric_sign_internal(Numeric num)
1478 : {
1479 3570 : if (NUMERIC_IS_SPECIAL(num))
1480 : {
1481 : Assert(!NUMERIC_IS_NAN(num));
1482 : /* Must be Inf or -Inf */
1483 312 : if (NUMERIC_IS_PINF(num))
1484 186 : return 1;
1485 : else
1486 126 : return -1;
1487 : }
1488 :
1489 : /*
1490 : * The packed format is known to be totally zero digit trimmed always. So
1491 : * once we've eliminated specials, we can identify a zero by the fact that
1492 : * there are no digits at all.
1493 : */
1494 3258 : else if (NUMERIC_NDIGITS(num) == 0)
1495 228 : return 0;
1496 3030 : else if (NUMERIC_SIGN(num) == NUMERIC_NEG)
1497 732 : return -1;
1498 : else
1499 2298 : return 1;
1500 : }
1501 :
1502 : /*
1503 : * numeric_sign() -
1504 : *
1505 : * returns -1 if the argument is less than 0, 0 if the argument is equal
1506 : * to 0, and 1 if the argument is greater than zero.
1507 : */
1508 : Datum
1509 48 : numeric_sign(PG_FUNCTION_ARGS)
1510 : {
1511 48 : Numeric num = PG_GETARG_NUMERIC(0);
1512 :
1513 : /*
1514 : * Handle NaN (infinities can be handled normally)
1515 : */
1516 48 : if (NUMERIC_IS_NAN(num))
1517 6 : PG_RETURN_NUMERIC(make_result(&const_nan));
1518 :
1519 42 : switch (numeric_sign_internal(num))
1520 : {
1521 6 : case 0:
1522 6 : PG_RETURN_NUMERIC(make_result(&const_zero));
1523 18 : case 1:
1524 18 : PG_RETURN_NUMERIC(make_result(&const_one));
1525 18 : case -1:
1526 18 : PG_RETURN_NUMERIC(make_result(&const_minus_one));
1527 : }
1528 :
1529 : Assert(false);
1530 0 : return (Datum) 0;
1531 : }
1532 :
1533 :
1534 : /*
1535 : * numeric_round() -
1536 : *
1537 : * Round a value to have 'scale' digits after the decimal point.
1538 : * We allow negative 'scale', implying rounding before the decimal
1539 : * point --- Oracle interprets rounding that way.
1540 : */
1541 : Datum
1542 7808 : numeric_round(PG_FUNCTION_ARGS)
1543 : {
1544 7808 : Numeric num = PG_GETARG_NUMERIC(0);
1545 7808 : int32 scale = PG_GETARG_INT32(1);
1546 : Numeric res;
1547 : NumericVar arg;
1548 :
1549 : /*
1550 : * Handle NaN and infinities
1551 : */
1552 7808 : if (NUMERIC_IS_SPECIAL(num))
1553 96 : PG_RETURN_NUMERIC(duplicate_numeric(num));
1554 :
1555 : /*
1556 : * Limit the scale value to avoid possible overflow in calculations.
1557 : *
1558 : * These limits are based on the maximum number of digits a Numeric value
1559 : * can have before and after the decimal point, but we must allow for one
1560 : * extra digit before the decimal point, in case the most significant
1561 : * digit rounds up; we must check if that causes Numeric overflow.
1562 : */
1563 7712 : scale = Max(scale, -(NUMERIC_WEIGHT_MAX + 1) * DEC_DIGITS - 1);
1564 7712 : scale = Min(scale, NUMERIC_DSCALE_MAX);
1565 :
1566 : /*
1567 : * Unpack the argument and round it at the proper digit position
1568 : */
1569 7712 : init_var(&arg);
1570 7712 : set_var_from_num(num, &arg);
1571 :
1572 7712 : round_var(&arg, scale);
1573 :
1574 : /* We don't allow negative output dscale */
1575 7712 : if (scale < 0)
1576 216 : arg.dscale = 0;
1577 :
1578 : /*
1579 : * Return the rounded result
1580 : */
1581 7712 : res = make_result(&arg);
1582 :
1583 7706 : free_var(&arg);
1584 7706 : PG_RETURN_NUMERIC(res);
1585 : }
1586 :
1587 :
1588 : /*
1589 : * numeric_trunc() -
1590 : *
1591 : * Truncate a value to have 'scale' digits after the decimal point.
1592 : * We allow negative 'scale', implying a truncation before the decimal
1593 : * point --- Oracle interprets truncation that way.
1594 : */
1595 : Datum
1596 626 : numeric_trunc(PG_FUNCTION_ARGS)
1597 : {
1598 626 : Numeric num = PG_GETARG_NUMERIC(0);
1599 626 : int32 scale = PG_GETARG_INT32(1);
1600 : Numeric res;
1601 : NumericVar arg;
1602 :
1603 : /*
1604 : * Handle NaN and infinities
1605 : */
1606 626 : if (NUMERIC_IS_SPECIAL(num))
1607 36 : PG_RETURN_NUMERIC(duplicate_numeric(num));
1608 :
1609 : /*
1610 : * Limit the scale value to avoid possible overflow in calculations.
1611 : *
1612 : * These limits are based on the maximum number of digits a Numeric value
1613 : * can have before and after the decimal point.
1614 : */
1615 590 : scale = Max(scale, -(NUMERIC_WEIGHT_MAX + 1) * DEC_DIGITS);
1616 590 : scale = Min(scale, NUMERIC_DSCALE_MAX);
1617 :
1618 : /*
1619 : * Unpack the argument and truncate it at the proper digit position
1620 : */
1621 590 : init_var(&arg);
1622 590 : set_var_from_num(num, &arg);
1623 :
1624 590 : trunc_var(&arg, scale);
1625 :
1626 : /* We don't allow negative output dscale */
1627 590 : if (scale < 0)
1628 24 : arg.dscale = 0;
1629 :
1630 : /*
1631 : * Return the truncated result
1632 : */
1633 590 : res = make_result(&arg);
1634 :
1635 590 : free_var(&arg);
1636 590 : PG_RETURN_NUMERIC(res);
1637 : }
1638 :
1639 :
1640 : /*
1641 : * numeric_ceil() -
1642 : *
1643 : * Return the smallest integer greater than or equal to the argument
1644 : */
1645 : Datum
1646 222 : numeric_ceil(PG_FUNCTION_ARGS)
1647 : {
1648 222 : Numeric num = PG_GETARG_NUMERIC(0);
1649 : Numeric res;
1650 : NumericVar result;
1651 :
1652 : /*
1653 : * Handle NaN and infinities
1654 : */
1655 222 : if (NUMERIC_IS_SPECIAL(num))
1656 18 : PG_RETURN_NUMERIC(duplicate_numeric(num));
1657 :
1658 204 : init_var_from_num(num, &result);
1659 204 : ceil_var(&result, &result);
1660 :
1661 204 : res = make_result(&result);
1662 204 : free_var(&result);
1663 :
1664 204 : PG_RETURN_NUMERIC(res);
1665 : }
1666 :
1667 :
1668 : /*
1669 : * numeric_floor() -
1670 : *
1671 : * Return the largest integer equal to or less than the argument
1672 : */
1673 : Datum
1674 126 : numeric_floor(PG_FUNCTION_ARGS)
1675 : {
1676 126 : Numeric num = PG_GETARG_NUMERIC(0);
1677 : Numeric res;
1678 : NumericVar result;
1679 :
1680 : /*
1681 : * Handle NaN and infinities
1682 : */
1683 126 : if (NUMERIC_IS_SPECIAL(num))
1684 18 : PG_RETURN_NUMERIC(duplicate_numeric(num));
1685 :
1686 108 : init_var_from_num(num, &result);
1687 108 : floor_var(&result, &result);
1688 :
1689 108 : res = make_result(&result);
1690 108 : free_var(&result);
1691 :
1692 108 : PG_RETURN_NUMERIC(res);
1693 : }
1694 :
1695 :
1696 : /*
1697 : * generate_series_numeric() -
1698 : *
1699 : * Generate series of numeric.
1700 : */
1701 : Datum
1702 216 : generate_series_numeric(PG_FUNCTION_ARGS)
1703 : {
1704 216 : return generate_series_step_numeric(fcinfo);
1705 : }
1706 :
1707 : Datum
1708 420 : generate_series_step_numeric(PG_FUNCTION_ARGS)
1709 : {
1710 : generate_series_numeric_fctx *fctx;
1711 : FuncCallContext *funcctx;
1712 : MemoryContext oldcontext;
1713 :
1714 420 : if (SRF_IS_FIRSTCALL())
1715 : {
1716 138 : Numeric start_num = PG_GETARG_NUMERIC(0);
1717 138 : Numeric stop_num = PG_GETARG_NUMERIC(1);
1718 138 : NumericVar steploc = const_one;
1719 :
1720 : /* Reject NaN and infinities in start and stop values */
1721 138 : if (NUMERIC_IS_SPECIAL(start_num))
1722 : {
1723 12 : if (NUMERIC_IS_NAN(start_num))
1724 6 : ereport(ERROR,
1725 : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1726 : errmsg("start value cannot be NaN")));
1727 : else
1728 6 : ereport(ERROR,
1729 : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1730 : errmsg("start value cannot be infinity")));
1731 : }
1732 126 : if (NUMERIC_IS_SPECIAL(stop_num))
1733 : {
1734 12 : if (NUMERIC_IS_NAN(stop_num))
1735 6 : ereport(ERROR,
1736 : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1737 : errmsg("stop value cannot be NaN")));
1738 : else
1739 6 : ereport(ERROR,
1740 : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1741 : errmsg("stop value cannot be infinity")));
1742 : }
1743 :
1744 : /* see if we were given an explicit step size */
1745 114 : if (PG_NARGS() == 3)
1746 : {
1747 54 : Numeric step_num = PG_GETARG_NUMERIC(2);
1748 :
1749 54 : if (NUMERIC_IS_SPECIAL(step_num))
1750 : {
1751 12 : if (NUMERIC_IS_NAN(step_num))
1752 6 : ereport(ERROR,
1753 : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1754 : errmsg("step size cannot be NaN")));
1755 : else
1756 6 : ereport(ERROR,
1757 : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1758 : errmsg("step size cannot be infinity")));
1759 : }
1760 :
1761 42 : init_var_from_num(step_num, &steploc);
1762 :
1763 42 : if (cmp_var(&steploc, &const_zero) == 0)
1764 6 : ereport(ERROR,
1765 : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1766 : errmsg("step size cannot equal zero")));
1767 : }
1768 :
1769 : /* create a function context for cross-call persistence */
1770 96 : funcctx = SRF_FIRSTCALL_INIT();
1771 :
1772 : /*
1773 : * Switch to memory context appropriate for multiple function calls.
1774 : */
1775 96 : oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
1776 :
1777 : /* allocate memory for user context */
1778 : fctx = (generate_series_numeric_fctx *)
1779 96 : palloc(sizeof(generate_series_numeric_fctx));
1780 :
1781 : /*
1782 : * Use fctx to keep state from call to call. Seed current with the
1783 : * original start value. We must copy the start_num and stop_num
1784 : * values rather than pointing to them, since we may have detoasted
1785 : * them in the per-call context.
1786 : */
1787 96 : init_var(&fctx->current);
1788 96 : init_var(&fctx->stop);
1789 96 : init_var(&fctx->step);
1790 :
1791 96 : set_var_from_num(start_num, &fctx->current);
1792 96 : set_var_from_num(stop_num, &fctx->stop);
1793 96 : set_var_from_var(&steploc, &fctx->step);
1794 :
1795 96 : funcctx->user_fctx = fctx;
1796 96 : MemoryContextSwitchTo(oldcontext);
1797 : }
1798 :
1799 : /* stuff done on every call of the function */
1800 378 : funcctx = SRF_PERCALL_SETUP();
1801 :
1802 : /*
1803 : * Get the saved state and use current state as the result of this
1804 : * iteration.
1805 : */
1806 378 : fctx = funcctx->user_fctx;
1807 :
1808 732 : if ((fctx->step.sign == NUMERIC_POS &&
1809 354 : cmp_var(&fctx->current, &fctx->stop) <= 0) ||
1810 138 : (fctx->step.sign == NUMERIC_NEG &&
1811 24 : cmp_var(&fctx->current, &fctx->stop) >= 0))
1812 : {
1813 282 : Numeric result = make_result(&fctx->current);
1814 :
1815 : /* switch to memory context appropriate for iteration calculation */
1816 282 : oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
1817 :
1818 : /* increment current in preparation for next iteration */
1819 282 : add_var(&fctx->current, &fctx->step, &fctx->current);
1820 282 : MemoryContextSwitchTo(oldcontext);
1821 :
1822 : /* do when there is more left to send */
1823 282 : SRF_RETURN_NEXT(funcctx, NumericGetDatum(result));
1824 : }
1825 : else
1826 : /* do when there is no more left */
1827 96 : SRF_RETURN_DONE(funcctx);
1828 : }
1829 :
1830 :
1831 : /*
1832 : * Implements the numeric version of the width_bucket() function
1833 : * defined by SQL2003. See also width_bucket_float8().
1834 : *
1835 : * 'bound1' and 'bound2' are the lower and upper bounds of the
1836 : * histogram's range, respectively. 'count' is the number of buckets
1837 : * in the histogram. width_bucket() returns an integer indicating the
1838 : * bucket number that 'operand' belongs to in an equiwidth histogram
1839 : * with the specified characteristics. An operand smaller than the
1840 : * lower bound is assigned to bucket 0. An operand greater than the
1841 : * upper bound is assigned to an additional bucket (with number
1842 : * count+1). We don't allow "NaN" for any of the numeric arguments.
1843 : */
1844 : Datum
1845 780 : width_bucket_numeric(PG_FUNCTION_ARGS)
1846 : {
1847 780 : Numeric operand = PG_GETARG_NUMERIC(0);
1848 780 : Numeric bound1 = PG_GETARG_NUMERIC(1);
1849 780 : Numeric bound2 = PG_GETARG_NUMERIC(2);
1850 780 : int32 count = PG_GETARG_INT32(3);
1851 : NumericVar count_var;
1852 : NumericVar result_var;
1853 : int32 result;
1854 :
1855 780 : if (count <= 0)
1856 12 : ereport(ERROR,
1857 : (errcode(ERRCODE_INVALID_ARGUMENT_FOR_WIDTH_BUCKET_FUNCTION),
1858 : errmsg("count must be greater than zero")));
1859 :
1860 768 : if (NUMERIC_IS_SPECIAL(operand) ||
1861 750 : NUMERIC_IS_SPECIAL(bound1) ||
1862 744 : NUMERIC_IS_SPECIAL(bound2))
1863 : {
1864 36 : if (NUMERIC_IS_NAN(operand) ||
1865 30 : NUMERIC_IS_NAN(bound1) ||
1866 30 : NUMERIC_IS_NAN(bound2))
1867 6 : ereport(ERROR,
1868 : (errcode(ERRCODE_INVALID_ARGUMENT_FOR_WIDTH_BUCKET_FUNCTION),
1869 : errmsg("operand, lower bound, and upper bound cannot be NaN")));
1870 : /* We allow "operand" to be infinite; cmp_numerics will cope */
1871 30 : if (NUMERIC_IS_INF(bound1) || NUMERIC_IS_INF(bound2))
1872 18 : ereport(ERROR,
1873 : (errcode(ERRCODE_INVALID_ARGUMENT_FOR_WIDTH_BUCKET_FUNCTION),
1874 : errmsg("lower and upper bounds must be finite")));
1875 : }
1876 :
1877 744 : init_var(&result_var);
1878 744 : init_var(&count_var);
1879 :
1880 : /* Convert 'count' to a numeric, for ease of use later */
1881 744 : int64_to_numericvar((int64) count, &count_var);
1882 :
1883 744 : switch (cmp_numerics(bound1, bound2))
1884 : {
1885 6 : case 0:
1886 6 : ereport(ERROR,
1887 : (errcode(ERRCODE_INVALID_ARGUMENT_FOR_WIDTH_BUCKET_FUNCTION),
1888 : errmsg("lower bound cannot equal upper bound")));
1889 : break;
1890 :
1891 : /* bound1 < bound2 */
1892 546 : case -1:
1893 546 : if (cmp_numerics(operand, bound1) < 0)
1894 114 : set_var_from_var(&const_zero, &result_var);
1895 432 : else if (cmp_numerics(operand, bound2) >= 0)
1896 108 : add_var(&count_var, &const_one, &result_var);
1897 : else
1898 324 : compute_bucket(operand, bound1, bound2, &count_var,
1899 : &result_var);
1900 546 : break;
1901 :
1902 : /* bound1 > bound2 */
1903 192 : case 1:
1904 192 : if (cmp_numerics(operand, bound1) > 0)
1905 12 : set_var_from_var(&const_zero, &result_var);
1906 180 : else if (cmp_numerics(operand, bound2) <= 0)
1907 24 : add_var(&count_var, &const_one, &result_var);
1908 : else
1909 156 : compute_bucket(operand, bound1, bound2, &count_var,
1910 : &result_var);
1911 192 : break;
1912 : }
1913 :
1914 : /* if result exceeds the range of a legal int4, we ereport here */
1915 738 : if (!numericvar_to_int32(&result_var, &result))
1916 0 : ereport(ERROR,
1917 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1918 : errmsg("integer out of range")));
1919 :
1920 738 : free_var(&count_var);
1921 738 : free_var(&result_var);
1922 :
1923 738 : PG_RETURN_INT32(result);
1924 : }
1925 :
1926 : /*
1927 : * 'operand' is inside the bucket range, so determine the correct
1928 : * bucket for it to go in. The calculations performed by this function
1929 : * are derived directly from the SQL2003 spec. Note however that we
1930 : * multiply by count before dividing, to avoid unnecessary roundoff error.
1931 : */
1932 : static void
1933 480 : compute_bucket(Numeric operand, Numeric bound1, Numeric bound2,
1934 : const NumericVar *count_var, NumericVar *result_var)
1935 : {
1936 : NumericVar bound1_var;
1937 : NumericVar bound2_var;
1938 : NumericVar operand_var;
1939 :
1940 480 : init_var_from_num(bound1, &bound1_var);
1941 480 : init_var_from_num(bound2, &bound2_var);
1942 480 : init_var_from_num(operand, &operand_var);
1943 :
1944 : /*
1945 : * Per spec, bound1 is inclusive and bound2 is exclusive, and so we have
1946 : * bound1 <= operand < bound2 or bound1 >= operand > bound2. Either way,
1947 : * the result is ((operand - bound1) * count) / (bound2 - bound1) + 1,
1948 : * where the quotient is computed using floor division (i.e., division to
1949 : * zero decimal places with truncation), which guarantees that the result
1950 : * is in the range [1, count]. Reversing the bounds doesn't affect the
1951 : * computation, because the signs cancel out when dividing.
1952 : */
1953 480 : sub_var(&operand_var, &bound1_var, &operand_var);
1954 480 : sub_var(&bound2_var, &bound1_var, &bound2_var);
1955 :
1956 480 : mul_var(&operand_var, count_var, &operand_var,
1957 480 : operand_var.dscale + count_var->dscale);
1958 480 : div_var(&operand_var, &bound2_var, result_var, 0, false, true);
1959 480 : add_var(result_var, &const_one, result_var);
1960 :
1961 480 : free_var(&bound1_var);
1962 480 : free_var(&bound2_var);
1963 480 : free_var(&operand_var);
1964 480 : }
1965 :
1966 : /* ----------------------------------------------------------------------
1967 : *
1968 : * Comparison functions
1969 : *
1970 : * Note: btree indexes need these routines not to leak memory; therefore,
1971 : * be careful to free working copies of toasted datums. Most places don't
1972 : * need to be so careful.
1973 : *
1974 : * Sort support:
1975 : *
1976 : * We implement the sortsupport strategy routine in order to get the benefit of
1977 : * abbreviation. The ordinary numeric comparison can be quite slow as a result
1978 : * of palloc/pfree cycles (due to detoasting packed values for alignment);
1979 : * while this could be worked on itself, the abbreviation strategy gives more
1980 : * speedup in many common cases.
1981 : *
1982 : * Two different representations are used for the abbreviated form, one in
1983 : * int32 and one in int64, whichever fits into a by-value Datum. In both cases
1984 : * the representation is negated relative to the original value, because we use
1985 : * the largest negative value for NaN, which sorts higher than other values. We
1986 : * convert the absolute value of the numeric to a 31-bit or 63-bit positive
1987 : * value, and then negate it if the original number was positive.
1988 : *
1989 : * We abort the abbreviation process if the abbreviation cardinality is below
1990 : * 0.01% of the row count (1 per 10k non-null rows). The actual break-even
1991 : * point is somewhat below that, perhaps 1 per 30k (at 1 per 100k there's a
1992 : * very small penalty), but we don't want to build up too many abbreviated
1993 : * values before first testing for abort, so we take the slightly pessimistic
1994 : * number. We make no attempt to estimate the cardinality of the real values,
1995 : * since it plays no part in the cost model here (if the abbreviation is equal,
1996 : * the cost of comparing equal and unequal underlying values is comparable).
1997 : * We discontinue even checking for abort (saving us the hashing overhead) if
1998 : * the estimated cardinality gets to 100k; that would be enough to support many
1999 : * billions of rows while doing no worse than breaking even.
2000 : *
2001 : * ----------------------------------------------------------------------
2002 : */
2003 :
2004 : /*
2005 : * Sort support strategy routine.
2006 : */
2007 : Datum
2008 972 : numeric_sortsupport(PG_FUNCTION_ARGS)
2009 : {
2010 972 : SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0);
2011 :
2012 972 : ssup->comparator = numeric_fast_cmp;
2013 :
2014 972 : if (ssup->abbreviate)
2015 : {
2016 : NumericSortSupport *nss;
2017 250 : MemoryContext oldcontext = MemoryContextSwitchTo(ssup->ssup_cxt);
2018 :
2019 250 : nss = palloc(sizeof(NumericSortSupport));
2020 :
2021 : /*
2022 : * palloc a buffer for handling unaligned packed values in addition to
2023 : * the support struct
2024 : */
2025 250 : nss->buf = palloc(VARATT_SHORT_MAX + VARHDRSZ + 1);
2026 :
2027 250 : nss->input_count = 0;
2028 250 : nss->estimating = true;
2029 250 : initHyperLogLog(&nss->abbr_card, 10);
2030 :
2031 250 : ssup->ssup_extra = nss;
2032 :
2033 250 : ssup->abbrev_full_comparator = ssup->comparator;
2034 250 : ssup->comparator = numeric_cmp_abbrev;
2035 250 : ssup->abbrev_converter = numeric_abbrev_convert;
2036 250 : ssup->abbrev_abort = numeric_abbrev_abort;
2037 :
2038 250 : MemoryContextSwitchTo(oldcontext);
2039 : }
2040 :
2041 972 : PG_RETURN_VOID();
2042 : }
2043 :
2044 : /*
2045 : * Abbreviate a numeric datum, handling NaNs and detoasting
2046 : * (must not leak memory!)
2047 : */
2048 : static Datum
2049 19132 : numeric_abbrev_convert(Datum original_datum, SortSupport ssup)
2050 : {
2051 19132 : NumericSortSupport *nss = ssup->ssup_extra;
2052 19132 : void *original_varatt = PG_DETOAST_DATUM_PACKED(original_datum);
2053 : Numeric value;
2054 : Datum result;
2055 :
2056 19132 : nss->input_count += 1;
2057 :
2058 : /*
2059 : * This is to handle packed datums without needing a palloc/pfree cycle;
2060 : * we keep and reuse a buffer large enough to handle any short datum.
2061 : */
2062 19132 : if (VARATT_IS_SHORT(original_varatt))
2063 : {
2064 1026 : void *buf = nss->buf;
2065 1026 : Size sz = VARSIZE_SHORT(original_varatt) - VARHDRSZ_SHORT;
2066 :
2067 : Assert(sz <= VARATT_SHORT_MAX - VARHDRSZ_SHORT);
2068 :
2069 1026 : SET_VARSIZE(buf, VARHDRSZ + sz);
2070 1026 : memcpy(VARDATA(buf), VARDATA_SHORT(original_varatt), sz);
2071 :
2072 1026 : value = (Numeric) buf;
2073 : }
2074 : else
2075 18106 : value = (Numeric) original_varatt;
2076 :
2077 19132 : if (NUMERIC_IS_SPECIAL(value))
2078 : {
2079 150 : if (NUMERIC_IS_PINF(value))
2080 48 : result = NUMERIC_ABBREV_PINF;
2081 102 : else if (NUMERIC_IS_NINF(value))
2082 48 : result = NUMERIC_ABBREV_NINF;
2083 : else
2084 54 : result = NUMERIC_ABBREV_NAN;
2085 : }
2086 : else
2087 : {
2088 : NumericVar var;
2089 :
2090 18982 : init_var_from_num(value, &var);
2091 :
2092 18982 : result = numeric_abbrev_convert_var(&var, nss);
2093 : }
2094 :
2095 : /* should happen only for external/compressed toasts */
2096 19132 : if ((Pointer) original_varatt != DatumGetPointer(original_datum))
2097 0 : pfree(original_varatt);
2098 :
2099 19132 : return result;
2100 : }
2101 :
2102 : /*
2103 : * Consider whether to abort abbreviation.
2104 : *
2105 : * We pay no attention to the cardinality of the non-abbreviated data. There is
2106 : * no reason to do so: unlike text, we have no fast check for equal values, so
2107 : * we pay the full overhead whenever the abbreviations are equal regardless of
2108 : * whether the underlying values are also equal.
2109 : */
2110 : static bool
2111 144 : numeric_abbrev_abort(int memtupcount, SortSupport ssup)
2112 : {
2113 144 : NumericSortSupport *nss = ssup->ssup_extra;
2114 : double abbr_card;
2115 :
2116 144 : if (memtupcount < 10000 || nss->input_count < 10000 || !nss->estimating)
2117 144 : return false;
2118 :
2119 0 : abbr_card = estimateHyperLogLog(&nss->abbr_card);
2120 :
2121 : /*
2122 : * If we have >100k distinct values, then even if we were sorting many
2123 : * billion rows we'd likely still break even, and the penalty of undoing
2124 : * that many rows of abbrevs would probably not be worth it. Stop even
2125 : * counting at that point.
2126 : */
2127 0 : if (abbr_card > 100000.0)
2128 : {
2129 0 : if (trace_sort)
2130 0 : elog(LOG,
2131 : "numeric_abbrev: estimation ends at cardinality %f"
2132 : " after " INT64_FORMAT " values (%d rows)",
2133 : abbr_card, nss->input_count, memtupcount);
2134 0 : nss->estimating = false;
2135 0 : return false;
2136 : }
2137 :
2138 : /*
2139 : * Target minimum cardinality is 1 per ~10k of non-null inputs. (The
2140 : * break even point is somewhere between one per 100k rows, where
2141 : * abbreviation has a very slight penalty, and 1 per 10k where it wins by
2142 : * a measurable percentage.) We use the relatively pessimistic 10k
2143 : * threshold, and add a 0.5 row fudge factor, because it allows us to
2144 : * abort earlier on genuinely pathological data where we've had exactly
2145 : * one abbreviated value in the first 10k (non-null) rows.
2146 : */
2147 0 : if (abbr_card < nss->input_count / 10000.0 + 0.5)
2148 : {
2149 0 : if (trace_sort)
2150 0 : elog(LOG,
2151 : "numeric_abbrev: aborting abbreviation at cardinality %f"
2152 : " below threshold %f after " INT64_FORMAT " values (%d rows)",
2153 : abbr_card, nss->input_count / 10000.0 + 0.5,
2154 : nss->input_count, memtupcount);
2155 0 : return true;
2156 : }
2157 :
2158 0 : if (trace_sort)
2159 0 : elog(LOG,
2160 : "numeric_abbrev: cardinality %f"
2161 : " after " INT64_FORMAT " values (%d rows)",
2162 : abbr_card, nss->input_count, memtupcount);
2163 :
2164 0 : return false;
2165 : }
2166 :
2167 : /*
2168 : * Non-fmgr interface to the comparison routine to allow sortsupport to elide
2169 : * the fmgr call. The saving here is small given how slow numeric comparisons
2170 : * are, but it is a required part of the sort support API when abbreviations
2171 : * are performed.
2172 : *
2173 : * Two palloc/pfree cycles could be saved here by using persistent buffers for
2174 : * aligning short-varlena inputs, but this has not so far been considered to
2175 : * be worth the effort.
2176 : */
2177 : static int
2178 4548024 : numeric_fast_cmp(Datum x, Datum y, SortSupport ssup)
2179 : {
2180 4548024 : Numeric nx = DatumGetNumeric(x);
2181 4548024 : Numeric ny = DatumGetNumeric(y);
2182 : int result;
2183 :
2184 4548024 : result = cmp_numerics(nx, ny);
2185 :
2186 4548024 : if ((Pointer) nx != DatumGetPointer(x))
2187 172830 : pfree(nx);
2188 4548024 : if ((Pointer) ny != DatumGetPointer(y))
2189 172824 : pfree(ny);
2190 :
2191 4548024 : return result;
2192 : }
2193 :
2194 : /*
2195 : * Compare abbreviations of values. (Abbreviations may be equal where the true
2196 : * values differ, but if the abbreviations differ, they must reflect the
2197 : * ordering of the true values.)
2198 : */
2199 : static int
2200 188260 : numeric_cmp_abbrev(Datum x, Datum y, SortSupport ssup)
2201 : {
2202 : /*
2203 : * NOTE WELL: this is intentionally backwards, because the abbreviation is
2204 : * negated relative to the original value, to handle NaN/infinity cases.
2205 : */
2206 188260 : if (DatumGetNumericAbbrev(x) < DatumGetNumericAbbrev(y))
2207 98124 : return 1;
2208 90136 : if (DatumGetNumericAbbrev(x) > DatumGetNumericAbbrev(y))
2209 89914 : return -1;
2210 222 : return 0;
2211 : }
2212 :
2213 : /*
2214 : * Abbreviate a NumericVar according to the available bit size.
2215 : *
2216 : * The 31-bit value is constructed as:
2217 : *
2218 : * 0 + 7bits digit weight + 24 bits digit value
2219 : *
2220 : * where the digit weight is in single decimal digits, not digit words, and
2221 : * stored in excess-44 representation[1]. The 24-bit digit value is the 7 most
2222 : * significant decimal digits of the value converted to binary. Values whose
2223 : * weights would fall outside the representable range are rounded off to zero
2224 : * (which is also used to represent actual zeros) or to 0x7FFFFFFF (which
2225 : * otherwise cannot occur). Abbreviation therefore fails to gain any advantage
2226 : * where values are outside the range 10^-44 to 10^83, which is not considered
2227 : * to be a serious limitation, or when values are of the same magnitude and
2228 : * equal in the first 7 decimal digits, which is considered to be an
2229 : * unavoidable limitation given the available bits. (Stealing three more bits
2230 : * to compare another digit would narrow the range of representable weights by
2231 : * a factor of 8, which starts to look like a real limiting factor.)
2232 : *
2233 : * (The value 44 for the excess is essentially arbitrary)
2234 : *
2235 : * The 63-bit value is constructed as:
2236 : *
2237 : * 0 + 7bits weight + 4 x 14-bit packed digit words
2238 : *
2239 : * The weight in this case is again stored in excess-44, but this time it is
2240 : * the original weight in digit words (i.e. powers of 10000). The first four
2241 : * digit words of the value (if present; trailing zeros are assumed as needed)
2242 : * are packed into 14 bits each to form the rest of the value. Again,
2243 : * out-of-range values are rounded off to 0 or 0x7FFFFFFFFFFFFFFF. The
2244 : * representable range in this case is 10^-176 to 10^332, which is considered
2245 : * to be good enough for all practical purposes, and comparison of 4 words
2246 : * means that at least 13 decimal digits are compared, which is considered to
2247 : * be a reasonable compromise between effectiveness and efficiency in computing
2248 : * the abbreviation.
2249 : *
2250 : * (The value 44 for the excess is even more arbitrary here, it was chosen just
2251 : * to match the value used in the 31-bit case)
2252 : *
2253 : * [1] - Excess-k representation means that the value is offset by adding 'k'
2254 : * and then treated as unsigned, so the smallest representable value is stored
2255 : * with all bits zero. This allows simple comparisons to work on the composite
2256 : * value.
2257 : */
2258 :
2259 : #if NUMERIC_ABBREV_BITS == 64
2260 :
2261 : static Datum
2262 18982 : numeric_abbrev_convert_var(const NumericVar *var, NumericSortSupport *nss)
2263 : {
2264 18982 : int ndigits = var->ndigits;
2265 18982 : int weight = var->weight;
2266 : int64 result;
2267 :
2268 18982 : if (ndigits == 0 || weight < -44)
2269 : {
2270 52 : result = 0;
2271 : }
2272 18930 : else if (weight > 83)
2273 : {
2274 12 : result = PG_INT64_MAX;
2275 : }
2276 : else
2277 : {
2278 18918 : result = ((int64) (weight + 44) << 56);
2279 :
2280 18918 : switch (ndigits)
2281 : {
2282 0 : default:
2283 0 : result |= ((int64) var->digits[3]);
2284 : /* FALLTHROUGH */
2285 6208 : case 3:
2286 6208 : result |= ((int64) var->digits[2]) << 14;
2287 : /* FALLTHROUGH */
2288 18270 : case 2:
2289 18270 : result |= ((int64) var->digits[1]) << 28;
2290 : /* FALLTHROUGH */
2291 18918 : case 1:
2292 18918 : result |= ((int64) var->digits[0]) << 42;
2293 18918 : break;
2294 : }
2295 : }
2296 :
2297 : /* the abbrev is negated relative to the original */
2298 18982 : if (var->sign == NUMERIC_POS)
2299 18884 : result = -result;
2300 :
2301 18982 : if (nss->estimating)
2302 : {
2303 18982 : uint32 tmp = ((uint32) result
2304 18982 : ^ (uint32) ((uint64) result >> 32));
2305 :
2306 18982 : addHyperLogLog(&nss->abbr_card, DatumGetUInt32(hash_uint32(tmp)));
2307 : }
2308 :
2309 18982 : return NumericAbbrevGetDatum(result);
2310 : }
2311 :
2312 : #endif /* NUMERIC_ABBREV_BITS == 64 */
2313 :
2314 : #if NUMERIC_ABBREV_BITS == 32
2315 :
2316 : static Datum
2317 : numeric_abbrev_convert_var(const NumericVar *var, NumericSortSupport *nss)
2318 : {
2319 : int ndigits = var->ndigits;
2320 : int weight = var->weight;
2321 : int32 result;
2322 :
2323 : if (ndigits == 0 || weight < -11)
2324 : {
2325 : result = 0;
2326 : }
2327 : else if (weight > 20)
2328 : {
2329 : result = PG_INT32_MAX;
2330 : }
2331 : else
2332 : {
2333 : NumericDigit nxt1 = (ndigits > 1) ? var->digits[1] : 0;
2334 :
2335 : weight = (weight + 11) * 4;
2336 :
2337 : result = var->digits[0];
2338 :
2339 : /*
2340 : * "result" now has 1 to 4 nonzero decimal digits. We pack in more
2341 : * digits to make 7 in total (largest we can fit in 24 bits)
2342 : */
2343 :
2344 : if (result > 999)
2345 : {
2346 : /* already have 4 digits, add 3 more */
2347 : result = (result * 1000) + (nxt1 / 10);
2348 : weight += 3;
2349 : }
2350 : else if (result > 99)
2351 : {
2352 : /* already have 3 digits, add 4 more */
2353 : result = (result * 10000) + nxt1;
2354 : weight += 2;
2355 : }
2356 : else if (result > 9)
2357 : {
2358 : NumericDigit nxt2 = (ndigits > 2) ? var->digits[2] : 0;
2359 :
2360 : /* already have 2 digits, add 5 more */
2361 : result = (result * 100000) + (nxt1 * 10) + (nxt2 / 1000);
2362 : weight += 1;
2363 : }
2364 : else
2365 : {
2366 : NumericDigit nxt2 = (ndigits > 2) ? var->digits[2] : 0;
2367 :
2368 : /* already have 1 digit, add 6 more */
2369 : result = (result * 1000000) + (nxt1 * 100) + (nxt2 / 100);
2370 : }
2371 :
2372 : result = result | (weight << 24);
2373 : }
2374 :
2375 : /* the abbrev is negated relative to the original */
2376 : if (var->sign == NUMERIC_POS)
2377 : result = -result;
2378 :
2379 : if (nss->estimating)
2380 : {
2381 : uint32 tmp = (uint32) result;
2382 :
2383 : addHyperLogLog(&nss->abbr_card, DatumGetUInt32(hash_uint32(tmp)));
2384 : }
2385 :
2386 : return NumericAbbrevGetDatum(result);
2387 : }
2388 :
2389 : #endif /* NUMERIC_ABBREV_BITS == 32 */
2390 :
2391 : /*
2392 : * Ordinary (non-sortsupport) comparisons follow.
2393 : */
2394 :
2395 : Datum
2396 759688 : numeric_cmp(PG_FUNCTION_ARGS)
2397 : {
2398 759688 : Numeric num1 = PG_GETARG_NUMERIC(0);
2399 759688 : Numeric num2 = PG_GETARG_NUMERIC(1);
2400 : int result;
2401 :
2402 759688 : result = cmp_numerics(num1, num2);
2403 :
2404 759688 : PG_FREE_IF_COPY(num1, 0);
2405 759688 : PG_FREE_IF_COPY(num2, 1);
2406 :
2407 759688 : PG_RETURN_INT32(result);
2408 : }
2409 :
2410 :
2411 : Datum
2412 625886 : numeric_eq(PG_FUNCTION_ARGS)
2413 : {
2414 625886 : Numeric num1 = PG_GETARG_NUMERIC(0);
2415 625886 : Numeric num2 = PG_GETARG_NUMERIC(1);
2416 : bool result;
2417 :
2418 625886 : result = cmp_numerics(num1, num2) == 0;
2419 :
2420 625886 : PG_FREE_IF_COPY(num1, 0);
2421 625886 : PG_FREE_IF_COPY(num2, 1);
2422 :
2423 625886 : PG_RETURN_BOOL(result);
2424 : }
2425 :
2426 : Datum
2427 5376 : numeric_ne(PG_FUNCTION_ARGS)
2428 : {
2429 5376 : Numeric num1 = PG_GETARG_NUMERIC(0);
2430 5376 : Numeric num2 = PG_GETARG_NUMERIC(1);
2431 : bool result;
2432 :
2433 5376 : result = cmp_numerics(num1, num2) != 0;
2434 :
2435 5376 : PG_FREE_IF_COPY(num1, 0);
2436 5376 : PG_FREE_IF_COPY(num2, 1);
2437 :
2438 5376 : PG_RETURN_BOOL(result);
2439 : }
2440 :
2441 : Datum
2442 61388 : numeric_gt(PG_FUNCTION_ARGS)
2443 : {
2444 61388 : Numeric num1 = PG_GETARG_NUMERIC(0);
2445 61388 : Numeric num2 = PG_GETARG_NUMERIC(1);
2446 : bool result;
2447 :
2448 61388 : result = cmp_numerics(num1, num2) > 0;
2449 :
2450 61388 : PG_FREE_IF_COPY(num1, 0);
2451 61388 : PG_FREE_IF_COPY(num2, 1);
2452 :
2453 61388 : PG_RETURN_BOOL(result);
2454 : }
2455 :
2456 : Datum
2457 16720 : numeric_ge(PG_FUNCTION_ARGS)
2458 : {
2459 16720 : Numeric num1 = PG_GETARG_NUMERIC(0);
2460 16720 : Numeric num2 = PG_GETARG_NUMERIC(1);
2461 : bool result;
2462 :
2463 16720 : result = cmp_numerics(num1, num2) >= 0;
2464 :
2465 16720 : PG_FREE_IF_COPY(num1, 0);
2466 16720 : PG_FREE_IF_COPY(num2, 1);
2467 :
2468 16720 : PG_RETURN_BOOL(result);
2469 : }
2470 :
2471 : Datum
2472 52532 : numeric_lt(PG_FUNCTION_ARGS)
2473 : {
2474 52532 : Numeric num1 = PG_GETARG_NUMERIC(0);
2475 52532 : Numeric num2 = PG_GETARG_NUMERIC(1);
2476 : bool result;
2477 :
2478 52532 : result = cmp_numerics(num1, num2) < 0;
2479 :
2480 52532 : PG_FREE_IF_COPY(num1, 0);
2481 52532 : PG_FREE_IF_COPY(num2, 1);
2482 :
2483 52532 : PG_RETURN_BOOL(result);
2484 : }
2485 :
2486 : Datum
2487 15484 : numeric_le(PG_FUNCTION_ARGS)
2488 : {
2489 15484 : Numeric num1 = PG_GETARG_NUMERIC(0);
2490 15484 : Numeric num2 = PG_GETARG_NUMERIC(1);
2491 : bool result;
2492 :
2493 15484 : result = cmp_numerics(num1, num2) <= 0;
2494 :
2495 15484 : PG_FREE_IF_COPY(num1, 0);
2496 15484 : PG_FREE_IF_COPY(num2, 1);
2497 :
2498 15484 : PG_RETURN_BOOL(result);
2499 : }
2500 :
2501 : static int
2502 6106620 : cmp_numerics(Numeric num1, Numeric num2)
2503 : {
2504 : int result;
2505 :
2506 : /*
2507 : * We consider all NANs to be equal and larger than any non-NAN (including
2508 : * Infinity). This is somewhat arbitrary; the important thing is to have
2509 : * a consistent sort order.
2510 : */
2511 6106620 : if (NUMERIC_IS_SPECIAL(num1))
2512 : {
2513 8634 : if (NUMERIC_IS_NAN(num1))
2514 : {
2515 8544 : if (NUMERIC_IS_NAN(num2))
2516 970 : result = 0; /* NAN = NAN */
2517 : else
2518 7574 : result = 1; /* NAN > non-NAN */
2519 : }
2520 90 : else if (NUMERIC_IS_PINF(num1))
2521 : {
2522 72 : if (NUMERIC_IS_NAN(num2))
2523 0 : result = -1; /* PINF < NAN */
2524 72 : else if (NUMERIC_IS_PINF(num2))
2525 6 : result = 0; /* PINF = PINF */
2526 : else
2527 66 : result = 1; /* PINF > anything else */
2528 : }
2529 : else /* num1 must be NINF */
2530 : {
2531 18 : if (NUMERIC_IS_NINF(num2))
2532 6 : result = 0; /* NINF = NINF */
2533 : else
2534 12 : result = -1; /* NINF < anything else */
2535 : }
2536 : }
2537 6097986 : else if (NUMERIC_IS_SPECIAL(num2))
2538 : {
2539 11214 : if (NUMERIC_IS_NINF(num2))
2540 12 : result = 1; /* normal > NINF */
2541 : else
2542 11202 : result = -1; /* normal < NAN or PINF */
2543 : }
2544 : else
2545 : {
2546 12175654 : result = cmp_var_common(NUMERIC_DIGITS(num1), NUMERIC_NDIGITS(num1),
2547 6088136 : NUMERIC_WEIGHT(num1), NUMERIC_SIGN(num1),
2548 6086772 : NUMERIC_DIGITS(num2), NUMERIC_NDIGITS(num2),
2549 6087518 : NUMERIC_WEIGHT(num2), NUMERIC_SIGN(num2));
2550 : }
2551 :
2552 6106620 : return result;
2553 : }
2554 :
2555 : /*
2556 : * in_range support function for numeric.
2557 : */
2558 : Datum
2559 1152 : in_range_numeric_numeric(PG_FUNCTION_ARGS)
2560 : {
2561 1152 : Numeric val = PG_GETARG_NUMERIC(0);
2562 1152 : Numeric base = PG_GETARG_NUMERIC(1);
2563 1152 : Numeric offset = PG_GETARG_NUMERIC(2);
2564 1152 : bool sub = PG_GETARG_BOOL(3);
2565 1152 : bool less = PG_GETARG_BOOL(4);
2566 : bool result;
2567 :
2568 : /*
2569 : * Reject negative (including -Inf) or NaN offset. Negative is per spec,
2570 : * and NaN is because appropriate semantics for that seem non-obvious.
2571 : */
2572 1152 : if (NUMERIC_IS_NAN(offset) ||
2573 1146 : NUMERIC_IS_NINF(offset) ||
2574 1146 : NUMERIC_SIGN(offset) == NUMERIC_NEG)
2575 6 : ereport(ERROR,
2576 : (errcode(ERRCODE_INVALID_PRECEDING_OR_FOLLOWING_SIZE),
2577 : errmsg("invalid preceding or following size in window function")));
2578 :
2579 : /*
2580 : * Deal with cases where val and/or base is NaN, following the rule that
2581 : * NaN sorts after non-NaN (cf cmp_numerics). The offset cannot affect
2582 : * the conclusion.
2583 : */
2584 1146 : if (NUMERIC_IS_NAN(val))
2585 : {
2586 186 : if (NUMERIC_IS_NAN(base))
2587 60 : result = true; /* NAN = NAN */
2588 : else
2589 126 : result = !less; /* NAN > non-NAN */
2590 : }
2591 960 : else if (NUMERIC_IS_NAN(base))
2592 : {
2593 126 : result = less; /* non-NAN < NAN */
2594 : }
2595 :
2596 : /*
2597 : * Deal with infinite offset (necessarily +Inf, at this point).
2598 : */
2599 834 : else if (NUMERIC_IS_SPECIAL(offset))
2600 : {
2601 : Assert(NUMERIC_IS_PINF(offset));
2602 420 : if (sub ? NUMERIC_IS_PINF(base) : NUMERIC_IS_NINF(base))
2603 : {
2604 : /*
2605 : * base +/- offset would produce NaN, so return true for any val
2606 : * (see in_range_float8_float8() for reasoning).
2607 : */
2608 174 : result = true;
2609 : }
2610 246 : else if (sub)
2611 : {
2612 : /* base - offset must be -inf */
2613 150 : if (less)
2614 54 : result = NUMERIC_IS_NINF(val); /* only -inf is <= sum */
2615 : else
2616 96 : result = true; /* any val is >= sum */
2617 : }
2618 : else
2619 : {
2620 : /* base + offset must be +inf */
2621 96 : if (less)
2622 0 : result = true; /* any val is <= sum */
2623 : else
2624 96 : result = NUMERIC_IS_PINF(val); /* only +inf is >= sum */
2625 : }
2626 : }
2627 :
2628 : /*
2629 : * Deal with cases where val and/or base is infinite. The offset, being
2630 : * now known finite, cannot affect the conclusion.
2631 : */
2632 414 : else if (NUMERIC_IS_SPECIAL(val))
2633 : {
2634 78 : if (NUMERIC_IS_PINF(val))
2635 : {
2636 36 : if (NUMERIC_IS_PINF(base))
2637 24 : result = true; /* PINF = PINF */
2638 : else
2639 12 : result = !less; /* PINF > any other non-NAN */
2640 : }
2641 : else /* val must be NINF */
2642 : {
2643 42 : if (NUMERIC_IS_NINF(base))
2644 30 : result = true; /* NINF = NINF */
2645 : else
2646 12 : result = less; /* NINF < anything else */
2647 : }
2648 : }
2649 336 : else if (NUMERIC_IS_SPECIAL(base))
2650 : {
2651 24 : if (NUMERIC_IS_NINF(base))
2652 12 : result = !less; /* normal > NINF */
2653 : else
2654 12 : result = less; /* normal < PINF */
2655 : }
2656 : else
2657 : {
2658 : /*
2659 : * Otherwise go ahead and compute base +/- offset. While it's
2660 : * possible for this to overflow the numeric format, it's unlikely
2661 : * enough that we don't take measures to prevent it.
2662 : */
2663 : NumericVar valv;
2664 : NumericVar basev;
2665 : NumericVar offsetv;
2666 : NumericVar sum;
2667 :
2668 312 : init_var_from_num(val, &valv);
2669 312 : init_var_from_num(base, &basev);
2670 312 : init_var_from_num(offset, &offsetv);
2671 312 : init_var(&sum);
2672 :
2673 312 : if (sub)
2674 156 : sub_var(&basev, &offsetv, &sum);
2675 : else
2676 156 : add_var(&basev, &offsetv, &sum);
2677 :
2678 312 : if (less)
2679 156 : result = (cmp_var(&valv, &sum) <= 0);
2680 : else
2681 156 : result = (cmp_var(&valv, &sum) >= 0);
2682 :
2683 312 : free_var(&sum);
2684 : }
2685 :
2686 1146 : PG_FREE_IF_COPY(val, 0);
2687 1146 : PG_FREE_IF_COPY(base, 1);
2688 1146 : PG_FREE_IF_COPY(offset, 2);
2689 :
2690 1146 : PG_RETURN_BOOL(result);
2691 : }
2692 :
2693 : Datum
2694 607512 : hash_numeric(PG_FUNCTION_ARGS)
2695 : {
2696 607512 : Numeric key = PG_GETARG_NUMERIC(0);
2697 : Datum digit_hash;
2698 : Datum result;
2699 : int weight;
2700 : int start_offset;
2701 : int end_offset;
2702 : int i;
2703 : int hash_len;
2704 : NumericDigit *digits;
2705 :
2706 : /* If it's NaN or infinity, don't try to hash the rest of the fields */
2707 607512 : if (NUMERIC_IS_SPECIAL(key))
2708 0 : PG_RETURN_UINT32(0);
2709 :
2710 607512 : weight = NUMERIC_WEIGHT(key);
2711 607512 : start_offset = 0;
2712 607512 : end_offset = 0;
2713 :
2714 : /*
2715 : * Omit any leading or trailing zeros from the input to the hash. The
2716 : * numeric implementation *should* guarantee that leading and trailing
2717 : * zeros are suppressed, but we're paranoid. Note that we measure the
2718 : * starting and ending offsets in units of NumericDigits, not bytes.
2719 : */
2720 607512 : digits = NUMERIC_DIGITS(key);
2721 607512 : for (i = 0; i < NUMERIC_NDIGITS(key); i++)
2722 : {
2723 605874 : if (digits[i] != (NumericDigit) 0)
2724 605874 : break;
2725 :
2726 0 : start_offset++;
2727 :
2728 : /*
2729 : * The weight is effectively the # of digits before the decimal point,
2730 : * so decrement it for each leading zero we skip.
2731 : */
2732 0 : weight--;
2733 : }
2734 :
2735 : /*
2736 : * If there are no non-zero digits, then the value of the number is zero,
2737 : * regardless of any other fields.
2738 : */
2739 607512 : if (NUMERIC_NDIGITS(key) == start_offset)
2740 1638 : PG_RETURN_UINT32(-1);
2741 :
2742 605874 : for (i = NUMERIC_NDIGITS(key) - 1; i >= 0; i--)
2743 : {
2744 605874 : if (digits[i] != (NumericDigit) 0)
2745 605874 : break;
2746 :
2747 0 : end_offset++;
2748 : }
2749 :
2750 : /* If we get here, there should be at least one non-zero digit */
2751 : Assert(start_offset + end_offset < NUMERIC_NDIGITS(key));
2752 :
2753 : /*
2754 : * Note that we don't hash on the Numeric's scale, since two numerics can
2755 : * compare equal but have different scales. We also don't hash on the
2756 : * sign, although we could: since a sign difference implies inequality,
2757 : * this shouldn't affect correctness.
2758 : */
2759 605874 : hash_len = NUMERIC_NDIGITS(key) - start_offset - end_offset;
2760 605874 : digit_hash = hash_any((unsigned char *) (NUMERIC_DIGITS(key) + start_offset),
2761 : hash_len * sizeof(NumericDigit));
2762 :
2763 : /* Mix in the weight, via XOR */
2764 605874 : result = digit_hash ^ weight;
2765 :
2766 605874 : PG_RETURN_DATUM(result);
2767 : }
2768 :
2769 : /*
2770 : * Returns 64-bit value by hashing a value to a 64-bit value, with a seed.
2771 : * Otherwise, similar to hash_numeric.
2772 : */
2773 : Datum
2774 84 : hash_numeric_extended(PG_FUNCTION_ARGS)
2775 : {
2776 84 : Numeric key = PG_GETARG_NUMERIC(0);
2777 84 : uint64 seed = PG_GETARG_INT64(1);
2778 : Datum digit_hash;
2779 : Datum result;
2780 : int weight;
2781 : int start_offset;
2782 : int end_offset;
2783 : int i;
2784 : int hash_len;
2785 : NumericDigit *digits;
2786 :
2787 : /* If it's NaN or infinity, don't try to hash the rest of the fields */
2788 84 : if (NUMERIC_IS_SPECIAL(key))
2789 0 : PG_RETURN_UINT64(seed);
2790 :
2791 84 : weight = NUMERIC_WEIGHT(key);
2792 84 : start_offset = 0;
2793 84 : end_offset = 0;
2794 :
2795 84 : digits = NUMERIC_DIGITS(key);
2796 84 : for (i = 0; i < NUMERIC_NDIGITS(key); i++)
2797 : {
2798 72 : if (digits[i] != (NumericDigit) 0)
2799 72 : break;
2800 :
2801 0 : start_offset++;
2802 :
2803 0 : weight--;
2804 : }
2805 :
2806 84 : if (NUMERIC_NDIGITS(key) == start_offset)
2807 12 : PG_RETURN_UINT64(seed - 1);
2808 :
2809 72 : for (i = NUMERIC_NDIGITS(key) - 1; i >= 0; i--)
2810 : {
2811 72 : if (digits[i] != (NumericDigit) 0)
2812 72 : break;
2813 :
2814 0 : end_offset++;
2815 : }
2816 :
2817 : Assert(start_offset + end_offset < NUMERIC_NDIGITS(key));
2818 :
2819 72 : hash_len = NUMERIC_NDIGITS(key) - start_offset - end_offset;
2820 72 : digit_hash = hash_any_extended((unsigned char *) (NUMERIC_DIGITS(key)
2821 72 : + start_offset),
2822 : hash_len * sizeof(NumericDigit),
2823 : seed);
2824 :
2825 72 : result = UInt64GetDatum(DatumGetUInt64(digit_hash) ^ weight);
2826 :
2827 72 : PG_RETURN_DATUM(result);
2828 : }
2829 :
2830 :
2831 : /* ----------------------------------------------------------------------
2832 : *
2833 : * Basic arithmetic functions
2834 : *
2835 : * ----------------------------------------------------------------------
2836 : */
2837 :
2838 :
2839 : /*
2840 : * numeric_add() -
2841 : *
2842 : * Add two numerics
2843 : */
2844 : Datum
2845 251992 : numeric_add(PG_FUNCTION_ARGS)
2846 : {
2847 251992 : Numeric num1 = PG_GETARG_NUMERIC(0);
2848 251992 : Numeric num2 = PG_GETARG_NUMERIC(1);
2849 : Numeric res;
2850 :
2851 251992 : res = numeric_add_opt_error(num1, num2, NULL);
2852 :
2853 251992 : PG_RETURN_NUMERIC(res);
2854 : }
2855 :
2856 : /*
2857 : * numeric_add_opt_error() -
2858 : *
2859 : * Internal version of numeric_add(). If "*have_error" flag is provided,
2860 : * on error it's set to true, NULL returned. This is helpful when caller
2861 : * need to handle errors by itself.
2862 : */
2863 : Numeric
2864 253030 : numeric_add_opt_error(Numeric num1, Numeric num2, bool *have_error)
2865 : {
2866 : NumericVar arg1;
2867 : NumericVar arg2;
2868 : NumericVar result;
2869 : Numeric res;
2870 :
2871 : /*
2872 : * Handle NaN and infinities
2873 : */
2874 253030 : if (NUMERIC_IS_SPECIAL(num1) || NUMERIC_IS_SPECIAL(num2))
2875 : {
2876 198 : if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
2877 78 : return make_result(&const_nan);
2878 120 : if (NUMERIC_IS_PINF(num1))
2879 : {
2880 36 : if (NUMERIC_IS_NINF(num2))
2881 6 : return make_result(&const_nan); /* Inf + -Inf */
2882 : else
2883 30 : return make_result(&const_pinf);
2884 : }
2885 84 : if (NUMERIC_IS_NINF(num1))
2886 : {
2887 36 : if (NUMERIC_IS_PINF(num2))
2888 6 : return make_result(&const_nan); /* -Inf + Inf */
2889 : else
2890 30 : return make_result(&const_ninf);
2891 : }
2892 : /* by here, num1 must be finite, so num2 is not */
2893 48 : if (NUMERIC_IS_PINF(num2))
2894 24 : return make_result(&const_pinf);
2895 : Assert(NUMERIC_IS_NINF(num2));
2896 24 : return make_result(&const_ninf);
2897 : }
2898 :
2899 : /*
2900 : * Unpack the values, let add_var() compute the result and return it.
2901 : */
2902 252832 : init_var_from_num(num1, &arg1);
2903 252832 : init_var_from_num(num2, &arg2);
2904 :
2905 252832 : init_var(&result);
2906 252832 : add_var(&arg1, &arg2, &result);
2907 :
2908 252832 : res = make_result_opt_error(&result, have_error);
2909 :
2910 252832 : free_var(&result);
2911 :
2912 252832 : return res;
2913 : }
2914 :
2915 :
2916 : /*
2917 : * numeric_sub() -
2918 : *
2919 : * Subtract one numeric from another
2920 : */
2921 : Datum
2922 91684 : numeric_sub(PG_FUNCTION_ARGS)
2923 : {
2924 91684 : Numeric num1 = PG_GETARG_NUMERIC(0);
2925 91684 : Numeric num2 = PG_GETARG_NUMERIC(1);
2926 : Numeric res;
2927 :
2928 91684 : res = numeric_sub_opt_error(num1, num2, NULL);
2929 :
2930 91684 : PG_RETURN_NUMERIC(res);
2931 : }
2932 :
2933 :
2934 : /*
2935 : * numeric_sub_opt_error() -
2936 : *
2937 : * Internal version of numeric_sub(). If "*have_error" flag is provided,
2938 : * on error it's set to true, NULL returned. This is helpful when caller
2939 : * need to handle errors by itself.
2940 : */
2941 : Numeric
2942 91834 : numeric_sub_opt_error(Numeric num1, Numeric num2, bool *have_error)
2943 : {
2944 : NumericVar arg1;
2945 : NumericVar arg2;
2946 : NumericVar result;
2947 : Numeric res;
2948 :
2949 : /*
2950 : * Handle NaN and infinities
2951 : */
2952 91834 : if (NUMERIC_IS_SPECIAL(num1) || NUMERIC_IS_SPECIAL(num2))
2953 : {
2954 2426 : if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
2955 2306 : return make_result(&const_nan);
2956 120 : if (NUMERIC_IS_PINF(num1))
2957 : {
2958 36 : if (NUMERIC_IS_PINF(num2))
2959 6 : return make_result(&const_nan); /* Inf - Inf */
2960 : else
2961 30 : return make_result(&const_pinf);
2962 : }
2963 84 : if (NUMERIC_IS_NINF(num1))
2964 : {
2965 36 : if (NUMERIC_IS_NINF(num2))
2966 6 : return make_result(&const_nan); /* -Inf - -Inf */
2967 : else
2968 30 : return make_result(&const_ninf);
2969 : }
2970 : /* by here, num1 must be finite, so num2 is not */
2971 48 : if (NUMERIC_IS_PINF(num2))
2972 24 : return make_result(&const_ninf);
2973 : Assert(NUMERIC_IS_NINF(num2));
2974 24 : return make_result(&const_pinf);
2975 : }
2976 :
2977 : /*
2978 : * Unpack the values, let sub_var() compute the result and return it.
2979 : */
2980 89408 : init_var_from_num(num1, &arg1);
2981 89408 : init_var_from_num(num2, &arg2);
2982 :
2983 89408 : init_var(&result);
2984 89408 : sub_var(&arg1, &arg2, &result);
2985 :
2986 89408 : res = make_result_opt_error(&result, have_error);
2987 :
2988 89408 : free_var(&result);
2989 :
2990 89408 : return res;
2991 : }
2992 :
2993 :
2994 : /*
2995 : * numeric_mul() -
2996 : *
2997 : * Calculate the product of two numerics
2998 : */
2999 : Datum
3000 489704 : numeric_mul(PG_FUNCTION_ARGS)
3001 : {
3002 489704 : Numeric num1 = PG_GETARG_NUMERIC(0);
3003 489704 : Numeric num2 = PG_GETARG_NUMERIC(1);
3004 : Numeric res;
3005 :
3006 489704 : res = numeric_mul_opt_error(num1, num2, NULL);
3007 :
3008 489704 : PG_RETURN_NUMERIC(res);
3009 : }
3010 :
3011 :
3012 : /*
3013 : * numeric_mul_opt_error() -
3014 : *
3015 : * Internal version of numeric_mul(). If "*have_error" flag is provided,
3016 : * on error it's set to true, NULL returned. This is helpful when caller
3017 : * need to handle errors by itself.
3018 : */
3019 : Numeric
3020 489740 : numeric_mul_opt_error(Numeric num1, Numeric num2, bool *have_error)
3021 : {
3022 : NumericVar arg1;
3023 : NumericVar arg2;
3024 : NumericVar result;
3025 : Numeric res;
3026 :
3027 : /*
3028 : * Handle NaN and infinities
3029 : */
3030 489740 : if (NUMERIC_IS_SPECIAL(num1) || NUMERIC_IS_SPECIAL(num2))
3031 : {
3032 198 : if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
3033 78 : return make_result(&const_nan);
3034 120 : if (NUMERIC_IS_PINF(num1))
3035 : {
3036 36 : switch (numeric_sign_internal(num2))
3037 : {
3038 6 : case 0:
3039 6 : return make_result(&const_nan); /* Inf * 0 */
3040 18 : case 1:
3041 18 : return make_result(&const_pinf);
3042 12 : case -1:
3043 12 : return make_result(&const_ninf);
3044 : }
3045 : Assert(false);
3046 : }
3047 84 : if (NUMERIC_IS_NINF(num1))
3048 : {
3049 36 : switch (numeric_sign_internal(num2))
3050 : {
3051 6 : case 0:
3052 6 : return make_result(&const_nan); /* -Inf * 0 */
3053 18 : case 1:
3054 18 : return make_result(&const_ninf);
3055 12 : case -1:
3056 12 : return make_result(&const_pinf);
3057 : }
3058 : Assert(false);
3059 : }
3060 : /* by here, num1 must be finite, so num2 is not */
3061 48 : if (NUMERIC_IS_PINF(num2))
3062 : {
3063 24 : switch (numeric_sign_internal(num1))
3064 : {
3065 6 : case 0:
3066 6 : return make_result(&const_nan); /* 0 * Inf */
3067 12 : case 1:
3068 12 : return make_result(&const_pinf);
3069 6 : case -1:
3070 6 : return make_result(&const_ninf);
3071 : }
3072 : Assert(false);
3073 : }
3074 : Assert(NUMERIC_IS_NINF(num2));
3075 24 : switch (numeric_sign_internal(num1))
3076 : {
3077 6 : case 0:
3078 6 : return make_result(&const_nan); /* 0 * -Inf */
3079 12 : case 1:
3080 12 : return make_result(&const_ninf);
3081 6 : case -1:
3082 6 : return make_result(&const_pinf);
3083 : }
3084 : Assert(false);
3085 : }
3086 :
3087 : /*
3088 : * Unpack the values, let mul_var() compute the result and return it.
3089 : * Unlike add_var() and sub_var(), mul_var() will round its result. In the
3090 : * case of numeric_mul(), which is invoked for the * operator on numerics,
3091 : * we request exact representation for the product (rscale = sum(dscale of
3092 : * arg1, dscale of arg2)). If the exact result has more digits after the
3093 : * decimal point than can be stored in a numeric, we round it. Rounding
3094 : * after computing the exact result ensures that the final result is
3095 : * correctly rounded (rounding in mul_var() using a truncated product
3096 : * would not guarantee this).
3097 : */
3098 489542 : init_var_from_num(num1, &arg1);
3099 489542 : init_var_from_num(num2, &arg2);
3100 :
3101 489542 : init_var(&result);
3102 489542 : mul_var(&arg1, &arg2, &result, arg1.dscale + arg2.dscale);
3103 :
3104 489542 : if (result.dscale > NUMERIC_DSCALE_MAX)
3105 6 : round_var(&result, NUMERIC_DSCALE_MAX);
3106 :
3107 489542 : res = make_result_opt_error(&result, have_error);
3108 :
3109 489542 : free_var(&result);
3110 :
3111 489542 : return res;
3112 : }
3113 :
3114 :
3115 : /*
3116 : * numeric_div() -
3117 : *
3118 : * Divide one numeric into another
3119 : */
3120 : Datum
3121 151270 : numeric_div(PG_FUNCTION_ARGS)
3122 : {
3123 151270 : Numeric num1 = PG_GETARG_NUMERIC(0);
3124 151270 : Numeric num2 = PG_GETARG_NUMERIC(1);
3125 : Numeric res;
3126 :
3127 151270 : res = numeric_div_opt_error(num1, num2, NULL);
3128 :
3129 151238 : PG_RETURN_NUMERIC(res);
3130 : }
3131 :
3132 :
3133 : /*
3134 : * numeric_div_opt_error() -
3135 : *
3136 : * Internal version of numeric_div(). If "*have_error" flag is provided,
3137 : * on error it's set to true, NULL returned. This is helpful when caller
3138 : * need to handle errors by itself.
3139 : */
3140 : Numeric
3141 152110 : numeric_div_opt_error(Numeric num1, Numeric num2, bool *have_error)
3142 : {
3143 : NumericVar arg1;
3144 : NumericVar arg2;
3145 : NumericVar result;
3146 : Numeric res;
3147 : int rscale;
3148 :
3149 152110 : if (have_error)
3150 48 : *have_error = false;
3151 :
3152 : /*
3153 : * Handle NaN and infinities
3154 : */
3155 152110 : if (NUMERIC_IS_SPECIAL(num1) || NUMERIC_IS_SPECIAL(num2))
3156 : {
3157 198 : if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
3158 78 : return make_result(&const_nan);
3159 120 : if (NUMERIC_IS_PINF(num1))
3160 : {
3161 36 : if (NUMERIC_IS_SPECIAL(num2))
3162 12 : return make_result(&const_nan); /* Inf / [-]Inf */
3163 24 : switch (numeric_sign_internal(num2))
3164 : {
3165 6 : case 0:
3166 6 : if (have_error)
3167 : {
3168 0 : *have_error = true;
3169 0 : return NULL;
3170 : }
3171 6 : ereport(ERROR,
3172 : (errcode(ERRCODE_DIVISION_BY_ZERO),
3173 : errmsg("division by zero")));
3174 : break;
3175 12 : case 1:
3176 12 : return make_result(&const_pinf);
3177 6 : case -1:
3178 6 : return make_result(&const_ninf);
3179 : }
3180 84 : Assert(false);
3181 : }
3182 84 : if (NUMERIC_IS_NINF(num1))
3183 : {
3184 36 : if (NUMERIC_IS_SPECIAL(num2))
3185 12 : return make_result(&const_nan); /* -Inf / [-]Inf */
3186 24 : switch (numeric_sign_internal(num2))
3187 : {
3188 6 : case 0:
3189 6 : if (have_error)
3190 : {
3191 0 : *have_error = true;
3192 0 : return NULL;
3193 : }
3194 6 : ereport(ERROR,
3195 : (errcode(ERRCODE_DIVISION_BY_ZERO),
3196 : errmsg("division by zero")));
3197 : break;
3198 12 : case 1:
3199 12 : return make_result(&const_ninf);
3200 6 : case -1:
3201 6 : return make_result(&const_pinf);
3202 : }
3203 48 : Assert(false);
3204 : }
3205 : /* by here, num1 must be finite, so num2 is not */
3206 :
3207 : /*
3208 : * POSIX would have us return zero or minus zero if num1 is zero, and
3209 : * otherwise throw an underflow error. But the numeric type doesn't
3210 : * really do underflow, so let's just return zero.
3211 : */
3212 48 : return make_result(&const_zero);
3213 : }
3214 :
3215 : /*
3216 : * Unpack the arguments
3217 : */
3218 151912 : init_var_from_num(num1, &arg1);
3219 151912 : init_var_from_num(num2, &arg2);
3220 :
3221 151912 : init_var(&result);
3222 :
3223 : /*
3224 : * Select scale for division result
3225 : */
3226 151912 : rscale = select_div_scale(&arg1, &arg2);
3227 :
3228 : /*
3229 : * If "have_error" is provided, check for division by zero here
3230 : */
3231 151912 : if (have_error && (arg2.ndigits == 0 || arg2.digits[0] == 0))
3232 : {
3233 12 : *have_error = true;
3234 12 : return NULL;
3235 : }
3236 :
3237 : /*
3238 : * Do the divide and return the result
3239 : */
3240 151900 : div_var(&arg1, &arg2, &result, rscale, true, true);
3241 :
3242 151862 : res = make_result_opt_error(&result, have_error);
3243 :
3244 151862 : free_var(&result);
3245 :
3246 151862 : return res;
3247 : }
3248 :
3249 :
3250 : /*
3251 : * numeric_div_trunc() -
3252 : *
3253 : * Divide one numeric into another, truncating the result to an integer
3254 : */
3255 : Datum
3256 1218 : numeric_div_trunc(PG_FUNCTION_ARGS)
3257 : {
3258 1218 : Numeric num1 = PG_GETARG_NUMERIC(0);
3259 1218 : Numeric num2 = PG_GETARG_NUMERIC(1);
3260 : NumericVar arg1;
3261 : NumericVar arg2;
3262 : NumericVar result;
3263 : Numeric res;
3264 :
3265 : /*
3266 : * Handle NaN and infinities
3267 : */
3268 1218 : if (NUMERIC_IS_SPECIAL(num1) || NUMERIC_IS_SPECIAL(num2))
3269 : {
3270 198 : if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
3271 78 : PG_RETURN_NUMERIC(make_result(&const_nan));
3272 120 : if (NUMERIC_IS_PINF(num1))
3273 : {
3274 36 : if (NUMERIC_IS_SPECIAL(num2))
3275 12 : PG_RETURN_NUMERIC(make_result(&const_nan)); /* Inf / [-]Inf */
3276 24 : switch (numeric_sign_internal(num2))
3277 : {
3278 6 : case 0:
3279 6 : ereport(ERROR,
3280 : (errcode(ERRCODE_DIVISION_BY_ZERO),
3281 : errmsg("division by zero")));
3282 : break;
3283 12 : case 1:
3284 12 : PG_RETURN_NUMERIC(make_result(&const_pinf));
3285 6 : case -1:
3286 6 : PG_RETURN_NUMERIC(make_result(&const_ninf));
3287 : }
3288 84 : Assert(false);
3289 : }
3290 84 : if (NUMERIC_IS_NINF(num1))
3291 : {
3292 36 : if (NUMERIC_IS_SPECIAL(num2))
3293 12 : PG_RETURN_NUMERIC(make_result(&const_nan)); /* -Inf / [-]Inf */
3294 24 : switch (numeric_sign_internal(num2))
3295 : {
3296 6 : case 0:
3297 6 : ereport(ERROR,
3298 : (errcode(ERRCODE_DIVISION_BY_ZERO),
3299 : errmsg("division by zero")));
3300 : break;
3301 12 : case 1:
3302 12 : PG_RETURN_NUMERIC(make_result(&const_ninf));
3303 6 : case -1:
3304 6 : PG_RETURN_NUMERIC(make_result(&const_pinf));
3305 : }
3306 48 : Assert(false);
3307 : }
3308 : /* by here, num1 must be finite, so num2 is not */
3309 :
3310 : /*
3311 : * POSIX would have us return zero or minus zero if num1 is zero, and
3312 : * otherwise throw an underflow error. But the numeric type doesn't
3313 : * really do underflow, so let's just return zero.
3314 : */
3315 48 : PG_RETURN_NUMERIC(make_result(&const_zero));
3316 : }
3317 :
3318 : /*
3319 : * Unpack the arguments
3320 : */
3321 1020 : init_var_from_num(num1, &arg1);
3322 1020 : init_var_from_num(num2, &arg2);
3323 :
3324 1020 : init_var(&result);
3325 :
3326 : /*
3327 : * Do the divide and return the result
3328 : */
3329 1020 : div_var(&arg1, &arg2, &result, 0, false, true);
3330 :
3331 1014 : res = make_result(&result);
3332 :
3333 1014 : free_var(&result);
3334 :
3335 1014 : PG_RETURN_NUMERIC(res);
3336 : }
3337 :
3338 :
3339 : /*
3340 : * numeric_mod() -
3341 : *
3342 : * Calculate the modulo of two numerics
3343 : */
3344 : Datum
3345 53390 : numeric_mod(PG_FUNCTION_ARGS)
3346 : {
3347 53390 : Numeric num1 = PG_GETARG_NUMERIC(0);
3348 53390 : Numeric num2 = PG_GETARG_NUMERIC(1);
3349 : Numeric res;
3350 :
3351 53390 : res = numeric_mod_opt_error(num1, num2, NULL);
3352 :
3353 53372 : PG_RETURN_NUMERIC(res);
3354 : }
3355 :
3356 :
3357 : /*
3358 : * numeric_mod_opt_error() -
3359 : *
3360 : * Internal version of numeric_mod(). If "*have_error" flag is provided,
3361 : * on error it's set to true, NULL returned. This is helpful when caller
3362 : * need to handle errors by itself.
3363 : */
3364 : Numeric
3365 53402 : numeric_mod_opt_error(Numeric num1, Numeric num2, bool *have_error)
3366 : {
3367 : Numeric res;
3368 : NumericVar arg1;
3369 : NumericVar arg2;
3370 : NumericVar result;
3371 :
3372 53402 : if (have_error)
3373 0 : *have_error = false;
3374 :
3375 : /*
3376 : * Handle NaN and infinities. We follow POSIX fmod() on this, except that
3377 : * POSIX treats x-is-infinite and y-is-zero identically, raising EDOM and
3378 : * returning NaN. We choose to throw error only for y-is-zero.
3379 : */
3380 53402 : if (NUMERIC_IS_SPECIAL(num1) || NUMERIC_IS_SPECIAL(num2))
3381 : {
3382 198 : if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
3383 78 : return make_result(&const_nan);
3384 120 : if (NUMERIC_IS_INF(num1))
3385 : {
3386 72 : if (numeric_sign_internal(num2) == 0)
3387 : {
3388 12 : if (have_error)
3389 : {
3390 0 : *have_error = true;
3391 0 : return NULL;
3392 : }
3393 12 : ereport(ERROR,
3394 : (errcode(ERRCODE_DIVISION_BY_ZERO),
3395 : errmsg("division by zero")));
3396 : }
3397 : /* Inf % any nonzero = NaN */
3398 60 : return make_result(&const_nan);
3399 : }
3400 : /* num2 must be [-]Inf; result is num1 regardless of sign of num2 */
3401 48 : return duplicate_numeric(num1);
3402 : }
3403 :
3404 53204 : init_var_from_num(num1, &arg1);
3405 53204 : init_var_from_num(num2, &arg2);
3406 :
3407 53204 : init_var(&result);
3408 :
3409 : /*
3410 : * If "have_error" is provided, check for division by zero here
3411 : */
3412 53204 : if (have_error && (arg2.ndigits == 0 || arg2.digits[0] == 0))
3413 : {
3414 0 : *have_error = true;
3415 0 : return NULL;
3416 : }
3417 :
3418 53204 : mod_var(&arg1, &arg2, &result);
3419 :
3420 53192 : res = make_result_opt_error(&result, NULL);
3421 :
3422 53192 : free_var(&result);
3423 :
3424 53192 : return res;
3425 : }
3426 :
3427 :
3428 : /*
3429 : * numeric_inc() -
3430 : *
3431 : * Increment a number by one
3432 : */
3433 : Datum
3434 48 : numeric_inc(PG_FUNCTION_ARGS)
3435 : {
3436 48 : Numeric num = PG_GETARG_NUMERIC(0);
3437 : NumericVar arg;
3438 : Numeric res;
3439 :
3440 : /*
3441 : * Handle NaN and infinities
3442 : */
3443 48 : if (NUMERIC_IS_SPECIAL(num))
3444 18 : PG_RETURN_NUMERIC(duplicate_numeric(num));
3445 :
3446 : /*
3447 : * Compute the result and return it
3448 : */
3449 30 : init_var_from_num(num, &arg);
3450 :
3451 30 : add_var(&arg, &const_one, &arg);
3452 :
3453 30 : res = make_result(&arg);
3454 :
3455 30 : free_var(&arg);
3456 :
3457 30 : PG_RETURN_NUMERIC(res);
3458 : }
3459 :
3460 :
3461 : /*
3462 : * numeric_smaller() -
3463 : *
3464 : * Return the smaller of two numbers
3465 : */
3466 : Datum
3467 798 : numeric_smaller(PG_FUNCTION_ARGS)
3468 : {
3469 798 : Numeric num1 = PG_GETARG_NUMERIC(0);
3470 798 : Numeric num2 = PG_GETARG_NUMERIC(1);
3471 :
3472 : /*
3473 : * Use cmp_numerics so that this will agree with the comparison operators,
3474 : * particularly as regards comparisons involving NaN.
3475 : */
3476 798 : if (cmp_numerics(num1, num2) < 0)
3477 638 : PG_RETURN_NUMERIC(num1);
3478 : else
3479 160 : PG_RETURN_NUMERIC(num2);
3480 : }
3481 :
3482 :
3483 : /*
3484 : * numeric_larger() -
3485 : *
3486 : * Return the larger of two numbers
3487 : */
3488 : Datum
3489 18630 : numeric_larger(PG_FUNCTION_ARGS)
3490 : {
3491 18630 : Numeric num1 = PG_GETARG_NUMERIC(0);
3492 18630 : Numeric num2 = PG_GETARG_NUMERIC(1);
3493 :
3494 : /*
3495 : * Use cmp_numerics so that this will agree with the comparison operators,
3496 : * particularly as regards comparisons involving NaN.
3497 : */
3498 18630 : if (cmp_numerics(num1, num2) > 0)
3499 17878 : PG_RETURN_NUMERIC(num1);
3500 : else
3501 752 : PG_RETURN_NUMERIC(num2);
3502 : }
3503 :
3504 :
3505 : /* ----------------------------------------------------------------------
3506 : *
3507 : * Advanced math functions
3508 : *
3509 : * ----------------------------------------------------------------------
3510 : */
3511 :
3512 : /*
3513 : * numeric_gcd() -
3514 : *
3515 : * Calculate the greatest common divisor of two numerics
3516 : */
3517 : Datum
3518 216 : numeric_gcd(PG_FUNCTION_ARGS)
3519 : {
3520 216 : Numeric num1 = PG_GETARG_NUMERIC(0);
3521 216 : Numeric num2 = PG_GETARG_NUMERIC(1);
3522 : NumericVar arg1;
3523 : NumericVar arg2;
3524 : NumericVar result;
3525 : Numeric res;
3526 :
3527 : /*
3528 : * Handle NaN and infinities: we consider the result to be NaN in all such
3529 : * cases.
3530 : */
3531 216 : if (NUMERIC_IS_SPECIAL(num1) || NUMERIC_IS_SPECIAL(num2))
3532 96 : PG_RETURN_NUMERIC(make_result(&const_nan));
3533 :
3534 : /*
3535 : * Unpack the arguments
3536 : */
3537 120 : init_var_from_num(num1, &arg1);
3538 120 : init_var_from_num(num2, &arg2);
3539 :
3540 120 : init_var(&result);
3541 :
3542 : /*
3543 : * Find the GCD and return the result
3544 : */
3545 120 : gcd_var(&arg1, &arg2, &result);
3546 :
3547 120 : res = make_result(&result);
3548 :
3549 120 : free_var(&result);
3550 :
3551 120 : PG_RETURN_NUMERIC(res);
3552 : }
3553 :
3554 :
3555 : /*
3556 : * numeric_lcm() -
3557 : *
3558 : * Calculate the least common multiple of two numerics
3559 : */
3560 : Datum
3561 246 : numeric_lcm(PG_FUNCTION_ARGS)
3562 : {
3563 246 : Numeric num1 = PG_GETARG_NUMERIC(0);
3564 246 : Numeric num2 = PG_GETARG_NUMERIC(1);
3565 : NumericVar arg1;
3566 : NumericVar arg2;
3567 : NumericVar result;
3568 : Numeric res;
3569 :
3570 : /*
3571 : * Handle NaN and infinities: we consider the result to be NaN in all such
3572 : * cases.
3573 : */
3574 246 : if (NUMERIC_IS_SPECIAL(num1) || NUMERIC_IS_SPECIAL(num2))
3575 96 : PG_RETURN_NUMERIC(make_result(&const_nan));
3576 :
3577 : /*
3578 : * Unpack the arguments
3579 : */
3580 150 : init_var_from_num(num1, &arg1);
3581 150 : init_var_from_num(num2, &arg2);
3582 :
3583 150 : init_var(&result);
3584 :
3585 : /*
3586 : * Compute the result using lcm(x, y) = abs(x / gcd(x, y) * y), returning
3587 : * zero if either input is zero.
3588 : *
3589 : * Note that the division is guaranteed to be exact, returning an integer
3590 : * result, so the LCM is an integral multiple of both x and y. A display
3591 : * scale of Min(x.dscale, y.dscale) would be sufficient to represent it,
3592 : * but as with other numeric functions, we choose to return a result whose
3593 : * display scale is no smaller than either input.
3594 : */
3595 150 : if (arg1.ndigits == 0 || arg2.ndigits == 0)
3596 48 : set_var_from_var(&const_zero, &result);
3597 : else
3598 : {
3599 102 : gcd_var(&arg1, &arg2, &result);
3600 102 : div_var(&arg1, &result, &result, 0, false, true);
3601 102 : mul_var(&arg2, &result, &result, arg2.dscale);
3602 102 : result.sign = NUMERIC_POS;
3603 : }
3604 :
3605 150 : result.dscale = Max(arg1.dscale, arg2.dscale);
3606 :
3607 150 : res = make_result(&result);
3608 :
3609 144 : free_var(&result);
3610 :
3611 144 : PG_RETURN_NUMERIC(res);
3612 : }
3613 :
3614 :
3615 : /*
3616 : * numeric_fac()
3617 : *
3618 : * Compute factorial
3619 : */
3620 : Datum
3621 42 : numeric_fac(PG_FUNCTION_ARGS)
3622 : {
3623 42 : int64 num = PG_GETARG_INT64(0);
3624 : Numeric res;
3625 : NumericVar fact;
3626 : NumericVar result;
3627 :
3628 42 : if (num < 0)
3629 6 : ereport(ERROR,
3630 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
3631 : errmsg("factorial of a negative number is undefined")));
3632 36 : if (num <= 1)
3633 : {
3634 6 : res = make_result(&const_one);
3635 6 : PG_RETURN_NUMERIC(res);
3636 : }
3637 : /* Fail immediately if the result would overflow */
3638 30 : if (num > 32177)
3639 6 : ereport(ERROR,
3640 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
3641 : errmsg("value overflows numeric format")));
3642 :
3643 24 : init_var(&fact);
3644 24 : init_var(&result);
3645 :
3646 24 : int64_to_numericvar(num, &result);
3647 :
3648 294 : for (num = num - 1; num > 1; num--)
3649 : {
3650 : /* this loop can take awhile, so allow it to be interrupted */
3651 270 : CHECK_FOR_INTERRUPTS();
3652 :
3653 270 : int64_to_numericvar(num, &fact);
3654 :
3655 270 : mul_var(&result, &fact, &result, 0);
3656 : }
3657 :
3658 24 : res = make_result(&result);
3659 :
3660 24 : free_var(&fact);
3661 24 : free_var(&result);
3662 :
3663 24 : PG_RETURN_NUMERIC(res);
3664 : }
3665 :
3666 :
3667 : /*
3668 : * numeric_sqrt() -
3669 : *
3670 : * Compute the square root of a numeric.
3671 : */
3672 : Datum
3673 150 : numeric_sqrt(PG_FUNCTION_ARGS)
3674 : {
3675 150 : Numeric num = PG_GETARG_NUMERIC(0);
3676 : Numeric res;
3677 : NumericVar arg;
3678 : NumericVar result;
3679 : int sweight;
3680 : int rscale;
3681 :
3682 : /*
3683 : * Handle NaN and infinities
3684 : */
3685 150 : if (NUMERIC_IS_SPECIAL(num))
3686 : {
3687 : /* error should match that in sqrt_var() */
3688 18 : if (NUMERIC_IS_NINF(num))
3689 6 : ereport(ERROR,
3690 : (errcode(ERRCODE_INVALID_ARGUMENT_FOR_POWER_FUNCTION),
3691 : errmsg("cannot take square root of a negative number")));
3692 : /* For NAN or PINF, just duplicate the input */
3693 12 : PG_RETURN_NUMERIC(duplicate_numeric(num));
3694 : }
3695 :
3696 : /*
3697 : * Unpack the argument and determine the result scale. We choose a scale
3698 : * to give at least NUMERIC_MIN_SIG_DIGITS significant digits; but in any
3699 : * case not less than the input's dscale.
3700 : */
3701 132 : init_var_from_num(num, &arg);
3702 :
3703 132 : init_var(&result);
3704 :
3705 : /*
3706 : * Assume the input was normalized, so arg.weight is accurate. The result
3707 : * then has at least sweight = floor(arg.weight * DEC_DIGITS / 2 + 1)
3708 : * digits before the decimal point. When DEC_DIGITS is even, we can save
3709 : * a few cycles, since the division is exact and there is no need to round
3710 : * towards negative infinity.
3711 : */
3712 : #if DEC_DIGITS == ((DEC_DIGITS / 2) * 2)
3713 132 : sweight = arg.weight * DEC_DIGITS / 2 + 1;
3714 : #else
3715 : if (arg.weight >= 0)
3716 : sweight = arg.weight * DEC_DIGITS / 2 + 1;
3717 : else
3718 : sweight = 1 - (1 - arg.weight * DEC_DIGITS) / 2;
3719 : #endif
3720 :
3721 132 : rscale = NUMERIC_MIN_SIG_DIGITS - sweight;
3722 132 : rscale = Max(rscale, arg.dscale);
3723 132 : rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
3724 132 : rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
3725 :
3726 : /*
3727 : * Let sqrt_var() do the calculation and return the result.
3728 : */
3729 132 : sqrt_var(&arg, &result, rscale);
3730 :
3731 126 : res = make_result(&result);
3732 :
3733 126 : free_var(&result);
3734 :
3735 126 : PG_RETURN_NUMERIC(res);
3736 : }
3737 :
3738 :
3739 : /*
3740 : * numeric_exp() -
3741 : *
3742 : * Raise e to the power of x
3743 : */
3744 : Datum
3745 78 : numeric_exp(PG_FUNCTION_ARGS)
3746 : {
3747 78 : Numeric num = PG_GETARG_NUMERIC(0);
3748 : Numeric res;
3749 : NumericVar arg;
3750 : NumericVar result;
3751 : int rscale;
3752 : double val;
3753 :
3754 : /*
3755 : * Handle NaN and infinities
3756 : */
3757 78 : if (NUMERIC_IS_SPECIAL(num))
3758 : {
3759 : /* Per POSIX, exp(-Inf) is zero */
3760 18 : if (NUMERIC_IS_NINF(num))
3761 6 : PG_RETURN_NUMERIC(make_result(&const_zero));
3762 : /* For NAN or PINF, just duplicate the input */
3763 12 : PG_RETURN_NUMERIC(duplicate_numeric(num));
3764 : }
3765 :
3766 : /*
3767 : * Unpack the argument and determine the result scale. We choose a scale
3768 : * to give at least NUMERIC_MIN_SIG_DIGITS significant digits; but in any
3769 : * case not less than the input's dscale.
3770 : */
3771 60 : init_var_from_num(num, &arg);
3772 :
3773 60 : init_var(&result);
3774 :
3775 : /* convert input to float8, ignoring overflow */
3776 60 : val = numericvar_to_double_no_overflow(&arg);
3777 :
3778 : /*
3779 : * log10(result) = num * log10(e), so this is approximately the decimal
3780 : * weight of the result:
3781 : */
3782 60 : val *= 0.434294481903252;
3783 :
3784 : /* limit to something that won't cause integer overflow */
3785 60 : val = Max(val, -NUMERIC_MAX_RESULT_SCALE);
3786 60 : val = Min(val, NUMERIC_MAX_RESULT_SCALE);
3787 :
3788 60 : rscale = NUMERIC_MIN_SIG_DIGITS - (int) val;
3789 60 : rscale = Max(rscale, arg.dscale);
3790 60 : rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
3791 60 : rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
3792 :
3793 : /*
3794 : * Let exp_var() do the calculation and return the result.
3795 : */
3796 60 : exp_var(&arg, &result, rscale);
3797 :
3798 60 : res = make_result(&result);
3799 :
3800 60 : free_var(&result);
3801 :
3802 60 : PG_RETURN_NUMERIC(res);
3803 : }
3804 :
3805 :
3806 : /*
3807 : * numeric_ln() -
3808 : *
3809 : * Compute the natural logarithm of x
3810 : */
3811 : Datum
3812 198 : numeric_ln(PG_FUNCTION_ARGS)
3813 : {
3814 198 : Numeric num = PG_GETARG_NUMERIC(0);
3815 : Numeric res;
3816 : NumericVar arg;
3817 : NumericVar result;
3818 : int ln_dweight;
3819 : int rscale;
3820 :
3821 : /*
3822 : * Handle NaN and infinities
3823 : */
3824 198 : if (NUMERIC_IS_SPECIAL(num))
3825 : {
3826 18 : if (NUMERIC_IS_NINF(num))
3827 6 : ereport(ERROR,
3828 : (errcode(ERRCODE_INVALID_ARGUMENT_FOR_LOG),
3829 : errmsg("cannot take logarithm of a negative number")));
3830 : /* For NAN or PINF, just duplicate the input */
3831 12 : PG_RETURN_NUMERIC(duplicate_numeric(num));
3832 : }
3833 :
3834 180 : init_var_from_num(num, &arg);
3835 180 : init_var(&result);
3836 :
3837 : /* Estimated dweight of logarithm */
3838 180 : ln_dweight = estimate_ln_dweight(&arg);
3839 :
3840 180 : rscale = NUMERIC_MIN_SIG_DIGITS - ln_dweight;
3841 180 : rscale = Max(rscale, arg.dscale);
3842 180 : rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
3843 180 : rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
3844 :
3845 180 : ln_var(&arg, &result, rscale);
3846 :
3847 156 : res = make_result(&result);
3848 :
3849 156 : free_var(&result);
3850 :
3851 156 : PG_RETURN_NUMERIC(res);
3852 : }
3853 :
3854 :
3855 : /*
3856 : * numeric_log() -
3857 : *
3858 : * Compute the logarithm of x in a given base
3859 : */
3860 : Datum
3861 342 : numeric_log(PG_FUNCTION_ARGS)
3862 : {
3863 342 : Numeric num1 = PG_GETARG_NUMERIC(0);
3864 342 : Numeric num2 = PG_GETARG_NUMERIC(1);
3865 : Numeric res;
3866 : NumericVar arg1;
3867 : NumericVar arg2;
3868 : NumericVar result;
3869 :
3870 : /*
3871 : * Handle NaN and infinities
3872 : */
3873 342 : if (NUMERIC_IS_SPECIAL(num1) || NUMERIC_IS_SPECIAL(num2))
3874 : {
3875 : int sign1,
3876 : sign2;
3877 :
3878 126 : if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
3879 54 : PG_RETURN_NUMERIC(make_result(&const_nan));
3880 : /* fail on negative inputs including -Inf, as log_var would */
3881 72 : sign1 = numeric_sign_internal(num1);
3882 72 : sign2 = numeric_sign_internal(num2);
3883 72 : if (sign1 < 0 || sign2 < 0)
3884 24 : ereport(ERROR,
3885 : (errcode(ERRCODE_INVALID_ARGUMENT_FOR_LOG),
3886 : errmsg("cannot take logarithm of a negative number")));
3887 : /* fail on zero inputs, as log_var would */
3888 48 : if (sign1 == 0 || sign2 == 0)
3889 6 : ereport(ERROR,
3890 : (errcode(ERRCODE_INVALID_ARGUMENT_FOR_LOG),
3891 : errmsg("cannot take logarithm of zero")));
3892 42 : if (NUMERIC_IS_PINF(num1))
3893 : {
3894 : /* log(Inf, Inf) reduces to Inf/Inf, so it's NaN */
3895 18 : if (NUMERIC_IS_PINF(num2))
3896 6 : PG_RETURN_NUMERIC(make_result(&const_nan));
3897 : /* log(Inf, finite-positive) is zero (we don't throw underflow) */
3898 12 : PG_RETURN_NUMERIC(make_result(&const_zero));
3899 : }
3900 : Assert(NUMERIC_IS_PINF(num2));
3901 : /* log(finite-positive, Inf) is Inf */
3902 24 : PG_RETURN_NUMERIC(make_result(&const_pinf));
3903 : }
3904 :
3905 : /*
3906 : * Initialize things
3907 : */
3908 216 : init_var_from_num(num1, &arg1);
3909 216 : init_var_from_num(num2, &arg2);
3910 216 : init_var(&result);
3911 :
3912 : /*
3913 : * Call log_var() to compute and return the result; note it handles scale
3914 : * selection itself.
3915 : */
3916 216 : log_var(&arg1, &arg2, &result);
3917 :
3918 156 : res = make_result(&result);
3919 :
3920 156 : free_var(&result);
3921 :
3922 156 : PG_RETURN_NUMERIC(res);
3923 : }
3924 :
3925 :
3926 : /*
3927 : * numeric_power() -
3928 : *
3929 : * Raise x to the power of y
3930 : */
3931 : Datum
3932 1644 : numeric_power(PG_FUNCTION_ARGS)
3933 : {
3934 1644 : Numeric num1 = PG_GETARG_NUMERIC(0);
3935 1644 : Numeric num2 = PG_GETARG_NUMERIC(1);
3936 : Numeric res;
3937 : NumericVar arg1;
3938 : NumericVar arg2;
3939 : NumericVar result;
3940 : int sign1,
3941 : sign2;
3942 :
3943 : /*
3944 : * Handle NaN and infinities
3945 : */
3946 1644 : if (NUMERIC_IS_SPECIAL(num1) || NUMERIC_IS_SPECIAL(num2))
3947 : {
3948 : /*
3949 : * We follow the POSIX spec for pow(3), which says that NaN ^ 0 = 1,
3950 : * and 1 ^ NaN = 1, while all other cases with NaN inputs yield NaN
3951 : * (with no error).
3952 : */
3953 234 : if (NUMERIC_IS_NAN(num1))
3954 : {
3955 54 : if (!NUMERIC_IS_SPECIAL(num2))
3956 : {
3957 36 : init_var_from_num(num2, &arg2);
3958 36 : if (cmp_var(&arg2, &const_zero) == 0)
3959 12 : PG_RETURN_NUMERIC(make_result(&const_one));
3960 : }
3961 42 : PG_RETURN_NUMERIC(make_result(&const_nan));
3962 : }
3963 180 : if (NUMERIC_IS_NAN(num2))
3964 : {
3965 42 : if (!NUMERIC_IS_SPECIAL(num1))
3966 : {
3967 36 : init_var_from_num(num1, &arg1);
3968 36 : if (cmp_var(&arg1, &const_one) == 0)
3969 12 : PG_RETURN_NUMERIC(make_result(&const_one));
3970 : }
3971 30 : PG_RETURN_NUMERIC(make_result(&const_nan));
3972 : }
3973 : /* At least one input is infinite, but error rules still apply */
3974 138 : sign1 = numeric_sign_internal(num1);
3975 138 : sign2 = numeric_sign_internal(num2);
3976 138 : if (sign1 == 0 && sign2 < 0)
3977 6 : ereport(ERROR,
3978 : (errcode(ERRCODE_INVALID_ARGUMENT_FOR_POWER_FUNCTION),
3979 : errmsg("zero raised to a negative power is undefined")));
3980 132 : if (sign1 < 0 && !numeric_is_integral(num2))
3981 6 : ereport(ERROR,
3982 : (errcode(ERRCODE_INVALID_ARGUMENT_FOR_POWER_FUNCTION),
3983 : errmsg("a negative number raised to a non-integer power yields a complex result")));
3984 :
3985 : /*
3986 : * POSIX gives this series of rules for pow(3) with infinite inputs:
3987 : *
3988 : * For any value of y, if x is +1, 1.0 shall be returned.
3989 : */
3990 126 : if (!NUMERIC_IS_SPECIAL(num1))
3991 : {
3992 42 : init_var_from_num(num1, &arg1);
3993 42 : if (cmp_var(&arg1, &const_one) == 0)
3994 6 : PG_RETURN_NUMERIC(make_result(&const_one));
3995 : }
3996 :
3997 : /*
3998 : * For any value of x, if y is [-]0, 1.0 shall be returned.
3999 : */
4000 120 : if (sign2 == 0)
4001 12 : PG_RETURN_NUMERIC(make_result(&const_one));
4002 :
4003 : /*
4004 : * For any odd integer value of y > 0, if x is [-]0, [-]0 shall be
4005 : * returned. For y > 0 and not an odd integer, if x is [-]0, +0 shall
4006 : * be returned. (Since we don't deal in minus zero, we need not
4007 : * distinguish these two cases.)
4008 : */
4009 108 : if (sign1 == 0 && sign2 > 0)
4010 6 : PG_RETURN_NUMERIC(make_result(&const_zero));
4011 :
4012 : /*
4013 : * If x is -1, and y is [-]Inf, 1.0 shall be returned.
4014 : *
4015 : * For |x| < 1, if y is -Inf, +Inf shall be returned.
4016 : *
4017 : * For |x| > 1, if y is -Inf, +0 shall be returned.
4018 : *
4019 : * For |x| < 1, if y is +Inf, +0 shall be returned.
4020 : *
4021 : * For |x| > 1, if y is +Inf, +Inf shall be returned.
4022 : */
4023 102 : if (NUMERIC_IS_INF(num2))
4024 : {
4025 : bool abs_x_gt_one;
4026 :
4027 54 : if (NUMERIC_IS_SPECIAL(num1))
4028 24 : abs_x_gt_one = true; /* x is either Inf or -Inf */
4029 : else
4030 : {
4031 30 : init_var_from_num(num1, &arg1);
4032 30 : if (cmp_var(&arg1, &const_minus_one) == 0)
4033 6 : PG_RETURN_NUMERIC(make_result(&const_one));
4034 24 : arg1.sign = NUMERIC_POS; /* now arg1 = abs(x) */
4035 24 : abs_x_gt_one = (cmp_var(&arg1, &const_one) > 0);
4036 : }
4037 48 : if (abs_x_gt_one == (sign2 > 0))
4038 30 : PG_RETURN_NUMERIC(make_result(&const_pinf));
4039 : else
4040 18 : PG_RETURN_NUMERIC(make_result(&const_zero));
4041 : }
4042 :
4043 : /*
4044 : * For y < 0, if x is +Inf, +0 shall be returned.
4045 : *
4046 : * For y > 0, if x is +Inf, +Inf shall be returned.
4047 : */
4048 48 : if (NUMERIC_IS_PINF(num1))
4049 : {
4050 24 : if (sign2 > 0)
4051 18 : PG_RETURN_NUMERIC(make_result(&const_pinf));
4052 : else
4053 6 : PG_RETURN_NUMERIC(make_result(&const_zero));
4054 : }
4055 :
4056 : Assert(NUMERIC_IS_NINF(num1));
4057 :
4058 : /*
4059 : * For y an odd integer < 0, if x is -Inf, -0 shall be returned. For
4060 : * y < 0 and not an odd integer, if x is -Inf, +0 shall be returned.
4061 : * (Again, we need not distinguish these two cases.)
4062 : */
4063 24 : if (sign2 < 0)
4064 12 : PG_RETURN_NUMERIC(make_result(&const_zero));
4065 :
4066 : /*
4067 : * For y an odd integer > 0, if x is -Inf, -Inf shall be returned. For
4068 : * y > 0 and not an odd integer, if x is -Inf, +Inf shall be returned.
4069 : */
4070 12 : init_var_from_num(num2, &arg2);
4071 12 : if (arg2.ndigits > 0 && arg2.ndigits == arg2.weight + 1 &&
4072 12 : (arg2.digits[arg2.ndigits - 1] & 1))
4073 6 : PG_RETURN_NUMERIC(make_result(&const_ninf));
4074 : else
4075 6 : PG_RETURN_NUMERIC(make_result(&const_pinf));
4076 : }
4077 :
4078 : /*
4079 : * The SQL spec requires that we emit a particular SQLSTATE error code for
4080 : * certain error conditions. Specifically, we don't return a
4081 : * divide-by-zero error code for 0 ^ -1. Raising a negative number to a
4082 : * non-integer power must produce the same error code, but that case is
4083 : * handled in power_var().
4084 : */
4085 1410 : sign1 = numeric_sign_internal(num1);
4086 1410 : sign2 = numeric_sign_internal(num2);
4087 :
4088 1410 : if (sign1 == 0 && sign2 < 0)
4089 12 : ereport(ERROR,
4090 : (errcode(ERRCODE_INVALID_ARGUMENT_FOR_POWER_FUNCTION),
4091 : errmsg("zero raised to a negative power is undefined")));
4092 :
4093 : /*
4094 : * Initialize things
4095 : */
4096 1398 : init_var(&result);
4097 1398 : init_var_from_num(num1, &arg1);
4098 1398 : init_var_from_num(num2, &arg2);
4099 :
4100 : /*
4101 : * Call power_var() to compute and return the result; note it handles
4102 : * scale selection itself.
4103 : */
4104 1398 : power_var(&arg1, &arg2, &result);
4105 :
4106 1368 : res = make_result(&result);
4107 :
4108 1368 : free_var(&result);
4109 :
4110 1368 : PG_RETURN_NUMERIC(res);
4111 : }
4112 :
4113 : /*
4114 : * numeric_scale() -
4115 : *
4116 : * Returns the scale, i.e. the count of decimal digits in the fractional part
4117 : */
4118 : Datum
4119 108 : numeric_scale(PG_FUNCTION_ARGS)
4120 : {
4121 108 : Numeric num = PG_GETARG_NUMERIC(0);
4122 :
4123 108 : if (NUMERIC_IS_SPECIAL(num))
4124 18 : PG_RETURN_NULL();
4125 :
4126 90 : PG_RETURN_INT32(NUMERIC_DSCALE(num));
4127 : }
4128 :
4129 : /*
4130 : * Calculate minimum scale for value.
4131 : */
4132 : static int
4133 372 : get_min_scale(NumericVar *var)
4134 : {
4135 : int min_scale;
4136 : int last_digit_pos;
4137 :
4138 : /*
4139 : * Ordinarily, the input value will be "stripped" so that the last
4140 : * NumericDigit is nonzero. But we don't want to get into an infinite
4141 : * loop if it isn't, so explicitly find the last nonzero digit.
4142 : */
4143 372 : last_digit_pos = var->ndigits - 1;
4144 372 : while (last_digit_pos >= 0 &&
4145 342 : var->digits[last_digit_pos] == 0)
4146 0 : last_digit_pos--;
4147 :
4148 372 : if (last_digit_pos >= 0)
4149 : {
4150 : /* compute min_scale assuming that last ndigit has no zeroes */
4151 342 : min_scale = (last_digit_pos - var->weight) * DEC_DIGITS;
4152 :
4153 : /*
4154 : * We could get a negative result if there are no digits after the
4155 : * decimal point. In this case the min_scale must be zero.
4156 : */
4157 342 : if (min_scale > 0)
4158 : {
4159 : /*
4160 : * Reduce min_scale if trailing digit(s) in last NumericDigit are
4161 : * zero.
4162 : */
4163 186 : NumericDigit last_digit = var->digits[last_digit_pos];
4164 :
4165 498 : while (last_digit % 10 == 0)
4166 : {
4167 312 : min_scale--;
4168 312 : last_digit /= 10;
4169 : }
4170 : }
4171 : else
4172 156 : min_scale = 0;
4173 : }
4174 : else
4175 30 : min_scale = 0; /* result if input is zero */
4176 :
4177 372 : return min_scale;
4178 : }
4179 :
4180 : /*
4181 : * Returns minimum scale required to represent supplied value without loss.
4182 : */
4183 : Datum
4184 72 : numeric_min_scale(PG_FUNCTION_ARGS)
4185 : {
4186 72 : Numeric num = PG_GETARG_NUMERIC(0);
4187 : NumericVar arg;
4188 : int min_scale;
4189 :
4190 72 : if (NUMERIC_IS_SPECIAL(num))
4191 12 : PG_RETURN_NULL();
4192 :
4193 60 : init_var_from_num(num, &arg);
4194 60 : min_scale = get_min_scale(&arg);
4195 60 : free_var(&arg);
4196 :
4197 60 : PG_RETURN_INT32(min_scale);
4198 : }
4199 :
4200 : /*
4201 : * Reduce scale of numeric value to represent supplied value without loss.
4202 : */
4203 : Datum
4204 324 : numeric_trim_scale(PG_FUNCTION_ARGS)
4205 : {
4206 324 : Numeric num = PG_GETARG_NUMERIC(0);
4207 : Numeric res;
4208 : NumericVar result;
4209 :
4210 324 : if (NUMERIC_IS_SPECIAL(num))
4211 12 : PG_RETURN_NUMERIC(duplicate_numeric(num));
4212 :
4213 312 : init_var_from_num(num, &result);
4214 312 : result.dscale = get_min_scale(&result);
4215 312 : res = make_result(&result);
4216 312 : free_var(&result);
4217 :
4218 312 : PG_RETURN_NUMERIC(res);
4219 : }
4220 :
4221 : /*
4222 : * Return a random numeric value in the range [rmin, rmax].
4223 : */
4224 : Numeric
4225 33462 : random_numeric(pg_prng_state *state, Numeric rmin, Numeric rmax)
4226 : {
4227 : NumericVar rmin_var;
4228 : NumericVar rmax_var;
4229 : NumericVar result;
4230 : Numeric res;
4231 :
4232 : /* Range bounds must not be NaN/infinity */
4233 33462 : if (NUMERIC_IS_SPECIAL(rmin))
4234 : {
4235 12 : if (NUMERIC_IS_NAN(rmin))
4236 6 : ereport(ERROR,
4237 : errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4238 : errmsg("lower bound cannot be NaN"));
4239 : else
4240 6 : ereport(ERROR,
4241 : errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4242 : errmsg("lower bound cannot be infinity"));
4243 : }
4244 33450 : if (NUMERIC_IS_SPECIAL(rmax))
4245 : {
4246 12 : if (NUMERIC_IS_NAN(rmax))
4247 6 : ereport(ERROR,
4248 : errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4249 : errmsg("upper bound cannot be NaN"));
4250 : else
4251 6 : ereport(ERROR,
4252 : errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4253 : errmsg("upper bound cannot be infinity"));
4254 : }
4255 :
4256 : /* Return a random value in the range [rmin, rmax] */
4257 33438 : init_var_from_num(rmin, &rmin_var);
4258 33438 : init_var_from_num(rmax, &rmax_var);
4259 :
4260 33438 : init_var(&result);
4261 :
4262 33438 : random_var(state, &rmin_var, &rmax_var, &result);
4263 :
4264 33432 : res = make_result(&result);
4265 :
4266 33432 : free_var(&result);
4267 :
4268 33432 : return res;
4269 : }
4270 :
4271 :
4272 : /* ----------------------------------------------------------------------
4273 : *
4274 : * Type conversion functions
4275 : *
4276 : * ----------------------------------------------------------------------
4277 : */
4278 :
4279 : Numeric
4280 1848664 : int64_to_numeric(int64 val)
4281 : {
4282 : Numeric res;
4283 : NumericVar result;
4284 :
4285 1848664 : init_var(&result);
4286 :
4287 1848664 : int64_to_numericvar(val, &result);
4288 :
4289 1848664 : res = make_result(&result);
4290 :
4291 1848664 : free_var(&result);
4292 :
4293 1848664 : return res;
4294 : }
4295 :
4296 : /*
4297 : * Convert val1/(10**log10val2) to numeric. This is much faster than normal
4298 : * numeric division.
4299 : */
4300 : Numeric
4301 29380 : int64_div_fast_to_numeric(int64 val1, int log10val2)
4302 : {
4303 : Numeric res;
4304 : NumericVar result;
4305 : int rscale;
4306 : int w;
4307 : int m;
4308 :
4309 29380 : init_var(&result);
4310 :
4311 : /* result scale */
4312 29380 : rscale = log10val2 < 0 ? 0 : log10val2;
4313 :
4314 : /* how much to decrease the weight by */
4315 29380 : w = log10val2 / DEC_DIGITS;
4316 : /* how much is left to divide by */
4317 29380 : m = log10val2 % DEC_DIGITS;
4318 29380 : if (m < 0)
4319 : {
4320 0 : m += DEC_DIGITS;
4321 0 : w--;
4322 : }
4323 :
4324 : /*
4325 : * If there is anything left to divide by (10^m with 0 < m < DEC_DIGITS),
4326 : * multiply the dividend by 10^(DEC_DIGITS - m), and shift the weight by
4327 : * one more.
4328 : */
4329 29380 : if (m > 0)
4330 : {
4331 : #if DEC_DIGITS == 4
4332 : static const int pow10[] = {1, 10, 100, 1000};
4333 : #elif DEC_DIGITS == 2
4334 : static const int pow10[] = {1, 10};
4335 : #elif DEC_DIGITS == 1
4336 : static const int pow10[] = {1};
4337 : #else
4338 : #error unsupported NBASE
4339 : #endif
4340 29380 : int64 factor = pow10[DEC_DIGITS - m];
4341 : int64 new_val1;
4342 :
4343 : StaticAssertDecl(lengthof(pow10) == DEC_DIGITS, "mismatch with DEC_DIGITS");
4344 :
4345 29380 : if (unlikely(pg_mul_s64_overflow(val1, factor, &new_val1)))
4346 : {
4347 : #ifdef HAVE_INT128
4348 : /* do the multiplication using 128-bit integers */
4349 : int128 tmp;
4350 :
4351 12 : tmp = (int128) val1 * (int128) factor;
4352 :
4353 12 : int128_to_numericvar(tmp, &result);
4354 : #else
4355 : /* do the multiplication using numerics */
4356 : NumericVar tmp;
4357 :
4358 : init_var(&tmp);
4359 :
4360 : int64_to_numericvar(val1, &result);
4361 : int64_to_numericvar(factor, &tmp);
4362 : mul_var(&result, &tmp, &result, 0);
4363 :
4364 : free_var(&tmp);
4365 : #endif
4366 : }
4367 : else
4368 29368 : int64_to_numericvar(new_val1, &result);
4369 :
4370 29380 : w++;
4371 : }
4372 : else
4373 0 : int64_to_numericvar(val1, &result);
4374 :
4375 29380 : result.weight -= w;
4376 29380 : result.dscale = rscale;
4377 :
4378 29380 : res = make_result(&result);
4379 :
4380 29380 : free_var(&result);
4381 :
4382 29380 : return res;
4383 : }
4384 :
4385 : Datum
4386 1530668 : int4_numeric(PG_FUNCTION_ARGS)
4387 : {
4388 1530668 : int32 val = PG_GETARG_INT32(0);
4389 :
4390 1530668 : PG_RETURN_NUMERIC(int64_to_numeric(val));
4391 : }
4392 :
4393 : int32
4394 7680 : numeric_int4_opt_error(Numeric num, bool *have_error)
4395 : {
4396 : NumericVar x;
4397 : int32 result;
4398 :
4399 7680 : if (have_error)
4400 1584 : *have_error = false;
4401 :
4402 7680 : if (NUMERIC_IS_SPECIAL(num))
4403 : {
4404 18 : if (have_error)
4405 : {
4406 0 : *have_error = true;
4407 0 : return 0;
4408 : }
4409 : else
4410 : {
4411 18 : if (NUMERIC_IS_NAN(num))
4412 6 : ereport(ERROR,
4413 : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4414 : errmsg("cannot convert NaN to %s", "integer")));
4415 : else
4416 12 : ereport(ERROR,
4417 : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4418 : errmsg("cannot convert infinity to %s", "integer")));
4419 : }
4420 : }
4421 :
4422 : /* Convert to variable format, then convert to int4 */
4423 7662 : init_var_from_num(num, &x);
4424 :
4425 7662 : if (!numericvar_to_int32(&x, &result))
4426 : {
4427 90 : if (have_error)
4428 : {
4429 78 : *have_error = true;
4430 78 : return 0;
4431 : }
4432 : else
4433 : {
4434 12 : ereport(ERROR,
4435 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
4436 : errmsg("integer out of range")));
4437 : }
4438 : }
4439 :
4440 7572 : return result;
4441 : }
4442 :
4443 : Datum
4444 6096 : numeric_int4(PG_FUNCTION_ARGS)
4445 : {
4446 6096 : Numeric num = PG_GETARG_NUMERIC(0);
4447 :
4448 6096 : PG_RETURN_INT32(numeric_int4_opt_error(num, NULL));
4449 : }
4450 :
4451 : /*
4452 : * Given a NumericVar, convert it to an int32. If the NumericVar
4453 : * exceeds the range of an int32, false is returned, otherwise true is returned.
4454 : * The input NumericVar is *not* free'd.
4455 : */
4456 : static bool
4457 8400 : numericvar_to_int32(const NumericVar *var, int32 *result)
4458 : {
4459 : int64 val;
4460 :
4461 8400 : if (!numericvar_to_int64(var, &val))
4462 6 : return false;
4463 :
4464 8394 : if (unlikely(val < PG_INT32_MIN) || unlikely(val > PG_INT32_MAX))
4465 84 : return false;
4466 :
4467 : /* Down-convert to int4 */
4468 8310 : *result = (int32) val;
4469 :
4470 8310 : return true;
4471 : }
4472 :
4473 : Datum
4474 36850 : int8_numeric(PG_FUNCTION_ARGS)
4475 : {
4476 36850 : int64 val = PG_GETARG_INT64(0);
4477 :
4478 36850 : PG_RETURN_NUMERIC(int64_to_numeric(val));
4479 : }
4480 :
4481 : int64
4482 564 : numeric_int8_opt_error(Numeric num, bool *have_error)
4483 : {
4484 : NumericVar x;
4485 : int64 result;
4486 :
4487 564 : if (have_error)
4488 48 : *have_error = false;
4489 :
4490 564 : if (NUMERIC_IS_SPECIAL(num))
4491 : {
4492 18 : if (have_error)
4493 : {
4494 0 : *have_error = true;
4495 0 : return 0;
4496 : }
4497 : else
4498 : {
4499 18 : if (NUMERIC_IS_NAN(num))
4500 6 : ereport(ERROR,
4501 : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4502 : errmsg("cannot convert NaN to %s", "bigint")));
4503 : else
4504 12 : ereport(ERROR,
4505 : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4506 : errmsg("cannot convert infinity to %s", "bigint")));
4507 : }
4508 : }
4509 :
4510 : /* Convert to variable format, then convert to int8 */
4511 546 : init_var_from_num(num, &x);
4512 :
4513 546 : if (!numericvar_to_int64(&x, &result))
4514 : {
4515 60 : if (have_error)
4516 : {
4517 12 : *have_error = true;
4518 12 : return 0;
4519 : }
4520 : else
4521 : {
4522 48 : ereport(ERROR,
4523 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
4524 : errmsg("bigint out of range")));
4525 : }
4526 : }
4527 :
4528 486 : return result;
4529 : }
4530 :
4531 : Datum
4532 516 : numeric_int8(PG_FUNCTION_ARGS)
4533 : {
4534 516 : Numeric num = PG_GETARG_NUMERIC(0);
4535 :
4536 516 : PG_RETURN_INT64(numeric_int8_opt_error(num, NULL));
4537 : }
4538 :
4539 :
4540 : Datum
4541 6 : int2_numeric(PG_FUNCTION_ARGS)
4542 : {
4543 6 : int16 val = PG_GETARG_INT16(0);
4544 :
4545 6 : PG_RETURN_NUMERIC(int64_to_numeric(val));
4546 : }
4547 :
4548 :
4549 : Datum
4550 96 : numeric_int2(PG_FUNCTION_ARGS)
4551 : {
4552 96 : Numeric num = PG_GETARG_NUMERIC(0);
4553 : NumericVar x;
4554 : int64 val;
4555 : int16 result;
4556 :
4557 96 : if (NUMERIC_IS_SPECIAL(num))
4558 : {
4559 18 : if (NUMERIC_IS_NAN(num))
4560 6 : ereport(ERROR,
4561 : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4562 : errmsg("cannot convert NaN to %s", "smallint")));
4563 : else
4564 12 : ereport(ERROR,
4565 : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4566 : errmsg("cannot convert infinity to %s", "smallint")));
4567 : }
4568 :
4569 : /* Convert to variable format and thence to int8 */
4570 78 : init_var_from_num(num, &x);
4571 :
4572 78 : if (!numericvar_to_int64(&x, &val))
4573 0 : ereport(ERROR,
4574 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
4575 : errmsg("smallint out of range")));
4576 :
4577 78 : if (unlikely(val < PG_INT16_MIN) || unlikely(val > PG_INT16_MAX))
4578 12 : ereport(ERROR,
4579 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
4580 : errmsg("smallint out of range")));
4581 :
4582 : /* Down-convert to int2 */
4583 66 : result = (int16) val;
4584 :
4585 66 : PG_RETURN_INT16(result);
4586 : }
4587 :
4588 :
4589 : Datum
4590 1074 : float8_numeric(PG_FUNCTION_ARGS)
4591 : {
4592 1074 : float8 val = PG_GETARG_FLOAT8(0);
4593 : Numeric res;
4594 : NumericVar result;
4595 : char buf[DBL_DIG + 100];
4596 : const char *endptr;
4597 :
4598 1074 : if (isnan(val))
4599 6 : PG_RETURN_NUMERIC(make_result(&const_nan));
4600 :
4601 1068 : if (isinf(val))
4602 : {
4603 12 : if (val < 0)
4604 6 : PG_RETURN_NUMERIC(make_result(&const_ninf));
4605 : else
4606 6 : PG_RETURN_NUMERIC(make_result(&const_pinf));
4607 : }
4608 :
4609 1056 : snprintf(buf, sizeof(buf), "%.*g", DBL_DIG, val);
4610 :
4611 1056 : init_var(&result);
4612 :
4613 : /* Assume we need not worry about leading/trailing spaces */
4614 1056 : (void) set_var_from_str(buf, buf, &result, &endptr, NULL);
4615 :
4616 1056 : res = make_result(&result);
4617 :
4618 1056 : free_var(&result);
4619 :
4620 1056 : PG_RETURN_NUMERIC(res);
4621 : }
4622 :
4623 :
4624 : Datum
4625 519450 : numeric_float8(PG_FUNCTION_ARGS)
4626 : {
4627 519450 : Numeric num = PG_GETARG_NUMERIC(0);
4628 : char *tmp;
4629 : Datum result;
4630 :
4631 519450 : if (NUMERIC_IS_SPECIAL(num))
4632 : {
4633 78 : if (NUMERIC_IS_PINF(num))
4634 24 : PG_RETURN_FLOAT8(get_float8_infinity());
4635 54 : else if (NUMERIC_IS_NINF(num))
4636 24 : PG_RETURN_FLOAT8(-get_float8_infinity());
4637 : else
4638 30 : PG_RETURN_FLOAT8(get_float8_nan());
4639 : }
4640 :
4641 519372 : tmp = DatumGetCString(DirectFunctionCall1(numeric_out,
4642 : NumericGetDatum(num)));
4643 :
4644 519372 : result = DirectFunctionCall1(float8in, CStringGetDatum(tmp));
4645 :
4646 519372 : pfree(tmp);
4647 :
4648 519372 : PG_RETURN_DATUM(result);
4649 : }
4650 :
4651 :
4652 : /*
4653 : * Convert numeric to float8; if out of range, return +/- HUGE_VAL
4654 : *
4655 : * (internal helper function, not directly callable from SQL)
4656 : */
4657 : Datum
4658 3100 : numeric_float8_no_overflow(PG_FUNCTION_ARGS)
4659 : {
4660 3100 : Numeric num = PG_GETARG_NUMERIC(0);
4661 : double val;
4662 :
4663 3100 : if (NUMERIC_IS_SPECIAL(num))
4664 : {
4665 0 : if (NUMERIC_IS_PINF(num))
4666 0 : val = HUGE_VAL;
4667 0 : else if (NUMERIC_IS_NINF(num))
4668 0 : val = -HUGE_VAL;
4669 : else
4670 0 : val = get_float8_nan();
4671 : }
4672 : else
4673 : {
4674 : NumericVar x;
4675 :
4676 3100 : init_var_from_num(num, &x);
4677 3100 : val = numericvar_to_double_no_overflow(&x);
4678 : }
4679 :
4680 3100 : PG_RETURN_FLOAT8(val);
4681 : }
4682 :
4683 : Datum
4684 21942 : float4_numeric(PG_FUNCTION_ARGS)
4685 : {
4686 21942 : float4 val = PG_GETARG_FLOAT4(0);
4687 : Numeric res;
4688 : NumericVar result;
4689 : char buf[FLT_DIG + 100];
4690 : const char *endptr;
4691 :
4692 21942 : if (isnan(val))
4693 6 : PG_RETURN_NUMERIC(make_result(&const_nan));
4694 :
4695 21936 : if (isinf(val))
4696 : {
4697 12 : if (val < 0)
4698 6 : PG_RETURN_NUMERIC(make_result(&const_ninf));
4699 : else
4700 6 : PG_RETURN_NUMERIC(make_result(&const_pinf));
4701 : }
4702 :
4703 21924 : snprintf(buf, sizeof(buf), "%.*g", FLT_DIG, val);
4704 :
4705 21924 : init_var(&result);
4706 :
4707 : /* Assume we need not worry about leading/trailing spaces */
4708 21924 : (void) set_var_from_str(buf, buf, &result, &endptr, NULL);
4709 :
4710 21924 : res = make_result(&result);
4711 :
4712 21924 : free_var(&result);
4713 :
4714 21924 : PG_RETURN_NUMERIC(res);
4715 : }
4716 :
4717 :
4718 : Datum
4719 2936 : numeric_float4(PG_FUNCTION_ARGS)
4720 : {
4721 2936 : Numeric num = PG_GETARG_NUMERIC(0);
4722 : char *tmp;
4723 : Datum result;
4724 :
4725 2936 : if (NUMERIC_IS_SPECIAL(num))
4726 : {
4727 78 : if (NUMERIC_IS_PINF(num))
4728 24 : PG_RETURN_FLOAT4(get_float4_infinity());
4729 54 : else if (NUMERIC_IS_NINF(num))
4730 24 : PG_RETURN_FLOAT4(-get_float4_infinity());
4731 : else
4732 30 : PG_RETURN_FLOAT4(get_float4_nan());
4733 : }
4734 :
4735 2858 : tmp = DatumGetCString(DirectFunctionCall1(numeric_out,
4736 : NumericGetDatum(num)));
4737 :
4738 2858 : result = DirectFunctionCall1(float4in, CStringGetDatum(tmp));
4739 :
4740 2858 : pfree(tmp);
4741 :
4742 2858 : PG_RETURN_DATUM(result);
4743 : }
4744 :
4745 :
4746 : Datum
4747 120 : numeric_pg_lsn(PG_FUNCTION_ARGS)
4748 : {
4749 120 : Numeric num = PG_GETARG_NUMERIC(0);
4750 : NumericVar x;
4751 : XLogRecPtr result;
4752 :
4753 120 : if (NUMERIC_IS_SPECIAL(num))
4754 : {
4755 6 : if (NUMERIC_IS_NAN(num))
4756 6 : ereport(ERROR,
4757 : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4758 : errmsg("cannot convert NaN to %s", "pg_lsn")));
4759 : else
4760 0 : ereport(ERROR,
4761 : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4762 : errmsg("cannot convert infinity to %s", "pg_lsn")));
4763 : }
4764 :
4765 : /* Convert to variable format and thence to pg_lsn */
4766 114 : init_var_from_num(num, &x);
4767 :
4768 114 : if (!numericvar_to_uint64(&x, (uint64 *) &result))
4769 24 : ereport(ERROR,
4770 : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4771 : errmsg("pg_lsn out of range")));
4772 :
4773 90 : PG_RETURN_LSN(result);
4774 : }
4775 :
4776 :
4777 : /* ----------------------------------------------------------------------
4778 : *
4779 : * Aggregate functions
4780 : *
4781 : * The transition datatype for all these aggregates is declared as INTERNAL.
4782 : * Actually, it's a pointer to a NumericAggState allocated in the aggregate
4783 : * context. The digit buffers for the NumericVars will be there too.
4784 : *
4785 : * On platforms which support 128-bit integers some aggregates instead use a
4786 : * 128-bit integer based transition datatype to speed up calculations.
4787 : *
4788 : * ----------------------------------------------------------------------
4789 : */
4790 :
4791 : typedef struct NumericAggState
4792 : {
4793 : bool calcSumX2; /* if true, calculate sumX2 */
4794 : MemoryContext agg_context; /* context we're calculating in */
4795 : int64 N; /* count of processed numbers */
4796 : NumericSumAccum sumX; /* sum of processed numbers */
4797 : NumericSumAccum sumX2; /* sum of squares of processed numbers */
4798 : int maxScale; /* maximum scale seen so far */
4799 : int64 maxScaleCount; /* number of values seen with maximum scale */
4800 : /* These counts are *not* included in N! Use NA_TOTAL_COUNT() as needed */
4801 : int64 NaNcount; /* count of NaN values */
4802 : int64 pInfcount; /* count of +Inf values */
4803 : int64 nInfcount; /* count of -Inf values */
4804 : } NumericAggState;
4805 :
4806 : #define NA_TOTAL_COUNT(na) \
4807 : ((na)->N + (na)->NaNcount + (na)->pInfcount + (na)->nInfcount)
4808 :
4809 : /*
4810 : * Prepare state data for a numeric aggregate function that needs to compute
4811 : * sum, count and optionally sum of squares of the input.
4812 : */
4813 : static NumericAggState *
4814 171116 : makeNumericAggState(FunctionCallInfo fcinfo, bool calcSumX2)
4815 : {
4816 : NumericAggState *state;
4817 : MemoryContext agg_context;
4818 : MemoryContext old_context;
4819 :
4820 171116 : if (!AggCheckCallContext(fcinfo, &agg_context))
4821 0 : elog(ERROR, "aggregate function called in non-aggregate context");
4822 :
4823 171116 : old_context = MemoryContextSwitchTo(agg_context);
4824 :
4825 171116 : state = (NumericAggState *) palloc0(sizeof(NumericAggState));
4826 171116 : state->calcSumX2 = calcSumX2;
4827 171116 : state->agg_context = agg_context;
4828 :
4829 171116 : MemoryContextSwitchTo(old_context);
4830 :
4831 171116 : return state;
4832 : }
4833 :
4834 : /*
4835 : * Like makeNumericAggState(), but allocate the state in the current memory
4836 : * context.
4837 : */
4838 : static NumericAggState *
4839 60 : makeNumericAggStateCurrentContext(bool calcSumX2)
4840 : {
4841 : NumericAggState *state;
4842 :
4843 60 : state = (NumericAggState *) palloc0(sizeof(NumericAggState));
4844 60 : state->calcSumX2 = calcSumX2;
4845 60 : state->agg_context = CurrentMemoryContext;
4846 :
4847 60 : return state;
4848 : }
4849 :
4850 : /*
4851 : * Accumulate a new input value for numeric aggregate functions.
4852 : */
4853 : static void
4854 2113552 : do_numeric_accum(NumericAggState *state, Numeric newval)
4855 : {
4856 : NumericVar X;
4857 : NumericVar X2;
4858 : MemoryContext old_context;
4859 :
4860 : /* Count NaN/infinity inputs separately from all else */
4861 2113552 : if (NUMERIC_IS_SPECIAL(newval))
4862 : {
4863 162 : if (NUMERIC_IS_PINF(newval))
4864 72 : state->pInfcount++;
4865 90 : else if (NUMERIC_IS_NINF(newval))
4866 36 : state->nInfcount++;
4867 : else
4868 54 : state->NaNcount++;
4869 162 : return;
4870 : }
4871 :
4872 : /* load processed number in short-lived context */
4873 2113390 : init_var_from_num(newval, &X);
4874 :
4875 : /*
4876 : * Track the highest input dscale that we've seen, to support inverse
4877 : * transitions (see do_numeric_discard).
4878 : */
4879 2113390 : if (X.dscale > state->maxScale)
4880 : {
4881 156 : state->maxScale = X.dscale;
4882 156 : state->maxScaleCount = 1;
4883 : }
4884 2113234 : else if (X.dscale == state->maxScale)
4885 2113198 : state->maxScaleCount++;
4886 :
4887 : /* if we need X^2, calculate that in short-lived context */
4888 2113390 : if (state->calcSumX2)
4889 : {
4890 240732 : init_var(&X2);
4891 240732 : mul_var(&X, &X, &X2, X.dscale * 2);
4892 : }
4893 :
4894 : /* The rest of this needs to work in the aggregate context */
4895 2113390 : old_context = MemoryContextSwitchTo(state->agg_context);
4896 :
4897 2113390 : state->N++;
4898 :
4899 : /* Accumulate sums */
4900 2113390 : accum_sum_add(&(state->sumX), &X);
4901 :
4902 2113390 : if (state->calcSumX2)
4903 240732 : accum_sum_add(&(state->sumX2), &X2);
4904 :
4905 2113390 : MemoryContextSwitchTo(old_context);
4906 : }
4907 :
4908 : /*
4909 : * Attempt to remove an input value from the aggregated state.
4910 : *
4911 : * If the value cannot be removed then the function will return false; the
4912 : * possible reasons for failing are described below.
4913 : *
4914 : * If we aggregate the values 1.01 and 2 then the result will be 3.01.
4915 : * If we are then asked to un-aggregate the 1.01 then we must fail as we
4916 : * won't be able to tell what the new aggregated value's dscale should be.
4917 : * We don't want to return 2.00 (dscale = 2), since the sum's dscale would
4918 : * have been zero if we'd really aggregated only 2.
4919 : *
4920 : * Note: alternatively, we could count the number of inputs with each possible
4921 : * dscale (up to some sane limit). Not yet clear if it's worth the trouble.
4922 : */
4923 : static bool
4924 342 : do_numeric_discard(NumericAggState *state, Numeric newval)
4925 : {
4926 : NumericVar X;
4927 : NumericVar X2;
4928 : MemoryContext old_context;
4929 :
4930 : /* Count NaN/infinity inputs separately from all else */
4931 342 : if (NUMERIC_IS_SPECIAL(newval))
4932 : {
4933 6 : if (NUMERIC_IS_PINF(newval))
4934 0 : state->pInfcount--;
4935 6 : else if (NUMERIC_IS_NINF(newval))
4936 0 : state->nInfcount--;
4937 : else
4938 6 : state->NaNcount--;
4939 6 : return true;
4940 : }
4941 :
4942 : /* load processed number in short-lived context */
4943 336 : init_var_from_num(newval, &X);
4944 :
4945 : /*
4946 : * state->sumX's dscale is the maximum dscale of any of the inputs.
4947 : * Removing the last input with that dscale would require us to recompute
4948 : * the maximum dscale of the *remaining* inputs, which we cannot do unless
4949 : * no more non-NaN inputs remain at all. So we report a failure instead,
4950 : * and force the aggregation to be redone from scratch.
4951 : */
4952 336 : if (X.dscale == state->maxScale)
4953 : {
4954 336 : if (state->maxScaleCount > 1 || state->maxScale == 0)
4955 : {
4956 : /*
4957 : * Some remaining inputs have same dscale, or dscale hasn't gotten
4958 : * above zero anyway
4959 : */
4960 318 : state->maxScaleCount--;
4961 : }
4962 18 : else if (state->N == 1)
4963 : {
4964 : /* No remaining non-NaN inputs at all, so reset maxScale */
4965 12 : state->maxScale = 0;
4966 12 : state->maxScaleCount = 0;
4967 : }
4968 : else
4969 : {
4970 : /* Correct new maxScale is uncertain, must fail */
4971 6 : return false;
4972 : }
4973 : }
4974 :
4975 : /* if we need X^2, calculate that in short-lived context */
4976 330 : if (state->calcSumX2)
4977 : {
4978 288 : init_var(&X2);
4979 288 : mul_var(&X, &X, &X2, X.dscale * 2);
4980 : }
4981 :
4982 : /* The rest of this needs to work in the aggregate context */
4983 330 : old_context = MemoryContextSwitchTo(state->agg_context);
4984 :
4985 330 : if (state->N-- > 1)
4986 : {
4987 : /* Negate X, to subtract it from the sum */
4988 312 : X.sign = (X.sign == NUMERIC_POS ? NUMERIC_NEG : NUMERIC_POS);
4989 312 : accum_sum_add(&(state->sumX), &X);
4990 :
4991 312 : if (state->calcSumX2)
4992 : {
4993 : /* Negate X^2. X^2 is always positive */
4994 288 : X2.sign = NUMERIC_NEG;
4995 288 : accum_sum_add(&(state->sumX2), &X2);
4996 : }
4997 : }
4998 : else
4999 : {
5000 : /* Zero the sums */
5001 : Assert(state->N == 0);
5002 :
5003 18 : accum_sum_reset(&state->sumX);
5004 18 : if (state->calcSumX2)
5005 0 : accum_sum_reset(&state->sumX2);
5006 : }
5007 :
5008 330 : MemoryContextSwitchTo(old_context);
5009 :
5010 330 : return true;
5011 : }
5012 :
5013 : /*
5014 : * Generic transition function for numeric aggregates that require sumX2.
5015 : */
5016 : Datum
5017 642 : numeric_accum(PG_FUNCTION_ARGS)
5018 : {
5019 : NumericAggState *state;
5020 :
5021 642 : state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
5022 :
5023 : /* Create the state data on the first call */
5024 642 : if (state == NULL)
5025 174 : state = makeNumericAggState(fcinfo, true);
5026 :
5027 642 : if (!PG_ARGISNULL(1))
5028 624 : do_numeric_accum(state, PG_GETARG_NUMERIC(1));
5029 :
5030 642 : PG_RETURN_POINTER(state);
5031 : }
5032 :
5033 : /*
5034 : * Generic combine function for numeric aggregates which require sumX2
5035 : */
5036 : Datum
5037 24 : numeric_combine(PG_FUNCTION_ARGS)
5038 : {
5039 : NumericAggState *state1;
5040 : NumericAggState *state2;
5041 : MemoryContext agg_context;
5042 : MemoryContext old_context;
5043 :
5044 24 : if (!AggCheckCallContext(fcinfo, &agg_context))
5045 0 : elog(ERROR, "aggregate function called in non-aggregate context");
5046 :
5047 24 : state1 = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
5048 24 : state2 = PG_ARGISNULL(1) ? NULL : (NumericAggState *) PG_GETARG_POINTER(1);
5049 :
5050 24 : if (state2 == NULL)
5051 0 : PG_RETURN_POINTER(state1);
5052 :
5053 : /* manually copy all fields from state2 to state1 */
5054 24 : if (state1 == NULL)
5055 : {
5056 18 : old_context = MemoryContextSwitchTo(agg_context);
5057 :
5058 18 : state1 = makeNumericAggStateCurrentContext(true);
5059 18 : state1->N = state2->N;
5060 18 : state1->NaNcount = state2->NaNcount;
5061 18 : state1->pInfcount = state2->pInfcount;
5062 18 : state1->nInfcount = state2->nInfcount;
5063 18 : state1->maxScale = state2->maxScale;
5064 18 : state1->maxScaleCount = state2->maxScaleCount;
5065 :
5066 18 : accum_sum_copy(&state1->sumX, &state2->sumX);
5067 18 : accum_sum_copy(&state1->sumX2, &state2->sumX2);
5068 :
5069 18 : MemoryContextSwitchTo(old_context);
5070 :
5071 18 : PG_RETURN_POINTER(state1);
5072 : }
5073 :
5074 6 : state1->N += state2->N;
5075 6 : state1->NaNcount += state2->NaNcount;
5076 6 : state1->pInfcount += state2->pInfcount;
5077 6 : state1->nInfcount += state2->nInfcount;
5078 :
5079 6 : if (state2->N > 0)
5080 : {
5081 : /*
5082 : * These are currently only needed for moving aggregates, but let's do
5083 : * the right thing anyway...
5084 : */
5085 6 : if (state2->maxScale > state1->maxScale)
5086 : {
5087 0 : state1->maxScale = state2->maxScale;
5088 0 : state1->maxScaleCount = state2->maxScaleCount;
5089 : }
5090 6 : else if (state2->maxScale == state1->maxScale)
5091 6 : state1->maxScaleCount += state2->maxScaleCount;
5092 :
5093 : /* The rest of this needs to work in the aggregate context */
5094 6 : old_context = MemoryContextSwitchTo(agg_context);
5095 :
5096 : /* Accumulate sums */
5097 6 : accum_sum_combine(&state1->sumX, &state2->sumX);
5098 6 : accum_sum_combine(&state1->sumX2, &state2->sumX2);
5099 :
5100 6 : MemoryContextSwitchTo(old_context);
5101 : }
5102 6 : PG_RETURN_POINTER(state1);
5103 : }
5104 :
5105 : /*
5106 : * Generic transition function for numeric aggregates that don't require sumX2.
5107 : */
5108 : Datum
5109 1872808 : numeric_avg_accum(PG_FUNCTION_ARGS)
5110 : {
5111 : NumericAggState *state;
5112 :
5113 1872808 : state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
5114 :
5115 : /* Create the state data on the first call */
5116 1872808 : if (state == NULL)
5117 170894 : state = makeNumericAggState(fcinfo, false);
5118 :
5119 1872808 : if (!PG_ARGISNULL(1))
5120 1872748 : do_numeric_accum(state, PG_GETARG_NUMERIC(1));
5121 :
5122 1872808 : PG_RETURN_POINTER(state);
5123 : }
5124 :
5125 : /*
5126 : * Combine function for numeric aggregates which don't require sumX2
5127 : */
5128 : Datum
5129 12 : numeric_avg_combine(PG_FUNCTION_ARGS)
5130 : {
5131 : NumericAggState *state1;
5132 : NumericAggState *state2;
5133 : MemoryContext agg_context;
5134 : MemoryContext old_context;
5135 :
5136 12 : if (!AggCheckCallContext(fcinfo, &agg_context))
5137 0 : elog(ERROR, "aggregate function called in non-aggregate context");
5138 :
5139 12 : state1 = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
5140 12 : state2 = PG_ARGISNULL(1) ? NULL : (NumericAggState *) PG_GETARG_POINTER(1);
5141 :
5142 12 : if (state2 == NULL)
5143 0 : PG_RETURN_POINTER(state1);
5144 :
5145 : /* manually copy all fields from state2 to state1 */
5146 12 : if (state1 == NULL)
5147 : {
5148 6 : old_context = MemoryContextSwitchTo(agg_context);
5149 :
5150 6 : state1 = makeNumericAggStateCurrentContext(false);
5151 6 : state1->N = state2->N;
5152 6 : state1->NaNcount = state2->NaNcount;
5153 6 : state1->pInfcount = state2->pInfcount;
5154 6 : state1->nInfcount = state2->nInfcount;
5155 6 : state1->maxScale = state2->maxScale;
5156 6 : state1->maxScaleCount = state2->maxScaleCount;
5157 :
5158 6 : accum_sum_copy(&state1->sumX, &state2->sumX);
5159 :
5160 6 : MemoryContextSwitchTo(old_context);
5161 :
5162 6 : PG_RETURN_POINTER(state1);
5163 : }
5164 :
5165 6 : state1->N += state2->N;
5166 6 : state1->NaNcount += state2->NaNcount;
5167 6 : state1->pInfcount += state2->pInfcount;
5168 6 : state1->nInfcount += state2->nInfcount;
5169 :
5170 6 : if (state2->N > 0)
5171 : {
5172 : /*
5173 : * These are currently only needed for moving aggregates, but let's do
5174 : * the right thing anyway...
5175 : */
5176 6 : if (state2->maxScale > state1->maxScale)
5177 : {
5178 0 : state1->maxScale = state2->maxScale;
5179 0 : state1->maxScaleCount = state2->maxScaleCount;
5180 : }
5181 6 : else if (state2->maxScale == state1->maxScale)
5182 6 : state1->maxScaleCount += state2->maxScaleCount;
5183 :
5184 : /* The rest of this needs to work in the aggregate context */
5185 6 : old_context = MemoryContextSwitchTo(agg_context);
5186 :
5187 : /* Accumulate sums */
5188 6 : accum_sum_combine(&state1->sumX, &state2->sumX);
5189 :
5190 6 : MemoryContextSwitchTo(old_context);
5191 : }
5192 6 : PG_RETURN_POINTER(state1);
5193 : }
5194 :
5195 : /*
5196 : * numeric_avg_serialize
5197 : * Serialize NumericAggState for numeric aggregates that don't require
5198 : * sumX2.
5199 : */
5200 : Datum
5201 12 : numeric_avg_serialize(PG_FUNCTION_ARGS)
5202 : {
5203 : NumericAggState *state;
5204 : StringInfoData buf;
5205 : bytea *result;
5206 : NumericVar tmp_var;
5207 :
5208 : /* Ensure we disallow calling when not in aggregate context */
5209 12 : if (!AggCheckCallContext(fcinfo, NULL))
5210 0 : elog(ERROR, "aggregate function called in non-aggregate context");
5211 :
5212 12 : state = (NumericAggState *) PG_GETARG_POINTER(0);
5213 :
5214 12 : init_var(&tmp_var);
5215 :
5216 12 : pq_begintypsend(&buf);
5217 :
5218 : /* N */
5219 12 : pq_sendint64(&buf, state->N);
5220 :
5221 : /* sumX */
5222 12 : accum_sum_final(&state->sumX, &tmp_var);
5223 12 : numericvar_serialize(&buf, &tmp_var);
5224 :
5225 : /* maxScale */
5226 12 : pq_sendint32(&buf, state->maxScale);
5227 :
5228 : /* maxScaleCount */
5229 12 : pq_sendint64(&buf, state->maxScaleCount);
5230 :
5231 : /* NaNcount */
5232 12 : pq_sendint64(&buf, state->NaNcount);
5233 :
5234 : /* pInfcount */
5235 12 : pq_sendint64(&buf, state->pInfcount);
5236 :
5237 : /* nInfcount */
5238 12 : pq_sendint64(&buf, state->nInfcount);
5239 :
5240 12 : result = pq_endtypsend(&buf);
5241 :
5242 12 : free_var(&tmp_var);
5243 :
5244 12 : PG_RETURN_BYTEA_P(result);
5245 : }
5246 :
5247 : /*
5248 : * numeric_avg_deserialize
5249 : * Deserialize bytea into NumericAggState for numeric aggregates that
5250 : * don't require sumX2.
5251 : */
5252 : Datum
5253 12 : numeric_avg_deserialize(PG_FUNCTION_ARGS)
5254 : {
5255 : bytea *sstate;
5256 : NumericAggState *result;
5257 : StringInfoData buf;
5258 : NumericVar tmp_var;
5259 :
5260 12 : if (!AggCheckCallContext(fcinfo, NULL))
5261 0 : elog(ERROR, "aggregate function called in non-aggregate context");
5262 :
5263 12 : sstate = PG_GETARG_BYTEA_PP(0);
5264 :
5265 12 : init_var(&tmp_var);
5266 :
5267 : /*
5268 : * Initialize a StringInfo so that we can "receive" it using the standard
5269 : * recv-function infrastructure.
5270 : */
5271 12 : initReadOnlyStringInfo(&buf, VARDATA_ANY(sstate),
5272 12 : VARSIZE_ANY_EXHDR(sstate));
5273 :
5274 12 : result = makeNumericAggStateCurrentContext(false);
5275 :
5276 : /* N */
5277 12 : result->N = pq_getmsgint64(&buf);
5278 :
5279 : /* sumX */
5280 12 : numericvar_deserialize(&buf, &tmp_var);
5281 12 : accum_sum_add(&(result->sumX), &tmp_var);
5282 :
5283 : /* maxScale */
5284 12 : result->maxScale = pq_getmsgint(&buf, 4);
5285 :
5286 : /* maxScaleCount */
5287 12 : result->maxScaleCount = pq_getmsgint64(&buf);
5288 :
5289 : /* NaNcount */
5290 12 : result->NaNcount = pq_getmsgint64(&buf);
5291 :
5292 : /* pInfcount */
5293 12 : result->pInfcount = pq_getmsgint64(&buf);
5294 :
5295 : /* nInfcount */
5296 12 : result->nInfcount = pq_getmsgint64(&buf);
5297 :
5298 12 : pq_getmsgend(&buf);
5299 :
5300 12 : free_var(&tmp_var);
5301 :
5302 12 : PG_RETURN_POINTER(result);
5303 : }
5304 :
5305 : /*
5306 : * numeric_serialize
5307 : * Serialization function for NumericAggState for numeric aggregates that
5308 : * require sumX2.
5309 : */
5310 : Datum
5311 24 : numeric_serialize(PG_FUNCTION_ARGS)
5312 : {
5313 : NumericAggState *state;
5314 : StringInfoData buf;
5315 : bytea *result;
5316 : NumericVar tmp_var;
5317 :
5318 : /* Ensure we disallow calling when not in aggregate context */
5319 24 : if (!AggCheckCallContext(fcinfo, NULL))
5320 0 : elog(ERROR, "aggregate function called in non-aggregate context");
5321 :
5322 24 : state = (NumericAggState *) PG_GETARG_POINTER(0);
5323 :
5324 24 : init_var(&tmp_var);
5325 :
5326 24 : pq_begintypsend(&buf);
5327 :
5328 : /* N */
5329 24 : pq_sendint64(&buf, state->N);
5330 :
5331 : /* sumX */
5332 24 : accum_sum_final(&state->sumX, &tmp_var);
5333 24 : numericvar_serialize(&buf, &tmp_var);
5334 :
5335 : /* sumX2 */
5336 24 : accum_sum_final(&state->sumX2, &tmp_var);
5337 24 : numericvar_serialize(&buf, &tmp_var);
5338 :
5339 : /* maxScale */
5340 24 : pq_sendint32(&buf, state->maxScale);
5341 :
5342 : /* maxScaleCount */
5343 24 : pq_sendint64(&buf, state->maxScaleCount);
5344 :
5345 : /* NaNcount */
5346 24 : pq_sendint64(&buf, state->NaNcount);
5347 :
5348 : /* pInfcount */
5349 24 : pq_sendint64(&buf, state->pInfcount);
5350 :
5351 : /* nInfcount */
5352 24 : pq_sendint64(&buf, state->nInfcount);
5353 :
5354 24 : result = pq_endtypsend(&buf);
5355 :
5356 24 : free_var(&tmp_var);
5357 :
5358 24 : PG_RETURN_BYTEA_P(result);
5359 : }
5360 :
5361 : /*
5362 : * numeric_deserialize
5363 : * Deserialization function for NumericAggState for numeric aggregates that
5364 : * require sumX2.
5365 : */
5366 : Datum
5367 24 : numeric_deserialize(PG_FUNCTION_ARGS)
5368 : {
5369 : bytea *sstate;
5370 : NumericAggState *result;
5371 : StringInfoData buf;
5372 : NumericVar tmp_var;
5373 :
5374 24 : if (!AggCheckCallContext(fcinfo, NULL))
5375 0 : elog(ERROR, "aggregate function called in non-aggregate context");
5376 :
5377 24 : sstate = PG_GETARG_BYTEA_PP(0);
5378 :
5379 24 : init_var(&tmp_var);
5380 :
5381 : /*
5382 : * Initialize a StringInfo so that we can "receive" it using the standard
5383 : * recv-function infrastructure.
5384 : */
5385 24 : initReadOnlyStringInfo(&buf, VARDATA_ANY(sstate),
5386 24 : VARSIZE_ANY_EXHDR(sstate));
5387 :
5388 24 : result = makeNumericAggStateCurrentContext(false);
5389 :
5390 : /* N */
5391 24 : result->N = pq_getmsgint64(&buf);
5392 :
5393 : /* sumX */
5394 24 : numericvar_deserialize(&buf, &tmp_var);
5395 24 : accum_sum_add(&(result->sumX), &tmp_var);
5396 :
5397 : /* sumX2 */
5398 24 : numericvar_deserialize(&buf, &tmp_var);
5399 24 : accum_sum_add(&(result->sumX2), &tmp_var);
5400 :
5401 : /* maxScale */
5402 24 : result->maxScale = pq_getmsgint(&buf, 4);
5403 :
5404 : /* maxScaleCount */
5405 24 : result->maxScaleCount = pq_getmsgint64(&buf);
5406 :
5407 : /* NaNcount */
5408 24 : result->NaNcount = pq_getmsgint64(&buf);
5409 :
5410 : /* pInfcount */
5411 24 : result->pInfcount = pq_getmsgint64(&buf);
5412 :
5413 : /* nInfcount */
5414 24 : result->nInfcount = pq_getmsgint64(&buf);
5415 :
5416 24 : pq_getmsgend(&buf);
5417 :
5418 24 : free_var(&tmp_var);
5419 :
5420 24 : PG_RETURN_POINTER(result);
5421 : }
5422 :
5423 : /*
5424 : * Generic inverse transition function for numeric aggregates
5425 : * (with or without requirement for X^2).
5426 : */
5427 : Datum
5428 228 : numeric_accum_inv(PG_FUNCTION_ARGS)
5429 : {
5430 : NumericAggState *state;
5431 :
5432 228 : state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
5433 :
5434 : /* Should not get here with no state */
5435 228 : if (state == NULL)
5436 0 : elog(ERROR, "numeric_accum_inv called with NULL state");
5437 :
5438 228 : if (!PG_ARGISNULL(1))
5439 : {
5440 : /* If we fail to perform the inverse transition, return NULL */
5441 198 : if (!do_numeric_discard(state, PG_GETARG_NUMERIC(1)))
5442 6 : PG_RETURN_NULL();
5443 : }
5444 :
5445 222 : PG_RETURN_POINTER(state);
5446 : }
5447 :
5448 :
5449 : /*
5450 : * Integer data types in general use Numeric accumulators to share code
5451 : * and avoid risk of overflow.
5452 : *
5453 : * However for performance reasons optimized special-purpose accumulator
5454 : * routines are used when possible.
5455 : *
5456 : * On platforms with 128-bit integer support, the 128-bit routines will be
5457 : * used when sum(X) or sum(X*X) fit into 128-bit.
5458 : *
5459 : * For 16 and 32 bit inputs, the N and sum(X) fit into 64-bit so the 64-bit
5460 : * accumulators will be used for SUM and AVG of these data types.
5461 : */
5462 :
5463 : #ifdef HAVE_INT128
5464 : typedef struct Int128AggState
5465 : {
5466 : bool calcSumX2; /* if true, calculate sumX2 */
5467 : int64 N; /* count of processed numbers */
5468 : int128 sumX; /* sum of processed numbers */
5469 : int128 sumX2; /* sum of squares of processed numbers */
5470 : } Int128AggState;
5471 :
5472 : /*
5473 : * Prepare state data for a 128-bit aggregate function that needs to compute
5474 : * sum, count and optionally sum of squares of the input.
5475 : */
5476 : static Int128AggState *
5477 668 : makeInt128AggState(FunctionCallInfo fcinfo, bool calcSumX2)
5478 : {
5479 : Int128AggState *state;
5480 : MemoryContext agg_context;
5481 : MemoryContext old_context;
5482 :
5483 668 : if (!AggCheckCallContext(fcinfo, &agg_context))
5484 0 : elog(ERROR, "aggregate function called in non-aggregate context");
5485 :
5486 668 : old_context = MemoryContextSwitchTo(agg_context);
5487 :
5488 668 : state = (Int128AggState *) palloc0(sizeof(Int128AggState));
5489 668 : state->calcSumX2 = calcSumX2;
5490 :
5491 668 : MemoryContextSwitchTo(old_context);
5492 :
5493 668 : return state;
5494 : }
5495 :
5496 : /*
5497 : * Like makeInt128AggState(), but allocate the state in the current memory
5498 : * context.
5499 : */
5500 : static Int128AggState *
5501 26 : makeInt128AggStateCurrentContext(bool calcSumX2)
5502 : {
5503 : Int128AggState *state;
5504 :
5505 26 : state = (Int128AggState *) palloc0(sizeof(Int128AggState));
5506 26 : state->calcSumX2 = calcSumX2;
5507 :
5508 26 : return state;
5509 : }
5510 :
5511 : /*
5512 : * Accumulate a new input value for 128-bit aggregate functions.
5513 : */
5514 : static void
5515 553538 : do_int128_accum(Int128AggState *state, int128 newval)
5516 : {
5517 553538 : if (state->calcSumX2)
5518 242360 : state->sumX2 += newval * newval;
5519 :
5520 553538 : state->sumX += newval;
5521 553538 : state->N++;
5522 553538 : }
5523 :
5524 : /*
5525 : * Remove an input value from the aggregated state.
5526 : */
5527 : static void
5528 312 : do_int128_discard(Int128AggState *state, int128 newval)
5529 : {
5530 312 : if (state->calcSumX2)
5531 288 : state->sumX2 -= newval * newval;
5532 :
5533 312 : state->sumX -= newval;
5534 312 : state->N--;
5535 312 : }
5536 :
5537 : typedef Int128AggState PolyNumAggState;
5538 : #define makePolyNumAggState makeInt128AggState
5539 : #define makePolyNumAggStateCurrentContext makeInt128AggStateCurrentContext
5540 : #else
5541 : typedef NumericAggState PolyNumAggState;
5542 : #define makePolyNumAggState makeNumericAggState
5543 : #define makePolyNumAggStateCurrentContext makeNumericAggStateCurrentContext
5544 : #endif
5545 :
5546 : Datum
5547 198 : int2_accum(PG_FUNCTION_ARGS)
5548 : {
5549 : PolyNumAggState *state;
5550 :
5551 198 : state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
5552 :
5553 : /* Create the state data on the first call */
5554 198 : if (state == NULL)
5555 36 : state = makePolyNumAggState(fcinfo, true);
5556 :
5557 198 : if (!PG_ARGISNULL(1))
5558 : {
5559 : #ifdef HAVE_INT128
5560 180 : do_int128_accum(state, (int128) PG_GETARG_INT16(1));
5561 : #else
5562 : do_numeric_accum(state, int64_to_numeric(PG_GETARG_INT16(1)));
5563 : #endif
5564 : }
5565 :
5566 198 : PG_RETURN_POINTER(state);
5567 : }
5568 :
5569 : Datum
5570 242198 : int4_accum(PG_FUNCTION_ARGS)
5571 : {
5572 : PolyNumAggState *state;
5573 :
5574 242198 : state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
5575 :
5576 : /* Create the state data on the first call */
5577 242198 : if (state == NULL)
5578 66 : state = makePolyNumAggState(fcinfo, true);
5579 :
5580 242198 : if (!PG_ARGISNULL(1))
5581 : {
5582 : #ifdef HAVE_INT128
5583 242180 : do_int128_accum(state, (int128) PG_GETARG_INT32(1));
5584 : #else
5585 : do_numeric_accum(state, int64_to_numeric(PG_GETARG_INT32(1)));
5586 : #endif
5587 : }
5588 :
5589 242198 : PG_RETURN_POINTER(state);
5590 : }
5591 :
5592 : Datum
5593 240198 : int8_accum(PG_FUNCTION_ARGS)
5594 : {
5595 : NumericAggState *state;
5596 :
5597 240198 : state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
5598 :
5599 : /* Create the state data on the first call */
5600 240198 : if (state == NULL)
5601 48 : state = makeNumericAggState(fcinfo, true);
5602 :
5603 240198 : if (!PG_ARGISNULL(1))
5604 240180 : do_numeric_accum(state, int64_to_numeric(PG_GETARG_INT64(1)));
5605 :
5606 240198 : PG_RETURN_POINTER(state);
5607 : }
5608 :
5609 : /*
5610 : * Combine function for numeric aggregates which require sumX2
5611 : */
5612 : Datum
5613 10 : numeric_poly_combine(PG_FUNCTION_ARGS)
5614 : {
5615 : PolyNumAggState *state1;
5616 : PolyNumAggState *state2;
5617 : MemoryContext agg_context;
5618 : MemoryContext old_context;
5619 :
5620 10 : if (!AggCheckCallContext(fcinfo, &agg_context))
5621 0 : elog(ERROR, "aggregate function called in non-aggregate context");
5622 :
5623 10 : state1 = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
5624 10 : state2 = PG_ARGISNULL(1) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(1);
5625 :
5626 10 : if (state2 == NULL)
5627 0 : PG_RETURN_POINTER(state1);
5628 :
5629 : /* manually copy all fields from state2 to state1 */
5630 10 : if (state1 == NULL)
5631 : {
5632 6 : old_context = MemoryContextSwitchTo(agg_context);
5633 :
5634 6 : state1 = makePolyNumAggState(fcinfo, true);
5635 6 : state1->N = state2->N;
5636 :
5637 : #ifdef HAVE_INT128
5638 6 : state1->sumX = state2->sumX;
5639 6 : state1->sumX2 = state2->sumX2;
5640 : #else
5641 : accum_sum_copy(&state1->sumX, &state2->sumX);
5642 : accum_sum_copy(&state1->sumX2, &state2->sumX2);
5643 : #endif
5644 :
5645 6 : MemoryContextSwitchTo(old_context);
5646 :
5647 6 : PG_RETURN_POINTER(state1);
5648 : }
5649 :
5650 4 : if (state2->N > 0)
5651 : {
5652 4 : state1->N += state2->N;
5653 :
5654 : #ifdef HAVE_INT128
5655 4 : state1->sumX += state2->sumX;
5656 4 : state1->sumX2 += state2->sumX2;
5657 : #else
5658 : /* The rest of this needs to work in the aggregate context */
5659 : old_context = MemoryContextSwitchTo(agg_context);
5660 :
5661 : /* Accumulate sums */
5662 : accum_sum_combine(&state1->sumX, &state2->sumX);
5663 : accum_sum_combine(&state1->sumX2, &state2->sumX2);
5664 :
5665 : MemoryContextSwitchTo(old_context);
5666 : #endif
5667 :
5668 : }
5669 4 : PG_RETURN_POINTER(state1);
5670 : }
5671 :
5672 : /*
5673 : * numeric_poly_serialize
5674 : * Serialize PolyNumAggState into bytea for aggregate functions which
5675 : * require sumX2.
5676 : */
5677 : Datum
5678 10 : numeric_poly_serialize(PG_FUNCTION_ARGS)
5679 : {
5680 : PolyNumAggState *state;
5681 : StringInfoData buf;
5682 : bytea *result;
5683 : NumericVar tmp_var;
5684 :
5685 : /* Ensure we disallow calling when not in aggregate context */
5686 10 : if (!AggCheckCallContext(fcinfo, NULL))
5687 0 : elog(ERROR, "aggregate function called in non-aggregate context");
5688 :
5689 10 : state = (PolyNumAggState *) PG_GETARG_POINTER(0);
5690 :
5691 : /*
5692 : * If the platform supports int128 then sumX and sumX2 will be a 128 bit
5693 : * integer type. Here we'll convert that into a numeric type so that the
5694 : * combine state is in the same format for both int128 enabled machines
5695 : * and machines which don't support that type. The logic here is that one
5696 : * day we might like to send these over to another server for further
5697 : * processing and we want a standard format to work with.
5698 : */
5699 :
5700 10 : init_var(&tmp_var);
5701 :
5702 10 : pq_begintypsend(&buf);
5703 :
5704 : /* N */
5705 10 : pq_sendint64(&buf, state->N);
5706 :
5707 : /* sumX */
5708 : #ifdef HAVE_INT128
5709 10 : int128_to_numericvar(state->sumX, &tmp_var);
5710 : #else
5711 : accum_sum_final(&state->sumX, &tmp_var);
5712 : #endif
5713 10 : numericvar_serialize(&buf, &tmp_var);
5714 :
5715 : /* sumX2 */
5716 : #ifdef HAVE_INT128
5717 10 : int128_to_numericvar(state->sumX2, &tmp_var);
5718 : #else
5719 : accum_sum_final(&state->sumX2, &tmp_var);
5720 : #endif
5721 10 : numericvar_serialize(&buf, &tmp_var);
5722 :
5723 10 : result = pq_endtypsend(&buf);
5724 :
5725 10 : free_var(&tmp_var);
5726 :
5727 10 : PG_RETURN_BYTEA_P(result);
5728 : }
5729 :
5730 : /*
5731 : * numeric_poly_deserialize
5732 : * Deserialize PolyNumAggState from bytea for aggregate functions which
5733 : * require sumX2.
5734 : */
5735 : Datum
5736 10 : numeric_poly_deserialize(PG_FUNCTION_ARGS)
5737 : {
5738 : bytea *sstate;
5739 : PolyNumAggState *result;
5740 : StringInfoData buf;
5741 : NumericVar tmp_var;
5742 :
5743 10 : if (!AggCheckCallContext(fcinfo, NULL))
5744 0 : elog(ERROR, "aggregate function called in non-aggregate context");
5745 :
5746 10 : sstate = PG_GETARG_BYTEA_PP(0);
5747 :
5748 10 : init_var(&tmp_var);
5749 :
5750 : /*
5751 : * Initialize a StringInfo so that we can "receive" it using the standard
5752 : * recv-function infrastructure.
5753 : */
5754 10 : initReadOnlyStringInfo(&buf, VARDATA_ANY(sstate),
5755 10 : VARSIZE_ANY_EXHDR(sstate));
5756 :
5757 10 : result = makePolyNumAggStateCurrentContext(false);
5758 :
5759 : /* N */
5760 10 : result->N = pq_getmsgint64(&buf);
5761 :
5762 : /* sumX */
5763 10 : numericvar_deserialize(&buf, &tmp_var);
5764 : #ifdef HAVE_INT128
5765 10 : numericvar_to_int128(&tmp_var, &result->sumX);
5766 : #else
5767 : accum_sum_add(&result->sumX, &tmp_var);
5768 : #endif
5769 :
5770 : /* sumX2 */
5771 10 : numericvar_deserialize(&buf, &tmp_var);
5772 : #ifdef HAVE_INT128
5773 10 : numericvar_to_int128(&tmp_var, &result->sumX2);
5774 : #else
5775 : accum_sum_add(&result->sumX2, &tmp_var);
5776 : #endif
5777 :
5778 10 : pq_getmsgend(&buf);
5779 :
5780 10 : free_var(&tmp_var);
5781 :
5782 10 : PG_RETURN_POINTER(result);
5783 : }
5784 :
5785 : /*
5786 : * Transition function for int8 input when we don't need sumX2.
5787 : */
5788 : Datum
5789 312294 : int8_avg_accum(PG_FUNCTION_ARGS)
5790 : {
5791 : PolyNumAggState *state;
5792 :
5793 312294 : state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
5794 :
5795 : /* Create the state data on the first call */
5796 312294 : if (state == NULL)
5797 548 : state = makePolyNumAggState(fcinfo, false);
5798 :
5799 312294 : if (!PG_ARGISNULL(1))
5800 : {
5801 : #ifdef HAVE_INT128
5802 311178 : do_int128_accum(state, (int128) PG_GETARG_INT64(1));
5803 : #else
5804 : do_numeric_accum(state, int64_to_numeric(PG_GETARG_INT64(1)));
5805 : #endif
5806 : }
5807 :
5808 312294 : PG_RETURN_POINTER(state);
5809 : }
5810 :
5811 : /*
5812 : * Combine function for PolyNumAggState for aggregates which don't require
5813 : * sumX2
5814 : */
5815 : Datum
5816 16 : int8_avg_combine(PG_FUNCTION_ARGS)
5817 : {
5818 : PolyNumAggState *state1;
5819 : PolyNumAggState *state2;
5820 : MemoryContext agg_context;
5821 : MemoryContext old_context;
5822 :
5823 16 : if (!AggCheckCallContext(fcinfo, &agg_context))
5824 0 : elog(ERROR, "aggregate function called in non-aggregate context");
5825 :
5826 16 : state1 = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
5827 16 : state2 = PG_ARGISNULL(1) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(1);
5828 :
5829 16 : if (state2 == NULL)
5830 0 : PG_RETURN_POINTER(state1);
5831 :
5832 : /* manually copy all fields from state2 to state1 */
5833 16 : if (state1 == NULL)
5834 : {
5835 12 : old_context = MemoryContextSwitchTo(agg_context);
5836 :
5837 12 : state1 = makePolyNumAggState(fcinfo, false);
5838 12 : state1->N = state2->N;
5839 :
5840 : #ifdef HAVE_INT128
5841 12 : state1->sumX = state2->sumX;
5842 : #else
5843 : accum_sum_copy(&state1->sumX, &state2->sumX);
5844 : #endif
5845 12 : MemoryContextSwitchTo(old_context);
5846 :
5847 12 : PG_RETURN_POINTER(state1);
5848 : }
5849 :
5850 4 : if (state2->N > 0)
5851 : {
5852 4 : state1->N += state2->N;
5853 :
5854 : #ifdef HAVE_INT128
5855 4 : state1->sumX += state2->sumX;
5856 : #else
5857 : /* The rest of this needs to work in the aggregate context */
5858 : old_context = MemoryContextSwitchTo(agg_context);
5859 :
5860 : /* Accumulate sums */
5861 : accum_sum_combine(&state1->sumX, &state2->sumX);
5862 :
5863 : MemoryContextSwitchTo(old_context);
5864 : #endif
5865 :
5866 : }
5867 4 : PG_RETURN_POINTER(state1);
5868 : }
5869 :
5870 : /*
5871 : * int8_avg_serialize
5872 : * Serialize PolyNumAggState into bytea using the standard
5873 : * recv-function infrastructure.
5874 : */
5875 : Datum
5876 16 : int8_avg_serialize(PG_FUNCTION_ARGS)
5877 : {
5878 : PolyNumAggState *state;
5879 : StringInfoData buf;
5880 : bytea *result;
5881 : NumericVar tmp_var;
5882 :
5883 : /* Ensure we disallow calling when not in aggregate context */
5884 16 : if (!AggCheckCallContext(fcinfo, NULL))
5885 0 : elog(ERROR, "aggregate function called in non-aggregate context");
5886 :
5887 16 : state = (PolyNumAggState *) PG_GETARG_POINTER(0);
5888 :
5889 : /*
5890 : * If the platform supports int128 then sumX will be a 128 integer type.
5891 : * Here we'll convert that into a numeric type so that the combine state
5892 : * is in the same format for both int128 enabled machines and machines
5893 : * which don't support that type. The logic here is that one day we might
5894 : * like to send these over to another server for further processing and we
5895 : * want a standard format to work with.
5896 : */
5897 :
5898 16 : init_var(&tmp_var);
5899 :
5900 16 : pq_begintypsend(&buf);
5901 :
5902 : /* N */
5903 16 : pq_sendint64(&buf, state->N);
5904 :
5905 : /* sumX */
5906 : #ifdef HAVE_INT128
5907 16 : int128_to_numericvar(state->sumX, &tmp_var);
5908 : #else
5909 : accum_sum_final(&state->sumX, &tmp_var);
5910 : #endif
5911 16 : numericvar_serialize(&buf, &tmp_var);
5912 :
5913 16 : result = pq_endtypsend(&buf);
5914 :
5915 16 : free_var(&tmp_var);
5916 :
5917 16 : PG_RETURN_BYTEA_P(result);
5918 : }
5919 :
5920 : /*
5921 : * int8_avg_deserialize
5922 : * Deserialize bytea back into PolyNumAggState.
5923 : */
5924 : Datum
5925 16 : int8_avg_deserialize(PG_FUNCTION_ARGS)
5926 : {
5927 : bytea *sstate;
5928 : PolyNumAggState *result;
5929 : StringInfoData buf;
5930 : NumericVar tmp_var;
5931 :
5932 16 : if (!AggCheckCallContext(fcinfo, NULL))
5933 0 : elog(ERROR, "aggregate function called in non-aggregate context");
5934 :
5935 16 : sstate = PG_GETARG_BYTEA_PP(0);
5936 :
5937 16 : init_var(&tmp_var);
5938 :
5939 : /*
5940 : * Initialize a StringInfo so that we can "receive" it using the standard
5941 : * recv-function infrastructure.
5942 : */
5943 16 : initReadOnlyStringInfo(&buf, VARDATA_ANY(sstate),
5944 16 : VARSIZE_ANY_EXHDR(sstate));
5945 :
5946 16 : result = makePolyNumAggStateCurrentContext(false);
5947 :
5948 : /* N */
5949 16 : result->N = pq_getmsgint64(&buf);
5950 :
5951 : /* sumX */
5952 16 : numericvar_deserialize(&buf, &tmp_var);
5953 : #ifdef HAVE_INT128
5954 16 : numericvar_to_int128(&tmp_var, &result->sumX);
5955 : #else
5956 : accum_sum_add(&result->sumX, &tmp_var);
5957 : #endif
5958 :
5959 16 : pq_getmsgend(&buf);
5960 :
5961 16 : free_var(&tmp_var);
5962 :
5963 16 : PG_RETURN_POINTER(result);
5964 : }
5965 :
5966 : /*
5967 : * Inverse transition functions to go with the above.
5968 : */
5969 :
5970 : Datum
5971 162 : int2_accum_inv(PG_FUNCTION_ARGS)
5972 : {
5973 : PolyNumAggState *state;
5974 :
5975 162 : state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
5976 :
5977 : /* Should not get here with no state */
5978 162 : if (state == NULL)
5979 0 : elog(ERROR, "int2_accum_inv called with NULL state");
5980 :
5981 162 : if (!PG_ARGISNULL(1))
5982 : {
5983 : #ifdef HAVE_INT128
5984 144 : do_int128_discard(state, (int128) PG_GETARG_INT16(1));
5985 : #else
5986 : /* Should never fail, all inputs have dscale 0 */
5987 : if (!do_numeric_discard(state, int64_to_numeric(PG_GETARG_INT16(1))))
5988 : elog(ERROR, "do_numeric_discard failed unexpectedly");
5989 : #endif
5990 : }
5991 :
5992 162 : PG_RETURN_POINTER(state);
5993 : }
5994 :
5995 : Datum
5996 162 : int4_accum_inv(PG_FUNCTION_ARGS)
5997 : {
5998 : PolyNumAggState *state;
5999 :
6000 162 : state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
6001 :
6002 : /* Should not get here with no state */
6003 162 : if (state == NULL)
6004 0 : elog(ERROR, "int4_accum_inv called with NULL state");
6005 :
6006 162 : if (!PG_ARGISNULL(1))
6007 : {
6008 : #ifdef HAVE_INT128
6009 144 : do_int128_discard(state, (int128) PG_GETARG_INT32(1));
6010 : #else
6011 : /* Should never fail, all inputs have dscale 0 */
6012 : if (!do_numeric_discard(state, int64_to_numeric(PG_GETARG_INT32(1))))
6013 : elog(ERROR, "do_numeric_discard failed unexpectedly");
6014 : #endif
6015 : }
6016 :
6017 162 : PG_RETURN_POINTER(state);
6018 : }
6019 :
6020 : Datum
6021 162 : int8_accum_inv(PG_FUNCTION_ARGS)
6022 : {
6023 : NumericAggState *state;
6024 :
6025 162 : state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
6026 :
6027 : /* Should not get here with no state */
6028 162 : if (state == NULL)
6029 0 : elog(ERROR, "int8_accum_inv called with NULL state");
6030 :
6031 162 : if (!PG_ARGISNULL(1))
6032 : {
6033 : /* Should never fail, all inputs have dscale 0 */
6034 144 : if (!do_numeric_discard(state, int64_to_numeric(PG_GETARG_INT64(1))))
6035 0 : elog(ERROR, "do_numeric_discard failed unexpectedly");
6036 : }
6037 :
6038 162 : PG_RETURN_POINTER(state);
6039 : }
6040 :
6041 : Datum
6042 36 : int8_avg_accum_inv(PG_FUNCTION_ARGS)
6043 : {
6044 : PolyNumAggState *state;
6045 :
6046 36 : state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
6047 :
6048 : /* Should not get here with no state */
6049 36 : if (state == NULL)
6050 0 : elog(ERROR, "int8_avg_accum_inv called with NULL state");
6051 :
6052 36 : if (!PG_ARGISNULL(1))
6053 : {
6054 : #ifdef HAVE_INT128
6055 24 : do_int128_discard(state, (int128) PG_GETARG_INT64(1));
6056 : #else
6057 : /* Should never fail, all inputs have dscale 0 */
6058 : if (!do_numeric_discard(state, int64_to_numeric(PG_GETARG_INT64(1))))
6059 : elog(ERROR, "do_numeric_discard failed unexpectedly");
6060 : #endif
6061 : }
6062 :
6063 36 : PG_RETURN_POINTER(state);
6064 : }
6065 :
6066 : Datum
6067 778 : numeric_poly_sum(PG_FUNCTION_ARGS)
6068 : {
6069 : #ifdef HAVE_INT128
6070 : PolyNumAggState *state;
6071 : Numeric res;
6072 : NumericVar result;
6073 :
6074 778 : state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
6075 :
6076 : /* If there were no non-null inputs, return NULL */
6077 778 : if (state == NULL || state->N == 0)
6078 24 : PG_RETURN_NULL();
6079 :
6080 754 : init_var(&result);
6081 :
6082 754 : int128_to_numericvar(state->sumX, &result);
6083 :
6084 754 : res = make_result(&result);
6085 :
6086 754 : free_var(&result);
6087 :
6088 754 : PG_RETURN_NUMERIC(res);
6089 : #else
6090 : return numeric_sum(fcinfo);
6091 : #endif
6092 : }
6093 :
6094 : Datum
6095 36 : numeric_poly_avg(PG_FUNCTION_ARGS)
6096 : {
6097 : #ifdef HAVE_INT128
6098 : PolyNumAggState *state;
6099 : NumericVar result;
6100 : Datum countd,
6101 : sumd;
6102 :
6103 36 : state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
6104 :
6105 : /* If there were no non-null inputs, return NULL */
6106 36 : if (state == NULL || state->N == 0)
6107 18 : PG_RETURN_NULL();
6108 :
6109 18 : init_var(&result);
6110 :
6111 18 : int128_to_numericvar(state->sumX, &result);
6112 :
6113 18 : countd = NumericGetDatum(int64_to_numeric(state->N));
6114 18 : sumd = NumericGetDatum(make_result(&result));
6115 :
6116 18 : free_var(&result);
6117 :
6118 18 : PG_RETURN_DATUM(DirectFunctionCall2(numeric_div, sumd, countd));
6119 : #else
6120 : return numeric_avg(fcinfo);
6121 : #endif
6122 : }
6123 :
6124 : Datum
6125 78 : numeric_avg(PG_FUNCTION_ARGS)
6126 : {
6127 : NumericAggState *state;
6128 : Datum N_datum;
6129 : Datum sumX_datum;
6130 : NumericVar sumX_var;
6131 :
6132 78 : state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
6133 :
6134 : /* If there were no non-null inputs, return NULL */
6135 78 : if (state == NULL || NA_TOTAL_COUNT(state) == 0)
6136 18 : PG_RETURN_NULL();
6137 :
6138 60 : if (state->NaNcount > 0) /* there was at least one NaN input */
6139 6 : PG_RETURN_NUMERIC(make_result(&const_nan));
6140 :
6141 : /* adding plus and minus infinities gives NaN */
6142 54 : if (state->pInfcount > 0 && state->nInfcount > 0)
6143 6 : PG_RETURN_NUMERIC(make_result(&const_nan));
6144 48 : if (state->pInfcount > 0)
6145 18 : PG_RETURN_NUMERIC(make_result(&const_pinf));
6146 30 : if (state->nInfcount > 0)
6147 6 : PG_RETURN_NUMERIC(make_result(&const_ninf));
6148 :
6149 24 : N_datum = NumericGetDatum(int64_to_numeric(state->N));
6150 :
6151 24 : init_var(&sumX_var);
6152 24 : accum_sum_final(&state->sumX, &sumX_var);
6153 24 : sumX_datum = NumericGetDatum(make_result(&sumX_var));
6154 24 : free_var(&sumX_var);
6155 :
6156 24 : PG_RETURN_DATUM(DirectFunctionCall2(numeric_div, sumX_datum, N_datum));
6157 : }
6158 :
6159 : Datum
6160 170906 : numeric_sum(PG_FUNCTION_ARGS)
6161 : {
6162 : NumericAggState *state;
6163 : NumericVar sumX_var;
6164 : Numeric result;
6165 :
6166 170906 : state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
6167 :
6168 : /* If there were no non-null inputs, return NULL */
6169 170906 : if (state == NULL || NA_TOTAL_COUNT(state) == 0)
6170 18 : PG_RETURN_NULL();
6171 :
6172 170888 : if (state->NaNcount > 0) /* there was at least one NaN input */
6173 18 : PG_RETURN_NUMERIC(make_result(&const_nan));
6174 :
6175 : /* adding plus and minus infinities gives NaN */
6176 170870 : if (state->pInfcount > 0 && state->nInfcount > 0)
6177 6 : PG_RETURN_NUMERIC(make_result(&const_nan));
6178 170864 : if (state->pInfcount > 0)
6179 18 : PG_RETURN_NUMERIC(make_result(&const_pinf));
6180 170846 : if (state->nInfcount > 0)
6181 6 : PG_RETURN_NUMERIC(make_result(&const_ninf));
6182 :
6183 170840 : init_var(&sumX_var);
6184 170840 : accum_sum_final(&state->sumX, &sumX_var);
6185 170840 : result = make_result(&sumX_var);
6186 170840 : free_var(&sumX_var);
6187 :
6188 170840 : PG_RETURN_NUMERIC(result);
6189 : }
6190 :
6191 : /*
6192 : * Workhorse routine for the standard deviance and variance
6193 : * aggregates. 'state' is aggregate's transition state.
6194 : * 'variance' specifies whether we should calculate the
6195 : * variance or the standard deviation. 'sample' indicates whether the
6196 : * caller is interested in the sample or the population
6197 : * variance/stddev.
6198 : *
6199 : * If appropriate variance statistic is undefined for the input,
6200 : * *is_null is set to true and NULL is returned.
6201 : */
6202 : static Numeric
6203 986 : numeric_stddev_internal(NumericAggState *state,
6204 : bool variance, bool sample,
6205 : bool *is_null)
6206 : {
6207 : Numeric res;
6208 : NumericVar vN,
6209 : vsumX,
6210 : vsumX2,
6211 : vNminus1;
6212 : int64 totCount;
6213 : int rscale;
6214 :
6215 : /*
6216 : * Sample stddev and variance are undefined when N <= 1; population stddev
6217 : * is undefined when N == 0. Return NULL in either case (note that NaNs
6218 : * and infinities count as normal inputs for this purpose).
6219 : */
6220 986 : if (state == NULL || (totCount = NA_TOTAL_COUNT(state)) == 0)
6221 : {
6222 0 : *is_null = true;
6223 0 : return NULL;
6224 : }
6225 :
6226 986 : if (sample && totCount <= 1)
6227 : {
6228 132 : *is_null = true;
6229 132 : return NULL;
6230 : }
6231 :
6232 854 : *is_null = false;
6233 :
6234 : /*
6235 : * Deal with NaN and infinity cases. By analogy to the behavior of the
6236 : * float8 functions, any infinity input produces NaN output.
6237 : */
6238 854 : if (state->NaNcount > 0 || state->pInfcount > 0 || state->nInfcount > 0)
6239 54 : return make_result(&const_nan);
6240 :
6241 : /* OK, normal calculation applies */
6242 800 : init_var(&vN);
6243 800 : init_var(&vsumX);
6244 800 : init_var(&vsumX2);
6245 :
6246 800 : int64_to_numericvar(state->N, &vN);
6247 800 : accum_sum_final(&(state->sumX), &vsumX);
6248 800 : accum_sum_final(&(state->sumX2), &vsumX2);
6249 :
6250 800 : init_var(&vNminus1);
6251 800 : sub_var(&vN, &const_one, &vNminus1);
6252 :
6253 : /* compute rscale for mul_var calls */
6254 800 : rscale = vsumX.dscale * 2;
6255 :
6256 800 : mul_var(&vsumX, &vsumX, &vsumX, rscale); /* vsumX = sumX * sumX */
6257 800 : mul_var(&vN, &vsumX2, &vsumX2, rscale); /* vsumX2 = N * sumX2 */
6258 800 : sub_var(&vsumX2, &vsumX, &vsumX2); /* N * sumX2 - sumX * sumX */
6259 :
6260 800 : if (cmp_var(&vsumX2, &const_zero) <= 0)
6261 : {
6262 : /* Watch out for roundoff error producing a negative numerator */
6263 80 : res = make_result(&const_zero);
6264 : }
6265 : else
6266 : {
6267 720 : if (sample)
6268 492 : mul_var(&vN, &vNminus1, &vNminus1, 0); /* N * (N - 1) */
6269 : else
6270 228 : mul_var(&vN, &vN, &vNminus1, 0); /* N * N */
6271 720 : rscale = select_div_scale(&vsumX2, &vNminus1);
6272 720 : div_var(&vsumX2, &vNminus1, &vsumX, rscale, true, true); /* variance */
6273 720 : if (!variance)
6274 378 : sqrt_var(&vsumX, &vsumX, rscale); /* stddev */
6275 :
6276 720 : res = make_result(&vsumX);
6277 : }
6278 :
6279 800 : free_var(&vNminus1);
6280 800 : free_var(&vsumX);
6281 800 : free_var(&vsumX2);
6282 :
6283 800 : return res;
6284 : }
6285 :
6286 : Datum
6287 180 : numeric_var_samp(PG_FUNCTION_ARGS)
6288 : {
6289 : NumericAggState *state;
6290 : Numeric res;
6291 : bool is_null;
6292 :
6293 180 : state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
6294 :
6295 180 : res = numeric_stddev_internal(state, true, true, &is_null);
6296 :
6297 180 : if (is_null)
6298 42 : PG_RETURN_NULL();
6299 : else
6300 138 : PG_RETURN_NUMERIC(res);
6301 : }
6302 :
6303 : Datum
6304 174 : numeric_stddev_samp(PG_FUNCTION_ARGS)
6305 : {
6306 : NumericAggState *state;
6307 : Numeric res;
6308 : bool is_null;
6309 :
6310 174 : state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
6311 :
6312 174 : res = numeric_stddev_internal(state, false, true, &is_null);
6313 :
6314 174 : if (is_null)
6315 42 : PG_RETURN_NULL();
6316 : else
6317 132 : PG_RETURN_NUMERIC(res);
6318 : }
6319 :
6320 : Datum
6321 114 : numeric_var_pop(PG_FUNCTION_ARGS)
6322 : {
6323 : NumericAggState *state;
6324 : Numeric res;
6325 : bool is_null;
6326 :
6327 114 : state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
6328 :
6329 114 : res = numeric_stddev_internal(state, true, false, &is_null);
6330 :
6331 114 : if (is_null)
6332 0 : PG_RETURN_NULL();
6333 : else
6334 114 : PG_RETURN_NUMERIC(res);
6335 : }
6336 :
6337 : Datum
6338 96 : numeric_stddev_pop(PG_FUNCTION_ARGS)
6339 : {
6340 : NumericAggState *state;
6341 : Numeric res;
6342 : bool is_null;
6343 :
6344 96 : state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
6345 :
6346 96 : res = numeric_stddev_internal(state, false, false, &is_null);
6347 :
6348 96 : if (is_null)
6349 0 : PG_RETURN_NULL();
6350 : else
6351 96 : PG_RETURN_NUMERIC(res);
6352 : }
6353 :
6354 : #ifdef HAVE_INT128
6355 : static Numeric
6356 422 : numeric_poly_stddev_internal(Int128AggState *state,
6357 : bool variance, bool sample,
6358 : bool *is_null)
6359 : {
6360 : NumericAggState numstate;
6361 : Numeric res;
6362 :
6363 : /* Initialize an empty agg state */
6364 422 : memset(&numstate, 0, sizeof(NumericAggState));
6365 :
6366 422 : if (state)
6367 : {
6368 : NumericVar tmp_var;
6369 :
6370 422 : numstate.N = state->N;
6371 :
6372 422 : init_var(&tmp_var);
6373 :
6374 422 : int128_to_numericvar(state->sumX, &tmp_var);
6375 422 : accum_sum_add(&numstate.sumX, &tmp_var);
6376 :
6377 422 : int128_to_numericvar(state->sumX2, &tmp_var);
6378 422 : accum_sum_add(&numstate.sumX2, &tmp_var);
6379 :
6380 422 : free_var(&tmp_var);
6381 : }
6382 :
6383 422 : res = numeric_stddev_internal(&numstate, variance, sample, is_null);
6384 :
6385 422 : if (numstate.sumX.ndigits > 0)
6386 : {
6387 422 : pfree(numstate.sumX.pos_digits);
6388 422 : pfree(numstate.sumX.neg_digits);
6389 : }
6390 422 : if (numstate.sumX2.ndigits > 0)
6391 : {
6392 422 : pfree(numstate.sumX2.pos_digits);
6393 422 : pfree(numstate.sumX2.neg_digits);
6394 : }
6395 :
6396 422 : return res;
6397 : }
6398 : #endif
6399 :
6400 : Datum
6401 126 : numeric_poly_var_samp(PG_FUNCTION_ARGS)
6402 : {
6403 : #ifdef HAVE_INT128
6404 : PolyNumAggState *state;
6405 : Numeric res;
6406 : bool is_null;
6407 :
6408 126 : state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
6409 :
6410 126 : res = numeric_poly_stddev_internal(state, true, true, &is_null);
6411 :
6412 126 : if (is_null)
6413 24 : PG_RETURN_NULL();
6414 : else
6415 102 : PG_RETURN_NUMERIC(res);
6416 : #else
6417 : return numeric_var_samp(fcinfo);
6418 : #endif
6419 : }
6420 :
6421 : Datum
6422 164 : numeric_poly_stddev_samp(PG_FUNCTION_ARGS)
6423 : {
6424 : #ifdef HAVE_INT128
6425 : PolyNumAggState *state;
6426 : Numeric res;
6427 : bool is_null;
6428 :
6429 164 : state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
6430 :
6431 164 : res = numeric_poly_stddev_internal(state, false, true, &is_null);
6432 :
6433 164 : if (is_null)
6434 24 : PG_RETURN_NULL();
6435 : else
6436 140 : PG_RETURN_NUMERIC(res);
6437 : #else
6438 : return numeric_stddev_samp(fcinfo);
6439 : #endif
6440 : }
6441 :
6442 : Datum
6443 60 : numeric_poly_var_pop(PG_FUNCTION_ARGS)
6444 : {
6445 : #ifdef HAVE_INT128
6446 : PolyNumAggState *state;
6447 : Numeric res;
6448 : bool is_null;
6449 :
6450 60 : state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
6451 :
6452 60 : res = numeric_poly_stddev_internal(state, true, false, &is_null);
6453 :
6454 60 : if (is_null)
6455 0 : PG_RETURN_NULL();
6456 : else
6457 60 : PG_RETURN_NUMERIC(res);
6458 : #else
6459 : return numeric_var_pop(fcinfo);
6460 : #endif
6461 : }
6462 :
6463 : Datum
6464 72 : numeric_poly_stddev_pop(PG_FUNCTION_ARGS)
6465 : {
6466 : #ifdef HAVE_INT128
6467 : PolyNumAggState *state;
6468 : Numeric res;
6469 : bool is_null;
6470 :
6471 72 : state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
6472 :
6473 72 : res = numeric_poly_stddev_internal(state, false, false, &is_null);
6474 :
6475 72 : if (is_null)
6476 0 : PG_RETURN_NULL();
6477 : else
6478 72 : PG_RETURN_NUMERIC(res);
6479 : #else
6480 : return numeric_stddev_pop(fcinfo);
6481 : #endif
6482 : }
6483 :
6484 : /*
6485 : * SUM transition functions for integer datatypes.
6486 : *
6487 : * To avoid overflow, we use accumulators wider than the input datatype.
6488 : * A Numeric accumulator is needed for int8 input; for int4 and int2
6489 : * inputs, we use int8 accumulators which should be sufficient for practical
6490 : * purposes. (The latter two therefore don't really belong in this file,
6491 : * but we keep them here anyway.)
6492 : *
6493 : * Because SQL defines the SUM() of no values to be NULL, not zero,
6494 : * the initial condition of the transition data value needs to be NULL. This
6495 : * means we can't rely on ExecAgg to automatically insert the first non-null
6496 : * data value into the transition data: it doesn't know how to do the type
6497 : * conversion. The upshot is that these routines have to be marked non-strict
6498 : * and handle substitution of the first non-null input themselves.
6499 : *
6500 : * Note: these functions are used only in plain aggregation mode.
6501 : * In moving-aggregate mode, we use intX_avg_accum and intX_avg_accum_inv.
6502 : */
6503 :
6504 : Datum
6505 24 : int2_sum(PG_FUNCTION_ARGS)
6506 : {
6507 : int64 newval;
6508 :
6509 24 : if (PG_ARGISNULL(0))
6510 : {
6511 : /* No non-null input seen so far... */
6512 6 : if (PG_ARGISNULL(1))
6513 0 : PG_RETURN_NULL(); /* still no non-null */
6514 : /* This is the first non-null input. */
6515 6 : newval = (int64) PG_GETARG_INT16(1);
6516 6 : PG_RETURN_INT64(newval);
6517 : }
6518 :
6519 : /*
6520 : * If we're invoked as an aggregate, we can cheat and modify our first
6521 : * parameter in-place to avoid palloc overhead. If not, we need to return
6522 : * the new value of the transition variable. (If int8 is pass-by-value,
6523 : * then of course this is useless as well as incorrect, so just ifdef it
6524 : * out.)
6525 : */
6526 : #ifndef USE_FLOAT8_BYVAL /* controls int8 too */
6527 : if (AggCheckCallContext(fcinfo, NULL))
6528 : {
6529 : int64 *oldsum = (int64 *) PG_GETARG_POINTER(0);
6530 :
6531 : /* Leave the running sum unchanged in the new input is null */
6532 : if (!PG_ARGISNULL(1))
6533 : *oldsum = *oldsum + (int64) PG_GETARG_INT16(1);
6534 :
6535 : PG_RETURN_POINTER(oldsum);
6536 : }
6537 : else
6538 : #endif
6539 : {
6540 18 : int64 oldsum = PG_GETARG_INT64(0);
6541 :
6542 : /* Leave sum unchanged if new input is null. */
6543 18 : if (PG_ARGISNULL(1))
6544 0 : PG_RETURN_INT64(oldsum);
6545 :
6546 : /* OK to do the addition. */
6547 18 : newval = oldsum + (int64) PG_GETARG_INT16(1);
6548 :
6549 18 : PG_RETURN_INT64(newval);
6550 : }
6551 : }
6552 :
6553 : Datum
6554 3602120 : int4_sum(PG_FUNCTION_ARGS)
6555 : {
6556 : int64 newval;
6557 :
6558 3602120 : if (PG_ARGISNULL(0))
6559 : {
6560 : /* No non-null input seen so far... */
6561 206522 : if (PG_ARGISNULL(1))
6562 986 : PG_RETURN_NULL(); /* still no non-null */
6563 : /* This is the first non-null input. */
6564 205536 : newval = (int64) PG_GETARG_INT32(1);
6565 205536 : PG_RETURN_INT64(newval);
6566 : }
6567 :
6568 : /*
6569 : * If we're invoked as an aggregate, we can cheat and modify our first
6570 : * parameter in-place to avoid palloc overhead. If not, we need to return
6571 : * the new value of the transition variable. (If int8 is pass-by-value,
6572 : * then of course this is useless as well as incorrect, so just ifdef it
6573 : * out.)
6574 : */
6575 : #ifndef USE_FLOAT8_BYVAL /* controls int8 too */
6576 : if (AggCheckCallContext(fcinfo, NULL))
6577 : {
6578 : int64 *oldsum = (int64 *) PG_GETARG_POINTER(0);
6579 :
6580 : /* Leave the running sum unchanged in the new input is null */
6581 : if (!PG_ARGISNULL(1))
6582 : *oldsum = *oldsum + (int64) PG_GETARG_INT32(1);
6583 :
6584 : PG_RETURN_POINTER(oldsum);
6585 : }
6586 : else
6587 : #endif
6588 : {
6589 3395598 : int64 oldsum = PG_GETARG_INT64(0);
6590 :
6591 : /* Leave sum unchanged if new input is null. */
6592 3395598 : if (PG_ARGISNULL(1))
6593 874 : PG_RETURN_INT64(oldsum);
6594 :
6595 : /* OK to do the addition. */
6596 3394724 : newval = oldsum + (int64) PG_GETARG_INT32(1);
6597 :
6598 3394724 : PG_RETURN_INT64(newval);
6599 : }
6600 : }
6601 :
6602 : /*
6603 : * Note: this function is obsolete, it's no longer used for SUM(int8).
6604 : */
6605 : Datum
6606 0 : int8_sum(PG_FUNCTION_ARGS)
6607 : {
6608 : Numeric oldsum;
6609 :
6610 0 : if (PG_ARGISNULL(0))
6611 : {
6612 : /* No non-null input seen so far... */
6613 0 : if (PG_ARGISNULL(1))
6614 0 : PG_RETURN_NULL(); /* still no non-null */
6615 : /* This is the first non-null input. */
6616 0 : PG_RETURN_NUMERIC(int64_to_numeric(PG_GETARG_INT64(1)));
6617 : }
6618 :
6619 : /*
6620 : * Note that we cannot special-case the aggregate case here, as we do for
6621 : * int2_sum and int4_sum: numeric is of variable size, so we cannot modify
6622 : * our first parameter in-place.
6623 : */
6624 :
6625 0 : oldsum = PG_GETARG_NUMERIC(0);
6626 :
6627 : /* Leave sum unchanged if new input is null. */
6628 0 : if (PG_ARGISNULL(1))
6629 0 : PG_RETURN_NUMERIC(oldsum);
6630 :
6631 : /* OK to do the addition. */
6632 0 : PG_RETURN_DATUM(DirectFunctionCall2(numeric_add,
6633 : NumericGetDatum(oldsum),
6634 : NumericGetDatum(int64_to_numeric(PG_GETARG_INT64(1)))));
6635 : }
6636 :
6637 :
6638 : /*
6639 : * Routines for avg(int2) and avg(int4). The transition datatype
6640 : * is a two-element int8 array, holding count and sum.
6641 : *
6642 : * These functions are also used for sum(int2) and sum(int4) when
6643 : * operating in moving-aggregate mode, since for correct inverse transitions
6644 : * we need to count the inputs.
6645 : */
6646 :
6647 : typedef struct Int8TransTypeData
6648 : {
6649 : int64 count;
6650 : int64 sum;
6651 : } Int8TransTypeData;
6652 :
6653 : Datum
6654 42 : int2_avg_accum(PG_FUNCTION_ARGS)
6655 : {
6656 : ArrayType *transarray;
6657 42 : int16 newval = PG_GETARG_INT16(1);
6658 : Int8TransTypeData *transdata;
6659 :
6660 : /*
6661 : * If we're invoked as an aggregate, we can cheat and modify our first
6662 : * parameter in-place to reduce palloc overhead. Otherwise we need to make
6663 : * a copy of it before scribbling on it.
6664 : */
6665 42 : if (AggCheckCallContext(fcinfo, NULL))
6666 42 : transarray = PG_GETARG_ARRAYTYPE_P(0);
6667 : else
6668 0 : transarray = PG_GETARG_ARRAYTYPE_P_COPY(0);
6669 :
6670 42 : if (ARR_HASNULL(transarray) ||
6671 42 : ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
6672 0 : elog(ERROR, "expected 2-element int8 array");
6673 :
6674 42 : transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
6675 42 : transdata->count++;
6676 42 : transdata->sum += newval;
6677 :
6678 42 : PG_RETURN_ARRAYTYPE_P(transarray);
6679 : }
6680 :
6681 : Datum
6682 2620302 : int4_avg_accum(PG_FUNCTION_ARGS)
6683 : {
6684 : ArrayType *transarray;
6685 2620302 : int32 newval = PG_GETARG_INT32(1);
6686 : Int8TransTypeData *transdata;
6687 :
6688 : /*
6689 : * If we're invoked as an aggregate, we can cheat and modify our first
6690 : * parameter in-place to reduce palloc overhead. Otherwise we need to make
6691 : * a copy of it before scribbling on it.
6692 : */
6693 2620302 : if (AggCheckCallContext(fcinfo, NULL))
6694 2620302 : transarray = PG_GETARG_ARRAYTYPE_P(0);
6695 : else
6696 0 : transarray = PG_GETARG_ARRAYTYPE_P_COPY(0);
6697 :
6698 2620302 : if (ARR_HASNULL(transarray) ||
6699 2620302 : ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
6700 0 : elog(ERROR, "expected 2-element int8 array");
6701 :
6702 2620302 : transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
6703 2620302 : transdata->count++;
6704 2620302 : transdata->sum += newval;
6705 :
6706 2620302 : PG_RETURN_ARRAYTYPE_P(transarray);
6707 : }
6708 :
6709 : Datum
6710 3522 : int4_avg_combine(PG_FUNCTION_ARGS)
6711 : {
6712 : ArrayType *transarray1;
6713 : ArrayType *transarray2;
6714 : Int8TransTypeData *state1;
6715 : Int8TransTypeData *state2;
6716 :
6717 3522 : if (!AggCheckCallContext(fcinfo, NULL))
6718 0 : elog(ERROR, "aggregate function called in non-aggregate context");
6719 :
6720 3522 : transarray1 = PG_GETARG_ARRAYTYPE_P(0);
6721 3522 : transarray2 = PG_GETARG_ARRAYTYPE_P(1);
6722 :
6723 3522 : if (ARR_HASNULL(transarray1) ||
6724 3522 : ARR_SIZE(transarray1) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
6725 0 : elog(ERROR, "expected 2-element int8 array");
6726 :
6727 3522 : if (ARR_HASNULL(transarray2) ||
6728 3522 : ARR_SIZE(transarray2) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
6729 0 : elog(ERROR, "expected 2-element int8 array");
6730 :
6731 3522 : state1 = (Int8TransTypeData *) ARR_DATA_PTR(transarray1);
6732 3522 : state2 = (Int8TransTypeData *) ARR_DATA_PTR(transarray2);
6733 :
6734 3522 : state1->count += state2->count;
6735 3522 : state1->sum += state2->sum;
6736 :
6737 3522 : PG_RETURN_ARRAYTYPE_P(transarray1);
6738 : }
6739 :
6740 : Datum
6741 12 : int2_avg_accum_inv(PG_FUNCTION_ARGS)
6742 : {
6743 : ArrayType *transarray;
6744 12 : int16 newval = PG_GETARG_INT16(1);
6745 : Int8TransTypeData *transdata;
6746 :
6747 : /*
6748 : * If we're invoked as an aggregate, we can cheat and modify our first
6749 : * parameter in-place to reduce palloc overhead. Otherwise we need to make
6750 : * a copy of it before scribbling on it.
6751 : */
6752 12 : if (AggCheckCallContext(fcinfo, NULL))
6753 12 : transarray = PG_GETARG_ARRAYTYPE_P(0);
6754 : else
6755 0 : transarray = PG_GETARG_ARRAYTYPE_P_COPY(0);
6756 :
6757 12 : if (ARR_HASNULL(transarray) ||
6758 12 : ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
6759 0 : elog(ERROR, "expected 2-element int8 array");
6760 :
6761 12 : transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
6762 12 : transdata->count--;
6763 12 : transdata->sum -= newval;
6764 :
6765 12 : PG_RETURN_ARRAYTYPE_P(transarray);
6766 : }
6767 :
6768 : Datum
6769 1452 : int4_avg_accum_inv(PG_FUNCTION_ARGS)
6770 : {
6771 : ArrayType *transarray;
6772 1452 : int32 newval = PG_GETARG_INT32(1);
6773 : Int8TransTypeData *transdata;
6774 :
6775 : /*
6776 : * If we're invoked as an aggregate, we can cheat and modify our first
6777 : * parameter in-place to reduce palloc overhead. Otherwise we need to make
6778 : * a copy of it before scribbling on it.
6779 : */
6780 1452 : if (AggCheckCallContext(fcinfo, NULL))
6781 1452 : transarray = PG_GETARG_ARRAYTYPE_P(0);
6782 : else
6783 0 : transarray = PG_GETARG_ARRAYTYPE_P_COPY(0);
6784 :
6785 1452 : if (ARR_HASNULL(transarray) ||
6786 1452 : ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
6787 0 : elog(ERROR, "expected 2-element int8 array");
6788 :
6789 1452 : transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
6790 1452 : transdata->count--;
6791 1452 : transdata->sum -= newval;
6792 :
6793 1452 : PG_RETURN_ARRAYTYPE_P(transarray);
6794 : }
6795 :
6796 : Datum
6797 10774 : int8_avg(PG_FUNCTION_ARGS)
6798 : {
6799 10774 : ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
6800 : Int8TransTypeData *transdata;
6801 : Datum countd,
6802 : sumd;
6803 :
6804 10774 : if (ARR_HASNULL(transarray) ||
6805 10774 : ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
6806 0 : elog(ERROR, "expected 2-element int8 array");
6807 10774 : transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
6808 :
6809 : /* SQL defines AVG of no values to be NULL */
6810 10774 : if (transdata->count == 0)
6811 118 : PG_RETURN_NULL();
6812 :
6813 10656 : countd = NumericGetDatum(int64_to_numeric(transdata->count));
6814 10656 : sumd = NumericGetDatum(int64_to_numeric(transdata->sum));
6815 :
6816 10656 : PG_RETURN_DATUM(DirectFunctionCall2(numeric_div, sumd, countd));
6817 : }
6818 :
6819 : /*
6820 : * SUM(int2) and SUM(int4) both return int8, so we can use this
6821 : * final function for both.
6822 : */
6823 : Datum
6824 3834 : int2int4_sum(PG_FUNCTION_ARGS)
6825 : {
6826 3834 : ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
6827 : Int8TransTypeData *transdata;
6828 :
6829 3834 : if (ARR_HASNULL(transarray) ||
6830 3834 : ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
6831 0 : elog(ERROR, "expected 2-element int8 array");
6832 3834 : transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
6833 :
6834 : /* SQL defines SUM of no values to be NULL */
6835 3834 : if (transdata->count == 0)
6836 480 : PG_RETURN_NULL();
6837 :
6838 3354 : PG_RETURN_DATUM(Int64GetDatumFast(transdata->sum));
6839 : }
6840 :
6841 :
6842 : /* ----------------------------------------------------------------------
6843 : *
6844 : * Debug support
6845 : *
6846 : * ----------------------------------------------------------------------
6847 : */
6848 :
6849 : #ifdef NUMERIC_DEBUG
6850 :
6851 : /*
6852 : * dump_numeric() - Dump a value in the db storage format for debugging
6853 : */
6854 : static void
6855 : dump_numeric(const char *str, Numeric num)
6856 : {
6857 : NumericDigit *digits = NUMERIC_DIGITS(num);
6858 : int ndigits;
6859 : int i;
6860 :
6861 : ndigits = NUMERIC_NDIGITS(num);
6862 :
6863 : printf("%s: NUMERIC w=%d d=%d ", str,
6864 : NUMERIC_WEIGHT(num), NUMERIC_DSCALE(num));
6865 : switch (NUMERIC_SIGN(num))
6866 : {
6867 : case NUMERIC_POS:
6868 : printf("POS");
6869 : break;
6870 : case NUMERIC_NEG:
6871 : printf("NEG");
6872 : break;
6873 : case NUMERIC_NAN:
6874 : printf("NaN");
6875 : break;
6876 : case NUMERIC_PINF:
6877 : printf("Infinity");
6878 : break;
6879 : case NUMERIC_NINF:
6880 : printf("-Infinity");
6881 : break;
6882 : default:
6883 : printf("SIGN=0x%x", NUMERIC_SIGN(num));
6884 : break;
6885 : }
6886 :
6887 : for (i = 0; i < ndigits; i++)
6888 : printf(" %0*d", DEC_DIGITS, digits[i]);
6889 : printf("\n");
6890 : }
6891 :
6892 :
6893 : /*
6894 : * dump_var() - Dump a value in the variable format for debugging
6895 : */
6896 : static void
6897 : dump_var(const char *str, NumericVar *var)
6898 : {
6899 : int i;
6900 :
6901 : printf("%s: VAR w=%d d=%d ", str, var->weight, var->dscale);
6902 : switch (var->sign)
6903 : {
6904 : case NUMERIC_POS:
6905 : printf("POS");
6906 : break;
6907 : case NUMERIC_NEG:
6908 : printf("NEG");
6909 : break;
6910 : case NUMERIC_NAN:
6911 : printf("NaN");
6912 : break;
6913 : case NUMERIC_PINF:
6914 : printf("Infinity");
6915 : break;
6916 : case NUMERIC_NINF:
6917 : printf("-Infinity");
6918 : break;
6919 : default:
6920 : printf("SIGN=0x%x", var->sign);
6921 : break;
6922 : }
6923 :
6924 : for (i = 0; i < var->ndigits; i++)
6925 : printf(" %0*d", DEC_DIGITS, var->digits[i]);
6926 :
6927 : printf("\n");
6928 : }
6929 : #endif /* NUMERIC_DEBUG */
6930 :
6931 :
6932 : /* ----------------------------------------------------------------------
6933 : *
6934 : * Local functions follow
6935 : *
6936 : * In general, these do not support "special" (NaN or infinity) inputs;
6937 : * callers should handle those possibilities first.
6938 : * (There are one or two exceptions, noted in their header comments.)
6939 : *
6940 : * ----------------------------------------------------------------------
6941 : */
6942 :
6943 :
6944 : /*
6945 : * alloc_var() -
6946 : *
6947 : * Allocate a digit buffer of ndigits digits (plus a spare digit for rounding)
6948 : */
6949 : static void
6950 2104584 : alloc_var(NumericVar *var, int ndigits)
6951 : {
6952 2104584 : digitbuf_free(var->buf);
6953 2104584 : var->buf = digitbuf_alloc(ndigits + 1);
6954 2104584 : var->buf[0] = 0; /* spare digit for rounding */
6955 2104584 : var->digits = var->buf + 1;
6956 2104584 : var->ndigits = ndigits;
6957 2104584 : }
6958 :
6959 :
6960 : /*
6961 : * free_var() -
6962 : *
6963 : * Return the digit buffer of a variable to the free pool
6964 : */
6965 : static void
6966 3409894 : free_var(NumericVar *var)
6967 : {
6968 3409894 : digitbuf_free(var->buf);
6969 3409894 : var->buf = NULL;
6970 3409894 : var->digits = NULL;
6971 3409894 : var->sign = NUMERIC_NAN;
6972 3409894 : }
6973 :
6974 :
6975 : /*
6976 : * zero_var() -
6977 : *
6978 : * Set a variable to ZERO.
6979 : * Note: its dscale is not touched.
6980 : */
6981 : static void
6982 39870 : zero_var(NumericVar *var)
6983 : {
6984 39870 : digitbuf_free(var->buf);
6985 39870 : var->buf = NULL;
6986 39870 : var->digits = NULL;
6987 39870 : var->ndigits = 0;
6988 39870 : var->weight = 0; /* by convention; doesn't really matter */
6989 39870 : var->sign = NUMERIC_POS; /* anything but NAN... */
6990 39870 : }
6991 :
6992 :
6993 : /*
6994 : * set_var_from_str()
6995 : *
6996 : * Parse a string and put the number into a variable
6997 : *
6998 : * This function does not handle leading or trailing spaces. It returns
6999 : * the end+1 position parsed into *endptr, so that caller can check for
7000 : * trailing spaces/garbage if deemed necessary.
7001 : *
7002 : * cp is the place to actually start parsing; str is what to use in error
7003 : * reports. (Typically cp would be the same except advanced over spaces.)
7004 : *
7005 : * Returns true on success, false on failure (if escontext points to an
7006 : * ErrorSaveContext; otherwise errors are thrown).
7007 : */
7008 : static bool
7009 129254 : set_var_from_str(const char *str, const char *cp,
7010 : NumericVar *dest, const char **endptr,
7011 : Node *escontext)
7012 : {
7013 129254 : bool have_dp = false;
7014 : int i;
7015 : unsigned char *decdigits;
7016 129254 : int sign = NUMERIC_POS;
7017 129254 : int dweight = -1;
7018 : int ddigits;
7019 129254 : int dscale = 0;
7020 : int weight;
7021 : int ndigits;
7022 : int offset;
7023 : NumericDigit *digits;
7024 :
7025 : /*
7026 : * We first parse the string to extract decimal digits and determine the
7027 : * correct decimal weight. Then convert to NBASE representation.
7028 : */
7029 129254 : switch (*cp)
7030 : {
7031 0 : case '+':
7032 0 : sign = NUMERIC_POS;
7033 0 : cp++;
7034 0 : break;
7035 :
7036 300 : case '-':
7037 300 : sign = NUMERIC_NEG;
7038 300 : cp++;
7039 300 : break;
7040 : }
7041 :
7042 129254 : if (*cp == '.')
7043 : {
7044 384 : have_dp = true;
7045 384 : cp++;
7046 : }
7047 :
7048 129254 : if (!isdigit((unsigned char) *cp))
7049 0 : goto invalid_syntax;
7050 :
7051 129254 : decdigits = (unsigned char *) palloc(strlen(cp) + DEC_DIGITS * 2);
7052 :
7053 : /* leading padding for digit alignment later */
7054 129254 : memset(decdigits, 0, DEC_DIGITS);
7055 129254 : i = DEC_DIGITS;
7056 :
7057 568992 : while (*cp)
7058 : {
7059 441070 : if (isdigit((unsigned char) *cp))
7060 : {
7061 422498 : decdigits[i++] = *cp++ - '0';
7062 422498 : if (!have_dp)
7063 349978 : dweight++;
7064 : else
7065 72520 : dscale++;
7066 : }
7067 18572 : else if (*cp == '.')
7068 : {
7069 17078 : if (have_dp)
7070 0 : goto invalid_syntax;
7071 17078 : have_dp = true;
7072 17078 : cp++;
7073 : /* decimal point must not be followed by underscore */
7074 17078 : if (*cp == '_')
7075 6 : goto invalid_syntax;
7076 : }
7077 1494 : else if (*cp == '_')
7078 : {
7079 : /* underscore must be followed by more digits */
7080 186 : cp++;
7081 186 : if (!isdigit((unsigned char) *cp))
7082 18 : goto invalid_syntax;
7083 : }
7084 : else
7085 1308 : break;
7086 : }
7087 :
7088 129230 : ddigits = i - DEC_DIGITS;
7089 : /* trailing padding for digit alignment later */
7090 129230 : memset(decdigits + i, 0, DEC_DIGITS - 1);
7091 :
7092 : /* Handle exponent, if any */
7093 129230 : if (*cp == 'e' || *cp == 'E')
7094 : {
7095 1260 : int64 exponent = 0;
7096 1260 : bool neg = false;
7097 :
7098 : /*
7099 : * At this point, dweight and dscale can't be more than about
7100 : * INT_MAX/2 due to the MaxAllocSize limit on string length, so
7101 : * constraining the exponent similarly should be enough to prevent
7102 : * integer overflow in this function. If the value is too large to
7103 : * fit in storage format, make_result() will complain about it later;
7104 : * for consistency use the same ereport errcode/text as make_result().
7105 : */
7106 :
7107 : /* exponent sign */
7108 1260 : cp++;
7109 1260 : if (*cp == '+')
7110 154 : cp++;
7111 1106 : else if (*cp == '-')
7112 : {
7113 470 : neg = true;
7114 470 : cp++;
7115 : }
7116 :
7117 : /* exponent digits */
7118 1260 : if (!isdigit((unsigned char) *cp))
7119 6 : goto invalid_syntax;
7120 :
7121 4440 : while (*cp)
7122 : {
7123 3204 : if (isdigit((unsigned char) *cp))
7124 : {
7125 3162 : exponent = exponent * 10 + (*cp++ - '0');
7126 3162 : if (exponent > PG_INT32_MAX / 2)
7127 6 : goto out_of_range;
7128 : }
7129 42 : else if (*cp == '_')
7130 : {
7131 : /* underscore must be followed by more digits */
7132 42 : cp++;
7133 42 : if (!isdigit((unsigned char) *cp))
7134 12 : goto invalid_syntax;
7135 : }
7136 : else
7137 0 : break;
7138 : }
7139 :
7140 1236 : if (neg)
7141 470 : exponent = -exponent;
7142 :
7143 1236 : dweight += (int) exponent;
7144 1236 : dscale -= (int) exponent;
7145 1236 : if (dscale < 0)
7146 562 : dscale = 0;
7147 : }
7148 :
7149 : /*
7150 : * Okay, convert pure-decimal representation to base NBASE. First we need
7151 : * to determine the converted weight and ndigits. offset is the number of
7152 : * decimal zeroes to insert before the first given digit to have a
7153 : * correctly aligned first NBASE digit.
7154 : */
7155 129206 : if (dweight >= 0)
7156 128454 : weight = (dweight + 1 + DEC_DIGITS - 1) / DEC_DIGITS - 1;
7157 : else
7158 752 : weight = -((-dweight - 1) / DEC_DIGITS + 1);
7159 129206 : offset = (weight + 1) * DEC_DIGITS - (dweight + 1);
7160 129206 : ndigits = (ddigits + offset + DEC_DIGITS - 1) / DEC_DIGITS;
7161 :
7162 129206 : alloc_var(dest, ndigits);
7163 129206 : dest->sign = sign;
7164 129206 : dest->weight = weight;
7165 129206 : dest->dscale = dscale;
7166 :
7167 129206 : i = DEC_DIGITS - offset;
7168 129206 : digits = dest->digits;
7169 :
7170 322534 : while (ndigits-- > 0)
7171 : {
7172 : #if DEC_DIGITS == 4
7173 193328 : *digits++ = ((decdigits[i] * 10 + decdigits[i + 1]) * 10 +
7174 193328 : decdigits[i + 2]) * 10 + decdigits[i + 3];
7175 : #elif DEC_DIGITS == 2
7176 : *digits++ = decdigits[i] * 10 + decdigits[i + 1];
7177 : #elif DEC_DIGITS == 1
7178 : *digits++ = decdigits[i];
7179 : #else
7180 : #error unsupported NBASE
7181 : #endif
7182 193328 : i += DEC_DIGITS;
7183 : }
7184 :
7185 129206 : pfree(decdigits);
7186 :
7187 : /* Strip any leading/trailing zeroes, and normalize weight if zero */
7188 129206 : strip_var(dest);
7189 :
7190 : /* Return end+1 position for caller */
7191 129206 : *endptr = cp;
7192 :
7193 129206 : return true;
7194 :
7195 6 : out_of_range:
7196 6 : ereturn(escontext, false,
7197 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
7198 : errmsg("value overflows numeric format")));
7199 :
7200 42 : invalid_syntax:
7201 42 : ereturn(escontext, false,
7202 : (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
7203 : errmsg("invalid input syntax for type %s: \"%s\"",
7204 : "numeric", str)));
7205 : }
7206 :
7207 :
7208 : /*
7209 : * Return the numeric value of a single hex digit.
7210 : */
7211 : static inline int
7212 708 : xdigit_value(char dig)
7213 : {
7214 894 : return dig >= '0' && dig <= '9' ? dig - '0' :
7215 294 : dig >= 'a' && dig <= 'f' ? dig - 'a' + 10 :
7216 108 : dig >= 'A' && dig <= 'F' ? dig - 'A' + 10 : -1;
7217 : }
7218 :
7219 : /*
7220 : * set_var_from_non_decimal_integer_str()
7221 : *
7222 : * Parse a string containing a non-decimal integer
7223 : *
7224 : * This function does not handle leading or trailing spaces. It returns
7225 : * the end+1 position parsed into *endptr, so that caller can check for
7226 : * trailing spaces/garbage if deemed necessary.
7227 : *
7228 : * cp is the place to actually start parsing; str is what to use in error
7229 : * reports. The number's sign and base prefix indicator (e.g., "0x") are
7230 : * assumed to have already been parsed, so cp should point to the number's
7231 : * first digit in the base specified.
7232 : *
7233 : * base is expected to be 2, 8 or 16.
7234 : *
7235 : * Returns true on success, false on failure (if escontext points to an
7236 : * ErrorSaveContext; otherwise errors are thrown).
7237 : */
7238 : static bool
7239 156 : set_var_from_non_decimal_integer_str(const char *str, const char *cp, int sign,
7240 : int base, NumericVar *dest,
7241 : const char **endptr, Node *escontext)
7242 : {
7243 156 : const char *firstdigit = cp;
7244 : int64 tmp;
7245 : int64 mul;
7246 : NumericVar tmp_var;
7247 :
7248 156 : init_var(&tmp_var);
7249 :
7250 156 : zero_var(dest);
7251 :
7252 : /*
7253 : * Process input digits in groups that fit in int64. Here "tmp" is the
7254 : * value of the digits in the group, and "mul" is base^n, where n is the
7255 : * number of digits in the group. Thus tmp < mul, and we must start a new
7256 : * group when mul * base threatens to overflow PG_INT64_MAX.
7257 : */
7258 156 : tmp = 0;
7259 156 : mul = 1;
7260 :
7261 156 : if (base == 16)
7262 : {
7263 828 : while (*cp)
7264 : {
7265 798 : if (isxdigit((unsigned char) *cp))
7266 : {
7267 708 : if (mul > PG_INT64_MAX / 16)
7268 : {
7269 : /* Add the contribution from this group of digits */
7270 30 : int64_to_numericvar(mul, &tmp_var);
7271 30 : mul_var(dest, &tmp_var, dest, 0);
7272 30 : int64_to_numericvar(tmp, &tmp_var);
7273 30 : add_var(dest, &tmp_var, dest);
7274 :
7275 : /* Result will overflow if weight overflows int16 */
7276 30 : if (dest->weight > NUMERIC_WEIGHT_MAX)
7277 0 : goto out_of_range;
7278 :
7279 : /* Begin a new group */
7280 30 : tmp = 0;
7281 30 : mul = 1;
7282 : }
7283 :
7284 708 : tmp = tmp * 16 + xdigit_value(*cp++);
7285 708 : mul = mul * 16;
7286 : }
7287 90 : else if (*cp == '_')
7288 : {
7289 : /* Underscore must be followed by more digits */
7290 66 : cp++;
7291 66 : if (!isxdigit((unsigned char) *cp))
7292 18 : goto invalid_syntax;
7293 : }
7294 : else
7295 24 : break;
7296 : }
7297 : }
7298 84 : else if (base == 8)
7299 : {
7300 636 : while (*cp)
7301 : {
7302 606 : if (*cp >= '0' && *cp <= '7')
7303 : {
7304 558 : if (mul > PG_INT64_MAX / 8)
7305 : {
7306 : /* Add the contribution from this group of digits */
7307 18 : int64_to_numericvar(mul, &tmp_var);
7308 18 : mul_var(dest, &tmp_var, dest, 0);
7309 18 : int64_to_numericvar(tmp, &tmp_var);
7310 18 : add_var(dest, &tmp_var, dest);
7311 :
7312 : /* Result will overflow if weight overflows int16 */
7313 18 : if (dest->weight > NUMERIC_WEIGHT_MAX)
7314 0 : goto out_of_range;
7315 :
7316 : /* Begin a new group */
7317 18 : tmp = 0;
7318 18 : mul = 1;
7319 : }
7320 :
7321 558 : tmp = tmp * 8 + (*cp++ - '0');
7322 558 : mul = mul * 8;
7323 : }
7324 48 : else if (*cp == '_')
7325 : {
7326 : /* Underscore must be followed by more digits */
7327 36 : cp++;
7328 36 : if (*cp < '0' || *cp > '7')
7329 0 : goto invalid_syntax;
7330 : }
7331 : else
7332 12 : break;
7333 : }
7334 : }
7335 42 : else if (base == 2)
7336 : {
7337 1560 : while (*cp)
7338 : {
7339 1530 : if (*cp >= '0' && *cp <= '1')
7340 : {
7341 1416 : if (mul > PG_INT64_MAX / 2)
7342 : {
7343 : /* Add the contribution from this group of digits */
7344 18 : int64_to_numericvar(mul, &tmp_var);
7345 18 : mul_var(dest, &tmp_var, dest, 0);
7346 18 : int64_to_numericvar(tmp, &tmp_var);
7347 18 : add_var(dest, &tmp_var, dest);
7348 :
7349 : /* Result will overflow if weight overflows int16 */
7350 18 : if (dest->weight > NUMERIC_WEIGHT_MAX)
7351 0 : goto out_of_range;
7352 :
7353 : /* Begin a new group */
7354 18 : tmp = 0;
7355 18 : mul = 1;
7356 : }
7357 :
7358 1416 : tmp = tmp * 2 + (*cp++ - '0');
7359 1416 : mul = mul * 2;
7360 : }
7361 114 : else if (*cp == '_')
7362 : {
7363 : /* Underscore must be followed by more digits */
7364 102 : cp++;
7365 102 : if (*cp < '0' || *cp > '1')
7366 0 : goto invalid_syntax;
7367 : }
7368 : else
7369 12 : break;
7370 : }
7371 : }
7372 : else
7373 : /* Should never happen; treat as invalid input */
7374 0 : goto invalid_syntax;
7375 :
7376 : /* Check that we got at least one digit */
7377 138 : if (unlikely(cp == firstdigit))
7378 0 : goto invalid_syntax;
7379 :
7380 : /* Add the contribution from the final group of digits */
7381 138 : int64_to_numericvar(mul, &tmp_var);
7382 138 : mul_var(dest, &tmp_var, dest, 0);
7383 138 : int64_to_numericvar(tmp, &tmp_var);
7384 138 : add_var(dest, &tmp_var, dest);
7385 :
7386 138 : if (dest->weight > NUMERIC_WEIGHT_MAX)
7387 0 : goto out_of_range;
7388 :
7389 138 : dest->sign = sign;
7390 :
7391 138 : free_var(&tmp_var);
7392 :
7393 : /* Return end+1 position for caller */
7394 138 : *endptr = cp;
7395 :
7396 138 : return true;
7397 :
7398 0 : out_of_range:
7399 0 : ereturn(escontext, false,
7400 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
7401 : errmsg("value overflows numeric format")));
7402 :
7403 18 : invalid_syntax:
7404 18 : ereturn(escontext, false,
7405 : (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
7406 : errmsg("invalid input syntax for type %s: \"%s\"",
7407 : "numeric", str)));
7408 : }
7409 :
7410 :
7411 : /*
7412 : * set_var_from_num() -
7413 : *
7414 : * Convert the packed db format into a variable
7415 : */
7416 : static void
7417 12940 : set_var_from_num(Numeric num, NumericVar *dest)
7418 : {
7419 : int ndigits;
7420 :
7421 12940 : ndigits = NUMERIC_NDIGITS(num);
7422 :
7423 12940 : alloc_var(dest, ndigits);
7424 :
7425 12940 : dest->weight = NUMERIC_WEIGHT(num);
7426 12940 : dest->sign = NUMERIC_SIGN(num);
7427 12940 : dest->dscale = NUMERIC_DSCALE(num);
7428 :
7429 12940 : memcpy(dest->digits, NUMERIC_DIGITS(num), ndigits * sizeof(NumericDigit));
7430 12940 : }
7431 :
7432 :
7433 : /*
7434 : * init_var_from_num() -
7435 : *
7436 : * Initialize a variable from packed db format. The digits array is not
7437 : * copied, which saves some cycles when the resulting var is not modified.
7438 : * Also, there's no need to call free_var(), as long as you don't assign any
7439 : * other value to it (with set_var_* functions, or by using the var as the
7440 : * destination of a function like add_var())
7441 : *
7442 : * CAUTION: Do not modify the digits buffer of a var initialized with this
7443 : * function, e.g by calling round_var() or trunc_var(), as the changes will
7444 : * propagate to the original Numeric! It's OK to use it as the destination
7445 : * argument of one of the calculational functions, though.
7446 : */
7447 : static void
7448 5093018 : init_var_from_num(Numeric num, NumericVar *dest)
7449 : {
7450 5093018 : dest->ndigits = NUMERIC_NDIGITS(num);
7451 5093018 : dest->weight = NUMERIC_WEIGHT(num);
7452 5093018 : dest->sign = NUMERIC_SIGN(num);
7453 5093018 : dest->dscale = NUMERIC_DSCALE(num);
7454 5093018 : dest->digits = NUMERIC_DIGITS(num);
7455 5093018 : dest->buf = NULL; /* digits array is not palloc'd */
7456 5093018 : }
7457 :
7458 :
7459 : /*
7460 : * set_var_from_var() -
7461 : *
7462 : * Copy one variable into another
7463 : */
7464 : static void
7465 35172 : set_var_from_var(const NumericVar *value, NumericVar *dest)
7466 : {
7467 : NumericDigit *newbuf;
7468 :
7469 35172 : newbuf = digitbuf_alloc(value->ndigits + 1);
7470 35172 : newbuf[0] = 0; /* spare digit for rounding */
7471 35172 : if (value->ndigits > 0) /* else value->digits might be null */
7472 34226 : memcpy(newbuf + 1, value->digits,
7473 34226 : value->ndigits * sizeof(NumericDigit));
7474 :
7475 35172 : digitbuf_free(dest->buf);
7476 :
7477 35172 : memmove(dest, value, sizeof(NumericVar));
7478 35172 : dest->buf = newbuf;
7479 35172 : dest->digits = newbuf + 1;
7480 35172 : }
7481 :
7482 :
7483 : /*
7484 : * get_str_from_var() -
7485 : *
7486 : * Convert a var to text representation (guts of numeric_out).
7487 : * The var is displayed to the number of digits indicated by its dscale.
7488 : * Returns a palloc'd string.
7489 : */
7490 : static char *
7491 802030 : get_str_from_var(const NumericVar *var)
7492 : {
7493 : int dscale;
7494 : char *str;
7495 : char *cp;
7496 : char *endcp;
7497 : int i;
7498 : int d;
7499 : NumericDigit dig;
7500 :
7501 : #if DEC_DIGITS > 1
7502 : NumericDigit d1;
7503 : #endif
7504 :
7505 802030 : dscale = var->dscale;
7506 :
7507 : /*
7508 : * Allocate space for the result.
7509 : *
7510 : * i is set to the # of decimal digits before decimal point. dscale is the
7511 : * # of decimal digits we will print after decimal point. We may generate
7512 : * as many as DEC_DIGITS-1 excess digits at the end, and in addition we
7513 : * need room for sign, decimal point, null terminator.
7514 : */
7515 802030 : i = (var->weight + 1) * DEC_DIGITS;
7516 802030 : if (i <= 0)
7517 140642 : i = 1;
7518 :
7519 802030 : str = palloc(i + dscale + DEC_DIGITS + 2);
7520 802030 : cp = str;
7521 :
7522 : /*
7523 : * Output a dash for negative values
7524 : */
7525 802030 : if (var->sign == NUMERIC_NEG)
7526 5566 : *cp++ = '-';
7527 :
7528 : /*
7529 : * Output all digits before the decimal point
7530 : */
7531 802030 : if (var->weight < 0)
7532 : {
7533 140642 : d = var->weight + 1;
7534 140642 : *cp++ = '0';
7535 : }
7536 : else
7537 : {
7538 1428688 : for (d = 0; d <= var->weight; d++)
7539 : {
7540 767300 : dig = (d < var->ndigits) ? var->digits[d] : 0;
7541 : /* In the first digit, suppress extra leading decimal zeroes */
7542 : #if DEC_DIGITS == 4
7543 : {
7544 767300 : bool putit = (d > 0);
7545 :
7546 767300 : d1 = dig / 1000;
7547 767300 : dig -= d1 * 1000;
7548 767300 : putit |= (d1 > 0);
7549 767300 : if (putit)
7550 112842 : *cp++ = d1 + '0';
7551 767300 : d1 = dig / 100;
7552 767300 : dig -= d1 * 100;
7553 767300 : putit |= (d1 > 0);
7554 767300 : if (putit)
7555 517924 : *cp++ = d1 + '0';
7556 767300 : d1 = dig / 10;
7557 767300 : dig -= d1 * 10;
7558 767300 : putit |= (d1 > 0);
7559 767300 : if (putit)
7560 645130 : *cp++ = d1 + '0';
7561 767300 : *cp++ = dig + '0';
7562 : }
7563 : #elif DEC_DIGITS == 2
7564 : d1 = dig / 10;
7565 : dig -= d1 * 10;
7566 : if (d1 > 0 || d > 0)
7567 : *cp++ = d1 + '0';
7568 : *cp++ = dig + '0';
7569 : #elif DEC_DIGITS == 1
7570 : *cp++ = dig + '0';
7571 : #else
7572 : #error unsupported NBASE
7573 : #endif
7574 : }
7575 : }
7576 :
7577 : /*
7578 : * If requested, output a decimal point and all the digits that follow it.
7579 : * We initially put out a multiple of DEC_DIGITS digits, then truncate if
7580 : * needed.
7581 : */
7582 802030 : if (dscale > 0)
7583 : {
7584 646334 : *cp++ = '.';
7585 646334 : endcp = cp + dscale;
7586 2018486 : for (i = 0; i < dscale; d++, i += DEC_DIGITS)
7587 : {
7588 1372152 : dig = (d >= 0 && d < var->ndigits) ? var->digits[d] : 0;
7589 : #if DEC_DIGITS == 4
7590 1372152 : d1 = dig / 1000;
7591 1372152 : dig -= d1 * 1000;
7592 1372152 : *cp++ = d1 + '0';
7593 1372152 : d1 = dig / 100;
7594 1372152 : dig -= d1 * 100;
7595 1372152 : *cp++ = d1 + '0';
7596 1372152 : d1 = dig / 10;
7597 1372152 : dig -= d1 * 10;
7598 1372152 : *cp++ = d1 + '0';
7599 1372152 : *cp++ = dig + '0';
7600 : #elif DEC_DIGITS == 2
7601 : d1 = dig / 10;
7602 : dig -= d1 * 10;
7603 : *cp++ = d1 + '0';
7604 : *cp++ = dig + '0';
7605 : #elif DEC_DIGITS == 1
7606 : *cp++ = dig + '0';
7607 : #else
7608 : #error unsupported NBASE
7609 : #endif
7610 : }
7611 646334 : cp = endcp;
7612 : }
7613 :
7614 : /*
7615 : * terminate the string and return it
7616 : */
7617 802030 : *cp = '\0';
7618 802030 : return str;
7619 : }
7620 :
7621 : /*
7622 : * get_str_from_var_sci() -
7623 : *
7624 : * Convert a var to a normalised scientific notation text representation.
7625 : * This function does the heavy lifting for numeric_out_sci().
7626 : *
7627 : * This notation has the general form a * 10^b, where a is known as the
7628 : * "significand" and b is known as the "exponent".
7629 : *
7630 : * Because we can't do superscript in ASCII (and because we want to copy
7631 : * printf's behaviour) we display the exponent using E notation, with a
7632 : * minimum of two exponent digits.
7633 : *
7634 : * For example, the value 1234 could be output as 1.2e+03.
7635 : *
7636 : * We assume that the exponent can fit into an int32.
7637 : *
7638 : * rscale is the number of decimal digits desired after the decimal point in
7639 : * the output, negative values will be treated as meaning zero.
7640 : *
7641 : * Returns a palloc'd string.
7642 : */
7643 : static char *
7644 228 : get_str_from_var_sci(const NumericVar *var, int rscale)
7645 : {
7646 : int32 exponent;
7647 : NumericVar tmp_var;
7648 : size_t len;
7649 : char *str;
7650 : char *sig_out;
7651 :
7652 228 : if (rscale < 0)
7653 0 : rscale = 0;
7654 :
7655 : /*
7656 : * Determine the exponent of this number in normalised form.
7657 : *
7658 : * This is the exponent required to represent the number with only one
7659 : * significant digit before the decimal place.
7660 : */
7661 228 : if (var->ndigits > 0)
7662 : {
7663 210 : exponent = (var->weight + 1) * DEC_DIGITS;
7664 :
7665 : /*
7666 : * Compensate for leading decimal zeroes in the first numeric digit by
7667 : * decrementing the exponent.
7668 : */
7669 210 : exponent -= DEC_DIGITS - (int) log10(var->digits[0]);
7670 : }
7671 : else
7672 : {
7673 : /*
7674 : * If var has no digits, then it must be zero.
7675 : *
7676 : * Zero doesn't technically have a meaningful exponent in normalised
7677 : * notation, but we just display the exponent as zero for consistency
7678 : * of output.
7679 : */
7680 18 : exponent = 0;
7681 : }
7682 :
7683 : /*
7684 : * Divide var by 10^exponent to get the significand, rounding to rscale
7685 : * decimal digits in the process.
7686 : */
7687 228 : init_var(&tmp_var);
7688 :
7689 228 : power_ten_int(exponent, &tmp_var);
7690 228 : div_var(var, &tmp_var, &tmp_var, rscale, true, true);
7691 228 : sig_out = get_str_from_var(&tmp_var);
7692 :
7693 228 : free_var(&tmp_var);
7694 :
7695 : /*
7696 : * Allocate space for the result.
7697 : *
7698 : * In addition to the significand, we need room for the exponent
7699 : * decoration ("e"), the sign of the exponent, up to 10 digits for the
7700 : * exponent itself, and of course the null terminator.
7701 : */
7702 228 : len = strlen(sig_out) + 13;
7703 228 : str = palloc(len);
7704 228 : snprintf(str, len, "%se%+03d", sig_out, exponent);
7705 :
7706 228 : pfree(sig_out);
7707 :
7708 228 : return str;
7709 : }
7710 :
7711 :
7712 : /*
7713 : * numericvar_serialize - serialize NumericVar to binary format
7714 : *
7715 : * At variable level, no checks are performed on the weight or dscale, allowing
7716 : * us to pass around intermediate values with higher precision than supported
7717 : * by the numeric type. Note: this is incompatible with numeric_send/recv(),
7718 : * which use 16-bit integers for these fields.
7719 : */
7720 : static void
7721 96 : numericvar_serialize(StringInfo buf, const NumericVar *var)
7722 : {
7723 : int i;
7724 :
7725 96 : pq_sendint32(buf, var->ndigits);
7726 96 : pq_sendint32(buf, var->weight);
7727 96 : pq_sendint32(buf, var->sign);
7728 96 : pq_sendint32(buf, var->dscale);
7729 637786 : for (i = 0; i < var->ndigits; i++)
7730 637690 : pq_sendint16(buf, var->digits[i]);
7731 96 : }
7732 :
7733 : /*
7734 : * numericvar_deserialize - deserialize binary format to NumericVar
7735 : */
7736 : static void
7737 96 : numericvar_deserialize(StringInfo buf, NumericVar *var)
7738 : {
7739 : int len,
7740 : i;
7741 :
7742 96 : len = pq_getmsgint(buf, sizeof(int32));
7743 :
7744 96 : alloc_var(var, len); /* sets var->ndigits */
7745 :
7746 96 : var->weight = pq_getmsgint(buf, sizeof(int32));
7747 96 : var->sign = pq_getmsgint(buf, sizeof(int32));
7748 96 : var->dscale = pq_getmsgint(buf, sizeof(int32));
7749 637786 : for (i = 0; i < len; i++)
7750 637690 : var->digits[i] = pq_getmsgint(buf, sizeof(int16));
7751 96 : }
7752 :
7753 :
7754 : /*
7755 : * duplicate_numeric() - copy a packed-format Numeric
7756 : *
7757 : * This will handle NaN and Infinity cases.
7758 : */
7759 : static Numeric
7760 28496 : duplicate_numeric(Numeric num)
7761 : {
7762 : Numeric res;
7763 :
7764 28496 : res = (Numeric) palloc(VARSIZE(num));
7765 28496 : memcpy(res, num, VARSIZE(num));
7766 28496 : return res;
7767 : }
7768 :
7769 : /*
7770 : * make_result_opt_error() -
7771 : *
7772 : * Create the packed db numeric format in palloc()'d memory from
7773 : * a variable. This will handle NaN and Infinity cases.
7774 : *
7775 : * If "have_error" isn't NULL, on overflow *have_error is set to true and
7776 : * NULL is returned. This is helpful when caller needs to handle errors.
7777 : */
7778 : static Numeric
7779 3272626 : make_result_opt_error(const NumericVar *var, bool *have_error)
7780 : {
7781 : Numeric result;
7782 3272626 : NumericDigit *digits = var->digits;
7783 3272626 : int weight = var->weight;
7784 3272626 : int sign = var->sign;
7785 : int n;
7786 : Size len;
7787 :
7788 3272626 : if (have_error)
7789 106676 : *have_error = false;
7790 :
7791 3272626 : if ((sign & NUMERIC_SIGN_MASK) == NUMERIC_SPECIAL)
7792 : {
7793 : /*
7794 : * Verify valid special value. This could be just an Assert, perhaps,
7795 : * but it seems worthwhile to expend a few cycles to ensure that we
7796 : * never write any nonzero reserved bits to disk.
7797 : */
7798 5478 : if (!(sign == NUMERIC_NAN ||
7799 : sign == NUMERIC_PINF ||
7800 : sign == NUMERIC_NINF))
7801 0 : elog(ERROR, "invalid numeric sign value 0x%x", sign);
7802 :
7803 5478 : result = (Numeric) palloc(NUMERIC_HDRSZ_SHORT);
7804 :
7805 5478 : SET_VARSIZE(result, NUMERIC_HDRSZ_SHORT);
7806 5478 : result->choice.n_header = sign;
7807 : /* the header word is all we need */
7808 :
7809 : dump_numeric("make_result()", result);
7810 5478 : return result;
7811 : }
7812 :
7813 3267148 : n = var->ndigits;
7814 :
7815 : /* truncate leading zeroes */
7816 3267184 : while (n > 0 && *digits == 0)
7817 : {
7818 36 : digits++;
7819 36 : weight--;
7820 36 : n--;
7821 : }
7822 : /* truncate trailing zeroes */
7823 3352484 : while (n > 0 && digits[n - 1] == 0)
7824 85336 : n--;
7825 :
7826 : /* If zero result, force to weight=0 and positive sign */
7827 3267148 : if (n == 0)
7828 : {
7829 94568 : weight = 0;
7830 94568 : sign = NUMERIC_POS;
7831 : }
7832 :
7833 : /* Build the result */
7834 3267148 : if (NUMERIC_CAN_BE_SHORT(var->dscale, weight))
7835 : {
7836 3261854 : len = NUMERIC_HDRSZ_SHORT + n * sizeof(NumericDigit);
7837 3261854 : result = (Numeric) palloc(len);
7838 3261854 : SET_VARSIZE(result, len);
7839 3261854 : result->choice.n_short.n_header =
7840 : (sign == NUMERIC_NEG ? (NUMERIC_SHORT | NUMERIC_SHORT_SIGN_MASK)
7841 : : NUMERIC_SHORT)
7842 3261854 : | (var->dscale << NUMERIC_SHORT_DSCALE_SHIFT)
7843 3261854 : | (weight < 0 ? NUMERIC_SHORT_WEIGHT_SIGN_MASK : 0)
7844 3261854 : | (weight & NUMERIC_SHORT_WEIGHT_MASK);
7845 : }
7846 : else
7847 : {
7848 5294 : len = NUMERIC_HDRSZ + n * sizeof(NumericDigit);
7849 5294 : result = (Numeric) palloc(len);
7850 5294 : SET_VARSIZE(result, len);
7851 5294 : result->choice.n_long.n_sign_dscale =
7852 5294 : sign | (var->dscale & NUMERIC_DSCALE_MASK);
7853 5294 : result->choice.n_long.n_weight = weight;
7854 : }
7855 :
7856 : Assert(NUMERIC_NDIGITS(result) == n);
7857 3267148 : if (n > 0)
7858 3172580 : memcpy(NUMERIC_DIGITS(result), digits, n * sizeof(NumericDigit));
7859 :
7860 : /* Check for overflow of int16 fields */
7861 3267148 : if (NUMERIC_WEIGHT(result) != weight ||
7862 3267118 : NUMERIC_DSCALE(result) != var->dscale)
7863 : {
7864 30 : if (have_error)
7865 : {
7866 18 : *have_error = true;
7867 18 : return NULL;
7868 : }
7869 : else
7870 : {
7871 12 : ereport(ERROR,
7872 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
7873 : errmsg("value overflows numeric format")));
7874 : }
7875 : }
7876 :
7877 : dump_numeric("make_result()", result);
7878 3267118 : return result;
7879 : }
7880 :
7881 :
7882 : /*
7883 : * make_result() -
7884 : *
7885 : * An interface to make_result_opt_error() without "have_error" argument.
7886 : */
7887 : static Numeric
7888 2129522 : make_result(const NumericVar *var)
7889 : {
7890 2129522 : return make_result_opt_error(var, NULL);
7891 : }
7892 :
7893 :
7894 : /*
7895 : * apply_typmod() -
7896 : *
7897 : * Do bounds checking and rounding according to the specified typmod.
7898 : * Note that this is only applied to normal finite values.
7899 : *
7900 : * Returns true on success, false on failure (if escontext points to an
7901 : * ErrorSaveContext; otherwise errors are thrown).
7902 : */
7903 : static bool
7904 110840 : apply_typmod(NumericVar *var, int32 typmod, Node *escontext)
7905 : {
7906 : int precision;
7907 : int scale;
7908 : int maxdigits;
7909 : int ddigits;
7910 : int i;
7911 :
7912 : /* Do nothing if we have an invalid typmod */
7913 110840 : if (!is_valid_numeric_typmod(typmod))
7914 106142 : return true;
7915 :
7916 4698 : precision = numeric_typmod_precision(typmod);
7917 4698 : scale = numeric_typmod_scale(typmod);
7918 4698 : maxdigits = precision - scale;
7919 :
7920 : /* Round to target scale (and set var->dscale) */
7921 4698 : round_var(var, scale);
7922 :
7923 : /* but don't allow var->dscale to be negative */
7924 4698 : if (var->dscale < 0)
7925 126 : var->dscale = 0;
7926 :
7927 : /*
7928 : * Check for overflow - note we can't do this before rounding, because
7929 : * rounding could raise the weight. Also note that the var's weight could
7930 : * be inflated by leading zeroes, which will be stripped before storage
7931 : * but perhaps might not have been yet. In any case, we must recognize a
7932 : * true zero, whose weight doesn't mean anything.
7933 : */
7934 4698 : ddigits = (var->weight + 1) * DEC_DIGITS;
7935 4698 : if (ddigits > maxdigits)
7936 : {
7937 : /* Determine true weight; and check for all-zero result */
7938 410 : for (i = 0; i < var->ndigits; i++)
7939 : {
7940 394 : NumericDigit dig = var->digits[i];
7941 :
7942 394 : if (dig)
7943 : {
7944 : /* Adjust for any high-order decimal zero digits */
7945 : #if DEC_DIGITS == 4
7946 394 : if (dig < 10)
7947 252 : ddigits -= 3;
7948 142 : else if (dig < 100)
7949 72 : ddigits -= 2;
7950 70 : else if (dig < 1000)
7951 52 : ddigits -= 1;
7952 : #elif DEC_DIGITS == 2
7953 : if (dig < 10)
7954 : ddigits -= 1;
7955 : #elif DEC_DIGITS == 1
7956 : /* no adjustment */
7957 : #else
7958 : #error unsupported NBASE
7959 : #endif
7960 394 : if (ddigits > maxdigits)
7961 84 : ereturn(escontext, false,
7962 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
7963 : errmsg("numeric field overflow"),
7964 : errdetail("A field with precision %d, scale %d must round to an absolute value less than %s%d.",
7965 : precision, scale,
7966 : /* Display 10^0 as 1 */
7967 : maxdigits ? "10^" : "",
7968 : maxdigits ? maxdigits : 1
7969 : )));
7970 310 : break;
7971 : }
7972 0 : ddigits -= DEC_DIGITS;
7973 : }
7974 : }
7975 :
7976 4614 : return true;
7977 : }
7978 :
7979 : /*
7980 : * apply_typmod_special() -
7981 : *
7982 : * Do bounds checking according to the specified typmod, for an Inf or NaN.
7983 : * For convenience of most callers, the value is presented in packed form.
7984 : *
7985 : * Returns true on success, false on failure (if escontext points to an
7986 : * ErrorSaveContext; otherwise errors are thrown).
7987 : */
7988 : static bool
7989 1864 : apply_typmod_special(Numeric num, int32 typmod, Node *escontext)
7990 : {
7991 : int precision;
7992 : int scale;
7993 :
7994 : Assert(NUMERIC_IS_SPECIAL(num)); /* caller error if not */
7995 :
7996 : /*
7997 : * NaN is allowed regardless of the typmod; that's rather dubious perhaps,
7998 : * but it's a longstanding behavior. Inf is rejected if we have any
7999 : * typmod restriction, since an infinity shouldn't be claimed to fit in
8000 : * any finite number of digits.
8001 : */
8002 1864 : if (NUMERIC_IS_NAN(num))
8003 778 : return true;
8004 :
8005 : /* Do nothing if we have a default typmod (-1) */
8006 1086 : if (!is_valid_numeric_typmod(typmod))
8007 1068 : return true;
8008 :
8009 18 : precision = numeric_typmod_precision(typmod);
8010 18 : scale = numeric_typmod_scale(typmod);
8011 :
8012 18 : ereturn(escontext, false,
8013 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
8014 : errmsg("numeric field overflow"),
8015 : errdetail("A field with precision %d, scale %d cannot hold an infinite value.",
8016 : precision, scale)));
8017 : }
8018 :
8019 :
8020 : /*
8021 : * Convert numeric to int8, rounding if needed.
8022 : *
8023 : * If overflow, return false (no error is raised). Return true if okay.
8024 : */
8025 : static bool
8026 10296 : numericvar_to_int64(const NumericVar *var, int64 *result)
8027 : {
8028 : NumericDigit *digits;
8029 : int ndigits;
8030 : int weight;
8031 : int i;
8032 : int64 val;
8033 : bool neg;
8034 : NumericVar rounded;
8035 :
8036 : /* Round to nearest integer */
8037 10296 : init_var(&rounded);
8038 10296 : set_var_from_var(var, &rounded);
8039 10296 : round_var(&rounded, 0);
8040 :
8041 : /* Check for zero input */
8042 10296 : strip_var(&rounded);
8043 10296 : ndigits = rounded.ndigits;
8044 10296 : if (ndigits == 0)
8045 : {
8046 478 : *result = 0;
8047 478 : free_var(&rounded);
8048 478 : return true;
8049 : }
8050 :
8051 : /*
8052 : * For input like 10000000000, we must treat stripped digits as real. So
8053 : * the loop assumes there are weight+1 digits before the decimal point.
8054 : */
8055 9818 : weight = rounded.weight;
8056 : Assert(weight >= 0 && ndigits <= weight + 1);
8057 :
8058 : /*
8059 : * Construct the result. To avoid issues with converting a value
8060 : * corresponding to INT64_MIN (which can't be represented as a positive 64
8061 : * bit two's complement integer), accumulate value as a negative number.
8062 : */
8063 9818 : digits = rounded.digits;
8064 9818 : neg = (rounded.sign == NUMERIC_NEG);
8065 9818 : val = -digits[0];
8066 14030 : for (i = 1; i <= weight; i++)
8067 : {
8068 4260 : if (unlikely(pg_mul_s64_overflow(val, NBASE, &val)))
8069 : {
8070 30 : free_var(&rounded);
8071 30 : return false;
8072 : }
8073 :
8074 4230 : if (i < ndigits)
8075 : {
8076 3948 : if (unlikely(pg_sub_s64_overflow(val, digits[i], &val)))
8077 : {
8078 18 : free_var(&rounded);
8079 18 : return false;
8080 : }
8081 : }
8082 : }
8083 :
8084 9770 : free_var(&rounded);
8085 :
8086 9770 : if (!neg)
8087 : {
8088 8978 : if (unlikely(val == PG_INT64_MIN))
8089 24 : return false;
8090 8954 : val = -val;
8091 : }
8092 9746 : *result = val;
8093 :
8094 9746 : return true;
8095 : }
8096 :
8097 : /*
8098 : * Convert int8 value to numeric.
8099 : */
8100 : static void
8101 1880278 : int64_to_numericvar(int64 val, NumericVar *var)
8102 : {
8103 : uint64 uval,
8104 : newuval;
8105 : NumericDigit *ptr;
8106 : int ndigits;
8107 :
8108 : /* int64 can require at most 19 decimal digits; add one for safety */
8109 1880278 : alloc_var(var, 20 / DEC_DIGITS);
8110 1880278 : if (val < 0)
8111 : {
8112 1814 : var->sign = NUMERIC_NEG;
8113 1814 : uval = pg_abs_s64(val);
8114 : }
8115 : else
8116 : {
8117 1878464 : var->sign = NUMERIC_POS;
8118 1878464 : uval = val;
8119 : }
8120 1880278 : var->dscale = 0;
8121 1880278 : if (val == 0)
8122 : {
8123 35300 : var->ndigits = 0;
8124 35300 : var->weight = 0;
8125 35300 : return;
8126 : }
8127 1844978 : ptr = var->digits + var->ndigits;
8128 1844978 : ndigits = 0;
8129 : do
8130 : {
8131 2168734 : ptr--;
8132 2168734 : ndigits++;
8133 2168734 : newuval = uval / NBASE;
8134 2168734 : *ptr = uval - newuval * NBASE;
8135 2168734 : uval = newuval;
8136 2168734 : } while (uval);
8137 1844978 : var->digits = ptr;
8138 1844978 : var->ndigits = ndigits;
8139 1844978 : var->weight = ndigits - 1;
8140 : }
8141 :
8142 : /*
8143 : * Convert numeric to uint64, rounding if needed.
8144 : *
8145 : * If overflow, return false (no error is raised). Return true if okay.
8146 : */
8147 : static bool
8148 114 : numericvar_to_uint64(const NumericVar *var, uint64 *result)
8149 : {
8150 : NumericDigit *digits;
8151 : int ndigits;
8152 : int weight;
8153 : int i;
8154 : uint64 val;
8155 : NumericVar rounded;
8156 :
8157 : /* Round to nearest integer */
8158 114 : init_var(&rounded);
8159 114 : set_var_from_var(var, &rounded);
8160 114 : round_var(&rounded, 0);
8161 :
8162 : /* Check for zero input */
8163 114 : strip_var(&rounded);
8164 114 : ndigits = rounded.ndigits;
8165 114 : if (ndigits == 0)
8166 : {
8167 18 : *result = 0;
8168 18 : free_var(&rounded);
8169 18 : return true;
8170 : }
8171 :
8172 : /* Check for negative input */
8173 96 : if (rounded.sign == NUMERIC_NEG)
8174 : {
8175 12 : free_var(&rounded);
8176 12 : return false;
8177 : }
8178 :
8179 : /*
8180 : * For input like 10000000000, we must treat stripped digits as real. So
8181 : * the loop assumes there are weight+1 digits before the decimal point.
8182 : */
8183 84 : weight = rounded.weight;
8184 : Assert(weight >= 0 && ndigits <= weight + 1);
8185 :
8186 : /* Construct the result */
8187 84 : digits = rounded.digits;
8188 84 : val = digits[0];
8189 246 : for (i = 1; i <= weight; i++)
8190 : {
8191 174 : if (unlikely(pg_mul_u64_overflow(val, NBASE, &val)))
8192 : {
8193 0 : free_var(&rounded);
8194 0 : return false;
8195 : }
8196 :
8197 174 : if (i < ndigits)
8198 : {
8199 174 : if (unlikely(pg_add_u64_overflow(val, digits[i], &val)))
8200 : {
8201 12 : free_var(&rounded);
8202 12 : return false;
8203 : }
8204 : }
8205 : }
8206 :
8207 72 : free_var(&rounded);
8208 :
8209 72 : *result = val;
8210 :
8211 72 : return true;
8212 : }
8213 :
8214 : #ifdef HAVE_INT128
8215 : /*
8216 : * Convert numeric to int128, rounding if needed.
8217 : *
8218 : * If overflow, return false (no error is raised). Return true if okay.
8219 : */
8220 : static bool
8221 36 : numericvar_to_int128(const NumericVar *var, int128 *result)
8222 : {
8223 : NumericDigit *digits;
8224 : int ndigits;
8225 : int weight;
8226 : int i;
8227 : int128 val,
8228 : oldval;
8229 : bool neg;
8230 : NumericVar rounded;
8231 :
8232 : /* Round to nearest integer */
8233 36 : init_var(&rounded);
8234 36 : set_var_from_var(var, &rounded);
8235 36 : round_var(&rounded, 0);
8236 :
8237 : /* Check for zero input */
8238 36 : strip_var(&rounded);
8239 36 : ndigits = rounded.ndigits;
8240 36 : if (ndigits == 0)
8241 : {
8242 0 : *result = 0;
8243 0 : free_var(&rounded);
8244 0 : return true;
8245 : }
8246 :
8247 : /*
8248 : * For input like 10000000000, we must treat stripped digits as real. So
8249 : * the loop assumes there are weight+1 digits before the decimal point.
8250 : */
8251 36 : weight = rounded.weight;
8252 : Assert(weight >= 0 && ndigits <= weight + 1);
8253 :
8254 : /* Construct the result */
8255 36 : digits = rounded.digits;
8256 36 : neg = (rounded.sign == NUMERIC_NEG);
8257 36 : val = digits[0];
8258 100 : for (i = 1; i <= weight; i++)
8259 : {
8260 64 : oldval = val;
8261 64 : val *= NBASE;
8262 64 : if (i < ndigits)
8263 52 : val += digits[i];
8264 :
8265 : /*
8266 : * The overflow check is a bit tricky because we want to accept
8267 : * INT128_MIN, which will overflow the positive accumulator. We can
8268 : * detect this case easily though because INT128_MIN is the only
8269 : * nonzero value for which -val == val (on a two's complement machine,
8270 : * anyway).
8271 : */
8272 64 : if ((val / NBASE) != oldval) /* possible overflow? */
8273 : {
8274 0 : if (!neg || (-val) != val || val == 0 || oldval < 0)
8275 : {
8276 0 : free_var(&rounded);
8277 0 : return false;
8278 : }
8279 : }
8280 : }
8281 :
8282 36 : free_var(&rounded);
8283 :
8284 36 : *result = neg ? -val : val;
8285 36 : return true;
8286 : }
8287 :
8288 : /*
8289 : * Convert 128 bit integer to numeric.
8290 : */
8291 : static void
8292 8558 : int128_to_numericvar(int128 val, NumericVar *var)
8293 : {
8294 : uint128 uval,
8295 : newuval;
8296 : NumericDigit *ptr;
8297 : int ndigits;
8298 :
8299 : /* int128 can require at most 39 decimal digits; add one for safety */
8300 8558 : alloc_var(var, 40 / DEC_DIGITS);
8301 8558 : if (val < 0)
8302 : {
8303 0 : var->sign = NUMERIC_NEG;
8304 0 : uval = -val;
8305 : }
8306 : else
8307 : {
8308 8558 : var->sign = NUMERIC_POS;
8309 8558 : uval = val;
8310 : }
8311 8558 : var->dscale = 0;
8312 8558 : if (val == 0)
8313 : {
8314 124 : var->ndigits = 0;
8315 124 : var->weight = 0;
8316 124 : return;
8317 : }
8318 8434 : ptr = var->digits + var->ndigits;
8319 8434 : ndigits = 0;
8320 : do
8321 : {
8322 44914 : ptr--;
8323 44914 : ndigits++;
8324 44914 : newuval = uval / NBASE;
8325 44914 : *ptr = uval - newuval * NBASE;
8326 44914 : uval = newuval;
8327 44914 : } while (uval);
8328 8434 : var->digits = ptr;
8329 8434 : var->ndigits = ndigits;
8330 8434 : var->weight = ndigits - 1;
8331 : }
8332 : #endif
8333 :
8334 : /*
8335 : * Convert a NumericVar to float8; if out of range, return +/- HUGE_VAL
8336 : */
8337 : static double
8338 3466 : numericvar_to_double_no_overflow(const NumericVar *var)
8339 : {
8340 : char *tmp;
8341 : double val;
8342 : char *endptr;
8343 :
8344 3466 : tmp = get_str_from_var(var);
8345 :
8346 : /* unlike float8in, we ignore ERANGE from strtod */
8347 3466 : val = strtod(tmp, &endptr);
8348 3466 : if (*endptr != '\0')
8349 : {
8350 : /* shouldn't happen ... */
8351 0 : ereport(ERROR,
8352 : (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
8353 : errmsg("invalid input syntax for type %s: \"%s\"",
8354 : "double precision", tmp)));
8355 : }
8356 :
8357 3466 : pfree(tmp);
8358 :
8359 3466 : return val;
8360 : }
8361 :
8362 :
8363 : /*
8364 : * cmp_var() -
8365 : *
8366 : * Compare two values on variable level. We assume zeroes have been
8367 : * truncated to no digits.
8368 : */
8369 : static int
8370 49706 : cmp_var(const NumericVar *var1, const NumericVar *var2)
8371 : {
8372 99412 : return cmp_var_common(var1->digits, var1->ndigits,
8373 : var1->weight, var1->sign,
8374 49706 : var2->digits, var2->ndigits,
8375 : var2->weight, var2->sign);
8376 : }
8377 :
8378 : /*
8379 : * cmp_var_common() -
8380 : *
8381 : * Main routine of cmp_var(). This function can be used by both
8382 : * NumericVar and Numeric.
8383 : */
8384 : static int
8385 6136478 : cmp_var_common(const NumericDigit *var1digits, int var1ndigits,
8386 : int var1weight, int var1sign,
8387 : const NumericDigit *var2digits, int var2ndigits,
8388 : int var2weight, int var2sign)
8389 : {
8390 6136478 : if (var1ndigits == 0)
8391 : {
8392 183784 : if (var2ndigits == 0)
8393 155892 : return 0;
8394 27892 : if (var2sign == NUMERIC_NEG)
8395 4156 : return 1;
8396 23736 : return -1;
8397 : }
8398 5952694 : if (var2ndigits == 0)
8399 : {
8400 31696 : if (var1sign == NUMERIC_POS)
8401 25010 : return 1;
8402 6686 : return -1;
8403 : }
8404 :
8405 5920998 : if (var1sign == NUMERIC_POS)
8406 : {
8407 5833926 : if (var2sign == NUMERIC_NEG)
8408 26458 : return 1;
8409 5807468 : return cmp_abs_common(var1digits, var1ndigits, var1weight,
8410 : var2digits, var2ndigits, var2weight);
8411 : }
8412 :
8413 87072 : if (var2sign == NUMERIC_POS)
8414 28766 : return -1;
8415 :
8416 58306 : return cmp_abs_common(var2digits, var2ndigits, var2weight,
8417 : var1digits, var1ndigits, var1weight);
8418 : }
8419 :
8420 :
8421 : /*
8422 : * add_var() -
8423 : *
8424 : * Full version of add functionality on variable level (handling signs).
8425 : * result might point to one of the operands too without danger.
8426 : */
8427 : static void
8428 497464 : add_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
8429 : {
8430 : /*
8431 : * Decide on the signs of the two variables what to do
8432 : */
8433 497464 : if (var1->sign == NUMERIC_POS)
8434 : {
8435 495898 : if (var2->sign == NUMERIC_POS)
8436 : {
8437 : /*
8438 : * Both are positive result = +(ABS(var1) + ABS(var2))
8439 : */
8440 295744 : add_abs(var1, var2, result);
8441 295744 : result->sign = NUMERIC_POS;
8442 : }
8443 : else
8444 : {
8445 : /*
8446 : * var1 is positive, var2 is negative Must compare absolute values
8447 : */
8448 200154 : switch (cmp_abs(var1, var2))
8449 : {
8450 188 : case 0:
8451 : /* ----------
8452 : * ABS(var1) == ABS(var2)
8453 : * result = ZERO
8454 : * ----------
8455 : */
8456 188 : zero_var(result);
8457 188 : result->dscale = Max(var1->dscale, var2->dscale);
8458 188 : break;
8459 :
8460 185904 : case 1:
8461 : /* ----------
8462 : * ABS(var1) > ABS(var2)
8463 : * result = +(ABS(var1) - ABS(var2))
8464 : * ----------
8465 : */
8466 185904 : sub_abs(var1, var2, result);
8467 185904 : result->sign = NUMERIC_POS;
8468 185904 : break;
8469 :
8470 14062 : case -1:
8471 : /* ----------
8472 : * ABS(var1) < ABS(var2)
8473 : * result = -(ABS(var2) - ABS(var1))
8474 : * ----------
8475 : */
8476 14062 : sub_abs(var2, var1, result);
8477 14062 : result->sign = NUMERIC_NEG;
8478 14062 : break;
8479 : }
8480 495898 : }
8481 : }
8482 : else
8483 : {
8484 1566 : if (var2->sign == NUMERIC_POS)
8485 : {
8486 : /* ----------
8487 : * var1 is negative, var2 is positive
8488 : * Must compare absolute values
8489 : * ----------
8490 : */
8491 468 : switch (cmp_abs(var1, var2))
8492 : {
8493 30 : case 0:
8494 : /* ----------
8495 : * ABS(var1) == ABS(var2)
8496 : * result = ZERO
8497 : * ----------
8498 : */
8499 30 : zero_var(result);
8500 30 : result->dscale = Max(var1->dscale, var2->dscale);
8501 30 : break;
8502 :
8503 294 : case 1:
8504 : /* ----------
8505 : * ABS(var1) > ABS(var2)
8506 : * result = -(ABS(var1) - ABS(var2))
8507 : * ----------
8508 : */
8509 294 : sub_abs(var1, var2, result);
8510 294 : result->sign = NUMERIC_NEG;
8511 294 : break;
8512 :
8513 144 : case -1:
8514 : /* ----------
8515 : * ABS(var1) < ABS(var2)
8516 : * result = +(ABS(var2) - ABS(var1))
8517 : * ----------
8518 : */
8519 144 : sub_abs(var2, var1, result);
8520 144 : result->sign = NUMERIC_POS;
8521 144 : break;
8522 : }
8523 468 : }
8524 : else
8525 : {
8526 : /* ----------
8527 : * Both are negative
8528 : * result = -(ABS(var1) + ABS(var2))
8529 : * ----------
8530 : */
8531 1098 : add_abs(var1, var2, result);
8532 1098 : result->sign = NUMERIC_NEG;
8533 : }
8534 : }
8535 497464 : }
8536 :
8537 :
8538 : /*
8539 : * sub_var() -
8540 : *
8541 : * Full version of sub functionality on variable level (handling signs).
8542 : * result might point to one of the operands too without danger.
8543 : */
8544 : static void
8545 186686 : sub_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
8546 : {
8547 : /*
8548 : * Decide on the signs of the two variables what to do
8549 : */
8550 186686 : if (var1->sign == NUMERIC_POS)
8551 : {
8552 183914 : if (var2->sign == NUMERIC_NEG)
8553 : {
8554 : /* ----------
8555 : * var1 is positive, var2 is negative
8556 : * result = +(ABS(var1) + ABS(var2))
8557 : * ----------
8558 : */
8559 33254 : add_abs(var1, var2, result);
8560 33254 : result->sign = NUMERIC_POS;
8561 : }
8562 : else
8563 : {
8564 : /* ----------
8565 : * Both are positive
8566 : * Must compare absolute values
8567 : * ----------
8568 : */
8569 150660 : switch (cmp_abs(var1, var2))
8570 : {
8571 29120 : case 0:
8572 : /* ----------
8573 : * ABS(var1) == ABS(var2)
8574 : * result = ZERO
8575 : * ----------
8576 : */
8577 29120 : zero_var(result);
8578 29120 : result->dscale = Max(var1->dscale, var2->dscale);
8579 29120 : break;
8580 :
8581 112986 : case 1:
8582 : /* ----------
8583 : * ABS(var1) > ABS(var2)
8584 : * result = +(ABS(var1) - ABS(var2))
8585 : * ----------
8586 : */
8587 112986 : sub_abs(var1, var2, result);
8588 112986 : result->sign = NUMERIC_POS;
8589 112986 : break;
8590 :
8591 8554 : case -1:
8592 : /* ----------
8593 : * ABS(var1) < ABS(var2)
8594 : * result = -(ABS(var2) - ABS(var1))
8595 : * ----------
8596 : */
8597 8554 : sub_abs(var2, var1, result);
8598 8554 : result->sign = NUMERIC_NEG;
8599 8554 : break;
8600 : }
8601 183914 : }
8602 : }
8603 : else
8604 : {
8605 2772 : if (var2->sign == NUMERIC_NEG)
8606 : {
8607 : /* ----------
8608 : * Both are negative
8609 : * Must compare absolute values
8610 : * ----------
8611 : */
8612 2322 : switch (cmp_abs(var1, var2))
8613 : {
8614 166 : case 0:
8615 : /* ----------
8616 : * ABS(var1) == ABS(var2)
8617 : * result = ZERO
8618 : * ----------
8619 : */
8620 166 : zero_var(result);
8621 166 : result->dscale = Max(var1->dscale, var2->dscale);
8622 166 : break;
8623 :
8624 240 : case 1:
8625 : /* ----------
8626 : * ABS(var1) > ABS(var2)
8627 : * result = -(ABS(var1) - ABS(var2))
8628 : * ----------
8629 : */
8630 240 : sub_abs(var1, var2, result);
8631 240 : result->sign = NUMERIC_NEG;
8632 240 : break;
8633 :
8634 1916 : case -1:
8635 : /* ----------
8636 : * ABS(var1) < ABS(var2)
8637 : * result = +(ABS(var2) - ABS(var1))
8638 : * ----------
8639 : */
8640 1916 : sub_abs(var2, var1, result);
8641 1916 : result->sign = NUMERIC_POS;
8642 1916 : break;
8643 : }
8644 2322 : }
8645 : else
8646 : {
8647 : /* ----------
8648 : * var1 is negative, var2 is positive
8649 : * result = -(ABS(var1) + ABS(var2))
8650 : * ----------
8651 : */
8652 450 : add_abs(var1, var2, result);
8653 450 : result->sign = NUMERIC_NEG;
8654 : }
8655 : }
8656 186686 : }
8657 :
8658 :
8659 : /*
8660 : * mul_var() -
8661 : *
8662 : * Multiplication on variable level. Product of var1 * var2 is stored
8663 : * in result. Result is rounded to no more than rscale fractional digits.
8664 : */
8665 : static void
8666 829808 : mul_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result,
8667 : int rscale)
8668 : {
8669 : int res_ndigits;
8670 : int res_ndigitpairs;
8671 : int res_sign;
8672 : int res_weight;
8673 : int pair_offset;
8674 : int maxdigits;
8675 : int maxdigitpairs;
8676 : uint64 *dig,
8677 : *dig_i1_off;
8678 : uint64 maxdig;
8679 : uint64 carry;
8680 : uint64 newdig;
8681 : int var1ndigits;
8682 : int var2ndigits;
8683 : int var1ndigitpairs;
8684 : int var2ndigitpairs;
8685 : NumericDigit *var1digits;
8686 : NumericDigit *var2digits;
8687 : uint32 var1digitpair;
8688 : uint32 *var2digitpairs;
8689 : NumericDigit *res_digits;
8690 : int i,
8691 : i1,
8692 : i2,
8693 : i2limit;
8694 :
8695 : /*
8696 : * Arrange for var1 to be the shorter of the two numbers. This improves
8697 : * performance because the inner multiplication loop is much simpler than
8698 : * the outer loop, so it's better to have a smaller number of iterations
8699 : * of the outer loop. This also reduces the number of times that the
8700 : * accumulator array needs to be normalized.
8701 : */
8702 829808 : if (var1->ndigits > var2->ndigits)
8703 : {
8704 14052 : const NumericVar *tmp = var1;
8705 :
8706 14052 : var1 = var2;
8707 14052 : var2 = tmp;
8708 : }
8709 :
8710 : /* copy these values into local vars for speed in inner loop */
8711 829808 : var1ndigits = var1->ndigits;
8712 829808 : var2ndigits = var2->ndigits;
8713 829808 : var1digits = var1->digits;
8714 829808 : var2digits = var2->digits;
8715 :
8716 829808 : if (var1ndigits == 0)
8717 : {
8718 : /* one or both inputs is zero; so is result */
8719 1712 : zero_var(result);
8720 1712 : result->dscale = rscale;
8721 1712 : return;
8722 : }
8723 :
8724 : /*
8725 : * If var1 has 1-6 digits and the exact result was requested, delegate to
8726 : * mul_var_short() which uses a faster direct multiplication algorithm.
8727 : */
8728 828096 : if (var1ndigits <= 6 && rscale == var1->dscale + var2->dscale)
8729 : {
8730 799620 : mul_var_short(var1, var2, result);
8731 799620 : return;
8732 : }
8733 :
8734 : /* Determine result sign */
8735 28476 : if (var1->sign == var2->sign)
8736 26994 : res_sign = NUMERIC_POS;
8737 : else
8738 1482 : res_sign = NUMERIC_NEG;
8739 :
8740 : /*
8741 : * Determine the number of result digits to compute and the (maximum
8742 : * possible) result weight. If the exact result would have more than
8743 : * rscale fractional digits, truncate the computation with
8744 : * MUL_GUARD_DIGITS guard digits, i.e., ignore input digits that would
8745 : * only contribute to the right of that. (This will give the exact
8746 : * rounded-to-rscale answer unless carries out of the ignored positions
8747 : * would have propagated through more than MUL_GUARD_DIGITS digits.)
8748 : *
8749 : * Note: an exact computation could not produce more than var1ndigits +
8750 : * var2ndigits digits, but we allocate at least one extra output digit in
8751 : * case rscale-driven rounding produces a carry out of the highest exact
8752 : * digit.
8753 : *
8754 : * The computation itself is done using base-NBASE^2 arithmetic, so we
8755 : * actually process the input digits in pairs, producing a base-NBASE^2
8756 : * intermediate result. This significantly improves performance, since
8757 : * schoolbook multiplication is O(N^2) in the number of input digits, and
8758 : * working in base NBASE^2 effectively halves "N".
8759 : *
8760 : * Note: in a truncated computation, we must compute at least one extra
8761 : * output digit to ensure that all the guard digits are fully computed.
8762 : */
8763 : /* digit pairs in each input */
8764 28476 : var1ndigitpairs = (var1ndigits + 1) / 2;
8765 28476 : var2ndigitpairs = (var2ndigits + 1) / 2;
8766 :
8767 : /* digits in exact result */
8768 28476 : res_ndigits = var1ndigits + var2ndigits;
8769 :
8770 : /* digit pairs in exact result with at least one extra output digit */
8771 28476 : res_ndigitpairs = res_ndigits / 2 + 1;
8772 :
8773 : /* pair offset to align result to end of dig[] */
8774 28476 : pair_offset = res_ndigitpairs - var1ndigitpairs - var2ndigitpairs + 1;
8775 :
8776 : /* maximum possible result weight (odd-length inputs shifted up below) */
8777 28476 : res_weight = var1->weight + var2->weight + 1 + 2 * res_ndigitpairs -
8778 28476 : res_ndigits - (var1ndigits & 1) - (var2ndigits & 1);
8779 :
8780 : /* rscale-based truncation with at least one extra output digit */
8781 28476 : maxdigits = res_weight + 1 + (rscale + DEC_DIGITS - 1) / DEC_DIGITS +
8782 : MUL_GUARD_DIGITS;
8783 28476 : maxdigitpairs = maxdigits / 2 + 1;
8784 :
8785 28476 : res_ndigitpairs = Min(res_ndigitpairs, maxdigitpairs);
8786 28476 : res_ndigits = 2 * res_ndigitpairs;
8787 :
8788 : /*
8789 : * In the computation below, digit pair i1 of var1 and digit pair i2 of
8790 : * var2 are multiplied and added to digit i1+i2+pair_offset of dig[]. Thus
8791 : * input digit pairs with index >= res_ndigitpairs - pair_offset don't
8792 : * contribute to the result, and can be ignored.
8793 : */
8794 28476 : if (res_ndigitpairs <= pair_offset)
8795 : {
8796 : /* All input digits will be ignored; so result is zero */
8797 12 : zero_var(result);
8798 12 : result->dscale = rscale;
8799 12 : return;
8800 : }
8801 28464 : var1ndigitpairs = Min(var1ndigitpairs, res_ndigitpairs - pair_offset);
8802 28464 : var2ndigitpairs = Min(var2ndigitpairs, res_ndigitpairs - pair_offset);
8803 :
8804 : /*
8805 : * We do the arithmetic in an array "dig[]" of unsigned 64-bit integers.
8806 : * Since PG_UINT64_MAX is much larger than NBASE^4, this gives us a lot of
8807 : * headroom to avoid normalizing carries immediately.
8808 : *
8809 : * maxdig tracks the maximum possible value of any dig[] entry; when this
8810 : * threatens to exceed PG_UINT64_MAX, we take the time to propagate
8811 : * carries. Furthermore, we need to ensure that overflow doesn't occur
8812 : * during the carry propagation passes either. The carry values could be
8813 : * as much as PG_UINT64_MAX / NBASE^2, so really we must normalize when
8814 : * digits threaten to exceed PG_UINT64_MAX - PG_UINT64_MAX / NBASE^2.
8815 : *
8816 : * To avoid overflow in maxdig itself, it actually represents the maximum
8817 : * possible value divided by NBASE^2-1, i.e., at the top of the loop it is
8818 : * known that no dig[] entry exceeds maxdig * (NBASE^2-1).
8819 : *
8820 : * The conversion of var1 to base NBASE^2 is done on the fly, as each new
8821 : * digit is required. The digits of var2 are converted upfront, and
8822 : * stored at the end of dig[]. To avoid loss of precision, the input
8823 : * digits are aligned with the start of digit pair array, effectively
8824 : * shifting them up (multiplying by NBASE) if the inputs have an odd
8825 : * number of NBASE digits.
8826 : */
8827 28464 : dig = (uint64 *) palloc(res_ndigitpairs * sizeof(uint64) +
8828 : var2ndigitpairs * sizeof(uint32));
8829 :
8830 : /* convert var2 to base NBASE^2, shifting up if its length is odd */
8831 28464 : var2digitpairs = (uint32 *) (dig + res_ndigitpairs);
8832 :
8833 1547190 : for (i2 = 0; i2 < var2ndigitpairs - 1; i2++)
8834 1518726 : var2digitpairs[i2] = var2digits[2 * i2] * NBASE + var2digits[2 * i2 + 1];
8835 :
8836 28464 : if (2 * i2 + 1 < var2ndigits)
8837 20448 : var2digitpairs[i2] = var2digits[2 * i2] * NBASE + var2digits[2 * i2 + 1];
8838 : else
8839 8016 : var2digitpairs[i2] = var2digits[2 * i2] * NBASE;
8840 :
8841 : /*
8842 : * Start by multiplying var2 by the least significant contributing digit
8843 : * pair from var1, storing the results at the end of dig[], and filling
8844 : * the leading digits with zeros.
8845 : *
8846 : * The loop here is the same as the inner loop below, except that we set
8847 : * the results in dig[], rather than adding to them. This is the
8848 : * performance bottleneck for multiplication, so we want to keep it simple
8849 : * enough so that it can be auto-vectorized. Accordingly, process the
8850 : * digits left-to-right even though schoolbook multiplication would
8851 : * suggest right-to-left. Since we aren't propagating carries in this
8852 : * loop, the order does not matter.
8853 : */
8854 28464 : i1 = var1ndigitpairs - 1;
8855 28464 : if (2 * i1 + 1 < var1ndigits)
8856 12720 : var1digitpair = var1digits[2 * i1] * NBASE + var1digits[2 * i1 + 1];
8857 : else
8858 15744 : var1digitpair = var1digits[2 * i1] * NBASE;
8859 28464 : maxdig = var1digitpair;
8860 :
8861 28464 : i2limit = Min(var2ndigitpairs, res_ndigitpairs - i1 - pair_offset);
8862 28464 : dig_i1_off = &dig[i1 + pair_offset];
8863 :
8864 28464 : memset(dig, 0, (i1 + pair_offset) * sizeof(uint64));
8865 1376622 : for (i2 = 0; i2 < i2limit; i2++)
8866 1348158 : dig_i1_off[i2] = (uint64) var1digitpair * var2digitpairs[i2];
8867 :
8868 : /*
8869 : * Next, multiply var2 by the remaining digit pairs from var1, adding the
8870 : * results to dig[] at the appropriate offsets, and normalizing whenever
8871 : * there is a risk of any dig[] entry overflowing.
8872 : */
8873 1501710 : for (i1 = i1 - 1; i1 >= 0; i1--)
8874 : {
8875 1473246 : var1digitpair = var1digits[2 * i1] * NBASE + var1digits[2 * i1 + 1];
8876 1473246 : if (var1digitpair == 0)
8877 1179516 : continue;
8878 :
8879 : /* Time to normalize? */
8880 293730 : maxdig += var1digitpair;
8881 293730 : if (maxdig > (PG_UINT64_MAX - PG_UINT64_MAX / NBASE_SQR) / (NBASE_SQR - 1))
8882 : {
8883 : /* Yes, do it (to base NBASE^2) */
8884 30 : carry = 0;
8885 119964 : for (i = res_ndigitpairs - 1; i >= 0; i--)
8886 : {
8887 119934 : newdig = dig[i] + carry;
8888 119934 : if (newdig >= NBASE_SQR)
8889 : {
8890 115242 : carry = newdig / NBASE_SQR;
8891 115242 : newdig -= carry * NBASE_SQR;
8892 : }
8893 : else
8894 4692 : carry = 0;
8895 119934 : dig[i] = newdig;
8896 : }
8897 : Assert(carry == 0);
8898 : /* Reset maxdig to indicate new worst-case */
8899 30 : maxdig = 1 + var1digitpair;
8900 : }
8901 :
8902 : /* Multiply and add */
8903 293730 : i2limit = Min(var2ndigitpairs, res_ndigitpairs - i1 - pair_offset);
8904 293730 : dig_i1_off = &dig[i1 + pair_offset];
8905 :
8906 124047846 : for (i2 = 0; i2 < i2limit; i2++)
8907 123754116 : dig_i1_off[i2] += (uint64) var1digitpair * var2digitpairs[i2];
8908 : }
8909 :
8910 : /*
8911 : * Now we do a final carry propagation pass to normalize back to base
8912 : * NBASE^2, and construct the base-NBASE result digits. Note that this is
8913 : * still done at full precision w/guard digits.
8914 : */
8915 28464 : alloc_var(result, res_ndigits);
8916 28464 : res_digits = result->digits;
8917 28464 : carry = 0;
8918 2882922 : for (i = res_ndigitpairs - 1; i >= 0; i--)
8919 : {
8920 2854458 : newdig = dig[i] + carry;
8921 2854458 : if (newdig >= NBASE_SQR)
8922 : {
8923 406914 : carry = newdig / NBASE_SQR;
8924 406914 : newdig -= carry * NBASE_SQR;
8925 : }
8926 : else
8927 2447544 : carry = 0;
8928 2854458 : res_digits[2 * i + 1] = (NumericDigit) ((uint32) newdig % NBASE);
8929 2854458 : res_digits[2 * i] = (NumericDigit) ((uint32) newdig / NBASE);
8930 : }
8931 : Assert(carry == 0);
8932 :
8933 28464 : pfree(dig);
8934 :
8935 : /*
8936 : * Finally, round the result to the requested precision.
8937 : */
8938 28464 : result->weight = res_weight;
8939 28464 : result->sign = res_sign;
8940 :
8941 : /* Round to target rscale (and set result->dscale) */
8942 28464 : round_var(result, rscale);
8943 :
8944 : /* Strip leading and trailing zeroes */
8945 28464 : strip_var(result);
8946 : }
8947 :
8948 :
8949 : /*
8950 : * mul_var_short() -
8951 : *
8952 : * Special-case multiplication function used when var1 has 1-6 digits, var2
8953 : * has at least as many digits as var1, and the exact product var1 * var2 is
8954 : * requested.
8955 : */
8956 : static void
8957 799620 : mul_var_short(const NumericVar *var1, const NumericVar *var2,
8958 : NumericVar *result)
8959 : {
8960 799620 : int var1ndigits = var1->ndigits;
8961 799620 : int var2ndigits = var2->ndigits;
8962 799620 : NumericDigit *var1digits = var1->digits;
8963 799620 : NumericDigit *var2digits = var2->digits;
8964 : int res_sign;
8965 : int res_weight;
8966 : int res_ndigits;
8967 : NumericDigit *res_buf;
8968 : NumericDigit *res_digits;
8969 799620 : uint32 carry = 0;
8970 : uint32 term;
8971 :
8972 : /* Check preconditions */
8973 : Assert(var1ndigits >= 1);
8974 : Assert(var1ndigits <= 6);
8975 : Assert(var2ndigits >= var1ndigits);
8976 :
8977 : /*
8978 : * Determine the result sign, weight, and number of digits to calculate.
8979 : * The weight figured here is correct if the product has no leading zero
8980 : * digits; otherwise strip_var() will fix things up. Note that, unlike
8981 : * mul_var(), we do not need to allocate an extra output digit, because we
8982 : * are not rounding here.
8983 : */
8984 799620 : if (var1->sign == var2->sign)
8985 798428 : res_sign = NUMERIC_POS;
8986 : else
8987 1192 : res_sign = NUMERIC_NEG;
8988 799620 : res_weight = var1->weight + var2->weight + 1;
8989 799620 : res_ndigits = var1ndigits + var2ndigits;
8990 :
8991 : /* Allocate result digit array */
8992 799620 : res_buf = digitbuf_alloc(res_ndigits + 1);
8993 799620 : res_buf[0] = 0; /* spare digit for later rounding */
8994 799620 : res_digits = res_buf + 1;
8995 :
8996 : /*
8997 : * Compute the result digits in reverse, in one pass, propagating the
8998 : * carry up as we go. The i'th result digit consists of the sum of the
8999 : * products var1digits[i1] * var2digits[i2] for which i = i1 + i2 + 1.
9000 : */
9001 : #define PRODSUM1(v1,i1,v2,i2) ((v1)[(i1)] * (v2)[(i2)])
9002 : #define PRODSUM2(v1,i1,v2,i2) (PRODSUM1(v1,i1,v2,i2) + (v1)[(i1)+1] * (v2)[(i2)-1])
9003 : #define PRODSUM3(v1,i1,v2,i2) (PRODSUM2(v1,i1,v2,i2) + (v1)[(i1)+2] * (v2)[(i2)-2])
9004 : #define PRODSUM4(v1,i1,v2,i2) (PRODSUM3(v1,i1,v2,i2) + (v1)[(i1)+3] * (v2)[(i2)-3])
9005 : #define PRODSUM5(v1,i1,v2,i2) (PRODSUM4(v1,i1,v2,i2) + (v1)[(i1)+4] * (v2)[(i2)-4])
9006 : #define PRODSUM6(v1,i1,v2,i2) (PRODSUM5(v1,i1,v2,i2) + (v1)[(i1)+5] * (v2)[(i2)-5])
9007 :
9008 799620 : switch (var1ndigits)
9009 : {
9010 793914 : case 1:
9011 : /* ---------
9012 : * 1-digit case:
9013 : * var1ndigits = 1
9014 : * var2ndigits >= 1
9015 : * res_ndigits = var2ndigits + 1
9016 : * ----------
9017 : */
9018 2887628 : for (int i = var2ndigits - 1; i >= 0; i--)
9019 : {
9020 2093714 : term = PRODSUM1(var1digits, 0, var2digits, i) + carry;
9021 2093714 : res_digits[i + 1] = (NumericDigit) (term % NBASE);
9022 2093714 : carry = term / NBASE;
9023 : }
9024 793914 : res_digits[0] = (NumericDigit) carry;
9025 793914 : break;
9026 :
9027 756 : case 2:
9028 : /* ---------
9029 : * 2-digit case:
9030 : * var1ndigits = 2
9031 : * var2ndigits >= 2
9032 : * res_ndigits = var2ndigits + 2
9033 : * ----------
9034 : */
9035 : /* last result digit and carry */
9036 756 : term = PRODSUM1(var1digits, 1, var2digits, var2ndigits - 1);
9037 756 : res_digits[res_ndigits - 1] = (NumericDigit) (term % NBASE);
9038 756 : carry = term / NBASE;
9039 :
9040 : /* remaining digits, except for the first two */
9041 2304 : for (int i = var2ndigits - 1; i >= 1; i--)
9042 : {
9043 1548 : term = PRODSUM2(var1digits, 0, var2digits, i) + carry;
9044 1548 : res_digits[i + 1] = (NumericDigit) (term % NBASE);
9045 1548 : carry = term / NBASE;
9046 : }
9047 756 : break;
9048 :
9049 204 : case 3:
9050 : /* ---------
9051 : * 3-digit case:
9052 : * var1ndigits = 3
9053 : * var2ndigits >= 3
9054 : * res_ndigits = var2ndigits + 3
9055 : * ----------
9056 : */
9057 : /* last two result digits */
9058 204 : term = PRODSUM1(var1digits, 2, var2digits, var2ndigits - 1);
9059 204 : res_digits[res_ndigits - 1] = (NumericDigit) (term % NBASE);
9060 204 : carry = term / NBASE;
9061 :
9062 204 : term = PRODSUM2(var1digits, 1, var2digits, var2ndigits - 1) + carry;
9063 204 : res_digits[res_ndigits - 2] = (NumericDigit) (term % NBASE);
9064 204 : carry = term / NBASE;
9065 :
9066 : /* remaining digits, except for the first three */
9067 546 : for (int i = var2ndigits - 1; i >= 2; i--)
9068 : {
9069 342 : term = PRODSUM3(var1digits, 0, var2digits, i) + carry;
9070 342 : res_digits[i + 1] = (NumericDigit) (term % NBASE);
9071 342 : carry = term / NBASE;
9072 : }
9073 204 : break;
9074 :
9075 4038 : case 4:
9076 : /* ---------
9077 : * 4-digit case:
9078 : * var1ndigits = 4
9079 : * var2ndigits >= 4
9080 : * res_ndigits = var2ndigits + 4
9081 : * ----------
9082 : */
9083 : /* last three result digits */
9084 4038 : term = PRODSUM1(var1digits, 3, var2digits, var2ndigits - 1);
9085 4038 : res_digits[res_ndigits - 1] = (NumericDigit) (term % NBASE);
9086 4038 : carry = term / NBASE;
9087 :
9088 4038 : term = PRODSUM2(var1digits, 2, var2digits, var2ndigits - 1) + carry;
9089 4038 : res_digits[res_ndigits - 2] = (NumericDigit) (term % NBASE);
9090 4038 : carry = term / NBASE;
9091 :
9092 4038 : term = PRODSUM3(var1digits, 1, var2digits, var2ndigits - 1) + carry;
9093 4038 : res_digits[res_ndigits - 3] = (NumericDigit) (term % NBASE);
9094 4038 : carry = term / NBASE;
9095 :
9096 : /* remaining digits, except for the first four */
9097 11268 : for (int i = var2ndigits - 1; i >= 3; i--)
9098 : {
9099 7230 : term = PRODSUM4(var1digits, 0, var2digits, i) + carry;
9100 7230 : res_digits[i + 1] = (NumericDigit) (term % NBASE);
9101 7230 : carry = term / NBASE;
9102 : }
9103 4038 : break;
9104 :
9105 114 : case 5:
9106 : /* ---------
9107 : * 5-digit case:
9108 : * var1ndigits = 5
9109 : * var2ndigits >= 5
9110 : * res_ndigits = var2ndigits + 5
9111 : * ----------
9112 : */
9113 : /* last four result digits */
9114 114 : term = PRODSUM1(var1digits, 4, var2digits, var2ndigits - 1);
9115 114 : res_digits[res_ndigits - 1] = (NumericDigit) (term % NBASE);
9116 114 : carry = term / NBASE;
9117 :
9118 114 : term = PRODSUM2(var1digits, 3, var2digits, var2ndigits - 1) + carry;
9119 114 : res_digits[res_ndigits - 2] = (NumericDigit) (term % NBASE);
9120 114 : carry = term / NBASE;
9121 :
9122 114 : term = PRODSUM3(var1digits, 2, var2digits, var2ndigits - 1) + carry;
9123 114 : res_digits[res_ndigits - 3] = (NumericDigit) (term % NBASE);
9124 114 : carry = term / NBASE;
9125 :
9126 114 : term = PRODSUM4(var1digits, 1, var2digits, var2ndigits - 1) + carry;
9127 114 : res_digits[res_ndigits - 4] = (NumericDigit) (term % NBASE);
9128 114 : carry = term / NBASE;
9129 :
9130 : /* remaining digits, except for the first five */
9131 300 : for (int i = var2ndigits - 1; i >= 4; i--)
9132 : {
9133 186 : term = PRODSUM5(var1digits, 0, var2digits, i) + carry;
9134 186 : res_digits[i + 1] = (NumericDigit) (term % NBASE);
9135 186 : carry = term / NBASE;
9136 : }
9137 114 : break;
9138 :
9139 594 : case 6:
9140 : /* ---------
9141 : * 6-digit case:
9142 : * var1ndigits = 6
9143 : * var2ndigits >= 6
9144 : * res_ndigits = var2ndigits + 6
9145 : * ----------
9146 : */
9147 : /* last five result digits */
9148 594 : term = PRODSUM1(var1digits, 5, var2digits, var2ndigits - 1);
9149 594 : res_digits[res_ndigits - 1] = (NumericDigit) (term % NBASE);
9150 594 : carry = term / NBASE;
9151 :
9152 594 : term = PRODSUM2(var1digits, 4, var2digits, var2ndigits - 1) + carry;
9153 594 : res_digits[res_ndigits - 2] = (NumericDigit) (term % NBASE);
9154 594 : carry = term / NBASE;
9155 :
9156 594 : term = PRODSUM3(var1digits, 3, var2digits, var2ndigits - 1) + carry;
9157 594 : res_digits[res_ndigits - 3] = (NumericDigit) (term % NBASE);
9158 594 : carry = term / NBASE;
9159 :
9160 594 : term = PRODSUM4(var1digits, 2, var2digits, var2ndigits - 1) + carry;
9161 594 : res_digits[res_ndigits - 4] = (NumericDigit) (term % NBASE);
9162 594 : carry = term / NBASE;
9163 :
9164 594 : term = PRODSUM5(var1digits, 1, var2digits, var2ndigits - 1) + carry;
9165 594 : res_digits[res_ndigits - 5] = (NumericDigit) (term % NBASE);
9166 594 : carry = term / NBASE;
9167 :
9168 : /* remaining digits, except for the first six */
9169 1656 : for (int i = var2ndigits - 1; i >= 5; i--)
9170 : {
9171 1062 : term = PRODSUM6(var1digits, 0, var2digits, i) + carry;
9172 1062 : res_digits[i + 1] = (NumericDigit) (term % NBASE);
9173 1062 : carry = term / NBASE;
9174 : }
9175 594 : break;
9176 : }
9177 :
9178 : /*
9179 : * Finally, for var1ndigits > 1, compute the remaining var1ndigits most
9180 : * significant result digits.
9181 : */
9182 799620 : switch (var1ndigits)
9183 : {
9184 594 : case 6:
9185 594 : term = PRODSUM5(var1digits, 0, var2digits, 4) + carry;
9186 594 : res_digits[5] = (NumericDigit) (term % NBASE);
9187 594 : carry = term / NBASE;
9188 : /* FALLTHROUGH */
9189 708 : case 5:
9190 708 : term = PRODSUM4(var1digits, 0, var2digits, 3) + carry;
9191 708 : res_digits[4] = (NumericDigit) (term % NBASE);
9192 708 : carry = term / NBASE;
9193 : /* FALLTHROUGH */
9194 4746 : case 4:
9195 4746 : term = PRODSUM3(var1digits, 0, var2digits, 2) + carry;
9196 4746 : res_digits[3] = (NumericDigit) (term % NBASE);
9197 4746 : carry = term / NBASE;
9198 : /* FALLTHROUGH */
9199 4950 : case 3:
9200 4950 : term = PRODSUM2(var1digits, 0, var2digits, 1) + carry;
9201 4950 : res_digits[2] = (NumericDigit) (term % NBASE);
9202 4950 : carry = term / NBASE;
9203 : /* FALLTHROUGH */
9204 5706 : case 2:
9205 5706 : term = PRODSUM1(var1digits, 0, var2digits, 0) + carry;
9206 5706 : res_digits[1] = (NumericDigit) (term % NBASE);
9207 5706 : res_digits[0] = (NumericDigit) (term / NBASE);
9208 5706 : break;
9209 : }
9210 :
9211 : /* Store the product in result */
9212 799620 : digitbuf_free(result->buf);
9213 799620 : result->ndigits = res_ndigits;
9214 799620 : result->buf = res_buf;
9215 799620 : result->digits = res_digits;
9216 799620 : result->weight = res_weight;
9217 799620 : result->sign = res_sign;
9218 799620 : result->dscale = var1->dscale + var2->dscale;
9219 :
9220 : /* Strip leading and trailing zeroes */
9221 799620 : strip_var(result);
9222 799620 : }
9223 :
9224 :
9225 : /*
9226 : * div_var() -
9227 : *
9228 : * Compute the quotient var1 / var2 to rscale fractional digits.
9229 : *
9230 : * If "round" is true, the result is rounded at the rscale'th digit; if
9231 : * false, it is truncated (towards zero) at that digit.
9232 : *
9233 : * If "exact" is true, the exact result is computed to the specified rscale;
9234 : * if false, successive quotient digits are approximated up to rscale plus
9235 : * DIV_GUARD_DIGITS extra digits, ignoring all contributions from digits to
9236 : * the right of that, before rounding or truncating to the specified rscale.
9237 : * This can be significantly faster, and usually gives the same result as the
9238 : * exact computation, but it may occasionally be off by one in the final
9239 : * digit, if contributions from the ignored digits would have propagated
9240 : * through the guard digits. This is good enough for the transcendental
9241 : * functions, where small errors are acceptable.
9242 : */
9243 : static void
9244 214194 : div_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result,
9245 : int rscale, bool round, bool exact)
9246 : {
9247 214194 : int var1ndigits = var1->ndigits;
9248 214194 : int var2ndigits = var2->ndigits;
9249 : int res_sign;
9250 : int res_weight;
9251 : int res_ndigits;
9252 : int var1ndigitpairs;
9253 : int var2ndigitpairs;
9254 : int res_ndigitpairs;
9255 : int div_ndigitpairs;
9256 : int64 *dividend;
9257 : int32 *divisor;
9258 : double fdivisor,
9259 : fdivisorinverse,
9260 : fdividend,
9261 : fquotient;
9262 : int64 maxdiv;
9263 : int qi;
9264 : int32 qdigit;
9265 : int64 carry;
9266 : int64 newdig;
9267 : int64 *remainder;
9268 : NumericDigit *res_digits;
9269 : int i;
9270 :
9271 : /*
9272 : * First of all division by zero check; we must not be handed an
9273 : * unnormalized divisor.
9274 : */
9275 214194 : if (var2ndigits == 0 || var2->digits[0] == 0)
9276 62 : ereport(ERROR,
9277 : (errcode(ERRCODE_DIVISION_BY_ZERO),
9278 : errmsg("division by zero")));
9279 :
9280 : /*
9281 : * If the divisor has just one or two digits, delegate to div_var_int(),
9282 : * which uses fast short division.
9283 : *
9284 : * Similarly, on platforms with 128-bit integer support, delegate to
9285 : * div_var_int64() for divisors with three or four digits.
9286 : */
9287 214132 : if (var2ndigits <= 2)
9288 : {
9289 : int idivisor;
9290 : int idivisor_weight;
9291 :
9292 205054 : idivisor = var2->digits[0];
9293 205054 : idivisor_weight = var2->weight;
9294 205054 : if (var2ndigits == 2)
9295 : {
9296 3914 : idivisor = idivisor * NBASE + var2->digits[1];
9297 3914 : idivisor_weight--;
9298 : }
9299 205054 : if (var2->sign == NUMERIC_NEG)
9300 642 : idivisor = -idivisor;
9301 :
9302 205054 : div_var_int(var1, idivisor, idivisor_weight, result, rscale, round);
9303 205054 : return;
9304 : }
9305 : #ifdef HAVE_INT128
9306 9078 : if (var2ndigits <= 4)
9307 : {
9308 : int64 idivisor;
9309 : int idivisor_weight;
9310 :
9311 546 : idivisor = var2->digits[0];
9312 546 : idivisor_weight = var2->weight;
9313 2040 : for (i = 1; i < var2ndigits; i++)
9314 : {
9315 1494 : idivisor = idivisor * NBASE + var2->digits[i];
9316 1494 : idivisor_weight--;
9317 : }
9318 546 : if (var2->sign == NUMERIC_NEG)
9319 120 : idivisor = -idivisor;
9320 :
9321 546 : div_var_int64(var1, idivisor, idivisor_weight, result, rscale, round);
9322 546 : return;
9323 : }
9324 : #endif
9325 :
9326 : /*
9327 : * Otherwise, perform full long division.
9328 : */
9329 :
9330 : /* Result zero check */
9331 8532 : if (var1ndigits == 0)
9332 : {
9333 36 : zero_var(result);
9334 36 : result->dscale = rscale;
9335 36 : return;
9336 : }
9337 :
9338 : /*
9339 : * The approximate computation can be significantly faster than the exact
9340 : * one, since the working dividend is var2ndigitpairs base-NBASE^2 digits
9341 : * shorter below. However, that comes with the tradeoff of computing
9342 : * DIV_GUARD_DIGITS extra base-NBASE result digits. Ignoring all other
9343 : * overheads, that suggests that, in theory, the approximate computation
9344 : * will only be faster than the exact one when var2ndigits is greater than
9345 : * 2 * (DIV_GUARD_DIGITS + 1), independent of the size of var1.
9346 : *
9347 : * Thus, we're better off doing an exact computation when var2 is shorter
9348 : * than this. Empirically, it has been found that the exact threshold is
9349 : * a little higher, due to other overheads in the outer division loop.
9350 : */
9351 8496 : if (var2ndigits <= 2 * (DIV_GUARD_DIGITS + 2))
9352 5630 : exact = true;
9353 :
9354 : /*
9355 : * Determine the result sign, weight and number of digits to calculate.
9356 : * The weight figured here is correct if the emitted quotient has no
9357 : * leading zero digits; otherwise strip_var() will fix things up.
9358 : */
9359 8496 : if (var1->sign == var2->sign)
9360 8364 : res_sign = NUMERIC_POS;
9361 : else
9362 132 : res_sign = NUMERIC_NEG;
9363 8496 : res_weight = var1->weight - var2->weight + 1;
9364 : /* The number of accurate result digits we need to produce: */
9365 8496 : res_ndigits = res_weight + 1 + (rscale + DEC_DIGITS - 1) / DEC_DIGITS;
9366 : /* ... but always at least 1 */
9367 8496 : res_ndigits = Max(res_ndigits, 1);
9368 : /* If rounding needed, figure one more digit to ensure correct result */
9369 8496 : if (round)
9370 3960 : res_ndigits++;
9371 : /* Add guard digits for roundoff error when producing approx result */
9372 8496 : if (!exact)
9373 1722 : res_ndigits += DIV_GUARD_DIGITS;
9374 :
9375 : /*
9376 : * The computation itself is done using base-NBASE^2 arithmetic, so we
9377 : * actually process the input digits in pairs, producing a base-NBASE^2
9378 : * intermediate result. This significantly improves performance, since
9379 : * the computation is O(N^2) in the number of input digits, and working in
9380 : * base NBASE^2 effectively halves "N".
9381 : */
9382 8496 : var1ndigitpairs = (var1ndigits + 1) / 2;
9383 8496 : var2ndigitpairs = (var2ndigits + 1) / 2;
9384 8496 : res_ndigitpairs = (res_ndigits + 1) / 2;
9385 8496 : res_ndigits = 2 * res_ndigitpairs;
9386 :
9387 : /*
9388 : * We do the arithmetic in an array "dividend[]" of signed 64-bit
9389 : * integers. Since PG_INT64_MAX is much larger than NBASE^4, this gives
9390 : * us a lot of headroom to avoid normalizing carries immediately.
9391 : *
9392 : * When performing an exact computation, the working dividend requires
9393 : * res_ndigitpairs + var2ndigitpairs digits. If var1 is larger than that,
9394 : * the extra digits do not contribute to the result, and are ignored.
9395 : *
9396 : * When performing an approximate computation, the working dividend only
9397 : * requires res_ndigitpairs digits (which includes the extra guard
9398 : * digits). All input digits beyond that are ignored.
9399 : */
9400 8496 : if (exact)
9401 : {
9402 6774 : div_ndigitpairs = res_ndigitpairs + var2ndigitpairs;
9403 6774 : var1ndigitpairs = Min(var1ndigitpairs, div_ndigitpairs);
9404 : }
9405 : else
9406 : {
9407 1722 : div_ndigitpairs = res_ndigitpairs;
9408 1722 : var1ndigitpairs = Min(var1ndigitpairs, div_ndigitpairs);
9409 1722 : var2ndigitpairs = Min(var2ndigitpairs, div_ndigitpairs);
9410 : }
9411 :
9412 : /*
9413 : * Allocate room for the working dividend (div_ndigitpairs 64-bit digits)
9414 : * plus the divisor (var2ndigitpairs 32-bit base-NBASE^2 digits).
9415 : *
9416 : * For convenience, we allocate one extra dividend digit, which is set to
9417 : * zero and not counted in div_ndigitpairs, so that the main loop below
9418 : * can safely read and write the (qi+1)'th digit in the approximate case.
9419 : */
9420 8496 : dividend = (int64 *) palloc((div_ndigitpairs + 1) * sizeof(int64) +
9421 : var2ndigitpairs * sizeof(int32));
9422 8496 : divisor = (int32 *) (dividend + div_ndigitpairs + 1);
9423 :
9424 : /* load var1 into dividend[0 .. var1ndigitpairs-1], zeroing the rest */
9425 60342 : for (i = 0; i < var1ndigitpairs - 1; i++)
9426 51846 : dividend[i] = var1->digits[2 * i] * NBASE + var1->digits[2 * i + 1];
9427 :
9428 8496 : if (2 * i + 1 < var1ndigits)
9429 4846 : dividend[i] = var1->digits[2 * i] * NBASE + var1->digits[2 * i + 1];
9430 : else
9431 3650 : dividend[i] = var1->digits[2 * i] * NBASE;
9432 :
9433 8496 : memset(dividend + i + 1, 0, (div_ndigitpairs - i) * sizeof(int64));
9434 :
9435 : /* load var2 into divisor[0 .. var2ndigitpairs-1] */
9436 107304 : for (i = 0; i < var2ndigitpairs - 1; i++)
9437 98808 : divisor[i] = var2->digits[2 * i] * NBASE + var2->digits[2 * i + 1];
9438 :
9439 8496 : if (2 * i + 1 < var2ndigits)
9440 2956 : divisor[i] = var2->digits[2 * i] * NBASE + var2->digits[2 * i + 1];
9441 : else
9442 5540 : divisor[i] = var2->digits[2 * i] * NBASE;
9443 :
9444 : /*
9445 : * We estimate each quotient digit using floating-point arithmetic, taking
9446 : * the first 2 base-NBASE^2 digits of the (current) dividend and divisor.
9447 : * This must be float to avoid overflow.
9448 : *
9449 : * Since the floating-point dividend and divisor use 4 base-NBASE input
9450 : * digits, they include roughly 40-53 bits of information from their
9451 : * respective inputs (assuming NBASE is 10000), which fits well in IEEE
9452 : * double-precision variables. The relative error in the floating-point
9453 : * quotient digit will then be less than around 2/NBASE^3, so the
9454 : * estimated base-NBASE^2 quotient digit will typically be correct, and
9455 : * should not be off by more than one from the correct value.
9456 : */
9457 8496 : fdivisor = (double) divisor[0] * NBASE_SQR;
9458 8496 : if (var2ndigitpairs > 1)
9459 8496 : fdivisor += (double) divisor[1];
9460 8496 : fdivisorinverse = 1.0 / fdivisor;
9461 :
9462 : /*
9463 : * maxdiv tracks the maximum possible absolute value of any dividend[]
9464 : * entry; when this threatens to exceed PG_INT64_MAX, we take the time to
9465 : * propagate carries. Furthermore, we need to ensure that overflow
9466 : * doesn't occur during the carry propagation passes either. The carry
9467 : * values may have an absolute value as high as PG_INT64_MAX/NBASE^2 + 1,
9468 : * so really we must normalize when digits threaten to exceed PG_INT64_MAX
9469 : * - PG_INT64_MAX/NBASE^2 - 1.
9470 : *
9471 : * To avoid overflow in maxdiv itself, it represents the max absolute
9472 : * value divided by NBASE^2-1, i.e., at the top of the loop it is known
9473 : * that no dividend[] entry has an absolute value exceeding maxdiv *
9474 : * (NBASE^2-1).
9475 : *
9476 : * Actually, though, that holds good only for dividend[] entries after
9477 : * dividend[qi]; the adjustment done at the bottom of the loop may cause
9478 : * dividend[qi + 1] to exceed the maxdiv limit, so that dividend[qi] in
9479 : * the next iteration is beyond the limit. This does not cause problems,
9480 : * as explained below.
9481 : */
9482 8496 : maxdiv = 1;
9483 :
9484 : /*
9485 : * Outer loop computes next quotient digit, which goes in dividend[qi].
9486 : */
9487 64896 : for (qi = 0; qi < res_ndigitpairs; qi++)
9488 : {
9489 : /* Approximate the current dividend value */
9490 56400 : fdividend = (double) dividend[qi] * NBASE_SQR;
9491 56400 : fdividend += (double) dividend[qi + 1];
9492 :
9493 : /* Compute the (approximate) quotient digit */
9494 56400 : fquotient = fdividend * fdivisorinverse;
9495 56400 : qdigit = (fquotient >= 0.0) ? ((int32) fquotient) :
9496 6 : (((int32) fquotient) - 1); /* truncate towards -infinity */
9497 :
9498 56400 : if (qdigit != 0)
9499 : {
9500 : /* Do we need to normalize now? */
9501 50176 : maxdiv += i64abs(qdigit);
9502 50176 : if (maxdiv > (PG_INT64_MAX - PG_INT64_MAX / NBASE_SQR - 1) / (NBASE_SQR - 1))
9503 : {
9504 : /*
9505 : * Yes, do it. Note that if var2ndigitpairs is much smaller
9506 : * than div_ndigitpairs, we can save a significant amount of
9507 : * effort here by noting that we only need to normalise those
9508 : * dividend[] entries touched where prior iterations
9509 : * subtracted multiples of the divisor.
9510 : */
9511 6 : carry = 0;
9512 6750 : for (i = Min(qi + var2ndigitpairs - 2, div_ndigitpairs - 1); i > qi; i--)
9513 : {
9514 6744 : newdig = dividend[i] + carry;
9515 6744 : if (newdig < 0)
9516 : {
9517 6744 : carry = -((-newdig - 1) / NBASE_SQR) - 1;
9518 6744 : newdig -= carry * NBASE_SQR;
9519 : }
9520 0 : else if (newdig >= NBASE_SQR)
9521 : {
9522 0 : carry = newdig / NBASE_SQR;
9523 0 : newdig -= carry * NBASE_SQR;
9524 : }
9525 : else
9526 0 : carry = 0;
9527 6744 : dividend[i] = newdig;
9528 : }
9529 6 : dividend[qi] += carry;
9530 :
9531 : /*
9532 : * All the dividend[] digits except possibly dividend[qi] are
9533 : * now in the range 0..NBASE^2-1. We do not need to consider
9534 : * dividend[qi] in the maxdiv value anymore, so we can reset
9535 : * maxdiv to 1.
9536 : */
9537 6 : maxdiv = 1;
9538 :
9539 : /*
9540 : * Recompute the quotient digit since new info may have
9541 : * propagated into the top two dividend digits.
9542 : */
9543 6 : fdividend = (double) dividend[qi] * NBASE_SQR;
9544 6 : fdividend += (double) dividend[qi + 1];
9545 6 : fquotient = fdividend * fdivisorinverse;
9546 6 : qdigit = (fquotient >= 0.0) ? ((int32) fquotient) :
9547 0 : (((int32) fquotient) - 1); /* truncate towards -infinity */
9548 :
9549 6 : maxdiv += i64abs(qdigit);
9550 : }
9551 :
9552 : /*
9553 : * Subtract off the appropriate multiple of the divisor.
9554 : *
9555 : * The digits beyond dividend[qi] cannot overflow, because we know
9556 : * they will fall within the maxdiv limit. As for dividend[qi]
9557 : * itself, note that qdigit is approximately trunc(dividend[qi] /
9558 : * divisor[0]), which would make the new value simply dividend[qi]
9559 : * mod divisor[0]. The lower-order terms in qdigit can change
9560 : * this result by not more than about twice PG_INT64_MAX/NBASE^2,
9561 : * so overflow is impossible.
9562 : *
9563 : * This inner loop is the performance bottleneck for division, so
9564 : * code it in the same way as the inner loop of mul_var() so that
9565 : * it can be auto-vectorized.
9566 : */
9567 50176 : if (qdigit != 0)
9568 : {
9569 50176 : int istop = Min(var2ndigitpairs, div_ndigitpairs - qi);
9570 50176 : int64 *dividend_qi = ÷nd[qi];
9571 :
9572 8073828 : for (i = 0; i < istop; i++)
9573 8023652 : dividend_qi[i] -= (int64) qdigit * divisor[i];
9574 : }
9575 : }
9576 :
9577 : /*
9578 : * The dividend digit we are about to replace might still be nonzero.
9579 : * Fold it into the next digit position.
9580 : *
9581 : * There is no risk of overflow here, although proving that requires
9582 : * some care. Much as with the argument for dividend[qi] not
9583 : * overflowing, if we consider the first two terms in the numerator
9584 : * and denominator of qdigit, we can see that the final value of
9585 : * dividend[qi + 1] will be approximately a remainder mod
9586 : * (divisor[0]*NBASE^2 + divisor[1]). Accounting for the lower-order
9587 : * terms is a bit complicated but ends up adding not much more than
9588 : * PG_INT64_MAX/NBASE^2 to the possible range. Thus, dividend[qi + 1]
9589 : * cannot overflow here, and in its role as dividend[qi] in the next
9590 : * loop iteration, it can't be large enough to cause overflow in the
9591 : * carry propagation step (if any), either.
9592 : *
9593 : * But having said that: dividend[qi] can be more than
9594 : * PG_INT64_MAX/NBASE^2, as noted above, which means that the product
9595 : * dividend[qi] * NBASE^2 *can* overflow. When that happens, adding
9596 : * it to dividend[qi + 1] will always cause a canceling overflow so
9597 : * that the end result is correct. We could avoid the intermediate
9598 : * overflow by doing the multiplication and addition using unsigned
9599 : * int64 arithmetic, which is modulo 2^64, but so far there appears no
9600 : * need.
9601 : */
9602 56400 : dividend[qi + 1] += dividend[qi] * NBASE_SQR;
9603 :
9604 56400 : dividend[qi] = qdigit;
9605 : }
9606 :
9607 : /*
9608 : * If an exact result was requested, use the remainder to correct the
9609 : * approximate quotient. The remainder is in dividend[], immediately
9610 : * after the quotient digits. Note, however, that although the remainder
9611 : * starts at dividend[qi = res_ndigitpairs], the first digit is the result
9612 : * of folding two remainder digits into one above, and the remainder
9613 : * currently only occupies var2ndigitpairs - 1 digits (the last digit of
9614 : * the working dividend was untouched by the computation above). Thus we
9615 : * expand the remainder down by one base-NBASE^2 digit when we normalize
9616 : * it, so that it completely fills the last var2ndigitpairs digits of the
9617 : * dividend array.
9618 : */
9619 8496 : if (exact)
9620 : {
9621 : /* Normalize the remainder, expanding it down by one digit */
9622 6774 : remainder = ÷nd[qi];
9623 6774 : carry = 0;
9624 87678 : for (i = var2ndigitpairs - 2; i >= 0; i--)
9625 : {
9626 80904 : newdig = remainder[i] + carry;
9627 80904 : if (newdig < 0)
9628 : {
9629 74040 : carry = -((-newdig - 1) / NBASE_SQR) - 1;
9630 74040 : newdig -= carry * NBASE_SQR;
9631 : }
9632 6864 : else if (newdig >= NBASE_SQR)
9633 : {
9634 6718 : carry = newdig / NBASE_SQR;
9635 6718 : newdig -= carry * NBASE_SQR;
9636 : }
9637 : else
9638 146 : carry = 0;
9639 80904 : remainder[i + 1] = newdig;
9640 : }
9641 6774 : remainder[0] = carry;
9642 :
9643 6774 : if (remainder[0] < 0)
9644 : {
9645 : /*
9646 : * The remainder is negative, so the approximate quotient is too
9647 : * large. Correct by reducing the quotient by one and adding the
9648 : * divisor to the remainder until the remainder is positive. We
9649 : * expect the quotient to be off by at most one, which has been
9650 : * borne out in all testing, but not conclusively proven, so we
9651 : * allow for larger corrections, just in case.
9652 : */
9653 : do
9654 : {
9655 : /* Add the divisor to the remainder */
9656 26 : carry = 0;
9657 1138 : for (i = var2ndigitpairs - 1; i > 0; i--)
9658 : {
9659 1112 : newdig = remainder[i] + divisor[i] + carry;
9660 1112 : if (newdig >= NBASE_SQR)
9661 : {
9662 966 : remainder[i] = newdig - NBASE_SQR;
9663 966 : carry = 1;
9664 : }
9665 : else
9666 : {
9667 146 : remainder[i] = newdig;
9668 146 : carry = 0;
9669 : }
9670 : }
9671 26 : remainder[0] += divisor[0] + carry;
9672 :
9673 : /* Subtract 1 from the quotient (propagating carries later) */
9674 26 : dividend[qi - 1]--;
9675 :
9676 26 : } while (remainder[0] < 0);
9677 : }
9678 : else
9679 : {
9680 : /*
9681 : * The remainder is nonnegative. If it's greater than or equal to
9682 : * the divisor, then the approximate quotient is too small and
9683 : * must be corrected. As above, we don't expect to have to apply
9684 : * more than one correction, but allow for it just in case.
9685 : */
9686 : while (true)
9687 6 : {
9688 6754 : bool less = false;
9689 :
9690 : /* Is remainder < divisor? */
9691 6772 : for (i = 0; i < var2ndigitpairs; i++)
9692 : {
9693 6766 : if (remainder[i] < divisor[i])
9694 : {
9695 6748 : less = true;
9696 6748 : break;
9697 : }
9698 18 : if (remainder[i] > divisor[i])
9699 0 : break; /* remainder > divisor */
9700 : }
9701 6754 : if (less)
9702 6748 : break; /* quotient is correct */
9703 :
9704 : /* Subtract the divisor from the remainder */
9705 6 : carry = 0;
9706 18 : for (i = var2ndigitpairs - 1; i > 0; i--)
9707 : {
9708 12 : newdig = remainder[i] - divisor[i] + carry;
9709 12 : if (newdig < 0)
9710 : {
9711 0 : remainder[i] = newdig + NBASE_SQR;
9712 0 : carry = -1;
9713 : }
9714 : else
9715 : {
9716 12 : remainder[i] = newdig;
9717 12 : carry = 0;
9718 : }
9719 : }
9720 6 : remainder[0] = remainder[0] - divisor[0] + carry;
9721 :
9722 : /* Add 1 to the quotient (propagating carries later) */
9723 6 : dividend[qi - 1]++;
9724 : }
9725 : }
9726 : }
9727 :
9728 : /*
9729 : * Because the quotient digits were estimates that might have been off by
9730 : * one (and we didn't bother propagating carries when adjusting the
9731 : * quotient above), some quotient digits might be out of range, so do a
9732 : * final carry propagation pass to normalize back to base NBASE^2, and
9733 : * construct the base-NBASE result digits. Note that this is still done
9734 : * at full precision w/guard digits.
9735 : */
9736 8496 : alloc_var(result, res_ndigits);
9737 8496 : res_digits = result->digits;
9738 8496 : carry = 0;
9739 64896 : for (i = res_ndigitpairs - 1; i >= 0; i--)
9740 : {
9741 56400 : newdig = dividend[i] + carry;
9742 56400 : if (newdig < 0)
9743 : {
9744 66 : carry = -((-newdig - 1) / NBASE_SQR) - 1;
9745 66 : newdig -= carry * NBASE_SQR;
9746 : }
9747 56334 : else if (newdig >= NBASE_SQR)
9748 : {
9749 0 : carry = newdig / NBASE_SQR;
9750 0 : newdig -= carry * NBASE_SQR;
9751 : }
9752 : else
9753 56334 : carry = 0;
9754 56400 : res_digits[2 * i + 1] = (NumericDigit) ((uint32) newdig % NBASE);
9755 56400 : res_digits[2 * i] = (NumericDigit) ((uint32) newdig / NBASE);
9756 : }
9757 : Assert(carry == 0);
9758 :
9759 8496 : pfree(dividend);
9760 :
9761 : /*
9762 : * Finally, round or truncate the result to the requested precision.
9763 : */
9764 8496 : result->weight = res_weight;
9765 8496 : result->sign = res_sign;
9766 :
9767 : /* Round or truncate to target rscale (and set result->dscale) */
9768 8496 : if (round)
9769 3960 : round_var(result, rscale);
9770 : else
9771 4536 : trunc_var(result, rscale);
9772 :
9773 : /* Strip leading and trailing zeroes */
9774 8496 : strip_var(result);
9775 : }
9776 :
9777 :
9778 : /*
9779 : * div_var_int() -
9780 : *
9781 : * Divide a numeric variable by a 32-bit integer with the specified weight.
9782 : * The quotient var / (ival * NBASE^ival_weight) is stored in result.
9783 : */
9784 : static void
9785 224212 : div_var_int(const NumericVar *var, int ival, int ival_weight,
9786 : NumericVar *result, int rscale, bool round)
9787 : {
9788 224212 : NumericDigit *var_digits = var->digits;
9789 224212 : int var_ndigits = var->ndigits;
9790 : int res_sign;
9791 : int res_weight;
9792 : int res_ndigits;
9793 : NumericDigit *res_buf;
9794 : NumericDigit *res_digits;
9795 : uint32 divisor;
9796 : int i;
9797 :
9798 : /* Guard against division by zero */
9799 224212 : if (ival == 0)
9800 0 : ereport(ERROR,
9801 : errcode(ERRCODE_DIVISION_BY_ZERO),
9802 : errmsg("division by zero"));
9803 :
9804 : /* Result zero check */
9805 224212 : if (var_ndigits == 0)
9806 : {
9807 2300 : zero_var(result);
9808 2300 : result->dscale = rscale;
9809 2300 : return;
9810 : }
9811 :
9812 : /*
9813 : * Determine the result sign, weight and number of digits to calculate.
9814 : * The weight figured here is correct if the emitted quotient has no
9815 : * leading zero digits; otherwise strip_var() will fix things up.
9816 : */
9817 221912 : if (var->sign == NUMERIC_POS)
9818 218936 : res_sign = ival > 0 ? NUMERIC_POS : NUMERIC_NEG;
9819 : else
9820 2976 : res_sign = ival > 0 ? NUMERIC_NEG : NUMERIC_POS;
9821 221912 : res_weight = var->weight - ival_weight;
9822 : /* The number of accurate result digits we need to produce: */
9823 221912 : res_ndigits = res_weight + 1 + (rscale + DEC_DIGITS - 1) / DEC_DIGITS;
9824 : /* ... but always at least 1 */
9825 221912 : res_ndigits = Max(res_ndigits, 1);
9826 : /* If rounding needed, figure one more digit to ensure correct result */
9827 221912 : if (round)
9828 166626 : res_ndigits++;
9829 :
9830 221912 : res_buf = digitbuf_alloc(res_ndigits + 1);
9831 221912 : res_buf[0] = 0; /* spare digit for later rounding */
9832 221912 : res_digits = res_buf + 1;
9833 :
9834 : /*
9835 : * Now compute the quotient digits. This is the short division algorithm
9836 : * described in Knuth volume 2, section 4.3.1 exercise 16, except that we
9837 : * allow the divisor to exceed the internal base.
9838 : *
9839 : * In this algorithm, the carry from one digit to the next is at most
9840 : * divisor - 1. Therefore, while processing the next digit, carry may
9841 : * become as large as divisor * NBASE - 1, and so it requires a 64-bit
9842 : * integer if this exceeds UINT_MAX.
9843 : */
9844 221912 : divisor = abs(ival);
9845 :
9846 221912 : if (divisor <= UINT_MAX / NBASE)
9847 : {
9848 : /* carry cannot overflow 32 bits */
9849 218586 : uint32 carry = 0;
9850 :
9851 2124320 : for (i = 0; i < res_ndigits; i++)
9852 : {
9853 1905734 : carry = carry * NBASE + (i < var_ndigits ? var_digits[i] : 0);
9854 1905734 : res_digits[i] = (NumericDigit) (carry / divisor);
9855 1905734 : carry = carry % divisor;
9856 : }
9857 : }
9858 : else
9859 : {
9860 : /* carry may exceed 32 bits */
9861 3326 : uint64 carry = 0;
9862 :
9863 10644 : for (i = 0; i < res_ndigits; i++)
9864 : {
9865 7318 : carry = carry * NBASE + (i < var_ndigits ? var_digits[i] : 0);
9866 7318 : res_digits[i] = (NumericDigit) (carry / divisor);
9867 7318 : carry = carry % divisor;
9868 : }
9869 : }
9870 :
9871 : /* Store the quotient in result */
9872 221912 : digitbuf_free(result->buf);
9873 221912 : result->ndigits = res_ndigits;
9874 221912 : result->buf = res_buf;
9875 221912 : result->digits = res_digits;
9876 221912 : result->weight = res_weight;
9877 221912 : result->sign = res_sign;
9878 :
9879 : /* Round or truncate to target rscale (and set result->dscale) */
9880 221912 : if (round)
9881 166626 : round_var(result, rscale);
9882 : else
9883 55286 : trunc_var(result, rscale);
9884 :
9885 : /* Strip leading/trailing zeroes */
9886 221912 : strip_var(result);
9887 : }
9888 :
9889 :
9890 : #ifdef HAVE_INT128
9891 : /*
9892 : * div_var_int64() -
9893 : *
9894 : * Divide a numeric variable by a 64-bit integer with the specified weight.
9895 : * The quotient var / (ival * NBASE^ival_weight) is stored in result.
9896 : *
9897 : * This duplicates the logic in div_var_int(), so any changes made there
9898 : * should be made here too.
9899 : */
9900 : static void
9901 546 : div_var_int64(const NumericVar *var, int64 ival, int ival_weight,
9902 : NumericVar *result, int rscale, bool round)
9903 : {
9904 546 : NumericDigit *var_digits = var->digits;
9905 546 : int var_ndigits = var->ndigits;
9906 : int res_sign;
9907 : int res_weight;
9908 : int res_ndigits;
9909 : NumericDigit *res_buf;
9910 : NumericDigit *res_digits;
9911 : uint64 divisor;
9912 : int i;
9913 :
9914 : /* Guard against division by zero */
9915 546 : if (ival == 0)
9916 0 : ereport(ERROR,
9917 : errcode(ERRCODE_DIVISION_BY_ZERO),
9918 : errmsg("division by zero"));
9919 :
9920 : /* Result zero check */
9921 546 : if (var_ndigits == 0)
9922 : {
9923 96 : zero_var(result);
9924 96 : result->dscale = rscale;
9925 96 : return;
9926 : }
9927 :
9928 : /*
9929 : * Determine the result sign, weight and number of digits to calculate.
9930 : * The weight figured here is correct if the emitted quotient has no
9931 : * leading zero digits; otherwise strip_var() will fix things up.
9932 : */
9933 450 : if (var->sign == NUMERIC_POS)
9934 276 : res_sign = ival > 0 ? NUMERIC_POS : NUMERIC_NEG;
9935 : else
9936 174 : res_sign = ival > 0 ? NUMERIC_NEG : NUMERIC_POS;
9937 450 : res_weight = var->weight - ival_weight;
9938 : /* The number of accurate result digits we need to produce: */
9939 450 : res_ndigits = res_weight + 1 + (rscale + DEC_DIGITS - 1) / DEC_DIGITS;
9940 : /* ... but always at least 1 */
9941 450 : res_ndigits = Max(res_ndigits, 1);
9942 : /* If rounding needed, figure one more digit to ensure correct result */
9943 450 : if (round)
9944 444 : res_ndigits++;
9945 :
9946 450 : res_buf = digitbuf_alloc(res_ndigits + 1);
9947 450 : res_buf[0] = 0; /* spare digit for later rounding */
9948 450 : res_digits = res_buf + 1;
9949 :
9950 : /*
9951 : * Now compute the quotient digits. This is the short division algorithm
9952 : * described in Knuth volume 2, section 4.3.1 exercise 16, except that we
9953 : * allow the divisor to exceed the internal base.
9954 : *
9955 : * In this algorithm, the carry from one digit to the next is at most
9956 : * divisor - 1. Therefore, while processing the next digit, carry may
9957 : * become as large as divisor * NBASE - 1, and so it requires a 128-bit
9958 : * integer if this exceeds PG_UINT64_MAX.
9959 : */
9960 450 : divisor = i64abs(ival);
9961 :
9962 450 : if (divisor <= PG_UINT64_MAX / NBASE)
9963 : {
9964 : /* carry cannot overflow 64 bits */
9965 354 : uint64 carry = 0;
9966 :
9967 3608 : for (i = 0; i < res_ndigits; i++)
9968 : {
9969 3254 : carry = carry * NBASE + (i < var_ndigits ? var_digits[i] : 0);
9970 3254 : res_digits[i] = (NumericDigit) (carry / divisor);
9971 3254 : carry = carry % divisor;
9972 : }
9973 : }
9974 : else
9975 : {
9976 : /* carry may exceed 64 bits */
9977 96 : uint128 carry = 0;
9978 :
9979 1032 : for (i = 0; i < res_ndigits; i++)
9980 : {
9981 936 : carry = carry * NBASE + (i < var_ndigits ? var_digits[i] : 0);
9982 936 : res_digits[i] = (NumericDigit) (carry / divisor);
9983 936 : carry = carry % divisor;
9984 : }
9985 : }
9986 :
9987 : /* Store the quotient in result */
9988 450 : digitbuf_free(result->buf);
9989 450 : result->ndigits = res_ndigits;
9990 450 : result->buf = res_buf;
9991 450 : result->digits = res_digits;
9992 450 : result->weight = res_weight;
9993 450 : result->sign = res_sign;
9994 :
9995 : /* Round or truncate to target rscale (and set result->dscale) */
9996 450 : if (round)
9997 444 : round_var(result, rscale);
9998 : else
9999 6 : trunc_var(result, rscale);
10000 :
10001 : /* Strip leading/trailing zeroes */
10002 450 : strip_var(result);
10003 : }
10004 : #endif
10005 :
10006 :
10007 : /*
10008 : * Default scale selection for division
10009 : *
10010 : * Returns the appropriate result scale for the division result.
10011 : */
10012 : static int
10013 152632 : select_div_scale(const NumericVar *var1, const NumericVar *var2)
10014 : {
10015 : int weight1,
10016 : weight2,
10017 : qweight,
10018 : i;
10019 : NumericDigit firstdigit1,
10020 : firstdigit2;
10021 : int rscale;
10022 :
10023 : /*
10024 : * The result scale of a division isn't specified in any SQL standard. For
10025 : * PostgreSQL we select a result scale that will give at least
10026 : * NUMERIC_MIN_SIG_DIGITS significant digits, so that numeric gives a
10027 : * result no less accurate than float8; but use a scale not less than
10028 : * either input's display scale.
10029 : */
10030 :
10031 : /* Get the actual (normalized) weight and first digit of each input */
10032 :
10033 152632 : weight1 = 0; /* values to use if var1 is zero */
10034 152632 : firstdigit1 = 0;
10035 152632 : for (i = 0; i < var1->ndigits; i++)
10036 : {
10037 150932 : firstdigit1 = var1->digits[i];
10038 150932 : if (firstdigit1 != 0)
10039 : {
10040 150932 : weight1 = var1->weight - i;
10041 150932 : break;
10042 : }
10043 : }
10044 :
10045 152632 : weight2 = 0; /* values to use if var2 is zero */
10046 152632 : firstdigit2 = 0;
10047 152632 : for (i = 0; i < var2->ndigits; i++)
10048 : {
10049 152582 : firstdigit2 = var2->digits[i];
10050 152582 : if (firstdigit2 != 0)
10051 : {
10052 152582 : weight2 = var2->weight - i;
10053 152582 : break;
10054 : }
10055 : }
10056 :
10057 : /*
10058 : * Estimate weight of quotient. If the two first digits are equal, we
10059 : * can't be sure, but assume that var1 is less than var2.
10060 : */
10061 152632 : qweight = weight1 - weight2;
10062 152632 : if (firstdigit1 <= firstdigit2)
10063 135334 : qweight--;
10064 :
10065 : /* Select result scale */
10066 152632 : rscale = NUMERIC_MIN_SIG_DIGITS - qweight * DEC_DIGITS;
10067 152632 : rscale = Max(rscale, var1->dscale);
10068 152632 : rscale = Max(rscale, var2->dscale);
10069 152632 : rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
10070 152632 : rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
10071 :
10072 152632 : return rscale;
10073 : }
10074 :
10075 :
10076 : /*
10077 : * mod_var() -
10078 : *
10079 : * Calculate the modulo of two numerics at variable level
10080 : */
10081 : static void
10082 53792 : mod_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
10083 : {
10084 : NumericVar tmp;
10085 :
10086 53792 : init_var(&tmp);
10087 :
10088 : /* ---------
10089 : * We do this using the equation
10090 : * mod(x,y) = x - trunc(x/y)*y
10091 : * div_var can be persuaded to give us trunc(x/y) directly.
10092 : * ----------
10093 : */
10094 53792 : div_var(var1, var2, &tmp, 0, false, true);
10095 :
10096 53780 : mul_var(var2, &tmp, &tmp, var2->dscale);
10097 :
10098 53780 : sub_var(var1, &tmp, result);
10099 :
10100 53780 : free_var(&tmp);
10101 53780 : }
10102 :
10103 :
10104 : /*
10105 : * div_mod_var() -
10106 : *
10107 : * Calculate the truncated integer quotient and numeric remainder of two
10108 : * numeric variables. The remainder is precise to var2's dscale.
10109 : */
10110 : static void
10111 4518 : div_mod_var(const NumericVar *var1, const NumericVar *var2,
10112 : NumericVar *quot, NumericVar *rem)
10113 : {
10114 : NumericVar q;
10115 : NumericVar r;
10116 :
10117 4518 : init_var(&q);
10118 4518 : init_var(&r);
10119 :
10120 : /*
10121 : * Use div_var() with exact = false to get an initial estimate for the
10122 : * integer quotient (truncated towards zero). This might be slightly
10123 : * inaccurate, but we correct it below.
10124 : */
10125 4518 : div_var(var1, var2, &q, 0, false, false);
10126 :
10127 : /* Compute initial estimate of remainder using the quotient estimate. */
10128 4518 : mul_var(var2, &q, &r, var2->dscale);
10129 4518 : sub_var(var1, &r, &r);
10130 :
10131 : /*
10132 : * Adjust the results if necessary --- the remainder should have the same
10133 : * sign as var1, and its absolute value should be less than the absolute
10134 : * value of var2.
10135 : */
10136 4518 : while (r.ndigits != 0 && r.sign != var1->sign)
10137 : {
10138 : /* The absolute value of the quotient is too large */
10139 0 : if (var1->sign == var2->sign)
10140 : {
10141 0 : sub_var(&q, &const_one, &q);
10142 0 : add_var(&r, var2, &r);
10143 : }
10144 : else
10145 : {
10146 0 : add_var(&q, &const_one, &q);
10147 0 : sub_var(&r, var2, &r);
10148 : }
10149 : }
10150 :
10151 4518 : while (cmp_abs(&r, var2) >= 0)
10152 : {
10153 : /* The absolute value of the quotient is too small */
10154 0 : if (var1->sign == var2->sign)
10155 : {
10156 0 : add_var(&q, &const_one, &q);
10157 0 : sub_var(&r, var2, &r);
10158 : }
10159 : else
10160 : {
10161 0 : sub_var(&q, &const_one, &q);
10162 0 : add_var(&r, var2, &r);
10163 : }
10164 : }
10165 :
10166 4518 : set_var_from_var(&q, quot);
10167 4518 : set_var_from_var(&r, rem);
10168 :
10169 4518 : free_var(&q);
10170 4518 : free_var(&r);
10171 4518 : }
10172 :
10173 :
10174 : /*
10175 : * ceil_var() -
10176 : *
10177 : * Return the smallest integer greater than or equal to the argument
10178 : * on variable level
10179 : */
10180 : static void
10181 204 : ceil_var(const NumericVar *var, NumericVar *result)
10182 : {
10183 : NumericVar tmp;
10184 :
10185 204 : init_var(&tmp);
10186 204 : set_var_from_var(var, &tmp);
10187 :
10188 204 : trunc_var(&tmp, 0);
10189 :
10190 204 : if (var->sign == NUMERIC_POS && cmp_var(var, &tmp) != 0)
10191 60 : add_var(&tmp, &const_one, &tmp);
10192 :
10193 204 : set_var_from_var(&tmp, result);
10194 204 : free_var(&tmp);
10195 204 : }
10196 :
10197 :
10198 : /*
10199 : * floor_var() -
10200 : *
10201 : * Return the largest integer equal to or less than the argument
10202 : * on variable level
10203 : */
10204 : static void
10205 108 : floor_var(const NumericVar *var, NumericVar *result)
10206 : {
10207 : NumericVar tmp;
10208 :
10209 108 : init_var(&tmp);
10210 108 : set_var_from_var(var, &tmp);
10211 :
10212 108 : trunc_var(&tmp, 0);
10213 :
10214 108 : if (var->sign == NUMERIC_NEG && cmp_var(var, &tmp) != 0)
10215 30 : sub_var(&tmp, &const_one, &tmp);
10216 :
10217 108 : set_var_from_var(&tmp, result);
10218 108 : free_var(&tmp);
10219 108 : }
10220 :
10221 :
10222 : /*
10223 : * gcd_var() -
10224 : *
10225 : * Calculate the greatest common divisor of two numerics at variable level
10226 : */
10227 : static void
10228 222 : gcd_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
10229 : {
10230 : int res_dscale;
10231 : int cmp;
10232 : NumericVar tmp_arg;
10233 : NumericVar mod;
10234 :
10235 222 : res_dscale = Max(var1->dscale, var2->dscale);
10236 :
10237 : /*
10238 : * Arrange for var1 to be the number with the greater absolute value.
10239 : *
10240 : * This would happen automatically in the loop below, but avoids an
10241 : * expensive modulo operation.
10242 : */
10243 222 : cmp = cmp_abs(var1, var2);
10244 222 : if (cmp < 0)
10245 : {
10246 84 : const NumericVar *tmp = var1;
10247 :
10248 84 : var1 = var2;
10249 84 : var2 = tmp;
10250 : }
10251 :
10252 : /*
10253 : * Also avoid the taking the modulo if the inputs have the same absolute
10254 : * value, or if the smaller input is zero.
10255 : */
10256 222 : if (cmp == 0 || var2->ndigits == 0)
10257 : {
10258 72 : set_var_from_var(var1, result);
10259 72 : result->sign = NUMERIC_POS;
10260 72 : result->dscale = res_dscale;
10261 72 : return;
10262 : }
10263 :
10264 150 : init_var(&tmp_arg);
10265 150 : init_var(&mod);
10266 :
10267 : /* Use the Euclidean algorithm to find the GCD */
10268 150 : set_var_from_var(var1, &tmp_arg);
10269 150 : set_var_from_var(var2, result);
10270 :
10271 : for (;;)
10272 : {
10273 : /* this loop can take a while, so allow it to be interrupted */
10274 588 : CHECK_FOR_INTERRUPTS();
10275 :
10276 588 : mod_var(&tmp_arg, result, &mod);
10277 588 : if (mod.ndigits == 0)
10278 150 : break;
10279 438 : set_var_from_var(result, &tmp_arg);
10280 438 : set_var_from_var(&mod, result);
10281 : }
10282 150 : result->sign = NUMERIC_POS;
10283 150 : result->dscale = res_dscale;
10284 :
10285 150 : free_var(&tmp_arg);
10286 150 : free_var(&mod);
10287 : }
10288 :
10289 :
10290 : /*
10291 : * sqrt_var() -
10292 : *
10293 : * Compute the square root of x using the Karatsuba Square Root algorithm.
10294 : * NOTE: we allow rscale < 0 here, implying rounding before the decimal
10295 : * point.
10296 : */
10297 : static void
10298 4194 : sqrt_var(const NumericVar *arg, NumericVar *result, int rscale)
10299 : {
10300 : int stat;
10301 : int res_weight;
10302 : int res_ndigits;
10303 : int src_ndigits;
10304 : int step;
10305 : int ndigits[32];
10306 : int blen;
10307 : int64 arg_int64;
10308 : int src_idx;
10309 : int64 s_int64;
10310 : int64 r_int64;
10311 : NumericVar s_var;
10312 : NumericVar r_var;
10313 : NumericVar a0_var;
10314 : NumericVar a1_var;
10315 : NumericVar q_var;
10316 : NumericVar u_var;
10317 :
10318 4194 : stat = cmp_var(arg, &const_zero);
10319 4194 : if (stat == 0)
10320 : {
10321 18 : zero_var(result);
10322 18 : result->dscale = rscale;
10323 18 : return;
10324 : }
10325 :
10326 : /*
10327 : * SQL2003 defines sqrt() in terms of power, so we need to emit the right
10328 : * SQLSTATE error code if the operand is negative.
10329 : */
10330 4176 : if (stat < 0)
10331 6 : ereport(ERROR,
10332 : (errcode(ERRCODE_INVALID_ARGUMENT_FOR_POWER_FUNCTION),
10333 : errmsg("cannot take square root of a negative number")));
10334 :
10335 4170 : init_var(&s_var);
10336 4170 : init_var(&r_var);
10337 4170 : init_var(&a0_var);
10338 4170 : init_var(&a1_var);
10339 4170 : init_var(&q_var);
10340 4170 : init_var(&u_var);
10341 :
10342 : /*
10343 : * The result weight is half the input weight, rounded towards minus
10344 : * infinity --- res_weight = floor(arg->weight / 2).
10345 : */
10346 4170 : if (arg->weight >= 0)
10347 3858 : res_weight = arg->weight / 2;
10348 : else
10349 312 : res_weight = -((-arg->weight - 1) / 2 + 1);
10350 :
10351 : /*
10352 : * Number of NBASE digits to compute. To ensure correct rounding, compute
10353 : * at least 1 extra decimal digit. We explicitly allow rscale to be
10354 : * negative here, but must always compute at least 1 NBASE digit. Thus
10355 : * res_ndigits = res_weight + 1 + ceil((rscale + 1) / DEC_DIGITS) or 1.
10356 : */
10357 4170 : if (rscale + 1 >= 0)
10358 4170 : res_ndigits = res_weight + 1 + (rscale + DEC_DIGITS) / DEC_DIGITS;
10359 : else
10360 0 : res_ndigits = res_weight + 1 - (-rscale - 1) / DEC_DIGITS;
10361 4170 : res_ndigits = Max(res_ndigits, 1);
10362 :
10363 : /*
10364 : * Number of source NBASE digits logically required to produce a result
10365 : * with this precision --- every digit before the decimal point, plus 2
10366 : * for each result digit after the decimal point (or minus 2 for each
10367 : * result digit we round before the decimal point).
10368 : */
10369 4170 : src_ndigits = arg->weight + 1 + (res_ndigits - res_weight - 1) * 2;
10370 4170 : src_ndigits = Max(src_ndigits, 1);
10371 :
10372 : /* ----------
10373 : * From this point on, we treat the input and the result as integers and
10374 : * compute the integer square root and remainder using the Karatsuba
10375 : * Square Root algorithm, which may be written recursively as follows:
10376 : *
10377 : * SqrtRem(n = a3*b^3 + a2*b^2 + a1*b + a0):
10378 : * [ for some base b, and coefficients a0,a1,a2,a3 chosen so that
10379 : * 0 <= a0,a1,a2 < b and a3 >= b/4 ]
10380 : * Let (s,r) = SqrtRem(a3*b + a2)
10381 : * Let (q,u) = DivRem(r*b + a1, 2*s)
10382 : * Let s = s*b + q
10383 : * Let r = u*b + a0 - q^2
10384 : * If r < 0 Then
10385 : * Let r = r + s
10386 : * Let s = s - 1
10387 : * Let r = r + s
10388 : * Return (s,r)
10389 : *
10390 : * See "Karatsuba Square Root", Paul Zimmermann, INRIA Research Report
10391 : * RR-3805, November 1999. At the time of writing this was available
10392 : * on the net at <https://hal.inria.fr/inria-00072854>.
10393 : *
10394 : * The way to read the assumption "n = a3*b^3 + a2*b^2 + a1*b + a0" is
10395 : * "choose a base b such that n requires at least four base-b digits to
10396 : * express; then those digits are a3,a2,a1,a0, with a3 possibly larger
10397 : * than b". For optimal performance, b should have approximately a
10398 : * quarter the number of digits in the input, so that the outer square
10399 : * root computes roughly twice as many digits as the inner one. For
10400 : * simplicity, we choose b = NBASE^blen, an integer power of NBASE.
10401 : *
10402 : * We implement the algorithm iteratively rather than recursively, to
10403 : * allow the working variables to be reused. With this approach, each
10404 : * digit of the input is read precisely once --- src_idx tracks the number
10405 : * of input digits used so far.
10406 : *
10407 : * The array ndigits[] holds the number of NBASE digits of the input that
10408 : * will have been used at the end of each iteration, which roughly doubles
10409 : * each time. Note that the array elements are stored in reverse order,
10410 : * so if the final iteration requires src_ndigits = 37 input digits, the
10411 : * array will contain [37,19,11,7,5,3], and we would start by computing
10412 : * the square root of the 3 most significant NBASE digits.
10413 : *
10414 : * In each iteration, we choose blen to be the largest integer for which
10415 : * the input number has a3 >= b/4, when written in the form above. In
10416 : * general, this means blen = src_ndigits / 4 (truncated), but if
10417 : * src_ndigits is a multiple of 4, that might lead to the coefficient a3
10418 : * being less than b/4 (if the first input digit is less than NBASE/4), in
10419 : * which case we choose blen = src_ndigits / 4 - 1. The number of digits
10420 : * in the inner square root is then src_ndigits - 2*blen. So, for
10421 : * example, if we have src_ndigits = 26 initially, the array ndigits[]
10422 : * will be either [26,14,8,4] or [26,14,8,6,4], depending on the size of
10423 : * the first input digit.
10424 : *
10425 : * Additionally, we can put an upper bound on the number of steps required
10426 : * as follows --- suppose that the number of source digits is an n-bit
10427 : * number in the range [2^(n-1), 2^n-1], then blen will be in the range
10428 : * [2^(n-3)-1, 2^(n-2)-1] and the number of digits in the inner square
10429 : * root will be in the range [2^(n-2), 2^(n-1)+1]. In the next step, blen
10430 : * will be in the range [2^(n-4)-1, 2^(n-3)] and the number of digits in
10431 : * the next inner square root will be in the range [2^(n-3), 2^(n-2)+1].
10432 : * This pattern repeats, and in the worst case the array ndigits[] will
10433 : * contain [2^n-1, 2^(n-1)+1, 2^(n-2)+1, ... 9, 5, 3], and the computation
10434 : * will require n steps. Therefore, since all digit array sizes are
10435 : * signed 32-bit integers, the number of steps required is guaranteed to
10436 : * be less than 32.
10437 : * ----------
10438 : */
10439 4170 : step = 0;
10440 19962 : while ((ndigits[step] = src_ndigits) > 4)
10441 : {
10442 : /* Choose b so that a3 >= b/4, as described above */
10443 15792 : blen = src_ndigits / 4;
10444 15792 : if (blen * 4 == src_ndigits && arg->digits[0] < NBASE / 4)
10445 324 : blen--;
10446 :
10447 : /* Number of digits in the next step (inner square root) */
10448 15792 : src_ndigits -= 2 * blen;
10449 15792 : step++;
10450 : }
10451 :
10452 : /*
10453 : * First iteration (innermost square root and remainder):
10454 : *
10455 : * Here src_ndigits <= 4, and the input fits in an int64. Its square root
10456 : * has at most 9 decimal digits, so estimate it using double precision
10457 : * arithmetic, which will in fact almost certainly return the correct
10458 : * result with no further correction required.
10459 : */
10460 4170 : arg_int64 = arg->digits[0];
10461 13314 : for (src_idx = 1; src_idx < src_ndigits; src_idx++)
10462 : {
10463 9144 : arg_int64 *= NBASE;
10464 9144 : if (src_idx < arg->ndigits)
10465 7686 : arg_int64 += arg->digits[src_idx];
10466 : }
10467 :
10468 4170 : s_int64 = (int64) sqrt((double) arg_int64);
10469 4170 : r_int64 = arg_int64 - s_int64 * s_int64;
10470 :
10471 : /*
10472 : * Use Newton's method to correct the result, if necessary.
10473 : *
10474 : * This uses integer division with truncation to compute the truncated
10475 : * integer square root by iterating using the formula x -> (x + n/x) / 2.
10476 : * This is known to converge to isqrt(n), unless n+1 is a perfect square.
10477 : * If n+1 is a perfect square, the sequence will oscillate between the two
10478 : * values isqrt(n) and isqrt(n)+1, so we can be assured of convergence by
10479 : * checking the remainder.
10480 : */
10481 4170 : while (r_int64 < 0 || r_int64 > 2 * s_int64)
10482 : {
10483 0 : s_int64 = (s_int64 + arg_int64 / s_int64) / 2;
10484 0 : r_int64 = arg_int64 - s_int64 * s_int64;
10485 : }
10486 :
10487 : /*
10488 : * Iterations with src_ndigits <= 8:
10489 : *
10490 : * The next 1 or 2 iterations compute larger (outer) square roots with
10491 : * src_ndigits <= 8, so the result still fits in an int64 (even though the
10492 : * input no longer does) and we can continue to compute using int64
10493 : * variables to avoid more expensive numeric computations.
10494 : *
10495 : * It is fairly easy to see that there is no risk of the intermediate
10496 : * values below overflowing 64-bit integers. In the worst case, the
10497 : * previous iteration will have computed a 3-digit square root (of a
10498 : * 6-digit input less than NBASE^6 / 4), so at the start of this
10499 : * iteration, s will be less than NBASE^3 / 2 = 10^12 / 2, and r will be
10500 : * less than 10^12. In this case, blen will be 1, so numer will be less
10501 : * than 10^17, and denom will be less than 10^12 (and hence u will also be
10502 : * less than 10^12). Finally, since q^2 = u*b + a0 - r, we can also be
10503 : * sure that q^2 < 10^17. Therefore all these quantities fit comfortably
10504 : * in 64-bit integers.
10505 : */
10506 4170 : step--;
10507 10566 : while (step >= 0 && (src_ndigits = ndigits[step]) <= 8)
10508 : {
10509 : int b;
10510 : int a0;
10511 : int a1;
10512 : int i;
10513 : int64 numer;
10514 : int64 denom;
10515 : int64 q;
10516 : int64 u;
10517 :
10518 6396 : blen = (src_ndigits - src_idx) / 2;
10519 :
10520 : /* Extract a1 and a0, and compute b */
10521 6396 : a0 = 0;
10522 6396 : a1 = 0;
10523 6396 : b = 1;
10524 :
10525 12936 : for (i = 0; i < blen; i++, src_idx++)
10526 : {
10527 6540 : b *= NBASE;
10528 6540 : a1 *= NBASE;
10529 6540 : if (src_idx < arg->ndigits)
10530 4800 : a1 += arg->digits[src_idx];
10531 : }
10532 :
10533 12936 : for (i = 0; i < blen; i++, src_idx++)
10534 : {
10535 6540 : a0 *= NBASE;
10536 6540 : if (src_idx < arg->ndigits)
10537 4644 : a0 += arg->digits[src_idx];
10538 : }
10539 :
10540 : /* Compute (q,u) = DivRem(r*b + a1, 2*s) */
10541 6396 : numer = r_int64 * b + a1;
10542 6396 : denom = 2 * s_int64;
10543 6396 : q = numer / denom;
10544 6396 : u = numer - q * denom;
10545 :
10546 : /* Compute s = s*b + q and r = u*b + a0 - q^2 */
10547 6396 : s_int64 = s_int64 * b + q;
10548 6396 : r_int64 = u * b + a0 - q * q;
10549 :
10550 6396 : if (r_int64 < 0)
10551 : {
10552 : /* s is too large by 1; set r += s, s--, r += s */
10553 210 : r_int64 += s_int64;
10554 210 : s_int64--;
10555 210 : r_int64 += s_int64;
10556 : }
10557 :
10558 : Assert(src_idx == src_ndigits); /* All input digits consumed */
10559 6396 : step--;
10560 : }
10561 :
10562 : /*
10563 : * On platforms with 128-bit integer support, we can further delay the
10564 : * need to use numeric variables.
10565 : */
10566 : #ifdef HAVE_INT128
10567 4170 : if (step >= 0)
10568 : {
10569 : int128 s_int128;
10570 : int128 r_int128;
10571 :
10572 4170 : s_int128 = s_int64;
10573 4170 : r_int128 = r_int64;
10574 :
10575 : /*
10576 : * Iterations with src_ndigits <= 16:
10577 : *
10578 : * The result fits in an int128 (even though the input doesn't) so we
10579 : * use int128 variables to avoid more expensive numeric computations.
10580 : */
10581 9048 : while (step >= 0 && (src_ndigits = ndigits[step]) <= 16)
10582 : {
10583 : int64 b;
10584 : int64 a0;
10585 : int64 a1;
10586 : int64 i;
10587 : int128 numer;
10588 : int128 denom;
10589 : int128 q;
10590 : int128 u;
10591 :
10592 4878 : blen = (src_ndigits - src_idx) / 2;
10593 :
10594 : /* Extract a1 and a0, and compute b */
10595 4878 : a0 = 0;
10596 4878 : a1 = 0;
10597 4878 : b = 1;
10598 :
10599 16080 : for (i = 0; i < blen; i++, src_idx++)
10600 : {
10601 11202 : b *= NBASE;
10602 11202 : a1 *= NBASE;
10603 11202 : if (src_idx < arg->ndigits)
10604 6606 : a1 += arg->digits[src_idx];
10605 : }
10606 :
10607 16080 : for (i = 0; i < blen; i++, src_idx++)
10608 : {
10609 11202 : a0 *= NBASE;
10610 11202 : if (src_idx < arg->ndigits)
10611 4470 : a0 += arg->digits[src_idx];
10612 : }
10613 :
10614 : /* Compute (q,u) = DivRem(r*b + a1, 2*s) */
10615 4878 : numer = r_int128 * b + a1;
10616 4878 : denom = 2 * s_int128;
10617 4878 : q = numer / denom;
10618 4878 : u = numer - q * denom;
10619 :
10620 : /* Compute s = s*b + q and r = u*b + a0 - q^2 */
10621 4878 : s_int128 = s_int128 * b + q;
10622 4878 : r_int128 = u * b + a0 - q * q;
10623 :
10624 4878 : if (r_int128 < 0)
10625 : {
10626 : /* s is too large by 1; set r += s, s--, r += s */
10627 192 : r_int128 += s_int128;
10628 192 : s_int128--;
10629 192 : r_int128 += s_int128;
10630 : }
10631 :
10632 : Assert(src_idx == src_ndigits); /* All input digits consumed */
10633 4878 : step--;
10634 : }
10635 :
10636 : /*
10637 : * All remaining iterations require numeric variables. Convert the
10638 : * integer values to NumericVar and continue. Note that in the final
10639 : * iteration we don't need the remainder, so we can save a few cycles
10640 : * there by not fully computing it.
10641 : */
10642 4170 : int128_to_numericvar(s_int128, &s_var);
10643 4170 : if (step >= 0)
10644 2724 : int128_to_numericvar(r_int128, &r_var);
10645 : }
10646 : else
10647 : {
10648 0 : int64_to_numericvar(s_int64, &s_var);
10649 : /* step < 0, so we certainly don't need r */
10650 : }
10651 : #else /* !HAVE_INT128 */
10652 : int64_to_numericvar(s_int64, &s_var);
10653 : if (step >= 0)
10654 : int64_to_numericvar(r_int64, &r_var);
10655 : #endif /* HAVE_INT128 */
10656 :
10657 : /*
10658 : * The remaining iterations with src_ndigits > 8 (or 16, if have int128)
10659 : * use numeric variables.
10660 : */
10661 8688 : while (step >= 0)
10662 : {
10663 : int tmp_len;
10664 :
10665 4518 : src_ndigits = ndigits[step];
10666 4518 : blen = (src_ndigits - src_idx) / 2;
10667 :
10668 : /* Extract a1 and a0 */
10669 4518 : if (src_idx < arg->ndigits)
10670 : {
10671 1512 : tmp_len = Min(blen, arg->ndigits - src_idx);
10672 1512 : alloc_var(&a1_var, tmp_len);
10673 1512 : memcpy(a1_var.digits, arg->digits + src_idx,
10674 : tmp_len * sizeof(NumericDigit));
10675 1512 : a1_var.weight = blen - 1;
10676 1512 : a1_var.sign = NUMERIC_POS;
10677 1512 : a1_var.dscale = 0;
10678 1512 : strip_var(&a1_var);
10679 : }
10680 : else
10681 : {
10682 3006 : zero_var(&a1_var);
10683 3006 : a1_var.dscale = 0;
10684 : }
10685 4518 : src_idx += blen;
10686 :
10687 4518 : if (src_idx < arg->ndigits)
10688 : {
10689 1512 : tmp_len = Min(blen, arg->ndigits - src_idx);
10690 1512 : alloc_var(&a0_var, tmp_len);
10691 1512 : memcpy(a0_var.digits, arg->digits + src_idx,
10692 : tmp_len * sizeof(NumericDigit));
10693 1512 : a0_var.weight = blen - 1;
10694 1512 : a0_var.sign = NUMERIC_POS;
10695 1512 : a0_var.dscale = 0;
10696 1512 : strip_var(&a0_var);
10697 : }
10698 : else
10699 : {
10700 3006 : zero_var(&a0_var);
10701 3006 : a0_var.dscale = 0;
10702 : }
10703 4518 : src_idx += blen;
10704 :
10705 : /* Compute (q,u) = DivRem(r*b + a1, 2*s) */
10706 4518 : set_var_from_var(&r_var, &q_var);
10707 4518 : q_var.weight += blen;
10708 4518 : add_var(&q_var, &a1_var, &q_var);
10709 4518 : add_var(&s_var, &s_var, &u_var);
10710 4518 : div_mod_var(&q_var, &u_var, &q_var, &u_var);
10711 :
10712 : /* Compute s = s*b + q */
10713 4518 : s_var.weight += blen;
10714 4518 : add_var(&s_var, &q_var, &s_var);
10715 :
10716 : /*
10717 : * Compute r = u*b + a0 - q^2.
10718 : *
10719 : * In the final iteration, we don't actually need r; we just need to
10720 : * know whether it is negative, so that we know whether to adjust s.
10721 : * So instead of the final subtraction we can just compare.
10722 : */
10723 4518 : u_var.weight += blen;
10724 4518 : add_var(&u_var, &a0_var, &u_var);
10725 4518 : mul_var(&q_var, &q_var, &q_var, 0);
10726 :
10727 4518 : if (step > 0)
10728 : {
10729 : /* Need r for later iterations */
10730 1794 : sub_var(&u_var, &q_var, &r_var);
10731 1794 : if (r_var.sign == NUMERIC_NEG)
10732 : {
10733 : /* s is too large by 1; set r += s, s--, r += s */
10734 120 : add_var(&r_var, &s_var, &r_var);
10735 120 : sub_var(&s_var, &const_one, &s_var);
10736 120 : add_var(&r_var, &s_var, &r_var);
10737 : }
10738 : }
10739 : else
10740 : {
10741 : /* Don't need r anymore, except to test if s is too large by 1 */
10742 2724 : if (cmp_var(&u_var, &q_var) < 0)
10743 36 : sub_var(&s_var, &const_one, &s_var);
10744 : }
10745 :
10746 : Assert(src_idx == src_ndigits); /* All input digits consumed */
10747 4518 : step--;
10748 : }
10749 :
10750 : /*
10751 : * Construct the final result, rounding it to the requested precision.
10752 : */
10753 4170 : set_var_from_var(&s_var, result);
10754 4170 : result->weight = res_weight;
10755 4170 : result->sign = NUMERIC_POS;
10756 :
10757 : /* Round to target rscale (and set result->dscale) */
10758 4170 : round_var(result, rscale);
10759 :
10760 : /* Strip leading and trailing zeroes */
10761 4170 : strip_var(result);
10762 :
10763 4170 : free_var(&s_var);
10764 4170 : free_var(&r_var);
10765 4170 : free_var(&a0_var);
10766 4170 : free_var(&a1_var);
10767 4170 : free_var(&q_var);
10768 4170 : free_var(&u_var);
10769 : }
10770 :
10771 :
10772 : /*
10773 : * exp_var() -
10774 : *
10775 : * Raise e to the power of x, computed to rscale fractional digits
10776 : */
10777 : static void
10778 180 : exp_var(const NumericVar *arg, NumericVar *result, int rscale)
10779 : {
10780 : NumericVar x;
10781 : NumericVar elem;
10782 : int ni;
10783 : double val;
10784 : int dweight;
10785 : int ndiv2;
10786 : int sig_digits;
10787 : int local_rscale;
10788 :
10789 180 : init_var(&x);
10790 180 : init_var(&elem);
10791 :
10792 180 : set_var_from_var(arg, &x);
10793 :
10794 : /*
10795 : * Estimate the dweight of the result using floating point arithmetic, so
10796 : * that we can choose an appropriate local rscale for the calculation.
10797 : */
10798 180 : val = numericvar_to_double_no_overflow(&x);
10799 :
10800 : /* Guard against overflow/underflow */
10801 : /* If you change this limit, see also power_var()'s limit */
10802 180 : if (fabs(val) >= NUMERIC_MAX_RESULT_SCALE * 3)
10803 : {
10804 6 : if (val > 0)
10805 0 : ereport(ERROR,
10806 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
10807 : errmsg("value overflows numeric format")));
10808 6 : zero_var(result);
10809 6 : result->dscale = rscale;
10810 6 : return;
10811 : }
10812 :
10813 : /* decimal weight = log10(e^x) = x * log10(e) */
10814 174 : dweight = (int) (val * 0.434294481903252);
10815 :
10816 : /*
10817 : * Reduce x to the range -0.01 <= x <= 0.01 (approximately) by dividing by
10818 : * 2^ndiv2, to improve the convergence rate of the Taylor series.
10819 : *
10820 : * Note that the overflow check above ensures that fabs(x) < 6000, which
10821 : * means that ndiv2 <= 20 here.
10822 : */
10823 174 : if (fabs(val) > 0.01)
10824 : {
10825 144 : ndiv2 = 1;
10826 144 : val /= 2;
10827 :
10828 1818 : while (fabs(val) > 0.01)
10829 : {
10830 1674 : ndiv2++;
10831 1674 : val /= 2;
10832 : }
10833 :
10834 144 : local_rscale = x.dscale + ndiv2;
10835 144 : div_var_int(&x, 1 << ndiv2, 0, &x, local_rscale, true);
10836 : }
10837 : else
10838 30 : ndiv2 = 0;
10839 :
10840 : /*
10841 : * Set the scale for the Taylor series expansion. The final result has
10842 : * (dweight + rscale + 1) significant digits. In addition, we have to
10843 : * raise the Taylor series result to the power 2^ndiv2, which introduces
10844 : * an error of up to around log10(2^ndiv2) digits, so work with this many
10845 : * extra digits of precision (plus a few more for good measure).
10846 : */
10847 174 : sig_digits = 1 + dweight + rscale + (int) (ndiv2 * 0.301029995663981);
10848 174 : sig_digits = Max(sig_digits, 0) + 8;
10849 :
10850 174 : local_rscale = sig_digits - 1;
10851 :
10852 : /*
10853 : * Use the Taylor series
10854 : *
10855 : * exp(x) = 1 + x + x^2/2! + x^3/3! + ...
10856 : *
10857 : * Given the limited range of x, this should converge reasonably quickly.
10858 : * We run the series until the terms fall below the local_rscale limit.
10859 : */
10860 174 : add_var(&const_one, &x, result);
10861 :
10862 174 : mul_var(&x, &x, &elem, local_rscale);
10863 174 : ni = 2;
10864 174 : div_var_int(&elem, ni, 0, &elem, local_rscale, true);
10865 :
10866 4992 : while (elem.ndigits != 0)
10867 : {
10868 4818 : add_var(result, &elem, result);
10869 :
10870 4818 : mul_var(&elem, &x, &elem, local_rscale);
10871 4818 : ni++;
10872 4818 : div_var_int(&elem, ni, 0, &elem, local_rscale, true);
10873 : }
10874 :
10875 : /*
10876 : * Compensate for the argument range reduction. Since the weight of the
10877 : * result doubles with each multiplication, we can reduce the local rscale
10878 : * as we proceed.
10879 : */
10880 1992 : while (ndiv2-- > 0)
10881 : {
10882 1818 : local_rscale = sig_digits - result->weight * 2 * DEC_DIGITS;
10883 1818 : local_rscale = Max(local_rscale, NUMERIC_MIN_DISPLAY_SCALE);
10884 1818 : mul_var(result, result, result, local_rscale);
10885 : }
10886 :
10887 : /* Round to requested rscale */
10888 174 : round_var(result, rscale);
10889 :
10890 174 : free_var(&x);
10891 174 : free_var(&elem);
10892 : }
10893 :
10894 :
10895 : /*
10896 : * Estimate the dweight of the most significant decimal digit of the natural
10897 : * logarithm of a number.
10898 : *
10899 : * Essentially, we're approximating log10(abs(ln(var))). This is used to
10900 : * determine the appropriate rscale when computing natural logarithms.
10901 : *
10902 : * Note: many callers call this before range-checking the input. Therefore,
10903 : * we must be robust against values that are invalid to apply ln() to.
10904 : * We don't wish to throw an error here, so just return zero in such cases.
10905 : */
10906 : static int
10907 738 : estimate_ln_dweight(const NumericVar *var)
10908 : {
10909 : int ln_dweight;
10910 :
10911 : /* Caller should fail on ln(negative), but for the moment return zero */
10912 738 : if (var->sign != NUMERIC_POS)
10913 42 : return 0;
10914 :
10915 1314 : if (cmp_var(var, &const_zero_point_nine) >= 0 &&
10916 618 : cmp_var(var, &const_one_point_one) <= 0)
10917 90 : {
10918 : /*
10919 : * 0.9 <= var <= 1.1
10920 : *
10921 : * ln(var) has a negative weight (possibly very large). To get a
10922 : * reasonably accurate result, estimate it using ln(1+x) ~= x.
10923 : */
10924 : NumericVar x;
10925 :
10926 90 : init_var(&x);
10927 90 : sub_var(var, &const_one, &x);
10928 :
10929 90 : if (x.ndigits > 0)
10930 : {
10931 : /* Use weight of most significant decimal digit of x */
10932 42 : ln_dweight = x.weight * DEC_DIGITS + (int) log10(x.digits[0]);
10933 : }
10934 : else
10935 : {
10936 : /* x = 0. Since ln(1) = 0 exactly, we don't need extra digits */
10937 48 : ln_dweight = 0;
10938 : }
10939 :
10940 90 : free_var(&x);
10941 : }
10942 : else
10943 : {
10944 : /*
10945 : * Estimate the logarithm using the first couple of digits from the
10946 : * input number. This will give an accurate result whenever the input
10947 : * is not too close to 1.
10948 : */
10949 606 : if (var->ndigits > 0)
10950 : {
10951 : int digits;
10952 : int dweight;
10953 : double ln_var;
10954 :
10955 564 : digits = var->digits[0];
10956 564 : dweight = var->weight * DEC_DIGITS;
10957 :
10958 564 : if (var->ndigits > 1)
10959 : {
10960 342 : digits = digits * NBASE + var->digits[1];
10961 342 : dweight -= DEC_DIGITS;
10962 : }
10963 :
10964 : /*----------
10965 : * We have var ~= digits * 10^dweight
10966 : * so ln(var) ~= ln(digits) + dweight * ln(10)
10967 : *----------
10968 : */
10969 564 : ln_var = log((double) digits) + dweight * 2.302585092994046;
10970 564 : ln_dweight = (int) log10(fabs(ln_var));
10971 : }
10972 : else
10973 : {
10974 : /* Caller should fail on ln(0), but for the moment return zero */
10975 42 : ln_dweight = 0;
10976 : }
10977 : }
10978 :
10979 696 : return ln_dweight;
10980 : }
10981 :
10982 :
10983 : /*
10984 : * ln_var() -
10985 : *
10986 : * Compute the natural log of x
10987 : */
10988 : static void
10989 834 : ln_var(const NumericVar *arg, NumericVar *result, int rscale)
10990 : {
10991 : NumericVar x;
10992 : NumericVar xx;
10993 : int ni;
10994 : NumericVar elem;
10995 : NumericVar fact;
10996 : int nsqrt;
10997 : int local_rscale;
10998 : int cmp;
10999 :
11000 834 : cmp = cmp_var(arg, &const_zero);
11001 834 : if (cmp == 0)
11002 42 : ereport(ERROR,
11003 : (errcode(ERRCODE_INVALID_ARGUMENT_FOR_LOG),
11004 : errmsg("cannot take logarithm of zero")));
11005 792 : else if (cmp < 0)
11006 36 : ereport(ERROR,
11007 : (errcode(ERRCODE_INVALID_ARGUMENT_FOR_LOG),
11008 : errmsg("cannot take logarithm of a negative number")));
11009 :
11010 756 : init_var(&x);
11011 756 : init_var(&xx);
11012 756 : init_var(&elem);
11013 756 : init_var(&fact);
11014 :
11015 756 : set_var_from_var(arg, &x);
11016 756 : set_var_from_var(&const_two, &fact);
11017 :
11018 : /*
11019 : * Reduce input into range 0.9 < x < 1.1 with repeated sqrt() operations.
11020 : *
11021 : * The final logarithm will have up to around rscale+6 significant digits.
11022 : * Each sqrt() will roughly halve the weight of x, so adjust the local
11023 : * rscale as we work so that we keep this many significant digits at each
11024 : * step (plus a few more for good measure).
11025 : *
11026 : * Note that we allow local_rscale < 0 during this input reduction
11027 : * process, which implies rounding before the decimal point. sqrt_var()
11028 : * explicitly supports this, and it significantly reduces the work
11029 : * required to reduce very large inputs to the required range. Once the
11030 : * input reduction is complete, x.weight will be 0 and its display scale
11031 : * will be non-negative again.
11032 : */
11033 756 : nsqrt = 0;
11034 1068 : while (cmp_var(&x, &const_zero_point_nine) <= 0)
11035 : {
11036 312 : local_rscale = rscale - x.weight * DEC_DIGITS / 2 + 8;
11037 312 : sqrt_var(&x, &x, local_rscale);
11038 312 : mul_var(&fact, &const_two, &fact, 0);
11039 312 : nsqrt++;
11040 : }
11041 4128 : while (cmp_var(&x, &const_one_point_one) >= 0)
11042 : {
11043 3372 : local_rscale = rscale - x.weight * DEC_DIGITS / 2 + 8;
11044 3372 : sqrt_var(&x, &x, local_rscale);
11045 3372 : mul_var(&fact, &const_two, &fact, 0);
11046 3372 : nsqrt++;
11047 : }
11048 :
11049 : /*
11050 : * We use the Taylor series for 0.5 * ln((1+z)/(1-z)),
11051 : *
11052 : * z + z^3/3 + z^5/5 + ...
11053 : *
11054 : * where z = (x-1)/(x+1) is in the range (approximately) -0.053 .. 0.048
11055 : * due to the above range-reduction of x.
11056 : *
11057 : * The convergence of this is not as fast as one would like, but is
11058 : * tolerable given that z is small.
11059 : *
11060 : * The Taylor series result will be multiplied by 2^(nsqrt+1), which has a
11061 : * decimal weight of (nsqrt+1) * log10(2), so work with this many extra
11062 : * digits of precision (plus a few more for good measure).
11063 : */
11064 756 : local_rscale = rscale + (int) ((nsqrt + 1) * 0.301029995663981) + 8;
11065 :
11066 756 : sub_var(&x, &const_one, result);
11067 756 : add_var(&x, &const_one, &elem);
11068 756 : div_var(result, &elem, result, local_rscale, true, false);
11069 756 : set_var_from_var(result, &xx);
11070 756 : mul_var(result, result, &x, local_rscale);
11071 :
11072 756 : ni = 1;
11073 :
11074 : for (;;)
11075 : {
11076 14022 : ni += 2;
11077 14022 : mul_var(&xx, &x, &xx, local_rscale);
11078 14022 : div_var_int(&xx, ni, 0, &elem, local_rscale, true);
11079 :
11080 14022 : if (elem.ndigits == 0)
11081 756 : break;
11082 :
11083 13266 : add_var(result, &elem, result);
11084 :
11085 13266 : if (elem.weight < (result->weight - local_rscale * 2 / DEC_DIGITS))
11086 0 : break;
11087 : }
11088 :
11089 : /* Compensate for argument range reduction, round to requested rscale */
11090 756 : mul_var(result, &fact, result, rscale);
11091 :
11092 756 : free_var(&x);
11093 756 : free_var(&xx);
11094 756 : free_var(&elem);
11095 756 : free_var(&fact);
11096 756 : }
11097 :
11098 :
11099 : /*
11100 : * log_var() -
11101 : *
11102 : * Compute the logarithm of num in a given base.
11103 : *
11104 : * Note: this routine chooses dscale of the result.
11105 : */
11106 : static void
11107 216 : log_var(const NumericVar *base, const NumericVar *num, NumericVar *result)
11108 : {
11109 : NumericVar ln_base;
11110 : NumericVar ln_num;
11111 : int ln_base_dweight;
11112 : int ln_num_dweight;
11113 : int result_dweight;
11114 : int rscale;
11115 : int ln_base_rscale;
11116 : int ln_num_rscale;
11117 :
11118 216 : init_var(&ln_base);
11119 216 : init_var(&ln_num);
11120 :
11121 : /* Estimated dweights of ln(base), ln(num) and the final result */
11122 216 : ln_base_dweight = estimate_ln_dweight(base);
11123 216 : ln_num_dweight = estimate_ln_dweight(num);
11124 216 : result_dweight = ln_num_dweight - ln_base_dweight;
11125 :
11126 : /*
11127 : * Select the scale of the result so that it will have at least
11128 : * NUMERIC_MIN_SIG_DIGITS significant digits and is not less than either
11129 : * input's display scale.
11130 : */
11131 216 : rscale = NUMERIC_MIN_SIG_DIGITS - result_dweight;
11132 216 : rscale = Max(rscale, base->dscale);
11133 216 : rscale = Max(rscale, num->dscale);
11134 216 : rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
11135 216 : rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
11136 :
11137 : /*
11138 : * Set the scales for ln(base) and ln(num) so that they each have more
11139 : * significant digits than the final result.
11140 : */
11141 216 : ln_base_rscale = rscale + result_dweight - ln_base_dweight + 8;
11142 216 : ln_base_rscale = Max(ln_base_rscale, NUMERIC_MIN_DISPLAY_SCALE);
11143 :
11144 216 : ln_num_rscale = rscale + result_dweight - ln_num_dweight + 8;
11145 216 : ln_num_rscale = Max(ln_num_rscale, NUMERIC_MIN_DISPLAY_SCALE);
11146 :
11147 : /* Form natural logarithms */
11148 216 : ln_var(base, &ln_base, ln_base_rscale);
11149 192 : ln_var(num, &ln_num, ln_num_rscale);
11150 :
11151 : /* Divide and round to the required scale */
11152 162 : div_var(&ln_num, &ln_base, result, rscale, true, false);
11153 :
11154 156 : free_var(&ln_num);
11155 156 : free_var(&ln_base);
11156 156 : }
11157 :
11158 :
11159 : /*
11160 : * power_var() -
11161 : *
11162 : * Raise base to the power of exp
11163 : *
11164 : * Note: this routine chooses dscale of the result.
11165 : */
11166 : static void
11167 1398 : power_var(const NumericVar *base, const NumericVar *exp, NumericVar *result)
11168 : {
11169 : int res_sign;
11170 : NumericVar abs_base;
11171 : NumericVar ln_base;
11172 : NumericVar ln_num;
11173 : int ln_dweight;
11174 : int rscale;
11175 : int sig_digits;
11176 : int local_rscale;
11177 : double val;
11178 :
11179 : /* If exp can be represented as an integer, use power_var_int */
11180 1398 : if (exp->ndigits == 0 || exp->ndigits <= exp->weight + 1)
11181 : {
11182 : /* exact integer, but does it fit in int? */
11183 : int64 expval64;
11184 :
11185 1272 : if (numericvar_to_int64(exp, &expval64))
11186 : {
11187 1266 : if (expval64 >= PG_INT32_MIN && expval64 <= PG_INT32_MAX)
11188 : {
11189 : /* Okay, use power_var_int */
11190 1236 : power_var_int(base, (int) expval64, exp->dscale, result);
11191 1224 : return;
11192 : }
11193 : }
11194 : }
11195 :
11196 : /*
11197 : * This avoids log(0) for cases of 0 raised to a non-integer. 0 ^ 0 is
11198 : * handled by power_var_int().
11199 : */
11200 162 : if (cmp_var(base, &const_zero) == 0)
11201 : {
11202 18 : set_var_from_var(&const_zero, result);
11203 18 : result->dscale = NUMERIC_MIN_SIG_DIGITS; /* no need to round */
11204 18 : return;
11205 : }
11206 :
11207 144 : init_var(&abs_base);
11208 144 : init_var(&ln_base);
11209 144 : init_var(&ln_num);
11210 :
11211 : /*
11212 : * If base is negative, insist that exp be an integer. The result is then
11213 : * positive if exp is even and negative if exp is odd.
11214 : */
11215 144 : if (base->sign == NUMERIC_NEG)
11216 : {
11217 : /*
11218 : * Check that exp is an integer. This error code is defined by the
11219 : * SQL standard, and matches other errors in numeric_power().
11220 : */
11221 36 : if (exp->ndigits > 0 && exp->ndigits > exp->weight + 1)
11222 18 : ereport(ERROR,
11223 : (errcode(ERRCODE_INVALID_ARGUMENT_FOR_POWER_FUNCTION),
11224 : errmsg("a negative number raised to a non-integer power yields a complex result")));
11225 :
11226 : /* Test if exp is odd or even */
11227 18 : if (exp->ndigits > 0 && exp->ndigits == exp->weight + 1 &&
11228 12 : (exp->digits[exp->ndigits - 1] & 1))
11229 6 : res_sign = NUMERIC_NEG;
11230 : else
11231 12 : res_sign = NUMERIC_POS;
11232 :
11233 : /* Then work with abs(base) below */
11234 18 : set_var_from_var(base, &abs_base);
11235 18 : abs_base.sign = NUMERIC_POS;
11236 18 : base = &abs_base;
11237 : }
11238 : else
11239 108 : res_sign = NUMERIC_POS;
11240 :
11241 : /*----------
11242 : * Decide on the scale for the ln() calculation. For this we need an
11243 : * estimate of the weight of the result, which we obtain by doing an
11244 : * initial low-precision calculation of exp * ln(base).
11245 : *
11246 : * We want result = e ^ (exp * ln(base))
11247 : * so result dweight = log10(result) = exp * ln(base) * log10(e)
11248 : *
11249 : * We also perform a crude overflow test here so that we can exit early if
11250 : * the full-precision result is sure to overflow, and to guard against
11251 : * integer overflow when determining the scale for the real calculation.
11252 : * exp_var() supports inputs up to NUMERIC_MAX_RESULT_SCALE * 3, so the
11253 : * result will overflow if exp * ln(base) >= NUMERIC_MAX_RESULT_SCALE * 3.
11254 : * Since the values here are only approximations, we apply a small fuzz
11255 : * factor to this overflow test and let exp_var() determine the exact
11256 : * overflow threshold so that it is consistent for all inputs.
11257 : *----------
11258 : */
11259 126 : ln_dweight = estimate_ln_dweight(base);
11260 :
11261 : /*
11262 : * Set the scale for the low-precision calculation, computing ln(base) to
11263 : * around 8 significant digits. Note that ln_dweight may be as small as
11264 : * -NUMERIC_DSCALE_MAX, so the scale may exceed NUMERIC_MAX_DISPLAY_SCALE
11265 : * here.
11266 : */
11267 126 : local_rscale = 8 - ln_dweight;
11268 126 : local_rscale = Max(local_rscale, NUMERIC_MIN_DISPLAY_SCALE);
11269 :
11270 126 : ln_var(base, &ln_base, local_rscale);
11271 :
11272 126 : mul_var(&ln_base, exp, &ln_num, local_rscale);
11273 :
11274 126 : val = numericvar_to_double_no_overflow(&ln_num);
11275 :
11276 : /* initial overflow/underflow test with fuzz factor */
11277 126 : if (fabs(val) > NUMERIC_MAX_RESULT_SCALE * 3.01)
11278 : {
11279 6 : if (val > 0)
11280 0 : ereport(ERROR,
11281 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
11282 : errmsg("value overflows numeric format")));
11283 6 : zero_var(result);
11284 6 : result->dscale = NUMERIC_MAX_DISPLAY_SCALE;
11285 6 : return;
11286 : }
11287 :
11288 120 : val *= 0.434294481903252; /* approximate decimal result weight */
11289 :
11290 : /* choose the result scale */
11291 120 : rscale = NUMERIC_MIN_SIG_DIGITS - (int) val;
11292 120 : rscale = Max(rscale, base->dscale);
11293 120 : rscale = Max(rscale, exp->dscale);
11294 120 : rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
11295 120 : rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
11296 :
11297 : /* significant digits required in the result */
11298 120 : sig_digits = rscale + (int) val;
11299 120 : sig_digits = Max(sig_digits, 0);
11300 :
11301 : /* set the scale for the real exp * ln(base) calculation */
11302 120 : local_rscale = sig_digits - ln_dweight + 8;
11303 120 : local_rscale = Max(local_rscale, NUMERIC_MIN_DISPLAY_SCALE);
11304 :
11305 : /* and do the real calculation */
11306 :
11307 120 : ln_var(base, &ln_base, local_rscale);
11308 :
11309 120 : mul_var(&ln_base, exp, &ln_num, local_rscale);
11310 :
11311 120 : exp_var(&ln_num, result, rscale);
11312 :
11313 120 : if (res_sign == NUMERIC_NEG && result->ndigits > 0)
11314 6 : result->sign = NUMERIC_NEG;
11315 :
11316 120 : free_var(&ln_num);
11317 120 : free_var(&ln_base);
11318 120 : free_var(&abs_base);
11319 : }
11320 :
11321 : /*
11322 : * power_var_int() -
11323 : *
11324 : * Raise base to the power of exp, where exp is an integer.
11325 : *
11326 : * Note: this routine chooses dscale of the result.
11327 : */
11328 : static void
11329 1236 : power_var_int(const NumericVar *base, int exp, int exp_dscale,
11330 : NumericVar *result)
11331 : {
11332 : double f;
11333 : int p;
11334 : int i;
11335 : int rscale;
11336 : int sig_digits;
11337 : unsigned int mask;
11338 : bool neg;
11339 : NumericVar base_prod;
11340 : int local_rscale;
11341 :
11342 : /*
11343 : * Choose the result scale. For this we need an estimate of the decimal
11344 : * weight of the result, which we obtain by approximating using double
11345 : * precision arithmetic.
11346 : *
11347 : * We also perform crude overflow/underflow tests here so that we can exit
11348 : * early if the result is sure to overflow/underflow, and to guard against
11349 : * integer overflow when choosing the result scale.
11350 : */
11351 1236 : if (base->ndigits != 0)
11352 : {
11353 : /*----------
11354 : * Choose f (double) and p (int) such that base ~= f * 10^p.
11355 : * Then log10(result) = log10(base^exp) ~= exp * (log10(f) + p).
11356 : *----------
11357 : */
11358 1206 : f = base->digits[0];
11359 1206 : p = base->weight * DEC_DIGITS;
11360 :
11361 1290 : for (i = 1; i < base->ndigits && i * DEC_DIGITS < 16; i++)
11362 : {
11363 84 : f = f * NBASE + base->digits[i];
11364 84 : p -= DEC_DIGITS;
11365 : }
11366 :
11367 1206 : f = exp * (log10(f) + p); /* approximate decimal result weight */
11368 : }
11369 : else
11370 30 : f = 0; /* result is 0 or 1 (weight 0), or error */
11371 :
11372 : /* overflow/underflow tests with fuzz factors */
11373 1236 : if (f > (NUMERIC_WEIGHT_MAX + 1) * DEC_DIGITS)
11374 12 : ereport(ERROR,
11375 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
11376 : errmsg("value overflows numeric format")));
11377 1224 : if (f + 1 < -NUMERIC_MAX_DISPLAY_SCALE)
11378 : {
11379 12 : zero_var(result);
11380 12 : result->dscale = NUMERIC_MAX_DISPLAY_SCALE;
11381 216 : return;
11382 : }
11383 :
11384 : /*
11385 : * Choose the result scale in the same way as power_var(), so it has at
11386 : * least NUMERIC_MIN_SIG_DIGITS significant digits and is not less than
11387 : * either input's display scale.
11388 : */
11389 1212 : rscale = NUMERIC_MIN_SIG_DIGITS - (int) f;
11390 1212 : rscale = Max(rscale, base->dscale);
11391 1212 : rscale = Max(rscale, exp_dscale);
11392 1212 : rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
11393 1212 : rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
11394 :
11395 : /* Handle some common special cases, as well as corner cases */
11396 1212 : switch (exp)
11397 : {
11398 72 : case 0:
11399 :
11400 : /*
11401 : * While 0 ^ 0 can be either 1 or indeterminate (error), we treat
11402 : * it as 1 because most programming languages do this. SQL:2003
11403 : * also requires a return value of 1.
11404 : * https://en.wikipedia.org/wiki/Exponentiation#Zero_to_the_zero_power
11405 : */
11406 72 : set_var_from_var(&const_one, result);
11407 72 : result->dscale = rscale; /* no need to round */
11408 72 : return;
11409 48 : case 1:
11410 48 : set_var_from_var(base, result);
11411 48 : round_var(result, rscale);
11412 48 : return;
11413 30 : case -1:
11414 30 : div_var(&const_one, base, result, rscale, true, true);
11415 30 : return;
11416 54 : case 2:
11417 54 : mul_var(base, base, result, rscale);
11418 54 : return;
11419 1008 : default:
11420 1008 : break;
11421 : }
11422 :
11423 : /* Handle the special case where the base is zero */
11424 1008 : if (base->ndigits == 0)
11425 : {
11426 0 : if (exp < 0)
11427 0 : ereport(ERROR,
11428 : (errcode(ERRCODE_DIVISION_BY_ZERO),
11429 : errmsg("division by zero")));
11430 0 : zero_var(result);
11431 0 : result->dscale = rscale;
11432 0 : return;
11433 : }
11434 :
11435 : /*
11436 : * The general case repeatedly multiplies base according to the bit
11437 : * pattern of exp.
11438 : *
11439 : * The local rscale used for each multiplication is varied to keep a fixed
11440 : * number of significant digits, sufficient to give the required result
11441 : * scale.
11442 : */
11443 :
11444 : /*
11445 : * Approximate number of significant digits in the result. Note that the
11446 : * underflow test above, together with the choice of rscale, ensures that
11447 : * this approximation is necessarily > 0.
11448 : */
11449 1008 : sig_digits = 1 + rscale + (int) f;
11450 :
11451 : /*
11452 : * The multiplications to produce the result may introduce an error of up
11453 : * to around log10(abs(exp)) digits, so work with this many extra digits
11454 : * of precision (plus a few more for good measure).
11455 : */
11456 1008 : sig_digits += (int) log(fabs((double) exp)) + 8;
11457 :
11458 : /*
11459 : * Now we can proceed with the multiplications.
11460 : */
11461 1008 : neg = (exp < 0);
11462 1008 : mask = pg_abs_s32(exp);
11463 :
11464 1008 : init_var(&base_prod);
11465 1008 : set_var_from_var(base, &base_prod);
11466 :
11467 1008 : if (mask & 1)
11468 498 : set_var_from_var(base, result);
11469 : else
11470 510 : set_var_from_var(&const_one, result);
11471 :
11472 5076 : while ((mask >>= 1) > 0)
11473 : {
11474 : /*
11475 : * Do the multiplications using rscales large enough to hold the
11476 : * results to the required number of significant digits, but don't
11477 : * waste time by exceeding the scales of the numbers themselves.
11478 : */
11479 4068 : local_rscale = sig_digits - 2 * base_prod.weight * DEC_DIGITS;
11480 4068 : local_rscale = Min(local_rscale, 2 * base_prod.dscale);
11481 4068 : local_rscale = Max(local_rscale, NUMERIC_MIN_DISPLAY_SCALE);
11482 :
11483 4068 : mul_var(&base_prod, &base_prod, &base_prod, local_rscale);
11484 :
11485 4068 : if (mask & 1)
11486 : {
11487 2658 : local_rscale = sig_digits -
11488 2658 : (base_prod.weight + result->weight) * DEC_DIGITS;
11489 2658 : local_rscale = Min(local_rscale,
11490 : base_prod.dscale + result->dscale);
11491 2658 : local_rscale = Max(local_rscale, NUMERIC_MIN_DISPLAY_SCALE);
11492 :
11493 2658 : mul_var(&base_prod, result, result, local_rscale);
11494 : }
11495 :
11496 : /*
11497 : * When abs(base) > 1, the number of digits to the left of the decimal
11498 : * point in base_prod doubles at each iteration, so if exp is large we
11499 : * could easily spend large amounts of time and memory space doing the
11500 : * multiplications. But once the weight exceeds what will fit in
11501 : * int16, the final result is guaranteed to overflow (or underflow, if
11502 : * exp < 0), so we can give up before wasting too many cycles.
11503 : */
11504 4068 : if (base_prod.weight > NUMERIC_WEIGHT_MAX ||
11505 4068 : result->weight > NUMERIC_WEIGHT_MAX)
11506 : {
11507 : /* overflow, unless neg, in which case result should be 0 */
11508 0 : if (!neg)
11509 0 : ereport(ERROR,
11510 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
11511 : errmsg("value overflows numeric format")));
11512 0 : zero_var(result);
11513 0 : neg = false;
11514 0 : break;
11515 : }
11516 : }
11517 :
11518 1008 : free_var(&base_prod);
11519 :
11520 : /* Compensate for input sign, and round to requested rscale */
11521 1008 : if (neg)
11522 486 : div_var(&const_one, result, result, rscale, true, false);
11523 : else
11524 522 : round_var(result, rscale);
11525 : }
11526 :
11527 : /*
11528 : * power_ten_int() -
11529 : *
11530 : * Raise ten to the power of exp, where exp is an integer. Note that unlike
11531 : * power_var_int(), this does no overflow/underflow checking or rounding.
11532 : */
11533 : static void
11534 228 : power_ten_int(int exp, NumericVar *result)
11535 : {
11536 : /* Construct the result directly, starting from 10^0 = 1 */
11537 228 : set_var_from_var(&const_one, result);
11538 :
11539 : /* Scale needed to represent the result exactly */
11540 228 : result->dscale = exp < 0 ? -exp : 0;
11541 :
11542 : /* Base-NBASE weight of result and remaining exponent */
11543 228 : if (exp >= 0)
11544 162 : result->weight = exp / DEC_DIGITS;
11545 : else
11546 66 : result->weight = (exp + 1) / DEC_DIGITS - 1;
11547 :
11548 228 : exp -= result->weight * DEC_DIGITS;
11549 :
11550 : /* Final adjustment of the result's single NBASE digit */
11551 594 : while (exp-- > 0)
11552 366 : result->digits[0] *= 10;
11553 228 : }
11554 :
11555 : /*
11556 : * random_var() - return a random value in the range [rmin, rmax].
11557 : */
11558 : static void
11559 33438 : random_var(pg_prng_state *state, const NumericVar *rmin,
11560 : const NumericVar *rmax, NumericVar *result)
11561 : {
11562 : int rscale;
11563 : NumericVar rlen;
11564 : int res_ndigits;
11565 : int n;
11566 : int pow10;
11567 : int i;
11568 : uint64 rlen64;
11569 : int rlen64_ndigits;
11570 :
11571 33438 : rscale = Max(rmin->dscale, rmax->dscale);
11572 :
11573 : /* Compute rlen = rmax - rmin and check the range bounds */
11574 33438 : init_var(&rlen);
11575 33438 : sub_var(rmax, rmin, &rlen);
11576 :
11577 33438 : if (rlen.sign == NUMERIC_NEG)
11578 6 : ereport(ERROR,
11579 : errcode(ERRCODE_INVALID_PARAMETER_VALUE),
11580 : errmsg("lower bound must be less than or equal to upper bound"));
11581 :
11582 : /* Special case for an empty range */
11583 33432 : if (rlen.ndigits == 0)
11584 : {
11585 12 : set_var_from_var(rmin, result);
11586 12 : result->dscale = rscale;
11587 12 : free_var(&rlen);
11588 12 : return;
11589 : }
11590 :
11591 : /*
11592 : * Otherwise, select a random value in the range [0, rlen = rmax - rmin],
11593 : * and shift it to the required range by adding rmin.
11594 : */
11595 :
11596 : /* Required result digits */
11597 33420 : res_ndigits = rlen.weight + 1 + (rscale + DEC_DIGITS - 1) / DEC_DIGITS;
11598 :
11599 : /*
11600 : * To get the required rscale, the final result digit must be a multiple
11601 : * of pow10 = 10^n, where n = (-rscale) mod DEC_DIGITS.
11602 : */
11603 33420 : n = ((rscale + DEC_DIGITS - 1) / DEC_DIGITS) * DEC_DIGITS - rscale;
11604 33420 : pow10 = 1;
11605 87900 : for (i = 0; i < n; i++)
11606 54480 : pow10 *= 10;
11607 :
11608 : /*
11609 : * To choose a random value uniformly from the range [0, rlen], we choose
11610 : * from the slightly larger range [0, rlen2], where rlen2 is formed from
11611 : * rlen by copying the first 4 NBASE digits, and setting all remaining
11612 : * decimal digits to "9".
11613 : *
11614 : * Without loss of generality, we can ignore the weight of rlen2 and treat
11615 : * it as a pure integer for the purposes of this discussion. The process
11616 : * above gives rlen2 + 1 = rlen64 * 10^N, for some integer N, where rlen64
11617 : * is a 64-bit integer formed from the first 4 NBASE digits copied from
11618 : * rlen. Since this trivially factors into smaller pieces that fit in
11619 : * 64-bit integers, the task of choosing a random value uniformly from the
11620 : * rlen2 + 1 possible values in [0, rlen2] is much simpler.
11621 : *
11622 : * If the random value selected is too large, it is rejected, and we try
11623 : * again until we get a result <= rlen, ensuring that the overall result
11624 : * is uniform (no particular value is any more likely than any other).
11625 : *
11626 : * Since rlen64 holds 4 NBASE digits from rlen, it contains at least
11627 : * DEC_DIGITS * 3 + 1 decimal digits (i.e., at least 13 decimal digits,
11628 : * when DEC_DIGITS is 4). Therefore the probability of needing to reject
11629 : * the value chosen and retry is less than 1e-13.
11630 : */
11631 33420 : rlen64 = (uint64) rlen.digits[0];
11632 33420 : rlen64_ndigits = 1;
11633 76212 : while (rlen64_ndigits < res_ndigits && rlen64_ndigits < 4)
11634 : {
11635 42792 : rlen64 *= NBASE;
11636 42792 : if (rlen64_ndigits < rlen.ndigits)
11637 6612 : rlen64 += rlen.digits[rlen64_ndigits];
11638 42792 : rlen64_ndigits++;
11639 : }
11640 :
11641 : /* Loop until we get a result <= rlen */
11642 : do
11643 : {
11644 : NumericDigit *res_digits;
11645 : uint64 rand;
11646 : int whole_ndigits;
11647 :
11648 33420 : alloc_var(result, res_ndigits);
11649 33420 : result->sign = NUMERIC_POS;
11650 33420 : result->weight = rlen.weight;
11651 33420 : result->dscale = rscale;
11652 33420 : res_digits = result->digits;
11653 :
11654 : /*
11655 : * Set the first rlen64_ndigits using a random value in [0, rlen64].
11656 : *
11657 : * If this is the whole result, and rscale is not a multiple of
11658 : * DEC_DIGITS (pow10 from above is not 1), then we need this to be a
11659 : * multiple of pow10.
11660 : */
11661 33420 : if (rlen64_ndigits == res_ndigits && pow10 != 1)
11662 21132 : rand = pg_prng_uint64_range(state, 0, rlen64 / pow10) * pow10;
11663 : else
11664 12288 : rand = pg_prng_uint64_range(state, 0, rlen64);
11665 :
11666 109632 : for (i = rlen64_ndigits - 1; i >= 0; i--)
11667 : {
11668 76212 : res_digits[i] = (NumericDigit) (rand % NBASE);
11669 76212 : rand = rand / NBASE;
11670 : }
11671 :
11672 : /*
11673 : * Set the remaining digits to random values in range [0, NBASE),
11674 : * noting that the last digit needs to be a multiple of pow10.
11675 : */
11676 33420 : whole_ndigits = res_ndigits;
11677 33420 : if (pow10 != 1)
11678 33210 : whole_ndigits--;
11679 :
11680 : /* Set whole digits in groups of 4 for best performance */
11681 33420 : i = rlen64_ndigits;
11682 33480 : while (i < whole_ndigits - 3)
11683 : {
11684 60 : rand = pg_prng_uint64_range(state, 0,
11685 : (uint64) NBASE * NBASE * NBASE * NBASE - 1);
11686 60 : res_digits[i++] = (NumericDigit) (rand % NBASE);
11687 60 : rand = rand / NBASE;
11688 60 : res_digits[i++] = (NumericDigit) (rand % NBASE);
11689 60 : rand = rand / NBASE;
11690 60 : res_digits[i++] = (NumericDigit) (rand % NBASE);
11691 60 : rand = rand / NBASE;
11692 60 : res_digits[i++] = (NumericDigit) rand;
11693 : }
11694 :
11695 : /* Remaining whole digits */
11696 33630 : while (i < whole_ndigits)
11697 : {
11698 210 : rand = pg_prng_uint64_range(state, 0, NBASE - 1);
11699 210 : res_digits[i++] = (NumericDigit) rand;
11700 : }
11701 :
11702 : /* Final partial digit (multiple of pow10) */
11703 33420 : if (i < res_ndigits)
11704 : {
11705 12078 : rand = pg_prng_uint64_range(state, 0, NBASE / pow10 - 1) * pow10;
11706 12078 : res_digits[i] = (NumericDigit) rand;
11707 : }
11708 :
11709 : /* Remove leading/trailing zeroes */
11710 33420 : strip_var(result);
11711 :
11712 : /* If result > rlen, try again */
11713 :
11714 33420 : } while (cmp_var(result, &rlen) > 0);
11715 :
11716 : /* Offset the result to the required range */
11717 33420 : add_var(result, rmin, result);
11718 :
11719 33420 : free_var(&rlen);
11720 : }
11721 :
11722 :
11723 : /* ----------------------------------------------------------------------
11724 : *
11725 : * Following are the lowest level functions that operate unsigned
11726 : * on the variable level
11727 : *
11728 : * ----------------------------------------------------------------------
11729 : */
11730 :
11731 :
11732 : /* ----------
11733 : * cmp_abs() -
11734 : *
11735 : * Compare the absolute values of var1 and var2
11736 : * Returns: -1 for ABS(var1) < ABS(var2)
11737 : * 0 for ABS(var1) == ABS(var2)
11738 : * 1 for ABS(var1) > ABS(var2)
11739 : * ----------
11740 : */
11741 : static int
11742 358344 : cmp_abs(const NumericVar *var1, const NumericVar *var2)
11743 : {
11744 716688 : return cmp_abs_common(var1->digits, var1->ndigits, var1->weight,
11745 358344 : var2->digits, var2->ndigits, var2->weight);
11746 : }
11747 :
11748 : /* ----------
11749 : * cmp_abs_common() -
11750 : *
11751 : * Main routine of cmp_abs(). This function can be used by both
11752 : * NumericVar and Numeric.
11753 : * ----------
11754 : */
11755 : static int
11756 6224118 : cmp_abs_common(const NumericDigit *var1digits, int var1ndigits, int var1weight,
11757 : const NumericDigit *var2digits, int var2ndigits, int var2weight)
11758 : {
11759 6224118 : int i1 = 0;
11760 6224118 : int i2 = 0;
11761 :
11762 : /* Check any digits before the first common digit */
11763 :
11764 6224118 : while (var1weight > var2weight && i1 < var1ndigits)
11765 : {
11766 29634 : if (var1digits[i1++] != 0)
11767 29634 : return 1;
11768 0 : var1weight--;
11769 : }
11770 6194484 : while (var2weight > var1weight && i2 < var2ndigits)
11771 : {
11772 31918 : if (var2digits[i2++] != 0)
11773 31918 : return -1;
11774 0 : var2weight--;
11775 : }
11776 :
11777 : /* At this point, either w1 == w2 or we've run out of digits */
11778 :
11779 6162566 : if (var1weight == var2weight)
11780 : {
11781 11592786 : while (i1 < var1ndigits && i2 < var2ndigits)
11782 : {
11783 7851716 : int stat = var1digits[i1++] - var2digits[i2++];
11784 :
11785 7851716 : if (stat)
11786 : {
11787 2415122 : if (stat > 0)
11788 1603194 : return 1;
11789 811928 : return -1;
11790 : }
11791 : }
11792 : }
11793 :
11794 : /*
11795 : * At this point, we've run out of digits on one side or the other; so any
11796 : * remaining nonzero digits imply that side is larger
11797 : */
11798 3747744 : while (i1 < var1ndigits)
11799 : {
11800 8258 : if (var1digits[i1++] != 0)
11801 7958 : return 1;
11802 : }
11803 3739666 : while (i2 < var2ndigits)
11804 : {
11805 1074 : if (var2digits[i2++] != 0)
11806 894 : return -1;
11807 : }
11808 :
11809 3738592 : return 0;
11810 : }
11811 :
11812 :
11813 : /*
11814 : * add_abs() -
11815 : *
11816 : * Add the absolute values of two variables into result.
11817 : * result might point to one of the operands without danger.
11818 : */
11819 : static void
11820 330546 : add_abs(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
11821 : {
11822 : NumericDigit *res_buf;
11823 : NumericDigit *res_digits;
11824 : int res_ndigits;
11825 : int res_weight;
11826 : int res_rscale,
11827 : rscale1,
11828 : rscale2;
11829 : int res_dscale;
11830 : int i,
11831 : i1,
11832 : i2;
11833 330546 : int carry = 0;
11834 :
11835 : /* copy these values into local vars for speed in inner loop */
11836 330546 : int var1ndigits = var1->ndigits;
11837 330546 : int var2ndigits = var2->ndigits;
11838 330546 : NumericDigit *var1digits = var1->digits;
11839 330546 : NumericDigit *var2digits = var2->digits;
11840 :
11841 330546 : res_weight = Max(var1->weight, var2->weight) + 1;
11842 :
11843 330546 : res_dscale = Max(var1->dscale, var2->dscale);
11844 :
11845 : /* Note: here we are figuring rscale in base-NBASE digits */
11846 330546 : rscale1 = var1->ndigits - var1->weight - 1;
11847 330546 : rscale2 = var2->ndigits - var2->weight - 1;
11848 330546 : res_rscale = Max(rscale1, rscale2);
11849 :
11850 330546 : res_ndigits = res_rscale + res_weight + 1;
11851 330546 : if (res_ndigits <= 0)
11852 0 : res_ndigits = 1;
11853 :
11854 330546 : res_buf = digitbuf_alloc(res_ndigits + 1);
11855 330546 : res_buf[0] = 0; /* spare digit for later rounding */
11856 330546 : res_digits = res_buf + 1;
11857 :
11858 330546 : i1 = res_rscale + var1->weight + 1;
11859 330546 : i2 = res_rscale + var2->weight + 1;
11860 3366702 : for (i = res_ndigits - 1; i >= 0; i--)
11861 : {
11862 3036156 : i1--;
11863 3036156 : i2--;
11864 3036156 : if (i1 >= 0 && i1 < var1ndigits)
11865 1369246 : carry += var1digits[i1];
11866 3036156 : if (i2 >= 0 && i2 < var2ndigits)
11867 1037704 : carry += var2digits[i2];
11868 :
11869 3036156 : if (carry >= NBASE)
11870 : {
11871 234292 : res_digits[i] = carry - NBASE;
11872 234292 : carry = 1;
11873 : }
11874 : else
11875 : {
11876 2801864 : res_digits[i] = carry;
11877 2801864 : carry = 0;
11878 : }
11879 : }
11880 :
11881 : Assert(carry == 0); /* else we failed to allow for carry out */
11882 :
11883 330546 : digitbuf_free(result->buf);
11884 330546 : result->ndigits = res_ndigits;
11885 330546 : result->buf = res_buf;
11886 330546 : result->digits = res_digits;
11887 330546 : result->weight = res_weight;
11888 330546 : result->dscale = res_dscale;
11889 :
11890 : /* Remove leading/trailing zeroes */
11891 330546 : strip_var(result);
11892 330546 : }
11893 :
11894 :
11895 : /*
11896 : * sub_abs()
11897 : *
11898 : * Subtract the absolute value of var2 from the absolute value of var1
11899 : * and store in result. result might point to one of the operands
11900 : * without danger.
11901 : *
11902 : * ABS(var1) MUST BE GREATER OR EQUAL ABS(var2) !!!
11903 : */
11904 : static void
11905 324100 : sub_abs(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
11906 : {
11907 : NumericDigit *res_buf;
11908 : NumericDigit *res_digits;
11909 : int res_ndigits;
11910 : int res_weight;
11911 : int res_rscale,
11912 : rscale1,
11913 : rscale2;
11914 : int res_dscale;
11915 : int i,
11916 : i1,
11917 : i2;
11918 324100 : int borrow = 0;
11919 :
11920 : /* copy these values into local vars for speed in inner loop */
11921 324100 : int var1ndigits = var1->ndigits;
11922 324100 : int var2ndigits = var2->ndigits;
11923 324100 : NumericDigit *var1digits = var1->digits;
11924 324100 : NumericDigit *var2digits = var2->digits;
11925 :
11926 324100 : res_weight = var1->weight;
11927 :
11928 324100 : res_dscale = Max(var1->dscale, var2->dscale);
11929 :
11930 : /* Note: here we are figuring rscale in base-NBASE digits */
11931 324100 : rscale1 = var1->ndigits - var1->weight - 1;
11932 324100 : rscale2 = var2->ndigits - var2->weight - 1;
11933 324100 : res_rscale = Max(rscale1, rscale2);
11934 :
11935 324100 : res_ndigits = res_rscale + res_weight + 1;
11936 324100 : if (res_ndigits <= 0)
11937 0 : res_ndigits = 1;
11938 :
11939 324100 : res_buf = digitbuf_alloc(res_ndigits + 1);
11940 324100 : res_buf[0] = 0; /* spare digit for later rounding */
11941 324100 : res_digits = res_buf + 1;
11942 :
11943 324100 : i1 = res_rscale + var1->weight + 1;
11944 324100 : i2 = res_rscale + var2->weight + 1;
11945 4846764 : for (i = res_ndigits - 1; i >= 0; i--)
11946 : {
11947 4522664 : i1--;
11948 4522664 : i2--;
11949 4522664 : if (i1 >= 0 && i1 < var1ndigits)
11950 4096550 : borrow += var1digits[i1];
11951 4522664 : if (i2 >= 0 && i2 < var2ndigits)
11952 3842368 : borrow -= var2digits[i2];
11953 :
11954 4522664 : if (borrow < 0)
11955 : {
11956 473990 : res_digits[i] = borrow + NBASE;
11957 473990 : borrow = -1;
11958 : }
11959 : else
11960 : {
11961 4048674 : res_digits[i] = borrow;
11962 4048674 : borrow = 0;
11963 : }
11964 : }
11965 :
11966 : Assert(borrow == 0); /* else caller gave us var1 < var2 */
11967 :
11968 324100 : digitbuf_free(result->buf);
11969 324100 : result->ndigits = res_ndigits;
11970 324100 : result->buf = res_buf;
11971 324100 : result->digits = res_digits;
11972 324100 : result->weight = res_weight;
11973 324100 : result->dscale = res_dscale;
11974 :
11975 : /* Remove leading/trailing zeroes */
11976 324100 : strip_var(result);
11977 324100 : }
11978 :
11979 : /*
11980 : * round_var
11981 : *
11982 : * Round the value of a variable to no more than rscale decimal digits
11983 : * after the decimal point. NOTE: we allow rscale < 0 here, implying
11984 : * rounding before the decimal point.
11985 : */
11986 : static void
11987 227270 : round_var(NumericVar *var, int rscale)
11988 : {
11989 227270 : NumericDigit *digits = var->digits;
11990 : int di;
11991 : int ndigits;
11992 : int carry;
11993 :
11994 227270 : var->dscale = rscale;
11995 :
11996 : /* decimal digits wanted */
11997 227270 : di = (var->weight + 1) * DEC_DIGITS + rscale;
11998 :
11999 : /*
12000 : * If di = 0, the value loses all digits, but could round up to 1 if its
12001 : * first extra digit is >= 5. If di < 0 the result must be 0.
12002 : */
12003 227270 : if (di < 0)
12004 : {
12005 104 : var->ndigits = 0;
12006 104 : var->weight = 0;
12007 104 : var->sign = NUMERIC_POS;
12008 : }
12009 : else
12010 : {
12011 : /* NBASE digits wanted */
12012 227166 : ndigits = (di + DEC_DIGITS - 1) / DEC_DIGITS;
12013 :
12014 : /* 0, or number of decimal digits to keep in last NBASE digit */
12015 227166 : di %= DEC_DIGITS;
12016 :
12017 227166 : if (ndigits < var->ndigits ||
12018 21368 : (ndigits == var->ndigits && di > 0))
12019 : {
12020 208990 : var->ndigits = ndigits;
12021 :
12022 : #if DEC_DIGITS == 1
12023 : /* di must be zero */
12024 : carry = (digits[ndigits] >= HALF_NBASE) ? 1 : 0;
12025 : #else
12026 208990 : if (di == 0)
12027 167304 : carry = (digits[ndigits] >= HALF_NBASE) ? 1 : 0;
12028 : else
12029 : {
12030 : /* Must round within last NBASE digit */
12031 : int extra,
12032 : pow10;
12033 :
12034 : #if DEC_DIGITS == 4
12035 41686 : pow10 = round_powers[di];
12036 : #elif DEC_DIGITS == 2
12037 : pow10 = 10;
12038 : #else
12039 : #error unsupported NBASE
12040 : #endif
12041 41686 : extra = digits[--ndigits] % pow10;
12042 41686 : digits[ndigits] -= extra;
12043 41686 : carry = 0;
12044 41686 : if (extra >= pow10 / 2)
12045 : {
12046 19486 : pow10 += digits[ndigits];
12047 19486 : if (pow10 >= NBASE)
12048 : {
12049 812 : pow10 -= NBASE;
12050 812 : carry = 1;
12051 : }
12052 19486 : digits[ndigits] = pow10;
12053 : }
12054 : }
12055 : #endif
12056 :
12057 : /* Propagate carry if needed */
12058 244228 : while (carry)
12059 : {
12060 35238 : carry += digits[--ndigits];
12061 35238 : if (carry >= NBASE)
12062 : {
12063 24726 : digits[ndigits] = carry - NBASE;
12064 24726 : carry = 1;
12065 : }
12066 : else
12067 : {
12068 10512 : digits[ndigits] = carry;
12069 10512 : carry = 0;
12070 : }
12071 : }
12072 :
12073 208990 : if (ndigits < 0)
12074 : {
12075 : Assert(ndigits == -1); /* better not have added > 1 digit */
12076 : Assert(var->digits > var->buf);
12077 96 : var->digits--;
12078 96 : var->ndigits++;
12079 96 : var->weight++;
12080 : }
12081 : }
12082 : }
12083 227270 : }
12084 :
12085 : /*
12086 : * trunc_var
12087 : *
12088 : * Truncate (towards zero) the value of a variable at rscale decimal digits
12089 : * after the decimal point. NOTE: we allow rscale < 0 here, implying
12090 : * truncation before the decimal point.
12091 : */
12092 : static void
12093 60832 : trunc_var(NumericVar *var, int rscale)
12094 : {
12095 : int di;
12096 : int ndigits;
12097 :
12098 60832 : var->dscale = rscale;
12099 :
12100 : /* decimal digits wanted */
12101 60832 : di = (var->weight + 1) * DEC_DIGITS + rscale;
12102 :
12103 : /*
12104 : * If di <= 0, the value loses all digits.
12105 : */
12106 60832 : if (di <= 0)
12107 : {
12108 90 : var->ndigits = 0;
12109 90 : var->weight = 0;
12110 90 : var->sign = NUMERIC_POS;
12111 : }
12112 : else
12113 : {
12114 : /* NBASE digits wanted */
12115 60742 : ndigits = (di + DEC_DIGITS - 1) / DEC_DIGITS;
12116 :
12117 60742 : if (ndigits <= var->ndigits)
12118 : {
12119 60472 : var->ndigits = ndigits;
12120 :
12121 : #if DEC_DIGITS == 1
12122 : /* no within-digit stuff to worry about */
12123 : #else
12124 : /* 0, or number of decimal digits to keep in last NBASE digit */
12125 60472 : di %= DEC_DIGITS;
12126 :
12127 60472 : if (di > 0)
12128 : {
12129 : /* Must truncate within last NBASE digit */
12130 106 : NumericDigit *digits = var->digits;
12131 : int extra,
12132 : pow10;
12133 :
12134 : #if DEC_DIGITS == 4
12135 106 : pow10 = round_powers[di];
12136 : #elif DEC_DIGITS == 2
12137 : pow10 = 10;
12138 : #else
12139 : #error unsupported NBASE
12140 : #endif
12141 106 : extra = digits[--ndigits] % pow10;
12142 106 : digits[ndigits] -= extra;
12143 : }
12144 : #endif
12145 : }
12146 : }
12147 60832 : }
12148 :
12149 : /*
12150 : * strip_var
12151 : *
12152 : * Strip any leading and trailing zeroes from a numeric variable
12153 : */
12154 : static void
12155 2066396 : strip_var(NumericVar *var)
12156 : {
12157 2066396 : NumericDigit *digits = var->digits;
12158 2066396 : int ndigits = var->ndigits;
12159 :
12160 : /* Strip leading zeroes */
12161 4031974 : while (ndigits > 0 && *digits == 0)
12162 : {
12163 1965578 : digits++;
12164 1965578 : var->weight--;
12165 1965578 : ndigits--;
12166 : }
12167 :
12168 : /* Strip trailing zeroes */
12169 2738258 : while (ndigits > 0 && digits[ndigits - 1] == 0)
12170 671862 : ndigits--;
12171 :
12172 : /* If it's zero, normalize the sign and weight */
12173 2066396 : if (ndigits == 0)
12174 : {
12175 27352 : var->sign = NUMERIC_POS;
12176 27352 : var->weight = 0;
12177 : }
12178 :
12179 2066396 : var->digits = digits;
12180 2066396 : var->ndigits = ndigits;
12181 2066396 : }
12182 :
12183 :
12184 : /* ----------------------------------------------------------------------
12185 : *
12186 : * Fast sum accumulator functions
12187 : *
12188 : * ----------------------------------------------------------------------
12189 : */
12190 :
12191 : /*
12192 : * Reset the accumulator's value to zero. The buffers to hold the digits
12193 : * are not free'd.
12194 : */
12195 : static void
12196 18 : accum_sum_reset(NumericSumAccum *accum)
12197 : {
12198 : int i;
12199 :
12200 18 : accum->dscale = 0;
12201 66 : for (i = 0; i < accum->ndigits; i++)
12202 : {
12203 48 : accum->pos_digits[i] = 0;
12204 48 : accum->neg_digits[i] = 0;
12205 : }
12206 18 : }
12207 :
12208 : /*
12209 : * Accumulate a new value.
12210 : */
12211 : static void
12212 2355644 : accum_sum_add(NumericSumAccum *accum, const NumericVar *val)
12213 : {
12214 : int32 *accum_digits;
12215 : int i,
12216 : val_i;
12217 : int val_ndigits;
12218 : NumericDigit *val_digits;
12219 :
12220 : /*
12221 : * If we have accumulated too many values since the last carry
12222 : * propagation, do it now, to avoid overflowing. (We could allow more
12223 : * than NBASE - 1, if we reserved two extra digits, rather than one, for
12224 : * carry propagation. But even with NBASE - 1, this needs to be done so
12225 : * seldom, that the performance difference is negligible.)
12226 : */
12227 2355644 : if (accum->num_uncarried == NBASE - 1)
12228 174 : accum_sum_carry(accum);
12229 :
12230 : /*
12231 : * Adjust the weight or scale of the old value, so that it can accommodate
12232 : * the new value.
12233 : */
12234 2355644 : accum_sum_rescale(accum, val);
12235 :
12236 : /* */
12237 2355644 : if (val->sign == NUMERIC_POS)
12238 1754966 : accum_digits = accum->pos_digits;
12239 : else
12240 600678 : accum_digits = accum->neg_digits;
12241 :
12242 : /* copy these values into local vars for speed in loop */
12243 2355644 : val_ndigits = val->ndigits;
12244 2355644 : val_digits = val->digits;
12245 :
12246 2355644 : i = accum->weight - val->weight;
12247 11889758 : for (val_i = 0; val_i < val_ndigits; val_i++)
12248 : {
12249 9534114 : accum_digits[i] += (int32) val_digits[val_i];
12250 9534114 : i++;
12251 : }
12252 :
12253 2355644 : accum->num_uncarried++;
12254 2355644 : }
12255 :
12256 : /*
12257 : * Propagate carries.
12258 : */
12259 : static void
12260 172716 : accum_sum_carry(NumericSumAccum *accum)
12261 : {
12262 : int i;
12263 : int ndigits;
12264 : int32 *dig;
12265 : int32 carry;
12266 172716 : int32 newdig = 0;
12267 :
12268 : /*
12269 : * If no new values have been added since last carry propagation, nothing
12270 : * to do.
12271 : */
12272 172716 : if (accum->num_uncarried == 0)
12273 72 : return;
12274 :
12275 : /*
12276 : * We maintain that the weight of the accumulator is always one larger
12277 : * than needed to hold the current value, before carrying, to make sure
12278 : * there is enough space for the possible extra digit when carry is
12279 : * propagated. We cannot expand the buffer here, unless we require
12280 : * callers of accum_sum_final() to switch to the right memory context.
12281 : */
12282 : Assert(accum->pos_digits[0] == 0 && accum->neg_digits[0] == 0);
12283 :
12284 172644 : ndigits = accum->ndigits;
12285 :
12286 : /* Propagate carry in the positive sum */
12287 172644 : dig = accum->pos_digits;
12288 172644 : carry = 0;
12289 2605384 : for (i = ndigits - 1; i >= 0; i--)
12290 : {
12291 2432740 : newdig = dig[i] + carry;
12292 2432740 : if (newdig >= NBASE)
12293 : {
12294 110790 : carry = newdig / NBASE;
12295 110790 : newdig -= carry * NBASE;
12296 : }
12297 : else
12298 2321950 : carry = 0;
12299 2432740 : dig[i] = newdig;
12300 : }
12301 : /* Did we use up the digit reserved for carry propagation? */
12302 172644 : if (newdig > 0)
12303 2616 : accum->have_carry_space = false;
12304 :
12305 : /* And the same for the negative sum */
12306 172644 : dig = accum->neg_digits;
12307 172644 : carry = 0;
12308 2605384 : for (i = ndigits - 1; i >= 0; i--)
12309 : {
12310 2432740 : newdig = dig[i] + carry;
12311 2432740 : if (newdig >= NBASE)
12312 : {
12313 198 : carry = newdig / NBASE;
12314 198 : newdig -= carry * NBASE;
12315 : }
12316 : else
12317 2432542 : carry = 0;
12318 2432740 : dig[i] = newdig;
12319 : }
12320 172644 : if (newdig > 0)
12321 30 : accum->have_carry_space = false;
12322 :
12323 172644 : accum->num_uncarried = 0;
12324 : }
12325 :
12326 : /*
12327 : * Re-scale accumulator to accommodate new value.
12328 : *
12329 : * If the new value has more digits than the current digit buffers in the
12330 : * accumulator, enlarge the buffers.
12331 : */
12332 : static void
12333 2355644 : accum_sum_rescale(NumericSumAccum *accum, const NumericVar *val)
12334 : {
12335 2355644 : int old_weight = accum->weight;
12336 2355644 : int old_ndigits = accum->ndigits;
12337 : int accum_ndigits;
12338 : int accum_weight;
12339 : int accum_rscale;
12340 : int val_rscale;
12341 :
12342 2355644 : accum_weight = old_weight;
12343 2355644 : accum_ndigits = old_ndigits;
12344 :
12345 : /*
12346 : * Does the new value have a larger weight? If so, enlarge the buffers,
12347 : * and shift the existing value to the new weight, by adding leading
12348 : * zeros.
12349 : *
12350 : * We enforce that the accumulator always has a weight one larger than
12351 : * needed for the inputs, so that we have space for an extra digit at the
12352 : * final carry-propagation phase, if necessary.
12353 : */
12354 2355644 : if (val->weight >= accum_weight)
12355 : {
12356 262176 : accum_weight = val->weight + 1;
12357 262176 : accum_ndigits = accum_ndigits + (accum_weight - old_weight);
12358 : }
12359 :
12360 : /*
12361 : * Even though the new value is small, we might've used up the space
12362 : * reserved for the carry digit in the last call to accum_sum_carry(). If
12363 : * so, enlarge to make room for another one.
12364 : */
12365 2093468 : else if (!accum->have_carry_space)
12366 : {
12367 72 : accum_weight++;
12368 72 : accum_ndigits++;
12369 : }
12370 :
12371 : /* Is the new value wider on the right side? */
12372 2355644 : accum_rscale = accum_ndigits - accum_weight - 1;
12373 2355644 : val_rscale = val->ndigits - val->weight - 1;
12374 2355644 : if (val_rscale > accum_rscale)
12375 172186 : accum_ndigits = accum_ndigits + (val_rscale - accum_rscale);
12376 :
12377 2355644 : if (accum_ndigits != old_ndigits ||
12378 : accum_weight != old_weight)
12379 : {
12380 : int32 *new_pos_digits;
12381 : int32 *new_neg_digits;
12382 : int weightdiff;
12383 :
12384 262512 : weightdiff = accum_weight - old_weight;
12385 :
12386 262512 : new_pos_digits = palloc0(accum_ndigits * sizeof(int32));
12387 262512 : new_neg_digits = palloc0(accum_ndigits * sizeof(int32));
12388 :
12389 262512 : if (accum->pos_digits)
12390 : {
12391 90396 : memcpy(&new_pos_digits[weightdiff], accum->pos_digits,
12392 : old_ndigits * sizeof(int32));
12393 90396 : pfree(accum->pos_digits);
12394 :
12395 90396 : memcpy(&new_neg_digits[weightdiff], accum->neg_digits,
12396 : old_ndigits * sizeof(int32));
12397 90396 : pfree(accum->neg_digits);
12398 : }
12399 :
12400 262512 : accum->pos_digits = new_pos_digits;
12401 262512 : accum->neg_digits = new_neg_digits;
12402 :
12403 262512 : accum->weight = accum_weight;
12404 262512 : accum->ndigits = accum_ndigits;
12405 :
12406 : Assert(accum->pos_digits[0] == 0 && accum->neg_digits[0] == 0);
12407 262512 : accum->have_carry_space = true;
12408 : }
12409 :
12410 2355644 : if (val->dscale > accum->dscale)
12411 300 : accum->dscale = val->dscale;
12412 2355644 : }
12413 :
12414 : /*
12415 : * Return the current value of the accumulator. This perform final carry
12416 : * propagation, and adds together the positive and negative sums.
12417 : *
12418 : * Unlike all the other routines, the caller is not required to switch to
12419 : * the memory context that holds the accumulator.
12420 : */
12421 : static void
12422 172542 : accum_sum_final(NumericSumAccum *accum, NumericVar *result)
12423 : {
12424 : int i;
12425 : NumericVar pos_var;
12426 : NumericVar neg_var;
12427 :
12428 172542 : if (accum->ndigits == 0)
12429 : {
12430 0 : set_var_from_var(&const_zero, result);
12431 0 : return;
12432 : }
12433 :
12434 : /* Perform final carry */
12435 172542 : accum_sum_carry(accum);
12436 :
12437 : /* Create NumericVars representing the positive and negative sums */
12438 172542 : init_var(&pos_var);
12439 172542 : init_var(&neg_var);
12440 :
12441 172542 : pos_var.ndigits = neg_var.ndigits = accum->ndigits;
12442 172542 : pos_var.weight = neg_var.weight = accum->weight;
12443 172542 : pos_var.dscale = neg_var.dscale = accum->dscale;
12444 172542 : pos_var.sign = NUMERIC_POS;
12445 172542 : neg_var.sign = NUMERIC_NEG;
12446 :
12447 172542 : pos_var.buf = pos_var.digits = digitbuf_alloc(accum->ndigits);
12448 172542 : neg_var.buf = neg_var.digits = digitbuf_alloc(accum->ndigits);
12449 :
12450 2604874 : for (i = 0; i < accum->ndigits; i++)
12451 : {
12452 : Assert(accum->pos_digits[i] < NBASE);
12453 2432332 : pos_var.digits[i] = (int16) accum->pos_digits[i];
12454 :
12455 : Assert(accum->neg_digits[i] < NBASE);
12456 2432332 : neg_var.digits[i] = (int16) accum->neg_digits[i];
12457 : }
12458 :
12459 : /* And add them together */
12460 172542 : add_var(&pos_var, &neg_var, result);
12461 :
12462 : /* Remove leading/trailing zeroes */
12463 172542 : strip_var(result);
12464 : }
12465 :
12466 : /*
12467 : * Copy an accumulator's state.
12468 : *
12469 : * 'dst' is assumed to be uninitialized beforehand. No attempt is made at
12470 : * freeing old values.
12471 : */
12472 : static void
12473 42 : accum_sum_copy(NumericSumAccum *dst, NumericSumAccum *src)
12474 : {
12475 42 : dst->pos_digits = palloc(src->ndigits * sizeof(int32));
12476 42 : dst->neg_digits = palloc(src->ndigits * sizeof(int32));
12477 :
12478 42 : memcpy(dst->pos_digits, src->pos_digits, src->ndigits * sizeof(int32));
12479 42 : memcpy(dst->neg_digits, src->neg_digits, src->ndigits * sizeof(int32));
12480 42 : dst->num_uncarried = src->num_uncarried;
12481 42 : dst->ndigits = src->ndigits;
12482 42 : dst->weight = src->weight;
12483 42 : dst->dscale = src->dscale;
12484 42 : }
12485 :
12486 : /*
12487 : * Add the current value of 'accum2' into 'accum'.
12488 : */
12489 : static void
12490 18 : accum_sum_combine(NumericSumAccum *accum, NumericSumAccum *accum2)
12491 : {
12492 : NumericVar tmp_var;
12493 :
12494 18 : init_var(&tmp_var);
12495 :
12496 18 : accum_sum_final(accum2, &tmp_var);
12497 18 : accum_sum_add(accum, &tmp_var);
12498 :
12499 18 : free_var(&tmp_var);
12500 18 : }
|