1 /*-------------------------------------------------------------------------
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,
14 * Copyright (c) 1998-2008, PostgreSQL Global Development Group
17 * $PostgreSQL: pgsql/src/backend/utils/adt/numeric.c,v 1.113 2008/05/09 15:36:06 momjian Exp $
19 *-------------------------------------------------------------------------
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"
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().
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.
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;
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;
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;
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
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.
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 */
147 * Some preinitialized constants
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};
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};
169 static NumericVar const_zero_point_five =
170 {1, -1, NUMERIC_POS, 1, NULL, const_zero_point_five_data};
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};
179 static NumericVar const_zero_point_nine =
180 {1, -1, NUMERIC_POS, 1, NULL, const_zero_point_nine_data};
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};
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};
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};
210 static const int round_powers[4] = {0, 1000, 100, 10};
220 static void dump_numeric(const char *str, Numeric num);
221 static void dump_var(const char *str, NumericVar *var);
223 #define dump_numeric(s,n)
224 #define dump_var(s,v)
227 #define digitbuf_alloc(ndigits) \
228 ((NumericDigit *) palloc((ndigits) * sizeof(NumericDigit)))
229 #define digitbuf_free(buf) \
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 void set_var_from_str(const char *str, NumericVar *dest);
246 static void set_var_from_num(Numeric value, NumericVar *dest);
247 static void set_var_from_var(NumericVar *value, NumericVar *dest);
248 static char *get_str_from_var(NumericVar *var, int dscale);
250 static Numeric make_result(NumericVar *var);
252 static void apply_typmod(NumericVar *var, int32 typmod);
254 static int32 numericvar_to_int4(NumericVar *var);
255 static bool numericvar_to_int8(NumericVar *var, int64 *result);
256 static void int8_to_numericvar(int64 val, NumericVar *var);
257 static double numeric_to_double_no_overflow(Numeric num);
258 static double numericvar_to_double_no_overflow(NumericVar *var);
260 static int cmp_numerics(Numeric num1, Numeric num2);
261 static int cmp_var(NumericVar *var1, NumericVar *var2);
262 static int cmp_var_common(const NumericDigit *var1digits, int var1ndigits,
263 int var1weight, int var1sign,
264 const NumericDigit *var2digits, int var2ndigits,
265 int var2weight, int var2sign);
266 static void add_var(NumericVar *var1, NumericVar *var2, NumericVar *result);
267 static void sub_var(NumericVar *var1, NumericVar *var2, NumericVar *result);
268 static void mul_var(NumericVar *var1, NumericVar *var2, NumericVar *result,
270 static void div_var(NumericVar *var1, NumericVar *var2, NumericVar *result,
271 int rscale, bool round);
272 static void div_var_fast(NumericVar *var1, NumericVar *var2, NumericVar *result,
273 int rscale, bool round);
274 static int select_div_scale(NumericVar *var1, NumericVar *var2);
275 static void mod_var(NumericVar *var1, NumericVar *var2, NumericVar *result);
276 static void ceil_var(NumericVar *var, NumericVar *result);
277 static void floor_var(NumericVar *var, NumericVar *result);
279 static void sqrt_var(NumericVar *arg, NumericVar *result, int rscale);
280 static void exp_var(NumericVar *arg, NumericVar *result, int rscale);
281 static void exp_var_internal(NumericVar *arg, NumericVar *result, int rscale);
282 static void ln_var(NumericVar *arg, NumericVar *result, int rscale);
283 static void log_var(NumericVar *base, NumericVar *num, NumericVar *result);
284 static void power_var(NumericVar *base, NumericVar *exp, NumericVar *result);
285 static void power_var_int(NumericVar *base, int exp, NumericVar *result,
288 static int cmp_abs(NumericVar *var1, NumericVar *var2);
289 static int cmp_abs_common(const NumericDigit *var1digits, int var1ndigits,
291 const NumericDigit *var2digits, int var2ndigits,
293 static void add_abs(NumericVar *var1, NumericVar *var2, NumericVar *result);
294 static void sub_abs(NumericVar *var1, NumericVar *var2, NumericVar *result);
295 static void round_var(NumericVar *var, int rscale);
296 static void trunc_var(NumericVar *var, int rscale);
297 static void strip_var(NumericVar *var);
298 static void compute_bucket(Numeric operand, Numeric bound1, Numeric bound2,
299 NumericVar *count_var, NumericVar *result_var);
302 /* ----------------------------------------------------------------------
304 * Input-, output- and rounding-functions
306 * ----------------------------------------------------------------------
313 * Input function for numeric data type
316 numeric_in(PG_FUNCTION_ARGS)
318 char *str = PG_GETARG_CSTRING(0);
321 Oid typelem = PG_GETARG_OID(1);
323 int32 typmod = PG_GETARG_INT32(2);
330 if (pg_strcasecmp(str, "NaN") == 0)
331 PG_RETURN_NUMERIC(make_result(&const_nan));
334 * Use set_var_from_str() to parse the input string and return it in the
335 * packed DB storage format
338 set_var_from_str(str, &value);
340 apply_typmod(&value, typmod);
342 res = make_result(&value);
345 PG_RETURN_NUMERIC(res);
352 * Output function for numeric data type
355 numeric_out(PG_FUNCTION_ARGS)
357 Numeric num = PG_GETARG_NUMERIC(0);
364 if (NUMERIC_IS_NAN(num))
365 PG_RETURN_CSTRING(pstrdup("NaN"));
368 * Get the number in the variable format.
370 * Even if we didn't need to change format, we'd still need to copy the
371 * value to have a modifiable copy for rounding. set_var_from_num() also
372 * guarantees there is extra digit space in case we produce a carry out
376 set_var_from_num(num, &x);
378 str = get_str_from_var(&x, x.dscale);
382 PG_RETURN_CSTRING(str);
386 * numeric_recv - converts external binary format to numeric
388 * External format is a sequence of int16's:
389 * ndigits, weight, sign, dscale, NumericDigits.
392 numeric_recv(PG_FUNCTION_ARGS)
394 StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
397 Oid typelem = PG_GETARG_OID(1);
399 int32 typmod = PG_GETARG_INT32(2);
407 len = (uint16) pq_getmsgint(buf, sizeof(uint16));
408 if (len < 0 || len > NUMERIC_MAX_PRECISION + NUMERIC_MAX_RESULT_SCALE)
410 (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
411 errmsg("invalid length in external \"numeric\" value")));
413 alloc_var(&value, len);
415 value.weight = (int16) pq_getmsgint(buf, sizeof(int16));
416 value.sign = (uint16) pq_getmsgint(buf, sizeof(uint16));
417 if (!(value.sign == NUMERIC_POS ||
418 value.sign == NUMERIC_NEG ||
419 value.sign == NUMERIC_NAN))
421 (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
422 errmsg("invalid sign in external \"numeric\" value")));
424 value.dscale = (uint16) pq_getmsgint(buf, sizeof(uint16));
425 for (i = 0; i < len; i++)
427 NumericDigit d = pq_getmsgint(buf, sizeof(NumericDigit));
429 if (d < 0 || d >= NBASE)
431 (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
432 errmsg("invalid digit in external \"numeric\" value")));
436 apply_typmod(&value, typmod);
438 res = make_result(&value);
441 PG_RETURN_NUMERIC(res);
445 * numeric_send - converts numeric to binary format
448 numeric_send(PG_FUNCTION_ARGS)
450 Numeric num = PG_GETARG_NUMERIC(0);
456 set_var_from_num(num, &x);
458 pq_begintypsend(&buf);
460 pq_sendint(&buf, x.ndigits, sizeof(int16));
461 pq_sendint(&buf, x.weight, sizeof(int16));
462 pq_sendint(&buf, x.sign, sizeof(int16));
463 pq_sendint(&buf, x.dscale, sizeof(int16));
464 for (i = 0; i < x.ndigits; i++)
465 pq_sendint(&buf, x.digits[i], sizeof(NumericDigit));
469 PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
476 * This is a special function called by the Postgres database system
477 * before a value is stored in a tuple's attribute. The precision and
478 * scale of the attribute have to be applied on the value.
481 numeric (PG_FUNCTION_ARGS)
483 Numeric num = PG_GETARG_NUMERIC(0);
484 int32 typmod = PG_GETARG_INT32(1);
496 if (NUMERIC_IS_NAN(num))
497 PG_RETURN_NUMERIC(make_result(&const_nan));
500 * If the value isn't a valid type modifier, simply return a copy of the
503 if (typmod < (int32) (VARHDRSZ))
505 new = (Numeric) palloc(VARSIZE(num));
506 memcpy(new, num, VARSIZE(num));
507 PG_RETURN_NUMERIC(new);
511 * Get the precision and scale out of the typmod value
513 tmp_typmod = typmod - VARHDRSZ;
514 precision = (tmp_typmod >> 16) & 0xffff;
515 scale = tmp_typmod & 0xffff;
516 maxdigits = precision - scale;
519 * If the number is certainly in bounds and due to the target scale no
520 * rounding could be necessary, just make a copy of the input and modify
521 * its scale fields. (Note we assume the existing dscale is honest...)
523 ddigits = (num->n_weight + 1) * DEC_DIGITS;
524 if (ddigits <= maxdigits && scale >= NUMERIC_DSCALE(num))
526 new = (Numeric) palloc(VARSIZE(num));
527 memcpy(new, num, VARSIZE(num));
528 new->n_sign_dscale = NUMERIC_SIGN(new) |
529 ((uint16) scale & NUMERIC_DSCALE_MASK);
530 PG_RETURN_NUMERIC(new);
534 * We really need to fiddle with things - unpack the number into a
535 * variable and let apply_typmod() do it.
539 set_var_from_num(num, &var);
540 apply_typmod(&var, typmod);
541 new = make_result(&var);
545 PG_RETURN_NUMERIC(new);
549 numerictypmodin(PG_FUNCTION_ARGS)
551 ArrayType *ta = PG_GETARG_ARRAYTYPE_P(0);
556 tl = ArrayGetIntegerTypmods(ta, &n);
560 if (tl[0] < 1 || tl[0] > NUMERIC_MAX_PRECISION)
562 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
563 errmsg("NUMERIC precision %d must be between 1 and %d",
564 tl[0], NUMERIC_MAX_PRECISION)));
565 if (tl[1] < 0 || tl[1] > tl[0])
567 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
568 errmsg("NUMERIC scale %d must be between 0 and precision %d",
570 typmod = ((tl[0] << 16) | tl[1]) + VARHDRSZ;
574 if (tl[0] < 1 || tl[0] > NUMERIC_MAX_PRECISION)
576 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
577 errmsg("NUMERIC precision %d must be between 1 and %d",
578 tl[0], NUMERIC_MAX_PRECISION)));
579 /* scale defaults to zero */
580 typmod = (tl[0] << 16) + VARHDRSZ;
585 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
586 errmsg("invalid NUMERIC type modifier")));
587 typmod = 0; /* keep compiler quiet */
590 PG_RETURN_INT32(typmod);
594 numerictypmodout(PG_FUNCTION_ARGS)
596 int32 typmod = PG_GETARG_INT32(0);
597 char *res = (char *) palloc(64);
600 snprintf(res, 64, "(%d,%d)",
601 ((typmod - VARHDRSZ) >> 16) & 0xffff,
602 (typmod - VARHDRSZ) & 0xffff);
606 PG_RETURN_CSTRING(res);
610 /* ----------------------------------------------------------------------
612 * Sign manipulation, rounding and the like
614 * ----------------------------------------------------------------------
618 numeric_abs(PG_FUNCTION_ARGS)
620 Numeric num = PG_GETARG_NUMERIC(0);
626 if (NUMERIC_IS_NAN(num))
627 PG_RETURN_NUMERIC(make_result(&const_nan));
630 * Do it the easy way directly on the packed format
632 res = (Numeric) palloc(VARSIZE(num));
633 memcpy(res, num, VARSIZE(num));
635 res->n_sign_dscale = NUMERIC_POS | NUMERIC_DSCALE(num);
637 PG_RETURN_NUMERIC(res);
642 numeric_uminus(PG_FUNCTION_ARGS)
644 Numeric num = PG_GETARG_NUMERIC(0);
650 if (NUMERIC_IS_NAN(num))
651 PG_RETURN_NUMERIC(make_result(&const_nan));
654 * Do it the easy way directly on the packed format
656 res = (Numeric) palloc(VARSIZE(num));
657 memcpy(res, num, VARSIZE(num));
660 * The packed format is known to be totally zero digit trimmed always. So
661 * we can identify a ZERO by the fact that there are no digits at all. Do
664 if (VARSIZE(num) != NUMERIC_HDRSZ)
666 /* Else, flip the sign */
667 if (NUMERIC_SIGN(num) == NUMERIC_POS)
668 res->n_sign_dscale = NUMERIC_NEG | NUMERIC_DSCALE(num);
670 res->n_sign_dscale = NUMERIC_POS | NUMERIC_DSCALE(num);
673 PG_RETURN_NUMERIC(res);
678 numeric_uplus(PG_FUNCTION_ARGS)
680 Numeric num = PG_GETARG_NUMERIC(0);
683 res = (Numeric) palloc(VARSIZE(num));
684 memcpy(res, num, VARSIZE(num));
686 PG_RETURN_NUMERIC(res);
692 * returns -1 if the argument is less than 0, 0 if the argument is equal
693 * to 0, and 1 if the argument is greater than zero.
696 numeric_sign(PG_FUNCTION_ARGS)
698 Numeric num = PG_GETARG_NUMERIC(0);
705 if (NUMERIC_IS_NAN(num))
706 PG_RETURN_NUMERIC(make_result(&const_nan));
711 * The packed format is known to be totally zero digit trimmed always. So
712 * we can identify a ZERO by the fact that there are no digits at all.
714 if (VARSIZE(num) == NUMERIC_HDRSZ)
715 set_var_from_var(&const_zero, &result);
719 * And if there are some, we return a copy of ONE with the sign of our
722 set_var_from_var(&const_one, &result);
723 result.sign = NUMERIC_SIGN(num);
726 res = make_result(&result);
729 PG_RETURN_NUMERIC(res);
736 * Round a value to have 'scale' digits after the decimal point.
737 * We allow negative 'scale', implying rounding before the decimal
738 * point --- Oracle interprets rounding that way.
741 numeric_round(PG_FUNCTION_ARGS)
743 Numeric num = PG_GETARG_NUMERIC(0);
744 int32 scale = PG_GETARG_INT32(1);
751 if (NUMERIC_IS_NAN(num))
752 PG_RETURN_NUMERIC(make_result(&const_nan));
755 * Limit the scale value to avoid possible overflow in calculations
757 scale = Max(scale, -NUMERIC_MAX_RESULT_SCALE);
758 scale = Min(scale, NUMERIC_MAX_RESULT_SCALE);
761 * Unpack the argument and round it at the proper digit position
764 set_var_from_num(num, &arg);
766 round_var(&arg, scale);
768 /* We don't allow negative output dscale */
773 * Return the rounded result
775 res = make_result(&arg);
778 PG_RETURN_NUMERIC(res);
785 * Truncate a value to have 'scale' digits after the decimal point.
786 * We allow negative 'scale', implying a truncation before the decimal
787 * point --- Oracle interprets truncation that way.
790 numeric_trunc(PG_FUNCTION_ARGS)
792 Numeric num = PG_GETARG_NUMERIC(0);
793 int32 scale = PG_GETARG_INT32(1);
800 if (NUMERIC_IS_NAN(num))
801 PG_RETURN_NUMERIC(make_result(&const_nan));
804 * Limit the scale value to avoid possible overflow in calculations
806 scale = Max(scale, -NUMERIC_MAX_RESULT_SCALE);
807 scale = Min(scale, NUMERIC_MAX_RESULT_SCALE);
810 * Unpack the argument and truncate it at the proper digit position
813 set_var_from_num(num, &arg);
815 trunc_var(&arg, scale);
817 /* We don't allow negative output dscale */
822 * Return the truncated result
824 res = make_result(&arg);
827 PG_RETURN_NUMERIC(res);
834 * Return the smallest integer greater than or equal to the argument
837 numeric_ceil(PG_FUNCTION_ARGS)
839 Numeric num = PG_GETARG_NUMERIC(0);
843 if (NUMERIC_IS_NAN(num))
844 PG_RETURN_NUMERIC(make_result(&const_nan));
848 set_var_from_num(num, &result);
849 ceil_var(&result, &result);
851 res = make_result(&result);
854 PG_RETURN_NUMERIC(res);
861 * Return the largest integer equal to or less than the argument
864 numeric_floor(PG_FUNCTION_ARGS)
866 Numeric num = PG_GETARG_NUMERIC(0);
870 if (NUMERIC_IS_NAN(num))
871 PG_RETURN_NUMERIC(make_result(&const_nan));
875 set_var_from_num(num, &result);
876 floor_var(&result, &result);
878 res = make_result(&result);
881 PG_RETURN_NUMERIC(res);
885 * Implements the numeric version of the width_bucket() function
886 * defined by SQL2003. See also width_bucket_float8().
888 * 'bound1' and 'bound2' are the lower and upper bounds of the
889 * histogram's range, respectively. 'count' is the number of buckets
890 * in the histogram. width_bucket() returns an integer indicating the
891 * bucket number that 'operand' belongs to in an equiwidth histogram
892 * with the specified characteristics. An operand smaller than the
893 * lower bound is assigned to bucket 0. An operand greater than the
894 * upper bound is assigned to an additional bucket (with number
895 * count+1). We don't allow "NaN" for any of the numeric arguments.
898 width_bucket_numeric(PG_FUNCTION_ARGS)
900 Numeric operand = PG_GETARG_NUMERIC(0);
901 Numeric bound1 = PG_GETARG_NUMERIC(1);
902 Numeric bound2 = PG_GETARG_NUMERIC(2);
903 int32 count = PG_GETARG_INT32(3);
904 NumericVar count_var;
905 NumericVar result_var;
910 (errcode(ERRCODE_INVALID_ARGUMENT_FOR_WIDTH_BUCKET_FUNCTION),
911 errmsg("count must be greater than zero")));
913 if (NUMERIC_IS_NAN(operand) ||
914 NUMERIC_IS_NAN(bound1) ||
915 NUMERIC_IS_NAN(bound2))
917 (errcode(ERRCODE_INVALID_ARGUMENT_FOR_WIDTH_BUCKET_FUNCTION),
918 errmsg("operand, lower bound and upper bound cannot be NaN")));
920 init_var(&result_var);
921 init_var(&count_var);
923 /* Convert 'count' to a numeric, for ease of use later */
924 int8_to_numericvar((int64) count, &count_var);
926 switch (cmp_numerics(bound1, bound2))
930 (errcode(ERRCODE_INVALID_ARGUMENT_FOR_WIDTH_BUCKET_FUNCTION),
931 errmsg("lower bound cannot equal upper bound")));
933 /* bound1 < bound2 */
935 if (cmp_numerics(operand, bound1) < 0)
936 set_var_from_var(&const_zero, &result_var);
937 else if (cmp_numerics(operand, bound2) >= 0)
938 add_var(&count_var, &const_one, &result_var);
940 compute_bucket(operand, bound1, bound2,
941 &count_var, &result_var);
944 /* bound1 > bound2 */
946 if (cmp_numerics(operand, bound1) > 0)
947 set_var_from_var(&const_zero, &result_var);
948 else if (cmp_numerics(operand, bound2) <= 0)
949 add_var(&count_var, &const_one, &result_var);
951 compute_bucket(operand, bound1, bound2,
952 &count_var, &result_var);
956 /* if result exceeds the range of a legal int4, we ereport here */
957 result = numericvar_to_int4(&result_var);
959 free_var(&count_var);
960 free_var(&result_var);
962 PG_RETURN_INT32(result);
966 * If 'operand' is not outside the bucket range, determine the correct
967 * bucket for it to go. The calculations performed by this function
968 * are derived directly from the SQL2003 spec.
971 compute_bucket(Numeric operand, Numeric bound1, Numeric bound2,
972 NumericVar *count_var, NumericVar *result_var)
974 NumericVar bound1_var;
975 NumericVar bound2_var;
976 NumericVar operand_var;
978 init_var(&bound1_var);
979 init_var(&bound2_var);
980 init_var(&operand_var);
982 set_var_from_num(bound1, &bound1_var);
983 set_var_from_num(bound2, &bound2_var);
984 set_var_from_num(operand, &operand_var);
986 if (cmp_var(&bound1_var, &bound2_var) < 0)
988 sub_var(&operand_var, &bound1_var, &operand_var);
989 sub_var(&bound2_var, &bound1_var, &bound2_var);
990 div_var(&operand_var, &bound2_var, result_var,
991 select_div_scale(&operand_var, &bound2_var), true);
995 sub_var(&bound1_var, &operand_var, &operand_var);
996 sub_var(&bound1_var, &bound2_var, &bound1_var);
997 div_var(&operand_var, &bound1_var, result_var,
998 select_div_scale(&operand_var, &bound1_var), true);
1001 mul_var(result_var, count_var, result_var,
1002 result_var->dscale + count_var->dscale);
1003 add_var(result_var, &const_one, result_var);
1004 floor_var(result_var, result_var);
1006 free_var(&bound1_var);
1007 free_var(&bound2_var);
1008 free_var(&operand_var);
1011 /* ----------------------------------------------------------------------
1013 * Comparison functions
1015 * Note: btree indexes need these routines not to leak memory; therefore,
1016 * be careful to free working copies of toasted datums. Most places don't
1017 * need to be so careful.
1018 * ----------------------------------------------------------------------
1023 numeric_cmp(PG_FUNCTION_ARGS)
1025 Numeric num1 = PG_GETARG_NUMERIC(0);
1026 Numeric num2 = PG_GETARG_NUMERIC(1);
1029 result = cmp_numerics(num1, num2);
1031 PG_FREE_IF_COPY(num1, 0);
1032 PG_FREE_IF_COPY(num2, 1);
1034 PG_RETURN_INT32(result);
1039 numeric_eq(PG_FUNCTION_ARGS)
1041 Numeric num1 = PG_GETARG_NUMERIC(0);
1042 Numeric num2 = PG_GETARG_NUMERIC(1);
1045 result = cmp_numerics(num1, num2) == 0;
1047 PG_FREE_IF_COPY(num1, 0);
1048 PG_FREE_IF_COPY(num2, 1);
1050 PG_RETURN_BOOL(result);
1054 numeric_ne(PG_FUNCTION_ARGS)
1056 Numeric num1 = PG_GETARG_NUMERIC(0);
1057 Numeric num2 = PG_GETARG_NUMERIC(1);
1060 result = cmp_numerics(num1, num2) != 0;
1062 PG_FREE_IF_COPY(num1, 0);
1063 PG_FREE_IF_COPY(num2, 1);
1065 PG_RETURN_BOOL(result);
1069 numeric_gt(PG_FUNCTION_ARGS)
1071 Numeric num1 = PG_GETARG_NUMERIC(0);
1072 Numeric num2 = PG_GETARG_NUMERIC(1);
1075 result = cmp_numerics(num1, num2) > 0;
1077 PG_FREE_IF_COPY(num1, 0);
1078 PG_FREE_IF_COPY(num2, 1);
1080 PG_RETURN_BOOL(result);
1084 numeric_ge(PG_FUNCTION_ARGS)
1086 Numeric num1 = PG_GETARG_NUMERIC(0);
1087 Numeric num2 = PG_GETARG_NUMERIC(1);
1090 result = cmp_numerics(num1, num2) >= 0;
1092 PG_FREE_IF_COPY(num1, 0);
1093 PG_FREE_IF_COPY(num2, 1);
1095 PG_RETURN_BOOL(result);
1099 numeric_lt(PG_FUNCTION_ARGS)
1101 Numeric num1 = PG_GETARG_NUMERIC(0);
1102 Numeric num2 = PG_GETARG_NUMERIC(1);
1105 result = cmp_numerics(num1, num2) < 0;
1107 PG_FREE_IF_COPY(num1, 0);
1108 PG_FREE_IF_COPY(num2, 1);
1110 PG_RETURN_BOOL(result);
1114 numeric_le(PG_FUNCTION_ARGS)
1116 Numeric num1 = PG_GETARG_NUMERIC(0);
1117 Numeric num2 = PG_GETARG_NUMERIC(1);
1120 result = cmp_numerics(num1, num2) <= 0;
1122 PG_FREE_IF_COPY(num1, 0);
1123 PG_FREE_IF_COPY(num2, 1);
1125 PG_RETURN_BOOL(result);
1129 cmp_numerics(Numeric num1, Numeric num2)
1134 * We consider all NANs to be equal and larger than any non-NAN. This is
1135 * somewhat arbitrary; the important thing is to have a consistent sort
1138 if (NUMERIC_IS_NAN(num1))
1140 if (NUMERIC_IS_NAN(num2))
1141 result = 0; /* NAN = NAN */
1143 result = 1; /* NAN > non-NAN */
1145 else if (NUMERIC_IS_NAN(num2))
1147 result = -1; /* non-NAN < NAN */
1151 result = cmp_var_common(NUMERIC_DIGITS(num1), NUMERIC_NDIGITS(num1),
1152 num1->n_weight, NUMERIC_SIGN(num1),
1153 NUMERIC_DIGITS(num2), NUMERIC_NDIGITS(num2),
1154 num2->n_weight, NUMERIC_SIGN(num2));
1161 hash_numeric(PG_FUNCTION_ARGS)
1163 Numeric key = PG_GETARG_NUMERIC(0);
1172 /* If it's NaN, don't try to hash the rest of the fields */
1173 if (NUMERIC_IS_NAN(key))
1174 PG_RETURN_UINT32(0);
1176 weight = key->n_weight;
1181 * Omit any leading or trailing zeros from the input to the hash. The
1182 * numeric implementation *should* guarantee that leading and trailing
1183 * zeros are suppressed, but we're paranoid. Note that we measure the
1184 * starting and ending offsets in units of NumericDigits, not bytes.
1186 for (i = 0; i < NUMERIC_NDIGITS(key); i++)
1188 if (NUMERIC_DIGITS(key)[i] != (NumericDigit) 0)
1194 * The weight is effectively the # of digits before the decimal point,
1195 * so decrement it for each leading zero we skip.
1201 * If there are no non-zero digits, then the value of the number is zero,
1202 * regardless of any other fields.
1204 if (NUMERIC_NDIGITS(key) == start_offset)
1205 PG_RETURN_UINT32(-1);
1207 for (i = NUMERIC_NDIGITS(key) - 1; i >= 0; i--)
1209 if (NUMERIC_DIGITS(key)[i] != (NumericDigit) 0)
1215 /* If we get here, there should be at least one non-zero digit */
1216 Assert(start_offset + end_offset < NUMERIC_NDIGITS(key));
1219 * Note that we don't hash on the Numeric's scale, since two numerics can
1220 * compare equal but have different scales. We also don't hash on the
1221 * sign, although we could: since a sign difference implies inequality,
1222 * this shouldn't affect correctness.
1224 hash_len = NUMERIC_NDIGITS(key) - start_offset - end_offset;
1225 digit_hash = hash_any((unsigned char *) (NUMERIC_DIGITS(key) + start_offset),
1226 hash_len * sizeof(NumericDigit));
1228 /* Mix in the weight, via XOR */
1229 result = digit_hash ^ weight;
1231 PG_RETURN_DATUM(result);
1235 /* ----------------------------------------------------------------------
1237 * Basic arithmetic functions
1239 * ----------------------------------------------------------------------
1249 numeric_add(PG_FUNCTION_ARGS)
1251 Numeric num1 = PG_GETARG_NUMERIC(0);
1252 Numeric num2 = PG_GETARG_NUMERIC(1);
1261 if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
1262 PG_RETURN_NUMERIC(make_result(&const_nan));
1265 * Unpack the values, let add_var() compute the result and return it.
1271 set_var_from_num(num1, &arg1);
1272 set_var_from_num(num2, &arg2);
1274 add_var(&arg1, &arg2, &result);
1276 res = make_result(&result);
1282 PG_RETURN_NUMERIC(res);
1289 * Subtract one numeric from another
1292 numeric_sub(PG_FUNCTION_ARGS)
1294 Numeric num1 = PG_GETARG_NUMERIC(0);
1295 Numeric num2 = PG_GETARG_NUMERIC(1);
1304 if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
1305 PG_RETURN_NUMERIC(make_result(&const_nan));
1308 * Unpack the values, let sub_var() compute the result and return it.
1314 set_var_from_num(num1, &arg1);
1315 set_var_from_num(num2, &arg2);
1317 sub_var(&arg1, &arg2, &result);
1319 res = make_result(&result);
1325 PG_RETURN_NUMERIC(res);
1332 * Calculate the product of two numerics
1335 numeric_mul(PG_FUNCTION_ARGS)
1337 Numeric num1 = PG_GETARG_NUMERIC(0);
1338 Numeric num2 = PG_GETARG_NUMERIC(1);
1347 if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
1348 PG_RETURN_NUMERIC(make_result(&const_nan));
1351 * Unpack the values, let mul_var() compute the result and return it.
1352 * Unlike add_var() and sub_var(), mul_var() will round its result. In the
1353 * case of numeric_mul(), which is invoked for the * operator on numerics,
1354 * we request exact representation for the product (rscale = sum(dscale of
1355 * arg1, dscale of arg2)).
1361 set_var_from_num(num1, &arg1);
1362 set_var_from_num(num2, &arg2);
1364 mul_var(&arg1, &arg2, &result, arg1.dscale + arg2.dscale);
1366 res = make_result(&result);
1372 PG_RETURN_NUMERIC(res);
1379 * Divide one numeric into another
1382 numeric_div(PG_FUNCTION_ARGS)
1384 Numeric num1 = PG_GETARG_NUMERIC(0);
1385 Numeric num2 = PG_GETARG_NUMERIC(1);
1395 if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
1396 PG_RETURN_NUMERIC(make_result(&const_nan));
1399 * Unpack the arguments
1405 set_var_from_num(num1, &arg1);
1406 set_var_from_num(num2, &arg2);
1409 * Select scale for division result
1411 rscale = select_div_scale(&arg1, &arg2);
1414 * Do the divide and return the result
1416 div_var(&arg1, &arg2, &result, rscale, true);
1418 res = make_result(&result);
1424 PG_RETURN_NUMERIC(res);
1429 * numeric_div_trunc() -
1431 * Divide one numeric into another, truncating the result to an integer
1434 numeric_div_trunc(PG_FUNCTION_ARGS)
1436 Numeric num1 = PG_GETARG_NUMERIC(0);
1437 Numeric num2 = PG_GETARG_NUMERIC(1);
1446 if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
1447 PG_RETURN_NUMERIC(make_result(&const_nan));
1450 * Unpack the arguments
1456 set_var_from_num(num1, &arg1);
1457 set_var_from_num(num2, &arg2);
1460 * Do the divide and return the result
1462 div_var(&arg1, &arg2, &result, 0, false);
1464 res = make_result(&result);
1470 PG_RETURN_NUMERIC(res);
1477 * Calculate the modulo of two numerics
1480 numeric_mod(PG_FUNCTION_ARGS)
1482 Numeric num1 = PG_GETARG_NUMERIC(0);
1483 Numeric num2 = PG_GETARG_NUMERIC(1);
1489 if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
1490 PG_RETURN_NUMERIC(make_result(&const_nan));
1496 set_var_from_num(num1, &arg1);
1497 set_var_from_num(num2, &arg2);
1499 mod_var(&arg1, &arg2, &result);
1501 res = make_result(&result);
1507 PG_RETURN_NUMERIC(res);
1514 * Increment a number by one
1517 numeric_inc(PG_FUNCTION_ARGS)
1519 Numeric num = PG_GETARG_NUMERIC(0);
1526 if (NUMERIC_IS_NAN(num))
1527 PG_RETURN_NUMERIC(make_result(&const_nan));
1530 * Compute the result and return it
1534 set_var_from_num(num, &arg);
1536 add_var(&arg, &const_one, &arg);
1538 res = make_result(&arg);
1542 PG_RETURN_NUMERIC(res);
1547 * numeric_smaller() -
1549 * Return the smaller of two numbers
1552 numeric_smaller(PG_FUNCTION_ARGS)
1554 Numeric num1 = PG_GETARG_NUMERIC(0);
1555 Numeric num2 = PG_GETARG_NUMERIC(1);
1558 * Use cmp_numerics so that this will agree with the comparison operators,
1559 * particularly as regards comparisons involving NaN.
1561 if (cmp_numerics(num1, num2) < 0)
1562 PG_RETURN_NUMERIC(num1);
1564 PG_RETURN_NUMERIC(num2);
1569 * numeric_larger() -
1571 * Return the larger of two numbers
1574 numeric_larger(PG_FUNCTION_ARGS)
1576 Numeric num1 = PG_GETARG_NUMERIC(0);
1577 Numeric num2 = PG_GETARG_NUMERIC(1);
1580 * Use cmp_numerics so that this will agree with the comparison operators,
1581 * particularly as regards comparisons involving NaN.
1583 if (cmp_numerics(num1, num2) > 0)
1584 PG_RETURN_NUMERIC(num1);
1586 PG_RETURN_NUMERIC(num2);
1590 /* ----------------------------------------------------------------------
1592 * Advanced math functions
1594 * ----------------------------------------------------------------------
1603 numeric_fac(PG_FUNCTION_ARGS)
1605 int64 num = PG_GETARG_INT64(0);
1612 res = make_result(&const_one);
1613 PG_RETURN_NUMERIC(res);
1615 /* Fail immediately if the result would overflow */
1618 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1619 errmsg("value overflows numeric format")));
1624 int8_to_numericvar(num, &result);
1626 for (num = num - 1; num > 1; num--)
1628 /* this loop can take awhile, so allow it to be interrupted */
1629 CHECK_FOR_INTERRUPTS();
1631 int8_to_numericvar(num, &fact);
1633 mul_var(&result, &fact, &result, 0);
1636 res = make_result(&result);
1641 PG_RETURN_NUMERIC(res);
1648 * Compute the square root of a numeric.
1651 numeric_sqrt(PG_FUNCTION_ARGS)
1653 Numeric num = PG_GETARG_NUMERIC(0);
1663 if (NUMERIC_IS_NAN(num))
1664 PG_RETURN_NUMERIC(make_result(&const_nan));
1667 * Unpack the argument and determine the result scale. We choose a scale
1668 * to give at least NUMERIC_MIN_SIG_DIGITS significant digits; but in any
1669 * case not less than the input's dscale.
1674 set_var_from_num(num, &arg);
1676 /* Assume the input was normalized, so arg.weight is accurate */
1677 sweight = (arg.weight + 1) * DEC_DIGITS / 2 - 1;
1679 rscale = NUMERIC_MIN_SIG_DIGITS - sweight;
1680 rscale = Max(rscale, arg.dscale);
1681 rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
1682 rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
1685 * Let sqrt_var() do the calculation and return the result.
1687 sqrt_var(&arg, &result, rscale);
1689 res = make_result(&result);
1694 PG_RETURN_NUMERIC(res);
1701 * Raise e to the power of x
1704 numeric_exp(PG_FUNCTION_ARGS)
1706 Numeric num = PG_GETARG_NUMERIC(0);
1716 if (NUMERIC_IS_NAN(num))
1717 PG_RETURN_NUMERIC(make_result(&const_nan));
1720 * Unpack the argument and determine the result scale. We choose a scale
1721 * to give at least NUMERIC_MIN_SIG_DIGITS significant digits; but in any
1722 * case not less than the input's dscale.
1727 set_var_from_num(num, &arg);
1729 /* convert input to float8, ignoring overflow */
1730 val = numericvar_to_double_no_overflow(&arg);
1733 * log10(result) = num * log10(e), so this is approximately the decimal
1734 * weight of the result:
1736 val *= 0.434294481903252;
1738 /* limit to something that won't cause integer overflow */
1739 val = Max(val, -NUMERIC_MAX_RESULT_SCALE);
1740 val = Min(val, NUMERIC_MAX_RESULT_SCALE);
1742 rscale = NUMERIC_MIN_SIG_DIGITS - (int) val;
1743 rscale = Max(rscale, arg.dscale);
1744 rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
1745 rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
1748 * Let exp_var() do the calculation and return the result.
1750 exp_var(&arg, &result, rscale);
1752 res = make_result(&result);
1757 PG_RETURN_NUMERIC(res);
1764 * Compute the natural logarithm of x
1767 numeric_ln(PG_FUNCTION_ARGS)
1769 Numeric num = PG_GETARG_NUMERIC(0);
1779 if (NUMERIC_IS_NAN(num))
1780 PG_RETURN_NUMERIC(make_result(&const_nan));
1785 set_var_from_num(num, &arg);
1787 /* Approx decimal digits before decimal point */
1788 dec_digits = (arg.weight + 1) * DEC_DIGITS;
1791 rscale = NUMERIC_MIN_SIG_DIGITS - (int) log10(dec_digits - 1);
1792 else if (dec_digits < 1)
1793 rscale = NUMERIC_MIN_SIG_DIGITS - (int) log10(1 - dec_digits);
1795 rscale = NUMERIC_MIN_SIG_DIGITS;
1797 rscale = Max(rscale, arg.dscale);
1798 rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
1799 rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
1801 ln_var(&arg, &result, rscale);
1803 res = make_result(&result);
1808 PG_RETURN_NUMERIC(res);
1815 * Compute the logarithm of x in a given base
1818 numeric_log(PG_FUNCTION_ARGS)
1820 Numeric num1 = PG_GETARG_NUMERIC(0);
1821 Numeric num2 = PG_GETARG_NUMERIC(1);
1830 if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
1831 PG_RETURN_NUMERIC(make_result(&const_nan));
1840 set_var_from_num(num1, &arg1);
1841 set_var_from_num(num2, &arg2);
1844 * Call log_var() to compute and return the result; note it handles scale
1847 log_var(&arg1, &arg2, &result);
1849 res = make_result(&result);
1855 PG_RETURN_NUMERIC(res);
1862 * Raise b to the power of x
1865 numeric_power(PG_FUNCTION_ARGS)
1867 Numeric num1 = PG_GETARG_NUMERIC(0);
1868 Numeric num2 = PG_GETARG_NUMERIC(1);
1872 NumericVar arg2_trunc;
1878 if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
1879 PG_RETURN_NUMERIC(make_result(&const_nan));
1886 init_var(&arg2_trunc);
1889 set_var_from_num(num1, &arg1);
1890 set_var_from_num(num2, &arg2);
1891 set_var_from_var(&arg2, &arg2_trunc);
1893 trunc_var(&arg2_trunc, 0);
1896 * The SQL spec requires that we emit a particular SQLSTATE error code for
1897 * certain error conditions. Specifically, we don't return a divide-by-zero
1898 * error code for 0 ^ -1.
1900 if ((cmp_var(&arg1, &const_zero) == 0 &&
1901 cmp_var(&arg2, &const_zero) < 0) ||
1902 (cmp_var(&arg1, &const_zero) < 0 &&
1903 cmp_var(&arg2, &arg2_trunc) != 0))
1905 (errcode(ERRCODE_INVALID_ARGUMENT_FOR_POWER_FUNCTION),
1906 errmsg("invalid argument for power function")));
1909 * Call power_var() to compute and return the result; note it handles
1910 * scale selection itself.
1912 power_var(&arg1, &arg2, &result);
1914 res = make_result(&result);
1918 free_var(&arg2_trunc);
1921 PG_RETURN_NUMERIC(res);
1925 /* ----------------------------------------------------------------------
1927 * Type conversion functions
1929 * ----------------------------------------------------------------------
1934 int4_numeric(PG_FUNCTION_ARGS)
1936 int32 val = PG_GETARG_INT32(0);
1942 int8_to_numericvar((int64) val, &result);
1944 res = make_result(&result);
1948 PG_RETURN_NUMERIC(res);
1953 numeric_int4(PG_FUNCTION_ARGS)
1955 Numeric num = PG_GETARG_NUMERIC(0);
1959 /* XXX would it be better to return NULL? */
1960 if (NUMERIC_IS_NAN(num))
1962 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1963 errmsg("cannot convert NaN to integer")));
1965 /* Convert to variable format, then convert to int4 */
1967 set_var_from_num(num, &x);
1968 result = numericvar_to_int4(&x);
1970 PG_RETURN_INT32(result);
1974 * Given a NumericVar, convert it to an int32. If the NumericVar
1975 * exceeds the range of an int32, raise the appropriate error via
1976 * ereport(). The input NumericVar is *not* free'd.
1979 numericvar_to_int4(NumericVar *var)
1984 if (!numericvar_to_int8(var, &val))
1986 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1987 errmsg("integer out of range")));
1989 /* Down-convert to int4 */
1990 result = (int32) val;
1992 /* Test for overflow by reverse-conversion. */
1993 if ((int64) result != val)
1995 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1996 errmsg("integer out of range")));
2002 int8_numeric(PG_FUNCTION_ARGS)
2004 int64 val = PG_GETARG_INT64(0);
2010 int8_to_numericvar(val, &result);
2012 res = make_result(&result);
2016 PG_RETURN_NUMERIC(res);
2021 numeric_int8(PG_FUNCTION_ARGS)
2023 Numeric num = PG_GETARG_NUMERIC(0);
2027 /* XXX would it be better to return NULL? */
2028 if (NUMERIC_IS_NAN(num))
2030 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2031 errmsg("cannot convert NaN to bigint")));
2033 /* Convert to variable format and thence to int8 */
2035 set_var_from_num(num, &x);
2037 if (!numericvar_to_int8(&x, &result))
2039 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
2040 errmsg("bigint out of range")));
2044 PG_RETURN_INT64(result);
2049 int2_numeric(PG_FUNCTION_ARGS)
2051 int16 val = PG_GETARG_INT16(0);
2057 int8_to_numericvar((int64) val, &result);
2059 res = make_result(&result);
2063 PG_RETURN_NUMERIC(res);
2068 numeric_int2(PG_FUNCTION_ARGS)
2070 Numeric num = PG_GETARG_NUMERIC(0);
2075 /* XXX would it be better to return NULL? */
2076 if (NUMERIC_IS_NAN(num))
2078 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2079 errmsg("cannot convert NaN to smallint")));
2081 /* Convert to variable format and thence to int8 */
2083 set_var_from_num(num, &x);
2085 if (!numericvar_to_int8(&x, &val))
2087 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
2088 errmsg("smallint out of range")));
2092 /* Down-convert to int2 */
2093 result = (int16) val;
2095 /* Test for overflow by reverse-conversion. */
2096 if ((int64) result != val)
2098 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
2099 errmsg("smallint out of range")));
2101 PG_RETURN_INT16(result);
2106 float8_numeric(PG_FUNCTION_ARGS)
2108 float8 val = PG_GETARG_FLOAT8(0);
2111 char buf[DBL_DIG + 100];
2114 PG_RETURN_NUMERIC(make_result(&const_nan));
2116 sprintf(buf, "%.*g", DBL_DIG, val);
2120 set_var_from_str(buf, &result);
2121 res = make_result(&result);
2125 PG_RETURN_NUMERIC(res);
2130 numeric_float8(PG_FUNCTION_ARGS)
2132 Numeric num = PG_GETARG_NUMERIC(0);
2136 if (NUMERIC_IS_NAN(num))
2137 PG_RETURN_FLOAT8(get_float8_nan());
2139 tmp = DatumGetCString(DirectFunctionCall1(numeric_out,
2140 NumericGetDatum(num)));
2142 result = DirectFunctionCall1(float8in, CStringGetDatum(tmp));
2146 PG_RETURN_DATUM(result);
2150 /* Convert numeric to float8; if out of range, return +/- HUGE_VAL */
2152 numeric_float8_no_overflow(PG_FUNCTION_ARGS)
2154 Numeric num = PG_GETARG_NUMERIC(0);
2157 if (NUMERIC_IS_NAN(num))
2158 PG_RETURN_FLOAT8(get_float8_nan());
2160 val = numeric_to_double_no_overflow(num);
2162 PG_RETURN_FLOAT8(val);
2166 float4_numeric(PG_FUNCTION_ARGS)
2168 float4 val = PG_GETARG_FLOAT4(0);
2171 char buf[FLT_DIG + 100];
2174 PG_RETURN_NUMERIC(make_result(&const_nan));
2176 sprintf(buf, "%.*g", FLT_DIG, val);
2180 set_var_from_str(buf, &result);
2181 res = make_result(&result);
2185 PG_RETURN_NUMERIC(res);
2190 numeric_float4(PG_FUNCTION_ARGS)
2192 Numeric num = PG_GETARG_NUMERIC(0);
2196 if (NUMERIC_IS_NAN(num))
2197 PG_RETURN_FLOAT4(get_float4_nan());
2199 tmp = DatumGetCString(DirectFunctionCall1(numeric_out,
2200 NumericGetDatum(num)));
2202 result = DirectFunctionCall1(float4in, CStringGetDatum(tmp));
2206 PG_RETURN_DATUM(result);
2210 /* ----------------------------------------------------------------------
2212 * Aggregate functions
2214 * The transition datatype for all these aggregates is a 3-element array
2215 * of Numeric, holding the values N, sum(X), sum(X*X) in that order.
2217 * We represent N as a numeric mainly to avoid having to build a special
2218 * datatype; it's unlikely it'd overflow an int4, but ...
2220 * ----------------------------------------------------------------------
2224 do_numeric_accum(ArrayType *transarray, Numeric newval)
2233 /* We assume the input is array of numeric */
2234 deconstruct_array(transarray,
2235 NUMERICOID, -1, false, 'i',
2236 &transdatums, NULL, &ndatums);
2238 elog(ERROR, "expected 3-element numeric array");
2240 sumX = transdatums[1];
2241 sumX2 = transdatums[2];
2243 N = DirectFunctionCall1(numeric_inc, N);
2244 sumX = DirectFunctionCall2(numeric_add, sumX,
2245 NumericGetDatum(newval));
2246 sumX2 = DirectFunctionCall2(numeric_add, sumX2,
2247 DirectFunctionCall2(numeric_mul,
2248 NumericGetDatum(newval),
2249 NumericGetDatum(newval)));
2252 transdatums[1] = sumX;
2253 transdatums[2] = sumX2;
2255 result = construct_array(transdatums, 3,
2256 NUMERICOID, -1, false, 'i');
2262 * Improve avg performance by not caclulating sum(X*X).
2265 do_numeric_avg_accum(ArrayType *transarray, Numeric newval)
2273 /* We assume the input is array of numeric */
2274 deconstruct_array(transarray,
2275 NUMERICOID, -1, false, 'i',
2276 &transdatums, NULL, &ndatums);
2278 elog(ERROR, "expected 2-element numeric array");
2280 sumX = transdatums[1];
2282 N = DirectFunctionCall1(numeric_inc, N);
2283 sumX = DirectFunctionCall2(numeric_add, sumX,
2284 NumericGetDatum(newval));
2287 transdatums[1] = sumX;
2289 result = construct_array(transdatums, 2,
2290 NUMERICOID, -1, false, 'i');
2296 numeric_accum(PG_FUNCTION_ARGS)
2298 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
2299 Numeric newval = PG_GETARG_NUMERIC(1);
2301 PG_RETURN_ARRAYTYPE_P(do_numeric_accum(transarray, newval));
2305 * Optimized case for average of numeric.
2308 numeric_avg_accum(PG_FUNCTION_ARGS)
2310 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
2311 Numeric newval = PG_GETARG_NUMERIC(1);
2313 PG_RETURN_ARRAYTYPE_P(do_numeric_avg_accum(transarray, newval));
2317 * Integer data types all use Numeric accumulators to share code and
2318 * avoid risk of overflow. For int2 and int4 inputs, Numeric accumulation
2319 * is overkill for the N and sum(X) values, but definitely not overkill
2320 * for the sum(X*X) value. Hence, we use int2_accum and int4_accum only
2321 * for stddev/variance --- there are faster special-purpose accumulator
2322 * routines for SUM and AVG of these datatypes.
2326 int2_accum(PG_FUNCTION_ARGS)
2328 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
2329 Datum newval2 = PG_GETARG_DATUM(1);
2332 newval = DatumGetNumeric(DirectFunctionCall1(int2_numeric, newval2));
2334 PG_RETURN_ARRAYTYPE_P(do_numeric_accum(transarray, newval));
2338 int4_accum(PG_FUNCTION_ARGS)
2340 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
2341 Datum newval4 = PG_GETARG_DATUM(1);
2344 newval = DatumGetNumeric(DirectFunctionCall1(int4_numeric, newval4));
2346 PG_RETURN_ARRAYTYPE_P(do_numeric_accum(transarray, newval));
2350 int8_accum(PG_FUNCTION_ARGS)
2352 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
2353 Datum newval8 = PG_GETARG_DATUM(1);
2356 newval = DatumGetNumeric(DirectFunctionCall1(int8_numeric, newval8));
2358 PG_RETURN_ARRAYTYPE_P(do_numeric_accum(transarray, newval));
2362 * Optimized case for average of int8.
2365 int8_avg_accum(PG_FUNCTION_ARGS)
2367 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
2368 Datum newval8 = PG_GETARG_DATUM(1);
2371 newval = DatumGetNumeric(DirectFunctionCall1(int8_numeric, newval8));
2373 PG_RETURN_ARRAYTYPE_P(do_numeric_avg_accum(transarray, newval));
2378 numeric_avg(PG_FUNCTION_ARGS)
2380 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
2386 /* We assume the input is array of numeric */
2387 deconstruct_array(transarray,
2388 NUMERICOID, -1, false, 'i',
2389 &transdatums, NULL, &ndatums);
2391 elog(ERROR, "expected 2-element numeric array");
2392 N = DatumGetNumeric(transdatums[0]);
2393 sumX = DatumGetNumeric(transdatums[1]);
2395 /* SQL92 defines AVG of no values to be NULL */
2396 /* N is zero iff no digits (cf. numeric_uminus) */
2397 if (VARSIZE(N) == NUMERIC_HDRSZ)
2400 PG_RETURN_DATUM(DirectFunctionCall2(numeric_div,
2401 NumericGetDatum(sumX),
2402 NumericGetDatum(N)));
2406 * Workhorse routine for the standard deviance and variance
2407 * aggregates. 'transarray' is the aggregate's transition
2408 * array. 'variance' specifies whether we should calculate the
2409 * variance or the standard deviation. 'sample' indicates whether the
2410 * caller is interested in the sample or the population
2413 * If appropriate variance statistic is undefined for the input,
2414 * *is_null is set to true and NULL is returned.
2417 numeric_stddev_internal(ArrayType *transarray,
2418 bool variance, bool sample,
2436 /* We assume the input is array of numeric */
2437 deconstruct_array(transarray,
2438 NUMERICOID, -1, false, 'i',
2439 &transdatums, NULL, &ndatums);
2441 elog(ERROR, "expected 3-element numeric array");
2442 N = DatumGetNumeric(transdatums[0]);
2443 sumX = DatumGetNumeric(transdatums[1]);
2444 sumX2 = DatumGetNumeric(transdatums[2]);
2446 if (NUMERIC_IS_NAN(N) || NUMERIC_IS_NAN(sumX) || NUMERIC_IS_NAN(sumX2))
2447 return make_result(&const_nan);
2450 set_var_from_num(N, &vN);
2453 * Sample stddev and variance are undefined when N <= 1; population stddev
2454 * is undefined when N == 0. Return NULL in either case.
2461 if (cmp_var(&vN, comp) <= 0)
2468 init_var(&vNminus1);
2469 sub_var(&vN, &const_one, &vNminus1);
2472 set_var_from_num(sumX, &vsumX);
2474 set_var_from_num(sumX2, &vsumX2);
2476 /* compute rscale for mul_var calls */
2477 rscale = vsumX.dscale * 2;
2479 mul_var(&vsumX, &vsumX, &vsumX, rscale); /* vsumX = sumX * sumX */
2480 mul_var(&vN, &vsumX2, &vsumX2, rscale); /* vsumX2 = N * sumX2 */
2481 sub_var(&vsumX2, &vsumX, &vsumX2); /* N * sumX2 - sumX * sumX */
2483 if (cmp_var(&vsumX2, &const_zero) <= 0)
2485 /* Watch out for roundoff error producing a negative numerator */
2486 res = make_result(&const_zero);
2491 mul_var(&vN, &vNminus1, &vNminus1, 0); /* N * (N - 1) */
2493 mul_var(&vN, &vN, &vNminus1, 0); /* N * N */
2494 rscale = select_div_scale(&vsumX2, &vNminus1);
2495 div_var(&vsumX2, &vNminus1, &vsumX, rscale, true); /* variance */
2497 sqrt_var(&vsumX, &vsumX, rscale); /* stddev */
2499 res = make_result(&vsumX);
2503 free_var(&vNminus1);
2511 numeric_var_samp(PG_FUNCTION_ARGS)
2516 res = numeric_stddev_internal(PG_GETARG_ARRAYTYPE_P(0),
2517 true, true, &is_null);
2522 PG_RETURN_NUMERIC(res);
2526 numeric_stddev_samp(PG_FUNCTION_ARGS)
2531 res = numeric_stddev_internal(PG_GETARG_ARRAYTYPE_P(0),
2532 false, true, &is_null);
2537 PG_RETURN_NUMERIC(res);
2541 numeric_var_pop(PG_FUNCTION_ARGS)
2546 res = numeric_stddev_internal(PG_GETARG_ARRAYTYPE_P(0),
2547 true, false, &is_null);
2552 PG_RETURN_NUMERIC(res);
2556 numeric_stddev_pop(PG_FUNCTION_ARGS)
2561 res = numeric_stddev_internal(PG_GETARG_ARRAYTYPE_P(0),
2562 false, false, &is_null);
2567 PG_RETURN_NUMERIC(res);
2571 * SUM transition functions for integer datatypes.
2573 * To avoid overflow, we use accumulators wider than the input datatype.
2574 * A Numeric accumulator is needed for int8 input; for int4 and int2
2575 * inputs, we use int8 accumulators which should be sufficient for practical
2576 * purposes. (The latter two therefore don't really belong in this file,
2577 * but we keep them here anyway.)
2579 * Because SQL92 defines the SUM() of no values to be NULL, not zero,
2580 * the initial condition of the transition data value needs to be NULL. This
2581 * means we can't rely on ExecAgg to automatically insert the first non-null
2582 * data value into the transition data: it doesn't know how to do the type
2583 * conversion. The upshot is that these routines have to be marked non-strict
2584 * and handle substitution of the first non-null input themselves.
2588 int2_sum(PG_FUNCTION_ARGS)
2592 if (PG_ARGISNULL(0))
2594 /* No non-null input seen so far... */
2595 if (PG_ARGISNULL(1))
2596 PG_RETURN_NULL(); /* still no non-null */
2597 /* This is the first non-null input. */
2598 newval = (int64) PG_GETARG_INT16(1);
2599 PG_RETURN_INT64(newval);
2603 * If we're invoked by nodeAgg, we can cheat and modify our first
2604 * parameter in-place to avoid palloc overhead. If not, we need to return
2605 * the new value of the transition variable.
2606 * (If int8 is pass-by-value, then of course this is useless as well
2607 * as incorrect, so just ifdef it out.)
2609 #ifndef USE_FLOAT8_BYVAL /* controls int8 too */
2610 if (fcinfo->context && IsA(fcinfo->context, AggState))
2612 int64 *oldsum = (int64 *) PG_GETARG_POINTER(0);
2614 /* Leave the running sum unchanged in the new input is null */
2615 if (!PG_ARGISNULL(1))
2616 *oldsum = *oldsum + (int64) PG_GETARG_INT16(1);
2618 PG_RETURN_POINTER(oldsum);
2623 int64 oldsum = PG_GETARG_INT64(0);
2625 /* Leave sum unchanged if new input is null. */
2626 if (PG_ARGISNULL(1))
2627 PG_RETURN_INT64(oldsum);
2629 /* OK to do the addition. */
2630 newval = oldsum + (int64) PG_GETARG_INT16(1);
2632 PG_RETURN_INT64(newval);
2637 int4_sum(PG_FUNCTION_ARGS)
2641 if (PG_ARGISNULL(0))
2643 /* No non-null input seen so far... */
2644 if (PG_ARGISNULL(1))
2645 PG_RETURN_NULL(); /* still no non-null */
2646 /* This is the first non-null input. */
2647 newval = (int64) PG_GETARG_INT32(1);
2648 PG_RETURN_INT64(newval);
2652 * If we're invoked by nodeAgg, we can cheat and modify our first
2653 * parameter in-place to avoid palloc overhead. If not, we need to return
2654 * the new value of the transition variable.
2655 * (If int8 is pass-by-value, then of course this is useless as well
2656 * as incorrect, so just ifdef it out.)
2658 #ifndef USE_FLOAT8_BYVAL /* controls int8 too */
2659 if (fcinfo->context && IsA(fcinfo->context, AggState))
2661 int64 *oldsum = (int64 *) PG_GETARG_POINTER(0);
2663 /* Leave the running sum unchanged in the new input is null */
2664 if (!PG_ARGISNULL(1))
2665 *oldsum = *oldsum + (int64) PG_GETARG_INT32(1);
2667 PG_RETURN_POINTER(oldsum);
2672 int64 oldsum = PG_GETARG_INT64(0);
2674 /* Leave sum unchanged if new input is null. */
2675 if (PG_ARGISNULL(1))
2676 PG_RETURN_INT64(oldsum);
2678 /* OK to do the addition. */
2679 newval = oldsum + (int64) PG_GETARG_INT32(1);
2681 PG_RETURN_INT64(newval);
2686 int8_sum(PG_FUNCTION_ARGS)
2691 if (PG_ARGISNULL(0))
2693 /* No non-null input seen so far... */
2694 if (PG_ARGISNULL(1))
2695 PG_RETURN_NULL(); /* still no non-null */
2696 /* This is the first non-null input. */
2697 newval = DirectFunctionCall1(int8_numeric, PG_GETARG_DATUM(1));
2698 PG_RETURN_DATUM(newval);
2702 * Note that we cannot special-case the nodeAgg case here, as we do for
2703 * int2_sum and int4_sum: numeric is of variable size, so we cannot modify
2704 * our first parameter in-place.
2707 oldsum = PG_GETARG_NUMERIC(0);
2709 /* Leave sum unchanged if new input is null. */
2710 if (PG_ARGISNULL(1))
2711 PG_RETURN_NUMERIC(oldsum);
2713 /* OK to do the addition. */
2714 newval = DirectFunctionCall1(int8_numeric, PG_GETARG_DATUM(1));
2716 PG_RETURN_DATUM(DirectFunctionCall2(numeric_add,
2717 NumericGetDatum(oldsum), newval));
2722 * Routines for avg(int2) and avg(int4). The transition datatype
2723 * is a two-element int8 array, holding count and sum.
2726 typedef struct Int8TransTypeData
2728 #ifndef INT64_IS_BUSTED
2732 /* "int64" isn't really 64 bits, so fake up properly-aligned fields */
2738 } Int8TransTypeData;
2741 int2_avg_accum(PG_FUNCTION_ARGS)
2743 ArrayType *transarray;
2744 int16 newval = PG_GETARG_INT16(1);
2745 Int8TransTypeData *transdata;
2748 * If we're invoked by nodeAgg, we can cheat and modify our first
2749 * parameter in-place to reduce palloc overhead. Otherwise we need to make
2750 * a copy of it before scribbling on it.
2752 if (fcinfo->context && IsA(fcinfo->context, AggState))
2753 transarray = PG_GETARG_ARRAYTYPE_P(0);
2755 transarray = PG_GETARG_ARRAYTYPE_P_COPY(0);
2757 if (ARR_HASNULL(transarray) ||
2758 ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
2759 elog(ERROR, "expected 2-element int8 array");
2761 transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
2763 transdata->sum += newval;
2765 PG_RETURN_ARRAYTYPE_P(transarray);
2769 int4_avg_accum(PG_FUNCTION_ARGS)
2771 ArrayType *transarray;
2772 int32 newval = PG_GETARG_INT32(1);
2773 Int8TransTypeData *transdata;
2776 * If we're invoked by nodeAgg, we can cheat and modify our first
2777 * parameter in-place to reduce palloc overhead. Otherwise we need to make
2778 * a copy of it before scribbling on it.
2780 if (fcinfo->context && IsA(fcinfo->context, AggState))
2781 transarray = PG_GETARG_ARRAYTYPE_P(0);
2783 transarray = PG_GETARG_ARRAYTYPE_P_COPY(0);
2785 if (ARR_HASNULL(transarray) ||
2786 ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
2787 elog(ERROR, "expected 2-element int8 array");
2789 transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
2791 transdata->sum += newval;
2793 PG_RETURN_ARRAYTYPE_P(transarray);
2797 int8_avg(PG_FUNCTION_ARGS)
2799 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
2800 Int8TransTypeData *transdata;
2804 if (ARR_HASNULL(transarray) ||
2805 ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
2806 elog(ERROR, "expected 2-element int8 array");
2807 transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
2809 /* SQL92 defines AVG of no values to be NULL */
2810 if (transdata->count == 0)
2813 countd = DirectFunctionCall1(int8_numeric,
2814 Int64GetDatumFast(transdata->count));
2815 sumd = DirectFunctionCall1(int8_numeric,
2816 Int64GetDatumFast(transdata->sum));
2818 PG_RETURN_DATUM(DirectFunctionCall2(numeric_div, sumd, countd));
2822 /* ----------------------------------------------------------------------
2826 * ----------------------------------------------------------------------
2829 #ifdef NUMERIC_DEBUG
2832 * dump_numeric() - Dump a value in the db storage format for debugging
2835 dump_numeric(const char *str, Numeric num)
2837 NumericDigit *digits = NUMERIC_DIGITS(num);
2841 ndigits = NUMERIC_NDIGITS(num);
2843 printf("%s: NUMERIC w=%d d=%d ", str, num->n_weight, NUMERIC_DSCALE(num));
2844 switch (NUMERIC_SIGN(num))
2856 printf("SIGN=0x%x", NUMERIC_SIGN(num));
2860 for (i = 0; i < ndigits; i++)
2861 printf(" %0*d", DEC_DIGITS, digits[i]);
2867 * dump_var() - Dump a value in the variable format for debugging
2870 dump_var(const char *str, NumericVar *var)
2874 printf("%s: VAR w=%d d=%d ", str, var->weight, var->dscale);
2887 printf("SIGN=0x%x", var->sign);
2891 for (i = 0; i < var->ndigits; i++)
2892 printf(" %0*d", DEC_DIGITS, var->digits[i]);
2896 #endif /* NUMERIC_DEBUG */
2899 /* ----------------------------------------------------------------------
2901 * Local functions follow
2903 * In general, these do not support NaNs --- callers must eliminate
2904 * the possibility of NaN first. (make_result() is an exception.)
2906 * ----------------------------------------------------------------------
2913 * Allocate a digit buffer of ndigits digits (plus a spare digit for rounding)
2916 alloc_var(NumericVar *var, int ndigits)
2918 digitbuf_free(var->buf);
2919 var->buf = digitbuf_alloc(ndigits + 1);
2920 var->buf[0] = 0; /* spare digit for rounding */
2921 var->digits = var->buf + 1;
2922 var->ndigits = ndigits;
2929 * Return the digit buffer of a variable to the free pool
2932 free_var(NumericVar *var)
2934 digitbuf_free(var->buf);
2937 var->sign = NUMERIC_NAN;
2944 * Set a variable to ZERO.
2945 * Note: its dscale is not touched.
2948 zero_var(NumericVar *var)
2950 digitbuf_free(var->buf);
2954 var->weight = 0; /* by convention; doesn't really matter */
2955 var->sign = NUMERIC_POS; /* anything but NAN... */
2960 * set_var_from_str()
2962 * Parse a string and put the number into a variable
2965 set_var_from_str(const char *str, NumericVar *dest)
2967 const char *cp = str;
2968 bool have_dp = FALSE;
2970 unsigned char *decdigits;
2971 int sign = NUMERIC_POS;
2978 NumericDigit *digits;
2981 * We first parse the string to extract decimal digits and determine the
2982 * correct decimal weight. Then convert to NBASE representation.
2985 /* skip leading spaces */
2988 if (!isspace((unsigned char) *cp))
3012 if (!isdigit((unsigned char) *cp))
3014 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
3015 errmsg("invalid input syntax for type numeric: \"%s\"", str)));
3017 decdigits = (unsigned char *) palloc(strlen(cp) + DEC_DIGITS * 2);
3019 /* leading padding for digit alignment later */
3020 memset(decdigits, 0, DEC_DIGITS);
3025 if (isdigit((unsigned char) *cp))
3027 decdigits[i++] = *cp++ - '0';
3033 else if (*cp == '.')
3037 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
3038 errmsg("invalid input syntax for type numeric: \"%s\"",
3047 ddigits = i - DEC_DIGITS;
3048 /* trailing padding for digit alignment later */
3049 memset(decdigits + i, 0, DEC_DIGITS - 1);
3051 /* Handle exponent, if any */
3052 if (*cp == 'e' || *cp == 'E')
3058 exponent = strtol(cp, &endptr, 10);
3061 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
3062 errmsg("invalid input syntax for type numeric: \"%s\"",
3065 if (exponent > NUMERIC_MAX_PRECISION ||
3066 exponent < -NUMERIC_MAX_PRECISION)
3068 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
3069 errmsg("invalid input syntax for type numeric: \"%s\"",
3071 dweight += (int) exponent;
3072 dscale -= (int) exponent;
3077 /* Should be nothing left but spaces */
3080 if (!isspace((unsigned char) *cp))
3082 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
3083 errmsg("invalid input syntax for type numeric: \"%s\"",
3089 * Okay, convert pure-decimal representation to base NBASE. First we need
3090 * to determine the converted weight and ndigits. offset is the number of
3091 * decimal zeroes to insert before the first given digit to have a
3092 * correctly aligned first NBASE digit.
3095 weight = (dweight + 1 + DEC_DIGITS - 1) / DEC_DIGITS - 1;
3097 weight = -((-dweight - 1) / DEC_DIGITS + 1);
3098 offset = (weight + 1) * DEC_DIGITS - (dweight + 1);
3099 ndigits = (ddigits + offset + DEC_DIGITS - 1) / DEC_DIGITS;
3101 alloc_var(dest, ndigits);
3103 dest->weight = weight;
3104 dest->dscale = dscale;
3106 i = DEC_DIGITS - offset;
3107 digits = dest->digits;
3109 while (ndigits-- > 0)
3112 *digits++ = ((decdigits[i] * 10 + decdigits[i + 1]) * 10 +
3113 decdigits[i + 2]) * 10 + decdigits[i + 3];
3114 #elif DEC_DIGITS == 2
3115 *digits++ = decdigits[i] * 10 + decdigits[i + 1];
3116 #elif DEC_DIGITS == 1
3117 *digits++ = decdigits[i];
3119 #error unsupported NBASE
3126 /* Strip any leading/trailing zeroes, and normalize weight if zero */
3132 * set_var_from_num() -
3134 * Convert the packed db format into a variable
3137 set_var_from_num(Numeric num, NumericVar *dest)
3141 ndigits = NUMERIC_NDIGITS(num);
3143 alloc_var(dest, ndigits);
3145 dest->weight = num->n_weight;
3146 dest->sign = NUMERIC_SIGN(num);
3147 dest->dscale = NUMERIC_DSCALE(num);
3149 memcpy(dest->digits, num->n_data, ndigits * sizeof(NumericDigit));
3154 * set_var_from_var() -
3156 * Copy one variable into another
3159 set_var_from_var(NumericVar *value, NumericVar *dest)
3161 NumericDigit *newbuf;
3163 newbuf = digitbuf_alloc(value->ndigits + 1);
3164 newbuf[0] = 0; /* spare digit for rounding */
3165 memcpy(newbuf + 1, value->digits, value->ndigits * sizeof(NumericDigit));
3167 digitbuf_free(dest->buf);
3169 memmove(dest, value, sizeof(NumericVar));
3171 dest->digits = newbuf + 1;
3176 * get_str_from_var() -
3178 * Convert a var to text representation (guts of numeric_out).
3179 * CAUTION: var's contents may be modified by rounding!
3180 * Returns a palloc'd string.
3183 get_str_from_var(NumericVar *var, int dscale)
3200 * Check if we must round up before printing the value and do so.
3202 round_var(var, dscale);
3205 * Allocate space for the result.
3207 * i is set to to # of decimal digits before decimal point. dscale is the
3208 * # of decimal digits we will print after decimal point. We may generate
3209 * as many as DEC_DIGITS-1 excess digits at the end, and in addition we
3210 * need room for sign, decimal point, null terminator.
3212 i = (var->weight + 1) * DEC_DIGITS;
3216 str = palloc(i + dscale + DEC_DIGITS + 2);
3220 * Output a dash for negative values
3222 if (var->sign == NUMERIC_NEG)
3226 * Output all digits before the decimal point
3228 if (var->weight < 0)
3230 d = var->weight + 1;
3235 for (d = 0; d <= var->weight; d++)
3237 dig = (d < var->ndigits) ? var->digits[d] : 0;
3238 /* In the first digit, suppress extra leading decimal zeroes */
3241 bool putit = (d > 0);
3260 #elif DEC_DIGITS == 2
3263 if (d1 > 0 || d > 0)
3266 #elif DEC_DIGITS == 1
3269 #error unsupported NBASE
3275 * If requested, output a decimal point and all the digits that follow it.
3276 * We initially put out a multiple of DEC_DIGITS digits, then truncate if
3282 endcp = cp + dscale;
3283 for (i = 0; i < dscale; d++, i += DEC_DIGITS)
3285 dig = (d >= 0 && d < var->ndigits) ? var->digits[d] : 0;
3297 #elif DEC_DIGITS == 2
3302 #elif DEC_DIGITS == 1
3305 #error unsupported NBASE
3312 * terminate the string and return it
3322 * Create the packed db numeric format in palloc()'d memory from
3326 make_result(NumericVar *var)
3329 NumericDigit *digits = var->digits;
3330 int weight = var->weight;
3331 int sign = var->sign;
3335 if (sign == NUMERIC_NAN)
3337 result = (Numeric) palloc(NUMERIC_HDRSZ);
3339 SET_VARSIZE(result, NUMERIC_HDRSZ);
3340 result->n_weight = 0;
3341 result->n_sign_dscale = NUMERIC_NAN;
3343 dump_numeric("make_result()", result);
3349 /* truncate leading zeroes */
3350 while (n > 0 && *digits == 0)
3356 /* truncate trailing zeroes */
3357 while (n > 0 && digits[n - 1] == 0)
3360 /* If zero result, force to weight=0 and positive sign */
3367 /* Build the result */
3368 len = NUMERIC_HDRSZ + n * sizeof(NumericDigit);
3369 result = (Numeric) palloc(len);
3370 SET_VARSIZE(result, len);
3371 result->n_weight = weight;
3372 result->n_sign_dscale = sign | (var->dscale & NUMERIC_DSCALE_MASK);
3374 memcpy(result->n_data, digits, n * sizeof(NumericDigit));
3376 /* Check for overflow of int16 fields */
3377 if (result->n_weight != weight ||
3378 NUMERIC_DSCALE(result) != var->dscale)
3380 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
3381 errmsg("value overflows numeric format")));
3383 dump_numeric("make_result()", result);
3391 * Do bounds checking and rounding according to the attributes
3395 apply_typmod(NumericVar *var, int32 typmod)
3403 /* Do nothing if we have a default typmod (-1) */
3404 if (typmod < (int32) (VARHDRSZ))
3408 precision = (typmod >> 16) & 0xffff;
3409 scale = typmod & 0xffff;
3410 maxdigits = precision - scale;
3412 /* Round to target scale (and set var->dscale) */
3413 round_var(var, scale);
3416 * Check for overflow - note we can't do this before rounding, because
3417 * rounding could raise the weight. Also note that the var's weight could
3418 * be inflated by leading zeroes, which will be stripped before storage
3419 * but perhaps might not have been yet. In any case, we must recognize a
3420 * true zero, whose weight doesn't mean anything.
3422 ddigits = (var->weight + 1) * DEC_DIGITS;
3423 if (ddigits > maxdigits)
3425 /* Determine true weight; and check for all-zero result */
3426 for (i = 0; i < var->ndigits; i++)
3428 NumericDigit dig = var->digits[i];
3432 /* Adjust for any high-order decimal zero digits */
3438 else if (dig < 1000)
3440 #elif DEC_DIGITS == 2
3443 #elif DEC_DIGITS == 1
3446 #error unsupported NBASE
3448 if (ddigits > maxdigits)
3450 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
3451 errmsg("numeric field overflow"),
3452 errdetail("A field with precision %d, scale %d must round to an absolute value less than %s%d.",
3454 /* Display 10^0 as 1 */
3455 maxdigits ? "10^" : "",
3456 maxdigits ? maxdigits : 1
3460 ddigits -= DEC_DIGITS;
3466 * Convert numeric to int8, rounding if needed.
3468 * If overflow, return FALSE (no error is raised). Return TRUE if okay.
3470 * CAUTION: var's contents may be modified by rounding!
3473 numericvar_to_int8(NumericVar *var, int64 *result)
3475 NumericDigit *digits;
3483 /* Round to nearest integer */
3486 /* Check for zero input */
3488 ndigits = var->ndigits;
3496 * For input like 10000000000, we must treat stripped digits as real. So
3497 * the loop assumes there are weight+1 digits before the decimal point.
3499 weight = var->weight;
3500 Assert(weight >= 0 && ndigits <= weight + 1);
3502 /* Construct the result */
3503 digits = var->digits;
3504 neg = (var->sign == NUMERIC_NEG);
3506 for (i = 1; i <= weight; i++)
3514 * The overflow check is a bit tricky because we want to accept
3515 * INT64_MIN, which will overflow the positive accumulator. We can
3516 * detect this case easily though because INT64_MIN is the only
3517 * nonzero value for which -val == val (on a two's complement machine,
3520 if ((val / NBASE) != oldval) /* possible overflow? */
3522 if (!neg || (-val) != val || val == 0 || oldval < 0)
3527 *result = neg ? -val : val;
3532 * Convert int8 value to numeric.
3535 int8_to_numericvar(int64 val, NumericVar *var)
3542 /* int8 can require at most 19 decimal digits; add one for safety */
3543 alloc_var(var, 20 / DEC_DIGITS);
3546 var->sign = NUMERIC_NEG;
3551 var->sign = NUMERIC_POS;
3561 ptr = var->digits + var->ndigits;
3567 newuval = uval / NBASE;
3568 *ptr = uval - newuval * NBASE;
3572 var->ndigits = ndigits;
3573 var->weight = ndigits - 1;
3577 * Convert numeric to float8; if out of range, return +/- HUGE_VAL
3580 numeric_to_double_no_overflow(Numeric num)
3586 tmp = DatumGetCString(DirectFunctionCall1(numeric_out,
3587 NumericGetDatum(num)));
3589 /* unlike float8in, we ignore ERANGE from strtod */
3590 val = strtod(tmp, &endptr);
3591 if (*endptr != '\0')
3593 /* shouldn't happen ... */
3595 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
3596 errmsg("invalid input syntax for type double precision: \"%s\"",
3605 /* As above, but work from a NumericVar */
3607 numericvar_to_double_no_overflow(NumericVar *var)
3613 tmp = get_str_from_var(var, var->dscale);
3615 /* unlike float8in, we ignore ERANGE from strtod */
3616 val = strtod(tmp, &endptr);
3617 if (*endptr != '\0')
3619 /* shouldn't happen ... */
3621 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
3622 errmsg("invalid input syntax for type double precision: \"%s\"",
3635 * Compare two values on variable level. We assume zeroes have been
3636 * truncated to no digits.
3639 cmp_var(NumericVar *var1, NumericVar *var2)
3641 return cmp_var_common(var1->digits, var1->ndigits,
3642 var1->weight, var1->sign,
3643 var2->digits, var2->ndigits,
3644 var2->weight, var2->sign);
3648 * cmp_var_common() -
3650 * Main routine of cmp_var(). This function can be used by both
3651 * NumericVar and Numeric.
3654 cmp_var_common(const NumericDigit *var1digits, int var1ndigits,
3655 int var1weight, int var1sign,
3656 const NumericDigit *var2digits, int var2ndigits,
3657 int var2weight, int var2sign)
3659 if (var1ndigits == 0)
3661 if (var2ndigits == 0)
3663 if (var2sign == NUMERIC_NEG)
3667 if (var2ndigits == 0)
3669 if (var1sign == NUMERIC_POS)
3674 if (var1sign == NUMERIC_POS)
3676 if (var2sign == NUMERIC_NEG)
3678 return cmp_abs_common(var1digits, var1ndigits, var1weight,
3679 var2digits, var2ndigits, var2weight);
3682 if (var2sign == NUMERIC_POS)
3685 return cmp_abs_common(var2digits, var2ndigits, var2weight,
3686 var1digits, var1ndigits, var1weight);
3693 * Full version of add functionality on variable level (handling signs).
3694 * result might point to one of the operands too without danger.
3697 add_var(NumericVar *var1, NumericVar *var2, NumericVar *result)
3700 * Decide on the signs of the two variables what to do
3702 if (var1->sign == NUMERIC_POS)
3704 if (var2->sign == NUMERIC_POS)
3707 * Both are positive result = +(ABS(var1) + ABS(var2))
3709 add_abs(var1, var2, result);
3710 result->sign = NUMERIC_POS;
3715 * var1 is positive, var2 is negative Must compare absolute values
3717 switch (cmp_abs(var1, var2))
3721 * ABS(var1) == ABS(var2)
3726 result->dscale = Max(var1->dscale, var2->dscale);
3731 * ABS(var1) > ABS(var2)
3732 * result = +(ABS(var1) - ABS(var2))
3735 sub_abs(var1, var2, result);
3736 result->sign = NUMERIC_POS;
3741 * ABS(var1) < ABS(var2)
3742 * result = -(ABS(var2) - ABS(var1))
3745 sub_abs(var2, var1, result);
3746 result->sign = NUMERIC_NEG;
3753 if (var2->sign == NUMERIC_POS)
3756 * var1 is negative, var2 is positive
3757 * Must compare absolute values
3760 switch (cmp_abs(var1, var2))
3764 * ABS(var1) == ABS(var2)
3769 result->dscale = Max(var1->dscale, var2->dscale);
3774 * ABS(var1) > ABS(var2)
3775 * result = -(ABS(var1) - ABS(var2))
3778 sub_abs(var1, var2, result);
3779 result->sign = NUMERIC_NEG;
3784 * ABS(var1) < ABS(var2)
3785 * result = +(ABS(var2) - ABS(var1))
3788 sub_abs(var2, var1, result);
3789 result->sign = NUMERIC_POS;
3797 * result = -(ABS(var1) + ABS(var2))
3800 add_abs(var1, var2, result);
3801 result->sign = NUMERIC_NEG;
3810 * Full version of sub functionality on variable level (handling signs).
3811 * result might point to one of the operands too without danger.
3814 sub_var(NumericVar *var1, NumericVar *var2, NumericVar *result)
3817 * Decide on the signs of the two variables what to do
3819 if (var1->sign == NUMERIC_POS)
3821 if (var2->sign == NUMERIC_NEG)
3824 * var1 is positive, var2 is negative
3825 * result = +(ABS(var1) + ABS(var2))
3828 add_abs(var1, var2, result);
3829 result->sign = NUMERIC_POS;
3835 * Must compare absolute values
3838 switch (cmp_abs(var1, var2))
3842 * ABS(var1) == ABS(var2)
3847 result->dscale = Max(var1->dscale, var2->dscale);
3852 * ABS(var1) > ABS(var2)
3853 * result = +(ABS(var1) - ABS(var2))
3856 sub_abs(var1, var2, result);
3857 result->sign = NUMERIC_POS;
3862 * ABS(var1) < ABS(var2)
3863 * result = -(ABS(var2) - ABS(var1))
3866 sub_abs(var2, var1, result);
3867 result->sign = NUMERIC_NEG;
3874 if (var2->sign == NUMERIC_NEG)
3878 * Must compare absolute values
3881 switch (cmp_abs(var1, var2))
3885 * ABS(var1) == ABS(var2)
3890 result->dscale = Max(var1->dscale, var2->dscale);
3895 * ABS(var1) > ABS(var2)
3896 * result = -(ABS(var1) - ABS(var2))
3899 sub_abs(var1, var2, result);
3900 result->sign = NUMERIC_NEG;
3905 * ABS(var1) < ABS(var2)
3906 * result = +(ABS(var2) - ABS(var1))
3909 sub_abs(var2, var1, result);
3910 result->sign = NUMERIC_POS;
3917 * var1 is negative, var2 is positive
3918 * result = -(ABS(var1) + ABS(var2))
3921 add_abs(var1, var2, result);
3922 result->sign = NUMERIC_NEG;
3931 * Multiplication on variable level. Product of var1 * var2 is stored
3932 * in result. Result is rounded to no more than rscale fractional digits.
3935 mul_var(NumericVar *var1, NumericVar *var2, NumericVar *result,
3946 NumericDigit *res_digits;
3952 /* copy these values into local vars for speed in inner loop */
3953 int var1ndigits = var1->ndigits;
3954 int var2ndigits = var2->ndigits;
3955 NumericDigit *var1digits = var1->digits;
3956 NumericDigit *var2digits = var2->digits;
3958 if (var1ndigits == 0 || var2ndigits == 0)
3960 /* one or both inputs is zero; so is result */
3962 result->dscale = rscale;
3966 /* Determine result sign and (maximum possible) weight */
3967 if (var1->sign == var2->sign)
3968 res_sign = NUMERIC_POS;
3970 res_sign = NUMERIC_NEG;
3971 res_weight = var1->weight + var2->weight + 2;
3974 * Determine number of result digits to compute. If the exact result
3975 * would have more than rscale fractional digits, truncate the computation
3976 * with MUL_GUARD_DIGITS guard digits. We do that by pretending that one
3977 * or both inputs have fewer digits than they really do.
3979 res_ndigits = var1ndigits + var2ndigits + 1;
3980 maxdigits = res_weight + 1 + (rscale * DEC_DIGITS) + MUL_GUARD_DIGITS;
3981 if (res_ndigits > maxdigits)
3985 /* no useful precision at all in the result... */
3987 result->dscale = rscale;
3990 /* force maxdigits odd so that input ndigits can be equal */
3991 if ((maxdigits & 1) == 0)
3993 if (var1ndigits > var2ndigits)
3995 var1ndigits -= res_ndigits - maxdigits;
3996 if (var1ndigits < var2ndigits)
3997 var1ndigits = var2ndigits = (var1ndigits + var2ndigits) / 2;
4001 var2ndigits -= res_ndigits - maxdigits;
4002 if (var2ndigits < var1ndigits)
4003 var1ndigits = var2ndigits = (var1ndigits + var2ndigits) / 2;
4005 res_ndigits = maxdigits;
4006 Assert(res_ndigits == var1ndigits + var2ndigits + 1);
4010 * We do the arithmetic in an array "dig[]" of signed int's. Since
4011 * INT_MAX is noticeably larger than NBASE*NBASE, this gives us headroom
4012 * to avoid normalizing carries immediately.
4014 * maxdig tracks the maximum possible value of any dig[] entry; when this
4015 * threatens to exceed INT_MAX, we take the time to propagate carries. To
4016 * avoid overflow in maxdig itself, it actually represents the max
4017 * possible value divided by NBASE-1.
4019 dig = (int *) palloc0(res_ndigits * sizeof(int));
4022 ri = res_ndigits - 1;
4023 for (i1 = var1ndigits - 1; i1 >= 0; ri--, i1--)
4025 int var1digit = var1digits[i1];
4030 /* Time to normalize? */
4031 maxdig += var1digit;
4032 if (maxdig > INT_MAX / (NBASE - 1))
4036 for (i = res_ndigits - 1; i >= 0; i--)
4038 newdig = dig[i] + carry;
4039 if (newdig >= NBASE)
4041 carry = newdig / NBASE;
4042 newdig -= carry * NBASE;
4049 /* Reset maxdig to indicate new worst-case */
4050 maxdig = 1 + var1digit;
4053 /* Add appropriate multiple of var2 into the accumulator */
4055 for (i2 = var2ndigits - 1; i2 >= 0; i2--)
4056 dig[i--] += var1digit * var2digits[i2];
4060 * Now we do a final carry propagation pass to normalize the result, which
4061 * we combine with storing the result digits into the output. Note that
4062 * this is still done at full precision w/guard digits.
4064 alloc_var(result, res_ndigits);
4065 res_digits = result->digits;
4067 for (i = res_ndigits - 1; i >= 0; i--)
4069 newdig = dig[i] + carry;
4070 if (newdig >= NBASE)
4072 carry = newdig / NBASE;
4073 newdig -= carry * NBASE;
4077 res_digits[i] = newdig;
4084 * Finally, round the result to the requested precision.
4086 result->weight = res_weight;
4087 result->sign = res_sign;
4089 /* Round to target rscale (and set result->dscale) */
4090 round_var(result, rscale);
4092 /* Strip leading and trailing zeroes */
4100 * Division on variable level. Quotient of var1 / var2 is stored in result.
4101 * The quotient is figured to exactly rscale fractional digits.
4102 * If round is true, it is rounded at the rscale'th digit; if false, it
4103 * is truncated (towards zero) at that digit.
4106 div_var(NumericVar *var1, NumericVar *var2, NumericVar *result,
4107 int rscale, bool round)
4117 NumericDigit *dividend;
4118 NumericDigit *divisor;
4119 NumericDigit *res_digits;
4123 /* copy these values into local vars for speed in inner loop */
4124 int var1ndigits = var1->ndigits;
4125 int var2ndigits = var2->ndigits;
4128 * First of all division by zero check; we must not be handed an
4129 * unnormalized divisor.
4131 if (var2ndigits == 0 || var2->digits[0] == 0)
4133 (errcode(ERRCODE_DIVISION_BY_ZERO),
4134 errmsg("division by zero")));
4137 * Now result zero check
4139 if (var1ndigits == 0)
4142 result->dscale = rscale;
4147 * Determine the result sign, weight and number of digits to calculate.
4148 * The weight figured here is correct if the emitted quotient has no
4149 * leading zero digits; otherwise strip_var() will fix things up.
4151 if (var1->sign == var2->sign)
4152 res_sign = NUMERIC_POS;
4154 res_sign = NUMERIC_NEG;
4155 res_weight = var1->weight - var2->weight;
4156 /* The number of accurate result digits we need to produce: */
4157 res_ndigits = res_weight + 1 + (rscale + DEC_DIGITS - 1) / DEC_DIGITS;
4158 /* ... but always at least 1 */
4159 res_ndigits = Max(res_ndigits, 1);
4160 /* If rounding needed, figure one more digit to ensure correct result */
4164 * The working dividend normally requires res_ndigits + var2ndigits
4165 * digits, but make it at least var1ndigits so we can load all of var1
4166 * into it. (There will be an additional digit dividend[0] in the
4167 * dividend space, but for consistency with Knuth's notation we don't
4168 * count that in div_ndigits.)
4170 div_ndigits = res_ndigits + var2ndigits;
4171 div_ndigits = Max(div_ndigits, var1ndigits);
4174 * We need a workspace with room for the working dividend (div_ndigits+1
4175 * digits) plus room for the possibly-normalized divisor (var2ndigits
4176 * digits). It is convenient also to have a zero at divisor[0] with
4177 * the actual divisor data in divisor[1 .. var2ndigits]. Transferring the
4178 * digits into the workspace also allows us to realloc the result (which
4179 * might be the same as either input var) before we begin the main loop.
4180 * Note that we use palloc0 to ensure that divisor[0], dividend[0], and
4181 * any additional dividend positions beyond var1ndigits, start out 0.
4183 dividend = (NumericDigit *)
4184 palloc0((div_ndigits + var2ndigits + 2) * sizeof(NumericDigit));
4185 divisor = dividend + (div_ndigits + 1);
4186 memcpy(dividend + 1, var1->digits, var1ndigits * sizeof(NumericDigit));
4187 memcpy(divisor + 1, var2->digits, var2ndigits * sizeof(NumericDigit));
4190 * Now we can realloc the result to hold the generated quotient digits.
4192 alloc_var(result, res_ndigits);
4193 res_digits = result->digits;
4195 if (var2ndigits == 1)
4198 * If there's only a single divisor digit, we can use a fast path
4199 * (cf. Knuth section 4.3.1 exercise 16).
4201 divisor1 = divisor[1];
4203 for (i = 0; i < res_ndigits; i++)
4205 carry = carry * NBASE + dividend[i + 1];
4206 res_digits[i] = carry / divisor1;
4207 carry = carry % divisor1;
4213 * The full multiple-place algorithm is taken from Knuth volume 2,
4216 * We need the first divisor digit to be >= NBASE/2. If it isn't,
4217 * make it so by scaling up both the divisor and dividend by the
4218 * factor "d". (The reason for allocating dividend[0] above is to
4219 * leave room for possible carry here.)
4221 if (divisor[1] < HALF_NBASE)
4223 int d = NBASE / (divisor[1] + 1);
4226 for (i = var2ndigits; i > 0; i--)
4228 carry += divisor[i] * d;
4229 divisor[i] = carry % NBASE;
4230 carry = carry / NBASE;
4234 /* at this point only var1ndigits of dividend can be nonzero */
4235 for (i = var1ndigits; i >= 0; i--)
4237 carry += dividend[i] * d;
4238 dividend[i] = carry % NBASE;
4239 carry = carry / NBASE;
4242 Assert(divisor[1] >= HALF_NBASE);
4244 /* First 2 divisor digits are used repeatedly in main loop */
4245 divisor1 = divisor[1];
4246 divisor2 = divisor[2];
4249 * Begin the main loop. Each iteration of this loop produces the
4250 * j'th quotient digit by dividing dividend[j .. j + var2ndigits]
4251 * by the divisor; this is essentially the same as the common manual
4252 * procedure for long division.
4254 for (j = 0; j < res_ndigits; j++)
4256 /* Estimate quotient digit from the first two dividend digits */
4257 int next2digits = dividend[j] * NBASE + dividend[j+1];
4261 * If next2digits are 0, then quotient digit must be 0 and there's
4262 * no need to adjust the working dividend. It's worth testing
4263 * here to fall out ASAP when processing trailing zeroes in
4266 if (next2digits == 0)
4272 if (dividend[j] == divisor1)
4275 qhat = next2digits / divisor1;
4277 * Adjust quotient digit if it's too large. Knuth proves that
4278 * after this step, the quotient digit will be either correct
4279 * or just one too large. (Note: it's OK to use dividend[j+2]
4280 * here because we know the divisor length is at least 2.)
4282 while (divisor2 * qhat >
4283 (next2digits - qhat * divisor1) * NBASE + dividend[j+2])
4286 /* As above, need do nothing more when quotient digit is 0 */
4290 * Multiply the divisor by qhat, and subtract that from the
4291 * working dividend. "carry" tracks the multiplication,
4292 * "borrow" the subtraction (could we fold these together?)
4296 for (i = var2ndigits; i >= 0; i--)
4298 carry += divisor[i] * qhat;
4299 borrow -= carry % NBASE;
4300 carry = carry / NBASE;
4301 borrow += dividend[j + i];
4304 dividend[j + i] = borrow + NBASE;
4309 dividend[j + i] = borrow;
4316 * If we got a borrow out of the top dividend digit, then
4317 * indeed qhat was one too large. Fix it, and add back the
4318 * divisor to correct the working dividend. (Knuth proves
4319 * that this will occur only about 3/NBASE of the time; hence,
4320 * it's a good idea to test this code with small NBASE to be
4321 * sure this section gets exercised.)
4327 for (i = var2ndigits; i >= 0; i--)
4329 carry += dividend[j + i] + divisor[i];
4332 dividend[j + i] = carry - NBASE;
4337 dividend[j + i] = carry;
4341 /* A carry should occur here to cancel the borrow above */
4346 /* And we're done with this quotient digit */
4347 res_digits[j] = qhat;
4354 * Finally, round or truncate the result to the requested precision.
4356 result->weight = res_weight;
4357 result->sign = res_sign;
4359 /* Round or truncate to target rscale (and set result->dscale) */
4361 round_var(result, rscale);
4363 trunc_var(result, rscale);
4365 /* Strip leading and trailing zeroes */
4373 * This has the same API as div_var, but is implemented using the division
4374 * algorithm from the "FM" library, rather than Knuth's schoolbook-division
4375 * approach. This is significantly faster but can produce inaccurate
4376 * results, because it sometimes has to propagate rounding to the left,
4377 * and so we can never be entirely sure that we know the requested digits
4378 * exactly. We compute DIV_GUARD_DIGITS extra digits, but there is
4379 * no certainty that that's enough. We use this only in the transcendental
4380 * function calculation routines, where everything is approximate anyway.
4383 div_var_fast(NumericVar *var1, NumericVar *var2, NumericVar *result,
4384 int rscale, bool round)
4394 NumericDigit *res_digits;
4402 /* copy these values into local vars for speed in inner loop */
4403 int var1ndigits = var1->ndigits;
4404 int var2ndigits = var2->ndigits;
4405 NumericDigit *var1digits = var1->digits;
4406 NumericDigit *var2digits = var2->digits;
4409 * First of all division by zero check; we must not be handed an
4410 * unnormalized divisor.
4412 if (var2ndigits == 0 || var2digits[0] == 0)
4414 (errcode(ERRCODE_DIVISION_BY_ZERO),
4415 errmsg("division by zero")));
4418 * Now result zero check
4420 if (var1ndigits == 0)
4423 result->dscale = rscale;
4428 * Determine the result sign, weight and number of digits to calculate
4430 if (var1->sign == var2->sign)
4431 res_sign = NUMERIC_POS;
4433 res_sign = NUMERIC_NEG;
4434 res_weight = var1->weight - var2->weight + 1;
4435 /* The number of accurate result digits we need to produce: */
4436 div_ndigits = res_weight + 1 + (rscale + DEC_DIGITS - 1) / DEC_DIGITS;
4437 /* Add guard digits for roundoff error */
4438 div_ndigits += DIV_GUARD_DIGITS;
4439 if (div_ndigits < DIV_GUARD_DIGITS)
4440 div_ndigits = DIV_GUARD_DIGITS;
4441 /* Must be at least var1ndigits, too, to simplify data-loading loop */
4442 if (div_ndigits < var1ndigits)
4443 div_ndigits = var1ndigits;
4446 * We do the arithmetic in an array "div[]" of signed int's. Since
4447 * INT_MAX is noticeably larger than NBASE*NBASE, this gives us headroom
4448 * to avoid normalizing carries immediately.
4450 * We start with div[] containing one zero digit followed by the
4451 * dividend's digits (plus appended zeroes to reach the desired precision
4452 * including guard digits). Each step of the main loop computes an
4453 * (approximate) quotient digit and stores it into div[], removing one
4454 * position of dividend space. A final pass of carry propagation takes
4455 * care of any mistaken quotient digits.
4457 div = (int *) palloc0((div_ndigits + 1) * sizeof(int));
4458 for (i = 0; i < var1ndigits; i++)
4459 div[i + 1] = var1digits[i];
4462 * We estimate each quotient digit using floating-point arithmetic, taking
4463 * the first four digits of the (current) dividend and divisor. This must
4464 * be float to avoid overflow.
4466 fdivisor = (double) var2digits[0];
4467 for (i = 1; i < 4; i++)
4470 if (i < var2ndigits)
4471 fdivisor += (double) var2digits[i];
4473 fdivisorinverse = 1.0 / fdivisor;
4476 * maxdiv tracks the maximum possible absolute value of any div[] entry;
4477 * when this threatens to exceed INT_MAX, we take the time to propagate
4478 * carries. To avoid overflow in maxdiv itself, it actually represents
4479 * the max possible abs. value divided by NBASE-1.
4484 * Outer loop computes next quotient digit, which will go into div[qi]
4486 for (qi = 0; qi < div_ndigits; qi++)
4488 /* Approximate the current dividend value */
4489 fdividend = (double) div[qi];
4490 for (i = 1; i < 4; i++)
4493 if (qi + i <= div_ndigits)
4494 fdividend += (double) div[qi + i];
4496 /* Compute the (approximate) quotient digit */
4497 fquotient = fdividend * fdivisorinverse;
4498 qdigit = (fquotient >= 0.0) ? ((int) fquotient) :
4499 (((int) fquotient) - 1); /* truncate towards -infinity */
4503 /* Do we need to normalize now? */
4504 maxdiv += Abs(qdigit);
4505 if (maxdiv > INT_MAX / (NBASE - 1))
4509 for (i = div_ndigits; i > qi; i--)
4511 newdig = div[i] + carry;
4514 carry = -((-newdig - 1) / NBASE) - 1;
4515 newdig -= carry * NBASE;
4517 else if (newdig >= NBASE)
4519 carry = newdig / NBASE;
4520 newdig -= carry * NBASE;
4526 newdig = div[qi] + carry;
4530 * All the div[] digits except possibly div[qi] are now in the
4533 maxdiv = Abs(newdig) / (NBASE - 1);
4534 maxdiv = Max(maxdiv, 1);
4537 * Recompute the quotient digit since new info may have
4538 * propagated into the top four dividend digits
4540 fdividend = (double) div[qi];
4541 for (i = 1; i < 4; i++)
4544 if (qi + i <= div_ndigits)
4545 fdividend += (double) div[qi + i];
4547 /* Compute the (approximate) quotient digit */
4548 fquotient = fdividend * fdivisorinverse;
4549 qdigit = (fquotient >= 0.0) ? ((int) fquotient) :
4550 (((int) fquotient) - 1); /* truncate towards -infinity */
4551 maxdiv += Abs(qdigit);
4554 /* Subtract off the appropriate multiple of the divisor */
4557 int istop = Min(var2ndigits, div_ndigits - qi + 1);
4559 for (i = 0; i < istop; i++)
4560 div[qi + i] -= qdigit * var2digits[i];
4565 * The dividend digit we are about to replace might still be nonzero.
4566 * Fold it into the next digit position. We don't need to worry about
4567 * overflow here since this should nearly cancel with the subtraction
4570 div[qi + 1] += div[qi] * NBASE;
4576 * Approximate and store the last quotient digit (div[div_ndigits])
4578 fdividend = (double) div[qi];
4579 for (i = 1; i < 4; i++)
4581 fquotient = fdividend * fdivisorinverse;
4582 qdigit = (fquotient >= 0.0) ? ((int) fquotient) :
4583 (((int) fquotient) - 1); /* truncate towards -infinity */
4587 * Now we do a final carry propagation pass to normalize the result, which
4588 * we combine with storing the result digits into the output. Note that
4589 * this is still done at full precision w/guard digits.
4591 alloc_var(result, div_ndigits + 1);
4592 res_digits = result->digits;
4594 for (i = div_ndigits; i >= 0; i--)
4596 newdig = div[i] + carry;
4599 carry = -((-newdig - 1) / NBASE) - 1;
4600 newdig -= carry * NBASE;
4602 else if (newdig >= NBASE)
4604 carry = newdig / NBASE;
4605 newdig -= carry * NBASE;
4609 res_digits[i] = newdig;
4616 * Finally, round the result to the requested precision.
4618 result->weight = res_weight;
4619 result->sign = res_sign;
4621 /* Round to target rscale (and set result->dscale) */
4623 round_var(result, rscale);
4625 trunc_var(result, rscale);
4627 /* Strip leading and trailing zeroes */
4633 * Default scale selection for division
4635 * Returns the appropriate result scale for the division result.
4638 select_div_scale(NumericVar *var1, NumericVar *var2)
4644 NumericDigit firstdigit1,
4649 * The result scale of a division isn't specified in any SQL standard. For
4650 * PostgreSQL we select a result scale that will give at least
4651 * NUMERIC_MIN_SIG_DIGITS significant digits, so that numeric gives a
4652 * result no less accurate than float8; but use a scale not less than
4653 * either input's display scale.
4656 /* Get the actual (normalized) weight and first digit of each input */
4658 weight1 = 0; /* values to use if var1 is zero */
4660 for (i = 0; i < var1->ndigits; i++)
4662 firstdigit1 = var1->digits[i];
4663 if (firstdigit1 != 0)
4665 weight1 = var1->weight - i;
4670 weight2 = 0; /* values to use if var2 is zero */
4672 for (i = 0; i < var2->ndigits; i++)
4674 firstdigit2 = var2->digits[i];
4675 if (firstdigit2 != 0)
4677 weight2 = var2->weight - i;
4683 * Estimate weight of quotient. If the two first digits are equal, we
4684 * can't be sure, but assume that var1 is less than var2.
4686 qweight = weight1 - weight2;
4687 if (firstdigit1 <= firstdigit2)
4690 /* Select result scale */
4691 rscale = NUMERIC_MIN_SIG_DIGITS - qweight * DEC_DIGITS;
4692 rscale = Max(rscale, var1->dscale);
4693 rscale = Max(rscale, var2->dscale);
4694 rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
4695 rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
4704 * Calculate the modulo of two numerics at variable level
4707 mod_var(NumericVar *var1, NumericVar *var2, NumericVar *result)
4714 * We do this using the equation
4715 * mod(x,y) = x - trunc(x/y)*y
4716 * div_var can be persuaded to give us trunc(x/y) directly.
4719 div_var(var1, var2, &tmp, 0, false);
4721 mul_var(var2, &tmp, &tmp, var2->dscale);
4723 sub_var(var1, &tmp, result);
4732 * Return the smallest integer greater than or equal to the argument
4736 ceil_var(NumericVar *var, NumericVar *result)
4741 set_var_from_var(var, &tmp);
4745 if (var->sign == NUMERIC_POS && cmp_var(var, &tmp) != 0)
4746 add_var(&tmp, &const_one, &tmp);
4748 set_var_from_var(&tmp, result);
4756 * Return the largest integer equal to or less than the argument
4760 floor_var(NumericVar *var, NumericVar *result)
4765 set_var_from_var(var, &tmp);
4769 if (var->sign == NUMERIC_NEG && cmp_var(var, &tmp) != 0)
4770 sub_var(&tmp, &const_one, &tmp);
4772 set_var_from_var(&tmp, result);
4780 * Compute the square root of x using Newton's algorithm
4783 sqrt_var(NumericVar *arg, NumericVar *result, int rscale)
4787 NumericVar last_val;
4791 local_rscale = rscale + 8;
4793 stat = cmp_var(arg, &const_zero);
4797 result->dscale = rscale;
4802 * SQL2003 defines sqrt() in terms of power, so we need to emit the right
4803 * SQLSTATE error code if the operand is negative.
4807 (errcode(ERRCODE_INVALID_ARGUMENT_FOR_POWER_FUNCTION),
4808 errmsg("cannot take square root of a negative number")));
4812 init_var(&last_val);
4814 /* Copy arg in case it is the same var as result */
4815 set_var_from_var(arg, &tmp_arg);
4818 * Initialize the result to the first guess
4820 alloc_var(result, 1);
4821 result->digits[0] = tmp_arg.digits[0] / 2;
4822 if (result->digits[0] == 0)
4823 result->digits[0] = 1;
4824 result->weight = tmp_arg.weight / 2;
4825 result->sign = NUMERIC_POS;
4827 set_var_from_var(result, &last_val);
4831 div_var_fast(&tmp_arg, result, &tmp_val, local_rscale, true);
4833 add_var(result, &tmp_val, result);
4834 mul_var(result, &const_zero_point_five, result, local_rscale);
4836 if (cmp_var(&last_val, result) == 0)
4838 set_var_from_var(result, &last_val);
4841 free_var(&last_val);
4845 /* Round to requested precision */
4846 round_var(result, rscale);
4853 * Raise e to the power of x
4856 exp_var(NumericVar *arg, NumericVar *result, int rscale)
4864 * We separate the integral and fraction parts of x, then compute
4865 * e^x = e^xint * e^xfrac
4866 * where e = exp(1) and e^xfrac = exp(xfrac) are computed by
4867 * exp_var_internal; the limited range of inputs allows that routine
4868 * to do a good job with a simple Taylor series. Raising e^xint is
4869 * done by repeated multiplications in power_var_int.
4874 set_var_from_var(arg, &x);
4876 if (x.sign == NUMERIC_NEG)
4879 x.sign = NUMERIC_POS;
4882 /* Extract the integer part, remove it from x */
4884 while (x.weight >= 0)
4889 xintval += x.digits[0];
4894 /* Guard against overflow */
4895 if (xintval >= NUMERIC_MAX_RESULT_SCALE * 3)
4897 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
4898 errmsg("argument for function \"exp\" too big")));
4901 /* Select an appropriate scale for internal calculation */
4902 local_rscale = rscale + MUL_GUARD_DIGITS * 2;
4904 /* Compute e^xfrac */
4905 exp_var_internal(&x, result, local_rscale);
4907 /* If there's an integer part, multiply by e^xint */
4913 exp_var_internal(&const_one, &e, local_rscale);
4914 power_var_int(&e, xintval, &e, local_rscale);
4915 mul_var(&e, result, result, local_rscale);
4919 /* Compensate for input sign, and round to requested rscale */
4921 div_var_fast(&const_one, result, result, rscale, true);
4923 round_var(result, rscale);
4930 * exp_var_internal() -
4932 * Raise e to the power of x, where 0 <= x <= 1
4934 * NB: the result should be good to at least rscale digits, but it has
4935 * *not* been rounded off; the caller must do that if wanted.
4938 exp_var_internal(NumericVar *arg, NumericVar *result, int rscale)
4954 set_var_from_var(arg, &x);
4956 Assert(x.sign == NUMERIC_POS);
4958 local_rscale = rscale + 8;
4960 /* Reduce input into range 0 <= x <= 0.01 */
4961 while (cmp_var(&x, &const_zero_point_01) > 0)
4965 mul_var(&x, &const_zero_point_five, &x, x.dscale + 1);
4969 * Use the Taylor series
4971 * exp(x) = 1 + x + x^2/2! + x^3/3! + ...
4973 * Given the limited range of x, this should converge reasonably quickly.
4974 * We run the series until the terms fall below the local_rscale limit.
4976 add_var(&const_one, &x, result);
4977 set_var_from_var(&x, &xpow);
4978 set_var_from_var(&const_one, &ifac);
4979 set_var_from_var(&const_one, &ni);
4983 add_var(&ni, &const_one, &ni);
4984 mul_var(&xpow, &x, &xpow, local_rscale);
4985 mul_var(&ifac, &ni, &ifac, 0);
4986 div_var_fast(&xpow, &ifac, &elem, local_rscale, true);
4988 if (elem.ndigits == 0)
4991 add_var(result, &elem, result);
4994 /* Compensate for argument range reduction */
4996 mul_var(result, result, result, local_rscale);
5009 * Compute the natural log of x
5012 ln_var(NumericVar *arg, NumericVar *result, int rscale)
5022 cmp = cmp_var(arg, &const_zero);
5025 (errcode(ERRCODE_INVALID_ARGUMENT_FOR_LOG),
5026 errmsg("cannot take logarithm of zero")));
5029 (errcode(ERRCODE_INVALID_ARGUMENT_FOR_LOG),
5030 errmsg("cannot take logarithm of a negative number")));
5032 local_rscale = rscale + 8;
5040 set_var_from_var(arg, &x);
5041 set_var_from_var(&const_two, &fact);
5043 /* Reduce input into range 0.9 < x < 1.1 */
5044 while (cmp_var(&x, &const_zero_point_nine) <= 0)
5047 sqrt_var(&x, &x, local_rscale);
5048 mul_var(&fact, &const_two, &fact, 0);
5050 while (cmp_var(&x, &const_one_point_one) >= 0)
5053 sqrt_var(&x, &x, local_rscale);
5054 mul_var(&fact, &const_two, &fact, 0);
5058 * We use the Taylor series for 0.5 * ln((1+z)/(1-z)),
5060 * z + z^3/3 + z^5/5 + ...
5062 * where z = (x-1)/(x+1) is in the range (approximately) -0.053 .. 0.048
5063 * due to the above range-reduction of x.
5065 * The convergence of this is not as fast as one would like, but is
5066 * tolerable given that z is small.
5068 sub_var(&x, &const_one, result);
5069 add_var(&x, &const_one, &elem);
5070 div_var_fast(result, &elem, result, local_rscale, true);
5071 set_var_from_var(result, &xx);
5072 mul_var(result, result, &x, local_rscale);
5074 set_var_from_var(&const_one, &ni);
5078 add_var(&ni, &const_two, &ni);
5079 mul_var(&xx, &x, &xx, local_rscale);
5080 div_var_fast(&xx, &ni, &elem, local_rscale, true);
5082 if (elem.ndigits == 0)
5085 add_var(result, &elem, result);
5087 if (elem.weight < (result->weight - local_rscale * 2 / DEC_DIGITS))
5091 /* Compensate for argument range reduction, round to requested rscale */
5092 mul_var(result, &fact, result, rscale);
5105 * Compute the logarithm of num in a given base.
5107 * Note: this routine chooses dscale of the result.
5110 log_var(NumericVar *base, NumericVar *num, NumericVar *result)
5121 /* Set scale for ln() calculations --- compare numeric_ln() */
5123 /* Approx decimal digits before decimal point */
5124 dec_digits = (num->weight + 1) * DEC_DIGITS;
5127 rscale = NUMERIC_MIN_SIG_DIGITS - (int) log10(dec_digits - 1);
5128 else if (dec_digits < 1)
5129 rscale = NUMERIC_MIN_SIG_DIGITS - (int) log10(1 - dec_digits);
5131 rscale = NUMERIC_MIN_SIG_DIGITS;
5133 rscale = Max(rscale, base->dscale);
5134 rscale = Max(rscale, num->dscale);
5135 rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
5136 rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
5138 local_rscale = rscale + 8;
5140 /* Form natural logarithms */
5141 ln_var(base, &ln_base, local_rscale);
5142 ln_var(num, &ln_num, local_rscale);
5144 ln_base.dscale = rscale;
5145 ln_num.dscale = rscale;
5147 /* Select scale for division result */
5148 rscale = select_div_scale(&ln_num, &ln_base);
5150 div_var_fast(&ln_num, &ln_base, result, rscale, true);
5160 * Raise base to the power of exp
5162 * Note: this routine chooses dscale of the result.
5165 power_var(NumericVar *base, NumericVar *exp, NumericVar *result)
5174 /* If exp can be represented as an integer, use power_var_int */
5175 if (exp->ndigits == 0 || exp->ndigits <= exp->weight + 1)
5177 /* exact integer, but does it fit in int? */
5181 /* must copy because numericvar_to_int8() scribbles on input */
5183 set_var_from_var(exp, &x);
5184 if (numericvar_to_int8(&x, &expval64))
5186 int expval = (int) expval64;
5188 /* Test for overflow by reverse-conversion. */
5189 if ((int64) expval == expval64)
5191 /* Okay, select rscale */
5192 rscale = NUMERIC_MIN_SIG_DIGITS;
5193 rscale = Max(rscale, base->dscale);
5194 rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
5195 rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
5197 power_var_int(base, expval, result, rscale);
5207 * This avoids log(0) for cases of 0 raised to a non-integer.
5208 * 0 ^ 0 handled by power_var_int().
5210 if (cmp_var(base, &const_zero) == 0)
5212 set_var_from_var(&const_zero, result);
5213 result->dscale = NUMERIC_MIN_SIG_DIGITS; /* no need to round */
5220 /* Set scale for ln() calculation --- need extra accuracy here */
5222 /* Approx decimal digits before decimal point */
5223 dec_digits = (base->weight + 1) * DEC_DIGITS;
5226 rscale = NUMERIC_MIN_SIG_DIGITS * 2 - (int) log10(dec_digits - 1);
5227 else if (dec_digits < 1)
5228 rscale = NUMERIC_MIN_SIG_DIGITS * 2 - (int) log10(1 - dec_digits);
5230 rscale = NUMERIC_MIN_SIG_DIGITS * 2;
5232 rscale = Max(rscale, base->dscale * 2);
5233 rscale = Max(rscale, exp->dscale * 2);
5234 rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE * 2);
5235 rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE * 2);
5237 local_rscale = rscale + 8;
5239 ln_var(base, &ln_base, local_rscale);
5241 mul_var(&ln_base, exp, &ln_num, local_rscale);
5243 /* Set scale for exp() -- compare numeric_exp() */
5245 /* convert input to float8, ignoring overflow */
5246 val = numericvar_to_double_no_overflow(&ln_num);
5249 * log10(result) = num * log10(e), so this is approximately the weight:
5251 val *= 0.434294481903252;
5253 /* limit to something that won't cause integer overflow */
5254 val = Max(val, -NUMERIC_MAX_RESULT_SCALE);
5255 val = Min(val, NUMERIC_MAX_RESULT_SCALE);
5257 rscale = NUMERIC_MIN_SIG_DIGITS - (int) val;
5258 rscale = Max(rscale, base->dscale);
5259 rscale = Max(rscale, exp->dscale);
5260 rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
5261 rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
5263 exp_var(&ln_num, result, rscale);
5272 * Raise base to the power of exp, where exp is an integer.
5275 power_var_int(NumericVar *base, int exp, NumericVar *result, int rscale)
5278 NumericVar base_prod;
5285 * While 0 ^ 0 can be either 1 or indeterminate (error), we
5286 * treat it as 1 because most programming languages do this.
5287 * SQL:2003 also requires a return value of 1.
5288 * http://en.wikipedia.org/wiki/Exponentiation#Zero_to_the_zero_power
5290 set_var_from_var(&const_one, result);
5291 result->dscale = rscale; /* no need to round */
5294 set_var_from_var(base, result);
5295 round_var(result, rscale);
5298 div_var(&const_one, base, result, rscale, true);
5301 mul_var(base, base, result, rscale);
5308 * The general case repeatedly multiplies base according to the bit
5309 * pattern of exp. We do the multiplications with some extra precision.
5314 local_rscale = rscale + MUL_GUARD_DIGITS * 2;
5316 init_var(&base_prod);
5317 set_var_from_var(base, &base_prod);
5320 set_var_from_var(base, result);
5322 set_var_from_var(&const_one, result);
5324 while ((exp >>= 1) > 0)
5326 mul_var(&base_prod, &base_prod, &base_prod, local_rscale);
5328 mul_var(&base_prod, result, result, local_rscale);
5331 free_var(&base_prod);
5333 /* Compensate for input sign, and round to requested rscale */
5335 div_var_fast(&const_one, result, result, rscale, true);
5337 round_var(result, rscale);
5341 /* ----------------------------------------------------------------------
5343 * Following are the lowest level functions that operate unsigned
5344 * on the variable level
5346 * ----------------------------------------------------------------------
5353 * Compare the absolute values of var1 and var2
5354 * Returns: -1 for ABS(var1) < ABS(var2)
5355 * 0 for ABS(var1) == ABS(var2)
5356 * 1 for ABS(var1) > ABS(var2)
5360 cmp_abs(NumericVar *var1, NumericVar *var2)
5362 return cmp_abs_common(var1->digits, var1->ndigits, var1->weight,
5363 var2->digits, var2->ndigits, var2->weight);
5367 * cmp_abs_common() -
5369 * Main routine of cmp_abs(). This function can be used by both
5370 * NumericVar and Numeric.
5374 cmp_abs_common(const NumericDigit *var1digits, int var1ndigits, int var1weight,
5375 const NumericDigit *var2digits, int var2ndigits, int var2weight)
5380 /* Check any digits before the first common digit */
5382 while (var1weight > var2weight && i1 < var1ndigits)
5384 if (var1digits[i1++] != 0)
5388 while (var2weight > var1weight && i2 < var2ndigits)
5390 if (var2digits[i2++] != 0)
5395 /* At this point, either w1 == w2 or we've run out of digits */
5397 if (var1weight == var2weight)
5399 while (i1 < var1ndigits && i2 < var2ndigits)
5401 int stat = var1digits[i1++] - var2digits[i2++];
5413 * At this point, we've run out of digits on one side or the other; so any
5414 * remaining nonzero digits imply that side is larger
5416 while (i1 < var1ndigits)
5418 if (var1digits[i1++] != 0)
5421 while (i2 < var2ndigits)
5423 if (var2digits[i2++] != 0)
5434 * Add the absolute values of two variables into result.
5435 * result might point to one of the operands without danger.
5438 add_abs(NumericVar *var1, NumericVar *var2, NumericVar *result)
5440 NumericDigit *res_buf;
5441 NumericDigit *res_digits;
5453 /* copy these values into local vars for speed in inner loop */
5454 int var1ndigits = var1->ndigits;
5455 int var2ndigits = var2->ndigits;
5456 NumericDigit *var1digits = var1->digits;
5457 NumericDigit *var2digits = var2->digits;
5459 res_weight = Max(var1->weight, var2->weight) + 1;
5461 res_dscale = Max(var1->dscale, var2->dscale);
5463 /* Note: here we are figuring rscale in base-NBASE digits */
5464 rscale1 = var1->ndigits - var1->weight - 1;
5465 rscale2 = var2->ndigits - var2->weight - 1;
5466 res_rscale = Max(rscale1, rscale2);
5468 res_ndigits = res_rscale + res_weight + 1;
5469 if (res_ndigits <= 0)
5472 res_buf = digitbuf_alloc(res_ndigits + 1);
5473 res_buf[0] = 0; /* spare digit for later rounding */
5474 res_digits = res_buf + 1;
5476 i1 = res_rscale + var1->weight + 1;
5477 i2 = res_rscale + var2->weight + 1;
5478 for (i = res_ndigits - 1; i >= 0; i--)
5482 if (i1 >= 0 && i1 < var1ndigits)
5483 carry += var1digits[i1];
5484 if (i2 >= 0 && i2 < var2ndigits)
5485 carry += var2digits[i2];
5489 res_digits[i] = carry - NBASE;
5494 res_digits[i] = carry;
5499 Assert(carry == 0); /* else we failed to allow for carry out */
5501 digitbuf_free(result->buf);
5502 result->ndigits = res_ndigits;
5503 result->buf = res_buf;
5504 result->digits = res_digits;
5505 result->weight = res_weight;
5506 result->dscale = res_dscale;
5508 /* Remove leading/trailing zeroes */
5516 * Subtract the absolute value of var2 from the absolute value of var1
5517 * and store in result. result might point to one of the operands
5520 * ABS(var1) MUST BE GREATER OR EQUAL ABS(var2) !!!
5523 sub_abs(NumericVar *var1, NumericVar *var2, NumericVar *result)
5525 NumericDigit *res_buf;
5526 NumericDigit *res_digits;
5538 /* copy these values into local vars for speed in inner loop */
5539 int var1ndigits = var1->ndigits;
5540 int var2ndigits = var2->ndigits;
5541 NumericDigit *var1digits = var1->digits;
5542 NumericDigit *var2digits = var2->digits;
5544 res_weight = var1->weight;
5546 res_dscale = Max(var1->dscale, var2->dscale);
5548 /* Note: here we are figuring rscale in base-NBASE digits */
5549 rscale1 = var1->ndigits - var1->weight - 1;
5550 rscale2 = var2->ndigits - var2->weight - 1;
5551 res_rscale = Max(rscale1, rscale2);
5553 res_ndigits = res_rscale + res_weight + 1;
5554 if (res_ndigits <= 0)
5557 res_buf = digitbuf_alloc(res_ndigits + 1);
5558 res_buf[0] = 0; /* spare digit for later rounding */
5559 res_digits = res_buf + 1;
5561 i1 = res_rscale + var1->weight + 1;
5562 i2 = res_rscale + var2->weight + 1;
5563 for (i = res_ndigits - 1; i >= 0; i--)
5567 if (i1 >= 0 && i1 < var1ndigits)
5568 borrow += var1digits[i1];
5569 if (i2 >= 0 && i2 < var2ndigits)
5570 borrow -= var2digits[i2];
5574 res_digits[i] = borrow + NBASE;
5579 res_digits[i] = borrow;
5584 Assert(borrow == 0); /* else caller gave us var1 < var2 */
5586 digitbuf_free(result->buf);
5587 result->ndigits = res_ndigits;
5588 result->buf = res_buf;
5589 result->digits = res_digits;
5590 result->weight = res_weight;
5591 result->dscale = res_dscale;
5593 /* Remove leading/trailing zeroes */
5600 * Round the value of a variable to no more than rscale decimal digits
5601 * after the decimal point. NOTE: we allow rscale < 0 here, implying
5602 * rounding before the decimal point.
5605 round_var(NumericVar *var, int rscale)
5607 NumericDigit *digits = var->digits;
5612 var->dscale = rscale;
5614 /* decimal digits wanted */
5615 di = (var->weight + 1) * DEC_DIGITS + rscale;
5618 * If di = 0, the value loses all digits, but could round up to 1 if its
5619 * first extra digit is >= 5. If di < 0 the result must be 0.
5625 var->sign = NUMERIC_POS;
5629 /* NBASE digits wanted */
5630 ndigits = (di + DEC_DIGITS - 1) / DEC_DIGITS;
5632 /* 0, or number of decimal digits to keep in last NBASE digit */
5635 if (ndigits < var->ndigits ||
5636 (ndigits == var->ndigits && di > 0))
5638 var->ndigits = ndigits;
5641 /* di must be zero */
5642 carry = (digits[ndigits] >= HALF_NBASE) ? 1 : 0;
5645 carry = (digits[ndigits] >= HALF_NBASE) ? 1 : 0;
5648 /* Must round within last NBASE digit */
5653 pow10 = round_powers[di];
5654 #elif DEC_DIGITS == 2
5657 #error unsupported NBASE
5659 extra = digits[--ndigits] % pow10;
5660 digits[ndigits] -= extra;
5662 if (extra >= pow10 / 2)
5664 pow10 += digits[ndigits];
5670 digits[ndigits] = pow10;
5675 /* Propagate carry if needed */
5678 carry += digits[--ndigits];
5681 digits[ndigits] = carry - NBASE;
5686 digits[ndigits] = carry;
5693 Assert(ndigits == -1); /* better not have added > 1 digit */
5694 Assert(var->digits > var->buf);
5706 * Truncate (towards zero) the value of a variable at rscale decimal digits
5707 * after the decimal point. NOTE: we allow rscale < 0 here, implying
5708 * truncation before the decimal point.
5711 trunc_var(NumericVar *var, int rscale)
5716 var->dscale = rscale;
5718 /* decimal digits wanted */
5719 di = (var->weight + 1) * DEC_DIGITS + rscale;
5722 * If di <= 0, the value loses all digits.
5728 var->sign = NUMERIC_POS;
5732 /* NBASE digits wanted */
5733 ndigits = (di + DEC_DIGITS - 1) / DEC_DIGITS;
5735 if (ndigits <= var->ndigits)
5737 var->ndigits = ndigits;
5740 /* no within-digit stuff to worry about */
5742 /* 0, or number of decimal digits to keep in last NBASE digit */
5747 /* Must truncate within last NBASE digit */
5748 NumericDigit *digits = var->digits;
5753 pow10 = round_powers[di];
5754 #elif DEC_DIGITS == 2
5757 #error unsupported NBASE
5759 extra = digits[--ndigits] % pow10;
5760 digits[ndigits] -= extra;
5770 * Strip any leading and trailing zeroes from a numeric variable
5773 strip_var(NumericVar *var)
5775 NumericDigit *digits = var->digits;
5776 int ndigits = var->ndigits;
5778 /* Strip leading zeroes */
5779 while (ndigits > 0 && *digits == 0)
5786 /* Strip trailing zeroes */
5787 while (ndigits > 0 && digits[ndigits - 1] == 0)
5790 /* If it's zero, normalize the sign and weight */
5793 var->sign = NUMERIC_POS;
5797 var->digits = digits;
5798 var->ndigits = ndigits;