[Python-checkins] r46842 - sandbox/trunk/decimal-c/_decimal.c
mateusz.rukowicz
python-checkins at python.org
Sun Jun 11 01:33:54 CEST 2006
Author: mateusz.rukowicz
Date: Sun Jun 11 01:33:53 2006
New Revision: 46842
Modified:
sandbox/trunk/decimal-c/_decimal.c
Log:
Multiplying and min works.
Modified: sandbox/trunk/decimal-c/_decimal.c
==============================================================================
--- sandbox/trunk/decimal-c/_decimal.c (original)
+++ sandbox/trunk/decimal-c/_decimal.c Sun Jun 11 01:33:53 2006
@@ -301,6 +301,59 @@
return left_digits;
}
+/* temporary solution, will be speeded up */
+static long
+_limb_multiply_core(long *first, long flimbs, long *second, long slimbs, long *out)
+{
+ long max_limbs = flimbs + slimbs;
+ long i,j;
+
+ for(i = 0;i<max_limbs;i++)
+ out[i] = 0;
+
+ for(i = 0;i<flimbs;i++)
+ for(j = 0;j<slimbs;j++)
+ {
+ out[i+j] += first[i] * second[j];
+ if(out[i+j] >= BASE)
+ {
+ out[i+j+1] += out[i+j]/BASE;
+ out[i+j] %= BASE;
+ }
+ }
+
+ for(i = 0;i<max_limbs;i++)
+ {
+ if(out[i] >= BASE)
+ {
+ assert(i+1 < max_limbs);
+ out[i+1] += out[i] / BASE;
+ out[i] %= BASE;
+ }
+ }
+
+ while(!out[max_limbs -1] && max_limbs > 1) max_limbs --;
+ return max_limbs;
+}
+
+static long
+_limb_multiply(long *first, long fsize, long *second, long ssize, long *out)
+{
+ long used_limbs;
+ long flimbs, slimbs;
+ long digits_at_most;
+ flimbs = (fsize + LOG - 1)/LOG;
+ slimbs = (ssize + LOG - 1)/LOG;
+ used_limbs = _limb_multiply_core(first, flimbs, second, slimbs, out);
+
+ digits_at_most = used_limbs * LOG;
+ if(!digits_at_most)
+ return 1;
+
+ while(_limb_get_digit(out, digits_at_most, 0) == 0 && digits_at_most >1) digits_at_most --;
+
+ return digits_at_most;
+}
/* helpful macros ************************************************************/
@@ -1540,6 +1593,8 @@
if (context_ignore_all_flags(ctx2) == NULL)
return 0; /* error */
+ Py_XDECREF(ctx2);
+
/* XXX: WTF? */
ans = _do_decimal_subtract(self, other, ctx2);
if (!ans) return 0;
@@ -1671,8 +1726,71 @@
_do_decimal_min(decimalobject *self, decimalobject *other,
contextobject *ctx)
{
- /* XXX */
- Py_RETURN_NONE;
+ decimalobject *ans;
+ long cmp;
+ decimalobject *ctx2;
+
+ if(ISSPECIAL(self) || ISSPECIAL(other))
+ {
+ decimalobject *nan;
+ int sn = GETNAN(self);
+ int so = GETNAN(other);
+
+ if(sn || so)
+ {
+ if(so == 1 && sn != 2)
+ {
+ Py_INCREF(self);
+ return self;
+ }
+ else if (sn == 1 && so != 2)
+ {
+ Py_INCREF(other);
+ return other;
+ }
+ }
+
+ if(_check_nans(self, other, ctx, &nan) != 0)
+ return nan;
+ }
+
+ ans = self;
+ if(!ctx)
+ ctx = getcontext();
+ if(!ctx)
+ return NULL;
+
+ ctx2 = getcontext();
+ if(!ctx2)
+ return NULL;
+ cmp = _do_real_decimal_compare(self,other,ctx2);
+
+ if(PyErr_Occurred())
+ return NULL;
+
+ if(!cmp)
+ {
+ if(self->sign != other->sign)
+ {
+ if(!self->sign)
+ ans = other;
+ }
+ else{
+ if(self->exp > other->exp && !self->sign)
+ ans = other;
+ else if (self->exp < other->exp && self->sign)
+ ans = other;
+ }
+ }
+ else if(cmp == 1)
+ ans = other;
+
+ if(ctx->rounding_dec == ALWAYS_ROUND)
+ return _decimal_fix(ans, ctx);
+
+ Py_INCREF(ans);
+ return ans;
+
}
DECIMAL_BINARY_FUNC(min)
@@ -1697,14 +1815,16 @@
new = _NEW_decimalobj(1, dup->sign, 0);
Py_DECREF(dup);
if (!new) return NULL;
- new->digits[0] = 0;
+ new->limbs[0] = 0;
return new;
}
/* strip trailing 0s from dup */
- while (dup->digits[dup->ob_size - 1] == 0) {
- dup->ob_size--;
- dup->exp++;
+// while (dup->digits[dup->ob_size - 1] == 0) {
+ 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 ++;
}
return dup;
}
@@ -1776,7 +1896,7 @@
static PyObject *
_do_decimal_same_quantum(decimalobject *self, decimalobject *other)
{
- if (ISSPECIAL(self) && ISSPECIAL(other)) {
+ if (ISSPECIAL(self) || ISSPECIAL(other)) {
if (GETNAN(self) || GETNAN(other)) {
if (GETNAN(self) && GETNAN(other))
Py_RETURN_TRUE;
@@ -1870,6 +1990,8 @@
&rounding, &ctx))
return NULL;
ENSURE_CONTEXT("to_integral", ctx);
+ if(rounding == -1)
+ rounding = ctx->rounding;
if (!VALID_ROUND(rounding)) {
PyErr_SetString(PyExc_ValueError, "invalid rounding value");
return NULL;
@@ -2673,12 +2795,103 @@
DECIMAL_SPECIAL_2FUNC(decimal_subtract)
+/* it's just so straightforward, wish adding was the same ;P */
static decimalobject *
_do_decimal_multiply(decimalobject *self, decimalobject *other,
contextobject *ctx)
{
- /* XXX */
- Py_RETURN_NONE;
+ long resultsign;
+ long resultexp;
+ long shouldround;
+ long i;
+ long max_limbs;
+ long size;
+ decimalobject *ans;
+
+ resultsign = (self->sign&1) ^ (other->sign&1);
+
+ if(ISSPECIAL(self) || ISSPECIAL(other))
+ {
+ decimalobject *nan;
+ if(_check_nans(self, other, ctx, &nan))
+ return nan;
+
+ if(ISINF(self))
+ {
+ if(decimal_nonzero(other))
+ {
+ ans = _NEW_decimalobj(1, resultsign ? SIGN_NEGINF : SIGN_POSINF, 0);
+ return ans;
+ }
+ return handle_InvalidOperation(self->ob_type, ctx, "(+-)INF * 0", NULL);
+ }
+
+ if(ISINF(other))
+ {
+ if(decimal_nonzero(self))
+ {
+ ans = _NEW_decimalobj(1, resultsign ? SIGN_NEGINF : SIGN_POSINF, 0);
+ return ans;
+ }
+ return handle_InvalidOperation(self->ob_type, ctx, "0 * (+-)INF", NULL);
+ }
+ }
+
+ resultexp = self->exp + other->exp;
+ shouldround = ctx->rounding_dec == ALWAYS_ROUND;
+
+ if(!decimal_nonzero(self) || !decimal_nonzero(other))
+ {
+ decimalobject *ret;
+ ans = _NEW_decimalobj(1, resultsign, resultexp);
+ if(!ans)
+ return NULL;
+
+ ans->limbs[0] = 0;
+ goto done;
+ }
+
+ if(self->ob_size == 1 && self->limbs[0] == 1)
+ {
+ ans = _NEW_decimalobj(other->ob_size, resultsign, resultexp);
+ if(!ans)
+ return NULL;
+
+ for(i = 0; i<ans->limb_count;i++)
+ ans->limbs[i] = other->limbs[i];
+ goto done;
+ }
+
+ if(other->ob_size == 1 && other->limbs[0] == 1)
+ {
+ ans = _NEW_decimalobj(self->ob_size, resultsign, resultexp);
+ if(!ans)
+ return NULL;
+
+ for(i = 0; i<ans->limb_count; i++)
+ ans->limbs[i] = self->limbs[i];
+
+ goto done;
+ }
+
+ max_limbs = (self->ob_size + LOG -1)/ LOG + (other->ob_size + LOG -1)/LOG;
+ ans = _NEW_decimalobj(max_limbs * LOG, resultsign, resultexp);
+ if(!ans)
+ return NULL;
+
+ size = _limb_multiply(self->limbs, self->ob_size, other->limbs, other->ob_size, ans->limbs);
+
+ ans->ob_size = size;
+
+
+done:
+ if(shouldround)
+ {
+ decimalobject *fixed = _decimal_fix(ans, ctx);
+ Py_DECREF(ans);
+ return fixed;
+ }
+ return ans;
}
DECIMAL_SPECIAL_2FUNC(decimal_multiply)
@@ -4333,12 +4546,13 @@
static PyObject *
-context_to_integral(contextobject *self, PyObject *args)
+context_to_integral(contextobject *self, PyObject *args, PyObject *kwds)
{
+ static char *kwlist[] = {"a", 0};
PyObject *a, *res;
decimalobject *dec_a = NULL;
- if (!PyArg_ParseTuple(args, "O:to_integral", &a))
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "O:to_integral", kwlist, &a))
return NULL;
dec_a = (decimalobject *)_convert_to_decimal(
@@ -4714,7 +4928,7 @@
{"to_eng_string", (PyCFunction)context_to_eng_string,
METH_O},
{"to_integral", (PyCFunction)context_to_integral,
- METH_O},
+ METH_VARARGS | METH_KEYWORDS},
{"to_sci_string", (PyCFunction)context_to_sci_string,
METH_VARARGS | METH_KEYWORDS},
{"_ignore_all_flags", (PyCFunction)context_ignore_all_flags,
More information about the Python-checkins
mailing list