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-2007, PostgreSQL Global Development Group
17 * $PostgreSQL: pgsql/src/backend/utils/adt/numeric.c,v 1.106 2007/07/09 16:13:57 tgl 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 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 * The value represented by a NumericVar is determined by the sign, weight,
94 * ndigits, and digits[] array.
95 * Note: the first digit of a NumericVar's value is assumed to be multiplied
96 * by NBASE ** weight. Another way to say it is that there are weight+1
97 * digits before the decimal point. It is possible to have weight < 0.
99 * buf points at the physical start of the palloc'd digit buffer for the
100 * NumericVar. digits points at the first digit in actual use (the one
101 * with the specified weight). We normally leave an unused digit or two
102 * (preset to zeroes) between buf and digits, so that there is room to store
103 * a carry out of the top digit without special pushups. We just need to
104 * decrement digits (and increment weight) to make room for the carry digit.
105 * (There is no such extra space in a numeric value stored in the database,
106 * only in a NumericVar in memory.)
108 * If buf is NULL then the digit buffer isn't actually palloc'd and should
109 * not be freed --- see the constants below for an example.
111 * dscale, or display scale, is the nominal precision expressed as number
112 * of digits after the decimal point (it must always be >= 0 at present).
113 * dscale may be more than the number of physically stored fractional digits,
114 * implying that we have suppressed storage of significant trailing zeroes.
115 * It should never be less than the number of stored digits, since that would
116 * imply hiding digits that are present. NOTE that dscale is always expressed
117 * in *decimal* digits, and so it may correspond to a fractional number of
118 * base-NBASE digits --- divide by DEC_DIGITS to convert to NBASE digits.
120 * rscale, or result scale, is the target precision for a computation.
121 * Like dscale it is expressed as number of *decimal* digits after the decimal
122 * point, and is always >= 0 at present.
123 * Note that rscale is not stored in variables --- it's figured on-the-fly
124 * from the dscales of the inputs.
126 * NB: All the variable-level functions are written in a style that makes it
127 * possible to give one and the same variable as argument and destination.
128 * This is feasible because the digit buffer is separate from the variable.
131 typedef struct NumericVar
133 int ndigits; /* # of digits in digits[] - can be 0! */
134 int weight; /* weight of first digit */
135 int sign; /* NUMERIC_POS, NUMERIC_NEG, or NUMERIC_NAN */
136 int dscale; /* display scale */
137 NumericDigit *buf; /* start of palloc'd space for digits[] */
138 NumericDigit *digits; /* base-NBASE digits */
143 * Some preinitialized constants
146 static NumericDigit const_zero_data[1] = {0};
147 static NumericVar const_zero =
148 {0, 0, NUMERIC_POS, 0, NULL, const_zero_data};
150 static NumericDigit const_one_data[1] = {1};
151 static NumericVar const_one =
152 {1, 0, NUMERIC_POS, 0, NULL, const_one_data};
154 static NumericDigit const_two_data[1] = {2};
155 static NumericVar const_two =
156 {1, 0, NUMERIC_POS, 0, NULL, const_two_data};
159 static NumericDigit const_zero_point_five_data[1] = {5000};
160 #elif DEC_DIGITS == 2
161 static NumericDigit const_zero_point_five_data[1] = {50};
162 #elif DEC_DIGITS == 1
163 static NumericDigit const_zero_point_five_data[1] = {5};
165 static NumericVar const_zero_point_five =
166 {1, -1, NUMERIC_POS, 1, NULL, const_zero_point_five_data};
169 static NumericDigit const_zero_point_nine_data[1] = {9000};
170 #elif DEC_DIGITS == 2
171 static NumericDigit const_zero_point_nine_data[1] = {90};
172 #elif DEC_DIGITS == 1
173 static NumericDigit const_zero_point_nine_data[1] = {9};
175 static NumericVar const_zero_point_nine =
176 {1, -1, NUMERIC_POS, 1, NULL, const_zero_point_nine_data};
179 static NumericDigit const_zero_point_01_data[1] = {100};
180 static NumericVar const_zero_point_01 =
181 {1, -1, NUMERIC_POS, 2, NULL, const_zero_point_01_data};
182 #elif DEC_DIGITS == 2
183 static NumericDigit const_zero_point_01_data[1] = {1};
184 static NumericVar const_zero_point_01 =
185 {1, -1, NUMERIC_POS, 2, NULL, const_zero_point_01_data};
186 #elif DEC_DIGITS == 1
187 static NumericDigit const_zero_point_01_data[1] = {1};
188 static NumericVar const_zero_point_01 =
189 {1, -2, NUMERIC_POS, 2, NULL, const_zero_point_01_data};
193 static NumericDigit const_one_point_one_data[2] = {1, 1000};
194 #elif DEC_DIGITS == 2
195 static NumericDigit const_one_point_one_data[2] = {1, 10};
196 #elif DEC_DIGITS == 1
197 static NumericDigit const_one_point_one_data[2] = {1, 1};
199 static NumericVar const_one_point_one =
200 {2, 0, NUMERIC_POS, 1, NULL, const_one_point_one_data};
202 static NumericVar const_nan =
203 {0, 0, NUMERIC_NAN, 0, NULL, NULL};
206 static const int round_powers[4] = {0, 1000, 100, 10};
216 static void dump_numeric(const char *str, Numeric num);
217 static void dump_var(const char *str, NumericVar *var);
219 #define dump_numeric(s,n)
220 #define dump_var(s,v)
223 #define digitbuf_alloc(ndigits) \
224 ((NumericDigit *) palloc((ndigits) * sizeof(NumericDigit)))
225 #define digitbuf_free(buf) \
231 #define init_var(v) MemSetAligned(v, 0, sizeof(NumericVar))
233 #define NUMERIC_DIGITS(num) ((NumericDigit *)(num)->n_data)
234 #define NUMERIC_NDIGITS(num) \
235 ((VARSIZE(num) - NUMERIC_HDRSZ) / sizeof(NumericDigit))
237 static void alloc_var(NumericVar *var, int ndigits);
238 static void free_var(NumericVar *var);
239 static void zero_var(NumericVar *var);
241 static void set_var_from_str(const char *str, NumericVar *dest);
242 static void set_var_from_num(Numeric value, NumericVar *dest);
243 static void set_var_from_var(NumericVar *value, NumericVar *dest);
244 static char *get_str_from_var(NumericVar *var, int dscale);
246 static Numeric make_result(NumericVar *var);
248 static void apply_typmod(NumericVar *var, int32 typmod);
250 static int32 numericvar_to_int4(NumericVar *var);
251 static bool numericvar_to_int8(NumericVar *var, int64 *result);
252 static void int8_to_numericvar(int64 val, NumericVar *var);
253 static double numeric_to_double_no_overflow(Numeric num);
254 static double numericvar_to_double_no_overflow(NumericVar *var);
256 static int cmp_numerics(Numeric num1, Numeric num2);
257 static int cmp_var(NumericVar *var1, NumericVar *var2);
258 static int cmp_var_common(const NumericDigit *var1digits, int var1ndigits,
259 int var1weight, int var1sign,
260 const NumericDigit *var2digits, int var2ndigits,
261 int var2weight, int var2sign);
262 static void add_var(NumericVar *var1, NumericVar *var2, NumericVar *result);
263 static void sub_var(NumericVar *var1, NumericVar *var2, NumericVar *result);
264 static void mul_var(NumericVar *var1, NumericVar *var2, NumericVar *result,
266 static void div_var(NumericVar *var1, NumericVar *var2, NumericVar *result,
267 int rscale, bool round);
268 static int select_div_scale(NumericVar *var1, NumericVar *var2);
269 static void mod_var(NumericVar *var1, NumericVar *var2, NumericVar *result);
270 static void ceil_var(NumericVar *var, NumericVar *result);
271 static void floor_var(NumericVar *var, NumericVar *result);
273 static void sqrt_var(NumericVar *arg, NumericVar *result, int rscale);
274 static void exp_var(NumericVar *arg, NumericVar *result, int rscale);
275 static void exp_var_internal(NumericVar *arg, NumericVar *result, int rscale);
276 static void ln_var(NumericVar *arg, NumericVar *result, int rscale);
277 static void log_var(NumericVar *base, NumericVar *num, NumericVar *result);
278 static void power_var(NumericVar *base, NumericVar *exp, NumericVar *result);
279 static void power_var_int(NumericVar *base, int exp, NumericVar *result,
282 static int cmp_abs(NumericVar *var1, NumericVar *var2);
283 static int cmp_abs_common(const NumericDigit *var1digits, int var1ndigits,
285 const NumericDigit *var2digits, int var2ndigits,
287 static void add_abs(NumericVar *var1, NumericVar *var2, NumericVar *result);
288 static void sub_abs(NumericVar *var1, NumericVar *var2, NumericVar *result);
289 static void round_var(NumericVar *var, int rscale);
290 static void trunc_var(NumericVar *var, int rscale);
291 static void strip_var(NumericVar *var);
292 static void compute_bucket(Numeric operand, Numeric bound1, Numeric bound2,
293 NumericVar *count_var, NumericVar *result_var);
296 /* ----------------------------------------------------------------------
298 * Input-, output- and rounding-functions
300 * ----------------------------------------------------------------------
307 * Input function for numeric data type
310 numeric_in(PG_FUNCTION_ARGS)
312 char *str = PG_GETARG_CSTRING(0);
315 Oid typelem = PG_GETARG_OID(1);
317 int32 typmod = PG_GETARG_INT32(2);
324 if (pg_strcasecmp(str, "NaN") == 0)
325 PG_RETURN_NUMERIC(make_result(&const_nan));
328 * Use set_var_from_str() to parse the input string and return it in the
329 * packed DB storage format
332 set_var_from_str(str, &value);
334 apply_typmod(&value, typmod);
336 res = make_result(&value);
339 PG_RETURN_NUMERIC(res);
346 * Output function for numeric data type
349 numeric_out(PG_FUNCTION_ARGS)
351 Numeric num = PG_GETARG_NUMERIC(0);
358 if (NUMERIC_IS_NAN(num))
359 PG_RETURN_CSTRING(pstrdup("NaN"));
362 * Get the number in the variable format.
364 * Even if we didn't need to change format, we'd still need to copy the
365 * value to have a modifiable copy for rounding. set_var_from_num() also
366 * guarantees there is extra digit space in case we produce a carry out
370 set_var_from_num(num, &x);
372 str = get_str_from_var(&x, x.dscale);
376 PG_RETURN_CSTRING(str);
380 * numeric_recv - converts external binary format to numeric
382 * External format is a sequence of int16's:
383 * ndigits, weight, sign, dscale, NumericDigits.
386 numeric_recv(PG_FUNCTION_ARGS)
388 StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
391 Oid typelem = PG_GETARG_OID(1);
393 int32 typmod = PG_GETARG_INT32(2);
401 len = (uint16) pq_getmsgint(buf, sizeof(uint16));
402 if (len < 0 || len > NUMERIC_MAX_PRECISION + NUMERIC_MAX_RESULT_SCALE)
404 (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
405 errmsg("invalid length in external \"numeric\" value")));
407 alloc_var(&value, len);
409 value.weight = (int16) pq_getmsgint(buf, sizeof(int16));
410 value.sign = (uint16) pq_getmsgint(buf, sizeof(uint16));
411 if (!(value.sign == NUMERIC_POS ||
412 value.sign == NUMERIC_NEG ||
413 value.sign == NUMERIC_NAN))
415 (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
416 errmsg("invalid sign in external \"numeric\" value")));
418 value.dscale = (uint16) pq_getmsgint(buf, sizeof(uint16));
419 for (i = 0; i < len; i++)
421 NumericDigit d = pq_getmsgint(buf, sizeof(NumericDigit));
423 if (d < 0 || d >= NBASE)
425 (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
426 errmsg("invalid digit in external \"numeric\" value")));
430 apply_typmod(&value, typmod);
432 res = make_result(&value);
435 PG_RETURN_NUMERIC(res);
439 * numeric_send - converts numeric to binary format
442 numeric_send(PG_FUNCTION_ARGS)
444 Numeric num = PG_GETARG_NUMERIC(0);
450 set_var_from_num(num, &x);
452 pq_begintypsend(&buf);
454 pq_sendint(&buf, x.ndigits, sizeof(int16));
455 pq_sendint(&buf, x.weight, sizeof(int16));
456 pq_sendint(&buf, x.sign, sizeof(int16));
457 pq_sendint(&buf, x.dscale, sizeof(int16));
458 for (i = 0; i < x.ndigits; i++)
459 pq_sendint(&buf, x.digits[i], sizeof(NumericDigit));
463 PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
470 * This is a special function called by the Postgres database system
471 * before a value is stored in a tuple's attribute. The precision and
472 * scale of the attribute have to be applied on the value.
475 numeric(PG_FUNCTION_ARGS)
477 Numeric num = PG_GETARG_NUMERIC(0);
478 int32 typmod = PG_GETARG_INT32(1);
490 if (NUMERIC_IS_NAN(num))
491 PG_RETURN_NUMERIC(make_result(&const_nan));
494 * If the value isn't a valid type modifier, simply return a copy of the
497 if (typmod < (int32) (VARHDRSZ))
499 new = (Numeric) palloc(VARSIZE(num));
500 memcpy(new, num, VARSIZE(num));
501 PG_RETURN_NUMERIC(new);
505 * Get the precision and scale out of the typmod value
507 tmp_typmod = typmod - VARHDRSZ;
508 precision = (tmp_typmod >> 16) & 0xffff;
509 scale = tmp_typmod & 0xffff;
510 maxdigits = precision - scale;
513 * If the number is certainly in bounds and due to the target scale no
514 * rounding could be necessary, just make a copy of the input and modify
515 * its scale fields. (Note we assume the existing dscale is honest...)
517 ddigits = (num->n_weight + 1) * DEC_DIGITS;
518 if (ddigits <= maxdigits && scale >= NUMERIC_DSCALE(num))
520 new = (Numeric) palloc(VARSIZE(num));
521 memcpy(new, num, VARSIZE(num));
522 new->n_sign_dscale = NUMERIC_SIGN(new) |
523 ((uint16) scale & NUMERIC_DSCALE_MASK);
524 PG_RETURN_NUMERIC(new);
528 * We really need to fiddle with things - unpack the number into a
529 * variable and let apply_typmod() do it.
533 set_var_from_num(num, &var);
534 apply_typmod(&var, typmod);
535 new = make_result(&var);
539 PG_RETURN_NUMERIC(new);
543 numerictypmodin(PG_FUNCTION_ARGS)
545 ArrayType *ta = PG_GETARG_ARRAYTYPE_P(0);
550 tl = ArrayGetIntegerTypmods(ta, &n);
554 if (tl[0] < 1 || tl[0] > NUMERIC_MAX_PRECISION)
556 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
557 errmsg("NUMERIC precision %d must be between 1 and %d",
558 tl[0], NUMERIC_MAX_PRECISION)));
559 if (tl[1] < 0 || tl[1] > tl[0])
561 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
562 errmsg("NUMERIC scale %d must be between 0 and precision %d",
564 typmod = ((tl[0] << 16) | tl[1]) + VARHDRSZ;
568 if (tl[0] < 1 || tl[0] > NUMERIC_MAX_PRECISION)
570 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
571 errmsg("NUMERIC precision %d must be between 1 and %d",
572 tl[0], NUMERIC_MAX_PRECISION)));
573 /* scale defaults to zero */
574 typmod = (tl[0] << 16) + VARHDRSZ;
579 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
580 errmsg("invalid NUMERIC type modifier")));
581 typmod = 0; /* keep compiler quiet */
584 PG_RETURN_INT32(typmod);
588 numerictypmodout(PG_FUNCTION_ARGS)
590 int32 typmod = PG_GETARG_INT32(0);
591 char *res = (char *) palloc(64);
594 snprintf(res, 64, "(%d,%d)",
595 ((typmod - VARHDRSZ) >> 16) & 0xffff,
596 (typmod - VARHDRSZ) & 0xffff);
600 PG_RETURN_CSTRING(res);
604 /* ----------------------------------------------------------------------
606 * Sign manipulation, rounding and the like
608 * ----------------------------------------------------------------------
612 numeric_abs(PG_FUNCTION_ARGS)
614 Numeric num = PG_GETARG_NUMERIC(0);
620 if (NUMERIC_IS_NAN(num))
621 PG_RETURN_NUMERIC(make_result(&const_nan));
624 * Do it the easy way directly on the packed format
626 res = (Numeric) palloc(VARSIZE(num));
627 memcpy(res, num, VARSIZE(num));
629 res->n_sign_dscale = NUMERIC_POS | NUMERIC_DSCALE(num);
631 PG_RETURN_NUMERIC(res);
636 numeric_uminus(PG_FUNCTION_ARGS)
638 Numeric num = PG_GETARG_NUMERIC(0);
644 if (NUMERIC_IS_NAN(num))
645 PG_RETURN_NUMERIC(make_result(&const_nan));
648 * Do it the easy way directly on the packed format
650 res = (Numeric) palloc(VARSIZE(num));
651 memcpy(res, num, VARSIZE(num));
654 * The packed format is known to be totally zero digit trimmed always. So
655 * we can identify a ZERO by the fact that there are no digits at all. Do
658 if (VARSIZE(num) != NUMERIC_HDRSZ)
660 /* Else, flip the sign */
661 if (NUMERIC_SIGN(num) == NUMERIC_POS)
662 res->n_sign_dscale = NUMERIC_NEG | NUMERIC_DSCALE(num);
664 res->n_sign_dscale = NUMERIC_POS | NUMERIC_DSCALE(num);
667 PG_RETURN_NUMERIC(res);
672 numeric_uplus(PG_FUNCTION_ARGS)
674 Numeric num = PG_GETARG_NUMERIC(0);
677 res = (Numeric) palloc(VARSIZE(num));
678 memcpy(res, num, VARSIZE(num));
680 PG_RETURN_NUMERIC(res);
686 * returns -1 if the argument is less than 0, 0 if the argument is equal
687 * to 0, and 1 if the argument is greater than zero.
690 numeric_sign(PG_FUNCTION_ARGS)
692 Numeric num = PG_GETARG_NUMERIC(0);
699 if (NUMERIC_IS_NAN(num))
700 PG_RETURN_NUMERIC(make_result(&const_nan));
705 * The packed format is known to be totally zero digit trimmed always. So
706 * we can identify a ZERO by the fact that there are no digits at all.
708 if (VARSIZE(num) == NUMERIC_HDRSZ)
709 set_var_from_var(&const_zero, &result);
713 * And if there are some, we return a copy of ONE with the sign of our
716 set_var_from_var(&const_one, &result);
717 result.sign = NUMERIC_SIGN(num);
720 res = make_result(&result);
723 PG_RETURN_NUMERIC(res);
730 * Round a value to have 'scale' digits after the decimal point.
731 * We allow negative 'scale', implying rounding before the decimal
732 * point --- Oracle interprets rounding that way.
735 numeric_round(PG_FUNCTION_ARGS)
737 Numeric num = PG_GETARG_NUMERIC(0);
738 int32 scale = PG_GETARG_INT32(1);
745 if (NUMERIC_IS_NAN(num))
746 PG_RETURN_NUMERIC(make_result(&const_nan));
749 * Limit the scale value to avoid possible overflow in calculations
751 scale = Max(scale, -NUMERIC_MAX_RESULT_SCALE);
752 scale = Min(scale, NUMERIC_MAX_RESULT_SCALE);
755 * Unpack the argument and round it at the proper digit position
758 set_var_from_num(num, &arg);
760 round_var(&arg, scale);
762 /* We don't allow negative output dscale */
767 * Return the rounded result
769 res = make_result(&arg);
772 PG_RETURN_NUMERIC(res);
779 * Truncate a value to have 'scale' digits after the decimal point.
780 * We allow negative 'scale', implying a truncation before the decimal
781 * point --- Oracle interprets truncation that way.
784 numeric_trunc(PG_FUNCTION_ARGS)
786 Numeric num = PG_GETARG_NUMERIC(0);
787 int32 scale = PG_GETARG_INT32(1);
794 if (NUMERIC_IS_NAN(num))
795 PG_RETURN_NUMERIC(make_result(&const_nan));
798 * Limit the scale value to avoid possible overflow in calculations
800 scale = Max(scale, -NUMERIC_MAX_RESULT_SCALE);
801 scale = Min(scale, NUMERIC_MAX_RESULT_SCALE);
804 * Unpack the argument and truncate it at the proper digit position
807 set_var_from_num(num, &arg);
809 trunc_var(&arg, scale);
811 /* We don't allow negative output dscale */
816 * Return the truncated result
818 res = make_result(&arg);
821 PG_RETURN_NUMERIC(res);
828 * Return the smallest integer greater than or equal to the argument
831 numeric_ceil(PG_FUNCTION_ARGS)
833 Numeric num = PG_GETARG_NUMERIC(0);
837 if (NUMERIC_IS_NAN(num))
838 PG_RETURN_NUMERIC(make_result(&const_nan));
842 set_var_from_num(num, &result);
843 ceil_var(&result, &result);
845 res = make_result(&result);
848 PG_RETURN_NUMERIC(res);
855 * Return the largest integer equal to or less than the argument
858 numeric_floor(PG_FUNCTION_ARGS)
860 Numeric num = PG_GETARG_NUMERIC(0);
864 if (NUMERIC_IS_NAN(num))
865 PG_RETURN_NUMERIC(make_result(&const_nan));
869 set_var_from_num(num, &result);
870 floor_var(&result, &result);
872 res = make_result(&result);
875 PG_RETURN_NUMERIC(res);
879 * Implements the numeric version of the width_bucket() function
880 * defined by SQL2003. See also width_bucket_float8().
882 * 'bound1' and 'bound2' are the lower and upper bounds of the
883 * histogram's range, respectively. 'count' is the number of buckets
884 * in the histogram. width_bucket() returns an integer indicating the
885 * bucket number that 'operand' belongs to in an equiwidth histogram
886 * with the specified characteristics. An operand smaller than the
887 * lower bound is assigned to bucket 0. An operand greater than the
888 * upper bound is assigned to an additional bucket (with number
889 * count+1). We don't allow "NaN" for any of the numeric arguments.
892 width_bucket_numeric(PG_FUNCTION_ARGS)
894 Numeric operand = PG_GETARG_NUMERIC(0);
895 Numeric bound1 = PG_GETARG_NUMERIC(1);
896 Numeric bound2 = PG_GETARG_NUMERIC(2);
897 int32 count = PG_GETARG_INT32(3);
898 NumericVar count_var;
899 NumericVar result_var;
904 (errcode(ERRCODE_INVALID_ARGUMENT_FOR_WIDTH_BUCKET_FUNCTION),
905 errmsg("count must be greater than zero")));
907 if (NUMERIC_IS_NAN(operand) ||
908 NUMERIC_IS_NAN(bound1) ||
909 NUMERIC_IS_NAN(bound2))
911 (errcode(ERRCODE_INVALID_ARGUMENT_FOR_WIDTH_BUCKET_FUNCTION),
912 errmsg("operand, lower bound and upper bound cannot be NaN")));
914 init_var(&result_var);
915 init_var(&count_var);
917 /* Convert 'count' to a numeric, for ease of use later */
918 int8_to_numericvar((int64) count, &count_var);
920 switch (cmp_numerics(bound1, bound2))
924 (errcode(ERRCODE_INVALID_ARGUMENT_FOR_WIDTH_BUCKET_FUNCTION),
925 errmsg("lower bound cannot equal upper bound")));
927 /* bound1 < bound2 */
929 if (cmp_numerics(operand, bound1) < 0)
930 set_var_from_var(&const_zero, &result_var);
931 else if (cmp_numerics(operand, bound2) >= 0)
932 add_var(&count_var, &const_one, &result_var);
934 compute_bucket(operand, bound1, bound2,
935 &count_var, &result_var);
938 /* bound1 > bound2 */
940 if (cmp_numerics(operand, bound1) > 0)
941 set_var_from_var(&const_zero, &result_var);
942 else if (cmp_numerics(operand, bound2) <= 0)
943 add_var(&count_var, &const_one, &result_var);
945 compute_bucket(operand, bound1, bound2,
946 &count_var, &result_var);
950 /* if result exceeds the range of a legal int4, we ereport here */
951 result = numericvar_to_int4(&result_var);
953 free_var(&count_var);
954 free_var(&result_var);
956 PG_RETURN_INT32(result);
960 * If 'operand' is not outside the bucket range, determine the correct
961 * bucket for it to go. The calculations performed by this function
962 * are derived directly from the SQL2003 spec.
965 compute_bucket(Numeric operand, Numeric bound1, Numeric bound2,
966 NumericVar *count_var, NumericVar *result_var)
968 NumericVar bound1_var;
969 NumericVar bound2_var;
970 NumericVar operand_var;
972 init_var(&bound1_var);
973 init_var(&bound2_var);
974 init_var(&operand_var);
976 set_var_from_num(bound1, &bound1_var);
977 set_var_from_num(bound2, &bound2_var);
978 set_var_from_num(operand, &operand_var);
980 if (cmp_var(&bound1_var, &bound2_var) < 0)
982 sub_var(&operand_var, &bound1_var, &operand_var);
983 sub_var(&bound2_var, &bound1_var, &bound2_var);
984 div_var(&operand_var, &bound2_var, result_var,
985 select_div_scale(&operand_var, &bound2_var), true);
989 sub_var(&bound1_var, &operand_var, &operand_var);
990 sub_var(&bound1_var, &bound2_var, &bound1_var);
991 div_var(&operand_var, &bound1_var, result_var,
992 select_div_scale(&operand_var, &bound1_var), true);
995 mul_var(result_var, count_var, result_var,
996 result_var->dscale + count_var->dscale);
997 add_var(result_var, &const_one, result_var);
998 floor_var(result_var, result_var);
1000 free_var(&bound1_var);
1001 free_var(&bound2_var);
1002 free_var(&operand_var);
1005 /* ----------------------------------------------------------------------
1007 * Comparison functions
1009 * Note: btree indexes need these routines not to leak memory; therefore,
1010 * be careful to free working copies of toasted datums. Most places don't
1011 * need to be so careful.
1012 * ----------------------------------------------------------------------
1017 numeric_cmp(PG_FUNCTION_ARGS)
1019 Numeric num1 = PG_GETARG_NUMERIC(0);
1020 Numeric num2 = PG_GETARG_NUMERIC(1);
1023 result = cmp_numerics(num1, num2);
1025 PG_FREE_IF_COPY(num1, 0);
1026 PG_FREE_IF_COPY(num2, 1);
1028 PG_RETURN_INT32(result);
1033 numeric_eq(PG_FUNCTION_ARGS)
1035 Numeric num1 = PG_GETARG_NUMERIC(0);
1036 Numeric num2 = PG_GETARG_NUMERIC(1);
1039 result = cmp_numerics(num1, num2) == 0;
1041 PG_FREE_IF_COPY(num1, 0);
1042 PG_FREE_IF_COPY(num2, 1);
1044 PG_RETURN_BOOL(result);
1048 numeric_ne(PG_FUNCTION_ARGS)
1050 Numeric num1 = PG_GETARG_NUMERIC(0);
1051 Numeric num2 = PG_GETARG_NUMERIC(1);
1054 result = cmp_numerics(num1, num2) != 0;
1056 PG_FREE_IF_COPY(num1, 0);
1057 PG_FREE_IF_COPY(num2, 1);
1059 PG_RETURN_BOOL(result);
1063 numeric_gt(PG_FUNCTION_ARGS)
1065 Numeric num1 = PG_GETARG_NUMERIC(0);
1066 Numeric num2 = PG_GETARG_NUMERIC(1);
1069 result = cmp_numerics(num1, num2) > 0;
1071 PG_FREE_IF_COPY(num1, 0);
1072 PG_FREE_IF_COPY(num2, 1);
1074 PG_RETURN_BOOL(result);
1078 numeric_ge(PG_FUNCTION_ARGS)
1080 Numeric num1 = PG_GETARG_NUMERIC(0);
1081 Numeric num2 = PG_GETARG_NUMERIC(1);
1084 result = cmp_numerics(num1, num2) >= 0;
1086 PG_FREE_IF_COPY(num1, 0);
1087 PG_FREE_IF_COPY(num2, 1);
1089 PG_RETURN_BOOL(result);
1093 numeric_lt(PG_FUNCTION_ARGS)
1095 Numeric num1 = PG_GETARG_NUMERIC(0);
1096 Numeric num2 = PG_GETARG_NUMERIC(1);
1099 result = cmp_numerics(num1, num2) < 0;
1101 PG_FREE_IF_COPY(num1, 0);
1102 PG_FREE_IF_COPY(num2, 1);
1104 PG_RETURN_BOOL(result);
1108 numeric_le(PG_FUNCTION_ARGS)
1110 Numeric num1 = PG_GETARG_NUMERIC(0);
1111 Numeric num2 = PG_GETARG_NUMERIC(1);
1114 result = cmp_numerics(num1, num2) <= 0;
1116 PG_FREE_IF_COPY(num1, 0);
1117 PG_FREE_IF_COPY(num2, 1);
1119 PG_RETURN_BOOL(result);
1123 cmp_numerics(Numeric num1, Numeric num2)
1128 * We consider all NANs to be equal and larger than any non-NAN. This is
1129 * somewhat arbitrary; the important thing is to have a consistent sort
1132 if (NUMERIC_IS_NAN(num1))
1134 if (NUMERIC_IS_NAN(num2))
1135 result = 0; /* NAN = NAN */
1137 result = 1; /* NAN > non-NAN */
1139 else if (NUMERIC_IS_NAN(num2))
1141 result = -1; /* non-NAN < NAN */
1145 result = cmp_var_common(NUMERIC_DIGITS(num1), NUMERIC_NDIGITS(num1),
1146 num1->n_weight, NUMERIC_SIGN(num1),
1147 NUMERIC_DIGITS(num2), NUMERIC_NDIGITS(num2),
1148 num2->n_weight, NUMERIC_SIGN(num2));
1155 hash_numeric(PG_FUNCTION_ARGS)
1157 Numeric key = PG_GETARG_NUMERIC(0);
1166 /* If it's NaN, don't try to hash the rest of the fields */
1167 if (NUMERIC_IS_NAN(key))
1168 PG_RETURN_UINT32(0);
1170 weight = key->n_weight;
1175 * Omit any leading or trailing zeros from the input to the
1176 * hash. The numeric implementation *should* guarantee that
1177 * leading and trailing zeros are suppressed, but we're
1178 * paranoid. Note that we measure the starting and ending offsets
1179 * in units of NumericDigits, not bytes.
1181 for (i = 0; i < NUMERIC_NDIGITS(key); i++)
1183 if (NUMERIC_DIGITS(key)[i] != (NumericDigit) 0)
1188 * The weight is effectively the # of digits before the
1189 * decimal point, so decrement it for each leading zero we
1196 * If there are no non-zero digits, then the value of the number
1197 * is zero, regardless of any other fields.
1199 if (NUMERIC_NDIGITS(key) == start_offset)
1200 PG_RETURN_UINT32(-1);
1202 for (i = NUMERIC_NDIGITS(key) - 1; i >= 0; i--)
1204 if (NUMERIC_DIGITS(key)[i] != (NumericDigit) 0)
1210 /* If we get here, there should be at least one non-zero digit */
1211 Assert(start_offset + end_offset < NUMERIC_NDIGITS(key));
1214 * Note that we don't hash on the Numeric's scale, since two
1215 * numerics can compare equal but have different scales. We also
1216 * don't hash on the sign, although we could: since a sign
1217 * difference implies inequality, this shouldn't affect correctness.
1219 hash_len = NUMERIC_NDIGITS(key) - start_offset - end_offset;
1220 digit_hash = hash_any((unsigned char *) (NUMERIC_DIGITS(key) + start_offset),
1221 hash_len * sizeof(NumericDigit));
1223 /* Mix in the weight, via XOR */
1224 result = digit_hash ^ weight;
1226 PG_RETURN_DATUM(result);
1230 /* ----------------------------------------------------------------------
1232 * Basic arithmetic functions
1234 * ----------------------------------------------------------------------
1244 numeric_add(PG_FUNCTION_ARGS)
1246 Numeric num1 = PG_GETARG_NUMERIC(0);
1247 Numeric num2 = PG_GETARG_NUMERIC(1);
1256 if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
1257 PG_RETURN_NUMERIC(make_result(&const_nan));
1260 * Unpack the values, let add_var() compute the result and return it.
1266 set_var_from_num(num1, &arg1);
1267 set_var_from_num(num2, &arg2);
1269 add_var(&arg1, &arg2, &result);
1271 res = make_result(&result);
1277 PG_RETURN_NUMERIC(res);
1284 * Subtract one numeric from another
1287 numeric_sub(PG_FUNCTION_ARGS)
1289 Numeric num1 = PG_GETARG_NUMERIC(0);
1290 Numeric num2 = PG_GETARG_NUMERIC(1);
1299 if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
1300 PG_RETURN_NUMERIC(make_result(&const_nan));
1303 * Unpack the values, let sub_var() compute the result and return it.
1309 set_var_from_num(num1, &arg1);
1310 set_var_from_num(num2, &arg2);
1312 sub_var(&arg1, &arg2, &result);
1314 res = make_result(&result);
1320 PG_RETURN_NUMERIC(res);
1327 * Calculate the product of two numerics
1330 numeric_mul(PG_FUNCTION_ARGS)
1332 Numeric num1 = PG_GETARG_NUMERIC(0);
1333 Numeric num2 = PG_GETARG_NUMERIC(1);
1342 if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
1343 PG_RETURN_NUMERIC(make_result(&const_nan));
1346 * Unpack the values, let mul_var() compute the result and return it.
1347 * Unlike add_var() and sub_var(), mul_var() will round its result. In the
1348 * case of numeric_mul(), which is invoked for the * operator on numerics,
1349 * we request exact representation for the product (rscale = sum(dscale of
1350 * arg1, dscale of arg2)).
1356 set_var_from_num(num1, &arg1);
1357 set_var_from_num(num2, &arg2);
1359 mul_var(&arg1, &arg2, &result, arg1.dscale + arg2.dscale);
1361 res = make_result(&result);
1367 PG_RETURN_NUMERIC(res);
1374 * Divide one numeric into another
1377 numeric_div(PG_FUNCTION_ARGS)
1379 Numeric num1 = PG_GETARG_NUMERIC(0);
1380 Numeric num2 = PG_GETARG_NUMERIC(1);
1390 if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
1391 PG_RETURN_NUMERIC(make_result(&const_nan));
1394 * Unpack the arguments
1400 set_var_from_num(num1, &arg1);
1401 set_var_from_num(num2, &arg2);
1404 * Select scale for division result
1406 rscale = select_div_scale(&arg1, &arg2);
1409 * Do the divide and return the result
1411 div_var(&arg1, &arg2, &result, rscale, true);
1413 res = make_result(&result);
1419 PG_RETURN_NUMERIC(res);
1426 * Calculate the modulo of two numerics
1429 numeric_mod(PG_FUNCTION_ARGS)
1431 Numeric num1 = PG_GETARG_NUMERIC(0);
1432 Numeric num2 = PG_GETARG_NUMERIC(1);
1438 if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
1439 PG_RETURN_NUMERIC(make_result(&const_nan));
1445 set_var_from_num(num1, &arg1);
1446 set_var_from_num(num2, &arg2);
1448 mod_var(&arg1, &arg2, &result);
1450 res = make_result(&result);
1456 PG_RETURN_NUMERIC(res);
1463 * Increment a number by one
1466 numeric_inc(PG_FUNCTION_ARGS)
1468 Numeric num = PG_GETARG_NUMERIC(0);
1475 if (NUMERIC_IS_NAN(num))
1476 PG_RETURN_NUMERIC(make_result(&const_nan));
1479 * Compute the result and return it
1483 set_var_from_num(num, &arg);
1485 add_var(&arg, &const_one, &arg);
1487 res = make_result(&arg);
1491 PG_RETURN_NUMERIC(res);
1496 * numeric_smaller() -
1498 * Return the smaller of two numbers
1501 numeric_smaller(PG_FUNCTION_ARGS)
1503 Numeric num1 = PG_GETARG_NUMERIC(0);
1504 Numeric num2 = PG_GETARG_NUMERIC(1);
1507 * Use cmp_numerics so that this will agree with the comparison operators,
1508 * particularly as regards comparisons involving NaN.
1510 if (cmp_numerics(num1, num2) < 0)
1511 PG_RETURN_NUMERIC(num1);
1513 PG_RETURN_NUMERIC(num2);
1518 * numeric_larger() -
1520 * Return the larger of two numbers
1523 numeric_larger(PG_FUNCTION_ARGS)
1525 Numeric num1 = PG_GETARG_NUMERIC(0);
1526 Numeric num2 = PG_GETARG_NUMERIC(1);
1529 * Use cmp_numerics so that this will agree with the comparison operators,
1530 * particularly as regards comparisons involving NaN.
1532 if (cmp_numerics(num1, num2) > 0)
1533 PG_RETURN_NUMERIC(num1);
1535 PG_RETURN_NUMERIC(num2);
1539 /* ----------------------------------------------------------------------
1541 * Advanced math functions
1543 * ----------------------------------------------------------------------
1552 numeric_fac(PG_FUNCTION_ARGS)
1554 int64 num = PG_GETARG_INT64(0);
1561 res = make_result(&const_one);
1562 PG_RETURN_NUMERIC(res);
1564 /* Fail immediately if the result would overflow */
1567 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1568 errmsg("value overflows numeric format")));
1573 int8_to_numericvar(num, &result);
1575 for (num = num - 1; num > 1; num--)
1577 /* this loop can take awhile, so allow it to be interrupted */
1578 CHECK_FOR_INTERRUPTS();
1580 int8_to_numericvar(num, &fact);
1582 mul_var(&result, &fact, &result, 0);
1585 res = make_result(&result);
1590 PG_RETURN_NUMERIC(res);
1597 * Compute the square root of a numeric.
1600 numeric_sqrt(PG_FUNCTION_ARGS)
1602 Numeric num = PG_GETARG_NUMERIC(0);
1612 if (NUMERIC_IS_NAN(num))
1613 PG_RETURN_NUMERIC(make_result(&const_nan));
1616 * Unpack the argument and determine the result scale. We choose a scale
1617 * to give at least NUMERIC_MIN_SIG_DIGITS significant digits; but in any
1618 * case not less than the input's dscale.
1623 set_var_from_num(num, &arg);
1625 /* Assume the input was normalized, so arg.weight is accurate */
1626 sweight = (arg.weight + 1) * DEC_DIGITS / 2 - 1;
1628 rscale = NUMERIC_MIN_SIG_DIGITS - sweight;
1629 rscale = Max(rscale, arg.dscale);
1630 rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
1631 rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
1634 * Let sqrt_var() do the calculation and return the result.
1636 sqrt_var(&arg, &result, rscale);
1638 res = make_result(&result);
1643 PG_RETURN_NUMERIC(res);
1650 * Raise e to the power of x
1653 numeric_exp(PG_FUNCTION_ARGS)
1655 Numeric num = PG_GETARG_NUMERIC(0);
1665 if (NUMERIC_IS_NAN(num))
1666 PG_RETURN_NUMERIC(make_result(&const_nan));
1669 * Unpack the argument and determine the result scale. We choose a scale
1670 * to give at least NUMERIC_MIN_SIG_DIGITS significant digits; but in any
1671 * case not less than the input's dscale.
1676 set_var_from_num(num, &arg);
1678 /* convert input to float8, ignoring overflow */
1679 val = numericvar_to_double_no_overflow(&arg);
1682 * log10(result) = num * log10(e), so this is approximately the decimal
1683 * weight of the result:
1685 val *= 0.434294481903252;
1687 /* limit to something that won't cause integer overflow */
1688 val = Max(val, -NUMERIC_MAX_RESULT_SCALE);
1689 val = Min(val, NUMERIC_MAX_RESULT_SCALE);
1691 rscale = NUMERIC_MIN_SIG_DIGITS - (int) val;
1692 rscale = Max(rscale, arg.dscale);
1693 rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
1694 rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
1697 * Let exp_var() do the calculation and return the result.
1699 exp_var(&arg, &result, rscale);
1701 res = make_result(&result);
1706 PG_RETURN_NUMERIC(res);
1713 * Compute the natural logarithm of x
1716 numeric_ln(PG_FUNCTION_ARGS)
1718 Numeric num = PG_GETARG_NUMERIC(0);
1728 if (NUMERIC_IS_NAN(num))
1729 PG_RETURN_NUMERIC(make_result(&const_nan));
1734 set_var_from_num(num, &arg);
1736 /* Approx decimal digits before decimal point */
1737 dec_digits = (arg.weight + 1) * DEC_DIGITS;
1740 rscale = NUMERIC_MIN_SIG_DIGITS - (int) log10(dec_digits - 1);
1741 else if (dec_digits < 1)
1742 rscale = NUMERIC_MIN_SIG_DIGITS - (int) log10(1 - dec_digits);
1744 rscale = NUMERIC_MIN_SIG_DIGITS;
1746 rscale = Max(rscale, arg.dscale);
1747 rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
1748 rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
1750 ln_var(&arg, &result, rscale);
1752 res = make_result(&result);
1757 PG_RETURN_NUMERIC(res);
1764 * Compute the logarithm of x in a given base
1767 numeric_log(PG_FUNCTION_ARGS)
1769 Numeric num1 = PG_GETARG_NUMERIC(0);
1770 Numeric num2 = PG_GETARG_NUMERIC(1);
1779 if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
1780 PG_RETURN_NUMERIC(make_result(&const_nan));
1789 set_var_from_num(num1, &arg1);
1790 set_var_from_num(num2, &arg2);
1793 * Call log_var() to compute and return the result; note it handles scale
1796 log_var(&arg1, &arg2, &result);
1798 res = make_result(&result);
1804 PG_RETURN_NUMERIC(res);
1811 * Raise b to the power of x
1814 numeric_power(PG_FUNCTION_ARGS)
1816 Numeric num1 = PG_GETARG_NUMERIC(0);
1817 Numeric num2 = PG_GETARG_NUMERIC(1);
1821 NumericVar arg2_trunc;
1827 if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
1828 PG_RETURN_NUMERIC(make_result(&const_nan));
1835 init_var(&arg2_trunc);
1838 set_var_from_num(num1, &arg1);
1839 set_var_from_num(num2, &arg2);
1840 set_var_from_var(&arg2, &arg2_trunc);
1842 trunc_var(&arg2_trunc, 0);
1845 * Return special SQLSTATE error codes for a few conditions mandated by
1848 if ((cmp_var(&arg1, &const_zero) == 0 &&
1849 cmp_var(&arg2, &const_zero) < 0) ||
1850 (cmp_var(&arg1, &const_zero) < 0 &&
1851 cmp_var(&arg2, &arg2_trunc) != 0))
1853 (errcode(ERRCODE_INVALID_ARGUMENT_FOR_POWER_FUNCTION),
1854 errmsg("invalid argument for power function")));
1857 * Call power_var() to compute and return the result; note it handles
1858 * scale selection itself.
1860 power_var(&arg1, &arg2, &result);
1862 res = make_result(&result);
1866 free_var(&arg2_trunc);
1869 PG_RETURN_NUMERIC(res);
1873 /* ----------------------------------------------------------------------
1875 * Type conversion functions
1877 * ----------------------------------------------------------------------
1882 int4_numeric(PG_FUNCTION_ARGS)
1884 int32 val = PG_GETARG_INT32(0);
1890 int8_to_numericvar((int64) val, &result);
1892 res = make_result(&result);
1896 PG_RETURN_NUMERIC(res);
1901 numeric_int4(PG_FUNCTION_ARGS)
1903 Numeric num = PG_GETARG_NUMERIC(0);
1907 /* XXX would it be better to return NULL? */
1908 if (NUMERIC_IS_NAN(num))
1910 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1911 errmsg("cannot convert NaN to integer")));
1913 /* Convert to variable format, then convert to int4 */
1915 set_var_from_num(num, &x);
1916 result = numericvar_to_int4(&x);
1918 PG_RETURN_INT32(result);
1922 * Given a NumericVar, convert it to an int32. If the NumericVar
1923 * exceeds the range of an int32, raise the appropriate error via
1924 * ereport(). The input NumericVar is *not* free'd.
1927 numericvar_to_int4(NumericVar *var)
1932 if (!numericvar_to_int8(var, &val))
1934 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1935 errmsg("integer out of range")));
1937 /* Down-convert to int4 */
1938 result = (int32) val;
1940 /* Test for overflow by reverse-conversion. */
1941 if ((int64) result != val)
1943 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1944 errmsg("integer out of range")));
1950 int8_numeric(PG_FUNCTION_ARGS)
1952 int64 val = PG_GETARG_INT64(0);
1958 int8_to_numericvar(val, &result);
1960 res = make_result(&result);
1964 PG_RETURN_NUMERIC(res);
1969 numeric_int8(PG_FUNCTION_ARGS)
1971 Numeric num = PG_GETARG_NUMERIC(0);
1975 /* XXX would it be better to return NULL? */
1976 if (NUMERIC_IS_NAN(num))
1978 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1979 errmsg("cannot convert NaN to bigint")));
1981 /* Convert to variable format and thence to int8 */
1983 set_var_from_num(num, &x);
1985 if (!numericvar_to_int8(&x, &result))
1987 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1988 errmsg("bigint out of range")));
1992 PG_RETURN_INT64(result);
1997 int2_numeric(PG_FUNCTION_ARGS)
1999 int16 val = PG_GETARG_INT16(0);
2005 int8_to_numericvar((int64) val, &result);
2007 res = make_result(&result);
2011 PG_RETURN_NUMERIC(res);
2016 numeric_int2(PG_FUNCTION_ARGS)
2018 Numeric num = PG_GETARG_NUMERIC(0);
2023 /* XXX would it be better to return NULL? */
2024 if (NUMERIC_IS_NAN(num))
2026 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2027 errmsg("cannot convert NaN to smallint")));
2029 /* Convert to variable format and thence to int8 */
2031 set_var_from_num(num, &x);
2033 if (!numericvar_to_int8(&x, &val))
2035 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
2036 errmsg("smallint out of range")));
2040 /* Down-convert to int2 */
2041 result = (int16) val;
2043 /* Test for overflow by reverse-conversion. */
2044 if ((int64) result != val)
2046 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
2047 errmsg("smallint out of range")));
2049 PG_RETURN_INT16(result);
2054 float8_numeric(PG_FUNCTION_ARGS)
2056 float8 val = PG_GETARG_FLOAT8(0);
2059 char buf[DBL_DIG + 100];
2062 PG_RETURN_NUMERIC(make_result(&const_nan));
2064 sprintf(buf, "%.*g", DBL_DIG, val);
2068 set_var_from_str(buf, &result);
2069 res = make_result(&result);
2073 PG_RETURN_NUMERIC(res);
2078 numeric_float8(PG_FUNCTION_ARGS)
2080 Numeric num = PG_GETARG_NUMERIC(0);
2084 if (NUMERIC_IS_NAN(num))
2085 PG_RETURN_FLOAT8(get_float8_nan());
2087 tmp = DatumGetCString(DirectFunctionCall1(numeric_out,
2088 NumericGetDatum(num)));
2090 result = DirectFunctionCall1(float8in, CStringGetDatum(tmp));
2094 PG_RETURN_DATUM(result);
2098 /* Convert numeric to float8; if out of range, return +/- HUGE_VAL */
2100 numeric_float8_no_overflow(PG_FUNCTION_ARGS)
2102 Numeric num = PG_GETARG_NUMERIC(0);
2105 if (NUMERIC_IS_NAN(num))
2106 PG_RETURN_FLOAT8(get_float8_nan());
2108 val = numeric_to_double_no_overflow(num);
2110 PG_RETURN_FLOAT8(val);
2114 float4_numeric(PG_FUNCTION_ARGS)
2116 float4 val = PG_GETARG_FLOAT4(0);
2119 char buf[FLT_DIG + 100];
2122 PG_RETURN_NUMERIC(make_result(&const_nan));
2124 sprintf(buf, "%.*g", FLT_DIG, val);
2128 set_var_from_str(buf, &result);
2129 res = make_result(&result);
2133 PG_RETURN_NUMERIC(res);
2138 numeric_float4(PG_FUNCTION_ARGS)
2140 Numeric num = PG_GETARG_NUMERIC(0);
2144 if (NUMERIC_IS_NAN(num))
2145 PG_RETURN_FLOAT4(get_float4_nan());
2147 tmp = DatumGetCString(DirectFunctionCall1(numeric_out,
2148 NumericGetDatum(num)));
2150 result = DirectFunctionCall1(float4in, CStringGetDatum(tmp));
2154 PG_RETURN_DATUM(result);
2158 /* ----------------------------------------------------------------------
2160 * Aggregate functions
2162 * The transition datatype for all these aggregates is a 3-element array
2163 * of Numeric, holding the values N, sum(X), sum(X*X) in that order.
2165 * We represent N as a numeric mainly to avoid having to build a special
2166 * datatype; it's unlikely it'd overflow an int4, but ...
2168 * ----------------------------------------------------------------------
2172 do_numeric_accum(ArrayType *transarray, Numeric newval)
2181 /* We assume the input is array of numeric */
2182 deconstruct_array(transarray,
2183 NUMERICOID, -1, false, 'i',
2184 &transdatums, NULL, &ndatums);
2186 elog(ERROR, "expected 3-element numeric array");
2188 sumX = transdatums[1];
2189 sumX2 = transdatums[2];
2191 N = DirectFunctionCall1(numeric_inc, N);
2192 sumX = DirectFunctionCall2(numeric_add, sumX,
2193 NumericGetDatum(newval));
2194 sumX2 = DirectFunctionCall2(numeric_add, sumX2,
2195 DirectFunctionCall2(numeric_mul,
2196 NumericGetDatum(newval),
2197 NumericGetDatum(newval)));
2200 transdatums[1] = sumX;
2201 transdatums[2] = sumX2;
2203 result = construct_array(transdatums, 3,
2204 NUMERICOID, -1, false, 'i');
2210 * Improve avg performance by not caclulating sum(X*X).
2213 do_numeric_avg_accum(ArrayType *transarray, Numeric newval)
2221 /* We assume the input is array of numeric */
2222 deconstruct_array(transarray,
2223 NUMERICOID, -1, false, 'i',
2224 &transdatums, NULL, &ndatums);
2226 elog(ERROR, "expected 2-element numeric array");
2228 sumX = transdatums[1];
2230 N = DirectFunctionCall1(numeric_inc, N);
2231 sumX = DirectFunctionCall2(numeric_add, sumX,
2232 NumericGetDatum(newval));
2235 transdatums[1] = sumX;
2237 result = construct_array(transdatums, 2,
2238 NUMERICOID, -1, false, 'i');
2244 numeric_accum(PG_FUNCTION_ARGS)
2246 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
2247 Numeric newval = PG_GETARG_NUMERIC(1);
2249 PG_RETURN_ARRAYTYPE_P(do_numeric_accum(transarray, newval));
2253 * Optimized case for average of numeric.
2256 numeric_avg_accum(PG_FUNCTION_ARGS)
2258 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
2259 Numeric newval = PG_GETARG_NUMERIC(1);
2261 PG_RETURN_ARRAYTYPE_P(do_numeric_avg_accum(transarray, newval));
2265 * Integer data types all use Numeric accumulators to share code and
2266 * avoid risk of overflow. For int2 and int4 inputs, Numeric accumulation
2267 * is overkill for the N and sum(X) values, but definitely not overkill
2268 * for the sum(X*X) value. Hence, we use int2_accum and int4_accum only
2269 * for stddev/variance --- there are faster special-purpose accumulator
2270 * routines for SUM and AVG of these datatypes.
2274 int2_accum(PG_FUNCTION_ARGS)
2276 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
2277 Datum newval2 = PG_GETARG_DATUM(1);
2280 newval = DatumGetNumeric(DirectFunctionCall1(int2_numeric, newval2));
2282 PG_RETURN_ARRAYTYPE_P(do_numeric_accum(transarray, newval));
2286 int4_accum(PG_FUNCTION_ARGS)
2288 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
2289 Datum newval4 = PG_GETARG_DATUM(1);
2292 newval = DatumGetNumeric(DirectFunctionCall1(int4_numeric, newval4));
2294 PG_RETURN_ARRAYTYPE_P(do_numeric_accum(transarray, newval));
2298 int8_accum(PG_FUNCTION_ARGS)
2300 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
2301 Datum newval8 = PG_GETARG_DATUM(1);
2304 newval = DatumGetNumeric(DirectFunctionCall1(int8_numeric, newval8));
2306 PG_RETURN_ARRAYTYPE_P(do_numeric_accum(transarray, newval));
2310 * Optimized case for average of int8.
2313 int8_avg_accum(PG_FUNCTION_ARGS)
2315 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
2316 Datum newval8 = PG_GETARG_DATUM(1);
2319 newval = DatumGetNumeric(DirectFunctionCall1(int8_numeric, newval8));
2321 PG_RETURN_ARRAYTYPE_P(do_numeric_avg_accum(transarray, newval));
2326 numeric_avg(PG_FUNCTION_ARGS)
2328 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
2334 /* We assume the input is array of numeric */
2335 deconstruct_array(transarray,
2336 NUMERICOID, -1, false, 'i',
2337 &transdatums, NULL, &ndatums);
2339 elog(ERROR, "expected 2-element numeric array");
2340 N = DatumGetNumeric(transdatums[0]);
2341 sumX = DatumGetNumeric(transdatums[1]);
2343 /* SQL92 defines AVG of no values to be NULL */
2344 /* N is zero iff no digits (cf. numeric_uminus) */
2345 if (VARSIZE(N) == NUMERIC_HDRSZ)
2348 PG_RETURN_DATUM(DirectFunctionCall2(numeric_div,
2349 NumericGetDatum(sumX),
2350 NumericGetDatum(N)));
2354 * Workhorse routine for the standard deviance and variance
2355 * aggregates. 'transarray' is the aggregate's transition
2356 * array. 'variance' specifies whether we should calculate the
2357 * variance or the standard deviation. 'sample' indicates whether the
2358 * caller is interested in the sample or the population
2361 * If appropriate variance statistic is undefined for the input,
2362 * *is_null is set to true and NULL is returned.
2365 numeric_stddev_internal(ArrayType *transarray,
2366 bool variance, bool sample,
2384 /* We assume the input is array of numeric */
2385 deconstruct_array(transarray,
2386 NUMERICOID, -1, false, 'i',
2387 &transdatums, NULL, &ndatums);
2389 elog(ERROR, "expected 3-element numeric array");
2390 N = DatumGetNumeric(transdatums[0]);
2391 sumX = DatumGetNumeric(transdatums[1]);
2392 sumX2 = DatumGetNumeric(transdatums[2]);
2394 if (NUMERIC_IS_NAN(N) || NUMERIC_IS_NAN(sumX) || NUMERIC_IS_NAN(sumX2))
2395 return make_result(&const_nan);
2398 set_var_from_num(N, &vN);
2401 * Sample stddev and variance are undefined when N <= 1; population stddev
2402 * is undefined when N == 0. Return NULL in either case.
2409 if (cmp_var(&vN, comp) <= 0)
2416 init_var(&vNminus1);
2417 sub_var(&vN, &const_one, &vNminus1);
2420 set_var_from_num(sumX, &vsumX);
2422 set_var_from_num(sumX2, &vsumX2);
2424 /* compute rscale for mul_var calls */
2425 rscale = vsumX.dscale * 2;
2427 mul_var(&vsumX, &vsumX, &vsumX, rscale); /* vsumX = sumX * sumX */
2428 mul_var(&vN, &vsumX2, &vsumX2, rscale); /* vsumX2 = N * sumX2 */
2429 sub_var(&vsumX2, &vsumX, &vsumX2); /* N * sumX2 - sumX * sumX */
2431 if (cmp_var(&vsumX2, &const_zero) <= 0)
2433 /* Watch out for roundoff error producing a negative numerator */
2434 res = make_result(&const_zero);
2439 mul_var(&vN, &vNminus1, &vNminus1, 0); /* N * (N - 1) */
2441 mul_var(&vN, &vN, &vNminus1, 0); /* N * N */
2442 rscale = select_div_scale(&vsumX2, &vNminus1);
2443 div_var(&vsumX2, &vNminus1, &vsumX, rscale, true); /* variance */
2445 sqrt_var(&vsumX, &vsumX, rscale); /* stddev */
2447 res = make_result(&vsumX);
2451 free_var(&vNminus1);
2459 numeric_var_samp(PG_FUNCTION_ARGS)
2464 res = numeric_stddev_internal(PG_GETARG_ARRAYTYPE_P(0),
2465 true, true, &is_null);
2470 PG_RETURN_NUMERIC(res);
2474 numeric_stddev_samp(PG_FUNCTION_ARGS)
2479 res = numeric_stddev_internal(PG_GETARG_ARRAYTYPE_P(0),
2480 false, true, &is_null);
2485 PG_RETURN_NUMERIC(res);
2489 numeric_var_pop(PG_FUNCTION_ARGS)
2494 res = numeric_stddev_internal(PG_GETARG_ARRAYTYPE_P(0),
2495 true, false, &is_null);
2500 PG_RETURN_NUMERIC(res);
2504 numeric_stddev_pop(PG_FUNCTION_ARGS)
2509 res = numeric_stddev_internal(PG_GETARG_ARRAYTYPE_P(0),
2510 false, false, &is_null);
2515 PG_RETURN_NUMERIC(res);
2519 * SUM transition functions for integer datatypes.
2521 * To avoid overflow, we use accumulators wider than the input datatype.
2522 * A Numeric accumulator is needed for int8 input; for int4 and int2
2523 * inputs, we use int8 accumulators which should be sufficient for practical
2524 * purposes. (The latter two therefore don't really belong in this file,
2525 * but we keep them here anyway.)
2527 * Because SQL92 defines the SUM() of no values to be NULL, not zero,
2528 * the initial condition of the transition data value needs to be NULL. This
2529 * means we can't rely on ExecAgg to automatically insert the first non-null
2530 * data value into the transition data: it doesn't know how to do the type
2531 * conversion. The upshot is that these routines have to be marked non-strict
2532 * and handle substitution of the first non-null input themselves.
2536 int2_sum(PG_FUNCTION_ARGS)
2540 if (PG_ARGISNULL(0))
2542 /* No non-null input seen so far... */
2543 if (PG_ARGISNULL(1))
2544 PG_RETURN_NULL(); /* still no non-null */
2545 /* This is the first non-null input. */
2546 newval = (int64) PG_GETARG_INT16(1);
2547 PG_RETURN_INT64(newval);
2551 * If we're invoked by nodeAgg, we can cheat and modify out first
2552 * parameter in-place to avoid palloc overhead. If not, we need to return
2553 * the new value of the transition variable.
2555 if (fcinfo->context && IsA(fcinfo->context, AggState))
2557 int64 *oldsum = (int64 *) PG_GETARG_POINTER(0);
2559 /* Leave the running sum unchanged in the new input is null */
2560 if (!PG_ARGISNULL(1))
2561 *oldsum = *oldsum + (int64) PG_GETARG_INT16(1);
2563 PG_RETURN_POINTER(oldsum);
2567 int64 oldsum = PG_GETARG_INT64(0);
2569 /* Leave sum unchanged if new input is null. */
2570 if (PG_ARGISNULL(1))
2571 PG_RETURN_INT64(oldsum);
2573 /* OK to do the addition. */
2574 newval = oldsum + (int64) PG_GETARG_INT16(1);
2576 PG_RETURN_INT64(newval);
2581 int4_sum(PG_FUNCTION_ARGS)
2585 if (PG_ARGISNULL(0))
2587 /* No non-null input seen so far... */
2588 if (PG_ARGISNULL(1))
2589 PG_RETURN_NULL(); /* still no non-null */
2590 /* This is the first non-null input. */
2591 newval = (int64) PG_GETARG_INT32(1);
2592 PG_RETURN_INT64(newval);
2596 * If we're invoked by nodeAgg, we can cheat and modify out first
2597 * parameter in-place to avoid palloc overhead. If not, we need to return
2598 * the new value of the transition variable.
2600 if (fcinfo->context && IsA(fcinfo->context, AggState))
2602 int64 *oldsum = (int64 *) PG_GETARG_POINTER(0);
2604 /* Leave the running sum unchanged in the new input is null */
2605 if (!PG_ARGISNULL(1))
2606 *oldsum = *oldsum + (int64) PG_GETARG_INT32(1);
2608 PG_RETURN_POINTER(oldsum);
2612 int64 oldsum = PG_GETARG_INT64(0);
2614 /* Leave sum unchanged if new input is null. */
2615 if (PG_ARGISNULL(1))
2616 PG_RETURN_INT64(oldsum);
2618 /* OK to do the addition. */
2619 newval = oldsum + (int64) PG_GETARG_INT32(1);
2621 PG_RETURN_INT64(newval);
2626 int8_sum(PG_FUNCTION_ARGS)
2631 if (PG_ARGISNULL(0))
2633 /* No non-null input seen so far... */
2634 if (PG_ARGISNULL(1))
2635 PG_RETURN_NULL(); /* still no non-null */
2636 /* This is the first non-null input. */
2637 newval = DirectFunctionCall1(int8_numeric, PG_GETARG_DATUM(1));
2638 PG_RETURN_DATUM(newval);
2642 * Note that we cannot special-case the nodeAgg case here, as we do for
2643 * int2_sum and int4_sum: numeric is of variable size, so we cannot modify
2644 * our first parameter in-place.
2647 oldsum = PG_GETARG_NUMERIC(0);
2649 /* Leave sum unchanged if new input is null. */
2650 if (PG_ARGISNULL(1))
2651 PG_RETURN_NUMERIC(oldsum);
2653 /* OK to do the addition. */
2654 newval = DirectFunctionCall1(int8_numeric, PG_GETARG_DATUM(1));
2656 PG_RETURN_DATUM(DirectFunctionCall2(numeric_add,
2657 NumericGetDatum(oldsum), newval));
2662 * Routines for avg(int2) and avg(int4). The transition datatype
2663 * is a two-element int8 array, holding count and sum.
2666 typedef struct Int8TransTypeData
2668 #ifndef INT64_IS_BUSTED
2672 /* "int64" isn't really 64 bits, so fake up properly-aligned fields */
2678 } Int8TransTypeData;
2681 int2_avg_accum(PG_FUNCTION_ARGS)
2683 ArrayType *transarray;
2684 int16 newval = PG_GETARG_INT16(1);
2685 Int8TransTypeData *transdata;
2688 * If we're invoked by nodeAgg, we can cheat and modify our first
2689 * parameter in-place to reduce palloc overhead. Otherwise we need to make
2690 * a copy of it before scribbling on it.
2692 if (fcinfo->context && IsA(fcinfo->context, AggState))
2693 transarray = PG_GETARG_ARRAYTYPE_P(0);
2695 transarray = PG_GETARG_ARRAYTYPE_P_COPY(0);
2697 if (ARR_HASNULL(transarray) ||
2698 ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
2699 elog(ERROR, "expected 2-element int8 array");
2701 transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
2703 transdata->sum += newval;
2705 PG_RETURN_ARRAYTYPE_P(transarray);
2709 int4_avg_accum(PG_FUNCTION_ARGS)
2711 ArrayType *transarray;
2712 int32 newval = PG_GETARG_INT32(1);
2713 Int8TransTypeData *transdata;
2716 * If we're invoked by nodeAgg, we can cheat and modify our first
2717 * parameter in-place to reduce palloc overhead. Otherwise we need to make
2718 * a copy of it before scribbling on it.
2720 if (fcinfo->context && IsA(fcinfo->context, AggState))
2721 transarray = PG_GETARG_ARRAYTYPE_P(0);
2723 transarray = PG_GETARG_ARRAYTYPE_P_COPY(0);
2725 if (ARR_HASNULL(transarray) ||
2726 ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
2727 elog(ERROR, "expected 2-element int8 array");
2729 transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
2731 transdata->sum += newval;
2733 PG_RETURN_ARRAYTYPE_P(transarray);
2737 int8_avg(PG_FUNCTION_ARGS)
2739 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
2740 Int8TransTypeData *transdata;
2744 if (ARR_HASNULL(transarray) ||
2745 ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
2746 elog(ERROR, "expected 2-element int8 array");
2747 transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
2749 /* SQL92 defines AVG of no values to be NULL */
2750 if (transdata->count == 0)
2753 countd = DirectFunctionCall1(int8_numeric,
2754 Int64GetDatumFast(transdata->count));
2755 sumd = DirectFunctionCall1(int8_numeric,
2756 Int64GetDatumFast(transdata->sum));
2758 PG_RETURN_DATUM(DirectFunctionCall2(numeric_div, sumd, countd));
2762 /* ----------------------------------------------------------------------
2766 * ----------------------------------------------------------------------
2769 #ifdef NUMERIC_DEBUG
2772 * dump_numeric() - Dump a value in the db storage format for debugging
2775 dump_numeric(const char *str, Numeric num)
2777 NumericDigit *digits = NUMERIC_DIGITS(num);
2781 ndigits = NUMERIC_NDIGITS(num);
2783 printf("%s: NUMERIC w=%d d=%d ", str, num->n_weight, NUMERIC_DSCALE(num));
2784 switch (NUMERIC_SIGN(num))
2796 printf("SIGN=0x%x", NUMERIC_SIGN(num));
2800 for (i = 0; i < ndigits; i++)
2801 printf(" %0*d", DEC_DIGITS, digits[i]);
2807 * dump_var() - Dump a value in the variable format for debugging
2810 dump_var(const char *str, NumericVar *var)
2814 printf("%s: VAR w=%d d=%d ", str, var->weight, var->dscale);
2827 printf("SIGN=0x%x", var->sign);
2831 for (i = 0; i < var->ndigits; i++)
2832 printf(" %0*d", DEC_DIGITS, var->digits[i]);
2836 #endif /* NUMERIC_DEBUG */
2839 /* ----------------------------------------------------------------------
2841 * Local functions follow
2843 * In general, these do not support NaNs --- callers must eliminate
2844 * the possibility of NaN first. (make_result() is an exception.)
2846 * ----------------------------------------------------------------------
2853 * Allocate a digit buffer of ndigits digits (plus a spare digit for rounding)
2856 alloc_var(NumericVar *var, int ndigits)
2858 digitbuf_free(var->buf);
2859 var->buf = digitbuf_alloc(ndigits + 1);
2860 var->buf[0] = 0; /* spare digit for rounding */
2861 var->digits = var->buf + 1;
2862 var->ndigits = ndigits;
2869 * Return the digit buffer of a variable to the free pool
2872 free_var(NumericVar *var)
2874 digitbuf_free(var->buf);
2877 var->sign = NUMERIC_NAN;
2884 * Set a variable to ZERO.
2885 * Note: its dscale is not touched.
2888 zero_var(NumericVar *var)
2890 digitbuf_free(var->buf);
2894 var->weight = 0; /* by convention; doesn't really matter */
2895 var->sign = NUMERIC_POS; /* anything but NAN... */
2900 * set_var_from_str()
2902 * Parse a string and put the number into a variable
2905 set_var_from_str(const char *str, NumericVar *dest)
2907 const char *cp = str;
2908 bool have_dp = FALSE;
2910 unsigned char *decdigits;
2911 int sign = NUMERIC_POS;
2918 NumericDigit *digits;
2921 * We first parse the string to extract decimal digits and determine the
2922 * correct decimal weight. Then convert to NBASE representation.
2925 /* skip leading spaces */
2928 if (!isspace((unsigned char) *cp))
2952 if (!isdigit((unsigned char) *cp))
2954 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
2955 errmsg("invalid input syntax for type numeric: \"%s\"", str)));
2957 decdigits = (unsigned char *) palloc(strlen(cp) + DEC_DIGITS * 2);
2959 /* leading padding for digit alignment later */
2960 memset(decdigits, 0, DEC_DIGITS);
2965 if (isdigit((unsigned char) *cp))
2967 decdigits[i++] = *cp++ - '0';
2973 else if (*cp == '.')
2977 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
2978 errmsg("invalid input syntax for type numeric: \"%s\"",
2987 ddigits = i - DEC_DIGITS;
2988 /* trailing padding for digit alignment later */
2989 memset(decdigits + i, 0, DEC_DIGITS - 1);
2991 /* Handle exponent, if any */
2992 if (*cp == 'e' || *cp == 'E')
2998 exponent = strtol(cp, &endptr, 10);
3001 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
3002 errmsg("invalid input syntax for type numeric: \"%s\"",
3005 if (exponent > NUMERIC_MAX_PRECISION ||
3006 exponent < -NUMERIC_MAX_PRECISION)
3008 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
3009 errmsg("invalid input syntax for type numeric: \"%s\"",
3011 dweight += (int) exponent;
3012 dscale -= (int) exponent;
3017 /* Should be nothing left but spaces */
3020 if (!isspace((unsigned char) *cp))
3022 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
3023 errmsg("invalid input syntax for type numeric: \"%s\"",
3029 * Okay, convert pure-decimal representation to base NBASE. First we need
3030 * to determine the converted weight and ndigits. offset is the number of
3031 * decimal zeroes to insert before the first given digit to have a
3032 * correctly aligned first NBASE digit.
3035 weight = (dweight + 1 + DEC_DIGITS - 1) / DEC_DIGITS - 1;
3037 weight = -((-dweight - 1) / DEC_DIGITS + 1);
3038 offset = (weight + 1) * DEC_DIGITS - (dweight + 1);
3039 ndigits = (ddigits + offset + DEC_DIGITS - 1) / DEC_DIGITS;
3041 alloc_var(dest, ndigits);
3043 dest->weight = weight;
3044 dest->dscale = dscale;
3046 i = DEC_DIGITS - offset;
3047 digits = dest->digits;
3049 while (ndigits-- > 0)
3052 *digits++ = ((decdigits[i] * 10 + decdigits[i + 1]) * 10 +
3053 decdigits[i + 2]) * 10 + decdigits[i + 3];
3054 #elif DEC_DIGITS == 2
3055 *digits++ = decdigits[i] * 10 + decdigits[i + 1];
3056 #elif DEC_DIGITS == 1
3057 *digits++ = decdigits[i];
3059 #error unsupported NBASE
3066 /* Strip any leading/trailing zeroes, and normalize weight if zero */
3072 * set_var_from_num() -
3074 * Convert the packed db format into a variable
3077 set_var_from_num(Numeric num, NumericVar *dest)
3081 ndigits = NUMERIC_NDIGITS(num);
3083 alloc_var(dest, ndigits);
3085 dest->weight = num->n_weight;
3086 dest->sign = NUMERIC_SIGN(num);
3087 dest->dscale = NUMERIC_DSCALE(num);
3089 memcpy(dest->digits, num->n_data, ndigits * sizeof(NumericDigit));
3094 * set_var_from_var() -
3096 * Copy one variable into another
3099 set_var_from_var(NumericVar *value, NumericVar *dest)
3101 NumericDigit *newbuf;
3103 newbuf = digitbuf_alloc(value->ndigits + 1);
3104 newbuf[0] = 0; /* spare digit for rounding */
3105 memcpy(newbuf + 1, value->digits, value->ndigits * sizeof(NumericDigit));
3107 digitbuf_free(dest->buf);
3109 memmove(dest, value, sizeof(NumericVar));
3111 dest->digits = newbuf + 1;
3116 * get_str_from_var() -
3118 * Convert a var to text representation (guts of numeric_out).
3119 * CAUTION: var's contents may be modified by rounding!
3120 * Returns a palloc'd string.
3123 get_str_from_var(NumericVar *var, int dscale)
3140 * Check if we must round up before printing the value and do so.
3142 round_var(var, dscale);
3145 * Allocate space for the result.
3147 * i is set to to # of decimal digits before decimal point. dscale is the
3148 * # of decimal digits we will print after decimal point. We may generate
3149 * as many as DEC_DIGITS-1 excess digits at the end, and in addition we
3150 * need room for sign, decimal point, null terminator.
3152 i = (var->weight + 1) * DEC_DIGITS;
3156 str = palloc(i + dscale + DEC_DIGITS + 2);
3160 * Output a dash for negative values
3162 if (var->sign == NUMERIC_NEG)
3166 * Output all digits before the decimal point
3168 if (var->weight < 0)
3170 d = var->weight + 1;
3175 for (d = 0; d <= var->weight; d++)
3177 dig = (d < var->ndigits) ? var->digits[d] : 0;
3178 /* In the first digit, suppress extra leading decimal zeroes */
3181 bool putit = (d > 0);
3200 #elif DEC_DIGITS == 2
3203 if (d1 > 0 || d > 0)
3206 #elif DEC_DIGITS == 1
3209 #error unsupported NBASE
3215 * If requested, output a decimal point and all the digits that follow it.
3216 * We initially put out a multiple of DEC_DIGITS digits, then truncate if
3222 endcp = cp + dscale;
3223 for (i = 0; i < dscale; d++, i += DEC_DIGITS)
3225 dig = (d >= 0 && d < var->ndigits) ? var->digits[d] : 0;
3237 #elif DEC_DIGITS == 2
3242 #elif DEC_DIGITS == 1
3245 #error unsupported NBASE
3252 * terminate the string and return it
3262 * Create the packed db numeric format in palloc()'d memory from
3266 make_result(NumericVar *var)
3269 NumericDigit *digits = var->digits;
3270 int weight = var->weight;
3271 int sign = var->sign;
3275 if (sign == NUMERIC_NAN)
3277 result = (Numeric) palloc(NUMERIC_HDRSZ);
3279 SET_VARSIZE(result, NUMERIC_HDRSZ);
3280 result->n_weight = 0;
3281 result->n_sign_dscale = NUMERIC_NAN;
3283 dump_numeric("make_result()", result);
3289 /* truncate leading zeroes */
3290 while (n > 0 && *digits == 0)
3296 /* truncate trailing zeroes */
3297 while (n > 0 && digits[n - 1] == 0)
3300 /* If zero result, force to weight=0 and positive sign */
3307 /* Build the result */
3308 len = NUMERIC_HDRSZ + n * sizeof(NumericDigit);
3309 result = (Numeric) palloc(len);
3310 SET_VARSIZE(result, len);
3311 result->n_weight = weight;
3312 result->n_sign_dscale = sign | (var->dscale & NUMERIC_DSCALE_MASK);
3314 memcpy(result->n_data, digits, n * sizeof(NumericDigit));
3316 /* Check for overflow of int16 fields */
3317 if (result->n_weight != weight ||
3318 NUMERIC_DSCALE(result) != var->dscale)
3320 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
3321 errmsg("value overflows numeric format")));
3323 dump_numeric("make_result()", result);
3331 * Do bounds checking and rounding according to the attributes
3335 apply_typmod(NumericVar *var, int32 typmod)
3343 /* Do nothing if we have a default typmod (-1) */
3344 if (typmod < (int32) (VARHDRSZ))
3348 precision = (typmod >> 16) & 0xffff;
3349 scale = typmod & 0xffff;
3350 maxdigits = precision - scale;
3352 /* Round to target scale (and set var->dscale) */
3353 round_var(var, scale);
3356 * Check for overflow - note we can't do this before rounding, because
3357 * rounding could raise the weight. Also note that the var's weight could
3358 * be inflated by leading zeroes, which will be stripped before storage
3359 * but perhaps might not have been yet. In any case, we must recognize a
3360 * true zero, whose weight doesn't mean anything.
3362 ddigits = (var->weight + 1) * DEC_DIGITS;
3363 if (ddigits > maxdigits)
3365 /* Determine true weight; and check for all-zero result */
3366 for (i = 0; i < var->ndigits; i++)
3368 NumericDigit dig = var->digits[i];
3372 /* Adjust for any high-order decimal zero digits */
3378 else if (dig < 1000)
3380 #elif DEC_DIGITS == 2
3383 #elif DEC_DIGITS == 1
3386 #error unsupported NBASE
3388 if (ddigits > maxdigits)
3390 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
3391 errmsg("numeric field overflow"),
3392 errdetail("A field with precision %d, scale %d must round to an absolute value less than %s%d.",
3394 /* Display 10^0 as 1 */
3395 maxdigits ? "10^" : "",
3396 maxdigits ? maxdigits : 1
3400 ddigits -= DEC_DIGITS;
3406 * Convert numeric to int8, rounding if needed.
3408 * If overflow, return FALSE (no error is raised). Return TRUE if okay.
3410 * CAUTION: var's contents may be modified by rounding!
3413 numericvar_to_int8(NumericVar *var, int64 *result)
3415 NumericDigit *digits;
3423 /* Round to nearest integer */
3426 /* Check for zero input */
3428 ndigits = var->ndigits;
3436 * For input like 10000000000, we must treat stripped digits as real. So
3437 * the loop assumes there are weight+1 digits before the decimal point.
3439 weight = var->weight;
3440 Assert(weight >= 0 && ndigits <= weight + 1);
3442 /* Construct the result */
3443 digits = var->digits;
3444 neg = (var->sign == NUMERIC_NEG);
3446 for (i = 1; i <= weight; i++)
3454 * The overflow check is a bit tricky because we want to accept
3455 * INT64_MIN, which will overflow the positive accumulator. We can
3456 * detect this case easily though because INT64_MIN is the only
3457 * nonzero value for which -val == val (on a two's complement machine,
3460 if ((val / NBASE) != oldval) /* possible overflow? */
3462 if (!neg || (-val) != val || val == 0 || oldval < 0)
3467 *result = neg ? -val : val;
3472 * Convert int8 value to numeric.
3475 int8_to_numericvar(int64 val, NumericVar *var)
3482 /* int8 can require at most 19 decimal digits; add one for safety */
3483 alloc_var(var, 20 / DEC_DIGITS);
3486 var->sign = NUMERIC_NEG;
3491 var->sign = NUMERIC_POS;
3501 ptr = var->digits + var->ndigits;
3507 newuval = uval / NBASE;
3508 *ptr = uval - newuval * NBASE;
3512 var->ndigits = ndigits;
3513 var->weight = ndigits - 1;
3517 * Convert numeric to float8; if out of range, return +/- HUGE_VAL
3520 numeric_to_double_no_overflow(Numeric num)
3526 tmp = DatumGetCString(DirectFunctionCall1(numeric_out,
3527 NumericGetDatum(num)));
3529 /* unlike float8in, we ignore ERANGE from strtod */
3530 val = strtod(tmp, &endptr);
3531 if (*endptr != '\0')
3533 /* shouldn't happen ... */
3535 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
3536 errmsg("invalid input syntax for type double precision: \"%s\"",
3545 /* As above, but work from a NumericVar */
3547 numericvar_to_double_no_overflow(NumericVar *var)
3553 tmp = get_str_from_var(var, var->dscale);
3555 /* unlike float8in, we ignore ERANGE from strtod */
3556 val = strtod(tmp, &endptr);
3557 if (*endptr != '\0')
3559 /* shouldn't happen ... */
3561 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
3562 errmsg("invalid input syntax for type double precision: \"%s\"",
3575 * Compare two values on variable level. We assume zeroes have been
3576 * truncated to no digits.
3579 cmp_var(NumericVar *var1, NumericVar *var2)
3581 return cmp_var_common(var1->digits, var1->ndigits,
3582 var1->weight, var1->sign,
3583 var2->digits, var2->ndigits,
3584 var2->weight, var2->sign);
3588 * cmp_var_common() -
3590 * Main routine of cmp_var(). This function can be used by both
3591 * NumericVar and Numeric.
3594 cmp_var_common(const NumericDigit *var1digits, int var1ndigits,
3595 int var1weight, int var1sign,
3596 const NumericDigit *var2digits, int var2ndigits,
3597 int var2weight, int var2sign)
3599 if (var1ndigits == 0)
3601 if (var2ndigits == 0)
3603 if (var2sign == NUMERIC_NEG)
3607 if (var2ndigits == 0)
3609 if (var1sign == NUMERIC_POS)
3614 if (var1sign == NUMERIC_POS)
3616 if (var2sign == NUMERIC_NEG)
3618 return cmp_abs_common(var1digits, var1ndigits, var1weight,
3619 var2digits, var2ndigits, var2weight);
3622 if (var2sign == NUMERIC_POS)
3625 return cmp_abs_common(var2digits, var2ndigits, var2weight,
3626 var1digits, var1ndigits, var1weight);
3633 * Full version of add functionality on variable level (handling signs).
3634 * result might point to one of the operands too without danger.
3637 add_var(NumericVar *var1, NumericVar *var2, NumericVar *result)
3640 * Decide on the signs of the two variables what to do
3642 if (var1->sign == NUMERIC_POS)
3644 if (var2->sign == NUMERIC_POS)
3647 * Both are positive result = +(ABS(var1) + ABS(var2))
3649 add_abs(var1, var2, result);
3650 result->sign = NUMERIC_POS;
3655 * var1 is positive, var2 is negative Must compare absolute values
3657 switch (cmp_abs(var1, var2))
3661 * ABS(var1) == ABS(var2)
3666 result->dscale = Max(var1->dscale, var2->dscale);
3671 * ABS(var1) > ABS(var2)
3672 * result = +(ABS(var1) - ABS(var2))
3675 sub_abs(var1, var2, result);
3676 result->sign = NUMERIC_POS;
3681 * ABS(var1) < ABS(var2)
3682 * result = -(ABS(var2) - ABS(var1))
3685 sub_abs(var2, var1, result);
3686 result->sign = NUMERIC_NEG;
3693 if (var2->sign == NUMERIC_POS)
3696 * var1 is negative, var2 is positive
3697 * Must compare absolute values
3700 switch (cmp_abs(var1, var2))
3704 * ABS(var1) == ABS(var2)
3709 result->dscale = Max(var1->dscale, var2->dscale);
3714 * ABS(var1) > ABS(var2)
3715 * result = -(ABS(var1) - ABS(var2))
3718 sub_abs(var1, var2, result);
3719 result->sign = NUMERIC_NEG;
3724 * ABS(var1) < ABS(var2)
3725 * result = +(ABS(var2) - ABS(var1))
3728 sub_abs(var2, var1, result);
3729 result->sign = NUMERIC_POS;
3737 * result = -(ABS(var1) + ABS(var2))
3740 add_abs(var1, var2, result);
3741 result->sign = NUMERIC_NEG;
3750 * Full version of sub functionality on variable level (handling signs).
3751 * result might point to one of the operands too without danger.
3754 sub_var(NumericVar *var1, NumericVar *var2, NumericVar *result)
3757 * Decide on the signs of the two variables what to do
3759 if (var1->sign == NUMERIC_POS)
3761 if (var2->sign == NUMERIC_NEG)
3764 * var1 is positive, var2 is negative
3765 * result = +(ABS(var1) + ABS(var2))
3768 add_abs(var1, var2, result);
3769 result->sign = NUMERIC_POS;
3775 * Must compare absolute values
3778 switch (cmp_abs(var1, var2))
3782 * ABS(var1) == ABS(var2)
3787 result->dscale = Max(var1->dscale, var2->dscale);
3792 * ABS(var1) > ABS(var2)
3793 * result = +(ABS(var1) - ABS(var2))
3796 sub_abs(var1, var2, result);
3797 result->sign = NUMERIC_POS;
3802 * ABS(var1) < ABS(var2)
3803 * result = -(ABS(var2) - ABS(var1))
3806 sub_abs(var2, var1, result);
3807 result->sign = NUMERIC_NEG;
3814 if (var2->sign == NUMERIC_NEG)
3818 * Must compare absolute values
3821 switch (cmp_abs(var1, var2))
3825 * ABS(var1) == ABS(var2)
3830 result->dscale = Max(var1->dscale, var2->dscale);
3835 * ABS(var1) > ABS(var2)
3836 * result = -(ABS(var1) - ABS(var2))
3839 sub_abs(var1, var2, result);
3840 result->sign = NUMERIC_NEG;
3845 * ABS(var1) < ABS(var2)
3846 * result = +(ABS(var2) - ABS(var1))
3849 sub_abs(var2, var1, result);
3850 result->sign = NUMERIC_POS;
3857 * var1 is negative, var2 is positive
3858 * result = -(ABS(var1) + ABS(var2))
3861 add_abs(var1, var2, result);
3862 result->sign = NUMERIC_NEG;
3871 * Multiplication on variable level. Product of var1 * var2 is stored
3872 * in result. Result is rounded to no more than rscale fractional digits.
3875 mul_var(NumericVar *var1, NumericVar *var2, NumericVar *result,
3886 NumericDigit *res_digits;
3892 /* copy these values into local vars for speed in inner loop */
3893 int var1ndigits = var1->ndigits;
3894 int var2ndigits = var2->ndigits;
3895 NumericDigit *var1digits = var1->digits;
3896 NumericDigit *var2digits = var2->digits;
3898 if (var1ndigits == 0 || var2ndigits == 0)
3900 /* one or both inputs is zero; so is result */
3902 result->dscale = rscale;
3906 /* Determine result sign and (maximum possible) weight */
3907 if (var1->sign == var2->sign)
3908 res_sign = NUMERIC_POS;
3910 res_sign = NUMERIC_NEG;
3911 res_weight = var1->weight + var2->weight + 2;
3914 * Determine number of result digits to compute. If the exact result
3915 * would have more than rscale fractional digits, truncate the computation
3916 * with MUL_GUARD_DIGITS guard digits. We do that by pretending that one
3917 * or both inputs have fewer digits than they really do.
3919 res_ndigits = var1ndigits + var2ndigits + 1;
3920 maxdigits = res_weight + 1 + (rscale * DEC_DIGITS) + MUL_GUARD_DIGITS;
3921 if (res_ndigits > maxdigits)
3925 /* no useful precision at all in the result... */
3927 result->dscale = rscale;
3930 /* force maxdigits odd so that input ndigits can be equal */
3931 if ((maxdigits & 1) == 0)
3933 if (var1ndigits > var2ndigits)
3935 var1ndigits -= res_ndigits - maxdigits;
3936 if (var1ndigits < var2ndigits)
3937 var1ndigits = var2ndigits = (var1ndigits + var2ndigits) / 2;
3941 var2ndigits -= res_ndigits - maxdigits;
3942 if (var2ndigits < var1ndigits)
3943 var1ndigits = var2ndigits = (var1ndigits + var2ndigits) / 2;
3945 res_ndigits = maxdigits;
3946 Assert(res_ndigits == var1ndigits + var2ndigits + 1);
3950 * We do the arithmetic in an array "dig[]" of signed int's. Since
3951 * INT_MAX is noticeably larger than NBASE*NBASE, this gives us headroom
3952 * to avoid normalizing carries immediately.
3954 * maxdig tracks the maximum possible value of any dig[] entry; when this
3955 * threatens to exceed INT_MAX, we take the time to propagate carries. To
3956 * avoid overflow in maxdig itself, it actually represents the max
3957 * possible value divided by NBASE-1.
3959 dig = (int *) palloc0(res_ndigits * sizeof(int));
3962 ri = res_ndigits - 1;
3963 for (i1 = var1ndigits - 1; i1 >= 0; ri--, i1--)
3965 int var1digit = var1digits[i1];
3970 /* Time to normalize? */
3971 maxdig += var1digit;
3972 if (maxdig > INT_MAX / (NBASE - 1))
3976 for (i = res_ndigits - 1; i >= 0; i--)
3978 newdig = dig[i] + carry;
3979 if (newdig >= NBASE)
3981 carry = newdig / NBASE;
3982 newdig -= carry * NBASE;
3989 /* Reset maxdig to indicate new worst-case */
3990 maxdig = 1 + var1digit;
3993 /* Add appropriate multiple of var2 into the accumulator */
3995 for (i2 = var2ndigits - 1; i2 >= 0; i2--)
3996 dig[i--] += var1digit * var2digits[i2];
4000 * Now we do a final carry propagation pass to normalize the result, which
4001 * we combine with storing the result digits into the output. Note that
4002 * this is still done at full precision w/guard digits.
4004 alloc_var(result, res_ndigits);
4005 res_digits = result->digits;
4007 for (i = res_ndigits - 1; i >= 0; i--)
4009 newdig = dig[i] + carry;
4010 if (newdig >= NBASE)
4012 carry = newdig / NBASE;
4013 newdig -= carry * NBASE;
4017 res_digits[i] = newdig;
4024 * Finally, round the result to the requested precision.
4026 result->weight = res_weight;
4027 result->sign = res_sign;
4029 /* Round to target rscale (and set result->dscale) */
4030 round_var(result, rscale);
4032 /* Strip leading and trailing zeroes */
4040 * Division on variable level. Quotient of var1 / var2 is stored
4041 * in result. Result is rounded to no more than rscale fractional digits.
4044 div_var(NumericVar *var1, NumericVar *var2, NumericVar *result,
4045 int rscale, bool round)
4055 NumericDigit *res_digits;
4063 /* copy these values into local vars for speed in inner loop */
4064 int var1ndigits = var1->ndigits;
4065 int var2ndigits = var2->ndigits;
4066 NumericDigit *var1digits = var1->digits;
4067 NumericDigit *var2digits = var2->digits;
4070 * First of all division by zero check; we must not be handed an
4071 * unnormalized divisor.
4073 if (var2ndigits == 0 || var2digits[0] == 0)
4075 (errcode(ERRCODE_DIVISION_BY_ZERO),
4076 errmsg("division by zero")));
4079 * Now result zero check
4081 if (var1ndigits == 0)
4084 result->dscale = rscale;
4089 * Determine the result sign, weight and number of digits to calculate
4091 if (var1->sign == var2->sign)
4092 res_sign = NUMERIC_POS;
4094 res_sign = NUMERIC_NEG;
4095 res_weight = var1->weight - var2->weight + 1;
4096 /* The number of accurate result digits we need to produce: */
4097 div_ndigits = res_weight + 1 + (rscale + DEC_DIGITS - 1) / DEC_DIGITS;
4098 /* Add guard digits for roundoff error */
4099 div_ndigits += DIV_GUARD_DIGITS;
4100 if (div_ndigits < DIV_GUARD_DIGITS)
4101 div_ndigits = DIV_GUARD_DIGITS;
4102 /* Must be at least var1ndigits, too, to simplify data-loading loop */
4103 if (div_ndigits < var1ndigits)
4104 div_ndigits = var1ndigits;
4107 * We do the arithmetic in an array "div[]" of signed int's. Since
4108 * INT_MAX is noticeably larger than NBASE*NBASE, this gives us headroom
4109 * to avoid normalizing carries immediately.
4111 * We start with div[] containing one zero digit followed by the
4112 * dividend's digits (plus appended zeroes to reach the desired precision
4113 * including guard digits). Each step of the main loop computes an
4114 * (approximate) quotient digit and stores it into div[], removing one
4115 * position of dividend space. A final pass of carry propagation takes
4116 * care of any mistaken quotient digits.
4118 div = (int *) palloc0((div_ndigits + 1) * sizeof(int));
4119 for (i = 0; i < var1ndigits; i++)
4120 div[i + 1] = var1digits[i];
4123 * We estimate each quotient digit using floating-point arithmetic, taking
4124 * the first four digits of the (current) dividend and divisor. This must
4125 * be float to avoid overflow.
4127 fdivisor = (double) var2digits[0];
4128 for (i = 1; i < 4; i++)
4131 if (i < var2ndigits)
4132 fdivisor += (double) var2digits[i];
4134 fdivisorinverse = 1.0 / fdivisor;
4137 * maxdiv tracks the maximum possible absolute value of any div[] entry;
4138 * when this threatens to exceed INT_MAX, we take the time to propagate
4139 * carries. To avoid overflow in maxdiv itself, it actually represents
4140 * the max possible abs. value divided by NBASE-1.
4145 * Outer loop computes next quotient digit, which will go into div[qi]
4147 for (qi = 0; qi < div_ndigits; qi++)
4149 /* Approximate the current dividend value */
4150 fdividend = (double) div[qi];
4151 for (i = 1; i < 4; i++)
4154 if (qi + i <= div_ndigits)
4155 fdividend += (double) div[qi + i];
4157 /* Compute the (approximate) quotient digit */
4158 fquotient = fdividend * fdivisorinverse;
4159 qdigit = (fquotient >= 0.0) ? ((int) fquotient) :
4160 (((int) fquotient) - 1); /* truncate towards -infinity */
4164 /* Do we need to normalize now? */
4165 maxdiv += Abs(qdigit);
4166 if (maxdiv > INT_MAX / (NBASE - 1))
4170 for (i = div_ndigits; i > qi; i--)
4172 newdig = div[i] + carry;
4175 carry = -((-newdig - 1) / NBASE) - 1;
4176 newdig -= carry * NBASE;
4178 else if (newdig >= NBASE)
4180 carry = newdig / NBASE;
4181 newdig -= carry * NBASE;
4187 newdig = div[qi] + carry;
4191 * All the div[] digits except possibly div[qi] are now in the
4194 maxdiv = Abs(newdig) / (NBASE - 1);
4195 maxdiv = Max(maxdiv, 1);
4198 * Recompute the quotient digit since new info may have
4199 * propagated into the top four dividend digits
4201 fdividend = (double) div[qi];
4202 for (i = 1; i < 4; i++)
4205 if (qi + i <= div_ndigits)
4206 fdividend += (double) div[qi + i];
4208 /* Compute the (approximate) quotient digit */
4209 fquotient = fdividend * fdivisorinverse;
4210 qdigit = (fquotient >= 0.0) ? ((int) fquotient) :
4211 (((int) fquotient) - 1); /* truncate towards -infinity */
4212 maxdiv += Abs(qdigit);
4215 /* Subtract off the appropriate multiple of the divisor */
4218 int istop = Min(var2ndigits, div_ndigits - qi + 1);
4220 for (i = 0; i < istop; i++)
4221 div[qi + i] -= qdigit * var2digits[i];
4226 * The dividend digit we are about to replace might still be nonzero.
4227 * Fold it into the next digit position. We don't need to worry about
4228 * overflow here since this should nearly cancel with the subtraction
4231 div[qi + 1] += div[qi] * NBASE;
4237 * Approximate and store the last quotient digit (div[div_ndigits])
4239 fdividend = (double) div[qi];
4240 for (i = 1; i < 4; i++)
4242 fquotient = fdividend * fdivisorinverse;
4243 qdigit = (fquotient >= 0.0) ? ((int) fquotient) :
4244 (((int) fquotient) - 1); /* truncate towards -infinity */
4248 * Now we do a final carry propagation pass to normalize the result, which
4249 * we combine with storing the result digits into the output. Note that
4250 * this is still done at full precision w/guard digits.
4252 alloc_var(result, div_ndigits + 1);
4253 res_digits = result->digits;
4255 for (i = div_ndigits; i >= 0; i--)
4257 newdig = div[i] + carry;
4260 carry = -((-newdig - 1) / NBASE) - 1;
4261 newdig -= carry * NBASE;
4263 else if (newdig >= NBASE)
4265 carry = newdig / NBASE;
4266 newdig -= carry * NBASE;
4270 res_digits[i] = newdig;
4277 * Finally, round the result to the requested precision.
4279 result->weight = res_weight;
4280 result->sign = res_sign;
4282 /* Round to target rscale (and set result->dscale) */
4284 round_var(result, rscale);
4286 trunc_var(result, rscale);
4288 /* Strip leading and trailing zeroes */
4294 * Default scale selection for division
4296 * Returns the appropriate result scale for the division result.
4299 select_div_scale(NumericVar *var1, NumericVar *var2)
4305 NumericDigit firstdigit1,
4310 * The result scale of a division isn't specified in any SQL standard. For
4311 * PostgreSQL we select a result scale that will give at least
4312 * NUMERIC_MIN_SIG_DIGITS significant digits, so that numeric gives a
4313 * result no less accurate than float8; but use a scale not less than
4314 * either input's display scale.
4317 /* Get the actual (normalized) weight and first digit of each input */
4319 weight1 = 0; /* values to use if var1 is zero */
4321 for (i = 0; i < var1->ndigits; i++)
4323 firstdigit1 = var1->digits[i];
4324 if (firstdigit1 != 0)
4326 weight1 = var1->weight - i;
4331 weight2 = 0; /* values to use if var2 is zero */
4333 for (i = 0; i < var2->ndigits; i++)
4335 firstdigit2 = var2->digits[i];
4336 if (firstdigit2 != 0)
4338 weight2 = var2->weight - i;
4344 * Estimate weight of quotient. If the two first digits are equal, we
4345 * can't be sure, but assume that var1 is less than var2.
4347 qweight = weight1 - weight2;
4348 if (firstdigit1 <= firstdigit2)
4351 /* Select result scale */
4352 rscale = NUMERIC_MIN_SIG_DIGITS - qweight * DEC_DIGITS;
4353 rscale = Max(rscale, var1->dscale);
4354 rscale = Max(rscale, var2->dscale);
4355 rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
4356 rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
4365 * Calculate the modulo of two numerics at variable level
4368 mod_var(NumericVar *var1, NumericVar *var2, NumericVar *result)
4376 * We do this using the equation
4377 * mod(x,y) = x - trunc(x/y)*y
4378 * We set rscale the same way numeric_div and numeric_mul do
4379 * to get the right answer from the equation. The final result,
4380 * however, need not be displayed to more precision than the inputs.
4383 rscale = select_div_scale(var1, var2);
4385 div_var(var1, var2, &tmp, rscale, false);
4389 mul_var(var2, &tmp, &tmp, var2->dscale + tmp.dscale);
4391 sub_var(var1, &tmp, result);
4393 round_var(result, Max(var1->dscale, var2->dscale));
4402 * Return the smallest integer greater than or equal to the argument
4406 ceil_var(NumericVar *var, NumericVar *result)
4411 set_var_from_var(var, &tmp);
4415 if (var->sign == NUMERIC_POS && cmp_var(var, &tmp) != 0)
4416 add_var(&tmp, &const_one, &tmp);
4418 set_var_from_var(&tmp, result);
4426 * Return the largest integer equal to or less than the argument
4430 floor_var(NumericVar *var, NumericVar *result)
4435 set_var_from_var(var, &tmp);
4439 if (var->sign == NUMERIC_NEG && cmp_var(var, &tmp) != 0)
4440 sub_var(&tmp, &const_one, &tmp);
4442 set_var_from_var(&tmp, result);
4450 * Compute the square root of x using Newton's algorithm
4453 sqrt_var(NumericVar *arg, NumericVar *result, int rscale)
4457 NumericVar last_val;
4461 local_rscale = rscale + 8;
4463 stat = cmp_var(arg, &const_zero);
4467 result->dscale = rscale;
4472 * SQL2003 defines sqrt() in terms of power, so we need to emit the right
4473 * SQLSTATE error code if the operand is negative.
4477 (errcode(ERRCODE_INVALID_ARGUMENT_FOR_POWER_FUNCTION),
4478 errmsg("cannot take square root of a negative number")));
4482 init_var(&last_val);
4484 /* Copy arg in case it is the same var as result */
4485 set_var_from_var(arg, &tmp_arg);
4488 * Initialize the result to the first guess
4490 alloc_var(result, 1);
4491 result->digits[0] = tmp_arg.digits[0] / 2;
4492 if (result->digits[0] == 0)
4493 result->digits[0] = 1;
4494 result->weight = tmp_arg.weight / 2;
4495 result->sign = NUMERIC_POS;
4497 set_var_from_var(result, &last_val);
4501 div_var(&tmp_arg, result, &tmp_val, local_rscale, true);
4503 add_var(result, &tmp_val, result);
4504 mul_var(result, &const_zero_point_five, result, local_rscale);
4506 if (cmp_var(&last_val, result) == 0)
4508 set_var_from_var(result, &last_val);
4511 free_var(&last_val);
4515 /* Round to requested precision */
4516 round_var(result, rscale);
4523 * Raise e to the power of x
4526 exp_var(NumericVar *arg, NumericVar *result, int rscale)
4534 * We separate the integral and fraction parts of x, then compute
4535 * e^x = e^xint * e^xfrac
4536 * where e = exp(1) and e^xfrac = exp(xfrac) are computed by
4537 * exp_var_internal; the limited range of inputs allows that routine
4538 * to do a good job with a simple Taylor series. Raising e^xint is
4539 * done by repeated multiplications in power_var_int.
4544 set_var_from_var(arg, &x);
4546 if (x.sign == NUMERIC_NEG)
4549 x.sign = NUMERIC_POS;
4552 /* Extract the integer part, remove it from x */
4554 while (x.weight >= 0)
4559 xintval += x.digits[0];
4564 /* Guard against overflow */
4565 if (xintval >= NUMERIC_MAX_RESULT_SCALE * 3)
4567 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
4568 errmsg("argument for function \"exp\" too big")));
4571 /* Select an appropriate scale for internal calculation */
4572 local_rscale = rscale + MUL_GUARD_DIGITS * 2;
4574 /* Compute e^xfrac */
4575 exp_var_internal(&x, result, local_rscale);
4577 /* If there's an integer part, multiply by e^xint */
4583 exp_var_internal(&const_one, &e, local_rscale);
4584 power_var_int(&e, xintval, &e, local_rscale);
4585 mul_var(&e, result, result, local_rscale);
4589 /* Compensate for input sign, and round to requested rscale */
4591 div_var(&const_one, result, result, rscale, true);
4593 round_var(result, rscale);
4600 * exp_var_internal() -
4602 * Raise e to the power of x, where 0 <= x <= 1
4604 * NB: the result should be good to at least rscale digits, but it has
4605 * *not* been rounded off; the caller must do that if wanted.
4608 exp_var_internal(NumericVar *arg, NumericVar *result, int rscale)
4624 set_var_from_var(arg, &x);
4626 Assert(x.sign == NUMERIC_POS);
4628 local_rscale = rscale + 8;
4630 /* Reduce input into range 0 <= x <= 0.01 */
4631 while (cmp_var(&x, &const_zero_point_01) > 0)
4635 mul_var(&x, &const_zero_point_five, &x, x.dscale + 1);
4639 * Use the Taylor series
4641 * exp(x) = 1 + x + x^2/2! + x^3/3! + ...
4643 * Given the limited range of x, this should converge reasonably quickly.
4644 * We run the series until the terms fall below the local_rscale limit.
4646 add_var(&const_one, &x, result);
4647 set_var_from_var(&x, &xpow);
4648 set_var_from_var(&const_one, &ifac);
4649 set_var_from_var(&const_one, &ni);
4653 add_var(&ni, &const_one, &ni);
4654 mul_var(&xpow, &x, &xpow, local_rscale);
4655 mul_var(&ifac, &ni, &ifac, 0);
4656 div_var(&xpow, &ifac, &elem, local_rscale, true);
4658 if (elem.ndigits == 0)
4661 add_var(result, &elem, result);
4664 /* Compensate for argument range reduction */
4666 mul_var(result, result, result, local_rscale);
4679 * Compute the natural log of x
4682 ln_var(NumericVar *arg, NumericVar *result, int rscale)
4692 cmp = cmp_var(arg, &const_zero);
4695 (errcode(ERRCODE_INVALID_ARGUMENT_FOR_LOG),
4696 errmsg("cannot take logarithm of zero")));
4699 (errcode(ERRCODE_INVALID_ARGUMENT_FOR_LOG),
4700 errmsg("cannot take logarithm of a negative number")));
4702 local_rscale = rscale + 8;
4710 set_var_from_var(arg, &x);
4711 set_var_from_var(&const_two, &fact);
4713 /* Reduce input into range 0.9 < x < 1.1 */
4714 while (cmp_var(&x, &const_zero_point_nine) <= 0)
4717 sqrt_var(&x, &x, local_rscale);
4718 mul_var(&fact, &const_two, &fact, 0);
4720 while (cmp_var(&x, &const_one_point_one) >= 0)
4723 sqrt_var(&x, &x, local_rscale);
4724 mul_var(&fact, &const_two, &fact, 0);
4728 * We use the Taylor series for 0.5 * ln((1+z)/(1-z)),
4730 * z + z^3/3 + z^5/5 + ...
4732 * where z = (x-1)/(x+1) is in the range (approximately) -0.053 .. 0.048
4733 * due to the above range-reduction of x.
4735 * The convergence of this is not as fast as one would like, but is
4736 * tolerable given that z is small.
4738 sub_var(&x, &const_one, result);
4739 add_var(&x, &const_one, &elem);
4740 div_var(result, &elem, result, local_rscale, true);
4741 set_var_from_var(result, &xx);
4742 mul_var(result, result, &x, local_rscale);
4744 set_var_from_var(&const_one, &ni);
4748 add_var(&ni, &const_two, &ni);
4749 mul_var(&xx, &x, &xx, local_rscale);
4750 div_var(&xx, &ni, &elem, local_rscale, true);
4752 if (elem.ndigits == 0)
4755 add_var(result, &elem, result);
4757 if (elem.weight < (result->weight - local_rscale * 2 / DEC_DIGITS))
4761 /* Compensate for argument range reduction, round to requested rscale */
4762 mul_var(result, &fact, result, rscale);
4775 * Compute the logarithm of num in a given base.
4777 * Note: this routine chooses dscale of the result.
4780 log_var(NumericVar *base, NumericVar *num, NumericVar *result)
4791 /* Set scale for ln() calculations --- compare numeric_ln() */
4793 /* Approx decimal digits before decimal point */
4794 dec_digits = (num->weight + 1) * DEC_DIGITS;
4797 rscale = NUMERIC_MIN_SIG_DIGITS - (int) log10(dec_digits - 1);
4798 else if (dec_digits < 1)
4799 rscale = NUMERIC_MIN_SIG_DIGITS - (int) log10(1 - dec_digits);
4801 rscale = NUMERIC_MIN_SIG_DIGITS;
4803 rscale = Max(rscale, base->dscale);
4804 rscale = Max(rscale, num->dscale);
4805 rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
4806 rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
4808 local_rscale = rscale + 8;
4810 /* Form natural logarithms */
4811 ln_var(base, &ln_base, local_rscale);
4812 ln_var(num, &ln_num, local_rscale);
4814 ln_base.dscale = rscale;
4815 ln_num.dscale = rscale;
4817 /* Select scale for division result */
4818 rscale = select_div_scale(&ln_num, &ln_base);
4820 div_var(&ln_num, &ln_base, result, rscale, true);
4830 * Raise base to the power of exp
4832 * Note: this routine chooses dscale of the result.
4835 power_var(NumericVar *base, NumericVar *exp, NumericVar *result)
4844 /* If exp can be represented as an integer, use power_var_int */
4845 if (exp->ndigits == 0 || exp->ndigits <= exp->weight + 1)
4847 /* exact integer, but does it fit in int? */
4851 /* must copy because numericvar_to_int8() scribbles on input */
4853 set_var_from_var(exp, &x);
4854 if (numericvar_to_int8(&x, &expval64))
4856 int expval = (int) expval64;
4858 /* Test for overflow by reverse-conversion. */
4859 if ((int64) expval == expval64)
4861 /* Okay, select rscale */
4862 rscale = NUMERIC_MIN_SIG_DIGITS;
4863 rscale = Max(rscale, base->dscale);
4864 rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
4865 rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
4867 power_var_int(base, expval, result, rscale);
4879 /* Set scale for ln() calculation --- need extra accuracy here */
4881 /* Approx decimal digits before decimal point */
4882 dec_digits = (base->weight + 1) * DEC_DIGITS;
4885 rscale = NUMERIC_MIN_SIG_DIGITS * 2 - (int) log10(dec_digits - 1);
4886 else if (dec_digits < 1)
4887 rscale = NUMERIC_MIN_SIG_DIGITS * 2 - (int) log10(1 - dec_digits);
4889 rscale = NUMERIC_MIN_SIG_DIGITS * 2;
4891 rscale = Max(rscale, base->dscale * 2);
4892 rscale = Max(rscale, exp->dscale * 2);
4893 rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE * 2);
4894 rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE * 2);
4896 local_rscale = rscale + 8;
4898 ln_var(base, &ln_base, local_rscale);
4900 mul_var(&ln_base, exp, &ln_num, local_rscale);
4902 /* Set scale for exp() -- compare numeric_exp() */
4904 /* convert input to float8, ignoring overflow */
4905 val = numericvar_to_double_no_overflow(&ln_num);
4908 * log10(result) = num * log10(e), so this is approximately the weight:
4910 val *= 0.434294481903252;
4912 /* limit to something that won't cause integer overflow */
4913 val = Max(val, -NUMERIC_MAX_RESULT_SCALE);
4914 val = Min(val, NUMERIC_MAX_RESULT_SCALE);
4916 rscale = NUMERIC_MIN_SIG_DIGITS - (int) val;
4917 rscale = Max(rscale, base->dscale);
4918 rscale = Max(rscale, exp->dscale);
4919 rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
4920 rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
4922 exp_var(&ln_num, result, rscale);
4931 * Raise base to the power of exp, where exp is an integer.
4934 power_var_int(NumericVar *base, int exp, NumericVar *result, int rscale)
4937 NumericVar base_prod;
4940 /* Detect some special cases, particularly 0^0. */
4945 if (base->ndigits == 0)
4947 (errcode(ERRCODE_FLOATING_POINT_EXCEPTION),
4948 errmsg("zero raised to zero is undefined")));
4949 set_var_from_var(&const_one, result);
4950 result->dscale = rscale; /* no need to round */
4953 set_var_from_var(base, result);
4954 round_var(result, rscale);
4957 div_var(&const_one, base, result, rscale, true);
4960 mul_var(base, base, result, rscale);
4967 * The general case repeatedly multiplies base according to the bit
4968 * pattern of exp. We do the multiplications with some extra precision.
4973 local_rscale = rscale + MUL_GUARD_DIGITS * 2;
4975 init_var(&base_prod);
4976 set_var_from_var(base, &base_prod);
4979 set_var_from_var(base, result);
4981 set_var_from_var(&const_one, result);
4983 while ((exp >>= 1) > 0)
4985 mul_var(&base_prod, &base_prod, &base_prod, local_rscale);
4987 mul_var(&base_prod, result, result, local_rscale);
4990 free_var(&base_prod);
4992 /* Compensate for input sign, and round to requested rscale */
4994 div_var(&const_one, result, result, rscale, true);
4996 round_var(result, rscale);
5000 /* ----------------------------------------------------------------------
5002 * Following are the lowest level functions that operate unsigned
5003 * on the variable level
5005 * ----------------------------------------------------------------------
5012 * Compare the absolute values of var1 and var2
5013 * Returns: -1 for ABS(var1) < ABS(var2)
5014 * 0 for ABS(var1) == ABS(var2)
5015 * 1 for ABS(var1) > ABS(var2)
5019 cmp_abs(NumericVar *var1, NumericVar *var2)
5021 return cmp_abs_common(var1->digits, var1->ndigits, var1->weight,
5022 var2->digits, var2->ndigits, var2->weight);
5026 * cmp_abs_common() -
5028 * Main routine of cmp_abs(). This function can be used by both
5029 * NumericVar and Numeric.
5033 cmp_abs_common(const NumericDigit *var1digits, int var1ndigits, int var1weight,
5034 const NumericDigit *var2digits, int var2ndigits, int var2weight)
5039 /* Check any digits before the first common digit */
5041 while (var1weight > var2weight && i1 < var1ndigits)
5043 if (var1digits[i1++] != 0)
5047 while (var2weight > var1weight && i2 < var2ndigits)
5049 if (var2digits[i2++] != 0)
5054 /* At this point, either w1 == w2 or we've run out of digits */
5056 if (var1weight == var2weight)
5058 while (i1 < var1ndigits && i2 < var2ndigits)
5060 int stat = var1digits[i1++] - var2digits[i2++];
5072 * At this point, we've run out of digits on one side or the other; so any
5073 * remaining nonzero digits imply that side is larger
5075 while (i1 < var1ndigits)
5077 if (var1digits[i1++] != 0)
5080 while (i2 < var2ndigits)
5082 if (var2digits[i2++] != 0)
5093 * Add the absolute values of two variables into result.
5094 * result might point to one of the operands without danger.
5097 add_abs(NumericVar *var1, NumericVar *var2, NumericVar *result)
5099 NumericDigit *res_buf;
5100 NumericDigit *res_digits;
5112 /* copy these values into local vars for speed in inner loop */
5113 int var1ndigits = var1->ndigits;
5114 int var2ndigits = var2->ndigits;
5115 NumericDigit *var1digits = var1->digits;
5116 NumericDigit *var2digits = var2->digits;
5118 res_weight = Max(var1->weight, var2->weight) + 1;
5120 res_dscale = Max(var1->dscale, var2->dscale);
5122 /* Note: here we are figuring rscale in base-NBASE digits */
5123 rscale1 = var1->ndigits - var1->weight - 1;
5124 rscale2 = var2->ndigits - var2->weight - 1;
5125 res_rscale = Max(rscale1, rscale2);
5127 res_ndigits = res_rscale + res_weight + 1;
5128 if (res_ndigits <= 0)
5131 res_buf = digitbuf_alloc(res_ndigits + 1);
5132 res_buf[0] = 0; /* spare digit for later rounding */
5133 res_digits = res_buf + 1;
5135 i1 = res_rscale + var1->weight + 1;
5136 i2 = res_rscale + var2->weight + 1;
5137 for (i = res_ndigits - 1; i >= 0; i--)
5141 if (i1 >= 0 && i1 < var1ndigits)
5142 carry += var1digits[i1];
5143 if (i2 >= 0 && i2 < var2ndigits)
5144 carry += var2digits[i2];
5148 res_digits[i] = carry - NBASE;
5153 res_digits[i] = carry;
5158 Assert(carry == 0); /* else we failed to allow for carry out */
5160 digitbuf_free(result->buf);
5161 result->ndigits = res_ndigits;
5162 result->buf = res_buf;
5163 result->digits = res_digits;
5164 result->weight = res_weight;
5165 result->dscale = res_dscale;
5167 /* Remove leading/trailing zeroes */
5175 * Subtract the absolute value of var2 from the absolute value of var1
5176 * and store in result. result might point to one of the operands
5179 * ABS(var1) MUST BE GREATER OR EQUAL ABS(var2) !!!
5182 sub_abs(NumericVar *var1, NumericVar *var2, NumericVar *result)
5184 NumericDigit *res_buf;
5185 NumericDigit *res_digits;
5197 /* copy these values into local vars for speed in inner loop */
5198 int var1ndigits = var1->ndigits;
5199 int var2ndigits = var2->ndigits;
5200 NumericDigit *var1digits = var1->digits;
5201 NumericDigit *var2digits = var2->digits;
5203 res_weight = var1->weight;
5205 res_dscale = Max(var1->dscale, var2->dscale);
5207 /* Note: here we are figuring rscale in base-NBASE digits */
5208 rscale1 = var1->ndigits - var1->weight - 1;
5209 rscale2 = var2->ndigits - var2->weight - 1;
5210 res_rscale = Max(rscale1, rscale2);
5212 res_ndigits = res_rscale + res_weight + 1;
5213 if (res_ndigits <= 0)
5216 res_buf = digitbuf_alloc(res_ndigits + 1);
5217 res_buf[0] = 0; /* spare digit for later rounding */
5218 res_digits = res_buf + 1;
5220 i1 = res_rscale + var1->weight + 1;
5221 i2 = res_rscale + var2->weight + 1;
5222 for (i = res_ndigits - 1; i >= 0; i--)
5226 if (i1 >= 0 && i1 < var1ndigits)
5227 borrow += var1digits[i1];
5228 if (i2 >= 0 && i2 < var2ndigits)
5229 borrow -= var2digits[i2];
5233 res_digits[i] = borrow + NBASE;
5238 res_digits[i] = borrow;
5243 Assert(borrow == 0); /* else caller gave us var1 < var2 */
5245 digitbuf_free(result->buf);
5246 result->ndigits = res_ndigits;
5247 result->buf = res_buf;
5248 result->digits = res_digits;
5249 result->weight = res_weight;
5250 result->dscale = res_dscale;
5252 /* Remove leading/trailing zeroes */
5259 * Round the value of a variable to no more than rscale decimal digits
5260 * after the decimal point. NOTE: we allow rscale < 0 here, implying
5261 * rounding before the decimal point.
5264 round_var(NumericVar *var, int rscale)
5266 NumericDigit *digits = var->digits;
5271 var->dscale = rscale;
5273 /* decimal digits wanted */
5274 di = (var->weight + 1) * DEC_DIGITS + rscale;
5277 * If di = 0, the value loses all digits, but could round up to 1 if its
5278 * first extra digit is >= 5. If di < 0 the result must be 0.
5284 var->sign = NUMERIC_POS;
5288 /* NBASE digits wanted */
5289 ndigits = (di + DEC_DIGITS - 1) / DEC_DIGITS;
5291 /* 0, or number of decimal digits to keep in last NBASE digit */
5294 if (ndigits < var->ndigits ||
5295 (ndigits == var->ndigits && di > 0))
5297 var->ndigits = ndigits;
5300 /* di must be zero */
5301 carry = (digits[ndigits] >= HALF_NBASE) ? 1 : 0;
5304 carry = (digits[ndigits] >= HALF_NBASE) ? 1 : 0;
5307 /* Must round within last NBASE digit */
5312 pow10 = round_powers[di];
5313 #elif DEC_DIGITS == 2
5316 #error unsupported NBASE
5318 extra = digits[--ndigits] % pow10;
5319 digits[ndigits] -= extra;
5321 if (extra >= pow10 / 2)
5323 pow10 += digits[ndigits];
5329 digits[ndigits] = pow10;
5334 /* Propagate carry if needed */
5337 carry += digits[--ndigits];
5340 digits[ndigits] = carry - NBASE;
5345 digits[ndigits] = carry;
5352 Assert(ndigits == -1); /* better not have added > 1 digit */
5353 Assert(var->digits > var->buf);
5365 * Truncate the value of a variable at rscale decimal digits after the
5366 * decimal point. NOTE: we allow rscale < 0 here, implying
5367 * truncation before the decimal point.
5370 trunc_var(NumericVar *var, int rscale)
5375 var->dscale = rscale;
5377 /* decimal digits wanted */
5378 di = (var->weight + 1) * DEC_DIGITS + rscale;
5381 * If di <= 0, the value loses all digits.
5387 var->sign = NUMERIC_POS;
5391 /* NBASE digits wanted */
5392 ndigits = (di + DEC_DIGITS - 1) / DEC_DIGITS;
5394 if (ndigits <= var->ndigits)
5396 var->ndigits = ndigits;
5399 /* no within-digit stuff to worry about */
5401 /* 0, or number of decimal digits to keep in last NBASE digit */
5406 /* Must truncate within last NBASE digit */
5407 NumericDigit *digits = var->digits;
5412 pow10 = round_powers[di];
5413 #elif DEC_DIGITS == 2
5416 #error unsupported NBASE
5418 extra = digits[--ndigits] % pow10;
5419 digits[ndigits] -= extra;
5429 * Strip any leading and trailing zeroes from a numeric variable
5432 strip_var(NumericVar *var)
5434 NumericDigit *digits = var->digits;
5435 int ndigits = var->ndigits;
5437 /* Strip leading zeroes */
5438 while (ndigits > 0 && *digits == 0)
5445 /* Strip trailing zeroes */
5446 while (ndigits > 0 && digits[ndigits - 1] == 0)
5449 /* If it's zero, normalize the sign and weight */
5452 var->sign = NUMERIC_POS;
5456 var->digits = digits;
5457 var->ndigits = ndigits;