[Python-checkins] r47250 - sandbox/trunk/decimal-c/_decimal.c sandbox/trunk/decimal-c/decimal.h sandbox/trunk/decimal-c/test_decimal.py

mateusz.rukowicz python-checkins at python.org
Thu Jul 6 03:06:40 CEST 2006


Author: mateusz.rukowicz
Date: Thu Jul  6 03:06:35 2006
New Revision: 47250

Modified:
   sandbox/trunk/decimal-c/_decimal.c
   sandbox/trunk/decimal-c/decimal.h
   sandbox/trunk/decimal-c/test_decimal.py
Log:
Made things ready to switch to big exponents, fixed pickling of Context. Changed test_decimal.py so it doesn't need __dict__ attribute of Context instance.


Modified: sandbox/trunk/decimal-c/_decimal.c
==============================================================================
--- sandbox/trunk/decimal-c/_decimal.c	(original)
+++ sandbox/trunk/decimal-c/_decimal.c	Thu Jul  6 03:06:35 2006
@@ -521,6 +521,43 @@
     return new_pos;
 }
 
+
+#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))
+#define exp_mod_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))
+
+
+
 /* helpful macros ************************************************************/
 
 /* if we later decide to call this module "squeaky" */
@@ -545,9 +582,10 @@
 /* Exponent calculations */
 
 /* XXX: overflow checking? */
-#define ETINY(ctx) ((ctx)->Emin - (ctx)->prec + 1)
-#define ETOP(ctx)  ((ctx)->Emax - (ctx)->prec + 1)
-#define ADJUSTED(dec) ((dec)->exp + (dec)->ob_size - 1)
+#define ETINY(ctx) (exp_sub_i((ctx)->Emin, (ctx)->prec - 1))
+#define ETOP(ctx)  (exp_sub_i((ctx)->Emax, (ctx)->prec - 1))
+/*#define ADJUSTED(dec) ((dec)->exp + (dec)->ob_size - 1) */
+#define ADJUSTED(dec) (exp_add_i((dec)->exp, (dec)->ob_size - 1))
 
 /* constant values ***********************************************************/
 
@@ -897,7 +935,7 @@
 */
 
 static decimalobject *
-_new_decimalobj(PyTypeObject *type, long ndigits, char sign, long exp)
+_new_decimalobj(PyTypeObject *type, long ndigits, char sign, exp_t exp)
 {
     decimalobject *new;
     char *arr = NULL;
@@ -1034,10 +1072,10 @@
 
 /* Round towards 0, that is, truncate digits. */
 static decimalobject *
-_round_down(decimalobject *self, long prec, long expdiff, contextobject *ctx)
+_round_down(decimalobject *self, long prec, exp_t expdiff, contextobject *ctx)
 {
     long i;
-    decimalobject *new = _NEW_decimalobj(prec, self->sign, self->exp + expdiff);
+    decimalobject *new = _NEW_decimalobj(prec, self->sign, exp_add(self->exp, expdiff));
     if (!new) return NULL;
     for (i = 0; i < prec; i++)
         new->digits[i] = self->digits[i];
@@ -1048,10 +1086,10 @@
 
 /* Round away from 0. */
 static decimalobject *
-_round_up(decimalobject *self, long prec, long expdiff, contextobject *ctx)
+_round_up(decimalobject *self, long prec, exp_t expdiff, contextobject *ctx)
 {
     long i;
-    decimalobject *new = _NEW_decimalobj(prec, self->sign, self->exp + expdiff);
+    decimalobject *new = _NEW_decimalobj(prec, self->sign, exp_add(self->exp, expdiff));
     decimalobject *new2 = NULL;
     if (!new) return NULL;
     for (i = 0; i < prec; i++)
@@ -1068,7 +1106,7 @@
                 _limb_cut_one_digit(new2->limbs,new2->ob_size);
                 new2->ob_size--;
                 new2->limb_count = (new2->ob_size + LOG -1)/LOG;
-                new2->exp++;
+                exp_inc(&(new2->exp));
             }
             return new2;
         }
@@ -1081,7 +1119,7 @@
  * without DECREFing tmp afterwards.
  */
 static decimalobject *
-_do_round_half_up(decimalobject *self, long prec, long expdiff,
+_do_round_half_up(decimalobject *self, long prec, exp_t expdiff,
                     contextobject *ctx, decimalobject *tmp)
 {
     decimalobject *new;
@@ -1094,7 +1132,7 @@
             _limb_cut_one_digit(new->limbs,new->ob_size);
             new->ob_size--;
             new->limb_count = (new->ob_size + LOG - 1)/LOG;
-            new->exp++;
+            exp_inc(&(new->exp));
         }
         return new;            
     } else {
@@ -1104,12 +1142,12 @@
 
 /* Round 5 down. */
 static decimalobject *
-_round_half_down(decimalobject *self, long prec, long expdiff, contextobject *ctx)
+_round_half_down(decimalobject *self, long prec, exp_t expdiff, contextobject *ctx)
 {
     long i, last;
     decimalobject *tmp;
     assert(expdiff > 0);
-    tmp = _NEW_decimalobj(prec, self->sign, self->exp + expdiff);
+    tmp = _NEW_decimalobj(prec, self->sign, exp_add(self->exp, expdiff));
     if (!tmp) return NULL;
     for (i = 0; i < prec; i++)
         tmp->digits[i] = self->digits[i];
@@ -1128,12 +1166,12 @@
 
 /* Round 5 to even, rest to nearest. */
 static decimalobject *
-_round_half_even(decimalobject *self, long prec, long expdiff, contextobject *ctx)
+_round_half_even(decimalobject *self, long prec, exp_t expdiff, contextobject *ctx)
 {
     decimalobject *tmp;
     long i, last;
     assert(expdiff > 0);
-    tmp = _NEW_decimalobj(prec, self->sign, self->exp + expdiff);
+    tmp = _NEW_decimalobj(prec, self->sign, exp_add(self->exp, expdiff));
     if (!tmp) return NULL;
     for (i = 0; i < prec; i++)
         tmp->digits[i] = self->digits[i];
@@ -1151,11 +1189,11 @@
 
 /* Round 5 up (away from 0). */
 static decimalobject *
-_round_half_up(decimalobject *self, long prec, long expdiff, contextobject *ctx)
+_round_half_up(decimalobject *self, long prec, exp_t expdiff, contextobject *ctx)
 {
     decimalobject *tmp;
     long i;
-    tmp = _NEW_decimalobj(prec, self->sign, self->exp + expdiff);
+    tmp = _NEW_decimalobj(prec, self->sign, exp_add(self->exp, expdiff));
     if (!tmp) return NULL;
     for (i = 0; i < prec; i++)
         tmp->digits[i] = self->digits[i];
@@ -1165,7 +1203,7 @@
 
 /* Round up (regardless of sign) */
 static decimalobject *
-_round_ceiling(decimalobject *self, long prec, long expdiff, contextobject *ctx)
+_round_ceiling(decimalobject *self, long prec, exp_t expdiff, contextobject *ctx)
 {
     assert(self->sign <= 1);
     if (self->sign > 0)
@@ -1176,7 +1214,7 @@
 
 /* Round down (regardless of sign) */
 static decimalobject *
-_round_floor(decimalobject *self, long prec, long expdiff, contextobject *ctx)
+_round_floor(decimalobject *self, long prec, exp_t expdiff, contextobject *ctx)
 {
     assert(self->sign <= 1);
     if (self->sign > 0)
@@ -1199,7 +1237,8 @@
 {
     decimalobject *new, *new2 = NULL;
     contextobject *ctx2 = NULL;
-    long i, expdiff;
+    long i;
+    exp_t expdiff;
     round_func rnd_func;
     
     if (ISSPECIAL(self)) {
@@ -1226,7 +1265,7 @@
             i = prec;
         
         new = _NEW_decimalobj(i, self->sign,
-                              self->ob_size - prec + self->exp);
+                              exp_add_i(self->exp, self->ob_size - prec));
         if (!new) return NULL;
         while (i--)
             new->digits[i] = 0;
@@ -1249,7 +1288,7 @@
         prec = 1;
     } else if (prec < 0) {
         new = _NEW_decimalobj(2, self->sign,
-                              self->exp + self->ob_size - prec - 1);
+                              exp_add_i(self->exp, self->ob_size - prec - 1));
         if (!new) return NULL;
         new->digits[0] = 0;
         new->digits[1] = 1;
@@ -1260,12 +1299,14 @@
         if (!new) return NULL;
     }
 
-    expdiff = new->ob_size - prec;
-    if (expdiff == 0)
+    expdiff = exp_from_i(new->ob_size - prec);
+/*    if (expdiff == 0) */
+    if(exp_is_zero(expdiff))
         return new;
-    else if (expdiff < 0) {
+    
+    else if (exp_is_neg(expdiff)) {
         /* we need to extend precision */
-        new2 = _NEW_decimalobj(prec, new->sign, new->exp + expdiff);
+        new2 = _NEW_decimalobj(prec, new->sign, exp_add(new->exp,  expdiff));
         if (!new2) {
             Py_DECREF(new);
             return NULL;
@@ -1283,7 +1324,7 @@
     }
 
     /* Maybe all the lost digits are 0. */
-    for (i = self->ob_size - expdiff; i < self->ob_size; i++) {
+    for (i = self->ob_size - exp_to_int(expdiff); i < self->ob_size; i++) {
         if(_limb_get_digit(self->limbs, self->ob_size, i) > 0)
             goto no_way;
     }
@@ -1295,7 +1336,8 @@
         new->ob_size --;
     }
     new->limb_count = (new->ob_size + LOG - 1)/LOG;
-    new->exp += expdiff;
+/*    new->exp += expdiff; */
+    exp_inp_add(&(new->exp), expdiff);
     if (handle_Rounded(ctx, NULL) != 0) {
         Py_DECREF(new);
         return NULL;
@@ -1339,12 +1381,13 @@
 
 /* Default values: rounding=-1 (use context), watchexp=1 */
 static decimalobject *
-_decimal_rescale(decimalobject *self, long exp, contextobject *ctx,
+_decimal_rescale(decimalobject *self, exp_t exp, contextobject *ctx,
                  int rounding, int watchexp)
 {
     decimalobject *ans = NULL, *tmp;
     int ret;
-    long diff, adj;
+    exp_t diff;
+    long adj;
     long digits, i;
 
     if (ISSPECIAL(self)) {
@@ -1357,7 +1400,7 @@
             return ans;
     }
     
-    if (watchexp && (exp > ctx->Emax || exp < ETINY(ctx)))
+    if (watchexp && (exp_g(exp, ctx->Emax) || exp_l(exp, ETINY(ctx))))
         return handle_InvalidOperation(self->ob_type, ctx,
                                        "rescale(a, INF)", NULL);
 
@@ -1370,8 +1413,8 @@
         return ans;
     }
 
-    diff = self->exp - exp;
-    digits = self->ob_size + diff;
+    diff = exp_sub(self->exp, exp);
+    digits = exp_to_int(exp_add_i(diff, self->ob_size));
 
     if (watchexp && ctx->prec < digits)
         return handle_InvalidOperation(self->ob_type, ctx,
@@ -1379,7 +1422,7 @@
 
     digits += 1;
     if (digits < 0) {
-        ans = _NEW_decimalobj(2, self->sign, self->exp - digits);
+        ans = _NEW_decimalobj(2, self->sign, exp_sub_i(self->exp, digits));
         if (!ans)
             return NULL;
         ans->digits[0] = 0;
@@ -1432,13 +1475,16 @@
 {
     static char *kwlist[] = {"exp", "rounding", "context", "watchexp", 0};
     contextobject *ctx = NULL;
-    long exp;
+    exp_t exp;
+    long tmp_exp;
     int rounding = -1, watchexp = 1;
 
+    /* TODO big exp*/
     if(!PyArg_ParseTupleAndKeywords(args,kwds,"l|iOi:_rescale",kwlist,
-                            &exp, &rounding, &ctx, &watchexp))
+                            &tmp_exp, &rounding, &ctx, &watchexp))
         return NULL;
 
+    exp = exp_from_i(tmp_exp);
     if(ctx == NULL)
         if(!(ctx = getcontext()))
             return NULL;
@@ -1457,13 +1503,13 @@
 _fixexponents(decimalobject *self, contextobject *ctx)
 {
     decimalobject *ans = NULL;
-    long adj;
+    exp_t adj;
     assert(!ISSPECIAL(self));
 
     adj = ADJUSTED(self);
-    if (adj < ctx->Emin) {
-        long Etiny = ETINY(ctx);
-        if (self->exp < Etiny) {
+    if (exp_l(adj, ctx->Emin)) {
+        exp_t Etiny = ETINY(ctx);
+        if (exp_l(self->exp, Etiny)) {
             if (!decimal_nonzero(self)) {
                 ans = _decimal_get_copy(self);
                 if (!ans)
@@ -1491,8 +1537,8 @@
             /* this returns self, below */
         }
     } else {
-        long Etop = ETOP(ctx);
-        if (ctx->clamp && self->exp > Etop) {
+        exp_t Etop = ETOP(ctx);
+        if (ctx->clamp && exp_g(self->exp, Etop)) {
             if (handle_Clamped(ctx, NULL) != 0)
                 return NULL;
             ans = _decimal_rescale(self, Etop, ctx, -1, 1);
@@ -1500,7 +1546,7 @@
                 return NULL;
             return ans;
         } else {
-            if (adj > ctx->Emax) {
+            if (exp_g(adj, ctx->Emax)) {
                 if (!decimal_nonzero(self)) {
                     ans = _decimal_get_copy(self);
                     if (!ans)
@@ -1671,7 +1717,7 @@
 _do_real_decimal_compare(decimalobject *self, decimalobject *other,
                          contextobject *ctx)
 {
-    long adj1, adj2;
+    exp_t adj1, adj2;
     long i, minsize;
     decimalobject *longer, *ans;
     contextobject *ctx2;
@@ -1707,7 +1753,7 @@
     adj1 = ADJUSTED(self);
     adj2 = ADJUSTED(other);
 
-    if (adj1 == adj2) {
+    if (exp_eq(adj1, adj2)) {
         if (self->ob_size <= other->ob_size) {
             minsize = self->ob_size;
             longer = other;
@@ -1733,9 +1779,9 @@
              
   next:
     /* Adjusted sizes are not equal. */
-    if(adj1 > adj2 && _limb_get_digit(self->limbs, self->ob_size, 0) != 0)
+    if(exp_g(adj1, adj2) && _limb_get_digit(self->limbs, self->ob_size, 0) != 0)
         return 1 - 2*(self->sign & 1); /* 0 -> 1, 1 -> -1 */
-    else if(adj1 < adj2 && _limb_get_digit(other->limbs, other->ob_size, 0) != 0)
+    else if(exp_l(adj1, adj2) && _limb_get_digit(other->limbs, other->ob_size, 0) != 0)
         return -1 + 2*(other->sign & 1);
 
     ctx2 = context_copy(ctx);
@@ -1882,9 +1928,9 @@
         }
         else
         {
-            if(self->exp < other->exp && !self->sign)
+            if (exp_l(self->exp, other->exp) && !self->sign)
                 ans = other;
-            else if(self->exp > other->exp && self->sign)
+            else if (exp_g(self->exp, other->exp) && self->sign)
                 ans = other;
         }
     }
@@ -1954,9 +2000,9 @@
                 ans = other;
         }
         else{    
-        if(self->exp > other->exp && !self->sign)
+        if (exp_g(self->exp, other->exp) && !self->sign)
             ans = other;
-        else if (self->exp < other->exp && self->sign)
+        else if (exp_l(self->exp, other->exp) && self->sign)
             ans = other;
         }
     }
@@ -2001,7 +2047,7 @@
     while(_limb_get_digit(dup->limbs, dup->ob_size, dup->ob_size -1) == 0){
         _limb_cut_one_digit(dup->limbs,dup->ob_size);
         dup->ob_size --;
-        dup->exp ++;
+        exp_inc(&(dup->exp));
     }
     return dup;
 }
@@ -2353,7 +2399,7 @@
         }
     }
 
-    if (self->exp == other->exp)
+    if (exp_eq(self->exp, other->exp))
         Py_RETURN_TRUE;
     else
         Py_RETURN_FALSE;
@@ -2392,14 +2438,14 @@
     contextobject *ctx2 = 0;
     decimalobject *half = 0;
     PyObject *flags = 0;
-    long expadd;
+    exp_t expadd;
     long firstprec;
     long i;
-    long Emax;
-    long Emin;
+    exp_t Emax;
+    exp_t Emin;
     long maxp;
     long rounding;
-    long prevexp;
+    exp_t prevexp;
     
     if (ISSPECIAL(self)) {
         decimalobject *nan;
@@ -2416,9 +2462,10 @@
             return NULL;
 
         ret->limbs[0] = 0;
-        ret->exp = self->exp / 2;
-        if (self->exp < 0 && self->exp%2)
-            ret->exp --;
+        ret->exp = exp_floordiv_i(self->exp, 2);
+//        ret->exp = self->exp / 2;
+//        if (self->exp < 0 && self->exp%2)
+//            ret->exp --;
         ret->sign = self->sign & 1;
 
         return ret;
@@ -2433,11 +2480,12 @@
     if (!tmp)
         return NULL;
 
-    expadd = tmp->exp/2;
-    if (tmp->exp < 0 && tmp->exp % 2)
-        expadd --;
+    expadd = exp_floordiv_i(tmp->exp, 2);
+//    expadd = tmp->exp/2;
+//    if (tmp->exp < 0 && tmp->exp % 2)
+//        expadd --;
     
-    if (tmp->exp &1) {
+    if (exp_mod_i(tmp->exp, 2)) {
         _limb_first_n_digits(self->limbs, self->ob_size, 0, tmp->limbs, tmp->ob_size);
     }
     else {
@@ -2447,7 +2495,7 @@
             tmp->limbs[i] = self->limbs[i];
     }
 
-    tmp->exp = 0;
+    tmp->exp = exp_from_i(0);
     
     ctx2 = context_copy(ctx);
 
@@ -2464,7 +2512,7 @@
         return NULL;
     }
 
-    ans = _NEW_decimalobj(3, 0, 0);
+    ans = _NEW_decimalobj(3, 0, exp_from_i(0));
 
     if (!ans) {
         Py_DECREF(tmp);
@@ -2472,7 +2520,7 @@
         Py_DECREF(flags);
     }
 
-    tmp2 = _NEW_decimalobj(3, 0, 0);
+    tmp2 = _NEW_decimalobj(3, 0, exp_from_i(0));
 
     if (!tmp2) {
         Py_DECREF(tmp);
@@ -2481,17 +2529,19 @@
         Py_DECREF(ans);
     }
 
-    if ((ADJUSTED(tmp) & 1) == 0) {
+    if (exp_mod_i(ADJUSTED(tmp), 2) == 0) {
         ans->limbs[0] = 819;
-        ans->exp = ADJUSTED(tmp) - 2;
+        ans->exp = exp_sub_i(ADJUSTED(tmp), 2);
         tmp2->limbs[0] = 259;
-        tmp2->exp = -2;
+//        tmp2->exp = -2;
+        exp_inp_sub_i(&(tmp2->exp), 2);
     }
     else {
         ans->limbs[0] = 259;
-        ans->exp = tmp->exp + tmp->ob_size - 3;
+        ans->exp = exp_add_i(tmp->exp, tmp->ob_size - 3);
         tmp2->limbs[0] = 819;
-        tmp2->exp = -3;
+//        tmp2->exp = -3;
+        exp_inp_sub_i(&(tmp2->exp), 3);
     }
 
     firstprec = ctx2->prec;
@@ -2514,10 +2564,11 @@
     Py_DECREF(ans);
     ans = tmp2;
     tmp2 = 0;
-    ans->exp -= 1 + ADJUSTED(tmp)/2;
+/*    ans->exp -= 1 + ADJUSTED(tmp)/2;
     if (1 + ADJUSTED(tmp) < 0 && (1 + ADJUSTED(tmp)) % 2)
         ans->exp --;
-    
+  */
+    exp_inp_sub(&(ans->exp),exp_add_i(exp_floordiv_i(ADJUSTED(tmp), 2), 1));  
     Emax = ctx2->Emax;
     Emin = ctx2->Emin;
 
@@ -2571,9 +2622,10 @@
         goto err;
 
     ctx2->prec = firstprec + 1;
-    if (prevexp != ADJUSTED(tmp2)) {
+    if (exp_ne(prevexp, ADJUSTED(tmp2))) {
         _limb_first_n_digits(tmp2->limbs, tmp2->ob_size, 0, ans->limbs, ans->ob_size);
-        ans->exp --;    
+//        ans->exp --;    
+        exp_dec(&(ans->exp));
     }
     else {
         ans->limb_count = tmp2->limb_count;
@@ -2588,7 +2640,7 @@
     {
         int cmp;
         decimalobject *lower;
-        half->exp = ans->exp - 1;
+        half->exp = exp_sub_i(ans->exp, 1);
         half->limbs[0] = 5;
         lower = _do_decimal_subtract(ans, half, ctx2);
         if (!lower)
@@ -2622,7 +2674,7 @@
         }
         else {
             decimalobject *upper;
-            half->exp = ans->exp-1;
+            half->exp = exp_sub_i(ans->exp, 1);
             half->limbs[0] = 5;
             upper = _do_decimal_add(ans, half, ctx2);
             if (!upper)
@@ -2655,7 +2707,8 @@
         }
     }
 
-    ans->exp += expadd;
+//    ans->exp += expadd;
+    exp_inp_add(&(ans->exp), expadd);
     ctx2->rounding = rounding;
 
     tmp2 = _decimal_fix(ans, ctx2);
@@ -2691,10 +2744,11 @@
         }
 
         else {
-            long exp = self->exp / 2;
+/*            long exp = self->exp / 2;
             if (self->exp < 0 && self->exp % 2)
-                exp --;
-            ctx2->prec += ans->exp - exp;
+                exp --;*/
+            exp_t exp = exp_floordiv_i(self->exp, 2);
+            ctx2->prec += exp_to_i(exp_sub(ans->exp, exp));
             tmp2 = _decimal_rescale(ans, exp, ctx2, -1, 1);
 
             if (!tmp2)
@@ -2753,7 +2807,8 @@
         if (_check_nans(self, NULL, ctx, &nan) != 0)
             return nan;
     }
-    if (self->exp >= 0) {
+//    if (self->exp >= 0) {
+    if (exp_is_pos(self->exp) || exp_is_zero(self->exp)) {
         Py_INCREF(self);
         return self;
     }
@@ -2933,7 +2988,8 @@
 {
     char outbuf[FORMAT_SIZE];
     char *p, *end;
-    int roundexp, i;
+    int i;
+    exp_t roundexp;
 
     end = &outbuf[FORMAT_SIZE-1];
     p = outbuf;
@@ -2941,39 +2997,40 @@
         *p++ = '-';
         SANITY_CHECK(p);
     }
-    if (d->exp < 0 && d->exp >= -6) {
-        
+//    if (d->exp < 0 && d->exp >= -6) {
+    if(exp_is_neg(d->exp) && exp_ge_i(d->exp, -6)) {        
         i = 0;
         *p++ = '0';
         *p++ = '.';
-        for (;i<abs(d->exp);i++)
+        for (;i<abs(exp_to_i(d->exp));i++)
             *p++ = '0';
         SANITY_CHECK(p);
     } else {
         roundexp = d->exp;
-        while(roundexp%3)
-            roundexp ++;
-        if (roundexp != d->exp) {
+        while(exp_mod_i(roundexp, 3))
+            exp_inc (&roundexp);
+        if (exp_ne(roundexp, d->exp)) {
             *p++ = '0';
             *p++ = '.';
-            for (i = 0; i < (roundexp - d->exp); i++)
+            for (i = 0; i < (exp_to_i(exp_sub(roundexp, d->exp))); i++)
                 *p++ = '0';
             SANITY_CHECK(p);
         } else {
             *p++ = '0';
         }
-        if (roundexp != 0) {
+        if (!exp_is_zero(roundexp)) {
             if (context->capitals)
                 *p++ = 'E';
             else
                 *p++ = 'e';
             SANITY_CHECK(p);
 
-            if (roundexp > 0)
+            if (exp_is_pos(roundexp))
                 *p++ = '+';
             SANITY_CHECK(p);
 
-            p += sprintf(p, "%d", roundexp);
+//            p += sprintf(p, "%d", roundexp);
+            p += exp_sprintf(p, roundexp);
             SANITY_CHECK(p);
         }
     }
@@ -3002,7 +3059,8 @@
 {
     char *outbuf;
     int buflen, i;
-    int dotplace, adjexp;
+    int dotplace;
+    exp_t adjexp;
     int append_E = 0, append_adjexp = 0;
     long extra_zeros=0;
     char *p, *end;
@@ -3042,7 +3100,7 @@
     /* (1) dotplace = -adjexp + d->exp + d->ob_size */
     /* why is that like? well, d->exp moves dot right, d->ob_size moves dot right
      * and adjexp moves dot left */
-    adjexp = 0;
+    adjexp = exp_from_i(0);
     dotplace = 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)
@@ -3050,13 +3108,14 @@
         /* ok, we have to put dot after 1 digit, that is dotplace = 1 
          * we compute adjexp from equation (1) */
         dotplace = 1;
-        adjexp = -dotplace + d->exp + d->ob_size;
+//        adjexp = -dotplace + d->exp + d->ob_size;
+        adjexp = exp_add_i(d->exp, d->ob_size - dotplace);
     }
 
     if(engineering)        /* we have to be sure, adjexp%3 == 0 */
-        while(adjexp%3)
+        while(exp_mod_i(adjexp,3))
         {
-            adjexp --;
+            exp_dec(&adjexp);
             dotplace ++;
         }
 
@@ -3086,7 +3145,7 @@
     /* that was a way easier way =] */
     
 
-    if(adjexp)
+    if(!exp_is_zero(adjexp))
     {
         append_E = 1;
         append_adjexp = 1;
@@ -3095,7 +3154,7 @@
         if (context->capitals) {
             *p++ = 'E';
             SANITY_CHECK(p);
-            if (adjexp > 0) {
+            if (exp_is_pos(adjexp)) {
                 *p++ = '+';
                 SANITY_CHECK(p);
             }
@@ -3106,7 +3165,7 @@
     }
 
     if (append_adjexp) {
-        p += sprintf(p, "%d", adjexp);
+        p += exp_sprintf(p, adjexp);
     }
     SANITY_CHECK(p);
     *p++ = 0;
@@ -3295,15 +3354,15 @@
     }
 
     if (self_is_zero) {
-        long exp;
+        exp_t exp;
         if (divmod) {
             decimalobject *ans1, *ans2;
             
             ans2 = _decimal_get_copy(self);
             if (!ans2)
                 return NULL;
-            ans2->exp = self->exp < other->exp ? self->exp : other->exp;
-
+            //ans2->exp = self->exp < other->exp ? self->exp : other->exp;
+            ans2->exp = exp_min(self->exp, other->exp);
             ans1 = _NEW_decimalobj(1, sign, 0);
             if (!ans1) {
                 Py_DECREF(ans2);
@@ -3317,15 +3376,15 @@
             return ans;
         }
 
-        exp = self->exp - other->exp;
+        exp = exp_sub(self->exp, other->exp);
 
-        if (exp < ETINY(ctx)) {
+        if (exp_l(exp, ETINY(ctx))) {
             exp = ETINY(ctx);
             if (handle_Clamped(ctx, "0e-x / y"))
                 return NULL;
         }
 
-        if (exp > ctx->Emax) {
+        if (exp_g(exp, ctx->Emax)) {
             exp = ctx->Emax;
             if (handle_Clamped(ctx, "0e+x / y"))
                 return NULL;
@@ -3387,8 +3446,9 @@
 
             if (divmod == 1 || divmod == 3) {
                 decimalobject *tmp;
-                long exp;
-                exp = self->exp < other->exp ? self->exp : other->exp;
+                exp_t exp;
+//                exp = self->exp < other->exp ? self->exp : other->exp;
+                exp = exp_min(self->exp, other->exp);
                 tmp = _decimal_rescale(self, exp, ctx, -1, 0);
 
                 if (!tmp) {
@@ -3434,12 +3494,12 @@
     /* if divmod, then op1->exp - op2->exp must be divisible by LOG */
 
     if (divmod) {
-        long expdiff = op1->exp - op2->exp;
-        long tmp_exp = op1->exp;
+        exp_t expdiff = exp_sub(op1->exp, op2->exp);
+        exp_t tmp_exp = op1->exp;
         /* we will do in loop, because of some issues with x % a, when x < 0 */
-        while (expdiff % LOG) {
-            tmp_exp --;
-            expdiff = tmp_exp - op2->exp;
+        while (exp_mod_i(expdiff, LOG)) {
+            exp_dec(&tmp_exp);
+            expdiff = exp_sub(tmp_exp, op2->exp);
         }
 
         op1 = _decimal_rescale(self, tmp_exp, ctx, -1, 0);
@@ -3451,14 +3511,14 @@
         decimalobject *result;
         decimalobject *remainder_ret;
         long *remainder;
-        long exp = op1->exp - op2->exp;
-        long expdiff;
+        exp_t exp = exp_sub(op1->exp, op2->exp);
+        exp_t expdiff;
         long rlimbs;
         long old_size;
-        long adj1, adj2, adjusted = 0;
+        exp_t adj1, adj2, adjusted = exp_from_i(0);
         long i;
         long max_size;
-        long min_expdiff;   /* used when divmod */
+        exp_t min_expdiff;   /* used when divmod */
         long remainder_limbs = op2->limb_count+1 > op1->limb_count ? 
             op2->limb_count + 1 : op1->limb_count;
         
@@ -3501,25 +3561,28 @@
          * expdiff * LOG >= -exp - LOG
          * expdiff >= (-exp - LOG)/ LOG */
         if (divmod) {
-            assert(!(exp % LOG));
-            min_expdiff = (-exp - LOG)/ LOG;
-
+            assert(!(exp_mod_i(exp, LOG)));
+//            min_expdiff = (-exp - LOG)/ LOG;
+            min_expdiff = exp_sub_i(exp_neg(exp), LOG);
+            min_expdiff = exp_floordiv_i(min_expdiff, LOG);
+            
         }
         else
-            min_expdiff = op1->limb_count;
+            min_expdiff = exp_from_i(op1->limb_count);
 
-        expdiff = _limb_divide(op1->limbs, op1->limb_count, 
+        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, min_expdiff));
         result->limbs[significant_limbs] = 0;
 
-        exp += expdiff * LOG + LOG;
-
+//        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)) {
             /* we have not enough precision to do exact integer division */
-            if (divmod && exp < 0) {
+            if (divmod && exp_is_neg(exp)) {
                 Py_DECREF(op1);
                 Py_DECREF(result);
                 PyMem_FREE(remainder);
@@ -3527,7 +3590,8 @@
             }
             
             if (!divmod) {
-                exp -= LOG;
+//                exp -= LOG;
+                exp_inp_sub_i(&exp, LOG);
                 result->limb_count ++;
                 result->ob_size += LOG;
                 _limb_move_left(result->limbs, result->limb_count, 1);
@@ -3545,8 +3609,8 @@
             }
             for (i = 0; i< rlimbs; i++)
                 remainder_ret->limbs[i] = remainder[i];
-            if (expdiff <= 0)
-                remainder_ret->exp = op1->exp + expdiff * LOG;
+            if (exp_le_i(expdiff, 0))
+                remainder_ret->exp = exp_add(op1->exp, exp_mul_i( expdiff, LOG));
             else
                 remainder_ret->exp = op1->exp;
             remainder_ret->ob_size = _limb_size_s(remainder_ret->limbs, remainder_ret->ob_size);
@@ -3581,16 +3645,17 @@
         while (result->ob_size > adjusted &&
                 _limb_get_digit(result->limbs, result->ob_size, result->ob_size -1) == 0) {
             /* when int dividing, exp should be 0 */
-            if (result->exp >= 0 && divmod)
+            if (exp_ge_i(result->exp, 0) && divmod)
                 break;
             _limb_cut_one_digit(result->limbs, result->ob_size);
             result->ob_size --;
-            result->exp ++;
+//            result->exp ++;
+            exp_inc(&(result->exp));
         }
 
         result->limb_count = (result->ob_size + LOG -1)/LOG;
 
-        if (result->ob_size + result->exp > ctx->prec && shouldround && divmod) {
+        if (exp_add_i(result->exp, result->ob_size) > ctx->prec && shouldround && divmod) {
             Py_DECREF(remainder_ret);
             Py_DECREF(result);
             Py_DECREF(op1);
@@ -3604,7 +3669,7 @@
             /* we need to rescale, to be compatible with python implementation */
             PyObject *flags = 0;
             contextobject *ctx2 = 0;
-            long remainder_exp = self->exp < other->exp ? self->exp : other->exp;
+            exp_t remainder_exp = exp_min(self->exp, other->exp);
             decimalobject *rescaled_rem = 0;
             decimalobject *rescaled = _decimal_rescale(result, 0, ctx, -1, 0);
             if (!rescaled) {
@@ -3834,7 +3899,7 @@
     assert(PyDecimal_Check(other));
     assert(PyDecimal_Check(self));
     int shouldround, sign, negativezero = 0;
-    long exp, oexp;
+    exp_t exp, oexp;
     long prec,cmp;
     decimalobject *res, *res2, *ret, *o1, *o2;
     prec = ctx->prec;
@@ -3857,8 +3922,8 @@
     }
 
     shouldround = (ctx->rounding_dec == ALWAYS_ROUND);
-    exp = (self->exp < other->exp ? self->exp : other->exp);
-
+//    exp = (self->exp < other->exp ? self->exp : other->exp);
+    exp = exp_min(self->exp, other->exp);
     if (ctx->rounding == ROUND_FLOOR &&
         (self->sign & 1) != (other->sign & 1))
         negativezero = 1;
@@ -3877,8 +3942,10 @@
         return res;
     }
     if (!decimal_nonzero(self)) {
-        oexp = other->exp - ctx->prec - 1;
-        exp = (exp > oexp ? exp : oexp);
+//        oexp = other->exp - ctx->prec - 1;
+        oexp = exp_sub(other->exp, ctx->prec + 1);
+//        exp = (exp > oexp ? exp : oexp);
+        exp = exp_max(exp, oexp);
         res = _decimal_rescale(other, exp, ctx, 0, 0);
         if (!res) return NULL;
         if (shouldround) {
@@ -3890,8 +3957,10 @@
         }            
     }
     if (!decimal_nonzero(other)) {
-        oexp = self->exp - ctx->prec - 1;
-        exp = (exp > oexp ? exp : oexp);
+//        oexp = self->exp - ctx->prec - 1;
+        oexp = exp_sub(self->exp, ctx->prec + 1);
+//        exp = (exp > oexp ? exp : oexp);
+        exp = exp_max(exp, oexp);
         res = _decimal_rescale(self, exp, ctx, 0, 0);
         if (!res) return NULL;
         if (shouldround) {
@@ -3906,7 +3975,7 @@
     decimalobject *tmp;    /* we borrow refference */
     decimalobject *oother;
 
-    long numdigits = self->exp - other->exp;
+    long numdigits = exp_to_i(exp_sub(self->exp, other->exp));
 
     if(numdigits < 0)
     {
@@ -3928,7 +3997,7 @@
             long extend = prec + 2 - tmp->ob_size;
             if(extend <= 0)
                 extend = 1;
-            o1 = _NEW_decimalobj(tmp->ob_size + extend, tmp->sign, tmp->exp - extend);
+            o1 = _NEW_decimalobj(tmp->ob_size + extend, tmp->sign, exp_sub_i(tmp->exp, extend));
             if(!o1)
                 return NULL;
 
@@ -3944,7 +4013,7 @@
         }    
     }
 
-    o1 = _NEW_decimalobj(tmp->ob_size + numdigits, tmp->sign, tmp->exp - numdigits);
+    o1 = _NEW_decimalobj(tmp->ob_size + numdigits, tmp->sign, exp_sub_i(tmp->exp, numdigits));
     _limb_first_n_digits(tmp->limbs, tmp->ob_size, 0, o1->limbs, o1->ob_size);
 
     if(!o1)
@@ -3957,7 +4026,7 @@
 
 calc:
 
-    assert(o1->exp == o2->exp);
+    assert(exp_eq(o1->exp, o2->exp));
     exp = o1->exp;
     cmp = _limb_compare(o1->limbs, o1->limb_count, o2->limbs, o2->limb_count);
 
@@ -3971,7 +4040,7 @@
             if(!ret)
                 return NULL;
             ret->limbs[0] = 0;
-            if(ret->exp < ETINY(ctx))
+            if(exp_l(ret->exp, ETINY(ctx)))
             {
                 ret->exp = ETINY(ctx);
                 if(handle_Clamped(ctx, NULL) != 0)
@@ -4096,7 +4165,7 @@
                      contextobject *ctx)
 {
     long resultsign;
-    long resultexp;
+    exp_t resultexp;
     long shouldround;
     long i;
     long max_limbs;
@@ -4132,7 +4201,7 @@
         }
     }
 
-    resultexp = self->exp + other->exp;
+    resultexp = exp_add(self->exp, other->exp);
     shouldround = ctx->rounding_dec == ALWAYS_ROUND;
 
     if(!decimal_nonzero(self) || !decimal_nonzero(other))
@@ -4622,7 +4691,7 @@
     char *buf;
     PyObject *res;
 
-    max = self->ob_size + self->exp;
+    max = exp_to_i(self->ob_size) + self->exp;
     
     buf = PyMem_MALLOC(max + 2); /* with sign */
     if (!buf) return NULL;
@@ -4660,7 +4729,7 @@
     }
 
     /* try converting to int, if it's too big, convert to long  */
-    max = self->ob_size + self->exp;
+    max = self->ob_size + exp_to_i(self->exp);
 
 #if SIZEOF_LONG == 4
     if (max > 9) return decimal_long(self);
@@ -4756,17 +4825,20 @@
 int
 _decimal_isint(decimalobject *d)
 {
-    long i;
+    exp_t i;
+    exp_t cmp;
 
-    if (d->exp >= 0)
+    if (exp_ge_i(d->exp, 0))
         /* if the exponent is positive, there's no
          * fractional part at all. */
         return 1;
     /* Here comes the tricky part. We have to find out
      * whether the fractional part consists only of zeroes. */
-    for (i = d->ob_size-1; i >= d->ob_size + d->exp; --i) {
+    i = exp_from_i(d->ob_size-1);
+    cmp = exp_add_i(d->exp, d->ob_size);
+    for (; exp_ge(i, cmp); --i) {
 /*        if (d->digits[i] > 0)*/
-        if(_limb_get_digit(d->limbs, d->ob_size, i) > 0)
+        if(_limb_get_digit(d->limbs, d->ob_size, exp_to_i(i)) > 0)
             return 0;
     }
     return 1;
@@ -4834,7 +4906,7 @@
     if (size > ctx->prec)
         return handle_ConversionSyntax(type, ctx, "diagnostic info too long");
 
-    new = _new_decimalobj(type, size, sign, 0);
+    new = _new_decimalobj(type, size, sign, exp_from_i(0));
     if (!new)
         return NULL;
     for (i = 0; i < size; i++)
@@ -4884,7 +4956,7 @@
         }
     } while (*++p);
     if (sign) {
-        new = _new_decimalobj(type, 1, sign, 0);
+        new = _new_decimalobj(type, 1, sign, exp_from_i(0));
         if (!new)
             return NULL;
         new->digits[0] = 0;
@@ -4899,7 +4971,7 @@
 _decimal_fromliteral(PyTypeObject *type, char *str, long len, contextobject *ctx)
 {
     char sign = 0;    
-    long exp = 0;
+    exp_t exp = exp_from_i(0);
     long ndigits;
     long zero = 0;                /* if zero */
     long digits_after_dot = 0;
@@ -5002,14 +5074,15 @@
     if(e)            /* pretty obvious */
     {
         int ok;
-        ok = sscanf(e+1,"%d", &exp);
+//        ok = sscanf(e+1,"%d", &exp);
+        ok = exp_sscanf(e+1, &exp);
         if(ok!=1)
         {
             goto err;
         }
     }
-    exp -= digits_after_dot;
-
+//    exp -= digits_after_dot;
+    exp_inp_sub_i(&exp, digits_after_dot);
     new = _new_decimalobj(type, ndigits, sign, exp);
     if(!new)
         return NULL;
@@ -5082,7 +5155,7 @@
     int ndigits = 0, neg = 0, i = 0;
 
     if (value == 0) {
-        new = _new_decimalobj(type, 1, 0, 0);
+        new = _new_decimalobj(type, 1, 0, exp_from_i(0));
         if (!new) return NULL;
         new->digits[0] = 0;    
         new->limbs[0] = 0;
@@ -5132,7 +5205,9 @@
     decimalobject *new = NULL;
     PyObject *tup, *digits, *digtup = NULL, *item;
     int sign;
-    long i, exp;
+    long i;
+    exp_t exp;
+    long tmp_exp;
 
     if (PyTuple_Check(seq)) {
         tup = seq;
@@ -5147,8 +5222,11 @@
         PyErr_SetString(PyExc_ValueError, "Invalid arguments");
         goto err;
     }
-    if (!PyArg_ParseTuple(tup, "iOl", &sign, &digits, &exp))
+    
+    /* TODO big exponents reading */
+    if (!PyArg_ParseTuple(tup, "iOl", &sign, &digits, &tmp_exp))
         goto err;
+    exp = exp_from_i(tmp_exp);
     if (sign < 0 || sign > 7) {
         PyErr_SetString(PyExc_ValueError, "Invalid sign");
         goto err;
@@ -5654,7 +5732,7 @@
 
 static contextobject *
 _new_contextobj(long prec, int rounding, int rounding_dec, PyObject *traps,
-                PyObject *flags, long Emin, long Emax, int capitals,
+                PyObject *flags, exp_t Emin, exp_t Emax, int capitals,
                 int clamp, PyObject *ignored, int copy_dicts)
 {
     contextobject *new;
@@ -6510,7 +6588,7 @@
     PyObject *_ignored = NULL;
     int i, j;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwds, "|nbbOOnnbbO:Context", kwlist,
+    if (!PyArg_ParseTupleAndKeywords(args, kwds, "|liiOOlliiO:Context", kwlist,
                                      &prec, &rounding, &rounding_dec, &pytraps,
                                      &pyflags, &Emin, &Emax, &capitals, &clamp,
                                      &pyignored))

Modified: sandbox/trunk/decimal-c/decimal.h
==============================================================================
--- sandbox/trunk/decimal-c/decimal.h	(original)
+++ sandbox/trunk/decimal-c/decimal.h	Thu Jul  6 03:06:35 2006
@@ -7,6 +7,7 @@
 extern "C" {
 #endif
 
+#define exp_t long
 
 #define BASE 1000	/* biggest value of limb power of 10 */
 #define LOG 3		/* number of digits per limb LOG = log10(BASE) */
@@ -16,7 +17,7 @@
     PyObject_HEAD
     long ob_size;    /* number of digits */
     unsigned int sign;     /* see sign contstants above */
-    long exp;
+    exp_t exp;
     signed char *digits;   /* digits are stored as the actual numbers 0-9 */
     long limb_count;	/* number of limbs */
     long *limbs;
@@ -37,8 +38,8 @@
     int clamp;        /* change exponents if they are too high */
     
     /* min/max exponents */
-    long Emin;
-    long Emax;
+    exp_t Emin;
+    exp_t Emax;
 
     /* signal handling -- these are dicts */
     PyObject *traps;   /* if a signal is trapped */

Modified: sandbox/trunk/decimal-c/test_decimal.py
==============================================================================
--- sandbox/trunk/decimal-c/test_decimal.py	(original)
+++ sandbox/trunk/decimal-c/test_decimal.py	Thu Jul  6 03:06:35 2006
@@ -28,7 +28,7 @@
 import glob
 import os, sys
 import pickle, copy
-from decimal import *
+from _decimal import *
 from test.test_support import (TestSkipped, run_unittest, run_doctest,
                                is_resource_enabled)
 import random
@@ -1047,9 +1047,11 @@
     def test_pickle(self):
         c = Context()
         e = pickle.loads(pickle.dumps(c))
-        for k in vars(c):
-            v1 = vars(c)[k]
-            v2 = vars(e)[k]
+        for k in dir(c):
+            #v1 = vars(c)[k]
+            v1 = c.__getattribute__(k)
+            #v2 = vars(e)[k]
+            v2 = c.__getattribute__(k)
             self.assertEqual(v1, v2)
 
     def test_equality_with_other_types(self):
@@ -1079,7 +1081,7 @@
         DecimalExplicitConstructionTest,
         DecimalImplicitConstructionTest,
         DecimalArithmeticOperatorsTest,
-        #DecimalUseOfContextTest,
+        DecimalUseOfContextTest,
         DecimalUsabilityTest,
         DecimalPythonAPItests,
         ContextAPItests,
@@ -1088,7 +1090,7 @@
 
     try:
         run_unittest(*test_classes)
-        import decimal as DecimalModule
+        import _decimal as DecimalModule
         run_doctest(DecimalModule, verbose)
     finally:
         setcontext(ORIGINAL_CONTEXT)


More information about the Python-checkins mailing list