/src/postgres/src/backend/utils/adt/numeric.c
Line | Count | Source |
1 | | /*------------------------------------------------------------------------- |
2 | | * |
3 | | * numeric.c |
4 | | * An exact numeric data type for the Postgres database system |
5 | | * |
6 | | * Original coding 1998, Jan Wieck. Heavily revised 2003, Tom Lane. |
7 | | * |
8 | | * Many of the algorithmic ideas are borrowed from David M. Smith's "FM" |
9 | | * multiple-precision math library, most recently published as Algorithm |
10 | | * 786: Multiple-Precision Complex Arithmetic and Functions, ACM |
11 | | * Transactions on Mathematical Software, Vol. 24, No. 4, December 1998, |
12 | | * pages 359-367. |
13 | | * |
14 | | * Copyright (c) 1998-2026, PostgreSQL Global Development Group |
15 | | * |
16 | | * IDENTIFICATION |
17 | | * src/backend/utils/adt/numeric.c |
18 | | * |
19 | | *------------------------------------------------------------------------- |
20 | | */ |
21 | | |
22 | | #include "postgres.h" |
23 | | |
24 | | #include <ctype.h> |
25 | | #include <float.h> |
26 | | #include <limits.h> |
27 | | #include <math.h> |
28 | | |
29 | | #include "common/hashfn.h" |
30 | | #include "common/int.h" |
31 | | #include "common/int128.h" |
32 | | #include "funcapi.h" |
33 | | #include "lib/hyperloglog.h" |
34 | | #include "libpq/pqformat.h" |
35 | | #include "miscadmin.h" |
36 | | #include "nodes/nodeFuncs.h" |
37 | | #include "nodes/supportnodes.h" |
38 | | #include "optimizer/optimizer.h" |
39 | | #include "utils/array.h" |
40 | | #include "utils/builtins.h" |
41 | | #include "utils/float.h" |
42 | | #include "utils/guc.h" |
43 | | #include "utils/numeric.h" |
44 | | #include "utils/pg_lsn.h" |
45 | | #include "utils/sortsupport.h" |
46 | | |
47 | | /* ---------- |
48 | | * Uncomment the following to enable compilation of dump_numeric() |
49 | | * and dump_var() and to get a dump of any result produced by make_result(). |
50 | | * ---------- |
51 | | */ |
52 | | /* #define NUMERIC_DEBUG */ |
53 | | |
54 | | |
55 | | /* ---------- |
56 | | * Local data types |
57 | | * |
58 | | * Numeric values are represented in a base-NBASE floating point format. |
59 | | * Each "digit" ranges from 0 to NBASE-1. The type NumericDigit is signed |
60 | | * and wide enough to store a digit. We assume that NBASE*NBASE can fit in |
61 | | * an int. Although the purely calculational routines could handle any even |
62 | | * NBASE that's less than sqrt(INT_MAX), in practice we are only interested |
63 | | * in NBASE a power of ten, so that I/O conversions and decimal rounding |
64 | | * are easy. Also, it's actually more efficient if NBASE is rather less than |
65 | | * sqrt(INT_MAX), so that there is "headroom" for mul_var and div_var to |
66 | | * postpone processing carries. |
67 | | * |
68 | | * Values of NBASE other than 10000 are considered of historical interest only |
69 | | * and are no longer supported in any sense; no mechanism exists for the client |
70 | | * to discover the base, so every client supporting binary mode expects the |
71 | | * base-10000 format. If you plan to change this, also note the numeric |
72 | | * abbreviation code, which assumes NBASE=10000. |
73 | | * ---------- |
74 | | */ |
75 | | |
76 | | #if 0 |
77 | | #define NBASE 10 |
78 | | #define HALF_NBASE 5 |
79 | | #define DEC_DIGITS 1 /* decimal digits per NBASE digit */ |
80 | | #define MUL_GUARD_DIGITS 4 /* these are measured in NBASE digits */ |
81 | | #define DIV_GUARD_DIGITS 8 |
82 | | |
83 | | typedef signed char NumericDigit; |
84 | | #endif |
85 | | |
86 | | #if 0 |
87 | | #define NBASE 100 |
88 | | #define HALF_NBASE 50 |
89 | | #define DEC_DIGITS 2 /* decimal digits per NBASE digit */ |
90 | | #define MUL_GUARD_DIGITS 3 /* these are measured in NBASE digits */ |
91 | | #define DIV_GUARD_DIGITS 6 |
92 | | |
93 | | typedef signed char NumericDigit; |
94 | | #endif |
95 | | |
96 | | #if 1 |
97 | 0 | #define NBASE 10000 |
98 | 0 | #define HALF_NBASE 5000 |
99 | 0 | #define DEC_DIGITS 4 /* decimal digits per NBASE digit */ |
100 | 0 | #define MUL_GUARD_DIGITS 2 /* these are measured in NBASE digits */ |
101 | 0 | #define DIV_GUARD_DIGITS 4 |
102 | | |
103 | | typedef int16 NumericDigit; |
104 | | #endif |
105 | | |
106 | 0 | #define NBASE_SQR (NBASE * NBASE) |
107 | | |
108 | | /* |
109 | | * The Numeric type as stored on disk. |
110 | | * |
111 | | * If the high bits of the first word of a NumericChoice (n_header, or |
112 | | * n_short.n_header, or n_long.n_sign_dscale) are NUMERIC_SHORT, then the |
113 | | * numeric follows the NumericShort format; if they are NUMERIC_POS or |
114 | | * NUMERIC_NEG, it follows the NumericLong format. If they are NUMERIC_SPECIAL, |
115 | | * the value is a NaN or Infinity. We currently always store SPECIAL values |
116 | | * using just two bytes (i.e. only n_header), but previous releases used only |
117 | | * the NumericLong format, so we might find 4-byte NaNs (though not infinities) |
118 | | * on disk if a database has been migrated using pg_upgrade. In either case, |
119 | | * the low-order bits of a special value's header are reserved and currently |
120 | | * should always be set to zero. |
121 | | * |
122 | | * In the NumericShort format, the remaining 14 bits of the header word |
123 | | * (n_short.n_header) are allocated as follows: 1 for sign (positive or |
124 | | * negative), 6 for dynamic scale, and 7 for weight. In practice, most |
125 | | * commonly-encountered values can be represented this way. |
126 | | * |
127 | | * In the NumericLong format, the remaining 14 bits of the header word |
128 | | * (n_long.n_sign_dscale) represent the display scale; and the weight is |
129 | | * stored separately in n_weight. |
130 | | * |
131 | | * NOTE: by convention, values in the packed form have been stripped of |
132 | | * all leading and trailing zero digits (where a "digit" is of base NBASE). |
133 | | * In particular, if the value is zero, there will be no digits at all! |
134 | | * The weight is arbitrary in that case, but we normally set it to zero. |
135 | | */ |
136 | | |
137 | | struct NumericShort |
138 | | { |
139 | | uint16 n_header; /* Sign + display scale + weight */ |
140 | | NumericDigit n_data[FLEXIBLE_ARRAY_MEMBER]; /* Digits */ |
141 | | }; |
142 | | |
143 | | struct NumericLong |
144 | | { |
145 | | uint16 n_sign_dscale; /* Sign + display scale */ |
146 | | int16 n_weight; /* Weight of 1st digit */ |
147 | | NumericDigit n_data[FLEXIBLE_ARRAY_MEMBER]; /* Digits */ |
148 | | }; |
149 | | |
150 | | union NumericChoice |
151 | | { |
152 | | uint16 n_header; /* Header word */ |
153 | | struct NumericLong n_long; /* Long form (4-byte header) */ |
154 | | struct NumericShort n_short; /* Short form (2-byte header) */ |
155 | | }; |
156 | | |
157 | | struct NumericData |
158 | | { |
159 | | int32 vl_len_; /* varlena header (do not touch directly!) */ |
160 | | union NumericChoice choice; /* choice of format */ |
161 | | }; |
162 | | |
163 | | |
164 | | /* |
165 | | * Interpretation of high bits. |
166 | | */ |
167 | | |
168 | 0 | #define NUMERIC_SIGN_MASK 0xC000 |
169 | 0 | #define NUMERIC_POS 0x0000 |
170 | 0 | #define NUMERIC_NEG 0x4000 |
171 | 0 | #define NUMERIC_SHORT 0x8000 |
172 | 0 | #define NUMERIC_SPECIAL 0xC000 |
173 | | |
174 | 0 | #define NUMERIC_FLAGBITS(n) ((n)->choice.n_header & NUMERIC_SIGN_MASK) |
175 | 0 | #define NUMERIC_IS_SHORT(n) (NUMERIC_FLAGBITS(n) == NUMERIC_SHORT) |
176 | 0 | #define NUMERIC_IS_SPECIAL(n) (NUMERIC_FLAGBITS(n) == NUMERIC_SPECIAL) |
177 | | |
178 | 0 | #define NUMERIC_HDRSZ (VARHDRSZ + sizeof(uint16) + sizeof(int16)) |
179 | 0 | #define NUMERIC_HDRSZ_SHORT (VARHDRSZ + sizeof(uint16)) |
180 | | |
181 | | /* |
182 | | * If the flag bits are NUMERIC_SHORT or NUMERIC_SPECIAL, we want the short |
183 | | * header; otherwise, we want the long one. Instead of testing against each |
184 | | * value, we can just look at the high bit, for a slight efficiency gain. |
185 | | */ |
186 | 0 | #define NUMERIC_HEADER_IS_SHORT(n) (((n)->choice.n_header & 0x8000) != 0) |
187 | | #define NUMERIC_HEADER_SIZE(n) \ |
188 | 0 | (VARHDRSZ + sizeof(uint16) + \ |
189 | 0 | (NUMERIC_HEADER_IS_SHORT(n) ? 0 : sizeof(int16))) |
190 | | |
191 | | /* |
192 | | * Definitions for special values (NaN, positive infinity, negative infinity). |
193 | | * |
194 | | * The two bits after the NUMERIC_SPECIAL bits are 00 for NaN, 01 for positive |
195 | | * infinity, 11 for negative infinity. (This makes the sign bit match where |
196 | | * it is in a short-format value, though we make no use of that at present.) |
197 | | * We could mask off the remaining bits before testing the active bits, but |
198 | | * currently those bits must be zeroes, so masking would just add cycles. |
199 | | */ |
200 | 0 | #define NUMERIC_EXT_SIGN_MASK 0xF000 /* high bits plus NaN/Inf flag bits */ |
201 | 0 | #define NUMERIC_NAN 0xC000 |
202 | 0 | #define NUMERIC_PINF 0xD000 |
203 | 0 | #define NUMERIC_NINF 0xF000 |
204 | 0 | #define NUMERIC_INF_SIGN_MASK 0x2000 |
205 | | |
206 | 0 | #define NUMERIC_EXT_FLAGBITS(n) ((n)->choice.n_header & NUMERIC_EXT_SIGN_MASK) |
207 | 0 | #define NUMERIC_IS_NAN(n) ((n)->choice.n_header == NUMERIC_NAN) |
208 | 0 | #define NUMERIC_IS_PINF(n) ((n)->choice.n_header == NUMERIC_PINF) |
209 | 0 | #define NUMERIC_IS_NINF(n) ((n)->choice.n_header == NUMERIC_NINF) |
210 | | #define NUMERIC_IS_INF(n) \ |
211 | 0 | (((n)->choice.n_header & ~NUMERIC_INF_SIGN_MASK) == NUMERIC_PINF) |
212 | | |
213 | | /* |
214 | | * Short format definitions. |
215 | | */ |
216 | | |
217 | 0 | #define NUMERIC_SHORT_SIGN_MASK 0x2000 |
218 | 0 | #define NUMERIC_SHORT_DSCALE_MASK 0x1F80 |
219 | 0 | #define NUMERIC_SHORT_DSCALE_SHIFT 7 |
220 | | #define NUMERIC_SHORT_DSCALE_MAX \ |
221 | 0 | (NUMERIC_SHORT_DSCALE_MASK >> NUMERIC_SHORT_DSCALE_SHIFT) |
222 | 0 | #define NUMERIC_SHORT_WEIGHT_SIGN_MASK 0x0040 |
223 | 0 | #define NUMERIC_SHORT_WEIGHT_MASK 0x003F |
224 | 0 | #define NUMERIC_SHORT_WEIGHT_MAX NUMERIC_SHORT_WEIGHT_MASK |
225 | 0 | #define NUMERIC_SHORT_WEIGHT_MIN (-(NUMERIC_SHORT_WEIGHT_MASK+1)) |
226 | | |
227 | | /* |
228 | | * Extract sign, display scale, weight. These macros extract field values |
229 | | * suitable for the NumericVar format from the Numeric (on-disk) format. |
230 | | * |
231 | | * Note that we don't trouble to ensure that dscale and weight read as zero |
232 | | * for an infinity; however, that doesn't matter since we never convert |
233 | | * "special" numerics to NumericVar form. Only the constants defined below |
234 | | * (const_nan, etc) ever represent a non-finite value as a NumericVar. |
235 | | */ |
236 | | |
237 | 0 | #define NUMERIC_DSCALE_MASK 0x3FFF |
238 | 0 | #define NUMERIC_DSCALE_MAX NUMERIC_DSCALE_MASK |
239 | | |
240 | | #define NUMERIC_SIGN(n) \ |
241 | 0 | (NUMERIC_IS_SHORT(n) ? \ |
242 | 0 | (((n)->choice.n_short.n_header & NUMERIC_SHORT_SIGN_MASK) ? \ |
243 | 0 | NUMERIC_NEG : NUMERIC_POS) : \ |
244 | 0 | (NUMERIC_IS_SPECIAL(n) ? \ |
245 | 0 | NUMERIC_EXT_FLAGBITS(n) : NUMERIC_FLAGBITS(n))) |
246 | 0 | #define NUMERIC_DSCALE(n) (NUMERIC_HEADER_IS_SHORT((n)) ? \ |
247 | 0 | ((n)->choice.n_short.n_header & NUMERIC_SHORT_DSCALE_MASK) \ |
248 | 0 | >> NUMERIC_SHORT_DSCALE_SHIFT \ |
249 | 0 | : ((n)->choice.n_long.n_sign_dscale & NUMERIC_DSCALE_MASK)) |
250 | 0 | #define NUMERIC_WEIGHT(n) (NUMERIC_HEADER_IS_SHORT((n)) ? \ |
251 | 0 | (((n)->choice.n_short.n_header & NUMERIC_SHORT_WEIGHT_SIGN_MASK ? \ |
252 | 0 | ~NUMERIC_SHORT_WEIGHT_MASK : 0) \ |
253 | 0 | | ((n)->choice.n_short.n_header & NUMERIC_SHORT_WEIGHT_MASK)) \ |
254 | 0 | : ((n)->choice.n_long.n_weight)) |
255 | | |
256 | | /* |
257 | | * Maximum weight of a stored Numeric value (based on the use of int16 for the |
258 | | * weight in NumericLong). Note that intermediate values held in NumericVar |
259 | | * and NumericSumAccum variables may have much larger weights. |
260 | | */ |
261 | 0 | #define NUMERIC_WEIGHT_MAX PG_INT16_MAX |
262 | | |
263 | | /* ---------- |
264 | | * NumericVar is the format we use for arithmetic. The digit-array part |
265 | | * is the same as the NumericData storage format, but the header is more |
266 | | * complex. |
267 | | * |
268 | | * The value represented by a NumericVar is determined by the sign, weight, |
269 | | * ndigits, and digits[] array. If it is a "special" value (NaN or Inf) |
270 | | * then only the sign field matters; ndigits should be zero, and the weight |
271 | | * and dscale fields are ignored. |
272 | | * |
273 | | * Note: the first digit of a NumericVar's value is assumed to be multiplied |
274 | | * by NBASE ** weight. Another way to say it is that there are weight+1 |
275 | | * digits before the decimal point. It is possible to have weight < 0. |
276 | | * |
277 | | * buf points at the physical start of the palloc'd digit buffer for the |
278 | | * NumericVar. digits points at the first digit in actual use (the one |
279 | | * with the specified weight). We normally leave an unused digit or two |
280 | | * (preset to zeroes) between buf and digits, so that there is room to store |
281 | | * a carry out of the top digit without reallocating space. We just need to |
282 | | * decrement digits (and increment weight) to make room for the carry digit. |
283 | | * (There is no such extra space in a numeric value stored in the database, |
284 | | * only in a NumericVar in memory.) |
285 | | * |
286 | | * If buf is NULL then the digit buffer isn't actually palloc'd and should |
287 | | * not be freed --- see the constants below for an example. |
288 | | * |
289 | | * dscale, or display scale, is the nominal precision expressed as number |
290 | | * of digits after the decimal point (it must always be >= 0 at present). |
291 | | * dscale may be more than the number of physically stored fractional digits, |
292 | | * implying that we have suppressed storage of significant trailing zeroes. |
293 | | * It should never be less than the number of stored digits, since that would |
294 | | * imply hiding digits that are present. NOTE that dscale is always expressed |
295 | | * in *decimal* digits, and so it may correspond to a fractional number of |
296 | | * base-NBASE digits --- divide by DEC_DIGITS to convert to NBASE digits. |
297 | | * |
298 | | * rscale, or result scale, is the target precision for a computation. |
299 | | * Like dscale it is expressed as number of *decimal* digits after the decimal |
300 | | * point, and is always >= 0 at present. |
301 | | * Note that rscale is not stored in variables --- it's figured on-the-fly |
302 | | * from the dscales of the inputs. |
303 | | * |
304 | | * While we consistently use "weight" to refer to the base-NBASE weight of |
305 | | * a numeric value, it is convenient in some scale-related calculations to |
306 | | * make use of the base-10 weight (ie, the approximate log10 of the value). |
307 | | * To avoid confusion, such a decimal-units weight is called a "dweight". |
308 | | * |
309 | | * NB: All the variable-level functions are written in a style that makes it |
310 | | * possible to give one and the same variable as argument and destination. |
311 | | * This is feasible because the digit buffer is separate from the variable. |
312 | | * ---------- |
313 | | */ |
314 | | typedef struct NumericVar |
315 | | { |
316 | | int ndigits; /* # of digits in digits[] - can be 0! */ |
317 | | int weight; /* weight of first digit */ |
318 | | int sign; /* NUMERIC_POS, _NEG, _NAN, _PINF, or _NINF */ |
319 | | int dscale; /* display scale */ |
320 | | NumericDigit *buf; /* start of palloc'd space for digits[] */ |
321 | | NumericDigit *digits; /* base-NBASE digits */ |
322 | | } NumericVar; |
323 | | |
324 | | |
325 | | /* ---------- |
326 | | * Data for generate_series |
327 | | * ---------- |
328 | | */ |
329 | | typedef struct |
330 | | { |
331 | | NumericVar current; |
332 | | NumericVar stop; |
333 | | NumericVar step; |
334 | | } generate_series_numeric_fctx; |
335 | | |
336 | | |
337 | | /* ---------- |
338 | | * Sort support. |
339 | | * ---------- |
340 | | */ |
341 | | typedef struct |
342 | | { |
343 | | void *buf; /* buffer for short varlenas */ |
344 | | int64 input_count; /* number of non-null values seen */ |
345 | | bool estimating; /* true if estimating cardinality */ |
346 | | |
347 | | hyperLogLogState abbr_card; /* cardinality estimator */ |
348 | | } NumericSortSupport; |
349 | | |
350 | | |
351 | | /* ---------- |
352 | | * Fast sum accumulator. |
353 | | * |
354 | | * NumericSumAccum is used to implement SUM(), and other standard aggregates |
355 | | * that track the sum of input values. It uses 32-bit integers to store the |
356 | | * digits, instead of the normal 16-bit integers (with NBASE=10000). This |
357 | | * way, we can safely accumulate up to NBASE - 1 values without propagating |
358 | | * carry, before risking overflow of any of the digits. 'num_uncarried' |
359 | | * tracks how many values have been accumulated without propagating carry. |
360 | | * |
361 | | * Positive and negative values are accumulated separately, in 'pos_digits' |
362 | | * and 'neg_digits'. This is simpler and faster than deciding whether to add |
363 | | * or subtract from the current value, for each new value (see sub_var() for |
364 | | * the logic we avoid by doing this). Both buffers are of same size, and |
365 | | * have the same weight and scale. In accum_sum_final(), the positive and |
366 | | * negative sums are added together to produce the final result. |
367 | | * |
368 | | * When a new value has a larger ndigits or weight than the accumulator |
369 | | * currently does, the accumulator is enlarged to accommodate the new value. |
370 | | * We normally have one zero digit reserved for carry propagation, and that |
371 | | * is indicated by the 'have_carry_space' flag. When accum_sum_carry() uses |
372 | | * up the reserved digit, it clears the 'have_carry_space' flag. The next |
373 | | * call to accum_sum_add() will enlarge the buffer, to make room for the |
374 | | * extra digit, and set the flag again. |
375 | | * |
376 | | * To initialize a new accumulator, simply reset all fields to zeros. |
377 | | * |
378 | | * The accumulator does not handle NaNs. |
379 | | * ---------- |
380 | | */ |
381 | | typedef struct NumericSumAccum |
382 | | { |
383 | | int ndigits; |
384 | | int weight; |
385 | | int dscale; |
386 | | int num_uncarried; |
387 | | bool have_carry_space; |
388 | | int32 *pos_digits; |
389 | | int32 *neg_digits; |
390 | | } NumericSumAccum; |
391 | | |
392 | | |
393 | | /* |
394 | | * We define our own macros for packing and unpacking abbreviated-key |
395 | | * representations, just to have a notational indication that that's |
396 | | * what we're doing. Now that sizeof(Datum) is always 8, we can rely |
397 | | * on fitting an int64 into Datum. |
398 | | * |
399 | | * The range of abbreviations for finite values is from +PG_INT64_MAX |
400 | | * to -PG_INT64_MAX. NaN has the abbreviation PG_INT64_MIN, and we |
401 | | * define the sort ordering to make that work out properly (see further |
402 | | * comments below). PINF and NINF share the abbreviations of the largest |
403 | | * and smallest finite abbreviation classes. |
404 | | */ |
405 | 0 | #define NumericAbbrevGetDatum(X) Int64GetDatum(X) |
406 | 0 | #define DatumGetNumericAbbrev(X) DatumGetInt64(X) |
407 | 0 | #define NUMERIC_ABBREV_NAN NumericAbbrevGetDatum(PG_INT64_MIN) |
408 | 0 | #define NUMERIC_ABBREV_PINF NumericAbbrevGetDatum(-PG_INT64_MAX) |
409 | 0 | #define NUMERIC_ABBREV_NINF NumericAbbrevGetDatum(PG_INT64_MAX) |
410 | | |
411 | | |
412 | | /* ---------- |
413 | | * Some preinitialized constants |
414 | | * ---------- |
415 | | */ |
416 | | static const NumericDigit const_zero_data[1] = {0}; |
417 | | static const NumericVar const_zero = |
418 | | {0, 0, NUMERIC_POS, 0, NULL, unconstify_constexpr(NumericDigit *, const_zero_data)}; |
419 | | |
420 | | static const NumericDigit const_one_data[1] = {1}; |
421 | | static const NumericVar const_one = |
422 | | {1, 0, NUMERIC_POS, 0, NULL, unconstify_constexpr(NumericDigit *, const_one_data)}; |
423 | | |
424 | | static const NumericVar const_minus_one = |
425 | | {1, 0, NUMERIC_NEG, 0, NULL, unconstify_constexpr(NumericDigit *, const_one_data)}; |
426 | | |
427 | | static const NumericDigit const_two_data[1] = {2}; |
428 | | static const NumericVar const_two = |
429 | | {1, 0, NUMERIC_POS, 0, NULL, unconstify_constexpr(NumericDigit *, const_two_data)}; |
430 | | |
431 | | #if DEC_DIGITS == 4 |
432 | | static const NumericDigit const_zero_point_nine_data[1] = {9000}; |
433 | | #elif DEC_DIGITS == 2 |
434 | | static const NumericDigit const_zero_point_nine_data[1] = {90}; |
435 | | #elif DEC_DIGITS == 1 |
436 | | static const NumericDigit const_zero_point_nine_data[1] = {9}; |
437 | | #endif |
438 | | static const NumericVar const_zero_point_nine = |
439 | | {1, -1, NUMERIC_POS, 1, NULL, unconstify_constexpr(NumericDigit *, const_zero_point_nine_data)}; |
440 | | |
441 | | #if DEC_DIGITS == 4 |
442 | | static const NumericDigit const_one_point_one_data[2] = {1, 1000}; |
443 | | #elif DEC_DIGITS == 2 |
444 | | static const NumericDigit const_one_point_one_data[2] = {1, 10}; |
445 | | #elif DEC_DIGITS == 1 |
446 | | static const NumericDigit const_one_point_one_data[2] = {1, 1}; |
447 | | #endif |
448 | | static const NumericVar const_one_point_one = |
449 | | {2, 0, NUMERIC_POS, 1, NULL, unconstify_constexpr(NumericDigit *, const_one_point_one_data)}; |
450 | | |
451 | | static const NumericVar const_nan = |
452 | | {0, 0, NUMERIC_NAN, 0, NULL, NULL}; |
453 | | |
454 | | static const NumericVar const_pinf = |
455 | | {0, 0, NUMERIC_PINF, 0, NULL, NULL}; |
456 | | |
457 | | static const NumericVar const_ninf = |
458 | | {0, 0, NUMERIC_NINF, 0, NULL, NULL}; |
459 | | |
460 | | #if DEC_DIGITS == 4 |
461 | | static const int round_powers[4] = {0, 1000, 100, 10}; |
462 | | #endif |
463 | | |
464 | | |
465 | | /* ---------- |
466 | | * Local functions |
467 | | * ---------- |
468 | | */ |
469 | | |
470 | | #ifdef NUMERIC_DEBUG |
471 | | static void dump_numeric(const char *str, Numeric num); |
472 | | static void dump_var(const char *str, NumericVar *var); |
473 | | #else |
474 | | #define dump_numeric(s,n) |
475 | | #define dump_var(s,v) |
476 | | #endif |
477 | | |
478 | | #define digitbuf_alloc(ndigits) \ |
479 | 0 | (palloc_array(NumericDigit, (ndigits))) |
480 | | #define digitbuf_free(buf) \ |
481 | 0 | do { \ |
482 | 0 | if ((buf) != NULL) \ |
483 | 0 | pfree(buf); \ |
484 | 0 | } while (0) |
485 | | |
486 | 0 | #define init_var(v) memset(v, 0, sizeof(NumericVar)) |
487 | | |
488 | 0 | #define NUMERIC_DIGITS(num) (NUMERIC_HEADER_IS_SHORT(num) ? \ |
489 | 0 | (num)->choice.n_short.n_data : (num)->choice.n_long.n_data) |
490 | | #define NUMERIC_NDIGITS(num) \ |
491 | 0 | ((VARSIZE(num) - NUMERIC_HEADER_SIZE(num)) / sizeof(NumericDigit)) |
492 | | #define NUMERIC_CAN_BE_SHORT(scale,weight) \ |
493 | 0 | ((scale) <= NUMERIC_SHORT_DSCALE_MAX && \ |
494 | 0 | (weight) <= NUMERIC_SHORT_WEIGHT_MAX && \ |
495 | 0 | (weight) >= NUMERIC_SHORT_WEIGHT_MIN) |
496 | | |
497 | | static void alloc_var(NumericVar *var, int ndigits); |
498 | | static void free_var(NumericVar *var); |
499 | | static void zero_var(NumericVar *var); |
500 | | |
501 | | static bool set_var_from_str(const char *str, const char *cp, |
502 | | NumericVar *dest, const char **endptr, |
503 | | Node *escontext); |
504 | | static bool set_var_from_non_decimal_integer_str(const char *str, |
505 | | const char *cp, int sign, |
506 | | int base, NumericVar *dest, |
507 | | const char **endptr, |
508 | | Node *escontext); |
509 | | static void set_var_from_num(Numeric num, NumericVar *dest); |
510 | | static void init_var_from_num(Numeric num, NumericVar *dest); |
511 | | static void set_var_from_var(const NumericVar *value, NumericVar *dest); |
512 | | static char *get_str_from_var(const NumericVar *var); |
513 | | static char *get_str_from_var_sci(const NumericVar *var, int rscale); |
514 | | |
515 | | static void numericvar_serialize(StringInfo buf, const NumericVar *var); |
516 | | static void numericvar_deserialize(StringInfo buf, NumericVar *var); |
517 | | |
518 | | static Numeric duplicate_numeric(Numeric num); |
519 | | static Numeric make_result(const NumericVar *var); |
520 | | static Numeric make_result_safe(const NumericVar *var, Node *escontext); |
521 | | |
522 | | static bool apply_typmod(NumericVar *var, int32 typmod, Node *escontext); |
523 | | static bool apply_typmod_special(Numeric num, int32 typmod, Node *escontext); |
524 | | |
525 | | static bool numericvar_to_int32(const NumericVar *var, int32 *result); |
526 | | static bool numericvar_to_int64(const NumericVar *var, int64 *result); |
527 | | static void int64_to_numericvar(int64 val, NumericVar *var); |
528 | | static bool numericvar_to_uint64(const NumericVar *var, uint64 *result); |
529 | | static void int128_to_numericvar(INT128 val, NumericVar *var); |
530 | | static double numericvar_to_double_no_overflow(const NumericVar *var); |
531 | | |
532 | | static Datum numeric_abbrev_convert(Datum original_datum, SortSupport ssup); |
533 | | static bool numeric_abbrev_abort(int memtupcount, SortSupport ssup); |
534 | | static int numeric_fast_cmp(Datum x, Datum y, SortSupport ssup); |
535 | | static int numeric_cmp_abbrev(Datum x, Datum y, SortSupport ssup); |
536 | | |
537 | | static Datum numeric_abbrev_convert_var(const NumericVar *var, |
538 | | NumericSortSupport *nss); |
539 | | |
540 | | static int cmp_numerics(Numeric num1, Numeric num2); |
541 | | static int cmp_var(const NumericVar *var1, const NumericVar *var2); |
542 | | static int cmp_var_common(const NumericDigit *var1digits, int var1ndigits, |
543 | | int var1weight, int var1sign, |
544 | | const NumericDigit *var2digits, int var2ndigits, |
545 | | int var2weight, int var2sign); |
546 | | static void add_var(const NumericVar *var1, const NumericVar *var2, |
547 | | NumericVar *result); |
548 | | static void sub_var(const NumericVar *var1, const NumericVar *var2, |
549 | | NumericVar *result); |
550 | | static void mul_var(const NumericVar *var1, const NumericVar *var2, |
551 | | NumericVar *result, |
552 | | int rscale); |
553 | | static void mul_var_short(const NumericVar *var1, const NumericVar *var2, |
554 | | NumericVar *result); |
555 | | static void div_var(const NumericVar *var1, const NumericVar *var2, |
556 | | NumericVar *result, int rscale, bool round, bool exact); |
557 | | static void div_var_int(const NumericVar *var, int ival, int ival_weight, |
558 | | NumericVar *result, int rscale, bool round); |
559 | | #ifdef HAVE_INT128 |
560 | | static void div_var_int64(const NumericVar *var, int64 ival, int ival_weight, |
561 | | NumericVar *result, int rscale, bool round); |
562 | | #endif |
563 | | static int select_div_scale(const NumericVar *var1, const NumericVar *var2); |
564 | | static void mod_var(const NumericVar *var1, const NumericVar *var2, |
565 | | NumericVar *result); |
566 | | static void div_mod_var(const NumericVar *var1, const NumericVar *var2, |
567 | | NumericVar *quot, NumericVar *rem); |
568 | | static void ceil_var(const NumericVar *var, NumericVar *result); |
569 | | static void floor_var(const NumericVar *var, NumericVar *result); |
570 | | |
571 | | static void gcd_var(const NumericVar *var1, const NumericVar *var2, |
572 | | NumericVar *result); |
573 | | static void sqrt_var(const NumericVar *arg, NumericVar *result, int rscale); |
574 | | static void exp_var(const NumericVar *arg, NumericVar *result, int rscale); |
575 | | static int estimate_ln_dweight(const NumericVar *var); |
576 | | static void ln_var(const NumericVar *arg, NumericVar *result, int rscale); |
577 | | static void log_var(const NumericVar *base, const NumericVar *num, |
578 | | NumericVar *result); |
579 | | static void power_var(const NumericVar *base, const NumericVar *exp, |
580 | | NumericVar *result); |
581 | | static void power_var_int(const NumericVar *base, int exp, int exp_dscale, |
582 | | NumericVar *result); |
583 | | static void power_ten_int(int exp, NumericVar *result); |
584 | | static void random_var(pg_prng_state *state, const NumericVar *rmin, |
585 | | const NumericVar *rmax, NumericVar *result); |
586 | | |
587 | | static int cmp_abs(const NumericVar *var1, const NumericVar *var2); |
588 | | static int cmp_abs_common(const NumericDigit *var1digits, int var1ndigits, |
589 | | int var1weight, |
590 | | const NumericDigit *var2digits, int var2ndigits, |
591 | | int var2weight); |
592 | | static void add_abs(const NumericVar *var1, const NumericVar *var2, |
593 | | NumericVar *result); |
594 | | static void sub_abs(const NumericVar *var1, const NumericVar *var2, |
595 | | NumericVar *result); |
596 | | static void round_var(NumericVar *var, int rscale); |
597 | | static void trunc_var(NumericVar *var, int rscale); |
598 | | static void strip_var(NumericVar *var); |
599 | | static void compute_bucket(Numeric operand, Numeric bound1, Numeric bound2, |
600 | | const NumericVar *count_var, |
601 | | NumericVar *result_var); |
602 | | |
603 | | static void accum_sum_add(NumericSumAccum *accum, const NumericVar *val); |
604 | | static void accum_sum_rescale(NumericSumAccum *accum, const NumericVar *val); |
605 | | static void accum_sum_carry(NumericSumAccum *accum); |
606 | | static void accum_sum_reset(NumericSumAccum *accum); |
607 | | static void accum_sum_final(NumericSumAccum *accum, NumericVar *result); |
608 | | static void accum_sum_copy(NumericSumAccum *dst, NumericSumAccum *src); |
609 | | static void accum_sum_combine(NumericSumAccum *accum, NumericSumAccum *accum2); |
610 | | |
611 | | |
612 | | /* ---------------------------------------------------------------------- |
613 | | * |
614 | | * Input-, output- and rounding-functions |
615 | | * |
616 | | * ---------------------------------------------------------------------- |
617 | | */ |
618 | | |
619 | | |
620 | | /* |
621 | | * numeric_in() - |
622 | | * |
623 | | * Input function for numeric data type |
624 | | */ |
625 | | Datum |
626 | | numeric_in(PG_FUNCTION_ARGS) |
627 | 0 | { |
628 | 0 | char *str = PG_GETARG_CSTRING(0); |
629 | | #ifdef NOT_USED |
630 | | Oid typelem = PG_GETARG_OID(1); |
631 | | #endif |
632 | 0 | int32 typmod = PG_GETARG_INT32(2); |
633 | 0 | Node *escontext = fcinfo->context; |
634 | 0 | Numeric res; |
635 | 0 | const char *cp; |
636 | 0 | const char *numstart; |
637 | 0 | int sign; |
638 | | |
639 | | /* Skip leading spaces */ |
640 | 0 | cp = str; |
641 | 0 | while (*cp) |
642 | 0 | { |
643 | 0 | if (!isspace((unsigned char) *cp)) |
644 | 0 | break; |
645 | 0 | cp++; |
646 | 0 | } |
647 | | |
648 | | /* |
649 | | * Process the number's sign. This duplicates logic in set_var_from_str(), |
650 | | * but it's worth doing here, since it simplifies the handling of |
651 | | * infinities and non-decimal integers. |
652 | | */ |
653 | 0 | numstart = cp; |
654 | 0 | sign = NUMERIC_POS; |
655 | |
|
656 | 0 | if (*cp == '+') |
657 | 0 | cp++; |
658 | 0 | else if (*cp == '-') |
659 | 0 | { |
660 | 0 | sign = NUMERIC_NEG; |
661 | 0 | cp++; |
662 | 0 | } |
663 | | |
664 | | /* |
665 | | * Check for NaN and infinities. We recognize the same strings allowed by |
666 | | * float8in(). |
667 | | * |
668 | | * Since all other legal inputs have a digit or a decimal point after the |
669 | | * sign, we need only check for NaN/infinity if that's not the case. |
670 | | */ |
671 | 0 | if (!isdigit((unsigned char) *cp) && *cp != '.') |
672 | 0 | { |
673 | | /* |
674 | | * The number must be NaN or infinity; anything else can only be a |
675 | | * syntax error. Note that NaN mustn't have a sign. |
676 | | */ |
677 | 0 | if (pg_strncasecmp(numstart, "NaN", 3) == 0) |
678 | 0 | { |
679 | 0 | res = make_result(&const_nan); |
680 | 0 | cp = numstart + 3; |
681 | 0 | } |
682 | 0 | else if (pg_strncasecmp(cp, "Infinity", 8) == 0) |
683 | 0 | { |
684 | 0 | res = make_result(sign == NUMERIC_POS ? &const_pinf : &const_ninf); |
685 | 0 | cp += 8; |
686 | 0 | } |
687 | 0 | else if (pg_strncasecmp(cp, "inf", 3) == 0) |
688 | 0 | { |
689 | 0 | res = make_result(sign == NUMERIC_POS ? &const_pinf : &const_ninf); |
690 | 0 | cp += 3; |
691 | 0 | } |
692 | 0 | else |
693 | 0 | goto invalid_syntax; |
694 | | |
695 | | /* |
696 | | * Check for trailing junk; there should be nothing left but spaces. |
697 | | * |
698 | | * We intentionally do this check before applying the typmod because |
699 | | * we would like to throw any trailing-junk syntax error before any |
700 | | * semantic error resulting from apply_typmod_special(). |
701 | | */ |
702 | 0 | while (*cp) |
703 | 0 | { |
704 | 0 | if (!isspace((unsigned char) *cp)) |
705 | 0 | goto invalid_syntax; |
706 | 0 | cp++; |
707 | 0 | } |
708 | | |
709 | 0 | if (!apply_typmod_special(res, typmod, escontext)) |
710 | 0 | PG_RETURN_NULL(); |
711 | 0 | } |
712 | 0 | else |
713 | 0 | { |
714 | | /* |
715 | | * We have a normal numeric value, which may be a non-decimal integer |
716 | | * or a regular decimal number. |
717 | | */ |
718 | 0 | NumericVar value; |
719 | 0 | int base; |
720 | |
|
721 | 0 | init_var(&value); |
722 | | |
723 | | /* |
724 | | * Determine the number's base by looking for a non-decimal prefix |
725 | | * indicator ("0x", "0o", or "0b"). |
726 | | */ |
727 | 0 | if (cp[0] == '0') |
728 | 0 | { |
729 | 0 | switch (cp[1]) |
730 | 0 | { |
731 | 0 | case 'x': |
732 | 0 | case 'X': |
733 | 0 | base = 16; |
734 | 0 | break; |
735 | 0 | case 'o': |
736 | 0 | case 'O': |
737 | 0 | base = 8; |
738 | 0 | break; |
739 | 0 | case 'b': |
740 | 0 | case 'B': |
741 | 0 | base = 2; |
742 | 0 | break; |
743 | 0 | default: |
744 | 0 | base = 10; |
745 | 0 | } |
746 | 0 | } |
747 | 0 | else |
748 | 0 | base = 10; |
749 | | |
750 | | /* Parse the rest of the number and apply the sign */ |
751 | 0 | if (base == 10) |
752 | 0 | { |
753 | 0 | if (!set_var_from_str(str, cp, &value, &cp, escontext)) |
754 | 0 | PG_RETURN_NULL(); |
755 | 0 | value.sign = sign; |
756 | 0 | } |
757 | 0 | else |
758 | 0 | { |
759 | 0 | if (!set_var_from_non_decimal_integer_str(str, cp + 2, sign, base, |
760 | 0 | &value, &cp, escontext)) |
761 | 0 | PG_RETURN_NULL(); |
762 | 0 | } |
763 | | |
764 | | /* |
765 | | * Should be nothing left but spaces. As above, throw any typmod error |
766 | | * after finishing syntax check. |
767 | | */ |
768 | 0 | while (*cp) |
769 | 0 | { |
770 | 0 | if (!isspace((unsigned char) *cp)) |
771 | 0 | goto invalid_syntax; |
772 | 0 | cp++; |
773 | 0 | } |
774 | | |
775 | 0 | if (!apply_typmod(&value, typmod, escontext)) |
776 | 0 | PG_RETURN_NULL(); |
777 | | |
778 | 0 | res = make_result_safe(&value, escontext); |
779 | |
|
780 | 0 | free_var(&value); |
781 | 0 | } |
782 | | |
783 | 0 | PG_RETURN_NUMERIC(res); |
784 | | |
785 | 0 | invalid_syntax: |
786 | 0 | ereturn(escontext, (Datum) 0, |
787 | 0 | (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), |
788 | 0 | errmsg("invalid input syntax for type %s: \"%s\"", |
789 | 0 | "numeric", str))); |
790 | 0 | } |
791 | | |
792 | | |
793 | | /* |
794 | | * numeric_out() - |
795 | | * |
796 | | * Output function for numeric data type |
797 | | */ |
798 | | Datum |
799 | | numeric_out(PG_FUNCTION_ARGS) |
800 | 0 | { |
801 | 0 | Numeric num = PG_GETARG_NUMERIC(0); |
802 | 0 | NumericVar x; |
803 | 0 | char *str; |
804 | | |
805 | | /* |
806 | | * Handle NaN and infinities |
807 | | */ |
808 | 0 | if (NUMERIC_IS_SPECIAL(num)) |
809 | 0 | { |
810 | 0 | if (NUMERIC_IS_PINF(num)) |
811 | 0 | PG_RETURN_CSTRING(pstrdup("Infinity")); |
812 | 0 | else if (NUMERIC_IS_NINF(num)) |
813 | 0 | PG_RETURN_CSTRING(pstrdup("-Infinity")); |
814 | 0 | else |
815 | 0 | PG_RETURN_CSTRING(pstrdup("NaN")); |
816 | 0 | } |
817 | | |
818 | | /* |
819 | | * Get the number in the variable format. |
820 | | */ |
821 | 0 | init_var_from_num(num, &x); |
822 | |
|
823 | 0 | str = get_str_from_var(&x); |
824 | |
|
825 | 0 | PG_RETURN_CSTRING(str); |
826 | 0 | } |
827 | | |
828 | | /* |
829 | | * numeric_is_nan() - |
830 | | * |
831 | | * Is Numeric value a NaN? |
832 | | */ |
833 | | bool |
834 | | numeric_is_nan(Numeric num) |
835 | 0 | { |
836 | 0 | return NUMERIC_IS_NAN(num); |
837 | 0 | } |
838 | | |
839 | | /* |
840 | | * numeric_is_inf() - |
841 | | * |
842 | | * Is Numeric value an infinity? |
843 | | */ |
844 | | bool |
845 | | numeric_is_inf(Numeric num) |
846 | 0 | { |
847 | 0 | return NUMERIC_IS_INF(num); |
848 | 0 | } |
849 | | |
850 | | /* |
851 | | * numeric_is_integral() - |
852 | | * |
853 | | * Is Numeric value integral? |
854 | | */ |
855 | | static bool |
856 | | numeric_is_integral(Numeric num) |
857 | 0 | { |
858 | 0 | NumericVar arg; |
859 | | |
860 | | /* Reject NaN, but infinities are considered integral */ |
861 | 0 | if (NUMERIC_IS_SPECIAL(num)) |
862 | 0 | { |
863 | 0 | if (NUMERIC_IS_NAN(num)) |
864 | 0 | return false; |
865 | 0 | return true; |
866 | 0 | } |
867 | | |
868 | | /* Integral if there are no digits to the right of the decimal point */ |
869 | 0 | init_var_from_num(num, &arg); |
870 | |
|
871 | 0 | return (arg.ndigits == 0 || arg.ndigits <= arg.weight + 1); |
872 | 0 | } |
873 | | |
874 | | /* |
875 | | * make_numeric_typmod() - |
876 | | * |
877 | | * Pack numeric precision and scale values into a typmod. The upper 16 bits |
878 | | * are used for the precision (though actually not all these bits are needed, |
879 | | * since the maximum allowed precision is 1000). The lower 16 bits are for |
880 | | * the scale, but since the scale is constrained to the range [-1000, 1000], |
881 | | * we use just the lower 11 of those 16 bits, and leave the remaining 5 bits |
882 | | * unset, for possible future use. |
883 | | * |
884 | | * For purely historical reasons VARHDRSZ is then added to the result, thus |
885 | | * the unused space in the upper 16 bits is not all as freely available as it |
886 | | * might seem. (We can't let the result overflow to a negative int32, as |
887 | | * other parts of the system would interpret that as not-a-valid-typmod.) |
888 | | */ |
889 | | static inline int32 |
890 | | make_numeric_typmod(int precision, int scale) |
891 | 0 | { |
892 | 0 | return ((precision << 16) | (scale & 0x7ff)) + VARHDRSZ; |
893 | 0 | } |
894 | | |
895 | | /* |
896 | | * Because of the offset, valid numeric typmods are at least VARHDRSZ |
897 | | */ |
898 | | static inline bool |
899 | | is_valid_numeric_typmod(int32 typmod) |
900 | 0 | { |
901 | 0 | return typmod >= (int32) VARHDRSZ; |
902 | 0 | } |
903 | | |
904 | | /* |
905 | | * numeric_typmod_precision() - |
906 | | * |
907 | | * Extract the precision from a numeric typmod --- see make_numeric_typmod(). |
908 | | */ |
909 | | static inline int |
910 | | numeric_typmod_precision(int32 typmod) |
911 | 0 | { |
912 | 0 | return ((typmod - VARHDRSZ) >> 16) & 0xffff; |
913 | 0 | } |
914 | | |
915 | | /* |
916 | | * numeric_typmod_scale() - |
917 | | * |
918 | | * Extract the scale from a numeric typmod --- see make_numeric_typmod(). |
919 | | * |
920 | | * Note that the scale may be negative, so we must do sign extension when |
921 | | * unpacking it. We do this using the bit hack (x^1024)-1024, which sign |
922 | | * extends an 11-bit two's complement number x. |
923 | | */ |
924 | | static inline int |
925 | | numeric_typmod_scale(int32 typmod) |
926 | 0 | { |
927 | 0 | return (((typmod - VARHDRSZ) & 0x7ff) ^ 1024) - 1024; |
928 | 0 | } |
929 | | |
930 | | /* |
931 | | * numeric_maximum_size() - |
932 | | * |
933 | | * Maximum size of a numeric with given typmod, or -1 if unlimited/unknown. |
934 | | */ |
935 | | int32 |
936 | | numeric_maximum_size(int32 typmod) |
937 | 0 | { |
938 | 0 | int precision; |
939 | 0 | int numeric_digits; |
940 | |
|
941 | 0 | if (!is_valid_numeric_typmod(typmod)) |
942 | 0 | return -1; |
943 | | |
944 | | /* precision (ie, max # of digits) is in upper bits of typmod */ |
945 | 0 | precision = numeric_typmod_precision(typmod); |
946 | | |
947 | | /* |
948 | | * This formula computes the maximum number of NumericDigits we could need |
949 | | * in order to store the specified number of decimal digits. Because the |
950 | | * weight is stored as a number of NumericDigits rather than a number of |
951 | | * decimal digits, it's possible that the first NumericDigit will contain |
952 | | * only a single decimal digit. Thus, the first two decimal digits can |
953 | | * require two NumericDigits to store, but it isn't until we reach |
954 | | * DEC_DIGITS + 2 decimal digits that we potentially need a third |
955 | | * NumericDigit. |
956 | | */ |
957 | 0 | numeric_digits = (precision + 2 * (DEC_DIGITS - 1)) / DEC_DIGITS; |
958 | | |
959 | | /* |
960 | | * In most cases, the size of a numeric will be smaller than the value |
961 | | * computed below, because the varlena header will typically get toasted |
962 | | * down to a single byte before being stored on disk, and it may also be |
963 | | * possible to use a short numeric header. But our job here is to compute |
964 | | * the worst case. |
965 | | */ |
966 | 0 | return NUMERIC_HDRSZ + (numeric_digits * sizeof(NumericDigit)); |
967 | 0 | } |
968 | | |
969 | | /* |
970 | | * numeric_out_sci() - |
971 | | * |
972 | | * Output function for numeric data type in scientific notation. |
973 | | */ |
974 | | char * |
975 | | numeric_out_sci(Numeric num, int scale) |
976 | 0 | { |
977 | 0 | NumericVar x; |
978 | 0 | char *str; |
979 | | |
980 | | /* |
981 | | * Handle NaN and infinities |
982 | | */ |
983 | 0 | if (NUMERIC_IS_SPECIAL(num)) |
984 | 0 | { |
985 | 0 | if (NUMERIC_IS_PINF(num)) |
986 | 0 | return pstrdup("Infinity"); |
987 | 0 | else if (NUMERIC_IS_NINF(num)) |
988 | 0 | return pstrdup("-Infinity"); |
989 | 0 | else |
990 | 0 | return pstrdup("NaN"); |
991 | 0 | } |
992 | | |
993 | 0 | init_var_from_num(num, &x); |
994 | |
|
995 | 0 | str = get_str_from_var_sci(&x, scale); |
996 | |
|
997 | 0 | return str; |
998 | 0 | } |
999 | | |
1000 | | /* |
1001 | | * numeric_normalize() - |
1002 | | * |
1003 | | * Output function for numeric data type, suppressing insignificant trailing |
1004 | | * zeroes and then any trailing decimal point. The intent of this is to |
1005 | | * produce strings that are equal if and only if the input numeric values |
1006 | | * compare equal. |
1007 | | */ |
1008 | | char * |
1009 | | numeric_normalize(Numeric num) |
1010 | 0 | { |
1011 | 0 | NumericVar x; |
1012 | 0 | char *str; |
1013 | 0 | int last; |
1014 | | |
1015 | | /* |
1016 | | * Handle NaN and infinities |
1017 | | */ |
1018 | 0 | if (NUMERIC_IS_SPECIAL(num)) |
1019 | 0 | { |
1020 | 0 | if (NUMERIC_IS_PINF(num)) |
1021 | 0 | return pstrdup("Infinity"); |
1022 | 0 | else if (NUMERIC_IS_NINF(num)) |
1023 | 0 | return pstrdup("-Infinity"); |
1024 | 0 | else |
1025 | 0 | return pstrdup("NaN"); |
1026 | 0 | } |
1027 | | |
1028 | 0 | init_var_from_num(num, &x); |
1029 | |
|
1030 | 0 | str = get_str_from_var(&x); |
1031 | | |
1032 | | /* If there's no decimal point, there's certainly nothing to remove. */ |
1033 | 0 | if (strchr(str, '.') != NULL) |
1034 | 0 | { |
1035 | | /* |
1036 | | * Back up over trailing fractional zeroes. Since there is a decimal |
1037 | | * point, this loop will terminate safely. |
1038 | | */ |
1039 | 0 | last = strlen(str) - 1; |
1040 | 0 | while (str[last] == '0') |
1041 | 0 | last--; |
1042 | | |
1043 | | /* We want to get rid of the decimal point too, if it's now last. */ |
1044 | 0 | if (str[last] == '.') |
1045 | 0 | last--; |
1046 | | |
1047 | | /* Delete whatever we backed up over. */ |
1048 | 0 | str[last + 1] = '\0'; |
1049 | 0 | } |
1050 | |
|
1051 | 0 | return str; |
1052 | 0 | } |
1053 | | |
1054 | | /* |
1055 | | * numeric_recv - converts external binary format to numeric |
1056 | | * |
1057 | | * External format is a sequence of int16's: |
1058 | | * ndigits, weight, sign, dscale, NumericDigits. |
1059 | | */ |
1060 | | Datum |
1061 | | numeric_recv(PG_FUNCTION_ARGS) |
1062 | 0 | { |
1063 | 0 | StringInfo buf = (StringInfo) PG_GETARG_POINTER(0); |
1064 | |
|
1065 | | #ifdef NOT_USED |
1066 | | Oid typelem = PG_GETARG_OID(1); |
1067 | | #endif |
1068 | 0 | int32 typmod = PG_GETARG_INT32(2); |
1069 | 0 | NumericVar value; |
1070 | 0 | Numeric res; |
1071 | 0 | int len, |
1072 | 0 | i; |
1073 | |
|
1074 | 0 | init_var(&value); |
1075 | |
|
1076 | 0 | len = (uint16) pq_getmsgint(buf, sizeof(uint16)); |
1077 | |
|
1078 | 0 | alloc_var(&value, len); |
1079 | |
|
1080 | 0 | value.weight = (int16) pq_getmsgint(buf, sizeof(int16)); |
1081 | | /* we allow any int16 for weight --- OK? */ |
1082 | |
|
1083 | 0 | value.sign = (uint16) pq_getmsgint(buf, sizeof(uint16)); |
1084 | 0 | if (!(value.sign == NUMERIC_POS || |
1085 | 0 | value.sign == NUMERIC_NEG || |
1086 | 0 | value.sign == NUMERIC_NAN || |
1087 | 0 | value.sign == NUMERIC_PINF || |
1088 | 0 | value.sign == NUMERIC_NINF)) |
1089 | 0 | ereport(ERROR, |
1090 | 0 | (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION), |
1091 | 0 | errmsg("invalid sign in external \"numeric\" value"))); |
1092 | | |
1093 | 0 | value.dscale = (uint16) pq_getmsgint(buf, sizeof(uint16)); |
1094 | 0 | if ((value.dscale & NUMERIC_DSCALE_MASK) != value.dscale) |
1095 | 0 | ereport(ERROR, |
1096 | 0 | (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION), |
1097 | 0 | errmsg("invalid scale in external \"numeric\" value"))); |
1098 | | |
1099 | 0 | for (i = 0; i < len; i++) |
1100 | 0 | { |
1101 | 0 | NumericDigit d = pq_getmsgint(buf, sizeof(NumericDigit)); |
1102 | |
|
1103 | 0 | if (d < 0 || d >= NBASE) |
1104 | 0 | ereport(ERROR, |
1105 | 0 | (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION), |
1106 | 0 | errmsg("invalid digit in external \"numeric\" value"))); |
1107 | 0 | value.digits[i] = d; |
1108 | 0 | } |
1109 | | |
1110 | | /* |
1111 | | * If the given dscale would hide any digits, truncate those digits away. |
1112 | | * We could alternatively throw an error, but that would take a bunch of |
1113 | | * extra code (about as much as trunc_var involves), and it might cause |
1114 | | * client compatibility issues. Be careful not to apply trunc_var to |
1115 | | * special values, as it could do the wrong thing; we don't need it |
1116 | | * anyway, since make_result will ignore all but the sign field. |
1117 | | * |
1118 | | * After doing that, be sure to check the typmod restriction. |
1119 | | */ |
1120 | 0 | if (value.sign == NUMERIC_POS || |
1121 | 0 | value.sign == NUMERIC_NEG) |
1122 | 0 | { |
1123 | 0 | trunc_var(&value, value.dscale); |
1124 | |
|
1125 | 0 | (void) apply_typmod(&value, typmod, NULL); |
1126 | |
|
1127 | 0 | res = make_result(&value); |
1128 | 0 | } |
1129 | 0 | else |
1130 | 0 | { |
1131 | | /* apply_typmod_special wants us to make the Numeric first */ |
1132 | 0 | res = make_result(&value); |
1133 | |
|
1134 | 0 | (void) apply_typmod_special(res, typmod, NULL); |
1135 | 0 | } |
1136 | |
|
1137 | 0 | free_var(&value); |
1138 | |
|
1139 | 0 | PG_RETURN_NUMERIC(res); |
1140 | 0 | } |
1141 | | |
1142 | | /* |
1143 | | * numeric_send - converts numeric to binary format |
1144 | | */ |
1145 | | Datum |
1146 | | numeric_send(PG_FUNCTION_ARGS) |
1147 | 0 | { |
1148 | 0 | Numeric num = PG_GETARG_NUMERIC(0); |
1149 | 0 | NumericVar x; |
1150 | 0 | StringInfoData buf; |
1151 | 0 | int i; |
1152 | |
|
1153 | 0 | init_var_from_num(num, &x); |
1154 | |
|
1155 | 0 | pq_begintypsend(&buf); |
1156 | |
|
1157 | 0 | pq_sendint16(&buf, x.ndigits); |
1158 | 0 | pq_sendint16(&buf, x.weight); |
1159 | 0 | pq_sendint16(&buf, x.sign); |
1160 | 0 | pq_sendint16(&buf, x.dscale); |
1161 | 0 | for (i = 0; i < x.ndigits; i++) |
1162 | 0 | pq_sendint16(&buf, x.digits[i]); |
1163 | |
|
1164 | 0 | PG_RETURN_BYTEA_P(pq_endtypsend(&buf)); |
1165 | 0 | } |
1166 | | |
1167 | | |
1168 | | /* |
1169 | | * numeric_support() |
1170 | | * |
1171 | | * Planner support function for the numeric() length coercion function. |
1172 | | * |
1173 | | * Flatten calls that solely represent increases in allowable precision. |
1174 | | * Scale changes mutate every datum, so they are unoptimizable. Some values, |
1175 | | * e.g. 1E-1001, can only fit into an unconstrained numeric, so a change from |
1176 | | * an unconstrained numeric to any constrained numeric is also unoptimizable. |
1177 | | */ |
1178 | | Datum |
1179 | | numeric_support(PG_FUNCTION_ARGS) |
1180 | 0 | { |
1181 | 0 | Node *rawreq = (Node *) PG_GETARG_POINTER(0); |
1182 | 0 | Node *ret = NULL; |
1183 | |
|
1184 | 0 | if (IsA(rawreq, SupportRequestSimplify)) |
1185 | 0 | { |
1186 | 0 | SupportRequestSimplify *req = (SupportRequestSimplify *) rawreq; |
1187 | 0 | FuncExpr *expr = req->fcall; |
1188 | 0 | Node *typmod; |
1189 | |
|
1190 | 0 | Assert(list_length(expr->args) >= 2); |
1191 | |
|
1192 | 0 | typmod = (Node *) lsecond(expr->args); |
1193 | |
|
1194 | 0 | if (IsA(typmod, Const) && !((Const *) typmod)->constisnull) |
1195 | 0 | { |
1196 | 0 | Node *source = (Node *) linitial(expr->args); |
1197 | 0 | int32 old_typmod = exprTypmod(source); |
1198 | 0 | int32 new_typmod = DatumGetInt32(((Const *) typmod)->constvalue); |
1199 | 0 | int32 old_scale = numeric_typmod_scale(old_typmod); |
1200 | 0 | int32 new_scale = numeric_typmod_scale(new_typmod); |
1201 | 0 | int32 old_precision = numeric_typmod_precision(old_typmod); |
1202 | 0 | int32 new_precision = numeric_typmod_precision(new_typmod); |
1203 | | |
1204 | | /* |
1205 | | * If new_typmod is invalid, the destination is unconstrained; |
1206 | | * that's always OK. If old_typmod is valid, the source is |
1207 | | * constrained, and we're OK if the scale is unchanged and the |
1208 | | * precision is not decreasing. See further notes in function |
1209 | | * header comment. |
1210 | | */ |
1211 | 0 | if (!is_valid_numeric_typmod(new_typmod) || |
1212 | 0 | (is_valid_numeric_typmod(old_typmod) && |
1213 | 0 | new_scale == old_scale && new_precision >= old_precision)) |
1214 | 0 | ret = relabel_to_typmod(source, new_typmod); |
1215 | 0 | } |
1216 | 0 | } |
1217 | |
|
1218 | 0 | PG_RETURN_POINTER(ret); |
1219 | 0 | } |
1220 | | |
1221 | | /* |
1222 | | * numeric() - |
1223 | | * |
1224 | | * This is a special function called by the Postgres database system |
1225 | | * before a value is stored in a tuple's attribute. The precision and |
1226 | | * scale of the attribute have to be applied on the value. |
1227 | | */ |
1228 | | Datum |
1229 | | numeric (PG_FUNCTION_ARGS) |
1230 | 0 | { |
1231 | 0 | Numeric num = PG_GETARG_NUMERIC(0); |
1232 | 0 | int32 typmod = PG_GETARG_INT32(1); |
1233 | 0 | Numeric new; |
1234 | 0 | int precision; |
1235 | 0 | int scale; |
1236 | 0 | int ddigits; |
1237 | 0 | int maxdigits; |
1238 | 0 | int dscale; |
1239 | 0 | NumericVar var; |
1240 | | |
1241 | | /* |
1242 | | * Handle NaN and infinities: if apply_typmod_special doesn't complain, |
1243 | | * just return a copy of the input. |
1244 | | */ |
1245 | 0 | if (NUMERIC_IS_SPECIAL(num)) |
1246 | 0 | { |
1247 | 0 | if (!apply_typmod_special(num, typmod, fcinfo->context)) |
1248 | 0 | PG_RETURN_NULL(); |
1249 | 0 | PG_RETURN_NUMERIC(duplicate_numeric(num)); |
1250 | 0 | } |
1251 | | |
1252 | | /* |
1253 | | * If the value isn't a valid type modifier, simply return a copy of the |
1254 | | * input value |
1255 | | */ |
1256 | 0 | if (!is_valid_numeric_typmod(typmod)) |
1257 | 0 | PG_RETURN_NUMERIC(duplicate_numeric(num)); |
1258 | | |
1259 | | /* |
1260 | | * Get the precision and scale out of the typmod value |
1261 | | */ |
1262 | 0 | precision = numeric_typmod_precision(typmod); |
1263 | 0 | scale = numeric_typmod_scale(typmod); |
1264 | 0 | maxdigits = precision - scale; |
1265 | | |
1266 | | /* The target display scale is non-negative */ |
1267 | 0 | dscale = Max(scale, 0); |
1268 | | |
1269 | | /* |
1270 | | * If the number is certainly in bounds and due to the target scale no |
1271 | | * rounding could be necessary, just make a copy of the input and modify |
1272 | | * its scale fields, unless the larger scale forces us to abandon the |
1273 | | * short representation. (Note we assume the existing dscale is |
1274 | | * honest...) |
1275 | | */ |
1276 | 0 | ddigits = (NUMERIC_WEIGHT(num) + 1) * DEC_DIGITS; |
1277 | 0 | if (ddigits <= maxdigits && scale >= NUMERIC_DSCALE(num) |
1278 | 0 | && (NUMERIC_CAN_BE_SHORT(dscale, NUMERIC_WEIGHT(num)) |
1279 | 0 | || !NUMERIC_IS_SHORT(num))) |
1280 | 0 | { |
1281 | 0 | new = duplicate_numeric(num); |
1282 | 0 | if (NUMERIC_IS_SHORT(num)) |
1283 | 0 | new->choice.n_short.n_header = |
1284 | 0 | (num->choice.n_short.n_header & ~NUMERIC_SHORT_DSCALE_MASK) |
1285 | 0 | | (dscale << NUMERIC_SHORT_DSCALE_SHIFT); |
1286 | 0 | else |
1287 | 0 | new->choice.n_long.n_sign_dscale = NUMERIC_SIGN(new) | |
1288 | 0 | ((uint16) dscale & NUMERIC_DSCALE_MASK); |
1289 | 0 | PG_RETURN_NUMERIC(new); |
1290 | 0 | } |
1291 | | |
1292 | | /* |
1293 | | * We really need to fiddle with things - unpack the number into a |
1294 | | * variable and let apply_typmod() do it. |
1295 | | */ |
1296 | 0 | init_var(&var); |
1297 | |
|
1298 | 0 | set_var_from_num(num, &var); |
1299 | 0 | if (!apply_typmod(&var, typmod, fcinfo->context)) |
1300 | 0 | PG_RETURN_NULL(); |
1301 | 0 | new = make_result_safe(&var, fcinfo->context); |
1302 | |
|
1303 | 0 | free_var(&var); |
1304 | |
|
1305 | 0 | PG_RETURN_NUMERIC(new); |
1306 | 0 | } |
1307 | | |
1308 | | /* |
1309 | | * make_numeric_typmod_safe() - |
1310 | | * |
1311 | | * Validate a numeric precision/scale and pack them into a typmod value, |
1312 | | * with soft error handling. |
1313 | | */ |
1314 | | int32 |
1315 | | make_numeric_typmod_safe(int32 precision, int32 scale, Node *escontext) |
1316 | 0 | { |
1317 | 0 | if (precision < 1 || precision > NUMERIC_MAX_PRECISION) |
1318 | 0 | ereturn(escontext, -1, |
1319 | 0 | (errcode(ERRCODE_INVALID_PARAMETER_VALUE), |
1320 | 0 | errmsg("NUMERIC precision %d must be between 1 and %d", |
1321 | 0 | precision, NUMERIC_MAX_PRECISION))); |
1322 | 0 | if (scale < NUMERIC_MIN_SCALE || scale > NUMERIC_MAX_SCALE) |
1323 | 0 | ereturn(escontext, -1, |
1324 | 0 | (errcode(ERRCODE_INVALID_PARAMETER_VALUE), |
1325 | 0 | errmsg("NUMERIC scale %d must be between %d and %d", |
1326 | 0 | scale, NUMERIC_MIN_SCALE, NUMERIC_MAX_SCALE))); |
1327 | | |
1328 | 0 | return make_numeric_typmod(precision, scale); |
1329 | 0 | } |
1330 | | |
1331 | | Datum |
1332 | | numerictypmodin(PG_FUNCTION_ARGS) |
1333 | 0 | { |
1334 | 0 | ArrayType *ta = PG_GETARG_ARRAYTYPE_P(0); |
1335 | 0 | int32 *tl; |
1336 | 0 | int n; |
1337 | 0 | int32 typmod; |
1338 | |
|
1339 | 0 | tl = ArrayGetIntegerTypmods(ta, &n); |
1340 | |
|
1341 | 0 | if (n == 2) |
1342 | 0 | typmod = make_numeric_typmod_safe(tl[0], tl[1], NULL); |
1343 | 0 | else if (n == 1) |
1344 | 0 | { |
1345 | | /* scale defaults to zero */ |
1346 | 0 | typmod = make_numeric_typmod_safe(tl[0], 0, NULL); |
1347 | 0 | } |
1348 | 0 | else |
1349 | 0 | { |
1350 | 0 | ereport(ERROR, |
1351 | 0 | (errcode(ERRCODE_INVALID_PARAMETER_VALUE), |
1352 | 0 | errmsg("invalid NUMERIC type modifier"))); |
1353 | 0 | typmod = 0; /* keep compiler quiet */ |
1354 | 0 | } |
1355 | | |
1356 | 0 | PG_RETURN_INT32(typmod); |
1357 | 0 | } |
1358 | | |
1359 | | Datum |
1360 | | numerictypmodout(PG_FUNCTION_ARGS) |
1361 | 0 | { |
1362 | 0 | int32 typmod = PG_GETARG_INT32(0); |
1363 | 0 | char *res = (char *) palloc(64); |
1364 | |
|
1365 | 0 | if (is_valid_numeric_typmod(typmod)) |
1366 | 0 | snprintf(res, 64, "(%d,%d)", |
1367 | 0 | numeric_typmod_precision(typmod), |
1368 | 0 | numeric_typmod_scale(typmod)); |
1369 | 0 | else |
1370 | 0 | *res = '\0'; |
1371 | |
|
1372 | 0 | PG_RETURN_CSTRING(res); |
1373 | 0 | } |
1374 | | |
1375 | | |
1376 | | /* ---------------------------------------------------------------------- |
1377 | | * |
1378 | | * Sign manipulation, rounding and the like |
1379 | | * |
1380 | | * ---------------------------------------------------------------------- |
1381 | | */ |
1382 | | |
1383 | | Datum |
1384 | | numeric_abs(PG_FUNCTION_ARGS) |
1385 | 0 | { |
1386 | 0 | Numeric num = PG_GETARG_NUMERIC(0); |
1387 | 0 | Numeric res; |
1388 | | |
1389 | | /* |
1390 | | * Do it the easy way directly on the packed format |
1391 | | */ |
1392 | 0 | res = duplicate_numeric(num); |
1393 | |
|
1394 | 0 | if (NUMERIC_IS_SHORT(num)) |
1395 | 0 | res->choice.n_short.n_header = |
1396 | 0 | num->choice.n_short.n_header & ~NUMERIC_SHORT_SIGN_MASK; |
1397 | 0 | else if (NUMERIC_IS_SPECIAL(num)) |
1398 | 0 | { |
1399 | | /* This changes -Inf to Inf, and doesn't affect NaN */ |
1400 | 0 | res->choice.n_short.n_header = |
1401 | 0 | num->choice.n_short.n_header & ~NUMERIC_INF_SIGN_MASK; |
1402 | 0 | } |
1403 | 0 | else |
1404 | 0 | res->choice.n_long.n_sign_dscale = NUMERIC_POS | NUMERIC_DSCALE(num); |
1405 | |
|
1406 | 0 | PG_RETURN_NUMERIC(res); |
1407 | 0 | } |
1408 | | |
1409 | | |
1410 | | Datum |
1411 | | numeric_uminus(PG_FUNCTION_ARGS) |
1412 | 0 | { |
1413 | 0 | Numeric num = PG_GETARG_NUMERIC(0); |
1414 | 0 | Numeric res; |
1415 | | |
1416 | | /* |
1417 | | * Do it the easy way directly on the packed format |
1418 | | */ |
1419 | 0 | res = duplicate_numeric(num); |
1420 | |
|
1421 | 0 | if (NUMERIC_IS_SPECIAL(num)) |
1422 | 0 | { |
1423 | | /* Flip the sign, if it's Inf or -Inf */ |
1424 | 0 | if (!NUMERIC_IS_NAN(num)) |
1425 | 0 | res->choice.n_short.n_header = |
1426 | 0 | num->choice.n_short.n_header ^ NUMERIC_INF_SIGN_MASK; |
1427 | 0 | } |
1428 | | |
1429 | | /* |
1430 | | * The packed format is known to be totally zero digit trimmed always. So |
1431 | | * once we've eliminated specials, we can identify a zero by the fact that |
1432 | | * there are no digits at all. Do nothing to a zero. |
1433 | | */ |
1434 | 0 | else if (NUMERIC_NDIGITS(num) != 0) |
1435 | 0 | { |
1436 | | /* Else, flip the sign */ |
1437 | 0 | if (NUMERIC_IS_SHORT(num)) |
1438 | 0 | res->choice.n_short.n_header = |
1439 | 0 | num->choice.n_short.n_header ^ NUMERIC_SHORT_SIGN_MASK; |
1440 | 0 | else if (NUMERIC_SIGN(num) == NUMERIC_POS) |
1441 | 0 | res->choice.n_long.n_sign_dscale = |
1442 | 0 | NUMERIC_NEG | NUMERIC_DSCALE(num); |
1443 | 0 | else |
1444 | 0 | res->choice.n_long.n_sign_dscale = |
1445 | 0 | NUMERIC_POS | NUMERIC_DSCALE(num); |
1446 | 0 | } |
1447 | |
|
1448 | 0 | PG_RETURN_NUMERIC(res); |
1449 | 0 | } |
1450 | | |
1451 | | |
1452 | | Datum |
1453 | | numeric_uplus(PG_FUNCTION_ARGS) |
1454 | 0 | { |
1455 | 0 | Numeric num = PG_GETARG_NUMERIC(0); |
1456 | |
|
1457 | 0 | PG_RETURN_NUMERIC(duplicate_numeric(num)); |
1458 | 0 | } |
1459 | | |
1460 | | |
1461 | | /* |
1462 | | * numeric_sign_internal() - |
1463 | | * |
1464 | | * Returns -1 if the argument is less than 0, 0 if the argument is equal |
1465 | | * to 0, and 1 if the argument is greater than zero. Caller must have |
1466 | | * taken care of the NaN case, but we can handle infinities here. |
1467 | | */ |
1468 | | static int |
1469 | | numeric_sign_internal(Numeric num) |
1470 | 0 | { |
1471 | 0 | if (NUMERIC_IS_SPECIAL(num)) |
1472 | 0 | { |
1473 | 0 | Assert(!NUMERIC_IS_NAN(num)); |
1474 | | /* Must be Inf or -Inf */ |
1475 | 0 | if (NUMERIC_IS_PINF(num)) |
1476 | 0 | return 1; |
1477 | 0 | else |
1478 | 0 | return -1; |
1479 | 0 | } |
1480 | | |
1481 | | /* |
1482 | | * The packed format is known to be totally zero digit trimmed always. So |
1483 | | * once we've eliminated specials, we can identify a zero by the fact that |
1484 | | * there are no digits at all. |
1485 | | */ |
1486 | 0 | else if (NUMERIC_NDIGITS(num) == 0) |
1487 | 0 | return 0; |
1488 | 0 | else if (NUMERIC_SIGN(num) == NUMERIC_NEG) |
1489 | 0 | return -1; |
1490 | 0 | else |
1491 | 0 | return 1; |
1492 | 0 | } |
1493 | | |
1494 | | /* |
1495 | | * numeric_sign() - |
1496 | | * |
1497 | | * returns -1 if the argument is less than 0, 0 if the argument is equal |
1498 | | * to 0, and 1 if the argument is greater than zero. |
1499 | | */ |
1500 | | Datum |
1501 | | numeric_sign(PG_FUNCTION_ARGS) |
1502 | 0 | { |
1503 | 0 | Numeric num = PG_GETARG_NUMERIC(0); |
1504 | | |
1505 | | /* |
1506 | | * Handle NaN (infinities can be handled normally) |
1507 | | */ |
1508 | 0 | if (NUMERIC_IS_NAN(num)) |
1509 | 0 | PG_RETURN_NUMERIC(make_result(&const_nan)); |
1510 | | |
1511 | 0 | switch (numeric_sign_internal(num)) |
1512 | 0 | { |
1513 | 0 | case 0: |
1514 | 0 | PG_RETURN_NUMERIC(make_result(&const_zero)); |
1515 | 0 | case 1: |
1516 | 0 | PG_RETURN_NUMERIC(make_result(&const_one)); |
1517 | 0 | case -1: |
1518 | 0 | PG_RETURN_NUMERIC(make_result(&const_minus_one)); |
1519 | 0 | } |
1520 | | |
1521 | 0 | Assert(false); |
1522 | 0 | return (Datum) 0; |
1523 | 0 | } |
1524 | | |
1525 | | |
1526 | | /* |
1527 | | * numeric_round() - |
1528 | | * |
1529 | | * Round a value to have 'scale' digits after the decimal point. |
1530 | | * We allow negative 'scale', implying rounding before the decimal |
1531 | | * point --- Oracle interprets rounding that way. |
1532 | | */ |
1533 | | Datum |
1534 | | numeric_round(PG_FUNCTION_ARGS) |
1535 | 0 | { |
1536 | 0 | Numeric num = PG_GETARG_NUMERIC(0); |
1537 | 0 | int32 scale = PG_GETARG_INT32(1); |
1538 | 0 | Numeric res; |
1539 | 0 | NumericVar arg; |
1540 | | |
1541 | | /* |
1542 | | * Handle NaN and infinities |
1543 | | */ |
1544 | 0 | if (NUMERIC_IS_SPECIAL(num)) |
1545 | 0 | PG_RETURN_NUMERIC(duplicate_numeric(num)); |
1546 | | |
1547 | | /* |
1548 | | * Limit the scale value to avoid possible overflow in calculations. |
1549 | | * |
1550 | | * These limits are based on the maximum number of digits a Numeric value |
1551 | | * can have before and after the decimal point, but we must allow for one |
1552 | | * extra digit before the decimal point, in case the most significant |
1553 | | * digit rounds up; we must check if that causes Numeric overflow. |
1554 | | */ |
1555 | 0 | scale = Max(scale, -(NUMERIC_WEIGHT_MAX + 1) * DEC_DIGITS - 1); |
1556 | 0 | scale = Min(scale, NUMERIC_DSCALE_MAX); |
1557 | | |
1558 | | /* |
1559 | | * Unpack the argument and round it at the proper digit position |
1560 | | */ |
1561 | 0 | init_var(&arg); |
1562 | 0 | set_var_from_num(num, &arg); |
1563 | |
|
1564 | 0 | round_var(&arg, scale); |
1565 | | |
1566 | | /* We don't allow negative output dscale */ |
1567 | 0 | if (scale < 0) |
1568 | 0 | arg.dscale = 0; |
1569 | | |
1570 | | /* |
1571 | | * Return the rounded result |
1572 | | */ |
1573 | 0 | res = make_result(&arg); |
1574 | |
|
1575 | 0 | free_var(&arg); |
1576 | 0 | PG_RETURN_NUMERIC(res); |
1577 | 0 | } |
1578 | | |
1579 | | |
1580 | | /* |
1581 | | * numeric_trunc() - |
1582 | | * |
1583 | | * Truncate a value to have 'scale' digits after the decimal point. |
1584 | | * We allow negative 'scale', implying a truncation before the decimal |
1585 | | * point --- Oracle interprets truncation that way. |
1586 | | */ |
1587 | | Datum |
1588 | | numeric_trunc(PG_FUNCTION_ARGS) |
1589 | 0 | { |
1590 | 0 | Numeric num = PG_GETARG_NUMERIC(0); |
1591 | 0 | int32 scale = PG_GETARG_INT32(1); |
1592 | 0 | Numeric res; |
1593 | 0 | NumericVar arg; |
1594 | | |
1595 | | /* |
1596 | | * Handle NaN and infinities |
1597 | | */ |
1598 | 0 | if (NUMERIC_IS_SPECIAL(num)) |
1599 | 0 | PG_RETURN_NUMERIC(duplicate_numeric(num)); |
1600 | | |
1601 | | /* |
1602 | | * Limit the scale value to avoid possible overflow in calculations. |
1603 | | * |
1604 | | * These limits are based on the maximum number of digits a Numeric value |
1605 | | * can have before and after the decimal point. |
1606 | | */ |
1607 | 0 | scale = Max(scale, -(NUMERIC_WEIGHT_MAX + 1) * DEC_DIGITS); |
1608 | 0 | scale = Min(scale, NUMERIC_DSCALE_MAX); |
1609 | | |
1610 | | /* |
1611 | | * Unpack the argument and truncate it at the proper digit position |
1612 | | */ |
1613 | 0 | init_var(&arg); |
1614 | 0 | set_var_from_num(num, &arg); |
1615 | |
|
1616 | 0 | trunc_var(&arg, scale); |
1617 | | |
1618 | | /* We don't allow negative output dscale */ |
1619 | 0 | if (scale < 0) |
1620 | 0 | arg.dscale = 0; |
1621 | | |
1622 | | /* |
1623 | | * Return the truncated result |
1624 | | */ |
1625 | 0 | res = make_result(&arg); |
1626 | |
|
1627 | 0 | free_var(&arg); |
1628 | 0 | PG_RETURN_NUMERIC(res); |
1629 | 0 | } |
1630 | | |
1631 | | |
1632 | | /* |
1633 | | * numeric_ceil() - |
1634 | | * |
1635 | | * Return the smallest integer greater than or equal to the argument |
1636 | | */ |
1637 | | Datum |
1638 | | numeric_ceil(PG_FUNCTION_ARGS) |
1639 | 0 | { |
1640 | 0 | Numeric num = PG_GETARG_NUMERIC(0); |
1641 | 0 | Numeric res; |
1642 | 0 | NumericVar result; |
1643 | | |
1644 | | /* |
1645 | | * Handle NaN and infinities |
1646 | | */ |
1647 | 0 | if (NUMERIC_IS_SPECIAL(num)) |
1648 | 0 | PG_RETURN_NUMERIC(duplicate_numeric(num)); |
1649 | | |
1650 | 0 | init_var_from_num(num, &result); |
1651 | 0 | ceil_var(&result, &result); |
1652 | |
|
1653 | 0 | res = make_result(&result); |
1654 | 0 | free_var(&result); |
1655 | |
|
1656 | 0 | PG_RETURN_NUMERIC(res); |
1657 | 0 | } |
1658 | | |
1659 | | |
1660 | | /* |
1661 | | * numeric_floor() - |
1662 | | * |
1663 | | * Return the largest integer equal to or less than the argument |
1664 | | */ |
1665 | | Datum |
1666 | | numeric_floor(PG_FUNCTION_ARGS) |
1667 | 0 | { |
1668 | 0 | Numeric num = PG_GETARG_NUMERIC(0); |
1669 | 0 | Numeric res; |
1670 | 0 | NumericVar result; |
1671 | | |
1672 | | /* |
1673 | | * Handle NaN and infinities |
1674 | | */ |
1675 | 0 | if (NUMERIC_IS_SPECIAL(num)) |
1676 | 0 | PG_RETURN_NUMERIC(duplicate_numeric(num)); |
1677 | | |
1678 | 0 | init_var_from_num(num, &result); |
1679 | 0 | floor_var(&result, &result); |
1680 | |
|
1681 | 0 | res = make_result(&result); |
1682 | 0 | free_var(&result); |
1683 | |
|
1684 | 0 | PG_RETURN_NUMERIC(res); |
1685 | 0 | } |
1686 | | |
1687 | | |
1688 | | /* |
1689 | | * generate_series_numeric() - |
1690 | | * |
1691 | | * Generate series of numeric. |
1692 | | */ |
1693 | | Datum |
1694 | | generate_series_numeric(PG_FUNCTION_ARGS) |
1695 | 0 | { |
1696 | 0 | return generate_series_step_numeric(fcinfo); |
1697 | 0 | } |
1698 | | |
1699 | | Datum |
1700 | | generate_series_step_numeric(PG_FUNCTION_ARGS) |
1701 | 0 | { |
1702 | 0 | generate_series_numeric_fctx *fctx; |
1703 | 0 | FuncCallContext *funcctx; |
1704 | 0 | MemoryContext oldcontext; |
1705 | |
|
1706 | 0 | if (SRF_IS_FIRSTCALL()) |
1707 | 0 | { |
1708 | 0 | Numeric start_num = PG_GETARG_NUMERIC(0); |
1709 | 0 | Numeric stop_num = PG_GETARG_NUMERIC(1); |
1710 | 0 | NumericVar steploc = const_one; |
1711 | | |
1712 | | /* Reject NaN and infinities in start and stop values */ |
1713 | 0 | if (NUMERIC_IS_SPECIAL(start_num)) |
1714 | 0 | { |
1715 | 0 | if (NUMERIC_IS_NAN(start_num)) |
1716 | 0 | ereport(ERROR, |
1717 | 0 | (errcode(ERRCODE_INVALID_PARAMETER_VALUE), |
1718 | 0 | errmsg("start value cannot be NaN"))); |
1719 | 0 | else |
1720 | 0 | ereport(ERROR, |
1721 | 0 | (errcode(ERRCODE_INVALID_PARAMETER_VALUE), |
1722 | 0 | errmsg("start value cannot be infinity"))); |
1723 | 0 | } |
1724 | 0 | if (NUMERIC_IS_SPECIAL(stop_num)) |
1725 | 0 | { |
1726 | 0 | if (NUMERIC_IS_NAN(stop_num)) |
1727 | 0 | ereport(ERROR, |
1728 | 0 | (errcode(ERRCODE_INVALID_PARAMETER_VALUE), |
1729 | 0 | errmsg("stop value cannot be NaN"))); |
1730 | 0 | else |
1731 | 0 | ereport(ERROR, |
1732 | 0 | (errcode(ERRCODE_INVALID_PARAMETER_VALUE), |
1733 | 0 | errmsg("stop value cannot be infinity"))); |
1734 | 0 | } |
1735 | | |
1736 | | /* see if we were given an explicit step size */ |
1737 | 0 | if (PG_NARGS() == 3) |
1738 | 0 | { |
1739 | 0 | Numeric step_num = PG_GETARG_NUMERIC(2); |
1740 | |
|
1741 | 0 | if (NUMERIC_IS_SPECIAL(step_num)) |
1742 | 0 | { |
1743 | 0 | if (NUMERIC_IS_NAN(step_num)) |
1744 | 0 | ereport(ERROR, |
1745 | 0 | (errcode(ERRCODE_INVALID_PARAMETER_VALUE), |
1746 | 0 | errmsg("step size cannot be NaN"))); |
1747 | 0 | else |
1748 | 0 | ereport(ERROR, |
1749 | 0 | (errcode(ERRCODE_INVALID_PARAMETER_VALUE), |
1750 | 0 | errmsg("step size cannot be infinity"))); |
1751 | 0 | } |
1752 | | |
1753 | 0 | init_var_from_num(step_num, &steploc); |
1754 | |
|
1755 | 0 | if (cmp_var(&steploc, &const_zero) == 0) |
1756 | 0 | ereport(ERROR, |
1757 | 0 | (errcode(ERRCODE_INVALID_PARAMETER_VALUE), |
1758 | 0 | errmsg("step size cannot equal zero"))); |
1759 | 0 | } |
1760 | | |
1761 | | /* create a function context for cross-call persistence */ |
1762 | 0 | funcctx = SRF_FIRSTCALL_INIT(); |
1763 | | |
1764 | | /* |
1765 | | * Switch to memory context appropriate for multiple function calls. |
1766 | | */ |
1767 | 0 | oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx); |
1768 | | |
1769 | | /* allocate memory for user context */ |
1770 | 0 | fctx = palloc_object(generate_series_numeric_fctx); |
1771 | | |
1772 | | /* |
1773 | | * Use fctx to keep state from call to call. Seed current with the |
1774 | | * original start value. We must copy the start_num and stop_num |
1775 | | * values rather than pointing to them, since we may have detoasted |
1776 | | * them in the per-call context. |
1777 | | */ |
1778 | 0 | init_var(&fctx->current); |
1779 | 0 | init_var(&fctx->stop); |
1780 | 0 | init_var(&fctx->step); |
1781 | |
|
1782 | 0 | set_var_from_num(start_num, &fctx->current); |
1783 | 0 | set_var_from_num(stop_num, &fctx->stop); |
1784 | 0 | set_var_from_var(&steploc, &fctx->step); |
1785 | |
|
1786 | 0 | funcctx->user_fctx = fctx; |
1787 | 0 | MemoryContextSwitchTo(oldcontext); |
1788 | 0 | } |
1789 | | |
1790 | | /* stuff done on every call of the function */ |
1791 | 0 | funcctx = SRF_PERCALL_SETUP(); |
1792 | | |
1793 | | /* |
1794 | | * Get the saved state and use current state as the result of this |
1795 | | * iteration. |
1796 | | */ |
1797 | 0 | fctx = funcctx->user_fctx; |
1798 | |
|
1799 | 0 | if ((fctx->step.sign == NUMERIC_POS && |
1800 | 0 | cmp_var(&fctx->current, &fctx->stop) <= 0) || |
1801 | 0 | (fctx->step.sign == NUMERIC_NEG && |
1802 | 0 | cmp_var(&fctx->current, &fctx->stop) >= 0)) |
1803 | 0 | { |
1804 | 0 | Numeric result = make_result(&fctx->current); |
1805 | | |
1806 | | /* switch to memory context appropriate for iteration calculation */ |
1807 | 0 | oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx); |
1808 | | |
1809 | | /* increment current in preparation for next iteration */ |
1810 | 0 | add_var(&fctx->current, &fctx->step, &fctx->current); |
1811 | 0 | MemoryContextSwitchTo(oldcontext); |
1812 | | |
1813 | | /* do when there is more left to send */ |
1814 | 0 | SRF_RETURN_NEXT(funcctx, NumericGetDatum(result)); |
1815 | 0 | } |
1816 | 0 | else |
1817 | | /* do when there is no more left */ |
1818 | 0 | SRF_RETURN_DONE(funcctx); |
1819 | 0 | } |
1820 | | |
1821 | | /* |
1822 | | * Planner support function for generate_series(numeric, numeric [, numeric]) |
1823 | | */ |
1824 | | Datum |
1825 | | generate_series_numeric_support(PG_FUNCTION_ARGS) |
1826 | 0 | { |
1827 | 0 | Node *rawreq = (Node *) PG_GETARG_POINTER(0); |
1828 | 0 | Node *ret = NULL; |
1829 | |
|
1830 | 0 | if (IsA(rawreq, SupportRequestRows)) |
1831 | 0 | { |
1832 | | /* Try to estimate the number of rows returned */ |
1833 | 0 | SupportRequestRows *req = (SupportRequestRows *) rawreq; |
1834 | |
|
1835 | 0 | if (is_funcclause(req->node)) /* be paranoid */ |
1836 | 0 | { |
1837 | 0 | List *args = ((FuncExpr *) req->node)->args; |
1838 | 0 | Node *arg1, |
1839 | 0 | *arg2, |
1840 | 0 | *arg3; |
1841 | | |
1842 | | /* We can use estimated argument values here */ |
1843 | 0 | arg1 = estimate_expression_value(req->root, linitial(args)); |
1844 | 0 | arg2 = estimate_expression_value(req->root, lsecond(args)); |
1845 | 0 | if (list_length(args) >= 3) |
1846 | 0 | arg3 = estimate_expression_value(req->root, lthird(args)); |
1847 | 0 | else |
1848 | 0 | arg3 = NULL; |
1849 | | |
1850 | | /* |
1851 | | * If any argument is constant NULL, we can safely assume that |
1852 | | * zero rows are returned. Otherwise, if they're all non-NULL |
1853 | | * constants, we can calculate the number of rows that will be |
1854 | | * returned. |
1855 | | */ |
1856 | 0 | if ((IsA(arg1, Const) && |
1857 | 0 | ((Const *) arg1)->constisnull) || |
1858 | 0 | (IsA(arg2, Const) && |
1859 | 0 | ((Const *) arg2)->constisnull) || |
1860 | 0 | (arg3 != NULL && IsA(arg3, Const) && |
1861 | 0 | ((Const *) arg3)->constisnull)) |
1862 | 0 | { |
1863 | 0 | req->rows = 0; |
1864 | 0 | ret = (Node *) req; |
1865 | 0 | } |
1866 | 0 | else if (IsA(arg1, Const) && |
1867 | 0 | IsA(arg2, Const) && |
1868 | 0 | (arg3 == NULL || IsA(arg3, Const))) |
1869 | 0 | { |
1870 | 0 | Numeric start_num; |
1871 | 0 | Numeric stop_num; |
1872 | 0 | NumericVar step = const_one; |
1873 | | |
1874 | | /* |
1875 | | * If any argument is NaN or infinity, generate_series() will |
1876 | | * error out, so we needn't produce an estimate. |
1877 | | */ |
1878 | 0 | start_num = DatumGetNumeric(((Const *) arg1)->constvalue); |
1879 | 0 | stop_num = DatumGetNumeric(((Const *) arg2)->constvalue); |
1880 | |
|
1881 | 0 | if (NUMERIC_IS_SPECIAL(start_num) || |
1882 | 0 | NUMERIC_IS_SPECIAL(stop_num)) |
1883 | 0 | PG_RETURN_POINTER(NULL); |
1884 | | |
1885 | 0 | if (arg3) |
1886 | 0 | { |
1887 | 0 | Numeric step_num; |
1888 | |
|
1889 | 0 | step_num = DatumGetNumeric(((Const *) arg3)->constvalue); |
1890 | |
|
1891 | 0 | if (NUMERIC_IS_SPECIAL(step_num)) |
1892 | 0 | PG_RETURN_POINTER(NULL); |
1893 | | |
1894 | 0 | init_var_from_num(step_num, &step); |
1895 | 0 | } |
1896 | | |
1897 | | /* |
1898 | | * The number of rows that will be returned is given by |
1899 | | * floor((stop - start) / step) + 1, if the sign of step |
1900 | | * matches the sign of stop - start. Otherwise, no rows will |
1901 | | * be returned. |
1902 | | */ |
1903 | 0 | if (cmp_var(&step, &const_zero) != 0) |
1904 | 0 | { |
1905 | 0 | NumericVar start; |
1906 | 0 | NumericVar stop; |
1907 | 0 | NumericVar res; |
1908 | |
|
1909 | 0 | init_var_from_num(start_num, &start); |
1910 | 0 | init_var_from_num(stop_num, &stop); |
1911 | |
|
1912 | 0 | init_var(&res); |
1913 | 0 | sub_var(&stop, &start, &res); |
1914 | |
|
1915 | 0 | if (step.sign != res.sign) |
1916 | 0 | { |
1917 | | /* no rows will be returned */ |
1918 | 0 | req->rows = 0; |
1919 | 0 | ret = (Node *) req; |
1920 | 0 | } |
1921 | 0 | else |
1922 | 0 | { |
1923 | 0 | if (arg3) |
1924 | 0 | div_var(&res, &step, &res, 0, false, false); |
1925 | 0 | else |
1926 | 0 | trunc_var(&res, 0); /* step = 1 */ |
1927 | |
|
1928 | 0 | req->rows = numericvar_to_double_no_overflow(&res) + 1; |
1929 | 0 | ret = (Node *) req; |
1930 | 0 | } |
1931 | |
|
1932 | 0 | free_var(&res); |
1933 | 0 | } |
1934 | 0 | } |
1935 | 0 | } |
1936 | 0 | } |
1937 | | |
1938 | 0 | PG_RETURN_POINTER(ret); |
1939 | 0 | } |
1940 | | |
1941 | | |
1942 | | /* |
1943 | | * Implements the numeric version of the width_bucket() function |
1944 | | * defined by SQL2003. See also width_bucket_float8(). |
1945 | | * |
1946 | | * 'bound1' and 'bound2' are the lower and upper bounds of the |
1947 | | * histogram's range, respectively. 'count' is the number of buckets |
1948 | | * in the histogram. width_bucket() returns an integer indicating the |
1949 | | * bucket number that 'operand' belongs to in an equiwidth histogram |
1950 | | * with the specified characteristics. An operand smaller than the |
1951 | | * lower bound is assigned to bucket 0. An operand greater than or equal |
1952 | | * to the upper bound is assigned to an additional bucket (with number |
1953 | | * count+1). We don't allow the histogram bounds to be NaN or +/- infinity, |
1954 | | * but we do allow those values for the operand (taking NaN to be larger |
1955 | | * than any other value, as we do in comparisons). |
1956 | | */ |
1957 | | Datum |
1958 | | width_bucket_numeric(PG_FUNCTION_ARGS) |
1959 | 0 | { |
1960 | 0 | Numeric operand = PG_GETARG_NUMERIC(0); |
1961 | 0 | Numeric bound1 = PG_GETARG_NUMERIC(1); |
1962 | 0 | Numeric bound2 = PG_GETARG_NUMERIC(2); |
1963 | 0 | int32 count = PG_GETARG_INT32(3); |
1964 | 0 | NumericVar count_var; |
1965 | 0 | NumericVar result_var; |
1966 | 0 | int32 result; |
1967 | |
|
1968 | 0 | if (count <= 0) |
1969 | 0 | ereport(ERROR, |
1970 | 0 | (errcode(ERRCODE_INVALID_ARGUMENT_FOR_WIDTH_BUCKET_FUNCTION), |
1971 | 0 | errmsg("count must be greater than zero"))); |
1972 | | |
1973 | 0 | if (NUMERIC_IS_SPECIAL(bound1) || NUMERIC_IS_SPECIAL(bound2)) |
1974 | 0 | { |
1975 | 0 | if (NUMERIC_IS_NAN(bound1) || NUMERIC_IS_NAN(bound2)) |
1976 | 0 | ereport(ERROR, |
1977 | 0 | (errcode(ERRCODE_INVALID_ARGUMENT_FOR_WIDTH_BUCKET_FUNCTION), |
1978 | 0 | errmsg("lower and upper bounds cannot be NaN"))); |
1979 | | |
1980 | 0 | if (NUMERIC_IS_INF(bound1) || NUMERIC_IS_INF(bound2)) |
1981 | 0 | ereport(ERROR, |
1982 | 0 | (errcode(ERRCODE_INVALID_ARGUMENT_FOR_WIDTH_BUCKET_FUNCTION), |
1983 | 0 | errmsg("lower and upper bounds must be finite"))); |
1984 | 0 | } |
1985 | | |
1986 | 0 | init_var(&result_var); |
1987 | 0 | init_var(&count_var); |
1988 | | |
1989 | | /* Convert 'count' to a numeric, for ease of use later */ |
1990 | 0 | int64_to_numericvar((int64) count, &count_var); |
1991 | |
|
1992 | 0 | switch (cmp_numerics(bound1, bound2)) |
1993 | 0 | { |
1994 | 0 | case 0: |
1995 | 0 | ereport(ERROR, |
1996 | 0 | (errcode(ERRCODE_INVALID_ARGUMENT_FOR_WIDTH_BUCKET_FUNCTION), |
1997 | 0 | errmsg("lower bound cannot equal upper bound"))); |
1998 | 0 | break; |
1999 | | |
2000 | | /* bound1 < bound2 */ |
2001 | 0 | case -1: |
2002 | 0 | if (cmp_numerics(operand, bound1) < 0) |
2003 | 0 | set_var_from_var(&const_zero, &result_var); |
2004 | 0 | else if (cmp_numerics(operand, bound2) >= 0) |
2005 | 0 | add_var(&count_var, &const_one, &result_var); |
2006 | 0 | else |
2007 | 0 | compute_bucket(operand, bound1, bound2, &count_var, |
2008 | 0 | &result_var); |
2009 | 0 | break; |
2010 | | |
2011 | | /* bound1 > bound2 */ |
2012 | 0 | case 1: |
2013 | 0 | if (cmp_numerics(operand, bound1) > 0) |
2014 | 0 | set_var_from_var(&const_zero, &result_var); |
2015 | 0 | else if (cmp_numerics(operand, bound2) <= 0) |
2016 | 0 | add_var(&count_var, &const_one, &result_var); |
2017 | 0 | else |
2018 | 0 | compute_bucket(operand, bound1, bound2, &count_var, |
2019 | 0 | &result_var); |
2020 | 0 | break; |
2021 | 0 | } |
2022 | | |
2023 | | /* if result exceeds the range of a legal int4, we ereport here */ |
2024 | 0 | if (!numericvar_to_int32(&result_var, &result)) |
2025 | 0 | ereport(ERROR, |
2026 | 0 | (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), |
2027 | 0 | errmsg("integer out of range"))); |
2028 | | |
2029 | 0 | free_var(&count_var); |
2030 | 0 | free_var(&result_var); |
2031 | |
|
2032 | 0 | PG_RETURN_INT32(result); |
2033 | 0 | } |
2034 | | |
2035 | | /* |
2036 | | * 'operand' is inside the bucket range, so determine the correct |
2037 | | * bucket for it to go in. The calculations performed by this function |
2038 | | * are derived directly from the SQL2003 spec. Note however that we |
2039 | | * multiply by count before dividing, to avoid unnecessary roundoff error. |
2040 | | */ |
2041 | | static void |
2042 | | compute_bucket(Numeric operand, Numeric bound1, Numeric bound2, |
2043 | | const NumericVar *count_var, NumericVar *result_var) |
2044 | 0 | { |
2045 | 0 | NumericVar bound1_var; |
2046 | 0 | NumericVar bound2_var; |
2047 | 0 | NumericVar operand_var; |
2048 | |
|
2049 | 0 | init_var_from_num(bound1, &bound1_var); |
2050 | 0 | init_var_from_num(bound2, &bound2_var); |
2051 | 0 | init_var_from_num(operand, &operand_var); |
2052 | | |
2053 | | /* |
2054 | | * Per spec, bound1 is inclusive and bound2 is exclusive, and so we have |
2055 | | * bound1 <= operand < bound2 or bound1 >= operand > bound2. Either way, |
2056 | | * the result is ((operand - bound1) * count) / (bound2 - bound1) + 1, |
2057 | | * where the quotient is computed using floor division (i.e., division to |
2058 | | * zero decimal places with truncation), which guarantees that the result |
2059 | | * is in the range [1, count]. Reversing the bounds doesn't affect the |
2060 | | * computation, because the signs cancel out when dividing. |
2061 | | */ |
2062 | 0 | sub_var(&operand_var, &bound1_var, &operand_var); |
2063 | 0 | sub_var(&bound2_var, &bound1_var, &bound2_var); |
2064 | |
|
2065 | 0 | mul_var(&operand_var, count_var, &operand_var, |
2066 | 0 | operand_var.dscale + count_var->dscale); |
2067 | 0 | div_var(&operand_var, &bound2_var, result_var, 0, false, true); |
2068 | 0 | add_var(result_var, &const_one, result_var); |
2069 | |
|
2070 | 0 | free_var(&bound1_var); |
2071 | 0 | free_var(&bound2_var); |
2072 | 0 | free_var(&operand_var); |
2073 | 0 | } |
2074 | | |
2075 | | /* ---------------------------------------------------------------------- |
2076 | | * |
2077 | | * Comparison functions |
2078 | | * |
2079 | | * Note: btree indexes need these routines not to leak memory; therefore, |
2080 | | * be careful to free working copies of toasted datums. Most places don't |
2081 | | * need to be so careful. |
2082 | | * |
2083 | | * Sort support: |
2084 | | * |
2085 | | * We implement the sortsupport strategy routine in order to get the benefit of |
2086 | | * abbreviation. The ordinary numeric comparison can be quite slow as a result |
2087 | | * of palloc/pfree cycles (due to detoasting packed values for alignment); |
2088 | | * while this could be worked on itself, the abbreviation strategy gives more |
2089 | | * speedup in many common cases. |
2090 | | * |
2091 | | * The abbreviated format is an int64. The representation is negated relative |
2092 | | * to the original value, because we use the largest negative value for NaN, |
2093 | | * which sorts higher than other values. We convert the absolute value of the |
2094 | | * numeric to a 63-bit positive value, and then negate it if the original |
2095 | | * number was positive. |
2096 | | * |
2097 | | * We abort the abbreviation process if the abbreviation cardinality is below |
2098 | | * 0.01% of the row count (1 per 10k non-null rows). The actual break-even |
2099 | | * point is somewhat below that, perhaps 1 per 30k (at 1 per 100k there's a |
2100 | | * very small penalty), but we don't want to build up too many abbreviated |
2101 | | * values before first testing for abort, so we take the slightly pessimistic |
2102 | | * number. We make no attempt to estimate the cardinality of the real values, |
2103 | | * since it plays no part in the cost model here (if the abbreviation is equal, |
2104 | | * the cost of comparing equal and unequal underlying values is comparable). |
2105 | | * We discontinue even checking for abort (saving us the hashing overhead) if |
2106 | | * the estimated cardinality gets to 100k; that would be enough to support many |
2107 | | * billions of rows while doing no worse than breaking even. |
2108 | | * |
2109 | | * ---------------------------------------------------------------------- |
2110 | | */ |
2111 | | |
2112 | | /* |
2113 | | * Sort support strategy routine. |
2114 | | */ |
2115 | | Datum |
2116 | | numeric_sortsupport(PG_FUNCTION_ARGS) |
2117 | 0 | { |
2118 | 0 | SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0); |
2119 | |
|
2120 | 0 | ssup->comparator = numeric_fast_cmp; |
2121 | |
|
2122 | 0 | if (ssup->abbreviate) |
2123 | 0 | { |
2124 | 0 | NumericSortSupport *nss; |
2125 | 0 | MemoryContext oldcontext = MemoryContextSwitchTo(ssup->ssup_cxt); |
2126 | |
|
2127 | 0 | nss = palloc_object(NumericSortSupport); |
2128 | | |
2129 | | /* |
2130 | | * palloc a buffer for handling unaligned packed values in addition to |
2131 | | * the support struct |
2132 | | */ |
2133 | 0 | nss->buf = palloc(VARATT_SHORT_MAX + VARHDRSZ + 1); |
2134 | |
|
2135 | 0 | nss->input_count = 0; |
2136 | 0 | nss->estimating = true; |
2137 | 0 | initHyperLogLog(&nss->abbr_card, 10); |
2138 | |
|
2139 | 0 | ssup->ssup_extra = nss; |
2140 | |
|
2141 | 0 | ssup->abbrev_full_comparator = ssup->comparator; |
2142 | 0 | ssup->comparator = numeric_cmp_abbrev; |
2143 | 0 | ssup->abbrev_converter = numeric_abbrev_convert; |
2144 | 0 | ssup->abbrev_abort = numeric_abbrev_abort; |
2145 | |
|
2146 | 0 | MemoryContextSwitchTo(oldcontext); |
2147 | 0 | } |
2148 | |
|
2149 | 0 | PG_RETURN_VOID(); |
2150 | 0 | } |
2151 | | |
2152 | | /* |
2153 | | * Abbreviate a numeric datum, handling NaNs and detoasting |
2154 | | * (must not leak memory!) |
2155 | | */ |
2156 | | static Datum |
2157 | | numeric_abbrev_convert(Datum original_datum, SortSupport ssup) |
2158 | 0 | { |
2159 | 0 | NumericSortSupport *nss = ssup->ssup_extra; |
2160 | 0 | void *original_varatt = PG_DETOAST_DATUM_PACKED(original_datum); |
2161 | 0 | Numeric value; |
2162 | 0 | Datum result; |
2163 | |
|
2164 | 0 | nss->input_count += 1; |
2165 | | |
2166 | | /* |
2167 | | * This is to handle packed datums without needing a palloc/pfree cycle; |
2168 | | * we keep and reuse a buffer large enough to handle any short datum. |
2169 | | */ |
2170 | 0 | if (VARATT_IS_SHORT(original_varatt)) |
2171 | 0 | { |
2172 | 0 | void *buf = nss->buf; |
2173 | 0 | Size sz = VARSIZE_SHORT(original_varatt) - VARHDRSZ_SHORT; |
2174 | |
|
2175 | 0 | Assert(sz <= VARATT_SHORT_MAX - VARHDRSZ_SHORT); |
2176 | |
|
2177 | 0 | SET_VARSIZE(buf, VARHDRSZ + sz); |
2178 | 0 | memcpy(VARDATA(buf), VARDATA_SHORT(original_varatt), sz); |
2179 | |
|
2180 | 0 | value = (Numeric) buf; |
2181 | 0 | } |
2182 | 0 | else |
2183 | 0 | value = (Numeric) original_varatt; |
2184 | |
|
2185 | 0 | if (NUMERIC_IS_SPECIAL(value)) |
2186 | 0 | { |
2187 | 0 | if (NUMERIC_IS_PINF(value)) |
2188 | 0 | result = NUMERIC_ABBREV_PINF; |
2189 | 0 | else if (NUMERIC_IS_NINF(value)) |
2190 | 0 | result = NUMERIC_ABBREV_NINF; |
2191 | 0 | else |
2192 | 0 | result = NUMERIC_ABBREV_NAN; |
2193 | 0 | } |
2194 | 0 | else |
2195 | 0 | { |
2196 | 0 | NumericVar var; |
2197 | |
|
2198 | 0 | init_var_from_num(value, &var); |
2199 | |
|
2200 | 0 | result = numeric_abbrev_convert_var(&var, nss); |
2201 | 0 | } |
2202 | | |
2203 | | /* should happen only for external/compressed toasts */ |
2204 | 0 | if (original_varatt != DatumGetPointer(original_datum)) |
2205 | 0 | pfree(original_varatt); |
2206 | |
|
2207 | 0 | return result; |
2208 | 0 | } |
2209 | | |
2210 | | /* |
2211 | | * Consider whether to abort abbreviation. |
2212 | | * |
2213 | | * We pay no attention to the cardinality of the non-abbreviated data. There is |
2214 | | * no reason to do so: unlike text, we have no fast check for equal values, so |
2215 | | * we pay the full overhead whenever the abbreviations are equal regardless of |
2216 | | * whether the underlying values are also equal. |
2217 | | */ |
2218 | | static bool |
2219 | | numeric_abbrev_abort(int memtupcount, SortSupport ssup) |
2220 | | { |
2221 | | NumericSortSupport *nss = ssup->ssup_extra; |
2222 | | double abbr_card; |
2223 | | |
2224 | | if (memtupcount < 10000 || nss->input_count < 10000 || !nss->estimating) |
2225 | | return false; |
2226 | | |
2227 | | abbr_card = estimateHyperLogLog(&nss->abbr_card); |
2228 | | |
2229 | | /* |
2230 | | * If we have >100k distinct values, then even if we were sorting many |
2231 | | * billion rows we'd likely still break even, and the penalty of undoing |
2232 | | * that many rows of abbrevs would probably not be worth it. Stop even |
2233 | | * counting at that point. |
2234 | | */ |
2235 | | if (abbr_card > 100000.0) |
2236 | | { |
2237 | | if (trace_sort) |
2238 | | elog(LOG, |
2239 | | "numeric_abbrev: estimation ends at cardinality %f" |
2240 | | " after " INT64_FORMAT " values (%d rows)", |
2241 | | abbr_card, nss->input_count, memtupcount); |
2242 | | nss->estimating = false; |
2243 | | return false; |
2244 | | } |
2245 | | |
2246 | | /* |
2247 | | * Target minimum cardinality is 1 per ~10k of non-null inputs. (The |
2248 | | * break even point is somewhere between one per 100k rows, where |
2249 | | * abbreviation has a very slight penalty, and 1 per 10k where it wins by |
2250 | | * a measurable percentage.) We use the relatively pessimistic 10k |
2251 | | * threshold, and add a 0.5 row fudge factor, because it allows us to |
2252 | | * abort earlier on genuinely pathological data where we've had exactly |
2253 | | * one abbreviated value in the first 10k (non-null) rows. |
2254 | | */ |
2255 | | if (abbr_card < nss->input_count / 10000.0 + 0.5) |
2256 | | { |
2257 | | if (trace_sort) |
2258 | | elog(LOG, |
2259 | | "numeric_abbrev: aborting abbreviation at cardinality %f" |
2260 | | " below threshold %f after " INT64_FORMAT " values (%d rows)", |
2261 | | abbr_card, nss->input_count / 10000.0 + 0.5, |
2262 | | nss->input_count, memtupcount); |
2263 | | return true; |
2264 | | } |
2265 | | |
2266 | | if (trace_sort) |
2267 | | elog(LOG, |
2268 | | "numeric_abbrev: cardinality %f" |
2269 | | " after " INT64_FORMAT " values (%d rows)", |
2270 | | abbr_card, nss->input_count, memtupcount); |
2271 | | |
2272 | | return false; |
2273 | | } |
2274 | | |
2275 | | /* |
2276 | | * Non-fmgr interface to the comparison routine to allow sortsupport to elide |
2277 | | * the fmgr call. The saving here is small given how slow numeric comparisons |
2278 | | * are, but it is a required part of the sort support API when abbreviations |
2279 | | * are performed. |
2280 | | * |
2281 | | * Two palloc/pfree cycles could be saved here by using persistent buffers for |
2282 | | * aligning short-varlena inputs, but this has not so far been considered to |
2283 | | * be worth the effort. |
2284 | | */ |
2285 | | static int |
2286 | | numeric_fast_cmp(Datum x, Datum y, SortSupport ssup) |
2287 | 0 | { |
2288 | 0 | Numeric nx = DatumGetNumeric(x); |
2289 | 0 | Numeric ny = DatumGetNumeric(y); |
2290 | 0 | int result; |
2291 | |
|
2292 | 0 | result = cmp_numerics(nx, ny); |
2293 | |
|
2294 | 0 | if (nx != DatumGetPointer(x)) |
2295 | 0 | pfree(nx); |
2296 | 0 | if (ny != DatumGetPointer(y)) |
2297 | 0 | pfree(ny); |
2298 | |
|
2299 | 0 | return result; |
2300 | 0 | } |
2301 | | |
2302 | | /* |
2303 | | * Compare abbreviations of values. (Abbreviations may be equal where the true |
2304 | | * values differ, but if the abbreviations differ, they must reflect the |
2305 | | * ordering of the true values.) |
2306 | | */ |
2307 | | static int |
2308 | | numeric_cmp_abbrev(Datum x, Datum y, SortSupport ssup) |
2309 | 0 | { |
2310 | | /* |
2311 | | * NOTE WELL: this is intentionally backwards, because the abbreviation is |
2312 | | * negated relative to the original value, to handle NaN/infinity cases. |
2313 | | */ |
2314 | 0 | if (DatumGetNumericAbbrev(x) < DatumGetNumericAbbrev(y)) |
2315 | 0 | return 1; |
2316 | 0 | if (DatumGetNumericAbbrev(x) > DatumGetNumericAbbrev(y)) |
2317 | 0 | return -1; |
2318 | 0 | return 0; |
2319 | 0 | } |
2320 | | |
2321 | | /* |
2322 | | * Abbreviate a NumericVar into the 64-bit sortsupport size. |
2323 | | * |
2324 | | * The 31-bit value is constructed as: |
2325 | | * |
2326 | | * 0 + 7bits digit weight + 24 bits digit value |
2327 | | * |
2328 | | * where the digit weight is in single decimal digits, not digit words, and |
2329 | | * stored in excess-44 representation[1]. The 24-bit digit value is the 7 most |
2330 | | * significant decimal digits of the value converted to binary. Values whose |
2331 | | * weights would fall outside the representable range are rounded off to zero |
2332 | | * (which is also used to represent actual zeros) or to 0x7FFFFFFF (which |
2333 | | * otherwise cannot occur). Abbreviation therefore fails to gain any advantage |
2334 | | * where values are outside the range 10^-44 to 10^83, which is not considered |
2335 | | * to be a serious limitation, or when values are of the same magnitude and |
2336 | | * equal in the first 7 decimal digits, which is considered to be an |
2337 | | * unavoidable limitation given the available bits. (Stealing three more bits |
2338 | | * to compare another digit would narrow the range of representable weights by |
2339 | | * a factor of 8, which starts to look like a real limiting factor.) |
2340 | | * |
2341 | | * (The value 44 for the excess is essentially arbitrary) |
2342 | | * |
2343 | | * The 63-bit value is constructed as: |
2344 | | * |
2345 | | * 0 + 7bits weight + 4 x 14-bit packed digit words |
2346 | | * |
2347 | | * The weight in this case is again stored in excess-44, but this time it is |
2348 | | * the original weight in digit words (i.e. powers of 10000). The first four |
2349 | | * digit words of the value (if present; trailing zeros are assumed as needed) |
2350 | | * are packed into 14 bits each to form the rest of the value. Again, |
2351 | | * out-of-range values are rounded off to 0 or 0x7FFFFFFFFFFFFFFF. The |
2352 | | * representable range in this case is 10^-176 to 10^332, which is considered |
2353 | | * to be good enough for all practical purposes, and comparison of 4 words |
2354 | | * means that at least 13 decimal digits are compared, which is considered to |
2355 | | * be a reasonable compromise between effectiveness and efficiency in computing |
2356 | | * the abbreviation. |
2357 | | * |
2358 | | * (The value 44 for the excess is even more arbitrary here, it was chosen just |
2359 | | * to match the value used in the 31-bit case) |
2360 | | * |
2361 | | * [1] - Excess-k representation means that the value is offset by adding 'k' |
2362 | | * and then treated as unsigned, so the smallest representable value is stored |
2363 | | * with all bits zero. This allows simple comparisons to work on the composite |
2364 | | * value. |
2365 | | */ |
2366 | | static Datum |
2367 | | numeric_abbrev_convert_var(const NumericVar *var, NumericSortSupport *nss) |
2368 | 0 | { |
2369 | 0 | int ndigits = var->ndigits; |
2370 | 0 | int weight = var->weight; |
2371 | 0 | int64 result; |
2372 | |
|
2373 | 0 | if (ndigits == 0 || weight < -44) |
2374 | 0 | { |
2375 | 0 | result = 0; |
2376 | 0 | } |
2377 | 0 | else if (weight > 83) |
2378 | 0 | { |
2379 | 0 | result = PG_INT64_MAX; |
2380 | 0 | } |
2381 | 0 | else |
2382 | 0 | { |
2383 | 0 | result = ((int64) (weight + 44) << 56); |
2384 | |
|
2385 | 0 | switch (ndigits) |
2386 | 0 | { |
2387 | 0 | default: |
2388 | 0 | result |= ((int64) var->digits[3]); |
2389 | 0 | pg_fallthrough; |
2390 | 0 | case 3: |
2391 | 0 | result |= ((int64) var->digits[2]) << 14; |
2392 | 0 | pg_fallthrough; |
2393 | 0 | case 2: |
2394 | 0 | result |= ((int64) var->digits[1]) << 28; |
2395 | 0 | pg_fallthrough; |
2396 | 0 | case 1: |
2397 | 0 | result |= ((int64) var->digits[0]) << 42; |
2398 | 0 | break; |
2399 | 0 | } |
2400 | 0 | } |
2401 | | |
2402 | | /* the abbrev is negated relative to the original */ |
2403 | 0 | if (var->sign == NUMERIC_POS) |
2404 | 0 | result = -result; |
2405 | |
|
2406 | 0 | if (nss->estimating) |
2407 | 0 | addHyperLogLog(&nss->abbr_card, |
2408 | 0 | (uint32) murmurhash64((uint64) result)); |
2409 | |
|
2410 | 0 | return NumericAbbrevGetDatum(result); |
2411 | 0 | } |
2412 | | |
2413 | | |
2414 | | /* |
2415 | | * Ordinary (non-sortsupport) comparisons follow. |
2416 | | */ |
2417 | | |
2418 | | Datum |
2419 | | numeric_cmp(PG_FUNCTION_ARGS) |
2420 | 0 | { |
2421 | 0 | Numeric num1 = PG_GETARG_NUMERIC(0); |
2422 | 0 | Numeric num2 = PG_GETARG_NUMERIC(1); |
2423 | 0 | int result; |
2424 | |
|
2425 | 0 | result = cmp_numerics(num1, num2); |
2426 | |
|
2427 | 0 | PG_FREE_IF_COPY(num1, 0); |
2428 | 0 | PG_FREE_IF_COPY(num2, 1); |
2429 | |
|
2430 | 0 | PG_RETURN_INT32(result); |
2431 | 0 | } |
2432 | | |
2433 | | |
2434 | | Datum |
2435 | | numeric_eq(PG_FUNCTION_ARGS) |
2436 | 0 | { |
2437 | 0 | Numeric num1 = PG_GETARG_NUMERIC(0); |
2438 | 0 | Numeric num2 = PG_GETARG_NUMERIC(1); |
2439 | 0 | bool result; |
2440 | |
|
2441 | 0 | result = cmp_numerics(num1, num2) == 0; |
2442 | |
|
2443 | 0 | PG_FREE_IF_COPY(num1, 0); |
2444 | 0 | PG_FREE_IF_COPY(num2, 1); |
2445 | |
|
2446 | 0 | PG_RETURN_BOOL(result); |
2447 | 0 | } |
2448 | | |
2449 | | Datum |
2450 | | numeric_ne(PG_FUNCTION_ARGS) |
2451 | 0 | { |
2452 | 0 | Numeric num1 = PG_GETARG_NUMERIC(0); |
2453 | 0 | Numeric num2 = PG_GETARG_NUMERIC(1); |
2454 | 0 | bool result; |
2455 | |
|
2456 | 0 | result = cmp_numerics(num1, num2) != 0; |
2457 | |
|
2458 | 0 | PG_FREE_IF_COPY(num1, 0); |
2459 | 0 | PG_FREE_IF_COPY(num2, 1); |
2460 | |
|
2461 | 0 | PG_RETURN_BOOL(result); |
2462 | 0 | } |
2463 | | |
2464 | | Datum |
2465 | | numeric_gt(PG_FUNCTION_ARGS) |
2466 | 0 | { |
2467 | 0 | Numeric num1 = PG_GETARG_NUMERIC(0); |
2468 | 0 | Numeric num2 = PG_GETARG_NUMERIC(1); |
2469 | 0 | bool result; |
2470 | |
|
2471 | 0 | result = cmp_numerics(num1, num2) > 0; |
2472 | |
|
2473 | 0 | PG_FREE_IF_COPY(num1, 0); |
2474 | 0 | PG_FREE_IF_COPY(num2, 1); |
2475 | |
|
2476 | 0 | PG_RETURN_BOOL(result); |
2477 | 0 | } |
2478 | | |
2479 | | Datum |
2480 | | numeric_ge(PG_FUNCTION_ARGS) |
2481 | 0 | { |
2482 | 0 | Numeric num1 = PG_GETARG_NUMERIC(0); |
2483 | 0 | Numeric num2 = PG_GETARG_NUMERIC(1); |
2484 | 0 | bool result; |
2485 | |
|
2486 | 0 | result = cmp_numerics(num1, num2) >= 0; |
2487 | |
|
2488 | 0 | PG_FREE_IF_COPY(num1, 0); |
2489 | 0 | PG_FREE_IF_COPY(num2, 1); |
2490 | |
|
2491 | 0 | PG_RETURN_BOOL(result); |
2492 | 0 | } |
2493 | | |
2494 | | Datum |
2495 | | numeric_lt(PG_FUNCTION_ARGS) |
2496 | 0 | { |
2497 | 0 | Numeric num1 = PG_GETARG_NUMERIC(0); |
2498 | 0 | Numeric num2 = PG_GETARG_NUMERIC(1); |
2499 | 0 | bool result; |
2500 | |
|
2501 | 0 | result = cmp_numerics(num1, num2) < 0; |
2502 | |
|
2503 | 0 | PG_FREE_IF_COPY(num1, 0); |
2504 | 0 | PG_FREE_IF_COPY(num2, 1); |
2505 | |
|
2506 | 0 | PG_RETURN_BOOL(result); |
2507 | 0 | } |
2508 | | |
2509 | | Datum |
2510 | | numeric_le(PG_FUNCTION_ARGS) |
2511 | 0 | { |
2512 | 0 | Numeric num1 = PG_GETARG_NUMERIC(0); |
2513 | 0 | Numeric num2 = PG_GETARG_NUMERIC(1); |
2514 | 0 | bool result; |
2515 | |
|
2516 | 0 | result = cmp_numerics(num1, num2) <= 0; |
2517 | |
|
2518 | 0 | PG_FREE_IF_COPY(num1, 0); |
2519 | 0 | PG_FREE_IF_COPY(num2, 1); |
2520 | |
|
2521 | 0 | PG_RETURN_BOOL(result); |
2522 | 0 | } |
2523 | | |
2524 | | static int |
2525 | | cmp_numerics(Numeric num1, Numeric num2) |
2526 | 0 | { |
2527 | 0 | int result; |
2528 | | |
2529 | | /* |
2530 | | * We consider all NANs to be equal and larger than any non-NAN (including |
2531 | | * Infinity). This is somewhat arbitrary; the important thing is to have |
2532 | | * a consistent sort order. |
2533 | | */ |
2534 | 0 | if (NUMERIC_IS_SPECIAL(num1)) |
2535 | 0 | { |
2536 | 0 | if (NUMERIC_IS_NAN(num1)) |
2537 | 0 | { |
2538 | 0 | if (NUMERIC_IS_NAN(num2)) |
2539 | 0 | result = 0; /* NAN = NAN */ |
2540 | 0 | else |
2541 | 0 | result = 1; /* NAN > non-NAN */ |
2542 | 0 | } |
2543 | 0 | else if (NUMERIC_IS_PINF(num1)) |
2544 | 0 | { |
2545 | 0 | if (NUMERIC_IS_NAN(num2)) |
2546 | 0 | result = -1; /* PINF < NAN */ |
2547 | 0 | else if (NUMERIC_IS_PINF(num2)) |
2548 | 0 | result = 0; /* PINF = PINF */ |
2549 | 0 | else |
2550 | 0 | result = 1; /* PINF > anything else */ |
2551 | 0 | } |
2552 | 0 | else /* num1 must be NINF */ |
2553 | 0 | { |
2554 | 0 | if (NUMERIC_IS_NINF(num2)) |
2555 | 0 | result = 0; /* NINF = NINF */ |
2556 | 0 | else |
2557 | 0 | result = -1; /* NINF < anything else */ |
2558 | 0 | } |
2559 | 0 | } |
2560 | 0 | else if (NUMERIC_IS_SPECIAL(num2)) |
2561 | 0 | { |
2562 | 0 | if (NUMERIC_IS_NINF(num2)) |
2563 | 0 | result = 1; /* normal > NINF */ |
2564 | 0 | else |
2565 | 0 | result = -1; /* normal < NAN or PINF */ |
2566 | 0 | } |
2567 | 0 | else |
2568 | 0 | { |
2569 | 0 | result = cmp_var_common(NUMERIC_DIGITS(num1), NUMERIC_NDIGITS(num1), |
2570 | 0 | NUMERIC_WEIGHT(num1), NUMERIC_SIGN(num1), |
2571 | 0 | NUMERIC_DIGITS(num2), NUMERIC_NDIGITS(num2), |
2572 | 0 | NUMERIC_WEIGHT(num2), NUMERIC_SIGN(num2)); |
2573 | 0 | } |
2574 | |
|
2575 | 0 | return result; |
2576 | 0 | } |
2577 | | |
2578 | | /* |
2579 | | * in_range support function for numeric. |
2580 | | */ |
2581 | | Datum |
2582 | | in_range_numeric_numeric(PG_FUNCTION_ARGS) |
2583 | 0 | { |
2584 | 0 | Numeric val = PG_GETARG_NUMERIC(0); |
2585 | 0 | Numeric base = PG_GETARG_NUMERIC(1); |
2586 | 0 | Numeric offset = PG_GETARG_NUMERIC(2); |
2587 | 0 | bool sub = PG_GETARG_BOOL(3); |
2588 | 0 | bool less = PG_GETARG_BOOL(4); |
2589 | 0 | bool result; |
2590 | | |
2591 | | /* |
2592 | | * Reject negative (including -Inf) or NaN offset. Negative is per spec, |
2593 | | * and NaN is because appropriate semantics for that seem non-obvious. |
2594 | | */ |
2595 | 0 | if (NUMERIC_IS_NAN(offset) || |
2596 | 0 | NUMERIC_IS_NINF(offset) || |
2597 | 0 | NUMERIC_SIGN(offset) == NUMERIC_NEG) |
2598 | 0 | ereport(ERROR, |
2599 | 0 | (errcode(ERRCODE_INVALID_PRECEDING_OR_FOLLOWING_SIZE), |
2600 | 0 | errmsg("invalid preceding or following size in window function"))); |
2601 | | |
2602 | | /* |
2603 | | * Deal with cases where val and/or base is NaN, following the rule that |
2604 | | * NaN sorts after non-NaN (cf cmp_numerics). The offset cannot affect |
2605 | | * the conclusion. |
2606 | | */ |
2607 | 0 | if (NUMERIC_IS_NAN(val)) |
2608 | 0 | { |
2609 | 0 | if (NUMERIC_IS_NAN(base)) |
2610 | 0 | result = true; /* NAN = NAN */ |
2611 | 0 | else |
2612 | 0 | result = !less; /* NAN > non-NAN */ |
2613 | 0 | } |
2614 | 0 | else if (NUMERIC_IS_NAN(base)) |
2615 | 0 | { |
2616 | 0 | result = less; /* non-NAN < NAN */ |
2617 | 0 | } |
2618 | | |
2619 | | /* |
2620 | | * Deal with infinite offset (necessarily +Inf, at this point). |
2621 | | */ |
2622 | 0 | else if (NUMERIC_IS_SPECIAL(offset)) |
2623 | 0 | { |
2624 | 0 | Assert(NUMERIC_IS_PINF(offset)); |
2625 | 0 | if (sub ? NUMERIC_IS_PINF(base) : NUMERIC_IS_NINF(base)) |
2626 | 0 | { |
2627 | | /* |
2628 | | * base +/- offset would produce NaN, so return true for any val |
2629 | | * (see in_range_float8_float8() for reasoning). |
2630 | | */ |
2631 | 0 | result = true; |
2632 | 0 | } |
2633 | 0 | else if (sub) |
2634 | 0 | { |
2635 | | /* base - offset must be -inf */ |
2636 | 0 | if (less) |
2637 | 0 | result = NUMERIC_IS_NINF(val); /* only -inf is <= sum */ |
2638 | 0 | else |
2639 | 0 | result = true; /* any val is >= sum */ |
2640 | 0 | } |
2641 | 0 | else |
2642 | 0 | { |
2643 | | /* base + offset must be +inf */ |
2644 | 0 | if (less) |
2645 | 0 | result = true; /* any val is <= sum */ |
2646 | 0 | else |
2647 | 0 | result = NUMERIC_IS_PINF(val); /* only +inf is >= sum */ |
2648 | 0 | } |
2649 | 0 | } |
2650 | | |
2651 | | /* |
2652 | | * Deal with cases where val and/or base is infinite. The offset, being |
2653 | | * now known finite, cannot affect the conclusion. |
2654 | | */ |
2655 | 0 | else if (NUMERIC_IS_SPECIAL(val)) |
2656 | 0 | { |
2657 | 0 | if (NUMERIC_IS_PINF(val)) |
2658 | 0 | { |
2659 | 0 | if (NUMERIC_IS_PINF(base)) |
2660 | 0 | result = true; /* PINF = PINF */ |
2661 | 0 | else |
2662 | 0 | result = !less; /* PINF > any other non-NAN */ |
2663 | 0 | } |
2664 | 0 | else /* val must be NINF */ |
2665 | 0 | { |
2666 | 0 | if (NUMERIC_IS_NINF(base)) |
2667 | 0 | result = true; /* NINF = NINF */ |
2668 | 0 | else |
2669 | 0 | result = less; /* NINF < anything else */ |
2670 | 0 | } |
2671 | 0 | } |
2672 | 0 | else if (NUMERIC_IS_SPECIAL(base)) |
2673 | 0 | { |
2674 | 0 | if (NUMERIC_IS_NINF(base)) |
2675 | 0 | result = !less; /* normal > NINF */ |
2676 | 0 | else |
2677 | 0 | result = less; /* normal < PINF */ |
2678 | 0 | } |
2679 | 0 | else |
2680 | 0 | { |
2681 | | /* |
2682 | | * Otherwise go ahead and compute base +/- offset. While it's |
2683 | | * possible for this to overflow the numeric format, it's unlikely |
2684 | | * enough that we don't take measures to prevent it. |
2685 | | */ |
2686 | 0 | NumericVar valv; |
2687 | 0 | NumericVar basev; |
2688 | 0 | NumericVar offsetv; |
2689 | 0 | NumericVar sum; |
2690 | |
|
2691 | 0 | init_var_from_num(val, &valv); |
2692 | 0 | init_var_from_num(base, &basev); |
2693 | 0 | init_var_from_num(offset, &offsetv); |
2694 | 0 | init_var(&sum); |
2695 | |
|
2696 | 0 | if (sub) |
2697 | 0 | sub_var(&basev, &offsetv, &sum); |
2698 | 0 | else |
2699 | 0 | add_var(&basev, &offsetv, &sum); |
2700 | |
|
2701 | 0 | if (less) |
2702 | 0 | result = (cmp_var(&valv, &sum) <= 0); |
2703 | 0 | else |
2704 | 0 | result = (cmp_var(&valv, &sum) >= 0); |
2705 | |
|
2706 | 0 | free_var(&sum); |
2707 | 0 | } |
2708 | |
|
2709 | 0 | PG_FREE_IF_COPY(val, 0); |
2710 | 0 | PG_FREE_IF_COPY(base, 1); |
2711 | 0 | PG_FREE_IF_COPY(offset, 2); |
2712 | |
|
2713 | 0 | PG_RETURN_BOOL(result); |
2714 | 0 | } |
2715 | | |
2716 | | Datum |
2717 | | hash_numeric(PG_FUNCTION_ARGS) |
2718 | 0 | { |
2719 | 0 | Numeric key = PG_GETARG_NUMERIC(0); |
2720 | 0 | uint32 digit_hash; |
2721 | 0 | uint32 result; |
2722 | 0 | int weight; |
2723 | 0 | int start_offset; |
2724 | 0 | int end_offset; |
2725 | 0 | int i; |
2726 | 0 | int hash_len; |
2727 | 0 | NumericDigit *digits; |
2728 | | |
2729 | | /* If it's NaN or infinity, don't try to hash the rest of the fields */ |
2730 | 0 | if (NUMERIC_IS_SPECIAL(key)) |
2731 | 0 | PG_RETURN_UINT32(0); |
2732 | | |
2733 | 0 | weight = NUMERIC_WEIGHT(key); |
2734 | 0 | start_offset = 0; |
2735 | 0 | end_offset = 0; |
2736 | | |
2737 | | /* |
2738 | | * Omit any leading or trailing zeros from the input to the hash. The |
2739 | | * numeric implementation *should* guarantee that leading and trailing |
2740 | | * zeros are suppressed, but we're paranoid. Note that we measure the |
2741 | | * starting and ending offsets in units of NumericDigits, not bytes. |
2742 | | */ |
2743 | 0 | digits = NUMERIC_DIGITS(key); |
2744 | 0 | for (i = 0; i < NUMERIC_NDIGITS(key); i++) |
2745 | 0 | { |
2746 | 0 | if (digits[i] != (NumericDigit) 0) |
2747 | 0 | break; |
2748 | | |
2749 | 0 | start_offset++; |
2750 | | |
2751 | | /* |
2752 | | * The weight is effectively the # of digits before the decimal point, |
2753 | | * so decrement it for each leading zero we skip. |
2754 | | */ |
2755 | 0 | weight--; |
2756 | 0 | } |
2757 | | |
2758 | | /* |
2759 | | * If there are no non-zero digits, then the value of the number is zero, |
2760 | | * regardless of any other fields. |
2761 | | */ |
2762 | 0 | if (NUMERIC_NDIGITS(key) == start_offset) |
2763 | 0 | PG_RETURN_UINT32(-1); |
2764 | | |
2765 | 0 | for (i = NUMERIC_NDIGITS(key) - 1; i >= 0; i--) |
2766 | 0 | { |
2767 | 0 | if (digits[i] != (NumericDigit) 0) |
2768 | 0 | break; |
2769 | | |
2770 | 0 | end_offset++; |
2771 | 0 | } |
2772 | | |
2773 | | /* If we get here, there should be at least one non-zero digit */ |
2774 | 0 | Assert(start_offset + end_offset < NUMERIC_NDIGITS(key)); |
2775 | | |
2776 | | /* |
2777 | | * Note that we don't hash on the Numeric's scale, since two numerics can |
2778 | | * compare equal but have different scales. We also don't hash on the |
2779 | | * sign, although we could: since a sign difference implies inequality, |
2780 | | * this shouldn't affect correctness. |
2781 | | */ |
2782 | 0 | hash_len = NUMERIC_NDIGITS(key) - start_offset - end_offset; |
2783 | 0 | digit_hash = hash_bytes((unsigned char *) (NUMERIC_DIGITS(key) |
2784 | 0 | + start_offset), |
2785 | 0 | hash_len * sizeof(NumericDigit)); |
2786 | | |
2787 | | /* Mix in the weight, via XOR */ |
2788 | 0 | result = digit_hash ^ weight; |
2789 | |
|
2790 | 0 | PG_RETURN_UINT32(result); |
2791 | 0 | } |
2792 | | |
2793 | | /* |
2794 | | * Returns 64-bit value by hashing a value to a 64-bit value, with a seed. |
2795 | | * Otherwise, similar to hash_numeric. |
2796 | | */ |
2797 | | Datum |
2798 | | hash_numeric_extended(PG_FUNCTION_ARGS) |
2799 | 0 | { |
2800 | 0 | Numeric key = PG_GETARG_NUMERIC(0); |
2801 | 0 | uint64 seed = PG_GETARG_INT64(1); |
2802 | 0 | uint64 digit_hash; |
2803 | 0 | uint64 result; |
2804 | 0 | int weight; |
2805 | 0 | int start_offset; |
2806 | 0 | int end_offset; |
2807 | 0 | int i; |
2808 | 0 | int hash_len; |
2809 | 0 | NumericDigit *digits; |
2810 | | |
2811 | | /* If it's NaN or infinity, don't try to hash the rest of the fields */ |
2812 | 0 | if (NUMERIC_IS_SPECIAL(key)) |
2813 | 0 | PG_RETURN_UINT64(seed); |
2814 | | |
2815 | 0 | weight = NUMERIC_WEIGHT(key); |
2816 | 0 | start_offset = 0; |
2817 | 0 | end_offset = 0; |
2818 | |
|
2819 | 0 | digits = NUMERIC_DIGITS(key); |
2820 | 0 | for (i = 0; i < NUMERIC_NDIGITS(key); i++) |
2821 | 0 | { |
2822 | 0 | if (digits[i] != (NumericDigit) 0) |
2823 | 0 | break; |
2824 | | |
2825 | 0 | start_offset++; |
2826 | |
|
2827 | 0 | weight--; |
2828 | 0 | } |
2829 | |
|
2830 | 0 | if (NUMERIC_NDIGITS(key) == start_offset) |
2831 | 0 | PG_RETURN_UINT64(seed - 1); |
2832 | | |
2833 | 0 | for (i = NUMERIC_NDIGITS(key) - 1; i >= 0; i--) |
2834 | 0 | { |
2835 | 0 | if (digits[i] != (NumericDigit) 0) |
2836 | 0 | break; |
2837 | | |
2838 | 0 | end_offset++; |
2839 | 0 | } |
2840 | |
|
2841 | 0 | Assert(start_offset + end_offset < NUMERIC_NDIGITS(key)); |
2842 | |
|
2843 | 0 | hash_len = NUMERIC_NDIGITS(key) - start_offset - end_offset; |
2844 | 0 | digit_hash = hash_bytes_extended((unsigned char *) (NUMERIC_DIGITS(key) |
2845 | 0 | + start_offset), |
2846 | 0 | hash_len * sizeof(NumericDigit), |
2847 | 0 | seed); |
2848 | |
|
2849 | 0 | result = digit_hash ^ weight; |
2850 | |
|
2851 | 0 | PG_RETURN_UINT64(result); |
2852 | 0 | } |
2853 | | |
2854 | | |
2855 | | /* ---------------------------------------------------------------------- |
2856 | | * |
2857 | | * Basic arithmetic functions |
2858 | | * |
2859 | | * ---------------------------------------------------------------------- |
2860 | | */ |
2861 | | |
2862 | | |
2863 | | /* |
2864 | | * numeric_add() - |
2865 | | * |
2866 | | * Add two numerics |
2867 | | */ |
2868 | | Datum |
2869 | | numeric_add(PG_FUNCTION_ARGS) |
2870 | 0 | { |
2871 | 0 | Numeric num1 = PG_GETARG_NUMERIC(0); |
2872 | 0 | Numeric num2 = PG_GETARG_NUMERIC(1); |
2873 | 0 | Numeric res; |
2874 | |
|
2875 | 0 | res = numeric_add_safe(num1, num2, NULL); |
2876 | |
|
2877 | 0 | PG_RETURN_NUMERIC(res); |
2878 | 0 | } |
2879 | | |
2880 | | /* |
2881 | | * numeric_add_safe() - |
2882 | | * |
2883 | | * Internal version of numeric_add() with support for soft error reporting. |
2884 | | */ |
2885 | | Numeric |
2886 | | numeric_add_safe(Numeric num1, Numeric num2, Node *escontext) |
2887 | 0 | { |
2888 | 0 | NumericVar arg1; |
2889 | 0 | NumericVar arg2; |
2890 | 0 | NumericVar result; |
2891 | 0 | Numeric res; |
2892 | | |
2893 | | /* |
2894 | | * Handle NaN and infinities |
2895 | | */ |
2896 | 0 | if (NUMERIC_IS_SPECIAL(num1) || NUMERIC_IS_SPECIAL(num2)) |
2897 | 0 | { |
2898 | 0 | if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2)) |
2899 | 0 | return make_result(&const_nan); |
2900 | 0 | if (NUMERIC_IS_PINF(num1)) |
2901 | 0 | { |
2902 | 0 | if (NUMERIC_IS_NINF(num2)) |
2903 | 0 | return make_result(&const_nan); /* Inf + -Inf */ |
2904 | 0 | else |
2905 | 0 | return make_result(&const_pinf); |
2906 | 0 | } |
2907 | 0 | if (NUMERIC_IS_NINF(num1)) |
2908 | 0 | { |
2909 | 0 | if (NUMERIC_IS_PINF(num2)) |
2910 | 0 | return make_result(&const_nan); /* -Inf + Inf */ |
2911 | 0 | else |
2912 | 0 | return make_result(&const_ninf); |
2913 | 0 | } |
2914 | | /* by here, num1 must be finite, so num2 is not */ |
2915 | 0 | if (NUMERIC_IS_PINF(num2)) |
2916 | 0 | return make_result(&const_pinf); |
2917 | 0 | Assert(NUMERIC_IS_NINF(num2)); |
2918 | 0 | return make_result(&const_ninf); |
2919 | 0 | } |
2920 | | |
2921 | | /* |
2922 | | * Unpack the values, let add_var() compute the result and return it. |
2923 | | */ |
2924 | 0 | init_var_from_num(num1, &arg1); |
2925 | 0 | init_var_from_num(num2, &arg2); |
2926 | |
|
2927 | 0 | init_var(&result); |
2928 | 0 | add_var(&arg1, &arg2, &result); |
2929 | |
|
2930 | 0 | res = make_result_safe(&result, escontext); |
2931 | |
|
2932 | 0 | free_var(&result); |
2933 | |
|
2934 | 0 | return res; |
2935 | 0 | } |
2936 | | |
2937 | | |
2938 | | /* |
2939 | | * numeric_sub() - |
2940 | | * |
2941 | | * Subtract one numeric from another |
2942 | | */ |
2943 | | Datum |
2944 | | numeric_sub(PG_FUNCTION_ARGS) |
2945 | 0 | { |
2946 | 0 | Numeric num1 = PG_GETARG_NUMERIC(0); |
2947 | 0 | Numeric num2 = PG_GETARG_NUMERIC(1); |
2948 | 0 | Numeric res; |
2949 | |
|
2950 | 0 | res = numeric_sub_safe(num1, num2, NULL); |
2951 | |
|
2952 | 0 | PG_RETURN_NUMERIC(res); |
2953 | 0 | } |
2954 | | |
2955 | | |
2956 | | /* |
2957 | | * numeric_sub_safe() - |
2958 | | * |
2959 | | * Internal version of numeric_sub() with support for soft error reporting. |
2960 | | */ |
2961 | | Numeric |
2962 | | numeric_sub_safe(Numeric num1, Numeric num2, Node *escontext) |
2963 | 0 | { |
2964 | 0 | NumericVar arg1; |
2965 | 0 | NumericVar arg2; |
2966 | 0 | NumericVar result; |
2967 | 0 | Numeric res; |
2968 | | |
2969 | | /* |
2970 | | * Handle NaN and infinities |
2971 | | */ |
2972 | 0 | if (NUMERIC_IS_SPECIAL(num1) || NUMERIC_IS_SPECIAL(num2)) |
2973 | 0 | { |
2974 | 0 | if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2)) |
2975 | 0 | return make_result(&const_nan); |
2976 | 0 | if (NUMERIC_IS_PINF(num1)) |
2977 | 0 | { |
2978 | 0 | if (NUMERIC_IS_PINF(num2)) |
2979 | 0 | return make_result(&const_nan); /* Inf - Inf */ |
2980 | 0 | else |
2981 | 0 | return make_result(&const_pinf); |
2982 | 0 | } |
2983 | 0 | if (NUMERIC_IS_NINF(num1)) |
2984 | 0 | { |
2985 | 0 | if (NUMERIC_IS_NINF(num2)) |
2986 | 0 | return make_result(&const_nan); /* -Inf - -Inf */ |
2987 | 0 | else |
2988 | 0 | return make_result(&const_ninf); |
2989 | 0 | } |
2990 | | /* by here, num1 must be finite, so num2 is not */ |
2991 | 0 | if (NUMERIC_IS_PINF(num2)) |
2992 | 0 | return make_result(&const_ninf); |
2993 | 0 | Assert(NUMERIC_IS_NINF(num2)); |
2994 | 0 | return make_result(&const_pinf); |
2995 | 0 | } |
2996 | | |
2997 | | /* |
2998 | | * Unpack the values, let sub_var() compute the result and return it. |
2999 | | */ |
3000 | 0 | init_var_from_num(num1, &arg1); |
3001 | 0 | init_var_from_num(num2, &arg2); |
3002 | |
|
3003 | 0 | init_var(&result); |
3004 | 0 | sub_var(&arg1, &arg2, &result); |
3005 | |
|
3006 | 0 | res = make_result_safe(&result, escontext); |
3007 | |
|
3008 | 0 | free_var(&result); |
3009 | |
|
3010 | 0 | return res; |
3011 | 0 | } |
3012 | | |
3013 | | |
3014 | | /* |
3015 | | * numeric_mul() - |
3016 | | * |
3017 | | * Calculate the product of two numerics |
3018 | | */ |
3019 | | Datum |
3020 | | numeric_mul(PG_FUNCTION_ARGS) |
3021 | 0 | { |
3022 | 0 | Numeric num1 = PG_GETARG_NUMERIC(0); |
3023 | 0 | Numeric num2 = PG_GETARG_NUMERIC(1); |
3024 | 0 | Numeric res; |
3025 | |
|
3026 | 0 | res = numeric_mul_safe(num1, num2, fcinfo->context); |
3027 | |
|
3028 | 0 | if (unlikely(SOFT_ERROR_OCCURRED(fcinfo->context))) |
3029 | 0 | PG_RETURN_NULL(); |
3030 | | |
3031 | 0 | PG_RETURN_NUMERIC(res); |
3032 | 0 | } |
3033 | | |
3034 | | |
3035 | | /* |
3036 | | * numeric_mul_safe() - |
3037 | | * |
3038 | | * Internal version of numeric_mul() with support for soft error reporting. |
3039 | | */ |
3040 | | Numeric |
3041 | | numeric_mul_safe(Numeric num1, Numeric num2, Node *escontext) |
3042 | 0 | { |
3043 | 0 | NumericVar arg1; |
3044 | 0 | NumericVar arg2; |
3045 | 0 | NumericVar result; |
3046 | 0 | Numeric res; |
3047 | | |
3048 | | /* |
3049 | | * Handle NaN and infinities |
3050 | | */ |
3051 | 0 | if (NUMERIC_IS_SPECIAL(num1) || NUMERIC_IS_SPECIAL(num2)) |
3052 | 0 | { |
3053 | 0 | if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2)) |
3054 | 0 | return make_result(&const_nan); |
3055 | 0 | if (NUMERIC_IS_PINF(num1)) |
3056 | 0 | { |
3057 | 0 | switch (numeric_sign_internal(num2)) |
3058 | 0 | { |
3059 | 0 | case 0: |
3060 | 0 | return make_result(&const_nan); /* Inf * 0 */ |
3061 | 0 | case 1: |
3062 | 0 | return make_result(&const_pinf); |
3063 | 0 | case -1: |
3064 | 0 | return make_result(&const_ninf); |
3065 | 0 | } |
3066 | 0 | Assert(false); |
3067 | 0 | } |
3068 | 0 | if (NUMERIC_IS_NINF(num1)) |
3069 | 0 | { |
3070 | 0 | switch (numeric_sign_internal(num2)) |
3071 | 0 | { |
3072 | 0 | case 0: |
3073 | 0 | return make_result(&const_nan); /* -Inf * 0 */ |
3074 | 0 | case 1: |
3075 | 0 | return make_result(&const_ninf); |
3076 | 0 | case -1: |
3077 | 0 | return make_result(&const_pinf); |
3078 | 0 | } |
3079 | 0 | Assert(false); |
3080 | 0 | } |
3081 | | /* by here, num1 must be finite, so num2 is not */ |
3082 | 0 | if (NUMERIC_IS_PINF(num2)) |
3083 | 0 | { |
3084 | 0 | switch (numeric_sign_internal(num1)) |
3085 | 0 | { |
3086 | 0 | case 0: |
3087 | 0 | return make_result(&const_nan); /* 0 * Inf */ |
3088 | 0 | case 1: |
3089 | 0 | return make_result(&const_pinf); |
3090 | 0 | case -1: |
3091 | 0 | return make_result(&const_ninf); |
3092 | 0 | } |
3093 | 0 | Assert(false); |
3094 | 0 | } |
3095 | 0 | Assert(NUMERIC_IS_NINF(num2)); |
3096 | 0 | switch (numeric_sign_internal(num1)) |
3097 | 0 | { |
3098 | 0 | case 0: |
3099 | 0 | return make_result(&const_nan); /* 0 * -Inf */ |
3100 | 0 | case 1: |
3101 | 0 | return make_result(&const_ninf); |
3102 | 0 | case -1: |
3103 | 0 | return make_result(&const_pinf); |
3104 | 0 | } |
3105 | 0 | Assert(false); |
3106 | 0 | } |
3107 | | |
3108 | | /* |
3109 | | * Unpack the values, let mul_var() compute the result and return it. |
3110 | | * Unlike add_var() and sub_var(), mul_var() will round its result. In the |
3111 | | * case of numeric_mul(), which is invoked for the * operator on numerics, |
3112 | | * we request exact representation for the product (rscale = sum(dscale of |
3113 | | * arg1, dscale of arg2)). If the exact result has more digits after the |
3114 | | * decimal point than can be stored in a numeric, we round it. Rounding |
3115 | | * after computing the exact result ensures that the final result is |
3116 | | * correctly rounded (rounding in mul_var() using a truncated product |
3117 | | * would not guarantee this). |
3118 | | */ |
3119 | 0 | init_var_from_num(num1, &arg1); |
3120 | 0 | init_var_from_num(num2, &arg2); |
3121 | |
|
3122 | 0 | init_var(&result); |
3123 | 0 | mul_var(&arg1, &arg2, &result, arg1.dscale + arg2.dscale); |
3124 | |
|
3125 | 0 | if (result.dscale > NUMERIC_DSCALE_MAX) |
3126 | 0 | round_var(&result, NUMERIC_DSCALE_MAX); |
3127 | |
|
3128 | 0 | res = make_result_safe(&result, escontext); |
3129 | |
|
3130 | 0 | free_var(&result); |
3131 | |
|
3132 | 0 | return res; |
3133 | 0 | } |
3134 | | |
3135 | | |
3136 | | /* |
3137 | | * numeric_div() - |
3138 | | * |
3139 | | * Divide one numeric into another |
3140 | | */ |
3141 | | Datum |
3142 | | numeric_div(PG_FUNCTION_ARGS) |
3143 | 0 | { |
3144 | 0 | Numeric num1 = PG_GETARG_NUMERIC(0); |
3145 | 0 | Numeric num2 = PG_GETARG_NUMERIC(1); |
3146 | 0 | Numeric res; |
3147 | |
|
3148 | 0 | res = numeric_div_safe(num1, num2, NULL); |
3149 | |
|
3150 | 0 | PG_RETURN_NUMERIC(res); |
3151 | 0 | } |
3152 | | |
3153 | | |
3154 | | /* |
3155 | | * numeric_div_safe() - |
3156 | | * |
3157 | | * Internal version of numeric_div() with support for soft error reporting. |
3158 | | */ |
3159 | | Numeric |
3160 | | numeric_div_safe(Numeric num1, Numeric num2, Node *escontext) |
3161 | 0 | { |
3162 | 0 | NumericVar arg1; |
3163 | 0 | NumericVar arg2; |
3164 | 0 | NumericVar result; |
3165 | 0 | Numeric res; |
3166 | 0 | int rscale; |
3167 | | |
3168 | | /* |
3169 | | * Handle NaN and infinities |
3170 | | */ |
3171 | 0 | if (NUMERIC_IS_SPECIAL(num1) || NUMERIC_IS_SPECIAL(num2)) |
3172 | 0 | { |
3173 | 0 | if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2)) |
3174 | 0 | return make_result(&const_nan); |
3175 | 0 | if (NUMERIC_IS_PINF(num1)) |
3176 | 0 | { |
3177 | 0 | if (NUMERIC_IS_SPECIAL(num2)) |
3178 | 0 | return make_result(&const_nan); /* Inf / [-]Inf */ |
3179 | 0 | switch (numeric_sign_internal(num2)) |
3180 | 0 | { |
3181 | 0 | case 0: |
3182 | 0 | goto division_by_zero; |
3183 | 0 | case 1: |
3184 | 0 | return make_result(&const_pinf); |
3185 | 0 | case -1: |
3186 | 0 | return make_result(&const_ninf); |
3187 | 0 | } |
3188 | 0 | Assert(false); |
3189 | 0 | } |
3190 | 0 | if (NUMERIC_IS_NINF(num1)) |
3191 | 0 | { |
3192 | 0 | if (NUMERIC_IS_SPECIAL(num2)) |
3193 | 0 | return make_result(&const_nan); /* -Inf / [-]Inf */ |
3194 | 0 | switch (numeric_sign_internal(num2)) |
3195 | 0 | { |
3196 | 0 | case 0: |
3197 | 0 | goto division_by_zero; |
3198 | 0 | case 1: |
3199 | 0 | return make_result(&const_ninf); |
3200 | 0 | case -1: |
3201 | 0 | return make_result(&const_pinf); |
3202 | 0 | } |
3203 | 0 | Assert(false); |
3204 | 0 | } |
3205 | | /* by here, num1 must be finite, so num2 is not */ |
3206 | | |
3207 | | /* |
3208 | | * POSIX would have us return zero or minus zero if num1 is zero, and |
3209 | | * otherwise throw an underflow error. But the numeric type doesn't |
3210 | | * really do underflow, so let's just return zero. |
3211 | | */ |
3212 | 0 | return make_result(&const_zero); |
3213 | 0 | } |
3214 | | |
3215 | | /* |
3216 | | * Unpack the arguments |
3217 | | */ |
3218 | 0 | init_var_from_num(num1, &arg1); |
3219 | 0 | init_var_from_num(num2, &arg2); |
3220 | |
|
3221 | 0 | init_var(&result); |
3222 | | |
3223 | | /* |
3224 | | * Select scale for division result |
3225 | | */ |
3226 | 0 | rscale = select_div_scale(&arg1, &arg2); |
3227 | | |
3228 | | /* Check for division by zero */ |
3229 | 0 | if (arg2.ndigits == 0 || arg2.digits[0] == 0) |
3230 | 0 | goto division_by_zero; |
3231 | | |
3232 | | /* |
3233 | | * Do the divide and return the result |
3234 | | */ |
3235 | 0 | div_var(&arg1, &arg2, &result, rscale, true, true); |
3236 | |
|
3237 | 0 | res = make_result_safe(&result, escontext); |
3238 | |
|
3239 | 0 | free_var(&result); |
3240 | |
|
3241 | 0 | return res; |
3242 | | |
3243 | 0 | division_by_zero: |
3244 | 0 | ereturn(escontext, NULL, |
3245 | 0 | errcode(ERRCODE_DIVISION_BY_ZERO), |
3246 | 0 | errmsg("division by zero")); |
3247 | 0 | } |
3248 | | |
3249 | | |
3250 | | /* |
3251 | | * numeric_div_trunc() - |
3252 | | * |
3253 | | * Divide one numeric into another, truncating the result to an integer |
3254 | | */ |
3255 | | Datum |
3256 | | numeric_div_trunc(PG_FUNCTION_ARGS) |
3257 | 0 | { |
3258 | 0 | Numeric num1 = PG_GETARG_NUMERIC(0); |
3259 | 0 | Numeric num2 = PG_GETARG_NUMERIC(1); |
3260 | 0 | NumericVar arg1; |
3261 | 0 | NumericVar arg2; |
3262 | 0 | NumericVar result; |
3263 | 0 | Numeric res; |
3264 | | |
3265 | | /* |
3266 | | * Handle NaN and infinities |
3267 | | */ |
3268 | 0 | if (NUMERIC_IS_SPECIAL(num1) || NUMERIC_IS_SPECIAL(num2)) |
3269 | 0 | { |
3270 | 0 | if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2)) |
3271 | 0 | PG_RETURN_NUMERIC(make_result(&const_nan)); |
3272 | 0 | if (NUMERIC_IS_PINF(num1)) |
3273 | 0 | { |
3274 | 0 | if (NUMERIC_IS_SPECIAL(num2)) |
3275 | 0 | PG_RETURN_NUMERIC(make_result(&const_nan)); /* Inf / [-]Inf */ |
3276 | 0 | switch (numeric_sign_internal(num2)) |
3277 | 0 | { |
3278 | 0 | case 0: |
3279 | 0 | ereport(ERROR, |
3280 | 0 | (errcode(ERRCODE_DIVISION_BY_ZERO), |
3281 | 0 | errmsg("division by zero"))); |
3282 | 0 | break; |
3283 | 0 | case 1: |
3284 | 0 | PG_RETURN_NUMERIC(make_result(&const_pinf)); |
3285 | 0 | case -1: |
3286 | 0 | PG_RETURN_NUMERIC(make_result(&const_ninf)); |
3287 | 0 | } |
3288 | 0 | Assert(false); |
3289 | 0 | } |
3290 | 0 | if (NUMERIC_IS_NINF(num1)) |
3291 | 0 | { |
3292 | 0 | if (NUMERIC_IS_SPECIAL(num2)) |
3293 | 0 | PG_RETURN_NUMERIC(make_result(&const_nan)); /* -Inf / [-]Inf */ |
3294 | 0 | switch (numeric_sign_internal(num2)) |
3295 | 0 | { |
3296 | 0 | case 0: |
3297 | 0 | ereport(ERROR, |
3298 | 0 | (errcode(ERRCODE_DIVISION_BY_ZERO), |
3299 | 0 | errmsg("division by zero"))); |
3300 | 0 | break; |
3301 | 0 | case 1: |
3302 | 0 | PG_RETURN_NUMERIC(make_result(&const_ninf)); |
3303 | 0 | case -1: |
3304 | 0 | PG_RETURN_NUMERIC(make_result(&const_pinf)); |
3305 | 0 | } |
3306 | 0 | Assert(false); |
3307 | 0 | } |
3308 | | /* by here, num1 must be finite, so num2 is not */ |
3309 | | |
3310 | | /* |
3311 | | * POSIX would have us return zero or minus zero if num1 is zero, and |
3312 | | * otherwise throw an underflow error. But the numeric type doesn't |
3313 | | * really do underflow, so let's just return zero. |
3314 | | */ |
3315 | 0 | PG_RETURN_NUMERIC(make_result(&const_zero)); |
3316 | 0 | } |
3317 | | |
3318 | | /* |
3319 | | * Unpack the arguments |
3320 | | */ |
3321 | 0 | init_var_from_num(num1, &arg1); |
3322 | 0 | init_var_from_num(num2, &arg2); |
3323 | |
|
3324 | 0 | init_var(&result); |
3325 | | |
3326 | | /* |
3327 | | * Do the divide and return the result |
3328 | | */ |
3329 | 0 | div_var(&arg1, &arg2, &result, 0, false, true); |
3330 | |
|
3331 | 0 | res = make_result(&result); |
3332 | |
|
3333 | 0 | free_var(&result); |
3334 | |
|
3335 | 0 | PG_RETURN_NUMERIC(res); |
3336 | 0 | } |
3337 | | |
3338 | | |
3339 | | /* |
3340 | | * numeric_mod() - |
3341 | | * |
3342 | | * Calculate the modulo of two numerics |
3343 | | */ |
3344 | | Datum |
3345 | | numeric_mod(PG_FUNCTION_ARGS) |
3346 | 0 | { |
3347 | 0 | Numeric num1 = PG_GETARG_NUMERIC(0); |
3348 | 0 | Numeric num2 = PG_GETARG_NUMERIC(1); |
3349 | 0 | Numeric res; |
3350 | |
|
3351 | 0 | res = numeric_mod_safe(num1, num2, NULL); |
3352 | |
|
3353 | 0 | PG_RETURN_NUMERIC(res); |
3354 | 0 | } |
3355 | | |
3356 | | |
3357 | | /* |
3358 | | * numeric_mod_safe() - |
3359 | | * |
3360 | | * Internal version of numeric_mod() with support for soft error reporting. |
3361 | | */ |
3362 | | Numeric |
3363 | | numeric_mod_safe(Numeric num1, Numeric num2, Node *escontext) |
3364 | 0 | { |
3365 | 0 | Numeric res; |
3366 | 0 | NumericVar arg1; |
3367 | 0 | NumericVar arg2; |
3368 | 0 | NumericVar result; |
3369 | | |
3370 | | /* |
3371 | | * Handle NaN and infinities. We follow POSIX fmod() on this, except that |
3372 | | * POSIX treats x-is-infinite and y-is-zero identically, raising EDOM and |
3373 | | * returning NaN. We choose to throw error only for y-is-zero. |
3374 | | */ |
3375 | 0 | if (NUMERIC_IS_SPECIAL(num1) || NUMERIC_IS_SPECIAL(num2)) |
3376 | 0 | { |
3377 | 0 | if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2)) |
3378 | 0 | return make_result(&const_nan); |
3379 | 0 | if (NUMERIC_IS_INF(num1)) |
3380 | 0 | { |
3381 | 0 | if (numeric_sign_internal(num2) == 0) |
3382 | 0 | goto division_by_zero; |
3383 | | |
3384 | | /* Inf % any nonzero = NaN */ |
3385 | 0 | return make_result(&const_nan); |
3386 | 0 | } |
3387 | | /* num2 must be [-]Inf; result is num1 regardless of sign of num2 */ |
3388 | 0 | return duplicate_numeric(num1); |
3389 | 0 | } |
3390 | | |
3391 | 0 | init_var_from_num(num1, &arg1); |
3392 | 0 | init_var_from_num(num2, &arg2); |
3393 | |
|
3394 | 0 | init_var(&result); |
3395 | | |
3396 | | /* Check for division by zero */ |
3397 | 0 | if (arg2.ndigits == 0 || arg2.digits[0] == 0) |
3398 | 0 | goto division_by_zero; |
3399 | | |
3400 | 0 | mod_var(&arg1, &arg2, &result); |
3401 | |
|
3402 | 0 | res = make_result_safe(&result, escontext); |
3403 | |
|
3404 | 0 | free_var(&result); |
3405 | |
|
3406 | 0 | return res; |
3407 | | |
3408 | 0 | division_by_zero: |
3409 | 0 | ereturn(escontext, NULL, |
3410 | 0 | errcode(ERRCODE_DIVISION_BY_ZERO), |
3411 | 0 | errmsg("division by zero")); |
3412 | 0 | } |
3413 | | |
3414 | | |
3415 | | /* |
3416 | | * numeric_inc() - |
3417 | | * |
3418 | | * Increment a number by one |
3419 | | */ |
3420 | | Datum |
3421 | | numeric_inc(PG_FUNCTION_ARGS) |
3422 | 0 | { |
3423 | 0 | Numeric num = PG_GETARG_NUMERIC(0); |
3424 | 0 | NumericVar arg; |
3425 | 0 | Numeric res; |
3426 | | |
3427 | | /* |
3428 | | * Handle NaN and infinities |
3429 | | */ |
3430 | 0 | if (NUMERIC_IS_SPECIAL(num)) |
3431 | 0 | PG_RETURN_NUMERIC(duplicate_numeric(num)); |
3432 | | |
3433 | | /* |
3434 | | * Compute the result and return it |
3435 | | */ |
3436 | 0 | init_var_from_num(num, &arg); |
3437 | |
|
3438 | 0 | add_var(&arg, &const_one, &arg); |
3439 | |
|
3440 | 0 | res = make_result(&arg); |
3441 | |
|
3442 | 0 | free_var(&arg); |
3443 | |
|
3444 | 0 | PG_RETURN_NUMERIC(res); |
3445 | 0 | } |
3446 | | |
3447 | | |
3448 | | /* |
3449 | | * numeric_smaller() - |
3450 | | * |
3451 | | * Return the smaller of two numbers |
3452 | | */ |
3453 | | Datum |
3454 | | numeric_smaller(PG_FUNCTION_ARGS) |
3455 | 0 | { |
3456 | 0 | Numeric num1 = PG_GETARG_NUMERIC(0); |
3457 | 0 | Numeric num2 = PG_GETARG_NUMERIC(1); |
3458 | | |
3459 | | /* |
3460 | | * Use cmp_numerics so that this will agree with the comparison operators, |
3461 | | * particularly as regards comparisons involving NaN. |
3462 | | */ |
3463 | 0 | if (cmp_numerics(num1, num2) < 0) |
3464 | 0 | PG_RETURN_NUMERIC(num1); |
3465 | 0 | else |
3466 | 0 | PG_RETURN_NUMERIC(num2); |
3467 | 0 | } |
3468 | | |
3469 | | |
3470 | | /* |
3471 | | * numeric_larger() - |
3472 | | * |
3473 | | * Return the larger of two numbers |
3474 | | */ |
3475 | | Datum |
3476 | | numeric_larger(PG_FUNCTION_ARGS) |
3477 | 0 | { |
3478 | 0 | Numeric num1 = PG_GETARG_NUMERIC(0); |
3479 | 0 | Numeric num2 = PG_GETARG_NUMERIC(1); |
3480 | | |
3481 | | /* |
3482 | | * Use cmp_numerics so that this will agree with the comparison operators, |
3483 | | * particularly as regards comparisons involving NaN. |
3484 | | */ |
3485 | 0 | if (cmp_numerics(num1, num2) > 0) |
3486 | 0 | PG_RETURN_NUMERIC(num1); |
3487 | 0 | else |
3488 | 0 | PG_RETURN_NUMERIC(num2); |
3489 | 0 | } |
3490 | | |
3491 | | |
3492 | | /* ---------------------------------------------------------------------- |
3493 | | * |
3494 | | * Advanced math functions |
3495 | | * |
3496 | | * ---------------------------------------------------------------------- |
3497 | | */ |
3498 | | |
3499 | | /* |
3500 | | * numeric_gcd() - |
3501 | | * |
3502 | | * Calculate the greatest common divisor of two numerics |
3503 | | */ |
3504 | | Datum |
3505 | | numeric_gcd(PG_FUNCTION_ARGS) |
3506 | 0 | { |
3507 | 0 | Numeric num1 = PG_GETARG_NUMERIC(0); |
3508 | 0 | Numeric num2 = PG_GETARG_NUMERIC(1); |
3509 | 0 | NumericVar arg1; |
3510 | 0 | NumericVar arg2; |
3511 | 0 | NumericVar result; |
3512 | 0 | Numeric res; |
3513 | | |
3514 | | /* |
3515 | | * Handle NaN and infinities: we consider the result to be NaN in all such |
3516 | | * cases. |
3517 | | */ |
3518 | 0 | if (NUMERIC_IS_SPECIAL(num1) || NUMERIC_IS_SPECIAL(num2)) |
3519 | 0 | PG_RETURN_NUMERIC(make_result(&const_nan)); |
3520 | | |
3521 | | /* |
3522 | | * Unpack the arguments |
3523 | | */ |
3524 | 0 | init_var_from_num(num1, &arg1); |
3525 | 0 | init_var_from_num(num2, &arg2); |
3526 | |
|
3527 | 0 | init_var(&result); |
3528 | | |
3529 | | /* |
3530 | | * Find the GCD and return the result |
3531 | | */ |
3532 | 0 | gcd_var(&arg1, &arg2, &result); |
3533 | |
|
3534 | 0 | res = make_result(&result); |
3535 | |
|
3536 | 0 | free_var(&result); |
3537 | |
|
3538 | 0 | PG_RETURN_NUMERIC(res); |
3539 | 0 | } |
3540 | | |
3541 | | |
3542 | | /* |
3543 | | * numeric_lcm() - |
3544 | | * |
3545 | | * Calculate the least common multiple of two numerics |
3546 | | */ |
3547 | | Datum |
3548 | | numeric_lcm(PG_FUNCTION_ARGS) |
3549 | 0 | { |
3550 | 0 | Numeric num1 = PG_GETARG_NUMERIC(0); |
3551 | 0 | Numeric num2 = PG_GETARG_NUMERIC(1); |
3552 | 0 | NumericVar arg1; |
3553 | 0 | NumericVar arg2; |
3554 | 0 | NumericVar result; |
3555 | 0 | Numeric res; |
3556 | | |
3557 | | /* |
3558 | | * Handle NaN and infinities: we consider the result to be NaN in all such |
3559 | | * cases. |
3560 | | */ |
3561 | 0 | if (NUMERIC_IS_SPECIAL(num1) || NUMERIC_IS_SPECIAL(num2)) |
3562 | 0 | PG_RETURN_NUMERIC(make_result(&const_nan)); |
3563 | | |
3564 | | /* |
3565 | | * Unpack the arguments |
3566 | | */ |
3567 | 0 | init_var_from_num(num1, &arg1); |
3568 | 0 | init_var_from_num(num2, &arg2); |
3569 | |
|
3570 | 0 | init_var(&result); |
3571 | | |
3572 | | /* |
3573 | | * Compute the result using lcm(x, y) = abs(x / gcd(x, y) * y), returning |
3574 | | * zero if either input is zero. |
3575 | | * |
3576 | | * Note that the division is guaranteed to be exact, returning an integer |
3577 | | * result, so the LCM is an integral multiple of both x and y. A display |
3578 | | * scale of Min(x.dscale, y.dscale) would be sufficient to represent it, |
3579 | | * but as with other numeric functions, we choose to return a result whose |
3580 | | * display scale is no smaller than either input. |
3581 | | */ |
3582 | 0 | if (arg1.ndigits == 0 || arg2.ndigits == 0) |
3583 | 0 | set_var_from_var(&const_zero, &result); |
3584 | 0 | else |
3585 | 0 | { |
3586 | 0 | gcd_var(&arg1, &arg2, &result); |
3587 | 0 | div_var(&arg1, &result, &result, 0, false, true); |
3588 | 0 | mul_var(&arg2, &result, &result, arg2.dscale); |
3589 | 0 | result.sign = NUMERIC_POS; |
3590 | 0 | } |
3591 | |
|
3592 | 0 | result.dscale = Max(arg1.dscale, arg2.dscale); |
3593 | |
|
3594 | 0 | res = make_result(&result); |
3595 | |
|
3596 | 0 | free_var(&result); |
3597 | |
|
3598 | 0 | PG_RETURN_NUMERIC(res); |
3599 | 0 | } |
3600 | | |
3601 | | |
3602 | | /* |
3603 | | * numeric_fac() |
3604 | | * |
3605 | | * Compute factorial |
3606 | | */ |
3607 | | Datum |
3608 | | numeric_fac(PG_FUNCTION_ARGS) |
3609 | 0 | { |
3610 | 0 | int64 num = PG_GETARG_INT64(0); |
3611 | 0 | Numeric res; |
3612 | 0 | NumericVar fact; |
3613 | 0 | NumericVar result; |
3614 | |
|
3615 | 0 | if (num < 0) |
3616 | 0 | ereport(ERROR, |
3617 | 0 | (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), |
3618 | 0 | errmsg("factorial of a negative number is undefined"))); |
3619 | 0 | if (num <= 1) |
3620 | 0 | { |
3621 | 0 | res = make_result(&const_one); |
3622 | 0 | PG_RETURN_NUMERIC(res); |
3623 | 0 | } |
3624 | | /* Fail immediately if the result would overflow */ |
3625 | 0 | if (num > 32177) |
3626 | 0 | ereport(ERROR, |
3627 | 0 | (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), |
3628 | 0 | errmsg("value overflows numeric format"))); |
3629 | | |
3630 | 0 | init_var(&fact); |
3631 | 0 | init_var(&result); |
3632 | |
|
3633 | 0 | int64_to_numericvar(num, &result); |
3634 | |
|
3635 | 0 | for (num = num - 1; num > 1; num--) |
3636 | 0 | { |
3637 | | /* this loop can take awhile, so allow it to be interrupted */ |
3638 | 0 | CHECK_FOR_INTERRUPTS(); |
3639 | |
|
3640 | 0 | int64_to_numericvar(num, &fact); |
3641 | |
|
3642 | 0 | mul_var(&result, &fact, &result, 0); |
3643 | 0 | } |
3644 | |
|
3645 | 0 | res = make_result(&result); |
3646 | |
|
3647 | 0 | free_var(&fact); |
3648 | 0 | free_var(&result); |
3649 | |
|
3650 | 0 | PG_RETURN_NUMERIC(res); |
3651 | 0 | } |
3652 | | |
3653 | | |
3654 | | /* |
3655 | | * numeric_sqrt() - |
3656 | | * |
3657 | | * Compute the square root of a numeric. |
3658 | | */ |
3659 | | Datum |
3660 | | numeric_sqrt(PG_FUNCTION_ARGS) |
3661 | 0 | { |
3662 | 0 | Numeric num = PG_GETARG_NUMERIC(0); |
3663 | 0 | Numeric res; |
3664 | 0 | NumericVar arg; |
3665 | 0 | NumericVar result; |
3666 | 0 | int sweight; |
3667 | 0 | int rscale; |
3668 | | |
3669 | | /* |
3670 | | * Handle NaN and infinities |
3671 | | */ |
3672 | 0 | if (NUMERIC_IS_SPECIAL(num)) |
3673 | 0 | { |
3674 | | /* error should match that in sqrt_var() */ |
3675 | 0 | if (NUMERIC_IS_NINF(num)) |
3676 | 0 | ereport(ERROR, |
3677 | 0 | (errcode(ERRCODE_INVALID_ARGUMENT_FOR_POWER_FUNCTION), |
3678 | 0 | errmsg("cannot take square root of a negative number"))); |
3679 | | /* For NAN or PINF, just duplicate the input */ |
3680 | 0 | PG_RETURN_NUMERIC(duplicate_numeric(num)); |
3681 | 0 | } |
3682 | | |
3683 | | /* |
3684 | | * Unpack the argument and determine the result scale. We choose a scale |
3685 | | * to give at least NUMERIC_MIN_SIG_DIGITS significant digits; but in any |
3686 | | * case not less than the input's dscale. |
3687 | | */ |
3688 | 0 | init_var_from_num(num, &arg); |
3689 | |
|
3690 | 0 | init_var(&result); |
3691 | | |
3692 | | /* |
3693 | | * Assume the input was normalized, so arg.weight is accurate. The result |
3694 | | * then has at least sweight = floor(arg.weight * DEC_DIGITS / 2 + 1) |
3695 | | * digits before the decimal point. When DEC_DIGITS is even, we can save |
3696 | | * a few cycles, since the division is exact and there is no need to round |
3697 | | * towards negative infinity. |
3698 | | */ |
3699 | 0 | #if DEC_DIGITS == ((DEC_DIGITS / 2) * 2) |
3700 | 0 | sweight = arg.weight * DEC_DIGITS / 2 + 1; |
3701 | | #else |
3702 | | if (arg.weight >= 0) |
3703 | | sweight = arg.weight * DEC_DIGITS / 2 + 1; |
3704 | | else |
3705 | | sweight = 1 - (1 - arg.weight * DEC_DIGITS) / 2; |
3706 | | #endif |
3707 | |
|
3708 | 0 | rscale = NUMERIC_MIN_SIG_DIGITS - sweight; |
3709 | 0 | rscale = Max(rscale, arg.dscale); |
3710 | 0 | rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE); |
3711 | 0 | rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE); |
3712 | | |
3713 | | /* |
3714 | | * Let sqrt_var() do the calculation and return the result. |
3715 | | */ |
3716 | 0 | sqrt_var(&arg, &result, rscale); |
3717 | |
|
3718 | 0 | res = make_result(&result); |
3719 | |
|
3720 | 0 | free_var(&result); |
3721 | |
|
3722 | 0 | PG_RETURN_NUMERIC(res); |
3723 | 0 | } |
3724 | | |
3725 | | |
3726 | | /* |
3727 | | * numeric_exp() - |
3728 | | * |
3729 | | * Raise e to the power of x |
3730 | | */ |
3731 | | Datum |
3732 | | numeric_exp(PG_FUNCTION_ARGS) |
3733 | 0 | { |
3734 | 0 | Numeric num = PG_GETARG_NUMERIC(0); |
3735 | 0 | Numeric res; |
3736 | 0 | NumericVar arg; |
3737 | 0 | NumericVar result; |
3738 | 0 | int rscale; |
3739 | 0 | double val; |
3740 | | |
3741 | | /* |
3742 | | * Handle NaN and infinities |
3743 | | */ |
3744 | 0 | if (NUMERIC_IS_SPECIAL(num)) |
3745 | 0 | { |
3746 | | /* Per POSIX, exp(-Inf) is zero */ |
3747 | 0 | if (NUMERIC_IS_NINF(num)) |
3748 | 0 | PG_RETURN_NUMERIC(make_result(&const_zero)); |
3749 | | /* For NAN or PINF, just duplicate the input */ |
3750 | 0 | PG_RETURN_NUMERIC(duplicate_numeric(num)); |
3751 | 0 | } |
3752 | | |
3753 | | /* |
3754 | | * Unpack the argument and determine the result scale. We choose a scale |
3755 | | * to give at least NUMERIC_MIN_SIG_DIGITS significant digits; but in any |
3756 | | * case not less than the input's dscale. |
3757 | | */ |
3758 | 0 | init_var_from_num(num, &arg); |
3759 | |
|
3760 | 0 | init_var(&result); |
3761 | | |
3762 | | /* convert input to float8, ignoring overflow */ |
3763 | 0 | val = numericvar_to_double_no_overflow(&arg); |
3764 | | |
3765 | | /* |
3766 | | * log10(result) = num * log10(e), so this is approximately the decimal |
3767 | | * weight of the result: |
3768 | | */ |
3769 | 0 | val *= 0.434294481903252; |
3770 | | |
3771 | | /* limit to something that won't cause integer overflow */ |
3772 | 0 | val = Max(val, -NUMERIC_MAX_RESULT_SCALE); |
3773 | 0 | val = Min(val, NUMERIC_MAX_RESULT_SCALE); |
3774 | |
|
3775 | 0 | rscale = NUMERIC_MIN_SIG_DIGITS - (int) val; |
3776 | 0 | rscale = Max(rscale, arg.dscale); |
3777 | 0 | rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE); |
3778 | 0 | rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE); |
3779 | | |
3780 | | /* |
3781 | | * Let exp_var() do the calculation and return the result. |
3782 | | */ |
3783 | 0 | exp_var(&arg, &result, rscale); |
3784 | |
|
3785 | 0 | res = make_result(&result); |
3786 | |
|
3787 | 0 | free_var(&result); |
3788 | |
|
3789 | 0 | PG_RETURN_NUMERIC(res); |
3790 | 0 | } |
3791 | | |
3792 | | |
3793 | | /* |
3794 | | * numeric_ln() - |
3795 | | * |
3796 | | * Compute the natural logarithm of x |
3797 | | */ |
3798 | | Datum |
3799 | | numeric_ln(PG_FUNCTION_ARGS) |
3800 | 0 | { |
3801 | 0 | Numeric num = PG_GETARG_NUMERIC(0); |
3802 | 0 | Numeric res; |
3803 | 0 | NumericVar arg; |
3804 | 0 | NumericVar result; |
3805 | 0 | int ln_dweight; |
3806 | 0 | int rscale; |
3807 | | |
3808 | | /* |
3809 | | * Handle NaN and infinities |
3810 | | */ |
3811 | 0 | if (NUMERIC_IS_SPECIAL(num)) |
3812 | 0 | { |
3813 | 0 | if (NUMERIC_IS_NINF(num)) |
3814 | 0 | ereport(ERROR, |
3815 | 0 | (errcode(ERRCODE_INVALID_ARGUMENT_FOR_LOG), |
3816 | 0 | errmsg("cannot take logarithm of a negative number"))); |
3817 | | /* For NAN or PINF, just duplicate the input */ |
3818 | 0 | PG_RETURN_NUMERIC(duplicate_numeric(num)); |
3819 | 0 | } |
3820 | | |
3821 | 0 | init_var_from_num(num, &arg); |
3822 | 0 | init_var(&result); |
3823 | | |
3824 | | /* Estimated dweight of logarithm */ |
3825 | 0 | ln_dweight = estimate_ln_dweight(&arg); |
3826 | |
|
3827 | 0 | rscale = NUMERIC_MIN_SIG_DIGITS - ln_dweight; |
3828 | 0 | rscale = Max(rscale, arg.dscale); |
3829 | 0 | rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE); |
3830 | 0 | rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE); |
3831 | |
|
3832 | 0 | ln_var(&arg, &result, rscale); |
3833 | |
|
3834 | 0 | res = make_result(&result); |
3835 | |
|
3836 | 0 | free_var(&result); |
3837 | |
|
3838 | 0 | PG_RETURN_NUMERIC(res); |
3839 | 0 | } |
3840 | | |
3841 | | |
3842 | | /* |
3843 | | * numeric_log() - |
3844 | | * |
3845 | | * Compute the logarithm of x in a given base |
3846 | | */ |
3847 | | Datum |
3848 | | numeric_log(PG_FUNCTION_ARGS) |
3849 | 0 | { |
3850 | 0 | Numeric num1 = PG_GETARG_NUMERIC(0); |
3851 | 0 | Numeric num2 = PG_GETARG_NUMERIC(1); |
3852 | 0 | Numeric res; |
3853 | 0 | NumericVar arg1; |
3854 | 0 | NumericVar arg2; |
3855 | 0 | NumericVar result; |
3856 | | |
3857 | | /* |
3858 | | * Handle NaN and infinities |
3859 | | */ |
3860 | 0 | if (NUMERIC_IS_SPECIAL(num1) || NUMERIC_IS_SPECIAL(num2)) |
3861 | 0 | { |
3862 | 0 | int sign1, |
3863 | 0 | sign2; |
3864 | |
|
3865 | 0 | if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2)) |
3866 | 0 | PG_RETURN_NUMERIC(make_result(&const_nan)); |
3867 | | /* fail on negative inputs including -Inf, as log_var would */ |
3868 | 0 | sign1 = numeric_sign_internal(num1); |
3869 | 0 | sign2 = numeric_sign_internal(num2); |
3870 | 0 | if (sign1 < 0 || sign2 < 0) |
3871 | 0 | ereport(ERROR, |
3872 | 0 | (errcode(ERRCODE_INVALID_ARGUMENT_FOR_LOG), |
3873 | 0 | errmsg("cannot take logarithm of a negative number"))); |
3874 | | /* fail on zero inputs, as log_var would */ |
3875 | 0 | if (sign1 == 0 || sign2 == 0) |
3876 | 0 | ereport(ERROR, |
3877 | 0 | (errcode(ERRCODE_INVALID_ARGUMENT_FOR_LOG), |
3878 | 0 | errmsg("cannot take logarithm of zero"))); |
3879 | 0 | if (NUMERIC_IS_PINF(num1)) |
3880 | 0 | { |
3881 | | /* log(Inf, Inf) reduces to Inf/Inf, so it's NaN */ |
3882 | 0 | if (NUMERIC_IS_PINF(num2)) |
3883 | 0 | PG_RETURN_NUMERIC(make_result(&const_nan)); |
3884 | | /* log(Inf, finite-positive) is zero (we don't throw underflow) */ |
3885 | 0 | PG_RETURN_NUMERIC(make_result(&const_zero)); |
3886 | 0 | } |
3887 | 0 | Assert(NUMERIC_IS_PINF(num2)); |
3888 | | |
3889 | | /* |
3890 | | * For a finite-positive base, log(base, Inf) = Inf / ln(base), so the |
3891 | | * sign depends on whether base is more or less than 1. If base = 1, |
3892 | | * fall through and let log_var report the error. |
3893 | | */ |
3894 | 0 | init_var_from_num(num1, &arg1); |
3895 | 0 | sign1 = cmp_var(&arg1, &const_one); |
3896 | 0 | if (sign1 < 0) |
3897 | 0 | PG_RETURN_NUMERIC(make_result(&const_ninf)); |
3898 | 0 | if (sign1 > 0) |
3899 | 0 | PG_RETURN_NUMERIC(make_result(&const_pinf)); |
3900 | 0 | } |
3901 | | |
3902 | | /* |
3903 | | * Initialize things |
3904 | | */ |
3905 | 0 | init_var_from_num(num1, &arg1); |
3906 | 0 | init_var_from_num(num2, &arg2); |
3907 | 0 | init_var(&result); |
3908 | | |
3909 | | /* |
3910 | | * Call log_var() to compute and return the result; note it handles scale |
3911 | | * selection itself. |
3912 | | */ |
3913 | 0 | log_var(&arg1, &arg2, &result); |
3914 | |
|
3915 | 0 | res = make_result(&result); |
3916 | |
|
3917 | 0 | free_var(&result); |
3918 | |
|
3919 | 0 | PG_RETURN_NUMERIC(res); |
3920 | 0 | } |
3921 | | |
3922 | | |
3923 | | /* |
3924 | | * numeric_power() - |
3925 | | * |
3926 | | * Raise x to the power of y |
3927 | | */ |
3928 | | Datum |
3929 | | numeric_power(PG_FUNCTION_ARGS) |
3930 | 0 | { |
3931 | 0 | Numeric num1 = PG_GETARG_NUMERIC(0); |
3932 | 0 | Numeric num2 = PG_GETARG_NUMERIC(1); |
3933 | 0 | Numeric res; |
3934 | 0 | NumericVar arg1; |
3935 | 0 | NumericVar arg2; |
3936 | 0 | NumericVar result; |
3937 | 0 | int sign1, |
3938 | 0 | sign2; |
3939 | | |
3940 | | /* |
3941 | | * Handle NaN and infinities |
3942 | | */ |
3943 | 0 | if (NUMERIC_IS_SPECIAL(num1) || NUMERIC_IS_SPECIAL(num2)) |
3944 | 0 | { |
3945 | | /* |
3946 | | * We follow the POSIX spec for pow(3), which says that NaN ^ 0 = 1, |
3947 | | * and 1 ^ NaN = 1, while all other cases with NaN inputs yield NaN |
3948 | | * (with no error). |
3949 | | */ |
3950 | 0 | if (NUMERIC_IS_NAN(num1)) |
3951 | 0 | { |
3952 | 0 | if (!NUMERIC_IS_SPECIAL(num2)) |
3953 | 0 | { |
3954 | 0 | init_var_from_num(num2, &arg2); |
3955 | 0 | if (cmp_var(&arg2, &const_zero) == 0) |
3956 | 0 | PG_RETURN_NUMERIC(make_result(&const_one)); |
3957 | 0 | } |
3958 | 0 | PG_RETURN_NUMERIC(make_result(&const_nan)); |
3959 | 0 | } |
3960 | 0 | if (NUMERIC_IS_NAN(num2)) |
3961 | 0 | { |
3962 | 0 | if (!NUMERIC_IS_SPECIAL(num1)) |
3963 | 0 | { |
3964 | 0 | init_var_from_num(num1, &arg1); |
3965 | 0 | if (cmp_var(&arg1, &const_one) == 0) |
3966 | 0 | PG_RETURN_NUMERIC(make_result(&const_one)); |
3967 | 0 | } |
3968 | 0 | PG_RETURN_NUMERIC(make_result(&const_nan)); |
3969 | 0 | } |
3970 | | /* At least one input is infinite, but error rules still apply */ |
3971 | 0 | sign1 = numeric_sign_internal(num1); |
3972 | 0 | sign2 = numeric_sign_internal(num2); |
3973 | 0 | if (sign1 == 0 && sign2 < 0) |
3974 | 0 | ereport(ERROR, |
3975 | 0 | (errcode(ERRCODE_INVALID_ARGUMENT_FOR_POWER_FUNCTION), |
3976 | 0 | errmsg("zero raised to a negative power is undefined"))); |
3977 | 0 | if (sign1 < 0 && !numeric_is_integral(num2)) |
3978 | 0 | ereport(ERROR, |
3979 | 0 | (errcode(ERRCODE_INVALID_ARGUMENT_FOR_POWER_FUNCTION), |
3980 | 0 | errmsg("a negative number raised to a non-integer power yields a complex result"))); |
3981 | | |
3982 | | /* |
3983 | | * POSIX gives this series of rules for pow(3) with infinite inputs: |
3984 | | * |
3985 | | * For any value of y, if x is +1, 1.0 shall be returned. |
3986 | | */ |
3987 | 0 | if (!NUMERIC_IS_SPECIAL(num1)) |
3988 | 0 | { |
3989 | 0 | init_var_from_num(num1, &arg1); |
3990 | 0 | if (cmp_var(&arg1, &const_one) == 0) |
3991 | 0 | PG_RETURN_NUMERIC(make_result(&const_one)); |
3992 | 0 | } |
3993 | | |
3994 | | /* |
3995 | | * For any value of x, if y is [-]0, 1.0 shall be returned. |
3996 | | */ |
3997 | 0 | if (sign2 == 0) |
3998 | 0 | PG_RETURN_NUMERIC(make_result(&const_one)); |
3999 | | |
4000 | | /* |
4001 | | * For any odd integer value of y > 0, if x is [-]0, [-]0 shall be |
4002 | | * returned. For y > 0 and not an odd integer, if x is [-]0, +0 shall |
4003 | | * be returned. (Since we don't deal in minus zero, we need not |
4004 | | * distinguish these two cases.) |
4005 | | */ |
4006 | 0 | if (sign1 == 0 && sign2 > 0) |
4007 | 0 | PG_RETURN_NUMERIC(make_result(&const_zero)); |
4008 | | |
4009 | | /* |
4010 | | * If x is -1, and y is [-]Inf, 1.0 shall be returned. |
4011 | | * |
4012 | | * For |x| < 1, if y is -Inf, +Inf shall be returned. |
4013 | | * |
4014 | | * For |x| > 1, if y is -Inf, +0 shall be returned. |
4015 | | * |
4016 | | * For |x| < 1, if y is +Inf, +0 shall be returned. |
4017 | | * |
4018 | | * For |x| > 1, if y is +Inf, +Inf shall be returned. |
4019 | | */ |
4020 | 0 | if (NUMERIC_IS_INF(num2)) |
4021 | 0 | { |
4022 | 0 | bool abs_x_gt_one; |
4023 | |
|
4024 | 0 | if (NUMERIC_IS_SPECIAL(num1)) |
4025 | 0 | abs_x_gt_one = true; /* x is either Inf or -Inf */ |
4026 | 0 | else |
4027 | 0 | { |
4028 | 0 | init_var_from_num(num1, &arg1); |
4029 | 0 | if (cmp_var(&arg1, &const_minus_one) == 0) |
4030 | 0 | PG_RETURN_NUMERIC(make_result(&const_one)); |
4031 | 0 | arg1.sign = NUMERIC_POS; /* now arg1 = abs(x) */ |
4032 | 0 | abs_x_gt_one = (cmp_var(&arg1, &const_one) > 0); |
4033 | 0 | } |
4034 | 0 | if (abs_x_gt_one == (sign2 > 0)) |
4035 | 0 | PG_RETURN_NUMERIC(make_result(&const_pinf)); |
4036 | 0 | else |
4037 | 0 | PG_RETURN_NUMERIC(make_result(&const_zero)); |
4038 | 0 | } |
4039 | | |
4040 | | /* |
4041 | | * For y < 0, if x is +Inf, +0 shall be returned. |
4042 | | * |
4043 | | * For y > 0, if x is +Inf, +Inf shall be returned. |
4044 | | */ |
4045 | 0 | if (NUMERIC_IS_PINF(num1)) |
4046 | 0 | { |
4047 | 0 | if (sign2 > 0) |
4048 | 0 | PG_RETURN_NUMERIC(make_result(&const_pinf)); |
4049 | 0 | else |
4050 | 0 | PG_RETURN_NUMERIC(make_result(&const_zero)); |
4051 | 0 | } |
4052 | | |
4053 | 0 | Assert(NUMERIC_IS_NINF(num1)); |
4054 | | |
4055 | | /* |
4056 | | * For y an odd integer < 0, if x is -Inf, -0 shall be returned. For |
4057 | | * y < 0 and not an odd integer, if x is -Inf, +0 shall be returned. |
4058 | | * (Again, we need not distinguish these two cases.) |
4059 | | */ |
4060 | 0 | if (sign2 < 0) |
4061 | 0 | PG_RETURN_NUMERIC(make_result(&const_zero)); |
4062 | | |
4063 | | /* |
4064 | | * For y an odd integer > 0, if x is -Inf, -Inf shall be returned. For |
4065 | | * y > 0 and not an odd integer, if x is -Inf, +Inf shall be returned. |
4066 | | */ |
4067 | 0 | init_var_from_num(num2, &arg2); |
4068 | 0 | if (arg2.ndigits > 0 && arg2.ndigits == arg2.weight + 1 && |
4069 | 0 | (arg2.digits[arg2.ndigits - 1] & 1)) |
4070 | 0 | PG_RETURN_NUMERIC(make_result(&const_ninf)); |
4071 | 0 | else |
4072 | 0 | PG_RETURN_NUMERIC(make_result(&const_pinf)); |
4073 | 0 | } |
4074 | | |
4075 | | /* |
4076 | | * The SQL spec requires that we emit a particular SQLSTATE error code for |
4077 | | * certain error conditions. Specifically, we don't return a |
4078 | | * divide-by-zero error code for 0 ^ -1. Raising a negative number to a |
4079 | | * non-integer power must produce the same error code, but that case is |
4080 | | * handled in power_var(). |
4081 | | */ |
4082 | 0 | sign1 = numeric_sign_internal(num1); |
4083 | 0 | sign2 = numeric_sign_internal(num2); |
4084 | |
|
4085 | 0 | if (sign1 == 0 && sign2 < 0) |
4086 | 0 | ereport(ERROR, |
4087 | 0 | (errcode(ERRCODE_INVALID_ARGUMENT_FOR_POWER_FUNCTION), |
4088 | 0 | errmsg("zero raised to a negative power is undefined"))); |
4089 | | |
4090 | | /* |
4091 | | * Initialize things |
4092 | | */ |
4093 | 0 | init_var(&result); |
4094 | 0 | init_var_from_num(num1, &arg1); |
4095 | 0 | init_var_from_num(num2, &arg2); |
4096 | | |
4097 | | /* |
4098 | | * Call power_var() to compute and return the result; note it handles |
4099 | | * scale selection itself. |
4100 | | */ |
4101 | 0 | power_var(&arg1, &arg2, &result); |
4102 | |
|
4103 | 0 | res = make_result(&result); |
4104 | |
|
4105 | 0 | free_var(&result); |
4106 | |
|
4107 | 0 | PG_RETURN_NUMERIC(res); |
4108 | 0 | } |
4109 | | |
4110 | | /* |
4111 | | * numeric_scale() - |
4112 | | * |
4113 | | * Returns the scale, i.e. the count of decimal digits in the fractional part |
4114 | | */ |
4115 | | Datum |
4116 | | numeric_scale(PG_FUNCTION_ARGS) |
4117 | 0 | { |
4118 | 0 | Numeric num = PG_GETARG_NUMERIC(0); |
4119 | |
|
4120 | 0 | if (NUMERIC_IS_SPECIAL(num)) |
4121 | 0 | PG_RETURN_NULL(); |
4122 | | |
4123 | 0 | PG_RETURN_INT32(NUMERIC_DSCALE(num)); |
4124 | 0 | } |
4125 | | |
4126 | | /* |
4127 | | * Calculate minimum scale for value. |
4128 | | */ |
4129 | | static int |
4130 | | get_min_scale(NumericVar *var) |
4131 | 0 | { |
4132 | 0 | int min_scale; |
4133 | 0 | int last_digit_pos; |
4134 | | |
4135 | | /* |
4136 | | * Ordinarily, the input value will be "stripped" so that the last |
4137 | | * NumericDigit is nonzero. But we don't want to get into an infinite |
4138 | | * loop if it isn't, so explicitly find the last nonzero digit. |
4139 | | */ |
4140 | 0 | last_digit_pos = var->ndigits - 1; |
4141 | 0 | while (last_digit_pos >= 0 && |
4142 | 0 | var->digits[last_digit_pos] == 0) |
4143 | 0 | last_digit_pos--; |
4144 | |
|
4145 | 0 | if (last_digit_pos >= 0) |
4146 | 0 | { |
4147 | | /* compute min_scale assuming that last ndigit has no zeroes */ |
4148 | 0 | min_scale = (last_digit_pos - var->weight) * DEC_DIGITS; |
4149 | | |
4150 | | /* |
4151 | | * We could get a negative result if there are no digits after the |
4152 | | * decimal point. In this case the min_scale must be zero. |
4153 | | */ |
4154 | 0 | if (min_scale > 0) |
4155 | 0 | { |
4156 | | /* |
4157 | | * Reduce min_scale if trailing digit(s) in last NumericDigit are |
4158 | | * zero. |
4159 | | */ |
4160 | 0 | NumericDigit last_digit = var->digits[last_digit_pos]; |
4161 | |
|
4162 | 0 | while (last_digit % 10 == 0) |
4163 | 0 | { |
4164 | 0 | min_scale--; |
4165 | 0 | last_digit /= 10; |
4166 | 0 | } |
4167 | 0 | } |
4168 | 0 | else |
4169 | 0 | min_scale = 0; |
4170 | 0 | } |
4171 | 0 | else |
4172 | 0 | min_scale = 0; /* result if input is zero */ |
4173 | |
|
4174 | 0 | return min_scale; |
4175 | 0 | } |
4176 | | |
4177 | | /* |
4178 | | * Returns minimum scale required to represent supplied value without loss. |
4179 | | */ |
4180 | | Datum |
4181 | | numeric_min_scale(PG_FUNCTION_ARGS) |
4182 | 0 | { |
4183 | 0 | Numeric num = PG_GETARG_NUMERIC(0); |
4184 | 0 | NumericVar arg; |
4185 | 0 | int min_scale; |
4186 | |
|
4187 | 0 | if (NUMERIC_IS_SPECIAL(num)) |
4188 | 0 | PG_RETURN_NULL(); |
4189 | | |
4190 | 0 | init_var_from_num(num, &arg); |
4191 | 0 | min_scale = get_min_scale(&arg); |
4192 | 0 | free_var(&arg); |
4193 | |
|
4194 | 0 | PG_RETURN_INT32(min_scale); |
4195 | 0 | } |
4196 | | |
4197 | | /* |
4198 | | * Reduce scale of numeric value to represent supplied value without loss. |
4199 | | */ |
4200 | | Datum |
4201 | | numeric_trim_scale(PG_FUNCTION_ARGS) |
4202 | 0 | { |
4203 | 0 | Numeric num = PG_GETARG_NUMERIC(0); |
4204 | 0 | Numeric res; |
4205 | 0 | NumericVar result; |
4206 | |
|
4207 | 0 | if (NUMERIC_IS_SPECIAL(num)) |
4208 | 0 | PG_RETURN_NUMERIC(duplicate_numeric(num)); |
4209 | | |
4210 | 0 | init_var_from_num(num, &result); |
4211 | 0 | result.dscale = get_min_scale(&result); |
4212 | 0 | res = make_result(&result); |
4213 | 0 | free_var(&result); |
4214 | |
|
4215 | 0 | PG_RETURN_NUMERIC(res); |
4216 | 0 | } |
4217 | | |
4218 | | /* |
4219 | | * Return a random numeric value in the range [rmin, rmax]. |
4220 | | */ |
4221 | | Numeric |
4222 | | random_numeric(pg_prng_state *state, Numeric rmin, Numeric rmax) |
4223 | 0 | { |
4224 | 0 | NumericVar rmin_var; |
4225 | 0 | NumericVar rmax_var; |
4226 | 0 | NumericVar result; |
4227 | 0 | Numeric res; |
4228 | | |
4229 | | /* Range bounds must not be NaN/infinity */ |
4230 | 0 | if (NUMERIC_IS_SPECIAL(rmin)) |
4231 | 0 | { |
4232 | 0 | if (NUMERIC_IS_NAN(rmin)) |
4233 | 0 | ereport(ERROR, |
4234 | 0 | errcode(ERRCODE_INVALID_PARAMETER_VALUE), |
4235 | 0 | errmsg("lower bound cannot be NaN")); |
4236 | 0 | else |
4237 | 0 | ereport(ERROR, |
4238 | 0 | errcode(ERRCODE_INVALID_PARAMETER_VALUE), |
4239 | 0 | errmsg("lower bound cannot be infinity")); |
4240 | 0 | } |
4241 | 0 | if (NUMERIC_IS_SPECIAL(rmax)) |
4242 | 0 | { |
4243 | 0 | if (NUMERIC_IS_NAN(rmax)) |
4244 | 0 | ereport(ERROR, |
4245 | 0 | errcode(ERRCODE_INVALID_PARAMETER_VALUE), |
4246 | 0 | errmsg("upper bound cannot be NaN")); |
4247 | 0 | else |
4248 | 0 | ereport(ERROR, |
4249 | 0 | errcode(ERRCODE_INVALID_PARAMETER_VALUE), |
4250 | 0 | errmsg("upper bound cannot be infinity")); |
4251 | 0 | } |
4252 | | |
4253 | | /* Return a random value in the range [rmin, rmax] */ |
4254 | 0 | init_var_from_num(rmin, &rmin_var); |
4255 | 0 | init_var_from_num(rmax, &rmax_var); |
4256 | |
|
4257 | 0 | init_var(&result); |
4258 | |
|
4259 | 0 | random_var(state, &rmin_var, &rmax_var, &result); |
4260 | |
|
4261 | 0 | res = make_result(&result); |
4262 | |
|
4263 | 0 | free_var(&result); |
4264 | |
|
4265 | 0 | return res; |
4266 | 0 | } |
4267 | | |
4268 | | |
4269 | | /* ---------------------------------------------------------------------- |
4270 | | * |
4271 | | * Type conversion functions |
4272 | | * |
4273 | | * ---------------------------------------------------------------------- |
4274 | | */ |
4275 | | |
4276 | | Numeric |
4277 | | int64_to_numeric(int64 val) |
4278 | 0 | { |
4279 | 0 | Numeric res; |
4280 | 0 | NumericVar result; |
4281 | |
|
4282 | 0 | init_var(&result); |
4283 | |
|
4284 | 0 | int64_to_numericvar(val, &result); |
4285 | |
|
4286 | 0 | res = make_result(&result); |
4287 | |
|
4288 | 0 | free_var(&result); |
4289 | |
|
4290 | 0 | return res; |
4291 | 0 | } |
4292 | | |
4293 | | /* |
4294 | | * Convert val1/(10**log10val2) to numeric. This is much faster than normal |
4295 | | * numeric division. |
4296 | | */ |
4297 | | Numeric |
4298 | | int64_div_fast_to_numeric(int64 val1, int log10val2) |
4299 | 0 | { |
4300 | 0 | Numeric res; |
4301 | 0 | NumericVar result; |
4302 | 0 | int rscale; |
4303 | 0 | int w; |
4304 | 0 | int m; |
4305 | |
|
4306 | 0 | init_var(&result); |
4307 | | |
4308 | | /* result scale */ |
4309 | 0 | rscale = log10val2 < 0 ? 0 : log10val2; |
4310 | | |
4311 | | /* how much to decrease the weight by */ |
4312 | 0 | w = log10val2 / DEC_DIGITS; |
4313 | | /* how much is left to divide by */ |
4314 | 0 | m = log10val2 % DEC_DIGITS; |
4315 | 0 | if (m < 0) |
4316 | 0 | { |
4317 | 0 | m += DEC_DIGITS; |
4318 | 0 | w--; |
4319 | 0 | } |
4320 | | |
4321 | | /* |
4322 | | * If there is anything left to divide by (10^m with 0 < m < DEC_DIGITS), |
4323 | | * multiply the dividend by 10^(DEC_DIGITS - m), and shift the weight by |
4324 | | * one more. |
4325 | | */ |
4326 | 0 | if (m > 0) |
4327 | 0 | { |
4328 | 0 | #if DEC_DIGITS == 4 |
4329 | 0 | static const int pow10[] = {1, 10, 100, 1000}; |
4330 | | #elif DEC_DIGITS == 2 |
4331 | | static const int pow10[] = {1, 10}; |
4332 | | #elif DEC_DIGITS == 1 |
4333 | | static const int pow10[] = {1}; |
4334 | | #else |
4335 | | #error unsupported NBASE |
4336 | | #endif |
4337 | 0 | int64 factor = pow10[DEC_DIGITS - m]; |
4338 | 0 | int64 new_val1; |
4339 | |
|
4340 | 0 | StaticAssertDecl(lengthof(pow10) == DEC_DIGITS, "mismatch with DEC_DIGITS"); |
4341 | |
|
4342 | 0 | if (unlikely(pg_mul_s64_overflow(val1, factor, &new_val1))) |
4343 | 0 | { |
4344 | | /* do the multiplication using 128-bit integers */ |
4345 | 0 | INT128 tmp; |
4346 | |
|
4347 | 0 | tmp = int64_to_int128(0); |
4348 | 0 | int128_add_int64_mul_int64(&tmp, val1, factor); |
4349 | |
|
4350 | 0 | int128_to_numericvar(tmp, &result); |
4351 | 0 | } |
4352 | 0 | else |
4353 | 0 | int64_to_numericvar(new_val1, &result); |
4354 | |
|
4355 | 0 | w++; |
4356 | 0 | } |
4357 | 0 | else |
4358 | 0 | int64_to_numericvar(val1, &result); |
4359 | |
|
4360 | 0 | result.weight -= w; |
4361 | 0 | result.dscale = rscale; |
4362 | |
|
4363 | 0 | res = make_result(&result); |
4364 | |
|
4365 | 0 | free_var(&result); |
4366 | |
|
4367 | 0 | return res; |
4368 | 0 | } |
4369 | | |
4370 | | Datum |
4371 | | int4_numeric(PG_FUNCTION_ARGS) |
4372 | 0 | { |
4373 | 0 | int32 val = PG_GETARG_INT32(0); |
4374 | |
|
4375 | 0 | PG_RETURN_NUMERIC(int64_to_numeric(val)); |
4376 | 0 | } |
4377 | | |
4378 | | /* |
4379 | | * Internal version of numeric_int4() with support for soft error reporting. |
4380 | | */ |
4381 | | int32 |
4382 | | numeric_int4_safe(Numeric num, Node *escontext) |
4383 | 0 | { |
4384 | 0 | NumericVar x; |
4385 | 0 | int32 result; |
4386 | |
|
4387 | 0 | if (NUMERIC_IS_SPECIAL(num)) |
4388 | 0 | { |
4389 | 0 | if (NUMERIC_IS_NAN(num)) |
4390 | 0 | ereturn(escontext, 0, |
4391 | 0 | (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), |
4392 | 0 | errmsg("cannot convert NaN to %s", "integer"))); |
4393 | 0 | else |
4394 | 0 | ereturn(escontext, 0, |
4395 | 0 | (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), |
4396 | 0 | errmsg("cannot convert infinity to %s", "integer"))); |
4397 | 0 | } |
4398 | | |
4399 | | /* Convert to variable format, then convert to int4 */ |
4400 | 0 | init_var_from_num(num, &x); |
4401 | |
|
4402 | 0 | if (!numericvar_to_int32(&x, &result)) |
4403 | 0 | ereturn(escontext, 0, |
4404 | 0 | (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), |
4405 | 0 | errmsg("integer out of range"))); |
4406 | | |
4407 | 0 | return result; |
4408 | 0 | } |
4409 | | |
4410 | | Datum |
4411 | | numeric_int4(PG_FUNCTION_ARGS) |
4412 | 0 | { |
4413 | 0 | Numeric num = PG_GETARG_NUMERIC(0); |
4414 | 0 | int32 result; |
4415 | |
|
4416 | 0 | result = numeric_int4_safe(num, fcinfo->context); |
4417 | |
|
4418 | 0 | if (unlikely(SOFT_ERROR_OCCURRED(fcinfo->context))) |
4419 | 0 | PG_RETURN_NULL(); |
4420 | | |
4421 | 0 | PG_RETURN_INT32(result); |
4422 | 0 | } |
4423 | | |
4424 | | /* |
4425 | | * Given a NumericVar, convert it to an int32. If the NumericVar |
4426 | | * exceeds the range of an int32, false is returned, otherwise true is returned. |
4427 | | * The input NumericVar is *not* free'd. |
4428 | | */ |
4429 | | static bool |
4430 | | numericvar_to_int32(const NumericVar *var, int32 *result) |
4431 | 0 | { |
4432 | 0 | int64 val; |
4433 | |
|
4434 | 0 | if (!numericvar_to_int64(var, &val)) |
4435 | 0 | return false; |
4436 | | |
4437 | 0 | if (unlikely(val < PG_INT32_MIN) || unlikely(val > PG_INT32_MAX)) |
4438 | 0 | return false; |
4439 | | |
4440 | | /* Down-convert to int4 */ |
4441 | 0 | *result = (int32) val; |
4442 | |
|
4443 | 0 | return true; |
4444 | 0 | } |
4445 | | |
4446 | | Datum |
4447 | | int8_numeric(PG_FUNCTION_ARGS) |
4448 | 0 | { |
4449 | 0 | int64 val = PG_GETARG_INT64(0); |
4450 | |
|
4451 | 0 | PG_RETURN_NUMERIC(int64_to_numeric(val)); |
4452 | 0 | } |
4453 | | |
4454 | | /* |
4455 | | * Internal version of numeric_int8() with support for soft error reporting. |
4456 | | */ |
4457 | | int64 |
4458 | | numeric_int8_safe(Numeric num, Node *escontext) |
4459 | 0 | { |
4460 | 0 | NumericVar x; |
4461 | 0 | int64 result; |
4462 | |
|
4463 | 0 | if (NUMERIC_IS_SPECIAL(num)) |
4464 | 0 | { |
4465 | 0 | if (NUMERIC_IS_NAN(num)) |
4466 | 0 | ereturn(escontext, 0, |
4467 | 0 | (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), |
4468 | 0 | errmsg("cannot convert NaN to %s", "bigint"))); |
4469 | 0 | else |
4470 | 0 | ereturn(escontext, 0, |
4471 | 0 | (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), |
4472 | 0 | errmsg("cannot convert infinity to %s", "bigint"))); |
4473 | 0 | } |
4474 | | |
4475 | | /* Convert to variable format, then convert to int8 */ |
4476 | 0 | init_var_from_num(num, &x); |
4477 | |
|
4478 | 0 | if (!numericvar_to_int64(&x, &result)) |
4479 | 0 | ereturn(escontext, 0, |
4480 | 0 | (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), |
4481 | 0 | errmsg("bigint out of range"))); |
4482 | | |
4483 | 0 | return result; |
4484 | 0 | } |
4485 | | |
4486 | | Datum |
4487 | | numeric_int8(PG_FUNCTION_ARGS) |
4488 | 0 | { |
4489 | 0 | Numeric num = PG_GETARG_NUMERIC(0); |
4490 | 0 | int64 result; |
4491 | |
|
4492 | 0 | result = numeric_int8_safe(num, fcinfo->context); |
4493 | |
|
4494 | 0 | if (unlikely(SOFT_ERROR_OCCURRED(fcinfo->context))) |
4495 | 0 | PG_RETURN_NULL(); |
4496 | | |
4497 | 0 | PG_RETURN_INT64(result); |
4498 | 0 | } |
4499 | | |
4500 | | |
4501 | | Datum |
4502 | | int2_numeric(PG_FUNCTION_ARGS) |
4503 | 0 | { |
4504 | 0 | int16 val = PG_GETARG_INT16(0); |
4505 | |
|
4506 | 0 | PG_RETURN_NUMERIC(int64_to_numeric(val)); |
4507 | 0 | } |
4508 | | |
4509 | | |
4510 | | Datum |
4511 | | numeric_int2(PG_FUNCTION_ARGS) |
4512 | 0 | { |
4513 | 0 | Numeric num = PG_GETARG_NUMERIC(0); |
4514 | 0 | NumericVar x; |
4515 | 0 | int64 val; |
4516 | 0 | int16 result; |
4517 | |
|
4518 | 0 | if (NUMERIC_IS_SPECIAL(num)) |
4519 | 0 | { |
4520 | 0 | if (NUMERIC_IS_NAN(num)) |
4521 | 0 | ereturn(fcinfo->context, (Datum) 0, |
4522 | 0 | (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), |
4523 | 0 | errmsg("cannot convert NaN to %s", "smallint"))); |
4524 | 0 | else |
4525 | 0 | ereturn(fcinfo->context, (Datum) 0, |
4526 | 0 | (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), |
4527 | 0 | errmsg("cannot convert infinity to %s", "smallint"))); |
4528 | 0 | } |
4529 | | |
4530 | | /* Convert to variable format and thence to int8 */ |
4531 | 0 | init_var_from_num(num, &x); |
4532 | |
|
4533 | 0 | if (!numericvar_to_int64(&x, &val)) |
4534 | 0 | ereturn(fcinfo->context, (Datum) 0, |
4535 | 0 | (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), |
4536 | 0 | errmsg("smallint out of range"))); |
4537 | | |
4538 | 0 | if (unlikely(val < PG_INT16_MIN) || unlikely(val > PG_INT16_MAX)) |
4539 | 0 | ereturn(fcinfo->context, (Datum) 0, |
4540 | 0 | (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), |
4541 | 0 | errmsg("smallint out of range"))); |
4542 | | |
4543 | | /* Down-convert to int2 */ |
4544 | 0 | result = (int16) val; |
4545 | |
|
4546 | 0 | PG_RETURN_INT16(result); |
4547 | 0 | } |
4548 | | |
4549 | | |
4550 | | Datum |
4551 | | float8_numeric(PG_FUNCTION_ARGS) |
4552 | 0 | { |
4553 | 0 | float8 val = PG_GETARG_FLOAT8(0); |
4554 | 0 | Numeric res; |
4555 | 0 | NumericVar result; |
4556 | 0 | char buf[DBL_DIG + 100]; |
4557 | 0 | const char *endptr; |
4558 | |
|
4559 | 0 | if (isnan(val)) |
4560 | 0 | PG_RETURN_NUMERIC(make_result(&const_nan)); |
4561 | | |
4562 | 0 | if (isinf(val)) |
4563 | 0 | { |
4564 | 0 | if (val < 0) |
4565 | 0 | PG_RETURN_NUMERIC(make_result(&const_ninf)); |
4566 | 0 | else |
4567 | 0 | PG_RETURN_NUMERIC(make_result(&const_pinf)); |
4568 | 0 | } |
4569 | | |
4570 | 0 | snprintf(buf, sizeof(buf), "%.*g", DBL_DIG, val); |
4571 | |
|
4572 | 0 | init_var(&result); |
4573 | | |
4574 | | /* Assume we need not worry about leading/trailing spaces */ |
4575 | 0 | if (!set_var_from_str(buf, buf, &result, &endptr, fcinfo->context)) |
4576 | 0 | PG_RETURN_NULL(); |
4577 | | |
4578 | 0 | res = make_result(&result); |
4579 | |
|
4580 | 0 | free_var(&result); |
4581 | |
|
4582 | 0 | PG_RETURN_NUMERIC(res); |
4583 | 0 | } |
4584 | | |
4585 | | |
4586 | | Datum |
4587 | | numeric_float8(PG_FUNCTION_ARGS) |
4588 | 0 | { |
4589 | 0 | Numeric num = PG_GETARG_NUMERIC(0); |
4590 | 0 | char *tmp; |
4591 | 0 | Datum result; |
4592 | |
|
4593 | 0 | if (NUMERIC_IS_SPECIAL(num)) |
4594 | 0 | { |
4595 | 0 | if (NUMERIC_IS_PINF(num)) |
4596 | 0 | PG_RETURN_FLOAT8(get_float8_infinity()); |
4597 | 0 | else if (NUMERIC_IS_NINF(num)) |
4598 | 0 | PG_RETURN_FLOAT8(-get_float8_infinity()); |
4599 | 0 | else |
4600 | 0 | PG_RETURN_FLOAT8(get_float8_nan()); |
4601 | 0 | } |
4602 | | |
4603 | 0 | tmp = DatumGetCString(DirectFunctionCall1(numeric_out, |
4604 | 0 | NumericGetDatum(num))); |
4605 | 0 | if (!DirectInputFunctionCallSafe(float8in, tmp, |
4606 | 0 | InvalidOid, -1, |
4607 | 0 | (Node *) fcinfo->context, |
4608 | 0 | &result)) |
4609 | 0 | { |
4610 | 0 | pfree(tmp); |
4611 | 0 | PG_RETURN_NULL(); |
4612 | 0 | } |
4613 | | |
4614 | 0 | PG_RETURN_DATUM(result); |
4615 | 0 | } |
4616 | | |
4617 | | |
4618 | | /* |
4619 | | * Convert numeric to float8; if out of range, return +/- HUGE_VAL |
4620 | | * |
4621 | | * (internal helper function, not directly callable from SQL) |
4622 | | */ |
4623 | | Datum |
4624 | | numeric_float8_no_overflow(PG_FUNCTION_ARGS) |
4625 | 0 | { |
4626 | 0 | Numeric num = PG_GETARG_NUMERIC(0); |
4627 | 0 | double val; |
4628 | |
|
4629 | 0 | if (NUMERIC_IS_SPECIAL(num)) |
4630 | 0 | { |
4631 | 0 | if (NUMERIC_IS_PINF(num)) |
4632 | 0 | val = HUGE_VAL; |
4633 | 0 | else if (NUMERIC_IS_NINF(num)) |
4634 | 0 | val = -HUGE_VAL; |
4635 | 0 | else |
4636 | 0 | val = get_float8_nan(); |
4637 | 0 | } |
4638 | 0 | else |
4639 | 0 | { |
4640 | 0 | NumericVar x; |
4641 | |
|
4642 | 0 | init_var_from_num(num, &x); |
4643 | 0 | val = numericvar_to_double_no_overflow(&x); |
4644 | 0 | } |
4645 | |
|
4646 | 0 | PG_RETURN_FLOAT8(val); |
4647 | 0 | } |
4648 | | |
4649 | | Datum |
4650 | | float4_numeric(PG_FUNCTION_ARGS) |
4651 | 0 | { |
4652 | 0 | float4 val = PG_GETARG_FLOAT4(0); |
4653 | 0 | Numeric res; |
4654 | 0 | NumericVar result; |
4655 | 0 | char buf[FLT_DIG + 100]; |
4656 | 0 | const char *endptr; |
4657 | |
|
4658 | 0 | if (isnan(val)) |
4659 | 0 | PG_RETURN_NUMERIC(make_result(&const_nan)); |
4660 | | |
4661 | 0 | if (isinf(val)) |
4662 | 0 | { |
4663 | 0 | if (val < 0) |
4664 | 0 | PG_RETURN_NUMERIC(make_result(&const_ninf)); |
4665 | 0 | else |
4666 | 0 | PG_RETURN_NUMERIC(make_result(&const_pinf)); |
4667 | 0 | } |
4668 | | |
4669 | 0 | snprintf(buf, sizeof(buf), "%.*g", FLT_DIG, val); |
4670 | |
|
4671 | 0 | init_var(&result); |
4672 | | |
4673 | | /* Assume we need not worry about leading/trailing spaces */ |
4674 | 0 | if (!set_var_from_str(buf, buf, &result, &endptr, fcinfo->context)) |
4675 | 0 | PG_RETURN_NULL(); |
4676 | | |
4677 | 0 | res = make_result(&result); |
4678 | |
|
4679 | 0 | free_var(&result); |
4680 | |
|
4681 | 0 | PG_RETURN_NUMERIC(res); |
4682 | 0 | } |
4683 | | |
4684 | | |
4685 | | Datum |
4686 | | numeric_float4(PG_FUNCTION_ARGS) |
4687 | 0 | { |
4688 | 0 | Numeric num = PG_GETARG_NUMERIC(0); |
4689 | 0 | char *tmp; |
4690 | 0 | Datum result; |
4691 | |
|
4692 | 0 | if (NUMERIC_IS_SPECIAL(num)) |
4693 | 0 | { |
4694 | 0 | if (NUMERIC_IS_PINF(num)) |
4695 | 0 | PG_RETURN_FLOAT4(get_float4_infinity()); |
4696 | 0 | else if (NUMERIC_IS_NINF(num)) |
4697 | 0 | PG_RETURN_FLOAT4(-get_float4_infinity()); |
4698 | 0 | else |
4699 | 0 | PG_RETURN_FLOAT4(get_float4_nan()); |
4700 | 0 | } |
4701 | | |
4702 | 0 | tmp = DatumGetCString(DirectFunctionCall1(numeric_out, |
4703 | 0 | NumericGetDatum(num))); |
4704 | |
|
4705 | 0 | if (!DirectInputFunctionCallSafe(float4in, tmp, |
4706 | 0 | InvalidOid, -1, |
4707 | 0 | (Node *) fcinfo->context, |
4708 | 0 | &result)) |
4709 | 0 | { |
4710 | 0 | pfree(tmp); |
4711 | 0 | PG_RETURN_NULL(); |
4712 | 0 | } |
4713 | | |
4714 | 0 | pfree(tmp); |
4715 | |
|
4716 | 0 | PG_RETURN_DATUM(result); |
4717 | 0 | } |
4718 | | |
4719 | | |
4720 | | Datum |
4721 | | numeric_pg_lsn(PG_FUNCTION_ARGS) |
4722 | 0 | { |
4723 | 0 | Numeric num = PG_GETARG_NUMERIC(0); |
4724 | 0 | NumericVar x; |
4725 | 0 | XLogRecPtr result; |
4726 | |
|
4727 | 0 | if (NUMERIC_IS_SPECIAL(num)) |
4728 | 0 | { |
4729 | 0 | if (NUMERIC_IS_NAN(num)) |
4730 | 0 | ereport(ERROR, |
4731 | 0 | (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), |
4732 | 0 | errmsg("cannot convert NaN to %s", "pg_lsn"))); |
4733 | 0 | else |
4734 | 0 | ereport(ERROR, |
4735 | 0 | (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), |
4736 | 0 | errmsg("cannot convert infinity to %s", "pg_lsn"))); |
4737 | 0 | } |
4738 | | |
4739 | | /* Convert to variable format and thence to pg_lsn */ |
4740 | 0 | init_var_from_num(num, &x); |
4741 | |
|
4742 | 0 | if (!numericvar_to_uint64(&x, (uint64 *) &result)) |
4743 | 0 | ereport(ERROR, |
4744 | 0 | (errcode(ERRCODE_INVALID_PARAMETER_VALUE), |
4745 | 0 | errmsg("pg_lsn out of range"))); |
4746 | | |
4747 | 0 | PG_RETURN_LSN(result); |
4748 | 0 | } |
4749 | | |
4750 | | |
4751 | | /* ---------------------------------------------------------------------- |
4752 | | * |
4753 | | * Aggregate functions |
4754 | | * |
4755 | | * The transition datatype for all these aggregates is declared as INTERNAL. |
4756 | | * Actually, it's a pointer to a NumericAggState allocated in the aggregate |
4757 | | * context. The digit buffers for the NumericVars will be there too. |
4758 | | * |
4759 | | * For integer inputs, some aggregates use special-purpose 64-bit or 128-bit |
4760 | | * integer based transition datatypes to speed up calculations. |
4761 | | * |
4762 | | * ---------------------------------------------------------------------- |
4763 | | */ |
4764 | | |
4765 | | typedef struct NumericAggState |
4766 | | { |
4767 | | bool calcSumX2; /* if true, calculate sumX2 */ |
4768 | | MemoryContext agg_context; /* context we're calculating in */ |
4769 | | int64 N; /* count of processed numbers */ |
4770 | | NumericSumAccum sumX; /* sum of processed numbers */ |
4771 | | NumericSumAccum sumX2; /* sum of squares of processed numbers */ |
4772 | | int maxScale; /* maximum scale seen so far */ |
4773 | | int64 maxScaleCount; /* number of values seen with maximum scale */ |
4774 | | /* These counts are *not* included in N! Use NA_TOTAL_COUNT() as needed */ |
4775 | | int64 NaNcount; /* count of NaN values */ |
4776 | | int64 pInfcount; /* count of +Inf values */ |
4777 | | int64 nInfcount; /* count of -Inf values */ |
4778 | | } NumericAggState; |
4779 | | |
4780 | | #define NA_TOTAL_COUNT(na) \ |
4781 | 0 | ((na)->N + (na)->NaNcount + (na)->pInfcount + (na)->nInfcount) |
4782 | | |
4783 | | /* |
4784 | | * Prepare state data for a numeric aggregate function that needs to compute |
4785 | | * sum, count and optionally sum of squares of the input. |
4786 | | */ |
4787 | | static NumericAggState * |
4788 | | makeNumericAggState(FunctionCallInfo fcinfo, bool calcSumX2) |
4789 | 0 | { |
4790 | 0 | NumericAggState *state; |
4791 | 0 | MemoryContext agg_context; |
4792 | 0 | MemoryContext old_context; |
4793 | |
|
4794 | 0 | if (!AggCheckCallContext(fcinfo, &agg_context)) |
4795 | 0 | elog(ERROR, "aggregate function called in non-aggregate context"); |
4796 | | |
4797 | 0 | old_context = MemoryContextSwitchTo(agg_context); |
4798 | |
|
4799 | 0 | state = palloc0_object(NumericAggState); |
4800 | 0 | state->calcSumX2 = calcSumX2; |
4801 | 0 | state->agg_context = agg_context; |
4802 | |
|
4803 | 0 | MemoryContextSwitchTo(old_context); |
4804 | |
|
4805 | 0 | return state; |
4806 | 0 | } |
4807 | | |
4808 | | /* |
4809 | | * Like makeNumericAggState(), but allocate the state in the current memory |
4810 | | * context. |
4811 | | */ |
4812 | | static NumericAggState * |
4813 | | makeNumericAggStateCurrentContext(bool calcSumX2) |
4814 | 0 | { |
4815 | 0 | NumericAggState *state; |
4816 | |
|
4817 | 0 | state = palloc0_object(NumericAggState); |
4818 | 0 | state->calcSumX2 = calcSumX2; |
4819 | 0 | state->agg_context = CurrentMemoryContext; |
4820 | |
|
4821 | 0 | return state; |
4822 | 0 | } |
4823 | | |
4824 | | /* |
4825 | | * Accumulate a new input value for numeric aggregate functions. |
4826 | | */ |
4827 | | static void |
4828 | | do_numeric_accum(NumericAggState *state, Numeric newval) |
4829 | 0 | { |
4830 | 0 | NumericVar X; |
4831 | 0 | NumericVar X2; |
4832 | 0 | MemoryContext old_context; |
4833 | | |
4834 | | /* Count NaN/infinity inputs separately from all else */ |
4835 | 0 | if (NUMERIC_IS_SPECIAL(newval)) |
4836 | 0 | { |
4837 | 0 | if (NUMERIC_IS_PINF(newval)) |
4838 | 0 | state->pInfcount++; |
4839 | 0 | else if (NUMERIC_IS_NINF(newval)) |
4840 | 0 | state->nInfcount++; |
4841 | 0 | else |
4842 | 0 | state->NaNcount++; |
4843 | 0 | return; |
4844 | 0 | } |
4845 | | |
4846 | | /* load processed number in short-lived context */ |
4847 | 0 | init_var_from_num(newval, &X); |
4848 | | |
4849 | | /* |
4850 | | * Track the highest input dscale that we've seen, to support inverse |
4851 | | * transitions (see do_numeric_discard). |
4852 | | */ |
4853 | 0 | if (X.dscale > state->maxScale) |
4854 | 0 | { |
4855 | 0 | state->maxScale = X.dscale; |
4856 | 0 | state->maxScaleCount = 1; |
4857 | 0 | } |
4858 | 0 | else if (X.dscale == state->maxScale) |
4859 | 0 | state->maxScaleCount++; |
4860 | | |
4861 | | /* if we need X^2, calculate that in short-lived context */ |
4862 | 0 | if (state->calcSumX2) |
4863 | 0 | { |
4864 | 0 | init_var(&X2); |
4865 | 0 | mul_var(&X, &X, &X2, X.dscale * 2); |
4866 | 0 | } |
4867 | | |
4868 | | /* The rest of this needs to work in the aggregate context */ |
4869 | 0 | old_context = MemoryContextSwitchTo(state->agg_context); |
4870 | |
|
4871 | 0 | state->N++; |
4872 | | |
4873 | | /* Accumulate sums */ |
4874 | 0 | accum_sum_add(&(state->sumX), &X); |
4875 | |
|
4876 | 0 | if (state->calcSumX2) |
4877 | 0 | accum_sum_add(&(state->sumX2), &X2); |
4878 | |
|
4879 | 0 | MemoryContextSwitchTo(old_context); |
4880 | 0 | } |
4881 | | |
4882 | | /* |
4883 | | * Attempt to remove an input value from the aggregated state. |
4884 | | * |
4885 | | * If the value cannot be removed then the function will return false; the |
4886 | | * possible reasons for failing are described below. |
4887 | | * |
4888 | | * If we aggregate the values 1.01 and 2 then the result will be 3.01. |
4889 | | * If we are then asked to un-aggregate the 1.01 then we must fail as we |
4890 | | * won't be able to tell what the new aggregated value's dscale should be. |
4891 | | * We don't want to return 2.00 (dscale = 2), since the sum's dscale would |
4892 | | * have been zero if we'd really aggregated only 2. |
4893 | | * |
4894 | | * Note: alternatively, we could count the number of inputs with each possible |
4895 | | * dscale (up to some sane limit). Not yet clear if it's worth the trouble. |
4896 | | */ |
4897 | | static bool |
4898 | | do_numeric_discard(NumericAggState *state, Numeric newval) |
4899 | 0 | { |
4900 | 0 | NumericVar X; |
4901 | 0 | NumericVar X2; |
4902 | 0 | MemoryContext old_context; |
4903 | | |
4904 | | /* Count NaN/infinity inputs separately from all else */ |
4905 | 0 | if (NUMERIC_IS_SPECIAL(newval)) |
4906 | 0 | { |
4907 | 0 | if (NUMERIC_IS_PINF(newval)) |
4908 | 0 | state->pInfcount--; |
4909 | 0 | else if (NUMERIC_IS_NINF(newval)) |
4910 | 0 | state->nInfcount--; |
4911 | 0 | else |
4912 | 0 | state->NaNcount--; |
4913 | 0 | return true; |
4914 | 0 | } |
4915 | | |
4916 | | /* load processed number in short-lived context */ |
4917 | 0 | init_var_from_num(newval, &X); |
4918 | | |
4919 | | /* |
4920 | | * state->sumX's dscale is the maximum dscale of any of the inputs. |
4921 | | * Removing the last input with that dscale would require us to recompute |
4922 | | * the maximum dscale of the *remaining* inputs, which we cannot do unless |
4923 | | * no more non-NaN inputs remain at all. So we report a failure instead, |
4924 | | * and force the aggregation to be redone from scratch. |
4925 | | */ |
4926 | 0 | if (X.dscale == state->maxScale) |
4927 | 0 | { |
4928 | 0 | if (state->maxScaleCount > 1 || state->maxScale == 0) |
4929 | 0 | { |
4930 | | /* |
4931 | | * Some remaining inputs have same dscale, or dscale hasn't gotten |
4932 | | * above zero anyway |
4933 | | */ |
4934 | 0 | state->maxScaleCount--; |
4935 | 0 | } |
4936 | 0 | else if (state->N == 1) |
4937 | 0 | { |
4938 | | /* No remaining non-NaN inputs at all, so reset maxScale */ |
4939 | 0 | state->maxScale = 0; |
4940 | 0 | state->maxScaleCount = 0; |
4941 | 0 | } |
4942 | 0 | else |
4943 | 0 | { |
4944 | | /* Correct new maxScale is uncertain, must fail */ |
4945 | 0 | return false; |
4946 | 0 | } |
4947 | 0 | } |
4948 | | |
4949 | | /* if we need X^2, calculate that in short-lived context */ |
4950 | 0 | if (state->calcSumX2) |
4951 | 0 | { |
4952 | 0 | init_var(&X2); |
4953 | 0 | mul_var(&X, &X, &X2, X.dscale * 2); |
4954 | 0 | } |
4955 | | |
4956 | | /* The rest of this needs to work in the aggregate context */ |
4957 | 0 | old_context = MemoryContextSwitchTo(state->agg_context); |
4958 | |
|
4959 | 0 | if (state->N-- > 1) |
4960 | 0 | { |
4961 | | /* Negate X, to subtract it from the sum */ |
4962 | 0 | X.sign = (X.sign == NUMERIC_POS ? NUMERIC_NEG : NUMERIC_POS); |
4963 | 0 | accum_sum_add(&(state->sumX), &X); |
4964 | |
|
4965 | 0 | if (state->calcSumX2) |
4966 | 0 | { |
4967 | | /* Negate X^2. X^2 is always positive */ |
4968 | 0 | X2.sign = NUMERIC_NEG; |
4969 | 0 | accum_sum_add(&(state->sumX2), &X2); |
4970 | 0 | } |
4971 | 0 | } |
4972 | 0 | else |
4973 | 0 | { |
4974 | | /* Zero the sums */ |
4975 | 0 | Assert(state->N == 0); |
4976 | |
|
4977 | 0 | accum_sum_reset(&state->sumX); |
4978 | 0 | if (state->calcSumX2) |
4979 | 0 | accum_sum_reset(&state->sumX2); |
4980 | 0 | } |
4981 | |
|
4982 | 0 | MemoryContextSwitchTo(old_context); |
4983 | |
|
4984 | 0 | return true; |
4985 | 0 | } |
4986 | | |
4987 | | /* |
4988 | | * Generic transition function for numeric aggregates that require sumX2. |
4989 | | */ |
4990 | | Datum |
4991 | | numeric_accum(PG_FUNCTION_ARGS) |
4992 | 0 | { |
4993 | 0 | NumericAggState *state; |
4994 | |
|
4995 | 0 | state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0); |
4996 | | |
4997 | | /* Create the state data on the first call */ |
4998 | 0 | if (state == NULL) |
4999 | 0 | state = makeNumericAggState(fcinfo, true); |
5000 | |
|
5001 | 0 | if (!PG_ARGISNULL(1)) |
5002 | 0 | do_numeric_accum(state, PG_GETARG_NUMERIC(1)); |
5003 | |
|
5004 | 0 | PG_RETURN_POINTER(state); |
5005 | 0 | } |
5006 | | |
5007 | | /* |
5008 | | * Generic combine function for numeric aggregates which require sumX2 |
5009 | | */ |
5010 | | Datum |
5011 | | numeric_combine(PG_FUNCTION_ARGS) |
5012 | 0 | { |
5013 | 0 | NumericAggState *state1; |
5014 | 0 | NumericAggState *state2; |
5015 | 0 | MemoryContext agg_context; |
5016 | 0 | MemoryContext old_context; |
5017 | |
|
5018 | 0 | if (!AggCheckCallContext(fcinfo, &agg_context)) |
5019 | 0 | elog(ERROR, "aggregate function called in non-aggregate context"); |
5020 | | |
5021 | 0 | state1 = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0); |
5022 | 0 | state2 = PG_ARGISNULL(1) ? NULL : (NumericAggState *) PG_GETARG_POINTER(1); |
5023 | |
|
5024 | 0 | if (state2 == NULL) |
5025 | 0 | { |
5026 | | /* |
5027 | | * NULL state2 is easy, just return state1, which we know is already |
5028 | | * in the agg_context |
5029 | | */ |
5030 | 0 | if (state1 == NULL) |
5031 | 0 | PG_RETURN_NULL(); |
5032 | 0 | PG_RETURN_POINTER(state1); |
5033 | 0 | } |
5034 | | |
5035 | | /* manually copy all fields from state2 to state1 */ |
5036 | 0 | if (state1 == NULL) |
5037 | 0 | { |
5038 | 0 | old_context = MemoryContextSwitchTo(agg_context); |
5039 | |
|
5040 | 0 | state1 = makeNumericAggStateCurrentContext(true); |
5041 | 0 | state1->N = state2->N; |
5042 | 0 | state1->NaNcount = state2->NaNcount; |
5043 | 0 | state1->pInfcount = state2->pInfcount; |
5044 | 0 | state1->nInfcount = state2->nInfcount; |
5045 | 0 | state1->maxScale = state2->maxScale; |
5046 | 0 | state1->maxScaleCount = state2->maxScaleCount; |
5047 | |
|
5048 | 0 | accum_sum_copy(&state1->sumX, &state2->sumX); |
5049 | 0 | accum_sum_copy(&state1->sumX2, &state2->sumX2); |
5050 | |
|
5051 | 0 | MemoryContextSwitchTo(old_context); |
5052 | |
|
5053 | 0 | PG_RETURN_POINTER(state1); |
5054 | 0 | } |
5055 | | |
5056 | 0 | state1->N += state2->N; |
5057 | 0 | state1->NaNcount += state2->NaNcount; |
5058 | 0 | state1->pInfcount += state2->pInfcount; |
5059 | 0 | state1->nInfcount += state2->nInfcount; |
5060 | |
|
5061 | 0 | if (state2->N > 0) |
5062 | 0 | { |
5063 | | /* |
5064 | | * These are currently only needed for moving aggregates, but let's do |
5065 | | * the right thing anyway... |
5066 | | */ |
5067 | 0 | if (state2->maxScale > state1->maxScale) |
5068 | 0 | { |
5069 | 0 | state1->maxScale = state2->maxScale; |
5070 | 0 | state1->maxScaleCount = state2->maxScaleCount; |
5071 | 0 | } |
5072 | 0 | else if (state2->maxScale == state1->maxScale) |
5073 | 0 | state1->maxScaleCount += state2->maxScaleCount; |
5074 | | |
5075 | | /* The rest of this needs to work in the aggregate context */ |
5076 | 0 | old_context = MemoryContextSwitchTo(agg_context); |
5077 | | |
5078 | | /* Accumulate sums */ |
5079 | 0 | accum_sum_combine(&state1->sumX, &state2->sumX); |
5080 | 0 | accum_sum_combine(&state1->sumX2, &state2->sumX2); |
5081 | |
|
5082 | 0 | MemoryContextSwitchTo(old_context); |
5083 | 0 | } |
5084 | 0 | PG_RETURN_POINTER(state1); |
5085 | 0 | } |
5086 | | |
5087 | | /* |
5088 | | * Generic transition function for numeric aggregates that don't require sumX2. |
5089 | | */ |
5090 | | Datum |
5091 | | numeric_avg_accum(PG_FUNCTION_ARGS) |
5092 | 0 | { |
5093 | 0 | NumericAggState *state; |
5094 | |
|
5095 | 0 | state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0); |
5096 | | |
5097 | | /* Create the state data on the first call */ |
5098 | 0 | if (state == NULL) |
5099 | 0 | state = makeNumericAggState(fcinfo, false); |
5100 | |
|
5101 | 0 | if (!PG_ARGISNULL(1)) |
5102 | 0 | do_numeric_accum(state, PG_GETARG_NUMERIC(1)); |
5103 | |
|
5104 | 0 | PG_RETURN_POINTER(state); |
5105 | 0 | } |
5106 | | |
5107 | | /* |
5108 | | * Combine function for numeric aggregates which don't require sumX2 |
5109 | | */ |
5110 | | Datum |
5111 | | numeric_avg_combine(PG_FUNCTION_ARGS) |
5112 | 0 | { |
5113 | 0 | NumericAggState *state1; |
5114 | 0 | NumericAggState *state2; |
5115 | 0 | MemoryContext agg_context; |
5116 | 0 | MemoryContext old_context; |
5117 | |
|
5118 | 0 | if (!AggCheckCallContext(fcinfo, &agg_context)) |
5119 | 0 | elog(ERROR, "aggregate function called in non-aggregate context"); |
5120 | | |
5121 | 0 | state1 = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0); |
5122 | 0 | state2 = PG_ARGISNULL(1) ? NULL : (NumericAggState *) PG_GETARG_POINTER(1); |
5123 | |
|
5124 | 0 | if (state2 == NULL) |
5125 | 0 | { |
5126 | | /* |
5127 | | * NULL state2 is easy, just return state1, which we know is already |
5128 | | * in the agg_context |
5129 | | */ |
5130 | 0 | if (state1 == NULL) |
5131 | 0 | PG_RETURN_NULL(); |
5132 | 0 | PG_RETURN_POINTER(state1); |
5133 | 0 | } |
5134 | | |
5135 | | /* manually copy all fields from state2 to state1 */ |
5136 | 0 | if (state1 == NULL) |
5137 | 0 | { |
5138 | 0 | old_context = MemoryContextSwitchTo(agg_context); |
5139 | |
|
5140 | 0 | state1 = makeNumericAggStateCurrentContext(false); |
5141 | 0 | state1->N = state2->N; |
5142 | 0 | state1->NaNcount = state2->NaNcount; |
5143 | 0 | state1->pInfcount = state2->pInfcount; |
5144 | 0 | state1->nInfcount = state2->nInfcount; |
5145 | 0 | state1->maxScale = state2->maxScale; |
5146 | 0 | state1->maxScaleCount = state2->maxScaleCount; |
5147 | |
|
5148 | 0 | accum_sum_copy(&state1->sumX, &state2->sumX); |
5149 | |
|
5150 | 0 | MemoryContextSwitchTo(old_context); |
5151 | |
|
5152 | 0 | PG_RETURN_POINTER(state1); |
5153 | 0 | } |
5154 | | |
5155 | 0 | state1->N += state2->N; |
5156 | 0 | state1->NaNcount += state2->NaNcount; |
5157 | 0 | state1->pInfcount += state2->pInfcount; |
5158 | 0 | state1->nInfcount += state2->nInfcount; |
5159 | |
|
5160 | 0 | if (state2->N > 0) |
5161 | 0 | { |
5162 | | /* |
5163 | | * These are currently only needed for moving aggregates, but let's do |
5164 | | * the right thing anyway... |
5165 | | */ |
5166 | 0 | if (state2->maxScale > state1->maxScale) |
5167 | 0 | { |
5168 | 0 | state1->maxScale = state2->maxScale; |
5169 | 0 | state1->maxScaleCount = state2->maxScaleCount; |
5170 | 0 | } |
5171 | 0 | else if (state2->maxScale == state1->maxScale) |
5172 | 0 | state1->maxScaleCount += state2->maxScaleCount; |
5173 | | |
5174 | | /* The rest of this needs to work in the aggregate context */ |
5175 | 0 | old_context = MemoryContextSwitchTo(agg_context); |
5176 | | |
5177 | | /* Accumulate sums */ |
5178 | 0 | accum_sum_combine(&state1->sumX, &state2->sumX); |
5179 | |
|
5180 | 0 | MemoryContextSwitchTo(old_context); |
5181 | 0 | } |
5182 | 0 | PG_RETURN_POINTER(state1); |
5183 | 0 | } |
5184 | | |
5185 | | /* |
5186 | | * numeric_avg_serialize |
5187 | | * Serialize NumericAggState for numeric aggregates that don't require |
5188 | | * sumX2. |
5189 | | */ |
5190 | | Datum |
5191 | | numeric_avg_serialize(PG_FUNCTION_ARGS) |
5192 | 0 | { |
5193 | 0 | NumericAggState *state; |
5194 | 0 | StringInfoData buf; |
5195 | 0 | bytea *result; |
5196 | 0 | NumericVar tmp_var; |
5197 | | |
5198 | | /* Ensure we disallow calling when not in aggregate context */ |
5199 | 0 | if (!AggCheckCallContext(fcinfo, NULL)) |
5200 | 0 | elog(ERROR, "aggregate function called in non-aggregate context"); |
5201 | | |
5202 | 0 | state = (NumericAggState *) PG_GETARG_POINTER(0); |
5203 | |
|
5204 | 0 | init_var(&tmp_var); |
5205 | |
|
5206 | 0 | pq_begintypsend(&buf); |
5207 | | |
5208 | | /* N */ |
5209 | 0 | pq_sendint64(&buf, state->N); |
5210 | | |
5211 | | /* sumX */ |
5212 | 0 | accum_sum_final(&state->sumX, &tmp_var); |
5213 | 0 | numericvar_serialize(&buf, &tmp_var); |
5214 | | |
5215 | | /* maxScale */ |
5216 | 0 | pq_sendint32(&buf, state->maxScale); |
5217 | | |
5218 | | /* maxScaleCount */ |
5219 | 0 | pq_sendint64(&buf, state->maxScaleCount); |
5220 | | |
5221 | | /* NaNcount */ |
5222 | 0 | pq_sendint64(&buf, state->NaNcount); |
5223 | | |
5224 | | /* pInfcount */ |
5225 | 0 | pq_sendint64(&buf, state->pInfcount); |
5226 | | |
5227 | | /* nInfcount */ |
5228 | 0 | pq_sendint64(&buf, state->nInfcount); |
5229 | |
|
5230 | 0 | result = pq_endtypsend(&buf); |
5231 | |
|
5232 | 0 | free_var(&tmp_var); |
5233 | |
|
5234 | 0 | PG_RETURN_BYTEA_P(result); |
5235 | 0 | } |
5236 | | |
5237 | | /* |
5238 | | * numeric_avg_deserialize |
5239 | | * Deserialize bytea into NumericAggState for numeric aggregates that |
5240 | | * don't require sumX2. |
5241 | | */ |
5242 | | Datum |
5243 | | numeric_avg_deserialize(PG_FUNCTION_ARGS) |
5244 | 0 | { |
5245 | 0 | bytea *sstate; |
5246 | 0 | NumericAggState *result; |
5247 | 0 | StringInfoData buf; |
5248 | 0 | NumericVar tmp_var; |
5249 | |
|
5250 | 0 | if (!AggCheckCallContext(fcinfo, NULL)) |
5251 | 0 | elog(ERROR, "aggregate function called in non-aggregate context"); |
5252 | | |
5253 | 0 | sstate = PG_GETARG_BYTEA_PP(0); |
5254 | |
|
5255 | 0 | init_var(&tmp_var); |
5256 | | |
5257 | | /* |
5258 | | * Initialize a StringInfo so that we can "receive" it using the standard |
5259 | | * recv-function infrastructure. |
5260 | | */ |
5261 | 0 | initReadOnlyStringInfo(&buf, VARDATA_ANY(sstate), |
5262 | 0 | VARSIZE_ANY_EXHDR(sstate)); |
5263 | |
|
5264 | 0 | result = makeNumericAggStateCurrentContext(false); |
5265 | | |
5266 | | /* N */ |
5267 | 0 | result->N = pq_getmsgint64(&buf); |
5268 | | |
5269 | | /* sumX */ |
5270 | 0 | numericvar_deserialize(&buf, &tmp_var); |
5271 | 0 | accum_sum_add(&(result->sumX), &tmp_var); |
5272 | | |
5273 | | /* maxScale */ |
5274 | 0 | result->maxScale = pq_getmsgint(&buf, 4); |
5275 | | |
5276 | | /* maxScaleCount */ |
5277 | 0 | result->maxScaleCount = pq_getmsgint64(&buf); |
5278 | | |
5279 | | /* NaNcount */ |
5280 | 0 | result->NaNcount = pq_getmsgint64(&buf); |
5281 | | |
5282 | | /* pInfcount */ |
5283 | 0 | result->pInfcount = pq_getmsgint64(&buf); |
5284 | | |
5285 | | /* nInfcount */ |
5286 | 0 | result->nInfcount = pq_getmsgint64(&buf); |
5287 | |
|
5288 | 0 | pq_getmsgend(&buf); |
5289 | |
|
5290 | 0 | free_var(&tmp_var); |
5291 | |
|
5292 | 0 | PG_RETURN_POINTER(result); |
5293 | 0 | } |
5294 | | |
5295 | | /* |
5296 | | * numeric_serialize |
5297 | | * Serialization function for NumericAggState for numeric aggregates that |
5298 | | * require sumX2. |
5299 | | */ |
5300 | | Datum |
5301 | | numeric_serialize(PG_FUNCTION_ARGS) |
5302 | 0 | { |
5303 | 0 | NumericAggState *state; |
5304 | 0 | StringInfoData buf; |
5305 | 0 | bytea *result; |
5306 | 0 | NumericVar tmp_var; |
5307 | | |
5308 | | /* Ensure we disallow calling when not in aggregate context */ |
5309 | 0 | if (!AggCheckCallContext(fcinfo, NULL)) |
5310 | 0 | elog(ERROR, "aggregate function called in non-aggregate context"); |
5311 | | |
5312 | 0 | state = (NumericAggState *) PG_GETARG_POINTER(0); |
5313 | |
|
5314 | 0 | init_var(&tmp_var); |
5315 | |
|
5316 | 0 | pq_begintypsend(&buf); |
5317 | | |
5318 | | /* N */ |
5319 | 0 | pq_sendint64(&buf, state->N); |
5320 | | |
5321 | | /* sumX */ |
5322 | 0 | accum_sum_final(&state->sumX, &tmp_var); |
5323 | 0 | numericvar_serialize(&buf, &tmp_var); |
5324 | | |
5325 | | /* sumX2 */ |
5326 | 0 | accum_sum_final(&state->sumX2, &tmp_var); |
5327 | 0 | numericvar_serialize(&buf, &tmp_var); |
5328 | | |
5329 | | /* maxScale */ |
5330 | 0 | pq_sendint32(&buf, state->maxScale); |
5331 | | |
5332 | | /* maxScaleCount */ |
5333 | 0 | pq_sendint64(&buf, state->maxScaleCount); |
5334 | | |
5335 | | /* NaNcount */ |
5336 | 0 | pq_sendint64(&buf, state->NaNcount); |
5337 | | |
5338 | | /* pInfcount */ |
5339 | 0 | pq_sendint64(&buf, state->pInfcount); |
5340 | | |
5341 | | /* nInfcount */ |
5342 | 0 | pq_sendint64(&buf, state->nInfcount); |
5343 | |
|
5344 | 0 | result = pq_endtypsend(&buf); |
5345 | |
|
5346 | 0 | free_var(&tmp_var); |
5347 | |
|
5348 | 0 | PG_RETURN_BYTEA_P(result); |
5349 | 0 | } |
5350 | | |
5351 | | /* |
5352 | | * numeric_deserialize |
5353 | | * Deserialization function for NumericAggState for numeric aggregates that |
5354 | | * require sumX2. |
5355 | | */ |
5356 | | Datum |
5357 | | numeric_deserialize(PG_FUNCTION_ARGS) |
5358 | 0 | { |
5359 | 0 | bytea *sstate; |
5360 | 0 | NumericAggState *result; |
5361 | 0 | StringInfoData buf; |
5362 | 0 | NumericVar tmp_var; |
5363 | |
|
5364 | 0 | if (!AggCheckCallContext(fcinfo, NULL)) |
5365 | 0 | elog(ERROR, "aggregate function called in non-aggregate context"); |
5366 | | |
5367 | 0 | sstate = PG_GETARG_BYTEA_PP(0); |
5368 | |
|
5369 | 0 | init_var(&tmp_var); |
5370 | | |
5371 | | /* |
5372 | | * Initialize a StringInfo so that we can "receive" it using the standard |
5373 | | * recv-function infrastructure. |
5374 | | */ |
5375 | 0 | initReadOnlyStringInfo(&buf, VARDATA_ANY(sstate), |
5376 | 0 | VARSIZE_ANY_EXHDR(sstate)); |
5377 | |
|
5378 | 0 | result = makeNumericAggStateCurrentContext(true); |
5379 | | |
5380 | | /* N */ |
5381 | 0 | result->N = pq_getmsgint64(&buf); |
5382 | | |
5383 | | /* sumX */ |
5384 | 0 | numericvar_deserialize(&buf, &tmp_var); |
5385 | 0 | accum_sum_add(&(result->sumX), &tmp_var); |
5386 | | |
5387 | | /* sumX2 */ |
5388 | 0 | numericvar_deserialize(&buf, &tmp_var); |
5389 | 0 | accum_sum_add(&(result->sumX2), &tmp_var); |
5390 | | |
5391 | | /* maxScale */ |
5392 | 0 | result->maxScale = pq_getmsgint(&buf, 4); |
5393 | | |
5394 | | /* maxScaleCount */ |
5395 | 0 | result->maxScaleCount = pq_getmsgint64(&buf); |
5396 | | |
5397 | | /* NaNcount */ |
5398 | 0 | result->NaNcount = pq_getmsgint64(&buf); |
5399 | | |
5400 | | /* pInfcount */ |
5401 | 0 | result->pInfcount = pq_getmsgint64(&buf); |
5402 | | |
5403 | | /* nInfcount */ |
5404 | 0 | result->nInfcount = pq_getmsgint64(&buf); |
5405 | |
|
5406 | 0 | pq_getmsgend(&buf); |
5407 | |
|
5408 | 0 | free_var(&tmp_var); |
5409 | |
|
5410 | 0 | PG_RETURN_POINTER(result); |
5411 | 0 | } |
5412 | | |
5413 | | /* |
5414 | | * Generic inverse transition function for numeric aggregates |
5415 | | * (with or without requirement for X^2). |
5416 | | */ |
5417 | | Datum |
5418 | | numeric_accum_inv(PG_FUNCTION_ARGS) |
5419 | 0 | { |
5420 | 0 | NumericAggState *state; |
5421 | |
|
5422 | 0 | state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0); |
5423 | | |
5424 | | /* Should not get here with no state */ |
5425 | 0 | if (state == NULL) |
5426 | 0 | elog(ERROR, "numeric_accum_inv called with NULL state"); |
5427 | | |
5428 | 0 | if (!PG_ARGISNULL(1)) |
5429 | 0 | { |
5430 | | /* If we fail to perform the inverse transition, return NULL */ |
5431 | 0 | if (!do_numeric_discard(state, PG_GETARG_NUMERIC(1))) |
5432 | 0 | PG_RETURN_NULL(); |
5433 | 0 | } |
5434 | | |
5435 | 0 | PG_RETURN_POINTER(state); |
5436 | 0 | } |
5437 | | |
5438 | | |
5439 | | /* |
5440 | | * Integer data types in general use Numeric accumulators to share code and |
5441 | | * avoid risk of overflow. However for performance reasons optimized |
5442 | | * special-purpose accumulator routines are used when possible: |
5443 | | * |
5444 | | * For 16-bit and 32-bit inputs, N and sum(X) fit into 64-bit, so 64-bit |
5445 | | * accumulators are used for SUM and AVG of these data types. |
5446 | | * |
5447 | | * For 16-bit and 32-bit inputs, sum(X^2) fits into 128-bit, so 128-bit |
5448 | | * accumulators are used for STDDEV_POP, STDDEV_SAMP, VAR_POP, and VAR_SAMP of |
5449 | | * these data types. |
5450 | | * |
5451 | | * For 64-bit inputs, sum(X) fits into 128-bit, so a 128-bit accumulator is |
5452 | | * used for SUM(int8) and AVG(int8). |
5453 | | */ |
5454 | | |
5455 | | typedef struct Int128AggState |
5456 | | { |
5457 | | bool calcSumX2; /* if true, calculate sumX2 */ |
5458 | | int64 N; /* count of processed numbers */ |
5459 | | INT128 sumX; /* sum of processed numbers */ |
5460 | | INT128 sumX2; /* sum of squares of processed numbers */ |
5461 | | } Int128AggState; |
5462 | | |
5463 | | /* |
5464 | | * Prepare state data for a 128-bit aggregate function that needs to compute |
5465 | | * sum, count and optionally sum of squares of the input. |
5466 | | */ |
5467 | | static Int128AggState * |
5468 | | makeInt128AggState(FunctionCallInfo fcinfo, bool calcSumX2) |
5469 | 0 | { |
5470 | 0 | Int128AggState *state; |
5471 | 0 | MemoryContext agg_context; |
5472 | 0 | MemoryContext old_context; |
5473 | |
|
5474 | 0 | if (!AggCheckCallContext(fcinfo, &agg_context)) |
5475 | 0 | elog(ERROR, "aggregate function called in non-aggregate context"); |
5476 | | |
5477 | 0 | old_context = MemoryContextSwitchTo(agg_context); |
5478 | |
|
5479 | 0 | state = palloc0_object(Int128AggState); |
5480 | 0 | state->calcSumX2 = calcSumX2; |
5481 | |
|
5482 | 0 | MemoryContextSwitchTo(old_context); |
5483 | |
|
5484 | 0 | return state; |
5485 | 0 | } |
5486 | | |
5487 | | /* |
5488 | | * Like makeInt128AggState(), but allocate the state in the current memory |
5489 | | * context. |
5490 | | */ |
5491 | | static Int128AggState * |
5492 | | makeInt128AggStateCurrentContext(bool calcSumX2) |
5493 | 0 | { |
5494 | 0 | Int128AggState *state; |
5495 | |
|
5496 | 0 | state = palloc0_object(Int128AggState); |
5497 | 0 | state->calcSumX2 = calcSumX2; |
5498 | |
|
5499 | 0 | return state; |
5500 | 0 | } |
5501 | | |
5502 | | /* |
5503 | | * Accumulate a new input value for 128-bit aggregate functions. |
5504 | | */ |
5505 | | static void |
5506 | | do_int128_accum(Int128AggState *state, int64 newval) |
5507 | 0 | { |
5508 | 0 | if (state->calcSumX2) |
5509 | 0 | int128_add_int64_mul_int64(&state->sumX2, newval, newval); |
5510 | |
|
5511 | 0 | int128_add_int64(&state->sumX, newval); |
5512 | 0 | state->N++; |
5513 | 0 | } |
5514 | | |
5515 | | /* |
5516 | | * Remove an input value from the aggregated state. |
5517 | | */ |
5518 | | static void |
5519 | | do_int128_discard(Int128AggState *state, int64 newval) |
5520 | 0 | { |
5521 | 0 | if (state->calcSumX2) |
5522 | 0 | int128_sub_int64_mul_int64(&state->sumX2, newval, newval); |
5523 | |
|
5524 | 0 | int128_sub_int64(&state->sumX, newval); |
5525 | 0 | state->N--; |
5526 | 0 | } |
5527 | | |
5528 | | Datum |
5529 | | int2_accum(PG_FUNCTION_ARGS) |
5530 | 0 | { |
5531 | 0 | Int128AggState *state; |
5532 | |
|
5533 | 0 | state = PG_ARGISNULL(0) ? NULL : (Int128AggState *) PG_GETARG_POINTER(0); |
5534 | | |
5535 | | /* Create the state data on the first call */ |
5536 | 0 | if (state == NULL) |
5537 | 0 | state = makeInt128AggState(fcinfo, true); |
5538 | |
|
5539 | 0 | if (!PG_ARGISNULL(1)) |
5540 | 0 | do_int128_accum(state, PG_GETARG_INT16(1)); |
5541 | |
|
5542 | 0 | PG_RETURN_POINTER(state); |
5543 | 0 | } |
5544 | | |
5545 | | Datum |
5546 | | int4_accum(PG_FUNCTION_ARGS) |
5547 | 0 | { |
5548 | 0 | Int128AggState *state; |
5549 | |
|
5550 | 0 | state = PG_ARGISNULL(0) ? NULL : (Int128AggState *) PG_GETARG_POINTER(0); |
5551 | | |
5552 | | /* Create the state data on the first call */ |
5553 | 0 | if (state == NULL) |
5554 | 0 | state = makeInt128AggState(fcinfo, true); |
5555 | |
|
5556 | 0 | if (!PG_ARGISNULL(1)) |
5557 | 0 | do_int128_accum(state, PG_GETARG_INT32(1)); |
5558 | |
|
5559 | 0 | PG_RETURN_POINTER(state); |
5560 | 0 | } |
5561 | | |
5562 | | Datum |
5563 | | int8_accum(PG_FUNCTION_ARGS) |
5564 | 0 | { |
5565 | 0 | NumericAggState *state; |
5566 | |
|
5567 | 0 | state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0); |
5568 | | |
5569 | | /* Create the state data on the first call */ |
5570 | 0 | if (state == NULL) |
5571 | 0 | state = makeNumericAggState(fcinfo, true); |
5572 | |
|
5573 | 0 | if (!PG_ARGISNULL(1)) |
5574 | 0 | do_numeric_accum(state, int64_to_numeric(PG_GETARG_INT64(1))); |
5575 | |
|
5576 | 0 | PG_RETURN_POINTER(state); |
5577 | 0 | } |
5578 | | |
5579 | | /* |
5580 | | * Combine function for Int128AggState for aggregates which require sumX2 |
5581 | | */ |
5582 | | Datum |
5583 | | numeric_poly_combine(PG_FUNCTION_ARGS) |
5584 | 0 | { |
5585 | 0 | Int128AggState *state1; |
5586 | 0 | Int128AggState *state2; |
5587 | 0 | MemoryContext agg_context; |
5588 | 0 | MemoryContext old_context; |
5589 | |
|
5590 | 0 | if (!AggCheckCallContext(fcinfo, &agg_context)) |
5591 | 0 | elog(ERROR, "aggregate function called in non-aggregate context"); |
5592 | | |
5593 | 0 | state1 = PG_ARGISNULL(0) ? NULL : (Int128AggState *) PG_GETARG_POINTER(0); |
5594 | 0 | state2 = PG_ARGISNULL(1) ? NULL : (Int128AggState *) PG_GETARG_POINTER(1); |
5595 | |
|
5596 | 0 | if (state2 == NULL) |
5597 | 0 | { |
5598 | | /* |
5599 | | * NULL state2 is easy, just return state1, which we know is already |
5600 | | * in the agg_context |
5601 | | */ |
5602 | 0 | if (state1 == NULL) |
5603 | 0 | PG_RETURN_NULL(); |
5604 | 0 | PG_RETURN_POINTER(state1); |
5605 | 0 | } |
5606 | | |
5607 | | /* manually copy all fields from state2 to state1 */ |
5608 | 0 | if (state1 == NULL) |
5609 | 0 | { |
5610 | 0 | old_context = MemoryContextSwitchTo(agg_context); |
5611 | |
|
5612 | 0 | state1 = makeInt128AggState(fcinfo, true); |
5613 | 0 | state1->N = state2->N; |
5614 | 0 | state1->sumX = state2->sumX; |
5615 | 0 | state1->sumX2 = state2->sumX2; |
5616 | |
|
5617 | 0 | MemoryContextSwitchTo(old_context); |
5618 | |
|
5619 | 0 | PG_RETURN_POINTER(state1); |
5620 | 0 | } |
5621 | | |
5622 | 0 | if (state2->N > 0) |
5623 | 0 | { |
5624 | 0 | state1->N += state2->N; |
5625 | 0 | int128_add_int128(&state1->sumX, state2->sumX); |
5626 | 0 | int128_add_int128(&state1->sumX2, state2->sumX2); |
5627 | 0 | } |
5628 | 0 | PG_RETURN_POINTER(state1); |
5629 | 0 | } |
5630 | | |
5631 | | /* |
5632 | | * int128_serialize - serialize a 128-bit integer to binary format |
5633 | | */ |
5634 | | static inline void |
5635 | | int128_serialize(StringInfo buf, INT128 val) |
5636 | 0 | { |
5637 | 0 | pq_sendint64(buf, PG_INT128_HI_INT64(val)); |
5638 | 0 | pq_sendint64(buf, PG_INT128_LO_UINT64(val)); |
5639 | 0 | } |
5640 | | |
5641 | | /* |
5642 | | * int128_deserialize - deserialize binary format to a 128-bit integer. |
5643 | | */ |
5644 | | static inline INT128 |
5645 | | int128_deserialize(StringInfo buf) |
5646 | 0 | { |
5647 | 0 | int64 hi = pq_getmsgint64(buf); |
5648 | 0 | uint64 lo = pq_getmsgint64(buf); |
5649 | |
|
5650 | 0 | return make_int128(hi, lo); |
5651 | 0 | } |
5652 | | |
5653 | | /* |
5654 | | * numeric_poly_serialize |
5655 | | * Serialize Int128AggState into bytea for aggregate functions which |
5656 | | * require sumX2. |
5657 | | */ |
5658 | | Datum |
5659 | | numeric_poly_serialize(PG_FUNCTION_ARGS) |
5660 | 0 | { |
5661 | 0 | Int128AggState *state; |
5662 | 0 | StringInfoData buf; |
5663 | 0 | bytea *result; |
5664 | | |
5665 | | /* Ensure we disallow calling when not in aggregate context */ |
5666 | 0 | if (!AggCheckCallContext(fcinfo, NULL)) |
5667 | 0 | elog(ERROR, "aggregate function called in non-aggregate context"); |
5668 | | |
5669 | 0 | state = (Int128AggState *) PG_GETARG_POINTER(0); |
5670 | |
|
5671 | 0 | pq_begintypsend(&buf); |
5672 | | |
5673 | | /* N */ |
5674 | 0 | pq_sendint64(&buf, state->N); |
5675 | | |
5676 | | /* sumX */ |
5677 | 0 | int128_serialize(&buf, state->sumX); |
5678 | | |
5679 | | /* sumX2 */ |
5680 | 0 | int128_serialize(&buf, state->sumX2); |
5681 | |
|
5682 | 0 | result = pq_endtypsend(&buf); |
5683 | |
|
5684 | 0 | PG_RETURN_BYTEA_P(result); |
5685 | 0 | } |
5686 | | |
5687 | | /* |
5688 | | * numeric_poly_deserialize |
5689 | | * Deserialize Int128AggState from bytea for aggregate functions which |
5690 | | * require sumX2. |
5691 | | */ |
5692 | | Datum |
5693 | | numeric_poly_deserialize(PG_FUNCTION_ARGS) |
5694 | 0 | { |
5695 | 0 | bytea *sstate; |
5696 | 0 | Int128AggState *result; |
5697 | 0 | StringInfoData buf; |
5698 | |
|
5699 | 0 | if (!AggCheckCallContext(fcinfo, NULL)) |
5700 | 0 | elog(ERROR, "aggregate function called in non-aggregate context"); |
5701 | | |
5702 | 0 | sstate = PG_GETARG_BYTEA_PP(0); |
5703 | | |
5704 | | /* |
5705 | | * Initialize a StringInfo so that we can "receive" it using the standard |
5706 | | * recv-function infrastructure. |
5707 | | */ |
5708 | 0 | initReadOnlyStringInfo(&buf, VARDATA_ANY(sstate), |
5709 | 0 | VARSIZE_ANY_EXHDR(sstate)); |
5710 | |
|
5711 | 0 | result = makeInt128AggStateCurrentContext(true); |
5712 | | |
5713 | | /* N */ |
5714 | 0 | result->N = pq_getmsgint64(&buf); |
5715 | | |
5716 | | /* sumX */ |
5717 | 0 | result->sumX = int128_deserialize(&buf); |
5718 | | |
5719 | | /* sumX2 */ |
5720 | 0 | result->sumX2 = int128_deserialize(&buf); |
5721 | |
|
5722 | 0 | pq_getmsgend(&buf); |
5723 | |
|
5724 | 0 | PG_RETURN_POINTER(result); |
5725 | 0 | } |
5726 | | |
5727 | | /* |
5728 | | * Transition function for int8 input when we don't need sumX2. |
5729 | | */ |
5730 | | Datum |
5731 | | int8_avg_accum(PG_FUNCTION_ARGS) |
5732 | 0 | { |
5733 | 0 | Int128AggState *state; |
5734 | |
|
5735 | 0 | state = PG_ARGISNULL(0) ? NULL : (Int128AggState *) PG_GETARG_POINTER(0); |
5736 | | |
5737 | | /* Create the state data on the first call */ |
5738 | 0 | if (state == NULL) |
5739 | 0 | state = makeInt128AggState(fcinfo, false); |
5740 | |
|
5741 | 0 | if (!PG_ARGISNULL(1)) |
5742 | 0 | do_int128_accum(state, PG_GETARG_INT64(1)); |
5743 | |
|
5744 | 0 | PG_RETURN_POINTER(state); |
5745 | 0 | } |
5746 | | |
5747 | | /* |
5748 | | * Combine function for Int128AggState for aggregates which don't require |
5749 | | * sumX2 |
5750 | | */ |
5751 | | Datum |
5752 | | int8_avg_combine(PG_FUNCTION_ARGS) |
5753 | 0 | { |
5754 | 0 | Int128AggState *state1; |
5755 | 0 | Int128AggState *state2; |
5756 | 0 | MemoryContext agg_context; |
5757 | 0 | MemoryContext old_context; |
5758 | |
|
5759 | 0 | if (!AggCheckCallContext(fcinfo, &agg_context)) |
5760 | 0 | elog(ERROR, "aggregate function called in non-aggregate context"); |
5761 | | |
5762 | 0 | state1 = PG_ARGISNULL(0) ? NULL : (Int128AggState *) PG_GETARG_POINTER(0); |
5763 | 0 | state2 = PG_ARGISNULL(1) ? NULL : (Int128AggState *) PG_GETARG_POINTER(1); |
5764 | |
|
5765 | 0 | if (state2 == NULL) |
5766 | 0 | { |
5767 | | /* |
5768 | | * NULL state2 is easy, just return state1, which we know is already |
5769 | | * in the agg_context |
5770 | | */ |
5771 | 0 | if (state1 == NULL) |
5772 | 0 | PG_RETURN_NULL(); |
5773 | 0 | PG_RETURN_POINTER(state1); |
5774 | 0 | } |
5775 | | |
5776 | | /* manually copy all fields from state2 to state1 */ |
5777 | 0 | if (state1 == NULL) |
5778 | 0 | { |
5779 | 0 | old_context = MemoryContextSwitchTo(agg_context); |
5780 | |
|
5781 | 0 | state1 = makeInt128AggState(fcinfo, false); |
5782 | 0 | state1->N = state2->N; |
5783 | 0 | state1->sumX = state2->sumX; |
5784 | |
|
5785 | 0 | MemoryContextSwitchTo(old_context); |
5786 | |
|
5787 | 0 | PG_RETURN_POINTER(state1); |
5788 | 0 | } |
5789 | | |
5790 | 0 | if (state2->N > 0) |
5791 | 0 | { |
5792 | 0 | state1->N += state2->N; |
5793 | 0 | int128_add_int128(&state1->sumX, state2->sumX); |
5794 | 0 | } |
5795 | 0 | PG_RETURN_POINTER(state1); |
5796 | 0 | } |
5797 | | |
5798 | | /* |
5799 | | * int8_avg_serialize |
5800 | | * Serialize Int128AggState into bytea for aggregate functions which |
5801 | | * don't require sumX2. |
5802 | | */ |
5803 | | Datum |
5804 | | int8_avg_serialize(PG_FUNCTION_ARGS) |
5805 | 0 | { |
5806 | 0 | Int128AggState *state; |
5807 | 0 | StringInfoData buf; |
5808 | 0 | bytea *result; |
5809 | | |
5810 | | /* Ensure we disallow calling when not in aggregate context */ |
5811 | 0 | if (!AggCheckCallContext(fcinfo, NULL)) |
5812 | 0 | elog(ERROR, "aggregate function called in non-aggregate context"); |
5813 | | |
5814 | 0 | state = (Int128AggState *) PG_GETARG_POINTER(0); |
5815 | |
|
5816 | 0 | pq_begintypsend(&buf); |
5817 | | |
5818 | | /* N */ |
5819 | 0 | pq_sendint64(&buf, state->N); |
5820 | | |
5821 | | /* sumX */ |
5822 | 0 | int128_serialize(&buf, state->sumX); |
5823 | |
|
5824 | 0 | result = pq_endtypsend(&buf); |
5825 | |
|
5826 | 0 | PG_RETURN_BYTEA_P(result); |
5827 | 0 | } |
5828 | | |
5829 | | /* |
5830 | | * int8_avg_deserialize |
5831 | | * Deserialize Int128AggState from bytea for aggregate functions which |
5832 | | * don't require sumX2. |
5833 | | */ |
5834 | | Datum |
5835 | | int8_avg_deserialize(PG_FUNCTION_ARGS) |
5836 | 0 | { |
5837 | 0 | bytea *sstate; |
5838 | 0 | Int128AggState *result; |
5839 | 0 | StringInfoData buf; |
5840 | |
|
5841 | 0 | if (!AggCheckCallContext(fcinfo, NULL)) |
5842 | 0 | elog(ERROR, "aggregate function called in non-aggregate context"); |
5843 | | |
5844 | 0 | sstate = PG_GETARG_BYTEA_PP(0); |
5845 | | |
5846 | | /* |
5847 | | * Initialize a StringInfo so that we can "receive" it using the standard |
5848 | | * recv-function infrastructure. |
5849 | | */ |
5850 | 0 | initReadOnlyStringInfo(&buf, VARDATA_ANY(sstate), |
5851 | 0 | VARSIZE_ANY_EXHDR(sstate)); |
5852 | |
|
5853 | 0 | result = makeInt128AggStateCurrentContext(false); |
5854 | | |
5855 | | /* N */ |
5856 | 0 | result->N = pq_getmsgint64(&buf); |
5857 | | |
5858 | | /* sumX */ |
5859 | 0 | result->sumX = int128_deserialize(&buf); |
5860 | |
|
5861 | 0 | pq_getmsgend(&buf); |
5862 | |
|
5863 | 0 | PG_RETURN_POINTER(result); |
5864 | 0 | } |
5865 | | |
5866 | | /* |
5867 | | * Inverse transition functions to go with the above. |
5868 | | */ |
5869 | | |
5870 | | Datum |
5871 | | int2_accum_inv(PG_FUNCTION_ARGS) |
5872 | 0 | { |
5873 | 0 | Int128AggState *state; |
5874 | |
|
5875 | 0 | state = PG_ARGISNULL(0) ? NULL : (Int128AggState *) PG_GETARG_POINTER(0); |
5876 | | |
5877 | | /* Should not get here with no state */ |
5878 | 0 | if (state == NULL) |
5879 | 0 | elog(ERROR, "int2_accum_inv called with NULL state"); |
5880 | | |
5881 | 0 | if (!PG_ARGISNULL(1)) |
5882 | 0 | do_int128_discard(state, PG_GETARG_INT16(1)); |
5883 | |
|
5884 | 0 | PG_RETURN_POINTER(state); |
5885 | 0 | } |
5886 | | |
5887 | | Datum |
5888 | | int4_accum_inv(PG_FUNCTION_ARGS) |
5889 | 0 | { |
5890 | 0 | Int128AggState *state; |
5891 | |
|
5892 | 0 | state = PG_ARGISNULL(0) ? NULL : (Int128AggState *) PG_GETARG_POINTER(0); |
5893 | | |
5894 | | /* Should not get here with no state */ |
5895 | 0 | if (state == NULL) |
5896 | 0 | elog(ERROR, "int4_accum_inv called with NULL state"); |
5897 | | |
5898 | 0 | if (!PG_ARGISNULL(1)) |
5899 | 0 | do_int128_discard(state, PG_GETARG_INT32(1)); |
5900 | |
|
5901 | 0 | PG_RETURN_POINTER(state); |
5902 | 0 | } |
5903 | | |
5904 | | Datum |
5905 | | int8_accum_inv(PG_FUNCTION_ARGS) |
5906 | 0 | { |
5907 | 0 | NumericAggState *state; |
5908 | |
|
5909 | 0 | state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0); |
5910 | | |
5911 | | /* Should not get here with no state */ |
5912 | 0 | if (state == NULL) |
5913 | 0 | elog(ERROR, "int8_accum_inv called with NULL state"); |
5914 | | |
5915 | 0 | if (!PG_ARGISNULL(1)) |
5916 | 0 | { |
5917 | | /* Should never fail, all inputs have dscale 0 */ |
5918 | 0 | if (!do_numeric_discard(state, int64_to_numeric(PG_GETARG_INT64(1)))) |
5919 | 0 | elog(ERROR, "do_numeric_discard failed unexpectedly"); |
5920 | 0 | } |
5921 | | |
5922 | 0 | PG_RETURN_POINTER(state); |
5923 | 0 | } |
5924 | | |
5925 | | Datum |
5926 | | int8_avg_accum_inv(PG_FUNCTION_ARGS) |
5927 | 0 | { |
5928 | 0 | Int128AggState *state; |
5929 | |
|
5930 | 0 | state = PG_ARGISNULL(0) ? NULL : (Int128AggState *) PG_GETARG_POINTER(0); |
5931 | | |
5932 | | /* Should not get here with no state */ |
5933 | 0 | if (state == NULL) |
5934 | 0 | elog(ERROR, "int8_avg_accum_inv called with NULL state"); |
5935 | | |
5936 | 0 | if (!PG_ARGISNULL(1)) |
5937 | 0 | do_int128_discard(state, PG_GETARG_INT64(1)); |
5938 | |
|
5939 | 0 | PG_RETURN_POINTER(state); |
5940 | 0 | } |
5941 | | |
5942 | | Datum |
5943 | | numeric_poly_sum(PG_FUNCTION_ARGS) |
5944 | 0 | { |
5945 | 0 | Int128AggState *state; |
5946 | 0 | Numeric res; |
5947 | 0 | NumericVar result; |
5948 | |
|
5949 | 0 | state = PG_ARGISNULL(0) ? NULL : (Int128AggState *) PG_GETARG_POINTER(0); |
5950 | | |
5951 | | /* If there were no non-null inputs, return NULL */ |
5952 | 0 | if (state == NULL || state->N == 0) |
5953 | 0 | PG_RETURN_NULL(); |
5954 | | |
5955 | 0 | init_var(&result); |
5956 | |
|
5957 | 0 | int128_to_numericvar(state->sumX, &result); |
5958 | |
|
5959 | 0 | res = make_result(&result); |
5960 | |
|
5961 | 0 | free_var(&result); |
5962 | |
|
5963 | 0 | PG_RETURN_NUMERIC(res); |
5964 | 0 | } |
5965 | | |
5966 | | Datum |
5967 | | numeric_poly_avg(PG_FUNCTION_ARGS) |
5968 | 0 | { |
5969 | 0 | Int128AggState *state; |
5970 | 0 | NumericVar result; |
5971 | 0 | Datum countd, |
5972 | 0 | sumd; |
5973 | |
|
5974 | 0 | state = PG_ARGISNULL(0) ? NULL : (Int128AggState *) PG_GETARG_POINTER(0); |
5975 | | |
5976 | | /* If there were no non-null inputs, return NULL */ |
5977 | 0 | if (state == NULL || state->N == 0) |
5978 | 0 | PG_RETURN_NULL(); |
5979 | | |
5980 | 0 | init_var(&result); |
5981 | |
|
5982 | 0 | int128_to_numericvar(state->sumX, &result); |
5983 | |
|
5984 | 0 | countd = NumericGetDatum(int64_to_numeric(state->N)); |
5985 | 0 | sumd = NumericGetDatum(make_result(&result)); |
5986 | |
|
5987 | 0 | free_var(&result); |
5988 | |
|
5989 | 0 | PG_RETURN_DATUM(DirectFunctionCall2(numeric_div, sumd, countd)); |
5990 | 0 | } |
5991 | | |
5992 | | Datum |
5993 | | numeric_avg(PG_FUNCTION_ARGS) |
5994 | 0 | { |
5995 | 0 | NumericAggState *state; |
5996 | 0 | Datum N_datum; |
5997 | 0 | Datum sumX_datum; |
5998 | 0 | NumericVar sumX_var; |
5999 | |
|
6000 | 0 | state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0); |
6001 | | |
6002 | | /* If there were no non-null inputs, return NULL */ |
6003 | 0 | if (state == NULL || NA_TOTAL_COUNT(state) == 0) |
6004 | 0 | PG_RETURN_NULL(); |
6005 | | |
6006 | 0 | if (state->NaNcount > 0) /* there was at least one NaN input */ |
6007 | 0 | PG_RETURN_NUMERIC(make_result(&const_nan)); |
6008 | | |
6009 | | /* adding plus and minus infinities gives NaN */ |
6010 | 0 | if (state->pInfcount > 0 && state->nInfcount > 0) |
6011 | 0 | PG_RETURN_NUMERIC(make_result(&const_nan)); |
6012 | 0 | if (state->pInfcount > 0) |
6013 | 0 | PG_RETURN_NUMERIC(make_result(&const_pinf)); |
6014 | 0 | if (state->nInfcount > 0) |
6015 | 0 | PG_RETURN_NUMERIC(make_result(&const_ninf)); |
6016 | | |
6017 | 0 | N_datum = NumericGetDatum(int64_to_numeric(state->N)); |
6018 | |
|
6019 | 0 | init_var(&sumX_var); |
6020 | 0 | accum_sum_final(&state->sumX, &sumX_var); |
6021 | 0 | sumX_datum = NumericGetDatum(make_result(&sumX_var)); |
6022 | 0 | free_var(&sumX_var); |
6023 | |
|
6024 | 0 | PG_RETURN_DATUM(DirectFunctionCall2(numeric_div, sumX_datum, N_datum)); |
6025 | 0 | } |
6026 | | |
6027 | | Datum |
6028 | | numeric_sum(PG_FUNCTION_ARGS) |
6029 | 0 | { |
6030 | 0 | NumericAggState *state; |
6031 | 0 | NumericVar sumX_var; |
6032 | 0 | Numeric result; |
6033 | |
|
6034 | 0 | state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0); |
6035 | | |
6036 | | /* If there were no non-null inputs, return NULL */ |
6037 | 0 | if (state == NULL || NA_TOTAL_COUNT(state) == 0) |
6038 | 0 | PG_RETURN_NULL(); |
6039 | | |
6040 | 0 | if (state->NaNcount > 0) /* there was at least one NaN input */ |
6041 | 0 | PG_RETURN_NUMERIC(make_result(&const_nan)); |
6042 | | |
6043 | | /* adding plus and minus infinities gives NaN */ |
6044 | 0 | if (state->pInfcount > 0 && state->nInfcount > 0) |
6045 | 0 | PG_RETURN_NUMERIC(make_result(&const_nan)); |
6046 | 0 | if (state->pInfcount > 0) |
6047 | 0 | PG_RETURN_NUMERIC(make_result(&const_pinf)); |
6048 | 0 | if (state->nInfcount > 0) |
6049 | 0 | PG_RETURN_NUMERIC(make_result(&const_ninf)); |
6050 | | |
6051 | 0 | init_var(&sumX_var); |
6052 | 0 | accum_sum_final(&state->sumX, &sumX_var); |
6053 | 0 | result = make_result(&sumX_var); |
6054 | 0 | free_var(&sumX_var); |
6055 | |
|
6056 | 0 | PG_RETURN_NUMERIC(result); |
6057 | 0 | } |
6058 | | |
6059 | | /* |
6060 | | * Workhorse routine for the standard deviance and variance |
6061 | | * aggregates. 'state' is aggregate's transition state. |
6062 | | * 'variance' specifies whether we should calculate the |
6063 | | * variance or the standard deviation. 'sample' indicates whether the |
6064 | | * caller is interested in the sample or the population |
6065 | | * variance/stddev. |
6066 | | * |
6067 | | * If appropriate variance statistic is undefined for the input, |
6068 | | * *is_null is set to true and NULL is returned. |
6069 | | */ |
6070 | | static Numeric |
6071 | | numeric_stddev_internal(NumericAggState *state, |
6072 | | bool variance, bool sample, |
6073 | | bool *is_null) |
6074 | 0 | { |
6075 | 0 | Numeric res; |
6076 | 0 | NumericVar vN, |
6077 | 0 | vsumX, |
6078 | 0 | vsumX2, |
6079 | 0 | vNminus1; |
6080 | 0 | int64 totCount; |
6081 | 0 | int rscale; |
6082 | | |
6083 | | /* |
6084 | | * Sample stddev and variance are undefined when N <= 1; population stddev |
6085 | | * is undefined when N == 0. Return NULL in either case (note that NaNs |
6086 | | * and infinities count as normal inputs for this purpose). |
6087 | | */ |
6088 | 0 | if (state == NULL || (totCount = NA_TOTAL_COUNT(state)) == 0) |
6089 | 0 | { |
6090 | 0 | *is_null = true; |
6091 | 0 | return NULL; |
6092 | 0 | } |
6093 | | |
6094 | 0 | if (sample && totCount <= 1) |
6095 | 0 | { |
6096 | 0 | *is_null = true; |
6097 | 0 | return NULL; |
6098 | 0 | } |
6099 | | |
6100 | 0 | *is_null = false; |
6101 | | |
6102 | | /* |
6103 | | * Deal with NaN and infinity cases. By analogy to the behavior of the |
6104 | | * float8 functions, any infinity input produces NaN output. |
6105 | | */ |
6106 | 0 | if (state->NaNcount > 0 || state->pInfcount > 0 || state->nInfcount > 0) |
6107 | 0 | return make_result(&const_nan); |
6108 | | |
6109 | | /* OK, normal calculation applies */ |
6110 | 0 | init_var(&vN); |
6111 | 0 | init_var(&vsumX); |
6112 | 0 | init_var(&vsumX2); |
6113 | |
|
6114 | 0 | int64_to_numericvar(state->N, &vN); |
6115 | 0 | accum_sum_final(&(state->sumX), &vsumX); |
6116 | 0 | accum_sum_final(&(state->sumX2), &vsumX2); |
6117 | |
|
6118 | 0 | init_var(&vNminus1); |
6119 | 0 | sub_var(&vN, &const_one, &vNminus1); |
6120 | | |
6121 | | /* compute rscale for mul_var calls */ |
6122 | 0 | rscale = vsumX.dscale * 2; |
6123 | |
|
6124 | 0 | mul_var(&vsumX, &vsumX, &vsumX, rscale); /* vsumX = sumX * sumX */ |
6125 | 0 | mul_var(&vN, &vsumX2, &vsumX2, rscale); /* vsumX2 = N * sumX2 */ |
6126 | 0 | sub_var(&vsumX2, &vsumX, &vsumX2); /* N * sumX2 - sumX * sumX */ |
6127 | |
|
6128 | 0 | if (cmp_var(&vsumX2, &const_zero) <= 0) |
6129 | 0 | { |
6130 | | /* Watch out for roundoff error producing a negative numerator */ |
6131 | 0 | res = make_result(&const_zero); |
6132 | 0 | } |
6133 | 0 | else |
6134 | 0 | { |
6135 | 0 | if (sample) |
6136 | 0 | mul_var(&vN, &vNminus1, &vNminus1, 0); /* N * (N - 1) */ |
6137 | 0 | else |
6138 | 0 | mul_var(&vN, &vN, &vNminus1, 0); /* N * N */ |
6139 | 0 | rscale = select_div_scale(&vsumX2, &vNminus1); |
6140 | 0 | div_var(&vsumX2, &vNminus1, &vsumX, rscale, true, true); /* variance */ |
6141 | 0 | if (!variance) |
6142 | 0 | sqrt_var(&vsumX, &vsumX, rscale); /* stddev */ |
6143 | |
|
6144 | 0 | res = make_result(&vsumX); |
6145 | 0 | } |
6146 | |
|
6147 | 0 | free_var(&vNminus1); |
6148 | 0 | free_var(&vsumX); |
6149 | 0 | free_var(&vsumX2); |
6150 | |
|
6151 | 0 | return res; |
6152 | 0 | } |
6153 | | |
6154 | | Datum |
6155 | | numeric_var_samp(PG_FUNCTION_ARGS) |
6156 | 0 | { |
6157 | 0 | NumericAggState *state; |
6158 | 0 | Numeric res; |
6159 | 0 | bool is_null; |
6160 | |
|
6161 | 0 | state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0); |
6162 | |
|
6163 | 0 | res = numeric_stddev_internal(state, true, true, &is_null); |
6164 | |
|
6165 | 0 | if (is_null) |
6166 | 0 | PG_RETURN_NULL(); |
6167 | 0 | else |
6168 | 0 | PG_RETURN_NUMERIC(res); |
6169 | 0 | } |
6170 | | |
6171 | | Datum |
6172 | | numeric_stddev_samp(PG_FUNCTION_ARGS) |
6173 | 0 | { |
6174 | 0 | NumericAggState *state; |
6175 | 0 | Numeric res; |
6176 | 0 | bool is_null; |
6177 | |
|
6178 | 0 | state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0); |
6179 | |
|
6180 | 0 | res = numeric_stddev_internal(state, false, true, &is_null); |
6181 | |
|
6182 | 0 | if (is_null) |
6183 | 0 | PG_RETURN_NULL(); |
6184 | 0 | else |
6185 | 0 | PG_RETURN_NUMERIC(res); |
6186 | 0 | } |
6187 | | |
6188 | | Datum |
6189 | | numeric_var_pop(PG_FUNCTION_ARGS) |
6190 | 0 | { |
6191 | 0 | NumericAggState *state; |
6192 | 0 | Numeric res; |
6193 | 0 | bool is_null; |
6194 | |
|
6195 | 0 | state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0); |
6196 | |
|
6197 | 0 | res = numeric_stddev_internal(state, true, false, &is_null); |
6198 | |
|
6199 | 0 | if (is_null) |
6200 | 0 | PG_RETURN_NULL(); |
6201 | 0 | else |
6202 | 0 | PG_RETURN_NUMERIC(res); |
6203 | 0 | } |
6204 | | |
6205 | | Datum |
6206 | | numeric_stddev_pop(PG_FUNCTION_ARGS) |
6207 | 0 | { |
6208 | 0 | NumericAggState *state; |
6209 | 0 | Numeric res; |
6210 | 0 | bool is_null; |
6211 | |
|
6212 | 0 | state = PG_ARGISNULL(0) ? NULL : (NumericAggState *) PG_GETARG_POINTER(0); |
6213 | |
|
6214 | 0 | res = numeric_stddev_internal(state, false, false, &is_null); |
6215 | |
|
6216 | 0 | if (is_null) |
6217 | 0 | PG_RETURN_NULL(); |
6218 | 0 | else |
6219 | 0 | PG_RETURN_NUMERIC(res); |
6220 | 0 | } |
6221 | | |
6222 | | static Numeric |
6223 | | numeric_poly_stddev_internal(Int128AggState *state, |
6224 | | bool variance, bool sample, |
6225 | | bool *is_null) |
6226 | 0 | { |
6227 | 0 | NumericAggState numstate; |
6228 | 0 | Numeric res; |
6229 | | |
6230 | | /* Initialize an empty agg state */ |
6231 | 0 | memset(&numstate, 0, sizeof(NumericAggState)); |
6232 | |
|
6233 | 0 | if (state) |
6234 | 0 | { |
6235 | 0 | NumericVar tmp_var; |
6236 | |
|
6237 | 0 | numstate.N = state->N; |
6238 | |
|
6239 | 0 | init_var(&tmp_var); |
6240 | |
|
6241 | 0 | int128_to_numericvar(state->sumX, &tmp_var); |
6242 | 0 | accum_sum_add(&numstate.sumX, &tmp_var); |
6243 | |
|
6244 | 0 | int128_to_numericvar(state->sumX2, &tmp_var); |
6245 | 0 | accum_sum_add(&numstate.sumX2, &tmp_var); |
6246 | |
|
6247 | 0 | free_var(&tmp_var); |
6248 | 0 | } |
6249 | |
|
6250 | 0 | res = numeric_stddev_internal(&numstate, variance, sample, is_null); |
6251 | |
|
6252 | 0 | if (numstate.sumX.ndigits > 0) |
6253 | 0 | { |
6254 | 0 | pfree(numstate.sumX.pos_digits); |
6255 | 0 | pfree(numstate.sumX.neg_digits); |
6256 | 0 | } |
6257 | 0 | if (numstate.sumX2.ndigits > 0) |
6258 | 0 | { |
6259 | 0 | pfree(numstate.sumX2.pos_digits); |
6260 | 0 | pfree(numstate.sumX2.neg_digits); |
6261 | 0 | } |
6262 | |
|
6263 | 0 | return res; |
6264 | 0 | } |
6265 | | |
6266 | | Datum |
6267 | | numeric_poly_var_samp(PG_FUNCTION_ARGS) |
6268 | 0 | { |
6269 | 0 | Int128AggState *state; |
6270 | 0 | Numeric res; |
6271 | 0 | bool is_null; |
6272 | |
|
6273 | 0 | state = PG_ARGISNULL(0) ? NULL : (Int128AggState *) PG_GETARG_POINTER(0); |
6274 | |
|
6275 | 0 | res = numeric_poly_stddev_internal(state, true, true, &is_null); |
6276 | |
|
6277 | 0 | if (is_null) |
6278 | 0 | PG_RETURN_NULL(); |
6279 | 0 | else |
6280 | 0 | PG_RETURN_NUMERIC(res); |
6281 | 0 | } |
6282 | | |
6283 | | Datum |
6284 | | numeric_poly_stddev_samp(PG_FUNCTION_ARGS) |
6285 | 0 | { |
6286 | 0 | Int128AggState *state; |
6287 | 0 | Numeric res; |
6288 | 0 | bool is_null; |
6289 | |
|
6290 | 0 | state = PG_ARGISNULL(0) ? NULL : (Int128AggState *) PG_GETARG_POINTER(0); |
6291 | |
|
6292 | 0 | res = numeric_poly_stddev_internal(state, false, true, &is_null); |
6293 | |
|
6294 | 0 | if (is_null) |
6295 | 0 | PG_RETURN_NULL(); |
6296 | 0 | else |
6297 | 0 | PG_RETURN_NUMERIC(res); |
6298 | 0 | } |
6299 | | |
6300 | | Datum |
6301 | | numeric_poly_var_pop(PG_FUNCTION_ARGS) |
6302 | 0 | { |
6303 | 0 | Int128AggState *state; |
6304 | 0 | Numeric res; |
6305 | 0 | bool is_null; |
6306 | |
|
6307 | 0 | state = PG_ARGISNULL(0) ? NULL : (Int128AggState *) PG_GETARG_POINTER(0); |
6308 | |
|
6309 | 0 | res = numeric_poly_stddev_internal(state, true, false, &is_null); |
6310 | |
|
6311 | 0 | if (is_null) |
6312 | 0 | PG_RETURN_NULL(); |
6313 | 0 | else |
6314 | 0 | PG_RETURN_NUMERIC(res); |
6315 | 0 | } |
6316 | | |
6317 | | Datum |
6318 | | numeric_poly_stddev_pop(PG_FUNCTION_ARGS) |
6319 | 0 | { |
6320 | 0 | Int128AggState *state; |
6321 | 0 | Numeric res; |
6322 | 0 | bool is_null; |
6323 | |
|
6324 | 0 | state = PG_ARGISNULL(0) ? NULL : (Int128AggState *) PG_GETARG_POINTER(0); |
6325 | |
|
6326 | 0 | res = numeric_poly_stddev_internal(state, false, false, &is_null); |
6327 | |
|
6328 | 0 | if (is_null) |
6329 | 0 | PG_RETURN_NULL(); |
6330 | 0 | else |
6331 | 0 | PG_RETURN_NUMERIC(res); |
6332 | 0 | } |
6333 | | |
6334 | | /* |
6335 | | * SUM transition functions for integer datatypes. |
6336 | | * |
6337 | | * To avoid overflow, we use accumulators wider than the input datatype. |
6338 | | * A Numeric accumulator is needed for int8 input; for int4 and int2 |
6339 | | * inputs, we use int8 accumulators which should be sufficient for practical |
6340 | | * purposes. (The latter two therefore don't really belong in this file, |
6341 | | * but we keep them here anyway.) |
6342 | | * |
6343 | | * Because SQL defines the SUM() of no values to be NULL, not zero, |
6344 | | * the initial condition of the transition data value needs to be NULL. This |
6345 | | * means we can't rely on ExecAgg to automatically insert the first non-null |
6346 | | * data value into the transition data: it doesn't know how to do the type |
6347 | | * conversion. The upshot is that these routines have to be marked non-strict |
6348 | | * and handle substitution of the first non-null input themselves. |
6349 | | * |
6350 | | * Note: these functions are used only in plain aggregation mode. |
6351 | | * In moving-aggregate mode, we use intX_avg_accum and intX_avg_accum_inv. |
6352 | | */ |
6353 | | |
6354 | | Datum |
6355 | | int2_sum(PG_FUNCTION_ARGS) |
6356 | 0 | { |
6357 | 0 | int64 oldsum; |
6358 | 0 | int64 newval; |
6359 | |
|
6360 | 0 | if (PG_ARGISNULL(0)) |
6361 | 0 | { |
6362 | | /* No non-null input seen so far... */ |
6363 | 0 | if (PG_ARGISNULL(1)) |
6364 | 0 | PG_RETURN_NULL(); /* still no non-null */ |
6365 | | /* This is the first non-null input. */ |
6366 | 0 | newval = (int64) PG_GETARG_INT16(1); |
6367 | 0 | PG_RETURN_INT64(newval); |
6368 | 0 | } |
6369 | | |
6370 | 0 | oldsum = PG_GETARG_INT64(0); |
6371 | | |
6372 | | /* Leave sum unchanged if new input is null. */ |
6373 | 0 | if (PG_ARGISNULL(1)) |
6374 | 0 | PG_RETURN_INT64(oldsum); |
6375 | | |
6376 | | /* OK to do the addition. */ |
6377 | 0 | newval = oldsum + (int64) PG_GETARG_INT16(1); |
6378 | |
|
6379 | 0 | PG_RETURN_INT64(newval); |
6380 | 0 | } |
6381 | | |
6382 | | Datum |
6383 | | int4_sum(PG_FUNCTION_ARGS) |
6384 | 0 | { |
6385 | 0 | int64 oldsum; |
6386 | 0 | int64 newval; |
6387 | |
|
6388 | 0 | if (PG_ARGISNULL(0)) |
6389 | 0 | { |
6390 | | /* No non-null input seen so far... */ |
6391 | 0 | if (PG_ARGISNULL(1)) |
6392 | 0 | PG_RETURN_NULL(); /* still no non-null */ |
6393 | | /* This is the first non-null input. */ |
6394 | 0 | newval = (int64) PG_GETARG_INT32(1); |
6395 | 0 | PG_RETURN_INT64(newval); |
6396 | 0 | } |
6397 | | |
6398 | 0 | oldsum = PG_GETARG_INT64(0); |
6399 | | |
6400 | | /* Leave sum unchanged if new input is null. */ |
6401 | 0 | if (PG_ARGISNULL(1)) |
6402 | 0 | PG_RETURN_INT64(oldsum); |
6403 | | |
6404 | | /* OK to do the addition. */ |
6405 | 0 | newval = oldsum + (int64) PG_GETARG_INT32(1); |
6406 | |
|
6407 | 0 | PG_RETURN_INT64(newval); |
6408 | 0 | } |
6409 | | |
6410 | | /* |
6411 | | * Note: this function is obsolete, it's no longer used for SUM(int8). |
6412 | | */ |
6413 | | Datum |
6414 | | int8_sum(PG_FUNCTION_ARGS) |
6415 | 0 | { |
6416 | 0 | Numeric oldsum; |
6417 | |
|
6418 | 0 | if (PG_ARGISNULL(0)) |
6419 | 0 | { |
6420 | | /* No non-null input seen so far... */ |
6421 | 0 | if (PG_ARGISNULL(1)) |
6422 | 0 | PG_RETURN_NULL(); /* still no non-null */ |
6423 | | /* This is the first non-null input. */ |
6424 | 0 | PG_RETURN_NUMERIC(int64_to_numeric(PG_GETARG_INT64(1))); |
6425 | 0 | } |
6426 | | |
6427 | | /* |
6428 | | * Note that we cannot special-case the aggregate case here, as we do for |
6429 | | * int2_sum and int4_sum: numeric is of variable size, so we cannot modify |
6430 | | * our first parameter in-place. |
6431 | | */ |
6432 | | |
6433 | 0 | oldsum = PG_GETARG_NUMERIC(0); |
6434 | | |
6435 | | /* Leave sum unchanged if new input is null. */ |
6436 | 0 | if (PG_ARGISNULL(1)) |
6437 | 0 | PG_RETURN_NUMERIC(oldsum); |
6438 | | |
6439 | | /* OK to do the addition. */ |
6440 | 0 | PG_RETURN_DATUM(DirectFunctionCall2(numeric_add, |
6441 | 0 | NumericGetDatum(oldsum), |
6442 | 0 | NumericGetDatum(int64_to_numeric(PG_GETARG_INT64(1))))); |
6443 | 0 | } |
6444 | | |
6445 | | |
6446 | | /* |
6447 | | * Routines for avg(int2) and avg(int4). The transition datatype |
6448 | | * is a two-element int8 array, holding count and sum. |
6449 | | * |
6450 | | * These functions are also used for sum(int2) and sum(int4) when |
6451 | | * operating in moving-aggregate mode, since for correct inverse transitions |
6452 | | * we need to count the inputs. |
6453 | | */ |
6454 | | |
6455 | | typedef struct Int8TransTypeData |
6456 | | { |
6457 | | int64 count; |
6458 | | int64 sum; |
6459 | | } Int8TransTypeData; |
6460 | | |
6461 | | Datum |
6462 | | int2_avg_accum(PG_FUNCTION_ARGS) |
6463 | 0 | { |
6464 | 0 | ArrayType *transarray; |
6465 | 0 | int16 newval = PG_GETARG_INT16(1); |
6466 | 0 | Int8TransTypeData *transdata; |
6467 | | |
6468 | | /* |
6469 | | * If we're invoked as an aggregate, we can cheat and modify our first |
6470 | | * parameter in-place to reduce palloc overhead. Otherwise we need to make |
6471 | | * a copy of it before scribbling on it. |
6472 | | */ |
6473 | 0 | if (AggCheckCallContext(fcinfo, NULL)) |
6474 | 0 | transarray = PG_GETARG_ARRAYTYPE_P(0); |
6475 | 0 | else |
6476 | 0 | transarray = PG_GETARG_ARRAYTYPE_P_COPY(0); |
6477 | |
|
6478 | 0 | if (ARR_HASNULL(transarray) || |
6479 | 0 | ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData)) |
6480 | 0 | elog(ERROR, "expected 2-element int8 array"); |
6481 | | |
6482 | 0 | transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray); |
6483 | 0 | transdata->count++; |
6484 | 0 | transdata->sum += newval; |
6485 | |
|
6486 | 0 | PG_RETURN_ARRAYTYPE_P(transarray); |
6487 | 0 | } |
6488 | | |
6489 | | Datum |
6490 | | int4_avg_accum(PG_FUNCTION_ARGS) |
6491 | 0 | { |
6492 | 0 | ArrayType *transarray; |
6493 | 0 | int32 newval = PG_GETARG_INT32(1); |
6494 | 0 | Int8TransTypeData *transdata; |
6495 | | |
6496 | | /* |
6497 | | * If we're invoked as an aggregate, we can cheat and modify our first |
6498 | | * parameter in-place to reduce palloc overhead. Otherwise we need to make |
6499 | | * a copy of it before scribbling on it. |
6500 | | */ |
6501 | 0 | if (AggCheckCallContext(fcinfo, NULL)) |
6502 | 0 | transarray = PG_GETARG_ARRAYTYPE_P(0); |
6503 | 0 | else |
6504 | 0 | transarray = PG_GETARG_ARRAYTYPE_P_COPY(0); |
6505 | |
|
6506 | 0 | if (ARR_HASNULL(transarray) || |
6507 | 0 | ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData)) |
6508 | 0 | elog(ERROR, "expected 2-element int8 array"); |
6509 | | |
6510 | 0 | transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray); |
6511 | 0 | transdata->count++; |
6512 | 0 | transdata->sum += newval; |
6513 | |
|
6514 | 0 | PG_RETURN_ARRAYTYPE_P(transarray); |
6515 | 0 | } |
6516 | | |
6517 | | Datum |
6518 | | int4_avg_combine(PG_FUNCTION_ARGS) |
6519 | 0 | { |
6520 | 0 | ArrayType *transarray1; |
6521 | 0 | ArrayType *transarray2; |
6522 | 0 | Int8TransTypeData *state1; |
6523 | 0 | Int8TransTypeData *state2; |
6524 | |
|
6525 | 0 | if (!AggCheckCallContext(fcinfo, NULL)) |
6526 | 0 | elog(ERROR, "aggregate function called in non-aggregate context"); |
6527 | | |
6528 | 0 | transarray1 = PG_GETARG_ARRAYTYPE_P(0); |
6529 | 0 | transarray2 = PG_GETARG_ARRAYTYPE_P(1); |
6530 | |
|
6531 | 0 | if (ARR_HASNULL(transarray1) || |
6532 | 0 | ARR_SIZE(transarray1) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData)) |
6533 | 0 | elog(ERROR, "expected 2-element int8 array"); |
6534 | | |
6535 | 0 | if (ARR_HASNULL(transarray2) || |
6536 | 0 | ARR_SIZE(transarray2) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData)) |
6537 | 0 | elog(ERROR, "expected 2-element int8 array"); |
6538 | | |
6539 | 0 | state1 = (Int8TransTypeData *) ARR_DATA_PTR(transarray1); |
6540 | 0 | state2 = (Int8TransTypeData *) ARR_DATA_PTR(transarray2); |
6541 | |
|
6542 | 0 | state1->count += state2->count; |
6543 | 0 | state1->sum += state2->sum; |
6544 | |
|
6545 | 0 | PG_RETURN_ARRAYTYPE_P(transarray1); |
6546 | 0 | } |
6547 | | |
6548 | | Datum |
6549 | | int2_avg_accum_inv(PG_FUNCTION_ARGS) |
6550 | 0 | { |
6551 | 0 | ArrayType *transarray; |
6552 | 0 | int16 newval = PG_GETARG_INT16(1); |
6553 | 0 | Int8TransTypeData *transdata; |
6554 | | |
6555 | | /* |
6556 | | * If we're invoked as an aggregate, we can cheat and modify our first |
6557 | | * parameter in-place to reduce palloc overhead. Otherwise we need to make |
6558 | | * a copy of it before scribbling on it. |
6559 | | */ |
6560 | 0 | if (AggCheckCallContext(fcinfo, NULL)) |
6561 | 0 | transarray = PG_GETARG_ARRAYTYPE_P(0); |
6562 | 0 | else |
6563 | 0 | transarray = PG_GETARG_ARRAYTYPE_P_COPY(0); |
6564 | |
|
6565 | 0 | if (ARR_HASNULL(transarray) || |
6566 | 0 | ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData)) |
6567 | 0 | elog(ERROR, "expected 2-element int8 array"); |
6568 | | |
6569 | 0 | transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray); |
6570 | 0 | transdata->count--; |
6571 | 0 | transdata->sum -= newval; |
6572 | |
|
6573 | 0 | PG_RETURN_ARRAYTYPE_P(transarray); |
6574 | 0 | } |
6575 | | |
6576 | | Datum |
6577 | | int4_avg_accum_inv(PG_FUNCTION_ARGS) |
6578 | 0 | { |
6579 | 0 | ArrayType *transarray; |
6580 | 0 | int32 newval = PG_GETARG_INT32(1); |
6581 | 0 | Int8TransTypeData *transdata; |
6582 | | |
6583 | | /* |
6584 | | * If we're invoked as an aggregate, we can cheat and modify our first |
6585 | | * parameter in-place to reduce palloc overhead. Otherwise we need to make |
6586 | | * a copy of it before scribbling on it. |
6587 | | */ |
6588 | 0 | if (AggCheckCallContext(fcinfo, NULL)) |
6589 | 0 | transarray = PG_GETARG_ARRAYTYPE_P(0); |
6590 | 0 | else |
6591 | 0 | transarray = PG_GETARG_ARRAYTYPE_P_COPY(0); |
6592 | |
|
6593 | 0 | if (ARR_HASNULL(transarray) || |
6594 | 0 | ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData)) |
6595 | 0 | elog(ERROR, "expected 2-element int8 array"); |
6596 | | |
6597 | 0 | transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray); |
6598 | 0 | transdata->count--; |
6599 | 0 | transdata->sum -= newval; |
6600 | |
|
6601 | 0 | PG_RETURN_ARRAYTYPE_P(transarray); |
6602 | 0 | } |
6603 | | |
6604 | | Datum |
6605 | | int8_avg(PG_FUNCTION_ARGS) |
6606 | 0 | { |
6607 | 0 | ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0); |
6608 | 0 | Int8TransTypeData *transdata; |
6609 | 0 | Datum countd, |
6610 | 0 | sumd; |
6611 | |
|
6612 | 0 | if (ARR_HASNULL(transarray) || |
6613 | 0 | ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData)) |
6614 | 0 | elog(ERROR, "expected 2-element int8 array"); |
6615 | 0 | transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray); |
6616 | | |
6617 | | /* SQL defines AVG of no values to be NULL */ |
6618 | 0 | if (transdata->count == 0) |
6619 | 0 | PG_RETURN_NULL(); |
6620 | | |
6621 | 0 | countd = NumericGetDatum(int64_to_numeric(transdata->count)); |
6622 | 0 | sumd = NumericGetDatum(int64_to_numeric(transdata->sum)); |
6623 | |
|
6624 | 0 | PG_RETURN_DATUM(DirectFunctionCall2(numeric_div, sumd, countd)); |
6625 | 0 | } |
6626 | | |
6627 | | /* |
6628 | | * SUM(int2) and SUM(int4) both return int8, so we can use this |
6629 | | * final function for both. |
6630 | | */ |
6631 | | Datum |
6632 | | int2int4_sum(PG_FUNCTION_ARGS) |
6633 | 0 | { |
6634 | 0 | ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0); |
6635 | 0 | Int8TransTypeData *transdata; |
6636 | |
|
6637 | 0 | if (ARR_HASNULL(transarray) || |
6638 | 0 | ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData)) |
6639 | 0 | elog(ERROR, "expected 2-element int8 array"); |
6640 | 0 | transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray); |
6641 | | |
6642 | | /* SQL defines SUM of no values to be NULL */ |
6643 | 0 | if (transdata->count == 0) |
6644 | 0 | PG_RETURN_NULL(); |
6645 | | |
6646 | 0 | PG_RETURN_DATUM(Int64GetDatumFast(transdata->sum)); |
6647 | 0 | } |
6648 | | |
6649 | | |
6650 | | /* ---------------------------------------------------------------------- |
6651 | | * |
6652 | | * Debug support |
6653 | | * |
6654 | | * ---------------------------------------------------------------------- |
6655 | | */ |
6656 | | |
6657 | | #ifdef NUMERIC_DEBUG |
6658 | | |
6659 | | /* |
6660 | | * dump_numeric() - Dump a value in the db storage format for debugging |
6661 | | */ |
6662 | | static void |
6663 | | dump_numeric(const char *str, Numeric num) |
6664 | | { |
6665 | | NumericDigit *digits = NUMERIC_DIGITS(num); |
6666 | | int ndigits; |
6667 | | int i; |
6668 | | |
6669 | | ndigits = NUMERIC_NDIGITS(num); |
6670 | | |
6671 | | printf("%s: NUMERIC w=%d d=%d ", str, |
6672 | | NUMERIC_WEIGHT(num), NUMERIC_DSCALE(num)); |
6673 | | switch (NUMERIC_SIGN(num)) |
6674 | | { |
6675 | | case NUMERIC_POS: |
6676 | | printf("POS"); |
6677 | | break; |
6678 | | case NUMERIC_NEG: |
6679 | | printf("NEG"); |
6680 | | break; |
6681 | | case NUMERIC_NAN: |
6682 | | printf("NaN"); |
6683 | | break; |
6684 | | case NUMERIC_PINF: |
6685 | | printf("Infinity"); |
6686 | | break; |
6687 | | case NUMERIC_NINF: |
6688 | | printf("-Infinity"); |
6689 | | break; |
6690 | | default: |
6691 | | printf("SIGN=0x%x", NUMERIC_SIGN(num)); |
6692 | | break; |
6693 | | } |
6694 | | |
6695 | | for (i = 0; i < ndigits; i++) |
6696 | | printf(" %0*d", DEC_DIGITS, digits[i]); |
6697 | | printf("\n"); |
6698 | | } |
6699 | | |
6700 | | |
6701 | | /* |
6702 | | * dump_var() - Dump a value in the variable format for debugging |
6703 | | */ |
6704 | | static void |
6705 | | dump_var(const char *str, NumericVar *var) |
6706 | | { |
6707 | | int i; |
6708 | | |
6709 | | printf("%s: VAR w=%d d=%d ", str, var->weight, var->dscale); |
6710 | | switch (var->sign) |
6711 | | { |
6712 | | case NUMERIC_POS: |
6713 | | printf("POS"); |
6714 | | break; |
6715 | | case NUMERIC_NEG: |
6716 | | printf("NEG"); |
6717 | | break; |
6718 | | case NUMERIC_NAN: |
6719 | | printf("NaN"); |
6720 | | break; |
6721 | | case NUMERIC_PINF: |
6722 | | printf("Infinity"); |
6723 | | break; |
6724 | | case NUMERIC_NINF: |
6725 | | printf("-Infinity"); |
6726 | | break; |
6727 | | default: |
6728 | | printf("SIGN=0x%x", var->sign); |
6729 | | break; |
6730 | | } |
6731 | | |
6732 | | for (i = 0; i < var->ndigits; i++) |
6733 | | printf(" %0*d", DEC_DIGITS, var->digits[i]); |
6734 | | |
6735 | | printf("\n"); |
6736 | | } |
6737 | | #endif /* NUMERIC_DEBUG */ |
6738 | | |
6739 | | |
6740 | | /* ---------------------------------------------------------------------- |
6741 | | * |
6742 | | * Local functions follow |
6743 | | * |
6744 | | * In general, these do not support "special" (NaN or infinity) inputs; |
6745 | | * callers should handle those possibilities first. |
6746 | | * (There are one or two exceptions, noted in their header comments.) |
6747 | | * |
6748 | | * ---------------------------------------------------------------------- |
6749 | | */ |
6750 | | |
6751 | | |
6752 | | /* |
6753 | | * alloc_var() - |
6754 | | * |
6755 | | * Allocate a digit buffer of ndigits digits (plus a spare digit for rounding) |
6756 | | */ |
6757 | | static void |
6758 | | alloc_var(NumericVar *var, int ndigits) |
6759 | 0 | { |
6760 | 0 | digitbuf_free(var->buf); |
6761 | 0 | var->buf = digitbuf_alloc(ndigits + 1); |
6762 | 0 | var->buf[0] = 0; /* spare digit for rounding */ |
6763 | 0 | var->digits = var->buf + 1; |
6764 | 0 | var->ndigits = ndigits; |
6765 | 0 | } |
6766 | | |
6767 | | |
6768 | | /* |
6769 | | * free_var() - |
6770 | | * |
6771 | | * Return the digit buffer of a variable to the free pool |
6772 | | */ |
6773 | | static void |
6774 | | free_var(NumericVar *var) |
6775 | 0 | { |
6776 | 0 | digitbuf_free(var->buf); |
6777 | 0 | var->buf = NULL; |
6778 | 0 | var->digits = NULL; |
6779 | 0 | var->sign = NUMERIC_NAN; |
6780 | 0 | } |
6781 | | |
6782 | | |
6783 | | /* |
6784 | | * zero_var() - |
6785 | | * |
6786 | | * Set a variable to ZERO. |
6787 | | * Note: its dscale is not touched. |
6788 | | */ |
6789 | | static void |
6790 | | zero_var(NumericVar *var) |
6791 | 0 | { |
6792 | 0 | digitbuf_free(var->buf); |
6793 | 0 | var->buf = NULL; |
6794 | 0 | var->digits = NULL; |
6795 | 0 | var->ndigits = 0; |
6796 | 0 | var->weight = 0; /* by convention; doesn't really matter */ |
6797 | 0 | var->sign = NUMERIC_POS; /* anything but NAN... */ |
6798 | 0 | } |
6799 | | |
6800 | | |
6801 | | /* |
6802 | | * set_var_from_str() |
6803 | | * |
6804 | | * Parse a string and put the number into a variable |
6805 | | * |
6806 | | * This function does not handle leading or trailing spaces. It returns |
6807 | | * the end+1 position parsed into *endptr, so that caller can check for |
6808 | | * trailing spaces/garbage if deemed necessary. |
6809 | | * |
6810 | | * cp is the place to actually start parsing; str is what to use in error |
6811 | | * reports. (Typically cp would be the same except advanced over spaces.) |
6812 | | * |
6813 | | * Returns true on success, false on failure (if escontext points to an |
6814 | | * ErrorSaveContext; otherwise errors are thrown). |
6815 | | */ |
6816 | | static bool |
6817 | | set_var_from_str(const char *str, const char *cp, |
6818 | | NumericVar *dest, const char **endptr, |
6819 | | Node *escontext) |
6820 | 0 | { |
6821 | 0 | bool have_dp = false; |
6822 | 0 | int i; |
6823 | 0 | unsigned char *decdigits; |
6824 | 0 | int sign = NUMERIC_POS; |
6825 | 0 | int dweight = -1; |
6826 | 0 | int ddigits; |
6827 | 0 | int dscale = 0; |
6828 | 0 | int weight; |
6829 | 0 | int ndigits; |
6830 | 0 | int offset; |
6831 | 0 | NumericDigit *digits; |
6832 | | |
6833 | | /* |
6834 | | * We first parse the string to extract decimal digits and determine the |
6835 | | * correct decimal weight. Then convert to NBASE representation. |
6836 | | */ |
6837 | 0 | switch (*cp) |
6838 | 0 | { |
6839 | 0 | case '+': |
6840 | 0 | sign = NUMERIC_POS; |
6841 | 0 | cp++; |
6842 | 0 | break; |
6843 | | |
6844 | 0 | case '-': |
6845 | 0 | sign = NUMERIC_NEG; |
6846 | 0 | cp++; |
6847 | 0 | break; |
6848 | 0 | } |
6849 | | |
6850 | 0 | if (*cp == '.') |
6851 | 0 | { |
6852 | 0 | have_dp = true; |
6853 | 0 | cp++; |
6854 | 0 | } |
6855 | |
|
6856 | 0 | if (!isdigit((unsigned char) *cp)) |
6857 | 0 | goto invalid_syntax; |
6858 | | |
6859 | 0 | decdigits = (unsigned char *) palloc(strlen(cp) + DEC_DIGITS * 2); |
6860 | | |
6861 | | /* leading padding for digit alignment later */ |
6862 | 0 | memset(decdigits, 0, DEC_DIGITS); |
6863 | 0 | i = DEC_DIGITS; |
6864 | |
|
6865 | 0 | while (*cp) |
6866 | 0 | { |
6867 | 0 | if (isdigit((unsigned char) *cp)) |
6868 | 0 | { |
6869 | 0 | decdigits[i++] = *cp++ - '0'; |
6870 | 0 | if (!have_dp) |
6871 | 0 | dweight++; |
6872 | 0 | else |
6873 | 0 | dscale++; |
6874 | 0 | } |
6875 | 0 | else if (*cp == '.') |
6876 | 0 | { |
6877 | 0 | if (have_dp) |
6878 | 0 | goto invalid_syntax; |
6879 | 0 | have_dp = true; |
6880 | 0 | cp++; |
6881 | | /* decimal point must not be followed by underscore */ |
6882 | 0 | if (*cp == '_') |
6883 | 0 | goto invalid_syntax; |
6884 | 0 | } |
6885 | 0 | else if (*cp == '_') |
6886 | 0 | { |
6887 | | /* underscore must be followed by more digits */ |
6888 | 0 | cp++; |
6889 | 0 | if (!isdigit((unsigned char) *cp)) |
6890 | 0 | goto invalid_syntax; |
6891 | 0 | } |
6892 | 0 | else |
6893 | 0 | break; |
6894 | 0 | } |
6895 | | |
6896 | 0 | ddigits = i - DEC_DIGITS; |
6897 | | /* trailing padding for digit alignment later */ |
6898 | 0 | memset(decdigits + i, 0, DEC_DIGITS - 1); |
6899 | | |
6900 | | /* Handle exponent, if any */ |
6901 | 0 | if (*cp == 'e' || *cp == 'E') |
6902 | 0 | { |
6903 | 0 | int64 exponent = 0; |
6904 | 0 | bool neg = false; |
6905 | | |
6906 | | /* |
6907 | | * At this point, dweight and dscale can't be more than about |
6908 | | * INT_MAX/2 due to the MaxAllocSize limit on string length, so |
6909 | | * constraining the exponent similarly should be enough to prevent |
6910 | | * integer overflow in this function. If the value is too large to |
6911 | | * fit in storage format, make_result() will complain about it later; |
6912 | | * for consistency use the same ereport errcode/text as make_result(). |
6913 | | */ |
6914 | | |
6915 | | /* exponent sign */ |
6916 | 0 | cp++; |
6917 | 0 | if (*cp == '+') |
6918 | 0 | cp++; |
6919 | 0 | else if (*cp == '-') |
6920 | 0 | { |
6921 | 0 | neg = true; |
6922 | 0 | cp++; |
6923 | 0 | } |
6924 | | |
6925 | | /* exponent digits */ |
6926 | 0 | if (!isdigit((unsigned char) *cp)) |
6927 | 0 | goto invalid_syntax; |
6928 | | |
6929 | 0 | while (*cp) |
6930 | 0 | { |
6931 | 0 | if (isdigit((unsigned char) *cp)) |
6932 | 0 | { |
6933 | 0 | exponent = exponent * 10 + (*cp++ - '0'); |
6934 | 0 | if (exponent > PG_INT32_MAX / 2) |
6935 | 0 | goto out_of_range; |
6936 | 0 | } |
6937 | 0 | else if (*cp == '_') |
6938 | 0 | { |
6939 | | /* underscore must be followed by more digits */ |
6940 | 0 | cp++; |
6941 | 0 | if (!isdigit((unsigned char) *cp)) |
6942 | 0 | goto invalid_syntax; |
6943 | 0 | } |
6944 | 0 | else |
6945 | 0 | break; |
6946 | 0 | } |
6947 | | |
6948 | 0 | if (neg) |
6949 | 0 | exponent = -exponent; |
6950 | |
|
6951 | 0 | dweight += (int) exponent; |
6952 | 0 | dscale -= (int) exponent; |
6953 | 0 | if (dscale < 0) |
6954 | 0 | dscale = 0; |
6955 | 0 | } |
6956 | | |
6957 | | /* |
6958 | | * Okay, convert pure-decimal representation to base NBASE. First we need |
6959 | | * to determine the converted weight and ndigits. offset is the number of |
6960 | | * decimal zeroes to insert before the first given digit to have a |
6961 | | * correctly aligned first NBASE digit. |
6962 | | */ |
6963 | 0 | if (dweight >= 0) |
6964 | 0 | weight = (dweight + 1 + DEC_DIGITS - 1) / DEC_DIGITS - 1; |
6965 | 0 | else |
6966 | 0 | weight = -((-dweight - 1) / DEC_DIGITS + 1); |
6967 | 0 | offset = (weight + 1) * DEC_DIGITS - (dweight + 1); |
6968 | 0 | ndigits = (ddigits + offset + DEC_DIGITS - 1) / DEC_DIGITS; |
6969 | |
|
6970 | 0 | alloc_var(dest, ndigits); |
6971 | 0 | dest->sign = sign; |
6972 | 0 | dest->weight = weight; |
6973 | 0 | dest->dscale = dscale; |
6974 | |
|
6975 | 0 | i = DEC_DIGITS - offset; |
6976 | 0 | digits = dest->digits; |
6977 | |
|
6978 | 0 | while (ndigits-- > 0) |
6979 | 0 | { |
6980 | 0 | #if DEC_DIGITS == 4 |
6981 | 0 | *digits++ = ((decdigits[i] * 10 + decdigits[i + 1]) * 10 + |
6982 | 0 | decdigits[i + 2]) * 10 + decdigits[i + 3]; |
6983 | | #elif DEC_DIGITS == 2 |
6984 | | *digits++ = decdigits[i] * 10 + decdigits[i + 1]; |
6985 | | #elif DEC_DIGITS == 1 |
6986 | | *digits++ = decdigits[i]; |
6987 | | #else |
6988 | | #error unsupported NBASE |
6989 | | #endif |
6990 | 0 | i += DEC_DIGITS; |
6991 | 0 | } |
6992 | |
|
6993 | 0 | pfree(decdigits); |
6994 | | |
6995 | | /* Strip any leading/trailing zeroes, and normalize weight if zero */ |
6996 | 0 | strip_var(dest); |
6997 | | |
6998 | | /* Return end+1 position for caller */ |
6999 | 0 | *endptr = cp; |
7000 | |
|
7001 | 0 | return true; |
7002 | | |
7003 | 0 | out_of_range: |
7004 | 0 | ereturn(escontext, false, |
7005 | 0 | (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), |
7006 | 0 | errmsg("value overflows numeric format"))); |
7007 | | |
7008 | 0 | invalid_syntax: |
7009 | 0 | ereturn(escontext, false, |
7010 | 0 | (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), |
7011 | 0 | errmsg("invalid input syntax for type %s: \"%s\"", |
7012 | 0 | "numeric", str))); |
7013 | 0 | } |
7014 | | |
7015 | | |
7016 | | /* |
7017 | | * Return the numeric value of a single hex digit. |
7018 | | */ |
7019 | | static inline int |
7020 | | xdigit_value(char dig) |
7021 | 0 | { |
7022 | 0 | return dig >= '0' && dig <= '9' ? dig - '0' : |
7023 | 0 | dig >= 'a' && dig <= 'f' ? dig - 'a' + 10 : |
7024 | 0 | dig >= 'A' && dig <= 'F' ? dig - 'A' + 10 : -1; |
7025 | 0 | } |
7026 | | |
7027 | | /* |
7028 | | * set_var_from_non_decimal_integer_str() |
7029 | | * |
7030 | | * Parse a string containing a non-decimal integer |
7031 | | * |
7032 | | * This function does not handle leading or trailing spaces. It returns |
7033 | | * the end+1 position parsed into *endptr, so that caller can check for |
7034 | | * trailing spaces/garbage if deemed necessary. |
7035 | | * |
7036 | | * cp is the place to actually start parsing; str is what to use in error |
7037 | | * reports. The number's sign and base prefix indicator (e.g., "0x") are |
7038 | | * assumed to have already been parsed, so cp should point to the number's |
7039 | | * first digit in the base specified. |
7040 | | * |
7041 | | * base is expected to be 2, 8 or 16. |
7042 | | * |
7043 | | * Returns true on success, false on failure (if escontext points to an |
7044 | | * ErrorSaveContext; otherwise errors are thrown). |
7045 | | */ |
7046 | | static bool |
7047 | | set_var_from_non_decimal_integer_str(const char *str, const char *cp, int sign, |
7048 | | int base, NumericVar *dest, |
7049 | | const char **endptr, Node *escontext) |
7050 | 0 | { |
7051 | 0 | const char *firstdigit = cp; |
7052 | 0 | int64 tmp; |
7053 | 0 | int64 mul; |
7054 | 0 | NumericVar tmp_var; |
7055 | |
|
7056 | 0 | init_var(&tmp_var); |
7057 | |
|
7058 | 0 | zero_var(dest); |
7059 | | |
7060 | | /* |
7061 | | * Process input digits in groups that fit in int64. Here "tmp" is the |
7062 | | * value of the digits in the group, and "mul" is base^n, where n is the |
7063 | | * number of digits in the group. Thus tmp < mul, and we must start a new |
7064 | | * group when mul * base threatens to overflow PG_INT64_MAX. |
7065 | | */ |
7066 | 0 | tmp = 0; |
7067 | 0 | mul = 1; |
7068 | |
|
7069 | 0 | if (base == 16) |
7070 | 0 | { |
7071 | 0 | while (*cp) |
7072 | 0 | { |
7073 | 0 | if (isxdigit((unsigned char) *cp)) |
7074 | 0 | { |
7075 | 0 | if (mul > PG_INT64_MAX / 16) |
7076 | 0 | { |
7077 | | /* Add the contribution from this group of digits */ |
7078 | 0 | int64_to_numericvar(mul, &tmp_var); |
7079 | 0 | mul_var(dest, &tmp_var, dest, 0); |
7080 | 0 | int64_to_numericvar(tmp, &tmp_var); |
7081 | 0 | add_var(dest, &tmp_var, dest); |
7082 | | |
7083 | | /* Result will overflow if weight overflows int16 */ |
7084 | 0 | if (dest->weight > NUMERIC_WEIGHT_MAX) |
7085 | 0 | goto out_of_range; |
7086 | | |
7087 | | /* Begin a new group */ |
7088 | 0 | tmp = 0; |
7089 | 0 | mul = 1; |
7090 | 0 | } |
7091 | | |
7092 | 0 | tmp = tmp * 16 + xdigit_value(*cp++); |
7093 | 0 | mul = mul * 16; |
7094 | 0 | } |
7095 | 0 | else if (*cp == '_') |
7096 | 0 | { |
7097 | | /* Underscore must be followed by more digits */ |
7098 | 0 | cp++; |
7099 | 0 | if (!isxdigit((unsigned char) *cp)) |
7100 | 0 | goto invalid_syntax; |
7101 | 0 | } |
7102 | 0 | else |
7103 | 0 | break; |
7104 | 0 | } |
7105 | 0 | } |
7106 | 0 | else if (base == 8) |
7107 | 0 | { |
7108 | 0 | while (*cp) |
7109 | 0 | { |
7110 | 0 | if (*cp >= '0' && *cp <= '7') |
7111 | 0 | { |
7112 | 0 | if (mul > PG_INT64_MAX / 8) |
7113 | 0 | { |
7114 | | /* Add the contribution from this group of digits */ |
7115 | 0 | int64_to_numericvar(mul, &tmp_var); |
7116 | 0 | mul_var(dest, &tmp_var, dest, 0); |
7117 | 0 | int64_to_numericvar(tmp, &tmp_var); |
7118 | 0 | add_var(dest, &tmp_var, dest); |
7119 | | |
7120 | | /* Result will overflow if weight overflows int16 */ |
7121 | 0 | if (dest->weight > NUMERIC_WEIGHT_MAX) |
7122 | 0 | goto out_of_range; |
7123 | | |
7124 | | /* Begin a new group */ |
7125 | 0 | tmp = 0; |
7126 | 0 | mul = 1; |
7127 | 0 | } |
7128 | | |
7129 | 0 | tmp = tmp * 8 + (*cp++ - '0'); |
7130 | 0 | mul = mul * 8; |
7131 | 0 | } |
7132 | 0 | else if (*cp == '_') |
7133 | 0 | { |
7134 | | /* Underscore must be followed by more digits */ |
7135 | 0 | cp++; |
7136 | 0 | if (*cp < '0' || *cp > '7') |
7137 | 0 | goto invalid_syntax; |
7138 | 0 | } |
7139 | 0 | else |
7140 | 0 | break; |
7141 | 0 | } |
7142 | 0 | } |
7143 | 0 | else if (base == 2) |
7144 | 0 | { |
7145 | 0 | while (*cp) |
7146 | 0 | { |
7147 | 0 | if (*cp >= '0' && *cp <= '1') |
7148 | 0 | { |
7149 | 0 | if (mul > PG_INT64_MAX / 2) |
7150 | 0 | { |
7151 | | /* Add the contribution from this group of digits */ |
7152 | 0 | int64_to_numericvar(mul, &tmp_var); |
7153 | 0 | mul_var(dest, &tmp_var, dest, 0); |
7154 | 0 | int64_to_numericvar(tmp, &tmp_var); |
7155 | 0 | add_var(dest, &tmp_var, dest); |
7156 | | |
7157 | | /* Result will overflow if weight overflows int16 */ |
7158 | 0 | if (dest->weight > NUMERIC_WEIGHT_MAX) |
7159 | 0 | goto out_of_range; |
7160 | | |
7161 | | /* Begin a new group */ |
7162 | 0 | tmp = 0; |
7163 | 0 | mul = 1; |
7164 | 0 | } |
7165 | | |
7166 | 0 | tmp = tmp * 2 + (*cp++ - '0'); |
7167 | 0 | mul = mul * 2; |
7168 | 0 | } |
7169 | 0 | else if (*cp == '_') |
7170 | 0 | { |
7171 | | /* Underscore must be followed by more digits */ |
7172 | 0 | cp++; |
7173 | 0 | if (*cp < '0' || *cp > '1') |
7174 | 0 | goto invalid_syntax; |
7175 | 0 | } |
7176 | 0 | else |
7177 | 0 | break; |
7178 | 0 | } |
7179 | 0 | } |
7180 | 0 | else |
7181 | | /* Should never happen; treat as invalid input */ |
7182 | 0 | goto invalid_syntax; |
7183 | | |
7184 | | /* Check that we got at least one digit */ |
7185 | 0 | if (unlikely(cp == firstdigit)) |
7186 | 0 | goto invalid_syntax; |
7187 | | |
7188 | | /* Add the contribution from the final group of digits */ |
7189 | 0 | int64_to_numericvar(mul, &tmp_var); |
7190 | 0 | mul_var(dest, &tmp_var, dest, 0); |
7191 | 0 | int64_to_numericvar(tmp, &tmp_var); |
7192 | 0 | add_var(dest, &tmp_var, dest); |
7193 | |
|
7194 | 0 | if (dest->weight > NUMERIC_WEIGHT_MAX) |
7195 | 0 | goto out_of_range; |
7196 | | |
7197 | 0 | dest->sign = sign; |
7198 | |
|
7199 | 0 | free_var(&tmp_var); |
7200 | | |
7201 | | /* Return end+1 position for caller */ |
7202 | 0 | *endptr = cp; |
7203 | |
|
7204 | 0 | return true; |
7205 | | |
7206 | 0 | out_of_range: |
7207 | 0 | ereturn(escontext, false, |
7208 | 0 | (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), |
7209 | 0 | errmsg("value overflows numeric format"))); |
7210 | | |
7211 | 0 | invalid_syntax: |
7212 | 0 | ereturn(escontext, false, |
7213 | 0 | (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), |
7214 | 0 | errmsg("invalid input syntax for type %s: \"%s\"", |
7215 | 0 | "numeric", str))); |
7216 | 0 | } |
7217 | | |
7218 | | |
7219 | | /* |
7220 | | * set_var_from_num() - |
7221 | | * |
7222 | | * Convert the packed db format into a variable |
7223 | | */ |
7224 | | static void |
7225 | | set_var_from_num(Numeric num, NumericVar *dest) |
7226 | 0 | { |
7227 | 0 | int ndigits; |
7228 | |
|
7229 | 0 | ndigits = NUMERIC_NDIGITS(num); |
7230 | |
|
7231 | 0 | alloc_var(dest, ndigits); |
7232 | |
|
7233 | 0 | dest->weight = NUMERIC_WEIGHT(num); |
7234 | 0 | dest->sign = NUMERIC_SIGN(num); |
7235 | 0 | dest->dscale = NUMERIC_DSCALE(num); |
7236 | |
|
7237 | 0 | memcpy(dest->digits, NUMERIC_DIGITS(num), ndigits * sizeof(NumericDigit)); |
7238 | 0 | } |
7239 | | |
7240 | | |
7241 | | /* |
7242 | | * init_var_from_num() - |
7243 | | * |
7244 | | * Initialize a variable from packed db format. The digits array is not |
7245 | | * copied, which saves some cycles when the resulting var is not modified. |
7246 | | * Also, there's no need to call free_var(), as long as you don't assign any |
7247 | | * other value to it (with set_var_* functions, or by using the var as the |
7248 | | * destination of a function like add_var()) |
7249 | | * |
7250 | | * CAUTION: Do not modify the digits buffer of a var initialized with this |
7251 | | * function, e.g by calling round_var() or trunc_var(), as the changes will |
7252 | | * propagate to the original Numeric! It's OK to use it as the destination |
7253 | | * argument of one of the calculational functions, though. |
7254 | | */ |
7255 | | static void |
7256 | | init_var_from_num(Numeric num, NumericVar *dest) |
7257 | 0 | { |
7258 | 0 | dest->ndigits = NUMERIC_NDIGITS(num); |
7259 | 0 | dest->weight = NUMERIC_WEIGHT(num); |
7260 | 0 | dest->sign = NUMERIC_SIGN(num); |
7261 | 0 | dest->dscale = NUMERIC_DSCALE(num); |
7262 | 0 | dest->digits = NUMERIC_DIGITS(num); |
7263 | 0 | dest->buf = NULL; /* digits array is not palloc'd */ |
7264 | 0 | } |
7265 | | |
7266 | | |
7267 | | /* |
7268 | | * set_var_from_var() - |
7269 | | * |
7270 | | * Copy one variable into another |
7271 | | */ |
7272 | | static void |
7273 | | set_var_from_var(const NumericVar *value, NumericVar *dest) |
7274 | 0 | { |
7275 | 0 | NumericDigit *newbuf; |
7276 | |
|
7277 | 0 | newbuf = digitbuf_alloc(value->ndigits + 1); |
7278 | 0 | newbuf[0] = 0; /* spare digit for rounding */ |
7279 | 0 | if (value->ndigits > 0) /* else value->digits might be null */ |
7280 | 0 | memcpy(newbuf + 1, value->digits, |
7281 | 0 | value->ndigits * sizeof(NumericDigit)); |
7282 | |
|
7283 | 0 | digitbuf_free(dest->buf); |
7284 | |
|
7285 | 0 | memmove(dest, value, sizeof(NumericVar)); |
7286 | 0 | dest->buf = newbuf; |
7287 | 0 | dest->digits = newbuf + 1; |
7288 | 0 | } |
7289 | | |
7290 | | |
7291 | | /* |
7292 | | * get_str_from_var() - |
7293 | | * |
7294 | | * Convert a var to text representation (guts of numeric_out). |
7295 | | * The var is displayed to the number of digits indicated by its dscale. |
7296 | | * Returns a palloc'd string. |
7297 | | */ |
7298 | | static char * |
7299 | | get_str_from_var(const NumericVar *var) |
7300 | 0 | { |
7301 | 0 | int dscale; |
7302 | 0 | char *str; |
7303 | 0 | char *cp; |
7304 | 0 | char *endcp; |
7305 | 0 | int i; |
7306 | 0 | int d; |
7307 | 0 | NumericDigit dig; |
7308 | |
|
7309 | 0 | #if DEC_DIGITS > 1 |
7310 | 0 | NumericDigit d1; |
7311 | 0 | #endif |
7312 | |
|
7313 | 0 | dscale = var->dscale; |
7314 | | |
7315 | | /* |
7316 | | * Allocate space for the result. |
7317 | | * |
7318 | | * i is set to the # of decimal digits before decimal point. dscale is the |
7319 | | * # of decimal digits we will print after decimal point. We may generate |
7320 | | * as many as DEC_DIGITS-1 excess digits at the end, and in addition we |
7321 | | * need room for sign, decimal point, null terminator. |
7322 | | */ |
7323 | 0 | i = (var->weight + 1) * DEC_DIGITS; |
7324 | 0 | if (i <= 0) |
7325 | 0 | i = 1; |
7326 | |
|
7327 | 0 | str = palloc(i + dscale + DEC_DIGITS + 2); |
7328 | 0 | cp = str; |
7329 | | |
7330 | | /* |
7331 | | * Output a dash for negative values |
7332 | | */ |
7333 | 0 | if (var->sign == NUMERIC_NEG) |
7334 | 0 | *cp++ = '-'; |
7335 | | |
7336 | | /* |
7337 | | * Output all digits before the decimal point |
7338 | | */ |
7339 | 0 | if (var->weight < 0) |
7340 | 0 | { |
7341 | 0 | d = var->weight + 1; |
7342 | 0 | *cp++ = '0'; |
7343 | 0 | } |
7344 | 0 | else |
7345 | 0 | { |
7346 | 0 | for (d = 0; d <= var->weight; d++) |
7347 | 0 | { |
7348 | 0 | dig = (d < var->ndigits) ? var->digits[d] : 0; |
7349 | | /* In the first digit, suppress extra leading decimal zeroes */ |
7350 | 0 | #if DEC_DIGITS == 4 |
7351 | 0 | { |
7352 | 0 | bool putit = (d > 0); |
7353 | |
|
7354 | 0 | d1 = dig / 1000; |
7355 | 0 | dig -= d1 * 1000; |
7356 | 0 | putit |= (d1 > 0); |
7357 | 0 | if (putit) |
7358 | 0 | *cp++ = d1 + '0'; |
7359 | 0 | d1 = dig / 100; |
7360 | 0 | dig -= d1 * 100; |
7361 | 0 | putit |= (d1 > 0); |
7362 | 0 | if (putit) |
7363 | 0 | *cp++ = d1 + '0'; |
7364 | 0 | d1 = dig / 10; |
7365 | 0 | dig -= d1 * 10; |
7366 | 0 | putit |= (d1 > 0); |
7367 | 0 | if (putit) |
7368 | 0 | *cp++ = d1 + '0'; |
7369 | 0 | *cp++ = dig + '0'; |
7370 | 0 | } |
7371 | | #elif DEC_DIGITS == 2 |
7372 | | d1 = dig / 10; |
7373 | | dig -= d1 * 10; |
7374 | | if (d1 > 0 || d > 0) |
7375 | | *cp++ = d1 + '0'; |
7376 | | *cp++ = dig + '0'; |
7377 | | #elif DEC_DIGITS == 1 |
7378 | | *cp++ = dig + '0'; |
7379 | | #else |
7380 | | #error unsupported NBASE |
7381 | | #endif |
7382 | 0 | } |
7383 | 0 | } |
7384 | | |
7385 | | /* |
7386 | | * If requested, output a decimal point and all the digits that follow it. |
7387 | | * We initially put out a multiple of DEC_DIGITS digits, then truncate if |
7388 | | * needed. |
7389 | | */ |
7390 | 0 | if (dscale > 0) |
7391 | 0 | { |
7392 | 0 | *cp++ = '.'; |
7393 | 0 | endcp = cp + dscale; |
7394 | 0 | for (i = 0; i < dscale; d++, i += DEC_DIGITS) |
7395 | 0 | { |
7396 | 0 | dig = (d >= 0 && d < var->ndigits) ? var->digits[d] : 0; |
7397 | 0 | #if DEC_DIGITS == 4 |
7398 | 0 | d1 = dig / 1000; |
7399 | 0 | dig -= d1 * 1000; |
7400 | 0 | *cp++ = d1 + '0'; |
7401 | 0 | d1 = dig / 100; |
7402 | 0 | dig -= d1 * 100; |
7403 | 0 | *cp++ = d1 + '0'; |
7404 | 0 | d1 = dig / 10; |
7405 | 0 | dig -= d1 * 10; |
7406 | 0 | *cp++ = d1 + '0'; |
7407 | 0 | *cp++ = dig + '0'; |
7408 | | #elif DEC_DIGITS == 2 |
7409 | | d1 = dig / 10; |
7410 | | dig -= d1 * 10; |
7411 | | *cp++ = d1 + '0'; |
7412 | | *cp++ = dig + '0'; |
7413 | | #elif DEC_DIGITS == 1 |
7414 | | *cp++ = dig + '0'; |
7415 | | #else |
7416 | | #error unsupported NBASE |
7417 | | #endif |
7418 | 0 | } |
7419 | 0 | cp = endcp; |
7420 | 0 | } |
7421 | | |
7422 | | /* |
7423 | | * terminate the string and return it |
7424 | | */ |
7425 | 0 | *cp = '\0'; |
7426 | 0 | return str; |
7427 | 0 | } |
7428 | | |
7429 | | /* |
7430 | | * get_str_from_var_sci() - |
7431 | | * |
7432 | | * Convert a var to a normalised scientific notation text representation. |
7433 | | * This function does the heavy lifting for numeric_out_sci(). |
7434 | | * |
7435 | | * This notation has the general form a * 10^b, where a is known as the |
7436 | | * "significand" and b is known as the "exponent". |
7437 | | * |
7438 | | * Because we can't do superscript in ASCII (and because we want to copy |
7439 | | * printf's behaviour) we display the exponent using E notation, with a |
7440 | | * minimum of two exponent digits. |
7441 | | * |
7442 | | * For example, the value 1234 could be output as 1.2e+03. |
7443 | | * |
7444 | | * We assume that the exponent can fit into an int32. |
7445 | | * |
7446 | | * rscale is the number of decimal digits desired after the decimal point in |
7447 | | * the output, negative values will be treated as meaning zero. |
7448 | | * |
7449 | | * Returns a palloc'd string. |
7450 | | */ |
7451 | | static char * |
7452 | | get_str_from_var_sci(const NumericVar *var, int rscale) |
7453 | 0 | { |
7454 | 0 | int32 exponent; |
7455 | 0 | NumericVar tmp_var; |
7456 | 0 | size_t len; |
7457 | 0 | char *str; |
7458 | 0 | char *sig_out; |
7459 | |
|
7460 | 0 | if (rscale < 0) |
7461 | 0 | rscale = 0; |
7462 | | |
7463 | | /* |
7464 | | * Determine the exponent of this number in normalised form. |
7465 | | * |
7466 | | * This is the exponent required to represent the number with only one |
7467 | | * significant digit before the decimal place. |
7468 | | */ |
7469 | 0 | if (var->ndigits > 0) |
7470 | 0 | { |
7471 | 0 | exponent = (var->weight + 1) * DEC_DIGITS; |
7472 | | |
7473 | | /* |
7474 | | * Compensate for leading decimal zeroes in the first numeric digit by |
7475 | | * decrementing the exponent. |
7476 | | */ |
7477 | 0 | exponent -= DEC_DIGITS - (int) log10(var->digits[0]); |
7478 | 0 | } |
7479 | 0 | else |
7480 | 0 | { |
7481 | | /* |
7482 | | * If var has no digits, then it must be zero. |
7483 | | * |
7484 | | * Zero doesn't technically have a meaningful exponent in normalised |
7485 | | * notation, but we just display the exponent as zero for consistency |
7486 | | * of output. |
7487 | | */ |
7488 | 0 | exponent = 0; |
7489 | 0 | } |
7490 | | |
7491 | | /* |
7492 | | * Divide var by 10^exponent to get the significand, rounding to rscale |
7493 | | * decimal digits in the process. |
7494 | | */ |
7495 | 0 | init_var(&tmp_var); |
7496 | |
|
7497 | 0 | power_ten_int(exponent, &tmp_var); |
7498 | 0 | div_var(var, &tmp_var, &tmp_var, rscale, true, true); |
7499 | 0 | sig_out = get_str_from_var(&tmp_var); |
7500 | |
|
7501 | 0 | free_var(&tmp_var); |
7502 | | |
7503 | | /* |
7504 | | * Allocate space for the result. |
7505 | | * |
7506 | | * In addition to the significand, we need room for the exponent |
7507 | | * decoration ("e"), the sign of the exponent, up to 10 digits for the |
7508 | | * exponent itself, and of course the null terminator. |
7509 | | */ |
7510 | 0 | len = strlen(sig_out) + 13; |
7511 | 0 | str = palloc(len); |
7512 | 0 | snprintf(str, len, "%se%+03d", sig_out, exponent); |
7513 | |
|
7514 | 0 | pfree(sig_out); |
7515 | |
|
7516 | 0 | return str; |
7517 | 0 | } |
7518 | | |
7519 | | |
7520 | | /* |
7521 | | * numericvar_serialize - serialize NumericVar to binary format |
7522 | | * |
7523 | | * At variable level, no checks are performed on the weight or dscale, allowing |
7524 | | * us to pass around intermediate values with higher precision than supported |
7525 | | * by the numeric type. Note: this is incompatible with numeric_send/recv(), |
7526 | | * which use 16-bit integers for these fields. |
7527 | | */ |
7528 | | static void |
7529 | | numericvar_serialize(StringInfo buf, const NumericVar *var) |
7530 | 0 | { |
7531 | 0 | int i; |
7532 | |
|
7533 | 0 | pq_sendint32(buf, var->ndigits); |
7534 | 0 | pq_sendint32(buf, var->weight); |
7535 | 0 | pq_sendint32(buf, var->sign); |
7536 | 0 | pq_sendint32(buf, var->dscale); |
7537 | 0 | for (i = 0; i < var->ndigits; i++) |
7538 | 0 | pq_sendint16(buf, var->digits[i]); |
7539 | 0 | } |
7540 | | |
7541 | | /* |
7542 | | * numericvar_deserialize - deserialize binary format to NumericVar |
7543 | | */ |
7544 | | static void |
7545 | | numericvar_deserialize(StringInfo buf, NumericVar *var) |
7546 | 0 | { |
7547 | 0 | int len, |
7548 | 0 | i; |
7549 | |
|
7550 | 0 | len = pq_getmsgint(buf, sizeof(int32)); |
7551 | |
|
7552 | 0 | alloc_var(var, len); /* sets var->ndigits */ |
7553 | |
|
7554 | 0 | var->weight = pq_getmsgint(buf, sizeof(int32)); |
7555 | 0 | var->sign = pq_getmsgint(buf, sizeof(int32)); |
7556 | 0 | var->dscale = pq_getmsgint(buf, sizeof(int32)); |
7557 | 0 | for (i = 0; i < len; i++) |
7558 | 0 | var->digits[i] = pq_getmsgint(buf, sizeof(int16)); |
7559 | 0 | } |
7560 | | |
7561 | | |
7562 | | /* |
7563 | | * duplicate_numeric() - copy a packed-format Numeric |
7564 | | * |
7565 | | * This will handle NaN and Infinity cases. |
7566 | | */ |
7567 | | static Numeric |
7568 | | duplicate_numeric(Numeric num) |
7569 | 0 | { |
7570 | 0 | Numeric res; |
7571 | |
|
7572 | 0 | res = (Numeric) palloc(VARSIZE(num)); |
7573 | 0 | memcpy(res, num, VARSIZE(num)); |
7574 | 0 | return res; |
7575 | 0 | } |
7576 | | |
7577 | | /* |
7578 | | * make_result_safe() - |
7579 | | * |
7580 | | * Create the packed db numeric format in palloc()'d memory from |
7581 | | * a variable. This will handle NaN and Infinity cases. |
7582 | | */ |
7583 | | static Numeric |
7584 | | make_result_safe(const NumericVar *var, Node *escontext) |
7585 | 0 | { |
7586 | 0 | Numeric result; |
7587 | 0 | NumericDigit *digits = var->digits; |
7588 | 0 | int weight = var->weight; |
7589 | 0 | int sign = var->sign; |
7590 | 0 | int n; |
7591 | 0 | Size len; |
7592 | |
|
7593 | 0 | if ((sign & NUMERIC_SIGN_MASK) == NUMERIC_SPECIAL) |
7594 | 0 | { |
7595 | | /* |
7596 | | * Verify valid special value. This could be just an Assert, perhaps, |
7597 | | * but it seems worthwhile to expend a few cycles to ensure that we |
7598 | | * never write any nonzero reserved bits to disk. |
7599 | | */ |
7600 | 0 | if (!(sign == NUMERIC_NAN || |
7601 | 0 | sign == NUMERIC_PINF || |
7602 | 0 | sign == NUMERIC_NINF)) |
7603 | 0 | elog(ERROR, "invalid numeric sign value 0x%x", sign); |
7604 | | |
7605 | 0 | result = (Numeric) palloc(NUMERIC_HDRSZ_SHORT); |
7606 | |
|
7607 | 0 | SET_VARSIZE(result, NUMERIC_HDRSZ_SHORT); |
7608 | 0 | result->choice.n_header = sign; |
7609 | | /* the header word is all we need */ |
7610 | |
|
7611 | 0 | dump_numeric("make_result()", result); |
7612 | 0 | return result; |
7613 | 0 | } |
7614 | | |
7615 | 0 | n = var->ndigits; |
7616 | | |
7617 | | /* truncate leading zeroes */ |
7618 | 0 | while (n > 0 && *digits == 0) |
7619 | 0 | { |
7620 | 0 | digits++; |
7621 | 0 | weight--; |
7622 | 0 | n--; |
7623 | 0 | } |
7624 | | /* truncate trailing zeroes */ |
7625 | 0 | while (n > 0 && digits[n - 1] == 0) |
7626 | 0 | n--; |
7627 | | |
7628 | | /* If zero result, force to weight=0 and positive sign */ |
7629 | 0 | if (n == 0) |
7630 | 0 | { |
7631 | 0 | weight = 0; |
7632 | 0 | sign = NUMERIC_POS; |
7633 | 0 | } |
7634 | | |
7635 | | /* Build the result */ |
7636 | 0 | if (NUMERIC_CAN_BE_SHORT(var->dscale, weight)) |
7637 | 0 | { |
7638 | 0 | len = NUMERIC_HDRSZ_SHORT + n * sizeof(NumericDigit); |
7639 | 0 | result = (Numeric) palloc(len); |
7640 | 0 | SET_VARSIZE(result, len); |
7641 | 0 | result->choice.n_short.n_header = |
7642 | 0 | (sign == NUMERIC_NEG ? (NUMERIC_SHORT | NUMERIC_SHORT_SIGN_MASK) |
7643 | 0 | : NUMERIC_SHORT) |
7644 | 0 | | (var->dscale << NUMERIC_SHORT_DSCALE_SHIFT) |
7645 | 0 | | (weight < 0 ? NUMERIC_SHORT_WEIGHT_SIGN_MASK : 0) |
7646 | 0 | | (weight & NUMERIC_SHORT_WEIGHT_MASK); |
7647 | 0 | } |
7648 | 0 | else |
7649 | 0 | { |
7650 | 0 | len = NUMERIC_HDRSZ + n * sizeof(NumericDigit); |
7651 | 0 | result = (Numeric) palloc(len); |
7652 | 0 | SET_VARSIZE(result, len); |
7653 | 0 | result->choice.n_long.n_sign_dscale = |
7654 | 0 | sign | (var->dscale & NUMERIC_DSCALE_MASK); |
7655 | 0 | result->choice.n_long.n_weight = weight; |
7656 | 0 | } |
7657 | |
|
7658 | 0 | Assert(NUMERIC_NDIGITS(result) == n); |
7659 | 0 | if (n > 0) |
7660 | 0 | memcpy(NUMERIC_DIGITS(result), digits, n * sizeof(NumericDigit)); |
7661 | | |
7662 | | /* Check for overflow of int16 fields */ |
7663 | 0 | if (NUMERIC_WEIGHT(result) != weight || |
7664 | 0 | NUMERIC_DSCALE(result) != var->dscale) |
7665 | 0 | ereturn(escontext, NULL, |
7666 | 0 | (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), |
7667 | 0 | errmsg("value overflows numeric format"))); |
7668 | | |
7669 | 0 | dump_numeric("make_result()", result); |
7670 | 0 | return result; |
7671 | 0 | } |
7672 | | |
7673 | | |
7674 | | /* |
7675 | | * make_result() - |
7676 | | * |
7677 | | * An interface to make_result_safe() without "escontext" argument. |
7678 | | */ |
7679 | | static Numeric |
7680 | | make_result(const NumericVar *var) |
7681 | 0 | { |
7682 | 0 | return make_result_safe(var, NULL); |
7683 | 0 | } |
7684 | | |
7685 | | |
7686 | | /* |
7687 | | * apply_typmod() - |
7688 | | * |
7689 | | * Do bounds checking and rounding according to the specified typmod. |
7690 | | * Note that this is only applied to normal finite values. |
7691 | | * |
7692 | | * Returns true on success, false on failure (if escontext points to an |
7693 | | * ErrorSaveContext; otherwise errors are thrown). |
7694 | | */ |
7695 | | static bool |
7696 | | apply_typmod(NumericVar *var, int32 typmod, Node *escontext) |
7697 | 0 | { |
7698 | 0 | int precision; |
7699 | 0 | int scale; |
7700 | 0 | int maxdigits; |
7701 | 0 | int ddigits; |
7702 | 0 | int i; |
7703 | | |
7704 | | /* Do nothing if we have an invalid typmod */ |
7705 | 0 | if (!is_valid_numeric_typmod(typmod)) |
7706 | 0 | return true; |
7707 | | |
7708 | 0 | precision = numeric_typmod_precision(typmod); |
7709 | 0 | scale = numeric_typmod_scale(typmod); |
7710 | 0 | maxdigits = precision - scale; |
7711 | | |
7712 | | /* Round to target scale (and set var->dscale) */ |
7713 | 0 | round_var(var, scale); |
7714 | | |
7715 | | /* but don't allow var->dscale to be negative */ |
7716 | 0 | if (var->dscale < 0) |
7717 | 0 | var->dscale = 0; |
7718 | | |
7719 | | /* |
7720 | | * Check for overflow - note we can't do this before rounding, because |
7721 | | * rounding could raise the weight. Also note that the var's weight could |
7722 | | * be inflated by leading zeroes, which will be stripped before storage |
7723 | | * but perhaps might not have been yet. In any case, we must recognize a |
7724 | | * true zero, whose weight doesn't mean anything. |
7725 | | */ |
7726 | 0 | ddigits = (var->weight + 1) * DEC_DIGITS; |
7727 | 0 | if (ddigits > maxdigits) |
7728 | 0 | { |
7729 | | /* Determine true weight; and check for all-zero result */ |
7730 | 0 | for (i = 0; i < var->ndigits; i++) |
7731 | 0 | { |
7732 | 0 | NumericDigit dig = var->digits[i]; |
7733 | |
|
7734 | 0 | if (dig) |
7735 | 0 | { |
7736 | | /* Adjust for any high-order decimal zero digits */ |
7737 | 0 | #if DEC_DIGITS == 4 |
7738 | 0 | if (dig < 10) |
7739 | 0 | ddigits -= 3; |
7740 | 0 | else if (dig < 100) |
7741 | 0 | ddigits -= 2; |
7742 | 0 | else if (dig < 1000) |
7743 | 0 | ddigits -= 1; |
7744 | | #elif DEC_DIGITS == 2 |
7745 | | if (dig < 10) |
7746 | | ddigits -= 1; |
7747 | | #elif DEC_DIGITS == 1 |
7748 | | /* no adjustment */ |
7749 | | #else |
7750 | | #error unsupported NBASE |
7751 | | #endif |
7752 | 0 | if (ddigits > maxdigits) |
7753 | 0 | ereturn(escontext, false, |
7754 | 0 | (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), |
7755 | 0 | errmsg("numeric field overflow"), |
7756 | 0 | errdetail("A field with precision %d, scale %d must round to an absolute value less than %s%d.", |
7757 | 0 | precision, scale, |
7758 | | /* Display 10^0 as 1 */ |
7759 | 0 | maxdigits ? "10^" : "", |
7760 | 0 | maxdigits ? maxdigits : 1 |
7761 | 0 | ))); |
7762 | 0 | break; |
7763 | 0 | } |
7764 | 0 | ddigits -= DEC_DIGITS; |
7765 | 0 | } |
7766 | 0 | } |
7767 | | |
7768 | 0 | return true; |
7769 | 0 | } |
7770 | | |
7771 | | /* |
7772 | | * apply_typmod_special() - |
7773 | | * |
7774 | | * Do bounds checking according to the specified typmod, for an Inf or NaN. |
7775 | | * For convenience of most callers, the value is presented in packed form. |
7776 | | * |
7777 | | * Returns true on success, false on failure (if escontext points to an |
7778 | | * ErrorSaveContext; otherwise errors are thrown). |
7779 | | */ |
7780 | | static bool |
7781 | | apply_typmod_special(Numeric num, int32 typmod, Node *escontext) |
7782 | 0 | { |
7783 | 0 | int precision; |
7784 | 0 | int scale; |
7785 | |
|
7786 | 0 | Assert(NUMERIC_IS_SPECIAL(num)); /* caller error if not */ |
7787 | | |
7788 | | /* |
7789 | | * NaN is allowed regardless of the typmod; that's rather dubious perhaps, |
7790 | | * but it's a longstanding behavior. Inf is rejected if we have any |
7791 | | * typmod restriction, since an infinity shouldn't be claimed to fit in |
7792 | | * any finite number of digits. |
7793 | | */ |
7794 | 0 | if (NUMERIC_IS_NAN(num)) |
7795 | 0 | return true; |
7796 | | |
7797 | | /* Do nothing if we have a default typmod (-1) */ |
7798 | 0 | if (!is_valid_numeric_typmod(typmod)) |
7799 | 0 | return true; |
7800 | | |
7801 | 0 | precision = numeric_typmod_precision(typmod); |
7802 | 0 | scale = numeric_typmod_scale(typmod); |
7803 | |
|
7804 | 0 | ereturn(escontext, false, |
7805 | 0 | (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), |
7806 | 0 | errmsg("numeric field overflow"), |
7807 | 0 | errdetail("A field with precision %d, scale %d cannot hold an infinite value.", |
7808 | 0 | precision, scale))); |
7809 | 0 | } |
7810 | | |
7811 | | |
7812 | | /* |
7813 | | * Convert numeric to int8, rounding if needed. |
7814 | | * |
7815 | | * If overflow, return false (no error is raised). Return true if okay. |
7816 | | */ |
7817 | | static bool |
7818 | | numericvar_to_int64(const NumericVar *var, int64 *result) |
7819 | 0 | { |
7820 | 0 | NumericDigit *digits; |
7821 | 0 | int ndigits; |
7822 | 0 | int weight; |
7823 | 0 | int i; |
7824 | 0 | int64 val; |
7825 | 0 | bool neg; |
7826 | 0 | NumericVar rounded; |
7827 | | |
7828 | | /* Round to nearest integer */ |
7829 | 0 | init_var(&rounded); |
7830 | 0 | set_var_from_var(var, &rounded); |
7831 | 0 | round_var(&rounded, 0); |
7832 | | |
7833 | | /* Check for zero input */ |
7834 | 0 | strip_var(&rounded); |
7835 | 0 | ndigits = rounded.ndigits; |
7836 | 0 | if (ndigits == 0) |
7837 | 0 | { |
7838 | 0 | *result = 0; |
7839 | 0 | free_var(&rounded); |
7840 | 0 | return true; |
7841 | 0 | } |
7842 | | |
7843 | | /* |
7844 | | * For input like 10000000000, we must treat stripped digits as real. So |
7845 | | * the loop assumes there are weight+1 digits before the decimal point. |
7846 | | */ |
7847 | 0 | weight = rounded.weight; |
7848 | 0 | Assert(weight >= 0 && ndigits <= weight + 1); |
7849 | | |
7850 | | /* |
7851 | | * Construct the result. To avoid issues with converting a value |
7852 | | * corresponding to INT64_MIN (which can't be represented as a positive 64 |
7853 | | * bit two's complement integer), accumulate value as a negative number. |
7854 | | */ |
7855 | 0 | digits = rounded.digits; |
7856 | 0 | neg = (rounded.sign == NUMERIC_NEG); |
7857 | 0 | val = -digits[0]; |
7858 | 0 | for (i = 1; i <= weight; i++) |
7859 | 0 | { |
7860 | 0 | if (unlikely(pg_mul_s64_overflow(val, NBASE, &val))) |
7861 | 0 | { |
7862 | 0 | free_var(&rounded); |
7863 | 0 | return false; |
7864 | 0 | } |
7865 | | |
7866 | 0 | if (i < ndigits) |
7867 | 0 | { |
7868 | 0 | if (unlikely(pg_sub_s64_overflow(val, digits[i], &val))) |
7869 | 0 | { |
7870 | 0 | free_var(&rounded); |
7871 | 0 | return false; |
7872 | 0 | } |
7873 | 0 | } |
7874 | 0 | } |
7875 | | |
7876 | 0 | free_var(&rounded); |
7877 | |
|
7878 | 0 | if (!neg) |
7879 | 0 | { |
7880 | 0 | if (unlikely(pg_neg_s64_overflow(val, &val))) |
7881 | 0 | return false; |
7882 | 0 | } |
7883 | 0 | *result = val; |
7884 | |
|
7885 | 0 | return true; |
7886 | 0 | } |
7887 | | |
7888 | | /* |
7889 | | * Convert int8 value to numeric. |
7890 | | */ |
7891 | | static void |
7892 | | int64_to_numericvar(int64 val, NumericVar *var) |
7893 | 0 | { |
7894 | 0 | uint64 uval, |
7895 | 0 | newuval; |
7896 | 0 | NumericDigit *ptr; |
7897 | 0 | int ndigits; |
7898 | | |
7899 | | /* int64 can require at most 19 decimal digits; add one for safety */ |
7900 | 0 | alloc_var(var, 20 / DEC_DIGITS); |
7901 | 0 | if (val < 0) |
7902 | 0 | { |
7903 | 0 | var->sign = NUMERIC_NEG; |
7904 | 0 | uval = pg_abs_s64(val); |
7905 | 0 | } |
7906 | 0 | else |
7907 | 0 | { |
7908 | 0 | var->sign = NUMERIC_POS; |
7909 | 0 | uval = val; |
7910 | 0 | } |
7911 | 0 | var->dscale = 0; |
7912 | 0 | if (val == 0) |
7913 | 0 | { |
7914 | 0 | var->ndigits = 0; |
7915 | 0 | var->weight = 0; |
7916 | 0 | return; |
7917 | 0 | } |
7918 | 0 | ptr = var->digits + var->ndigits; |
7919 | 0 | ndigits = 0; |
7920 | 0 | do |
7921 | 0 | { |
7922 | 0 | ptr--; |
7923 | 0 | ndigits++; |
7924 | 0 | newuval = uval / NBASE; |
7925 | 0 | *ptr = uval - newuval * NBASE; |
7926 | 0 | uval = newuval; |
7927 | 0 | } while (uval); |
7928 | 0 | var->digits = ptr; |
7929 | 0 | var->ndigits = ndigits; |
7930 | 0 | var->weight = ndigits - 1; |
7931 | 0 | } |
7932 | | |
7933 | | /* |
7934 | | * Convert numeric to uint64, rounding if needed. |
7935 | | * |
7936 | | * If overflow, return false (no error is raised). Return true if okay. |
7937 | | */ |
7938 | | static bool |
7939 | | numericvar_to_uint64(const NumericVar *var, uint64 *result) |
7940 | 0 | { |
7941 | 0 | NumericDigit *digits; |
7942 | 0 | int ndigits; |
7943 | 0 | int weight; |
7944 | 0 | int i; |
7945 | 0 | uint64 val; |
7946 | 0 | NumericVar rounded; |
7947 | | |
7948 | | /* Round to nearest integer */ |
7949 | 0 | init_var(&rounded); |
7950 | 0 | set_var_from_var(var, &rounded); |
7951 | 0 | round_var(&rounded, 0); |
7952 | | |
7953 | | /* Check for zero input */ |
7954 | 0 | strip_var(&rounded); |
7955 | 0 | ndigits = rounded.ndigits; |
7956 | 0 | if (ndigits == 0) |
7957 | 0 | { |
7958 | 0 | *result = 0; |
7959 | 0 | free_var(&rounded); |
7960 | 0 | return true; |
7961 | 0 | } |
7962 | | |
7963 | | /* Check for negative input */ |
7964 | 0 | if (rounded.sign == NUMERIC_NEG) |
7965 | 0 | { |
7966 | 0 | free_var(&rounded); |
7967 | 0 | return false; |
7968 | 0 | } |
7969 | | |
7970 | | /* |
7971 | | * For input like 10000000000, we must treat stripped digits as real. So |
7972 | | * the loop assumes there are weight+1 digits before the decimal point. |
7973 | | */ |
7974 | 0 | weight = rounded.weight; |
7975 | 0 | Assert(weight >= 0 && ndigits <= weight + 1); |
7976 | | |
7977 | | /* Construct the result */ |
7978 | 0 | digits = rounded.digits; |
7979 | 0 | val = digits[0]; |
7980 | 0 | for (i = 1; i <= weight; i++) |
7981 | 0 | { |
7982 | 0 | if (unlikely(pg_mul_u64_overflow(val, NBASE, &val))) |
7983 | 0 | { |
7984 | 0 | free_var(&rounded); |
7985 | 0 | return false; |
7986 | 0 | } |
7987 | | |
7988 | 0 | if (i < ndigits) |
7989 | 0 | { |
7990 | 0 | if (unlikely(pg_add_u64_overflow(val, digits[i], &val))) |
7991 | 0 | { |
7992 | 0 | free_var(&rounded); |
7993 | 0 | return false; |
7994 | 0 | } |
7995 | 0 | } |
7996 | 0 | } |
7997 | | |
7998 | 0 | free_var(&rounded); |
7999 | |
|
8000 | 0 | *result = val; |
8001 | |
|
8002 | 0 | return true; |
8003 | 0 | } |
8004 | | |
8005 | | /* |
8006 | | * Convert 128 bit integer to numeric. |
8007 | | */ |
8008 | | static void |
8009 | | int128_to_numericvar(INT128 val, NumericVar *var) |
8010 | 0 | { |
8011 | 0 | int sign; |
8012 | 0 | NumericDigit *ptr; |
8013 | 0 | int ndigits; |
8014 | 0 | int32 dig; |
8015 | | |
8016 | | /* int128 can require at most 39 decimal digits; add one for safety */ |
8017 | 0 | alloc_var(var, 40 / DEC_DIGITS); |
8018 | 0 | sign = int128_sign(val); |
8019 | 0 | var->sign = sign < 0 ? NUMERIC_NEG : NUMERIC_POS; |
8020 | 0 | var->dscale = 0; |
8021 | 0 | if (sign == 0) |
8022 | 0 | { |
8023 | 0 | var->ndigits = 0; |
8024 | 0 | var->weight = 0; |
8025 | 0 | return; |
8026 | 0 | } |
8027 | 0 | ptr = var->digits + var->ndigits; |
8028 | 0 | ndigits = 0; |
8029 | 0 | do |
8030 | 0 | { |
8031 | 0 | ptr--; |
8032 | 0 | ndigits++; |
8033 | 0 | int128_div_mod_int32(&val, NBASE, &dig); |
8034 | 0 | *ptr = (NumericDigit) abs(dig); |
8035 | 0 | } while (!int128_is_zero(val)); |
8036 | 0 | var->digits = ptr; |
8037 | 0 | var->ndigits = ndigits; |
8038 | 0 | var->weight = ndigits - 1; |
8039 | 0 | } |
8040 | | |
8041 | | /* |
8042 | | * Convert a NumericVar to float8; if out of range, return +/- HUGE_VAL |
8043 | | */ |
8044 | | static double |
8045 | | numericvar_to_double_no_overflow(const NumericVar *var) |
8046 | 0 | { |
8047 | 0 | char *tmp; |
8048 | 0 | double val; |
8049 | 0 | char *endptr; |
8050 | |
|
8051 | 0 | tmp = get_str_from_var(var); |
8052 | | |
8053 | | /* unlike float8in, we ignore ERANGE from strtod */ |
8054 | 0 | val = strtod(tmp, &endptr); |
8055 | 0 | if (*endptr != '\0') |
8056 | 0 | { |
8057 | | /* shouldn't happen ... */ |
8058 | 0 | ereport(ERROR, |
8059 | 0 | (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), |
8060 | 0 | errmsg("invalid input syntax for type %s: \"%s\"", |
8061 | 0 | "double precision", tmp))); |
8062 | 0 | } |
8063 | | |
8064 | 0 | pfree(tmp); |
8065 | |
|
8066 | 0 | return val; |
8067 | 0 | } |
8068 | | |
8069 | | |
8070 | | /* |
8071 | | * cmp_var() - |
8072 | | * |
8073 | | * Compare two values on variable level. We assume zeroes have been |
8074 | | * truncated to no digits. |
8075 | | */ |
8076 | | static int |
8077 | | cmp_var(const NumericVar *var1, const NumericVar *var2) |
8078 | 0 | { |
8079 | 0 | return cmp_var_common(var1->digits, var1->ndigits, |
8080 | 0 | var1->weight, var1->sign, |
8081 | 0 | var2->digits, var2->ndigits, |
8082 | 0 | var2->weight, var2->sign); |
8083 | 0 | } |
8084 | | |
8085 | | /* |
8086 | | * cmp_var_common() - |
8087 | | * |
8088 | | * Main routine of cmp_var(). This function can be used by both |
8089 | | * NumericVar and Numeric. |
8090 | | */ |
8091 | | static int |
8092 | | cmp_var_common(const NumericDigit *var1digits, int var1ndigits, |
8093 | | int var1weight, int var1sign, |
8094 | | const NumericDigit *var2digits, int var2ndigits, |
8095 | | int var2weight, int var2sign) |
8096 | 0 | { |
8097 | 0 | if (var1ndigits == 0) |
8098 | 0 | { |
8099 | 0 | if (var2ndigits == 0) |
8100 | 0 | return 0; |
8101 | 0 | if (var2sign == NUMERIC_NEG) |
8102 | 0 | return 1; |
8103 | 0 | return -1; |
8104 | 0 | } |
8105 | 0 | if (var2ndigits == 0) |
8106 | 0 | { |
8107 | 0 | if (var1sign == NUMERIC_POS) |
8108 | 0 | return 1; |
8109 | 0 | return -1; |
8110 | 0 | } |
8111 | | |
8112 | 0 | if (var1sign == NUMERIC_POS) |
8113 | 0 | { |
8114 | 0 | if (var2sign == NUMERIC_NEG) |
8115 | 0 | return 1; |
8116 | 0 | return cmp_abs_common(var1digits, var1ndigits, var1weight, |
8117 | 0 | var2digits, var2ndigits, var2weight); |
8118 | 0 | } |
8119 | | |
8120 | 0 | if (var2sign == NUMERIC_POS) |
8121 | 0 | return -1; |
8122 | | |
8123 | 0 | return cmp_abs_common(var2digits, var2ndigits, var2weight, |
8124 | 0 | var1digits, var1ndigits, var1weight); |
8125 | 0 | } |
8126 | | |
8127 | | |
8128 | | /* |
8129 | | * add_var() - |
8130 | | * |
8131 | | * Full version of add functionality on variable level (handling signs). |
8132 | | * result might point to one of the operands too without danger. |
8133 | | */ |
8134 | | static void |
8135 | | add_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result) |
8136 | 0 | { |
8137 | | /* |
8138 | | * Decide on the signs of the two variables what to do |
8139 | | */ |
8140 | 0 | if (var1->sign == NUMERIC_POS) |
8141 | 0 | { |
8142 | 0 | if (var2->sign == NUMERIC_POS) |
8143 | 0 | { |
8144 | | /* |
8145 | | * Both are positive result = +(ABS(var1) + ABS(var2)) |
8146 | | */ |
8147 | 0 | add_abs(var1, var2, result); |
8148 | 0 | result->sign = NUMERIC_POS; |
8149 | 0 | } |
8150 | 0 | else |
8151 | 0 | { |
8152 | | /* |
8153 | | * var1 is positive, var2 is negative Must compare absolute values |
8154 | | */ |
8155 | 0 | switch (cmp_abs(var1, var2)) |
8156 | 0 | { |
8157 | 0 | case 0: |
8158 | | /* ---------- |
8159 | | * ABS(var1) == ABS(var2) |
8160 | | * result = ZERO |
8161 | | * ---------- |
8162 | | */ |
8163 | 0 | zero_var(result); |
8164 | 0 | result->dscale = Max(var1->dscale, var2->dscale); |
8165 | 0 | break; |
8166 | | |
8167 | 0 | case 1: |
8168 | | /* ---------- |
8169 | | * ABS(var1) > ABS(var2) |
8170 | | * result = +(ABS(var1) - ABS(var2)) |
8171 | | * ---------- |
8172 | | */ |
8173 | 0 | sub_abs(var1, var2, result); |
8174 | 0 | result->sign = NUMERIC_POS; |
8175 | 0 | break; |
8176 | | |
8177 | 0 | case -1: |
8178 | | /* ---------- |
8179 | | * ABS(var1) < ABS(var2) |
8180 | | * result = -(ABS(var2) - ABS(var1)) |
8181 | | * ---------- |
8182 | | */ |
8183 | 0 | sub_abs(var2, var1, result); |
8184 | 0 | result->sign = NUMERIC_NEG; |
8185 | 0 | break; |
8186 | 0 | } |
8187 | 0 | } |
8188 | 0 | } |
8189 | 0 | else |
8190 | 0 | { |
8191 | 0 | if (var2->sign == NUMERIC_POS) |
8192 | 0 | { |
8193 | | /* ---------- |
8194 | | * var1 is negative, var2 is positive |
8195 | | * Must compare absolute values |
8196 | | * ---------- |
8197 | | */ |
8198 | 0 | switch (cmp_abs(var1, var2)) |
8199 | 0 | { |
8200 | 0 | case 0: |
8201 | | /* ---------- |
8202 | | * ABS(var1) == ABS(var2) |
8203 | | * result = ZERO |
8204 | | * ---------- |
8205 | | */ |
8206 | 0 | zero_var(result); |
8207 | 0 | result->dscale = Max(var1->dscale, var2->dscale); |
8208 | 0 | break; |
8209 | | |
8210 | 0 | case 1: |
8211 | | /* ---------- |
8212 | | * ABS(var1) > ABS(var2) |
8213 | | * result = -(ABS(var1) - ABS(var2)) |
8214 | | * ---------- |
8215 | | */ |
8216 | 0 | sub_abs(var1, var2, result); |
8217 | 0 | result->sign = NUMERIC_NEG; |
8218 | 0 | break; |
8219 | | |
8220 | 0 | case -1: |
8221 | | /* ---------- |
8222 | | * ABS(var1) < ABS(var2) |
8223 | | * result = +(ABS(var2) - ABS(var1)) |
8224 | | * ---------- |
8225 | | */ |
8226 | 0 | sub_abs(var2, var1, result); |
8227 | 0 | result->sign = NUMERIC_POS; |
8228 | 0 | break; |
8229 | 0 | } |
8230 | 0 | } |
8231 | 0 | else |
8232 | 0 | { |
8233 | | /* ---------- |
8234 | | * Both are negative |
8235 | | * result = -(ABS(var1) + ABS(var2)) |
8236 | | * ---------- |
8237 | | */ |
8238 | 0 | add_abs(var1, var2, result); |
8239 | 0 | result->sign = NUMERIC_NEG; |
8240 | 0 | } |
8241 | 0 | } |
8242 | 0 | } |
8243 | | |
8244 | | |
8245 | | /* |
8246 | | * sub_var() - |
8247 | | * |
8248 | | * Full version of sub functionality on variable level (handling signs). |
8249 | | * result might point to one of the operands too without danger. |
8250 | | */ |
8251 | | static void |
8252 | | sub_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result) |
8253 | 0 | { |
8254 | | /* |
8255 | | * Decide on the signs of the two variables what to do |
8256 | | */ |
8257 | 0 | if (var1->sign == NUMERIC_POS) |
8258 | 0 | { |
8259 | 0 | if (var2->sign == NUMERIC_NEG) |
8260 | 0 | { |
8261 | | /* ---------- |
8262 | | * var1 is positive, var2 is negative |
8263 | | * result = +(ABS(var1) + ABS(var2)) |
8264 | | * ---------- |
8265 | | */ |
8266 | 0 | add_abs(var1, var2, result); |
8267 | 0 | result->sign = NUMERIC_POS; |
8268 | 0 | } |
8269 | 0 | else |
8270 | 0 | { |
8271 | | /* ---------- |
8272 | | * Both are positive |
8273 | | * Must compare absolute values |
8274 | | * ---------- |
8275 | | */ |
8276 | 0 | switch (cmp_abs(var1, var2)) |
8277 | 0 | { |
8278 | 0 | case 0: |
8279 | | /* ---------- |
8280 | | * ABS(var1) == ABS(var2) |
8281 | | * result = ZERO |
8282 | | * ---------- |
8283 | | */ |
8284 | 0 | zero_var(result); |
8285 | 0 | result->dscale = Max(var1->dscale, var2->dscale); |
8286 | 0 | break; |
8287 | | |
8288 | 0 | case 1: |
8289 | | /* ---------- |
8290 | | * ABS(var1) > ABS(var2) |
8291 | | * result = +(ABS(var1) - ABS(var2)) |
8292 | | * ---------- |
8293 | | */ |
8294 | 0 | sub_abs(var1, var2, result); |
8295 | 0 | result->sign = NUMERIC_POS; |
8296 | 0 | break; |
8297 | | |
8298 | 0 | case -1: |
8299 | | /* ---------- |
8300 | | * ABS(var1) < ABS(var2) |
8301 | | * result = -(ABS(var2) - ABS(var1)) |
8302 | | * ---------- |
8303 | | */ |
8304 | 0 | sub_abs(var2, var1, result); |
8305 | 0 | result->sign = NUMERIC_NEG; |
8306 | 0 | break; |
8307 | 0 | } |
8308 | 0 | } |
8309 | 0 | } |
8310 | 0 | else |
8311 | 0 | { |
8312 | 0 | if (var2->sign == NUMERIC_NEG) |
8313 | 0 | { |
8314 | | /* ---------- |
8315 | | * Both are negative |
8316 | | * Must compare absolute values |
8317 | | * ---------- |
8318 | | */ |
8319 | 0 | switch (cmp_abs(var1, var2)) |
8320 | 0 | { |
8321 | 0 | case 0: |
8322 | | /* ---------- |
8323 | | * ABS(var1) == ABS(var2) |
8324 | | * result = ZERO |
8325 | | * ---------- |
8326 | | */ |
8327 | 0 | zero_var(result); |
8328 | 0 | result->dscale = Max(var1->dscale, var2->dscale); |
8329 | 0 | break; |
8330 | | |
8331 | 0 | case 1: |
8332 | | /* ---------- |
8333 | | * ABS(var1) > ABS(var2) |
8334 | | * result = -(ABS(var1) - ABS(var2)) |
8335 | | * ---------- |
8336 | | */ |
8337 | 0 | sub_abs(var1, var2, result); |
8338 | 0 | result->sign = NUMERIC_NEG; |
8339 | 0 | break; |
8340 | | |
8341 | 0 | case -1: |
8342 | | /* ---------- |
8343 | | * ABS(var1) < ABS(var2) |
8344 | | * result = +(ABS(var2) - ABS(var1)) |
8345 | | * ---------- |
8346 | | */ |
8347 | 0 | sub_abs(var2, var1, result); |
8348 | 0 | result->sign = NUMERIC_POS; |
8349 | 0 | break; |
8350 | 0 | } |
8351 | 0 | } |
8352 | 0 | else |
8353 | 0 | { |
8354 | | /* ---------- |
8355 | | * var1 is negative, var2 is positive |
8356 | | * result = -(ABS(var1) + ABS(var2)) |
8357 | | * ---------- |
8358 | | */ |
8359 | 0 | add_abs(var1, var2, result); |
8360 | 0 | result->sign = NUMERIC_NEG; |
8361 | 0 | } |
8362 | 0 | } |
8363 | 0 | } |
8364 | | |
8365 | | |
8366 | | /* |
8367 | | * mul_var() - |
8368 | | * |
8369 | | * Multiplication on variable level. Product of var1 * var2 is stored |
8370 | | * in result. Result is rounded to no more than rscale fractional digits. |
8371 | | */ |
8372 | | static void |
8373 | | mul_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result, |
8374 | | int rscale) |
8375 | 0 | { |
8376 | 0 | int res_ndigits; |
8377 | 0 | int res_ndigitpairs; |
8378 | 0 | int res_sign; |
8379 | 0 | int res_weight; |
8380 | 0 | int pair_offset; |
8381 | 0 | int maxdigits; |
8382 | 0 | int maxdigitpairs; |
8383 | 0 | uint64 *dig, |
8384 | 0 | *dig_i1_off; |
8385 | 0 | uint64 maxdig; |
8386 | 0 | uint64 carry; |
8387 | 0 | uint64 newdig; |
8388 | 0 | int var1ndigits; |
8389 | 0 | int var2ndigits; |
8390 | 0 | int var1ndigitpairs; |
8391 | 0 | int var2ndigitpairs; |
8392 | 0 | NumericDigit *var1digits; |
8393 | 0 | NumericDigit *var2digits; |
8394 | 0 | uint32 var1digitpair; |
8395 | 0 | uint32 *var2digitpairs; |
8396 | 0 | NumericDigit *res_digits; |
8397 | 0 | int i, |
8398 | 0 | i1, |
8399 | 0 | i2, |
8400 | 0 | i2limit; |
8401 | | |
8402 | | /* |
8403 | | * Arrange for var1 to be the shorter of the two numbers. This improves |
8404 | | * performance because the inner multiplication loop is much simpler than |
8405 | | * the outer loop, so it's better to have a smaller number of iterations |
8406 | | * of the outer loop. This also reduces the number of times that the |
8407 | | * accumulator array needs to be normalized. |
8408 | | */ |
8409 | 0 | if (var1->ndigits > var2->ndigits) |
8410 | 0 | { |
8411 | 0 | const NumericVar *tmp = var1; |
8412 | |
|
8413 | 0 | var1 = var2; |
8414 | 0 | var2 = tmp; |
8415 | 0 | } |
8416 | | |
8417 | | /* copy these values into local vars for speed in inner loop */ |
8418 | 0 | var1ndigits = var1->ndigits; |
8419 | 0 | var2ndigits = var2->ndigits; |
8420 | 0 | var1digits = var1->digits; |
8421 | 0 | var2digits = var2->digits; |
8422 | |
|
8423 | 0 | if (var1ndigits == 0) |
8424 | 0 | { |
8425 | | /* one or both inputs is zero; so is result */ |
8426 | 0 | zero_var(result); |
8427 | 0 | result->dscale = rscale; |
8428 | 0 | return; |
8429 | 0 | } |
8430 | | |
8431 | | /* |
8432 | | * If var1 has 1-6 digits and the exact result was requested, delegate to |
8433 | | * mul_var_short() which uses a faster direct multiplication algorithm. |
8434 | | */ |
8435 | 0 | if (var1ndigits <= 6 && rscale == var1->dscale + var2->dscale) |
8436 | 0 | { |
8437 | 0 | mul_var_short(var1, var2, result); |
8438 | 0 | return; |
8439 | 0 | } |
8440 | | |
8441 | | /* Determine result sign */ |
8442 | 0 | if (var1->sign == var2->sign) |
8443 | 0 | res_sign = NUMERIC_POS; |
8444 | 0 | else |
8445 | 0 | res_sign = NUMERIC_NEG; |
8446 | | |
8447 | | /* |
8448 | | * Determine the number of result digits to compute and the (maximum |
8449 | | * possible) result weight. If the exact result would have more than |
8450 | | * rscale fractional digits, truncate the computation with |
8451 | | * MUL_GUARD_DIGITS guard digits, i.e., ignore input digits that would |
8452 | | * only contribute to the right of that. (This will give the exact |
8453 | | * rounded-to-rscale answer unless carries out of the ignored positions |
8454 | | * would have propagated through more than MUL_GUARD_DIGITS digits.) |
8455 | | * |
8456 | | * Note: an exact computation could not produce more than var1ndigits + |
8457 | | * var2ndigits digits, but we allocate at least one extra output digit in |
8458 | | * case rscale-driven rounding produces a carry out of the highest exact |
8459 | | * digit. |
8460 | | * |
8461 | | * The computation itself is done using base-NBASE^2 arithmetic, so we |
8462 | | * actually process the input digits in pairs, producing a base-NBASE^2 |
8463 | | * intermediate result. This significantly improves performance, since |
8464 | | * schoolbook multiplication is O(N^2) in the number of input digits, and |
8465 | | * working in base NBASE^2 effectively halves "N". |
8466 | | * |
8467 | | * Note: in a truncated computation, we must compute at least one extra |
8468 | | * output digit to ensure that all the guard digits are fully computed. |
8469 | | */ |
8470 | | /* digit pairs in each input */ |
8471 | 0 | var1ndigitpairs = (var1ndigits + 1) / 2; |
8472 | 0 | var2ndigitpairs = (var2ndigits + 1) / 2; |
8473 | | |
8474 | | /* digits in exact result */ |
8475 | 0 | res_ndigits = var1ndigits + var2ndigits; |
8476 | | |
8477 | | /* digit pairs in exact result with at least one extra output digit */ |
8478 | 0 | res_ndigitpairs = res_ndigits / 2 + 1; |
8479 | | |
8480 | | /* pair offset to align result to end of dig[] */ |
8481 | 0 | pair_offset = res_ndigitpairs - var1ndigitpairs - var2ndigitpairs + 1; |
8482 | | |
8483 | | /* maximum possible result weight (odd-length inputs shifted up below) */ |
8484 | 0 | res_weight = var1->weight + var2->weight + 1 + 2 * res_ndigitpairs - |
8485 | 0 | res_ndigits - (var1ndigits & 1) - (var2ndigits & 1); |
8486 | | |
8487 | | /* rscale-based truncation with at least one extra output digit */ |
8488 | 0 | maxdigits = res_weight + 1 + (rscale + DEC_DIGITS - 1) / DEC_DIGITS + |
8489 | 0 | MUL_GUARD_DIGITS; |
8490 | 0 | maxdigitpairs = maxdigits / 2 + 1; |
8491 | |
|
8492 | 0 | res_ndigitpairs = Min(res_ndigitpairs, maxdigitpairs); |
8493 | 0 | res_ndigits = 2 * res_ndigitpairs; |
8494 | | |
8495 | | /* |
8496 | | * In the computation below, digit pair i1 of var1 and digit pair i2 of |
8497 | | * var2 are multiplied and added to digit i1+i2+pair_offset of dig[]. Thus |
8498 | | * input digit pairs with index >= res_ndigitpairs - pair_offset don't |
8499 | | * contribute to the result, and can be ignored. |
8500 | | */ |
8501 | 0 | if (res_ndigitpairs <= pair_offset) |
8502 | 0 | { |
8503 | | /* All input digits will be ignored; so result is zero */ |
8504 | 0 | zero_var(result); |
8505 | 0 | result->dscale = rscale; |
8506 | 0 | return; |
8507 | 0 | } |
8508 | 0 | var1ndigitpairs = Min(var1ndigitpairs, res_ndigitpairs - pair_offset); |
8509 | 0 | var2ndigitpairs = Min(var2ndigitpairs, res_ndigitpairs - pair_offset); |
8510 | | |
8511 | | /* |
8512 | | * We do the arithmetic in an array "dig[]" of unsigned 64-bit integers. |
8513 | | * Since PG_UINT64_MAX is much larger than NBASE^4, this gives us a lot of |
8514 | | * headroom to avoid normalizing carries immediately. |
8515 | | * |
8516 | | * maxdig tracks the maximum possible value of any dig[] entry; when this |
8517 | | * threatens to exceed PG_UINT64_MAX, we take the time to propagate |
8518 | | * carries. Furthermore, we need to ensure that overflow doesn't occur |
8519 | | * during the carry propagation passes either. The carry values could be |
8520 | | * as much as PG_UINT64_MAX / NBASE^2, so really we must normalize when |
8521 | | * digits threaten to exceed PG_UINT64_MAX - PG_UINT64_MAX / NBASE^2. |
8522 | | * |
8523 | | * To avoid overflow in maxdig itself, it actually represents the maximum |
8524 | | * possible value divided by NBASE^2-1, i.e., at the top of the loop it is |
8525 | | * known that no dig[] entry exceeds maxdig * (NBASE^2-1). |
8526 | | * |
8527 | | * The conversion of var1 to base NBASE^2 is done on the fly, as each new |
8528 | | * digit is required. The digits of var2 are converted upfront, and |
8529 | | * stored at the end of dig[]. To avoid loss of precision, the input |
8530 | | * digits are aligned with the start of digit pair array, effectively |
8531 | | * shifting them up (multiplying by NBASE) if the inputs have an odd |
8532 | | * number of NBASE digits. |
8533 | | */ |
8534 | 0 | dig = (uint64 *) palloc(res_ndigitpairs * sizeof(uint64) + |
8535 | 0 | var2ndigitpairs * sizeof(uint32)); |
8536 | | |
8537 | | /* convert var2 to base NBASE^2, shifting up if its length is odd */ |
8538 | 0 | var2digitpairs = (uint32 *) (dig + res_ndigitpairs); |
8539 | |
|
8540 | 0 | for (i2 = 0; i2 < var2ndigitpairs - 1; i2++) |
8541 | 0 | var2digitpairs[i2] = var2digits[2 * i2] * NBASE + var2digits[2 * i2 + 1]; |
8542 | |
|
8543 | 0 | if (2 * i2 + 1 < var2ndigits) |
8544 | 0 | var2digitpairs[i2] = var2digits[2 * i2] * NBASE + var2digits[2 * i2 + 1]; |
8545 | 0 | else |
8546 | 0 | var2digitpairs[i2] = var2digits[2 * i2] * NBASE; |
8547 | | |
8548 | | /* |
8549 | | * Start by multiplying var2 by the least significant contributing digit |
8550 | | * pair from var1, storing the results at the end of dig[], and filling |
8551 | | * the leading digits with zeros. |
8552 | | * |
8553 | | * The loop here is the same as the inner loop below, except that we set |
8554 | | * the results in dig[], rather than adding to them. This is the |
8555 | | * performance bottleneck for multiplication, so we want to keep it simple |
8556 | | * enough so that it can be auto-vectorized. Accordingly, process the |
8557 | | * digits left-to-right even though schoolbook multiplication would |
8558 | | * suggest right-to-left. Since we aren't propagating carries in this |
8559 | | * loop, the order does not matter. |
8560 | | */ |
8561 | 0 | i1 = var1ndigitpairs - 1; |
8562 | 0 | if (2 * i1 + 1 < var1ndigits) |
8563 | 0 | var1digitpair = var1digits[2 * i1] * NBASE + var1digits[2 * i1 + 1]; |
8564 | 0 | else |
8565 | 0 | var1digitpair = var1digits[2 * i1] * NBASE; |
8566 | 0 | maxdig = var1digitpair; |
8567 | |
|
8568 | 0 | i2limit = Min(var2ndigitpairs, res_ndigitpairs - i1 - pair_offset); |
8569 | 0 | dig_i1_off = &dig[i1 + pair_offset]; |
8570 | |
|
8571 | 0 | memset(dig, 0, (i1 + pair_offset) * sizeof(uint64)); |
8572 | 0 | for (i2 = 0; i2 < i2limit; i2++) |
8573 | 0 | dig_i1_off[i2] = (uint64) var1digitpair * var2digitpairs[i2]; |
8574 | | |
8575 | | /* |
8576 | | * Next, multiply var2 by the remaining digit pairs from var1, adding the |
8577 | | * results to dig[] at the appropriate offsets, and normalizing whenever |
8578 | | * there is a risk of any dig[] entry overflowing. |
8579 | | */ |
8580 | 0 | for (i1 = i1 - 1; i1 >= 0; i1--) |
8581 | 0 | { |
8582 | 0 | var1digitpair = var1digits[2 * i1] * NBASE + var1digits[2 * i1 + 1]; |
8583 | 0 | if (var1digitpair == 0) |
8584 | 0 | continue; |
8585 | | |
8586 | | /* Time to normalize? */ |
8587 | 0 | maxdig += var1digitpair; |
8588 | 0 | if (maxdig > (PG_UINT64_MAX - PG_UINT64_MAX / NBASE_SQR) / (NBASE_SQR - 1)) |
8589 | 0 | { |
8590 | | /* Yes, do it (to base NBASE^2) */ |
8591 | 0 | carry = 0; |
8592 | 0 | for (i = res_ndigitpairs - 1; i >= 0; i--) |
8593 | 0 | { |
8594 | 0 | newdig = dig[i] + carry; |
8595 | 0 | if (newdig >= NBASE_SQR) |
8596 | 0 | { |
8597 | 0 | carry = newdig / NBASE_SQR; |
8598 | 0 | newdig -= carry * NBASE_SQR; |
8599 | 0 | } |
8600 | 0 | else |
8601 | 0 | carry = 0; |
8602 | 0 | dig[i] = newdig; |
8603 | 0 | } |
8604 | 0 | Assert(carry == 0); |
8605 | | /* Reset maxdig to indicate new worst-case */ |
8606 | 0 | maxdig = 1 + var1digitpair; |
8607 | 0 | } |
8608 | | |
8609 | | /* Multiply and add */ |
8610 | 0 | i2limit = Min(var2ndigitpairs, res_ndigitpairs - i1 - pair_offset); |
8611 | 0 | dig_i1_off = &dig[i1 + pair_offset]; |
8612 | |
|
8613 | 0 | for (i2 = 0; i2 < i2limit; i2++) |
8614 | 0 | dig_i1_off[i2] += (uint64) var1digitpair * var2digitpairs[i2]; |
8615 | 0 | } |
8616 | | |
8617 | | /* |
8618 | | * Now we do a final carry propagation pass to normalize back to base |
8619 | | * NBASE^2, and construct the base-NBASE result digits. Note that this is |
8620 | | * still done at full precision w/guard digits. |
8621 | | */ |
8622 | 0 | alloc_var(result, res_ndigits); |
8623 | 0 | res_digits = result->digits; |
8624 | 0 | carry = 0; |
8625 | 0 | for (i = res_ndigitpairs - 1; i >= 0; i--) |
8626 | 0 | { |
8627 | 0 | newdig = dig[i] + carry; |
8628 | 0 | if (newdig >= NBASE_SQR) |
8629 | 0 | { |
8630 | 0 | carry = newdig / NBASE_SQR; |
8631 | 0 | newdig -= carry * NBASE_SQR; |
8632 | 0 | } |
8633 | 0 | else |
8634 | 0 | carry = 0; |
8635 | 0 | res_digits[2 * i + 1] = (NumericDigit) ((uint32) newdig % NBASE); |
8636 | 0 | res_digits[2 * i] = (NumericDigit) ((uint32) newdig / NBASE); |
8637 | 0 | } |
8638 | 0 | Assert(carry == 0); |
8639 | |
|
8640 | 0 | pfree(dig); |
8641 | | |
8642 | | /* |
8643 | | * Finally, round the result to the requested precision. |
8644 | | */ |
8645 | 0 | result->weight = res_weight; |
8646 | 0 | result->sign = res_sign; |
8647 | | |
8648 | | /* Round to target rscale (and set result->dscale) */ |
8649 | 0 | round_var(result, rscale); |
8650 | | |
8651 | | /* Strip leading and trailing zeroes */ |
8652 | 0 | strip_var(result); |
8653 | 0 | } |
8654 | | |
8655 | | |
8656 | | /* |
8657 | | * mul_var_short() - |
8658 | | * |
8659 | | * Special-case multiplication function used when var1 has 1-6 digits, var2 |
8660 | | * has at least as many digits as var1, and the exact product var1 * var2 is |
8661 | | * requested. |
8662 | | */ |
8663 | | static void |
8664 | | mul_var_short(const NumericVar *var1, const NumericVar *var2, |
8665 | | NumericVar *result) |
8666 | 0 | { |
8667 | 0 | int var1ndigits = var1->ndigits; |
8668 | 0 | int var2ndigits = var2->ndigits; |
8669 | 0 | NumericDigit *var1digits = var1->digits; |
8670 | 0 | NumericDigit *var2digits = var2->digits; |
8671 | 0 | int res_sign; |
8672 | 0 | int res_weight; |
8673 | 0 | int res_ndigits; |
8674 | 0 | NumericDigit *res_buf; |
8675 | 0 | NumericDigit *res_digits; |
8676 | 0 | uint32 carry = 0; |
8677 | 0 | uint32 term; |
8678 | | |
8679 | | /* Check preconditions */ |
8680 | 0 | Assert(var1ndigits >= 1); |
8681 | 0 | Assert(var1ndigits <= 6); |
8682 | 0 | Assert(var2ndigits >= var1ndigits); |
8683 | | |
8684 | | /* |
8685 | | * Determine the result sign, weight, and number of digits to calculate. |
8686 | | * The weight figured here is correct if the product has no leading zero |
8687 | | * digits; otherwise strip_var() will fix things up. Note that, unlike |
8688 | | * mul_var(), we do not need to allocate an extra output digit, because we |
8689 | | * are not rounding here. |
8690 | | */ |
8691 | 0 | if (var1->sign == var2->sign) |
8692 | 0 | res_sign = NUMERIC_POS; |
8693 | 0 | else |
8694 | 0 | res_sign = NUMERIC_NEG; |
8695 | 0 | res_weight = var1->weight + var2->weight + 1; |
8696 | 0 | res_ndigits = var1ndigits + var2ndigits; |
8697 | | |
8698 | | /* Allocate result digit array */ |
8699 | 0 | res_buf = digitbuf_alloc(res_ndigits + 1); |
8700 | 0 | res_buf[0] = 0; /* spare digit for later rounding */ |
8701 | 0 | res_digits = res_buf + 1; |
8702 | | |
8703 | | /* |
8704 | | * Compute the result digits in reverse, in one pass, propagating the |
8705 | | * carry up as we go. The i'th result digit consists of the sum of the |
8706 | | * products var1digits[i1] * var2digits[i2] for which i = i1 + i2 + 1. |
8707 | | */ |
8708 | 0 | #define PRODSUM1(v1,i1,v2,i2) ((v1)[(i1)] * (v2)[(i2)]) |
8709 | 0 | #define PRODSUM2(v1,i1,v2,i2) (PRODSUM1(v1,i1,v2,i2) + (v1)[(i1)+1] * (v2)[(i2)-1]) |
8710 | 0 | #define PRODSUM3(v1,i1,v2,i2) (PRODSUM2(v1,i1,v2,i2) + (v1)[(i1)+2] * (v2)[(i2)-2]) |
8711 | 0 | #define PRODSUM4(v1,i1,v2,i2) (PRODSUM3(v1,i1,v2,i2) + (v1)[(i1)+3] * (v2)[(i2)-3]) |
8712 | 0 | #define PRODSUM5(v1,i1,v2,i2) (PRODSUM4(v1,i1,v2,i2) + (v1)[(i1)+4] * (v2)[(i2)-4]) |
8713 | 0 | #define PRODSUM6(v1,i1,v2,i2) (PRODSUM5(v1,i1,v2,i2) + (v1)[(i1)+5] * (v2)[(i2)-5]) |
8714 | |
|
8715 | 0 | switch (var1ndigits) |
8716 | 0 | { |
8717 | 0 | case 1: |
8718 | | /* --------- |
8719 | | * 1-digit case: |
8720 | | * var1ndigits = 1 |
8721 | | * var2ndigits >= 1 |
8722 | | * res_ndigits = var2ndigits + 1 |
8723 | | * ---------- |
8724 | | */ |
8725 | 0 | for (int i = var2ndigits - 1; i >= 0; i--) |
8726 | 0 | { |
8727 | 0 | term = PRODSUM1(var1digits, 0, var2digits, i) + carry; |
8728 | 0 | res_digits[i + 1] = (NumericDigit) (term % NBASE); |
8729 | 0 | carry = term / NBASE; |
8730 | 0 | } |
8731 | 0 | res_digits[0] = (NumericDigit) carry; |
8732 | 0 | break; |
8733 | | |
8734 | 0 | case 2: |
8735 | | /* --------- |
8736 | | * 2-digit case: |
8737 | | * var1ndigits = 2 |
8738 | | * var2ndigits >= 2 |
8739 | | * res_ndigits = var2ndigits + 2 |
8740 | | * ---------- |
8741 | | */ |
8742 | | /* last result digit and carry */ |
8743 | 0 | term = PRODSUM1(var1digits, 1, var2digits, var2ndigits - 1); |
8744 | 0 | res_digits[res_ndigits - 1] = (NumericDigit) (term % NBASE); |
8745 | 0 | carry = term / NBASE; |
8746 | | |
8747 | | /* remaining digits, except for the first two */ |
8748 | 0 | for (int i = var2ndigits - 1; i >= 1; i--) |
8749 | 0 | { |
8750 | 0 | term = PRODSUM2(var1digits, 0, var2digits, i) + carry; |
8751 | 0 | res_digits[i + 1] = (NumericDigit) (term % NBASE); |
8752 | 0 | carry = term / NBASE; |
8753 | 0 | } |
8754 | 0 | break; |
8755 | | |
8756 | 0 | case 3: |
8757 | | /* --------- |
8758 | | * 3-digit case: |
8759 | | * var1ndigits = 3 |
8760 | | * var2ndigits >= 3 |
8761 | | * res_ndigits = var2ndigits + 3 |
8762 | | * ---------- |
8763 | | */ |
8764 | | /* last two result digits */ |
8765 | 0 | term = PRODSUM1(var1digits, 2, var2digits, var2ndigits - 1); |
8766 | 0 | res_digits[res_ndigits - 1] = (NumericDigit) (term % NBASE); |
8767 | 0 | carry = term / NBASE; |
8768 | |
|
8769 | 0 | term = PRODSUM2(var1digits, 1, var2digits, var2ndigits - 1) + carry; |
8770 | 0 | res_digits[res_ndigits - 2] = (NumericDigit) (term % NBASE); |
8771 | 0 | carry = term / NBASE; |
8772 | | |
8773 | | /* remaining digits, except for the first three */ |
8774 | 0 | for (int i = var2ndigits - 1; i >= 2; i--) |
8775 | 0 | { |
8776 | 0 | term = PRODSUM3(var1digits, 0, var2digits, i) + carry; |
8777 | 0 | res_digits[i + 1] = (NumericDigit) (term % NBASE); |
8778 | 0 | carry = term / NBASE; |
8779 | 0 | } |
8780 | 0 | break; |
8781 | | |
8782 | 0 | case 4: |
8783 | | /* --------- |
8784 | | * 4-digit case: |
8785 | | * var1ndigits = 4 |
8786 | | * var2ndigits >= 4 |
8787 | | * res_ndigits = var2ndigits + 4 |
8788 | | * ---------- |
8789 | | */ |
8790 | | /* last three result digits */ |
8791 | 0 | term = PRODSUM1(var1digits, 3, var2digits, var2ndigits - 1); |
8792 | 0 | res_digits[res_ndigits - 1] = (NumericDigit) (term % NBASE); |
8793 | 0 | carry = term / NBASE; |
8794 | |
|
8795 | 0 | term = PRODSUM2(var1digits, 2, var2digits, var2ndigits - 1) + carry; |
8796 | 0 | res_digits[res_ndigits - 2] = (NumericDigit) (term % NBASE); |
8797 | 0 | carry = term / NBASE; |
8798 | |
|
8799 | 0 | term = PRODSUM3(var1digits, 1, var2digits, var2ndigits - 1) + carry; |
8800 | 0 | res_digits[res_ndigits - 3] = (NumericDigit) (term % NBASE); |
8801 | 0 | carry = term / NBASE; |
8802 | | |
8803 | | /* remaining digits, except for the first four */ |
8804 | 0 | for (int i = var2ndigits - 1; i >= 3; i--) |
8805 | 0 | { |
8806 | 0 | term = PRODSUM4(var1digits, 0, var2digits, i) + carry; |
8807 | 0 | res_digits[i + 1] = (NumericDigit) (term % NBASE); |
8808 | 0 | carry = term / NBASE; |
8809 | 0 | } |
8810 | 0 | break; |
8811 | | |
8812 | 0 | case 5: |
8813 | | /* --------- |
8814 | | * 5-digit case: |
8815 | | * var1ndigits = 5 |
8816 | | * var2ndigits >= 5 |
8817 | | * res_ndigits = var2ndigits + 5 |
8818 | | * ---------- |
8819 | | */ |
8820 | | /* last four result digits */ |
8821 | 0 | term = PRODSUM1(var1digits, 4, var2digits, var2ndigits - 1); |
8822 | 0 | res_digits[res_ndigits - 1] = (NumericDigit) (term % NBASE); |
8823 | 0 | carry = term / NBASE; |
8824 | |
|
8825 | 0 | term = PRODSUM2(var1digits, 3, var2digits, var2ndigits - 1) + carry; |
8826 | 0 | res_digits[res_ndigits - 2] = (NumericDigit) (term % NBASE); |
8827 | 0 | carry = term / NBASE; |
8828 | |
|
8829 | 0 | term = PRODSUM3(var1digits, 2, var2digits, var2ndigits - 1) + carry; |
8830 | 0 | res_digits[res_ndigits - 3] = (NumericDigit) (term % NBASE); |
8831 | 0 | carry = term / NBASE; |
8832 | |
|
8833 | 0 | term = PRODSUM4(var1digits, 1, var2digits, var2ndigits - 1) + carry; |
8834 | 0 | res_digits[res_ndigits - 4] = (NumericDigit) (term % NBASE); |
8835 | 0 | carry = term / NBASE; |
8836 | | |
8837 | | /* remaining digits, except for the first five */ |
8838 | 0 | for (int i = var2ndigits - 1; i >= 4; i--) |
8839 | 0 | { |
8840 | 0 | term = PRODSUM5(var1digits, 0, var2digits, i) + carry; |
8841 | 0 | res_digits[i + 1] = (NumericDigit) (term % NBASE); |
8842 | 0 | carry = term / NBASE; |
8843 | 0 | } |
8844 | 0 | break; |
8845 | | |
8846 | 0 | case 6: |
8847 | | /* --------- |
8848 | | * 6-digit case: |
8849 | | * var1ndigits = 6 |
8850 | | * var2ndigits >= 6 |
8851 | | * res_ndigits = var2ndigits + 6 |
8852 | | * ---------- |
8853 | | */ |
8854 | | /* last five result digits */ |
8855 | 0 | term = PRODSUM1(var1digits, 5, var2digits, var2ndigits - 1); |
8856 | 0 | res_digits[res_ndigits - 1] = (NumericDigit) (term % NBASE); |
8857 | 0 | carry = term / NBASE; |
8858 | |
|
8859 | 0 | term = PRODSUM2(var1digits, 4, var2digits, var2ndigits - 1) + carry; |
8860 | 0 | res_digits[res_ndigits - 2] = (NumericDigit) (term % NBASE); |
8861 | 0 | carry = term / NBASE; |
8862 | |
|
8863 | 0 | term = PRODSUM3(var1digits, 3, var2digits, var2ndigits - 1) + carry; |
8864 | 0 | res_digits[res_ndigits - 3] = (NumericDigit) (term % NBASE); |
8865 | 0 | carry = term / NBASE; |
8866 | |
|
8867 | 0 | term = PRODSUM4(var1digits, 2, var2digits, var2ndigits - 1) + carry; |
8868 | 0 | res_digits[res_ndigits - 4] = (NumericDigit) (term % NBASE); |
8869 | 0 | carry = term / NBASE; |
8870 | |
|
8871 | 0 | term = PRODSUM5(var1digits, 1, var2digits, var2ndigits - 1) + carry; |
8872 | 0 | res_digits[res_ndigits - 5] = (NumericDigit) (term % NBASE); |
8873 | 0 | carry = term / NBASE; |
8874 | | |
8875 | | /* remaining digits, except for the first six */ |
8876 | 0 | for (int i = var2ndigits - 1; i >= 5; i--) |
8877 | 0 | { |
8878 | 0 | term = PRODSUM6(var1digits, 0, var2digits, i) + carry; |
8879 | 0 | res_digits[i + 1] = (NumericDigit) (term % NBASE); |
8880 | 0 | carry = term / NBASE; |
8881 | 0 | } |
8882 | 0 | break; |
8883 | 0 | } |
8884 | | |
8885 | | /* |
8886 | | * Finally, for var1ndigits > 1, compute the remaining var1ndigits most |
8887 | | * significant result digits. |
8888 | | */ |
8889 | 0 | switch (var1ndigits) |
8890 | 0 | { |
8891 | 0 | case 6: |
8892 | 0 | term = PRODSUM5(var1digits, 0, var2digits, 4) + carry; |
8893 | 0 | res_digits[5] = (NumericDigit) (term % NBASE); |
8894 | 0 | carry = term / NBASE; |
8895 | 0 | pg_fallthrough; |
8896 | 0 | case 5: |
8897 | 0 | term = PRODSUM4(var1digits, 0, var2digits, 3) + carry; |
8898 | 0 | res_digits[4] = (NumericDigit) (term % NBASE); |
8899 | 0 | carry = term / NBASE; |
8900 | 0 | pg_fallthrough; |
8901 | 0 | case 4: |
8902 | 0 | term = PRODSUM3(var1digits, 0, var2digits, 2) + carry; |
8903 | 0 | res_digits[3] = (NumericDigit) (term % NBASE); |
8904 | 0 | carry = term / NBASE; |
8905 | 0 | pg_fallthrough; |
8906 | 0 | case 3: |
8907 | 0 | term = PRODSUM2(var1digits, 0, var2digits, 1) + carry; |
8908 | 0 | res_digits[2] = (NumericDigit) (term % NBASE); |
8909 | 0 | carry = term / NBASE; |
8910 | 0 | pg_fallthrough; |
8911 | 0 | case 2: |
8912 | 0 | term = PRODSUM1(var1digits, 0, var2digits, 0) + carry; |
8913 | 0 | res_digits[1] = (NumericDigit) (term % NBASE); |
8914 | 0 | res_digits[0] = (NumericDigit) (term / NBASE); |
8915 | 0 | break; |
8916 | 0 | } |
8917 | | |
8918 | | /* Store the product in result */ |
8919 | 0 | digitbuf_free(result->buf); |
8920 | 0 | result->ndigits = res_ndigits; |
8921 | 0 | result->buf = res_buf; |
8922 | 0 | result->digits = res_digits; |
8923 | 0 | result->weight = res_weight; |
8924 | 0 | result->sign = res_sign; |
8925 | 0 | result->dscale = var1->dscale + var2->dscale; |
8926 | | |
8927 | | /* Strip leading and trailing zeroes */ |
8928 | 0 | strip_var(result); |
8929 | 0 | } |
8930 | | |
8931 | | |
8932 | | /* |
8933 | | * div_var() - |
8934 | | * |
8935 | | * Compute the quotient var1 / var2 to rscale fractional digits. |
8936 | | * |
8937 | | * If "round" is true, the result is rounded at the rscale'th digit; if |
8938 | | * false, it is truncated (towards zero) at that digit. |
8939 | | * |
8940 | | * If "exact" is true, the exact result is computed to the specified rscale; |
8941 | | * if false, successive quotient digits are approximated up to rscale plus |
8942 | | * DIV_GUARD_DIGITS extra digits, ignoring all contributions from digits to |
8943 | | * the right of that, before rounding or truncating to the specified rscale. |
8944 | | * This can be significantly faster, and usually gives the same result as the |
8945 | | * exact computation, but it may occasionally be off by one in the final |
8946 | | * digit, if contributions from the ignored digits would have propagated |
8947 | | * through the guard digits. This is good enough for the transcendental |
8948 | | * functions, where small errors are acceptable. |
8949 | | */ |
8950 | | static void |
8951 | | div_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result, |
8952 | | int rscale, bool round, bool exact) |
8953 | 0 | { |
8954 | 0 | int var1ndigits = var1->ndigits; |
8955 | 0 | int var2ndigits = var2->ndigits; |
8956 | 0 | int res_sign; |
8957 | 0 | int res_weight; |
8958 | 0 | int res_ndigits; |
8959 | 0 | int var1ndigitpairs; |
8960 | 0 | int var2ndigitpairs; |
8961 | 0 | int res_ndigitpairs; |
8962 | 0 | int div_ndigitpairs; |
8963 | 0 | int64 *dividend; |
8964 | 0 | int32 *divisor; |
8965 | 0 | double fdivisor, |
8966 | 0 | fdivisorinverse, |
8967 | 0 | fdividend, |
8968 | 0 | fquotient; |
8969 | 0 | int64 maxdiv; |
8970 | 0 | int qi; |
8971 | 0 | int32 qdigit; |
8972 | 0 | int64 carry; |
8973 | 0 | int64 newdig; |
8974 | 0 | int64 *remainder; |
8975 | 0 | NumericDigit *res_digits; |
8976 | 0 | int i; |
8977 | | |
8978 | | /* |
8979 | | * First of all division by zero check; we must not be handed an |
8980 | | * unnormalized divisor. |
8981 | | */ |
8982 | 0 | if (var2ndigits == 0 || var2->digits[0] == 0) |
8983 | 0 | ereport(ERROR, |
8984 | 0 | (errcode(ERRCODE_DIVISION_BY_ZERO), |
8985 | 0 | errmsg("division by zero"))); |
8986 | | |
8987 | | /* |
8988 | | * If the divisor has just one or two digits, delegate to div_var_int(), |
8989 | | * which uses fast short division. |
8990 | | * |
8991 | | * Similarly, on platforms with 128-bit integer support, delegate to |
8992 | | * div_var_int64() for divisors with three or four digits. |
8993 | | */ |
8994 | 0 | if (var2ndigits <= 2) |
8995 | 0 | { |
8996 | 0 | int idivisor; |
8997 | 0 | int idivisor_weight; |
8998 | |
|
8999 | 0 | idivisor = var2->digits[0]; |
9000 | 0 | idivisor_weight = var2->weight; |
9001 | 0 | if (var2ndigits == 2) |
9002 | 0 | { |
9003 | 0 | idivisor = idivisor * NBASE + var2->digits[1]; |
9004 | 0 | idivisor_weight--; |
9005 | 0 | } |
9006 | 0 | if (var2->sign == NUMERIC_NEG) |
9007 | 0 | idivisor = -idivisor; |
9008 | |
|
9009 | 0 | div_var_int(var1, idivisor, idivisor_weight, result, rscale, round); |
9010 | 0 | return; |
9011 | 0 | } |
9012 | 0 | #ifdef HAVE_INT128 |
9013 | 0 | if (var2ndigits <= 4) |
9014 | 0 | { |
9015 | 0 | int64 idivisor; |
9016 | 0 | int idivisor_weight; |
9017 | |
|
9018 | 0 | idivisor = var2->digits[0]; |
9019 | 0 | idivisor_weight = var2->weight; |
9020 | 0 | for (i = 1; i < var2ndigits; i++) |
9021 | 0 | { |
9022 | 0 | idivisor = idivisor * NBASE + var2->digits[i]; |
9023 | 0 | idivisor_weight--; |
9024 | 0 | } |
9025 | 0 | if (var2->sign == NUMERIC_NEG) |
9026 | 0 | idivisor = -idivisor; |
9027 | |
|
9028 | 0 | div_var_int64(var1, idivisor, idivisor_weight, result, rscale, round); |
9029 | 0 | return; |
9030 | 0 | } |
9031 | 0 | #endif |
9032 | | |
9033 | | /* |
9034 | | * Otherwise, perform full long division. |
9035 | | */ |
9036 | | |
9037 | | /* Result zero check */ |
9038 | 0 | if (var1ndigits == 0) |
9039 | 0 | { |
9040 | 0 | zero_var(result); |
9041 | 0 | result->dscale = rscale; |
9042 | 0 | return; |
9043 | 0 | } |
9044 | | |
9045 | | /* |
9046 | | * The approximate computation can be significantly faster than the exact |
9047 | | * one, since the working dividend is var2ndigitpairs base-NBASE^2 digits |
9048 | | * shorter below. However, that comes with the tradeoff of computing |
9049 | | * DIV_GUARD_DIGITS extra base-NBASE result digits. Ignoring all other |
9050 | | * overheads, that suggests that, in theory, the approximate computation |
9051 | | * will only be faster than the exact one when var2ndigits is greater than |
9052 | | * 2 * (DIV_GUARD_DIGITS + 1), independent of the size of var1. |
9053 | | * |
9054 | | * Thus, we're better off doing an exact computation when var2 is shorter |
9055 | | * than this. Empirically, it has been found that the exact threshold is |
9056 | | * a little higher, due to other overheads in the outer division loop. |
9057 | | */ |
9058 | 0 | if (var2ndigits <= 2 * (DIV_GUARD_DIGITS + 2)) |
9059 | 0 | exact = true; |
9060 | | |
9061 | | /* |
9062 | | * Determine the result sign, weight and number of digits to calculate. |
9063 | | * The weight figured here is correct if the emitted quotient has no |
9064 | | * leading zero digits; otherwise strip_var() will fix things up. |
9065 | | */ |
9066 | 0 | if (var1->sign == var2->sign) |
9067 | 0 | res_sign = NUMERIC_POS; |
9068 | 0 | else |
9069 | 0 | res_sign = NUMERIC_NEG; |
9070 | 0 | res_weight = var1->weight - var2->weight + 1; |
9071 | | /* The number of accurate result digits we need to produce: */ |
9072 | 0 | res_ndigits = res_weight + 1 + (rscale + DEC_DIGITS - 1) / DEC_DIGITS; |
9073 | | /* ... but always at least 1 */ |
9074 | 0 | res_ndigits = Max(res_ndigits, 1); |
9075 | | /* If rounding needed, figure one more digit to ensure correct result */ |
9076 | 0 | if (round) |
9077 | 0 | res_ndigits++; |
9078 | | /* Add guard digits for roundoff error when producing approx result */ |
9079 | 0 | if (!exact) |
9080 | 0 | res_ndigits += DIV_GUARD_DIGITS; |
9081 | | |
9082 | | /* |
9083 | | * The computation itself is done using base-NBASE^2 arithmetic, so we |
9084 | | * actually process the input digits in pairs, producing a base-NBASE^2 |
9085 | | * intermediate result. This significantly improves performance, since |
9086 | | * the computation is O(N^2) in the number of input digits, and working in |
9087 | | * base NBASE^2 effectively halves "N". |
9088 | | */ |
9089 | 0 | var1ndigitpairs = (var1ndigits + 1) / 2; |
9090 | 0 | var2ndigitpairs = (var2ndigits + 1) / 2; |
9091 | 0 | res_ndigitpairs = (res_ndigits + 1) / 2; |
9092 | 0 | res_ndigits = 2 * res_ndigitpairs; |
9093 | | |
9094 | | /* |
9095 | | * We do the arithmetic in an array "dividend[]" of signed 64-bit |
9096 | | * integers. Since PG_INT64_MAX is much larger than NBASE^4, this gives |
9097 | | * us a lot of headroom to avoid normalizing carries immediately. |
9098 | | * |
9099 | | * When performing an exact computation, the working dividend requires |
9100 | | * res_ndigitpairs + var2ndigitpairs digits. If var1 is larger than that, |
9101 | | * the extra digits do not contribute to the result, and are ignored. |
9102 | | * |
9103 | | * When performing an approximate computation, the working dividend only |
9104 | | * requires res_ndigitpairs digits (which includes the extra guard |
9105 | | * digits). All input digits beyond that are ignored. |
9106 | | */ |
9107 | 0 | if (exact) |
9108 | 0 | { |
9109 | 0 | div_ndigitpairs = res_ndigitpairs + var2ndigitpairs; |
9110 | 0 | var1ndigitpairs = Min(var1ndigitpairs, div_ndigitpairs); |
9111 | 0 | } |
9112 | 0 | else |
9113 | 0 | { |
9114 | 0 | div_ndigitpairs = res_ndigitpairs; |
9115 | 0 | var1ndigitpairs = Min(var1ndigitpairs, div_ndigitpairs); |
9116 | 0 | var2ndigitpairs = Min(var2ndigitpairs, div_ndigitpairs); |
9117 | 0 | } |
9118 | | |
9119 | | /* |
9120 | | * Allocate room for the working dividend (div_ndigitpairs 64-bit digits) |
9121 | | * plus the divisor (var2ndigitpairs 32-bit base-NBASE^2 digits). |
9122 | | * |
9123 | | * For convenience, we allocate one extra dividend digit, which is set to |
9124 | | * zero and not counted in div_ndigitpairs, so that the main loop below |
9125 | | * can safely read and write the (qi+1)'th digit in the approximate case. |
9126 | | */ |
9127 | 0 | dividend = (int64 *) palloc((div_ndigitpairs + 1) * sizeof(int64) + |
9128 | 0 | var2ndigitpairs * sizeof(int32)); |
9129 | 0 | divisor = (int32 *) (dividend + div_ndigitpairs + 1); |
9130 | | |
9131 | | /* load var1 into dividend[0 .. var1ndigitpairs-1], zeroing the rest */ |
9132 | 0 | for (i = 0; i < var1ndigitpairs - 1; i++) |
9133 | 0 | dividend[i] = var1->digits[2 * i] * NBASE + var1->digits[2 * i + 1]; |
9134 | |
|
9135 | 0 | if (2 * i + 1 < var1ndigits) |
9136 | 0 | dividend[i] = var1->digits[2 * i] * NBASE + var1->digits[2 * i + 1]; |
9137 | 0 | else |
9138 | 0 | dividend[i] = var1->digits[2 * i] * NBASE; |
9139 | |
|
9140 | 0 | memset(dividend + i + 1, 0, (div_ndigitpairs - i) * sizeof(int64)); |
9141 | | |
9142 | | /* load var2 into divisor[0 .. var2ndigitpairs-1] */ |
9143 | 0 | for (i = 0; i < var2ndigitpairs - 1; i++) |
9144 | 0 | divisor[i] = var2->digits[2 * i] * NBASE + var2->digits[2 * i + 1]; |
9145 | |
|
9146 | 0 | if (2 * i + 1 < var2ndigits) |
9147 | 0 | divisor[i] = var2->digits[2 * i] * NBASE + var2->digits[2 * i + 1]; |
9148 | 0 | else |
9149 | 0 | divisor[i] = var2->digits[2 * i] * NBASE; |
9150 | | |
9151 | | /* |
9152 | | * We estimate each quotient digit using floating-point arithmetic, taking |
9153 | | * the first 2 base-NBASE^2 digits of the (current) dividend and divisor. |
9154 | | * This must be float to avoid overflow. |
9155 | | * |
9156 | | * Since the floating-point dividend and divisor use 4 base-NBASE input |
9157 | | * digits, they include roughly 40-53 bits of information from their |
9158 | | * respective inputs (assuming NBASE is 10000), which fits well in IEEE |
9159 | | * double-precision variables. The relative error in the floating-point |
9160 | | * quotient digit will then be less than around 2/NBASE^3, so the |
9161 | | * estimated base-NBASE^2 quotient digit will typically be correct, and |
9162 | | * should not be off by more than one from the correct value. |
9163 | | */ |
9164 | 0 | fdivisor = (double) divisor[0] * NBASE_SQR; |
9165 | 0 | if (var2ndigitpairs > 1) |
9166 | 0 | fdivisor += (double) divisor[1]; |
9167 | 0 | fdivisorinverse = 1.0 / fdivisor; |
9168 | | |
9169 | | /* |
9170 | | * maxdiv tracks the maximum possible absolute value of any dividend[] |
9171 | | * entry; when this threatens to exceed PG_INT64_MAX, we take the time to |
9172 | | * propagate carries. Furthermore, we need to ensure that overflow |
9173 | | * doesn't occur during the carry propagation passes either. The carry |
9174 | | * values may have an absolute value as high as PG_INT64_MAX/NBASE^2 + 1, |
9175 | | * so really we must normalize when digits threaten to exceed PG_INT64_MAX |
9176 | | * - PG_INT64_MAX/NBASE^2 - 1. |
9177 | | * |
9178 | | * To avoid overflow in maxdiv itself, it represents the max absolute |
9179 | | * value divided by NBASE^2-1, i.e., at the top of the loop it is known |
9180 | | * that no dividend[] entry has an absolute value exceeding maxdiv * |
9181 | | * (NBASE^2-1). |
9182 | | * |
9183 | | * Actually, though, that holds good only for dividend[] entries after |
9184 | | * dividend[qi]; the adjustment done at the bottom of the loop may cause |
9185 | | * dividend[qi + 1] to exceed the maxdiv limit, so that dividend[qi] in |
9186 | | * the next iteration is beyond the limit. This does not cause problems, |
9187 | | * as explained below. |
9188 | | */ |
9189 | 0 | maxdiv = 1; |
9190 | | |
9191 | | /* |
9192 | | * Outer loop computes next quotient digit, which goes in dividend[qi]. |
9193 | | */ |
9194 | 0 | for (qi = 0; qi < res_ndigitpairs; qi++) |
9195 | 0 | { |
9196 | | /* Approximate the current dividend value */ |
9197 | 0 | fdividend = (double) dividend[qi] * NBASE_SQR; |
9198 | 0 | fdividend += (double) dividend[qi + 1]; |
9199 | | |
9200 | | /* Compute the (approximate) quotient digit */ |
9201 | 0 | fquotient = fdividend * fdivisorinverse; |
9202 | 0 | qdigit = (fquotient >= 0.0) ? ((int32) fquotient) : |
9203 | 0 | (((int32) fquotient) - 1); /* truncate towards -infinity */ |
9204 | |
|
9205 | 0 | if (qdigit != 0) |
9206 | 0 | { |
9207 | | /* Do we need to normalize now? */ |
9208 | 0 | maxdiv += i64abs(qdigit); |
9209 | 0 | if (maxdiv > (PG_INT64_MAX - PG_INT64_MAX / NBASE_SQR - 1) / (NBASE_SQR - 1)) |
9210 | 0 | { |
9211 | | /* |
9212 | | * Yes, do it. Note that if var2ndigitpairs is much smaller |
9213 | | * than div_ndigitpairs, we can save a significant amount of |
9214 | | * effort here by noting that we only need to normalise those |
9215 | | * dividend[] entries touched where prior iterations |
9216 | | * subtracted multiples of the divisor. |
9217 | | */ |
9218 | 0 | carry = 0; |
9219 | 0 | for (i = Min(qi + var2ndigitpairs - 2, div_ndigitpairs - 1); i > qi; i--) |
9220 | 0 | { |
9221 | 0 | newdig = dividend[i] + carry; |
9222 | 0 | if (newdig < 0) |
9223 | 0 | { |
9224 | 0 | carry = -((-newdig - 1) / NBASE_SQR) - 1; |
9225 | 0 | newdig -= carry * NBASE_SQR; |
9226 | 0 | } |
9227 | 0 | else if (newdig >= NBASE_SQR) |
9228 | 0 | { |
9229 | 0 | carry = newdig / NBASE_SQR; |
9230 | 0 | newdig -= carry * NBASE_SQR; |
9231 | 0 | } |
9232 | 0 | else |
9233 | 0 | carry = 0; |
9234 | 0 | dividend[i] = newdig; |
9235 | 0 | } |
9236 | 0 | dividend[qi] += carry; |
9237 | | |
9238 | | /* |
9239 | | * All the dividend[] digits except possibly dividend[qi] are |
9240 | | * now in the range 0..NBASE^2-1. We do not need to consider |
9241 | | * dividend[qi] in the maxdiv value anymore, so we can reset |
9242 | | * maxdiv to 1. |
9243 | | */ |
9244 | 0 | maxdiv = 1; |
9245 | | |
9246 | | /* |
9247 | | * Recompute the quotient digit since new info may have |
9248 | | * propagated into the top two dividend digits. |
9249 | | */ |
9250 | 0 | fdividend = (double) dividend[qi] * NBASE_SQR; |
9251 | 0 | fdividend += (double) dividend[qi + 1]; |
9252 | 0 | fquotient = fdividend * fdivisorinverse; |
9253 | 0 | qdigit = (fquotient >= 0.0) ? ((int32) fquotient) : |
9254 | 0 | (((int32) fquotient) - 1); /* truncate towards -infinity */ |
9255 | |
|
9256 | 0 | maxdiv += i64abs(qdigit); |
9257 | 0 | } |
9258 | | |
9259 | | /* |
9260 | | * Subtract off the appropriate multiple of the divisor. |
9261 | | * |
9262 | | * The digits beyond dividend[qi] cannot overflow, because we know |
9263 | | * they will fall within the maxdiv limit. As for dividend[qi] |
9264 | | * itself, note that qdigit is approximately trunc(dividend[qi] / |
9265 | | * divisor[0]), which would make the new value simply dividend[qi] |
9266 | | * mod divisor[0]. The lower-order terms in qdigit can change |
9267 | | * this result by not more than about twice PG_INT64_MAX/NBASE^2, |
9268 | | * so overflow is impossible. |
9269 | | * |
9270 | | * This inner loop is the performance bottleneck for division, so |
9271 | | * code it in the same way as the inner loop of mul_var() so that |
9272 | | * it can be auto-vectorized. |
9273 | | */ |
9274 | 0 | if (qdigit != 0) |
9275 | 0 | { |
9276 | 0 | int istop = Min(var2ndigitpairs, div_ndigitpairs - qi); |
9277 | 0 | int64 *dividend_qi = ÷nd[qi]; |
9278 | |
|
9279 | 0 | for (i = 0; i < istop; i++) |
9280 | 0 | dividend_qi[i] -= (int64) qdigit * divisor[i]; |
9281 | 0 | } |
9282 | 0 | } |
9283 | | |
9284 | | /* |
9285 | | * The dividend digit we are about to replace might still be nonzero. |
9286 | | * Fold it into the next digit position. |
9287 | | * |
9288 | | * There is no risk of overflow here, although proving that requires |
9289 | | * some care. Much as with the argument for dividend[qi] not |
9290 | | * overflowing, if we consider the first two terms in the numerator |
9291 | | * and denominator of qdigit, we can see that the final value of |
9292 | | * dividend[qi + 1] will be approximately a remainder mod |
9293 | | * (divisor[0]*NBASE^2 + divisor[1]). Accounting for the lower-order |
9294 | | * terms is a bit complicated but ends up adding not much more than |
9295 | | * PG_INT64_MAX/NBASE^2 to the possible range. Thus, dividend[qi + 1] |
9296 | | * cannot overflow here, and in its role as dividend[qi] in the next |
9297 | | * loop iteration, it can't be large enough to cause overflow in the |
9298 | | * carry propagation step (if any), either. |
9299 | | * |
9300 | | * But having said that: dividend[qi] can be more than |
9301 | | * PG_INT64_MAX/NBASE^2, as noted above, which means that the product |
9302 | | * dividend[qi] * NBASE^2 *can* overflow. When that happens, adding |
9303 | | * it to dividend[qi + 1] will always cause a canceling overflow so |
9304 | | * that the end result is correct. We could avoid the intermediate |
9305 | | * overflow by doing the multiplication and addition using unsigned |
9306 | | * int64 arithmetic, which is modulo 2^64, but so far there appears no |
9307 | | * need. |
9308 | | */ |
9309 | 0 | dividend[qi + 1] += dividend[qi] * NBASE_SQR; |
9310 | |
|
9311 | 0 | dividend[qi] = qdigit; |
9312 | 0 | } |
9313 | | |
9314 | | /* |
9315 | | * If an exact result was requested, use the remainder to correct the |
9316 | | * approximate quotient. The remainder is in dividend[], immediately |
9317 | | * after the quotient digits. Note, however, that although the remainder |
9318 | | * starts at dividend[qi = res_ndigitpairs], the first digit is the result |
9319 | | * of folding two remainder digits into one above, and the remainder |
9320 | | * currently only occupies var2ndigitpairs - 1 digits (the last digit of |
9321 | | * the working dividend was untouched by the computation above). Thus we |
9322 | | * expand the remainder down by one base-NBASE^2 digit when we normalize |
9323 | | * it, so that it completely fills the last var2ndigitpairs digits of the |
9324 | | * dividend array. |
9325 | | */ |
9326 | 0 | if (exact) |
9327 | 0 | { |
9328 | | /* Normalize the remainder, expanding it down by one digit */ |
9329 | 0 | remainder = ÷nd[qi]; |
9330 | 0 | carry = 0; |
9331 | 0 | for (i = var2ndigitpairs - 2; i >= 0; i--) |
9332 | 0 | { |
9333 | 0 | newdig = remainder[i] + carry; |
9334 | 0 | if (newdig < 0) |
9335 | 0 | { |
9336 | 0 | carry = -((-newdig - 1) / NBASE_SQR) - 1; |
9337 | 0 | newdig -= carry * NBASE_SQR; |
9338 | 0 | } |
9339 | 0 | else if (newdig >= NBASE_SQR) |
9340 | 0 | { |
9341 | 0 | carry = newdig / NBASE_SQR; |
9342 | 0 | newdig -= carry * NBASE_SQR; |
9343 | 0 | } |
9344 | 0 | else |
9345 | 0 | carry = 0; |
9346 | 0 | remainder[i + 1] = newdig; |
9347 | 0 | } |
9348 | 0 | remainder[0] = carry; |
9349 | |
|
9350 | 0 | if (remainder[0] < 0) |
9351 | 0 | { |
9352 | | /* |
9353 | | * The remainder is negative, so the approximate quotient is too |
9354 | | * large. Correct by reducing the quotient by one and adding the |
9355 | | * divisor to the remainder until the remainder is positive. We |
9356 | | * expect the quotient to be off by at most one, which has been |
9357 | | * borne out in all testing, but not conclusively proven, so we |
9358 | | * allow for larger corrections, just in case. |
9359 | | */ |
9360 | 0 | do |
9361 | 0 | { |
9362 | | /* Add the divisor to the remainder */ |
9363 | 0 | carry = 0; |
9364 | 0 | for (i = var2ndigitpairs - 1; i > 0; i--) |
9365 | 0 | { |
9366 | 0 | newdig = remainder[i] + divisor[i] + carry; |
9367 | 0 | if (newdig >= NBASE_SQR) |
9368 | 0 | { |
9369 | 0 | remainder[i] = newdig - NBASE_SQR; |
9370 | 0 | carry = 1; |
9371 | 0 | } |
9372 | 0 | else |
9373 | 0 | { |
9374 | 0 | remainder[i] = newdig; |
9375 | 0 | carry = 0; |
9376 | 0 | } |
9377 | 0 | } |
9378 | 0 | remainder[0] += divisor[0] + carry; |
9379 | | |
9380 | | /* Subtract 1 from the quotient (propagating carries later) */ |
9381 | 0 | dividend[qi - 1]--; |
9382 | |
|
9383 | 0 | } while (remainder[0] < 0); |
9384 | 0 | } |
9385 | 0 | else |
9386 | 0 | { |
9387 | | /* |
9388 | | * The remainder is nonnegative. If it's greater than or equal to |
9389 | | * the divisor, then the approximate quotient is too small and |
9390 | | * must be corrected. As above, we don't expect to have to apply |
9391 | | * more than one correction, but allow for it just in case. |
9392 | | */ |
9393 | 0 | while (true) |
9394 | 0 | { |
9395 | 0 | bool less = false; |
9396 | | |
9397 | | /* Is remainder < divisor? */ |
9398 | 0 | for (i = 0; i < var2ndigitpairs; i++) |
9399 | 0 | { |
9400 | 0 | if (remainder[i] < divisor[i]) |
9401 | 0 | { |
9402 | 0 | less = true; |
9403 | 0 | break; |
9404 | 0 | } |
9405 | 0 | if (remainder[i] > divisor[i]) |
9406 | 0 | break; /* remainder > divisor */ |
9407 | 0 | } |
9408 | 0 | if (less) |
9409 | 0 | break; /* quotient is correct */ |
9410 | | |
9411 | | /* Subtract the divisor from the remainder */ |
9412 | 0 | carry = 0; |
9413 | 0 | for (i = var2ndigitpairs - 1; i > 0; i--) |
9414 | 0 | { |
9415 | 0 | newdig = remainder[i] - divisor[i] + carry; |
9416 | 0 | if (newdig < 0) |
9417 | 0 | { |
9418 | 0 | remainder[i] = newdig + NBASE_SQR; |
9419 | 0 | carry = -1; |
9420 | 0 | } |
9421 | 0 | else |
9422 | 0 | { |
9423 | 0 | remainder[i] = newdig; |
9424 | 0 | carry = 0; |
9425 | 0 | } |
9426 | 0 | } |
9427 | 0 | remainder[0] = remainder[0] - divisor[0] + carry; |
9428 | | |
9429 | | /* Add 1 to the quotient (propagating carries later) */ |
9430 | 0 | dividend[qi - 1]++; |
9431 | 0 | } |
9432 | 0 | } |
9433 | 0 | } |
9434 | | |
9435 | | /* |
9436 | | * Because the quotient digits were estimates that might have been off by |
9437 | | * one (and we didn't bother propagating carries when adjusting the |
9438 | | * quotient above), some quotient digits might be out of range, so do a |
9439 | | * final carry propagation pass to normalize back to base NBASE^2, and |
9440 | | * construct the base-NBASE result digits. Note that this is still done |
9441 | | * at full precision w/guard digits. |
9442 | | */ |
9443 | 0 | alloc_var(result, res_ndigits); |
9444 | 0 | res_digits = result->digits; |
9445 | 0 | carry = 0; |
9446 | 0 | for (i = res_ndigitpairs - 1; i >= 0; i--) |
9447 | 0 | { |
9448 | 0 | newdig = dividend[i] + carry; |
9449 | 0 | if (newdig < 0) |
9450 | 0 | { |
9451 | 0 | carry = -((-newdig - 1) / NBASE_SQR) - 1; |
9452 | 0 | newdig -= carry * NBASE_SQR; |
9453 | 0 | } |
9454 | 0 | else if (newdig >= NBASE_SQR) |
9455 | 0 | { |
9456 | 0 | carry = newdig / NBASE_SQR; |
9457 | 0 | newdig -= carry * NBASE_SQR; |
9458 | 0 | } |
9459 | 0 | else |
9460 | 0 | carry = 0; |
9461 | 0 | res_digits[2 * i + 1] = (NumericDigit) ((uint32) newdig % NBASE); |
9462 | 0 | res_digits[2 * i] = (NumericDigit) ((uint32) newdig / NBASE); |
9463 | 0 | } |
9464 | 0 | Assert(carry == 0); |
9465 | |
|
9466 | 0 | pfree(dividend); |
9467 | | |
9468 | | /* |
9469 | | * Finally, round or truncate the result to the requested precision. |
9470 | | */ |
9471 | 0 | result->weight = res_weight; |
9472 | 0 | result->sign = res_sign; |
9473 | | |
9474 | | /* Round or truncate to target rscale (and set result->dscale) */ |
9475 | 0 | if (round) |
9476 | 0 | round_var(result, rscale); |
9477 | 0 | else |
9478 | 0 | trunc_var(result, rscale); |
9479 | | |
9480 | | /* Strip leading and trailing zeroes */ |
9481 | 0 | strip_var(result); |
9482 | 0 | } |
9483 | | |
9484 | | |
9485 | | /* |
9486 | | * div_var_int() - |
9487 | | * |
9488 | | * Divide a numeric variable by a 32-bit integer with the specified weight. |
9489 | | * The quotient var / (ival * NBASE^ival_weight) is stored in result. |
9490 | | */ |
9491 | | static void |
9492 | | div_var_int(const NumericVar *var, int ival, int ival_weight, |
9493 | | NumericVar *result, int rscale, bool round) |
9494 | 0 | { |
9495 | 0 | NumericDigit *var_digits = var->digits; |
9496 | 0 | int var_ndigits = var->ndigits; |
9497 | 0 | int res_sign; |
9498 | 0 | int res_weight; |
9499 | 0 | int res_ndigits; |
9500 | 0 | NumericDigit *res_buf; |
9501 | 0 | NumericDigit *res_digits; |
9502 | 0 | uint32 divisor; |
9503 | 0 | int i; |
9504 | | |
9505 | | /* Guard against division by zero */ |
9506 | 0 | if (ival == 0) |
9507 | 0 | ereport(ERROR, |
9508 | 0 | errcode(ERRCODE_DIVISION_BY_ZERO), |
9509 | 0 | errmsg("division by zero")); |
9510 | | |
9511 | | /* Result zero check */ |
9512 | 0 | if (var_ndigits == 0) |
9513 | 0 | { |
9514 | 0 | zero_var(result); |
9515 | 0 | result->dscale = rscale; |
9516 | 0 | return; |
9517 | 0 | } |
9518 | | |
9519 | | /* |
9520 | | * Determine the result sign, weight and number of digits to calculate. |
9521 | | * The weight figured here is correct if the emitted quotient has no |
9522 | | * leading zero digits; otherwise strip_var() will fix things up. |
9523 | | */ |
9524 | 0 | if (var->sign == NUMERIC_POS) |
9525 | 0 | res_sign = ival > 0 ? NUMERIC_POS : NUMERIC_NEG; |
9526 | 0 | else |
9527 | 0 | res_sign = ival > 0 ? NUMERIC_NEG : NUMERIC_POS; |
9528 | 0 | res_weight = var->weight - ival_weight; |
9529 | | /* The number of accurate result digits we need to produce: */ |
9530 | 0 | res_ndigits = res_weight + 1 + (rscale + DEC_DIGITS - 1) / DEC_DIGITS; |
9531 | | /* ... but always at least 1 */ |
9532 | 0 | res_ndigits = Max(res_ndigits, 1); |
9533 | | /* If rounding needed, figure one more digit to ensure correct result */ |
9534 | 0 | if (round) |
9535 | 0 | res_ndigits++; |
9536 | |
|
9537 | 0 | res_buf = digitbuf_alloc(res_ndigits + 1); |
9538 | 0 | res_buf[0] = 0; /* spare digit for later rounding */ |
9539 | 0 | res_digits = res_buf + 1; |
9540 | | |
9541 | | /* |
9542 | | * Now compute the quotient digits. This is the short division algorithm |
9543 | | * described in Knuth volume 2, section 4.3.1 exercise 16, except that we |
9544 | | * allow the divisor to exceed the internal base. |
9545 | | * |
9546 | | * In this algorithm, the carry from one digit to the next is at most |
9547 | | * divisor - 1. Therefore, while processing the next digit, carry may |
9548 | | * become as large as divisor * NBASE - 1, and so it requires a 64-bit |
9549 | | * integer if this exceeds UINT_MAX. |
9550 | | */ |
9551 | 0 | divisor = abs(ival); |
9552 | |
|
9553 | 0 | if (divisor <= UINT_MAX / NBASE) |
9554 | 0 | { |
9555 | | /* carry cannot overflow 32 bits */ |
9556 | 0 | uint32 carry = 0; |
9557 | |
|
9558 | 0 | for (i = 0; i < res_ndigits; i++) |
9559 | 0 | { |
9560 | 0 | carry = carry * NBASE + (i < var_ndigits ? var_digits[i] : 0); |
9561 | 0 | res_digits[i] = (NumericDigit) (carry / divisor); |
9562 | 0 | carry = carry % divisor; |
9563 | 0 | } |
9564 | 0 | } |
9565 | 0 | else |
9566 | 0 | { |
9567 | | /* carry may exceed 32 bits */ |
9568 | 0 | uint64 carry = 0; |
9569 | |
|
9570 | 0 | for (i = 0; i < res_ndigits; i++) |
9571 | 0 | { |
9572 | 0 | carry = carry * NBASE + (i < var_ndigits ? var_digits[i] : 0); |
9573 | 0 | res_digits[i] = (NumericDigit) (carry / divisor); |
9574 | 0 | carry = carry % divisor; |
9575 | 0 | } |
9576 | 0 | } |
9577 | | |
9578 | | /* Store the quotient in result */ |
9579 | 0 | digitbuf_free(result->buf); |
9580 | 0 | result->ndigits = res_ndigits; |
9581 | 0 | result->buf = res_buf; |
9582 | 0 | result->digits = res_digits; |
9583 | 0 | result->weight = res_weight; |
9584 | 0 | result->sign = res_sign; |
9585 | | |
9586 | | /* Round or truncate to target rscale (and set result->dscale) */ |
9587 | 0 | if (round) |
9588 | 0 | round_var(result, rscale); |
9589 | 0 | else |
9590 | 0 | trunc_var(result, rscale); |
9591 | | |
9592 | | /* Strip leading/trailing zeroes */ |
9593 | 0 | strip_var(result); |
9594 | 0 | } |
9595 | | |
9596 | | |
9597 | | #ifdef HAVE_INT128 |
9598 | | /* |
9599 | | * div_var_int64() - |
9600 | | * |
9601 | | * Divide a numeric variable by a 64-bit integer with the specified weight. |
9602 | | * The quotient var / (ival * NBASE^ival_weight) is stored in result. |
9603 | | * |
9604 | | * This duplicates the logic in div_var_int(), so any changes made there |
9605 | | * should be made here too. |
9606 | | */ |
9607 | | static void |
9608 | | div_var_int64(const NumericVar *var, int64 ival, int ival_weight, |
9609 | | NumericVar *result, int rscale, bool round) |
9610 | 0 | { |
9611 | 0 | NumericDigit *var_digits = var->digits; |
9612 | 0 | int var_ndigits = var->ndigits; |
9613 | 0 | int res_sign; |
9614 | 0 | int res_weight; |
9615 | 0 | int res_ndigits; |
9616 | 0 | NumericDigit *res_buf; |
9617 | 0 | NumericDigit *res_digits; |
9618 | 0 | uint64 divisor; |
9619 | 0 | int i; |
9620 | | |
9621 | | /* Guard against division by zero */ |
9622 | 0 | if (ival == 0) |
9623 | 0 | ereport(ERROR, |
9624 | 0 | errcode(ERRCODE_DIVISION_BY_ZERO), |
9625 | 0 | errmsg("division by zero")); |
9626 | | |
9627 | | /* Result zero check */ |
9628 | 0 | if (var_ndigits == 0) |
9629 | 0 | { |
9630 | 0 | zero_var(result); |
9631 | 0 | result->dscale = rscale; |
9632 | 0 | return; |
9633 | 0 | } |
9634 | | |
9635 | | /* |
9636 | | * Determine the result sign, weight and number of digits to calculate. |
9637 | | * The weight figured here is correct if the emitted quotient has no |
9638 | | * leading zero digits; otherwise strip_var() will fix things up. |
9639 | | */ |
9640 | 0 | if (var->sign == NUMERIC_POS) |
9641 | 0 | res_sign = ival > 0 ? NUMERIC_POS : NUMERIC_NEG; |
9642 | 0 | else |
9643 | 0 | res_sign = ival > 0 ? NUMERIC_NEG : NUMERIC_POS; |
9644 | 0 | res_weight = var->weight - ival_weight; |
9645 | | /* The number of accurate result digits we need to produce: */ |
9646 | 0 | res_ndigits = res_weight + 1 + (rscale + DEC_DIGITS - 1) / DEC_DIGITS; |
9647 | | /* ... but always at least 1 */ |
9648 | 0 | res_ndigits = Max(res_ndigits, 1); |
9649 | | /* If rounding needed, figure one more digit to ensure correct result */ |
9650 | 0 | if (round) |
9651 | 0 | res_ndigits++; |
9652 | |
|
9653 | 0 | res_buf = digitbuf_alloc(res_ndigits + 1); |
9654 | 0 | res_buf[0] = 0; /* spare digit for later rounding */ |
9655 | 0 | res_digits = res_buf + 1; |
9656 | | |
9657 | | /* |
9658 | | * Now compute the quotient digits. This is the short division algorithm |
9659 | | * described in Knuth volume 2, section 4.3.1 exercise 16, except that we |
9660 | | * allow the divisor to exceed the internal base. |
9661 | | * |
9662 | | * In this algorithm, the carry from one digit to the next is at most |
9663 | | * divisor - 1. Therefore, while processing the next digit, carry may |
9664 | | * become as large as divisor * NBASE - 1, and so it requires a 128-bit |
9665 | | * integer if this exceeds PG_UINT64_MAX. |
9666 | | */ |
9667 | 0 | divisor = i64abs(ival); |
9668 | |
|
9669 | 0 | if (divisor <= PG_UINT64_MAX / NBASE) |
9670 | 0 | { |
9671 | | /* carry cannot overflow 64 bits */ |
9672 | 0 | uint64 carry = 0; |
9673 | |
|
9674 | 0 | for (i = 0; i < res_ndigits; i++) |
9675 | 0 | { |
9676 | 0 | carry = carry * NBASE + (i < var_ndigits ? var_digits[i] : 0); |
9677 | 0 | res_digits[i] = (NumericDigit) (carry / divisor); |
9678 | 0 | carry = carry % divisor; |
9679 | 0 | } |
9680 | 0 | } |
9681 | 0 | else |
9682 | 0 | { |
9683 | | /* carry may exceed 64 bits */ |
9684 | 0 | uint128 carry = 0; |
9685 | |
|
9686 | 0 | for (i = 0; i < res_ndigits; i++) |
9687 | 0 | { |
9688 | 0 | carry = carry * NBASE + (i < var_ndigits ? var_digits[i] : 0); |
9689 | 0 | res_digits[i] = (NumericDigit) (carry / divisor); |
9690 | 0 | carry = carry % divisor; |
9691 | 0 | } |
9692 | 0 | } |
9693 | | |
9694 | | /* Store the quotient in result */ |
9695 | 0 | digitbuf_free(result->buf); |
9696 | 0 | result->ndigits = res_ndigits; |
9697 | 0 | result->buf = res_buf; |
9698 | 0 | result->digits = res_digits; |
9699 | 0 | result->weight = res_weight; |
9700 | 0 | result->sign = res_sign; |
9701 | | |
9702 | | /* Round or truncate to target rscale (and set result->dscale) */ |
9703 | 0 | if (round) |
9704 | 0 | round_var(result, rscale); |
9705 | 0 | else |
9706 | 0 | trunc_var(result, rscale); |
9707 | | |
9708 | | /* Strip leading/trailing zeroes */ |
9709 | 0 | strip_var(result); |
9710 | 0 | } |
9711 | | #endif |
9712 | | |
9713 | | |
9714 | | /* |
9715 | | * Default scale selection for division |
9716 | | * |
9717 | | * Returns the appropriate result scale for the division result. |
9718 | | */ |
9719 | | static int |
9720 | | select_div_scale(const NumericVar *var1, const NumericVar *var2) |
9721 | 0 | { |
9722 | 0 | int weight1, |
9723 | 0 | weight2, |
9724 | 0 | qweight, |
9725 | 0 | i; |
9726 | 0 | NumericDigit firstdigit1, |
9727 | 0 | firstdigit2; |
9728 | 0 | int rscale; |
9729 | | |
9730 | | /* |
9731 | | * The result scale of a division isn't specified in any SQL standard. For |
9732 | | * PostgreSQL we select a result scale that will give at least |
9733 | | * NUMERIC_MIN_SIG_DIGITS significant digits, so that numeric gives a |
9734 | | * result no less accurate than float8; but use a scale not less than |
9735 | | * either input's display scale. |
9736 | | */ |
9737 | | |
9738 | | /* Get the actual (normalized) weight and first digit of each input */ |
9739 | |
|
9740 | 0 | weight1 = 0; /* values to use if var1 is zero */ |
9741 | 0 | firstdigit1 = 0; |
9742 | 0 | for (i = 0; i < var1->ndigits; i++) |
9743 | 0 | { |
9744 | 0 | firstdigit1 = var1->digits[i]; |
9745 | 0 | if (firstdigit1 != 0) |
9746 | 0 | { |
9747 | 0 | weight1 = var1->weight - i; |
9748 | 0 | break; |
9749 | 0 | } |
9750 | 0 | } |
9751 | |
|
9752 | 0 | weight2 = 0; /* values to use if var2 is zero */ |
9753 | 0 | firstdigit2 = 0; |
9754 | 0 | for (i = 0; i < var2->ndigits; i++) |
9755 | 0 | { |
9756 | 0 | firstdigit2 = var2->digits[i]; |
9757 | 0 | if (firstdigit2 != 0) |
9758 | 0 | { |
9759 | 0 | weight2 = var2->weight - i; |
9760 | 0 | break; |
9761 | 0 | } |
9762 | 0 | } |
9763 | | |
9764 | | /* |
9765 | | * Estimate weight of quotient. If the two first digits are equal, we |
9766 | | * can't be sure, but assume that var1 is less than var2. |
9767 | | */ |
9768 | 0 | qweight = weight1 - weight2; |
9769 | 0 | if (firstdigit1 <= firstdigit2) |
9770 | 0 | qweight--; |
9771 | | |
9772 | | /* Select result scale */ |
9773 | 0 | rscale = NUMERIC_MIN_SIG_DIGITS - qweight * DEC_DIGITS; |
9774 | 0 | rscale = Max(rscale, var1->dscale); |
9775 | 0 | rscale = Max(rscale, var2->dscale); |
9776 | 0 | rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE); |
9777 | 0 | rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE); |
9778 | |
|
9779 | 0 | return rscale; |
9780 | 0 | } |
9781 | | |
9782 | | |
9783 | | /* |
9784 | | * mod_var() - |
9785 | | * |
9786 | | * Calculate the modulo of two numerics at variable level |
9787 | | */ |
9788 | | static void |
9789 | | mod_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result) |
9790 | 0 | { |
9791 | 0 | NumericVar tmp; |
9792 | |
|
9793 | 0 | init_var(&tmp); |
9794 | | |
9795 | | /* --------- |
9796 | | * We do this using the equation |
9797 | | * mod(x,y) = x - trunc(x/y)*y |
9798 | | * div_var can be persuaded to give us trunc(x/y) directly. |
9799 | | * ---------- |
9800 | | */ |
9801 | 0 | div_var(var1, var2, &tmp, 0, false, true); |
9802 | |
|
9803 | 0 | mul_var(var2, &tmp, &tmp, var2->dscale); |
9804 | |
|
9805 | 0 | sub_var(var1, &tmp, result); |
9806 | |
|
9807 | 0 | free_var(&tmp); |
9808 | 0 | } |
9809 | | |
9810 | | |
9811 | | /* |
9812 | | * div_mod_var() - |
9813 | | * |
9814 | | * Calculate the truncated integer quotient and numeric remainder of two |
9815 | | * numeric variables. The remainder is precise to var2's dscale. |
9816 | | */ |
9817 | | static void |
9818 | | div_mod_var(const NumericVar *var1, const NumericVar *var2, |
9819 | | NumericVar *quot, NumericVar *rem) |
9820 | 0 | { |
9821 | 0 | NumericVar q; |
9822 | 0 | NumericVar r; |
9823 | |
|
9824 | 0 | init_var(&q); |
9825 | 0 | init_var(&r); |
9826 | | |
9827 | | /* |
9828 | | * Use div_var() with exact = false to get an initial estimate for the |
9829 | | * integer quotient (truncated towards zero). This might be slightly |
9830 | | * inaccurate, but we correct it below. |
9831 | | */ |
9832 | 0 | div_var(var1, var2, &q, 0, false, false); |
9833 | | |
9834 | | /* Compute initial estimate of remainder using the quotient estimate. */ |
9835 | 0 | mul_var(var2, &q, &r, var2->dscale); |
9836 | 0 | sub_var(var1, &r, &r); |
9837 | | |
9838 | | /* |
9839 | | * Adjust the results if necessary --- the remainder should have the same |
9840 | | * sign as var1, and its absolute value should be less than the absolute |
9841 | | * value of var2. |
9842 | | */ |
9843 | 0 | while (r.ndigits != 0 && r.sign != var1->sign) |
9844 | 0 | { |
9845 | | /* The absolute value of the quotient is too large */ |
9846 | 0 | if (var1->sign == var2->sign) |
9847 | 0 | { |
9848 | 0 | sub_var(&q, &const_one, &q); |
9849 | 0 | add_var(&r, var2, &r); |
9850 | 0 | } |
9851 | 0 | else |
9852 | 0 | { |
9853 | 0 | add_var(&q, &const_one, &q); |
9854 | 0 | sub_var(&r, var2, &r); |
9855 | 0 | } |
9856 | 0 | } |
9857 | |
|
9858 | 0 | while (cmp_abs(&r, var2) >= 0) |
9859 | 0 | { |
9860 | | /* The absolute value of the quotient is too small */ |
9861 | 0 | if (var1->sign == var2->sign) |
9862 | 0 | { |
9863 | 0 | add_var(&q, &const_one, &q); |
9864 | 0 | sub_var(&r, var2, &r); |
9865 | 0 | } |
9866 | 0 | else |
9867 | 0 | { |
9868 | 0 | sub_var(&q, &const_one, &q); |
9869 | 0 | add_var(&r, var2, &r); |
9870 | 0 | } |
9871 | 0 | } |
9872 | |
|
9873 | 0 | set_var_from_var(&q, quot); |
9874 | 0 | set_var_from_var(&r, rem); |
9875 | |
|
9876 | 0 | free_var(&q); |
9877 | 0 | free_var(&r); |
9878 | 0 | } |
9879 | | |
9880 | | |
9881 | | /* |
9882 | | * ceil_var() - |
9883 | | * |
9884 | | * Return the smallest integer greater than or equal to the argument |
9885 | | * on variable level |
9886 | | */ |
9887 | | static void |
9888 | | ceil_var(const NumericVar *var, NumericVar *result) |
9889 | 0 | { |
9890 | 0 | NumericVar tmp; |
9891 | |
|
9892 | 0 | init_var(&tmp); |
9893 | 0 | set_var_from_var(var, &tmp); |
9894 | |
|
9895 | 0 | trunc_var(&tmp, 0); |
9896 | |
|
9897 | 0 | if (var->sign == NUMERIC_POS && cmp_var(var, &tmp) != 0) |
9898 | 0 | add_var(&tmp, &const_one, &tmp); |
9899 | |
|
9900 | 0 | set_var_from_var(&tmp, result); |
9901 | 0 | free_var(&tmp); |
9902 | 0 | } |
9903 | | |
9904 | | |
9905 | | /* |
9906 | | * floor_var() - |
9907 | | * |
9908 | | * Return the largest integer equal to or less than the argument |
9909 | | * on variable level |
9910 | | */ |
9911 | | static void |
9912 | | floor_var(const NumericVar *var, NumericVar *result) |
9913 | 0 | { |
9914 | 0 | NumericVar tmp; |
9915 | |
|
9916 | 0 | init_var(&tmp); |
9917 | 0 | set_var_from_var(var, &tmp); |
9918 | |
|
9919 | 0 | trunc_var(&tmp, 0); |
9920 | |
|
9921 | 0 | if (var->sign == NUMERIC_NEG && cmp_var(var, &tmp) != 0) |
9922 | 0 | sub_var(&tmp, &const_one, &tmp); |
9923 | |
|
9924 | 0 | set_var_from_var(&tmp, result); |
9925 | 0 | free_var(&tmp); |
9926 | 0 | } |
9927 | | |
9928 | | |
9929 | | /* |
9930 | | * gcd_var() - |
9931 | | * |
9932 | | * Calculate the greatest common divisor of two numerics at variable level |
9933 | | */ |
9934 | | static void |
9935 | | gcd_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result) |
9936 | 0 | { |
9937 | 0 | int res_dscale; |
9938 | 0 | int cmp; |
9939 | 0 | NumericVar tmp_arg; |
9940 | 0 | NumericVar mod; |
9941 | |
|
9942 | 0 | res_dscale = Max(var1->dscale, var2->dscale); |
9943 | | |
9944 | | /* |
9945 | | * Arrange for var1 to be the number with the greater absolute value. |
9946 | | * |
9947 | | * This would happen automatically in the loop below, but avoids an |
9948 | | * expensive modulo operation. |
9949 | | */ |
9950 | 0 | cmp = cmp_abs(var1, var2); |
9951 | 0 | if (cmp < 0) |
9952 | 0 | { |
9953 | 0 | const NumericVar *tmp = var1; |
9954 | |
|
9955 | 0 | var1 = var2; |
9956 | 0 | var2 = tmp; |
9957 | 0 | } |
9958 | | |
9959 | | /* |
9960 | | * Also avoid the taking the modulo if the inputs have the same absolute |
9961 | | * value, or if the smaller input is zero. |
9962 | | */ |
9963 | 0 | if (cmp == 0 || var2->ndigits == 0) |
9964 | 0 | { |
9965 | 0 | set_var_from_var(var1, result); |
9966 | 0 | result->sign = NUMERIC_POS; |
9967 | 0 | result->dscale = res_dscale; |
9968 | 0 | return; |
9969 | 0 | } |
9970 | | |
9971 | 0 | init_var(&tmp_arg); |
9972 | 0 | init_var(&mod); |
9973 | | |
9974 | | /* Use the Euclidean algorithm to find the GCD */ |
9975 | 0 | set_var_from_var(var1, &tmp_arg); |
9976 | 0 | set_var_from_var(var2, result); |
9977 | |
|
9978 | 0 | for (;;) |
9979 | 0 | { |
9980 | | /* this loop can take a while, so allow it to be interrupted */ |
9981 | 0 | CHECK_FOR_INTERRUPTS(); |
9982 | |
|
9983 | 0 | mod_var(&tmp_arg, result, &mod); |
9984 | 0 | if (mod.ndigits == 0) |
9985 | 0 | break; |
9986 | 0 | set_var_from_var(result, &tmp_arg); |
9987 | 0 | set_var_from_var(&mod, result); |
9988 | 0 | } |
9989 | 0 | result->sign = NUMERIC_POS; |
9990 | 0 | result->dscale = res_dscale; |
9991 | |
|
9992 | 0 | free_var(&tmp_arg); |
9993 | 0 | free_var(&mod); |
9994 | 0 | } |
9995 | | |
9996 | | |
9997 | | /* |
9998 | | * sqrt_var() - |
9999 | | * |
10000 | | * Compute the square root of x using the Karatsuba Square Root algorithm. |
10001 | | * NOTE: we allow rscale < 0 here, implying rounding before the decimal |
10002 | | * point. |
10003 | | */ |
10004 | | static void |
10005 | | sqrt_var(const NumericVar *arg, NumericVar *result, int rscale) |
10006 | 0 | { |
10007 | 0 | int stat; |
10008 | 0 | int res_weight; |
10009 | 0 | int res_ndigits; |
10010 | 0 | int src_ndigits; |
10011 | 0 | int step; |
10012 | 0 | int ndigits[32]; |
10013 | 0 | int blen; |
10014 | 0 | int64 arg_int64; |
10015 | 0 | int src_idx; |
10016 | 0 | int64 s_int64; |
10017 | 0 | int64 r_int64; |
10018 | 0 | NumericVar s_var; |
10019 | 0 | NumericVar r_var; |
10020 | 0 | NumericVar a0_var; |
10021 | 0 | NumericVar a1_var; |
10022 | 0 | NumericVar q_var; |
10023 | 0 | NumericVar u_var; |
10024 | |
|
10025 | 0 | stat = cmp_var(arg, &const_zero); |
10026 | 0 | if (stat == 0) |
10027 | 0 | { |
10028 | 0 | zero_var(result); |
10029 | 0 | result->dscale = rscale; |
10030 | 0 | return; |
10031 | 0 | } |
10032 | | |
10033 | | /* |
10034 | | * SQL2003 defines sqrt() in terms of power, so we need to emit the right |
10035 | | * SQLSTATE error code if the operand is negative. |
10036 | | */ |
10037 | 0 | if (stat < 0) |
10038 | 0 | ereport(ERROR, |
10039 | 0 | (errcode(ERRCODE_INVALID_ARGUMENT_FOR_POWER_FUNCTION), |
10040 | 0 | errmsg("cannot take square root of a negative number"))); |
10041 | | |
10042 | 0 | init_var(&s_var); |
10043 | 0 | init_var(&r_var); |
10044 | 0 | init_var(&a0_var); |
10045 | 0 | init_var(&a1_var); |
10046 | 0 | init_var(&q_var); |
10047 | 0 | init_var(&u_var); |
10048 | | |
10049 | | /* |
10050 | | * The result weight is half the input weight, rounded towards minus |
10051 | | * infinity --- res_weight = floor(arg->weight / 2). |
10052 | | */ |
10053 | 0 | if (arg->weight >= 0) |
10054 | 0 | res_weight = arg->weight / 2; |
10055 | 0 | else |
10056 | 0 | res_weight = -((-arg->weight - 1) / 2 + 1); |
10057 | | |
10058 | | /* |
10059 | | * Number of NBASE digits to compute. To ensure correct rounding, compute |
10060 | | * at least 1 extra decimal digit. We explicitly allow rscale to be |
10061 | | * negative here, but must always compute at least 1 NBASE digit. Thus |
10062 | | * res_ndigits = res_weight + 1 + ceil((rscale + 1) / DEC_DIGITS) or 1. |
10063 | | */ |
10064 | 0 | if (rscale + 1 >= 0) |
10065 | 0 | res_ndigits = res_weight + 1 + (rscale + DEC_DIGITS) / DEC_DIGITS; |
10066 | 0 | else |
10067 | 0 | res_ndigits = res_weight + 1 - (-rscale - 1) / DEC_DIGITS; |
10068 | 0 | res_ndigits = Max(res_ndigits, 1); |
10069 | | |
10070 | | /* |
10071 | | * Number of source NBASE digits logically required to produce a result |
10072 | | * with this precision --- every digit before the decimal point, plus 2 |
10073 | | * for each result digit after the decimal point (or minus 2 for each |
10074 | | * result digit we round before the decimal point). |
10075 | | */ |
10076 | 0 | src_ndigits = arg->weight + 1 + (res_ndigits - res_weight - 1) * 2; |
10077 | 0 | src_ndigits = Max(src_ndigits, 1); |
10078 | | |
10079 | | /* ---------- |
10080 | | * From this point on, we treat the input and the result as integers and |
10081 | | * compute the integer square root and remainder using the Karatsuba |
10082 | | * Square Root algorithm, which may be written recursively as follows: |
10083 | | * |
10084 | | * SqrtRem(n = a3*b^3 + a2*b^2 + a1*b + a0): |
10085 | | * [ for some base b, and coefficients a0,a1,a2,a3 chosen so that |
10086 | | * 0 <= a0,a1,a2 < b and a3 >= b/4 ] |
10087 | | * Let (s,r) = SqrtRem(a3*b + a2) |
10088 | | * Let (q,u) = DivRem(r*b + a1, 2*s) |
10089 | | * Let s = s*b + q |
10090 | | * Let r = u*b + a0 - q^2 |
10091 | | * If r < 0 Then |
10092 | | * Let r = r + s |
10093 | | * Let s = s - 1 |
10094 | | * Let r = r + s |
10095 | | * Return (s,r) |
10096 | | * |
10097 | | * See "Karatsuba Square Root", Paul Zimmermann, INRIA Research Report |
10098 | | * RR-3805, November 1999. At the time of writing this was available |
10099 | | * on the net at <https://hal.inria.fr/inria-00072854>. |
10100 | | * |
10101 | | * The way to read the assumption "n = a3*b^3 + a2*b^2 + a1*b + a0" is |
10102 | | * "choose a base b such that n requires at least four base-b digits to |
10103 | | * express; then those digits are a3,a2,a1,a0, with a3 possibly larger |
10104 | | * than b". For optimal performance, b should have approximately a |
10105 | | * quarter the number of digits in the input, so that the outer square |
10106 | | * root computes roughly twice as many digits as the inner one. For |
10107 | | * simplicity, we choose b = NBASE^blen, an integer power of NBASE. |
10108 | | * |
10109 | | * We implement the algorithm iteratively rather than recursively, to |
10110 | | * allow the working variables to be reused. With this approach, each |
10111 | | * digit of the input is read precisely once --- src_idx tracks the number |
10112 | | * of input digits used so far. |
10113 | | * |
10114 | | * The array ndigits[] holds the number of NBASE digits of the input that |
10115 | | * will have been used at the end of each iteration, which roughly doubles |
10116 | | * each time. Note that the array elements are stored in reverse order, |
10117 | | * so if the final iteration requires src_ndigits = 37 input digits, the |
10118 | | * array will contain [37,19,11,7,5,3], and we would start by computing |
10119 | | * the square root of the 3 most significant NBASE digits. |
10120 | | * |
10121 | | * In each iteration, we choose blen to be the largest integer for which |
10122 | | * the input number has a3 >= b/4, when written in the form above. In |
10123 | | * general, this means blen = src_ndigits / 4 (truncated), but if |
10124 | | * src_ndigits is a multiple of 4, that might lead to the coefficient a3 |
10125 | | * being less than b/4 (if the first input digit is less than NBASE/4), in |
10126 | | * which case we choose blen = src_ndigits / 4 - 1. The number of digits |
10127 | | * in the inner square root is then src_ndigits - 2*blen. So, for |
10128 | | * example, if we have src_ndigits = 26 initially, the array ndigits[] |
10129 | | * will be either [26,14,8,4] or [26,14,8,6,4], depending on the size of |
10130 | | * the first input digit. |
10131 | | * |
10132 | | * Additionally, we can put an upper bound on the number of steps required |
10133 | | * as follows --- suppose that the number of source digits is an n-bit |
10134 | | * number in the range [2^(n-1), 2^n-1], then blen will be in the range |
10135 | | * [2^(n-3)-1, 2^(n-2)-1] and the number of digits in the inner square |
10136 | | * root will be in the range [2^(n-2), 2^(n-1)+1]. In the next step, blen |
10137 | | * will be in the range [2^(n-4)-1, 2^(n-3)] and the number of digits in |
10138 | | * the next inner square root will be in the range [2^(n-3), 2^(n-2)+1]. |
10139 | | * This pattern repeats, and in the worst case the array ndigits[] will |
10140 | | * contain [2^n-1, 2^(n-1)+1, 2^(n-2)+1, ... 9, 5, 3], and the computation |
10141 | | * will require n steps. Therefore, since all digit array sizes are |
10142 | | * signed 32-bit integers, the number of steps required is guaranteed to |
10143 | | * be less than 32. |
10144 | | * ---------- |
10145 | | */ |
10146 | 0 | step = 0; |
10147 | 0 | while ((ndigits[step] = src_ndigits) > 4) |
10148 | 0 | { |
10149 | | /* Choose b so that a3 >= b/4, as described above */ |
10150 | 0 | blen = src_ndigits / 4; |
10151 | 0 | if (blen * 4 == src_ndigits && arg->digits[0] < NBASE / 4) |
10152 | 0 | blen--; |
10153 | | |
10154 | | /* Number of digits in the next step (inner square root) */ |
10155 | 0 | src_ndigits -= 2 * blen; |
10156 | 0 | step++; |
10157 | 0 | } |
10158 | | |
10159 | | /* |
10160 | | * First iteration (innermost square root and remainder): |
10161 | | * |
10162 | | * Here src_ndigits <= 4, and the input fits in an int64. Its square root |
10163 | | * has at most 9 decimal digits, so estimate it using double precision |
10164 | | * arithmetic, which will in fact almost certainly return the correct |
10165 | | * result with no further correction required. |
10166 | | */ |
10167 | 0 | arg_int64 = arg->digits[0]; |
10168 | 0 | for (src_idx = 1; src_idx < src_ndigits; src_idx++) |
10169 | 0 | { |
10170 | 0 | arg_int64 *= NBASE; |
10171 | 0 | if (src_idx < arg->ndigits) |
10172 | 0 | arg_int64 += arg->digits[src_idx]; |
10173 | 0 | } |
10174 | |
|
10175 | 0 | s_int64 = (int64) sqrt((double) arg_int64); |
10176 | 0 | r_int64 = arg_int64 - s_int64 * s_int64; |
10177 | | |
10178 | | /* |
10179 | | * Use Newton's method to correct the result, if necessary. |
10180 | | * |
10181 | | * This uses integer division with truncation to compute the truncated |
10182 | | * integer square root by iterating using the formula x -> (x + n/x) / 2. |
10183 | | * This is known to converge to isqrt(n), unless n+1 is a perfect square. |
10184 | | * If n+1 is a perfect square, the sequence will oscillate between the two |
10185 | | * values isqrt(n) and isqrt(n)+1, so we can be assured of convergence by |
10186 | | * checking the remainder. |
10187 | | */ |
10188 | 0 | while (r_int64 < 0 || r_int64 > 2 * s_int64) |
10189 | 0 | { |
10190 | 0 | s_int64 = (s_int64 + arg_int64 / s_int64) / 2; |
10191 | 0 | r_int64 = arg_int64 - s_int64 * s_int64; |
10192 | 0 | } |
10193 | | |
10194 | | /* |
10195 | | * Iterations with src_ndigits <= 8: |
10196 | | * |
10197 | | * The next 1 or 2 iterations compute larger (outer) square roots with |
10198 | | * src_ndigits <= 8, so the result still fits in an int64 (even though the |
10199 | | * input no longer does) and we can continue to compute using int64 |
10200 | | * variables to avoid more expensive numeric computations. |
10201 | | * |
10202 | | * It is fairly easy to see that there is no risk of the intermediate |
10203 | | * values below overflowing 64-bit integers. In the worst case, the |
10204 | | * previous iteration will have computed a 3-digit square root (of a |
10205 | | * 6-digit input less than NBASE^6 / 4), so at the start of this |
10206 | | * iteration, s will be less than NBASE^3 / 2 = 10^12 / 2, and r will be |
10207 | | * less than 10^12. In this case, blen will be 1, so numer will be less |
10208 | | * than 10^17, and denom will be less than 10^12 (and hence u will also be |
10209 | | * less than 10^12). Finally, since q^2 = u*b + a0 - r, we can also be |
10210 | | * sure that q^2 < 10^17. Therefore all these quantities fit comfortably |
10211 | | * in 64-bit integers. |
10212 | | */ |
10213 | 0 | step--; |
10214 | 0 | while (step >= 0 && (src_ndigits = ndigits[step]) <= 8) |
10215 | 0 | { |
10216 | 0 | int b; |
10217 | 0 | int a0; |
10218 | 0 | int a1; |
10219 | 0 | int i; |
10220 | 0 | int64 numer; |
10221 | 0 | int64 denom; |
10222 | 0 | int64 q; |
10223 | 0 | int64 u; |
10224 | |
|
10225 | 0 | blen = (src_ndigits - src_idx) / 2; |
10226 | | |
10227 | | /* Extract a1 and a0, and compute b */ |
10228 | 0 | a0 = 0; |
10229 | 0 | a1 = 0; |
10230 | 0 | b = 1; |
10231 | |
|
10232 | 0 | for (i = 0; i < blen; i++, src_idx++) |
10233 | 0 | { |
10234 | 0 | b *= NBASE; |
10235 | 0 | a1 *= NBASE; |
10236 | 0 | if (src_idx < arg->ndigits) |
10237 | 0 | a1 += arg->digits[src_idx]; |
10238 | 0 | } |
10239 | |
|
10240 | 0 | for (i = 0; i < blen; i++, src_idx++) |
10241 | 0 | { |
10242 | 0 | a0 *= NBASE; |
10243 | 0 | if (src_idx < arg->ndigits) |
10244 | 0 | a0 += arg->digits[src_idx]; |
10245 | 0 | } |
10246 | | |
10247 | | /* Compute (q,u) = DivRem(r*b + a1, 2*s) */ |
10248 | 0 | numer = r_int64 * b + a1; |
10249 | 0 | denom = 2 * s_int64; |
10250 | 0 | q = numer / denom; |
10251 | 0 | u = numer - q * denom; |
10252 | | |
10253 | | /* Compute s = s*b + q and r = u*b + a0 - q^2 */ |
10254 | 0 | s_int64 = s_int64 * b + q; |
10255 | 0 | r_int64 = u * b + a0 - q * q; |
10256 | |
|
10257 | 0 | if (r_int64 < 0) |
10258 | 0 | { |
10259 | | /* s is too large by 1; set r += s, s--, r += s */ |
10260 | 0 | r_int64 += s_int64; |
10261 | 0 | s_int64--; |
10262 | 0 | r_int64 += s_int64; |
10263 | 0 | } |
10264 | |
|
10265 | 0 | Assert(src_idx == src_ndigits); /* All input digits consumed */ |
10266 | 0 | step--; |
10267 | 0 | } |
10268 | | |
10269 | | /* |
10270 | | * On platforms with 128-bit integer support, we can further delay the |
10271 | | * need to use numeric variables. |
10272 | | */ |
10273 | 0 | #ifdef HAVE_INT128 |
10274 | 0 | if (step >= 0) |
10275 | 0 | { |
10276 | 0 | int128 s_int128; |
10277 | 0 | int128 r_int128; |
10278 | |
|
10279 | 0 | s_int128 = s_int64; |
10280 | 0 | r_int128 = r_int64; |
10281 | | |
10282 | | /* |
10283 | | * Iterations with src_ndigits <= 16: |
10284 | | * |
10285 | | * The result fits in an int128 (even though the input doesn't) so we |
10286 | | * use int128 variables to avoid more expensive numeric computations. |
10287 | | */ |
10288 | 0 | while (step >= 0 && (src_ndigits = ndigits[step]) <= 16) |
10289 | 0 | { |
10290 | 0 | int64 b; |
10291 | 0 | int64 a0; |
10292 | 0 | int64 a1; |
10293 | 0 | int64 i; |
10294 | 0 | int128 numer; |
10295 | 0 | int128 denom; |
10296 | 0 | int128 q; |
10297 | 0 | int128 u; |
10298 | |
|
10299 | 0 | blen = (src_ndigits - src_idx) / 2; |
10300 | | |
10301 | | /* Extract a1 and a0, and compute b */ |
10302 | 0 | a0 = 0; |
10303 | 0 | a1 = 0; |
10304 | 0 | b = 1; |
10305 | |
|
10306 | 0 | for (i = 0; i < blen; i++, src_idx++) |
10307 | 0 | { |
10308 | 0 | b *= NBASE; |
10309 | 0 | a1 *= NBASE; |
10310 | 0 | if (src_idx < arg->ndigits) |
10311 | 0 | a1 += arg->digits[src_idx]; |
10312 | 0 | } |
10313 | |
|
10314 | 0 | for (i = 0; i < blen; i++, src_idx++) |
10315 | 0 | { |
10316 | 0 | a0 *= NBASE; |
10317 | 0 | if (src_idx < arg->ndigits) |
10318 | 0 | a0 += arg->digits[src_idx]; |
10319 | 0 | } |
10320 | | |
10321 | | /* Compute (q,u) = DivRem(r*b + a1, 2*s) */ |
10322 | 0 | numer = r_int128 * b + a1; |
10323 | 0 | denom = 2 * s_int128; |
10324 | 0 | q = numer / denom; |
10325 | 0 | u = numer - q * denom; |
10326 | | |
10327 | | /* Compute s = s*b + q and r = u*b + a0 - q^2 */ |
10328 | 0 | s_int128 = s_int128 * b + q; |
10329 | 0 | r_int128 = u * b + a0 - q * q; |
10330 | |
|
10331 | 0 | if (r_int128 < 0) |
10332 | 0 | { |
10333 | | /* s is too large by 1; set r += s, s--, r += s */ |
10334 | 0 | r_int128 += s_int128; |
10335 | 0 | s_int128--; |
10336 | 0 | r_int128 += s_int128; |
10337 | 0 | } |
10338 | |
|
10339 | 0 | Assert(src_idx == src_ndigits); /* All input digits consumed */ |
10340 | 0 | step--; |
10341 | 0 | } |
10342 | | |
10343 | | /* |
10344 | | * All remaining iterations require numeric variables. Convert the |
10345 | | * integer values to NumericVar and continue. Note that in the final |
10346 | | * iteration we don't need the remainder, so we can save a few cycles |
10347 | | * there by not fully computing it. |
10348 | | */ |
10349 | 0 | int128_to_numericvar(s_int128, &s_var); |
10350 | 0 | if (step >= 0) |
10351 | 0 | int128_to_numericvar(r_int128, &r_var); |
10352 | 0 | } |
10353 | 0 | else |
10354 | 0 | { |
10355 | 0 | int64_to_numericvar(s_int64, &s_var); |
10356 | | /* step < 0, so we certainly don't need r */ |
10357 | 0 | } |
10358 | | #else /* !HAVE_INT128 */ |
10359 | | int64_to_numericvar(s_int64, &s_var); |
10360 | | if (step >= 0) |
10361 | | int64_to_numericvar(r_int64, &r_var); |
10362 | | #endif /* HAVE_INT128 */ |
10363 | | |
10364 | | /* |
10365 | | * The remaining iterations with src_ndigits > 8 (or 16, if have int128) |
10366 | | * use numeric variables. |
10367 | | */ |
10368 | 0 | while (step >= 0) |
10369 | 0 | { |
10370 | 0 | int tmp_len; |
10371 | |
|
10372 | 0 | src_ndigits = ndigits[step]; |
10373 | 0 | blen = (src_ndigits - src_idx) / 2; |
10374 | | |
10375 | | /* Extract a1 and a0 */ |
10376 | 0 | if (src_idx < arg->ndigits) |
10377 | 0 | { |
10378 | 0 | tmp_len = Min(blen, arg->ndigits - src_idx); |
10379 | 0 | alloc_var(&a1_var, tmp_len); |
10380 | 0 | memcpy(a1_var.digits, arg->digits + src_idx, |
10381 | 0 | tmp_len * sizeof(NumericDigit)); |
10382 | 0 | a1_var.weight = blen - 1; |
10383 | 0 | a1_var.sign = NUMERIC_POS; |
10384 | 0 | a1_var.dscale = 0; |
10385 | 0 | strip_var(&a1_var); |
10386 | 0 | } |
10387 | 0 | else |
10388 | 0 | { |
10389 | 0 | zero_var(&a1_var); |
10390 | 0 | a1_var.dscale = 0; |
10391 | 0 | } |
10392 | 0 | src_idx += blen; |
10393 | |
|
10394 | 0 | if (src_idx < arg->ndigits) |
10395 | 0 | { |
10396 | 0 | tmp_len = Min(blen, arg->ndigits - src_idx); |
10397 | 0 | alloc_var(&a0_var, tmp_len); |
10398 | 0 | memcpy(a0_var.digits, arg->digits + src_idx, |
10399 | 0 | tmp_len * sizeof(NumericDigit)); |
10400 | 0 | a0_var.weight = blen - 1; |
10401 | 0 | a0_var.sign = NUMERIC_POS; |
10402 | 0 | a0_var.dscale = 0; |
10403 | 0 | strip_var(&a0_var); |
10404 | 0 | } |
10405 | 0 | else |
10406 | 0 | { |
10407 | 0 | zero_var(&a0_var); |
10408 | 0 | a0_var.dscale = 0; |
10409 | 0 | } |
10410 | 0 | src_idx += blen; |
10411 | | |
10412 | | /* Compute (q,u) = DivRem(r*b + a1, 2*s) */ |
10413 | 0 | set_var_from_var(&r_var, &q_var); |
10414 | 0 | q_var.weight += blen; |
10415 | 0 | add_var(&q_var, &a1_var, &q_var); |
10416 | 0 | add_var(&s_var, &s_var, &u_var); |
10417 | 0 | div_mod_var(&q_var, &u_var, &q_var, &u_var); |
10418 | | |
10419 | | /* Compute s = s*b + q */ |
10420 | 0 | s_var.weight += blen; |
10421 | 0 | add_var(&s_var, &q_var, &s_var); |
10422 | | |
10423 | | /* |
10424 | | * Compute r = u*b + a0 - q^2. |
10425 | | * |
10426 | | * In the final iteration, we don't actually need r; we just need to |
10427 | | * know whether it is negative, so that we know whether to adjust s. |
10428 | | * So instead of the final subtraction we can just compare. |
10429 | | */ |
10430 | 0 | u_var.weight += blen; |
10431 | 0 | add_var(&u_var, &a0_var, &u_var); |
10432 | 0 | mul_var(&q_var, &q_var, &q_var, 0); |
10433 | |
|
10434 | 0 | if (step > 0) |
10435 | 0 | { |
10436 | | /* Need r for later iterations */ |
10437 | 0 | sub_var(&u_var, &q_var, &r_var); |
10438 | 0 | if (r_var.sign == NUMERIC_NEG) |
10439 | 0 | { |
10440 | | /* s is too large by 1; set r += s, s--, r += s */ |
10441 | 0 | add_var(&r_var, &s_var, &r_var); |
10442 | 0 | sub_var(&s_var, &const_one, &s_var); |
10443 | 0 | add_var(&r_var, &s_var, &r_var); |
10444 | 0 | } |
10445 | 0 | } |
10446 | 0 | else |
10447 | 0 | { |
10448 | | /* Don't need r anymore, except to test if s is too large by 1 */ |
10449 | 0 | if (cmp_var(&u_var, &q_var) < 0) |
10450 | 0 | sub_var(&s_var, &const_one, &s_var); |
10451 | 0 | } |
10452 | |
|
10453 | 0 | Assert(src_idx == src_ndigits); /* All input digits consumed */ |
10454 | 0 | step--; |
10455 | 0 | } |
10456 | | |
10457 | | /* |
10458 | | * Construct the final result, rounding it to the requested precision. |
10459 | | */ |
10460 | 0 | set_var_from_var(&s_var, result); |
10461 | 0 | result->weight = res_weight; |
10462 | 0 | result->sign = NUMERIC_POS; |
10463 | | |
10464 | | /* Round to target rscale (and set result->dscale) */ |
10465 | 0 | round_var(result, rscale); |
10466 | | |
10467 | | /* Strip leading and trailing zeroes */ |
10468 | 0 | strip_var(result); |
10469 | |
|
10470 | 0 | free_var(&s_var); |
10471 | 0 | free_var(&r_var); |
10472 | 0 | free_var(&a0_var); |
10473 | 0 | free_var(&a1_var); |
10474 | 0 | free_var(&q_var); |
10475 | 0 | free_var(&u_var); |
10476 | 0 | } |
10477 | | |
10478 | | |
10479 | | /* |
10480 | | * exp_var() - |
10481 | | * |
10482 | | * Raise e to the power of x, computed to rscale fractional digits |
10483 | | */ |
10484 | | static void |
10485 | | exp_var(const NumericVar *arg, NumericVar *result, int rscale) |
10486 | 0 | { |
10487 | 0 | NumericVar x; |
10488 | 0 | NumericVar elem; |
10489 | 0 | int ni; |
10490 | 0 | double val; |
10491 | 0 | int dweight; |
10492 | 0 | int ndiv2; |
10493 | 0 | int sig_digits; |
10494 | 0 | int local_rscale; |
10495 | |
|
10496 | 0 | init_var(&x); |
10497 | 0 | init_var(&elem); |
10498 | |
|
10499 | 0 | set_var_from_var(arg, &x); |
10500 | | |
10501 | | /* |
10502 | | * Estimate the dweight of the result using floating point arithmetic, so |
10503 | | * that we can choose an appropriate local rscale for the calculation. |
10504 | | */ |
10505 | 0 | val = numericvar_to_double_no_overflow(&x); |
10506 | | |
10507 | | /* Guard against overflow/underflow */ |
10508 | | /* If you change this limit, see also power_var()'s limit */ |
10509 | 0 | if (fabs(val) >= NUMERIC_MAX_RESULT_SCALE * 3) |
10510 | 0 | { |
10511 | 0 | if (val > 0) |
10512 | 0 | ereport(ERROR, |
10513 | 0 | (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), |
10514 | 0 | errmsg("value overflows numeric format"))); |
10515 | 0 | zero_var(result); |
10516 | 0 | result->dscale = rscale; |
10517 | 0 | return; |
10518 | 0 | } |
10519 | | |
10520 | | /* decimal weight = log10(e^x) = x * log10(e) */ |
10521 | 0 | dweight = (int) (val * 0.434294481903252); |
10522 | | |
10523 | | /* |
10524 | | * Reduce x to the range -0.01 <= x <= 0.01 (approximately) by dividing by |
10525 | | * 2^ndiv2, to improve the convergence rate of the Taylor series. |
10526 | | * |
10527 | | * Note that the overflow check above ensures that fabs(x) < 6000, which |
10528 | | * means that ndiv2 <= 20 here. |
10529 | | */ |
10530 | 0 | if (fabs(val) > 0.01) |
10531 | 0 | { |
10532 | 0 | ndiv2 = 1; |
10533 | 0 | val /= 2; |
10534 | |
|
10535 | 0 | while (fabs(val) > 0.01) |
10536 | 0 | { |
10537 | 0 | ndiv2++; |
10538 | 0 | val /= 2; |
10539 | 0 | } |
10540 | |
|
10541 | 0 | local_rscale = x.dscale + ndiv2; |
10542 | 0 | div_var_int(&x, 1 << ndiv2, 0, &x, local_rscale, true); |
10543 | 0 | } |
10544 | 0 | else |
10545 | 0 | ndiv2 = 0; |
10546 | | |
10547 | | /* |
10548 | | * Set the scale for the Taylor series expansion. The final result has |
10549 | | * (dweight + rscale + 1) significant digits. In addition, we have to |
10550 | | * raise the Taylor series result to the power 2^ndiv2, which introduces |
10551 | | * an error of up to around log10(2^ndiv2) digits, so work with this many |
10552 | | * extra digits of precision (plus a few more for good measure). |
10553 | | */ |
10554 | 0 | sig_digits = 1 + dweight + rscale + (int) (ndiv2 * 0.301029995663981); |
10555 | 0 | sig_digits = Max(sig_digits, 0) + 8; |
10556 | |
|
10557 | 0 | local_rscale = sig_digits - 1; |
10558 | | |
10559 | | /* |
10560 | | * Use the Taylor series |
10561 | | * |
10562 | | * exp(x) = 1 + x + x^2/2! + x^3/3! + ... |
10563 | | * |
10564 | | * Given the limited range of x, this should converge reasonably quickly. |
10565 | | * We run the series until the terms fall below the local_rscale limit. |
10566 | | */ |
10567 | 0 | add_var(&const_one, &x, result); |
10568 | |
|
10569 | 0 | mul_var(&x, &x, &elem, local_rscale); |
10570 | 0 | ni = 2; |
10571 | 0 | div_var_int(&elem, ni, 0, &elem, local_rscale, true); |
10572 | |
|
10573 | 0 | while (elem.ndigits != 0) |
10574 | 0 | { |
10575 | 0 | add_var(result, &elem, result); |
10576 | |
|
10577 | 0 | mul_var(&elem, &x, &elem, local_rscale); |
10578 | 0 | ni++; |
10579 | 0 | div_var_int(&elem, ni, 0, &elem, local_rscale, true); |
10580 | 0 | } |
10581 | | |
10582 | | /* |
10583 | | * Compensate for the argument range reduction. Since the weight of the |
10584 | | * result doubles with each multiplication, we can reduce the local rscale |
10585 | | * as we proceed. |
10586 | | */ |
10587 | 0 | while (ndiv2-- > 0) |
10588 | 0 | { |
10589 | 0 | local_rscale = sig_digits - result->weight * 2 * DEC_DIGITS; |
10590 | 0 | local_rscale = Max(local_rscale, NUMERIC_MIN_DISPLAY_SCALE); |
10591 | 0 | mul_var(result, result, result, local_rscale); |
10592 | 0 | } |
10593 | | |
10594 | | /* Round to requested rscale */ |
10595 | 0 | round_var(result, rscale); |
10596 | |
|
10597 | 0 | free_var(&x); |
10598 | 0 | free_var(&elem); |
10599 | 0 | } |
10600 | | |
10601 | | |
10602 | | /* |
10603 | | * Estimate the dweight of the most significant decimal digit of the natural |
10604 | | * logarithm of a number. |
10605 | | * |
10606 | | * Essentially, we're approximating log10(abs(ln(var))). This is used to |
10607 | | * determine the appropriate rscale when computing natural logarithms. |
10608 | | * |
10609 | | * Note: many callers call this before range-checking the input. Therefore, |
10610 | | * we must be robust against values that are invalid to apply ln() to. |
10611 | | * We don't wish to throw an error here, so just return zero in such cases. |
10612 | | */ |
10613 | | static int |
10614 | | estimate_ln_dweight(const NumericVar *var) |
10615 | 0 | { |
10616 | 0 | int ln_dweight; |
10617 | | |
10618 | | /* Caller should fail on ln(negative), but for the moment return zero */ |
10619 | 0 | if (var->sign != NUMERIC_POS) |
10620 | 0 | return 0; |
10621 | | |
10622 | 0 | if (cmp_var(var, &const_zero_point_nine) >= 0 && |
10623 | 0 | cmp_var(var, &const_one_point_one) <= 0) |
10624 | 0 | { |
10625 | | /* |
10626 | | * 0.9 <= var <= 1.1 |
10627 | | * |
10628 | | * ln(var) has a negative weight (possibly very large). To get a |
10629 | | * reasonably accurate result, estimate it using ln(1+x) ~= x. |
10630 | | */ |
10631 | 0 | NumericVar x; |
10632 | |
|
10633 | 0 | init_var(&x); |
10634 | 0 | sub_var(var, &const_one, &x); |
10635 | |
|
10636 | 0 | if (x.ndigits > 0) |
10637 | 0 | { |
10638 | | /* Use weight of most significant decimal digit of x */ |
10639 | 0 | ln_dweight = x.weight * DEC_DIGITS + (int) log10(x.digits[0]); |
10640 | 0 | } |
10641 | 0 | else |
10642 | 0 | { |
10643 | | /* x = 0. Since ln(1) = 0 exactly, we don't need extra digits */ |
10644 | 0 | ln_dweight = 0; |
10645 | 0 | } |
10646 | |
|
10647 | 0 | free_var(&x); |
10648 | 0 | } |
10649 | 0 | else |
10650 | 0 | { |
10651 | | /* |
10652 | | * Estimate the logarithm using the first couple of digits from the |
10653 | | * input number. This will give an accurate result whenever the input |
10654 | | * is not too close to 1. |
10655 | | */ |
10656 | 0 | if (var->ndigits > 0) |
10657 | 0 | { |
10658 | 0 | int digits; |
10659 | 0 | int dweight; |
10660 | 0 | double ln_var; |
10661 | |
|
10662 | 0 | digits = var->digits[0]; |
10663 | 0 | dweight = var->weight * DEC_DIGITS; |
10664 | |
|
10665 | 0 | if (var->ndigits > 1) |
10666 | 0 | { |
10667 | 0 | digits = digits * NBASE + var->digits[1]; |
10668 | 0 | dweight -= DEC_DIGITS; |
10669 | 0 | } |
10670 | | |
10671 | | /*---------- |
10672 | | * We have var ~= digits * 10^dweight |
10673 | | * so ln(var) ~= ln(digits) + dweight * ln(10) |
10674 | | *---------- |
10675 | | */ |
10676 | 0 | ln_var = log((double) digits) + dweight * 2.302585092994046; |
10677 | 0 | ln_dweight = (int) log10(fabs(ln_var)); |
10678 | 0 | } |
10679 | 0 | else |
10680 | 0 | { |
10681 | | /* Caller should fail on ln(0), but for the moment return zero */ |
10682 | 0 | ln_dweight = 0; |
10683 | 0 | } |
10684 | 0 | } |
10685 | |
|
10686 | 0 | return ln_dweight; |
10687 | 0 | } |
10688 | | |
10689 | | |
10690 | | /* |
10691 | | * ln_var() - |
10692 | | * |
10693 | | * Compute the natural log of x |
10694 | | */ |
10695 | | static void |
10696 | | ln_var(const NumericVar *arg, NumericVar *result, int rscale) |
10697 | 0 | { |
10698 | 0 | NumericVar x; |
10699 | 0 | NumericVar xx; |
10700 | 0 | int ni; |
10701 | 0 | NumericVar elem; |
10702 | 0 | NumericVar fact; |
10703 | 0 | int nsqrt; |
10704 | 0 | int local_rscale; |
10705 | 0 | int cmp; |
10706 | |
|
10707 | 0 | cmp = cmp_var(arg, &const_zero); |
10708 | 0 | if (cmp == 0) |
10709 | 0 | ereport(ERROR, |
10710 | 0 | (errcode(ERRCODE_INVALID_ARGUMENT_FOR_LOG), |
10711 | 0 | errmsg("cannot take logarithm of zero"))); |
10712 | 0 | else if (cmp < 0) |
10713 | 0 | ereport(ERROR, |
10714 | 0 | (errcode(ERRCODE_INVALID_ARGUMENT_FOR_LOG), |
10715 | 0 | errmsg("cannot take logarithm of a negative number"))); |
10716 | | |
10717 | 0 | init_var(&x); |
10718 | 0 | init_var(&xx); |
10719 | 0 | init_var(&elem); |
10720 | 0 | init_var(&fact); |
10721 | |
|
10722 | 0 | set_var_from_var(arg, &x); |
10723 | 0 | set_var_from_var(&const_two, &fact); |
10724 | | |
10725 | | /* |
10726 | | * Reduce input into range 0.9 < x < 1.1 with repeated sqrt() operations. |
10727 | | * |
10728 | | * The final logarithm will have up to around rscale+6 significant digits. |
10729 | | * Each sqrt() will roughly halve the weight of x, so adjust the local |
10730 | | * rscale as we work so that we keep this many significant digits at each |
10731 | | * step (plus a few more for good measure). |
10732 | | * |
10733 | | * Note that we allow local_rscale < 0 during this input reduction |
10734 | | * process, which implies rounding before the decimal point. sqrt_var() |
10735 | | * explicitly supports this, and it significantly reduces the work |
10736 | | * required to reduce very large inputs to the required range. Once the |
10737 | | * input reduction is complete, x.weight will be 0 and its display scale |
10738 | | * will be non-negative again. |
10739 | | */ |
10740 | 0 | nsqrt = 0; |
10741 | 0 | while (cmp_var(&x, &const_zero_point_nine) <= 0) |
10742 | 0 | { |
10743 | 0 | local_rscale = rscale - x.weight * DEC_DIGITS / 2 + 8; |
10744 | 0 | sqrt_var(&x, &x, local_rscale); |
10745 | 0 | mul_var(&fact, &const_two, &fact, 0); |
10746 | 0 | nsqrt++; |
10747 | 0 | } |
10748 | 0 | while (cmp_var(&x, &const_one_point_one) >= 0) |
10749 | 0 | { |
10750 | 0 | local_rscale = rscale - x.weight * DEC_DIGITS / 2 + 8; |
10751 | 0 | sqrt_var(&x, &x, local_rscale); |
10752 | 0 | mul_var(&fact, &const_two, &fact, 0); |
10753 | 0 | nsqrt++; |
10754 | 0 | } |
10755 | | |
10756 | | /* |
10757 | | * We use the Taylor series for 0.5 * ln((1+z)/(1-z)), |
10758 | | * |
10759 | | * z + z^3/3 + z^5/5 + ... |
10760 | | * |
10761 | | * where z = (x-1)/(x+1) is in the range (approximately) -0.053 .. 0.048 |
10762 | | * due to the above range-reduction of x. |
10763 | | * |
10764 | | * The convergence of this is not as fast as one would like, but is |
10765 | | * tolerable given that z is small. |
10766 | | * |
10767 | | * The Taylor series result will be multiplied by 2^(nsqrt+1), which has a |
10768 | | * decimal weight of (nsqrt+1) * log10(2), so work with this many extra |
10769 | | * digits of precision (plus a few more for good measure). |
10770 | | */ |
10771 | 0 | local_rscale = rscale + (int) ((nsqrt + 1) * 0.301029995663981) + 8; |
10772 | |
|
10773 | 0 | sub_var(&x, &const_one, result); |
10774 | 0 | add_var(&x, &const_one, &elem); |
10775 | 0 | div_var(result, &elem, result, local_rscale, true, false); |
10776 | 0 | set_var_from_var(result, &xx); |
10777 | 0 | mul_var(result, result, &x, local_rscale); |
10778 | |
|
10779 | 0 | ni = 1; |
10780 | |
|
10781 | 0 | for (;;) |
10782 | 0 | { |
10783 | 0 | ni += 2; |
10784 | 0 | mul_var(&xx, &x, &xx, local_rscale); |
10785 | 0 | div_var_int(&xx, ni, 0, &elem, local_rscale, true); |
10786 | |
|
10787 | 0 | if (elem.ndigits == 0) |
10788 | 0 | break; |
10789 | | |
10790 | 0 | add_var(result, &elem, result); |
10791 | |
|
10792 | 0 | if (elem.weight < (result->weight - local_rscale * 2 / DEC_DIGITS)) |
10793 | 0 | break; |
10794 | 0 | } |
10795 | | |
10796 | | /* Compensate for argument range reduction, round to requested rscale */ |
10797 | 0 | mul_var(result, &fact, result, rscale); |
10798 | |
|
10799 | 0 | free_var(&x); |
10800 | 0 | free_var(&xx); |
10801 | 0 | free_var(&elem); |
10802 | 0 | free_var(&fact); |
10803 | 0 | } |
10804 | | |
10805 | | |
10806 | | /* |
10807 | | * log_var() - |
10808 | | * |
10809 | | * Compute the logarithm of num in a given base. |
10810 | | * |
10811 | | * Note: this routine chooses dscale of the result. |
10812 | | */ |
10813 | | static void |
10814 | | log_var(const NumericVar *base, const NumericVar *num, NumericVar *result) |
10815 | 0 | { |
10816 | 0 | NumericVar ln_base; |
10817 | 0 | NumericVar ln_num; |
10818 | 0 | int ln_base_dweight; |
10819 | 0 | int ln_num_dweight; |
10820 | 0 | int result_dweight; |
10821 | 0 | int rscale; |
10822 | 0 | int ln_base_rscale; |
10823 | 0 | int ln_num_rscale; |
10824 | | |
10825 | | /* |
10826 | | * ln_var will throw a suitable error for most invalid-input cases, but we |
10827 | | * need a special case for base == 1, else we'd report "division by zero" |
10828 | | * which is a bit confusing. |
10829 | | */ |
10830 | 0 | if (cmp_var(base, &const_one) == 0) |
10831 | 0 | ereport(ERROR, |
10832 | 0 | (errcode(ERRCODE_INVALID_ARGUMENT_FOR_LOG), |
10833 | 0 | errmsg("cannot take logarithm using base one"))); |
10834 | | |
10835 | 0 | init_var(&ln_base); |
10836 | 0 | init_var(&ln_num); |
10837 | | |
10838 | | /* Estimated dweights of ln(base), ln(num) and the final result */ |
10839 | 0 | ln_base_dweight = estimate_ln_dweight(base); |
10840 | 0 | ln_num_dweight = estimate_ln_dweight(num); |
10841 | 0 | result_dweight = ln_num_dweight - ln_base_dweight; |
10842 | | |
10843 | | /* |
10844 | | * Select the scale of the result so that it will have at least |
10845 | | * NUMERIC_MIN_SIG_DIGITS significant digits and is not less than either |
10846 | | * input's display scale. |
10847 | | */ |
10848 | 0 | rscale = NUMERIC_MIN_SIG_DIGITS - result_dweight; |
10849 | 0 | rscale = Max(rscale, base->dscale); |
10850 | 0 | rscale = Max(rscale, num->dscale); |
10851 | 0 | rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE); |
10852 | 0 | rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE); |
10853 | | |
10854 | | /* |
10855 | | * Set the scales for ln(base) and ln(num) so that they each have more |
10856 | | * significant digits than the final result. |
10857 | | */ |
10858 | 0 | ln_base_rscale = rscale + result_dweight - ln_base_dweight + 8; |
10859 | 0 | ln_base_rscale = Max(ln_base_rscale, NUMERIC_MIN_DISPLAY_SCALE); |
10860 | |
|
10861 | 0 | ln_num_rscale = rscale + result_dweight - ln_num_dweight + 8; |
10862 | 0 | ln_num_rscale = Max(ln_num_rscale, NUMERIC_MIN_DISPLAY_SCALE); |
10863 | | |
10864 | | /* Form natural logarithms */ |
10865 | 0 | ln_var(base, &ln_base, ln_base_rscale); |
10866 | 0 | ln_var(num, &ln_num, ln_num_rscale); |
10867 | | |
10868 | | /* Divide and round to the required scale */ |
10869 | 0 | div_var(&ln_num, &ln_base, result, rscale, true, false); |
10870 | |
|
10871 | 0 | free_var(&ln_num); |
10872 | 0 | free_var(&ln_base); |
10873 | 0 | } |
10874 | | |
10875 | | |
10876 | | /* |
10877 | | * power_var() - |
10878 | | * |
10879 | | * Raise base to the power of exp |
10880 | | * |
10881 | | * Note: this routine chooses dscale of the result. |
10882 | | */ |
10883 | | static void |
10884 | | power_var(const NumericVar *base, const NumericVar *exp, NumericVar *result) |
10885 | 0 | { |
10886 | 0 | int res_sign; |
10887 | 0 | NumericVar abs_base; |
10888 | 0 | NumericVar ln_base; |
10889 | 0 | NumericVar ln_num; |
10890 | 0 | int ln_dweight; |
10891 | 0 | int rscale; |
10892 | 0 | int sig_digits; |
10893 | 0 | int local_rscale; |
10894 | 0 | double val; |
10895 | | |
10896 | | /* If exp can be represented as an integer, use power_var_int */ |
10897 | 0 | if (exp->ndigits == 0 || exp->ndigits <= exp->weight + 1) |
10898 | 0 | { |
10899 | | /* exact integer, but does it fit in int? */ |
10900 | 0 | int64 expval64; |
10901 | |
|
10902 | 0 | if (numericvar_to_int64(exp, &expval64)) |
10903 | 0 | { |
10904 | 0 | if (expval64 >= PG_INT32_MIN && expval64 <= PG_INT32_MAX) |
10905 | 0 | { |
10906 | | /* Okay, use power_var_int */ |
10907 | 0 | power_var_int(base, (int) expval64, exp->dscale, result); |
10908 | 0 | return; |
10909 | 0 | } |
10910 | 0 | } |
10911 | 0 | } |
10912 | | |
10913 | | /* |
10914 | | * This avoids log(0) for cases of 0 raised to a non-integer. 0 ^ 0 is |
10915 | | * handled by power_var_int(). |
10916 | | */ |
10917 | 0 | if (cmp_var(base, &const_zero) == 0) |
10918 | 0 | { |
10919 | 0 | set_var_from_var(&const_zero, result); |
10920 | 0 | result->dscale = NUMERIC_MIN_SIG_DIGITS; /* no need to round */ |
10921 | 0 | return; |
10922 | 0 | } |
10923 | | |
10924 | 0 | init_var(&abs_base); |
10925 | 0 | init_var(&ln_base); |
10926 | 0 | init_var(&ln_num); |
10927 | | |
10928 | | /* |
10929 | | * If base is negative, insist that exp be an integer. The result is then |
10930 | | * positive if exp is even and negative if exp is odd. |
10931 | | */ |
10932 | 0 | if (base->sign == NUMERIC_NEG) |
10933 | 0 | { |
10934 | | /* |
10935 | | * Check that exp is an integer. This error code is defined by the |
10936 | | * SQL standard, and matches other errors in numeric_power(). |
10937 | | */ |
10938 | 0 | if (exp->ndigits > 0 && exp->ndigits > exp->weight + 1) |
10939 | 0 | ereport(ERROR, |
10940 | 0 | (errcode(ERRCODE_INVALID_ARGUMENT_FOR_POWER_FUNCTION), |
10941 | 0 | errmsg("a negative number raised to a non-integer power yields a complex result"))); |
10942 | | |
10943 | | /* Test if exp is odd or even */ |
10944 | 0 | if (exp->ndigits > 0 && exp->ndigits == exp->weight + 1 && |
10945 | 0 | (exp->digits[exp->ndigits - 1] & 1)) |
10946 | 0 | res_sign = NUMERIC_NEG; |
10947 | 0 | else |
10948 | 0 | res_sign = NUMERIC_POS; |
10949 | | |
10950 | | /* Then work with abs(base) below */ |
10951 | 0 | set_var_from_var(base, &abs_base); |
10952 | 0 | abs_base.sign = NUMERIC_POS; |
10953 | 0 | base = &abs_base; |
10954 | 0 | } |
10955 | 0 | else |
10956 | 0 | res_sign = NUMERIC_POS; |
10957 | | |
10958 | | /*---------- |
10959 | | * Decide on the scale for the ln() calculation. For this we need an |
10960 | | * estimate of the weight of the result, which we obtain by doing an |
10961 | | * initial low-precision calculation of exp * ln(base). |
10962 | | * |
10963 | | * We want result = e ^ (exp * ln(base)) |
10964 | | * so result dweight = log10(result) = exp * ln(base) * log10(e) |
10965 | | * |
10966 | | * We also perform a crude overflow test here so that we can exit early if |
10967 | | * the full-precision result is sure to overflow, and to guard against |
10968 | | * integer overflow when determining the scale for the real calculation. |
10969 | | * exp_var() supports inputs up to NUMERIC_MAX_RESULT_SCALE * 3, so the |
10970 | | * result will overflow if exp * ln(base) >= NUMERIC_MAX_RESULT_SCALE * 3. |
10971 | | * Since the values here are only approximations, we apply a small fuzz |
10972 | | * factor to this overflow test and let exp_var() determine the exact |
10973 | | * overflow threshold so that it is consistent for all inputs. |
10974 | | *---------- |
10975 | | */ |
10976 | 0 | ln_dweight = estimate_ln_dweight(base); |
10977 | | |
10978 | | /* |
10979 | | * Set the scale for the low-precision calculation, computing ln(base) to |
10980 | | * around 8 significant digits. Note that ln_dweight may be as small as |
10981 | | * -NUMERIC_DSCALE_MAX, so the scale may exceed NUMERIC_MAX_DISPLAY_SCALE |
10982 | | * here. |
10983 | | */ |
10984 | 0 | local_rscale = 8 - ln_dweight; |
10985 | 0 | local_rscale = Max(local_rscale, NUMERIC_MIN_DISPLAY_SCALE); |
10986 | |
|
10987 | 0 | ln_var(base, &ln_base, local_rscale); |
10988 | |
|
10989 | 0 | mul_var(&ln_base, exp, &ln_num, local_rscale); |
10990 | |
|
10991 | 0 | val = numericvar_to_double_no_overflow(&ln_num); |
10992 | | |
10993 | | /* initial overflow/underflow test with fuzz factor */ |
10994 | 0 | if (fabs(val) > NUMERIC_MAX_RESULT_SCALE * 3.01) |
10995 | 0 | { |
10996 | 0 | if (val > 0) |
10997 | 0 | ereport(ERROR, |
10998 | 0 | (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), |
10999 | 0 | errmsg("value overflows numeric format"))); |
11000 | 0 | zero_var(result); |
11001 | 0 | result->dscale = NUMERIC_MAX_DISPLAY_SCALE; |
11002 | 0 | return; |
11003 | 0 | } |
11004 | | |
11005 | 0 | val *= 0.434294481903252; /* approximate decimal result weight */ |
11006 | | |
11007 | | /* choose the result scale */ |
11008 | 0 | rscale = NUMERIC_MIN_SIG_DIGITS - (int) val; |
11009 | 0 | rscale = Max(rscale, base->dscale); |
11010 | 0 | rscale = Max(rscale, exp->dscale); |
11011 | 0 | rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE); |
11012 | 0 | rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE); |
11013 | | |
11014 | | /* significant digits required in the result */ |
11015 | 0 | sig_digits = rscale + (int) val; |
11016 | 0 | sig_digits = Max(sig_digits, 0); |
11017 | | |
11018 | | /* set the scale for the real exp * ln(base) calculation */ |
11019 | 0 | local_rscale = sig_digits - ln_dweight + 8; |
11020 | 0 | local_rscale = Max(local_rscale, NUMERIC_MIN_DISPLAY_SCALE); |
11021 | | |
11022 | | /* and do the real calculation */ |
11023 | |
|
11024 | 0 | ln_var(base, &ln_base, local_rscale); |
11025 | |
|
11026 | 0 | mul_var(&ln_base, exp, &ln_num, local_rscale); |
11027 | |
|
11028 | 0 | exp_var(&ln_num, result, rscale); |
11029 | |
|
11030 | 0 | if (res_sign == NUMERIC_NEG && result->ndigits > 0) |
11031 | 0 | result->sign = NUMERIC_NEG; |
11032 | |
|
11033 | 0 | free_var(&ln_num); |
11034 | 0 | free_var(&ln_base); |
11035 | 0 | free_var(&abs_base); |
11036 | 0 | } |
11037 | | |
11038 | | /* |
11039 | | * power_var_int() - |
11040 | | * |
11041 | | * Raise base to the power of exp, where exp is an integer. |
11042 | | * |
11043 | | * Note: this routine chooses dscale of the result. |
11044 | | */ |
11045 | | static void |
11046 | | power_var_int(const NumericVar *base, int exp, int exp_dscale, |
11047 | | NumericVar *result) |
11048 | 0 | { |
11049 | 0 | double f; |
11050 | 0 | int p; |
11051 | 0 | int i; |
11052 | 0 | int rscale; |
11053 | 0 | int sig_digits; |
11054 | 0 | unsigned int mask; |
11055 | 0 | bool neg; |
11056 | 0 | NumericVar base_prod; |
11057 | 0 | int local_rscale; |
11058 | | |
11059 | | /* |
11060 | | * Choose the result scale. For this we need an estimate of the decimal |
11061 | | * weight of the result, which we obtain by approximating using double |
11062 | | * precision arithmetic. |
11063 | | * |
11064 | | * We also perform crude overflow/underflow tests here so that we can exit |
11065 | | * early if the result is sure to overflow/underflow, and to guard against |
11066 | | * integer overflow when choosing the result scale. |
11067 | | */ |
11068 | 0 | if (base->ndigits != 0) |
11069 | 0 | { |
11070 | | /*---------- |
11071 | | * Choose f (double) and p (int) such that base ~= f * 10^p. |
11072 | | * Then log10(result) = log10(base^exp) ~= exp * (log10(f) + p). |
11073 | | *---------- |
11074 | | */ |
11075 | 0 | f = base->digits[0]; |
11076 | 0 | p = base->weight * DEC_DIGITS; |
11077 | |
|
11078 | 0 | for (i = 1; i < base->ndigits && i * DEC_DIGITS < 16; i++) |
11079 | 0 | { |
11080 | 0 | f = f * NBASE + base->digits[i]; |
11081 | 0 | p -= DEC_DIGITS; |
11082 | 0 | } |
11083 | |
|
11084 | 0 | f = exp * (log10(f) + p); /* approximate decimal result weight */ |
11085 | 0 | } |
11086 | 0 | else |
11087 | 0 | f = 0; /* result is 0 or 1 (weight 0), or error */ |
11088 | | |
11089 | | /* overflow/underflow tests with fuzz factors */ |
11090 | 0 | if (f > (NUMERIC_WEIGHT_MAX + 1) * DEC_DIGITS) |
11091 | 0 | ereport(ERROR, |
11092 | 0 | (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), |
11093 | 0 | errmsg("value overflows numeric format"))); |
11094 | 0 | if (f + 1 < -NUMERIC_MAX_DISPLAY_SCALE) |
11095 | 0 | { |
11096 | 0 | zero_var(result); |
11097 | 0 | result->dscale = NUMERIC_MAX_DISPLAY_SCALE; |
11098 | 0 | return; |
11099 | 0 | } |
11100 | | |
11101 | | /* |
11102 | | * Choose the result scale in the same way as power_var(), so it has at |
11103 | | * least NUMERIC_MIN_SIG_DIGITS significant digits and is not less than |
11104 | | * either input's display scale. |
11105 | | */ |
11106 | 0 | rscale = NUMERIC_MIN_SIG_DIGITS - (int) f; |
11107 | 0 | rscale = Max(rscale, base->dscale); |
11108 | 0 | rscale = Max(rscale, exp_dscale); |
11109 | 0 | rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE); |
11110 | 0 | rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE); |
11111 | | |
11112 | | /* Handle some common special cases, as well as corner cases */ |
11113 | 0 | switch (exp) |
11114 | 0 | { |
11115 | 0 | case 0: |
11116 | | |
11117 | | /* |
11118 | | * While 0 ^ 0 can be either 1 or indeterminate (error), we treat |
11119 | | * it as 1 because most programming languages do this. SQL:2003 |
11120 | | * also requires a return value of 1. |
11121 | | * https://en.wikipedia.org/wiki/Exponentiation#Zero_to_the_zero_power |
11122 | | */ |
11123 | 0 | set_var_from_var(&const_one, result); |
11124 | 0 | result->dscale = rscale; /* no need to round */ |
11125 | 0 | return; |
11126 | 0 | case 1: |
11127 | 0 | set_var_from_var(base, result); |
11128 | 0 | round_var(result, rscale); |
11129 | 0 | return; |
11130 | 0 | case -1: |
11131 | 0 | div_var(&const_one, base, result, rscale, true, true); |
11132 | 0 | return; |
11133 | 0 | case 2: |
11134 | 0 | mul_var(base, base, result, rscale); |
11135 | 0 | return; |
11136 | 0 | default: |
11137 | 0 | break; |
11138 | 0 | } |
11139 | | |
11140 | | /* Handle the special case where the base is zero */ |
11141 | 0 | if (base->ndigits == 0) |
11142 | 0 | { |
11143 | 0 | if (exp < 0) |
11144 | 0 | ereport(ERROR, |
11145 | 0 | (errcode(ERRCODE_DIVISION_BY_ZERO), |
11146 | 0 | errmsg("division by zero"))); |
11147 | 0 | zero_var(result); |
11148 | 0 | result->dscale = rscale; |
11149 | 0 | return; |
11150 | 0 | } |
11151 | | |
11152 | | /* |
11153 | | * The general case repeatedly multiplies base according to the bit |
11154 | | * pattern of exp. |
11155 | | * |
11156 | | * The local rscale used for each multiplication is varied to keep a fixed |
11157 | | * number of significant digits, sufficient to give the required result |
11158 | | * scale. |
11159 | | */ |
11160 | | |
11161 | | /* |
11162 | | * Approximate number of significant digits in the result. Note that the |
11163 | | * underflow test above, together with the choice of rscale, ensures that |
11164 | | * this approximation is necessarily > 0. |
11165 | | */ |
11166 | 0 | sig_digits = 1 + rscale + (int) f; |
11167 | | |
11168 | | /* |
11169 | | * The multiplications to produce the result may introduce an error of up |
11170 | | * to around log10(abs(exp)) digits, so work with this many extra digits |
11171 | | * of precision (plus a few more for good measure). |
11172 | | */ |
11173 | 0 | sig_digits += (int) log(fabs((double) exp)) + 8; |
11174 | | |
11175 | | /* |
11176 | | * Now we can proceed with the multiplications. |
11177 | | */ |
11178 | 0 | neg = (exp < 0); |
11179 | 0 | mask = pg_abs_s32(exp); |
11180 | |
|
11181 | 0 | init_var(&base_prod); |
11182 | 0 | set_var_from_var(base, &base_prod); |
11183 | |
|
11184 | 0 | if (mask & 1) |
11185 | 0 | set_var_from_var(base, result); |
11186 | 0 | else |
11187 | 0 | set_var_from_var(&const_one, result); |
11188 | |
|
11189 | 0 | while ((mask >>= 1) > 0) |
11190 | 0 | { |
11191 | | /* |
11192 | | * Do the multiplications using rscales large enough to hold the |
11193 | | * results to the required number of significant digits, but don't |
11194 | | * waste time by exceeding the scales of the numbers themselves. |
11195 | | */ |
11196 | 0 | local_rscale = sig_digits - 2 * base_prod.weight * DEC_DIGITS; |
11197 | 0 | local_rscale = Min(local_rscale, 2 * base_prod.dscale); |
11198 | 0 | local_rscale = Max(local_rscale, NUMERIC_MIN_DISPLAY_SCALE); |
11199 | |
|
11200 | 0 | mul_var(&base_prod, &base_prod, &base_prod, local_rscale); |
11201 | |
|
11202 | 0 | if (mask & 1) |
11203 | 0 | { |
11204 | 0 | local_rscale = sig_digits - |
11205 | 0 | (base_prod.weight + result->weight) * DEC_DIGITS; |
11206 | 0 | local_rscale = Min(local_rscale, |
11207 | 0 | base_prod.dscale + result->dscale); |
11208 | 0 | local_rscale = Max(local_rscale, NUMERIC_MIN_DISPLAY_SCALE); |
11209 | |
|
11210 | 0 | mul_var(&base_prod, result, result, local_rscale); |
11211 | 0 | } |
11212 | | |
11213 | | /* |
11214 | | * When abs(base) > 1, the number of digits to the left of the decimal |
11215 | | * point in base_prod doubles at each iteration, so if exp is large we |
11216 | | * could easily spend large amounts of time and memory space doing the |
11217 | | * multiplications. But once the weight exceeds what will fit in |
11218 | | * int16, the final result is guaranteed to overflow (or underflow, if |
11219 | | * exp < 0), so we can give up before wasting too many cycles. |
11220 | | */ |
11221 | 0 | if (base_prod.weight > NUMERIC_WEIGHT_MAX || |
11222 | 0 | result->weight > NUMERIC_WEIGHT_MAX) |
11223 | 0 | { |
11224 | | /* overflow, unless neg, in which case result should be 0 */ |
11225 | 0 | if (!neg) |
11226 | 0 | ereport(ERROR, |
11227 | 0 | (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), |
11228 | 0 | errmsg("value overflows numeric format"))); |
11229 | 0 | zero_var(result); |
11230 | 0 | neg = false; |
11231 | 0 | break; |
11232 | 0 | } |
11233 | 0 | } |
11234 | | |
11235 | 0 | free_var(&base_prod); |
11236 | | |
11237 | | /* Compensate for input sign, and round to requested rscale */ |
11238 | 0 | if (neg) |
11239 | 0 | div_var(&const_one, result, result, rscale, true, false); |
11240 | 0 | else |
11241 | 0 | round_var(result, rscale); |
11242 | 0 | } |
11243 | | |
11244 | | /* |
11245 | | * power_ten_int() - |
11246 | | * |
11247 | | * Raise ten to the power of exp, where exp is an integer. Note that unlike |
11248 | | * power_var_int(), this does no overflow/underflow checking or rounding. |
11249 | | */ |
11250 | | static void |
11251 | | power_ten_int(int exp, NumericVar *result) |
11252 | 0 | { |
11253 | | /* Construct the result directly, starting from 10^0 = 1 */ |
11254 | 0 | set_var_from_var(&const_one, result); |
11255 | | |
11256 | | /* Scale needed to represent the result exactly */ |
11257 | 0 | result->dscale = exp < 0 ? -exp : 0; |
11258 | | |
11259 | | /* Base-NBASE weight of result and remaining exponent */ |
11260 | 0 | if (exp >= 0) |
11261 | 0 | result->weight = exp / DEC_DIGITS; |
11262 | 0 | else |
11263 | 0 | result->weight = (exp + 1) / DEC_DIGITS - 1; |
11264 | |
|
11265 | 0 | exp -= result->weight * DEC_DIGITS; |
11266 | | |
11267 | | /* Final adjustment of the result's single NBASE digit */ |
11268 | 0 | while (exp-- > 0) |
11269 | 0 | result->digits[0] *= 10; |
11270 | 0 | } |
11271 | | |
11272 | | /* |
11273 | | * random_var() - return a random value in the range [rmin, rmax]. |
11274 | | */ |
11275 | | static void |
11276 | | random_var(pg_prng_state *state, const NumericVar *rmin, |
11277 | | const NumericVar *rmax, NumericVar *result) |
11278 | 0 | { |
11279 | 0 | int rscale; |
11280 | 0 | NumericVar rlen; |
11281 | 0 | int res_ndigits; |
11282 | 0 | int n; |
11283 | 0 | int pow10; |
11284 | 0 | int i; |
11285 | 0 | uint64 rlen64; |
11286 | 0 | int rlen64_ndigits; |
11287 | |
|
11288 | 0 | rscale = Max(rmin->dscale, rmax->dscale); |
11289 | | |
11290 | | /* Compute rlen = rmax - rmin and check the range bounds */ |
11291 | 0 | init_var(&rlen); |
11292 | 0 | sub_var(rmax, rmin, &rlen); |
11293 | |
|
11294 | 0 | if (rlen.sign == NUMERIC_NEG) |
11295 | 0 | ereport(ERROR, |
11296 | 0 | errcode(ERRCODE_INVALID_PARAMETER_VALUE), |
11297 | 0 | errmsg("lower bound must be less than or equal to upper bound")); |
11298 | | |
11299 | | /* Special case for an empty range */ |
11300 | 0 | if (rlen.ndigits == 0) |
11301 | 0 | { |
11302 | 0 | set_var_from_var(rmin, result); |
11303 | 0 | result->dscale = rscale; |
11304 | 0 | free_var(&rlen); |
11305 | 0 | return; |
11306 | 0 | } |
11307 | | |
11308 | | /* |
11309 | | * Otherwise, select a random value in the range [0, rlen = rmax - rmin], |
11310 | | * and shift it to the required range by adding rmin. |
11311 | | */ |
11312 | | |
11313 | | /* Required result digits */ |
11314 | 0 | res_ndigits = rlen.weight + 1 + (rscale + DEC_DIGITS - 1) / DEC_DIGITS; |
11315 | | |
11316 | | /* |
11317 | | * To get the required rscale, the final result digit must be a multiple |
11318 | | * of pow10 = 10^n, where n = (-rscale) mod DEC_DIGITS. |
11319 | | */ |
11320 | 0 | n = ((rscale + DEC_DIGITS - 1) / DEC_DIGITS) * DEC_DIGITS - rscale; |
11321 | 0 | pow10 = 1; |
11322 | 0 | for (i = 0; i < n; i++) |
11323 | 0 | pow10 *= 10; |
11324 | | |
11325 | | /* |
11326 | | * To choose a random value uniformly from the range [0, rlen], we choose |
11327 | | * from the slightly larger range [0, rlen2], where rlen2 is formed from |
11328 | | * rlen by copying the first 4 NBASE digits, and setting all remaining |
11329 | | * decimal digits to "9". |
11330 | | * |
11331 | | * Without loss of generality, we can ignore the weight of rlen2 and treat |
11332 | | * it as a pure integer for the purposes of this discussion. The process |
11333 | | * above gives rlen2 + 1 = rlen64 * 10^N, for some integer N, where rlen64 |
11334 | | * is a 64-bit integer formed from the first 4 NBASE digits copied from |
11335 | | * rlen. Since this trivially factors into smaller pieces that fit in |
11336 | | * 64-bit integers, the task of choosing a random value uniformly from the |
11337 | | * rlen2 + 1 possible values in [0, rlen2] is much simpler. |
11338 | | * |
11339 | | * If the random value selected is too large, it is rejected, and we try |
11340 | | * again until we get a result <= rlen, ensuring that the overall result |
11341 | | * is uniform (no particular value is any more likely than any other). |
11342 | | * |
11343 | | * Since rlen64 holds 4 NBASE digits from rlen, it contains at least |
11344 | | * DEC_DIGITS * 3 + 1 decimal digits (i.e., at least 13 decimal digits, |
11345 | | * when DEC_DIGITS is 4). Therefore the probability of needing to reject |
11346 | | * the value chosen and retry is less than 1e-13. |
11347 | | */ |
11348 | 0 | rlen64 = (uint64) rlen.digits[0]; |
11349 | 0 | rlen64_ndigits = 1; |
11350 | 0 | while (rlen64_ndigits < res_ndigits && rlen64_ndigits < 4) |
11351 | 0 | { |
11352 | 0 | rlen64 *= NBASE; |
11353 | 0 | if (rlen64_ndigits < rlen.ndigits) |
11354 | 0 | rlen64 += rlen.digits[rlen64_ndigits]; |
11355 | 0 | rlen64_ndigits++; |
11356 | 0 | } |
11357 | | |
11358 | | /* Loop until we get a result <= rlen */ |
11359 | 0 | do |
11360 | 0 | { |
11361 | 0 | NumericDigit *res_digits; |
11362 | 0 | uint64 rand; |
11363 | 0 | int whole_ndigits; |
11364 | |
|
11365 | 0 | alloc_var(result, res_ndigits); |
11366 | 0 | result->sign = NUMERIC_POS; |
11367 | 0 | result->weight = rlen.weight; |
11368 | 0 | result->dscale = rscale; |
11369 | 0 | res_digits = result->digits; |
11370 | | |
11371 | | /* |
11372 | | * Set the first rlen64_ndigits using a random value in [0, rlen64]. |
11373 | | * |
11374 | | * If this is the whole result, and rscale is not a multiple of |
11375 | | * DEC_DIGITS (pow10 from above is not 1), then we need this to be a |
11376 | | * multiple of pow10. |
11377 | | */ |
11378 | 0 | if (rlen64_ndigits == res_ndigits && pow10 != 1) |
11379 | 0 | rand = pg_prng_uint64_range(state, 0, rlen64 / pow10) * pow10; |
11380 | 0 | else |
11381 | 0 | rand = pg_prng_uint64_range(state, 0, rlen64); |
11382 | |
|
11383 | 0 | for (i = rlen64_ndigits - 1; i >= 0; i--) |
11384 | 0 | { |
11385 | 0 | res_digits[i] = (NumericDigit) (rand % NBASE); |
11386 | 0 | rand = rand / NBASE; |
11387 | 0 | } |
11388 | | |
11389 | | /* |
11390 | | * Set the remaining digits to random values in range [0, NBASE), |
11391 | | * noting that the last digit needs to be a multiple of pow10. |
11392 | | */ |
11393 | 0 | whole_ndigits = res_ndigits; |
11394 | 0 | if (pow10 != 1) |
11395 | 0 | whole_ndigits--; |
11396 | | |
11397 | | /* Set whole digits in groups of 4 for best performance */ |
11398 | 0 | i = rlen64_ndigits; |
11399 | 0 | while (i < whole_ndigits - 3) |
11400 | 0 | { |
11401 | 0 | rand = pg_prng_uint64_range(state, 0, |
11402 | 0 | (uint64) NBASE * NBASE * NBASE * NBASE - 1); |
11403 | 0 | res_digits[i++] = (NumericDigit) (rand % NBASE); |
11404 | 0 | rand = rand / NBASE; |
11405 | 0 | res_digits[i++] = (NumericDigit) (rand % NBASE); |
11406 | 0 | rand = rand / NBASE; |
11407 | 0 | res_digits[i++] = (NumericDigit) (rand % NBASE); |
11408 | 0 | rand = rand / NBASE; |
11409 | 0 | res_digits[i++] = (NumericDigit) rand; |
11410 | 0 | } |
11411 | | |
11412 | | /* Remaining whole digits */ |
11413 | 0 | while (i < whole_ndigits) |
11414 | 0 | { |
11415 | 0 | rand = pg_prng_uint64_range(state, 0, NBASE - 1); |
11416 | 0 | res_digits[i++] = (NumericDigit) rand; |
11417 | 0 | } |
11418 | | |
11419 | | /* Final partial digit (multiple of pow10) */ |
11420 | 0 | if (i < res_ndigits) |
11421 | 0 | { |
11422 | 0 | rand = pg_prng_uint64_range(state, 0, NBASE / pow10 - 1) * pow10; |
11423 | 0 | res_digits[i] = (NumericDigit) rand; |
11424 | 0 | } |
11425 | | |
11426 | | /* Remove leading/trailing zeroes */ |
11427 | 0 | strip_var(result); |
11428 | | |
11429 | | /* If result > rlen, try again */ |
11430 | |
|
11431 | 0 | } while (cmp_var(result, &rlen) > 0); |
11432 | | |
11433 | | /* Offset the result to the required range */ |
11434 | 0 | add_var(result, rmin, result); |
11435 | |
|
11436 | 0 | free_var(&rlen); |
11437 | 0 | } |
11438 | | |
11439 | | |
11440 | | /* ---------------------------------------------------------------------- |
11441 | | * |
11442 | | * Following are the lowest level functions that operate unsigned |
11443 | | * on the variable level |
11444 | | * |
11445 | | * ---------------------------------------------------------------------- |
11446 | | */ |
11447 | | |
11448 | | |
11449 | | /* ---------- |
11450 | | * cmp_abs() - |
11451 | | * |
11452 | | * Compare the absolute values of var1 and var2 |
11453 | | * Returns: -1 for ABS(var1) < ABS(var2) |
11454 | | * 0 for ABS(var1) == ABS(var2) |
11455 | | * 1 for ABS(var1) > ABS(var2) |
11456 | | * ---------- |
11457 | | */ |
11458 | | static int |
11459 | | cmp_abs(const NumericVar *var1, const NumericVar *var2) |
11460 | 0 | { |
11461 | 0 | return cmp_abs_common(var1->digits, var1->ndigits, var1->weight, |
11462 | 0 | var2->digits, var2->ndigits, var2->weight); |
11463 | 0 | } |
11464 | | |
11465 | | /* ---------- |
11466 | | * cmp_abs_common() - |
11467 | | * |
11468 | | * Main routine of cmp_abs(). This function can be used by both |
11469 | | * NumericVar and Numeric. |
11470 | | * ---------- |
11471 | | */ |
11472 | | static int |
11473 | | cmp_abs_common(const NumericDigit *var1digits, int var1ndigits, int var1weight, |
11474 | | const NumericDigit *var2digits, int var2ndigits, int var2weight) |
11475 | 0 | { |
11476 | 0 | int i1 = 0; |
11477 | 0 | int i2 = 0; |
11478 | | |
11479 | | /* Check any digits before the first common digit */ |
11480 | |
|
11481 | 0 | while (var1weight > var2weight && i1 < var1ndigits) |
11482 | 0 | { |
11483 | 0 | if (var1digits[i1++] != 0) |
11484 | 0 | return 1; |
11485 | 0 | var1weight--; |
11486 | 0 | } |
11487 | 0 | while (var2weight > var1weight && i2 < var2ndigits) |
11488 | 0 | { |
11489 | 0 | if (var2digits[i2++] != 0) |
11490 | 0 | return -1; |
11491 | 0 | var2weight--; |
11492 | 0 | } |
11493 | | |
11494 | | /* At this point, either w1 == w2 or we've run out of digits */ |
11495 | | |
11496 | 0 | if (var1weight == var2weight) |
11497 | 0 | { |
11498 | 0 | while (i1 < var1ndigits && i2 < var2ndigits) |
11499 | 0 | { |
11500 | 0 | int stat = var1digits[i1++] - var2digits[i2++]; |
11501 | |
|
11502 | 0 | if (stat) |
11503 | 0 | { |
11504 | 0 | if (stat > 0) |
11505 | 0 | return 1; |
11506 | 0 | return -1; |
11507 | 0 | } |
11508 | 0 | } |
11509 | 0 | } |
11510 | | |
11511 | | /* |
11512 | | * At this point, we've run out of digits on one side or the other; so any |
11513 | | * remaining nonzero digits imply that side is larger |
11514 | | */ |
11515 | 0 | while (i1 < var1ndigits) |
11516 | 0 | { |
11517 | 0 | if (var1digits[i1++] != 0) |
11518 | 0 | return 1; |
11519 | 0 | } |
11520 | 0 | while (i2 < var2ndigits) |
11521 | 0 | { |
11522 | 0 | if (var2digits[i2++] != 0) |
11523 | 0 | return -1; |
11524 | 0 | } |
11525 | | |
11526 | 0 | return 0; |
11527 | 0 | } |
11528 | | |
11529 | | |
11530 | | /* |
11531 | | * add_abs() - |
11532 | | * |
11533 | | * Add the absolute values of two variables into result. |
11534 | | * result might point to one of the operands without danger. |
11535 | | */ |
11536 | | static void |
11537 | | add_abs(const NumericVar *var1, const NumericVar *var2, NumericVar *result) |
11538 | 0 | { |
11539 | 0 | NumericDigit *res_buf; |
11540 | 0 | NumericDigit *res_digits; |
11541 | 0 | int res_ndigits; |
11542 | 0 | int res_weight; |
11543 | 0 | int res_rscale, |
11544 | 0 | rscale1, |
11545 | 0 | rscale2; |
11546 | 0 | int res_dscale; |
11547 | 0 | int i, |
11548 | 0 | i1, |
11549 | 0 | i2; |
11550 | 0 | int carry = 0; |
11551 | | |
11552 | | /* copy these values into local vars for speed in inner loop */ |
11553 | 0 | int var1ndigits = var1->ndigits; |
11554 | 0 | int var2ndigits = var2->ndigits; |
11555 | 0 | NumericDigit *var1digits = var1->digits; |
11556 | 0 | NumericDigit *var2digits = var2->digits; |
11557 | |
|
11558 | 0 | res_weight = Max(var1->weight, var2->weight) + 1; |
11559 | |
|
11560 | 0 | res_dscale = Max(var1->dscale, var2->dscale); |
11561 | | |
11562 | | /* Note: here we are figuring rscale in base-NBASE digits */ |
11563 | 0 | rscale1 = var1->ndigits - var1->weight - 1; |
11564 | 0 | rscale2 = var2->ndigits - var2->weight - 1; |
11565 | 0 | res_rscale = Max(rscale1, rscale2); |
11566 | |
|
11567 | 0 | res_ndigits = res_rscale + res_weight + 1; |
11568 | 0 | if (res_ndigits <= 0) |
11569 | 0 | res_ndigits = 1; |
11570 | |
|
11571 | 0 | res_buf = digitbuf_alloc(res_ndigits + 1); |
11572 | 0 | res_buf[0] = 0; /* spare digit for later rounding */ |
11573 | 0 | res_digits = res_buf + 1; |
11574 | |
|
11575 | 0 | i1 = res_rscale + var1->weight + 1; |
11576 | 0 | i2 = res_rscale + var2->weight + 1; |
11577 | 0 | for (i = res_ndigits - 1; i >= 0; i--) |
11578 | 0 | { |
11579 | 0 | i1--; |
11580 | 0 | i2--; |
11581 | 0 | if (i1 >= 0 && i1 < var1ndigits) |
11582 | 0 | carry += var1digits[i1]; |
11583 | 0 | if (i2 >= 0 && i2 < var2ndigits) |
11584 | 0 | carry += var2digits[i2]; |
11585 | |
|
11586 | 0 | if (carry >= NBASE) |
11587 | 0 | { |
11588 | 0 | res_digits[i] = carry - NBASE; |
11589 | 0 | carry = 1; |
11590 | 0 | } |
11591 | 0 | else |
11592 | 0 | { |
11593 | 0 | res_digits[i] = carry; |
11594 | 0 | carry = 0; |
11595 | 0 | } |
11596 | 0 | } |
11597 | |
|
11598 | 0 | Assert(carry == 0); /* else we failed to allow for carry out */ |
11599 | |
|
11600 | 0 | digitbuf_free(result->buf); |
11601 | 0 | result->ndigits = res_ndigits; |
11602 | 0 | result->buf = res_buf; |
11603 | 0 | result->digits = res_digits; |
11604 | 0 | result->weight = res_weight; |
11605 | 0 | result->dscale = res_dscale; |
11606 | | |
11607 | | /* Remove leading/trailing zeroes */ |
11608 | 0 | strip_var(result); |
11609 | 0 | } |
11610 | | |
11611 | | |
11612 | | /* |
11613 | | * sub_abs() |
11614 | | * |
11615 | | * Subtract the absolute value of var2 from the absolute value of var1 |
11616 | | * and store in result. result might point to one of the operands |
11617 | | * without danger. |
11618 | | * |
11619 | | * ABS(var1) MUST BE GREATER OR EQUAL ABS(var2) !!! |
11620 | | */ |
11621 | | static void |
11622 | | sub_abs(const NumericVar *var1, const NumericVar *var2, NumericVar *result) |
11623 | 0 | { |
11624 | 0 | NumericDigit *res_buf; |
11625 | 0 | NumericDigit *res_digits; |
11626 | 0 | int res_ndigits; |
11627 | 0 | int res_weight; |
11628 | 0 | int res_rscale, |
11629 | 0 | rscale1, |
11630 | 0 | rscale2; |
11631 | 0 | int res_dscale; |
11632 | 0 | int i, |
11633 | 0 | i1, |
11634 | 0 | i2; |
11635 | 0 | int borrow = 0; |
11636 | | |
11637 | | /* copy these values into local vars for speed in inner loop */ |
11638 | 0 | int var1ndigits = var1->ndigits; |
11639 | 0 | int var2ndigits = var2->ndigits; |
11640 | 0 | NumericDigit *var1digits = var1->digits; |
11641 | 0 | NumericDigit *var2digits = var2->digits; |
11642 | |
|
11643 | 0 | res_weight = var1->weight; |
11644 | |
|
11645 | 0 | res_dscale = Max(var1->dscale, var2->dscale); |
11646 | | |
11647 | | /* Note: here we are figuring rscale in base-NBASE digits */ |
11648 | 0 | rscale1 = var1->ndigits - var1->weight - 1; |
11649 | 0 | rscale2 = var2->ndigits - var2->weight - 1; |
11650 | 0 | res_rscale = Max(rscale1, rscale2); |
11651 | |
|
11652 | 0 | res_ndigits = res_rscale + res_weight + 1; |
11653 | 0 | if (res_ndigits <= 0) |
11654 | 0 | res_ndigits = 1; |
11655 | |
|
11656 | 0 | res_buf = digitbuf_alloc(res_ndigits + 1); |
11657 | 0 | res_buf[0] = 0; /* spare digit for later rounding */ |
11658 | 0 | res_digits = res_buf + 1; |
11659 | |
|
11660 | 0 | i1 = res_rscale + var1->weight + 1; |
11661 | 0 | i2 = res_rscale + var2->weight + 1; |
11662 | 0 | for (i = res_ndigits - 1; i >= 0; i--) |
11663 | 0 | { |
11664 | 0 | i1--; |
11665 | 0 | i2--; |
11666 | 0 | if (i1 >= 0 && i1 < var1ndigits) |
11667 | 0 | borrow += var1digits[i1]; |
11668 | 0 | if (i2 >= 0 && i2 < var2ndigits) |
11669 | 0 | borrow -= var2digits[i2]; |
11670 | |
|
11671 | 0 | if (borrow < 0) |
11672 | 0 | { |
11673 | 0 | res_digits[i] = borrow + NBASE; |
11674 | 0 | borrow = -1; |
11675 | 0 | } |
11676 | 0 | else |
11677 | 0 | { |
11678 | 0 | res_digits[i] = borrow; |
11679 | 0 | borrow = 0; |
11680 | 0 | } |
11681 | 0 | } |
11682 | |
|
11683 | 0 | Assert(borrow == 0); /* else caller gave us var1 < var2 */ |
11684 | |
|
11685 | 0 | digitbuf_free(result->buf); |
11686 | 0 | result->ndigits = res_ndigits; |
11687 | 0 | result->buf = res_buf; |
11688 | 0 | result->digits = res_digits; |
11689 | 0 | result->weight = res_weight; |
11690 | 0 | result->dscale = res_dscale; |
11691 | | |
11692 | | /* Remove leading/trailing zeroes */ |
11693 | 0 | strip_var(result); |
11694 | 0 | } |
11695 | | |
11696 | | /* |
11697 | | * round_var |
11698 | | * |
11699 | | * Round the value of a variable to no more than rscale decimal digits |
11700 | | * after the decimal point. NOTE: we allow rscale < 0 here, implying |
11701 | | * rounding before the decimal point. |
11702 | | */ |
11703 | | static void |
11704 | | round_var(NumericVar *var, int rscale) |
11705 | 0 | { |
11706 | 0 | NumericDigit *digits = var->digits; |
11707 | 0 | int di; |
11708 | 0 | int ndigits; |
11709 | 0 | int carry; |
11710 | |
|
11711 | 0 | var->dscale = rscale; |
11712 | | |
11713 | | /* decimal digits wanted */ |
11714 | 0 | di = (var->weight + 1) * DEC_DIGITS + rscale; |
11715 | | |
11716 | | /* |
11717 | | * If di = 0, the value loses all digits, but could round up to 1 if its |
11718 | | * first extra digit is >= 5. If di < 0 the result must be 0. |
11719 | | */ |
11720 | 0 | if (di < 0) |
11721 | 0 | { |
11722 | 0 | var->ndigits = 0; |
11723 | 0 | var->weight = 0; |
11724 | 0 | var->sign = NUMERIC_POS; |
11725 | 0 | } |
11726 | 0 | else |
11727 | 0 | { |
11728 | | /* NBASE digits wanted */ |
11729 | 0 | ndigits = (di + DEC_DIGITS - 1) / DEC_DIGITS; |
11730 | | |
11731 | | /* 0, or number of decimal digits to keep in last NBASE digit */ |
11732 | 0 | di %= DEC_DIGITS; |
11733 | |
|
11734 | 0 | if (ndigits < var->ndigits || |
11735 | 0 | (ndigits == var->ndigits && di > 0)) |
11736 | 0 | { |
11737 | 0 | var->ndigits = ndigits; |
11738 | |
|
11739 | | #if DEC_DIGITS == 1 |
11740 | | /* di must be zero */ |
11741 | | carry = (digits[ndigits] >= HALF_NBASE) ? 1 : 0; |
11742 | | #else |
11743 | 0 | if (di == 0) |
11744 | 0 | carry = (digits[ndigits] >= HALF_NBASE) ? 1 : 0; |
11745 | 0 | else |
11746 | 0 | { |
11747 | | /* Must round within last NBASE digit */ |
11748 | 0 | int extra, |
11749 | 0 | pow10; |
11750 | |
|
11751 | 0 | #if DEC_DIGITS == 4 |
11752 | 0 | pow10 = round_powers[di]; |
11753 | | #elif DEC_DIGITS == 2 |
11754 | | pow10 = 10; |
11755 | | #else |
11756 | | #error unsupported NBASE |
11757 | | #endif |
11758 | 0 | extra = digits[--ndigits] % pow10; |
11759 | 0 | digits[ndigits] -= extra; |
11760 | 0 | carry = 0; |
11761 | 0 | if (extra >= pow10 / 2) |
11762 | 0 | { |
11763 | 0 | pow10 += digits[ndigits]; |
11764 | 0 | if (pow10 >= NBASE) |
11765 | 0 | { |
11766 | 0 | pow10 -= NBASE; |
11767 | 0 | carry = 1; |
11768 | 0 | } |
11769 | 0 | digits[ndigits] = pow10; |
11770 | 0 | } |
11771 | 0 | } |
11772 | 0 | #endif |
11773 | | |
11774 | | /* Propagate carry if needed */ |
11775 | 0 | while (carry) |
11776 | 0 | { |
11777 | 0 | carry += digits[--ndigits]; |
11778 | 0 | if (carry >= NBASE) |
11779 | 0 | { |
11780 | 0 | digits[ndigits] = carry - NBASE; |
11781 | 0 | carry = 1; |
11782 | 0 | } |
11783 | 0 | else |
11784 | 0 | { |
11785 | 0 | digits[ndigits] = carry; |
11786 | 0 | carry = 0; |
11787 | 0 | } |
11788 | 0 | } |
11789 | |
|
11790 | 0 | if (ndigits < 0) |
11791 | 0 | { |
11792 | 0 | Assert(ndigits == -1); /* better not have added > 1 digit */ |
11793 | 0 | Assert(var->digits > var->buf); |
11794 | 0 | var->digits--; |
11795 | 0 | var->ndigits++; |
11796 | 0 | var->weight++; |
11797 | 0 | } |
11798 | 0 | } |
11799 | 0 | } |
11800 | 0 | } |
11801 | | |
11802 | | /* |
11803 | | * trunc_var |
11804 | | * |
11805 | | * Truncate (towards zero) the value of a variable at rscale decimal digits |
11806 | | * after the decimal point. NOTE: we allow rscale < 0 here, implying |
11807 | | * truncation before the decimal point. |
11808 | | */ |
11809 | | static void |
11810 | | trunc_var(NumericVar *var, int rscale) |
11811 | 0 | { |
11812 | 0 | int di; |
11813 | 0 | int ndigits; |
11814 | |
|
11815 | 0 | var->dscale = rscale; |
11816 | | |
11817 | | /* decimal digits wanted */ |
11818 | 0 | di = (var->weight + 1) * DEC_DIGITS + rscale; |
11819 | | |
11820 | | /* |
11821 | | * If di <= 0, the value loses all digits. |
11822 | | */ |
11823 | 0 | if (di <= 0) |
11824 | 0 | { |
11825 | 0 | var->ndigits = 0; |
11826 | 0 | var->weight = 0; |
11827 | 0 | var->sign = NUMERIC_POS; |
11828 | 0 | } |
11829 | 0 | else |
11830 | 0 | { |
11831 | | /* NBASE digits wanted */ |
11832 | 0 | ndigits = (di + DEC_DIGITS - 1) / DEC_DIGITS; |
11833 | |
|
11834 | 0 | if (ndigits <= var->ndigits) |
11835 | 0 | { |
11836 | 0 | var->ndigits = ndigits; |
11837 | |
|
11838 | | #if DEC_DIGITS == 1 |
11839 | | /* no within-digit stuff to worry about */ |
11840 | | #else |
11841 | | /* 0, or number of decimal digits to keep in last NBASE digit */ |
11842 | 0 | di %= DEC_DIGITS; |
11843 | |
|
11844 | 0 | if (di > 0) |
11845 | 0 | { |
11846 | | /* Must truncate within last NBASE digit */ |
11847 | 0 | NumericDigit *digits = var->digits; |
11848 | 0 | int extra, |
11849 | 0 | pow10; |
11850 | |
|
11851 | 0 | #if DEC_DIGITS == 4 |
11852 | 0 | pow10 = round_powers[di]; |
11853 | | #elif DEC_DIGITS == 2 |
11854 | | pow10 = 10; |
11855 | | #else |
11856 | | #error unsupported NBASE |
11857 | | #endif |
11858 | 0 | extra = digits[--ndigits] % pow10; |
11859 | 0 | digits[ndigits] -= extra; |
11860 | 0 | } |
11861 | 0 | #endif |
11862 | 0 | } |
11863 | 0 | } |
11864 | 0 | } |
11865 | | |
11866 | | /* |
11867 | | * strip_var |
11868 | | * |
11869 | | * Strip any leading and trailing zeroes from a numeric variable |
11870 | | */ |
11871 | | static void |
11872 | | strip_var(NumericVar *var) |
11873 | 0 | { |
11874 | 0 | NumericDigit *digits = var->digits; |
11875 | 0 | int ndigits = var->ndigits; |
11876 | | |
11877 | | /* Strip leading zeroes */ |
11878 | 0 | while (ndigits > 0 && *digits == 0) |
11879 | 0 | { |
11880 | 0 | digits++; |
11881 | 0 | var->weight--; |
11882 | 0 | ndigits--; |
11883 | 0 | } |
11884 | | |
11885 | | /* Strip trailing zeroes */ |
11886 | 0 | while (ndigits > 0 && digits[ndigits - 1] == 0) |
11887 | 0 | ndigits--; |
11888 | | |
11889 | | /* If it's zero, normalize the sign and weight */ |
11890 | 0 | if (ndigits == 0) |
11891 | 0 | { |
11892 | 0 | var->sign = NUMERIC_POS; |
11893 | 0 | var->weight = 0; |
11894 | 0 | } |
11895 | |
|
11896 | 0 | var->digits = digits; |
11897 | 0 | var->ndigits = ndigits; |
11898 | 0 | } |
11899 | | |
11900 | | |
11901 | | /* ---------------------------------------------------------------------- |
11902 | | * |
11903 | | * Fast sum accumulator functions |
11904 | | * |
11905 | | * ---------------------------------------------------------------------- |
11906 | | */ |
11907 | | |
11908 | | /* |
11909 | | * Reset the accumulator's value to zero. The buffers to hold the digits |
11910 | | * are not free'd. |
11911 | | */ |
11912 | | static void |
11913 | | accum_sum_reset(NumericSumAccum *accum) |
11914 | 0 | { |
11915 | 0 | int i; |
11916 | |
|
11917 | 0 | accum->dscale = 0; |
11918 | 0 | for (i = 0; i < accum->ndigits; i++) |
11919 | 0 | { |
11920 | 0 | accum->pos_digits[i] = 0; |
11921 | 0 | accum->neg_digits[i] = 0; |
11922 | 0 | } |
11923 | 0 | } |
11924 | | |
11925 | | /* |
11926 | | * Accumulate a new value. |
11927 | | */ |
11928 | | static void |
11929 | | accum_sum_add(NumericSumAccum *accum, const NumericVar *val) |
11930 | 0 | { |
11931 | 0 | int32 *accum_digits; |
11932 | 0 | int val_ndigits; |
11933 | 0 | NumericDigit *val_digits; |
11934 | | |
11935 | | /* |
11936 | | * If we have accumulated too many values since the last carry |
11937 | | * propagation, do it now, to avoid overflowing. (We could allow more |
11938 | | * than NBASE - 1, if we reserved two extra digits, rather than one, for |
11939 | | * carry propagation. But even with NBASE - 1, this needs to be done so |
11940 | | * seldom, that the performance difference is negligible.) |
11941 | | */ |
11942 | 0 | if (accum->num_uncarried == NBASE - 1) |
11943 | 0 | accum_sum_carry(accum); |
11944 | | |
11945 | | /* |
11946 | | * Adjust the weight or scale of the old value, so that it can accommodate |
11947 | | * the new value. |
11948 | | */ |
11949 | 0 | accum_sum_rescale(accum, val); |
11950 | | |
11951 | | /* */ |
11952 | 0 | if (val->sign == NUMERIC_POS) |
11953 | 0 | accum_digits = accum->pos_digits; |
11954 | 0 | else |
11955 | 0 | accum_digits = accum->neg_digits; |
11956 | | |
11957 | | /* copy these values into local vars for speed in loop */ |
11958 | 0 | val_ndigits = val->ndigits; |
11959 | 0 | val_digits = val->digits; |
11960 | |
|
11961 | 0 | accum_digits += accum->weight - val->weight; |
11962 | 0 | for (int i = 0; i < val_ndigits; i++) |
11963 | 0 | accum_digits[i] += (int32) val_digits[i]; |
11964 | |
|
11965 | 0 | accum->num_uncarried++; |
11966 | 0 | } |
11967 | | |
11968 | | /* |
11969 | | * Propagate carries. |
11970 | | */ |
11971 | | static void |
11972 | | accum_sum_carry(NumericSumAccum *accum) |
11973 | 0 | { |
11974 | 0 | int i; |
11975 | 0 | int ndigits; |
11976 | 0 | int32 *dig; |
11977 | 0 | int32 carry; |
11978 | 0 | int32 newdig = 0; |
11979 | | |
11980 | | /* |
11981 | | * If no new values have been added since last carry propagation, nothing |
11982 | | * to do. |
11983 | | */ |
11984 | 0 | if (accum->num_uncarried == 0) |
11985 | 0 | return; |
11986 | | |
11987 | | /* |
11988 | | * We maintain that the weight of the accumulator is always one larger |
11989 | | * than needed to hold the current value, before carrying, to make sure |
11990 | | * there is enough space for the possible extra digit when carry is |
11991 | | * propagated. We cannot expand the buffer here, unless we require |
11992 | | * callers of accum_sum_final() to switch to the right memory context. |
11993 | | */ |
11994 | 0 | Assert(accum->pos_digits[0] == 0 && accum->neg_digits[0] == 0); |
11995 | |
|
11996 | 0 | ndigits = accum->ndigits; |
11997 | | |
11998 | | /* Propagate carry in the positive sum */ |
11999 | 0 | dig = accum->pos_digits; |
12000 | 0 | carry = 0; |
12001 | 0 | for (i = ndigits - 1; i >= 0; i--) |
12002 | 0 | { |
12003 | 0 | newdig = dig[i] + carry; |
12004 | 0 | if (newdig >= NBASE) |
12005 | 0 | { |
12006 | 0 | carry = newdig / NBASE; |
12007 | 0 | newdig -= carry * NBASE; |
12008 | 0 | } |
12009 | 0 | else |
12010 | 0 | carry = 0; |
12011 | 0 | dig[i] = newdig; |
12012 | 0 | } |
12013 | | /* Did we use up the digit reserved for carry propagation? */ |
12014 | 0 | if (newdig > 0) |
12015 | 0 | accum->have_carry_space = false; |
12016 | | |
12017 | | /* And the same for the negative sum */ |
12018 | 0 | dig = accum->neg_digits; |
12019 | 0 | carry = 0; |
12020 | 0 | for (i = ndigits - 1; i >= 0; i--) |
12021 | 0 | { |
12022 | 0 | newdig = dig[i] + carry; |
12023 | 0 | if (newdig >= NBASE) |
12024 | 0 | { |
12025 | 0 | carry = newdig / NBASE; |
12026 | 0 | newdig -= carry * NBASE; |
12027 | 0 | } |
12028 | 0 | else |
12029 | 0 | carry = 0; |
12030 | 0 | dig[i] = newdig; |
12031 | 0 | } |
12032 | 0 | if (newdig > 0) |
12033 | 0 | accum->have_carry_space = false; |
12034 | |
|
12035 | 0 | accum->num_uncarried = 0; |
12036 | 0 | } |
12037 | | |
12038 | | /* |
12039 | | * Re-scale accumulator to accommodate new value. |
12040 | | * |
12041 | | * If the new value has more digits than the current digit buffers in the |
12042 | | * accumulator, enlarge the buffers. |
12043 | | */ |
12044 | | static void |
12045 | | accum_sum_rescale(NumericSumAccum *accum, const NumericVar *val) |
12046 | 0 | { |
12047 | 0 | int old_weight = accum->weight; |
12048 | 0 | int old_ndigits = accum->ndigits; |
12049 | 0 | int accum_ndigits; |
12050 | 0 | int accum_weight; |
12051 | 0 | int accum_rscale; |
12052 | 0 | int val_rscale; |
12053 | |
|
12054 | 0 | accum_weight = old_weight; |
12055 | 0 | accum_ndigits = old_ndigits; |
12056 | | |
12057 | | /* |
12058 | | * Does the new value have a larger weight? If so, enlarge the buffers, |
12059 | | * and shift the existing value to the new weight, by adding leading |
12060 | | * zeros. |
12061 | | * |
12062 | | * We enforce that the accumulator always has a weight one larger than |
12063 | | * needed for the inputs, so that we have space for an extra digit at the |
12064 | | * final carry-propagation phase, if necessary. |
12065 | | */ |
12066 | 0 | if (val->weight >= accum_weight) |
12067 | 0 | { |
12068 | 0 | accum_weight = val->weight + 1; |
12069 | 0 | accum_ndigits = accum_ndigits + (accum_weight - old_weight); |
12070 | 0 | } |
12071 | | |
12072 | | /* |
12073 | | * Even though the new value is small, we might've used up the space |
12074 | | * reserved for the carry digit in the last call to accum_sum_carry(). If |
12075 | | * so, enlarge to make room for another one. |
12076 | | */ |
12077 | 0 | else if (!accum->have_carry_space) |
12078 | 0 | { |
12079 | 0 | accum_weight++; |
12080 | 0 | accum_ndigits++; |
12081 | 0 | } |
12082 | | |
12083 | | /* Is the new value wider on the right side? */ |
12084 | 0 | accum_rscale = accum_ndigits - accum_weight - 1; |
12085 | 0 | val_rscale = val->ndigits - val->weight - 1; |
12086 | 0 | if (val_rscale > accum_rscale) |
12087 | 0 | accum_ndigits = accum_ndigits + (val_rscale - accum_rscale); |
12088 | |
|
12089 | 0 | if (accum_ndigits != old_ndigits || |
12090 | 0 | accum_weight != old_weight) |
12091 | 0 | { |
12092 | 0 | int32 *new_pos_digits; |
12093 | 0 | int32 *new_neg_digits; |
12094 | 0 | int weightdiff; |
12095 | |
|
12096 | 0 | weightdiff = accum_weight - old_weight; |
12097 | |
|
12098 | 0 | new_pos_digits = palloc0_array(int32, accum_ndigits); |
12099 | 0 | new_neg_digits = palloc0_array(int32, accum_ndigits); |
12100 | |
|
12101 | 0 | if (accum->pos_digits) |
12102 | 0 | { |
12103 | 0 | memcpy(&new_pos_digits[weightdiff], accum->pos_digits, |
12104 | 0 | old_ndigits * sizeof(int32)); |
12105 | 0 | pfree(accum->pos_digits); |
12106 | |
|
12107 | 0 | memcpy(&new_neg_digits[weightdiff], accum->neg_digits, |
12108 | 0 | old_ndigits * sizeof(int32)); |
12109 | 0 | pfree(accum->neg_digits); |
12110 | 0 | } |
12111 | |
|
12112 | 0 | accum->pos_digits = new_pos_digits; |
12113 | 0 | accum->neg_digits = new_neg_digits; |
12114 | |
|
12115 | 0 | accum->weight = accum_weight; |
12116 | 0 | accum->ndigits = accum_ndigits; |
12117 | |
|
12118 | 0 | Assert(accum->pos_digits[0] == 0 && accum->neg_digits[0] == 0); |
12119 | 0 | accum->have_carry_space = true; |
12120 | 0 | } |
12121 | |
|
12122 | 0 | if (val->dscale > accum->dscale) |
12123 | 0 | accum->dscale = val->dscale; |
12124 | 0 | } |
12125 | | |
12126 | | /* |
12127 | | * Return the current value of the accumulator. This perform final carry |
12128 | | * propagation, and adds together the positive and negative sums. |
12129 | | * |
12130 | | * Unlike all the other routines, the caller is not required to switch to |
12131 | | * the memory context that holds the accumulator. |
12132 | | */ |
12133 | | static void |
12134 | | accum_sum_final(NumericSumAccum *accum, NumericVar *result) |
12135 | 0 | { |
12136 | 0 | int i; |
12137 | 0 | NumericVar pos_var; |
12138 | 0 | NumericVar neg_var; |
12139 | |
|
12140 | 0 | if (accum->ndigits == 0) |
12141 | 0 | { |
12142 | 0 | set_var_from_var(&const_zero, result); |
12143 | 0 | return; |
12144 | 0 | } |
12145 | | |
12146 | | /* Perform final carry */ |
12147 | 0 | accum_sum_carry(accum); |
12148 | | |
12149 | | /* Create NumericVars representing the positive and negative sums */ |
12150 | 0 | init_var(&pos_var); |
12151 | 0 | init_var(&neg_var); |
12152 | |
|
12153 | 0 | pos_var.ndigits = neg_var.ndigits = accum->ndigits; |
12154 | 0 | pos_var.weight = neg_var.weight = accum->weight; |
12155 | 0 | pos_var.dscale = neg_var.dscale = accum->dscale; |
12156 | 0 | pos_var.sign = NUMERIC_POS; |
12157 | 0 | neg_var.sign = NUMERIC_NEG; |
12158 | |
|
12159 | 0 | pos_var.buf = pos_var.digits = digitbuf_alloc(accum->ndigits); |
12160 | 0 | neg_var.buf = neg_var.digits = digitbuf_alloc(accum->ndigits); |
12161 | |
|
12162 | 0 | for (i = 0; i < accum->ndigits; i++) |
12163 | 0 | { |
12164 | 0 | Assert(accum->pos_digits[i] < NBASE); |
12165 | 0 | pos_var.digits[i] = (int16) accum->pos_digits[i]; |
12166 | |
|
12167 | 0 | Assert(accum->neg_digits[i] < NBASE); |
12168 | 0 | neg_var.digits[i] = (int16) accum->neg_digits[i]; |
12169 | 0 | } |
12170 | | |
12171 | | /* And add them together */ |
12172 | 0 | add_var(&pos_var, &neg_var, result); |
12173 | | |
12174 | | /* Remove leading/trailing zeroes */ |
12175 | 0 | strip_var(result); |
12176 | 0 | } |
12177 | | |
12178 | | /* |
12179 | | * Copy an accumulator's state. |
12180 | | * |
12181 | | * 'dst' is assumed to be uninitialized beforehand. No attempt is made at |
12182 | | * freeing old values. |
12183 | | */ |
12184 | | static void |
12185 | | accum_sum_copy(NumericSumAccum *dst, NumericSumAccum *src) |
12186 | 0 | { |
12187 | 0 | dst->pos_digits = palloc_array(int32, src->ndigits); |
12188 | 0 | dst->neg_digits = palloc_array(int32, src->ndigits); |
12189 | |
|
12190 | 0 | memcpy(dst->pos_digits, src->pos_digits, src->ndigits * sizeof(int32)); |
12191 | 0 | memcpy(dst->neg_digits, src->neg_digits, src->ndigits * sizeof(int32)); |
12192 | 0 | dst->num_uncarried = src->num_uncarried; |
12193 | 0 | dst->ndigits = src->ndigits; |
12194 | 0 | dst->weight = src->weight; |
12195 | 0 | dst->dscale = src->dscale; |
12196 | 0 | } |
12197 | | |
12198 | | /* |
12199 | | * Add the current value of 'accum2' into 'accum'. |
12200 | | */ |
12201 | | static void |
12202 | | accum_sum_combine(NumericSumAccum *accum, NumericSumAccum *accum2) |
12203 | 0 | { |
12204 | 0 | NumericVar tmp_var; |
12205 | |
|
12206 | 0 | init_var(&tmp_var); |
12207 | |
|
12208 | 0 | accum_sum_final(accum2, &tmp_var); |
12209 | 0 | accum_sum_add(accum, &tmp_var); |
12210 | |
|
12211 | 0 | free_var(&tmp_var); |
12212 | 0 | } |