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-2026, 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 "common/int128.h"
32 : #include "funcapi.h"
33 : #include "lib/hyperloglog.h"
34 : #include "libpq/pqformat.h"
35 : #include "miscadmin.h"
36 : #include "nodes/nodeFuncs.h"
37 : #include "nodes/supportnodes.h"
38 : #include "optimizer/optimizer.h"
39 : #include "utils/array.h"
40 : #include "utils/builtins.h"
41 : #include "utils/float.h"
42 : #include "utils/guc.h"
43 : #include "utils/numeric.h"
44 : #include "utils/pg_lsn.h"
45 : #include "utils/sortsupport.h"
46 :
47 : /* ----------
48 : * Uncomment the following to enable compilation of dump_numeric()
49 : * and dump_var() and to get a dump of any result produced by make_result().
50 : * ----------
51 : #define NUMERIC_DEBUG
52 : */
53 :
54 :
55 : /* ----------
56 : * Local data types
57 : *
58 : * Numeric values are represented in a base-NBASE floating point format.
59 : * Each "digit" ranges from 0 to NBASE-1. The type NumericDigit is signed
60 : * and wide enough to store a digit. We assume that NBASE*NBASE can fit in
61 : * an int. Although the purely calculational routines could handle any even
62 : * NBASE that's less than sqrt(INT_MAX), in practice we are only interested
63 : * in NBASE a power of ten, so that I/O conversions and decimal rounding
64 : * are easy. Also, it's actually more efficient if NBASE is rather less than
65 : * sqrt(INT_MAX), so that there is "headroom" for mul_var and div_var to
66 : * postpone processing carries.
67 : *
68 : * Values of NBASE other than 10000 are considered of historical interest only
69 : * and are no longer supported in any sense; no mechanism exists for the client
70 : * to discover the base, so every client supporting binary mode expects the
71 : * base-10000 format. If you plan to change this, also note the numeric
72 : * abbreviation code, which assumes NBASE=10000.
73 : * ----------
74 : */
75 :
76 : #if 0
77 : #define NBASE 10
78 : #define HALF_NBASE 5
79 : #define DEC_DIGITS 1 /* decimal digits per NBASE digit */
80 : #define MUL_GUARD_DIGITS 4 /* these are measured in NBASE digits */
81 : #define DIV_GUARD_DIGITS 8
82 :
83 : typedef signed char NumericDigit;
84 : #endif
85 :
86 : #if 0
87 : #define NBASE 100
88 : #define HALF_NBASE 50
89 : #define DEC_DIGITS 2 /* decimal digits per NBASE digit */
90 : #define MUL_GUARD_DIGITS 3 /* these are measured in NBASE digits */
91 : #define DIV_GUARD_DIGITS 6
92 :
93 : typedef signed char NumericDigit;
94 : #endif
95 :
96 : #if 1
97 : #define NBASE 10000
98 : #define HALF_NBASE 5000
99 : #define DEC_DIGITS 4 /* decimal digits per NBASE digit */
100 : #define MUL_GUARD_DIGITS 2 /* these are measured in NBASE digits */
101 : #define DIV_GUARD_DIGITS 4
102 :
103 : typedef int16 NumericDigit;
104 : #endif
105 :
106 : #define NBASE_SQR (NBASE * NBASE)
107 :
108 : /*
109 : * The Numeric type as stored on disk.
110 : *
111 : * If the high bits of the first word of a NumericChoice (n_header, or
112 : * n_short.n_header, or n_long.n_sign_dscale) are NUMERIC_SHORT, then the
113 : * numeric follows the NumericShort format; if they are NUMERIC_POS or
114 : * NUMERIC_NEG, it follows the NumericLong format. If they are NUMERIC_SPECIAL,
115 : * the value is a NaN or Infinity. We currently always store SPECIAL values
116 : * using just two bytes (i.e. only n_header), but previous releases used only
117 : * the NumericLong format, so we might find 4-byte NaNs (though not infinities)
118 : * on disk if a database has been migrated using pg_upgrade. In either case,
119 : * the low-order bits of a special value's header are reserved and currently
120 : * should always be set to zero.
121 : *
122 : * In the NumericShort format, the remaining 14 bits of the header word
123 : * (n_short.n_header) are allocated as follows: 1 for sign (positive or
124 : * negative), 6 for dynamic scale, and 7 for weight. In practice, most
125 : * commonly-encountered values can be represented this way.
126 : *
127 : * In the NumericLong format, the remaining 14 bits of the header word
128 : * (n_long.n_sign_dscale) represent the display scale; and the weight is
129 : * stored separately in n_weight.
130 : *
131 : * NOTE: by convention, values in the packed form have been stripped of
132 : * all leading and trailing zero digits (where a "digit" is of base NBASE).
133 : * In particular, if the value is zero, there will be no digits at all!
134 : * The weight is arbitrary in that case, but we normally set it to zero.
135 : */
136 :
137 : struct NumericShort
138 : {
139 : uint16 n_header; /* Sign + display scale + weight */
140 : NumericDigit n_data[FLEXIBLE_ARRAY_MEMBER]; /* Digits */
141 : };
142 :
143 : struct NumericLong
144 : {
145 : uint16 n_sign_dscale; /* Sign + display scale */
146 : int16 n_weight; /* Weight of 1st digit */
147 : NumericDigit n_data[FLEXIBLE_ARRAY_MEMBER]; /* Digits */
148 : };
149 :
150 : union NumericChoice
151 : {
152 : uint16 n_header; /* Header word */
153 : struct NumericLong n_long; /* Long form (4-byte header) */
154 : struct NumericShort n_short; /* Short form (2-byte header) */
155 : };
156 :
157 : struct NumericData
158 : {
159 : int32 vl_len_; /* varlena header (do not touch directly!) */
160 : union NumericChoice choice; /* choice of format */
161 : };
162 :
163 :
164 : /*
165 : * Interpretation of high bits.
166 : */
167 :
168 : #define NUMERIC_SIGN_MASK 0xC000
169 : #define NUMERIC_POS 0x0000
170 : #define NUMERIC_NEG 0x4000
171 : #define NUMERIC_SHORT 0x8000
172 : #define NUMERIC_SPECIAL 0xC000
173 :
174 : #define NUMERIC_FLAGBITS(n) ((n)->choice.n_header & NUMERIC_SIGN_MASK)
175 : #define NUMERIC_IS_SHORT(n) (NUMERIC_FLAGBITS(n) == NUMERIC_SHORT)
176 : #define NUMERIC_IS_SPECIAL(n) (NUMERIC_FLAGBITS(n) == NUMERIC_SPECIAL)
177 :
178 : #define NUMERIC_HDRSZ (VARHDRSZ + sizeof(uint16) + sizeof(int16))
179 : #define NUMERIC_HDRSZ_SHORT (VARHDRSZ + sizeof(uint16))
180 :
181 : /*
182 : * If the flag bits are NUMERIC_SHORT or NUMERIC_SPECIAL, we want the short
183 : * header; otherwise, we want the long one. Instead of testing against each
184 : * value, we can just look at the high bit, for a slight efficiency gain.
185 : */
186 : #define NUMERIC_HEADER_IS_SHORT(n) (((n)->choice.n_header & 0x8000) != 0)
187 : #define NUMERIC_HEADER_SIZE(n) \
188 : (VARHDRSZ + sizeof(uint16) + \
189 : (NUMERIC_HEADER_IS_SHORT(n) ? 0 : sizeof(int16)))
190 :
191 : /*
192 : * Definitions for special values (NaN, positive infinity, negative infinity).
193 : *
194 : * The two bits after the NUMERIC_SPECIAL bits are 00 for NaN, 01 for positive
195 : * infinity, 11 for negative infinity. (This makes the sign bit match where
196 : * it is in a short-format value, though we make no use of that at present.)
197 : * We could mask off the remaining bits before testing the active bits, but
198 : * currently those bits must be zeroes, so masking would just add cycles.
199 : */
200 : #define NUMERIC_EXT_SIGN_MASK 0xF000 /* high bits plus NaN/Inf flag bits */
201 : #define NUMERIC_NAN 0xC000
202 : #define NUMERIC_PINF 0xD000
203 : #define NUMERIC_NINF 0xF000
204 : #define NUMERIC_INF_SIGN_MASK 0x2000
205 :
206 : #define NUMERIC_EXT_FLAGBITS(n) ((n)->choice.n_header & NUMERIC_EXT_SIGN_MASK)
207 : #define NUMERIC_IS_NAN(n) ((n)->choice.n_header == NUMERIC_NAN)
208 : #define NUMERIC_IS_PINF(n) ((n)->choice.n_header == NUMERIC_PINF)
209 : #define NUMERIC_IS_NINF(n) ((n)->choice.n_header == NUMERIC_NINF)
210 : #define NUMERIC_IS_INF(n) \
211 : (((n)->choice.n_header & ~NUMERIC_INF_SIGN_MASK) == NUMERIC_PINF)
212 :
213 : /*
214 : * Short format definitions.
215 : */
216 :
217 : #define NUMERIC_SHORT_SIGN_MASK 0x2000
218 : #define NUMERIC_SHORT_DSCALE_MASK 0x1F80
219 : #define NUMERIC_SHORT_DSCALE_SHIFT 7
220 : #define NUMERIC_SHORT_DSCALE_MAX \
221 : (NUMERIC_SHORT_DSCALE_MASK >> NUMERIC_SHORT_DSCALE_SHIFT)
222 : #define NUMERIC_SHORT_WEIGHT_SIGN_MASK 0x0040
223 : #define NUMERIC_SHORT_WEIGHT_MASK 0x003F
224 : #define NUMERIC_SHORT_WEIGHT_MAX NUMERIC_SHORT_WEIGHT_MASK
225 : #define NUMERIC_SHORT_WEIGHT_MIN (-(NUMERIC_SHORT_WEIGHT_MASK+1))
226 :
227 : /*
228 : * Extract sign, display scale, weight. These macros extract field values
229 : * suitable for the NumericVar format from the Numeric (on-disk) format.
230 : *
231 : * Note that we don't trouble to ensure that dscale and weight read as zero
232 : * for an infinity; however, that doesn't matter since we never convert
233 : * "special" numerics to NumericVar form. Only the constants defined below
234 : * (const_nan, etc) ever represent a non-finite value as a NumericVar.
235 : */
236 :
237 : #define NUMERIC_DSCALE_MASK 0x3FFF
238 : #define NUMERIC_DSCALE_MAX NUMERIC_DSCALE_MASK
239 :
240 : #define NUMERIC_SIGN(n) \
241 : (NUMERIC_IS_SHORT(n) ? \
242 : (((n)->choice.n_short.n_header & NUMERIC_SHORT_SIGN_MASK) ? \
243 : NUMERIC_NEG : NUMERIC_POS) : \
244 : (NUMERIC_IS_SPECIAL(n) ? \
245 : NUMERIC_EXT_FLAGBITS(n) : NUMERIC_FLAGBITS(n)))
246 : #define NUMERIC_DSCALE(n) (NUMERIC_HEADER_IS_SHORT((n)) ? \
247 : ((n)->choice.n_short.n_header & NUMERIC_SHORT_DSCALE_MASK) \
248 : >> NUMERIC_SHORT_DSCALE_SHIFT \
249 : : ((n)->choice.n_long.n_sign_dscale & NUMERIC_DSCALE_MASK))
250 : #define NUMERIC_WEIGHT(n) (NUMERIC_HEADER_IS_SHORT((n)) ? \
251 : (((n)->choice.n_short.n_header & NUMERIC_SHORT_WEIGHT_SIGN_MASK ? \
252 : ~NUMERIC_SHORT_WEIGHT_MASK : 0) \
253 : | ((n)->choice.n_short.n_header & NUMERIC_SHORT_WEIGHT_MASK)) \
254 : : ((n)->choice.n_long.n_weight))
255 :
256 : /*
257 : * Maximum weight of a stored Numeric value (based on the use of int16 for the
258 : * weight in NumericLong). Note that intermediate values held in NumericVar
259 : * and NumericSumAccum variables may have much larger weights.
260 : */
261 : #define NUMERIC_WEIGHT_MAX PG_INT16_MAX
262 :
263 : /* ----------
264 : * NumericVar is the format we use for arithmetic. The digit-array part
265 : * is the same as the NumericData storage format, but the header is more
266 : * complex.
267 : *
268 : * The value represented by a NumericVar is determined by the sign, weight,
269 : * ndigits, and digits[] array. If it is a "special" value (NaN or Inf)
270 : * then only the sign field matters; ndigits should be zero, and the weight
271 : * and dscale fields are ignored.
272 : *
273 : * Note: the first digit of a NumericVar's value is assumed to be multiplied
274 : * by NBASE ** weight. Another way to say it is that there are weight+1
275 : * digits before the decimal point. It is possible to have weight < 0.
276 : *
277 : * buf points at the physical start of the palloc'd digit buffer for the
278 : * NumericVar. digits points at the first digit in actual use (the one
279 : * with the specified weight). We normally leave an unused digit or two
280 : * (preset to zeroes) between buf and digits, so that there is room to store
281 : * a carry out of the top digit without reallocating space. We just need to
282 : * decrement digits (and increment weight) to make room for the carry digit.
283 : * (There is no such extra space in a numeric value stored in the database,
284 : * only in a NumericVar in memory.)
285 : *
286 : * If buf is NULL then the digit buffer isn't actually palloc'd and should
287 : * not be freed --- see the constants below for an example.
288 : *
289 : * dscale, or display scale, is the nominal precision expressed as number
290 : * of digits after the decimal point (it must always be >= 0 at present).
291 : * dscale may be more than the number of physically stored fractional digits,
292 : * implying that we have suppressed storage of significant trailing zeroes.
293 : * It should never be less than the number of stored digits, since that would
294 : * imply hiding digits that are present. NOTE that dscale is always expressed
295 : * in *decimal* digits, and so it may correspond to a fractional number of
296 : * base-NBASE digits --- divide by DEC_DIGITS to convert to NBASE digits.
297 : *
298 : * rscale, or result scale, is the target precision for a computation.
299 : * Like dscale it is expressed as number of *decimal* digits after the decimal
300 : * point, and is always >= 0 at present.
301 : * Note that rscale is not stored in variables --- it's figured on-the-fly
302 : * from the dscales of the inputs.
303 : *
304 : * While we consistently use "weight" to refer to the base-NBASE weight of
305 : * a numeric value, it is convenient in some scale-related calculations to
306 : * make use of the base-10 weight (ie, the approximate log10 of the value).
307 : * To avoid confusion, such a decimal-units weight is called a "dweight".
308 : *
309 : * NB: All the variable-level functions are written in a style that makes it
310 : * possible to give one and the same variable as argument and destination.
311 : * This is feasible because the digit buffer is separate from the variable.
312 : * ----------
313 : */
314 : typedef struct NumericVar
315 : {
316 : int ndigits; /* # of digits in digits[] - can be 0! */
317 : int weight; /* weight of first digit */
318 : int sign; /* NUMERIC_POS, _NEG, _NAN, _PINF, or _NINF */
319 : int dscale; /* display scale */
320 : NumericDigit *buf; /* start of palloc'd space for digits[] */
321 : NumericDigit *digits; /* base-NBASE digits */
322 : } NumericVar;
323 :
324 :
325 : /* ----------
326 : * Data for generate_series
327 : * ----------
328 : */
329 : typedef struct
330 : {
331 : NumericVar current;
332 : NumericVar stop;
333 : NumericVar step;
334 : } generate_series_numeric_fctx;
335 :
336 :
337 : /* ----------
338 : * Sort support.
339 : * ----------
340 : */
341 : typedef struct
342 : {
343 : void *buf; /* buffer for short varlenas */
344 : int64 input_count; /* number of non-null values seen */
345 : bool estimating; /* true if estimating cardinality */
346 :
347 : hyperLogLogState abbr_card; /* cardinality estimator */
348 : } NumericSortSupport;
349 :
350 :
351 : /* ----------
352 : * Fast sum accumulator.
353 : *
354 : * NumericSumAccum is used to implement SUM(), and other standard aggregates
355 : * that track the sum of input values. It uses 32-bit integers to store the
356 : * digits, instead of the normal 16-bit integers (with NBASE=10000). This
357 : * way, we can safely accumulate up to NBASE - 1 values without propagating
358 : * carry, before risking overflow of any of the digits. 'num_uncarried'
359 : * tracks how many values have been accumulated without propagating carry.
360 : *
361 : * Positive and negative values are accumulated separately, in 'pos_digits'
362 : * and 'neg_digits'. This is simpler and faster than deciding whether to add
363 : * or subtract from the current value, for each new value (see sub_var() for
364 : * the logic we avoid by doing this). Both buffers are of same size, and
365 : * have the same weight and scale. In accum_sum_final(), the positive and
366 : * negative sums are added together to produce the final result.
367 : *
368 : * When a new value has a larger ndigits or weight than the accumulator
369 : * currently does, the accumulator is enlarged to accommodate the new value.
370 : * We normally have one zero digit reserved for carry propagation, and that
371 : * is indicated by the 'have_carry_space' flag. When accum_sum_carry() uses
372 : * up the reserved digit, it clears the 'have_carry_space' flag. The next
373 : * call to accum_sum_add() will enlarge the buffer, to make room for the
374 : * extra digit, and set the flag again.
375 : *
376 : * To initialize a new accumulator, simply reset all fields to zeros.
377 : *
378 : * The accumulator does not handle NaNs.
379 : * ----------
380 : */
381 : typedef struct NumericSumAccum
382 : {
383 : int ndigits;
384 : int weight;
385 : int dscale;
386 : int num_uncarried;
387 : bool have_carry_space;
388 : int32 *pos_digits;
389 : int32 *neg_digits;
390 : } NumericSumAccum;
391 :
392 :
393 : /*
394 : * We define our own macros for packing and unpacking abbreviated-key
395 : * representations, just to have a notational indication that that's
396 : * what we're doing. Now that sizeof(Datum) is always 8, we can rely
397 : * on fitting an int64 into Datum.
398 : *
399 : * The range of abbreviations for finite values is from +PG_INT64_MAX
400 : * to -PG_INT64_MAX. NaN has the abbreviation PG_INT64_MIN, and we
401 : * define the sort ordering to make that work out properly (see further
402 : * comments below). PINF and NINF share the abbreviations of the largest
403 : * and smallest finite abbreviation classes.
404 : */
405 : #define NumericAbbrevGetDatum(X) Int64GetDatum(X)
406 : #define DatumGetNumericAbbrev(X) DatumGetInt64(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 :
411 :
412 : /* ----------
413 : * Some preinitialized constants
414 : * ----------
415 : */
416 : static const NumericDigit const_zero_data[1] = {0};
417 : static const NumericVar const_zero =
418 : {0, 0, NUMERIC_POS, 0, NULL, (NumericDigit *) const_zero_data};
419 :
420 : static const NumericDigit const_one_data[1] = {1};
421 : static const NumericVar const_one =
422 : {1, 0, NUMERIC_POS, 0, NULL, (NumericDigit *) const_one_data};
423 :
424 : static const NumericVar const_minus_one =
425 : {1, 0, NUMERIC_NEG, 0, NULL, (NumericDigit *) const_one_data};
426 :
427 : static const NumericDigit const_two_data[1] = {2};
428 : static const NumericVar const_two =
429 : {1, 0, NUMERIC_POS, 0, NULL, (NumericDigit *) const_two_data};
430 :
431 : #if DEC_DIGITS == 4
432 : static const NumericDigit const_zero_point_nine_data[1] = {9000};
433 : #elif DEC_DIGITS == 2
434 : static const NumericDigit const_zero_point_nine_data[1] = {90};
435 : #elif DEC_DIGITS == 1
436 : static const NumericDigit const_zero_point_nine_data[1] = {9};
437 : #endif
438 : static const NumericVar const_zero_point_nine =
439 : {1, -1, NUMERIC_POS, 1, NULL, (NumericDigit *) const_zero_point_nine_data};
440 :
441 : #if DEC_DIGITS == 4
442 : static const NumericDigit const_one_point_one_data[2] = {1, 1000};
443 : #elif DEC_DIGITS == 2
444 : static const NumericDigit const_one_point_one_data[2] = {1, 10};
445 : #elif DEC_DIGITS == 1
446 : static const NumericDigit const_one_point_one_data[2] = {1, 1};
447 : #endif
448 : static const NumericVar const_one_point_one =
449 : {2, 0, NUMERIC_POS, 1, NULL, (NumericDigit *) const_one_point_one_data};
450 :
451 : static const NumericVar const_nan =
452 : {0, 0, NUMERIC_NAN, 0, NULL, NULL};
453 :
454 : static const NumericVar const_pinf =
455 : {0, 0, NUMERIC_PINF, 0, NULL, NULL};
456 :
457 : static const NumericVar const_ninf =
458 : {0, 0, NUMERIC_NINF, 0, NULL, NULL};
459 :
460 : #if DEC_DIGITS == 4
461 : static const int round_powers[4] = {0, 1000, 100, 10};
462 : #endif
463 :
464 :
465 : /* ----------
466 : * Local functions
467 : * ----------
468 : */
469 :
470 : #ifdef NUMERIC_DEBUG
471 : static void dump_numeric(const char *str, Numeric num);
472 : static void dump_var(const char *str, NumericVar *var);
473 : #else
474 : #define dump_numeric(s,n)
475 : #define dump_var(s,v)
476 : #endif
477 :
478 : #define digitbuf_alloc(ndigits) \
479 : ((NumericDigit *) palloc((ndigits) * sizeof(NumericDigit)))
480 : #define digitbuf_free(buf) \
481 : do { \
482 : if ((buf) != NULL) \
483 : pfree(buf); \
484 : } while (0)
485 :
486 : #define init_var(v) memset(v, 0, sizeof(NumericVar))
487 :
488 : #define NUMERIC_DIGITS(num) (NUMERIC_HEADER_IS_SHORT(num) ? \
489 : (num)->choice.n_short.n_data : (num)->choice.n_long.n_data)
490 : #define NUMERIC_NDIGITS(num) \
491 : ((VARSIZE(num) - NUMERIC_HEADER_SIZE(num)) / sizeof(NumericDigit))
492 : #define NUMERIC_CAN_BE_SHORT(scale,weight) \
493 : ((scale) <= NUMERIC_SHORT_DSCALE_MAX && \
494 : (weight) <= NUMERIC_SHORT_WEIGHT_MAX && \
495 : (weight) >= NUMERIC_SHORT_WEIGHT_MIN)
496 :
497 : static void alloc_var(NumericVar *var, int ndigits);
498 : static void free_var(NumericVar *var);
499 : static void zero_var(NumericVar *var);
500 :
501 : static bool set_var_from_str(const char *str, const char *cp,
502 : NumericVar *dest, const char **endptr,
503 : Node *escontext);
504 : static bool set_var_from_non_decimal_integer_str(const char *str,
505 : const char *cp, int sign,
506 : int base, NumericVar *dest,
507 : const char **endptr,
508 : Node *escontext);
509 : static void set_var_from_num(Numeric num, NumericVar *dest);
510 : static void init_var_from_num(Numeric num, NumericVar *dest);
511 : static void set_var_from_var(const NumericVar *value, NumericVar *dest);
512 : static char *get_str_from_var(const NumericVar *var);
513 : static char *get_str_from_var_sci(const NumericVar *var, int rscale);
514 :
515 : static void numericvar_serialize(StringInfo buf, const NumericVar *var);
516 : static void numericvar_deserialize(StringInfo buf, NumericVar *var);
517 :
518 : static Numeric duplicate_numeric(Numeric num);
519 : static Numeric make_result(const NumericVar *var);
520 : static Numeric make_result_safe(const NumericVar *var, Node *escontext);
521 :
522 : static bool apply_typmod(NumericVar *var, int32 typmod, Node *escontext);
523 : static bool apply_typmod_special(Numeric num, int32 typmod, Node *escontext);
524 :
525 : static bool numericvar_to_int32(const NumericVar *var, int32 *result);
526 : static bool numericvar_to_int64(const NumericVar *var, int64 *result);
527 : static void int64_to_numericvar(int64 val, NumericVar *var);
528 : static bool numericvar_to_uint64(const NumericVar *var, uint64 *result);
529 : static void int128_to_numericvar(INT128 val, NumericVar *var);
530 : static double numericvar_to_double_no_overflow(const NumericVar *var);
531 :
532 : static Datum numeric_abbrev_convert(Datum original_datum, SortSupport ssup);
533 : static bool numeric_abbrev_abort(int memtupcount, SortSupport ssup);
534 : static int numeric_fast_cmp(Datum x, Datum y, SortSupport ssup);
535 : static int numeric_cmp_abbrev(Datum x, Datum y, SortSupport ssup);
536 :
537 : static Datum numeric_abbrev_convert_var(const NumericVar *var,
538 : NumericSortSupport *nss);
539 :
540 : static int cmp_numerics(Numeric num1, Numeric num2);
541 : static int cmp_var(const NumericVar *var1, const NumericVar *var2);
542 : static int cmp_var_common(const NumericDigit *var1digits, int var1ndigits,
543 : int var1weight, int var1sign,
544 : const NumericDigit *var2digits, int var2ndigits,
545 : int var2weight, int var2sign);
546 : static void add_var(const NumericVar *var1, const NumericVar *var2,
547 : NumericVar *result);
548 : static void sub_var(const NumericVar *var1, const NumericVar *var2,
549 : NumericVar *result);
550 : static void mul_var(const NumericVar *var1, const NumericVar *var2,
551 : NumericVar *result,
552 : int rscale);
553 : static void mul_var_short(const NumericVar *var1, const NumericVar *var2,
554 : NumericVar *result);
555 : static void div_var(const NumericVar *var1, const NumericVar *var2,
556 : NumericVar *result, int rscale, bool round, bool exact);
557 : static void div_var_int(const NumericVar *var, int ival, int ival_weight,
558 : NumericVar *result, int rscale, bool round);
559 : #ifdef HAVE_INT128
560 : static void div_var_int64(const NumericVar *var, int64 ival, int ival_weight,
561 : NumericVar *result, int rscale, bool round);
562 : #endif
563 : static int select_div_scale(const NumericVar *var1, const NumericVar *var2);
564 : static void mod_var(const NumericVar *var1, const NumericVar *var2,
565 : NumericVar *result);
566 : static void div_mod_var(const NumericVar *var1, const NumericVar *var2,
567 : NumericVar *quot, NumericVar *rem);
568 : static void ceil_var(const NumericVar *var, NumericVar *result);
569 : static void floor_var(const NumericVar *var, NumericVar *result);
570 :
571 : static void gcd_var(const NumericVar *var1, const NumericVar *var2,
572 : NumericVar *result);
573 : static void sqrt_var(const NumericVar *arg, NumericVar *result, int rscale);
574 : static void exp_var(const NumericVar *arg, NumericVar *result, int rscale);
575 : static int estimate_ln_dweight(const NumericVar *var);
576 : static void ln_var(const NumericVar *arg, NumericVar *result, int rscale);
577 : static void log_var(const NumericVar *base, const NumericVar *num,
578 : NumericVar *result);
579 : static void power_var(const NumericVar *base, const NumericVar *exp,
580 : NumericVar *result);
581 : static void power_var_int(const NumericVar *base, int exp, int exp_dscale,
582 : NumericVar *result);
583 : static void power_ten_int(int exp, NumericVar *result);
584 : static void random_var(pg_prng_state *state, const NumericVar *rmin,
585 : const NumericVar *rmax, NumericVar *result);
586 :
587 : static int cmp_abs(const NumericVar *var1, const NumericVar *var2);
588 : static int cmp_abs_common(const NumericDigit *var1digits, int var1ndigits,
589 : int var1weight,
590 : const NumericDigit *var2digits, int var2ndigits,
591 : int var2weight);
592 : static void add_abs(const NumericVar *var1, const NumericVar *var2,
593 : NumericVar *result);
594 : static void sub_abs(const NumericVar *var1, const NumericVar *var2,
595 : NumericVar *result);
596 : static void round_var(NumericVar *var, int rscale);
597 : static void trunc_var(NumericVar *var, int rscale);
598 : static void strip_var(NumericVar *var);
599 : static void compute_bucket(Numeric operand, Numeric bound1, Numeric bound2,
600 : const NumericVar *count_var,
601 : NumericVar *result_var);
602 :
603 : static void accum_sum_add(NumericSumAccum *accum, const NumericVar *val);
604 : static void accum_sum_rescale(NumericSumAccum *accum, const NumericVar *val);
605 : static void accum_sum_carry(NumericSumAccum *accum);
606 : static void accum_sum_reset(NumericSumAccum *accum);
607 : static void accum_sum_final(NumericSumAccum *accum, NumericVar *result);
608 : static void accum_sum_copy(NumericSumAccum *dst, NumericSumAccum *src);
609 : static void accum_sum_combine(NumericSumAccum *accum, NumericSumAccum *accum2);
610 :
611 :
612 : /* ----------------------------------------------------------------------
613 : *
614 : * Input-, output- and rounding-functions
615 : *
616 : * ----------------------------------------------------------------------
617 : */
618 :
619 :
620 : /*
621 : * numeric_in() -
622 : *
623 : * Input function for numeric data type
624 : */
625 : Datum
626 165080 : numeric_in(PG_FUNCTION_ARGS)
627 : {
628 165080 : char *str = PG_GETARG_CSTRING(0);
629 : #ifdef NOT_USED
630 : Oid typelem = PG_GETARG_OID(1);
631 : #endif
632 165080 : int32 typmod = PG_GETARG_INT32(2);
633 165080 : Node *escontext = fcinfo->context;
634 : Numeric res;
635 : const char *cp;
636 : const char *numstart;
637 : int sign;
638 :
639 : /* Skip leading spaces */
640 165080 : cp = str;
641 189500 : while (*cp)
642 : {
643 189482 : if (!isspace((unsigned char) *cp))
644 165062 : break;
645 24420 : cp++;
646 : }
647 :
648 : /*
649 : * Process the number's sign. This duplicates logic in set_var_from_str(),
650 : * but it's worth doing here, since it simplifies the handling of
651 : * infinities and non-decimal integers.
652 : */
653 165080 : numstart = cp;
654 165080 : sign = NUMERIC_POS;
655 :
656 165080 : if (*cp == '+')
657 48 : cp++;
658 165032 : else if (*cp == '-')
659 : {
660 4110 : sign = NUMERIC_NEG;
661 4110 : cp++;
662 : }
663 :
664 : /*
665 : * Check for NaN and infinities. We recognize the same strings allowed by
666 : * float8in().
667 : *
668 : * Since all other legal inputs have a digit or a decimal point after the
669 : * sign, we need only check for NaN/infinity if that's not the case.
670 : */
671 165080 : if (!isdigit((unsigned char) *cp) && *cp != '.')
672 : {
673 : /*
674 : * The number must be NaN or infinity; anything else can only be a
675 : * syntax error. Note that NaN mustn't have a sign.
676 : */
677 1796 : if (pg_strncasecmp(numstart, "NaN", 3) == 0)
678 : {
679 606 : res = make_result(&const_nan);
680 606 : cp = numstart + 3;
681 : }
682 1190 : else if (pg_strncasecmp(cp, "Infinity", 8) == 0)
683 : {
684 492 : res = make_result(sign == NUMERIC_POS ? &const_pinf : &const_ninf);
685 492 : cp += 8;
686 : }
687 698 : else if (pg_strncasecmp(cp, "inf", 3) == 0)
688 : {
689 588 : res = make_result(sign == NUMERIC_POS ? &const_pinf : &const_ninf);
690 588 : cp += 3;
691 : }
692 : else
693 110 : goto invalid_syntax;
694 :
695 : /*
696 : * Check for trailing junk; there should be nothing left but spaces.
697 : *
698 : * We intentionally do this check before applying the typmod because
699 : * we would like to throw any trailing-junk syntax error before any
700 : * semantic error resulting from apply_typmod_special().
701 : */
702 1728 : while (*cp)
703 : {
704 42 : if (!isspace((unsigned char) *cp))
705 0 : goto invalid_syntax;
706 42 : cp++;
707 : }
708 :
709 1686 : if (!apply_typmod_special(res, typmod, escontext))
710 0 : PG_RETURN_NULL();
711 : }
712 : else
713 : {
714 : /*
715 : * We have a normal numeric value, which may be a non-decimal integer
716 : * or a regular decimal number.
717 : */
718 : NumericVar value;
719 : int base;
720 :
721 163284 : init_var(&value);
722 :
723 : /*
724 : * Determine the number's base by looking for a non-decimal prefix
725 : * indicator ("0x", "0o", or "0b").
726 : */
727 163284 : if (cp[0] == '0')
728 : {
729 51100 : switch (cp[1])
730 : {
731 72 : case 'x':
732 : case 'X':
733 72 : base = 16;
734 72 : break;
735 42 : case 'o':
736 : case 'O':
737 42 : base = 8;
738 42 : break;
739 42 : case 'b':
740 : case 'B':
741 42 : base = 2;
742 42 : break;
743 50944 : default:
744 50944 : base = 10;
745 : }
746 : }
747 : else
748 112184 : base = 10;
749 :
750 : /* Parse the rest of the number and apply the sign */
751 163284 : if (base == 10)
752 : {
753 163128 : if (!set_var_from_str(str, cp, &value, &cp, escontext))
754 24 : PG_RETURN_NULL();
755 163080 : value.sign = sign;
756 : }
757 : else
758 : {
759 156 : if (!set_var_from_non_decimal_integer_str(str, cp + 2, sign, base,
760 : &value, &cp, escontext))
761 0 : PG_RETURN_NULL();
762 : }
763 :
764 : /*
765 : * Should be nothing left but spaces. As above, throw any typmod error
766 : * after finishing syntax check.
767 : */
768 163296 : while (*cp)
769 : {
770 150 : if (!isspace((unsigned char) *cp))
771 72 : goto invalid_syntax;
772 78 : cp++;
773 : }
774 :
775 163146 : if (!apply_typmod(&value, typmod, escontext))
776 24 : PG_RETURN_NULL();
777 :
778 163122 : res = make_result_safe(&value, escontext);
779 :
780 163122 : free_var(&value);
781 : }
782 :
783 164808 : PG_RETURN_NUMERIC(res);
784 :
785 182 : invalid_syntax:
786 182 : ereturn(escontext, (Datum) 0,
787 : (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
788 : errmsg("invalid input syntax for type %s: \"%s\"",
789 : "numeric", str)));
790 : }
791 :
792 :
793 : /*
794 : * numeric_out() -
795 : *
796 : * Output function for numeric data type
797 : */
798 : Datum
799 853782 : numeric_out(PG_FUNCTION_ARGS)
800 : {
801 853782 : Numeric num = PG_GETARG_NUMERIC(0);
802 : NumericVar x;
803 : char *str;
804 :
805 : /*
806 : * Handle NaN and infinities
807 : */
808 853782 : if (NUMERIC_IS_SPECIAL(num))
809 : {
810 3612 : if (NUMERIC_IS_PINF(num))
811 1040 : PG_RETURN_CSTRING(pstrdup("Infinity"));
812 2572 : else if (NUMERIC_IS_NINF(num))
813 658 : PG_RETURN_CSTRING(pstrdup("-Infinity"));
814 : else
815 1914 : PG_RETURN_CSTRING(pstrdup("NaN"));
816 : }
817 :
818 : /*
819 : * Get the number in the variable format.
820 : */
821 850170 : init_var_from_num(num, &x);
822 :
823 850170 : str = get_str_from_var(&x);
824 :
825 850170 : PG_RETURN_CSTRING(str);
826 : }
827 :
828 : /*
829 : * numeric_is_nan() -
830 : *
831 : * Is Numeric value a NaN?
832 : */
833 : bool
834 8378 : numeric_is_nan(Numeric num)
835 : {
836 8378 : return NUMERIC_IS_NAN(num);
837 : }
838 :
839 : /*
840 : * numeric_is_inf() -
841 : *
842 : * Is Numeric value an infinity?
843 : */
844 : bool
845 1210 : numeric_is_inf(Numeric num)
846 : {
847 1210 : return NUMERIC_IS_INF(num);
848 : }
849 :
850 : /*
851 : * numeric_is_integral() -
852 : *
853 : * Is Numeric value integral?
854 : */
855 : static bool
856 66 : numeric_is_integral(Numeric num)
857 : {
858 : NumericVar arg;
859 :
860 : /* Reject NaN, but infinities are considered integral */
861 66 : if (NUMERIC_IS_SPECIAL(num))
862 : {
863 30 : if (NUMERIC_IS_NAN(num))
864 0 : return false;
865 30 : return true;
866 : }
867 :
868 : /* Integral if there are no digits to the right of the decimal point */
869 36 : init_var_from_num(num, &arg);
870 :
871 36 : return (arg.ndigits == 0 || arg.ndigits <= arg.weight + 1);
872 : }
873 :
874 : /*
875 : * make_numeric_typmod() -
876 : *
877 : * Pack numeric precision and scale values into a typmod. The upper 16 bits
878 : * are used for the precision (though actually not all these bits are needed,
879 : * since the maximum allowed precision is 1000). The lower 16 bits are for
880 : * the scale, but since the scale is constrained to the range [-1000, 1000],
881 : * we use just the lower 11 of those 16 bits, and leave the remaining 5 bits
882 : * unset, for possible future use.
883 : *
884 : * For purely historical reasons VARHDRSZ is then added to the result, thus
885 : * the unused space in the upper 16 bits is not all as freely available as it
886 : * might seem. (We can't let the result overflow to a negative int32, as
887 : * other parts of the system would interpret that as not-a-valid-typmod.)
888 : */
889 : static inline int32
890 1894 : make_numeric_typmod(int precision, int scale)
891 : {
892 1894 : return ((precision << 16) | (scale & 0x7ff)) + VARHDRSZ;
893 : }
894 :
895 : /*
896 : * Because of the offset, valid numeric typmods are at least VARHDRSZ
897 : */
898 : static inline bool
899 188180 : is_valid_numeric_typmod(int32 typmod)
900 : {
901 188180 : return typmod >= (int32) VARHDRSZ;
902 : }
903 :
904 : /*
905 : * numeric_typmod_precision() -
906 : *
907 : * Extract the precision from a numeric typmod --- see make_numeric_typmod().
908 : */
909 : static inline int
910 48620 : numeric_typmod_precision(int32 typmod)
911 : {
912 48620 : return ((typmod - VARHDRSZ) >> 16) & 0xffff;
913 : }
914 :
915 : /*
916 : * numeric_typmod_scale() -
917 : *
918 : * Extract the scale from a numeric typmod --- see make_numeric_typmod().
919 : *
920 : * Note that the scale may be negative, so we must do sign extension when
921 : * unpacking it. We do this using the bit hack (x^1024)-1024, which sign
922 : * extends an 11-bit two's complement number x.
923 : */
924 : static inline int
925 41526 : numeric_typmod_scale(int32 typmod)
926 : {
927 41526 : return (((typmod - VARHDRSZ) & 0x7ff) ^ 1024) - 1024;
928 : }
929 :
930 : /*
931 : * numeric_maximum_size() -
932 : *
933 : * Maximum size of a numeric with given typmod, or -1 if unlimited/unknown.
934 : */
935 : int32
936 7094 : numeric_maximum_size(int32 typmod)
937 : {
938 : int precision;
939 : int numeric_digits;
940 :
941 7094 : if (!is_valid_numeric_typmod(typmod))
942 0 : return -1;
943 :
944 : /* precision (ie, max # of digits) is in upper bits of typmod */
945 7094 : precision = numeric_typmod_precision(typmod);
946 :
947 : /*
948 : * This formula computes the maximum number of NumericDigits we could need
949 : * in order to store the specified number of decimal digits. Because the
950 : * weight is stored as a number of NumericDigits rather than a number of
951 : * decimal digits, it's possible that the first NumericDigit will contain
952 : * only a single decimal digit. Thus, the first two decimal digits can
953 : * require two NumericDigits to store, but it isn't until we reach
954 : * DEC_DIGITS + 2 decimal digits that we potentially need a third
955 : * NumericDigit.
956 : */
957 7094 : numeric_digits = (precision + 2 * (DEC_DIGITS - 1)) / DEC_DIGITS;
958 :
959 : /*
960 : * In most cases, the size of a numeric will be smaller than the value
961 : * computed below, because the varlena header will typically get toasted
962 : * down to a single byte before being stored on disk, and it may also be
963 : * possible to use a short numeric header. But our job here is to compute
964 : * the worst case.
965 : */
966 7094 : return NUMERIC_HDRSZ + (numeric_digits * sizeof(NumericDigit));
967 : }
968 :
969 : /*
970 : * numeric_out_sci() -
971 : *
972 : * Output function for numeric data type in scientific notation.
973 : */
974 : char *
975 246 : numeric_out_sci(Numeric num, int scale)
976 : {
977 : NumericVar x;
978 : char *str;
979 :
980 : /*
981 : * Handle NaN and infinities
982 : */
983 246 : if (NUMERIC_IS_SPECIAL(num))
984 : {
985 18 : if (NUMERIC_IS_PINF(num))
986 6 : return pstrdup("Infinity");
987 12 : else if (NUMERIC_IS_NINF(num))
988 6 : return pstrdup("-Infinity");
989 : else
990 6 : return pstrdup("NaN");
991 : }
992 :
993 228 : init_var_from_num(num, &x);
994 :
995 228 : str = get_str_from_var_sci(&x, scale);
996 :
997 228 : return str;
998 : }
999 :
1000 : /*
1001 : * numeric_normalize() -
1002 : *
1003 : * Output function for numeric data type, suppressing insignificant trailing
1004 : * zeroes and then any trailing decimal point. The intent of this is to
1005 : * produce strings that are equal if and only if the input numeric values
1006 : * compare equal.
1007 : */
1008 : char *
1009 38492 : numeric_normalize(Numeric num)
1010 : {
1011 : NumericVar x;
1012 : char *str;
1013 : int last;
1014 :
1015 : /*
1016 : * Handle NaN and infinities
1017 : */
1018 38492 : if (NUMERIC_IS_SPECIAL(num))
1019 : {
1020 0 : if (NUMERIC_IS_PINF(num))
1021 0 : return pstrdup("Infinity");
1022 0 : else if (NUMERIC_IS_NINF(num))
1023 0 : return pstrdup("-Infinity");
1024 : else
1025 0 : return pstrdup("NaN");
1026 : }
1027 :
1028 38492 : init_var_from_num(num, &x);
1029 :
1030 38492 : str = get_str_from_var(&x);
1031 :
1032 : /* If there's no decimal point, there's certainly nothing to remove. */
1033 38492 : if (strchr(str, '.') != NULL)
1034 : {
1035 : /*
1036 : * Back up over trailing fractional zeroes. Since there is a decimal
1037 : * point, this loop will terminate safely.
1038 : */
1039 42 : last = strlen(str) - 1;
1040 84 : while (str[last] == '0')
1041 42 : last--;
1042 :
1043 : /* We want to get rid of the decimal point too, if it's now last. */
1044 42 : if (str[last] == '.')
1045 42 : last--;
1046 :
1047 : /* Delete whatever we backed up over. */
1048 42 : str[last + 1] = '\0';
1049 : }
1050 :
1051 38492 : return str;
1052 : }
1053 :
1054 : /*
1055 : * numeric_recv - converts external binary format to numeric
1056 : *
1057 : * External format is a sequence of int16's:
1058 : * ndigits, weight, sign, dscale, NumericDigits.
1059 : */
1060 : Datum
1061 102 : numeric_recv(PG_FUNCTION_ARGS)
1062 : {
1063 102 : StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
1064 :
1065 : #ifdef NOT_USED
1066 : Oid typelem = PG_GETARG_OID(1);
1067 : #endif
1068 102 : int32 typmod = PG_GETARG_INT32(2);
1069 : NumericVar value;
1070 : Numeric res;
1071 : int len,
1072 : i;
1073 :
1074 102 : init_var(&value);
1075 :
1076 102 : len = (uint16) pq_getmsgint(buf, sizeof(uint16));
1077 :
1078 102 : alloc_var(&value, len);
1079 :
1080 102 : value.weight = (int16) pq_getmsgint(buf, sizeof(int16));
1081 : /* we allow any int16 for weight --- OK? */
1082 :
1083 102 : value.sign = (uint16) pq_getmsgint(buf, sizeof(uint16));
1084 102 : if (!(value.sign == NUMERIC_POS ||
1085 0 : value.sign == NUMERIC_NEG ||
1086 0 : value.sign == NUMERIC_NAN ||
1087 0 : value.sign == NUMERIC_PINF ||
1088 0 : value.sign == NUMERIC_NINF))
1089 0 : ereport(ERROR,
1090 : (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
1091 : errmsg("invalid sign in external \"numeric\" value")));
1092 :
1093 102 : value.dscale = (uint16) pq_getmsgint(buf, sizeof(uint16));
1094 102 : if ((value.dscale & NUMERIC_DSCALE_MASK) != value.dscale)
1095 0 : ereport(ERROR,
1096 : (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
1097 : errmsg("invalid scale in external \"numeric\" value")));
1098 :
1099 274 : for (i = 0; i < len; i++)
1100 : {
1101 172 : NumericDigit d = pq_getmsgint(buf, sizeof(NumericDigit));
1102 :
1103 172 : if (d < 0 || d >= NBASE)
1104 0 : ereport(ERROR,
1105 : (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
1106 : errmsg("invalid digit in external \"numeric\" value")));
1107 172 : value.digits[i] = d;
1108 : }
1109 :
1110 : /*
1111 : * If the given dscale would hide any digits, truncate those digits away.
1112 : * We could alternatively throw an error, but that would take a bunch of
1113 : * extra code (about as much as trunc_var involves), and it might cause
1114 : * client compatibility issues. Be careful not to apply trunc_var to
1115 : * special values, as it could do the wrong thing; we don't need it
1116 : * anyway, since make_result will ignore all but the sign field.
1117 : *
1118 : * After doing that, be sure to check the typmod restriction.
1119 : */
1120 102 : if (value.sign == NUMERIC_POS ||
1121 0 : value.sign == NUMERIC_NEG)
1122 : {
1123 102 : trunc_var(&value, value.dscale);
1124 :
1125 102 : (void) apply_typmod(&value, typmod, NULL);
1126 :
1127 102 : res = make_result(&value);
1128 : }
1129 : else
1130 : {
1131 : /* apply_typmod_special wants us to make the Numeric first */
1132 0 : res = make_result(&value);
1133 :
1134 0 : (void) apply_typmod_special(res, typmod, NULL);
1135 : }
1136 :
1137 102 : free_var(&value);
1138 :
1139 102 : PG_RETURN_NUMERIC(res);
1140 : }
1141 :
1142 : /*
1143 : * numeric_send - converts numeric to binary format
1144 : */
1145 : Datum
1146 70 : numeric_send(PG_FUNCTION_ARGS)
1147 : {
1148 70 : Numeric num = PG_GETARG_NUMERIC(0);
1149 : NumericVar x;
1150 : StringInfoData buf;
1151 : int i;
1152 :
1153 70 : init_var_from_num(num, &x);
1154 :
1155 70 : pq_begintypsend(&buf);
1156 :
1157 70 : pq_sendint16(&buf, x.ndigits);
1158 70 : pq_sendint16(&buf, x.weight);
1159 70 : pq_sendint16(&buf, x.sign);
1160 70 : pq_sendint16(&buf, x.dscale);
1161 194 : for (i = 0; i < x.ndigits; i++)
1162 124 : pq_sendint16(&buf, x.digits[i]);
1163 :
1164 70 : PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
1165 : }
1166 :
1167 :
1168 : /*
1169 : * numeric_support()
1170 : *
1171 : * Planner support function for the numeric() length coercion function.
1172 : *
1173 : * Flatten calls that solely represent increases in allowable precision.
1174 : * Scale changes mutate every datum, so they are unoptimizable. Some values,
1175 : * e.g. 1E-1001, can only fit into an unconstrained numeric, so a change from
1176 : * an unconstrained numeric to any constrained numeric is also unoptimizable.
1177 : */
1178 : Datum
1179 516 : numeric_support(PG_FUNCTION_ARGS)
1180 : {
1181 516 : Node *rawreq = (Node *) PG_GETARG_POINTER(0);
1182 516 : Node *ret = NULL;
1183 :
1184 516 : if (IsA(rawreq, SupportRequestSimplify))
1185 : {
1186 228 : SupportRequestSimplify *req = (SupportRequestSimplify *) rawreq;
1187 228 : FuncExpr *expr = req->fcall;
1188 : Node *typmod;
1189 :
1190 : Assert(list_length(expr->args) >= 2);
1191 :
1192 228 : typmod = (Node *) lsecond(expr->args);
1193 :
1194 228 : if (IsA(typmod, Const) && !((Const *) typmod)->constisnull)
1195 : {
1196 228 : Node *source = (Node *) linitial(expr->args);
1197 228 : int32 old_typmod = exprTypmod(source);
1198 228 : int32 new_typmod = DatumGetInt32(((Const *) typmod)->constvalue);
1199 228 : int32 old_scale = numeric_typmod_scale(old_typmod);
1200 228 : int32 new_scale = numeric_typmod_scale(new_typmod);
1201 228 : int32 old_precision = numeric_typmod_precision(old_typmod);
1202 228 : int32 new_precision = numeric_typmod_precision(new_typmod);
1203 :
1204 : /*
1205 : * If new_typmod is invalid, the destination is unconstrained;
1206 : * that's always OK. If old_typmod is valid, the source is
1207 : * constrained, and we're OK if the scale is unchanged and the
1208 : * precision is not decreasing. See further notes in function
1209 : * header comment.
1210 : */
1211 456 : if (!is_valid_numeric_typmod(new_typmod) ||
1212 240 : (is_valid_numeric_typmod(old_typmod) &&
1213 6 : new_scale == old_scale && new_precision >= old_precision))
1214 6 : ret = relabel_to_typmod(source, new_typmod);
1215 : }
1216 : }
1217 :
1218 516 : PG_RETURN_POINTER(ret);
1219 : }
1220 :
1221 : /*
1222 : * numeric() -
1223 : *
1224 : * This is a special function called by the Postgres database system
1225 : * before a value is stored in a tuple's attribute. The precision and
1226 : * scale of the attribute have to be applied on the value.
1227 : */
1228 : Datum
1229 11730 : numeric (PG_FUNCTION_ARGS)
1230 : {
1231 11730 : Numeric num = PG_GETARG_NUMERIC(0);
1232 11730 : int32 typmod = PG_GETARG_INT32(1);
1233 : Numeric new;
1234 : int precision;
1235 : int scale;
1236 : int ddigits;
1237 : int maxdigits;
1238 : int dscale;
1239 : NumericVar var;
1240 :
1241 : /*
1242 : * Handle NaN and infinities: if apply_typmod_special doesn't complain,
1243 : * just return a copy of the input.
1244 : */
1245 11730 : if (NUMERIC_IS_SPECIAL(num))
1246 : {
1247 210 : (void) apply_typmod_special(num, typmod, NULL);
1248 192 : PG_RETURN_NUMERIC(duplicate_numeric(num));
1249 : }
1250 :
1251 : /*
1252 : * If the value isn't a valid type modifier, simply return a copy of the
1253 : * input value
1254 : */
1255 11520 : if (!is_valid_numeric_typmod(typmod))
1256 0 : PG_RETURN_NUMERIC(duplicate_numeric(num));
1257 :
1258 : /*
1259 : * Get the precision and scale out of the typmod value
1260 : */
1261 11520 : precision = numeric_typmod_precision(typmod);
1262 11520 : scale = numeric_typmod_scale(typmod);
1263 11520 : maxdigits = precision - scale;
1264 :
1265 : /* The target display scale is non-negative */
1266 11520 : dscale = Max(scale, 0);
1267 :
1268 : /*
1269 : * If the number is certainly in bounds and due to the target scale no
1270 : * rounding could be necessary, just make a copy of the input and modify
1271 : * its scale fields, unless the larger scale forces us to abandon the
1272 : * short representation. (Note we assume the existing dscale is
1273 : * honest...)
1274 : */
1275 11520 : ddigits = (NUMERIC_WEIGHT(num) + 1) * DEC_DIGITS;
1276 11520 : if (ddigits <= maxdigits && scale >= NUMERIC_DSCALE(num)
1277 7132 : && (NUMERIC_CAN_BE_SHORT(dscale, NUMERIC_WEIGHT(num))
1278 0 : || !NUMERIC_IS_SHORT(num)))
1279 : {
1280 7132 : new = duplicate_numeric(num);
1281 7132 : if (NUMERIC_IS_SHORT(num))
1282 7132 : new->choice.n_short.n_header =
1283 7132 : (num->choice.n_short.n_header & ~NUMERIC_SHORT_DSCALE_MASK)
1284 7132 : | (dscale << NUMERIC_SHORT_DSCALE_SHIFT);
1285 : else
1286 0 : new->choice.n_long.n_sign_dscale = NUMERIC_SIGN(new) |
1287 0 : ((uint16) dscale & NUMERIC_DSCALE_MASK);
1288 7132 : PG_RETURN_NUMERIC(new);
1289 : }
1290 :
1291 : /*
1292 : * We really need to fiddle with things - unpack the number into a
1293 : * variable and let apply_typmod() do it.
1294 : */
1295 4388 : init_var(&var);
1296 :
1297 4388 : set_var_from_num(num, &var);
1298 4388 : (void) apply_typmod(&var, typmod, NULL);
1299 4328 : new = make_result(&var);
1300 :
1301 4328 : free_var(&var);
1302 :
1303 4328 : PG_RETURN_NUMERIC(new);
1304 : }
1305 :
1306 : Datum
1307 1936 : numerictypmodin(PG_FUNCTION_ARGS)
1308 : {
1309 1936 : ArrayType *ta = PG_GETARG_ARRAYTYPE_P(0);
1310 : int32 *tl;
1311 : int n;
1312 : int32 typmod;
1313 :
1314 1936 : tl = ArrayGetIntegerTypmods(ta, &n);
1315 :
1316 1936 : if (n == 2)
1317 : {
1318 1916 : if (tl[0] < 1 || tl[0] > NUMERIC_MAX_PRECISION)
1319 18 : ereport(ERROR,
1320 : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1321 : errmsg("NUMERIC precision %d must be between 1 and %d",
1322 : tl[0], NUMERIC_MAX_PRECISION)));
1323 1898 : if (tl[1] < NUMERIC_MIN_SCALE || tl[1] > NUMERIC_MAX_SCALE)
1324 12 : ereport(ERROR,
1325 : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1326 : errmsg("NUMERIC scale %d must be between %d and %d",
1327 : tl[1], NUMERIC_MIN_SCALE, NUMERIC_MAX_SCALE)));
1328 1886 : typmod = make_numeric_typmod(tl[0], tl[1]);
1329 : }
1330 20 : else if (n == 1)
1331 : {
1332 8 : if (tl[0] < 1 || tl[0] > NUMERIC_MAX_PRECISION)
1333 0 : ereport(ERROR,
1334 : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1335 : errmsg("NUMERIC precision %d must be between 1 and %d",
1336 : tl[0], NUMERIC_MAX_PRECISION)));
1337 : /* scale defaults to zero */
1338 8 : typmod = make_numeric_typmod(tl[0], 0);
1339 : }
1340 : else
1341 : {
1342 12 : ereport(ERROR,
1343 : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1344 : errmsg("invalid NUMERIC type modifier")));
1345 : typmod = 0; /* keep compiler quiet */
1346 : }
1347 :
1348 1894 : PG_RETURN_INT32(typmod);
1349 : }
1350 :
1351 : Datum
1352 376 : numerictypmodout(PG_FUNCTION_ARGS)
1353 : {
1354 376 : int32 typmod = PG_GETARG_INT32(0);
1355 376 : char *res = (char *) palloc(64);
1356 :
1357 376 : if (is_valid_numeric_typmod(typmod))
1358 376 : snprintf(res, 64, "(%d,%d)",
1359 : numeric_typmod_precision(typmod),
1360 : numeric_typmod_scale(typmod));
1361 : else
1362 0 : *res = '\0';
1363 :
1364 376 : PG_RETURN_CSTRING(res);
1365 : }
1366 :
1367 :
1368 : /* ----------------------------------------------------------------------
1369 : *
1370 : * Sign manipulation, rounding and the like
1371 : *
1372 : * ----------------------------------------------------------------------
1373 : */
1374 :
1375 : Datum
1376 19506 : numeric_abs(PG_FUNCTION_ARGS)
1377 : {
1378 19506 : Numeric num = PG_GETARG_NUMERIC(0);
1379 : Numeric res;
1380 :
1381 : /*
1382 : * Do it the easy way directly on the packed format
1383 : */
1384 19506 : res = duplicate_numeric(num);
1385 :
1386 19506 : if (NUMERIC_IS_SHORT(num))
1387 19440 : res->choice.n_short.n_header =
1388 19440 : num->choice.n_short.n_header & ~NUMERIC_SHORT_SIGN_MASK;
1389 66 : else if (NUMERIC_IS_SPECIAL(num))
1390 : {
1391 : /* This changes -Inf to Inf, and doesn't affect NaN */
1392 18 : res->choice.n_short.n_header =
1393 18 : num->choice.n_short.n_header & ~NUMERIC_INF_SIGN_MASK;
1394 : }
1395 : else
1396 48 : res->choice.n_long.n_sign_dscale = NUMERIC_POS | NUMERIC_DSCALE(num);
1397 :
1398 19506 : PG_RETURN_NUMERIC(res);
1399 : }
1400 :
1401 :
1402 : Datum
1403 884 : numeric_uminus(PG_FUNCTION_ARGS)
1404 : {
1405 884 : Numeric num = PG_GETARG_NUMERIC(0);
1406 : Numeric res;
1407 :
1408 : /*
1409 : * Do it the easy way directly on the packed format
1410 : */
1411 884 : res = duplicate_numeric(num);
1412 :
1413 884 : if (NUMERIC_IS_SPECIAL(num))
1414 : {
1415 : /* Flip the sign, if it's Inf or -Inf */
1416 126 : if (!NUMERIC_IS_NAN(num))
1417 84 : res->choice.n_short.n_header =
1418 84 : num->choice.n_short.n_header ^ NUMERIC_INF_SIGN_MASK;
1419 : }
1420 :
1421 : /*
1422 : * The packed format is known to be totally zero digit trimmed always. So
1423 : * once we've eliminated specials, we can identify a zero by the fact that
1424 : * there are no digits at all. Do nothing to a zero.
1425 : */
1426 758 : else if (NUMERIC_NDIGITS(num) != 0)
1427 : {
1428 : /* Else, flip the sign */
1429 644 : if (NUMERIC_IS_SHORT(num))
1430 644 : res->choice.n_short.n_header =
1431 644 : num->choice.n_short.n_header ^ NUMERIC_SHORT_SIGN_MASK;
1432 0 : else if (NUMERIC_SIGN(num) == NUMERIC_POS)
1433 0 : res->choice.n_long.n_sign_dscale =
1434 0 : NUMERIC_NEG | NUMERIC_DSCALE(num);
1435 : else
1436 0 : res->choice.n_long.n_sign_dscale =
1437 0 : NUMERIC_POS | NUMERIC_DSCALE(num);
1438 : }
1439 :
1440 884 : PG_RETURN_NUMERIC(res);
1441 : }
1442 :
1443 :
1444 : Datum
1445 0 : numeric_uplus(PG_FUNCTION_ARGS)
1446 : {
1447 0 : Numeric num = PG_GETARG_NUMERIC(0);
1448 :
1449 0 : PG_RETURN_NUMERIC(duplicate_numeric(num));
1450 : }
1451 :
1452 :
1453 : /*
1454 : * numeric_sign_internal() -
1455 : *
1456 : * Returns -1 if the argument is less than 0, 0 if the argument is equal
1457 : * to 0, and 1 if the argument is greater than zero. Caller must have
1458 : * taken care of the NaN case, but we can handle infinities here.
1459 : */
1460 : static int
1461 3570 : numeric_sign_internal(Numeric num)
1462 : {
1463 3570 : if (NUMERIC_IS_SPECIAL(num))
1464 : {
1465 : Assert(!NUMERIC_IS_NAN(num));
1466 : /* Must be Inf or -Inf */
1467 312 : if (NUMERIC_IS_PINF(num))
1468 186 : return 1;
1469 : else
1470 126 : return -1;
1471 : }
1472 :
1473 : /*
1474 : * The packed format is known to be totally zero digit trimmed always. So
1475 : * once we've eliminated specials, we can identify a zero by the fact that
1476 : * there are no digits at all.
1477 : */
1478 3258 : else if (NUMERIC_NDIGITS(num) == 0)
1479 228 : return 0;
1480 3030 : else if (NUMERIC_SIGN(num) == NUMERIC_NEG)
1481 732 : return -1;
1482 : else
1483 2298 : return 1;
1484 : }
1485 :
1486 : /*
1487 : * numeric_sign() -
1488 : *
1489 : * returns -1 if the argument is less than 0, 0 if the argument is equal
1490 : * to 0, and 1 if the argument is greater than zero.
1491 : */
1492 : Datum
1493 48 : numeric_sign(PG_FUNCTION_ARGS)
1494 : {
1495 48 : Numeric num = PG_GETARG_NUMERIC(0);
1496 :
1497 : /*
1498 : * Handle NaN (infinities can be handled normally)
1499 : */
1500 48 : if (NUMERIC_IS_NAN(num))
1501 6 : PG_RETURN_NUMERIC(make_result(&const_nan));
1502 :
1503 42 : switch (numeric_sign_internal(num))
1504 : {
1505 6 : case 0:
1506 6 : PG_RETURN_NUMERIC(make_result(&const_zero));
1507 18 : case 1:
1508 18 : PG_RETURN_NUMERIC(make_result(&const_one));
1509 18 : case -1:
1510 18 : PG_RETURN_NUMERIC(make_result(&const_minus_one));
1511 : }
1512 :
1513 : Assert(false);
1514 0 : return (Datum) 0;
1515 : }
1516 :
1517 :
1518 : /*
1519 : * numeric_round() -
1520 : *
1521 : * Round a value to have 'scale' digits after the decimal point.
1522 : * We allow negative 'scale', implying rounding before the decimal
1523 : * point --- Oracle interprets rounding that way.
1524 : */
1525 : Datum
1526 7808 : numeric_round(PG_FUNCTION_ARGS)
1527 : {
1528 7808 : Numeric num = PG_GETARG_NUMERIC(0);
1529 7808 : int32 scale = PG_GETARG_INT32(1);
1530 : Numeric res;
1531 : NumericVar arg;
1532 :
1533 : /*
1534 : * Handle NaN and infinities
1535 : */
1536 7808 : if (NUMERIC_IS_SPECIAL(num))
1537 96 : PG_RETURN_NUMERIC(duplicate_numeric(num));
1538 :
1539 : /*
1540 : * Limit the scale value to avoid possible overflow in calculations.
1541 : *
1542 : * These limits are based on the maximum number of digits a Numeric value
1543 : * can have before and after the decimal point, but we must allow for one
1544 : * extra digit before the decimal point, in case the most significant
1545 : * digit rounds up; we must check if that causes Numeric overflow.
1546 : */
1547 7712 : scale = Max(scale, -(NUMERIC_WEIGHT_MAX + 1) * DEC_DIGITS - 1);
1548 7712 : scale = Min(scale, NUMERIC_DSCALE_MAX);
1549 :
1550 : /*
1551 : * Unpack the argument and round it at the proper digit position
1552 : */
1553 7712 : init_var(&arg);
1554 7712 : set_var_from_num(num, &arg);
1555 :
1556 7712 : round_var(&arg, scale);
1557 :
1558 : /* We don't allow negative output dscale */
1559 7712 : if (scale < 0)
1560 216 : arg.dscale = 0;
1561 :
1562 : /*
1563 : * Return the rounded result
1564 : */
1565 7712 : res = make_result(&arg);
1566 :
1567 7706 : free_var(&arg);
1568 7706 : PG_RETURN_NUMERIC(res);
1569 : }
1570 :
1571 :
1572 : /*
1573 : * numeric_trunc() -
1574 : *
1575 : * Truncate a value to have 'scale' digits after the decimal point.
1576 : * We allow negative 'scale', implying a truncation before the decimal
1577 : * point --- Oracle interprets truncation that way.
1578 : */
1579 : Datum
1580 626 : numeric_trunc(PG_FUNCTION_ARGS)
1581 : {
1582 626 : Numeric num = PG_GETARG_NUMERIC(0);
1583 626 : int32 scale = PG_GETARG_INT32(1);
1584 : Numeric res;
1585 : NumericVar arg;
1586 :
1587 : /*
1588 : * Handle NaN and infinities
1589 : */
1590 626 : if (NUMERIC_IS_SPECIAL(num))
1591 36 : PG_RETURN_NUMERIC(duplicate_numeric(num));
1592 :
1593 : /*
1594 : * Limit the scale value to avoid possible overflow in calculations.
1595 : *
1596 : * These limits are based on the maximum number of digits a Numeric value
1597 : * can have before and after the decimal point.
1598 : */
1599 590 : scale = Max(scale, -(NUMERIC_WEIGHT_MAX + 1) * DEC_DIGITS);
1600 590 : scale = Min(scale, NUMERIC_DSCALE_MAX);
1601 :
1602 : /*
1603 : * Unpack the argument and truncate it at the proper digit position
1604 : */
1605 590 : init_var(&arg);
1606 590 : set_var_from_num(num, &arg);
1607 :
1608 590 : trunc_var(&arg, scale);
1609 :
1610 : /* We don't allow negative output dscale */
1611 590 : if (scale < 0)
1612 24 : arg.dscale = 0;
1613 :
1614 : /*
1615 : * Return the truncated result
1616 : */
1617 590 : res = make_result(&arg);
1618 :
1619 590 : free_var(&arg);
1620 590 : PG_RETURN_NUMERIC(res);
1621 : }
1622 :
1623 :
1624 : /*
1625 : * numeric_ceil() -
1626 : *
1627 : * Return the smallest integer greater than or equal to the argument
1628 : */
1629 : Datum
1630 222 : numeric_ceil(PG_FUNCTION_ARGS)
1631 : {
1632 222 : Numeric num = PG_GETARG_NUMERIC(0);
1633 : Numeric res;
1634 : NumericVar result;
1635 :
1636 : /*
1637 : * Handle NaN and infinities
1638 : */
1639 222 : if (NUMERIC_IS_SPECIAL(num))
1640 18 : PG_RETURN_NUMERIC(duplicate_numeric(num));
1641 :
1642 204 : init_var_from_num(num, &result);
1643 204 : ceil_var(&result, &result);
1644 :
1645 204 : res = make_result(&result);
1646 204 : free_var(&result);
1647 :
1648 204 : PG_RETURN_NUMERIC(res);
1649 : }
1650 :
1651 :
1652 : /*
1653 : * numeric_floor() -
1654 : *
1655 : * Return the largest integer equal to or less than the argument
1656 : */
1657 : Datum
1658 126 : numeric_floor(PG_FUNCTION_ARGS)
1659 : {
1660 126 : Numeric num = PG_GETARG_NUMERIC(0);
1661 : Numeric res;
1662 : NumericVar result;
1663 :
1664 : /*
1665 : * Handle NaN and infinities
1666 : */
1667 126 : if (NUMERIC_IS_SPECIAL(num))
1668 18 : PG_RETURN_NUMERIC(duplicate_numeric(num));
1669 :
1670 108 : init_var_from_num(num, &result);
1671 108 : floor_var(&result, &result);
1672 :
1673 108 : res = make_result(&result);
1674 108 : free_var(&result);
1675 :
1676 108 : PG_RETURN_NUMERIC(res);
1677 : }
1678 :
1679 :
1680 : /*
1681 : * generate_series_numeric() -
1682 : *
1683 : * Generate series of numeric.
1684 : */
1685 : Datum
1686 120384 : generate_series_numeric(PG_FUNCTION_ARGS)
1687 : {
1688 120384 : return generate_series_step_numeric(fcinfo);
1689 : }
1690 :
1691 : Datum
1692 120834 : generate_series_step_numeric(PG_FUNCTION_ARGS)
1693 : {
1694 : generate_series_numeric_fctx *fctx;
1695 : FuncCallContext *funcctx;
1696 : MemoryContext oldcontext;
1697 :
1698 120834 : if (SRF_IS_FIRSTCALL())
1699 : {
1700 174 : Numeric start_num = PG_GETARG_NUMERIC(0);
1701 174 : Numeric stop_num = PG_GETARG_NUMERIC(1);
1702 174 : NumericVar steploc = const_one;
1703 :
1704 : /* Reject NaN and infinities in start and stop values */
1705 174 : if (NUMERIC_IS_SPECIAL(start_num))
1706 : {
1707 12 : if (NUMERIC_IS_NAN(start_num))
1708 6 : ereport(ERROR,
1709 : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1710 : errmsg("start value cannot be NaN")));
1711 : else
1712 6 : ereport(ERROR,
1713 : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1714 : errmsg("start value cannot be infinity")));
1715 : }
1716 162 : if (NUMERIC_IS_SPECIAL(stop_num))
1717 : {
1718 12 : if (NUMERIC_IS_NAN(stop_num))
1719 6 : ereport(ERROR,
1720 : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1721 : errmsg("stop value cannot be NaN")));
1722 : else
1723 6 : ereport(ERROR,
1724 : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1725 : errmsg("stop value cannot be infinity")));
1726 : }
1727 :
1728 : /* see if we were given an explicit step size */
1729 150 : if (PG_NARGS() == 3)
1730 : {
1731 72 : Numeric step_num = PG_GETARG_NUMERIC(2);
1732 :
1733 72 : if (NUMERIC_IS_SPECIAL(step_num))
1734 : {
1735 12 : if (NUMERIC_IS_NAN(step_num))
1736 6 : ereport(ERROR,
1737 : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1738 : errmsg("step size cannot be NaN")));
1739 : else
1740 6 : ereport(ERROR,
1741 : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1742 : errmsg("step size cannot be infinity")));
1743 : }
1744 :
1745 60 : init_var_from_num(step_num, &steploc);
1746 :
1747 60 : if (cmp_var(&steploc, &const_zero) == 0)
1748 6 : ereport(ERROR,
1749 : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1750 : errmsg("step size cannot equal zero")));
1751 : }
1752 :
1753 : /* create a function context for cross-call persistence */
1754 132 : funcctx = SRF_FIRSTCALL_INIT();
1755 :
1756 : /*
1757 : * Switch to memory context appropriate for multiple function calls.
1758 : */
1759 132 : oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
1760 :
1761 : /* allocate memory for user context */
1762 132 : fctx = palloc_object(generate_series_numeric_fctx);
1763 :
1764 : /*
1765 : * Use fctx to keep state from call to call. Seed current with the
1766 : * original start value. We must copy the start_num and stop_num
1767 : * values rather than pointing to them, since we may have detoasted
1768 : * them in the per-call context.
1769 : */
1770 132 : init_var(&fctx->current);
1771 132 : init_var(&fctx->stop);
1772 132 : init_var(&fctx->step);
1773 :
1774 132 : set_var_from_num(start_num, &fctx->current);
1775 132 : set_var_from_num(stop_num, &fctx->stop);
1776 132 : set_var_from_var(&steploc, &fctx->step);
1777 :
1778 132 : funcctx->user_fctx = fctx;
1779 132 : MemoryContextSwitchTo(oldcontext);
1780 : }
1781 :
1782 : /* stuff done on every call of the function */
1783 120792 : funcctx = SRF_PERCALL_SETUP();
1784 :
1785 : /*
1786 : * Get the saved state and use current state as the result of this
1787 : * iteration.
1788 : */
1789 120792 : fctx = funcctx->user_fctx;
1790 :
1791 241404 : if ((fctx->step.sign == NUMERIC_POS &&
1792 120612 : cmp_var(&fctx->current, &fctx->stop) <= 0) ||
1793 480 : (fctx->step.sign == NUMERIC_NEG &&
1794 180 : cmp_var(&fctx->current, &fctx->stop) >= 0))
1795 : {
1796 120660 : Numeric result = make_result(&fctx->current);
1797 :
1798 : /* switch to memory context appropriate for iteration calculation */
1799 120660 : oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
1800 :
1801 : /* increment current in preparation for next iteration */
1802 120660 : add_var(&fctx->current, &fctx->step, &fctx->current);
1803 120660 : MemoryContextSwitchTo(oldcontext);
1804 :
1805 : /* do when there is more left to send */
1806 120660 : SRF_RETURN_NEXT(funcctx, NumericGetDatum(result));
1807 : }
1808 : else
1809 : /* do when there is no more left */
1810 132 : SRF_RETURN_DONE(funcctx);
1811 : }
1812 :
1813 : /*
1814 : * Planner support function for generate_series(numeric, numeric [, numeric])
1815 : */
1816 : Datum
1817 642 : generate_series_numeric_support(PG_FUNCTION_ARGS)
1818 : {
1819 642 : Node *rawreq = (Node *) PG_GETARG_POINTER(0);
1820 642 : Node *ret = NULL;
1821 :
1822 642 : if (IsA(rawreq, SupportRequestRows))
1823 : {
1824 : /* Try to estimate the number of rows returned */
1825 156 : SupportRequestRows *req = (SupportRequestRows *) rawreq;
1826 :
1827 156 : if (is_funcclause(req->node)) /* be paranoid */
1828 : {
1829 156 : List *args = ((FuncExpr *) req->node)->args;
1830 : Node *arg1,
1831 : *arg2,
1832 : *arg3;
1833 :
1834 : /* We can use estimated argument values here */
1835 156 : arg1 = estimate_expression_value(req->root, linitial(args));
1836 156 : arg2 = estimate_expression_value(req->root, lsecond(args));
1837 156 : if (list_length(args) >= 3)
1838 102 : arg3 = estimate_expression_value(req->root, lthird(args));
1839 : else
1840 54 : arg3 = NULL;
1841 :
1842 : /*
1843 : * If any argument is constant NULL, we can safely assume that
1844 : * zero rows are returned. Otherwise, if they're all non-NULL
1845 : * constants, we can calculate the number of rows that will be
1846 : * returned.
1847 : */
1848 156 : if ((IsA(arg1, Const) &&
1849 150 : ((Const *) arg1)->constisnull) ||
1850 156 : (IsA(arg2, Const) &&
1851 156 : ((Const *) arg2)->constisnull) ||
1852 102 : (arg3 != NULL && IsA(arg3, Const) &&
1853 96 : ((Const *) arg3)->constisnull))
1854 : {
1855 0 : req->rows = 0;
1856 0 : ret = (Node *) req;
1857 : }
1858 156 : else if (IsA(arg1, Const) &&
1859 150 : IsA(arg2, Const) &&
1860 102 : (arg3 == NULL || IsA(arg3, Const)))
1861 : {
1862 : Numeric start_num;
1863 : Numeric stop_num;
1864 138 : NumericVar step = const_one;
1865 :
1866 : /*
1867 : * If any argument is NaN or infinity, generate_series() will
1868 : * error out, so we needn't produce an estimate.
1869 : */
1870 138 : start_num = DatumGetNumeric(((Const *) arg1)->constvalue);
1871 138 : stop_num = DatumGetNumeric(((Const *) arg2)->constvalue);
1872 :
1873 138 : if (NUMERIC_IS_SPECIAL(start_num) ||
1874 120 : NUMERIC_IS_SPECIAL(stop_num))
1875 48 : PG_RETURN_POINTER(NULL);
1876 :
1877 108 : if (arg3)
1878 : {
1879 : Numeric step_num;
1880 :
1881 66 : step_num = DatumGetNumeric(((Const *) arg3)->constvalue);
1882 :
1883 66 : if (NUMERIC_IS_SPECIAL(step_num))
1884 18 : PG_RETURN_POINTER(NULL);
1885 :
1886 48 : init_var_from_num(step_num, &step);
1887 : }
1888 :
1889 : /*
1890 : * The number of rows that will be returned is given by
1891 : * floor((stop - start) / step) + 1, if the sign of step
1892 : * matches the sign of stop - start. Otherwise, no rows will
1893 : * be returned.
1894 : */
1895 90 : if (cmp_var(&step, &const_zero) != 0)
1896 : {
1897 : NumericVar start;
1898 : NumericVar stop;
1899 : NumericVar res;
1900 :
1901 78 : init_var_from_num(start_num, &start);
1902 78 : init_var_from_num(stop_num, &stop);
1903 :
1904 78 : init_var(&res);
1905 78 : sub_var(&stop, &start, &res);
1906 :
1907 78 : if (step.sign != res.sign)
1908 : {
1909 : /* no rows will be returned */
1910 6 : req->rows = 0;
1911 6 : ret = (Node *) req;
1912 : }
1913 : else
1914 : {
1915 72 : if (arg3)
1916 30 : div_var(&res, &step, &res, 0, false, false);
1917 : else
1918 42 : trunc_var(&res, 0); /* step = 1 */
1919 :
1920 72 : req->rows = numericvar_to_double_no_overflow(&res) + 1;
1921 72 : ret = (Node *) req;
1922 : }
1923 :
1924 78 : free_var(&res);
1925 : }
1926 : }
1927 : }
1928 : }
1929 :
1930 594 : PG_RETURN_POINTER(ret);
1931 : }
1932 :
1933 :
1934 : /*
1935 : * Implements the numeric version of the width_bucket() function
1936 : * defined by SQL2003. See also width_bucket_float8().
1937 : *
1938 : * 'bound1' and 'bound2' are the lower and upper bounds of the
1939 : * histogram's range, respectively. 'count' is the number of buckets
1940 : * in the histogram. width_bucket() returns an integer indicating the
1941 : * bucket number that 'operand' belongs to in an equiwidth histogram
1942 : * with the specified characteristics. An operand smaller than the
1943 : * lower bound is assigned to bucket 0. An operand greater than or equal
1944 : * to the upper bound is assigned to an additional bucket (with number
1945 : * count+1). We don't allow the histogram bounds to be NaN or +/- infinity,
1946 : * but we do allow those values for the operand (taking NaN to be larger
1947 : * than any other value, as we do in comparisons).
1948 : */
1949 : Datum
1950 786 : width_bucket_numeric(PG_FUNCTION_ARGS)
1951 : {
1952 786 : Numeric operand = PG_GETARG_NUMERIC(0);
1953 786 : Numeric bound1 = PG_GETARG_NUMERIC(1);
1954 786 : Numeric bound2 = PG_GETARG_NUMERIC(2);
1955 786 : int32 count = PG_GETARG_INT32(3);
1956 : NumericVar count_var;
1957 : NumericVar result_var;
1958 : int32 result;
1959 :
1960 786 : if (count <= 0)
1961 12 : ereport(ERROR,
1962 : (errcode(ERRCODE_INVALID_ARGUMENT_FOR_WIDTH_BUCKET_FUNCTION),
1963 : errmsg("count must be greater than zero")));
1964 :
1965 774 : if (NUMERIC_IS_SPECIAL(bound1) || NUMERIC_IS_SPECIAL(bound2))
1966 : {
1967 24 : if (NUMERIC_IS_NAN(bound1) || NUMERIC_IS_NAN(bound2))
1968 6 : ereport(ERROR,
1969 : (errcode(ERRCODE_INVALID_ARGUMENT_FOR_WIDTH_BUCKET_FUNCTION),
1970 : errmsg("lower and upper bounds cannot be NaN")));
1971 :
1972 18 : if (NUMERIC_IS_INF(bound1) || NUMERIC_IS_INF(bound2))
1973 18 : ereport(ERROR,
1974 : (errcode(ERRCODE_INVALID_ARGUMENT_FOR_WIDTH_BUCKET_FUNCTION),
1975 : errmsg("lower and upper bounds must be finite")));
1976 : }
1977 :
1978 750 : init_var(&result_var);
1979 750 : init_var(&count_var);
1980 :
1981 : /* Convert 'count' to a numeric, for ease of use later */
1982 750 : int64_to_numericvar((int64) count, &count_var);
1983 :
1984 750 : switch (cmp_numerics(bound1, bound2))
1985 : {
1986 6 : case 0:
1987 6 : ereport(ERROR,
1988 : (errcode(ERRCODE_INVALID_ARGUMENT_FOR_WIDTH_BUCKET_FUNCTION),
1989 : errmsg("lower bound cannot equal upper bound")));
1990 : break;
1991 :
1992 : /* bound1 < bound2 */
1993 552 : case -1:
1994 552 : if (cmp_numerics(operand, bound1) < 0)
1995 114 : set_var_from_var(&const_zero, &result_var);
1996 438 : else if (cmp_numerics(operand, bound2) >= 0)
1997 114 : add_var(&count_var, &const_one, &result_var);
1998 : else
1999 324 : compute_bucket(operand, bound1, bound2, &count_var,
2000 : &result_var);
2001 552 : break;
2002 :
2003 : /* bound1 > bound2 */
2004 192 : case 1:
2005 192 : if (cmp_numerics(operand, bound1) > 0)
2006 12 : set_var_from_var(&const_zero, &result_var);
2007 180 : else if (cmp_numerics(operand, bound2) <= 0)
2008 24 : add_var(&count_var, &const_one, &result_var);
2009 : else
2010 156 : compute_bucket(operand, bound1, bound2, &count_var,
2011 : &result_var);
2012 192 : break;
2013 : }
2014 :
2015 : /* if result exceeds the range of a legal int4, we ereport here */
2016 744 : if (!numericvar_to_int32(&result_var, &result))
2017 0 : ereport(ERROR,
2018 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
2019 : errmsg("integer out of range")));
2020 :
2021 744 : free_var(&count_var);
2022 744 : free_var(&result_var);
2023 :
2024 744 : PG_RETURN_INT32(result);
2025 : }
2026 :
2027 : /*
2028 : * 'operand' is inside the bucket range, so determine the correct
2029 : * bucket for it to go in. The calculations performed by this function
2030 : * are derived directly from the SQL2003 spec. Note however that we
2031 : * multiply by count before dividing, to avoid unnecessary roundoff error.
2032 : */
2033 : static void
2034 480 : compute_bucket(Numeric operand, Numeric bound1, Numeric bound2,
2035 : const NumericVar *count_var, NumericVar *result_var)
2036 : {
2037 : NumericVar bound1_var;
2038 : NumericVar bound2_var;
2039 : NumericVar operand_var;
2040 :
2041 480 : init_var_from_num(bound1, &bound1_var);
2042 480 : init_var_from_num(bound2, &bound2_var);
2043 480 : init_var_from_num(operand, &operand_var);
2044 :
2045 : /*
2046 : * Per spec, bound1 is inclusive and bound2 is exclusive, and so we have
2047 : * bound1 <= operand < bound2 or bound1 >= operand > bound2. Either way,
2048 : * the result is ((operand - bound1) * count) / (bound2 - bound1) + 1,
2049 : * where the quotient is computed using floor division (i.e., division to
2050 : * zero decimal places with truncation), which guarantees that the result
2051 : * is in the range [1, count]. Reversing the bounds doesn't affect the
2052 : * computation, because the signs cancel out when dividing.
2053 : */
2054 480 : sub_var(&operand_var, &bound1_var, &operand_var);
2055 480 : sub_var(&bound2_var, &bound1_var, &bound2_var);
2056 :
2057 480 : mul_var(&operand_var, count_var, &operand_var,
2058 480 : operand_var.dscale + count_var->dscale);
2059 480 : div_var(&operand_var, &bound2_var, result_var, 0, false, true);
2060 480 : add_var(result_var, &const_one, result_var);
2061 :
2062 480 : free_var(&bound1_var);
2063 480 : free_var(&bound2_var);
2064 480 : free_var(&operand_var);
2065 480 : }
2066 :
2067 : /* ----------------------------------------------------------------------
2068 : *
2069 : * Comparison functions
2070 : *
2071 : * Note: btree indexes need these routines not to leak memory; therefore,
2072 : * be careful to free working copies of toasted datums. Most places don't
2073 : * need to be so careful.
2074 : *
2075 : * Sort support:
2076 : *
2077 : * We implement the sortsupport strategy routine in order to get the benefit of
2078 : * abbreviation. The ordinary numeric comparison can be quite slow as a result
2079 : * of palloc/pfree cycles (due to detoasting packed values for alignment);
2080 : * while this could be worked on itself, the abbreviation strategy gives more
2081 : * speedup in many common cases.
2082 : *
2083 : * The abbreviated format is an int64. The representation is negated relative
2084 : * to the original value, because we use the largest negative value for NaN,
2085 : * which sorts higher than other values. We convert the absolute value of the
2086 : * numeric to a 63-bit positive value, and then negate it if the original
2087 : * number was positive.
2088 : *
2089 : * We abort the abbreviation process if the abbreviation cardinality is below
2090 : * 0.01% of the row count (1 per 10k non-null rows). The actual break-even
2091 : * point is somewhat below that, perhaps 1 per 30k (at 1 per 100k there's a
2092 : * very small penalty), but we don't want to build up too many abbreviated
2093 : * values before first testing for abort, so we take the slightly pessimistic
2094 : * number. We make no attempt to estimate the cardinality of the real values,
2095 : * since it plays no part in the cost model here (if the abbreviation is equal,
2096 : * the cost of comparing equal and unequal underlying values is comparable).
2097 : * We discontinue even checking for abort (saving us the hashing overhead) if
2098 : * the estimated cardinality gets to 100k; that would be enough to support many
2099 : * billions of rows while doing no worse than breaking even.
2100 : *
2101 : * ----------------------------------------------------------------------
2102 : */
2103 :
2104 : /*
2105 : * Sort support strategy routine.
2106 : */
2107 : Datum
2108 1202 : numeric_sortsupport(PG_FUNCTION_ARGS)
2109 : {
2110 1202 : SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0);
2111 :
2112 1202 : ssup->comparator = numeric_fast_cmp;
2113 :
2114 1202 : if (ssup->abbreviate)
2115 : {
2116 : NumericSortSupport *nss;
2117 262 : MemoryContext oldcontext = MemoryContextSwitchTo(ssup->ssup_cxt);
2118 :
2119 262 : nss = palloc_object(NumericSortSupport);
2120 :
2121 : /*
2122 : * palloc a buffer for handling unaligned packed values in addition to
2123 : * the support struct
2124 : */
2125 262 : nss->buf = palloc(VARATT_SHORT_MAX + VARHDRSZ + 1);
2126 :
2127 262 : nss->input_count = 0;
2128 262 : nss->estimating = true;
2129 262 : initHyperLogLog(&nss->abbr_card, 10);
2130 :
2131 262 : ssup->ssup_extra = nss;
2132 :
2133 262 : ssup->abbrev_full_comparator = ssup->comparator;
2134 262 : ssup->comparator = numeric_cmp_abbrev;
2135 262 : ssup->abbrev_converter = numeric_abbrev_convert;
2136 262 : ssup->abbrev_abort = numeric_abbrev_abort;
2137 :
2138 262 : MemoryContextSwitchTo(oldcontext);
2139 : }
2140 :
2141 1202 : PG_RETURN_VOID();
2142 : }
2143 :
2144 : /*
2145 : * Abbreviate a numeric datum, handling NaNs and detoasting
2146 : * (must not leak memory!)
2147 : */
2148 : static Datum
2149 19168 : numeric_abbrev_convert(Datum original_datum, SortSupport ssup)
2150 : {
2151 19168 : NumericSortSupport *nss = ssup->ssup_extra;
2152 19168 : void *original_varatt = PG_DETOAST_DATUM_PACKED(original_datum);
2153 : Numeric value;
2154 : Datum result;
2155 :
2156 19168 : nss->input_count += 1;
2157 :
2158 : /*
2159 : * This is to handle packed datums without needing a palloc/pfree cycle;
2160 : * we keep and reuse a buffer large enough to handle any short datum.
2161 : */
2162 19168 : if (VARATT_IS_SHORT(original_varatt))
2163 : {
2164 1026 : void *buf = nss->buf;
2165 1026 : Size sz = VARSIZE_SHORT(original_varatt) - VARHDRSZ_SHORT;
2166 :
2167 : Assert(sz <= VARATT_SHORT_MAX - VARHDRSZ_SHORT);
2168 :
2169 1026 : SET_VARSIZE(buf, VARHDRSZ + sz);
2170 1026 : memcpy(VARDATA(buf), VARDATA_SHORT(original_varatt), sz);
2171 :
2172 1026 : value = (Numeric) buf;
2173 : }
2174 : else
2175 18142 : value = (Numeric) original_varatt;
2176 :
2177 19168 : if (NUMERIC_IS_SPECIAL(value))
2178 : {
2179 150 : if (NUMERIC_IS_PINF(value))
2180 48 : result = NUMERIC_ABBREV_PINF;
2181 102 : else if (NUMERIC_IS_NINF(value))
2182 48 : result = NUMERIC_ABBREV_NINF;
2183 : else
2184 54 : result = NUMERIC_ABBREV_NAN;
2185 : }
2186 : else
2187 : {
2188 : NumericVar var;
2189 :
2190 19018 : init_var_from_num(value, &var);
2191 :
2192 19018 : result = numeric_abbrev_convert_var(&var, nss);
2193 : }
2194 :
2195 : /* should happen only for external/compressed toasts */
2196 19168 : if (original_varatt != DatumGetPointer(original_datum))
2197 0 : pfree(original_varatt);
2198 :
2199 19168 : return result;
2200 : }
2201 :
2202 : /*
2203 : * Consider whether to abort abbreviation.
2204 : *
2205 : * We pay no attention to the cardinality of the non-abbreviated data. There is
2206 : * no reason to do so: unlike text, we have no fast check for equal values, so
2207 : * we pay the full overhead whenever the abbreviations are equal regardless of
2208 : * whether the underlying values are also equal.
2209 : */
2210 : static bool
2211 144 : numeric_abbrev_abort(int memtupcount, SortSupport ssup)
2212 : {
2213 144 : NumericSortSupport *nss = ssup->ssup_extra;
2214 : double abbr_card;
2215 :
2216 144 : if (memtupcount < 10000 || nss->input_count < 10000 || !nss->estimating)
2217 144 : return false;
2218 :
2219 0 : abbr_card = estimateHyperLogLog(&nss->abbr_card);
2220 :
2221 : /*
2222 : * If we have >100k distinct values, then even if we were sorting many
2223 : * billion rows we'd likely still break even, and the penalty of undoing
2224 : * that many rows of abbrevs would probably not be worth it. Stop even
2225 : * counting at that point.
2226 : */
2227 0 : if (abbr_card > 100000.0)
2228 : {
2229 0 : if (trace_sort)
2230 0 : elog(LOG,
2231 : "numeric_abbrev: estimation ends at cardinality %f"
2232 : " after " INT64_FORMAT " values (%d rows)",
2233 : abbr_card, nss->input_count, memtupcount);
2234 0 : nss->estimating = false;
2235 0 : return false;
2236 : }
2237 :
2238 : /*
2239 : * Target minimum cardinality is 1 per ~10k of non-null inputs. (The
2240 : * break even point is somewhere between one per 100k rows, where
2241 : * abbreviation has a very slight penalty, and 1 per 10k where it wins by
2242 : * a measurable percentage.) We use the relatively pessimistic 10k
2243 : * threshold, and add a 0.5 row fudge factor, because it allows us to
2244 : * abort earlier on genuinely pathological data where we've had exactly
2245 : * one abbreviated value in the first 10k (non-null) rows.
2246 : */
2247 0 : if (abbr_card < nss->input_count / 10000.0 + 0.5)
2248 : {
2249 0 : if (trace_sort)
2250 0 : elog(LOG,
2251 : "numeric_abbrev: aborting abbreviation at cardinality %f"
2252 : " below threshold %f after " INT64_FORMAT " values (%d rows)",
2253 : abbr_card, nss->input_count / 10000.0 + 0.5,
2254 : nss->input_count, memtupcount);
2255 0 : return true;
2256 : }
2257 :
2258 0 : if (trace_sort)
2259 0 : elog(LOG,
2260 : "numeric_abbrev: cardinality %f"
2261 : " after " INT64_FORMAT " values (%d rows)",
2262 : abbr_card, nss->input_count, memtupcount);
2263 :
2264 0 : return false;
2265 : }
2266 :
2267 : /*
2268 : * Non-fmgr interface to the comparison routine to allow sortsupport to elide
2269 : * the fmgr call. The saving here is small given how slow numeric comparisons
2270 : * are, but it is a required part of the sort support API when abbreviations
2271 : * are performed.
2272 : *
2273 : * Two palloc/pfree cycles could be saved here by using persistent buffers for
2274 : * aligning short-varlena inputs, but this has not so far been considered to
2275 : * be worth the effort.
2276 : */
2277 : static int
2278 25841764 : numeric_fast_cmp(Datum x, Datum y, SortSupport ssup)
2279 : {
2280 25841764 : Numeric nx = DatumGetNumeric(x);
2281 25841764 : Numeric ny = DatumGetNumeric(y);
2282 : int result;
2283 :
2284 25841764 : result = cmp_numerics(nx, ny);
2285 :
2286 25841764 : if (nx != DatumGetPointer(x))
2287 11139510 : pfree(nx);
2288 25841764 : if (ny != DatumGetPointer(y))
2289 11139504 : pfree(ny);
2290 :
2291 25841764 : return result;
2292 : }
2293 :
2294 : /*
2295 : * Compare abbreviations of values. (Abbreviations may be equal where the true
2296 : * values differ, but if the abbreviations differ, they must reflect the
2297 : * ordering of the true values.)
2298 : */
2299 : static int
2300 189012 : numeric_cmp_abbrev(Datum x, Datum y, SortSupport ssup)
2301 : {
2302 : /*
2303 : * NOTE WELL: this is intentionally backwards, because the abbreviation is
2304 : * negated relative to the original value, to handle NaN/infinity cases.
2305 : */
2306 189012 : if (DatumGetNumericAbbrev(x) < DatumGetNumericAbbrev(y))
2307 98148 : return 1;
2308 90864 : if (DatumGetNumericAbbrev(x) > DatumGetNumericAbbrev(y))
2309 90642 : return -1;
2310 222 : return 0;
2311 : }
2312 :
2313 : /*
2314 : * Abbreviate a NumericVar into the 64-bit sortsupport size.
2315 : *
2316 : * The 31-bit value is constructed as:
2317 : *
2318 : * 0 + 7bits digit weight + 24 bits digit value
2319 : *
2320 : * where the digit weight is in single decimal digits, not digit words, and
2321 : * stored in excess-44 representation[1]. The 24-bit digit value is the 7 most
2322 : * significant decimal digits of the value converted to binary. Values whose
2323 : * weights would fall outside the representable range are rounded off to zero
2324 : * (which is also used to represent actual zeros) or to 0x7FFFFFFF (which
2325 : * otherwise cannot occur). Abbreviation therefore fails to gain any advantage
2326 : * where values are outside the range 10^-44 to 10^83, which is not considered
2327 : * to be a serious limitation, or when values are of the same magnitude and
2328 : * equal in the first 7 decimal digits, which is considered to be an
2329 : * unavoidable limitation given the available bits. (Stealing three more bits
2330 : * to compare another digit would narrow the range of representable weights by
2331 : * a factor of 8, which starts to look like a real limiting factor.)
2332 : *
2333 : * (The value 44 for the excess is essentially arbitrary)
2334 : *
2335 : * The 63-bit value is constructed as:
2336 : *
2337 : * 0 + 7bits weight + 4 x 14-bit packed digit words
2338 : *
2339 : * The weight in this case is again stored in excess-44, but this time it is
2340 : * the original weight in digit words (i.e. powers of 10000). The first four
2341 : * digit words of the value (if present; trailing zeros are assumed as needed)
2342 : * are packed into 14 bits each to form the rest of the value. Again,
2343 : * out-of-range values are rounded off to 0 or 0x7FFFFFFFFFFFFFFF. The
2344 : * representable range in this case is 10^-176 to 10^332, which is considered
2345 : * to be good enough for all practical purposes, and comparison of 4 words
2346 : * means that at least 13 decimal digits are compared, which is considered to
2347 : * be a reasonable compromise between effectiveness and efficiency in computing
2348 : * the abbreviation.
2349 : *
2350 : * (The value 44 for the excess is even more arbitrary here, it was chosen just
2351 : * to match the value used in the 31-bit case)
2352 : *
2353 : * [1] - Excess-k representation means that the value is offset by adding 'k'
2354 : * and then treated as unsigned, so the smallest representable value is stored
2355 : * with all bits zero. This allows simple comparisons to work on the composite
2356 : * value.
2357 : */
2358 : static Datum
2359 19018 : numeric_abbrev_convert_var(const NumericVar *var, NumericSortSupport *nss)
2360 : {
2361 19018 : int ndigits = var->ndigits;
2362 19018 : int weight = var->weight;
2363 : int64 result;
2364 :
2365 19018 : if (ndigits == 0 || weight < -44)
2366 : {
2367 52 : result = 0;
2368 : }
2369 18966 : else if (weight > 83)
2370 : {
2371 12 : result = PG_INT64_MAX;
2372 : }
2373 : else
2374 : {
2375 18954 : result = ((int64) (weight + 44) << 56);
2376 :
2377 18954 : switch (ndigits)
2378 : {
2379 0 : default:
2380 0 : result |= ((int64) var->digits[3]);
2381 : /* FALLTHROUGH */
2382 6206 : case 3:
2383 6206 : result |= ((int64) var->digits[2]) << 14;
2384 : /* FALLTHROUGH */
2385 18328 : case 2:
2386 18328 : result |= ((int64) var->digits[1]) << 28;
2387 : /* FALLTHROUGH */
2388 18954 : case 1:
2389 18954 : result |= ((int64) var->digits[0]) << 42;
2390 18954 : break;
2391 : }
2392 : }
2393 :
2394 : /* the abbrev is negated relative to the original */
2395 19018 : if (var->sign == NUMERIC_POS)
2396 18920 : result = -result;
2397 :
2398 19018 : if (nss->estimating)
2399 : {
2400 19018 : uint32 tmp = ((uint32) result
2401 19018 : ^ (uint32) ((uint64) result >> 32));
2402 :
2403 19018 : addHyperLogLog(&nss->abbr_card, DatumGetUInt32(hash_uint32(tmp)));
2404 : }
2405 :
2406 19018 : return NumericAbbrevGetDatum(result);
2407 : }
2408 :
2409 :
2410 : /*
2411 : * Ordinary (non-sortsupport) comparisons follow.
2412 : */
2413 :
2414 : Datum
2415 758572 : numeric_cmp(PG_FUNCTION_ARGS)
2416 : {
2417 758572 : Numeric num1 = PG_GETARG_NUMERIC(0);
2418 758572 : Numeric num2 = PG_GETARG_NUMERIC(1);
2419 : int result;
2420 :
2421 758572 : result = cmp_numerics(num1, num2);
2422 :
2423 758572 : PG_FREE_IF_COPY(num1, 0);
2424 758572 : PG_FREE_IF_COPY(num2, 1);
2425 :
2426 758572 : PG_RETURN_INT32(result);
2427 : }
2428 :
2429 :
2430 : Datum
2431 650560 : numeric_eq(PG_FUNCTION_ARGS)
2432 : {
2433 650560 : Numeric num1 = PG_GETARG_NUMERIC(0);
2434 650560 : Numeric num2 = PG_GETARG_NUMERIC(1);
2435 : bool result;
2436 :
2437 650560 : result = cmp_numerics(num1, num2) == 0;
2438 :
2439 650560 : PG_FREE_IF_COPY(num1, 0);
2440 650560 : PG_FREE_IF_COPY(num2, 1);
2441 :
2442 650560 : PG_RETURN_BOOL(result);
2443 : }
2444 :
2445 : Datum
2446 5376 : numeric_ne(PG_FUNCTION_ARGS)
2447 : {
2448 5376 : Numeric num1 = PG_GETARG_NUMERIC(0);
2449 5376 : Numeric num2 = PG_GETARG_NUMERIC(1);
2450 : bool result;
2451 :
2452 5376 : result = cmp_numerics(num1, num2) != 0;
2453 :
2454 5376 : PG_FREE_IF_COPY(num1, 0);
2455 5376 : PG_FREE_IF_COPY(num2, 1);
2456 :
2457 5376 : PG_RETURN_BOOL(result);
2458 : }
2459 :
2460 : Datum
2461 55676 : numeric_gt(PG_FUNCTION_ARGS)
2462 : {
2463 55676 : Numeric num1 = PG_GETARG_NUMERIC(0);
2464 55676 : Numeric num2 = PG_GETARG_NUMERIC(1);
2465 : bool result;
2466 :
2467 55676 : result = cmp_numerics(num1, num2) > 0;
2468 :
2469 55676 : PG_FREE_IF_COPY(num1, 0);
2470 55676 : PG_FREE_IF_COPY(num2, 1);
2471 :
2472 55676 : PG_RETURN_BOOL(result);
2473 : }
2474 :
2475 : Datum
2476 15012 : numeric_ge(PG_FUNCTION_ARGS)
2477 : {
2478 15012 : Numeric num1 = PG_GETARG_NUMERIC(0);
2479 15012 : Numeric num2 = PG_GETARG_NUMERIC(1);
2480 : bool result;
2481 :
2482 15012 : result = cmp_numerics(num1, num2) >= 0;
2483 :
2484 15012 : PG_FREE_IF_COPY(num1, 0);
2485 15012 : PG_FREE_IF_COPY(num2, 1);
2486 :
2487 15012 : PG_RETURN_BOOL(result);
2488 : }
2489 :
2490 : Datum
2491 299282 : numeric_lt(PG_FUNCTION_ARGS)
2492 : {
2493 299282 : Numeric num1 = PG_GETARG_NUMERIC(0);
2494 299282 : Numeric num2 = PG_GETARG_NUMERIC(1);
2495 : bool result;
2496 :
2497 299282 : result = cmp_numerics(num1, num2) < 0;
2498 :
2499 299282 : PG_FREE_IF_COPY(num1, 0);
2500 299282 : PG_FREE_IF_COPY(num2, 1);
2501 :
2502 299282 : PG_RETURN_BOOL(result);
2503 : }
2504 :
2505 : Datum
2506 16888 : numeric_le(PG_FUNCTION_ARGS)
2507 : {
2508 16888 : Numeric num1 = PG_GETARG_NUMERIC(0);
2509 16888 : Numeric num2 = PG_GETARG_NUMERIC(1);
2510 : bool result;
2511 :
2512 16888 : result = cmp_numerics(num1, num2) <= 0;
2513 :
2514 16888 : PG_FREE_IF_COPY(num1, 0);
2515 16888 : PG_FREE_IF_COPY(num2, 1);
2516 :
2517 16888 : PG_RETURN_BOOL(result);
2518 : }
2519 :
2520 : static int
2521 27664682 : cmp_numerics(Numeric num1, Numeric num2)
2522 : {
2523 : int result;
2524 :
2525 : /*
2526 : * We consider all NANs to be equal and larger than any non-NAN (including
2527 : * Infinity). This is somewhat arbitrary; the important thing is to have
2528 : * a consistent sort order.
2529 : */
2530 27664682 : if (NUMERIC_IS_SPECIAL(num1))
2531 : {
2532 6236 : if (NUMERIC_IS_NAN(num1))
2533 : {
2534 6146 : if (NUMERIC_IS_NAN(num2))
2535 748 : result = 0; /* NAN = NAN */
2536 : else
2537 5398 : result = 1; /* NAN > non-NAN */
2538 : }
2539 90 : else if (NUMERIC_IS_PINF(num1))
2540 : {
2541 72 : if (NUMERIC_IS_NAN(num2))
2542 0 : result = -1; /* PINF < NAN */
2543 72 : else if (NUMERIC_IS_PINF(num2))
2544 6 : result = 0; /* PINF = PINF */
2545 : else
2546 66 : result = 1; /* PINF > anything else */
2547 : }
2548 : else /* num1 must be NINF */
2549 : {
2550 18 : if (NUMERIC_IS_NINF(num2))
2551 6 : result = 0; /* NINF = NINF */
2552 : else
2553 12 : result = -1; /* NINF < anything else */
2554 : }
2555 : }
2556 27658446 : else if (NUMERIC_IS_SPECIAL(num2))
2557 : {
2558 11156 : if (NUMERIC_IS_NINF(num2))
2559 12 : result = 1; /* normal > NINF */
2560 : else
2561 11144 : result = -1; /* normal < NAN or PINF */
2562 : }
2563 : else
2564 : {
2565 55295608 : result = cmp_var_common(NUMERIC_DIGITS(num1), NUMERIC_NDIGITS(num1),
2566 27647592 : NUMERIC_WEIGHT(num1), NUMERIC_SIGN(num1),
2567 27647290 : NUMERIC_DIGITS(num2), NUMERIC_NDIGITS(num2),
2568 27648016 : NUMERIC_WEIGHT(num2), NUMERIC_SIGN(num2));
2569 : }
2570 :
2571 27664682 : return result;
2572 : }
2573 :
2574 : /*
2575 : * in_range support function for numeric.
2576 : */
2577 : Datum
2578 1152 : in_range_numeric_numeric(PG_FUNCTION_ARGS)
2579 : {
2580 1152 : Numeric val = PG_GETARG_NUMERIC(0);
2581 1152 : Numeric base = PG_GETARG_NUMERIC(1);
2582 1152 : Numeric offset = PG_GETARG_NUMERIC(2);
2583 1152 : bool sub = PG_GETARG_BOOL(3);
2584 1152 : bool less = PG_GETARG_BOOL(4);
2585 : bool result;
2586 :
2587 : /*
2588 : * Reject negative (including -Inf) or NaN offset. Negative is per spec,
2589 : * and NaN is because appropriate semantics for that seem non-obvious.
2590 : */
2591 1152 : if (NUMERIC_IS_NAN(offset) ||
2592 1146 : NUMERIC_IS_NINF(offset) ||
2593 1146 : NUMERIC_SIGN(offset) == NUMERIC_NEG)
2594 6 : ereport(ERROR,
2595 : (errcode(ERRCODE_INVALID_PRECEDING_OR_FOLLOWING_SIZE),
2596 : errmsg("invalid preceding or following size in window function")));
2597 :
2598 : /*
2599 : * Deal with cases where val and/or base is NaN, following the rule that
2600 : * NaN sorts after non-NaN (cf cmp_numerics). The offset cannot affect
2601 : * the conclusion.
2602 : */
2603 1146 : if (NUMERIC_IS_NAN(val))
2604 : {
2605 186 : if (NUMERIC_IS_NAN(base))
2606 60 : result = true; /* NAN = NAN */
2607 : else
2608 126 : result = !less; /* NAN > non-NAN */
2609 : }
2610 960 : else if (NUMERIC_IS_NAN(base))
2611 : {
2612 126 : result = less; /* non-NAN < NAN */
2613 : }
2614 :
2615 : /*
2616 : * Deal with infinite offset (necessarily +Inf, at this point).
2617 : */
2618 834 : else if (NUMERIC_IS_SPECIAL(offset))
2619 : {
2620 : Assert(NUMERIC_IS_PINF(offset));
2621 420 : if (sub ? NUMERIC_IS_PINF(base) : NUMERIC_IS_NINF(base))
2622 : {
2623 : /*
2624 : * base +/- offset would produce NaN, so return true for any val
2625 : * (see in_range_float8_float8() for reasoning).
2626 : */
2627 174 : result = true;
2628 : }
2629 246 : else if (sub)
2630 : {
2631 : /* base - offset must be -inf */
2632 150 : if (less)
2633 54 : result = NUMERIC_IS_NINF(val); /* only -inf is <= sum */
2634 : else
2635 96 : result = true; /* any val is >= sum */
2636 : }
2637 : else
2638 : {
2639 : /* base + offset must be +inf */
2640 96 : if (less)
2641 0 : result = true; /* any val is <= sum */
2642 : else
2643 96 : result = NUMERIC_IS_PINF(val); /* only +inf is >= sum */
2644 : }
2645 : }
2646 :
2647 : /*
2648 : * Deal with cases where val and/or base is infinite. The offset, being
2649 : * now known finite, cannot affect the conclusion.
2650 : */
2651 414 : else if (NUMERIC_IS_SPECIAL(val))
2652 : {
2653 78 : if (NUMERIC_IS_PINF(val))
2654 : {
2655 36 : if (NUMERIC_IS_PINF(base))
2656 24 : result = true; /* PINF = PINF */
2657 : else
2658 12 : result = !less; /* PINF > any other non-NAN */
2659 : }
2660 : else /* val must be NINF */
2661 : {
2662 42 : if (NUMERIC_IS_NINF(base))
2663 30 : result = true; /* NINF = NINF */
2664 : else
2665 12 : result = less; /* NINF < anything else */
2666 : }
2667 : }
2668 336 : else if (NUMERIC_IS_SPECIAL(base))
2669 : {
2670 24 : if (NUMERIC_IS_NINF(base))
2671 12 : result = !less; /* normal > NINF */
2672 : else
2673 12 : result = less; /* normal < PINF */
2674 : }
2675 : else
2676 : {
2677 : /*
2678 : * Otherwise go ahead and compute base +/- offset. While it's
2679 : * possible for this to overflow the numeric format, it's unlikely
2680 : * enough that we don't take measures to prevent it.
2681 : */
2682 : NumericVar valv;
2683 : NumericVar basev;
2684 : NumericVar offsetv;
2685 : NumericVar sum;
2686 :
2687 312 : init_var_from_num(val, &valv);
2688 312 : init_var_from_num(base, &basev);
2689 312 : init_var_from_num(offset, &offsetv);
2690 312 : init_var(&sum);
2691 :
2692 312 : if (sub)
2693 156 : sub_var(&basev, &offsetv, &sum);
2694 : else
2695 156 : add_var(&basev, &offsetv, &sum);
2696 :
2697 312 : if (less)
2698 156 : result = (cmp_var(&valv, &sum) <= 0);
2699 : else
2700 156 : result = (cmp_var(&valv, &sum) >= 0);
2701 :
2702 312 : free_var(&sum);
2703 : }
2704 :
2705 1146 : PG_FREE_IF_COPY(val, 0);
2706 1146 : PG_FREE_IF_COPY(base, 1);
2707 1146 : PG_FREE_IF_COPY(offset, 2);
2708 :
2709 1146 : PG_RETURN_BOOL(result);
2710 : }
2711 :
2712 : Datum
2713 607540 : hash_numeric(PG_FUNCTION_ARGS)
2714 : {
2715 607540 : Numeric key = PG_GETARG_NUMERIC(0);
2716 : Datum digit_hash;
2717 : Datum result;
2718 : int weight;
2719 : int start_offset;
2720 : int end_offset;
2721 : int i;
2722 : int hash_len;
2723 : NumericDigit *digits;
2724 :
2725 : /* If it's NaN or infinity, don't try to hash the rest of the fields */
2726 607540 : if (NUMERIC_IS_SPECIAL(key))
2727 0 : PG_RETURN_UINT32(0);
2728 :
2729 607540 : weight = NUMERIC_WEIGHT(key);
2730 607540 : start_offset = 0;
2731 607540 : end_offset = 0;
2732 :
2733 : /*
2734 : * Omit any leading or trailing zeros from the input to the hash. The
2735 : * numeric implementation *should* guarantee that leading and trailing
2736 : * zeros are suppressed, but we're paranoid. Note that we measure the
2737 : * starting and ending offsets in units of NumericDigits, not bytes.
2738 : */
2739 607540 : digits = NUMERIC_DIGITS(key);
2740 607540 : for (i = 0; i < NUMERIC_NDIGITS(key); i++)
2741 : {
2742 605902 : if (digits[i] != (NumericDigit) 0)
2743 605902 : break;
2744 :
2745 0 : start_offset++;
2746 :
2747 : /*
2748 : * The weight is effectively the # of digits before the decimal point,
2749 : * so decrement it for each leading zero we skip.
2750 : */
2751 0 : weight--;
2752 : }
2753 :
2754 : /*
2755 : * If there are no non-zero digits, then the value of the number is zero,
2756 : * regardless of any other fields.
2757 : */
2758 607540 : if (NUMERIC_NDIGITS(key) == start_offset)
2759 1638 : PG_RETURN_UINT32(-1);
2760 :
2761 605902 : for (i = NUMERIC_NDIGITS(key) - 1; i >= 0; i--)
2762 : {
2763 605902 : if (digits[i] != (NumericDigit) 0)
2764 605902 : break;
2765 :
2766 0 : end_offset++;
2767 : }
2768 :
2769 : /* If we get here, there should be at least one non-zero digit */
2770 : Assert(start_offset + end_offset < NUMERIC_NDIGITS(key));
2771 :
2772 : /*
2773 : * Note that we don't hash on the Numeric's scale, since two numerics can
2774 : * compare equal but have different scales. We also don't hash on the
2775 : * sign, although we could: since a sign difference implies inequality,
2776 : * this shouldn't affect correctness.
2777 : */
2778 605902 : hash_len = NUMERIC_NDIGITS(key) - start_offset - end_offset;
2779 605902 : digit_hash = hash_any((unsigned char *) (NUMERIC_DIGITS(key) + start_offset),
2780 : hash_len * sizeof(NumericDigit));
2781 :
2782 : /* Mix in the weight, via XOR */
2783 605902 : result = digit_hash ^ weight;
2784 :
2785 605902 : PG_RETURN_DATUM(result);
2786 : }
2787 :
2788 : /*
2789 : * Returns 64-bit value by hashing a value to a 64-bit value, with a seed.
2790 : * Otherwise, similar to hash_numeric.
2791 : */
2792 : Datum
2793 84 : hash_numeric_extended(PG_FUNCTION_ARGS)
2794 : {
2795 84 : Numeric key = PG_GETARG_NUMERIC(0);
2796 84 : uint64 seed = PG_GETARG_INT64(1);
2797 : Datum digit_hash;
2798 : Datum result;
2799 : int weight;
2800 : int start_offset;
2801 : int end_offset;
2802 : int i;
2803 : int hash_len;
2804 : NumericDigit *digits;
2805 :
2806 : /* If it's NaN or infinity, don't try to hash the rest of the fields */
2807 84 : if (NUMERIC_IS_SPECIAL(key))
2808 0 : PG_RETURN_UINT64(seed);
2809 :
2810 84 : weight = NUMERIC_WEIGHT(key);
2811 84 : start_offset = 0;
2812 84 : end_offset = 0;
2813 :
2814 84 : digits = NUMERIC_DIGITS(key);
2815 84 : for (i = 0; i < NUMERIC_NDIGITS(key); i++)
2816 : {
2817 72 : if (digits[i] != (NumericDigit) 0)
2818 72 : break;
2819 :
2820 0 : start_offset++;
2821 :
2822 0 : weight--;
2823 : }
2824 :
2825 84 : if (NUMERIC_NDIGITS(key) == start_offset)
2826 12 : PG_RETURN_UINT64(seed - 1);
2827 :
2828 72 : for (i = NUMERIC_NDIGITS(key) - 1; i >= 0; i--)
2829 : {
2830 72 : if (digits[i] != (NumericDigit) 0)
2831 72 : break;
2832 :
2833 0 : end_offset++;
2834 : }
2835 :
2836 : Assert(start_offset + end_offset < NUMERIC_NDIGITS(key));
2837 :
2838 72 : hash_len = NUMERIC_NDIGITS(key) - start_offset - end_offset;
2839 72 : digit_hash = hash_any_extended((unsigned char *) (NUMERIC_DIGITS(key)
2840 72 : + start_offset),
2841 : hash_len * sizeof(NumericDigit),
2842 : seed);
2843 :
2844 72 : result = UInt64GetDatum(DatumGetUInt64(digit_hash) ^ weight);
2845 :
2846 72 : PG_RETURN_DATUM(result);
2847 : }
2848 :
2849 :
2850 : /* ----------------------------------------------------------------------
2851 : *
2852 : * Basic arithmetic functions
2853 : *
2854 : * ----------------------------------------------------------------------
2855 : */
2856 :
2857 :
2858 : /*
2859 : * numeric_add() -
2860 : *
2861 : * Add two numerics
2862 : */
2863 : Datum
2864 252638 : numeric_add(PG_FUNCTION_ARGS)
2865 : {
2866 252638 : Numeric num1 = PG_GETARG_NUMERIC(0);
2867 252638 : Numeric num2 = PG_GETARG_NUMERIC(1);
2868 : Numeric res;
2869 :
2870 252638 : res = numeric_add_safe(num1, num2, NULL);
2871 :
2872 252638 : PG_RETURN_NUMERIC(res);
2873 : }
2874 :
2875 : /*
2876 : * numeric_add_safe() -
2877 : *
2878 : * Internal version of numeric_add() with support for soft error reporting.
2879 : */
2880 : Numeric
2881 253676 : numeric_add_safe(Numeric num1, Numeric num2, Node *escontext)
2882 : {
2883 : NumericVar arg1;
2884 : NumericVar arg2;
2885 : NumericVar result;
2886 : Numeric res;
2887 :
2888 : /*
2889 : * Handle NaN and infinities
2890 : */
2891 253676 : if (NUMERIC_IS_SPECIAL(num1) || NUMERIC_IS_SPECIAL(num2))
2892 : {
2893 198 : if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
2894 78 : return make_result(&const_nan);
2895 120 : if (NUMERIC_IS_PINF(num1))
2896 : {
2897 36 : if (NUMERIC_IS_NINF(num2))
2898 6 : return make_result(&const_nan); /* Inf + -Inf */
2899 : else
2900 30 : return make_result(&const_pinf);
2901 : }
2902 84 : if (NUMERIC_IS_NINF(num1))
2903 : {
2904 36 : if (NUMERIC_IS_PINF(num2))
2905 6 : return make_result(&const_nan); /* -Inf + Inf */
2906 : else
2907 30 : return make_result(&const_ninf);
2908 : }
2909 : /* by here, num1 must be finite, so num2 is not */
2910 48 : if (NUMERIC_IS_PINF(num2))
2911 24 : return make_result(&const_pinf);
2912 : Assert(NUMERIC_IS_NINF(num2));
2913 24 : return make_result(&const_ninf);
2914 : }
2915 :
2916 : /*
2917 : * Unpack the values, let add_var() compute the result and return it.
2918 : */
2919 253478 : init_var_from_num(num1, &arg1);
2920 253478 : init_var_from_num(num2, &arg2);
2921 :
2922 253478 : init_var(&result);
2923 253478 : add_var(&arg1, &arg2, &result);
2924 :
2925 253478 : res = make_result_safe(&result, escontext);
2926 :
2927 253478 : free_var(&result);
2928 :
2929 253478 : return res;
2930 : }
2931 :
2932 :
2933 : /*
2934 : * numeric_sub() -
2935 : *
2936 : * Subtract one numeric from another
2937 : */
2938 : Datum
2939 75506 : numeric_sub(PG_FUNCTION_ARGS)
2940 : {
2941 75506 : Numeric num1 = PG_GETARG_NUMERIC(0);
2942 75506 : Numeric num2 = PG_GETARG_NUMERIC(1);
2943 : Numeric res;
2944 :
2945 75506 : res = numeric_sub_safe(num1, num2, NULL);
2946 :
2947 75506 : PG_RETURN_NUMERIC(res);
2948 : }
2949 :
2950 :
2951 : /*
2952 : * numeric_sub_safe() -
2953 : *
2954 : * Internal version of numeric_sub() with support for soft error reporting.
2955 : */
2956 : Numeric
2957 75656 : numeric_sub_safe(Numeric num1, Numeric num2, Node *escontext)
2958 : {
2959 : NumericVar arg1;
2960 : NumericVar arg2;
2961 : NumericVar result;
2962 : Numeric res;
2963 :
2964 : /*
2965 : * Handle NaN and infinities
2966 : */
2967 75656 : if (NUMERIC_IS_SPECIAL(num1) || NUMERIC_IS_SPECIAL(num2))
2968 : {
2969 198 : if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
2970 78 : return make_result(&const_nan);
2971 120 : if (NUMERIC_IS_PINF(num1))
2972 : {
2973 36 : if (NUMERIC_IS_PINF(num2))
2974 6 : return make_result(&const_nan); /* Inf - Inf */
2975 : else
2976 30 : return make_result(&const_pinf);
2977 : }
2978 84 : if (NUMERIC_IS_NINF(num1))
2979 : {
2980 36 : if (NUMERIC_IS_NINF(num2))
2981 6 : return make_result(&const_nan); /* -Inf - -Inf */
2982 : else
2983 30 : return make_result(&const_ninf);
2984 : }
2985 : /* by here, num1 must be finite, so num2 is not */
2986 48 : if (NUMERIC_IS_PINF(num2))
2987 24 : return make_result(&const_ninf);
2988 : Assert(NUMERIC_IS_NINF(num2));
2989 24 : return make_result(&const_pinf);
2990 : }
2991 :
2992 : /*
2993 : * Unpack the values, let sub_var() compute the result and return it.
2994 : */
2995 75458 : init_var_from_num(num1, &arg1);
2996 75458 : init_var_from_num(num2, &arg2);
2997 :
2998 75458 : init_var(&result);
2999 75458 : sub_var(&arg1, &arg2, &result);
3000 :
3001 75458 : res = make_result_safe(&result, escontext);
3002 :
3003 75458 : free_var(&result);
3004 :
3005 75458 : return res;
3006 : }
3007 :
3008 :
3009 : /*
3010 : * numeric_mul() -
3011 : *
3012 : * Calculate the product of two numerics
3013 : */
3014 : Datum
3015 490184 : numeric_mul(PG_FUNCTION_ARGS)
3016 : {
3017 490184 : Numeric num1 = PG_GETARG_NUMERIC(0);
3018 490184 : Numeric num2 = PG_GETARG_NUMERIC(1);
3019 : Numeric res;
3020 :
3021 490184 : res = numeric_mul_safe(num1, num2, NULL);
3022 :
3023 490184 : PG_RETURN_NUMERIC(res);
3024 : }
3025 :
3026 :
3027 : /*
3028 : * numeric_mul_safe() -
3029 : *
3030 : * Internal version of numeric_mul() with support for soft error reporting.
3031 : */
3032 : Numeric
3033 490220 : numeric_mul_safe(Numeric num1, Numeric num2, Node *escontext)
3034 : {
3035 : NumericVar arg1;
3036 : NumericVar arg2;
3037 : NumericVar result;
3038 : Numeric res;
3039 :
3040 : /*
3041 : * Handle NaN and infinities
3042 : */
3043 490220 : if (NUMERIC_IS_SPECIAL(num1) || NUMERIC_IS_SPECIAL(num2))
3044 : {
3045 198 : if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
3046 78 : return make_result(&const_nan);
3047 120 : if (NUMERIC_IS_PINF(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_pinf);
3055 12 : case -1:
3056 12 : return make_result(&const_ninf);
3057 : }
3058 : Assert(false);
3059 : }
3060 84 : if (NUMERIC_IS_NINF(num1))
3061 : {
3062 36 : switch (numeric_sign_internal(num2))
3063 : {
3064 6 : case 0:
3065 6 : return make_result(&const_nan); /* -Inf * 0 */
3066 18 : case 1:
3067 18 : return make_result(&const_ninf);
3068 12 : case -1:
3069 12 : return make_result(&const_pinf);
3070 : }
3071 : Assert(false);
3072 : }
3073 : /* by here, num1 must be finite, so num2 is not */
3074 48 : if (NUMERIC_IS_PINF(num2))
3075 : {
3076 24 : switch (numeric_sign_internal(num1))
3077 : {
3078 6 : case 0:
3079 6 : return make_result(&const_nan); /* 0 * Inf */
3080 12 : case 1:
3081 12 : return make_result(&const_pinf);
3082 6 : case -1:
3083 6 : return make_result(&const_ninf);
3084 : }
3085 : Assert(false);
3086 : }
3087 : Assert(NUMERIC_IS_NINF(num2));
3088 24 : switch (numeric_sign_internal(num1))
3089 : {
3090 6 : case 0:
3091 6 : return make_result(&const_nan); /* 0 * -Inf */
3092 12 : case 1:
3093 12 : return make_result(&const_ninf);
3094 6 : case -1:
3095 6 : return make_result(&const_pinf);
3096 : }
3097 : Assert(false);
3098 : }
3099 :
3100 : /*
3101 : * Unpack the values, let mul_var() compute the result and return it.
3102 : * Unlike add_var() and sub_var(), mul_var() will round its result. In the
3103 : * case of numeric_mul(), which is invoked for the * operator on numerics,
3104 : * we request exact representation for the product (rscale = sum(dscale of
3105 : * arg1, dscale of arg2)). If the exact result has more digits after the
3106 : * decimal point than can be stored in a numeric, we round it. Rounding
3107 : * after computing the exact result ensures that the final result is
3108 : * correctly rounded (rounding in mul_var() using a truncated product
3109 : * would not guarantee this).
3110 : */
3111 490022 : init_var_from_num(num1, &arg1);
3112 490022 : init_var_from_num(num2, &arg2);
3113 :
3114 490022 : init_var(&result);
3115 490022 : mul_var(&arg1, &arg2, &result, arg1.dscale + arg2.dscale);
3116 :
3117 490022 : if (result.dscale > NUMERIC_DSCALE_MAX)
3118 6 : round_var(&result, NUMERIC_DSCALE_MAX);
3119 :
3120 490022 : res = make_result_safe(&result, escontext);
3121 :
3122 490022 : free_var(&result);
3123 :
3124 490022 : return res;
3125 : }
3126 :
3127 :
3128 : /*
3129 : * numeric_div() -
3130 : *
3131 : * Divide one numeric into another
3132 : */
3133 : Datum
3134 148320 : numeric_div(PG_FUNCTION_ARGS)
3135 : {
3136 148320 : Numeric num1 = PG_GETARG_NUMERIC(0);
3137 148320 : Numeric num2 = PG_GETARG_NUMERIC(1);
3138 : Numeric res;
3139 :
3140 148320 : res = numeric_div_safe(num1, num2, NULL);
3141 :
3142 148288 : PG_RETURN_NUMERIC(res);
3143 : }
3144 :
3145 :
3146 : /*
3147 : * numeric_div_safe() -
3148 : *
3149 : * Internal version of numeric_div() with support for soft error reporting.
3150 : */
3151 : Numeric
3152 149160 : numeric_div_safe(Numeric num1, Numeric num2, Node *escontext)
3153 : {
3154 : NumericVar arg1;
3155 : NumericVar arg2;
3156 : NumericVar result;
3157 : Numeric res;
3158 : int rscale;
3159 :
3160 : /*
3161 : * Handle NaN and infinities
3162 : */
3163 149160 : if (NUMERIC_IS_SPECIAL(num1) || NUMERIC_IS_SPECIAL(num2))
3164 : {
3165 198 : if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
3166 78 : return make_result(&const_nan);
3167 120 : if (NUMERIC_IS_PINF(num1))
3168 : {
3169 36 : if (NUMERIC_IS_SPECIAL(num2))
3170 12 : return make_result(&const_nan); /* Inf / [-]Inf */
3171 24 : switch (numeric_sign_internal(num2))
3172 : {
3173 6 : case 0:
3174 6 : goto division_by_zero;
3175 12 : case 1:
3176 12 : return make_result(&const_pinf);
3177 6 : case -1:
3178 6 : return make_result(&const_ninf);
3179 : }
3180 : 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 : goto division_by_zero;
3190 12 : case 1:
3191 12 : return make_result(&const_ninf);
3192 6 : case -1:
3193 6 : return make_result(&const_pinf);
3194 : }
3195 : Assert(false);
3196 : }
3197 : /* by here, num1 must be finite, so num2 is not */
3198 :
3199 : /*
3200 : * POSIX would have us return zero or minus zero if num1 is zero, and
3201 : * otherwise throw an underflow error. But the numeric type doesn't
3202 : * really do underflow, so let's just return zero.
3203 : */
3204 48 : return make_result(&const_zero);
3205 : }
3206 :
3207 : /*
3208 : * Unpack the arguments
3209 : */
3210 148962 : init_var_from_num(num1, &arg1);
3211 148962 : init_var_from_num(num2, &arg2);
3212 :
3213 148962 : init_var(&result);
3214 :
3215 : /*
3216 : * Select scale for division result
3217 : */
3218 148962 : rscale = select_div_scale(&arg1, &arg2);
3219 :
3220 : /* Check for division by zero */
3221 148962 : if (arg2.ndigits == 0 || arg2.digits[0] == 0)
3222 50 : goto division_by_zero;
3223 :
3224 : /*
3225 : * Do the divide and return the result
3226 : */
3227 148912 : div_var(&arg1, &arg2, &result, rscale, true, true);
3228 :
3229 148912 : res = make_result_safe(&result, escontext);
3230 :
3231 148912 : free_var(&result);
3232 :
3233 148912 : return res;
3234 :
3235 62 : division_by_zero:
3236 62 : ereturn(escontext, NULL,
3237 : errcode(ERRCODE_DIVISION_BY_ZERO),
3238 : errmsg("division by zero"));
3239 : }
3240 :
3241 :
3242 : /*
3243 : * numeric_div_trunc() -
3244 : *
3245 : * Divide one numeric into another, truncating the result to an integer
3246 : */
3247 : Datum
3248 1218 : numeric_div_trunc(PG_FUNCTION_ARGS)
3249 : {
3250 1218 : Numeric num1 = PG_GETARG_NUMERIC(0);
3251 1218 : Numeric num2 = PG_GETARG_NUMERIC(1);
3252 : NumericVar arg1;
3253 : NumericVar arg2;
3254 : NumericVar result;
3255 : Numeric res;
3256 :
3257 : /*
3258 : * Handle NaN and infinities
3259 : */
3260 1218 : if (NUMERIC_IS_SPECIAL(num1) || NUMERIC_IS_SPECIAL(num2))
3261 : {
3262 198 : if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
3263 78 : PG_RETURN_NUMERIC(make_result(&const_nan));
3264 120 : if (NUMERIC_IS_PINF(num1))
3265 : {
3266 36 : if (NUMERIC_IS_SPECIAL(num2))
3267 12 : PG_RETURN_NUMERIC(make_result(&const_nan)); /* Inf / [-]Inf */
3268 24 : switch (numeric_sign_internal(num2))
3269 : {
3270 6 : case 0:
3271 6 : ereport(ERROR,
3272 : (errcode(ERRCODE_DIVISION_BY_ZERO),
3273 : errmsg("division by zero")));
3274 : break;
3275 12 : case 1:
3276 12 : PG_RETURN_NUMERIC(make_result(&const_pinf));
3277 6 : case -1:
3278 6 : PG_RETURN_NUMERIC(make_result(&const_ninf));
3279 : }
3280 : Assert(false);
3281 : }
3282 84 : if (NUMERIC_IS_NINF(num1))
3283 : {
3284 36 : if (NUMERIC_IS_SPECIAL(num2))
3285 12 : PG_RETURN_NUMERIC(make_result(&const_nan)); /* -Inf / [-]Inf */
3286 24 : switch (numeric_sign_internal(num2))
3287 : {
3288 6 : case 0:
3289 6 : ereport(ERROR,
3290 : (errcode(ERRCODE_DIVISION_BY_ZERO),
3291 : errmsg("division by zero")));
3292 : break;
3293 12 : case 1:
3294 12 : PG_RETURN_NUMERIC(make_result(&const_ninf));
3295 6 : case -1:
3296 6 : PG_RETURN_NUMERIC(make_result(&const_pinf));
3297 : }
3298 : Assert(false);
3299 : }
3300 : /* by here, num1 must be finite, so num2 is not */
3301 :
3302 : /*
3303 : * POSIX would have us return zero or minus zero if num1 is zero, and
3304 : * otherwise throw an underflow error. But the numeric type doesn't
3305 : * really do underflow, so let's just return zero.
3306 : */
3307 48 : PG_RETURN_NUMERIC(make_result(&const_zero));
3308 : }
3309 :
3310 : /*
3311 : * Unpack the arguments
3312 : */
3313 1020 : init_var_from_num(num1, &arg1);
3314 1020 : init_var_from_num(num2, &arg2);
3315 :
3316 1020 : init_var(&result);
3317 :
3318 : /*
3319 : * Do the divide and return the result
3320 : */
3321 1020 : div_var(&arg1, &arg2, &result, 0, false, true);
3322 :
3323 1014 : res = make_result(&result);
3324 :
3325 1014 : free_var(&result);
3326 :
3327 1014 : PG_RETURN_NUMERIC(res);
3328 : }
3329 :
3330 :
3331 : /*
3332 : * numeric_mod() -
3333 : *
3334 : * Calculate the modulo of two numerics
3335 : */
3336 : Datum
3337 413374 : numeric_mod(PG_FUNCTION_ARGS)
3338 : {
3339 413374 : Numeric num1 = PG_GETARG_NUMERIC(0);
3340 413374 : Numeric num2 = PG_GETARG_NUMERIC(1);
3341 : Numeric res;
3342 :
3343 413374 : res = numeric_mod_safe(num1, num2, NULL);
3344 :
3345 413356 : PG_RETURN_NUMERIC(res);
3346 : }
3347 :
3348 :
3349 : /*
3350 : * numeric_mod_safe() -
3351 : *
3352 : * Internal version of numeric_mod() with support for soft error reporting.
3353 : */
3354 : Numeric
3355 413386 : numeric_mod_safe(Numeric num1, Numeric num2, Node *escontext)
3356 : {
3357 : Numeric res;
3358 : NumericVar arg1;
3359 : NumericVar arg2;
3360 : NumericVar result;
3361 :
3362 : /*
3363 : * Handle NaN and infinities. We follow POSIX fmod() on this, except that
3364 : * POSIX treats x-is-infinite and y-is-zero identically, raising EDOM and
3365 : * returning NaN. We choose to throw error only for y-is-zero.
3366 : */
3367 413386 : if (NUMERIC_IS_SPECIAL(num1) || NUMERIC_IS_SPECIAL(num2))
3368 : {
3369 198 : if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
3370 78 : return make_result(&const_nan);
3371 120 : if (NUMERIC_IS_INF(num1))
3372 : {
3373 72 : if (numeric_sign_internal(num2) == 0)
3374 12 : goto division_by_zero;
3375 :
3376 : /* Inf % any nonzero = NaN */
3377 60 : return make_result(&const_nan);
3378 : }
3379 : /* num2 must be [-]Inf; result is num1 regardless of sign of num2 */
3380 48 : return duplicate_numeric(num1);
3381 : }
3382 :
3383 413188 : init_var_from_num(num1, &arg1);
3384 413188 : init_var_from_num(num2, &arg2);
3385 :
3386 413188 : init_var(&result);
3387 :
3388 : /* Check for division by zero */
3389 413188 : if (arg2.ndigits == 0 || arg2.digits[0] == 0)
3390 12 : goto division_by_zero;
3391 :
3392 413176 : mod_var(&arg1, &arg2, &result);
3393 :
3394 413176 : res = make_result_safe(&result, escontext);
3395 :
3396 413176 : free_var(&result);
3397 :
3398 413176 : return res;
3399 :
3400 24 : division_by_zero:
3401 24 : ereturn(escontext, NULL,
3402 : errcode(ERRCODE_DIVISION_BY_ZERO),
3403 : errmsg("division by zero"));
3404 : }
3405 :
3406 :
3407 : /*
3408 : * numeric_inc() -
3409 : *
3410 : * Increment a number by one
3411 : */
3412 : Datum
3413 48 : numeric_inc(PG_FUNCTION_ARGS)
3414 : {
3415 48 : Numeric num = PG_GETARG_NUMERIC(0);
3416 : NumericVar arg;
3417 : Numeric res;
3418 :
3419 : /*
3420 : * Handle NaN and infinities
3421 : */
3422 48 : if (NUMERIC_IS_SPECIAL(num))
3423 18 : PG_RETURN_NUMERIC(duplicate_numeric(num));
3424 :
3425 : /*
3426 : * Compute the result and return it
3427 : */
3428 30 : init_var_from_num(num, &arg);
3429 :
3430 30 : add_var(&arg, &const_one, &arg);
3431 :
3432 30 : res = make_result(&arg);
3433 :
3434 30 : free_var(&arg);
3435 :
3436 30 : PG_RETURN_NUMERIC(res);
3437 : }
3438 :
3439 :
3440 : /*
3441 : * numeric_smaller() -
3442 : *
3443 : * Return the smaller of two numbers
3444 : */
3445 : Datum
3446 810 : numeric_smaller(PG_FUNCTION_ARGS)
3447 : {
3448 810 : Numeric num1 = PG_GETARG_NUMERIC(0);
3449 810 : Numeric num2 = PG_GETARG_NUMERIC(1);
3450 :
3451 : /*
3452 : * Use cmp_numerics so that this will agree with the comparison operators,
3453 : * particularly as regards comparisons involving NaN.
3454 : */
3455 810 : if (cmp_numerics(num1, num2) < 0)
3456 650 : PG_RETURN_NUMERIC(num1);
3457 : else
3458 160 : PG_RETURN_NUMERIC(num2);
3459 : }
3460 :
3461 :
3462 : /*
3463 : * numeric_larger() -
3464 : *
3465 : * Return the larger of two numbers
3466 : */
3467 : Datum
3468 18630 : numeric_larger(PG_FUNCTION_ARGS)
3469 : {
3470 18630 : Numeric num1 = PG_GETARG_NUMERIC(0);
3471 18630 : Numeric num2 = PG_GETARG_NUMERIC(1);
3472 :
3473 : /*
3474 : * Use cmp_numerics so that this will agree with the comparison operators,
3475 : * particularly as regards comparisons involving NaN.
3476 : */
3477 18630 : if (cmp_numerics(num1, num2) > 0)
3478 17888 : PG_RETURN_NUMERIC(num1);
3479 : else
3480 742 : PG_RETURN_NUMERIC(num2);
3481 : }
3482 :
3483 :
3484 : /* ----------------------------------------------------------------------
3485 : *
3486 : * Advanced math functions
3487 : *
3488 : * ----------------------------------------------------------------------
3489 : */
3490 :
3491 : /*
3492 : * numeric_gcd() -
3493 : *
3494 : * Calculate the greatest common divisor of two numerics
3495 : */
3496 : Datum
3497 216 : numeric_gcd(PG_FUNCTION_ARGS)
3498 : {
3499 216 : Numeric num1 = PG_GETARG_NUMERIC(0);
3500 216 : Numeric num2 = PG_GETARG_NUMERIC(1);
3501 : NumericVar arg1;
3502 : NumericVar arg2;
3503 : NumericVar result;
3504 : Numeric res;
3505 :
3506 : /*
3507 : * Handle NaN and infinities: we consider the result to be NaN in all such
3508 : * cases.
3509 : */
3510 216 : if (NUMERIC_IS_SPECIAL(num1) || NUMERIC_IS_SPECIAL(num2))
3511 96 : PG_RETURN_NUMERIC(make_result(&const_nan));
3512 :
3513 : /*
3514 : * Unpack the arguments
3515 : */
3516 120 : init_var_from_num(num1, &arg1);
3517 120 : init_var_from_num(num2, &arg2);
3518 :
3519 120 : init_var(&result);
3520 :
3521 : /*
3522 : * Find the GCD and return the result
3523 : */
3524 120 : gcd_var(&arg1, &arg2, &result);
3525 :
3526 120 : res = make_result(&result);
3527 :
3528 120 : free_var(&result);
3529 :
3530 120 : PG_RETURN_NUMERIC(res);
3531 : }
3532 :
3533 :
3534 : /*
3535 : * numeric_lcm() -
3536 : *
3537 : * Calculate the least common multiple of two numerics
3538 : */
3539 : Datum
3540 246 : numeric_lcm(PG_FUNCTION_ARGS)
3541 : {
3542 246 : Numeric num1 = PG_GETARG_NUMERIC(0);
3543 246 : Numeric num2 = PG_GETARG_NUMERIC(1);
3544 : NumericVar arg1;
3545 : NumericVar arg2;
3546 : NumericVar result;
3547 : Numeric res;
3548 :
3549 : /*
3550 : * Handle NaN and infinities: we consider the result to be NaN in all such
3551 : * cases.
3552 : */
3553 246 : if (NUMERIC_IS_SPECIAL(num1) || NUMERIC_IS_SPECIAL(num2))
3554 96 : PG_RETURN_NUMERIC(make_result(&const_nan));
3555 :
3556 : /*
3557 : * Unpack the arguments
3558 : */
3559 150 : init_var_from_num(num1, &arg1);
3560 150 : init_var_from_num(num2, &arg2);
3561 :
3562 150 : init_var(&result);
3563 :
3564 : /*
3565 : * Compute the result using lcm(x, y) = abs(x / gcd(x, y) * y), returning
3566 : * zero if either input is zero.
3567 : *
3568 : * Note that the division is guaranteed to be exact, returning an integer
3569 : * result, so the LCM is an integral multiple of both x and y. A display
3570 : * scale of Min(x.dscale, y.dscale) would be sufficient to represent it,
3571 : * but as with other numeric functions, we choose to return a result whose
3572 : * display scale is no smaller than either input.
3573 : */
3574 150 : if (arg1.ndigits == 0 || arg2.ndigits == 0)
3575 48 : set_var_from_var(&const_zero, &result);
3576 : else
3577 : {
3578 102 : gcd_var(&arg1, &arg2, &result);
3579 102 : div_var(&arg1, &result, &result, 0, false, true);
3580 102 : mul_var(&arg2, &result, &result, arg2.dscale);
3581 102 : result.sign = NUMERIC_POS;
3582 : }
3583 :
3584 150 : result.dscale = Max(arg1.dscale, arg2.dscale);
3585 :
3586 150 : res = make_result(&result);
3587 :
3588 144 : free_var(&result);
3589 :
3590 144 : PG_RETURN_NUMERIC(res);
3591 : }
3592 :
3593 :
3594 : /*
3595 : * numeric_fac()
3596 : *
3597 : * Compute factorial
3598 : */
3599 : Datum
3600 42 : numeric_fac(PG_FUNCTION_ARGS)
3601 : {
3602 42 : int64 num = PG_GETARG_INT64(0);
3603 : Numeric res;
3604 : NumericVar fact;
3605 : NumericVar result;
3606 :
3607 42 : if (num < 0)
3608 6 : ereport(ERROR,
3609 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
3610 : errmsg("factorial of a negative number is undefined")));
3611 36 : if (num <= 1)
3612 : {
3613 6 : res = make_result(&const_one);
3614 6 : PG_RETURN_NUMERIC(res);
3615 : }
3616 : /* Fail immediately if the result would overflow */
3617 30 : if (num > 32177)
3618 6 : ereport(ERROR,
3619 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
3620 : errmsg("value overflows numeric format")));
3621 :
3622 24 : init_var(&fact);
3623 24 : init_var(&result);
3624 :
3625 24 : int64_to_numericvar(num, &result);
3626 :
3627 294 : for (num = num - 1; num > 1; num--)
3628 : {
3629 : /* this loop can take awhile, so allow it to be interrupted */
3630 270 : CHECK_FOR_INTERRUPTS();
3631 :
3632 270 : int64_to_numericvar(num, &fact);
3633 :
3634 270 : mul_var(&result, &fact, &result, 0);
3635 : }
3636 :
3637 24 : res = make_result(&result);
3638 :
3639 24 : free_var(&fact);
3640 24 : free_var(&result);
3641 :
3642 24 : PG_RETURN_NUMERIC(res);
3643 : }
3644 :
3645 :
3646 : /*
3647 : * numeric_sqrt() -
3648 : *
3649 : * Compute the square root of a numeric.
3650 : */
3651 : Datum
3652 150 : numeric_sqrt(PG_FUNCTION_ARGS)
3653 : {
3654 150 : Numeric num = PG_GETARG_NUMERIC(0);
3655 : Numeric res;
3656 : NumericVar arg;
3657 : NumericVar result;
3658 : int sweight;
3659 : int rscale;
3660 :
3661 : /*
3662 : * Handle NaN and infinities
3663 : */
3664 150 : if (NUMERIC_IS_SPECIAL(num))
3665 : {
3666 : /* error should match that in sqrt_var() */
3667 18 : if (NUMERIC_IS_NINF(num))
3668 6 : ereport(ERROR,
3669 : (errcode(ERRCODE_INVALID_ARGUMENT_FOR_POWER_FUNCTION),
3670 : errmsg("cannot take square root of a negative number")));
3671 : /* For NAN or PINF, just duplicate the input */
3672 12 : PG_RETURN_NUMERIC(duplicate_numeric(num));
3673 : }
3674 :
3675 : /*
3676 : * Unpack the argument and determine the result scale. We choose a scale
3677 : * to give at least NUMERIC_MIN_SIG_DIGITS significant digits; but in any
3678 : * case not less than the input's dscale.
3679 : */
3680 132 : init_var_from_num(num, &arg);
3681 :
3682 132 : init_var(&result);
3683 :
3684 : /*
3685 : * Assume the input was normalized, so arg.weight is accurate. The result
3686 : * then has at least sweight = floor(arg.weight * DEC_DIGITS / 2 + 1)
3687 : * digits before the decimal point. When DEC_DIGITS is even, we can save
3688 : * a few cycles, since the division is exact and there is no need to round
3689 : * towards negative infinity.
3690 : */
3691 : #if DEC_DIGITS == ((DEC_DIGITS / 2) * 2)
3692 132 : sweight = arg.weight * DEC_DIGITS / 2 + 1;
3693 : #else
3694 : if (arg.weight >= 0)
3695 : sweight = arg.weight * DEC_DIGITS / 2 + 1;
3696 : else
3697 : sweight = 1 - (1 - arg.weight * DEC_DIGITS) / 2;
3698 : #endif
3699 :
3700 132 : rscale = NUMERIC_MIN_SIG_DIGITS - sweight;
3701 132 : rscale = Max(rscale, arg.dscale);
3702 132 : rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
3703 132 : rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
3704 :
3705 : /*
3706 : * Let sqrt_var() do the calculation and return the result.
3707 : */
3708 132 : sqrt_var(&arg, &result, rscale);
3709 :
3710 126 : res = make_result(&result);
3711 :
3712 126 : free_var(&result);
3713 :
3714 126 : PG_RETURN_NUMERIC(res);
3715 : }
3716 :
3717 :
3718 : /*
3719 : * numeric_exp() -
3720 : *
3721 : * Raise e to the power of x
3722 : */
3723 : Datum
3724 78 : numeric_exp(PG_FUNCTION_ARGS)
3725 : {
3726 78 : Numeric num = PG_GETARG_NUMERIC(0);
3727 : Numeric res;
3728 : NumericVar arg;
3729 : NumericVar result;
3730 : int rscale;
3731 : double val;
3732 :
3733 : /*
3734 : * Handle NaN and infinities
3735 : */
3736 78 : if (NUMERIC_IS_SPECIAL(num))
3737 : {
3738 : /* Per POSIX, exp(-Inf) is zero */
3739 18 : if (NUMERIC_IS_NINF(num))
3740 6 : PG_RETURN_NUMERIC(make_result(&const_zero));
3741 : /* For NAN or PINF, just duplicate the input */
3742 12 : PG_RETURN_NUMERIC(duplicate_numeric(num));
3743 : }
3744 :
3745 : /*
3746 : * Unpack the argument and determine the result scale. We choose a scale
3747 : * to give at least NUMERIC_MIN_SIG_DIGITS significant digits; but in any
3748 : * case not less than the input's dscale.
3749 : */
3750 60 : init_var_from_num(num, &arg);
3751 :
3752 60 : init_var(&result);
3753 :
3754 : /* convert input to float8, ignoring overflow */
3755 60 : val = numericvar_to_double_no_overflow(&arg);
3756 :
3757 : /*
3758 : * log10(result) = num * log10(e), so this is approximately the decimal
3759 : * weight of the result:
3760 : */
3761 60 : val *= 0.434294481903252;
3762 :
3763 : /* limit to something that won't cause integer overflow */
3764 60 : val = Max(val, -NUMERIC_MAX_RESULT_SCALE);
3765 60 : val = Min(val, NUMERIC_MAX_RESULT_SCALE);
3766 :
3767 60 : rscale = NUMERIC_MIN_SIG_DIGITS - (int) val;
3768 60 : rscale = Max(rscale, arg.dscale);
3769 60 : rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
3770 60 : rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
3771 :
3772 : /*
3773 : * Let exp_var() do the calculation and return the result.
3774 : */
3775 60 : exp_var(&arg, &result, rscale);
3776 :
3777 60 : res = make_result(&result);
3778 :
3779 60 : free_var(&result);
3780 :
3781 60 : PG_RETURN_NUMERIC(res);
3782 : }
3783 :
3784 :
3785 : /*
3786 : * numeric_ln() -
3787 : *
3788 : * Compute the natural logarithm of x
3789 : */
3790 : Datum
3791 198 : numeric_ln(PG_FUNCTION_ARGS)
3792 : {
3793 198 : Numeric num = PG_GETARG_NUMERIC(0);
3794 : Numeric res;
3795 : NumericVar arg;
3796 : NumericVar result;
3797 : int ln_dweight;
3798 : int rscale;
3799 :
3800 : /*
3801 : * Handle NaN and infinities
3802 : */
3803 198 : if (NUMERIC_IS_SPECIAL(num))
3804 : {
3805 18 : if (NUMERIC_IS_NINF(num))
3806 6 : ereport(ERROR,
3807 : (errcode(ERRCODE_INVALID_ARGUMENT_FOR_LOG),
3808 : errmsg("cannot take logarithm of a negative number")));
3809 : /* For NAN or PINF, just duplicate the input */
3810 12 : PG_RETURN_NUMERIC(duplicate_numeric(num));
3811 : }
3812 :
3813 180 : init_var_from_num(num, &arg);
3814 180 : init_var(&result);
3815 :
3816 : /* Estimated dweight of logarithm */
3817 180 : ln_dweight = estimate_ln_dweight(&arg);
3818 :
3819 180 : rscale = NUMERIC_MIN_SIG_DIGITS - ln_dweight;
3820 180 : rscale = Max(rscale, arg.dscale);
3821 180 : rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
3822 180 : rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
3823 :
3824 180 : ln_var(&arg, &result, rscale);
3825 :
3826 156 : res = make_result(&result);
3827 :
3828 156 : free_var(&result);
3829 :
3830 156 : PG_RETURN_NUMERIC(res);
3831 : }
3832 :
3833 :
3834 : /*
3835 : * numeric_log() -
3836 : *
3837 : * Compute the logarithm of x in a given base
3838 : */
3839 : Datum
3840 342 : numeric_log(PG_FUNCTION_ARGS)
3841 : {
3842 342 : Numeric num1 = PG_GETARG_NUMERIC(0);
3843 342 : Numeric num2 = PG_GETARG_NUMERIC(1);
3844 : Numeric res;
3845 : NumericVar arg1;
3846 : NumericVar arg2;
3847 : NumericVar result;
3848 :
3849 : /*
3850 : * Handle NaN and infinities
3851 : */
3852 342 : if (NUMERIC_IS_SPECIAL(num1) || NUMERIC_IS_SPECIAL(num2))
3853 : {
3854 : int sign1,
3855 : sign2;
3856 :
3857 126 : if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
3858 54 : PG_RETURN_NUMERIC(make_result(&const_nan));
3859 : /* fail on negative inputs including -Inf, as log_var would */
3860 72 : sign1 = numeric_sign_internal(num1);
3861 72 : sign2 = numeric_sign_internal(num2);
3862 72 : if (sign1 < 0 || sign2 < 0)
3863 24 : ereport(ERROR,
3864 : (errcode(ERRCODE_INVALID_ARGUMENT_FOR_LOG),
3865 : errmsg("cannot take logarithm of a negative number")));
3866 : /* fail on zero inputs, as log_var would */
3867 48 : if (sign1 == 0 || sign2 == 0)
3868 6 : ereport(ERROR,
3869 : (errcode(ERRCODE_INVALID_ARGUMENT_FOR_LOG),
3870 : errmsg("cannot take logarithm of zero")));
3871 42 : if (NUMERIC_IS_PINF(num1))
3872 : {
3873 : /* log(Inf, Inf) reduces to Inf/Inf, so it's NaN */
3874 18 : if (NUMERIC_IS_PINF(num2))
3875 6 : PG_RETURN_NUMERIC(make_result(&const_nan));
3876 : /* log(Inf, finite-positive) is zero (we don't throw underflow) */
3877 12 : PG_RETURN_NUMERIC(make_result(&const_zero));
3878 : }
3879 : Assert(NUMERIC_IS_PINF(num2));
3880 : /* log(finite-positive, Inf) is Inf */
3881 24 : PG_RETURN_NUMERIC(make_result(&const_pinf));
3882 : }
3883 :
3884 : /*
3885 : * Initialize things
3886 : */
3887 216 : init_var_from_num(num1, &arg1);
3888 216 : init_var_from_num(num2, &arg2);
3889 216 : init_var(&result);
3890 :
3891 : /*
3892 : * Call log_var() to compute and return the result; note it handles scale
3893 : * selection itself.
3894 : */
3895 216 : log_var(&arg1, &arg2, &result);
3896 :
3897 156 : res = make_result(&result);
3898 :
3899 156 : free_var(&result);
3900 :
3901 156 : PG_RETURN_NUMERIC(res);
3902 : }
3903 :
3904 :
3905 : /*
3906 : * numeric_power() -
3907 : *
3908 : * Raise x to the power of y
3909 : */
3910 : Datum
3911 1644 : numeric_power(PG_FUNCTION_ARGS)
3912 : {
3913 1644 : Numeric num1 = PG_GETARG_NUMERIC(0);
3914 1644 : Numeric num2 = PG_GETARG_NUMERIC(1);
3915 : Numeric res;
3916 : NumericVar arg1;
3917 : NumericVar arg2;
3918 : NumericVar result;
3919 : int sign1,
3920 : sign2;
3921 :
3922 : /*
3923 : * Handle NaN and infinities
3924 : */
3925 1644 : if (NUMERIC_IS_SPECIAL(num1) || NUMERIC_IS_SPECIAL(num2))
3926 : {
3927 : /*
3928 : * We follow the POSIX spec for pow(3), which says that NaN ^ 0 = 1,
3929 : * and 1 ^ NaN = 1, while all other cases with NaN inputs yield NaN
3930 : * (with no error).
3931 : */
3932 234 : if (NUMERIC_IS_NAN(num1))
3933 : {
3934 54 : if (!NUMERIC_IS_SPECIAL(num2))
3935 : {
3936 36 : init_var_from_num(num2, &arg2);
3937 36 : if (cmp_var(&arg2, &const_zero) == 0)
3938 12 : PG_RETURN_NUMERIC(make_result(&const_one));
3939 : }
3940 42 : PG_RETURN_NUMERIC(make_result(&const_nan));
3941 : }
3942 180 : if (NUMERIC_IS_NAN(num2))
3943 : {
3944 42 : if (!NUMERIC_IS_SPECIAL(num1))
3945 : {
3946 36 : init_var_from_num(num1, &arg1);
3947 36 : if (cmp_var(&arg1, &const_one) == 0)
3948 12 : PG_RETURN_NUMERIC(make_result(&const_one));
3949 : }
3950 30 : PG_RETURN_NUMERIC(make_result(&const_nan));
3951 : }
3952 : /* At least one input is infinite, but error rules still apply */
3953 138 : sign1 = numeric_sign_internal(num1);
3954 138 : sign2 = numeric_sign_internal(num2);
3955 138 : if (sign1 == 0 && sign2 < 0)
3956 6 : ereport(ERROR,
3957 : (errcode(ERRCODE_INVALID_ARGUMENT_FOR_POWER_FUNCTION),
3958 : errmsg("zero raised to a negative power is undefined")));
3959 132 : if (sign1 < 0 && !numeric_is_integral(num2))
3960 6 : ereport(ERROR,
3961 : (errcode(ERRCODE_INVALID_ARGUMENT_FOR_POWER_FUNCTION),
3962 : errmsg("a negative number raised to a non-integer power yields a complex result")));
3963 :
3964 : /*
3965 : * POSIX gives this series of rules for pow(3) with infinite inputs:
3966 : *
3967 : * For any value of y, if x is +1, 1.0 shall be returned.
3968 : */
3969 126 : if (!NUMERIC_IS_SPECIAL(num1))
3970 : {
3971 42 : init_var_from_num(num1, &arg1);
3972 42 : if (cmp_var(&arg1, &const_one) == 0)
3973 6 : PG_RETURN_NUMERIC(make_result(&const_one));
3974 : }
3975 :
3976 : /*
3977 : * For any value of x, if y is [-]0, 1.0 shall be returned.
3978 : */
3979 120 : if (sign2 == 0)
3980 12 : PG_RETURN_NUMERIC(make_result(&const_one));
3981 :
3982 : /*
3983 : * For any odd integer value of y > 0, if x is [-]0, [-]0 shall be
3984 : * returned. For y > 0 and not an odd integer, if x is [-]0, +0 shall
3985 : * be returned. (Since we don't deal in minus zero, we need not
3986 : * distinguish these two cases.)
3987 : */
3988 108 : if (sign1 == 0 && sign2 > 0)
3989 6 : PG_RETURN_NUMERIC(make_result(&const_zero));
3990 :
3991 : /*
3992 : * If x is -1, and y is [-]Inf, 1.0 shall be returned.
3993 : *
3994 : * For |x| < 1, if y is -Inf, +Inf shall be returned.
3995 : *
3996 : * For |x| > 1, if y is -Inf, +0 shall be returned.
3997 : *
3998 : * For |x| < 1, if y is +Inf, +0 shall be returned.
3999 : *
4000 : * For |x| > 1, if y is +Inf, +Inf shall be returned.
4001 : */
4002 102 : if (NUMERIC_IS_INF(num2))
4003 : {
4004 : bool abs_x_gt_one;
4005 :
4006 54 : if (NUMERIC_IS_SPECIAL(num1))
4007 24 : abs_x_gt_one = true; /* x is either Inf or -Inf */
4008 : else
4009 : {
4010 30 : init_var_from_num(num1, &arg1);
4011 30 : if (cmp_var(&arg1, &const_minus_one) == 0)
4012 6 : PG_RETURN_NUMERIC(make_result(&const_one));
4013 24 : arg1.sign = NUMERIC_POS; /* now arg1 = abs(x) */
4014 24 : abs_x_gt_one = (cmp_var(&arg1, &const_one) > 0);
4015 : }
4016 48 : if (abs_x_gt_one == (sign2 > 0))
4017 30 : PG_RETURN_NUMERIC(make_result(&const_pinf));
4018 : else
4019 18 : PG_RETURN_NUMERIC(make_result(&const_zero));
4020 : }
4021 :
4022 : /*
4023 : * For y < 0, if x is +Inf, +0 shall be returned.
4024 : *
4025 : * For y > 0, if x is +Inf, +Inf shall be returned.
4026 : */
4027 48 : if (NUMERIC_IS_PINF(num1))
4028 : {
4029 24 : if (sign2 > 0)
4030 18 : PG_RETURN_NUMERIC(make_result(&const_pinf));
4031 : else
4032 6 : PG_RETURN_NUMERIC(make_result(&const_zero));
4033 : }
4034 :
4035 : Assert(NUMERIC_IS_NINF(num1));
4036 :
4037 : /*
4038 : * For y an odd integer < 0, if x is -Inf, -0 shall be returned. For
4039 : * y < 0 and not an odd integer, if x is -Inf, +0 shall be returned.
4040 : * (Again, we need not distinguish these two cases.)
4041 : */
4042 24 : if (sign2 < 0)
4043 12 : PG_RETURN_NUMERIC(make_result(&const_zero));
4044 :
4045 : /*
4046 : * For y an odd integer > 0, if x is -Inf, -Inf shall be returned. For
4047 : * y > 0 and not an odd integer, if x is -Inf, +Inf shall be returned.
4048 : */
4049 12 : init_var_from_num(num2, &arg2);
4050 12 : if (arg2.ndigits > 0 && arg2.ndigits == arg2.weight + 1 &&
4051 12 : (arg2.digits[arg2.ndigits - 1] & 1))
4052 6 : PG_RETURN_NUMERIC(make_result(&const_ninf));
4053 : else
4054 6 : PG_RETURN_NUMERIC(make_result(&const_pinf));
4055 : }
4056 :
4057 : /*
4058 : * The SQL spec requires that we emit a particular SQLSTATE error code for
4059 : * certain error conditions. Specifically, we don't return a
4060 : * divide-by-zero error code for 0 ^ -1. Raising a negative number to a
4061 : * non-integer power must produce the same error code, but that case is
4062 : * handled in power_var().
4063 : */
4064 1410 : sign1 = numeric_sign_internal(num1);
4065 1410 : sign2 = numeric_sign_internal(num2);
4066 :
4067 1410 : if (sign1 == 0 && sign2 < 0)
4068 12 : ereport(ERROR,
4069 : (errcode(ERRCODE_INVALID_ARGUMENT_FOR_POWER_FUNCTION),
4070 : errmsg("zero raised to a negative power is undefined")));
4071 :
4072 : /*
4073 : * Initialize things
4074 : */
4075 1398 : init_var(&result);
4076 1398 : init_var_from_num(num1, &arg1);
4077 1398 : init_var_from_num(num2, &arg2);
4078 :
4079 : /*
4080 : * Call power_var() to compute and return the result; note it handles
4081 : * scale selection itself.
4082 : */
4083 1398 : power_var(&arg1, &arg2, &result);
4084 :
4085 1368 : res = make_result(&result);
4086 :
4087 1368 : free_var(&result);
4088 :
4089 1368 : PG_RETURN_NUMERIC(res);
4090 : }
4091 :
4092 : /*
4093 : * numeric_scale() -
4094 : *
4095 : * Returns the scale, i.e. the count of decimal digits in the fractional part
4096 : */
4097 : Datum
4098 108 : numeric_scale(PG_FUNCTION_ARGS)
4099 : {
4100 108 : Numeric num = PG_GETARG_NUMERIC(0);
4101 :
4102 108 : if (NUMERIC_IS_SPECIAL(num))
4103 18 : PG_RETURN_NULL();
4104 :
4105 90 : PG_RETURN_INT32(NUMERIC_DSCALE(num));
4106 : }
4107 :
4108 : /*
4109 : * Calculate minimum scale for value.
4110 : */
4111 : static int
4112 372 : get_min_scale(NumericVar *var)
4113 : {
4114 : int min_scale;
4115 : int last_digit_pos;
4116 :
4117 : /*
4118 : * Ordinarily, the input value will be "stripped" so that the last
4119 : * NumericDigit is nonzero. But we don't want to get into an infinite
4120 : * loop if it isn't, so explicitly find the last nonzero digit.
4121 : */
4122 372 : last_digit_pos = var->ndigits - 1;
4123 372 : while (last_digit_pos >= 0 &&
4124 342 : var->digits[last_digit_pos] == 0)
4125 0 : last_digit_pos--;
4126 :
4127 372 : if (last_digit_pos >= 0)
4128 : {
4129 : /* compute min_scale assuming that last ndigit has no zeroes */
4130 342 : min_scale = (last_digit_pos - var->weight) * DEC_DIGITS;
4131 :
4132 : /*
4133 : * We could get a negative result if there are no digits after the
4134 : * decimal point. In this case the min_scale must be zero.
4135 : */
4136 342 : if (min_scale > 0)
4137 : {
4138 : /*
4139 : * Reduce min_scale if trailing digit(s) in last NumericDigit are
4140 : * zero.
4141 : */
4142 186 : NumericDigit last_digit = var->digits[last_digit_pos];
4143 :
4144 498 : while (last_digit % 10 == 0)
4145 : {
4146 312 : min_scale--;
4147 312 : last_digit /= 10;
4148 : }
4149 : }
4150 : else
4151 156 : min_scale = 0;
4152 : }
4153 : else
4154 30 : min_scale = 0; /* result if input is zero */
4155 :
4156 372 : return min_scale;
4157 : }
4158 :
4159 : /*
4160 : * Returns minimum scale required to represent supplied value without loss.
4161 : */
4162 : Datum
4163 72 : numeric_min_scale(PG_FUNCTION_ARGS)
4164 : {
4165 72 : Numeric num = PG_GETARG_NUMERIC(0);
4166 : NumericVar arg;
4167 : int min_scale;
4168 :
4169 72 : if (NUMERIC_IS_SPECIAL(num))
4170 12 : PG_RETURN_NULL();
4171 :
4172 60 : init_var_from_num(num, &arg);
4173 60 : min_scale = get_min_scale(&arg);
4174 60 : free_var(&arg);
4175 :
4176 60 : PG_RETURN_INT32(min_scale);
4177 : }
4178 :
4179 : /*
4180 : * Reduce scale of numeric value to represent supplied value without loss.
4181 : */
4182 : Datum
4183 324 : numeric_trim_scale(PG_FUNCTION_ARGS)
4184 : {
4185 324 : Numeric num = PG_GETARG_NUMERIC(0);
4186 : Numeric res;
4187 : NumericVar result;
4188 :
4189 324 : if (NUMERIC_IS_SPECIAL(num))
4190 12 : PG_RETURN_NUMERIC(duplicate_numeric(num));
4191 :
4192 312 : init_var_from_num(num, &result);
4193 312 : result.dscale = get_min_scale(&result);
4194 312 : res = make_result(&result);
4195 312 : free_var(&result);
4196 :
4197 312 : PG_RETURN_NUMERIC(res);
4198 : }
4199 :
4200 : /*
4201 : * Return a random numeric value in the range [rmin, rmax].
4202 : */
4203 : Numeric
4204 33462 : random_numeric(pg_prng_state *state, Numeric rmin, Numeric rmax)
4205 : {
4206 : NumericVar rmin_var;
4207 : NumericVar rmax_var;
4208 : NumericVar result;
4209 : Numeric res;
4210 :
4211 : /* Range bounds must not be NaN/infinity */
4212 33462 : if (NUMERIC_IS_SPECIAL(rmin))
4213 : {
4214 12 : if (NUMERIC_IS_NAN(rmin))
4215 6 : ereport(ERROR,
4216 : errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4217 : errmsg("lower bound cannot be NaN"));
4218 : else
4219 6 : ereport(ERROR,
4220 : errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4221 : errmsg("lower bound cannot be infinity"));
4222 : }
4223 33450 : if (NUMERIC_IS_SPECIAL(rmax))
4224 : {
4225 12 : if (NUMERIC_IS_NAN(rmax))
4226 6 : ereport(ERROR,
4227 : errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4228 : errmsg("upper bound cannot be NaN"));
4229 : else
4230 6 : ereport(ERROR,
4231 : errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4232 : errmsg("upper bound cannot be infinity"));
4233 : }
4234 :
4235 : /* Return a random value in the range [rmin, rmax] */
4236 33438 : init_var_from_num(rmin, &rmin_var);
4237 33438 : init_var_from_num(rmax, &rmax_var);
4238 :
4239 33438 : init_var(&result);
4240 :
4241 33438 : random_var(state, &rmin_var, &rmax_var, &result);
4242 :
4243 33432 : res = make_result(&result);
4244 :
4245 33432 : free_var(&result);
4246 :
4247 33432 : return res;
4248 : }
4249 :
4250 :
4251 : /* ----------------------------------------------------------------------
4252 : *
4253 : * Type conversion functions
4254 : *
4255 : * ----------------------------------------------------------------------
4256 : */
4257 :
4258 : Numeric
4259 1870570 : int64_to_numeric(int64 val)
4260 : {
4261 : Numeric res;
4262 : NumericVar result;
4263 :
4264 1870570 : init_var(&result);
4265 :
4266 1870570 : int64_to_numericvar(val, &result);
4267 :
4268 1870570 : res = make_result(&result);
4269 :
4270 1870570 : free_var(&result);
4271 :
4272 1870570 : return res;
4273 : }
4274 :
4275 : /*
4276 : * Convert val1/(10**log10val2) to numeric. This is much faster than normal
4277 : * numeric division.
4278 : */
4279 : Numeric
4280 29380 : int64_div_fast_to_numeric(int64 val1, int log10val2)
4281 : {
4282 : Numeric res;
4283 : NumericVar result;
4284 : int rscale;
4285 : int w;
4286 : int m;
4287 :
4288 29380 : init_var(&result);
4289 :
4290 : /* result scale */
4291 29380 : rscale = log10val2 < 0 ? 0 : log10val2;
4292 :
4293 : /* how much to decrease the weight by */
4294 29380 : w = log10val2 / DEC_DIGITS;
4295 : /* how much is left to divide by */
4296 29380 : m = log10val2 % DEC_DIGITS;
4297 29380 : if (m < 0)
4298 : {
4299 0 : m += DEC_DIGITS;
4300 0 : w--;
4301 : }
4302 :
4303 : /*
4304 : * If there is anything left to divide by (10^m with 0 < m < DEC_DIGITS),
4305 : * multiply the dividend by 10^(DEC_DIGITS - m), and shift the weight by
4306 : * one more.
4307 : */
4308 29380 : if (m > 0)
4309 : {
4310 : #if DEC_DIGITS == 4
4311 : static const int pow10[] = {1, 10, 100, 1000};
4312 : #elif DEC_DIGITS == 2
4313 : static const int pow10[] = {1, 10};
4314 : #elif DEC_DIGITS == 1
4315 : static const int pow10[] = {1};
4316 : #else
4317 : #error unsupported NBASE
4318 : #endif
4319 29380 : int64 factor = pow10[DEC_DIGITS - m];
4320 : int64 new_val1;
4321 :
4322 : StaticAssertDecl(lengthof(pow10) == DEC_DIGITS, "mismatch with DEC_DIGITS");
4323 :
4324 29380 : if (unlikely(pg_mul_s64_overflow(val1, factor, &new_val1)))
4325 : {
4326 : /* do the multiplication using 128-bit integers */
4327 : INT128 tmp;
4328 :
4329 12 : tmp = int64_to_int128(0);
4330 12 : int128_add_int64_mul_int64(&tmp, val1, factor);
4331 :
4332 12 : int128_to_numericvar(tmp, &result);
4333 : }
4334 : else
4335 29368 : int64_to_numericvar(new_val1, &result);
4336 :
4337 29380 : w++;
4338 : }
4339 : else
4340 0 : int64_to_numericvar(val1, &result);
4341 :
4342 29380 : result.weight -= w;
4343 29380 : result.dscale = rscale;
4344 :
4345 29380 : res = make_result(&result);
4346 :
4347 29380 : free_var(&result);
4348 :
4349 29380 : return res;
4350 : }
4351 :
4352 : Datum
4353 1556126 : int4_numeric(PG_FUNCTION_ARGS)
4354 : {
4355 1556126 : int32 val = PG_GETARG_INT32(0);
4356 :
4357 1556126 : PG_RETURN_NUMERIC(int64_to_numeric(val));
4358 : }
4359 :
4360 : /*
4361 : * Internal version of numeric_int4() with support for soft error reporting.
4362 : */
4363 : int32
4364 7760 : numeric_int4_safe(Numeric num, Node *escontext)
4365 : {
4366 : NumericVar x;
4367 : int32 result;
4368 :
4369 7760 : if (NUMERIC_IS_SPECIAL(num))
4370 : {
4371 18 : if (NUMERIC_IS_NAN(num))
4372 6 : ereturn(escontext, 0,
4373 : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4374 : errmsg("cannot convert NaN to %s", "integer")));
4375 : else
4376 12 : ereturn(escontext, 0,
4377 : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4378 : errmsg("cannot convert infinity to %s", "integer")));
4379 : }
4380 :
4381 : /* Convert to variable format, then convert to int4 */
4382 7742 : init_var_from_num(num, &x);
4383 :
4384 7742 : if (!numericvar_to_int32(&x, &result))
4385 90 : ereturn(escontext, 0,
4386 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
4387 : errmsg("integer out of range")));
4388 :
4389 7652 : return result;
4390 : }
4391 :
4392 : Datum
4393 6176 : numeric_int4(PG_FUNCTION_ARGS)
4394 : {
4395 6176 : Numeric num = PG_GETARG_NUMERIC(0);
4396 :
4397 6176 : PG_RETURN_INT32(numeric_int4_safe(num, NULL));
4398 : }
4399 :
4400 : /*
4401 : * Given a NumericVar, convert it to an int32. If the NumericVar
4402 : * exceeds the range of an int32, false is returned, otherwise true is returned.
4403 : * The input NumericVar is *not* free'd.
4404 : */
4405 : static bool
4406 8486 : numericvar_to_int32(const NumericVar *var, int32 *result)
4407 : {
4408 : int64 val;
4409 :
4410 8486 : if (!numericvar_to_int64(var, &val))
4411 6 : return false;
4412 :
4413 8480 : if (unlikely(val < PG_INT32_MIN) || unlikely(val > PG_INT32_MAX))
4414 84 : return false;
4415 :
4416 : /* Down-convert to int4 */
4417 8396 : *result = (int32) val;
4418 :
4419 8396 : return true;
4420 : }
4421 :
4422 : Datum
4423 36854 : int8_numeric(PG_FUNCTION_ARGS)
4424 : {
4425 36854 : int64 val = PG_GETARG_INT64(0);
4426 :
4427 36854 : PG_RETURN_NUMERIC(int64_to_numeric(val));
4428 : }
4429 :
4430 : /*
4431 : * Internal version of numeric_int8() with support for soft error reporting.
4432 : */
4433 : int64
4434 570 : numeric_int8_safe(Numeric num, Node *escontext)
4435 : {
4436 : NumericVar x;
4437 : int64 result;
4438 :
4439 570 : if (NUMERIC_IS_SPECIAL(num))
4440 : {
4441 18 : if (NUMERIC_IS_NAN(num))
4442 6 : ereturn(escontext, 0,
4443 : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4444 : errmsg("cannot convert NaN to %s", "bigint")));
4445 : else
4446 12 : ereturn(escontext, 0,
4447 : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4448 : errmsg("cannot convert infinity to %s", "bigint")));
4449 : }
4450 :
4451 : /* Convert to variable format, then convert to int8 */
4452 552 : init_var_from_num(num, &x);
4453 :
4454 552 : if (!numericvar_to_int64(&x, &result))
4455 60 : ereturn(escontext, 0,
4456 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
4457 : errmsg("bigint out of range")));
4458 :
4459 492 : return result;
4460 : }
4461 :
4462 : Datum
4463 522 : numeric_int8(PG_FUNCTION_ARGS)
4464 : {
4465 522 : Numeric num = PG_GETARG_NUMERIC(0);
4466 :
4467 522 : PG_RETURN_INT64(numeric_int8_safe(num, NULL));
4468 : }
4469 :
4470 :
4471 : Datum
4472 6 : int2_numeric(PG_FUNCTION_ARGS)
4473 : {
4474 6 : int16 val = PG_GETARG_INT16(0);
4475 :
4476 6 : PG_RETURN_NUMERIC(int64_to_numeric(val));
4477 : }
4478 :
4479 :
4480 : Datum
4481 102 : numeric_int2(PG_FUNCTION_ARGS)
4482 : {
4483 102 : Numeric num = PG_GETARG_NUMERIC(0);
4484 : NumericVar x;
4485 : int64 val;
4486 : int16 result;
4487 :
4488 102 : if (NUMERIC_IS_SPECIAL(num))
4489 : {
4490 18 : if (NUMERIC_IS_NAN(num))
4491 6 : ereport(ERROR,
4492 : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4493 : errmsg("cannot convert NaN to %s", "smallint")));
4494 : else
4495 12 : ereport(ERROR,
4496 : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4497 : errmsg("cannot convert infinity to %s", "smallint")));
4498 : }
4499 :
4500 : /* Convert to variable format and thence to int8 */
4501 84 : init_var_from_num(num, &x);
4502 :
4503 84 : if (!numericvar_to_int64(&x, &val))
4504 0 : ereport(ERROR,
4505 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
4506 : errmsg("smallint out of range")));
4507 :
4508 84 : if (unlikely(val < PG_INT16_MIN) || unlikely(val > PG_INT16_MAX))
4509 12 : ereport(ERROR,
4510 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
4511 : errmsg("smallint out of range")));
4512 :
4513 : /* Down-convert to int2 */
4514 72 : result = (int16) val;
4515 :
4516 72 : PG_RETURN_INT16(result);
4517 : }
4518 :
4519 :
4520 : Datum
4521 1074 : float8_numeric(PG_FUNCTION_ARGS)
4522 : {
4523 1074 : float8 val = PG_GETARG_FLOAT8(0);
4524 : Numeric res;
4525 : NumericVar result;
4526 : char buf[DBL_DIG + 100];
4527 : const char *endptr;
4528 :
4529 1074 : if (isnan(val))
4530 6 : PG_RETURN_NUMERIC(make_result(&const_nan));
4531 :
4532 1068 : if (isinf(val))
4533 : {
4534 12 : if (val < 0)
4535 6 : PG_RETURN_NUMERIC(make_result(&const_ninf));
4536 : else
4537 6 : PG_RETURN_NUMERIC(make_result(&const_pinf));
4538 : }
4539 :
4540 1056 : snprintf(buf, sizeof(buf), "%.*g", DBL_DIG, val);
4541 :
4542 1056 : init_var(&result);
4543 :
4544 : /* Assume we need not worry about leading/trailing spaces */
4545 1056 : (void) set_var_from_str(buf, buf, &result, &endptr, NULL);
4546 :
4547 1056 : res = make_result(&result);
4548 :
4549 1056 : free_var(&result);
4550 :
4551 1056 : PG_RETURN_NUMERIC(res);
4552 : }
4553 :
4554 :
4555 : Datum
4556 520726 : numeric_float8(PG_FUNCTION_ARGS)
4557 : {
4558 520726 : Numeric num = PG_GETARG_NUMERIC(0);
4559 : char *tmp;
4560 : Datum result;
4561 :
4562 520726 : if (NUMERIC_IS_SPECIAL(num))
4563 : {
4564 78 : if (NUMERIC_IS_PINF(num))
4565 24 : PG_RETURN_FLOAT8(get_float8_infinity());
4566 54 : else if (NUMERIC_IS_NINF(num))
4567 24 : PG_RETURN_FLOAT8(-get_float8_infinity());
4568 : else
4569 30 : PG_RETURN_FLOAT8(get_float8_nan());
4570 : }
4571 :
4572 520648 : tmp = DatumGetCString(DirectFunctionCall1(numeric_out,
4573 : NumericGetDatum(num)));
4574 :
4575 520648 : result = DirectFunctionCall1(float8in, CStringGetDatum(tmp));
4576 :
4577 520648 : pfree(tmp);
4578 :
4579 520648 : PG_RETURN_DATUM(result);
4580 : }
4581 :
4582 :
4583 : /*
4584 : * Convert numeric to float8; if out of range, return +/- HUGE_VAL
4585 : *
4586 : * (internal helper function, not directly callable from SQL)
4587 : */
4588 : Datum
4589 30 : numeric_float8_no_overflow(PG_FUNCTION_ARGS)
4590 : {
4591 30 : Numeric num = PG_GETARG_NUMERIC(0);
4592 : double val;
4593 :
4594 30 : if (NUMERIC_IS_SPECIAL(num))
4595 : {
4596 0 : if (NUMERIC_IS_PINF(num))
4597 0 : val = HUGE_VAL;
4598 0 : else if (NUMERIC_IS_NINF(num))
4599 0 : val = -HUGE_VAL;
4600 : else
4601 0 : val = get_float8_nan();
4602 : }
4603 : else
4604 : {
4605 : NumericVar x;
4606 :
4607 30 : init_var_from_num(num, &x);
4608 30 : val = numericvar_to_double_no_overflow(&x);
4609 : }
4610 :
4611 30 : PG_RETURN_FLOAT8(val);
4612 : }
4613 :
4614 : Datum
4615 22582 : float4_numeric(PG_FUNCTION_ARGS)
4616 : {
4617 22582 : float4 val = PG_GETARG_FLOAT4(0);
4618 : Numeric res;
4619 : NumericVar result;
4620 : char buf[FLT_DIG + 100];
4621 : const char *endptr;
4622 :
4623 22582 : if (isnan(val))
4624 6 : PG_RETURN_NUMERIC(make_result(&const_nan));
4625 :
4626 22576 : if (isinf(val))
4627 : {
4628 12 : if (val < 0)
4629 6 : PG_RETURN_NUMERIC(make_result(&const_ninf));
4630 : else
4631 6 : PG_RETURN_NUMERIC(make_result(&const_pinf));
4632 : }
4633 :
4634 22564 : snprintf(buf, sizeof(buf), "%.*g", FLT_DIG, val);
4635 :
4636 22564 : init_var(&result);
4637 :
4638 : /* Assume we need not worry about leading/trailing spaces */
4639 22564 : (void) set_var_from_str(buf, buf, &result, &endptr, NULL);
4640 :
4641 22564 : res = make_result(&result);
4642 :
4643 22564 : free_var(&result);
4644 :
4645 22564 : PG_RETURN_NUMERIC(res);
4646 : }
4647 :
4648 :
4649 : Datum
4650 2456 : numeric_float4(PG_FUNCTION_ARGS)
4651 : {
4652 2456 : Numeric num = PG_GETARG_NUMERIC(0);
4653 : char *tmp;
4654 : Datum result;
4655 :
4656 2456 : if (NUMERIC_IS_SPECIAL(num))
4657 : {
4658 78 : if (NUMERIC_IS_PINF(num))
4659 24 : PG_RETURN_FLOAT4(get_float4_infinity());
4660 54 : else if (NUMERIC_IS_NINF(num))
4661 24 : PG_RETURN_FLOAT4(-get_float4_infinity());
4662 : else
4663 30 : PG_RETURN_FLOAT4(get_float4_nan());
4664 : }
4665 :
4666 2378 : tmp = DatumGetCString(DirectFunctionCall1(numeric_out,
4667 : NumericGetDatum(num)));
4668 :
4669 2378 : result = DirectFunctionCall1(float4in, CStringGetDatum(tmp));
4670 :
4671 2378 : pfree(tmp);
4672 :
4673 2378 : PG_RETURN_DATUM(result);
4674 : }
4675 :
4676 :
4677 : Datum
4678 124 : numeric_pg_lsn(PG_FUNCTION_ARGS)
4679 : {
4680 124 : Numeric num = PG_GETARG_NUMERIC(0);
4681 : NumericVar x;
4682 : XLogRecPtr result;
4683 :
4684 124 : if (NUMERIC_IS_SPECIAL(num))
4685 : {
4686 6 : if (NUMERIC_IS_NAN(num))
4687 6 : ereport(ERROR,
4688 : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4689 : errmsg("cannot convert NaN to %s", "pg_lsn")));
4690 : else
4691 0 : ereport(ERROR,
4692 : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4693 : errmsg("cannot convert infinity to %s", "pg_lsn")));
4694 : }
4695 :
4696 : /* Convert to variable format and thence to pg_lsn */
4697 118 : init_var_from_num(num, &x);
4698 :
4699 118 : if (!numericvar_to_uint64(&x, (uint64 *) &result))
4700 24 : ereport(ERROR,
4701 : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4702 : errmsg("pg_lsn out of range")));
4703 :
4704 94 : PG_RETURN_LSN(result);
4705 : }
4706 :
4707 :
4708 : /* ----------------------------------------------------------------------
4709 : *
4710 : * Aggregate functions
4711 : *
4712 : * The transition datatype for all these aggregates is declared as INTERNAL.
4713 : * Actually, it's a pointer to a NumericAggState allocated in the aggregate
4714 : * context. The digit buffers for the NumericVars will be there too.
4715 : *
4716 : * For integer inputs, some aggregates use special-purpose 64-bit or 128-bit
4717 : * integer based transition datatypes to speed up calculations.
4718 : *
4719 : * ----------------------------------------------------------------------
4720 : */
4721 :
4722 : typedef struct NumericAggState
4723 : {
4724 : bool calcSumX2; /* if true, calculate sumX2 */
4725 : MemoryContext agg_context; /* context we're calculating in */
4726 : int64 N; /* count of processed numbers */
4727 : NumericSumAccum sumX; /* sum of processed numbers */
4728 : NumericSumAccum sumX2; /* sum of squares of processed numbers */
4729 : int maxScale; /* maximum scale seen so far */
4730 : int64 maxScaleCount; /* number of values seen with maximum scale */
4731 : /* These counts are *not* included in N! Use NA_TOTAL_COUNT() as needed */
4732 : int64 NaNcount; /* count of NaN values */
4733 : int64 pInfcount; /* count of +Inf values */
4734 : int64 nInfcount; /* count of -Inf values */
4735 : } NumericAggState;
4736 :
4737 : #define NA_TOTAL_COUNT(na) \
4738 : ((na)->N + (na)->NaNcount + (na)->pInfcount + (na)->nInfcount)
4739 :
4740 : /*
4741 : * Prepare state data for a numeric aggregate function that needs to compute
4742 : * sum, count and optionally sum of squares of the input.
4743 : */
4744 : static NumericAggState *
4745 171140 : makeNumericAggState(FunctionCallInfo fcinfo, bool calcSumX2)
4746 : {
4747 : NumericAggState *state;
4748 : MemoryContext agg_context;
4749 : MemoryContext old_context;
4750 :
4751 171140 : if (!AggCheckCallContext(fcinfo, &agg_context))
4752 0 : elog(ERROR, "aggregate function called in non-aggregate context");
4753 :
4754 171140 : old_context = MemoryContextSwitchTo(agg_context);
4755 :
4756 171140 : state = palloc0_object(NumericAggState);
4757 171140 : state->calcSumX2 = calcSumX2;
4758 171140 : state->agg_context = agg_context;
4759 :
4760 171140 : MemoryContextSwitchTo(old_context);
4761 :
4762 171140 : return state;
4763 : }
4764 :
4765 : /*
4766 : * Like makeNumericAggState(), but allocate the state in the current memory
4767 : * context.
4768 : */
4769 : static NumericAggState *
4770 84 : makeNumericAggStateCurrentContext(bool calcSumX2)
4771 : {
4772 : NumericAggState *state;
4773 :
4774 84 : state = palloc0_object(NumericAggState);
4775 84 : state->calcSumX2 = calcSumX2;
4776 84 : state->agg_context = CurrentMemoryContext;
4777 :
4778 84 : return state;
4779 : }
4780 :
4781 : /*
4782 : * Accumulate a new input value for numeric aggregate functions.
4783 : */
4784 : static void
4785 2113552 : do_numeric_accum(NumericAggState *state, Numeric newval)
4786 : {
4787 : NumericVar X;
4788 : NumericVar X2;
4789 : MemoryContext old_context;
4790 :
4791 : /* Count NaN/infinity inputs separately from all else */
4792 2113552 : if (NUMERIC_IS_SPECIAL(newval))
4793 : {
4794 162 : if (NUMERIC_IS_PINF(newval))
4795 72 : state->pInfcount++;
4796 90 : else if (NUMERIC_IS_NINF(newval))
4797 36 : state->nInfcount++;
4798 : else
4799 54 : state->NaNcount++;
4800 162 : return;
4801 : }
4802 :
4803 : /* load processed number in short-lived context */
4804 2113390 : init_var_from_num(newval, &X);
4805 :
4806 : /*
4807 : * Track the highest input dscale that we've seen, to support inverse
4808 : * transitions (see do_numeric_discard).
4809 : */
4810 2113390 : if (X.dscale > state->maxScale)
4811 : {
4812 156 : state->maxScale = X.dscale;
4813 156 : state->maxScaleCount = 1;
4814 : }
4815 2113234 : else if (X.dscale == state->maxScale)
4816 2113198 : state->maxScaleCount++;
4817 :
4818 : /* if we need X^2, calculate that in short-lived context */
4819 2113390 : if (state->calcSumX2)
4820 : {
4821 240732 : init_var(&X2);
4822 240732 : mul_var(&X, &X, &X2, X.dscale * 2);
4823 : }
4824 :
4825 : /* The rest of this needs to work in the aggregate context */
4826 2113390 : old_context = MemoryContextSwitchTo(state->agg_context);
4827 :
4828 2113390 : state->N++;
4829 :
4830 : /* Accumulate sums */
4831 2113390 : accum_sum_add(&(state->sumX), &X);
4832 :
4833 2113390 : if (state->calcSumX2)
4834 240732 : accum_sum_add(&(state->sumX2), &X2);
4835 :
4836 2113390 : MemoryContextSwitchTo(old_context);
4837 : }
4838 :
4839 : /*
4840 : * Attempt to remove an input value from the aggregated state.
4841 : *
4842 : * If the value cannot be removed then the function will return false; the
4843 : * possible reasons for failing are described below.
4844 : *
4845 : * If we aggregate the values 1.01 and 2 then the result will be 3.01.
4846 : * If we are then asked to un-aggregate the 1.01 then we must fail as we
4847 : * won't be able to tell what the new aggregated value's dscale should be.
4848 : * We don't want to return 2.00 (dscale = 2), since the sum's dscale would
4849 : * have been zero if we'd really aggregated only 2.
4850 : *
4851 : * Note: alternatively, we could count the number of inputs with each possible
4852 : * dscale (up to some sane limit). Not yet clear if it's worth the trouble.
4853 : */
4854 : static bool
4855 342 : do_numeric_discard(NumericAggState *state, Numeric newval)
4856 : {
4857 : NumericVar X;
4858 : NumericVar X2;
4859 : MemoryContext old_context;
4860 :
4861 : /* Count NaN/infinity inputs separately from all else */
4862 342 : if (NUMERIC_IS_SPECIAL(newval))
4863 : {
4864 6 : if (NUMERIC_IS_PINF(newval))
4865 0 : state->pInfcount--;
4866 6 : else if (NUMERIC_IS_NINF(newval))
4867 0 : state->nInfcount--;
4868 : else
4869 6 : state->NaNcount--;
4870 6 : return true;
4871 : }
4872 :
4873 : /* load processed number in short-lived context */
4874 336 : init_var_from_num(newval, &X);
4875 :
4876 : /*
4877 : * state->sumX's dscale is the maximum dscale of any of the inputs.
4878 : * Removing the last input with that dscale would require us to recompute
4879 : * the maximum dscale of the *remaining* inputs, which we cannot do unless
4880 : * no more non-NaN inputs remain at all. So we report a failure instead,
4881 : * and force the aggregation to be redone from scratch.
4882 : */
4883 336 : if (X.dscale == state->maxScale)
4884 : {
4885 336 : if (state->maxScaleCount > 1 || state->maxScale == 0)
4886 : {
4887 : /*
4888 : * Some remaining inputs have same dscale, or dscale hasn't gotten
4889 : * above zero anyway
4890 : */
4891 318 : state->maxScaleCount--;
4892 : }
4893 18 : else if (state->N == 1)
4894 : {
4895 : /* No remaining non-NaN inputs at all, so reset maxScale */
4896 12 : state->maxScale = 0;
4897 12 : state->maxScaleCount = 0;
4898 : }
4899 : else
4900 : {
4901 : /* Correct new maxScale is uncertain, must fail */
4902 6 : return false;
4903 : }
4904 : }
4905 :
4906 : /* if we need X^2, calculate that in short-lived context */
4907 330 : if (state->calcSumX2)
4908 : {
4909 288 : init_var(&X2);
4910 288 : mul_var(&X, &X, &X2, X.dscale * 2);
4911 : }
4912 :
4913 : /* The rest of this needs to work in the aggregate context */
4914 330 : old_context = MemoryContextSwitchTo(state->agg_context);
4915 :
4916 330 : if (state->N-- > 1)
4917 : {
4918 : /* Negate X, to subtract it from the sum */
4919 312 : X.sign = (X.sign == NUMERIC_POS ? NUMERIC_NEG : NUMERIC_POS);
4920 312 : accum_sum_add(&(state->sumX), &X);
4921 :
4922 312 : if (state->calcSumX2)
4923 : {
4924 : /* Negate X^2. X^2 is always positive */
4925 288 : X2.sign = NUMERIC_NEG;
4926 288 : accum_sum_add(&(state->sumX2), &X2);
4927 : }
4928 : }
4929 : else
4930 : {
4931 : /* Zero the sums */
4932 : Assert(state->N == 0);
4933 :
4934 18 : accum_sum_reset(&state->sumX);
4935 18 : if (state->calcSumX2)
4936 0 : accum_sum_reset(&state->sumX2);
4937 : }
4938 :
4939 330 : MemoryContextSwitchTo(old_context);
4940 :
4941 330 : return true;
4942 : }
4943 :
4944 : /*
4945 : * Generic transition function for numeric aggregates that require sumX2.
4946 : */
4947 : Datum
4948 642 : numeric_accum(PG_FUNCTION_ARGS)
4949 : {
4950 : NumericAggState *state;
4951 :
4952 642 : state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
4953 :
4954 : /* Create the state data on the first call */
4955 642 : if (state == NULL)
4956 174 : state = makeNumericAggState(fcinfo, true);
4957 :
4958 642 : if (!PG_ARGISNULL(1))
4959 624 : do_numeric_accum(state, PG_GETARG_NUMERIC(1));
4960 :
4961 642 : PG_RETURN_POINTER(state);
4962 : }
4963 :
4964 : /*
4965 : * Generic combine function for numeric aggregates which require sumX2
4966 : */
4967 : Datum
4968 36 : numeric_combine(PG_FUNCTION_ARGS)
4969 : {
4970 : NumericAggState *state1;
4971 : NumericAggState *state2;
4972 : MemoryContext agg_context;
4973 : MemoryContext old_context;
4974 :
4975 36 : if (!AggCheckCallContext(fcinfo, &agg_context))
4976 0 : elog(ERROR, "aggregate function called in non-aggregate context");
4977 :
4978 36 : state1 = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
4979 36 : state2 = PG_ARGISNULL(1) ? NULL : (NumericAggState *) PG_GETARG_POINTER(1);
4980 :
4981 36 : if (state2 == NULL)
4982 0 : PG_RETURN_POINTER(state1);
4983 :
4984 : /* manually copy all fields from state2 to state1 */
4985 36 : if (state1 == NULL)
4986 : {
4987 18 : old_context = MemoryContextSwitchTo(agg_context);
4988 :
4989 18 : state1 = makeNumericAggStateCurrentContext(true);
4990 18 : state1->N = state2->N;
4991 18 : state1->NaNcount = state2->NaNcount;
4992 18 : state1->pInfcount = state2->pInfcount;
4993 18 : state1->nInfcount = state2->nInfcount;
4994 18 : state1->maxScale = state2->maxScale;
4995 18 : state1->maxScaleCount = state2->maxScaleCount;
4996 :
4997 18 : accum_sum_copy(&state1->sumX, &state2->sumX);
4998 18 : accum_sum_copy(&state1->sumX2, &state2->sumX2);
4999 :
5000 18 : MemoryContextSwitchTo(old_context);
5001 :
5002 18 : PG_RETURN_POINTER(state1);
5003 : }
5004 :
5005 18 : state1->N += state2->N;
5006 18 : state1->NaNcount += state2->NaNcount;
5007 18 : state1->pInfcount += state2->pInfcount;
5008 18 : state1->nInfcount += state2->nInfcount;
5009 :
5010 18 : if (state2->N > 0)
5011 : {
5012 : /*
5013 : * These are currently only needed for moving aggregates, but let's do
5014 : * the right thing anyway...
5015 : */
5016 18 : if (state2->maxScale > state1->maxScale)
5017 : {
5018 0 : state1->maxScale = state2->maxScale;
5019 0 : state1->maxScaleCount = state2->maxScaleCount;
5020 : }
5021 18 : else if (state2->maxScale == state1->maxScale)
5022 18 : state1->maxScaleCount += state2->maxScaleCount;
5023 :
5024 : /* The rest of this needs to work in the aggregate context */
5025 18 : old_context = MemoryContextSwitchTo(agg_context);
5026 :
5027 : /* Accumulate sums */
5028 18 : accum_sum_combine(&state1->sumX, &state2->sumX);
5029 18 : accum_sum_combine(&state1->sumX2, &state2->sumX2);
5030 :
5031 18 : MemoryContextSwitchTo(old_context);
5032 : }
5033 18 : PG_RETURN_POINTER(state1);
5034 : }
5035 :
5036 : /*
5037 : * Generic transition function for numeric aggregates that don't require sumX2.
5038 : */
5039 : Datum
5040 1872808 : numeric_avg_accum(PG_FUNCTION_ARGS)
5041 : {
5042 : NumericAggState *state;
5043 :
5044 1872808 : state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
5045 :
5046 : /* Create the state data on the first call */
5047 1872808 : if (state == NULL)
5048 170906 : state = makeNumericAggState(fcinfo, false);
5049 :
5050 1872808 : if (!PG_ARGISNULL(1))
5051 1872748 : do_numeric_accum(state, PG_GETARG_NUMERIC(1));
5052 :
5053 1872808 : PG_RETURN_POINTER(state);
5054 : }
5055 :
5056 : /*
5057 : * Combine function for numeric aggregates which don't require sumX2
5058 : */
5059 : Datum
5060 24 : numeric_avg_combine(PG_FUNCTION_ARGS)
5061 : {
5062 : NumericAggState *state1;
5063 : NumericAggState *state2;
5064 : MemoryContext agg_context;
5065 : MemoryContext old_context;
5066 :
5067 24 : if (!AggCheckCallContext(fcinfo, &agg_context))
5068 0 : elog(ERROR, "aggregate function called in non-aggregate context");
5069 :
5070 24 : state1 = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
5071 24 : state2 = PG_ARGISNULL(1) ? NULL : (NumericAggState *) PG_GETARG_POINTER(1);
5072 :
5073 24 : if (state2 == NULL)
5074 0 : PG_RETURN_POINTER(state1);
5075 :
5076 : /* manually copy all fields from state2 to state1 */
5077 24 : if (state1 == NULL)
5078 : {
5079 6 : old_context = MemoryContextSwitchTo(agg_context);
5080 :
5081 6 : state1 = makeNumericAggStateCurrentContext(false);
5082 6 : state1->N = state2->N;
5083 6 : state1->NaNcount = state2->NaNcount;
5084 6 : state1->pInfcount = state2->pInfcount;
5085 6 : state1->nInfcount = state2->nInfcount;
5086 6 : state1->maxScale = state2->maxScale;
5087 6 : state1->maxScaleCount = state2->maxScaleCount;
5088 :
5089 6 : accum_sum_copy(&state1->sumX, &state2->sumX);
5090 :
5091 6 : MemoryContextSwitchTo(old_context);
5092 :
5093 6 : PG_RETURN_POINTER(state1);
5094 : }
5095 :
5096 18 : state1->N += state2->N;
5097 18 : state1->NaNcount += state2->NaNcount;
5098 18 : state1->pInfcount += state2->pInfcount;
5099 18 : state1->nInfcount += state2->nInfcount;
5100 :
5101 18 : if (state2->N > 0)
5102 : {
5103 : /*
5104 : * These are currently only needed for moving aggregates, but let's do
5105 : * the right thing anyway...
5106 : */
5107 18 : if (state2->maxScale > state1->maxScale)
5108 : {
5109 0 : state1->maxScale = state2->maxScale;
5110 0 : state1->maxScaleCount = state2->maxScaleCount;
5111 : }
5112 18 : else if (state2->maxScale == state1->maxScale)
5113 18 : state1->maxScaleCount += state2->maxScaleCount;
5114 :
5115 : /* The rest of this needs to work in the aggregate context */
5116 18 : old_context = MemoryContextSwitchTo(agg_context);
5117 :
5118 : /* Accumulate sums */
5119 18 : accum_sum_combine(&state1->sumX, &state2->sumX);
5120 :
5121 18 : MemoryContextSwitchTo(old_context);
5122 : }
5123 18 : PG_RETURN_POINTER(state1);
5124 : }
5125 :
5126 : /*
5127 : * numeric_avg_serialize
5128 : * Serialize NumericAggState for numeric aggregates that don't require
5129 : * sumX2.
5130 : */
5131 : Datum
5132 24 : numeric_avg_serialize(PG_FUNCTION_ARGS)
5133 : {
5134 : NumericAggState *state;
5135 : StringInfoData buf;
5136 : bytea *result;
5137 : NumericVar tmp_var;
5138 :
5139 : /* Ensure we disallow calling when not in aggregate context */
5140 24 : if (!AggCheckCallContext(fcinfo, NULL))
5141 0 : elog(ERROR, "aggregate function called in non-aggregate context");
5142 :
5143 24 : state = (NumericAggState *) PG_GETARG_POINTER(0);
5144 :
5145 24 : init_var(&tmp_var);
5146 :
5147 24 : pq_begintypsend(&buf);
5148 :
5149 : /* N */
5150 24 : pq_sendint64(&buf, state->N);
5151 :
5152 : /* sumX */
5153 24 : accum_sum_final(&state->sumX, &tmp_var);
5154 24 : numericvar_serialize(&buf, &tmp_var);
5155 :
5156 : /* maxScale */
5157 24 : pq_sendint32(&buf, state->maxScale);
5158 :
5159 : /* maxScaleCount */
5160 24 : pq_sendint64(&buf, state->maxScaleCount);
5161 :
5162 : /* NaNcount */
5163 24 : pq_sendint64(&buf, state->NaNcount);
5164 :
5165 : /* pInfcount */
5166 24 : pq_sendint64(&buf, state->pInfcount);
5167 :
5168 : /* nInfcount */
5169 24 : pq_sendint64(&buf, state->nInfcount);
5170 :
5171 24 : result = pq_endtypsend(&buf);
5172 :
5173 24 : free_var(&tmp_var);
5174 :
5175 24 : PG_RETURN_BYTEA_P(result);
5176 : }
5177 :
5178 : /*
5179 : * numeric_avg_deserialize
5180 : * Deserialize bytea into NumericAggState for numeric aggregates that
5181 : * don't require sumX2.
5182 : */
5183 : Datum
5184 24 : numeric_avg_deserialize(PG_FUNCTION_ARGS)
5185 : {
5186 : bytea *sstate;
5187 : NumericAggState *result;
5188 : StringInfoData buf;
5189 : NumericVar tmp_var;
5190 :
5191 24 : if (!AggCheckCallContext(fcinfo, NULL))
5192 0 : elog(ERROR, "aggregate function called in non-aggregate context");
5193 :
5194 24 : sstate = PG_GETARG_BYTEA_PP(0);
5195 :
5196 24 : init_var(&tmp_var);
5197 :
5198 : /*
5199 : * Initialize a StringInfo so that we can "receive" it using the standard
5200 : * recv-function infrastructure.
5201 : */
5202 24 : initReadOnlyStringInfo(&buf, VARDATA_ANY(sstate),
5203 24 : VARSIZE_ANY_EXHDR(sstate));
5204 :
5205 24 : result = makeNumericAggStateCurrentContext(false);
5206 :
5207 : /* N */
5208 24 : result->N = pq_getmsgint64(&buf);
5209 :
5210 : /* sumX */
5211 24 : numericvar_deserialize(&buf, &tmp_var);
5212 24 : accum_sum_add(&(result->sumX), &tmp_var);
5213 :
5214 : /* maxScale */
5215 24 : result->maxScale = pq_getmsgint(&buf, 4);
5216 :
5217 : /* maxScaleCount */
5218 24 : result->maxScaleCount = pq_getmsgint64(&buf);
5219 :
5220 : /* NaNcount */
5221 24 : result->NaNcount = pq_getmsgint64(&buf);
5222 :
5223 : /* pInfcount */
5224 24 : result->pInfcount = pq_getmsgint64(&buf);
5225 :
5226 : /* nInfcount */
5227 24 : result->nInfcount = pq_getmsgint64(&buf);
5228 :
5229 24 : pq_getmsgend(&buf);
5230 :
5231 24 : free_var(&tmp_var);
5232 :
5233 24 : PG_RETURN_POINTER(result);
5234 : }
5235 :
5236 : /*
5237 : * numeric_serialize
5238 : * Serialization function for NumericAggState for numeric aggregates that
5239 : * require sumX2.
5240 : */
5241 : Datum
5242 36 : numeric_serialize(PG_FUNCTION_ARGS)
5243 : {
5244 : NumericAggState *state;
5245 : StringInfoData buf;
5246 : bytea *result;
5247 : NumericVar tmp_var;
5248 :
5249 : /* Ensure we disallow calling when not in aggregate context */
5250 36 : if (!AggCheckCallContext(fcinfo, NULL))
5251 0 : elog(ERROR, "aggregate function called in non-aggregate context");
5252 :
5253 36 : state = (NumericAggState *) PG_GETARG_POINTER(0);
5254 :
5255 36 : init_var(&tmp_var);
5256 :
5257 36 : pq_begintypsend(&buf);
5258 :
5259 : /* N */
5260 36 : pq_sendint64(&buf, state->N);
5261 :
5262 : /* sumX */
5263 36 : accum_sum_final(&state->sumX, &tmp_var);
5264 36 : numericvar_serialize(&buf, &tmp_var);
5265 :
5266 : /* sumX2 */
5267 36 : accum_sum_final(&state->sumX2, &tmp_var);
5268 36 : numericvar_serialize(&buf, &tmp_var);
5269 :
5270 : /* maxScale */
5271 36 : pq_sendint32(&buf, state->maxScale);
5272 :
5273 : /* maxScaleCount */
5274 36 : pq_sendint64(&buf, state->maxScaleCount);
5275 :
5276 : /* NaNcount */
5277 36 : pq_sendint64(&buf, state->NaNcount);
5278 :
5279 : /* pInfcount */
5280 36 : pq_sendint64(&buf, state->pInfcount);
5281 :
5282 : /* nInfcount */
5283 36 : pq_sendint64(&buf, state->nInfcount);
5284 :
5285 36 : result = pq_endtypsend(&buf);
5286 :
5287 36 : free_var(&tmp_var);
5288 :
5289 36 : PG_RETURN_BYTEA_P(result);
5290 : }
5291 :
5292 : /*
5293 : * numeric_deserialize
5294 : * Deserialization function for NumericAggState for numeric aggregates that
5295 : * require sumX2.
5296 : */
5297 : Datum
5298 36 : numeric_deserialize(PG_FUNCTION_ARGS)
5299 : {
5300 : bytea *sstate;
5301 : NumericAggState *result;
5302 : StringInfoData buf;
5303 : NumericVar tmp_var;
5304 :
5305 36 : if (!AggCheckCallContext(fcinfo, NULL))
5306 0 : elog(ERROR, "aggregate function called in non-aggregate context");
5307 :
5308 36 : sstate = PG_GETARG_BYTEA_PP(0);
5309 :
5310 36 : init_var(&tmp_var);
5311 :
5312 : /*
5313 : * Initialize a StringInfo so that we can "receive" it using the standard
5314 : * recv-function infrastructure.
5315 : */
5316 36 : initReadOnlyStringInfo(&buf, VARDATA_ANY(sstate),
5317 36 : VARSIZE_ANY_EXHDR(sstate));
5318 :
5319 36 : result = makeNumericAggStateCurrentContext(false);
5320 :
5321 : /* N */
5322 36 : result->N = pq_getmsgint64(&buf);
5323 :
5324 : /* sumX */
5325 36 : numericvar_deserialize(&buf, &tmp_var);
5326 36 : accum_sum_add(&(result->sumX), &tmp_var);
5327 :
5328 : /* sumX2 */
5329 36 : numericvar_deserialize(&buf, &tmp_var);
5330 36 : accum_sum_add(&(result->sumX2), &tmp_var);
5331 :
5332 : /* maxScale */
5333 36 : result->maxScale = pq_getmsgint(&buf, 4);
5334 :
5335 : /* maxScaleCount */
5336 36 : result->maxScaleCount = pq_getmsgint64(&buf);
5337 :
5338 : /* NaNcount */
5339 36 : result->NaNcount = pq_getmsgint64(&buf);
5340 :
5341 : /* pInfcount */
5342 36 : result->pInfcount = pq_getmsgint64(&buf);
5343 :
5344 : /* nInfcount */
5345 36 : result->nInfcount = pq_getmsgint64(&buf);
5346 :
5347 36 : pq_getmsgend(&buf);
5348 :
5349 36 : free_var(&tmp_var);
5350 :
5351 36 : PG_RETURN_POINTER(result);
5352 : }
5353 :
5354 : /*
5355 : * Generic inverse transition function for numeric aggregates
5356 : * (with or without requirement for X^2).
5357 : */
5358 : Datum
5359 228 : numeric_accum_inv(PG_FUNCTION_ARGS)
5360 : {
5361 : NumericAggState *state;
5362 :
5363 228 : state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
5364 :
5365 : /* Should not get here with no state */
5366 228 : if (state == NULL)
5367 0 : elog(ERROR, "numeric_accum_inv called with NULL state");
5368 :
5369 228 : if (!PG_ARGISNULL(1))
5370 : {
5371 : /* If we fail to perform the inverse transition, return NULL */
5372 198 : if (!do_numeric_discard(state, PG_GETARG_NUMERIC(1)))
5373 6 : PG_RETURN_NULL();
5374 : }
5375 :
5376 222 : PG_RETURN_POINTER(state);
5377 : }
5378 :
5379 :
5380 : /*
5381 : * Integer data types in general use Numeric accumulators to share code and
5382 : * avoid risk of overflow. However for performance reasons optimized
5383 : * special-purpose accumulator routines are used when possible:
5384 : *
5385 : * For 16-bit and 32-bit inputs, N and sum(X) fit into 64-bit, so 64-bit
5386 : * accumulators are used for SUM and AVG of these data types.
5387 : *
5388 : * For 16-bit and 32-bit inputs, sum(X^2) fits into 128-bit, so 128-bit
5389 : * accumulators are used for STDDEV_POP, STDDEV_SAMP, VAR_POP, and VAR_SAMP of
5390 : * these data types.
5391 : *
5392 : * For 64-bit inputs, sum(X) fits into 128-bit, so a 128-bit accumulator is
5393 : * used for SUM(int8) and AVG(int8).
5394 : */
5395 :
5396 : typedef struct Int128AggState
5397 : {
5398 : bool calcSumX2; /* if true, calculate sumX2 */
5399 : int64 N; /* count of processed numbers */
5400 : INT128 sumX; /* sum of processed numbers */
5401 : INT128 sumX2; /* sum of squares of processed numbers */
5402 : } Int128AggState;
5403 :
5404 : /*
5405 : * Prepare state data for a 128-bit aggregate function that needs to compute
5406 : * sum, count and optionally sum of squares of the input.
5407 : */
5408 : static Int128AggState *
5409 956 : makeInt128AggState(FunctionCallInfo fcinfo, bool calcSumX2)
5410 : {
5411 : Int128AggState *state;
5412 : MemoryContext agg_context;
5413 : MemoryContext old_context;
5414 :
5415 956 : if (!AggCheckCallContext(fcinfo, &agg_context))
5416 0 : elog(ERROR, "aggregate function called in non-aggregate context");
5417 :
5418 956 : old_context = MemoryContextSwitchTo(agg_context);
5419 :
5420 956 : state = palloc0_object(Int128AggState);
5421 956 : state->calcSumX2 = calcSumX2;
5422 :
5423 956 : MemoryContextSwitchTo(old_context);
5424 :
5425 956 : return state;
5426 : }
5427 :
5428 : /*
5429 : * Like makeInt128AggState(), but allocate the state in the current memory
5430 : * context.
5431 : */
5432 : static Int128AggState *
5433 42 : makeInt128AggStateCurrentContext(bool calcSumX2)
5434 : {
5435 : Int128AggState *state;
5436 :
5437 42 : state = palloc0_object(Int128AggState);
5438 42 : state->calcSumX2 = calcSumX2;
5439 :
5440 42 : return state;
5441 : }
5442 :
5443 : /*
5444 : * Accumulate a new input value for 128-bit aggregate functions.
5445 : */
5446 : static void
5447 557478 : do_int128_accum(Int128AggState *state, int64 newval)
5448 : {
5449 557478 : if (state->calcSumX2)
5450 242360 : int128_add_int64_mul_int64(&state->sumX2, newval, newval);
5451 :
5452 557478 : int128_add_int64(&state->sumX, newval);
5453 557478 : state->N++;
5454 557478 : }
5455 :
5456 : /*
5457 : * Remove an input value from the aggregated state.
5458 : */
5459 : static void
5460 312 : do_int128_discard(Int128AggState *state, int64 newval)
5461 : {
5462 312 : if (state->calcSumX2)
5463 288 : int128_sub_int64_mul_int64(&state->sumX2, newval, newval);
5464 :
5465 312 : int128_sub_int64(&state->sumX, newval);
5466 312 : state->N--;
5467 312 : }
5468 :
5469 : Datum
5470 198 : int2_accum(PG_FUNCTION_ARGS)
5471 : {
5472 : Int128AggState *state;
5473 :
5474 198 : state = PG_ARGISNULL(0) ? NULL : (Int128AggState *) PG_GETARG_POINTER(0);
5475 :
5476 : /* Create the state data on the first call */
5477 198 : if (state == NULL)
5478 36 : state = makeInt128AggState(fcinfo, true);
5479 :
5480 198 : if (!PG_ARGISNULL(1))
5481 180 : do_int128_accum(state, PG_GETARG_INT16(1));
5482 :
5483 198 : PG_RETURN_POINTER(state);
5484 : }
5485 :
5486 : Datum
5487 242198 : int4_accum(PG_FUNCTION_ARGS)
5488 : {
5489 : Int128AggState *state;
5490 :
5491 242198 : state = PG_ARGISNULL(0) ? NULL : (Int128AggState *) PG_GETARG_POINTER(0);
5492 :
5493 : /* Create the state data on the first call */
5494 242198 : if (state == NULL)
5495 74 : state = makeInt128AggState(fcinfo, true);
5496 :
5497 242198 : if (!PG_ARGISNULL(1))
5498 242180 : do_int128_accum(state, PG_GETARG_INT32(1));
5499 :
5500 242198 : PG_RETURN_POINTER(state);
5501 : }
5502 :
5503 : Datum
5504 240198 : int8_accum(PG_FUNCTION_ARGS)
5505 : {
5506 : NumericAggState *state;
5507 :
5508 240198 : state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
5509 :
5510 : /* Create the state data on the first call */
5511 240198 : if (state == NULL)
5512 60 : state = makeNumericAggState(fcinfo, true);
5513 :
5514 240198 : if (!PG_ARGISNULL(1))
5515 240180 : do_numeric_accum(state, int64_to_numeric(PG_GETARG_INT64(1)));
5516 :
5517 240198 : PG_RETURN_POINTER(state);
5518 : }
5519 :
5520 : /*
5521 : * Combine function for Int128AggState for aggregates which require sumX2
5522 : */
5523 : Datum
5524 18 : numeric_poly_combine(PG_FUNCTION_ARGS)
5525 : {
5526 : Int128AggState *state1;
5527 : Int128AggState *state2;
5528 : MemoryContext agg_context;
5529 : MemoryContext old_context;
5530 :
5531 18 : if (!AggCheckCallContext(fcinfo, &agg_context))
5532 0 : elog(ERROR, "aggregate function called in non-aggregate context");
5533 :
5534 18 : state1 = PG_ARGISNULL(0) ? NULL : (Int128AggState *) PG_GETARG_POINTER(0);
5535 18 : state2 = PG_ARGISNULL(1) ? NULL : (Int128AggState *) PG_GETARG_POINTER(1);
5536 :
5537 18 : if (state2 == NULL)
5538 0 : PG_RETURN_POINTER(state1);
5539 :
5540 : /* manually copy all fields from state2 to state1 */
5541 18 : if (state1 == NULL)
5542 : {
5543 6 : old_context = MemoryContextSwitchTo(agg_context);
5544 :
5545 6 : state1 = makeInt128AggState(fcinfo, true);
5546 6 : state1->N = state2->N;
5547 6 : state1->sumX = state2->sumX;
5548 6 : state1->sumX2 = state2->sumX2;
5549 :
5550 6 : MemoryContextSwitchTo(old_context);
5551 :
5552 6 : PG_RETURN_POINTER(state1);
5553 : }
5554 :
5555 12 : if (state2->N > 0)
5556 : {
5557 12 : state1->N += state2->N;
5558 12 : int128_add_int128(&state1->sumX, state2->sumX);
5559 12 : int128_add_int128(&state1->sumX2, state2->sumX2);
5560 : }
5561 12 : PG_RETURN_POINTER(state1);
5562 : }
5563 :
5564 : /*
5565 : * int128_serialize - serialize a 128-bit integer to binary format
5566 : */
5567 : static inline void
5568 60 : int128_serialize(StringInfo buf, INT128 val)
5569 : {
5570 60 : pq_sendint64(buf, PG_INT128_HI_INT64(val));
5571 60 : pq_sendint64(buf, PG_INT128_LO_UINT64(val));
5572 60 : }
5573 :
5574 : /*
5575 : * int128_deserialize - deserialize binary format to a 128-bit integer.
5576 : */
5577 : static inline INT128
5578 60 : int128_deserialize(StringInfo buf)
5579 : {
5580 60 : int64 hi = pq_getmsgint64(buf);
5581 60 : uint64 lo = pq_getmsgint64(buf);
5582 :
5583 60 : return make_int128(hi, lo);
5584 : }
5585 :
5586 : /*
5587 : * numeric_poly_serialize
5588 : * Serialize Int128AggState into bytea for aggregate functions which
5589 : * require sumX2.
5590 : */
5591 : Datum
5592 18 : numeric_poly_serialize(PG_FUNCTION_ARGS)
5593 : {
5594 : Int128AggState *state;
5595 : StringInfoData buf;
5596 : bytea *result;
5597 :
5598 : /* Ensure we disallow calling when not in aggregate context */
5599 18 : if (!AggCheckCallContext(fcinfo, NULL))
5600 0 : elog(ERROR, "aggregate function called in non-aggregate context");
5601 :
5602 18 : state = (Int128AggState *) PG_GETARG_POINTER(0);
5603 :
5604 18 : pq_begintypsend(&buf);
5605 :
5606 : /* N */
5607 18 : pq_sendint64(&buf, state->N);
5608 :
5609 : /* sumX */
5610 18 : int128_serialize(&buf, state->sumX);
5611 :
5612 : /* sumX2 */
5613 18 : int128_serialize(&buf, state->sumX2);
5614 :
5615 18 : result = pq_endtypsend(&buf);
5616 :
5617 18 : PG_RETURN_BYTEA_P(result);
5618 : }
5619 :
5620 : /*
5621 : * numeric_poly_deserialize
5622 : * Deserialize Int128AggState from bytea for aggregate functions which
5623 : * require sumX2.
5624 : */
5625 : Datum
5626 18 : numeric_poly_deserialize(PG_FUNCTION_ARGS)
5627 : {
5628 : bytea *sstate;
5629 : Int128AggState *result;
5630 : StringInfoData buf;
5631 :
5632 18 : if (!AggCheckCallContext(fcinfo, NULL))
5633 0 : elog(ERROR, "aggregate function called in non-aggregate context");
5634 :
5635 18 : sstate = PG_GETARG_BYTEA_PP(0);
5636 :
5637 : /*
5638 : * Initialize a StringInfo so that we can "receive" it using the standard
5639 : * recv-function infrastructure.
5640 : */
5641 18 : initReadOnlyStringInfo(&buf, VARDATA_ANY(sstate),
5642 18 : VARSIZE_ANY_EXHDR(sstate));
5643 :
5644 18 : result = makeInt128AggStateCurrentContext(false);
5645 :
5646 : /* N */
5647 18 : result->N = pq_getmsgint64(&buf);
5648 :
5649 : /* sumX */
5650 18 : result->sumX = int128_deserialize(&buf);
5651 :
5652 : /* sumX2 */
5653 18 : result->sumX2 = int128_deserialize(&buf);
5654 :
5655 18 : pq_getmsgend(&buf);
5656 :
5657 18 : PG_RETURN_POINTER(result);
5658 : }
5659 :
5660 : /*
5661 : * Transition function for int8 input when we don't need sumX2.
5662 : */
5663 : Datum
5664 318916 : int8_avg_accum(PG_FUNCTION_ARGS)
5665 : {
5666 : Int128AggState *state;
5667 :
5668 318916 : state = PG_ARGISNULL(0) ? NULL : (Int128AggState *) PG_GETARG_POINTER(0);
5669 :
5670 : /* Create the state data on the first call */
5671 318916 : if (state == NULL)
5672 828 : state = makeInt128AggState(fcinfo, false);
5673 :
5674 318916 : if (!PG_ARGISNULL(1))
5675 315118 : do_int128_accum(state, PG_GETARG_INT64(1));
5676 :
5677 318916 : PG_RETURN_POINTER(state);
5678 : }
5679 :
5680 : /*
5681 : * Combine function for Int128AggState for aggregates which don't require
5682 : * sumX2
5683 : */
5684 : Datum
5685 24 : int8_avg_combine(PG_FUNCTION_ARGS)
5686 : {
5687 : Int128AggState *state1;
5688 : Int128AggState *state2;
5689 : MemoryContext agg_context;
5690 : MemoryContext old_context;
5691 :
5692 24 : if (!AggCheckCallContext(fcinfo, &agg_context))
5693 0 : elog(ERROR, "aggregate function called in non-aggregate context");
5694 :
5695 24 : state1 = PG_ARGISNULL(0) ? NULL : (Int128AggState *) PG_GETARG_POINTER(0);
5696 24 : state2 = PG_ARGISNULL(1) ? NULL : (Int128AggState *) PG_GETARG_POINTER(1);
5697 :
5698 24 : if (state2 == NULL)
5699 0 : PG_RETURN_POINTER(state1);
5700 :
5701 : /* manually copy all fields from state2 to state1 */
5702 24 : if (state1 == NULL)
5703 : {
5704 12 : old_context = MemoryContextSwitchTo(agg_context);
5705 :
5706 12 : state1 = makeInt128AggState(fcinfo, false);
5707 12 : state1->N = state2->N;
5708 12 : state1->sumX = state2->sumX;
5709 :
5710 12 : MemoryContextSwitchTo(old_context);
5711 :
5712 12 : PG_RETURN_POINTER(state1);
5713 : }
5714 :
5715 12 : if (state2->N > 0)
5716 : {
5717 12 : state1->N += state2->N;
5718 12 : int128_add_int128(&state1->sumX, state2->sumX);
5719 : }
5720 12 : PG_RETURN_POINTER(state1);
5721 : }
5722 :
5723 : /*
5724 : * int8_avg_serialize
5725 : * Serialize Int128AggState into bytea for aggregate functions which
5726 : * don't require sumX2.
5727 : */
5728 : Datum
5729 24 : int8_avg_serialize(PG_FUNCTION_ARGS)
5730 : {
5731 : Int128AggState *state;
5732 : StringInfoData buf;
5733 : bytea *result;
5734 :
5735 : /* Ensure we disallow calling when not in aggregate context */
5736 24 : if (!AggCheckCallContext(fcinfo, NULL))
5737 0 : elog(ERROR, "aggregate function called in non-aggregate context");
5738 :
5739 24 : state = (Int128AggState *) PG_GETARG_POINTER(0);
5740 :
5741 24 : pq_begintypsend(&buf);
5742 :
5743 : /* N */
5744 24 : pq_sendint64(&buf, state->N);
5745 :
5746 : /* sumX */
5747 24 : int128_serialize(&buf, state->sumX);
5748 :
5749 24 : result = pq_endtypsend(&buf);
5750 :
5751 24 : PG_RETURN_BYTEA_P(result);
5752 : }
5753 :
5754 : /*
5755 : * int8_avg_deserialize
5756 : * Deserialize Int128AggState from bytea for aggregate functions which
5757 : * don't require sumX2.
5758 : */
5759 : Datum
5760 24 : int8_avg_deserialize(PG_FUNCTION_ARGS)
5761 : {
5762 : bytea *sstate;
5763 : Int128AggState *result;
5764 : StringInfoData buf;
5765 :
5766 24 : if (!AggCheckCallContext(fcinfo, NULL))
5767 0 : elog(ERROR, "aggregate function called in non-aggregate context");
5768 :
5769 24 : sstate = PG_GETARG_BYTEA_PP(0);
5770 :
5771 : /*
5772 : * Initialize a StringInfo so that we can "receive" it using the standard
5773 : * recv-function infrastructure.
5774 : */
5775 24 : initReadOnlyStringInfo(&buf, VARDATA_ANY(sstate),
5776 24 : VARSIZE_ANY_EXHDR(sstate));
5777 :
5778 24 : result = makeInt128AggStateCurrentContext(false);
5779 :
5780 : /* N */
5781 24 : result->N = pq_getmsgint64(&buf);
5782 :
5783 : /* sumX */
5784 24 : result->sumX = int128_deserialize(&buf);
5785 :
5786 24 : pq_getmsgend(&buf);
5787 :
5788 24 : PG_RETURN_POINTER(result);
5789 : }
5790 :
5791 : /*
5792 : * Inverse transition functions to go with the above.
5793 : */
5794 :
5795 : Datum
5796 162 : int2_accum_inv(PG_FUNCTION_ARGS)
5797 : {
5798 : Int128AggState *state;
5799 :
5800 162 : state = PG_ARGISNULL(0) ? NULL : (Int128AggState *) PG_GETARG_POINTER(0);
5801 :
5802 : /* Should not get here with no state */
5803 162 : if (state == NULL)
5804 0 : elog(ERROR, "int2_accum_inv called with NULL state");
5805 :
5806 162 : if (!PG_ARGISNULL(1))
5807 144 : do_int128_discard(state, PG_GETARG_INT16(1));
5808 :
5809 162 : PG_RETURN_POINTER(state);
5810 : }
5811 :
5812 : Datum
5813 162 : int4_accum_inv(PG_FUNCTION_ARGS)
5814 : {
5815 : Int128AggState *state;
5816 :
5817 162 : state = PG_ARGISNULL(0) ? NULL : (Int128AggState *) PG_GETARG_POINTER(0);
5818 :
5819 : /* Should not get here with no state */
5820 162 : if (state == NULL)
5821 0 : elog(ERROR, "int4_accum_inv called with NULL state");
5822 :
5823 162 : if (!PG_ARGISNULL(1))
5824 144 : do_int128_discard(state, PG_GETARG_INT32(1));
5825 :
5826 162 : PG_RETURN_POINTER(state);
5827 : }
5828 :
5829 : Datum
5830 162 : int8_accum_inv(PG_FUNCTION_ARGS)
5831 : {
5832 : NumericAggState *state;
5833 :
5834 162 : state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
5835 :
5836 : /* Should not get here with no state */
5837 162 : if (state == NULL)
5838 0 : elog(ERROR, "int8_accum_inv called with NULL state");
5839 :
5840 162 : if (!PG_ARGISNULL(1))
5841 : {
5842 : /* Should never fail, all inputs have dscale 0 */
5843 144 : if (!do_numeric_discard(state, int64_to_numeric(PG_GETARG_INT64(1))))
5844 0 : elog(ERROR, "do_numeric_discard failed unexpectedly");
5845 : }
5846 :
5847 162 : PG_RETURN_POINTER(state);
5848 : }
5849 :
5850 : Datum
5851 36 : int8_avg_accum_inv(PG_FUNCTION_ARGS)
5852 : {
5853 : Int128AggState *state;
5854 :
5855 36 : state = PG_ARGISNULL(0) ? NULL : (Int128AggState *) PG_GETARG_POINTER(0);
5856 :
5857 : /* Should not get here with no state */
5858 36 : if (state == NULL)
5859 0 : elog(ERROR, "int8_avg_accum_inv called with NULL state");
5860 :
5861 36 : if (!PG_ARGISNULL(1))
5862 24 : do_int128_discard(state, PG_GETARG_INT64(1));
5863 :
5864 36 : PG_RETURN_POINTER(state);
5865 : }
5866 :
5867 : Datum
5868 1050 : numeric_poly_sum(PG_FUNCTION_ARGS)
5869 : {
5870 : Int128AggState *state;
5871 : Numeric res;
5872 : NumericVar result;
5873 :
5874 1050 : state = PG_ARGISNULL(0) ? NULL : (Int128AggState *) PG_GETARG_POINTER(0);
5875 :
5876 : /* If there were no non-null inputs, return NULL */
5877 1050 : if (state == NULL || state->N == 0)
5878 24 : PG_RETURN_NULL();
5879 :
5880 1026 : init_var(&result);
5881 :
5882 1026 : int128_to_numericvar(state->sumX, &result);
5883 :
5884 1026 : res = make_result(&result);
5885 :
5886 1026 : free_var(&result);
5887 :
5888 1026 : PG_RETURN_NUMERIC(res);
5889 : }
5890 :
5891 : Datum
5892 36 : numeric_poly_avg(PG_FUNCTION_ARGS)
5893 : {
5894 : Int128AggState *state;
5895 : NumericVar result;
5896 : Datum countd,
5897 : sumd;
5898 :
5899 36 : state = PG_ARGISNULL(0) ? NULL : (Int128AggState *) PG_GETARG_POINTER(0);
5900 :
5901 : /* If there were no non-null inputs, return NULL */
5902 36 : if (state == NULL || state->N == 0)
5903 18 : PG_RETURN_NULL();
5904 :
5905 18 : init_var(&result);
5906 :
5907 18 : int128_to_numericvar(state->sumX, &result);
5908 :
5909 18 : countd = NumericGetDatum(int64_to_numeric(state->N));
5910 18 : sumd = NumericGetDatum(make_result(&result));
5911 :
5912 18 : free_var(&result);
5913 :
5914 18 : PG_RETURN_DATUM(DirectFunctionCall2(numeric_div, sumd, countd));
5915 : }
5916 :
5917 : Datum
5918 78 : numeric_avg(PG_FUNCTION_ARGS)
5919 : {
5920 : NumericAggState *state;
5921 : Datum N_datum;
5922 : Datum sumX_datum;
5923 : NumericVar sumX_var;
5924 :
5925 78 : state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
5926 :
5927 : /* If there were no non-null inputs, return NULL */
5928 78 : if (state == NULL || NA_TOTAL_COUNT(state) == 0)
5929 18 : PG_RETURN_NULL();
5930 :
5931 60 : if (state->NaNcount > 0) /* there was at least one NaN input */
5932 6 : PG_RETURN_NUMERIC(make_result(&const_nan));
5933 :
5934 : /* adding plus and minus infinities gives NaN */
5935 54 : if (state->pInfcount > 0 && state->nInfcount > 0)
5936 6 : PG_RETURN_NUMERIC(make_result(&const_nan));
5937 48 : if (state->pInfcount > 0)
5938 18 : PG_RETURN_NUMERIC(make_result(&const_pinf));
5939 30 : if (state->nInfcount > 0)
5940 6 : PG_RETURN_NUMERIC(make_result(&const_ninf));
5941 :
5942 24 : N_datum = NumericGetDatum(int64_to_numeric(state->N));
5943 :
5944 24 : init_var(&sumX_var);
5945 24 : accum_sum_final(&state->sumX, &sumX_var);
5946 24 : sumX_datum = NumericGetDatum(make_result(&sumX_var));
5947 24 : free_var(&sumX_var);
5948 :
5949 24 : PG_RETURN_DATUM(DirectFunctionCall2(numeric_div, sumX_datum, N_datum));
5950 : }
5951 :
5952 : Datum
5953 170906 : numeric_sum(PG_FUNCTION_ARGS)
5954 : {
5955 : NumericAggState *state;
5956 : NumericVar sumX_var;
5957 : Numeric result;
5958 :
5959 170906 : state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
5960 :
5961 : /* If there were no non-null inputs, return NULL */
5962 170906 : if (state == NULL || NA_TOTAL_COUNT(state) == 0)
5963 18 : PG_RETURN_NULL();
5964 :
5965 170888 : if (state->NaNcount > 0) /* there was at least one NaN input */
5966 18 : PG_RETURN_NUMERIC(make_result(&const_nan));
5967 :
5968 : /* adding plus and minus infinities gives NaN */
5969 170870 : if (state->pInfcount > 0 && state->nInfcount > 0)
5970 6 : PG_RETURN_NUMERIC(make_result(&const_nan));
5971 170864 : if (state->pInfcount > 0)
5972 18 : PG_RETURN_NUMERIC(make_result(&const_pinf));
5973 170846 : if (state->nInfcount > 0)
5974 6 : PG_RETURN_NUMERIC(make_result(&const_ninf));
5975 :
5976 170840 : init_var(&sumX_var);
5977 170840 : accum_sum_final(&state->sumX, &sumX_var);
5978 170840 : result = make_result(&sumX_var);
5979 170840 : free_var(&sumX_var);
5980 :
5981 170840 : PG_RETURN_NUMERIC(result);
5982 : }
5983 :
5984 : /*
5985 : * Workhorse routine for the standard deviance and variance
5986 : * aggregates. 'state' is aggregate's transition state.
5987 : * 'variance' specifies whether we should calculate the
5988 : * variance or the standard deviation. 'sample' indicates whether the
5989 : * caller is interested in the sample or the population
5990 : * variance/stddev.
5991 : *
5992 : * If appropriate variance statistic is undefined for the input,
5993 : * *is_null is set to true and NULL is returned.
5994 : */
5995 : static Numeric
5996 986 : numeric_stddev_internal(NumericAggState *state,
5997 : bool variance, bool sample,
5998 : bool *is_null)
5999 : {
6000 : Numeric res;
6001 : NumericVar vN,
6002 : vsumX,
6003 : vsumX2,
6004 : vNminus1;
6005 : int64 totCount;
6006 : int rscale;
6007 :
6008 : /*
6009 : * Sample stddev and variance are undefined when N <= 1; population stddev
6010 : * is undefined when N == 0. Return NULL in either case (note that NaNs
6011 : * and infinities count as normal inputs for this purpose).
6012 : */
6013 986 : if (state == NULL || (totCount = NA_TOTAL_COUNT(state)) == 0)
6014 : {
6015 0 : *is_null = true;
6016 0 : return NULL;
6017 : }
6018 :
6019 986 : if (sample && totCount <= 1)
6020 : {
6021 132 : *is_null = true;
6022 132 : return NULL;
6023 : }
6024 :
6025 854 : *is_null = false;
6026 :
6027 : /*
6028 : * Deal with NaN and infinity cases. By analogy to the behavior of the
6029 : * float8 functions, any infinity input produces NaN output.
6030 : */
6031 854 : if (state->NaNcount > 0 || state->pInfcount > 0 || state->nInfcount > 0)
6032 54 : return make_result(&const_nan);
6033 :
6034 : /* OK, normal calculation applies */
6035 800 : init_var(&vN);
6036 800 : init_var(&vsumX);
6037 800 : init_var(&vsumX2);
6038 :
6039 800 : int64_to_numericvar(state->N, &vN);
6040 800 : accum_sum_final(&(state->sumX), &vsumX);
6041 800 : accum_sum_final(&(state->sumX2), &vsumX2);
6042 :
6043 800 : init_var(&vNminus1);
6044 800 : sub_var(&vN, &const_one, &vNminus1);
6045 :
6046 : /* compute rscale for mul_var calls */
6047 800 : rscale = vsumX.dscale * 2;
6048 :
6049 800 : mul_var(&vsumX, &vsumX, &vsumX, rscale); /* vsumX = sumX * sumX */
6050 800 : mul_var(&vN, &vsumX2, &vsumX2, rscale); /* vsumX2 = N * sumX2 */
6051 800 : sub_var(&vsumX2, &vsumX, &vsumX2); /* N * sumX2 - sumX * sumX */
6052 :
6053 800 : if (cmp_var(&vsumX2, &const_zero) <= 0)
6054 : {
6055 : /* Watch out for roundoff error producing a negative numerator */
6056 80 : res = make_result(&const_zero);
6057 : }
6058 : else
6059 : {
6060 720 : if (sample)
6061 492 : mul_var(&vN, &vNminus1, &vNminus1, 0); /* N * (N - 1) */
6062 : else
6063 228 : mul_var(&vN, &vN, &vNminus1, 0); /* N * N */
6064 720 : rscale = select_div_scale(&vsumX2, &vNminus1);
6065 720 : div_var(&vsumX2, &vNminus1, &vsumX, rscale, true, true); /* variance */
6066 720 : if (!variance)
6067 378 : sqrt_var(&vsumX, &vsumX, rscale); /* stddev */
6068 :
6069 720 : res = make_result(&vsumX);
6070 : }
6071 :
6072 800 : free_var(&vNminus1);
6073 800 : free_var(&vsumX);
6074 800 : free_var(&vsumX2);
6075 :
6076 800 : return res;
6077 : }
6078 :
6079 : Datum
6080 180 : numeric_var_samp(PG_FUNCTION_ARGS)
6081 : {
6082 : NumericAggState *state;
6083 : Numeric res;
6084 : bool is_null;
6085 :
6086 180 : state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
6087 :
6088 180 : res = numeric_stddev_internal(state, true, true, &is_null);
6089 :
6090 180 : if (is_null)
6091 42 : PG_RETURN_NULL();
6092 : else
6093 138 : PG_RETURN_NUMERIC(res);
6094 : }
6095 :
6096 : Datum
6097 174 : numeric_stddev_samp(PG_FUNCTION_ARGS)
6098 : {
6099 : NumericAggState *state;
6100 : Numeric res;
6101 : bool is_null;
6102 :
6103 174 : state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
6104 :
6105 174 : res = numeric_stddev_internal(state, false, true, &is_null);
6106 :
6107 174 : if (is_null)
6108 42 : PG_RETURN_NULL();
6109 : else
6110 132 : PG_RETURN_NUMERIC(res);
6111 : }
6112 :
6113 : Datum
6114 114 : numeric_var_pop(PG_FUNCTION_ARGS)
6115 : {
6116 : NumericAggState *state;
6117 : Numeric res;
6118 : bool is_null;
6119 :
6120 114 : state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
6121 :
6122 114 : res = numeric_stddev_internal(state, true, false, &is_null);
6123 :
6124 114 : if (is_null)
6125 0 : PG_RETURN_NULL();
6126 : else
6127 114 : PG_RETURN_NUMERIC(res);
6128 : }
6129 :
6130 : Datum
6131 96 : numeric_stddev_pop(PG_FUNCTION_ARGS)
6132 : {
6133 : NumericAggState *state;
6134 : Numeric res;
6135 : bool is_null;
6136 :
6137 96 : state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
6138 :
6139 96 : res = numeric_stddev_internal(state, false, false, &is_null);
6140 :
6141 96 : if (is_null)
6142 0 : PG_RETURN_NULL();
6143 : else
6144 96 : PG_RETURN_NUMERIC(res);
6145 : }
6146 :
6147 : static Numeric
6148 422 : numeric_poly_stddev_internal(Int128AggState *state,
6149 : bool variance, bool sample,
6150 : bool *is_null)
6151 : {
6152 : NumericAggState numstate;
6153 : Numeric res;
6154 :
6155 : /* Initialize an empty agg state */
6156 422 : memset(&numstate, 0, sizeof(NumericAggState));
6157 :
6158 422 : if (state)
6159 : {
6160 : NumericVar tmp_var;
6161 :
6162 422 : numstate.N = state->N;
6163 :
6164 422 : init_var(&tmp_var);
6165 :
6166 422 : int128_to_numericvar(state->sumX, &tmp_var);
6167 422 : accum_sum_add(&numstate.sumX, &tmp_var);
6168 :
6169 422 : int128_to_numericvar(state->sumX2, &tmp_var);
6170 422 : accum_sum_add(&numstate.sumX2, &tmp_var);
6171 :
6172 422 : free_var(&tmp_var);
6173 : }
6174 :
6175 422 : res = numeric_stddev_internal(&numstate, variance, sample, is_null);
6176 :
6177 422 : if (numstate.sumX.ndigits > 0)
6178 : {
6179 422 : pfree(numstate.sumX.pos_digits);
6180 422 : pfree(numstate.sumX.neg_digits);
6181 : }
6182 422 : if (numstate.sumX2.ndigits > 0)
6183 : {
6184 422 : pfree(numstate.sumX2.pos_digits);
6185 422 : pfree(numstate.sumX2.neg_digits);
6186 : }
6187 :
6188 422 : return res;
6189 : }
6190 :
6191 : Datum
6192 126 : numeric_poly_var_samp(PG_FUNCTION_ARGS)
6193 : {
6194 : Int128AggState *state;
6195 : Numeric res;
6196 : bool is_null;
6197 :
6198 126 : state = PG_ARGISNULL(0) ? NULL : (Int128AggState *) PG_GETARG_POINTER(0);
6199 :
6200 126 : res = numeric_poly_stddev_internal(state, true, true, &is_null);
6201 :
6202 126 : if (is_null)
6203 24 : PG_RETURN_NULL();
6204 : else
6205 102 : PG_RETURN_NUMERIC(res);
6206 : }
6207 :
6208 : Datum
6209 164 : numeric_poly_stddev_samp(PG_FUNCTION_ARGS)
6210 : {
6211 : Int128AggState *state;
6212 : Numeric res;
6213 : bool is_null;
6214 :
6215 164 : state = PG_ARGISNULL(0) ? NULL : (Int128AggState *) PG_GETARG_POINTER(0);
6216 :
6217 164 : res = numeric_poly_stddev_internal(state, false, true, &is_null);
6218 :
6219 164 : if (is_null)
6220 24 : PG_RETURN_NULL();
6221 : else
6222 140 : PG_RETURN_NUMERIC(res);
6223 : }
6224 :
6225 : Datum
6226 60 : numeric_poly_var_pop(PG_FUNCTION_ARGS)
6227 : {
6228 : Int128AggState *state;
6229 : Numeric res;
6230 : bool is_null;
6231 :
6232 60 : state = PG_ARGISNULL(0) ? NULL : (Int128AggState *) PG_GETARG_POINTER(0);
6233 :
6234 60 : res = numeric_poly_stddev_internal(state, true, false, &is_null);
6235 :
6236 60 : if (is_null)
6237 0 : PG_RETURN_NULL();
6238 : else
6239 60 : PG_RETURN_NUMERIC(res);
6240 : }
6241 :
6242 : Datum
6243 72 : numeric_poly_stddev_pop(PG_FUNCTION_ARGS)
6244 : {
6245 : Int128AggState *state;
6246 : Numeric res;
6247 : bool is_null;
6248 :
6249 72 : state = PG_ARGISNULL(0) ? NULL : (Int128AggState *) PG_GETARG_POINTER(0);
6250 :
6251 72 : res = numeric_poly_stddev_internal(state, false, false, &is_null);
6252 :
6253 72 : if (is_null)
6254 0 : PG_RETURN_NULL();
6255 : else
6256 72 : PG_RETURN_NUMERIC(res);
6257 : }
6258 :
6259 : /*
6260 : * SUM transition functions for integer datatypes.
6261 : *
6262 : * To avoid overflow, we use accumulators wider than the input datatype.
6263 : * A Numeric accumulator is needed for int8 input; for int4 and int2
6264 : * inputs, we use int8 accumulators which should be sufficient for practical
6265 : * purposes. (The latter two therefore don't really belong in this file,
6266 : * but we keep them here anyway.)
6267 : *
6268 : * Because SQL defines the SUM() of no values to be NULL, not zero,
6269 : * the initial condition of the transition data value needs to be NULL. This
6270 : * means we can't rely on ExecAgg to automatically insert the first non-null
6271 : * data value into the transition data: it doesn't know how to do the type
6272 : * conversion. The upshot is that these routines have to be marked non-strict
6273 : * and handle substitution of the first non-null input themselves.
6274 : *
6275 : * Note: these functions are used only in plain aggregation mode.
6276 : * In moving-aggregate mode, we use intX_avg_accum and intX_avg_accum_inv.
6277 : */
6278 :
6279 : Datum
6280 24 : int2_sum(PG_FUNCTION_ARGS)
6281 : {
6282 : int64 oldsum;
6283 : int64 newval;
6284 :
6285 24 : if (PG_ARGISNULL(0))
6286 : {
6287 : /* No non-null input seen so far... */
6288 6 : if (PG_ARGISNULL(1))
6289 0 : PG_RETURN_NULL(); /* still no non-null */
6290 : /* This is the first non-null input. */
6291 6 : newval = (int64) PG_GETARG_INT16(1);
6292 6 : PG_RETURN_INT64(newval);
6293 : }
6294 :
6295 18 : oldsum = PG_GETARG_INT64(0);
6296 :
6297 : /* Leave sum unchanged if new input is null. */
6298 18 : if (PG_ARGISNULL(1))
6299 0 : PG_RETURN_INT64(oldsum);
6300 :
6301 : /* OK to do the addition. */
6302 18 : newval = oldsum + (int64) PG_GETARG_INT16(1);
6303 :
6304 18 : PG_RETURN_INT64(newval);
6305 : }
6306 :
6307 : Datum
6308 4940348 : int4_sum(PG_FUNCTION_ARGS)
6309 : {
6310 : int64 oldsum;
6311 : int64 newval;
6312 :
6313 4940348 : if (PG_ARGISNULL(0))
6314 : {
6315 : /* No non-null input seen so far... */
6316 208696 : if (PG_ARGISNULL(1))
6317 986 : PG_RETURN_NULL(); /* still no non-null */
6318 : /* This is the first non-null input. */
6319 207710 : newval = (int64) PG_GETARG_INT32(1);
6320 207710 : PG_RETURN_INT64(newval);
6321 : }
6322 :
6323 4731652 : oldsum = PG_GETARG_INT64(0);
6324 :
6325 : /* Leave sum unchanged if new input is null. */
6326 4731652 : if (PG_ARGISNULL(1))
6327 30898 : PG_RETURN_INT64(oldsum);
6328 :
6329 : /* OK to do the addition. */
6330 4700754 : newval = oldsum + (int64) PG_GETARG_INT32(1);
6331 :
6332 4700754 : PG_RETURN_INT64(newval);
6333 : }
6334 :
6335 : /*
6336 : * Note: this function is obsolete, it's no longer used for SUM(int8).
6337 : */
6338 : Datum
6339 0 : int8_sum(PG_FUNCTION_ARGS)
6340 : {
6341 : Numeric oldsum;
6342 :
6343 0 : if (PG_ARGISNULL(0))
6344 : {
6345 : /* No non-null input seen so far... */
6346 0 : if (PG_ARGISNULL(1))
6347 0 : PG_RETURN_NULL(); /* still no non-null */
6348 : /* This is the first non-null input. */
6349 0 : PG_RETURN_NUMERIC(int64_to_numeric(PG_GETARG_INT64(1)));
6350 : }
6351 :
6352 : /*
6353 : * Note that we cannot special-case the aggregate case here, as we do for
6354 : * int2_sum and int4_sum: numeric is of variable size, so we cannot modify
6355 : * our first parameter in-place.
6356 : */
6357 :
6358 0 : oldsum = PG_GETARG_NUMERIC(0);
6359 :
6360 : /* Leave sum unchanged if new input is null. */
6361 0 : if (PG_ARGISNULL(1))
6362 0 : PG_RETURN_NUMERIC(oldsum);
6363 :
6364 : /* OK to do the addition. */
6365 0 : PG_RETURN_DATUM(DirectFunctionCall2(numeric_add,
6366 : NumericGetDatum(oldsum),
6367 : NumericGetDatum(int64_to_numeric(PG_GETARG_INT64(1)))));
6368 : }
6369 :
6370 :
6371 : /*
6372 : * Routines for avg(int2) and avg(int4). The transition datatype
6373 : * is a two-element int8 array, holding count and sum.
6374 : *
6375 : * These functions are also used for sum(int2) and sum(int4) when
6376 : * operating in moving-aggregate mode, since for correct inverse transitions
6377 : * we need to count the inputs.
6378 : */
6379 :
6380 : typedef struct Int8TransTypeData
6381 : {
6382 : int64 count;
6383 : int64 sum;
6384 : } Int8TransTypeData;
6385 :
6386 : Datum
6387 42 : int2_avg_accum(PG_FUNCTION_ARGS)
6388 : {
6389 : ArrayType *transarray;
6390 42 : int16 newval = PG_GETARG_INT16(1);
6391 : Int8TransTypeData *transdata;
6392 :
6393 : /*
6394 : * If we're invoked as an aggregate, we can cheat and modify our first
6395 : * parameter in-place to reduce palloc overhead. Otherwise we need to make
6396 : * a copy of it before scribbling on it.
6397 : */
6398 42 : if (AggCheckCallContext(fcinfo, NULL))
6399 42 : transarray = PG_GETARG_ARRAYTYPE_P(0);
6400 : else
6401 0 : transarray = PG_GETARG_ARRAYTYPE_P_COPY(0);
6402 :
6403 84 : if (ARR_HASNULL(transarray) ||
6404 42 : ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
6405 0 : elog(ERROR, "expected 2-element int8 array");
6406 :
6407 42 : transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
6408 42 : transdata->count++;
6409 42 : transdata->sum += newval;
6410 :
6411 42 : PG_RETURN_ARRAYTYPE_P(transarray);
6412 : }
6413 :
6414 : Datum
6415 2626302 : int4_avg_accum(PG_FUNCTION_ARGS)
6416 : {
6417 : ArrayType *transarray;
6418 2626302 : int32 newval = PG_GETARG_INT32(1);
6419 : Int8TransTypeData *transdata;
6420 :
6421 : /*
6422 : * If we're invoked as an aggregate, we can cheat and modify our first
6423 : * parameter in-place to reduce palloc overhead. Otherwise we need to make
6424 : * a copy of it before scribbling on it.
6425 : */
6426 2626302 : if (AggCheckCallContext(fcinfo, NULL))
6427 2626302 : transarray = PG_GETARG_ARRAYTYPE_P(0);
6428 : else
6429 0 : transarray = PG_GETARG_ARRAYTYPE_P_COPY(0);
6430 :
6431 5252604 : if (ARR_HASNULL(transarray) ||
6432 2626302 : ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
6433 0 : elog(ERROR, "expected 2-element int8 array");
6434 :
6435 2626302 : transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
6436 2626302 : transdata->count++;
6437 2626302 : transdata->sum += newval;
6438 :
6439 2626302 : PG_RETURN_ARRAYTYPE_P(transarray);
6440 : }
6441 :
6442 : Datum
6443 10058 : int4_avg_combine(PG_FUNCTION_ARGS)
6444 : {
6445 : ArrayType *transarray1;
6446 : ArrayType *transarray2;
6447 : Int8TransTypeData *state1;
6448 : Int8TransTypeData *state2;
6449 :
6450 10058 : if (!AggCheckCallContext(fcinfo, NULL))
6451 0 : elog(ERROR, "aggregate function called in non-aggregate context");
6452 :
6453 10058 : transarray1 = PG_GETARG_ARRAYTYPE_P(0);
6454 10058 : transarray2 = PG_GETARG_ARRAYTYPE_P(1);
6455 :
6456 20116 : if (ARR_HASNULL(transarray1) ||
6457 10058 : ARR_SIZE(transarray1) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
6458 0 : elog(ERROR, "expected 2-element int8 array");
6459 :
6460 20116 : if (ARR_HASNULL(transarray2) ||
6461 10058 : ARR_SIZE(transarray2) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
6462 0 : elog(ERROR, "expected 2-element int8 array");
6463 :
6464 10058 : state1 = (Int8TransTypeData *) ARR_DATA_PTR(transarray1);
6465 10058 : state2 = (Int8TransTypeData *) ARR_DATA_PTR(transarray2);
6466 :
6467 10058 : state1->count += state2->count;
6468 10058 : state1->sum += state2->sum;
6469 :
6470 10058 : PG_RETURN_ARRAYTYPE_P(transarray1);
6471 : }
6472 :
6473 : Datum
6474 12 : int2_avg_accum_inv(PG_FUNCTION_ARGS)
6475 : {
6476 : ArrayType *transarray;
6477 12 : int16 newval = PG_GETARG_INT16(1);
6478 : Int8TransTypeData *transdata;
6479 :
6480 : /*
6481 : * If we're invoked as an aggregate, we can cheat and modify our first
6482 : * parameter in-place to reduce palloc overhead. Otherwise we need to make
6483 : * a copy of it before scribbling on it.
6484 : */
6485 12 : if (AggCheckCallContext(fcinfo, NULL))
6486 12 : transarray = PG_GETARG_ARRAYTYPE_P(0);
6487 : else
6488 0 : transarray = PG_GETARG_ARRAYTYPE_P_COPY(0);
6489 :
6490 24 : if (ARR_HASNULL(transarray) ||
6491 12 : ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
6492 0 : elog(ERROR, "expected 2-element int8 array");
6493 :
6494 12 : transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
6495 12 : transdata->count--;
6496 12 : transdata->sum -= newval;
6497 :
6498 12 : PG_RETURN_ARRAYTYPE_P(transarray);
6499 : }
6500 :
6501 : Datum
6502 1452 : int4_avg_accum_inv(PG_FUNCTION_ARGS)
6503 : {
6504 : ArrayType *transarray;
6505 1452 : int32 newval = PG_GETARG_INT32(1);
6506 : Int8TransTypeData *transdata;
6507 :
6508 : /*
6509 : * If we're invoked as an aggregate, we can cheat and modify our first
6510 : * parameter in-place to reduce palloc overhead. Otherwise we need to make
6511 : * a copy of it before scribbling on it.
6512 : */
6513 1452 : if (AggCheckCallContext(fcinfo, NULL))
6514 1452 : transarray = PG_GETARG_ARRAYTYPE_P(0);
6515 : else
6516 0 : transarray = PG_GETARG_ARRAYTYPE_P_COPY(0);
6517 :
6518 2904 : if (ARR_HASNULL(transarray) ||
6519 1452 : ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
6520 0 : elog(ERROR, "expected 2-element int8 array");
6521 :
6522 1452 : transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
6523 1452 : transdata->count--;
6524 1452 : transdata->sum -= newval;
6525 :
6526 1452 : PG_RETURN_ARRAYTYPE_P(transarray);
6527 : }
6528 :
6529 : Datum
6530 10834 : int8_avg(PG_FUNCTION_ARGS)
6531 : {
6532 10834 : ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
6533 : Int8TransTypeData *transdata;
6534 : Datum countd,
6535 : sumd;
6536 :
6537 21668 : if (ARR_HASNULL(transarray) ||
6538 10834 : ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
6539 0 : elog(ERROR, "expected 2-element int8 array");
6540 10834 : transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
6541 :
6542 : /* SQL defines AVG of no values to be NULL */
6543 10834 : if (transdata->count == 0)
6544 118 : PG_RETURN_NULL();
6545 :
6546 10716 : countd = NumericGetDatum(int64_to_numeric(transdata->count));
6547 10716 : sumd = NumericGetDatum(int64_to_numeric(transdata->sum));
6548 :
6549 10716 : PG_RETURN_DATUM(DirectFunctionCall2(numeric_div, sumd, countd));
6550 : }
6551 :
6552 : /*
6553 : * SUM(int2) and SUM(int4) both return int8, so we can use this
6554 : * final function for both.
6555 : */
6556 : Datum
6557 3834 : int2int4_sum(PG_FUNCTION_ARGS)
6558 : {
6559 3834 : ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
6560 : Int8TransTypeData *transdata;
6561 :
6562 7668 : if (ARR_HASNULL(transarray) ||
6563 3834 : ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
6564 0 : elog(ERROR, "expected 2-element int8 array");
6565 3834 : transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
6566 :
6567 : /* SQL defines SUM of no values to be NULL */
6568 3834 : if (transdata->count == 0)
6569 480 : PG_RETURN_NULL();
6570 :
6571 3354 : PG_RETURN_DATUM(Int64GetDatumFast(transdata->sum));
6572 : }
6573 :
6574 :
6575 : /* ----------------------------------------------------------------------
6576 : *
6577 : * Debug support
6578 : *
6579 : * ----------------------------------------------------------------------
6580 : */
6581 :
6582 : #ifdef NUMERIC_DEBUG
6583 :
6584 : /*
6585 : * dump_numeric() - Dump a value in the db storage format for debugging
6586 : */
6587 : static void
6588 : dump_numeric(const char *str, Numeric num)
6589 : {
6590 : NumericDigit *digits = NUMERIC_DIGITS(num);
6591 : int ndigits;
6592 : int i;
6593 :
6594 : ndigits = NUMERIC_NDIGITS(num);
6595 :
6596 : printf("%s: NUMERIC w=%d d=%d ", str,
6597 : NUMERIC_WEIGHT(num), NUMERIC_DSCALE(num));
6598 : switch (NUMERIC_SIGN(num))
6599 : {
6600 : case NUMERIC_POS:
6601 : printf("POS");
6602 : break;
6603 : case NUMERIC_NEG:
6604 : printf("NEG");
6605 : break;
6606 : case NUMERIC_NAN:
6607 : printf("NaN");
6608 : break;
6609 : case NUMERIC_PINF:
6610 : printf("Infinity");
6611 : break;
6612 : case NUMERIC_NINF:
6613 : printf("-Infinity");
6614 : break;
6615 : default:
6616 : printf("SIGN=0x%x", NUMERIC_SIGN(num));
6617 : break;
6618 : }
6619 :
6620 : for (i = 0; i < ndigits; i++)
6621 : printf(" %0*d", DEC_DIGITS, digits[i]);
6622 : printf("\n");
6623 : }
6624 :
6625 :
6626 : /*
6627 : * dump_var() - Dump a value in the variable format for debugging
6628 : */
6629 : static void
6630 : dump_var(const char *str, NumericVar *var)
6631 : {
6632 : int i;
6633 :
6634 : printf("%s: VAR w=%d d=%d ", str, var->weight, var->dscale);
6635 : switch (var->sign)
6636 : {
6637 : case NUMERIC_POS:
6638 : printf("POS");
6639 : break;
6640 : case NUMERIC_NEG:
6641 : printf("NEG");
6642 : break;
6643 : case NUMERIC_NAN:
6644 : printf("NaN");
6645 : break;
6646 : case NUMERIC_PINF:
6647 : printf("Infinity");
6648 : break;
6649 : case NUMERIC_NINF:
6650 : printf("-Infinity");
6651 : break;
6652 : default:
6653 : printf("SIGN=0x%x", var->sign);
6654 : break;
6655 : }
6656 :
6657 : for (i = 0; i < var->ndigits; i++)
6658 : printf(" %0*d", DEC_DIGITS, var->digits[i]);
6659 :
6660 : printf("\n");
6661 : }
6662 : #endif /* NUMERIC_DEBUG */
6663 :
6664 :
6665 : /* ----------------------------------------------------------------------
6666 : *
6667 : * Local functions follow
6668 : *
6669 : * In general, these do not support "special" (NaN or infinity) inputs;
6670 : * callers should handle those possibilities first.
6671 : * (There are one or two exceptions, noted in their header comments.)
6672 : *
6673 : * ----------------------------------------------------------------------
6674 : */
6675 :
6676 :
6677 : /*
6678 : * alloc_var() -
6679 : *
6680 : * Allocate a digit buffer of ndigits digits (plus a spare digit for rounding)
6681 : */
6682 : static void
6683 2181186 : alloc_var(NumericVar *var, int ndigits)
6684 : {
6685 2181186 : digitbuf_free(var->buf);
6686 2181186 : var->buf = digitbuf_alloc(ndigits + 1);
6687 2181186 : var->buf[0] = 0; /* spare digit for rounding */
6688 2181186 : var->digits = var->buf + 1;
6689 2181186 : var->ndigits = ndigits;
6690 2181186 : }
6691 :
6692 :
6693 : /*
6694 : * free_var() -
6695 : *
6696 : * Return the digit buffer of a variable to the free pool
6697 : */
6698 : static void
6699 4193908 : free_var(NumericVar *var)
6700 : {
6701 4193908 : digitbuf_free(var->buf);
6702 4193908 : var->buf = NULL;
6703 4193908 : var->digits = NULL;
6704 4193908 : var->sign = NUMERIC_NAN;
6705 4193908 : }
6706 :
6707 :
6708 : /*
6709 : * zero_var() -
6710 : *
6711 : * Set a variable to ZERO.
6712 : * Note: its dscale is not touched.
6713 : */
6714 : static void
6715 61296 : zero_var(NumericVar *var)
6716 : {
6717 61296 : digitbuf_free(var->buf);
6718 61296 : var->buf = NULL;
6719 61296 : var->digits = NULL;
6720 61296 : var->ndigits = 0;
6721 61296 : var->weight = 0; /* by convention; doesn't really matter */
6722 61296 : var->sign = NUMERIC_POS; /* anything but NAN... */
6723 61296 : }
6724 :
6725 :
6726 : /*
6727 : * set_var_from_str()
6728 : *
6729 : * Parse a string and put the number into a variable
6730 : *
6731 : * This function does not handle leading or trailing spaces. It returns
6732 : * the end+1 position parsed into *endptr, so that caller can check for
6733 : * trailing spaces/garbage if deemed necessary.
6734 : *
6735 : * cp is the place to actually start parsing; str is what to use in error
6736 : * reports. (Typically cp would be the same except advanced over spaces.)
6737 : *
6738 : * Returns true on success, false on failure (if escontext points to an
6739 : * ErrorSaveContext; otherwise errors are thrown).
6740 : */
6741 : static bool
6742 186748 : set_var_from_str(const char *str, const char *cp,
6743 : NumericVar *dest, const char **endptr,
6744 : Node *escontext)
6745 : {
6746 186748 : bool have_dp = false;
6747 : int i;
6748 : unsigned char *decdigits;
6749 186748 : int sign = NUMERIC_POS;
6750 186748 : int dweight = -1;
6751 : int ddigits;
6752 186748 : int dscale = 0;
6753 : int weight;
6754 : int ndigits;
6755 : int offset;
6756 : NumericDigit *digits;
6757 :
6758 : /*
6759 : * We first parse the string to extract decimal digits and determine the
6760 : * correct decimal weight. Then convert to NBASE representation.
6761 : */
6762 186748 : switch (*cp)
6763 : {
6764 0 : case '+':
6765 0 : sign = NUMERIC_POS;
6766 0 : cp++;
6767 0 : break;
6768 :
6769 300 : case '-':
6770 300 : sign = NUMERIC_NEG;
6771 300 : cp++;
6772 300 : break;
6773 : }
6774 :
6775 186748 : if (*cp == '.')
6776 : {
6777 384 : have_dp = true;
6778 384 : cp++;
6779 : }
6780 :
6781 186748 : if (!isdigit((unsigned char) *cp))
6782 0 : goto invalid_syntax;
6783 :
6784 186748 : decdigits = (unsigned char *) palloc(strlen(cp) + DEC_DIGITS * 2);
6785 :
6786 : /* leading padding for digit alignment later */
6787 186748 : memset(decdigits, 0, DEC_DIGITS);
6788 186748 : i = DEC_DIGITS;
6789 :
6790 807922 : while (*cp)
6791 : {
6792 622682 : if (isdigit((unsigned char) *cp))
6793 : {
6794 602848 : decdigits[i++] = *cp++ - '0';
6795 602848 : if (!have_dp)
6796 517880 : dweight++;
6797 : else
6798 84968 : dscale++;
6799 : }
6800 19834 : else if (*cp == '.')
6801 : {
6802 18164 : if (have_dp)
6803 0 : goto invalid_syntax;
6804 18164 : have_dp = true;
6805 18164 : cp++;
6806 : /* decimal point must not be followed by underscore */
6807 18164 : if (*cp == '_')
6808 6 : goto invalid_syntax;
6809 : }
6810 1670 : else if (*cp == '_')
6811 : {
6812 : /* underscore must be followed by more digits */
6813 186 : cp++;
6814 186 : if (!isdigit((unsigned char) *cp))
6815 18 : goto invalid_syntax;
6816 : }
6817 : else
6818 1484 : break;
6819 : }
6820 :
6821 186724 : ddigits = i - DEC_DIGITS;
6822 : /* trailing padding for digit alignment later */
6823 186724 : memset(decdigits + i, 0, DEC_DIGITS - 1);
6824 :
6825 : /* Handle exponent, if any */
6826 186724 : if (*cp == 'e' || *cp == 'E')
6827 : {
6828 1436 : int64 exponent = 0;
6829 1436 : bool neg = false;
6830 :
6831 : /*
6832 : * At this point, dweight and dscale can't be more than about
6833 : * INT_MAX/2 due to the MaxAllocSize limit on string length, so
6834 : * constraining the exponent similarly should be enough to prevent
6835 : * integer overflow in this function. If the value is too large to
6836 : * fit in storage format, make_result() will complain about it later;
6837 : * for consistency use the same ereport errcode/text as make_result().
6838 : */
6839 :
6840 : /* exponent sign */
6841 1436 : cp++;
6842 1436 : if (*cp == '+')
6843 154 : cp++;
6844 1282 : else if (*cp == '-')
6845 : {
6846 634 : neg = true;
6847 634 : cp++;
6848 : }
6849 :
6850 : /* exponent digits */
6851 1436 : if (!isdigit((unsigned char) *cp))
6852 6 : goto invalid_syntax;
6853 :
6854 4940 : while (*cp)
6855 : {
6856 3528 : if (isdigit((unsigned char) *cp))
6857 : {
6858 3486 : exponent = exponent * 10 + (*cp++ - '0');
6859 3486 : if (exponent > PG_INT32_MAX / 2)
6860 6 : goto out_of_range;
6861 : }
6862 42 : else if (*cp == '_')
6863 : {
6864 : /* underscore must be followed by more digits */
6865 42 : cp++;
6866 42 : if (!isdigit((unsigned char) *cp))
6867 12 : goto invalid_syntax;
6868 : }
6869 : else
6870 0 : break;
6871 : }
6872 :
6873 1412 : if (neg)
6874 634 : exponent = -exponent;
6875 :
6876 1412 : dweight += (int) exponent;
6877 1412 : dscale -= (int) exponent;
6878 1412 : if (dscale < 0)
6879 574 : dscale = 0;
6880 : }
6881 :
6882 : /*
6883 : * Okay, convert pure-decimal representation to base NBASE. First we need
6884 : * to determine the converted weight and ndigits. offset is the number of
6885 : * decimal zeroes to insert before the first given digit to have a
6886 : * correctly aligned first NBASE digit.
6887 : */
6888 186700 : if (dweight >= 0)
6889 185784 : weight = (dweight + 1 + DEC_DIGITS - 1) / DEC_DIGITS - 1;
6890 : else
6891 916 : weight = -((-dweight - 1) / DEC_DIGITS + 1);
6892 186700 : offset = (weight + 1) * DEC_DIGITS - (dweight + 1);
6893 186700 : ndigits = (ddigits + offset + DEC_DIGITS - 1) / DEC_DIGITS;
6894 :
6895 186700 : alloc_var(dest, ndigits);
6896 186700 : dest->sign = sign;
6897 186700 : dest->weight = weight;
6898 186700 : dest->dscale = dscale;
6899 :
6900 186700 : i = DEC_DIGITS - offset;
6901 186700 : digits = dest->digits;
6902 :
6903 449290 : while (ndigits-- > 0)
6904 : {
6905 : #if DEC_DIGITS == 4
6906 262590 : *digits++ = ((decdigits[i] * 10 + decdigits[i + 1]) * 10 +
6907 262590 : decdigits[i + 2]) * 10 + decdigits[i + 3];
6908 : #elif DEC_DIGITS == 2
6909 : *digits++ = decdigits[i] * 10 + decdigits[i + 1];
6910 : #elif DEC_DIGITS == 1
6911 : *digits++ = decdigits[i];
6912 : #else
6913 : #error unsupported NBASE
6914 : #endif
6915 262590 : i += DEC_DIGITS;
6916 : }
6917 :
6918 186700 : pfree(decdigits);
6919 :
6920 : /* Strip any leading/trailing zeroes, and normalize weight if zero */
6921 186700 : strip_var(dest);
6922 :
6923 : /* Return end+1 position for caller */
6924 186700 : *endptr = cp;
6925 :
6926 186700 : return true;
6927 :
6928 6 : out_of_range:
6929 6 : ereturn(escontext, false,
6930 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
6931 : errmsg("value overflows numeric format")));
6932 :
6933 42 : invalid_syntax:
6934 42 : ereturn(escontext, false,
6935 : (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
6936 : errmsg("invalid input syntax for type %s: \"%s\"",
6937 : "numeric", str)));
6938 : }
6939 :
6940 :
6941 : /*
6942 : * Return the numeric value of a single hex digit.
6943 : */
6944 : static inline int
6945 708 : xdigit_value(char dig)
6946 : {
6947 894 : return dig >= '0' && dig <= '9' ? dig - '0' :
6948 294 : dig >= 'a' && dig <= 'f' ? dig - 'a' + 10 :
6949 108 : dig >= 'A' && dig <= 'F' ? dig - 'A' + 10 : -1;
6950 : }
6951 :
6952 : /*
6953 : * set_var_from_non_decimal_integer_str()
6954 : *
6955 : * Parse a string containing a non-decimal integer
6956 : *
6957 : * This function does not handle leading or trailing spaces. It returns
6958 : * the end+1 position parsed into *endptr, so that caller can check for
6959 : * trailing spaces/garbage if deemed necessary.
6960 : *
6961 : * cp is the place to actually start parsing; str is what to use in error
6962 : * reports. The number's sign and base prefix indicator (e.g., "0x") are
6963 : * assumed to have already been parsed, so cp should point to the number's
6964 : * first digit in the base specified.
6965 : *
6966 : * base is expected to be 2, 8 or 16.
6967 : *
6968 : * Returns true on success, false on failure (if escontext points to an
6969 : * ErrorSaveContext; otherwise errors are thrown).
6970 : */
6971 : static bool
6972 156 : set_var_from_non_decimal_integer_str(const char *str, const char *cp, int sign,
6973 : int base, NumericVar *dest,
6974 : const char **endptr, Node *escontext)
6975 : {
6976 156 : const char *firstdigit = cp;
6977 : int64 tmp;
6978 : int64 mul;
6979 : NumericVar tmp_var;
6980 :
6981 156 : init_var(&tmp_var);
6982 :
6983 156 : zero_var(dest);
6984 :
6985 : /*
6986 : * Process input digits in groups that fit in int64. Here "tmp" is the
6987 : * value of the digits in the group, and "mul" is base^n, where n is the
6988 : * number of digits in the group. Thus tmp < mul, and we must start a new
6989 : * group when mul * base threatens to overflow PG_INT64_MAX.
6990 : */
6991 156 : tmp = 0;
6992 156 : mul = 1;
6993 :
6994 156 : if (base == 16)
6995 : {
6996 828 : while (*cp)
6997 : {
6998 798 : if (isxdigit((unsigned char) *cp))
6999 : {
7000 708 : if (mul > PG_INT64_MAX / 16)
7001 : {
7002 : /* Add the contribution from this group of digits */
7003 30 : int64_to_numericvar(mul, &tmp_var);
7004 30 : mul_var(dest, &tmp_var, dest, 0);
7005 30 : int64_to_numericvar(tmp, &tmp_var);
7006 30 : add_var(dest, &tmp_var, dest);
7007 :
7008 : /* Result will overflow if weight overflows int16 */
7009 30 : if (dest->weight > NUMERIC_WEIGHT_MAX)
7010 0 : goto out_of_range;
7011 :
7012 : /* Begin a new group */
7013 30 : tmp = 0;
7014 30 : mul = 1;
7015 : }
7016 :
7017 708 : tmp = tmp * 16 + xdigit_value(*cp++);
7018 708 : mul = mul * 16;
7019 : }
7020 90 : else if (*cp == '_')
7021 : {
7022 : /* Underscore must be followed by more digits */
7023 66 : cp++;
7024 66 : if (!isxdigit((unsigned char) *cp))
7025 18 : goto invalid_syntax;
7026 : }
7027 : else
7028 24 : break;
7029 : }
7030 : }
7031 84 : else if (base == 8)
7032 : {
7033 636 : while (*cp)
7034 : {
7035 606 : if (*cp >= '0' && *cp <= '7')
7036 : {
7037 558 : if (mul > PG_INT64_MAX / 8)
7038 : {
7039 : /* Add the contribution from this group of digits */
7040 18 : int64_to_numericvar(mul, &tmp_var);
7041 18 : mul_var(dest, &tmp_var, dest, 0);
7042 18 : int64_to_numericvar(tmp, &tmp_var);
7043 18 : add_var(dest, &tmp_var, dest);
7044 :
7045 : /* Result will overflow if weight overflows int16 */
7046 18 : if (dest->weight > NUMERIC_WEIGHT_MAX)
7047 0 : goto out_of_range;
7048 :
7049 : /* Begin a new group */
7050 18 : tmp = 0;
7051 18 : mul = 1;
7052 : }
7053 :
7054 558 : tmp = tmp * 8 + (*cp++ - '0');
7055 558 : mul = mul * 8;
7056 : }
7057 48 : else if (*cp == '_')
7058 : {
7059 : /* Underscore must be followed by more digits */
7060 36 : cp++;
7061 36 : if (*cp < '0' || *cp > '7')
7062 0 : goto invalid_syntax;
7063 : }
7064 : else
7065 12 : break;
7066 : }
7067 : }
7068 42 : else if (base == 2)
7069 : {
7070 1560 : while (*cp)
7071 : {
7072 1530 : if (*cp >= '0' && *cp <= '1')
7073 : {
7074 1416 : if (mul > PG_INT64_MAX / 2)
7075 : {
7076 : /* Add the contribution from this group of digits */
7077 18 : int64_to_numericvar(mul, &tmp_var);
7078 18 : mul_var(dest, &tmp_var, dest, 0);
7079 18 : int64_to_numericvar(tmp, &tmp_var);
7080 18 : add_var(dest, &tmp_var, dest);
7081 :
7082 : /* Result will overflow if weight overflows int16 */
7083 18 : if (dest->weight > NUMERIC_WEIGHT_MAX)
7084 0 : goto out_of_range;
7085 :
7086 : /* Begin a new group */
7087 18 : tmp = 0;
7088 18 : mul = 1;
7089 : }
7090 :
7091 1416 : tmp = tmp * 2 + (*cp++ - '0');
7092 1416 : mul = mul * 2;
7093 : }
7094 114 : else if (*cp == '_')
7095 : {
7096 : /* Underscore must be followed by more digits */
7097 102 : cp++;
7098 102 : if (*cp < '0' || *cp > '1')
7099 0 : goto invalid_syntax;
7100 : }
7101 : else
7102 12 : break;
7103 : }
7104 : }
7105 : else
7106 : /* Should never happen; treat as invalid input */
7107 0 : goto invalid_syntax;
7108 :
7109 : /* Check that we got at least one digit */
7110 138 : if (unlikely(cp == firstdigit))
7111 0 : goto invalid_syntax;
7112 :
7113 : /* Add the contribution from the final group of digits */
7114 138 : int64_to_numericvar(mul, &tmp_var);
7115 138 : mul_var(dest, &tmp_var, dest, 0);
7116 138 : int64_to_numericvar(tmp, &tmp_var);
7117 138 : add_var(dest, &tmp_var, dest);
7118 :
7119 138 : if (dest->weight > NUMERIC_WEIGHT_MAX)
7120 0 : goto out_of_range;
7121 :
7122 138 : dest->sign = sign;
7123 :
7124 138 : free_var(&tmp_var);
7125 :
7126 : /* Return end+1 position for caller */
7127 138 : *endptr = cp;
7128 :
7129 138 : return true;
7130 :
7131 0 : out_of_range:
7132 0 : ereturn(escontext, false,
7133 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
7134 : errmsg("value overflows numeric format")));
7135 :
7136 18 : invalid_syntax:
7137 18 : ereturn(escontext, false,
7138 : (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
7139 : errmsg("invalid input syntax for type %s: \"%s\"",
7140 : "numeric", str)));
7141 : }
7142 :
7143 :
7144 : /*
7145 : * set_var_from_num() -
7146 : *
7147 : * Convert the packed db format into a variable
7148 : */
7149 : static void
7150 12954 : set_var_from_num(Numeric num, NumericVar *dest)
7151 : {
7152 : int ndigits;
7153 :
7154 12954 : ndigits = NUMERIC_NDIGITS(num);
7155 :
7156 12954 : alloc_var(dest, ndigits);
7157 :
7158 12954 : dest->weight = NUMERIC_WEIGHT(num);
7159 12954 : dest->sign = NUMERIC_SIGN(num);
7160 12954 : dest->dscale = NUMERIC_DSCALE(num);
7161 :
7162 12954 : memcpy(dest->digits, NUMERIC_DIGITS(num), ndigits * sizeof(NumericDigit));
7163 12954 : }
7164 :
7165 :
7166 : /*
7167 : * init_var_from_num() -
7168 : *
7169 : * Initialize a variable from packed db format. The digits array is not
7170 : * copied, which saves some cycles when the resulting var is not modified.
7171 : * Also, there's no need to call free_var(), as long as you don't assign any
7172 : * other value to it (with set_var_* functions, or by using the var as the
7173 : * destination of a function like add_var())
7174 : *
7175 : * CAUTION: Do not modify the digits buffer of a var initialized with this
7176 : * function, e.g by calling round_var() or trunc_var(), as the changes will
7177 : * propagate to the original Numeric! It's OK to use it as the destination
7178 : * argument of one of the calculational functions, though.
7179 : */
7180 : static void
7181 5869048 : init_var_from_num(Numeric num, NumericVar *dest)
7182 : {
7183 5869048 : dest->ndigits = NUMERIC_NDIGITS(num);
7184 5869048 : dest->weight = NUMERIC_WEIGHT(num);
7185 5869048 : dest->sign = NUMERIC_SIGN(num);
7186 5869048 : dest->dscale = NUMERIC_DSCALE(num);
7187 5869048 : dest->digits = NUMERIC_DIGITS(num);
7188 5869048 : dest->buf = NULL; /* digits array is not palloc'd */
7189 5869048 : }
7190 :
7191 :
7192 : /*
7193 : * set_var_from_var() -
7194 : *
7195 : * Copy one variable into another
7196 : */
7197 : static void
7198 35274 : set_var_from_var(const NumericVar *value, NumericVar *dest)
7199 : {
7200 : NumericDigit *newbuf;
7201 :
7202 35274 : newbuf = digitbuf_alloc(value->ndigits + 1);
7203 35274 : newbuf[0] = 0; /* spare digit for rounding */
7204 35274 : if (value->ndigits > 0) /* else value->digits might be null */
7205 34332 : memcpy(newbuf + 1, value->digits,
7206 34332 : value->ndigits * sizeof(NumericDigit));
7207 :
7208 35274 : digitbuf_free(dest->buf);
7209 :
7210 35274 : memmove(dest, value, sizeof(NumericVar));
7211 35274 : dest->buf = newbuf;
7212 35274 : dest->digits = newbuf + 1;
7213 35274 : }
7214 :
7215 :
7216 : /*
7217 : * get_str_from_var() -
7218 : *
7219 : * Convert a var to text representation (guts of numeric_out).
7220 : * The var is displayed to the number of digits indicated by its dscale.
7221 : * Returns a palloc'd string.
7222 : */
7223 : static char *
7224 889358 : get_str_from_var(const NumericVar *var)
7225 : {
7226 : int dscale;
7227 : char *str;
7228 : char *cp;
7229 : char *endcp;
7230 : int i;
7231 : int d;
7232 : NumericDigit dig;
7233 :
7234 : #if DEC_DIGITS > 1
7235 : NumericDigit d1;
7236 : #endif
7237 :
7238 889358 : dscale = var->dscale;
7239 :
7240 : /*
7241 : * Allocate space for the result.
7242 : *
7243 : * i is set to the # of decimal digits before decimal point. dscale is the
7244 : * # of decimal digits we will print after decimal point. We may generate
7245 : * as many as DEC_DIGITS-1 excess digits at the end, and in addition we
7246 : * need room for sign, decimal point, null terminator.
7247 : */
7248 889358 : i = (var->weight + 1) * DEC_DIGITS;
7249 889358 : if (i <= 0)
7250 138182 : i = 1;
7251 :
7252 889358 : str = palloc(i + dscale + DEC_DIGITS + 2);
7253 889358 : cp = str;
7254 :
7255 : /*
7256 : * Output a dash for negative values
7257 : */
7258 889358 : if (var->sign == NUMERIC_NEG)
7259 7462 : *cp++ = '-';
7260 :
7261 : /*
7262 : * Output all digits before the decimal point
7263 : */
7264 889358 : if (var->weight < 0)
7265 : {
7266 138182 : d = var->weight + 1;
7267 138182 : *cp++ = '0';
7268 : }
7269 : else
7270 : {
7271 1609794 : for (d = 0; d <= var->weight; d++)
7272 : {
7273 858618 : dig = (d < var->ndigits) ? var->digits[d] : 0;
7274 : /* In the first digit, suppress extra leading decimal zeroes */
7275 : #if DEC_DIGITS == 4
7276 : {
7277 858618 : bool putit = (d > 0);
7278 :
7279 858618 : d1 = dig / 1000;
7280 858618 : dig -= d1 * 1000;
7281 858618 : putit |= (d1 > 0);
7282 858618 : if (putit)
7283 169162 : *cp++ = d1 + '0';
7284 858618 : d1 = dig / 100;
7285 858618 : dig -= d1 * 100;
7286 858618 : putit |= (d1 > 0);
7287 858618 : if (putit)
7288 580430 : *cp++ = d1 + '0';
7289 858618 : d1 = dig / 10;
7290 858618 : dig -= d1 * 10;
7291 858618 : putit |= (d1 > 0);
7292 858618 : if (putit)
7293 713842 : *cp++ = d1 + '0';
7294 858618 : *cp++ = dig + '0';
7295 : }
7296 : #elif DEC_DIGITS == 2
7297 : d1 = dig / 10;
7298 : dig -= d1 * 10;
7299 : if (d1 > 0 || d > 0)
7300 : *cp++ = d1 + '0';
7301 : *cp++ = dig + '0';
7302 : #elif DEC_DIGITS == 1
7303 : *cp++ = dig + '0';
7304 : #else
7305 : #error unsupported NBASE
7306 : #endif
7307 : }
7308 : }
7309 :
7310 : /*
7311 : * If requested, output a decimal point and all the digits that follow it.
7312 : * We initially put out a multiple of DEC_DIGITS digits, then truncate if
7313 : * needed.
7314 : */
7315 889358 : if (dscale > 0)
7316 : {
7317 645362 : *cp++ = '.';
7318 645362 : endcp = cp + dscale;
7319 1913224 : for (i = 0; i < dscale; d++, i += DEC_DIGITS)
7320 : {
7321 1267862 : dig = (d >= 0 && d < var->ndigits) ? var->digits[d] : 0;
7322 : #if DEC_DIGITS == 4
7323 1267862 : d1 = dig / 1000;
7324 1267862 : dig -= d1 * 1000;
7325 1267862 : *cp++ = d1 + '0';
7326 1267862 : d1 = dig / 100;
7327 1267862 : dig -= d1 * 100;
7328 1267862 : *cp++ = d1 + '0';
7329 1267862 : d1 = dig / 10;
7330 1267862 : dig -= d1 * 10;
7331 1267862 : *cp++ = d1 + '0';
7332 1267862 : *cp++ = dig + '0';
7333 : #elif DEC_DIGITS == 2
7334 : d1 = dig / 10;
7335 : dig -= d1 * 10;
7336 : *cp++ = d1 + '0';
7337 : *cp++ = dig + '0';
7338 : #elif DEC_DIGITS == 1
7339 : *cp++ = dig + '0';
7340 : #else
7341 : #error unsupported NBASE
7342 : #endif
7343 : }
7344 645362 : cp = endcp;
7345 : }
7346 :
7347 : /*
7348 : * terminate the string and return it
7349 : */
7350 889358 : *cp = '\0';
7351 889358 : return str;
7352 : }
7353 :
7354 : /*
7355 : * get_str_from_var_sci() -
7356 : *
7357 : * Convert a var to a normalised scientific notation text representation.
7358 : * This function does the heavy lifting for numeric_out_sci().
7359 : *
7360 : * This notation has the general form a * 10^b, where a is known as the
7361 : * "significand" and b is known as the "exponent".
7362 : *
7363 : * Because we can't do superscript in ASCII (and because we want to copy
7364 : * printf's behaviour) we display the exponent using E notation, with a
7365 : * minimum of two exponent digits.
7366 : *
7367 : * For example, the value 1234 could be output as 1.2e+03.
7368 : *
7369 : * We assume that the exponent can fit into an int32.
7370 : *
7371 : * rscale is the number of decimal digits desired after the decimal point in
7372 : * the output, negative values will be treated as meaning zero.
7373 : *
7374 : * Returns a palloc'd string.
7375 : */
7376 : static char *
7377 228 : get_str_from_var_sci(const NumericVar *var, int rscale)
7378 : {
7379 : int32 exponent;
7380 : NumericVar tmp_var;
7381 : size_t len;
7382 : char *str;
7383 : char *sig_out;
7384 :
7385 228 : if (rscale < 0)
7386 0 : rscale = 0;
7387 :
7388 : /*
7389 : * Determine the exponent of this number in normalised form.
7390 : *
7391 : * This is the exponent required to represent the number with only one
7392 : * significant digit before the decimal place.
7393 : */
7394 228 : if (var->ndigits > 0)
7395 : {
7396 210 : exponent = (var->weight + 1) * DEC_DIGITS;
7397 :
7398 : /*
7399 : * Compensate for leading decimal zeroes in the first numeric digit by
7400 : * decrementing the exponent.
7401 : */
7402 210 : exponent -= DEC_DIGITS - (int) log10(var->digits[0]);
7403 : }
7404 : else
7405 : {
7406 : /*
7407 : * If var has no digits, then it must be zero.
7408 : *
7409 : * Zero doesn't technically have a meaningful exponent in normalised
7410 : * notation, but we just display the exponent as zero for consistency
7411 : * of output.
7412 : */
7413 18 : exponent = 0;
7414 : }
7415 :
7416 : /*
7417 : * Divide var by 10^exponent to get the significand, rounding to rscale
7418 : * decimal digits in the process.
7419 : */
7420 228 : init_var(&tmp_var);
7421 :
7422 228 : power_ten_int(exponent, &tmp_var);
7423 228 : div_var(var, &tmp_var, &tmp_var, rscale, true, true);
7424 228 : sig_out = get_str_from_var(&tmp_var);
7425 :
7426 228 : free_var(&tmp_var);
7427 :
7428 : /*
7429 : * Allocate space for the result.
7430 : *
7431 : * In addition to the significand, we need room for the exponent
7432 : * decoration ("e"), the sign of the exponent, up to 10 digits for the
7433 : * exponent itself, and of course the null terminator.
7434 : */
7435 228 : len = strlen(sig_out) + 13;
7436 228 : str = palloc(len);
7437 228 : snprintf(str, len, "%se%+03d", sig_out, exponent);
7438 :
7439 228 : pfree(sig_out);
7440 :
7441 228 : return str;
7442 : }
7443 :
7444 :
7445 : /*
7446 : * numericvar_serialize - serialize NumericVar to binary format
7447 : *
7448 : * At variable level, no checks are performed on the weight or dscale, allowing
7449 : * us to pass around intermediate values with higher precision than supported
7450 : * by the numeric type. Note: this is incompatible with numeric_send/recv(),
7451 : * which use 16-bit integers for these fields.
7452 : */
7453 : static void
7454 96 : numericvar_serialize(StringInfo buf, const NumericVar *var)
7455 : {
7456 : int i;
7457 :
7458 96 : pq_sendint32(buf, var->ndigits);
7459 96 : pq_sendint32(buf, var->weight);
7460 96 : pq_sendint32(buf, var->sign);
7461 96 : pq_sendint32(buf, var->dscale);
7462 637762 : for (i = 0; i < var->ndigits; i++)
7463 637666 : pq_sendint16(buf, var->digits[i]);
7464 96 : }
7465 :
7466 : /*
7467 : * numericvar_deserialize - deserialize binary format to NumericVar
7468 : */
7469 : static void
7470 96 : numericvar_deserialize(StringInfo buf, NumericVar *var)
7471 : {
7472 : int len,
7473 : i;
7474 :
7475 96 : len = pq_getmsgint(buf, sizeof(int32));
7476 :
7477 96 : alloc_var(var, len); /* sets var->ndigits */
7478 :
7479 96 : var->weight = pq_getmsgint(buf, sizeof(int32));
7480 96 : var->sign = pq_getmsgint(buf, sizeof(int32));
7481 96 : var->dscale = pq_getmsgint(buf, sizeof(int32));
7482 637762 : for (i = 0; i < len; i++)
7483 637666 : var->digits[i] = pq_getmsgint(buf, sizeof(int16));
7484 96 : }
7485 :
7486 :
7487 : /*
7488 : * duplicate_numeric() - copy a packed-format Numeric
7489 : *
7490 : * This will handle NaN and Infinity cases.
7491 : */
7492 : static Numeric
7493 27996 : duplicate_numeric(Numeric num)
7494 : {
7495 : Numeric res;
7496 :
7497 27996 : res = (Numeric) palloc(VARSIZE(num));
7498 27996 : memcpy(res, num, VARSIZE(num));
7499 27996 : return res;
7500 : }
7501 :
7502 : /*
7503 : * make_result_safe() -
7504 : *
7505 : * Create the packed db numeric format in palloc()'d memory from
7506 : * a variable. This will handle NaN and Infinity cases.
7507 : */
7508 : static Numeric
7509 3814632 : make_result_safe(const NumericVar *var, Node *escontext)
7510 : {
7511 : Numeric result;
7512 3814632 : NumericDigit *digits = var->digits;
7513 3814632 : int weight = var->weight;
7514 3814632 : int sign = var->sign;
7515 : int n;
7516 : Size len;
7517 :
7518 3814632 : if ((sign & NUMERIC_SIGN_MASK) == NUMERIC_SPECIAL)
7519 : {
7520 : /*
7521 : * Verify valid special value. This could be just an Assert, perhaps,
7522 : * but it seems worthwhile to expend a few cycles to ensure that we
7523 : * never write any nonzero reserved bits to disk.
7524 : */
7525 3282 : if (!(sign == NUMERIC_NAN ||
7526 : sign == NUMERIC_PINF ||
7527 : sign == NUMERIC_NINF))
7528 0 : elog(ERROR, "invalid numeric sign value 0x%x", sign);
7529 :
7530 3282 : result = (Numeric) palloc(NUMERIC_HDRSZ_SHORT);
7531 :
7532 3282 : SET_VARSIZE(result, NUMERIC_HDRSZ_SHORT);
7533 3282 : result->choice.n_header = sign;
7534 : /* the header word is all we need */
7535 :
7536 : dump_numeric("make_result()", result);
7537 3282 : return result;
7538 : }
7539 :
7540 3811350 : n = var->ndigits;
7541 :
7542 : /* truncate leading zeroes */
7543 3811386 : while (n > 0 && *digits == 0)
7544 : {
7545 36 : digits++;
7546 36 : weight--;
7547 36 : n--;
7548 : }
7549 : /* truncate trailing zeroes */
7550 3896696 : while (n > 0 && digits[n - 1] == 0)
7551 85346 : n--;
7552 :
7553 : /* If zero result, force to weight=0 and positive sign */
7554 3811350 : if (n == 0)
7555 : {
7556 133838 : weight = 0;
7557 133838 : sign = NUMERIC_POS;
7558 : }
7559 :
7560 : /* Build the result */
7561 3811350 : if (NUMERIC_CAN_BE_SHORT(var->dscale, weight))
7562 : {
7563 3808576 : len = NUMERIC_HDRSZ_SHORT + n * sizeof(NumericDigit);
7564 3808576 : result = (Numeric) palloc(len);
7565 3808576 : SET_VARSIZE(result, len);
7566 3808576 : result->choice.n_short.n_header =
7567 : (sign == NUMERIC_NEG ? (NUMERIC_SHORT | NUMERIC_SHORT_SIGN_MASK)
7568 : : NUMERIC_SHORT)
7569 3808576 : | (var->dscale << NUMERIC_SHORT_DSCALE_SHIFT)
7570 3808576 : | (weight < 0 ? NUMERIC_SHORT_WEIGHT_SIGN_MASK : 0)
7571 3808576 : | (weight & NUMERIC_SHORT_WEIGHT_MASK);
7572 : }
7573 : else
7574 : {
7575 2774 : len = NUMERIC_HDRSZ + n * sizeof(NumericDigit);
7576 2774 : result = (Numeric) palloc(len);
7577 2774 : SET_VARSIZE(result, len);
7578 2774 : result->choice.n_long.n_sign_dscale =
7579 2774 : sign | (var->dscale & NUMERIC_DSCALE_MASK);
7580 2774 : result->choice.n_long.n_weight = weight;
7581 : }
7582 :
7583 : Assert(NUMERIC_NDIGITS(result) == n);
7584 3811350 : if (n > 0)
7585 3677512 : memcpy(NUMERIC_DIGITS(result), digits, n * sizeof(NumericDigit));
7586 :
7587 : /* Check for overflow of int16 fields */
7588 3811350 : if (NUMERIC_WEIGHT(result) != weight ||
7589 3811320 : NUMERIC_DSCALE(result) != var->dscale)
7590 30 : ereturn(escontext, NULL,
7591 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
7592 : errmsg("value overflows numeric format")));
7593 :
7594 : dump_numeric("make_result()", result);
7595 3811320 : return result;
7596 : }
7597 :
7598 :
7599 : /*
7600 : * make_result() -
7601 : *
7602 : * An interface to make_result_safe() without "escontext" argument.
7603 : */
7604 : static Numeric
7605 2270464 : make_result(const NumericVar *var)
7606 : {
7607 2270464 : return make_result_safe(var, NULL);
7608 : }
7609 :
7610 :
7611 : /*
7612 : * apply_typmod() -
7613 : *
7614 : * Do bounds checking and rounding according to the specified typmod.
7615 : * Note that this is only applied to normal finite values.
7616 : *
7617 : * Returns true on success, false on failure (if escontext points to an
7618 : * ErrorSaveContext; otherwise errors are thrown).
7619 : */
7620 : static bool
7621 167636 : apply_typmod(NumericVar *var, int32 typmod, Node *escontext)
7622 : {
7623 : int precision;
7624 : int scale;
7625 : int maxdigits;
7626 : int ddigits;
7627 : int i;
7628 :
7629 : /* Do nothing if we have an invalid typmod */
7630 167636 : if (!is_valid_numeric_typmod(typmod))
7631 138480 : return true;
7632 :
7633 29156 : precision = numeric_typmod_precision(typmod);
7634 29156 : scale = numeric_typmod_scale(typmod);
7635 29156 : maxdigits = precision - scale;
7636 :
7637 : /* Round to target scale (and set var->dscale) */
7638 29156 : round_var(var, scale);
7639 :
7640 : /* but don't allow var->dscale to be negative */
7641 29156 : if (var->dscale < 0)
7642 126 : var->dscale = 0;
7643 :
7644 : /*
7645 : * Check for overflow - note we can't do this before rounding, because
7646 : * rounding could raise the weight. Also note that the var's weight could
7647 : * be inflated by leading zeroes, which will be stripped before storage
7648 : * but perhaps might not have been yet. In any case, we must recognize a
7649 : * true zero, whose weight doesn't mean anything.
7650 : */
7651 29156 : ddigits = (var->weight + 1) * DEC_DIGITS;
7652 29156 : if (ddigits > maxdigits)
7653 : {
7654 : /* Determine true weight; and check for all-zero result */
7655 6422 : for (i = 0; i < var->ndigits; i++)
7656 : {
7657 6406 : NumericDigit dig = var->digits[i];
7658 :
7659 6406 : if (dig)
7660 : {
7661 : /* Adjust for any high-order decimal zero digits */
7662 : #if DEC_DIGITS == 4
7663 6406 : if (dig < 10)
7664 306 : ddigits -= 3;
7665 6100 : else if (dig < 100)
7666 624 : ddigits -= 2;
7667 5476 : else if (dig < 1000)
7668 5458 : ddigits -= 1;
7669 : #elif DEC_DIGITS == 2
7670 : if (dig < 10)
7671 : ddigits -= 1;
7672 : #elif DEC_DIGITS == 1
7673 : /* no adjustment */
7674 : #else
7675 : #error unsupported NBASE
7676 : #endif
7677 6406 : if (ddigits > maxdigits)
7678 84 : ereturn(escontext, false,
7679 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
7680 : errmsg("numeric field overflow"),
7681 : errdetail("A field with precision %d, scale %d must round to an absolute value less than %s%d.",
7682 : precision, scale,
7683 : /* Display 10^0 as 1 */
7684 : maxdigits ? "10^" : "",
7685 : maxdigits ? maxdigits : 1
7686 : )));
7687 6322 : break;
7688 : }
7689 0 : ddigits -= DEC_DIGITS;
7690 : }
7691 : }
7692 :
7693 29072 : return true;
7694 : }
7695 :
7696 : /*
7697 : * apply_typmod_special() -
7698 : *
7699 : * Do bounds checking according to the specified typmod, for an Inf or NaN.
7700 : * For convenience of most callers, the value is presented in packed form.
7701 : *
7702 : * Returns true on success, false on failure (if escontext points to an
7703 : * ErrorSaveContext; otherwise errors are thrown).
7704 : */
7705 : static bool
7706 1896 : apply_typmod_special(Numeric num, int32 typmod, Node *escontext)
7707 : {
7708 : int precision;
7709 : int scale;
7710 :
7711 : Assert(NUMERIC_IS_SPECIAL(num)); /* caller error if not */
7712 :
7713 : /*
7714 : * NaN is allowed regardless of the typmod; that's rather dubious perhaps,
7715 : * but it's a longstanding behavior. Inf is rejected if we have any
7716 : * typmod restriction, since an infinity shouldn't be claimed to fit in
7717 : * any finite number of digits.
7718 : */
7719 1896 : if (NUMERIC_IS_NAN(num))
7720 798 : return true;
7721 :
7722 : /* Do nothing if we have a default typmod (-1) */
7723 1098 : if (!is_valid_numeric_typmod(typmod))
7724 1080 : return true;
7725 :
7726 18 : precision = numeric_typmod_precision(typmod);
7727 18 : scale = numeric_typmod_scale(typmod);
7728 :
7729 18 : ereturn(escontext, false,
7730 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
7731 : errmsg("numeric field overflow"),
7732 : errdetail("A field with precision %d, scale %d cannot hold an infinite value.",
7733 : precision, scale)));
7734 : }
7735 :
7736 :
7737 : /*
7738 : * Convert numeric to int8, rounding if needed.
7739 : *
7740 : * If overflow, return false (no error is raised). Return true if okay.
7741 : */
7742 : static bool
7743 10394 : numericvar_to_int64(const NumericVar *var, int64 *result)
7744 : {
7745 : NumericDigit *digits;
7746 : int ndigits;
7747 : int weight;
7748 : int i;
7749 : int64 val;
7750 : bool neg;
7751 : NumericVar rounded;
7752 :
7753 : /* Round to nearest integer */
7754 10394 : init_var(&rounded);
7755 10394 : set_var_from_var(var, &rounded);
7756 10394 : round_var(&rounded, 0);
7757 :
7758 : /* Check for zero input */
7759 10394 : strip_var(&rounded);
7760 10394 : ndigits = rounded.ndigits;
7761 10394 : if (ndigits == 0)
7762 : {
7763 474 : *result = 0;
7764 474 : free_var(&rounded);
7765 474 : return true;
7766 : }
7767 :
7768 : /*
7769 : * For input like 10000000000, we must treat stripped digits as real. So
7770 : * the loop assumes there are weight+1 digits before the decimal point.
7771 : */
7772 9920 : weight = rounded.weight;
7773 : Assert(weight >= 0 && ndigits <= weight + 1);
7774 :
7775 : /*
7776 : * Construct the result. To avoid issues with converting a value
7777 : * corresponding to INT64_MIN (which can't be represented as a positive 64
7778 : * bit two's complement integer), accumulate value as a negative number.
7779 : */
7780 9920 : digits = rounded.digits;
7781 9920 : neg = (rounded.sign == NUMERIC_NEG);
7782 9920 : val = -digits[0];
7783 14128 : for (i = 1; i <= weight; i++)
7784 : {
7785 4256 : if (unlikely(pg_mul_s64_overflow(val, NBASE, &val)))
7786 : {
7787 30 : free_var(&rounded);
7788 30 : return false;
7789 : }
7790 :
7791 4226 : if (i < ndigits)
7792 : {
7793 3948 : if (unlikely(pg_sub_s64_overflow(val, digits[i], &val)))
7794 : {
7795 18 : free_var(&rounded);
7796 18 : return false;
7797 : }
7798 : }
7799 : }
7800 :
7801 9872 : free_var(&rounded);
7802 :
7803 9872 : if (!neg)
7804 : {
7805 9080 : if (unlikely(val == PG_INT64_MIN))
7806 24 : return false;
7807 9056 : val = -val;
7808 : }
7809 9848 : *result = val;
7810 :
7811 9848 : return true;
7812 : }
7813 :
7814 : /*
7815 : * Convert int8 value to numeric.
7816 : */
7817 : static void
7818 1902190 : int64_to_numericvar(int64 val, NumericVar *var)
7819 : {
7820 : uint64 uval,
7821 : newuval;
7822 : NumericDigit *ptr;
7823 : int ndigits;
7824 :
7825 : /* int64 can require at most 19 decimal digits; add one for safety */
7826 1902190 : alloc_var(var, 20 / DEC_DIGITS);
7827 1902190 : if (val < 0)
7828 : {
7829 1826 : var->sign = NUMERIC_NEG;
7830 1826 : uval = pg_abs_s64(val);
7831 : }
7832 : else
7833 : {
7834 1900364 : var->sign = NUMERIC_POS;
7835 1900364 : uval = val;
7836 : }
7837 1902190 : var->dscale = 0;
7838 1902190 : if (val == 0)
7839 : {
7840 30736 : var->ndigits = 0;
7841 30736 : var->weight = 0;
7842 30736 : return;
7843 : }
7844 1871454 : ptr = var->digits + var->ndigits;
7845 1871454 : ndigits = 0;
7846 : do
7847 : {
7848 2195298 : ptr--;
7849 2195298 : ndigits++;
7850 2195298 : newuval = uval / NBASE;
7851 2195298 : *ptr = uval - newuval * NBASE;
7852 2195298 : uval = newuval;
7853 2195298 : } while (uval);
7854 1871454 : var->digits = ptr;
7855 1871454 : var->ndigits = ndigits;
7856 1871454 : var->weight = ndigits - 1;
7857 : }
7858 :
7859 : /*
7860 : * Convert numeric to uint64, rounding if needed.
7861 : *
7862 : * If overflow, return false (no error is raised). Return true if okay.
7863 : */
7864 : static bool
7865 118 : numericvar_to_uint64(const NumericVar *var, uint64 *result)
7866 : {
7867 : NumericDigit *digits;
7868 : int ndigits;
7869 : int weight;
7870 : int i;
7871 : uint64 val;
7872 : NumericVar rounded;
7873 :
7874 : /* Round to nearest integer */
7875 118 : init_var(&rounded);
7876 118 : set_var_from_var(var, &rounded);
7877 118 : round_var(&rounded, 0);
7878 :
7879 : /* Check for zero input */
7880 118 : strip_var(&rounded);
7881 118 : ndigits = rounded.ndigits;
7882 118 : if (ndigits == 0)
7883 : {
7884 18 : *result = 0;
7885 18 : free_var(&rounded);
7886 18 : return true;
7887 : }
7888 :
7889 : /* Check for negative input */
7890 100 : if (rounded.sign == NUMERIC_NEG)
7891 : {
7892 12 : free_var(&rounded);
7893 12 : return false;
7894 : }
7895 :
7896 : /*
7897 : * For input like 10000000000, we must treat stripped digits as real. So
7898 : * the loop assumes there are weight+1 digits before the decimal point.
7899 : */
7900 88 : weight = rounded.weight;
7901 : Assert(weight >= 0 && ndigits <= weight + 1);
7902 :
7903 : /* Construct the result */
7904 88 : digits = rounded.digits;
7905 88 : val = digits[0];
7906 258 : for (i = 1; i <= weight; i++)
7907 : {
7908 182 : if (unlikely(pg_mul_u64_overflow(val, NBASE, &val)))
7909 : {
7910 0 : free_var(&rounded);
7911 0 : return false;
7912 : }
7913 :
7914 182 : if (i < ndigits)
7915 : {
7916 182 : if (unlikely(pg_add_u64_overflow(val, digits[i], &val)))
7917 : {
7918 12 : free_var(&rounded);
7919 12 : return false;
7920 : }
7921 : }
7922 : }
7923 :
7924 76 : free_var(&rounded);
7925 :
7926 76 : *result = val;
7927 :
7928 76 : return true;
7929 : }
7930 :
7931 : /*
7932 : * Convert 128 bit integer to numeric.
7933 : */
7934 : static void
7935 8794 : int128_to_numericvar(INT128 val, NumericVar *var)
7936 : {
7937 : int sign;
7938 : NumericDigit *ptr;
7939 : int ndigits;
7940 : int32 dig;
7941 :
7942 : /* int128 can require at most 39 decimal digits; add one for safety */
7943 8794 : alloc_var(var, 40 / DEC_DIGITS);
7944 8794 : sign = int128_sign(val);
7945 8794 : var->sign = sign < 0 ? NUMERIC_NEG : NUMERIC_POS;
7946 8794 : var->dscale = 0;
7947 8794 : if (sign == 0)
7948 : {
7949 214 : var->ndigits = 0;
7950 214 : var->weight = 0;
7951 214 : return;
7952 : }
7953 8580 : ptr = var->digits + var->ndigits;
7954 8580 : ndigits = 0;
7955 : do
7956 : {
7957 45236 : ptr--;
7958 45236 : ndigits++;
7959 45236 : int128_div_mod_int32(&val, NBASE, &dig);
7960 45236 : *ptr = (NumericDigit) abs(dig);
7961 45236 : } while (!int128_is_zero(val));
7962 8580 : var->digits = ptr;
7963 8580 : var->ndigits = ndigits;
7964 8580 : var->weight = ndigits - 1;
7965 : }
7966 :
7967 : /*
7968 : * Convert a NumericVar to float8; if out of range, return +/- HUGE_VAL
7969 : */
7970 : static double
7971 468 : numericvar_to_double_no_overflow(const NumericVar *var)
7972 : {
7973 : char *tmp;
7974 : double val;
7975 : char *endptr;
7976 :
7977 468 : tmp = get_str_from_var(var);
7978 :
7979 : /* unlike float8in, we ignore ERANGE from strtod */
7980 468 : val = strtod(tmp, &endptr);
7981 468 : if (*endptr != '\0')
7982 : {
7983 : /* shouldn't happen ... */
7984 0 : ereport(ERROR,
7985 : (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
7986 : errmsg("invalid input syntax for type %s: \"%s\"",
7987 : "double precision", tmp)));
7988 : }
7989 :
7990 468 : pfree(tmp);
7991 :
7992 468 : return val;
7993 : }
7994 :
7995 :
7996 : /*
7997 : * cmp_var() -
7998 : *
7999 : * Compare two values on variable level. We assume zeroes have been
8000 : * truncated to no digits.
8001 : */
8002 : static int
8003 170228 : cmp_var(const NumericVar *var1, const NumericVar *var2)
8004 : {
8005 340456 : return cmp_var_common(var1->digits, var1->ndigits,
8006 170228 : var1->weight, var1->sign,
8007 170228 : var2->digits, var2->ndigits,
8008 170228 : var2->weight, var2->sign);
8009 : }
8010 :
8011 : /*
8012 : * cmp_var_common() -
8013 : *
8014 : * Main routine of cmp_var(). This function can be used by both
8015 : * NumericVar and Numeric.
8016 : */
8017 : static int
8018 27817518 : cmp_var_common(const NumericDigit *var1digits, int var1ndigits,
8019 : int var1weight, int var1sign,
8020 : const NumericDigit *var2digits, int var2ndigits,
8021 : int var2weight, int var2sign)
8022 : {
8023 27817518 : if (var1ndigits == 0)
8024 : {
8025 644948 : if (var2ndigits == 0)
8026 505690 : return 0;
8027 139258 : if (var2sign == NUMERIC_NEG)
8028 4230 : return 1;
8029 135028 : return -1;
8030 : }
8031 27172570 : if (var2ndigits == 0)
8032 : {
8033 101434 : if (var1sign == NUMERIC_POS)
8034 94450 : return 1;
8035 6984 : return -1;
8036 : }
8037 :
8038 27071136 : if (var1sign == NUMERIC_POS)
8039 : {
8040 26989526 : if (var2sign == NUMERIC_NEG)
8041 24104 : return 1;
8042 26965422 : return cmp_abs_common(var1digits, var1ndigits, var1weight,
8043 : var2digits, var2ndigits, var2weight);
8044 : }
8045 :
8046 81610 : if (var2sign == NUMERIC_POS)
8047 22604 : return -1;
8048 :
8049 59006 : return cmp_abs_common(var2digits, var2ndigits, var2weight,
8050 : var1digits, var1ndigits, var1weight);
8051 : }
8052 :
8053 :
8054 : /*
8055 : * add_var() -
8056 : *
8057 : * Full version of add functionality on variable level (handling signs).
8058 : * result might point to one of the operands too without danger.
8059 : */
8060 : static void
8061 618566 : add_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
8062 : {
8063 : /*
8064 : * Decide on the signs of the two variables what to do
8065 : */
8066 618566 : if (var1->sign == NUMERIC_POS)
8067 : {
8068 617000 : if (var2->sign == NUMERIC_POS)
8069 : {
8070 : /*
8071 : * Both are positive result = +(ABS(var1) + ABS(var2))
8072 : */
8073 416624 : add_abs(var1, var2, result);
8074 416624 : result->sign = NUMERIC_POS;
8075 : }
8076 : else
8077 : {
8078 : /*
8079 : * var1 is positive, var2 is negative Must compare absolute values
8080 : */
8081 200376 : switch (cmp_abs(var1, var2))
8082 : {
8083 194 : case 0:
8084 : /* ----------
8085 : * ABS(var1) == ABS(var2)
8086 : * result = ZERO
8087 : * ----------
8088 : */
8089 194 : zero_var(result);
8090 194 : result->dscale = Max(var1->dscale, var2->dscale);
8091 194 : break;
8092 :
8093 186204 : case 1:
8094 : /* ----------
8095 : * ABS(var1) > ABS(var2)
8096 : * result = +(ABS(var1) - ABS(var2))
8097 : * ----------
8098 : */
8099 186204 : sub_abs(var1, var2, result);
8100 186204 : result->sign = NUMERIC_POS;
8101 186204 : break;
8102 :
8103 13978 : case -1:
8104 : /* ----------
8105 : * ABS(var1) < ABS(var2)
8106 : * result = -(ABS(var2) - ABS(var1))
8107 : * ----------
8108 : */
8109 13978 : sub_abs(var2, var1, result);
8110 13978 : result->sign = NUMERIC_NEG;
8111 13978 : break;
8112 : }
8113 : }
8114 : }
8115 : else
8116 : {
8117 1566 : if (var2->sign == NUMERIC_POS)
8118 : {
8119 : /* ----------
8120 : * var1 is negative, var2 is positive
8121 : * Must compare absolute values
8122 : * ----------
8123 : */
8124 468 : switch (cmp_abs(var1, var2))
8125 : {
8126 30 : case 0:
8127 : /* ----------
8128 : * ABS(var1) == ABS(var2)
8129 : * result = ZERO
8130 : * ----------
8131 : */
8132 30 : zero_var(result);
8133 30 : result->dscale = Max(var1->dscale, var2->dscale);
8134 30 : break;
8135 :
8136 294 : case 1:
8137 : /* ----------
8138 : * ABS(var1) > ABS(var2)
8139 : * result = -(ABS(var1) - ABS(var2))
8140 : * ----------
8141 : */
8142 294 : sub_abs(var1, var2, result);
8143 294 : result->sign = NUMERIC_NEG;
8144 294 : break;
8145 :
8146 144 : case -1:
8147 : /* ----------
8148 : * ABS(var1) < ABS(var2)
8149 : * result = +(ABS(var2) - ABS(var1))
8150 : * ----------
8151 : */
8152 144 : sub_abs(var2, var1, result);
8153 144 : result->sign = NUMERIC_POS;
8154 144 : break;
8155 : }
8156 : }
8157 : else
8158 : {
8159 : /* ----------
8160 : * Both are negative
8161 : * result = -(ABS(var1) + ABS(var2))
8162 : * ----------
8163 : */
8164 1098 : add_abs(var1, var2, result);
8165 1098 : result->sign = NUMERIC_NEG;
8166 : }
8167 : }
8168 618566 : }
8169 :
8170 :
8171 : /*
8172 : * sub_var() -
8173 : *
8174 : * Full version of sub functionality on variable level (handling signs).
8175 : * result might point to one of the operands too without danger.
8176 : */
8177 : static void
8178 532798 : sub_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
8179 : {
8180 : /*
8181 : * Decide on the signs of the two variables what to do
8182 : */
8183 532798 : if (var1->sign == NUMERIC_POS)
8184 : {
8185 531888 : if (var2->sign == NUMERIC_NEG)
8186 : {
8187 : /* ----------
8188 : * var1 is positive, var2 is negative
8189 : * result = +(ABS(var1) + ABS(var2))
8190 : * ----------
8191 : */
8192 28542 : add_abs(var1, var2, result);
8193 28542 : result->sign = NUMERIC_POS;
8194 : }
8195 : else
8196 : {
8197 : /* ----------
8198 : * Both are positive
8199 : * Must compare absolute values
8200 : * ----------
8201 : */
8202 503346 : switch (cmp_abs(var1, var2))
8203 : {
8204 49358 : case 0:
8205 : /* ----------
8206 : * ABS(var1) == ABS(var2)
8207 : * result = ZERO
8208 : * ----------
8209 : */
8210 49358 : zero_var(result);
8211 49358 : result->dscale = Max(var1->dscale, var2->dscale);
8212 49358 : break;
8213 :
8214 446688 : case 1:
8215 : /* ----------
8216 : * ABS(var1) > ABS(var2)
8217 : * result = +(ABS(var1) - ABS(var2))
8218 : * ----------
8219 : */
8220 446688 : sub_abs(var1, var2, result);
8221 446688 : result->sign = NUMERIC_POS;
8222 446688 : break;
8223 :
8224 7300 : case -1:
8225 : /* ----------
8226 : * ABS(var1) < ABS(var2)
8227 : * result = -(ABS(var2) - ABS(var1))
8228 : * ----------
8229 : */
8230 7300 : sub_abs(var2, var1, result);
8231 7300 : result->sign = NUMERIC_NEG;
8232 7300 : break;
8233 : }
8234 : }
8235 : }
8236 : else
8237 : {
8238 910 : if (var2->sign == NUMERIC_NEG)
8239 : {
8240 : /* ----------
8241 : * Both are negative
8242 : * Must compare absolute values
8243 : * ----------
8244 : */
8245 454 : switch (cmp_abs(var1, var2))
8246 : {
8247 166 : case 0:
8248 : /* ----------
8249 : * ABS(var1) == ABS(var2)
8250 : * result = ZERO
8251 : * ----------
8252 : */
8253 166 : zero_var(result);
8254 166 : result->dscale = Max(var1->dscale, var2->dscale);
8255 166 : break;
8256 :
8257 240 : case 1:
8258 : /* ----------
8259 : * ABS(var1) > ABS(var2)
8260 : * result = -(ABS(var1) - ABS(var2))
8261 : * ----------
8262 : */
8263 240 : sub_abs(var1, var2, result);
8264 240 : result->sign = NUMERIC_NEG;
8265 240 : break;
8266 :
8267 48 : case -1:
8268 : /* ----------
8269 : * ABS(var1) < ABS(var2)
8270 : * result = +(ABS(var2) - ABS(var1))
8271 : * ----------
8272 : */
8273 48 : sub_abs(var2, var1, result);
8274 48 : result->sign = NUMERIC_POS;
8275 48 : break;
8276 : }
8277 : }
8278 : else
8279 : {
8280 : /* ----------
8281 : * var1 is negative, var2 is positive
8282 : * result = -(ABS(var1) + ABS(var2))
8283 : * ----------
8284 : */
8285 456 : add_abs(var1, var2, result);
8286 456 : result->sign = NUMERIC_NEG;
8287 : }
8288 : }
8289 532798 : }
8290 :
8291 :
8292 : /*
8293 : * mul_var() -
8294 : *
8295 : * Multiplication on variable level. Product of var1 * var2 is stored
8296 : * in result. Result is rounded to no more than rscale fractional digits.
8297 : */
8298 : static void
8299 1190272 : mul_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result,
8300 : int rscale)
8301 : {
8302 : int res_ndigits;
8303 : int res_ndigitpairs;
8304 : int res_sign;
8305 : int res_weight;
8306 : int pair_offset;
8307 : int maxdigits;
8308 : int maxdigitpairs;
8309 : uint64 *dig,
8310 : *dig_i1_off;
8311 : uint64 maxdig;
8312 : uint64 carry;
8313 : uint64 newdig;
8314 : int var1ndigits;
8315 : int var2ndigits;
8316 : int var1ndigitpairs;
8317 : int var2ndigitpairs;
8318 : NumericDigit *var1digits;
8319 : NumericDigit *var2digits;
8320 : uint32 var1digitpair;
8321 : uint32 *var2digitpairs;
8322 : NumericDigit *res_digits;
8323 : int i,
8324 : i1,
8325 : i2,
8326 : i2limit;
8327 :
8328 : /*
8329 : * Arrange for var1 to be the shorter of the two numbers. This improves
8330 : * performance because the inner multiplication loop is much simpler than
8331 : * the outer loop, so it's better to have a smaller number of iterations
8332 : * of the outer loop. This also reduces the number of times that the
8333 : * accumulator array needs to be normalized.
8334 : */
8335 1190272 : if (var1->ndigits > var2->ndigits)
8336 : {
8337 15218 : const NumericVar *tmp = var1;
8338 :
8339 15218 : var1 = var2;
8340 15218 : var2 = tmp;
8341 : }
8342 :
8343 : /* copy these values into local vars for speed in inner loop */
8344 1190272 : var1ndigits = var1->ndigits;
8345 1190272 : var2ndigits = var2->ndigits;
8346 1190272 : var1digits = var1->digits;
8347 1190272 : var2digits = var2->digits;
8348 :
8349 1190272 : if (var1ndigits == 0)
8350 : {
8351 : /* one or both inputs is zero; so is result */
8352 2894 : zero_var(result);
8353 2894 : result->dscale = rscale;
8354 2894 : return;
8355 : }
8356 :
8357 : /*
8358 : * If var1 has 1-6 digits and the exact result was requested, delegate to
8359 : * mul_var_short() which uses a faster direct multiplication algorithm.
8360 : */
8361 1187378 : if (var1ndigits <= 6 && rscale == var1->dscale + var2->dscale)
8362 : {
8363 1158902 : mul_var_short(var1, var2, result);
8364 1158902 : return;
8365 : }
8366 :
8367 : /* Determine result sign */
8368 28476 : if (var1->sign == var2->sign)
8369 26994 : res_sign = NUMERIC_POS;
8370 : else
8371 1482 : res_sign = NUMERIC_NEG;
8372 :
8373 : /*
8374 : * Determine the number of result digits to compute and the (maximum
8375 : * possible) result weight. If the exact result would have more than
8376 : * rscale fractional digits, truncate the computation with
8377 : * MUL_GUARD_DIGITS guard digits, i.e., ignore input digits that would
8378 : * only contribute to the right of that. (This will give the exact
8379 : * rounded-to-rscale answer unless carries out of the ignored positions
8380 : * would have propagated through more than MUL_GUARD_DIGITS digits.)
8381 : *
8382 : * Note: an exact computation could not produce more than var1ndigits +
8383 : * var2ndigits digits, but we allocate at least one extra output digit in
8384 : * case rscale-driven rounding produces a carry out of the highest exact
8385 : * digit.
8386 : *
8387 : * The computation itself is done using base-NBASE^2 arithmetic, so we
8388 : * actually process the input digits in pairs, producing a base-NBASE^2
8389 : * intermediate result. This significantly improves performance, since
8390 : * schoolbook multiplication is O(N^2) in the number of input digits, and
8391 : * working in base NBASE^2 effectively halves "N".
8392 : *
8393 : * Note: in a truncated computation, we must compute at least one extra
8394 : * output digit to ensure that all the guard digits are fully computed.
8395 : */
8396 : /* digit pairs in each input */
8397 28476 : var1ndigitpairs = (var1ndigits + 1) / 2;
8398 28476 : var2ndigitpairs = (var2ndigits + 1) / 2;
8399 :
8400 : /* digits in exact result */
8401 28476 : res_ndigits = var1ndigits + var2ndigits;
8402 :
8403 : /* digit pairs in exact result with at least one extra output digit */
8404 28476 : res_ndigitpairs = res_ndigits / 2 + 1;
8405 :
8406 : /* pair offset to align result to end of dig[] */
8407 28476 : pair_offset = res_ndigitpairs - var1ndigitpairs - var2ndigitpairs + 1;
8408 :
8409 : /* maximum possible result weight (odd-length inputs shifted up below) */
8410 28476 : res_weight = var1->weight + var2->weight + 1 + 2 * res_ndigitpairs -
8411 28476 : res_ndigits - (var1ndigits & 1) - (var2ndigits & 1);
8412 :
8413 : /* rscale-based truncation with at least one extra output digit */
8414 28476 : maxdigits = res_weight + 1 + (rscale + DEC_DIGITS - 1) / DEC_DIGITS +
8415 : MUL_GUARD_DIGITS;
8416 28476 : maxdigitpairs = maxdigits / 2 + 1;
8417 :
8418 28476 : res_ndigitpairs = Min(res_ndigitpairs, maxdigitpairs);
8419 28476 : res_ndigits = 2 * res_ndigitpairs;
8420 :
8421 : /*
8422 : * In the computation below, digit pair i1 of var1 and digit pair i2 of
8423 : * var2 are multiplied and added to digit i1+i2+pair_offset of dig[]. Thus
8424 : * input digit pairs with index >= res_ndigitpairs - pair_offset don't
8425 : * contribute to the result, and can be ignored.
8426 : */
8427 28476 : if (res_ndigitpairs <= pair_offset)
8428 : {
8429 : /* All input digits will be ignored; so result is zero */
8430 12 : zero_var(result);
8431 12 : result->dscale = rscale;
8432 12 : return;
8433 : }
8434 28464 : var1ndigitpairs = Min(var1ndigitpairs, res_ndigitpairs - pair_offset);
8435 28464 : var2ndigitpairs = Min(var2ndigitpairs, res_ndigitpairs - pair_offset);
8436 :
8437 : /*
8438 : * We do the arithmetic in an array "dig[]" of unsigned 64-bit integers.
8439 : * Since PG_UINT64_MAX is much larger than NBASE^4, this gives us a lot of
8440 : * headroom to avoid normalizing carries immediately.
8441 : *
8442 : * maxdig tracks the maximum possible value of any dig[] entry; when this
8443 : * threatens to exceed PG_UINT64_MAX, we take the time to propagate
8444 : * carries. Furthermore, we need to ensure that overflow doesn't occur
8445 : * during the carry propagation passes either. The carry values could be
8446 : * as much as PG_UINT64_MAX / NBASE^2, so really we must normalize when
8447 : * digits threaten to exceed PG_UINT64_MAX - PG_UINT64_MAX / NBASE^2.
8448 : *
8449 : * To avoid overflow in maxdig itself, it actually represents the maximum
8450 : * possible value divided by NBASE^2-1, i.e., at the top of the loop it is
8451 : * known that no dig[] entry exceeds maxdig * (NBASE^2-1).
8452 : *
8453 : * The conversion of var1 to base NBASE^2 is done on the fly, as each new
8454 : * digit is required. The digits of var2 are converted upfront, and
8455 : * stored at the end of dig[]. To avoid loss of precision, the input
8456 : * digits are aligned with the start of digit pair array, effectively
8457 : * shifting them up (multiplying by NBASE) if the inputs have an odd
8458 : * number of NBASE digits.
8459 : */
8460 28464 : dig = (uint64 *) palloc(res_ndigitpairs * sizeof(uint64) +
8461 : var2ndigitpairs * sizeof(uint32));
8462 :
8463 : /* convert var2 to base NBASE^2, shifting up if its length is odd */
8464 28464 : var2digitpairs = (uint32 *) (dig + res_ndigitpairs);
8465 :
8466 1547190 : for (i2 = 0; i2 < var2ndigitpairs - 1; i2++)
8467 1518726 : var2digitpairs[i2] = var2digits[2 * i2] * NBASE + var2digits[2 * i2 + 1];
8468 :
8469 28464 : if (2 * i2 + 1 < var2ndigits)
8470 20448 : var2digitpairs[i2] = var2digits[2 * i2] * NBASE + var2digits[2 * i2 + 1];
8471 : else
8472 8016 : var2digitpairs[i2] = var2digits[2 * i2] * NBASE;
8473 :
8474 : /*
8475 : * Start by multiplying var2 by the least significant contributing digit
8476 : * pair from var1, storing the results at the end of dig[], and filling
8477 : * the leading digits with zeros.
8478 : *
8479 : * The loop here is the same as the inner loop below, except that we set
8480 : * the results in dig[], rather than adding to them. This is the
8481 : * performance bottleneck for multiplication, so we want to keep it simple
8482 : * enough so that it can be auto-vectorized. Accordingly, process the
8483 : * digits left-to-right even though schoolbook multiplication would
8484 : * suggest right-to-left. Since we aren't propagating carries in this
8485 : * loop, the order does not matter.
8486 : */
8487 28464 : i1 = var1ndigitpairs - 1;
8488 28464 : if (2 * i1 + 1 < var1ndigits)
8489 12720 : var1digitpair = var1digits[2 * i1] * NBASE + var1digits[2 * i1 + 1];
8490 : else
8491 15744 : var1digitpair = var1digits[2 * i1] * NBASE;
8492 28464 : maxdig = var1digitpair;
8493 :
8494 28464 : i2limit = Min(var2ndigitpairs, res_ndigitpairs - i1 - pair_offset);
8495 28464 : dig_i1_off = &dig[i1 + pair_offset];
8496 :
8497 28464 : memset(dig, 0, (i1 + pair_offset) * sizeof(uint64));
8498 1376622 : for (i2 = 0; i2 < i2limit; i2++)
8499 1348158 : dig_i1_off[i2] = (uint64) var1digitpair * var2digitpairs[i2];
8500 :
8501 : /*
8502 : * Next, multiply var2 by the remaining digit pairs from var1, adding the
8503 : * results to dig[] at the appropriate offsets, and normalizing whenever
8504 : * there is a risk of any dig[] entry overflowing.
8505 : */
8506 1501710 : for (i1 = i1 - 1; i1 >= 0; i1--)
8507 : {
8508 1473246 : var1digitpair = var1digits[2 * i1] * NBASE + var1digits[2 * i1 + 1];
8509 1473246 : if (var1digitpair == 0)
8510 1179516 : continue;
8511 :
8512 : /* Time to normalize? */
8513 293730 : maxdig += var1digitpair;
8514 293730 : if (maxdig > (PG_UINT64_MAX - PG_UINT64_MAX / NBASE_SQR) / (NBASE_SQR - 1))
8515 : {
8516 : /* Yes, do it (to base NBASE^2) */
8517 30 : carry = 0;
8518 119964 : for (i = res_ndigitpairs - 1; i >= 0; i--)
8519 : {
8520 119934 : newdig = dig[i] + carry;
8521 119934 : if (newdig >= NBASE_SQR)
8522 : {
8523 115242 : carry = newdig / NBASE_SQR;
8524 115242 : newdig -= carry * NBASE_SQR;
8525 : }
8526 : else
8527 4692 : carry = 0;
8528 119934 : dig[i] = newdig;
8529 : }
8530 : Assert(carry == 0);
8531 : /* Reset maxdig to indicate new worst-case */
8532 30 : maxdig = 1 + var1digitpair;
8533 : }
8534 :
8535 : /* Multiply and add */
8536 293730 : i2limit = Min(var2ndigitpairs, res_ndigitpairs - i1 - pair_offset);
8537 293730 : dig_i1_off = &dig[i1 + pair_offset];
8538 :
8539 124047846 : for (i2 = 0; i2 < i2limit; i2++)
8540 123754116 : dig_i1_off[i2] += (uint64) var1digitpair * var2digitpairs[i2];
8541 : }
8542 :
8543 : /*
8544 : * Now we do a final carry propagation pass to normalize back to base
8545 : * NBASE^2, and construct the base-NBASE result digits. Note that this is
8546 : * still done at full precision w/guard digits.
8547 : */
8548 28464 : alloc_var(result, res_ndigits);
8549 28464 : res_digits = result->digits;
8550 28464 : carry = 0;
8551 2882922 : for (i = res_ndigitpairs - 1; i >= 0; i--)
8552 : {
8553 2854458 : newdig = dig[i] + carry;
8554 2854458 : if (newdig >= NBASE_SQR)
8555 : {
8556 406914 : carry = newdig / NBASE_SQR;
8557 406914 : newdig -= carry * NBASE_SQR;
8558 : }
8559 : else
8560 2447544 : carry = 0;
8561 2854458 : res_digits[2 * i + 1] = (NumericDigit) ((uint32) newdig % NBASE);
8562 2854458 : res_digits[2 * i] = (NumericDigit) ((uint32) newdig / NBASE);
8563 : }
8564 : Assert(carry == 0);
8565 :
8566 28464 : pfree(dig);
8567 :
8568 : /*
8569 : * Finally, round the result to the requested precision.
8570 : */
8571 28464 : result->weight = res_weight;
8572 28464 : result->sign = res_sign;
8573 :
8574 : /* Round to target rscale (and set result->dscale) */
8575 28464 : round_var(result, rscale);
8576 :
8577 : /* Strip leading and trailing zeroes */
8578 28464 : strip_var(result);
8579 : }
8580 :
8581 :
8582 : /*
8583 : * mul_var_short() -
8584 : *
8585 : * Special-case multiplication function used when var1 has 1-6 digits, var2
8586 : * has at least as many digits as var1, and the exact product var1 * var2 is
8587 : * requested.
8588 : */
8589 : static void
8590 1158902 : mul_var_short(const NumericVar *var1, const NumericVar *var2,
8591 : NumericVar *result)
8592 : {
8593 1158902 : int var1ndigits = var1->ndigits;
8594 1158902 : int var2ndigits = var2->ndigits;
8595 1158902 : NumericDigit *var1digits = var1->digits;
8596 1158902 : NumericDigit *var2digits = var2->digits;
8597 : int res_sign;
8598 : int res_weight;
8599 : int res_ndigits;
8600 : NumericDigit *res_buf;
8601 : NumericDigit *res_digits;
8602 1158902 : uint32 carry = 0;
8603 : uint32 term;
8604 :
8605 : /* Check preconditions */
8606 : Assert(var1ndigits >= 1);
8607 : Assert(var1ndigits <= 6);
8608 : Assert(var2ndigits >= var1ndigits);
8609 :
8610 : /*
8611 : * Determine the result sign, weight, and number of digits to calculate.
8612 : * The weight figured here is correct if the product has no leading zero
8613 : * digits; otherwise strip_var() will fix things up. Note that, unlike
8614 : * mul_var(), we do not need to allocate an extra output digit, because we
8615 : * are not rounding here.
8616 : */
8617 1158902 : if (var1->sign == var2->sign)
8618 1157710 : res_sign = NUMERIC_POS;
8619 : else
8620 1192 : res_sign = NUMERIC_NEG;
8621 1158902 : res_weight = var1->weight + var2->weight + 1;
8622 1158902 : res_ndigits = var1ndigits + var2ndigits;
8623 :
8624 : /* Allocate result digit array */
8625 1158902 : res_buf = digitbuf_alloc(res_ndigits + 1);
8626 1158902 : res_buf[0] = 0; /* spare digit for later rounding */
8627 1158902 : res_digits = res_buf + 1;
8628 :
8629 : /*
8630 : * Compute the result digits in reverse, in one pass, propagating the
8631 : * carry up as we go. The i'th result digit consists of the sum of the
8632 : * products var1digits[i1] * var2digits[i2] for which i = i1 + i2 + 1.
8633 : */
8634 : #define PRODSUM1(v1,i1,v2,i2) ((v1)[(i1)] * (v2)[(i2)])
8635 : #define PRODSUM2(v1,i1,v2,i2) (PRODSUM1(v1,i1,v2,i2) + (v1)[(i1)+1] * (v2)[(i2)-1])
8636 : #define PRODSUM3(v1,i1,v2,i2) (PRODSUM2(v1,i1,v2,i2) + (v1)[(i1)+2] * (v2)[(i2)-2])
8637 : #define PRODSUM4(v1,i1,v2,i2) (PRODSUM3(v1,i1,v2,i2) + (v1)[(i1)+3] * (v2)[(i2)-3])
8638 : #define PRODSUM5(v1,i1,v2,i2) (PRODSUM4(v1,i1,v2,i2) + (v1)[(i1)+4] * (v2)[(i2)-4])
8639 : #define PRODSUM6(v1,i1,v2,i2) (PRODSUM5(v1,i1,v2,i2) + (v1)[(i1)+5] * (v2)[(i2)-5])
8640 :
8641 1158902 : switch (var1ndigits)
8642 : {
8643 1153196 : case 1:
8644 : /* ---------
8645 : * 1-digit case:
8646 : * var1ndigits = 1
8647 : * var2ndigits >= 1
8648 : * res_ndigits = var2ndigits + 1
8649 : * ----------
8650 : */
8651 3606200 : for (int i = var2ndigits - 1; i >= 0; i--)
8652 : {
8653 2453004 : term = PRODSUM1(var1digits, 0, var2digits, i) + carry;
8654 2453004 : res_digits[i + 1] = (NumericDigit) (term % NBASE);
8655 2453004 : carry = term / NBASE;
8656 : }
8657 1153196 : res_digits[0] = (NumericDigit) carry;
8658 1153196 : break;
8659 :
8660 756 : case 2:
8661 : /* ---------
8662 : * 2-digit case:
8663 : * var1ndigits = 2
8664 : * var2ndigits >= 2
8665 : * res_ndigits = var2ndigits + 2
8666 : * ----------
8667 : */
8668 : /* last result digit and carry */
8669 756 : term = PRODSUM1(var1digits, 1, var2digits, var2ndigits - 1);
8670 756 : res_digits[res_ndigits - 1] = (NumericDigit) (term % NBASE);
8671 756 : carry = term / NBASE;
8672 :
8673 : /* remaining digits, except for the first two */
8674 2304 : for (int i = var2ndigits - 1; i >= 1; i--)
8675 : {
8676 1548 : term = PRODSUM2(var1digits, 0, var2digits, i) + carry;
8677 1548 : res_digits[i + 1] = (NumericDigit) (term % NBASE);
8678 1548 : carry = term / NBASE;
8679 : }
8680 756 : break;
8681 :
8682 204 : case 3:
8683 : /* ---------
8684 : * 3-digit case:
8685 : * var1ndigits = 3
8686 : * var2ndigits >= 3
8687 : * res_ndigits = var2ndigits + 3
8688 : * ----------
8689 : */
8690 : /* last two result digits */
8691 204 : term = PRODSUM1(var1digits, 2, var2digits, var2ndigits - 1);
8692 204 : res_digits[res_ndigits - 1] = (NumericDigit) (term % NBASE);
8693 204 : carry = term / NBASE;
8694 :
8695 204 : term = PRODSUM2(var1digits, 1, var2digits, var2ndigits - 1) + carry;
8696 204 : res_digits[res_ndigits - 2] = (NumericDigit) (term % NBASE);
8697 204 : carry = term / NBASE;
8698 :
8699 : /* remaining digits, except for the first three */
8700 546 : for (int i = var2ndigits - 1; i >= 2; i--)
8701 : {
8702 342 : term = PRODSUM3(var1digits, 0, var2digits, i) + carry;
8703 342 : res_digits[i + 1] = (NumericDigit) (term % NBASE);
8704 342 : carry = term / NBASE;
8705 : }
8706 204 : break;
8707 :
8708 4038 : case 4:
8709 : /* ---------
8710 : * 4-digit case:
8711 : * var1ndigits = 4
8712 : * var2ndigits >= 4
8713 : * res_ndigits = var2ndigits + 4
8714 : * ----------
8715 : */
8716 : /* last three result digits */
8717 4038 : term = PRODSUM1(var1digits, 3, var2digits, var2ndigits - 1);
8718 4038 : res_digits[res_ndigits - 1] = (NumericDigit) (term % NBASE);
8719 4038 : carry = term / NBASE;
8720 :
8721 4038 : term = PRODSUM2(var1digits, 2, var2digits, var2ndigits - 1) + carry;
8722 4038 : res_digits[res_ndigits - 2] = (NumericDigit) (term % NBASE);
8723 4038 : carry = term / NBASE;
8724 :
8725 4038 : term = PRODSUM3(var1digits, 1, var2digits, var2ndigits - 1) + carry;
8726 4038 : res_digits[res_ndigits - 3] = (NumericDigit) (term % NBASE);
8727 4038 : carry = term / NBASE;
8728 :
8729 : /* remaining digits, except for the first four */
8730 11268 : for (int i = var2ndigits - 1; i >= 3; i--)
8731 : {
8732 7230 : term = PRODSUM4(var1digits, 0, var2digits, i) + carry;
8733 7230 : res_digits[i + 1] = (NumericDigit) (term % NBASE);
8734 7230 : carry = term / NBASE;
8735 : }
8736 4038 : break;
8737 :
8738 114 : case 5:
8739 : /* ---------
8740 : * 5-digit case:
8741 : * var1ndigits = 5
8742 : * var2ndigits >= 5
8743 : * res_ndigits = var2ndigits + 5
8744 : * ----------
8745 : */
8746 : /* last four result digits */
8747 114 : term = PRODSUM1(var1digits, 4, var2digits, var2ndigits - 1);
8748 114 : res_digits[res_ndigits - 1] = (NumericDigit) (term % NBASE);
8749 114 : carry = term / NBASE;
8750 :
8751 114 : term = PRODSUM2(var1digits, 3, var2digits, var2ndigits - 1) + carry;
8752 114 : res_digits[res_ndigits - 2] = (NumericDigit) (term % NBASE);
8753 114 : carry = term / NBASE;
8754 :
8755 114 : term = PRODSUM3(var1digits, 2, var2digits, var2ndigits - 1) + carry;
8756 114 : res_digits[res_ndigits - 3] = (NumericDigit) (term % NBASE);
8757 114 : carry = term / NBASE;
8758 :
8759 114 : term = PRODSUM4(var1digits, 1, var2digits, var2ndigits - 1) + carry;
8760 114 : res_digits[res_ndigits - 4] = (NumericDigit) (term % NBASE);
8761 114 : carry = term / NBASE;
8762 :
8763 : /* remaining digits, except for the first five */
8764 300 : for (int i = var2ndigits - 1; i >= 4; i--)
8765 : {
8766 186 : term = PRODSUM5(var1digits, 0, var2digits, i) + carry;
8767 186 : res_digits[i + 1] = (NumericDigit) (term % NBASE);
8768 186 : carry = term / NBASE;
8769 : }
8770 114 : break;
8771 :
8772 594 : case 6:
8773 : /* ---------
8774 : * 6-digit case:
8775 : * var1ndigits = 6
8776 : * var2ndigits >= 6
8777 : * res_ndigits = var2ndigits + 6
8778 : * ----------
8779 : */
8780 : /* last five result digits */
8781 594 : term = PRODSUM1(var1digits, 5, var2digits, var2ndigits - 1);
8782 594 : res_digits[res_ndigits - 1] = (NumericDigit) (term % NBASE);
8783 594 : carry = term / NBASE;
8784 :
8785 594 : term = PRODSUM2(var1digits, 4, var2digits, var2ndigits - 1) + carry;
8786 594 : res_digits[res_ndigits - 2] = (NumericDigit) (term % NBASE);
8787 594 : carry = term / NBASE;
8788 :
8789 594 : term = PRODSUM3(var1digits, 3, var2digits, var2ndigits - 1) + carry;
8790 594 : res_digits[res_ndigits - 3] = (NumericDigit) (term % NBASE);
8791 594 : carry = term / NBASE;
8792 :
8793 594 : term = PRODSUM4(var1digits, 2, var2digits, var2ndigits - 1) + carry;
8794 594 : res_digits[res_ndigits - 4] = (NumericDigit) (term % NBASE);
8795 594 : carry = term / NBASE;
8796 :
8797 594 : term = PRODSUM5(var1digits, 1, var2digits, var2ndigits - 1) + carry;
8798 594 : res_digits[res_ndigits - 5] = (NumericDigit) (term % NBASE);
8799 594 : carry = term / NBASE;
8800 :
8801 : /* remaining digits, except for the first six */
8802 1656 : for (int i = var2ndigits - 1; i >= 5; i--)
8803 : {
8804 1062 : term = PRODSUM6(var1digits, 0, var2digits, i) + carry;
8805 1062 : res_digits[i + 1] = (NumericDigit) (term % NBASE);
8806 1062 : carry = term / NBASE;
8807 : }
8808 594 : break;
8809 : }
8810 :
8811 : /*
8812 : * Finally, for var1ndigits > 1, compute the remaining var1ndigits most
8813 : * significant result digits.
8814 : */
8815 1158902 : switch (var1ndigits)
8816 : {
8817 594 : case 6:
8818 594 : term = PRODSUM5(var1digits, 0, var2digits, 4) + carry;
8819 594 : res_digits[5] = (NumericDigit) (term % NBASE);
8820 594 : carry = term / NBASE;
8821 : /* FALLTHROUGH */
8822 708 : case 5:
8823 708 : term = PRODSUM4(var1digits, 0, var2digits, 3) + carry;
8824 708 : res_digits[4] = (NumericDigit) (term % NBASE);
8825 708 : carry = term / NBASE;
8826 : /* FALLTHROUGH */
8827 4746 : case 4:
8828 4746 : term = PRODSUM3(var1digits, 0, var2digits, 2) + carry;
8829 4746 : res_digits[3] = (NumericDigit) (term % NBASE);
8830 4746 : carry = term / NBASE;
8831 : /* FALLTHROUGH */
8832 4950 : case 3:
8833 4950 : term = PRODSUM2(var1digits, 0, var2digits, 1) + carry;
8834 4950 : res_digits[2] = (NumericDigit) (term % NBASE);
8835 4950 : carry = term / NBASE;
8836 : /* FALLTHROUGH */
8837 5706 : case 2:
8838 5706 : term = PRODSUM1(var1digits, 0, var2digits, 0) + carry;
8839 5706 : res_digits[1] = (NumericDigit) (term % NBASE);
8840 5706 : res_digits[0] = (NumericDigit) (term / NBASE);
8841 5706 : break;
8842 : }
8843 :
8844 : /* Store the product in result */
8845 1158902 : digitbuf_free(result->buf);
8846 1158902 : result->ndigits = res_ndigits;
8847 1158902 : result->buf = res_buf;
8848 1158902 : result->digits = res_digits;
8849 1158902 : result->weight = res_weight;
8850 1158902 : result->sign = res_sign;
8851 1158902 : result->dscale = var1->dscale + var2->dscale;
8852 :
8853 : /* Strip leading and trailing zeroes */
8854 1158902 : strip_var(result);
8855 1158902 : }
8856 :
8857 :
8858 : /*
8859 : * div_var() -
8860 : *
8861 : * Compute the quotient var1 / var2 to rscale fractional digits.
8862 : *
8863 : * If "round" is true, the result is rounded at the rscale'th digit; if
8864 : * false, it is truncated (towards zero) at that digit.
8865 : *
8866 : * If "exact" is true, the exact result is computed to the specified rscale;
8867 : * if false, successive quotient digits are approximated up to rscale plus
8868 : * DIV_GUARD_DIGITS extra digits, ignoring all contributions from digits to
8869 : * the right of that, before rounding or truncating to the specified rscale.
8870 : * This can be significantly faster, and usually gives the same result as the
8871 : * exact computation, but it may occasionally be off by one in the final
8872 : * digit, if contributions from the ignored digits would have propagated
8873 : * through the guard digits. This is good enough for the transcendental
8874 : * functions, where small errors are acceptable.
8875 : */
8876 : static void
8877 571208 : div_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result,
8878 : int rscale, bool round, bool exact)
8879 : {
8880 571208 : int var1ndigits = var1->ndigits;
8881 571208 : int var2ndigits = var2->ndigits;
8882 : int res_sign;
8883 : int res_weight;
8884 : int res_ndigits;
8885 : int var1ndigitpairs;
8886 : int var2ndigitpairs;
8887 : int res_ndigitpairs;
8888 : int div_ndigitpairs;
8889 : int64 *dividend;
8890 : int32 *divisor;
8891 : double fdivisor,
8892 : fdivisorinverse,
8893 : fdividend,
8894 : fquotient;
8895 : int64 maxdiv;
8896 : int qi;
8897 : int32 qdigit;
8898 : int64 carry;
8899 : int64 newdig;
8900 : int64 *remainder;
8901 : NumericDigit *res_digits;
8902 : int i;
8903 :
8904 : /*
8905 : * First of all division by zero check; we must not be handed an
8906 : * unnormalized divisor.
8907 : */
8908 571208 : if (var2ndigits == 0 || var2->digits[0] == 0)
8909 12 : ereport(ERROR,
8910 : (errcode(ERRCODE_DIVISION_BY_ZERO),
8911 : errmsg("division by zero")));
8912 :
8913 : /*
8914 : * If the divisor has just one or two digits, delegate to div_var_int(),
8915 : * which uses fast short division.
8916 : *
8917 : * Similarly, on platforms with 128-bit integer support, delegate to
8918 : * div_var_int64() for divisors with three or four digits.
8919 : */
8920 571196 : if (var2ndigits <= 2)
8921 : {
8922 : int idivisor;
8923 : int idivisor_weight;
8924 :
8925 565190 : idivisor = var2->digits[0];
8926 565190 : idivisor_weight = var2->weight;
8927 565190 : if (var2ndigits == 2)
8928 : {
8929 3910 : idivisor = idivisor * NBASE + var2->digits[1];
8930 3910 : idivisor_weight--;
8931 : }
8932 565190 : if (var2->sign == NUMERIC_NEG)
8933 654 : idivisor = -idivisor;
8934 :
8935 565190 : div_var_int(var1, idivisor, idivisor_weight, result, rscale, round);
8936 565190 : return;
8937 : }
8938 : #ifdef HAVE_INT128
8939 6006 : if (var2ndigits <= 4)
8940 : {
8941 : int64 idivisor;
8942 : int idivisor_weight;
8943 :
8944 528 : idivisor = var2->digits[0];
8945 528 : idivisor_weight = var2->weight;
8946 1968 : for (i = 1; i < var2ndigits; i++)
8947 : {
8948 1440 : idivisor = idivisor * NBASE + var2->digits[i];
8949 1440 : idivisor_weight--;
8950 : }
8951 528 : if (var2->sign == NUMERIC_NEG)
8952 120 : idivisor = -idivisor;
8953 :
8954 528 : div_var_int64(var1, idivisor, idivisor_weight, result, rscale, round);
8955 528 : return;
8956 : }
8957 : #endif
8958 :
8959 : /*
8960 : * Otherwise, perform full long division.
8961 : */
8962 :
8963 : /* Result zero check */
8964 5478 : if (var1ndigits == 0)
8965 : {
8966 36 : zero_var(result);
8967 36 : result->dscale = rscale;
8968 36 : return;
8969 : }
8970 :
8971 : /*
8972 : * The approximate computation can be significantly faster than the exact
8973 : * one, since the working dividend is var2ndigitpairs base-NBASE^2 digits
8974 : * shorter below. However, that comes with the tradeoff of computing
8975 : * DIV_GUARD_DIGITS extra base-NBASE result digits. Ignoring all other
8976 : * overheads, that suggests that, in theory, the approximate computation
8977 : * will only be faster than the exact one when var2ndigits is greater than
8978 : * 2 * (DIV_GUARD_DIGITS + 1), independent of the size of var1.
8979 : *
8980 : * Thus, we're better off doing an exact computation when var2 is shorter
8981 : * than this. Empirically, it has been found that the exact threshold is
8982 : * a little higher, due to other overheads in the outer division loop.
8983 : */
8984 5442 : if (var2ndigits <= 2 * (DIV_GUARD_DIGITS + 2))
8985 3708 : exact = true;
8986 :
8987 : /*
8988 : * Determine the result sign, weight and number of digits to calculate.
8989 : * The weight figured here is correct if the emitted quotient has no
8990 : * leading zero digits; otherwise strip_var() will fix things up.
8991 : */
8992 5442 : if (var1->sign == var2->sign)
8993 5310 : res_sign = NUMERIC_POS;
8994 : else
8995 132 : res_sign = NUMERIC_NEG;
8996 5442 : res_weight = var1->weight - var2->weight + 1;
8997 : /* The number of accurate result digits we need to produce: */
8998 5442 : res_ndigits = res_weight + 1 + (rscale + DEC_DIGITS - 1) / DEC_DIGITS;
8999 : /* ... but always at least 1 */
9000 5442 : res_ndigits = Max(res_ndigits, 1);
9001 : /* If rounding needed, figure one more digit to ensure correct result */
9002 5442 : if (round)
9003 906 : res_ndigits++;
9004 : /* Add guard digits for roundoff error when producing approx result */
9005 5442 : if (!exact)
9006 1722 : res_ndigits += DIV_GUARD_DIGITS;
9007 :
9008 : /*
9009 : * The computation itself is done using base-NBASE^2 arithmetic, so we
9010 : * actually process the input digits in pairs, producing a base-NBASE^2
9011 : * intermediate result. This significantly improves performance, since
9012 : * the computation is O(N^2) in the number of input digits, and working in
9013 : * base NBASE^2 effectively halves "N".
9014 : */
9015 5442 : var1ndigitpairs = (var1ndigits + 1) / 2;
9016 5442 : var2ndigitpairs = (var2ndigits + 1) / 2;
9017 5442 : res_ndigitpairs = (res_ndigits + 1) / 2;
9018 5442 : res_ndigits = 2 * res_ndigitpairs;
9019 :
9020 : /*
9021 : * We do the arithmetic in an array "dividend[]" of signed 64-bit
9022 : * integers. Since PG_INT64_MAX is much larger than NBASE^4, this gives
9023 : * us a lot of headroom to avoid normalizing carries immediately.
9024 : *
9025 : * When performing an exact computation, the working dividend requires
9026 : * res_ndigitpairs + var2ndigitpairs digits. If var1 is larger than that,
9027 : * the extra digits do not contribute to the result, and are ignored.
9028 : *
9029 : * When performing an approximate computation, the working dividend only
9030 : * requires res_ndigitpairs digits (which includes the extra guard
9031 : * digits). All input digits beyond that are ignored.
9032 : */
9033 5442 : if (exact)
9034 : {
9035 3720 : div_ndigitpairs = res_ndigitpairs + var2ndigitpairs;
9036 3720 : var1ndigitpairs = Min(var1ndigitpairs, div_ndigitpairs);
9037 : }
9038 : else
9039 : {
9040 1722 : div_ndigitpairs = res_ndigitpairs;
9041 1722 : var1ndigitpairs = Min(var1ndigitpairs, div_ndigitpairs);
9042 1722 : var2ndigitpairs = Min(var2ndigitpairs, div_ndigitpairs);
9043 : }
9044 :
9045 : /*
9046 : * Allocate room for the working dividend (div_ndigitpairs 64-bit digits)
9047 : * plus the divisor (var2ndigitpairs 32-bit base-NBASE^2 digits).
9048 : *
9049 : * For convenience, we allocate one extra dividend digit, which is set to
9050 : * zero and not counted in div_ndigitpairs, so that the main loop below
9051 : * can safely read and write the (qi+1)'th digit in the approximate case.
9052 : */
9053 5442 : dividend = (int64 *) palloc((div_ndigitpairs + 1) * sizeof(int64) +
9054 : var2ndigitpairs * sizeof(int32));
9055 5442 : divisor = (int32 *) (dividend + div_ndigitpairs + 1);
9056 :
9057 : /* load var1 into dividend[0 .. var1ndigitpairs-1], zeroing the rest */
9058 49458 : for (i = 0; i < var1ndigitpairs - 1; i++)
9059 44016 : dividend[i] = var1->digits[2 * i] * NBASE + var1->digits[2 * i + 1];
9060 :
9061 5442 : if (2 * i + 1 < var1ndigits)
9062 3282 : dividend[i] = var1->digits[2 * i] * NBASE + var1->digits[2 * i + 1];
9063 : else
9064 2160 : dividend[i] = var1->digits[2 * i] * NBASE;
9065 :
9066 5442 : memset(dividend + i + 1, 0, (div_ndigitpairs - i) * sizeof(int64));
9067 :
9068 : /* load var2 into divisor[0 .. var2ndigitpairs-1] */
9069 39840 : for (i = 0; i < var2ndigitpairs - 1; i++)
9070 34398 : divisor[i] = var2->digits[2 * i] * NBASE + var2->digits[2 * i + 1];
9071 :
9072 5442 : if (2 * i + 1 < var2ndigits)
9073 2922 : divisor[i] = var2->digits[2 * i] * NBASE + var2->digits[2 * i + 1];
9074 : else
9075 2520 : divisor[i] = var2->digits[2 * i] * NBASE;
9076 :
9077 : /*
9078 : * We estimate each quotient digit using floating-point arithmetic, taking
9079 : * the first 2 base-NBASE^2 digits of the (current) dividend and divisor.
9080 : * This must be float to avoid overflow.
9081 : *
9082 : * Since the floating-point dividend and divisor use 4 base-NBASE input
9083 : * digits, they include roughly 40-53 bits of information from their
9084 : * respective inputs (assuming NBASE is 10000), which fits well in IEEE
9085 : * double-precision variables. The relative error in the floating-point
9086 : * quotient digit will then be less than around 2/NBASE^3, so the
9087 : * estimated base-NBASE^2 quotient digit will typically be correct, and
9088 : * should not be off by more than one from the correct value.
9089 : */
9090 5442 : fdivisor = (double) divisor[0] * NBASE_SQR;
9091 5442 : if (var2ndigitpairs > 1)
9092 5442 : fdivisor += (double) divisor[1];
9093 5442 : fdivisorinverse = 1.0 / fdivisor;
9094 :
9095 : /*
9096 : * maxdiv tracks the maximum possible absolute value of any dividend[]
9097 : * entry; when this threatens to exceed PG_INT64_MAX, we take the time to
9098 : * propagate carries. Furthermore, we need to ensure that overflow
9099 : * doesn't occur during the carry propagation passes either. The carry
9100 : * values may have an absolute value as high as PG_INT64_MAX/NBASE^2 + 1,
9101 : * so really we must normalize when digits threaten to exceed PG_INT64_MAX
9102 : * - PG_INT64_MAX/NBASE^2 - 1.
9103 : *
9104 : * To avoid overflow in maxdiv itself, it represents the max absolute
9105 : * value divided by NBASE^2-1, i.e., at the top of the loop it is known
9106 : * that no dividend[] entry has an absolute value exceeding maxdiv *
9107 : * (NBASE^2-1).
9108 : *
9109 : * Actually, though, that holds good only for dividend[] entries after
9110 : * dividend[qi]; the adjustment done at the bottom of the loop may cause
9111 : * dividend[qi + 1] to exceed the maxdiv limit, so that dividend[qi] in
9112 : * the next iteration is beyond the limit. This does not cause problems,
9113 : * as explained below.
9114 : */
9115 5442 : maxdiv = 1;
9116 :
9117 : /*
9118 : * Outer loop computes next quotient digit, which goes in dividend[qi].
9119 : */
9120 49542 : for (qi = 0; qi < res_ndigitpairs; qi++)
9121 : {
9122 : /* Approximate the current dividend value */
9123 44100 : fdividend = (double) dividend[qi] * NBASE_SQR;
9124 44100 : fdividend += (double) dividend[qi + 1];
9125 :
9126 : /* Compute the (approximate) quotient digit */
9127 44100 : fquotient = fdividend * fdivisorinverse;
9128 44100 : qdigit = (fquotient >= 0.0) ? ((int32) fquotient) :
9129 6 : (((int32) fquotient) - 1); /* truncate towards -infinity */
9130 :
9131 44100 : if (qdigit != 0)
9132 : {
9133 : /* Do we need to normalize now? */
9134 40506 : maxdiv += i64abs(qdigit);
9135 40506 : if (maxdiv > (PG_INT64_MAX - PG_INT64_MAX / NBASE_SQR - 1) / (NBASE_SQR - 1))
9136 : {
9137 : /*
9138 : * Yes, do it. Note that if var2ndigitpairs is much smaller
9139 : * than div_ndigitpairs, we can save a significant amount of
9140 : * effort here by noting that we only need to normalise those
9141 : * dividend[] entries touched where prior iterations
9142 : * subtracted multiples of the divisor.
9143 : */
9144 6 : carry = 0;
9145 6750 : for (i = Min(qi + var2ndigitpairs - 2, div_ndigitpairs - 1); i > qi; i--)
9146 : {
9147 6744 : newdig = dividend[i] + carry;
9148 6744 : if (newdig < 0)
9149 : {
9150 6744 : carry = -((-newdig - 1) / NBASE_SQR) - 1;
9151 6744 : newdig -= carry * NBASE_SQR;
9152 : }
9153 0 : else if (newdig >= NBASE_SQR)
9154 : {
9155 0 : carry = newdig / NBASE_SQR;
9156 0 : newdig -= carry * NBASE_SQR;
9157 : }
9158 : else
9159 0 : carry = 0;
9160 6744 : dividend[i] = newdig;
9161 : }
9162 6 : dividend[qi] += carry;
9163 :
9164 : /*
9165 : * All the dividend[] digits except possibly dividend[qi] are
9166 : * now in the range 0..NBASE^2-1. We do not need to consider
9167 : * dividend[qi] in the maxdiv value anymore, so we can reset
9168 : * maxdiv to 1.
9169 : */
9170 6 : maxdiv = 1;
9171 :
9172 : /*
9173 : * Recompute the quotient digit since new info may have
9174 : * propagated into the top two dividend digits.
9175 : */
9176 6 : fdividend = (double) dividend[qi] * NBASE_SQR;
9177 6 : fdividend += (double) dividend[qi + 1];
9178 6 : fquotient = fdividend * fdivisorinverse;
9179 6 : qdigit = (fquotient >= 0.0) ? ((int32) fquotient) :
9180 0 : (((int32) fquotient) - 1); /* truncate towards -infinity */
9181 :
9182 6 : maxdiv += i64abs(qdigit);
9183 : }
9184 :
9185 : /*
9186 : * Subtract off the appropriate multiple of the divisor.
9187 : *
9188 : * The digits beyond dividend[qi] cannot overflow, because we know
9189 : * they will fall within the maxdiv limit. As for dividend[qi]
9190 : * itself, note that qdigit is approximately trunc(dividend[qi] /
9191 : * divisor[0]), which would make the new value simply dividend[qi]
9192 : * mod divisor[0]. The lower-order terms in qdigit can change
9193 : * this result by not more than about twice PG_INT64_MAX/NBASE^2,
9194 : * so overflow is impossible.
9195 : *
9196 : * This inner loop is the performance bottleneck for division, so
9197 : * code it in the same way as the inner loop of mul_var() so that
9198 : * it can be auto-vectorized.
9199 : */
9200 40506 : if (qdigit != 0)
9201 : {
9202 40506 : int istop = Min(var2ndigitpairs, div_ndigitpairs - qi);
9203 40506 : int64 *dividend_qi = ÷nd[qi];
9204 :
9205 7861254 : for (i = 0; i < istop; i++)
9206 7820748 : dividend_qi[i] -= (int64) qdigit * divisor[i];
9207 : }
9208 : }
9209 :
9210 : /*
9211 : * The dividend digit we are about to replace might still be nonzero.
9212 : * Fold it into the next digit position.
9213 : *
9214 : * There is no risk of overflow here, although proving that requires
9215 : * some care. Much as with the argument for dividend[qi] not
9216 : * overflowing, if we consider the first two terms in the numerator
9217 : * and denominator of qdigit, we can see that the final value of
9218 : * dividend[qi + 1] will be approximately a remainder mod
9219 : * (divisor[0]*NBASE^2 + divisor[1]). Accounting for the lower-order
9220 : * terms is a bit complicated but ends up adding not much more than
9221 : * PG_INT64_MAX/NBASE^2 to the possible range. Thus, dividend[qi + 1]
9222 : * cannot overflow here, and in its role as dividend[qi] in the next
9223 : * loop iteration, it can't be large enough to cause overflow in the
9224 : * carry propagation step (if any), either.
9225 : *
9226 : * But having said that: dividend[qi] can be more than
9227 : * PG_INT64_MAX/NBASE^2, as noted above, which means that the product
9228 : * dividend[qi] * NBASE^2 *can* overflow. When that happens, adding
9229 : * it to dividend[qi + 1] will always cause a canceling overflow so
9230 : * that the end result is correct. We could avoid the intermediate
9231 : * overflow by doing the multiplication and addition using unsigned
9232 : * int64 arithmetic, which is modulo 2^64, but so far there appears no
9233 : * need.
9234 : */
9235 44100 : dividend[qi + 1] += dividend[qi] * NBASE_SQR;
9236 :
9237 44100 : dividend[qi] = qdigit;
9238 : }
9239 :
9240 : /*
9241 : * If an exact result was requested, use the remainder to correct the
9242 : * approximate quotient. The remainder is in dividend[], immediately
9243 : * after the quotient digits. Note, however, that although the remainder
9244 : * starts at dividend[qi = res_ndigitpairs], the first digit is the result
9245 : * of folding two remainder digits into one above, and the remainder
9246 : * currently only occupies var2ndigitpairs - 1 digits (the last digit of
9247 : * the working dividend was untouched by the computation above). Thus we
9248 : * expand the remainder down by one base-NBASE^2 digit when we normalize
9249 : * it, so that it completely fills the last var2ndigitpairs digits of the
9250 : * dividend array.
9251 : */
9252 5442 : if (exact)
9253 : {
9254 : /* Normalize the remainder, expanding it down by one digit */
9255 3720 : remainder = ÷nd[qi];
9256 3720 : carry = 0;
9257 20214 : for (i = var2ndigitpairs - 2; i >= 0; i--)
9258 : {
9259 16494 : newdig = remainder[i] + carry;
9260 16494 : if (newdig < 0)
9261 : {
9262 12732 : carry = -((-newdig - 1) / NBASE_SQR) - 1;
9263 12732 : newdig -= carry * NBASE_SQR;
9264 : }
9265 3762 : else if (newdig >= NBASE_SQR)
9266 : {
9267 3684 : carry = newdig / NBASE_SQR;
9268 3684 : newdig -= carry * NBASE_SQR;
9269 : }
9270 : else
9271 78 : carry = 0;
9272 16494 : remainder[i + 1] = newdig;
9273 : }
9274 3720 : remainder[0] = carry;
9275 :
9276 3720 : if (remainder[0] < 0)
9277 : {
9278 : /*
9279 : * The remainder is negative, so the approximate quotient is too
9280 : * large. Correct by reducing the quotient by one and adding the
9281 : * divisor to the remainder until the remainder is positive. We
9282 : * expect the quotient to be off by at most one, which has been
9283 : * borne out in all testing, but not conclusively proven, so we
9284 : * allow for larger corrections, just in case.
9285 : */
9286 : do
9287 : {
9288 : /* Add the divisor to the remainder */
9289 6 : carry = 0;
9290 78 : for (i = var2ndigitpairs - 1; i > 0; i--)
9291 : {
9292 72 : newdig = remainder[i] + divisor[i] + carry;
9293 72 : if (newdig >= NBASE_SQR)
9294 : {
9295 0 : remainder[i] = newdig - NBASE_SQR;
9296 0 : carry = 1;
9297 : }
9298 : else
9299 : {
9300 72 : remainder[i] = newdig;
9301 72 : carry = 0;
9302 : }
9303 : }
9304 6 : remainder[0] += divisor[0] + carry;
9305 :
9306 : /* Subtract 1 from the quotient (propagating carries later) */
9307 6 : dividend[qi - 1]--;
9308 :
9309 6 : } while (remainder[0] < 0);
9310 : }
9311 : else
9312 : {
9313 : /*
9314 : * The remainder is nonnegative. If it's greater than or equal to
9315 : * the divisor, then the approximate quotient is too small and
9316 : * must be corrected. As above, we don't expect to have to apply
9317 : * more than one correction, but allow for it just in case.
9318 : */
9319 : while (true)
9320 6 : {
9321 3720 : bool less = false;
9322 :
9323 : /* Is remainder < divisor? */
9324 3738 : for (i = 0; i < var2ndigitpairs; i++)
9325 : {
9326 3732 : if (remainder[i] < divisor[i])
9327 : {
9328 3714 : less = true;
9329 3714 : break;
9330 : }
9331 18 : if (remainder[i] > divisor[i])
9332 0 : break; /* remainder > divisor */
9333 : }
9334 3720 : if (less)
9335 3714 : break; /* quotient is correct */
9336 :
9337 : /* Subtract the divisor from the remainder */
9338 6 : carry = 0;
9339 18 : for (i = var2ndigitpairs - 1; i > 0; i--)
9340 : {
9341 12 : newdig = remainder[i] - divisor[i] + carry;
9342 12 : if (newdig < 0)
9343 : {
9344 0 : remainder[i] = newdig + NBASE_SQR;
9345 0 : carry = -1;
9346 : }
9347 : else
9348 : {
9349 12 : remainder[i] = newdig;
9350 12 : carry = 0;
9351 : }
9352 : }
9353 6 : remainder[0] = remainder[0] - divisor[0] + carry;
9354 :
9355 : /* Add 1 to the quotient (propagating carries later) */
9356 6 : dividend[qi - 1]++;
9357 : }
9358 : }
9359 : }
9360 :
9361 : /*
9362 : * Because the quotient digits were estimates that might have been off by
9363 : * one (and we didn't bother propagating carries when adjusting the
9364 : * quotient above), some quotient digits might be out of range, so do a
9365 : * final carry propagation pass to normalize back to base NBASE^2, and
9366 : * construct the base-NBASE result digits. Note that this is still done
9367 : * at full precision w/guard digits.
9368 : */
9369 5442 : alloc_var(result, res_ndigits);
9370 5442 : res_digits = result->digits;
9371 5442 : carry = 0;
9372 49542 : for (i = res_ndigitpairs - 1; i >= 0; i--)
9373 : {
9374 44100 : newdig = dividend[i] + carry;
9375 44100 : if (newdig < 0)
9376 : {
9377 6 : carry = -((-newdig - 1) / NBASE_SQR) - 1;
9378 6 : newdig -= carry * NBASE_SQR;
9379 : }
9380 44094 : else if (newdig >= NBASE_SQR)
9381 : {
9382 0 : carry = newdig / NBASE_SQR;
9383 0 : newdig -= carry * NBASE_SQR;
9384 : }
9385 : else
9386 44094 : carry = 0;
9387 44100 : res_digits[2 * i + 1] = (NumericDigit) ((uint32) newdig % NBASE);
9388 44100 : res_digits[2 * i] = (NumericDigit) ((uint32) newdig / NBASE);
9389 : }
9390 : Assert(carry == 0);
9391 :
9392 5442 : pfree(dividend);
9393 :
9394 : /*
9395 : * Finally, round or truncate the result to the requested precision.
9396 : */
9397 5442 : result->weight = res_weight;
9398 5442 : result->sign = res_sign;
9399 :
9400 : /* Round or truncate to target rscale (and set result->dscale) */
9401 5442 : if (round)
9402 906 : round_var(result, rscale);
9403 : else
9404 4536 : trunc_var(result, rscale);
9405 :
9406 : /* Strip leading and trailing zeroes */
9407 5442 : strip_var(result);
9408 : }
9409 :
9410 :
9411 : /*
9412 : * div_var_int() -
9413 : *
9414 : * Divide a numeric variable by a 32-bit integer with the specified weight.
9415 : * The quotient var / (ival * NBASE^ival_weight) is stored in result.
9416 : */
9417 : static void
9418 584348 : div_var_int(const NumericVar *var, int ival, int ival_weight,
9419 : NumericVar *result, int rscale, bool round)
9420 : {
9421 584348 : NumericDigit *var_digits = var->digits;
9422 584348 : int var_ndigits = var->ndigits;
9423 : int res_sign;
9424 : int res_weight;
9425 : int res_ndigits;
9426 : NumericDigit *res_buf;
9427 : NumericDigit *res_digits;
9428 : uint32 divisor;
9429 : int i;
9430 :
9431 : /* Guard against division by zero */
9432 584348 : if (ival == 0)
9433 0 : ereport(ERROR,
9434 : errcode(ERRCODE_DIVISION_BY_ZERO),
9435 : errmsg("division by zero"));
9436 :
9437 : /* Result zero check */
9438 584348 : if (var_ndigits == 0)
9439 : {
9440 2300 : zero_var(result);
9441 2300 : result->dscale = rscale;
9442 2300 : return;
9443 : }
9444 :
9445 : /*
9446 : * Determine the result sign, weight and number of digits to calculate.
9447 : * The weight figured here is correct if the emitted quotient has no
9448 : * leading zero digits; otherwise strip_var() will fix things up.
9449 : */
9450 582048 : if (var->sign == NUMERIC_POS)
9451 579060 : res_sign = ival > 0 ? NUMERIC_POS : NUMERIC_NEG;
9452 : else
9453 2988 : res_sign = ival > 0 ? NUMERIC_NEG : NUMERIC_POS;
9454 582048 : res_weight = var->weight - ival_weight;
9455 : /* The number of accurate result digits we need to produce: */
9456 582048 : res_ndigits = res_weight + 1 + (rscale + DEC_DIGITS - 1) / DEC_DIGITS;
9457 : /* ... but always at least 1 */
9458 582048 : res_ndigits = Max(res_ndigits, 1);
9459 : /* If rounding needed, figure one more digit to ensure correct result */
9460 582048 : if (round)
9461 166748 : res_ndigits++;
9462 :
9463 582048 : res_buf = digitbuf_alloc(res_ndigits + 1);
9464 582048 : res_buf[0] = 0; /* spare digit for later rounding */
9465 582048 : res_digits = res_buf + 1;
9466 :
9467 : /*
9468 : * Now compute the quotient digits. This is the short division algorithm
9469 : * described in Knuth volume 2, section 4.3.1 exercise 16, except that we
9470 : * allow the divisor to exceed the internal base.
9471 : *
9472 : * In this algorithm, the carry from one digit to the next is at most
9473 : * divisor - 1. Therefore, while processing the next digit, carry may
9474 : * become as large as divisor * NBASE - 1, and so it requires a 64-bit
9475 : * integer if this exceeds UINT_MAX.
9476 : */
9477 582048 : divisor = abs(ival);
9478 :
9479 582048 : if (divisor <= UINT_MAX / NBASE)
9480 : {
9481 : /* carry cannot overflow 32 bits */
9482 578738 : uint32 carry = 0;
9483 :
9484 2845402 : for (i = 0; i < res_ndigits; i++)
9485 : {
9486 2266664 : carry = carry * NBASE + (i < var_ndigits ? var_digits[i] : 0);
9487 2266664 : res_digits[i] = (NumericDigit) (carry / divisor);
9488 2266664 : carry = carry % divisor;
9489 : }
9490 : }
9491 : else
9492 : {
9493 : /* carry may exceed 32 bits */
9494 3310 : uint64 carry = 0;
9495 :
9496 10596 : for (i = 0; i < res_ndigits; i++)
9497 : {
9498 7286 : carry = carry * NBASE + (i < var_ndigits ? var_digits[i] : 0);
9499 7286 : res_digits[i] = (NumericDigit) (carry / divisor);
9500 7286 : carry = carry % divisor;
9501 : }
9502 : }
9503 :
9504 : /* Store the quotient in result */
9505 582048 : digitbuf_free(result->buf);
9506 582048 : result->ndigits = res_ndigits;
9507 582048 : result->buf = res_buf;
9508 582048 : result->digits = res_digits;
9509 582048 : result->weight = res_weight;
9510 582048 : result->sign = res_sign;
9511 :
9512 : /* Round or truncate to target rscale (and set result->dscale) */
9513 582048 : if (round)
9514 166748 : round_var(result, rscale);
9515 : else
9516 415300 : trunc_var(result, rscale);
9517 :
9518 : /* Strip leading/trailing zeroes */
9519 582048 : strip_var(result);
9520 : }
9521 :
9522 :
9523 : #ifdef HAVE_INT128
9524 : /*
9525 : * div_var_int64() -
9526 : *
9527 : * Divide a numeric variable by a 64-bit integer with the specified weight.
9528 : * The quotient var / (ival * NBASE^ival_weight) is stored in result.
9529 : *
9530 : * This duplicates the logic in div_var_int(), so any changes made there
9531 : * should be made here too.
9532 : */
9533 : static void
9534 528 : div_var_int64(const NumericVar *var, int64 ival, int ival_weight,
9535 : NumericVar *result, int rscale, bool round)
9536 : {
9537 528 : NumericDigit *var_digits = var->digits;
9538 528 : int var_ndigits = var->ndigits;
9539 : int res_sign;
9540 : int res_weight;
9541 : int res_ndigits;
9542 : NumericDigit *res_buf;
9543 : NumericDigit *res_digits;
9544 : uint64 divisor;
9545 : int i;
9546 :
9547 : /* Guard against division by zero */
9548 528 : if (ival == 0)
9549 0 : ereport(ERROR,
9550 : errcode(ERRCODE_DIVISION_BY_ZERO),
9551 : errmsg("division by zero"));
9552 :
9553 : /* Result zero check */
9554 528 : if (var_ndigits == 0)
9555 : {
9556 96 : zero_var(result);
9557 96 : result->dscale = rscale;
9558 96 : return;
9559 : }
9560 :
9561 : /*
9562 : * Determine the result sign, weight and number of digits to calculate.
9563 : * The weight figured here is correct if the emitted quotient has no
9564 : * leading zero digits; otherwise strip_var() will fix things up.
9565 : */
9566 432 : if (var->sign == NUMERIC_POS)
9567 258 : res_sign = ival > 0 ? NUMERIC_POS : NUMERIC_NEG;
9568 : else
9569 174 : res_sign = ival > 0 ? NUMERIC_NEG : NUMERIC_POS;
9570 432 : res_weight = var->weight - ival_weight;
9571 : /* The number of accurate result digits we need to produce: */
9572 432 : res_ndigits = res_weight + 1 + (rscale + DEC_DIGITS - 1) / DEC_DIGITS;
9573 : /* ... but always at least 1 */
9574 432 : res_ndigits = Max(res_ndigits, 1);
9575 : /* If rounding needed, figure one more digit to ensure correct result */
9576 432 : if (round)
9577 426 : res_ndigits++;
9578 :
9579 432 : res_buf = digitbuf_alloc(res_ndigits + 1);
9580 432 : res_buf[0] = 0; /* spare digit for later rounding */
9581 432 : res_digits = res_buf + 1;
9582 :
9583 : /*
9584 : * Now compute the quotient digits. This is the short division algorithm
9585 : * described in Knuth volume 2, section 4.3.1 exercise 16, except that we
9586 : * allow the divisor to exceed the internal base.
9587 : *
9588 : * In this algorithm, the carry from one digit to the next is at most
9589 : * divisor - 1. Therefore, while processing the next digit, carry may
9590 : * become as large as divisor * NBASE - 1, and so it requires a 128-bit
9591 : * integer if this exceeds PG_UINT64_MAX.
9592 : */
9593 432 : divisor = i64abs(ival);
9594 :
9595 432 : if (divisor <= PG_UINT64_MAX / NBASE)
9596 : {
9597 : /* carry cannot overflow 64 bits */
9598 336 : uint64 carry = 0;
9599 :
9600 3414 : for (i = 0; i < res_ndigits; i++)
9601 : {
9602 3078 : carry = carry * NBASE + (i < var_ndigits ? var_digits[i] : 0);
9603 3078 : res_digits[i] = (NumericDigit) (carry / divisor);
9604 3078 : carry = carry % divisor;
9605 : }
9606 : }
9607 : else
9608 : {
9609 : /* carry may exceed 64 bits */
9610 96 : uint128 carry = 0;
9611 :
9612 1032 : for (i = 0; i < res_ndigits; i++)
9613 : {
9614 936 : carry = carry * NBASE + (i < var_ndigits ? var_digits[i] : 0);
9615 936 : res_digits[i] = (NumericDigit) (carry / divisor);
9616 936 : carry = carry % divisor;
9617 : }
9618 : }
9619 :
9620 : /* Store the quotient in result */
9621 432 : digitbuf_free(result->buf);
9622 432 : result->ndigits = res_ndigits;
9623 432 : result->buf = res_buf;
9624 432 : result->digits = res_digits;
9625 432 : result->weight = res_weight;
9626 432 : result->sign = res_sign;
9627 :
9628 : /* Round or truncate to target rscale (and set result->dscale) */
9629 432 : if (round)
9630 426 : round_var(result, rscale);
9631 : else
9632 6 : trunc_var(result, rscale);
9633 :
9634 : /* Strip leading/trailing zeroes */
9635 432 : strip_var(result);
9636 : }
9637 : #endif
9638 :
9639 :
9640 : /*
9641 : * Default scale selection for division
9642 : *
9643 : * Returns the appropriate result scale for the division result.
9644 : */
9645 : static int
9646 149682 : select_div_scale(const NumericVar *var1, const NumericVar *var2)
9647 : {
9648 : int weight1,
9649 : weight2,
9650 : qweight,
9651 : i;
9652 : NumericDigit firstdigit1,
9653 : firstdigit2;
9654 : int rscale;
9655 :
9656 : /*
9657 : * The result scale of a division isn't specified in any SQL standard. For
9658 : * PostgreSQL we select a result scale that will give at least
9659 : * NUMERIC_MIN_SIG_DIGITS significant digits, so that numeric gives a
9660 : * result no less accurate than float8; but use a scale not less than
9661 : * either input's display scale.
9662 : */
9663 :
9664 : /* Get the actual (normalized) weight and first digit of each input */
9665 :
9666 149682 : weight1 = 0; /* values to use if var1 is zero */
9667 149682 : firstdigit1 = 0;
9668 149682 : for (i = 0; i < var1->ndigits; i++)
9669 : {
9670 147982 : firstdigit1 = var1->digits[i];
9671 147982 : if (firstdigit1 != 0)
9672 : {
9673 147982 : weight1 = var1->weight - i;
9674 147982 : break;
9675 : }
9676 : }
9677 :
9678 149682 : weight2 = 0; /* values to use if var2 is zero */
9679 149682 : firstdigit2 = 0;
9680 149682 : for (i = 0; i < var2->ndigits; i++)
9681 : {
9682 149632 : firstdigit2 = var2->digits[i];
9683 149632 : if (firstdigit2 != 0)
9684 : {
9685 149632 : weight2 = var2->weight - i;
9686 149632 : break;
9687 : }
9688 : }
9689 :
9690 : /*
9691 : * Estimate weight of quotient. If the two first digits are equal, we
9692 : * can't be sure, but assume that var1 is less than var2.
9693 : */
9694 149682 : qweight = weight1 - weight2;
9695 149682 : if (firstdigit1 <= firstdigit2)
9696 132850 : qweight--;
9697 :
9698 : /* Select result scale */
9699 149682 : rscale = NUMERIC_MIN_SIG_DIGITS - qweight * DEC_DIGITS;
9700 149682 : rscale = Max(rscale, var1->dscale);
9701 149682 : rscale = Max(rscale, var2->dscale);
9702 149682 : rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
9703 149682 : rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
9704 :
9705 149682 : return rscale;
9706 : }
9707 :
9708 :
9709 : /*
9710 : * mod_var() -
9711 : *
9712 : * Calculate the modulo of two numerics at variable level
9713 : */
9714 : static void
9715 413764 : mod_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
9716 : {
9717 : NumericVar tmp;
9718 :
9719 413764 : init_var(&tmp);
9720 :
9721 : /* ---------
9722 : * We do this using the equation
9723 : * mod(x,y) = x - trunc(x/y)*y
9724 : * div_var can be persuaded to give us trunc(x/y) directly.
9725 : * ----------
9726 : */
9727 413764 : div_var(var1, var2, &tmp, 0, false, true);
9728 :
9729 413764 : mul_var(var2, &tmp, &tmp, var2->dscale);
9730 :
9731 413764 : sub_var(var1, &tmp, result);
9732 :
9733 413764 : free_var(&tmp);
9734 413764 : }
9735 :
9736 :
9737 : /*
9738 : * div_mod_var() -
9739 : *
9740 : * Calculate the truncated integer quotient and numeric remainder of two
9741 : * numeric variables. The remainder is precise to var2's dscale.
9742 : */
9743 : static void
9744 4518 : div_mod_var(const NumericVar *var1, const NumericVar *var2,
9745 : NumericVar *quot, NumericVar *rem)
9746 : {
9747 : NumericVar q;
9748 : NumericVar r;
9749 :
9750 4518 : init_var(&q);
9751 4518 : init_var(&r);
9752 :
9753 : /*
9754 : * Use div_var() with exact = false to get an initial estimate for the
9755 : * integer quotient (truncated towards zero). This might be slightly
9756 : * inaccurate, but we correct it below.
9757 : */
9758 4518 : div_var(var1, var2, &q, 0, false, false);
9759 :
9760 : /* Compute initial estimate of remainder using the quotient estimate. */
9761 4518 : mul_var(var2, &q, &r, var2->dscale);
9762 4518 : sub_var(var1, &r, &r);
9763 :
9764 : /*
9765 : * Adjust the results if necessary --- the remainder should have the same
9766 : * sign as var1, and its absolute value should be less than the absolute
9767 : * value of var2.
9768 : */
9769 4518 : while (r.ndigits != 0 && r.sign != var1->sign)
9770 : {
9771 : /* The absolute value of the quotient is too large */
9772 0 : if (var1->sign == var2->sign)
9773 : {
9774 0 : sub_var(&q, &const_one, &q);
9775 0 : add_var(&r, var2, &r);
9776 : }
9777 : else
9778 : {
9779 0 : add_var(&q, &const_one, &q);
9780 0 : sub_var(&r, var2, &r);
9781 : }
9782 : }
9783 :
9784 4518 : while (cmp_abs(&r, var2) >= 0)
9785 : {
9786 : /* The absolute value of the quotient is too small */
9787 0 : if (var1->sign == var2->sign)
9788 : {
9789 0 : add_var(&q, &const_one, &q);
9790 0 : sub_var(&r, var2, &r);
9791 : }
9792 : else
9793 : {
9794 0 : sub_var(&q, &const_one, &q);
9795 0 : add_var(&r, var2, &r);
9796 : }
9797 : }
9798 :
9799 4518 : set_var_from_var(&q, quot);
9800 4518 : set_var_from_var(&r, rem);
9801 :
9802 4518 : free_var(&q);
9803 4518 : free_var(&r);
9804 4518 : }
9805 :
9806 :
9807 : /*
9808 : * ceil_var() -
9809 : *
9810 : * Return the smallest integer greater than or equal to the argument
9811 : * on variable level
9812 : */
9813 : static void
9814 204 : ceil_var(const NumericVar *var, NumericVar *result)
9815 : {
9816 : NumericVar tmp;
9817 :
9818 204 : init_var(&tmp);
9819 204 : set_var_from_var(var, &tmp);
9820 :
9821 204 : trunc_var(&tmp, 0);
9822 :
9823 204 : if (var->sign == NUMERIC_POS && cmp_var(var, &tmp) != 0)
9824 60 : add_var(&tmp, &const_one, &tmp);
9825 :
9826 204 : set_var_from_var(&tmp, result);
9827 204 : free_var(&tmp);
9828 204 : }
9829 :
9830 :
9831 : /*
9832 : * floor_var() -
9833 : *
9834 : * Return the largest integer equal to or less than the argument
9835 : * on variable level
9836 : */
9837 : static void
9838 108 : floor_var(const NumericVar *var, NumericVar *result)
9839 : {
9840 : NumericVar tmp;
9841 :
9842 108 : init_var(&tmp);
9843 108 : set_var_from_var(var, &tmp);
9844 :
9845 108 : trunc_var(&tmp, 0);
9846 :
9847 108 : if (var->sign == NUMERIC_NEG && cmp_var(var, &tmp) != 0)
9848 30 : sub_var(&tmp, &const_one, &tmp);
9849 :
9850 108 : set_var_from_var(&tmp, result);
9851 108 : free_var(&tmp);
9852 108 : }
9853 :
9854 :
9855 : /*
9856 : * gcd_var() -
9857 : *
9858 : * Calculate the greatest common divisor of two numerics at variable level
9859 : */
9860 : static void
9861 222 : gcd_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
9862 : {
9863 : int res_dscale;
9864 : int cmp;
9865 : NumericVar tmp_arg;
9866 : NumericVar mod;
9867 :
9868 222 : res_dscale = Max(var1->dscale, var2->dscale);
9869 :
9870 : /*
9871 : * Arrange for var1 to be the number with the greater absolute value.
9872 : *
9873 : * This would happen automatically in the loop below, but avoids an
9874 : * expensive modulo operation.
9875 : */
9876 222 : cmp = cmp_abs(var1, var2);
9877 222 : if (cmp < 0)
9878 : {
9879 84 : const NumericVar *tmp = var1;
9880 :
9881 84 : var1 = var2;
9882 84 : var2 = tmp;
9883 : }
9884 :
9885 : /*
9886 : * Also avoid the taking the modulo if the inputs have the same absolute
9887 : * value, or if the smaller input is zero.
9888 : */
9889 222 : if (cmp == 0 || var2->ndigits == 0)
9890 : {
9891 72 : set_var_from_var(var1, result);
9892 72 : result->sign = NUMERIC_POS;
9893 72 : result->dscale = res_dscale;
9894 72 : return;
9895 : }
9896 :
9897 150 : init_var(&tmp_arg);
9898 150 : init_var(&mod);
9899 :
9900 : /* Use the Euclidean algorithm to find the GCD */
9901 150 : set_var_from_var(var1, &tmp_arg);
9902 150 : set_var_from_var(var2, result);
9903 :
9904 : for (;;)
9905 : {
9906 : /* this loop can take a while, so allow it to be interrupted */
9907 588 : CHECK_FOR_INTERRUPTS();
9908 :
9909 588 : mod_var(&tmp_arg, result, &mod);
9910 588 : if (mod.ndigits == 0)
9911 150 : break;
9912 438 : set_var_from_var(result, &tmp_arg);
9913 438 : set_var_from_var(&mod, result);
9914 : }
9915 150 : result->sign = NUMERIC_POS;
9916 150 : result->dscale = res_dscale;
9917 :
9918 150 : free_var(&tmp_arg);
9919 150 : free_var(&mod);
9920 : }
9921 :
9922 :
9923 : /*
9924 : * sqrt_var() -
9925 : *
9926 : * Compute the square root of x using the Karatsuba Square Root algorithm.
9927 : * NOTE: we allow rscale < 0 here, implying rounding before the decimal
9928 : * point.
9929 : */
9930 : static void
9931 4194 : sqrt_var(const NumericVar *arg, NumericVar *result, int rscale)
9932 : {
9933 : int stat;
9934 : int res_weight;
9935 : int res_ndigits;
9936 : int src_ndigits;
9937 : int step;
9938 : int ndigits[32];
9939 : int blen;
9940 : int64 arg_int64;
9941 : int src_idx;
9942 : int64 s_int64;
9943 : int64 r_int64;
9944 : NumericVar s_var;
9945 : NumericVar r_var;
9946 : NumericVar a0_var;
9947 : NumericVar a1_var;
9948 : NumericVar q_var;
9949 : NumericVar u_var;
9950 :
9951 4194 : stat = cmp_var(arg, &const_zero);
9952 4194 : if (stat == 0)
9953 : {
9954 18 : zero_var(result);
9955 18 : result->dscale = rscale;
9956 18 : return;
9957 : }
9958 :
9959 : /*
9960 : * SQL2003 defines sqrt() in terms of power, so we need to emit the right
9961 : * SQLSTATE error code if the operand is negative.
9962 : */
9963 4176 : if (stat < 0)
9964 6 : ereport(ERROR,
9965 : (errcode(ERRCODE_INVALID_ARGUMENT_FOR_POWER_FUNCTION),
9966 : errmsg("cannot take square root of a negative number")));
9967 :
9968 4170 : init_var(&s_var);
9969 4170 : init_var(&r_var);
9970 4170 : init_var(&a0_var);
9971 4170 : init_var(&a1_var);
9972 4170 : init_var(&q_var);
9973 4170 : init_var(&u_var);
9974 :
9975 : /*
9976 : * The result weight is half the input weight, rounded towards minus
9977 : * infinity --- res_weight = floor(arg->weight / 2).
9978 : */
9979 4170 : if (arg->weight >= 0)
9980 3858 : res_weight = arg->weight / 2;
9981 : else
9982 312 : res_weight = -((-arg->weight - 1) / 2 + 1);
9983 :
9984 : /*
9985 : * Number of NBASE digits to compute. To ensure correct rounding, compute
9986 : * at least 1 extra decimal digit. We explicitly allow rscale to be
9987 : * negative here, but must always compute at least 1 NBASE digit. Thus
9988 : * res_ndigits = res_weight + 1 + ceil((rscale + 1) / DEC_DIGITS) or 1.
9989 : */
9990 4170 : if (rscale + 1 >= 0)
9991 4170 : res_ndigits = res_weight + 1 + (rscale + DEC_DIGITS) / DEC_DIGITS;
9992 : else
9993 0 : res_ndigits = res_weight + 1 - (-rscale - 1) / DEC_DIGITS;
9994 4170 : res_ndigits = Max(res_ndigits, 1);
9995 :
9996 : /*
9997 : * Number of source NBASE digits logically required to produce a result
9998 : * with this precision --- every digit before the decimal point, plus 2
9999 : * for each result digit after the decimal point (or minus 2 for each
10000 : * result digit we round before the decimal point).
10001 : */
10002 4170 : src_ndigits = arg->weight + 1 + (res_ndigits - res_weight - 1) * 2;
10003 4170 : src_ndigits = Max(src_ndigits, 1);
10004 :
10005 : /* ----------
10006 : * From this point on, we treat the input and the result as integers and
10007 : * compute the integer square root and remainder using the Karatsuba
10008 : * Square Root algorithm, which may be written recursively as follows:
10009 : *
10010 : * SqrtRem(n = a3*b^3 + a2*b^2 + a1*b + a0):
10011 : * [ for some base b, and coefficients a0,a1,a2,a3 chosen so that
10012 : * 0 <= a0,a1,a2 < b and a3 >= b/4 ]
10013 : * Let (s,r) = SqrtRem(a3*b + a2)
10014 : * Let (q,u) = DivRem(r*b + a1, 2*s)
10015 : * Let s = s*b + q
10016 : * Let r = u*b + a0 - q^2
10017 : * If r < 0 Then
10018 : * Let r = r + s
10019 : * Let s = s - 1
10020 : * Let r = r + s
10021 : * Return (s,r)
10022 : *
10023 : * See "Karatsuba Square Root", Paul Zimmermann, INRIA Research Report
10024 : * RR-3805, November 1999. At the time of writing this was available
10025 : * on the net at <https://hal.inria.fr/inria-00072854>.
10026 : *
10027 : * The way to read the assumption "n = a3*b^3 + a2*b^2 + a1*b + a0" is
10028 : * "choose a base b such that n requires at least four base-b digits to
10029 : * express; then those digits are a3,a2,a1,a0, with a3 possibly larger
10030 : * than b". For optimal performance, b should have approximately a
10031 : * quarter the number of digits in the input, so that the outer square
10032 : * root computes roughly twice as many digits as the inner one. For
10033 : * simplicity, we choose b = NBASE^blen, an integer power of NBASE.
10034 : *
10035 : * We implement the algorithm iteratively rather than recursively, to
10036 : * allow the working variables to be reused. With this approach, each
10037 : * digit of the input is read precisely once --- src_idx tracks the number
10038 : * of input digits used so far.
10039 : *
10040 : * The array ndigits[] holds the number of NBASE digits of the input that
10041 : * will have been used at the end of each iteration, which roughly doubles
10042 : * each time. Note that the array elements are stored in reverse order,
10043 : * so if the final iteration requires src_ndigits = 37 input digits, the
10044 : * array will contain [37,19,11,7,5,3], and we would start by computing
10045 : * the square root of the 3 most significant NBASE digits.
10046 : *
10047 : * In each iteration, we choose blen to be the largest integer for which
10048 : * the input number has a3 >= b/4, when written in the form above. In
10049 : * general, this means blen = src_ndigits / 4 (truncated), but if
10050 : * src_ndigits is a multiple of 4, that might lead to the coefficient a3
10051 : * being less than b/4 (if the first input digit is less than NBASE/4), in
10052 : * which case we choose blen = src_ndigits / 4 - 1. The number of digits
10053 : * in the inner square root is then src_ndigits - 2*blen. So, for
10054 : * example, if we have src_ndigits = 26 initially, the array ndigits[]
10055 : * will be either [26,14,8,4] or [26,14,8,6,4], depending on the size of
10056 : * the first input digit.
10057 : *
10058 : * Additionally, we can put an upper bound on the number of steps required
10059 : * as follows --- suppose that the number of source digits is an n-bit
10060 : * number in the range [2^(n-1), 2^n-1], then blen will be in the range
10061 : * [2^(n-3)-1, 2^(n-2)-1] and the number of digits in the inner square
10062 : * root will be in the range [2^(n-2), 2^(n-1)+1]. In the next step, blen
10063 : * will be in the range [2^(n-4)-1, 2^(n-3)] and the number of digits in
10064 : * the next inner square root will be in the range [2^(n-3), 2^(n-2)+1].
10065 : * This pattern repeats, and in the worst case the array ndigits[] will
10066 : * contain [2^n-1, 2^(n-1)+1, 2^(n-2)+1, ... 9, 5, 3], and the computation
10067 : * will require n steps. Therefore, since all digit array sizes are
10068 : * signed 32-bit integers, the number of steps required is guaranteed to
10069 : * be less than 32.
10070 : * ----------
10071 : */
10072 4170 : step = 0;
10073 19962 : while ((ndigits[step] = src_ndigits) > 4)
10074 : {
10075 : /* Choose b so that a3 >= b/4, as described above */
10076 15792 : blen = src_ndigits / 4;
10077 15792 : if (blen * 4 == src_ndigits && arg->digits[0] < NBASE / 4)
10078 324 : blen--;
10079 :
10080 : /* Number of digits in the next step (inner square root) */
10081 15792 : src_ndigits -= 2 * blen;
10082 15792 : step++;
10083 : }
10084 :
10085 : /*
10086 : * First iteration (innermost square root and remainder):
10087 : *
10088 : * Here src_ndigits <= 4, and the input fits in an int64. Its square root
10089 : * has at most 9 decimal digits, so estimate it using double precision
10090 : * arithmetic, which will in fact almost certainly return the correct
10091 : * result with no further correction required.
10092 : */
10093 4170 : arg_int64 = arg->digits[0];
10094 13314 : for (src_idx = 1; src_idx < src_ndigits; src_idx++)
10095 : {
10096 9144 : arg_int64 *= NBASE;
10097 9144 : if (src_idx < arg->ndigits)
10098 7686 : arg_int64 += arg->digits[src_idx];
10099 : }
10100 :
10101 4170 : s_int64 = (int64) sqrt((double) arg_int64);
10102 4170 : r_int64 = arg_int64 - s_int64 * s_int64;
10103 :
10104 : /*
10105 : * Use Newton's method to correct the result, if necessary.
10106 : *
10107 : * This uses integer division with truncation to compute the truncated
10108 : * integer square root by iterating using the formula x -> (x + n/x) / 2.
10109 : * This is known to converge to isqrt(n), unless n+1 is a perfect square.
10110 : * If n+1 is a perfect square, the sequence will oscillate between the two
10111 : * values isqrt(n) and isqrt(n)+1, so we can be assured of convergence by
10112 : * checking the remainder.
10113 : */
10114 4170 : while (r_int64 < 0 || r_int64 > 2 * s_int64)
10115 : {
10116 0 : s_int64 = (s_int64 + arg_int64 / s_int64) / 2;
10117 0 : r_int64 = arg_int64 - s_int64 * s_int64;
10118 : }
10119 :
10120 : /*
10121 : * Iterations with src_ndigits <= 8:
10122 : *
10123 : * The next 1 or 2 iterations compute larger (outer) square roots with
10124 : * src_ndigits <= 8, so the result still fits in an int64 (even though the
10125 : * input no longer does) and we can continue to compute using int64
10126 : * variables to avoid more expensive numeric computations.
10127 : *
10128 : * It is fairly easy to see that there is no risk of the intermediate
10129 : * values below overflowing 64-bit integers. In the worst case, the
10130 : * previous iteration will have computed a 3-digit square root (of a
10131 : * 6-digit input less than NBASE^6 / 4), so at the start of this
10132 : * iteration, s will be less than NBASE^3 / 2 = 10^12 / 2, and r will be
10133 : * less than 10^12. In this case, blen will be 1, so numer will be less
10134 : * than 10^17, and denom will be less than 10^12 (and hence u will also be
10135 : * less than 10^12). Finally, since q^2 = u*b + a0 - r, we can also be
10136 : * sure that q^2 < 10^17. Therefore all these quantities fit comfortably
10137 : * in 64-bit integers.
10138 : */
10139 4170 : step--;
10140 10566 : while (step >= 0 && (src_ndigits = ndigits[step]) <= 8)
10141 : {
10142 : int b;
10143 : int a0;
10144 : int a1;
10145 : int i;
10146 : int64 numer;
10147 : int64 denom;
10148 : int64 q;
10149 : int64 u;
10150 :
10151 6396 : blen = (src_ndigits - src_idx) / 2;
10152 :
10153 : /* Extract a1 and a0, and compute b */
10154 6396 : a0 = 0;
10155 6396 : a1 = 0;
10156 6396 : b = 1;
10157 :
10158 12936 : for (i = 0; i < blen; i++, src_idx++)
10159 : {
10160 6540 : b *= NBASE;
10161 6540 : a1 *= NBASE;
10162 6540 : if (src_idx < arg->ndigits)
10163 4800 : a1 += arg->digits[src_idx];
10164 : }
10165 :
10166 12936 : for (i = 0; i < blen; i++, src_idx++)
10167 : {
10168 6540 : a0 *= NBASE;
10169 6540 : if (src_idx < arg->ndigits)
10170 4644 : a0 += arg->digits[src_idx];
10171 : }
10172 :
10173 : /* Compute (q,u) = DivRem(r*b + a1, 2*s) */
10174 6396 : numer = r_int64 * b + a1;
10175 6396 : denom = 2 * s_int64;
10176 6396 : q = numer / denom;
10177 6396 : u = numer - q * denom;
10178 :
10179 : /* Compute s = s*b + q and r = u*b + a0 - q^2 */
10180 6396 : s_int64 = s_int64 * b + q;
10181 6396 : r_int64 = u * b + a0 - q * q;
10182 :
10183 6396 : if (r_int64 < 0)
10184 : {
10185 : /* s is too large by 1; set r += s, s--, r += s */
10186 210 : r_int64 += s_int64;
10187 210 : s_int64--;
10188 210 : r_int64 += s_int64;
10189 : }
10190 :
10191 : Assert(src_idx == src_ndigits); /* All input digits consumed */
10192 6396 : step--;
10193 : }
10194 :
10195 : /*
10196 : * On platforms with 128-bit integer support, we can further delay the
10197 : * need to use numeric variables.
10198 : */
10199 : #ifdef HAVE_INT128
10200 4170 : if (step >= 0)
10201 : {
10202 : int128 s_int128;
10203 : int128 r_int128;
10204 :
10205 4170 : s_int128 = s_int64;
10206 4170 : r_int128 = r_int64;
10207 :
10208 : /*
10209 : * Iterations with src_ndigits <= 16:
10210 : *
10211 : * The result fits in an int128 (even though the input doesn't) so we
10212 : * use int128 variables to avoid more expensive numeric computations.
10213 : */
10214 9048 : while (step >= 0 && (src_ndigits = ndigits[step]) <= 16)
10215 : {
10216 : int64 b;
10217 : int64 a0;
10218 : int64 a1;
10219 : int64 i;
10220 : int128 numer;
10221 : int128 denom;
10222 : int128 q;
10223 : int128 u;
10224 :
10225 4878 : blen = (src_ndigits - src_idx) / 2;
10226 :
10227 : /* Extract a1 and a0, and compute b */
10228 4878 : a0 = 0;
10229 4878 : a1 = 0;
10230 4878 : b = 1;
10231 :
10232 16080 : for (i = 0; i < blen; i++, src_idx++)
10233 : {
10234 11202 : b *= NBASE;
10235 11202 : a1 *= NBASE;
10236 11202 : if (src_idx < arg->ndigits)
10237 6606 : a1 += arg->digits[src_idx];
10238 : }
10239 :
10240 16080 : for (i = 0; i < blen; i++, src_idx++)
10241 : {
10242 11202 : a0 *= NBASE;
10243 11202 : if (src_idx < arg->ndigits)
10244 4470 : a0 += arg->digits[src_idx];
10245 : }
10246 :
10247 : /* Compute (q,u) = DivRem(r*b + a1, 2*s) */
10248 4878 : numer = r_int128 * b + a1;
10249 4878 : denom = 2 * s_int128;
10250 4878 : q = numer / denom;
10251 4878 : u = numer - q * denom;
10252 :
10253 : /* Compute s = s*b + q and r = u*b + a0 - q^2 */
10254 4878 : s_int128 = s_int128 * b + q;
10255 4878 : r_int128 = u * b + a0 - q * q;
10256 :
10257 4878 : if (r_int128 < 0)
10258 : {
10259 : /* s is too large by 1; set r += s, s--, r += s */
10260 192 : r_int128 += s_int128;
10261 192 : s_int128--;
10262 192 : r_int128 += s_int128;
10263 : }
10264 :
10265 : Assert(src_idx == src_ndigits); /* All input digits consumed */
10266 4878 : step--;
10267 : }
10268 :
10269 : /*
10270 : * All remaining iterations require numeric variables. Convert the
10271 : * integer values to NumericVar and continue. Note that in the final
10272 : * iteration we don't need the remainder, so we can save a few cycles
10273 : * there by not fully computing it.
10274 : */
10275 4170 : int128_to_numericvar(s_int128, &s_var);
10276 4170 : if (step >= 0)
10277 2724 : int128_to_numericvar(r_int128, &r_var);
10278 : }
10279 : else
10280 : {
10281 0 : int64_to_numericvar(s_int64, &s_var);
10282 : /* step < 0, so we certainly don't need r */
10283 : }
10284 : #else /* !HAVE_INT128 */
10285 : int64_to_numericvar(s_int64, &s_var);
10286 : if (step >= 0)
10287 : int64_to_numericvar(r_int64, &r_var);
10288 : #endif /* HAVE_INT128 */
10289 :
10290 : /*
10291 : * The remaining iterations with src_ndigits > 8 (or 16, if have int128)
10292 : * use numeric variables.
10293 : */
10294 8688 : while (step >= 0)
10295 : {
10296 : int tmp_len;
10297 :
10298 4518 : src_ndigits = ndigits[step];
10299 4518 : blen = (src_ndigits - src_idx) / 2;
10300 :
10301 : /* Extract a1 and a0 */
10302 4518 : if (src_idx < arg->ndigits)
10303 : {
10304 1512 : tmp_len = Min(blen, arg->ndigits - src_idx);
10305 1512 : alloc_var(&a1_var, tmp_len);
10306 1512 : memcpy(a1_var.digits, arg->digits + src_idx,
10307 : tmp_len * sizeof(NumericDigit));
10308 1512 : a1_var.weight = blen - 1;
10309 1512 : a1_var.sign = NUMERIC_POS;
10310 1512 : a1_var.dscale = 0;
10311 1512 : strip_var(&a1_var);
10312 : }
10313 : else
10314 : {
10315 3006 : zero_var(&a1_var);
10316 3006 : a1_var.dscale = 0;
10317 : }
10318 4518 : src_idx += blen;
10319 :
10320 4518 : if (src_idx < arg->ndigits)
10321 : {
10322 1512 : tmp_len = Min(blen, arg->ndigits - src_idx);
10323 1512 : alloc_var(&a0_var, tmp_len);
10324 1512 : memcpy(a0_var.digits, arg->digits + src_idx,
10325 : tmp_len * sizeof(NumericDigit));
10326 1512 : a0_var.weight = blen - 1;
10327 1512 : a0_var.sign = NUMERIC_POS;
10328 1512 : a0_var.dscale = 0;
10329 1512 : strip_var(&a0_var);
10330 : }
10331 : else
10332 : {
10333 3006 : zero_var(&a0_var);
10334 3006 : a0_var.dscale = 0;
10335 : }
10336 4518 : src_idx += blen;
10337 :
10338 : /* Compute (q,u) = DivRem(r*b + a1, 2*s) */
10339 4518 : set_var_from_var(&r_var, &q_var);
10340 4518 : q_var.weight += blen;
10341 4518 : add_var(&q_var, &a1_var, &q_var);
10342 4518 : add_var(&s_var, &s_var, &u_var);
10343 4518 : div_mod_var(&q_var, &u_var, &q_var, &u_var);
10344 :
10345 : /* Compute s = s*b + q */
10346 4518 : s_var.weight += blen;
10347 4518 : add_var(&s_var, &q_var, &s_var);
10348 :
10349 : /*
10350 : * Compute r = u*b + a0 - q^2.
10351 : *
10352 : * In the final iteration, we don't actually need r; we just need to
10353 : * know whether it is negative, so that we know whether to adjust s.
10354 : * So instead of the final subtraction we can just compare.
10355 : */
10356 4518 : u_var.weight += blen;
10357 4518 : add_var(&u_var, &a0_var, &u_var);
10358 4518 : mul_var(&q_var, &q_var, &q_var, 0);
10359 :
10360 4518 : if (step > 0)
10361 : {
10362 : /* Need r for later iterations */
10363 1794 : sub_var(&u_var, &q_var, &r_var);
10364 1794 : if (r_var.sign == NUMERIC_NEG)
10365 : {
10366 : /* s is too large by 1; set r += s, s--, r += s */
10367 120 : add_var(&r_var, &s_var, &r_var);
10368 120 : sub_var(&s_var, &const_one, &s_var);
10369 120 : add_var(&r_var, &s_var, &r_var);
10370 : }
10371 : }
10372 : else
10373 : {
10374 : /* Don't need r anymore, except to test if s is too large by 1 */
10375 2724 : if (cmp_var(&u_var, &q_var) < 0)
10376 36 : sub_var(&s_var, &const_one, &s_var);
10377 : }
10378 :
10379 : Assert(src_idx == src_ndigits); /* All input digits consumed */
10380 4518 : step--;
10381 : }
10382 :
10383 : /*
10384 : * Construct the final result, rounding it to the requested precision.
10385 : */
10386 4170 : set_var_from_var(&s_var, result);
10387 4170 : result->weight = res_weight;
10388 4170 : result->sign = NUMERIC_POS;
10389 :
10390 : /* Round to target rscale (and set result->dscale) */
10391 4170 : round_var(result, rscale);
10392 :
10393 : /* Strip leading and trailing zeroes */
10394 4170 : strip_var(result);
10395 :
10396 4170 : free_var(&s_var);
10397 4170 : free_var(&r_var);
10398 4170 : free_var(&a0_var);
10399 4170 : free_var(&a1_var);
10400 4170 : free_var(&q_var);
10401 4170 : free_var(&u_var);
10402 : }
10403 :
10404 :
10405 : /*
10406 : * exp_var() -
10407 : *
10408 : * Raise e to the power of x, computed to rscale fractional digits
10409 : */
10410 : static void
10411 180 : exp_var(const NumericVar *arg, NumericVar *result, int rscale)
10412 : {
10413 : NumericVar x;
10414 : NumericVar elem;
10415 : int ni;
10416 : double val;
10417 : int dweight;
10418 : int ndiv2;
10419 : int sig_digits;
10420 : int local_rscale;
10421 :
10422 180 : init_var(&x);
10423 180 : init_var(&elem);
10424 :
10425 180 : set_var_from_var(arg, &x);
10426 :
10427 : /*
10428 : * Estimate the dweight of the result using floating point arithmetic, so
10429 : * that we can choose an appropriate local rscale for the calculation.
10430 : */
10431 180 : val = numericvar_to_double_no_overflow(&x);
10432 :
10433 : /* Guard against overflow/underflow */
10434 : /* If you change this limit, see also power_var()'s limit */
10435 180 : if (fabs(val) >= NUMERIC_MAX_RESULT_SCALE * 3)
10436 : {
10437 6 : if (val > 0)
10438 0 : ereport(ERROR,
10439 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
10440 : errmsg("value overflows numeric format")));
10441 6 : zero_var(result);
10442 6 : result->dscale = rscale;
10443 6 : return;
10444 : }
10445 :
10446 : /* decimal weight = log10(e^x) = x * log10(e) */
10447 174 : dweight = (int) (val * 0.434294481903252);
10448 :
10449 : /*
10450 : * Reduce x to the range -0.01 <= x <= 0.01 (approximately) by dividing by
10451 : * 2^ndiv2, to improve the convergence rate of the Taylor series.
10452 : *
10453 : * Note that the overflow check above ensures that fabs(x) < 6000, which
10454 : * means that ndiv2 <= 20 here.
10455 : */
10456 174 : if (fabs(val) > 0.01)
10457 : {
10458 144 : ndiv2 = 1;
10459 144 : val /= 2;
10460 :
10461 1818 : while (fabs(val) > 0.01)
10462 : {
10463 1674 : ndiv2++;
10464 1674 : val /= 2;
10465 : }
10466 :
10467 144 : local_rscale = x.dscale + ndiv2;
10468 144 : div_var_int(&x, 1 << ndiv2, 0, &x, local_rscale, true);
10469 : }
10470 : else
10471 30 : ndiv2 = 0;
10472 :
10473 : /*
10474 : * Set the scale for the Taylor series expansion. The final result has
10475 : * (dweight + rscale + 1) significant digits. In addition, we have to
10476 : * raise the Taylor series result to the power 2^ndiv2, which introduces
10477 : * an error of up to around log10(2^ndiv2) digits, so work with this many
10478 : * extra digits of precision (plus a few more for good measure).
10479 : */
10480 174 : sig_digits = 1 + dweight + rscale + (int) (ndiv2 * 0.301029995663981);
10481 174 : sig_digits = Max(sig_digits, 0) + 8;
10482 :
10483 174 : local_rscale = sig_digits - 1;
10484 :
10485 : /*
10486 : * Use the Taylor series
10487 : *
10488 : * exp(x) = 1 + x + x^2/2! + x^3/3! + ...
10489 : *
10490 : * Given the limited range of x, this should converge reasonably quickly.
10491 : * We run the series until the terms fall below the local_rscale limit.
10492 : */
10493 174 : add_var(&const_one, &x, result);
10494 :
10495 174 : mul_var(&x, &x, &elem, local_rscale);
10496 174 : ni = 2;
10497 174 : div_var_int(&elem, ni, 0, &elem, local_rscale, true);
10498 :
10499 4992 : while (elem.ndigits != 0)
10500 : {
10501 4818 : add_var(result, &elem, result);
10502 :
10503 4818 : mul_var(&elem, &x, &elem, local_rscale);
10504 4818 : ni++;
10505 4818 : div_var_int(&elem, ni, 0, &elem, local_rscale, true);
10506 : }
10507 :
10508 : /*
10509 : * Compensate for the argument range reduction. Since the weight of the
10510 : * result doubles with each multiplication, we can reduce the local rscale
10511 : * as we proceed.
10512 : */
10513 1992 : while (ndiv2-- > 0)
10514 : {
10515 1818 : local_rscale = sig_digits - result->weight * 2 * DEC_DIGITS;
10516 1818 : local_rscale = Max(local_rscale, NUMERIC_MIN_DISPLAY_SCALE);
10517 1818 : mul_var(result, result, result, local_rscale);
10518 : }
10519 :
10520 : /* Round to requested rscale */
10521 174 : round_var(result, rscale);
10522 :
10523 174 : free_var(&x);
10524 174 : free_var(&elem);
10525 : }
10526 :
10527 :
10528 : /*
10529 : * Estimate the dweight of the most significant decimal digit of the natural
10530 : * logarithm of a number.
10531 : *
10532 : * Essentially, we're approximating log10(abs(ln(var))). This is used to
10533 : * determine the appropriate rscale when computing natural logarithms.
10534 : *
10535 : * Note: many callers call this before range-checking the input. Therefore,
10536 : * we must be robust against values that are invalid to apply ln() to.
10537 : * We don't wish to throw an error here, so just return zero in such cases.
10538 : */
10539 : static int
10540 738 : estimate_ln_dweight(const NumericVar *var)
10541 : {
10542 : int ln_dweight;
10543 :
10544 : /* Caller should fail on ln(negative), but for the moment return zero */
10545 738 : if (var->sign != NUMERIC_POS)
10546 42 : return 0;
10547 :
10548 1314 : if (cmp_var(var, &const_zero_point_nine) >= 0 &&
10549 618 : cmp_var(var, &const_one_point_one) <= 0)
10550 90 : {
10551 : /*
10552 : * 0.9 <= var <= 1.1
10553 : *
10554 : * ln(var) has a negative weight (possibly very large). To get a
10555 : * reasonably accurate result, estimate it using ln(1+x) ~= x.
10556 : */
10557 : NumericVar x;
10558 :
10559 90 : init_var(&x);
10560 90 : sub_var(var, &const_one, &x);
10561 :
10562 90 : if (x.ndigits > 0)
10563 : {
10564 : /* Use weight of most significant decimal digit of x */
10565 42 : ln_dweight = x.weight * DEC_DIGITS + (int) log10(x.digits[0]);
10566 : }
10567 : else
10568 : {
10569 : /* x = 0. Since ln(1) = 0 exactly, we don't need extra digits */
10570 48 : ln_dweight = 0;
10571 : }
10572 :
10573 90 : free_var(&x);
10574 : }
10575 : else
10576 : {
10577 : /*
10578 : * Estimate the logarithm using the first couple of digits from the
10579 : * input number. This will give an accurate result whenever the input
10580 : * is not too close to 1.
10581 : */
10582 606 : if (var->ndigits > 0)
10583 : {
10584 : int digits;
10585 : int dweight;
10586 : double ln_var;
10587 :
10588 564 : digits = var->digits[0];
10589 564 : dweight = var->weight * DEC_DIGITS;
10590 :
10591 564 : if (var->ndigits > 1)
10592 : {
10593 342 : digits = digits * NBASE + var->digits[1];
10594 342 : dweight -= DEC_DIGITS;
10595 : }
10596 :
10597 : /*----------
10598 : * We have var ~= digits * 10^dweight
10599 : * so ln(var) ~= ln(digits) + dweight * ln(10)
10600 : *----------
10601 : */
10602 564 : ln_var = log((double) digits) + dweight * 2.302585092994046;
10603 564 : ln_dweight = (int) log10(fabs(ln_var));
10604 : }
10605 : else
10606 : {
10607 : /* Caller should fail on ln(0), but for the moment return zero */
10608 42 : ln_dweight = 0;
10609 : }
10610 : }
10611 :
10612 696 : return ln_dweight;
10613 : }
10614 :
10615 :
10616 : /*
10617 : * ln_var() -
10618 : *
10619 : * Compute the natural log of x
10620 : */
10621 : static void
10622 834 : ln_var(const NumericVar *arg, NumericVar *result, int rscale)
10623 : {
10624 : NumericVar x;
10625 : NumericVar xx;
10626 : int ni;
10627 : NumericVar elem;
10628 : NumericVar fact;
10629 : int nsqrt;
10630 : int local_rscale;
10631 : int cmp;
10632 :
10633 834 : cmp = cmp_var(arg, &const_zero);
10634 834 : if (cmp == 0)
10635 42 : ereport(ERROR,
10636 : (errcode(ERRCODE_INVALID_ARGUMENT_FOR_LOG),
10637 : errmsg("cannot take logarithm of zero")));
10638 792 : else if (cmp < 0)
10639 36 : ereport(ERROR,
10640 : (errcode(ERRCODE_INVALID_ARGUMENT_FOR_LOG),
10641 : errmsg("cannot take logarithm of a negative number")));
10642 :
10643 756 : init_var(&x);
10644 756 : init_var(&xx);
10645 756 : init_var(&elem);
10646 756 : init_var(&fact);
10647 :
10648 756 : set_var_from_var(arg, &x);
10649 756 : set_var_from_var(&const_two, &fact);
10650 :
10651 : /*
10652 : * Reduce input into range 0.9 < x < 1.1 with repeated sqrt() operations.
10653 : *
10654 : * The final logarithm will have up to around rscale+6 significant digits.
10655 : * Each sqrt() will roughly halve the weight of x, so adjust the local
10656 : * rscale as we work so that we keep this many significant digits at each
10657 : * step (plus a few more for good measure).
10658 : *
10659 : * Note that we allow local_rscale < 0 during this input reduction
10660 : * process, which implies rounding before the decimal point. sqrt_var()
10661 : * explicitly supports this, and it significantly reduces the work
10662 : * required to reduce very large inputs to the required range. Once the
10663 : * input reduction is complete, x.weight will be 0 and its display scale
10664 : * will be non-negative again.
10665 : */
10666 756 : nsqrt = 0;
10667 1068 : while (cmp_var(&x, &const_zero_point_nine) <= 0)
10668 : {
10669 312 : local_rscale = rscale - x.weight * DEC_DIGITS / 2 + 8;
10670 312 : sqrt_var(&x, &x, local_rscale);
10671 312 : mul_var(&fact, &const_two, &fact, 0);
10672 312 : nsqrt++;
10673 : }
10674 4128 : while (cmp_var(&x, &const_one_point_one) >= 0)
10675 : {
10676 3372 : local_rscale = rscale - x.weight * DEC_DIGITS / 2 + 8;
10677 3372 : sqrt_var(&x, &x, local_rscale);
10678 3372 : mul_var(&fact, &const_two, &fact, 0);
10679 3372 : nsqrt++;
10680 : }
10681 :
10682 : /*
10683 : * We use the Taylor series for 0.5 * ln((1+z)/(1-z)),
10684 : *
10685 : * z + z^3/3 + z^5/5 + ...
10686 : *
10687 : * where z = (x-1)/(x+1) is in the range (approximately) -0.053 .. 0.048
10688 : * due to the above range-reduction of x.
10689 : *
10690 : * The convergence of this is not as fast as one would like, but is
10691 : * tolerable given that z is small.
10692 : *
10693 : * The Taylor series result will be multiplied by 2^(nsqrt+1), which has a
10694 : * decimal weight of (nsqrt+1) * log10(2), so work with this many extra
10695 : * digits of precision (plus a few more for good measure).
10696 : */
10697 756 : local_rscale = rscale + (int) ((nsqrt + 1) * 0.301029995663981) + 8;
10698 :
10699 756 : sub_var(&x, &const_one, result);
10700 756 : add_var(&x, &const_one, &elem);
10701 756 : div_var(result, &elem, result, local_rscale, true, false);
10702 756 : set_var_from_var(result, &xx);
10703 756 : mul_var(result, result, &x, local_rscale);
10704 :
10705 756 : ni = 1;
10706 :
10707 : for (;;)
10708 : {
10709 14022 : ni += 2;
10710 14022 : mul_var(&xx, &x, &xx, local_rscale);
10711 14022 : div_var_int(&xx, ni, 0, &elem, local_rscale, true);
10712 :
10713 14022 : if (elem.ndigits == 0)
10714 756 : break;
10715 :
10716 13266 : add_var(result, &elem, result);
10717 :
10718 13266 : if (elem.weight < (result->weight - local_rscale * 2 / DEC_DIGITS))
10719 0 : break;
10720 : }
10721 :
10722 : /* Compensate for argument range reduction, round to requested rscale */
10723 756 : mul_var(result, &fact, result, rscale);
10724 :
10725 756 : free_var(&x);
10726 756 : free_var(&xx);
10727 756 : free_var(&elem);
10728 756 : free_var(&fact);
10729 756 : }
10730 :
10731 :
10732 : /*
10733 : * log_var() -
10734 : *
10735 : * Compute the logarithm of num in a given base.
10736 : *
10737 : * Note: this routine chooses dscale of the result.
10738 : */
10739 : static void
10740 216 : log_var(const NumericVar *base, const NumericVar *num, NumericVar *result)
10741 : {
10742 : NumericVar ln_base;
10743 : NumericVar ln_num;
10744 : int ln_base_dweight;
10745 : int ln_num_dweight;
10746 : int result_dweight;
10747 : int rscale;
10748 : int ln_base_rscale;
10749 : int ln_num_rscale;
10750 :
10751 216 : init_var(&ln_base);
10752 216 : init_var(&ln_num);
10753 :
10754 : /* Estimated dweights of ln(base), ln(num) and the final result */
10755 216 : ln_base_dweight = estimate_ln_dweight(base);
10756 216 : ln_num_dweight = estimate_ln_dweight(num);
10757 216 : result_dweight = ln_num_dweight - ln_base_dweight;
10758 :
10759 : /*
10760 : * Select the scale of the result so that it will have at least
10761 : * NUMERIC_MIN_SIG_DIGITS significant digits and is not less than either
10762 : * input's display scale.
10763 : */
10764 216 : rscale = NUMERIC_MIN_SIG_DIGITS - result_dweight;
10765 216 : rscale = Max(rscale, base->dscale);
10766 216 : rscale = Max(rscale, num->dscale);
10767 216 : rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
10768 216 : rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
10769 :
10770 : /*
10771 : * Set the scales for ln(base) and ln(num) so that they each have more
10772 : * significant digits than the final result.
10773 : */
10774 216 : ln_base_rscale = rscale + result_dweight - ln_base_dweight + 8;
10775 216 : ln_base_rscale = Max(ln_base_rscale, NUMERIC_MIN_DISPLAY_SCALE);
10776 :
10777 216 : ln_num_rscale = rscale + result_dweight - ln_num_dweight + 8;
10778 216 : ln_num_rscale = Max(ln_num_rscale, NUMERIC_MIN_DISPLAY_SCALE);
10779 :
10780 : /* Form natural logarithms */
10781 216 : ln_var(base, &ln_base, ln_base_rscale);
10782 192 : ln_var(num, &ln_num, ln_num_rscale);
10783 :
10784 : /* Divide and round to the required scale */
10785 162 : div_var(&ln_num, &ln_base, result, rscale, true, false);
10786 :
10787 156 : free_var(&ln_num);
10788 156 : free_var(&ln_base);
10789 156 : }
10790 :
10791 :
10792 : /*
10793 : * power_var() -
10794 : *
10795 : * Raise base to the power of exp
10796 : *
10797 : * Note: this routine chooses dscale of the result.
10798 : */
10799 : static void
10800 1398 : power_var(const NumericVar *base, const NumericVar *exp, NumericVar *result)
10801 : {
10802 : int res_sign;
10803 : NumericVar abs_base;
10804 : NumericVar ln_base;
10805 : NumericVar ln_num;
10806 : int ln_dweight;
10807 : int rscale;
10808 : int sig_digits;
10809 : int local_rscale;
10810 : double val;
10811 :
10812 : /* If exp can be represented as an integer, use power_var_int */
10813 1398 : if (exp->ndigits == 0 || exp->ndigits <= exp->weight + 1)
10814 : {
10815 : /* exact integer, but does it fit in int? */
10816 : int64 expval64;
10817 :
10818 1272 : if (numericvar_to_int64(exp, &expval64))
10819 : {
10820 1266 : if (expval64 >= PG_INT32_MIN && expval64 <= PG_INT32_MAX)
10821 : {
10822 : /* Okay, use power_var_int */
10823 1236 : power_var_int(base, (int) expval64, exp->dscale, result);
10824 1224 : return;
10825 : }
10826 : }
10827 : }
10828 :
10829 : /*
10830 : * This avoids log(0) for cases of 0 raised to a non-integer. 0 ^ 0 is
10831 : * handled by power_var_int().
10832 : */
10833 162 : if (cmp_var(base, &const_zero) == 0)
10834 : {
10835 18 : set_var_from_var(&const_zero, result);
10836 18 : result->dscale = NUMERIC_MIN_SIG_DIGITS; /* no need to round */
10837 18 : return;
10838 : }
10839 :
10840 144 : init_var(&abs_base);
10841 144 : init_var(&ln_base);
10842 144 : init_var(&ln_num);
10843 :
10844 : /*
10845 : * If base is negative, insist that exp be an integer. The result is then
10846 : * positive if exp is even and negative if exp is odd.
10847 : */
10848 144 : if (base->sign == NUMERIC_NEG)
10849 : {
10850 : /*
10851 : * Check that exp is an integer. This error code is defined by the
10852 : * SQL standard, and matches other errors in numeric_power().
10853 : */
10854 36 : if (exp->ndigits > 0 && exp->ndigits > exp->weight + 1)
10855 18 : ereport(ERROR,
10856 : (errcode(ERRCODE_INVALID_ARGUMENT_FOR_POWER_FUNCTION),
10857 : errmsg("a negative number raised to a non-integer power yields a complex result")));
10858 :
10859 : /* Test if exp is odd or even */
10860 18 : if (exp->ndigits > 0 && exp->ndigits == exp->weight + 1 &&
10861 12 : (exp->digits[exp->ndigits - 1] & 1))
10862 6 : res_sign = NUMERIC_NEG;
10863 : else
10864 12 : res_sign = NUMERIC_POS;
10865 :
10866 : /* Then work with abs(base) below */
10867 18 : set_var_from_var(base, &abs_base);
10868 18 : abs_base.sign = NUMERIC_POS;
10869 18 : base = &abs_base;
10870 : }
10871 : else
10872 108 : res_sign = NUMERIC_POS;
10873 :
10874 : /*----------
10875 : * Decide on the scale for the ln() calculation. For this we need an
10876 : * estimate of the weight of the result, which we obtain by doing an
10877 : * initial low-precision calculation of exp * ln(base).
10878 : *
10879 : * We want result = e ^ (exp * ln(base))
10880 : * so result dweight = log10(result) = exp * ln(base) * log10(e)
10881 : *
10882 : * We also perform a crude overflow test here so that we can exit early if
10883 : * the full-precision result is sure to overflow, and to guard against
10884 : * integer overflow when determining the scale for the real calculation.
10885 : * exp_var() supports inputs up to NUMERIC_MAX_RESULT_SCALE * 3, so the
10886 : * result will overflow if exp * ln(base) >= NUMERIC_MAX_RESULT_SCALE * 3.
10887 : * Since the values here are only approximations, we apply a small fuzz
10888 : * factor to this overflow test and let exp_var() determine the exact
10889 : * overflow threshold so that it is consistent for all inputs.
10890 : *----------
10891 : */
10892 126 : ln_dweight = estimate_ln_dweight(base);
10893 :
10894 : /*
10895 : * Set the scale for the low-precision calculation, computing ln(base) to
10896 : * around 8 significant digits. Note that ln_dweight may be as small as
10897 : * -NUMERIC_DSCALE_MAX, so the scale may exceed NUMERIC_MAX_DISPLAY_SCALE
10898 : * here.
10899 : */
10900 126 : local_rscale = 8 - ln_dweight;
10901 126 : local_rscale = Max(local_rscale, NUMERIC_MIN_DISPLAY_SCALE);
10902 :
10903 126 : ln_var(base, &ln_base, local_rscale);
10904 :
10905 126 : mul_var(&ln_base, exp, &ln_num, local_rscale);
10906 :
10907 126 : val = numericvar_to_double_no_overflow(&ln_num);
10908 :
10909 : /* initial overflow/underflow test with fuzz factor */
10910 126 : if (fabs(val) > NUMERIC_MAX_RESULT_SCALE * 3.01)
10911 : {
10912 6 : if (val > 0)
10913 0 : ereport(ERROR,
10914 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
10915 : errmsg("value overflows numeric format")));
10916 6 : zero_var(result);
10917 6 : result->dscale = NUMERIC_MAX_DISPLAY_SCALE;
10918 6 : return;
10919 : }
10920 :
10921 120 : val *= 0.434294481903252; /* approximate decimal result weight */
10922 :
10923 : /* choose the result scale */
10924 120 : rscale = NUMERIC_MIN_SIG_DIGITS - (int) val;
10925 120 : rscale = Max(rscale, base->dscale);
10926 120 : rscale = Max(rscale, exp->dscale);
10927 120 : rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
10928 120 : rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
10929 :
10930 : /* significant digits required in the result */
10931 120 : sig_digits = rscale + (int) val;
10932 120 : sig_digits = Max(sig_digits, 0);
10933 :
10934 : /* set the scale for the real exp * ln(base) calculation */
10935 120 : local_rscale = sig_digits - ln_dweight + 8;
10936 120 : local_rscale = Max(local_rscale, NUMERIC_MIN_DISPLAY_SCALE);
10937 :
10938 : /* and do the real calculation */
10939 :
10940 120 : ln_var(base, &ln_base, local_rscale);
10941 :
10942 120 : mul_var(&ln_base, exp, &ln_num, local_rscale);
10943 :
10944 120 : exp_var(&ln_num, result, rscale);
10945 :
10946 120 : if (res_sign == NUMERIC_NEG && result->ndigits > 0)
10947 6 : result->sign = NUMERIC_NEG;
10948 :
10949 120 : free_var(&ln_num);
10950 120 : free_var(&ln_base);
10951 120 : free_var(&abs_base);
10952 : }
10953 :
10954 : /*
10955 : * power_var_int() -
10956 : *
10957 : * Raise base to the power of exp, where exp is an integer.
10958 : *
10959 : * Note: this routine chooses dscale of the result.
10960 : */
10961 : static void
10962 1236 : power_var_int(const NumericVar *base, int exp, int exp_dscale,
10963 : NumericVar *result)
10964 : {
10965 : double f;
10966 : int p;
10967 : int i;
10968 : int rscale;
10969 : int sig_digits;
10970 : unsigned int mask;
10971 : bool neg;
10972 : NumericVar base_prod;
10973 : int local_rscale;
10974 :
10975 : /*
10976 : * Choose the result scale. For this we need an estimate of the decimal
10977 : * weight of the result, which we obtain by approximating using double
10978 : * precision arithmetic.
10979 : *
10980 : * We also perform crude overflow/underflow tests here so that we can exit
10981 : * early if the result is sure to overflow/underflow, and to guard against
10982 : * integer overflow when choosing the result scale.
10983 : */
10984 1236 : if (base->ndigits != 0)
10985 : {
10986 : /*----------
10987 : * Choose f (double) and p (int) such that base ~= f * 10^p.
10988 : * Then log10(result) = log10(base^exp) ~= exp * (log10(f) + p).
10989 : *----------
10990 : */
10991 1206 : f = base->digits[0];
10992 1206 : p = base->weight * DEC_DIGITS;
10993 :
10994 1290 : for (i = 1; i < base->ndigits && i * DEC_DIGITS < 16; i++)
10995 : {
10996 84 : f = f * NBASE + base->digits[i];
10997 84 : p -= DEC_DIGITS;
10998 : }
10999 :
11000 1206 : f = exp * (log10(f) + p); /* approximate decimal result weight */
11001 : }
11002 : else
11003 30 : f = 0; /* result is 0 or 1 (weight 0), or error */
11004 :
11005 : /* overflow/underflow tests with fuzz factors */
11006 1236 : if (f > (NUMERIC_WEIGHT_MAX + 1) * DEC_DIGITS)
11007 12 : ereport(ERROR,
11008 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
11009 : errmsg("value overflows numeric format")));
11010 1224 : if (f + 1 < -NUMERIC_MAX_DISPLAY_SCALE)
11011 : {
11012 12 : zero_var(result);
11013 12 : result->dscale = NUMERIC_MAX_DISPLAY_SCALE;
11014 216 : return;
11015 : }
11016 :
11017 : /*
11018 : * Choose the result scale in the same way as power_var(), so it has at
11019 : * least NUMERIC_MIN_SIG_DIGITS significant digits and is not less than
11020 : * either input's display scale.
11021 : */
11022 1212 : rscale = NUMERIC_MIN_SIG_DIGITS - (int) f;
11023 1212 : rscale = Max(rscale, base->dscale);
11024 1212 : rscale = Max(rscale, exp_dscale);
11025 1212 : rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
11026 1212 : rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
11027 :
11028 : /* Handle some common special cases, as well as corner cases */
11029 1212 : switch (exp)
11030 : {
11031 72 : case 0:
11032 :
11033 : /*
11034 : * While 0 ^ 0 can be either 1 or indeterminate (error), we treat
11035 : * it as 1 because most programming languages do this. SQL:2003
11036 : * also requires a return value of 1.
11037 : * https://en.wikipedia.org/wiki/Exponentiation#Zero_to_the_zero_power
11038 : */
11039 72 : set_var_from_var(&const_one, result);
11040 72 : result->dscale = rscale; /* no need to round */
11041 72 : return;
11042 48 : case 1:
11043 48 : set_var_from_var(base, result);
11044 48 : round_var(result, rscale);
11045 48 : return;
11046 30 : case -1:
11047 30 : div_var(&const_one, base, result, rscale, true, true);
11048 30 : return;
11049 54 : case 2:
11050 54 : mul_var(base, base, result, rscale);
11051 54 : return;
11052 1008 : default:
11053 1008 : break;
11054 : }
11055 :
11056 : /* Handle the special case where the base is zero */
11057 1008 : if (base->ndigits == 0)
11058 : {
11059 0 : if (exp < 0)
11060 0 : ereport(ERROR,
11061 : (errcode(ERRCODE_DIVISION_BY_ZERO),
11062 : errmsg("division by zero")));
11063 0 : zero_var(result);
11064 0 : result->dscale = rscale;
11065 0 : return;
11066 : }
11067 :
11068 : /*
11069 : * The general case repeatedly multiplies base according to the bit
11070 : * pattern of exp.
11071 : *
11072 : * The local rscale used for each multiplication is varied to keep a fixed
11073 : * number of significant digits, sufficient to give the required result
11074 : * scale.
11075 : */
11076 :
11077 : /*
11078 : * Approximate number of significant digits in the result. Note that the
11079 : * underflow test above, together with the choice of rscale, ensures that
11080 : * this approximation is necessarily > 0.
11081 : */
11082 1008 : sig_digits = 1 + rscale + (int) f;
11083 :
11084 : /*
11085 : * The multiplications to produce the result may introduce an error of up
11086 : * to around log10(abs(exp)) digits, so work with this many extra digits
11087 : * of precision (plus a few more for good measure).
11088 : */
11089 1008 : sig_digits += (int) log(fabs((double) exp)) + 8;
11090 :
11091 : /*
11092 : * Now we can proceed with the multiplications.
11093 : */
11094 1008 : neg = (exp < 0);
11095 1008 : mask = pg_abs_s32(exp);
11096 :
11097 1008 : init_var(&base_prod);
11098 1008 : set_var_from_var(base, &base_prod);
11099 :
11100 1008 : if (mask & 1)
11101 498 : set_var_from_var(base, result);
11102 : else
11103 510 : set_var_from_var(&const_one, result);
11104 :
11105 5076 : while ((mask >>= 1) > 0)
11106 : {
11107 : /*
11108 : * Do the multiplications using rscales large enough to hold the
11109 : * results to the required number of significant digits, but don't
11110 : * waste time by exceeding the scales of the numbers themselves.
11111 : */
11112 4068 : local_rscale = sig_digits - 2 * base_prod.weight * DEC_DIGITS;
11113 4068 : local_rscale = Min(local_rscale, 2 * base_prod.dscale);
11114 4068 : local_rscale = Max(local_rscale, NUMERIC_MIN_DISPLAY_SCALE);
11115 :
11116 4068 : mul_var(&base_prod, &base_prod, &base_prod, local_rscale);
11117 :
11118 4068 : if (mask & 1)
11119 : {
11120 2658 : local_rscale = sig_digits -
11121 2658 : (base_prod.weight + result->weight) * DEC_DIGITS;
11122 2658 : local_rscale = Min(local_rscale,
11123 : base_prod.dscale + result->dscale);
11124 2658 : local_rscale = Max(local_rscale, NUMERIC_MIN_DISPLAY_SCALE);
11125 :
11126 2658 : mul_var(&base_prod, result, result, local_rscale);
11127 : }
11128 :
11129 : /*
11130 : * When abs(base) > 1, the number of digits to the left of the decimal
11131 : * point in base_prod doubles at each iteration, so if exp is large we
11132 : * could easily spend large amounts of time and memory space doing the
11133 : * multiplications. But once the weight exceeds what will fit in
11134 : * int16, the final result is guaranteed to overflow (or underflow, if
11135 : * exp < 0), so we can give up before wasting too many cycles.
11136 : */
11137 4068 : if (base_prod.weight > NUMERIC_WEIGHT_MAX ||
11138 4068 : result->weight > NUMERIC_WEIGHT_MAX)
11139 : {
11140 : /* overflow, unless neg, in which case result should be 0 */
11141 0 : if (!neg)
11142 0 : ereport(ERROR,
11143 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
11144 : errmsg("value overflows numeric format")));
11145 0 : zero_var(result);
11146 0 : neg = false;
11147 0 : break;
11148 : }
11149 : }
11150 :
11151 1008 : free_var(&base_prod);
11152 :
11153 : /* Compensate for input sign, and round to requested rscale */
11154 1008 : if (neg)
11155 486 : div_var(&const_one, result, result, rscale, true, false);
11156 : else
11157 522 : round_var(result, rscale);
11158 : }
11159 :
11160 : /*
11161 : * power_ten_int() -
11162 : *
11163 : * Raise ten to the power of exp, where exp is an integer. Note that unlike
11164 : * power_var_int(), this does no overflow/underflow checking or rounding.
11165 : */
11166 : static void
11167 228 : power_ten_int(int exp, NumericVar *result)
11168 : {
11169 : /* Construct the result directly, starting from 10^0 = 1 */
11170 228 : set_var_from_var(&const_one, result);
11171 :
11172 : /* Scale needed to represent the result exactly */
11173 228 : result->dscale = exp < 0 ? -exp : 0;
11174 :
11175 : /* Base-NBASE weight of result and remaining exponent */
11176 228 : if (exp >= 0)
11177 162 : result->weight = exp / DEC_DIGITS;
11178 : else
11179 66 : result->weight = (exp + 1) / DEC_DIGITS - 1;
11180 :
11181 228 : exp -= result->weight * DEC_DIGITS;
11182 :
11183 : /* Final adjustment of the result's single NBASE digit */
11184 594 : while (exp-- > 0)
11185 366 : result->digits[0] *= 10;
11186 228 : }
11187 :
11188 : /*
11189 : * random_var() - return a random value in the range [rmin, rmax].
11190 : */
11191 : static void
11192 33438 : random_var(pg_prng_state *state, const NumericVar *rmin,
11193 : const NumericVar *rmax, NumericVar *result)
11194 : {
11195 : int rscale;
11196 : NumericVar rlen;
11197 : int res_ndigits;
11198 : int n;
11199 : int pow10;
11200 : int i;
11201 : uint64 rlen64;
11202 : int rlen64_ndigits;
11203 :
11204 33438 : rscale = Max(rmin->dscale, rmax->dscale);
11205 :
11206 : /* Compute rlen = rmax - rmin and check the range bounds */
11207 33438 : init_var(&rlen);
11208 33438 : sub_var(rmax, rmin, &rlen);
11209 :
11210 33438 : if (rlen.sign == NUMERIC_NEG)
11211 6 : ereport(ERROR,
11212 : errcode(ERRCODE_INVALID_PARAMETER_VALUE),
11213 : errmsg("lower bound must be less than or equal to upper bound"));
11214 :
11215 : /* Special case for an empty range */
11216 33432 : if (rlen.ndigits == 0)
11217 : {
11218 12 : set_var_from_var(rmin, result);
11219 12 : result->dscale = rscale;
11220 12 : free_var(&rlen);
11221 12 : return;
11222 : }
11223 :
11224 : /*
11225 : * Otherwise, select a random value in the range [0, rlen = rmax - rmin],
11226 : * and shift it to the required range by adding rmin.
11227 : */
11228 :
11229 : /* Required result digits */
11230 33420 : res_ndigits = rlen.weight + 1 + (rscale + DEC_DIGITS - 1) / DEC_DIGITS;
11231 :
11232 : /*
11233 : * To get the required rscale, the final result digit must be a multiple
11234 : * of pow10 = 10^n, where n = (-rscale) mod DEC_DIGITS.
11235 : */
11236 33420 : n = ((rscale + DEC_DIGITS - 1) / DEC_DIGITS) * DEC_DIGITS - rscale;
11237 33420 : pow10 = 1;
11238 87900 : for (i = 0; i < n; i++)
11239 54480 : pow10 *= 10;
11240 :
11241 : /*
11242 : * To choose a random value uniformly from the range [0, rlen], we choose
11243 : * from the slightly larger range [0, rlen2], where rlen2 is formed from
11244 : * rlen by copying the first 4 NBASE digits, and setting all remaining
11245 : * decimal digits to "9".
11246 : *
11247 : * Without loss of generality, we can ignore the weight of rlen2 and treat
11248 : * it as a pure integer for the purposes of this discussion. The process
11249 : * above gives rlen2 + 1 = rlen64 * 10^N, for some integer N, where rlen64
11250 : * is a 64-bit integer formed from the first 4 NBASE digits copied from
11251 : * rlen. Since this trivially factors into smaller pieces that fit in
11252 : * 64-bit integers, the task of choosing a random value uniformly from the
11253 : * rlen2 + 1 possible values in [0, rlen2] is much simpler.
11254 : *
11255 : * If the random value selected is too large, it is rejected, and we try
11256 : * again until we get a result <= rlen, ensuring that the overall result
11257 : * is uniform (no particular value is any more likely than any other).
11258 : *
11259 : * Since rlen64 holds 4 NBASE digits from rlen, it contains at least
11260 : * DEC_DIGITS * 3 + 1 decimal digits (i.e., at least 13 decimal digits,
11261 : * when DEC_DIGITS is 4). Therefore the probability of needing to reject
11262 : * the value chosen and retry is less than 1e-13.
11263 : */
11264 33420 : rlen64 = (uint64) rlen.digits[0];
11265 33420 : rlen64_ndigits = 1;
11266 76212 : while (rlen64_ndigits < res_ndigits && rlen64_ndigits < 4)
11267 : {
11268 42792 : rlen64 *= NBASE;
11269 42792 : if (rlen64_ndigits < rlen.ndigits)
11270 6612 : rlen64 += rlen.digits[rlen64_ndigits];
11271 42792 : rlen64_ndigits++;
11272 : }
11273 :
11274 : /* Loop until we get a result <= rlen */
11275 : do
11276 : {
11277 : NumericDigit *res_digits;
11278 : uint64 rand;
11279 : int whole_ndigits;
11280 :
11281 33420 : alloc_var(result, res_ndigits);
11282 33420 : result->sign = NUMERIC_POS;
11283 33420 : result->weight = rlen.weight;
11284 33420 : result->dscale = rscale;
11285 33420 : res_digits = result->digits;
11286 :
11287 : /*
11288 : * Set the first rlen64_ndigits using a random value in [0, rlen64].
11289 : *
11290 : * If this is the whole result, and rscale is not a multiple of
11291 : * DEC_DIGITS (pow10 from above is not 1), then we need this to be a
11292 : * multiple of pow10.
11293 : */
11294 33420 : if (rlen64_ndigits == res_ndigits && pow10 != 1)
11295 21132 : rand = pg_prng_uint64_range(state, 0, rlen64 / pow10) * pow10;
11296 : else
11297 12288 : rand = pg_prng_uint64_range(state, 0, rlen64);
11298 :
11299 109632 : for (i = rlen64_ndigits - 1; i >= 0; i--)
11300 : {
11301 76212 : res_digits[i] = (NumericDigit) (rand % NBASE);
11302 76212 : rand = rand / NBASE;
11303 : }
11304 :
11305 : /*
11306 : * Set the remaining digits to random values in range [0, NBASE),
11307 : * noting that the last digit needs to be a multiple of pow10.
11308 : */
11309 33420 : whole_ndigits = res_ndigits;
11310 33420 : if (pow10 != 1)
11311 33210 : whole_ndigits--;
11312 :
11313 : /* Set whole digits in groups of 4 for best performance */
11314 33420 : i = rlen64_ndigits;
11315 33480 : while (i < whole_ndigits - 3)
11316 : {
11317 60 : rand = pg_prng_uint64_range(state, 0,
11318 : (uint64) NBASE * NBASE * NBASE * NBASE - 1);
11319 60 : res_digits[i++] = (NumericDigit) (rand % NBASE);
11320 60 : rand = rand / NBASE;
11321 60 : res_digits[i++] = (NumericDigit) (rand % NBASE);
11322 60 : rand = rand / NBASE;
11323 60 : res_digits[i++] = (NumericDigit) (rand % NBASE);
11324 60 : rand = rand / NBASE;
11325 60 : res_digits[i++] = (NumericDigit) rand;
11326 : }
11327 :
11328 : /* Remaining whole digits */
11329 33630 : while (i < whole_ndigits)
11330 : {
11331 210 : rand = pg_prng_uint64_range(state, 0, NBASE - 1);
11332 210 : res_digits[i++] = (NumericDigit) rand;
11333 : }
11334 :
11335 : /* Final partial digit (multiple of pow10) */
11336 33420 : if (i < res_ndigits)
11337 : {
11338 12078 : rand = pg_prng_uint64_range(state, 0, NBASE / pow10 - 1) * pow10;
11339 12078 : res_digits[i] = (NumericDigit) rand;
11340 : }
11341 :
11342 : /* Remove leading/trailing zeroes */
11343 33420 : strip_var(result);
11344 :
11345 : /* If result > rlen, try again */
11346 :
11347 33420 : } while (cmp_var(result, &rlen) > 0);
11348 :
11349 : /* Offset the result to the required range */
11350 33420 : add_var(result, rmin, result);
11351 :
11352 33420 : free_var(&rlen);
11353 : }
11354 :
11355 :
11356 : /* ----------------------------------------------------------------------
11357 : *
11358 : * Following are the lowest level functions that operate unsigned
11359 : * on the variable level
11360 : *
11361 : * ----------------------------------------------------------------------
11362 : */
11363 :
11364 :
11365 : /* ----------
11366 : * cmp_abs() -
11367 : *
11368 : * Compare the absolute values of var1 and var2
11369 : * Returns: -1 for ABS(var1) < ABS(var2)
11370 : * 0 for ABS(var1) == ABS(var2)
11371 : * 1 for ABS(var1) > ABS(var2)
11372 : * ----------
11373 : */
11374 : static int
11375 709384 : cmp_abs(const NumericVar *var1, const NumericVar *var2)
11376 : {
11377 1418768 : return cmp_abs_common(var1->digits, var1->ndigits, var1->weight,
11378 709384 : var2->digits, var2->ndigits, var2->weight);
11379 : }
11380 :
11381 : /* ----------
11382 : * cmp_abs_common() -
11383 : *
11384 : * Main routine of cmp_abs(). This function can be used by both
11385 : * NumericVar and Numeric.
11386 : * ----------
11387 : */
11388 : static int
11389 27733812 : cmp_abs_common(const NumericDigit *var1digits, int var1ndigits, int var1weight,
11390 : const NumericDigit *var2digits, int var2ndigits, int var2weight)
11391 : {
11392 27733812 : int i1 = 0;
11393 27733812 : int i2 = 0;
11394 :
11395 : /* Check any digits before the first common digit */
11396 :
11397 27733812 : while (var1weight > var2weight && i1 < var1ndigits)
11398 : {
11399 26214 : if (var1digits[i1++] != 0)
11400 26214 : return 1;
11401 0 : var1weight--;
11402 : }
11403 27707598 : while (var2weight > var1weight && i2 < var2ndigits)
11404 : {
11405 150914 : if (var2digits[i2++] != 0)
11406 150914 : return -1;
11407 0 : var2weight--;
11408 : }
11409 :
11410 : /* At this point, either w1 == w2 or we've run out of digits */
11411 :
11412 27556684 : if (var1weight == var2weight)
11413 : {
11414 43367184 : while (i1 < var1ndigits && i2 < var2ndigits)
11415 : {
11416 29122456 : int stat = var1digits[i1++] - var2digits[i2++];
11417 :
11418 29122456 : if (stat)
11419 : {
11420 13305584 : if (stat > 0)
11421 7885192 : return 1;
11422 5420392 : return -1;
11423 : }
11424 : }
11425 : }
11426 :
11427 : /*
11428 : * At this point, we've run out of digits on one side or the other; so any
11429 : * remaining nonzero digits imply that side is larger
11430 : */
11431 14251436 : while (i1 < var1ndigits)
11432 : {
11433 9542 : if (var1digits[i1++] != 0)
11434 9206 : return 1;
11435 : }
11436 14242218 : while (i2 < var2ndigits)
11437 : {
11438 1236 : if (var2digits[i2++] != 0)
11439 912 : return -1;
11440 : }
11441 :
11442 14240982 : return 0;
11443 : }
11444 :
11445 :
11446 : /*
11447 : * add_abs() -
11448 : *
11449 : * Add the absolute values of two variables into result.
11450 : * result might point to one of the operands without danger.
11451 : */
11452 : static void
11453 446720 : add_abs(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
11454 : {
11455 : NumericDigit *res_buf;
11456 : NumericDigit *res_digits;
11457 : int res_ndigits;
11458 : int res_weight;
11459 : int res_rscale,
11460 : rscale1,
11461 : rscale2;
11462 : int res_dscale;
11463 : int i,
11464 : i1,
11465 : i2;
11466 446720 : int carry = 0;
11467 :
11468 : /* copy these values into local vars for speed in inner loop */
11469 446720 : int var1ndigits = var1->ndigits;
11470 446720 : int var2ndigits = var2->ndigits;
11471 446720 : NumericDigit *var1digits = var1->digits;
11472 446720 : NumericDigit *var2digits = var2->digits;
11473 :
11474 446720 : res_weight = Max(var1->weight, var2->weight) + 1;
11475 :
11476 446720 : res_dscale = Max(var1->dscale, var2->dscale);
11477 :
11478 : /* Note: here we are figuring rscale in base-NBASE digits */
11479 446720 : rscale1 = var1->ndigits - var1->weight - 1;
11480 446720 : rscale2 = var2->ndigits - var2->weight - 1;
11481 446720 : res_rscale = Max(rscale1, rscale2);
11482 :
11483 446720 : res_ndigits = res_rscale + res_weight + 1;
11484 446720 : if (res_ndigits <= 0)
11485 0 : res_ndigits = 1;
11486 :
11487 446720 : res_buf = digitbuf_alloc(res_ndigits + 1);
11488 446720 : res_buf[0] = 0; /* spare digit for later rounding */
11489 446720 : res_digits = res_buf + 1;
11490 :
11491 446720 : i1 = res_rscale + var1->weight + 1;
11492 446720 : i2 = res_rscale + var2->weight + 1;
11493 3641190 : for (i = res_ndigits - 1; i >= 0; i--)
11494 : {
11495 3194470 : i1--;
11496 3194470 : i2--;
11497 3194470 : if (i1 >= 0 && i1 < var1ndigits)
11498 1417312 : carry += var1digits[i1];
11499 3194470 : if (i2 >= 0 && i2 < var2ndigits)
11500 1137000 : carry += var2digits[i2];
11501 :
11502 3194470 : if (carry >= NBASE)
11503 : {
11504 226032 : res_digits[i] = carry - NBASE;
11505 226032 : carry = 1;
11506 : }
11507 : else
11508 : {
11509 2968438 : res_digits[i] = carry;
11510 2968438 : carry = 0;
11511 : }
11512 : }
11513 :
11514 : Assert(carry == 0); /* else we failed to allow for carry out */
11515 :
11516 446720 : digitbuf_free(result->buf);
11517 446720 : result->ndigits = res_ndigits;
11518 446720 : result->buf = res_buf;
11519 446720 : result->digits = res_digits;
11520 446720 : result->weight = res_weight;
11521 446720 : result->dscale = res_dscale;
11522 :
11523 : /* Remove leading/trailing zeroes */
11524 446720 : strip_var(result);
11525 446720 : }
11526 :
11527 :
11528 : /*
11529 : * sub_abs()
11530 : *
11531 : * Subtract the absolute value of var2 from the absolute value of var1
11532 : * and store in result. result might point to one of the operands
11533 : * without danger.
11534 : *
11535 : * ABS(var1) MUST BE GREATER OR EQUAL ABS(var2) !!!
11536 : */
11537 : static void
11538 654896 : sub_abs(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
11539 : {
11540 : NumericDigit *res_buf;
11541 : NumericDigit *res_digits;
11542 : int res_ndigits;
11543 : int res_weight;
11544 : int res_rscale,
11545 : rscale1,
11546 : rscale2;
11547 : int res_dscale;
11548 : int i,
11549 : i1,
11550 : i2;
11551 654896 : int borrow = 0;
11552 :
11553 : /* copy these values into local vars for speed in inner loop */
11554 654896 : int var1ndigits = var1->ndigits;
11555 654896 : int var2ndigits = var2->ndigits;
11556 654896 : NumericDigit *var1digits = var1->digits;
11557 654896 : NumericDigit *var2digits = var2->digits;
11558 :
11559 654896 : res_weight = var1->weight;
11560 :
11561 654896 : res_dscale = Max(var1->dscale, var2->dscale);
11562 :
11563 : /* Note: here we are figuring rscale in base-NBASE digits */
11564 654896 : rscale1 = var1->ndigits - var1->weight - 1;
11565 654896 : rscale2 = var2->ndigits - var2->weight - 1;
11566 654896 : res_rscale = Max(rscale1, rscale2);
11567 :
11568 654896 : res_ndigits = res_rscale + res_weight + 1;
11569 654896 : if (res_ndigits <= 0)
11570 0 : res_ndigits = 1;
11571 :
11572 654896 : res_buf = digitbuf_alloc(res_ndigits + 1);
11573 654896 : res_buf[0] = 0; /* spare digit for later rounding */
11574 654896 : res_digits = res_buf + 1;
11575 :
11576 654896 : i1 = res_rscale + var1->weight + 1;
11577 654896 : i2 = res_rscale + var2->weight + 1;
11578 5187370 : for (i = res_ndigits - 1; i >= 0; i--)
11579 : {
11580 4532474 : i1--;
11581 4532474 : i2--;
11582 4532474 : if (i1 >= 0 && i1 < var1ndigits)
11583 4107316 : borrow += var1digits[i1];
11584 4532474 : if (i2 >= 0 && i2 < var2ndigits)
11585 4035134 : borrow -= var2digits[i2];
11586 :
11587 4532474 : if (borrow < 0)
11588 : {
11589 458286 : res_digits[i] = borrow + NBASE;
11590 458286 : borrow = -1;
11591 : }
11592 : else
11593 : {
11594 4074188 : res_digits[i] = borrow;
11595 4074188 : borrow = 0;
11596 : }
11597 : }
11598 :
11599 : Assert(borrow == 0); /* else caller gave us var1 < var2 */
11600 :
11601 654896 : digitbuf_free(result->buf);
11602 654896 : result->ndigits = res_ndigits;
11603 654896 : result->buf = res_buf;
11604 654896 : result->digits = res_digits;
11605 654896 : result->weight = res_weight;
11606 654896 : result->dscale = res_dscale;
11607 :
11608 : /* Remove leading/trailing zeroes */
11609 654896 : strip_var(result);
11610 654896 : }
11611 :
11612 : /*
11613 : * round_var
11614 : *
11615 : * Round the value of a variable to no more than rscale decimal digits
11616 : * after the decimal point. NOTE: we allow rscale < 0 here, implying
11617 : * rounding before the decimal point.
11618 : */
11619 : static void
11620 248844 : round_var(NumericVar *var, int rscale)
11621 : {
11622 248844 : NumericDigit *digits = var->digits;
11623 : int di;
11624 : int ndigits;
11625 : int carry;
11626 :
11627 248844 : var->dscale = rscale;
11628 :
11629 : /* decimal digits wanted */
11630 248844 : di = (var->weight + 1) * DEC_DIGITS + rscale;
11631 :
11632 : /*
11633 : * If di = 0, the value loses all digits, but could round up to 1 if its
11634 : * first extra digit is >= 5. If di < 0 the result must be 0.
11635 : */
11636 248844 : if (di < 0)
11637 : {
11638 104 : var->ndigits = 0;
11639 104 : var->weight = 0;
11640 104 : var->sign = NUMERIC_POS;
11641 : }
11642 : else
11643 : {
11644 : /* NBASE digits wanted */
11645 248740 : ndigits = (di + DEC_DIGITS - 1) / DEC_DIGITS;
11646 :
11647 : /* 0, or number of decimal digits to keep in last NBASE digit */
11648 248740 : di %= DEC_DIGITS;
11649 :
11650 248740 : if (ndigits < var->ndigits ||
11651 45886 : (ndigits == var->ndigits && di > 0))
11652 : {
11653 206308 : var->ndigits = ndigits;
11654 :
11655 : #if DEC_DIGITS == 1
11656 : /* di must be zero */
11657 : carry = (digits[ndigits] >= HALF_NBASE) ? 1 : 0;
11658 : #else
11659 206308 : if (di == 0)
11660 164432 : carry = (digits[ndigits] >= HALF_NBASE) ? 1 : 0;
11661 : else
11662 : {
11663 : /* Must round within last NBASE digit */
11664 : int extra,
11665 : pow10;
11666 :
11667 : #if DEC_DIGITS == 4
11668 41876 : pow10 = round_powers[di];
11669 : #elif DEC_DIGITS == 2
11670 : pow10 = 10;
11671 : #else
11672 : #error unsupported NBASE
11673 : #endif
11674 41876 : extra = digits[--ndigits] % pow10;
11675 41876 : digits[ndigits] -= extra;
11676 41876 : carry = 0;
11677 41876 : if (extra >= pow10 / 2)
11678 : {
11679 19448 : pow10 += digits[ndigits];
11680 19448 : if (pow10 >= NBASE)
11681 : {
11682 812 : pow10 -= NBASE;
11683 812 : carry = 1;
11684 : }
11685 19448 : digits[ndigits] = pow10;
11686 : }
11687 : }
11688 : #endif
11689 :
11690 : /* Propagate carry if needed */
11691 240038 : while (carry)
11692 : {
11693 33730 : carry += digits[--ndigits];
11694 33730 : if (carry >= NBASE)
11695 : {
11696 24626 : digits[ndigits] = carry - NBASE;
11697 24626 : carry = 1;
11698 : }
11699 : else
11700 : {
11701 9104 : digits[ndigits] = carry;
11702 9104 : carry = 0;
11703 : }
11704 : }
11705 :
11706 206308 : if (ndigits < 0)
11707 : {
11708 : Assert(ndigits == -1); /* better not have added > 1 digit */
11709 : Assert(var->digits > var->buf);
11710 96 : var->digits--;
11711 96 : var->ndigits++;
11712 96 : var->weight++;
11713 : }
11714 : }
11715 : }
11716 248844 : }
11717 :
11718 : /*
11719 : * trunc_var
11720 : *
11721 : * Truncate (towards zero) the value of a variable at rscale decimal digits
11722 : * after the decimal point. NOTE: we allow rscale < 0 here, implying
11723 : * truncation before the decimal point.
11724 : */
11725 : static void
11726 420888 : trunc_var(NumericVar *var, int rscale)
11727 : {
11728 : int di;
11729 : int ndigits;
11730 :
11731 420888 : var->dscale = rscale;
11732 :
11733 : /* decimal digits wanted */
11734 420888 : di = (var->weight + 1) * DEC_DIGITS + rscale;
11735 :
11736 : /*
11737 : * If di <= 0, the value loses all digits.
11738 : */
11739 420888 : if (di <= 0)
11740 : {
11741 90 : var->ndigits = 0;
11742 90 : var->weight = 0;
11743 90 : var->sign = NUMERIC_POS;
11744 : }
11745 : else
11746 : {
11747 : /* NBASE digits wanted */
11748 420798 : ndigits = (di + DEC_DIGITS - 1) / DEC_DIGITS;
11749 :
11750 420798 : if (ndigits <= var->ndigits)
11751 : {
11752 420528 : var->ndigits = ndigits;
11753 :
11754 : #if DEC_DIGITS == 1
11755 : /* no within-digit stuff to worry about */
11756 : #else
11757 : /* 0, or number of decimal digits to keep in last NBASE digit */
11758 420528 : di %= DEC_DIGITS;
11759 :
11760 420528 : if (di > 0)
11761 : {
11762 : /* Must truncate within last NBASE digit */
11763 106 : NumericDigit *digits = var->digits;
11764 : int extra,
11765 : pow10;
11766 :
11767 : #if DEC_DIGITS == 4
11768 106 : pow10 = round_powers[di];
11769 : #elif DEC_DIGITS == 2
11770 : pow10 = 10;
11771 : #else
11772 : #error unsupported NBASE
11773 : #endif
11774 106 : extra = digits[--ndigits] % pow10;
11775 106 : digits[ndigits] -= extra;
11776 : }
11777 : #endif
11778 : }
11779 : }
11780 420888 : }
11781 :
11782 : /*
11783 : * strip_var
11784 : *
11785 : * Strip any leading and trailing zeroes from a numeric variable
11786 : */
11787 : static void
11788 3287344 : strip_var(NumericVar *var)
11789 : {
11790 3287344 : NumericDigit *digits = var->digits;
11791 3287344 : int ndigits = var->ndigits;
11792 :
11793 : /* Strip leading zeroes */
11794 5635854 : while (ndigits > 0 && *digits == 0)
11795 : {
11796 2348510 : digits++;
11797 2348510 : var->weight--;
11798 2348510 : ndigits--;
11799 : }
11800 :
11801 : /* Strip trailing zeroes */
11802 3961120 : while (ndigits > 0 && digits[ndigits - 1] == 0)
11803 673776 : ndigits--;
11804 :
11805 : /* If it's zero, normalize the sign and weight */
11806 3287344 : if (ndigits == 0)
11807 : {
11808 52034 : var->sign = NUMERIC_POS;
11809 52034 : var->weight = 0;
11810 : }
11811 :
11812 3287344 : var->digits = digits;
11813 3287344 : var->ndigits = ndigits;
11814 3287344 : }
11815 :
11816 :
11817 : /* ----------------------------------------------------------------------
11818 : *
11819 : * Fast sum accumulator functions
11820 : *
11821 : * ----------------------------------------------------------------------
11822 : */
11823 :
11824 : /*
11825 : * Reset the accumulator's value to zero. The buffers to hold the digits
11826 : * are not free'd.
11827 : */
11828 : static void
11829 18 : accum_sum_reset(NumericSumAccum *accum)
11830 : {
11831 : int i;
11832 :
11833 18 : accum->dscale = 0;
11834 66 : for (i = 0; i < accum->ndigits; i++)
11835 : {
11836 48 : accum->pos_digits[i] = 0;
11837 48 : accum->neg_digits[i] = 0;
11838 : }
11839 18 : }
11840 :
11841 : /*
11842 : * Accumulate a new value.
11843 : */
11844 : static void
11845 2355716 : accum_sum_add(NumericSumAccum *accum, const NumericVar *val)
11846 : {
11847 : int32 *accum_digits;
11848 : int i,
11849 : val_i;
11850 : int val_ndigits;
11851 : NumericDigit *val_digits;
11852 :
11853 : /*
11854 : * If we have accumulated too many values since the last carry
11855 : * propagation, do it now, to avoid overflowing. (We could allow more
11856 : * than NBASE - 1, if we reserved two extra digits, rather than one, for
11857 : * carry propagation. But even with NBASE - 1, this needs to be done so
11858 : * seldom, that the performance difference is negligible.)
11859 : */
11860 2355716 : if (accum->num_uncarried == NBASE - 1)
11861 144 : accum_sum_carry(accum);
11862 :
11863 : /*
11864 : * Adjust the weight or scale of the old value, so that it can accommodate
11865 : * the new value.
11866 : */
11867 2355716 : accum_sum_rescale(accum, val);
11868 :
11869 : /* */
11870 2355716 : if (val->sign == NUMERIC_POS)
11871 1755038 : accum_digits = accum->pos_digits;
11872 : else
11873 600678 : accum_digits = accum->neg_digits;
11874 :
11875 : /* copy these values into local vars for speed in loop */
11876 2355716 : val_ndigits = val->ndigits;
11877 2355716 : val_digits = val->digits;
11878 :
11879 2355716 : i = accum->weight - val->weight;
11880 11889978 : for (val_i = 0; val_i < val_ndigits; val_i++)
11881 : {
11882 9534262 : accum_digits[i] += (int32) val_digits[val_i];
11883 9534262 : i++;
11884 : }
11885 :
11886 2355716 : accum->num_uncarried++;
11887 2355716 : }
11888 :
11889 : /*
11890 : * Propagate carries.
11891 : */
11892 : static void
11893 172758 : accum_sum_carry(NumericSumAccum *accum)
11894 : {
11895 : int i;
11896 : int ndigits;
11897 : int32 *dig;
11898 : int32 carry;
11899 172758 : int32 newdig = 0;
11900 :
11901 : /*
11902 : * If no new values have been added since last carry propagation, nothing
11903 : * to do.
11904 : */
11905 172758 : if (accum->num_uncarried == 0)
11906 72 : return;
11907 :
11908 : /*
11909 : * We maintain that the weight of the accumulator is always one larger
11910 : * than needed to hold the current value, before carrying, to make sure
11911 : * there is enough space for the possible extra digit when carry is
11912 : * propagated. We cannot expand the buffer here, unless we require
11913 : * callers of accum_sum_final() to switch to the right memory context.
11914 : */
11915 : Assert(accum->pos_digits[0] == 0 && accum->neg_digits[0] == 0);
11916 :
11917 172686 : ndigits = accum->ndigits;
11918 :
11919 : /* Propagate carry in the positive sum */
11920 172686 : dig = accum->pos_digits;
11921 172686 : carry = 0;
11922 2605522 : for (i = ndigits - 1; i >= 0; i--)
11923 : {
11924 2432836 : newdig = dig[i] + carry;
11925 2432836 : if (newdig >= NBASE)
11926 : {
11927 110798 : carry = newdig / NBASE;
11928 110798 : newdig -= carry * NBASE;
11929 : }
11930 : else
11931 2322038 : carry = 0;
11932 2432836 : dig[i] = newdig;
11933 : }
11934 : /* Did we use up the digit reserved for carry propagation? */
11935 172686 : if (newdig > 0)
11936 2644 : accum->have_carry_space = false;
11937 :
11938 : /* And the same for the negative sum */
11939 172686 : dig = accum->neg_digits;
11940 172686 : carry = 0;
11941 2605522 : for (i = ndigits - 1; i >= 0; i--)
11942 : {
11943 2432836 : newdig = dig[i] + carry;
11944 2432836 : if (newdig >= NBASE)
11945 : {
11946 198 : carry = newdig / NBASE;
11947 198 : newdig -= carry * NBASE;
11948 : }
11949 : else
11950 2432638 : carry = 0;
11951 2432836 : dig[i] = newdig;
11952 : }
11953 172686 : if (newdig > 0)
11954 30 : accum->have_carry_space = false;
11955 :
11956 172686 : accum->num_uncarried = 0;
11957 : }
11958 :
11959 : /*
11960 : * Re-scale accumulator to accommodate new value.
11961 : *
11962 : * If the new value has more digits than the current digit buffers in the
11963 : * accumulator, enlarge the buffers.
11964 : */
11965 : static void
11966 2355716 : accum_sum_rescale(NumericSumAccum *accum, const NumericVar *val)
11967 : {
11968 2355716 : int old_weight = accum->weight;
11969 2355716 : int old_ndigits = accum->ndigits;
11970 : int accum_ndigits;
11971 : int accum_weight;
11972 : int accum_rscale;
11973 : int val_rscale;
11974 :
11975 2355716 : accum_weight = old_weight;
11976 2355716 : accum_ndigits = old_ndigits;
11977 :
11978 : /*
11979 : * Does the new value have a larger weight? If so, enlarge the buffers,
11980 : * and shift the existing value to the new weight, by adding leading
11981 : * zeros.
11982 : *
11983 : * We enforce that the accumulator always has a weight one larger than
11984 : * needed for the inputs, so that we have space for an extra digit at the
11985 : * final carry-propagation phase, if necessary.
11986 : */
11987 2355716 : if (val->weight >= accum_weight)
11988 : {
11989 262236 : accum_weight = val->weight + 1;
11990 262236 : accum_ndigits = accum_ndigits + (accum_weight - old_weight);
11991 : }
11992 :
11993 : /*
11994 : * Even though the new value is small, we might've used up the space
11995 : * reserved for the carry digit in the last call to accum_sum_carry(). If
11996 : * so, enlarge to make room for another one.
11997 : */
11998 2093480 : else if (!accum->have_carry_space)
11999 : {
12000 66 : accum_weight++;
12001 66 : accum_ndigits++;
12002 : }
12003 :
12004 : /* Is the new value wider on the right side? */
12005 2355716 : accum_rscale = accum_ndigits - accum_weight - 1;
12006 2355716 : val_rscale = val->ndigits - val->weight - 1;
12007 2355716 : if (val_rscale > accum_rscale)
12008 172258 : accum_ndigits = accum_ndigits + (val_rscale - accum_rscale);
12009 :
12010 2355716 : if (accum_ndigits != old_ndigits ||
12011 : accum_weight != old_weight)
12012 : {
12013 : int32 *new_pos_digits;
12014 : int32 *new_neg_digits;
12015 : int weightdiff;
12016 :
12017 262572 : weightdiff = accum_weight - old_weight;
12018 :
12019 262572 : new_pos_digits = palloc0(accum_ndigits * sizeof(int32));
12020 262572 : new_neg_digits = palloc0(accum_ndigits * sizeof(int32));
12021 :
12022 262572 : if (accum->pos_digits)
12023 : {
12024 90384 : memcpy(&new_pos_digits[weightdiff], accum->pos_digits,
12025 : old_ndigits * sizeof(int32));
12026 90384 : pfree(accum->pos_digits);
12027 :
12028 90384 : memcpy(&new_neg_digits[weightdiff], accum->neg_digits,
12029 : old_ndigits * sizeof(int32));
12030 90384 : pfree(accum->neg_digits);
12031 : }
12032 :
12033 262572 : accum->pos_digits = new_pos_digits;
12034 262572 : accum->neg_digits = new_neg_digits;
12035 :
12036 262572 : accum->weight = accum_weight;
12037 262572 : accum->ndigits = accum_ndigits;
12038 :
12039 : Assert(accum->pos_digits[0] == 0 && accum->neg_digits[0] == 0);
12040 262572 : accum->have_carry_space = true;
12041 : }
12042 :
12043 2355716 : if (val->dscale > accum->dscale)
12044 300 : accum->dscale = val->dscale;
12045 2355716 : }
12046 :
12047 : /*
12048 : * Return the current value of the accumulator. This perform final carry
12049 : * propagation, and adds together the positive and negative sums.
12050 : *
12051 : * Unlike all the other routines, the caller is not required to switch to
12052 : * the memory context that holds the accumulator.
12053 : */
12054 : static void
12055 172614 : accum_sum_final(NumericSumAccum *accum, NumericVar *result)
12056 : {
12057 : int i;
12058 : NumericVar pos_var;
12059 : NumericVar neg_var;
12060 :
12061 172614 : if (accum->ndigits == 0)
12062 : {
12063 0 : set_var_from_var(&const_zero, result);
12064 0 : return;
12065 : }
12066 :
12067 : /* Perform final carry */
12068 172614 : accum_sum_carry(accum);
12069 :
12070 : /* Create NumericVars representing the positive and negative sums */
12071 172614 : init_var(&pos_var);
12072 172614 : init_var(&neg_var);
12073 :
12074 172614 : pos_var.ndigits = neg_var.ndigits = accum->ndigits;
12075 172614 : pos_var.weight = neg_var.weight = accum->weight;
12076 172614 : pos_var.dscale = neg_var.dscale = accum->dscale;
12077 172614 : pos_var.sign = NUMERIC_POS;
12078 172614 : neg_var.sign = NUMERIC_NEG;
12079 :
12080 172614 : pos_var.buf = pos_var.digits = digitbuf_alloc(accum->ndigits);
12081 172614 : neg_var.buf = neg_var.digits = digitbuf_alloc(accum->ndigits);
12082 :
12083 2605124 : for (i = 0; i < accum->ndigits; i++)
12084 : {
12085 : Assert(accum->pos_digits[i] < NBASE);
12086 2432510 : pos_var.digits[i] = (int16) accum->pos_digits[i];
12087 :
12088 : Assert(accum->neg_digits[i] < NBASE);
12089 2432510 : neg_var.digits[i] = (int16) accum->neg_digits[i];
12090 : }
12091 :
12092 : /* And add them together */
12093 172614 : add_var(&pos_var, &neg_var, result);
12094 :
12095 : /* Remove leading/trailing zeroes */
12096 172614 : strip_var(result);
12097 : }
12098 :
12099 : /*
12100 : * Copy an accumulator's state.
12101 : *
12102 : * 'dst' is assumed to be uninitialized beforehand. No attempt is made at
12103 : * freeing old values.
12104 : */
12105 : static void
12106 42 : accum_sum_copy(NumericSumAccum *dst, NumericSumAccum *src)
12107 : {
12108 42 : dst->pos_digits = palloc(src->ndigits * sizeof(int32));
12109 42 : dst->neg_digits = palloc(src->ndigits * sizeof(int32));
12110 :
12111 42 : memcpy(dst->pos_digits, src->pos_digits, src->ndigits * sizeof(int32));
12112 42 : memcpy(dst->neg_digits, src->neg_digits, src->ndigits * sizeof(int32));
12113 42 : dst->num_uncarried = src->num_uncarried;
12114 42 : dst->ndigits = src->ndigits;
12115 42 : dst->weight = src->weight;
12116 42 : dst->dscale = src->dscale;
12117 42 : }
12118 :
12119 : /*
12120 : * Add the current value of 'accum2' into 'accum'.
12121 : */
12122 : static void
12123 54 : accum_sum_combine(NumericSumAccum *accum, NumericSumAccum *accum2)
12124 : {
12125 : NumericVar tmp_var;
12126 :
12127 54 : init_var(&tmp_var);
12128 :
12129 54 : accum_sum_final(accum2, &tmp_var);
12130 54 : accum_sum_add(accum, &tmp_var);
12131 :
12132 54 : free_var(&tmp_var);
12133 54 : }
|