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 * $PostgreSQL: pgsql/src/backend/utils/adt/numeric.c,v 1.70 2003/12/02 00:26:59 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};
170 #elif DEC_DIGITS == 2
171 static NumericDigit const_zero_point_five_data[1] = {50};
173 #elif DEC_DIGITS == 1
174 static NumericDigit const_zero_point_five_data[1] = {5};
176 static NumericVar const_zero_point_five =
177 {1, -1, NUMERIC_POS, 1, NULL, const_zero_point_five_data};
180 static NumericDigit const_zero_point_nine_data[1] = {9000};
182 #elif DEC_DIGITS == 2
183 static NumericDigit const_zero_point_nine_data[1] = {90};
185 #elif DEC_DIGITS == 1
186 static NumericDigit const_zero_point_nine_data[1] = {9};
188 static NumericVar const_zero_point_nine =
189 {1, -1, NUMERIC_POS, 1, NULL, const_zero_point_nine_data};
192 static NumericDigit const_zero_point_01_data[1] = {100};
193 static NumericVar const_zero_point_01 =
194 {1, -1, NUMERIC_POS, 2, NULL, const_zero_point_01_data};
196 #elif DEC_DIGITS == 2
197 static NumericDigit const_zero_point_01_data[1] = {1};
198 static NumericVar const_zero_point_01 =
199 {1, -1, NUMERIC_POS, 2, NULL, const_zero_point_01_data};
201 #elif DEC_DIGITS == 1
202 static NumericDigit const_zero_point_01_data[1] = {1};
203 static NumericVar const_zero_point_01 =
204 {1, -2, NUMERIC_POS, 2, NULL, const_zero_point_01_data};
208 static NumericDigit const_one_point_one_data[2] = {1, 1000};
210 #elif DEC_DIGITS == 2
211 static NumericDigit const_one_point_one_data[2] = {1, 10};
213 #elif DEC_DIGITS == 1
214 static NumericDigit const_one_point_one_data[2] = {1, 1};
216 static NumericVar const_one_point_one =
217 {2, 0, NUMERIC_POS, 1, NULL, const_one_point_one_data};
219 static NumericVar const_nan =
220 {0, 0, NUMERIC_NAN, 0, NULL, NULL};
223 static const int round_powers[4] = {0, 1000, 100, 10};
233 static void dump_numeric(const char *str, Numeric num);
234 static void dump_var(const char *str, NumericVar *var);
237 #define dump_numeric(s,n)
238 #define dump_var(s,v)
241 #define digitbuf_alloc(ndigits) \
242 ((NumericDigit *) palloc((ndigits) * sizeof(NumericDigit)))
243 #define digitbuf_free(buf) \
249 #define init_var(v) MemSetAligned(v, 0, sizeof(NumericVar))
251 static void alloc_var(NumericVar *var, int ndigits);
252 static void free_var(NumericVar *var);
253 static void zero_var(NumericVar *var);
255 static void set_var_from_str(const char *str, NumericVar *dest);
256 static void set_var_from_num(Numeric value, NumericVar *dest);
257 static void set_var_from_var(NumericVar *value, NumericVar *dest);
258 static char *get_str_from_var(NumericVar *var, int dscale);
260 static Numeric make_result(NumericVar *var);
262 static void apply_typmod(NumericVar *var, int32 typmod);
264 static bool numericvar_to_int8(NumericVar *var, int64 *result);
265 static void int8_to_numericvar(int64 val, NumericVar *var);
266 static double numeric_to_double_no_overflow(Numeric num);
267 static double numericvar_to_double_no_overflow(NumericVar *var);
269 static int cmp_numerics(Numeric num1, Numeric num2);
270 static int cmp_var(NumericVar *var1, NumericVar *var2);
271 static void add_var(NumericVar *var1, NumericVar *var2, NumericVar *result);
272 static void sub_var(NumericVar *var1, NumericVar *var2, NumericVar *result);
273 static void mul_var(NumericVar *var1, NumericVar *var2, NumericVar *result,
275 static void div_var(NumericVar *var1, NumericVar *var2, NumericVar *result,
277 static int select_div_scale(NumericVar *var1, NumericVar *var2);
278 static void mod_var(NumericVar *var1, NumericVar *var2, NumericVar *result);
279 static void ceil_var(NumericVar *var, NumericVar *result);
280 static void floor_var(NumericVar *var, NumericVar *result);
282 static void sqrt_var(NumericVar *arg, NumericVar *result, int rscale);
283 static void exp_var(NumericVar *arg, NumericVar *result, int rscale);
284 static void exp_var_internal(NumericVar *arg, NumericVar *result, int rscale);
285 static void ln_var(NumericVar *arg, NumericVar *result, int rscale);
286 static void log_var(NumericVar *base, NumericVar *num, NumericVar *result);
287 static void power_var(NumericVar *base, NumericVar *exp, NumericVar *result);
288 static void power_var_int(NumericVar *base, int exp, NumericVar *result,
291 static int cmp_abs(NumericVar *var1, NumericVar *var2);
292 static void add_abs(NumericVar *var1, NumericVar *var2, NumericVar *result);
293 static void sub_abs(NumericVar *var1, NumericVar *var2, NumericVar *result);
294 static void round_var(NumericVar *var, int rscale);
295 static void trunc_var(NumericVar *var, int rscale);
296 static void strip_var(NumericVar *var);
299 /* ----------------------------------------------------------------------
301 * Input-, output- and rounding-functions
303 * ----------------------------------------------------------------------
310 * Input function for numeric data type
313 numeric_in(PG_FUNCTION_ARGS)
315 char *str = PG_GETARG_CSTRING(0);
318 Oid typelem = PG_GETARG_OID(1);
320 int32 typmod = PG_GETARG_INT32(2);
327 if (strcasecmp(str, "NaN") == 0)
328 PG_RETURN_NUMERIC(make_result(&const_nan));
331 * Use set_var_from_str() to parse the input string and return it in
332 * the packed DB storage format
335 set_var_from_str(str, &value);
337 apply_typmod(&value, typmod);
339 res = make_result(&value);
342 PG_RETURN_NUMERIC(res);
349 * Output function for numeric data type
352 numeric_out(PG_FUNCTION_ARGS)
354 Numeric num = PG_GETARG_NUMERIC(0);
361 if (NUMERIC_IS_NAN(num))
362 PG_RETURN_CSTRING(pstrdup("NaN"));
365 * Get the number in the variable format.
367 * Even if we didn't need to change format, we'd still need to copy the
368 * value to have a modifiable copy for rounding. set_var_from_num()
369 * also guarantees there is extra digit space in case we produce a
370 * carry out from rounding.
373 set_var_from_num(num, &x);
375 str = get_str_from_var(&x, x.dscale);
379 PG_RETURN_CSTRING(str);
383 * numeric_recv - converts external binary format to numeric
385 * External format is a sequence of int16's:
386 * ndigits, weight, sign, dscale, NumericDigits.
389 numeric_recv(PG_FUNCTION_ARGS)
391 StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
399 len = (uint16) pq_getmsgint(buf, sizeof(uint16));
400 if (len < 0 || len > NUMERIC_MAX_PRECISION + NUMERIC_MAX_RESULT_SCALE)
402 (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
403 errmsg("invalid length in external \"numeric\" value")));
405 alloc_var(&value, len);
407 value.weight = (int16) pq_getmsgint(buf, sizeof(int16));
408 value.sign = (uint16) pq_getmsgint(buf, sizeof(uint16));
409 if (!(value.sign == NUMERIC_POS ||
410 value.sign == NUMERIC_NEG ||
411 value.sign == NUMERIC_NAN))
413 (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
414 errmsg("invalid sign in external \"numeric\" value")));
416 value.dscale = (uint16) pq_getmsgint(buf, sizeof(uint16));
417 for (i = 0; i < len; i++)
419 NumericDigit d = pq_getmsgint(buf, sizeof(NumericDigit));
421 if (d < 0 || d >= NBASE)
423 (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
424 errmsg("invalid digit in external \"numeric\" value")));
428 res = make_result(&value);
431 PG_RETURN_NUMERIC(res);
435 * numeric_send - converts numeric to binary format
438 numeric_send(PG_FUNCTION_ARGS)
440 Numeric num = PG_GETARG_NUMERIC(0);
446 set_var_from_num(num, &x);
448 pq_begintypsend(&buf);
450 pq_sendint(&buf, x.ndigits, sizeof(int16));
451 pq_sendint(&buf, x.weight, sizeof(int16));
452 pq_sendint(&buf, x.sign, sizeof(int16));
453 pq_sendint(&buf, x.dscale, sizeof(int16));
454 for (i = 0; i < x.ndigits; i++)
455 pq_sendint(&buf, x.digits[i], sizeof(NumericDigit));
459 PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
466 * This is a special function called by the Postgres database system
467 * before a value is stored in a tuple's attribute. The precision and
468 * scale of the attribute have to be applied on the value.
471 numeric(PG_FUNCTION_ARGS)
473 Numeric num = PG_GETARG_NUMERIC(0);
474 int32 typmod = PG_GETARG_INT32(1);
486 if (NUMERIC_IS_NAN(num))
487 PG_RETURN_NUMERIC(make_result(&const_nan));
490 * If the value isn't a valid type modifier, simply return a copy of
493 if (typmod < (int32) (VARHDRSZ))
495 new = (Numeric) palloc(num->varlen);
496 memcpy(new, num, num->varlen);
497 PG_RETURN_NUMERIC(new);
501 * Get the precision and scale out of the typmod value
503 tmp_typmod = typmod - VARHDRSZ;
504 precision = (tmp_typmod >> 16) & 0xffff;
505 scale = tmp_typmod & 0xffff;
506 maxdigits = precision - scale;
509 * If the number is certainly in bounds and due to the target scale no
510 * rounding could be necessary, just make a copy of the input and
511 * modify its scale fields. (Note we assume the existing dscale is
514 ddigits = (num->n_weight + 1) * DEC_DIGITS;
515 if (ddigits <= maxdigits && scale >= NUMERIC_DSCALE(num))
517 new = (Numeric) palloc(num->varlen);
518 memcpy(new, num, num->varlen);
519 new->n_sign_dscale = NUMERIC_SIGN(new) |
520 ((uint16) scale & NUMERIC_DSCALE_MASK);
521 PG_RETURN_NUMERIC(new);
525 * We really need to fiddle with things - unpack the number into a
526 * variable and let apply_typmod() do it.
530 set_var_from_num(num, &var);
531 apply_typmod(&var, typmod);
532 new = make_result(&var);
536 PG_RETURN_NUMERIC(new);
540 /* ----------------------------------------------------------------------
542 * Sign manipulation, rounding and the like
544 * ----------------------------------------------------------------------
548 numeric_abs(PG_FUNCTION_ARGS)
550 Numeric num = PG_GETARG_NUMERIC(0);
556 if (NUMERIC_IS_NAN(num))
557 PG_RETURN_NUMERIC(make_result(&const_nan));
560 * Do it the easy way directly on the packed format
562 res = (Numeric) palloc(num->varlen);
563 memcpy(res, num, num->varlen);
565 res->n_sign_dscale = NUMERIC_POS | NUMERIC_DSCALE(num);
567 PG_RETURN_NUMERIC(res);
572 numeric_uminus(PG_FUNCTION_ARGS)
574 Numeric num = PG_GETARG_NUMERIC(0);
580 if (NUMERIC_IS_NAN(num))
581 PG_RETURN_NUMERIC(make_result(&const_nan));
584 * Do it the easy way directly on the packed format
586 res = (Numeric) palloc(num->varlen);
587 memcpy(res, num, num->varlen);
590 * The packed format is known to be totally zero digit trimmed always.
591 * So we can identify a ZERO by the fact that there are no digits at
592 * all. Do nothing to a zero.
594 if (num->varlen != NUMERIC_HDRSZ)
596 /* Else, flip the sign */
597 if (NUMERIC_SIGN(num) == NUMERIC_POS)
598 res->n_sign_dscale = NUMERIC_NEG | NUMERIC_DSCALE(num);
600 res->n_sign_dscale = NUMERIC_POS | NUMERIC_DSCALE(num);
603 PG_RETURN_NUMERIC(res);
608 numeric_uplus(PG_FUNCTION_ARGS)
610 Numeric num = PG_GETARG_NUMERIC(0);
613 res = (Numeric) palloc(num->varlen);
614 memcpy(res, num, num->varlen);
616 PG_RETURN_NUMERIC(res);
622 * returns -1 if the argument is less than 0, 0 if the argument is equal
623 * to 0, and 1 if the argument is greater than zero.
626 numeric_sign(PG_FUNCTION_ARGS)
628 Numeric num = PG_GETARG_NUMERIC(0);
635 if (NUMERIC_IS_NAN(num))
636 PG_RETURN_NUMERIC(make_result(&const_nan));
641 * The packed format is known to be totally zero digit trimmed always.
642 * So we can identify a ZERO by the fact that there are no digits at
645 if (num->varlen == NUMERIC_HDRSZ)
646 set_var_from_var(&const_zero, &result);
650 * And if there are some, we return a copy of ONE with the sign of
653 set_var_from_var(&const_one, &result);
654 result.sign = NUMERIC_SIGN(num);
657 res = make_result(&result);
660 PG_RETURN_NUMERIC(res);
667 * Round a value to have 'scale' digits after the decimal point.
668 * We allow negative 'scale', implying rounding before the decimal
669 * point --- Oracle interprets rounding that way.
672 numeric_round(PG_FUNCTION_ARGS)
674 Numeric num = PG_GETARG_NUMERIC(0);
675 int32 scale = PG_GETARG_INT32(1);
682 if (NUMERIC_IS_NAN(num))
683 PG_RETURN_NUMERIC(make_result(&const_nan));
686 * Limit the scale value to avoid possible overflow in calculations
688 scale = Max(scale, -NUMERIC_MAX_RESULT_SCALE);
689 scale = Min(scale, NUMERIC_MAX_RESULT_SCALE);
692 * Unpack the argument and round it at the proper digit position
695 set_var_from_num(num, &arg);
697 round_var(&arg, scale);
699 /* We don't allow negative output dscale */
704 * Return the rounded result
706 res = make_result(&arg);
709 PG_RETURN_NUMERIC(res);
716 * Truncate a value to have 'scale' digits after the decimal point.
717 * We allow negative 'scale', implying a truncation before the decimal
718 * point --- Oracle interprets truncation that way.
721 numeric_trunc(PG_FUNCTION_ARGS)
723 Numeric num = PG_GETARG_NUMERIC(0);
724 int32 scale = PG_GETARG_INT32(1);
731 if (NUMERIC_IS_NAN(num))
732 PG_RETURN_NUMERIC(make_result(&const_nan));
735 * Limit the scale value to avoid possible overflow in calculations
737 scale = Max(scale, -NUMERIC_MAX_RESULT_SCALE);
738 scale = Min(scale, NUMERIC_MAX_RESULT_SCALE);
741 * Unpack the argument and truncate it at the proper digit position
744 set_var_from_num(num, &arg);
746 trunc_var(&arg, scale);
748 /* We don't allow negative output dscale */
753 * Return the truncated result
755 res = make_result(&arg);
758 PG_RETURN_NUMERIC(res);
765 * Return the smallest integer greater than or equal to the argument
768 numeric_ceil(PG_FUNCTION_ARGS)
770 Numeric num = PG_GETARG_NUMERIC(0);
774 if (NUMERIC_IS_NAN(num))
775 PG_RETURN_NUMERIC(make_result(&const_nan));
779 set_var_from_num(num, &result);
780 ceil_var(&result, &result);
782 res = make_result(&result);
785 PG_RETURN_NUMERIC(res);
792 * Return the largest integer equal to or less than the argument
795 numeric_floor(PG_FUNCTION_ARGS)
797 Numeric num = PG_GETARG_NUMERIC(0);
801 if (NUMERIC_IS_NAN(num))
802 PG_RETURN_NUMERIC(make_result(&const_nan));
806 set_var_from_num(num, &result);
807 floor_var(&result, &result);
809 res = make_result(&result);
812 PG_RETURN_NUMERIC(res);
816 /* ----------------------------------------------------------------------
818 * Comparison functions
820 * Note: btree indexes need these routines not to leak memory; therefore,
821 * be careful to free working copies of toasted datums. Most places don't
822 * need to be so careful.
823 * ----------------------------------------------------------------------
828 numeric_cmp(PG_FUNCTION_ARGS)
830 Numeric num1 = PG_GETARG_NUMERIC(0);
831 Numeric num2 = PG_GETARG_NUMERIC(1);
834 result = cmp_numerics(num1, num2);
836 PG_FREE_IF_COPY(num1, 0);
837 PG_FREE_IF_COPY(num2, 1);
839 PG_RETURN_INT32(result);
844 numeric_eq(PG_FUNCTION_ARGS)
846 Numeric num1 = PG_GETARG_NUMERIC(0);
847 Numeric num2 = PG_GETARG_NUMERIC(1);
850 result = cmp_numerics(num1, num2) == 0;
852 PG_FREE_IF_COPY(num1, 0);
853 PG_FREE_IF_COPY(num2, 1);
855 PG_RETURN_BOOL(result);
859 numeric_ne(PG_FUNCTION_ARGS)
861 Numeric num1 = PG_GETARG_NUMERIC(0);
862 Numeric num2 = PG_GETARG_NUMERIC(1);
865 result = cmp_numerics(num1, num2) != 0;
867 PG_FREE_IF_COPY(num1, 0);
868 PG_FREE_IF_COPY(num2, 1);
870 PG_RETURN_BOOL(result);
874 numeric_gt(PG_FUNCTION_ARGS)
876 Numeric num1 = PG_GETARG_NUMERIC(0);
877 Numeric num2 = PG_GETARG_NUMERIC(1);
880 result = cmp_numerics(num1, num2) > 0;
882 PG_FREE_IF_COPY(num1, 0);
883 PG_FREE_IF_COPY(num2, 1);
885 PG_RETURN_BOOL(result);
889 numeric_ge(PG_FUNCTION_ARGS)
891 Numeric num1 = PG_GETARG_NUMERIC(0);
892 Numeric num2 = PG_GETARG_NUMERIC(1);
895 result = cmp_numerics(num1, num2) >= 0;
897 PG_FREE_IF_COPY(num1, 0);
898 PG_FREE_IF_COPY(num2, 1);
900 PG_RETURN_BOOL(result);
904 numeric_lt(PG_FUNCTION_ARGS)
906 Numeric num1 = PG_GETARG_NUMERIC(0);
907 Numeric num2 = PG_GETARG_NUMERIC(1);
910 result = cmp_numerics(num1, num2) < 0;
912 PG_FREE_IF_COPY(num1, 0);
913 PG_FREE_IF_COPY(num2, 1);
915 PG_RETURN_BOOL(result);
919 numeric_le(PG_FUNCTION_ARGS)
921 Numeric num1 = PG_GETARG_NUMERIC(0);
922 Numeric num2 = PG_GETARG_NUMERIC(1);
925 result = cmp_numerics(num1, num2) <= 0;
927 PG_FREE_IF_COPY(num1, 0);
928 PG_FREE_IF_COPY(num2, 1);
930 PG_RETURN_BOOL(result);
934 cmp_numerics(Numeric num1, Numeric num2)
939 * We consider all NANs to be equal and larger than any non-NAN. This
940 * is somewhat arbitrary; the important thing is to have a consistent
943 if (NUMERIC_IS_NAN(num1))
945 if (NUMERIC_IS_NAN(num2))
946 result = 0; /* NAN = NAN */
948 result = 1; /* NAN > non-NAN */
950 else if (NUMERIC_IS_NAN(num2))
952 result = -1; /* non-NAN < NAN */
962 set_var_from_num(num1, &arg1);
963 set_var_from_num(num2, &arg2);
965 result = cmp_var(&arg1, &arg2);
975 /* ----------------------------------------------------------------------
977 * Basic arithmetic functions
979 * ----------------------------------------------------------------------
989 numeric_add(PG_FUNCTION_ARGS)
991 Numeric num1 = PG_GETARG_NUMERIC(0);
992 Numeric num2 = PG_GETARG_NUMERIC(1);
1001 if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
1002 PG_RETURN_NUMERIC(make_result(&const_nan));
1005 * Unpack the values, let add_var() compute the result and return it.
1011 set_var_from_num(num1, &arg1);
1012 set_var_from_num(num2, &arg2);
1014 add_var(&arg1, &arg2, &result);
1016 res = make_result(&result);
1022 PG_RETURN_NUMERIC(res);
1029 * Subtract one numeric from another
1032 numeric_sub(PG_FUNCTION_ARGS)
1034 Numeric num1 = PG_GETARG_NUMERIC(0);
1035 Numeric num2 = PG_GETARG_NUMERIC(1);
1044 if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
1045 PG_RETURN_NUMERIC(make_result(&const_nan));
1048 * Unpack the values, let sub_var() compute the result and return it.
1054 set_var_from_num(num1, &arg1);
1055 set_var_from_num(num2, &arg2);
1057 sub_var(&arg1, &arg2, &result);
1059 res = make_result(&result);
1065 PG_RETURN_NUMERIC(res);
1072 * Calculate the product of two numerics
1075 numeric_mul(PG_FUNCTION_ARGS)
1077 Numeric num1 = PG_GETARG_NUMERIC(0);
1078 Numeric num2 = PG_GETARG_NUMERIC(1);
1087 if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
1088 PG_RETURN_NUMERIC(make_result(&const_nan));
1091 * Unpack the values, let mul_var() compute the result and return it.
1092 * Unlike add_var() and sub_var(), mul_var() will round its result. In
1093 * the case of numeric_mul(), which is invoked for the * operator on
1094 * numerics, we request exact representation for the product (rscale =
1095 * sum(dscale of arg1, dscale of arg2)).
1101 set_var_from_num(num1, &arg1);
1102 set_var_from_num(num2, &arg2);
1104 mul_var(&arg1, &arg2, &result, arg1.dscale + arg2.dscale);
1106 res = make_result(&result);
1112 PG_RETURN_NUMERIC(res);
1119 * Divide one numeric into another
1122 numeric_div(PG_FUNCTION_ARGS)
1124 Numeric num1 = PG_GETARG_NUMERIC(0);
1125 Numeric num2 = PG_GETARG_NUMERIC(1);
1135 if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
1136 PG_RETURN_NUMERIC(make_result(&const_nan));
1139 * Unpack the arguments
1145 set_var_from_num(num1, &arg1);
1146 set_var_from_num(num2, &arg2);
1149 * Select scale for division result
1151 rscale = select_div_scale(&arg1, &arg2);
1154 * Do the divide and return the result
1156 div_var(&arg1, &arg2, &result, rscale);
1158 res = make_result(&result);
1164 PG_RETURN_NUMERIC(res);
1171 * Calculate the modulo of two numerics
1174 numeric_mod(PG_FUNCTION_ARGS)
1176 Numeric num1 = PG_GETARG_NUMERIC(0);
1177 Numeric num2 = PG_GETARG_NUMERIC(1);
1183 if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
1184 PG_RETURN_NUMERIC(make_result(&const_nan));
1190 set_var_from_num(num1, &arg1);
1191 set_var_from_num(num2, &arg2);
1193 mod_var(&arg1, &arg2, &result);
1195 res = make_result(&result);
1201 PG_RETURN_NUMERIC(res);
1208 * Increment a number by one
1211 numeric_inc(PG_FUNCTION_ARGS)
1213 Numeric num = PG_GETARG_NUMERIC(0);
1220 if (NUMERIC_IS_NAN(num))
1221 PG_RETURN_NUMERIC(make_result(&const_nan));
1224 * Compute the result and return it
1228 set_var_from_num(num, &arg);
1230 add_var(&arg, &const_one, &arg);
1232 res = make_result(&arg);
1236 PG_RETURN_NUMERIC(res);
1241 * numeric_smaller() -
1243 * Return the smaller of two numbers
1246 numeric_smaller(PG_FUNCTION_ARGS)
1248 Numeric num1 = PG_GETARG_NUMERIC(0);
1249 Numeric num2 = PG_GETARG_NUMERIC(1);
1252 * Use cmp_numerics so that this will agree with the comparison
1253 * operators, particularly as regards comparisons involving NaN.
1255 if (cmp_numerics(num1, num2) < 0)
1256 PG_RETURN_NUMERIC(num1);
1258 PG_RETURN_NUMERIC(num2);
1263 * numeric_larger() -
1265 * Return the larger of two numbers
1268 numeric_larger(PG_FUNCTION_ARGS)
1270 Numeric num1 = PG_GETARG_NUMERIC(0);
1271 Numeric num2 = PG_GETARG_NUMERIC(1);
1274 * Use cmp_numerics so that this will agree with the comparison
1275 * operators, particularly as regards comparisons involving NaN.
1277 if (cmp_numerics(num1, num2) > 0)
1278 PG_RETURN_NUMERIC(num1);
1280 PG_RETURN_NUMERIC(num2);
1284 /* ----------------------------------------------------------------------
1286 * Advanced math functions
1288 * ----------------------------------------------------------------------
1297 numeric_fac(PG_FUNCTION_ARGS)
1299 int64 num = PG_GETARG_INT64(0);
1306 res = make_result(&const_one);
1307 PG_RETURN_NUMERIC(res);
1313 int8_to_numericvar(num, &result);
1315 for (num = num - 1; num > 1; num--)
1317 int8_to_numericvar(num, &fact);
1319 mul_var(&result, &fact, &result, 0);
1322 res = make_result(&result);
1327 PG_RETURN_NUMERIC(res);
1334 * Compute the square root of a numeric.
1337 numeric_sqrt(PG_FUNCTION_ARGS)
1339 Numeric num = PG_GETARG_NUMERIC(0);
1349 if (NUMERIC_IS_NAN(num))
1350 PG_RETURN_NUMERIC(make_result(&const_nan));
1353 * Unpack the argument and determine the result scale. We choose a
1354 * scale to give at least NUMERIC_MIN_SIG_DIGITS significant digits;
1355 * but in any case not less than the input's dscale.
1360 set_var_from_num(num, &arg);
1362 /* Assume the input was normalized, so arg.weight is accurate */
1363 sweight = (arg.weight + 1) * DEC_DIGITS / 2 - 1;
1365 rscale = NUMERIC_MIN_SIG_DIGITS - sweight;
1366 rscale = Max(rscale, arg.dscale);
1367 rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
1368 rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
1371 * Let sqrt_var() do the calculation and return the result.
1373 sqrt_var(&arg, &result, rscale);
1375 res = make_result(&result);
1380 PG_RETURN_NUMERIC(res);
1387 * Raise e to the power of x
1390 numeric_exp(PG_FUNCTION_ARGS)
1392 Numeric num = PG_GETARG_NUMERIC(0);
1402 if (NUMERIC_IS_NAN(num))
1403 PG_RETURN_NUMERIC(make_result(&const_nan));
1406 * Unpack the argument and determine the result scale. We choose a
1407 * scale to give at least NUMERIC_MIN_SIG_DIGITS significant digits;
1408 * but in any case not less than the input's dscale.
1413 set_var_from_num(num, &arg);
1415 /* convert input to float8, ignoring overflow */
1416 val = numericvar_to_double_no_overflow(&arg);
1419 * log10(result) = num * log10(e), so this is approximately the
1420 * decimal weight of the result:
1422 val *= 0.434294481903252;
1424 /* limit to something that won't cause integer overflow */
1425 val = Max(val, -NUMERIC_MAX_RESULT_SCALE);
1426 val = Min(val, NUMERIC_MAX_RESULT_SCALE);
1428 rscale = NUMERIC_MIN_SIG_DIGITS - (int) val;
1429 rscale = Max(rscale, arg.dscale);
1430 rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
1431 rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
1434 * Let exp_var() do the calculation and return the result.
1436 exp_var(&arg, &result, rscale);
1438 res = make_result(&result);
1443 PG_RETURN_NUMERIC(res);
1450 * Compute the natural logarithm of x
1453 numeric_ln(PG_FUNCTION_ARGS)
1455 Numeric num = PG_GETARG_NUMERIC(0);
1465 if (NUMERIC_IS_NAN(num))
1466 PG_RETURN_NUMERIC(make_result(&const_nan));
1471 set_var_from_num(num, &arg);
1473 /* Approx decimal digits before decimal point */
1474 dec_digits = (arg.weight + 1) * DEC_DIGITS;
1477 rscale = NUMERIC_MIN_SIG_DIGITS - (int) log10(dec_digits - 1);
1478 else if (dec_digits < 1)
1479 rscale = NUMERIC_MIN_SIG_DIGITS - (int) log10(1 - dec_digits);
1481 rscale = NUMERIC_MIN_SIG_DIGITS;
1483 rscale = Max(rscale, arg.dscale);
1484 rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
1485 rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
1487 ln_var(&arg, &result, rscale);
1489 res = make_result(&result);
1494 PG_RETURN_NUMERIC(res);
1501 * Compute the logarithm of x in a given base
1504 numeric_log(PG_FUNCTION_ARGS)
1506 Numeric num1 = PG_GETARG_NUMERIC(0);
1507 Numeric num2 = PG_GETARG_NUMERIC(1);
1516 if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
1517 PG_RETURN_NUMERIC(make_result(&const_nan));
1526 set_var_from_num(num1, &arg1);
1527 set_var_from_num(num2, &arg2);
1530 * Call log_var() to compute and return the result; note it handles
1531 * scale selection itself.
1533 log_var(&arg1, &arg2, &result);
1535 res = make_result(&result);
1541 PG_RETURN_NUMERIC(res);
1548 * Raise b to the power of x
1551 numeric_power(PG_FUNCTION_ARGS)
1553 Numeric num1 = PG_GETARG_NUMERIC(0);
1554 Numeric num2 = PG_GETARG_NUMERIC(1);
1563 if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
1564 PG_RETURN_NUMERIC(make_result(&const_nan));
1573 set_var_from_num(num1, &arg1);
1574 set_var_from_num(num2, &arg2);
1577 * Call power_var() to compute and return the result; note it handles
1578 * scale selection itself.
1580 power_var(&arg1, &arg2, &result);
1582 res = make_result(&result);
1588 PG_RETURN_NUMERIC(res);
1592 /* ----------------------------------------------------------------------
1594 * Type conversion functions
1596 * ----------------------------------------------------------------------
1601 int4_numeric(PG_FUNCTION_ARGS)
1603 int32 val = PG_GETARG_INT32(0);
1609 int8_to_numericvar((int64) val, &result);
1611 res = make_result(&result);
1615 PG_RETURN_NUMERIC(res);
1620 numeric_int4(PG_FUNCTION_ARGS)
1622 Numeric num = PG_GETARG_NUMERIC(0);
1627 /* XXX would it be better to return NULL? */
1628 if (NUMERIC_IS_NAN(num))
1630 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1631 errmsg("cannot convert NaN to integer")));
1633 /* Convert to variable format and thence to int8 */
1635 set_var_from_num(num, &x);
1637 if (!numericvar_to_int8(&x, &val))
1639 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1640 errmsg("integer out of range")));
1644 /* Down-convert to int4 */
1645 result = (int32) val;
1647 /* Test for overflow by reverse-conversion. */
1648 if ((int64) result != val)
1650 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1651 errmsg("integer out of range")));
1653 PG_RETURN_INT32(result);
1658 int8_numeric(PG_FUNCTION_ARGS)
1660 int64 val = PG_GETARG_INT64(0);
1666 int8_to_numericvar(val, &result);
1668 res = make_result(&result);
1672 PG_RETURN_NUMERIC(res);
1677 numeric_int8(PG_FUNCTION_ARGS)
1679 Numeric num = PG_GETARG_NUMERIC(0);
1683 /* XXX would it be better to return NULL? */
1684 if (NUMERIC_IS_NAN(num))
1686 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1687 errmsg("cannot convert NaN to integer")));
1689 /* Convert to variable format and thence to int8 */
1691 set_var_from_num(num, &x);
1693 if (!numericvar_to_int8(&x, &result))
1695 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1696 errmsg("integer out of range")));
1700 PG_RETURN_INT64(result);
1705 int2_numeric(PG_FUNCTION_ARGS)
1707 int16 val = PG_GETARG_INT16(0);
1713 int8_to_numericvar((int64) val, &result);
1715 res = make_result(&result);
1719 PG_RETURN_NUMERIC(res);
1724 numeric_int2(PG_FUNCTION_ARGS)
1726 Numeric num = PG_GETARG_NUMERIC(0);
1731 /* XXX would it be better to return NULL? */
1732 if (NUMERIC_IS_NAN(num))
1734 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1735 errmsg("cannot convert NaN to integer")));
1737 /* Convert to variable format and thence to int8 */
1739 set_var_from_num(num, &x);
1741 if (!numericvar_to_int8(&x, &val))
1743 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1744 errmsg("integer out of range")));
1748 /* Down-convert to int2 */
1749 result = (int16) val;
1751 /* Test for overflow by reverse-conversion. */
1752 if ((int64) result != val)
1754 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1755 errmsg("integer out of range")));
1757 PG_RETURN_INT16(result);
1762 float8_numeric(PG_FUNCTION_ARGS)
1764 float8 val = PG_GETARG_FLOAT8(0);
1767 char buf[DBL_DIG + 100];
1770 PG_RETURN_NUMERIC(make_result(&const_nan));
1772 sprintf(buf, "%.*g", DBL_DIG, val);
1776 set_var_from_str(buf, &result);
1777 res = make_result(&result);
1781 PG_RETURN_NUMERIC(res);
1786 numeric_float8(PG_FUNCTION_ARGS)
1788 Numeric num = PG_GETARG_NUMERIC(0);
1792 if (NUMERIC_IS_NAN(num))
1793 PG_RETURN_FLOAT8(NAN);
1795 tmp = DatumGetCString(DirectFunctionCall1(numeric_out,
1796 NumericGetDatum(num)));
1798 result = DirectFunctionCall1(float8in, CStringGetDatum(tmp));
1802 PG_RETURN_DATUM(result);
1806 /* Convert numeric to float8; if out of range, return +/- HUGE_VAL */
1808 numeric_float8_no_overflow(PG_FUNCTION_ARGS)
1810 Numeric num = PG_GETARG_NUMERIC(0);
1813 if (NUMERIC_IS_NAN(num))
1814 PG_RETURN_FLOAT8(NAN);
1816 val = numeric_to_double_no_overflow(num);
1818 PG_RETURN_FLOAT8(val);
1822 float4_numeric(PG_FUNCTION_ARGS)
1824 float4 val = PG_GETARG_FLOAT4(0);
1827 char buf[FLT_DIG + 100];
1830 PG_RETURN_NUMERIC(make_result(&const_nan));
1832 sprintf(buf, "%.*g", FLT_DIG, val);
1836 set_var_from_str(buf, &result);
1837 res = make_result(&result);
1841 PG_RETURN_NUMERIC(res);
1846 numeric_float4(PG_FUNCTION_ARGS)
1848 Numeric num = PG_GETARG_NUMERIC(0);
1852 if (NUMERIC_IS_NAN(num))
1853 PG_RETURN_FLOAT4((float4) NAN);
1855 tmp = DatumGetCString(DirectFunctionCall1(numeric_out,
1856 NumericGetDatum(num)));
1858 result = DirectFunctionCall1(float4in, CStringGetDatum(tmp));
1862 PG_RETURN_DATUM(result);
1867 text_numeric(PG_FUNCTION_ARGS)
1869 text *str = PG_GETARG_TEXT_P(0);
1874 len = (VARSIZE(str) - VARHDRSZ);
1875 s = palloc(len + 1);
1876 memcpy(s, VARDATA(str), len);
1879 result = DirectFunctionCall3(numeric_in, CStringGetDatum(s),
1880 ObjectIdGetDatum(0), Int32GetDatum(-1));
1888 numeric_text(PG_FUNCTION_ARGS)
1890 /* val is numeric, but easier to leave it as Datum */
1891 Datum val = PG_GETARG_DATUM(0);
1896 s = DatumGetCString(DirectFunctionCall1(numeric_out, val));
1899 result = (text *) palloc(VARHDRSZ + len);
1901 VARATT_SIZEP(result) = len + VARHDRSZ;
1902 memcpy(VARDATA(result), s, len);
1906 PG_RETURN_TEXT_P(result);
1910 /* ----------------------------------------------------------------------
1912 * Aggregate functions
1914 * The transition datatype for all these aggregates is a 3-element array
1915 * of Numeric, holding the values N, sum(X), sum(X*X) in that order.
1917 * We represent N as a numeric mainly to avoid having to build a special
1918 * datatype; it's unlikely it'd overflow an int4, but ...
1920 * ----------------------------------------------------------------------
1924 do_numeric_accum(ArrayType *transarray, Numeric newval)
1933 /* We assume the input is array of numeric */
1934 deconstruct_array(transarray,
1935 NUMERICOID, -1, false, 'i',
1936 &transdatums, &ndatums);
1938 elog(ERROR, "expected 3-element numeric array");
1940 sumX = transdatums[1];
1941 sumX2 = transdatums[2];
1943 N = DirectFunctionCall1(numeric_inc, N);
1944 sumX = DirectFunctionCall2(numeric_add, sumX,
1945 NumericGetDatum(newval));
1946 sumX2 = DirectFunctionCall2(numeric_add, sumX2,
1947 DirectFunctionCall2(numeric_mul,
1948 NumericGetDatum(newval),
1949 NumericGetDatum(newval)));
1952 transdatums[1] = sumX;
1953 transdatums[2] = sumX2;
1955 result = construct_array(transdatums, 3,
1956 NUMERICOID, -1, false, 'i');
1962 numeric_accum(PG_FUNCTION_ARGS)
1964 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
1965 Numeric newval = PG_GETARG_NUMERIC(1);
1967 PG_RETURN_ARRAYTYPE_P(do_numeric_accum(transarray, newval));
1971 * Integer data types all use Numeric accumulators to share code and
1972 * avoid risk of overflow. For int2 and int4 inputs, Numeric accumulation
1973 * is overkill for the N and sum(X) values, but definitely not overkill
1974 * for the sum(X*X) value. Hence, we use int2_accum and int4_accum only
1975 * for stddev/variance --- there are faster special-purpose accumulator
1976 * routines for SUM and AVG of these datatypes.
1980 int2_accum(PG_FUNCTION_ARGS)
1982 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
1983 Datum newval2 = PG_GETARG_DATUM(1);
1986 newval = DatumGetNumeric(DirectFunctionCall1(int2_numeric, newval2));
1988 PG_RETURN_ARRAYTYPE_P(do_numeric_accum(transarray, newval));
1992 int4_accum(PG_FUNCTION_ARGS)
1994 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
1995 Datum newval4 = PG_GETARG_DATUM(1);
1998 newval = DatumGetNumeric(DirectFunctionCall1(int4_numeric, newval4));
2000 PG_RETURN_ARRAYTYPE_P(do_numeric_accum(transarray, newval));
2004 int8_accum(PG_FUNCTION_ARGS)
2006 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
2007 Datum newval8 = PG_GETARG_DATUM(1);
2010 newval = DatumGetNumeric(DirectFunctionCall1(int8_numeric, newval8));
2012 PG_RETURN_ARRAYTYPE_P(do_numeric_accum(transarray, newval));
2016 numeric_avg(PG_FUNCTION_ARGS)
2018 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
2024 /* We assume the input is array of numeric */
2025 deconstruct_array(transarray,
2026 NUMERICOID, -1, false, 'i',
2027 &transdatums, &ndatums);
2029 elog(ERROR, "expected 3-element numeric array");
2030 N = DatumGetNumeric(transdatums[0]);
2031 sumX = DatumGetNumeric(transdatums[1]);
2034 /* SQL92 defines AVG of no values to be NULL */
2035 /* N is zero iff no digits (cf. numeric_uminus) */
2036 if (N->varlen == NUMERIC_HDRSZ)
2039 PG_RETURN_DATUM(DirectFunctionCall2(numeric_div,
2040 NumericGetDatum(sumX),
2041 NumericGetDatum(N)));
2045 numeric_variance(PG_FUNCTION_ARGS)
2047 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
2060 /* We assume the input is array of numeric */
2061 deconstruct_array(transarray,
2062 NUMERICOID, -1, false, 'i',
2063 &transdatums, &ndatums);
2065 elog(ERROR, "expected 3-element numeric array");
2066 N = DatumGetNumeric(transdatums[0]);
2067 sumX = DatumGetNumeric(transdatums[1]);
2068 sumX2 = DatumGetNumeric(transdatums[2]);
2070 if (NUMERIC_IS_NAN(N) || NUMERIC_IS_NAN(sumX) || NUMERIC_IS_NAN(sumX2))
2071 PG_RETURN_NUMERIC(make_result(&const_nan));
2073 /* Sample variance is undefined when N is 0 or 1, so return NULL */
2075 set_var_from_num(N, &vN);
2077 if (cmp_var(&vN, &const_one) <= 0)
2083 init_var(&vNminus1);
2084 sub_var(&vN, &const_one, &vNminus1);
2087 set_var_from_num(sumX, &vsumX);
2089 set_var_from_num(sumX2, &vsumX2);
2091 /* compute rscale for mul_var calls */
2092 rscale = vsumX.dscale * 2;
2094 mul_var(&vsumX, &vsumX, &vsumX, rscale); /* vsumX = sumX * sumX */
2095 mul_var(&vN, &vsumX2, &vsumX2, rscale); /* vsumX2 = N * sumX2 */
2096 sub_var(&vsumX2, &vsumX, &vsumX2); /* N * sumX2 - sumX * sumX */
2098 if (cmp_var(&vsumX2, &const_zero) <= 0)
2100 /* Watch out for roundoff error producing a negative numerator */
2101 res = make_result(&const_zero);
2105 mul_var(&vN, &vNminus1, &vNminus1, 0); /* N * (N - 1) */
2106 rscale = select_div_scale(&vsumX2, &vNminus1);
2107 div_var(&vsumX2, &vNminus1, &vsumX, rscale); /* variance */
2109 res = make_result(&vsumX);
2113 free_var(&vNminus1);
2117 PG_RETURN_NUMERIC(res);
2121 numeric_stddev(PG_FUNCTION_ARGS)
2123 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
2136 /* We assume the input is array of numeric */
2137 deconstruct_array(transarray,
2138 NUMERICOID, -1, false, 'i',
2139 &transdatums, &ndatums);
2141 elog(ERROR, "expected 3-element numeric array");
2142 N = DatumGetNumeric(transdatums[0]);
2143 sumX = DatumGetNumeric(transdatums[1]);
2144 sumX2 = DatumGetNumeric(transdatums[2]);
2146 if (NUMERIC_IS_NAN(N) || NUMERIC_IS_NAN(sumX) || NUMERIC_IS_NAN(sumX2))
2147 PG_RETURN_NUMERIC(make_result(&const_nan));
2149 /* Sample stddev is undefined when N is 0 or 1, so return NULL */
2151 set_var_from_num(N, &vN);
2153 if (cmp_var(&vN, &const_one) <= 0)
2159 init_var(&vNminus1);
2160 sub_var(&vN, &const_one, &vNminus1);
2163 set_var_from_num(sumX, &vsumX);
2165 set_var_from_num(sumX2, &vsumX2);
2167 /* compute rscale for mul_var calls */
2168 rscale = vsumX.dscale * 2;
2170 mul_var(&vsumX, &vsumX, &vsumX, rscale); /* vsumX = sumX * sumX */
2171 mul_var(&vN, &vsumX2, &vsumX2, rscale); /* vsumX2 = N * sumX2 */
2172 sub_var(&vsumX2, &vsumX, &vsumX2); /* N * sumX2 - sumX * sumX */
2174 if (cmp_var(&vsumX2, &const_zero) <= 0)
2176 /* Watch out for roundoff error producing a negative numerator */
2177 res = make_result(&const_zero);
2181 mul_var(&vN, &vNminus1, &vNminus1, 0); /* N * (N - 1) */
2182 rscale = select_div_scale(&vsumX2, &vNminus1);
2183 div_var(&vsumX2, &vNminus1, &vsumX, rscale); /* variance */
2184 sqrt_var(&vsumX, &vsumX, rscale); /* stddev */
2186 res = make_result(&vsumX);
2190 free_var(&vNminus1);
2194 PG_RETURN_NUMERIC(res);
2199 * SUM transition functions for integer datatypes.
2201 * To avoid overflow, we use accumulators wider than the input datatype.
2202 * A Numeric accumulator is needed for int8 input; for int4 and int2
2203 * inputs, we use int8 accumulators which should be sufficient for practical
2204 * purposes. (The latter two therefore don't really belong in this file,
2205 * but we keep them here anyway.)
2207 * Because SQL92 defines the SUM() of no values to be NULL, not zero,
2208 * the initial condition of the transition data value needs to be NULL. This
2209 * means we can't rely on ExecAgg to automatically insert the first non-null
2210 * data value into the transition data: it doesn't know how to do the type
2211 * conversion. The upshot is that these routines have to be marked non-strict
2212 * and handle substitution of the first non-null input themselves.
2216 int2_sum(PG_FUNCTION_ARGS)
2221 if (PG_ARGISNULL(0))
2223 /* No non-null input seen so far... */
2224 if (PG_ARGISNULL(1))
2225 PG_RETURN_NULL(); /* still no non-null */
2226 /* This is the first non-null input. */
2227 newval = (int64) PG_GETARG_INT16(1);
2228 PG_RETURN_INT64(newval);
2231 oldsum = PG_GETARG_INT64(0);
2233 /* Leave sum unchanged if new input is null. */
2234 if (PG_ARGISNULL(1))
2235 PG_RETURN_INT64(oldsum);
2237 /* OK to do the addition. */
2238 newval = oldsum + (int64) PG_GETARG_INT16(1);
2240 PG_RETURN_INT64(newval);
2244 int4_sum(PG_FUNCTION_ARGS)
2249 if (PG_ARGISNULL(0))
2251 /* No non-null input seen so far... */
2252 if (PG_ARGISNULL(1))
2253 PG_RETURN_NULL(); /* still no non-null */
2254 /* This is the first non-null input. */
2255 newval = (int64) PG_GETARG_INT32(1);
2256 PG_RETURN_INT64(newval);
2259 oldsum = PG_GETARG_INT64(0);
2261 /* Leave sum unchanged if new input is null. */
2262 if (PG_ARGISNULL(1))
2263 PG_RETURN_INT64(oldsum);
2265 /* OK to do the addition. */
2266 newval = oldsum + (int64) PG_GETARG_INT32(1);
2268 PG_RETURN_INT64(newval);
2272 int8_sum(PG_FUNCTION_ARGS)
2277 if (PG_ARGISNULL(0))
2279 /* No non-null input seen so far... */
2280 if (PG_ARGISNULL(1))
2281 PG_RETURN_NULL(); /* still no non-null */
2282 /* This is the first non-null input. */
2283 newval = DirectFunctionCall1(int8_numeric, PG_GETARG_DATUM(1));
2284 PG_RETURN_DATUM(newval);
2287 oldsum = PG_GETARG_NUMERIC(0);
2289 /* Leave sum unchanged if new input is null. */
2290 if (PG_ARGISNULL(1))
2291 PG_RETURN_NUMERIC(oldsum);
2293 /* OK to do the addition. */
2294 newval = DirectFunctionCall1(int8_numeric, PG_GETARG_DATUM(1));
2296 PG_RETURN_DATUM(DirectFunctionCall2(numeric_add,
2297 NumericGetDatum(oldsum), newval));
2302 * Routines for avg(int2) and avg(int4). The transition datatype
2303 * is a two-element int8 array, holding count and sum.
2306 typedef struct Int8TransTypeData
2308 #ifndef INT64_IS_BUSTED
2312 /* "int64" isn't really 64 bits, so fake up properly-aligned fields */
2318 } Int8TransTypeData;
2321 int2_avg_accum(PG_FUNCTION_ARGS)
2323 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P_COPY(0);
2324 int16 newval = PG_GETARG_INT16(1);
2325 Int8TransTypeData *transdata;
2328 * We copied the input array, so it's okay to scribble on it directly.
2330 if (ARR_SIZE(transarray) != ARR_OVERHEAD(1) + sizeof(Int8TransTypeData))
2331 elog(ERROR, "expected 2-element int8 array");
2332 transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
2335 transdata->sum += newval;
2337 PG_RETURN_ARRAYTYPE_P(transarray);
2341 int4_avg_accum(PG_FUNCTION_ARGS)
2343 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P_COPY(0);
2344 int32 newval = PG_GETARG_INT32(1);
2345 Int8TransTypeData *transdata;
2348 * We copied the input array, so it's okay to scribble on it directly.
2350 if (ARR_SIZE(transarray) != ARR_OVERHEAD(1) + sizeof(Int8TransTypeData))
2351 elog(ERROR, "expected 2-element int8 array");
2352 transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
2355 transdata->sum += newval;
2357 PG_RETURN_ARRAYTYPE_P(transarray);
2361 int8_avg(PG_FUNCTION_ARGS)
2363 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
2364 Int8TransTypeData *transdata;
2368 if (ARR_SIZE(transarray) != ARR_OVERHEAD(1) + sizeof(Int8TransTypeData))
2369 elog(ERROR, "expected 2-element int8 array");
2370 transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
2372 /* SQL92 defines AVG of no values to be NULL */
2373 if (transdata->count == 0)
2376 countd = DirectFunctionCall1(int8_numeric,
2377 Int64GetDatumFast(transdata->count));
2378 sumd = DirectFunctionCall1(int8_numeric,
2379 Int64GetDatumFast(transdata->sum));
2381 PG_RETURN_DATUM(DirectFunctionCall2(numeric_div, sumd, countd));
2385 /* ----------------------------------------------------------------------
2389 * ----------------------------------------------------------------------
2392 #ifdef NUMERIC_DEBUG
2395 * dump_numeric() - Dump a value in the db storage format for debugging
2398 dump_numeric(const char *str, Numeric num)
2400 NumericDigit *digits = (NumericDigit *) num->n_data;
2404 ndigits = (num->varlen - NUMERIC_HDRSZ) / sizeof(NumericDigit);
2406 printf("%s: NUMERIC w=%d d=%d ", str, num->n_weight, NUMERIC_DSCALE(num));
2407 switch (NUMERIC_SIGN(num))
2419 printf("SIGN=0x%x", NUMERIC_SIGN(num));
2423 for (i = 0; i < ndigits; i++)
2424 printf(" %0*d", DEC_DIGITS, digits[i]);
2430 * dump_var() - Dump a value in the variable format for debugging
2433 dump_var(const char *str, NumericVar *var)
2437 printf("%s: VAR w=%d d=%d ", str, var->weight, var->dscale);
2450 printf("SIGN=0x%x", var->sign);
2454 for (i = 0; i < var->ndigits; i++)
2455 printf(" %0*d", DEC_DIGITS, var->digits[i]);
2459 #endif /* NUMERIC_DEBUG */
2462 /* ----------------------------------------------------------------------
2464 * Local functions follow
2466 * In general, these do not support NaNs --- callers must eliminate
2467 * the possibility of NaN first. (make_result() is an exception.)
2469 * ----------------------------------------------------------------------
2476 * Allocate a digit buffer of ndigits digits (plus a spare digit for rounding)
2479 alloc_var(NumericVar *var, int ndigits)
2481 digitbuf_free(var->buf);
2482 var->buf = digitbuf_alloc(ndigits + 1);
2483 var->buf[0] = 0; /* spare digit for rounding */
2484 var->digits = var->buf + 1;
2485 var->ndigits = ndigits;
2492 * Return the digit buffer of a variable to the free pool
2495 free_var(NumericVar *var)
2497 digitbuf_free(var->buf);
2500 var->sign = NUMERIC_NAN;
2507 * Set a variable to ZERO.
2508 * Note: its dscale is not touched.
2511 zero_var(NumericVar *var)
2513 digitbuf_free(var->buf);
2517 var->weight = 0; /* by convention; doesn't really matter */
2518 var->sign = NUMERIC_POS; /* anything but NAN... */
2523 * set_var_from_str()
2525 * Parse a string and put the number into a variable
2528 set_var_from_str(const char *str, NumericVar *dest)
2530 const char *cp = str;
2531 bool have_dp = FALSE;
2533 unsigned char *decdigits;
2534 int sign = NUMERIC_POS;
2541 NumericDigit *digits;
2544 * We first parse the string to extract decimal digits and determine
2545 * the correct decimal weight. Then convert to NBASE representation.
2548 /* skip leading spaces */
2551 if (!isspace((unsigned char) *cp))
2575 if (!isdigit((unsigned char) *cp))
2577 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
2578 errmsg("invalid input syntax for type numeric: \"%s\"", str)));
2580 decdigits = (unsigned char *) palloc(strlen(cp) + DEC_DIGITS * 2);
2582 /* leading padding for digit alignment later */
2583 memset(decdigits, 0, DEC_DIGITS);
2588 if (isdigit((unsigned char) *cp))
2590 decdigits[i++] = *cp++ - '0';
2596 else if (*cp == '.')
2600 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
2601 errmsg("invalid input syntax for type numeric: \"%s\"",
2610 ddigits = i - DEC_DIGITS;
2611 /* trailing padding for digit alignment later */
2612 memset(decdigits + i, 0, DEC_DIGITS - 1);
2614 /* Handle exponent, if any */
2615 if (*cp == 'e' || *cp == 'E')
2621 exponent = strtol(cp, &endptr, 10);
2624 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
2625 errmsg("invalid input syntax for type numeric: \"%s\"",
2628 if (exponent > NUMERIC_MAX_PRECISION ||
2629 exponent < -NUMERIC_MAX_PRECISION)
2631 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
2632 errmsg("invalid input syntax for type numeric: \"%s\"",
2634 dweight += (int) exponent;
2635 dscale -= (int) exponent;
2640 /* Should be nothing left but spaces */
2643 if (!isspace((unsigned char) *cp))
2645 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
2646 errmsg("invalid input syntax for type numeric: \"%s\"",
2652 * Okay, convert pure-decimal representation to base NBASE. First we
2653 * need to determine the converted weight and ndigits. offset is the
2654 * number of decimal zeroes to insert before the first given digit to
2655 * have a correctly aligned first NBASE digit.
2658 weight = (dweight + 1 + DEC_DIGITS - 1) / DEC_DIGITS - 1;
2660 weight = -((-dweight - 1) / DEC_DIGITS + 1);
2661 offset = (weight + 1) * DEC_DIGITS - (dweight + 1);
2662 ndigits = (ddigits + offset + DEC_DIGITS - 1) / DEC_DIGITS;
2664 alloc_var(dest, ndigits);
2666 dest->weight = weight;
2667 dest->dscale = dscale;
2669 i = DEC_DIGITS - offset;
2670 digits = dest->digits;
2672 while (ndigits-- > 0)
2675 *digits++ = ((decdigits[i] * 10 + decdigits[i + 1]) * 10 +
2676 decdigits[i + 2]) * 10 + decdigits[i + 3];
2677 #elif DEC_DIGITS == 2
2678 *digits++ = decdigits[i] * 10 + decdigits[i + 1];
2679 #elif DEC_DIGITS == 1
2680 *digits++ = decdigits[i];
2682 #error unsupported NBASE
2689 /* Strip any leading/trailing zeroes, and normalize weight if zero */
2695 * set_var_from_num() -
2697 * Convert the packed db format into a variable
2700 set_var_from_num(Numeric num, NumericVar *dest)
2704 ndigits = (num->varlen - NUMERIC_HDRSZ) / sizeof(NumericDigit);
2706 alloc_var(dest, ndigits);
2708 dest->weight = num->n_weight;
2709 dest->sign = NUMERIC_SIGN(num);
2710 dest->dscale = NUMERIC_DSCALE(num);
2712 memcpy(dest->digits, num->n_data, ndigits * sizeof(NumericDigit));
2717 * set_var_from_var() -
2719 * Copy one variable into another
2722 set_var_from_var(NumericVar *value, NumericVar *dest)
2724 NumericDigit *newbuf;
2726 newbuf = digitbuf_alloc(value->ndigits + 1);
2727 newbuf[0] = 0; /* spare digit for rounding */
2728 memcpy(newbuf + 1, value->digits, value->ndigits * sizeof(NumericDigit));
2730 digitbuf_free(dest->buf);
2732 memcpy(dest, value, sizeof(NumericVar));
2734 dest->digits = newbuf + 1;
2739 * get_str_from_var() -
2741 * Convert a var to text representation (guts of numeric_out).
2742 * CAUTION: var's contents may be modified by rounding!
2743 * Returns a palloc'd string.
2746 get_str_from_var(NumericVar *var, int dscale)
2763 * Check if we must round up before printing the value and do so.
2765 round_var(var, dscale);
2768 * Allocate space for the result.
2770 * i is set to to # of decimal digits before decimal point. dscale is the
2771 * # of decimal digits we will print after decimal point. We may
2772 * generate as many as DEC_DIGITS-1 excess digits at the end, and in
2773 * addition we need room for sign, decimal point, null terminator.
2775 i = (var->weight + 1) * DEC_DIGITS;
2779 str = palloc(i + dscale + DEC_DIGITS + 2);
2783 * Output a dash for negative values
2785 if (var->sign == NUMERIC_NEG)
2789 * Output all digits before the decimal point
2791 if (var->weight < 0)
2793 d = var->weight + 1;
2798 for (d = 0; d <= var->weight; d++)
2800 dig = (d < var->ndigits) ? var->digits[d] : 0;
2801 /* In the first digit, suppress extra leading decimal zeroes */
2804 bool putit = (d > 0);
2823 #elif DEC_DIGITS == 2
2826 if (d1 > 0 || d > 0)
2829 #elif DEC_DIGITS == 1
2832 #error unsupported NBASE
2838 * If requested, output a decimal point and all the digits that follow
2839 * it. We initially put out a multiple of DEC_DIGITS digits, then
2840 * truncate if needed.
2845 endcp = cp + dscale;
2846 for (i = 0; i < dscale; d++, i += DEC_DIGITS)
2848 dig = (d >= 0 && d < var->ndigits) ? var->digits[d] : 0;
2860 #elif DEC_DIGITS == 2
2865 #elif DEC_DIGITS == 1
2868 #error unsupported NBASE
2875 * terminate the string and return it
2885 * Create the packed db numeric format in palloc()'d memory from
2889 make_result(NumericVar *var)
2892 NumericDigit *digits = var->digits;
2893 int weight = var->weight;
2894 int sign = var->sign;
2898 if (sign == NUMERIC_NAN)
2900 result = (Numeric) palloc(NUMERIC_HDRSZ);
2902 result->varlen = NUMERIC_HDRSZ;
2903 result->n_weight = 0;
2904 result->n_sign_dscale = NUMERIC_NAN;
2906 dump_numeric("make_result()", result);
2912 /* truncate leading zeroes */
2913 while (n > 0 && *digits == 0)
2919 /* truncate trailing zeroes */
2920 while (n > 0 && digits[n - 1] == 0)
2923 /* If zero result, force to weight=0 and positive sign */
2930 /* Build the result */
2931 len = NUMERIC_HDRSZ + n * sizeof(NumericDigit);
2932 result = (Numeric) palloc(len);
2933 result->varlen = len;
2934 result->n_weight = weight;
2935 result->n_sign_dscale = sign | (var->dscale & NUMERIC_DSCALE_MASK);
2937 memcpy(result->n_data, digits, n * sizeof(NumericDigit));
2939 /* Check for overflow of int16 fields */
2940 if (result->n_weight != weight ||
2941 NUMERIC_DSCALE(result) != var->dscale)
2943 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
2944 errmsg("value overflows numeric format")));
2946 dump_numeric("make_result()", result);
2954 * Do bounds checking and rounding according to the attributes
2958 apply_typmod(NumericVar *var, int32 typmod)
2966 /* Do nothing if we have a default typmod (-1) */
2967 if (typmod < (int32) (VARHDRSZ))
2971 precision = (typmod >> 16) & 0xffff;
2972 scale = typmod & 0xffff;
2973 maxdigits = precision - scale;
2975 /* Round to target scale (and set var->dscale) */
2976 round_var(var, scale);
2979 * Check for overflow - note we can't do this before rounding, because
2980 * rounding could raise the weight. Also note that the var's weight
2981 * could be inflated by leading zeroes, which will be stripped before
2982 * storage but perhaps might not have been yet. In any case, we must
2983 * recognize a true zero, whose weight doesn't mean anything.
2985 ddigits = (var->weight + 1) * DEC_DIGITS;
2986 if (ddigits > maxdigits)
2988 /* Determine true weight; and check for all-zero result */
2989 for (i = 0; i < var->ndigits; i++)
2991 NumericDigit dig = var->digits[i];
2995 /* Adjust for any high-order decimal zero digits */
3001 else if (dig < 1000)
3003 #elif DEC_DIGITS == 2
3006 #elif DEC_DIGITS == 1
3009 #error unsupported NBASE
3011 if (ddigits > maxdigits)
3013 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
3014 errmsg("numeric field overflow"),
3015 errdetail("The absolute value is greater than or equal to 10^%d for field with precision %d, scale %d.",
3016 ddigits - 1, precision, scale)));
3019 ddigits -= DEC_DIGITS;
3025 * Convert numeric to int8, rounding if needed.
3027 * If overflow, return FALSE (no error is raised). Return TRUE if okay.
3029 * CAUTION: var's contents may be modified by rounding!
3032 numericvar_to_int8(NumericVar *var, int64 *result)
3034 NumericDigit *digits;
3042 /* Round to nearest integer */
3045 /* Check for zero input */
3047 ndigits = var->ndigits;
3055 * For input like 10000000000, we must treat stripped digits as real.
3056 * So the loop assumes there are weight+1 digits before the decimal
3059 weight = var->weight;
3060 Assert(weight >= 0 && ndigits <= weight + 1);
3062 /* Construct the result */
3063 digits = var->digits;
3064 neg = (var->sign == NUMERIC_NEG);
3066 for (i = 1; i <= weight; i++)
3074 * The overflow check is a bit tricky because we want to accept
3075 * INT64_MIN, which will overflow the positive accumulator. We
3076 * can detect this case easily though because INT64_MIN is the
3077 * only nonzero value for which -val == val (on a two's complement
3080 if ((val / NBASE) != oldval) /* possible overflow? */
3082 if (!neg || (-val) != val || val == 0 || oldval < 0)
3087 *result = neg ? -val : val;
3092 * Convert int8 value to numeric.
3095 int8_to_numericvar(int64 val, NumericVar *var)
3102 /* int8 can require at most 19 decimal digits; add one for safety */
3103 alloc_var(var, 20 / DEC_DIGITS);
3106 var->sign = NUMERIC_NEG;
3111 var->sign = NUMERIC_POS;
3121 ptr = var->digits + var->ndigits;
3127 newuval = uval / NBASE;
3128 *ptr = uval - newuval * NBASE;
3132 var->ndigits = ndigits;
3133 var->weight = ndigits - 1;
3137 * Convert numeric to float8; if out of range, return +/- HUGE_VAL
3140 numeric_to_double_no_overflow(Numeric num)
3146 tmp = DatumGetCString(DirectFunctionCall1(numeric_out,
3147 NumericGetDatum(num)));
3149 /* unlike float8in, we ignore ERANGE from strtod */
3150 val = strtod(tmp, &endptr);
3151 if (*endptr != '\0')
3153 /* shouldn't happen ... */
3155 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
3156 errmsg("invalid input syntax for type double precision: \"%s\"",
3165 /* As above, but work from a NumericVar */
3167 numericvar_to_double_no_overflow(NumericVar *var)
3173 tmp = get_str_from_var(var, var->dscale);
3175 /* unlike float8in, we ignore ERANGE from strtod */
3176 val = strtod(tmp, &endptr);
3177 if (*endptr != '\0')
3179 /* shouldn't happen ... */
3181 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
3182 errmsg("invalid input syntax for type double precision: \"%s\"",
3195 * Compare two values on variable level. We assume zeroes have been
3196 * truncated to no digits.
3199 cmp_var(NumericVar *var1, NumericVar *var2)
3201 if (var1->ndigits == 0)
3203 if (var2->ndigits == 0)
3205 if (var2->sign == NUMERIC_NEG)
3209 if (var2->ndigits == 0)
3211 if (var1->sign == NUMERIC_POS)
3216 if (var1->sign == NUMERIC_POS)
3218 if (var2->sign == NUMERIC_NEG)
3220 return cmp_abs(var1, var2);
3223 if (var2->sign == NUMERIC_POS)
3226 return cmp_abs(var2, var1);
3233 * Full version of add functionality on variable level (handling signs).
3234 * result might point to one of the operands too without danger.
3237 add_var(NumericVar *var1, NumericVar *var2, NumericVar *result)
3240 * Decide on the signs of the two variables what to do
3242 if (var1->sign == NUMERIC_POS)
3244 if (var2->sign == NUMERIC_POS)
3247 * Both are positive result = +(ABS(var1) + ABS(var2))
3249 add_abs(var1, var2, result);
3250 result->sign = NUMERIC_POS;
3255 * var1 is positive, var2 is negative Must compare absolute
3258 switch (cmp_abs(var1, var2))
3262 * ABS(var1) == ABS(var2)
3267 result->dscale = Max(var1->dscale, var2->dscale);
3272 * ABS(var1) > ABS(var2)
3273 * result = +(ABS(var1) - ABS(var2))
3276 sub_abs(var1, var2, result);
3277 result->sign = NUMERIC_POS;
3282 * ABS(var1) < ABS(var2)
3283 * result = -(ABS(var2) - ABS(var1))
3286 sub_abs(var2, var1, result);
3287 result->sign = NUMERIC_NEG;
3294 if (var2->sign == NUMERIC_POS)
3297 * var1 is negative, var2 is positive
3298 * Must compare absolute values
3301 switch (cmp_abs(var1, var2))
3305 * ABS(var1) == ABS(var2)
3310 result->dscale = Max(var1->dscale, var2->dscale);
3315 * ABS(var1) > ABS(var2)
3316 * result = -(ABS(var1) - ABS(var2))
3319 sub_abs(var1, var2, result);
3320 result->sign = NUMERIC_NEG;
3325 * ABS(var1) < ABS(var2)
3326 * result = +(ABS(var2) - ABS(var1))
3329 sub_abs(var2, var1, result);
3330 result->sign = NUMERIC_POS;
3338 * result = -(ABS(var1) + ABS(var2))
3341 add_abs(var1, var2, result);
3342 result->sign = NUMERIC_NEG;
3351 * Full version of sub functionality on variable level (handling signs).
3352 * result might point to one of the operands too without danger.
3355 sub_var(NumericVar *var1, NumericVar *var2, NumericVar *result)
3358 * Decide on the signs of the two variables what to do
3360 if (var1->sign == NUMERIC_POS)
3362 if (var2->sign == NUMERIC_NEG)
3365 * var1 is positive, var2 is negative
3366 * result = +(ABS(var1) + ABS(var2))
3369 add_abs(var1, var2, result);
3370 result->sign = NUMERIC_POS;
3376 * Must compare absolute values
3379 switch (cmp_abs(var1, var2))
3383 * ABS(var1) == ABS(var2)
3388 result->dscale = Max(var1->dscale, var2->dscale);
3393 * ABS(var1) > ABS(var2)
3394 * result = +(ABS(var1) - ABS(var2))
3397 sub_abs(var1, var2, result);
3398 result->sign = NUMERIC_POS;
3403 * ABS(var1) < ABS(var2)
3404 * result = -(ABS(var2) - ABS(var1))
3407 sub_abs(var2, var1, result);
3408 result->sign = NUMERIC_NEG;
3415 if (var2->sign == NUMERIC_NEG)
3419 * Must compare absolute values
3422 switch (cmp_abs(var1, var2))
3426 * ABS(var1) == ABS(var2)
3431 result->dscale = Max(var1->dscale, var2->dscale);
3436 * ABS(var1) > ABS(var2)
3437 * result = -(ABS(var1) - ABS(var2))
3440 sub_abs(var1, var2, result);
3441 result->sign = NUMERIC_NEG;
3446 * ABS(var1) < ABS(var2)
3447 * result = +(ABS(var2) - ABS(var1))
3450 sub_abs(var2, var1, result);
3451 result->sign = NUMERIC_POS;
3458 * var1 is negative, var2 is positive
3459 * result = -(ABS(var1) + ABS(var2))
3462 add_abs(var1, var2, result);
3463 result->sign = NUMERIC_NEG;
3472 * Multiplication on variable level. Product of var1 * var2 is stored
3473 * in result. Result is rounded to no more than rscale fractional digits.
3476 mul_var(NumericVar *var1, NumericVar *var2, NumericVar *result,
3487 NumericDigit *res_digits;
3493 /* copy these values into local vars for speed in inner loop */
3494 int var1ndigits = var1->ndigits;
3495 int var2ndigits = var2->ndigits;
3496 NumericDigit *var1digits = var1->digits;
3497 NumericDigit *var2digits = var2->digits;
3499 if (var1ndigits == 0 || var2ndigits == 0)
3501 /* one or both inputs is zero; so is result */
3503 result->dscale = rscale;
3507 /* Determine result sign and (maximum possible) weight */
3508 if (var1->sign == var2->sign)
3509 res_sign = NUMERIC_POS;
3511 res_sign = NUMERIC_NEG;
3512 res_weight = var1->weight + var2->weight + 2;
3515 * Determine number of result digits to compute. If the exact result
3516 * would have more than rscale fractional digits, truncate the
3517 * computation with MUL_GUARD_DIGITS guard digits. We do that by
3518 * pretending that one or both inputs have fewer digits than they
3521 res_ndigits = var1ndigits + var2ndigits + 1;
3522 maxdigits = res_weight + 1 + (rscale * DEC_DIGITS) + MUL_GUARD_DIGITS;
3523 if (res_ndigits > maxdigits)
3527 /* no useful precision at all in the result... */
3529 result->dscale = rscale;
3532 /* force maxdigits odd so that input ndigits can be equal */
3533 if ((maxdigits & 1) == 0)
3535 if (var1ndigits > var2ndigits)
3537 var1ndigits -= res_ndigits - maxdigits;
3538 if (var1ndigits < var2ndigits)
3539 var1ndigits = var2ndigits = (var1ndigits + var2ndigits) / 2;
3543 var2ndigits -= res_ndigits - maxdigits;
3544 if (var2ndigits < var1ndigits)
3545 var1ndigits = var2ndigits = (var1ndigits + var2ndigits) / 2;
3547 res_ndigits = maxdigits;
3548 Assert(res_ndigits == var1ndigits + var2ndigits + 1);
3552 * We do the arithmetic in an array "dig[]" of signed int's. Since
3553 * INT_MAX is noticeably larger than NBASE*NBASE, this gives us
3554 * headroom to avoid normalizing carries immediately.
3556 * maxdig tracks the maximum possible value of any dig[] entry; when this
3557 * threatens to exceed INT_MAX, we take the time to propagate carries.
3558 * To avoid overflow in maxdig itself, it actually represents the max
3559 * possible value divided by NBASE-1.
3561 dig = (int *) palloc0(res_ndigits * sizeof(int));
3564 ri = res_ndigits - 1;
3565 for (i1 = var1ndigits - 1; i1 >= 0; ri--, i1--)
3567 int var1digit = var1digits[i1];
3572 /* Time to normalize? */
3573 maxdig += var1digit;
3574 if (maxdig > INT_MAX / (NBASE - 1))
3578 for (i = res_ndigits - 1; i >= 0; i--)
3580 newdig = dig[i] + carry;
3581 if (newdig >= NBASE)
3583 carry = newdig / NBASE;
3584 newdig -= carry * NBASE;
3591 /* Reset maxdig to indicate new worst-case */
3592 maxdig = 1 + var1digit;
3595 /* Add appropriate multiple of var2 into the accumulator */
3597 for (i2 = var2ndigits - 1; i2 >= 0; i2--)
3598 dig[i--] += var1digit * var2digits[i2];
3602 * Now we do a final carry propagation pass to normalize the result,
3603 * which we combine with storing the result digits into the output.
3604 * Note that this is still done at full precision w/guard digits.
3606 alloc_var(result, res_ndigits);
3607 res_digits = result->digits;
3609 for (i = res_ndigits - 1; i >= 0; i--)
3611 newdig = dig[i] + carry;
3612 if (newdig >= NBASE)
3614 carry = newdig / NBASE;
3615 newdig -= carry * NBASE;
3619 res_digits[i] = newdig;
3626 * Finally, round the result to the requested precision.
3628 result->weight = res_weight;
3629 result->sign = res_sign;
3631 /* Round to target rscale (and set result->dscale) */
3632 round_var(result, rscale);
3634 /* Strip leading and trailing zeroes */
3642 * Division on variable level. Quotient of var1 / var2 is stored
3643 * in result. Result is rounded to no more than rscale fractional digits.
3646 div_var(NumericVar *var1, NumericVar *var2, NumericVar *result,
3657 NumericDigit *res_digits;
3665 /* copy these values into local vars for speed in inner loop */
3666 int var1ndigits = var1->ndigits;
3667 int var2ndigits = var2->ndigits;
3668 NumericDigit *var1digits = var1->digits;
3669 NumericDigit *var2digits = var2->digits;
3672 * First of all division by zero check; we must not be handed an
3673 * unnormalized divisor.
3675 if (var2ndigits == 0 || var2digits[0] == 0)
3677 (errcode(ERRCODE_DIVISION_BY_ZERO),
3678 errmsg("division by zero")));
3681 * Now result zero check
3683 if (var1ndigits == 0)
3686 result->dscale = rscale;
3691 * Determine the result sign, weight and number of digits to calculate
3693 if (var1->sign == var2->sign)
3694 res_sign = NUMERIC_POS;
3696 res_sign = NUMERIC_NEG;
3697 res_weight = var1->weight - var2->weight + 1;
3698 /* The number of accurate result digits we need to produce: */
3699 div_ndigits = res_weight + 1 + (rscale + DEC_DIGITS - 1) / DEC_DIGITS;
3700 /* Add guard digits for roundoff error */
3701 div_ndigits += DIV_GUARD_DIGITS;
3702 if (div_ndigits < DIV_GUARD_DIGITS)
3703 div_ndigits = DIV_GUARD_DIGITS;
3704 /* Must be at least var1ndigits, too, to simplify data-loading loop */
3705 if (div_ndigits < var1ndigits)
3706 div_ndigits = var1ndigits;
3709 * We do the arithmetic in an array "div[]" of signed int's. Since
3710 * INT_MAX is noticeably larger than NBASE*NBASE, this gives us
3711 * headroom to avoid normalizing carries immediately.
3713 * We start with div[] containing one zero digit followed by the
3714 * dividend's digits (plus appended zeroes to reach the desired
3715 * precision including guard digits). Each step of the main loop
3716 * computes an (approximate) quotient digit and stores it into div[],
3717 * removing one position of dividend space. A final pass of carry
3718 * propagation takes care of any mistaken quotient digits.
3720 div = (int *) palloc0((div_ndigits + 1) * sizeof(int));
3721 for (i = 0; i < var1ndigits; i++)
3722 div[i + 1] = var1digits[i];
3725 * We estimate each quotient digit using floating-point arithmetic,
3726 * taking the first four digits of the (current) dividend and divisor.
3727 * This must be float to avoid overflow.
3729 fdivisor = (double) var2digits[0];
3730 for (i = 1; i < 4; i++)
3733 if (i < var2ndigits)
3734 fdivisor += (double) var2digits[i];
3736 fdivisorinverse = 1.0 / fdivisor;
3739 * maxdiv tracks the maximum possible absolute value of any div[]
3740 * entry; when this threatens to exceed INT_MAX, we take the time to
3741 * propagate carries. To avoid overflow in maxdiv itself, it actually
3742 * represents the max possible abs. value divided by NBASE-1.
3747 * Outer loop computes next quotient digit, which will go into div[qi]
3749 for (qi = 0; qi < div_ndigits; qi++)
3751 /* Approximate the current dividend value */
3752 fdividend = (double) div[qi];
3753 for (i = 1; i < 4; i++)
3756 if (qi + i <= div_ndigits)
3757 fdividend += (double) div[qi + i];
3759 /* Compute the (approximate) quotient digit */
3760 fquotient = fdividend * fdivisorinverse;
3761 qdigit = (fquotient >= 0.0) ? ((int) fquotient) :
3762 (((int) fquotient) - 1); /* truncate towards -infinity */
3766 /* Do we need to normalize now? */
3767 maxdiv += Abs(qdigit);
3768 if (maxdiv > INT_MAX / (NBASE - 1))
3772 for (i = div_ndigits; i > qi; i--)
3774 newdig = div[i] + carry;
3777 carry = -((-newdig - 1) / NBASE) - 1;
3778 newdig -= carry * NBASE;
3780 else if (newdig >= NBASE)
3782 carry = newdig / NBASE;
3783 newdig -= carry * NBASE;
3789 newdig = div[qi] + carry;
3793 * All the div[] digits except possibly div[qi] are now in
3794 * the range 0..NBASE-1.
3796 maxdiv = Abs(newdig) / (NBASE - 1);
3797 maxdiv = Max(maxdiv, 1);
3800 * Recompute the quotient digit since new info may have
3801 * propagated into the top four dividend digits
3803 fdividend = (double) div[qi];
3804 for (i = 1; i < 4; i++)
3807 if (qi + i <= div_ndigits)
3808 fdividend += (double) div[qi + i];
3810 /* Compute the (approximate) quotient digit */
3811 fquotient = fdividend * fdivisorinverse;
3812 qdigit = (fquotient >= 0.0) ? ((int) fquotient) :
3813 (((int) fquotient) - 1); /* truncate towards
3815 maxdiv += Abs(qdigit);
3818 /* Subtract off the appropriate multiple of the divisor */
3821 int istop = Min(var2ndigits, div_ndigits - qi + 1);
3823 for (i = 0; i < istop; i++)
3824 div[qi + i] -= qdigit * var2digits[i];
3829 * The dividend digit we are about to replace might still be
3830 * nonzero. Fold it into the next digit position. We don't need
3831 * to worry about overflow here since this should nearly cancel
3832 * with the subtraction of the divisor.
3834 div[qi + 1] += div[qi] * NBASE;
3840 * Approximate and store the last quotient digit (div[div_ndigits])
3842 fdividend = (double) div[qi];
3843 for (i = 1; i < 4; i++)
3845 fquotient = fdividend * fdivisorinverse;
3846 qdigit = (fquotient >= 0.0) ? ((int) fquotient) :
3847 (((int) fquotient) - 1); /* truncate towards -infinity */
3851 * Now we do a final carry propagation pass to normalize the result,
3852 * which we combine with storing the result digits into the output.
3853 * Note that this is still done at full precision w/guard digits.
3855 alloc_var(result, div_ndigits + 1);
3856 res_digits = result->digits;
3858 for (i = div_ndigits; i >= 0; i--)
3860 newdig = div[i] + carry;
3863 carry = -((-newdig - 1) / NBASE) - 1;
3864 newdig -= carry * NBASE;
3866 else if (newdig >= NBASE)
3868 carry = newdig / NBASE;
3869 newdig -= carry * NBASE;
3873 res_digits[i] = newdig;
3880 * Finally, round the result to the requested precision.
3882 result->weight = res_weight;
3883 result->sign = res_sign;
3885 /* Round to target rscale (and set result->dscale) */
3886 round_var(result, rscale);
3888 /* Strip leading and trailing zeroes */
3894 * Default scale selection for division
3896 * Returns the appropriate result scale for the division result.
3899 select_div_scale(NumericVar *var1, NumericVar *var2)
3905 NumericDigit firstdigit1,
3910 * The result scale of a division isn't specified in any SQL standard.
3911 * For PostgreSQL we select a result scale that will give at least
3912 * NUMERIC_MIN_SIG_DIGITS significant digits, so that numeric gives a
3913 * result no less accurate than float8; but use a scale not less than
3914 * either input's display scale.
3917 /* Get the actual (normalized) weight and first digit of each input */
3919 weight1 = 0; /* values to use if var1 is zero */
3921 for (i = 0; i < var1->ndigits; i++)
3923 firstdigit1 = var1->digits[i];
3924 if (firstdigit1 != 0)
3926 weight1 = var1->weight - i;
3931 weight2 = 0; /* values to use if var2 is zero */
3933 for (i = 0; i < var2->ndigits; i++)
3935 firstdigit2 = var2->digits[i];
3936 if (firstdigit2 != 0)
3938 weight2 = var2->weight - i;
3944 * Estimate weight of quotient. If the two first digits are equal, we
3945 * can't be sure, but assume that var1 is less than var2.
3947 qweight = weight1 - weight2;
3948 if (firstdigit1 <= firstdigit2)
3951 /* Select result scale */
3952 rscale = NUMERIC_MIN_SIG_DIGITS - qweight * DEC_DIGITS;
3953 rscale = Max(rscale, var1->dscale);
3954 rscale = Max(rscale, var2->dscale);
3955 rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
3956 rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
3965 * Calculate the modulo of two numerics at variable level
3968 mod_var(NumericVar *var1, NumericVar *var2, NumericVar *result)
3976 * We do this using the equation
3977 * mod(x,y) = x - trunc(x/y)*y
3978 * We set rscale the same way numeric_div and numeric_mul do
3979 * to get the right answer from the equation. The final result,
3980 * however, need not be displayed to more precision than the inputs.
3983 rscale = select_div_scale(var1, var2);
3985 div_var(var1, var2, &tmp, rscale);
3989 mul_var(var2, &tmp, &tmp, var2->dscale + tmp.dscale);
3991 sub_var(var1, &tmp, result);
3993 round_var(result, Max(var1->dscale, var2->dscale));
4002 * Return the smallest integer greater than or equal to the argument
4006 ceil_var(NumericVar *var, NumericVar *result)
4011 set_var_from_var(var, &tmp);
4015 if (var->sign == NUMERIC_POS && cmp_var(var, &tmp) != 0)
4016 add_var(&tmp, &const_one, &tmp);
4018 set_var_from_var(&tmp, result);
4026 * Return the largest integer equal to or less than the argument
4030 floor_var(NumericVar *var, NumericVar *result)
4035 set_var_from_var(var, &tmp);
4039 if (var->sign == NUMERIC_NEG && cmp_var(var, &tmp) != 0)
4040 sub_var(&tmp, &const_one, &tmp);
4042 set_var_from_var(&tmp, result);
4050 * Compute the square root of x using Newton's algorithm
4053 sqrt_var(NumericVar *arg, NumericVar *result, int rscale)
4057 NumericVar last_val;
4061 local_rscale = rscale + 8;
4063 stat = cmp_var(arg, &const_zero);
4067 result->dscale = rscale;
4073 (errcode(ERRCODE_FLOATING_POINT_EXCEPTION),
4074 errmsg("cannot take square root of a negative number")));
4078 init_var(&last_val);
4080 /* Copy arg in case it is the same var as result */
4081 set_var_from_var(arg, &tmp_arg);
4084 * Initialize the result to the first guess
4086 alloc_var(result, 1);
4087 result->digits[0] = tmp_arg.digits[0] / 2;
4088 if (result->digits[0] == 0)
4089 result->digits[0] = 1;
4090 result->weight = tmp_arg.weight / 2;
4091 result->sign = NUMERIC_POS;
4093 set_var_from_var(result, &last_val);
4097 div_var(&tmp_arg, result, &tmp_val, local_rscale);
4099 add_var(result, &tmp_val, result);
4100 mul_var(result, &const_zero_point_five, result, local_rscale);
4102 if (cmp_var(&last_val, result) == 0)
4104 set_var_from_var(result, &last_val);
4107 free_var(&last_val);
4111 /* Round to requested precision */
4112 round_var(result, rscale);
4119 * Raise e to the power of x
4122 exp_var(NumericVar *arg, NumericVar *result, int rscale)
4130 * We separate the integral and fraction parts of x, then compute
4131 * e^x = e^xint * e^xfrac
4132 * where e = exp(1) and e^xfrac = exp(xfrac) are computed by
4133 * exp_var_internal; the limited range of inputs allows that routine
4134 * to do a good job with a simple Taylor series. Raising e^xint is
4135 * done by repeated multiplications in power_var_int.
4140 set_var_from_var(arg, &x);
4142 if (x.sign == NUMERIC_NEG)
4145 x.sign = NUMERIC_POS;
4148 /* Extract the integer part, remove it from x */
4150 while (x.weight >= 0)
4155 xintval += x.digits[0];
4160 /* Guard against overflow */
4161 if (xintval >= NUMERIC_MAX_RESULT_SCALE * 3)
4163 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
4164 errmsg("argument for function \"exp\" too big")));
4167 /* Select an appropriate scale for internal calculation */
4168 local_rscale = rscale + MUL_GUARD_DIGITS * 2;
4170 /* Compute e^xfrac */
4171 exp_var_internal(&x, result, local_rscale);
4173 /* If there's an integer part, multiply by e^xint */
4179 exp_var_internal(&const_one, &e, local_rscale);
4180 power_var_int(&e, xintval, &e, local_rscale);
4181 mul_var(&e, result, result, local_rscale);
4185 /* Compensate for input sign, and round to requested rscale */
4187 div_var(&const_one, result, result, rscale);
4189 round_var(result, rscale);
4196 * exp_var_internal() -
4198 * Raise e to the power of x, where 0 <= x <= 1
4200 * NB: the result should be good to at least rscale digits, but it has
4201 * *not* been rounded off; the caller must do that if wanted.
4204 exp_var_internal(NumericVar *arg, NumericVar *result, int rscale)
4220 set_var_from_var(arg, &x);
4222 Assert(x.sign == NUMERIC_POS);
4224 local_rscale = rscale + 8;
4226 /* Reduce input into range 0 <= x <= 0.01 */
4227 while (cmp_var(&x, &const_zero_point_01) > 0)
4231 mul_var(&x, &const_zero_point_five, &x, x.dscale + 1);
4235 * Use the Taylor series
4237 * exp(x) = 1 + x + x^2/2! + x^3/3! + ...
4239 * Given the limited range of x, this should converge reasonably quickly.
4240 * We run the series until the terms fall below the local_rscale
4243 add_var(&const_one, &x, result);
4244 set_var_from_var(&x, &xpow);
4245 set_var_from_var(&const_one, &ifac);
4246 set_var_from_var(&const_one, &ni);
4250 add_var(&ni, &const_one, &ni);
4251 mul_var(&xpow, &x, &xpow, local_rscale);
4252 mul_var(&ifac, &ni, &ifac, 0);
4253 div_var(&xpow, &ifac, &elem, local_rscale);
4255 if (elem.ndigits == 0)
4258 add_var(result, &elem, result);
4261 /* Compensate for argument range reduction */
4263 mul_var(result, result, result, local_rscale);
4276 * Compute the natural log of x
4279 ln_var(NumericVar *arg, NumericVar *result, int rscale)
4288 if (cmp_var(arg, &const_zero) <= 0)
4290 (errcode(ERRCODE_FLOATING_POINT_EXCEPTION),
4291 errmsg("cannot take logarithm of a negative number")));
4293 local_rscale = rscale + 8;
4301 set_var_from_var(arg, &x);
4302 set_var_from_var(&const_two, &fact);
4304 /* Reduce input into range 0.9 < x < 1.1 */
4305 while (cmp_var(&x, &const_zero_point_nine) <= 0)
4308 sqrt_var(&x, &x, local_rscale);
4309 mul_var(&fact, &const_two, &fact, 0);
4311 while (cmp_var(&x, &const_one_point_one) >= 0)
4314 sqrt_var(&x, &x, local_rscale);
4315 mul_var(&fact, &const_two, &fact, 0);
4319 * We use the Taylor series for 0.5 * ln((1+z)/(1-z)),
4321 * z + z^3/3 + z^5/5 + ...
4323 * where z = (x-1)/(x+1) is in the range (approximately) -0.053 .. 0.048
4324 * due to the above range-reduction of x.
4326 * The convergence of this is not as fast as one would like, but is
4327 * tolerable given that z is small.
4329 sub_var(&x, &const_one, result);
4330 add_var(&x, &const_one, &elem);
4331 div_var(result, &elem, result, local_rscale);
4332 set_var_from_var(result, &xx);
4333 mul_var(result, result, &x, local_rscale);
4335 set_var_from_var(&const_one, &ni);
4339 add_var(&ni, &const_two, &ni);
4340 mul_var(&xx, &x, &xx, local_rscale);
4341 div_var(&xx, &ni, &elem, local_rscale);
4343 if (elem.ndigits == 0)
4346 add_var(result, &elem, result);
4348 if (elem.weight < (result->weight - local_rscale * 2 / DEC_DIGITS))
4352 /* Compensate for argument range reduction, round to requested rscale */
4353 mul_var(result, &fact, result, rscale);
4366 * Compute the logarithm of num in a given base.
4368 * Note: this routine chooses dscale of the result.
4371 log_var(NumericVar *base, NumericVar *num, NumericVar *result)
4382 /* Set scale for ln() calculations --- compare numeric_ln() */
4384 /* Approx decimal digits before decimal point */
4385 dec_digits = (num->weight + 1) * DEC_DIGITS;
4388 rscale = NUMERIC_MIN_SIG_DIGITS - (int) log10(dec_digits - 1);
4389 else if (dec_digits < 1)
4390 rscale = NUMERIC_MIN_SIG_DIGITS - (int) log10(1 - dec_digits);
4392 rscale = NUMERIC_MIN_SIG_DIGITS;
4394 rscale = Max(rscale, base->dscale);
4395 rscale = Max(rscale, num->dscale);
4396 rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
4397 rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
4399 local_rscale = rscale + 8;
4401 /* Form natural logarithms */
4402 ln_var(base, &ln_base, local_rscale);
4403 ln_var(num, &ln_num, local_rscale);
4405 ln_base.dscale = rscale;
4406 ln_num.dscale = rscale;
4408 /* Select scale for division result */
4409 rscale = select_div_scale(&ln_num, &ln_base);
4411 div_var(&ln_num, &ln_base, result, rscale);
4421 * Raise base to the power of exp
4423 * Note: this routine chooses dscale of the result.
4426 power_var(NumericVar *base, NumericVar *exp, NumericVar *result)
4435 /* If exp can be represented as an integer, use power_var_int */
4436 if (exp->ndigits == 0 || exp->ndigits <= exp->weight + 1)
4438 /* exact integer, but does it fit in int? */
4442 /* must copy because numericvar_to_int8() scribbles on input */
4444 set_var_from_var(exp, &x);
4445 if (numericvar_to_int8(&x, &expval64))
4447 int expval = (int) expval64;
4449 /* Test for overflow by reverse-conversion. */
4450 if ((int64) expval == expval64)
4452 /* Okay, select rscale */
4453 rscale = NUMERIC_MIN_SIG_DIGITS;
4454 rscale = Max(rscale, base->dscale);
4455 rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
4456 rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
4458 power_var_int(base, expval, result, rscale);
4470 /* Set scale for ln() calculation --- need extra accuracy here */
4472 /* Approx decimal digits before decimal point */
4473 dec_digits = (base->weight + 1) * DEC_DIGITS;
4476 rscale = NUMERIC_MIN_SIG_DIGITS * 2 - (int) log10(dec_digits - 1);
4477 else if (dec_digits < 1)
4478 rscale = NUMERIC_MIN_SIG_DIGITS * 2 - (int) log10(1 - dec_digits);
4480 rscale = NUMERIC_MIN_SIG_DIGITS * 2;
4482 rscale = Max(rscale, base->dscale * 2);
4483 rscale = Max(rscale, exp->dscale * 2);
4484 rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE * 2);
4485 rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE * 2);
4487 local_rscale = rscale + 8;
4489 ln_var(base, &ln_base, local_rscale);
4491 mul_var(&ln_base, exp, &ln_num, local_rscale);
4493 /* Set scale for exp() -- compare numeric_exp() */
4495 /* convert input to float8, ignoring overflow */
4496 val = numericvar_to_double_no_overflow(&ln_num);
4499 * log10(result) = num * log10(e), so this is approximately the
4502 val *= 0.434294481903252;
4504 /* limit to something that won't cause integer overflow */
4505 val = Max(val, -NUMERIC_MAX_RESULT_SCALE);
4506 val = Min(val, NUMERIC_MAX_RESULT_SCALE);
4508 rscale = NUMERIC_MIN_SIG_DIGITS - (int) val;
4509 rscale = Max(rscale, base->dscale);
4510 rscale = Max(rscale, exp->dscale);
4511 rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
4512 rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
4514 exp_var(&ln_num, result, rscale);
4523 * Raise base to the power of exp, where exp is an integer.
4526 power_var_int(NumericVar *base, int exp, NumericVar *result, int rscale)
4529 NumericVar base_prod;
4532 /* Detect some special cases, particularly 0^0. */
4537 if (base->ndigits == 0)
4539 (errcode(ERRCODE_FLOATING_POINT_EXCEPTION),
4540 errmsg("zero raised to zero is undefined")));
4541 set_var_from_var(&const_one, result);
4542 result->dscale = rscale; /* no need to round */
4545 set_var_from_var(base, result);
4546 round_var(result, rscale);
4549 div_var(&const_one, base, result, rscale);
4552 mul_var(base, base, result, rscale);
4559 * The general case repeatedly multiplies base according to the bit
4560 * pattern of exp. We do the multiplications with some extra
4566 local_rscale = rscale + MUL_GUARD_DIGITS * 2;
4568 init_var(&base_prod);
4569 set_var_from_var(base, &base_prod);
4572 set_var_from_var(base, result);
4574 set_var_from_var(&const_one, result);
4576 while ((exp >>= 1) > 0)
4578 mul_var(&base_prod, &base_prod, &base_prod, local_rscale);
4580 mul_var(&base_prod, result, result, local_rscale);
4583 free_var(&base_prod);
4585 /* Compensate for input sign, and round to requested rscale */
4587 div_var(&const_one, result, result, rscale);
4589 round_var(result, rscale);
4593 /* ----------------------------------------------------------------------
4595 * Following are the lowest level functions that operate unsigned
4596 * on the variable level
4598 * ----------------------------------------------------------------------
4605 * Compare the absolute values of var1 and var2
4606 * Returns: -1 for ABS(var1) < ABS(var2)
4607 * 0 for ABS(var1) == ABS(var2)
4608 * 1 for ABS(var1) > ABS(var2)
4612 cmp_abs(NumericVar *var1, NumericVar *var2)
4614 NumericDigit *var1digits = var1->digits;
4615 NumericDigit *var2digits = var2->digits;
4618 int w1 = var1->weight;
4619 int w2 = var2->weight;
4621 /* Check any digits before the first common digit */
4623 while (w1 > w2 && i1 < var1->ndigits)
4625 if (var1digits[i1++] != 0)
4629 while (w2 > w1 && i2 < var2->ndigits)
4631 if (var2digits[i2++] != 0)
4636 /* At this point, either w1 == w2 or we've run out of digits */
4640 while (i1 < var1->ndigits && i2 < var2->ndigits)
4642 int stat = var1digits[i1++] - var2digits[i2++];
4654 * At this point, we've run out of digits on one side or the other; so
4655 * any remaining nonzero digits imply that side is larger
4657 while (i1 < var1->ndigits)
4659 if (var1digits[i1++] != 0)
4662 while (i2 < var2->ndigits)
4664 if (var2digits[i2++] != 0)
4675 * Add the absolute values of two variables into result.
4676 * result might point to one of the operands without danger.
4679 add_abs(NumericVar *var1, NumericVar *var2, NumericVar *result)
4681 NumericDigit *res_buf;
4682 NumericDigit *res_digits;
4694 /* copy these values into local vars for speed in inner loop */
4695 int var1ndigits = var1->ndigits;
4696 int var2ndigits = var2->ndigits;
4697 NumericDigit *var1digits = var1->digits;
4698 NumericDigit *var2digits = var2->digits;
4700 res_weight = Max(var1->weight, var2->weight) + 1;
4702 res_dscale = Max(var1->dscale, var2->dscale);
4704 /* Note: here we are figuring rscale in base-NBASE digits */
4705 rscale1 = var1->ndigits - var1->weight - 1;
4706 rscale2 = var2->ndigits - var2->weight - 1;
4707 res_rscale = Max(rscale1, rscale2);
4709 res_ndigits = res_rscale + res_weight + 1;
4710 if (res_ndigits <= 0)
4713 res_buf = digitbuf_alloc(res_ndigits + 1);
4714 res_buf[0] = 0; /* spare digit for later rounding */
4715 res_digits = res_buf + 1;
4717 i1 = res_rscale + var1->weight + 1;
4718 i2 = res_rscale + var2->weight + 1;
4719 for (i = res_ndigits - 1; i >= 0; i--)
4723 if (i1 >= 0 && i1 < var1ndigits)
4724 carry += var1digits[i1];
4725 if (i2 >= 0 && i2 < var2ndigits)
4726 carry += var2digits[i2];
4730 res_digits[i] = carry - NBASE;
4735 res_digits[i] = carry;
4740 Assert(carry == 0); /* else we failed to allow for carry out */
4742 digitbuf_free(result->buf);
4743 result->ndigits = res_ndigits;
4744 result->buf = res_buf;
4745 result->digits = res_digits;
4746 result->weight = res_weight;
4747 result->dscale = res_dscale;
4749 /* Remove leading/trailing zeroes */
4757 * Subtract the absolute value of var2 from the absolute value of var1
4758 * and store in result. result might point to one of the operands
4761 * ABS(var1) MUST BE GREATER OR EQUAL ABS(var2) !!!
4764 sub_abs(NumericVar *var1, NumericVar *var2, NumericVar *result)
4766 NumericDigit *res_buf;
4767 NumericDigit *res_digits;
4779 /* copy these values into local vars for speed in inner loop */
4780 int var1ndigits = var1->ndigits;
4781 int var2ndigits = var2->ndigits;
4782 NumericDigit *var1digits = var1->digits;
4783 NumericDigit *var2digits = var2->digits;
4785 res_weight = var1->weight;
4787 res_dscale = Max(var1->dscale, var2->dscale);
4789 /* Note: here we are figuring rscale in base-NBASE digits */
4790 rscale1 = var1->ndigits - var1->weight - 1;
4791 rscale2 = var2->ndigits - var2->weight - 1;
4792 res_rscale = Max(rscale1, rscale2);
4794 res_ndigits = res_rscale + res_weight + 1;
4795 if (res_ndigits <= 0)
4798 res_buf = digitbuf_alloc(res_ndigits + 1);
4799 res_buf[0] = 0; /* spare digit for later rounding */
4800 res_digits = res_buf + 1;
4802 i1 = res_rscale + var1->weight + 1;
4803 i2 = res_rscale + var2->weight + 1;
4804 for (i = res_ndigits - 1; i >= 0; i--)
4808 if (i1 >= 0 && i1 < var1ndigits)
4809 borrow += var1digits[i1];
4810 if (i2 >= 0 && i2 < var2ndigits)
4811 borrow -= var2digits[i2];
4815 res_digits[i] = borrow + NBASE;
4820 res_digits[i] = borrow;
4825 Assert(borrow == 0); /* else caller gave us var1 < var2 */
4827 digitbuf_free(result->buf);
4828 result->ndigits = res_ndigits;
4829 result->buf = res_buf;
4830 result->digits = res_digits;
4831 result->weight = res_weight;
4832 result->dscale = res_dscale;
4834 /* Remove leading/trailing zeroes */
4841 * Round the value of a variable to no more than rscale decimal digits
4842 * after the decimal point. NOTE: we allow rscale < 0 here, implying
4843 * rounding before the decimal point.
4846 round_var(NumericVar *var, int rscale)
4848 NumericDigit *digits = var->digits;
4853 var->dscale = rscale;
4855 /* decimal digits wanted */
4856 di = (var->weight + 1) * DEC_DIGITS + rscale;
4859 * If di = 0, the value loses all digits, but could round up to 1 if
4860 * its first extra digit is >= 5. If di < 0 the result must be 0.
4866 var->sign = NUMERIC_POS;
4870 /* NBASE digits wanted */
4871 ndigits = (di + DEC_DIGITS - 1) / DEC_DIGITS;
4873 /* 0, or number of decimal digits to keep in last NBASE digit */
4876 if (ndigits < var->ndigits ||
4877 (ndigits == var->ndigits && di > 0))
4879 var->ndigits = ndigits;
4882 /* di must be zero */
4883 carry = (digits[ndigits] >= HALF_NBASE) ? 1 : 0;
4886 carry = (digits[ndigits] >= HALF_NBASE) ? 1 : 0;
4889 /* Must round within last NBASE digit */
4894 pow10 = round_powers[di];
4895 #elif DEC_DIGITS == 2
4898 #error unsupported NBASE
4900 extra = digits[--ndigits] % pow10;
4901 digits[ndigits] -= extra;
4903 if (extra >= pow10 / 2)
4905 pow10 += digits[ndigits];
4911 digits[ndigits] = pow10;
4916 /* Propagate carry if needed */
4919 carry += digits[--ndigits];
4922 digits[ndigits] = carry - NBASE;
4927 digits[ndigits] = carry;
4934 Assert(ndigits == -1); /* better not have added > 1 digit */
4935 Assert(var->digits > var->buf);
4947 * Truncate the value of a variable at rscale decimal digits after the
4948 * decimal point. NOTE: we allow rscale < 0 here, implying
4949 * truncation before the decimal point.
4952 trunc_var(NumericVar *var, int rscale)
4957 var->dscale = rscale;
4959 /* decimal digits wanted */
4960 di = (var->weight + 1) * DEC_DIGITS + rscale;
4963 * If di <= 0, the value loses all digits.
4969 var->sign = NUMERIC_POS;
4973 /* NBASE digits wanted */
4974 ndigits = (di + DEC_DIGITS - 1) / DEC_DIGITS;
4976 if (ndigits <= var->ndigits)
4978 var->ndigits = ndigits;
4981 /* no within-digit stuff to worry about */
4983 /* 0, or number of decimal digits to keep in last NBASE digit */
4988 /* Must truncate within last NBASE digit */
4989 NumericDigit *digits = var->digits;
4994 pow10 = round_powers[di];
4995 #elif DEC_DIGITS == 2
4998 #error unsupported NBASE
5000 extra = digits[--ndigits] % pow10;
5001 digits[ndigits] -= extra;
5011 * Strip any leading and trailing zeroes from a numeric variable
5014 strip_var(NumericVar *var)
5016 NumericDigit *digits = var->digits;
5017 int ndigits = var->ndigits;
5019 /* Strip leading zeroes */
5020 while (ndigits > 0 && *digits == 0)
5027 /* Strip trailing zeroes */
5028 while (ndigits > 0 && digits[ndigits - 1] == 0)
5031 /* If it's zero, normalize the sign and weight */
5034 var->sign = NUMERIC_POS;
5038 var->digits = digits;
5039 var->ndigits = ndigits;