4 * An exact numeric data type for the Postgres database system
8 * $Header: /cvsroot/pgsql/src/backend/utils/adt/numeric.c,v 1.30 2000/06/14 18:17:44 petere Exp $
19 #include <sys/types.h>
21 #include "utils/builtins.h"
22 #include "utils/numeric.h"
25 * Uncomment the following to enable compilation of dump_numeric()
26 * and dump_var() and to get a dump of any result produced by make_result().
37 #define MIN(a,b) (((a)<(b)) ? (a) : (b))
40 #define MAX(a,b) (((a)>(b)) ? (a) : (b))
51 * Note: the first digit of a NumericVar's value is assumed to be multiplied
52 * by 10 ** weight. Another way to say it is that there are weight+1 digits
53 * before the decimal point. It is possible to have weight < 0.
55 * The value represented by a NumericVar is determined by the sign, weight,
56 * ndigits, and digits[] array. The rscale and dscale are carried along,
57 * but they are just auxiliary information until rounding is done before
58 * final storage or display. (Scales are the number of digits wanted
59 * *after* the decimal point. Scales are always >= 0.)
61 * buf points at the physical start of the palloc'd digit buffer for the
62 * NumericVar. digits points at the first digit in actual use (the one
63 * with the specified weight). We normally leave an unused byte or two
64 * (preset to zeroes) between buf and digits, so that there is room to store
65 * a carry out of the top digit without special pushups. We just need to
66 * decrement digits (and increment weight) to make room for the carry digit.
68 * If buf is NULL then the digit buffer isn't actually palloc'd and should
69 * not be freed --- see the constants below for an example.
71 * NB: All the variable-level functions are written in a style that makes it
72 * possible to give one and the same variable as argument and destination.
73 * This is feasible because the digit buffer is separate from the variable.
76 typedef unsigned char NumericDigit;
78 typedef struct NumericVar
80 int ndigits; /* number of digits in digits[] - can be
82 int weight; /* weight of first digit */
83 int rscale; /* result scale */
84 int dscale; /* display scale */
85 int sign; /* NUMERIC_POS, NUMERIC_NEG, or
87 NumericDigit *buf; /* start of palloc'd space for digits[] */
88 NumericDigit *digits; /* decimal digits */
96 static int global_rscale = NUMERIC_MIN_RESULT_SCALE;
99 * Some preinitialized variables we need often
102 static NumericDigit const_zero_data[1] = {0};
103 static NumericVar const_zero =
104 {0, 0, 0, 0, NUMERIC_POS, NULL, const_zero_data};
106 static NumericDigit const_one_data[1] = {1};
107 static NumericVar const_one =
108 {1, 0, 0, 0, NUMERIC_POS, NULL, const_one_data};
110 static NumericDigit const_two_data[1] = {2};
111 static NumericVar const_two =
112 {1, 0, 0, 0, NUMERIC_POS, NULL, const_two_data};
114 static NumericVar const_nan =
115 {0, 0, 0, 0, NUMERIC_NAN, NULL, NULL};
125 static void dump_numeric(char *str, Numeric num);
126 static void dump_var(char *str, NumericVar *var);
129 #define dump_numeric(s,n)
130 #define dump_var(s,v)
133 #define digitbuf_alloc(size) ((NumericDigit *) palloc(size))
134 #define digitbuf_free(buf) \
140 #define init_var(v) memset(v,0,sizeof(NumericVar))
141 static void alloc_var(NumericVar *var, int ndigits);
142 static void free_var(NumericVar *var);
143 static void zero_var(NumericVar *var);
145 static void set_var_from_str(char *str, NumericVar *dest);
146 static void set_var_from_num(Numeric value, NumericVar *dest);
147 static void set_var_from_var(NumericVar *value, NumericVar *dest);
148 static char *get_str_from_var(NumericVar *var, int dscale);
150 static Numeric make_result(NumericVar *var);
152 static void apply_typmod(NumericVar *var, int32 typmod);
154 static int cmp_var(NumericVar *var1, NumericVar *var2);
155 static void add_var(NumericVar *var1, NumericVar *var2, NumericVar *result);
156 static void sub_var(NumericVar *var1, NumericVar *var2, NumericVar *result);
157 static void mul_var(NumericVar *var1, NumericVar *var2, NumericVar *result);
158 static void div_var(NumericVar *var1, NumericVar *var2, NumericVar *result);
159 static void mod_var(NumericVar *var1, NumericVar *var2, NumericVar *result);
160 static void ceil_var(NumericVar *var, NumericVar *result);
161 static void floor_var(NumericVar *var, NumericVar *result);
163 static void sqrt_var(NumericVar *arg, NumericVar *result);
164 static void exp_var(NumericVar *arg, NumericVar *result);
165 static void ln_var(NumericVar *arg, NumericVar *result);
166 static void log_var(NumericVar *base, NumericVar *num, NumericVar *result);
167 static void power_var(NumericVar *base, NumericVar *exp, NumericVar *result);
169 static int cmp_abs(NumericVar *var1, NumericVar *var2);
170 static void add_abs(NumericVar *var1, NumericVar *var2, NumericVar *result);
171 static void sub_abs(NumericVar *var1, NumericVar *var2, NumericVar *result);
175 /* ----------------------------------------------------------------------
177 * Input-, output- and rounding-functions
179 * ----------------------------------------------------------------------
186 * Input function for numeric data type
190 numeric_in(PG_FUNCTION_ARGS)
192 char *str = PG_GETARG_CSTRING(0);
194 Oid typelem = PG_GETARG_OID(1);
196 int32 typmod = PG_GETARG_INT32(2);
204 if (strcmp(str, "NaN") == 0)
205 PG_RETURN_NUMERIC(make_result(&const_nan));
208 * Use set_var_from_str() to parse the input string
209 * and return it in the packed DB storage format
213 set_var_from_str(str, &value);
215 apply_typmod(&value, typmod);
217 res = make_result(&value);
220 PG_RETURN_NUMERIC(res);
227 * Output function for numeric data type
231 numeric_out(PG_FUNCTION_ARGS)
233 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
248 * the 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.
254 set_var_from_num(num, &x);
256 str = get_str_from_var(&x, x.dscale);
260 PG_RETURN_CSTRING(str);
267 * This is a special function called by the Postgres database system
268 * before a value is stored in a tuples attribute. The precision and
269 * scale of the attribute have to be applied on the value.
273 numeric(PG_FUNCTION_ARGS)
275 Numeric num = PG_GETARG_NUMERIC(0);
276 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
293 * copy of the input value
296 if (typmod < (int32) (VARHDRSZ))
298 new = (Numeric) palloc(num->varlen);
299 memcpy(new, num, num->varlen);
300 PG_RETURN_NUMERIC(new);
304 * Get the precision and scale out of the typmod value
307 tmp_typmod = typmod - VARHDRSZ;
308 precision = (tmp_typmod >> 16) & 0xffff;
309 scale = tmp_typmod & 0xffff;
310 maxweight = precision - scale;
313 * If the number is in bounds and due to the present result scale
314 * no rounding could be necessary, just make a copy of the input
315 * and modify its scale fields.
318 if (num->n_weight < maxweight && scale >= num->n_rscale)
320 new = (Numeric) palloc(num->varlen);
321 memcpy(new, num, num->varlen);
322 new->n_rscale = scale;
323 new->n_sign_dscale = NUMERIC_SIGN(new) |
324 ((uint16) scale & NUMERIC_DSCALE_MASK);
325 PG_RETURN_NUMERIC(new);
329 * We really need to fiddle with things - unpack the number into
330 * a variable and let apply_typmod() do it.
335 set_var_from_num(num, &var);
336 apply_typmod(&var, typmod);
337 new = make_result(&var);
341 PG_RETURN_NUMERIC(new);
345 /* ----------------------------------------------------------------------
347 * Sign manipulation, rounding and the like
349 * ----------------------------------------------------------------------
354 numeric_abs(Numeric num)
369 if (NUMERIC_IS_NAN(num))
370 return make_result(&const_nan);
373 * Do it the easy way directly on the packed format
376 res = (Numeric) palloc(num->varlen);
377 memcpy(res, num, num->varlen);
379 res->n_sign_dscale = NUMERIC_POS | NUMERIC_DSCALE(num);
386 numeric_uminus(Numeric num)
401 if (NUMERIC_IS_NAN(num))
402 return make_result(&const_nan);
405 * Do it the easy way directly on the packed format
408 res = (Numeric) palloc(num->varlen);
409 memcpy(res, num, num->varlen);
412 * The packed format is known to be totally zero digit trimmed
413 * always. So we can identify a ZERO by the fact that there
414 * are no digits at all. Do nothing to a zero.
417 if (num->varlen != NUMERIC_HDRSZ)
419 /* Else, flip the sign */
420 if (NUMERIC_SIGN(num) == NUMERIC_POS)
421 res->n_sign_dscale = NUMERIC_NEG | NUMERIC_DSCALE(num);
423 res->n_sign_dscale = NUMERIC_POS | NUMERIC_DSCALE(num);
431 numeric_sign(Numeric num)
447 if (NUMERIC_IS_NAN(num))
448 return make_result(&const_nan);
453 * The packed format is known to be totally zero digit trimmed
454 * always. So we can identify a ZERO by the fact that there
455 * are no digits at all.
458 if (num->varlen == NUMERIC_HDRSZ)
459 set_var_from_var(&const_zero, &result);
463 * And if there are some, we return a copy of ONE
464 * with the sign of our argument
467 set_var_from_var(&const_one, &result);
468 result.sign = NUMERIC_SIGN(num);
471 res = make_result(&result);
481 * Round a value to have 'scale' digits after the decimal point.
482 * We allow negative 'scale', implying rounding before the decimal
483 * point --- Oracle interprets rounding that way.
487 numeric_round(PG_FUNCTION_ARGS)
489 Numeric num = PG_GETARG_NUMERIC(0);
490 int32 scale = PG_GETARG_INT32(1);
499 if (NUMERIC_IS_NAN(num))
500 PG_RETURN_NUMERIC(make_result(&const_nan));
503 * Limit the scale value to avoid possible overflow in calculations below.
506 scale = MIN(NUMERIC_MAX_RESULT_SCALE,
507 MAX(-NUMERIC_MAX_RESULT_SCALE, scale));
510 * Unpack the argument and round it at the proper digit position
514 set_var_from_num(num, &arg);
516 i = arg.weight + scale + 1;
522 * If i = 0, the value loses all digits, but could round up if its
523 * first digit is more than 4. If i < 0 the result must be 0.
529 int carry = (arg.digits[i] > 4) ? 1 : 0;
535 carry += arg.digits[--i];
536 arg.digits[i] = carry % 10;
542 Assert(i == -1);/* better not have added more than 1 digit */
543 Assert(arg.digits > arg.buf);
552 * Set result's scale to something reasonable.
555 scale = MIN(NUMERIC_MAX_DISPLAY_SCALE, MAX(0, scale));
560 * Return the rounded result
563 res = make_result(&arg);
566 PG_RETURN_NUMERIC(res);
573 * Truncate a value to have 'scale' digits after the decimal point.
574 * We allow negative 'scale', implying a truncation before the decimal
575 * point --- Oracle interprets truncation that way.
579 numeric_trunc(PG_FUNCTION_ARGS)
581 Numeric num = PG_GETARG_NUMERIC(0);
582 int32 scale = PG_GETARG_INT32(1);
590 if (NUMERIC_IS_NAN(num))
591 PG_RETURN_NUMERIC(make_result(&const_nan));
594 * Limit the scale value to avoid possible overflow in calculations below.
597 scale = MIN(NUMERIC_MAX_RESULT_SCALE,
598 MAX(-NUMERIC_MAX_RESULT_SCALE, scale));
601 * Unpack the argument and truncate it at the proper digit position
605 set_var_from_num(num, &arg);
607 arg.ndigits = MIN(arg.ndigits, MAX(0, arg.weight + scale + 1));
610 * Set result's scale to something reasonable.
613 scale = MIN(NUMERIC_MAX_DISPLAY_SCALE, MAX(0, scale));
618 * Return the truncated result
621 res = make_result(&arg);
624 PG_RETURN_NUMERIC(res);
631 * Return the smallest integer greater than or equal to the argument
635 numeric_ceil(Numeric num)
643 if (NUMERIC_IS_NAN(num))
644 return make_result(&const_nan);
648 set_var_from_num(num, &result);
649 ceil_var(&result, &result);
653 res = make_result(&result);
663 * Return the largest integer equal to or less than the argument
667 numeric_floor(Numeric num)
675 if (NUMERIC_IS_NAN(num))
676 return make_result(&const_nan);
680 set_var_from_num(num, &result);
681 floor_var(&result, &result);
685 res = make_result(&result);
692 /* ----------------------------------------------------------------------
694 * Comparison functions
696 * ----------------------------------------------------------------------
701 numeric_cmp(Numeric num1, Numeric num2)
707 if (num1 == NULL || num2 == NULL)
710 if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
716 set_var_from_num(num1, &arg1);
717 set_var_from_num(num2, &arg2);
719 result = cmp_var(&arg1, &arg2);
724 return (int32) ((result == 0) ? 0 : ((result < 0) ? -1 : 1));
729 numeric_eq(Numeric num1, Numeric num2)
735 if (num1 == NULL || num2 == NULL)
738 if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
744 set_var_from_num(num1, &arg1);
745 set_var_from_num(num2, &arg2);
747 result = cmp_var(&arg1, &arg2);
752 return (result == 0);
757 numeric_ne(Numeric num1, Numeric num2)
763 if (num1 == NULL || num2 == NULL)
766 if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
772 set_var_from_num(num1, &arg1);
773 set_var_from_num(num2, &arg2);
775 result = cmp_var(&arg1, &arg2);
780 return (result != 0);
785 numeric_gt(Numeric num1, Numeric num2)
791 if (num1 == NULL || num2 == NULL)
794 if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
800 set_var_from_num(num1, &arg1);
801 set_var_from_num(num2, &arg2);
803 result = cmp_var(&arg1, &arg2);
813 numeric_ge(Numeric num1, Numeric num2)
819 if (num1 == NULL || num2 == NULL)
822 if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
828 set_var_from_num(num1, &arg1);
829 set_var_from_num(num2, &arg2);
831 result = cmp_var(&arg1, &arg2);
836 return (result >= 0);
841 numeric_lt(Numeric num1, Numeric num2)
847 if (num1 == NULL || num2 == NULL)
850 if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
856 set_var_from_num(num1, &arg1);
857 set_var_from_num(num2, &arg2);
859 result = cmp_var(&arg1, &arg2);
869 numeric_le(Numeric num1, Numeric num2)
875 if (num1 == NULL || num2 == NULL)
878 if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
884 set_var_from_num(num1, &arg1);
885 set_var_from_num(num2, &arg2);
887 result = cmp_var(&arg1, &arg2);
892 return (result <= 0);
896 /* ----------------------------------------------------------------------
898 * Arithmetic base functions
900 * ----------------------------------------------------------------------
911 numeric_add(Numeric num1, Numeric num2)
922 if (num1 == NULL || num2 == NULL)
929 if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
930 return make_result(&const_nan);
933 * Unpack the values, let add_var() compute the result
934 * and return it. The internals of add_var() will automatically
935 * set the correct result and display scales in the result.
942 set_var_from_num(num1, &arg1);
943 set_var_from_num(num2, &arg2);
945 add_var(&arg1, &arg2, &result);
946 res = make_result(&result);
959 * Subtract one numeric from another
963 numeric_sub(Numeric num1, Numeric num2)
974 if (num1 == NULL || num2 == NULL)
981 if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
982 return make_result(&const_nan);
985 * Unpack the two arguments, let sub_var() compute the
986 * result and return it.
993 set_var_from_num(num1, &arg1);
994 set_var_from_num(num2, &arg2);
996 sub_var(&arg1, &arg2, &result);
997 res = make_result(&result);
1010 * Calculate the product of two numerics
1014 numeric_mul(Numeric num1, Numeric num2)
1025 if (num1 == NULL || num2 == NULL)
1032 if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
1033 return make_result(&const_nan);
1036 * Unpack the arguments, let mul_var() compute the result
1037 * and return it. Unlike add_var() and sub_var(), mul_var()
1038 * will round the result to the scale stored in global_rscale.
1039 * In the case of numeric_mul(), which is invoked for the *
1040 * operator on numerics, we set it to the exact representation
1041 * for the product (rscale = sum(rscale of arg1, rscale of arg2)
1042 * and the same for the dscale).
1049 set_var_from_num(num1, &arg1);
1050 set_var_from_num(num2, &arg2);
1052 global_rscale = arg1.rscale + arg2.rscale;
1054 mul_var(&arg1, &arg2, &result);
1056 result.dscale = arg1.dscale + arg2.dscale;
1058 res = make_result(&result);
1071 * Divide one numeric into another
1075 numeric_div(Numeric num1, Numeric num2)
1087 if (num1 == NULL || num2 == NULL)
1094 if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
1095 return make_result(&const_nan);
1098 * Unpack the arguments
1105 set_var_from_num(num1, &arg1);
1106 set_var_from_num(num2, &arg2);
1109 * The result scale of a division isn't specified in any
1110 * SQL standard. For Postgres it is the following (where
1111 * SR, DR are the result- and display-scales of the returned
1112 * value, S1, D1, S2 and D2 are the scales of the two arguments,
1113 * The minimum and maximum scales are compile time options from
1116 * DR = MIN(MAX(D1 + D2, MIN_DISPLAY_SCALE), MAX_DISPLAY_SCALE)
1117 * SR = MIN(MAX(MAX(S1 + S2, MIN_RESULT_SCALE), DR + 4), MAX_RESULT_SCALE)
1119 * By default, any result is computed with a minimum of 34 digits
1120 * after the decimal point or at least with 4 digits more than
1124 res_dscale = MAX(arg1.dscale + arg2.dscale, NUMERIC_MIN_DISPLAY_SCALE);
1125 res_dscale = MIN(res_dscale, NUMERIC_MAX_DISPLAY_SCALE);
1126 global_rscale = MAX(arg1.rscale + arg2.rscale,
1127 NUMERIC_MIN_RESULT_SCALE);
1128 global_rscale = MAX(global_rscale, res_dscale + 4);
1129 global_rscale = MIN(global_rscale, NUMERIC_MAX_RESULT_SCALE);
1132 * Do the divide, set the display scale and return the result
1135 div_var(&arg1, &arg2, &result);
1137 result.dscale = res_dscale;
1139 res = make_result(&result);
1152 * Calculate the modulo of two numerics
1156 numeric_mod(Numeric num1, Numeric num2)
1163 if (num1 == NULL || num2 == NULL)
1166 if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
1167 return make_result(&const_nan);
1173 set_var_from_num(num1, &arg1);
1174 set_var_from_num(num2, &arg2);
1176 mod_var(&arg1, &arg2, &result);
1178 result.dscale = result.rscale;
1179 res = make_result(&result);
1192 * Increment a number by one
1196 numeric_inc(Numeric num)
1212 if (NUMERIC_IS_NAN(num))
1213 return make_result(&const_nan);
1216 * Compute the result and return it
1221 set_var_from_num(num, &arg);
1223 add_var(&arg, &const_one, &arg);
1224 res = make_result(&arg);
1235 * Decrement a number by one
1239 numeric_dec(Numeric num)
1255 if (NUMERIC_IS_NAN(num))
1256 return make_result(&const_nan);
1259 * Compute the result and return it
1264 set_var_from_num(num, &arg);
1266 sub_var(&arg, &const_one, &arg);
1267 res = make_result(&arg);
1276 * numeric_smaller() -
1278 * Return the smaller of two numbers
1282 numeric_smaller(Numeric num1, Numeric num2)
1292 if (num1 == NULL || num2 == NULL)
1299 if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
1300 return make_result(&const_nan);
1303 * Unpack the values, and decide which is the smaller one
1309 set_var_from_num(num1, &arg1);
1310 set_var_from_num(num2, &arg2);
1312 if (cmp_var(&arg1, &arg2) <= 0)
1313 res = make_result(&arg1);
1315 res = make_result(&arg2);
1325 * numeric_larger() -
1327 * Return the larger of two numbers
1331 numeric_larger(Numeric num1, Numeric num2)
1341 if (num1 == NULL || num2 == NULL)
1348 if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
1349 return make_result(&const_nan);
1352 * Unpack the values, and decide which is the larger one
1358 set_var_from_num(num1, &arg1);
1359 set_var_from_num(num2, &arg2);
1361 if (cmp_var(&arg1, &arg2) >= 0)
1362 res = make_result(&arg1);
1364 res = make_result(&arg2);
1373 /* ----------------------------------------------------------------------
1375 * Complex math functions
1377 * ----------------------------------------------------------------------
1384 * Compute the square root of a numeric.
1388 numeric_sqrt(Numeric num)
1406 if (NUMERIC_IS_NAN(num))
1407 return make_result(&const_nan);
1410 * Unpack the argument, determine the scales like for divide,
1411 * let sqrt_var() do the calculation and return the result.
1417 set_var_from_num(num, &arg);
1419 res_dscale = MAX(arg.dscale, NUMERIC_MIN_DISPLAY_SCALE);
1420 res_dscale = MIN(res_dscale, NUMERIC_MAX_DISPLAY_SCALE);
1421 global_rscale = MAX(arg.rscale, NUMERIC_MIN_RESULT_SCALE);
1422 global_rscale = MAX(global_rscale, res_dscale + 4);
1423 global_rscale = MIN(global_rscale, NUMERIC_MAX_RESULT_SCALE);
1425 sqrt_var(&arg, &result);
1427 result.dscale = res_dscale;
1429 res = make_result(&result);
1441 * Raise e to the power of x
1445 numeric_exp(Numeric num)
1463 if (NUMERIC_IS_NAN(num))
1464 return make_result(&const_nan);
1467 * Same procedure like for sqrt().
1472 set_var_from_num(num, &arg);
1474 res_dscale = MAX(arg.dscale, NUMERIC_MIN_DISPLAY_SCALE);
1475 res_dscale = MIN(res_dscale, NUMERIC_MAX_DISPLAY_SCALE);
1476 global_rscale = MAX(arg.rscale, NUMERIC_MIN_RESULT_SCALE);
1477 global_rscale = MAX(global_rscale, res_dscale + 4);
1478 global_rscale = MIN(global_rscale, NUMERIC_MAX_RESULT_SCALE);
1480 exp_var(&arg, &result);
1482 result.dscale = res_dscale;
1484 res = make_result(&result);
1496 * Compute the natural logarithm of x
1500 numeric_ln(Numeric num)
1518 if (NUMERIC_IS_NAN(num))
1519 return make_result(&const_nan);
1522 * Same procedure like for sqrt()
1527 set_var_from_num(num, &arg);
1529 res_dscale = MAX(arg.dscale, NUMERIC_MIN_DISPLAY_SCALE);
1530 res_dscale = MIN(res_dscale, NUMERIC_MAX_DISPLAY_SCALE);
1531 global_rscale = MAX(arg.rscale, NUMERIC_MIN_RESULT_SCALE);
1532 global_rscale = MAX(global_rscale, res_dscale + 4);
1533 global_rscale = MIN(global_rscale, NUMERIC_MAX_RESULT_SCALE);
1535 ln_var(&arg, &result);
1537 result.dscale = res_dscale;
1539 res = make_result(&result);
1551 * Compute the logarithm of x in a given base
1555 numeric_log(Numeric num1, Numeric num2)
1567 if (num1 == NULL || num2 == NULL)
1574 if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
1575 return make_result(&const_nan);
1578 * Initialize things and calculate scales
1584 set_var_from_num(num1, &arg1);
1585 set_var_from_num(num2, &arg2);
1587 res_dscale = MAX(arg1.dscale + arg2.dscale, NUMERIC_MIN_DISPLAY_SCALE);
1588 res_dscale = MIN(res_dscale, NUMERIC_MAX_DISPLAY_SCALE);
1589 global_rscale = MAX(arg1.rscale + arg2.rscale, NUMERIC_MIN_RESULT_SCALE);
1590 global_rscale = MAX(global_rscale, res_dscale + 4);
1591 global_rscale = MIN(global_rscale, NUMERIC_MAX_RESULT_SCALE);
1594 * Call log_var() to compute and return the result
1597 log_var(&arg1, &arg2, &result);
1599 result.dscale = res_dscale;
1601 res = make_result(&result);
1614 * Raise m to the power of x
1618 numeric_power(Numeric num1, Numeric num2)
1630 if (num1 == NULL || num2 == NULL)
1637 if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
1638 return make_result(&const_nan);
1641 * Initialize things and calculate scales
1647 set_var_from_num(num1, &arg1);
1648 set_var_from_num(num2, &arg2);
1650 res_dscale = MAX(arg1.dscale + arg2.dscale, NUMERIC_MIN_DISPLAY_SCALE);
1651 res_dscale = MIN(res_dscale, NUMERIC_MAX_DISPLAY_SCALE);
1652 global_rscale = MAX(arg1.rscale + arg2.rscale, NUMERIC_MIN_RESULT_SCALE);
1653 global_rscale = MAX(global_rscale, res_dscale + 4);
1654 global_rscale = MIN(global_rscale, NUMERIC_MAX_RESULT_SCALE);
1657 * Call log_var() to compute and return the result
1660 power_var(&arg1, &arg2, &result);
1662 result.dscale = res_dscale;
1664 res = make_result(&result);
1674 /* ----------------------------------------------------------------------
1676 * Type conversion functions
1678 * ----------------------------------------------------------------------
1683 int4_numeric(PG_FUNCTION_ARGS)
1685 int32 val = PG_GETARG_INT32(0);
1692 tmp = DatumGetCString(DirectFunctionCall1(int4out,
1693 Int32GetDatum(val)));
1694 set_var_from_str(tmp, &result);
1695 res = make_result(&result);
1700 PG_RETURN_NUMERIC(res);
1705 numeric_int4(Numeric num)
1714 if (NUMERIC_IS_NAN(num))
1715 elog(ERROR, "Cannot convert NaN to int4");
1718 * Get the number in the variable format so we can round to integer.
1722 set_var_from_num(num, &x);
1724 str = get_str_from_var(&x, 0); /* dscale = 0 produces rounding */
1728 result = DirectFunctionCall1(int4in, CStringGetDatum(str));
1736 int8_numeric(int64 *val)
1744 tmp = DatumGetCString(DirectFunctionCall1(int8out,
1745 PointerGetDatum(val)));
1746 set_var_from_str(tmp, &result);
1747 res = make_result(&result);
1757 numeric_int8(Numeric num)
1766 if (NUMERIC_IS_NAN(num))
1767 elog(ERROR, "Cannot convert NaN to int8");
1770 * Get the number in the variable format so we can round to integer.
1774 set_var_from_num(num, &x);
1776 str = get_str_from_var(&x, 0); /* dscale = 0 produces rounding */
1780 result = DirectFunctionCall1(int8in, CStringGetDatum(str));
1784 return (int64 *) (result);
1789 int2_numeric(PG_FUNCTION_ARGS)
1791 int16 val = PG_GETARG_INT16(0);
1798 tmp = DatumGetCString(DirectFunctionCall1(int2out,
1799 Int16GetDatum(val)));
1800 set_var_from_str(tmp, &result);
1801 res = make_result(&result);
1806 PG_RETURN_NUMERIC(res);
1811 numeric_int2(PG_FUNCTION_ARGS)
1813 Numeric num = PG_GETARG_NUMERIC(0);
1818 if (NUMERIC_IS_NAN(num))
1819 elog(ERROR, "Cannot convert NaN to int2");
1822 * Get the number in the variable format so we can round to integer.
1826 set_var_from_num(num, &x);
1828 str = get_str_from_var(&x, 0); /* dscale = 0 produces rounding */
1832 result = DirectFunctionCall1(int2in, CStringGetDatum(str));
1840 float8_numeric(float64 val)
1844 char buf[DBL_DIG + 100];
1850 return make_result(&const_nan);
1852 sprintf(buf, "%.*g", DBL_DIG, *val);
1856 set_var_from_str(buf, &result);
1857 res = make_result(&result);
1866 numeric_float8(Numeric num)
1874 if (NUMERIC_IS_NAN(num))
1876 result = (float64) palloc(sizeof(float64data));
1881 tmp = DatumGetCString(DirectFunctionCall1(numeric_out,
1882 NumericGetDatum(num)));
1883 result = float8in(tmp);
1891 float4_numeric(float32 val)
1895 char buf[FLT_DIG + 100];
1901 return make_result(&const_nan);
1903 sprintf(buf, "%.*g", FLT_DIG, *val);
1907 set_var_from_str(buf, &result);
1908 res = make_result(&result);
1917 numeric_float4(Numeric num)
1925 if (NUMERIC_IS_NAN(num))
1927 result = (float32) palloc(sizeof(float32data));
1932 tmp = DatumGetCString(DirectFunctionCall1(numeric_out,
1933 NumericGetDatum(num)));
1934 result = float4in(tmp);
1941 /* ----------------------------------------------------------------------
1943 * Local functions follow
1945 * ----------------------------------------------------------------------
1949 #ifdef NUMERIC_DEBUG
1952 * dump_numeric() - Dump a value in the db storage format for debugging
1956 dump_numeric(char *str, Numeric num)
1960 printf("%s: NUMERIC w=%d r=%d d=%d ", str, num->n_weight, num->n_rscale,
1961 NUMERIC_DSCALE(num));
1962 switch (NUMERIC_SIGN(num))
1974 printf("SIGN=0x%x", NUMERIC_SIGN(num));
1978 for (i = 0; i < num->varlen - NUMERIC_HDRSZ; i++)
1979 printf(" %d %d", (num->n_data[i] >> 4) & 0x0f, num->n_data[i] & 0x0f);
1985 * dump_var() - Dump a value in the variable format for debugging
1989 dump_var(char *str, NumericVar *var)
1993 printf("%s: VAR w=%d r=%d d=%d ", str, var->weight, var->rscale,
2007 printf("SIGN=0x%x", var->sign);
2011 for (i = 0; i < var->ndigits; i++)
2012 printf(" %d", var->digits[i]);
2017 #endif /* NUMERIC_DEBUG */
2023 * Allocate a digit buffer of ndigits digits (plus a spare digit for rounding)
2027 alloc_var(NumericVar *var, int ndigits)
2029 digitbuf_free(var->buf);
2030 var->buf = digitbuf_alloc(ndigits + 1);
2032 var->digits = var->buf + 1;
2033 var->ndigits = ndigits;
2040 * Return the digit buffer of a variable to the free pool
2044 free_var(NumericVar *var)
2046 digitbuf_free(var->buf);
2049 var->sign = NUMERIC_NAN;
2056 * Set a variable to ZERO.
2057 * Note: rscale and dscale are not touched.
2061 zero_var(NumericVar *var)
2063 digitbuf_free(var->buf);
2067 var->weight = 0; /* by convention; doesn't really matter */
2068 var->sign = NUMERIC_POS; /* anything but NAN... */
2073 * set_var_from_str()
2075 * Parse a string and put the number into a variable
2079 set_var_from_str(char *str, NumericVar *dest)
2082 bool have_dp = FALSE;
2087 if (!isspace((int) *cp))
2092 alloc_var(dest, strlen(cp));
2095 dest->sign = NUMERIC_POS;
2100 dest->sign = NUMERIC_POS;
2105 dest->sign = NUMERIC_NEG;
2116 if (!isdigit((int) *cp))
2117 elog(ERROR, "Bad numeric input format '%s'", str);
2121 if (isdigit((int) *cp))
2123 dest->digits[i++] = *cp++ - '0';
2129 else if (*cp == '.')
2132 elog(ERROR, "Bad numeric input format '%s'", str);
2141 /* Handle exponent, if any */
2142 if (*cp == 'e' || *cp == 'E')
2148 exponent = strtol(cp, &endptr, 10);
2150 elog(ERROR, "Bad numeric input format '%s'", str);
2152 if (exponent > NUMERIC_MAX_PRECISION ||
2153 exponent < -NUMERIC_MAX_PRECISION)
2154 elog(ERROR, "Bad numeric input format '%s'", str);
2155 dest->weight += (int) exponent;
2156 dest->dscale -= (int) exponent;
2157 if (dest->dscale < 0)
2161 /* Should be nothing left but spaces */
2164 if (!isspace((int) *cp))
2165 elog(ERROR, "Bad numeric input format '%s'", str);
2169 /* Strip any leading zeroes */
2170 while (dest->ndigits > 0 && *(dest->digits) == 0)
2176 if (dest->ndigits == 0)
2179 dest->rscale = dest->dscale;
2184 * set_var_from_num() -
2186 * Parse back the packed db format into a variable
2190 set_var_from_num(Numeric num, NumericVar *dest)
2192 NumericDigit *digit;
2196 n = num->varlen - NUMERIC_HDRSZ; /* number of digit-pairs in packed
2199 alloc_var(dest, n * 2);
2201 dest->weight = num->n_weight;
2202 dest->rscale = num->n_rscale;
2203 dest->dscale = NUMERIC_DSCALE(num);
2204 dest->sign = NUMERIC_SIGN(num);
2206 digit = dest->digits;
2208 for (i = 0; i < n; i++)
2210 unsigned char digitpair = num->n_data[i];
2212 *digit++ = (digitpair >> 4) & 0x0f;
2213 *digit++ = digitpair & 0x0f;
2219 * set_var_from_var() -
2221 * Copy one variable into another
2225 set_var_from_var(NumericVar *value, NumericVar *dest)
2227 NumericDigit *newbuf;
2229 newbuf = digitbuf_alloc(value->ndigits + 1);
2230 newbuf[0] = 0; /* spare digit for rounding */
2231 memcpy(newbuf + 1, value->digits, value->ndigits);
2233 digitbuf_free(dest->buf);
2235 memcpy(dest, value, sizeof(NumericVar));
2237 dest->digits = newbuf + 1;
2242 * get_str_from_var() -
2244 * Convert a var to text representation (guts of numeric_out).
2245 * CAUTION: var's contents may be modified by rounding!
2246 * Caller must have checked for NaN case.
2247 * Returns a palloc'd string.
2251 get_str_from_var(NumericVar *var, int dscale)
2259 * Check if we must round up before printing the value and
2263 i = dscale + var->weight + 1;
2264 if (i >= 0 && var->ndigits > i)
2266 int carry = (var->digits[i] > 4) ? 1 : 0;
2272 carry += var->digits[--i];
2273 var->digits[i] = carry % 10;
2279 Assert(i == -1); /* better not have added more than 1 digit */
2280 Assert(var->digits > var->buf);
2287 var->ndigits = MAX(0, MIN(i, var->ndigits));
2290 * Allocate space for the result
2293 str = palloc(MAX(0, dscale) + MAX(0, var->weight) + 4);
2297 * Output a dash for negative values
2300 if (var->sign == NUMERIC_NEG)
2304 * Output all digits before the decimal point
2307 i = MAX(var->weight, 0);
2312 if (i <= var->weight && d < var->ndigits)
2313 *cp++ = var->digits[d++] + '0';
2320 * If requested, output a decimal point and all the digits
2327 while (i >= -dscale)
2329 if (i <= var->weight && d < var->ndigits)
2330 *cp++ = var->digits[d++] + '0';
2338 * terminate the string and return it
2349 * Create the packed db numeric format in palloc()'d memory from
2350 * a variable. The var's rscale determines the number of digits kept.
2354 make_result(NumericVar *var)
2357 NumericDigit *digit = var->digits;
2358 int weight = var->weight;
2359 int sign = var->sign;
2364 if (sign == NUMERIC_NAN)
2366 result = (Numeric) palloc(NUMERIC_HDRSZ);
2368 result->varlen = NUMERIC_HDRSZ;
2369 result->n_weight = 0;
2370 result->n_rscale = 0;
2371 result->n_sign_dscale = NUMERIC_NAN;
2373 dump_numeric("make_result()", result);
2377 n = MAX(0, MIN(var->ndigits, var->weight + var->rscale + 1));
2379 /* truncate leading zeroes */
2380 while (n > 0 && *digit == 0)
2386 /* truncate trailing zeroes */
2387 while (n > 0 && digit[n - 1] == 0)
2390 /* If zero result, force to weight=0 and positive sign */
2397 result = (Numeric) palloc(NUMERIC_HDRSZ + (n + 1) / 2);
2398 result->varlen = NUMERIC_HDRSZ + (n + 1) / 2;
2399 result->n_weight = weight;
2400 result->n_rscale = var->rscale;
2401 result->n_sign_dscale = sign |
2402 ((uint16) var->dscale & NUMERIC_DSCALE_MASK);
2408 unsigned char digitpair = digit[j++] << 4;
2411 digitpair |= digit[j++];
2412 result->n_data[i++] = digitpair;
2415 dump_numeric("make_result()", result);
2423 * Do bounds checking and rounding according to the attributes
2428 apply_typmod(NumericVar *var, int32 typmod)
2435 /* Do nothing if we have a default typmod (-1) */
2436 if (typmod < (int32) (VARHDRSZ))
2440 precision = (typmod >> 16) & 0xffff;
2441 scale = typmod & 0xffff;
2442 maxweight = precision - scale;
2444 /* Round to target scale */
2445 i = scale + var->weight + 1;
2446 if (i >= 0 && var->ndigits > i)
2448 int carry = (var->digits[i] > 4) ? 1 : 0;
2454 carry += var->digits[--i];
2455 var->digits[i] = carry % 10;
2461 Assert(i == -1); /* better not have added more than 1 digit */
2462 Assert(var->digits > var->buf);
2469 var->ndigits = MAX(0, MIN(i, var->ndigits));
2472 * Check for overflow - note we can't do this before rounding,
2473 * because rounding could raise the weight. Also note that the
2474 * var's weight could be inflated by leading zeroes, which will
2475 * be stripped before storage but perhaps might not have been yet.
2476 * In any case, we must recognize a true zero, whose weight doesn't
2480 if (var->weight >= maxweight)
2482 /* Determine true weight; and check for all-zero result */
2483 int tweight = var->weight;
2485 for (i = 0; i < var->ndigits; i++)
2492 if (tweight >= maxweight && i < var->ndigits)
2493 elog(ERROR, "overflow on numeric "
2494 "ABS(value) >= 10^%d for field with precision %d scale %d",
2495 tweight, precision, scale);
2498 var->rscale = scale;
2499 var->dscale = scale;
2506 * Compare two values on variable level
2510 cmp_var(NumericVar *var1, NumericVar *var2)
2512 if (var1->ndigits == 0)
2514 if (var2->ndigits == 0)
2516 if (var2->sign == NUMERIC_NEG)
2520 if (var2->ndigits == 0)
2522 if (var1->sign == NUMERIC_POS)
2527 if (var1->sign == NUMERIC_POS)
2529 if (var2->sign == NUMERIC_NEG)
2531 return cmp_abs(var1, var2);
2534 if (var2->sign == NUMERIC_POS)
2537 return cmp_abs(var2, var1);
2544 * Full version of add functionality on variable level (handling signs).
2545 * result might point to one of the operands too without danger.
2549 add_var(NumericVar *var1, NumericVar *var2, NumericVar *result)
2552 * Decide on the signs of the two variables what to do
2555 if (var1->sign == NUMERIC_POS)
2557 if (var2->sign == NUMERIC_POS)
2561 * result = +(ABS(var1) + ABS(var2))
2564 add_abs(var1, var2, result);
2565 result->sign = NUMERIC_POS;
2570 * var1 is positive, var2 is negative
2571 * Must compare absolute values
2574 switch (cmp_abs(var1, var2))
2576 case 0: /* ----------
2577 * ABS(var1) == ABS(var2)
2582 result->rscale = MAX(var1->rscale, var2->rscale);
2583 result->dscale = MAX(var1->dscale, var2->dscale);
2586 case 1: /* ----------
2587 * ABS(var1) > ABS(var2)
2588 * result = +(ABS(var1) - ABS(var2))
2591 sub_abs(var1, var2, result);
2592 result->sign = NUMERIC_POS;
2595 case -1: /* ----------
2596 * ABS(var1) < ABS(var2)
2597 * result = -(ABS(var2) - ABS(var1))
2600 sub_abs(var2, var1, result);
2601 result->sign = NUMERIC_NEG;
2608 if (var2->sign == NUMERIC_POS)
2611 * var1 is negative, var2 is positive
2612 * Must compare absolute values
2615 switch (cmp_abs(var1, var2))
2617 case 0: /* ----------
2618 * ABS(var1) == ABS(var2)
2623 result->rscale = MAX(var1->rscale, var2->rscale);
2624 result->dscale = MAX(var1->dscale, var2->dscale);
2627 case 1: /* ----------
2628 * ABS(var1) > ABS(var2)
2629 * result = -(ABS(var1) - ABS(var2))
2632 sub_abs(var1, var2, result);
2633 result->sign = NUMERIC_NEG;
2636 case -1: /* ----------
2637 * ABS(var1) < ABS(var2)
2638 * result = +(ABS(var2) - ABS(var1))
2641 sub_abs(var2, var1, result);
2642 result->sign = NUMERIC_POS;
2650 * result = -(ABS(var1) + ABS(var2))
2653 add_abs(var1, var2, result);
2654 result->sign = NUMERIC_NEG;
2663 * Full version of sub functionality on variable level (handling signs).
2664 * result might point to one of the operands too without danger.
2668 sub_var(NumericVar *var1, NumericVar *var2, NumericVar *result)
2671 * Decide on the signs of the two variables what to do
2674 if (var1->sign == NUMERIC_POS)
2676 if (var2->sign == NUMERIC_NEG)
2679 * var1 is positive, var2 is negative
2680 * result = +(ABS(var1) + ABS(var2))
2683 add_abs(var1, var2, result);
2684 result->sign = NUMERIC_POS;
2690 * Must compare absolute values
2693 switch (cmp_abs(var1, var2))
2695 case 0: /* ----------
2696 * ABS(var1) == ABS(var2)
2701 result->rscale = MAX(var1->rscale, var2->rscale);
2702 result->dscale = MAX(var1->dscale, var2->dscale);
2705 case 1: /* ----------
2706 * ABS(var1) > ABS(var2)
2707 * result = +(ABS(var1) - ABS(var2))
2710 sub_abs(var1, var2, result);
2711 result->sign = NUMERIC_POS;
2714 case -1: /* ----------
2715 * ABS(var1) < ABS(var2)
2716 * result = -(ABS(var2) - ABS(var1))
2719 sub_abs(var2, var1, result);
2720 result->sign = NUMERIC_NEG;
2727 if (var2->sign == NUMERIC_NEG)
2731 * Must compare absolute values
2734 switch (cmp_abs(var1, var2))
2736 case 0: /* ----------
2737 * ABS(var1) == ABS(var2)
2742 result->rscale = MAX(var1->rscale, var2->rscale);
2743 result->dscale = MAX(var1->dscale, var2->dscale);
2746 case 1: /* ----------
2747 * ABS(var1) > ABS(var2)
2748 * result = -(ABS(var1) - ABS(var2))
2751 sub_abs(var1, var2, result);
2752 result->sign = NUMERIC_NEG;
2755 case -1: /* ----------
2756 * ABS(var1) < ABS(var2)
2757 * result = +(ABS(var2) - ABS(var1))
2760 sub_abs(var2, var1, result);
2761 result->sign = NUMERIC_POS;
2768 * var1 is negative, var2 is positive
2769 * result = -(ABS(var1) + ABS(var2))
2772 add_abs(var1, var2, result);
2773 result->sign = NUMERIC_NEG;
2782 * Multiplication on variable level. Product of var1 * var2 is stored
2787 mul_var(NumericVar *var1, NumericVar *var2, NumericVar *result)
2789 NumericDigit *res_buf;
2790 NumericDigit *res_digits;
2800 res_weight = var1->weight + var2->weight + 2;
2801 res_ndigits = var1->ndigits + var2->ndigits + 1;
2802 if (var1->sign == var2->sign)
2803 res_sign = NUMERIC_POS;
2805 res_sign = NUMERIC_NEG;
2807 res_buf = digitbuf_alloc(res_ndigits);
2808 res_digits = res_buf;
2809 memset(res_digits, 0, res_ndigits);
2812 for (i1 = var1->ndigits - 1; i1 >= 0; i1--)
2817 for (i2 = var2->ndigits - 1; i2 >= 0; i2--)
2819 sum = sum + res_digits[i] + var1->digits[i1] * var2->digits[i2];
2820 res_digits[i--] = sum % 10;
2823 res_digits[i] = sum;
2826 i = res_weight + global_rscale + 2;
2827 if (i >= 0 && i < res_ndigits)
2829 sum = (res_digits[i] > 4) ? 1 : 0;
2834 sum += res_digits[i];
2835 res_digits[i--] = sum % 10;
2840 while (res_ndigits > 0 && *res_digits == 0)
2846 while (res_ndigits > 0 && res_digits[res_ndigits - 1] == 0)
2849 if (res_ndigits == 0)
2851 res_sign = NUMERIC_POS;
2855 digitbuf_free(result->buf);
2856 result->buf = res_buf;
2857 result->digits = res_digits;
2858 result->ndigits = res_ndigits;
2859 result->weight = res_weight;
2860 result->rscale = global_rscale;
2861 result->sign = res_sign;
2868 * Division on variable level.
2872 div_var(NumericVar *var1, NumericVar *var2, NumericVar *result)
2874 NumericDigit *res_digits;
2878 NumericVar dividend;
2879 NumericVar divisor[10];
2888 int first_nextdigit;
2892 * First of all division by zero check
2895 ndigits_tmp = var2->ndigits + 1;
2896 if (ndigits_tmp == 1)
2897 elog(ERROR, "division by zero on numeric");
2900 * Determine the result sign, weight and number of digits to calculate
2903 if (var1->sign == var2->sign)
2904 res_sign = NUMERIC_POS;
2906 res_sign = NUMERIC_NEG;
2907 res_weight = var1->weight - var2->weight + 1;
2908 res_ndigits = global_rscale + res_weight;
2909 if (res_ndigits <= 0)
2913 * Now result zero check
2916 if (var1->ndigits == 0)
2919 result->rscale = global_rscale;
2924 * Initialize local variables
2927 init_var(÷nd);
2928 for (i = 1; i < 10; i++)
2929 init_var(&divisor[i]);
2932 * Make a copy of the divisor which has one leading zero digit
2935 divisor[1].ndigits = ndigits_tmp;
2936 divisor[1].rscale = var2->ndigits;
2937 divisor[1].sign = NUMERIC_POS;
2938 divisor[1].buf = digitbuf_alloc(ndigits_tmp);
2939 divisor[1].digits = divisor[1].buf;
2940 divisor[1].digits[0] = 0;
2941 memcpy(&(divisor[1].digits[1]), var2->digits, ndigits_tmp - 1);
2944 * Make a copy of the dividend
2947 dividend.ndigits = var1->ndigits;
2948 dividend.weight = 0;
2949 dividend.rscale = var1->ndigits;
2950 dividend.sign = NUMERIC_POS;
2951 dividend.buf = digitbuf_alloc(var1->ndigits);
2952 dividend.digits = dividend.buf;
2953 memcpy(dividend.digits, var1->digits, var1->ndigits);
2959 digitbuf_free(result->buf);
2960 result->buf = digitbuf_alloc(res_ndigits + 2);
2961 res_digits = result->buf;
2962 result->digits = res_digits;
2963 result->ndigits = res_ndigits;
2964 result->weight = res_weight;
2965 result->rscale = global_rscale;
2966 result->sign = res_sign;
2969 first_div = divisor[1].digits[1] * 10;
2970 if (ndigits_tmp > 2)
2971 first_div += divisor[1].digits[2];
2974 first_nextdigit = 0;
2977 rscale_tmp = divisor[1].rscale;
2979 for (ri = 0; ri <= res_ndigits; ri++)
2981 first_have = first_have * 10;
2982 if (first_nextdigit >= 0 && first_nextdigit < dividend.ndigits)
2983 first_have += dividend.digits[first_nextdigit];
2986 guess = (first_have * 10) / first_div + 1;
2992 if (divisor[guess].buf == NULL)
2997 memcpy(&divisor[guess], &divisor[1], sizeof(NumericVar));
2998 divisor[guess].buf = digitbuf_alloc(divisor[guess].ndigits);
2999 divisor[guess].digits = divisor[guess].buf;
3000 for (i = divisor[1].ndigits - 1; i >= 0; i--)
3002 sum += divisor[1].digits[i] * guess;
3003 divisor[guess].digits[i] = sum % 10;
3008 divisor[guess].weight = weight_tmp;
3009 divisor[guess].rscale = rscale_tmp;
3011 stat = cmp_abs(÷nd, &divisor[guess]);
3018 res_digits[ri + 1] = guess;
3031 sub_abs(÷nd, &divisor[guess], ÷nd);
3033 first_nextdigit = dividend.weight - weight_tmp;
3035 if (first_nextdigit >= 0 && first_nextdigit < dividend.ndigits)
3036 first_have = dividend.digits[first_nextdigit];
3040 result->ndigits = ri + 1;
3041 if (ri == res_ndigits + 1)
3043 int carry = (res_digits[ri] > 4) ? 1 : 0;
3045 result->ndigits = ri;
3048 while (carry && ri > 0)
3050 carry += res_digits[--ri];
3051 res_digits[ri] = carry % 10;
3056 while (result->ndigits > 0 && *(result->digits) == 0)
3060 (result->ndigits)--;
3062 while (result->ndigits > 0 && result->digits[result->ndigits - 1] == 0)
3063 (result->ndigits)--;
3064 if (result->ndigits == 0)
3065 result->sign = NUMERIC_POS;
3071 digitbuf_free(dividend.buf);
3072 for (i = 1; i < 10; i++)
3073 digitbuf_free(divisor[i].buf);
3080 * Calculate the modulo of two numerics at variable level
3084 mod_var(NumericVar *var1, NumericVar *var2, NumericVar *result)
3087 int save_global_rscale;
3092 * We do it by fiddling around with global_rscale and truncating
3093 * the result of the division.
3096 save_global_rscale = global_rscale;
3097 global_rscale = var2->rscale + 2;
3099 div_var(var1, var2, &tmp);
3100 tmp.rscale = var2->rscale;
3101 tmp.ndigits = MAX(0, MIN(tmp.ndigits, tmp.weight + tmp.rscale + 1));
3103 global_rscale = var2->rscale;
3104 mul_var(var2, &tmp, &tmp);
3106 sub_var(var1, &tmp, result);
3108 global_rscale = save_global_rscale;
3116 * Return the smallest integer greater than or equal to the argument
3121 ceil_var(NumericVar *var, NumericVar *result)
3126 set_var_from_var(var, &tmp);
3129 tmp.ndigits = MIN(tmp.ndigits, MAX(0, tmp.weight + 1));
3130 if (tmp.sign == NUMERIC_POS && cmp_var(var, &tmp) != 0)
3131 add_var(&tmp, &const_one, &tmp);
3133 set_var_from_var(&tmp, result);
3141 * Return the largest integer equal to or less than the argument
3146 floor_var(NumericVar *var, NumericVar *result)
3151 set_var_from_var(var, &tmp);
3154 tmp.ndigits = MIN(tmp.ndigits, MAX(0, tmp.weight + 1));
3155 if (tmp.sign == NUMERIC_NEG && cmp_var(var, &tmp) != 0)
3156 sub_var(&tmp, &const_one, &tmp);
3158 set_var_from_var(&tmp, result);
3166 * Compute the square root of x using Newtons algorithm
3170 sqrt_var(NumericVar *arg, NumericVar *result)
3174 NumericVar last_val;
3176 int save_global_rscale;
3179 save_global_rscale = global_rscale;
3181 res_rscale = global_rscale;
3183 stat = cmp_var(arg, &const_zero);
3186 set_var_from_var(&const_zero, result);
3187 result->rscale = res_rscale;
3188 result->sign = NUMERIC_POS;
3193 elog(ERROR, "math error on numeric - cannot compute SQRT of negative value");
3197 init_var(&last_val);
3199 set_var_from_var(arg, &tmp_arg);
3200 set_var_from_var(result, &last_val);
3203 * Initialize the result to the first guess
3206 digitbuf_free(result->buf);
3207 result->buf = digitbuf_alloc(1);
3208 result->digits = result->buf;
3209 result->digits[0] = tmp_arg.digits[0] / 2;
3210 if (result->digits[0] == 0)
3211 result->digits[0] = 1;
3212 result->ndigits = 1;
3213 result->weight = tmp_arg.weight / 2;
3214 result->rscale = res_rscale;
3215 result->sign = NUMERIC_POS;
3219 div_var(&tmp_arg, result, &tmp_val);
3221 add_var(result, &tmp_val, result);
3222 div_var(result, &const_two, result);
3224 if (cmp_var(&last_val, result) == 0)
3226 set_var_from_var(result, &last_val);
3229 free_var(&last_val);
3233 global_rscale = save_global_rscale;
3234 div_var(result, &const_one, result);
3241 * Raise e to the power of x
3245 exp_var(NumericVar *arg, NumericVar *result)
3256 int save_global_rscale;
3264 set_var_from_var(arg, &x);
3266 if (x.sign == NUMERIC_NEG)
3269 x.sign = NUMERIC_POS;
3272 save_global_rscale = global_rscale;
3274 for (i = x.weight, d = 0; i >= 0; i--, d++)
3276 global_rscale *= 10;
3278 global_rscale += x.digits[d];
3279 if (global_rscale >= 1000)
3280 elog(ERROR, "argument for EXP() too big");
3283 global_rscale = global_rscale / 2 + save_global_rscale + 8;
3285 while (cmp_var(&x, &const_one) > 0)
3289 div_var(&x, &const_two, &x);
3292 add_var(&const_one, &x, result);
3293 set_var_from_var(&x, &xpow);
3294 set_var_from_var(&const_one, &ifac);
3295 set_var_from_var(&const_one, &ni);
3297 for (i = 2; TRUE; i++)
3299 add_var(&ni, &const_one, &ni);
3300 mul_var(&xpow, &x, &xpow);
3301 mul_var(&ifac, &ni, &ifac);
3302 div_var(&xpow, &ifac, &elem);
3304 if (elem.ndigits == 0)
3307 add_var(result, &elem, result);
3311 mul_var(result, result, result);
3313 global_rscale = save_global_rscale;
3315 div_var(&const_one, result, result);
3317 div_var(result, &const_one, result);
3319 result->sign = NUMERIC_POS;
3332 * Compute the natural log of x
3336 ln_var(NumericVar *arg, NumericVar *result)
3344 int save_global_rscale;
3346 if (cmp_var(arg, &const_zero) <= 0)
3347 elog(ERROR, "math error on numeric - cannot compute LN of value <= zero");
3349 save_global_rscale = global_rscale;
3358 set_var_from_var(&const_two, &fact);
3359 set_var_from_var(arg, &x);
3361 while (cmp_var(&x, &const_two) >= 0)
3364 mul_var(&fact, &const_two, &fact);
3366 set_var_from_str("0.5", &elem);
3367 while (cmp_var(&x, &elem) <= 0)
3370 mul_var(&fact, &const_two, &fact);
3373 sub_var(&x, &const_one, result);
3374 add_var(&x, &const_one, &elem);
3375 div_var(result, &elem, result);
3376 set_var_from_var(result, &xx);
3377 mul_var(result, result, &x);
3379 set_var_from_var(&const_one, &ni);
3381 for (i = 2; TRUE; i++)
3383 add_var(&ni, &const_two, &ni);
3384 mul_var(&xx, &x, &xx);
3385 div_var(&xx, &ni, &elem);
3387 if (cmp_var(&elem, &const_zero) == 0)
3390 add_var(result, &elem, result);
3393 global_rscale = save_global_rscale;
3394 mul_var(result, &fact, result);
3407 * Compute the logarithm of x in a given base
3411 log_var(NumericVar *base, NumericVar *num, NumericVar *result)
3421 ln_var(base, &ln_base);
3422 ln_var(num, &ln_num);
3426 div_var(&ln_num, &ln_base, result);
3436 * Raise base to the power of exp
3440 power_var(NumericVar *base, NumericVar *exp, NumericVar *result)
3444 int save_global_rscale;
3446 save_global_rscale = global_rscale;
3447 global_rscale += global_rscale / 3 + 8;
3452 ln_var(base, &ln_base);
3453 mul_var(&ln_base, exp, &ln_num);
3455 global_rscale = save_global_rscale;
3457 exp_var(&ln_num, result);
3465 /* ----------------------------------------------------------------------
3467 * Following are the lowest level functions that operate unsigned
3468 * on the variable level
3470 * ----------------------------------------------------------------------
3477 * Compare the absolute values of var1 and var2
3478 * Returns: -1 for ABS(var1) < ABS(var2)
3479 * 0 for ABS(var1) == ABS(var2)
3480 * 1 for ABS(var1) > ABS(var2)
3484 cmp_abs(NumericVar *var1, NumericVar *var2)
3488 int w1 = var1->weight;
3489 int w2 = var2->weight;
3492 while (w1 > w2 && i1 < var1->ndigits)
3494 if (var1->digits[i1++] != 0)
3498 while (w2 > w1 && i2 < var2->ndigits)
3500 if (var2->digits[i2++] != 0)
3507 while (i1 < var1->ndigits && i2 < var2->ndigits)
3509 stat = var1->digits[i1++] - var2->digits[i2++];
3519 while (i1 < var1->ndigits)
3521 if (var1->digits[i1++] != 0)
3524 while (i2 < var2->ndigits)
3526 if (var2->digits[i2++] != 0)
3537 * Add the absolute values of two variables into result.
3538 * result might point to one of the operands without danger.
3542 add_abs(NumericVar *var1, NumericVar *var2, NumericVar *result)
3544 NumericDigit *res_buf;
3545 NumericDigit *res_digits;
3555 res_weight = MAX(var1->weight, var2->weight) + 1;
3556 res_rscale = MAX(var1->rscale, var2->rscale);
3557 res_dscale = MAX(var1->dscale, var2->dscale);
3558 res_ndigits = res_rscale + res_weight + 1;
3559 if (res_ndigits <= 0)
3562 res_buf = digitbuf_alloc(res_ndigits);
3563 res_digits = res_buf;
3565 i1 = res_rscale + var1->weight + 1;
3566 i2 = res_rscale + var2->weight + 1;
3567 for (i = res_ndigits - 1; i >= 0; i--)
3571 if (i1 >= 0 && i1 < var1->ndigits)
3572 carry += var1->digits[i1];
3573 if (i2 >= 0 && i2 < var2->ndigits)
3574 carry += var2->digits[i2];
3576 res_digits[i] = carry % 10;
3580 while (res_ndigits > 0 && *res_digits == 0)
3586 while (res_ndigits > 0 && res_digits[res_ndigits - 1] == 0)
3589 if (res_ndigits == 0)
3592 digitbuf_free(result->buf);
3593 result->ndigits = res_ndigits;
3594 result->buf = res_buf;
3595 result->digits = res_digits;
3596 result->weight = res_weight;
3597 result->rscale = res_rscale;
3598 result->dscale = res_dscale;
3605 * Subtract the absolute value of var2 from the absolute value of var1
3606 * and store in result. result might point to one of the operands
3609 * ABS(var1) MUST BE GREATER OR EQUAL ABS(var2) !!!
3613 sub_abs(NumericVar *var1, NumericVar *var2, NumericVar *result)
3615 NumericDigit *res_buf;
3616 NumericDigit *res_digits;
3626 res_weight = var1->weight;
3627 res_rscale = MAX(var1->rscale, var2->rscale);
3628 res_dscale = MAX(var1->dscale, var2->dscale);
3629 res_ndigits = res_rscale + res_weight + 1;
3630 if (res_ndigits <= 0)
3633 res_buf = digitbuf_alloc(res_ndigits);
3634 res_digits = res_buf;
3636 i1 = res_rscale + var1->weight + 1;
3637 i2 = res_rscale + var2->weight + 1;
3638 for (i = res_ndigits - 1; i >= 0; i--)
3642 if (i1 >= 0 && i1 < var1->ndigits)
3643 borrow += var1->digits[i1];
3644 if (i2 >= 0 && i2 < var2->ndigits)
3645 borrow -= var2->digits[i2];
3649 res_digits[i] = borrow + 10;
3654 res_digits[i] = borrow;
3659 while (res_ndigits > 0 && *res_digits == 0)
3665 while (res_ndigits > 0 && res_digits[res_ndigits - 1] == 0)
3668 if (res_ndigits == 0)
3671 digitbuf_free(result->buf);
3672 result->ndigits = res_ndigits;
3673 result->buf = res_buf;
3674 result->digits = res_digits;
3675 result->weight = res_weight;
3676 result->rscale = res_rscale;
3677 result->dscale = res_dscale;