[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