[Python-checkins] r47281 - sandbox/trunk/decimal-c/_decimal.c sandbox/trunk/decimal-c/decimal.h
mateusz.rukowicz
python-checkins at python.org
Thu Jul 6 23:13:24 CEST 2006
Author: mateusz.rukowicz
Date: Thu Jul 6 23:13:23 2006
New Revision: 47281
Modified:
sandbox/trunk/decimal-c/_decimal.c
sandbox/trunk/decimal-c/decimal.h
Log:
Long exps now works, every test now passes. There are some fixes, polishes still needed. '//' are for my information, they will disappear.
Modified: sandbox/trunk/decimal-c/_decimal.c
==============================================================================
--- sandbox/trunk/decimal-c/_decimal.c (original)
+++ sandbox/trunk/decimal-c/_decimal.c Thu Jul 6 23:13:23 2006
@@ -521,41 +521,448 @@
return new_pos;
}
+static long
+_limb_normalize(long *first, long size) {
+ long i;
+ long new_size;
+
+ for (i = 0; i < size - 1; i++) {
+ first[i+1] += first[i] / BASE;
+ first[i] %= BASE;
+ }
+
+ new_size = size;
+
+ while (!first[new_size - 1] && new_size > 1) new_size --;
+
+ return new_size;
+}
+#ifdef BIG_EXP
+
+
+exp_t exp_from_i(long a) {
+ exp_t ret;
+
+ memset(ret.limbs, 0, sizeof(long) * EXP_LIMB_COUNT);
+ ret.limbs[0] = a;
+ ret.sign = 0;
+
+ if (a < 0) {
+ ret.sign = 1;
+ ret.limbs[0] *= -1;
+ }
+
+ ret.size = _limb_normalize(ret.limbs, EXP_LIMB_COUNT);
+
+ return ret;
+}
+
+int
+exp_sscanf(char *buf, exp_t *exp) {
+ int len;
+ long mul;
+ long limb;
+ long i;
+ exp->sign = 0;
+ exp->size = 1;
+ memset(exp->limbs, 0, sizeof(long) * EXP_LIMB_COUNT);
+
+ if (buf[0] == '-') {
+ exp->sign = 1;
+ buf ++;
+ }
+ else if (buf[0] == '+')
+ buf ++;
+
+ len = strlen(buf);
+ if (!len)
+ return 0;
+
+ while (buf[0] == '0') {
+ buf ++;
+ }
+ len = strlen(buf);
+
+ mul = 1;
+ limb = 0;
+
+ for (i = len-1; i>=0 ;i--) {
+ if (buf[i] < '0' && buf[i] > '9')
+ return 0;
+
+ exp->size = limb + 1;
+ if (limb >= EXP_LIMB_COUNT)
+ return 0;
+
+ exp->limbs[limb] += mul * (buf[i] - '0');
+
+ mul *= 10;
+ if (mul == BASE) {
+ limb ++;
+ mul = 1;
+ }
+ }
+
+ return 1;
+}
+
+int
+exp_sprintf(char *buf, exp_t exp) {
+ int written = 0;
+ int tmp;
+ long i;
+
+ if (exp.sign) {
+ buf[0] = '-';
+ buf ++;
+ written ++;
+ }
+
+ tmp = sprintf(buf, "%i", exp.limbs[exp.size-1]);
+ buf += tmp;
+ written += tmp;
+ for (i = exp.size - 2; i>=0; i--) {
+ tmp = sprintf(buf, "%."LOG_STR"i", exp.limbs[i]);
+ buf += tmp;
+ written += tmp;
+ }
+ buf[0] = '\0';
+
+ return written;
+}
+
+/* there is no overflow checking !*/
+long
+exp_to_i(exp_t exp) {
+ long mult;
+ long i;
+ long ret = 0;
+ long mul = 1;
+ mult = 1;
+ for (i=0; i<LOG; i++) {
+ mult *= 10;
+ }
+
+ for (i=0;i<exp.size;i++) {
+ ret -= exp.limbs[i] * mul;
+ mul *= mult;
+ }
+
+ if (!exp.sign)
+ ret *= -1;
+
+ return ret;
+}
+
+exp_t
+exp_inp_add(exp_t *a, exp_t b) {
+ if (a->sign == b.sign) {
+ a->size = _limb_add(a->limbs, a->size * LOG, b.limbs, b.size * LOG, a->limbs);
+ a->size = (a->size + LOG - 1) / LOG;
+ }
+ else {
+ int cmp;
+ cmp = _limb_compare(a->limbs, a->size, b.limbs, b.size);
+
+ if (cmp == 0) {
+ memset(a->limbs, 0, sizeof(long) * a->size);
+ a->size = 1;
+ a->sign = 0;
+ }
+
+ if (cmp == 1) {
+ a->size = _limb_sub_sl(a->limbs, a->size, b.limbs, b.size);
+ }
+
+ if (cmp == -1) {
+ exp_t tmp;
+ memset(tmp.limbs, 0, sizeof(long) * EXP_LIMB_COUNT);
+ tmp.size = _limb_sub(b.limbs, b.size * LOG, a->limbs, a->size * LOG, tmp.limbs);
+ tmp.size = (tmp.size + LOG -1) / LOG;
+ *a = tmp;
+ a->sign = b.sign;
+ }
+
+ }
+
+ return *a;
+}
+
+exp_t
+exp_inp_sub(exp_t *a, exp_t b) {
+ exp_t tmp_b = b;
+ tmp_b.sign ^= 1;
+ if (tmp_b.limbs[0] == 0 && tmp_b.size == 1)
+ tmp_b.sign =0;
+
+ return exp_inp_add(a, tmp_b);
+}
+
+exp_t
+exp_add(exp_t a, exp_t b) {
+ return exp_inp_add(&a, b);
+}
+
+exp_t
+exp_sub(exp_t a, exp_t b) {
+ return exp_inp_sub(&a, b);
+}
+
+exp_t
+exp_add_i(exp_t a, long b) {
+ return exp_add(a, exp_from_i(b));
+}
+
+exp_t
+exp_sub_i(exp_t a, long b) {
+ return exp_sub(a, exp_from_i(b));
+}
+
+exp_t
+exp_inp_add_i(exp_t *a, long b) {
+ return exp_inp_add(a, exp_from_i(b));
+}
+
+exp_t
+exp_inp_sub_i(exp_t *a, long b) {
+ return exp_inp_sub(a, exp_from_i(b));
+}
+
+exp_t
+exp_inc(exp_t *a) {
+ return exp_inp_add(a, exp_from_i(1));
+}
+
+exp_t
+exp_dec(exp_t *a) {
+ return exp_inp_sub(a, exp_from_i(1));
+}
+
+exp_t
+exp_mul(exp_t a, exp_t b) {
+ exp_t ret;
+ memset(ret.limbs, 0, sizeof(long) *EXP_LIMB_COUNT);
+ ret.size = _limb_multiply_core(a.limbs, a.size, b.limbs, b.size, ret.limbs);
+ ret.sign = a.sign ^ b.sign;
+ if (ret.size == 1 && ret.limbs[0] == 0)
+ ret.sign = 0;
+ return ret;
+}
+
+exp_t
+exp_mul_i(exp_t a, long b) {
+ return exp_mul(a, exp_from_i(b));
+}
+
+exp_t
+exp_div_i(exp_t a, long b, long *remainder) {
+ exp_t ret;
+ long i;
+ long mult = 1;
+ for (i=0 ; i<LOG ;i++)
+ mult *= 10;
+
+ memset(ret.limbs, 0, sizeof(long) * EXP_LIMB_COUNT);
+ *remainder = 0;
+
+ for (i = a.size - 1; i>=0; i--) {
+ *remainder *= mult;
+ *remainder += a.limbs[i];
+ ret.limbs[i] = *remainder / b;
+ *remainder %= b;
+ }
+
+ ret.size = EXP_LIMB_COUNT;
+ while (!ret.limbs[ret.size-1] && ret.size > 1) ret.size --;
+ ret.sign = a.sign ^ (b < 0);
+
+ if (ret.limbs[0] == 0 && ret.size == 1)
+ ret.sign = 0;
+
+ return ret;
+}
+
+/* TODO */
+exp_t
+exp_floordiv_i(exp_t a, long b) {
+ long remainder;
+ exp_t ret;
+ ret = exp_div_i(a, b, &remainder);
+ if (remainder && exp_is_neg(a))
+ exp_dec(&ret);
+
+ return ret;
+}
+
+/* TODO */
+int
+exp_mod_i(exp_t a, long b) {
+ long remainder;
+ exp_div_i(a, b, &remainder);
+ return remainder;
+}
+
+int
+exp_cmp(exp_t a, exp_t b) {
+ int cmp;
+ if (a.sign != b.sign) {
+ if (a.sign)
+ return -1;
+ else
+ return 1;
+ }
+
+ cmp = _limb_compare(a.limbs, a.size, b.limbs, b.size);
+ if (a.sign)
+ return -cmp;
+ else
+ return cmp;
+}
+
+int
+exp_cmp_i(exp_t a, long b) {
+ return exp_cmp(a, exp_from_i(b));
+}
+
+int
+exp_g(exp_t a, exp_t b) {
+ int cmp = exp_cmp(a, b);
+ return cmp == 1;
+}
+
+int
+exp_g_i(exp_t a, long b) {
+ return exp_g(a, exp_from_i(b));
+}
+
+int
+exp_l(exp_t a, exp_t b) {
+ int cmp = exp_cmp(a, b);
+ return cmp == -1;
+}
+
+int
+exp_l_i(exp_t a, long b) {
+ return exp_l(a, exp_from_i(b));
+}
+
+int
+exp_eq(exp_t a, exp_t b) {
+ int cmp = exp_cmp(a, b);
+ return cmp == 0;
+}
+
+int
+exp_eq_i(exp_t a, long b) {
+ return exp_eq(a, exp_from_i(b));
+}
-#define exp_add_i(exp, a) ((exp) + (a))
-#define exp_add(a, b) ((a) + (b))
-#define exp_inc(a) ((*a)++)
-#define exp_dec(a) ((*a)--)
-#define exp_is_zero(a) ((a) == 0)
-#define exp_is_neg(a) ((a) < 0)
-#define exp_is_pos(a) ((a) > 0)
-#define exp_inp_add(a,b) ((*(a)) += (b))
-#define exp_to_int(a) (a)
-#define exp_to_i(a) (a)
-#define exp_from_i(a) (a)
-#define exp_sub_i(exp, a) ((exp) - (a))
-#define exp_sub(a, b) ((a) - (b))
-#define exp_g(a, b) ((a) > (b))
-#define exp_l(a, b) ((a) < (b))
-#define exp_ge(a, b) ((a) >= (b))
-#define exp_eq(a, b) ((a) == (b))
-#define exp_ne(a, b) ((a) != (b))
-#define exp_g_i(a, b) ((a) > (b))
-#define exp_l_i(a, b) ((a) < (b))
-#define exp_ge_i(a, b) ((a) >= (b))
-#define exp_le_i(a, b) ((a) <= (b))
+int
+exp_ne(exp_t a, exp_t b) {
+ int cmp = exp_cmp(a, b);
+ return cmp != 0;
+}
+
+int
+exp_ne_i(exp_t a, long b) {
+ return exp_ne(a, exp_from_i(b));
+}
+
+int
+exp_ge(exp_t a, exp_t b) {
+ int cmp = exp_cmp(a, b);
+ return (cmp == 1) || (cmp == 0);
+}
+
+int
+exp_ge_i(exp_t a, long b) {
+ return exp_ge(a, exp_from_i(b));
+}
+
+int
+exp_le(exp_t a, exp_t b) {
+ int cmp = exp_cmp(a, b);
+ return (cmp == -1) || (cmp == 0);
+}
+
+int exp_le_i(exp_t a, long b) {
+ return exp_le(a, exp_from_i(b));
+}
+
+int exp_is_zero(exp_t a) {
+ return a.limbs[0] == 0 && a.size == 1;
+}
+
+int exp_is_neg(exp_t a) {
+ return !exp_is_zero(a) && a.sign == 1;
+}
+
+int exp_is_pos(exp_t a) {
+ return !exp_is_zero(a) && a.sign == 0;
+}
+
+exp_t
+exp_neg(exp_t a) {
+ a.sign ^= 1;
+ if (a.limbs[0] == 0 && a.size == 1)
+ a.sign = 0;
+ return a;
+}
+
+exp_t
+exp_min(exp_t a, exp_t b) {
+ int cmp = exp_cmp(a, b);
+ if (cmp == 1)
+ return b;
+ else
+ return a;
+}
+
+exp_t
+exp_max(exp_t a, exp_t b) {
+ int cmp = exp_cmp(a, b);
+ if(cmp == 1)
+ return a;
+ else
+ return b;
+}
+
+#else
+#define exp_add_i(exp, a) ((exp) + (a)) //
+#define exp_add(a, b) ((a) + (b)) //
+#define exp_inc(a) ((*a)++) //
+#define exp_dec(a) ((*a)--) //
+#define exp_is_zero(a) ((a) == 0) //
+#define exp_is_neg(a) ((a) < 0) //
+#define exp_is_pos(a) ((a) > 0) //
+#define exp_inp_add(a,b) ((*(a)) += (b)) //
+#define exp_to_int(a) (a) //
+#define exp_to_i(a) (a) //
+#define exp_from_i(a) (a) //
+#define exp_sub_i(exp, a) ((exp) - (a)) //
+#define exp_sub(a, b) ((a) - (b)) //
+#define exp_g(a, b) ((a) > (b)) //
+#define exp_l(a, b) ((a) < (b)) //
+#define exp_ge(a, b) ((a) >= (b)) //
+#define exp_eq(a, b) ((a) == (b)) //
+#define exp_eq_i(a, b) ((a) == (b)) //
+#define exp_ne(a, b) ((a) != (b)) //
+#define exp_g_i(a, b) ((a) > (b)) //
+#define exp_l_i(a, b) ((a) < (b)) //
+#define exp_ge_i(a, b) ((a) >= (b)) //
+#define exp_le_i(a, b) ((a) <= (b)) //
#define exp_mod_i(a, b) ((a) % (b))
-#define exp_ge_i(a, b) ((a) >= (b))
+#define exp_ge_i(a, b) ((a) >= (b)) //
#define exp_floordiv_i(a,b) ((a) / (b) - ((a) % (b) && (a) < 0))
-#define exp_inp_sub(a, b) ((*(a)) -= (b))
-#define exp_inp_sub_i(a, b) ((*(a)) -= (b))
-#define exp_sprintf(a, e) (sprintf(a, "%d", e))
-#define exp_sscanf(a, e) (sscanf(a, "%d", e))
-#define exp_min(a, b) ((a) < (b) ? (a) : (b))
-#define exp_max(a, b) ((a) > (b) ? (a) : (b))
-#define exp_neg(a) (-(a))
-#define exp_mul_i(a, b) ((a) * (b))
-
+#define exp_inp_sub(a, b) ((*(a)) -= (b)) //
+#define exp_inp_sub_i(a, b) ((*(a)) -= (b)) //
+#define exp_sprintf(a, e) (sprintf(a, "%d", e)) //
+#define exp_sscanf(a, e) (sscanf(a, "%d", e)) //
+#define exp_min(a, b) ((a) < (b) ? (a) : (b)) //
+#define exp_max(a, b) ((a) > (b) ? (a) : (b)) //
+#define exp_neg(a) (-(a)) //
+#define exp_mul_i(a, b) ((a) * (b)) //
+#endif
/* helpful macros ************************************************************/
@@ -720,7 +1127,7 @@
static PyObject *decimal_from_long(PyTypeObject *, long);
static PyObject *decimal_str(decimalobject *);
static PyObject *_do_decimal_str(decimalobject *, contextobject *, int);
-static decimalobject *_new_decimalobj(PyTypeObject *, long, char, long);
+static decimalobject *_new_decimalobj(PyTypeObject *, long, char, exp_t);
static decimalobject *_do_decimal_subtract(decimalobject *, decimalobject *, contextobject *);
static contextobject *context_shallow_copy(contextobject *);
static PyObject *context_ignore_all_flags(contextobject *);
@@ -776,7 +1183,7 @@
else
sign = SIGN_POSNAN;
- res = _new_decimalobj(type, thing->ob_size, sign, 0);
+ res = _new_decimalobj(type, thing->ob_size, sign, exp_from_i(0));
if (!res) return NULL;
for (i = 0; i < thing->ob_size; i++)
res->digits[i] = thing->digits[i]; /* DELETE */
@@ -890,7 +1297,7 @@
res = (decimalobject *)PyDecimal_Inf;
else {
res = _new_decimalobj(type, ctx->prec,
- lsign, ctx->Emax - ctx->prec + 1);
+ lsign, exp_sub_i(ctx->Emax, ctx->prec - 1));
if (res) {
for (i = 0; i < ctx->prec; i++)
res->digits[i] = 9;
@@ -903,7 +1310,7 @@
res = (decimalobject *)PyDecimal_NegInf;
else {
res = _new_decimalobj(type, ctx->prec,
- lsign, ctx->Emax - ctx->prec + 1);
+ lsign, exp_sub_i(ctx->Emax, ctx->prec - 1));
if (res) {
for (i = 0; i < ctx->prec; i++)
res->digits[i] = 9;
@@ -1123,7 +1530,7 @@
contextobject *ctx, decimalobject *tmp)
{
decimalobject *new;
- assert(expdiff > 0);
+ assert(exp_g_i(expdiff, 0));
if(self->ob_size > prec && _limb_get_digit(self->limbs, self->ob_size, prec) >= 5){ /* SLOW */
new = _decimal_increment(tmp, 1, ctx);
Py_DECREF(tmp);
@@ -1146,7 +1553,7 @@
{
long i, last;
decimalobject *tmp;
- assert(expdiff > 0);
+ assert(exp_g_i(expdiff, 0));
tmp = _NEW_decimalobj(prec, self->sign, exp_add(self->exp, expdiff));
if (!tmp) return NULL;
for (i = 0; i < prec; i++)
@@ -1170,7 +1577,7 @@
{
decimalobject *tmp;
long i, last;
- assert(expdiff > 0);
+ assert(exp_g_i(expdiff, 0));
tmp = _NEW_decimalobj(prec, self->sign, exp_add(self->exp, expdiff));
if (!tmp) return NULL;
for (i = 0; i < prec; i++)
@@ -1225,7 +1632,7 @@
/* Mapping rounding constants to functions. Since in C this can be indexed with
any value, it's important to check the rounding constants before! */
-typedef decimalobject*(*round_func)(decimalobject *, long, long, contextobject *);
+typedef decimalobject*(*round_func)(decimalobject *, long, exp_t, contextobject *);
static round_func round_funcs[] = {
_round_down, _round_up, _round_half_down, _round_half_even,
_round_half_up, _round_floor, _round_ceiling
@@ -1324,7 +1731,7 @@
}
/* Maybe all the lost digits are 0. */
- for (i = self->ob_size - exp_to_int(expdiff); i < self->ob_size; i++) {
+ for (i = self->ob_size - exp_to_i(expdiff); i < self->ob_size; i++) {
if(_limb_get_digit(self->limbs, self->ob_size, i) > 0)
goto no_way;
}
@@ -1387,7 +1794,7 @@
decimalobject *ans = NULL, *tmp;
int ret;
exp_t diff;
- long adj;
+ exp_t adj;
long digits, i;
if (ISSPECIAL(self)) {
@@ -1414,7 +1821,7 @@
}
diff = exp_sub(self->exp, exp);
- digits = exp_to_int(exp_add_i(diff, self->ob_size));
+ digits = exp_to_i(exp_add_i(diff, self->ob_size));
if (watchexp && ctx->prec < digits)
return handle_InvalidOperation(self->ob_type, ctx,
@@ -1457,10 +1864,10 @@
adj = ADJUSTED(tmp);
if (decimal_nonzero(tmp)) {
- if (adj < ctx->Emin) {
+ if (exp_l(adj, ctx->Emin)) {
if (handle_Subnormal(ctx, NULL) != 0)
return NULL;
- } else if (adj > ctx->Emax) {
+ } else if (exp_g(adj, ctx->Emax)) {
ans = handle_InvalidOperation(self->ob_type, ctx,
"rescale(a, INF)", NULL);
Py_DECREF(tmp);
@@ -2036,7 +2443,7 @@
return dup;
if (!decimal_nonzero(dup)) {
- new = _NEW_decimalobj(1, dup->sign, 0);
+ new = _NEW_decimalobj(1, dup->sign, exp_from_i(0));
Py_DECREF(dup);
if (!new) return NULL;
new->limbs[0] = 0;
@@ -2183,7 +2590,7 @@
{
- decimalobject *two = _NEW_decimalobj(1, 0, 0);
+ decimalobject *two = _NEW_decimalobj(1, 0, exp_from_i(0));
if (!two) {
PyObject *r = context_regard_flags(ctx2, flags);
Py_XDECREF(r);
@@ -2293,7 +2700,7 @@
{
decimalobject *one;
decimalobject *tmp;
- one = _NEW_decimalobj(1,0,0);
+ one = _NEW_decimalobj(1,0,exp_from_i(0));
if (!one)
goto err;
@@ -2457,7 +2864,7 @@
}
if (!decimal_nonzero(self)) {
- ret = _NEW_decimalobj(1, 0, 0);
+ ret = _NEW_decimalobj(1, 0, exp_from_i(0));
if (!ret)
return NULL;
@@ -2815,7 +3222,7 @@
/* XXX: slow? */
rnd = _set_flag(ctx->ignored, S_ROUNDED, 1);
inex =_set_flag(ctx->ignored, S_INEXACT, 1);
- ans = _decimal_rescale(self, 0, ctx, rounding, 1);
+ ans = _decimal_rescale(self, exp_from_i(0), ctx, rounding, 1);
if (!rnd) _set_flag(ctx->ignored, S_ROUNDED, rnd);
if (!inex) _set_flag(ctx->ignored, S_INEXACT, inex);
return ans;
@@ -2900,7 +3307,8 @@
return PyInt_FromLong(0);
/* XXX: Overflow? */
- return PyInt_FromSsize_t(ADJUSTED(self));
+ /* EXP TODO */
+ return PyInt_FromSsize_t(exp_to_i(ADJUSTED(self)));
}
@@ -2920,8 +3328,9 @@
PyTuple_SET_ITEM(digits, i, d);
}
+ /* TODO EXP */
if(!ISINF(self))
- res = Py_BuildValue("(bOn)", self->sign % 2, digits, self->exp);
+ res = Py_BuildValue("(bOn)", self->sign % 2, digits, exp_to_i(self->exp));
else {
inf = PyString_FromString("F");
if (!inf) {
@@ -3059,7 +3468,7 @@
{
char *outbuf;
int buflen, i;
- int dotplace;
+ exp_t dotplace;
exp_t adjexp;
int append_E = 0, append_adjexp = 0;
long extra_zeros=0;
@@ -3101,41 +3510,49 @@
/* why is that like? well, d->exp moves dot right, d->ob_size moves dot right
* and adjexp moves dot left */
adjexp = exp_from_i(0);
- dotplace = d->exp + d->ob_size;
+ dotplace = exp_add_i(d->exp, d->ob_size);
/* dotplace must be at most d->ob_size (no dot at all) and at last -5 (6 pre-zeros)*/
- if(dotplace >d->ob_size || dotplace <-5)
+// if(dotplace >d->ob_size || dotplace <-5)
+ if (exp_g_i(dotplace, d->ob_size) || exp_l_i(dotplace, -5))
{
/* ok, we have to put dot after 1 digit, that is dotplace = 1
* we compute adjexp from equation (1) */
- dotplace = 1;
+ dotplace = exp_from_i(1);
// adjexp = -dotplace + d->exp + d->ob_size;
- adjexp = exp_add_i(d->exp, d->ob_size - dotplace);
+ adjexp = exp_add_i(exp_sub(d->exp,dotplace), d->ob_size);
}
if(engineering) /* we have to be sure, adjexp%3 == 0 */
while(exp_mod_i(adjexp,3))
{
exp_dec(&adjexp);
- dotplace ++;
+ exp_inc(&dotplace);
}
/* now all we have to do, is to put it to the string =] */
- if(dotplace > d->ob_size)
- extra_zeros = dotplace - d->ob_size;
+// if(dotplace > d->ob_size)
+ if (exp_g_i(dotplace, d->ob_size))
+ extra_zeros = exp_to_i(exp_sub_i(dotplace, d->ob_size));
- if(dotplace <= 0)
+// if(dotplace <= 0)
+ if (exp_le_i(dotplace, 0))
{
*p++ = '0';
*p++ = '.';
- while(dotplace++ < 0)
+// while(dotplace++ < 0)
+// *p++ = '0';
+ while (exp_l_i(dotplace, 0)) {
+ exp_inc(&dotplace);
*p++ = '0';
- dotplace = -1;
+ }
+
+ dotplace = exp_from_i(-1);
}
for(i = 0;i<d->ob_size;i++)
{
- if(dotplace == i)
+ if(exp_eq_i(dotplace, i))
*p++ = '.';
p += sprintf(p, "%d", _limb_get_digit(d->limbs,d->ob_size,i));
}
@@ -3264,7 +3681,7 @@
int inf_sign;
inf_sign = sign ? SIGN_NEGINF : SIGN_POSINF;
- inf = _NEW_decimalobj(1, inf_sign, 0);
+ inf = _NEW_decimalobj(1, inf_sign, exp_from_i(0));
if (!inf)
return NULL;
@@ -3288,7 +3705,7 @@
else if (divmod == 2) {
decimalobject *nan;
- nan = _NEW_decimalobj(1, SIGN_POSNAN, 0);
+ nan = _NEW_decimalobj(1, SIGN_POSNAN, exp_from_i(0));
if (!nan) {
Py_DECREF(inf);
return NULL;
@@ -3310,7 +3727,7 @@
if (ISINF(other)) {
if (divmod) {
decimalobject *ans1, *ans2;
- ans1 = _NEW_decimalobj(1, sign, 0);
+ ans1 = _NEW_decimalobj(1, sign, exp_from_i(0));
if (!ans1)
return NULL;
@@ -3363,7 +3780,7 @@
return NULL;
//ans2->exp = self->exp < other->exp ? self->exp : other->exp;
ans2->exp = exp_min(self->exp, other->exp);
- ans1 = _NEW_decimalobj(1, sign, 0);
+ ans1 = _NEW_decimalobj(1, sign, exp_from_i(0));
if (!ans1) {
Py_DECREF(ans2);
return NULL;
@@ -3439,7 +3856,7 @@
if (cmp == -1) {
decimalobject *ans1, *ans2;
- ans1 = _NEW_decimalobj(1, sign, 0);
+ ans1 = _NEW_decimalobj(1, sign, exp_from_i(0));
if (!ans1)
return NULL;
ans1->limbs[0] = 0;
@@ -3546,7 +3963,7 @@
/* we create room for additional limb, in case remainder != 0
* then, we will just move results->limbs one left, and set first
* limb 1, to make rounding working properly */
- result = _NEW_decimalobj(significant_limbs * LOG + LOG, sign, 0);
+ result = _NEW_decimalobj(significant_limbs * LOG + LOG, sign, exp_from_i(0));
for (i = 0; i < result->limb_count; i++)
result->limbs[i] = 0;
@@ -3570,14 +3987,14 @@
else
min_expdiff = exp_from_i(op1->limb_count);
+ /* EXP TODO ?? (min_expdiff) */
expdiff = exp_from_i(_limb_divide(op1->limbs, op1->limb_count,
op2->limbs, op2->limb_count, result->limbs,
- significant_limbs, remainder, min_expdiff));
+ significant_limbs, remainder, exp_to_i(min_expdiff)));
result->limbs[significant_limbs] = 0;
// exp += expdiff * LOG + LOG;
exp_inp_add(&exp, exp_add_i(exp_mul_i(expdiff, LOG), LOG));
-
rlimbs = _limb_size(remainder, remainder_limbs);
/* remainder non-zero */
if (!(rlimbs == 1 && remainder[0] == 0)) {
@@ -3600,7 +4017,7 @@
}
if (divmod) {
- remainder_ret = _NEW_decimalobj(rlimbs * LOG, self->sign, 0);
+ remainder_ret = _NEW_decimalobj(rlimbs * LOG, self->sign, exp_from_i(0));
if (!remainder_ret) {
Py_DECREF(op1);
Py_DECREF(result);
@@ -3626,13 +4043,13 @@
max_size = op1->ob_size > op2->ob_size ? op1->ob_size : op2->ob_size;
/* adjusted is computed just like in the python code */
- adjusted = self->ob_size - other->ob_size + 1;
+ adjusted = exp_from_i(self->ob_size - other->ob_size + 1);
for (i = 0;i < max_size ;i++) {
long x1,x2;
x1 = _limb_get_digit(self->limbs, self->ob_size, i);
x2 = _limb_get_digit(other->limbs, other->ob_size, i);
if (x2 > x1) {
- adjusted --;
+ exp_dec(&adjusted);
break;
}
}
@@ -3642,7 +4059,7 @@
* have more than adjusted digits =] */
- while (result->ob_size > adjusted &&
+ while (exp_l_i(adjusted, result->ob_size) &&
_limb_get_digit(result->limbs, result->ob_size, result->ob_size -1) == 0) {
/* when int dividing, exp should be 0 */
if (exp_ge_i(result->exp, 0) && divmod)
@@ -3655,7 +4072,7 @@
result->limb_count = (result->ob_size + LOG -1)/LOG;
- if (exp_add_i(result->exp, result->ob_size) > ctx->prec && shouldround && divmod) {
+ if (exp_g_i(exp_add_i(result->exp, result->ob_size), ctx->prec) && shouldround && divmod) {
Py_DECREF(remainder_ret);
Py_DECREF(result);
Py_DECREF(op1);
@@ -3671,7 +4088,7 @@
contextobject *ctx2 = 0;
exp_t remainder_exp = exp_min(self->exp, other->exp);
decimalobject *rescaled_rem = 0;
- decimalobject *rescaled = _decimal_rescale(result, 0, ctx, -1, 0);
+ decimalobject *rescaled = _decimal_rescale(result, exp_from_i(0), ctx, -1, 0);
if (!rescaled) {
Py_DECREF(result);
Py_DECREF(remainder_ret);
@@ -3943,7 +4360,7 @@
}
if (!decimal_nonzero(self)) {
// oexp = other->exp - ctx->prec - 1;
- oexp = exp_sub(other->exp, ctx->prec + 1);
+ oexp = exp_sub_i(other->exp, ctx->prec + 1);
// exp = (exp > oexp ? exp : oexp);
exp = exp_max(exp, oexp);
res = _decimal_rescale(other, exp, ctx, 0, 0);
@@ -3958,7 +4375,7 @@
}
if (!decimal_nonzero(other)) {
// oexp = self->exp - ctx->prec - 1;
- oexp = exp_sub(self->exp, ctx->prec + 1);
+ oexp = exp_sub_i(self->exp, ctx->prec + 1);
// exp = (exp > oexp ? exp : oexp);
exp = exp_max(exp, oexp);
res = _decimal_rescale(self, exp, ctx, 0, 0);
@@ -4184,7 +4601,7 @@
{
if(decimal_nonzero(other))
{
- ans = _NEW_decimalobj(1, resultsign ? SIGN_NEGINF : SIGN_POSINF, 0);
+ ans = _NEW_decimalobj(1, resultsign ? SIGN_NEGINF : SIGN_POSINF, exp_from_i(0));
return ans;
}
return handle_InvalidOperation(self->ob_type, ctx, "(+-)INF * 0", NULL);
@@ -4194,7 +4611,7 @@
{
if(decimal_nonzero(self))
{
- ans = _NEW_decimalobj(1, resultsign ? SIGN_NEGINF : SIGN_POSINF, 0);
+ ans = _NEW_decimalobj(1, resultsign ? SIGN_NEGINF : SIGN_POSINF, exp_from_i(0));
return ans;
}
return handle_InvalidOperation(self->ob_type, ctx, "0 * (+-)INF", NULL);
@@ -4349,9 +4766,9 @@
long spot;
int mod = modulo != Py_None;
long firstprec = ctx->prec;
- double a, b;
+ int cmp;
- if (ISINF(other) || ADJUSTED(other) > 8) {
+ if (ISINF(other) || exp_g_i(ADJUSTED(other), 8)) {
return handle_InvalidOperation(self->ob_type, ctx, "x ** INF", NULL);
}
@@ -4371,7 +4788,7 @@
}
if (!decimal_nonzero(other)) {
- ret = _NEW_decimalobj(1, 0, 0);
+ ret = _NEW_decimalobj(1, 0, exp_from_i(0));
ret->limbs[0] = 1;
return ret;
}
@@ -4398,7 +4815,7 @@
"INF % x", NULL);
}
- ret = _NEW_decimalobj(1, sign, 0);
+ ret = _NEW_decimalobj(1, sign, exp_from_i(0));
ret->limbs[0] = 0;
if (n > 0)
@@ -4408,11 +4825,23 @@
}
/* XXX temporary solution */
- a = ((double) self->exp + (double) self->ob_size - (double) 1) * (double) n;
- b = ctx->Emax;
+ {
+#ifdef BIG_EXP
+ exp_t b;
+ exp_t a = exp_add_i(self->exp, self->ob_size - 1);
+ b = exp_mul_i(a, n);
+ cmp = exp_g(a, ctx->Emax);
+
+#else
+ double a,b;
+ a = ((double) self->exp + (double) self->ob_size - (double) 1) * (double) n;
+ b = ctx->Emax;
+ cmp = a > b;
+#endif
+ }
if (!mod && n > 0 && /* (self->exp + self->ob_size -1) * n > ctx->Emax && */
- a > b &&
+ cmp &&
decimal_nonzero(self)) {
if (handle_Rounded(ctx, NULL)) {
@@ -4442,12 +4871,12 @@
}
}
- if (!mod && ctx->prec > PyDecimal_DefaultContext->Emax) {
+ if (!mod && exp_l_i(PyDecimal_DefaultContext->Emax, ctx->prec)) {
ctx->prec = firstprec;
return handle_Overflow(self->ob_type, ctx, "Too much precision", sign);
}
mul = _decimal_get_copy(self);
- val = _NEW_decimalobj(1,0,0);
+ val = _NEW_decimalobj(1,0,exp_from_i(0));
val->limbs[0] = 1;
if(!val || !mul) {
@@ -4691,7 +5120,7 @@
char *buf;
PyObject *res;
- max = exp_to_i(self->ob_size) + self->exp;
+ max = exp_to_i(self->exp) + self->ob_size;
buf = PyMem_MALLOC(max + 2); /* with sign */
if (!buf) return NULL;
@@ -4836,7 +5265,7 @@
* whether the fractional part consists only of zeroes. */
i = exp_from_i(d->ob_size-1);
cmp = exp_add_i(d->exp, d->ob_size);
- for (; exp_ge(i, cmp); --i) {
+ for (; exp_ge(i, cmp); exp_dec(&i)) {
/* if (d->digits[i] > 0)*/
if(_limb_get_digit(d->limbs, d->ob_size, exp_to_i(i)) > 0)
return 0;
@@ -5173,7 +5602,7 @@
v = value;
- new = _new_decimalobj(type, ndigits, (neg ? SIGN_NEG : SIGN_POS), 0);
+ new = _new_decimalobj(type, ndigits, (neg ? SIGN_NEG : SIGN_POS), exp_from_i(0));
if (!new) return NULL;
while (value) {
new->digits[ndigits-i-1] = value % 10;
@@ -5361,7 +5790,7 @@
return NULL;
if (value == NULL) {
- decimalobject *new = _new_decimalobj(type, 1, 0, 0);
+ decimalobject *new = _new_decimalobj(type, 1, 0, exp_from_i(0));
if (!new) return NULL;
new->digits[0] = 0;
new->limbs[0] = 0;
@@ -5868,14 +6297,16 @@
static PyObject *
context_Etiny(contextobject *self)
{
- return PyInt_FromSsize_t(ETINY(self));
+ /* TODO EXP */
+ return PyInt_FromSsize_t(exp_to_i(ETINY(self)));
}
static PyObject *
context_Etop(contextobject *self)
{
- return PyInt_FromSsize_t(ETOP(self));
+ /* TODO EXP */
+ return PyInt_FromSsize_t(exp_to_i(ETOP(self)));
}
@@ -6105,6 +6536,7 @@
}
+/* TODO EXP */
static PyObject *
context_reduce(contextobject *self)
{
@@ -6112,7 +6544,7 @@
return Py_BuildValue("(O(liiOOlliiO))", self->ob_type,
self->prec, self->rounding,
self->rounding_dec, self->traps, self->flags,
- self->Emin, self->Emax, self->capitals,
+ exp_to_i(self->Emin), exp_to_i(self->Emax), self->capitals,
self->clamp, self->ignored);
}
@@ -6579,7 +7011,9 @@
"traps", "flags", "Emin", "Emax",
"capitals", "_clamp", "_ignored_flags", 0};
long prec = LONG_MIN;
- long Emin = LONG_MAX, Emax = LONG_MIN;
+// long Emin = LONG_MAX, Emax = LONG_MIN;
+ long TEmin, TEmax;
+ exp_t Emin, Emax;
int rounding = -1, rounding_dec = -1, capitals = -1, clamp = 0;
PyObject *pytraps = NULL, *pyflags = NULL, *pyignored = NULL;
PyObject *tmp, *res = NULL;
@@ -6588,12 +7022,17 @@
PyObject *_ignored = NULL;
int i, j;
+ TEmin = LONG_MAX;
+ TEmax = LONG_MIN;
+ /* TODO EXP */
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|liiOOlliiO:Context", kwlist,
&prec, &rounding, &rounding_dec, &pytraps,
- &pyflags, &Emin, &Emax, &capitals, &clamp,
+ &pyflags, &TEmin, &TEmax, &capitals, &clamp,
&pyignored))
return NULL;
+ Emin = exp_from_i(TEmin);
+ Emax = exp_from_i(TEmax);
if (pytraps == NULL) {
_traps = PyDict_Copy(PyDecimal_DefaultContext->traps);
@@ -6609,6 +7048,7 @@
goto err;
else if (j == 1)
_set_flag(_traps, i, 1);
+ else _set_flag(_traps, i, 0);
}
} else {
for (i = 0; i < NUMSIGNALS; i++) {
@@ -6625,6 +7065,7 @@
goto err;
else if (j == 1)
_set_flag(_traps, i, 1);
+ else _set_flag(_traps, i, 0);
}
}
}
@@ -6695,10 +7136,10 @@
if (prec == LONG_MIN)
prec = PyDecimal_DefaultContext->prec;
- if (Emin == LONG_MAX)
+ if (exp_eq_i(Emin, LONG_MAX))
Emin = PyDecimal_DefaultContext->Emin;
- if (Emax == LONG_MIN)
+ if (exp_eq_i(Emax, LONG_MIN))
Emax = PyDecimal_DefaultContext->Emax;
if (capitals == -1)
@@ -6736,8 +7177,8 @@
static PyMemberDef context_members[] = {
{"prec", T_LONG, OFF(prec), 0},
- {"Emin", T_LONG, OFF(Emin), 0},
- {"Emax", T_LONG, OFF(Emax), 0},
+// {"Emin", T_LONG, OFF(Emin), 0},
+// {"Emax", T_LONG, OFF(Emax), 0},
{"capitals", T_INT, OFF(capitals), 0},
{"rounding", T_INT, OFF(rounding), 0},
{"_rounding_decision", T_INT, OFF(rounding_dec), 0},
@@ -6748,6 +7189,42 @@
{NULL}
};
+static PyObject *
+context_get_emax(contextobject *self) {
+ return PyInt_FromLong(exp_to_i(self->Emax));
+}
+
+
+/* TODO EXP */
+static int
+context_set_emax(contextobject *self, PyObject *value) {
+ long var = PyInt_AsLong(value);
+ if (PyErr_Occurred())
+ return -1;
+ self->Emax = exp_from_i(var);
+ return 0;
+}
+
+static PyObject *
+context_get_emin(contextobject *self) {
+ return PyInt_FromLong(exp_to_i(self->Emin));
+}
+
+/* TODO EXP */
+static int
+context_set_emin(contextobject *self, PyObject *value) {
+ long var = PyInt_AsLong(value);
+ if (PyErr_Occurred())
+ return -1;
+ self->Emin = exp_from_i(var);
+ return 0;
+}
+
+static PyGetSetDef context_getset[] = {
+ {"Emax", (getter) context_get_emax, (setter)context_set_emax},
+ {"Emin", (getter) context_get_emin, (setter)context_set_emin},
+ {NULL}
+};
/* XXX: If the dicts stay, Context might need to become a GC type */
@@ -6783,7 +7260,7 @@
0, /* tp_iternext */
context_methods, /* tp_methods */
context_members, /* tp_members */
- 0, /* tp_getset */
+ context_getset, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
@@ -6941,7 +7418,8 @@
_set_flag(traps, S_OVERFLOW, 1);
_set_flag(traps, S_INV_OPERATION, 1);
PyDecimal_DefaultContext = _new_contextobj(28, ROUND_HALF_EVEN, ALWAYS_ROUND,
- traps, NULL, -999999999L, 999999999L,
+ traps, NULL, exp_from_i(-999999999L),
+ exp_from_i(999999999L),
1, 0, NULL, 1);
if (!PyDecimal_DefaultContext)
return;
@@ -6954,7 +7432,8 @@
_set_flag(traps, S_UNDERFLOW, 1);
PyDecimal_BasicContext = _new_contextobj(9, ROUND_HALF_UP, ALWAYS_ROUND,
- traps, NULL, -999999999L, 999999999L,
+ traps, NULL, exp_from_i(-999999999L),
+ exp_from_i(999999999L),
1, 0, NULL, 1);
if (!PyDecimal_BasicContext)
return;
@@ -6963,7 +7442,8 @@
return;
PyDecimal_ExtendedContext = _new_contextobj(9, ROUND_HALF_EVEN, ALWAYS_ROUND,
- NULL, NULL, -999999999L, 999999999L,
+ NULL, NULL, exp_from_i(-999999999L),
+ exp_from_i(999999999L),
1, 0, NULL, 1);
if (!PyDecimal_ExtendedContext)
return;
Modified: sandbox/trunk/decimal-c/decimal.h
==============================================================================
--- sandbox/trunk/decimal-c/decimal.h (original)
+++ sandbox/trunk/decimal-c/decimal.h Thu Jul 6 23:13:23 2006
@@ -7,10 +7,23 @@
extern "C" {
#endif
+#define BIG_EXP
+
+
+#ifdef BIG_EXP
+#define EXP_LIMB_COUNT 10 /* maximal number of limbs per exp */
+typedef struct {
+ long limbs[EXP_LIMB_COUNT];
+ int sign;
+ int size;
+} exp_t;
+#else
#define exp_t long
+#endif
#define BASE 1000 /* biggest value of limb power of 10 */
#define LOG 3 /* number of digits per limb LOG = log10(BASE) */
+#define LOG_STR "3" /* any ideas how to avoid that? :P */
/* decimalobject struct ******************************************************/
typedef struct {
More information about the Python-checkins
mailing list