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

georg.brandl python-checkins at python.org
Wed May 24 17:06:18 CEST 2006


Author: georg.brandl
Date: Wed May 24 17:06:16 2006
New Revision: 46179

Modified:
   sandbox/trunk/decimal-c/_decimal.c
Log:
Resolve conflict.



Modified: sandbox/trunk/decimal-c/_decimal.c
==============================================================================
--- sandbox/trunk/decimal-c/_decimal.c	(original)
+++ sandbox/trunk/decimal-c/_decimal.c	Wed May 24 17:06:16 2006
@@ -925,71 +925,83 @@
     return Py_NotImplemented;
 }
 
-#define STUB_HEAD static PyObject *
-#define STUB_TAIL  (PyObject *self, PyObject *args) { return NULL; }
-#define STUB_TAIL1 (PyObject *self) { return NULL; }
-#define STUB(name)  STUB_HEAD decimal_##name STUB_TAIL
-#define STUB1(name) STUB_HEAD decimal_##name STUB_TAIL1
-
 static char *ctxkwlist[] = {"context", 0};
+static char *decctxkwlist[] = {"other", "context", 0};
 
-#define ENSURE_DECIMAL(methname, dec) \
-  dec = _convert_to_decimal((PyObject *)dec, ctx); \
-  if (!dec) { \
-      PyErr_SetString(PyExc_TypeError, methname ": " #dec " must be a Decimal object"); \
-      return NULL; \
-  }
-
-#define ENSURE_CONTEXT(methname, ctx) \
-  if (ctx == NULL) { \
-      if (!(ctx = getcontext())) return NULL; \
-  } else if (!PyDecimalContext_Check(ctx)) { \
-      PyErr_SetString(PyExc_TypeError, methname ": context must be a Context object"); \
-      return NULL; \
-  }
-
-#define PARSE_CONTEXT(methname, ctx) \
-  if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O:" methname, ctxkwlist, &ctx)) \
-     { return NULL; } \
-  ENSURE_CONTEXT(methname, ctx)
+#define ENSURE_DECIMAL(methname, dec, type)                             \
+    dec = _convert_to_decimal(type, (PyObject *)dec, ctx, 1);           \
+    if (!dec) {                                                         \
+        PyErr_SetString(PyExc_TypeError, methname ": " #dec " must be a Decimal object"); \
+        return NULL;                                                    \
+    }
 
-STUB(compare)
+#define ENSURE_CONTEXT(methname, ctx)                                   \
+    if (ctx == NULL) {                                                  \
+        if (!(ctx = getcontext())) return NULL;                         \
+    } else if (!PyDecimalContext_Check(ctx)) {                          \
+        PyErr_SetString(PyExc_TypeError, methname ": context must be a Context object"); \
+        return NULL;                                                    \
+    }
 
-static decimalobject *
-decimal_max(decimalobject *self, PyObject *args, PyObject *kwds)
-{
-    static char *kwlist[] = {"other", "context", 0};
-    decimalobject *other = NULL;
-    contextobject *ctx = NULL;
+#define DECIMAL_UNARY_FUNC(methname)                               \
+    static PyObject *                                                   \
+    decimal_##methname(decimalobject *self, PyObject *args, PyObject *kwds) \
+    {                                                                   \
+        contextobject *ctx = NULL;                                      \
+        if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O:" #methname, ctxkwlist, &ctx)) \
+            return NULL;                                                \
+        ENSURE_CONTEXT(#methname, ctx);                                 \
+        return _do_decimal_##methname(self, ctx);                       \
+    }
+
+#define DECIMAL_BINARY_FUNC(methname)                                   \
+    static PyObject *                                                   \
+    decimal_##methname(decimalobject *self, PyObject *args, PyObject *kwds) \
+    {                                                                   \
+        decimalobject *res;                                             \
+        decimalobject *dec = NULL;                                      \
+        contextobject *ctx = NULL;                                      \
+        if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|O:" #methname,  \
+                                         decctxkwlist, &dec, &ctx))     \
+            return NULL;                                                \
+        ENSURE_CONTEXT(#methname, ctx);                                 \
+        ENSURE_DECIMAL(#methname, dec, self->ob_type);                  \
+        res = _do_decimal_##methname(self, dec, ctx);                   \
+        Py_DECREF(dec);                                                 \
+        return res;                                                     \
+    }
+        
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|O:max", kwlist,
-                                     &other, &ctx))
-        return NULL;
-    ENSURE_CONTEXT("max", ctx);
 
+static decimalobject *
+_do_decimal_compare(decimalobject *self, decimalobject *other,
+                    contextobject *ctx)
+{
+    /* XXX */
 }
+DECIMAL_BINARY_FUNC(compare)
 
 static decimalobject *
-decimal_min(decimalobject *self, PyObject *args, PyObject *kwds)
+_do_decimal_max(decimalobject *self, decimalobject *other,
+                contextobject *ctx)
 {
-    static char *kwlist[] = {"other", "context", 0};
-    decimalobject *other = NULL;
-    contextobject *ctx = NULL;
+    /* XXX */
+}
+DECIMAL_BINARY_FUNC(max)
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|O:min", kwlist,
-                                     &other, &ctx))
-        return NULL;
-    ENSURE_CONTEXT("max", ctx);
+static decimalobject *
+_do_decimal_min(decimalobject *self, decimalobject *other,
+                contextobject *ctx)
+{
+    /* XXX */
 }
+DECIMAL_BINARY_FUNC(min)
 
 /* strip trailing 0s, change anything equal to 0 to 0e0 */
 static decimalobject *
-decimal_normalize(decimalobject *self, PyObject *args, PyObject *kwds)
+_do_decimal_normalize(decimalobject *self, contextobject *ctx)
 {
     decimalobject *dup, *new;
-    contextobject *ctx = NULL;
-    PARSE_CONTEXT("normalize", ctx);
-
     if (ISSPECIAL(self)) {
         decimalobject *nan = NULL;
         int res;
@@ -1016,8 +1028,32 @@
     }
     return dup;
 }
+DECIMAL_UNARY_FUNC(normalize)
 
 /* Quantize self so that its exponent is the same as the exponent of another. */
+
+static decimalobject *
+_do_decimal_quantize(decimalobject *self, decimalobject *other,
+                     contextobject *ctx, int rounding, int watchexp)
+{
+    if (ISSPECIAL(self) || ISSPECIAL(other)) {
+        decimalobject *nan = NULL;
+        int res;
+        res = _check_nans(self, other, ctx, &nan);
+        if (res != 0) return nan;  /* can be NULL on error */
+
+        if (ISINF(self) || ISINF(other)) {
+            if (ISINF(self) && ISINF(other)) {
+                Py_INCREF(self);
+                return self;
+            }
+            return handle_InvalidOperation(self->ob_type, ctx, 
+                                           "quantize with one INF", NULL);
+        }
+    }
+    return _decimal_rescale(self, other->exp, ctx, rounding, watchexp);
+}
+
 static decimalobject *
 decimal_quantize(decimalobject *self, PyObject *args, PyObject *kwds)
 {
@@ -1041,42 +1077,22 @@
         PyErr_SetString(PyExc_TypeError, "exp must be a Decimal object");
         return NULL;
     }
-    if (ISSPECIAL(self) || ISSPECIAL(other)) {
-        decimalobject *nan = NULL;
-        int res;
-        res = _check_nans(self, other, ctx, &nan);
-        if (res != 0) return nan;  /* can be NULL on error */
 
-        if (ISINF(self) || ISINF(other)) {
-            if (ISINF(self) && ISINF(other)) {
-                Py_INCREF(self);
-                return self;
-            }
-            return handle_InvalidOperation(self->ob_type, ctx, 
-                                           "quantize with one INF", NULL);
-        }
-    }
-    return _decimal_rescale(self, other->exp, ctx, rounding, watchexp);
+    return _do_decimal_quantize(self, other, ctx, rounding, watchexp);
 }
 
 
-STUB(remainder_near)
-
-static PyObject *
-decimal_same_quantum(decimalobject *self, PyObject *args, PyObject *kwds)
+static decimalobject *
+_do_decimal_remainder_near(decimalobject *self, decimalobject *other,
+                           contextobject *ctx)
 {
-    static char *kwlist[] = {"other", 0};
-    decimalobject *other = NULL;
-
-    if (!PyArg_ParseTupleAndKeywords(args, kwds, "O:same_quantum", kwlist,
-                                     &other))
-        return NULL;
+}
+DECIMAL_BINARY_FUNC(remainder_near)
 
-    if (!PyDecimal_Check(other)) {
-        PyErr_SetString(PyExc_TypeError, "other must be a Decimal object");
-        return NULL;
-    }
 
+static PyObject *
+_do_decimal_same_quantum(decimalobject *self, decimalobject *other)
+{
     if (ISSPECIAL(self) && ISSPECIAL(other)) {
         if (GETNAN(self) || GETNAN(other)) {
             if (GETNAN(self) && GETNAN(other))
@@ -1098,9 +1114,65 @@
         Py_RETURN_FALSE;
 }
 
+static PyObject *
+decimal_same_quantum(decimalobject *self, PyObject *args, PyObject *kwds)
+{
+    static char *kwlist[] = {"other", 0};
+    decimalobject *other = NULL;
+
+
+    if (!PyArg_ParseTupleAndKeywords(args, kwds, "O:same_quantum", kwlist,
+                                     &other))
+        return NULL;
+
+
+    if (!PyDecimal_Check(other)) {
+        PyErr_SetString(PyExc_TypeError, "other must be a Decimal object");
+        return NULL;
+    }
+
+    return _do_decimal_same_quantum(self, other);
+}
+
+
+static decimalobject *
+_do_decimal_sqrt(decimalobject *self, contextobject *ctx)
+{
+}
+DECIMAL_UNARY_FUNC(sqrt)
+
+
+static decimalobject *
+_do_decimal_to_eng_string(decimalobject *self, contextobject *ctx)
+{
+    return _do_decimal_str(self, ctx, 1);
+}
+DECIMAL_UNARY_FUNC(to_eng_string)
+
 
-STUB(sqrt)
-STUB(to_integral)
+static decimalobject *
+_do_decimal_to_integral(decimalobject *self, contextobject *ctx, int rounding)
+{
+    /* XXX */
+}
+
+static PyObject *
+decimal_to_integral(decimalobject *self, PyObject *args, PyObject *kwds)
+{
+    static char *kwlist[] = {"rounding", "context", 0};
+    contextobject *ctx = NULL;
+    int rounding = -1;
+
+    if (!PyArg_ParseTupleAndKeywords(args, kwds, "|iO:to_integral", kwlist,
+                                     &rounding, &ctx))
+        return NULL;
+    ENSURE_CONTEXT("to_integral", ctx);
+    if (rounding < -1 || rounding > 6) {
+        PyErr_SetString(PyExc_ValueError, "invalid rounding value");
+        return NULL;
+    }
+    return _do_decimal_to_integral(self, ctx, rounding);
+}
 
 
 static PyObject *
@@ -1268,16 +1340,6 @@
 }
 
 PyObject *
-decimal_to_eng_string(PyObject *self, PyObject *args, PyObject *kwds)
-{
-    static char *kwlist[] = {"context", 0};
-    PyObject *context = NULL;
-
-    if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O!", kwlist, &context, &PyDecimal_DecimalContextType))
-        return NULL;
-    return _do_decimal_str((decimalobject *)self, (contextobject *)context, 1);
-}
-PyObject *
 PyDecimal_Str(PyObject *self, PyObject *args, PyObject *kwds)
 {
     return _do_decimal_str((decimalobject *)self, NULL, 0);
@@ -2338,6 +2400,8 @@
     tmp2 = PyTuple_New(0);
     if (!tmp2)
         return -1;
+    /* This is not calling _do_decimal_normalize because we're having
+       no Context ready. */
     tmp = (PyObject *)decimal_normalize(d, tmp2, NULL);
     Py_DECREF(tmp2);
     if (!tmp)
@@ -2583,10 +2647,59 @@
     return new;
 }
 
-/* Context methods ***********************************************************/
+/* Context properties *********************************************************/
 
 
-#define CSTUB(name) STUB_HEAD context_##name STUB_TAIL
+static PyObject *
+_dict_from_bitmask(int bitmask)
+{
+    PyObject *dict = NULL, *val, *dp;
+    int i, res;
+
+    dict = PyDict_New();
+    if (!dict) return NULL;
+    for (i = 0; i < NUMSIGNALS; i++) {
+        val = PyInt_FromLong(ISFLAGSET(bitmask, i));
+        if (!val) goto err;
+        res = PyDict_SetItem(dict, errors[i], val);
+        Py_DECREF(val);
+        if (val < 0) goto err;
+    }
+    dp = PyDictProxy_New(dict);
+    Py_DECREF(dict);
+    return dp;
+
+  err:
+    Py_XDECREF(dict);
+    return NULL;
+}    
+
+static PyObject *
+context_get_flags(contextobject *self)
+{
+    return _dict_from_bitmask(self->flags);
+}
+
+static PyObject *
+context_get_traps(contextobject *self)
+{
+    return _dict_from_bitmask(self->traps);
+}
+
+static PyObject *
+context_get_ignored(contextobject *self)
+{
+    return _dict_from_bitmask(self->ignored);
+}
+
+static PyGetSetDef context_getset[] = {
+    {"flags", (getter)context_get_flags, (setter)0},
+    {"traps", (getter)context_get_traps, (setter)0},
+    {"_ignored", (getter)context_get_ignored, (setter)0},
+    {NULL}
+};
+
+/* Context methods ************************************************************/
 
 static PyObject *
 context_clear_flags(contextobject *self)
@@ -2674,7 +2787,7 @@
     context_##name(contextobject *self, PyObject *args) {           \
         PyObject *a, *b;                                            \
         decimalobject *dec_a = NULL, *dec_b = NULL, *res;           \
-        if (!PyArg_ParseTuple(args, "OO:" #name)) return NULL;      \
+        if (!PyArg_ParseTuple(args, "OO:" #name, &a, &b)) return NULL;  \
         dec_a = (decimalobject *)_convert_to_decimal(               \
             &PyDecimal_DecimalType, a, self, 1);                    \
         if (dec_a == NULL) return NULL;                             \
@@ -2687,7 +2800,7 @@
         return res;                                                 \
     }
 
-/* helper so that I can use the CONTEXT_UNARY_FUNC macro above */
+/* helper so that we can use the CONTEXT_UNARY_FUNC macro above */
 #define _do_decimal_abs_with_round(a, b) \
     _do_decimal_absolute(a, b, 1)
 
@@ -2696,25 +2809,177 @@
 CONTEXT_BINARY_FUNC(divide, divide)
 CONTEXT_BINARY_FUNC(divide_int, floor_div)
 CONTEXT_BINARY_FUNC(divmod, divmod)
+CONTEXT_BINARY_FUNC(remainder, remainder)
 CONTEXT_UNARY_FUNC(minus, negative)
 CONTEXT_BINARY_FUNC(multiply, multiply)
 CONTEXT_UNARY_FUNC(plus, positive)
 CONTEXT_BINARY_FUNC(subtract, subtract)
 
-CSTUB(compare)
-CSTUB(min)
-CSTUB(max)
-CSTUB(normalize)
-CSTUB(power)
-CSTUB(quantize)
-CSTUB(reduce)
-CSTUB(remainder)
-CSTUB(remainder_near)
-CSTUB(same_quantum)
-CSTUB(sqrt)
-CSTUB(to_eng_string)
-CSTUB(to_integral)
-CSTUB(to_sci_string)
+CONTEXT_BINARY_FUNC(compare, compare)
+CONTEXT_BINARY_FUNC(min, min)
+CONTEXT_BINARY_FUNC(max, max)
+CONTEXT_UNARY_FUNC(normalize, normalize)
+CONTEXT_BINARY_FUNC(remainder_near, remainder_near)
+CONTEXT_UNARY_FUNC(sqrt, sqrt)
+CONTEXT_UNARY_FUNC(to_eng_string, to_eng_string)
+
+
+/* Unfortunately, the following methods are non-standard and can't
+   be created by macros. */
+
+static PyObject *
+context_power(contextobject *self, PyObject *args)
+{               
+    PyObject *a, *b, *c;                                                
+    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)
+        return NULL;                                 
+
+    dec_b = (decimalobject *)_convert_to_decimal(                   
+        &PyDecimal_DecimalType, b, self, 1);                        
+    if (dec_b == NULL) {
+        Py_DECREF(dec_a);
+        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;
+    }
+    res = _do_decimal_power(dec_a, dec_b, dec_c, self);                
+    Py_DECREF(dec_a);                                               
+    Py_DECREF(dec_b);
+    Py_DECREF(dec_c);
+    return res;                                                     
+}
+
+
+static PyObject *
+context_quantize(contextobject *self, PyObject *args)
+{
+    PyObject *a, *b;
+    decimalobject *dec_a = NULL, *dec_b = NULL, *res;
+    if (!PyArg_ParseTuple(args, "OO:quantize", &a, &b))
+        return NULL;
+
+    dec_a = (decimalobject *)_convert_to_decimal(
+        &PyDecimal_DecimalType, a, self, 1);
+    if (dec_a == NULL)
+        return NULL;
+
+    dec_b = (decimalobject *)_convert_to_decimal(
+        &PyDecimal_DecimalType, b, self, 1);
+    if (dec_b == NULL) {
+        Py_DECREF(dec_a);
+        return NULL;
+    }
+
+    res = _do_decimal_quantize(dec_a, dec_b, self, -1, 1);
+    Py_DECREF(dec_a);
+    Py_DECREF(dec_b);
+    return res;
+}
+
+
+static PyObject *
+context_same_quantum(contextobject *self, PyObject *args)
+{
+    PyObject *a, *b, *res;
+    decimalobject *dec_a = NULL, *dec_b = NULL;
+    if (!PyArg_ParseTuple(args, "OO:same_quantum", &a, &b))
+        return NULL;
+
+    dec_a = (decimalobject *)_convert_to_decimal(
+        &PyDecimal_DecimalType, a, self, 1);
+    if (dec_a == NULL)
+        return NULL;
+
+    dec_b = (decimalobject *)_convert_to_decimal(
+        &PyDecimal_DecimalType, b, self, 1);
+    if (dec_b == NULL) {
+        Py_DECREF(dec_a);
+        return NULL;
+    }
+
+    res = _do_decimal_same_quantum(dec_a, dec_b);
+    Py_DECREF(dec_a);
+    Py_DECREF(dec_b);
+    return res;
+}
+
+
+static PyObject *
+context_to_integral(contextobject *self, PyObject *args)
+{
+    PyObject *a, *res;
+    decimalobject *dec_a = NULL;
+
+    if (!PyArg_ParseTuple(args, "O:to_integral", &a))
+        return NULL;
+
+    dec_a = (decimalobject *)_convert_to_decimal(
+        &PyDecimal_DecimalType, a, self, 1);
+    if (dec_a == NULL)
+        return NULL;
+
+    res = _do_decimal_to_integral(dec_a, self, -1);
+    Py_DECREF(dec_a);
+    return res;
+}
+
+
+static PyObject *
+context_to_sci_string(contextobject *self, PyObject *args)
+{
+    PyObject *a, *res;
+    decimalobject *dec_a = NULL;
+
+    if (!PyArg_ParseTuple(args, "O:to_sci_string", &a))
+        return NULL;
+
+    dec_a = (decimalobject *)_convert_to_decimal(
+        &PyDecimal_DecimalType, a, self, 1);
+    if (dec_a == NULL)
+        return NULL;
+
+    /* XXX: default third argument? */
+    res = _do_decimal_str(dec_a, self, -1);
+    Py_DECREF(dec_a);
+    return res;
+}
+
+
+static PyObject *
+context_reduce(contextobject *self)
+{
+    PyObject *flags = NULL, *traps = NULL, *ignored = NULL;
+    PyObject *res = NULL;
+
+    flags = context_get_flags(self);
+    if (!flags) goto err;
+    traps = context_get_traps(self);
+    if (!traps) goto err;
+    ignored = context_get_ignored(self);
+    if (!ignored) goto err;
+
+    res = Py_BuildValue("liiOOlliiO", self->prec, self->rounding,
+                        self->rounding_dec, traps, flags, self->Emin,
+                        self->Emax, self->capitals, self->clamp,
+                        ignored);
+
+  err:
+    Py_XDECREF(flags);
+    Py_XDECREF(traps);
+    Py_XDECREF(ignored);
+    return res;
+}
 
 
 static PyMethodDef context_methods[] = {
@@ -2791,8 +3056,6 @@
     c->ob_type->tp_free(c);
 }
 
-CSTUB(richcompare)
-
 static PyObject *
 context_repr(contextobject *self)
 {
@@ -2973,59 +3236,6 @@
                                        ignored);
 }
 
-static PyObject *
-context_get_flags(contextobject *self)
-{
-    PyObject *dict = NULL, *val, *dp;
-    int i, res;
-
-    dict = PyDict_New();
-    if (!dict) return NULL;
-    for (i = 0; i < NUMSIGNALS; i++) {
-        val = PyInt_FromLong(ISFLAGSET(self->flags, i));
-        if (!val) goto err;
-        res = PyDict_SetItem(dict, errors[i], val);
-        Py_DECREF(val);
-        if (val < 0) goto err;
-    }
-    dp = PyDictProxy_New(dict);
-    Py_DECREF(dict);
-    return dp;
-
-  err:
-    Py_XDECREF(dict);
-    return NULL;
-}
-
-static PyObject *
-context_get_traps(contextobject *self)
-{
-    PyObject *dict = NULL, *val, *dp;
-    int i, res;
-
-    dict = PyDict_New();
-    if (!dict) return NULL;
-    for (i = 0; i < NUMSIGNALS; i++) {
-        val = PyInt_FromLong(ISFLAGSET(self->traps, i));
-        if (!val) goto err;
-        res = PyDict_SetItem(dict, errors[i], val);
-        Py_DECREF(val);
-        if (val < 0) goto err;
-    }
-    dp = PyDictProxy_New(dict);
-    Py_DECREF(dict);
-    return dp;
-
-  err:
-    Py_XDECREF(dict);
-    return NULL;
-}
-
-static PyGetSetDef context_getset[] = {
-    {"flags", (getter)context_get_flags, (setter)0},
-    {"traps", (getter)context_get_traps, (setter)0},
-    {NULL}
-};
 
 #define OFF(x) offsetof(contextobject, x)
 
@@ -3066,7 +3276,7 @@
     context_doc,                /* tp_doc */
     0,                          /* tp_traverse */
     0,                          /* tp_clear */
-    (richcmpfunc)context_richcompare, /* tp_richcompare */
+    0,                          /* tp_richcompare */
     0,                          /* tp_weaklistoffset */
     0,                          /* tp_iter */
     0,                          /* tp_iternext */
@@ -3162,8 +3372,10 @@
     return 0;
 }    
 
-#define ADD_CONST(m, name)                                          \
-    if (PyModule_AddIntConstant(m, #name, name) < 0) { return; }
+#define ADD_CONST(m, name)                               \
+    if (PyModule_AddIntConstant(m, #name, name) < 0) {   \
+        return;                                          \
+    }
 
 #define INIT_EXC(m, name, base)                                     \
     name = PyErr_NewException(MODULE_NAME "." #name, base, NULL);   \


More information about the Python-checkins mailing list