[Python-checkins] r51124 - sandbox/trunk/decimal-c/_decimal.c
mateusz.rukowicz
python-checkins at python.org
Sun Aug 6 02:24:51 CEST 2006
Author: mateusz.rukowicz
Date: Sun Aug 6 02:24:49 2006
New Revision: 51124
Modified:
sandbox/trunk/decimal-c/_decimal.c
Log:
Now every function work properly and passes most actual tests (except some powering tests, which cannot be passed - making code passing them, will make it unable to pass others).
Modified: sandbox/trunk/decimal-c/_decimal.c
==============================================================================
--- sandbox/trunk/decimal-c/_decimal.c (original)
+++ sandbox/trunk/decimal-c/_decimal.c Sun Aug 6 02:24:49 2006
@@ -1919,14 +1919,52 @@
ans->limbs[0] = 1;
digits = 1;
} else { /* SLOW */
+ ans = _decimal_get_copy(self);
ans = _NEW_decimalobj(self->ob_size+1, self->sign, self->exp);
if (!ans)
return NULL;
- for(i=0;i<ans->limb_count;i++)
- ans->limbs[i] = 0;
- _limb_first_n_digits(self->limbs, self->ob_size, 0, ans->limbs, ans->ob_size-1);
+ ans->limbs[ans->limb_count-1] = 0;
+ for (i=0 ; i < self->limb_count;i++)
+ ans->limbs[i] = self->limbs[i];
}
+ /* if watchexp, we need to check if after rounding ob_size is still <= prec
+ * there might be faster and easier solution I cannot see */
+ if (watchexp && digits > ctx->prec) {
+ PyObject *flags;
+ PyObject *r;
+ flags = context_ignore_all_flags(ctx);
+ if (!flags) {
+ Py_DECREF(ans);
+ return NULL;
+ }
+
+ tmp = _decimal_round(ans, digits, ctx, rounding);
+ if (!tmp) {
+ r = context_regard_flags(ctx, flags);
+ Py_DECREF(flags);
+ Py_XDECREF(r);
+ Py_DECREF(ans);
+ return NULL;
+ }
+ r = context_regard_flags(ctx, flags);
+ Py_DECREF(flags);
+ if (!r) {
+ Py_DECREF(ans);
+ Py_DECREF(tmp);
+ return NULL;
+ }
+ if (_limb_get_digit(tmp->limbs, tmp->ob_size, 0) == 0 && tmp->ob_size > 1)
+ tmp->ob_size --;
+
+ if (tmp->ob_size > ctx->prec) {
+ Py_DECREF(tmp);
+ Py_DECREF(ans);
+ return handle_InvalidOperation(self->ob_type, ctx,
+ "Rescale > prec", NULL);
+ }
+ Py_DECREF(tmp);
+ }
tmp = _decimal_round(ans, digits, ctx, rounding);
Py_DECREF(ans);
if (!tmp)
@@ -4967,62 +5005,68 @@
}
DECIMAL_UNARY_FUNC(log10);
+
+/* due to some nasty special cases, this code looks quite ugly */
static int
_do_real_decimal_comparetotal(decimalobject *self, decimalobject *other, contextobject *ctx) {
exp_t adj_self;
exp_t adj_other;
+ /* what should we return when less, greater, equal ie:
+ * when both are > 0 and aren't special then l = -1 g = 1 eq = 0
+ * when both are < 0 and aren't special then l = 1 g = -1 eq = 0
+ * when self is sNaN and other is NaN then l and g are as above, but eq = -1
+ * etc ... */
+ int when_l;
+ int when_g;
+ int cmp; /* comparison of abs(self) and abs(other) (remember, abs(NaN50) = 50 ) */
if (!ctx)
ctx = getcontext();
if (!ctx)
return 0;
+ /* sign is most important */
+ if ((other->sign &1) && !(self->sign&1))
+ return 1;
+ if ((self->sign &1) && !(other->sign&1))
+ return -1;
+
+ if (self->sign &1) {
+ when_l = 1;
+ when_g = -1;
+ }
+ else {
+ when_l = -1;
+ when_g = 1;
+ }
- if (ISSPECIAL(self) || ISSPECIAL(other)) {
-
- if (GETNAN(self) || GETNAN(other)) {
- if (!GETNAN(other))
- return 1;
- if (!GETNAN(self))
- return -1;
- if ((self->sign &1) && !(other->sign&1))
- return -1;
- if ((other->sign&1) && !(self->sign&1))
- return 1;
- if (GETNAN(other) == GETNAN(self)) {
- return 0;
- }
-
-
- if (GETNAN(other) == 2)
- return (1 ^ self->sign&1) * 2 -1;
- if (GETNAN(self) == 2)
- return (0 ^ self->sign&1) * 2 -1;
- }
-
- if (ISINF(self) || ISINF(other)) {
- if (ISINF(self) == ISINF(other))
- return 0;
+ /* abs(nan) always greater than abs(non-nan) */
+ if (GETNAN(self) && !GETNAN(other))
+ return when_g;
+ if (GETNAN(other) && !GETNAN(self))
+ return when_l;
+
+ /* both are nans */
+ if (GETNAN(self)) {
+ /* one is sNaN, and one NaN, in this case, when abs(sNaN) == abs(NaN)
+ * then NaN is greater if both signs are + and is less, if both signs
+ * are - */
+ if (GETNAN(self) != GETNAN(other)) {
+ if (GETNAN(self) == 2)
+ return when_l;
else
- return ISINF(self) > ISINF(other) ? 1 : -1;
+ return when_g;
+ /* now 'add' sign to this */
}
}
- if (!decimal_nonzero(self) && !decimal_nonzero(other)) {
- if ((self->sign&1) && !(other->sign&1))
- return -1;
- if ((other->sign&1) && !(self->sign&1))
- return 1;
-
- if (exp_eq(self->exp, other->exp))
+ if (ISINF(self) || ISINF(other)) {
+ if (ISINF(self) && ISINF(other))
return 0;
-
- return (((exp_l(other->exp, self->exp) ? 1 : 0) ^ (self->sign&1)) * 2) -1;
+ if (ISINF(self) && !ISINF(other))
+ return when_g;
+ return when_l;
}
- /* pretty obvious */
- if ((other->sign &1) && !(self->sign&1))
- return 1;
- if ((self->sign &1) && !(other->sign&1))
- return -1;
+ /* we now know that self->sign == other->sign, and everything is just fine ;P */
adj_self = ADJUSTED(self);
adj_other = ADJUSTED(other);
@@ -5039,29 +5083,40 @@
d_s = _limb_get_digit(self->limbs, self->ob_size, i);
d_o = _limb_get_digit(other->limbs, other->ob_size, i);
if (d_s != d_o) {
- ret = d_s > d_o;
- if (ret ^ (self->sign&1))
- return 1;
+ if (d_s > d_o)
+ cmp = 1;
else
- return -1;
+ cmp = -1;
+ break;
}
}
- if (exp_eq(self->exp, other->exp)) {
- return 0;
- }
- else if (exp_g(self->exp, other->exp))
- {
- return (1 ^ self->sign&1) * 2 -1;
+ /* equal */
+ /* abs(0.0000) > abs(0.0) */
+ if (i == digits) {
+ if (exp_eq(self->exp, other->exp)) {
+ cmp = 0;
+ }
+ else if (exp_g(self->exp, other->exp))
+ cmp = 1;
+ else cmp = -1;
}
- else return (0 ^ self->sign&1) * 2 -1;
}
- if (exp_g(adj_self, adj_other))
- return (1 ^ self->sign &1) * 2 -1;
+ else if (exp_g(adj_self, adj_other))
+ cmp = 1;
else
- return (0 ^ self->sign &1) * 2 -1;
+ cmp = -1;
+
+ switch (cmp) {
+ case 1: return when_g;
+ break;
+ case 0: return 0;
+ break;
+ case -1: return when_l;
+ break;
+ }
}
static decimalobject *
More information about the Python-checkins
mailing list