Line data Source code
1 : /*-------------------------------------------------------------------------
2 : *
3 : * numeric.c
4 : * An exact numeric data type for the Postgres database system
5 : *
6 : * Original coding 1998, Jan Wieck. Heavily revised 2003, Tom Lane.
7 : *
8 : * Many of the algorithmic ideas are borrowed from David M. Smith's "FM"
9 : * multiple-precision math library, most recently published as Algorithm
10 : * 786: Multiple-Precision Complex Arithmetic and Functions, ACM
11 : * Transactions on Mathematical Software, Vol. 24, No. 4, December 1998,
12 : * pages 359-367.
13 : *
14 : * Copyright (c) 1998-2024, PostgreSQL Global Development Group
15 : *
16 : * IDENTIFICATION
17 : * src/backend/utils/adt/numeric.c
18 : *
19 : *-------------------------------------------------------------------------
20 : */
21 :
22 : #include "postgres.h"
23 :
24 : #include <ctype.h>
25 : #include <float.h>
26 : #include <limits.h>
27 : #include <math.h>
28 :
29 : #include "common/hashfn.h"
30 : #include "common/int.h"
31 : #include "funcapi.h"
32 : #include "lib/hyperloglog.h"
33 : #include "libpq/pqformat.h"
34 : #include "miscadmin.h"
35 : #include "nodes/nodeFuncs.h"
36 : #include "nodes/supportnodes.h"
37 : #include "utils/array.h"
38 : #include "utils/builtins.h"
39 : #include "utils/float.h"
40 : #include "utils/guc.h"
41 : #include "utils/numeric.h"
42 : #include "utils/pg_lsn.h"
43 : #include "utils/sortsupport.h"
44 :
45 : /* ----------
46 : * Uncomment the following to enable compilation of dump_numeric()
47 : * and dump_var() and to get a dump of any result produced by make_result().
48 : * ----------
49 : #define NUMERIC_DEBUG
50 : */
51 :
52 :
53 : /* ----------
54 : * Local data types
55 : *
56 : * Numeric values are represented in a base-NBASE floating point format.
57 : * Each "digit" ranges from 0 to NBASE-1. The type NumericDigit is signed
58 : * and wide enough to store a digit. We assume that NBASE*NBASE can fit in
59 : * an int. Although the purely calculational routines could handle any even
60 : * NBASE that's less than sqrt(INT_MAX), in practice we are only interested
61 : * in NBASE a power of ten, so that I/O conversions and decimal rounding
62 : * are easy. Also, it's actually more efficient if NBASE is rather less than
63 : * sqrt(INT_MAX), so that there is "headroom" for mul_var and div_var_fast to
64 : * postpone processing carries.
65 : *
66 : * Values of NBASE other than 10000 are considered of historical interest only
67 : * and are no longer supported in any sense; no mechanism exists for the client
68 : * to discover the base, so every client supporting binary mode expects the
69 : * base-10000 format. If you plan to change this, also note the numeric
70 : * abbreviation code, which assumes NBASE=10000.
71 : * ----------
72 : */
73 :
74 : #if 0
75 : #define NBASE 10
76 : #define HALF_NBASE 5
77 : #define DEC_DIGITS 1 /* decimal digits per NBASE digit */
78 : #define MUL_GUARD_DIGITS 4 /* these are measured in NBASE digits */
79 : #define DIV_GUARD_DIGITS 8
80 :
81 : typedef signed char NumericDigit;
82 : #endif
83 :
84 : #if 0
85 : #define NBASE 100
86 : #define HALF_NBASE 50
87 : #define DEC_DIGITS 2 /* decimal digits per NBASE digit */
88 : #define MUL_GUARD_DIGITS 3 /* these are measured in NBASE digits */
89 : #define DIV_GUARD_DIGITS 6
90 :
91 : typedef signed char NumericDigit;
92 : #endif
93 :
94 : #if 1
95 : #define NBASE 10000
96 : #define HALF_NBASE 5000
97 : #define DEC_DIGITS 4 /* decimal digits per NBASE digit */
98 : #define MUL_GUARD_DIGITS 2 /* these are measured in NBASE digits */
99 : #define DIV_GUARD_DIGITS 4
100 :
101 : typedef int16 NumericDigit;
102 : #endif
103 :
104 : #define NBASE_SQR (NBASE * NBASE)
105 :
106 : /*
107 : * The Numeric type as stored on disk.
108 : *
109 : * If the high bits of the first word of a NumericChoice (n_header, or
110 : * n_short.n_header, or n_long.n_sign_dscale) are NUMERIC_SHORT, then the
111 : * numeric follows the NumericShort format; if they are NUMERIC_POS or
112 : * NUMERIC_NEG, it follows the NumericLong format. If they are NUMERIC_SPECIAL,
113 : * the value is a NaN or Infinity. We currently always store SPECIAL values
114 : * using just two bytes (i.e. only n_header), but previous releases used only
115 : * the NumericLong format, so we might find 4-byte NaNs (though not infinities)
116 : * on disk if a database has been migrated using pg_upgrade. In either case,
117 : * the low-order bits of a special value's header are reserved and currently
118 : * should always be set to zero.
119 : *
120 : * In the NumericShort format, the remaining 14 bits of the header word
121 : * (n_short.n_header) are allocated as follows: 1 for sign (positive or
122 : * negative), 6 for dynamic scale, and 7 for weight. In practice, most
123 : * commonly-encountered values can be represented this way.
124 : *
125 : * In the NumericLong format, the remaining 14 bits of the header word
126 : * (n_long.n_sign_dscale) represent the display scale; and the weight is
127 : * stored separately in n_weight.
128 : *
129 : * NOTE: by convention, values in the packed form have been stripped of
130 : * all leading and trailing zero digits (where a "digit" is of base NBASE).
131 : * In particular, if the value is zero, there will be no digits at all!
132 : * The weight is arbitrary in that case, but we normally set it to zero.
133 : */
134 :
135 : struct NumericShort
136 : {
137 : uint16 n_header; /* Sign + display scale + weight */
138 : NumericDigit n_data[FLEXIBLE_ARRAY_MEMBER]; /* Digits */
139 : };
140 :
141 : struct NumericLong
142 : {
143 : uint16 n_sign_dscale; /* Sign + display scale */
144 : int16 n_weight; /* Weight of 1st digit */
145 : NumericDigit n_data[FLEXIBLE_ARRAY_MEMBER]; /* Digits */
146 : };
147 :
148 : union NumericChoice
149 : {
150 : uint16 n_header; /* Header word */
151 : struct NumericLong n_long; /* Long form (4-byte header) */
152 : struct NumericShort n_short; /* Short form (2-byte header) */
153 : };
154 :
155 : struct NumericData
156 : {
157 : int32 vl_len_; /* varlena header (do not touch directly!) */
158 : union NumericChoice choice; /* choice of format */
159 : };
160 :
161 :
162 : /*
163 : * Interpretation of high bits.
164 : */
165 :
166 : #define NUMERIC_SIGN_MASK 0xC000
167 : #define NUMERIC_POS 0x0000
168 : #define NUMERIC_NEG 0x4000
169 : #define NUMERIC_SHORT 0x8000
170 : #define NUMERIC_SPECIAL 0xC000
171 :
172 : #define NUMERIC_FLAGBITS(n) ((n)->choice.n_header & NUMERIC_SIGN_MASK)
173 : #define NUMERIC_IS_SHORT(n) (NUMERIC_FLAGBITS(n) == NUMERIC_SHORT)
174 : #define NUMERIC_IS_SPECIAL(n) (NUMERIC_FLAGBITS(n) == NUMERIC_SPECIAL)
175 :
176 : #define NUMERIC_HDRSZ (VARHDRSZ + sizeof(uint16) + sizeof(int16))
177 : #define NUMERIC_HDRSZ_SHORT (VARHDRSZ + sizeof(uint16))
178 :
179 : /*
180 : * If the flag bits are NUMERIC_SHORT or NUMERIC_SPECIAL, we want the short
181 : * header; otherwise, we want the long one. Instead of testing against each
182 : * value, we can just look at the high bit, for a slight efficiency gain.
183 : */
184 : #define NUMERIC_HEADER_IS_SHORT(n) (((n)->choice.n_header & 0x8000) != 0)
185 : #define NUMERIC_HEADER_SIZE(n) \
186 : (VARHDRSZ + sizeof(uint16) + \
187 : (NUMERIC_HEADER_IS_SHORT(n) ? 0 : sizeof(int16)))
188 :
189 : /*
190 : * Definitions for special values (NaN, positive infinity, negative infinity).
191 : *
192 : * The two bits after the NUMERIC_SPECIAL bits are 00 for NaN, 01 for positive
193 : * infinity, 11 for negative infinity. (This makes the sign bit match where
194 : * it is in a short-format value, though we make no use of that at present.)
195 : * We could mask off the remaining bits before testing the active bits, but
196 : * currently those bits must be zeroes, so masking would just add cycles.
197 : */
198 : #define NUMERIC_EXT_SIGN_MASK 0xF000 /* high bits plus NaN/Inf flag bits */
199 : #define NUMERIC_NAN 0xC000
200 : #define NUMERIC_PINF 0xD000
201 : #define NUMERIC_NINF 0xF000
202 : #define NUMERIC_INF_SIGN_MASK 0x2000
203 :
204 : #define NUMERIC_EXT_FLAGBITS(n) ((n)->choice.n_header & NUMERIC_EXT_SIGN_MASK)
205 : #define NUMERIC_IS_NAN(n) ((n)->choice.n_header == NUMERIC_NAN)
206 : #define NUMERIC_IS_PINF(n) ((n)->choice.n_header == NUMERIC_PINF)
207 : #define NUMERIC_IS_NINF(n) ((n)->choice.n_header == NUMERIC_NINF)
208 : #define NUMERIC_IS_INF(n) \
209 : (((n)->choice.n_header & ~NUMERIC_INF_SIGN_MASK) == NUMERIC_PINF)
210 :
211 : /*
212 : * Short format definitions.
213 : */
214 :
215 : #define NUMERIC_SHORT_SIGN_MASK 0x2000
216 : #define NUMERIC_SHORT_DSCALE_MASK 0x1F80
217 : #define NUMERIC_SHORT_DSCALE_SHIFT 7
218 : #define NUMERIC_SHORT_DSCALE_MAX \
219 : (NUMERIC_SHORT_DSCALE_MASK >> NUMERIC_SHORT_DSCALE_SHIFT)
220 : #define NUMERIC_SHORT_WEIGHT_SIGN_MASK 0x0040
221 : #define NUMERIC_SHORT_WEIGHT_MASK 0x003F
222 : #define NUMERIC_SHORT_WEIGHT_MAX NUMERIC_SHORT_WEIGHT_MASK
223 : #define NUMERIC_SHORT_WEIGHT_MIN (-(NUMERIC_SHORT_WEIGHT_MASK+1))
224 :
225 : /*
226 : * Extract sign, display scale, weight. These macros extract field values
227 : * suitable for the NumericVar format from the Numeric (on-disk) format.
228 : *
229 : * Note that we don't trouble to ensure that dscale and weight read as zero
230 : * for an infinity; however, that doesn't matter since we never convert
231 : * "special" numerics to NumericVar form. Only the constants defined below
232 : * (const_nan, etc) ever represent a non-finite value as a NumericVar.
233 : */
234 :
235 : #define NUMERIC_DSCALE_MASK 0x3FFF
236 : #define NUMERIC_DSCALE_MAX NUMERIC_DSCALE_MASK
237 :
238 : #define NUMERIC_SIGN(n) \
239 : (NUMERIC_IS_SHORT(n) ? \
240 : (((n)->choice.n_short.n_header & NUMERIC_SHORT_SIGN_MASK) ? \
241 : NUMERIC_NEG : NUMERIC_POS) : \
242 : (NUMERIC_IS_SPECIAL(n) ? \
243 : NUMERIC_EXT_FLAGBITS(n) : NUMERIC_FLAGBITS(n)))
244 : #define NUMERIC_DSCALE(n) (NUMERIC_HEADER_IS_SHORT((n)) ? \
245 : ((n)->choice.n_short.n_header & NUMERIC_SHORT_DSCALE_MASK) \
246 : >> NUMERIC_SHORT_DSCALE_SHIFT \
247 : : ((n)->choice.n_long.n_sign_dscale & NUMERIC_DSCALE_MASK))
248 : #define NUMERIC_WEIGHT(n) (NUMERIC_HEADER_IS_SHORT((n)) ? \
249 : (((n)->choice.n_short.n_header & NUMERIC_SHORT_WEIGHT_SIGN_MASK ? \
250 : ~NUMERIC_SHORT_WEIGHT_MASK : 0) \
251 : | ((n)->choice.n_short.n_header & NUMERIC_SHORT_WEIGHT_MASK)) \
252 : : ((n)->choice.n_long.n_weight))
253 :
254 : /*
255 : * Maximum weight of a stored Numeric value (based on the use of int16 for the
256 : * weight in NumericLong). Note that intermediate values held in NumericVar
257 : * and NumericSumAccum variables may have much larger weights.
258 : */
259 : #define NUMERIC_WEIGHT_MAX PG_INT16_MAX
260 :
261 : /* ----------
262 : * NumericVar is the format we use for arithmetic. The digit-array part
263 : * is the same as the NumericData storage format, but the header is more
264 : * complex.
265 : *
266 : * The value represented by a NumericVar is determined by the sign, weight,
267 : * ndigits, and digits[] array. If it is a "special" value (NaN or Inf)
268 : * then only the sign field matters; ndigits should be zero, and the weight
269 : * and dscale fields are ignored.
270 : *
271 : * Note: the first digit of a NumericVar's value is assumed to be multiplied
272 : * by NBASE ** weight. Another way to say it is that there are weight+1
273 : * digits before the decimal point. It is possible to have weight < 0.
274 : *
275 : * buf points at the physical start of the palloc'd digit buffer for the
276 : * NumericVar. digits points at the first digit in actual use (the one
277 : * with the specified weight). We normally leave an unused digit or two
278 : * (preset to zeroes) between buf and digits, so that there is room to store
279 : * a carry out of the top digit without reallocating space. We just need to
280 : * decrement digits (and increment weight) to make room for the carry digit.
281 : * (There is no such extra space in a numeric value stored in the database,
282 : * only in a NumericVar in memory.)
283 : *
284 : * If buf is NULL then the digit buffer isn't actually palloc'd and should
285 : * not be freed --- see the constants below for an example.
286 : *
287 : * dscale, or display scale, is the nominal precision expressed as number
288 : * of digits after the decimal point (it must always be >= 0 at present).
289 : * dscale may be more than the number of physically stored fractional digits,
290 : * implying that we have suppressed storage of significant trailing zeroes.
291 : * It should never be less than the number of stored digits, since that would
292 : * imply hiding digits that are present. NOTE that dscale is always expressed
293 : * in *decimal* digits, and so it may correspond to a fractional number of
294 : * base-NBASE digits --- divide by DEC_DIGITS to convert to NBASE digits.
295 : *
296 : * rscale, or result scale, is the target precision for a computation.
297 : * Like dscale it is expressed as number of *decimal* digits after the decimal
298 : * point, and is always >= 0 at present.
299 : * Note that rscale is not stored in variables --- it's figured on-the-fly
300 : * from the dscales of the inputs.
301 : *
302 : * While we consistently use "weight" to refer to the base-NBASE weight of
303 : * a numeric value, it is convenient in some scale-related calculations to
304 : * make use of the base-10 weight (ie, the approximate log10 of the value).
305 : * To avoid confusion, such a decimal-units weight is called a "dweight".
306 : *
307 : * NB: All the variable-level functions are written in a style that makes it
308 : * possible to give one and the same variable as argument and destination.
309 : * This is feasible because the digit buffer is separate from the variable.
310 : * ----------
311 : */
312 : typedef struct NumericVar
313 : {
314 : int ndigits; /* # of digits in digits[] - can be 0! */
315 : int weight; /* weight of first digit */
316 : int sign; /* NUMERIC_POS, _NEG, _NAN, _PINF, or _NINF */
317 : int dscale; /* display scale */
318 : NumericDigit *buf; /* start of palloc'd space for digits[] */
319 : NumericDigit *digits; /* base-NBASE digits */
320 : } NumericVar;
321 :
322 :
323 : /* ----------
324 : * Data for generate_series
325 : * ----------
326 : */
327 : typedef struct
328 : {
329 : NumericVar current;
330 : NumericVar stop;
331 : NumericVar step;
332 : } generate_series_numeric_fctx;
333 :
334 :
335 : /* ----------
336 : * Sort support.
337 : * ----------
338 : */
339 : typedef struct
340 : {
341 : void *buf; /* buffer for short varlenas */
342 : int64 input_count; /* number of non-null values seen */
343 : bool estimating; /* true if estimating cardinality */
344 :
345 : hyperLogLogState abbr_card; /* cardinality estimator */
346 : } NumericSortSupport;
347 :
348 :
349 : /* ----------
350 : * Fast sum accumulator.
351 : *
352 : * NumericSumAccum is used to implement SUM(), and other standard aggregates
353 : * that track the sum of input values. It uses 32-bit integers to store the
354 : * digits, instead of the normal 16-bit integers (with NBASE=10000). This
355 : * way, we can safely accumulate up to NBASE - 1 values without propagating
356 : * carry, before risking overflow of any of the digits. 'num_uncarried'
357 : * tracks how many values have been accumulated without propagating carry.
358 : *
359 : * Positive and negative values are accumulated separately, in 'pos_digits'
360 : * and 'neg_digits'. This is simpler and faster than deciding whether to add
361 : * or subtract from the current value, for each new value (see sub_var() for
362 : * the logic we avoid by doing this). Both buffers are of same size, and
363 : * have the same weight and scale. In accum_sum_final(), the positive and
364 : * negative sums are added together to produce the final result.
365 : *
366 : * When a new value has a larger ndigits or weight than the accumulator
367 : * currently does, the accumulator is enlarged to accommodate the new value.
368 : * We normally have one zero digit reserved for carry propagation, and that
369 : * is indicated by the 'have_carry_space' flag. When accum_sum_carry() uses
370 : * up the reserved digit, it clears the 'have_carry_space' flag. The next
371 : * call to accum_sum_add() will enlarge the buffer, to make room for the
372 : * extra digit, and set the flag again.
373 : *
374 : * To initialize a new accumulator, simply reset all fields to zeros.
375 : *
376 : * The accumulator does not handle NaNs.
377 : * ----------
378 : */
379 : typedef struct NumericSumAccum
380 : {
381 : int ndigits;
382 : int weight;
383 : int dscale;
384 : int num_uncarried;
385 : bool have_carry_space;
386 : int32 *pos_digits;
387 : int32 *neg_digits;
388 : } NumericSumAccum;
389 :
390 :
391 : /*
392 : * We define our own macros for packing and unpacking abbreviated-key
393 : * representations for numeric values in order to avoid depending on
394 : * USE_FLOAT8_BYVAL. The type of abbreviation we use is based only on
395 : * the size of a datum, not the argument-passing convention for float8.
396 : *
397 : * The range of abbreviations for finite values is from +PG_INT64/32_MAX
398 : * to -PG_INT64/32_MAX. NaN has the abbreviation PG_INT64/32_MIN, and we
399 : * define the sort ordering to make that work out properly (see further
400 : * comments below). PINF and NINF share the abbreviations of the largest
401 : * and smallest finite abbreviation classes.
402 : */
403 : #define NUMERIC_ABBREV_BITS (SIZEOF_DATUM * BITS_PER_BYTE)
404 : #if SIZEOF_DATUM == 8
405 : #define NumericAbbrevGetDatum(X) ((Datum) (X))
406 : #define DatumGetNumericAbbrev(X) ((int64) (X))
407 : #define NUMERIC_ABBREV_NAN NumericAbbrevGetDatum(PG_INT64_MIN)
408 : #define NUMERIC_ABBREV_PINF NumericAbbrevGetDatum(-PG_INT64_MAX)
409 : #define NUMERIC_ABBREV_NINF NumericAbbrevGetDatum(PG_INT64_MAX)
410 : #else
411 : #define NumericAbbrevGetDatum(X) ((Datum) (X))
412 : #define DatumGetNumericAbbrev(X) ((int32) (X))
413 : #define NUMERIC_ABBREV_NAN NumericAbbrevGetDatum(PG_INT32_MIN)
414 : #define NUMERIC_ABBREV_PINF NumericAbbrevGetDatum(-PG_INT32_MAX)
415 : #define NUMERIC_ABBREV_NINF NumericAbbrevGetDatum(PG_INT32_MAX)
416 : #endif
417 :
418 :
419 : /* ----------
420 : * Some preinitialized constants
421 : * ----------
422 : */
423 : static const NumericDigit const_zero_data[1] = {0};
424 : static const NumericVar const_zero =
425 : {0, 0, NUMERIC_POS, 0, NULL, (NumericDigit *) const_zero_data};
426 :
427 : static const NumericDigit const_one_data[1] = {1};
428 : static const NumericVar const_one =
429 : {1, 0, NUMERIC_POS, 0, NULL, (NumericDigit *) const_one_data};
430 :
431 : static const NumericVar const_minus_one =
432 : {1, 0, NUMERIC_NEG, 0, NULL, (NumericDigit *) const_one_data};
433 :
434 : static const NumericDigit const_two_data[1] = {2};
435 : static const NumericVar const_two =
436 : {1, 0, NUMERIC_POS, 0, NULL, (NumericDigit *) const_two_data};
437 :
438 : #if DEC_DIGITS == 4
439 : static const NumericDigit const_zero_point_nine_data[1] = {9000};
440 : #elif DEC_DIGITS == 2
441 : static const NumericDigit const_zero_point_nine_data[1] = {90};
442 : #elif DEC_DIGITS == 1
443 : static const NumericDigit const_zero_point_nine_data[1] = {9};
444 : #endif
445 : static const NumericVar const_zero_point_nine =
446 : {1, -1, NUMERIC_POS, 1, NULL, (NumericDigit *) const_zero_point_nine_data};
447 :
448 : #if DEC_DIGITS == 4
449 : static const NumericDigit const_one_point_one_data[2] = {1, 1000};
450 : #elif DEC_DIGITS == 2
451 : static const NumericDigit const_one_point_one_data[2] = {1, 10};
452 : #elif DEC_DIGITS == 1
453 : static const NumericDigit const_one_point_one_data[2] = {1, 1};
454 : #endif
455 : static const NumericVar const_one_point_one =
456 : {2, 0, NUMERIC_POS, 1, NULL, (NumericDigit *) const_one_point_one_data};
457 :
458 : static const NumericVar const_nan =
459 : {0, 0, NUMERIC_NAN, 0, NULL, NULL};
460 :
461 : static const NumericVar const_pinf =
462 : {0, 0, NUMERIC_PINF, 0, NULL, NULL};
463 :
464 : static const NumericVar const_ninf =
465 : {0, 0, NUMERIC_NINF, 0, NULL, NULL};
466 :
467 : #if DEC_DIGITS == 4
468 : static const int round_powers[4] = {0, 1000, 100, 10};
469 : #endif
470 :
471 :
472 : /* ----------
473 : * Local functions
474 : * ----------
475 : */
476 :
477 : #ifdef NUMERIC_DEBUG
478 : static void dump_numeric(const char *str, Numeric num);
479 : static void dump_var(const char *str, NumericVar *var);
480 : #else
481 : #define dump_numeric(s,n)
482 : #define dump_var(s,v)
483 : #endif
484 :
485 : #define digitbuf_alloc(ndigits) \
486 : ((NumericDigit *) palloc((ndigits) * sizeof(NumericDigit)))
487 : #define digitbuf_free(buf) \
488 : do { \
489 : if ((buf) != NULL) \
490 : pfree(buf); \
491 : } while (0)
492 :
493 : #define init_var(v) memset(v, 0, sizeof(NumericVar))
494 :
495 : #define NUMERIC_DIGITS(num) (NUMERIC_HEADER_IS_SHORT(num) ? \
496 : (num)->choice.n_short.n_data : (num)->choice.n_long.n_data)
497 : #define NUMERIC_NDIGITS(num) \
498 : ((VARSIZE(num) - NUMERIC_HEADER_SIZE(num)) / sizeof(NumericDigit))
499 : #define NUMERIC_CAN_BE_SHORT(scale,weight) \
500 : ((scale) <= NUMERIC_SHORT_DSCALE_MAX && \
501 : (weight) <= NUMERIC_SHORT_WEIGHT_MAX && \
502 : (weight) >= NUMERIC_SHORT_WEIGHT_MIN)
503 :
504 : static void alloc_var(NumericVar *var, int ndigits);
505 : static void free_var(NumericVar *var);
506 : static void zero_var(NumericVar *var);
507 :
508 : static bool set_var_from_str(const char *str, const char *cp,
509 : NumericVar *dest, const char **endptr,
510 : Node *escontext);
511 : static bool set_var_from_non_decimal_integer_str(const char *str,
512 : const char *cp, int sign,
513 : int base, NumericVar *dest,
514 : const char **endptr,
515 : Node *escontext);
516 : static void set_var_from_num(Numeric num, NumericVar *dest);
517 : static void init_var_from_num(Numeric num, NumericVar *dest);
518 : static void set_var_from_var(const NumericVar *value, NumericVar *dest);
519 : static char *get_str_from_var(const NumericVar *var);
520 : static char *get_str_from_var_sci(const NumericVar *var, int rscale);
521 :
522 : static void numericvar_serialize(StringInfo buf, const NumericVar *var);
523 : static void numericvar_deserialize(StringInfo buf, NumericVar *var);
524 :
525 : static Numeric duplicate_numeric(Numeric num);
526 : static Numeric make_result(const NumericVar *var);
527 : static Numeric make_result_opt_error(const NumericVar *var, bool *have_error);
528 :
529 : static bool apply_typmod(NumericVar *var, int32 typmod, Node *escontext);
530 : static bool apply_typmod_special(Numeric num, int32 typmod, Node *escontext);
531 :
532 : static bool numericvar_to_int32(const NumericVar *var, int32 *result);
533 : static bool numericvar_to_int64(const NumericVar *var, int64 *result);
534 : static void int64_to_numericvar(int64 val, NumericVar *var);
535 : static bool numericvar_to_uint64(const NumericVar *var, uint64 *result);
536 : #ifdef HAVE_INT128
537 : static bool numericvar_to_int128(const NumericVar *var, int128 *result);
538 : static void int128_to_numericvar(int128 val, NumericVar *var);
539 : #endif
540 : static double numericvar_to_double_no_overflow(const NumericVar *var);
541 :
542 : static Datum numeric_abbrev_convert(Datum original_datum, SortSupport ssup);
543 : static bool numeric_abbrev_abort(int memtupcount, SortSupport ssup);
544 : static int numeric_fast_cmp(Datum x, Datum y, SortSupport ssup);
545 : static int numeric_cmp_abbrev(Datum x, Datum y, SortSupport ssup);
546 :
547 : static Datum numeric_abbrev_convert_var(const NumericVar *var,
548 : NumericSortSupport *nss);
549 :
550 : static int cmp_numerics(Numeric num1, Numeric num2);
551 : static int cmp_var(const NumericVar *var1, const NumericVar *var2);
552 : static int cmp_var_common(const NumericDigit *var1digits, int var1ndigits,
553 : int var1weight, int var1sign,
554 : const NumericDigit *var2digits, int var2ndigits,
555 : int var2weight, int var2sign);
556 : static void add_var(const NumericVar *var1, const NumericVar *var2,
557 : NumericVar *result);
558 : static void sub_var(const NumericVar *var1, const NumericVar *var2,
559 : NumericVar *result);
560 : static void mul_var(const NumericVar *var1, const NumericVar *var2,
561 : NumericVar *result,
562 : int rscale);
563 : static void mul_var_short(const NumericVar *var1, const NumericVar *var2,
564 : NumericVar *result);
565 : static void div_var(const NumericVar *var1, const NumericVar *var2,
566 : NumericVar *result,
567 : int rscale, bool round);
568 : static void div_var_fast(const NumericVar *var1, const NumericVar *var2,
569 : NumericVar *result, int rscale, bool round);
570 : static void div_var_int(const NumericVar *var, int ival, int ival_weight,
571 : NumericVar *result, int rscale, bool round);
572 : #ifdef HAVE_INT128
573 : static void div_var_int64(const NumericVar *var, int64 ival, int ival_weight,
574 : NumericVar *result, int rscale, bool round);
575 : #endif
576 : static int select_div_scale(const NumericVar *var1, const NumericVar *var2);
577 : static void mod_var(const NumericVar *var1, const NumericVar *var2,
578 : NumericVar *result);
579 : static void div_mod_var(const NumericVar *var1, const NumericVar *var2,
580 : NumericVar *quot, NumericVar *rem);
581 : static void ceil_var(const NumericVar *var, NumericVar *result);
582 : static void floor_var(const NumericVar *var, NumericVar *result);
583 :
584 : static void gcd_var(const NumericVar *var1, const NumericVar *var2,
585 : NumericVar *result);
586 : static void sqrt_var(const NumericVar *arg, NumericVar *result, int rscale);
587 : static void exp_var(const NumericVar *arg, NumericVar *result, int rscale);
588 : static int estimate_ln_dweight(const NumericVar *var);
589 : static void ln_var(const NumericVar *arg, NumericVar *result, int rscale);
590 : static void log_var(const NumericVar *base, const NumericVar *num,
591 : NumericVar *result);
592 : static void power_var(const NumericVar *base, const NumericVar *exp,
593 : NumericVar *result);
594 : static void power_var_int(const NumericVar *base, int exp, int exp_dscale,
595 : NumericVar *result);
596 : static void power_ten_int(int exp, NumericVar *result);
597 : static void random_var(pg_prng_state *state, const NumericVar *rmin,
598 : const NumericVar *rmax, NumericVar *result);
599 :
600 : static int cmp_abs(const NumericVar *var1, const NumericVar *var2);
601 : static int cmp_abs_common(const NumericDigit *var1digits, int var1ndigits,
602 : int var1weight,
603 : const NumericDigit *var2digits, int var2ndigits,
604 : int var2weight);
605 : static void add_abs(const NumericVar *var1, const NumericVar *var2,
606 : NumericVar *result);
607 : static void sub_abs(const NumericVar *var1, const NumericVar *var2,
608 : NumericVar *result);
609 : static void round_var(NumericVar *var, int rscale);
610 : static void trunc_var(NumericVar *var, int rscale);
611 : static void strip_var(NumericVar *var);
612 : static void compute_bucket(Numeric operand, Numeric bound1, Numeric bound2,
613 : const NumericVar *count_var,
614 : NumericVar *result_var);
615 :
616 : static void accum_sum_add(NumericSumAccum *accum, const NumericVar *val);
617 : static void accum_sum_rescale(NumericSumAccum *accum, const NumericVar *val);
618 : static void accum_sum_carry(NumericSumAccum *accum);
619 : static void accum_sum_reset(NumericSumAccum *accum);
620 : static void accum_sum_final(NumericSumAccum *accum, NumericVar *result);
621 : static void accum_sum_copy(NumericSumAccum *dst, NumericSumAccum *src);
622 : static void accum_sum_combine(NumericSumAccum *accum, NumericSumAccum *accum2);
623 :
624 :
625 : /* ----------------------------------------------------------------------
626 : *
627 : * Input-, output- and rounding-functions
628 : *
629 : * ----------------------------------------------------------------------
630 : */
631 :
632 :
633 : /*
634 : * numeric_in() -
635 : *
636 : * Input function for numeric data type
637 : */
638 : Datum
639 106834 : numeric_in(PG_FUNCTION_ARGS)
640 : {
641 106834 : char *str = PG_GETARG_CSTRING(0);
642 : #ifdef NOT_USED
643 : Oid typelem = PG_GETARG_OID(1);
644 : #endif
645 106834 : int32 typmod = PG_GETARG_INT32(2);
646 106834 : Node *escontext = fcinfo->context;
647 : Numeric res;
648 : const char *cp;
649 : const char *numstart;
650 : int sign;
651 :
652 : /* Skip leading spaces */
653 106834 : cp = str;
654 107218 : while (*cp)
655 : {
656 107206 : if (!isspace((unsigned char) *cp))
657 106822 : break;
658 384 : cp++;
659 : }
660 :
661 : /*
662 : * Process the number's sign. This duplicates logic in set_var_from_str(),
663 : * but it's worth doing here, since it simplifies the handling of
664 : * infinities and non-decimal integers.
665 : */
666 106834 : numstart = cp;
667 106834 : sign = NUMERIC_POS;
668 :
669 106834 : if (*cp == '+')
670 48 : cp++;
671 106786 : else if (*cp == '-')
672 : {
673 3720 : sign = NUMERIC_NEG;
674 3720 : cp++;
675 : }
676 :
677 : /*
678 : * Check for NaN and infinities. We recognize the same strings allowed by
679 : * float8in().
680 : *
681 : * Since all other legal inputs have a digit or a decimal point after the
682 : * sign, we need only check for NaN/infinity if that's not the case.
683 : */
684 106834 : if (!isdigit((unsigned char) *cp) && *cp != '.')
685 : {
686 : /*
687 : * The number must be NaN or infinity; anything else can only be a
688 : * syntax error. Note that NaN mustn't have a sign.
689 : */
690 1758 : if (pg_strncasecmp(numstart, "NaN", 3) == 0)
691 : {
692 586 : res = make_result(&const_nan);
693 586 : cp = numstart + 3;
694 : }
695 1172 : else if (pg_strncasecmp(cp, "Infinity", 8) == 0)
696 : {
697 480 : res = make_result(sign == NUMERIC_POS ? &const_pinf : &const_ninf);
698 480 : cp += 8;
699 : }
700 692 : else if (pg_strncasecmp(cp, "inf", 3) == 0)
701 : {
702 588 : res = make_result(sign == NUMERIC_POS ? &const_pinf : &const_ninf);
703 588 : cp += 3;
704 : }
705 : else
706 104 : goto invalid_syntax;
707 :
708 : /*
709 : * Check for trailing junk; there should be nothing left but spaces.
710 : *
711 : * We intentionally do this check before applying the typmod because
712 : * we would like to throw any trailing-junk syntax error before any
713 : * semantic error resulting from apply_typmod_special().
714 : */
715 1696 : while (*cp)
716 : {
717 42 : if (!isspace((unsigned char) *cp))
718 0 : goto invalid_syntax;
719 42 : cp++;
720 : }
721 :
722 1654 : if (!apply_typmod_special(res, typmod, escontext))
723 0 : PG_RETURN_NULL();
724 : }
725 : else
726 : {
727 : /*
728 : * We have a normal numeric value, which may be a non-decimal integer
729 : * or a regular decimal number.
730 : */
731 : NumericVar value;
732 : int base;
733 : bool have_error;
734 :
735 105076 : init_var(&value);
736 :
737 : /*
738 : * Determine the number's base by looking for a non-decimal prefix
739 : * indicator ("0x", "0o", or "0b").
740 : */
741 105076 : if (cp[0] == '0')
742 : {
743 26916 : switch (cp[1])
744 : {
745 72 : case 'x':
746 : case 'X':
747 72 : base = 16;
748 72 : break;
749 42 : case 'o':
750 : case 'O':
751 42 : base = 8;
752 42 : break;
753 42 : case 'b':
754 : case 'B':
755 42 : base = 2;
756 42 : break;
757 26760 : default:
758 26760 : base = 10;
759 : }
760 : }
761 : else
762 78160 : base = 10;
763 :
764 : /* Parse the rest of the number and apply the sign */
765 105076 : if (base == 10)
766 : {
767 104920 : if (!set_var_from_str(str, cp, &value, &cp, escontext))
768 42 : PG_RETURN_NULL();
769 104872 : value.sign = sign;
770 : }
771 : else
772 : {
773 156 : if (!set_var_from_non_decimal_integer_str(str, cp + 2, sign, base,
774 : &value, &cp, escontext))
775 0 : PG_RETURN_NULL();
776 : }
777 :
778 : /*
779 : * Should be nothing left but spaces. As above, throw any typmod error
780 : * after finishing syntax check.
781 : */
782 105088 : while (*cp)
783 : {
784 150 : if (!isspace((unsigned char) *cp))
785 72 : goto invalid_syntax;
786 78 : cp++;
787 : }
788 :
789 104938 : if (!apply_typmod(&value, typmod, escontext))
790 24 : PG_RETURN_NULL();
791 :
792 104914 : res = make_result_opt_error(&value, &have_error);
793 :
794 104914 : if (have_error)
795 18 : ereturn(escontext, (Datum) 0,
796 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
797 : errmsg("value overflows numeric format")));
798 :
799 104896 : free_var(&value);
800 : }
801 :
802 106550 : PG_RETURN_NUMERIC(res);
803 :
804 176 : invalid_syntax:
805 176 : ereturn(escontext, (Datum) 0,
806 : (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
807 : errmsg("invalid input syntax for type %s: \"%s\"",
808 : "numeric", str)));
809 : }
810 :
811 :
812 : /*
813 : * numeric_out() -
814 : *
815 : * Output function for numeric data type
816 : */
817 : Datum
818 788044 : numeric_out(PG_FUNCTION_ARGS)
819 : {
820 788044 : Numeric num = PG_GETARG_NUMERIC(0);
821 : NumericVar x;
822 : char *str;
823 :
824 : /*
825 : * Handle NaN and infinities
826 : */
827 788044 : if (NUMERIC_IS_SPECIAL(num))
828 : {
829 3604 : if (NUMERIC_IS_PINF(num))
830 1040 : PG_RETURN_CSTRING(pstrdup("Infinity"));
831 2564 : else if (NUMERIC_IS_NINF(num))
832 658 : PG_RETURN_CSTRING(pstrdup("-Infinity"));
833 : else
834 1906 : PG_RETURN_CSTRING(pstrdup("NaN"));
835 : }
836 :
837 : /*
838 : * Get the number in the variable format.
839 : */
840 784440 : init_var_from_num(num, &x);
841 :
842 784440 : str = get_str_from_var(&x);
843 :
844 784440 : PG_RETURN_CSTRING(str);
845 : }
846 :
847 : /*
848 : * numeric_is_nan() -
849 : *
850 : * Is Numeric value a NaN?
851 : */
852 : bool
853 14962 : numeric_is_nan(Numeric num)
854 : {
855 14962 : return NUMERIC_IS_NAN(num);
856 : }
857 :
858 : /*
859 : * numeric_is_inf() -
860 : *
861 : * Is Numeric value an infinity?
862 : */
863 : bool
864 312 : numeric_is_inf(Numeric num)
865 : {
866 312 : return NUMERIC_IS_INF(num);
867 : }
868 :
869 : /*
870 : * numeric_is_integral() -
871 : *
872 : * Is Numeric value integral?
873 : */
874 : static bool
875 66 : numeric_is_integral(Numeric num)
876 : {
877 : NumericVar arg;
878 :
879 : /* Reject NaN, but infinities are considered integral */
880 66 : if (NUMERIC_IS_SPECIAL(num))
881 : {
882 30 : if (NUMERIC_IS_NAN(num))
883 0 : return false;
884 30 : return true;
885 : }
886 :
887 : /* Integral if there are no digits to the right of the decimal point */
888 36 : init_var_from_num(num, &arg);
889 :
890 36 : return (arg.ndigits == 0 || arg.ndigits <= arg.weight + 1);
891 : }
892 :
893 : /*
894 : * make_numeric_typmod() -
895 : *
896 : * Pack numeric precision and scale values into a typmod. The upper 16 bits
897 : * are used for the precision (though actually not all these bits are needed,
898 : * since the maximum allowed precision is 1000). The lower 16 bits are for
899 : * the scale, but since the scale is constrained to the range [-1000, 1000],
900 : * we use just the lower 11 of those 16 bits, and leave the remaining 5 bits
901 : * unset, for possible future use.
902 : *
903 : * For purely historical reasons VARHDRSZ is then added to the result, thus
904 : * the unused space in the upper 16 bits is not all as freely available as it
905 : * might seem. (We can't let the result overflow to a negative int32, as
906 : * other parts of the system would interpret that as not-a-valid-typmod.)
907 : */
908 : static inline int32
909 1890 : make_numeric_typmod(int precision, int scale)
910 : {
911 1890 : return ((precision << 16) | (scale & 0x7ff)) + VARHDRSZ;
912 : }
913 :
914 : /*
915 : * Because of the offset, valid numeric typmods are at least VARHDRSZ
916 : */
917 : static inline bool
918 130142 : is_valid_numeric_typmod(int32 typmod)
919 : {
920 130142 : return typmod >= (int32) VARHDRSZ;
921 : }
922 :
923 : /*
924 : * numeric_typmod_precision() -
925 : *
926 : * Extract the precision from a numeric typmod --- see make_numeric_typmod().
927 : */
928 : static inline int
929 24280 : numeric_typmod_precision(int32 typmod)
930 : {
931 24280 : return ((typmod - VARHDRSZ) >> 16) & 0xffff;
932 : }
933 :
934 : /*
935 : * numeric_typmod_scale() -
936 : *
937 : * Extract the scale from a numeric typmod --- see make_numeric_typmod().
938 : *
939 : * Note that the scale may be negative, so we must do sign extension when
940 : * unpacking it. We do this using the bit hack (x^1024)-1024, which sign
941 : * extends an 11-bit two's complement number x.
942 : */
943 : static inline int
944 17122 : numeric_typmod_scale(int32 typmod)
945 : {
946 17122 : return (((typmod - VARHDRSZ) & 0x7ff) ^ 1024) - 1024;
947 : }
948 :
949 : /*
950 : * numeric_maximum_size() -
951 : *
952 : * Maximum size of a numeric with given typmod, or -1 if unlimited/unknown.
953 : */
954 : int32
955 7158 : numeric_maximum_size(int32 typmod)
956 : {
957 : int precision;
958 : int numeric_digits;
959 :
960 7158 : if (!is_valid_numeric_typmod(typmod))
961 0 : return -1;
962 :
963 : /* precision (ie, max # of digits) is in upper bits of typmod */
964 7158 : precision = numeric_typmod_precision(typmod);
965 :
966 : /*
967 : * This formula computes the maximum number of NumericDigits we could need
968 : * in order to store the specified number of decimal digits. Because the
969 : * weight is stored as a number of NumericDigits rather than a number of
970 : * decimal digits, it's possible that the first NumericDigit will contain
971 : * only a single decimal digit. Thus, the first two decimal digits can
972 : * require two NumericDigits to store, but it isn't until we reach
973 : * DEC_DIGITS + 2 decimal digits that we potentially need a third
974 : * NumericDigit.
975 : */
976 7158 : numeric_digits = (precision + 2 * (DEC_DIGITS - 1)) / DEC_DIGITS;
977 :
978 : /*
979 : * In most cases, the size of a numeric will be smaller than the value
980 : * computed below, because the varlena header will typically get toasted
981 : * down to a single byte before being stored on disk, and it may also be
982 : * possible to use a short numeric header. But our job here is to compute
983 : * the worst case.
984 : */
985 7158 : return NUMERIC_HDRSZ + (numeric_digits * sizeof(NumericDigit));
986 : }
987 :
988 : /*
989 : * numeric_out_sci() -
990 : *
991 : * Output function for numeric data type in scientific notation.
992 : */
993 : char *
994 234 : numeric_out_sci(Numeric num, int scale)
995 : {
996 : NumericVar x;
997 : char *str;
998 :
999 : /*
1000 : * Handle NaN and infinities
1001 : */
1002 234 : if (NUMERIC_IS_SPECIAL(num))
1003 : {
1004 18 : if (NUMERIC_IS_PINF(num))
1005 6 : return pstrdup("Infinity");
1006 12 : else if (NUMERIC_IS_NINF(num))
1007 6 : return pstrdup("-Infinity");
1008 : else
1009 6 : return pstrdup("NaN");
1010 : }
1011 :
1012 216 : init_var_from_num(num, &x);
1013 :
1014 216 : str = get_str_from_var_sci(&x, scale);
1015 :
1016 216 : return str;
1017 : }
1018 :
1019 : /*
1020 : * numeric_normalize() -
1021 : *
1022 : * Output function for numeric data type, suppressing insignificant trailing
1023 : * zeroes and then any trailing decimal point. The intent of this is to
1024 : * produce strings that are equal if and only if the input numeric values
1025 : * compare equal.
1026 : */
1027 : char *
1028 12966 : numeric_normalize(Numeric num)
1029 : {
1030 : NumericVar x;
1031 : char *str;
1032 : int last;
1033 :
1034 : /*
1035 : * Handle NaN and infinities
1036 : */
1037 12966 : if (NUMERIC_IS_SPECIAL(num))
1038 : {
1039 0 : if (NUMERIC_IS_PINF(num))
1040 0 : return pstrdup("Infinity");
1041 0 : else if (NUMERIC_IS_NINF(num))
1042 0 : return pstrdup("-Infinity");
1043 : else
1044 0 : return pstrdup("NaN");
1045 : }
1046 :
1047 12966 : init_var_from_num(num, &x);
1048 :
1049 12966 : str = get_str_from_var(&x);
1050 :
1051 : /* If there's no decimal point, there's certainly nothing to remove. */
1052 12966 : if (strchr(str, '.') != NULL)
1053 : {
1054 : /*
1055 : * Back up over trailing fractional zeroes. Since there is a decimal
1056 : * point, this loop will terminate safely.
1057 : */
1058 42 : last = strlen(str) - 1;
1059 84 : while (str[last] == '0')
1060 42 : last--;
1061 :
1062 : /* We want to get rid of the decimal point too, if it's now last. */
1063 42 : if (str[last] == '.')
1064 42 : last--;
1065 :
1066 : /* Delete whatever we backed up over. */
1067 42 : str[last + 1] = '\0';
1068 : }
1069 :
1070 12966 : return str;
1071 : }
1072 :
1073 : /*
1074 : * numeric_recv - converts external binary format to numeric
1075 : *
1076 : * External format is a sequence of int16's:
1077 : * ndigits, weight, sign, dscale, NumericDigits.
1078 : */
1079 : Datum
1080 102 : numeric_recv(PG_FUNCTION_ARGS)
1081 : {
1082 102 : StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
1083 :
1084 : #ifdef NOT_USED
1085 : Oid typelem = PG_GETARG_OID(1);
1086 : #endif
1087 102 : int32 typmod = PG_GETARG_INT32(2);
1088 : NumericVar value;
1089 : Numeric res;
1090 : int len,
1091 : i;
1092 :
1093 102 : init_var(&value);
1094 :
1095 102 : len = (uint16) pq_getmsgint(buf, sizeof(uint16));
1096 :
1097 102 : alloc_var(&value, len);
1098 :
1099 102 : value.weight = (int16) pq_getmsgint(buf, sizeof(int16));
1100 : /* we allow any int16 for weight --- OK? */
1101 :
1102 102 : value.sign = (uint16) pq_getmsgint(buf, sizeof(uint16));
1103 102 : if (!(value.sign == NUMERIC_POS ||
1104 0 : value.sign == NUMERIC_NEG ||
1105 0 : value.sign == NUMERIC_NAN ||
1106 0 : value.sign == NUMERIC_PINF ||
1107 0 : value.sign == NUMERIC_NINF))
1108 0 : ereport(ERROR,
1109 : (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
1110 : errmsg("invalid sign in external \"numeric\" value")));
1111 :
1112 102 : value.dscale = (uint16) pq_getmsgint(buf, sizeof(uint16));
1113 102 : if ((value.dscale & NUMERIC_DSCALE_MASK) != value.dscale)
1114 0 : ereport(ERROR,
1115 : (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
1116 : errmsg("invalid scale in external \"numeric\" value")));
1117 :
1118 274 : for (i = 0; i < len; i++)
1119 : {
1120 172 : NumericDigit d = pq_getmsgint(buf, sizeof(NumericDigit));
1121 :
1122 172 : if (d < 0 || d >= NBASE)
1123 0 : ereport(ERROR,
1124 : (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
1125 : errmsg("invalid digit in external \"numeric\" value")));
1126 172 : value.digits[i] = d;
1127 : }
1128 :
1129 : /*
1130 : * If the given dscale would hide any digits, truncate those digits away.
1131 : * We could alternatively throw an error, but that would take a bunch of
1132 : * extra code (about as much as trunc_var involves), and it might cause
1133 : * client compatibility issues. Be careful not to apply trunc_var to
1134 : * special values, as it could do the wrong thing; we don't need it
1135 : * anyway, since make_result will ignore all but the sign field.
1136 : *
1137 : * After doing that, be sure to check the typmod restriction.
1138 : */
1139 102 : if (value.sign == NUMERIC_POS ||
1140 0 : value.sign == NUMERIC_NEG)
1141 : {
1142 102 : trunc_var(&value, value.dscale);
1143 :
1144 102 : (void) apply_typmod(&value, typmod, NULL);
1145 :
1146 102 : res = make_result(&value);
1147 : }
1148 : else
1149 : {
1150 : /* apply_typmod_special wants us to make the Numeric first */
1151 0 : res = make_result(&value);
1152 :
1153 0 : (void) apply_typmod_special(res, typmod, NULL);
1154 : }
1155 :
1156 102 : free_var(&value);
1157 :
1158 102 : PG_RETURN_NUMERIC(res);
1159 : }
1160 :
1161 : /*
1162 : * numeric_send - converts numeric to binary format
1163 : */
1164 : Datum
1165 70 : numeric_send(PG_FUNCTION_ARGS)
1166 : {
1167 70 : Numeric num = PG_GETARG_NUMERIC(0);
1168 : NumericVar x;
1169 : StringInfoData buf;
1170 : int i;
1171 :
1172 70 : init_var_from_num(num, &x);
1173 :
1174 70 : pq_begintypsend(&buf);
1175 :
1176 70 : pq_sendint16(&buf, x.ndigits);
1177 70 : pq_sendint16(&buf, x.weight);
1178 70 : pq_sendint16(&buf, x.sign);
1179 70 : pq_sendint16(&buf, x.dscale);
1180 194 : for (i = 0; i < x.ndigits; i++)
1181 124 : pq_sendint16(&buf, x.digits[i]);
1182 :
1183 70 : PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
1184 : }
1185 :
1186 :
1187 : /*
1188 : * numeric_support()
1189 : *
1190 : * Planner support function for the numeric() length coercion function.
1191 : *
1192 : * Flatten calls that solely represent increases in allowable precision.
1193 : * Scale changes mutate every datum, so they are unoptimizable. Some values,
1194 : * e.g. 1E-1001, can only fit into an unconstrained numeric, so a change from
1195 : * an unconstrained numeric to any constrained numeric is also unoptimizable.
1196 : */
1197 : Datum
1198 516 : numeric_support(PG_FUNCTION_ARGS)
1199 : {
1200 516 : Node *rawreq = (Node *) PG_GETARG_POINTER(0);
1201 516 : Node *ret = NULL;
1202 :
1203 516 : if (IsA(rawreq, SupportRequestSimplify))
1204 : {
1205 228 : SupportRequestSimplify *req = (SupportRequestSimplify *) rawreq;
1206 228 : FuncExpr *expr = req->fcall;
1207 : Node *typmod;
1208 :
1209 : Assert(list_length(expr->args) >= 2);
1210 :
1211 228 : typmod = (Node *) lsecond(expr->args);
1212 :
1213 228 : if (IsA(typmod, Const) && !((Const *) typmod)->constisnull)
1214 : {
1215 228 : Node *source = (Node *) linitial(expr->args);
1216 228 : int32 old_typmod = exprTypmod(source);
1217 228 : int32 new_typmod = DatumGetInt32(((Const *) typmod)->constvalue);
1218 228 : int32 old_scale = numeric_typmod_scale(old_typmod);
1219 228 : int32 new_scale = numeric_typmod_scale(new_typmod);
1220 228 : int32 old_precision = numeric_typmod_precision(old_typmod);
1221 228 : int32 new_precision = numeric_typmod_precision(new_typmod);
1222 :
1223 : /*
1224 : * If new_typmod is invalid, the destination is unconstrained;
1225 : * that's always OK. If old_typmod is valid, the source is
1226 : * constrained, and we're OK if the scale is unchanged and the
1227 : * precision is not decreasing. See further notes in function
1228 : * header comment.
1229 : */
1230 456 : if (!is_valid_numeric_typmod(new_typmod) ||
1231 240 : (is_valid_numeric_typmod(old_typmod) &&
1232 6 : new_scale == old_scale && new_precision >= old_precision))
1233 6 : ret = relabel_to_typmod(source, new_typmod);
1234 : }
1235 : }
1236 :
1237 516 : PG_RETURN_POINTER(ret);
1238 : }
1239 :
1240 : /*
1241 : * numeric() -
1242 : *
1243 : * This is a special function called by the Postgres database system
1244 : * before a value is stored in a tuple's attribute. The precision and
1245 : * scale of the attribute have to be applied on the value.
1246 : */
1247 : Datum
1248 11790 : numeric (PG_FUNCTION_ARGS)
1249 : {
1250 11790 : Numeric num = PG_GETARG_NUMERIC(0);
1251 11790 : int32 typmod = PG_GETARG_INT32(1);
1252 : Numeric new;
1253 : int precision;
1254 : int scale;
1255 : int ddigits;
1256 : int maxdigits;
1257 : int dscale;
1258 : NumericVar var;
1259 :
1260 : /*
1261 : * Handle NaN and infinities: if apply_typmod_special doesn't complain,
1262 : * just return a copy of the input.
1263 : */
1264 11790 : if (NUMERIC_IS_SPECIAL(num))
1265 : {
1266 210 : (void) apply_typmod_special(num, typmod, NULL);
1267 192 : PG_RETURN_NUMERIC(duplicate_numeric(num));
1268 : }
1269 :
1270 : /*
1271 : * If the value isn't a valid type modifier, simply return a copy of the
1272 : * input value
1273 : */
1274 11580 : if (!is_valid_numeric_typmod(typmod))
1275 0 : PG_RETURN_NUMERIC(duplicate_numeric(num));
1276 :
1277 : /*
1278 : * Get the precision and scale out of the typmod value
1279 : */
1280 11580 : precision = numeric_typmod_precision(typmod);
1281 11580 : scale = numeric_typmod_scale(typmod);
1282 11580 : maxdigits = precision - scale;
1283 :
1284 : /* The target display scale is non-negative */
1285 11580 : dscale = Max(scale, 0);
1286 :
1287 : /*
1288 : * If the number is certainly in bounds and due to the target scale no
1289 : * rounding could be necessary, just make a copy of the input and modify
1290 : * its scale fields, unless the larger scale forces us to abandon the
1291 : * short representation. (Note we assume the existing dscale is
1292 : * honest...)
1293 : */
1294 11580 : ddigits = (NUMERIC_WEIGHT(num) + 1) * DEC_DIGITS;
1295 11580 : if (ddigits <= maxdigits && scale >= NUMERIC_DSCALE(num)
1296 7134 : && (NUMERIC_CAN_BE_SHORT(dscale, NUMERIC_WEIGHT(num))
1297 0 : || !NUMERIC_IS_SHORT(num)))
1298 : {
1299 7134 : new = duplicate_numeric(num);
1300 7134 : if (NUMERIC_IS_SHORT(num))
1301 7134 : new->choice.n_short.n_header =
1302 7134 : (num->choice.n_short.n_header & ~NUMERIC_SHORT_DSCALE_MASK)
1303 7134 : | (dscale << NUMERIC_SHORT_DSCALE_SHIFT);
1304 : else
1305 0 : new->choice.n_long.n_sign_dscale = NUMERIC_SIGN(new) |
1306 0 : ((uint16) dscale & NUMERIC_DSCALE_MASK);
1307 7134 : PG_RETURN_NUMERIC(new);
1308 : }
1309 :
1310 : /*
1311 : * We really need to fiddle with things - unpack the number into a
1312 : * variable and let apply_typmod() do it.
1313 : */
1314 4446 : init_var(&var);
1315 :
1316 4446 : set_var_from_num(num, &var);
1317 4446 : (void) apply_typmod(&var, typmod, NULL);
1318 4386 : new = make_result(&var);
1319 :
1320 4386 : free_var(&var);
1321 :
1322 4386 : PG_RETURN_NUMERIC(new);
1323 : }
1324 :
1325 : Datum
1326 1932 : numerictypmodin(PG_FUNCTION_ARGS)
1327 : {
1328 1932 : ArrayType *ta = PG_GETARG_ARRAYTYPE_P(0);
1329 : int32 *tl;
1330 : int n;
1331 : int32 typmod;
1332 :
1333 1932 : tl = ArrayGetIntegerTypmods(ta, &n);
1334 :
1335 1932 : if (n == 2)
1336 : {
1337 1912 : if (tl[0] < 1 || tl[0] > NUMERIC_MAX_PRECISION)
1338 18 : ereport(ERROR,
1339 : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1340 : errmsg("NUMERIC precision %d must be between 1 and %d",
1341 : tl[0], NUMERIC_MAX_PRECISION)));
1342 1894 : if (tl[1] < NUMERIC_MIN_SCALE || tl[1] > NUMERIC_MAX_SCALE)
1343 12 : ereport(ERROR,
1344 : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1345 : errmsg("NUMERIC scale %d must be between %d and %d",
1346 : tl[1], NUMERIC_MIN_SCALE, NUMERIC_MAX_SCALE)));
1347 1882 : typmod = make_numeric_typmod(tl[0], tl[1]);
1348 : }
1349 20 : else if (n == 1)
1350 : {
1351 8 : if (tl[0] < 1 || tl[0] > NUMERIC_MAX_PRECISION)
1352 0 : ereport(ERROR,
1353 : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1354 : errmsg("NUMERIC precision %d must be between 1 and %d",
1355 : tl[0], NUMERIC_MAX_PRECISION)));
1356 : /* scale defaults to zero */
1357 8 : typmod = make_numeric_typmod(tl[0], 0);
1358 : }
1359 : else
1360 : {
1361 12 : ereport(ERROR,
1362 : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1363 : errmsg("invalid NUMERIC type modifier")));
1364 : typmod = 0; /* keep compiler quiet */
1365 : }
1366 :
1367 1890 : PG_RETURN_INT32(typmod);
1368 : }
1369 :
1370 : Datum
1371 376 : numerictypmodout(PG_FUNCTION_ARGS)
1372 : {
1373 376 : int32 typmod = PG_GETARG_INT32(0);
1374 376 : char *res = (char *) palloc(64);
1375 :
1376 376 : if (is_valid_numeric_typmod(typmod))
1377 376 : snprintf(res, 64, "(%d,%d)",
1378 : numeric_typmod_precision(typmod),
1379 : numeric_typmod_scale(typmod));
1380 : else
1381 0 : *res = '\0';
1382 :
1383 376 : PG_RETURN_CSTRING(res);
1384 : }
1385 :
1386 :
1387 : /* ----------------------------------------------------------------------
1388 : *
1389 : * Sign manipulation, rounding and the like
1390 : *
1391 : * ----------------------------------------------------------------------
1392 : */
1393 :
1394 : Datum
1395 19506 : numeric_abs(PG_FUNCTION_ARGS)
1396 : {
1397 19506 : Numeric num = PG_GETARG_NUMERIC(0);
1398 : Numeric res;
1399 :
1400 : /*
1401 : * Do it the easy way directly on the packed format
1402 : */
1403 19506 : res = duplicate_numeric(num);
1404 :
1405 19506 : if (NUMERIC_IS_SHORT(num))
1406 19440 : res->choice.n_short.n_header =
1407 19440 : num->choice.n_short.n_header & ~NUMERIC_SHORT_SIGN_MASK;
1408 66 : else if (NUMERIC_IS_SPECIAL(num))
1409 : {
1410 : /* This changes -Inf to Inf, and doesn't affect NaN */
1411 18 : res->choice.n_short.n_header =
1412 18 : num->choice.n_short.n_header & ~NUMERIC_INF_SIGN_MASK;
1413 : }
1414 : else
1415 48 : res->choice.n_long.n_sign_dscale = NUMERIC_POS | NUMERIC_DSCALE(num);
1416 :
1417 19506 : PG_RETURN_NUMERIC(res);
1418 : }
1419 :
1420 :
1421 : Datum
1422 884 : numeric_uminus(PG_FUNCTION_ARGS)
1423 : {
1424 884 : Numeric num = PG_GETARG_NUMERIC(0);
1425 : Numeric res;
1426 :
1427 : /*
1428 : * Do it the easy way directly on the packed format
1429 : */
1430 884 : res = duplicate_numeric(num);
1431 :
1432 884 : if (NUMERIC_IS_SPECIAL(num))
1433 : {
1434 : /* Flip the sign, if it's Inf or -Inf */
1435 126 : if (!NUMERIC_IS_NAN(num))
1436 84 : res->choice.n_short.n_header =
1437 84 : num->choice.n_short.n_header ^ NUMERIC_INF_SIGN_MASK;
1438 : }
1439 :
1440 : /*
1441 : * The packed format is known to be totally zero digit trimmed always. So
1442 : * once we've eliminated specials, we can identify a zero by the fact that
1443 : * there are no digits at all. Do nothing to a zero.
1444 : */
1445 758 : else if (NUMERIC_NDIGITS(num) != 0)
1446 : {
1447 : /* Else, flip the sign */
1448 644 : if (NUMERIC_IS_SHORT(num))
1449 644 : res->choice.n_short.n_header =
1450 644 : num->choice.n_short.n_header ^ NUMERIC_SHORT_SIGN_MASK;
1451 0 : else if (NUMERIC_SIGN(num) == NUMERIC_POS)
1452 0 : res->choice.n_long.n_sign_dscale =
1453 0 : NUMERIC_NEG | NUMERIC_DSCALE(num);
1454 : else
1455 0 : res->choice.n_long.n_sign_dscale =
1456 0 : NUMERIC_POS | NUMERIC_DSCALE(num);
1457 : }
1458 :
1459 884 : PG_RETURN_NUMERIC(res);
1460 : }
1461 :
1462 :
1463 : Datum
1464 498 : numeric_uplus(PG_FUNCTION_ARGS)
1465 : {
1466 498 : Numeric num = PG_GETARG_NUMERIC(0);
1467 :
1468 498 : PG_RETURN_NUMERIC(duplicate_numeric(num));
1469 : }
1470 :
1471 :
1472 : /*
1473 : * numeric_sign_internal() -
1474 : *
1475 : * Returns -1 if the argument is less than 0, 0 if the argument is equal
1476 : * to 0, and 1 if the argument is greater than zero. Caller must have
1477 : * taken care of the NaN case, but we can handle infinities here.
1478 : */
1479 : static int
1480 3546 : numeric_sign_internal(Numeric num)
1481 : {
1482 3546 : if (NUMERIC_IS_SPECIAL(num))
1483 : {
1484 : Assert(!NUMERIC_IS_NAN(num));
1485 : /* Must be Inf or -Inf */
1486 312 : if (NUMERIC_IS_PINF(num))
1487 186 : return 1;
1488 : else
1489 126 : return -1;
1490 : }
1491 :
1492 : /*
1493 : * The packed format is known to be totally zero digit trimmed always. So
1494 : * once we've eliminated specials, we can identify a zero by the fact that
1495 : * there are no digits at all.
1496 : */
1497 3234 : else if (NUMERIC_NDIGITS(num) == 0)
1498 228 : return 0;
1499 3006 : else if (NUMERIC_SIGN(num) == NUMERIC_NEG)
1500 726 : return -1;
1501 : else
1502 2280 : return 1;
1503 : }
1504 :
1505 : /*
1506 : * numeric_sign() -
1507 : *
1508 : * returns -1 if the argument is less than 0, 0 if the argument is equal
1509 : * to 0, and 1 if the argument is greater than zero.
1510 : */
1511 : Datum
1512 48 : numeric_sign(PG_FUNCTION_ARGS)
1513 : {
1514 48 : Numeric num = PG_GETARG_NUMERIC(0);
1515 :
1516 : /*
1517 : * Handle NaN (infinities can be handled normally)
1518 : */
1519 48 : if (NUMERIC_IS_NAN(num))
1520 6 : PG_RETURN_NUMERIC(make_result(&const_nan));
1521 :
1522 42 : switch (numeric_sign_internal(num))
1523 : {
1524 6 : case 0:
1525 6 : PG_RETURN_NUMERIC(make_result(&const_zero));
1526 18 : case 1:
1527 18 : PG_RETURN_NUMERIC(make_result(&const_one));
1528 18 : case -1:
1529 18 : PG_RETURN_NUMERIC(make_result(&const_minus_one));
1530 : }
1531 :
1532 : Assert(false);
1533 0 : return (Datum) 0;
1534 : }
1535 :
1536 :
1537 : /*
1538 : * numeric_round() -
1539 : *
1540 : * Round a value to have 'scale' digits after the decimal point.
1541 : * We allow negative 'scale', implying rounding before the decimal
1542 : * point --- Oracle interprets rounding that way.
1543 : */
1544 : Datum
1545 7802 : numeric_round(PG_FUNCTION_ARGS)
1546 : {
1547 7802 : Numeric num = PG_GETARG_NUMERIC(0);
1548 7802 : int32 scale = PG_GETARG_INT32(1);
1549 : Numeric res;
1550 : NumericVar arg;
1551 :
1552 : /*
1553 : * Handle NaN and infinities
1554 : */
1555 7802 : if (NUMERIC_IS_SPECIAL(num))
1556 96 : PG_RETURN_NUMERIC(duplicate_numeric(num));
1557 :
1558 : /*
1559 : * Limit the scale value to avoid possible overflow in calculations.
1560 : *
1561 : * These limits are based on the maximum number of digits a Numeric value
1562 : * can have before and after the decimal point, but we must allow for one
1563 : * extra digit before the decimal point, in case the most significant
1564 : * digit rounds up; we must check if that causes Numeric overflow.
1565 : */
1566 7706 : scale = Max(scale, -(NUMERIC_WEIGHT_MAX + 1) * DEC_DIGITS - 1);
1567 7706 : scale = Min(scale, NUMERIC_DSCALE_MAX);
1568 :
1569 : /*
1570 : * Unpack the argument and round it at the proper digit position
1571 : */
1572 7706 : init_var(&arg);
1573 7706 : set_var_from_num(num, &arg);
1574 :
1575 7706 : round_var(&arg, scale);
1576 :
1577 : /* We don't allow negative output dscale */
1578 7706 : if (scale < 0)
1579 216 : arg.dscale = 0;
1580 :
1581 : /*
1582 : * Return the rounded result
1583 : */
1584 7706 : res = make_result(&arg);
1585 :
1586 7700 : free_var(&arg);
1587 7700 : PG_RETURN_NUMERIC(res);
1588 : }
1589 :
1590 :
1591 : /*
1592 : * numeric_trunc() -
1593 : *
1594 : * Truncate a value to have 'scale' digits after the decimal point.
1595 : * We allow negative 'scale', implying a truncation before the decimal
1596 : * point --- Oracle interprets truncation that way.
1597 : */
1598 : Datum
1599 626 : numeric_trunc(PG_FUNCTION_ARGS)
1600 : {
1601 626 : Numeric num = PG_GETARG_NUMERIC(0);
1602 626 : int32 scale = PG_GETARG_INT32(1);
1603 : Numeric res;
1604 : NumericVar arg;
1605 :
1606 : /*
1607 : * Handle NaN and infinities
1608 : */
1609 626 : if (NUMERIC_IS_SPECIAL(num))
1610 36 : PG_RETURN_NUMERIC(duplicate_numeric(num));
1611 :
1612 : /*
1613 : * Limit the scale value to avoid possible overflow in calculations.
1614 : *
1615 : * These limits are based on the maximum number of digits a Numeric value
1616 : * can have before and after the decimal point.
1617 : */
1618 590 : scale = Max(scale, -(NUMERIC_WEIGHT_MAX + 1) * DEC_DIGITS);
1619 590 : scale = Min(scale, NUMERIC_DSCALE_MAX);
1620 :
1621 : /*
1622 : * Unpack the argument and truncate it at the proper digit position
1623 : */
1624 590 : init_var(&arg);
1625 590 : set_var_from_num(num, &arg);
1626 :
1627 590 : trunc_var(&arg, scale);
1628 :
1629 : /* We don't allow negative output dscale */
1630 590 : if (scale < 0)
1631 24 : arg.dscale = 0;
1632 :
1633 : /*
1634 : * Return the truncated result
1635 : */
1636 590 : res = make_result(&arg);
1637 :
1638 590 : free_var(&arg);
1639 590 : PG_RETURN_NUMERIC(res);
1640 : }
1641 :
1642 :
1643 : /*
1644 : * numeric_ceil() -
1645 : *
1646 : * Return the smallest integer greater than or equal to the argument
1647 : */
1648 : Datum
1649 222 : numeric_ceil(PG_FUNCTION_ARGS)
1650 : {
1651 222 : Numeric num = PG_GETARG_NUMERIC(0);
1652 : Numeric res;
1653 : NumericVar result;
1654 :
1655 : /*
1656 : * Handle NaN and infinities
1657 : */
1658 222 : if (NUMERIC_IS_SPECIAL(num))
1659 18 : PG_RETURN_NUMERIC(duplicate_numeric(num));
1660 :
1661 204 : init_var_from_num(num, &result);
1662 204 : ceil_var(&result, &result);
1663 :
1664 204 : res = make_result(&result);
1665 204 : free_var(&result);
1666 :
1667 204 : PG_RETURN_NUMERIC(res);
1668 : }
1669 :
1670 :
1671 : /*
1672 : * numeric_floor() -
1673 : *
1674 : * Return the largest integer equal to or less than the argument
1675 : */
1676 : Datum
1677 126 : numeric_floor(PG_FUNCTION_ARGS)
1678 : {
1679 126 : Numeric num = PG_GETARG_NUMERIC(0);
1680 : Numeric res;
1681 : NumericVar result;
1682 :
1683 : /*
1684 : * Handle NaN and infinities
1685 : */
1686 126 : if (NUMERIC_IS_SPECIAL(num))
1687 18 : PG_RETURN_NUMERIC(duplicate_numeric(num));
1688 :
1689 108 : init_var_from_num(num, &result);
1690 108 : floor_var(&result, &result);
1691 :
1692 108 : res = make_result(&result);
1693 108 : free_var(&result);
1694 :
1695 108 : PG_RETURN_NUMERIC(res);
1696 : }
1697 :
1698 :
1699 : /*
1700 : * generate_series_numeric() -
1701 : *
1702 : * Generate series of numeric.
1703 : */
1704 : Datum
1705 216 : generate_series_numeric(PG_FUNCTION_ARGS)
1706 : {
1707 216 : return generate_series_step_numeric(fcinfo);
1708 : }
1709 :
1710 : Datum
1711 420 : generate_series_step_numeric(PG_FUNCTION_ARGS)
1712 : {
1713 : generate_series_numeric_fctx *fctx;
1714 : FuncCallContext *funcctx;
1715 : MemoryContext oldcontext;
1716 :
1717 420 : if (SRF_IS_FIRSTCALL())
1718 : {
1719 138 : Numeric start_num = PG_GETARG_NUMERIC(0);
1720 138 : Numeric stop_num = PG_GETARG_NUMERIC(1);
1721 138 : NumericVar steploc = const_one;
1722 :
1723 : /* Reject NaN and infinities in start and stop values */
1724 138 : if (NUMERIC_IS_SPECIAL(start_num))
1725 : {
1726 12 : if (NUMERIC_IS_NAN(start_num))
1727 6 : ereport(ERROR,
1728 : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1729 : errmsg("start value cannot be NaN")));
1730 : else
1731 6 : ereport(ERROR,
1732 : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1733 : errmsg("start value cannot be infinity")));
1734 : }
1735 126 : if (NUMERIC_IS_SPECIAL(stop_num))
1736 : {
1737 12 : if (NUMERIC_IS_NAN(stop_num))
1738 6 : ereport(ERROR,
1739 : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1740 : errmsg("stop value cannot be NaN")));
1741 : else
1742 6 : ereport(ERROR,
1743 : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1744 : errmsg("stop value cannot be infinity")));
1745 : }
1746 :
1747 : /* see if we were given an explicit step size */
1748 114 : if (PG_NARGS() == 3)
1749 : {
1750 54 : Numeric step_num = PG_GETARG_NUMERIC(2);
1751 :
1752 54 : if (NUMERIC_IS_SPECIAL(step_num))
1753 : {
1754 12 : if (NUMERIC_IS_NAN(step_num))
1755 6 : ereport(ERROR,
1756 : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1757 : errmsg("step size cannot be NaN")));
1758 : else
1759 6 : ereport(ERROR,
1760 : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1761 : errmsg("step size cannot be infinity")));
1762 : }
1763 :
1764 42 : init_var_from_num(step_num, &steploc);
1765 :
1766 42 : if (cmp_var(&steploc, &const_zero) == 0)
1767 6 : ereport(ERROR,
1768 : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1769 : errmsg("step size cannot equal zero")));
1770 : }
1771 :
1772 : /* create a function context for cross-call persistence */
1773 96 : funcctx = SRF_FIRSTCALL_INIT();
1774 :
1775 : /*
1776 : * Switch to memory context appropriate for multiple function calls.
1777 : */
1778 96 : oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
1779 :
1780 : /* allocate memory for user context */
1781 : fctx = (generate_series_numeric_fctx *)
1782 96 : palloc(sizeof(generate_series_numeric_fctx));
1783 :
1784 : /*
1785 : * Use fctx to keep state from call to call. Seed current with the
1786 : * original start value. We must copy the start_num and stop_num
1787 : * values rather than pointing to them, since we may have detoasted
1788 : * them in the per-call context.
1789 : */
1790 96 : init_var(&fctx->current);
1791 96 : init_var(&fctx->stop);
1792 96 : init_var(&fctx->step);
1793 :
1794 96 : set_var_from_num(start_num, &fctx->current);
1795 96 : set_var_from_num(stop_num, &fctx->stop);
1796 96 : set_var_from_var(&steploc, &fctx->step);
1797 :
1798 96 : funcctx->user_fctx = fctx;
1799 96 : MemoryContextSwitchTo(oldcontext);
1800 : }
1801 :
1802 : /* stuff done on every call of the function */
1803 378 : funcctx = SRF_PERCALL_SETUP();
1804 :
1805 : /*
1806 : * Get the saved state and use current state as the result of this
1807 : * iteration.
1808 : */
1809 378 : fctx = funcctx->user_fctx;
1810 :
1811 732 : if ((fctx->step.sign == NUMERIC_POS &&
1812 354 : cmp_var(&fctx->current, &fctx->stop) <= 0) ||
1813 138 : (fctx->step.sign == NUMERIC_NEG &&
1814 24 : cmp_var(&fctx->current, &fctx->stop) >= 0))
1815 : {
1816 282 : Numeric result = make_result(&fctx->current);
1817 :
1818 : /* switch to memory context appropriate for iteration calculation */
1819 282 : oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
1820 :
1821 : /* increment current in preparation for next iteration */
1822 282 : add_var(&fctx->current, &fctx->step, &fctx->current);
1823 282 : MemoryContextSwitchTo(oldcontext);
1824 :
1825 : /* do when there is more left to send */
1826 282 : SRF_RETURN_NEXT(funcctx, NumericGetDatum(result));
1827 : }
1828 : else
1829 : /* do when there is no more left */
1830 96 : SRF_RETURN_DONE(funcctx);
1831 : }
1832 :
1833 :
1834 : /*
1835 : * Implements the numeric version of the width_bucket() function
1836 : * defined by SQL2003. See also width_bucket_float8().
1837 : *
1838 : * 'bound1' and 'bound2' are the lower and upper bounds of the
1839 : * histogram's range, respectively. 'count' is the number of buckets
1840 : * in the histogram. width_bucket() returns an integer indicating the
1841 : * bucket number that 'operand' belongs to in an equiwidth histogram
1842 : * with the specified characteristics. An operand smaller than the
1843 : * lower bound is assigned to bucket 0. An operand greater than the
1844 : * upper bound is assigned to an additional bucket (with number
1845 : * count+1). We don't allow "NaN" for any of the numeric arguments.
1846 : */
1847 : Datum
1848 780 : width_bucket_numeric(PG_FUNCTION_ARGS)
1849 : {
1850 780 : Numeric operand = PG_GETARG_NUMERIC(0);
1851 780 : Numeric bound1 = PG_GETARG_NUMERIC(1);
1852 780 : Numeric bound2 = PG_GETARG_NUMERIC(2);
1853 780 : int32 count = PG_GETARG_INT32(3);
1854 : NumericVar count_var;
1855 : NumericVar result_var;
1856 : int32 result;
1857 :
1858 780 : if (count <= 0)
1859 12 : ereport(ERROR,
1860 : (errcode(ERRCODE_INVALID_ARGUMENT_FOR_WIDTH_BUCKET_FUNCTION),
1861 : errmsg("count must be greater than zero")));
1862 :
1863 768 : if (NUMERIC_IS_SPECIAL(operand) ||
1864 750 : NUMERIC_IS_SPECIAL(bound1) ||
1865 744 : NUMERIC_IS_SPECIAL(bound2))
1866 : {
1867 36 : if (NUMERIC_IS_NAN(operand) ||
1868 30 : NUMERIC_IS_NAN(bound1) ||
1869 30 : NUMERIC_IS_NAN(bound2))
1870 6 : ereport(ERROR,
1871 : (errcode(ERRCODE_INVALID_ARGUMENT_FOR_WIDTH_BUCKET_FUNCTION),
1872 : errmsg("operand, lower bound, and upper bound cannot be NaN")));
1873 : /* We allow "operand" to be infinite; cmp_numerics will cope */
1874 30 : if (NUMERIC_IS_INF(bound1) || NUMERIC_IS_INF(bound2))
1875 18 : ereport(ERROR,
1876 : (errcode(ERRCODE_INVALID_ARGUMENT_FOR_WIDTH_BUCKET_FUNCTION),
1877 : errmsg("lower and upper bounds must be finite")));
1878 : }
1879 :
1880 744 : init_var(&result_var);
1881 744 : init_var(&count_var);
1882 :
1883 : /* Convert 'count' to a numeric, for ease of use later */
1884 744 : int64_to_numericvar((int64) count, &count_var);
1885 :
1886 744 : switch (cmp_numerics(bound1, bound2))
1887 : {
1888 6 : case 0:
1889 6 : ereport(ERROR,
1890 : (errcode(ERRCODE_INVALID_ARGUMENT_FOR_WIDTH_BUCKET_FUNCTION),
1891 : errmsg("lower bound cannot equal upper bound")));
1892 : break;
1893 :
1894 : /* bound1 < bound2 */
1895 546 : case -1:
1896 546 : if (cmp_numerics(operand, bound1) < 0)
1897 114 : set_var_from_var(&const_zero, &result_var);
1898 432 : else if (cmp_numerics(operand, bound2) >= 0)
1899 108 : add_var(&count_var, &const_one, &result_var);
1900 : else
1901 324 : compute_bucket(operand, bound1, bound2, &count_var,
1902 : &result_var);
1903 546 : break;
1904 :
1905 : /* bound1 > bound2 */
1906 192 : case 1:
1907 192 : if (cmp_numerics(operand, bound1) > 0)
1908 12 : set_var_from_var(&const_zero, &result_var);
1909 180 : else if (cmp_numerics(operand, bound2) <= 0)
1910 24 : add_var(&count_var, &const_one, &result_var);
1911 : else
1912 156 : compute_bucket(operand, bound1, bound2, &count_var,
1913 : &result_var);
1914 192 : break;
1915 : }
1916 :
1917 : /* if result exceeds the range of a legal int4, we ereport here */
1918 738 : if (!numericvar_to_int32(&result_var, &result))
1919 0 : ereport(ERROR,
1920 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1921 : errmsg("integer out of range")));
1922 :
1923 738 : free_var(&count_var);
1924 738 : free_var(&result_var);
1925 :
1926 738 : PG_RETURN_INT32(result);
1927 : }
1928 :
1929 : /*
1930 : * 'operand' is inside the bucket range, so determine the correct
1931 : * bucket for it to go in. The calculations performed by this function
1932 : * are derived directly from the SQL2003 spec. Note however that we
1933 : * multiply by count before dividing, to avoid unnecessary roundoff error.
1934 : */
1935 : static void
1936 480 : compute_bucket(Numeric operand, Numeric bound1, Numeric bound2,
1937 : const NumericVar *count_var, NumericVar *result_var)
1938 : {
1939 : NumericVar bound1_var;
1940 : NumericVar bound2_var;
1941 : NumericVar operand_var;
1942 :
1943 480 : init_var_from_num(bound1, &bound1_var);
1944 480 : init_var_from_num(bound2, &bound2_var);
1945 480 : init_var_from_num(operand, &operand_var);
1946 :
1947 : /*
1948 : * Per spec, bound1 is inclusive and bound2 is exclusive, and so we have
1949 : * bound1 <= operand < bound2 or bound1 >= operand > bound2. Either way,
1950 : * the result is ((operand - bound1) * count) / (bound2 - bound1) + 1,
1951 : * where the quotient is computed using floor division (i.e., division to
1952 : * zero decimal places with truncation), which guarantees that the result
1953 : * is in the range [1, count]. Reversing the bounds doesn't affect the
1954 : * computation, because the signs cancel out when dividing.
1955 : */
1956 480 : sub_var(&operand_var, &bound1_var, &operand_var);
1957 480 : sub_var(&bound2_var, &bound1_var, &bound2_var);
1958 :
1959 480 : mul_var(&operand_var, count_var, &operand_var,
1960 480 : operand_var.dscale + count_var->dscale);
1961 480 : div_var(&operand_var, &bound2_var, result_var, 0, false);
1962 480 : add_var(result_var, &const_one, result_var);
1963 :
1964 480 : free_var(&bound1_var);
1965 480 : free_var(&bound2_var);
1966 480 : free_var(&operand_var);
1967 480 : }
1968 :
1969 : /* ----------------------------------------------------------------------
1970 : *
1971 : * Comparison functions
1972 : *
1973 : * Note: btree indexes need these routines not to leak memory; therefore,
1974 : * be careful to free working copies of toasted datums. Most places don't
1975 : * need to be so careful.
1976 : *
1977 : * Sort support:
1978 : *
1979 : * We implement the sortsupport strategy routine in order to get the benefit of
1980 : * abbreviation. The ordinary numeric comparison can be quite slow as a result
1981 : * of palloc/pfree cycles (due to detoasting packed values for alignment);
1982 : * while this could be worked on itself, the abbreviation strategy gives more
1983 : * speedup in many common cases.
1984 : *
1985 : * Two different representations are used for the abbreviated form, one in
1986 : * int32 and one in int64, whichever fits into a by-value Datum. In both cases
1987 : * the representation is negated relative to the original value, because we use
1988 : * the largest negative value for NaN, which sorts higher than other values. We
1989 : * convert the absolute value of the numeric to a 31-bit or 63-bit positive
1990 : * value, and then negate it if the original number was positive.
1991 : *
1992 : * We abort the abbreviation process if the abbreviation cardinality is below
1993 : * 0.01% of the row count (1 per 10k non-null rows). The actual break-even
1994 : * point is somewhat below that, perhaps 1 per 30k (at 1 per 100k there's a
1995 : * very small penalty), but we don't want to build up too many abbreviated
1996 : * values before first testing for abort, so we take the slightly pessimistic
1997 : * number. We make no attempt to estimate the cardinality of the real values,
1998 : * since it plays no part in the cost model here (if the abbreviation is equal,
1999 : * the cost of comparing equal and unequal underlying values is comparable).
2000 : * We discontinue even checking for abort (saving us the hashing overhead) if
2001 : * the estimated cardinality gets to 100k; that would be enough to support many
2002 : * billions of rows while doing no worse than breaking even.
2003 : *
2004 : * ----------------------------------------------------------------------
2005 : */
2006 :
2007 : /*
2008 : * Sort support strategy routine.
2009 : */
2010 : Datum
2011 972 : numeric_sortsupport(PG_FUNCTION_ARGS)
2012 : {
2013 972 : SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0);
2014 :
2015 972 : ssup->comparator = numeric_fast_cmp;
2016 :
2017 972 : if (ssup->abbreviate)
2018 : {
2019 : NumericSortSupport *nss;
2020 250 : MemoryContext oldcontext = MemoryContextSwitchTo(ssup->ssup_cxt);
2021 :
2022 250 : nss = palloc(sizeof(NumericSortSupport));
2023 :
2024 : /*
2025 : * palloc a buffer for handling unaligned packed values in addition to
2026 : * the support struct
2027 : */
2028 250 : nss->buf = palloc(VARATT_SHORT_MAX + VARHDRSZ + 1);
2029 :
2030 250 : nss->input_count = 0;
2031 250 : nss->estimating = true;
2032 250 : initHyperLogLog(&nss->abbr_card, 10);
2033 :
2034 250 : ssup->ssup_extra = nss;
2035 :
2036 250 : ssup->abbrev_full_comparator = ssup->comparator;
2037 250 : ssup->comparator = numeric_cmp_abbrev;
2038 250 : ssup->abbrev_converter = numeric_abbrev_convert;
2039 250 : ssup->abbrev_abort = numeric_abbrev_abort;
2040 :
2041 250 : MemoryContextSwitchTo(oldcontext);
2042 : }
2043 :
2044 972 : PG_RETURN_VOID();
2045 : }
2046 :
2047 : /*
2048 : * Abbreviate a numeric datum, handling NaNs and detoasting
2049 : * (must not leak memory!)
2050 : */
2051 : static Datum
2052 19132 : numeric_abbrev_convert(Datum original_datum, SortSupport ssup)
2053 : {
2054 19132 : NumericSortSupport *nss = ssup->ssup_extra;
2055 19132 : void *original_varatt = PG_DETOAST_DATUM_PACKED(original_datum);
2056 : Numeric value;
2057 : Datum result;
2058 :
2059 19132 : nss->input_count += 1;
2060 :
2061 : /*
2062 : * This is to handle packed datums without needing a palloc/pfree cycle;
2063 : * we keep and reuse a buffer large enough to handle any short datum.
2064 : */
2065 19132 : if (VARATT_IS_SHORT(original_varatt))
2066 : {
2067 1026 : void *buf = nss->buf;
2068 1026 : Size sz = VARSIZE_SHORT(original_varatt) - VARHDRSZ_SHORT;
2069 :
2070 : Assert(sz <= VARATT_SHORT_MAX - VARHDRSZ_SHORT);
2071 :
2072 1026 : SET_VARSIZE(buf, VARHDRSZ + sz);
2073 1026 : memcpy(VARDATA(buf), VARDATA_SHORT(original_varatt), sz);
2074 :
2075 1026 : value = (Numeric) buf;
2076 : }
2077 : else
2078 18106 : value = (Numeric) original_varatt;
2079 :
2080 19132 : if (NUMERIC_IS_SPECIAL(value))
2081 : {
2082 150 : if (NUMERIC_IS_PINF(value))
2083 48 : result = NUMERIC_ABBREV_PINF;
2084 102 : else if (NUMERIC_IS_NINF(value))
2085 48 : result = NUMERIC_ABBREV_NINF;
2086 : else
2087 54 : result = NUMERIC_ABBREV_NAN;
2088 : }
2089 : else
2090 : {
2091 : NumericVar var;
2092 :
2093 18982 : init_var_from_num(value, &var);
2094 :
2095 18982 : result = numeric_abbrev_convert_var(&var, nss);
2096 : }
2097 :
2098 : /* should happen only for external/compressed toasts */
2099 19132 : if ((Pointer) original_varatt != DatumGetPointer(original_datum))
2100 0 : pfree(original_varatt);
2101 :
2102 19132 : return result;
2103 : }
2104 :
2105 : /*
2106 : * Consider whether to abort abbreviation.
2107 : *
2108 : * We pay no attention to the cardinality of the non-abbreviated data. There is
2109 : * no reason to do so: unlike text, we have no fast check for equal values, so
2110 : * we pay the full overhead whenever the abbreviations are equal regardless of
2111 : * whether the underlying values are also equal.
2112 : */
2113 : static bool
2114 144 : numeric_abbrev_abort(int memtupcount, SortSupport ssup)
2115 : {
2116 144 : NumericSortSupport *nss = ssup->ssup_extra;
2117 : double abbr_card;
2118 :
2119 144 : if (memtupcount < 10000 || nss->input_count < 10000 || !nss->estimating)
2120 144 : return false;
2121 :
2122 0 : abbr_card = estimateHyperLogLog(&nss->abbr_card);
2123 :
2124 : /*
2125 : * If we have >100k distinct values, then even if we were sorting many
2126 : * billion rows we'd likely still break even, and the penalty of undoing
2127 : * that many rows of abbrevs would probably not be worth it. Stop even
2128 : * counting at that point.
2129 : */
2130 0 : if (abbr_card > 100000.0)
2131 : {
2132 0 : if (trace_sort)
2133 0 : elog(LOG,
2134 : "numeric_abbrev: estimation ends at cardinality %f"
2135 : " after " INT64_FORMAT " values (%d rows)",
2136 : abbr_card, nss->input_count, memtupcount);
2137 0 : nss->estimating = false;
2138 0 : return false;
2139 : }
2140 :
2141 : /*
2142 : * Target minimum cardinality is 1 per ~10k of non-null inputs. (The
2143 : * break even point is somewhere between one per 100k rows, where
2144 : * abbreviation has a very slight penalty, and 1 per 10k where it wins by
2145 : * a measurable percentage.) We use the relatively pessimistic 10k
2146 : * threshold, and add a 0.5 row fudge factor, because it allows us to
2147 : * abort earlier on genuinely pathological data where we've had exactly
2148 : * one abbreviated value in the first 10k (non-null) rows.
2149 : */
2150 0 : if (abbr_card < nss->input_count / 10000.0 + 0.5)
2151 : {
2152 0 : if (trace_sort)
2153 0 : elog(LOG,
2154 : "numeric_abbrev: aborting abbreviation at cardinality %f"
2155 : " below threshold %f after " INT64_FORMAT " values (%d rows)",
2156 : abbr_card, nss->input_count / 10000.0 + 0.5,
2157 : nss->input_count, memtupcount);
2158 0 : return true;
2159 : }
2160 :
2161 0 : if (trace_sort)
2162 0 : elog(LOG,
2163 : "numeric_abbrev: cardinality %f"
2164 : " after " INT64_FORMAT " values (%d rows)",
2165 : abbr_card, nss->input_count, memtupcount);
2166 :
2167 0 : return false;
2168 : }
2169 :
2170 : /*
2171 : * Non-fmgr interface to the comparison routine to allow sortsupport to elide
2172 : * the fmgr call. The saving here is small given how slow numeric comparisons
2173 : * are, but it is a required part of the sort support API when abbreviations
2174 : * are performed.
2175 : *
2176 : * Two palloc/pfree cycles could be saved here by using persistent buffers for
2177 : * aligning short-varlena inputs, but this has not so far been considered to
2178 : * be worth the effort.
2179 : */
2180 : static int
2181 4548024 : numeric_fast_cmp(Datum x, Datum y, SortSupport ssup)
2182 : {
2183 4548024 : Numeric nx = DatumGetNumeric(x);
2184 4548024 : Numeric ny = DatumGetNumeric(y);
2185 : int result;
2186 :
2187 4548024 : result = cmp_numerics(nx, ny);
2188 :
2189 4548024 : if ((Pointer) nx != DatumGetPointer(x))
2190 172830 : pfree(nx);
2191 4548024 : if ((Pointer) ny != DatumGetPointer(y))
2192 172824 : pfree(ny);
2193 :
2194 4548024 : return result;
2195 : }
2196 :
2197 : /*
2198 : * Compare abbreviations of values. (Abbreviations may be equal where the true
2199 : * values differ, but if the abbreviations differ, they must reflect the
2200 : * ordering of the true values.)
2201 : */
2202 : static int
2203 188672 : numeric_cmp_abbrev(Datum x, Datum y, SortSupport ssup)
2204 : {
2205 : /*
2206 : * NOTE WELL: this is intentionally backwards, because the abbreviation is
2207 : * negated relative to the original value, to handle NaN/infinity cases.
2208 : */
2209 188672 : if (DatumGetNumericAbbrev(x) < DatumGetNumericAbbrev(y))
2210 97436 : return 1;
2211 91236 : if (DatumGetNumericAbbrev(x) > DatumGetNumericAbbrev(y))
2212 91014 : return -1;
2213 222 : return 0;
2214 : }
2215 :
2216 : /*
2217 : * Abbreviate a NumericVar according to the available bit size.
2218 : *
2219 : * The 31-bit value is constructed as:
2220 : *
2221 : * 0 + 7bits digit weight + 24 bits digit value
2222 : *
2223 : * where the digit weight is in single decimal digits, not digit words, and
2224 : * stored in excess-44 representation[1]. The 24-bit digit value is the 7 most
2225 : * significant decimal digits of the value converted to binary. Values whose
2226 : * weights would fall outside the representable range are rounded off to zero
2227 : * (which is also used to represent actual zeros) or to 0x7FFFFFFF (which
2228 : * otherwise cannot occur). Abbreviation therefore fails to gain any advantage
2229 : * where values are outside the range 10^-44 to 10^83, which is not considered
2230 : * to be a serious limitation, or when values are of the same magnitude and
2231 : * equal in the first 7 decimal digits, which is considered to be an
2232 : * unavoidable limitation given the available bits. (Stealing three more bits
2233 : * to compare another digit would narrow the range of representable weights by
2234 : * a factor of 8, which starts to look like a real limiting factor.)
2235 : *
2236 : * (The value 44 for the excess is essentially arbitrary)
2237 : *
2238 : * The 63-bit value is constructed as:
2239 : *
2240 : * 0 + 7bits weight + 4 x 14-bit packed digit words
2241 : *
2242 : * The weight in this case is again stored in excess-44, but this time it is
2243 : * the original weight in digit words (i.e. powers of 10000). The first four
2244 : * digit words of the value (if present; trailing zeros are assumed as needed)
2245 : * are packed into 14 bits each to form the rest of the value. Again,
2246 : * out-of-range values are rounded off to 0 or 0x7FFFFFFFFFFFFFFF. The
2247 : * representable range in this case is 10^-176 to 10^332, which is considered
2248 : * to be good enough for all practical purposes, and comparison of 4 words
2249 : * means that at least 13 decimal digits are compared, which is considered to
2250 : * be a reasonable compromise between effectiveness and efficiency in computing
2251 : * the abbreviation.
2252 : *
2253 : * (The value 44 for the excess is even more arbitrary here, it was chosen just
2254 : * to match the value used in the 31-bit case)
2255 : *
2256 : * [1] - Excess-k representation means that the value is offset by adding 'k'
2257 : * and then treated as unsigned, so the smallest representable value is stored
2258 : * with all bits zero. This allows simple comparisons to work on the composite
2259 : * value.
2260 : */
2261 :
2262 : #if NUMERIC_ABBREV_BITS == 64
2263 :
2264 : static Datum
2265 18982 : numeric_abbrev_convert_var(const NumericVar *var, NumericSortSupport *nss)
2266 : {
2267 18982 : int ndigits = var->ndigits;
2268 18982 : int weight = var->weight;
2269 : int64 result;
2270 :
2271 18982 : if (ndigits == 0 || weight < -44)
2272 : {
2273 52 : result = 0;
2274 : }
2275 18930 : else if (weight > 83)
2276 : {
2277 12 : result = PG_INT64_MAX;
2278 : }
2279 : else
2280 : {
2281 18918 : result = ((int64) (weight + 44) << 56);
2282 :
2283 18918 : switch (ndigits)
2284 : {
2285 0 : default:
2286 0 : result |= ((int64) var->digits[3]);
2287 : /* FALLTHROUGH */
2288 6208 : case 3:
2289 6208 : result |= ((int64) var->digits[2]) << 14;
2290 : /* FALLTHROUGH */
2291 18304 : case 2:
2292 18304 : result |= ((int64) var->digits[1]) << 28;
2293 : /* FALLTHROUGH */
2294 18918 : case 1:
2295 18918 : result |= ((int64) var->digits[0]) << 42;
2296 18918 : break;
2297 : }
2298 : }
2299 :
2300 : /* the abbrev is negated relative to the original */
2301 18982 : if (var->sign == NUMERIC_POS)
2302 18884 : result = -result;
2303 :
2304 18982 : if (nss->estimating)
2305 : {
2306 18982 : uint32 tmp = ((uint32) result
2307 18982 : ^ (uint32) ((uint64) result >> 32));
2308 :
2309 18982 : addHyperLogLog(&nss->abbr_card, DatumGetUInt32(hash_uint32(tmp)));
2310 : }
2311 :
2312 18982 : return NumericAbbrevGetDatum(result);
2313 : }
2314 :
2315 : #endif /* NUMERIC_ABBREV_BITS == 64 */
2316 :
2317 : #if NUMERIC_ABBREV_BITS == 32
2318 :
2319 : static Datum
2320 : numeric_abbrev_convert_var(const NumericVar *var, NumericSortSupport *nss)
2321 : {
2322 : int ndigits = var->ndigits;
2323 : int weight = var->weight;
2324 : int32 result;
2325 :
2326 : if (ndigits == 0 || weight < -11)
2327 : {
2328 : result = 0;
2329 : }
2330 : else if (weight > 20)
2331 : {
2332 : result = PG_INT32_MAX;
2333 : }
2334 : else
2335 : {
2336 : NumericDigit nxt1 = (ndigits > 1) ? var->digits[1] : 0;
2337 :
2338 : weight = (weight + 11) * 4;
2339 :
2340 : result = var->digits[0];
2341 :
2342 : /*
2343 : * "result" now has 1 to 4 nonzero decimal digits. We pack in more
2344 : * digits to make 7 in total (largest we can fit in 24 bits)
2345 : */
2346 :
2347 : if (result > 999)
2348 : {
2349 : /* already have 4 digits, add 3 more */
2350 : result = (result * 1000) + (nxt1 / 10);
2351 : weight += 3;
2352 : }
2353 : else if (result > 99)
2354 : {
2355 : /* already have 3 digits, add 4 more */
2356 : result = (result * 10000) + nxt1;
2357 : weight += 2;
2358 : }
2359 : else if (result > 9)
2360 : {
2361 : NumericDigit nxt2 = (ndigits > 2) ? var->digits[2] : 0;
2362 :
2363 : /* already have 2 digits, add 5 more */
2364 : result = (result * 100000) + (nxt1 * 10) + (nxt2 / 1000);
2365 : weight += 1;
2366 : }
2367 : else
2368 : {
2369 : NumericDigit nxt2 = (ndigits > 2) ? var->digits[2] : 0;
2370 :
2371 : /* already have 1 digit, add 6 more */
2372 : result = (result * 1000000) + (nxt1 * 100) + (nxt2 / 100);
2373 : }
2374 :
2375 : result = result | (weight << 24);
2376 : }
2377 :
2378 : /* the abbrev is negated relative to the original */
2379 : if (var->sign == NUMERIC_POS)
2380 : result = -result;
2381 :
2382 : if (nss->estimating)
2383 : {
2384 : uint32 tmp = (uint32) result;
2385 :
2386 : addHyperLogLog(&nss->abbr_card, DatumGetUInt32(hash_uint32(tmp)));
2387 : }
2388 :
2389 : return NumericAbbrevGetDatum(result);
2390 : }
2391 :
2392 : #endif /* NUMERIC_ABBREV_BITS == 32 */
2393 :
2394 : /*
2395 : * Ordinary (non-sortsupport) comparisons follow.
2396 : */
2397 :
2398 : Datum
2399 768030 : numeric_cmp(PG_FUNCTION_ARGS)
2400 : {
2401 768030 : Numeric num1 = PG_GETARG_NUMERIC(0);
2402 768030 : Numeric num2 = PG_GETARG_NUMERIC(1);
2403 : int result;
2404 :
2405 768030 : result = cmp_numerics(num1, num2);
2406 :
2407 768030 : PG_FREE_IF_COPY(num1, 0);
2408 768030 : PG_FREE_IF_COPY(num2, 1);
2409 :
2410 768030 : PG_RETURN_INT32(result);
2411 : }
2412 :
2413 :
2414 : Datum
2415 624974 : numeric_eq(PG_FUNCTION_ARGS)
2416 : {
2417 624974 : Numeric num1 = PG_GETARG_NUMERIC(0);
2418 624974 : Numeric num2 = PG_GETARG_NUMERIC(1);
2419 : bool result;
2420 :
2421 624974 : result = cmp_numerics(num1, num2) == 0;
2422 :
2423 624974 : PG_FREE_IF_COPY(num1, 0);
2424 624974 : PG_FREE_IF_COPY(num2, 1);
2425 :
2426 624974 : PG_RETURN_BOOL(result);
2427 : }
2428 :
2429 : Datum
2430 5376 : numeric_ne(PG_FUNCTION_ARGS)
2431 : {
2432 5376 : Numeric num1 = PG_GETARG_NUMERIC(0);
2433 5376 : Numeric num2 = PG_GETARG_NUMERIC(1);
2434 : bool result;
2435 :
2436 5376 : result = cmp_numerics(num1, num2) != 0;
2437 :
2438 5376 : PG_FREE_IF_COPY(num1, 0);
2439 5376 : PG_FREE_IF_COPY(num2, 1);
2440 :
2441 5376 : PG_RETURN_BOOL(result);
2442 : }
2443 :
2444 : Datum
2445 61656 : numeric_gt(PG_FUNCTION_ARGS)
2446 : {
2447 61656 : Numeric num1 = PG_GETARG_NUMERIC(0);
2448 61656 : Numeric num2 = PG_GETARG_NUMERIC(1);
2449 : bool result;
2450 :
2451 61656 : result = cmp_numerics(num1, num2) > 0;
2452 :
2453 61656 : PG_FREE_IF_COPY(num1, 0);
2454 61656 : PG_FREE_IF_COPY(num2, 1);
2455 :
2456 61656 : PG_RETURN_BOOL(result);
2457 : }
2458 :
2459 : Datum
2460 15862 : numeric_ge(PG_FUNCTION_ARGS)
2461 : {
2462 15862 : Numeric num1 = PG_GETARG_NUMERIC(0);
2463 15862 : Numeric num2 = PG_GETARG_NUMERIC(1);
2464 : bool result;
2465 :
2466 15862 : result = cmp_numerics(num1, num2) >= 0;
2467 :
2468 15862 : PG_FREE_IF_COPY(num1, 0);
2469 15862 : PG_FREE_IF_COPY(num2, 1);
2470 :
2471 15862 : PG_RETURN_BOOL(result);
2472 : }
2473 :
2474 : Datum
2475 52182 : numeric_lt(PG_FUNCTION_ARGS)
2476 : {
2477 52182 : Numeric num1 = PG_GETARG_NUMERIC(0);
2478 52182 : Numeric num2 = PG_GETARG_NUMERIC(1);
2479 : bool result;
2480 :
2481 52182 : result = cmp_numerics(num1, num2) < 0;
2482 :
2483 52182 : PG_FREE_IF_COPY(num1, 0);
2484 52182 : PG_FREE_IF_COPY(num2, 1);
2485 :
2486 52182 : PG_RETURN_BOOL(result);
2487 : }
2488 :
2489 : Datum
2490 14594 : numeric_le(PG_FUNCTION_ARGS)
2491 : {
2492 14594 : Numeric num1 = PG_GETARG_NUMERIC(0);
2493 14594 : Numeric num2 = PG_GETARG_NUMERIC(1);
2494 : bool result;
2495 :
2496 14594 : result = cmp_numerics(num1, num2) <= 0;
2497 :
2498 14594 : PG_FREE_IF_COPY(num1, 0);
2499 14594 : PG_FREE_IF_COPY(num2, 1);
2500 :
2501 14594 : PG_RETURN_BOOL(result);
2502 : }
2503 :
2504 : static int
2505 6112220 : cmp_numerics(Numeric num1, Numeric num2)
2506 : {
2507 : int result;
2508 :
2509 : /*
2510 : * We consider all NANs to be equal and larger than any non-NAN (including
2511 : * Infinity). This is somewhat arbitrary; the important thing is to have
2512 : * a consistent sort order.
2513 : */
2514 6112220 : if (NUMERIC_IS_SPECIAL(num1))
2515 : {
2516 8830 : if (NUMERIC_IS_NAN(num1))
2517 : {
2518 8740 : if (NUMERIC_IS_NAN(num2))
2519 1128 : result = 0; /* NAN = NAN */
2520 : else
2521 7612 : result = 1; /* NAN > non-NAN */
2522 : }
2523 90 : else if (NUMERIC_IS_PINF(num1))
2524 : {
2525 72 : if (NUMERIC_IS_NAN(num2))
2526 0 : result = -1; /* PINF < NAN */
2527 72 : else if (NUMERIC_IS_PINF(num2))
2528 6 : result = 0; /* PINF = PINF */
2529 : else
2530 66 : result = 1; /* PINF > anything else */
2531 : }
2532 : else /* num1 must be NINF */
2533 : {
2534 18 : if (NUMERIC_IS_NINF(num2))
2535 6 : result = 0; /* NINF = NINF */
2536 : else
2537 12 : result = -1; /* NINF < anything else */
2538 : }
2539 : }
2540 6103390 : else if (NUMERIC_IS_SPECIAL(num2))
2541 : {
2542 11230 : if (NUMERIC_IS_NINF(num2))
2543 12 : result = 1; /* normal > NINF */
2544 : else
2545 11218 : result = -1; /* normal < NAN or PINF */
2546 : }
2547 : else
2548 : {
2549 12186500 : result = cmp_var_common(NUMERIC_DIGITS(num1), NUMERIC_NDIGITS(num1),
2550 6093576 : NUMERIC_WEIGHT(num1), NUMERIC_SIGN(num1),
2551 6092160 : NUMERIC_DIGITS(num2), NUMERIC_NDIGITS(num2),
2552 6092924 : NUMERIC_WEIGHT(num2), NUMERIC_SIGN(num2));
2553 : }
2554 :
2555 6112220 : return result;
2556 : }
2557 :
2558 : /*
2559 : * in_range support function for numeric.
2560 : */
2561 : Datum
2562 1152 : in_range_numeric_numeric(PG_FUNCTION_ARGS)
2563 : {
2564 1152 : Numeric val = PG_GETARG_NUMERIC(0);
2565 1152 : Numeric base = PG_GETARG_NUMERIC(1);
2566 1152 : Numeric offset = PG_GETARG_NUMERIC(2);
2567 1152 : bool sub = PG_GETARG_BOOL(3);
2568 1152 : bool less = PG_GETARG_BOOL(4);
2569 : bool result;
2570 :
2571 : /*
2572 : * Reject negative (including -Inf) or NaN offset. Negative is per spec,
2573 : * and NaN is because appropriate semantics for that seem non-obvious.
2574 : */
2575 1152 : if (NUMERIC_IS_NAN(offset) ||
2576 1146 : NUMERIC_IS_NINF(offset) ||
2577 1146 : NUMERIC_SIGN(offset) == NUMERIC_NEG)
2578 6 : ereport(ERROR,
2579 : (errcode(ERRCODE_INVALID_PRECEDING_OR_FOLLOWING_SIZE),
2580 : errmsg("invalid preceding or following size in window function")));
2581 :
2582 : /*
2583 : * Deal with cases where val and/or base is NaN, following the rule that
2584 : * NaN sorts after non-NaN (cf cmp_numerics). The offset cannot affect
2585 : * the conclusion.
2586 : */
2587 1146 : if (NUMERIC_IS_NAN(val))
2588 : {
2589 186 : if (NUMERIC_IS_NAN(base))
2590 60 : result = true; /* NAN = NAN */
2591 : else
2592 126 : result = !less; /* NAN > non-NAN */
2593 : }
2594 960 : else if (NUMERIC_IS_NAN(base))
2595 : {
2596 126 : result = less; /* non-NAN < NAN */
2597 : }
2598 :
2599 : /*
2600 : * Deal with infinite offset (necessarily +Inf, at this point).
2601 : */
2602 834 : else if (NUMERIC_IS_SPECIAL(offset))
2603 : {
2604 : Assert(NUMERIC_IS_PINF(offset));
2605 420 : if (sub ? NUMERIC_IS_PINF(base) : NUMERIC_IS_NINF(base))
2606 : {
2607 : /*
2608 : * base +/- offset would produce NaN, so return true for any val
2609 : * (see in_range_float8_float8() for reasoning).
2610 : */
2611 174 : result = true;
2612 : }
2613 246 : else if (sub)
2614 : {
2615 : /* base - offset must be -inf */
2616 150 : if (less)
2617 54 : result = NUMERIC_IS_NINF(val); /* only -inf is <= sum */
2618 : else
2619 96 : result = true; /* any val is >= sum */
2620 : }
2621 : else
2622 : {
2623 : /* base + offset must be +inf */
2624 96 : if (less)
2625 0 : result = true; /* any val is <= sum */
2626 : else
2627 96 : result = NUMERIC_IS_PINF(val); /* only +inf is >= sum */
2628 : }
2629 : }
2630 :
2631 : /*
2632 : * Deal with cases where val and/or base is infinite. The offset, being
2633 : * now known finite, cannot affect the conclusion.
2634 : */
2635 414 : else if (NUMERIC_IS_SPECIAL(val))
2636 : {
2637 78 : if (NUMERIC_IS_PINF(val))
2638 : {
2639 36 : if (NUMERIC_IS_PINF(base))
2640 24 : result = true; /* PINF = PINF */
2641 : else
2642 12 : result = !less; /* PINF > any other non-NAN */
2643 : }
2644 : else /* val must be NINF */
2645 : {
2646 42 : if (NUMERIC_IS_NINF(base))
2647 30 : result = true; /* NINF = NINF */
2648 : else
2649 12 : result = less; /* NINF < anything else */
2650 : }
2651 : }
2652 336 : else if (NUMERIC_IS_SPECIAL(base))
2653 : {
2654 24 : if (NUMERIC_IS_NINF(base))
2655 12 : result = !less; /* normal > NINF */
2656 : else
2657 12 : result = less; /* normal < PINF */
2658 : }
2659 : else
2660 : {
2661 : /*
2662 : * Otherwise go ahead and compute base +/- offset. While it's
2663 : * possible for this to overflow the numeric format, it's unlikely
2664 : * enough that we don't take measures to prevent it.
2665 : */
2666 : NumericVar valv;
2667 : NumericVar basev;
2668 : NumericVar offsetv;
2669 : NumericVar sum;
2670 :
2671 312 : init_var_from_num(val, &valv);
2672 312 : init_var_from_num(base, &basev);
2673 312 : init_var_from_num(offset, &offsetv);
2674 312 : init_var(&sum);
2675 :
2676 312 : if (sub)
2677 156 : sub_var(&basev, &offsetv, &sum);
2678 : else
2679 156 : add_var(&basev, &offsetv, &sum);
2680 :
2681 312 : if (less)
2682 156 : result = (cmp_var(&valv, &sum) <= 0);
2683 : else
2684 156 : result = (cmp_var(&valv, &sum) >= 0);
2685 :
2686 312 : free_var(&sum);
2687 : }
2688 :
2689 1146 : PG_FREE_IF_COPY(val, 0);
2690 1146 : PG_FREE_IF_COPY(base, 1);
2691 1146 : PG_FREE_IF_COPY(offset, 2);
2692 :
2693 1146 : PG_RETURN_BOOL(result);
2694 : }
2695 :
2696 : Datum
2697 607512 : hash_numeric(PG_FUNCTION_ARGS)
2698 : {
2699 607512 : Numeric key = PG_GETARG_NUMERIC(0);
2700 : Datum digit_hash;
2701 : Datum result;
2702 : int weight;
2703 : int start_offset;
2704 : int end_offset;
2705 : int i;
2706 : int hash_len;
2707 : NumericDigit *digits;
2708 :
2709 : /* If it's NaN or infinity, don't try to hash the rest of the fields */
2710 607512 : if (NUMERIC_IS_SPECIAL(key))
2711 0 : PG_RETURN_UINT32(0);
2712 :
2713 607512 : weight = NUMERIC_WEIGHT(key);
2714 607512 : start_offset = 0;
2715 607512 : end_offset = 0;
2716 :
2717 : /*
2718 : * Omit any leading or trailing zeros from the input to the hash. The
2719 : * numeric implementation *should* guarantee that leading and trailing
2720 : * zeros are suppressed, but we're paranoid. Note that we measure the
2721 : * starting and ending offsets in units of NumericDigits, not bytes.
2722 : */
2723 607512 : digits = NUMERIC_DIGITS(key);
2724 607512 : for (i = 0; i < NUMERIC_NDIGITS(key); i++)
2725 : {
2726 605884 : if (digits[i] != (NumericDigit) 0)
2727 605884 : break;
2728 :
2729 0 : start_offset++;
2730 :
2731 : /*
2732 : * The weight is effectively the # of digits before the decimal point,
2733 : * so decrement it for each leading zero we skip.
2734 : */
2735 0 : weight--;
2736 : }
2737 :
2738 : /*
2739 : * If there are no non-zero digits, then the value of the number is zero,
2740 : * regardless of any other fields.
2741 : */
2742 607512 : if (NUMERIC_NDIGITS(key) == start_offset)
2743 1628 : PG_RETURN_UINT32(-1);
2744 :
2745 605884 : for (i = NUMERIC_NDIGITS(key) - 1; i >= 0; i--)
2746 : {
2747 605884 : if (digits[i] != (NumericDigit) 0)
2748 605884 : break;
2749 :
2750 0 : end_offset++;
2751 : }
2752 :
2753 : /* If we get here, there should be at least one non-zero digit */
2754 : Assert(start_offset + end_offset < NUMERIC_NDIGITS(key));
2755 :
2756 : /*
2757 : * Note that we don't hash on the Numeric's scale, since two numerics can
2758 : * compare equal but have different scales. We also don't hash on the
2759 : * sign, although we could: since a sign difference implies inequality,
2760 : * this shouldn't affect correctness.
2761 : */
2762 605884 : hash_len = NUMERIC_NDIGITS(key) - start_offset - end_offset;
2763 605884 : digit_hash = hash_any((unsigned char *) (NUMERIC_DIGITS(key) + start_offset),
2764 : hash_len * sizeof(NumericDigit));
2765 :
2766 : /* Mix in the weight, via XOR */
2767 605884 : result = digit_hash ^ weight;
2768 :
2769 605884 : PG_RETURN_DATUM(result);
2770 : }
2771 :
2772 : /*
2773 : * Returns 64-bit value by hashing a value to a 64-bit value, with a seed.
2774 : * Otherwise, similar to hash_numeric.
2775 : */
2776 : Datum
2777 84 : hash_numeric_extended(PG_FUNCTION_ARGS)
2778 : {
2779 84 : Numeric key = PG_GETARG_NUMERIC(0);
2780 84 : uint64 seed = PG_GETARG_INT64(1);
2781 : Datum digit_hash;
2782 : Datum result;
2783 : int weight;
2784 : int start_offset;
2785 : int end_offset;
2786 : int i;
2787 : int hash_len;
2788 : NumericDigit *digits;
2789 :
2790 : /* If it's NaN or infinity, don't try to hash the rest of the fields */
2791 84 : if (NUMERIC_IS_SPECIAL(key))
2792 0 : PG_RETURN_UINT64(seed);
2793 :
2794 84 : weight = NUMERIC_WEIGHT(key);
2795 84 : start_offset = 0;
2796 84 : end_offset = 0;
2797 :
2798 84 : digits = NUMERIC_DIGITS(key);
2799 84 : for (i = 0; i < NUMERIC_NDIGITS(key); i++)
2800 : {
2801 72 : if (digits[i] != (NumericDigit) 0)
2802 72 : break;
2803 :
2804 0 : start_offset++;
2805 :
2806 0 : weight--;
2807 : }
2808 :
2809 84 : if (NUMERIC_NDIGITS(key) == start_offset)
2810 12 : PG_RETURN_UINT64(seed - 1);
2811 :
2812 72 : for (i = NUMERIC_NDIGITS(key) - 1; i >= 0; i--)
2813 : {
2814 72 : if (digits[i] != (NumericDigit) 0)
2815 72 : break;
2816 :
2817 0 : end_offset++;
2818 : }
2819 :
2820 : Assert(start_offset + end_offset < NUMERIC_NDIGITS(key));
2821 :
2822 72 : hash_len = NUMERIC_NDIGITS(key) - start_offset - end_offset;
2823 72 : digit_hash = hash_any_extended((unsigned char *) (NUMERIC_DIGITS(key)
2824 72 : + start_offset),
2825 : hash_len * sizeof(NumericDigit),
2826 : seed);
2827 :
2828 72 : result = UInt64GetDatum(DatumGetUInt64(digit_hash) ^ weight);
2829 :
2830 72 : PG_RETURN_DATUM(result);
2831 : }
2832 :
2833 :
2834 : /* ----------------------------------------------------------------------
2835 : *
2836 : * Basic arithmetic functions
2837 : *
2838 : * ----------------------------------------------------------------------
2839 : */
2840 :
2841 :
2842 : /*
2843 : * numeric_add() -
2844 : *
2845 : * Add two numerics
2846 : */
2847 : Datum
2848 251996 : numeric_add(PG_FUNCTION_ARGS)
2849 : {
2850 251996 : Numeric num1 = PG_GETARG_NUMERIC(0);
2851 251996 : Numeric num2 = PG_GETARG_NUMERIC(1);
2852 : Numeric res;
2853 :
2854 251996 : res = numeric_add_opt_error(num1, num2, NULL);
2855 :
2856 251996 : PG_RETURN_NUMERIC(res);
2857 : }
2858 :
2859 : /*
2860 : * numeric_add_opt_error() -
2861 : *
2862 : * Internal version of numeric_add(). If "*have_error" flag is provided,
2863 : * on error it's set to true, NULL returned. This is helpful when caller
2864 : * need to handle errors by itself.
2865 : */
2866 : Numeric
2867 253034 : numeric_add_opt_error(Numeric num1, Numeric num2, bool *have_error)
2868 : {
2869 : NumericVar arg1;
2870 : NumericVar arg2;
2871 : NumericVar result;
2872 : Numeric res;
2873 :
2874 : /*
2875 : * Handle NaN and infinities
2876 : */
2877 253034 : if (NUMERIC_IS_SPECIAL(num1) || NUMERIC_IS_SPECIAL(num2))
2878 : {
2879 198 : if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
2880 78 : return make_result(&const_nan);
2881 120 : if (NUMERIC_IS_PINF(num1))
2882 : {
2883 36 : if (NUMERIC_IS_NINF(num2))
2884 6 : return make_result(&const_nan); /* Inf + -Inf */
2885 : else
2886 30 : return make_result(&const_pinf);
2887 : }
2888 84 : if (NUMERIC_IS_NINF(num1))
2889 : {
2890 36 : if (NUMERIC_IS_PINF(num2))
2891 6 : return make_result(&const_nan); /* -Inf + Inf */
2892 : else
2893 30 : return make_result(&const_ninf);
2894 : }
2895 : /* by here, num1 must be finite, so num2 is not */
2896 48 : if (NUMERIC_IS_PINF(num2))
2897 24 : return make_result(&const_pinf);
2898 : Assert(NUMERIC_IS_NINF(num2));
2899 24 : return make_result(&const_ninf);
2900 : }
2901 :
2902 : /*
2903 : * Unpack the values, let add_var() compute the result and return it.
2904 : */
2905 252836 : init_var_from_num(num1, &arg1);
2906 252836 : init_var_from_num(num2, &arg2);
2907 :
2908 252836 : init_var(&result);
2909 252836 : add_var(&arg1, &arg2, &result);
2910 :
2911 252836 : res = make_result_opt_error(&result, have_error);
2912 :
2913 252836 : free_var(&result);
2914 :
2915 252836 : return res;
2916 : }
2917 :
2918 :
2919 : /*
2920 : * numeric_sub() -
2921 : *
2922 : * Subtract one numeric from another
2923 : */
2924 : Datum
2925 95738 : numeric_sub(PG_FUNCTION_ARGS)
2926 : {
2927 95738 : Numeric num1 = PG_GETARG_NUMERIC(0);
2928 95738 : Numeric num2 = PG_GETARG_NUMERIC(1);
2929 : Numeric res;
2930 :
2931 95738 : res = numeric_sub_opt_error(num1, num2, NULL);
2932 :
2933 95738 : PG_RETURN_NUMERIC(res);
2934 : }
2935 :
2936 :
2937 : /*
2938 : * numeric_sub_opt_error() -
2939 : *
2940 : * Internal version of numeric_sub(). If "*have_error" flag is provided,
2941 : * on error it's set to true, NULL returned. This is helpful when caller
2942 : * need to handle errors by itself.
2943 : */
2944 : Numeric
2945 95888 : numeric_sub_opt_error(Numeric num1, Numeric num2, bool *have_error)
2946 : {
2947 : NumericVar arg1;
2948 : NumericVar arg2;
2949 : NumericVar result;
2950 : Numeric res;
2951 :
2952 : /*
2953 : * Handle NaN and infinities
2954 : */
2955 95888 : if (NUMERIC_IS_SPECIAL(num1) || NUMERIC_IS_SPECIAL(num2))
2956 : {
2957 3184 : if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
2958 3064 : return make_result(&const_nan);
2959 120 : if (NUMERIC_IS_PINF(num1))
2960 : {
2961 36 : if (NUMERIC_IS_PINF(num2))
2962 6 : return make_result(&const_nan); /* Inf - Inf */
2963 : else
2964 30 : return make_result(&const_pinf);
2965 : }
2966 84 : if (NUMERIC_IS_NINF(num1))
2967 : {
2968 36 : if (NUMERIC_IS_NINF(num2))
2969 6 : return make_result(&const_nan); /* -Inf - -Inf */
2970 : else
2971 30 : return make_result(&const_ninf);
2972 : }
2973 : /* by here, num1 must be finite, so num2 is not */
2974 48 : if (NUMERIC_IS_PINF(num2))
2975 24 : return make_result(&const_ninf);
2976 : Assert(NUMERIC_IS_NINF(num2));
2977 24 : return make_result(&const_pinf);
2978 : }
2979 :
2980 : /*
2981 : * Unpack the values, let sub_var() compute the result and return it.
2982 : */
2983 92704 : init_var_from_num(num1, &arg1);
2984 92704 : init_var_from_num(num2, &arg2);
2985 :
2986 92704 : init_var(&result);
2987 92704 : sub_var(&arg1, &arg2, &result);
2988 :
2989 92704 : res = make_result_opt_error(&result, have_error);
2990 :
2991 92704 : free_var(&result);
2992 :
2993 92704 : return res;
2994 : }
2995 :
2996 :
2997 : /*
2998 : * numeric_mul() -
2999 : *
3000 : * Calculate the product of two numerics
3001 : */
3002 : Datum
3003 489686 : numeric_mul(PG_FUNCTION_ARGS)
3004 : {
3005 489686 : Numeric num1 = PG_GETARG_NUMERIC(0);
3006 489686 : Numeric num2 = PG_GETARG_NUMERIC(1);
3007 : Numeric res;
3008 :
3009 489686 : res = numeric_mul_opt_error(num1, num2, NULL);
3010 :
3011 489686 : PG_RETURN_NUMERIC(res);
3012 : }
3013 :
3014 :
3015 : /*
3016 : * numeric_mul_opt_error() -
3017 : *
3018 : * Internal version of numeric_mul(). If "*have_error" flag is provided,
3019 : * on error it's set to true, NULL returned. This is helpful when caller
3020 : * need to handle errors by itself.
3021 : */
3022 : Numeric
3023 489722 : numeric_mul_opt_error(Numeric num1, Numeric num2, bool *have_error)
3024 : {
3025 : NumericVar arg1;
3026 : NumericVar arg2;
3027 : NumericVar result;
3028 : Numeric res;
3029 :
3030 : /*
3031 : * Handle NaN and infinities
3032 : */
3033 489722 : if (NUMERIC_IS_SPECIAL(num1) || NUMERIC_IS_SPECIAL(num2))
3034 : {
3035 198 : if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
3036 78 : return make_result(&const_nan);
3037 120 : if (NUMERIC_IS_PINF(num1))
3038 : {
3039 36 : switch (numeric_sign_internal(num2))
3040 : {
3041 6 : case 0:
3042 6 : return make_result(&const_nan); /* Inf * 0 */
3043 18 : case 1:
3044 18 : return make_result(&const_pinf);
3045 12 : case -1:
3046 12 : return make_result(&const_ninf);
3047 : }
3048 : Assert(false);
3049 : }
3050 84 : if (NUMERIC_IS_NINF(num1))
3051 : {
3052 36 : switch (numeric_sign_internal(num2))
3053 : {
3054 6 : case 0:
3055 6 : return make_result(&const_nan); /* -Inf * 0 */
3056 18 : case 1:
3057 18 : return make_result(&const_ninf);
3058 12 : case -1:
3059 12 : return make_result(&const_pinf);
3060 : }
3061 : Assert(false);
3062 : }
3063 : /* by here, num1 must be finite, so num2 is not */
3064 48 : if (NUMERIC_IS_PINF(num2))
3065 : {
3066 24 : switch (numeric_sign_internal(num1))
3067 : {
3068 6 : case 0:
3069 6 : return make_result(&const_nan); /* 0 * Inf */
3070 12 : case 1:
3071 12 : return make_result(&const_pinf);
3072 6 : case -1:
3073 6 : return make_result(&const_ninf);
3074 : }
3075 : Assert(false);
3076 : }
3077 : Assert(NUMERIC_IS_NINF(num2));
3078 24 : switch (numeric_sign_internal(num1))
3079 : {
3080 6 : case 0:
3081 6 : return make_result(&const_nan); /* 0 * -Inf */
3082 12 : case 1:
3083 12 : return make_result(&const_ninf);
3084 6 : case -1:
3085 6 : return make_result(&const_pinf);
3086 : }
3087 : Assert(false);
3088 : }
3089 :
3090 : /*
3091 : * Unpack the values, let mul_var() compute the result and return it.
3092 : * Unlike add_var() and sub_var(), mul_var() will round its result. In the
3093 : * case of numeric_mul(), which is invoked for the * operator on numerics,
3094 : * we request exact representation for the product (rscale = sum(dscale of
3095 : * arg1, dscale of arg2)). If the exact result has more digits after the
3096 : * decimal point than can be stored in a numeric, we round it. Rounding
3097 : * after computing the exact result ensures that the final result is
3098 : * correctly rounded (rounding in mul_var() using a truncated product
3099 : * would not guarantee this).
3100 : */
3101 489524 : init_var_from_num(num1, &arg1);
3102 489524 : init_var_from_num(num2, &arg2);
3103 :
3104 489524 : init_var(&result);
3105 489524 : mul_var(&arg1, &arg2, &result, arg1.dscale + arg2.dscale);
3106 :
3107 489524 : if (result.dscale > NUMERIC_DSCALE_MAX)
3108 6 : round_var(&result, NUMERIC_DSCALE_MAX);
3109 :
3110 489524 : res = make_result_opt_error(&result, have_error);
3111 :
3112 489524 : free_var(&result);
3113 :
3114 489524 : return res;
3115 : }
3116 :
3117 :
3118 : /*
3119 : * numeric_div() -
3120 : *
3121 : * Divide one numeric into another
3122 : */
3123 : Datum
3124 152350 : numeric_div(PG_FUNCTION_ARGS)
3125 : {
3126 152350 : Numeric num1 = PG_GETARG_NUMERIC(0);
3127 152350 : Numeric num2 = PG_GETARG_NUMERIC(1);
3128 : Numeric res;
3129 :
3130 152350 : res = numeric_div_opt_error(num1, num2, NULL);
3131 :
3132 152318 : PG_RETURN_NUMERIC(res);
3133 : }
3134 :
3135 :
3136 : /*
3137 : * numeric_div_opt_error() -
3138 : *
3139 : * Internal version of numeric_div(). If "*have_error" flag is provided,
3140 : * on error it's set to true, NULL returned. This is helpful when caller
3141 : * need to handle errors by itself.
3142 : */
3143 : Numeric
3144 153190 : numeric_div_opt_error(Numeric num1, Numeric num2, bool *have_error)
3145 : {
3146 : NumericVar arg1;
3147 : NumericVar arg2;
3148 : NumericVar result;
3149 : Numeric res;
3150 : int rscale;
3151 :
3152 153190 : if (have_error)
3153 48 : *have_error = false;
3154 :
3155 : /*
3156 : * Handle NaN and infinities
3157 : */
3158 153190 : if (NUMERIC_IS_SPECIAL(num1) || NUMERIC_IS_SPECIAL(num2))
3159 : {
3160 198 : if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
3161 78 : return make_result(&const_nan);
3162 120 : if (NUMERIC_IS_PINF(num1))
3163 : {
3164 36 : if (NUMERIC_IS_SPECIAL(num2))
3165 12 : return make_result(&const_nan); /* Inf / [-]Inf */
3166 24 : switch (numeric_sign_internal(num2))
3167 : {
3168 6 : case 0:
3169 6 : if (have_error)
3170 : {
3171 0 : *have_error = true;
3172 0 : return NULL;
3173 : }
3174 6 : ereport(ERROR,
3175 : (errcode(ERRCODE_DIVISION_BY_ZERO),
3176 : errmsg("division by zero")));
3177 : break;
3178 12 : case 1:
3179 12 : return make_result(&const_pinf);
3180 6 : case -1:
3181 6 : return make_result(&const_ninf);
3182 : }
3183 84 : Assert(false);
3184 : }
3185 84 : if (NUMERIC_IS_NINF(num1))
3186 : {
3187 36 : if (NUMERIC_IS_SPECIAL(num2))
3188 12 : return make_result(&const_nan); /* -Inf / [-]Inf */
3189 24 : switch (numeric_sign_internal(num2))
3190 : {
3191 6 : case 0:
3192 6 : if (have_error)
3193 : {
3194 0 : *have_error = true;
3195 0 : return NULL;
3196 : }
3197 6 : ereport(ERROR,
3198 : (errcode(ERRCODE_DIVISION_BY_ZERO),
3199 : errmsg("division by zero")));
3200 : break;
3201 12 : case 1:
3202 12 : return make_result(&const_ninf);
3203 6 : case -1:
3204 6 : return make_result(&const_pinf);
3205 : }
3206 48 : Assert(false);
3207 : }
3208 : /* by here, num1 must be finite, so num2 is not */
3209 :
3210 : /*
3211 : * POSIX would have us return zero or minus zero if num1 is zero, and
3212 : * otherwise throw an underflow error. But the numeric type doesn't
3213 : * really do underflow, so let's just return zero.
3214 : */
3215 48 : return make_result(&const_zero);
3216 : }
3217 :
3218 : /*
3219 : * Unpack the arguments
3220 : */
3221 152992 : init_var_from_num(num1, &arg1);
3222 152992 : init_var_from_num(num2, &arg2);
3223 :
3224 152992 : init_var(&result);
3225 :
3226 : /*
3227 : * Select scale for division result
3228 : */
3229 152992 : rscale = select_div_scale(&arg1, &arg2);
3230 :
3231 : /*
3232 : * If "have_error" is provided, check for division by zero here
3233 : */
3234 152992 : if (have_error && (arg2.ndigits == 0 || arg2.digits[0] == 0))
3235 : {
3236 12 : *have_error = true;
3237 12 : return NULL;
3238 : }
3239 :
3240 : /*
3241 : * Do the divide and return the result
3242 : */
3243 152980 : div_var(&arg1, &arg2, &result, rscale, true);
3244 :
3245 152942 : res = make_result_opt_error(&result, have_error);
3246 :
3247 152942 : free_var(&result);
3248 :
3249 152942 : return res;
3250 : }
3251 :
3252 :
3253 : /*
3254 : * numeric_div_trunc() -
3255 : *
3256 : * Divide one numeric into another, truncating the result to an integer
3257 : */
3258 : Datum
3259 1200 : numeric_div_trunc(PG_FUNCTION_ARGS)
3260 : {
3261 1200 : Numeric num1 = PG_GETARG_NUMERIC(0);
3262 1200 : Numeric num2 = PG_GETARG_NUMERIC(1);
3263 : NumericVar arg1;
3264 : NumericVar arg2;
3265 : NumericVar result;
3266 : Numeric res;
3267 :
3268 : /*
3269 : * Handle NaN and infinities
3270 : */
3271 1200 : if (NUMERIC_IS_SPECIAL(num1) || NUMERIC_IS_SPECIAL(num2))
3272 : {
3273 198 : if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
3274 78 : PG_RETURN_NUMERIC(make_result(&const_nan));
3275 120 : if (NUMERIC_IS_PINF(num1))
3276 : {
3277 36 : if (NUMERIC_IS_SPECIAL(num2))
3278 12 : PG_RETURN_NUMERIC(make_result(&const_nan)); /* Inf / [-]Inf */
3279 24 : switch (numeric_sign_internal(num2))
3280 : {
3281 6 : case 0:
3282 6 : ereport(ERROR,
3283 : (errcode(ERRCODE_DIVISION_BY_ZERO),
3284 : errmsg("division by zero")));
3285 : break;
3286 12 : case 1:
3287 12 : PG_RETURN_NUMERIC(make_result(&const_pinf));
3288 6 : case -1:
3289 6 : PG_RETURN_NUMERIC(make_result(&const_ninf));
3290 : }
3291 84 : Assert(false);
3292 : }
3293 84 : if (NUMERIC_IS_NINF(num1))
3294 : {
3295 36 : if (NUMERIC_IS_SPECIAL(num2))
3296 12 : PG_RETURN_NUMERIC(make_result(&const_nan)); /* -Inf / [-]Inf */
3297 24 : switch (numeric_sign_internal(num2))
3298 : {
3299 6 : case 0:
3300 6 : ereport(ERROR,
3301 : (errcode(ERRCODE_DIVISION_BY_ZERO),
3302 : errmsg("division by zero")));
3303 : break;
3304 12 : case 1:
3305 12 : PG_RETURN_NUMERIC(make_result(&const_ninf));
3306 6 : case -1:
3307 6 : PG_RETURN_NUMERIC(make_result(&const_pinf));
3308 : }
3309 48 : Assert(false);
3310 : }
3311 : /* by here, num1 must be finite, so num2 is not */
3312 :
3313 : /*
3314 : * POSIX would have us return zero or minus zero if num1 is zero, and
3315 : * otherwise throw an underflow error. But the numeric type doesn't
3316 : * really do underflow, so let's just return zero.
3317 : */
3318 48 : PG_RETURN_NUMERIC(make_result(&const_zero));
3319 : }
3320 :
3321 : /*
3322 : * Unpack the arguments
3323 : */
3324 1002 : init_var_from_num(num1, &arg1);
3325 1002 : init_var_from_num(num2, &arg2);
3326 :
3327 1002 : init_var(&result);
3328 :
3329 : /*
3330 : * Do the divide and return the result
3331 : */
3332 1002 : div_var(&arg1, &arg2, &result, 0, false);
3333 :
3334 996 : res = make_result(&result);
3335 :
3336 996 : free_var(&result);
3337 :
3338 996 : PG_RETURN_NUMERIC(res);
3339 : }
3340 :
3341 :
3342 : /*
3343 : * numeric_mod() -
3344 : *
3345 : * Calculate the modulo of two numerics
3346 : */
3347 : Datum
3348 54204 : numeric_mod(PG_FUNCTION_ARGS)
3349 : {
3350 54204 : Numeric num1 = PG_GETARG_NUMERIC(0);
3351 54204 : Numeric num2 = PG_GETARG_NUMERIC(1);
3352 : Numeric res;
3353 :
3354 54204 : res = numeric_mod_opt_error(num1, num2, NULL);
3355 :
3356 54186 : PG_RETURN_NUMERIC(res);
3357 : }
3358 :
3359 :
3360 : /*
3361 : * numeric_mod_opt_error() -
3362 : *
3363 : * Internal version of numeric_mod(). If "*have_error" flag is provided,
3364 : * on error it's set to true, NULL returned. This is helpful when caller
3365 : * need to handle errors by itself.
3366 : */
3367 : Numeric
3368 54216 : numeric_mod_opt_error(Numeric num1, Numeric num2, bool *have_error)
3369 : {
3370 : Numeric res;
3371 : NumericVar arg1;
3372 : NumericVar arg2;
3373 : NumericVar result;
3374 :
3375 54216 : if (have_error)
3376 0 : *have_error = false;
3377 :
3378 : /*
3379 : * Handle NaN and infinities. We follow POSIX fmod() on this, except that
3380 : * POSIX treats x-is-infinite and y-is-zero identically, raising EDOM and
3381 : * returning NaN. We choose to throw error only for y-is-zero.
3382 : */
3383 54216 : if (NUMERIC_IS_SPECIAL(num1) || NUMERIC_IS_SPECIAL(num2))
3384 : {
3385 198 : if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
3386 78 : return make_result(&const_nan);
3387 120 : if (NUMERIC_IS_INF(num1))
3388 : {
3389 72 : if (numeric_sign_internal(num2) == 0)
3390 : {
3391 12 : if (have_error)
3392 : {
3393 0 : *have_error = true;
3394 0 : return NULL;
3395 : }
3396 12 : ereport(ERROR,
3397 : (errcode(ERRCODE_DIVISION_BY_ZERO),
3398 : errmsg("division by zero")));
3399 : }
3400 : /* Inf % any nonzero = NaN */
3401 60 : return make_result(&const_nan);
3402 : }
3403 : /* num2 must be [-]Inf; result is num1 regardless of sign of num2 */
3404 48 : return duplicate_numeric(num1);
3405 : }
3406 :
3407 54018 : init_var_from_num(num1, &arg1);
3408 54018 : init_var_from_num(num2, &arg2);
3409 :
3410 54018 : init_var(&result);
3411 :
3412 : /*
3413 : * If "have_error" is provided, check for division by zero here
3414 : */
3415 54018 : if (have_error && (arg2.ndigits == 0 || arg2.digits[0] == 0))
3416 : {
3417 0 : *have_error = true;
3418 0 : return NULL;
3419 : }
3420 :
3421 54018 : mod_var(&arg1, &arg2, &result);
3422 :
3423 54006 : res = make_result_opt_error(&result, NULL);
3424 :
3425 54006 : free_var(&result);
3426 :
3427 54006 : return res;
3428 : }
3429 :
3430 :
3431 : /*
3432 : * numeric_inc() -
3433 : *
3434 : * Increment a number by one
3435 : */
3436 : Datum
3437 48 : numeric_inc(PG_FUNCTION_ARGS)
3438 : {
3439 48 : Numeric num = PG_GETARG_NUMERIC(0);
3440 : NumericVar arg;
3441 : Numeric res;
3442 :
3443 : /*
3444 : * Handle NaN and infinities
3445 : */
3446 48 : if (NUMERIC_IS_SPECIAL(num))
3447 18 : PG_RETURN_NUMERIC(duplicate_numeric(num));
3448 :
3449 : /*
3450 : * Compute the result and return it
3451 : */
3452 30 : init_var_from_num(num, &arg);
3453 :
3454 30 : add_var(&arg, &const_one, &arg);
3455 :
3456 30 : res = make_result(&arg);
3457 :
3458 30 : free_var(&arg);
3459 :
3460 30 : PG_RETURN_NUMERIC(res);
3461 : }
3462 :
3463 :
3464 : /*
3465 : * numeric_smaller() -
3466 : *
3467 : * Return the smaller of two numbers
3468 : */
3469 : Datum
3470 798 : numeric_smaller(PG_FUNCTION_ARGS)
3471 : {
3472 798 : Numeric num1 = PG_GETARG_NUMERIC(0);
3473 798 : Numeric num2 = PG_GETARG_NUMERIC(1);
3474 :
3475 : /*
3476 : * Use cmp_numerics so that this will agree with the comparison operators,
3477 : * particularly as regards comparisons involving NaN.
3478 : */
3479 798 : if (cmp_numerics(num1, num2) < 0)
3480 644 : PG_RETURN_NUMERIC(num1);
3481 : else
3482 154 : PG_RETURN_NUMERIC(num2);
3483 : }
3484 :
3485 :
3486 : /*
3487 : * numeric_larger() -
3488 : *
3489 : * Return the larger of two numbers
3490 : */
3491 : Datum
3492 18630 : numeric_larger(PG_FUNCTION_ARGS)
3493 : {
3494 18630 : Numeric num1 = PG_GETARG_NUMERIC(0);
3495 18630 : Numeric num2 = PG_GETARG_NUMERIC(1);
3496 :
3497 : /*
3498 : * Use cmp_numerics so that this will agree with the comparison operators,
3499 : * particularly as regards comparisons involving NaN.
3500 : */
3501 18630 : if (cmp_numerics(num1, num2) > 0)
3502 17816 : PG_RETURN_NUMERIC(num1);
3503 : else
3504 814 : PG_RETURN_NUMERIC(num2);
3505 : }
3506 :
3507 :
3508 : /* ----------------------------------------------------------------------
3509 : *
3510 : * Advanced math functions
3511 : *
3512 : * ----------------------------------------------------------------------
3513 : */
3514 :
3515 : /*
3516 : * numeric_gcd() -
3517 : *
3518 : * Calculate the greatest common divisor of two numerics
3519 : */
3520 : Datum
3521 216 : numeric_gcd(PG_FUNCTION_ARGS)
3522 : {
3523 216 : Numeric num1 = PG_GETARG_NUMERIC(0);
3524 216 : Numeric num2 = PG_GETARG_NUMERIC(1);
3525 : NumericVar arg1;
3526 : NumericVar arg2;
3527 : NumericVar result;
3528 : Numeric res;
3529 :
3530 : /*
3531 : * Handle NaN and infinities: we consider the result to be NaN in all such
3532 : * cases.
3533 : */
3534 216 : if (NUMERIC_IS_SPECIAL(num1) || NUMERIC_IS_SPECIAL(num2))
3535 96 : PG_RETURN_NUMERIC(make_result(&const_nan));
3536 :
3537 : /*
3538 : * Unpack the arguments
3539 : */
3540 120 : init_var_from_num(num1, &arg1);
3541 120 : init_var_from_num(num2, &arg2);
3542 :
3543 120 : init_var(&result);
3544 :
3545 : /*
3546 : * Find the GCD and return the result
3547 : */
3548 120 : gcd_var(&arg1, &arg2, &result);
3549 :
3550 120 : res = make_result(&result);
3551 :
3552 120 : free_var(&result);
3553 :
3554 120 : PG_RETURN_NUMERIC(res);
3555 : }
3556 :
3557 :
3558 : /*
3559 : * numeric_lcm() -
3560 : *
3561 : * Calculate the least common multiple of two numerics
3562 : */
3563 : Datum
3564 246 : numeric_lcm(PG_FUNCTION_ARGS)
3565 : {
3566 246 : Numeric num1 = PG_GETARG_NUMERIC(0);
3567 246 : Numeric num2 = PG_GETARG_NUMERIC(1);
3568 : NumericVar arg1;
3569 : NumericVar arg2;
3570 : NumericVar result;
3571 : Numeric res;
3572 :
3573 : /*
3574 : * Handle NaN and infinities: we consider the result to be NaN in all such
3575 : * cases.
3576 : */
3577 246 : if (NUMERIC_IS_SPECIAL(num1) || NUMERIC_IS_SPECIAL(num2))
3578 96 : PG_RETURN_NUMERIC(make_result(&const_nan));
3579 :
3580 : /*
3581 : * Unpack the arguments
3582 : */
3583 150 : init_var_from_num(num1, &arg1);
3584 150 : init_var_from_num(num2, &arg2);
3585 :
3586 150 : init_var(&result);
3587 :
3588 : /*
3589 : * Compute the result using lcm(x, y) = abs(x / gcd(x, y) * y), returning
3590 : * zero if either input is zero.
3591 : *
3592 : * Note that the division is guaranteed to be exact, returning an integer
3593 : * result, so the LCM is an integral multiple of both x and y. A display
3594 : * scale of Min(x.dscale, y.dscale) would be sufficient to represent it,
3595 : * but as with other numeric functions, we choose to return a result whose
3596 : * display scale is no smaller than either input.
3597 : */
3598 150 : if (arg1.ndigits == 0 || arg2.ndigits == 0)
3599 48 : set_var_from_var(&const_zero, &result);
3600 : else
3601 : {
3602 102 : gcd_var(&arg1, &arg2, &result);
3603 102 : div_var(&arg1, &result, &result, 0, false);
3604 102 : mul_var(&arg2, &result, &result, arg2.dscale);
3605 102 : result.sign = NUMERIC_POS;
3606 : }
3607 :
3608 150 : result.dscale = Max(arg1.dscale, arg2.dscale);
3609 :
3610 150 : res = make_result(&result);
3611 :
3612 144 : free_var(&result);
3613 :
3614 144 : PG_RETURN_NUMERIC(res);
3615 : }
3616 :
3617 :
3618 : /*
3619 : * numeric_fac()
3620 : *
3621 : * Compute factorial
3622 : */
3623 : Datum
3624 42 : numeric_fac(PG_FUNCTION_ARGS)
3625 : {
3626 42 : int64 num = PG_GETARG_INT64(0);
3627 : Numeric res;
3628 : NumericVar fact;
3629 : NumericVar result;
3630 :
3631 42 : if (num < 0)
3632 6 : ereport(ERROR,
3633 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
3634 : errmsg("factorial of a negative number is undefined")));
3635 36 : if (num <= 1)
3636 : {
3637 6 : res = make_result(&const_one);
3638 6 : PG_RETURN_NUMERIC(res);
3639 : }
3640 : /* Fail immediately if the result would overflow */
3641 30 : if (num > 32177)
3642 6 : ereport(ERROR,
3643 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
3644 : errmsg("value overflows numeric format")));
3645 :
3646 24 : init_var(&fact);
3647 24 : init_var(&result);
3648 :
3649 24 : int64_to_numericvar(num, &result);
3650 :
3651 294 : for (num = num - 1; num > 1; num--)
3652 : {
3653 : /* this loop can take awhile, so allow it to be interrupted */
3654 270 : CHECK_FOR_INTERRUPTS();
3655 :
3656 270 : int64_to_numericvar(num, &fact);
3657 :
3658 270 : mul_var(&result, &fact, &result, 0);
3659 : }
3660 :
3661 24 : res = make_result(&result);
3662 :
3663 24 : free_var(&fact);
3664 24 : free_var(&result);
3665 :
3666 24 : PG_RETURN_NUMERIC(res);
3667 : }
3668 :
3669 :
3670 : /*
3671 : * numeric_sqrt() -
3672 : *
3673 : * Compute the square root of a numeric.
3674 : */
3675 : Datum
3676 150 : numeric_sqrt(PG_FUNCTION_ARGS)
3677 : {
3678 150 : Numeric num = PG_GETARG_NUMERIC(0);
3679 : Numeric res;
3680 : NumericVar arg;
3681 : NumericVar result;
3682 : int sweight;
3683 : int rscale;
3684 :
3685 : /*
3686 : * Handle NaN and infinities
3687 : */
3688 150 : if (NUMERIC_IS_SPECIAL(num))
3689 : {
3690 : /* error should match that in sqrt_var() */
3691 18 : if (NUMERIC_IS_NINF(num))
3692 6 : ereport(ERROR,
3693 : (errcode(ERRCODE_INVALID_ARGUMENT_FOR_POWER_FUNCTION),
3694 : errmsg("cannot take square root of a negative number")));
3695 : /* For NAN or PINF, just duplicate the input */
3696 12 : PG_RETURN_NUMERIC(duplicate_numeric(num));
3697 : }
3698 :
3699 : /*
3700 : * Unpack the argument and determine the result scale. We choose a scale
3701 : * to give at least NUMERIC_MIN_SIG_DIGITS significant digits; but in any
3702 : * case not less than the input's dscale.
3703 : */
3704 132 : init_var_from_num(num, &arg);
3705 :
3706 132 : init_var(&result);
3707 :
3708 : /*
3709 : * Assume the input was normalized, so arg.weight is accurate. The result
3710 : * then has at least sweight = floor(arg.weight * DEC_DIGITS / 2 + 1)
3711 : * digits before the decimal point. When DEC_DIGITS is even, we can save
3712 : * a few cycles, since the division is exact and there is no need to round
3713 : * towards negative infinity.
3714 : */
3715 : #if DEC_DIGITS == ((DEC_DIGITS / 2) * 2)
3716 132 : sweight = arg.weight * DEC_DIGITS / 2 + 1;
3717 : #else
3718 : if (arg.weight >= 0)
3719 : sweight = arg.weight * DEC_DIGITS / 2 + 1;
3720 : else
3721 : sweight = 1 - (1 - arg.weight * DEC_DIGITS) / 2;
3722 : #endif
3723 :
3724 132 : rscale = NUMERIC_MIN_SIG_DIGITS - sweight;
3725 132 : rscale = Max(rscale, arg.dscale);
3726 132 : rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
3727 132 : rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
3728 :
3729 : /*
3730 : * Let sqrt_var() do the calculation and return the result.
3731 : */
3732 132 : sqrt_var(&arg, &result, rscale);
3733 :
3734 126 : res = make_result(&result);
3735 :
3736 126 : free_var(&result);
3737 :
3738 126 : PG_RETURN_NUMERIC(res);
3739 : }
3740 :
3741 :
3742 : /*
3743 : * numeric_exp() -
3744 : *
3745 : * Raise e to the power of x
3746 : */
3747 : Datum
3748 78 : numeric_exp(PG_FUNCTION_ARGS)
3749 : {
3750 78 : Numeric num = PG_GETARG_NUMERIC(0);
3751 : Numeric res;
3752 : NumericVar arg;
3753 : NumericVar result;
3754 : int rscale;
3755 : double val;
3756 :
3757 : /*
3758 : * Handle NaN and infinities
3759 : */
3760 78 : if (NUMERIC_IS_SPECIAL(num))
3761 : {
3762 : /* Per POSIX, exp(-Inf) is zero */
3763 18 : if (NUMERIC_IS_NINF(num))
3764 6 : PG_RETURN_NUMERIC(make_result(&const_zero));
3765 : /* For NAN or PINF, just duplicate the input */
3766 12 : PG_RETURN_NUMERIC(duplicate_numeric(num));
3767 : }
3768 :
3769 : /*
3770 : * Unpack the argument and determine the result scale. We choose a scale
3771 : * to give at least NUMERIC_MIN_SIG_DIGITS significant digits; but in any
3772 : * case not less than the input's dscale.
3773 : */
3774 60 : init_var_from_num(num, &arg);
3775 :
3776 60 : init_var(&result);
3777 :
3778 : /* convert input to float8, ignoring overflow */
3779 60 : val = numericvar_to_double_no_overflow(&arg);
3780 :
3781 : /*
3782 : * log10(result) = num * log10(e), so this is approximately the decimal
3783 : * weight of the result:
3784 : */
3785 60 : val *= 0.434294481903252;
3786 :
3787 : /* limit to something that won't cause integer overflow */
3788 60 : val = Max(val, -NUMERIC_MAX_RESULT_SCALE);
3789 60 : val = Min(val, NUMERIC_MAX_RESULT_SCALE);
3790 :
3791 60 : rscale = NUMERIC_MIN_SIG_DIGITS - (int) val;
3792 60 : rscale = Max(rscale, arg.dscale);
3793 60 : rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
3794 60 : rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
3795 :
3796 : /*
3797 : * Let exp_var() do the calculation and return the result.
3798 : */
3799 60 : exp_var(&arg, &result, rscale);
3800 :
3801 60 : res = make_result(&result);
3802 :
3803 60 : free_var(&result);
3804 :
3805 60 : PG_RETURN_NUMERIC(res);
3806 : }
3807 :
3808 :
3809 : /*
3810 : * numeric_ln() -
3811 : *
3812 : * Compute the natural logarithm of x
3813 : */
3814 : Datum
3815 198 : numeric_ln(PG_FUNCTION_ARGS)
3816 : {
3817 198 : Numeric num = PG_GETARG_NUMERIC(0);
3818 : Numeric res;
3819 : NumericVar arg;
3820 : NumericVar result;
3821 : int ln_dweight;
3822 : int rscale;
3823 :
3824 : /*
3825 : * Handle NaN and infinities
3826 : */
3827 198 : if (NUMERIC_IS_SPECIAL(num))
3828 : {
3829 18 : if (NUMERIC_IS_NINF(num))
3830 6 : ereport(ERROR,
3831 : (errcode(ERRCODE_INVALID_ARGUMENT_FOR_LOG),
3832 : errmsg("cannot take logarithm of a negative number")));
3833 : /* For NAN or PINF, just duplicate the input */
3834 12 : PG_RETURN_NUMERIC(duplicate_numeric(num));
3835 : }
3836 :
3837 180 : init_var_from_num(num, &arg);
3838 180 : init_var(&result);
3839 :
3840 : /* Estimated dweight of logarithm */
3841 180 : ln_dweight = estimate_ln_dweight(&arg);
3842 :
3843 180 : rscale = NUMERIC_MIN_SIG_DIGITS - ln_dweight;
3844 180 : rscale = Max(rscale, arg.dscale);
3845 180 : rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
3846 180 : rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
3847 :
3848 180 : ln_var(&arg, &result, rscale);
3849 :
3850 156 : res = make_result(&result);
3851 :
3852 156 : free_var(&result);
3853 :
3854 156 : PG_RETURN_NUMERIC(res);
3855 : }
3856 :
3857 :
3858 : /*
3859 : * numeric_log() -
3860 : *
3861 : * Compute the logarithm of x in a given base
3862 : */
3863 : Datum
3864 342 : numeric_log(PG_FUNCTION_ARGS)
3865 : {
3866 342 : Numeric num1 = PG_GETARG_NUMERIC(0);
3867 342 : Numeric num2 = PG_GETARG_NUMERIC(1);
3868 : Numeric res;
3869 : NumericVar arg1;
3870 : NumericVar arg2;
3871 : NumericVar result;
3872 :
3873 : /*
3874 : * Handle NaN and infinities
3875 : */
3876 342 : if (NUMERIC_IS_SPECIAL(num1) || NUMERIC_IS_SPECIAL(num2))
3877 : {
3878 : int sign1,
3879 : sign2;
3880 :
3881 126 : if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
3882 54 : PG_RETURN_NUMERIC(make_result(&const_nan));
3883 : /* fail on negative inputs including -Inf, as log_var would */
3884 72 : sign1 = numeric_sign_internal(num1);
3885 72 : sign2 = numeric_sign_internal(num2);
3886 72 : if (sign1 < 0 || sign2 < 0)
3887 24 : ereport(ERROR,
3888 : (errcode(ERRCODE_INVALID_ARGUMENT_FOR_LOG),
3889 : errmsg("cannot take logarithm of a negative number")));
3890 : /* fail on zero inputs, as log_var would */
3891 48 : if (sign1 == 0 || sign2 == 0)
3892 6 : ereport(ERROR,
3893 : (errcode(ERRCODE_INVALID_ARGUMENT_FOR_LOG),
3894 : errmsg("cannot take logarithm of zero")));
3895 42 : if (NUMERIC_IS_PINF(num1))
3896 : {
3897 : /* log(Inf, Inf) reduces to Inf/Inf, so it's NaN */
3898 18 : if (NUMERIC_IS_PINF(num2))
3899 6 : PG_RETURN_NUMERIC(make_result(&const_nan));
3900 : /* log(Inf, finite-positive) is zero (we don't throw underflow) */
3901 12 : PG_RETURN_NUMERIC(make_result(&const_zero));
3902 : }
3903 : Assert(NUMERIC_IS_PINF(num2));
3904 : /* log(finite-positive, Inf) is Inf */
3905 24 : PG_RETURN_NUMERIC(make_result(&const_pinf));
3906 : }
3907 :
3908 : /*
3909 : * Initialize things
3910 : */
3911 216 : init_var_from_num(num1, &arg1);
3912 216 : init_var_from_num(num2, &arg2);
3913 216 : init_var(&result);
3914 :
3915 : /*
3916 : * Call log_var() to compute and return the result; note it handles scale
3917 : * selection itself.
3918 : */
3919 216 : log_var(&arg1, &arg2, &result);
3920 :
3921 156 : res = make_result(&result);
3922 :
3923 156 : free_var(&result);
3924 :
3925 156 : PG_RETURN_NUMERIC(res);
3926 : }
3927 :
3928 :
3929 : /*
3930 : * numeric_power() -
3931 : *
3932 : * Raise x to the power of y
3933 : */
3934 : Datum
3935 1632 : numeric_power(PG_FUNCTION_ARGS)
3936 : {
3937 1632 : Numeric num1 = PG_GETARG_NUMERIC(0);
3938 1632 : Numeric num2 = PG_GETARG_NUMERIC(1);
3939 : Numeric res;
3940 : NumericVar arg1;
3941 : NumericVar arg2;
3942 : NumericVar result;
3943 : int sign1,
3944 : sign2;
3945 :
3946 : /*
3947 : * Handle NaN and infinities
3948 : */
3949 1632 : if (NUMERIC_IS_SPECIAL(num1) || NUMERIC_IS_SPECIAL(num2))
3950 : {
3951 : /*
3952 : * We follow the POSIX spec for pow(3), which says that NaN ^ 0 = 1,
3953 : * and 1 ^ NaN = 1, while all other cases with NaN inputs yield NaN
3954 : * (with no error).
3955 : */
3956 234 : if (NUMERIC_IS_NAN(num1))
3957 : {
3958 54 : if (!NUMERIC_IS_SPECIAL(num2))
3959 : {
3960 36 : init_var_from_num(num2, &arg2);
3961 36 : if (cmp_var(&arg2, &const_zero) == 0)
3962 12 : PG_RETURN_NUMERIC(make_result(&const_one));
3963 : }
3964 42 : PG_RETURN_NUMERIC(make_result(&const_nan));
3965 : }
3966 180 : if (NUMERIC_IS_NAN(num2))
3967 : {
3968 42 : if (!NUMERIC_IS_SPECIAL(num1))
3969 : {
3970 36 : init_var_from_num(num1, &arg1);
3971 36 : if (cmp_var(&arg1, &const_one) == 0)
3972 12 : PG_RETURN_NUMERIC(make_result(&const_one));
3973 : }
3974 30 : PG_RETURN_NUMERIC(make_result(&const_nan));
3975 : }
3976 : /* At least one input is infinite, but error rules still apply */
3977 138 : sign1 = numeric_sign_internal(num1);
3978 138 : sign2 = numeric_sign_internal(num2);
3979 138 : if (sign1 == 0 && sign2 < 0)
3980 6 : ereport(ERROR,
3981 : (errcode(ERRCODE_INVALID_ARGUMENT_FOR_POWER_FUNCTION),
3982 : errmsg("zero raised to a negative power is undefined")));
3983 132 : if (sign1 < 0 && !numeric_is_integral(num2))
3984 6 : ereport(ERROR,
3985 : (errcode(ERRCODE_INVALID_ARGUMENT_FOR_POWER_FUNCTION),
3986 : errmsg("a negative number raised to a non-integer power yields a complex result")));
3987 :
3988 : /*
3989 : * POSIX gives this series of rules for pow(3) with infinite inputs:
3990 : *
3991 : * For any value of y, if x is +1, 1.0 shall be returned.
3992 : */
3993 126 : if (!NUMERIC_IS_SPECIAL(num1))
3994 : {
3995 42 : init_var_from_num(num1, &arg1);
3996 42 : if (cmp_var(&arg1, &const_one) == 0)
3997 6 : PG_RETURN_NUMERIC(make_result(&const_one));
3998 : }
3999 :
4000 : /*
4001 : * For any value of x, if y is [-]0, 1.0 shall be returned.
4002 : */
4003 120 : if (sign2 == 0)
4004 12 : PG_RETURN_NUMERIC(make_result(&const_one));
4005 :
4006 : /*
4007 : * For any odd integer value of y > 0, if x is [-]0, [-]0 shall be
4008 : * returned. For y > 0 and not an odd integer, if x is [-]0, +0 shall
4009 : * be returned. (Since we don't deal in minus zero, we need not
4010 : * distinguish these two cases.)
4011 : */
4012 108 : if (sign1 == 0 && sign2 > 0)
4013 6 : PG_RETURN_NUMERIC(make_result(&const_zero));
4014 :
4015 : /*
4016 : * If x is -1, and y is [-]Inf, 1.0 shall be returned.
4017 : *
4018 : * For |x| < 1, if y is -Inf, +Inf shall be returned.
4019 : *
4020 : * For |x| > 1, if y is -Inf, +0 shall be returned.
4021 : *
4022 : * For |x| < 1, if y is +Inf, +0 shall be returned.
4023 : *
4024 : * For |x| > 1, if y is +Inf, +Inf shall be returned.
4025 : */
4026 102 : if (NUMERIC_IS_INF(num2))
4027 : {
4028 : bool abs_x_gt_one;
4029 :
4030 54 : if (NUMERIC_IS_SPECIAL(num1))
4031 24 : abs_x_gt_one = true; /* x is either Inf or -Inf */
4032 : else
4033 : {
4034 30 : init_var_from_num(num1, &arg1);
4035 30 : if (cmp_var(&arg1, &const_minus_one) == 0)
4036 6 : PG_RETURN_NUMERIC(make_result(&const_one));
4037 24 : arg1.sign = NUMERIC_POS; /* now arg1 = abs(x) */
4038 24 : abs_x_gt_one = (cmp_var(&arg1, &const_one) > 0);
4039 : }
4040 48 : if (abs_x_gt_one == (sign2 > 0))
4041 30 : PG_RETURN_NUMERIC(make_result(&const_pinf));
4042 : else
4043 18 : PG_RETURN_NUMERIC(make_result(&const_zero));
4044 : }
4045 :
4046 : /*
4047 : * For y < 0, if x is +Inf, +0 shall be returned.
4048 : *
4049 : * For y > 0, if x is +Inf, +Inf shall be returned.
4050 : */
4051 48 : if (NUMERIC_IS_PINF(num1))
4052 : {
4053 24 : if (sign2 > 0)
4054 18 : PG_RETURN_NUMERIC(make_result(&const_pinf));
4055 : else
4056 6 : PG_RETURN_NUMERIC(make_result(&const_zero));
4057 : }
4058 :
4059 : Assert(NUMERIC_IS_NINF(num1));
4060 :
4061 : /*
4062 : * For y an odd integer < 0, if x is -Inf, -0 shall be returned. For
4063 : * y < 0 and not an odd integer, if x is -Inf, +0 shall be returned.
4064 : * (Again, we need not distinguish these two cases.)
4065 : */
4066 24 : if (sign2 < 0)
4067 12 : PG_RETURN_NUMERIC(make_result(&const_zero));
4068 :
4069 : /*
4070 : * For y an odd integer > 0, if x is -Inf, -Inf shall be returned. For
4071 : * y > 0 and not an odd integer, if x is -Inf, +Inf shall be returned.
4072 : */
4073 12 : init_var_from_num(num2, &arg2);
4074 12 : if (arg2.ndigits > 0 && arg2.ndigits == arg2.weight + 1 &&
4075 12 : (arg2.digits[arg2.ndigits - 1] & 1))
4076 6 : PG_RETURN_NUMERIC(make_result(&const_ninf));
4077 : else
4078 6 : PG_RETURN_NUMERIC(make_result(&const_pinf));
4079 : }
4080 :
4081 : /*
4082 : * The SQL spec requires that we emit a particular SQLSTATE error code for
4083 : * certain error conditions. Specifically, we don't return a
4084 : * divide-by-zero error code for 0 ^ -1. Raising a negative number to a
4085 : * non-integer power must produce the same error code, but that case is
4086 : * handled in power_var().
4087 : */
4088 1398 : sign1 = numeric_sign_internal(num1);
4089 1398 : sign2 = numeric_sign_internal(num2);
4090 :
4091 1398 : if (sign1 == 0 && sign2 < 0)
4092 12 : ereport(ERROR,
4093 : (errcode(ERRCODE_INVALID_ARGUMENT_FOR_POWER_FUNCTION),
4094 : errmsg("zero raised to a negative power is undefined")));
4095 :
4096 : /*
4097 : * Initialize things
4098 : */
4099 1386 : init_var(&result);
4100 1386 : init_var_from_num(num1, &arg1);
4101 1386 : init_var_from_num(num2, &arg2);
4102 :
4103 : /*
4104 : * Call power_var() to compute and return the result; note it handles
4105 : * scale selection itself.
4106 : */
4107 1386 : power_var(&arg1, &arg2, &result);
4108 :
4109 1356 : res = make_result(&result);
4110 :
4111 1356 : free_var(&result);
4112 :
4113 1356 : PG_RETURN_NUMERIC(res);
4114 : }
4115 :
4116 : /*
4117 : * numeric_scale() -
4118 : *
4119 : * Returns the scale, i.e. the count of decimal digits in the fractional part
4120 : */
4121 : Datum
4122 108 : numeric_scale(PG_FUNCTION_ARGS)
4123 : {
4124 108 : Numeric num = PG_GETARG_NUMERIC(0);
4125 :
4126 108 : if (NUMERIC_IS_SPECIAL(num))
4127 18 : PG_RETURN_NULL();
4128 :
4129 90 : PG_RETURN_INT32(NUMERIC_DSCALE(num));
4130 : }
4131 :
4132 : /*
4133 : * Calculate minimum scale for value.
4134 : */
4135 : static int
4136 372 : get_min_scale(NumericVar *var)
4137 : {
4138 : int min_scale;
4139 : int last_digit_pos;
4140 :
4141 : /*
4142 : * Ordinarily, the input value will be "stripped" so that the last
4143 : * NumericDigit is nonzero. But we don't want to get into an infinite
4144 : * loop if it isn't, so explicitly find the last nonzero digit.
4145 : */
4146 372 : last_digit_pos = var->ndigits - 1;
4147 372 : while (last_digit_pos >= 0 &&
4148 342 : var->digits[last_digit_pos] == 0)
4149 0 : last_digit_pos--;
4150 :
4151 372 : if (last_digit_pos >= 0)
4152 : {
4153 : /* compute min_scale assuming that last ndigit has no zeroes */
4154 342 : min_scale = (last_digit_pos - var->weight) * DEC_DIGITS;
4155 :
4156 : /*
4157 : * We could get a negative result if there are no digits after the
4158 : * decimal point. In this case the min_scale must be zero.
4159 : */
4160 342 : if (min_scale > 0)
4161 : {
4162 : /*
4163 : * Reduce min_scale if trailing digit(s) in last NumericDigit are
4164 : * zero.
4165 : */
4166 186 : NumericDigit last_digit = var->digits[last_digit_pos];
4167 :
4168 498 : while (last_digit % 10 == 0)
4169 : {
4170 312 : min_scale--;
4171 312 : last_digit /= 10;
4172 : }
4173 : }
4174 : else
4175 156 : min_scale = 0;
4176 : }
4177 : else
4178 30 : min_scale = 0; /* result if input is zero */
4179 :
4180 372 : return min_scale;
4181 : }
4182 :
4183 : /*
4184 : * Returns minimum scale required to represent supplied value without loss.
4185 : */
4186 : Datum
4187 72 : numeric_min_scale(PG_FUNCTION_ARGS)
4188 : {
4189 72 : Numeric num = PG_GETARG_NUMERIC(0);
4190 : NumericVar arg;
4191 : int min_scale;
4192 :
4193 72 : if (NUMERIC_IS_SPECIAL(num))
4194 12 : PG_RETURN_NULL();
4195 :
4196 60 : init_var_from_num(num, &arg);
4197 60 : min_scale = get_min_scale(&arg);
4198 60 : free_var(&arg);
4199 :
4200 60 : PG_RETURN_INT32(min_scale);
4201 : }
4202 :
4203 : /*
4204 : * Reduce scale of numeric value to represent supplied value without loss.
4205 : */
4206 : Datum
4207 324 : numeric_trim_scale(PG_FUNCTION_ARGS)
4208 : {
4209 324 : Numeric num = PG_GETARG_NUMERIC(0);
4210 : Numeric res;
4211 : NumericVar result;
4212 :
4213 324 : if (NUMERIC_IS_SPECIAL(num))
4214 12 : PG_RETURN_NUMERIC(duplicate_numeric(num));
4215 :
4216 312 : init_var_from_num(num, &result);
4217 312 : result.dscale = get_min_scale(&result);
4218 312 : res = make_result(&result);
4219 312 : free_var(&result);
4220 :
4221 312 : PG_RETURN_NUMERIC(res);
4222 : }
4223 :
4224 : /*
4225 : * Return a random numeric value in the range [rmin, rmax].
4226 : */
4227 : Numeric
4228 33462 : random_numeric(pg_prng_state *state, Numeric rmin, Numeric rmax)
4229 : {
4230 : NumericVar rmin_var;
4231 : NumericVar rmax_var;
4232 : NumericVar result;
4233 : Numeric res;
4234 :
4235 : /* Range bounds must not be NaN/infinity */
4236 33462 : if (NUMERIC_IS_SPECIAL(rmin))
4237 : {
4238 12 : if (NUMERIC_IS_NAN(rmin))
4239 6 : ereport(ERROR,
4240 : errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4241 : errmsg("lower bound cannot be NaN"));
4242 : else
4243 6 : ereport(ERROR,
4244 : errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4245 : errmsg("lower bound cannot be infinity"));
4246 : }
4247 33450 : if (NUMERIC_IS_SPECIAL(rmax))
4248 : {
4249 12 : if (NUMERIC_IS_NAN(rmax))
4250 6 : ereport(ERROR,
4251 : errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4252 : errmsg("upper bound cannot be NaN"));
4253 : else
4254 6 : ereport(ERROR,
4255 : errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4256 : errmsg("upper bound cannot be infinity"));
4257 : }
4258 :
4259 : /* Return a random value in the range [rmin, rmax] */
4260 33438 : init_var_from_num(rmin, &rmin_var);
4261 33438 : init_var_from_num(rmax, &rmax_var);
4262 :
4263 33438 : init_var(&result);
4264 :
4265 33438 : random_var(state, &rmin_var, &rmax_var, &result);
4266 :
4267 33432 : res = make_result(&result);
4268 :
4269 33432 : free_var(&result);
4270 :
4271 33432 : return res;
4272 : }
4273 :
4274 :
4275 : /* ----------------------------------------------------------------------
4276 : *
4277 : * Type conversion functions
4278 : *
4279 : * ----------------------------------------------------------------------
4280 : */
4281 :
4282 : Numeric
4283 1851046 : int64_to_numeric(int64 val)
4284 : {
4285 : Numeric res;
4286 : NumericVar result;
4287 :
4288 1851046 : init_var(&result);
4289 :
4290 1851046 : int64_to_numericvar(val, &result);
4291 :
4292 1851046 : res = make_result(&result);
4293 :
4294 1851046 : free_var(&result);
4295 :
4296 1851046 : return res;
4297 : }
4298 :
4299 : /*
4300 : * Convert val1/(10**log10val2) to numeric. This is much faster than normal
4301 : * numeric division.
4302 : */
4303 : Numeric
4304 29380 : int64_div_fast_to_numeric(int64 val1, int log10val2)
4305 : {
4306 : Numeric res;
4307 : NumericVar result;
4308 : int rscale;
4309 : int w;
4310 : int m;
4311 :
4312 29380 : init_var(&result);
4313 :
4314 : /* result scale */
4315 29380 : rscale = log10val2 < 0 ? 0 : log10val2;
4316 :
4317 : /* how much to decrease the weight by */
4318 29380 : w = log10val2 / DEC_DIGITS;
4319 : /* how much is left to divide by */
4320 29380 : m = log10val2 % DEC_DIGITS;
4321 29380 : if (m < 0)
4322 : {
4323 0 : m += DEC_DIGITS;
4324 0 : w--;
4325 : }
4326 :
4327 : /*
4328 : * If there is anything left to divide by (10^m with 0 < m < DEC_DIGITS),
4329 : * multiply the dividend by 10^(DEC_DIGITS - m), and shift the weight by
4330 : * one more.
4331 : */
4332 29380 : if (m > 0)
4333 : {
4334 : #if DEC_DIGITS == 4
4335 : static const int pow10[] = {1, 10, 100, 1000};
4336 : #elif DEC_DIGITS == 2
4337 : static const int pow10[] = {1, 10};
4338 : #elif DEC_DIGITS == 1
4339 : static const int pow10[] = {1};
4340 : #else
4341 : #error unsupported NBASE
4342 : #endif
4343 29380 : int64 factor = pow10[DEC_DIGITS - m];
4344 : int64 new_val1;
4345 :
4346 : StaticAssertDecl(lengthof(pow10) == DEC_DIGITS, "mismatch with DEC_DIGITS");
4347 :
4348 29380 : if (unlikely(pg_mul_s64_overflow(val1, factor, &new_val1)))
4349 : {
4350 : #ifdef HAVE_INT128
4351 : /* do the multiplication using 128-bit integers */
4352 : int128 tmp;
4353 :
4354 12 : tmp = (int128) val1 * (int128) factor;
4355 :
4356 12 : int128_to_numericvar(tmp, &result);
4357 : #else
4358 : /* do the multiplication using numerics */
4359 : NumericVar tmp;
4360 :
4361 : init_var(&tmp);
4362 :
4363 : int64_to_numericvar(val1, &result);
4364 : int64_to_numericvar(factor, &tmp);
4365 : mul_var(&result, &tmp, &result, 0);
4366 :
4367 : free_var(&tmp);
4368 : #endif
4369 : }
4370 : else
4371 29368 : int64_to_numericvar(new_val1, &result);
4372 :
4373 29380 : w++;
4374 : }
4375 : else
4376 0 : int64_to_numericvar(val1, &result);
4377 :
4378 29380 : result.weight -= w;
4379 29380 : result.dscale = rscale;
4380 :
4381 29380 : res = make_result(&result);
4382 :
4383 29380 : free_var(&result);
4384 :
4385 29380 : return res;
4386 : }
4387 :
4388 : Datum
4389 1532272 : int4_numeric(PG_FUNCTION_ARGS)
4390 : {
4391 1532272 : int32 val = PG_GETARG_INT32(0);
4392 :
4393 1532272 : PG_RETURN_NUMERIC(int64_to_numeric(val));
4394 : }
4395 :
4396 : int32
4397 8416 : numeric_int4_opt_error(Numeric num, bool *have_error)
4398 : {
4399 : NumericVar x;
4400 : int32 result;
4401 :
4402 8416 : if (have_error)
4403 1506 : *have_error = false;
4404 :
4405 8416 : if (NUMERIC_IS_SPECIAL(num))
4406 : {
4407 18 : if (have_error)
4408 : {
4409 0 : *have_error = true;
4410 0 : return 0;
4411 : }
4412 : else
4413 : {
4414 18 : if (NUMERIC_IS_NAN(num))
4415 6 : ereport(ERROR,
4416 : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4417 : errmsg("cannot convert NaN to %s", "integer")));
4418 : else
4419 12 : ereport(ERROR,
4420 : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4421 : errmsg("cannot convert infinity to %s", "integer")));
4422 : }
4423 : }
4424 :
4425 : /* Convert to variable format, then convert to int4 */
4426 8398 : init_var_from_num(num, &x);
4427 :
4428 8398 : if (!numericvar_to_int32(&x, &result))
4429 : {
4430 84 : if (have_error)
4431 : {
4432 72 : *have_error = true;
4433 72 : return 0;
4434 : }
4435 : else
4436 : {
4437 12 : ereport(ERROR,
4438 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
4439 : errmsg("integer out of range")));
4440 : }
4441 : }
4442 :
4443 8314 : return result;
4444 : }
4445 :
4446 : Datum
4447 6910 : numeric_int4(PG_FUNCTION_ARGS)
4448 : {
4449 6910 : Numeric num = PG_GETARG_NUMERIC(0);
4450 :
4451 6910 : PG_RETURN_INT32(numeric_int4_opt_error(num, NULL));
4452 : }
4453 :
4454 : /*
4455 : * Given a NumericVar, convert it to an int32. If the NumericVar
4456 : * exceeds the range of an int32, false is returned, otherwise true is returned.
4457 : * The input NumericVar is *not* free'd.
4458 : */
4459 : static bool
4460 9136 : numericvar_to_int32(const NumericVar *var, int32 *result)
4461 : {
4462 : int64 val;
4463 :
4464 9136 : if (!numericvar_to_int64(var, &val))
4465 6 : return false;
4466 :
4467 9130 : if (unlikely(val < PG_INT32_MIN) || unlikely(val > PG_INT32_MAX))
4468 78 : return false;
4469 :
4470 : /* Down-convert to int4 */
4471 9052 : *result = (int32) val;
4472 :
4473 9052 : return true;
4474 : }
4475 :
4476 : Datum
4477 36828 : int8_numeric(PG_FUNCTION_ARGS)
4478 : {
4479 36828 : int64 val = PG_GETARG_INT64(0);
4480 :
4481 36828 : PG_RETURN_NUMERIC(int64_to_numeric(val));
4482 : }
4483 :
4484 : int64
4485 564 : numeric_int8_opt_error(Numeric num, bool *have_error)
4486 : {
4487 : NumericVar x;
4488 : int64 result;
4489 :
4490 564 : if (have_error)
4491 48 : *have_error = false;
4492 :
4493 564 : if (NUMERIC_IS_SPECIAL(num))
4494 : {
4495 18 : if (have_error)
4496 : {
4497 0 : *have_error = true;
4498 0 : return 0;
4499 : }
4500 : else
4501 : {
4502 18 : if (NUMERIC_IS_NAN(num))
4503 6 : ereport(ERROR,
4504 : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4505 : errmsg("cannot convert NaN to %s", "bigint")));
4506 : else
4507 12 : ereport(ERROR,
4508 : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4509 : errmsg("cannot convert infinity to %s", "bigint")));
4510 : }
4511 : }
4512 :
4513 : /* Convert to variable format, then convert to int8 */
4514 546 : init_var_from_num(num, &x);
4515 :
4516 546 : if (!numericvar_to_int64(&x, &result))
4517 : {
4518 60 : if (have_error)
4519 : {
4520 12 : *have_error = true;
4521 12 : return 0;
4522 : }
4523 : else
4524 : {
4525 48 : ereport(ERROR,
4526 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
4527 : errmsg("bigint out of range")));
4528 : }
4529 : }
4530 :
4531 486 : return result;
4532 : }
4533 :
4534 : Datum
4535 516 : numeric_int8(PG_FUNCTION_ARGS)
4536 : {
4537 516 : Numeric num = PG_GETARG_NUMERIC(0);
4538 :
4539 516 : PG_RETURN_INT64(numeric_int8_opt_error(num, NULL));
4540 : }
4541 :
4542 :
4543 : Datum
4544 6 : int2_numeric(PG_FUNCTION_ARGS)
4545 : {
4546 6 : int16 val = PG_GETARG_INT16(0);
4547 :
4548 6 : PG_RETURN_NUMERIC(int64_to_numeric(val));
4549 : }
4550 :
4551 :
4552 : Datum
4553 96 : numeric_int2(PG_FUNCTION_ARGS)
4554 : {
4555 96 : Numeric num = PG_GETARG_NUMERIC(0);
4556 : NumericVar x;
4557 : int64 val;
4558 : int16 result;
4559 :
4560 96 : if (NUMERIC_IS_SPECIAL(num))
4561 : {
4562 18 : if (NUMERIC_IS_NAN(num))
4563 6 : ereport(ERROR,
4564 : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4565 : errmsg("cannot convert NaN to %s", "smallint")));
4566 : else
4567 12 : ereport(ERROR,
4568 : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4569 : errmsg("cannot convert infinity to %s", "smallint")));
4570 : }
4571 :
4572 : /* Convert to variable format and thence to int8 */
4573 78 : init_var_from_num(num, &x);
4574 :
4575 78 : if (!numericvar_to_int64(&x, &val))
4576 0 : ereport(ERROR,
4577 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
4578 : errmsg("smallint out of range")));
4579 :
4580 78 : if (unlikely(val < PG_INT16_MIN) || unlikely(val > PG_INT16_MAX))
4581 12 : ereport(ERROR,
4582 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
4583 : errmsg("smallint out of range")));
4584 :
4585 : /* Down-convert to int2 */
4586 66 : result = (int16) val;
4587 :
4588 66 : PG_RETURN_INT16(result);
4589 : }
4590 :
4591 :
4592 : Datum
4593 1074 : float8_numeric(PG_FUNCTION_ARGS)
4594 : {
4595 1074 : float8 val = PG_GETARG_FLOAT8(0);
4596 : Numeric res;
4597 : NumericVar result;
4598 : char buf[DBL_DIG + 100];
4599 : const char *endptr;
4600 :
4601 1074 : if (isnan(val))
4602 6 : PG_RETURN_NUMERIC(make_result(&const_nan));
4603 :
4604 1068 : if (isinf(val))
4605 : {
4606 12 : if (val < 0)
4607 6 : PG_RETURN_NUMERIC(make_result(&const_ninf));
4608 : else
4609 6 : PG_RETURN_NUMERIC(make_result(&const_pinf));
4610 : }
4611 :
4612 1056 : snprintf(buf, sizeof(buf), "%.*g", DBL_DIG, val);
4613 :
4614 1056 : init_var(&result);
4615 :
4616 : /* Assume we need not worry about leading/trailing spaces */
4617 1056 : (void) set_var_from_str(buf, buf, &result, &endptr, NULL);
4618 :
4619 1056 : res = make_result(&result);
4620 :
4621 1056 : free_var(&result);
4622 :
4623 1056 : PG_RETURN_NUMERIC(res);
4624 : }
4625 :
4626 :
4627 : Datum
4628 519412 : numeric_float8(PG_FUNCTION_ARGS)
4629 : {
4630 519412 : Numeric num = PG_GETARG_NUMERIC(0);
4631 : char *tmp;
4632 : Datum result;
4633 :
4634 519412 : if (NUMERIC_IS_SPECIAL(num))
4635 : {
4636 78 : if (NUMERIC_IS_PINF(num))
4637 24 : PG_RETURN_FLOAT8(get_float8_infinity());
4638 54 : else if (NUMERIC_IS_NINF(num))
4639 24 : PG_RETURN_FLOAT8(-get_float8_infinity());
4640 : else
4641 30 : PG_RETURN_FLOAT8(get_float8_nan());
4642 : }
4643 :
4644 519334 : tmp = DatumGetCString(DirectFunctionCall1(numeric_out,
4645 : NumericGetDatum(num)));
4646 :
4647 519334 : result = DirectFunctionCall1(float8in, CStringGetDatum(tmp));
4648 :
4649 519334 : pfree(tmp);
4650 :
4651 519334 : PG_RETURN_DATUM(result);
4652 : }
4653 :
4654 :
4655 : /*
4656 : * Convert numeric to float8; if out of range, return +/- HUGE_VAL
4657 : *
4658 : * (internal helper function, not directly callable from SQL)
4659 : */
4660 : Datum
4661 4180 : numeric_float8_no_overflow(PG_FUNCTION_ARGS)
4662 : {
4663 4180 : Numeric num = PG_GETARG_NUMERIC(0);
4664 : double val;
4665 :
4666 4180 : if (NUMERIC_IS_SPECIAL(num))
4667 : {
4668 0 : if (NUMERIC_IS_PINF(num))
4669 0 : val = HUGE_VAL;
4670 0 : else if (NUMERIC_IS_NINF(num))
4671 0 : val = -HUGE_VAL;
4672 : else
4673 0 : val = get_float8_nan();
4674 : }
4675 : else
4676 : {
4677 : NumericVar x;
4678 :
4679 4180 : init_var_from_num(num, &x);
4680 4180 : val = numericvar_to_double_no_overflow(&x);
4681 : }
4682 :
4683 4180 : PG_RETURN_FLOAT8(val);
4684 : }
4685 :
4686 : Datum
4687 21912 : float4_numeric(PG_FUNCTION_ARGS)
4688 : {
4689 21912 : float4 val = PG_GETARG_FLOAT4(0);
4690 : Numeric res;
4691 : NumericVar result;
4692 : char buf[FLT_DIG + 100];
4693 : const char *endptr;
4694 :
4695 21912 : if (isnan(val))
4696 6 : PG_RETURN_NUMERIC(make_result(&const_nan));
4697 :
4698 21906 : if (isinf(val))
4699 : {
4700 12 : if (val < 0)
4701 6 : PG_RETURN_NUMERIC(make_result(&const_ninf));
4702 : else
4703 6 : PG_RETURN_NUMERIC(make_result(&const_pinf));
4704 : }
4705 :
4706 21894 : snprintf(buf, sizeof(buf), "%.*g", FLT_DIG, val);
4707 :
4708 21894 : init_var(&result);
4709 :
4710 : /* Assume we need not worry about leading/trailing spaces */
4711 21894 : (void) set_var_from_str(buf, buf, &result, &endptr, NULL);
4712 :
4713 21894 : res = make_result(&result);
4714 :
4715 21894 : free_var(&result);
4716 :
4717 21894 : PG_RETURN_NUMERIC(res);
4718 : }
4719 :
4720 :
4721 : Datum
4722 2198 : numeric_float4(PG_FUNCTION_ARGS)
4723 : {
4724 2198 : Numeric num = PG_GETARG_NUMERIC(0);
4725 : char *tmp;
4726 : Datum result;
4727 :
4728 2198 : if (NUMERIC_IS_SPECIAL(num))
4729 : {
4730 78 : if (NUMERIC_IS_PINF(num))
4731 24 : PG_RETURN_FLOAT4(get_float4_infinity());
4732 54 : else if (NUMERIC_IS_NINF(num))
4733 24 : PG_RETURN_FLOAT4(-get_float4_infinity());
4734 : else
4735 30 : PG_RETURN_FLOAT4(get_float4_nan());
4736 : }
4737 :
4738 2120 : tmp = DatumGetCString(DirectFunctionCall1(numeric_out,
4739 : NumericGetDatum(num)));
4740 :
4741 2120 : result = DirectFunctionCall1(float4in, CStringGetDatum(tmp));
4742 :
4743 2120 : pfree(tmp);
4744 :
4745 2120 : PG_RETURN_DATUM(result);
4746 : }
4747 :
4748 :
4749 : Datum
4750 124 : numeric_pg_lsn(PG_FUNCTION_ARGS)
4751 : {
4752 124 : Numeric num = PG_GETARG_NUMERIC(0);
4753 : NumericVar x;
4754 : XLogRecPtr result;
4755 :
4756 124 : if (NUMERIC_IS_SPECIAL(num))
4757 : {
4758 6 : if (NUMERIC_IS_NAN(num))
4759 6 : ereport(ERROR,
4760 : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4761 : errmsg("cannot convert NaN to %s", "pg_lsn")));
4762 : else
4763 0 : ereport(ERROR,
4764 : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4765 : errmsg("cannot convert infinity to %s", "pg_lsn")));
4766 : }
4767 :
4768 : /* Convert to variable format and thence to pg_lsn */
4769 118 : init_var_from_num(num, &x);
4770 :
4771 118 : if (!numericvar_to_uint64(&x, (uint64 *) &result))
4772 24 : ereport(ERROR,
4773 : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4774 : errmsg("pg_lsn out of range")));
4775 :
4776 94 : PG_RETURN_LSN(result);
4777 : }
4778 :
4779 :
4780 : /* ----------------------------------------------------------------------
4781 : *
4782 : * Aggregate functions
4783 : *
4784 : * The transition datatype for all these aggregates is declared as INTERNAL.
4785 : * Actually, it's a pointer to a NumericAggState allocated in the aggregate
4786 : * context. The digit buffers for the NumericVars will be there too.
4787 : *
4788 : * On platforms which support 128-bit integers some aggregates instead use a
4789 : * 128-bit integer based transition datatype to speed up calculations.
4790 : *
4791 : * ----------------------------------------------------------------------
4792 : */
4793 :
4794 : typedef struct NumericAggState
4795 : {
4796 : bool calcSumX2; /* if true, calculate sumX2 */
4797 : MemoryContext agg_context; /* context we're calculating in */
4798 : int64 N; /* count of processed numbers */
4799 : NumericSumAccum sumX; /* sum of processed numbers */
4800 : NumericSumAccum sumX2; /* sum of squares of processed numbers */
4801 : int maxScale; /* maximum scale seen so far */
4802 : int64 maxScaleCount; /* number of values seen with maximum scale */
4803 : /* These counts are *not* included in N! Use NA_TOTAL_COUNT() as needed */
4804 : int64 NaNcount; /* count of NaN values */
4805 : int64 pInfcount; /* count of +Inf values */
4806 : int64 nInfcount; /* count of -Inf values */
4807 : } NumericAggState;
4808 :
4809 : #define NA_TOTAL_COUNT(na) \
4810 : ((na)->N + (na)->NaNcount + (na)->pInfcount + (na)->nInfcount)
4811 :
4812 : /*
4813 : * Prepare state data for a numeric aggregate function that needs to compute
4814 : * sum, count and optionally sum of squares of the input.
4815 : */
4816 : static NumericAggState *
4817 171120 : makeNumericAggState(FunctionCallInfo fcinfo, bool calcSumX2)
4818 : {
4819 : NumericAggState *state;
4820 : MemoryContext agg_context;
4821 : MemoryContext old_context;
4822 :
4823 171120 : if (!AggCheckCallContext(fcinfo, &agg_context))
4824 0 : elog(ERROR, "aggregate function called in non-aggregate context");
4825 :
4826 171120 : old_context = MemoryContextSwitchTo(agg_context);
4827 :
4828 171120 : state = (NumericAggState *) palloc0(sizeof(NumericAggState));
4829 171120 : state->calcSumX2 = calcSumX2;
4830 171120 : state->agg_context = agg_context;
4831 :
4832 171120 : MemoryContextSwitchTo(old_context);
4833 :
4834 171120 : return state;
4835 : }
4836 :
4837 : /*
4838 : * Like makeNumericAggState(), but allocate the state in the current memory
4839 : * context.
4840 : */
4841 : static NumericAggState *
4842 64 : makeNumericAggStateCurrentContext(bool calcSumX2)
4843 : {
4844 : NumericAggState *state;
4845 :
4846 64 : state = (NumericAggState *) palloc0(sizeof(NumericAggState));
4847 64 : state->calcSumX2 = calcSumX2;
4848 64 : state->agg_context = CurrentMemoryContext;
4849 :
4850 64 : return state;
4851 : }
4852 :
4853 : /*
4854 : * Accumulate a new input value for numeric aggregate functions.
4855 : */
4856 : static void
4857 2113552 : do_numeric_accum(NumericAggState *state, Numeric newval)
4858 : {
4859 : NumericVar X;
4860 : NumericVar X2;
4861 : MemoryContext old_context;
4862 :
4863 : /* Count NaN/infinity inputs separately from all else */
4864 2113552 : if (NUMERIC_IS_SPECIAL(newval))
4865 : {
4866 162 : if (NUMERIC_IS_PINF(newval))
4867 72 : state->pInfcount++;
4868 90 : else if (NUMERIC_IS_NINF(newval))
4869 36 : state->nInfcount++;
4870 : else
4871 54 : state->NaNcount++;
4872 162 : return;
4873 : }
4874 :
4875 : /* load processed number in short-lived context */
4876 2113390 : init_var_from_num(newval, &X);
4877 :
4878 : /*
4879 : * Track the highest input dscale that we've seen, to support inverse
4880 : * transitions (see do_numeric_discard).
4881 : */
4882 2113390 : if (X.dscale > state->maxScale)
4883 : {
4884 156 : state->maxScale = X.dscale;
4885 156 : state->maxScaleCount = 1;
4886 : }
4887 2113234 : else if (X.dscale == state->maxScale)
4888 2113198 : state->maxScaleCount++;
4889 :
4890 : /* if we need X^2, calculate that in short-lived context */
4891 2113390 : if (state->calcSumX2)
4892 : {
4893 240732 : init_var(&X2);
4894 240732 : mul_var(&X, &X, &X2, X.dscale * 2);
4895 : }
4896 :
4897 : /* The rest of this needs to work in the aggregate context */
4898 2113390 : old_context = MemoryContextSwitchTo(state->agg_context);
4899 :
4900 2113390 : state->N++;
4901 :
4902 : /* Accumulate sums */
4903 2113390 : accum_sum_add(&(state->sumX), &X);
4904 :
4905 2113390 : if (state->calcSumX2)
4906 240732 : accum_sum_add(&(state->sumX2), &X2);
4907 :
4908 2113390 : MemoryContextSwitchTo(old_context);
4909 : }
4910 :
4911 : /*
4912 : * Attempt to remove an input value from the aggregated state.
4913 : *
4914 : * If the value cannot be removed then the function will return false; the
4915 : * possible reasons for failing are described below.
4916 : *
4917 : * If we aggregate the values 1.01 and 2 then the result will be 3.01.
4918 : * If we are then asked to un-aggregate the 1.01 then we must fail as we
4919 : * won't be able to tell what the new aggregated value's dscale should be.
4920 : * We don't want to return 2.00 (dscale = 2), since the sum's dscale would
4921 : * have been zero if we'd really aggregated only 2.
4922 : *
4923 : * Note: alternatively, we could count the number of inputs with each possible
4924 : * dscale (up to some sane limit). Not yet clear if it's worth the trouble.
4925 : */
4926 : static bool
4927 342 : do_numeric_discard(NumericAggState *state, Numeric newval)
4928 : {
4929 : NumericVar X;
4930 : NumericVar X2;
4931 : MemoryContext old_context;
4932 :
4933 : /* Count NaN/infinity inputs separately from all else */
4934 342 : if (NUMERIC_IS_SPECIAL(newval))
4935 : {
4936 6 : if (NUMERIC_IS_PINF(newval))
4937 0 : state->pInfcount--;
4938 6 : else if (NUMERIC_IS_NINF(newval))
4939 0 : state->nInfcount--;
4940 : else
4941 6 : state->NaNcount--;
4942 6 : return true;
4943 : }
4944 :
4945 : /* load processed number in short-lived context */
4946 336 : init_var_from_num(newval, &X);
4947 :
4948 : /*
4949 : * state->sumX's dscale is the maximum dscale of any of the inputs.
4950 : * Removing the last input with that dscale would require us to recompute
4951 : * the maximum dscale of the *remaining* inputs, which we cannot do unless
4952 : * no more non-NaN inputs remain at all. So we report a failure instead,
4953 : * and force the aggregation to be redone from scratch.
4954 : */
4955 336 : if (X.dscale == state->maxScale)
4956 : {
4957 336 : if (state->maxScaleCount > 1 || state->maxScale == 0)
4958 : {
4959 : /*
4960 : * Some remaining inputs have same dscale, or dscale hasn't gotten
4961 : * above zero anyway
4962 : */
4963 318 : state->maxScaleCount--;
4964 : }
4965 18 : else if (state->N == 1)
4966 : {
4967 : /* No remaining non-NaN inputs at all, so reset maxScale */
4968 12 : state->maxScale = 0;
4969 12 : state->maxScaleCount = 0;
4970 : }
4971 : else
4972 : {
4973 : /* Correct new maxScale is uncertain, must fail */
4974 6 : return false;
4975 : }
4976 : }
4977 :
4978 : /* if we need X^2, calculate that in short-lived context */
4979 330 : if (state->calcSumX2)
4980 : {
4981 288 : init_var(&X2);
4982 288 : mul_var(&X, &X, &X2, X.dscale * 2);
4983 : }
4984 :
4985 : /* The rest of this needs to work in the aggregate context */
4986 330 : old_context = MemoryContextSwitchTo(state->agg_context);
4987 :
4988 330 : if (state->N-- > 1)
4989 : {
4990 : /* Negate X, to subtract it from the sum */
4991 312 : X.sign = (X.sign == NUMERIC_POS ? NUMERIC_NEG : NUMERIC_POS);
4992 312 : accum_sum_add(&(state->sumX), &X);
4993 :
4994 312 : if (state->calcSumX2)
4995 : {
4996 : /* Negate X^2. X^2 is always positive */
4997 288 : X2.sign = NUMERIC_NEG;
4998 288 : accum_sum_add(&(state->sumX2), &X2);
4999 : }
5000 : }
5001 : else
5002 : {
5003 : /* Zero the sums */
5004 : Assert(state->N == 0);
5005 :
5006 18 : accum_sum_reset(&state->sumX);
5007 18 : if (state->calcSumX2)
5008 0 : accum_sum_reset(&state->sumX2);
5009 : }
5010 :
5011 330 : MemoryContextSwitchTo(old_context);
5012 :
5013 330 : return true;
5014 : }
5015 :
5016 : /*
5017 : * Generic transition function for numeric aggregates that require sumX2.
5018 : */
5019 : Datum
5020 642 : numeric_accum(PG_FUNCTION_ARGS)
5021 : {
5022 : NumericAggState *state;
5023 :
5024 642 : state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
5025 :
5026 : /* Create the state data on the first call */
5027 642 : if (state == NULL)
5028 174 : state = makeNumericAggState(fcinfo, true);
5029 :
5030 642 : if (!PG_ARGISNULL(1))
5031 624 : do_numeric_accum(state, PG_GETARG_NUMERIC(1));
5032 :
5033 642 : PG_RETURN_POINTER(state);
5034 : }
5035 :
5036 : /*
5037 : * Generic combine function for numeric aggregates which require sumX2
5038 : */
5039 : Datum
5040 26 : numeric_combine(PG_FUNCTION_ARGS)
5041 : {
5042 : NumericAggState *state1;
5043 : NumericAggState *state2;
5044 : MemoryContext agg_context;
5045 : MemoryContext old_context;
5046 :
5047 26 : if (!AggCheckCallContext(fcinfo, &agg_context))
5048 0 : elog(ERROR, "aggregate function called in non-aggregate context");
5049 :
5050 26 : state1 = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
5051 26 : state2 = PG_ARGISNULL(1) ? NULL : (NumericAggState *) PG_GETARG_POINTER(1);
5052 :
5053 26 : if (state2 == NULL)
5054 0 : PG_RETURN_POINTER(state1);
5055 :
5056 : /* manually copy all fields from state2 to state1 */
5057 26 : if (state1 == NULL)
5058 : {
5059 18 : old_context = MemoryContextSwitchTo(agg_context);
5060 :
5061 18 : state1 = makeNumericAggStateCurrentContext(true);
5062 18 : state1->N = state2->N;
5063 18 : state1->NaNcount = state2->NaNcount;
5064 18 : state1->pInfcount = state2->pInfcount;
5065 18 : state1->nInfcount = state2->nInfcount;
5066 18 : state1->maxScale = state2->maxScale;
5067 18 : state1->maxScaleCount = state2->maxScaleCount;
5068 :
5069 18 : accum_sum_copy(&state1->sumX, &state2->sumX);
5070 18 : accum_sum_copy(&state1->sumX2, &state2->sumX2);
5071 :
5072 18 : MemoryContextSwitchTo(old_context);
5073 :
5074 18 : PG_RETURN_POINTER(state1);
5075 : }
5076 :
5077 8 : state1->N += state2->N;
5078 8 : state1->NaNcount += state2->NaNcount;
5079 8 : state1->pInfcount += state2->pInfcount;
5080 8 : state1->nInfcount += state2->nInfcount;
5081 :
5082 8 : if (state2->N > 0)
5083 : {
5084 : /*
5085 : * These are currently only needed for moving aggregates, but let's do
5086 : * the right thing anyway...
5087 : */
5088 8 : if (state2->maxScale > state1->maxScale)
5089 : {
5090 0 : state1->maxScale = state2->maxScale;
5091 0 : state1->maxScaleCount = state2->maxScaleCount;
5092 : }
5093 8 : else if (state2->maxScale == state1->maxScale)
5094 8 : state1->maxScaleCount += state2->maxScaleCount;
5095 :
5096 : /* The rest of this needs to work in the aggregate context */
5097 8 : old_context = MemoryContextSwitchTo(agg_context);
5098 :
5099 : /* Accumulate sums */
5100 8 : accum_sum_combine(&state1->sumX, &state2->sumX);
5101 8 : accum_sum_combine(&state1->sumX2, &state2->sumX2);
5102 :
5103 8 : MemoryContextSwitchTo(old_context);
5104 : }
5105 8 : PG_RETURN_POINTER(state1);
5106 : }
5107 :
5108 : /*
5109 : * Generic transition function for numeric aggregates that don't require sumX2.
5110 : */
5111 : Datum
5112 1872808 : numeric_avg_accum(PG_FUNCTION_ARGS)
5113 : {
5114 : NumericAggState *state;
5115 :
5116 1872808 : state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
5117 :
5118 : /* Create the state data on the first call */
5119 1872808 : if (state == NULL)
5120 170896 : state = makeNumericAggState(fcinfo, false);
5121 :
5122 1872808 : if (!PG_ARGISNULL(1))
5123 1872748 : do_numeric_accum(state, PG_GETARG_NUMERIC(1));
5124 :
5125 1872808 : PG_RETURN_POINTER(state);
5126 : }
5127 :
5128 : /*
5129 : * Combine function for numeric aggregates which don't require sumX2
5130 : */
5131 : Datum
5132 14 : numeric_avg_combine(PG_FUNCTION_ARGS)
5133 : {
5134 : NumericAggState *state1;
5135 : NumericAggState *state2;
5136 : MemoryContext agg_context;
5137 : MemoryContext old_context;
5138 :
5139 14 : if (!AggCheckCallContext(fcinfo, &agg_context))
5140 0 : elog(ERROR, "aggregate function called in non-aggregate context");
5141 :
5142 14 : state1 = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
5143 14 : state2 = PG_ARGISNULL(1) ? NULL : (NumericAggState *) PG_GETARG_POINTER(1);
5144 :
5145 14 : if (state2 == NULL)
5146 0 : PG_RETURN_POINTER(state1);
5147 :
5148 : /* manually copy all fields from state2 to state1 */
5149 14 : if (state1 == NULL)
5150 : {
5151 6 : old_context = MemoryContextSwitchTo(agg_context);
5152 :
5153 6 : state1 = makeNumericAggStateCurrentContext(false);
5154 6 : state1->N = state2->N;
5155 6 : state1->NaNcount = state2->NaNcount;
5156 6 : state1->pInfcount = state2->pInfcount;
5157 6 : state1->nInfcount = state2->nInfcount;
5158 6 : state1->maxScale = state2->maxScale;
5159 6 : state1->maxScaleCount = state2->maxScaleCount;
5160 :
5161 6 : accum_sum_copy(&state1->sumX, &state2->sumX);
5162 :
5163 6 : MemoryContextSwitchTo(old_context);
5164 :
5165 6 : PG_RETURN_POINTER(state1);
5166 : }
5167 :
5168 8 : state1->N += state2->N;
5169 8 : state1->NaNcount += state2->NaNcount;
5170 8 : state1->pInfcount += state2->pInfcount;
5171 8 : state1->nInfcount += state2->nInfcount;
5172 :
5173 8 : if (state2->N > 0)
5174 : {
5175 : /*
5176 : * These are currently only needed for moving aggregates, but let's do
5177 : * the right thing anyway...
5178 : */
5179 8 : if (state2->maxScale > state1->maxScale)
5180 : {
5181 0 : state1->maxScale = state2->maxScale;
5182 0 : state1->maxScaleCount = state2->maxScaleCount;
5183 : }
5184 8 : else if (state2->maxScale == state1->maxScale)
5185 8 : state1->maxScaleCount += state2->maxScaleCount;
5186 :
5187 : /* The rest of this needs to work in the aggregate context */
5188 8 : old_context = MemoryContextSwitchTo(agg_context);
5189 :
5190 : /* Accumulate sums */
5191 8 : accum_sum_combine(&state1->sumX, &state2->sumX);
5192 :
5193 8 : MemoryContextSwitchTo(old_context);
5194 : }
5195 8 : PG_RETURN_POINTER(state1);
5196 : }
5197 :
5198 : /*
5199 : * numeric_avg_serialize
5200 : * Serialize NumericAggState for numeric aggregates that don't require
5201 : * sumX2.
5202 : */
5203 : Datum
5204 14 : numeric_avg_serialize(PG_FUNCTION_ARGS)
5205 : {
5206 : NumericAggState *state;
5207 : StringInfoData buf;
5208 : bytea *result;
5209 : NumericVar tmp_var;
5210 :
5211 : /* Ensure we disallow calling when not in aggregate context */
5212 14 : if (!AggCheckCallContext(fcinfo, NULL))
5213 0 : elog(ERROR, "aggregate function called in non-aggregate context");
5214 :
5215 14 : state = (NumericAggState *) PG_GETARG_POINTER(0);
5216 :
5217 14 : init_var(&tmp_var);
5218 :
5219 14 : pq_begintypsend(&buf);
5220 :
5221 : /* N */
5222 14 : pq_sendint64(&buf, state->N);
5223 :
5224 : /* sumX */
5225 14 : accum_sum_final(&state->sumX, &tmp_var);
5226 14 : numericvar_serialize(&buf, &tmp_var);
5227 :
5228 : /* maxScale */
5229 14 : pq_sendint32(&buf, state->maxScale);
5230 :
5231 : /* maxScaleCount */
5232 14 : pq_sendint64(&buf, state->maxScaleCount);
5233 :
5234 : /* NaNcount */
5235 14 : pq_sendint64(&buf, state->NaNcount);
5236 :
5237 : /* pInfcount */
5238 14 : pq_sendint64(&buf, state->pInfcount);
5239 :
5240 : /* nInfcount */
5241 14 : pq_sendint64(&buf, state->nInfcount);
5242 :
5243 14 : result = pq_endtypsend(&buf);
5244 :
5245 14 : free_var(&tmp_var);
5246 :
5247 14 : PG_RETURN_BYTEA_P(result);
5248 : }
5249 :
5250 : /*
5251 : * numeric_avg_deserialize
5252 : * Deserialize bytea into NumericAggState for numeric aggregates that
5253 : * don't require sumX2.
5254 : */
5255 : Datum
5256 14 : numeric_avg_deserialize(PG_FUNCTION_ARGS)
5257 : {
5258 : bytea *sstate;
5259 : NumericAggState *result;
5260 : StringInfoData buf;
5261 : NumericVar tmp_var;
5262 :
5263 14 : if (!AggCheckCallContext(fcinfo, NULL))
5264 0 : elog(ERROR, "aggregate function called in non-aggregate context");
5265 :
5266 14 : sstate = PG_GETARG_BYTEA_PP(0);
5267 :
5268 14 : init_var(&tmp_var);
5269 :
5270 : /*
5271 : * Initialize a StringInfo so that we can "receive" it using the standard
5272 : * recv-function infrastructure.
5273 : */
5274 14 : initReadOnlyStringInfo(&buf, VARDATA_ANY(sstate),
5275 14 : VARSIZE_ANY_EXHDR(sstate));
5276 :
5277 14 : result = makeNumericAggStateCurrentContext(false);
5278 :
5279 : /* N */
5280 14 : result->N = pq_getmsgint64(&buf);
5281 :
5282 : /* sumX */
5283 14 : numericvar_deserialize(&buf, &tmp_var);
5284 14 : accum_sum_add(&(result->sumX), &tmp_var);
5285 :
5286 : /* maxScale */
5287 14 : result->maxScale = pq_getmsgint(&buf, 4);
5288 :
5289 : /* maxScaleCount */
5290 14 : result->maxScaleCount = pq_getmsgint64(&buf);
5291 :
5292 : /* NaNcount */
5293 14 : result->NaNcount = pq_getmsgint64(&buf);
5294 :
5295 : /* pInfcount */
5296 14 : result->pInfcount = pq_getmsgint64(&buf);
5297 :
5298 : /* nInfcount */
5299 14 : result->nInfcount = pq_getmsgint64(&buf);
5300 :
5301 14 : pq_getmsgend(&buf);
5302 :
5303 14 : free_var(&tmp_var);
5304 :
5305 14 : PG_RETURN_POINTER(result);
5306 : }
5307 :
5308 : /*
5309 : * numeric_serialize
5310 : * Serialization function for NumericAggState for numeric aggregates that
5311 : * require sumX2.
5312 : */
5313 : Datum
5314 26 : numeric_serialize(PG_FUNCTION_ARGS)
5315 : {
5316 : NumericAggState *state;
5317 : StringInfoData buf;
5318 : bytea *result;
5319 : NumericVar tmp_var;
5320 :
5321 : /* Ensure we disallow calling when not in aggregate context */
5322 26 : if (!AggCheckCallContext(fcinfo, NULL))
5323 0 : elog(ERROR, "aggregate function called in non-aggregate context");
5324 :
5325 26 : state = (NumericAggState *) PG_GETARG_POINTER(0);
5326 :
5327 26 : init_var(&tmp_var);
5328 :
5329 26 : pq_begintypsend(&buf);
5330 :
5331 : /* N */
5332 26 : pq_sendint64(&buf, state->N);
5333 :
5334 : /* sumX */
5335 26 : accum_sum_final(&state->sumX, &tmp_var);
5336 26 : numericvar_serialize(&buf, &tmp_var);
5337 :
5338 : /* sumX2 */
5339 26 : accum_sum_final(&state->sumX2, &tmp_var);
5340 26 : numericvar_serialize(&buf, &tmp_var);
5341 :
5342 : /* maxScale */
5343 26 : pq_sendint32(&buf, state->maxScale);
5344 :
5345 : /* maxScaleCount */
5346 26 : pq_sendint64(&buf, state->maxScaleCount);
5347 :
5348 : /* NaNcount */
5349 26 : pq_sendint64(&buf, state->NaNcount);
5350 :
5351 : /* pInfcount */
5352 26 : pq_sendint64(&buf, state->pInfcount);
5353 :
5354 : /* nInfcount */
5355 26 : pq_sendint64(&buf, state->nInfcount);
5356 :
5357 26 : result = pq_endtypsend(&buf);
5358 :
5359 26 : free_var(&tmp_var);
5360 :
5361 26 : PG_RETURN_BYTEA_P(result);
5362 : }
5363 :
5364 : /*
5365 : * numeric_deserialize
5366 : * Deserialization function for NumericAggState for numeric aggregates that
5367 : * require sumX2.
5368 : */
5369 : Datum
5370 26 : numeric_deserialize(PG_FUNCTION_ARGS)
5371 : {
5372 : bytea *sstate;
5373 : NumericAggState *result;
5374 : StringInfoData buf;
5375 : NumericVar tmp_var;
5376 :
5377 26 : if (!AggCheckCallContext(fcinfo, NULL))
5378 0 : elog(ERROR, "aggregate function called in non-aggregate context");
5379 :
5380 26 : sstate = PG_GETARG_BYTEA_PP(0);
5381 :
5382 26 : init_var(&tmp_var);
5383 :
5384 : /*
5385 : * Initialize a StringInfo so that we can "receive" it using the standard
5386 : * recv-function infrastructure.
5387 : */
5388 26 : initReadOnlyStringInfo(&buf, VARDATA_ANY(sstate),
5389 26 : VARSIZE_ANY_EXHDR(sstate));
5390 :
5391 26 : result = makeNumericAggStateCurrentContext(false);
5392 :
5393 : /* N */
5394 26 : result->N = pq_getmsgint64(&buf);
5395 :
5396 : /* sumX */
5397 26 : numericvar_deserialize(&buf, &tmp_var);
5398 26 : accum_sum_add(&(result->sumX), &tmp_var);
5399 :
5400 : /* sumX2 */
5401 26 : numericvar_deserialize(&buf, &tmp_var);
5402 26 : accum_sum_add(&(result->sumX2), &tmp_var);
5403 :
5404 : /* maxScale */
5405 26 : result->maxScale = pq_getmsgint(&buf, 4);
5406 :
5407 : /* maxScaleCount */
5408 26 : result->maxScaleCount = pq_getmsgint64(&buf);
5409 :
5410 : /* NaNcount */
5411 26 : result->NaNcount = pq_getmsgint64(&buf);
5412 :
5413 : /* pInfcount */
5414 26 : result->pInfcount = pq_getmsgint64(&buf);
5415 :
5416 : /* nInfcount */
5417 26 : result->nInfcount = pq_getmsgint64(&buf);
5418 :
5419 26 : pq_getmsgend(&buf);
5420 :
5421 26 : free_var(&tmp_var);
5422 :
5423 26 : PG_RETURN_POINTER(result);
5424 : }
5425 :
5426 : /*
5427 : * Generic inverse transition function for numeric aggregates
5428 : * (with or without requirement for X^2).
5429 : */
5430 : Datum
5431 228 : numeric_accum_inv(PG_FUNCTION_ARGS)
5432 : {
5433 : NumericAggState *state;
5434 :
5435 228 : state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
5436 :
5437 : /* Should not get here with no state */
5438 228 : if (state == NULL)
5439 0 : elog(ERROR, "numeric_accum_inv called with NULL state");
5440 :
5441 228 : if (!PG_ARGISNULL(1))
5442 : {
5443 : /* If we fail to perform the inverse transition, return NULL */
5444 198 : if (!do_numeric_discard(state, PG_GETARG_NUMERIC(1)))
5445 6 : PG_RETURN_NULL();
5446 : }
5447 :
5448 222 : PG_RETURN_POINTER(state);
5449 : }
5450 :
5451 :
5452 : /*
5453 : * Integer data types in general use Numeric accumulators to share code
5454 : * and avoid risk of overflow.
5455 : *
5456 : * However for performance reasons optimized special-purpose accumulator
5457 : * routines are used when possible.
5458 : *
5459 : * On platforms with 128-bit integer support, the 128-bit routines will be
5460 : * used when sum(X) or sum(X*X) fit into 128-bit.
5461 : *
5462 : * For 16 and 32 bit inputs, the N and sum(X) fit into 64-bit so the 64-bit
5463 : * accumulators will be used for SUM and AVG of these data types.
5464 : */
5465 :
5466 : #ifdef HAVE_INT128
5467 : typedef struct Int128AggState
5468 : {
5469 : bool calcSumX2; /* if true, calculate sumX2 */
5470 : int64 N; /* count of processed numbers */
5471 : int128 sumX; /* sum of processed numbers */
5472 : int128 sumX2; /* sum of squares of processed numbers */
5473 : } Int128AggState;
5474 :
5475 : /*
5476 : * Prepare state data for a 128-bit aggregate function that needs to compute
5477 : * sum, count and optionally sum of squares of the input.
5478 : */
5479 : static Int128AggState *
5480 670 : makeInt128AggState(FunctionCallInfo fcinfo, bool calcSumX2)
5481 : {
5482 : Int128AggState *state;
5483 : MemoryContext agg_context;
5484 : MemoryContext old_context;
5485 :
5486 670 : if (!AggCheckCallContext(fcinfo, &agg_context))
5487 0 : elog(ERROR, "aggregate function called in non-aggregate context");
5488 :
5489 670 : old_context = MemoryContextSwitchTo(agg_context);
5490 :
5491 670 : state = (Int128AggState *) palloc0(sizeof(Int128AggState));
5492 670 : state->calcSumX2 = calcSumX2;
5493 :
5494 670 : MemoryContextSwitchTo(old_context);
5495 :
5496 670 : return state;
5497 : }
5498 :
5499 : /*
5500 : * Like makeInt128AggState(), but allocate the state in the current memory
5501 : * context.
5502 : */
5503 : static Int128AggState *
5504 26 : makeInt128AggStateCurrentContext(bool calcSumX2)
5505 : {
5506 : Int128AggState *state;
5507 :
5508 26 : state = (Int128AggState *) palloc0(sizeof(Int128AggState));
5509 26 : state->calcSumX2 = calcSumX2;
5510 :
5511 26 : return state;
5512 : }
5513 :
5514 : /*
5515 : * Accumulate a new input value for 128-bit aggregate functions.
5516 : */
5517 : static void
5518 553542 : do_int128_accum(Int128AggState *state, int128 newval)
5519 : {
5520 553542 : if (state->calcSumX2)
5521 242360 : state->sumX2 += newval * newval;
5522 :
5523 553542 : state->sumX += newval;
5524 553542 : state->N++;
5525 553542 : }
5526 :
5527 : /*
5528 : * Remove an input value from the aggregated state.
5529 : */
5530 : static void
5531 312 : do_int128_discard(Int128AggState *state, int128 newval)
5532 : {
5533 312 : if (state->calcSumX2)
5534 288 : state->sumX2 -= newval * newval;
5535 :
5536 312 : state->sumX -= newval;
5537 312 : state->N--;
5538 312 : }
5539 :
5540 : typedef Int128AggState PolyNumAggState;
5541 : #define makePolyNumAggState makeInt128AggState
5542 : #define makePolyNumAggStateCurrentContext makeInt128AggStateCurrentContext
5543 : #else
5544 : typedef NumericAggState PolyNumAggState;
5545 : #define makePolyNumAggState makeNumericAggState
5546 : #define makePolyNumAggStateCurrentContext makeNumericAggStateCurrentContext
5547 : #endif
5548 :
5549 : Datum
5550 198 : int2_accum(PG_FUNCTION_ARGS)
5551 : {
5552 : PolyNumAggState *state;
5553 :
5554 198 : state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
5555 :
5556 : /* Create the state data on the first call */
5557 198 : if (state == NULL)
5558 36 : state = makePolyNumAggState(fcinfo, true);
5559 :
5560 198 : if (!PG_ARGISNULL(1))
5561 : {
5562 : #ifdef HAVE_INT128
5563 180 : do_int128_accum(state, (int128) PG_GETARG_INT16(1));
5564 : #else
5565 : do_numeric_accum(state, int64_to_numeric(PG_GETARG_INT16(1)));
5566 : #endif
5567 : }
5568 :
5569 198 : PG_RETURN_POINTER(state);
5570 : }
5571 :
5572 : Datum
5573 242198 : int4_accum(PG_FUNCTION_ARGS)
5574 : {
5575 : PolyNumAggState *state;
5576 :
5577 242198 : state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
5578 :
5579 : /* Create the state data on the first call */
5580 242198 : if (state == NULL)
5581 66 : state = makePolyNumAggState(fcinfo, true);
5582 :
5583 242198 : if (!PG_ARGISNULL(1))
5584 : {
5585 : #ifdef HAVE_INT128
5586 242180 : do_int128_accum(state, (int128) PG_GETARG_INT32(1));
5587 : #else
5588 : do_numeric_accum(state, int64_to_numeric(PG_GETARG_INT32(1)));
5589 : #endif
5590 : }
5591 :
5592 242198 : PG_RETURN_POINTER(state);
5593 : }
5594 :
5595 : Datum
5596 240198 : int8_accum(PG_FUNCTION_ARGS)
5597 : {
5598 : NumericAggState *state;
5599 :
5600 240198 : state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
5601 :
5602 : /* Create the state data on the first call */
5603 240198 : if (state == NULL)
5604 50 : state = makeNumericAggState(fcinfo, true);
5605 :
5606 240198 : if (!PG_ARGISNULL(1))
5607 240180 : do_numeric_accum(state, int64_to_numeric(PG_GETARG_INT64(1)));
5608 :
5609 240198 : PG_RETURN_POINTER(state);
5610 : }
5611 :
5612 : /*
5613 : * Combine function for numeric aggregates which require sumX2
5614 : */
5615 : Datum
5616 10 : numeric_poly_combine(PG_FUNCTION_ARGS)
5617 : {
5618 : PolyNumAggState *state1;
5619 : PolyNumAggState *state2;
5620 : MemoryContext agg_context;
5621 : MemoryContext old_context;
5622 :
5623 10 : if (!AggCheckCallContext(fcinfo, &agg_context))
5624 0 : elog(ERROR, "aggregate function called in non-aggregate context");
5625 :
5626 10 : state1 = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
5627 10 : state2 = PG_ARGISNULL(1) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(1);
5628 :
5629 10 : if (state2 == NULL)
5630 0 : PG_RETURN_POINTER(state1);
5631 :
5632 : /* manually copy all fields from state2 to state1 */
5633 10 : if (state1 == NULL)
5634 : {
5635 6 : old_context = MemoryContextSwitchTo(agg_context);
5636 :
5637 6 : state1 = makePolyNumAggState(fcinfo, true);
5638 6 : state1->N = state2->N;
5639 :
5640 : #ifdef HAVE_INT128
5641 6 : state1->sumX = state2->sumX;
5642 6 : state1->sumX2 = state2->sumX2;
5643 : #else
5644 : accum_sum_copy(&state1->sumX, &state2->sumX);
5645 : accum_sum_copy(&state1->sumX2, &state2->sumX2);
5646 : #endif
5647 :
5648 6 : MemoryContextSwitchTo(old_context);
5649 :
5650 6 : PG_RETURN_POINTER(state1);
5651 : }
5652 :
5653 4 : if (state2->N > 0)
5654 : {
5655 4 : state1->N += state2->N;
5656 :
5657 : #ifdef HAVE_INT128
5658 4 : state1->sumX += state2->sumX;
5659 4 : state1->sumX2 += state2->sumX2;
5660 : #else
5661 : /* The rest of this needs to work in the aggregate context */
5662 : old_context = MemoryContextSwitchTo(agg_context);
5663 :
5664 : /* Accumulate sums */
5665 : accum_sum_combine(&state1->sumX, &state2->sumX);
5666 : accum_sum_combine(&state1->sumX2, &state2->sumX2);
5667 :
5668 : MemoryContextSwitchTo(old_context);
5669 : #endif
5670 :
5671 : }
5672 4 : PG_RETURN_POINTER(state1);
5673 : }
5674 :
5675 : /*
5676 : * numeric_poly_serialize
5677 : * Serialize PolyNumAggState into bytea for aggregate functions which
5678 : * require sumX2.
5679 : */
5680 : Datum
5681 10 : numeric_poly_serialize(PG_FUNCTION_ARGS)
5682 : {
5683 : PolyNumAggState *state;
5684 : StringInfoData buf;
5685 : bytea *result;
5686 : NumericVar tmp_var;
5687 :
5688 : /* Ensure we disallow calling when not in aggregate context */
5689 10 : if (!AggCheckCallContext(fcinfo, NULL))
5690 0 : elog(ERROR, "aggregate function called in non-aggregate context");
5691 :
5692 10 : state = (PolyNumAggState *) PG_GETARG_POINTER(0);
5693 :
5694 : /*
5695 : * If the platform supports int128 then sumX and sumX2 will be a 128 bit
5696 : * integer type. Here we'll convert that into a numeric type so that the
5697 : * combine state is in the same format for both int128 enabled machines
5698 : * and machines which don't support that type. The logic here is that one
5699 : * day we might like to send these over to another server for further
5700 : * processing and we want a standard format to work with.
5701 : */
5702 :
5703 10 : init_var(&tmp_var);
5704 :
5705 10 : pq_begintypsend(&buf);
5706 :
5707 : /* N */
5708 10 : pq_sendint64(&buf, state->N);
5709 :
5710 : /* sumX */
5711 : #ifdef HAVE_INT128
5712 10 : int128_to_numericvar(state->sumX, &tmp_var);
5713 : #else
5714 : accum_sum_final(&state->sumX, &tmp_var);
5715 : #endif
5716 10 : numericvar_serialize(&buf, &tmp_var);
5717 :
5718 : /* sumX2 */
5719 : #ifdef HAVE_INT128
5720 10 : int128_to_numericvar(state->sumX2, &tmp_var);
5721 : #else
5722 : accum_sum_final(&state->sumX2, &tmp_var);
5723 : #endif
5724 10 : numericvar_serialize(&buf, &tmp_var);
5725 :
5726 10 : result = pq_endtypsend(&buf);
5727 :
5728 10 : free_var(&tmp_var);
5729 :
5730 10 : PG_RETURN_BYTEA_P(result);
5731 : }
5732 :
5733 : /*
5734 : * numeric_poly_deserialize
5735 : * Deserialize PolyNumAggState from bytea for aggregate functions which
5736 : * require sumX2.
5737 : */
5738 : Datum
5739 10 : numeric_poly_deserialize(PG_FUNCTION_ARGS)
5740 : {
5741 : bytea *sstate;
5742 : PolyNumAggState *result;
5743 : StringInfoData buf;
5744 : NumericVar tmp_var;
5745 :
5746 10 : if (!AggCheckCallContext(fcinfo, NULL))
5747 0 : elog(ERROR, "aggregate function called in non-aggregate context");
5748 :
5749 10 : sstate = PG_GETARG_BYTEA_PP(0);
5750 :
5751 10 : init_var(&tmp_var);
5752 :
5753 : /*
5754 : * Initialize a StringInfo so that we can "receive" it using the standard
5755 : * recv-function infrastructure.
5756 : */
5757 10 : initReadOnlyStringInfo(&buf, VARDATA_ANY(sstate),
5758 10 : VARSIZE_ANY_EXHDR(sstate));
5759 :
5760 10 : result = makePolyNumAggStateCurrentContext(false);
5761 :
5762 : /* N */
5763 10 : result->N = pq_getmsgint64(&buf);
5764 :
5765 : /* sumX */
5766 10 : numericvar_deserialize(&buf, &tmp_var);
5767 : #ifdef HAVE_INT128
5768 10 : numericvar_to_int128(&tmp_var, &result->sumX);
5769 : #else
5770 : accum_sum_add(&result->sumX, &tmp_var);
5771 : #endif
5772 :
5773 : /* sumX2 */
5774 10 : numericvar_deserialize(&buf, &tmp_var);
5775 : #ifdef HAVE_INT128
5776 10 : numericvar_to_int128(&tmp_var, &result->sumX2);
5777 : #else
5778 : accum_sum_add(&result->sumX2, &tmp_var);
5779 : #endif
5780 :
5781 10 : pq_getmsgend(&buf);
5782 :
5783 10 : free_var(&tmp_var);
5784 :
5785 10 : PG_RETURN_POINTER(result);
5786 : }
5787 :
5788 : /*
5789 : * Transition function for int8 input when we don't need sumX2.
5790 : */
5791 : Datum
5792 312298 : int8_avg_accum(PG_FUNCTION_ARGS)
5793 : {
5794 : PolyNumAggState *state;
5795 :
5796 312298 : state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
5797 :
5798 : /* Create the state data on the first call */
5799 312298 : if (state == NULL)
5800 550 : state = makePolyNumAggState(fcinfo, false);
5801 :
5802 312298 : if (!PG_ARGISNULL(1))
5803 : {
5804 : #ifdef HAVE_INT128
5805 311182 : do_int128_accum(state, (int128) PG_GETARG_INT64(1));
5806 : #else
5807 : do_numeric_accum(state, int64_to_numeric(PG_GETARG_INT64(1)));
5808 : #endif
5809 : }
5810 :
5811 312298 : PG_RETURN_POINTER(state);
5812 : }
5813 :
5814 : /*
5815 : * Combine function for PolyNumAggState for aggregates which don't require
5816 : * sumX2
5817 : */
5818 : Datum
5819 16 : int8_avg_combine(PG_FUNCTION_ARGS)
5820 : {
5821 : PolyNumAggState *state1;
5822 : PolyNumAggState *state2;
5823 : MemoryContext agg_context;
5824 : MemoryContext old_context;
5825 :
5826 16 : if (!AggCheckCallContext(fcinfo, &agg_context))
5827 0 : elog(ERROR, "aggregate function called in non-aggregate context");
5828 :
5829 16 : state1 = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
5830 16 : state2 = PG_ARGISNULL(1) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(1);
5831 :
5832 16 : if (state2 == NULL)
5833 0 : PG_RETURN_POINTER(state1);
5834 :
5835 : /* manually copy all fields from state2 to state1 */
5836 16 : if (state1 == NULL)
5837 : {
5838 12 : old_context = MemoryContextSwitchTo(agg_context);
5839 :
5840 12 : state1 = makePolyNumAggState(fcinfo, false);
5841 12 : state1->N = state2->N;
5842 :
5843 : #ifdef HAVE_INT128
5844 12 : state1->sumX = state2->sumX;
5845 : #else
5846 : accum_sum_copy(&state1->sumX, &state2->sumX);
5847 : #endif
5848 12 : MemoryContextSwitchTo(old_context);
5849 :
5850 12 : PG_RETURN_POINTER(state1);
5851 : }
5852 :
5853 4 : if (state2->N > 0)
5854 : {
5855 4 : state1->N += state2->N;
5856 :
5857 : #ifdef HAVE_INT128
5858 4 : state1->sumX += state2->sumX;
5859 : #else
5860 : /* The rest of this needs to work in the aggregate context */
5861 : old_context = MemoryContextSwitchTo(agg_context);
5862 :
5863 : /* Accumulate sums */
5864 : accum_sum_combine(&state1->sumX, &state2->sumX);
5865 :
5866 : MemoryContextSwitchTo(old_context);
5867 : #endif
5868 :
5869 : }
5870 4 : PG_RETURN_POINTER(state1);
5871 : }
5872 :
5873 : /*
5874 : * int8_avg_serialize
5875 : * Serialize PolyNumAggState into bytea using the standard
5876 : * recv-function infrastructure.
5877 : */
5878 : Datum
5879 16 : int8_avg_serialize(PG_FUNCTION_ARGS)
5880 : {
5881 : PolyNumAggState *state;
5882 : StringInfoData buf;
5883 : bytea *result;
5884 : NumericVar tmp_var;
5885 :
5886 : /* Ensure we disallow calling when not in aggregate context */
5887 16 : if (!AggCheckCallContext(fcinfo, NULL))
5888 0 : elog(ERROR, "aggregate function called in non-aggregate context");
5889 :
5890 16 : state = (PolyNumAggState *) PG_GETARG_POINTER(0);
5891 :
5892 : /*
5893 : * If the platform supports int128 then sumX will be a 128 integer type.
5894 : * Here we'll convert that into a numeric type so that the combine state
5895 : * is in the same format for both int128 enabled machines and machines
5896 : * which don't support that type. The logic here is that one day we might
5897 : * like to send these over to another server for further processing and we
5898 : * want a standard format to work with.
5899 : */
5900 :
5901 16 : init_var(&tmp_var);
5902 :
5903 16 : pq_begintypsend(&buf);
5904 :
5905 : /* N */
5906 16 : pq_sendint64(&buf, state->N);
5907 :
5908 : /* sumX */
5909 : #ifdef HAVE_INT128
5910 16 : int128_to_numericvar(state->sumX, &tmp_var);
5911 : #else
5912 : accum_sum_final(&state->sumX, &tmp_var);
5913 : #endif
5914 16 : numericvar_serialize(&buf, &tmp_var);
5915 :
5916 16 : result = pq_endtypsend(&buf);
5917 :
5918 16 : free_var(&tmp_var);
5919 :
5920 16 : PG_RETURN_BYTEA_P(result);
5921 : }
5922 :
5923 : /*
5924 : * int8_avg_deserialize
5925 : * Deserialize bytea back into PolyNumAggState.
5926 : */
5927 : Datum
5928 16 : int8_avg_deserialize(PG_FUNCTION_ARGS)
5929 : {
5930 : bytea *sstate;
5931 : PolyNumAggState *result;
5932 : StringInfoData buf;
5933 : NumericVar tmp_var;
5934 :
5935 16 : if (!AggCheckCallContext(fcinfo, NULL))
5936 0 : elog(ERROR, "aggregate function called in non-aggregate context");
5937 :
5938 16 : sstate = PG_GETARG_BYTEA_PP(0);
5939 :
5940 16 : init_var(&tmp_var);
5941 :
5942 : /*
5943 : * Initialize a StringInfo so that we can "receive" it using the standard
5944 : * recv-function infrastructure.
5945 : */
5946 16 : initReadOnlyStringInfo(&buf, VARDATA_ANY(sstate),
5947 16 : VARSIZE_ANY_EXHDR(sstate));
5948 :
5949 16 : result = makePolyNumAggStateCurrentContext(false);
5950 :
5951 : /* N */
5952 16 : result->N = pq_getmsgint64(&buf);
5953 :
5954 : /* sumX */
5955 16 : numericvar_deserialize(&buf, &tmp_var);
5956 : #ifdef HAVE_INT128
5957 16 : numericvar_to_int128(&tmp_var, &result->sumX);
5958 : #else
5959 : accum_sum_add(&result->sumX, &tmp_var);
5960 : #endif
5961 :
5962 16 : pq_getmsgend(&buf);
5963 :
5964 16 : free_var(&tmp_var);
5965 :
5966 16 : PG_RETURN_POINTER(result);
5967 : }
5968 :
5969 : /*
5970 : * Inverse transition functions to go with the above.
5971 : */
5972 :
5973 : Datum
5974 162 : int2_accum_inv(PG_FUNCTION_ARGS)
5975 : {
5976 : PolyNumAggState *state;
5977 :
5978 162 : state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
5979 :
5980 : /* Should not get here with no state */
5981 162 : if (state == NULL)
5982 0 : elog(ERROR, "int2_accum_inv called with NULL state");
5983 :
5984 162 : if (!PG_ARGISNULL(1))
5985 : {
5986 : #ifdef HAVE_INT128
5987 144 : do_int128_discard(state, (int128) PG_GETARG_INT16(1));
5988 : #else
5989 : /* Should never fail, all inputs have dscale 0 */
5990 : if (!do_numeric_discard(state, int64_to_numeric(PG_GETARG_INT16(1))))
5991 : elog(ERROR, "do_numeric_discard failed unexpectedly");
5992 : #endif
5993 : }
5994 :
5995 162 : PG_RETURN_POINTER(state);
5996 : }
5997 :
5998 : Datum
5999 162 : int4_accum_inv(PG_FUNCTION_ARGS)
6000 : {
6001 : PolyNumAggState *state;
6002 :
6003 162 : state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
6004 :
6005 : /* Should not get here with no state */
6006 162 : if (state == NULL)
6007 0 : elog(ERROR, "int4_accum_inv called with NULL state");
6008 :
6009 162 : if (!PG_ARGISNULL(1))
6010 : {
6011 : #ifdef HAVE_INT128
6012 144 : do_int128_discard(state, (int128) PG_GETARG_INT32(1));
6013 : #else
6014 : /* Should never fail, all inputs have dscale 0 */
6015 : if (!do_numeric_discard(state, int64_to_numeric(PG_GETARG_INT32(1))))
6016 : elog(ERROR, "do_numeric_discard failed unexpectedly");
6017 : #endif
6018 : }
6019 :
6020 162 : PG_RETURN_POINTER(state);
6021 : }
6022 :
6023 : Datum
6024 162 : int8_accum_inv(PG_FUNCTION_ARGS)
6025 : {
6026 : NumericAggState *state;
6027 :
6028 162 : state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
6029 :
6030 : /* Should not get here with no state */
6031 162 : if (state == NULL)
6032 0 : elog(ERROR, "int8_accum_inv called with NULL state");
6033 :
6034 162 : if (!PG_ARGISNULL(1))
6035 : {
6036 : /* Should never fail, all inputs have dscale 0 */
6037 144 : if (!do_numeric_discard(state, int64_to_numeric(PG_GETARG_INT64(1))))
6038 0 : elog(ERROR, "do_numeric_discard failed unexpectedly");
6039 : }
6040 :
6041 162 : PG_RETURN_POINTER(state);
6042 : }
6043 :
6044 : Datum
6045 36 : int8_avg_accum_inv(PG_FUNCTION_ARGS)
6046 : {
6047 : PolyNumAggState *state;
6048 :
6049 36 : state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
6050 :
6051 : /* Should not get here with no state */
6052 36 : if (state == NULL)
6053 0 : elog(ERROR, "int8_avg_accum_inv called with NULL state");
6054 :
6055 36 : if (!PG_ARGISNULL(1))
6056 : {
6057 : #ifdef HAVE_INT128
6058 24 : do_int128_discard(state, (int128) PG_GETARG_INT64(1));
6059 : #else
6060 : /* Should never fail, all inputs have dscale 0 */
6061 : if (!do_numeric_discard(state, int64_to_numeric(PG_GETARG_INT64(1))))
6062 : elog(ERROR, "do_numeric_discard failed unexpectedly");
6063 : #endif
6064 : }
6065 :
6066 36 : PG_RETURN_POINTER(state);
6067 : }
6068 :
6069 : Datum
6070 780 : numeric_poly_sum(PG_FUNCTION_ARGS)
6071 : {
6072 : #ifdef HAVE_INT128
6073 : PolyNumAggState *state;
6074 : Numeric res;
6075 : NumericVar result;
6076 :
6077 780 : state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
6078 :
6079 : /* If there were no non-null inputs, return NULL */
6080 780 : if (state == NULL || state->N == 0)
6081 24 : PG_RETURN_NULL();
6082 :
6083 756 : init_var(&result);
6084 :
6085 756 : int128_to_numericvar(state->sumX, &result);
6086 :
6087 756 : res = make_result(&result);
6088 :
6089 756 : free_var(&result);
6090 :
6091 756 : PG_RETURN_NUMERIC(res);
6092 : #else
6093 : return numeric_sum(fcinfo);
6094 : #endif
6095 : }
6096 :
6097 : Datum
6098 36 : numeric_poly_avg(PG_FUNCTION_ARGS)
6099 : {
6100 : #ifdef HAVE_INT128
6101 : PolyNumAggState *state;
6102 : NumericVar result;
6103 : Datum countd,
6104 : sumd;
6105 :
6106 36 : state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
6107 :
6108 : /* If there were no non-null inputs, return NULL */
6109 36 : if (state == NULL || state->N == 0)
6110 18 : PG_RETURN_NULL();
6111 :
6112 18 : init_var(&result);
6113 :
6114 18 : int128_to_numericvar(state->sumX, &result);
6115 :
6116 18 : countd = NumericGetDatum(int64_to_numeric(state->N));
6117 18 : sumd = NumericGetDatum(make_result(&result));
6118 :
6119 18 : free_var(&result);
6120 :
6121 18 : PG_RETURN_DATUM(DirectFunctionCall2(numeric_div, sumd, countd));
6122 : #else
6123 : return numeric_avg(fcinfo);
6124 : #endif
6125 : }
6126 :
6127 : Datum
6128 78 : numeric_avg(PG_FUNCTION_ARGS)
6129 : {
6130 : NumericAggState *state;
6131 : Datum N_datum;
6132 : Datum sumX_datum;
6133 : NumericVar sumX_var;
6134 :
6135 78 : state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
6136 :
6137 : /* If there were no non-null inputs, return NULL */
6138 78 : if (state == NULL || NA_TOTAL_COUNT(state) == 0)
6139 18 : PG_RETURN_NULL();
6140 :
6141 60 : if (state->NaNcount > 0) /* there was at least one NaN input */
6142 6 : PG_RETURN_NUMERIC(make_result(&const_nan));
6143 :
6144 : /* adding plus and minus infinities gives NaN */
6145 54 : if (state->pInfcount > 0 && state->nInfcount > 0)
6146 6 : PG_RETURN_NUMERIC(make_result(&const_nan));
6147 48 : if (state->pInfcount > 0)
6148 18 : PG_RETURN_NUMERIC(make_result(&const_pinf));
6149 30 : if (state->nInfcount > 0)
6150 6 : PG_RETURN_NUMERIC(make_result(&const_ninf));
6151 :
6152 24 : N_datum = NumericGetDatum(int64_to_numeric(state->N));
6153 :
6154 24 : init_var(&sumX_var);
6155 24 : accum_sum_final(&state->sumX, &sumX_var);
6156 24 : sumX_datum = NumericGetDatum(make_result(&sumX_var));
6157 24 : free_var(&sumX_var);
6158 :
6159 24 : PG_RETURN_DATUM(DirectFunctionCall2(numeric_div, sumX_datum, N_datum));
6160 : }
6161 :
6162 : Datum
6163 170906 : numeric_sum(PG_FUNCTION_ARGS)
6164 : {
6165 : NumericAggState *state;
6166 : NumericVar sumX_var;
6167 : Numeric result;
6168 :
6169 170906 : state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
6170 :
6171 : /* If there were no non-null inputs, return NULL */
6172 170906 : if (state == NULL || NA_TOTAL_COUNT(state) == 0)
6173 18 : PG_RETURN_NULL();
6174 :
6175 170888 : if (state->NaNcount > 0) /* there was at least one NaN input */
6176 18 : PG_RETURN_NUMERIC(make_result(&const_nan));
6177 :
6178 : /* adding plus and minus infinities gives NaN */
6179 170870 : if (state->pInfcount > 0 && state->nInfcount > 0)
6180 6 : PG_RETURN_NUMERIC(make_result(&const_nan));
6181 170864 : if (state->pInfcount > 0)
6182 18 : PG_RETURN_NUMERIC(make_result(&const_pinf));
6183 170846 : if (state->nInfcount > 0)
6184 6 : PG_RETURN_NUMERIC(make_result(&const_ninf));
6185 :
6186 170840 : init_var(&sumX_var);
6187 170840 : accum_sum_final(&state->sumX, &sumX_var);
6188 170840 : result = make_result(&sumX_var);
6189 170840 : free_var(&sumX_var);
6190 :
6191 170840 : PG_RETURN_NUMERIC(result);
6192 : }
6193 :
6194 : /*
6195 : * Workhorse routine for the standard deviance and variance
6196 : * aggregates. 'state' is aggregate's transition state.
6197 : * 'variance' specifies whether we should calculate the
6198 : * variance or the standard deviation. 'sample' indicates whether the
6199 : * caller is interested in the sample or the population
6200 : * variance/stddev.
6201 : *
6202 : * If appropriate variance statistic is undefined for the input,
6203 : * *is_null is set to true and NULL is returned.
6204 : */
6205 : static Numeric
6206 986 : numeric_stddev_internal(NumericAggState *state,
6207 : bool variance, bool sample,
6208 : bool *is_null)
6209 : {
6210 : Numeric res;
6211 : NumericVar vN,
6212 : vsumX,
6213 : vsumX2,
6214 : vNminus1;
6215 : int64 totCount;
6216 : int rscale;
6217 :
6218 : /*
6219 : * Sample stddev and variance are undefined when N <= 1; population stddev
6220 : * is undefined when N == 0. Return NULL in either case (note that NaNs
6221 : * and infinities count as normal inputs for this purpose).
6222 : */
6223 986 : if (state == NULL || (totCount = NA_TOTAL_COUNT(state)) == 0)
6224 : {
6225 0 : *is_null = true;
6226 0 : return NULL;
6227 : }
6228 :
6229 986 : if (sample && totCount <= 1)
6230 : {
6231 132 : *is_null = true;
6232 132 : return NULL;
6233 : }
6234 :
6235 854 : *is_null = false;
6236 :
6237 : /*
6238 : * Deal with NaN and infinity cases. By analogy to the behavior of the
6239 : * float8 functions, any infinity input produces NaN output.
6240 : */
6241 854 : if (state->NaNcount > 0 || state->pInfcount > 0 || state->nInfcount > 0)
6242 54 : return make_result(&const_nan);
6243 :
6244 : /* OK, normal calculation applies */
6245 800 : init_var(&vN);
6246 800 : init_var(&vsumX);
6247 800 : init_var(&vsumX2);
6248 :
6249 800 : int64_to_numericvar(state->N, &vN);
6250 800 : accum_sum_final(&(state->sumX), &vsumX);
6251 800 : accum_sum_final(&(state->sumX2), &vsumX2);
6252 :
6253 800 : init_var(&vNminus1);
6254 800 : sub_var(&vN, &const_one, &vNminus1);
6255 :
6256 : /* compute rscale for mul_var calls */
6257 800 : rscale = vsumX.dscale * 2;
6258 :
6259 800 : mul_var(&vsumX, &vsumX, &vsumX, rscale); /* vsumX = sumX * sumX */
6260 800 : mul_var(&vN, &vsumX2, &vsumX2, rscale); /* vsumX2 = N * sumX2 */
6261 800 : sub_var(&vsumX2, &vsumX, &vsumX2); /* N * sumX2 - sumX * sumX */
6262 :
6263 800 : if (cmp_var(&vsumX2, &const_zero) <= 0)
6264 : {
6265 : /* Watch out for roundoff error producing a negative numerator */
6266 80 : res = make_result(&const_zero);
6267 : }
6268 : else
6269 : {
6270 720 : if (sample)
6271 492 : mul_var(&vN, &vNminus1, &vNminus1, 0); /* N * (N - 1) */
6272 : else
6273 228 : mul_var(&vN, &vN, &vNminus1, 0); /* N * N */
6274 720 : rscale = select_div_scale(&vsumX2, &vNminus1);
6275 720 : div_var(&vsumX2, &vNminus1, &vsumX, rscale, true); /* variance */
6276 720 : if (!variance)
6277 378 : sqrt_var(&vsumX, &vsumX, rscale); /* stddev */
6278 :
6279 720 : res = make_result(&vsumX);
6280 : }
6281 :
6282 800 : free_var(&vNminus1);
6283 800 : free_var(&vsumX);
6284 800 : free_var(&vsumX2);
6285 :
6286 800 : return res;
6287 : }
6288 :
6289 : Datum
6290 180 : numeric_var_samp(PG_FUNCTION_ARGS)
6291 : {
6292 : NumericAggState *state;
6293 : Numeric res;
6294 : bool is_null;
6295 :
6296 180 : state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
6297 :
6298 180 : res = numeric_stddev_internal(state, true, true, &is_null);
6299 :
6300 180 : if (is_null)
6301 42 : PG_RETURN_NULL();
6302 : else
6303 138 : PG_RETURN_NUMERIC(res);
6304 : }
6305 :
6306 : Datum
6307 174 : numeric_stddev_samp(PG_FUNCTION_ARGS)
6308 : {
6309 : NumericAggState *state;
6310 : Numeric res;
6311 : bool is_null;
6312 :
6313 174 : state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
6314 :
6315 174 : res = numeric_stddev_internal(state, false, true, &is_null);
6316 :
6317 174 : if (is_null)
6318 42 : PG_RETURN_NULL();
6319 : else
6320 132 : PG_RETURN_NUMERIC(res);
6321 : }
6322 :
6323 : Datum
6324 114 : numeric_var_pop(PG_FUNCTION_ARGS)
6325 : {
6326 : NumericAggState *state;
6327 : Numeric res;
6328 : bool is_null;
6329 :
6330 114 : state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
6331 :
6332 114 : res = numeric_stddev_internal(state, true, false, &is_null);
6333 :
6334 114 : if (is_null)
6335 0 : PG_RETURN_NULL();
6336 : else
6337 114 : PG_RETURN_NUMERIC(res);
6338 : }
6339 :
6340 : Datum
6341 96 : numeric_stddev_pop(PG_FUNCTION_ARGS)
6342 : {
6343 : NumericAggState *state;
6344 : Numeric res;
6345 : bool is_null;
6346 :
6347 96 : state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0);
6348 :
6349 96 : res = numeric_stddev_internal(state, false, false, &is_null);
6350 :
6351 96 : if (is_null)
6352 0 : PG_RETURN_NULL();
6353 : else
6354 96 : PG_RETURN_NUMERIC(res);
6355 : }
6356 :
6357 : #ifdef HAVE_INT128
6358 : static Numeric
6359 422 : numeric_poly_stddev_internal(Int128AggState *state,
6360 : bool variance, bool sample,
6361 : bool *is_null)
6362 : {
6363 : NumericAggState numstate;
6364 : Numeric res;
6365 :
6366 : /* Initialize an empty agg state */
6367 422 : memset(&numstate, 0, sizeof(NumericAggState));
6368 :
6369 422 : if (state)
6370 : {
6371 : NumericVar tmp_var;
6372 :
6373 422 : numstate.N = state->N;
6374 :
6375 422 : init_var(&tmp_var);
6376 :
6377 422 : int128_to_numericvar(state->sumX, &tmp_var);
6378 422 : accum_sum_add(&numstate.sumX, &tmp_var);
6379 :
6380 422 : int128_to_numericvar(state->sumX2, &tmp_var);
6381 422 : accum_sum_add(&numstate.sumX2, &tmp_var);
6382 :
6383 422 : free_var(&tmp_var);
6384 : }
6385 :
6386 422 : res = numeric_stddev_internal(&numstate, variance, sample, is_null);
6387 :
6388 422 : if (numstate.sumX.ndigits > 0)
6389 : {
6390 422 : pfree(numstate.sumX.pos_digits);
6391 422 : pfree(numstate.sumX.neg_digits);
6392 : }
6393 422 : if (numstate.sumX2.ndigits > 0)
6394 : {
6395 422 : pfree(numstate.sumX2.pos_digits);
6396 422 : pfree(numstate.sumX2.neg_digits);
6397 : }
6398 :
6399 422 : return res;
6400 : }
6401 : #endif
6402 :
6403 : Datum
6404 126 : numeric_poly_var_samp(PG_FUNCTION_ARGS)
6405 : {
6406 : #ifdef HAVE_INT128
6407 : PolyNumAggState *state;
6408 : Numeric res;
6409 : bool is_null;
6410 :
6411 126 : state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
6412 :
6413 126 : res = numeric_poly_stddev_internal(state, true, true, &is_null);
6414 :
6415 126 : if (is_null)
6416 24 : PG_RETURN_NULL();
6417 : else
6418 102 : PG_RETURN_NUMERIC(res);
6419 : #else
6420 : return numeric_var_samp(fcinfo);
6421 : #endif
6422 : }
6423 :
6424 : Datum
6425 164 : numeric_poly_stddev_samp(PG_FUNCTION_ARGS)
6426 : {
6427 : #ifdef HAVE_INT128
6428 : PolyNumAggState *state;
6429 : Numeric res;
6430 : bool is_null;
6431 :
6432 164 : state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
6433 :
6434 164 : res = numeric_poly_stddev_internal(state, false, true, &is_null);
6435 :
6436 164 : if (is_null)
6437 24 : PG_RETURN_NULL();
6438 : else
6439 140 : PG_RETURN_NUMERIC(res);
6440 : #else
6441 : return numeric_stddev_samp(fcinfo);
6442 : #endif
6443 : }
6444 :
6445 : Datum
6446 60 : numeric_poly_var_pop(PG_FUNCTION_ARGS)
6447 : {
6448 : #ifdef HAVE_INT128
6449 : PolyNumAggState *state;
6450 : Numeric res;
6451 : bool is_null;
6452 :
6453 60 : state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
6454 :
6455 60 : res = numeric_poly_stddev_internal(state, true, false, &is_null);
6456 :
6457 60 : if (is_null)
6458 0 : PG_RETURN_NULL();
6459 : else
6460 60 : PG_RETURN_NUMERIC(res);
6461 : #else
6462 : return numeric_var_pop(fcinfo);
6463 : #endif
6464 : }
6465 :
6466 : Datum
6467 72 : numeric_poly_stddev_pop(PG_FUNCTION_ARGS)
6468 : {
6469 : #ifdef HAVE_INT128
6470 : PolyNumAggState *state;
6471 : Numeric res;
6472 : bool is_null;
6473 :
6474 72 : state = PG_ARGISNULL(0) ? NULL : (PolyNumAggState *) PG_GETARG_POINTER(0);
6475 :
6476 72 : res = numeric_poly_stddev_internal(state, false, false, &is_null);
6477 :
6478 72 : if (is_null)
6479 0 : PG_RETURN_NULL();
6480 : else
6481 72 : PG_RETURN_NUMERIC(res);
6482 : #else
6483 : return numeric_stddev_pop(fcinfo);
6484 : #endif
6485 : }
6486 :
6487 : /*
6488 : * SUM transition functions for integer datatypes.
6489 : *
6490 : * To avoid overflow, we use accumulators wider than the input datatype.
6491 : * A Numeric accumulator is needed for int8 input; for int4 and int2
6492 : * inputs, we use int8 accumulators which should be sufficient for practical
6493 : * purposes. (The latter two therefore don't really belong in this file,
6494 : * but we keep them here anyway.)
6495 : *
6496 : * Because SQL defines the SUM() of no values to be NULL, not zero,
6497 : * the initial condition of the transition data value needs to be NULL. This
6498 : * means we can't rely on ExecAgg to automatically insert the first non-null
6499 : * data value into the transition data: it doesn't know how to do the type
6500 : * conversion. The upshot is that these routines have to be marked non-strict
6501 : * and handle substitution of the first non-null input themselves.
6502 : *
6503 : * Note: these functions are used only in plain aggregation mode.
6504 : * In moving-aggregate mode, we use intX_avg_accum and intX_avg_accum_inv.
6505 : */
6506 :
6507 : Datum
6508 24 : int2_sum(PG_FUNCTION_ARGS)
6509 : {
6510 : int64 newval;
6511 :
6512 24 : if (PG_ARGISNULL(0))
6513 : {
6514 : /* No non-null input seen so far... */
6515 6 : if (PG_ARGISNULL(1))
6516 0 : PG_RETURN_NULL(); /* still no non-null */
6517 : /* This is the first non-null input. */
6518 6 : newval = (int64) PG_GETARG_INT16(1);
6519 6 : PG_RETURN_INT64(newval);
6520 : }
6521 :
6522 : /*
6523 : * If we're invoked as an aggregate, we can cheat and modify our first
6524 : * parameter in-place to avoid palloc overhead. If not, we need to return
6525 : * the new value of the transition variable. (If int8 is pass-by-value,
6526 : * then of course this is useless as well as incorrect, so just ifdef it
6527 : * out.)
6528 : */
6529 : #ifndef USE_FLOAT8_BYVAL /* controls int8 too */
6530 : if (AggCheckCallContext(fcinfo, NULL))
6531 : {
6532 : int64 *oldsum = (int64 *) PG_GETARG_POINTER(0);
6533 :
6534 : /* Leave the running sum unchanged in the new input is null */
6535 : if (!PG_ARGISNULL(1))
6536 : *oldsum = *oldsum + (int64) PG_GETARG_INT16(1);
6537 :
6538 : PG_RETURN_POINTER(oldsum);
6539 : }
6540 : else
6541 : #endif
6542 : {
6543 18 : int64 oldsum = PG_GETARG_INT64(0);
6544 :
6545 : /* Leave sum unchanged if new input is null. */
6546 18 : if (PG_ARGISNULL(1))
6547 0 : PG_RETURN_INT64(oldsum);
6548 :
6549 : /* OK to do the addition. */
6550 18 : newval = oldsum + (int64) PG_GETARG_INT16(1);
6551 :
6552 18 : PG_RETURN_INT64(newval);
6553 : }
6554 : }
6555 :
6556 : Datum
6557 3578060 : int4_sum(PG_FUNCTION_ARGS)
6558 : {
6559 : int64 newval;
6560 :
6561 3578060 : if (PG_ARGISNULL(0))
6562 : {
6563 : /* No non-null input seen so far... */
6564 206478 : if (PG_ARGISNULL(1))
6565 986 : PG_RETURN_NULL(); /* still no non-null */
6566 : /* This is the first non-null input. */
6567 205492 : newval = (int64) PG_GETARG_INT32(1);
6568 205492 : PG_RETURN_INT64(newval);
6569 : }
6570 :
6571 : /*
6572 : * If we're invoked as an aggregate, we can cheat and modify our first
6573 : * parameter in-place to avoid palloc overhead. If not, we need to return
6574 : * the new value of the transition variable. (If int8 is pass-by-value,
6575 : * then of course this is useless as well as incorrect, so just ifdef it
6576 : * out.)
6577 : */
6578 : #ifndef USE_FLOAT8_BYVAL /* controls int8 too */
6579 : if (AggCheckCallContext(fcinfo, NULL))
6580 : {
6581 : int64 *oldsum = (int64 *) PG_GETARG_POINTER(0);
6582 :
6583 : /* Leave the running sum unchanged in the new input is null */
6584 : if (!PG_ARGISNULL(1))
6585 : *oldsum = *oldsum + (int64) PG_GETARG_INT32(1);
6586 :
6587 : PG_RETURN_POINTER(oldsum);
6588 : }
6589 : else
6590 : #endif
6591 : {
6592 3371582 : int64 oldsum = PG_GETARG_INT64(0);
6593 :
6594 : /* Leave sum unchanged if new input is null. */
6595 3371582 : if (PG_ARGISNULL(1))
6596 874 : PG_RETURN_INT64(oldsum);
6597 :
6598 : /* OK to do the addition. */
6599 3370708 : newval = oldsum + (int64) PG_GETARG_INT32(1);
6600 :
6601 3370708 : PG_RETURN_INT64(newval);
6602 : }
6603 : }
6604 :
6605 : /*
6606 : * Note: this function is obsolete, it's no longer used for SUM(int8).
6607 : */
6608 : Datum
6609 0 : int8_sum(PG_FUNCTION_ARGS)
6610 : {
6611 : Numeric oldsum;
6612 :
6613 0 : if (PG_ARGISNULL(0))
6614 : {
6615 : /* No non-null input seen so far... */
6616 0 : if (PG_ARGISNULL(1))
6617 0 : PG_RETURN_NULL(); /* still no non-null */
6618 : /* This is the first non-null input. */
6619 0 : PG_RETURN_NUMERIC(int64_to_numeric(PG_GETARG_INT64(1)));
6620 : }
6621 :
6622 : /*
6623 : * Note that we cannot special-case the aggregate case here, as we do for
6624 : * int2_sum and int4_sum: numeric is of variable size, so we cannot modify
6625 : * our first parameter in-place.
6626 : */
6627 :
6628 0 : oldsum = PG_GETARG_NUMERIC(0);
6629 :
6630 : /* Leave sum unchanged if new input is null. */
6631 0 : if (PG_ARGISNULL(1))
6632 0 : PG_RETURN_NUMERIC(oldsum);
6633 :
6634 : /* OK to do the addition. */
6635 0 : PG_RETURN_DATUM(DirectFunctionCall2(numeric_add,
6636 : NumericGetDatum(oldsum),
6637 : NumericGetDatum(int64_to_numeric(PG_GETARG_INT64(1)))));
6638 : }
6639 :
6640 :
6641 : /*
6642 : * Routines for avg(int2) and avg(int4). The transition datatype
6643 : * is a two-element int8 array, holding count and sum.
6644 : *
6645 : * These functions are also used for sum(int2) and sum(int4) when
6646 : * operating in moving-aggregate mode, since for correct inverse transitions
6647 : * we need to count the inputs.
6648 : */
6649 :
6650 : typedef struct Int8TransTypeData
6651 : {
6652 : int64 count;
6653 : int64 sum;
6654 : } Int8TransTypeData;
6655 :
6656 : Datum
6657 42 : int2_avg_accum(PG_FUNCTION_ARGS)
6658 : {
6659 : ArrayType *transarray;
6660 42 : int16 newval = PG_GETARG_INT16(1);
6661 : Int8TransTypeData *transdata;
6662 :
6663 : /*
6664 : * If we're invoked as an aggregate, we can cheat and modify our first
6665 : * parameter in-place to reduce palloc overhead. Otherwise we need to make
6666 : * a copy of it before scribbling on it.
6667 : */
6668 42 : if (AggCheckCallContext(fcinfo, NULL))
6669 42 : transarray = PG_GETARG_ARRAYTYPE_P(0);
6670 : else
6671 0 : transarray = PG_GETARG_ARRAYTYPE_P_COPY(0);
6672 :
6673 42 : if (ARR_HASNULL(transarray) ||
6674 42 : ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
6675 0 : elog(ERROR, "expected 2-element int8 array");
6676 :
6677 42 : transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
6678 42 : transdata->count++;
6679 42 : transdata->sum += newval;
6680 :
6681 42 : PG_RETURN_ARRAYTYPE_P(transarray);
6682 : }
6683 :
6684 : Datum
6685 2620302 : int4_avg_accum(PG_FUNCTION_ARGS)
6686 : {
6687 : ArrayType *transarray;
6688 2620302 : int32 newval = PG_GETARG_INT32(1);
6689 : Int8TransTypeData *transdata;
6690 :
6691 : /*
6692 : * If we're invoked as an aggregate, we can cheat and modify our first
6693 : * parameter in-place to reduce palloc overhead. Otherwise we need to make
6694 : * a copy of it before scribbling on it.
6695 : */
6696 2620302 : if (AggCheckCallContext(fcinfo, NULL))
6697 2620302 : transarray = PG_GETARG_ARRAYTYPE_P(0);
6698 : else
6699 0 : transarray = PG_GETARG_ARRAYTYPE_P_COPY(0);
6700 :
6701 2620302 : if (ARR_HASNULL(transarray) ||
6702 2620302 : ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
6703 0 : elog(ERROR, "expected 2-element int8 array");
6704 :
6705 2620302 : transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
6706 2620302 : transdata->count++;
6707 2620302 : transdata->sum += newval;
6708 :
6709 2620302 : PG_RETURN_ARRAYTYPE_P(transarray);
6710 : }
6711 :
6712 : Datum
6713 3502 : int4_avg_combine(PG_FUNCTION_ARGS)
6714 : {
6715 : ArrayType *transarray1;
6716 : ArrayType *transarray2;
6717 : Int8TransTypeData *state1;
6718 : Int8TransTypeData *state2;
6719 :
6720 3502 : if (!AggCheckCallContext(fcinfo, NULL))
6721 0 : elog(ERROR, "aggregate function called in non-aggregate context");
6722 :
6723 3502 : transarray1 = PG_GETARG_ARRAYTYPE_P(0);
6724 3502 : transarray2 = PG_GETARG_ARRAYTYPE_P(1);
6725 :
6726 3502 : if (ARR_HASNULL(transarray1) ||
6727 3502 : ARR_SIZE(transarray1) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
6728 0 : elog(ERROR, "expected 2-element int8 array");
6729 :
6730 3502 : if (ARR_HASNULL(transarray2) ||
6731 3502 : ARR_SIZE(transarray2) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
6732 0 : elog(ERROR, "expected 2-element int8 array");
6733 :
6734 3502 : state1 = (Int8TransTypeData *) ARR_DATA_PTR(transarray1);
6735 3502 : state2 = (Int8TransTypeData *) ARR_DATA_PTR(transarray2);
6736 :
6737 3502 : state1->count += state2->count;
6738 3502 : state1->sum += state2->sum;
6739 :
6740 3502 : PG_RETURN_ARRAYTYPE_P(transarray1);
6741 : }
6742 :
6743 : Datum
6744 12 : int2_avg_accum_inv(PG_FUNCTION_ARGS)
6745 : {
6746 : ArrayType *transarray;
6747 12 : int16 newval = PG_GETARG_INT16(1);
6748 : Int8TransTypeData *transdata;
6749 :
6750 : /*
6751 : * If we're invoked as an aggregate, we can cheat and modify our first
6752 : * parameter in-place to reduce palloc overhead. Otherwise we need to make
6753 : * a copy of it before scribbling on it.
6754 : */
6755 12 : if (AggCheckCallContext(fcinfo, NULL))
6756 12 : transarray = PG_GETARG_ARRAYTYPE_P(0);
6757 : else
6758 0 : transarray = PG_GETARG_ARRAYTYPE_P_COPY(0);
6759 :
6760 12 : if (ARR_HASNULL(transarray) ||
6761 12 : ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
6762 0 : elog(ERROR, "expected 2-element int8 array");
6763 :
6764 12 : transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
6765 12 : transdata->count--;
6766 12 : transdata->sum -= newval;
6767 :
6768 12 : PG_RETURN_ARRAYTYPE_P(transarray);
6769 : }
6770 :
6771 : Datum
6772 1452 : int4_avg_accum_inv(PG_FUNCTION_ARGS)
6773 : {
6774 : ArrayType *transarray;
6775 1452 : int32 newval = PG_GETARG_INT32(1);
6776 : Int8TransTypeData *transdata;
6777 :
6778 : /*
6779 : * If we're invoked as an aggregate, we can cheat and modify our first
6780 : * parameter in-place to reduce palloc overhead. Otherwise we need to make
6781 : * a copy of it before scribbling on it.
6782 : */
6783 1452 : if (AggCheckCallContext(fcinfo, NULL))
6784 1452 : transarray = PG_GETARG_ARRAYTYPE_P(0);
6785 : else
6786 0 : transarray = PG_GETARG_ARRAYTYPE_P_COPY(0);
6787 :
6788 1452 : if (ARR_HASNULL(transarray) ||
6789 1452 : ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
6790 0 : elog(ERROR, "expected 2-element int8 array");
6791 :
6792 1452 : transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
6793 1452 : transdata->count--;
6794 1452 : transdata->sum -= newval;
6795 :
6796 1452 : PG_RETURN_ARRAYTYPE_P(transarray);
6797 : }
6798 :
6799 : Datum
6800 10774 : int8_avg(PG_FUNCTION_ARGS)
6801 : {
6802 10774 : ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
6803 : Int8TransTypeData *transdata;
6804 : Datum countd,
6805 : sumd;
6806 :
6807 10774 : if (ARR_HASNULL(transarray) ||
6808 10774 : ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
6809 0 : elog(ERROR, "expected 2-element int8 array");
6810 10774 : transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
6811 :
6812 : /* SQL defines AVG of no values to be NULL */
6813 10774 : if (transdata->count == 0)
6814 118 : PG_RETURN_NULL();
6815 :
6816 10656 : countd = NumericGetDatum(int64_to_numeric(transdata->count));
6817 10656 : sumd = NumericGetDatum(int64_to_numeric(transdata->sum));
6818 :
6819 10656 : PG_RETURN_DATUM(DirectFunctionCall2(numeric_div, sumd, countd));
6820 : }
6821 :
6822 : /*
6823 : * SUM(int2) and SUM(int4) both return int8, so we can use this
6824 : * final function for both.
6825 : */
6826 : Datum
6827 3834 : int2int4_sum(PG_FUNCTION_ARGS)
6828 : {
6829 3834 : ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
6830 : Int8TransTypeData *transdata;
6831 :
6832 3834 : if (ARR_HASNULL(transarray) ||
6833 3834 : ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
6834 0 : elog(ERROR, "expected 2-element int8 array");
6835 3834 : transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
6836 :
6837 : /* SQL defines SUM of no values to be NULL */
6838 3834 : if (transdata->count == 0)
6839 480 : PG_RETURN_NULL();
6840 :
6841 3354 : PG_RETURN_DATUM(Int64GetDatumFast(transdata->sum));
6842 : }
6843 :
6844 :
6845 : /* ----------------------------------------------------------------------
6846 : *
6847 : * Debug support
6848 : *
6849 : * ----------------------------------------------------------------------
6850 : */
6851 :
6852 : #ifdef NUMERIC_DEBUG
6853 :
6854 : /*
6855 : * dump_numeric() - Dump a value in the db storage format for debugging
6856 : */
6857 : static void
6858 : dump_numeric(const char *str, Numeric num)
6859 : {
6860 : NumericDigit *digits = NUMERIC_DIGITS(num);
6861 : int ndigits;
6862 : int i;
6863 :
6864 : ndigits = NUMERIC_NDIGITS(num);
6865 :
6866 : printf("%s: NUMERIC w=%d d=%d ", str,
6867 : NUMERIC_WEIGHT(num), NUMERIC_DSCALE(num));
6868 : switch (NUMERIC_SIGN(num))
6869 : {
6870 : case NUMERIC_POS:
6871 : printf("POS");
6872 : break;
6873 : case NUMERIC_NEG:
6874 : printf("NEG");
6875 : break;
6876 : case NUMERIC_NAN:
6877 : printf("NaN");
6878 : break;
6879 : case NUMERIC_PINF:
6880 : printf("Infinity");
6881 : break;
6882 : case NUMERIC_NINF:
6883 : printf("-Infinity");
6884 : break;
6885 : default:
6886 : printf("SIGN=0x%x", NUMERIC_SIGN(num));
6887 : break;
6888 : }
6889 :
6890 : for (i = 0; i < ndigits; i++)
6891 : printf(" %0*d", DEC_DIGITS, digits[i]);
6892 : printf("\n");
6893 : }
6894 :
6895 :
6896 : /*
6897 : * dump_var() - Dump a value in the variable format for debugging
6898 : */
6899 : static void
6900 : dump_var(const char *str, NumericVar *var)
6901 : {
6902 : int i;
6903 :
6904 : printf("%s: VAR w=%d d=%d ", str, var->weight, var->dscale);
6905 : switch (var->sign)
6906 : {
6907 : case NUMERIC_POS:
6908 : printf("POS");
6909 : break;
6910 : case NUMERIC_NEG:
6911 : printf("NEG");
6912 : break;
6913 : case NUMERIC_NAN:
6914 : printf("NaN");
6915 : break;
6916 : case NUMERIC_PINF:
6917 : printf("Infinity");
6918 : break;
6919 : case NUMERIC_NINF:
6920 : printf("-Infinity");
6921 : break;
6922 : default:
6923 : printf("SIGN=0x%x", var->sign);
6924 : break;
6925 : }
6926 :
6927 : for (i = 0; i < var->ndigits; i++)
6928 : printf(" %0*d", DEC_DIGITS, var->digits[i]);
6929 :
6930 : printf("\n");
6931 : }
6932 : #endif /* NUMERIC_DEBUG */
6933 :
6934 :
6935 : /* ----------------------------------------------------------------------
6936 : *
6937 : * Local functions follow
6938 : *
6939 : * In general, these do not support "special" (NaN or infinity) inputs;
6940 : * callers should handle those possibilities first.
6941 : * (There are one or two exceptions, noted in their header comments.)
6942 : *
6943 : * ----------------------------------------------------------------------
6944 : */
6945 :
6946 :
6947 : /*
6948 : * alloc_var() -
6949 : *
6950 : * Allocate a digit buffer of ndigits digits (plus a spare digit for rounding)
6951 : */
6952 : static void
6953 2106662 : alloc_var(NumericVar *var, int ndigits)
6954 : {
6955 2106662 : digitbuf_free(var->buf);
6956 2106662 : var->buf = digitbuf_alloc(ndigits + 1);
6957 2106662 : var->buf[0] = 0; /* spare digit for rounding */
6958 2106662 : var->digits = var->buf + 1;
6959 2106662 : var->ndigits = ndigits;
6960 2106662 : }
6961 :
6962 :
6963 : /*
6964 : * free_var() -
6965 : *
6966 : * Return the digit buffer of a variable to the free pool
6967 : */
6968 : static void
6969 3417572 : free_var(NumericVar *var)
6970 : {
6971 3417572 : digitbuf_free(var->buf);
6972 3417572 : var->buf = NULL;
6973 3417572 : var->digits = NULL;
6974 3417572 : var->sign = NUMERIC_NAN;
6975 3417572 : }
6976 :
6977 :
6978 : /*
6979 : * zero_var() -
6980 : *
6981 : * Set a variable to ZERO.
6982 : * Note: its dscale is not touched.
6983 : */
6984 : static void
6985 40094 : zero_var(NumericVar *var)
6986 : {
6987 40094 : digitbuf_free(var->buf);
6988 40094 : var->buf = NULL;
6989 40094 : var->digits = NULL;
6990 40094 : var->ndigits = 0;
6991 40094 : var->weight = 0; /* by convention; doesn't really matter */
6992 40094 : var->sign = NUMERIC_POS; /* anything but NAN... */
6993 40094 : }
6994 :
6995 :
6996 : /*
6997 : * set_var_from_str()
6998 : *
6999 : * Parse a string and put the number into a variable
7000 : *
7001 : * This function does not handle leading or trailing spaces. It returns
7002 : * the end+1 position parsed into *endptr, so that caller can check for
7003 : * trailing spaces/garbage if deemed necessary.
7004 : *
7005 : * cp is the place to actually start parsing; str is what to use in error
7006 : * reports. (Typically cp would be the same except advanced over spaces.)
7007 : *
7008 : * Returns true on success, false on failure (if escontext points to an
7009 : * ErrorSaveContext; otherwise errors are thrown).
7010 : */
7011 : static bool
7012 127870 : set_var_from_str(const char *str, const char *cp,
7013 : NumericVar *dest, const char **endptr,
7014 : Node *escontext)
7015 : {
7016 127870 : bool have_dp = false;
7017 : int i;
7018 : unsigned char *decdigits;
7019 127870 : int sign = NUMERIC_POS;
7020 127870 : int dweight = -1;
7021 : int ddigits;
7022 127870 : int dscale = 0;
7023 : int weight;
7024 : int ndigits;
7025 : int offset;
7026 : NumericDigit *digits;
7027 :
7028 : /*
7029 : * We first parse the string to extract decimal digits and determine the
7030 : * correct decimal weight. Then convert to NBASE representation.
7031 : */
7032 127870 : switch (*cp)
7033 : {
7034 0 : case '+':
7035 0 : sign = NUMERIC_POS;
7036 0 : cp++;
7037 0 : break;
7038 :
7039 300 : case '-':
7040 300 : sign = NUMERIC_NEG;
7041 300 : cp++;
7042 300 : break;
7043 : }
7044 :
7045 127870 : if (*cp == '.')
7046 : {
7047 382 : have_dp = true;
7048 382 : cp++;
7049 : }
7050 :
7051 127870 : if (!isdigit((unsigned char) *cp))
7052 0 : goto invalid_syntax;
7053 :
7054 127870 : decdigits = (unsigned char *) palloc(strlen(cp) + DEC_DIGITS * 2);
7055 :
7056 : /* leading padding for digit alignment later */
7057 127870 : memset(decdigits, 0, DEC_DIGITS);
7058 127870 : i = DEC_DIGITS;
7059 :
7060 523170 : while (*cp)
7061 : {
7062 396608 : if (isdigit((unsigned char) *cp))
7063 : {
7064 378820 : decdigits[i++] = *cp++ - '0';
7065 378820 : if (!have_dp)
7066 307124 : dweight++;
7067 : else
7068 71696 : dscale++;
7069 : }
7070 17788 : else if (*cp == '.')
7071 : {
7072 16318 : if (have_dp)
7073 0 : goto invalid_syntax;
7074 16318 : have_dp = true;
7075 16318 : cp++;
7076 : /* decimal point must not be followed by underscore */
7077 16318 : if (*cp == '_')
7078 6 : goto invalid_syntax;
7079 : }
7080 1470 : else if (*cp == '_')
7081 : {
7082 : /* underscore must be followed by more digits */
7083 186 : cp++;
7084 186 : if (!isdigit((unsigned char) *cp))
7085 18 : goto invalid_syntax;
7086 : }
7087 : else
7088 1284 : break;
7089 : }
7090 :
7091 127846 : ddigits = i - DEC_DIGITS;
7092 : /* trailing padding for digit alignment later */
7093 127846 : memset(decdigits + i, 0, DEC_DIGITS - 1);
7094 :
7095 : /* Handle exponent, if any */
7096 127846 : if (*cp == 'e' || *cp == 'E')
7097 : {
7098 1236 : int64 exponent = 0;
7099 1236 : bool neg = false;
7100 :
7101 : /*
7102 : * At this point, dweight and dscale can't be more than about
7103 : * INT_MAX/2 due to the MaxAllocSize limit on string length, so
7104 : * constraining the exponent similarly should be enough to prevent
7105 : * integer overflow in this function. If the value is too large to
7106 : * fit in storage format, make_result() will complain about it later;
7107 : * for consistency use the same ereport errcode/text as make_result().
7108 : */
7109 :
7110 : /* exponent sign */
7111 1236 : cp++;
7112 1236 : if (*cp == '+')
7113 154 : cp++;
7114 1082 : else if (*cp == '-')
7115 : {
7116 470 : neg = true;
7117 470 : cp++;
7118 : }
7119 :
7120 : /* exponent digits */
7121 1236 : if (!isdigit((unsigned char) *cp))
7122 6 : goto invalid_syntax;
7123 :
7124 4332 : while (*cp)
7125 : {
7126 3120 : if (isdigit((unsigned char) *cp))
7127 : {
7128 3078 : exponent = exponent * 10 + (*cp++ - '0');
7129 3078 : if (exponent > PG_INT32_MAX / 2)
7130 6 : goto out_of_range;
7131 : }
7132 42 : else if (*cp == '_')
7133 : {
7134 : /* underscore must be followed by more digits */
7135 42 : cp++;
7136 42 : if (!isdigit((unsigned char) *cp))
7137 12 : goto invalid_syntax;
7138 : }
7139 : else
7140 0 : break;
7141 : }
7142 :
7143 1212 : if (neg)
7144 470 : exponent = -exponent;
7145 :
7146 1212 : dweight += (int) exponent;
7147 1212 : dscale -= (int) exponent;
7148 1212 : if (dscale < 0)
7149 538 : dscale = 0;
7150 : }
7151 :
7152 : /*
7153 : * Okay, convert pure-decimal representation to base NBASE. First we need
7154 : * to determine the converted weight and ndigits. offset is the number of
7155 : * decimal zeroes to insert before the first given digit to have a
7156 : * correctly aligned first NBASE digit.
7157 : */
7158 127822 : if (dweight >= 0)
7159 127072 : weight = (dweight + 1 + DEC_DIGITS - 1) / DEC_DIGITS - 1;
7160 : else
7161 750 : weight = -((-dweight - 1) / DEC_DIGITS + 1);
7162 127822 : offset = (weight + 1) * DEC_DIGITS - (dweight + 1);
7163 127822 : ndigits = (ddigits + offset + DEC_DIGITS - 1) / DEC_DIGITS;
7164 :
7165 127822 : alloc_var(dest, ndigits);
7166 127822 : dest->sign = sign;
7167 127822 : dest->weight = weight;
7168 127822 : dest->dscale = dscale;
7169 :
7170 127822 : i = DEC_DIGITS - offset;
7171 127822 : digits = dest->digits;
7172 :
7173 301454 : while (ndigits-- > 0)
7174 : {
7175 : #if DEC_DIGITS == 4
7176 173632 : *digits++ = ((decdigits[i] * 10 + decdigits[i + 1]) * 10 +
7177 173632 : decdigits[i + 2]) * 10 + decdigits[i + 3];
7178 : #elif DEC_DIGITS == 2
7179 : *digits++ = decdigits[i] * 10 + decdigits[i + 1];
7180 : #elif DEC_DIGITS == 1
7181 : *digits++ = decdigits[i];
7182 : #else
7183 : #error unsupported NBASE
7184 : #endif
7185 173632 : i += DEC_DIGITS;
7186 : }
7187 :
7188 127822 : pfree(decdigits);
7189 :
7190 : /* Strip any leading/trailing zeroes, and normalize weight if zero */
7191 127822 : strip_var(dest);
7192 :
7193 : /* Return end+1 position for caller */
7194 127822 : *endptr = cp;
7195 :
7196 127822 : return true;
7197 :
7198 6 : out_of_range:
7199 6 : ereturn(escontext, false,
7200 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
7201 : errmsg("value overflows numeric format")));
7202 :
7203 42 : invalid_syntax:
7204 42 : ereturn(escontext, false,
7205 : (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
7206 : errmsg("invalid input syntax for type %s: \"%s\"",
7207 : "numeric", str)));
7208 : }
7209 :
7210 :
7211 : /*
7212 : * Return the numeric value of a single hex digit.
7213 : */
7214 : static inline int
7215 708 : xdigit_value(char dig)
7216 : {
7217 894 : return dig >= '0' && dig <= '9' ? dig - '0' :
7218 294 : dig >= 'a' && dig <= 'f' ? dig - 'a' + 10 :
7219 108 : dig >= 'A' && dig <= 'F' ? dig - 'A' + 10 : -1;
7220 : }
7221 :
7222 : /*
7223 : * set_var_from_non_decimal_integer_str()
7224 : *
7225 : * Parse a string containing a non-decimal integer
7226 : *
7227 : * This function does not handle leading or trailing spaces. It returns
7228 : * the end+1 position parsed into *endptr, so that caller can check for
7229 : * trailing spaces/garbage if deemed necessary.
7230 : *
7231 : * cp is the place to actually start parsing; str is what to use in error
7232 : * reports. The number's sign and base prefix indicator (e.g., "0x") are
7233 : * assumed to have already been parsed, so cp should point to the number's
7234 : * first digit in the base specified.
7235 : *
7236 : * base is expected to be 2, 8 or 16.
7237 : *
7238 : * Returns true on success, false on failure (if escontext points to an
7239 : * ErrorSaveContext; otherwise errors are thrown).
7240 : */
7241 : static bool
7242 156 : set_var_from_non_decimal_integer_str(const char *str, const char *cp, int sign,
7243 : int base, NumericVar *dest,
7244 : const char **endptr, Node *escontext)
7245 : {
7246 156 : const char *firstdigit = cp;
7247 : int64 tmp;
7248 : int64 mul;
7249 : NumericVar tmp_var;
7250 :
7251 156 : init_var(&tmp_var);
7252 :
7253 156 : zero_var(dest);
7254 :
7255 : /*
7256 : * Process input digits in groups that fit in int64. Here "tmp" is the
7257 : * value of the digits in the group, and "mul" is base^n, where n is the
7258 : * number of digits in the group. Thus tmp < mul, and we must start a new
7259 : * group when mul * base threatens to overflow PG_INT64_MAX.
7260 : */
7261 156 : tmp = 0;
7262 156 : mul = 1;
7263 :
7264 156 : if (base == 16)
7265 : {
7266 828 : while (*cp)
7267 : {
7268 798 : if (isxdigit((unsigned char) *cp))
7269 : {
7270 708 : if (mul > PG_INT64_MAX / 16)
7271 : {
7272 : /* Add the contribution from this group of digits */
7273 30 : int64_to_numericvar(mul, &tmp_var);
7274 30 : mul_var(dest, &tmp_var, dest, 0);
7275 30 : int64_to_numericvar(tmp, &tmp_var);
7276 30 : add_var(dest, &tmp_var, dest);
7277 :
7278 : /* Result will overflow if weight overflows int16 */
7279 30 : if (dest->weight > NUMERIC_WEIGHT_MAX)
7280 0 : goto out_of_range;
7281 :
7282 : /* Begin a new group */
7283 30 : tmp = 0;
7284 30 : mul = 1;
7285 : }
7286 :
7287 708 : tmp = tmp * 16 + xdigit_value(*cp++);
7288 708 : mul = mul * 16;
7289 : }
7290 90 : else if (*cp == '_')
7291 : {
7292 : /* Underscore must be followed by more digits */
7293 66 : cp++;
7294 66 : if (!isxdigit((unsigned char) *cp))
7295 18 : goto invalid_syntax;
7296 : }
7297 : else
7298 24 : break;
7299 : }
7300 : }
7301 84 : else if (base == 8)
7302 : {
7303 636 : while (*cp)
7304 : {
7305 606 : if (*cp >= '0' && *cp <= '7')
7306 : {
7307 558 : if (mul > PG_INT64_MAX / 8)
7308 : {
7309 : /* Add the contribution from this group of digits */
7310 18 : int64_to_numericvar(mul, &tmp_var);
7311 18 : mul_var(dest, &tmp_var, dest, 0);
7312 18 : int64_to_numericvar(tmp, &tmp_var);
7313 18 : add_var(dest, &tmp_var, dest);
7314 :
7315 : /* Result will overflow if weight overflows int16 */
7316 18 : if (dest->weight > NUMERIC_WEIGHT_MAX)
7317 0 : goto out_of_range;
7318 :
7319 : /* Begin a new group */
7320 18 : tmp = 0;
7321 18 : mul = 1;
7322 : }
7323 :
7324 558 : tmp = tmp * 8 + (*cp++ - '0');
7325 558 : mul = mul * 8;
7326 : }
7327 48 : else if (*cp == '_')
7328 : {
7329 : /* Underscore must be followed by more digits */
7330 36 : cp++;
7331 36 : if (*cp < '0' || *cp > '7')
7332 0 : goto invalid_syntax;
7333 : }
7334 : else
7335 12 : break;
7336 : }
7337 : }
7338 42 : else if (base == 2)
7339 : {
7340 1560 : while (*cp)
7341 : {
7342 1530 : if (*cp >= '0' && *cp <= '1')
7343 : {
7344 1416 : if (mul > PG_INT64_MAX / 2)
7345 : {
7346 : /* Add the contribution from this group of digits */
7347 18 : int64_to_numericvar(mul, &tmp_var);
7348 18 : mul_var(dest, &tmp_var, dest, 0);
7349 18 : int64_to_numericvar(tmp, &tmp_var);
7350 18 : add_var(dest, &tmp_var, dest);
7351 :
7352 : /* Result will overflow if weight overflows int16 */
7353 18 : if (dest->weight > NUMERIC_WEIGHT_MAX)
7354 0 : goto out_of_range;
7355 :
7356 : /* Begin a new group */
7357 18 : tmp = 0;
7358 18 : mul = 1;
7359 : }
7360 :
7361 1416 : tmp = tmp * 2 + (*cp++ - '0');
7362 1416 : mul = mul * 2;
7363 : }
7364 114 : else if (*cp == '_')
7365 : {
7366 : /* Underscore must be followed by more digits */
7367 102 : cp++;
7368 102 : if (*cp < '0' || *cp > '1')
7369 0 : goto invalid_syntax;
7370 : }
7371 : else
7372 12 : break;
7373 : }
7374 : }
7375 : else
7376 : /* Should never happen; treat as invalid input */
7377 0 : goto invalid_syntax;
7378 :
7379 : /* Check that we got at least one digit */
7380 138 : if (unlikely(cp == firstdigit))
7381 0 : goto invalid_syntax;
7382 :
7383 : /* Add the contribution from the final group of digits */
7384 138 : int64_to_numericvar(mul, &tmp_var);
7385 138 : mul_var(dest, &tmp_var, dest, 0);
7386 138 : int64_to_numericvar(tmp, &tmp_var);
7387 138 : add_var(dest, &tmp_var, dest);
7388 :
7389 138 : if (dest->weight > NUMERIC_WEIGHT_MAX)
7390 0 : goto out_of_range;
7391 :
7392 138 : dest->sign = sign;
7393 :
7394 138 : free_var(&tmp_var);
7395 :
7396 : /* Return end+1 position for caller */
7397 138 : *endptr = cp;
7398 :
7399 138 : return true;
7400 :
7401 0 : out_of_range:
7402 0 : ereturn(escontext, false,
7403 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
7404 : errmsg("value overflows numeric format")));
7405 :
7406 18 : invalid_syntax:
7407 18 : ereturn(escontext, false,
7408 : (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
7409 : errmsg("invalid input syntax for type %s: \"%s\"",
7410 : "numeric", str)));
7411 : }
7412 :
7413 :
7414 : /*
7415 : * set_var_from_num() -
7416 : *
7417 : * Convert the packed db format into a variable
7418 : */
7419 : static void
7420 12934 : set_var_from_num(Numeric num, NumericVar *dest)
7421 : {
7422 : int ndigits;
7423 :
7424 12934 : ndigits = NUMERIC_NDIGITS(num);
7425 :
7426 12934 : alloc_var(dest, ndigits);
7427 :
7428 12934 : dest->weight = NUMERIC_WEIGHT(num);
7429 12934 : dest->sign = NUMERIC_SIGN(num);
7430 12934 : dest->dscale = NUMERIC_DSCALE(num);
7431 :
7432 12934 : memcpy(dest->digits, NUMERIC_DIGITS(num), ndigits * sizeof(NumericDigit));
7433 12934 : }
7434 :
7435 :
7436 : /*
7437 : * init_var_from_num() -
7438 : *
7439 : * Initialize a variable from packed db format. The digits array is not
7440 : * copied, which saves some cycles when the resulting var is not modified.
7441 : * Also, there's no need to call free_var(), as long as you don't assign any
7442 : * other value to it (with set_var_* functions, or by using the var as the
7443 : * destination of a function like add_var())
7444 : *
7445 : * CAUTION: Do not modify the digits buffer of a var initialized with this
7446 : * function, e.g by calling round_var() or trunc_var(), as the changes will
7447 : * propagate to the original Numeric! It's OK to use it as the destination
7448 : * argument of one of the calculational functions, though.
7449 : */
7450 : static void
7451 5104188 : init_var_from_num(Numeric num, NumericVar *dest)
7452 : {
7453 5104188 : dest->ndigits = NUMERIC_NDIGITS(num);
7454 5104188 : dest->weight = NUMERIC_WEIGHT(num);
7455 5104188 : dest->sign = NUMERIC_SIGN(num);
7456 5104188 : dest->dscale = NUMERIC_DSCALE(num);
7457 5104188 : dest->digits = NUMERIC_DIGITS(num);
7458 5104188 : dest->buf = NULL; /* digits array is not palloc'd */
7459 5104188 : }
7460 :
7461 :
7462 : /*
7463 : * set_var_from_var() -
7464 : *
7465 : * Copy one variable into another
7466 : */
7467 : static void
7468 35876 : set_var_from_var(const NumericVar *value, NumericVar *dest)
7469 : {
7470 : NumericDigit *newbuf;
7471 :
7472 35876 : newbuf = digitbuf_alloc(value->ndigits + 1);
7473 35876 : newbuf[0] = 0; /* spare digit for rounding */
7474 35876 : if (value->ndigits > 0) /* else value->digits might be null */
7475 34942 : memcpy(newbuf + 1, value->digits,
7476 34942 : value->ndigits * sizeof(NumericDigit));
7477 :
7478 35876 : digitbuf_free(dest->buf);
7479 :
7480 35876 : memmove(dest, value, sizeof(NumericVar));
7481 35876 : dest->buf = newbuf;
7482 35876 : dest->digits = newbuf + 1;
7483 35876 : }
7484 :
7485 :
7486 : /*
7487 : * get_str_from_var() -
7488 : *
7489 : * Convert a var to text representation (guts of numeric_out).
7490 : * The var is displayed to the number of digits indicated by its dscale.
7491 : * Returns a palloc'd string.
7492 : */
7493 : static char *
7494 802168 : get_str_from_var(const NumericVar *var)
7495 : {
7496 : int dscale;
7497 : char *str;
7498 : char *cp;
7499 : char *endcp;
7500 : int i;
7501 : int d;
7502 : NumericDigit dig;
7503 :
7504 : #if DEC_DIGITS > 1
7505 : NumericDigit d1;
7506 : #endif
7507 :
7508 802168 : dscale = var->dscale;
7509 :
7510 : /*
7511 : * Allocate space for the result.
7512 : *
7513 : * i is set to the # of decimal digits before decimal point. dscale is the
7514 : * # of decimal digits we will print after decimal point. We may generate
7515 : * as many as DEC_DIGITS-1 excess digits at the end, and in addition we
7516 : * need room for sign, decimal point, null terminator.
7517 : */
7518 802168 : i = (var->weight + 1) * DEC_DIGITS;
7519 802168 : if (i <= 0)
7520 141052 : i = 1;
7521 :
7522 802168 : str = palloc(i + dscale + DEC_DIGITS + 2);
7523 802168 : cp = str;
7524 :
7525 : /*
7526 : * Output a dash for negative values
7527 : */
7528 802168 : if (var->sign == NUMERIC_NEG)
7529 5560 : *cp++ = '-';
7530 :
7531 : /*
7532 : * Output all digits before the decimal point
7533 : */
7534 802168 : if (var->weight < 0)
7535 : {
7536 141052 : d = var->weight + 1;
7537 141052 : *cp++ = '0';
7538 : }
7539 : else
7540 : {
7541 1428100 : for (d = 0; d <= var->weight; d++)
7542 : {
7543 766984 : dig = (d < var->ndigits) ? var->digits[d] : 0;
7544 : /* In the first digit, suppress extra leading decimal zeroes */
7545 : #if DEC_DIGITS == 4
7546 : {
7547 766984 : bool putit = (d > 0);
7548 :
7549 766984 : d1 = dig / 1000;
7550 766984 : dig -= d1 * 1000;
7551 766984 : putit |= (d1 > 0);
7552 766984 : if (putit)
7553 112750 : *cp++ = d1 + '0';
7554 766984 : d1 = dig / 100;
7555 766984 : dig -= d1 * 100;
7556 766984 : putit |= (d1 > 0);
7557 766984 : if (putit)
7558 517814 : *cp++ = d1 + '0';
7559 766984 : d1 = dig / 10;
7560 766984 : dig -= d1 * 10;
7561 766984 : putit |= (d1 > 0);
7562 766984 : if (putit)
7563 645002 : *cp++ = d1 + '0';
7564 766984 : *cp++ = dig + '0';
7565 : }
7566 : #elif DEC_DIGITS == 2
7567 : d1 = dig / 10;
7568 : dig -= d1 * 10;
7569 : if (d1 > 0 || d > 0)
7570 : *cp++ = d1 + '0';
7571 : *cp++ = dig + '0';
7572 : #elif DEC_DIGITS == 1
7573 : *cp++ = dig + '0';
7574 : #else
7575 : #error unsupported NBASE
7576 : #endif
7577 : }
7578 : }
7579 :
7580 : /*
7581 : * If requested, output a decimal point and all the digits that follow it.
7582 : * We initially put out a multiple of DEC_DIGITS digits, then truncate if
7583 : * needed.
7584 : */
7585 802168 : if (dscale > 0)
7586 : {
7587 646650 : *cp++ = '.';
7588 646650 : endcp = cp + dscale;
7589 2023602 : for (i = 0; i < dscale; d++, i += DEC_DIGITS)
7590 : {
7591 1376952 : dig = (d >= 0 && d < var->ndigits) ? var->digits[d] : 0;
7592 : #if DEC_DIGITS == 4
7593 1376952 : d1 = dig / 1000;
7594 1376952 : dig -= d1 * 1000;
7595 1376952 : *cp++ = d1 + '0';
7596 1376952 : d1 = dig / 100;
7597 1376952 : dig -= d1 * 100;
7598 1376952 : *cp++ = d1 + '0';
7599 1376952 : d1 = dig / 10;
7600 1376952 : dig -= d1 * 10;
7601 1376952 : *cp++ = d1 + '0';
7602 1376952 : *cp++ = dig + '0';
7603 : #elif DEC_DIGITS == 2
7604 : d1 = dig / 10;
7605 : dig -= d1 * 10;
7606 : *cp++ = d1 + '0';
7607 : *cp++ = dig + '0';
7608 : #elif DEC_DIGITS == 1
7609 : *cp++ = dig + '0';
7610 : #else
7611 : #error unsupported NBASE
7612 : #endif
7613 : }
7614 646650 : cp = endcp;
7615 : }
7616 :
7617 : /*
7618 : * terminate the string and return it
7619 : */
7620 802168 : *cp = '\0';
7621 802168 : return str;
7622 : }
7623 :
7624 : /*
7625 : * get_str_from_var_sci() -
7626 : *
7627 : * Convert a var to a normalised scientific notation text representation.
7628 : * This function does the heavy lifting for numeric_out_sci().
7629 : *
7630 : * This notation has the general form a * 10^b, where a is known as the
7631 : * "significand" and b is known as the "exponent".
7632 : *
7633 : * Because we can't do superscript in ASCII (and because we want to copy
7634 : * printf's behaviour) we display the exponent using E notation, with a
7635 : * minimum of two exponent digits.
7636 : *
7637 : * For example, the value 1234 could be output as 1.2e+03.
7638 : *
7639 : * We assume that the exponent can fit into an int32.
7640 : *
7641 : * rscale is the number of decimal digits desired after the decimal point in
7642 : * the output, negative values will be treated as meaning zero.
7643 : *
7644 : * Returns a palloc'd string.
7645 : */
7646 : static char *
7647 216 : get_str_from_var_sci(const NumericVar *var, int rscale)
7648 : {
7649 : int32 exponent;
7650 : NumericVar tmp_var;
7651 : size_t len;
7652 : char *str;
7653 : char *sig_out;
7654 :
7655 216 : if (rscale < 0)
7656 0 : rscale = 0;
7657 :
7658 : /*
7659 : * Determine the exponent of this number in normalised form.
7660 : *
7661 : * This is the exponent required to represent the number with only one
7662 : * significant digit before the decimal place.
7663 : */
7664 216 : if (var->ndigits > 0)
7665 : {
7666 198 : exponent = (var->weight + 1) * DEC_DIGITS;
7667 :
7668 : /*
7669 : * Compensate for leading decimal zeroes in the first numeric digit by
7670 : * decrementing the exponent.
7671 : */
7672 198 : exponent -= DEC_DIGITS - (int) log10(var->digits[0]);
7673 : }
7674 : else
7675 : {
7676 : /*
7677 : * If var has no digits, then it must be zero.
7678 : *
7679 : * Zero doesn't technically have a meaningful exponent in normalised
7680 : * notation, but we just display the exponent as zero for consistency
7681 : * of output.
7682 : */
7683 18 : exponent = 0;
7684 : }
7685 :
7686 : /*
7687 : * Divide var by 10^exponent to get the significand, rounding to rscale
7688 : * decimal digits in the process.
7689 : */
7690 216 : init_var(&tmp_var);
7691 :
7692 216 : power_ten_int(exponent, &tmp_var);
7693 216 : div_var(var, &tmp_var, &tmp_var, rscale, true);
7694 216 : sig_out = get_str_from_var(&tmp_var);
7695 :
7696 216 : free_var(&tmp_var);
7697 :
7698 : /*
7699 : * Allocate space for the result.
7700 : *
7701 : * In addition to the significand, we need room for the exponent
7702 : * decoration ("e"), the sign of the exponent, up to 10 digits for the
7703 : * exponent itself, and of course the null terminator.
7704 : */
7705 216 : len = strlen(sig_out) + 13;
7706 216 : str = palloc(len);
7707 216 : snprintf(str, len, "%se%+03d", sig_out, exponent);
7708 :
7709 216 : pfree(sig_out);
7710 :
7711 216 : return str;
7712 : }
7713 :
7714 :
7715 : /*
7716 : * numericvar_serialize - serialize NumericVar to binary format
7717 : *
7718 : * At variable level, no checks are performed on the weight or dscale, allowing
7719 : * us to pass around intermediate values with higher precision than supported
7720 : * by the numeric type. Note: this is incompatible with numeric_send/recv(),
7721 : * which use 16-bit integers for these fields.
7722 : */
7723 : static void
7724 102 : numericvar_serialize(StringInfo buf, const NumericVar *var)
7725 : {
7726 : int i;
7727 :
7728 102 : pq_sendint32(buf, var->ndigits);
7729 102 : pq_sendint32(buf, var->weight);
7730 102 : pq_sendint32(buf, var->sign);
7731 102 : pq_sendint32(buf, var->dscale);
7732 637810 : for (i = 0; i < var->ndigits; i++)
7733 637708 : pq_sendint16(buf, var->digits[i]);
7734 102 : }
7735 :
7736 : /*
7737 : * numericvar_deserialize - deserialize binary format to NumericVar
7738 : */
7739 : static void
7740 102 : numericvar_deserialize(StringInfo buf, NumericVar *var)
7741 : {
7742 : int len,
7743 : i;
7744 :
7745 102 : len = pq_getmsgint(buf, sizeof(int32));
7746 :
7747 102 : alloc_var(var, len); /* sets var->ndigits */
7748 :
7749 102 : var->weight = pq_getmsgint(buf, sizeof(int32));
7750 102 : var->sign = pq_getmsgint(buf, sizeof(int32));
7751 102 : var->dscale = pq_getmsgint(buf, sizeof(int32));
7752 637810 : for (i = 0; i < len; i++)
7753 637708 : var->digits[i] = pq_getmsgint(buf, sizeof(int16));
7754 102 : }
7755 :
7756 :
7757 : /*
7758 : * duplicate_numeric() - copy a packed-format Numeric
7759 : *
7760 : * This will handle NaN and Infinity cases.
7761 : */
7762 : static Numeric
7763 28496 : duplicate_numeric(Numeric num)
7764 : {
7765 : Numeric res;
7766 :
7767 28496 : res = (Numeric) palloc(VARSIZE(num));
7768 28496 : memcpy(res, num, VARSIZE(num));
7769 28496 : return res;
7770 : }
7771 :
7772 : /*
7773 : * make_result_opt_error() -
7774 : *
7775 : * Create the packed db numeric format in palloc()'d memory from
7776 : * a variable. This will handle NaN and Infinity cases.
7777 : *
7778 : * If "have_error" isn't NULL, on overflow *have_error is set to true and
7779 : * NULL is returned. This is helpful when caller needs to handle errors.
7780 : */
7781 : static Numeric
7782 3279524 : make_result_opt_error(const NumericVar *var, bool *have_error)
7783 : {
7784 : Numeric result;
7785 3279524 : NumericDigit *digits = var->digits;
7786 3279524 : int weight = var->weight;
7787 3279524 : int sign = var->sign;
7788 : int n;
7789 : Size len;
7790 :
7791 3279524 : if (have_error)
7792 105322 : *have_error = false;
7793 :
7794 3279524 : if ((sign & NUMERIC_SIGN_MASK) == NUMERIC_SPECIAL)
7795 : {
7796 : /*
7797 : * Verify valid special value. This could be just an Assert, perhaps,
7798 : * but it seems worthwhile to expend a few cycles to ensure that we
7799 : * never write any nonzero reserved bits to disk.
7800 : */
7801 6236 : if (!(sign == NUMERIC_NAN ||
7802 : sign == NUMERIC_PINF ||
7803 : sign == NUMERIC_NINF))
7804 0 : elog(ERROR, "invalid numeric sign value 0x%x", sign);
7805 :
7806 6236 : result = (Numeric) palloc(NUMERIC_HDRSZ_SHORT);
7807 :
7808 6236 : SET_VARSIZE(result, NUMERIC_HDRSZ_SHORT);
7809 6236 : result->choice.n_header = sign;
7810 : /* the header word is all we need */
7811 :
7812 : dump_numeric("make_result()", result);
7813 6236 : return result;
7814 : }
7815 :
7816 3273288 : n = var->ndigits;
7817 :
7818 : /* truncate leading zeroes */
7819 3273324 : while (n > 0 && *digits == 0)
7820 : {
7821 36 : digits++;
7822 36 : weight--;
7823 36 : n--;
7824 : }
7825 : /* truncate trailing zeroes */
7826 3358632 : while (n > 0 && digits[n - 1] == 0)
7827 85344 : n--;
7828 :
7829 : /* If zero result, force to weight=0 and positive sign */
7830 3273288 : if (n == 0)
7831 : {
7832 95624 : weight = 0;
7833 95624 : sign = NUMERIC_POS;
7834 : }
7835 :
7836 : /* Build the result */
7837 3273288 : if (NUMERIC_CAN_BE_SHORT(var->dscale, weight))
7838 : {
7839 3268036 : len = NUMERIC_HDRSZ_SHORT + n * sizeof(NumericDigit);
7840 3268036 : result = (Numeric) palloc(len);
7841 3268036 : SET_VARSIZE(result, len);
7842 3268036 : result->choice.n_short.n_header =
7843 : (sign == NUMERIC_NEG ? (NUMERIC_SHORT | NUMERIC_SHORT_SIGN_MASK)
7844 : : NUMERIC_SHORT)
7845 3268036 : | (var->dscale << NUMERIC_SHORT_DSCALE_SHIFT)
7846 3268036 : | (weight < 0 ? NUMERIC_SHORT_WEIGHT_SIGN_MASK : 0)
7847 3268036 : | (weight & NUMERIC_SHORT_WEIGHT_MASK);
7848 : }
7849 : else
7850 : {
7851 5252 : len = NUMERIC_HDRSZ + n * sizeof(NumericDigit);
7852 5252 : result = (Numeric) palloc(len);
7853 5252 : SET_VARSIZE(result, len);
7854 5252 : result->choice.n_long.n_sign_dscale =
7855 5252 : sign | (var->dscale & NUMERIC_DSCALE_MASK);
7856 5252 : result->choice.n_long.n_weight = weight;
7857 : }
7858 :
7859 : Assert(NUMERIC_NDIGITS(result) == n);
7860 3273288 : if (n > 0)
7861 3177664 : memcpy(NUMERIC_DIGITS(result), digits, n * sizeof(NumericDigit));
7862 :
7863 : /* Check for overflow of int16 fields */
7864 3273288 : if (NUMERIC_WEIGHT(result) != weight ||
7865 3273258 : NUMERIC_DSCALE(result) != var->dscale)
7866 : {
7867 30 : if (have_error)
7868 : {
7869 18 : *have_error = true;
7870 18 : return NULL;
7871 : }
7872 : else
7873 : {
7874 12 : ereport(ERROR,
7875 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
7876 : errmsg("value overflows numeric format")));
7877 : }
7878 : }
7879 :
7880 : dump_numeric("make_result()", result);
7881 3273258 : return result;
7882 : }
7883 :
7884 :
7885 : /*
7886 : * make_result() -
7887 : *
7888 : * An interface to make_result_opt_error() without "have_error" argument.
7889 : */
7890 : static Numeric
7891 2132598 : make_result(const NumericVar *var)
7892 : {
7893 2132598 : return make_result_opt_error(var, NULL);
7894 : }
7895 :
7896 :
7897 : /*
7898 : * apply_typmod() -
7899 : *
7900 : * Do bounds checking and rounding according to the specified typmod.
7901 : * Note that this is only applied to normal finite values.
7902 : *
7903 : * Returns true on success, false on failure (if escontext points to an
7904 : * ErrorSaveContext; otherwise errors are thrown).
7905 : */
7906 : static bool
7907 109486 : apply_typmod(NumericVar *var, int32 typmod, Node *escontext)
7908 : {
7909 : int precision;
7910 : int scale;
7911 : int maxdigits;
7912 : int ddigits;
7913 : int i;
7914 :
7915 : /* Do nothing if we have an invalid typmod */
7916 109486 : if (!is_valid_numeric_typmod(typmod))
7917 104794 : return true;
7918 :
7919 4692 : precision = numeric_typmod_precision(typmod);
7920 4692 : scale = numeric_typmod_scale(typmod);
7921 4692 : maxdigits = precision - scale;
7922 :
7923 : /* Round to target scale (and set var->dscale) */
7924 4692 : round_var(var, scale);
7925 :
7926 : /* but don't allow var->dscale to be negative */
7927 4692 : if (var->dscale < 0)
7928 126 : var->dscale = 0;
7929 :
7930 : /*
7931 : * Check for overflow - note we can't do this before rounding, because
7932 : * rounding could raise the weight. Also note that the var's weight could
7933 : * be inflated by leading zeroes, which will be stripped before storage
7934 : * but perhaps might not have been yet. In any case, we must recognize a
7935 : * true zero, whose weight doesn't mean anything.
7936 : */
7937 4692 : ddigits = (var->weight + 1) * DEC_DIGITS;
7938 4692 : if (ddigits > maxdigits)
7939 : {
7940 : /* Determine true weight; and check for all-zero result */
7941 404 : for (i = 0; i < var->ndigits; i++)
7942 : {
7943 388 : NumericDigit dig = var->digits[i];
7944 :
7945 388 : if (dig)
7946 : {
7947 : /* Adjust for any high-order decimal zero digits */
7948 : #if DEC_DIGITS == 4
7949 388 : if (dig < 10)
7950 252 : ddigits -= 3;
7951 136 : else if (dig < 100)
7952 66 : ddigits -= 2;
7953 70 : else if (dig < 1000)
7954 52 : ddigits -= 1;
7955 : #elif DEC_DIGITS == 2
7956 : if (dig < 10)
7957 : ddigits -= 1;
7958 : #elif DEC_DIGITS == 1
7959 : /* no adjustment */
7960 : #else
7961 : #error unsupported NBASE
7962 : #endif
7963 388 : if (ddigits > maxdigits)
7964 84 : ereturn(escontext, false,
7965 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
7966 : errmsg("numeric field overflow"),
7967 : errdetail("A field with precision %d, scale %d must round to an absolute value less than %s%d.",
7968 : precision, scale,
7969 : /* Display 10^0 as 1 */
7970 : maxdigits ? "10^" : "",
7971 : maxdigits ? maxdigits : 1
7972 : )));
7973 304 : break;
7974 : }
7975 0 : ddigits -= DEC_DIGITS;
7976 : }
7977 : }
7978 :
7979 4608 : return true;
7980 : }
7981 :
7982 : /*
7983 : * apply_typmod_special() -
7984 : *
7985 : * Do bounds checking according to the specified typmod, for an Inf or NaN.
7986 : * For convenience of most callers, the value is presented in packed form.
7987 : *
7988 : * Returns true on success, false on failure (if escontext points to an
7989 : * ErrorSaveContext; otherwise errors are thrown).
7990 : */
7991 : static bool
7992 1864 : apply_typmod_special(Numeric num, int32 typmod, Node *escontext)
7993 : {
7994 : int precision;
7995 : int scale;
7996 :
7997 : Assert(NUMERIC_IS_SPECIAL(num)); /* caller error if not */
7998 :
7999 : /*
8000 : * NaN is allowed regardless of the typmod; that's rather dubious perhaps,
8001 : * but it's a longstanding behavior. Inf is rejected if we have any
8002 : * typmod restriction, since an infinity shouldn't be claimed to fit in
8003 : * any finite number of digits.
8004 : */
8005 1864 : if (NUMERIC_IS_NAN(num))
8006 778 : return true;
8007 :
8008 : /* Do nothing if we have a default typmod (-1) */
8009 1086 : if (!is_valid_numeric_typmod(typmod))
8010 1068 : return true;
8011 :
8012 18 : precision = numeric_typmod_precision(typmod);
8013 18 : scale = numeric_typmod_scale(typmod);
8014 :
8015 18 : ereturn(escontext, false,
8016 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
8017 : errmsg("numeric field overflow"),
8018 : errdetail("A field with precision %d, scale %d cannot hold an infinite value.",
8019 : precision, scale)));
8020 : }
8021 :
8022 :
8023 : /*
8024 : * Convert numeric to int8, rounding if needed.
8025 : *
8026 : * If overflow, return false (no error is raised). Return true if okay.
8027 : */
8028 : static bool
8029 11020 : numericvar_to_int64(const NumericVar *var, int64 *result)
8030 : {
8031 : NumericDigit *digits;
8032 : int ndigits;
8033 : int weight;
8034 : int i;
8035 : int64 val;
8036 : bool neg;
8037 : NumericVar rounded;
8038 :
8039 : /* Round to nearest integer */
8040 11020 : init_var(&rounded);
8041 11020 : set_var_from_var(var, &rounded);
8042 11020 : round_var(&rounded, 0);
8043 :
8044 : /* Check for zero input */
8045 11020 : strip_var(&rounded);
8046 11020 : ndigits = rounded.ndigits;
8047 11020 : if (ndigits == 0)
8048 : {
8049 466 : *result = 0;
8050 466 : free_var(&rounded);
8051 466 : return true;
8052 : }
8053 :
8054 : /*
8055 : * For input like 10000000000, we must treat stripped digits as real. So
8056 : * the loop assumes there are weight+1 digits before the decimal point.
8057 : */
8058 10554 : weight = rounded.weight;
8059 : Assert(weight >= 0 && ndigits <= weight + 1);
8060 :
8061 : /*
8062 : * Construct the result. To avoid issues with converting a value
8063 : * corresponding to INT64_MIN (which can't be represented as a positive 64
8064 : * bit two's complement integer), accumulate value as a negative number.
8065 : */
8066 10554 : digits = rounded.digits;
8067 10554 : neg = (rounded.sign == NUMERIC_NEG);
8068 10554 : val = -digits[0];
8069 15526 : for (i = 1; i <= weight; i++)
8070 : {
8071 5020 : if (unlikely(pg_mul_s64_overflow(val, NBASE, &val)))
8072 : {
8073 30 : free_var(&rounded);
8074 30 : return false;
8075 : }
8076 :
8077 4990 : if (i < ndigits)
8078 : {
8079 4726 : if (unlikely(pg_sub_s64_overflow(val, digits[i], &val)))
8080 : {
8081 18 : free_var(&rounded);
8082 18 : return false;
8083 : }
8084 : }
8085 : }
8086 :
8087 10506 : free_var(&rounded);
8088 :
8089 10506 : if (!neg)
8090 : {
8091 9738 : if (unlikely(val == PG_INT64_MIN))
8092 24 : return false;
8093 9714 : val = -val;
8094 : }
8095 10482 : *result = val;
8096 :
8097 10482 : return true;
8098 : }
8099 :
8100 : /*
8101 : * Convert int8 value to numeric.
8102 : */
8103 : static void
8104 1882660 : int64_to_numericvar(int64 val, NumericVar *var)
8105 : {
8106 : uint64 uval,
8107 : newuval;
8108 : NumericDigit *ptr;
8109 : int ndigits;
8110 :
8111 : /* int64 can require at most 19 decimal digits; add one for safety */
8112 1882660 : alloc_var(var, 20 / DEC_DIGITS);
8113 1882660 : if (val < 0)
8114 : {
8115 1802 : var->sign = NUMERIC_NEG;
8116 1802 : uval = pg_abs_s64(val);
8117 : }
8118 : else
8119 : {
8120 1880858 : var->sign = NUMERIC_POS;
8121 1880858 : uval = val;
8122 : }
8123 1882660 : var->dscale = 0;
8124 1882660 : if (val == 0)
8125 : {
8126 36130 : var->ndigits = 0;
8127 36130 : var->weight = 0;
8128 36130 : return;
8129 : }
8130 1846530 : ptr = var->digits + var->ndigits;
8131 1846530 : ndigits = 0;
8132 : do
8133 : {
8134 2171838 : ptr--;
8135 2171838 : ndigits++;
8136 2171838 : newuval = uval / NBASE;
8137 2171838 : *ptr = uval - newuval * NBASE;
8138 2171838 : uval = newuval;
8139 2171838 : } while (uval);
8140 1846530 : var->digits = ptr;
8141 1846530 : var->ndigits = ndigits;
8142 1846530 : var->weight = ndigits - 1;
8143 : }
8144 :
8145 : /*
8146 : * Convert numeric to uint64, rounding if needed.
8147 : *
8148 : * If overflow, return false (no error is raised). Return true if okay.
8149 : */
8150 : static bool
8151 118 : numericvar_to_uint64(const NumericVar *var, uint64 *result)
8152 : {
8153 : NumericDigit *digits;
8154 : int ndigits;
8155 : int weight;
8156 : int i;
8157 : uint64 val;
8158 : NumericVar rounded;
8159 :
8160 : /* Round to nearest integer */
8161 118 : init_var(&rounded);
8162 118 : set_var_from_var(var, &rounded);
8163 118 : round_var(&rounded, 0);
8164 :
8165 : /* Check for zero input */
8166 118 : strip_var(&rounded);
8167 118 : ndigits = rounded.ndigits;
8168 118 : if (ndigits == 0)
8169 : {
8170 18 : *result = 0;
8171 18 : free_var(&rounded);
8172 18 : return true;
8173 : }
8174 :
8175 : /* Check for negative input */
8176 100 : if (rounded.sign == NUMERIC_NEG)
8177 : {
8178 12 : free_var(&rounded);
8179 12 : return false;
8180 : }
8181 :
8182 : /*
8183 : * For input like 10000000000, we must treat stripped digits as real. So
8184 : * the loop assumes there are weight+1 digits before the decimal point.
8185 : */
8186 88 : weight = rounded.weight;
8187 : Assert(weight >= 0 && ndigits <= weight + 1);
8188 :
8189 : /* Construct the result */
8190 88 : digits = rounded.digits;
8191 88 : val = digits[0];
8192 258 : for (i = 1; i <= weight; i++)
8193 : {
8194 182 : if (unlikely(pg_mul_u64_overflow(val, NBASE, &val)))
8195 : {
8196 0 : free_var(&rounded);
8197 0 : return false;
8198 : }
8199 :
8200 182 : if (i < ndigits)
8201 : {
8202 182 : if (unlikely(pg_add_u64_overflow(val, digits[i], &val)))
8203 : {
8204 12 : free_var(&rounded);
8205 12 : return false;
8206 : }
8207 : }
8208 : }
8209 :
8210 76 : free_var(&rounded);
8211 :
8212 76 : *result = val;
8213 :
8214 76 : return true;
8215 : }
8216 :
8217 : #ifdef HAVE_INT128
8218 : /*
8219 : * Convert numeric to int128, rounding if needed.
8220 : *
8221 : * If overflow, return false (no error is raised). Return true if okay.
8222 : */
8223 : static bool
8224 36 : numericvar_to_int128(const NumericVar *var, int128 *result)
8225 : {
8226 : NumericDigit *digits;
8227 : int ndigits;
8228 : int weight;
8229 : int i;
8230 : int128 val,
8231 : oldval;
8232 : bool neg;
8233 : NumericVar rounded;
8234 :
8235 : /* Round to nearest integer */
8236 36 : init_var(&rounded);
8237 36 : set_var_from_var(var, &rounded);
8238 36 : round_var(&rounded, 0);
8239 :
8240 : /* Check for zero input */
8241 36 : strip_var(&rounded);
8242 36 : ndigits = rounded.ndigits;
8243 36 : if (ndigits == 0)
8244 : {
8245 0 : *result = 0;
8246 0 : free_var(&rounded);
8247 0 : return true;
8248 : }
8249 :
8250 : /*
8251 : * For input like 10000000000, we must treat stripped digits as real. So
8252 : * the loop assumes there are weight+1 digits before the decimal point.
8253 : */
8254 36 : weight = rounded.weight;
8255 : Assert(weight >= 0 && ndigits <= weight + 1);
8256 :
8257 : /* Construct the result */
8258 36 : digits = rounded.digits;
8259 36 : neg = (rounded.sign == NUMERIC_NEG);
8260 36 : val = digits[0];
8261 100 : for (i = 1; i <= weight; i++)
8262 : {
8263 64 : oldval = val;
8264 64 : val *= NBASE;
8265 64 : if (i < ndigits)
8266 58 : val += digits[i];
8267 :
8268 : /*
8269 : * The overflow check is a bit tricky because we want to accept
8270 : * INT128_MIN, which will overflow the positive accumulator. We can
8271 : * detect this case easily though because INT128_MIN is the only
8272 : * nonzero value for which -val == val (on a two's complement machine,
8273 : * anyway).
8274 : */
8275 64 : if ((val / NBASE) != oldval) /* possible overflow? */
8276 : {
8277 0 : if (!neg || (-val) != val || val == 0 || oldval < 0)
8278 : {
8279 0 : free_var(&rounded);
8280 0 : return false;
8281 : }
8282 : }
8283 : }
8284 :
8285 36 : free_var(&rounded);
8286 :
8287 36 : *result = neg ? -val : val;
8288 36 : return true;
8289 : }
8290 :
8291 : /*
8292 : * Convert 128 bit integer to numeric.
8293 : */
8294 : static void
8295 8560 : int128_to_numericvar(int128 val, NumericVar *var)
8296 : {
8297 : uint128 uval,
8298 : newuval;
8299 : NumericDigit *ptr;
8300 : int ndigits;
8301 :
8302 : /* int128 can require at most 39 decimal digits; add one for safety */
8303 8560 : alloc_var(var, 40 / DEC_DIGITS);
8304 8560 : if (val < 0)
8305 : {
8306 0 : var->sign = NUMERIC_NEG;
8307 0 : uval = -val;
8308 : }
8309 : else
8310 : {
8311 8560 : var->sign = NUMERIC_POS;
8312 8560 : uval = val;
8313 : }
8314 8560 : var->dscale = 0;
8315 8560 : if (val == 0)
8316 : {
8317 120 : var->ndigits = 0;
8318 120 : var->weight = 0;
8319 120 : return;
8320 : }
8321 8440 : ptr = var->digits + var->ndigits;
8322 8440 : ndigits = 0;
8323 : do
8324 : {
8325 44920 : ptr--;
8326 44920 : ndigits++;
8327 44920 : newuval = uval / NBASE;
8328 44920 : *ptr = uval - newuval * NBASE;
8329 44920 : uval = newuval;
8330 44920 : } while (uval);
8331 8440 : var->digits = ptr;
8332 8440 : var->ndigits = ndigits;
8333 8440 : var->weight = ndigits - 1;
8334 : }
8335 : #endif
8336 :
8337 : /*
8338 : * Convert a NumericVar to float8; if out of range, return +/- HUGE_VAL
8339 : */
8340 : static double
8341 4546 : numericvar_to_double_no_overflow(const NumericVar *var)
8342 : {
8343 : char *tmp;
8344 : double val;
8345 : char *endptr;
8346 :
8347 4546 : tmp = get_str_from_var(var);
8348 :
8349 : /* unlike float8in, we ignore ERANGE from strtod */
8350 4546 : val = strtod(tmp, &endptr);
8351 4546 : if (*endptr != '\0')
8352 : {
8353 : /* shouldn't happen ... */
8354 0 : ereport(ERROR,
8355 : (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
8356 : errmsg("invalid input syntax for type %s: \"%s\"",
8357 : "double precision", tmp)));
8358 : }
8359 :
8360 4546 : pfree(tmp);
8361 :
8362 4546 : return val;
8363 : }
8364 :
8365 :
8366 : /*
8367 : * cmp_var() -
8368 : *
8369 : * Compare two values on variable level. We assume zeroes have been
8370 : * truncated to no digits.
8371 : */
8372 : static int
8373 49706 : cmp_var(const NumericVar *var1, const NumericVar *var2)
8374 : {
8375 99412 : return cmp_var_common(var1->digits, var1->ndigits,
8376 : var1->weight, var1->sign,
8377 49706 : var2->digits, var2->ndigits,
8378 : var2->weight, var2->sign);
8379 : }
8380 :
8381 : /*
8382 : * cmp_var_common() -
8383 : *
8384 : * Main routine of cmp_var(). This function can be used by both
8385 : * NumericVar and Numeric.
8386 : */
8387 : static int
8388 6141866 : cmp_var_common(const NumericDigit *var1digits, int var1ndigits,
8389 : int var1weight, int var1sign,
8390 : const NumericDigit *var2digits, int var2ndigits,
8391 : int var2weight, int var2sign)
8392 : {
8393 6141866 : if (var1ndigits == 0)
8394 : {
8395 181952 : if (var2ndigits == 0)
8396 155662 : return 0;
8397 26290 : if (var2sign == NUMERIC_NEG)
8398 3404 : return 1;
8399 22886 : return -1;
8400 : }
8401 5959914 : if (var2ndigits == 0)
8402 : {
8403 32948 : if (var1sign == NUMERIC_POS)
8404 26182 : return 1;
8405 6766 : return -1;
8406 : }
8407 :
8408 5926966 : if (var1sign == NUMERIC_POS)
8409 : {
8410 5834800 : if (var2sign == NUMERIC_NEG)
8411 27542 : return 1;
8412 5807258 : return cmp_abs_common(var1digits, var1ndigits, var1weight,
8413 : var2digits, var2ndigits, var2weight);
8414 : }
8415 :
8416 92166 : if (var2sign == NUMERIC_POS)
8417 27824 : return -1;
8418 :
8419 64342 : return cmp_abs_common(var2digits, var2ndigits, var2weight,
8420 : var1digits, var1ndigits, var1weight);
8421 : }
8422 :
8423 :
8424 : /*
8425 : * add_var() -
8426 : *
8427 : * Full version of add functionality on variable level (handling signs).
8428 : * result might point to one of the operands too without danger.
8429 : */
8430 : static void
8431 497480 : add_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
8432 : {
8433 : /*
8434 : * Decide on the signs of the two variables what to do
8435 : */
8436 497480 : if (var1->sign == NUMERIC_POS)
8437 : {
8438 495914 : if (var2->sign == NUMERIC_POS)
8439 : {
8440 : /*
8441 : * Both are positive result = +(ABS(var1) + ABS(var2))
8442 : */
8443 295748 : add_abs(var1, var2, result);
8444 295748 : result->sign = NUMERIC_POS;
8445 : }
8446 : else
8447 : {
8448 : /*
8449 : * var1 is positive, var2 is negative Must compare absolute values
8450 : */
8451 200166 : switch (cmp_abs(var1, var2))
8452 : {
8453 178 : case 0:
8454 : /* ----------
8455 : * ABS(var1) == ABS(var2)
8456 : * result = ZERO
8457 : * ----------
8458 : */
8459 178 : zero_var(result);
8460 178 : result->dscale = Max(var1->dscale, var2->dscale);
8461 178 : break;
8462 :
8463 186244 : case 1:
8464 : /* ----------
8465 : * ABS(var1) > ABS(var2)
8466 : * result = +(ABS(var1) - ABS(var2))
8467 : * ----------
8468 : */
8469 186244 : sub_abs(var1, var2, result);
8470 186244 : result->sign = NUMERIC_POS;
8471 186244 : break;
8472 :
8473 13744 : case -1:
8474 : /* ----------
8475 : * ABS(var1) < ABS(var2)
8476 : * result = -(ABS(var2) - ABS(var1))
8477 : * ----------
8478 : */
8479 13744 : sub_abs(var2, var1, result);
8480 13744 : result->sign = NUMERIC_NEG;
8481 13744 : break;
8482 : }
8483 495914 : }
8484 : }
8485 : else
8486 : {
8487 1566 : if (var2->sign == NUMERIC_POS)
8488 : {
8489 : /* ----------
8490 : * var1 is negative, var2 is positive
8491 : * Must compare absolute values
8492 : * ----------
8493 : */
8494 468 : switch (cmp_abs(var1, var2))
8495 : {
8496 30 : case 0:
8497 : /* ----------
8498 : * ABS(var1) == ABS(var2)
8499 : * result = ZERO
8500 : * ----------
8501 : */
8502 30 : zero_var(result);
8503 30 : result->dscale = Max(var1->dscale, var2->dscale);
8504 30 : break;
8505 :
8506 294 : case 1:
8507 : /* ----------
8508 : * ABS(var1) > ABS(var2)
8509 : * result = -(ABS(var1) - ABS(var2))
8510 : * ----------
8511 : */
8512 294 : sub_abs(var1, var2, result);
8513 294 : result->sign = NUMERIC_NEG;
8514 294 : break;
8515 :
8516 144 : case -1:
8517 : /* ----------
8518 : * ABS(var1) < ABS(var2)
8519 : * result = +(ABS(var2) - ABS(var1))
8520 : * ----------
8521 : */
8522 144 : sub_abs(var2, var1, result);
8523 144 : result->sign = NUMERIC_POS;
8524 144 : break;
8525 : }
8526 468 : }
8527 : else
8528 : {
8529 : /* ----------
8530 : * Both are negative
8531 : * result = -(ABS(var1) + ABS(var2))
8532 : * ----------
8533 : */
8534 1098 : add_abs(var1, var2, result);
8535 1098 : result->sign = NUMERIC_NEG;
8536 : }
8537 : }
8538 497480 : }
8539 :
8540 :
8541 : /*
8542 : * sub_var() -
8543 : *
8544 : * Full version of sub functionality on variable level (handling signs).
8545 : * result might point to one of the operands too without danger.
8546 : */
8547 : static void
8548 190796 : sub_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result)
8549 : {
8550 : /*
8551 : * Decide on the signs of the two variables what to do
8552 : */
8553 190796 : if (var1->sign == NUMERIC_POS)
8554 : {
8555 187892 : if (var2->sign == NUMERIC_NEG)
8556 : {
8557 : /* ----------
8558 : * var1 is positive, var2 is negative
8559 : * result = +(ABS(var1) + ABS(var2))
8560 : * ----------
8561 : */
8562 33084 : add_abs(var1, var2, result);
8563 33084 : result->sign = NUMERIC_POS;
8564 : }
8565 : else
8566 : {
8567 : /* ----------
8568 : * Both are positive
8569 : * Must compare absolute values
8570 : * ----------
8571 : */
8572 154808 : switch (cmp_abs(var1, var2))
8573 : {
8574 29354 : case 0:
8575 : /* ----------
8576 : * ABS(var1) == ABS(var2)
8577 : * result = ZERO
8578 : * ----------
8579 : */
8580 29354 : zero_var(result);
8581 29354 : result->dscale = Max(var1->dscale, var2->dscale);
8582 29354 : break;
8583 :
8584 117634 : case 1:
8585 : /* ----------
8586 : * ABS(var1) > ABS(var2)
8587 : * result = +(ABS(var1) - ABS(var2))
8588 : * ----------
8589 : */
8590 117634 : sub_abs(var1, var2, result);
8591 117634 : result->sign = NUMERIC_POS;
8592 117634 : break;
8593 :
8594 7820 : case -1:
8595 : /* ----------
8596 : * ABS(var1) < ABS(var2)
8597 : * result = -(ABS(var2) - ABS(var1))
8598 : * ----------
8599 : */
8600 7820 : sub_abs(var2, var1, result);
8601 7820 : result->sign = NUMERIC_NEG;
8602 7820 : break;
8603 : }
8604 187892 : }
8605 : }
8606 : else
8607 : {
8608 2904 : if (var2->sign == NUMERIC_NEG)
8609 : {
8610 : /* ----------
8611 : * Both are negative
8612 : * Must compare absolute values
8613 : * ----------
8614 : */
8615 2454 : switch (cmp_abs(var1, var2))
8616 : {
8617 166 : case 0:
8618 : /* ----------
8619 : * ABS(var1) == ABS(var2)
8620 : * result = ZERO
8621 : * ----------
8622 : */
8623 166 : zero_var(result);
8624 166 : result->dscale = Max(var1->dscale, var2->dscale);
8625 166 : break;
8626 :
8627 240 : case 1:
8628 : /* ----------
8629 : * ABS(var1) > ABS(var2)
8630 : * result = -(ABS(var1) - ABS(var2))
8631 : * ----------
8632 : */
8633 240 : sub_abs(var1, var2, result);
8634 240 : result->sign = NUMERIC_NEG;
8635 240 : break;
8636 :
8637 2048 : case -1:
8638 : /* ----------
8639 : * ABS(var1) < ABS(var2)
8640 : * result = +(ABS(var2) - ABS(var1))
8641 : * ----------
8642 : */
8643 2048 : sub_abs(var2, var1, result);
8644 2048 : result->sign = NUMERIC_POS;
8645 2048 : break;
8646 : }
8647 2454 : }
8648 : else
8649 : {
8650 : /* ----------
8651 : * var1 is negative, var2 is positive
8652 : * result = -(ABS(var1) + ABS(var2))
8653 : * ----------
8654 : */
8655 450 : add_abs(var1, var2, result);
8656 450 : result->sign = NUMERIC_NEG;
8657 : }
8658 : }
8659 190796 : }
8660 :
8661 :
8662 : /*
8663 : * mul_var() -
8664 : *
8665 : * Multiplication on variable level. Product of var1 * var2 is stored
8666 : * in result. Result is rounded to no more than rscale fractional digits.
8667 : */
8668 : static void
8669 830586 : mul_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result,
8670 : int rscale)
8671 : {
8672 : int res_ndigits;
8673 : int res_ndigitpairs;
8674 : int res_sign;
8675 : int res_weight;
8676 : int pair_offset;
8677 : int maxdigits;
8678 : int maxdigitpairs;
8679 : uint64 *dig,
8680 : *dig_i1_off;
8681 : uint64 maxdig;
8682 : uint64 carry;
8683 : uint64 newdig;
8684 : int var1ndigits;
8685 : int var2ndigits;
8686 : int var1ndigitpairs;
8687 : int var2ndigitpairs;
8688 : NumericDigit *var1digits;
8689 : NumericDigit *var2digits;
8690 : uint32 var1digitpair;
8691 : uint32 *var2digitpairs;
8692 : NumericDigit *res_digits;
8693 : int i,
8694 : i1,
8695 : i2,
8696 : i2limit;
8697 :
8698 : /*
8699 : * Arrange for var1 to be the shorter of the two numbers. This improves
8700 : * performance because the inner multiplication loop is much simpler than
8701 : * the outer loop, so it's better to have a smaller number of iterations
8702 : * of the outer loop. This also reduces the number of times that the
8703 : * accumulator array needs to be normalized.
8704 : */
8705 830586 : if (var1->ndigits > var2->ndigits)
8706 : {
8707 14848 : const NumericVar *tmp = var1;
8708 :
8709 14848 : var1 = var2;
8710 14848 : var2 = tmp;
8711 : }
8712 :
8713 : /* copy these values into local vars for speed in inner loop */
8714 830586 : var1ndigits = var1->ndigits;
8715 830586 : var2ndigits = var2->ndigits;
8716 830586 : var1digits = var1->digits;
8717 830586 : var2digits = var2->digits;
8718 :
8719 830586 : if (var1ndigits == 0)
8720 : {
8721 : /* one or both inputs is zero; so is result */
8722 1712 : zero_var(result);
8723 1712 : result->dscale = rscale;
8724 1712 : return;
8725 : }
8726 :
8727 : /*
8728 : * If var1 has 1-6 digits and the exact result was requested, delegate to
8729 : * mul_var_short() which uses a faster direct multiplication algorithm.
8730 : */
8731 828874 : if (var1ndigits <= 6 && rscale == var1->dscale + var2->dscale)
8732 : {
8733 800404 : mul_var_short(var1, var2, result);
8734 800404 : return;
8735 : }
8736 :
8737 : /* Determine result sign */
8738 28470 : if (var1->sign == var2->sign)
8739 26988 : res_sign = NUMERIC_POS;
8740 : else
8741 1482 : res_sign = NUMERIC_NEG;
8742 :
8743 : /*
8744 : * Determine the number of result digits to compute and the (maximum
8745 : * possible) result weight. If the exact result would have more than
8746 : * rscale fractional digits, truncate the computation with
8747 : * MUL_GUARD_DIGITS guard digits, i.e., ignore input digits that would
8748 : * only contribute to the right of that. (This will give the exact
8749 : * rounded-to-rscale answer unless carries out of the ignored positions
8750 : * would have propagated through more than MUL_GUARD_DIGITS digits.)
8751 : *
8752 : * Note: an exact computation could not produce more than var1ndigits +
8753 : * var2ndigits digits, but we allocate at least one extra output digit in
8754 : * case rscale-driven rounding produces a carry out of the highest exact
8755 : * digit.
8756 : *
8757 : * The computation itself is done using base-NBASE^2 arithmetic, so we
8758 : * actually process the input digits in pairs, producing a base-NBASE^2
8759 : * intermediate result. This significantly improves performance, since
8760 : * schoolbook multiplication is O(N^2) in the number of input digits, and
8761 : * working in base NBASE^2 effectively halves "N".
8762 : *
8763 : * Note: in a truncated computation, we must compute at least one extra
8764 : * output digit to ensure that all the guard digits are fully computed.
8765 : */
8766 : /* digit pairs in each input */
8767 28470 : var1ndigitpairs = (var1ndigits + 1) / 2;
8768 28470 : var2ndigitpairs = (var2ndigits + 1) / 2;
8769 :
8770 : /* digits in exact result */
8771 28470 : res_ndigits = var1ndigits + var2ndigits;
8772 :
8773 : /* digit pairs in exact result with at least one extra output digit */
8774 28470 : res_ndigitpairs = res_ndigits / 2 + 1;
8775 :
8776 : /* pair offset to align result to end of dig[] */
8777 28470 : pair_offset = res_ndigitpairs - var1ndigitpairs - var2ndigitpairs + 1;
8778 :
8779 : /* maximum possible result weight (odd-length inputs shifted up below) */
8780 28470 : res_weight = var1->weight + var2->weight + 1 + 2 * res_ndigitpairs -
8781 28470 : res_ndigits - (var1ndigits & 1) - (var2ndigits & 1);
8782 :
8783 : /* rscale-based truncation with at least one extra output digit */
8784 28470 : maxdigits = res_weight + 1 + (rscale + DEC_DIGITS - 1) / DEC_DIGITS +
8785 : MUL_GUARD_DIGITS;
8786 28470 : maxdigitpairs = maxdigits / 2 + 1;
8787 :
8788 28470 : res_ndigitpairs = Min(res_ndigitpairs, maxdigitpairs);
8789 28470 : res_ndigits = 2 * res_ndigitpairs;
8790 :
8791 : /*
8792 : * In the computation below, digit pair i1 of var1 and digit pair i2 of
8793 : * var2 are multiplied and added to digit i1+i2+pair_offset of dig[]. Thus
8794 : * input digit pairs with index >= res_ndigitpairs - pair_offset don't
8795 : * contribute to the result, and can be ignored.
8796 : */
8797 28470 : if (res_ndigitpairs <= pair_offset)
8798 : {
8799 : /* All input digits will be ignored; so result is zero */
8800 12 : zero_var(result);
8801 12 : result->dscale = rscale;
8802 12 : return;
8803 : }
8804 28458 : var1ndigitpairs = Min(var1ndigitpairs, res_ndigitpairs - pair_offset);
8805 28458 : var2ndigitpairs = Min(var2ndigitpairs, res_ndigitpairs - pair_offset);
8806 :
8807 : /*
8808 : * We do the arithmetic in an array "dig[]" of unsigned 64-bit integers.
8809 : * Since PG_UINT64_MAX is much larger than NBASE^4, this gives us a lot of
8810 : * headroom to avoid normalizing carries immediately.
8811 : *
8812 : * maxdig tracks the maximum possible value of any dig[] entry; when this
8813 : * threatens to exceed PG_UINT64_MAX, we take the time to propagate
8814 : * carries. Furthermore, we need to ensure that overflow doesn't occur
8815 : * during the carry propagation passes either. The carry values could be
8816 : * as much as PG_UINT64_MAX / NBASE^2, so really we must normalize when
8817 : * digits threaten to exceed PG_UINT64_MAX - PG_UINT64_MAX / NBASE^2.
8818 : *
8819 : * To avoid overflow in maxdig itself, it actually represents the maximum
8820 : * possible value divided by NBASE^2-1, i.e., at the top of the loop it is
8821 : * known that no dig[] entry exceeds maxdig * (NBASE^2-1).
8822 : *
8823 : * The conversion of var1 to base NBASE^2 is done on the fly, as each new
8824 : * digit is required. The digits of var2 are converted upfront, and
8825 : * stored at the end of dig[]. To avoid loss of precision, the input
8826 : * digits are aligned with the start of digit pair array, effectively
8827 : * shifting them up (multiplying by NBASE) if the inputs have an odd
8828 : * number of NBASE digits.
8829 : */
8830 28458 : dig = (uint64 *) palloc(res_ndigitpairs * sizeof(uint64) +
8831 : var2ndigitpairs * sizeof(uint32));
8832 :
8833 : /* convert var2 to base NBASE^2, shifting up if its length is odd */
8834 28458 : var2digitpairs = (uint32 *) (dig + res_ndigitpairs);
8835 :
8836 1547184 : for (i2 = 0; i2 < var2ndigitpairs - 1; i2++)
8837 1518726 : var2digitpairs[i2] = var2digits[2 * i2] * NBASE + var2digits[2 * i2 + 1];
8838 :
8839 28458 : if (2 * i2 + 1 < var2ndigits)
8840 20448 : var2digitpairs[i2] = var2digits[2 * i2] * NBASE + var2digits[2 * i2 + 1];
8841 : else
8842 8010 : var2digitpairs[i2] = var2digits[2 * i2] * NBASE;
8843 :
8844 : /*
8845 : * Start by multiplying var2 by the least significant contributing digit
8846 : * pair from var1, storing the results at the end of dig[], and filling
8847 : * the leading digits with zeros.
8848 : *
8849 : * The loop here is the same as the inner loop below, except that we set
8850 : * the results in dig[], rather than adding to them. This is the
8851 : * performance bottleneck for multiplication, so we want to keep it simple
8852 : * enough so that it can be auto-vectorized. Accordingly, process the
8853 : * digits left-to-right even though schoolbook multiplication would
8854 : * suggest right-to-left. Since we aren't propagating carries in this
8855 : * loop, the order does not matter.
8856 : */
8857 28458 : i1 = var1ndigitpairs - 1;
8858 28458 : if (2 * i1 + 1 < var1ndigits)
8859 12720 : var1digitpair = var1digits[2 * i1] * NBASE + var1digits[2 * i1 + 1];
8860 : else
8861 15738 : var1digitpair = var1digits[2 * i1] * NBASE;
8862 28458 : maxdig = var1digitpair;
8863 :
8864 28458 : i2limit = Min(var2ndigitpairs, res_ndigitpairs - i1 - pair_offset);
8865 28458 : dig_i1_off = &dig[i1 + pair_offset];
8866 :
8867 28458 : memset(dig, 0, (i1 + pair_offset) * sizeof(uint64));
8868 1376610 : for (i2 = 0; i2 < i2limit; i2++)
8869 1348152 : dig_i1_off[i2] = (uint64) var1digitpair * var2digitpairs[i2];
8870 :
8871 : /*
8872 : * Next, multiply var2 by the remaining digit pairs from var1, adding the
8873 : * results to dig[] at the appropriate offsets, and normalizing whenever
8874 : * there is a risk of any dig[] entry overflowing.
8875 : */
8876 1501704 : for (i1 = i1 - 1; i1 >= 0; i1--)
8877 : {
8878 1473246 : var1digitpair = var1digits[2 * i1] * NBASE + var1digits[2 * i1 + 1];
8879 1473246 : if (var1digitpair == 0)
8880 1179516 : continue;
8881 :
8882 : /* Time to normalize? */
8883 293730 : maxdig += var1digitpair;
8884 293730 : if (maxdig > (PG_UINT64_MAX - PG_UINT64_MAX / NBASE_SQR) / (NBASE_SQR - 1))
8885 : {
8886 : /* Yes, do it (to base NBASE^2) */
8887 30 : carry = 0;
8888 119964 : for (i = res_ndigitpairs - 1; i >= 0; i--)
8889 : {
8890 119934 : newdig = dig[i] + carry;
8891 119934 : if (newdig >= NBASE_SQR)
8892 : {
8893 115242 : carry = newdig / NBASE_SQR;
8894 115242 : newdig -= carry * NBASE_SQR;
8895 : }
8896 : else
8897 4692 : carry = 0;
8898 119934 : dig[i] = newdig;
8899 : }
8900 : Assert(carry == 0);
8901 : /* Reset maxdig to indicate new worst-case */
8902 30 : maxdig = 1 + var1digitpair;
8903 : }
8904 :
8905 : /* Multiply and add */
8906 293730 : i2limit = Min(var2ndigitpairs, res_ndigitpairs - i1 - pair_offset);
8907 293730 : dig_i1_off = &dig[i1 + pair_offset];
8908 :
8909 124047846 : for (i2 = 0; i2 < i2limit; i2++)
8910 123754116 : dig_i1_off[i2] += (uint64) var1digitpair * var2digitpairs[i2];
8911 : }
8912 :
8913 : /*
8914 : * Now we do a final carry propagation pass to normalize back to base
8915 : * NBASE^2, and construct the base-NBASE result digits. Note that this is
8916 : * still done at full precision w/guard digits.
8917 : */
8918 28458 : alloc_var(result, res_ndigits);
8919 28458 : res_digits = result->digits;
8920 28458 : carry = 0;
8921 2882904 : for (i = res_ndigitpairs - 1; i >= 0; i--)
8922 : {
8923 2854446 : newdig = dig[i] + carry;
8924 2854446 : if (newdig >= NBASE_SQR)
8925 : {
8926 406908 : carry = newdig / NBASE_SQR;
8927 406908 : newdig -= carry * NBASE_SQR;
8928 : }
8929 : else
8930 2447538 : carry = 0;
8931 2854446 : res_digits[2 * i + 1] = (NumericDigit) ((uint32) newdig % NBASE);
8932 2854446 : res_digits[2 * i] = (NumericDigit) ((uint32) newdig / NBASE);
8933 : }
8934 : Assert(carry == 0);
8935 :
8936 28458 : pfree(dig);
8937 :
8938 : /*
8939 : * Finally, round the result to the requested precision.
8940 : */
8941 28458 : result->weight = res_weight;
8942 28458 : result->sign = res_sign;
8943 :
8944 : /* Round to target rscale (and set result->dscale) */
8945 28458 : round_var(result, rscale);
8946 :
8947 : /* Strip leading and trailing zeroes */
8948 28458 : strip_var(result);
8949 : }
8950 :
8951 :
8952 : /*
8953 : * mul_var_short() -
8954 : *
8955 : * Special-case multiplication function used when var1 has 1-6 digits, var2
8956 : * has at least as many digits as var1, and the exact product var1 * var2 is
8957 : * requested.
8958 : */
8959 : static void
8960 800404 : mul_var_short(const NumericVar *var1, const NumericVar *var2,
8961 : NumericVar *result)
8962 : {
8963 800404 : int var1ndigits = var1->ndigits;
8964 800404 : int var2ndigits = var2->ndigits;
8965 800404 : NumericDigit *var1digits = var1->digits;
8966 800404 : NumericDigit *var2digits = var2->digits;
8967 : int res_sign;
8968 : int res_weight;
8969 : int res_ndigits;
8970 : NumericDigit *res_buf;
8971 : NumericDigit *res_digits;
8972 800404 : uint32 carry = 0;
8973 : uint32 term;
8974 :
8975 : /* Check preconditions */
8976 : Assert(var1ndigits >= 1);
8977 : Assert(var1ndigits <= 6);
8978 : Assert(var2ndigits >= var1ndigits);
8979 :
8980 : /*
8981 : * Determine the result sign, weight, and number of digits to calculate.
8982 : * The weight figured here is correct if the product has no leading zero
8983 : * digits; otherwise strip_var() will fix things up. Note that, unlike
8984 : * mul_var(), we do not need to allocate an extra output digit, because we
8985 : * are not rounding here.
8986 : */
8987 800404 : if (var1->sign == var2->sign)
8988 799212 : res_sign = NUMERIC_POS;
8989 : else
8990 1192 : res_sign = NUMERIC_NEG;
8991 800404 : res_weight = var1->weight + var2->weight + 1;
8992 800404 : res_ndigits = var1ndigits + var2ndigits;
8993 :
8994 : /* Allocate result digit array */
8995 800404 : res_buf = digitbuf_alloc(res_ndigits + 1);
8996 800404 : res_buf[0] = 0; /* spare digit for later rounding */
8997 800404 : res_digits = res_buf + 1;
8998 :
8999 : /*
9000 : * Compute the result digits in reverse, in one pass, propagating the
9001 : * carry up as we go. The i'th result digit consists of the sum of the
9002 : * products var1digits[i1] * var2digits[i2] for which i = i1 + i2 + 1.
9003 : */
9004 : #define PRODSUM1(v1,i1,v2,i2) ((v1)[(i1)] * (v2)[(i2)])
9005 : #define PRODSUM2(v1,i1,v2,i2) (PRODSUM1(v1,i1,v2,i2) + (v1)[(i1)+1] * (v2)[(i2)-1])
9006 : #define PRODSUM3(v1,i1,v2,i2) (PRODSUM2(v1,i1,v2,i2) + (v1)[(i1)+2] * (v2)[(i2)-2])
9007 : #define PRODSUM4(v1,i1,v2,i2) (PRODSUM3(v1,i1,v2,i2) + (v1)[(i1)+3] * (v2)[(i2)-3])
9008 : #define PRODSUM5(v1,i1,v2,i2) (PRODSUM4(v1,i1,v2,i2) + (v1)[(i1)+4] * (v2)[(i2)-4])
9009 : #define PRODSUM6(v1,i1,v2,i2) (PRODSUM5(v1,i1,v2,i2) + (v1)[(i1)+5] * (v2)[(i2)-5])
9010 :
9011 800404 : switch (var1ndigits)
9012 : {
9013 794698 : case 1:
9014 : /* ---------
9015 : * 1-digit case:
9016 : * var1ndigits = 1
9017 : * var2ndigits >= 1
9018 : * res_ndigits = var2ndigits + 1
9019 : * ----------
9020 : */
9021 2876504 : for (int i = var2ndigits - 1; i >= 0; i--)
9022 : {
9023 2081806 : term = PRODSUM1(var1digits, 0, var2digits, i) + carry;
9024 2081806 : res_digits[i + 1] = (NumericDigit) (term % NBASE);
9025 2081806 : carry = term / NBASE;
9026 : }
9027 794698 : res_digits[0] = (NumericDigit) carry;
9028 794698 : break;
9029 :
9030 756 : case 2:
9031 : /* ---------
9032 : * 2-digit case:
9033 : * var1ndigits = 2
9034 : * var2ndigits >= 2
9035 : * res_ndigits = var2ndigits + 2
9036 : * ----------
9037 : */
9038 : /* last result digit and carry */
9039 756 : term = PRODSUM1(var1digits, 1, var2digits, var2ndigits - 1);
9040 756 : res_digits[res_ndigits - 1] = (NumericDigit) (term % NBASE);
9041 756 : carry = term / NBASE;
9042 :
9043 : /* remaining digits, except for the first two */
9044 2304 : for (int i = var2ndigits - 1; i >= 1; i--)
9045 : {
9046 1548 : term = PRODSUM2(var1digits, 0, var2digits, i) + carry;
9047 1548 : res_digits[i + 1] = (NumericDigit) (term % NBASE);
9048 1548 : carry = term / NBASE;
9049 : }
9050 756 : break;
9051 :
9052 204 : case 3:
9053 : /* ---------
9054 : * 3-digit case:
9055 : * var1ndigits = 3
9056 : * var2ndigits >= 3
9057 : * res_ndigits = var2ndigits + 3
9058 : * ----------
9059 : */
9060 : /* last two result digits */
9061 204 : term = PRODSUM1(var1digits, 2, var2digits, var2ndigits - 1);
9062 204 : res_digits[res_ndigits - 1] = (NumericDigit) (term % NBASE);
9063 204 : carry = term / NBASE;
9064 :
9065 204 : term = PRODSUM2(var1digits, 1, var2digits, var2ndigits - 1) + carry;
9066 204 : res_digits[res_ndigits - 2] = (NumericDigit) (term % NBASE);
9067 204 : carry = term / NBASE;
9068 :
9069 : /* remaining digits, except for the first three */
9070 546 : for (int i = var2ndigits - 1; i >= 2; i--)
9071 : {
9072 342 : term = PRODSUM3(var1digits, 0, var2digits, i) + carry;
9073 342 : res_digits[i + 1] = (NumericDigit) (term % NBASE);
9074 342 : carry = term / NBASE;
9075 : }
9076 204 : break;
9077 :
9078 4038 : case 4:
9079 : /* ---------
9080 : * 4-digit case:
9081 : * var1ndigits = 4
9082 : * var2ndigits >= 4
9083 : * res_ndigits = var2ndigits + 4
9084 : * ----------
9085 : */
9086 : /* last three result digits */
9087 4038 : term = PRODSUM1(var1digits, 3, var2digits, var2ndigits - 1);
9088 4038 : res_digits[res_ndigits - 1] = (NumericDigit) (term % NBASE);
9089 4038 : carry = term / NBASE;
9090 :
9091 4038 : term = PRODSUM2(var1digits, 2, var2digits, var2ndigits - 1) + carry;
9092 4038 : res_digits[res_ndigits - 2] = (NumericDigit) (term % NBASE);
9093 4038 : carry = term / NBASE;
9094 :
9095 4038 : term = PRODSUM3(var1digits, 1, var2digits, var2ndigits - 1) + carry;
9096 4038 : res_digits[res_ndigits - 3] = (NumericDigit) (term % NBASE);
9097 4038 : carry = term / NBASE;
9098 :
9099 : /* remaining digits, except for the first four */
9100 11268 : for (int i = var2ndigits - 1; i >= 3; i--)
9101 : {
9102 7230 : term = PRODSUM4(var1digits, 0, var2digits, i) + carry;
9103 7230 : res_digits[i + 1] = (NumericDigit) (term % NBASE);
9104 7230 : carry = term / NBASE;
9105 : }
9106 4038 : break;
9107 :
9108 114 : case 5:
9109 : /* ---------
9110 : * 5-digit case:
9111 : * var1ndigits = 5
9112 : * var2ndigits >= 5
9113 : * res_ndigits = var2ndigits + 5
9114 : * ----------
9115 : */
9116 : /* last four result digits */
9117 114 : term = PRODSUM1(var1digits, 4, var2digits, var2ndigits - 1);
9118 114 : res_digits[res_ndigits - 1] = (NumericDigit) (term % NBASE);
9119 114 : carry = term / NBASE;
9120 :
9121 114 : term = PRODSUM2(var1digits, 3, var2digits, var2ndigits - 1) + carry;
9122 114 : res_digits[res_ndigits - 2] = (NumericDigit) (term % NBASE);
9123 114 : carry = term / NBASE;
9124 :
9125 114 : term = PRODSUM3(var1digits, 2, var2digits, var2ndigits - 1) + carry;
9126 114 : res_digits[res_ndigits - 3] = (NumericDigit) (term % NBASE);
9127 114 : carry = term / NBASE;
9128 :
9129 114 : term = PRODSUM4(var1digits, 1, var2digits, var2ndigits - 1) + carry;
9130 114 : res_digits[res_ndigits - 4] = (NumericDigit) (term % NBASE);
9131 114 : carry = term / NBASE;
9132 :
9133 : /* remaining digits, except for the first five */
9134 300 : for (int i = var2ndigits - 1; i >= 4; i--)
9135 : {
9136 186 : term = PRODSUM5(var1digits, 0, var2digits, i) + carry;
9137 186 : res_digits[i + 1] = (NumericDigit) (term % NBASE);
9138 186 : carry = term / NBASE;
9139 : }
9140 114 : break;
9141 :
9142 594 : case 6:
9143 : /* ---------
9144 : * 6-digit case:
9145 : * var1ndigits = 6
9146 : * var2ndigits >= 6
9147 : * res_ndigits = var2ndigits + 6
9148 : * ----------
9149 : */
9150 : /* last five result digits */
9151 594 : term = PRODSUM1(var1digits, 5, var2digits, var2ndigits - 1);
9152 594 : res_digits[res_ndigits - 1] = (NumericDigit) (term % NBASE);
9153 594 : carry = term / NBASE;
9154 :
9155 594 : term = PRODSUM2(var1digits, 4, var2digits, var2ndigits - 1) + carry;
9156 594 : res_digits[res_ndigits - 2] = (NumericDigit) (term % NBASE);
9157 594 : carry = term / NBASE;
9158 :
9159 594 : term = PRODSUM3(var1digits, 3, var2digits, var2ndigits - 1) + carry;
9160 594 : res_digits[res_ndigits - 3] = (NumericDigit) (term % NBASE);
9161 594 : carry = term / NBASE;
9162 :
9163 594 : term = PRODSUM4(var1digits, 2, var2digits, var2ndigits - 1) + carry;
9164 594 : res_digits[res_ndigits - 4] = (NumericDigit) (term % NBASE);
9165 594 : carry = term / NBASE;
9166 :
9167 594 : term = PRODSUM5(var1digits, 1, var2digits, var2ndigits - 1) + carry;
9168 594 : res_digits[res_ndigits - 5] = (NumericDigit) (term % NBASE);
9169 594 : carry = term / NBASE;
9170 :
9171 : /* remaining digits, except for the first six */
9172 1656 : for (int i = var2ndigits - 1; i >= 5; i--)
9173 : {
9174 1062 : term = PRODSUM6(var1digits, 0, var2digits, i) + carry;
9175 1062 : res_digits[i + 1] = (NumericDigit) (term % NBASE);
9176 1062 : carry = term / NBASE;
9177 : }
9178 594 : break;
9179 : }
9180 :
9181 : /*
9182 : * Finally, for var1ndigits > 1, compute the remaining var1ndigits most
9183 : * significant result digits.
9184 : */
9185 800404 : switch (var1ndigits)
9186 : {
9187 594 : case 6:
9188 594 : term = PRODSUM5(var1digits, 0, var2digits, 4) + carry;
9189 594 : res_digits[5] = (NumericDigit) (term % NBASE);
9190 594 : carry = term / NBASE;
9191 : /* FALLTHROUGH */
9192 708 : case 5:
9193 708 : term = PRODSUM4(var1digits, 0, var2digits, 3) + carry;
9194 708 : res_digits[4] = (NumericDigit) (term % NBASE);
9195 708 : carry = term / NBASE;
9196 : /* FALLTHROUGH */
9197 4746 : case 4:
9198 4746 : term = PRODSUM3(var1digits, 0, var2digits, 2) + carry;
9199 4746 : res_digits[3] = (NumericDigit) (term % NBASE);
9200 4746 : carry = term / NBASE;
9201 : /* FALLTHROUGH */
9202 4950 : case 3:
9203 4950 : term = PRODSUM2(var1digits, 0, var2digits, 1) + carry;
9204 4950 : res_digits[2] = (NumericDigit) (term % NBASE);
9205 4950 : carry = term / NBASE;
9206 : /* FALLTHROUGH */
9207 5706 : case 2:
9208 5706 : term = PRODSUM1(var1digits, 0, var2digits, 0) + carry;
9209 5706 : res_digits[1] = (NumericDigit) (term % NBASE);
9210 5706 : res_digits[0] = (NumericDigit) (term / NBASE);
9211 5706 : break;
9212 : }
9213 :
9214 : /* Store the product in result */
9215 800404 : digitbuf_free(result->buf);
9216 800404 : result->ndigits = res_ndigits;
9217 800404 : result->buf = res_buf;
9218 800404 : result->digits = res_digits;
9219 800404 : result->weight = res_weight;
9220 800404 : result->sign = res_sign;
9221 800404 : result->dscale = var1->dscale + var2->dscale;
9222 :
9223 : /* Strip leading and trailing zeroes */
9224 800404 : strip_var(result);
9225 800404 : }
9226 :
9227 :
9228 : /*
9229 : * div_var() -
9230 : *
9231 : * Division on variable level. Quotient of var1 / var2 is stored in result.
9232 : * The quotient is figured to exactly rscale fractional digits.
9233 : * If round is true, it is rounded at the rscale'th digit; if false, it
9234 : * is truncated (towards zero) at that digit.
9235 : */
9236 : static void
9237 210136 : div_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result,
9238 : int rscale, bool round)
9239 : {
9240 : int div_ndigits;
9241 : int res_ndigits;
9242 : int res_sign;
9243 : int res_weight;
9244 : int carry;
9245 : int borrow;
9246 : int divisor1;
9247 : int divisor2;
9248 : NumericDigit *dividend;
9249 : NumericDigit *divisor;
9250 : NumericDigit *res_digits;
9251 : int i;
9252 : int j;
9253 :
9254 : /* copy these values into local vars for speed in inner loop */
9255 210136 : int var1ndigits = var1->ndigits;
9256 210136 : int var2ndigits = var2->ndigits;
9257 :
9258 : /*
9259 : * First of all division by zero check; we must not be handed an
9260 : * unnormalized divisor.
9261 : */
9262 210136 : if (var2ndigits == 0 || var2->digits[0] == 0)
9263 56 : ereport(ERROR,
9264 : (errcode(ERRCODE_DIVISION_BY_ZERO),
9265 : errmsg("division by zero")));
9266 :
9267 : /*
9268 : * If the divisor has just one or two digits, delegate to div_var_int(),
9269 : * which uses fast short division.
9270 : *
9271 : * Similarly, on platforms with 128-bit integer support, delegate to
9272 : * div_var_int64() for divisors with three or four digits.
9273 : */
9274 210080 : if (var2ndigits <= 2)
9275 : {
9276 : int idivisor;
9277 : int idivisor_weight;
9278 :
9279 205324 : idivisor = var2->digits[0];
9280 205324 : idivisor_weight = var2->weight;
9281 205324 : if (var2ndigits == 2)
9282 : {
9283 4728 : idivisor = idivisor * NBASE + var2->digits[1];
9284 4728 : idivisor_weight--;
9285 : }
9286 205324 : if (var2->sign == NUMERIC_NEG)
9287 642 : idivisor = -idivisor;
9288 :
9289 205324 : div_var_int(var1, idivisor, idivisor_weight, result, rscale, round);
9290 205324 : return;
9291 : }
9292 : #ifdef HAVE_INT128
9293 4756 : if (var2ndigits <= 4)
9294 : {
9295 : int64 idivisor;
9296 : int idivisor_weight;
9297 :
9298 480 : idivisor = var2->digits[0];
9299 480 : idivisor_weight = var2->weight;
9300 1800 : for (i = 1; i < var2ndigits; i++)
9301 : {
9302 1320 : idivisor = idivisor * NBASE + var2->digits[i];
9303 1320 : idivisor_weight--;
9304 : }
9305 480 : if (var2->sign == NUMERIC_NEG)
9306 120 : idivisor = -idivisor;
9307 :
9308 480 : div_var_int64(var1, idivisor, idivisor_weight, result, rscale, round);
9309 480 : return;
9310 : }
9311 : #endif
9312 :
9313 : /*
9314 : * Otherwise, perform full long division.
9315 : */
9316 :
9317 : /* Result zero check */
9318 4276 : if (var1ndigits == 0)
9319 : {
9320 24 : zero_var(result);
9321 24 : result->dscale = rscale;
9322 24 : return;
9323 : }
9324 :
9325 : /*
9326 : * Determine the result sign, weight and number of digits to calculate.
9327 : * The weight figured here is correct if the emitted quotient has no
9328 : * leading zero digits; otherwise strip_var() will fix things up.
9329 : */
9330 4252 : if (var1->sign == var2->sign)
9331 4192 : res_sign = NUMERIC_POS;
9332 : else
9333 60 : res_sign = NUMERIC_NEG;
9334 4252 : res_weight = var1->weight - var2->weight;
9335 : /* The number of accurate result digits we need to produce: */
9336 4252 : res_ndigits = res_weight + 1 + (rscale + DEC_DIGITS - 1) / DEC_DIGITS;
9337 : /* ... but always at least 1 */
9338 4252 : res_ndigits = Max(res_ndigits, 1);
9339 : /* If rounding needed, figure one more digit to ensure correct result */
9340 4252 : if (round)
9341 4246 : res_ndigits++;
9342 :
9343 : /*
9344 : * The working dividend normally requires res_ndigits + var2ndigits
9345 : * digits, but make it at least var1ndigits so we can load all of var1
9346 : * into it. (There will be an additional digit dividend[0] in the
9347 : * dividend space, but for consistency with Knuth's notation we don't
9348 : * count that in div_ndigits.)
9349 : */
9350 4252 : div_ndigits = res_ndigits + var2ndigits;
9351 4252 : div_ndigits = Max(div_ndigits, var1ndigits);
9352 :
9353 : /*
9354 : * We need a workspace with room for the working dividend (div_ndigits+1
9355 : * digits) plus room for the possibly-normalized divisor (var2ndigits
9356 : * digits). It is convenient also to have a zero at divisor[0] with the
9357 : * actual divisor data in divisor[1 .. var2ndigits]. Transferring the
9358 : * digits into the workspace also allows us to realloc the result (which
9359 : * might be the same as either input var) before we begin the main loop.
9360 : * Note that we use palloc0 to ensure that divisor[0], dividend[0], and
9361 : * any additional dividend positions beyond var1ndigits, start out 0.
9362 : */
9363 : dividend = (NumericDigit *)
9364 4252 : palloc0((div_ndigits + var2ndigits + 2) * sizeof(NumericDigit));
9365 4252 : divisor = dividend + (div_ndigits + 1);
9366 4252 : memcpy(dividend + 1, var1->digits, var1ndigits * sizeof(NumericDigit));
9367 4252 : memcpy(divisor + 1, var2->digits, var2ndigits * sizeof(NumericDigit));
9368 :
9369 : /*
9370 : * Now we can realloc the result to hold the generated quotient digits.
9371 : */
9372 4252 : alloc_var(result, res_ndigits);
9373 4252 : res_digits = result->digits;
9374 :
9375 : /*
9376 : * The full multiple-place algorithm is taken from Knuth volume 2,
9377 : * Algorithm 4.3.1D.
9378 : *
9379 : * We need the first divisor digit to be >= NBASE/2. If it isn't, make it
9380 : * so by scaling up both the divisor and dividend by the factor "d". (The
9381 : * reason for allocating dividend[0] above is to leave room for possible
9382 : * carry here.)
9383 : */
9384 4252 : if (divisor[1] < HALF_NBASE)
9385 : {
9386 4252 : int d = NBASE / (divisor[1] + 1);
9387 :
9388 4252 : carry = 0;
9389 144492 : for (i = var2ndigits; i > 0; i--)
9390 : {
9391 140240 : carry += divisor[i] * d;
9392 140240 : divisor[i] = carry % NBASE;
9393 140240 : carry = carry / NBASE;
9394 : }
9395 : Assert(carry == 0);
9396 4252 : carry = 0;
9397 : /* at this point only var1ndigits of dividend can be nonzero */
9398 36394 : for (i = var1ndigits; i >= 0; i--)
9399 : {
9400 32142 : carry += dividend[i] * d;
9401 32142 : dividend[i] = carry % NBASE;
9402 32142 : carry = carry / NBASE;
9403 : }
9404 : Assert(carry == 0);
9405 : Assert(divisor[1] >= HALF_NBASE);
9406 : }
9407 : /* First 2 divisor digits are used repeatedly in main loop */
9408 4252 : divisor1 = divisor[1];
9409 4252 : divisor2 = divisor[2];
9410 :
9411 : /*
9412 : * Begin the main loop. Each iteration of this loop produces the j'th
9413 : * quotient digit by dividing dividend[j .. j + var2ndigits] by the
9414 : * divisor; this is essentially the same as the common manual procedure
9415 : * for long division.
9416 : */
9417 33460 : for (j = 0; j < res_ndigits; j++)
9418 : {
9419 : /* Estimate quotient digit from the first two dividend digits */
9420 29208 : int next2digits = dividend[j] * NBASE + dividend[j + 1];
9421 : int qhat;
9422 :
9423 : /*
9424 : * If next2digits are 0, then quotient digit must be 0 and there's no
9425 : * need to adjust the working dividend. It's worth testing here to
9426 : * fall out ASAP when processing trailing zeroes in a dividend.
9427 : */
9428 29208 : if (next2digits == 0)
9429 : {
9430 72 : res_digits[j] = 0;
9431 72 : continue;
9432 : }
9433 :
9434 29136 : if (dividend[j] == divisor1)
9435 120 : qhat = NBASE - 1;
9436 : else
9437 29016 : qhat = next2digits / divisor1;
9438 :
9439 : /*
9440 : * Adjust quotient digit if it's too large. Knuth proves that after
9441 : * this step, the quotient digit will be either correct or just one
9442 : * too large. (Note: it's OK to use dividend[j+2] here because we
9443 : * know the divisor length is at least 2.)
9444 : */
9445 29136 : while (divisor2 * qhat >
9446 32096 : (next2digits - qhat * divisor1) * NBASE + dividend[j + 2])
9447 2960 : qhat--;
9448 :
9449 : /* As above, need do nothing more when quotient digit is 0 */
9450 29136 : if (qhat > 0)
9451 : {
9452 25616 : NumericDigit *dividend_j = ÷nd[j];
9453 :
9454 : /*
9455 : * Multiply the divisor by qhat, and subtract that from the
9456 : * working dividend. The multiplication and subtraction are
9457 : * folded together here, noting that qhat <= NBASE (since it might
9458 : * be one too large), and so the intermediate result "tmp_result"
9459 : * is in the range [-NBASE^2, NBASE - 1], and "borrow" is in the
9460 : * range [0, NBASE].
9461 : */
9462 25616 : borrow = 0;
9463 897766 : for (i = var2ndigits; i >= 0; i--)
9464 : {
9465 : int tmp_result;
9466 :
9467 872150 : tmp_result = dividend_j[i] - borrow - divisor[i] * qhat;
9468 872150 : borrow = (NBASE - 1 - tmp_result) / NBASE;
9469 872150 : dividend_j[i] = tmp_result + borrow * NBASE;
9470 : }
9471 :
9472 : /*
9473 : * If we got a borrow out of the top dividend digit, then indeed
9474 : * qhat was one too large. Fix it, and add back the divisor to
9475 : * correct the working dividend. (Knuth proves that this will
9476 : * occur only about 3/NBASE of the time; hence, it's a good idea
9477 : * to test this code with small NBASE to be sure this section gets
9478 : * exercised.)
9479 : */
9480 25616 : if (borrow)
9481 : {
9482 26 : qhat--;
9483 26 : carry = 0;
9484 2308 : for (i = var2ndigits; i >= 0; i--)
9485 : {
9486 2282 : carry += dividend_j[i] + divisor[i];
9487 2282 : if (carry >= NBASE)
9488 : {
9489 2094 : dividend_j[i] = carry - NBASE;
9490 2094 : carry = 1;
9491 : }
9492 : else
9493 : {
9494 188 : dividend_j[i] = carry;
9495 188 : carry = 0;
9496 : }
9497 : }
9498 : /* A carry should occur here to cancel the borrow above */
9499 : Assert(carry == 1);
9500 : }
9501 : }
9502 :
9503 : /* And we're done with this quotient digit */
9504 29136 : res_digits[j] = qhat;
9505 : }
9506 :
9507 4252 : pfree(dividend);
9508 :
9509 : /*
9510 : * Finally, round or truncate the result to the requested precision.
9511 : */
9512 4252 : result->weight = res_weight;
9513 4252 : result->sign = res_sign;
9514 :
9515 : /* Round or truncate to target rscale (and set result->dscale) */
9516 4252 : if (round)
9517 4246 : round_var(result, rscale);
9518 : else
9519 6 : trunc_var(result, rscale);
9520 :
9521 : /* Strip leading and trailing zeroes */
9522 4252 : strip_var(result);
9523 : }
9524 :
9525 :
9526 : /*
9527 : * div_var_fast() -
9528 : *
9529 : * This has the same API as div_var, but is implemented using the division
9530 : * algorithm from the "FM" library, rather than Knuth's schoolbook-division
9531 : * approach. This is significantly faster but can produce inaccurate
9532 : * results, because it sometimes has to propagate rounding to the left,
|