4 * An exact numeric data type for the Postgres database system
8 * $Header: /cvsroot/pgsql/src/backend/utils/adt/numeric.c,v 1.41 2001/05/03 19:00:36 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);
198 Oid typelem = PG_GETARG_OID(1);
201 int32 typmod = PG_GETARG_INT32(2);
208 if (strcmp(str, "NaN") == 0)
209 PG_RETURN_NUMERIC(make_result(&const_nan));
212 * Use set_var_from_str() to parse the input string and return it in
213 * the packed DB storage format
216 set_var_from_str(str, &value);
218 apply_typmod(&value, typmod);
220 res = make_result(&value);
223 PG_RETURN_NUMERIC(res);
230 * Output function for numeric data type
234 numeric_out(PG_FUNCTION_ARGS)
236 Numeric num = PG_GETARG_NUMERIC(0);
243 if (NUMERIC_IS_NAN(num))
244 PG_RETURN_CSTRING(pstrdup("NaN"));
247 * Get the number in the variable format.
249 * Even if we didn't need to change format, we'd still need to copy the
250 * value to have a modifiable copy for rounding. set_var_from_num()
251 * also guarantees there is extra digit space in case we produce a
252 * carry out from rounding.
255 set_var_from_num(num, &x);
257 str = get_str_from_var(&x, x.dscale);
261 PG_RETURN_CSTRING(str);
268 * This is a special function called by the Postgres database system
269 * before a value is stored in a tuples attribute. The precision and
270 * scale of the attribute have to be applied on the value.
274 numeric(PG_FUNCTION_ARGS)
276 Numeric num = PG_GETARG_NUMERIC(0);
277 int32 typmod = PG_GETARG_INT32(1);
288 if (NUMERIC_IS_NAN(num))
289 PG_RETURN_NUMERIC(make_result(&const_nan));
292 * If the value isn't a valid type modifier, simply return a copy of
295 if (typmod < (int32) (VARHDRSZ))
297 new = (Numeric) palloc(num->varlen);
298 memcpy(new, num, num->varlen);
299 PG_RETURN_NUMERIC(new);
303 * Get the precision and scale out of the typmod value
305 tmp_typmod = typmod - VARHDRSZ;
306 precision = (tmp_typmod >> 16) & 0xffff;
307 scale = tmp_typmod & 0xffff;
308 maxweight = precision - scale;
311 * If the number is in bounds and due to the present result scale no
312 * rounding could be necessary, just make a copy of the input and
313 * modify its scale fields.
315 if (num->n_weight < maxweight && scale >= num->n_rscale)
317 new = (Numeric) palloc(num->varlen);
318 memcpy(new, num, num->varlen);
319 new->n_rscale = scale;
320 new->n_sign_dscale = NUMERIC_SIGN(new) |
321 ((uint16) scale & NUMERIC_DSCALE_MASK);
322 PG_RETURN_NUMERIC(new);
326 * We really need to fiddle with things - unpack the number into a
327 * variable and let apply_typmod() do it.
331 set_var_from_num(num, &var);
332 apply_typmod(&var, typmod);
333 new = make_result(&var);
337 PG_RETURN_NUMERIC(new);
341 /* ----------------------------------------------------------------------
343 * Sign manipulation, rounding and the like
345 * ----------------------------------------------------------------------
349 numeric_abs(PG_FUNCTION_ARGS)
351 Numeric num = PG_GETARG_NUMERIC(0);
357 if (NUMERIC_IS_NAN(num))
358 PG_RETURN_NUMERIC(make_result(&const_nan));
361 * Do it the easy way directly on the packed format
363 res = (Numeric) palloc(num->varlen);
364 memcpy(res, num, num->varlen);
366 res->n_sign_dscale = NUMERIC_POS | NUMERIC_DSCALE(num);
368 PG_RETURN_NUMERIC(res);
373 numeric_uminus(PG_FUNCTION_ARGS)
375 Numeric num = PG_GETARG_NUMERIC(0);
381 if (NUMERIC_IS_NAN(num))
382 PG_RETURN_NUMERIC(make_result(&const_nan));
385 * Do it the easy way directly on the packed format
387 res = (Numeric) palloc(num->varlen);
388 memcpy(res, num, num->varlen);
391 * The packed format is known to be totally zero digit trimmed always.
392 * So we can identify a ZERO by the fact that there are no digits at
393 * all. Do nothing to a zero.
395 if (num->varlen != NUMERIC_HDRSZ)
397 /* Else, flip the sign */
398 if (NUMERIC_SIGN(num) == NUMERIC_POS)
399 res->n_sign_dscale = NUMERIC_NEG | NUMERIC_DSCALE(num);
401 res->n_sign_dscale = NUMERIC_POS | NUMERIC_DSCALE(num);
404 PG_RETURN_NUMERIC(res);
409 numeric_sign(PG_FUNCTION_ARGS)
411 Numeric num = PG_GETARG_NUMERIC(0);
418 if (NUMERIC_IS_NAN(num))
419 PG_RETURN_NUMERIC(make_result(&const_nan));
424 * The packed format is known to be totally zero digit trimmed always.
425 * So we can identify a ZERO by the fact that there are no digits at
428 if (num->varlen == NUMERIC_HDRSZ)
429 set_var_from_var(&const_zero, &result);
434 * And if there are some, we return a copy of ONE with the sign of
437 set_var_from_var(&const_one, &result);
438 result.sign = NUMERIC_SIGN(num);
441 res = make_result(&result);
444 PG_RETURN_NUMERIC(res);
451 * Round a value to have 'scale' digits after the decimal point.
452 * We allow negative 'scale', implying rounding before the decimal
453 * point --- Oracle interprets rounding that way.
457 numeric_round(PG_FUNCTION_ARGS)
459 Numeric num = PG_GETARG_NUMERIC(0);
460 int32 scale = PG_GETARG_INT32(1);
468 if (NUMERIC_IS_NAN(num))
469 PG_RETURN_NUMERIC(make_result(&const_nan));
472 * Limit the scale value to avoid possible overflow in calculations
475 scale = MIN(NUMERIC_MAX_RESULT_SCALE,
476 MAX(-NUMERIC_MAX_RESULT_SCALE, scale));
479 * Unpack the argument and round it at the proper digit position
482 set_var_from_num(num, &arg);
484 i = arg.weight + scale + 1;
490 * If i = 0, the value loses all digits, but could round up if its
491 * first digit is more than 4. If i < 0 the result must be 0.
497 int carry = (arg.digits[i] > 4) ? 1 : 0;
503 carry += arg.digits[--i];
504 arg.digits[i] = carry % 10;
510 Assert(i == -1);/* better not have added more than 1 digit */
511 Assert(arg.digits > arg.buf);
520 * Set result's scale to something reasonable.
522 scale = MIN(NUMERIC_MAX_DISPLAY_SCALE, MAX(0, scale));
527 * Return the rounded result
529 res = make_result(&arg);
532 PG_RETURN_NUMERIC(res);
539 * Truncate a value to have 'scale' digits after the decimal point.
540 * We allow negative 'scale', implying a truncation before the decimal
541 * point --- Oracle interprets truncation that way.
545 numeric_trunc(PG_FUNCTION_ARGS)
547 Numeric num = PG_GETARG_NUMERIC(0);
548 int32 scale = PG_GETARG_INT32(1);
555 if (NUMERIC_IS_NAN(num))
556 PG_RETURN_NUMERIC(make_result(&const_nan));
559 * Limit the scale value to avoid possible overflow in calculations
562 scale = MIN(NUMERIC_MAX_RESULT_SCALE,
563 MAX(-NUMERIC_MAX_RESULT_SCALE, scale));
566 * Unpack the argument and truncate it at the proper digit position
569 set_var_from_num(num, &arg);
571 arg.ndigits = MIN(arg.ndigits, MAX(0, arg.weight + scale + 1));
574 * Set result's scale to something reasonable.
576 scale = MIN(NUMERIC_MAX_DISPLAY_SCALE, MAX(0, scale));
581 * Return the truncated result
583 res = make_result(&arg);
586 PG_RETURN_NUMERIC(res);
593 * Return the smallest integer greater than or equal to the argument
597 numeric_ceil(PG_FUNCTION_ARGS)
599 Numeric num = PG_GETARG_NUMERIC(0);
603 if (NUMERIC_IS_NAN(num))
604 PG_RETURN_NUMERIC(make_result(&const_nan));
608 set_var_from_num(num, &result);
609 ceil_var(&result, &result);
613 res = make_result(&result);
616 PG_RETURN_NUMERIC(res);
623 * Return the largest integer equal to or less than the argument
627 numeric_floor(PG_FUNCTION_ARGS)
629 Numeric num = PG_GETARG_NUMERIC(0);
633 if (NUMERIC_IS_NAN(num))
634 PG_RETURN_NUMERIC(make_result(&const_nan));
638 set_var_from_num(num, &result);
639 floor_var(&result, &result);
643 res = make_result(&result);
646 PG_RETURN_NUMERIC(res);
650 /* ----------------------------------------------------------------------
652 * Comparison functions
654 * Note: btree indexes need these routines not to leak memory; therefore,
655 * be careful to free working copies of toasted datums. Most places don't
656 * need to be so careful.
657 * ----------------------------------------------------------------------
662 numeric_cmp(PG_FUNCTION_ARGS)
664 Numeric num1 = PG_GETARG_NUMERIC(0);
665 Numeric num2 = PG_GETARG_NUMERIC(1);
668 result = cmp_numerics(num1, num2);
670 PG_FREE_IF_COPY(num1, 0);
671 PG_FREE_IF_COPY(num2, 1);
673 PG_RETURN_INT32(result);
678 numeric_eq(PG_FUNCTION_ARGS)
680 Numeric num1 = PG_GETARG_NUMERIC(0);
681 Numeric num2 = PG_GETARG_NUMERIC(1);
684 result = cmp_numerics(num1, num2) == 0;
686 PG_FREE_IF_COPY(num1, 0);
687 PG_FREE_IF_COPY(num2, 1);
689 PG_RETURN_BOOL(result);
693 numeric_ne(PG_FUNCTION_ARGS)
695 Numeric num1 = PG_GETARG_NUMERIC(0);
696 Numeric num2 = PG_GETARG_NUMERIC(1);
699 result = cmp_numerics(num1, num2) != 0;
701 PG_FREE_IF_COPY(num1, 0);
702 PG_FREE_IF_COPY(num2, 1);
704 PG_RETURN_BOOL(result);
708 numeric_gt(PG_FUNCTION_ARGS)
710 Numeric num1 = PG_GETARG_NUMERIC(0);
711 Numeric num2 = PG_GETARG_NUMERIC(1);
714 result = cmp_numerics(num1, num2) > 0;
716 PG_FREE_IF_COPY(num1, 0);
717 PG_FREE_IF_COPY(num2, 1);
719 PG_RETURN_BOOL(result);
723 numeric_ge(PG_FUNCTION_ARGS)
725 Numeric num1 = PG_GETARG_NUMERIC(0);
726 Numeric num2 = PG_GETARG_NUMERIC(1);
729 result = cmp_numerics(num1, num2) >= 0;
731 PG_FREE_IF_COPY(num1, 0);
732 PG_FREE_IF_COPY(num2, 1);
734 PG_RETURN_BOOL(result);
738 numeric_lt(PG_FUNCTION_ARGS)
740 Numeric num1 = PG_GETARG_NUMERIC(0);
741 Numeric num2 = PG_GETARG_NUMERIC(1);
744 result = cmp_numerics(num1, num2) < 0;
746 PG_FREE_IF_COPY(num1, 0);
747 PG_FREE_IF_COPY(num2, 1);
749 PG_RETURN_BOOL(result);
753 numeric_le(PG_FUNCTION_ARGS)
755 Numeric num1 = PG_GETARG_NUMERIC(0);
756 Numeric num2 = PG_GETARG_NUMERIC(1);
759 result = cmp_numerics(num1, num2) <= 0;
761 PG_FREE_IF_COPY(num1, 0);
762 PG_FREE_IF_COPY(num2, 1);
764 PG_RETURN_BOOL(result);
768 cmp_numerics(Numeric num1, Numeric num2)
773 * We consider all NANs to be equal and larger than any non-NAN.
774 * This is somewhat arbitrary; the important thing is to have a
775 * consistent sort order.
777 if (NUMERIC_IS_NAN(num1))
779 if (NUMERIC_IS_NAN(num2))
780 result = 0; /* NAN = NAN */
782 result = 1; /* NAN > non-NAN */
784 else if (NUMERIC_IS_NAN(num2))
786 result = -1; /* non-NAN < NAN */
796 set_var_from_num(num1, &arg1);
797 set_var_from_num(num2, &arg2);
799 result = cmp_var(&arg1, &arg2);
809 /* ----------------------------------------------------------------------
811 * Arithmetic base functions
813 * ----------------------------------------------------------------------
824 numeric_add(PG_FUNCTION_ARGS)
826 Numeric num1 = PG_GETARG_NUMERIC(0);
827 Numeric num2 = PG_GETARG_NUMERIC(1);
836 if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
837 PG_RETURN_NUMERIC(make_result(&const_nan));
840 * Unpack the values, let add_var() compute the result and return it.
841 * The internals of add_var() will automatically set the correct
842 * result and display scales in the result.
848 set_var_from_num(num1, &arg1);
849 set_var_from_num(num2, &arg2);
851 add_var(&arg1, &arg2, &result);
852 res = make_result(&result);
858 PG_RETURN_NUMERIC(res);
865 * Subtract one numeric from another
869 numeric_sub(PG_FUNCTION_ARGS)
871 Numeric num1 = PG_GETARG_NUMERIC(0);
872 Numeric num2 = PG_GETARG_NUMERIC(1);
881 if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
882 PG_RETURN_NUMERIC(make_result(&const_nan));
885 * Unpack the two arguments, let sub_var() compute the result and
892 set_var_from_num(num1, &arg1);
893 set_var_from_num(num2, &arg2);
895 sub_var(&arg1, &arg2, &result);
896 res = make_result(&result);
902 PG_RETURN_NUMERIC(res);
909 * Calculate the product of two numerics
913 numeric_mul(PG_FUNCTION_ARGS)
915 Numeric num1 = PG_GETARG_NUMERIC(0);
916 Numeric num2 = PG_GETARG_NUMERIC(1);
925 if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
926 PG_RETURN_NUMERIC(make_result(&const_nan));
929 * Unpack the arguments, let mul_var() compute the result and return
930 * it. Unlike add_var() and sub_var(), mul_var() will round the result
931 * to the scale stored in global_rscale. In the case of numeric_mul(),
932 * which is invoked for the * operator on numerics, we set it to the
933 * exact representation for the product (rscale = sum(rscale of arg1,
934 * rscale of arg2) and the same for the dscale).
940 set_var_from_num(num1, &arg1);
941 set_var_from_num(num2, &arg2);
943 global_rscale = arg1.rscale + arg2.rscale;
945 mul_var(&arg1, &arg2, &result);
947 result.dscale = arg1.dscale + arg2.dscale;
949 res = make_result(&result);
955 PG_RETURN_NUMERIC(res);
962 * Divide one numeric into another
966 numeric_div(PG_FUNCTION_ARGS)
968 Numeric num1 = PG_GETARG_NUMERIC(0);
969 Numeric num2 = PG_GETARG_NUMERIC(1);
979 if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
980 PG_RETURN_NUMERIC(make_result(&const_nan));
983 * Unpack the arguments
989 set_var_from_num(num1, &arg1);
990 set_var_from_num(num2, &arg2);
993 * The result scale of a division isn't specified in any
994 * SQL standard. For Postgres it is the following (where
995 * SR, DR are the result- and display-scales of the returned
996 * value, S1, D1, S2 and D2 are the scales of the two arguments,
997 * The minimum and maximum scales are compile time options from
1000 * DR = MIN(MAX(D1 + D2, MIN_DISPLAY_SCALE), MAX_DISPLAY_SCALE)
1001 * SR = MIN(MAX(MAX(S1 + S2, MIN_RESULT_SCALE), DR + 4), MAX_RESULT_SCALE)
1003 * By default, any result is computed with a minimum of 34 digits
1004 * after the decimal point or at least with 4 digits more than
1008 res_dscale = MAX(arg1.dscale + arg2.dscale, NUMERIC_MIN_DISPLAY_SCALE);
1009 res_dscale = MIN(res_dscale, NUMERIC_MAX_DISPLAY_SCALE);
1010 global_rscale = MAX(arg1.rscale + arg2.rscale,
1011 NUMERIC_MIN_RESULT_SCALE);
1012 global_rscale = MAX(global_rscale, res_dscale + 4);
1013 global_rscale = MIN(global_rscale, NUMERIC_MAX_RESULT_SCALE);
1016 * Do the divide, set the display scale and return the result
1018 div_var(&arg1, &arg2, &result);
1020 result.dscale = res_dscale;
1022 res = make_result(&result);
1028 PG_RETURN_NUMERIC(res);
1035 * Calculate the modulo of two numerics
1039 numeric_mod(PG_FUNCTION_ARGS)
1041 Numeric num1 = PG_GETARG_NUMERIC(0);
1042 Numeric num2 = PG_GETARG_NUMERIC(1);
1048 if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
1049 PG_RETURN_NUMERIC(make_result(&const_nan));
1055 set_var_from_num(num1, &arg1);
1056 set_var_from_num(num2, &arg2);
1058 mod_var(&arg1, &arg2, &result);
1060 res = make_result(&result);
1066 PG_RETURN_NUMERIC(res);
1073 * Increment a number by one
1077 numeric_inc(PG_FUNCTION_ARGS)
1079 Numeric num = PG_GETARG_NUMERIC(0);
1086 if (NUMERIC_IS_NAN(num))
1087 PG_RETURN_NUMERIC(make_result(&const_nan));
1090 * Compute the result and return it
1094 set_var_from_num(num, &arg);
1096 add_var(&arg, &const_one, &arg);
1097 res = make_result(&arg);
1101 PG_RETURN_NUMERIC(res);
1106 * numeric_smaller() -
1108 * Return the smaller of two numbers
1112 numeric_smaller(PG_FUNCTION_ARGS)
1114 Numeric num1 = PG_GETARG_NUMERIC(0);
1115 Numeric num2 = PG_GETARG_NUMERIC(1);
1123 if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
1124 PG_RETURN_NUMERIC(make_result(&const_nan));
1127 * Unpack the values, and decide which is the smaller one
1132 set_var_from_num(num1, &arg1);
1133 set_var_from_num(num2, &arg2);
1135 if (cmp_var(&arg1, &arg2) <= 0)
1136 res = make_result(&arg1);
1138 res = make_result(&arg2);
1143 PG_RETURN_NUMERIC(res);
1148 * numeric_larger() -
1150 * Return the larger of two numbers
1154 numeric_larger(PG_FUNCTION_ARGS)
1156 Numeric num1 = PG_GETARG_NUMERIC(0);
1157 Numeric num2 = PG_GETARG_NUMERIC(1);
1165 if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
1166 PG_RETURN_NUMERIC(make_result(&const_nan));
1169 * Unpack the values, and decide which is the larger one
1174 set_var_from_num(num1, &arg1);
1175 set_var_from_num(num2, &arg2);
1177 if (cmp_var(&arg1, &arg2) >= 0)
1178 res = make_result(&arg1);
1180 res = make_result(&arg2);
1185 PG_RETURN_NUMERIC(res);
1189 /* ----------------------------------------------------------------------
1191 * Complex math functions
1193 * ----------------------------------------------------------------------
1200 * Compute the square root of a numeric.
1204 numeric_sqrt(PG_FUNCTION_ARGS)
1206 Numeric num = PG_GETARG_NUMERIC(0);
1215 if (NUMERIC_IS_NAN(num))
1216 PG_RETURN_NUMERIC(make_result(&const_nan));
1219 * Unpack the argument, determine the scales like for divide, let
1220 * sqrt_var() do the calculation and return the result.
1225 set_var_from_num(num, &arg);
1227 res_dscale = MAX(arg.dscale, NUMERIC_MIN_DISPLAY_SCALE);
1228 res_dscale = MIN(res_dscale, NUMERIC_MAX_DISPLAY_SCALE);
1229 global_rscale = MAX(arg.rscale, NUMERIC_MIN_RESULT_SCALE);
1230 global_rscale = MAX(global_rscale, res_dscale + 4);
1231 global_rscale = MIN(global_rscale, NUMERIC_MAX_RESULT_SCALE);
1233 sqrt_var(&arg, &result);
1235 result.dscale = res_dscale;
1237 res = make_result(&result);
1242 PG_RETURN_NUMERIC(res);
1249 * Raise e to the power of x
1253 numeric_exp(PG_FUNCTION_ARGS)
1255 Numeric num = PG_GETARG_NUMERIC(0);
1264 if (NUMERIC_IS_NAN(num))
1265 PG_RETURN_NUMERIC(make_result(&const_nan));
1268 * Same procedure like for sqrt().
1272 set_var_from_num(num, &arg);
1274 res_dscale = MAX(arg.dscale, NUMERIC_MIN_DISPLAY_SCALE);
1275 res_dscale = MIN(res_dscale, NUMERIC_MAX_DISPLAY_SCALE);
1276 global_rscale = MAX(arg.rscale, NUMERIC_MIN_RESULT_SCALE);
1277 global_rscale = MAX(global_rscale, res_dscale + 4);
1278 global_rscale = MIN(global_rscale, NUMERIC_MAX_RESULT_SCALE);
1280 exp_var(&arg, &result);
1282 result.dscale = res_dscale;
1284 res = make_result(&result);
1289 PG_RETURN_NUMERIC(res);
1296 * Compute the natural logarithm of x
1300 numeric_ln(PG_FUNCTION_ARGS)
1302 Numeric num = PG_GETARG_NUMERIC(0);
1311 if (NUMERIC_IS_NAN(num))
1312 PG_RETURN_NUMERIC(make_result(&const_nan));
1315 * Same procedure like for sqrt()
1319 set_var_from_num(num, &arg);
1321 res_dscale = MAX(arg.dscale, NUMERIC_MIN_DISPLAY_SCALE);
1322 res_dscale = MIN(res_dscale, NUMERIC_MAX_DISPLAY_SCALE);
1323 global_rscale = MAX(arg.rscale, NUMERIC_MIN_RESULT_SCALE);
1324 global_rscale = MAX(global_rscale, res_dscale + 4);
1325 global_rscale = MIN(global_rscale, NUMERIC_MAX_RESULT_SCALE);
1327 ln_var(&arg, &result);
1329 result.dscale = res_dscale;
1331 res = make_result(&result);
1336 PG_RETURN_NUMERIC(res);
1343 * Compute the logarithm of x in a given base
1347 numeric_log(PG_FUNCTION_ARGS)
1349 Numeric num1 = PG_GETARG_NUMERIC(0);
1350 Numeric num2 = PG_GETARG_NUMERIC(1);
1360 if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
1361 PG_RETURN_NUMERIC(make_result(&const_nan));
1364 * Initialize things and calculate scales
1369 set_var_from_num(num1, &arg1);
1370 set_var_from_num(num2, &arg2);
1372 res_dscale = MAX(arg1.dscale + arg2.dscale, NUMERIC_MIN_DISPLAY_SCALE);
1373 res_dscale = MIN(res_dscale, NUMERIC_MAX_DISPLAY_SCALE);
1374 global_rscale = MAX(arg1.rscale + arg2.rscale, NUMERIC_MIN_RESULT_SCALE);
1375 global_rscale = MAX(global_rscale, res_dscale + 4);
1376 global_rscale = MIN(global_rscale, NUMERIC_MAX_RESULT_SCALE);
1379 * Call log_var() to compute and return the result
1381 log_var(&arg1, &arg2, &result);
1383 result.dscale = res_dscale;
1385 res = make_result(&result);
1391 PG_RETURN_NUMERIC(res);
1398 * Raise m to the power of x
1402 numeric_power(PG_FUNCTION_ARGS)
1404 Numeric num1 = PG_GETARG_NUMERIC(0);
1405 Numeric num2 = PG_GETARG_NUMERIC(1);
1415 if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
1416 PG_RETURN_NUMERIC(make_result(&const_nan));
1419 * Initialize things and calculate scales
1424 set_var_from_num(num1, &arg1);
1425 set_var_from_num(num2, &arg2);
1427 res_dscale = MAX(arg1.dscale + arg2.dscale, NUMERIC_MIN_DISPLAY_SCALE);
1428 res_dscale = MIN(res_dscale, NUMERIC_MAX_DISPLAY_SCALE);
1429 global_rscale = MAX(arg1.rscale + arg2.rscale, NUMERIC_MIN_RESULT_SCALE);
1430 global_rscale = MAX(global_rscale, res_dscale + 4);
1431 global_rscale = MIN(global_rscale, NUMERIC_MAX_RESULT_SCALE);
1434 * Call log_var() to compute and return the result
1436 power_var(&arg1, &arg2, &result);
1438 result.dscale = res_dscale;
1440 res = make_result(&result);
1446 PG_RETURN_NUMERIC(res);
1450 /* ----------------------------------------------------------------------
1452 * Type conversion functions
1454 * ----------------------------------------------------------------------
1459 int4_numeric(PG_FUNCTION_ARGS)
1461 int32 val = PG_GETARG_INT32(0);
1468 tmp = DatumGetCString(DirectFunctionCall1(int4out,
1469 Int32GetDatum(val)));
1470 set_var_from_str(tmp, &result);
1471 res = make_result(&result);
1476 PG_RETURN_NUMERIC(res);
1481 numeric_int4(PG_FUNCTION_ARGS)
1483 Numeric num = PG_GETARG_NUMERIC(0);
1488 /* XXX would it be better to return NULL? */
1489 if (NUMERIC_IS_NAN(num))
1490 elog(ERROR, "Cannot convert NaN to int4");
1493 * Get the number in the variable format so we can round to integer.
1496 set_var_from_num(num, &x);
1498 str = get_str_from_var(&x, 0); /* dscale = 0 produces rounding */
1502 result = DirectFunctionCall1(int4in, CStringGetDatum(str));
1505 PG_RETURN_DATUM(result);
1510 int8_numeric(PG_FUNCTION_ARGS)
1512 Datum val = PG_GETARG_DATUM(0);
1519 tmp = DatumGetCString(DirectFunctionCall1(int8out, val));
1520 set_var_from_str(tmp, &result);
1521 res = make_result(&result);
1526 PG_RETURN_NUMERIC(res);
1531 numeric_int8(PG_FUNCTION_ARGS)
1533 Numeric num = PG_GETARG_NUMERIC(0);
1538 /* XXX would it be better to return NULL? */
1539 if (NUMERIC_IS_NAN(num))
1540 elog(ERROR, "Cannot convert NaN to int8");
1543 * Get the number in the variable format so we can round to integer.
1546 set_var_from_num(num, &x);
1548 str = get_str_from_var(&x, 0); /* dscale = 0 produces rounding */
1552 result = DirectFunctionCall1(int8in, CStringGetDatum(str));
1555 PG_RETURN_DATUM(result);
1560 int2_numeric(PG_FUNCTION_ARGS)
1562 int16 val = PG_GETARG_INT16(0);
1569 tmp = DatumGetCString(DirectFunctionCall1(int2out,
1570 Int16GetDatum(val)));
1571 set_var_from_str(tmp, &result);
1572 res = make_result(&result);
1577 PG_RETURN_NUMERIC(res);
1582 numeric_int2(PG_FUNCTION_ARGS)
1584 Numeric num = PG_GETARG_NUMERIC(0);
1589 /* XXX would it be better to return NULL? */
1590 if (NUMERIC_IS_NAN(num))
1591 elog(ERROR, "Cannot convert NaN to int2");
1594 * Get the number in the variable format so we can round to integer.
1597 set_var_from_num(num, &x);
1599 str = get_str_from_var(&x, 0); /* dscale = 0 produces rounding */
1603 result = DirectFunctionCall1(int2in, CStringGetDatum(str));
1611 float8_numeric(PG_FUNCTION_ARGS)
1613 float8 val = PG_GETARG_FLOAT8(0);
1616 char buf[DBL_DIG + 100];
1619 PG_RETURN_NUMERIC(make_result(&const_nan));
1621 sprintf(buf, "%.*g", DBL_DIG, val);
1625 set_var_from_str(buf, &result);
1626 res = make_result(&result);
1630 PG_RETURN_NUMERIC(res);
1635 numeric_float8(PG_FUNCTION_ARGS)
1637 Numeric num = PG_GETARG_NUMERIC(0);
1641 if (NUMERIC_IS_NAN(num))
1642 PG_RETURN_FLOAT8(NAN);
1644 tmp = DatumGetCString(DirectFunctionCall1(numeric_out,
1645 NumericGetDatum(num)));
1647 result = DirectFunctionCall1(float8in, CStringGetDatum(tmp));
1651 PG_RETURN_DATUM(result);
1656 float4_numeric(PG_FUNCTION_ARGS)
1658 float4 val = PG_GETARG_FLOAT4(0);
1661 char buf[FLT_DIG + 100];
1664 PG_RETURN_NUMERIC(make_result(&const_nan));
1666 sprintf(buf, "%.*g", FLT_DIG, val);
1670 set_var_from_str(buf, &result);
1671 res = make_result(&result);
1675 PG_RETURN_NUMERIC(res);
1680 numeric_float4(PG_FUNCTION_ARGS)
1682 Numeric num = PG_GETARG_NUMERIC(0);
1686 if (NUMERIC_IS_NAN(num))
1687 PG_RETURN_FLOAT4((float4) NAN);
1689 tmp = DatumGetCString(DirectFunctionCall1(numeric_out,
1690 NumericGetDatum(num)));
1692 result = DirectFunctionCall1(float4in, CStringGetDatum(tmp));
1696 PG_RETURN_DATUM(result);
1700 /* ----------------------------------------------------------------------
1702 * Aggregate functions
1704 * The transition datatype for all these aggregates is a 3-element array
1705 * of Numeric, holding the values N, sum(X), sum(X*X) in that order.
1707 * We represent N as a numeric mainly to avoid having to build a special
1708 * datatype; it's unlikely it'd overflow an int4, but ...
1710 * ----------------------------------------------------------------------
1714 do_numeric_accum(ArrayType *transarray, Numeric newval)
1723 /* We assume the input is array of numeric */
1724 deconstruct_array(transarray,
1726 &transdatums, &ndatums);
1728 elog(ERROR, "do_numeric_accum: expected 3-element numeric array");
1730 sumX = transdatums[1];
1731 sumX2 = transdatums[2];
1733 N = DirectFunctionCall1(numeric_inc, N);
1734 sumX = DirectFunctionCall2(numeric_add, sumX,
1735 NumericGetDatum(newval));
1736 sumX2 = DirectFunctionCall2(numeric_add, sumX2,
1737 DirectFunctionCall2(numeric_mul,
1738 NumericGetDatum(newval),
1739 NumericGetDatum(newval)));
1742 transdatums[1] = sumX;
1743 transdatums[2] = sumX2;
1745 result = construct_array(transdatums, 3,
1752 numeric_accum(PG_FUNCTION_ARGS)
1754 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
1755 Numeric newval = PG_GETARG_NUMERIC(1);
1757 PG_RETURN_ARRAYTYPE_P(do_numeric_accum(transarray, newval));
1761 * Integer data types all use Numeric accumulators to share code and
1762 * avoid risk of overflow.
1766 int2_accum(PG_FUNCTION_ARGS)
1768 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
1769 Datum newval2 = PG_GETARG_DATUM(1);
1772 newval = DatumGetNumeric(DirectFunctionCall1(int2_numeric, newval2));
1774 PG_RETURN_ARRAYTYPE_P(do_numeric_accum(transarray, newval));
1778 int4_accum(PG_FUNCTION_ARGS)
1780 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
1781 Datum newval4 = PG_GETARG_DATUM(1);
1784 newval = DatumGetNumeric(DirectFunctionCall1(int4_numeric, newval4));
1786 PG_RETURN_ARRAYTYPE_P(do_numeric_accum(transarray, newval));
1790 int8_accum(PG_FUNCTION_ARGS)
1792 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
1793 Datum newval8 = PG_GETARG_DATUM(1);
1796 newval = DatumGetNumeric(DirectFunctionCall1(int8_numeric, newval8));
1798 PG_RETURN_ARRAYTYPE_P(do_numeric_accum(transarray, newval));
1802 numeric_avg(PG_FUNCTION_ARGS)
1804 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
1810 /* We assume the input is array of numeric */
1811 deconstruct_array(transarray,
1813 &transdatums, &ndatums);
1815 elog(ERROR, "numeric_avg: expected 3-element numeric array");
1816 N = DatumGetNumeric(transdatums[0]);
1817 sumX = DatumGetNumeric(transdatums[1]);
1820 /* SQL92 defines AVG of no values to be NULL */
1821 /* N is zero iff no digits (cf. numeric_uminus) */
1822 if (N->varlen == NUMERIC_HDRSZ)
1825 PG_RETURN_DATUM(DirectFunctionCall2(numeric_div,
1826 NumericGetDatum(sumX),
1827 NumericGetDatum(N)));
1831 numeric_variance(PG_FUNCTION_ARGS)
1833 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
1845 /* We assume the input is array of numeric */
1846 deconstruct_array(transarray,
1848 &transdatums, &ndatums);
1850 elog(ERROR, "numeric_variance: expected 3-element numeric array");
1851 N = DatumGetNumeric(transdatums[0]);
1852 sumX = DatumGetNumeric(transdatums[1]);
1853 sumX2 = DatumGetNumeric(transdatums[2]);
1855 if (NUMERIC_IS_NAN(N) || NUMERIC_IS_NAN(sumX) || NUMERIC_IS_NAN(sumX2))
1856 PG_RETURN_NUMERIC(make_result(&const_nan));
1858 /* We define VARIANCE of no values to be NULL, of 1 value to be 0 */
1859 /* N is zero iff no digits (cf. numeric_uminus) */
1860 if (N->varlen == NUMERIC_HDRSZ)
1864 set_var_from_num(N, &vN);
1866 init_var(&vNminus1);
1867 sub_var(&vN, &const_one, &vNminus1);
1869 if (cmp_var(&vNminus1, &const_zero) <= 0)
1872 free_var(&vNminus1);
1873 PG_RETURN_NUMERIC(make_result(&const_zero));
1877 set_var_from_num(sumX, &vsumX);
1879 set_var_from_num(sumX2, &vsumX2);
1881 mul_var(&vsumX, &vsumX, &vsumX); /* now vsumX contains sumX * sumX */
1882 mul_var(&vN, &vsumX2, &vsumX2); /* now vsumX2 contains N * sumX2 */
1883 sub_var(&vsumX2, &vsumX, &vsumX2); /* N * sumX2 - sumX * sumX */
1884 mul_var(&vN, &vNminus1, &vNminus1); /* N * (N - 1) */
1885 div_var(&vsumX2, &vNminus1, &vsumX); /* variance */
1887 res = make_result(&vsumX);
1890 free_var(&vNminus1);
1894 PG_RETURN_NUMERIC(res);
1898 numeric_stddev(PG_FUNCTION_ARGS)
1900 ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0);
1912 /* We assume the input is array of numeric */
1913 deconstruct_array(transarray,
1915 &transdatums, &ndatums);
1917 elog(ERROR, "numeric_stddev: expected 3-element numeric array");
1918 N = DatumGetNumeric(transdatums[0]);
1919 sumX = DatumGetNumeric(transdatums[1]);
1920 sumX2 = DatumGetNumeric(transdatums[2]);
1922 if (NUMERIC_IS_NAN(N) || NUMERIC_IS_NAN(sumX) || NUMERIC_IS_NAN(sumX2))
1923 PG_RETURN_NUMERIC(make_result(&const_nan));
1925 /* We define STDDEV of no values to be NULL, of 1 value to be 0 */
1926 /* N is zero iff no digits (cf. numeric_uminus) */
1927 if (N->varlen == NUMERIC_HDRSZ)
1931 set_var_from_num(N, &vN);
1933 init_var(&vNminus1);
1934 sub_var(&vN, &const_one, &vNminus1);
1936 if (cmp_var(&vNminus1, &const_zero) <= 0)
1939 free_var(&vNminus1);
1940 PG_RETURN_NUMERIC(make_result(&const_zero));
1944 set_var_from_num(sumX, &vsumX);
1946 set_var_from_num(sumX2, &vsumX2);
1948 mul_var(&vsumX, &vsumX, &vsumX); /* now vsumX contains sumX * sumX */
1949 mul_var(&vN, &vsumX2, &vsumX2); /* now vsumX2 contains N * sumX2 */
1950 sub_var(&vsumX2, &vsumX, &vsumX2); /* N * sumX2 - sumX * sumX */
1951 mul_var(&vN, &vNminus1, &vNminus1); /* N * (N - 1) */
1952 div_var(&vsumX2, &vNminus1, &vsumX); /* variance */
1953 sqrt_var(&vsumX, &vsumX); /* stddev */
1955 res = make_result(&vsumX);
1958 free_var(&vNminus1);
1962 PG_RETURN_NUMERIC(res);
1967 * SUM transition functions for integer datatypes.
1969 * We use a Numeric accumulator to avoid overflow. Because SQL92 defines
1970 * the SUM() of no values to be NULL, not zero, the initial condition of
1971 * the transition data value needs to be NULL. This means we can't rely
1972 * on ExecAgg to automatically insert the first non-null data value into
1973 * the transition data: it doesn't know how to do the type conversion.
1974 * The upshot is that these routines have to be marked non-strict and
1975 * handle substitution of the first non-null input themselves.
1979 int2_sum(PG_FUNCTION_ARGS)
1984 if (PG_ARGISNULL(0))
1986 /* No non-null input seen so far... */
1987 if (PG_ARGISNULL(1))
1988 PG_RETURN_NULL(); /* still no non-null */
1989 /* This is the first non-null input. */
1990 newval = DirectFunctionCall1(int2_numeric, PG_GETARG_DATUM(1));
1991 PG_RETURN_DATUM(newval);
1994 oldsum = PG_GETARG_NUMERIC(0);
1996 /* Leave sum unchanged if new input is null. */
1997 if (PG_ARGISNULL(1))
1998 PG_RETURN_NUMERIC(oldsum);
2000 /* OK to do the addition. */
2001 newval = DirectFunctionCall1(int2_numeric, PG_GETARG_DATUM(1));
2003 PG_RETURN_DATUM(DirectFunctionCall2(numeric_add,
2004 NumericGetDatum(oldsum), newval));
2008 int4_sum(PG_FUNCTION_ARGS)
2013 if (PG_ARGISNULL(0))
2015 /* No non-null input seen so far... */
2016 if (PG_ARGISNULL(1))
2017 PG_RETURN_NULL(); /* still no non-null */
2018 /* This is the first non-null input. */
2019 newval = DirectFunctionCall1(int4_numeric, PG_GETARG_DATUM(1));
2020 PG_RETURN_DATUM(newval);
2023 oldsum = PG_GETARG_NUMERIC(0);
2025 /* Leave sum unchanged if new input is null. */
2026 if (PG_ARGISNULL(1))
2027 PG_RETURN_NUMERIC(oldsum);
2029 /* OK to do the addition. */
2030 newval = DirectFunctionCall1(int4_numeric, PG_GETARG_DATUM(1));
2032 PG_RETURN_DATUM(DirectFunctionCall2(numeric_add,
2033 NumericGetDatum(oldsum), newval));
2037 int8_sum(PG_FUNCTION_ARGS)
2042 if (PG_ARGISNULL(0))
2044 /* No non-null input seen so far... */
2045 if (PG_ARGISNULL(1))
2046 PG_RETURN_NULL(); /* still no non-null */
2047 /* This is the first non-null input. */
2048 newval = DirectFunctionCall1(int8_numeric, PG_GETARG_DATUM(1));
2049 PG_RETURN_DATUM(newval);
2052 oldsum = PG_GETARG_NUMERIC(0);
2054 /* Leave sum unchanged if new input is null. */
2055 if (PG_ARGISNULL(1))
2056 PG_RETURN_NUMERIC(oldsum);
2058 /* OK to do the addition. */
2059 newval = DirectFunctionCall1(int8_numeric, PG_GETARG_DATUM(1));
2061 PG_RETURN_DATUM(DirectFunctionCall2(numeric_add,
2062 NumericGetDatum(oldsum), newval));
2066 /* ----------------------------------------------------------------------
2068 * Local functions follow
2070 * ----------------------------------------------------------------------
2074 #ifdef NUMERIC_DEBUG
2077 * dump_numeric() - Dump a value in the db storage format for debugging
2081 dump_numeric(char *str, Numeric num)
2085 printf("%s: NUMERIC w=%d r=%d d=%d ", str, num->n_weight, num->n_rscale,
2086 NUMERIC_DSCALE(num));
2087 switch (NUMERIC_SIGN(num))
2099 printf("SIGN=0x%x", NUMERIC_SIGN(num));
2103 for (i = 0; i < num->varlen - NUMERIC_HDRSZ; i++)
2104 printf(" %d %d", (num->n_data[i] >> 4) & 0x0f, num->n_data[i] & 0x0f);
2110 * dump_var() - Dump a value in the variable format for debugging
2114 dump_var(char *str, NumericVar *var)
2118 printf("%s: VAR w=%d r=%d d=%d ", str, var->weight, var->rscale,
2132 printf("SIGN=0x%x", var->sign);
2136 for (i = 0; i < var->ndigits; i++)
2137 printf(" %d", var->digits[i]);
2142 #endif /* NUMERIC_DEBUG */
2148 * Allocate a digit buffer of ndigits digits (plus a spare digit for rounding)
2152 alloc_var(NumericVar *var, int ndigits)
2154 digitbuf_free(var->buf);
2155 var->buf = digitbuf_alloc(ndigits + 1);
2157 var->digits = var->buf + 1;
2158 var->ndigits = ndigits;
2165 * Return the digit buffer of a variable to the free pool
2169 free_var(NumericVar *var)
2171 digitbuf_free(var->buf);
2174 var->sign = NUMERIC_NAN;
2181 * Set a variable to ZERO.
2182 * Note: rscale and dscale are not touched.
2186 zero_var(NumericVar *var)
2188 digitbuf_free(var->buf);
2192 var->weight = 0; /* by convention; doesn't really matter */
2193 var->sign = NUMERIC_POS; /* anything but NAN... */
2198 * set_var_from_str()
2200 * Parse a string and put the number into a variable
2204 set_var_from_str(char *str, NumericVar *dest)
2207 bool have_dp = FALSE;
2212 if (!isspace((unsigned char) *cp))
2217 alloc_var(dest, strlen(cp));
2220 dest->sign = NUMERIC_POS;
2225 dest->sign = NUMERIC_POS;
2230 dest->sign = NUMERIC_NEG;
2241 if (!isdigit((unsigned char) *cp))
2242 elog(ERROR, "Bad numeric input format '%s'", str);
2246 if (isdigit((unsigned char) *cp))
2248 dest->digits[i++] = *cp++ - '0';
2254 else if (*cp == '.')
2257 elog(ERROR, "Bad numeric input format '%s'", str);
2266 /* Handle exponent, if any */
2267 if (*cp == 'e' || *cp == 'E')
2273 exponent = strtol(cp, &endptr, 10);
2275 elog(ERROR, "Bad numeric input format '%s'", str);
2277 if (exponent > NUMERIC_MAX_PRECISION ||
2278 exponent < -NUMERIC_MAX_PRECISION)
2279 elog(ERROR, "Bad numeric input format '%s'", str);
2280 dest->weight += (int) exponent;
2281 dest->dscale -= (int) exponent;
2282 if (dest->dscale < 0)
2286 /* Should be nothing left but spaces */
2289 if (!isspace((unsigned char) *cp))
2290 elog(ERROR, "Bad numeric input format '%s'", str);
2294 /* Strip any leading zeroes */
2295 while (dest->ndigits > 0 && *(dest->digits) == 0)
2301 if (dest->ndigits == 0)
2304 dest->rscale = dest->dscale;
2309 * set_var_from_num() -
2311 * Parse back the packed db format into a variable
2315 set_var_from_num(Numeric num, NumericVar *dest)
2317 NumericDigit *digit;
2321 n = num->varlen - NUMERIC_HDRSZ; /* number of digit-pairs in packed
2324 alloc_var(dest, n * 2);
2326 dest->weight = num->n_weight;
2327 dest->rscale = num->n_rscale;
2328 dest->dscale = NUMERIC_DSCALE(num);
2329 dest->sign = NUMERIC_SIGN(num);
2331 digit = dest->digits;
2333 for (i = 0; i < n; i++)
2335 unsigned char digitpair = num->n_data[i];
2337 *digit++ = (digitpair >> 4) & 0x0f;
2338 *digit++ = digitpair & 0x0f;
2344 * set_var_from_var() -
2346 * Copy one variable into another
2350 set_var_from_var(NumericVar *value, NumericVar *dest)
2352 NumericDigit *newbuf;
2354 newbuf = digitbuf_alloc(value->ndigits + 1);
2355 newbuf[0] = 0; /* spare digit for rounding */
2356 memcpy(newbuf + 1, value->digits, value->ndigits);
2358 digitbuf_free(dest->buf);
2360 memcpy(dest, value, sizeof(NumericVar));
2362 dest->digits = newbuf + 1;
2367 * get_str_from_var() -
2369 * Convert a var to text representation (guts of numeric_out).
2370 * CAUTION: var's contents may be modified by rounding!
2371 * Caller must have checked for NaN case.
2372 * Returns a palloc'd string.
2376 get_str_from_var(NumericVar *var, int dscale)
2384 * Check if we must round up before printing the value and do so.
2386 i = dscale + var->weight + 1;
2387 if (i >= 0 && var->ndigits > i)
2389 int carry = (var->digits[i] > 4) ? 1 : 0;
2395 carry += var->digits[--i];
2396 var->digits[i] = carry % 10;
2402 Assert(i == -1); /* better not have added more than 1 digit */
2403 Assert(var->digits > var->buf);
2410 var->ndigits = MAX(0, MIN(i, var->ndigits));
2413 * Allocate space for the result
2415 str = palloc(MAX(0, dscale) + MAX(0, var->weight) + 4);
2419 * Output a dash for negative values
2421 if (var->sign == NUMERIC_NEG)
2425 * Output all digits before the decimal point
2427 i = MAX(var->weight, 0);
2432 if (i <= var->weight && d < var->ndigits)
2433 *cp++ = var->digits[d++] + '0';
2440 * If requested, output a decimal point and all the digits that follow
2446 while (i >= -dscale)
2448 if (i <= var->weight && d < var->ndigits)
2449 *cp++ = var->digits[d++] + '0';
2457 * terminate the string and return it
2467 * Create the packed db numeric format in palloc()'d memory from
2468 * a variable. The var's rscale determines the number of digits kept.
2472 make_result(NumericVar *var)
2475 NumericDigit *digit = var->digits;
2476 int weight = var->weight;
2477 int sign = var->sign;
2482 if (sign == NUMERIC_NAN)
2484 result = (Numeric) palloc(NUMERIC_HDRSZ);
2486 result->varlen = NUMERIC_HDRSZ;
2487 result->n_weight = 0;
2488 result->n_rscale = 0;
2489 result->n_sign_dscale = NUMERIC_NAN;
2491 dump_numeric("make_result()", result);
2495 n = MAX(0, MIN(var->ndigits, var->weight + var->rscale + 1));
2497 /* truncate leading zeroes */
2498 while (n > 0 && *digit == 0)
2504 /* truncate trailing zeroes */
2505 while (n > 0 && digit[n - 1] == 0)
2508 /* If zero result, force to weight=0 and positive sign */
2515 result = (Numeric) palloc(NUMERIC_HDRSZ + (n + 1) / 2);
2516 result->varlen = NUMERIC_HDRSZ + (n + 1) / 2;
2517 result->n_weight = weight;
2518 result->n_rscale = var->rscale;
2519 result->n_sign_dscale = sign |
2520 ((uint16) var->dscale & NUMERIC_DSCALE_MASK);
2526 unsigned char digitpair = digit[j++] << 4;
2529 digitpair |= digit[j++];
2530 result->n_data[i++] = digitpair;
2533 dump_numeric("make_result()", result);
2541 * Do bounds checking and rounding according to the attributes
2546 apply_typmod(NumericVar *var, int32 typmod)
2553 /* Do nothing if we have a default typmod (-1) */
2554 if (typmod < (int32) (VARHDRSZ))
2558 precision = (typmod >> 16) & 0xffff;
2559 scale = typmod & 0xffff;
2560 maxweight = precision - scale;
2562 /* Round to target scale */
2563 i = scale + var->weight + 1;
2564 if (i >= 0 && var->ndigits > i)
2566 int carry = (var->digits[i] > 4) ? 1 : 0;
2572 carry += var->digits[--i];
2573 var->digits[i] = carry % 10;
2579 Assert(i == -1); /* better not have added more than 1 digit */
2580 Assert(var->digits > var->buf);
2587 var->ndigits = MAX(0, MIN(i, var->ndigits));
2590 * Check for overflow - note we can't do this before rounding, because
2591 * rounding could raise the weight. Also note that the var's weight
2592 * could be inflated by leading zeroes, which will be stripped before
2593 * storage but perhaps might not have been yet. In any case, we must
2594 * recognize a true zero, whose weight doesn't mean anything.
2596 if (var->weight >= maxweight)
2598 /* Determine true weight; and check for all-zero result */
2599 int tweight = var->weight;
2601 for (i = 0; i < var->ndigits; i++)
2608 if (tweight >= maxweight && i < var->ndigits)
2609 elog(ERROR, "overflow on numeric "
2610 "ABS(value) >= 10^%d for field with precision %d scale %d",
2611 tweight, precision, scale);
2614 var->rscale = scale;
2615 var->dscale = scale;
2622 * Compare two values on variable level
2626 cmp_var(NumericVar *var1, NumericVar *var2)
2628 if (var1->ndigits == 0)
2630 if (var2->ndigits == 0)
2632 if (var2->sign == NUMERIC_NEG)
2636 if (var2->ndigits == 0)
2638 if (var1->sign == NUMERIC_POS)
2643 if (var1->sign == NUMERIC_POS)
2645 if (var2->sign == NUMERIC_NEG)
2647 return cmp_abs(var1, var2);
2650 if (var2->sign == NUMERIC_POS)
2653 return cmp_abs(var2, var1);
2660 * Full version of add functionality on variable level (handling signs).
2661 * result might point to one of the operands too without danger.
2665 add_var(NumericVar *var1, NumericVar *var2, NumericVar *result)
2669 * Decide on the signs of the two variables what to do
2671 if (var1->sign == NUMERIC_POS)
2673 if (var2->sign == NUMERIC_POS)
2677 * Both are positive result = +(ABS(var1) + ABS(var2))
2679 add_abs(var1, var2, result);
2680 result->sign = NUMERIC_POS;
2686 * var1 is positive, var2 is negative Must compare absolute
2689 switch (cmp_abs(var1, var2))
2693 * ABS(var1) == ABS(var2)
2698 result->rscale = MAX(var1->rscale, var2->rscale);
2699 result->dscale = MAX(var1->dscale, var2->dscale);
2704 * ABS(var1) > ABS(var2)
2705 * result = +(ABS(var1) - ABS(var2))
2708 sub_abs(var1, var2, result);
2709 result->sign = NUMERIC_POS;
2714 * ABS(var1) < ABS(var2)
2715 * result = -(ABS(var2) - ABS(var1))
2718 sub_abs(var2, var1, result);
2719 result->sign = NUMERIC_NEG;
2726 if (var2->sign == NUMERIC_POS)
2729 * var1 is negative, var2 is positive
2730 * Must compare absolute values
2733 switch (cmp_abs(var1, var2))
2737 * ABS(var1) == ABS(var2)
2742 result->rscale = MAX(var1->rscale, var2->rscale);
2743 result->dscale = MAX(var1->dscale, var2->dscale);
2748 * ABS(var1) > ABS(var2)
2749 * result = -(ABS(var1) - ABS(var2))
2752 sub_abs(var1, var2, result);
2753 result->sign = NUMERIC_NEG;
2758 * ABS(var1) < ABS(var2)
2759 * result = +(ABS(var2) - ABS(var1))
2762 sub_abs(var2, var1, result);
2763 result->sign = NUMERIC_POS;
2771 * result = -(ABS(var1) + ABS(var2))
2774 add_abs(var1, var2, result);
2775 result->sign = NUMERIC_NEG;
2784 * Full version of sub functionality on variable level (handling signs).
2785 * result might point to one of the operands too without danger.
2789 sub_var(NumericVar *var1, NumericVar *var2, NumericVar *result)
2793 * Decide on the signs of the two variables what to do
2795 if (var1->sign == NUMERIC_POS)
2797 if (var2->sign == NUMERIC_NEG)
2800 * var1 is positive, var2 is negative
2801 * result = +(ABS(var1) + ABS(var2))
2804 add_abs(var1, var2, result);
2805 result->sign = NUMERIC_POS;
2811 * Must compare absolute values
2814 switch (cmp_abs(var1, var2))
2818 * ABS(var1) == ABS(var2)
2823 result->rscale = MAX(var1->rscale, var2->rscale);
2824 result->dscale = MAX(var1->dscale, var2->dscale);
2829 * ABS(var1) > ABS(var2)
2830 * result = +(ABS(var1) - ABS(var2))
2833 sub_abs(var1, var2, result);
2834 result->sign = NUMERIC_POS;
2839 * ABS(var1) < ABS(var2)
2840 * result = -(ABS(var2) - ABS(var1))
2843 sub_abs(var2, var1, result);
2844 result->sign = NUMERIC_NEG;
2851 if (var2->sign == NUMERIC_NEG)
2855 * Must compare absolute values
2858 switch (cmp_abs(var1, var2))
2862 * ABS(var1) == ABS(var2)
2867 result->rscale = MAX(var1->rscale, var2->rscale);
2868 result->dscale = MAX(var1->dscale, var2->dscale);
2873 * ABS(var1) > ABS(var2)
2874 * result = -(ABS(var1) - ABS(var2))
2877 sub_abs(var1, var2, result);
2878 result->sign = NUMERIC_NEG;
2883 * ABS(var1) < ABS(var2)
2884 * result = +(ABS(var2) - ABS(var1))
2887 sub_abs(var2, var1, result);
2888 result->sign = NUMERIC_POS;
2895 * var1 is negative, var2 is positive
2896 * result = -(ABS(var1) + ABS(var2))
2899 add_abs(var1, var2, result);
2900 result->sign = NUMERIC_NEG;
2909 * Multiplication on variable level. Product of var1 * var2 is stored
2914 mul_var(NumericVar *var1, NumericVar *var2, NumericVar *result)
2916 NumericDigit *res_buf;
2917 NumericDigit *res_digits;
2927 res_weight = var1->weight + var2->weight + 2;
2928 res_ndigits = var1->ndigits + var2->ndigits + 1;
2929 if (var1->sign == var2->sign)
2930 res_sign = NUMERIC_POS;
2932 res_sign = NUMERIC_NEG;
2934 res_buf = digitbuf_alloc(res_ndigits);
2935 res_digits = res_buf;
2936 memset(res_digits, 0, res_ndigits);
2939 for (i1 = var1->ndigits - 1; i1 >= 0; i1--)
2944 for (i2 = var2->ndigits - 1; i2 >= 0; i2--)
2946 sum += res_digits[i] + var1->digits[i1] * var2->digits[i2];
2947 res_digits[i--] = sum % 10;
2950 res_digits[i] = sum;
2953 i = res_weight + global_rscale + 2;
2954 if (i >= 0 && i < res_ndigits)
2956 sum = (res_digits[i] > 4) ? 1 : 0;
2961 sum += res_digits[i];
2962 res_digits[i--] = sum % 10;
2967 while (res_ndigits > 0 && *res_digits == 0)
2973 while (res_ndigits > 0 && res_digits[res_ndigits - 1] == 0)
2976 if (res_ndigits == 0)
2978 res_sign = NUMERIC_POS;
2982 digitbuf_free(result->buf);
2983 result->buf = res_buf;
2984 result->digits = res_digits;
2985 result->ndigits = res_ndigits;
2986 result->weight = res_weight;
2987 result->rscale = global_rscale;
2988 result->sign = res_sign;
2995 * Division on variable level.
2999 div_var(NumericVar *var1, NumericVar *var2, NumericVar *result)
3001 NumericDigit *res_digits;
3005 NumericVar dividend;
3006 NumericVar divisor[10];
3015 int first_nextdigit;
3019 * First of all division by zero check
3021 ndigits_tmp = var2->ndigits + 1;
3022 if (ndigits_tmp == 1)
3023 elog(ERROR, "division by zero on numeric");
3026 * Determine the result sign, weight and number of digits to calculate
3028 if (var1->sign == var2->sign)
3029 res_sign = NUMERIC_POS;
3031 res_sign = NUMERIC_NEG;
3032 res_weight = var1->weight - var2->weight + 1;
3033 res_ndigits = global_rscale + res_weight;
3034 if (res_ndigits <= 0)
3038 * Now result zero check
3040 if (var1->ndigits == 0)
3043 result->rscale = global_rscale;
3048 * Initialize local variables
3050 init_var(÷nd);
3051 for (i = 1; i < 10; i++)
3052 init_var(&divisor[i]);
3055 * Make a copy of the divisor which has one leading zero digit
3057 divisor[1].ndigits = ndigits_tmp;
3058 divisor[1].rscale = var2->ndigits;
3059 divisor[1].sign = NUMERIC_POS;
3060 divisor[1].buf = digitbuf_alloc(ndigits_tmp);
3061 divisor[1].digits = divisor[1].buf;
3062 divisor[1].digits[0] = 0;
3063 memcpy(&(divisor[1].digits[1]), var2->digits, ndigits_tmp - 1);
3066 * Make a copy of the dividend
3068 dividend.ndigits = var1->ndigits;
3069 dividend.weight = 0;
3070 dividend.rscale = var1->ndigits;
3071 dividend.sign = NUMERIC_POS;
3072 dividend.buf = digitbuf_alloc(var1->ndigits);
3073 dividend.digits = dividend.buf;
3074 memcpy(dividend.digits, var1->digits, var1->ndigits);
3079 digitbuf_free(result->buf);
3080 result->buf = digitbuf_alloc(res_ndigits + 2);
3081 res_digits = result->buf;
3082 result->digits = res_digits;
3083 result->ndigits = res_ndigits;
3084 result->weight = res_weight;
3085 result->rscale = global_rscale;
3086 result->sign = res_sign;
3089 first_div = divisor[1].digits[1] * 10;
3090 if (ndigits_tmp > 2)
3091 first_div += divisor[1].digits[2];
3094 first_nextdigit = 0;
3097 rscale_tmp = divisor[1].rscale;
3099 for (ri = 0; ri <= res_ndigits; ri++)
3101 first_have = first_have * 10;
3102 if (first_nextdigit >= 0 && first_nextdigit < dividend.ndigits)
3103 first_have += dividend.digits[first_nextdigit];
3106 guess = (first_have * 10) / first_div + 1;
3112 if (divisor[guess].buf == NULL)
3117 memcpy(&divisor[guess], &divisor[1], sizeof(NumericVar));
3118 divisor[guess].buf = digitbuf_alloc(divisor[guess].ndigits);
3119 divisor[guess].digits = divisor[guess].buf;
3120 for (i = divisor[1].ndigits - 1; i >= 0; i--)
3122 sum += divisor[1].digits[i] * guess;
3123 divisor[guess].digits[i] = sum % 10;
3128 divisor[guess].weight = weight_tmp;
3129 divisor[guess].rscale = rscale_tmp;
3131 stat = cmp_abs(÷nd, &divisor[guess]);
3138 res_digits[ri + 1] = guess;
3151 sub_abs(÷nd, &divisor[guess], ÷nd);
3153 first_nextdigit = dividend.weight - weight_tmp;
3155 if (first_nextdigit >= 0 && first_nextdigit < dividend.ndigits)
3156 first_have = dividend.digits[first_nextdigit];
3160 result->ndigits = ri + 1;
3161 if (ri == res_ndigits + 1)
3163 int carry = (res_digits[ri] > 4) ? 1 : 0;
3165 result->ndigits = ri;
3168 while (carry && ri > 0)
3170 carry += res_digits[--ri];
3171 res_digits[ri] = carry % 10;
3176 while (result->ndigits > 0 && *(result->digits) == 0)
3180 (result->ndigits)--;
3182 while (result->ndigits > 0 && result->digits[result->ndigits - 1] == 0)
3183 (result->ndigits)--;
3184 if (result->ndigits == 0)
3185 result->sign = NUMERIC_POS;
3190 digitbuf_free(dividend.buf);
3191 for (i = 1; i < 10; i++)
3192 digitbuf_free(divisor[i].buf);
3199 * Calculate the modulo of two numerics at variable level
3203 mod_var(NumericVar *var1, NumericVar *var2, NumericVar *result)
3206 int save_global_rscale;
3212 * We do this using the equation
3213 * mod(x,y) = x - trunc(x/y)*y
3214 * We set global_rscale the same way numeric_div and numeric_mul do
3215 * to get the right answer from the equation. The final result,
3216 * however, need not be displayed to more precision than the inputs.
3219 save_global_rscale = global_rscale;
3221 div_dscale = MAX(var1->dscale + var2->dscale, NUMERIC_MIN_DISPLAY_SCALE);
3222 div_dscale = MIN(div_dscale, NUMERIC_MAX_DISPLAY_SCALE);
3223 global_rscale = MAX(var1->rscale + var2->rscale,
3224 NUMERIC_MIN_RESULT_SCALE);
3225 global_rscale = MAX(global_rscale, div_dscale + 4);
3226 global_rscale = MIN(global_rscale, NUMERIC_MAX_RESULT_SCALE);
3228 div_var(var1, var2, &tmp);
3230 tmp.dscale = div_dscale;
3232 /* do trunc() by forgetting digits to the right of the decimal point */
3233 tmp.ndigits = MAX(0, MIN(tmp.ndigits, tmp.weight + 1));
3235 global_rscale = var2->rscale + tmp.rscale;
3237 mul_var(var2, &tmp, &tmp);
3239 sub_var(var1, &tmp, result);
3241 result->dscale = MAX(var1->dscale, var2->dscale);
3243 global_rscale = save_global_rscale;
3251 * Return the smallest integer greater than or equal to the argument
3256 ceil_var(NumericVar *var, NumericVar *result)
3261 set_var_from_var(var, &tmp);
3264 tmp.ndigits = MIN(tmp.ndigits, MAX(0, tmp.weight + 1));
3265 if (tmp.sign == NUMERIC_POS && cmp_var(var, &tmp) != 0)
3266 add_var(&tmp, &const_one, &tmp);
3268 set_var_from_var(&tmp, result);
3276 * Return the largest integer equal to or less than the argument
3281 floor_var(NumericVar *var, NumericVar *result)
3286 set_var_from_var(var, &tmp);
3289 tmp.ndigits = MIN(tmp.ndigits, MAX(0, tmp.weight + 1));
3290 if (tmp.sign == NUMERIC_NEG && cmp_var(var, &tmp) != 0)
3291 sub_var(&tmp, &const_one, &tmp);
3293 set_var_from_var(&tmp, result);
3301 * Compute the square root of x using Newtons algorithm
3305 sqrt_var(NumericVar *arg, NumericVar *result)
3309 NumericVar last_val;
3311 int save_global_rscale;
3314 save_global_rscale = global_rscale;
3316 res_rscale = global_rscale;
3318 stat = cmp_var(arg, &const_zero);
3321 set_var_from_var(&const_zero, result);
3322 result->rscale = res_rscale;
3323 result->sign = NUMERIC_POS;
3328 elog(ERROR, "math error on numeric - cannot compute SQRT of negative value");
3332 init_var(&last_val);
3334 set_var_from_var(arg, &tmp_arg);
3335 set_var_from_var(result, &last_val);
3338 * Initialize the result to the first guess
3340 digitbuf_free(result->buf);
3341 result->buf = digitbuf_alloc(1);
3342 result->digits = result->buf;
3343 result->digits[0] = tmp_arg.digits[0] / 2;
3344 if (result->digits[0] == 0)
3345 result->digits[0] = 1;
3346 result->ndigits = 1;
3347 result->weight = tmp_arg.weight / 2;
3348 result->rscale = res_rscale;
3349 result->sign = NUMERIC_POS;
3353 div_var(&tmp_arg, result, &tmp_val);
3355 add_var(result, &tmp_val, result);
3356 div_var(result, &const_two, result);
3358 if (cmp_var(&last_val, result) == 0)
3360 set_var_from_var(result, &last_val);
3363 free_var(&last_val);
3367 global_rscale = save_global_rscale;
3368 div_var(result, &const_one, result);
3375 * Raise e to the power of x
3379 exp_var(NumericVar *arg, NumericVar *result)
3390 int save_global_rscale;
3398 set_var_from_var(arg, &x);
3400 if (x.sign == NUMERIC_NEG)
3403 x.sign = NUMERIC_POS;
3406 save_global_rscale = global_rscale;
3408 for (i = x.weight, d = 0; i >= 0; i--, d++)
3410 global_rscale *= 10;
3412 global_rscale += x.digits[d];
3413 if (global_rscale >= 1000)
3414 elog(ERROR, "argument for EXP() too big");
3417 global_rscale = global_rscale / 2 + save_global_rscale + 8;
3419 while (cmp_var(&x, &const_one) > 0)
3423 div_var(&x, &const_two, &x);
3426 add_var(&const_one, &x, result);
3427 set_var_from_var(&x, &xpow);
3428 set_var_from_var(&const_one, &ifac);
3429 set_var_from_var(&const_one, &ni);
3433 add_var(&ni, &const_one, &ni);
3434 mul_var(&xpow, &x, &xpow);
3435 mul_var(&ifac, &ni, &ifac);
3436 div_var(&xpow, &ifac, &elem);
3438 if (elem.ndigits == 0)
3441 add_var(result, &elem, result);
3445 mul_var(result, result, result);
3447 global_rscale = save_global_rscale;
3449 div_var(&const_one, result, result);
3451 div_var(result, &const_one, result);
3453 result->sign = NUMERIC_POS;
3466 * Compute the natural log of x
3470 ln_var(NumericVar *arg, NumericVar *result)
3478 int save_global_rscale;
3480 if (cmp_var(arg, &const_zero) <= 0)
3481 elog(ERROR, "math error on numeric - cannot compute LN of value <= zero");
3483 save_global_rscale = global_rscale;
3492 set_var_from_var(&const_two, &fact);
3493 set_var_from_var(arg, &x);
3495 while (cmp_var(&x, &const_two) >= 0)
3498 mul_var(&fact, &const_two, &fact);
3500 set_var_from_str("0.5", &elem);
3501 while (cmp_var(&x, &elem) <= 0)
3504 mul_var(&fact, &const_two, &fact);
3507 sub_var(&x, &const_one, result);
3508 add_var(&x, &const_one, &elem);
3509 div_var(result, &elem, result);
3510 set_var_from_var(result, &xx);
3511 mul_var(result, result, &x);
3513 set_var_from_var(&const_one, &ni);
3517 add_var(&ni, &const_two, &ni);
3518 mul_var(&xx, &x, &xx);
3519 div_var(&xx, &ni, &elem);
3521 if (cmp_var(&elem, &const_zero) == 0)
3524 add_var(result, &elem, result);
3527 global_rscale = save_global_rscale;
3528 mul_var(result, &fact, result);
3541 * Compute the logarithm of x in a given base
3545 log_var(NumericVar *base, NumericVar *num, NumericVar *result)
3555 ln_var(base, &ln_base);
3556 ln_var(num, &ln_num);
3560 div_var(&ln_num, &ln_base, result);
3570 * Raise base to the power of exp
3574 power_var(NumericVar *base, NumericVar *exp, NumericVar *result)
3578 int save_global_rscale;
3580 save_global_rscale = global_rscale;
3581 global_rscale += global_rscale / 3 + 8;
3586 ln_var(base, &ln_base);
3587 mul_var(&ln_base, exp, &ln_num);
3589 global_rscale = save_global_rscale;
3591 exp_var(&ln_num, result);
3599 /* ----------------------------------------------------------------------
3601 * Following are the lowest level functions that operate unsigned
3602 * on the variable level
3604 * ----------------------------------------------------------------------
3611 * Compare the absolute values of var1 and var2
3612 * Returns: -1 for ABS(var1) < ABS(var2)
3613 * 0 for ABS(var1) == ABS(var2)
3614 * 1 for ABS(var1) > ABS(var2)
3618 cmp_abs(NumericVar *var1, NumericVar *var2)
3622 int w1 = var1->weight;
3623 int w2 = var2->weight;
3626 while (w1 > w2 && i1 < var1->ndigits)
3628 if (var1->digits[i1++] != 0)
3632 while (w2 > w1 && i2 < var2->ndigits)
3634 if (var2->digits[i2++] != 0)
3641 while (i1 < var1->ndigits && i2 < var2->ndigits)
3643 stat = var1->digits[i1++] - var2->digits[i2++];
3653 while (i1 < var1->ndigits)
3655 if (var1->digits[i1++] != 0)
3658 while (i2 < var2->ndigits)
3660 if (var2->digits[i2++] != 0)
3671 * Add the absolute values of two variables into result.
3672 * result might point to one of the operands without danger.
3676 add_abs(NumericVar *var1, NumericVar *var2, NumericVar *result)
3678 NumericDigit *res_buf;
3679 NumericDigit *res_digits;
3689 /* copy these values into local vars for speed in inner loop */
3690 int var1ndigits = var1->ndigits;
3691 int var2ndigits = var2->ndigits;
3692 NumericDigit *var1digits = var1->digits;
3693 NumericDigit *var2digits = var2->digits;
3695 res_weight = MAX(var1->weight, var2->weight) + 1;
3696 res_rscale = MAX(var1->rscale, var2->rscale);
3697 res_dscale = MAX(var1->dscale, var2->dscale);
3698 res_ndigits = res_rscale + res_weight + 1;
3699 if (res_ndigits <= 0)
3702 res_buf = digitbuf_alloc(res_ndigits);
3703 res_digits = res_buf;
3705 i1 = res_rscale + var1->weight + 1;
3706 i2 = res_rscale + var2->weight + 1;
3707 for (i = res_ndigits - 1; i >= 0; i--)
3711 if (i1 >= 0 && i1 < var1ndigits)
3712 carry += var1digits[i1];
3713 if (i2 >= 0 && i2 < var2ndigits)
3714 carry += var2digits[i2];
3718 res_digits[i] = carry - 10;
3723 res_digits[i] = carry;
3728 Assert(carry == 0); /* else we failed to allow for carry out */
3730 while (res_ndigits > 0 && *res_digits == 0)
3736 while (res_ndigits > 0 && res_digits[res_ndigits - 1] == 0)
3739 if (res_ndigits == 0)
3742 digitbuf_free(result->buf);
3743 result->ndigits = res_ndigits;
3744 result->buf = res_buf;
3745 result->digits = res_digits;
3746 result->weight = res_weight;
3747 result->rscale = res_rscale;
3748 result->dscale = res_dscale;
3755 * Subtract the absolute value of var2 from the absolute value of var1
3756 * and store in result. result might point to one of the operands
3759 * ABS(var1) MUST BE GREATER OR EQUAL ABS(var2) !!!
3763 sub_abs(NumericVar *var1, NumericVar *var2, NumericVar *result)
3765 NumericDigit *res_buf;
3766 NumericDigit *res_digits;
3776 /* copy these values into local vars for speed in inner loop */
3777 int var1ndigits = var1->ndigits;
3778 int var2ndigits = var2->ndigits;
3779 NumericDigit *var1digits = var1->digits;
3780 NumericDigit *var2digits = var2->digits;
3782 res_weight = var1->weight;
3783 res_rscale = MAX(var1->rscale, var2->rscale);
3784 res_dscale = MAX(var1->dscale, var2->dscale);
3785 res_ndigits = res_rscale + res_weight + 1;
3786 if (res_ndigits <= 0)
3789 res_buf = digitbuf_alloc(res_ndigits);
3790 res_digits = res_buf;
3792 i1 = res_rscale + var1->weight + 1;
3793 i2 = res_rscale + var2->weight + 1;
3794 for (i = res_ndigits - 1; i >= 0; i--)
3798 if (i1 >= 0 && i1 < var1ndigits)
3799 borrow += var1digits[i1];
3800 if (i2 >= 0 && i2 < var2ndigits)
3801 borrow -= var2digits[i2];
3805 res_digits[i] = borrow + 10;
3810 res_digits[i] = borrow;
3815 Assert(borrow == 0); /* else caller gave us var1 < var2 */
3817 while (res_ndigits > 0 && *res_digits == 0)
3823 while (res_ndigits > 0 && res_digits[res_ndigits - 1] == 0)
3826 if (res_ndigits == 0)
3829 digitbuf_free(result->buf);
3830 result->ndigits = res_ndigits;
3831 result->buf = res_buf;
3832 result->digits = res_digits;
3833 result->weight = res_weight;
3834 result->rscale = res_rscale;
3835 result->dscale = res_dscale;