[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