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-2003, PostgreSQL Global Development Group
17 * $Header: /cvsroot/pgsql/src/backend/utils/adt/numeric.c,v 1.63 2003/07/27 04:53:07 tgl Exp $
19 *-------------------------------------------------------------------------
30 #include "catalog/pg_type.h"
31 #include "libpq/pqformat.h"
32 #include "utils/array.h"
33 #include "utils/builtins.h"
34 #include "utils/int8.h"
35 #include "utils/numeric.h"
38 * Uncomment the following to enable compilation of dump_numeric()
39 * and dump_var() and to get a dump of any result produced by make_result().
57 * Numeric values are represented in a base-NBASE floating point format.
58 * Each "digit" ranges from 0 to NBASE-1. The type NumericDigit is signed
59 * and wide enough to store a digit. We assume that NBASE*NBASE can fit in
60 * an int. Although the purely calculational routines could handle any even
61 * NBASE that's less than sqrt(INT_MAX), in practice we are only interested
62 * in NBASE a power of ten, so that I/O conversions and decimal rounding
63 * are easy. Also, it's actually more efficient if NBASE is rather less than
64 * sqrt(INT_MAX), so that there is "headroom" for mul_var and div_var to
65 * postpone processing carries.
72 #define DEC_DIGITS 1 /* decimal digits per NBASE digit */
73 #define MUL_GUARD_DIGITS 4 /* these are measured in NBASE digits */
74 #define DIV_GUARD_DIGITS 8
76 typedef signed char NumericDigit;
82 #define DEC_DIGITS 2 /* decimal digits per NBASE digit */
83 #define MUL_GUARD_DIGITS 3 /* these are measured in NBASE digits */
84 #define DIV_GUARD_DIGITS 6
86 typedef signed char NumericDigit;
91 #define HALF_NBASE 5000
92 #define DEC_DIGITS 4 /* decimal digits per NBASE digit */
93 #define MUL_GUARD_DIGITS 2 /* these are measured in NBASE digits */
94 #define DIV_GUARD_DIGITS 4
96 typedef int16 NumericDigit;
101 * The value represented by a NumericVar is determined by the sign, weight,
102 * ndigits, and digits[] array.
103 * Note: the first digit of a NumericVar's value is assumed to be multiplied
104 * by NBASE ** weight. Another way to say it is that there are weight+1
105 * digits before the decimal point. It is possible to have weight < 0.
107 * buf points at the physical start of the palloc'd digit buffer for the
108 * NumericVar. digits points at the first digit in actual use (the one
109 * with the specified weight). We normally leave an unused digit or two
110 * (preset to zeroes) between buf and digits, so that there is room to store
111 * a carry out of the top digit without special pushups. We just need to
112 * decrement digits (and increment weight) to make room for the carry digit.
113 * (There is no such extra space in a numeric value stored in the database,
114 * only in a NumericVar in memory.)
116 * If buf is NULL then the digit buffer isn't actually palloc'd and should
117 * not be freed --- see the constants below for an example.
119 * dscale, or display scale, is the nominal precision expressed as number
120 * of digits after the decimal point (it must always be >= 0 at present).
121 * dscale may be more than the number of physically stored fractional digits,
122 * implying that we have suppressed storage of significant trailing zeroes.
123 * It should never be less than the number of stored digits, since that would
124 * imply hiding digits that are present. NOTE that dscale is always expressed
125 * in *decimal* digits, and so it may correspond to a fractional number of
126 * base-NBASE digits --- divide by DEC_DIGITS to convert to NBASE digits.
128 * rscale, or result scale, is the target precision for a computation.
129 * Like dscale it is expressed as number of *decimal* digits after the decimal
130 * point, and is always >= 0 at present.
131 * Note that rscale is not stored in variables --- it's figured on-the-fly
132 * from the dscales of the inputs.
134 * NB: All the variable-level functions are written in a style that makes it
135 * possible to give one and the same variable as argument and destination.
136 * This is feasible because the digit buffer is separate from the variable.
139 typedef struct NumericVar
141 int ndigits; /* # of digits in digits[] - can be 0! */
142 int weight; /* weight of first digit */
143 int sign; /* NUMERIC_POS, NUMERIC_NEG, or
145 int dscale; /* display scale */
146 NumericDigit *buf; /* start of palloc'd space for digits[] */
147 NumericDigit *digits; /* base-NBASE digits */
152 * Some preinitialized constants
155 static NumericDigit const_zero_data[1] = {0};
156 static NumericVar const_zero =
157 {0, 0, NUMERIC_POS, 0, NULL, const_zero_data};
159 static NumericDigit const_one_data[1] = {1};
160 static NumericVar const_one =
161 {1, 0, NUMERIC_POS, 0, NULL, const_one_data};
163 static NumericDigit const_two_data[1] = {2};
164 static NumericVar const_two =
165 {1, 0, NUMERIC_POS, 0, NULL, const_two_data};
168 static NumericDigit const_zero_point_five_data[1] = {5000};
169 #elif DEC_DIGITS == 2
170 static NumericDigit const_zero_point_five_data[1] = {50};
171 #elif DEC_DIGITS == 1
172 static NumericDigit const_zero_point_five_data[1] = {5};
174 static NumericVar const_zero_point_five =
175 {1, -1, NUMERIC_POS, 1, NULL, const_zero_point_five_data};
178 static NumericDigit const_zero_point_nine_data[1] = {9000};
179 #elif DEC_DIGITS == 2
180 static NumericDigit const_zero_point_nine_data[1] = {90};
181 #elif DEC_DIGITS == 1
182 static NumericDigit const_zero_point_nine_data[1] = {9};
184 static NumericVar const_zero_point_nine =
185 {1, -1, NUMERIC_POS, 1, NULL, const_zero_point_nine_data};
188 static NumericDigit const_zero_point_01_data[1] = {100};
189 static NumericVar const_zero_point_01 =
190 {1, -1, NUMERIC_POS, 2, NULL, const_zero_point_01_data};
191 #elif DEC_DIGITS == 2
192 static NumericDigit const_zero_point_01_data[1] = {1};
193 static NumericVar const_zero_point_01 =
194 {1, -1, NUMERIC_POS, 2, NULL, const_zero_point_01_data};
195 #elif DEC_DIGITS == 1
196 static NumericDigit const_zero_point_01_data[1] = {1};
197 static NumericVar const_zero_point_01 =
198 {1, -2, NUMERIC_POS, 2, NULL, const_zero_point_01_data};
202 static NumericDigit const_one_point_one_data[2] = {1, 1000};
203 #elif DEC_DIGITS == 2
204 static NumericDigit const_one_point_one_data[2] = {1, 10};
205 #elif DEC_DIGITS == 1
206 static NumericDigit const_one_point_one_data[2] = {1, 1};
208 static NumericVar const_one_point_one =
209 {2, 0, NUMERIC_POS, 1, NULL, const_one_point_one_data};
211 static NumericVar const_nan =
212 {0, 0, NUMERIC_NAN, 0, NULL, NULL};
215 static const int round_powers[4] = { 0, 1000, 100, 10 };
225 static void dump_numeric(const char *str, Numeric num);
226 static void dump_var(const char *str, NumericVar *var);
229 #define dump_numeric(s,n)
230 #define dump_var(s,v)
233 #define digitbuf_alloc(ndigits) \
234 ((NumericDigit *) palloc((ndigits) * sizeof(NumericDigit)))
235 #define digitbuf_free(buf) \
241 #define init_var(v) MemSetAligned(v, 0, sizeof(NumericVar))
243 static void alloc_var(NumericVar *var, int ndigits);
244 static void free_var(NumericVar *var);
245 static void zero_var(NumericVar *var);
247 static void set_var_from_str(const char *str, NumericVar *dest);
248 static void set_var_from_num(Numeric value, NumericVar *dest);
249 static void set_var_from_var(NumericVar *value, NumericVar *dest);
250 static char *get_str_from_var(NumericVar *var, int dscale);
252 static Numeric make_result(NumericVar *var);
254 static void apply_typmod(NumericVar *var, int32 typmod);
256 static bool numericvar_to_int8(NumericVar *var, int64 *result);
257 static void int8_to_numericvar(int64 val, NumericVar *var);
258 static double numeric_to_double_no_overflow(Numeric num);
259 static double numericvar_to_double_no_overflow(NumericVar *var);
261 static int cmp_numerics(Numeric num1, Numeric num2);
262 static int cmp_var(NumericVar *var1, NumericVar *var2);
263 static void add_var(NumericVar *var1, NumericVar *var2, NumericVar *result);
264 static void sub_var(NumericVar *var1, NumericVar *var2, NumericVar *result);
265 static void mul_var(NumericVar *var1, NumericVar *var2, NumericVar *result,
267 static void div_var(NumericVar *var1, NumericVar *var2, NumericVar *result,
269 static int select_div_scale(NumericVar *var1, NumericVar *var2);
270 static void mod_var(NumericVar *var1, NumericVar *var2, NumericVar *result);
271 static void ceil_var(NumericVar *var, NumericVar *result);
272 static void floor_var(NumericVar *var, NumericVar *result);
274 static void sqrt_var(NumericVar *arg, NumericVar *result, int rscale);
275 static void exp_var(NumericVar *arg, NumericVar *result, int rscale);
276 static void exp_var_internal(NumericVar *arg, NumericVar *result, int rscale);
277 static void ln_var(NumericVar *arg, NumericVar *result, int rscale);
278 static void log_var(NumericVar *base, NumericVar *num, NumericVar *result);
279 static void power_var(NumericVar *base, NumericVar *exp, NumericVar *result);
280 static void power_var_int(NumericVar *base, int exp, NumericVar *result,
283 static int cmp_abs(NumericVar *var1, NumericVar *var2);
284 static void add_abs(NumericVar *var1, NumericVar *var2, NumericVar *result);
285 static void sub_abs(NumericVar *var1, NumericVar *var2, NumericVar *result);
286 static void round_var(NumericVar *var, int rscale);
287 static void trunc_var(NumericVar *var, int rscale);
288 static void strip_var(NumericVar *var);
291 /* ----------------------------------------------------------------------
293 * Input-, output- and rounding-functions
295 * ----------------------------------------------------------------------
302 * Input function for numeric data type
305 numeric_in(PG_FUNCTION_ARGS)
307 char *str = PG_GETARG_CSTRING(0);
310 Oid typelem = PG_GETARG_OID(1);
312 int32 typmod = PG_GETARG_INT32(2);
319 if (strcmp(str, "NaN") == 0)
320 PG_RETURN_NUMERIC(make_result(&const_nan));
323 * Use set_var_from_str() to parse the input string and return it in
324 * the packed DB storage format
327 set_var_from_str(str, &value);
329 apply_typmod(&value, typmod);
331 res = make_result(&value);
334 PG_RETURN_NUMERIC(res);
341 * Output function for numeric data type
344 numeric_out(PG_FUNCTION_ARGS)
346 Numeric num = PG_GETARG_NUMERIC(0);
353 if (NUMERIC_IS_NAN(num))
354 PG_RETURN_CSTRING(pstrdup("NaN"));
357 * Get the number in the variable format.
359 * Even if we didn't need to change format, we'd still need to copy the
360 * value to have a modifiable copy for rounding. set_var_from_num()
361 * also guarantees there is extra digit space in case we produce a
362 * carry out from rounding.
365 set_var_from_num(num, &x);
367 str = get_str_from_var(&x, x.dscale);
371 PG_RETURN_CSTRING(str);
375 * numeric_recv - converts external binary format to numeric
377 * External format is a sequence of int16's:
378 * ndigits, weight, sign, dscale, NumericDigits.
381 numeric_recv(PG_FUNCTION_ARGS)
383 StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
391 len = (uint16) pq_getmsgint(buf, sizeof(uint16));
392 if (len < 0 || len > NUMERIC_MAX_PRECISION + NUMERIC_MAX_RESULT_SCALE)
394 (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
395 errmsg("invalid length in external numeric")));
397 alloc_var(&value, len);
399 value.weight = (int16) pq_getmsgint(buf, sizeof(int16));
400 value.sign = (uint16) pq_getmsgint(buf, sizeof(uint16));
401 if (!(value.sign == NUMERIC_POS ||
402 value.sign == NUMERIC_NEG ||
403 value.sign == NUMERIC_NAN))
405 (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
406 errmsg("invalid sign in external numeric")));
408 value.dscale = (uint16) pq_getmsgint(buf, sizeof(uint16));
409 for (i = 0; i < len; i++)
411 NumericDigit d = pq_getmsgint(buf, sizeof(NumericDigit));
413 if (d < 0 || d >= NBASE)
415 (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
416 errmsg("invalid digit in external numeric")));
420 res = make_result(&value);
423 PG_RETURN_NUMERIC(res);
427 * numeric_send - converts numeric to binary format
430 numeric_send(PG_FUNCTION_ARGS)
432 Numeric num = PG_GETARG_NUMERIC(0);
438 set_var_from_num(num, &x);
440 pq_begintypsend(&buf);
442 pq_sendint(&buf, x.ndigits, sizeof(int16));
443 pq_sendint(&buf, x.weight, sizeof(int16));
444 pq_sendint(&buf, x.sign, sizeof(int16));
445 pq_sendint(&buf, x.dscale, sizeof(int16));
446 for (i = 0; i < x.ndigits; i++)
447 pq_sendint(&buf, x.digits[i], sizeof(NumericDigit));
451 PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
458 * This is a special function called by the Postgres database system
459 * before a value is stored in a tuple's attribute. The precision and
460 * scale of the attribute have to be applied on the value.
463 numeric(PG_FUNCTION_ARGS)
465 Numeric num = PG_GETARG_NUMERIC(0);
466 int32 typmod = PG_GETARG_INT32(1);
478 if (NUMERIC_IS_NAN(num))
479 PG_RETURN_NUMERIC(make_result(&const_nan));
482 * If the value isn't a valid type modifier, simply return a copy of
485 if (typmod < (int32) (VARHDRSZ))
487 new = (Numeric) palloc(num->varlen);
488 memcpy(new, num, num->varlen);
489 PG_RETURN_NUMERIC(new);
493 * Get the precision and scale out of the typmod value
495 tmp_typmod = typmod - VARHDRSZ;
496 precision = (tmp_typmod >> 16) & 0xffff;
497 scale = tmp_typmod & 0xffff;
498 maxdigits = precision - scale;
501 * If the number is certainly in bounds and due to the target scale no
502 * rounding could be necessary, just make a copy of the input and
503 * modify its scale fields. (Note we assume the existing dscale is
506 ddigits = (num->n_weight + 1) * DEC_DIGITS;
507 if (ddigits <= maxdigits && scale >= NUMERIC_DSCALE(num))
509 new = (Numeric) palloc(num->varlen);
510 memcpy(new, num, num->varlen);
511 new->n_sign_dscale = NUMERIC_SIGN(new) |
512 ((uint16) scale & NUMERIC_DSCALE_MASK);
513 PG_RETURN_NUMERIC(new);
517 * We really need to fiddle with things - unpack the number into a
518 * variable and let apply_typmod() do it.
522 set_var_from_num(num, &var);
523 apply_typmod(&var, typmod);
524 new = make_result(&var);
528 PG_RETURN_NUMERIC(new);
532 /* ----------------------------------------------------------------------
534 * Sign manipulation, rounding and the like
536 * ----------------------------------------------------------------------
540 numeric_abs(PG_FUNCTION_ARGS)
542 Numeric num = PG_GETARG_NUMERIC(0);
548 if (NUMERIC_IS_NAN(num))
549 PG_RETURN_NUMERIC(make_result(&const_nan));
552 * Do it the easy way directly on the packed format
554 res = (Numeric) palloc(num->varlen);
555 memcpy(res, num, num->varlen);
557 res->n_sign_dscale = NUMERIC_POS | NUMERIC_DSCALE(num);
559 PG_RETURN_NUMERIC(res);
564 numeric_uminus(PG_FUNCTION_ARGS)
566 Numeric num = PG_GETARG_NUMERIC(0);
572 if (NUMERIC_IS_NAN(num))
573 PG_RETURN_NUMERIC(make_result(&const_nan));
576 * Do it the easy way directly on the packed format
578 res = (Numeric) palloc(num->varlen);
579 memcpy(res, num, num->varlen);
582 * The packed format is known to be totally zero digit trimmed always.
583 * So we can identify a ZERO by the fact that there are no digits at
584 * all. Do nothing to a zero.
586 if (num->varlen != NUMERIC_HDRSZ)
588 /* Else, flip the sign */
589 if (NUMERIC_SIGN(num) == NUMERIC_POS)
590 res->n_sign_dscale = NUMERIC_NEG | NUMERIC_DSCALE(num);
592 res->n_sign_dscale = NUMERIC_POS | NUMERIC_DSCALE(num);
595 PG_RETURN_NUMERIC(res);
600 numeric_uplus(PG_FUNCTION_ARGS)
602 Numeric num = PG_GETARG_NUMERIC(0);
605 res = (Numeric) palloc(num->varlen);
606 memcpy(res, num, num->varlen);
608 PG_RETURN_NUMERIC(res);
614 * returns -1 if the argument is less than 0, 0 if the argument is equal
615 * to 0, and 1 if the argument is greater than zero.
618 numeric_sign(PG_FUNCTION_ARGS)
620 Numeric num = PG_GETARG_NUMERIC(0);
627 if (NUMERIC_IS_NAN(num))
628 PG_RETURN_NUMERIC(make_result(&const_nan));
633 * The packed format is known to be totally zero digit trimmed always.
634 * So we can identify a ZERO by the fact that there are no digits at
637 if (num->varlen == NUMERIC_HDRSZ)
638 set_var_from_var(&const_zero, &result);
642 * And if there are some, we return a copy of ONE with the sign of
645 set_var_from_var(&const_one, &result);
646 result.sign = NUMERIC_SIGN(num);
649 res = make_result(&result);
652 PG_RETURN_NUMERIC(res);
659 * Round a value to have 'scale' digits after the decimal point.
660 * We allow negative 'scale', implying rounding before the decimal
661 * point --- Oracle interprets rounding that way.
664 numeric_round(PG_FUNCTION_ARGS)
666 Numeric num = PG_GETARG_NUMERIC(0);
667 int32 scale = PG_GETARG_INT32(1);
674 if (NUMERIC_IS_NAN(num))
675 PG_RETURN_NUMERIC(make_result(&const_nan));
678 * Limit the scale value to avoid possible overflow in calculations
680 scale = Max(scale, -NUMERIC_MAX_RESULT_SCALE);
681 scale = Min(scale, NUMERIC_MAX_RESULT_SCALE);
684 * Unpack the argument and round it at the proper digit position
687 set_var_from_num(num, &arg);
689 round_var(&arg, scale);
691 /* We don't allow negative output dscale */
696 * Return the rounded result
698 res = make_result(&arg);
701 PG_RETURN_NUMERIC(res);
708 * Truncate a value to have 'scale' digits after the decimal point.
709 * We allow negative 'scale', implying a truncation before the decimal
710 * point --- Oracle interprets truncation that way.
713 numeric_trunc(PG_FUNCTION_ARGS)
715 Numeric num = PG_GETARG_NUMERIC(0);
716 int32 scale = PG_GETARG_INT32(1);
723 if (NUMERIC_IS_NAN(num))
724 PG_RETURN_NUMERIC(make_result(&const_nan));
727 * Limit the scale value to avoid possible overflow in calculations
729 scale = Max(scale, -NUMERIC_MAX_RESULT_SCALE);
730 scale = Min(scale, NUMERIC_MAX_RESULT_SCALE);
733 * Unpack the argument and truncate it at the proper digit position
736 set_var_from_num(num, &arg);
738 trunc_var(&arg, scale);
740 /* We don't allow negative output dscale */
745 * Return the truncated result
747 res = make_result(&arg);
750 PG_RETURN_NUMERIC(res);
757 * Return the smallest integer greater than or equal to the argument
760 numeric_ceil(PG_FUNCTION_ARGS)
762 Numeric num = PG_GETARG_NUMERIC(0);
766 if (NUMERIC_IS_NAN(num))
767 PG_RETURN_NUMERIC(make_result(&const_nan));
771 set_var_from_num(num, &result);
772 ceil_var(&result, &result);
774 res = make_result(&result);
777 PG_RETURN_NUMERIC(res);
784 * Return the largest integer equal to or less than the argument
787 numeric_floor(PG_FUNCTION_ARGS)
789 Numeric num = PG_GETARG_NUMERIC(0);
793 if (NUMERIC_IS_NAN(num))
794 PG_RETURN_NUMERIC(make_result(&const_nan));
798 set_var_from_num(num, &result);
799 floor_var(&result, &result);
801 res = make_result(&result);
804 PG_RETURN_NUMERIC(res);
808 /* ----------------------------------------------------------------------
810 * Comparison functions
812 * Note: btree indexes need these routines not to leak memory; therefore,
813 * be careful to free working copies of toasted datums. Most places don't
814 * need to be so careful.
815 * ----------------------------------------------------------------------
820 numeric_cmp(PG_FUNCTION_ARGS)
822 Numeric num1 = PG_GETARG_NUMERIC(0);
823 Numeric num2 = PG_GETARG_NUMERIC(1);
826 result = cmp_numerics(num1, num2);
828 PG_FREE_IF_COPY(num1, 0);
829 PG_FREE_IF_COPY(num2, 1);
831 PG_RETURN_INT32(result);
836 numeric_eq(PG_FUNCTION_ARGS)
838 Numeric num1 = PG_GETARG_NUMERIC(0);
839 Numeric num2 = PG_GETARG_NUMERIC(1);
842 result = cmp_numerics(num1, num2) == 0;
844 PG_FREE_IF_COPY(num1, 0);
845 PG_FREE_IF_COPY(num2, 1);
847 PG_RETURN_BOOL(result);
851 numeric_ne(PG_FUNCTION_ARGS)
853 Numeric num1 = PG_GETARG_NUMERIC(0);
854 Numeric num2 = PG_GETARG_NUMERIC(1);
857 result = cmp_numerics(num1, num2) != 0;
859 PG_FREE_IF_COPY(num1, 0);
860 PG_FREE_IF_COPY(num2, 1);
862 PG_RETURN_BOOL(result);
866 numeric_gt(PG_FUNCTION_ARGS)
868 Numeric num1 = PG_GETARG_NUMERIC(0);
869 Numeric num2 = PG_GETARG_NUMERIC(1);
872 result = cmp_numerics(num1, num2) > 0;
874 PG_FREE_IF_COPY(num1, 0);
875 PG_FREE_IF_COPY(num2, 1);
877 PG_RETURN_BOOL(result);
881 numeric_ge(PG_FUNCTION_ARGS)
883 Numeric num1 = PG_GETARG_NUMERIC(0);
884 Numeric num2 = PG_GETARG_NUMERIC(1);
887 result = cmp_numerics(num1, num2) >= 0;
889 PG_FREE_IF_COPY(num1, 0);
890 PG_FREE_IF_COPY(num2, 1);
892 PG_RETURN_BOOL(result);
896 numeric_lt(PG_FUNCTION_ARGS)
898 Numeric num1 = PG_GETARG_NUMERIC(0);
899 Numeric num2 = PG_GETARG_NUMERIC(1);
902 result = cmp_numerics(num1, num2) < 0;
904 PG_FREE_IF_COPY(num1, 0);
905 PG_FREE_IF_COPY(num2, 1);
907 PG_RETURN_BOOL(result);
911 numeric_le(PG_FUNCTION_ARGS)
913 Numeric num1 = PG_GETARG_NUMERIC(0);
914 Numeric num2 = PG_GETARG_NUMERIC(1);
917 result = cmp_numerics(num1, num2) <= 0;
919 PG_FREE_IF_COPY(num1, 0);
920 PG_FREE_IF_COPY(num2, 1);
922 PG_RETURN_BOOL(result);
926 cmp_numerics(Numeric num1, Numeric num2)
931 * We consider all NANs to be equal and larger than any non-NAN. This
932 * is somewhat arbitrary; the important thing is to have a consistent
935 if (NUMERIC_IS_NAN(num1))
937 if (NUMERIC_IS_NAN(num2))
938 result = 0; /* NAN = NAN */
940 result = 1; /* NAN > non-NAN */
942 else if (NUMERIC_IS_NAN(num2))
944 result = -1; /* non-NAN < NAN */
954 set_var_from_num(num1, &arg1);
955 set_var_from_num(num2, &arg2);
957 result = cmp_var(&arg1, &arg2);
967 /* ----------------------------------------------------------------------
969 * Basic arithmetic functions
971 * ----------------------------------------------------------------------
981 numeric_add(PG_FUNCTION_ARGS)
983 Numeric num1 = PG_GETARG_NUMERIC(0);
984 Numeric num2 = PG_GETARG_NUMERIC(1);
993 if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
994 PG_RETURN_NUMERIC(make_result(&const_nan));
997 * Unpack the values, let add_var() compute the result and return it.
1003 set_var_from_num(num1, &arg1);
1004 set_var_from_num(num2, &arg2);
1006 add_var(&arg1, &arg2, &result);
1008 res = make_result(&result);
1014 PG_RETURN_NUMERIC(res);
1021 * Subtract one numeric from another
1024 numeric_sub(PG_FUNCTION_ARGS)
1026 Numeric num1 = PG_GETARG_NUMERIC(0);
1027 Numeric num2 = PG_GETARG_NUMERIC(1);
1036 if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
1037 PG_RETURN_NUMERIC(make_result(&const_nan));
1040 * Unpack the values, let sub_var() compute the result and return it.
1046 set_var_from_num(num1, &arg1);
1047 set_var_from_num(num2, &arg2);
1049 sub_var(&arg1, &arg2, &result);
1051 res = make_result(&result);
1057 PG_RETURN_NUMERIC(res);
1064 * Calculate the product of two numerics
1067 numeric_mul(PG_FUNCTION_ARGS)
1069 Numeric num1 = PG_GETARG_NUMERIC(0);
1070 Numeric num2 = PG_GETARG_NUMERIC(1);
1079 if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
1080 PG_RETURN_NUMERIC(make_result(&const_nan));
1083 * Unpack the values, let mul_var() compute the result and return it.
1084 * Unlike add_var() and sub_var(), mul_var() will round its result.
1085 * In the case of numeric_mul(), which is invoked for the * operator on
1086 * numerics, we request exact representation for the product (rscale =
1087 * sum(dscale of arg1, dscale of arg2)).
1093 set_var_from_num(num1, &arg1);
1094 set_var_from_num(num2, &arg2);
1096 mul_var(&arg1, &arg2, &result, arg1.dscale + arg2.dscale);
1098 res = make_result(&result);
1104 PG_RETURN_NUMERIC(res);
1111 * Divide one numeric into another
1114 numeric_div(PG_FUNCTION_ARGS)
1116 Numeric num1 = PG_GETARG_NUMERIC(0);
1117 Numeric num2 = PG_GETARG_NUMERIC(1);
1127 if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
1128 PG_RETURN_NUMERIC(make_result(&const_nan));
1131 * Unpack the arguments
1137 set_var_from_num(num1, &arg1);
1138 set_var_from_num(num2, &arg2);
1141 * Select scale for division result
1143 rscale = select_div_scale(&arg1, &arg2);
1146 * Do the divide and return the result
1148 div_var(&arg1, &arg2, &result, rscale);
1150 res = make_result(&result);
1156 PG_RETURN_NUMERIC(res);
1163 * Calculate the modulo of two numerics
1166 numeric_mod(PG_FUNCTION_ARGS)
1168 Numeric num1 = PG_GETARG_NUMERIC(0);
1169 Numeric num2 = PG_GETARG_NUMERIC(1);
1175 if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
1176 PG_RETURN_NUMERIC(make_result(&const_nan));
1182 set_var_from_num(num1, &arg1);
1183 set_var_from_num(num2, &arg2);
1185 mod_var(&arg1, &arg2, &result);
1187 res = make_result(&result);
1193 PG_RETURN_NUMERIC(res);
1200 * Increment a number by one
1203 numeric_inc(PG_FUNCTION_ARGS)
1205 Numeric num = PG_GETARG_NUMERIC(0);
1212 if (NUMERIC_IS_NAN(num))
1213 PG_RETURN_NUMERIC(make_result(&const_nan));
1216 * Compute the result and return it
1220 set_var_from_num(num, &arg);
1222 add_var(&arg, &const_one, &arg);
1224 res = make_result(&arg);
1228 PG_RETURN_NUMERIC(res);
1233 * numeric_smaller() -
1235 * Return the smaller of two numbers
1238 numeric_smaller(PG_FUNCTION_ARGS)
1240 Numeric num1 = PG_GETARG_NUMERIC(0);
1241 Numeric num2 = PG_GETARG_NUMERIC(1);
1249 if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
1250 PG_RETURN_NUMERIC(make_result(&const_nan));
1253 * Unpack the values, and decide which is the smaller one
1258 set_var_from_num(num1, &arg1);
1259 set_var_from_num(num2, &arg2);
1261 if (cmp_var(&arg1, &arg2) <= 0)
1262 res = make_result(&arg1);
1264 res = make_result(&arg2);
1269 PG_RETURN_NUMERIC(res);
1274 * numeric_larger() -
1276 * Return the larger of two numbers
1279 numeric_larger(PG_FUNCTION_ARGS)
1281 Numeric num1 = PG_GETARG_NUMERIC(0);
1282 Numeric num2 = PG_GETARG_NUMERIC(1);
1290 if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
1291 PG_RETURN_NUMERIC(make_result(&const_nan));
1294 * Unpack the values, and decide which is the larger one
1299 set_var_from_num(num1, &arg1);
1300 set_var_from_num(num2, &arg2);
1302 if (cmp_var(&arg1, &arg2) >= 0)
1303 res = make_result(&arg1);
1305 res = make_result(&arg2);
1310 PG_RETURN_NUMERIC(res);
1314 /* ----------------------------------------------------------------------
1316 * Advanced math functions
1318 * ----------------------------------------------------------------------
1325 * Compute the square root of a numeric.
1328 numeric_sqrt(PG_FUNCTION_ARGS)
1330 Numeric num = PG_GETARG_NUMERIC(0);
1340 if (NUMERIC_IS_NAN(num))
1341 PG_RETURN_NUMERIC(make_result(&const_nan));
1344 * Unpack the argument and determine the result scale. We choose a
1345 * scale to give at least NUMERIC_MIN_SIG_DIGITS significant digits;
1346 * but in any case not less than the input's dscale.
1351 set_var_from_num(num, &arg);
1353 /* Assume the input was normalized, so arg.weight is accurate */
1354 sweight = (arg.weight + 1) * DEC_DIGITS / 2 - 1;
1356 rscale = NUMERIC_MIN_SIG_DIGITS - sweight;
1357 rscale = Max(rscale, arg.dscale);
1358 rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
1359 rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
1362 * Let sqrt_var() do the calculation and return the result.
1364 sqrt_var(&arg, &result, rscale);
1366 res = make_result(&result);
1371 PG_RETURN_NUMERIC(res);
1378 * Raise e to the power of x
1381 numeric_exp(PG_FUNCTION_ARGS)
1383 Numeric num = PG_GETARG_NUMERIC(0);
1393 if (NUMERIC_IS_NAN(num))
1394 PG_RETURN_NUMERIC(make_result(&const_nan));
1397 * Unpack the argument and determine the result scale. We choose a
1398 * scale to give at least NUMERIC_MIN_SIG_DIGITS significant digits;
1399 * but in any case not less than the input's dscale.
1404 set_var_from_num(num, &arg);
1406 /* convert input to float8, ignoring overflow */
1407 val = numericvar_to_double_no_overflow(&arg);
1410 * log10(result) = num * log10(e), so this is approximately the decimal
1411 * weight of the result:
1413 val *= 0.434294481903252;
1415 /* limit to something that won't cause integer overflow */
1416 val = Max(val, -NUMERIC_MAX_RESULT_SCALE);
1417 val = Min(val, NUMERIC_MAX_RESULT_SCALE);
1419 rscale = NUMERIC_MIN_SIG_DIGITS - (int) val;
1420 rscale = Max(rscale, arg.dscale);
1421 rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
1422 rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
1425 * Let exp_var() do the calculation and return the result.
1427 exp_var(&arg, &result, rscale);
1429 res = make_result(&result);
1434 PG_RETURN_NUMERIC(res);
1441 * Compute the natural logarithm of x
1444 numeric_ln(PG_FUNCTION_ARGS)
1446 Numeric num = PG_GETARG_NUMERIC(0);
1456 if (NUMERIC_IS_NAN(num))
1457 PG_RETURN_NUMERIC(make_result(&const_nan));
1462 set_var_from_num(num, &arg);
1464 /* Approx decimal digits before decimal point */
1465 dec_digits = (arg.weight + 1) * DEC_DIGITS;
1468 rscale = NUMERIC_MIN_SIG_DIGITS - (int) log10(dec_digits - 1);
1469 else if (dec_digits < 1)
1470 rscale = NUMERIC_MIN_SIG_DIGITS - (int) log10(1 - dec_digits);
1472 rscale = NUMERIC_MIN_SIG_DIGITS;
1474 rscale = Max(rscale, arg.dscale);
1475 rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
1476 rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
1478 ln_var(&arg, &result, rscale);
1480 res = make_result(&result);
1485 PG_RETURN_NUMERIC(res);
1492 * Compute the logarithm of x in a given base
1495 numeric_log(PG_FUNCTION_ARGS)
1497 Numeric num1 = PG_GETARG_NUMERIC(0);
1498 Numeric num2 = PG_GETARG_NUMERIC(1);
1507 if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
1508 PG_RETURN_NUMERIC(make_result(&const_nan));
1517 set_var_from_num(num1, &arg1);
1518 set_var_from_num(num2, &arg2);
1521 * Call log_var() to compute and return the result; note it handles
1522 * scale selection itself.
1524 log_var(&arg1, &arg2, &result);
1526 res = make_result(&result);
1532 PG_RETURN_NUMERIC(res);
1539 * Raise b to the power of x
1542 numeric_power(PG_FUNCTION_ARGS)
1544 Numeric num1 = PG_GETARG_NUMERIC(0);
1545 Numeric num2 = PG_GETARG_NUMERIC(1);
1554 if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
1555 PG_RETURN_NUMERIC(make_result(&const_nan));
1564 set_var_from_num(num1, &arg1);
1565 set_var_from_num(num2, &arg2);
1568 * Call power_var() to compute and return the result; note it handles
1569 * scale selection itself.
1571 power_var(&arg1, &arg2, &result);
1573 res = make_result(&result);
1579 PG_RETURN_NUMERIC(res);
1583 /* ----------------------------------------------------------------------
1585 * Type conversion functions
1587 * ----------------------------------------------------------------------
1592 int4_numeric(PG_FUNCTION_ARGS)
1594 int32 val = PG_GETARG_INT32(0);
1600 int8_to_numericvar((int64) val, &result);
1602 res = make_result(&result);
1606 PG_RETURN_NUMERIC(res);
1611 numeric_int4(PG_FUNCTION_ARGS)
1613 Numeric num = PG_GETARG_NUMERIC(0);
1618 /* XXX would it be better to return NULL? */
1619 if (NUMERIC_IS_NAN(num))
1621 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1622 errmsg("cannot convert NaN to integer")));
1624 /* Convert to variable format and thence to int8 */
1626 set_var_from_num(num, &x);
1628 if (!numericvar_to_int8(&x, &val))
1630 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1631 errmsg("integer out of range")));
1635 /* Down-convert to int4 */
1636 result = (int32) val;
1638 /* Test for overflow by reverse-conversion. */
1639 if ((int64) result != val)
1641 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1642 errmsg("integer out of range")));
1644 PG_RETURN_INT32(result);
1649 int8_numeric(PG_FUNCTION_ARGS)
1651 int64 val = PG_GETARG_INT64(0);
1657 int8_to_numericvar(val, &result);
1659 res = make_result(&result);
1663 PG_RETURN_NUMERIC(res);
1668 numeric_int8(PG_FUNCTION_ARGS)
1670 Numeric num = PG_GETARG_NUMERIC(0);
1674 /* XXX would it be better to return NULL? */
1675 if (NUMERIC_IS_NAN(num))
1677 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1678 errmsg("cannot convert NaN to integer")));
1680 /* Convert to variable format and thence to int8 */
1682 set_var_from_num(num, &x);
1684 if (!numericvar_to_int8(&x, &result))
1686 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1687 errmsg("integer out of range")));
1691 PG_RETURN_INT64(result);
1696 int2_numeric(PG_FUNCTION_ARGS)
1698 int16 val = PG_GETARG_INT16(0);
1704 int8_to_numericvar((int64) val, &result);
1706 res = make_result(&result);
1710 PG_RETURN_NUMERIC(res);
1715 numeric_int2(PG_FUNCTION_ARGS)
1717 Numeric num = PG_GETARG_NUMERIC(0);
1722 /* XXX would it be better to return NULL? */
1723 if (NUMERIC_IS_NAN(num))
1725 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1726 errmsg("cannot convert NaN to integer")));
1728 /* Convert to variable format and thence to int8 */
1730 set_var_from_num(num, &x);
1732 if (!numericvar_to_int8(&x, &val))
1734 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1735 errmsg("integer out of range")));
1739 /* Down-convert to int2 */
1740 result = (int16) val;
1742 /* Test for overflow by reverse-conversion. */
1743 if ((int64) result != val)
1745 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1746 errmsg("integer out of range")));
1748 PG_RETURN_INT16(result);
1753 float8_numeric(PG_FUNCTION_ARGS)
1755 float8 val = PG_GETARG_FLOAT8(0);
1758 char buf[DBL_DIG + 100];
1761 PG_RETURN_NUMERIC(make_result(&const_nan));
1763 sprintf(buf, "%.*g", DBL_DIG, val);
1767 set_var_from_str(buf, &result);
1768 res = make_result(&result);
1772 PG_RETURN_NUMERIC(res);
1777 numeric_float8(PG_FUNCTION_ARGS)
1779 Numeric num = PG_GETARG_NUMERIC(0);
1783 if (NUMERIC_IS_NAN(num))
1784 PG_RETURN_FLOAT8(NAN);
1786 tmp = DatumGetCString(DirectFunctionCall1(numeric_out,
1787 NumericGetDatum(num)));
1789 result = DirectFunctionCall1(float8in, CStringGetDatum(tmp));
1793 PG_RETURN_DATUM(result);
1797 /* Convert numeric to float8; if out of range, return +/- HUGE_VAL */
1799 numeric_float8_no_overflow(PG_FUNCTION_ARGS)
1801 Numeric num = PG_GETARG_NUMERIC(0);
1804 if (NUMERIC_IS_NAN(num))
1805 PG_RETURN_FLOAT8(NAN);
1807 val = numeric_to_double_no_overflow(num);
1809 PG_RETURN_FLOAT8(val);
1813 float4_numeric(PG_FUNCTION_ARGS)
1815 float4 val = PG_GETARG_FLOAT4(0);
1818 char buf[FLT_DIG + 100];
1821 PG_RETURN_NUMERIC(make_result(&const_nan));
1823 sprintf(buf, "%.*g", FLT_DIG, val);
1827 set_var_from_str(buf, &result);
1828 res = make_result(&result);
1832 PG_RETURN_NUMERIC(res);
1837 numeric_float4(PG_FUNCTION_ARGS)
1839 Numeric num = PG_GETARG_NUMERIC(0);
1843 if (NUMERIC_IS_NAN(num))
1844 PG_RETURN_FLOAT4((float4) NAN);
1846 tmp = DatumGetCString(DirectFunctionCall1(numeric_out,
1847 NumericGetDatum(num)));
1849 result = DirectFunctionCall1(float4in, CStringGetDatum(tmp));
1853 PG_RETURN_DATUM(result);
1858 text_numeric(PG_FUNCTION_ARGS)
1860 text *str = PG_GETARG_TEXT_P(0);
1865 len = (VARSIZE(str) - VARHDRSZ);
1866 s = palloc(len + 1);
1867 memcpy(s, VARDATA(str), len);
1870 result = DirectFunctionCall3(numeric_in, CStringGetDatum(s),
1871 ObjectIdGetDatum(0), Int32GetDatum(-1));
1879 numeric_text(PG_FUNCTION_ARGS)
1881 /* val is numeric, but easier to leave it as Datum */
1882 Datum val = PG_GETARG_DATUM(0);
1887 s = DatumGetCString(DirectFunctionCall1(numeric_out, val));
1890 result = (text *) palloc(VARHDRSZ + len);
1892 VARATT_SIZEP(result) = len + VARHDRSZ;
1893 memcpy(VARDATA(result), s, len);
1897 PG_RETURN_TEXT_P(result);
1901 /* ----------------------------------------------------------------------
1903 * Aggregate functions
1905 * The transition datatype for all these aggregates is a 3-element array
1906 * of Numeric, holding the values N, sum(X), sum(X*X) in that order.
1908 * We represent N as a numeric mainly to avoid having to build a special
1909 * datatype; it's unlikely it'd overflow an int4, but ...
1911 * ----------------------------------------------------------------------
1915 do_numeric_accum(ArrayType *transarray, Numeric newval)
1924 /* We assume the input is array of numeric */
1925 deconstruct_array(transarray,
1926 NUMERICOID, -1, false, 'i',
1927 &transdatums, &ndatums);
1929 elog(ERROR, "expected 3-element numeric array");
1931 sumX = transdatums[1];
1932 sumX2 = transdatums[2];
1934 N = DirectFunctionCall1(numeric_inc, N);
1935 sumX = DirectFunctionCall2(numeric_add, sumX,
1936 NumericGetDatum(newval));
1937 sumX2 = DirectFunctionCall2(numeric_add, sumX2,
1938 DirectFunctionCall2(numeric_mul,
1939 NumericGetDatum(newval),
1940 NumericGetDatum(newval)));
1943 transdatums[1] = sumX;
1944 transdatums[2] = sumX2;
1946 result = construct_array(transdatums, 3,
1947 NUMERICOID, -1, false, 'i');
1953 numeric_accum(PG_FUNCTION_ARGS)
1955 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
1956 Numeric newval = PG_GETARG_NUMERIC(1);
1958 PG_RETURN_ARRAYTYPE_P(do_numeric_accum(transarray, newval));
1962 * Integer data types all use Numeric accumulators to share code and
1963 * avoid risk of overflow. For int2 and int4 inputs, Numeric accumulation
1964 * is overkill for the N and sum(X) values, but definitely not overkill
1965 * for the sum(X*X) value. Hence, we use int2_accum and int4_accum only
1966 * for stddev/variance --- there are faster special-purpose accumulator
1967 * routines for SUM and AVG of these datatypes.
1971 int2_accum(PG_FUNCTION_ARGS)
1973 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
1974 Datum newval2 = PG_GETARG_DATUM(1);
1977 newval = DatumGetNumeric(DirectFunctionCall1(int2_numeric, newval2));
1979 PG_RETURN_ARRAYTYPE_P(do_numeric_accum(transarray, newval));
1983 int4_accum(PG_FUNCTION_ARGS)
1985 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
1986 Datum newval4 = PG_GETARG_DATUM(1);
1989 newval = DatumGetNumeric(DirectFunctionCall1(int4_numeric, newval4));
1991 PG_RETURN_ARRAYTYPE_P(do_numeric_accum(transarray, newval));
1995 int8_accum(PG_FUNCTION_ARGS)
1997 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
1998 Datum newval8 = PG_GETARG_DATUM(1);
2001 newval = DatumGetNumeric(DirectFunctionCall1(int8_numeric, newval8));
2003 PG_RETURN_ARRAYTYPE_P(do_numeric_accum(transarray, newval));
2007 numeric_avg(PG_FUNCTION_ARGS)
2009 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
2015 /* We assume the input is array of numeric */
2016 deconstruct_array(transarray,
2017 NUMERICOID, -1, false, 'i',
2018 &transdatums, &ndatums);
2020 elog(ERROR, "expected 3-element numeric array");
2021 N = DatumGetNumeric(transdatums[0]);
2022 sumX = DatumGetNumeric(transdatums[1]);
2025 /* SQL92 defines AVG of no values to be NULL */
2026 /* N is zero iff no digits (cf. numeric_uminus) */
2027 if (N->varlen == NUMERIC_HDRSZ)
2030 PG_RETURN_DATUM(DirectFunctionCall2(numeric_div,
2031 NumericGetDatum(sumX),
2032 NumericGetDatum(N)));
2036 numeric_variance(PG_FUNCTION_ARGS)
2038 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
2051 /* We assume the input is array of numeric */
2052 deconstruct_array(transarray,
2053 NUMERICOID, -1, false, 'i',
2054 &transdatums, &ndatums);
2056 elog(ERROR, "expected 3-element numeric array");
2057 N = DatumGetNumeric(transdatums[0]);
2058 sumX = DatumGetNumeric(transdatums[1]);
2059 sumX2 = DatumGetNumeric(transdatums[2]);
2061 if (NUMERIC_IS_NAN(N) || NUMERIC_IS_NAN(sumX) || NUMERIC_IS_NAN(sumX2))
2062 PG_RETURN_NUMERIC(make_result(&const_nan));
2064 /* Sample variance is undefined when N is 0 or 1, so return NULL */
2066 set_var_from_num(N, &vN);
2068 if (cmp_var(&vN, &const_one) <= 0)
2074 init_var(&vNminus1);
2075 sub_var(&vN, &const_one, &vNminus1);
2078 set_var_from_num(sumX, &vsumX);
2080 set_var_from_num(sumX2, &vsumX2);
2082 /* compute rscale for mul_var calls */
2083 rscale = vsumX.dscale * 2;
2085 mul_var(&vsumX, &vsumX, &vsumX, rscale); /* vsumX = sumX * sumX */
2086 mul_var(&vN, &vsumX2, &vsumX2, rscale); /* vsumX2 = N * sumX2 */
2087 sub_var(&vsumX2, &vsumX, &vsumX2); /* N * sumX2 - sumX * sumX */
2089 if (cmp_var(&vsumX2, &const_zero) <= 0)
2091 /* Watch out for roundoff error producing a negative numerator */
2092 res = make_result(&const_zero);
2096 mul_var(&vN, &vNminus1, &vNminus1, 0); /* N * (N - 1) */
2097 rscale = select_div_scale(&vsumX2, &vNminus1);
2098 div_var(&vsumX2, &vNminus1, &vsumX, rscale); /* variance */
2100 res = make_result(&vsumX);
2104 free_var(&vNminus1);
2108 PG_RETURN_NUMERIC(res);
2112 numeric_stddev(PG_FUNCTION_ARGS)
2114 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
2127 /* We assume the input is array of numeric */
2128 deconstruct_array(transarray,
2129 NUMERICOID, -1, false, 'i',
2130 &transdatums, &ndatums);
2132 elog(ERROR, "expected 3-element numeric array");
2133 N = DatumGetNumeric(transdatums[0]);
2134 sumX = DatumGetNumeric(transdatums[1]);
2135 sumX2 = DatumGetNumeric(transdatums[2]);
2137 if (NUMERIC_IS_NAN(N) || NUMERIC_IS_NAN(sumX) || NUMERIC_IS_NAN(sumX2))
2138 PG_RETURN_NUMERIC(make_result(&const_nan));
2140 /* Sample stddev is undefined when N is 0 or 1, so return NULL */
2142 set_var_from_num(N, &vN);
2144 if (cmp_var(&vN, &const_one) <= 0)
2150 init_var(&vNminus1);
2151 sub_var(&vN, &const_one, &vNminus1);
2154 set_var_from_num(sumX, &vsumX);
2156 set_var_from_num(sumX2, &vsumX2);
2158 /* compute rscale for mul_var calls */
2159 rscale = vsumX.dscale * 2;
2161 mul_var(&vsumX, &vsumX, &vsumX, rscale); /* vsumX = sumX * sumX */
2162 mul_var(&vN, &vsumX2, &vsumX2, rscale); /* vsumX2 = N * sumX2 */
2163 sub_var(&vsumX2, &vsumX, &vsumX2); /* N * sumX2 - sumX * sumX */
2165 if (cmp_var(&vsumX2, &const_zero) <= 0)
2167 /* Watch out for roundoff error producing a negative numerator */
2168 res = make_result(&const_zero);
2172 mul_var(&vN, &vNminus1, &vNminus1, 0); /* N * (N - 1) */
2173 rscale = select_div_scale(&vsumX2, &vNminus1);
2174 div_var(&vsumX2, &vNminus1, &vsumX, rscale); /* variance */
2175 sqrt_var(&vsumX, &vsumX, rscale); /* stddev */
2177 res = make_result(&vsumX);
2181 free_var(&vNminus1);
2185 PG_RETURN_NUMERIC(res);
2190 * SUM transition functions for integer datatypes.
2192 * To avoid overflow, we use accumulators wider than the input datatype.
2193 * A Numeric accumulator is needed for int8 input; for int4 and int2
2194 * inputs, we use int8 accumulators which should be sufficient for practical
2195 * purposes. (The latter two therefore don't really belong in this file,
2196 * but we keep them here anyway.)
2198 * Because SQL92 defines the SUM() of no values to be NULL, not zero,
2199 * the initial condition of the transition data value needs to be NULL. This
2200 * means we can't rely on ExecAgg to automatically insert the first non-null
2201 * data value into the transition data: it doesn't know how to do the type
2202 * conversion. The upshot is that these routines have to be marked non-strict
2203 * and handle substitution of the first non-null input themselves.
2207 int2_sum(PG_FUNCTION_ARGS)
2212 if (PG_ARGISNULL(0))
2214 /* No non-null input seen so far... */
2215 if (PG_ARGISNULL(1))
2216 PG_RETURN_NULL(); /* still no non-null */
2217 /* This is the first non-null input. */
2218 newval = (int64) PG_GETARG_INT16(1);
2219 PG_RETURN_INT64(newval);
2222 oldsum = PG_GETARG_INT64(0);
2224 /* Leave sum unchanged if new input is null. */
2225 if (PG_ARGISNULL(1))
2226 PG_RETURN_INT64(oldsum);
2228 /* OK to do the addition. */
2229 newval = oldsum + (int64) PG_GETARG_INT16(1);
2231 PG_RETURN_INT64(newval);
2235 int4_sum(PG_FUNCTION_ARGS)
2240 if (PG_ARGISNULL(0))
2242 /* No non-null input seen so far... */
2243 if (PG_ARGISNULL(1))
2244 PG_RETURN_NULL(); /* still no non-null */
2245 /* This is the first non-null input. */
2246 newval = (int64) PG_GETARG_INT32(1);
2247 PG_RETURN_INT64(newval);
2250 oldsum = PG_GETARG_INT64(0);
2252 /* Leave sum unchanged if new input is null. */
2253 if (PG_ARGISNULL(1))
2254 PG_RETURN_INT64(oldsum);
2256 /* OK to do the addition. */
2257 newval = oldsum + (int64) PG_GETARG_INT32(1);
2259 PG_RETURN_INT64(newval);
2263 int8_sum(PG_FUNCTION_ARGS)
2268 if (PG_ARGISNULL(0))
2270 /* No non-null input seen so far... */
2271 if (PG_ARGISNULL(1))
2272 PG_RETURN_NULL(); /* still no non-null */
2273 /* This is the first non-null input. */
2274 newval = DirectFunctionCall1(int8_numeric, PG_GETARG_DATUM(1));
2275 PG_RETURN_DATUM(newval);
2278 oldsum = PG_GETARG_NUMERIC(0);
2280 /* Leave sum unchanged if new input is null. */
2281 if (PG_ARGISNULL(1))
2282 PG_RETURN_NUMERIC(oldsum);
2284 /* OK to do the addition. */
2285 newval = DirectFunctionCall1(int8_numeric, PG_GETARG_DATUM(1));
2287 PG_RETURN_DATUM(DirectFunctionCall2(numeric_add,
2288 NumericGetDatum(oldsum), newval));
2293 * Routines for avg(int2) and avg(int4). The transition datatype
2294 * is a two-element int8 array, holding count and sum.
2297 typedef struct Int8TransTypeData
2299 #ifndef INT64_IS_BUSTED
2303 /* "int64" isn't really 64 bits, so fake up properly-aligned fields */
2309 } Int8TransTypeData;
2312 int2_avg_accum(PG_FUNCTION_ARGS)
2314 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P_COPY(0);
2315 int16 newval = PG_GETARG_INT16(1);
2316 Int8TransTypeData *transdata;
2319 * We copied the input array, so it's okay to scribble on it directly.
2321 if (ARR_SIZE(transarray) != ARR_OVERHEAD(1) + sizeof(Int8TransTypeData))
2322 elog(ERROR, "expected 2-element int8 array");
2323 transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
2326 transdata->sum += newval;
2328 PG_RETURN_ARRAYTYPE_P(transarray);
2332 int4_avg_accum(PG_FUNCTION_ARGS)
2334 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P_COPY(0);
2335 int32 newval = PG_GETARG_INT32(1);
2336 Int8TransTypeData *transdata;
2339 * We copied the input array, so it's okay to scribble on it directly.
2341 if (ARR_SIZE(transarray) != ARR_OVERHEAD(1) + sizeof(Int8TransTypeData))
2342 elog(ERROR, "expected 2-element int8 array");
2343 transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
2346 transdata->sum += newval;
2348 PG_RETURN_ARRAYTYPE_P(transarray);
2352 int8_avg(PG_FUNCTION_ARGS)
2354 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
2355 Int8TransTypeData *transdata;
2359 if (ARR_SIZE(transarray) != ARR_OVERHEAD(1) + sizeof(Int8TransTypeData))
2360 elog(ERROR, "expected 2-element int8 array");
2361 transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
2363 /* SQL92 defines AVG of no values to be NULL */
2364 if (transdata->count == 0)
2367 countd = DirectFunctionCall1(int8_numeric,
2368 Int64GetDatumFast(transdata->count));
2369 sumd = DirectFunctionCall1(int8_numeric,
2370 Int64GetDatumFast(transdata->sum));
2372 PG_RETURN_DATUM(DirectFunctionCall2(numeric_div, sumd, countd));
2376 /* ----------------------------------------------------------------------
2380 * ----------------------------------------------------------------------
2383 #ifdef NUMERIC_DEBUG
2386 * dump_numeric() - Dump a value in the db storage format for debugging
2389 dump_numeric(const char *str, Numeric num)
2391 NumericDigit *digits = (NumericDigit *) num->n_data;
2395 ndigits = (num->varlen - NUMERIC_HDRSZ) / sizeof(NumericDigit);
2397 printf("%s: NUMERIC w=%d d=%d ", str, num->n_weight, NUMERIC_DSCALE(num));
2398 switch (NUMERIC_SIGN(num))
2410 printf("SIGN=0x%x", NUMERIC_SIGN(num));
2414 for (i = 0; i < ndigits; i++)
2415 printf(" %0*d", DEC_DIGITS, digits[i]);
2421 * dump_var() - Dump a value in the variable format for debugging
2424 dump_var(const char *str, NumericVar *var)
2428 printf("%s: VAR w=%d d=%d ", str, var->weight, var->dscale);
2441 printf("SIGN=0x%x", var->sign);
2445 for (i = 0; i < var->ndigits; i++)
2446 printf(" %0*d", DEC_DIGITS, var->digits[i]);
2451 #endif /* NUMERIC_DEBUG */
2454 /* ----------------------------------------------------------------------
2456 * Local functions follow
2458 * In general, these do not support NaNs --- callers must eliminate
2459 * the possibility of NaN first. (make_result() is an exception.)
2461 * ----------------------------------------------------------------------
2468 * Allocate a digit buffer of ndigits digits (plus a spare digit for rounding)
2471 alloc_var(NumericVar *var, int ndigits)
2473 digitbuf_free(var->buf);
2474 var->buf = digitbuf_alloc(ndigits + 1);
2475 var->buf[0] = 0; /* spare digit for rounding */
2476 var->digits = var->buf + 1;
2477 var->ndigits = ndigits;
2484 * Return the digit buffer of a variable to the free pool
2487 free_var(NumericVar *var)
2489 digitbuf_free(var->buf);
2492 var->sign = NUMERIC_NAN;
2499 * Set a variable to ZERO.
2500 * Note: its dscale is not touched.
2503 zero_var(NumericVar *var)
2505 digitbuf_free(var->buf);
2509 var->weight = 0; /* by convention; doesn't really matter */
2510 var->sign = NUMERIC_POS; /* anything but NAN... */
2515 * set_var_from_str()
2517 * Parse a string and put the number into a variable
2520 set_var_from_str(const char *str, NumericVar *dest)
2522 const char *cp = str;
2523 bool have_dp = FALSE;
2525 unsigned char *decdigits;
2526 int sign = NUMERIC_POS;
2533 NumericDigit *digits;
2536 * We first parse the string to extract decimal digits and determine the
2537 * correct decimal weight. Then convert to NBASE representation.
2540 /* skip leading spaces */
2543 if (!isspace((unsigned char) *cp))
2567 if (!isdigit((unsigned char) *cp))
2569 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
2570 errmsg("invalid input syntax for numeric: \"%s\"", str)));
2572 decdigits = (unsigned char *) palloc(strlen(cp) + DEC_DIGITS*2);
2574 /* leading padding for digit alignment later */
2575 memset(decdigits, 0, DEC_DIGITS);
2580 if (isdigit((unsigned char) *cp))
2582 decdigits[i++] = *cp++ - '0';
2588 else if (*cp == '.')
2592 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
2593 errmsg("invalid input syntax for numeric: \"%s\"",
2602 ddigits = i - DEC_DIGITS;
2603 /* trailing padding for digit alignment later */
2604 memset(decdigits + i, 0, DEC_DIGITS-1);
2606 /* Handle exponent, if any */
2607 if (*cp == 'e' || *cp == 'E')
2613 exponent = strtol(cp, &endptr, 10);
2616 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
2617 errmsg("invalid input syntax for numeric: \"%s\"",
2620 if (exponent > NUMERIC_MAX_PRECISION ||
2621 exponent < -NUMERIC_MAX_PRECISION)
2623 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
2624 errmsg("invalid input syntax for numeric: \"%s\"",
2626 dweight += (int) exponent;
2627 dscale -= (int) exponent;
2632 /* Should be nothing left but spaces */
2635 if (!isspace((unsigned char) *cp))
2637 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
2638 errmsg("invalid input syntax for numeric: \"%s\"",
2644 * Okay, convert pure-decimal representation to base NBASE. First we
2645 * need to determine the converted weight and ndigits. offset is the
2646 * number of decimal zeroes to insert before the first given digit to
2647 * have a correctly aligned first NBASE digit.
2650 weight = (dweight + 1 + DEC_DIGITS-1) / DEC_DIGITS - 1;
2652 weight = - ((-dweight - 1) / DEC_DIGITS + 1);
2653 offset = (weight + 1) * DEC_DIGITS - (dweight + 1);
2654 ndigits = (ddigits + offset + DEC_DIGITS-1) / DEC_DIGITS;
2656 alloc_var(dest, ndigits);
2658 dest->weight = weight;
2659 dest->dscale = dscale;
2661 i = DEC_DIGITS - offset;
2662 digits = dest->digits;
2664 while (ndigits-- > 0)
2667 *digits++ = ((decdigits[i] * 10 + decdigits[i+1]) * 10 +
2668 decdigits[i+2]) * 10 + decdigits[i+3];
2669 #elif DEC_DIGITS == 2
2670 *digits++ = decdigits[i] * 10 + decdigits[i+1];
2671 #elif DEC_DIGITS == 1
2672 *digits++ = decdigits[i];
2674 #error unsupported NBASE
2681 /* Strip any leading/trailing zeroes, and normalize weight if zero */
2687 * set_var_from_num() -
2689 * Convert the packed db format into a variable
2692 set_var_from_num(Numeric num, NumericVar *dest)
2696 ndigits = (num->varlen - NUMERIC_HDRSZ) / sizeof(NumericDigit);
2698 alloc_var(dest, ndigits);
2700 dest->weight = num->n_weight;
2701 dest->sign = NUMERIC_SIGN(num);
2702 dest->dscale = NUMERIC_DSCALE(num);
2704 memcpy(dest->digits, num->n_data, ndigits * sizeof(NumericDigit));
2709 * set_var_from_var() -
2711 * Copy one variable into another
2714 set_var_from_var(NumericVar *value, NumericVar *dest)
2716 NumericDigit *newbuf;
2718 newbuf = digitbuf_alloc(value->ndigits + 1);
2719 newbuf[0] = 0; /* spare digit for rounding */
2720 memcpy(newbuf + 1, value->digits, value->ndigits * sizeof(NumericDigit));
2722 digitbuf_free(dest->buf);
2724 memcpy(dest, value, sizeof(NumericVar));
2726 dest->digits = newbuf + 1;
2731 * get_str_from_var() -
2733 * Convert a var to text representation (guts of numeric_out).
2734 * CAUTION: var's contents may be modified by rounding!
2735 * Returns a palloc'd string.
2738 get_str_from_var(NumericVar *var, int dscale)
2754 * Check if we must round up before printing the value and do so.
2756 round_var(var, dscale);
2759 * Allocate space for the result.
2761 * i is set to to # of decimal digits before decimal point.
2762 * dscale is the # of decimal digits we will print after decimal point.
2763 * We may generate as many as DEC_DIGITS-1 excess digits at the end,
2764 * and in addition we need room for sign, decimal point, null terminator.
2766 i = (var->weight + 1) * DEC_DIGITS;
2770 str = palloc(i + dscale + DEC_DIGITS + 2);
2774 * Output a dash for negative values
2776 if (var->sign == NUMERIC_NEG)
2780 * Output all digits before the decimal point
2782 if (var->weight < 0)
2784 d = var->weight + 1;
2789 for (d = 0; d <= var->weight; d++)
2791 dig = (d < var->ndigits) ? var->digits[d] : 0;
2792 /* In the first digit, suppress extra leading decimal zeroes */
2795 bool putit = (d > 0);
2814 #elif DEC_DIGITS == 2
2817 if (d1 > 0 || d > 0)
2820 #elif DEC_DIGITS == 1
2823 #error unsupported NBASE
2829 * If requested, output a decimal point and all the digits that follow
2830 * it. We initially put out a multiple of DEC_DIGITS digits, then
2831 * truncate if needed.
2836 endcp = cp + dscale;
2837 for (i = 0; i < dscale; d++, i += DEC_DIGITS)
2839 dig = (d >= 0 && d < var->ndigits) ? var->digits[d] : 0;
2851 #elif DEC_DIGITS == 2
2856 #elif DEC_DIGITS == 1
2859 #error unsupported NBASE
2866 * terminate the string and return it
2876 * Create the packed db numeric format in palloc()'d memory from
2880 make_result(NumericVar *var)
2883 NumericDigit *digits = var->digits;
2884 int weight = var->weight;
2885 int sign = var->sign;
2889 if (sign == NUMERIC_NAN)
2891 result = (Numeric) palloc(NUMERIC_HDRSZ);
2893 result->varlen = NUMERIC_HDRSZ;
2894 result->n_weight = 0;
2895 result->n_sign_dscale = NUMERIC_NAN;
2897 dump_numeric("make_result()", result);
2903 /* truncate leading zeroes */
2904 while (n > 0 && *digits == 0)
2910 /* truncate trailing zeroes */
2911 while (n > 0 && digits[n - 1] == 0)
2914 /* If zero result, force to weight=0 and positive sign */
2921 /* Build the result */
2922 len = NUMERIC_HDRSZ + n * sizeof(NumericDigit);
2923 result = (Numeric) palloc(len);
2924 result->varlen = len;
2925 result->n_weight = weight;
2926 result->n_sign_dscale = sign | (var->dscale & NUMERIC_DSCALE_MASK);
2928 memcpy(result->n_data, digits, n * sizeof(NumericDigit));
2930 /* Check for overflow of int16 fields */
2931 if (result->n_weight != weight ||
2932 NUMERIC_DSCALE(result) != var->dscale)
2934 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
2935 errmsg("value overflows numeric format")));
2937 dump_numeric("make_result()", result);
2945 * Do bounds checking and rounding according to the attributes
2949 apply_typmod(NumericVar *var, int32 typmod)
2957 /* Do nothing if we have a default typmod (-1) */
2958 if (typmod < (int32) (VARHDRSZ))
2962 precision = (typmod >> 16) & 0xffff;
2963 scale = typmod & 0xffff;
2964 maxdigits = precision - scale;
2966 /* Round to target scale (and set var->dscale) */
2967 round_var(var, scale);
2970 * Check for overflow - note we can't do this before rounding, because
2971 * rounding could raise the weight. Also note that the var's weight
2972 * could be inflated by leading zeroes, which will be stripped before
2973 * storage but perhaps might not have been yet. In any case, we must
2974 * recognize a true zero, whose weight doesn't mean anything.
2976 ddigits = (var->weight + 1) * DEC_DIGITS;
2977 if (ddigits > maxdigits)
2979 /* Determine true weight; and check for all-zero result */
2980 for (i = 0; i < var->ndigits; i++)
2982 NumericDigit dig = var->digits[i];
2986 /* Adjust for any high-order decimal zero digits */
2992 else if (dig < 1000)
2994 #elif DEC_DIGITS == 2
2997 #elif DEC_DIGITS == 1
3000 #error unsupported NBASE
3002 if (ddigits > maxdigits)
3004 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
3005 errmsg("numeric field overflow"),
3006 errdetail("ABS(value) >= 10^%d for field with precision %d, scale %d.",
3007 ddigits-1, precision, scale)));
3010 ddigits -= DEC_DIGITS;
3016 * Convert numeric to int8, rounding if needed.
3018 * If overflow, return FALSE (no error is raised). Return TRUE if okay.
3020 * CAUTION: var's contents may be modified by rounding!
3023 numericvar_to_int8(NumericVar *var, int64 *result)
3025 NumericDigit *digits;
3033 /* Round to nearest integer */
3036 /* Check for zero input */
3038 ndigits = var->ndigits;
3046 * For input like 10000000000, we must treat stripped digits as real.
3047 * So the loop assumes there are weight+1 digits before the decimal point.
3049 weight = var->weight;
3050 Assert(weight >= 0 && ndigits <= weight+1);
3052 /* Construct the result */
3053 digits = var->digits;
3054 neg = (var->sign == NUMERIC_NEG);
3056 for (i = 1; i <= weight; i++)
3063 * The overflow check is a bit tricky because we want to accept
3064 * INT64_MIN, which will overflow the positive accumulator. We
3065 * can detect this case easily though because INT64_MIN is the
3066 * only nonzero value for which -val == val (on a two's complement
3069 if ((val / NBASE) != oldval) /* possible overflow? */
3071 if (!neg || (-val) != val || val == 0 || oldval < 0)
3076 *result = neg ? -val : val;
3081 * Convert int8 value to numeric.
3084 int8_to_numericvar(int64 val, NumericVar *var)
3091 /* int8 can require at most 19 decimal digits; add one for safety */
3092 alloc_var(var, 20/DEC_DIGITS);
3095 var->sign = NUMERIC_NEG;
3100 var->sign = NUMERIC_POS;
3110 ptr = var->digits + var->ndigits;
3115 newuval = uval / NBASE;
3116 *ptr = uval - newuval * NBASE;
3120 var->ndigits = ndigits;
3121 var->weight = ndigits - 1;
3125 * Convert numeric to float8; if out of range, return +/- HUGE_VAL
3128 numeric_to_double_no_overflow(Numeric num)
3134 tmp = DatumGetCString(DirectFunctionCall1(numeric_out,
3135 NumericGetDatum(num)));
3137 /* unlike float8in, we ignore ERANGE from strtod */
3138 val = strtod(tmp, &endptr);
3139 if (*endptr != '\0')
3141 /* shouldn't happen ... */
3143 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
3144 errmsg("invalid input syntax for float8: \"%s\"",
3153 /* As above, but work from a NumericVar */
3155 numericvar_to_double_no_overflow(NumericVar *var)
3161 tmp = get_str_from_var(var, var->dscale);
3163 /* unlike float8in, we ignore ERANGE from strtod */
3164 val = strtod(tmp, &endptr);
3165 if (*endptr != '\0')
3167 /* shouldn't happen ... */
3169 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
3170 errmsg("invalid input syntax for float8: \"%s\"",
3183 * Compare two values on variable level. We assume zeroes have been
3184 * truncated to no digits.
3187 cmp_var(NumericVar *var1, NumericVar *var2)
3189 if (var1->ndigits == 0)
3191 if (var2->ndigits == 0)
3193 if (var2->sign == NUMERIC_NEG)
3197 if (var2->ndigits == 0)
3199 if (var1->sign == NUMERIC_POS)
3204 if (var1->sign == NUMERIC_POS)
3206 if (var2->sign == NUMERIC_NEG)
3208 return cmp_abs(var1, var2);
3211 if (var2->sign == NUMERIC_POS)
3214 return cmp_abs(var2, var1);
3221 * Full version of add functionality on variable level (handling signs).
3222 * result might point to one of the operands too without danger.
3225 add_var(NumericVar *var1, NumericVar *var2, NumericVar *result)
3228 * Decide on the signs of the two variables what to do
3230 if (var1->sign == NUMERIC_POS)
3232 if (var2->sign == NUMERIC_POS)
3235 * Both are positive result = +(ABS(var1) + ABS(var2))
3237 add_abs(var1, var2, result);
3238 result->sign = NUMERIC_POS;
3243 * var1 is positive, var2 is negative Must compare absolute
3246 switch (cmp_abs(var1, var2))
3250 * ABS(var1) == ABS(var2)
3255 result->dscale = Max(var1->dscale, var2->dscale);
3260 * ABS(var1) > ABS(var2)
3261 * result = +(ABS(var1) - ABS(var2))
3264 sub_abs(var1, var2, result);
3265 result->sign = NUMERIC_POS;
3270 * ABS(var1) < ABS(var2)
3271 * result = -(ABS(var2) - ABS(var1))
3274 sub_abs(var2, var1, result);
3275 result->sign = NUMERIC_NEG;
3282 if (var2->sign == NUMERIC_POS)
3285 * var1 is negative, var2 is positive
3286 * Must compare absolute values
3289 switch (cmp_abs(var1, var2))
3293 * ABS(var1) == ABS(var2)
3298 result->dscale = Max(var1->dscale, var2->dscale);
3303 * ABS(var1) > ABS(var2)
3304 * result = -(ABS(var1) - ABS(var2))
3307 sub_abs(var1, var2, result);
3308 result->sign = NUMERIC_NEG;
3313 * ABS(var1) < ABS(var2)
3314 * result = +(ABS(var2) - ABS(var1))
3317 sub_abs(var2, var1, result);
3318 result->sign = NUMERIC_POS;
3326 * result = -(ABS(var1) + ABS(var2))
3329 add_abs(var1, var2, result);
3330 result->sign = NUMERIC_NEG;
3339 * Full version of sub functionality on variable level (handling signs).
3340 * result might point to one of the operands too without danger.
3343 sub_var(NumericVar *var1, NumericVar *var2, NumericVar *result)
3346 * Decide on the signs of the two variables what to do
3348 if (var1->sign == NUMERIC_POS)
3350 if (var2->sign == NUMERIC_NEG)
3353 * var1 is positive, var2 is negative
3354 * result = +(ABS(var1) + ABS(var2))
3357 add_abs(var1, var2, result);
3358 result->sign = NUMERIC_POS;
3364 * Must compare absolute values
3367 switch (cmp_abs(var1, var2))
3371 * ABS(var1) == ABS(var2)
3376 result->dscale = Max(var1->dscale, var2->dscale);
3381 * ABS(var1) > ABS(var2)
3382 * result = +(ABS(var1) - ABS(var2))
3385 sub_abs(var1, var2, result);
3386 result->sign = NUMERIC_POS;
3391 * ABS(var1) < ABS(var2)
3392 * result = -(ABS(var2) - ABS(var1))
3395 sub_abs(var2, var1, result);
3396 result->sign = NUMERIC_NEG;
3403 if (var2->sign == NUMERIC_NEG)
3407 * Must compare absolute values
3410 switch (cmp_abs(var1, var2))
3414 * ABS(var1) == ABS(var2)
3419 result->dscale = Max(var1->dscale, var2->dscale);
3424 * ABS(var1) > ABS(var2)
3425 * result = -(ABS(var1) - ABS(var2))
3428 sub_abs(var1, var2, result);
3429 result->sign = NUMERIC_NEG;
3434 * ABS(var1) < ABS(var2)
3435 * result = +(ABS(var2) - ABS(var1))
3438 sub_abs(var2, var1, result);
3439 result->sign = NUMERIC_POS;
3446 * var1 is negative, var2 is positive
3447 * result = -(ABS(var1) + ABS(var2))
3450 add_abs(var1, var2, result);
3451 result->sign = NUMERIC_NEG;
3460 * Multiplication on variable level. Product of var1 * var2 is stored
3461 * in result. Result is rounded to no more than rscale fractional digits.
3464 mul_var(NumericVar *var1, NumericVar *var2, NumericVar *result,
3475 NumericDigit *res_digits;
3480 /* copy these values into local vars for speed in inner loop */
3481 int var1ndigits = var1->ndigits;
3482 int var2ndigits = var2->ndigits;
3483 NumericDigit *var1digits = var1->digits;
3484 NumericDigit *var2digits = var2->digits;
3486 if (var1ndigits == 0 || var2ndigits == 0)
3488 /* one or both inputs is zero; so is result */
3490 result->dscale = rscale;
3494 /* Determine result sign and (maximum possible) weight */
3495 if (var1->sign == var2->sign)
3496 res_sign = NUMERIC_POS;
3498 res_sign = NUMERIC_NEG;
3499 res_weight = var1->weight + var2->weight + 2;
3502 * Determine number of result digits to compute. If the exact result
3503 * would have more than rscale fractional digits, truncate the computation
3504 * with MUL_GUARD_DIGITS guard digits. We do that by pretending that
3505 * one or both inputs have fewer digits than they really do.
3507 res_ndigits = var1ndigits + var2ndigits + 1;
3508 maxdigits = res_weight + 1 + (rscale * DEC_DIGITS) + MUL_GUARD_DIGITS;
3509 if (res_ndigits > maxdigits)
3513 /* no useful precision at all in the result... */
3515 result->dscale = rscale;
3518 /* force maxdigits odd so that input ndigits can be equal */
3519 if ((maxdigits & 1) == 0)
3521 if (var1ndigits > var2ndigits)
3523 var1ndigits -= res_ndigits - maxdigits;
3524 if (var1ndigits < var2ndigits)
3525 var1ndigits = var2ndigits = (var1ndigits + var2ndigits) / 2;
3529 var2ndigits -= res_ndigits - maxdigits;
3530 if (var2ndigits < var1ndigits)
3531 var1ndigits = var2ndigits = (var1ndigits + var2ndigits) / 2;
3533 res_ndigits = maxdigits;
3534 Assert(res_ndigits == var1ndigits + var2ndigits + 1);
3538 * We do the arithmetic in an array "dig[]" of signed int's. Since
3539 * INT_MAX is noticeably larger than NBASE*NBASE, this gives us headroom
3540 * to avoid normalizing carries immediately.
3542 * maxdig tracks the maximum possible value of any dig[] entry;
3543 * when this threatens to exceed INT_MAX, we take the time to propagate
3544 * carries. To avoid overflow in maxdig itself, it actually represents
3545 * the max possible value divided by NBASE-1.
3547 dig = (int *) palloc0(res_ndigits * sizeof(int));
3550 ri = res_ndigits - 1;
3551 for (i1 = var1ndigits - 1; i1 >= 0; ri--, i1--)
3553 int var1digit = var1digits[i1];
3558 /* Time to normalize? */
3559 maxdig += var1digit;
3560 if (maxdig > INT_MAX/(NBASE-1))
3564 for (i = res_ndigits-1; i >= 0; i--)
3566 newdig = dig[i] + carry;
3567 if (newdig >= NBASE)
3569 carry = newdig/NBASE;
3570 newdig -= carry*NBASE;
3577 /* Reset maxdig to indicate new worst-case */
3578 maxdig = 1 + var1digit;
3581 /* Add appropriate multiple of var2 into the accumulator */
3583 for (i2 = var2ndigits - 1; i2 >= 0; i2--)
3585 dig[i--] += var1digit * var2digits[i2];
3590 * Now we do a final carry propagation pass to normalize the result,
3591 * which we combine with storing the result digits into the output.
3592 * Note that this is still done at full precision w/guard digits.
3594 alloc_var(result, res_ndigits);
3595 res_digits = result->digits;
3597 for (i = res_ndigits-1; i >= 0; i--)
3599 newdig = dig[i] + carry;
3600 if (newdig >= NBASE)
3602 carry = newdig/NBASE;
3603 newdig -= carry*NBASE;
3607 res_digits[i] = newdig;
3614 * Finally, round the result to the requested precision.
3616 result->weight = res_weight;
3617 result->sign = res_sign;
3619 /* Round to target rscale (and set result->dscale) */
3620 round_var(result, rscale);
3622 /* Strip leading and trailing zeroes */
3630 * Division on variable level. Quotient of var1 / var2 is stored
3631 * in result. Result is rounded to no more than rscale fractional digits.
3634 div_var(NumericVar *var1, NumericVar *var2, NumericVar *result,
3645 NumericDigit *res_digits;
3652 /* copy these values into local vars for speed in inner loop */
3653 int var1ndigits = var1->ndigits;
3654 int var2ndigits = var2->ndigits;
3655 NumericDigit *var1digits = var1->digits;
3656 NumericDigit *var2digits = var2->digits;
3659 * First of all division by zero check; we must not be handed an
3660 * unnormalized divisor.
3662 if (var2ndigits == 0 || var2digits[0] == 0)
3664 (errcode(ERRCODE_DIVISION_BY_ZERO),
3665 errmsg("division by zero")));
3668 * Now result zero check
3670 if (var1ndigits == 0)
3673 result->dscale = rscale;
3678 * Determine the result sign, weight and number of digits to calculate
3680 if (var1->sign == var2->sign)
3681 res_sign = NUMERIC_POS;
3683 res_sign = NUMERIC_NEG;
3684 res_weight = var1->weight - var2->weight + 1;
3685 /* The number of accurate result digits we need to produce: */
3686 div_ndigits = res_weight + 1 + (rscale + DEC_DIGITS-1)/DEC_DIGITS;
3687 /* Add guard digits for roundoff error */
3688 div_ndigits += DIV_GUARD_DIGITS;
3689 if (div_ndigits < DIV_GUARD_DIGITS)
3690 div_ndigits = DIV_GUARD_DIGITS;
3691 /* Must be at least var1ndigits, too, to simplify data-loading loop */
3692 if (div_ndigits < var1ndigits)
3693 div_ndigits = var1ndigits;
3696 * We do the arithmetic in an array "div[]" of signed int's. Since
3697 * INT_MAX is noticeably larger than NBASE*NBASE, this gives us headroom
3698 * to avoid normalizing carries immediately.
3700 * We start with div[] containing one zero digit followed by the
3701 * dividend's digits (plus appended zeroes to reach the desired
3702 * precision including guard digits). Each step of the main loop
3703 * computes an (approximate) quotient digit and stores it into div[],
3704 * removing one position of dividend space. A final pass of carry
3705 * propagation takes care of any mistaken quotient digits.
3707 div = (int *) palloc0((div_ndigits + 1) * sizeof(int));
3708 for (i = 0; i < var1ndigits; i++)
3709 div[i+1] = var1digits[i];
3712 * We estimate each quotient digit using floating-point arithmetic,
3713 * taking the first four digits of the (current) dividend and divisor.
3714 * This must be float to avoid overflow.
3716 fdivisor = (double) var2digits[0];
3717 for (i = 1; i < 4; i++)
3720 if (i < var2ndigits)
3721 fdivisor += (double) var2digits[i];
3723 fdivisorinverse = 1.0 / fdivisor;
3726 * maxdiv tracks the maximum possible absolute value of any div[] entry;
3727 * when this threatens to exceed INT_MAX, we take the time to propagate
3728 * carries. To avoid overflow in maxdiv itself, it actually represents
3729 * the max possible abs. value divided by NBASE-1.
3734 * Outer loop computes next quotient digit, which will go into div[qi]
3736 for (qi = 0; qi < div_ndigits; qi++)
3738 /* Approximate the current dividend value */
3739 fdividend = (double) div[qi];
3740 for (i = 1; i < 4; i++)
3743 if (qi+i <= div_ndigits)
3744 fdividend += (double) div[qi+i];
3746 /* Compute the (approximate) quotient digit */
3747 fquotient = fdividend * fdivisorinverse;
3748 qdigit = (fquotient >= 0.0) ? ((int) fquotient) :
3749 (((int) fquotient) - 1); /* truncate towards -infinity */
3753 /* Do we need to normalize now? */
3754 maxdiv += Abs(qdigit);
3755 if (maxdiv > INT_MAX/(NBASE-1))
3759 for (i = div_ndigits; i > qi; i--)
3761 newdig = div[i] + carry;
3764 carry = -((-newdig-1)/NBASE) - 1;
3765 newdig -= carry*NBASE;
3767 else if (newdig >= NBASE)
3769 carry = newdig/NBASE;
3770 newdig -= carry*NBASE;
3776 newdig = div[qi] + carry;
3779 * All the div[] digits except possibly div[qi] are now
3780 * in the range 0..NBASE-1.
3782 maxdiv = Abs(newdig) / (NBASE-1);
3783 maxdiv = Max(maxdiv, 1);
3785 * Recompute the quotient digit since new info may have
3786 * propagated into the top four dividend digits
3788 fdividend = (double) div[qi];
3789 for (i = 1; i < 4; i++)
3792 if (qi+i <= div_ndigits)
3793 fdividend += (double) div[qi+i];
3795 /* Compute the (approximate) quotient digit */
3796 fquotient = fdividend * fdivisorinverse;
3797 qdigit = (fquotient >= 0.0) ? ((int) fquotient) :
3798 (((int) fquotient) - 1); /* truncate towards -infinity */
3799 maxdiv += Abs(qdigit);
3802 /* Subtract off the appropriate multiple of the divisor */
3805 int istop = Min(var2ndigits, div_ndigits-qi+1);
3807 for (i = 0; i < istop; i++)
3808 div[qi+i] -= qdigit * var2digits[i];
3813 * The dividend digit we are about to replace might still be nonzero.
3814 * Fold it into the next digit position. We don't need to worry about
3815 * overflow here since this should nearly cancel with the subtraction
3818 div[qi+1] += div[qi] * NBASE;
3824 * Approximate and store the last quotient digit (div[div_ndigits])
3826 fdividend = (double) div[qi];
3827 for (i = 1; i < 4; i++)
3831 fquotient = fdividend * fdivisorinverse;
3832 qdigit = (fquotient >= 0.0) ? ((int) fquotient) :
3833 (((int) fquotient) - 1); /* truncate towards -infinity */
3837 * Now we do a final carry propagation pass to normalize the result,
3838 * which we combine with storing the result digits into the output.
3839 * Note that this is still done at full precision w/guard digits.
3841 alloc_var(result, div_ndigits+1);
3842 res_digits = result->digits;
3844 for (i = div_ndigits; i >= 0; i--)
3846 newdig = div[i] + carry;
3849 carry = -((-newdig-1)/NBASE) - 1;
3850 newdig -= carry*NBASE;
3852 else if (newdig >= NBASE)
3854 carry = newdig/NBASE;
3855 newdig -= carry*NBASE;
3859 res_digits[i] = newdig;
3866 * Finally, round the result to the requested precision.
3868 result->weight = res_weight;
3869 result->sign = res_sign;
3871 /* Round to target rscale (and set result->dscale) */
3872 round_var(result, rscale);
3874 /* Strip leading and trailing zeroes */
3880 * Default scale selection for division
3882 * Returns the appropriate result scale for the division result.
3885 select_div_scale(NumericVar *var1, NumericVar *var2)
3891 NumericDigit firstdigit1,
3896 * The result scale of a division isn't specified in any SQL standard.
3897 * For PostgreSQL we select a result scale that will give at least
3898 * NUMERIC_MIN_SIG_DIGITS significant digits, so that numeric gives a
3899 * result no less accurate than float8; but use a scale not less than
3900 * either input's display scale.
3903 /* Get the actual (normalized) weight and first digit of each input */
3905 weight1 = 0; /* values to use if var1 is zero */
3907 for (i = 0; i < var1->ndigits; i++)
3909 firstdigit1 = var1->digits[i];
3910 if (firstdigit1 != 0)
3912 weight1 = var1->weight - i;
3917 weight2 = 0; /* values to use if var2 is zero */
3919 for (i = 0; i < var2->ndigits; i++)
3921 firstdigit2 = var2->digits[i];
3922 if (firstdigit2 != 0)
3924 weight2 = var2->weight - i;
3930 * Estimate weight of quotient. If the two first digits are equal,
3931 * we can't be sure, but assume that var1 is less than var2.
3933 qweight = weight1 - weight2;
3934 if (firstdigit1 <= firstdigit2)
3937 /* Select result scale */
3938 rscale = NUMERIC_MIN_SIG_DIGITS - qweight * DEC_DIGITS;
3939 rscale = Max(rscale, var1->dscale);
3940 rscale = Max(rscale, var2->dscale);
3941 rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
3942 rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
3951 * Calculate the modulo of two numerics at variable level
3954 mod_var(NumericVar *var1, NumericVar *var2, NumericVar *result)
3962 * We do this using the equation
3963 * mod(x,y) = x - trunc(x/y)*y
3964 * We set rscale the same way numeric_div and numeric_mul do
3965 * to get the right answer from the equation. The final result,
3966 * however, need not be displayed to more precision than the inputs.
3969 rscale = select_div_scale(var1, var2);
3971 div_var(var1, var2, &tmp, rscale);
3975 mul_var(var2, &tmp, &tmp, var2->dscale + tmp.dscale);
3977 sub_var(var1, &tmp, result);
3979 round_var(result, Max(var1->dscale, var2->dscale));
3988 * Return the smallest integer greater than or equal to the argument
3992 ceil_var(NumericVar *var, NumericVar *result)
3997 set_var_from_var(var, &tmp);
4001 if (var->sign == NUMERIC_POS && cmp_var(var, &tmp) != 0)
4002 add_var(&tmp, &const_one, &tmp);
4004 set_var_from_var(&tmp, result);
4012 * Return the largest integer equal to or less than the argument
4016 floor_var(NumericVar *var, NumericVar *result)
4021 set_var_from_var(var, &tmp);
4025 if (var->sign == NUMERIC_NEG && cmp_var(var, &tmp) != 0)
4026 sub_var(&tmp, &const_one, &tmp);
4028 set_var_from_var(&tmp, result);
4036 * Compute the square root of x using Newton's algorithm
4039 sqrt_var(NumericVar *arg, NumericVar *result, int rscale)
4043 NumericVar last_val;
4047 local_rscale = rscale + 8;
4049 stat = cmp_var(arg, &const_zero);
4053 result->dscale = rscale;
4059 (errcode(ERRCODE_FLOATING_POINT_EXCEPTION),
4060 errmsg("cannot take square root of a negative number")));
4064 init_var(&last_val);
4066 /* Copy arg in case it is the same var as result */
4067 set_var_from_var(arg, &tmp_arg);
4070 * Initialize the result to the first guess
4072 alloc_var(result, 1);
4073 result->digits[0] = tmp_arg.digits[0] / 2;
4074 if (result->digits[0] == 0)
4075 result->digits[0] = 1;
4076 result->weight = tmp_arg.weight / 2;
4077 result->sign = NUMERIC_POS;
4079 set_var_from_var(result, &last_val);
4083 div_var(&tmp_arg, result, &tmp_val, local_rscale);
4085 add_var(result, &tmp_val, result);
4086 mul_var(result, &const_zero_point_five, result, local_rscale);
4088 if (cmp_var(&last_val, result) == 0)
4090 set_var_from_var(result, &last_val);
4093 free_var(&last_val);
4097 /* Round to requested precision */
4098 round_var(result, rscale);
4105 * Raise e to the power of x
4108 exp_var(NumericVar *arg, NumericVar *result, int rscale)
4116 * We separate the integral and fraction parts of x, then compute
4117 * e^x = e^xint * e^xfrac
4118 * where e = exp(1) and e^xfrac = exp(xfrac) are computed by
4119 * exp_var_internal; the limited range of inputs allows that routine
4120 * to do a good job with a simple Taylor series. Raising e^xint is
4121 * done by repeated multiplications in power_var_int.
4126 set_var_from_var(arg, &x);
4128 if (x.sign == NUMERIC_NEG)
4131 x.sign = NUMERIC_POS;
4134 /* Extract the integer part, remove it from x */
4136 while (x.weight >= 0)
4141 xintval += x.digits[0];
4146 /* Guard against overflow */
4147 if (xintval >= NUMERIC_MAX_RESULT_SCALE * 3)
4149 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
4150 errmsg("argument for EXP() too big")));
4153 /* Select an appropriate scale for internal calculation */
4154 local_rscale = rscale + MUL_GUARD_DIGITS * 2;
4156 /* Compute e^xfrac */
4157 exp_var_internal(&x, result, local_rscale);
4159 /* If there's an integer part, multiply by e^xint */
4165 exp_var_internal(&const_one, &e, local_rscale);
4166 power_var_int(&e, xintval, &e, local_rscale);
4167 mul_var(&e, result, result, local_rscale);
4171 /* Compensate for input sign, and round to requested rscale */
4173 div_var(&const_one, result, result, rscale);
4175 round_var(result, rscale);
4182 * exp_var_internal() -
4184 * Raise e to the power of x, where 0 <= x <= 1
4186 * NB: the result should be good to at least rscale digits, but it has
4187 * *not* been rounded off; the caller must do that if wanted.
4190 exp_var_internal(NumericVar *arg, NumericVar *result, int rscale)
4206 set_var_from_var(arg, &x);
4208 Assert(x.sign == NUMERIC_POS);
4210 local_rscale = rscale + 8;
4212 /* Reduce input into range 0 <= x <= 0.01 */
4213 while (cmp_var(&x, &const_zero_point_01) > 0)
4217 mul_var(&x, &const_zero_point_five, &x, x.dscale+1);
4221 * Use the Taylor series
4223 * exp(x) = 1 + x + x^2/2! + x^3/3! + ...
4225 * Given the limited range of x, this should converge reasonably quickly.
4226 * We run the series until the terms fall below the local_rscale limit.
4228 add_var(&const_one, &x, result);
4229 set_var_from_var(&x, &xpow);
4230 set_var_from_var(&const_one, &ifac);
4231 set_var_from_var(&const_one, &ni);
4235 add_var(&ni, &const_one, &ni);
4236 mul_var(&xpow, &x, &xpow, local_rscale);
4237 mul_var(&ifac, &ni, &ifac, 0);
4238 div_var(&xpow, &ifac, &elem, local_rscale);
4240 if (elem.ndigits == 0)
4243 add_var(result, &elem, result);
4246 /* Compensate for argument range reduction */
4248 mul_var(result, result, result, local_rscale);
4261 * Compute the natural log of x
4264 ln_var(NumericVar *arg, NumericVar *result, int rscale)
4273 if (cmp_var(arg, &const_zero) <= 0)
4275 (errcode(ERRCODE_FLOATING_POINT_EXCEPTION),
4276 errmsg("cannot take log of a negative number")));
4278 local_rscale = rscale + 8;
4286 set_var_from_var(arg, &x);
4287 set_var_from_var(&const_two, &fact);
4289 /* Reduce input into range 0.9 < x < 1.1 */
4290 while (cmp_var(&x, &const_zero_point_nine) <= 0)
4293 sqrt_var(&x, &x, local_rscale);
4294 mul_var(&fact, &const_two, &fact, 0);
4296 while (cmp_var(&x, &const_one_point_one) >= 0)
4299 sqrt_var(&x, &x, local_rscale);
4300 mul_var(&fact, &const_two, &fact, 0);
4304 * We use the Taylor series for 0.5 * ln((1+z)/(1-z)),
4306 * z + z^3/3 + z^5/5 + ...
4308 * where z = (x-1)/(x+1) is in the range (approximately) -0.053 .. 0.048
4309 * due to the above range-reduction of x.
4311 * The convergence of this is not as fast as one would like, but is
4312 * tolerable given that z is small.
4314 sub_var(&x, &const_one, result);
4315 add_var(&x, &const_one, &elem);
4316 div_var(result, &elem, result, local_rscale);
4317 set_var_from_var(result, &xx);
4318 mul_var(result, result, &x, local_rscale);
4320 set_var_from_var(&const_one, &ni);
4324 add_var(&ni, &const_two, &ni);
4325 mul_var(&xx, &x, &xx, local_rscale);
4326 div_var(&xx, &ni, &elem, local_rscale);
4328 if (elem.ndigits == 0)
4331 add_var(result, &elem, result);
4333 if (elem.weight < (result->weight - local_rscale * 2/DEC_DIGITS))
4337 /* Compensate for argument range reduction, round to requested rscale */
4338 mul_var(result, &fact, result, rscale);
4351 * Compute the logarithm of num in a given base.
4353 * Note: this routine chooses dscale of the result.
4356 log_var(NumericVar *base, NumericVar *num, NumericVar *result)
4367 /* Set scale for ln() calculations --- compare numeric_ln() */
4369 /* Approx decimal digits before decimal point */
4370 dec_digits = (num->weight + 1) * DEC_DIGITS;
4373 rscale = NUMERIC_MIN_SIG_DIGITS - (int) log10(dec_digits - 1);
4374 else if (dec_digits < 1)
4375 rscale = NUMERIC_MIN_SIG_DIGITS - (int) log10(1 - dec_digits);
4377 rscale = NUMERIC_MIN_SIG_DIGITS;
4379 rscale = Max(rscale, base->dscale);
4380 rscale = Max(rscale, num->dscale);
4381 rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
4382 rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
4384 local_rscale = rscale + 8;
4386 /* Form natural logarithms */
4387 ln_var(base, &ln_base, local_rscale);
4388 ln_var(num, &ln_num, local_rscale);
4390 ln_base.dscale = rscale;
4391 ln_num.dscale = rscale;
4393 /* Select scale for division result */
4394 rscale = select_div_scale(&ln_num, &ln_base);
4396 div_var(&ln_num, &ln_base, result, rscale);
4406 * Raise base to the power of exp
4408 * Note: this routine chooses dscale of the result.
4411 power_var(NumericVar *base, NumericVar *exp, NumericVar *result)
4420 /* If exp can be represented as an integer, use power_var_int */
4421 if (exp->ndigits == 0 || exp->ndigits <= exp->weight + 1)
4423 /* exact integer, but does it fit in int? */
4427 /* must copy because numericvar_to_int8() scribbles on input */
4429 set_var_from_var(exp, &x);
4430 if (numericvar_to_int8(&x, &expval64))
4432 int expval = (int) expval64;
4434 /* Test for overflow by reverse-conversion. */
4435 if ((int64) expval == expval64)
4437 /* Okay, select rscale */
4438 rscale = NUMERIC_MIN_SIG_DIGITS;
4439 rscale = Max(rscale, base->dscale);
4440 rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
4441 rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
4443 power_var_int(base, expval, result, rscale);
4455 /* Set scale for ln() calculation --- need extra accuracy here */
4457 /* Approx decimal digits before decimal point */
4458 dec_digits = (base->weight + 1) * DEC_DIGITS;
4461 rscale = NUMERIC_MIN_SIG_DIGITS*2 - (int) log10(dec_digits - 1);
4462 else if (dec_digits < 1)
4463 rscale = NUMERIC_MIN_SIG_DIGITS*2 - (int) log10(1 - dec_digits);
4465 rscale = NUMERIC_MIN_SIG_DIGITS*2;
4467 rscale = Max(rscale, base->dscale * 2);
4468 rscale = Max(rscale, exp->dscale * 2);
4469 rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE * 2);
4470 rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE * 2);
4472 local_rscale = rscale + 8;
4474 ln_var(base, &ln_base, local_rscale);
4476 mul_var(&ln_base, exp, &ln_num, local_rscale);
4478 /* Set scale for exp() -- compare numeric_exp() */
4480 /* convert input to float8, ignoring overflow */
4481 val = numericvar_to_double_no_overflow(&ln_num);
4483 /* log10(result) = num * log10(e), so this is approximately the weight: */
4484 val *= 0.434294481903252;
4486 /* limit to something that won't cause integer overflow */
4487 val = Max(val, -NUMERIC_MAX_RESULT_SCALE);
4488 val = Min(val, NUMERIC_MAX_RESULT_SCALE);
4490 rscale = NUMERIC_MIN_SIG_DIGITS - (int) val;
4491 rscale = Max(rscale, base->dscale);
4492 rscale = Max(rscale, exp->dscale);
4493 rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
4494 rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
4496 exp_var(&ln_num, result, rscale);
4505 * Raise base to the power of exp, where exp is an integer.
4508 power_var_int(NumericVar *base, int exp, NumericVar *result, int rscale)
4511 NumericVar base_prod;
4514 /* Detect some special cases, particularly 0^0. */
4519 if (base->ndigits == 0)
4521 (errcode(ERRCODE_FLOATING_POINT_EXCEPTION),
4522 errmsg("zero raised to zero is undefined")));
4523 set_var_from_var(&const_one, result);
4524 result->dscale = rscale; /* no need to round */
4527 set_var_from_var(base, result);
4528 round_var(result, rscale);
4531 div_var(&const_one, base, result, rscale);
4534 mul_var(base, base, result, rscale);
4541 * The general case repeatedly multiplies base according to the
4542 * bit pattern of exp. We do the multiplications with some extra
4548 local_rscale = rscale + MUL_GUARD_DIGITS * 2;
4550 init_var(&base_prod);
4551 set_var_from_var(base, &base_prod);
4554 set_var_from_var(base, result);
4556 set_var_from_var(&const_one, result);
4558 while ((exp >>= 1) > 0)
4560 mul_var(&base_prod, &base_prod, &base_prod, local_rscale);
4562 mul_var(&base_prod, result, result, local_rscale);
4565 free_var(&base_prod);
4567 /* Compensate for input sign, and round to requested rscale */
4569 div_var(&const_one, result, result, rscale);
4571 round_var(result, rscale);
4575 /* ----------------------------------------------------------------------
4577 * Following are the lowest level functions that operate unsigned
4578 * on the variable level
4580 * ----------------------------------------------------------------------
4587 * Compare the absolute values of var1 and var2
4588 * Returns: -1 for ABS(var1) < ABS(var2)
4589 * 0 for ABS(var1) == ABS(var2)
4590 * 1 for ABS(var1) > ABS(var2)
4594 cmp_abs(NumericVar *var1, NumericVar *var2)
4596 NumericDigit *var1digits = var1->digits;
4597 NumericDigit *var2digits = var2->digits;
4600 int w1 = var1->weight;
4601 int w2 = var2->weight;
4603 /* Check any digits before the first common digit */
4605 while (w1 > w2 && i1 < var1->ndigits)
4607 if (var1digits[i1++] != 0)
4611 while (w2 > w1 && i2 < var2->ndigits)
4613 if (var2digits[i2++] != 0)
4618 /* At this point, either w1 == w2 or we've run out of digits */
4622 while (i1 < var1->ndigits && i2 < var2->ndigits)
4624 int stat = var1digits[i1++] - var2digits[i2++];
4636 * At this point, we've run out of digits on one side or the other;
4637 * so any remaining nonzero digits imply that side is larger
4639 while (i1 < var1->ndigits)
4641 if (var1digits[i1++] != 0)
4644 while (i2 < var2->ndigits)
4646 if (var2digits[i2++] != 0)
4657 * Add the absolute values of two variables into result.
4658 * result might point to one of the operands without danger.
4661 add_abs(NumericVar *var1, NumericVar *var2, NumericVar *result)
4663 NumericDigit *res_buf;
4664 NumericDigit *res_digits;
4676 /* copy these values into local vars for speed in inner loop */
4677 int var1ndigits = var1->ndigits;
4678 int var2ndigits = var2->ndigits;
4679 NumericDigit *var1digits = var1->digits;
4680 NumericDigit *var2digits = var2->digits;
4682 res_weight = Max(var1->weight, var2->weight) + 1;
4684 res_dscale = Max(var1->dscale, var2->dscale);
4686 /* Note: here we are figuring rscale in base-NBASE digits */
4687 rscale1 = var1->ndigits - var1->weight - 1;
4688 rscale2 = var2->ndigits - var2->weight - 1;
4689 res_rscale = Max(rscale1, rscale2);
4691 res_ndigits = res_rscale + res_weight + 1;
4692 if (res_ndigits <= 0)
4695 res_buf = digitbuf_alloc(res_ndigits + 1);
4696 res_buf[0] = 0; /* spare digit for later rounding */
4697 res_digits = res_buf + 1;
4699 i1 = res_rscale + var1->weight + 1;
4700 i2 = res_rscale + var2->weight + 1;
4701 for (i = res_ndigits - 1; i >= 0; i--)
4705 if (i1 >= 0 && i1 < var1ndigits)
4706 carry += var1digits[i1];
4707 if (i2 >= 0 && i2 < var2ndigits)
4708 carry += var2digits[i2];
4712 res_digits[i] = carry - NBASE;
4717 res_digits[i] = carry;
4722 Assert(carry == 0); /* else we failed to allow for carry out */
4724 digitbuf_free(result->buf);
4725 result->ndigits = res_ndigits;
4726 result->buf = res_buf;
4727 result->digits = res_digits;
4728 result->weight = res_weight;
4729 result->dscale = res_dscale;
4731 /* Remove leading/trailing zeroes */
4739 * Subtract the absolute value of var2 from the absolute value of var1
4740 * and store in result. result might point to one of the operands
4743 * ABS(var1) MUST BE GREATER OR EQUAL ABS(var2) !!!
4746 sub_abs(NumericVar *var1, NumericVar *var2, NumericVar *result)
4748 NumericDigit *res_buf;
4749 NumericDigit *res_digits;
4761 /* copy these values into local vars for speed in inner loop */
4762 int var1ndigits = var1->ndigits;
4763 int var2ndigits = var2->ndigits;
4764 NumericDigit *var1digits = var1->digits;
4765 NumericDigit *var2digits = var2->digits;
4767 res_weight = var1->weight;
4769 res_dscale = Max(var1->dscale, var2->dscale);
4771 /* Note: here we are figuring rscale in base-NBASE digits */
4772 rscale1 = var1->ndigits - var1->weight - 1;
4773 rscale2 = var2->ndigits - var2->weight - 1;
4774 res_rscale = Max(rscale1, rscale2);
4776 res_ndigits = res_rscale + res_weight + 1;
4777 if (res_ndigits <= 0)
4780 res_buf = digitbuf_alloc(res_ndigits + 1);
4781 res_buf[0] = 0; /* spare digit for later rounding */
4782 res_digits = res_buf + 1;
4784 i1 = res_rscale + var1->weight + 1;
4785 i2 = res_rscale + var2->weight + 1;
4786 for (i = res_ndigits - 1; i >= 0; i--)
4790 if (i1 >= 0 && i1 < var1ndigits)
4791 borrow += var1digits[i1];
4792 if (i2 >= 0 && i2 < var2ndigits)
4793 borrow -= var2digits[i2];
4797 res_digits[i] = borrow + NBASE;
4802 res_digits[i] = borrow;
4807 Assert(borrow == 0); /* else caller gave us var1 < var2 */
4809 digitbuf_free(result->buf);
4810 result->ndigits = res_ndigits;
4811 result->buf = res_buf;
4812 result->digits = res_digits;
4813 result->weight = res_weight;
4814 result->dscale = res_dscale;
4816 /* Remove leading/trailing zeroes */
4823 * Round the value of a variable to no more than rscale decimal digits
4824 * after the decimal point. NOTE: we allow rscale < 0 here, implying
4825 * rounding before the decimal point.
4828 round_var(NumericVar *var, int rscale)
4830 NumericDigit *digits = var->digits;
4835 var->dscale = rscale;
4837 /* decimal digits wanted */
4838 di = (var->weight + 1) * DEC_DIGITS + rscale;
4841 * If di = 0, the value loses all digits, but could round up to 1
4842 * if its first extra digit is >= 5. If di < 0 the result must be 0.
4848 var->sign = NUMERIC_POS;
4852 /* NBASE digits wanted */
4853 ndigits = (di + DEC_DIGITS-1) / DEC_DIGITS;
4855 /* 0, or number of decimal digits to keep in last NBASE digit */
4858 if (ndigits < var->ndigits ||
4859 (ndigits == var->ndigits && di > 0))
4861 var->ndigits = ndigits;
4864 /* di must be zero */
4865 carry = (digits[ndigits] >= HALF_NBASE) ? 1 : 0;
4869 carry = (digits[ndigits] >= HALF_NBASE) ? 1 : 0;
4873 /* Must round within last NBASE digit */
4878 pow10 = round_powers[di];
4879 #elif DEC_DIGITS == 2
4882 #error unsupported NBASE
4884 extra = digits[--ndigits] % pow10;
4885 digits[ndigits] -= extra;
4887 if (extra >= pow10/2)
4889 pow10 += digits[ndigits];
4895 digits[ndigits] = pow10;
4900 /* Propagate carry if needed */
4903 carry += digits[--ndigits];
4906 digits[ndigits] = carry - NBASE;
4911 digits[ndigits] = carry;
4918 Assert(ndigits == -1); /* better not have added > 1 digit */
4919 Assert(var->digits > var->buf);
4931 * Truncate the value of a variable at rscale decimal digits after the
4932 * decimal point. NOTE: we allow rscale < 0 here, implying
4933 * truncation before the decimal point.
4936 trunc_var(NumericVar *var, int rscale)
4941 var->dscale = rscale;
4943 /* decimal digits wanted */
4944 di = (var->weight + 1) * DEC_DIGITS + rscale;
4947 * If di <= 0, the value loses all digits.
4953 var->sign = NUMERIC_POS;
4957 /* NBASE digits wanted */
4958 ndigits = (di + DEC_DIGITS-1) / DEC_DIGITS;
4960 if (ndigits <= var->ndigits)
4962 var->ndigits = ndigits;
4965 /* no within-digit stuff to worry about */
4967 /* 0, or number of decimal digits to keep in last NBASE digit */
4972 /* Must truncate within last NBASE digit */
4973 NumericDigit *digits = var->digits;
4978 pow10 = round_powers[di];
4979 #elif DEC_DIGITS == 2
4982 #error unsupported NBASE
4984 extra = digits[--ndigits] % pow10;
4985 digits[ndigits] -= extra;
4995 * Strip any leading and trailing zeroes from a numeric variable
4998 strip_var(NumericVar *var)
5000 NumericDigit *digits = var->digits;
5001 int ndigits = var->ndigits;
5003 /* Strip leading zeroes */
5004 while (ndigits > 0 && *digits == 0)
5011 /* Strip trailing zeroes */
5012 while (ndigits > 0 && digits[ndigits - 1] == 0)
5015 /* If it's zero, normalize the sign and weight */
5018 var->sign = NUMERIC_POS;
5022 var->digits = digits;
5023 var->ndigits = ndigits;