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.101 2007/02/27 23:48:08 tgl Exp $
19 *-------------------------------------------------------------------------
29 #include "catalog/pg_type.h"
30 #include "libpq/pqformat.h"
31 #include "utils/array.h"
32 #include "utils/builtins.h"
33 #include "utils/int8.h"
34 #include "utils/numeric.h"
37 * Uncomment the following to enable compilation of dump_numeric()
38 * and dump_var() and to get a dump of any result produced by make_result().
47 * Numeric values are represented in a base-NBASE floating point format.
48 * Each "digit" ranges from 0 to NBASE-1. The type NumericDigit is signed
49 * and wide enough to store a digit. We assume that NBASE*NBASE can fit in
50 * an int. Although the purely calculational routines could handle any even
51 * NBASE that's less than sqrt(INT_MAX), in practice we are only interested
52 * in NBASE a power of ten, so that I/O conversions and decimal rounding
53 * are easy. Also, it's actually more efficient if NBASE is rather less than
54 * sqrt(INT_MAX), so that there is "headroom" for mul_var and div_var to
55 * postpone processing carries.
62 #define DEC_DIGITS 1 /* decimal digits per NBASE digit */
63 #define MUL_GUARD_DIGITS 4 /* these are measured in NBASE digits */
64 #define DIV_GUARD_DIGITS 8
66 typedef signed char NumericDigit;
72 #define DEC_DIGITS 2 /* decimal digits per NBASE digit */
73 #define MUL_GUARD_DIGITS 3 /* these are measured in NBASE digits */
74 #define DIV_GUARD_DIGITS 6
76 typedef signed char NumericDigit;
81 #define HALF_NBASE 5000
82 #define DEC_DIGITS 4 /* decimal digits per NBASE digit */
83 #define MUL_GUARD_DIGITS 2 /* these are measured in NBASE digits */
84 #define DIV_GUARD_DIGITS 4
86 typedef int16 NumericDigit;
91 * The value represented by a NumericVar is determined by the sign, weight,
92 * ndigits, and digits[] array.
93 * Note: the first digit of a NumericVar's value is assumed to be multiplied
94 * by NBASE ** weight. Another way to say it is that there are weight+1
95 * digits before the decimal point. It is possible to have weight < 0.
97 * buf points at the physical start of the palloc'd digit buffer for the
98 * NumericVar. digits points at the first digit in actual use (the one
99 * with the specified weight). We normally leave an unused digit or two
100 * (preset to zeroes) between buf and digits, so that there is room to store
101 * a carry out of the top digit without special pushups. We just need to
102 * decrement digits (and increment weight) to make room for the carry digit.
103 * (There is no such extra space in a numeric value stored in the database,
104 * only in a NumericVar in memory.)
106 * If buf is NULL then the digit buffer isn't actually palloc'd and should
107 * not be freed --- see the constants below for an example.
109 * dscale, or display scale, is the nominal precision expressed as number
110 * of digits after the decimal point (it must always be >= 0 at present).
111 * dscale may be more than the number of physically stored fractional digits,
112 * implying that we have suppressed storage of significant trailing zeroes.
113 * It should never be less than the number of stored digits, since that would
114 * imply hiding digits that are present. NOTE that dscale is always expressed
115 * in *decimal* digits, and so it may correspond to a fractional number of
116 * base-NBASE digits --- divide by DEC_DIGITS to convert to NBASE digits.
118 * rscale, or result scale, is the target precision for a computation.
119 * Like dscale it is expressed as number of *decimal* digits after the decimal
120 * point, and is always >= 0 at present.
121 * Note that rscale is not stored in variables --- it's figured on-the-fly
122 * from the dscales of the inputs.
124 * NB: All the variable-level functions are written in a style that makes it
125 * possible to give one and the same variable as argument and destination.
126 * This is feasible because the digit buffer is separate from the variable.
129 typedef struct NumericVar
131 int ndigits; /* # of digits in digits[] - can be 0! */
132 int weight; /* weight of first digit */
133 int sign; /* NUMERIC_POS, NUMERIC_NEG, or NUMERIC_NAN */
134 int dscale; /* display scale */
135 NumericDigit *buf; /* start of palloc'd space for digits[] */
136 NumericDigit *digits; /* base-NBASE digits */
141 * Some preinitialized constants
144 static NumericDigit const_zero_data[1] = {0};
145 static NumericVar const_zero =
146 {0, 0, NUMERIC_POS, 0, NULL, const_zero_data};
148 static NumericDigit const_one_data[1] = {1};
149 static NumericVar const_one =
150 {1, 0, NUMERIC_POS, 0, NULL, const_one_data};
152 static NumericDigit const_two_data[1] = {2};
153 static NumericVar const_two =
154 {1, 0, NUMERIC_POS, 0, NULL, const_two_data};
157 static NumericDigit const_zero_point_five_data[1] = {5000};
158 #elif DEC_DIGITS == 2
159 static NumericDigit const_zero_point_five_data[1] = {50};
160 #elif DEC_DIGITS == 1
161 static NumericDigit const_zero_point_five_data[1] = {5};
163 static NumericVar const_zero_point_five =
164 {1, -1, NUMERIC_POS, 1, NULL, const_zero_point_five_data};
167 static NumericDigit const_zero_point_nine_data[1] = {9000};
168 #elif DEC_DIGITS == 2
169 static NumericDigit const_zero_point_nine_data[1] = {90};
170 #elif DEC_DIGITS == 1
171 static NumericDigit const_zero_point_nine_data[1] = {9};
173 static NumericVar const_zero_point_nine =
174 {1, -1, NUMERIC_POS, 1, NULL, const_zero_point_nine_data};
177 static NumericDigit const_zero_point_01_data[1] = {100};
178 static NumericVar const_zero_point_01 =
179 {1, -1, NUMERIC_POS, 2, NULL, const_zero_point_01_data};
180 #elif DEC_DIGITS == 2
181 static NumericDigit const_zero_point_01_data[1] = {1};
182 static NumericVar const_zero_point_01 =
183 {1, -1, NUMERIC_POS, 2, NULL, const_zero_point_01_data};
184 #elif DEC_DIGITS == 1
185 static NumericDigit const_zero_point_01_data[1] = {1};
186 static NumericVar const_zero_point_01 =
187 {1, -2, NUMERIC_POS, 2, NULL, const_zero_point_01_data};
191 static NumericDigit const_one_point_one_data[2] = {1, 1000};
192 #elif DEC_DIGITS == 2
193 static NumericDigit const_one_point_one_data[2] = {1, 10};
194 #elif DEC_DIGITS == 1
195 static NumericDigit const_one_point_one_data[2] = {1, 1};
197 static NumericVar const_one_point_one =
198 {2, 0, NUMERIC_POS, 1, NULL, const_one_point_one_data};
200 static NumericVar const_nan =
201 {0, 0, NUMERIC_NAN, 0, NULL, NULL};
204 static const int round_powers[4] = {0, 1000, 100, 10};
214 static void dump_numeric(const char *str, Numeric num);
215 static void dump_var(const char *str, NumericVar *var);
217 #define dump_numeric(s,n)
218 #define dump_var(s,v)
221 #define digitbuf_alloc(ndigits) \
222 ((NumericDigit *) palloc((ndigits) * sizeof(NumericDigit)))
223 #define digitbuf_free(buf) \
229 #define init_var(v) MemSetAligned(v, 0, sizeof(NumericVar))
231 #define NUMERIC_DIGITS(num) ((NumericDigit *)(num)->n_data)
232 #define NUMERIC_NDIGITS(num) \
233 ((VARSIZE(num) - NUMERIC_HDRSZ) / sizeof(NumericDigit))
235 static void alloc_var(NumericVar *var, int ndigits);
236 static void free_var(NumericVar *var);
237 static void zero_var(NumericVar *var);
239 static void set_var_from_str(const char *str, NumericVar *dest);
240 static void set_var_from_num(Numeric value, NumericVar *dest);
241 static void set_var_from_var(NumericVar *value, NumericVar *dest);
242 static char *get_str_from_var(NumericVar *var, int dscale);
244 static Numeric make_result(NumericVar *var);
246 static void apply_typmod(NumericVar *var, int32 typmod);
248 static int32 numericvar_to_int4(NumericVar *var);
249 static bool numericvar_to_int8(NumericVar *var, int64 *result);
250 static void int8_to_numericvar(int64 val, NumericVar *var);
251 static double numeric_to_double_no_overflow(Numeric num);
252 static double numericvar_to_double_no_overflow(NumericVar *var);
254 static int cmp_numerics(Numeric num1, Numeric num2);
255 static int cmp_var(NumericVar *var1, NumericVar *var2);
256 static int cmp_var_common(const NumericDigit *var1digits, int var1ndigits,
257 int var1weight, int var1sign,
258 const NumericDigit *var2digits, int var2ndigits,
259 int var2weight, int var2sign);
260 static void add_var(NumericVar *var1, NumericVar *var2, NumericVar *result);
261 static void sub_var(NumericVar *var1, NumericVar *var2, NumericVar *result);
262 static void mul_var(NumericVar *var1, NumericVar *var2, NumericVar *result,
264 static void div_var(NumericVar *var1, NumericVar *var2, NumericVar *result,
265 int rscale, bool round);
266 static int select_div_scale(NumericVar *var1, NumericVar *var2);
267 static void mod_var(NumericVar *var1, NumericVar *var2, NumericVar *result);
268 static void ceil_var(NumericVar *var, NumericVar *result);
269 static void floor_var(NumericVar *var, NumericVar *result);
271 static void sqrt_var(NumericVar *arg, NumericVar *result, int rscale);
272 static void exp_var(NumericVar *arg, NumericVar *result, int rscale);
273 static void exp_var_internal(NumericVar *arg, NumericVar *result, int rscale);
274 static void ln_var(NumericVar *arg, NumericVar *result, int rscale);
275 static void log_var(NumericVar *base, NumericVar *num, NumericVar *result);
276 static void power_var(NumericVar *base, NumericVar *exp, NumericVar *result);
277 static void power_var_int(NumericVar *base, int exp, NumericVar *result,
280 static int cmp_abs(NumericVar *var1, NumericVar *var2);
281 static int cmp_abs_common(const NumericDigit *var1digits, int var1ndigits,
283 const NumericDigit *var2digits, int var2ndigits,
285 static void add_abs(NumericVar *var1, NumericVar *var2, NumericVar *result);
286 static void sub_abs(NumericVar *var1, NumericVar *var2, NumericVar *result);
287 static void round_var(NumericVar *var, int rscale);
288 static void trunc_var(NumericVar *var, int rscale);
289 static void strip_var(NumericVar *var);
290 static void compute_bucket(Numeric operand, Numeric bound1, Numeric bound2,
291 NumericVar *count_var, NumericVar *result_var);
294 /* ----------------------------------------------------------------------
296 * Input-, output- and rounding-functions
298 * ----------------------------------------------------------------------
305 * Input function for numeric data type
308 numeric_in(PG_FUNCTION_ARGS)
310 char *str = PG_GETARG_CSTRING(0);
313 Oid typelem = PG_GETARG_OID(1);
315 int32 typmod = PG_GETARG_INT32(2);
322 if (pg_strcasecmp(str, "NaN") == 0)
323 PG_RETURN_NUMERIC(make_result(&const_nan));
326 * Use set_var_from_str() to parse the input string and return it in the
327 * packed DB storage format
330 set_var_from_str(str, &value);
332 apply_typmod(&value, typmod);
334 res = make_result(&value);
337 PG_RETURN_NUMERIC(res);
344 * Output function for numeric data type
347 numeric_out(PG_FUNCTION_ARGS)
349 Numeric num = PG_GETARG_NUMERIC(0);
356 if (NUMERIC_IS_NAN(num))
357 PG_RETURN_CSTRING(pstrdup("NaN"));
360 * Get the number in the variable format.
362 * Even if we didn't need to change format, we'd still need to copy the
363 * value to have a modifiable copy for rounding. set_var_from_num() also
364 * guarantees there is extra digit space in case we produce a carry out
368 set_var_from_num(num, &x);
370 str = get_str_from_var(&x, x.dscale);
374 PG_RETURN_CSTRING(str);
378 * numeric_recv - converts external binary format to numeric
380 * External format is a sequence of int16's:
381 * ndigits, weight, sign, dscale, NumericDigits.
384 numeric_recv(PG_FUNCTION_ARGS)
386 StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
389 Oid typelem = PG_GETARG_OID(1);
391 int32 typmod = PG_GETARG_INT32(2);
399 len = (uint16) pq_getmsgint(buf, sizeof(uint16));
400 if (len < 0 || len > NUMERIC_MAX_PRECISION + NUMERIC_MAX_RESULT_SCALE)
402 (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
403 errmsg("invalid length in external \"numeric\" value")));
405 alloc_var(&value, len);
407 value.weight = (int16) pq_getmsgint(buf, sizeof(int16));
408 value.sign = (uint16) pq_getmsgint(buf, sizeof(uint16));
409 if (!(value.sign == NUMERIC_POS ||
410 value.sign == NUMERIC_NEG ||
411 value.sign == NUMERIC_NAN))
413 (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
414 errmsg("invalid sign in external \"numeric\" value")));
416 value.dscale = (uint16) pq_getmsgint(buf, sizeof(uint16));
417 for (i = 0; i < len; i++)
419 NumericDigit d = pq_getmsgint(buf, sizeof(NumericDigit));
421 if (d < 0 || d >= NBASE)
423 (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
424 errmsg("invalid digit in external \"numeric\" value")));
428 apply_typmod(&value, typmod);
430 res = make_result(&value);
433 PG_RETURN_NUMERIC(res);
437 * numeric_send - converts numeric to binary format
440 numeric_send(PG_FUNCTION_ARGS)
442 Numeric num = PG_GETARG_NUMERIC(0);
448 set_var_from_num(num, &x);
450 pq_begintypsend(&buf);
452 pq_sendint(&buf, x.ndigits, sizeof(int16));
453 pq_sendint(&buf, x.weight, sizeof(int16));
454 pq_sendint(&buf, x.sign, sizeof(int16));
455 pq_sendint(&buf, x.dscale, sizeof(int16));
456 for (i = 0; i < x.ndigits; i++)
457 pq_sendint(&buf, x.digits[i], sizeof(NumericDigit));
461 PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
468 * This is a special function called by the Postgres database system
469 * before a value is stored in a tuple's attribute. The precision and
470 * scale of the attribute have to be applied on the value.
473 numeric(PG_FUNCTION_ARGS)
475 Numeric num = PG_GETARG_NUMERIC(0);
476 int32 typmod = PG_GETARG_INT32(1);
488 if (NUMERIC_IS_NAN(num))
489 PG_RETURN_NUMERIC(make_result(&const_nan));
492 * If the value isn't a valid type modifier, simply return a copy of the
495 if (typmod < (int32) (VARHDRSZ))
497 new = (Numeric) palloc(VARSIZE(num));
498 memcpy(new, num, VARSIZE(num));
499 PG_RETURN_NUMERIC(new);
503 * Get the precision and scale out of the typmod value
505 tmp_typmod = typmod - VARHDRSZ;
506 precision = (tmp_typmod >> 16) & 0xffff;
507 scale = tmp_typmod & 0xffff;
508 maxdigits = precision - scale;
511 * If the number is certainly in bounds and due to the target scale no
512 * rounding could be necessary, just make a copy of the input and modify
513 * its scale fields. (Note we assume the existing dscale is honest...)
515 ddigits = (num->n_weight + 1) * DEC_DIGITS;
516 if (ddigits <= maxdigits && scale >= NUMERIC_DSCALE(num))
518 new = (Numeric) palloc(VARSIZE(num));
519 memcpy(new, num, VARSIZE(num));
520 new->n_sign_dscale = NUMERIC_SIGN(new) |
521 ((uint16) scale & NUMERIC_DSCALE_MASK);
522 PG_RETURN_NUMERIC(new);
526 * We really need to fiddle with things - unpack the number into a
527 * variable and let apply_typmod() do it.
531 set_var_from_num(num, &var);
532 apply_typmod(&var, typmod);
533 new = make_result(&var);
537 PG_RETURN_NUMERIC(new);
541 numerictypmodin(PG_FUNCTION_ARGS)
543 ArrayType *ta = PG_GETARG_ARRAYTYPE_P(0);
548 tl = ArrayGetTypmods(ta, &n);
552 if (tl[0] < 1 || tl[0] > NUMERIC_MAX_PRECISION)
554 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
555 errmsg("NUMERIC precision %d must be between 1 and %d",
556 tl[0], NUMERIC_MAX_PRECISION)));
557 if (tl[1] < 0 || tl[1] > tl[0])
559 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
560 errmsg("NUMERIC scale %d must be between 0 and precision %d",
562 typmod = ((tl[0] << 16) | tl[1]) + VARHDRSZ;
566 if (tl[0] < 1 || tl[0] > NUMERIC_MAX_PRECISION)
568 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
569 errmsg("NUMERIC precision %d must be between 1 and %d",
570 tl[0], NUMERIC_MAX_PRECISION)));
571 /* scale defaults to zero */
572 typmod = (tl[0] << 16) + VARHDRSZ;
577 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
578 errmsg("invalid NUMERIC type modifier")));
579 typmod = 0; /* keep compiler quiet */
582 PG_RETURN_INT32(typmod);
586 numerictypmodout(PG_FUNCTION_ARGS)
588 int32 typmod = PG_GETARG_INT32(0);
589 char *res = (char *) palloc(64);
592 snprintf(res, 64, "(%d,%d)",
593 ((typmod - VARHDRSZ) >> 16) & 0xffff,
594 (typmod - VARHDRSZ) & 0xffff);
598 PG_RETURN_CSTRING(res);
602 /* ----------------------------------------------------------------------
604 * Sign manipulation, rounding and the like
606 * ----------------------------------------------------------------------
610 numeric_abs(PG_FUNCTION_ARGS)
612 Numeric num = PG_GETARG_NUMERIC(0);
618 if (NUMERIC_IS_NAN(num))
619 PG_RETURN_NUMERIC(make_result(&const_nan));
622 * Do it the easy way directly on the packed format
624 res = (Numeric) palloc(VARSIZE(num));
625 memcpy(res, num, VARSIZE(num));
627 res->n_sign_dscale = NUMERIC_POS | NUMERIC_DSCALE(num);
629 PG_RETURN_NUMERIC(res);
634 numeric_uminus(PG_FUNCTION_ARGS)
636 Numeric num = PG_GETARG_NUMERIC(0);
642 if (NUMERIC_IS_NAN(num))
643 PG_RETURN_NUMERIC(make_result(&const_nan));
646 * Do it the easy way directly on the packed format
648 res = (Numeric) palloc(VARSIZE(num));
649 memcpy(res, num, VARSIZE(num));
652 * The packed format is known to be totally zero digit trimmed always. So
653 * we can identify a ZERO by the fact that there are no digits at all. Do
656 if (VARSIZE(num) != NUMERIC_HDRSZ)
658 /* Else, flip the sign */
659 if (NUMERIC_SIGN(num) == NUMERIC_POS)
660 res->n_sign_dscale = NUMERIC_NEG | NUMERIC_DSCALE(num);
662 res->n_sign_dscale = NUMERIC_POS | NUMERIC_DSCALE(num);
665 PG_RETURN_NUMERIC(res);
670 numeric_uplus(PG_FUNCTION_ARGS)
672 Numeric num = PG_GETARG_NUMERIC(0);
675 res = (Numeric) palloc(VARSIZE(num));
676 memcpy(res, num, VARSIZE(num));
678 PG_RETURN_NUMERIC(res);
684 * returns -1 if the argument is less than 0, 0 if the argument is equal
685 * to 0, and 1 if the argument is greater than zero.
688 numeric_sign(PG_FUNCTION_ARGS)
690 Numeric num = PG_GETARG_NUMERIC(0);
697 if (NUMERIC_IS_NAN(num))
698 PG_RETURN_NUMERIC(make_result(&const_nan));
703 * The packed format is known to be totally zero digit trimmed always. So
704 * we can identify a ZERO by the fact that there are no digits at all.
706 if (VARSIZE(num) == NUMERIC_HDRSZ)
707 set_var_from_var(&const_zero, &result);
711 * And if there are some, we return a copy of ONE with the sign of our
714 set_var_from_var(&const_one, &result);
715 result.sign = NUMERIC_SIGN(num);
718 res = make_result(&result);
721 PG_RETURN_NUMERIC(res);
728 * Round a value to have 'scale' digits after the decimal point.
729 * We allow negative 'scale', implying rounding before the decimal
730 * point --- Oracle interprets rounding that way.
733 numeric_round(PG_FUNCTION_ARGS)
735 Numeric num = PG_GETARG_NUMERIC(0);
736 int32 scale = PG_GETARG_INT32(1);
743 if (NUMERIC_IS_NAN(num))
744 PG_RETURN_NUMERIC(make_result(&const_nan));
747 * Limit the scale value to avoid possible overflow in calculations
749 scale = Max(scale, -NUMERIC_MAX_RESULT_SCALE);
750 scale = Min(scale, NUMERIC_MAX_RESULT_SCALE);
753 * Unpack the argument and round it at the proper digit position
756 set_var_from_num(num, &arg);
758 round_var(&arg, scale);
760 /* We don't allow negative output dscale */
765 * Return the rounded result
767 res = make_result(&arg);
770 PG_RETURN_NUMERIC(res);
777 * Truncate a value to have 'scale' digits after the decimal point.
778 * We allow negative 'scale', implying a truncation before the decimal
779 * point --- Oracle interprets truncation that way.
782 numeric_trunc(PG_FUNCTION_ARGS)
784 Numeric num = PG_GETARG_NUMERIC(0);
785 int32 scale = PG_GETARG_INT32(1);
792 if (NUMERIC_IS_NAN(num))
793 PG_RETURN_NUMERIC(make_result(&const_nan));
796 * Limit the scale value to avoid possible overflow in calculations
798 scale = Max(scale, -NUMERIC_MAX_RESULT_SCALE);
799 scale = Min(scale, NUMERIC_MAX_RESULT_SCALE);
802 * Unpack the argument and truncate it at the proper digit position
805 set_var_from_num(num, &arg);
807 trunc_var(&arg, scale);
809 /* We don't allow negative output dscale */
814 * Return the truncated result
816 res = make_result(&arg);
819 PG_RETURN_NUMERIC(res);
826 * Return the smallest integer greater than or equal to the argument
829 numeric_ceil(PG_FUNCTION_ARGS)
831 Numeric num = PG_GETARG_NUMERIC(0);
835 if (NUMERIC_IS_NAN(num))
836 PG_RETURN_NUMERIC(make_result(&const_nan));
840 set_var_from_num(num, &result);
841 ceil_var(&result, &result);
843 res = make_result(&result);
846 PG_RETURN_NUMERIC(res);
853 * Return the largest integer equal to or less than the argument
856 numeric_floor(PG_FUNCTION_ARGS)
858 Numeric num = PG_GETARG_NUMERIC(0);
862 if (NUMERIC_IS_NAN(num))
863 PG_RETURN_NUMERIC(make_result(&const_nan));
867 set_var_from_num(num, &result);
868 floor_var(&result, &result);
870 res = make_result(&result);
873 PG_RETURN_NUMERIC(res);
877 * Implements the numeric version of the width_bucket() function
878 * defined by SQL2003. See also width_bucket_float8().
880 * 'bound1' and 'bound2' are the lower and upper bounds of the
881 * histogram's range, respectively. 'count' is the number of buckets
882 * in the histogram. width_bucket() returns an integer indicating the
883 * bucket number that 'operand' belongs to in an equiwidth histogram
884 * with the specified characteristics. An operand smaller than the
885 * lower bound is assigned to bucket 0. An operand greater than the
886 * upper bound is assigned to an additional bucket (with number
887 * count+1). We don't allow "NaN" for any of the numeric arguments.
890 width_bucket_numeric(PG_FUNCTION_ARGS)
892 Numeric operand = PG_GETARG_NUMERIC(0);
893 Numeric bound1 = PG_GETARG_NUMERIC(1);
894 Numeric bound2 = PG_GETARG_NUMERIC(2);
895 int32 count = PG_GETARG_INT32(3);
896 NumericVar count_var;
897 NumericVar result_var;
902 (errcode(ERRCODE_INVALID_ARGUMENT_FOR_WIDTH_BUCKET_FUNCTION),
903 errmsg("count must be greater than zero")));
905 if (NUMERIC_IS_NAN(operand) ||
906 NUMERIC_IS_NAN(bound1) ||
907 NUMERIC_IS_NAN(bound2))
909 (errcode(ERRCODE_INVALID_ARGUMENT_FOR_WIDTH_BUCKET_FUNCTION),
910 errmsg("operand, lower bound and upper bound cannot be NaN")));
912 init_var(&result_var);
913 init_var(&count_var);
915 /* Convert 'count' to a numeric, for ease of use later */
916 int8_to_numericvar((int64) count, &count_var);
918 switch (cmp_numerics(bound1, bound2))
922 (errcode(ERRCODE_INVALID_ARGUMENT_FOR_WIDTH_BUCKET_FUNCTION),
923 errmsg("lower bound cannot equal upper bound")));
925 /* bound1 < bound2 */
927 if (cmp_numerics(operand, bound1) < 0)
928 set_var_from_var(&const_zero, &result_var);
929 else if (cmp_numerics(operand, bound2) >= 0)
930 add_var(&count_var, &const_one, &result_var);
932 compute_bucket(operand, bound1, bound2,
933 &count_var, &result_var);
936 /* bound1 > bound2 */
938 if (cmp_numerics(operand, bound1) > 0)
939 set_var_from_var(&const_zero, &result_var);
940 else if (cmp_numerics(operand, bound2) <= 0)
941 add_var(&count_var, &const_one, &result_var);
943 compute_bucket(operand, bound1, bound2,
944 &count_var, &result_var);
948 /* if result exceeds the range of a legal int4, we ereport here */
949 result = numericvar_to_int4(&result_var);
951 free_var(&count_var);
952 free_var(&result_var);
954 PG_RETURN_INT32(result);
958 * If 'operand' is not outside the bucket range, determine the correct
959 * bucket for it to go. The calculations performed by this function
960 * are derived directly from the SQL2003 spec.
963 compute_bucket(Numeric operand, Numeric bound1, Numeric bound2,
964 NumericVar *count_var, NumericVar *result_var)
966 NumericVar bound1_var;
967 NumericVar bound2_var;
968 NumericVar operand_var;
970 init_var(&bound1_var);
971 init_var(&bound2_var);
972 init_var(&operand_var);
974 set_var_from_num(bound1, &bound1_var);
975 set_var_from_num(bound2, &bound2_var);
976 set_var_from_num(operand, &operand_var);
978 if (cmp_var(&bound1_var, &bound2_var) < 0)
980 sub_var(&operand_var, &bound1_var, &operand_var);
981 sub_var(&bound2_var, &bound1_var, &bound2_var);
982 div_var(&operand_var, &bound2_var, result_var,
983 select_div_scale(&operand_var, &bound2_var), true);
987 sub_var(&bound1_var, &operand_var, &operand_var);
988 sub_var(&bound1_var, &bound2_var, &bound1_var);
989 div_var(&operand_var, &bound1_var, result_var,
990 select_div_scale(&operand_var, &bound1_var), true);
993 mul_var(result_var, count_var, result_var,
994 result_var->dscale + count_var->dscale);
995 add_var(result_var, &const_one, result_var);
996 floor_var(result_var, result_var);
998 free_var(&bound1_var);
999 free_var(&bound2_var);
1000 free_var(&operand_var);
1003 /* ----------------------------------------------------------------------
1005 * Comparison functions
1007 * Note: btree indexes need these routines not to leak memory; therefore,
1008 * be careful to free working copies of toasted datums. Most places don't
1009 * need to be so careful.
1010 * ----------------------------------------------------------------------
1015 numeric_cmp(PG_FUNCTION_ARGS)
1017 Numeric num1 = PG_GETARG_NUMERIC(0);
1018 Numeric num2 = PG_GETARG_NUMERIC(1);
1021 result = cmp_numerics(num1, num2);
1023 PG_FREE_IF_COPY(num1, 0);
1024 PG_FREE_IF_COPY(num2, 1);
1026 PG_RETURN_INT32(result);
1031 numeric_eq(PG_FUNCTION_ARGS)
1033 Numeric num1 = PG_GETARG_NUMERIC(0);
1034 Numeric num2 = PG_GETARG_NUMERIC(1);
1037 result = cmp_numerics(num1, num2) == 0;
1039 PG_FREE_IF_COPY(num1, 0);
1040 PG_FREE_IF_COPY(num2, 1);
1042 PG_RETURN_BOOL(result);
1046 numeric_ne(PG_FUNCTION_ARGS)
1048 Numeric num1 = PG_GETARG_NUMERIC(0);
1049 Numeric num2 = PG_GETARG_NUMERIC(1);
1052 result = cmp_numerics(num1, num2) != 0;
1054 PG_FREE_IF_COPY(num1, 0);
1055 PG_FREE_IF_COPY(num2, 1);
1057 PG_RETURN_BOOL(result);
1061 numeric_gt(PG_FUNCTION_ARGS)
1063 Numeric num1 = PG_GETARG_NUMERIC(0);
1064 Numeric num2 = PG_GETARG_NUMERIC(1);
1067 result = cmp_numerics(num1, num2) > 0;
1069 PG_FREE_IF_COPY(num1, 0);
1070 PG_FREE_IF_COPY(num2, 1);
1072 PG_RETURN_BOOL(result);
1076 numeric_ge(PG_FUNCTION_ARGS)
1078 Numeric num1 = PG_GETARG_NUMERIC(0);
1079 Numeric num2 = PG_GETARG_NUMERIC(1);
1082 result = cmp_numerics(num1, num2) >= 0;
1084 PG_FREE_IF_COPY(num1, 0);
1085 PG_FREE_IF_COPY(num2, 1);
1087 PG_RETURN_BOOL(result);
1091 numeric_lt(PG_FUNCTION_ARGS)
1093 Numeric num1 = PG_GETARG_NUMERIC(0);
1094 Numeric num2 = PG_GETARG_NUMERIC(1);
1097 result = cmp_numerics(num1, num2) < 0;
1099 PG_FREE_IF_COPY(num1, 0);
1100 PG_FREE_IF_COPY(num2, 1);
1102 PG_RETURN_BOOL(result);
1106 numeric_le(PG_FUNCTION_ARGS)
1108 Numeric num1 = PG_GETARG_NUMERIC(0);
1109 Numeric num2 = PG_GETARG_NUMERIC(1);
1112 result = cmp_numerics(num1, num2) <= 0;
1114 PG_FREE_IF_COPY(num1, 0);
1115 PG_FREE_IF_COPY(num2, 1);
1117 PG_RETURN_BOOL(result);
1121 cmp_numerics(Numeric num1, Numeric num2)
1126 * We consider all NANs to be equal and larger than any non-NAN. This is
1127 * somewhat arbitrary; the important thing is to have a consistent sort
1130 if (NUMERIC_IS_NAN(num1))
1132 if (NUMERIC_IS_NAN(num2))
1133 result = 0; /* NAN = NAN */
1135 result = 1; /* NAN > non-NAN */
1137 else if (NUMERIC_IS_NAN(num2))
1139 result = -1; /* non-NAN < NAN */
1143 result = cmp_var_common(NUMERIC_DIGITS(num1), NUMERIC_NDIGITS(num1),
1144 num1->n_weight, NUMERIC_SIGN(num1),
1145 NUMERIC_DIGITS(num2), NUMERIC_NDIGITS(num2),
1146 num2->n_weight, NUMERIC_SIGN(num2));
1153 /* ----------------------------------------------------------------------
1155 * Basic arithmetic functions
1157 * ----------------------------------------------------------------------
1167 numeric_add(PG_FUNCTION_ARGS)
1169 Numeric num1 = PG_GETARG_NUMERIC(0);
1170 Numeric num2 = PG_GETARG_NUMERIC(1);
1179 if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
1180 PG_RETURN_NUMERIC(make_result(&const_nan));
1183 * Unpack the values, let add_var() compute the result and return it.
1189 set_var_from_num(num1, &arg1);
1190 set_var_from_num(num2, &arg2);
1192 add_var(&arg1, &arg2, &result);
1194 res = make_result(&result);
1200 PG_RETURN_NUMERIC(res);
1207 * Subtract one numeric from another
1210 numeric_sub(PG_FUNCTION_ARGS)
1212 Numeric num1 = PG_GETARG_NUMERIC(0);
1213 Numeric num2 = PG_GETARG_NUMERIC(1);
1222 if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
1223 PG_RETURN_NUMERIC(make_result(&const_nan));
1226 * Unpack the values, let sub_var() compute the result and return it.
1232 set_var_from_num(num1, &arg1);
1233 set_var_from_num(num2, &arg2);
1235 sub_var(&arg1, &arg2, &result);
1237 res = make_result(&result);
1243 PG_RETURN_NUMERIC(res);
1250 * Calculate the product of two numerics
1253 numeric_mul(PG_FUNCTION_ARGS)
1255 Numeric num1 = PG_GETARG_NUMERIC(0);
1256 Numeric num2 = PG_GETARG_NUMERIC(1);
1265 if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
1266 PG_RETURN_NUMERIC(make_result(&const_nan));
1269 * Unpack the values, let mul_var() compute the result and return it.
1270 * Unlike add_var() and sub_var(), mul_var() will round its result. In the
1271 * case of numeric_mul(), which is invoked for the * operator on numerics,
1272 * we request exact representation for the product (rscale = sum(dscale of
1273 * arg1, dscale of arg2)).
1279 set_var_from_num(num1, &arg1);
1280 set_var_from_num(num2, &arg2);
1282 mul_var(&arg1, &arg2, &result, arg1.dscale + arg2.dscale);
1284 res = make_result(&result);
1290 PG_RETURN_NUMERIC(res);
1297 * Divide one numeric into another
1300 numeric_div(PG_FUNCTION_ARGS)
1302 Numeric num1 = PG_GETARG_NUMERIC(0);
1303 Numeric num2 = PG_GETARG_NUMERIC(1);
1313 if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
1314 PG_RETURN_NUMERIC(make_result(&const_nan));
1317 * Unpack the arguments
1323 set_var_from_num(num1, &arg1);
1324 set_var_from_num(num2, &arg2);
1327 * Select scale for division result
1329 rscale = select_div_scale(&arg1, &arg2);
1332 * Do the divide and return the result
1334 div_var(&arg1, &arg2, &result, rscale, true);
1336 res = make_result(&result);
1342 PG_RETURN_NUMERIC(res);
1349 * Calculate the modulo of two numerics
1352 numeric_mod(PG_FUNCTION_ARGS)
1354 Numeric num1 = PG_GETARG_NUMERIC(0);
1355 Numeric num2 = PG_GETARG_NUMERIC(1);
1361 if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
1362 PG_RETURN_NUMERIC(make_result(&const_nan));
1368 set_var_from_num(num1, &arg1);
1369 set_var_from_num(num2, &arg2);
1371 mod_var(&arg1, &arg2, &result);
1373 res = make_result(&result);
1379 PG_RETURN_NUMERIC(res);
1386 * Increment a number by one
1389 numeric_inc(PG_FUNCTION_ARGS)
1391 Numeric num = PG_GETARG_NUMERIC(0);
1398 if (NUMERIC_IS_NAN(num))
1399 PG_RETURN_NUMERIC(make_result(&const_nan));
1402 * Compute the result and return it
1406 set_var_from_num(num, &arg);
1408 add_var(&arg, &const_one, &arg);
1410 res = make_result(&arg);
1414 PG_RETURN_NUMERIC(res);
1419 * numeric_smaller() -
1421 * Return the smaller of two numbers
1424 numeric_smaller(PG_FUNCTION_ARGS)
1426 Numeric num1 = PG_GETARG_NUMERIC(0);
1427 Numeric num2 = PG_GETARG_NUMERIC(1);
1430 * Use cmp_numerics so that this will agree with the comparison operators,
1431 * particularly as regards comparisons involving NaN.
1433 if (cmp_numerics(num1, num2) < 0)
1434 PG_RETURN_NUMERIC(num1);
1436 PG_RETURN_NUMERIC(num2);
1441 * numeric_larger() -
1443 * Return the larger of two numbers
1446 numeric_larger(PG_FUNCTION_ARGS)
1448 Numeric num1 = PG_GETARG_NUMERIC(0);
1449 Numeric num2 = PG_GETARG_NUMERIC(1);
1452 * Use cmp_numerics so that this will agree with the comparison operators,
1453 * particularly as regards comparisons involving NaN.
1455 if (cmp_numerics(num1, num2) > 0)
1456 PG_RETURN_NUMERIC(num1);
1458 PG_RETURN_NUMERIC(num2);
1462 /* ----------------------------------------------------------------------
1464 * Advanced math functions
1466 * ----------------------------------------------------------------------
1475 numeric_fac(PG_FUNCTION_ARGS)
1477 int64 num = PG_GETARG_INT64(0);
1484 res = make_result(&const_one);
1485 PG_RETURN_NUMERIC(res);
1491 int8_to_numericvar(num, &result);
1493 for (num = num - 1; num > 1; num--)
1495 int8_to_numericvar(num, &fact);
1497 mul_var(&result, &fact, &result, 0);
1500 res = make_result(&result);
1505 PG_RETURN_NUMERIC(res);
1512 * Compute the square root of a numeric.
1515 numeric_sqrt(PG_FUNCTION_ARGS)
1517 Numeric num = PG_GETARG_NUMERIC(0);
1527 if (NUMERIC_IS_NAN(num))
1528 PG_RETURN_NUMERIC(make_result(&const_nan));
1531 * Unpack the argument and determine the result scale. We choose a scale
1532 * to give at least NUMERIC_MIN_SIG_DIGITS significant digits; but in any
1533 * case not less than the input's dscale.
1538 set_var_from_num(num, &arg);
1540 /* Assume the input was normalized, so arg.weight is accurate */
1541 sweight = (arg.weight + 1) * DEC_DIGITS / 2 - 1;
1543 rscale = NUMERIC_MIN_SIG_DIGITS - sweight;
1544 rscale = Max(rscale, arg.dscale);
1545 rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
1546 rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
1549 * Let sqrt_var() do the calculation and return the result.
1551 sqrt_var(&arg, &result, rscale);
1553 res = make_result(&result);
1558 PG_RETURN_NUMERIC(res);
1565 * Raise e to the power of x
1568 numeric_exp(PG_FUNCTION_ARGS)
1570 Numeric num = PG_GETARG_NUMERIC(0);
1580 if (NUMERIC_IS_NAN(num))
1581 PG_RETURN_NUMERIC(make_result(&const_nan));
1584 * Unpack the argument and determine the result scale. We choose a scale
1585 * to give at least NUMERIC_MIN_SIG_DIGITS significant digits; but in any
1586 * case not less than the input's dscale.
1591 set_var_from_num(num, &arg);
1593 /* convert input to float8, ignoring overflow */
1594 val = numericvar_to_double_no_overflow(&arg);
1597 * log10(result) = num * log10(e), so this is approximately the decimal
1598 * weight of the result:
1600 val *= 0.434294481903252;
1602 /* limit to something that won't cause integer overflow */
1603 val = Max(val, -NUMERIC_MAX_RESULT_SCALE);
1604 val = Min(val, NUMERIC_MAX_RESULT_SCALE);
1606 rscale = NUMERIC_MIN_SIG_DIGITS - (int) val;
1607 rscale = Max(rscale, arg.dscale);
1608 rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
1609 rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
1612 * Let exp_var() do the calculation and return the result.
1614 exp_var(&arg, &result, rscale);
1616 res = make_result(&result);
1621 PG_RETURN_NUMERIC(res);
1628 * Compute the natural logarithm of x
1631 numeric_ln(PG_FUNCTION_ARGS)
1633 Numeric num = PG_GETARG_NUMERIC(0);
1643 if (NUMERIC_IS_NAN(num))
1644 PG_RETURN_NUMERIC(make_result(&const_nan));
1649 set_var_from_num(num, &arg);
1651 /* Approx decimal digits before decimal point */
1652 dec_digits = (arg.weight + 1) * DEC_DIGITS;
1655 rscale = NUMERIC_MIN_SIG_DIGITS - (int) log10(dec_digits - 1);
1656 else if (dec_digits < 1)
1657 rscale = NUMERIC_MIN_SIG_DIGITS - (int) log10(1 - dec_digits);
1659 rscale = NUMERIC_MIN_SIG_DIGITS;
1661 rscale = Max(rscale, arg.dscale);
1662 rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
1663 rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
1665 ln_var(&arg, &result, rscale);
1667 res = make_result(&result);
1672 PG_RETURN_NUMERIC(res);
1679 * Compute the logarithm of x in a given base
1682 numeric_log(PG_FUNCTION_ARGS)
1684 Numeric num1 = PG_GETARG_NUMERIC(0);
1685 Numeric num2 = PG_GETARG_NUMERIC(1);
1694 if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
1695 PG_RETURN_NUMERIC(make_result(&const_nan));
1704 set_var_from_num(num1, &arg1);
1705 set_var_from_num(num2, &arg2);
1708 * Call log_var() to compute and return the result; note it handles scale
1711 log_var(&arg1, &arg2, &result);
1713 res = make_result(&result);
1719 PG_RETURN_NUMERIC(res);
1726 * Raise b to the power of x
1729 numeric_power(PG_FUNCTION_ARGS)
1731 Numeric num1 = PG_GETARG_NUMERIC(0);
1732 Numeric num2 = PG_GETARG_NUMERIC(1);
1736 NumericVar arg2_trunc;
1742 if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
1743 PG_RETURN_NUMERIC(make_result(&const_nan));
1750 init_var(&arg2_trunc);
1753 set_var_from_num(num1, &arg1);
1754 set_var_from_num(num2, &arg2);
1755 set_var_from_var(&arg2, &arg2_trunc);
1757 trunc_var(&arg2_trunc, 0);
1760 * Return special SQLSTATE error codes for a few conditions mandated by
1763 if ((cmp_var(&arg1, &const_zero) == 0 &&
1764 cmp_var(&arg2, &const_zero) < 0) ||
1765 (cmp_var(&arg1, &const_zero) < 0 &&
1766 cmp_var(&arg2, &arg2_trunc) != 0))
1768 (errcode(ERRCODE_INVALID_ARGUMENT_FOR_POWER_FUNCTION),
1769 errmsg("invalid argument for power function")));
1772 * Call power_var() to compute and return the result; note it handles
1773 * scale selection itself.
1775 power_var(&arg1, &arg2, &result);
1777 res = make_result(&result);
1781 free_var(&arg2_trunc);
1784 PG_RETURN_NUMERIC(res);
1788 /* ----------------------------------------------------------------------
1790 * Type conversion functions
1792 * ----------------------------------------------------------------------
1797 int4_numeric(PG_FUNCTION_ARGS)
1799 int32 val = PG_GETARG_INT32(0);
1805 int8_to_numericvar((int64) val, &result);
1807 res = make_result(&result);
1811 PG_RETURN_NUMERIC(res);
1816 numeric_int4(PG_FUNCTION_ARGS)
1818 Numeric num = PG_GETARG_NUMERIC(0);
1822 /* XXX would it be better to return NULL? */
1823 if (NUMERIC_IS_NAN(num))
1825 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1826 errmsg("cannot convert NaN to integer")));
1828 /* Convert to variable format, then convert to int4 */
1830 set_var_from_num(num, &x);
1831 result = numericvar_to_int4(&x);
1833 PG_RETURN_INT32(result);
1837 * Given a NumericVar, convert it to an int32. If the NumericVar
1838 * exceeds the range of an int32, raise the appropriate error via
1839 * ereport(). The input NumericVar is *not* free'd.
1842 numericvar_to_int4(NumericVar *var)
1847 if (!numericvar_to_int8(var, &val))
1849 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1850 errmsg("integer out of range")));
1852 /* Down-convert to int4 */
1853 result = (int32) val;
1855 /* Test for overflow by reverse-conversion. */
1856 if ((int64) result != val)
1858 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1859 errmsg("integer out of range")));
1865 int8_numeric(PG_FUNCTION_ARGS)
1867 int64 val = PG_GETARG_INT64(0);
1873 int8_to_numericvar(val, &result);
1875 res = make_result(&result);
1879 PG_RETURN_NUMERIC(res);
1884 numeric_int8(PG_FUNCTION_ARGS)
1886 Numeric num = PG_GETARG_NUMERIC(0);
1890 /* XXX would it be better to return NULL? */
1891 if (NUMERIC_IS_NAN(num))
1893 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1894 errmsg("cannot convert NaN to bigint")));
1896 /* Convert to variable format and thence to int8 */
1898 set_var_from_num(num, &x);
1900 if (!numericvar_to_int8(&x, &result))
1902 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1903 errmsg("bigint out of range")));
1907 PG_RETURN_INT64(result);
1912 int2_numeric(PG_FUNCTION_ARGS)
1914 int16 val = PG_GETARG_INT16(0);
1920 int8_to_numericvar((int64) val, &result);
1922 res = make_result(&result);
1926 PG_RETURN_NUMERIC(res);
1931 numeric_int2(PG_FUNCTION_ARGS)
1933 Numeric num = PG_GETARG_NUMERIC(0);
1938 /* XXX would it be better to return NULL? */
1939 if (NUMERIC_IS_NAN(num))
1941 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1942 errmsg("cannot convert NaN to smallint")));
1944 /* Convert to variable format and thence to int8 */
1946 set_var_from_num(num, &x);
1948 if (!numericvar_to_int8(&x, &val))
1950 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1951 errmsg("smallint out of range")));
1955 /* Down-convert to int2 */
1956 result = (int16) val;
1958 /* Test for overflow by reverse-conversion. */
1959 if ((int64) result != val)
1961 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1962 errmsg("smallint out of range")));
1964 PG_RETURN_INT16(result);
1969 float8_numeric(PG_FUNCTION_ARGS)
1971 float8 val = PG_GETARG_FLOAT8(0);
1974 char buf[DBL_DIG + 100];
1977 PG_RETURN_NUMERIC(make_result(&const_nan));
1979 sprintf(buf, "%.*g", DBL_DIG, val);
1983 set_var_from_str(buf, &result);
1984 res = make_result(&result);
1988 PG_RETURN_NUMERIC(res);
1993 numeric_float8(PG_FUNCTION_ARGS)
1995 Numeric num = PG_GETARG_NUMERIC(0);
1999 if (NUMERIC_IS_NAN(num))
2000 PG_RETURN_FLOAT8(get_float8_nan());
2002 tmp = DatumGetCString(DirectFunctionCall1(numeric_out,
2003 NumericGetDatum(num)));
2005 result = DirectFunctionCall1(float8in, CStringGetDatum(tmp));
2009 PG_RETURN_DATUM(result);
2013 /* Convert numeric to float8; if out of range, return +/- HUGE_VAL */
2015 numeric_float8_no_overflow(PG_FUNCTION_ARGS)
2017 Numeric num = PG_GETARG_NUMERIC(0);
2020 if (NUMERIC_IS_NAN(num))
2021 PG_RETURN_FLOAT8(get_float8_nan());
2023 val = numeric_to_double_no_overflow(num);
2025 PG_RETURN_FLOAT8(val);
2029 float4_numeric(PG_FUNCTION_ARGS)
2031 float4 val = PG_GETARG_FLOAT4(0);
2034 char buf[FLT_DIG + 100];
2037 PG_RETURN_NUMERIC(make_result(&const_nan));
2039 sprintf(buf, "%.*g", FLT_DIG, val);
2043 set_var_from_str(buf, &result);
2044 res = make_result(&result);
2048 PG_RETURN_NUMERIC(res);
2053 numeric_float4(PG_FUNCTION_ARGS)
2055 Numeric num = PG_GETARG_NUMERIC(0);
2059 if (NUMERIC_IS_NAN(num))
2060 PG_RETURN_FLOAT4(get_float4_nan());
2062 tmp = DatumGetCString(DirectFunctionCall1(numeric_out,
2063 NumericGetDatum(num)));
2065 result = DirectFunctionCall1(float4in, CStringGetDatum(tmp));
2069 PG_RETURN_DATUM(result);
2074 text_numeric(PG_FUNCTION_ARGS)
2076 text *str = PG_GETARG_TEXT_P(0);
2081 len = (VARSIZE(str) - VARHDRSZ);
2082 s = palloc(len + 1);
2083 memcpy(s, VARDATA(str), len);
2086 result = DirectFunctionCall3(numeric_in, CStringGetDatum(s),
2087 ObjectIdGetDatum(0), Int32GetDatum(-1));
2095 numeric_text(PG_FUNCTION_ARGS)
2097 /* val is numeric, but easier to leave it as Datum */
2098 Datum val = PG_GETARG_DATUM(0);
2103 s = DatumGetCString(DirectFunctionCall1(numeric_out, val));
2106 result = (text *) palloc(VARHDRSZ + len);
2108 SET_VARSIZE(result, VARHDRSZ + len);
2109 memcpy(VARDATA(result), s, len);
2113 PG_RETURN_TEXT_P(result);
2117 /* ----------------------------------------------------------------------
2119 * Aggregate functions
2121 * The transition datatype for all these aggregates is a 3-element array
2122 * of Numeric, holding the values N, sum(X), sum(X*X) in that order.
2124 * We represent N as a numeric mainly to avoid having to build a special
2125 * datatype; it's unlikely it'd overflow an int4, but ...
2127 * ----------------------------------------------------------------------
2131 do_numeric_accum(ArrayType *transarray, Numeric newval)
2140 /* We assume the input is array of numeric */
2141 deconstruct_array(transarray,
2142 NUMERICOID, -1, false, 'i',
2143 &transdatums, NULL, &ndatums);
2145 elog(ERROR, "expected 3-element numeric array");
2147 sumX = transdatums[1];
2148 sumX2 = transdatums[2];
2150 N = DirectFunctionCall1(numeric_inc, N);
2151 sumX = DirectFunctionCall2(numeric_add, sumX,
2152 NumericGetDatum(newval));
2153 sumX2 = DirectFunctionCall2(numeric_add, sumX2,
2154 DirectFunctionCall2(numeric_mul,
2155 NumericGetDatum(newval),
2156 NumericGetDatum(newval)));
2159 transdatums[1] = sumX;
2160 transdatums[2] = sumX2;
2162 result = construct_array(transdatums, 3,
2163 NUMERICOID, -1, false, 'i');
2169 * Improve avg performance by not caclulating sum(X*X).
2172 do_numeric_avg_accum(ArrayType *transarray, Numeric newval)
2180 /* We assume the input is array of numeric */
2181 deconstruct_array(transarray,
2182 NUMERICOID, -1, false, 'i',
2183 &transdatums, NULL, &ndatums);
2185 elog(ERROR, "expected 2-element numeric array");
2187 sumX = transdatums[1];
2189 N = DirectFunctionCall1(numeric_inc, N);
2190 sumX = DirectFunctionCall2(numeric_add, sumX,
2191 NumericGetDatum(newval));
2194 transdatums[1] = sumX;
2196 result = construct_array(transdatums, 2,
2197 NUMERICOID, -1, false, 'i');
2203 numeric_accum(PG_FUNCTION_ARGS)
2205 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
2206 Numeric newval = PG_GETARG_NUMERIC(1);
2208 PG_RETURN_ARRAYTYPE_P(do_numeric_accum(transarray, newval));
2212 * Optimized case for average of numeric.
2215 numeric_avg_accum(PG_FUNCTION_ARGS)
2217 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
2218 Numeric newval = PG_GETARG_NUMERIC(1);
2220 PG_RETURN_ARRAYTYPE_P(do_numeric_avg_accum(transarray, newval));
2224 * Integer data types all use Numeric accumulators to share code and
2225 * avoid risk of overflow. For int2 and int4 inputs, Numeric accumulation
2226 * is overkill for the N and sum(X) values, but definitely not overkill
2227 * for the sum(X*X) value. Hence, we use int2_accum and int4_accum only
2228 * for stddev/variance --- there are faster special-purpose accumulator
2229 * routines for SUM and AVG of these datatypes.
2233 int2_accum(PG_FUNCTION_ARGS)
2235 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
2236 Datum newval2 = PG_GETARG_DATUM(1);
2239 newval = DatumGetNumeric(DirectFunctionCall1(int2_numeric, newval2));
2241 PG_RETURN_ARRAYTYPE_P(do_numeric_accum(transarray, newval));
2245 int4_accum(PG_FUNCTION_ARGS)
2247 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
2248 Datum newval4 = PG_GETARG_DATUM(1);
2251 newval = DatumGetNumeric(DirectFunctionCall1(int4_numeric, newval4));
2253 PG_RETURN_ARRAYTYPE_P(do_numeric_accum(transarray, newval));
2257 int8_accum(PG_FUNCTION_ARGS)
2259 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
2260 Datum newval8 = PG_GETARG_DATUM(1);
2263 newval = DatumGetNumeric(DirectFunctionCall1(int8_numeric, newval8));
2265 PG_RETURN_ARRAYTYPE_P(do_numeric_accum(transarray, newval));
2269 * Optimized case for average of int8.
2272 int8_avg_accum(PG_FUNCTION_ARGS)
2274 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
2275 Datum newval8 = PG_GETARG_DATUM(1);
2278 newval = DatumGetNumeric(DirectFunctionCall1(int8_numeric, newval8));
2280 PG_RETURN_ARRAYTYPE_P(do_numeric_avg_accum(transarray, newval));
2285 numeric_avg(PG_FUNCTION_ARGS)
2287 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
2293 /* We assume the input is array of numeric */
2294 deconstruct_array(transarray,
2295 NUMERICOID, -1, false, 'i',
2296 &transdatums, NULL, &ndatums);
2298 elog(ERROR, "expected 2-element numeric array");
2299 N = DatumGetNumeric(transdatums[0]);
2300 sumX = DatumGetNumeric(transdatums[1]);
2302 /* SQL92 defines AVG of no values to be NULL */
2303 /* N is zero iff no digits (cf. numeric_uminus) */
2304 if (VARSIZE(N) == NUMERIC_HDRSZ)
2307 PG_RETURN_DATUM(DirectFunctionCall2(numeric_div,
2308 NumericGetDatum(sumX),
2309 NumericGetDatum(N)));
2313 * Workhorse routine for the standard deviance and variance
2314 * aggregates. 'transarray' is the aggregate's transition
2315 * array. 'variance' specifies whether we should calculate the
2316 * variance or the standard deviation. 'sample' indicates whether the
2317 * caller is interested in the sample or the population
2320 * If appropriate variance statistic is undefined for the input,
2321 * *is_null is set to true and NULL is returned.
2324 numeric_stddev_internal(ArrayType *transarray,
2325 bool variance, bool sample,
2343 /* We assume the input is array of numeric */
2344 deconstruct_array(transarray,
2345 NUMERICOID, -1, false, 'i',
2346 &transdatums, NULL, &ndatums);
2348 elog(ERROR, "expected 3-element numeric array");
2349 N = DatumGetNumeric(transdatums[0]);
2350 sumX = DatumGetNumeric(transdatums[1]);
2351 sumX2 = DatumGetNumeric(transdatums[2]);
2353 if (NUMERIC_IS_NAN(N) || NUMERIC_IS_NAN(sumX) || NUMERIC_IS_NAN(sumX2))
2354 return make_result(&const_nan);
2357 set_var_from_num(N, &vN);
2360 * Sample stddev and variance are undefined when N <= 1; population stddev
2361 * is undefined when N == 0. Return NULL in either case.
2368 if (cmp_var(&vN, comp) <= 0)
2375 init_var(&vNminus1);
2376 sub_var(&vN, &const_one, &vNminus1);
2379 set_var_from_num(sumX, &vsumX);
2381 set_var_from_num(sumX2, &vsumX2);
2383 /* compute rscale for mul_var calls */
2384 rscale = vsumX.dscale * 2;
2386 mul_var(&vsumX, &vsumX, &vsumX, rscale); /* vsumX = sumX * sumX */
2387 mul_var(&vN, &vsumX2, &vsumX2, rscale); /* vsumX2 = N * sumX2 */
2388 sub_var(&vsumX2, &vsumX, &vsumX2); /* N * sumX2 - sumX * sumX */
2390 if (cmp_var(&vsumX2, &const_zero) <= 0)
2392 /* Watch out for roundoff error producing a negative numerator */
2393 res = make_result(&const_zero);
2397 mul_var(&vN, &vNminus1, &vNminus1, 0); /* N * (N - 1) */
2398 rscale = select_div_scale(&vsumX2, &vNminus1);
2399 div_var(&vsumX2, &vNminus1, &vsumX, rscale, true); /* variance */
2401 sqrt_var(&vsumX, &vsumX, rscale); /* stddev */
2403 res = make_result(&vsumX);
2407 free_var(&vNminus1);
2415 numeric_var_samp(PG_FUNCTION_ARGS)
2420 res = numeric_stddev_internal(PG_GETARG_ARRAYTYPE_P(0),
2421 true, true, &is_null);
2426 PG_RETURN_NUMERIC(res);
2430 numeric_stddev_samp(PG_FUNCTION_ARGS)
2435 res = numeric_stddev_internal(PG_GETARG_ARRAYTYPE_P(0),
2436 false, true, &is_null);
2441 PG_RETURN_NUMERIC(res);
2445 numeric_var_pop(PG_FUNCTION_ARGS)
2450 res = numeric_stddev_internal(PG_GETARG_ARRAYTYPE_P(0),
2451 true, false, &is_null);
2456 PG_RETURN_NUMERIC(res);
2460 numeric_stddev_pop(PG_FUNCTION_ARGS)
2465 res = numeric_stddev_internal(PG_GETARG_ARRAYTYPE_P(0),
2466 false, false, &is_null);
2471 PG_RETURN_NUMERIC(res);
2475 * SUM transition functions for integer datatypes.
2477 * To avoid overflow, we use accumulators wider than the input datatype.
2478 * A Numeric accumulator is needed for int8 input; for int4 and int2
2479 * inputs, we use int8 accumulators which should be sufficient for practical
2480 * purposes. (The latter two therefore don't really belong in this file,
2481 * but we keep them here anyway.)
2483 * Because SQL92 defines the SUM() of no values to be NULL, not zero,
2484 * the initial condition of the transition data value needs to be NULL. This
2485 * means we can't rely on ExecAgg to automatically insert the first non-null
2486 * data value into the transition data: it doesn't know how to do the type
2487 * conversion. The upshot is that these routines have to be marked non-strict
2488 * and handle substitution of the first non-null input themselves.
2492 int2_sum(PG_FUNCTION_ARGS)
2496 if (PG_ARGISNULL(0))
2498 /* No non-null input seen so far... */
2499 if (PG_ARGISNULL(1))
2500 PG_RETURN_NULL(); /* still no non-null */
2501 /* This is the first non-null input. */
2502 newval = (int64) PG_GETARG_INT16(1);
2503 PG_RETURN_INT64(newval);
2507 * If we're invoked by nodeAgg, we can cheat and modify out first
2508 * parameter in-place to avoid palloc overhead. If not, we need to return
2509 * the new value of the transition variable.
2511 if (fcinfo->context && IsA(fcinfo->context, AggState))
2513 int64 *oldsum = (int64 *) PG_GETARG_POINTER(0);
2515 /* Leave the running sum unchanged in the new input is null */
2516 if (!PG_ARGISNULL(1))
2517 *oldsum = *oldsum + (int64) PG_GETARG_INT16(1);
2519 PG_RETURN_POINTER(oldsum);
2523 int64 oldsum = PG_GETARG_INT64(0);
2525 /* Leave sum unchanged if new input is null. */
2526 if (PG_ARGISNULL(1))
2527 PG_RETURN_INT64(oldsum);
2529 /* OK to do the addition. */
2530 newval = oldsum + (int64) PG_GETARG_INT16(1);
2532 PG_RETURN_INT64(newval);
2537 int4_sum(PG_FUNCTION_ARGS)
2541 if (PG_ARGISNULL(0))
2543 /* No non-null input seen so far... */
2544 if (PG_ARGISNULL(1))
2545 PG_RETURN_NULL(); /* still no non-null */
2546 /* This is the first non-null input. */
2547 newval = (int64) PG_GETARG_INT32(1);
2548 PG_RETURN_INT64(newval);
2552 * If we're invoked by nodeAgg, we can cheat and modify out first
2553 * parameter in-place to avoid palloc overhead. If not, we need to return
2554 * the new value of the transition variable.
2556 if (fcinfo->context && IsA(fcinfo->context, AggState))
2558 int64 *oldsum = (int64 *) PG_GETARG_POINTER(0);
2560 /* Leave the running sum unchanged in the new input is null */
2561 if (!PG_ARGISNULL(1))
2562 *oldsum = *oldsum + (int64) PG_GETARG_INT32(1);
2564 PG_RETURN_POINTER(oldsum);
2568 int64 oldsum = PG_GETARG_INT64(0);
2570 /* Leave sum unchanged if new input is null. */
2571 if (PG_ARGISNULL(1))
2572 PG_RETURN_INT64(oldsum);
2574 /* OK to do the addition. */
2575 newval = oldsum + (int64) PG_GETARG_INT32(1);
2577 PG_RETURN_INT64(newval);
2582 int8_sum(PG_FUNCTION_ARGS)
2587 if (PG_ARGISNULL(0))
2589 /* No non-null input seen so far... */
2590 if (PG_ARGISNULL(1))
2591 PG_RETURN_NULL(); /* still no non-null */
2592 /* This is the first non-null input. */
2593 newval = DirectFunctionCall1(int8_numeric, PG_GETARG_DATUM(1));
2594 PG_RETURN_DATUM(newval);
2598 * Note that we cannot special-case the nodeAgg case here, as we do for
2599 * int2_sum and int4_sum: numeric is of variable size, so we cannot modify
2600 * our first parameter in-place.
2603 oldsum = PG_GETARG_NUMERIC(0);
2605 /* Leave sum unchanged if new input is null. */
2606 if (PG_ARGISNULL(1))
2607 PG_RETURN_NUMERIC(oldsum);
2609 /* OK to do the addition. */
2610 newval = DirectFunctionCall1(int8_numeric, PG_GETARG_DATUM(1));
2612 PG_RETURN_DATUM(DirectFunctionCall2(numeric_add,
2613 NumericGetDatum(oldsum), newval));
2618 * Routines for avg(int2) and avg(int4). The transition datatype
2619 * is a two-element int8 array, holding count and sum.
2622 typedef struct Int8TransTypeData
2624 #ifndef INT64_IS_BUSTED
2628 /* "int64" isn't really 64 bits, so fake up properly-aligned fields */
2634 } Int8TransTypeData;
2637 int2_avg_accum(PG_FUNCTION_ARGS)
2639 ArrayType *transarray;
2640 int16 newval = PG_GETARG_INT16(1);
2641 Int8TransTypeData *transdata;
2644 * If we're invoked by nodeAgg, we can cheat and modify our first
2645 * parameter in-place to reduce palloc overhead. Otherwise we need to make
2646 * a copy of it before scribbling on it.
2648 if (fcinfo->context && IsA(fcinfo->context, AggState))
2649 transarray = PG_GETARG_ARRAYTYPE_P(0);
2651 transarray = PG_GETARG_ARRAYTYPE_P_COPY(0);
2653 if (ARR_HASNULL(transarray) ||
2654 ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
2655 elog(ERROR, "expected 2-element int8 array");
2657 transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
2659 transdata->sum += newval;
2661 PG_RETURN_ARRAYTYPE_P(transarray);
2665 int4_avg_accum(PG_FUNCTION_ARGS)
2667 ArrayType *transarray;
2668 int32 newval = PG_GETARG_INT32(1);
2669 Int8TransTypeData *transdata;
2672 * If we're invoked by nodeAgg, we can cheat and modify our first
2673 * parameter in-place to reduce palloc overhead. Otherwise we need to make
2674 * a copy of it before scribbling on it.
2676 if (fcinfo->context && IsA(fcinfo->context, AggState))
2677 transarray = PG_GETARG_ARRAYTYPE_P(0);
2679 transarray = PG_GETARG_ARRAYTYPE_P_COPY(0);
2681 if (ARR_HASNULL(transarray) ||
2682 ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
2683 elog(ERROR, "expected 2-element int8 array");
2685 transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
2687 transdata->sum += newval;
2689 PG_RETURN_ARRAYTYPE_P(transarray);
2693 int8_avg(PG_FUNCTION_ARGS)
2695 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
2696 Int8TransTypeData *transdata;
2700 if (ARR_HASNULL(transarray) ||
2701 ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
2702 elog(ERROR, "expected 2-element int8 array");
2703 transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
2705 /* SQL92 defines AVG of no values to be NULL */
2706 if (transdata->count == 0)
2709 countd = DirectFunctionCall1(int8_numeric,
2710 Int64GetDatumFast(transdata->count));
2711 sumd = DirectFunctionCall1(int8_numeric,
2712 Int64GetDatumFast(transdata->sum));
2714 PG_RETURN_DATUM(DirectFunctionCall2(numeric_div, sumd, countd));
2718 /* ----------------------------------------------------------------------
2722 * ----------------------------------------------------------------------
2725 #ifdef NUMERIC_DEBUG
2728 * dump_numeric() - Dump a value in the db storage format for debugging
2731 dump_numeric(const char *str, Numeric num)
2733 NumericDigit *digits = NUMERIC_DIGITS(num);
2737 ndigits = NUMERIC_NDIGITS(num);
2739 printf("%s: NUMERIC w=%d d=%d ", str, num->n_weight, NUMERIC_DSCALE(num));
2740 switch (NUMERIC_SIGN(num))
2752 printf("SIGN=0x%x", NUMERIC_SIGN(num));
2756 for (i = 0; i < ndigits; i++)
2757 printf(" %0*d", DEC_DIGITS, digits[i]);
2763 * dump_var() - Dump a value in the variable format for debugging
2766 dump_var(const char *str, NumericVar *var)
2770 printf("%s: VAR w=%d d=%d ", str, var->weight, var->dscale);
2783 printf("SIGN=0x%x", var->sign);
2787 for (i = 0; i < var->ndigits; i++)
2788 printf(" %0*d", DEC_DIGITS, var->digits[i]);
2792 #endif /* NUMERIC_DEBUG */
2795 /* ----------------------------------------------------------------------
2797 * Local functions follow
2799 * In general, these do not support NaNs --- callers must eliminate
2800 * the possibility of NaN first. (make_result() is an exception.)
2802 * ----------------------------------------------------------------------
2809 * Allocate a digit buffer of ndigits digits (plus a spare digit for rounding)
2812 alloc_var(NumericVar *var, int ndigits)
2814 digitbuf_free(var->buf);
2815 var->buf = digitbuf_alloc(ndigits + 1);
2816 var->buf[0] = 0; /* spare digit for rounding */
2817 var->digits = var->buf + 1;
2818 var->ndigits = ndigits;
2825 * Return the digit buffer of a variable to the free pool
2828 free_var(NumericVar *var)
2830 digitbuf_free(var->buf);
2833 var->sign = NUMERIC_NAN;
2840 * Set a variable to ZERO.
2841 * Note: its dscale is not touched.
2844 zero_var(NumericVar *var)
2846 digitbuf_free(var->buf);
2850 var->weight = 0; /* by convention; doesn't really matter */
2851 var->sign = NUMERIC_POS; /* anything but NAN... */
2856 * set_var_from_str()
2858 * Parse a string and put the number into a variable
2861 set_var_from_str(const char *str, NumericVar *dest)
2863 const char *cp = str;
2864 bool have_dp = FALSE;
2866 unsigned char *decdigits;
2867 int sign = NUMERIC_POS;
2874 NumericDigit *digits;
2877 * We first parse the string to extract decimal digits and determine the
2878 * correct decimal weight. Then convert to NBASE representation.
2881 /* skip leading spaces */
2884 if (!isspace((unsigned char) *cp))
2908 if (!isdigit((unsigned char) *cp))
2910 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
2911 errmsg("invalid input syntax for type numeric: \"%s\"", str)));
2913 decdigits = (unsigned char *) palloc(strlen(cp) + DEC_DIGITS * 2);
2915 /* leading padding for digit alignment later */
2916 memset(decdigits, 0, DEC_DIGITS);
2921 if (isdigit((unsigned char) *cp))
2923 decdigits[i++] = *cp++ - '0';
2929 else if (*cp == '.')
2933 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
2934 errmsg("invalid input syntax for type numeric: \"%s\"",
2943 ddigits = i - DEC_DIGITS;
2944 /* trailing padding for digit alignment later */
2945 memset(decdigits + i, 0, DEC_DIGITS - 1);
2947 /* Handle exponent, if any */
2948 if (*cp == 'e' || *cp == 'E')
2954 exponent = strtol(cp, &endptr, 10);
2957 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
2958 errmsg("invalid input syntax for type numeric: \"%s\"",
2961 if (exponent > NUMERIC_MAX_PRECISION ||
2962 exponent < -NUMERIC_MAX_PRECISION)
2964 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
2965 errmsg("invalid input syntax for type numeric: \"%s\"",
2967 dweight += (int) exponent;
2968 dscale -= (int) exponent;
2973 /* Should be nothing left but spaces */
2976 if (!isspace((unsigned char) *cp))
2978 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
2979 errmsg("invalid input syntax for type numeric: \"%s\"",
2985 * Okay, convert pure-decimal representation to base NBASE. First we need
2986 * to determine the converted weight and ndigits. offset is the number of
2987 * decimal zeroes to insert before the first given digit to have a
2988 * correctly aligned first NBASE digit.
2991 weight = (dweight + 1 + DEC_DIGITS - 1) / DEC_DIGITS - 1;
2993 weight = -((-dweight - 1) / DEC_DIGITS + 1);
2994 offset = (weight + 1) * DEC_DIGITS - (dweight + 1);
2995 ndigits = (ddigits + offset + DEC_DIGITS - 1) / DEC_DIGITS;
2997 alloc_var(dest, ndigits);
2999 dest->weight = weight;
3000 dest->dscale = dscale;
3002 i = DEC_DIGITS - offset;
3003 digits = dest->digits;
3005 while (ndigits-- > 0)
3008 *digits++ = ((decdigits[i] * 10 + decdigits[i + 1]) * 10 +
3009 decdigits[i + 2]) * 10 + decdigits[i + 3];
3010 #elif DEC_DIGITS == 2
3011 *digits++ = decdigits[i] * 10 + decdigits[i + 1];
3012 #elif DEC_DIGITS == 1
3013 *digits++ = decdigits[i];
3015 #error unsupported NBASE
3022 /* Strip any leading/trailing zeroes, and normalize weight if zero */
3028 * set_var_from_num() -
3030 * Convert the packed db format into a variable
3033 set_var_from_num(Numeric num, NumericVar *dest)
3037 ndigits = NUMERIC_NDIGITS(num);
3039 alloc_var(dest, ndigits);
3041 dest->weight = num->n_weight;
3042 dest->sign = NUMERIC_SIGN(num);
3043 dest->dscale = NUMERIC_DSCALE(num);
3045 memcpy(dest->digits, num->n_data, ndigits * sizeof(NumericDigit));
3050 * set_var_from_var() -
3052 * Copy one variable into another
3055 set_var_from_var(NumericVar *value, NumericVar *dest)
3057 NumericDigit *newbuf;
3059 newbuf = digitbuf_alloc(value->ndigits + 1);
3060 newbuf[0] = 0; /* spare digit for rounding */
3061 memcpy(newbuf + 1, value->digits, value->ndigits * sizeof(NumericDigit));
3063 digitbuf_free(dest->buf);
3065 memmove(dest, value, sizeof(NumericVar));
3067 dest->digits = newbuf + 1;
3072 * get_str_from_var() -
3074 * Convert a var to text representation (guts of numeric_out).
3075 * CAUTION: var's contents may be modified by rounding!
3076 * Returns a palloc'd string.
3079 get_str_from_var(NumericVar *var, int dscale)
3096 * Check if we must round up before printing the value and do so.
3098 round_var(var, dscale);
3101 * Allocate space for the result.
3103 * i is set to to # of decimal digits before decimal point. dscale is the
3104 * # of decimal digits we will print after decimal point. We may generate
3105 * as many as DEC_DIGITS-1 excess digits at the end, and in addition we
3106 * need room for sign, decimal point, null terminator.
3108 i = (var->weight + 1) * DEC_DIGITS;
3112 str = palloc(i + dscale + DEC_DIGITS + 2);
3116 * Output a dash for negative values
3118 if (var->sign == NUMERIC_NEG)
3122 * Output all digits before the decimal point
3124 if (var->weight < 0)
3126 d = var->weight + 1;
3131 for (d = 0; d <= var->weight; d++)
3133 dig = (d < var->ndigits) ? var->digits[d] : 0;
3134 /* In the first digit, suppress extra leading decimal zeroes */
3137 bool putit = (d > 0);
3156 #elif DEC_DIGITS == 2
3159 if (d1 > 0 || d > 0)
3162 #elif DEC_DIGITS == 1
3165 #error unsupported NBASE
3171 * If requested, output a decimal point and all the digits that follow it.
3172 * We initially put out a multiple of DEC_DIGITS digits, then truncate if
3178 endcp = cp + dscale;
3179 for (i = 0; i < dscale; d++, i += DEC_DIGITS)
3181 dig = (d >= 0 && d < var->ndigits) ? var->digits[d] : 0;
3193 #elif DEC_DIGITS == 2
3198 #elif DEC_DIGITS == 1
3201 #error unsupported NBASE
3208 * terminate the string and return it
3218 * Create the packed db numeric format in palloc()'d memory from
3222 make_result(NumericVar *var)
3225 NumericDigit *digits = var->digits;
3226 int weight = var->weight;
3227 int sign = var->sign;
3231 if (sign == NUMERIC_NAN)
3233 result = (Numeric) palloc(NUMERIC_HDRSZ);
3235 SET_VARSIZE(result, NUMERIC_HDRSZ);
3236 result->n_weight = 0;
3237 result->n_sign_dscale = NUMERIC_NAN;
3239 dump_numeric("make_result()", result);
3245 /* truncate leading zeroes */
3246 while (n > 0 && *digits == 0)
3252 /* truncate trailing zeroes */
3253 while (n > 0 && digits[n - 1] == 0)
3256 /* If zero result, force to weight=0 and positive sign */
3263 /* Build the result */
3264 len = NUMERIC_HDRSZ + n * sizeof(NumericDigit);
3265 result = (Numeric) palloc(len);
3266 SET_VARSIZE(result, len);
3267 result->n_weight = weight;
3268 result->n_sign_dscale = sign | (var->dscale & NUMERIC_DSCALE_MASK);
3270 memcpy(result->n_data, digits, n * sizeof(NumericDigit));
3272 /* Check for overflow of int16 fields */
3273 if (result->n_weight != weight ||
3274 NUMERIC_DSCALE(result) != var->dscale)
3276 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
3277 errmsg("value overflows numeric format")));
3279 dump_numeric("make_result()", result);
3287 * Do bounds checking and rounding according to the attributes
3291 apply_typmod(NumericVar *var, int32 typmod)
3299 /* Do nothing if we have a default typmod (-1) */
3300 if (typmod < (int32) (VARHDRSZ))
3304 precision = (typmod >> 16) & 0xffff;
3305 scale = typmod & 0xffff;
3306 maxdigits = precision - scale;
3308 /* Round to target scale (and set var->dscale) */
3309 round_var(var, scale);
3312 * Check for overflow - note we can't do this before rounding, because
3313 * rounding could raise the weight. Also note that the var's weight could
3314 * be inflated by leading zeroes, which will be stripped before storage
3315 * but perhaps might not have been yet. In any case, we must recognize a
3316 * true zero, whose weight doesn't mean anything.
3318 ddigits = (var->weight + 1) * DEC_DIGITS;
3319 if (ddigits > maxdigits)
3321 /* Determine true weight; and check for all-zero result */
3322 for (i = 0; i < var->ndigits; i++)
3324 NumericDigit dig = var->digits[i];
3328 /* Adjust for any high-order decimal zero digits */
3334 else if (dig < 1000)
3336 #elif DEC_DIGITS == 2
3339 #elif DEC_DIGITS == 1
3342 #error unsupported NBASE
3344 if (ddigits > maxdigits)
3346 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
3347 errmsg("numeric field overflow"),
3348 errdetail("A field with precision %d, scale %d must round to an absolute value less than %s%d.",
3350 /* Display 10^0 as 1 */
3351 maxdigits ? "10^" : "",
3352 maxdigits ? maxdigits : 1
3356 ddigits -= DEC_DIGITS;
3362 * Convert numeric to int8, rounding if needed.
3364 * If overflow, return FALSE (no error is raised). Return TRUE if okay.
3366 * CAUTION: var's contents may be modified by rounding!
3369 numericvar_to_int8(NumericVar *var, int64 *result)
3371 NumericDigit *digits;
3379 /* Round to nearest integer */
3382 /* Check for zero input */
3384 ndigits = var->ndigits;
3392 * For input like 10000000000, we must treat stripped digits as real. So
3393 * the loop assumes there are weight+1 digits before the decimal point.
3395 weight = var->weight;
3396 Assert(weight >= 0 && ndigits <= weight + 1);
3398 /* Construct the result */
3399 digits = var->digits;
3400 neg = (var->sign == NUMERIC_NEG);
3402 for (i = 1; i <= weight; i++)
3410 * The overflow check is a bit tricky because we want to accept
3411 * INT64_MIN, which will overflow the positive accumulator. We can
3412 * detect this case easily though because INT64_MIN is the only
3413 * nonzero value for which -val == val (on a two's complement machine,
3416 if ((val / NBASE) != oldval) /* possible overflow? */
3418 if (!neg || (-val) != val || val == 0 || oldval < 0)
3423 *result = neg ? -val : val;
3428 * Convert int8 value to numeric.
3431 int8_to_numericvar(int64 val, NumericVar *var)
3438 /* int8 can require at most 19 decimal digits; add one for safety */
3439 alloc_var(var, 20 / DEC_DIGITS);
3442 var->sign = NUMERIC_NEG;
3447 var->sign = NUMERIC_POS;
3457 ptr = var->digits + var->ndigits;
3463 newuval = uval / NBASE;
3464 *ptr = uval - newuval * NBASE;
3468 var->ndigits = ndigits;
3469 var->weight = ndigits - 1;
3473 * Convert numeric to float8; if out of range, return +/- HUGE_VAL
3476 numeric_to_double_no_overflow(Numeric num)
3482 tmp = DatumGetCString(DirectFunctionCall1(numeric_out,
3483 NumericGetDatum(num)));
3485 /* unlike float8in, we ignore ERANGE from strtod */
3486 val = strtod(tmp, &endptr);
3487 if (*endptr != '\0')
3489 /* shouldn't happen ... */
3491 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
3492 errmsg("invalid input syntax for type double precision: \"%s\"",
3501 /* As above, but work from a NumericVar */
3503 numericvar_to_double_no_overflow(NumericVar *var)
3509 tmp = get_str_from_var(var, var->dscale);
3511 /* unlike float8in, we ignore ERANGE from strtod */
3512 val = strtod(tmp, &endptr);
3513 if (*endptr != '\0')
3515 /* shouldn't happen ... */
3517 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
3518 errmsg("invalid input syntax for type double precision: \"%s\"",
3531 * Compare two values on variable level. We assume zeroes have been
3532 * truncated to no digits.
3535 cmp_var(NumericVar *var1, NumericVar *var2)
3537 return cmp_var_common(var1->digits, var1->ndigits,
3538 var1->weight, var1->sign,
3539 var2->digits, var2->ndigits,
3540 var2->weight, var2->sign);
3544 * cmp_var_common() -
3546 * Main routine of cmp_var(). This function can be used by both
3547 * NumericVar and Numeric.
3550 cmp_var_common(const NumericDigit *var1digits, int var1ndigits,
3551 int var1weight, int var1sign,
3552 const NumericDigit *var2digits, int var2ndigits,
3553 int var2weight, int var2sign)
3555 if (var1ndigits == 0)
3557 if (var2ndigits == 0)
3559 if (var2sign == NUMERIC_NEG)
3563 if (var2ndigits == 0)
3565 if (var1sign == NUMERIC_POS)
3570 if (var1sign == NUMERIC_POS)
3572 if (var2sign == NUMERIC_NEG)
3574 return cmp_abs_common(var1digits, var1ndigits, var1weight,
3575 var2digits, var2ndigits, var2weight);
3578 if (var2sign == NUMERIC_POS)
3581 return cmp_abs_common(var2digits, var2ndigits, var2weight,
3582 var1digits, var1ndigits, var1weight);
3589 * Full version of add functionality on variable level (handling signs).
3590 * result might point to one of the operands too without danger.
3593 add_var(NumericVar *var1, NumericVar *var2, NumericVar *result)
3596 * Decide on the signs of the two variables what to do
3598 if (var1->sign == NUMERIC_POS)
3600 if (var2->sign == NUMERIC_POS)
3603 * Both are positive result = +(ABS(var1) + ABS(var2))
3605 add_abs(var1, var2, result);
3606 result->sign = NUMERIC_POS;
3611 * var1 is positive, var2 is negative Must compare absolute values
3613 switch (cmp_abs(var1, var2))
3617 * ABS(var1) == ABS(var2)
3622 result->dscale = Max(var1->dscale, var2->dscale);
3627 * ABS(var1) > ABS(var2)
3628 * result = +(ABS(var1) - ABS(var2))
3631 sub_abs(var1, var2, result);
3632 result->sign = NUMERIC_POS;
3637 * ABS(var1) < ABS(var2)
3638 * result = -(ABS(var2) - ABS(var1))
3641 sub_abs(var2, var1, result);
3642 result->sign = NUMERIC_NEG;
3649 if (var2->sign == NUMERIC_POS)
3652 * var1 is negative, var2 is positive
3653 * Must compare absolute values
3656 switch (cmp_abs(var1, var2))
3660 * ABS(var1) == ABS(var2)
3665 result->dscale = Max(var1->dscale, var2->dscale);
3670 * ABS(var1) > ABS(var2)
3671 * result = -(ABS(var1) - ABS(var2))
3674 sub_abs(var1, var2, result);
3675 result->sign = NUMERIC_NEG;
3680 * ABS(var1) < ABS(var2)
3681 * result = +(ABS(var2) - ABS(var1))
3684 sub_abs(var2, var1, result);
3685 result->sign = NUMERIC_POS;
3693 * result = -(ABS(var1) + ABS(var2))
3696 add_abs(var1, var2, result);
3697 result->sign = NUMERIC_NEG;
3706 * Full version of sub functionality on variable level (handling signs).
3707 * result might point to one of the operands too without danger.
3710 sub_var(NumericVar *var1, NumericVar *var2, NumericVar *result)
3713 * Decide on the signs of the two variables what to do
3715 if (var1->sign == NUMERIC_POS)
3717 if (var2->sign == NUMERIC_NEG)
3720 * var1 is positive, var2 is negative
3721 * result = +(ABS(var1) + ABS(var2))
3724 add_abs(var1, var2, result);
3725 result->sign = NUMERIC_POS;
3731 * Must compare absolute values
3734 switch (cmp_abs(var1, var2))
3738 * ABS(var1) == ABS(var2)
3743 result->dscale = Max(var1->dscale, var2->dscale);
3748 * ABS(var1) > ABS(var2)
3749 * result = +(ABS(var1) - ABS(var2))
3752 sub_abs(var1, var2, result);
3753 result->sign = NUMERIC_POS;
3758 * ABS(var1) < ABS(var2)
3759 * result = -(ABS(var2) - ABS(var1))
3762 sub_abs(var2, var1, result);
3763 result->sign = NUMERIC_NEG;
3770 if (var2->sign == NUMERIC_NEG)
3774 * Must compare absolute values
3777 switch (cmp_abs(var1, var2))
3781 * ABS(var1) == ABS(var2)
3786 result->dscale = Max(var1->dscale, var2->dscale);
3791 * ABS(var1) > ABS(var2)
3792 * result = -(ABS(var1) - ABS(var2))
3795 sub_abs(var1, var2, result);
3796 result->sign = NUMERIC_NEG;
3801 * ABS(var1) < ABS(var2)
3802 * result = +(ABS(var2) - ABS(var1))
3805 sub_abs(var2, var1, result);
3806 result->sign = NUMERIC_POS;
3813 * var1 is negative, var2 is positive
3814 * result = -(ABS(var1) + ABS(var2))
3817 add_abs(var1, var2, result);
3818 result->sign = NUMERIC_NEG;
3827 * Multiplication on variable level. Product of var1 * var2 is stored
3828 * in result. Result is rounded to no more than rscale fractional digits.
3831 mul_var(NumericVar *var1, NumericVar *var2, NumericVar *result,
3842 NumericDigit *res_digits;
3848 /* copy these values into local vars for speed in inner loop */
3849 int var1ndigits = var1->ndigits;
3850 int var2ndigits = var2->ndigits;
3851 NumericDigit *var1digits = var1->digits;
3852 NumericDigit *var2digits = var2->digits;
3854 if (var1ndigits == 0 || var2ndigits == 0)
3856 /* one or both inputs is zero; so is result */
3858 result->dscale = rscale;
3862 /* Determine result sign and (maximum possible) weight */
3863 if (var1->sign == var2->sign)
3864 res_sign = NUMERIC_POS;
3866 res_sign = NUMERIC_NEG;
3867 res_weight = var1->weight + var2->weight + 2;
3870 * Determine number of result digits to compute. If the exact result
3871 * would have more than rscale fractional digits, truncate the computation
3872 * with MUL_GUARD_DIGITS guard digits. We do that by pretending that one
3873 * or both inputs have fewer digits than they really do.
3875 res_ndigits = var1ndigits + var2ndigits + 1;
3876 maxdigits = res_weight + 1 + (rscale * DEC_DIGITS) + MUL_GUARD_DIGITS;
3877 if (res_ndigits > maxdigits)
3881 /* no useful precision at all in the result... */
3883 result->dscale = rscale;
3886 /* force maxdigits odd so that input ndigits can be equal */
3887 if ((maxdigits & 1) == 0)
3889 if (var1ndigits > var2ndigits)
3891 var1ndigits -= res_ndigits - maxdigits;
3892 if (var1ndigits < var2ndigits)
3893 var1ndigits = var2ndigits = (var1ndigits + var2ndigits) / 2;
3897 var2ndigits -= res_ndigits - maxdigits;
3898 if (var2ndigits < var1ndigits)
3899 var1ndigits = var2ndigits = (var1ndigits + var2ndigits) / 2;
3901 res_ndigits = maxdigits;
3902 Assert(res_ndigits == var1ndigits + var2ndigits + 1);
3906 * We do the arithmetic in an array "dig[]" of signed int's. Since
3907 * INT_MAX is noticeably larger than NBASE*NBASE, this gives us headroom
3908 * to avoid normalizing carries immediately.
3910 * maxdig tracks the maximum possible value of any dig[] entry; when this
3911 * threatens to exceed INT_MAX, we take the time to propagate carries. To
3912 * avoid overflow in maxdig itself, it actually represents the max
3913 * possible value divided by NBASE-1.
3915 dig = (int *) palloc0(res_ndigits * sizeof(int));
3918 ri = res_ndigits - 1;
3919 for (i1 = var1ndigits - 1; i1 >= 0; ri--, i1--)
3921 int var1digit = var1digits[i1];
3926 /* Time to normalize? */
3927 maxdig += var1digit;
3928 if (maxdig > INT_MAX / (NBASE - 1))
3932 for (i = res_ndigits - 1; i >= 0; i--)
3934 newdig = dig[i] + carry;
3935 if (newdig >= NBASE)
3937 carry = newdig / NBASE;
3938 newdig -= carry * NBASE;
3945 /* Reset maxdig to indicate new worst-case */
3946 maxdig = 1 + var1digit;
3949 /* Add appropriate multiple of var2 into the accumulator */
3951 for (i2 = var2ndigits - 1; i2 >= 0; i2--)
3952 dig[i--] += var1digit * var2digits[i2];
3956 * Now we do a final carry propagation pass to normalize the result, which
3957 * we combine with storing the result digits into the output. Note that
3958 * this is still done at full precision w/guard digits.
3960 alloc_var(result, res_ndigits);
3961 res_digits = result->digits;
3963 for (i = res_ndigits - 1; i >= 0; i--)
3965 newdig = dig[i] + carry;
3966 if (newdig >= NBASE)
3968 carry = newdig / NBASE;
3969 newdig -= carry * NBASE;
3973 res_digits[i] = newdig;
3980 * Finally, round the result to the requested precision.
3982 result->weight = res_weight;
3983 result->sign = res_sign;
3985 /* Round to target rscale (and set result->dscale) */
3986 round_var(result, rscale);
3988 /* Strip leading and trailing zeroes */
3996 * Division on variable level. Quotient of var1 / var2 is stored
3997 * in result. Result is rounded to no more than rscale fractional digits.
4000 div_var(NumericVar *var1, NumericVar *var2, NumericVar *result,
4001 int rscale, bool round)
4011 NumericDigit *res_digits;
4019 /* copy these values into local vars for speed in inner loop */
4020 int var1ndigits = var1->ndigits;
4021 int var2ndigits = var2->ndigits;
4022 NumericDigit *var1digits = var1->digits;
4023 NumericDigit *var2digits = var2->digits;
4026 * First of all division by zero check; we must not be handed an
4027 * unnormalized divisor.
4029 if (var2ndigits == 0 || var2digits[0] == 0)
4031 (errcode(ERRCODE_DIVISION_BY_ZERO),
4032 errmsg("division by zero")));
4035 * Now result zero check
4037 if (var1ndigits == 0)
4040 result->dscale = rscale;
4045 * Determine the result sign, weight and number of digits to calculate
4047 if (var1->sign == var2->sign)
4048 res_sign = NUMERIC_POS;
4050 res_sign = NUMERIC_NEG;
4051 res_weight = var1->weight - var2->weight + 1;
4052 /* The number of accurate result digits we need to produce: */
4053 div_ndigits = res_weight + 1 + (rscale + DEC_DIGITS - 1) / DEC_DIGITS;
4054 /* Add guard digits for roundoff error */
4055 div_ndigits += DIV_GUARD_DIGITS;
4056 if (div_ndigits < DIV_GUARD_DIGITS)
4057 div_ndigits = DIV_GUARD_DIGITS;
4058 /* Must be at least var1ndigits, too, to simplify data-loading loop */
4059 if (div_ndigits < var1ndigits)
4060 div_ndigits = var1ndigits;
4063 * We do the arithmetic in an array "div[]" of signed int's. Since
4064 * INT_MAX is noticeably larger than NBASE*NBASE, this gives us headroom
4065 * to avoid normalizing carries immediately.
4067 * We start with div[] containing one zero digit followed by the
4068 * dividend's digits (plus appended zeroes to reach the desired precision
4069 * including guard digits). Each step of the main loop computes an
4070 * (approximate) quotient digit and stores it into div[], removing one
4071 * position of dividend space. A final pass of carry propagation takes
4072 * care of any mistaken quotient digits.
4074 div = (int *) palloc0((div_ndigits + 1) * sizeof(int));
4075 for (i = 0; i < var1ndigits; i++)
4076 div[i + 1] = var1digits[i];
4079 * We estimate each quotient digit using floating-point arithmetic, taking
4080 * the first four digits of the (current) dividend and divisor. This must
4081 * be float to avoid overflow.
4083 fdivisor = (double) var2digits[0];
4084 for (i = 1; i < 4; i++)
4087 if (i < var2ndigits)
4088 fdivisor += (double) var2digits[i];
4090 fdivisorinverse = 1.0 / fdivisor;
4093 * maxdiv tracks the maximum possible absolute value of any div[] entry;
4094 * when this threatens to exceed INT_MAX, we take the time to propagate
4095 * carries. To avoid overflow in maxdiv itself, it actually represents
4096 * the max possible abs. value divided by NBASE-1.
4101 * Outer loop computes next quotient digit, which will go into div[qi]
4103 for (qi = 0; qi < div_ndigits; qi++)
4105 /* Approximate the current dividend value */
4106 fdividend = (double) div[qi];
4107 for (i = 1; i < 4; i++)
4110 if (qi + i <= div_ndigits)
4111 fdividend += (double) div[qi + i];
4113 /* Compute the (approximate) quotient digit */
4114 fquotient = fdividend * fdivisorinverse;
4115 qdigit = (fquotient >= 0.0) ? ((int) fquotient) :
4116 (((int) fquotient) - 1); /* truncate towards -infinity */
4120 /* Do we need to normalize now? */
4121 maxdiv += Abs(qdigit);
4122 if (maxdiv > INT_MAX / (NBASE - 1))
4126 for (i = div_ndigits; i > qi; i--)
4128 newdig = div[i] + carry;
4131 carry = -((-newdig - 1) / NBASE) - 1;
4132 newdig -= carry * NBASE;
4134 else if (newdig >= NBASE)
4136 carry = newdig / NBASE;
4137 newdig -= carry * NBASE;
4143 newdig = div[qi] + carry;
4147 * All the div[] digits except possibly div[qi] are now in the
4150 maxdiv = Abs(newdig) / (NBASE - 1);
4151 maxdiv = Max(maxdiv, 1);
4154 * Recompute the quotient digit since new info may have
4155 * propagated into the top four dividend digits
4157 fdividend = (double) div[qi];
4158 for (i = 1; i < 4; i++)
4161 if (qi + i <= div_ndigits)
4162 fdividend += (double) div[qi + i];
4164 /* Compute the (approximate) quotient digit */
4165 fquotient = fdividend * fdivisorinverse;
4166 qdigit = (fquotient >= 0.0) ? ((int) fquotient) :
4167 (((int) fquotient) - 1); /* truncate towards -infinity */
4168 maxdiv += Abs(qdigit);
4171 /* Subtract off the appropriate multiple of the divisor */
4174 int istop = Min(var2ndigits, div_ndigits - qi + 1);
4176 for (i = 0; i < istop; i++)
4177 div[qi + i] -= qdigit * var2digits[i];
4182 * The dividend digit we are about to replace might still be nonzero.
4183 * Fold it into the next digit position. We don't need to worry about
4184 * overflow here since this should nearly cancel with the subtraction
4187 div[qi + 1] += div[qi] * NBASE;
4193 * Approximate and store the last quotient digit (div[div_ndigits])
4195 fdividend = (double) div[qi];
4196 for (i = 1; i < 4; i++)
4198 fquotient = fdividend * fdivisorinverse;
4199 qdigit = (fquotient >= 0.0) ? ((int) fquotient) :
4200 (((int) fquotient) - 1); /* truncate towards -infinity */
4204 * Now we do a final carry propagation pass to normalize the result, which
4205 * we combine with storing the result digits into the output. Note that
4206 * this is still done at full precision w/guard digits.
4208 alloc_var(result, div_ndigits + 1);
4209 res_digits = result->digits;
4211 for (i = div_ndigits; i >= 0; i--)
4213 newdig = div[i] + carry;
4216 carry = -((-newdig - 1) / NBASE) - 1;
4217 newdig -= carry * NBASE;
4219 else if (newdig >= NBASE)
4221 carry = newdig / NBASE;
4222 newdig -= carry * NBASE;
4226 res_digits[i] = newdig;
4233 * Finally, round the result to the requested precision.
4235 result->weight = res_weight;
4236 result->sign = res_sign;
4238 /* Round to target rscale (and set result->dscale) */
4240 round_var(result, rscale);
4242 trunc_var(result, rscale);
4244 /* Strip leading and trailing zeroes */
4250 * Default scale selection for division
4252 * Returns the appropriate result scale for the division result.
4255 select_div_scale(NumericVar *var1, NumericVar *var2)
4261 NumericDigit firstdigit1,
4266 * The result scale of a division isn't specified in any SQL standard. For
4267 * PostgreSQL we select a result scale that will give at least
4268 * NUMERIC_MIN_SIG_DIGITS significant digits, so that numeric gives a
4269 * result no less accurate than float8; but use a scale not less than
4270 * either input's display scale.
4273 /* Get the actual (normalized) weight and first digit of each input */
4275 weight1 = 0; /* values to use if var1 is zero */
4277 for (i = 0; i < var1->ndigits; i++)
4279 firstdigit1 = var1->digits[i];
4280 if (firstdigit1 != 0)
4282 weight1 = var1->weight - i;
4287 weight2 = 0; /* values to use if var2 is zero */
4289 for (i = 0; i < var2->ndigits; i++)
4291 firstdigit2 = var2->digits[i];
4292 if (firstdigit2 != 0)
4294 weight2 = var2->weight - i;
4300 * Estimate weight of quotient. If the two first digits are equal, we
4301 * can't be sure, but assume that var1 is less than var2.
4303 qweight = weight1 - weight2;
4304 if (firstdigit1 <= firstdigit2)
4307 /* Select result scale */
4308 rscale = NUMERIC_MIN_SIG_DIGITS - qweight * DEC_DIGITS;
4309 rscale = Max(rscale, var1->dscale);
4310 rscale = Max(rscale, var2->dscale);
4311 rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
4312 rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
4321 * Calculate the modulo of two numerics at variable level
4324 mod_var(NumericVar *var1, NumericVar *var2, NumericVar *result)
4332 * We do this using the equation
4333 * mod(x,y) = x - trunc(x/y)*y
4334 * We set rscale the same way numeric_div and numeric_mul do
4335 * to get the right answer from the equation. The final result,
4336 * however, need not be displayed to more precision than the inputs.
4339 rscale = select_div_scale(var1, var2);
4341 div_var(var1, var2, &tmp, rscale, false);
4345 mul_var(var2, &tmp, &tmp, var2->dscale + tmp.dscale);
4347 sub_var(var1, &tmp, result);
4349 round_var(result, Max(var1->dscale, var2->dscale));
4358 * Return the smallest integer greater than or equal to the argument
4362 ceil_var(NumericVar *var, NumericVar *result)
4367 set_var_from_var(var, &tmp);
4371 if (var->sign == NUMERIC_POS && cmp_var(var, &tmp) != 0)
4372 add_var(&tmp, &const_one, &tmp);
4374 set_var_from_var(&tmp, result);
4382 * Return the largest integer equal to or less than the argument
4386 floor_var(NumericVar *var, NumericVar *result)
4391 set_var_from_var(var, &tmp);
4395 if (var->sign == NUMERIC_NEG && cmp_var(var, &tmp) != 0)
4396 sub_var(&tmp, &const_one, &tmp);
4398 set_var_from_var(&tmp, result);
4406 * Compute the square root of x using Newton's algorithm
4409 sqrt_var(NumericVar *arg, NumericVar *result, int rscale)
4413 NumericVar last_val;
4417 local_rscale = rscale + 8;
4419 stat = cmp_var(arg, &const_zero);
4423 result->dscale = rscale;
4428 * SQL2003 defines sqrt() in terms of power, so we need to emit the right
4429 * SQLSTATE error code if the operand is negative.
4433 (errcode(ERRCODE_INVALID_ARGUMENT_FOR_POWER_FUNCTION),
4434 errmsg("cannot take square root of a negative number")));
4438 init_var(&last_val);
4440 /* Copy arg in case it is the same var as result */
4441 set_var_from_var(arg, &tmp_arg);
4444 * Initialize the result to the first guess
4446 alloc_var(result, 1);
4447 result->digits[0] = tmp_arg.digits[0] / 2;
4448 if (result->digits[0] == 0)
4449 result->digits[0] = 1;
4450 result->weight = tmp_arg.weight / 2;
4451 result->sign = NUMERIC_POS;
4453 set_var_from_var(result, &last_val);
4457 div_var(&tmp_arg, result, &tmp_val, local_rscale, true);
4459 add_var(result, &tmp_val, result);
4460 mul_var(result, &const_zero_point_five, result, local_rscale);
4462 if (cmp_var(&last_val, result) == 0)
4464 set_var_from_var(result, &last_val);
4467 free_var(&last_val);
4471 /* Round to requested precision */
4472 round_var(result, rscale);
4479 * Raise e to the power of x
4482 exp_var(NumericVar *arg, NumericVar *result, int rscale)
4490 * We separate the integral and fraction parts of x, then compute
4491 * e^x = e^xint * e^xfrac
4492 * where e = exp(1) and e^xfrac = exp(xfrac) are computed by
4493 * exp_var_internal; the limited range of inputs allows that routine
4494 * to do a good job with a simple Taylor series. Raising e^xint is
4495 * done by repeated multiplications in power_var_int.
4500 set_var_from_var(arg, &x);
4502 if (x.sign == NUMERIC_NEG)
4505 x.sign = NUMERIC_POS;
4508 /* Extract the integer part, remove it from x */
4510 while (x.weight >= 0)
4515 xintval += x.digits[0];
4520 /* Guard against overflow */
4521 if (xintval >= NUMERIC_MAX_RESULT_SCALE * 3)
4523 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
4524 errmsg("argument for function \"exp\" too big")));
4527 /* Select an appropriate scale for internal calculation */
4528 local_rscale = rscale + MUL_GUARD_DIGITS * 2;
4530 /* Compute e^xfrac */
4531 exp_var_internal(&x, result, local_rscale);
4533 /* If there's an integer part, multiply by e^xint */
4539 exp_var_internal(&const_one, &e, local_rscale);
4540 power_var_int(&e, xintval, &e, local_rscale);
4541 mul_var(&e, result, result, local_rscale);
4545 /* Compensate for input sign, and round to requested rscale */
4547 div_var(&const_one, result, result, rscale, true);
4549 round_var(result, rscale);
4556 * exp_var_internal() -
4558 * Raise e to the power of x, where 0 <= x <= 1
4560 * NB: the result should be good to at least rscale digits, but it has
4561 * *not* been rounded off; the caller must do that if wanted.
4564 exp_var_internal(NumericVar *arg, NumericVar *result, int rscale)
4580 set_var_from_var(arg, &x);
4582 Assert(x.sign == NUMERIC_POS);
4584 local_rscale = rscale + 8;
4586 /* Reduce input into range 0 <= x <= 0.01 */
4587 while (cmp_var(&x, &const_zero_point_01) > 0)
4591 mul_var(&x, &const_zero_point_five, &x, x.dscale + 1);
4595 * Use the Taylor series
4597 * exp(x) = 1 + x + x^2/2! + x^3/3! + ...
4599 * Given the limited range of x, this should converge reasonably quickly.
4600 * We run the series until the terms fall below the local_rscale limit.
4602 add_var(&const_one, &x, result);
4603 set_var_from_var(&x, &xpow);
4604 set_var_from_var(&const_one, &ifac);
4605 set_var_from_var(&const_one, &ni);
4609 add_var(&ni, &const_one, &ni);
4610 mul_var(&xpow, &x, &xpow, local_rscale);
4611 mul_var(&ifac, &ni, &ifac, 0);
4612 div_var(&xpow, &ifac, &elem, local_rscale, true);
4614 if (elem.ndigits == 0)
4617 add_var(result, &elem, result);
4620 /* Compensate for argument range reduction */
4622 mul_var(result, result, result, local_rscale);
4635 * Compute the natural log of x
4638 ln_var(NumericVar *arg, NumericVar *result, int rscale)
4648 cmp = cmp_var(arg, &const_zero);
4651 (errcode(ERRCODE_INVALID_ARGUMENT_FOR_LOG),
4652 errmsg("cannot take logarithm of zero")));
4655 (errcode(ERRCODE_INVALID_ARGUMENT_FOR_LOG),
4656 errmsg("cannot take logarithm of a negative number")));
4658 local_rscale = rscale + 8;
4666 set_var_from_var(arg, &x);
4667 set_var_from_var(&const_two, &fact);
4669 /* Reduce input into range 0.9 < x < 1.1 */
4670 while (cmp_var(&x, &const_zero_point_nine) <= 0)
4673 sqrt_var(&x, &x, local_rscale);
4674 mul_var(&fact, &const_two, &fact, 0);
4676 while (cmp_var(&x, &const_one_point_one) >= 0)
4679 sqrt_var(&x, &x, local_rscale);
4680 mul_var(&fact, &const_two, &fact, 0);
4684 * We use the Taylor series for 0.5 * ln((1+z)/(1-z)),
4686 * z + z^3/3 + z^5/5 + ...
4688 * where z = (x-1)/(x+1) is in the range (approximately) -0.053 .. 0.048
4689 * due to the above range-reduction of x.
4691 * The convergence of this is not as fast as one would like, but is
4692 * tolerable given that z is small.
4694 sub_var(&x, &const_one, result);
4695 add_var(&x, &const_one, &elem);
4696 div_var(result, &elem, result, local_rscale, true);
4697 set_var_from_var(result, &xx);
4698 mul_var(result, result, &x, local_rscale);
4700 set_var_from_var(&const_one, &ni);
4704 add_var(&ni, &const_two, &ni);
4705 mul_var(&xx, &x, &xx, local_rscale);
4706 div_var(&xx, &ni, &elem, local_rscale, true);
4708 if (elem.ndigits == 0)
4711 add_var(result, &elem, result);
4713 if (elem.weight < (result->weight - local_rscale * 2 / DEC_DIGITS))
4717 /* Compensate for argument range reduction, round to requested rscale */
4718 mul_var(result, &fact, result, rscale);
4731 * Compute the logarithm of num in a given base.
4733 * Note: this routine chooses dscale of the result.
4736 log_var(NumericVar *base, NumericVar *num, NumericVar *result)
4747 /* Set scale for ln() calculations --- compare numeric_ln() */
4749 /* Approx decimal digits before decimal point */
4750 dec_digits = (num->weight + 1) * DEC_DIGITS;
4753 rscale = NUMERIC_MIN_SIG_DIGITS - (int) log10(dec_digits - 1);
4754 else if (dec_digits < 1)
4755 rscale = NUMERIC_MIN_SIG_DIGITS - (int) log10(1 - dec_digits);
4757 rscale = NUMERIC_MIN_SIG_DIGITS;
4759 rscale = Max(rscale, base->dscale);
4760 rscale = Max(rscale, num->dscale);
4761 rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
4762 rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
4764 local_rscale = rscale + 8;
4766 /* Form natural logarithms */
4767 ln_var(base, &ln_base, local_rscale);
4768 ln_var(num, &ln_num, local_rscale);
4770 ln_base.dscale = rscale;
4771 ln_num.dscale = rscale;
4773 /* Select scale for division result */
4774 rscale = select_div_scale(&ln_num, &ln_base);
4776 div_var(&ln_num, &ln_base, result, rscale, true);
4786 * Raise base to the power of exp
4788 * Note: this routine chooses dscale of the result.
4791 power_var(NumericVar *base, NumericVar *exp, NumericVar *result)
4800 /* If exp can be represented as an integer, use power_var_int */
4801 if (exp->ndigits == 0 || exp->ndigits <= exp->weight + 1)
4803 /* exact integer, but does it fit in int? */
4807 /* must copy because numericvar_to_int8() scribbles on input */
4809 set_var_from_var(exp, &x);
4810 if (numericvar_to_int8(&x, &expval64))
4812 int expval = (int) expval64;
4814 /* Test for overflow by reverse-conversion. */
4815 if ((int64) expval == expval64)
4817 /* Okay, select rscale */
4818 rscale = NUMERIC_MIN_SIG_DIGITS;
4819 rscale = Max(rscale, base->dscale);
4820 rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
4821 rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
4823 power_var_int(base, expval, result, rscale);
4835 /* Set scale for ln() calculation --- need extra accuracy here */
4837 /* Approx decimal digits before decimal point */
4838 dec_digits = (base->weight + 1) * DEC_DIGITS;
4841 rscale = NUMERIC_MIN_SIG_DIGITS * 2 - (int) log10(dec_digits - 1);
4842 else if (dec_digits < 1)
4843 rscale = NUMERIC_MIN_SIG_DIGITS * 2 - (int) log10(1 - dec_digits);
4845 rscale = NUMERIC_MIN_SIG_DIGITS * 2;
4847 rscale = Max(rscale, base->dscale * 2);
4848 rscale = Max(rscale, exp->dscale * 2);
4849 rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE * 2);
4850 rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE * 2);
4852 local_rscale = rscale + 8;
4854 ln_var(base, &ln_base, local_rscale);
4856 mul_var(&ln_base, exp, &ln_num, local_rscale);
4858 /* Set scale for exp() -- compare numeric_exp() */
4860 /* convert input to float8, ignoring overflow */
4861 val = numericvar_to_double_no_overflow(&ln_num);
4864 * log10(result) = num * log10(e), so this is approximately the weight:
4866 val *= 0.434294481903252;
4868 /* limit to something that won't cause integer overflow */
4869 val = Max(val, -NUMERIC_MAX_RESULT_SCALE);
4870 val = Min(val, NUMERIC_MAX_RESULT_SCALE);
4872 rscale = NUMERIC_MIN_SIG_DIGITS - (int) val;
4873 rscale = Max(rscale, base->dscale);
4874 rscale = Max(rscale, exp->dscale);
4875 rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
4876 rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
4878 exp_var(&ln_num, result, rscale);
4887 * Raise base to the power of exp, where exp is an integer.
4890 power_var_int(NumericVar *base, int exp, NumericVar *result, int rscale)
4893 NumericVar base_prod;
4896 /* Detect some special cases, particularly 0^0. */
4901 if (base->ndigits == 0)
4903 (errcode(ERRCODE_FLOATING_POINT_EXCEPTION),
4904 errmsg("zero raised to zero is undefined")));
4905 set_var_from_var(&const_one, result);
4906 result->dscale = rscale; /* no need to round */
4909 set_var_from_var(base, result);
4910 round_var(result, rscale);
4913 div_var(&const_one, base, result, rscale, true);
4916 mul_var(base, base, result, rscale);
4923 * The general case repeatedly multiplies base according to the bit
4924 * pattern of exp. We do the multiplications with some extra precision.
4929 local_rscale = rscale + MUL_GUARD_DIGITS * 2;
4931 init_var(&base_prod);
4932 set_var_from_var(base, &base_prod);
4935 set_var_from_var(base, result);
4937 set_var_from_var(&const_one, result);
4939 while ((exp >>= 1) > 0)
4941 mul_var(&base_prod, &base_prod, &base_prod, local_rscale);
4943 mul_var(&base_prod, result, result, local_rscale);
4946 free_var(&base_prod);
4948 /* Compensate for input sign, and round to requested rscale */
4950 div_var(&const_one, result, result, rscale, true);
4952 round_var(result, rscale);
4956 /* ----------------------------------------------------------------------
4958 * Following are the lowest level functions that operate unsigned
4959 * on the variable level
4961 * ----------------------------------------------------------------------
4968 * Compare the absolute values of var1 and var2
4969 * Returns: -1 for ABS(var1) < ABS(var2)
4970 * 0 for ABS(var1) == ABS(var2)
4971 * 1 for ABS(var1) > ABS(var2)
4975 cmp_abs(NumericVar *var1, NumericVar *var2)
4977 return cmp_abs_common(var1->digits, var1->ndigits, var1->weight,
4978 var2->digits, var2->ndigits, var2->weight);
4982 * cmp_abs_common() -
4984 * Main routine of cmp_abs(). This function can be used by both
4985 * NumericVar and Numeric.
4989 cmp_abs_common(const NumericDigit *var1digits, int var1ndigits, int var1weight,
4990 const NumericDigit *var2digits, int var2ndigits, int var2weight)
4995 /* Check any digits before the first common digit */
4997 while (var1weight > var2weight && i1 < var1ndigits)
4999 if (var1digits[i1++] != 0)
5003 while (var2weight > var1weight && i2 < var2ndigits)
5005 if (var2digits[i2++] != 0)
5010 /* At this point, either w1 == w2 or we've run out of digits */
5012 if (var1weight == var2weight)
5014 while (i1 < var1ndigits && i2 < var2ndigits)
5016 int stat = var1digits[i1++] - var2digits[i2++];
5028 * At this point, we've run out of digits on one side or the other; so any
5029 * remaining nonzero digits imply that side is larger
5031 while (i1 < var1ndigits)
5033 if (var1digits[i1++] != 0)
5036 while (i2 < var2ndigits)
5038 if (var2digits[i2++] != 0)
5049 * Add the absolute values of two variables into result.
5050 * result might point to one of the operands without danger.
5053 add_abs(NumericVar *var1, NumericVar *var2, NumericVar *result)
5055 NumericDigit *res_buf;
5056 NumericDigit *res_digits;
5068 /* copy these values into local vars for speed in inner loop */
5069 int var1ndigits = var1->ndigits;
5070 int var2ndigits = var2->ndigits;
5071 NumericDigit *var1digits = var1->digits;
5072 NumericDigit *var2digits = var2->digits;
5074 res_weight = Max(var1->weight, var2->weight) + 1;
5076 res_dscale = Max(var1->dscale, var2->dscale);
5078 /* Note: here we are figuring rscale in base-NBASE digits */
5079 rscale1 = var1->ndigits - var1->weight - 1;
5080 rscale2 = var2->ndigits - var2->weight - 1;
5081 res_rscale = Max(rscale1, rscale2);
5083 res_ndigits = res_rscale + res_weight + 1;
5084 if (res_ndigits <= 0)
5087 res_buf = digitbuf_alloc(res_ndigits + 1);
5088 res_buf[0] = 0; /* spare digit for later rounding */
5089 res_digits = res_buf + 1;
5091 i1 = res_rscale + var1->weight + 1;
5092 i2 = res_rscale + var2->weight + 1;
5093 for (i = res_ndigits - 1; i >= 0; i--)
5097 if (i1 >= 0 && i1 < var1ndigits)
5098 carry += var1digits[i1];
5099 if (i2 >= 0 && i2 < var2ndigits)
5100 carry += var2digits[i2];
5104 res_digits[i] = carry - NBASE;
5109 res_digits[i] = carry;
5114 Assert(carry == 0); /* else we failed to allow for carry out */
5116 digitbuf_free(result->buf);
5117 result->ndigits = res_ndigits;
5118 result->buf = res_buf;
5119 result->digits = res_digits;
5120 result->weight = res_weight;
5121 result->dscale = res_dscale;
5123 /* Remove leading/trailing zeroes */
5131 * Subtract the absolute value of var2 from the absolute value of var1
5132 * and store in result. result might point to one of the operands
5135 * ABS(var1) MUST BE GREATER OR EQUAL ABS(var2) !!!
5138 sub_abs(NumericVar *var1, NumericVar *var2, NumericVar *result)
5140 NumericDigit *res_buf;
5141 NumericDigit *res_digits;
5153 /* copy these values into local vars for speed in inner loop */
5154 int var1ndigits = var1->ndigits;
5155 int var2ndigits = var2->ndigits;
5156 NumericDigit *var1digits = var1->digits;
5157 NumericDigit *var2digits = var2->digits;
5159 res_weight = var1->weight;
5161 res_dscale = Max(var1->dscale, var2->dscale);
5163 /* Note: here we are figuring rscale in base-NBASE digits */
5164 rscale1 = var1->ndigits - var1->weight - 1;
5165 rscale2 = var2->ndigits - var2->weight - 1;
5166 res_rscale = Max(rscale1, rscale2);
5168 res_ndigits = res_rscale + res_weight + 1;
5169 if (res_ndigits <= 0)
5172 res_buf = digitbuf_alloc(res_ndigits + 1);
5173 res_buf[0] = 0; /* spare digit for later rounding */
5174 res_digits = res_buf + 1;
5176 i1 = res_rscale + var1->weight + 1;
5177 i2 = res_rscale + var2->weight + 1;
5178 for (i = res_ndigits - 1; i >= 0; i--)
5182 if (i1 >= 0 && i1 < var1ndigits)
5183 borrow += var1digits[i1];
5184 if (i2 >= 0 && i2 < var2ndigits)
5185 borrow -= var2digits[i2];
5189 res_digits[i] = borrow + NBASE;
5194 res_digits[i] = borrow;
5199 Assert(borrow == 0); /* else caller gave us var1 < var2 */
5201 digitbuf_free(result->buf);
5202 result->ndigits = res_ndigits;
5203 result->buf = res_buf;
5204 result->digits = res_digits;
5205 result->weight = res_weight;
5206 result->dscale = res_dscale;
5208 /* Remove leading/trailing zeroes */
5215 * Round the value of a variable to no more than rscale decimal digits
5216 * after the decimal point. NOTE: we allow rscale < 0 here, implying
5217 * rounding before the decimal point.
5220 round_var(NumericVar *var, int rscale)
5222 NumericDigit *digits = var->digits;
5227 var->dscale = rscale;
5229 /* decimal digits wanted */
5230 di = (var->weight + 1) * DEC_DIGITS + rscale;
5233 * If di = 0, the value loses all digits, but could round up to 1 if its
5234 * first extra digit is >= 5. If di < 0 the result must be 0.
5240 var->sign = NUMERIC_POS;
5244 /* NBASE digits wanted */
5245 ndigits = (di + DEC_DIGITS - 1) / DEC_DIGITS;
5247 /* 0, or number of decimal digits to keep in last NBASE digit */
5250 if (ndigits < var->ndigits ||
5251 (ndigits == var->ndigits && di > 0))
5253 var->ndigits = ndigits;
5256 /* di must be zero */
5257 carry = (digits[ndigits] >= HALF_NBASE) ? 1 : 0;
5260 carry = (digits[ndigits] >= HALF_NBASE) ? 1 : 0;
5263 /* Must round within last NBASE digit */
5268 pow10 = round_powers[di];
5269 #elif DEC_DIGITS == 2
5272 #error unsupported NBASE
5274 extra = digits[--ndigits] % pow10;
5275 digits[ndigits] -= extra;
5277 if (extra >= pow10 / 2)
5279 pow10 += digits[ndigits];
5285 digits[ndigits] = pow10;
5290 /* Propagate carry if needed */
5293 carry += digits[--ndigits];
5296 digits[ndigits] = carry - NBASE;
5301 digits[ndigits] = carry;
5308 Assert(ndigits == -1); /* better not have added > 1 digit */
5309 Assert(var->digits > var->buf);
5321 * Truncate the value of a variable at rscale decimal digits after the
5322 * decimal point. NOTE: we allow rscale < 0 here, implying
5323 * truncation before the decimal point.
5326 trunc_var(NumericVar *var, int rscale)
5331 var->dscale = rscale;
5333 /* decimal digits wanted */
5334 di = (var->weight + 1) * DEC_DIGITS + rscale;
5337 * If di <= 0, the value loses all digits.
5343 var->sign = NUMERIC_POS;
5347 /* NBASE digits wanted */
5348 ndigits = (di + DEC_DIGITS - 1) / DEC_DIGITS;
5350 if (ndigits <= var->ndigits)
5352 var->ndigits = ndigits;
5355 /* no within-digit stuff to worry about */
5357 /* 0, or number of decimal digits to keep in last NBASE digit */
5362 /* Must truncate within last NBASE digit */
5363 NumericDigit *digits = var->digits;
5368 pow10 = round_powers[di];
5369 #elif DEC_DIGITS == 2
5372 #error unsupported NBASE
5374 extra = digits[--ndigits] % pow10;
5375 digits[ndigits] -= extra;
5385 * Strip any leading and trailing zeroes from a numeric variable
5388 strip_var(NumericVar *var)
5390 NumericDigit *digits = var->digits;
5391 int ndigits = var->ndigits;
5393 /* Strip leading zeroes */
5394 while (ndigits > 0 && *digits == 0)
5401 /* Strip trailing zeroes */
5402 while (ndigits > 0 && digits[ndigits - 1] == 0)
5405 /* If it's zero, normalize the sign and weight */
5408 var->sign = NUMERIC_POS;
5412 var->digits = digits;
5413 var->ndigits = ndigits;