[Python-checkins] r47087 - sandbox/trunk/decimal-c/Makefile sandbox/trunk/decimal-c/README.txt sandbox/trunk/decimal-c/_decimal.c

mateusz.rukowicz python-checkins at python.org
Sat Jun 24 00:50:55 CEST 2006


Author: mateusz.rukowicz
Date: Sat Jun 24 00:50:54 2006
New Revision: 47087

Modified:
   sandbox/trunk/decimal-c/Makefile
   sandbox/trunk/decimal-c/README.txt
   sandbox/trunk/decimal-c/_decimal.c
Log:
Powering works, there is only sqrt and remainderNear left unimplemented. Some update to README.


Modified: sandbox/trunk/decimal-c/Makefile
==============================================================================
--- sandbox/trunk/decimal-c/Makefile	(original)
+++ sandbox/trunk/decimal-c/Makefile	Sat Jun 24 00:50:54 2006
@@ -1,7 +1,7 @@
 # change PYTHON_25 to point to a 2.5 HEAD build
 # (a fairly recent HEAD is necessary)
-PYTHON_25=../../python/python
-PYTH_DIR=../../python
+PYTHON_25=../../pyth/python/python
+PYTH_DIR=../../pyth/python/
 
 all: _decimal.so run
 module: 
@@ -18,10 +18,10 @@
 	gdb $(PYTHON_25) 
 
 #_decimal.o: _decimal.c decimal.h
-#	gcc -pthread -fno-strict-aliasing -g -O1 -DNEDEBUG -Wall -Wstrict-prototypes -fPIC -I${PYTH_DIR}/Include -I${PYTH_DIR} -c _decimal.c -o _decimal.o
+#	gcc -pthread -fno-strict-aliasing -g -std=c89 -DNEDEBUG -Wall -Wstrict-prototypes -fPIC -I${PYTH_DIR}/Include -I${PYTH_DIR} -c _decimal.c -o _decimal.o
 #_decimal.so: _decimal.o
 #	gcc -pthread -shared _decimal.o -g -o _decimal.so
 
-_decimal.so: 
+_decimal.so: _decimal.c 
 	$(PYTHON_25) setup.py build
 	cp build/lib*/_decimal.so .

Modified: sandbox/trunk/decimal-c/README.txt
==============================================================================
--- sandbox/trunk/decimal-c/README.txt	(original)
+++ sandbox/trunk/decimal-c/README.txt	Sat Jun 24 00:50:54 2006
@@ -4,10 +4,9 @@
 _decimal builds as a regular stand-alone python extension module
 decimal.py and test_decimal.py are copies from the 2.5 trunk
 
-The plan is to change decimal.Decimal to inherit from _decimal.Decimal
-and replace the pure-python methods one-by-one while keeping all the
-tests passing.  This should allow us to tackle the job in small pieces
-and allow many people to tackle it at once.
+At the beginning decimal was meant to inherit from _decimal, and wrap
+not implemented functions. Now, when almost all functions work properly
+it is not necessary.
 
 Edit the Makefile to point PYTHON_25 to point to a trunk build of python
 and then run 'make' or 'make all' to build the extension and run the

Modified: sandbox/trunk/decimal-c/_decimal.c
==============================================================================
--- sandbox/trunk/decimal-c/_decimal.c	(original)
+++ sandbox/trunk/decimal-c/_decimal.c	Sat Jun 24 00:50:54 2006
@@ -688,6 +688,7 @@
 static PyObject *context_ignore_all_flags(contextobject *);
 static PyObject *context_regard_flags(contextobject *, PyObject*);
 static decimalobject *_do_decimal_absolute(decimalobject *, contextobject *, int);
+static PyObject *decimal_int(decimalobject*);
 
 /* Exception handlers *********************************************************/
 
@@ -2934,8 +2935,8 @@
         /* TODO this *need* clean up */
         if (divmod) {
             /* we need to rescale, to be compatible with python implementation */
-            PyObject *flags;
-            contextobject *ctx2;
+            PyObject *flags = 0;
+            contextobject *ctx2 = 0;
             long remainder_exp = self->exp < other->exp ? self->exp : other->exp;
             decimalobject *rescaled_rem = 0;
             decimalobject *rescaled = _decimal_rescale(result, 0, ctx, -1, 0);
@@ -2947,12 +2948,16 @@
             }
             ctx2 = context_copy(ctx);
             if (!ctx2) {
+                Py_DECREF(rescaled);
                 Py_DECREF(result);
                 Py_DECREF(remainder_ret);
                 Py_DECREF(op1);
+                return NULL;
             }
             flags = context_ignore_all_flags(ctx2);
             if (!flags) {
+                Py_DECREF(ctx2);
+                Py_DECREF(rescaled);
                 Py_DECREF(result);
                 Py_DECREF(remainder_ret);
                 Py_DECREF(op1);
@@ -3601,6 +3606,192 @@
 _do_decimal_power(decimalobject *self, decimalobject *other,
                   decimalobject *modulo, contextobject *ctx)
 {
+    decimalobject *ret=0, *val, *mul;
+    long n;
+    int sign;
+    long spot;
+    int mod = modulo != Py_None;
+    long firstprec = ctx->prec;
+    double a, b;
+    
+    if (ISINF(other) || ADJUSTED(other) > 8) {
+        return handle_InvalidOperation(self->ob_type, ctx, "x ** INF", NULL);
+    }
+
+    if (ISSPECIAL(self) || ISSPECIAL(other)) {
+        decimalobject *nan;
+        if (_check_nans(self, other, ctx, &nan))
+            return nan;
+    }
+
+    if (!_decimal_isint(other)) {
+        return handle_InvalidOperation(self->ob_type, ctx, 
+                                    "x ** (non-integer)", NULL);
+    }
+
+    if (!decimal_nonzero(self) && !decimal_nonzero(other)) {
+        return handle_InvalidOperation(self->ob_type, ctx, "0 ** 0", NULL);
+    }
+
+    if (!decimal_nonzero(other)) {
+        ret = _NEW_decimalobj(1, 0, 0);
+        ret->limbs[0] = 1;
+        return ret;
+    }
+
+    {
+        PyObject *tmp = decimal_int(other);
+        if (!tmp) 
+            return NULL;
+        
+        n = PyInt_AsLong(tmp);
+        Py_DECREF(tmp);
+
+        if (PyErr_Occurred()) {
+            return NULL;
+        }
+
+    }
+    sign = (self->sign&1) && n&1;
+
+
+    if (ISINF(self)) {
+        if (mod) {
+            return handle_InvalidOperation(self->ob_type, ctx, 
+                    "INF % x", NULL);
+        }
+
+        ret = _NEW_decimalobj(1, sign, 0);
+        ret->limbs[0] = 0;
+
+        if (n > 0) 
+            ret->sign = sign ? SIGN_NEGINF : SIGN_POSINF;
+
+        return ret;
+    }
+
+    /* XXX temporary solution */
+    a = ((double) self->exp + (double) self->ob_size - (double) 1) * (double) n;
+    b = ctx->Emax;
+
+    if (!mod && n > 0 && /* (self->exp + self->ob_size -1) * n > ctx->Emax && */
+            a > b &&
+            decimal_nonzero(self)) {
+
+        if (handle_Rounded(ctx, NULL)) {
+            return NULL;
+        }
+
+        if (handle_Inexact(ctx, NULL)) {
+            return NULL;
+        }
+
+        return handle_Overflow(self->ob_type, ctx, "Big power", sign);
+    }
+
+    firstprec = ctx->prec;
+    /* XXX I am not really sure is this ok, in python implementation it is 
+     * prec + 1 + len(str(n))*/
+    ctx->prec += 1;
+    {
+        long t = n;
+        if(!t)
+            ctx->prec += 1;
+        else
+            while(t)
+            {
+                ctx->prec += 1;
+                t/=10;
+            }
+    }
+
+    if (!mod && ctx->prec > PyDecimal_DefaultContext->Emax) {
+        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->limbs[0] = 1;
+
+    if(!val || !mul) {
+        Py_XDECREF(mul);
+        Py_XDECREF(val);
+        return NULL;
+    }
+
+    if (n < 0) {
+        decimalobject *tmp;
+        n *= -1;
+        tmp = _do_decimal__divide(val, mul, 0, ctx);
+        if (!tmp) {
+            Py_DECREF(mul);
+            Py_DECREF(val);
+            return NULL;
+        }
+
+        Py_DECREF(mul);
+        mul = tmp;
+    }
+
+    spot = 1;
+    while (spot <= n) {
+        spot <<= 1;
+    }
+
+    spot >>= 1;
+
+    while (spot) {
+        decimalobject *tmp;
+
+        tmp = _do_decimal_multiply(val, val, ctx);
+
+        if (!tmp) 
+            goto err;
+        
+        Py_DECREF(val);
+        val = tmp;
+
+        if (spot & n) {
+            tmp = _do_decimal_multiply(val, mul, ctx);
+
+            if (!tmp)
+                goto err;
+            Py_DECREF(val);
+            val = tmp;
+        }
+
+        if (mod) {
+            tmp = _do_decimal_remainder(val, modulo, ctx);
+            if (!tmp)
+                goto err;
+            Py_DECREF(val);
+            val = tmp;
+        }
+        spot >>= 1; 
+    }
+
+    ctx->prec = firstprec;
+
+    if (ctx->rounding_dec == ALWAYS_ROUND) {
+        ret = _decimal_fix(val, ctx);
+        if (!ret) 
+            goto err;
+    }
+    else {
+        ret = val;
+        Py_INCREF(val);
+    }
+
+    Py_DECREF(val);
+    Py_DECREF(mul);
+    return ret;
+
+err:
+    ctx->prec = firstprec;
+    Py_DECREF(val);
+    Py_DECREF(mul);
+    Py_XDECREF(ret);
+    return NULL;
     /* XXX */
     Py_RETURN_NONE;
 }
@@ -3608,13 +3799,30 @@
 
 static PyObject *
 decimal_power(PyObject *self, PyObject *other, PyObject *modulo) {
-#if 0
     decimalobject *res;
+    decimalobject *dec;
     contextobject *ctx = getcontext();
     if (!ctx) return NULL;
 
-    other = _convert_to_decimal(self->ob_type, other, ctx, 0);
-    if (other == NULL || other == Py_NotImplemented) return other;
+/*    other = _convert_to_decimal(self->ob_type, other, ctx, 0);
+    if (other == NULL || other == Py_NotImplemented) return other; */
+    
+    if (PyDecimal_Check(self)) {
+        other = _convert_to_decimal(self->ob_type, other, ctx, 0);
+        if (!other || other == Py_NotImplemented) 
+            return other;
+        dec = other;
+        
+    }
+
+    else {
+        assert(PyDecimal_Check(other));
+        self = _convert_to_decimal(other->ob_type, self, ctx, 0);
+        if (!self || self == Py_NotImplemented)
+            return self;
+        dec = self;
+    }
+
     
     if (modulo == Py_None) {
         Py_INCREF(modulo);
@@ -3629,12 +3837,9 @@
                             (decimalobject *)other,
                             (decimalobject *)modulo,
                             ctx);
-    Py_DECREF(other);
+    Py_DECREF(dec);
     Py_DECREF(modulo);
     return (PyObject *)res;
-#else
-    Py_RETURN_NONE;
-#endif
 }
 
 
@@ -3891,8 +4096,9 @@
         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) {
-        if (d->digits[i] > 0)
+    for (i = d->ob_size-1; i >= d->ob_size + d->exp; --i) {
+/*        if (d->digits[i] > 0)*/
+        if(_limb_get_digit(d->limbs, d->ob_size, i) > 0)
             return 0;
     }
     return 1;
@@ -5018,11 +5224,11 @@
 static PyObject *
 context_power(contextobject *self, PyObject *args)
 {               
-#if 0
-    PyObject *a, *b, *c;
+    PyObject *a, *b, *c = NULL;
     decimalobject *dec_a = NULL, *dec_b = NULL, *dec_c = NULL, *res;
     if (!PyArg_ParseTuple(args, "OO|O:power", &a, &b, &c))
         return NULL;          
+
     dec_a = (decimalobject *)_convert_to_decimal(
         &PyDecimal_DecimalType, a, self, 1);
     if (dec_a == NULL)
@@ -5035,21 +5241,25 @@
         return NULL;
     }
 
-    dec_c = (decimalobject *)_convert_to_decimal(
-        &PyDecimal_DecimalType, c, self, 1);
-    if (dec_c == NULL) {
-        Py_DECREF(dec_a);
-        Py_DECREF(dec_b);
-        return NULL;
+    if (c) {
+        dec_c = (decimalobject *)_convert_to_decimal(
+            &PyDecimal_DecimalType, c, self, 1);
+        if (dec_c == NULL) {
+            dec_c = Py_None;
+            Py_INCREF(Py_None);
+            /* XXX is it ok ? */
+            PyErr_Clear();
+        }
+    }
+    else {
+        dec_c = Py_None;
+        Py_INCREF(Py_None);
     }
     res = _do_decimal_power(dec_a, dec_b, dec_c, self);
     Py_DECREF(dec_a);
     Py_DECREF(dec_b);
     Py_DECREF(dec_c);
     return (PyObject *)res;
-#else
-    Py_RETURN_NONE;
-#endif
 }
 
 


More information about the Python-checkins mailing list