[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