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.73 2004/05/07 00:24:58 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().
48 * Numeric values are represented in a base-NBASE floating point format.
49 * Each "digit" ranges from 0 to NBASE-1. The type NumericDigit is signed
50 * and wide enough to store a digit. We assume that NBASE*NBASE can fit in
51 * an int. Although the purely calculational routines could handle any even
52 * NBASE that's less than sqrt(INT_MAX), in practice we are only interested
53 * in NBASE a power of ten, so that I/O conversions and decimal rounding
54 * are easy. Also, it's actually more efficient if NBASE is rather less than
55 * sqrt(INT_MAX), so that there is "headroom" for mul_var and div_var to
56 * postpone processing carries.
63 #define DEC_DIGITS 1 /* decimal digits per NBASE digit */
64 #define MUL_GUARD_DIGITS 4 /* these are measured in NBASE digits */
65 #define DIV_GUARD_DIGITS 8
67 typedef signed char NumericDigit;
73 #define DEC_DIGITS 2 /* decimal digits per NBASE digit */
74 #define MUL_GUARD_DIGITS 3 /* these are measured in NBASE digits */
75 #define DIV_GUARD_DIGITS 6
77 typedef signed char NumericDigit;
82 #define HALF_NBASE 5000
83 #define DEC_DIGITS 4 /* decimal digits per NBASE digit */
84 #define MUL_GUARD_DIGITS 2 /* these are measured in NBASE digits */
85 #define DIV_GUARD_DIGITS 4
87 typedef int16 NumericDigit;
92 * The value represented by a NumericVar is determined by the sign, weight,
93 * ndigits, and digits[] array.
94 * Note: the first digit of a NumericVar's value is assumed to be multiplied
95 * by NBASE ** weight. Another way to say it is that there are weight+1
96 * digits before the decimal point. It is possible to have weight < 0.
98 * buf points at the physical start of the palloc'd digit buffer for the
99 * NumericVar. digits points at the first digit in actual use (the one
100 * with the specified weight). We normally leave an unused digit or two
101 * (preset to zeroes) between buf and digits, so that there is room to store
102 * a carry out of the top digit without special pushups. We just need to
103 * decrement digits (and increment weight) to make room for the carry digit.
104 * (There is no such extra space in a numeric value stored in the database,
105 * only in a NumericVar in memory.)
107 * If buf is NULL then the digit buffer isn't actually palloc'd and should
108 * not be freed --- see the constants below for an example.
110 * dscale, or display scale, is the nominal precision expressed as number
111 * of digits after the decimal point (it must always be >= 0 at present).
112 * dscale may be more than the number of physically stored fractional digits,
113 * implying that we have suppressed storage of significant trailing zeroes.
114 * It should never be less than the number of stored digits, since that would
115 * imply hiding digits that are present. NOTE that dscale is always expressed
116 * in *decimal* digits, and so it may correspond to a fractional number of
117 * base-NBASE digits --- divide by DEC_DIGITS to convert to NBASE digits.
119 * rscale, or result scale, is the target precision for a computation.
120 * Like dscale it is expressed as number of *decimal* digits after the decimal
121 * point, and is always >= 0 at present.
122 * Note that rscale is not stored in variables --- it's figured on-the-fly
123 * from the dscales of the inputs.
125 * NB: All the variable-level functions are written in a style that makes it
126 * possible to give one and the same variable as argument and destination.
127 * This is feasible because the digit buffer is separate from the variable.
130 typedef struct NumericVar
132 int ndigits; /* # of digits in digits[] - can be 0! */
133 int weight; /* weight of first digit */
134 int sign; /* NUMERIC_POS, NUMERIC_NEG, or
136 int dscale; /* display scale */
137 NumericDigit *buf; /* start of palloc'd space for digits[] */
138 NumericDigit *digits; /* base-NBASE digits */
143 * Some preinitialized constants
146 static NumericDigit const_zero_data[1] = {0};
147 static NumericVar const_zero =
148 {0, 0, NUMERIC_POS, 0, NULL, const_zero_data};
150 static NumericDigit const_one_data[1] = {1};
151 static NumericVar const_one =
152 {1, 0, NUMERIC_POS, 0, NULL, const_one_data};
154 static NumericDigit const_two_data[1] = {2};
155 static NumericVar const_two =
156 {1, 0, NUMERIC_POS, 0, NULL, const_two_data};
159 static NumericDigit const_zero_point_five_data[1] = {5000};
161 #elif DEC_DIGITS == 2
162 static NumericDigit const_zero_point_five_data[1] = {50};
164 #elif DEC_DIGITS == 1
165 static NumericDigit const_zero_point_five_data[1] = {5};
167 static NumericVar const_zero_point_five =
168 {1, -1, NUMERIC_POS, 1, NULL, const_zero_point_five_data};
171 static NumericDigit const_zero_point_nine_data[1] = {9000};
173 #elif DEC_DIGITS == 2
174 static NumericDigit const_zero_point_nine_data[1] = {90};
176 #elif DEC_DIGITS == 1
177 static NumericDigit const_zero_point_nine_data[1] = {9};
179 static NumericVar const_zero_point_nine =
180 {1, -1, NUMERIC_POS, 1, NULL, const_zero_point_nine_data};
183 static NumericDigit const_zero_point_01_data[1] = {100};
184 static NumericVar const_zero_point_01 =
185 {1, -1, NUMERIC_POS, 2, NULL, const_zero_point_01_data};
187 #elif DEC_DIGITS == 2
188 static NumericDigit const_zero_point_01_data[1] = {1};
189 static NumericVar const_zero_point_01 =
190 {1, -1, NUMERIC_POS, 2, NULL, const_zero_point_01_data};
192 #elif DEC_DIGITS == 1
193 static NumericDigit const_zero_point_01_data[1] = {1};
194 static NumericVar const_zero_point_01 =
195 {1, -2, NUMERIC_POS, 2, NULL, const_zero_point_01_data};
199 static NumericDigit const_one_point_one_data[2] = {1, 1000};
201 #elif DEC_DIGITS == 2
202 static NumericDigit const_one_point_one_data[2] = {1, 10};
204 #elif DEC_DIGITS == 1
205 static NumericDigit const_one_point_one_data[2] = {1, 1};
207 static NumericVar const_one_point_one =
208 {2, 0, NUMERIC_POS, 1, NULL, const_one_point_one_data};
210 static NumericVar const_nan =
211 {0, 0, NUMERIC_NAN, 0, NULL, NULL};
214 static const int round_powers[4] = {0, 1000, 100, 10};
224 static void dump_numeric(const char *str, Numeric num);
225 static void dump_var(const char *str, NumericVar *var);
228 #define dump_numeric(s,n)
229 #define dump_var(s,v)
232 #define digitbuf_alloc(ndigits) \
233 ((NumericDigit *) palloc((ndigits) * sizeof(NumericDigit)))
234 #define digitbuf_free(buf) \
240 #define init_var(v) MemSetAligned(v, 0, sizeof(NumericVar))
242 static void alloc_var(NumericVar *var, int ndigits);
243 static void free_var(NumericVar *var);
244 static void zero_var(NumericVar *var);
246 static void set_var_from_str(const char *str, NumericVar *dest);
247 static void set_var_from_num(Numeric value, NumericVar *dest);
248 static void set_var_from_var(NumericVar *value, NumericVar *dest);
249 static char *get_str_from_var(NumericVar *var, int dscale);
251 static Numeric make_result(NumericVar *var);
253 static void apply_typmod(NumericVar *var, int32 typmod);
255 static bool numericvar_to_int8(NumericVar *var, int64 *result);
256 static void int8_to_numericvar(int64 val, NumericVar *var);
257 static double numeric_to_double_no_overflow(Numeric num);
258 static double numericvar_to_double_no_overflow(NumericVar *var);
260 static int cmp_numerics(Numeric num1, Numeric num2);
261 static int cmp_var(NumericVar *var1, NumericVar *var2);
262 static void add_var(NumericVar *var1, NumericVar *var2, NumericVar *result);
263 static void sub_var(NumericVar *var1, NumericVar *var2, NumericVar *result);
264 static void mul_var(NumericVar *var1, NumericVar *var2, NumericVar *result,
266 static void div_var(NumericVar *var1, NumericVar *var2, NumericVar *result,
268 static int select_div_scale(NumericVar *var1, NumericVar *var2);
269 static void mod_var(NumericVar *var1, NumericVar *var2, NumericVar *result);
270 static void ceil_var(NumericVar *var, NumericVar *result);
271 static void floor_var(NumericVar *var, NumericVar *result);
273 static void sqrt_var(NumericVar *arg, NumericVar *result, int rscale);
274 static void exp_var(NumericVar *arg, NumericVar *result, int rscale);
275 static void exp_var_internal(NumericVar *arg, NumericVar *result, int rscale);
276 static void ln_var(NumericVar *arg, NumericVar *result, int rscale);
277 static void log_var(NumericVar *base, NumericVar *num, NumericVar *result);
278 static void power_var(NumericVar *base, NumericVar *exp, NumericVar *result);
279 static void power_var_int(NumericVar *base, int exp, NumericVar *result,
282 static int cmp_abs(NumericVar *var1, NumericVar *var2);
283 static void add_abs(NumericVar *var1, NumericVar *var2, NumericVar *result);
284 static void sub_abs(NumericVar *var1, NumericVar *var2, NumericVar *result);
285 static void round_var(NumericVar *var, int rscale);
286 static void trunc_var(NumericVar *var, int rscale);
287 static void strip_var(NumericVar *var);
290 /* ----------------------------------------------------------------------
292 * Input-, output- and rounding-functions
294 * ----------------------------------------------------------------------
301 * Input function for numeric data type
304 numeric_in(PG_FUNCTION_ARGS)
306 char *str = PG_GETARG_CSTRING(0);
309 Oid typelem = PG_GETARG_OID(1);
311 int32 typmod = PG_GETARG_INT32(2);
318 if (pg_strcasecmp(str, "NaN") == 0)
319 PG_RETURN_NUMERIC(make_result(&const_nan));
322 * Use set_var_from_str() to parse the input string and return it in
323 * the packed DB storage format
326 set_var_from_str(str, &value);
328 apply_typmod(&value, typmod);
330 res = make_result(&value);
333 PG_RETURN_NUMERIC(res);
340 * Output function for numeric data type
343 numeric_out(PG_FUNCTION_ARGS)
345 Numeric num = PG_GETARG_NUMERIC(0);
352 if (NUMERIC_IS_NAN(num))
353 PG_RETURN_CSTRING(pstrdup("NaN"));
356 * Get the number in the variable format.
358 * Even if we didn't need to change format, we'd still need to copy the
359 * value to have a modifiable copy for rounding. set_var_from_num()
360 * also guarantees there is extra digit space in case we produce a
361 * carry out from rounding.
364 set_var_from_num(num, &x);
366 str = get_str_from_var(&x, x.dscale);
370 PG_RETURN_CSTRING(str);
374 * numeric_recv - converts external binary format to numeric
376 * External format is a sequence of int16's:
377 * ndigits, weight, sign, dscale, NumericDigits.
380 numeric_recv(PG_FUNCTION_ARGS)
382 StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
390 len = (uint16) pq_getmsgint(buf, sizeof(uint16));
391 if (len < 0 || len > NUMERIC_MAX_PRECISION + NUMERIC_MAX_RESULT_SCALE)
393 (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
394 errmsg("invalid length in external \"numeric\" value")));
396 alloc_var(&value, len);
398 value.weight = (int16) pq_getmsgint(buf, sizeof(int16));
399 value.sign = (uint16) pq_getmsgint(buf, sizeof(uint16));
400 if (!(value.sign == NUMERIC_POS ||
401 value.sign == NUMERIC_NEG ||
402 value.sign == NUMERIC_NAN))
404 (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
405 errmsg("invalid sign in external \"numeric\" value")));
407 value.dscale = (uint16) pq_getmsgint(buf, sizeof(uint16));
408 for (i = 0; i < len; i++)
410 NumericDigit d = pq_getmsgint(buf, sizeof(NumericDigit));
412 if (d < 0 || d >= NBASE)
414 (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
415 errmsg("invalid digit in external \"numeric\" value")));
419 res = make_result(&value);
422 PG_RETURN_NUMERIC(res);
426 * numeric_send - converts numeric to binary format
429 numeric_send(PG_FUNCTION_ARGS)
431 Numeric num = PG_GETARG_NUMERIC(0);
437 set_var_from_num(num, &x);
439 pq_begintypsend(&buf);
441 pq_sendint(&buf, x.ndigits, sizeof(int16));
442 pq_sendint(&buf, x.weight, sizeof(int16));
443 pq_sendint(&buf, x.sign, sizeof(int16));
444 pq_sendint(&buf, x.dscale, sizeof(int16));
445 for (i = 0; i < x.ndigits; i++)
446 pq_sendint(&buf, x.digits[i], sizeof(NumericDigit));
450 PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
457 * This is a special function called by the Postgres database system
458 * before a value is stored in a tuple's attribute. The precision and
459 * scale of the attribute have to be applied on the value.
462 numeric(PG_FUNCTION_ARGS)
464 Numeric num = PG_GETARG_NUMERIC(0);
465 int32 typmod = PG_GETARG_INT32(1);
477 if (NUMERIC_IS_NAN(num))
478 PG_RETURN_NUMERIC(make_result(&const_nan));
481 * If the value isn't a valid type modifier, simply return a copy of
484 if (typmod < (int32) (VARHDRSZ))
486 new = (Numeric) palloc(num->varlen);
487 memcpy(new, num, num->varlen);
488 PG_RETURN_NUMERIC(new);
492 * Get the precision and scale out of the typmod value
494 tmp_typmod = typmod - VARHDRSZ;
495 precision = (tmp_typmod >> 16) & 0xffff;
496 scale = tmp_typmod & 0xffff;
497 maxdigits = precision - scale;
500 * If the number is certainly in bounds and due to the target scale no
501 * rounding could be necessary, just make a copy of the input and
502 * modify its scale fields. (Note we assume the existing dscale is
505 ddigits = (num->n_weight + 1) * DEC_DIGITS;
506 if (ddigits <= maxdigits && scale >= NUMERIC_DSCALE(num))
508 new = (Numeric) palloc(num->varlen);
509 memcpy(new, num, num->varlen);
510 new->n_sign_dscale = NUMERIC_SIGN(new) |
511 ((uint16) scale & NUMERIC_DSCALE_MASK);
512 PG_RETURN_NUMERIC(new);
516 * We really need to fiddle with things - unpack the number into a
517 * variable and let apply_typmod() do it.
521 set_var_from_num(num, &var);
522 apply_typmod(&var, typmod);
523 new = make_result(&var);
527 PG_RETURN_NUMERIC(new);
531 /* ----------------------------------------------------------------------
533 * Sign manipulation, rounding and the like
535 * ----------------------------------------------------------------------
539 numeric_abs(PG_FUNCTION_ARGS)
541 Numeric num = PG_GETARG_NUMERIC(0);
547 if (NUMERIC_IS_NAN(num))
548 PG_RETURN_NUMERIC(make_result(&const_nan));
551 * Do it the easy way directly on the packed format
553 res = (Numeric) palloc(num->varlen);
554 memcpy(res, num, num->varlen);
556 res->n_sign_dscale = NUMERIC_POS | NUMERIC_DSCALE(num);
558 PG_RETURN_NUMERIC(res);
563 numeric_uminus(PG_FUNCTION_ARGS)
565 Numeric num = PG_GETARG_NUMERIC(0);
571 if (NUMERIC_IS_NAN(num))
572 PG_RETURN_NUMERIC(make_result(&const_nan));
575 * Do it the easy way directly on the packed format
577 res = (Numeric) palloc(num->varlen);
578 memcpy(res, num, num->varlen);
581 * The packed format is known to be totally zero digit trimmed always.
582 * So we can identify a ZERO by the fact that there are no digits at
583 * all. Do nothing to a zero.
585 if (num->varlen != NUMERIC_HDRSZ)
587 /* Else, flip the sign */
588 if (NUMERIC_SIGN(num) == NUMERIC_POS)
589 res->n_sign_dscale = NUMERIC_NEG | NUMERIC_DSCALE(num);
591 res->n_sign_dscale = NUMERIC_POS | NUMERIC_DSCALE(num);
594 PG_RETURN_NUMERIC(res);
599 numeric_uplus(PG_FUNCTION_ARGS)
601 Numeric num = PG_GETARG_NUMERIC(0);
604 res = (Numeric) palloc(num->varlen);
605 memcpy(res, num, num->varlen);
607 PG_RETURN_NUMERIC(res);
613 * returns -1 if the argument is less than 0, 0 if the argument is equal
614 * to 0, and 1 if the argument is greater than zero.
617 numeric_sign(PG_FUNCTION_ARGS)
619 Numeric num = PG_GETARG_NUMERIC(0);
626 if (NUMERIC_IS_NAN(num))
627 PG_RETURN_NUMERIC(make_result(&const_nan));
632 * The packed format is known to be totally zero digit trimmed always.
633 * So we can identify a ZERO by the fact that there are no digits at
636 if (num->varlen == NUMERIC_HDRSZ)
637 set_var_from_var(&const_zero, &result);
641 * And if there are some, we return a copy of ONE with the sign of
644 set_var_from_var(&const_one, &result);
645 result.sign = NUMERIC_SIGN(num);
648 res = make_result(&result);
651 PG_RETURN_NUMERIC(res);
658 * Round a value to have 'scale' digits after the decimal point.
659 * We allow negative 'scale', implying rounding before the decimal
660 * point --- Oracle interprets rounding that way.
663 numeric_round(PG_FUNCTION_ARGS)
665 Numeric num = PG_GETARG_NUMERIC(0);
666 int32 scale = PG_GETARG_INT32(1);
673 if (NUMERIC_IS_NAN(num))
674 PG_RETURN_NUMERIC(make_result(&const_nan));
677 * Limit the scale value to avoid possible overflow in calculations
679 scale = Max(scale, -NUMERIC_MAX_RESULT_SCALE);
680 scale = Min(scale, NUMERIC_MAX_RESULT_SCALE);
683 * Unpack the argument and round it at the proper digit position
686 set_var_from_num(num, &arg);
688 round_var(&arg, scale);
690 /* We don't allow negative output dscale */
695 * Return the rounded result
697 res = make_result(&arg);
700 PG_RETURN_NUMERIC(res);
707 * Truncate a value to have 'scale' digits after the decimal point.
708 * We allow negative 'scale', implying a truncation before the decimal
709 * point --- Oracle interprets truncation that way.
712 numeric_trunc(PG_FUNCTION_ARGS)
714 Numeric num = PG_GETARG_NUMERIC(0);
715 int32 scale = PG_GETARG_INT32(1);
722 if (NUMERIC_IS_NAN(num))
723 PG_RETURN_NUMERIC(make_result(&const_nan));
726 * Limit the scale value to avoid possible overflow in calculations
728 scale = Max(scale, -NUMERIC_MAX_RESULT_SCALE);
729 scale = Min(scale, NUMERIC_MAX_RESULT_SCALE);
732 * Unpack the argument and truncate it at the proper digit position
735 set_var_from_num(num, &arg);
737 trunc_var(&arg, scale);
739 /* We don't allow negative output dscale */
744 * Return the truncated result
746 res = make_result(&arg);
749 PG_RETURN_NUMERIC(res);
756 * Return the smallest integer greater than or equal to the argument
759 numeric_ceil(PG_FUNCTION_ARGS)
761 Numeric num = PG_GETARG_NUMERIC(0);
765 if (NUMERIC_IS_NAN(num))
766 PG_RETURN_NUMERIC(make_result(&const_nan));
770 set_var_from_num(num, &result);
771 ceil_var(&result, &result);
773 res = make_result(&result);
776 PG_RETURN_NUMERIC(res);
783 * Return the largest integer equal to or less than the argument
786 numeric_floor(PG_FUNCTION_ARGS)
788 Numeric num = PG_GETARG_NUMERIC(0);
792 if (NUMERIC_IS_NAN(num))
793 PG_RETURN_NUMERIC(make_result(&const_nan));
797 set_var_from_num(num, &result);
798 floor_var(&result, &result);
800 res = make_result(&result);
803 PG_RETURN_NUMERIC(res);
807 /* ----------------------------------------------------------------------
809 * Comparison functions
811 * Note: btree indexes need these routines not to leak memory; therefore,
812 * be careful to free working copies of toasted datums. Most places don't
813 * need to be so careful.
814 * ----------------------------------------------------------------------
819 numeric_cmp(PG_FUNCTION_ARGS)
821 Numeric num1 = PG_GETARG_NUMERIC(0);
822 Numeric num2 = PG_GETARG_NUMERIC(1);
825 result = cmp_numerics(num1, num2);
827 PG_FREE_IF_COPY(num1, 0);
828 PG_FREE_IF_COPY(num2, 1);
830 PG_RETURN_INT32(result);
835 numeric_eq(PG_FUNCTION_ARGS)
837 Numeric num1 = PG_GETARG_NUMERIC(0);
838 Numeric num2 = PG_GETARG_NUMERIC(1);
841 result = cmp_numerics(num1, num2) == 0;
843 PG_FREE_IF_COPY(num1, 0);
844 PG_FREE_IF_COPY(num2, 1);
846 PG_RETURN_BOOL(result);
850 numeric_ne(PG_FUNCTION_ARGS)
852 Numeric num1 = PG_GETARG_NUMERIC(0);
853 Numeric num2 = PG_GETARG_NUMERIC(1);
856 result = cmp_numerics(num1, num2) != 0;
858 PG_FREE_IF_COPY(num1, 0);
859 PG_FREE_IF_COPY(num2, 1);
861 PG_RETURN_BOOL(result);
865 numeric_gt(PG_FUNCTION_ARGS)
867 Numeric num1 = PG_GETARG_NUMERIC(0);
868 Numeric num2 = PG_GETARG_NUMERIC(1);
871 result = cmp_numerics(num1, num2) > 0;
873 PG_FREE_IF_COPY(num1, 0);
874 PG_FREE_IF_COPY(num2, 1);
876 PG_RETURN_BOOL(result);
880 numeric_ge(PG_FUNCTION_ARGS)
882 Numeric num1 = PG_GETARG_NUMERIC(0);
883 Numeric num2 = PG_GETARG_NUMERIC(1);
886 result = cmp_numerics(num1, num2) >= 0;
888 PG_FREE_IF_COPY(num1, 0);
889 PG_FREE_IF_COPY(num2, 1);
891 PG_RETURN_BOOL(result);
895 numeric_lt(PG_FUNCTION_ARGS)
897 Numeric num1 = PG_GETARG_NUMERIC(0);
898 Numeric num2 = PG_GETARG_NUMERIC(1);
901 result = cmp_numerics(num1, num2) < 0;
903 PG_FREE_IF_COPY(num1, 0);
904 PG_FREE_IF_COPY(num2, 1);
906 PG_RETURN_BOOL(result);
910 numeric_le(PG_FUNCTION_ARGS)
912 Numeric num1 = PG_GETARG_NUMERIC(0);
913 Numeric num2 = PG_GETARG_NUMERIC(1);
916 result = cmp_numerics(num1, num2) <= 0;
918 PG_FREE_IF_COPY(num1, 0);
919 PG_FREE_IF_COPY(num2, 1);
921 PG_RETURN_BOOL(result);
925 cmp_numerics(Numeric num1, Numeric num2)
930 * We consider all NANs to be equal and larger than any non-NAN. This
931 * is somewhat arbitrary; the important thing is to have a consistent
934 if (NUMERIC_IS_NAN(num1))
936 if (NUMERIC_IS_NAN(num2))
937 result = 0; /* NAN = NAN */
939 result = 1; /* NAN > non-NAN */
941 else if (NUMERIC_IS_NAN(num2))
943 result = -1; /* non-NAN < NAN */
953 set_var_from_num(num1, &arg1);
954 set_var_from_num(num2, &arg2);
956 result = cmp_var(&arg1, &arg2);
966 /* ----------------------------------------------------------------------
968 * Basic arithmetic functions
970 * ----------------------------------------------------------------------
980 numeric_add(PG_FUNCTION_ARGS)
982 Numeric num1 = PG_GETARG_NUMERIC(0);
983 Numeric num2 = PG_GETARG_NUMERIC(1);
992 if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
993 PG_RETURN_NUMERIC(make_result(&const_nan));
996 * Unpack the values, let add_var() compute the result and return it.
1002 set_var_from_num(num1, &arg1);
1003 set_var_from_num(num2, &arg2);
1005 add_var(&arg1, &arg2, &result);
1007 res = make_result(&result);
1013 PG_RETURN_NUMERIC(res);
1020 * Subtract one numeric from another
1023 numeric_sub(PG_FUNCTION_ARGS)
1025 Numeric num1 = PG_GETARG_NUMERIC(0);
1026 Numeric num2 = PG_GETARG_NUMERIC(1);
1035 if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
1036 PG_RETURN_NUMERIC(make_result(&const_nan));
1039 * Unpack the values, let sub_var() compute the result and return it.
1045 set_var_from_num(num1, &arg1);
1046 set_var_from_num(num2, &arg2);
1048 sub_var(&arg1, &arg2, &result);
1050 res = make_result(&result);
1056 PG_RETURN_NUMERIC(res);
1063 * Calculate the product of two numerics
1066 numeric_mul(PG_FUNCTION_ARGS)
1068 Numeric num1 = PG_GETARG_NUMERIC(0);
1069 Numeric num2 = PG_GETARG_NUMERIC(1);
1078 if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
1079 PG_RETURN_NUMERIC(make_result(&const_nan));
1082 * Unpack the values, let mul_var() compute the result and return it.
1083 * Unlike add_var() and sub_var(), mul_var() will round its result. In
1084 * the case of numeric_mul(), which is invoked for the * operator on
1085 * numerics, we request exact representation for the product (rscale =
1086 * sum(dscale of arg1, dscale of arg2)).
1092 set_var_from_num(num1, &arg1);
1093 set_var_from_num(num2, &arg2);
1095 mul_var(&arg1, &arg2, &result, arg1.dscale + arg2.dscale);
1097 res = make_result(&result);
1103 PG_RETURN_NUMERIC(res);
1110 * Divide one numeric into another
1113 numeric_div(PG_FUNCTION_ARGS)
1115 Numeric num1 = PG_GETARG_NUMERIC(0);
1116 Numeric num2 = PG_GETARG_NUMERIC(1);
1126 if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
1127 PG_RETURN_NUMERIC(make_result(&const_nan));
1130 * Unpack the arguments
1136 set_var_from_num(num1, &arg1);
1137 set_var_from_num(num2, &arg2);
1140 * Select scale for division result
1142 rscale = select_div_scale(&arg1, &arg2);
1145 * Do the divide and return the result
1147 div_var(&arg1, &arg2, &result, rscale);
1149 res = make_result(&result);
1155 PG_RETURN_NUMERIC(res);
1162 * Calculate the modulo of two numerics
1165 numeric_mod(PG_FUNCTION_ARGS)
1167 Numeric num1 = PG_GETARG_NUMERIC(0);
1168 Numeric num2 = PG_GETARG_NUMERIC(1);
1174 if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
1175 PG_RETURN_NUMERIC(make_result(&const_nan));
1181 set_var_from_num(num1, &arg1);
1182 set_var_from_num(num2, &arg2);
1184 mod_var(&arg1, &arg2, &result);
1186 res = make_result(&result);
1192 PG_RETURN_NUMERIC(res);
1199 * Increment a number by one
1202 numeric_inc(PG_FUNCTION_ARGS)
1204 Numeric num = PG_GETARG_NUMERIC(0);
1211 if (NUMERIC_IS_NAN(num))
1212 PG_RETURN_NUMERIC(make_result(&const_nan));
1215 * Compute the result and return it
1219 set_var_from_num(num, &arg);
1221 add_var(&arg, &const_one, &arg);
1223 res = make_result(&arg);
1227 PG_RETURN_NUMERIC(res);
1232 * numeric_smaller() -
1234 * Return the smaller of two numbers
1237 numeric_smaller(PG_FUNCTION_ARGS)
1239 Numeric num1 = PG_GETARG_NUMERIC(0);
1240 Numeric num2 = PG_GETARG_NUMERIC(1);
1243 * Use cmp_numerics so that this will agree with the comparison
1244 * operators, particularly as regards comparisons involving NaN.
1246 if (cmp_numerics(num1, num2) < 0)
1247 PG_RETURN_NUMERIC(num1);
1249 PG_RETURN_NUMERIC(num2);
1254 * numeric_larger() -
1256 * Return the larger of two numbers
1259 numeric_larger(PG_FUNCTION_ARGS)
1261 Numeric num1 = PG_GETARG_NUMERIC(0);
1262 Numeric num2 = PG_GETARG_NUMERIC(1);
1265 * Use cmp_numerics so that this will agree with the comparison
1266 * operators, particularly as regards comparisons involving NaN.
1268 if (cmp_numerics(num1, num2) > 0)
1269 PG_RETURN_NUMERIC(num1);
1271 PG_RETURN_NUMERIC(num2);
1275 /* ----------------------------------------------------------------------
1277 * Advanced math functions
1279 * ----------------------------------------------------------------------
1288 numeric_fac(PG_FUNCTION_ARGS)
1290 int64 num = PG_GETARG_INT64(0);
1297 res = make_result(&const_one);
1298 PG_RETURN_NUMERIC(res);
1304 int8_to_numericvar(num, &result);
1306 for (num = num - 1; num > 1; num--)
1308 int8_to_numericvar(num, &fact);
1310 mul_var(&result, &fact, &result, 0);
1313 res = make_result(&result);
1318 PG_RETURN_NUMERIC(res);
1325 * Compute the square root of a numeric.
1328 numeric_sqrt(PG_FUNCTION_ARGS)
1330 Numeric num = PG_GETARG_NUMERIC(0);
1340 if (NUMERIC_IS_NAN(num))
1341 PG_RETURN_NUMERIC(make_result(&const_nan));
1344 * Unpack the argument and determine the result scale. We choose a
1345 * scale to give at least NUMERIC_MIN_SIG_DIGITS significant digits;
1346 * but in any case not less than the input's dscale.
1351 set_var_from_num(num, &arg);
1353 /* Assume the input was normalized, so arg.weight is accurate */
1354 sweight = (arg.weight + 1) * DEC_DIGITS / 2 - 1;
1356 rscale = NUMERIC_MIN_SIG_DIGITS - sweight;
1357 rscale = Max(rscale, arg.dscale);
1358 rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
1359 rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
1362 * Let sqrt_var() do the calculation and return the result.
1364 sqrt_var(&arg, &result, rscale);
1366 res = make_result(&result);
1371 PG_RETURN_NUMERIC(res);
1378 * Raise e to the power of x
1381 numeric_exp(PG_FUNCTION_ARGS)
1383 Numeric num = PG_GETARG_NUMERIC(0);
1393 if (NUMERIC_IS_NAN(num))
1394 PG_RETURN_NUMERIC(make_result(&const_nan));
1397 * Unpack the argument and determine the result scale. We choose a
1398 * scale to give at least NUMERIC_MIN_SIG_DIGITS significant digits;
1399 * but in any case not less than the input's dscale.
1404 set_var_from_num(num, &arg);
1406 /* convert input to float8, ignoring overflow */
1407 val = numericvar_to_double_no_overflow(&arg);
1410 * log10(result) = num * log10(e), so this is approximately the
1411 * decimal weight of the result:
1413 val *= 0.434294481903252;
1415 /* limit to something that won't cause integer overflow */
1416 val = Max(val, -NUMERIC_MAX_RESULT_SCALE);
1417 val = Min(val, NUMERIC_MAX_RESULT_SCALE);
1419 rscale = NUMERIC_MIN_SIG_DIGITS - (int) val;
1420 rscale = Max(rscale, arg.dscale);
1421 rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
1422 rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
1425 * Let exp_var() do the calculation and return the result.
1427 exp_var(&arg, &result, rscale);
1429 res = make_result(&result);
1434 PG_RETURN_NUMERIC(res);
1441 * Compute the natural logarithm of x
1444 numeric_ln(PG_FUNCTION_ARGS)
1446 Numeric num = PG_GETARG_NUMERIC(0);
1456 if (NUMERIC_IS_NAN(num))
1457 PG_RETURN_NUMERIC(make_result(&const_nan));
1462 set_var_from_num(num, &arg);
1464 /* Approx decimal digits before decimal point */
1465 dec_digits = (arg.weight + 1) * DEC_DIGITS;
1468 rscale = NUMERIC_MIN_SIG_DIGITS - (int) log10(dec_digits - 1);
1469 else if (dec_digits < 1)
1470 rscale = NUMERIC_MIN_SIG_DIGITS - (int) log10(1 - dec_digits);
1472 rscale = NUMERIC_MIN_SIG_DIGITS;
1474 rscale = Max(rscale, arg.dscale);
1475 rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
1476 rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
1478 ln_var(&arg, &result, rscale);
1480 res = make_result(&result);
1485 PG_RETURN_NUMERIC(res);
1492 * Compute the logarithm of x in a given base
1495 numeric_log(PG_FUNCTION_ARGS)
1497 Numeric num1 = PG_GETARG_NUMERIC(0);
1498 Numeric num2 = PG_GETARG_NUMERIC(1);
1507 if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
1508 PG_RETURN_NUMERIC(make_result(&const_nan));
1517 set_var_from_num(num1, &arg1);
1518 set_var_from_num(num2, &arg2);
1521 * Call log_var() to compute and return the result; note it handles
1522 * scale selection itself.
1524 log_var(&arg1, &arg2, &result);
1526 res = make_result(&result);
1532 PG_RETURN_NUMERIC(res);
1539 * Raise b to the power of x
1542 numeric_power(PG_FUNCTION_ARGS)
1544 Numeric num1 = PG_GETARG_NUMERIC(0);
1545 Numeric num2 = PG_GETARG_NUMERIC(1);
1554 if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
1555 PG_RETURN_NUMERIC(make_result(&const_nan));
1564 set_var_from_num(num1, &arg1);
1565 set_var_from_num(num2, &arg2);
1568 * Call power_var() to compute and return the result; note it handles
1569 * scale selection itself.
1571 power_var(&arg1, &arg2, &result);
1573 res = make_result(&result);
1579 PG_RETURN_NUMERIC(res);
1583 /* ----------------------------------------------------------------------
1585 * Type conversion functions
1587 * ----------------------------------------------------------------------
1592 int4_numeric(PG_FUNCTION_ARGS)
1594 int32 val = PG_GETARG_INT32(0);
1600 int8_to_numericvar((int64) val, &result);
1602 res = make_result(&result);
1606 PG_RETURN_NUMERIC(res);
1611 numeric_int4(PG_FUNCTION_ARGS)
1613 Numeric num = PG_GETARG_NUMERIC(0);
1618 /* XXX would it be better to return NULL? */
1619 if (NUMERIC_IS_NAN(num))
1621 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1622 errmsg("cannot convert NaN to integer")));
1624 /* Convert to variable format and thence to int8 */
1626 set_var_from_num(num, &x);
1628 if (!numericvar_to_int8(&x, &val))
1630 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1631 errmsg("integer out of range")));
1635 /* Down-convert to int4 */
1636 result = (int32) val;
1638 /* Test for overflow by reverse-conversion. */
1639 if ((int64) result != val)
1641 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1642 errmsg("integer out of range")));
1644 PG_RETURN_INT32(result);
1649 int8_numeric(PG_FUNCTION_ARGS)
1651 int64 val = PG_GETARG_INT64(0);
1657 int8_to_numericvar(val, &result);
1659 res = make_result(&result);
1663 PG_RETURN_NUMERIC(res);
1668 numeric_int8(PG_FUNCTION_ARGS)
1670 Numeric num = PG_GETARG_NUMERIC(0);
1674 /* XXX would it be better to return NULL? */
1675 if (NUMERIC_IS_NAN(num))
1677 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1678 errmsg("cannot convert NaN to integer")));
1680 /* Convert to variable format and thence to int8 */
1682 set_var_from_num(num, &x);
1684 if (!numericvar_to_int8(&x, &result))
1686 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1687 errmsg("integer out of range")));
1691 PG_RETURN_INT64(result);
1696 int2_numeric(PG_FUNCTION_ARGS)
1698 int16 val = PG_GETARG_INT16(0);
1704 int8_to_numericvar((int64) val, &result);
1706 res = make_result(&result);
1710 PG_RETURN_NUMERIC(res);
1715 numeric_int2(PG_FUNCTION_ARGS)
1717 Numeric num = PG_GETARG_NUMERIC(0);
1722 /* XXX would it be better to return NULL? */
1723 if (NUMERIC_IS_NAN(num))
1725 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1726 errmsg("cannot convert NaN to integer")));
1728 /* Convert to variable format and thence to int8 */
1730 set_var_from_num(num, &x);
1732 if (!numericvar_to_int8(&x, &val))
1734 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1735 errmsg("integer out of range")));
1739 /* Down-convert to int2 */
1740 result = (int16) val;
1742 /* Test for overflow by reverse-conversion. */
1743 if ((int64) result != val)
1745 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1746 errmsg("integer out of range")));
1748 PG_RETURN_INT16(result);
1753 float8_numeric(PG_FUNCTION_ARGS)
1755 float8 val = PG_GETARG_FLOAT8(0);
1758 char buf[DBL_DIG + 100];
1761 PG_RETURN_NUMERIC(make_result(&const_nan));
1763 sprintf(buf, "%.*g", DBL_DIG, val);
1767 set_var_from_str(buf, &result);
1768 res = make_result(&result);
1772 PG_RETURN_NUMERIC(res);
1777 numeric_float8(PG_FUNCTION_ARGS)
1779 Numeric num = PG_GETARG_NUMERIC(0);
1783 if (NUMERIC_IS_NAN(num))
1784 PG_RETURN_FLOAT8(get_float8_nan());
1786 tmp = DatumGetCString(DirectFunctionCall1(numeric_out,
1787 NumericGetDatum(num)));
1789 result = DirectFunctionCall1(float8in, CStringGetDatum(tmp));
1793 PG_RETURN_DATUM(result);
1797 /* Convert numeric to float8; if out of range, return +/- HUGE_VAL */
1799 numeric_float8_no_overflow(PG_FUNCTION_ARGS)
1801 Numeric num = PG_GETARG_NUMERIC(0);
1804 if (NUMERIC_IS_NAN(num))
1805 PG_RETURN_FLOAT8(get_float8_nan());
1807 val = numeric_to_double_no_overflow(num);
1809 PG_RETURN_FLOAT8(val);
1813 float4_numeric(PG_FUNCTION_ARGS)
1815 float4 val = PG_GETARG_FLOAT4(0);
1818 char buf[FLT_DIG + 100];
1821 PG_RETURN_NUMERIC(make_result(&const_nan));
1823 sprintf(buf, "%.*g", FLT_DIG, val);
1827 set_var_from_str(buf, &result);
1828 res = make_result(&result);
1832 PG_RETURN_NUMERIC(res);
1837 numeric_float4(PG_FUNCTION_ARGS)
1839 Numeric num = PG_GETARG_NUMERIC(0);
1843 if (NUMERIC_IS_NAN(num))
1844 PG_RETURN_FLOAT4(get_float4_nan());
1846 tmp = DatumGetCString(DirectFunctionCall1(numeric_out,
1847 NumericGetDatum(num)));
1849 result = DirectFunctionCall1(float4in, CStringGetDatum(tmp));
1853 PG_RETURN_DATUM(result);
1858 text_numeric(PG_FUNCTION_ARGS)
1860 text *str = PG_GETARG_TEXT_P(0);
1865 len = (VARSIZE(str) - VARHDRSZ);
1866 s = palloc(len + 1);
1867 memcpy(s, VARDATA(str), len);
1870 result = DirectFunctionCall3(numeric_in, CStringGetDatum(s),
1871 ObjectIdGetDatum(0), Int32GetDatum(-1));
1879 numeric_text(PG_FUNCTION_ARGS)
1881 /* val is numeric, but easier to leave it as Datum */
1882 Datum val = PG_GETARG_DATUM(0);
1887 s = DatumGetCString(DirectFunctionCall1(numeric_out, val));
1890 result = (text *) palloc(VARHDRSZ + len);
1892 VARATT_SIZEP(result) = len + VARHDRSZ;
1893 memcpy(VARDATA(result), s, len);
1897 PG_RETURN_TEXT_P(result);
1901 /* ----------------------------------------------------------------------
1903 * Aggregate functions
1905 * The transition datatype for all these aggregates is a 3-element array
1906 * of Numeric, holding the values N, sum(X), sum(X*X) in that order.
1908 * We represent N as a numeric mainly to avoid having to build a special
1909 * datatype; it's unlikely it'd overflow an int4, but ...
1911 * ----------------------------------------------------------------------
1915 do_numeric_accum(ArrayType *transarray, Numeric newval)
1924 /* We assume the input is array of numeric */
1925 deconstruct_array(transarray,
1926 NUMERICOID, -1, false, 'i',
1927 &transdatums, &ndatums);
1929 elog(ERROR, "expected 3-element numeric array");
1931 sumX = transdatums[1];
1932 sumX2 = transdatums[2];
1934 N = DirectFunctionCall1(numeric_inc, N);
1935 sumX = DirectFunctionCall2(numeric_add, sumX,
1936 NumericGetDatum(newval));
1937 sumX2 = DirectFunctionCall2(numeric_add, sumX2,
1938 DirectFunctionCall2(numeric_mul,
1939 NumericGetDatum(newval),
1940 NumericGetDatum(newval)));
1943 transdatums[1] = sumX;
1944 transdatums[2] = sumX2;
1946 result = construct_array(transdatums, 3,
1947 NUMERICOID, -1, false, 'i');
1953 numeric_accum(PG_FUNCTION_ARGS)
1955 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
1956 Numeric newval = PG_GETARG_NUMERIC(1);
1958 PG_RETURN_ARRAYTYPE_P(do_numeric_accum(transarray, newval));
1962 * Integer data types all use Numeric accumulators to share code and
1963 * avoid risk of overflow. For int2 and int4 inputs, Numeric accumulation
1964 * is overkill for the N and sum(X) values, but definitely not overkill
1965 * for the sum(X*X) value. Hence, we use int2_accum and int4_accum only
1966 * for stddev/variance --- there are faster special-purpose accumulator
1967 * routines for SUM and AVG of these datatypes.
1971 int2_accum(PG_FUNCTION_ARGS)
1973 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
1974 Datum newval2 = PG_GETARG_DATUM(1);
1977 newval = DatumGetNumeric(DirectFunctionCall1(int2_numeric, newval2));
1979 PG_RETURN_ARRAYTYPE_P(do_numeric_accum(transarray, newval));
1983 int4_accum(PG_FUNCTION_ARGS)
1985 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
1986 Datum newval4 = PG_GETARG_DATUM(1);
1989 newval = DatumGetNumeric(DirectFunctionCall1(int4_numeric, newval4));
1991 PG_RETURN_ARRAYTYPE_P(do_numeric_accum(transarray, newval));
1995 int8_accum(PG_FUNCTION_ARGS)
1997 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
1998 Datum newval8 = PG_GETARG_DATUM(1);
2001 newval = DatumGetNumeric(DirectFunctionCall1(int8_numeric, newval8));
2003 PG_RETURN_ARRAYTYPE_P(do_numeric_accum(transarray, newval));
2007 numeric_avg(PG_FUNCTION_ARGS)
2009 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
2015 /* We assume the input is array of numeric */
2016 deconstruct_array(transarray,
2017 NUMERICOID, -1, false, 'i',
2018 &transdatums, &ndatums);
2020 elog(ERROR, "expected 3-element numeric array");
2021 N = DatumGetNumeric(transdatums[0]);
2022 sumX = DatumGetNumeric(transdatums[1]);
2025 /* SQL92 defines AVG of no values to be NULL */
2026 /* N is zero iff no digits (cf. numeric_uminus) */
2027 if (N->varlen == NUMERIC_HDRSZ)
2030 PG_RETURN_DATUM(DirectFunctionCall2(numeric_div,
2031 NumericGetDatum(sumX),
2032 NumericGetDatum(N)));
2036 numeric_variance(PG_FUNCTION_ARGS)
2038 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
2051 /* We assume the input is array of numeric */
2052 deconstruct_array(transarray,
2053 NUMERICOID, -1, false, 'i',
2054 &transdatums, &ndatums);
2056 elog(ERROR, "expected 3-element numeric array");
2057 N = DatumGetNumeric(transdatums[0]);
2058 sumX = DatumGetNumeric(transdatums[1]);
2059 sumX2 = DatumGetNumeric(transdatums[2]);
2061 if (NUMERIC_IS_NAN(N) || NUMERIC_IS_NAN(sumX) || NUMERIC_IS_NAN(sumX2))
2062 PG_RETURN_NUMERIC(make_result(&const_nan));
2064 /* Sample variance is undefined when N is 0 or 1, so return NULL */
2066 set_var_from_num(N, &vN);
2068 if (cmp_var(&vN, &const_one) <= 0)
2074 init_var(&vNminus1);
2075 sub_var(&vN, &const_one, &vNminus1);
2078 set_var_from_num(sumX, &vsumX);
2080 set_var_from_num(sumX2, &vsumX2);
2082 /* compute rscale for mul_var calls */
2083 rscale = vsumX.dscale * 2;
2085 mul_var(&vsumX, &vsumX, &vsumX, rscale); /* vsumX = sumX * sumX */
2086 mul_var(&vN, &vsumX2, &vsumX2, rscale); /* vsumX2 = N * sumX2 */
2087 sub_var(&vsumX2, &vsumX, &vsumX2); /* N * sumX2 - sumX * sumX */
2089 if (cmp_var(&vsumX2, &const_zero) <= 0)
2091 /* Watch out for roundoff error producing a negative numerator */
2092 res = make_result(&const_zero);
2096 mul_var(&vN, &vNminus1, &vNminus1, 0); /* N * (N - 1) */
2097 rscale = select_div_scale(&vsumX2, &vNminus1);
2098 div_var(&vsumX2, &vNminus1, &vsumX, rscale); /* variance */
2100 res = make_result(&vsumX);
2104 free_var(&vNminus1);
2108 PG_RETURN_NUMERIC(res);
2112 numeric_stddev(PG_FUNCTION_ARGS)
2114 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
2127 /* We assume the input is array of numeric */
2128 deconstruct_array(transarray,
2129 NUMERICOID, -1, false, 'i',
2130 &transdatums, &ndatums);
2132 elog(ERROR, "expected 3-element numeric array");
2133 N = DatumGetNumeric(transdatums[0]);
2134 sumX = DatumGetNumeric(transdatums[1]);
2135 sumX2 = DatumGetNumeric(transdatums[2]);
2137 if (NUMERIC_IS_NAN(N) || NUMERIC_IS_NAN(sumX) || NUMERIC_IS_NAN(sumX2))
2138 PG_RETURN_NUMERIC(make_result(&const_nan));
2140 /* Sample stddev is undefined when N is 0 or 1, so return NULL */
2142 set_var_from_num(N, &vN);
2144 if (cmp_var(&vN, &const_one) <= 0)
2150 init_var(&vNminus1);
2151 sub_var(&vN, &const_one, &vNminus1);
2154 set_var_from_num(sumX, &vsumX);
2156 set_var_from_num(sumX2, &vsumX2);
2158 /* compute rscale for mul_var calls */
2159 rscale = vsumX.dscale * 2;
2161 mul_var(&vsumX, &vsumX, &vsumX, rscale); /* vsumX = sumX * sumX */
2162 mul_var(&vN, &vsumX2, &vsumX2, rscale); /* vsumX2 = N * sumX2 */
2163 sub_var(&vsumX2, &vsumX, &vsumX2); /* N * sumX2 - sumX * sumX */
2165 if (cmp_var(&vsumX2, &const_zero) <= 0)
2167 /* Watch out for roundoff error producing a negative numerator */
2168 res = make_result(&const_zero);
2172 mul_var(&vN, &vNminus1, &vNminus1, 0); /* N * (N - 1) */
2173 rscale = select_div_scale(&vsumX2, &vNminus1);
2174 div_var(&vsumX2, &vNminus1, &vsumX, rscale); /* variance */
2175 sqrt_var(&vsumX, &vsumX, rscale); /* stddev */
2177 res = make_result(&vsumX);
2181 free_var(&vNminus1);
2185 PG_RETURN_NUMERIC(res);
2190 * SUM transition functions for integer datatypes.
2192 * To avoid overflow, we use accumulators wider than the input datatype.
2193 * A Numeric accumulator is needed for int8 input; for int4 and int2
2194 * inputs, we use int8 accumulators which should be sufficient for practical
2195 * purposes. (The latter two therefore don't really belong in this file,
2196 * but we keep them here anyway.)
2198 * Because SQL92 defines the SUM() of no values to be NULL, not zero,
2199 * the initial condition of the transition data value needs to be NULL. This
2200 * means we can't rely on ExecAgg to automatically insert the first non-null
2201 * data value into the transition data: it doesn't know how to do the type
2202 * conversion. The upshot is that these routines have to be marked non-strict
2203 * and handle substitution of the first non-null input themselves.
2207 int2_sum(PG_FUNCTION_ARGS)
2212 if (PG_ARGISNULL(0))
2214 /* No non-null input seen so far... */
2215 if (PG_ARGISNULL(1))
2216 PG_RETURN_NULL(); /* still no non-null */
2217 /* This is the first non-null input. */
2218 newval = (int64) PG_GETARG_INT16(1);
2219 PG_RETURN_INT64(newval);
2222 oldsum = PG_GETARG_INT64(0);
2224 /* Leave sum unchanged if new input is null. */
2225 if (PG_ARGISNULL(1))
2226 PG_RETURN_INT64(oldsum);
2228 /* OK to do the addition. */
2229 newval = oldsum + (int64) PG_GETARG_INT16(1);
2231 PG_RETURN_INT64(newval);
2235 int4_sum(PG_FUNCTION_ARGS)
2240 if (PG_ARGISNULL(0))
2242 /* No non-null input seen so far... */
2243 if (PG_ARGISNULL(1))
2244 PG_RETURN_NULL(); /* still no non-null */
2245 /* This is the first non-null input. */
2246 newval = (int64) PG_GETARG_INT32(1);
2247 PG_RETURN_INT64(newval);
2250 oldsum = PG_GETARG_INT64(0);
2252 /* Leave sum unchanged if new input is null. */
2253 if (PG_ARGISNULL(1))
2254 PG_RETURN_INT64(oldsum);
2256 /* OK to do the addition. */
2257 newval = oldsum + (int64) PG_GETARG_INT32(1);
2259 PG_RETURN_INT64(newval);
2263 int8_sum(PG_FUNCTION_ARGS)
2268 if (PG_ARGISNULL(0))
2270 /* No non-null input seen so far... */
2271 if (PG_ARGISNULL(1))
2272 PG_RETURN_NULL(); /* still no non-null */
2273 /* This is the first non-null input. */
2274 newval = DirectFunctionCall1(int8_numeric, PG_GETARG_DATUM(1));
2275 PG_RETURN_DATUM(newval);
2278 oldsum = PG_GETARG_NUMERIC(0);
2280 /* Leave sum unchanged if new input is null. */
2281 if (PG_ARGISNULL(1))
2282 PG_RETURN_NUMERIC(oldsum);
2284 /* OK to do the addition. */
2285 newval = DirectFunctionCall1(int8_numeric, PG_GETARG_DATUM(1));
2287 PG_RETURN_DATUM(DirectFunctionCall2(numeric_add,
2288 NumericGetDatum(oldsum), newval));
2293 * Routines for avg(int2) and avg(int4). The transition datatype
2294 * is a two-element int8 array, holding count and sum.
2297 typedef struct Int8TransTypeData
2299 #ifndef INT64_IS_BUSTED
2303 /* "int64" isn't really 64 bits, so fake up properly-aligned fields */
2309 } Int8TransTypeData;
2312 int2_avg_accum(PG_FUNCTION_ARGS)
2314 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P_COPY(0);
2315 int16 newval = PG_GETARG_INT16(1);
2316 Int8TransTypeData *transdata;
2319 * We copied the input array, so it's okay to scribble on it directly.
2321 if (ARR_SIZE(transarray) != ARR_OVERHEAD(1) + sizeof(Int8TransTypeData))
2322 elog(ERROR, "expected 2-element int8 array");
2323 transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
2326 transdata->sum += newval;
2328 PG_RETURN_ARRAYTYPE_P(transarray);
2332 int4_avg_accum(PG_FUNCTION_ARGS)
2334 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P_COPY(0);
2335 int32 newval = PG_GETARG_INT32(1);
2336 Int8TransTypeData *transdata;
2339 * We copied the input array, so it's okay to scribble on it directly.
2341 if (ARR_SIZE(transarray) != ARR_OVERHEAD(1) + sizeof(Int8TransTypeData))
2342 elog(ERROR, "expected 2-element int8 array");
2343 transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
2346 transdata->sum += newval;
2348 PG_RETURN_ARRAYTYPE_P(transarray);
2352 int8_avg(PG_FUNCTION_ARGS)
2354 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
2355 Int8TransTypeData *transdata;
2359 if (ARR_SIZE(transarray) != ARR_OVERHEAD(1) + sizeof(Int8TransTypeData))
2360 elog(ERROR, "expected 2-element int8 array");
2361 transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
2363 /* SQL92 defines AVG of no values to be NULL */
2364 if (transdata->count == 0)
2367 countd = DirectFunctionCall1(int8_numeric,
2368 Int64GetDatumFast(transdata->count));
2369 sumd = DirectFunctionCall1(int8_numeric,
2370 Int64GetDatumFast(transdata->sum));
2372 PG_RETURN_DATUM(DirectFunctionCall2(numeric_div, sumd, countd));
2376 /* ----------------------------------------------------------------------
2380 * ----------------------------------------------------------------------
2383 #ifdef NUMERIC_DEBUG
2386 * dump_numeric() - Dump a value in the db storage format for debugging
2389 dump_numeric(const char *str, Numeric num)
2391 NumericDigit *digits = (NumericDigit *) num->n_data;
2395 ndigits = (num->varlen - NUMERIC_HDRSZ) / sizeof(NumericDigit);
2397 printf("%s: NUMERIC w=%d d=%d ", str, num->n_weight, NUMERIC_DSCALE(num));
2398 switch (NUMERIC_SIGN(num))
2410 printf("SIGN=0x%x", NUMERIC_SIGN(num));
2414 for (i = 0; i < ndigits; i++)
2415 printf(" %0*d", DEC_DIGITS, digits[i]);
2421 * dump_var() - Dump a value in the variable format for debugging
2424 dump_var(const char *str, NumericVar *var)
2428 printf("%s: VAR w=%d d=%d ", str, var->weight, var->dscale);
2441 printf("SIGN=0x%x", var->sign);
2445 for (i = 0; i < var->ndigits; i++)
2446 printf(" %0*d", DEC_DIGITS, var->digits[i]);
2450 #endif /* NUMERIC_DEBUG */
2453 /* ----------------------------------------------------------------------
2455 * Local functions follow
2457 * In general, these do not support NaNs --- callers must eliminate
2458 * the possibility of NaN first. (make_result() is an exception.)
2460 * ----------------------------------------------------------------------
2467 * Allocate a digit buffer of ndigits digits (plus a spare digit for rounding)
2470 alloc_var(NumericVar *var, int ndigits)
2472 digitbuf_free(var->buf);
2473 var->buf = digitbuf_alloc(ndigits + 1);
2474 var->buf[0] = 0; /* spare digit for rounding */
2475 var->digits = var->buf + 1;
2476 var->ndigits = ndigits;
2483 * Return the digit buffer of a variable to the free pool
2486 free_var(NumericVar *var)
2488 digitbuf_free(var->buf);
2491 var->sign = NUMERIC_NAN;
2498 * Set a variable to ZERO.
2499 * Note: its dscale is not touched.
2502 zero_var(NumericVar *var)
2504 digitbuf_free(var->buf);
2508 var->weight = 0; /* by convention; doesn't really matter */
2509 var->sign = NUMERIC_POS; /* anything but NAN... */
2514 * set_var_from_str()
2516 * Parse a string and put the number into a variable
2519 set_var_from_str(const char *str, NumericVar *dest)
2521 const char *cp = str;
2522 bool have_dp = FALSE;
2524 unsigned char *decdigits;
2525 int sign = NUMERIC_POS;
2532 NumericDigit *digits;
2535 * We first parse the string to extract decimal digits and determine
2536 * the correct decimal weight. Then convert to NBASE representation.
2539 /* skip leading spaces */
2542 if (!isspace((unsigned char) *cp))
2566 if (!isdigit((unsigned char) *cp))
2568 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
2569 errmsg("invalid input syntax for type numeric: \"%s\"", str)));
2571 decdigits = (unsigned char *) palloc(strlen(cp) + DEC_DIGITS * 2);
2573 /* leading padding for digit alignment later */
2574 memset(decdigits, 0, DEC_DIGITS);
2579 if (isdigit((unsigned char) *cp))
2581 decdigits[i++] = *cp++ - '0';
2587 else if (*cp == '.')
2591 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
2592 errmsg("invalid input syntax for type numeric: \"%s\"",
2601 ddigits = i - DEC_DIGITS;
2602 /* trailing padding for digit alignment later */
2603 memset(decdigits + i, 0, DEC_DIGITS - 1);
2605 /* Handle exponent, if any */
2606 if (*cp == 'e' || *cp == 'E')
2612 exponent = strtol(cp, &endptr, 10);
2615 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
2616 errmsg("invalid input syntax for type numeric: \"%s\"",
2619 if (exponent > NUMERIC_MAX_PRECISION ||
2620 exponent < -NUMERIC_MAX_PRECISION)
2622 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
2623 errmsg("invalid input syntax for type numeric: \"%s\"",
2625 dweight += (int) exponent;
2626 dscale -= (int) exponent;
2631 /* Should be nothing left but spaces */
2634 if (!isspace((unsigned char) *cp))
2636 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
2637 errmsg("invalid input syntax for type numeric: \"%s\"",
2643 * Okay, convert pure-decimal representation to base NBASE. First we
2644 * need to determine the converted weight and ndigits. offset is the
2645 * number of decimal zeroes to insert before the first given digit to
2646 * have a correctly aligned first NBASE digit.
2649 weight = (dweight + 1 + DEC_DIGITS - 1) / DEC_DIGITS - 1;
2651 weight = -((-dweight - 1) / DEC_DIGITS + 1);
2652 offset = (weight + 1) * DEC_DIGITS - (dweight + 1);
2653 ndigits = (ddigits + offset + DEC_DIGITS - 1) / DEC_DIGITS;
2655 alloc_var(dest, ndigits);
2657 dest->weight = weight;
2658 dest->dscale = dscale;
2660 i = DEC_DIGITS - offset;
2661 digits = dest->digits;
2663 while (ndigits-- > 0)
2666 *digits++ = ((decdigits[i] * 10 + decdigits[i + 1]) * 10 +
2667 decdigits[i + 2]) * 10 + decdigits[i + 3];
2668 #elif DEC_DIGITS == 2
2669 *digits++ = decdigits[i] * 10 + decdigits[i + 1];
2670 #elif DEC_DIGITS == 1
2671 *digits++ = decdigits[i];
2673 #error unsupported NBASE
2680 /* Strip any leading/trailing zeroes, and normalize weight if zero */
2686 * set_var_from_num() -
2688 * Convert the packed db format into a variable
2691 set_var_from_num(Numeric num, NumericVar *dest)
2695 ndigits = (num->varlen - NUMERIC_HDRSZ) / sizeof(NumericDigit);
2697 alloc_var(dest, ndigits);
2699 dest->weight = num->n_weight;
2700 dest->sign = NUMERIC_SIGN(num);
2701 dest->dscale = NUMERIC_DSCALE(num);
2703 memcpy(dest->digits, num->n_data, ndigits * sizeof(NumericDigit));
2708 * set_var_from_var() -
2710 * Copy one variable into another
2713 set_var_from_var(NumericVar *value, NumericVar *dest)
2715 NumericDigit *newbuf;
2717 newbuf = digitbuf_alloc(value->ndigits + 1);
2718 newbuf[0] = 0; /* spare digit for rounding */
2719 memcpy(newbuf + 1, value->digits, value->ndigits * sizeof(NumericDigit));
2721 digitbuf_free(dest->buf);
2723 memmove(dest, value, sizeof(NumericVar));
2725 dest->digits = newbuf + 1;
2730 * get_str_from_var() -
2732 * Convert a var to text representation (guts of numeric_out).
2733 * CAUTION: var's contents may be modified by rounding!
2734 * Returns a palloc'd string.
2737 get_str_from_var(NumericVar *var, int dscale)
2754 * Check if we must round up before printing the value and do so.
2756 round_var(var, dscale);
2759 * Allocate space for the result.
2761 * i is set to to # of decimal digits before decimal point. dscale is the
2762 * # of decimal digits we will print after decimal point. We may
2763 * generate as many as DEC_DIGITS-1 excess digits at the end, and in
2764 * addition we need room for sign, decimal point, null terminator.
2766 i = (var->weight + 1) * DEC_DIGITS;
2770 str = palloc(i + dscale + DEC_DIGITS + 2);
2774 * Output a dash for negative values
2776 if (var->sign == NUMERIC_NEG)
2780 * Output all digits before the decimal point
2782 if (var->weight < 0)
2784 d = var->weight + 1;
2789 for (d = 0; d <= var->weight; d++)
2791 dig = (d < var->ndigits) ? var->digits[d] : 0;
2792 /* In the first digit, suppress extra leading decimal zeroes */
2795 bool putit = (d > 0);
2814 #elif DEC_DIGITS == 2
2817 if (d1 > 0 || d > 0)
2820 #elif DEC_DIGITS == 1
2823 #error unsupported NBASE
2829 * If requested, output a decimal point and all the digits that follow
2830 * it. We initially put out a multiple of DEC_DIGITS digits, then
2831 * truncate if needed.
2836 endcp = cp + dscale;
2837 for (i = 0; i < dscale; d++, i += DEC_DIGITS)
2839 dig = (d >= 0 && d < var->ndigits) ? var->digits[d] : 0;
2851 #elif DEC_DIGITS == 2
2856 #elif DEC_DIGITS == 1
2859 #error unsupported NBASE
2866 * terminate the string and return it
2876 * Create the packed db numeric format in palloc()'d memory from
2880 make_result(NumericVar *var)
2883 NumericDigit *digits = var->digits;
2884 int weight = var->weight;
2885 int sign = var->sign;
2889 if (sign == NUMERIC_NAN)
2891 result = (Numeric) palloc(NUMERIC_HDRSZ);
2893 result->varlen = NUMERIC_HDRSZ;
2894 result->n_weight = 0;
2895 result->n_sign_dscale = NUMERIC_NAN;
2897 dump_numeric("make_result()", result);
2903 /* truncate leading zeroes */
2904 while (n > 0 && *digits == 0)
2910 /* truncate trailing zeroes */
2911 while (n > 0 && digits[n - 1] == 0)
2914 /* If zero result, force to weight=0 and positive sign */
2921 /* Build the result */
2922 len = NUMERIC_HDRSZ + n * sizeof(NumericDigit);
2923 result = (Numeric) palloc(len);
2924 result->varlen = len;
2925 result->n_weight = weight;
2926 result->n_sign_dscale = sign | (var->dscale & NUMERIC_DSCALE_MASK);
2928 memcpy(result->n_data, digits, n * sizeof(NumericDigit));
2930 /* Check for overflow of int16 fields */
2931 if (result->n_weight != weight ||
2932 NUMERIC_DSCALE(result) != var->dscale)
2934 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
2935 errmsg("value overflows numeric format")));
2937 dump_numeric("make_result()", result);
2945 * Do bounds checking and rounding according to the attributes
2949 apply_typmod(NumericVar *var, int32 typmod)
2957 /* Do nothing if we have a default typmod (-1) */
2958 if (typmod < (int32) (VARHDRSZ))
2962 precision = (typmod >> 16) & 0xffff;
2963 scale = typmod & 0xffff;
2964 maxdigits = precision - scale;
2966 /* Round to target scale (and set var->dscale) */
2967 round_var(var, scale);
2970 * Check for overflow - note we can't do this before rounding, because
2971 * rounding could raise the weight. Also note that the var's weight
2972 * could be inflated by leading zeroes, which will be stripped before
2973 * storage but perhaps might not have been yet. In any case, we must
2974 * recognize a true zero, whose weight doesn't mean anything.
2976 ddigits = (var->weight + 1) * DEC_DIGITS;
2977 if (ddigits > maxdigits)
2979 /* Determine true weight; and check for all-zero result */
2980 for (i = 0; i < var->ndigits; i++)
2982 NumericDigit dig = var->digits[i];
2986 /* Adjust for any high-order decimal zero digits */
2992 else if (dig < 1000)
2994 #elif DEC_DIGITS == 2
2997 #elif DEC_DIGITS == 1
3000 #error unsupported NBASE
3002 if (ddigits > maxdigits)
3004 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
3005 errmsg("numeric field overflow"),
3006 errdetail("The absolute value is greater than or equal to 10^%d for field with precision %d, scale %d.",
3007 ddigits - 1, precision, scale)));
3010 ddigits -= DEC_DIGITS;
3016 * Convert numeric to int8, rounding if needed.
3018 * If overflow, return FALSE (no error is raised). Return TRUE if okay.
3020 * CAUTION: var's contents may be modified by rounding!
3023 numericvar_to_int8(NumericVar *var, int64 *result)
3025 NumericDigit *digits;
3033 /* Round to nearest integer */
3036 /* Check for zero input */
3038 ndigits = var->ndigits;
3046 * For input like 10000000000, we must treat stripped digits as real.
3047 * So the loop assumes there are weight+1 digits before the decimal
3050 weight = var->weight;
3051 Assert(weight >= 0 && ndigits <= weight + 1);
3053 /* Construct the result */
3054 digits = var->digits;
3055 neg = (var->sign == NUMERIC_NEG);
3057 for (i = 1; i <= weight; i++)
3065 * The overflow check is a bit tricky because we want to accept
3066 * INT64_MIN, which will overflow the positive accumulator. We
3067 * can detect this case easily though because INT64_MIN is the
3068 * only nonzero value for which -val == val (on a two's complement
3071 if ((val / NBASE) != oldval) /* possible overflow? */
3073 if (!neg || (-val) != val || val == 0 || oldval < 0)
3078 *result = neg ? -val : val;
3083 * Convert int8 value to numeric.
3086 int8_to_numericvar(int64 val, NumericVar *var)
3093 /* int8 can require at most 19 decimal digits; add one for safety */
3094 alloc_var(var, 20 / DEC_DIGITS);
3097 var->sign = NUMERIC_NEG;
3102 var->sign = NUMERIC_POS;
3112 ptr = var->digits + var->ndigits;
3118 newuval = uval / NBASE;
3119 *ptr = uval - newuval * NBASE;
3123 var->ndigits = ndigits;
3124 var->weight = ndigits - 1;
3128 * Convert numeric to float8; if out of range, return +/- HUGE_VAL
3131 numeric_to_double_no_overflow(Numeric num)
3137 tmp = DatumGetCString(DirectFunctionCall1(numeric_out,
3138 NumericGetDatum(num)));
3140 /* unlike float8in, we ignore ERANGE from strtod */
3141 val = strtod(tmp, &endptr);
3142 if (*endptr != '\0')
3144 /* shouldn't happen ... */
3146 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
3147 errmsg("invalid input syntax for type double precision: \"%s\"",
3156 /* As above, but work from a NumericVar */
3158 numericvar_to_double_no_overflow(NumericVar *var)
3164 tmp = get_str_from_var(var, var->dscale);
3166 /* unlike float8in, we ignore ERANGE from strtod */
3167 val = strtod(tmp, &endptr);
3168 if (*endptr != '\0')
3170 /* shouldn't happen ... */
3172 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
3173 errmsg("invalid input syntax for type double precision: \"%s\"",
3186 * Compare two values on variable level. We assume zeroes have been
3187 * truncated to no digits.
3190 cmp_var(NumericVar *var1, NumericVar *var2)
3192 if (var1->ndigits == 0)
3194 if (var2->ndigits == 0)
3196 if (var2->sign == NUMERIC_NEG)
3200 if (var2->ndigits == 0)
3202 if (var1->sign == NUMERIC_POS)
3207 if (var1->sign == NUMERIC_POS)
3209 if (var2->sign == NUMERIC_NEG)
3211 return cmp_abs(var1, var2);
3214 if (var2->sign == NUMERIC_POS)
3217 return cmp_abs(var2, var1);
3224 * Full version of add functionality on variable level (handling signs).
3225 * result might point to one of the operands too without danger.
3228 add_var(NumericVar *var1, NumericVar *var2, NumericVar *result)
3231 * Decide on the signs of the two variables what to do
3233 if (var1->sign == NUMERIC_POS)
3235 if (var2->sign == NUMERIC_POS)
3238 * Both are positive result = +(ABS(var1) + ABS(var2))
3240 add_abs(var1, var2, result);
3241 result->sign = NUMERIC_POS;
3246 * var1 is positive, var2 is negative Must compare absolute
3249 switch (cmp_abs(var1, var2))
3253 * ABS(var1) == ABS(var2)
3258 result->dscale = Max(var1->dscale, var2->dscale);
3263 * ABS(var1) > ABS(var2)
3264 * result = +(ABS(var1) - ABS(var2))
3267 sub_abs(var1, var2, result);
3268 result->sign = NUMERIC_POS;
3273 * ABS(var1) < ABS(var2)
3274 * result = -(ABS(var2) - ABS(var1))
3277 sub_abs(var2, var1, result);
3278 result->sign = NUMERIC_NEG;
3285 if (var2->sign == NUMERIC_POS)
3288 * var1 is negative, var2 is positive
3289 * Must compare absolute values
3292 switch (cmp_abs(var1, var2))
3296 * ABS(var1) == ABS(var2)
3301 result->dscale = Max(var1->dscale, var2->dscale);
3306 * ABS(var1) > ABS(var2)
3307 * result = -(ABS(var1) - ABS(var2))
3310 sub_abs(var1, var2, result);
3311 result->sign = NUMERIC_NEG;
3316 * ABS(var1) < ABS(var2)
3317 * result = +(ABS(var2) - ABS(var1))
3320 sub_abs(var2, var1, result);
3321 result->sign = NUMERIC_POS;
3329 * result = -(ABS(var1) + ABS(var2))
3332 add_abs(var1, var2, result);
3333 result->sign = NUMERIC_NEG;
3342 * Full version of sub functionality on variable level (handling signs).
3343 * result might point to one of the operands too without danger.
3346 sub_var(NumericVar *var1, NumericVar *var2, NumericVar *result)
3349 * Decide on the signs of the two variables what to do
3351 if (var1->sign == NUMERIC_POS)
3353 if (var2->sign == NUMERIC_NEG)
3356 * var1 is positive, var2 is negative
3357 * result = +(ABS(var1) + ABS(var2))
3360 add_abs(var1, var2, result);
3361 result->sign = NUMERIC_POS;
3367 * Must compare absolute values
3370 switch (cmp_abs(var1, var2))
3374 * ABS(var1) == ABS(var2)
3379 result->dscale = Max(var1->dscale, var2->dscale);
3384 * ABS(var1) > ABS(var2)
3385 * result = +(ABS(var1) - ABS(var2))
3388 sub_abs(var1, var2, result);
3389 result->sign = NUMERIC_POS;
3394 * ABS(var1) < ABS(var2)
3395 * result = -(ABS(var2) - ABS(var1))
3398 sub_abs(var2, var1, result);
3399 result->sign = NUMERIC_NEG;
3406 if (var2->sign == NUMERIC_NEG)
3410 * Must compare absolute values
3413 switch (cmp_abs(var1, var2))
3417 * ABS(var1) == ABS(var2)
3422 result->dscale = Max(var1->dscale, var2->dscale);
3427 * ABS(var1) > ABS(var2)
3428 * result = -(ABS(var1) - ABS(var2))
3431 sub_abs(var1, var2, result);
3432 result->sign = NUMERIC_NEG;
3437 * ABS(var1) < ABS(var2)
3438 * result = +(ABS(var2) - ABS(var1))
3441 sub_abs(var2, var1, result);
3442 result->sign = NUMERIC_POS;
3449 * var1 is negative, var2 is positive
3450 * result = -(ABS(var1) + ABS(var2))
3453 add_abs(var1, var2, result);
3454 result->sign = NUMERIC_NEG;
3463 * Multiplication on variable level. Product of var1 * var2 is stored
3464 * in result. Result is rounded to no more than rscale fractional digits.
3467 mul_var(NumericVar *var1, NumericVar *var2, NumericVar *result,
3478 NumericDigit *res_digits;
3484 /* copy these values into local vars for speed in inner loop */
3485 int var1ndigits = var1->ndigits;
3486 int var2ndigits = var2->ndigits;
3487 NumericDigit *var1digits = var1->digits;
3488 NumericDigit *var2digits = var2->digits;
3490 if (var1ndigits == 0 || var2ndigits == 0)
3492 /* one or both inputs is zero; so is result */
3494 result->dscale = rscale;
3498 /* Determine result sign and (maximum possible) weight */
3499 if (var1->sign == var2->sign)
3500 res_sign = NUMERIC_POS;
3502 res_sign = NUMERIC_NEG;
3503 res_weight = var1->weight + var2->weight + 2;
3506 * Determine number of result digits to compute. If the exact result
3507 * would have more than rscale fractional digits, truncate the
3508 * computation with MUL_GUARD_DIGITS guard digits. We do that by
3509 * pretending that one or both inputs have fewer digits than they
3512 res_ndigits = var1ndigits + var2ndigits + 1;
3513 maxdigits = res_weight + 1 + (rscale * DEC_DIGITS) + MUL_GUARD_DIGITS;
3514 if (res_ndigits > maxdigits)
3518 /* no useful precision at all in the result... */
3520 result->dscale = rscale;
3523 /* force maxdigits odd so that input ndigits can be equal */
3524 if ((maxdigits & 1) == 0)
3526 if (var1ndigits > var2ndigits)
3528 var1ndigits -= res_ndigits - maxdigits;
3529 if (var1ndigits < var2ndigits)
3530 var1ndigits = var2ndigits = (var1ndigits + var2ndigits) / 2;
3534 var2ndigits -= res_ndigits - maxdigits;
3535 if (var2ndigits < var1ndigits)
3536 var1ndigits = var2ndigits = (var1ndigits + var2ndigits) / 2;
3538 res_ndigits = maxdigits;
3539 Assert(res_ndigits == var1ndigits + var2ndigits + 1);
3543 * We do the arithmetic in an array "dig[]" of signed int's. Since
3544 * INT_MAX is noticeably larger than NBASE*NBASE, this gives us
3545 * headroom to avoid normalizing carries immediately.
3547 * maxdig tracks the maximum possible value of any dig[] entry; when this
3548 * threatens to exceed INT_MAX, we take the time to propagate carries.
3549 * To avoid overflow in maxdig itself, it actually represents the max
3550 * possible value divided by NBASE-1.
3552 dig = (int *) palloc0(res_ndigits * sizeof(int));
3555 ri = res_ndigits - 1;
3556 for (i1 = var1ndigits - 1; i1 >= 0; ri--, i1--)
3558 int var1digit = var1digits[i1];
3563 /* Time to normalize? */
3564 maxdig += var1digit;
3565 if (maxdig > INT_MAX / (NBASE - 1))
3569 for (i = res_ndigits - 1; i >= 0; i--)
3571 newdig = dig[i] + carry;
3572 if (newdig >= NBASE)
3574 carry = newdig / NBASE;
3575 newdig -= carry * NBASE;
3582 /* Reset maxdig to indicate new worst-case */
3583 maxdig = 1 + var1digit;
3586 /* Add appropriate multiple of var2 into the accumulator */
3588 for (i2 = var2ndigits - 1; i2 >= 0; i2--)
3589 dig[i--] += var1digit * var2digits[i2];
3593 * Now we do a final carry propagation pass to normalize the result,
3594 * which we combine with storing the result digits into the output.
3595 * Note that this is still done at full precision w/guard digits.
3597 alloc_var(result, res_ndigits);
3598 res_digits = result->digits;
3600 for (i = res_ndigits - 1; i >= 0; i--)
3602 newdig = dig[i] + carry;
3603 if (newdig >= NBASE)
3605 carry = newdig / NBASE;
3606 newdig -= carry * NBASE;
3610 res_digits[i] = newdig;
3617 * Finally, round the result to the requested precision.
3619 result->weight = res_weight;
3620 result->sign = res_sign;
3622 /* Round to target rscale (and set result->dscale) */
3623 round_var(result, rscale);
3625 /* Strip leading and trailing zeroes */
3633 * Division on variable level. Quotient of var1 / var2 is stored
3634 * in result. Result is rounded to no more than rscale fractional digits.
3637 div_var(NumericVar *var1, NumericVar *var2, NumericVar *result,
3648 NumericDigit *res_digits;
3656 /* copy these values into local vars for speed in inner loop */
3657 int var1ndigits = var1->ndigits;
3658 int var2ndigits = var2->ndigits;
3659 NumericDigit *var1digits = var1->digits;
3660 NumericDigit *var2digits = var2->digits;
3663 * First of all division by zero check; we must not be handed an
3664 * unnormalized divisor.
3666 if (var2ndigits == 0 || var2digits[0] == 0)
3668 (errcode(ERRCODE_DIVISION_BY_ZERO),
3669 errmsg("division by zero")));
3672 * Now result zero check
3674 if (var1ndigits == 0)
3677 result->dscale = rscale;
3682 * Determine the result sign, weight and number of digits to calculate
3684 if (var1->sign == var2->sign)
3685 res_sign = NUMERIC_POS;
3687 res_sign = NUMERIC_NEG;
3688 res_weight = var1->weight - var2->weight + 1;
3689 /* The number of accurate result digits we need to produce: */
3690 div_ndigits = res_weight + 1 + (rscale + DEC_DIGITS - 1) / DEC_DIGITS;
3691 /* Add guard digits for roundoff error */
3692 div_ndigits += DIV_GUARD_DIGITS;
3693 if (div_ndigits < DIV_GUARD_DIGITS)
3694 div_ndigits = DIV_GUARD_DIGITS;
3695 /* Must be at least var1ndigits, too, to simplify data-loading loop */
3696 if (div_ndigits < var1ndigits)
3697 div_ndigits = var1ndigits;
3700 * We do the arithmetic in an array "div[]" of signed int's. Since
3701 * INT_MAX is noticeably larger than NBASE*NBASE, this gives us
3702 * headroom to avoid normalizing carries immediately.
3704 * We start with div[] containing one zero digit followed by the
3705 * dividend's digits (plus appended zeroes to reach the desired
3706 * precision including guard digits). Each step of the main loop
3707 * computes an (approximate) quotient digit and stores it into div[],
3708 * removing one position of dividend space. A final pass of carry
3709 * propagation takes care of any mistaken quotient digits.
3711 div = (int *) palloc0((div_ndigits + 1) * sizeof(int));
3712 for (i = 0; i < var1ndigits; i++)
3713 div[i + 1] = var1digits[i];
3716 * We estimate each quotient digit using floating-point arithmetic,
3717 * taking the first four digits of the (current) dividend and divisor.
3718 * This must be float to avoid overflow.
3720 fdivisor = (double) var2digits[0];
3721 for (i = 1; i < 4; i++)
3724 if (i < var2ndigits)
3725 fdivisor += (double) var2digits[i];
3727 fdivisorinverse = 1.0 / fdivisor;
3730 * maxdiv tracks the maximum possible absolute value of any div[]
3731 * entry; when this threatens to exceed INT_MAX, we take the time to
3732 * propagate carries. To avoid overflow in maxdiv itself, it actually
3733 * represents the max possible abs. value divided by NBASE-1.
3738 * Outer loop computes next quotient digit, which will go into div[qi]
3740 for (qi = 0; qi < div_ndigits; qi++)
3742 /* Approximate the current dividend value */
3743 fdividend = (double) div[qi];
3744 for (i = 1; i < 4; i++)
3747 if (qi + i <= div_ndigits)
3748 fdividend += (double) div[qi + i];
3750 /* Compute the (approximate) quotient digit */
3751 fquotient = fdividend * fdivisorinverse;
3752 qdigit = (fquotient >= 0.0) ? ((int) fquotient) :
3753 (((int) fquotient) - 1); /* truncate towards -infinity */
3757 /* Do we need to normalize now? */
3758 maxdiv += Abs(qdigit);
3759 if (maxdiv > INT_MAX / (NBASE - 1))
3763 for (i = div_ndigits; i > qi; i--)
3765 newdig = div[i] + carry;
3768 carry = -((-newdig - 1) / NBASE) - 1;
3769 newdig -= carry * NBASE;
3771 else if (newdig >= NBASE)
3773 carry = newdig / NBASE;
3774 newdig -= carry * NBASE;
3780 newdig = div[qi] + carry;
3784 * All the div[] digits except possibly div[qi] are now in
3785 * the range 0..NBASE-1.
3787 maxdiv = Abs(newdig) / (NBASE - 1);
3788 maxdiv = Max(maxdiv, 1);
3791 * Recompute the quotient digit since new info may have
3792 * propagated into the top four dividend digits
3794 fdividend = (double) div[qi];
3795 for (i = 1; i < 4; i++)
3798 if (qi + i <= div_ndigits)
3799 fdividend += (double) div[qi + i];
3801 /* Compute the (approximate) quotient digit */
3802 fquotient = fdividend * fdivisorinverse;
3803 qdigit = (fquotient >= 0.0) ? ((int) fquotient) :
3804 (((int) fquotient) - 1); /* truncate towards
3806 maxdiv += Abs(qdigit);
3809 /* Subtract off the appropriate multiple of the divisor */
3812 int istop = Min(var2ndigits, div_ndigits - qi + 1);
3814 for (i = 0; i < istop; i++)
3815 div[qi + i] -= qdigit * var2digits[i];
3820 * The dividend digit we are about to replace might still be
3821 * nonzero. Fold it into the next digit position. We don't need
3822 * to worry about overflow here since this should nearly cancel
3823 * with the subtraction of the divisor.
3825 div[qi + 1] += div[qi] * NBASE;
3831 * Approximate and store the last quotient digit (div[div_ndigits])
3833 fdividend = (double) div[qi];
3834 for (i = 1; i < 4; i++)
3836 fquotient = fdividend * fdivisorinverse;
3837 qdigit = (fquotient >= 0.0) ? ((int) fquotient) :
3838 (((int) fquotient) - 1); /* truncate towards -infinity */
3842 * Now we do a final carry propagation pass to normalize the result,
3843 * which we combine with storing the result digits into the output.
3844 * Note that this is still done at full precision w/guard digits.
3846 alloc_var(result, div_ndigits + 1);
3847 res_digits = result->digits;
3849 for (i = div_ndigits; i >= 0; i--)
3851 newdig = div[i] + carry;
3854 carry = -((-newdig - 1) / NBASE) - 1;
3855 newdig -= carry * NBASE;
3857 else if (newdig >= NBASE)
3859 carry = newdig / NBASE;
3860 newdig -= carry * NBASE;
3864 res_digits[i] = newdig;
3871 * Finally, round the result to the requested precision.
3873 result->weight = res_weight;
3874 result->sign = res_sign;
3876 /* Round to target rscale (and set result->dscale) */
3877 round_var(result, rscale);
3879 /* Strip leading and trailing zeroes */
3885 * Default scale selection for division
3887 * Returns the appropriate result scale for the division result.
3890 select_div_scale(NumericVar *var1, NumericVar *var2)
3896 NumericDigit firstdigit1,
3901 * The result scale of a division isn't specified in any SQL standard.
3902 * For PostgreSQL we select a result scale that will give at least
3903 * NUMERIC_MIN_SIG_DIGITS significant digits, so that numeric gives a
3904 * result no less accurate than float8; but use a scale not less than
3905 * either input's display scale.
3908 /* Get the actual (normalized) weight and first digit of each input */
3910 weight1 = 0; /* values to use if var1 is zero */
3912 for (i = 0; i < var1->ndigits; i++)
3914 firstdigit1 = var1->digits[i];
3915 if (firstdigit1 != 0)
3917 weight1 = var1->weight - i;
3922 weight2 = 0; /* values to use if var2 is zero */
3924 for (i = 0; i < var2->ndigits; i++)
3926 firstdigit2 = var2->digits[i];
3927 if (firstdigit2 != 0)
3929 weight2 = var2->weight - i;
3935 * Estimate weight of quotient. If the two first digits are equal, we
3936 * can't be sure, but assume that var1 is less than var2.
3938 qweight = weight1 - weight2;
3939 if (firstdigit1 <= firstdigit2)
3942 /* Select result scale */
3943 rscale = NUMERIC_MIN_SIG_DIGITS - qweight * DEC_DIGITS;
3944 rscale = Max(rscale, var1->dscale);
3945 rscale = Max(rscale, var2->dscale);
3946 rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
3947 rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
3956 * Calculate the modulo of two numerics at variable level
3959 mod_var(NumericVar *var1, NumericVar *var2, NumericVar *result)
3967 * We do this using the equation
3968 * mod(x,y) = x - trunc(x/y)*y
3969 * We set rscale the same way numeric_div and numeric_mul do
3970 * to get the right answer from the equation. The final result,
3971 * however, need not be displayed to more precision than the inputs.
3974 rscale = select_div_scale(var1, var2);
3976 div_var(var1, var2, &tmp, rscale);
3980 mul_var(var2, &tmp, &tmp, var2->dscale + tmp.dscale);
3982 sub_var(var1, &tmp, result);
3984 round_var(result, Max(var1->dscale, var2->dscale));
3993 * Return the smallest integer greater than or equal to the argument
3997 ceil_var(NumericVar *var, NumericVar *result)
4002 set_var_from_var(var, &tmp);
4006 if (var->sign == NUMERIC_POS && cmp_var(var, &tmp) != 0)
4007 add_var(&tmp, &const_one, &tmp);
4009 set_var_from_var(&tmp, result);
4017 * Return the largest integer equal to or less than the argument
4021 floor_var(NumericVar *var, NumericVar *result)
4026 set_var_from_var(var, &tmp);
4030 if (var->sign == NUMERIC_NEG && cmp_var(var, &tmp) != 0)
4031 sub_var(&tmp, &const_one, &tmp);
4033 set_var_from_var(&tmp, result);
4041 * Compute the square root of x using Newton's algorithm
4044 sqrt_var(NumericVar *arg, NumericVar *result, int rscale)
4048 NumericVar last_val;
4052 local_rscale = rscale + 8;
4054 stat = cmp_var(arg, &const_zero);
4058 result->dscale = rscale;
4064 (errcode(ERRCODE_FLOATING_POINT_EXCEPTION),
4065 errmsg("cannot take square root of a negative number")));
4069 init_var(&last_val);
4071 /* Copy arg in case it is the same var as result */
4072 set_var_from_var(arg, &tmp_arg);
4075 * Initialize the result to the first guess
4077 alloc_var(result, 1);
4078 result->digits[0] = tmp_arg.digits[0] / 2;
4079 if (result->digits[0] == 0)
4080 result->digits[0] = 1;
4081 result->weight = tmp_arg.weight / 2;
4082 result->sign = NUMERIC_POS;
4084 set_var_from_var(result, &last_val);
4088 div_var(&tmp_arg, result, &tmp_val, local_rscale);
4090 add_var(result, &tmp_val, result);
4091 mul_var(result, &const_zero_point_five, result, local_rscale);
4093 if (cmp_var(&last_val, result) == 0)
4095 set_var_from_var(result, &last_val);
4098 free_var(&last_val);
4102 /* Round to requested precision */
4103 round_var(result, rscale);
4110 * Raise e to the power of x
4113 exp_var(NumericVar *arg, NumericVar *result, int rscale)
4121 * We separate the integral and fraction parts of x, then compute
4122 * e^x = e^xint * e^xfrac
4123 * where e = exp(1) and e^xfrac = exp(xfrac) are computed by
4124 * exp_var_internal; the limited range of inputs allows that routine
4125 * to do a good job with a simple Taylor series. Raising e^xint is
4126 * done by repeated multiplications in power_var_int.
4131 set_var_from_var(arg, &x);
4133 if (x.sign == NUMERIC_NEG)
4136 x.sign = NUMERIC_POS;
4139 /* Extract the integer part, remove it from x */
4141 while (x.weight >= 0)
4146 xintval += x.digits[0];
4151 /* Guard against overflow */
4152 if (xintval >= NUMERIC_MAX_RESULT_SCALE * 3)
4154 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
4155 errmsg("argument for function \"exp\" too big")));
4158 /* Select an appropriate scale for internal calculation */
4159 local_rscale = rscale + MUL_GUARD_DIGITS * 2;
4161 /* Compute e^xfrac */
4162 exp_var_internal(&x, result, local_rscale);
4164 /* If there's an integer part, multiply by e^xint */
4170 exp_var_internal(&const_one, &e, local_rscale);
4171 power_var_int(&e, xintval, &e, local_rscale);
4172 mul_var(&e, result, result, local_rscale);
4176 /* Compensate for input sign, and round to requested rscale */
4178 div_var(&const_one, result, result, rscale);
4180 round_var(result, rscale);
4187 * exp_var_internal() -
4189 * Raise e to the power of x, where 0 <= x <= 1
4191 * NB: the result should be good to at least rscale digits, but it has
4192 * *not* been rounded off; the caller must do that if wanted.
4195 exp_var_internal(NumericVar *arg, NumericVar *result, int rscale)
4211 set_var_from_var(arg, &x);
4213 Assert(x.sign == NUMERIC_POS);
4215 local_rscale = rscale + 8;
4217 /* Reduce input into range 0 <= x <= 0.01 */
4218 while (cmp_var(&x, &const_zero_point_01) > 0)
4222 mul_var(&x, &const_zero_point_five, &x, x.dscale + 1);
4226 * Use the Taylor series
4228 * exp(x) = 1 + x + x^2/2! + x^3/3! + ...
4230 * Given the limited range of x, this should converge reasonably quickly.
4231 * We run the series until the terms fall below the local_rscale
4234 add_var(&const_one, &x, result);
4235 set_var_from_var(&x, &xpow);
4236 set_var_from_var(&const_one, &ifac);
4237 set_var_from_var(&const_one, &ni);
4241 add_var(&ni, &const_one, &ni);
4242 mul_var(&xpow, &x, &xpow, local_rscale);
4243 mul_var(&ifac, &ni, &ifac, 0);
4244 div_var(&xpow, &ifac, &elem, local_rscale);
4246 if (elem.ndigits == 0)
4249 add_var(result, &elem, result);
4252 /* Compensate for argument range reduction */
4254 mul_var(result, result, result, local_rscale);
4267 * Compute the natural log of x
4270 ln_var(NumericVar *arg, NumericVar *result, int rscale)
4279 if (cmp_var(arg, &const_zero) <= 0)
4281 (errcode(ERRCODE_FLOATING_POINT_EXCEPTION),
4282 errmsg("cannot take logarithm of a negative number")));
4284 local_rscale = rscale + 8;
4292 set_var_from_var(arg, &x);
4293 set_var_from_var(&const_two, &fact);
4295 /* Reduce input into range 0.9 < x < 1.1 */
4296 while (cmp_var(&x, &const_zero_point_nine) <= 0)
4299 sqrt_var(&x, &x, local_rscale);
4300 mul_var(&fact, &const_two, &fact, 0);
4302 while (cmp_var(&x, &const_one_point_one) >= 0)
4305 sqrt_var(&x, &x, local_rscale);
4306 mul_var(&fact, &const_two, &fact, 0);
4310 * We use the Taylor series for 0.5 * ln((1+z)/(1-z)),
4312 * z + z^3/3 + z^5/5 + ...
4314 * where z = (x-1)/(x+1) is in the range (approximately) -0.053 .. 0.048
4315 * due to the above range-reduction of x.
4317 * The convergence of this is not as fast as one would like, but is
4318 * tolerable given that z is small.
4320 sub_var(&x, &const_one, result);
4321 add_var(&x, &const_one, &elem);
4322 div_var(result, &elem, result, local_rscale);
4323 set_var_from_var(result, &xx);
4324 mul_var(result, result, &x, local_rscale);
4326 set_var_from_var(&const_one, &ni);
4330 add_var(&ni, &const_two, &ni);
4331 mul_var(&xx, &x, &xx, local_rscale);
4332 div_var(&xx, &ni, &elem, local_rscale);
4334 if (elem.ndigits == 0)
4337 add_var(result, &elem, result);
4339 if (elem.weight < (result->weight - local_rscale * 2 / DEC_DIGITS))
4343 /* Compensate for argument range reduction, round to requested rscale */
4344 mul_var(result, &fact, result, rscale);
4357 * Compute the logarithm of num in a given base.
4359 * Note: this routine chooses dscale of the result.
4362 log_var(NumericVar *base, NumericVar *num, NumericVar *result)
4373 /* Set scale for ln() calculations --- compare numeric_ln() */
4375 /* Approx decimal digits before decimal point */
4376 dec_digits = (num->weight + 1) * DEC_DIGITS;
4379 rscale = NUMERIC_MIN_SIG_DIGITS - (int) log10(dec_digits - 1);
4380 else if (dec_digits < 1)
4381 rscale = NUMERIC_MIN_SIG_DIGITS - (int) log10(1 - dec_digits);
4383 rscale = NUMERIC_MIN_SIG_DIGITS;
4385 rscale = Max(rscale, base->dscale);
4386 rscale = Max(rscale, num->dscale);
4387 rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
4388 rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
4390 local_rscale = rscale + 8;
4392 /* Form natural logarithms */
4393 ln_var(base, &ln_base, local_rscale);
4394 ln_var(num, &ln_num, local_rscale);
4396 ln_base.dscale = rscale;
4397 ln_num.dscale = rscale;
4399 /* Select scale for division result */
4400 rscale = select_div_scale(&ln_num, &ln_base);
4402 div_var(&ln_num, &ln_base, result, rscale);
4412 * Raise base to the power of exp
4414 * Note: this routine chooses dscale of the result.
4417 power_var(NumericVar *base, NumericVar *exp, NumericVar *result)
4426 /* If exp can be represented as an integer, use power_var_int */
4427 if (exp->ndigits == 0 || exp->ndigits <= exp->weight + 1)
4429 /* exact integer, but does it fit in int? */
4433 /* must copy because numericvar_to_int8() scribbles on input */
4435 set_var_from_var(exp, &x);
4436 if (numericvar_to_int8(&x, &expval64))
4438 int expval = (int) expval64;
4440 /* Test for overflow by reverse-conversion. */
4441 if ((int64) expval == expval64)
4443 /* Okay, select rscale */
4444 rscale = NUMERIC_MIN_SIG_DIGITS;
4445 rscale = Max(rscale, base->dscale);
4446 rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
4447 rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
4449 power_var_int(base, expval, result, rscale);
4461 /* Set scale for ln() calculation --- need extra accuracy here */
4463 /* Approx decimal digits before decimal point */
4464 dec_digits = (base->weight + 1) * DEC_DIGITS;
4467 rscale = NUMERIC_MIN_SIG_DIGITS * 2 - (int) log10(dec_digits - 1);
4468 else if (dec_digits < 1)
4469 rscale = NUMERIC_MIN_SIG_DIGITS * 2 - (int) log10(1 - dec_digits);
4471 rscale = NUMERIC_MIN_SIG_DIGITS * 2;
4473 rscale = Max(rscale, base->dscale * 2);
4474 rscale = Max(rscale, exp->dscale * 2);
4475 rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE * 2);
4476 rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE * 2);
4478 local_rscale = rscale + 8;
4480 ln_var(base, &ln_base, local_rscale);
4482 mul_var(&ln_base, exp, &ln_num, local_rscale);
4484 /* Set scale for exp() -- compare numeric_exp() */
4486 /* convert input to float8, ignoring overflow */
4487 val = numericvar_to_double_no_overflow(&ln_num);
4490 * log10(result) = num * log10(e), so this is approximately the
4493 val *= 0.434294481903252;
4495 /* limit to something that won't cause integer overflow */
4496 val = Max(val, -NUMERIC_MAX_RESULT_SCALE);
4497 val = Min(val, NUMERIC_MAX_RESULT_SCALE);
4499 rscale = NUMERIC_MIN_SIG_DIGITS - (int) val;
4500 rscale = Max(rscale, base->dscale);
4501 rscale = Max(rscale, exp->dscale);
4502 rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
4503 rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
4505 exp_var(&ln_num, result, rscale);
4514 * Raise base to the power of exp, where exp is an integer.
4517 power_var_int(NumericVar *base, int exp, NumericVar *result, int rscale)
4520 NumericVar base_prod;
4523 /* Detect some special cases, particularly 0^0. */
4528 if (base->ndigits == 0)
4530 (errcode(ERRCODE_FLOATING_POINT_EXCEPTION),
4531 errmsg("zero raised to zero is undefined")));
4532 set_var_from_var(&const_one, result);
4533 result->dscale = rscale; /* no need to round */
4536 set_var_from_var(base, result);
4537 round_var(result, rscale);
4540 div_var(&const_one, base, result, rscale);
4543 mul_var(base, base, result, rscale);
4550 * The general case repeatedly multiplies base according to the bit
4551 * pattern of exp. We do the multiplications with some extra
4557 local_rscale = rscale + MUL_GUARD_DIGITS * 2;
4559 init_var(&base_prod);
4560 set_var_from_var(base, &base_prod);
4563 set_var_from_var(base, result);
4565 set_var_from_var(&const_one, result);
4567 while ((exp >>= 1) > 0)
4569 mul_var(&base_prod, &base_prod, &base_prod, local_rscale);
4571 mul_var(&base_prod, result, result, local_rscale);
4574 free_var(&base_prod);
4576 /* Compensate for input sign, and round to requested rscale */
4578 div_var(&const_one, result, result, rscale);
4580 round_var(result, rscale);
4584 /* ----------------------------------------------------------------------
4586 * Following are the lowest level functions that operate unsigned
4587 * on the variable level
4589 * ----------------------------------------------------------------------
4596 * Compare the absolute values of var1 and var2
4597 * Returns: -1 for ABS(var1) < ABS(var2)
4598 * 0 for ABS(var1) == ABS(var2)
4599 * 1 for ABS(var1) > ABS(var2)
4603 cmp_abs(NumericVar *var1, NumericVar *var2)
4605 NumericDigit *var1digits = var1->digits;
4606 NumericDigit *var2digits = var2->digits;
4609 int w1 = var1->weight;
4610 int w2 = var2->weight;
4612 /* Check any digits before the first common digit */
4614 while (w1 > w2 && i1 < var1->ndigits)
4616 if (var1digits[i1++] != 0)
4620 while (w2 > w1 && i2 < var2->ndigits)
4622 if (var2digits[i2++] != 0)
4627 /* At this point, either w1 == w2 or we've run out of digits */
4631 while (i1 < var1->ndigits && i2 < var2->ndigits)
4633 int stat = var1digits[i1++] - var2digits[i2++];
4645 * At this point, we've run out of digits on one side or the other; so
4646 * any remaining nonzero digits imply that side is larger
4648 while (i1 < var1->ndigits)
4650 if (var1digits[i1++] != 0)
4653 while (i2 < var2->ndigits)
4655 if (var2digits[i2++] != 0)
4666 * Add the absolute values of two variables into result.
4667 * result might point to one of the operands without danger.
4670 add_abs(NumericVar *var1, NumericVar *var2, NumericVar *result)
4672 NumericDigit *res_buf;
4673 NumericDigit *res_digits;
4685 /* copy these values into local vars for speed in inner loop */
4686 int var1ndigits = var1->ndigits;
4687 int var2ndigits = var2->ndigits;
4688 NumericDigit *var1digits = var1->digits;
4689 NumericDigit *var2digits = var2->digits;
4691 res_weight = Max(var1->weight, var2->weight) + 1;
4693 res_dscale = Max(var1->dscale, var2->dscale);
4695 /* Note: here we are figuring rscale in base-NBASE digits */
4696 rscale1 = var1->ndigits - var1->weight - 1;
4697 rscale2 = var2->ndigits - var2->weight - 1;
4698 res_rscale = Max(rscale1, rscale2);
4700 res_ndigits = res_rscale + res_weight + 1;
4701 if (res_ndigits <= 0)
4704 res_buf = digitbuf_alloc(res_ndigits + 1);
4705 res_buf[0] = 0; /* spare digit for later rounding */
4706 res_digits = res_buf + 1;
4708 i1 = res_rscale + var1->weight + 1;
4709 i2 = res_rscale + var2->weight + 1;
4710 for (i = res_ndigits - 1; i >= 0; i--)
4714 if (i1 >= 0 && i1 < var1ndigits)
4715 carry += var1digits[i1];
4716 if (i2 >= 0 && i2 < var2ndigits)
4717 carry += var2digits[i2];
4721 res_digits[i] = carry - NBASE;
4726 res_digits[i] = carry;
4731 Assert(carry == 0); /* else we failed to allow for carry out */
4733 digitbuf_free(result->buf);
4734 result->ndigits = res_ndigits;
4735 result->buf = res_buf;
4736 result->digits = res_digits;
4737 result->weight = res_weight;
4738 result->dscale = res_dscale;
4740 /* Remove leading/trailing zeroes */
4748 * Subtract the absolute value of var2 from the absolute value of var1
4749 * and store in result. result might point to one of the operands
4752 * ABS(var1) MUST BE GREATER OR EQUAL ABS(var2) !!!
4755 sub_abs(NumericVar *var1, NumericVar *var2, NumericVar *result)
4757 NumericDigit *res_buf;
4758 NumericDigit *res_digits;
4770 /* copy these values into local vars for speed in inner loop */
4771 int var1ndigits = var1->ndigits;
4772 int var2ndigits = var2->ndigits;
4773 NumericDigit *var1digits = var1->digits;
4774 NumericDigit *var2digits = var2->digits;
4776 res_weight = var1->weight;
4778 res_dscale = Max(var1->dscale, var2->dscale);
4780 /* Note: here we are figuring rscale in base-NBASE digits */
4781 rscale1 = var1->ndigits - var1->weight - 1;
4782 rscale2 = var2->ndigits - var2->weight - 1;
4783 res_rscale = Max(rscale1, rscale2);
4785 res_ndigits = res_rscale + res_weight + 1;
4786 if (res_ndigits <= 0)
4789 res_buf = digitbuf_alloc(res_ndigits + 1);
4790 res_buf[0] = 0; /* spare digit for later rounding */
4791 res_digits = res_buf + 1;
4793 i1 = res_rscale + var1->weight + 1;
4794 i2 = res_rscale + var2->weight + 1;
4795 for (i = res_ndigits - 1; i >= 0; i--)
4799 if (i1 >= 0 && i1 < var1ndigits)
4800 borrow += var1digits[i1];
4801 if (i2 >= 0 && i2 < var2ndigits)
4802 borrow -= var2digits[i2];
4806 res_digits[i] = borrow + NBASE;
4811 res_digits[i] = borrow;
4816 Assert(borrow == 0); /* else caller gave us var1 < var2 */
4818 digitbuf_free(result->buf);
4819 result->ndigits = res_ndigits;
4820 result->buf = res_buf;
4821 result->digits = res_digits;
4822 result->weight = res_weight;
4823 result->dscale = res_dscale;
4825 /* Remove leading/trailing zeroes */
4832 * Round the value of a variable to no more than rscale decimal digits
4833 * after the decimal point. NOTE: we allow rscale < 0 here, implying
4834 * rounding before the decimal point.
4837 round_var(NumericVar *var, int rscale)
4839 NumericDigit *digits = var->digits;
4844 var->dscale = rscale;
4846 /* decimal digits wanted */
4847 di = (var->weight + 1) * DEC_DIGITS + rscale;
4850 * If di = 0, the value loses all digits, but could round up to 1 if
4851 * its first extra digit is >= 5. If di < 0 the result must be 0.
4857 var->sign = NUMERIC_POS;
4861 /* NBASE digits wanted */
4862 ndigits = (di + DEC_DIGITS - 1) / DEC_DIGITS;
4864 /* 0, or number of decimal digits to keep in last NBASE digit */
4867 if (ndigits < var->ndigits ||
4868 (ndigits == var->ndigits && di > 0))
4870 var->ndigits = ndigits;
4873 /* di must be zero */
4874 carry = (digits[ndigits] >= HALF_NBASE) ? 1 : 0;
4877 carry = (digits[ndigits] >= HALF_NBASE) ? 1 : 0;
4880 /* Must round within last NBASE digit */
4885 pow10 = round_powers[di];
4886 #elif DEC_DIGITS == 2
4889 #error unsupported NBASE
4891 extra = digits[--ndigits] % pow10;
4892 digits[ndigits] -= extra;
4894 if (extra >= pow10 / 2)
4896 pow10 += digits[ndigits];
4902 digits[ndigits] = pow10;
4907 /* Propagate carry if needed */
4910 carry += digits[--ndigits];
4913 digits[ndigits] = carry - NBASE;
4918 digits[ndigits] = carry;
4925 Assert(ndigits == -1); /* better not have added > 1 digit */
4926 Assert(var->digits > var->buf);
4938 * Truncate the value of a variable at rscale decimal digits after the
4939 * decimal point. NOTE: we allow rscale < 0 here, implying
4940 * truncation before the decimal point.
4943 trunc_var(NumericVar *var, int rscale)
4948 var->dscale = rscale;
4950 /* decimal digits wanted */
4951 di = (var->weight + 1) * DEC_DIGITS + rscale;
4954 * If di <= 0, the value loses all digits.
4960 var->sign = NUMERIC_POS;
4964 /* NBASE digits wanted */
4965 ndigits = (di + DEC_DIGITS - 1) / DEC_DIGITS;
4967 if (ndigits <= var->ndigits)
4969 var->ndigits = ndigits;
4972 /* no within-digit stuff to worry about */
4974 /* 0, or number of decimal digits to keep in last NBASE digit */
4979 /* Must truncate within last NBASE digit */
4980 NumericDigit *digits = var->digits;
4985 pow10 = round_powers[di];
4986 #elif DEC_DIGITS == 2
4989 #error unsupported NBASE
4991 extra = digits[--ndigits] % pow10;
4992 digits[ndigits] -= extra;
5002 * Strip any leading and trailing zeroes from a numeric variable
5005 strip_var(NumericVar *var)
5007 NumericDigit *digits = var->digits;
5008 int ndigits = var->ndigits;
5010 /* Strip leading zeroes */
5011 while (ndigits > 0 && *digits == 0)
5018 /* Strip trailing zeroes */
5019 while (ndigits > 0 && digits[ndigits - 1] == 0)
5022 /* If it's zero, normalize the sign and weight */
5025 var->sign = NUMERIC_POS;
5029 var->digits = digits;
5030 var->ndigits = ndigits;