4 * An exact numeric data type for the Postgres database system
8 * $Header: /cvsroot/pgsql/src/backend/utils/adt/numeric.c,v 1.45 2001/10/13 23:32:33 tgl Exp $
19 #include <sys/types.h>
21 #include "utils/array.h"
22 #include "utils/builtins.h"
23 #include "utils/int8.h"
24 #include "utils/numeric.h"
27 * Uncomment the following to enable compilation of dump_numeric()
28 * and dump_var() and to get a dump of any result produced by make_result().
39 #define MIN(a,b) (((a)<(b)) ? (a) : (b))
42 #define MAX(a,b) (((a)>(b)) ? (a) : (b))
53 * Note: the first digit of a NumericVar's value is assumed to be multiplied
54 * by 10 ** weight. Another way to say it is that there are weight+1 digits
55 * before the decimal point. It is possible to have weight < 0.
57 * The value represented by a NumericVar is determined by the sign, weight,
58 * ndigits, and digits[] array. The rscale and dscale are carried along,
59 * but they are just auxiliary information until rounding is done before
60 * final storage or display. (Scales are the number of digits wanted
61 * *after* the decimal point. Scales are always >= 0.)
63 * buf points at the physical start of the palloc'd digit buffer for the
64 * NumericVar. digits points at the first digit in actual use (the one
65 * with the specified weight). We normally leave an unused byte or two
66 * (preset to zeroes) between buf and digits, so that there is room to store
67 * a carry out of the top digit without special pushups. We just need to
68 * decrement digits (and increment weight) to make room for the carry digit.
70 * If buf is NULL then the digit buffer isn't actually palloc'd and should
71 * not be freed --- see the constants below for an example.
73 * NB: All the variable-level functions are written in a style that makes it
74 * possible to give one and the same variable as argument and destination.
75 * This is feasible because the digit buffer is separate from the variable.
78 typedef unsigned char NumericDigit;
80 typedef struct NumericVar
82 int ndigits; /* number of digits in digits[] - can be
84 int weight; /* weight of first digit */
85 int rscale; /* result scale */
86 int dscale; /* display scale */
87 int sign; /* NUMERIC_POS, NUMERIC_NEG, or
89 NumericDigit *buf; /* start of palloc'd space for digits[] */
90 NumericDigit *digits; /* decimal digits */
98 static int global_rscale = NUMERIC_MIN_RESULT_SCALE;
101 * Some preinitialized variables we need often
104 static NumericDigit const_zero_data[1] = {0};
105 static NumericVar const_zero =
106 {0, 0, 0, 0, NUMERIC_POS, NULL, const_zero_data};
108 static NumericDigit const_one_data[1] = {1};
109 static NumericVar const_one =
110 {1, 0, 0, 0, NUMERIC_POS, NULL, const_one_data};
112 static NumericDigit const_two_data[1] = {2};
113 static NumericVar const_two =
114 {1, 0, 0, 0, NUMERIC_POS, NULL, const_two_data};
116 static NumericVar const_nan =
117 {0, 0, 0, 0, NUMERIC_NAN, NULL, NULL};
127 static void dump_numeric(char *str, Numeric num);
128 static void dump_var(char *str, NumericVar *var);
131 #define dump_numeric(s,n)
132 #define dump_var(s,v)
135 #define digitbuf_alloc(size) ((NumericDigit *) palloc(size))
136 #define digitbuf_free(buf) \
142 #define init_var(v) memset(v,0,sizeof(NumericVar))
143 static void alloc_var(NumericVar *var, int ndigits);
144 static void free_var(NumericVar *var);
145 static void zero_var(NumericVar *var);
147 static void set_var_from_str(char *str, NumericVar *dest);
148 static void set_var_from_num(Numeric value, NumericVar *dest);
149 static void set_var_from_var(NumericVar *value, NumericVar *dest);
150 static char *get_str_from_var(NumericVar *var, int dscale);
152 static Numeric make_result(NumericVar *var);
154 static void apply_typmod(NumericVar *var, int32 typmod);
156 static int cmp_numerics(Numeric num1, Numeric num2);
157 static int cmp_var(NumericVar *var1, NumericVar *var2);
158 static void add_var(NumericVar *var1, NumericVar *var2, NumericVar *result);
159 static void sub_var(NumericVar *var1, NumericVar *var2, NumericVar *result);
160 static void mul_var(NumericVar *var1, NumericVar *var2, NumericVar *result);
161 static void div_var(NumericVar *var1, NumericVar *var2, NumericVar *result);
162 static void mod_var(NumericVar *var1, NumericVar *var2, NumericVar *result);
163 static void ceil_var(NumericVar *var, NumericVar *result);
164 static void floor_var(NumericVar *var, NumericVar *result);
166 static void sqrt_var(NumericVar *arg, NumericVar *result);
167 static void exp_var(NumericVar *arg, NumericVar *result);
168 static void ln_var(NumericVar *arg, NumericVar *result);
169 static void log_var(NumericVar *base, NumericVar *num, NumericVar *result);
170 static void power_var(NumericVar *base, NumericVar *exp, NumericVar *result);
172 static int cmp_abs(NumericVar *var1, NumericVar *var2);
173 static void add_abs(NumericVar *var1, NumericVar *var2, NumericVar *result);
174 static void sub_abs(NumericVar *var1, NumericVar *var2, NumericVar *result);
178 /* ----------------------------------------------------------------------
180 * Input-, output- and rounding-functions
182 * ----------------------------------------------------------------------
189 * Input function for numeric data type
193 numeric_in(PG_FUNCTION_ARGS)
195 char *str = PG_GETARG_CSTRING(0);
197 Oid typelem = PG_GETARG_OID(1);
199 int32 typmod = PG_GETARG_INT32(2);
206 if (strcmp(str, "NaN") == 0)
207 PG_RETURN_NUMERIC(make_result(&const_nan));
210 * Use set_var_from_str() to parse the input string and return it in
211 * the packed DB storage format
214 set_var_from_str(str, &value);
216 apply_typmod(&value, typmod);
218 res = make_result(&value);
221 PG_RETURN_NUMERIC(res);
228 * Output function for numeric data type
232 numeric_out(PG_FUNCTION_ARGS)
234 Numeric num = PG_GETARG_NUMERIC(0);
241 if (NUMERIC_IS_NAN(num))
242 PG_RETURN_CSTRING(pstrdup("NaN"));
245 * Get the number in the variable format.
247 * Even if we didn't need to change format, we'd still need to copy the
248 * value to have a modifiable copy for rounding. set_var_from_num()
249 * also guarantees there is extra digit space in case we produce a
250 * carry out from rounding.
253 set_var_from_num(num, &x);
255 str = get_str_from_var(&x, x.dscale);
259 PG_RETURN_CSTRING(str);
266 * This is a special function called by the Postgres database system
267 * before a value is stored in a tuples attribute. The precision and
268 * scale of the attribute have to be applied on the value.
272 numeric(PG_FUNCTION_ARGS)
274 Numeric num = PG_GETARG_NUMERIC(0);
275 int32 typmod = PG_GETARG_INT32(1);
286 if (NUMERIC_IS_NAN(num))
287 PG_RETURN_NUMERIC(make_result(&const_nan));
290 * If the value isn't a valid type modifier, simply return a copy of
293 if (typmod < (int32) (VARHDRSZ))
295 new = (Numeric) palloc(num->varlen);
296 memcpy(new, num, num->varlen);
297 PG_RETURN_NUMERIC(new);
301 * Get the precision and scale out of the typmod value
303 tmp_typmod = typmod - VARHDRSZ;
304 precision = (tmp_typmod >> 16) & 0xffff;
305 scale = tmp_typmod & 0xffff;
306 maxweight = precision - scale;
309 * If the number is in bounds and due to the present result scale no
310 * rounding could be necessary, just make a copy of the input and
311 * modify its scale fields.
313 if (num->n_weight < maxweight && scale >= num->n_rscale)
315 new = (Numeric) palloc(num->varlen);
316 memcpy(new, num, num->varlen);
317 new->n_rscale = scale;
318 new->n_sign_dscale = NUMERIC_SIGN(new) |
319 ((uint16) scale & NUMERIC_DSCALE_MASK);
320 PG_RETURN_NUMERIC(new);
324 * We really need to fiddle with things - unpack the number into a
325 * variable and let apply_typmod() do it.
329 set_var_from_num(num, &var);
330 apply_typmod(&var, typmod);
331 new = make_result(&var);
335 PG_RETURN_NUMERIC(new);
339 /* ----------------------------------------------------------------------
341 * Sign manipulation, rounding and the like
343 * ----------------------------------------------------------------------
347 numeric_abs(PG_FUNCTION_ARGS)
349 Numeric num = PG_GETARG_NUMERIC(0);
355 if (NUMERIC_IS_NAN(num))
356 PG_RETURN_NUMERIC(make_result(&const_nan));
359 * Do it the easy way directly on the packed format
361 res = (Numeric) palloc(num->varlen);
362 memcpy(res, num, num->varlen);
364 res->n_sign_dscale = NUMERIC_POS | NUMERIC_DSCALE(num);
366 PG_RETURN_NUMERIC(res);
371 numeric_uminus(PG_FUNCTION_ARGS)
373 Numeric num = PG_GETARG_NUMERIC(0);
379 if (NUMERIC_IS_NAN(num))
380 PG_RETURN_NUMERIC(make_result(&const_nan));
383 * Do it the easy way directly on the packed format
385 res = (Numeric) palloc(num->varlen);
386 memcpy(res, num, num->varlen);
389 * The packed format is known to be totally zero digit trimmed always.
390 * So we can identify a ZERO by the fact that there are no digits at
391 * all. Do nothing to a zero.
393 if (num->varlen != NUMERIC_HDRSZ)
395 /* Else, flip the sign */
396 if (NUMERIC_SIGN(num) == NUMERIC_POS)
397 res->n_sign_dscale = NUMERIC_NEG | NUMERIC_DSCALE(num);
399 res->n_sign_dscale = NUMERIC_POS | NUMERIC_DSCALE(num);
402 PG_RETURN_NUMERIC(res);
407 numeric_uplus(PG_FUNCTION_ARGS)
409 Numeric num = PG_GETARG_NUMERIC(0);
412 res = (Numeric) palloc(num->varlen);
413 memcpy(res, num, num->varlen);
415 PG_RETURN_NUMERIC(res);
420 numeric_sign(PG_FUNCTION_ARGS)
422 Numeric num = PG_GETARG_NUMERIC(0);
429 if (NUMERIC_IS_NAN(num))
430 PG_RETURN_NUMERIC(make_result(&const_nan));
435 * The packed format is known to be totally zero digit trimmed always.
436 * So we can identify a ZERO by the fact that there are no digits at
439 if (num->varlen == NUMERIC_HDRSZ)
440 set_var_from_var(&const_zero, &result);
445 * And if there are some, we return a copy of ONE with the sign of
448 set_var_from_var(&const_one, &result);
449 result.sign = NUMERIC_SIGN(num);
452 res = make_result(&result);
455 PG_RETURN_NUMERIC(res);
462 * Round a value to have 'scale' digits after the decimal point.
463 * We allow negative 'scale', implying rounding before the decimal
464 * point --- Oracle interprets rounding that way.
468 numeric_round(PG_FUNCTION_ARGS)
470 Numeric num = PG_GETARG_NUMERIC(0);
471 int32 scale = PG_GETARG_INT32(1);
479 if (NUMERIC_IS_NAN(num))
480 PG_RETURN_NUMERIC(make_result(&const_nan));
483 * Limit the scale value to avoid possible overflow in calculations
486 scale = MIN(NUMERIC_MAX_RESULT_SCALE,
487 MAX(-NUMERIC_MAX_RESULT_SCALE, scale));
490 * Unpack the argument and round it at the proper digit position
493 set_var_from_num(num, &arg);
495 i = arg.weight + scale + 1;
501 * If i = 0, the value loses all digits, but could round up if its
502 * first digit is more than 4. If i < 0 the result must be 0.
508 int carry = (arg.digits[i] > 4) ? 1 : 0;
514 carry += arg.digits[--i];
515 arg.digits[i] = carry % 10;
521 Assert(i == -1);/* better not have added more than 1 digit */
522 Assert(arg.digits > arg.buf);
531 * Set result's scale to something reasonable.
533 scale = MIN(NUMERIC_MAX_DISPLAY_SCALE, MAX(0, scale));
538 * Return the rounded result
540 res = make_result(&arg);
543 PG_RETURN_NUMERIC(res);
550 * Truncate a value to have 'scale' digits after the decimal point.
551 * We allow negative 'scale', implying a truncation before the decimal
552 * point --- Oracle interprets truncation that way.
556 numeric_trunc(PG_FUNCTION_ARGS)
558 Numeric num = PG_GETARG_NUMERIC(0);
559 int32 scale = PG_GETARG_INT32(1);
566 if (NUMERIC_IS_NAN(num))
567 PG_RETURN_NUMERIC(make_result(&const_nan));
570 * Limit the scale value to avoid possible overflow in calculations
573 scale = MIN(NUMERIC_MAX_RESULT_SCALE,
574 MAX(-NUMERIC_MAX_RESULT_SCALE, scale));
577 * Unpack the argument and truncate it at the proper digit position
580 set_var_from_num(num, &arg);
582 arg.ndigits = MIN(arg.ndigits, MAX(0, arg.weight + scale + 1));
585 * Set result's scale to something reasonable.
587 scale = MIN(NUMERIC_MAX_DISPLAY_SCALE, MAX(0, scale));
592 * Return the truncated result
594 res = make_result(&arg);
597 PG_RETURN_NUMERIC(res);
604 * Return the smallest integer greater than or equal to the argument
608 numeric_ceil(PG_FUNCTION_ARGS)
610 Numeric num = PG_GETARG_NUMERIC(0);
614 if (NUMERIC_IS_NAN(num))
615 PG_RETURN_NUMERIC(make_result(&const_nan));
619 set_var_from_num(num, &result);
620 ceil_var(&result, &result);
624 res = make_result(&result);
627 PG_RETURN_NUMERIC(res);
634 * Return the largest integer equal to or less than the argument
638 numeric_floor(PG_FUNCTION_ARGS)
640 Numeric num = PG_GETARG_NUMERIC(0);
644 if (NUMERIC_IS_NAN(num))
645 PG_RETURN_NUMERIC(make_result(&const_nan));
649 set_var_from_num(num, &result);
650 floor_var(&result, &result);
654 res = make_result(&result);
657 PG_RETURN_NUMERIC(res);
661 /* ----------------------------------------------------------------------
663 * Comparison functions
665 * Note: btree indexes need these routines not to leak memory; therefore,
666 * be careful to free working copies of toasted datums. Most places don't
667 * need to be so careful.
668 * ----------------------------------------------------------------------
673 numeric_cmp(PG_FUNCTION_ARGS)
675 Numeric num1 = PG_GETARG_NUMERIC(0);
676 Numeric num2 = PG_GETARG_NUMERIC(1);
679 result = cmp_numerics(num1, num2);
681 PG_FREE_IF_COPY(num1, 0);
682 PG_FREE_IF_COPY(num2, 1);
684 PG_RETURN_INT32(result);
689 numeric_eq(PG_FUNCTION_ARGS)
691 Numeric num1 = PG_GETARG_NUMERIC(0);
692 Numeric num2 = PG_GETARG_NUMERIC(1);
695 result = cmp_numerics(num1, num2) == 0;
697 PG_FREE_IF_COPY(num1, 0);
698 PG_FREE_IF_COPY(num2, 1);
700 PG_RETURN_BOOL(result);
704 numeric_ne(PG_FUNCTION_ARGS)
706 Numeric num1 = PG_GETARG_NUMERIC(0);
707 Numeric num2 = PG_GETARG_NUMERIC(1);
710 result = cmp_numerics(num1, num2) != 0;
712 PG_FREE_IF_COPY(num1, 0);
713 PG_FREE_IF_COPY(num2, 1);
715 PG_RETURN_BOOL(result);
719 numeric_gt(PG_FUNCTION_ARGS)
721 Numeric num1 = PG_GETARG_NUMERIC(0);
722 Numeric num2 = PG_GETARG_NUMERIC(1);
725 result = cmp_numerics(num1, num2) > 0;
727 PG_FREE_IF_COPY(num1, 0);
728 PG_FREE_IF_COPY(num2, 1);
730 PG_RETURN_BOOL(result);
734 numeric_ge(PG_FUNCTION_ARGS)
736 Numeric num1 = PG_GETARG_NUMERIC(0);
737 Numeric num2 = PG_GETARG_NUMERIC(1);
740 result = cmp_numerics(num1, num2) >= 0;
742 PG_FREE_IF_COPY(num1, 0);
743 PG_FREE_IF_COPY(num2, 1);
745 PG_RETURN_BOOL(result);
749 numeric_lt(PG_FUNCTION_ARGS)
751 Numeric num1 = PG_GETARG_NUMERIC(0);
752 Numeric num2 = PG_GETARG_NUMERIC(1);
755 result = cmp_numerics(num1, num2) < 0;
757 PG_FREE_IF_COPY(num1, 0);
758 PG_FREE_IF_COPY(num2, 1);
760 PG_RETURN_BOOL(result);
764 numeric_le(PG_FUNCTION_ARGS)
766 Numeric num1 = PG_GETARG_NUMERIC(0);
767 Numeric num2 = PG_GETARG_NUMERIC(1);
770 result = cmp_numerics(num1, num2) <= 0;
772 PG_FREE_IF_COPY(num1, 0);
773 PG_FREE_IF_COPY(num2, 1);
775 PG_RETURN_BOOL(result);
779 cmp_numerics(Numeric num1, Numeric num2)
784 * We consider all NANs to be equal and larger than any non-NAN.
785 * This is somewhat arbitrary; the important thing is to have a
786 * consistent sort order.
788 if (NUMERIC_IS_NAN(num1))
790 if (NUMERIC_IS_NAN(num2))
791 result = 0; /* NAN = NAN */
793 result = 1; /* NAN > non-NAN */
795 else if (NUMERIC_IS_NAN(num2))
797 result = -1; /* non-NAN < NAN */
807 set_var_from_num(num1, &arg1);
808 set_var_from_num(num2, &arg2);
810 result = cmp_var(&arg1, &arg2);
820 /* ----------------------------------------------------------------------
822 * Arithmetic base functions
824 * ----------------------------------------------------------------------
835 numeric_add(PG_FUNCTION_ARGS)
837 Numeric num1 = PG_GETARG_NUMERIC(0);
838 Numeric num2 = PG_GETARG_NUMERIC(1);
847 if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
848 PG_RETURN_NUMERIC(make_result(&const_nan));
851 * Unpack the values, let add_var() compute the result and return it.
852 * The internals of add_var() will automatically set the correct
853 * result and display scales in the result.
859 set_var_from_num(num1, &arg1);
860 set_var_from_num(num2, &arg2);
862 add_var(&arg1, &arg2, &result);
863 res = make_result(&result);
869 PG_RETURN_NUMERIC(res);
876 * Subtract one numeric from another
880 numeric_sub(PG_FUNCTION_ARGS)
882 Numeric num1 = PG_GETARG_NUMERIC(0);
883 Numeric num2 = PG_GETARG_NUMERIC(1);
892 if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
893 PG_RETURN_NUMERIC(make_result(&const_nan));
896 * Unpack the two arguments, let sub_var() compute the result and
903 set_var_from_num(num1, &arg1);
904 set_var_from_num(num2, &arg2);
906 sub_var(&arg1, &arg2, &result);
907 res = make_result(&result);
913 PG_RETURN_NUMERIC(res);
920 * Calculate the product of two numerics
924 numeric_mul(PG_FUNCTION_ARGS)
926 Numeric num1 = PG_GETARG_NUMERIC(0);
927 Numeric num2 = PG_GETARG_NUMERIC(1);
936 if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
937 PG_RETURN_NUMERIC(make_result(&const_nan));
940 * Unpack the arguments, let mul_var() compute the result and return
941 * it. Unlike add_var() and sub_var(), mul_var() will round the result
942 * to the scale stored in global_rscale. In the case of numeric_mul(),
943 * which is invoked for the * operator on numerics, we set it to the
944 * exact representation for the product (rscale = sum(rscale of arg1,
945 * rscale of arg2) and the same for the dscale).
951 set_var_from_num(num1, &arg1);
952 set_var_from_num(num2, &arg2);
954 global_rscale = arg1.rscale + arg2.rscale;
956 mul_var(&arg1, &arg2, &result);
958 result.dscale = arg1.dscale + arg2.dscale;
960 res = make_result(&result);
966 PG_RETURN_NUMERIC(res);
973 * Divide one numeric into another
977 numeric_div(PG_FUNCTION_ARGS)
979 Numeric num1 = PG_GETARG_NUMERIC(0);
980 Numeric num2 = PG_GETARG_NUMERIC(1);
990 if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
991 PG_RETURN_NUMERIC(make_result(&const_nan));
994 * Unpack the arguments
1000 set_var_from_num(num1, &arg1);
1001 set_var_from_num(num2, &arg2);
1004 * The result scale of a division isn't specified in any
1005 * SQL standard. For Postgres it is the following (where
1006 * SR, DR are the result- and display-scales of the returned
1007 * value, S1, D1, S2 and D2 are the scales of the two arguments,
1008 * The minimum and maximum scales are compile time options from
1011 * DR = MIN(MAX(D1 + D2, MIN_DISPLAY_SCALE), MAX_DISPLAY_SCALE)
1012 * SR = MIN(MAX(MAX(S1 + S2, MIN_RESULT_SCALE), DR + 4), MAX_RESULT_SCALE)
1014 * By default, any result is computed with a minimum of 34 digits
1015 * after the decimal point or at least with 4 digits more than
1019 res_dscale = MAX(arg1.dscale + arg2.dscale, NUMERIC_MIN_DISPLAY_SCALE);
1020 res_dscale = MIN(res_dscale, NUMERIC_MAX_DISPLAY_SCALE);
1021 global_rscale = MAX(arg1.rscale + arg2.rscale,
1022 NUMERIC_MIN_RESULT_SCALE);
1023 global_rscale = MAX(global_rscale, res_dscale + 4);
1024 global_rscale = MIN(global_rscale, NUMERIC_MAX_RESULT_SCALE);
1027 * Do the divide, set the display scale and return the result
1029 div_var(&arg1, &arg2, &result);
1031 result.dscale = res_dscale;
1033 res = make_result(&result);
1039 PG_RETURN_NUMERIC(res);
1046 * Calculate the modulo of two numerics
1050 numeric_mod(PG_FUNCTION_ARGS)
1052 Numeric num1 = PG_GETARG_NUMERIC(0);
1053 Numeric num2 = PG_GETARG_NUMERIC(1);
1059 if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
1060 PG_RETURN_NUMERIC(make_result(&const_nan));
1066 set_var_from_num(num1, &arg1);
1067 set_var_from_num(num2, &arg2);
1069 mod_var(&arg1, &arg2, &result);
1071 res = make_result(&result);
1077 PG_RETURN_NUMERIC(res);
1084 * Increment a number by one
1088 numeric_inc(PG_FUNCTION_ARGS)
1090 Numeric num = PG_GETARG_NUMERIC(0);
1097 if (NUMERIC_IS_NAN(num))
1098 PG_RETURN_NUMERIC(make_result(&const_nan));
1101 * Compute the result and return it
1105 set_var_from_num(num, &arg);
1107 add_var(&arg, &const_one, &arg);
1108 res = make_result(&arg);
1112 PG_RETURN_NUMERIC(res);
1117 * numeric_smaller() -
1119 * Return the smaller of two numbers
1123 numeric_smaller(PG_FUNCTION_ARGS)
1125 Numeric num1 = PG_GETARG_NUMERIC(0);
1126 Numeric num2 = PG_GETARG_NUMERIC(1);
1134 if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
1135 PG_RETURN_NUMERIC(make_result(&const_nan));
1138 * Unpack the values, and decide which is the smaller one
1143 set_var_from_num(num1, &arg1);
1144 set_var_from_num(num2, &arg2);
1146 if (cmp_var(&arg1, &arg2) <= 0)
1147 res = make_result(&arg1);
1149 res = make_result(&arg2);
1154 PG_RETURN_NUMERIC(res);
1159 * numeric_larger() -
1161 * Return the larger of two numbers
1165 numeric_larger(PG_FUNCTION_ARGS)
1167 Numeric num1 = PG_GETARG_NUMERIC(0);
1168 Numeric num2 = PG_GETARG_NUMERIC(1);
1176 if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
1177 PG_RETURN_NUMERIC(make_result(&const_nan));
1180 * Unpack the values, and decide which is the larger one
1185 set_var_from_num(num1, &arg1);
1186 set_var_from_num(num2, &arg2);
1188 if (cmp_var(&arg1, &arg2) >= 0)
1189 res = make_result(&arg1);
1191 res = make_result(&arg2);
1196 PG_RETURN_NUMERIC(res);
1200 /* ----------------------------------------------------------------------
1202 * Complex math functions
1204 * ----------------------------------------------------------------------
1211 * Compute the square root of a numeric.
1215 numeric_sqrt(PG_FUNCTION_ARGS)
1217 Numeric num = PG_GETARG_NUMERIC(0);
1226 if (NUMERIC_IS_NAN(num))
1227 PG_RETURN_NUMERIC(make_result(&const_nan));
1230 * Unpack the argument, determine the scales like for divide, let
1231 * sqrt_var() do the calculation and return the result.
1236 set_var_from_num(num, &arg);
1238 res_dscale = MAX(arg.dscale, NUMERIC_MIN_DISPLAY_SCALE);
1239 res_dscale = MIN(res_dscale, NUMERIC_MAX_DISPLAY_SCALE);
1240 global_rscale = MAX(arg.rscale, NUMERIC_MIN_RESULT_SCALE);
1241 global_rscale = MAX(global_rscale, res_dscale + 4);
1242 global_rscale = MIN(global_rscale, NUMERIC_MAX_RESULT_SCALE);
1244 sqrt_var(&arg, &result);
1246 result.dscale = res_dscale;
1248 res = make_result(&result);
1253 PG_RETURN_NUMERIC(res);
1260 * Raise e to the power of x
1264 numeric_exp(PG_FUNCTION_ARGS)
1266 Numeric num = PG_GETARG_NUMERIC(0);
1275 if (NUMERIC_IS_NAN(num))
1276 PG_RETURN_NUMERIC(make_result(&const_nan));
1279 * Same procedure like for sqrt().
1283 set_var_from_num(num, &arg);
1285 res_dscale = MAX(arg.dscale, NUMERIC_MIN_DISPLAY_SCALE);
1286 res_dscale = MIN(res_dscale, NUMERIC_MAX_DISPLAY_SCALE);
1287 global_rscale = MAX(arg.rscale, NUMERIC_MIN_RESULT_SCALE);
1288 global_rscale = MAX(global_rscale, res_dscale + 4);
1289 global_rscale = MIN(global_rscale, NUMERIC_MAX_RESULT_SCALE);
1291 exp_var(&arg, &result);
1293 result.dscale = res_dscale;
1295 res = make_result(&result);
1300 PG_RETURN_NUMERIC(res);
1307 * Compute the natural logarithm of x
1311 numeric_ln(PG_FUNCTION_ARGS)
1313 Numeric num = PG_GETARG_NUMERIC(0);
1322 if (NUMERIC_IS_NAN(num))
1323 PG_RETURN_NUMERIC(make_result(&const_nan));
1326 * Same procedure like for sqrt()
1330 set_var_from_num(num, &arg);
1332 res_dscale = MAX(arg.dscale, NUMERIC_MIN_DISPLAY_SCALE);
1333 res_dscale = MIN(res_dscale, NUMERIC_MAX_DISPLAY_SCALE);
1334 global_rscale = MAX(arg.rscale, NUMERIC_MIN_RESULT_SCALE);
1335 global_rscale = MAX(global_rscale, res_dscale + 4);
1336 global_rscale = MIN(global_rscale, NUMERIC_MAX_RESULT_SCALE);
1338 ln_var(&arg, &result);
1340 result.dscale = res_dscale;
1342 res = make_result(&result);
1347 PG_RETURN_NUMERIC(res);
1354 * Compute the logarithm of x in a given base
1358 numeric_log(PG_FUNCTION_ARGS)
1360 Numeric num1 = PG_GETARG_NUMERIC(0);
1361 Numeric num2 = PG_GETARG_NUMERIC(1);
1371 if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
1372 PG_RETURN_NUMERIC(make_result(&const_nan));
1375 * Initialize things and calculate scales
1380 set_var_from_num(num1, &arg1);
1381 set_var_from_num(num2, &arg2);
1383 res_dscale = MAX(arg1.dscale + arg2.dscale, NUMERIC_MIN_DISPLAY_SCALE);
1384 res_dscale = MIN(res_dscale, NUMERIC_MAX_DISPLAY_SCALE);
1385 global_rscale = MAX(arg1.rscale + arg2.rscale, NUMERIC_MIN_RESULT_SCALE);
1386 global_rscale = MAX(global_rscale, res_dscale + 4);
1387 global_rscale = MIN(global_rscale, NUMERIC_MAX_RESULT_SCALE);
1390 * Call log_var() to compute and return the result
1392 log_var(&arg1, &arg2, &result);
1394 result.dscale = res_dscale;
1396 res = make_result(&result);
1402 PG_RETURN_NUMERIC(res);
1409 * Raise m to the power of x
1413 numeric_power(PG_FUNCTION_ARGS)
1415 Numeric num1 = PG_GETARG_NUMERIC(0);
1416 Numeric num2 = PG_GETARG_NUMERIC(1);
1426 if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
1427 PG_RETURN_NUMERIC(make_result(&const_nan));
1430 * Initialize things and calculate scales
1435 set_var_from_num(num1, &arg1);
1436 set_var_from_num(num2, &arg2);
1438 res_dscale = MAX(arg1.dscale + arg2.dscale, NUMERIC_MIN_DISPLAY_SCALE);
1439 res_dscale = MIN(res_dscale, NUMERIC_MAX_DISPLAY_SCALE);
1440 global_rscale = MAX(arg1.rscale + arg2.rscale, NUMERIC_MIN_RESULT_SCALE);
1441 global_rscale = MAX(global_rscale, res_dscale + 4);
1442 global_rscale = MIN(global_rscale, NUMERIC_MAX_RESULT_SCALE);
1445 * Call log_var() to compute and return the result
1447 power_var(&arg1, &arg2, &result);
1449 result.dscale = res_dscale;
1451 res = make_result(&result);
1457 PG_RETURN_NUMERIC(res);
1461 /* ----------------------------------------------------------------------
1463 * Type conversion functions
1465 * ----------------------------------------------------------------------
1470 int4_numeric(PG_FUNCTION_ARGS)
1472 int32 val = PG_GETARG_INT32(0);
1479 tmp = DatumGetCString(DirectFunctionCall1(int4out,
1480 Int32GetDatum(val)));
1481 set_var_from_str(tmp, &result);
1482 res = make_result(&result);
1487 PG_RETURN_NUMERIC(res);
1492 numeric_int4(PG_FUNCTION_ARGS)
1494 Numeric num = PG_GETARG_NUMERIC(0);
1499 /* XXX would it be better to return NULL? */
1500 if (NUMERIC_IS_NAN(num))
1501 elog(ERROR, "Cannot convert NaN to int4");
1504 * Get the number in the variable format so we can round to integer.
1507 set_var_from_num(num, &x);
1509 str = get_str_from_var(&x, 0); /* dscale = 0 produces rounding */
1513 result = DirectFunctionCall1(int4in, CStringGetDatum(str));
1516 PG_RETURN_DATUM(result);
1521 int8_numeric(PG_FUNCTION_ARGS)
1523 Datum val = PG_GETARG_DATUM(0);
1530 tmp = DatumGetCString(DirectFunctionCall1(int8out, val));
1531 set_var_from_str(tmp, &result);
1532 res = make_result(&result);
1537 PG_RETURN_NUMERIC(res);
1542 numeric_int8(PG_FUNCTION_ARGS)
1544 Numeric num = PG_GETARG_NUMERIC(0);
1549 /* XXX would it be better to return NULL? */
1550 if (NUMERIC_IS_NAN(num))
1551 elog(ERROR, "Cannot convert NaN to int8");
1554 * Get the number in the variable format so we can round to integer.
1557 set_var_from_num(num, &x);
1559 str = get_str_from_var(&x, 0); /* dscale = 0 produces rounding */
1563 result = DirectFunctionCall1(int8in, CStringGetDatum(str));
1566 PG_RETURN_DATUM(result);
1571 int2_numeric(PG_FUNCTION_ARGS)
1573 int16 val = PG_GETARG_INT16(0);
1580 tmp = DatumGetCString(DirectFunctionCall1(int2out,
1581 Int16GetDatum(val)));
1582 set_var_from_str(tmp, &result);
1583 res = make_result(&result);
1588 PG_RETURN_NUMERIC(res);
1593 numeric_int2(PG_FUNCTION_ARGS)
1595 Numeric num = PG_GETARG_NUMERIC(0);
1600 /* XXX would it be better to return NULL? */
1601 if (NUMERIC_IS_NAN(num))
1602 elog(ERROR, "Cannot convert NaN to int2");
1605 * Get the number in the variable format so we can round to integer.
1608 set_var_from_num(num, &x);
1610 str = get_str_from_var(&x, 0); /* dscale = 0 produces rounding */
1614 result = DirectFunctionCall1(int2in, CStringGetDatum(str));
1622 float8_numeric(PG_FUNCTION_ARGS)
1624 float8 val = PG_GETARG_FLOAT8(0);
1627 char buf[DBL_DIG + 100];
1630 PG_RETURN_NUMERIC(make_result(&const_nan));
1632 sprintf(buf, "%.*g", DBL_DIG, val);
1636 set_var_from_str(buf, &result);
1637 res = make_result(&result);
1641 PG_RETURN_NUMERIC(res);
1646 numeric_float8(PG_FUNCTION_ARGS)
1648 Numeric num = PG_GETARG_NUMERIC(0);
1652 if (NUMERIC_IS_NAN(num))
1653 PG_RETURN_FLOAT8(NAN);
1655 tmp = DatumGetCString(DirectFunctionCall1(numeric_out,
1656 NumericGetDatum(num)));
1658 result = DirectFunctionCall1(float8in, CStringGetDatum(tmp));
1662 PG_RETURN_DATUM(result);
1666 /* Convert numeric to float8; if out of range, return +/- HUGE_VAL */
1668 numeric_float8_no_overflow(PG_FUNCTION_ARGS)
1670 Numeric num = PG_GETARG_NUMERIC(0);
1675 if (NUMERIC_IS_NAN(num))
1676 PG_RETURN_FLOAT8(NAN);
1678 tmp = DatumGetCString(DirectFunctionCall1(numeric_out,
1679 NumericGetDatum(num)));
1681 /* unlike float8in, we ignore ERANGE from strtod */
1682 val = strtod(tmp, &endptr);
1683 if (*endptr != '\0')
1685 /* shouldn't happen ... */
1686 elog(ERROR, "Bad float8 input format '%s'", tmp);
1691 PG_RETURN_FLOAT8(val);
1696 float4_numeric(PG_FUNCTION_ARGS)
1698 float4 val = PG_GETARG_FLOAT4(0);
1701 char buf[FLT_DIG + 100];
1704 PG_RETURN_NUMERIC(make_result(&const_nan));
1706 sprintf(buf, "%.*g", FLT_DIG, val);
1710 set_var_from_str(buf, &result);
1711 res = make_result(&result);
1715 PG_RETURN_NUMERIC(res);
1720 numeric_float4(PG_FUNCTION_ARGS)
1722 Numeric num = PG_GETARG_NUMERIC(0);
1726 if (NUMERIC_IS_NAN(num))
1727 PG_RETURN_FLOAT4((float4) NAN);
1729 tmp = DatumGetCString(DirectFunctionCall1(numeric_out,
1730 NumericGetDatum(num)));
1732 result = DirectFunctionCall1(float4in, CStringGetDatum(tmp));
1736 PG_RETURN_DATUM(result);
1740 /* ----------------------------------------------------------------------
1742 * Aggregate functions
1744 * The transition datatype for all these aggregates is a 3-element array
1745 * of Numeric, holding the values N, sum(X), sum(X*X) in that order.
1747 * We represent N as a numeric mainly to avoid having to build a special
1748 * datatype; it's unlikely it'd overflow an int4, but ...
1750 * ----------------------------------------------------------------------
1754 do_numeric_accum(ArrayType *transarray, Numeric newval)
1763 /* We assume the input is array of numeric */
1764 deconstruct_array(transarray,
1766 &transdatums, &ndatums);
1768 elog(ERROR, "do_numeric_accum: expected 3-element numeric array");
1770 sumX = transdatums[1];
1771 sumX2 = transdatums[2];
1773 N = DirectFunctionCall1(numeric_inc, N);
1774 sumX = DirectFunctionCall2(numeric_add, sumX,
1775 NumericGetDatum(newval));
1776 sumX2 = DirectFunctionCall2(numeric_add, sumX2,
1777 DirectFunctionCall2(numeric_mul,
1778 NumericGetDatum(newval),
1779 NumericGetDatum(newval)));
1782 transdatums[1] = sumX;
1783 transdatums[2] = sumX2;
1785 result = construct_array(transdatums, 3,
1792 numeric_accum(PG_FUNCTION_ARGS)
1794 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
1795 Numeric newval = PG_GETARG_NUMERIC(1);
1797 PG_RETURN_ARRAYTYPE_P(do_numeric_accum(transarray, newval));
1801 * Integer data types all use Numeric accumulators to share code and
1802 * avoid risk of overflow. For int2 and int4 inputs, Numeric accumulation
1803 * is overkill for the N and sum(X) values, but definitely not overkill
1804 * for the sum(X*X) value. Hence, we use int2_accum and int4_accum only
1805 * for stddev/variance --- there are faster special-purpose accumulator
1806 * routines for SUM and AVG of these datatypes.
1810 int2_accum(PG_FUNCTION_ARGS)
1812 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
1813 Datum newval2 = PG_GETARG_DATUM(1);
1816 newval = DatumGetNumeric(DirectFunctionCall1(int2_numeric, newval2));
1818 PG_RETURN_ARRAYTYPE_P(do_numeric_accum(transarray, newval));
1822 int4_accum(PG_FUNCTION_ARGS)
1824 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
1825 Datum newval4 = PG_GETARG_DATUM(1);
1828 newval = DatumGetNumeric(DirectFunctionCall1(int4_numeric, newval4));
1830 PG_RETURN_ARRAYTYPE_P(do_numeric_accum(transarray, newval));
1834 int8_accum(PG_FUNCTION_ARGS)
1836 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
1837 Datum newval8 = PG_GETARG_DATUM(1);
1840 newval = DatumGetNumeric(DirectFunctionCall1(int8_numeric, newval8));
1842 PG_RETURN_ARRAYTYPE_P(do_numeric_accum(transarray, newval));
1846 numeric_avg(PG_FUNCTION_ARGS)
1848 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
1854 /* We assume the input is array of numeric */
1855 deconstruct_array(transarray,
1857 &transdatums, &ndatums);
1859 elog(ERROR, "numeric_avg: expected 3-element numeric array");
1860 N = DatumGetNumeric(transdatums[0]);
1861 sumX = DatumGetNumeric(transdatums[1]);
1864 /* SQL92 defines AVG of no values to be NULL */
1865 /* N is zero iff no digits (cf. numeric_uminus) */
1866 if (N->varlen == NUMERIC_HDRSZ)
1869 PG_RETURN_DATUM(DirectFunctionCall2(numeric_div,
1870 NumericGetDatum(sumX),
1871 NumericGetDatum(N)));
1875 numeric_variance(PG_FUNCTION_ARGS)
1877 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
1889 /* We assume the input is array of numeric */
1890 deconstruct_array(transarray,
1892 &transdatums, &ndatums);
1894 elog(ERROR, "numeric_variance: expected 3-element numeric array");
1895 N = DatumGetNumeric(transdatums[0]);
1896 sumX = DatumGetNumeric(transdatums[1]);
1897 sumX2 = DatumGetNumeric(transdatums[2]);
1899 if (NUMERIC_IS_NAN(N) || NUMERIC_IS_NAN(sumX) || NUMERIC_IS_NAN(sumX2))
1900 PG_RETURN_NUMERIC(make_result(&const_nan));
1902 /* We define VARIANCE of no values to be NULL, of 1 value to be 0 */
1903 /* N is zero iff no digits (cf. numeric_uminus) */
1904 if (N->varlen == NUMERIC_HDRSZ)
1908 set_var_from_num(N, &vN);
1910 init_var(&vNminus1);
1911 sub_var(&vN, &const_one, &vNminus1);
1913 if (cmp_var(&vNminus1, &const_zero) <= 0)
1916 free_var(&vNminus1);
1917 PG_RETURN_NUMERIC(make_result(&const_zero));
1921 set_var_from_num(sumX, &vsumX);
1923 set_var_from_num(sumX2, &vsumX2);
1925 mul_var(&vsumX, &vsumX, &vsumX); /* now vsumX contains sumX * sumX */
1926 mul_var(&vN, &vsumX2, &vsumX2); /* now vsumX2 contains N * sumX2 */
1927 sub_var(&vsumX2, &vsumX, &vsumX2); /* N * sumX2 - sumX * sumX */
1928 mul_var(&vN, &vNminus1, &vNminus1); /* N * (N - 1) */
1929 div_var(&vsumX2, &vNminus1, &vsumX); /* variance */
1931 res = make_result(&vsumX);
1934 free_var(&vNminus1);
1938 PG_RETURN_NUMERIC(res);
1942 numeric_stddev(PG_FUNCTION_ARGS)
1944 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
1956 /* We assume the input is array of numeric */
1957 deconstruct_array(transarray,
1959 &transdatums, &ndatums);
1961 elog(ERROR, "numeric_stddev: expected 3-element numeric array");
1962 N = DatumGetNumeric(transdatums[0]);
1963 sumX = DatumGetNumeric(transdatums[1]);
1964 sumX2 = DatumGetNumeric(transdatums[2]);
1966 if (NUMERIC_IS_NAN(N) || NUMERIC_IS_NAN(sumX) || NUMERIC_IS_NAN(sumX2))
1967 PG_RETURN_NUMERIC(make_result(&const_nan));
1969 /* We define STDDEV of no values to be NULL, of 1 value to be 0 */
1970 /* N is zero iff no digits (cf. numeric_uminus) */
1971 if (N->varlen == NUMERIC_HDRSZ)
1975 set_var_from_num(N, &vN);
1977 init_var(&vNminus1);
1978 sub_var(&vN, &const_one, &vNminus1);
1980 if (cmp_var(&vNminus1, &const_zero) <= 0)
1983 free_var(&vNminus1);
1984 PG_RETURN_NUMERIC(make_result(&const_zero));
1988 set_var_from_num(sumX, &vsumX);
1990 set_var_from_num(sumX2, &vsumX2);
1992 mul_var(&vsumX, &vsumX, &vsumX); /* now vsumX contains sumX * sumX */
1993 mul_var(&vN, &vsumX2, &vsumX2); /* now vsumX2 contains N * sumX2 */
1994 sub_var(&vsumX2, &vsumX, &vsumX2); /* N * sumX2 - sumX * sumX */
1995 mul_var(&vN, &vNminus1, &vNminus1); /* N * (N - 1) */
1996 div_var(&vsumX2, &vNminus1, &vsumX); /* variance */
1997 sqrt_var(&vsumX, &vsumX); /* stddev */
1999 res = make_result(&vsumX);
2002 free_var(&vNminus1);
2006 PG_RETURN_NUMERIC(res);
2011 * SUM transition functions for integer datatypes.
2013 * To avoid overflow, we use accumulators wider than the input datatype.
2014 * A Numeric accumulator is needed for int8 input; for int4 and int2
2015 * inputs, we use int8 accumulators which should be sufficient for practical
2016 * purposes. (The latter two therefore don't really belong in this file,
2017 * but we keep them here anyway.)
2019 * Because SQL92 defines the SUM() of no values to be NULL, not zero,
2020 * the initial condition of the transition data value needs to be NULL. This
2021 * means we can't rely on ExecAgg to automatically insert the first non-null
2022 * data value into the transition data: it doesn't know how to do the type
2023 * conversion. The upshot is that these routines have to be marked non-strict
2024 * and handle substitution of the first non-null input themselves.
2028 int2_sum(PG_FUNCTION_ARGS)
2033 if (PG_ARGISNULL(0))
2035 /* No non-null input seen so far... */
2036 if (PG_ARGISNULL(1))
2037 PG_RETURN_NULL(); /* still no non-null */
2038 /* This is the first non-null input. */
2039 newval = (int64) PG_GETARG_INT16(1);
2040 PG_RETURN_INT64(newval);
2043 oldsum = PG_GETARG_INT64(0);
2045 /* Leave sum unchanged if new input is null. */
2046 if (PG_ARGISNULL(1))
2047 PG_RETURN_INT64(oldsum);
2049 /* OK to do the addition. */
2050 newval = oldsum + (int64) PG_GETARG_INT16(1);
2052 PG_RETURN_INT64(newval);
2056 int4_sum(PG_FUNCTION_ARGS)
2061 if (PG_ARGISNULL(0))
2063 /* No non-null input seen so far... */
2064 if (PG_ARGISNULL(1))
2065 PG_RETURN_NULL(); /* still no non-null */
2066 /* This is the first non-null input. */
2067 newval = (int64) PG_GETARG_INT32(1);
2068 PG_RETURN_INT64(newval);
2071 oldsum = PG_GETARG_INT64(0);
2073 /* Leave sum unchanged if new input is null. */
2074 if (PG_ARGISNULL(1))
2075 PG_RETURN_INT64(oldsum);
2077 /* OK to do the addition. */
2078 newval = oldsum + (int64) PG_GETARG_INT32(1);
2080 PG_RETURN_INT64(newval);
2084 int8_sum(PG_FUNCTION_ARGS)
2089 if (PG_ARGISNULL(0))
2091 /* No non-null input seen so far... */
2092 if (PG_ARGISNULL(1))
2093 PG_RETURN_NULL(); /* still no non-null */
2094 /* This is the first non-null input. */
2095 newval = DirectFunctionCall1(int8_numeric, PG_GETARG_DATUM(1));
2096 PG_RETURN_DATUM(newval);
2099 oldsum = PG_GETARG_NUMERIC(0);
2101 /* Leave sum unchanged if new input is null. */
2102 if (PG_ARGISNULL(1))
2103 PG_RETURN_NUMERIC(oldsum);
2105 /* OK to do the addition. */
2106 newval = DirectFunctionCall1(int8_numeric, PG_GETARG_DATUM(1));
2108 PG_RETURN_DATUM(DirectFunctionCall2(numeric_add,
2109 NumericGetDatum(oldsum), newval));
2114 * Routines for avg(int2) and avg(int4). The transition datatype
2115 * is a two-element int8 array, holding count and sum.
2118 typedef struct Int8TransTypeData
2120 #ifndef INT64_IS_BUSTED
2124 /* "int64" isn't really 64 bits, so fake up properly-aligned fields */
2130 } Int8TransTypeData;
2133 int2_avg_accum(PG_FUNCTION_ARGS)
2135 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P_COPY(0);
2136 int16 newval = PG_GETARG_INT16(1);
2137 Int8TransTypeData *transdata;
2140 * We copied the input array, so it's okay to scribble on it directly.
2142 if (ARR_SIZE(transarray) != ARR_OVERHEAD(1) + sizeof(Int8TransTypeData))
2143 elog(ERROR, "int2_avg_accum: expected 2-element int8 array");
2144 transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
2147 transdata->sum += newval;
2149 PG_RETURN_ARRAYTYPE_P(transarray);
2153 int4_avg_accum(PG_FUNCTION_ARGS)
2155 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P_COPY(0);
2156 int32 newval = PG_GETARG_INT32(1);
2157 Int8TransTypeData *transdata;
2160 * We copied the input array, so it's okay to scribble on it directly.
2162 if (ARR_SIZE(transarray) != ARR_OVERHEAD(1) + sizeof(Int8TransTypeData))
2163 elog(ERROR, "int4_avg_accum: expected 2-element int8 array");
2164 transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
2167 transdata->sum += newval;
2169 PG_RETURN_ARRAYTYPE_P(transarray);
2173 int8_avg(PG_FUNCTION_ARGS)
2175 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
2176 Int8TransTypeData *transdata;
2180 if (ARR_SIZE(transarray) != ARR_OVERHEAD(1) + sizeof(Int8TransTypeData))
2181 elog(ERROR, "int8_avg: expected 2-element int8 array");
2182 transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
2184 /* SQL92 defines AVG of no values to be NULL */
2185 if (transdata->count == 0)
2188 countd = DirectFunctionCall1(int8_numeric,
2189 Int64GetDatumFast(transdata->count));
2190 sumd = DirectFunctionCall1(int8_numeric,
2191 Int64GetDatumFast(transdata->sum));
2193 PG_RETURN_DATUM(DirectFunctionCall2(numeric_div, sumd, countd));
2197 /* ----------------------------------------------------------------------
2199 * Local functions follow
2201 * ----------------------------------------------------------------------
2205 #ifdef NUMERIC_DEBUG
2208 * dump_numeric() - Dump a value in the db storage format for debugging
2212 dump_numeric(char *str, Numeric num)
2216 printf("%s: NUMERIC w=%d r=%d d=%d ", str, num->n_weight, num->n_rscale,
2217 NUMERIC_DSCALE(num));
2218 switch (NUMERIC_SIGN(num))
2230 printf("SIGN=0x%x", NUMERIC_SIGN(num));
2234 for (i = 0; i < num->varlen - NUMERIC_HDRSZ; i++)
2235 printf(" %d %d", (num->n_data[i] >> 4) & 0x0f, num->n_data[i] & 0x0f);
2241 * dump_var() - Dump a value in the variable format for debugging
2245 dump_var(char *str, NumericVar *var)
2249 printf("%s: VAR w=%d r=%d d=%d ", str, var->weight, var->rscale,
2263 printf("SIGN=0x%x", var->sign);
2267 for (i = 0; i < var->ndigits; i++)
2268 printf(" %d", var->digits[i]);
2273 #endif /* NUMERIC_DEBUG */
2279 * Allocate a digit buffer of ndigits digits (plus a spare digit for rounding)
2283 alloc_var(NumericVar *var, int ndigits)
2285 digitbuf_free(var->buf);
2286 var->buf = digitbuf_alloc(ndigits + 1);
2288 var->digits = var->buf + 1;
2289 var->ndigits = ndigits;
2296 * Return the digit buffer of a variable to the free pool
2300 free_var(NumericVar *var)
2302 digitbuf_free(var->buf);
2305 var->sign = NUMERIC_NAN;
2312 * Set a variable to ZERO.
2313 * Note: rscale and dscale are not touched.
2317 zero_var(NumericVar *var)
2319 digitbuf_free(var->buf);
2323 var->weight = 0; /* by convention; doesn't really matter */
2324 var->sign = NUMERIC_POS; /* anything but NAN... */
2329 * set_var_from_str()
2331 * Parse a string and put the number into a variable
2335 set_var_from_str(char *str, NumericVar *dest)
2338 bool have_dp = FALSE;
2343 if (!isspace((unsigned char) *cp))
2348 alloc_var(dest, strlen(cp));
2351 dest->sign = NUMERIC_POS;
2356 dest->sign = NUMERIC_POS;
2361 dest->sign = NUMERIC_NEG;
2372 if (!isdigit((unsigned char) *cp))
2373 elog(ERROR, "Bad numeric input format '%s'", str);
2377 if (isdigit((unsigned char) *cp))
2379 dest->digits[i++] = *cp++ - '0';
2385 else if (*cp == '.')
2388 elog(ERROR, "Bad numeric input format '%s'", str);
2397 /* Handle exponent, if any */
2398 if (*cp == 'e' || *cp == 'E')
2404 exponent = strtol(cp, &endptr, 10);
2406 elog(ERROR, "Bad numeric input format '%s'", str);
2408 if (exponent > NUMERIC_MAX_PRECISION ||
2409 exponent < -NUMERIC_MAX_PRECISION)
2410 elog(ERROR, "Bad numeric input format '%s'", str);
2411 dest->weight += (int) exponent;
2412 dest->dscale -= (int) exponent;
2413 if (dest->dscale < 0)
2417 /* Should be nothing left but spaces */
2420 if (!isspace((unsigned char) *cp))
2421 elog(ERROR, "Bad numeric input format '%s'", str);
2425 /* Strip any leading zeroes */
2426 while (dest->ndigits > 0 && *(dest->digits) == 0)
2432 if (dest->ndigits == 0)
2435 dest->rscale = dest->dscale;
2440 * set_var_from_num() -
2442 * Parse back the packed db format into a variable
2446 set_var_from_num(Numeric num, NumericVar *dest)
2448 NumericDigit *digit;
2452 n = num->varlen - NUMERIC_HDRSZ; /* number of digit-pairs in packed
2455 alloc_var(dest, n * 2);
2457 dest->weight = num->n_weight;
2458 dest->rscale = num->n_rscale;
2459 dest->dscale = NUMERIC_DSCALE(num);
2460 dest->sign = NUMERIC_SIGN(num);
2462 digit = dest->digits;
2464 for (i = 0; i < n; i++)
2466 unsigned char digitpair = num->n_data[i];
2468 *digit++ = (digitpair >> 4) & 0x0f;
2469 *digit++ = digitpair & 0x0f;
2475 * set_var_from_var() -
2477 * Copy one variable into another
2481 set_var_from_var(NumericVar *value, NumericVar *dest)
2483 NumericDigit *newbuf;
2485 newbuf = digitbuf_alloc(value->ndigits + 1);
2486 newbuf[0] = 0; /* spare digit for rounding */
2487 memcpy(newbuf + 1, value->digits, value->ndigits);
2489 digitbuf_free(dest->buf);
2491 memcpy(dest, value, sizeof(NumericVar));
2493 dest->digits = newbuf + 1;
2498 * get_str_from_var() -
2500 * Convert a var to text representation (guts of numeric_out).
2501 * CAUTION: var's contents may be modified by rounding!
2502 * Caller must have checked for NaN case.
2503 * Returns a palloc'd string.
2507 get_str_from_var(NumericVar *var, int dscale)
2515 * Check if we must round up before printing the value and do so.
2517 i = dscale + var->weight + 1;
2518 if (i >= 0 && var->ndigits > i)
2520 int carry = (var->digits[i] > 4) ? 1 : 0;
2526 carry += var->digits[--i];
2527 var->digits[i] = carry % 10;
2533 Assert(i == -1); /* better not have added more than 1 digit */
2534 Assert(var->digits > var->buf);
2541 var->ndigits = MAX(0, MIN(i, var->ndigits));
2544 * Allocate space for the result
2546 str = palloc(MAX(0, dscale) + MAX(0, var->weight) + 4);
2550 * Output a dash for negative values
2552 if (var->sign == NUMERIC_NEG)
2556 * Output all digits before the decimal point
2558 i = MAX(var->weight, 0);
2563 if (i <= var->weight && d < var->ndigits)
2564 *cp++ = var->digits[d++] + '0';
2571 * If requested, output a decimal point and all the digits that follow
2577 while (i >= -dscale)
2579 if (i <= var->weight && d < var->ndigits)
2580 *cp++ = var->digits[d++] + '0';
2588 * terminate the string and return it
2598 * Create the packed db numeric format in palloc()'d memory from
2599 * a variable. The var's rscale determines the number of digits kept.
2603 make_result(NumericVar *var)
2606 NumericDigit *digit = var->digits;
2607 int weight = var->weight;
2608 int sign = var->sign;
2613 if (sign == NUMERIC_NAN)
2615 result = (Numeric) palloc(NUMERIC_HDRSZ);
2617 result->varlen = NUMERIC_HDRSZ;
2618 result->n_weight = 0;
2619 result->n_rscale = 0;
2620 result->n_sign_dscale = NUMERIC_NAN;
2622 dump_numeric("make_result()", result);
2626 n = MAX(0, MIN(var->ndigits, var->weight + var->rscale + 1));
2628 /* truncate leading zeroes */
2629 while (n > 0 && *digit == 0)
2635 /* truncate trailing zeroes */
2636 while (n > 0 && digit[n - 1] == 0)
2639 /* If zero result, force to weight=0 and positive sign */
2646 result = (Numeric) palloc(NUMERIC_HDRSZ + (n + 1) / 2);
2647 result->varlen = NUMERIC_HDRSZ + (n + 1) / 2;
2648 result->n_weight = weight;
2649 result->n_rscale = var->rscale;
2650 result->n_sign_dscale = sign |
2651 ((uint16) var->dscale & NUMERIC_DSCALE_MASK);
2657 unsigned char digitpair = digit[j++] << 4;
2660 digitpair |= digit[j++];
2661 result->n_data[i++] = digitpair;
2664 dump_numeric("make_result()", result);
2672 * Do bounds checking and rounding according to the attributes
2677 apply_typmod(NumericVar *var, int32 typmod)
2684 /* Do nothing if we have a default typmod (-1) */
2685 if (typmod < (int32) (VARHDRSZ))
2689 precision = (typmod >> 16) & 0xffff;
2690 scale = typmod & 0xffff;
2691 maxweight = precision - scale;
2693 /* Round to target scale */
2694 i = scale + var->weight + 1;
2695 if (i >= 0 && var->ndigits > i)
2697 int carry = (var->digits[i] > 4) ? 1 : 0;
2703 carry += var->digits[--i];
2704 var->digits[i] = carry % 10;
2710 Assert(i == -1); /* better not have added more than 1 digit */
2711 Assert(var->digits > var->buf);
2718 var->ndigits = MAX(0, MIN(i, var->ndigits));
2721 * Check for overflow - note we can't do this before rounding, because
2722 * rounding could raise the weight. Also note that the var's weight
2723 * could be inflated by leading zeroes, which will be stripped before
2724 * storage but perhaps might not have been yet. In any case, we must
2725 * recognize a true zero, whose weight doesn't mean anything.
2727 if (var->weight >= maxweight)
2729 /* Determine true weight; and check for all-zero result */
2730 int tweight = var->weight;
2732 for (i = 0; i < var->ndigits; i++)
2739 if (tweight >= maxweight && i < var->ndigits)
2740 elog(ERROR, "overflow on numeric "
2741 "ABS(value) >= 10^%d for field with precision %d scale %d",
2742 tweight, precision, scale);
2745 var->rscale = scale;
2746 var->dscale = scale;
2753 * Compare two values on variable level
2757 cmp_var(NumericVar *var1, NumericVar *var2)
2759 if (var1->ndigits == 0)
2761 if (var2->ndigits == 0)
2763 if (var2->sign == NUMERIC_NEG)
2767 if (var2->ndigits == 0)
2769 if (var1->sign == NUMERIC_POS)
2774 if (var1->sign == NUMERIC_POS)
2776 if (var2->sign == NUMERIC_NEG)
2778 return cmp_abs(var1, var2);
2781 if (var2->sign == NUMERIC_POS)
2784 return cmp_abs(var2, var1);
2791 * Full version of add functionality on variable level (handling signs).
2792 * result might point to one of the operands too without danger.
2796 add_var(NumericVar *var1, NumericVar *var2, NumericVar *result)
2800 * Decide on the signs of the two variables what to do
2802 if (var1->sign == NUMERIC_POS)
2804 if (var2->sign == NUMERIC_POS)
2808 * Both are positive result = +(ABS(var1) + ABS(var2))
2810 add_abs(var1, var2, result);
2811 result->sign = NUMERIC_POS;
2817 * var1 is positive, var2 is negative Must compare absolute
2820 switch (cmp_abs(var1, var2))
2824 * ABS(var1) == ABS(var2)
2829 result->rscale = MAX(var1->rscale, var2->rscale);
2830 result->dscale = MAX(var1->dscale, var2->dscale);
2835 * ABS(var1) > ABS(var2)
2836 * result = +(ABS(var1) - ABS(var2))
2839 sub_abs(var1, var2, result);
2840 result->sign = NUMERIC_POS;
2845 * ABS(var1) < ABS(var2)
2846 * result = -(ABS(var2) - ABS(var1))
2849 sub_abs(var2, var1, result);
2850 result->sign = NUMERIC_NEG;
2857 if (var2->sign == NUMERIC_POS)
2860 * var1 is negative, var2 is positive
2861 * Must compare absolute values
2864 switch (cmp_abs(var1, var2))
2868 * ABS(var1) == ABS(var2)
2873 result->rscale = MAX(var1->rscale, var2->rscale);
2874 result->dscale = MAX(var1->dscale, var2->dscale);
2879 * ABS(var1) > ABS(var2)
2880 * result = -(ABS(var1) - ABS(var2))
2883 sub_abs(var1, var2, result);
2884 result->sign = NUMERIC_NEG;
2889 * ABS(var1) < ABS(var2)
2890 * result = +(ABS(var2) - ABS(var1))
2893 sub_abs(var2, var1, result);
2894 result->sign = NUMERIC_POS;
2902 * result = -(ABS(var1) + ABS(var2))
2905 add_abs(var1, var2, result);
2906 result->sign = NUMERIC_NEG;
2915 * Full version of sub functionality on variable level (handling signs).
2916 * result might point to one of the operands too without danger.
2920 sub_var(NumericVar *var1, NumericVar *var2, NumericVar *result)
2924 * Decide on the signs of the two variables what to do
2926 if (var1->sign == NUMERIC_POS)
2928 if (var2->sign == NUMERIC_NEG)
2931 * var1 is positive, var2 is negative
2932 * result = +(ABS(var1) + ABS(var2))
2935 add_abs(var1, var2, result);
2936 result->sign = NUMERIC_POS;
2942 * Must compare absolute values
2945 switch (cmp_abs(var1, var2))
2949 * ABS(var1) == ABS(var2)
2954 result->rscale = MAX(var1->rscale, var2->rscale);
2955 result->dscale = MAX(var1->dscale, var2->dscale);
2960 * ABS(var1) > ABS(var2)
2961 * result = +(ABS(var1) - ABS(var2))
2964 sub_abs(var1, var2, result);
2965 result->sign = NUMERIC_POS;
2970 * ABS(var1) < ABS(var2)
2971 * result = -(ABS(var2) - ABS(var1))
2974 sub_abs(var2, var1, result);
2975 result->sign = NUMERIC_NEG;
2982 if (var2->sign == NUMERIC_NEG)
2986 * Must compare absolute values
2989 switch (cmp_abs(var1, var2))
2993 * ABS(var1) == ABS(var2)
2998 result->rscale = MAX(var1->rscale, var2->rscale);
2999 result->dscale = MAX(var1->dscale, var2->dscale);
3004 * ABS(var1) > ABS(var2)
3005 * result = -(ABS(var1) - ABS(var2))
3008 sub_abs(var1, var2, result);
3009 result->sign = NUMERIC_NEG;
3014 * ABS(var1) < ABS(var2)
3015 * result = +(ABS(var2) - ABS(var1))
3018 sub_abs(var2, var1, result);
3019 result->sign = NUMERIC_POS;
3026 * var1 is negative, var2 is positive
3027 * result = -(ABS(var1) + ABS(var2))
3030 add_abs(var1, var2, result);
3031 result->sign = NUMERIC_NEG;
3040 * Multiplication on variable level. Product of var1 * var2 is stored
3045 mul_var(NumericVar *var1, NumericVar *var2, NumericVar *result)
3047 NumericDigit *res_buf;
3048 NumericDigit *res_digits;
3058 res_weight = var1->weight + var2->weight + 2;
3059 res_ndigits = var1->ndigits + var2->ndigits + 1;
3060 if (var1->sign == var2->sign)
3061 res_sign = NUMERIC_POS;
3063 res_sign = NUMERIC_NEG;
3065 res_buf = digitbuf_alloc(res_ndigits);
3066 res_digits = res_buf;
3067 memset(res_digits, 0, res_ndigits);
3070 for (i1 = var1->ndigits - 1; i1 >= 0; i1--)
3075 for (i2 = var2->ndigits - 1; i2 >= 0; i2--)
3077 sum += res_digits[i] + var1->digits[i1] * var2->digits[i2];
3078 res_digits[i--] = sum % 10;
3081 res_digits[i] = sum;
3084 i = res_weight + global_rscale + 2;
3085 if (i >= 0 && i < res_ndigits)
3087 sum = (res_digits[i] > 4) ? 1 : 0;
3092 sum += res_digits[i];
3093 res_digits[i--] = sum % 10;
3098 while (res_ndigits > 0 && *res_digits == 0)
3104 while (res_ndigits > 0 && res_digits[res_ndigits - 1] == 0)
3107 if (res_ndigits == 0)
3109 res_sign = NUMERIC_POS;
3113 digitbuf_free(result->buf);
3114 result->buf = res_buf;
3115 result->digits = res_digits;
3116 result->ndigits = res_ndigits;
3117 result->weight = res_weight;
3118 result->rscale = global_rscale;
3119 result->sign = res_sign;
3126 * Division on variable level.
3130 div_var(NumericVar *var1, NumericVar *var2, NumericVar *result)
3132 NumericDigit *res_digits;
3136 NumericVar dividend;
3137 NumericVar divisor[10];
3146 int first_nextdigit;
3150 * First of all division by zero check
3152 ndigits_tmp = var2->ndigits + 1;
3153 if (ndigits_tmp == 1)
3154 elog(ERROR, "division by zero on numeric");
3157 * Determine the result sign, weight and number of digits to calculate
3159 if (var1->sign == var2->sign)
3160 res_sign = NUMERIC_POS;
3162 res_sign = NUMERIC_NEG;
3163 res_weight = var1->weight - var2->weight + 1;
3164 res_ndigits = global_rscale + res_weight;
3165 if (res_ndigits <= 0)
3169 * Now result zero check
3171 if (var1->ndigits == 0)
3174 result->rscale = global_rscale;
3179 * Initialize local variables
3181 init_var(÷nd);
3182 for (i = 1; i < 10; i++)
3183 init_var(&divisor[i]);
3186 * Make a copy of the divisor which has one leading zero digit
3188 divisor[1].ndigits = ndigits_tmp;
3189 divisor[1].rscale = var2->ndigits;
3190 divisor[1].sign = NUMERIC_POS;
3191 divisor[1].buf = digitbuf_alloc(ndigits_tmp);
3192 divisor[1].digits = divisor[1].buf;
3193 divisor[1].digits[0] = 0;
3194 memcpy(&(divisor[1].digits[1]), var2->digits, ndigits_tmp - 1);
3197 * Make a copy of the dividend
3199 dividend.ndigits = var1->ndigits;
3200 dividend.weight = 0;
3201 dividend.rscale = var1->ndigits;
3202 dividend.sign = NUMERIC_POS;
3203 dividend.buf = digitbuf_alloc(var1->ndigits);
3204 dividend.digits = dividend.buf;
3205 memcpy(dividend.digits, var1->digits, var1->ndigits);
3210 digitbuf_free(result->buf);
3211 result->buf = digitbuf_alloc(res_ndigits + 2);
3212 res_digits = result->buf;
3213 result->digits = res_digits;
3214 result->ndigits = res_ndigits;
3215 result->weight = res_weight;
3216 result->rscale = global_rscale;
3217 result->sign = res_sign;
3220 first_div = divisor[1].digits[1] * 10;
3221 if (ndigits_tmp > 2)
3222 first_div += divisor[1].digits[2];
3225 first_nextdigit = 0;
3228 rscale_tmp = divisor[1].rscale;
3230 for (ri = 0; ri <= res_ndigits; ri++)
3232 first_have = first_have * 10;
3233 if (first_nextdigit >= 0 && first_nextdigit < dividend.ndigits)
3234 first_have += dividend.digits[first_nextdigit];
3237 guess = (first_have * 10) / first_div + 1;
3243 if (divisor[guess].buf == NULL)
3248 memcpy(&divisor[guess], &divisor[1], sizeof(NumericVar));
3249 divisor[guess].buf = digitbuf_alloc(divisor[guess].ndigits);
3250 divisor[guess].digits = divisor[guess].buf;
3251 for (i = divisor[1].ndigits - 1; i >= 0; i--)
3253 sum += divisor[1].digits[i] * guess;
3254 divisor[guess].digits[i] = sum % 10;
3259 divisor[guess].weight = weight_tmp;
3260 divisor[guess].rscale = rscale_tmp;
3262 stat = cmp_abs(÷nd, &divisor[guess]);
3269 res_digits[ri + 1] = guess;
3282 sub_abs(÷nd, &divisor[guess], ÷nd);
3284 first_nextdigit = dividend.weight - weight_tmp;
3286 if (first_nextdigit >= 0 && first_nextdigit < dividend.ndigits)
3287 first_have = dividend.digits[first_nextdigit];
3291 result->ndigits = ri + 1;
3292 if (ri == res_ndigits + 1)
3294 int carry = (res_digits[ri] > 4) ? 1 : 0;
3296 result->ndigits = ri;
3299 while (carry && ri > 0)
3301 carry += res_digits[--ri];
3302 res_digits[ri] = carry % 10;
3307 while (result->ndigits > 0 && *(result->digits) == 0)
3311 (result->ndigits)--;
3313 while (result->ndigits > 0 && result->digits[result->ndigits - 1] == 0)
3314 (result->ndigits)--;
3315 if (result->ndigits == 0)
3316 result->sign = NUMERIC_POS;
3321 digitbuf_free(dividend.buf);
3322 for (i = 1; i < 10; i++)
3323 digitbuf_free(divisor[i].buf);
3330 * Calculate the modulo of two numerics at variable level
3334 mod_var(NumericVar *var1, NumericVar *var2, NumericVar *result)
3337 int save_global_rscale;
3343 * We do this using the equation
3344 * mod(x,y) = x - trunc(x/y)*y
3345 * We set global_rscale the same way numeric_div and numeric_mul do
3346 * to get the right answer from the equation. The final result,
3347 * however, need not be displayed to more precision than the inputs.
3350 save_global_rscale = global_rscale;
3352 div_dscale = MAX(var1->dscale + var2->dscale, NUMERIC_MIN_DISPLAY_SCALE);
3353 div_dscale = MIN(div_dscale, NUMERIC_MAX_DISPLAY_SCALE);
3354 global_rscale = MAX(var1->rscale + var2->rscale,
3355 NUMERIC_MIN_RESULT_SCALE);
3356 global_rscale = MAX(global_rscale, div_dscale + 4);
3357 global_rscale = MIN(global_rscale, NUMERIC_MAX_RESULT_SCALE);
3359 div_var(var1, var2, &tmp);
3361 tmp.dscale = div_dscale;
3363 /* do trunc() by forgetting digits to the right of the decimal point */
3364 tmp.ndigits = MAX(0, MIN(tmp.ndigits, tmp.weight + 1));
3366 global_rscale = var2->rscale + tmp.rscale;
3368 mul_var(var2, &tmp, &tmp);
3370 sub_var(var1, &tmp, result);
3372 result->dscale = MAX(var1->dscale, var2->dscale);
3374 global_rscale = save_global_rscale;
3382 * Return the smallest integer greater than or equal to the argument
3387 ceil_var(NumericVar *var, NumericVar *result)
3392 set_var_from_var(var, &tmp);
3395 tmp.ndigits = MIN(tmp.ndigits, MAX(0, tmp.weight + 1));
3396 if (tmp.sign == NUMERIC_POS && cmp_var(var, &tmp) != 0)
3397 add_var(&tmp, &const_one, &tmp);
3399 set_var_from_var(&tmp, result);
3407 * Return the largest integer equal to or less than the argument
3412 floor_var(NumericVar *var, NumericVar *result)
3417 set_var_from_var(var, &tmp);
3420 tmp.ndigits = MIN(tmp.ndigits, MAX(0, tmp.weight + 1));
3421 if (tmp.sign == NUMERIC_NEG && cmp_var(var, &tmp) != 0)
3422 sub_var(&tmp, &const_one, &tmp);
3424 set_var_from_var(&tmp, result);
3432 * Compute the square root of x using Newtons algorithm
3436 sqrt_var(NumericVar *arg, NumericVar *result)
3440 NumericVar last_val;
3442 int save_global_rscale;
3445 save_global_rscale = global_rscale;
3447 res_rscale = global_rscale;
3449 stat = cmp_var(arg, &const_zero);
3452 set_var_from_var(&const_zero, result);
3453 result->rscale = res_rscale;
3454 result->sign = NUMERIC_POS;
3459 elog(ERROR, "math error on numeric - cannot compute SQRT of negative value");
3463 init_var(&last_val);
3465 set_var_from_var(arg, &tmp_arg);
3466 set_var_from_var(result, &last_val);
3469 * Initialize the result to the first guess
3471 digitbuf_free(result->buf);
3472 result->buf = digitbuf_alloc(1);
3473 result->digits = result->buf;
3474 result->digits[0] = tmp_arg.digits[0] / 2;
3475 if (result->digits[0] == 0)
3476 result->digits[0] = 1;
3477 result->ndigits = 1;
3478 result->weight = tmp_arg.weight / 2;
3479 result->rscale = res_rscale;
3480 result->sign = NUMERIC_POS;
3484 div_var(&tmp_arg, result, &tmp_val);
3486 add_var(result, &tmp_val, result);
3487 div_var(result, &const_two, result);
3489 if (cmp_var(&last_val, result) == 0)
3491 set_var_from_var(result, &last_val);
3494 free_var(&last_val);
3498 global_rscale = save_global_rscale;
3499 div_var(result, &const_one, result);
3506 * Raise e to the power of x
3510 exp_var(NumericVar *arg, NumericVar *result)
3521 int save_global_rscale;
3529 set_var_from_var(arg, &x);
3531 if (x.sign == NUMERIC_NEG)
3534 x.sign = NUMERIC_POS;
3537 save_global_rscale = global_rscale;
3539 for (i = x.weight, d = 0; i >= 0; i--, d++)
3541 global_rscale *= 10;
3543 global_rscale += x.digits[d];
3544 if (global_rscale >= 1000)
3545 elog(ERROR, "argument for EXP() too big");
3548 global_rscale = global_rscale / 2 + save_global_rscale + 8;
3550 while (cmp_var(&x, &const_one) > 0)
3554 div_var(&x, &const_two, &x);
3557 add_var(&const_one, &x, result);
3558 set_var_from_var(&x, &xpow);
3559 set_var_from_var(&const_one, &ifac);
3560 set_var_from_var(&const_one, &ni);
3564 add_var(&ni, &const_one, &ni);
3565 mul_var(&xpow, &x, &xpow);
3566 mul_var(&ifac, &ni, &ifac);
3567 div_var(&xpow, &ifac, &elem);
3569 if (elem.ndigits == 0)
3572 add_var(result, &elem, result);
3576 mul_var(result, result, result);
3578 global_rscale = save_global_rscale;
3580 div_var(&const_one, result, result);
3582 div_var(result, &const_one, result);
3584 result->sign = NUMERIC_POS;
3597 * Compute the natural log of x
3601 ln_var(NumericVar *arg, NumericVar *result)
3609 int save_global_rscale;
3611 if (cmp_var(arg, &const_zero) <= 0)
3612 elog(ERROR, "math error on numeric - cannot compute LN of value <= zero");
3614 save_global_rscale = global_rscale;
3623 set_var_from_var(&const_two, &fact);
3624 set_var_from_var(arg, &x);
3626 while (cmp_var(&x, &const_two) >= 0)
3629 mul_var(&fact, &const_two, &fact);
3631 set_var_from_str("0.5", &elem);
3632 while (cmp_var(&x, &elem) <= 0)
3635 mul_var(&fact, &const_two, &fact);
3638 sub_var(&x, &const_one, result);
3639 add_var(&x, &const_one, &elem);
3640 div_var(result, &elem, result);
3641 set_var_from_var(result, &xx);
3642 mul_var(result, result, &x);
3644 set_var_from_var(&const_one, &ni);
3648 add_var(&ni, &const_two, &ni);
3649 mul_var(&xx, &x, &xx);
3650 div_var(&xx, &ni, &elem);
3652 if (cmp_var(&elem, &const_zero) == 0)
3655 add_var(result, &elem, result);
3658 global_rscale = save_global_rscale;
3659 mul_var(result, &fact, result);
3672 * Compute the logarithm of x in a given base
3676 log_var(NumericVar *base, NumericVar *num, NumericVar *result)
3686 ln_var(base, &ln_base);
3687 ln_var(num, &ln_num);
3691 div_var(&ln_num, &ln_base, result);
3701 * Raise base to the power of exp
3705 power_var(NumericVar *base, NumericVar *exp, NumericVar *result)
3709 int save_global_rscale;
3711 save_global_rscale = global_rscale;
3712 global_rscale += global_rscale / 3 + 8;
3717 ln_var(base, &ln_base);
3718 mul_var(&ln_base, exp, &ln_num);
3720 global_rscale = save_global_rscale;
3722 exp_var(&ln_num, result);
3730 /* ----------------------------------------------------------------------
3732 * Following are the lowest level functions that operate unsigned
3733 * on the variable level
3735 * ----------------------------------------------------------------------
3742 * Compare the absolute values of var1 and var2
3743 * Returns: -1 for ABS(var1) < ABS(var2)
3744 * 0 for ABS(var1) == ABS(var2)
3745 * 1 for ABS(var1) > ABS(var2)
3749 cmp_abs(NumericVar *var1, NumericVar *var2)
3753 int w1 = var1->weight;
3754 int w2 = var2->weight;
3757 while (w1 > w2 && i1 < var1->ndigits)
3759 if (var1->digits[i1++] != 0)
3763 while (w2 > w1 && i2 < var2->ndigits)
3765 if (var2->digits[i2++] != 0)
3772 while (i1 < var1->ndigits && i2 < var2->ndigits)
3774 stat = var1->digits[i1++] - var2->digits[i2++];
3784 while (i1 < var1->ndigits)
3786 if (var1->digits[i1++] != 0)
3789 while (i2 < var2->ndigits)
3791 if (var2->digits[i2++] != 0)
3802 * Add the absolute values of two variables into result.
3803 * result might point to one of the operands without danger.
3807 add_abs(NumericVar *var1, NumericVar *var2, NumericVar *result)
3809 NumericDigit *res_buf;
3810 NumericDigit *res_digits;
3820 /* copy these values into local vars for speed in inner loop */
3821 int var1ndigits = var1->ndigits;
3822 int var2ndigits = var2->ndigits;
3823 NumericDigit *var1digits = var1->digits;
3824 NumericDigit *var2digits = var2->digits;
3826 res_weight = MAX(var1->weight, var2->weight) + 1;
3827 res_rscale = MAX(var1->rscale, var2->rscale);
3828 res_dscale = MAX(var1->dscale, var2->dscale);
3829 res_ndigits = res_rscale + res_weight + 1;
3830 if (res_ndigits <= 0)
3833 res_buf = digitbuf_alloc(res_ndigits);
3834 res_digits = res_buf;
3836 i1 = res_rscale + var1->weight + 1;
3837 i2 = res_rscale + var2->weight + 1;
3838 for (i = res_ndigits - 1; i >= 0; i--)
3842 if (i1 >= 0 && i1 < var1ndigits)
3843 carry += var1digits[i1];
3844 if (i2 >= 0 && i2 < var2ndigits)
3845 carry += var2digits[i2];
3849 res_digits[i] = carry - 10;
3854 res_digits[i] = carry;
3859 Assert(carry == 0); /* else we failed to allow for carry out */
3861 while (res_ndigits > 0 && *res_digits == 0)
3867 while (res_ndigits > 0 && res_digits[res_ndigits - 1] == 0)
3870 if (res_ndigits == 0)
3873 digitbuf_free(result->buf);
3874 result->ndigits = res_ndigits;
3875 result->buf = res_buf;
3876 result->digits = res_digits;
3877 result->weight = res_weight;
3878 result->rscale = res_rscale;
3879 result->dscale = res_dscale;
3886 * Subtract the absolute value of var2 from the absolute value of var1
3887 * and store in result. result might point to one of the operands
3890 * ABS(var1) MUST BE GREATER OR EQUAL ABS(var2) !!!
3894 sub_abs(NumericVar *var1, NumericVar *var2, NumericVar *result)
3896 NumericDigit *res_buf;
3897 NumericDigit *res_digits;
3907 /* copy these values into local vars for speed in inner loop */
3908 int var1ndigits = var1->ndigits;
3909 int var2ndigits = var2->ndigits;
3910 NumericDigit *var1digits = var1->digits;
3911 NumericDigit *var2digits = var2->digits;
3913 res_weight = var1->weight;
3914 res_rscale = MAX(var1->rscale, var2->rscale);
3915 res_dscale = MAX(var1->dscale, var2->dscale);
3916 res_ndigits = res_rscale + res_weight + 1;
3917 if (res_ndigits <= 0)
3920 res_buf = digitbuf_alloc(res_ndigits);
3921 res_digits = res_buf;
3923 i1 = res_rscale + var1->weight + 1;
3924 i2 = res_rscale + var2->weight + 1;
3925 for (i = res_ndigits - 1; i >= 0; i--)
3929 if (i1 >= 0 && i1 < var1ndigits)
3930 borrow += var1digits[i1];
3931 if (i2 >= 0 && i2 < var2ndigits)
3932 borrow -= var2digits[i2];
3936 res_digits[i] = borrow + 10;
3941 res_digits[i] = borrow;
3946 Assert(borrow == 0); /* else caller gave us var1 < var2 */
3948 while (res_ndigits > 0 && *res_digits == 0)
3954 while (res_ndigits > 0 && res_digits[res_ndigits - 1] == 0)
3957 if (res_ndigits == 0)
3960 digitbuf_free(result->buf);
3961 result->ndigits = res_ndigits;
3962 result->buf = res_buf;
3963 result->digits = res_digits;
3964 result->weight = res_weight;
3965 result->rscale = res_rscale;
3966 result->dscale = res_dscale;