[Python-checkins] r51120 - sandbox/trunk/decimal-c/_decimal.c

mateusz.rukowicz python-checkins at python.org
Sat Aug 5 02:44:54 CEST 2006


Author: mateusz.rukowicz
Date: Sat Aug  5 02:44:53 2006
New Revision: 51120

Modified:
   sandbox/trunk/decimal-c/_decimal.c
Log:
Added log10 and comparetotal functions, there are still some things to do.


Modified: sandbox/trunk/decimal-c/_decimal.c
==============================================================================
--- sandbox/trunk/decimal-c/_decimal.c	(original)
+++ sandbox/trunk/decimal-c/_decimal.c	Sat Aug  5 02:44:53 2006
@@ -4785,7 +4785,244 @@
 
 DECIMAL_UNARY_FUNC(ln);
 
+static PyObject *
+_do_decimal_log10(decimalobject *self, contextobject *ctx) {
+    decimalobject *ret;
+    long prec;
+    contextobject *ctx2;
+    PyObject *flags;
+
+    if (!ctx)
+        ctx = getcontext();
+    if (!ctx)
+        return NULL;
+
+    if (ISSPECIAL(self)) {
+        decimalobject *nan;
+        if (_check_nans(self, NULL, ctx, &nan) != 0)
+            return nan;
+
+        if (ISINF(self)) {
+            if (self->sign &1) 
+                return handle_InvalidOperation(self->ob_type, ctx, "log10(-inf)", NULL);
+            else
+                return _decimal_get_copy(self);
+        }
+    }
+
+
+    if (self->sign &1 && decimal_nonzero(self)) 
+        return handle_InvalidOperation(self->ob_type, ctx, "log10(-x)", NULL);
+    
+    /* first, check if self is power of 10*/
+
+    if (_limb_get_digit(self->limbs, self->ob_size, 0) == 1) {
+        /* SLOW */
+        int i;
+        for (i=1;i<self->ob_size;i++) {
+            if (_limb_get_digit(self->limbs, self->ob_size, i)) 
+                break;
+        }
+        /* self is power of 10 */
+        if (i == self->ob_size) {
+            decimalobject *fixed;
+            /* TODO what about big exp? */
+            ret = decimal_from_long(self->ob_type, exp_to_i(ADJUSTED(self)));
+            if (!ret)
+                return NULL;
+
+            fixed = _decimal_fix(ret, ctx);
+            Py_DECREF(ret);
+            return fixed;
+        }
+    }
+
+    /* we use context precision, or self->ob_size + 6 (biggest size of exponent)
+     * + 3 as precision */
+    prec = self->ob_size + 6 > ctx->prec ? self->ob_size+9: ctx->prec+3;
+    
+    ctx2 = context_shallow_copy(ctx);
+    if (!ctx2)
+        return NULL;
+
+    ctx2->prec = prec;
+    ctx2->Emax = exp_from_i(MAX_MATH);
+    ctx2->Emin = exp_from_i(-MAX_MATH);
+
+    {
+        decimalobject *a;   /* ln(self) */
+        decimalobject *ten; /* Decimal(10) */
+        decimalobject *ln10;   /* ln(10) */
+        
+        a = _do_decimal__ln(self, ctx2);
+        if (!a) {
+            Py_DECREF(ctx2);
+            return NULL;
+        }
+
+        ten = _NEW_decimalobj(2, 0, exp_from_i(0));
+        if (!ten) {
+            Py_DECREF(a);
+            Py_DECREF(ctx2);
+            return NULL;
+        }
+        ten->limbs[0] = 10;
+        flags = context_ignore_all_flags(ctx2);
+        if (!flags) {
+            Py_DECREF(a);
+            Py_DECREF(ctx2);
+            Py_DECREF(ten);
+            return NULL;
+        }
+        ctx2->prec = ctx->prec + 3;
+
+        ln10 = _do_decimal__ln(ten, ctx2);
+        Py_DECREF(ten);
+        
+        if (!ln10) {
+            Py_DECREF(a);
+            Py_DECREF(ctx2);
+            Py_DECREF(flags);
+            return NULL;
+        }
+        
+        {
+            PyObject *tmp = context_regard_flags(ctx2, flags);
+            Py_DECREF(flags);
+            if (!tmp) {
+                Py_DECREF(a);
+                Py_DECREF(ctx2);
+                return NULL;
+            }
+            Py_DECREF(tmp);
+        }
+
+        /* log10 = ln(self)/ln(10) */
+        ret = _do_decimal__divide(a, ln10, 0, ctx);
+        Py_DECREF(a);
+        Py_DECREF(ln10);
+
+        return ret;
+        
+    }
+}
+DECIMAL_UNARY_FUNC(log10);
+
+static int
+_do_real_decimal_comparetotal(decimalobject *self, decimalobject *other, contextobject *ctx) {
+    exp_t adj_self;
+    exp_t adj_other;
+    if (!ctx)
+        ctx = getcontext();
+    if (!ctx)
+        return 0;
+
+    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;
+            else
+                return ISINF(self) > ISINF(other) ? 1 : -1;
+        }
+    }
+
+    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))
+            return 0;
+        
+        return (((exp_l(other->exp, self->exp) ? 1 : 0) ^ (self->sign&1)) * 2) -1;
+    }
+
+    /* pretty obvious */
+    if ((other->sign &1) && !(self->sign&1))
+        return 1;
+    if ((self->sign &1) && !(other->sign&1))
+        return -1;
+
+    adj_self = ADJUSTED(self);
+    adj_other = ADJUSTED(other);
+
+    if (exp_eq(adj_self, adj_other)) {
+        long digits = self->ob_size > other->ob_size ? self->ob_size : other->ob_size;
+        long i;
+        long ret;
+        /* SLOW */
+
+        for (i=0;i<digits;i++) {
+            int d_s;
+            int d_o;
+            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;
+                else
+                    return -1;
+            }
+        }
+
+        if (exp_eq(self->exp, other->exp)) {
+            return 0;
+        }
+        else if (exp_g(self->exp, other->exp))
+        {
+            return (1 ^ self->sign&1) * 2 -1;
+        }
+        else return (0 ^ self->sign&1) * 2 -1;
+    }
+
+    if (exp_g(adj_self, adj_other))
+        return (1 ^ self->sign &1) * 2 -1;
+    else 
+        return (0 ^ self->sign &1) * 2 -1;
+    
+}
+
+static decimalobject *
+_do_decimal_comparetotal(decimalobject *self, decimalobject *other, contextobject *ctx) 
+{
+    int res;
+
+    res = _do_real_decimal_comparetotal(self, other, ctx);
+    return decimal_from_long(self->ob_type, res);
+}
+
+DECIMAL_BINARY_FUNC(comparetotal);
+
 static PyMethodDef decimal_methods[] = {
+    {"comparetotal",    (PyCFunction)decimal_comparetotal,
+    METH_VARARGS | METH_KEYWORDS,
+    PyDoc_STR("TODO")},
+    {"log10",           (PyCFunction)decimal_log10,
+    METH_VARARGS | METH_KEYWORDS,
+    PyDoc_STR("TODO")},
     {"ln",              (PyCFunction)decimal_ln,
     METH_VARARGS | METH_KEYWORDS,
     PyDoc_STR("TODO")},
@@ -7168,6 +7405,8 @@
 CONTEXT_UNARY_FUNC(to_eng_string, to_eng_string)
 CONTEXT_UNARY_FUNC(exp, exp)
 CONTEXT_UNARY_FUNC(ln, ln);
+CONTEXT_UNARY_FUNC(log10, log10);
+CONTEXT_BINARY_FUNC(comparetotal, comparetotal);
 
 
 /* Unfortunately, the following methods are non-standard and can't
@@ -7694,6 +7933,10 @@
      METH_O},
     {"ln",              (PyCFunction)context_ln,
      METH_O},
+    {"log10",           (PyCFunction)context_log10,
+     METH_O},
+    {"comparetotal",    (PyCFunction)context_comparetotal,
+     METH_VARARGS},
     {"subtract",        (PyCFunction)context_subtract,
      METH_VARARGS},
     {"to_eng_string",   (PyCFunction)context_to_eng_string,


More information about the Python-checkins mailing list