Allow leading and trailing spaces around NaN in numeric_in.
[PostgreSQL.git] / src / backend / utils / adt / numeric.c
blobb9cd45bbfed7c490e38ac6543b310653fc9ff586
1 /*-------------------------------------------------------------------------
3 * numeric.c
4 * An exact numeric data type for the Postgres database system
6 * Original coding 1998, Jan Wieck. Heavily revised 2003, Tom Lane.
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.
14 * Copyright (c) 1998-2009, PostgreSQL Global Development Group
16 * IDENTIFICATION
17 * $PostgreSQL$
19 *-------------------------------------------------------------------------
22 #include "postgres.h"
24 #include <ctype.h>
25 #include <float.h>
26 #include <limits.h>
27 #include <math.h>
29 #include "access/hash.h"
30 #include "catalog/pg_type.h"
31 #include "libpq/pqformat.h"
32 #include "miscadmin.h"
33 #include "utils/array.h"
34 #include "utils/builtins.h"
35 #include "utils/int8.h"
36 #include "utils/numeric.h"
38 /* ----------
39 * Uncomment the following to enable compilation of dump_numeric()
40 * and dump_var() and to get a dump of any result produced by make_result().
41 * ----------
42 #define NUMERIC_DEBUG
46 /* ----------
47 * Local data types
49 * Numeric values are represented in a base-NBASE floating point format.
50 * Each "digit" ranges from 0 to NBASE-1. The type NumericDigit is signed
51 * and wide enough to store a digit. We assume that NBASE*NBASE can fit in
52 * an int. Although the purely calculational routines could handle any even
53 * NBASE that's less than sqrt(INT_MAX), in practice we are only interested
54 * in NBASE a power of ten, so that I/O conversions and decimal rounding
55 * are easy. Also, it's actually more efficient if NBASE is rather less than
56 * sqrt(INT_MAX), so that there is "headroom" for mul_var and div_var_fast to
57 * postpone processing carries.
58 * ----------
61 #if 0
62 #define NBASE 10
63 #define HALF_NBASE 5
64 #define DEC_DIGITS 1 /* decimal digits per NBASE digit */
65 #define MUL_GUARD_DIGITS 4 /* these are measured in NBASE digits */
66 #define DIV_GUARD_DIGITS 8
68 typedef signed char NumericDigit;
69 #endif
71 #if 0
72 #define NBASE 100
73 #define HALF_NBASE 50
74 #define DEC_DIGITS 2 /* decimal digits per NBASE digit */
75 #define MUL_GUARD_DIGITS 3 /* these are measured in NBASE digits */
76 #define DIV_GUARD_DIGITS 6
78 typedef signed char NumericDigit;
79 #endif
81 #if 1
82 #define NBASE 10000
83 #define HALF_NBASE 5000
84 #define DEC_DIGITS 4 /* decimal digits per NBASE digit */
85 #define MUL_GUARD_DIGITS 2 /* these are measured in NBASE digits */
86 #define DIV_GUARD_DIGITS 4
88 typedef int16 NumericDigit;
89 #endif
92 /* ----------
93 * NumericVar is the format we use for arithmetic. The digit-array part
94 * is the same as the NumericData storage format, but the header is more
95 * complex.
97 * The value represented by a NumericVar is determined by the sign, weight,
98 * ndigits, and digits[] array.
99 * Note: the first digit of a NumericVar's value is assumed to be multiplied
100 * by NBASE ** weight. Another way to say it is that there are weight+1
101 * digits before the decimal point. It is possible to have weight < 0.
103 * buf points at the physical start of the palloc'd digit buffer for the
104 * NumericVar. digits points at the first digit in actual use (the one
105 * with the specified weight). We normally leave an unused digit or two
106 * (preset to zeroes) between buf and digits, so that there is room to store
107 * a carry out of the top digit without reallocating space. We just need to
108 * decrement digits (and increment weight) to make room for the carry digit.
109 * (There is no such extra space in a numeric value stored in the database,
110 * only in a NumericVar in memory.)
112 * If buf is NULL then the digit buffer isn't actually palloc'd and should
113 * not be freed --- see the constants below for an example.
115 * dscale, or display scale, is the nominal precision expressed as number
116 * of digits after the decimal point (it must always be >= 0 at present).
117 * dscale may be more than the number of physically stored fractional digits,
118 * implying that we have suppressed storage of significant trailing zeroes.
119 * It should never be less than the number of stored digits, since that would
120 * imply hiding digits that are present. NOTE that dscale is always expressed
121 * in *decimal* digits, and so it may correspond to a fractional number of
122 * base-NBASE digits --- divide by DEC_DIGITS to convert to NBASE digits.
124 * rscale, or result scale, is the target precision for a computation.
125 * Like dscale it is expressed as number of *decimal* digits after the decimal
126 * point, and is always >= 0 at present.
127 * Note that rscale is not stored in variables --- it's figured on-the-fly
128 * from the dscales of the inputs.
130 * NB: All the variable-level functions are written in a style that makes it
131 * possible to give one and the same variable as argument and destination.
132 * This is feasible because the digit buffer is separate from the variable.
133 * ----------
135 typedef struct NumericVar
137 int ndigits; /* # of digits in digits[] - can be 0! */
138 int weight; /* weight of first digit */
139 int sign; /* NUMERIC_POS, NUMERIC_NEG, or NUMERIC_NAN */
140 int dscale; /* display scale */
141 NumericDigit *buf; /* start of palloc'd space for digits[] */
142 NumericDigit *digits; /* base-NBASE digits */
143 } NumericVar;
146 /* ----------
147 * Some preinitialized constants
148 * ----------
150 static NumericDigit const_zero_data[1] = {0};
151 static NumericVar const_zero =
152 {0, 0, NUMERIC_POS, 0, NULL, const_zero_data};
154 static NumericDigit const_one_data[1] = {1};
155 static NumericVar const_one =
156 {1, 0, NUMERIC_POS, 0, NULL, const_one_data};
158 static NumericDigit const_two_data[1] = {2};
159 static NumericVar const_two =
160 {1, 0, NUMERIC_POS, 0, NULL, const_two_data};
162 #if DEC_DIGITS == 4
163 static NumericDigit const_zero_point_five_data[1] = {5000};
164 #elif DEC_DIGITS == 2
165 static NumericDigit const_zero_point_five_data[1] = {50};
166 #elif DEC_DIGITS == 1
167 static NumericDigit const_zero_point_five_data[1] = {5};
168 #endif
169 static NumericVar const_zero_point_five =
170 {1, -1, NUMERIC_POS, 1, NULL, const_zero_point_five_data};
172 #if DEC_DIGITS == 4
173 static NumericDigit const_zero_point_nine_data[1] = {9000};
174 #elif DEC_DIGITS == 2
175 static NumericDigit const_zero_point_nine_data[1] = {90};
176 #elif DEC_DIGITS == 1
177 static NumericDigit const_zero_point_nine_data[1] = {9};
178 #endif
179 static NumericVar const_zero_point_nine =
180 {1, -1, NUMERIC_POS, 1, NULL, const_zero_point_nine_data};
182 #if DEC_DIGITS == 4
183 static NumericDigit const_zero_point_01_data[1] = {100};
184 static NumericVar const_zero_point_01 =
185 {1, -1, NUMERIC_POS, 2, NULL, const_zero_point_01_data};
186 #elif DEC_DIGITS == 2
187 static NumericDigit const_zero_point_01_data[1] = {1};
188 static NumericVar const_zero_point_01 =
189 {1, -1, NUMERIC_POS, 2, NULL, const_zero_point_01_data};
190 #elif DEC_DIGITS == 1
191 static NumericDigit const_zero_point_01_data[1] = {1};
192 static NumericVar const_zero_point_01 =
193 {1, -2, NUMERIC_POS, 2, NULL, const_zero_point_01_data};
194 #endif
196 #if DEC_DIGITS == 4
197 static NumericDigit const_one_point_one_data[2] = {1, 1000};
198 #elif DEC_DIGITS == 2
199 static NumericDigit const_one_point_one_data[2] = {1, 10};
200 #elif DEC_DIGITS == 1
201 static NumericDigit const_one_point_one_data[2] = {1, 1};
202 #endif
203 static NumericVar const_one_point_one =
204 {2, 0, NUMERIC_POS, 1, NULL, const_one_point_one_data};
206 static NumericVar const_nan =
207 {0, 0, NUMERIC_NAN, 0, NULL, NULL};
209 #if DEC_DIGITS == 4
210 static const int round_powers[4] = {0, 1000, 100, 10};
211 #endif
214 /* ----------
215 * Local functions
216 * ----------
219 #ifdef NUMERIC_DEBUG
220 static void dump_numeric(const char *str, Numeric num);
221 static void dump_var(const char *str, NumericVar *var);
222 #else
223 #define dump_numeric(s,n)
224 #define dump_var(s,v)
225 #endif
227 #define digitbuf_alloc(ndigits) \
228 ((NumericDigit *) palloc((ndigits) * sizeof(NumericDigit)))
229 #define digitbuf_free(buf) \
230 do { \
231 if ((buf) != NULL) \
232 pfree(buf); \
233 } while (0)
235 #define init_var(v) MemSetAligned(v, 0, sizeof(NumericVar))
237 #define NUMERIC_DIGITS(num) ((NumericDigit *)(num)->n_data)
238 #define NUMERIC_NDIGITS(num) \
239 ((VARSIZE(num) - NUMERIC_HDRSZ) / sizeof(NumericDigit))
241 static void alloc_var(NumericVar *var, int ndigits);
242 static void free_var(NumericVar *var);
243 static void zero_var(NumericVar *var);
245 static const char *set_var_from_str(const char *str, const char *cp,
246 NumericVar *dest);
247 static void set_var_from_num(Numeric value, NumericVar *dest);
248 static void set_var_from_var(NumericVar *value, NumericVar *dest);
249 static char *get_str_from_var(NumericVar *var, int dscale);
251 static Numeric make_result(NumericVar *var);
253 static void apply_typmod(NumericVar *var, int32 typmod);
255 static int32 numericvar_to_int4(NumericVar *var);
256 static bool numericvar_to_int8(NumericVar *var, int64 *result);
257 static void int8_to_numericvar(int64 val, NumericVar *var);
258 static double numeric_to_double_no_overflow(Numeric num);
259 static double numericvar_to_double_no_overflow(NumericVar *var);
261 static int cmp_numerics(Numeric num1, Numeric num2);
262 static int cmp_var(NumericVar *var1, NumericVar *var2);
263 static int cmp_var_common(const NumericDigit *var1digits, int var1ndigits,
264 int var1weight, int var1sign,
265 const NumericDigit *var2digits, int var2ndigits,
266 int var2weight, int var2sign);
267 static void add_var(NumericVar *var1, NumericVar *var2, NumericVar *result);
268 static void sub_var(NumericVar *var1, NumericVar *var2, NumericVar *result);
269 static void mul_var(NumericVar *var1, NumericVar *var2, NumericVar *result,
270 int rscale);
271 static void div_var(NumericVar *var1, NumericVar *var2, NumericVar *result,
272 int rscale, bool round);
273 static void div_var_fast(NumericVar *var1, NumericVar *var2, NumericVar *result,
274 int rscale, bool round);
275 static int select_div_scale(NumericVar *var1, NumericVar *var2);
276 static void mod_var(NumericVar *var1, NumericVar *var2, NumericVar *result);
277 static void ceil_var(NumericVar *var, NumericVar *result);
278 static void floor_var(NumericVar *var, NumericVar *result);
280 static void sqrt_var(NumericVar *arg, NumericVar *result, int rscale);
281 static void exp_var(NumericVar *arg, NumericVar *result, int rscale);
282 static void exp_var_internal(NumericVar *arg, NumericVar *result, int rscale);
283 static void ln_var(NumericVar *arg, NumericVar *result, int rscale);
284 static void log_var(NumericVar *base, NumericVar *num, NumericVar *result);
285 static void power_var(NumericVar *base, NumericVar *exp, NumericVar *result);
286 static void power_var_int(NumericVar *base, int exp, NumericVar *result,
287 int rscale);
289 static int cmp_abs(NumericVar *var1, NumericVar *var2);
290 static int cmp_abs_common(const NumericDigit *var1digits, int var1ndigits,
291 int var1weight,
292 const NumericDigit *var2digits, int var2ndigits,
293 int var2weight);
294 static void add_abs(NumericVar *var1, NumericVar *var2, NumericVar *result);
295 static void sub_abs(NumericVar *var1, NumericVar *var2, NumericVar *result);
296 static void round_var(NumericVar *var, int rscale);
297 static void trunc_var(NumericVar *var, int rscale);
298 static void strip_var(NumericVar *var);
299 static void compute_bucket(Numeric operand, Numeric bound1, Numeric bound2,
300 NumericVar *count_var, NumericVar *result_var);
303 /* ----------------------------------------------------------------------
305 * Input-, output- and rounding-functions
307 * ----------------------------------------------------------------------
312 * numeric_in() -
314 * Input function for numeric data type
316 Datum
317 numeric_in(PG_FUNCTION_ARGS)
319 char *str = PG_GETARG_CSTRING(0);
321 #ifdef NOT_USED
322 Oid typelem = PG_GETARG_OID(1);
323 #endif
324 int32 typmod = PG_GETARG_INT32(2);
325 Numeric res;
326 const char *cp;
328 /* Skip leading spaces */
329 cp = str;
330 while (*cp)
332 if (!isspace((unsigned char) *cp))
333 break;
334 cp++;
338 * Check for NaN
340 if (pg_strncasecmp(cp, "NaN", 3) == 0)
342 res = make_result(&const_nan);
344 /* Should be nothing left but spaces */
345 cp += 3;
346 while (*cp)
348 if (!isspace((unsigned char) *cp))
349 ereport(ERROR,
350 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
351 errmsg("invalid input syntax for type numeric: \"%s\"",
352 str)));
353 cp++;
356 else
359 * Use set_var_from_str() to parse a normal numeric value
361 NumericVar value;
363 init_var(&value);
365 cp = set_var_from_str(str, cp, &value);
368 * We duplicate a few lines of code here because we would like to
369 * throw any trailing-junk syntax error before any semantic error
370 * resulting from apply_typmod. We can't easily fold the two
371 * cases together because we mustn't apply apply_typmod to a NaN.
373 while (*cp)
375 if (!isspace((unsigned char) *cp))
376 ereport(ERROR,
377 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
378 errmsg("invalid input syntax for type numeric: \"%s\"",
379 str)));
380 cp++;
383 apply_typmod(&value, typmod);
385 res = make_result(&value);
386 free_var(&value);
389 PG_RETURN_NUMERIC(res);
394 * numeric_out() -
396 * Output function for numeric data type
398 Datum
399 numeric_out(PG_FUNCTION_ARGS)
401 Numeric num = PG_GETARG_NUMERIC(0);
402 NumericVar x;
403 char *str;
406 * Handle NaN
408 if (NUMERIC_IS_NAN(num))
409 PG_RETURN_CSTRING(pstrdup("NaN"));
412 * Get the number in the variable format.
414 * Even if we didn't need to change format, we'd still need to copy the
415 * value to have a modifiable copy for rounding. set_var_from_num() also
416 * guarantees there is extra digit space in case we produce a carry out
417 * from rounding.
419 init_var(&x);
420 set_var_from_num(num, &x);
422 str = get_str_from_var(&x, x.dscale);
424 free_var(&x);
426 PG_RETURN_CSTRING(str);
430 * numeric_recv - converts external binary format to numeric
432 * External format is a sequence of int16's:
433 * ndigits, weight, sign, dscale, NumericDigits.
435 Datum
436 numeric_recv(PG_FUNCTION_ARGS)
438 StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
440 #ifdef NOT_USED
441 Oid typelem = PG_GETARG_OID(1);
442 #endif
443 int32 typmod = PG_GETARG_INT32(2);
444 NumericVar value;
445 Numeric res;
446 int len,
449 init_var(&value);
451 len = (uint16) pq_getmsgint(buf, sizeof(uint16));
452 if (len < 0 || len > NUMERIC_MAX_PRECISION + NUMERIC_MAX_RESULT_SCALE)
453 ereport(ERROR,
454 (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
455 errmsg("invalid length in external \"numeric\" value")));
457 alloc_var(&value, len);
459 value.weight = (int16) pq_getmsgint(buf, sizeof(int16));
460 value.sign = (uint16) pq_getmsgint(buf, sizeof(uint16));
461 if (!(value.sign == NUMERIC_POS ||
462 value.sign == NUMERIC_NEG ||
463 value.sign == NUMERIC_NAN))
464 ereport(ERROR,
465 (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
466 errmsg("invalid sign in external \"numeric\" value")));
468 value.dscale = (uint16) pq_getmsgint(buf, sizeof(uint16));
469 for (i = 0; i < len; i++)
471 NumericDigit d = pq_getmsgint(buf, sizeof(NumericDigit));
473 if (d < 0 || d >= NBASE)
474 ereport(ERROR,
475 (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
476 errmsg("invalid digit in external \"numeric\" value")));
477 value.digits[i] = d;
480 apply_typmod(&value, typmod);
482 res = make_result(&value);
483 free_var(&value);
485 PG_RETURN_NUMERIC(res);
489 * numeric_send - converts numeric to binary format
491 Datum
492 numeric_send(PG_FUNCTION_ARGS)
494 Numeric num = PG_GETARG_NUMERIC(0);
495 NumericVar x;
496 StringInfoData buf;
497 int i;
499 init_var(&x);
500 set_var_from_num(num, &x);
502 pq_begintypsend(&buf);
504 pq_sendint(&buf, x.ndigits, sizeof(int16));
505 pq_sendint(&buf, x.weight, sizeof(int16));
506 pq_sendint(&buf, x.sign, sizeof(int16));
507 pq_sendint(&buf, x.dscale, sizeof(int16));
508 for (i = 0; i < x.ndigits; i++)
509 pq_sendint(&buf, x.digits[i], sizeof(NumericDigit));
511 free_var(&x);
513 PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
518 * numeric() -
520 * This is a special function called by the Postgres database system
521 * before a value is stored in a tuple's attribute. The precision and
522 * scale of the attribute have to be applied on the value.
524 Datum
525 numeric (PG_FUNCTION_ARGS)
527 Numeric num = PG_GETARG_NUMERIC(0);
528 int32 typmod = PG_GETARG_INT32(1);
529 Numeric new;
530 int32 tmp_typmod;
531 int precision;
532 int scale;
533 int ddigits;
534 int maxdigits;
535 NumericVar var;
538 * Handle NaN
540 if (NUMERIC_IS_NAN(num))
541 PG_RETURN_NUMERIC(make_result(&const_nan));
544 * If the value isn't a valid type modifier, simply return a copy of the
545 * input value
547 if (typmod < (int32) (VARHDRSZ))
549 new = (Numeric) palloc(VARSIZE(num));
550 memcpy(new, num, VARSIZE(num));
551 PG_RETURN_NUMERIC(new);
555 * Get the precision and scale out of the typmod value
557 tmp_typmod = typmod - VARHDRSZ;
558 precision = (tmp_typmod >> 16) & 0xffff;
559 scale = tmp_typmod & 0xffff;
560 maxdigits = precision - scale;
563 * If the number is certainly in bounds and due to the target scale no
564 * rounding could be necessary, just make a copy of the input and modify
565 * its scale fields. (Note we assume the existing dscale is honest...)
567 ddigits = (num->n_weight + 1) * DEC_DIGITS;
568 if (ddigits <= maxdigits && scale >= NUMERIC_DSCALE(num))
570 new = (Numeric) palloc(VARSIZE(num));
571 memcpy(new, num, VARSIZE(num));
572 new->n_sign_dscale = NUMERIC_SIGN(new) |
573 ((uint16) scale & NUMERIC_DSCALE_MASK);
574 PG_RETURN_NUMERIC(new);
578 * We really need to fiddle with things - unpack the number into a
579 * variable and let apply_typmod() do it.
581 init_var(&var);
583 set_var_from_num(num, &var);
584 apply_typmod(&var, typmod);
585 new = make_result(&var);
587 free_var(&var);
589 PG_RETURN_NUMERIC(new);
592 Datum
593 numerictypmodin(PG_FUNCTION_ARGS)
595 ArrayType *ta = PG_GETARG_ARRAYTYPE_P(0);
596 int32 *tl;
597 int n;
598 int32 typmod;
600 tl = ArrayGetIntegerTypmods(ta, &n);
602 if (n == 2)
604 if (tl[0] < 1 || tl[0] > NUMERIC_MAX_PRECISION)
605 ereport(ERROR,
606 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
607 errmsg("NUMERIC precision %d must be between 1 and %d",
608 tl[0], NUMERIC_MAX_PRECISION)));
609 if (tl[1] < 0 || tl[1] > tl[0])
610 ereport(ERROR,
611 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
612 errmsg("NUMERIC scale %d must be between 0 and precision %d",
613 tl[1], tl[0])));
614 typmod = ((tl[0] << 16) | tl[1]) + VARHDRSZ;
616 else if (n == 1)
618 if (tl[0] < 1 || tl[0] > NUMERIC_MAX_PRECISION)
619 ereport(ERROR,
620 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
621 errmsg("NUMERIC precision %d must be between 1 and %d",
622 tl[0], NUMERIC_MAX_PRECISION)));
623 /* scale defaults to zero */
624 typmod = (tl[0] << 16) + VARHDRSZ;
626 else
628 ereport(ERROR,
629 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
630 errmsg("invalid NUMERIC type modifier")));
631 typmod = 0; /* keep compiler quiet */
634 PG_RETURN_INT32(typmod);
637 Datum
638 numerictypmodout(PG_FUNCTION_ARGS)
640 int32 typmod = PG_GETARG_INT32(0);
641 char *res = (char *) palloc(64);
643 if (typmod >= 0)
644 snprintf(res, 64, "(%d,%d)",
645 ((typmod - VARHDRSZ) >> 16) & 0xffff,
646 (typmod - VARHDRSZ) & 0xffff);
647 else
648 *res = '\0';
650 PG_RETURN_CSTRING(res);
654 /* ----------------------------------------------------------------------
656 * Sign manipulation, rounding and the like
658 * ----------------------------------------------------------------------
661 Datum
662 numeric_abs(PG_FUNCTION_ARGS)
664 Numeric num = PG_GETARG_NUMERIC(0);
665 Numeric res;
668 * Handle NaN
670 if (NUMERIC_IS_NAN(num))
671 PG_RETURN_NUMERIC(make_result(&const_nan));
674 * Do it the easy way directly on the packed format
676 res = (Numeric) palloc(VARSIZE(num));
677 memcpy(res, num, VARSIZE(num));
679 res->n_sign_dscale = NUMERIC_POS | NUMERIC_DSCALE(num);
681 PG_RETURN_NUMERIC(res);
685 Datum
686 numeric_uminus(PG_FUNCTION_ARGS)
688 Numeric num = PG_GETARG_NUMERIC(0);
689 Numeric res;
692 * Handle NaN
694 if (NUMERIC_IS_NAN(num))
695 PG_RETURN_NUMERIC(make_result(&const_nan));
698 * Do it the easy way directly on the packed format
700 res = (Numeric) palloc(VARSIZE(num));
701 memcpy(res, num, VARSIZE(num));
704 * The packed format is known to be totally zero digit trimmed always. So
705 * we can identify a ZERO by the fact that there are no digits at all. Do
706 * nothing to a zero.
708 if (VARSIZE(num) != NUMERIC_HDRSZ)
710 /* Else, flip the sign */
711 if (NUMERIC_SIGN(num) == NUMERIC_POS)
712 res->n_sign_dscale = NUMERIC_NEG | NUMERIC_DSCALE(num);
713 else
714 res->n_sign_dscale = NUMERIC_POS | NUMERIC_DSCALE(num);
717 PG_RETURN_NUMERIC(res);
721 Datum
722 numeric_uplus(PG_FUNCTION_ARGS)
724 Numeric num = PG_GETARG_NUMERIC(0);
725 Numeric res;
727 res = (Numeric) palloc(VARSIZE(num));
728 memcpy(res, num, VARSIZE(num));
730 PG_RETURN_NUMERIC(res);
734 * numeric_sign() -
736 * returns -1 if the argument is less than 0, 0 if the argument is equal
737 * to 0, and 1 if the argument is greater than zero.
739 Datum
740 numeric_sign(PG_FUNCTION_ARGS)
742 Numeric num = PG_GETARG_NUMERIC(0);
743 Numeric res;
744 NumericVar result;
747 * Handle NaN
749 if (NUMERIC_IS_NAN(num))
750 PG_RETURN_NUMERIC(make_result(&const_nan));
752 init_var(&result);
755 * The packed format is known to be totally zero digit trimmed always. So
756 * we can identify a ZERO by the fact that there are no digits at all.
758 if (VARSIZE(num) == NUMERIC_HDRSZ)
759 set_var_from_var(&const_zero, &result);
760 else
763 * And if there are some, we return a copy of ONE with the sign of our
764 * argument
766 set_var_from_var(&const_one, &result);
767 result.sign = NUMERIC_SIGN(num);
770 res = make_result(&result);
771 free_var(&result);
773 PG_RETURN_NUMERIC(res);
778 * numeric_round() -
780 * Round a value to have 'scale' digits after the decimal point.
781 * We allow negative 'scale', implying rounding before the decimal
782 * point --- Oracle interprets rounding that way.
784 Datum
785 numeric_round(PG_FUNCTION_ARGS)
787 Numeric num = PG_GETARG_NUMERIC(0);
788 int32 scale = PG_GETARG_INT32(1);
789 Numeric res;
790 NumericVar arg;
793 * Handle NaN
795 if (NUMERIC_IS_NAN(num))
796 PG_RETURN_NUMERIC(make_result(&const_nan));
799 * Limit the scale value to avoid possible overflow in calculations
801 scale = Max(scale, -NUMERIC_MAX_RESULT_SCALE);
802 scale = Min(scale, NUMERIC_MAX_RESULT_SCALE);
805 * Unpack the argument and round it at the proper digit position
807 init_var(&arg);
808 set_var_from_num(num, &arg);
810 round_var(&arg, scale);
812 /* We don't allow negative output dscale */
813 if (scale < 0)
814 arg.dscale = 0;
817 * Return the rounded result
819 res = make_result(&arg);
821 free_var(&arg);
822 PG_RETURN_NUMERIC(res);
827 * numeric_trunc() -
829 * Truncate a value to have 'scale' digits after the decimal point.
830 * We allow negative 'scale', implying a truncation before the decimal
831 * point --- Oracle interprets truncation that way.
833 Datum
834 numeric_trunc(PG_FUNCTION_ARGS)
836 Numeric num = PG_GETARG_NUMERIC(0);
837 int32 scale = PG_GETARG_INT32(1);
838 Numeric res;
839 NumericVar arg;
842 * Handle NaN
844 if (NUMERIC_IS_NAN(num))
845 PG_RETURN_NUMERIC(make_result(&const_nan));
848 * Limit the scale value to avoid possible overflow in calculations
850 scale = Max(scale, -NUMERIC_MAX_RESULT_SCALE);
851 scale = Min(scale, NUMERIC_MAX_RESULT_SCALE);
854 * Unpack the argument and truncate it at the proper digit position
856 init_var(&arg);
857 set_var_from_num(num, &arg);
859 trunc_var(&arg, scale);
861 /* We don't allow negative output dscale */
862 if (scale < 0)
863 arg.dscale = 0;
866 * Return the truncated result
868 res = make_result(&arg);
870 free_var(&arg);
871 PG_RETURN_NUMERIC(res);
876 * numeric_ceil() -
878 * Return the smallest integer greater than or equal to the argument
880 Datum
881 numeric_ceil(PG_FUNCTION_ARGS)
883 Numeric num = PG_GETARG_NUMERIC(0);
884 Numeric res;
885 NumericVar result;
887 if (NUMERIC_IS_NAN(num))
888 PG_RETURN_NUMERIC(make_result(&const_nan));
890 init_var(&result);
892 set_var_from_num(num, &result);
893 ceil_var(&result, &result);
895 res = make_result(&result);
896 free_var(&result);
898 PG_RETURN_NUMERIC(res);
903 * numeric_floor() -
905 * Return the largest integer equal to or less than the argument
907 Datum
908 numeric_floor(PG_FUNCTION_ARGS)
910 Numeric num = PG_GETARG_NUMERIC(0);
911 Numeric res;
912 NumericVar result;
914 if (NUMERIC_IS_NAN(num))
915 PG_RETURN_NUMERIC(make_result(&const_nan));
917 init_var(&result);
919 set_var_from_num(num, &result);
920 floor_var(&result, &result);
922 res = make_result(&result);
923 free_var(&result);
925 PG_RETURN_NUMERIC(res);
929 * Implements the numeric version of the width_bucket() function
930 * defined by SQL2003. See also width_bucket_float8().
932 * 'bound1' and 'bound2' are the lower and upper bounds of the
933 * histogram's range, respectively. 'count' is the number of buckets
934 * in the histogram. width_bucket() returns an integer indicating the
935 * bucket number that 'operand' belongs to in an equiwidth histogram
936 * with the specified characteristics. An operand smaller than the
937 * lower bound is assigned to bucket 0. An operand greater than the
938 * upper bound is assigned to an additional bucket (with number
939 * count+1). We don't allow "NaN" for any of the numeric arguments.
941 Datum
942 width_bucket_numeric(PG_FUNCTION_ARGS)
944 Numeric operand = PG_GETARG_NUMERIC(0);
945 Numeric bound1 = PG_GETARG_NUMERIC(1);
946 Numeric bound2 = PG_GETARG_NUMERIC(2);
947 int32 count = PG_GETARG_INT32(3);
948 NumericVar count_var;
949 NumericVar result_var;
950 int32 result;
952 if (count <= 0)
953 ereport(ERROR,
954 (errcode(ERRCODE_INVALID_ARGUMENT_FOR_WIDTH_BUCKET_FUNCTION),
955 errmsg("count must be greater than zero")));
957 if (NUMERIC_IS_NAN(operand) ||
958 NUMERIC_IS_NAN(bound1) ||
959 NUMERIC_IS_NAN(bound2))
960 ereport(ERROR,
961 (errcode(ERRCODE_INVALID_ARGUMENT_FOR_WIDTH_BUCKET_FUNCTION),
962 errmsg("operand, lower bound and upper bound cannot be NaN")));
964 init_var(&result_var);
965 init_var(&count_var);
967 /* Convert 'count' to a numeric, for ease of use later */
968 int8_to_numericvar((int64) count, &count_var);
970 switch (cmp_numerics(bound1, bound2))
972 case 0:
973 ereport(ERROR,
974 (errcode(ERRCODE_INVALID_ARGUMENT_FOR_WIDTH_BUCKET_FUNCTION),
975 errmsg("lower bound cannot equal upper bound")));
977 /* bound1 < bound2 */
978 case -1:
979 if (cmp_numerics(operand, bound1) < 0)
980 set_var_from_var(&const_zero, &result_var);
981 else if (cmp_numerics(operand, bound2) >= 0)
982 add_var(&count_var, &const_one, &result_var);
983 else
984 compute_bucket(operand, bound1, bound2,
985 &count_var, &result_var);
986 break;
988 /* bound1 > bound2 */
989 case 1:
990 if (cmp_numerics(operand, bound1) > 0)
991 set_var_from_var(&const_zero, &result_var);
992 else if (cmp_numerics(operand, bound2) <= 0)
993 add_var(&count_var, &const_one, &result_var);
994 else
995 compute_bucket(operand, bound1, bound2,
996 &count_var, &result_var);
997 break;
1000 /* if result exceeds the range of a legal int4, we ereport here */
1001 result = numericvar_to_int4(&result_var);
1003 free_var(&count_var);
1004 free_var(&result_var);
1006 PG_RETURN_INT32(result);
1010 * If 'operand' is not outside the bucket range, determine the correct
1011 * bucket for it to go. The calculations performed by this function
1012 * are derived directly from the SQL2003 spec.
1014 static void
1015 compute_bucket(Numeric operand, Numeric bound1, Numeric bound2,
1016 NumericVar *count_var, NumericVar *result_var)
1018 NumericVar bound1_var;
1019 NumericVar bound2_var;
1020 NumericVar operand_var;
1022 init_var(&bound1_var);
1023 init_var(&bound2_var);
1024 init_var(&operand_var);
1026 set_var_from_num(bound1, &bound1_var);
1027 set_var_from_num(bound2, &bound2_var);
1028 set_var_from_num(operand, &operand_var);
1030 if (cmp_var(&bound1_var, &bound2_var) < 0)
1032 sub_var(&operand_var, &bound1_var, &operand_var);
1033 sub_var(&bound2_var, &bound1_var, &bound2_var);
1034 div_var(&operand_var, &bound2_var, result_var,
1035 select_div_scale(&operand_var, &bound2_var), true);
1037 else
1039 sub_var(&bound1_var, &operand_var, &operand_var);
1040 sub_var(&bound1_var, &bound2_var, &bound1_var);
1041 div_var(&operand_var, &bound1_var, result_var,
1042 select_div_scale(&operand_var, &bound1_var), true);
1045 mul_var(result_var, count_var, result_var,
1046 result_var->dscale + count_var->dscale);
1047 add_var(result_var, &const_one, result_var);
1048 floor_var(result_var, result_var);
1050 free_var(&bound1_var);
1051 free_var(&bound2_var);
1052 free_var(&operand_var);
1055 /* ----------------------------------------------------------------------
1057 * Comparison functions
1059 * Note: btree indexes need these routines not to leak memory; therefore,
1060 * be careful to free working copies of toasted datums. Most places don't
1061 * need to be so careful.
1062 * ----------------------------------------------------------------------
1066 Datum
1067 numeric_cmp(PG_FUNCTION_ARGS)
1069 Numeric num1 = PG_GETARG_NUMERIC(0);
1070 Numeric num2 = PG_GETARG_NUMERIC(1);
1071 int result;
1073 result = cmp_numerics(num1, num2);
1075 PG_FREE_IF_COPY(num1, 0);
1076 PG_FREE_IF_COPY(num2, 1);
1078 PG_RETURN_INT32(result);
1082 Datum
1083 numeric_eq(PG_FUNCTION_ARGS)
1085 Numeric num1 = PG_GETARG_NUMERIC(0);
1086 Numeric num2 = PG_GETARG_NUMERIC(1);
1087 bool result;
1089 result = cmp_numerics(num1, num2) == 0;
1091 PG_FREE_IF_COPY(num1, 0);
1092 PG_FREE_IF_COPY(num2, 1);
1094 PG_RETURN_BOOL(result);
1097 Datum
1098 numeric_ne(PG_FUNCTION_ARGS)
1100 Numeric num1 = PG_GETARG_NUMERIC(0);
1101 Numeric num2 = PG_GETARG_NUMERIC(1);
1102 bool result;
1104 result = cmp_numerics(num1, num2) != 0;
1106 PG_FREE_IF_COPY(num1, 0);
1107 PG_FREE_IF_COPY(num2, 1);
1109 PG_RETURN_BOOL(result);
1112 Datum
1113 numeric_gt(PG_FUNCTION_ARGS)
1115 Numeric num1 = PG_GETARG_NUMERIC(0);
1116 Numeric num2 = PG_GETARG_NUMERIC(1);
1117 bool result;
1119 result = cmp_numerics(num1, num2) > 0;
1121 PG_FREE_IF_COPY(num1, 0);
1122 PG_FREE_IF_COPY(num2, 1);
1124 PG_RETURN_BOOL(result);
1127 Datum
1128 numeric_ge(PG_FUNCTION_ARGS)
1130 Numeric num1 = PG_GETARG_NUMERIC(0);
1131 Numeric num2 = PG_GETARG_NUMERIC(1);
1132 bool result;
1134 result = cmp_numerics(num1, num2) >= 0;
1136 PG_FREE_IF_COPY(num1, 0);
1137 PG_FREE_IF_COPY(num2, 1);
1139 PG_RETURN_BOOL(result);
1142 Datum
1143 numeric_lt(PG_FUNCTION_ARGS)
1145 Numeric num1 = PG_GETARG_NUMERIC(0);
1146 Numeric num2 = PG_GETARG_NUMERIC(1);
1147 bool result;
1149 result = cmp_numerics(num1, num2) < 0;
1151 PG_FREE_IF_COPY(num1, 0);
1152 PG_FREE_IF_COPY(num2, 1);
1154 PG_RETURN_BOOL(result);
1157 Datum
1158 numeric_le(PG_FUNCTION_ARGS)
1160 Numeric num1 = PG_GETARG_NUMERIC(0);
1161 Numeric num2 = PG_GETARG_NUMERIC(1);
1162 bool result;
1164 result = cmp_numerics(num1, num2) <= 0;
1166 PG_FREE_IF_COPY(num1, 0);
1167 PG_FREE_IF_COPY(num2, 1);
1169 PG_RETURN_BOOL(result);
1172 static int
1173 cmp_numerics(Numeric num1, Numeric num2)
1175 int result;
1178 * We consider all NANs to be equal and larger than any non-NAN. This is
1179 * somewhat arbitrary; the important thing is to have a consistent sort
1180 * order.
1182 if (NUMERIC_IS_NAN(num1))
1184 if (NUMERIC_IS_NAN(num2))
1185 result = 0; /* NAN = NAN */
1186 else
1187 result = 1; /* NAN > non-NAN */
1189 else if (NUMERIC_IS_NAN(num2))
1191 result = -1; /* non-NAN < NAN */
1193 else
1195 result = cmp_var_common(NUMERIC_DIGITS(num1), NUMERIC_NDIGITS(num1),
1196 num1->n_weight, NUMERIC_SIGN(num1),
1197 NUMERIC_DIGITS(num2), NUMERIC_NDIGITS(num2),
1198 num2->n_weight, NUMERIC_SIGN(num2));
1201 return result;
1204 Datum
1205 hash_numeric(PG_FUNCTION_ARGS)
1207 Numeric key = PG_GETARG_NUMERIC(0);
1208 Datum digit_hash;
1209 Datum result;
1210 int weight;
1211 int start_offset;
1212 int end_offset;
1213 int i;
1214 int hash_len;
1216 /* If it's NaN, don't try to hash the rest of the fields */
1217 if (NUMERIC_IS_NAN(key))
1218 PG_RETURN_UINT32(0);
1220 weight = key->n_weight;
1221 start_offset = 0;
1222 end_offset = 0;
1225 * Omit any leading or trailing zeros from the input to the hash. The
1226 * numeric implementation *should* guarantee that leading and trailing
1227 * zeros are suppressed, but we're paranoid. Note that we measure the
1228 * starting and ending offsets in units of NumericDigits, not bytes.
1230 for (i = 0; i < NUMERIC_NDIGITS(key); i++)
1232 if (NUMERIC_DIGITS(key)[i] != (NumericDigit) 0)
1233 break;
1235 start_offset++;
1238 * The weight is effectively the # of digits before the decimal point,
1239 * so decrement it for each leading zero we skip.
1241 weight--;
1245 * If there are no non-zero digits, then the value of the number is zero,
1246 * regardless of any other fields.
1248 if (NUMERIC_NDIGITS(key) == start_offset)
1249 PG_RETURN_UINT32(-1);
1251 for (i = NUMERIC_NDIGITS(key) - 1; i >= 0; i--)
1253 if (NUMERIC_DIGITS(key)[i] != (NumericDigit) 0)
1254 break;
1256 end_offset++;
1259 /* If we get here, there should be at least one non-zero digit */
1260 Assert(start_offset + end_offset < NUMERIC_NDIGITS(key));
1263 * Note that we don't hash on the Numeric's scale, since two numerics can
1264 * compare equal but have different scales. We also don't hash on the
1265 * sign, although we could: since a sign difference implies inequality,
1266 * this shouldn't affect correctness.
1268 hash_len = NUMERIC_NDIGITS(key) - start_offset - end_offset;
1269 digit_hash = hash_any((unsigned char *) (NUMERIC_DIGITS(key) + start_offset),
1270 hash_len * sizeof(NumericDigit));
1272 /* Mix in the weight, via XOR */
1273 result = digit_hash ^ weight;
1275 PG_RETURN_DATUM(result);
1279 /* ----------------------------------------------------------------------
1281 * Basic arithmetic functions
1283 * ----------------------------------------------------------------------
1288 * numeric_add() -
1290 * Add two numerics
1292 Datum
1293 numeric_add(PG_FUNCTION_ARGS)
1295 Numeric num1 = PG_GETARG_NUMERIC(0);
1296 Numeric num2 = PG_GETARG_NUMERIC(1);
1297 NumericVar arg1;
1298 NumericVar arg2;
1299 NumericVar result;
1300 Numeric res;
1303 * Handle NaN
1305 if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
1306 PG_RETURN_NUMERIC(make_result(&const_nan));
1309 * Unpack the values, let add_var() compute the result and return it.
1311 init_var(&arg1);
1312 init_var(&arg2);
1313 init_var(&result);
1315 set_var_from_num(num1, &arg1);
1316 set_var_from_num(num2, &arg2);
1318 add_var(&arg1, &arg2, &result);
1320 res = make_result(&result);
1322 free_var(&arg1);
1323 free_var(&arg2);
1324 free_var(&result);
1326 PG_RETURN_NUMERIC(res);
1331 * numeric_sub() -
1333 * Subtract one numeric from another
1335 Datum
1336 numeric_sub(PG_FUNCTION_ARGS)
1338 Numeric num1 = PG_GETARG_NUMERIC(0);
1339 Numeric num2 = PG_GETARG_NUMERIC(1);
1340 NumericVar arg1;
1341 NumericVar arg2;
1342 NumericVar result;
1343 Numeric res;
1346 * Handle NaN
1348 if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
1349 PG_RETURN_NUMERIC(make_result(&const_nan));
1352 * Unpack the values, let sub_var() compute the result and return it.
1354 init_var(&arg1);
1355 init_var(&arg2);
1356 init_var(&result);
1358 set_var_from_num(num1, &arg1);
1359 set_var_from_num(num2, &arg2);
1361 sub_var(&arg1, &arg2, &result);
1363 res = make_result(&result);
1365 free_var(&arg1);
1366 free_var(&arg2);
1367 free_var(&result);
1369 PG_RETURN_NUMERIC(res);
1374 * numeric_mul() -
1376 * Calculate the product of two numerics
1378 Datum
1379 numeric_mul(PG_FUNCTION_ARGS)
1381 Numeric num1 = PG_GETARG_NUMERIC(0);
1382 Numeric num2 = PG_GETARG_NUMERIC(1);
1383 NumericVar arg1;
1384 NumericVar arg2;
1385 NumericVar result;
1386 Numeric res;
1389 * Handle NaN
1391 if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
1392 PG_RETURN_NUMERIC(make_result(&const_nan));
1395 * Unpack the values, let mul_var() compute the result and return it.
1396 * Unlike add_var() and sub_var(), mul_var() will round its result. In the
1397 * case of numeric_mul(), which is invoked for the * operator on numerics,
1398 * we request exact representation for the product (rscale = sum(dscale of
1399 * arg1, dscale of arg2)).
1401 init_var(&arg1);
1402 init_var(&arg2);
1403 init_var(&result);
1405 set_var_from_num(num1, &arg1);
1406 set_var_from_num(num2, &arg2);
1408 mul_var(&arg1, &arg2, &result, arg1.dscale + arg2.dscale);
1410 res = make_result(&result);
1412 free_var(&arg1);
1413 free_var(&arg2);
1414 free_var(&result);
1416 PG_RETURN_NUMERIC(res);
1421 * numeric_div() -
1423 * Divide one numeric into another
1425 Datum
1426 numeric_div(PG_FUNCTION_ARGS)
1428 Numeric num1 = PG_GETARG_NUMERIC(0);
1429 Numeric num2 = PG_GETARG_NUMERIC(1);
1430 NumericVar arg1;
1431 NumericVar arg2;
1432 NumericVar result;
1433 Numeric res;
1434 int rscale;
1437 * Handle NaN
1439 if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
1440 PG_RETURN_NUMERIC(make_result(&const_nan));
1443 * Unpack the arguments
1445 init_var(&arg1);
1446 init_var(&arg2);
1447 init_var(&result);
1449 set_var_from_num(num1, &arg1);
1450 set_var_from_num(num2, &arg2);
1453 * Select scale for division result
1455 rscale = select_div_scale(&arg1, &arg2);
1458 * Do the divide and return the result
1460 div_var(&arg1, &arg2, &result, rscale, true);
1462 res = make_result(&result);
1464 free_var(&arg1);
1465 free_var(&arg2);
1466 free_var(&result);
1468 PG_RETURN_NUMERIC(res);
1473 * numeric_div_trunc() -
1475 * Divide one numeric into another, truncating the result to an integer
1477 Datum
1478 numeric_div_trunc(PG_FUNCTION_ARGS)
1480 Numeric num1 = PG_GETARG_NUMERIC(0);
1481 Numeric num2 = PG_GETARG_NUMERIC(1);
1482 NumericVar arg1;
1483 NumericVar arg2;
1484 NumericVar result;
1485 Numeric res;
1488 * Handle NaN
1490 if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
1491 PG_RETURN_NUMERIC(make_result(&const_nan));
1494 * Unpack the arguments
1496 init_var(&arg1);
1497 init_var(&arg2);
1498 init_var(&result);
1500 set_var_from_num(num1, &arg1);
1501 set_var_from_num(num2, &arg2);
1504 * Do the divide and return the result
1506 div_var(&arg1, &arg2, &result, 0, false);
1508 res = make_result(&result);
1510 free_var(&arg1);
1511 free_var(&arg2);
1512 free_var(&result);
1514 PG_RETURN_NUMERIC(res);
1519 * numeric_mod() -
1521 * Calculate the modulo of two numerics
1523 Datum
1524 numeric_mod(PG_FUNCTION_ARGS)
1526 Numeric num1 = PG_GETARG_NUMERIC(0);
1527 Numeric num2 = PG_GETARG_NUMERIC(1);
1528 Numeric res;
1529 NumericVar arg1;
1530 NumericVar arg2;
1531 NumericVar result;
1533 if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
1534 PG_RETURN_NUMERIC(make_result(&const_nan));
1536 init_var(&arg1);
1537 init_var(&arg2);
1538 init_var(&result);
1540 set_var_from_num(num1, &arg1);
1541 set_var_from_num(num2, &arg2);
1543 mod_var(&arg1, &arg2, &result);
1545 res = make_result(&result);
1547 free_var(&result);
1548 free_var(&arg2);
1549 free_var(&arg1);
1551 PG_RETURN_NUMERIC(res);
1556 * numeric_inc() -
1558 * Increment a number by one
1560 Datum
1561 numeric_inc(PG_FUNCTION_ARGS)
1563 Numeric num = PG_GETARG_NUMERIC(0);
1564 NumericVar arg;
1565 Numeric res;
1568 * Handle NaN
1570 if (NUMERIC_IS_NAN(num))
1571 PG_RETURN_NUMERIC(make_result(&const_nan));
1574 * Compute the result and return it
1576 init_var(&arg);
1578 set_var_from_num(num, &arg);
1580 add_var(&arg, &const_one, &arg);
1582 res = make_result(&arg);
1584 free_var(&arg);
1586 PG_RETURN_NUMERIC(res);
1591 * numeric_smaller() -
1593 * Return the smaller of two numbers
1595 Datum
1596 numeric_smaller(PG_FUNCTION_ARGS)
1598 Numeric num1 = PG_GETARG_NUMERIC(0);
1599 Numeric num2 = PG_GETARG_NUMERIC(1);
1602 * Use cmp_numerics so that this will agree with the comparison operators,
1603 * particularly as regards comparisons involving NaN.
1605 if (cmp_numerics(num1, num2) < 0)
1606 PG_RETURN_NUMERIC(num1);
1607 else
1608 PG_RETURN_NUMERIC(num2);
1613 * numeric_larger() -
1615 * Return the larger of two numbers
1617 Datum
1618 numeric_larger(PG_FUNCTION_ARGS)
1620 Numeric num1 = PG_GETARG_NUMERIC(0);
1621 Numeric num2 = PG_GETARG_NUMERIC(1);
1624 * Use cmp_numerics so that this will agree with the comparison operators,
1625 * particularly as regards comparisons involving NaN.
1627 if (cmp_numerics(num1, num2) > 0)
1628 PG_RETURN_NUMERIC(num1);
1629 else
1630 PG_RETURN_NUMERIC(num2);
1634 /* ----------------------------------------------------------------------
1636 * Advanced math functions
1638 * ----------------------------------------------------------------------
1642 * numeric_fac()
1644 * Compute factorial
1646 Datum
1647 numeric_fac(PG_FUNCTION_ARGS)
1649 int64 num = PG_GETARG_INT64(0);
1650 Numeric res;
1651 NumericVar fact;
1652 NumericVar result;
1654 if (num <= 1)
1656 res = make_result(&const_one);
1657 PG_RETURN_NUMERIC(res);
1659 /* Fail immediately if the result would overflow */
1660 if (num > 32177)
1661 ereport(ERROR,
1662 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1663 errmsg("value overflows numeric format")));
1665 init_var(&fact);
1666 init_var(&result);
1668 int8_to_numericvar(num, &result);
1670 for (num = num - 1; num > 1; num--)
1672 /* this loop can take awhile, so allow it to be interrupted */
1673 CHECK_FOR_INTERRUPTS();
1675 int8_to_numericvar(num, &fact);
1677 mul_var(&result, &fact, &result, 0);
1680 res = make_result(&result);
1682 free_var(&fact);
1683 free_var(&result);
1685 PG_RETURN_NUMERIC(res);
1690 * numeric_sqrt() -
1692 * Compute the square root of a numeric.
1694 Datum
1695 numeric_sqrt(PG_FUNCTION_ARGS)
1697 Numeric num = PG_GETARG_NUMERIC(0);
1698 Numeric res;
1699 NumericVar arg;
1700 NumericVar result;
1701 int sweight;
1702 int rscale;
1705 * Handle NaN
1707 if (NUMERIC_IS_NAN(num))
1708 PG_RETURN_NUMERIC(make_result(&const_nan));
1711 * Unpack the argument and determine the result scale. We choose a scale
1712 * to give at least NUMERIC_MIN_SIG_DIGITS significant digits; but in any
1713 * case not less than the input's dscale.
1715 init_var(&arg);
1716 init_var(&result);
1718 set_var_from_num(num, &arg);
1720 /* Assume the input was normalized, so arg.weight is accurate */
1721 sweight = (arg.weight + 1) * DEC_DIGITS / 2 - 1;
1723 rscale = NUMERIC_MIN_SIG_DIGITS - sweight;
1724 rscale = Max(rscale, arg.dscale);
1725 rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
1726 rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
1729 * Let sqrt_var() do the calculation and return the result.
1731 sqrt_var(&arg, &result, rscale);
1733 res = make_result(&result);
1735 free_var(&result);
1736 free_var(&arg);
1738 PG_RETURN_NUMERIC(res);
1743 * numeric_exp() -
1745 * Raise e to the power of x
1747 Datum
1748 numeric_exp(PG_FUNCTION_ARGS)
1750 Numeric num = PG_GETARG_NUMERIC(0);
1751 Numeric res;
1752 NumericVar arg;
1753 NumericVar result;
1754 int rscale;
1755 double val;
1758 * Handle NaN
1760 if (NUMERIC_IS_NAN(num))
1761 PG_RETURN_NUMERIC(make_result(&const_nan));
1764 * Unpack the argument and determine the result scale. We choose a scale
1765 * to give at least NUMERIC_MIN_SIG_DIGITS significant digits; but in any
1766 * case not less than the input's dscale.
1768 init_var(&arg);
1769 init_var(&result);
1771 set_var_from_num(num, &arg);
1773 /* convert input to float8, ignoring overflow */
1774 val = numericvar_to_double_no_overflow(&arg);
1777 * log10(result) = num * log10(e), so this is approximately the decimal
1778 * weight of the result:
1780 val *= 0.434294481903252;
1782 /* limit to something that won't cause integer overflow */
1783 val = Max(val, -NUMERIC_MAX_RESULT_SCALE);
1784 val = Min(val, NUMERIC_MAX_RESULT_SCALE);
1786 rscale = NUMERIC_MIN_SIG_DIGITS - (int) val;
1787 rscale = Max(rscale, arg.dscale);
1788 rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
1789 rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
1792 * Let exp_var() do the calculation and return the result.
1794 exp_var(&arg, &result, rscale);
1796 res = make_result(&result);
1798 free_var(&result);
1799 free_var(&arg);
1801 PG_RETURN_NUMERIC(res);
1806 * numeric_ln() -
1808 * Compute the natural logarithm of x
1810 Datum
1811 numeric_ln(PG_FUNCTION_ARGS)
1813 Numeric num = PG_GETARG_NUMERIC(0);
1814 Numeric res;
1815 NumericVar arg;
1816 NumericVar result;
1817 int dec_digits;
1818 int rscale;
1821 * Handle NaN
1823 if (NUMERIC_IS_NAN(num))
1824 PG_RETURN_NUMERIC(make_result(&const_nan));
1826 init_var(&arg);
1827 init_var(&result);
1829 set_var_from_num(num, &arg);
1831 /* Approx decimal digits before decimal point */
1832 dec_digits = (arg.weight + 1) * DEC_DIGITS;
1834 if (dec_digits > 1)
1835 rscale = NUMERIC_MIN_SIG_DIGITS - (int) log10(dec_digits - 1);
1836 else if (dec_digits < 1)
1837 rscale = NUMERIC_MIN_SIG_DIGITS - (int) log10(1 - dec_digits);
1838 else
1839 rscale = NUMERIC_MIN_SIG_DIGITS;
1841 rscale = Max(rscale, arg.dscale);
1842 rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
1843 rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
1845 ln_var(&arg, &result, rscale);
1847 res = make_result(&result);
1849 free_var(&result);
1850 free_var(&arg);
1852 PG_RETURN_NUMERIC(res);
1857 * numeric_log() -
1859 * Compute the logarithm of x in a given base
1861 Datum
1862 numeric_log(PG_FUNCTION_ARGS)
1864 Numeric num1 = PG_GETARG_NUMERIC(0);
1865 Numeric num2 = PG_GETARG_NUMERIC(1);
1866 Numeric res;
1867 NumericVar arg1;
1868 NumericVar arg2;
1869 NumericVar result;
1872 * Handle NaN
1874 if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
1875 PG_RETURN_NUMERIC(make_result(&const_nan));
1878 * Initialize things
1880 init_var(&arg1);
1881 init_var(&arg2);
1882 init_var(&result);
1884 set_var_from_num(num1, &arg1);
1885 set_var_from_num(num2, &arg2);
1888 * Call log_var() to compute and return the result; note it handles scale
1889 * selection itself.
1891 log_var(&arg1, &arg2, &result);
1893 res = make_result(&result);
1895 free_var(&result);
1896 free_var(&arg2);
1897 free_var(&arg1);
1899 PG_RETURN_NUMERIC(res);
1904 * numeric_power() -
1906 * Raise b to the power of x
1908 Datum
1909 numeric_power(PG_FUNCTION_ARGS)
1911 Numeric num1 = PG_GETARG_NUMERIC(0);
1912 Numeric num2 = PG_GETARG_NUMERIC(1);
1913 Numeric res;
1914 NumericVar arg1;
1915 NumericVar arg2;
1916 NumericVar arg2_trunc;
1917 NumericVar result;
1920 * Handle NaN
1922 if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
1923 PG_RETURN_NUMERIC(make_result(&const_nan));
1926 * Initialize things
1928 init_var(&arg1);
1929 init_var(&arg2);
1930 init_var(&arg2_trunc);
1931 init_var(&result);
1933 set_var_from_num(num1, &arg1);
1934 set_var_from_num(num2, &arg2);
1935 set_var_from_var(&arg2, &arg2_trunc);
1937 trunc_var(&arg2_trunc, 0);
1940 * The SQL spec requires that we emit a particular SQLSTATE error code for
1941 * certain error conditions. Specifically, we don't return a divide-by-zero
1942 * error code for 0 ^ -1.
1944 if (cmp_var(&arg1, &const_zero) == 0 &&
1945 cmp_var(&arg2, &const_zero) < 0)
1946 ereport(ERROR,
1947 (errcode(ERRCODE_INVALID_ARGUMENT_FOR_POWER_FUNCTION),
1948 errmsg("zero raised to a negative power is undefined")));
1950 if (cmp_var(&arg1, &const_zero) < 0 &&
1951 cmp_var(&arg2, &arg2_trunc) != 0)
1952 ereport(ERROR,
1953 (errcode(ERRCODE_INVALID_ARGUMENT_FOR_POWER_FUNCTION),
1954 errmsg("a negative number raised to a non-integer power yields a complex result")));
1957 * Call power_var() to compute and return the result; note it handles
1958 * scale selection itself.
1960 power_var(&arg1, &arg2, &result);
1962 res = make_result(&result);
1964 free_var(&result);
1965 free_var(&arg2);
1966 free_var(&arg2_trunc);
1967 free_var(&arg1);
1969 PG_RETURN_NUMERIC(res);
1973 /* ----------------------------------------------------------------------
1975 * Type conversion functions
1977 * ----------------------------------------------------------------------
1981 Datum
1982 int4_numeric(PG_FUNCTION_ARGS)
1984 int32 val = PG_GETARG_INT32(0);
1985 Numeric res;
1986 NumericVar result;
1988 init_var(&result);
1990 int8_to_numericvar((int64) val, &result);
1992 res = make_result(&result);
1994 free_var(&result);
1996 PG_RETURN_NUMERIC(res);
2000 Datum
2001 numeric_int4(PG_FUNCTION_ARGS)
2003 Numeric num = PG_GETARG_NUMERIC(0);
2004 NumericVar x;
2005 int32 result;
2007 /* XXX would it be better to return NULL? */
2008 if (NUMERIC_IS_NAN(num))
2009 ereport(ERROR,
2010 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2011 errmsg("cannot convert NaN to integer")));
2013 /* Convert to variable format, then convert to int4 */
2014 init_var(&x);
2015 set_var_from_num(num, &x);
2016 result = numericvar_to_int4(&x);
2017 free_var(&x);
2018 PG_RETURN_INT32(result);
2022 * Given a NumericVar, convert it to an int32. If the NumericVar
2023 * exceeds the range of an int32, raise the appropriate error via
2024 * ereport(). The input NumericVar is *not* free'd.
2026 static int32
2027 numericvar_to_int4(NumericVar *var)
2029 int32 result;
2030 int64 val;
2032 if (!numericvar_to_int8(var, &val))
2033 ereport(ERROR,
2034 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
2035 errmsg("integer out of range")));
2037 /* Down-convert to int4 */
2038 result = (int32) val;
2040 /* Test for overflow by reverse-conversion. */
2041 if ((int64) result != val)
2042 ereport(ERROR,
2043 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
2044 errmsg("integer out of range")));
2046 return result;
2049 Datum
2050 int8_numeric(PG_FUNCTION_ARGS)
2052 int64 val = PG_GETARG_INT64(0);
2053 Numeric res;
2054 NumericVar result;
2056 init_var(&result);
2058 int8_to_numericvar(val, &result);
2060 res = make_result(&result);
2062 free_var(&result);
2064 PG_RETURN_NUMERIC(res);
2068 Datum
2069 numeric_int8(PG_FUNCTION_ARGS)
2071 Numeric num = PG_GETARG_NUMERIC(0);
2072 NumericVar x;
2073 int64 result;
2075 /* XXX would it be better to return NULL? */
2076 if (NUMERIC_IS_NAN(num))
2077 ereport(ERROR,
2078 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2079 errmsg("cannot convert NaN to bigint")));
2081 /* Convert to variable format and thence to int8 */
2082 init_var(&x);
2083 set_var_from_num(num, &x);
2085 if (!numericvar_to_int8(&x, &result))
2086 ereport(ERROR,
2087 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
2088 errmsg("bigint out of range")));
2090 free_var(&x);
2092 PG_RETURN_INT64(result);
2096 Datum
2097 int2_numeric(PG_FUNCTION_ARGS)
2099 int16 val = PG_GETARG_INT16(0);
2100 Numeric res;
2101 NumericVar result;
2103 init_var(&result);
2105 int8_to_numericvar((int64) val, &result);
2107 res = make_result(&result);
2109 free_var(&result);
2111 PG_RETURN_NUMERIC(res);
2115 Datum
2116 numeric_int2(PG_FUNCTION_ARGS)
2118 Numeric num = PG_GETARG_NUMERIC(0);
2119 NumericVar x;
2120 int64 val;
2121 int16 result;
2123 /* XXX would it be better to return NULL? */
2124 if (NUMERIC_IS_NAN(num))
2125 ereport(ERROR,
2126 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2127 errmsg("cannot convert NaN to smallint")));
2129 /* Convert to variable format and thence to int8 */
2130 init_var(&x);
2131 set_var_from_num(num, &x);
2133 if (!numericvar_to_int8(&x, &val))
2134 ereport(ERROR,
2135 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
2136 errmsg("smallint out of range")));
2138 free_var(&x);
2140 /* Down-convert to int2 */
2141 result = (int16) val;
2143 /* Test for overflow by reverse-conversion. */
2144 if ((int64) result != val)
2145 ereport(ERROR,
2146 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
2147 errmsg("smallint out of range")));
2149 PG_RETURN_INT16(result);
2153 Datum
2154 float8_numeric(PG_FUNCTION_ARGS)
2156 float8 val = PG_GETARG_FLOAT8(0);
2157 Numeric res;
2158 NumericVar result;
2159 char buf[DBL_DIG + 100];
2161 if (isnan(val))
2162 PG_RETURN_NUMERIC(make_result(&const_nan));
2164 sprintf(buf, "%.*g", DBL_DIG, val);
2166 init_var(&result);
2168 /* Assume we need not worry about leading/trailing spaces */
2169 (void) set_var_from_str(buf, buf, &result);
2171 res = make_result(&result);
2173 free_var(&result);
2175 PG_RETURN_NUMERIC(res);
2179 Datum
2180 numeric_float8(PG_FUNCTION_ARGS)
2182 Numeric num = PG_GETARG_NUMERIC(0);
2183 char *tmp;
2184 Datum result;
2186 if (NUMERIC_IS_NAN(num))
2187 PG_RETURN_FLOAT8(get_float8_nan());
2189 tmp = DatumGetCString(DirectFunctionCall1(numeric_out,
2190 NumericGetDatum(num)));
2192 result = DirectFunctionCall1(float8in, CStringGetDatum(tmp));
2194 pfree(tmp);
2196 PG_RETURN_DATUM(result);
2200 /* Convert numeric to float8; if out of range, return +/- HUGE_VAL */
2201 Datum
2202 numeric_float8_no_overflow(PG_FUNCTION_ARGS)
2204 Numeric num = PG_GETARG_NUMERIC(0);
2205 double val;
2207 if (NUMERIC_IS_NAN(num))
2208 PG_RETURN_FLOAT8(get_float8_nan());
2210 val = numeric_to_double_no_overflow(num);
2212 PG_RETURN_FLOAT8(val);
2215 Datum
2216 float4_numeric(PG_FUNCTION_ARGS)
2218 float4 val = PG_GETARG_FLOAT4(0);
2219 Numeric res;
2220 NumericVar result;
2221 char buf[FLT_DIG + 100];
2223 if (isnan(val))
2224 PG_RETURN_NUMERIC(make_result(&const_nan));
2226 sprintf(buf, "%.*g", FLT_DIG, val);
2228 init_var(&result);
2230 /* Assume we need not worry about leading/trailing spaces */
2231 (void) set_var_from_str(buf, buf, &result);
2233 res = make_result(&result);
2235 free_var(&result);
2237 PG_RETURN_NUMERIC(res);
2241 Datum
2242 numeric_float4(PG_FUNCTION_ARGS)
2244 Numeric num = PG_GETARG_NUMERIC(0);
2245 char *tmp;
2246 Datum result;
2248 if (NUMERIC_IS_NAN(num))
2249 PG_RETURN_FLOAT4(get_float4_nan());
2251 tmp = DatumGetCString(DirectFunctionCall1(numeric_out,
2252 NumericGetDatum(num)));
2254 result = DirectFunctionCall1(float4in, CStringGetDatum(tmp));
2256 pfree(tmp);
2258 PG_RETURN_DATUM(result);
2262 /* ----------------------------------------------------------------------
2264 * Aggregate functions
2266 * The transition datatype for all these aggregates is a 3-element array
2267 * of Numeric, holding the values N, sum(X), sum(X*X) in that order.
2269 * We represent N as a numeric mainly to avoid having to build a special
2270 * datatype; it's unlikely it'd overflow an int4, but ...
2272 * ----------------------------------------------------------------------
2275 static ArrayType *
2276 do_numeric_accum(ArrayType *transarray, Numeric newval)
2278 Datum *transdatums;
2279 int ndatums;
2280 Datum N,
2281 sumX,
2282 sumX2;
2283 ArrayType *result;
2285 /* We assume the input is array of numeric */
2286 deconstruct_array(transarray,
2287 NUMERICOID, -1, false, 'i',
2288 &transdatums, NULL, &ndatums);
2289 if (ndatums != 3)
2290 elog(ERROR, "expected 3-element numeric array");
2291 N = transdatums[0];
2292 sumX = transdatums[1];
2293 sumX2 = transdatums[2];
2295 N = DirectFunctionCall1(numeric_inc, N);
2296 sumX = DirectFunctionCall2(numeric_add, sumX,
2297 NumericGetDatum(newval));
2298 sumX2 = DirectFunctionCall2(numeric_add, sumX2,
2299 DirectFunctionCall2(numeric_mul,
2300 NumericGetDatum(newval),
2301 NumericGetDatum(newval)));
2303 transdatums[0] = N;
2304 transdatums[1] = sumX;
2305 transdatums[2] = sumX2;
2307 result = construct_array(transdatums, 3,
2308 NUMERICOID, -1, false, 'i');
2310 return result;
2314 * Improve avg performance by not caclulating sum(X*X).
2316 static ArrayType *
2317 do_numeric_avg_accum(ArrayType *transarray, Numeric newval)
2319 Datum *transdatums;
2320 int ndatums;
2321 Datum N,
2322 sumX;
2323 ArrayType *result;
2325 /* We assume the input is array of numeric */
2326 deconstruct_array(transarray,
2327 NUMERICOID, -1, false, 'i',
2328 &transdatums, NULL, &ndatums);
2329 if (ndatums != 2)
2330 elog(ERROR, "expected 2-element numeric array");
2331 N = transdatums[0];
2332 sumX = transdatums[1];
2334 N = DirectFunctionCall1(numeric_inc, N);
2335 sumX = DirectFunctionCall2(numeric_add, sumX,
2336 NumericGetDatum(newval));
2338 transdatums[0] = N;
2339 transdatums[1] = sumX;
2341 result = construct_array(transdatums, 2,
2342 NUMERICOID, -1, false, 'i');
2344 return result;
2347 Datum
2348 numeric_accum(PG_FUNCTION_ARGS)
2350 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
2351 Numeric newval = PG_GETARG_NUMERIC(1);
2353 PG_RETURN_ARRAYTYPE_P(do_numeric_accum(transarray, newval));
2357 * Optimized case for average of numeric.
2359 Datum
2360 numeric_avg_accum(PG_FUNCTION_ARGS)
2362 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
2363 Numeric newval = PG_GETARG_NUMERIC(1);
2365 PG_RETURN_ARRAYTYPE_P(do_numeric_avg_accum(transarray, newval));
2369 * Integer data types all use Numeric accumulators to share code and
2370 * avoid risk of overflow. For int2 and int4 inputs, Numeric accumulation
2371 * is overkill for the N and sum(X) values, but definitely not overkill
2372 * for the sum(X*X) value. Hence, we use int2_accum and int4_accum only
2373 * for stddev/variance --- there are faster special-purpose accumulator
2374 * routines for SUM and AVG of these datatypes.
2377 Datum
2378 int2_accum(PG_FUNCTION_ARGS)
2380 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
2381 Datum newval2 = PG_GETARG_DATUM(1);
2382 Numeric newval;
2384 newval = DatumGetNumeric(DirectFunctionCall1(int2_numeric, newval2));
2386 PG_RETURN_ARRAYTYPE_P(do_numeric_accum(transarray, newval));
2389 Datum
2390 int4_accum(PG_FUNCTION_ARGS)
2392 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
2393 Datum newval4 = PG_GETARG_DATUM(1);
2394 Numeric newval;
2396 newval = DatumGetNumeric(DirectFunctionCall1(int4_numeric, newval4));
2398 PG_RETURN_ARRAYTYPE_P(do_numeric_accum(transarray, newval));
2401 Datum
2402 int8_accum(PG_FUNCTION_ARGS)
2404 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
2405 Datum newval8 = PG_GETARG_DATUM(1);
2406 Numeric newval;
2408 newval = DatumGetNumeric(DirectFunctionCall1(int8_numeric, newval8));
2410 PG_RETURN_ARRAYTYPE_P(do_numeric_accum(transarray, newval));
2414 * Optimized case for average of int8.
2416 Datum
2417 int8_avg_accum(PG_FUNCTION_ARGS)
2419 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
2420 Datum newval8 = PG_GETARG_DATUM(1);
2421 Numeric newval;
2423 newval = DatumGetNumeric(DirectFunctionCall1(int8_numeric, newval8));
2425 PG_RETURN_ARRAYTYPE_P(do_numeric_avg_accum(transarray, newval));
2429 Datum
2430 numeric_avg(PG_FUNCTION_ARGS)
2432 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
2433 Datum *transdatums;
2434 int ndatums;
2435 Numeric N,
2436 sumX;
2438 /* We assume the input is array of numeric */
2439 deconstruct_array(transarray,
2440 NUMERICOID, -1, false, 'i',
2441 &transdatums, NULL, &ndatums);
2442 if (ndatums != 2)
2443 elog(ERROR, "expected 2-element numeric array");
2444 N = DatumGetNumeric(transdatums[0]);
2445 sumX = DatumGetNumeric(transdatums[1]);
2447 /* SQL92 defines AVG of no values to be NULL */
2448 /* N is zero iff no digits (cf. numeric_uminus) */
2449 if (VARSIZE(N) == NUMERIC_HDRSZ)
2450 PG_RETURN_NULL();
2452 PG_RETURN_DATUM(DirectFunctionCall2(numeric_div,
2453 NumericGetDatum(sumX),
2454 NumericGetDatum(N)));
2458 * Workhorse routine for the standard deviance and variance
2459 * aggregates. 'transarray' is the aggregate's transition
2460 * array. 'variance' specifies whether we should calculate the
2461 * variance or the standard deviation. 'sample' indicates whether the
2462 * caller is interested in the sample or the population
2463 * variance/stddev.
2465 * If appropriate variance statistic is undefined for the input,
2466 * *is_null is set to true and NULL is returned.
2468 static Numeric
2469 numeric_stddev_internal(ArrayType *transarray,
2470 bool variance, bool sample,
2471 bool *is_null)
2473 Datum *transdatums;
2474 int ndatums;
2475 Numeric N,
2476 sumX,
2477 sumX2,
2478 res;
2479 NumericVar vN,
2480 vsumX,
2481 vsumX2,
2482 vNminus1;
2483 NumericVar *comp;
2484 int rscale;
2486 *is_null = false;
2488 /* We assume the input is array of numeric */
2489 deconstruct_array(transarray,
2490 NUMERICOID, -1, false, 'i',
2491 &transdatums, NULL, &ndatums);
2492 if (ndatums != 3)
2493 elog(ERROR, "expected 3-element numeric array");
2494 N = DatumGetNumeric(transdatums[0]);
2495 sumX = DatumGetNumeric(transdatums[1]);
2496 sumX2 = DatumGetNumeric(transdatums[2]);
2498 if (NUMERIC_IS_NAN(N) || NUMERIC_IS_NAN(sumX) || NUMERIC_IS_NAN(sumX2))
2499 return make_result(&const_nan);
2501 init_var(&vN);
2502 set_var_from_num(N, &vN);
2505 * Sample stddev and variance are undefined when N <= 1; population stddev
2506 * is undefined when N == 0. Return NULL in either case.
2508 if (sample)
2509 comp = &const_one;
2510 else
2511 comp = &const_zero;
2513 if (cmp_var(&vN, comp) <= 0)
2515 free_var(&vN);
2516 *is_null = true;
2517 return NULL;
2520 init_var(&vNminus1);
2521 sub_var(&vN, &const_one, &vNminus1);
2523 init_var(&vsumX);
2524 set_var_from_num(sumX, &vsumX);
2525 init_var(&vsumX2);
2526 set_var_from_num(sumX2, &vsumX2);
2528 /* compute rscale for mul_var calls */
2529 rscale = vsumX.dscale * 2;
2531 mul_var(&vsumX, &vsumX, &vsumX, rscale); /* vsumX = sumX * sumX */
2532 mul_var(&vN, &vsumX2, &vsumX2, rscale); /* vsumX2 = N * sumX2 */
2533 sub_var(&vsumX2, &vsumX, &vsumX2); /* N * sumX2 - sumX * sumX */
2535 if (cmp_var(&vsumX2, &const_zero) <= 0)
2537 /* Watch out for roundoff error producing a negative numerator */
2538 res = make_result(&const_zero);
2540 else
2542 if (sample)
2543 mul_var(&vN, &vNminus1, &vNminus1, 0); /* N * (N - 1) */
2544 else
2545 mul_var(&vN, &vN, &vNminus1, 0); /* N * N */
2546 rscale = select_div_scale(&vsumX2, &vNminus1);
2547 div_var(&vsumX2, &vNminus1, &vsumX, rscale, true); /* variance */
2548 if (!variance)
2549 sqrt_var(&vsumX, &vsumX, rscale); /* stddev */
2551 res = make_result(&vsumX);
2554 free_var(&vN);
2555 free_var(&vNminus1);
2556 free_var(&vsumX);
2557 free_var(&vsumX2);
2559 return res;
2562 Datum
2563 numeric_var_samp(PG_FUNCTION_ARGS)
2565 Numeric res;
2566 bool is_null;
2568 res = numeric_stddev_internal(PG_GETARG_ARRAYTYPE_P(0),
2569 true, true, &is_null);
2571 if (is_null)
2572 PG_RETURN_NULL();
2573 else
2574 PG_RETURN_NUMERIC(res);
2577 Datum
2578 numeric_stddev_samp(PG_FUNCTION_ARGS)
2580 Numeric res;
2581 bool is_null;
2583 res = numeric_stddev_internal(PG_GETARG_ARRAYTYPE_P(0),
2584 false, true, &is_null);
2586 if (is_null)
2587 PG_RETURN_NULL();
2588 else
2589 PG_RETURN_NUMERIC(res);
2592 Datum
2593 numeric_var_pop(PG_FUNCTION_ARGS)
2595 Numeric res;
2596 bool is_null;
2598 res = numeric_stddev_internal(PG_GETARG_ARRAYTYPE_P(0),
2599 true, false, &is_null);
2601 if (is_null)
2602 PG_RETURN_NULL();
2603 else
2604 PG_RETURN_NUMERIC(res);
2607 Datum
2608 numeric_stddev_pop(PG_FUNCTION_ARGS)
2610 Numeric res;
2611 bool is_null;
2613 res = numeric_stddev_internal(PG_GETARG_ARRAYTYPE_P(0),
2614 false, false, &is_null);
2616 if (is_null)
2617 PG_RETURN_NULL();
2618 else
2619 PG_RETURN_NUMERIC(res);
2623 * SUM transition functions for integer datatypes.
2625 * To avoid overflow, we use accumulators wider than the input datatype.
2626 * A Numeric accumulator is needed for int8 input; for int4 and int2
2627 * inputs, we use int8 accumulators which should be sufficient for practical
2628 * purposes. (The latter two therefore don't really belong in this file,
2629 * but we keep them here anyway.)
2631 * Because SQL92 defines the SUM() of no values to be NULL, not zero,
2632 * the initial condition of the transition data value needs to be NULL. This
2633 * means we can't rely on ExecAgg to automatically insert the first non-null
2634 * data value into the transition data: it doesn't know how to do the type
2635 * conversion. The upshot is that these routines have to be marked non-strict
2636 * and handle substitution of the first non-null input themselves.
2639 Datum
2640 int2_sum(PG_FUNCTION_ARGS)
2642 int64 newval;
2644 if (PG_ARGISNULL(0))
2646 /* No non-null input seen so far... */
2647 if (PG_ARGISNULL(1))
2648 PG_RETURN_NULL(); /* still no non-null */
2649 /* This is the first non-null input. */
2650 newval = (int64) PG_GETARG_INT16(1);
2651 PG_RETURN_INT64(newval);
2655 * If we're invoked by nodeAgg, we can cheat and modify our first
2656 * parameter in-place to avoid palloc overhead. If not, we need to return
2657 * the new value of the transition variable.
2658 * (If int8 is pass-by-value, then of course this is useless as well
2659 * as incorrect, so just ifdef it out.)
2661 #ifndef USE_FLOAT8_BYVAL /* controls int8 too */
2662 if (fcinfo->context &&
2663 (IsA(fcinfo->context, AggState) ||
2664 IsA(fcinfo->context, WindowAggState)))
2666 int64 *oldsum = (int64 *) PG_GETARG_POINTER(0);
2668 /* Leave the running sum unchanged in the new input is null */
2669 if (!PG_ARGISNULL(1))
2670 *oldsum = *oldsum + (int64) PG_GETARG_INT16(1);
2672 PG_RETURN_POINTER(oldsum);
2674 else
2675 #endif
2677 int64 oldsum = PG_GETARG_INT64(0);
2679 /* Leave sum unchanged if new input is null. */
2680 if (PG_ARGISNULL(1))
2681 PG_RETURN_INT64(oldsum);
2683 /* OK to do the addition. */
2684 newval = oldsum + (int64) PG_GETARG_INT16(1);
2686 PG_RETURN_INT64(newval);
2690 Datum
2691 int4_sum(PG_FUNCTION_ARGS)
2693 int64 newval;
2695 if (PG_ARGISNULL(0))
2697 /* No non-null input seen so far... */
2698 if (PG_ARGISNULL(1))
2699 PG_RETURN_NULL(); /* still no non-null */
2700 /* This is the first non-null input. */
2701 newval = (int64) PG_GETARG_INT32(1);
2702 PG_RETURN_INT64(newval);
2706 * If we're invoked by nodeAgg, we can cheat and modify our first
2707 * parameter in-place to avoid palloc overhead. If not, we need to return
2708 * the new value of the transition variable.
2709 * (If int8 is pass-by-value, then of course this is useless as well
2710 * as incorrect, so just ifdef it out.)
2712 #ifndef USE_FLOAT8_BYVAL /* controls int8 too */
2713 if (fcinfo->context &&
2714 (IsA(fcinfo->context, AggState) ||
2715 IsA(fcinfo->context, WindowAggState)))
2717 int64 *oldsum = (int64 *) PG_GETARG_POINTER(0);
2719 /* Leave the running sum unchanged in the new input is null */
2720 if (!PG_ARGISNULL(1))
2721 *oldsum = *oldsum + (int64) PG_GETARG_INT32(1);
2723 PG_RETURN_POINTER(oldsum);
2725 else
2726 #endif
2728 int64 oldsum = PG_GETARG_INT64(0);
2730 /* Leave sum unchanged if new input is null. */
2731 if (PG_ARGISNULL(1))
2732 PG_RETURN_INT64(oldsum);
2734 /* OK to do the addition. */
2735 newval = oldsum + (int64) PG_GETARG_INT32(1);
2737 PG_RETURN_INT64(newval);
2741 Datum
2742 int8_sum(PG_FUNCTION_ARGS)
2744 Numeric oldsum;
2745 Datum newval;
2747 if (PG_ARGISNULL(0))
2749 /* No non-null input seen so far... */
2750 if (PG_ARGISNULL(1))
2751 PG_RETURN_NULL(); /* still no non-null */
2752 /* This is the first non-null input. */
2753 newval = DirectFunctionCall1(int8_numeric, PG_GETARG_DATUM(1));
2754 PG_RETURN_DATUM(newval);
2758 * Note that we cannot special-case the nodeAgg case here, as we do for
2759 * int2_sum and int4_sum: numeric is of variable size, so we cannot modify
2760 * our first parameter in-place.
2763 oldsum = PG_GETARG_NUMERIC(0);
2765 /* Leave sum unchanged if new input is null. */
2766 if (PG_ARGISNULL(1))
2767 PG_RETURN_NUMERIC(oldsum);
2769 /* OK to do the addition. */
2770 newval = DirectFunctionCall1(int8_numeric, PG_GETARG_DATUM(1));
2772 PG_RETURN_DATUM(DirectFunctionCall2(numeric_add,
2773 NumericGetDatum(oldsum), newval));
2778 * Routines for avg(int2) and avg(int4). The transition datatype
2779 * is a two-element int8 array, holding count and sum.
2782 typedef struct Int8TransTypeData
2784 #ifndef INT64_IS_BUSTED
2785 int64 count;
2786 int64 sum;
2787 #else
2788 /* "int64" isn't really 64 bits, so fake up properly-aligned fields */
2789 int32 count;
2790 int32 pad1;
2791 int32 sum;
2792 int32 pad2;
2793 #endif
2794 } Int8TransTypeData;
2796 Datum
2797 int2_avg_accum(PG_FUNCTION_ARGS)
2799 ArrayType *transarray;
2800 int16 newval = PG_GETARG_INT16(1);
2801 Int8TransTypeData *transdata;
2804 * If we're invoked by nodeAgg, we can cheat and modify our first
2805 * parameter in-place to reduce palloc overhead. Otherwise we need to make
2806 * a copy of it before scribbling on it.
2808 if (fcinfo->context &&
2809 (IsA(fcinfo->context, AggState) ||
2810 IsA(fcinfo->context, WindowAggState)))
2811 transarray = PG_GETARG_ARRAYTYPE_P(0);
2812 else
2813 transarray = PG_GETARG_ARRAYTYPE_P_COPY(0);
2815 if (ARR_HASNULL(transarray) ||
2816 ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
2817 elog(ERROR, "expected 2-element int8 array");
2819 transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
2820 transdata->count++;
2821 transdata->sum += newval;
2823 PG_RETURN_ARRAYTYPE_P(transarray);
2826 Datum
2827 int4_avg_accum(PG_FUNCTION_ARGS)
2829 ArrayType *transarray;
2830 int32 newval = PG_GETARG_INT32(1);
2831 Int8TransTypeData *transdata;
2834 * If we're invoked by nodeAgg, we can cheat and modify our first
2835 * parameter in-place to reduce palloc overhead. Otherwise we need to make
2836 * a copy of it before scribbling on it.
2838 if (fcinfo->context &&
2839 (IsA(fcinfo->context, AggState) ||
2840 IsA(fcinfo->context, WindowAggState)))
2841 transarray = PG_GETARG_ARRAYTYPE_P(0);
2842 else
2843 transarray = PG_GETARG_ARRAYTYPE_P_COPY(0);
2845 if (ARR_HASNULL(transarray) ||
2846 ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
2847 elog(ERROR, "expected 2-element int8 array");
2849 transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
2850 transdata->count++;
2851 transdata->sum += newval;
2853 PG_RETURN_ARRAYTYPE_P(transarray);
2856 Datum
2857 int8_avg(PG_FUNCTION_ARGS)
2859 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
2860 Int8TransTypeData *transdata;
2861 Datum countd,
2862 sumd;
2864 if (ARR_HASNULL(transarray) ||
2865 ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
2866 elog(ERROR, "expected 2-element int8 array");
2867 transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
2869 /* SQL92 defines AVG of no values to be NULL */
2870 if (transdata->count == 0)
2871 PG_RETURN_NULL();
2873 countd = DirectFunctionCall1(int8_numeric,
2874 Int64GetDatumFast(transdata->count));
2875 sumd = DirectFunctionCall1(int8_numeric,
2876 Int64GetDatumFast(transdata->sum));
2878 PG_RETURN_DATUM(DirectFunctionCall2(numeric_div, sumd, countd));
2882 /* ----------------------------------------------------------------------
2884 * Debug support
2886 * ----------------------------------------------------------------------
2889 #ifdef NUMERIC_DEBUG
2892 * dump_numeric() - Dump a value in the db storage format for debugging
2894 static void
2895 dump_numeric(const char *str, Numeric num)
2897 NumericDigit *digits = NUMERIC_DIGITS(num);
2898 int ndigits;
2899 int i;
2901 ndigits = NUMERIC_NDIGITS(num);
2903 printf("%s: NUMERIC w=%d d=%d ", str, num->n_weight, NUMERIC_DSCALE(num));
2904 switch (NUMERIC_SIGN(num))
2906 case NUMERIC_POS:
2907 printf("POS");
2908 break;
2909 case NUMERIC_NEG:
2910 printf("NEG");
2911 break;
2912 case NUMERIC_NAN:
2913 printf("NaN");
2914 break;
2915 default:
2916 printf("SIGN=0x%x", NUMERIC_SIGN(num));
2917 break;
2920 for (i = 0; i < ndigits; i++)
2921 printf(" %0*d", DEC_DIGITS, digits[i]);
2922 printf("\n");
2927 * dump_var() - Dump a value in the variable format for debugging
2929 static void
2930 dump_var(const char *str, NumericVar *var)
2932 int i;
2934 printf("%s: VAR w=%d d=%d ", str, var->weight, var->dscale);
2935 switch (var->sign)
2937 case NUMERIC_POS:
2938 printf("POS");
2939 break;
2940 case NUMERIC_NEG:
2941 printf("NEG");
2942 break;
2943 case NUMERIC_NAN:
2944 printf("NaN");
2945 break;
2946 default:
2947 printf("SIGN=0x%x", var->sign);
2948 break;
2951 for (i = 0; i < var->ndigits; i++)
2952 printf(" %0*d", DEC_DIGITS, var->digits[i]);
2954 printf("\n");
2956 #endif /* NUMERIC_DEBUG */
2959 /* ----------------------------------------------------------------------
2961 * Local functions follow
2963 * In general, these do not support NaNs --- callers must eliminate
2964 * the possibility of NaN first. (make_result() is an exception.)
2966 * ----------------------------------------------------------------------
2971 * alloc_var() -
2973 * Allocate a digit buffer of ndigits digits (plus a spare digit for rounding)
2975 static void
2976 alloc_var(NumericVar *var, int ndigits)
2978 digitbuf_free(var->buf);
2979 var->buf = digitbuf_alloc(ndigits + 1);
2980 var->buf[0] = 0; /* spare digit for rounding */
2981 var->digits = var->buf + 1;
2982 var->ndigits = ndigits;
2987 * free_var() -
2989 * Return the digit buffer of a variable to the free pool
2991 static void
2992 free_var(NumericVar *var)
2994 digitbuf_free(var->buf);
2995 var->buf = NULL;
2996 var->digits = NULL;
2997 var->sign = NUMERIC_NAN;
3002 * zero_var() -
3004 * Set a variable to ZERO.
3005 * Note: its dscale is not touched.
3007 static void
3008 zero_var(NumericVar *var)
3010 digitbuf_free(var->buf);
3011 var->buf = NULL;
3012 var->digits = NULL;
3013 var->ndigits = 0;
3014 var->weight = 0; /* by convention; doesn't really matter */
3015 var->sign = NUMERIC_POS; /* anything but NAN... */
3020 * set_var_from_str()
3022 * Parse a string and put the number into a variable
3024 * This function does not handle leading or trailing spaces, and it doesn't
3025 * accept "NaN" either. It returns the end+1 position so that caller can
3026 * check for trailing spaces/garbage if deemed necessary.
3028 * cp is the place to actually start parsing; str is what to use in error
3029 * reports. (Typically cp would be the same except advanced over spaces.)
3031 static const char *
3032 set_var_from_str(const char *str, const char *cp, NumericVar *dest)
3034 bool have_dp = FALSE;
3035 int i;
3036 unsigned char *decdigits;
3037 int sign = NUMERIC_POS;
3038 int dweight = -1;
3039 int ddigits;
3040 int dscale = 0;
3041 int weight;
3042 int ndigits;
3043 int offset;
3044 NumericDigit *digits;
3047 * We first parse the string to extract decimal digits and determine the
3048 * correct decimal weight. Then convert to NBASE representation.
3050 switch (*cp)
3052 case '+':
3053 sign = NUMERIC_POS;
3054 cp++;
3055 break;
3057 case '-':
3058 sign = NUMERIC_NEG;
3059 cp++;
3060 break;
3063 if (*cp == '.')
3065 have_dp = TRUE;
3066 cp++;
3069 if (!isdigit((unsigned char) *cp))
3070 ereport(ERROR,
3071 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
3072 errmsg("invalid input syntax for type numeric: \"%s\"", str)));
3074 decdigits = (unsigned char *) palloc(strlen(cp) + DEC_DIGITS * 2);
3076 /* leading padding for digit alignment later */
3077 memset(decdigits, 0, DEC_DIGITS);
3078 i = DEC_DIGITS;
3080 while (*cp)
3082 if (isdigit((unsigned char) *cp))
3084 decdigits[i++] = *cp++ - '0';
3085 if (!have_dp)
3086 dweight++;
3087 else
3088 dscale++;
3090 else if (*cp == '.')
3092 if (have_dp)
3093 ereport(ERROR,
3094 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
3095 errmsg("invalid input syntax for type numeric: \"%s\"",
3096 str)));
3097 have_dp = TRUE;
3098 cp++;
3100 else
3101 break;
3104 ddigits = i - DEC_DIGITS;
3105 /* trailing padding for digit alignment later */
3106 memset(decdigits + i, 0, DEC_DIGITS - 1);
3108 /* Handle exponent, if any */
3109 if (*cp == 'e' || *cp == 'E')
3111 long exponent;
3112 char *endptr;
3114 cp++;
3115 exponent = strtol(cp, &endptr, 10);
3116 if (endptr == cp)
3117 ereport(ERROR,
3118 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
3119 errmsg("invalid input syntax for type numeric: \"%s\"",
3120 str)));
3121 cp = endptr;
3122 if (exponent > NUMERIC_MAX_PRECISION ||
3123 exponent < -NUMERIC_MAX_PRECISION)
3124 ereport(ERROR,
3125 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
3126 errmsg("invalid input syntax for type numeric: \"%s\"",
3127 str)));
3128 dweight += (int) exponent;
3129 dscale -= (int) exponent;
3130 if (dscale < 0)
3131 dscale = 0;
3135 * Okay, convert pure-decimal representation to base NBASE. First we need
3136 * to determine the converted weight and ndigits. offset is the number of
3137 * decimal zeroes to insert before the first given digit to have a
3138 * correctly aligned first NBASE digit.
3140 if (dweight >= 0)
3141 weight = (dweight + 1 + DEC_DIGITS - 1) / DEC_DIGITS - 1;
3142 else
3143 weight = -((-dweight - 1) / DEC_DIGITS + 1);
3144 offset = (weight + 1) * DEC_DIGITS - (dweight + 1);
3145 ndigits = (ddigits + offset + DEC_DIGITS - 1) / DEC_DIGITS;
3147 alloc_var(dest, ndigits);
3148 dest->sign = sign;
3149 dest->weight = weight;
3150 dest->dscale = dscale;
3152 i = DEC_DIGITS - offset;
3153 digits = dest->digits;
3155 while (ndigits-- > 0)
3157 #if DEC_DIGITS == 4
3158 *digits++ = ((decdigits[i] * 10 + decdigits[i + 1]) * 10 +
3159 decdigits[i + 2]) * 10 + decdigits[i + 3];
3160 #elif DEC_DIGITS == 2
3161 *digits++ = decdigits[i] * 10 + decdigits[i + 1];
3162 #elif DEC_DIGITS == 1
3163 *digits++ = decdigits[i];
3164 #else
3165 #error unsupported NBASE
3166 #endif
3167 i += DEC_DIGITS;
3170 pfree(decdigits);
3172 /* Strip any leading/trailing zeroes, and normalize weight if zero */
3173 strip_var(dest);
3175 /* Return end+1 position for caller */
3176 return cp;
3181 * set_var_from_num() -
3183 * Convert the packed db format into a variable
3185 static void
3186 set_var_from_num(Numeric num, NumericVar *dest)
3188 int ndigits;
3190 ndigits = NUMERIC_NDIGITS(num);
3192 alloc_var(dest, ndigits);
3194 dest->weight = num->n_weight;
3195 dest->sign = NUMERIC_SIGN(num);
3196 dest->dscale = NUMERIC_DSCALE(num);
3198 memcpy(dest->digits, num->n_data, ndigits * sizeof(NumericDigit));
3203 * set_var_from_var() -
3205 * Copy one variable into another
3207 static void
3208 set_var_from_var(NumericVar *value, NumericVar *dest)
3210 NumericDigit *newbuf;
3212 newbuf = digitbuf_alloc(value->ndigits + 1);
3213 newbuf[0] = 0; /* spare digit for rounding */
3214 memcpy(newbuf + 1, value->digits, value->ndigits * sizeof(NumericDigit));
3216 digitbuf_free(dest->buf);
3218 memmove(dest, value, sizeof(NumericVar));
3219 dest->buf = newbuf;
3220 dest->digits = newbuf + 1;
3225 * get_str_from_var() -
3227 * Convert a var to text representation (guts of numeric_out).
3228 * CAUTION: var's contents may be modified by rounding!
3229 * Returns a palloc'd string.
3231 static char *
3232 get_str_from_var(NumericVar *var, int dscale)
3234 char *str;
3235 char *cp;
3236 char *endcp;
3237 int i;
3238 int d;
3239 NumericDigit dig;
3241 #if DEC_DIGITS > 1
3242 NumericDigit d1;
3243 #endif
3245 if (dscale < 0)
3246 dscale = 0;
3249 * Check if we must round up before printing the value and do so.
3251 round_var(var, dscale);
3254 * Allocate space for the result.
3256 * i is set to to # of decimal digits before decimal point. dscale is the
3257 * # of decimal digits we will print after decimal point. We may generate
3258 * as many as DEC_DIGITS-1 excess digits at the end, and in addition we
3259 * need room for sign, decimal point, null terminator.
3261 i = (var->weight + 1) * DEC_DIGITS;
3262 if (i <= 0)
3263 i = 1;
3265 str = palloc(i + dscale + DEC_DIGITS + 2);
3266 cp = str;
3269 * Output a dash for negative values
3271 if (var->sign == NUMERIC_NEG)
3272 *cp++ = '-';
3275 * Output all digits before the decimal point
3277 if (var->weight < 0)
3279 d = var->weight + 1;
3280 *cp++ = '0';
3282 else
3284 for (d = 0; d <= var->weight; d++)
3286 dig = (d < var->ndigits) ? var->digits[d] : 0;
3287 /* In the first digit, suppress extra leading decimal zeroes */
3288 #if DEC_DIGITS == 4
3290 bool putit = (d > 0);
3292 d1 = dig / 1000;
3293 dig -= d1 * 1000;
3294 putit |= (d1 > 0);
3295 if (putit)
3296 *cp++ = d1 + '0';
3297 d1 = dig / 100;
3298 dig -= d1 * 100;
3299 putit |= (d1 > 0);
3300 if (putit)
3301 *cp++ = d1 + '0';
3302 d1 = dig / 10;
3303 dig -= d1 * 10;
3304 putit |= (d1 > 0);
3305 if (putit)
3306 *cp++ = d1 + '0';
3307 *cp++ = dig + '0';
3309 #elif DEC_DIGITS == 2
3310 d1 = dig / 10;
3311 dig -= d1 * 10;
3312 if (d1 > 0 || d > 0)
3313 *cp++ = d1 + '0';
3314 *cp++ = dig + '0';
3315 #elif DEC_DIGITS == 1
3316 *cp++ = dig + '0';
3317 #else
3318 #error unsupported NBASE
3319 #endif
3324 * If requested, output a decimal point and all the digits that follow it.
3325 * We initially put out a multiple of DEC_DIGITS digits, then truncate if
3326 * needed.
3328 if (dscale > 0)
3330 *cp++ = '.';
3331 endcp = cp + dscale;
3332 for (i = 0; i < dscale; d++, i += DEC_DIGITS)
3334 dig = (d >= 0 && d < var->ndigits) ? var->digits[d] : 0;
3335 #if DEC_DIGITS == 4
3336 d1 = dig / 1000;
3337 dig -= d1 * 1000;
3338 *cp++ = d1 + '0';
3339 d1 = dig / 100;
3340 dig -= d1 * 100;
3341 *cp++ = d1 + '0';
3342 d1 = dig / 10;
3343 dig -= d1 * 10;
3344 *cp++ = d1 + '0';
3345 *cp++ = dig + '0';
3346 #elif DEC_DIGITS == 2
3347 d1 = dig / 10;
3348 dig -= d1 * 10;
3349 *cp++ = d1 + '0';
3350 *cp++ = dig + '0';
3351 #elif DEC_DIGITS == 1
3352 *cp++ = dig + '0';
3353 #else
3354 #error unsupported NBASE
3355 #endif
3357 cp = endcp;
3361 * terminate the string and return it
3363 *cp = '\0';
3364 return str;
3369 * make_result() -
3371 * Create the packed db numeric format in palloc()'d memory from
3372 * a variable.
3374 static Numeric
3375 make_result(NumericVar *var)
3377 Numeric result;
3378 NumericDigit *digits = var->digits;
3379 int weight = var->weight;
3380 int sign = var->sign;
3381 int n;
3382 Size len;
3384 if (sign == NUMERIC_NAN)
3386 result = (Numeric) palloc(NUMERIC_HDRSZ);
3388 SET_VARSIZE(result, NUMERIC_HDRSZ);
3389 result->n_weight = 0;
3390 result->n_sign_dscale = NUMERIC_NAN;
3392 dump_numeric("make_result()", result);
3393 return result;
3396 n = var->ndigits;
3398 /* truncate leading zeroes */
3399 while (n > 0 && *digits == 0)
3401 digits++;
3402 weight--;
3403 n--;
3405 /* truncate trailing zeroes */
3406 while (n > 0 && digits[n - 1] == 0)
3407 n--;
3409 /* If zero result, force to weight=0 and positive sign */
3410 if (n == 0)
3412 weight = 0;
3413 sign = NUMERIC_POS;
3416 /* Build the result */
3417 len = NUMERIC_HDRSZ + n * sizeof(NumericDigit);
3418 result = (Numeric) palloc(len);
3419 SET_VARSIZE(result, len);
3420 result->n_weight = weight;
3421 result->n_sign_dscale = sign | (var->dscale & NUMERIC_DSCALE_MASK);
3423 memcpy(result->n_data, digits, n * sizeof(NumericDigit));
3425 /* Check for overflow of int16 fields */
3426 if (result->n_weight != weight ||
3427 NUMERIC_DSCALE(result) != var->dscale)
3428 ereport(ERROR,
3429 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
3430 errmsg("value overflows numeric format")));
3432 dump_numeric("make_result()", result);
3433 return result;
3438 * apply_typmod() -
3440 * Do bounds checking and rounding according to the attributes
3441 * typmod field.
3443 static void
3444 apply_typmod(NumericVar *var, int32 typmod)
3446 int precision;
3447 int scale;
3448 int maxdigits;
3449 int ddigits;
3450 int i;
3452 /* Do nothing if we have a default typmod (-1) */
3453 if (typmod < (int32) (VARHDRSZ))
3454 return;
3456 typmod -= VARHDRSZ;
3457 precision = (typmod >> 16) & 0xffff;
3458 scale = typmod & 0xffff;
3459 maxdigits = precision - scale;
3461 /* Round to target scale (and set var->dscale) */
3462 round_var(var, scale);
3465 * Check for overflow - note we can't do this before rounding, because
3466 * rounding could raise the weight. Also note that the var's weight could
3467 * be inflated by leading zeroes, which will be stripped before storage
3468 * but perhaps might not have been yet. In any case, we must recognize a
3469 * true zero, whose weight doesn't mean anything.
3471 ddigits = (var->weight + 1) * DEC_DIGITS;
3472 if (ddigits > maxdigits)
3474 /* Determine true weight; and check for all-zero result */
3475 for (i = 0; i < var->ndigits; i++)
3477 NumericDigit dig = var->digits[i];
3479 if (dig)
3481 /* Adjust for any high-order decimal zero digits */
3482 #if DEC_DIGITS == 4
3483 if (dig < 10)
3484 ddigits -= 3;
3485 else if (dig < 100)
3486 ddigits -= 2;
3487 else if (dig < 1000)
3488 ddigits -= 1;
3489 #elif DEC_DIGITS == 2
3490 if (dig < 10)
3491 ddigits -= 1;
3492 #elif DEC_DIGITS == 1
3493 /* no adjustment */
3494 #else
3495 #error unsupported NBASE
3496 #endif
3497 if (ddigits > maxdigits)
3498 ereport(ERROR,
3499 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
3500 errmsg("numeric field overflow"),
3501 errdetail("A field with precision %d, scale %d must round to an absolute value less than %s%d.",
3502 precision, scale,
3503 /* Display 10^0 as 1 */
3504 maxdigits ? "10^" : "",
3505 maxdigits ? maxdigits : 1
3506 )));
3507 break;
3509 ddigits -= DEC_DIGITS;
3515 * Convert numeric to int8, rounding if needed.
3517 * If overflow, return FALSE (no error is raised). Return TRUE if okay.
3519 * CAUTION: var's contents may be modified by rounding!
3521 static bool
3522 numericvar_to_int8(NumericVar *var, int64 *result)
3524 NumericDigit *digits;
3525 int ndigits;
3526 int weight;
3527 int i;
3528 int64 val,
3529 oldval;
3530 bool neg;
3532 /* Round to nearest integer */
3533 round_var(var, 0);
3535 /* Check for zero input */
3536 strip_var(var);
3537 ndigits = var->ndigits;
3538 if (ndigits == 0)
3540 *result = 0;
3541 return true;
3545 * For input like 10000000000, we must treat stripped digits as real. So
3546 * the loop assumes there are weight+1 digits before the decimal point.
3548 weight = var->weight;
3549 Assert(weight >= 0 && ndigits <= weight + 1);
3551 /* Construct the result */
3552 digits = var->digits;
3553 neg = (var->sign == NUMERIC_NEG);
3554 val = digits[0];
3555 for (i = 1; i <= weight; i++)
3557 oldval = val;
3558 val *= NBASE;
3559 if (i < ndigits)
3560 val += digits[i];
3563 * The overflow check is a bit tricky because we want to accept
3564 * INT64_MIN, which will overflow the positive accumulator. We can
3565 * detect this case easily though because INT64_MIN is the only
3566 * nonzero value for which -val == val (on a two's complement machine,
3567 * anyway).
3569 if ((val / NBASE) != oldval) /* possible overflow? */
3571 if (!neg || (-val) != val || val == 0 || oldval < 0)
3572 return false;
3576 *result = neg ? -val : val;
3577 return true;
3581 * Convert int8 value to numeric.
3583 static void
3584 int8_to_numericvar(int64 val, NumericVar *var)
3586 uint64 uval,
3587 newuval;
3588 NumericDigit *ptr;
3589 int ndigits;
3591 /* int8 can require at most 19 decimal digits; add one for safety */
3592 alloc_var(var, 20 / DEC_DIGITS);
3593 if (val < 0)
3595 var->sign = NUMERIC_NEG;
3596 uval = -val;
3598 else
3600 var->sign = NUMERIC_POS;
3601 uval = val;
3603 var->dscale = 0;
3604 if (val == 0)
3606 var->ndigits = 0;
3607 var->weight = 0;
3608 return;
3610 ptr = var->digits + var->ndigits;
3611 ndigits = 0;
3614 ptr--;
3615 ndigits++;
3616 newuval = uval / NBASE;
3617 *ptr = uval - newuval * NBASE;
3618 uval = newuval;
3619 } while (uval);
3620 var->digits = ptr;
3621 var->ndigits = ndigits;
3622 var->weight = ndigits - 1;
3626 * Convert numeric to float8; if out of range, return +/- HUGE_VAL
3628 static double
3629 numeric_to_double_no_overflow(Numeric num)
3631 char *tmp;
3632 double val;
3633 char *endptr;
3635 tmp = DatumGetCString(DirectFunctionCall1(numeric_out,
3636 NumericGetDatum(num)));
3638 /* unlike float8in, we ignore ERANGE from strtod */
3639 val = strtod(tmp, &endptr);
3640 if (*endptr != '\0')
3642 /* shouldn't happen ... */
3643 ereport(ERROR,
3644 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
3645 errmsg("invalid input syntax for type double precision: \"%s\"",
3646 tmp)));
3649 pfree(tmp);
3651 return val;
3654 /* As above, but work from a NumericVar */
3655 static double
3656 numericvar_to_double_no_overflow(NumericVar *var)
3658 char *tmp;
3659 double val;
3660 char *endptr;
3662 tmp = get_str_from_var(var, var->dscale);
3664 /* unlike float8in, we ignore ERANGE from strtod */
3665 val = strtod(tmp, &endptr);
3666 if (*endptr != '\0')
3668 /* shouldn't happen ... */
3669 ereport(ERROR,
3670 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
3671 errmsg("invalid input syntax for type double precision: \"%s\"",
3672 tmp)));
3675 pfree(tmp);
3677 return val;
3682 * cmp_var() -
3684 * Compare two values on variable level. We assume zeroes have been
3685 * truncated to no digits.
3687 static int
3688 cmp_var(NumericVar *var1, NumericVar *var2)
3690 return cmp_var_common(var1->digits, var1->ndigits,
3691 var1->weight, var1->sign,
3692 var2->digits, var2->ndigits,
3693 var2->weight, var2->sign);
3697 * cmp_var_common() -
3699 * Main routine of cmp_var(). This function can be used by both
3700 * NumericVar and Numeric.
3702 static int
3703 cmp_var_common(const NumericDigit *var1digits, int var1ndigits,
3704 int var1weight, int var1sign,
3705 const NumericDigit *var2digits, int var2ndigits,
3706 int var2weight, int var2sign)
3708 if (var1ndigits == 0)
3710 if (var2ndigits == 0)
3711 return 0;
3712 if (var2sign == NUMERIC_NEG)
3713 return 1;
3714 return -1;
3716 if (var2ndigits == 0)
3718 if (var1sign == NUMERIC_POS)
3719 return 1;
3720 return -1;
3723 if (var1sign == NUMERIC_POS)
3725 if (var2sign == NUMERIC_NEG)
3726 return 1;
3727 return cmp_abs_common(var1digits, var1ndigits, var1weight,
3728 var2digits, var2ndigits, var2weight);
3731 if (var2sign == NUMERIC_POS)
3732 return -1;
3734 return cmp_abs_common(var2digits, var2ndigits, var2weight,
3735 var1digits, var1ndigits, var1weight);
3740 * add_var() -
3742 * Full version of add functionality on variable level (handling signs).
3743 * result might point to one of the operands too without danger.
3745 static void
3746 add_var(NumericVar *var1, NumericVar *var2, NumericVar *result)
3749 * Decide on the signs of the two variables what to do
3751 if (var1->sign == NUMERIC_POS)
3753 if (var2->sign == NUMERIC_POS)
3756 * Both are positive result = +(ABS(var1) + ABS(var2))
3758 add_abs(var1, var2, result);
3759 result->sign = NUMERIC_POS;
3761 else
3764 * var1 is positive, var2 is negative Must compare absolute values
3766 switch (cmp_abs(var1, var2))
3768 case 0:
3769 /* ----------
3770 * ABS(var1) == ABS(var2)
3771 * result = ZERO
3772 * ----------
3774 zero_var(result);
3775 result->dscale = Max(var1->dscale, var2->dscale);
3776 break;
3778 case 1:
3779 /* ----------
3780 * ABS(var1) > ABS(var2)
3781 * result = +(ABS(var1) - ABS(var2))
3782 * ----------
3784 sub_abs(var1, var2, result);
3785 result->sign = NUMERIC_POS;
3786 break;
3788 case -1:
3789 /* ----------
3790 * ABS(var1) < ABS(var2)
3791 * result = -(ABS(var2) - ABS(var1))
3792 * ----------
3794 sub_abs(var2, var1, result);
3795 result->sign = NUMERIC_NEG;
3796 break;
3800 else
3802 if (var2->sign == NUMERIC_POS)
3804 /* ----------
3805 * var1 is negative, var2 is positive
3806 * Must compare absolute values
3807 * ----------
3809 switch (cmp_abs(var1, var2))
3811 case 0:
3812 /* ----------
3813 * ABS(var1) == ABS(var2)
3814 * result = ZERO
3815 * ----------
3817 zero_var(result);
3818 result->dscale = Max(var1->dscale, var2->dscale);
3819 break;
3821 case 1:
3822 /* ----------
3823 * ABS(var1) > ABS(var2)
3824 * result = -(ABS(var1) - ABS(var2))
3825 * ----------
3827 sub_abs(var1, var2, result);
3828 result->sign = NUMERIC_NEG;
3829 break;
3831 case -1:
3832 /* ----------
3833 * ABS(var1) < ABS(var2)
3834 * result = +(ABS(var2) - ABS(var1))
3835 * ----------
3837 sub_abs(var2, var1, result);
3838 result->sign = NUMERIC_POS;
3839 break;
3842 else
3844 /* ----------
3845 * Both are negative
3846 * result = -(ABS(var1) + ABS(var2))
3847 * ----------
3849 add_abs(var1, var2, result);
3850 result->sign = NUMERIC_NEG;
3857 * sub_var() -
3859 * Full version of sub functionality on variable level (handling signs).
3860 * result might point to one of the operands too without danger.
3862 static void
3863 sub_var(NumericVar *var1, NumericVar *var2, NumericVar *result)
3866 * Decide on the signs of the two variables what to do
3868 if (var1->sign == NUMERIC_POS)
3870 if (var2->sign == NUMERIC_NEG)
3872 /* ----------
3873 * var1 is positive, var2 is negative
3874 * result = +(ABS(var1) + ABS(var2))
3875 * ----------
3877 add_abs(var1, var2, result);
3878 result->sign = NUMERIC_POS;
3880 else
3882 /* ----------
3883 * Both are positive
3884 * Must compare absolute values
3885 * ----------
3887 switch (cmp_abs(var1, var2))
3889 case 0:
3890 /* ----------
3891 * ABS(var1) == ABS(var2)
3892 * result = ZERO
3893 * ----------
3895 zero_var(result);
3896 result->dscale = Max(var1->dscale, var2->dscale);
3897 break;
3899 case 1:
3900 /* ----------
3901 * ABS(var1) > ABS(var2)
3902 * result = +(ABS(var1) - ABS(var2))
3903 * ----------
3905 sub_abs(var1, var2, result);
3906 result->sign = NUMERIC_POS;
3907 break;
3909 case -1:
3910 /* ----------
3911 * ABS(var1) < ABS(var2)
3912 * result = -(ABS(var2) - ABS(var1))
3913 * ----------
3915 sub_abs(var2, var1, result);
3916 result->sign = NUMERIC_NEG;
3917 break;
3921 else
3923 if (var2->sign == NUMERIC_NEG)
3925 /* ----------
3926 * Both are negative
3927 * Must compare absolute values
3928 * ----------
3930 switch (cmp_abs(var1, var2))
3932 case 0:
3933 /* ----------
3934 * ABS(var1) == ABS(var2)
3935 * result = ZERO
3936 * ----------
3938 zero_var(result);
3939 result->dscale = Max(var1->dscale, var2->dscale);
3940 break;
3942 case 1:
3943 /* ----------
3944 * ABS(var1) > ABS(var2)
3945 * result = -(ABS(var1) - ABS(var2))
3946 * ----------
3948 sub_abs(var1, var2, result);
3949 result->sign = NUMERIC_NEG;
3950 break;
3952 case -1:
3953 /* ----------
3954 * ABS(var1) < ABS(var2)
3955 * result = +(ABS(var2) - ABS(var1))
3956 * ----------
3958 sub_abs(var2, var1, result);
3959 result->sign = NUMERIC_POS;
3960 break;
3963 else
3965 /* ----------
3966 * var1 is negative, var2 is positive
3967 * result = -(ABS(var1) + ABS(var2))
3968 * ----------
3970 add_abs(var1, var2, result);
3971 result->sign = NUMERIC_NEG;
3978 * mul_var() -
3980 * Multiplication on variable level. Product of var1 * var2 is stored
3981 * in result. Result is rounded to no more than rscale fractional digits.
3983 static void
3984 mul_var(NumericVar *var1, NumericVar *var2, NumericVar *result,
3985 int rscale)
3987 int res_ndigits;
3988 int res_sign;
3989 int res_weight;
3990 int maxdigits;
3991 int *dig;
3992 int carry;
3993 int maxdig;
3994 int newdig;
3995 NumericDigit *res_digits;
3996 int i,
4001 /* copy these values into local vars for speed in inner loop */
4002 int var1ndigits = var1->ndigits;
4003 int var2ndigits = var2->ndigits;
4004 NumericDigit *var1digits = var1->digits;
4005 NumericDigit *var2digits = var2->digits;
4007 if (var1ndigits == 0 || var2ndigits == 0)
4009 /* one or both inputs is zero; so is result */
4010 zero_var(result);
4011 result->dscale = rscale;
4012 return;
4015 /* Determine result sign and (maximum possible) weight */
4016 if (var1->sign == var2->sign)
4017 res_sign = NUMERIC_POS;
4018 else
4019 res_sign = NUMERIC_NEG;
4020 res_weight = var1->weight + var2->weight + 2;
4023 * Determine number of result digits to compute. If the exact result
4024 * would have more than rscale fractional digits, truncate the computation
4025 * with MUL_GUARD_DIGITS guard digits. We do that by pretending that one
4026 * or both inputs have fewer digits than they really do.
4028 res_ndigits = var1ndigits + var2ndigits + 1;
4029 maxdigits = res_weight + 1 + (rscale * DEC_DIGITS) + MUL_GUARD_DIGITS;
4030 if (res_ndigits > maxdigits)
4032 if (maxdigits < 3)
4034 /* no useful precision at all in the result... */
4035 zero_var(result);
4036 result->dscale = rscale;
4037 return;
4039 /* force maxdigits odd so that input ndigits can be equal */
4040 if ((maxdigits & 1) == 0)
4041 maxdigits++;
4042 if (var1ndigits > var2ndigits)
4044 var1ndigits -= res_ndigits - maxdigits;
4045 if (var1ndigits < var2ndigits)
4046 var1ndigits = var2ndigits = (var1ndigits + var2ndigits) / 2;
4048 else
4050 var2ndigits -= res_ndigits - maxdigits;
4051 if (var2ndigits < var1ndigits)
4052 var1ndigits = var2ndigits = (var1ndigits + var2ndigits) / 2;
4054 res_ndigits = maxdigits;
4055 Assert(res_ndigits == var1ndigits + var2ndigits + 1);
4059 * We do the arithmetic in an array "dig[]" of signed int's. Since
4060 * INT_MAX is noticeably larger than NBASE*NBASE, this gives us headroom
4061 * to avoid normalizing carries immediately.
4063 * maxdig tracks the maximum possible value of any dig[] entry; when this
4064 * threatens to exceed INT_MAX, we take the time to propagate carries. To
4065 * avoid overflow in maxdig itself, it actually represents the max
4066 * possible value divided by NBASE-1.
4068 dig = (int *) palloc0(res_ndigits * sizeof(int));
4069 maxdig = 0;
4071 ri = res_ndigits - 1;
4072 for (i1 = var1ndigits - 1; i1 >= 0; ri--, i1--)
4074 int var1digit = var1digits[i1];
4076 if (var1digit == 0)
4077 continue;
4079 /* Time to normalize? */
4080 maxdig += var1digit;
4081 if (maxdig > INT_MAX / (NBASE - 1))
4083 /* Yes, do it */
4084 carry = 0;
4085 for (i = res_ndigits - 1; i >= 0; i--)
4087 newdig = dig[i] + carry;
4088 if (newdig >= NBASE)
4090 carry = newdig / NBASE;
4091 newdig -= carry * NBASE;
4093 else
4094 carry = 0;
4095 dig[i] = newdig;
4097 Assert(carry == 0);
4098 /* Reset maxdig to indicate new worst-case */
4099 maxdig = 1 + var1digit;
4102 /* Add appropriate multiple of var2 into the accumulator */
4103 i = ri;
4104 for (i2 = var2ndigits - 1; i2 >= 0; i2--)
4105 dig[i--] += var1digit * var2digits[i2];
4109 * Now we do a final carry propagation pass to normalize the result, which
4110 * we combine with storing the result digits into the output. Note that
4111 * this is still done at full precision w/guard digits.
4113 alloc_var(result, res_ndigits);
4114 res_digits = result->digits;
4115 carry = 0;
4116 for (i = res_ndigits - 1; i >= 0; i--)
4118 newdig = dig[i] + carry;
4119 if (newdig >= NBASE)
4121 carry = newdig / NBASE;
4122 newdig -= carry * NBASE;
4124 else
4125 carry = 0;
4126 res_digits[i] = newdig;
4128 Assert(carry == 0);
4130 pfree(dig);
4133 * Finally, round the result to the requested precision.
4135 result->weight = res_weight;
4136 result->sign = res_sign;
4138 /* Round to target rscale (and set result->dscale) */
4139 round_var(result, rscale);
4141 /* Strip leading and trailing zeroes */
4142 strip_var(result);
4147 * div_var() -
4149 * Division on variable level. Quotient of var1 / var2 is stored in result.
4150 * The quotient is figured to exactly rscale fractional digits.
4151 * If round is true, it is rounded at the rscale'th digit; if false, it
4152 * is truncated (towards zero) at that digit.
4154 static void
4155 div_var(NumericVar *var1, NumericVar *var2, NumericVar *result,
4156 int rscale, bool round)
4158 int div_ndigits;
4159 int res_ndigits;
4160 int res_sign;
4161 int res_weight;
4162 int carry;
4163 int borrow;
4164 int divisor1;
4165 int divisor2;
4166 NumericDigit *dividend;
4167 NumericDigit *divisor;
4168 NumericDigit *res_digits;
4169 int i;
4170 int j;
4172 /* copy these values into local vars for speed in inner loop */
4173 int var1ndigits = var1->ndigits;
4174 int var2ndigits = var2->ndigits;
4177 * First of all division by zero check; we must not be handed an
4178 * unnormalized divisor.
4180 if (var2ndigits == 0 || var2->digits[0] == 0)
4181 ereport(ERROR,
4182 (errcode(ERRCODE_DIVISION_BY_ZERO),
4183 errmsg("division by zero")));
4186 * Now result zero check
4188 if (var1ndigits == 0)
4190 zero_var(result);
4191 result->dscale = rscale;
4192 return;
4196 * Determine the result sign, weight and number of digits to calculate.
4197 * The weight figured here is correct if the emitted quotient has no
4198 * leading zero digits; otherwise strip_var() will fix things up.
4200 if (var1->sign == var2->sign)
4201 res_sign = NUMERIC_POS;
4202 else
4203 res_sign = NUMERIC_NEG;
4204 res_weight = var1->weight - var2->weight;
4205 /* The number of accurate result digits we need to produce: */
4206 res_ndigits = res_weight + 1 + (rscale + DEC_DIGITS - 1) / DEC_DIGITS;
4207 /* ... but always at least 1 */
4208 res_ndigits = Max(res_ndigits, 1);
4209 /* If rounding needed, figure one more digit to ensure correct result */
4210 if (round)
4211 res_ndigits++;
4213 * The working dividend normally requires res_ndigits + var2ndigits
4214 * digits, but make it at least var1ndigits so we can load all of var1
4215 * into it. (There will be an additional digit dividend[0] in the
4216 * dividend space, but for consistency with Knuth's notation we don't
4217 * count that in div_ndigits.)
4219 div_ndigits = res_ndigits + var2ndigits;
4220 div_ndigits = Max(div_ndigits, var1ndigits);
4223 * We need a workspace with room for the working dividend (div_ndigits+1
4224 * digits) plus room for the possibly-normalized divisor (var2ndigits
4225 * digits). It is convenient also to have a zero at divisor[0] with
4226 * the actual divisor data in divisor[1 .. var2ndigits]. Transferring the
4227 * digits into the workspace also allows us to realloc the result (which
4228 * might be the same as either input var) before we begin the main loop.
4229 * Note that we use palloc0 to ensure that divisor[0], dividend[0], and
4230 * any additional dividend positions beyond var1ndigits, start out 0.
4232 dividend = (NumericDigit *)
4233 palloc0((div_ndigits + var2ndigits + 2) * sizeof(NumericDigit));
4234 divisor = dividend + (div_ndigits + 1);
4235 memcpy(dividend + 1, var1->digits, var1ndigits * sizeof(NumericDigit));
4236 memcpy(divisor + 1, var2->digits, var2ndigits * sizeof(NumericDigit));
4239 * Now we can realloc the result to hold the generated quotient digits.
4241 alloc_var(result, res_ndigits);
4242 res_digits = result->digits;
4244 if (var2ndigits == 1)
4247 * If there's only a single divisor digit, we can use a fast path
4248 * (cf. Knuth section 4.3.1 exercise 16).
4250 divisor1 = divisor[1];
4251 carry = 0;
4252 for (i = 0; i < res_ndigits; i++)
4254 carry = carry * NBASE + dividend[i + 1];
4255 res_digits[i] = carry / divisor1;
4256 carry = carry % divisor1;
4259 else
4262 * The full multiple-place algorithm is taken from Knuth volume 2,
4263 * Algorithm 4.3.1D.
4265 * We need the first divisor digit to be >= NBASE/2. If it isn't,
4266 * make it so by scaling up both the divisor and dividend by the
4267 * factor "d". (The reason for allocating dividend[0] above is to
4268 * leave room for possible carry here.)
4270 if (divisor[1] < HALF_NBASE)
4272 int d = NBASE / (divisor[1] + 1);
4274 carry = 0;
4275 for (i = var2ndigits; i > 0; i--)
4277 carry += divisor[i] * d;
4278 divisor[i] = carry % NBASE;
4279 carry = carry / NBASE;
4281 Assert(carry == 0);
4282 carry = 0;
4283 /* at this point only var1ndigits of dividend can be nonzero */
4284 for (i = var1ndigits; i >= 0; i--)
4286 carry += dividend[i] * d;
4287 dividend[i] = carry % NBASE;
4288 carry = carry / NBASE;
4290 Assert(carry == 0);
4291 Assert(divisor[1] >= HALF_NBASE);
4293 /* First 2 divisor digits are used repeatedly in main loop */
4294 divisor1 = divisor[1];
4295 divisor2 = divisor[2];
4298 * Begin the main loop. Each iteration of this loop produces the
4299 * j'th quotient digit by dividing dividend[j .. j + var2ndigits]
4300 * by the divisor; this is essentially the same as the common manual
4301 * procedure for long division.
4303 for (j = 0; j < res_ndigits; j++)
4305 /* Estimate quotient digit from the first two dividend digits */
4306 int next2digits = dividend[j] * NBASE + dividend[j+1];
4307 int qhat;
4310 * If next2digits are 0, then quotient digit must be 0 and there's
4311 * no need to adjust the working dividend. It's worth testing
4312 * here to fall out ASAP when processing trailing zeroes in
4313 * a dividend.
4315 if (next2digits == 0)
4317 res_digits[j] = 0;
4318 continue;
4321 if (dividend[j] == divisor1)
4322 qhat = NBASE - 1;
4323 else
4324 qhat = next2digits / divisor1;
4326 * Adjust quotient digit if it's too large. Knuth proves that
4327 * after this step, the quotient digit will be either correct
4328 * or just one too large. (Note: it's OK to use dividend[j+2]
4329 * here because we know the divisor length is at least 2.)
4331 while (divisor2 * qhat >
4332 (next2digits - qhat * divisor1) * NBASE + dividend[j+2])
4333 qhat--;
4335 /* As above, need do nothing more when quotient digit is 0 */
4336 if (qhat > 0)
4339 * Multiply the divisor by qhat, and subtract that from the
4340 * working dividend. "carry" tracks the multiplication,
4341 * "borrow" the subtraction (could we fold these together?)
4343 carry = 0;
4344 borrow = 0;
4345 for (i = var2ndigits; i >= 0; i--)
4347 carry += divisor[i] * qhat;
4348 borrow -= carry % NBASE;
4349 carry = carry / NBASE;
4350 borrow += dividend[j + i];
4351 if (borrow < 0)
4353 dividend[j + i] = borrow + NBASE;
4354 borrow = -1;
4356 else
4358 dividend[j + i] = borrow;
4359 borrow = 0;
4362 Assert(carry == 0);
4365 * If we got a borrow out of the top dividend digit, then
4366 * indeed qhat was one too large. Fix it, and add back the
4367 * divisor to correct the working dividend. (Knuth proves
4368 * that this will occur only about 3/NBASE of the time; hence,
4369 * it's a good idea to test this code with small NBASE to be
4370 * sure this section gets exercised.)
4372 if (borrow)
4374 qhat--;
4375 carry = 0;
4376 for (i = var2ndigits; i >= 0; i--)
4378 carry += dividend[j + i] + divisor[i];
4379 if (carry >= NBASE)
4381 dividend[j + i] = carry - NBASE;
4382 carry = 1;
4384 else
4386 dividend[j + i] = carry;
4387 carry = 0;
4390 /* A carry should occur here to cancel the borrow above */
4391 Assert(carry == 1);
4395 /* And we're done with this quotient digit */
4396 res_digits[j] = qhat;
4400 pfree(dividend);
4403 * Finally, round or truncate the result to the requested precision.
4405 result->weight = res_weight;
4406 result->sign = res_sign;
4408 /* Round or truncate to target rscale (and set result->dscale) */
4409 if (round)
4410 round_var(result, rscale);
4411 else
4412 trunc_var(result, rscale);
4414 /* Strip leading and trailing zeroes */
4415 strip_var(result);
4420 * div_var_fast() -
4422 * This has the same API as div_var, but is implemented using the division
4423 * algorithm from the "FM" library, rather than Knuth's schoolbook-division
4424 * approach. This is significantly faster but can produce inaccurate
4425 * results, because it sometimes has to propagate rounding to the left,
4426 * and so we can never be entirely sure that we know the requested digits
4427 * exactly. We compute DIV_GUARD_DIGITS extra digits, but there is
4428 * no certainty that that's enough. We use this only in the transcendental
4429 * function calculation routines, where everything is approximate anyway.
4431 static void
4432 div_var_fast(NumericVar *var1, NumericVar *var2, NumericVar *result,
4433 int rscale, bool round)
4435 int div_ndigits;
4436 int res_sign;
4437 int res_weight;
4438 int *div;
4439 int qdigit;
4440 int carry;
4441 int maxdiv;
4442 int newdig;
4443 NumericDigit *res_digits;
4444 double fdividend,
4445 fdivisor,
4446 fdivisorinverse,
4447 fquotient;
4448 int qi;
4449 int i;
4451 /* copy these values into local vars for speed in inner loop */
4452 int var1ndigits = var1->ndigits;
4453 int var2ndigits = var2->ndigits;
4454 NumericDigit *var1digits = var1->digits;
4455 NumericDigit *var2digits = var2->digits;
4458 * First of all division by zero check; we must not be handed an
4459 * unnormalized divisor.
4461 if (var2ndigits == 0 || var2digits[0] == 0)
4462 ereport(ERROR,
4463 (errcode(ERRCODE_DIVISION_BY_ZERO),
4464 errmsg("division by zero")));
4467 * Now result zero check
4469 if (var1ndigits == 0)
4471 zero_var(result);
4472 result->dscale = rscale;
4473 return;
4477 * Determine the result sign, weight and number of digits to calculate
4479 if (var1->sign == var2->sign)
4480 res_sign = NUMERIC_POS;
4481 else
4482 res_sign = NUMERIC_NEG;
4483 res_weight = var1->weight - var2->weight + 1;
4484 /* The number of accurate result digits we need to produce: */
4485 div_ndigits = res_weight + 1 + (rscale + DEC_DIGITS - 1) / DEC_DIGITS;
4486 /* Add guard digits for roundoff error */
4487 div_ndigits += DIV_GUARD_DIGITS;
4488 if (div_ndigits < DIV_GUARD_DIGITS)
4489 div_ndigits = DIV_GUARD_DIGITS;
4490 /* Must be at least var1ndigits, too, to simplify data-loading loop */
4491 if (div_ndigits < var1ndigits)
4492 div_ndigits = var1ndigits;
4495 * We do the arithmetic in an array "div[]" of signed int's. Since
4496 * INT_MAX is noticeably larger than NBASE*NBASE, this gives us headroom
4497 * to avoid normalizing carries immediately.
4499 * We start with div[] containing one zero digit followed by the
4500 * dividend's digits (plus appended zeroes to reach the desired precision
4501 * including guard digits). Each step of the main loop computes an
4502 * (approximate) quotient digit and stores it into div[], removing one
4503 * position of dividend space. A final pass of carry propagation takes
4504 * care of any mistaken quotient digits.
4506 div = (int *) palloc0((div_ndigits + 1) * sizeof(int));
4507 for (i = 0; i < var1ndigits; i++)
4508 div[i + 1] = var1digits[i];
4511 * We estimate each quotient digit using floating-point arithmetic, taking
4512 * the first four digits of the (current) dividend and divisor. This must
4513 * be float to avoid overflow.
4515 fdivisor = (double) var2digits[0];
4516 for (i = 1; i < 4; i++)
4518 fdivisor *= NBASE;
4519 if (i < var2ndigits)
4520 fdivisor += (double) var2digits[i];
4522 fdivisorinverse = 1.0 / fdivisor;
4525 * maxdiv tracks the maximum possible absolute value of any div[] entry;
4526 * when this threatens to exceed INT_MAX, we take the time to propagate
4527 * carries. To avoid overflow in maxdiv itself, it actually represents
4528 * the max possible abs. value divided by NBASE-1.
4530 maxdiv = 1;
4533 * Outer loop computes next quotient digit, which will go into div[qi]
4535 for (qi = 0; qi < div_ndigits; qi++)
4537 /* Approximate the current dividend value */
4538 fdividend = (double) div[qi];
4539 for (i = 1; i < 4; i++)
4541 fdividend *= NBASE;
4542 if (qi + i <= div_ndigits)
4543 fdividend += (double) div[qi + i];
4545 /* Compute the (approximate) quotient digit */
4546 fquotient = fdividend * fdivisorinverse;
4547 qdigit = (fquotient >= 0.0) ? ((int) fquotient) :
4548 (((int) fquotient) - 1); /* truncate towards -infinity */
4550 if (qdigit != 0)
4552 /* Do we need to normalize now? */
4553 maxdiv += Abs(qdigit);
4554 if (maxdiv > INT_MAX / (NBASE - 1))
4556 /* Yes, do it */
4557 carry = 0;
4558 for (i = div_ndigits; i > qi; i--)
4560 newdig = div[i] + carry;
4561 if (newdig < 0)
4563 carry = -((-newdig - 1) / NBASE) - 1;
4564 newdig -= carry * NBASE;
4566 else if (newdig >= NBASE)
4568 carry = newdig / NBASE;
4569 newdig -= carry * NBASE;
4571 else
4572 carry = 0;
4573 div[i] = newdig;
4575 newdig = div[qi] + carry;
4576 div[qi] = newdig;
4579 * All the div[] digits except possibly div[qi] are now in the
4580 * range 0..NBASE-1.
4582 maxdiv = Abs(newdig) / (NBASE - 1);
4583 maxdiv = Max(maxdiv, 1);
4586 * Recompute the quotient digit since new info may have
4587 * propagated into the top four dividend digits
4589 fdividend = (double) div[qi];
4590 for (i = 1; i < 4; i++)
4592 fdividend *= NBASE;
4593 if (qi + i <= div_ndigits)
4594 fdividend += (double) div[qi + i];
4596 /* Compute the (approximate) quotient digit */
4597 fquotient = fdividend * fdivisorinverse;
4598 qdigit = (fquotient >= 0.0) ? ((int) fquotient) :
4599 (((int) fquotient) - 1); /* truncate towards -infinity */
4600 maxdiv += Abs(qdigit);
4603 /* Subtract off the appropriate multiple of the divisor */
4604 if (qdigit != 0)
4606 int istop = Min(var2ndigits, div_ndigits - qi + 1);
4608 for (i = 0; i < istop; i++)
4609 div[qi + i] -= qdigit * var2digits[i];
4614 * The dividend digit we are about to replace might still be nonzero.
4615 * Fold it into the next digit position. We don't need to worry about
4616 * overflow here since this should nearly cancel with the subtraction
4617 * of the divisor.
4619 div[qi + 1] += div[qi] * NBASE;
4621 div[qi] = qdigit;
4625 * Approximate and store the last quotient digit (div[div_ndigits])
4627 fdividend = (double) div[qi];
4628 for (i = 1; i < 4; i++)
4629 fdividend *= NBASE;
4630 fquotient = fdividend * fdivisorinverse;
4631 qdigit = (fquotient >= 0.0) ? ((int) fquotient) :
4632 (((int) fquotient) - 1); /* truncate towards -infinity */
4633 div[qi] = qdigit;
4636 * Now we do a final carry propagation pass to normalize the result, which
4637 * we combine with storing the result digits into the output. Note that
4638 * this is still done at full precision w/guard digits.
4640 alloc_var(result, div_ndigits + 1);
4641 res_digits = result->digits;
4642 carry = 0;
4643 for (i = div_ndigits; i >= 0; i--)
4645 newdig = div[i] + carry;
4646 if (newdig < 0)
4648 carry = -((-newdig - 1) / NBASE) - 1;
4649 newdig -= carry * NBASE;
4651 else if (newdig >= NBASE)
4653 carry = newdig / NBASE;
4654 newdig -= carry * NBASE;
4656 else
4657 carry = 0;
4658 res_digits[i] = newdig;
4660 Assert(carry == 0);
4662 pfree(div);
4665 * Finally, round the result to the requested precision.
4667 result->weight = res_weight;
4668 result->sign = res_sign;
4670 /* Round to target rscale (and set result->dscale) */
4671 if (round)
4672 round_var(result, rscale);
4673 else
4674 trunc_var(result, rscale);
4676 /* Strip leading and trailing zeroes */
4677 strip_var(result);
4682 * Default scale selection for division
4684 * Returns the appropriate result scale for the division result.
4686 static int
4687 select_div_scale(NumericVar *var1, NumericVar *var2)
4689 int weight1,
4690 weight2,
4691 qweight,
4693 NumericDigit firstdigit1,
4694 firstdigit2;
4695 int rscale;
4698 * The result scale of a division isn't specified in any SQL standard. For
4699 * PostgreSQL we select a result scale that will give at least
4700 * NUMERIC_MIN_SIG_DIGITS significant digits, so that numeric gives a
4701 * result no less accurate than float8; but use a scale not less than
4702 * either input's display scale.
4705 /* Get the actual (normalized) weight and first digit of each input */
4707 weight1 = 0; /* values to use if var1 is zero */
4708 firstdigit1 = 0;
4709 for (i = 0; i < var1->ndigits; i++)
4711 firstdigit1 = var1->digits[i];
4712 if (firstdigit1 != 0)
4714 weight1 = var1->weight - i;
4715 break;
4719 weight2 = 0; /* values to use if var2 is zero */
4720 firstdigit2 = 0;
4721 for (i = 0; i < var2->ndigits; i++)
4723 firstdigit2 = var2->digits[i];
4724 if (firstdigit2 != 0)
4726 weight2 = var2->weight - i;
4727 break;
4732 * Estimate weight of quotient. If the two first digits are equal, we
4733 * can't be sure, but assume that var1 is less than var2.
4735 qweight = weight1 - weight2;
4736 if (firstdigit1 <= firstdigit2)
4737 qweight--;
4739 /* Select result scale */
4740 rscale = NUMERIC_MIN_SIG_DIGITS - qweight * DEC_DIGITS;
4741 rscale = Max(rscale, var1->dscale);
4742 rscale = Max(rscale, var2->dscale);
4743 rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
4744 rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
4746 return rscale;
4751 * mod_var() -
4753 * Calculate the modulo of two numerics at variable level
4755 static void
4756 mod_var(NumericVar *var1, NumericVar *var2, NumericVar *result)
4758 NumericVar tmp;
4760 init_var(&tmp);
4762 /* ---------
4763 * We do this using the equation
4764 * mod(x,y) = x - trunc(x/y)*y
4765 * div_var can be persuaded to give us trunc(x/y) directly.
4766 * ----------
4768 div_var(var1, var2, &tmp, 0, false);
4770 mul_var(var2, &tmp, &tmp, var2->dscale);
4772 sub_var(var1, &tmp, result);
4774 free_var(&tmp);
4779 * ceil_var() -
4781 * Return the smallest integer greater than or equal to the argument
4782 * on variable level
4784 static void
4785 ceil_var(NumericVar *var, NumericVar *result)
4787 NumericVar tmp;
4789 init_var(&tmp);
4790 set_var_from_var(var, &tmp);
4792 trunc_var(&tmp, 0);
4794 if (var->sign == NUMERIC_POS && cmp_var(var, &tmp) != 0)
4795 add_var(&tmp, &const_one, &tmp);
4797 set_var_from_var(&tmp, result);
4798 free_var(&tmp);
4803 * floor_var() -
4805 * Return the largest integer equal to or less than the argument
4806 * on variable level
4808 static void
4809 floor_var(NumericVar *var, NumericVar *result)
4811 NumericVar tmp;
4813 init_var(&tmp);
4814 set_var_from_var(var, &tmp);
4816 trunc_var(&tmp, 0);
4818 if (var->sign == NUMERIC_NEG && cmp_var(var, &tmp) != 0)
4819 sub_var(&tmp, &const_one, &tmp);
4821 set_var_from_var(&tmp, result);
4822 free_var(&tmp);
4827 * sqrt_var() -
4829 * Compute the square root of x using Newton's algorithm
4831 static void
4832 sqrt_var(NumericVar *arg, NumericVar *result, int rscale)
4834 NumericVar tmp_arg;
4835 NumericVar tmp_val;
4836 NumericVar last_val;
4837 int local_rscale;
4838 int stat;
4840 local_rscale = rscale + 8;
4842 stat = cmp_var(arg, &const_zero);
4843 if (stat == 0)
4845 zero_var(result);
4846 result->dscale = rscale;
4847 return;
4851 * SQL2003 defines sqrt() in terms of power, so we need to emit the right
4852 * SQLSTATE error code if the operand is negative.
4854 if (stat < 0)
4855 ereport(ERROR,
4856 (errcode(ERRCODE_INVALID_ARGUMENT_FOR_POWER_FUNCTION),
4857 errmsg("cannot take square root of a negative number")));
4859 init_var(&tmp_arg);
4860 init_var(&tmp_val);
4861 init_var(&last_val);
4863 /* Copy arg in case it is the same var as result */
4864 set_var_from_var(arg, &tmp_arg);
4867 * Initialize the result to the first guess
4869 alloc_var(result, 1);
4870 result->digits[0] = tmp_arg.digits[0] / 2;
4871 if (result->digits[0] == 0)
4872 result->digits[0] = 1;
4873 result->weight = tmp_arg.weight / 2;
4874 result->sign = NUMERIC_POS;
4876 set_var_from_var(result, &last_val);
4878 for (;;)
4880 div_var_fast(&tmp_arg, result, &tmp_val, local_rscale, true);
4882 add_var(result, &tmp_val, result);
4883 mul_var(result, &const_zero_point_five, result, local_rscale);
4885 if (cmp_var(&last_val, result) == 0)
4886 break;
4887 set_var_from_var(result, &last_val);
4890 free_var(&last_val);
4891 free_var(&tmp_val);
4892 free_var(&tmp_arg);
4894 /* Round to requested precision */
4895 round_var(result, rscale);
4900 * exp_var() -
4902 * Raise e to the power of x
4904 static void
4905 exp_var(NumericVar *arg, NumericVar *result, int rscale)
4907 NumericVar x;
4908 int xintval;
4909 bool xneg = FALSE;
4910 int local_rscale;
4912 /*----------
4913 * We separate the integral and fraction parts of x, then compute
4914 * e^x = e^xint * e^xfrac
4915 * where e = exp(1) and e^xfrac = exp(xfrac) are computed by
4916 * exp_var_internal; the limited range of inputs allows that routine
4917 * to do a good job with a simple Taylor series. Raising e^xint is
4918 * done by repeated multiplications in power_var_int.
4919 *----------
4921 init_var(&x);
4923 set_var_from_var(arg, &x);
4925 if (x.sign == NUMERIC_NEG)
4927 xneg = TRUE;
4928 x.sign = NUMERIC_POS;
4931 /* Extract the integer part, remove it from x */
4932 xintval = 0;
4933 while (x.weight >= 0)
4935 xintval *= NBASE;
4936 if (x.ndigits > 0)
4938 xintval += x.digits[0];
4939 x.digits++;
4940 x.ndigits--;
4942 x.weight--;
4943 /* Guard against overflow */
4944 if (xintval >= NUMERIC_MAX_RESULT_SCALE * 3)
4945 ereport(ERROR,
4946 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
4947 errmsg("argument for function \"exp\" too big")));
4950 /* Select an appropriate scale for internal calculation */
4951 local_rscale = rscale + MUL_GUARD_DIGITS * 2;
4953 /* Compute e^xfrac */
4954 exp_var_internal(&x, result, local_rscale);
4956 /* If there's an integer part, multiply by e^xint */
4957 if (xintval > 0)
4959 NumericVar e;
4961 init_var(&e);
4962 exp_var_internal(&const_one, &e, local_rscale);
4963 power_var_int(&e, xintval, &e, local_rscale);
4964 mul_var(&e, result, result, local_rscale);
4965 free_var(&e);
4968 /* Compensate for input sign, and round to requested rscale */
4969 if (xneg)
4970 div_var_fast(&const_one, result, result, rscale, true);
4971 else
4972 round_var(result, rscale);
4974 free_var(&x);
4979 * exp_var_internal() -
4981 * Raise e to the power of x, where 0 <= x <= 1
4983 * NB: the result should be good to at least rscale digits, but it has
4984 * *not* been rounded off; the caller must do that if wanted.
4986 static void
4987 exp_var_internal(NumericVar *arg, NumericVar *result, int rscale)
4989 NumericVar x;
4990 NumericVar xpow;
4991 NumericVar ifac;
4992 NumericVar elem;
4993 NumericVar ni;
4994 int ndiv2 = 0;
4995 int local_rscale;
4997 init_var(&x);
4998 init_var(&xpow);
4999 init_var(&ifac);
5000 init_var(&elem);
5001 init_var(&ni);
5003 set_var_from_var(arg, &x);
5005 Assert(x.sign == NUMERIC_POS);
5007 local_rscale = rscale + 8;
5009 /* Reduce input into range 0 <= x <= 0.01 */
5010 while (cmp_var(&x, &const_zero_point_01) > 0)
5012 ndiv2++;
5013 local_rscale++;
5014 mul_var(&x, &const_zero_point_five, &x, x.dscale + 1);
5018 * Use the Taylor series
5020 * exp(x) = 1 + x + x^2/2! + x^3/3! + ...
5022 * Given the limited range of x, this should converge reasonably quickly.
5023 * We run the series until the terms fall below the local_rscale limit.
5025 add_var(&const_one, &x, result);
5026 set_var_from_var(&x, &xpow);
5027 set_var_from_var(&const_one, &ifac);
5028 set_var_from_var(&const_one, &ni);
5030 for (;;)
5032 add_var(&ni, &const_one, &ni);
5033 mul_var(&xpow, &x, &xpow, local_rscale);
5034 mul_var(&ifac, &ni, &ifac, 0);
5035 div_var_fast(&xpow, &ifac, &elem, local_rscale, true);
5037 if (elem.ndigits == 0)
5038 break;
5040 add_var(result, &elem, result);
5043 /* Compensate for argument range reduction */
5044 while (ndiv2-- > 0)
5045 mul_var(result, result, result, local_rscale);
5047 free_var(&x);
5048 free_var(&xpow);
5049 free_var(&ifac);
5050 free_var(&elem);
5051 free_var(&ni);
5056 * ln_var() -
5058 * Compute the natural log of x
5060 static void
5061 ln_var(NumericVar *arg, NumericVar *result, int rscale)
5063 NumericVar x;
5064 NumericVar xx;
5065 NumericVar ni;
5066 NumericVar elem;
5067 NumericVar fact;
5068 int local_rscale;
5069 int cmp;
5071 cmp = cmp_var(arg, &const_zero);
5072 if (cmp == 0)
5073 ereport(ERROR,
5074 (errcode(ERRCODE_INVALID_ARGUMENT_FOR_LOG),
5075 errmsg("cannot take logarithm of zero")));
5076 else if (cmp < 0)
5077 ereport(ERROR,
5078 (errcode(ERRCODE_INVALID_ARGUMENT_FOR_LOG),
5079 errmsg("cannot take logarithm of a negative number")));
5081 local_rscale = rscale + 8;
5083 init_var(&x);
5084 init_var(&xx);
5085 init_var(&ni);
5086 init_var(&elem);
5087 init_var(&fact);
5089 set_var_from_var(arg, &x);
5090 set_var_from_var(&const_two, &fact);
5092 /* Reduce input into range 0.9 < x < 1.1 */
5093 while (cmp_var(&x, &const_zero_point_nine) <= 0)
5095 local_rscale++;
5096 sqrt_var(&x, &x, local_rscale);
5097 mul_var(&fact, &const_two, &fact, 0);
5099 while (cmp_var(&x, &const_one_point_one) >= 0)
5101 local_rscale++;
5102 sqrt_var(&x, &x, local_rscale);
5103 mul_var(&fact, &const_two, &fact, 0);
5107 * We use the Taylor series for 0.5 * ln((1+z)/(1-z)),
5109 * z + z^3/3 + z^5/5 + ...
5111 * where z = (x-1)/(x+1) is in the range (approximately) -0.053 .. 0.048
5112 * due to the above range-reduction of x.
5114 * The convergence of this is not as fast as one would like, but is
5115 * tolerable given that z is small.
5117 sub_var(&x, &const_one, result);
5118 add_var(&x, &const_one, &elem);
5119 div_var_fast(result, &elem, result, local_rscale, true);
5120 set_var_from_var(result, &xx);
5121 mul_var(result, result, &x, local_rscale);
5123 set_var_from_var(&const_one, &ni);
5125 for (;;)
5127 add_var(&ni, &const_two, &ni);
5128 mul_var(&xx, &x, &xx, local_rscale);
5129 div_var_fast(&xx, &ni, &elem, local_rscale, true);
5131 if (elem.ndigits == 0)
5132 break;
5134 add_var(result, &elem, result);
5136 if (elem.weight < (result->weight - local_rscale * 2 / DEC_DIGITS))
5137 break;
5140 /* Compensate for argument range reduction, round to requested rscale */
5141 mul_var(result, &fact, result, rscale);
5143 free_var(&x);
5144 free_var(&xx);
5145 free_var(&ni);
5146 free_var(&elem);
5147 free_var(&fact);
5152 * log_var() -
5154 * Compute the logarithm of num in a given base.
5156 * Note: this routine chooses dscale of the result.
5158 static void
5159 log_var(NumericVar *base, NumericVar *num, NumericVar *result)
5161 NumericVar ln_base;
5162 NumericVar ln_num;
5163 int dec_digits;
5164 int rscale;
5165 int local_rscale;
5167 init_var(&ln_base);
5168 init_var(&ln_num);
5170 /* Set scale for ln() calculations --- compare numeric_ln() */
5172 /* Approx decimal digits before decimal point */
5173 dec_digits = (num->weight + 1) * DEC_DIGITS;
5175 if (dec_digits > 1)
5176 rscale = NUMERIC_MIN_SIG_DIGITS - (int) log10(dec_digits - 1);
5177 else if (dec_digits < 1)
5178 rscale = NUMERIC_MIN_SIG_DIGITS - (int) log10(1 - dec_digits);
5179 else
5180 rscale = NUMERIC_MIN_SIG_DIGITS;
5182 rscale = Max(rscale, base->dscale);
5183 rscale = Max(rscale, num->dscale);
5184 rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
5185 rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
5187 local_rscale = rscale + 8;
5189 /* Form natural logarithms */
5190 ln_var(base, &ln_base, local_rscale);
5191 ln_var(num, &ln_num, local_rscale);
5193 ln_base.dscale = rscale;
5194 ln_num.dscale = rscale;
5196 /* Select scale for division result */
5197 rscale = select_div_scale(&ln_num, &ln_base);
5199 div_var_fast(&ln_num, &ln_base, result, rscale, true);
5201 free_var(&ln_num);
5202 free_var(&ln_base);
5207 * power_var() -
5209 * Raise base to the power of exp
5211 * Note: this routine chooses dscale of the result.
5213 static void
5214 power_var(NumericVar *base, NumericVar *exp, NumericVar *result)
5216 NumericVar ln_base;
5217 NumericVar ln_num;
5218 int dec_digits;
5219 int rscale;
5220 int local_rscale;
5221 double val;
5223 /* If exp can be represented as an integer, use power_var_int */
5224 if (exp->ndigits == 0 || exp->ndigits <= exp->weight + 1)
5226 /* exact integer, but does it fit in int? */
5227 NumericVar x;
5228 int64 expval64;
5230 /* must copy because numericvar_to_int8() scribbles on input */
5231 init_var(&x);
5232 set_var_from_var(exp, &x);
5233 if (numericvar_to_int8(&x, &expval64))
5235 int expval = (int) expval64;
5237 /* Test for overflow by reverse-conversion. */
5238 if ((int64) expval == expval64)
5240 /* Okay, select rscale */
5241 rscale = NUMERIC_MIN_SIG_DIGITS;
5242 rscale = Max(rscale, base->dscale);
5243 rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
5244 rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
5246 power_var_int(base, expval, result, rscale);
5248 free_var(&x);
5249 return;
5252 free_var(&x);
5256 * This avoids log(0) for cases of 0 raised to a non-integer.
5257 * 0 ^ 0 handled by power_var_int().
5259 if (cmp_var(base, &const_zero) == 0)
5261 set_var_from_var(&const_zero, result);
5262 result->dscale = NUMERIC_MIN_SIG_DIGITS; /* no need to round */
5263 return;
5266 init_var(&ln_base);
5267 init_var(&ln_num);
5269 /* Set scale for ln() calculation --- need extra accuracy here */
5271 /* Approx decimal digits before decimal point */
5272 dec_digits = (base->weight + 1) * DEC_DIGITS;
5274 if (dec_digits > 1)
5275 rscale = NUMERIC_MIN_SIG_DIGITS * 2 - (int) log10(dec_digits - 1);
5276 else if (dec_digits < 1)
5277 rscale = NUMERIC_MIN_SIG_DIGITS * 2 - (int) log10(1 - dec_digits);
5278 else
5279 rscale = NUMERIC_MIN_SIG_DIGITS * 2;
5281 rscale = Max(rscale, base->dscale * 2);
5282 rscale = Max(rscale, exp->dscale * 2);
5283 rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE * 2);
5284 rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE * 2);
5286 local_rscale = rscale + 8;
5288 ln_var(base, &ln_base, local_rscale);
5290 mul_var(&ln_base, exp, &ln_num, local_rscale);
5292 /* Set scale for exp() -- compare numeric_exp() */
5294 /* convert input to float8, ignoring overflow */
5295 val = numericvar_to_double_no_overflow(&ln_num);
5298 * log10(result) = num * log10(e), so this is approximately the weight:
5300 val *= 0.434294481903252;
5302 /* limit to something that won't cause integer overflow */
5303 val = Max(val, -NUMERIC_MAX_RESULT_SCALE);
5304 val = Min(val, NUMERIC_MAX_RESULT_SCALE);
5306 rscale = NUMERIC_MIN_SIG_DIGITS - (int) val;
5307 rscale = Max(rscale, base->dscale);
5308 rscale = Max(rscale, exp->dscale);
5309 rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
5310 rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
5312 exp_var(&ln_num, result, rscale);
5314 free_var(&ln_num);
5315 free_var(&ln_base);
5319 * power_var_int() -
5321 * Raise base to the power of exp, where exp is an integer.
5323 static void
5324 power_var_int(NumericVar *base, int exp, NumericVar *result, int rscale)
5326 bool neg;
5327 NumericVar base_prod;
5328 int local_rscale;
5330 switch (exp)
5332 case 0:
5334 * While 0 ^ 0 can be either 1 or indeterminate (error), we
5335 * treat it as 1 because most programming languages do this.
5336 * SQL:2003 also requires a return value of 1.
5337 * http://en.wikipedia.org/wiki/Exponentiation#Zero_to_the_zero_power
5339 set_var_from_var(&const_one, result);
5340 result->dscale = rscale; /* no need to round */
5341 return;
5342 case 1:
5343 set_var_from_var(base, result);
5344 round_var(result, rscale);
5345 return;
5346 case -1:
5347 div_var(&const_one, base, result, rscale, true);
5348 return;
5349 case 2:
5350 mul_var(base, base, result, rscale);
5351 return;
5352 default:
5353 break;
5357 * The general case repeatedly multiplies base according to the bit
5358 * pattern of exp. We do the multiplications with some extra precision.
5360 neg = (exp < 0);
5361 exp = Abs(exp);
5363 local_rscale = rscale + MUL_GUARD_DIGITS * 2;
5365 init_var(&base_prod);
5366 set_var_from_var(base, &base_prod);
5368 if (exp & 1)
5369 set_var_from_var(base, result);
5370 else
5371 set_var_from_var(&const_one, result);
5373 while ((exp >>= 1) > 0)
5375 mul_var(&base_prod, &base_prod, &base_prod, local_rscale);
5376 if (exp & 1)
5377 mul_var(&base_prod, result, result, local_rscale);
5380 free_var(&base_prod);
5382 /* Compensate for input sign, and round to requested rscale */
5383 if (neg)
5384 div_var_fast(&const_one, result, result, rscale, true);
5385 else
5386 round_var(result, rscale);
5390 /* ----------------------------------------------------------------------
5392 * Following are the lowest level functions that operate unsigned
5393 * on the variable level
5395 * ----------------------------------------------------------------------
5399 /* ----------
5400 * cmp_abs() -
5402 * Compare the absolute values of var1 and var2
5403 * Returns: -1 for ABS(var1) < ABS(var2)
5404 * 0 for ABS(var1) == ABS(var2)
5405 * 1 for ABS(var1) > ABS(var2)
5406 * ----------
5408 static int
5409 cmp_abs(NumericVar *var1, NumericVar *var2)
5411 return cmp_abs_common(var1->digits, var1->ndigits, var1->weight,
5412 var2->digits, var2->ndigits, var2->weight);
5415 /* ----------
5416 * cmp_abs_common() -
5418 * Main routine of cmp_abs(). This function can be used by both
5419 * NumericVar and Numeric.
5420 * ----------
5422 static int
5423 cmp_abs_common(const NumericDigit *var1digits, int var1ndigits, int var1weight,
5424 const NumericDigit *var2digits, int var2ndigits, int var2weight)
5426 int i1 = 0;
5427 int i2 = 0;
5429 /* Check any digits before the first common digit */
5431 while (var1weight > var2weight && i1 < var1ndigits)
5433 if (var1digits[i1++] != 0)
5434 return 1;
5435 var1weight--;
5437 while (var2weight > var1weight && i2 < var2ndigits)
5439 if (var2digits[i2++] != 0)
5440 return -1;
5441 var2weight--;
5444 /* At this point, either w1 == w2 or we've run out of digits */
5446 if (var1weight == var2weight)
5448 while (i1 < var1ndigits && i2 < var2ndigits)
5450 int stat = var1digits[i1++] - var2digits[i2++];
5452 if (stat)
5454 if (stat > 0)
5455 return 1;
5456 return -1;
5462 * At this point, we've run out of digits on one side or the other; so any
5463 * remaining nonzero digits imply that side is larger
5465 while (i1 < var1ndigits)
5467 if (var1digits[i1++] != 0)
5468 return 1;
5470 while (i2 < var2ndigits)
5472 if (var2digits[i2++] != 0)
5473 return -1;
5476 return 0;
5481 * add_abs() -
5483 * Add the absolute values of two variables into result.
5484 * result might point to one of the operands without danger.
5486 static void
5487 add_abs(NumericVar *var1, NumericVar *var2, NumericVar *result)
5489 NumericDigit *res_buf;
5490 NumericDigit *res_digits;
5491 int res_ndigits;
5492 int res_weight;
5493 int res_rscale,
5494 rscale1,
5495 rscale2;
5496 int res_dscale;
5497 int i,
5500 int carry = 0;
5502 /* copy these values into local vars for speed in inner loop */
5503 int var1ndigits = var1->ndigits;
5504 int var2ndigits = var2->ndigits;
5505 NumericDigit *var1digits = var1->digits;
5506 NumericDigit *var2digits = var2->digits;
5508 res_weight = Max(var1->weight, var2->weight) + 1;
5510 res_dscale = Max(var1->dscale, var2->dscale);
5512 /* Note: here we are figuring rscale in base-NBASE digits */
5513 rscale1 = var1->ndigits - var1->weight - 1;
5514 rscale2 = var2->ndigits - var2->weight - 1;
5515 res_rscale = Max(rscale1, rscale2);
5517 res_ndigits = res_rscale + res_weight + 1;
5518 if (res_ndigits <= 0)
5519 res_ndigits = 1;
5521 res_buf = digitbuf_alloc(res_ndigits + 1);
5522 res_buf[0] = 0; /* spare digit for later rounding */
5523 res_digits = res_buf + 1;
5525 i1 = res_rscale + var1->weight + 1;
5526 i2 = res_rscale + var2->weight + 1;
5527 for (i = res_ndigits - 1; i >= 0; i--)
5529 i1--;
5530 i2--;
5531 if (i1 >= 0 && i1 < var1ndigits)
5532 carry += var1digits[i1];
5533 if (i2 >= 0 && i2 < var2ndigits)
5534 carry += var2digits[i2];
5536 if (carry >= NBASE)
5538 res_digits[i] = carry - NBASE;
5539 carry = 1;
5541 else
5543 res_digits[i] = carry;
5544 carry = 0;
5548 Assert(carry == 0); /* else we failed to allow for carry out */
5550 digitbuf_free(result->buf);
5551 result->ndigits = res_ndigits;
5552 result->buf = res_buf;
5553 result->digits = res_digits;
5554 result->weight = res_weight;
5555 result->dscale = res_dscale;
5557 /* Remove leading/trailing zeroes */
5558 strip_var(result);
5563 * sub_abs()
5565 * Subtract the absolute value of var2 from the absolute value of var1
5566 * and store in result. result might point to one of the operands
5567 * without danger.
5569 * ABS(var1) MUST BE GREATER OR EQUAL ABS(var2) !!!
5571 static void
5572 sub_abs(NumericVar *var1, NumericVar *var2, NumericVar *result)
5574 NumericDigit *res_buf;
5575 NumericDigit *res_digits;
5576 int res_ndigits;
5577 int res_weight;
5578 int res_rscale,
5579 rscale1,
5580 rscale2;
5581 int res_dscale;
5582 int i,
5585 int borrow = 0;
5587 /* copy these values into local vars for speed in inner loop */
5588 int var1ndigits = var1->ndigits;
5589 int var2ndigits = var2->ndigits;
5590 NumericDigit *var1digits = var1->digits;
5591 NumericDigit *var2digits = var2->digits;
5593 res_weight = var1->weight;
5595 res_dscale = Max(var1->dscale, var2->dscale);
5597 /* Note: here we are figuring rscale in base-NBASE digits */
5598 rscale1 = var1->ndigits - var1->weight - 1;
5599 rscale2 = var2->ndigits - var2->weight - 1;
5600 res_rscale = Max(rscale1, rscale2);
5602 res_ndigits = res_rscale + res_weight + 1;
5603 if (res_ndigits <= 0)
5604 res_ndigits = 1;
5606 res_buf = digitbuf_alloc(res_ndigits + 1);
5607 res_buf[0] = 0; /* spare digit for later rounding */
5608 res_digits = res_buf + 1;
5610 i1 = res_rscale + var1->weight + 1;
5611 i2 = res_rscale + var2->weight + 1;
5612 for (i = res_ndigits - 1; i >= 0; i--)
5614 i1--;
5615 i2--;
5616 if (i1 >= 0 && i1 < var1ndigits)
5617 borrow += var1digits[i1];
5618 if (i2 >= 0 && i2 < var2ndigits)
5619 borrow -= var2digits[i2];
5621 if (borrow < 0)
5623 res_digits[i] = borrow + NBASE;
5624 borrow = -1;
5626 else
5628 res_digits[i] = borrow;
5629 borrow = 0;
5633 Assert(borrow == 0); /* else caller gave us var1 < var2 */
5635 digitbuf_free(result->buf);
5636 result->ndigits = res_ndigits;
5637 result->buf = res_buf;
5638 result->digits = res_digits;
5639 result->weight = res_weight;
5640 result->dscale = res_dscale;
5642 /* Remove leading/trailing zeroes */
5643 strip_var(result);
5647 * round_var
5649 * Round the value of a variable to no more than rscale decimal digits
5650 * after the decimal point. NOTE: we allow rscale < 0 here, implying
5651 * rounding before the decimal point.
5653 static void
5654 round_var(NumericVar *var, int rscale)
5656 NumericDigit *digits = var->digits;
5657 int di;
5658 int ndigits;
5659 int carry;
5661 var->dscale = rscale;
5663 /* decimal digits wanted */
5664 di = (var->weight + 1) * DEC_DIGITS + rscale;
5667 * If di = 0, the value loses all digits, but could round up to 1 if its
5668 * first extra digit is >= 5. If di < 0 the result must be 0.
5670 if (di < 0)
5672 var->ndigits = 0;
5673 var->weight = 0;
5674 var->sign = NUMERIC_POS;
5676 else
5678 /* NBASE digits wanted */
5679 ndigits = (di + DEC_DIGITS - 1) / DEC_DIGITS;
5681 /* 0, or number of decimal digits to keep in last NBASE digit */
5682 di %= DEC_DIGITS;
5684 if (ndigits < var->ndigits ||
5685 (ndigits == var->ndigits && di > 0))
5687 var->ndigits = ndigits;
5689 #if DEC_DIGITS == 1
5690 /* di must be zero */
5691 carry = (digits[ndigits] >= HALF_NBASE) ? 1 : 0;
5692 #else
5693 if (di == 0)
5694 carry = (digits[ndigits] >= HALF_NBASE) ? 1 : 0;
5695 else
5697 /* Must round within last NBASE digit */
5698 int extra,
5699 pow10;
5701 #if DEC_DIGITS == 4
5702 pow10 = round_powers[di];
5703 #elif DEC_DIGITS == 2
5704 pow10 = 10;
5705 #else
5706 #error unsupported NBASE
5707 #endif
5708 extra = digits[--ndigits] % pow10;
5709 digits[ndigits] -= extra;
5710 carry = 0;
5711 if (extra >= pow10 / 2)
5713 pow10 += digits[ndigits];
5714 if (pow10 >= NBASE)
5716 pow10 -= NBASE;
5717 carry = 1;
5719 digits[ndigits] = pow10;
5722 #endif
5724 /* Propagate carry if needed */
5725 while (carry)
5727 carry += digits[--ndigits];
5728 if (carry >= NBASE)
5730 digits[ndigits] = carry - NBASE;
5731 carry = 1;
5733 else
5735 digits[ndigits] = carry;
5736 carry = 0;
5740 if (ndigits < 0)
5742 Assert(ndigits == -1); /* better not have added > 1 digit */
5743 Assert(var->digits > var->buf);
5744 var->digits--;
5745 var->ndigits++;
5746 var->weight++;
5753 * trunc_var
5755 * Truncate (towards zero) the value of a variable at rscale decimal digits
5756 * after the decimal point. NOTE: we allow rscale < 0 here, implying
5757 * truncation before the decimal point.
5759 static void
5760 trunc_var(NumericVar *var, int rscale)
5762 int di;
5763 int ndigits;
5765 var->dscale = rscale;
5767 /* decimal digits wanted */
5768 di = (var->weight + 1) * DEC_DIGITS + rscale;
5771 * If di <= 0, the value loses all digits.
5773 if (di <= 0)
5775 var->ndigits = 0;
5776 var->weight = 0;
5777 var->sign = NUMERIC_POS;
5779 else
5781 /* NBASE digits wanted */
5782 ndigits = (di + DEC_DIGITS - 1) / DEC_DIGITS;
5784 if (ndigits <= var->ndigits)
5786 var->ndigits = ndigits;
5788 #if DEC_DIGITS == 1
5789 /* no within-digit stuff to worry about */
5790 #else
5791 /* 0, or number of decimal digits to keep in last NBASE digit */
5792 di %= DEC_DIGITS;
5794 if (di > 0)
5796 /* Must truncate within last NBASE digit */
5797 NumericDigit *digits = var->digits;
5798 int extra,
5799 pow10;
5801 #if DEC_DIGITS == 4
5802 pow10 = round_powers[di];
5803 #elif DEC_DIGITS == 2
5804 pow10 = 10;
5805 #else
5806 #error unsupported NBASE
5807 #endif
5808 extra = digits[--ndigits] % pow10;
5809 digits[ndigits] -= extra;
5811 #endif
5817 * strip_var
5819 * Strip any leading and trailing zeroes from a numeric variable
5821 static void
5822 strip_var(NumericVar *var)
5824 NumericDigit *digits = var->digits;
5825 int ndigits = var->ndigits;
5827 /* Strip leading zeroes */
5828 while (ndigits > 0 && *digits == 0)
5830 digits++;
5831 var->weight--;
5832 ndigits--;
5835 /* Strip trailing zeroes */
5836 while (ndigits > 0 && digits[ndigits - 1] == 0)
5837 ndigits--;
5839 /* If it's zero, normalize the sign and weight */
5840 if (ndigits == 0)
5842 var->sign = NUMERIC_POS;
5843 var->weight = 0;
5846 var->digits = digits;
5847 var->ndigits = ndigits;