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

georg.brandl python-checkins at python.org
Fri May 26 11:35:32 CEST 2006


Author: georg.brandl
Date: Fri May 26 11:35:31 2006
New Revision: 46277

Modified:
   sandbox/trunk/decimal-c/_decimal.c
   sandbox/trunk/decimal-c/decimal.h
Log:
Checkpoint.



Modified: sandbox/trunk/decimal-c/_decimal.c
==============================================================================
--- sandbox/trunk/decimal-c/_decimal.c	(original)
+++ sandbox/trunk/decimal-c/_decimal.c	Fri May 26 11:35:31 2006
@@ -7,11 +7,15 @@
 /* Notable incompatibilities between this and the original decimal.py:
 
    - Rounding constants are integers.
-   - There's handle method on the exceptions.
+   - There's no handle method on the exceptions.
    - Special values are represented by special sign values, so
      the results of as_tuple() differ.
    - Many internal "underscore" methods are not accessible on the object.
+*/
 
+/* This is not yet optimized C code, but mostly translated
+   Python that was not really made for translating, though
+   it originally should have been.
 */
 
 #include "Python.h"
@@ -27,10 +31,6 @@
 #define contextobject PyDecimalContextObject
 #define decimalobject PyDecimalObject
 
-/* for context->flags, ->traps, ->ignored */
-#define ISFLAGSET(f, b) (((f) >> b) & 1)
-#define SETFLAG(f, b) (f |= (1 << b))
-#define UNSETFLAG(f, b) (f ^= (1 << b))
 
 /* Checks */
 
@@ -129,6 +129,38 @@
 static PyObject *errors[NUMSIGNALS+NUMCONDITIONS];
 
 
+/* for context->flags, ->traps, ->ignored *************************************/
+
+/* XXX: lazy error checking */
+static int
+_is_flag_set(PyObject *d, int f)
+{
+    PyObject *item = PyDict_GetItem(d, errors[f]);
+    if (item)
+        return PyObject_IsTrue(item);
+    return 0;
+}
+
+static int
+_set_flag(PyObject *d, int f, int v)
+{
+    PyObject *i = PyInt_FromLong(v);
+    PyObject *item;
+    int res = 0;
+    
+    if (!i) return -1;
+    item = PyDict_GetItem(d, errors[f]);
+    if (item)
+        res = PyObject_IsTrue(item);
+    
+    if (PyDict_SetItem(d, errors[f], i) < 0)
+        res = -1;
+    Py_DECREF(i);
+    return res;
+}
+
+
+
 /* Forwarding ****************************************************************/
 
 static contextobject *getcontext(void);
@@ -142,18 +174,22 @@
 static PyObject *decimal_str(decimalobject *);
 static PyObject *_do_decimal_str(decimalobject *, contextobject *, int);
 static decimalobject *_new_decimalobj(PyTypeObject *, long, char, long);
+static decimalobject *_do_decimal_subtract(decimalobject *, decimalobject *, contextobject *);
+static contextobject *context_shallow_copy(contextobject *);
+static PyObject *context_ignore_all_flags(contextobject *);
+static decimalobject *_do_decimal_absolute(decimalobject *, contextobject *, int);
 
 /* Exception handlers *********************************************************/
 
 /* Raise the exception if signal is trapped and not ignored. */
-#define HANDLE_ERROR(ctx, cond, expl, onerror)                    \
-    int err = (cond >= NUMSIGNALS ? S_INV_OPERATION : cond);      \
-    if (! ISFLAGSET(ctx->ignored, err)) {                         \
-        SETFLAG(ctx->flags, err);                                 \
-        if (ISFLAGSET(ctx->traps, err)) {                         \
-            PyErr_SetString(errors[err], (expl ? expl : ""));     \
-            return onerror;                                       \
-        }                                                         \
+#define HANDLE_ERROR(ctx, cond, expl, onerror)                         \
+    int err = (cond >= NUMSIGNALS ? S_INV_OPERATION : cond);           \
+    if (! _is_flag_set(ctx->ignored, err)) {                           \
+        _set_flag(ctx->flags, err, 1);                                 \
+        if (_is_flag_set(ctx->traps, err)) {                           \
+            PyErr_SetString(errors[err], (expl ? expl : ""));          \
+            return onerror;                                            \
+        }                                                              \
     }
 
 
@@ -321,24 +357,30 @@
 _new_decimalobj(PyTypeObject *type, long ndigits, char sign, long exp)
 {
     decimalobject *new;
-    char *arr;
+    char *arr = NULL;
+    
     if (ndigits > LONG_MAX) {
         PyErr_NoMemory();
         return NULL;
     }
+    
     arr = PyObject_MALLOC(ndigits);
     if (!arr) {
         PyErr_NoMemory();
-        return NULL;
+        goto err;
     }
     new = (decimalobject *)type->tp_alloc(type, 0);
     if (new == NULL)
-        return NULL;
+        goto err;
     new->sign = sign;
     new->exp = exp;
     new->ob_size = ndigits;
     new->digits = arr;
     return new;
+        
+  err:
+    if (arr) PyObject_FREE(arr);
+    return NULL;
 }
 
 /* shortcut for use in methods */
@@ -608,7 +650,7 @@
     if (prec == -1)
         prec = ctx->prec;
     
-    if (rounding < 0 || rounding > ROUND_CEILING) {
+    if (!VALID_ROUND(rounding)) {
         PyErr_SetString(PyExc_ValueError, "invalid rounding mode");
         return NULL;
     }
@@ -827,7 +869,7 @@
                 return NULL;
             if (handle_Subnormal(ctx, NULL) != 0)
                 goto err;
-            if (ISFLAGSET(ctx->flags, S_INEXACT)) {
+            if (_is_flag_set(ctx->flags, S_INEXACT)) {
                 if (handle_Underflow(ctx, NULL) != 0)
                     goto err;
             }
@@ -978,19 +1020,159 @@
     }
 
 
+/* Returns -1, 0, 1. No special error return code, must check
+   PyErr_Occurred() */
+static int
+_do_real_decimal_compare(decimalobject *self, decimalobject *other,
+                         contextobject *ctx)
+{
+    long adj1, adj2;
+    long i, minsize;
+    decimalobject *longer, *ans;
+    contextobject *ctx2;
+    
+    if (ISSPECIAL(self) || ISSPECIAL(other)) {
+        decimalobject *nan;
+        if (_check_nans(self, other, ctx, &nan) != 0) {
+            Py_XDECREF(nan);
+            /* comparisons with NaN always report self>other */
+            return 1;
+        }
+    }
+
+    /* If both are 0, sign comparison isn't correct. */
+    if (!decimal_nonzero(self) && !decimal_nonzero(other))
+        return 0;
+
+    /* If different signs, neg one is less */
+    if ((other->sign & 1) && !(self->sign & 1))
+        return 1;
+    if ((self->sign & 1) && !(other->sign & 1))
+        return -1;
+
+    adj1 = ADJUSTED(self);
+    adj2 = ADJUSTED(other);
+
+    if (adj1 == adj2) {
+        if (self->ob_size <= other->ob_size) {
+            minsize = self->ob_size;
+            longer = other;
+        } else {
+            minsize = other->ob_size;
+            longer = self;
+        }
+
+        for (i = 0; i < minsize; i++) {
+            if (self->digits[i] != other->digits[i])
+                goto next;
+        }
+        /* Okay, now the remaining digits of the longer
+           one must consist of only digits. */
+        for (i = minsize; i < longer->ob_size; i++)
+            if (longer->digits[i] != 0)
+                goto next;
+        /* All digits match, so they're equal. */
+        return 0;
+    }
+             
+  next:
+    /* Adjusted sizes are not equal. */
+    if (adj1 > adj2 && self->digits[0] != 0)
+        return 1 - 2*(self->sign & 1); /* 0 -> 1, 1 -> -1 */
+    else if (adj1 < adj2 && other->digits[0] != 0)
+        return 1 - 2*(other->sign & 1);
+
+    ctx2 = context_shallow_copy(ctx);
+    if (!ctx2) return 0; /* error */
+
+    ctx2->rounding = ROUND_UP; /* away from 0 */
+    if (context_ignore_all_flags(ctx2) == NULL)
+        return 0; /* error */
+
+    /* XXX: WTF? */
+    ans = _do_decimal_subtract(self, other, ctx2);
+    if (!ans) return 0;
+
+    if (decimal_nonzero(ans))
+        i = 0;
+    else if (ans->sign & 1)
+        i = -1;
+    else
+        i = 1;
+    Py_DECREF(ans);
+    return i;
+}
+
 static decimalobject *
 _do_decimal_compare(decimalobject *self, decimalobject *other,
                     contextobject *ctx)
 {
-    /* XXX */
+    int res;
+    if (ISSPECIAL(self) || (decimal_nonzero(other) &&
+                            ISSPECIAL(other))) {
+        decimalobject *nan;
+        if (_check_nans(self, other, ctx, &nan) != 0)
+            return nan;
+    }
+
+    res = _do_real_decimal_compare(self, other, ctx);
+    return (decimalobject *)decimal_from_long(self->ob_type, res);
 }
 DECIMAL_BINARY_FUNC(compare)
 
+
+static PyObject *
+decimal_richcompare(decimalobject *self, decimalobject *other,
+                    int op)
+{
+    int res;
+    contextobject *ctx;
+    ctx = getcontext();
+    if (!ctx) return NULL;
+
+    other = (decimalobject *)_convert_to_decimal(self->ob_type,
+                                                 (PyObject *)other,
+                                                 ctx, 0);
+    if (other == Py_NotImplemented) return other;
+
+    res = _do_real_decimal_compare(self, other, ctx);
+    Py_DECREF(other);
+    if (PyErr_Occurred())
+        return NULL;
+
+    if ( (res == 0  && (op == Py_EQ || op == Py_LE || op == Py_GT)) ||
+         (res == -1 && (op == Py_NE || op == Py_LT || op == Py_LE)) ||
+         (res == 1  && (op == Py_NE || op == Py_GT || op == Py_GE)))
+        Py_RETURN_TRUE;
+    else
+        Py_RETURN_FALSE;
+}
+
+
 static decimalobject *
 _do_decimal_max(decimalobject *self, decimalobject *other,
                 contextobject *ctx)
 {
-    /* XXX */
+    decimalobject *ans, *cmp;
+    
+    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;
+    }
+
+        
 }
 DECIMAL_BINARY_FUNC(max)
 
@@ -999,6 +1181,7 @@
                 contextobject *ctx)
 {
     /* XXX */
+    Py_RETURN_NONE;
 }
 DECIMAL_BINARY_FUNC(min)
 
@@ -1091,6 +1274,7 @@
 _do_decimal_remainder_near(decimalobject *self, decimalobject *other,
                            contextobject *ctx)
 {
+    Py_RETURN_NONE;
 }
 DECIMAL_BINARY_FUNC(remainder_near)
 
@@ -1143,6 +1327,7 @@
 static decimalobject *
 _do_decimal_sqrt(decimalobject *self, contextobject *ctx)
 {
+    Py_RETURN_NONE;
 }
 DECIMAL_UNARY_FUNC(sqrt)
 
@@ -1170,13 +1355,12 @@
         Py_INCREF(self);
         return self;
     }
-    rnd = ISFLAGSET(ctx->ignored, S_ROUNDED);
-    inex = ISFLAGSET(ctx->ignored, S_INEXACT);
-    SETFLAG(ctx->ignored, S_ROUNDED);
-    SETFLAG(ctx->ignored, S_INEXACT);
+    /* XXX: slow? */
+    rnd = _set_flag(ctx->ignored, S_ROUNDED, 1);
+    inex =_set_flag(ctx->ignored, S_INEXACT, 1);
     ans = _decimal_rescale(self, 0, ctx, rounding, 1);
-    if (!rnd) UNSETFLAG(ctx->ignored, S_ROUNDED);
-    if (!inex) UNSETFLAG(ctx->ignored, S_INEXACT);
+    if (!rnd) _set_flag(ctx->ignored, S_ROUNDED, rnd);
+    if (!inex) _set_flag(ctx->ignored, S_INEXACT, inex);
     return ans;
 }
 
@@ -1500,6 +1684,35 @@
 }
 #undef SANITY_CHECK
 
+/* XXX */
+static PyObject *
+decimal_round(decimalobject *self, PyObject *args)
+{
+    contextobject *ctx = NULL;
+    long prec = -1, rnd = -1;
+    if (!PyArg_ParseTuple(args, "|llO", &prec, &rnd, &ctx))
+        return NULL;
+    ENSURE_CONTEXT("_round", ctx);
+    if (prec == -1) prec = ctx->prec;
+    if (rnd == -1) rnd = ctx->rounding;
+
+    return _decimal_round(self, prec, ctx, rnd);
+}
+
+static PyObject *
+decimal_XXX_abs(decimalobject *self, PyObject *args)
+{
+    int round = -1;
+    contextobject *ctx;
+
+    if (!PyArg_ParseTuple(args, "|iO", &round, &ctx))
+        return NULL;
+    ENSURE_CONTEXT("abs", ctx);
+    if (round == -1)
+        round = ctx->rounding;
+    return _do_decimal_absolute(self, ctx, round);
+}
+
 static PyMethodDef decimal_methods[] = {
     {"adjusted",        (PyCFunction)decimal_adjusted,
      METH_NOARGS,
@@ -1561,6 +1774,10 @@
      METH_NOARGS},
     {"__deepcopy__",    decimal_deepcopy,
      METH_O},
+    /* XXX */
+    {"_round",          (PyCFunction)decimal_round,
+     METH_VARARGS},
+    {"abs__", (PyCFunction)decimal_XXX_abs, METH_VARARGS},
     {NULL, NULL}
 };
 
@@ -1596,10 +1813,79 @@
 _do_decimal_add(decimalobject *self, decimalobject *other,
                 contextobject *ctx)
 {
+    int shouldround, sign, negativezero = 0;
+    long exp, oexp;
+    decimalobject *res, *res2;
+    
+    if (ISSPECIAL(self) || ISSPECIAL(other)) {
+        decimalobject *nan;
+        if (_check_nans(self, other, ctx, &nan) != 0)
+            return nan;
+        if (ISINF(self)) {
+            if (((self->sign&1) != (other->sign&1)) &&
+                ISINF(other))
+                return handle_InvalidOperation(self->ob_type, ctx,
+                                               "-INF + INF", NULL);
+            return _decimal_get_copy(self);
+        } else if (ISINF(other)) {
+            return _decimal_get_copy(other);
+        }
+
+        
+    }
+
+    shouldround = (ctx->rounding_dec == ALWAYS_ROUND);
+    exp = (self->exp < other->exp ? self->exp : other->exp);
+
+    if (ctx->rounding == ROUND_FLOOR &&
+        (self->sign & 1) != (other->sign & 1))
+        negativezero = 1;
+
+    if (!decimal_nonzero(self) && !decimal_nonzero(other)) {
+        if (negativezero)
+            sign = 1;
+        else if (self->sign < other->sign)
+            sign = self->sign;
+        else
+            sign = other->sign;
+        res = _new_decimalobj(self->ob_type, 1, sign, exp);
+        if (!res) return NULL;
+        res->digits[0] = 0;
+        return res;
+    }
+    if (!decimal_nonzero(self)) {
+        oexp = other->exp - ctx->prec - 1;
+        exp = (exp > oexp ? exp : oexp);
+        res = _decimal_rescale(other, exp, ctx, 0);
+        if (!res) return NULL;
+        if (shouldround) {
+            res2 = _decimal_fix(res, ctx);
+            Py_DECREF(res);
+            return res2;
+        } else {
+            return res;
+        }            
+    }
+    if (!decimal_nonzero(other)) {
+        oexp = self->exp - ctx->prec - 1;
+        exp = (exp > oexp ? exp : oexp);
+        res = _decimal_rescale(self, exp, ctx, 0);
+        if (!res) return NULL;
+        if (shouldround) {
+            res2 = _decimal_fix(res, ctx);
+            Py_DECREF(res);
+            return res2;
+        } else {
+            return res;
+        }            
+    }
+
     /* XXX */
+    Py_RETURN_NONE;
 }
 DECIMAL_SPECIAL_2FUNC(decimal_add)
 
+
 static decimalobject *
 _do_decimal_subtract(decimalobject *self, decimalobject *other,
                      contextobject *ctx)
@@ -1627,17 +1913,21 @@
 }
 DECIMAL_SPECIAL_2FUNC(decimal_subtract)
 
+
 static decimalobject *
 _do_decimal_multiply(decimalobject *self, decimalobject *other,
                      contextobject *ctx)
 {
+    Py_RETURN_NONE;
 }
 DECIMAL_SPECIAL_2FUNC(decimal_multiply)
 
+
 static decimalobject *
 _do_decimal_divide(decimalobject *self, decimalobject *other,
                    contextobject *ctx)
 {
+    Py_RETURN_NONE;
 }
 DECIMAL_SPECIAL_2FUNC(decimal_divide)
 
@@ -1646,43 +1936,55 @@
 _do_decimal_floor_div(decimalobject *self, decimalobject *other,
                       contextobject *ctx)
 {
+    Py_RETURN_NONE;
 }
 DECIMAL_SPECIAL_2FUNC(decimal_floor_div)
 
+
 static decimalobject *
 _do_decimal_true_div(decimalobject *self, decimalobject *other,
                      contextobject *ctx)
 {
+    Py_RETURN_NONE;
 }
 DECIMAL_SPECIAL_2FUNC(decimal_true_div)
 
+
 static decimalobject *
 _do_decimal_remainder(decimalobject *self, decimalobject *other,
                       contextobject *ctx)
 {
+    Py_RETURN_NONE;
 }
 DECIMAL_SPECIAL_2FUNC(decimal_remainder)
 
+
 static decimalobject *
 _do_decimal_divmod(decimalobject *self, decimalobject *other,
                    contextobject *ctx)
 {
+    Py_RETURN_NONE;
 }
 DECIMAL_SPECIAL_2FUNC(decimal_divmod)
 
+
 static decimalobject *
 _do_decimal_power(decimalobject *self, decimalobject *other,
-                           decimalobject *modulo, contextobject *ctx)
+                  decimalobject *modulo, contextobject *ctx)
 {
+    Py_RETURN_NONE;
 }
 
+
 static PyObject *                                                       
 decimal_power(PyObject *self, PyObject *other, PyObject *modulo) {                               
     decimalobject *res;                                                
     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;
+    
     if (modulo == Py_None) {
         Py_INCREF(modulo);
     } else {
@@ -1785,16 +2087,18 @@
         ctx2 = context_copy(ctx);
         if (!ctx2) return NULL;
         ctx2->rounding_dec = NEVER_ROUND;
+        ctx = ctx2;
     }
 
     if (self->sign & 1)
-        ans = _do_decimal_negative(self, ctx2);
+        ans = _do_decimal_negative(self, ctx);
     else
-        ans = _do_decimal_positive(self, ctx2);
+        ans = _do_decimal_positive(self, ctx);
     Py_XDECREF(ctx2);
     return ans;
 }
 
+
 static PyObject *
 decimal_absolute(PyObject *self)
 {
@@ -1828,6 +2132,7 @@
     return res;
 }
 
+
 /* Convert to int, truncating. */
 static PyObject *
 decimal_int(decimalobject *self)
@@ -1867,7 +2172,8 @@
     if (self->sign & 1) res = -res;
     return PyInt_FromLong(res);
 }
-            
+
+
 static PyObject *
 decimal_float(decimalobject *self)
 {
@@ -1880,6 +2186,7 @@
     return res;
 }
 
+
 static int
 decimal_nonzero(decimalobject *self)
 {
@@ -1891,6 +2198,7 @@
     return 0;
 }
 
+
 static PyNumberMethods decimal_as_number = {
     decimal_add,         /* nb_add */
     decimal_subtract,    /* nb_subtract */
@@ -1935,13 +2243,6 @@
 };
 
 
-static PyObject *
-decimal_richcompare(decimalobject *a, decimalobject *b, int op)
-{
-    /* XXX */
-    return NULL;
-}
-
 int
 _decimal_isint(decimalobject *d)
 {
@@ -1960,6 +2261,7 @@
     return 1;
 }
 
+
 static void
 decimal_dealloc(decimalobject *d)
 {
@@ -1967,6 +2269,7 @@
     d->ob_type->tp_free(d);
 }
 
+
 static decimalobject *
 _decimal_fromliteralnan(PyTypeObject *type, char *str, long len, contextobject *ctx)
 {
@@ -2023,11 +2326,13 @@
     return new;
 }
 
+
 static char *infinities[] = {
     "inf", "infinity", "+inf", "+infinity",
     "-inf", "-infinity", 0
 };
 
+
 static decimalobject *
 _decimal_fromliteralinfinity(PyTypeObject *type, char *str)
 {
@@ -2053,6 +2358,7 @@
     return NULL;
 }
 
+
 static decimalobject *
 _decimal_fromliteral(PyTypeObject *type, char *str, long len, contextobject *ctx)
 {
@@ -2197,12 +2503,14 @@
     return (PyObject *)new;
 }
 
+
 PyObject *
 PyDecimal_FromLong(long value)
 {
     return decimal_from_long(&PyDecimal_DecimalType, value);
 }
 
+
 /* convert from a 3-tuple of (sign, digits, exp) */
 static PyObject *
 decimal_from_sequence(PyTypeObject *type, PyObject *seq)
@@ -2273,12 +2581,14 @@
     return NULL;
 }
 
+
 PyObject *
 PyDecimal_FromSequence(PyObject *seq)
 {
     return decimal_from_sequence(&PyDecimal_DecimalType, seq);
 }
 
+
 static decimalobject *
 _decimal_from_pylong(PyTypeObject *type, PyObject *val, contextobject *ctx)
 {
@@ -2303,7 +2613,6 @@
     return res;
 }
 
-static PyObject *decimal_new(PyTypeObject *, PyObject *, PyObject *);
 
 static PyObject *
 decimal_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
@@ -2379,6 +2688,7 @@
     return NULL;
 }
 
+
 static PyObject *
 decimal_repr(decimalobject *d)
 {
@@ -2396,6 +2706,7 @@
     return res;
 }
 
+
 static long
 decimal_hash(decimalobject *d)
 {
@@ -2440,6 +2751,7 @@
     return hash;
 }
 
+
 /* XXX: just for debugging? */
 static PyMemberDef _decimal_members[] = {
     {"_sign", T_INT, offsetof(decimalobject, sign), 0},
@@ -2447,6 +2759,7 @@
     {NULL}
 };
 
+
 static PyObject *
 _decimal_get_int(decimalobject *self)
 {
@@ -2459,6 +2772,7 @@
     return tup;
 }
 
+
 static int
 _decimal_set_int(decimalobject *self, PyObject *value)
 {
@@ -2497,6 +2811,7 @@
     return 0;
 }
 
+
 static PyObject *
 _decimal_is_special(decimalobject *self)
 {
@@ -2506,6 +2821,7 @@
         Py_RETURN_FALSE;
 }
 
+
 static PyGetSetDef _decimal_getset[] = {
     {"_int", (getter)_decimal_get_int, (setter)_decimal_set_int},
     {"_is_special", (getter)_decimal_is_special, 0},
@@ -2539,7 +2855,7 @@
     decimal_doc,                 /* tp_doc */
     0,                           /* tp_traverse */
     0,                           /* tp_clear */
-    0, /* XXX: activate when it's implemented (richcmpfunc)decimal_richcompare,*/ /* tp_richcompare */
+    (richcmpfunc)decimal_richcompare, /* tp_richcompare */
     0,                           /* tp_weaklistoffset */
     0,                           /* tp_iter */
     0,                           /* tp_iternext */
@@ -2651,14 +2967,50 @@
 /* Context object ************************************************************/
 
 static contextobject *
-_new_contextobj(long prec, int rounding, int rounding_dec, int traps,
-                int flags, long Emin, long Emax, int capitals,
-                int clamp, int ignored)
+_new_contextobj(long prec, int rounding, int rounding_dec, PyObject *traps,
+                PyObject *flags, long Emin, long Emax, int capitals,
+                int clamp, PyObject *ignored, int copy_dicts)
 {
     contextobject *new;
+    PyObject *f = NULL, *t = NULL, *i = NULL;
+
     new = (contextobject *)PyObject_NEW(contextobject, &PyDecimal_DecimalContextType);
     if (new == NULL)
         return NULL;
+
+    if (!flags) {
+        f = PyDict_New();
+    } else if (copy_dicts) {
+        f = PyDict_Copy(flags);
+    } else {
+        f = flags;
+        Py_INCREF(f);
+    }
+    if (!f) goto err;
+    
+    if (!traps) {
+        t = PyDict_New();
+    } else if (copy_dicts) {
+        t = PyDict_Copy(traps);
+    } else {
+        t = traps;
+        Py_INCREF(t);
+    }
+    if (!t) goto err;    
+    
+    if (!ignored) {
+        i = PyDict_New();
+    } else if (copy_dicts) {
+        i = PyDict_Copy(ignored);
+    } else {
+        i = ignored;
+        Py_INCREF(i);
+    }
+    if (!i) goto err;
+
+    new->flags = f;
+    new->traps = t;
+    new->ignored = i;
     new->prec = prec;
     new->rounding = rounding;
     new->rounding_dec = rounding_dec;
@@ -2666,64 +3018,15 @@
     new->Emax = Emax;
     new->capitals = capitals;
     new->clamp = clamp;
-    new->flags = flags;
-    new->traps = traps;
-    new->ignored = ignored;
     return new;
-}
-
-/* Context properties *********************************************************/
-
-
-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);
+    Py_XDECREF(f);
+    Py_XDECREF(t);
+    Py_XDECREF(i);
     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 *
@@ -2733,14 +3036,21 @@
     Py_RETURN_NONE;
 }
 
-/* As a C Context doesn't have mutable attributes, this is the
-   same as Context._shallow_copy. */
+
+static contextobject *
+context_shallow_copy(contextobject *ctx)
+{
+    return _new_contextobj(ctx->prec, ctx->rounding, ctx->rounding_dec, ctx->traps,
+                           ctx->flags, ctx->Emin, ctx->Emax, ctx->capitals, ctx->clamp,
+                           ctx->ignored, 0);
+}
+
 static contextobject *
 context_copy(contextobject *ctx)
 {
     return _new_contextobj(ctx->prec, ctx->rounding, ctx->rounding_dec, ctx->traps,
                            ctx->flags, ctx->Emin, ctx->Emax, ctx->capitals, ctx->clamp,
-                           ctx->ignored);
+                           ctx->ignored, 1);
 }
 
 static decimalobject *
@@ -2986,52 +3296,41 @@
 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("(O(liiOOlliiO))", self->ob_type,
-                        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;
+    return Py_BuildValue("(O(liiOOlliiO))", self->ob_type,
+                         self->prec, self->rounding,
+                         self->rounding_dec, self->traps, self->flags,
+                         self->Emin, self->Emax, self->capitals,
+                         self->clamp, self->ignored);
 }
 
 static PyObject *
 context_ignore_flags(contextobject *self, PyObject *args)
 {
     PyObject *flag, *ret_flags;
-    Py_ssize_t i, j;
+    long i, j;
 
     /* NB, unlike regard_flags this doesn't accept a sequence as the
        first element and regard_flags returns a list-ized version of
        its arguments instead of None
     */
+    ret_flags = PyList_New(0);
 
     if (ret_flags == NULL)
         return NULL;
+    
     for (i = 0; i < PyTuple_GET_SIZE(args); i++) {
         flag = PyTuple_GET_ITEM(args, i);
         for (j = 0; j < NUMSIGNALS; j++) {
             if (errors[j] == flag) {
-                SETFLAG(self->ignored, j);
-                Py_INCREF(flag);
-                PyList_SET_ITEM(ret_flags, i, flag);
+                _set_flag(self->ignored, j, 1);
+                if (PyList_Append(ret_flags, flag) < 0) {
+                    Py_DECREF(ret_flags);
+                    return NULL;
+                }
                 break;
             }
         }
+        /* No DECREF of flag here. */
         if (j == NUMSIGNALS) {
             Py_DECREF(ret_flags);
             PyErr_SetString(PyExc_ValueError, "arguments must be valid flags");
@@ -3044,27 +3343,33 @@
 static PyObject *
 context_ignore_all_flags(contextobject *self)
 {
-    PyObject *allflags, *flag;
+    PyObject *allflags, *flag, *res;
     int i = 0;
 
     allflags = PyTuple_New(NUMSIGNALS);
     if (allflags == NULL)
         return NULL;
-        
+
     for (i = 0; i < NUMSIGNALS; i++) {
         flag = errors[i];
         Py_INCREF(flag);
         PyTuple_SET_ITEM(allflags, i, flag);
     }
-    return context_ignore_flags(self, allflags);
+    res = context_ignore_flags(self, allflags);
+    Py_DECREF(allflags);
+    return res;
 }
 
 static PyObject *
 context_regard_flags(contextobject *self, PyObject *args)
 {
     PyObject *flag, *flags;
-    Py_ssize_t i, j;
+    long i, j;
 
+    if (PyTuple_GET_SIZE(args) <= 0) {
+        PyErr_BadInternalCall();
+        return NULL;
+    }
     /* regard_flags allows a list of flags as the first arg */
     flags = PyTuple_GET_ITEM(args, 0);
     if (PyTuple_GET_SIZE(args) != 1 && !PySequence_Check(flags))
@@ -3074,10 +3379,11 @@
         flag = PySequence_GetItem(flags, i);
         for (j = 0; j < NUMSIGNALS; j++) {
             if (flag == errors[j]) {
-                UNSETFLAG(self->ignored, j);
+                _set_flag(self->ignored, j, 0);
                 break;
             }
         }
+        Py_DECREF(flag);
         if (j == NUMSIGNALS) {
             PyErr_SetString(PyExc_ValueError, "arguments must be valid flags");
             return NULL;
@@ -3090,7 +3396,6 @@
 context_set_rounding_decision(contextobject *self, PyObject *args)
 {
     int old_dec, new_dec;
-    PyObject *ret;
 
     if (!PyArg_ParseTuple(args, "i:_set_rounding_decision", &new_dec))
         return NULL;
@@ -3101,16 +3406,13 @@
         
     old_dec = self->rounding_dec;
     self->rounding_dec = new_dec;
-    ret = PyInt_FromLong((long)old_dec);
-    if (ret == NULL)
-        return NULL;
-    return ret;
+    return PyInt_FromLong((long)old_dec);
 }
+
 static PyObject *
 context_set_rounding(contextobject *self, PyObject *args)
 {
     int old_round, new_round;
-    PyObject *ret;
 
     if (!PyArg_ParseTuple(args, "i:_set_rounding", &new_round))
         return NULL;
@@ -3120,10 +3422,7 @@
     }
     old_round = self->rounding;
     self->rounding = new_round;
-    ret = PyInt_FromLong((long)old_round);
-    if (ret == NULL)
-        return NULL;
-    return ret;
+    return PyInt_FromLong((long)old_round);
 }
 
 static PyObject *
@@ -3217,7 +3516,7 @@
     PyObject *rest = NULL;
     PyObject *handler;
     PyObject *dummy;
-    int flag = -1;
+    int errindex = -1, condindex = -1;
     int i;
     
     if (!PyArg_ParseTuple(args, "O|OO:_raise_error", &condition, &explanation, &rest))
@@ -3228,10 +3527,11 @@
         return NULL;
 
     
-    if (explanation == NULL && !PyArg_ParseTupleAndKeywords(dummy, kwds,
+/*    if (explanation == NULL && !PyArg_ParseTupleAndKeywords(dummy, kwds,
                                                            "O:_raise_error", kwlist,
                                                             &explanation))
         return NULL;
+*/
 
     if ((condition == ConversionSyntax) ||
         (condition == DivisionImpossible) ||
@@ -3242,27 +3542,21 @@
         /* reuse the condition */
         handler = condition;
     }
-    for (i = 0; i < NUMSIGNALS; i++) {
-        if (errors[i] == handler) {
-            flag = i;
-            break;
-        }
+    /* The condition handle is called based on condition,
+       the exception on handler. */
+    for (i = 0; i < NUMSIGNALS+NUMCONDITIONS; i++) {
+        if (errors[i] == condition)
+            condindex = i;
+        if (errors[i] == handler)
+            errindex = i;
     }
 
-    if (ISFLAGSET(self->ignored, flag)) {
-        return _do_context_error_dispatch(flag, args);
+    if (_is_flag_set(self->ignored, errindex)) {
+        return _do_context_error_dispatch(condindex, args);
     } else {
-        SETFLAG(self->ignored, flag);
-        if (!ISFLAGSET(self->traps, flag)) {
-            for (i = 0; i < NUMSIGNALS; i++) {
-                if (errors[i] == condition) {
-                    flag = i;
-                    break;
-                }
-            }
-            return _do_context_error_dispatch(flag, args);
-        
-        }
+        _set_flag(self->flags, errindex, 1);
+        if (!_is_flag_set(self->traps, errindex))
+            return _do_context_error_dispatch(condindex, args);
     }
     PyErr_SetString(handler, PyString_AsString(explanation));
     return NULL;
@@ -3335,7 +3629,7 @@
      METH_VARARGS | METH_KEYWORDS},
     {"__copy__",        (PyCFunction)context_copy,
      METH_NOARGS},
-    {"_shallow_copy",   (PyCFunction)context_copy,
+    {"_shallow_copy",   (PyCFunction)context_shallow_copy,
      METH_NOARGS},
     {"__reduce__",      (PyCFunction)context_reduce,
      METH_NOARGS},
@@ -3347,18 +3641,21 @@
 
 
 static void
-context_dealloc(PyObject *c)
+context_dealloc(contextobject *c)
 {
+    Py_DECREF(c->flags);
+    Py_DECREF(c->traps);
+    Py_DECREF(c->ignored);
     c->ob_type->tp_free(c);
 }
 
 #define TEST_AND_CAT(num, name)                 \
-    if (ISFLAGSET(self->flags, num)) {          \
+    if (_is_flag_set(self->flags, num)) {          \
         strcat(flags, name);                    \
         strcat(flags, ", ");                    \
         flaglen += strlen(name) + 2;            \
     }                                           \
-    if (ISFLAGSET(self->traps, num)) {          \
+    if (_is_flag_set(self->traps, num)) {          \
         strcat(traps, name);                    \
         strcat(traps, ", ");                    \
         traplen += strlen(name) + 2;            \
@@ -3442,8 +3739,10 @@
     long Emin = LONG_MAX, Emax = LONG_MIN;
     int rounding = -1, rounding_dec = -1, capitals = -1, clamp = 0;
     PyObject *pytraps = NULL, *pyflags = NULL, *pyignored = NULL;
-    PyObject *tmp;
-    int traps = 0, flags = 0, ignored = 0;
+    PyObject *tmp, *res = NULL;
+    PyObject *_traps = NULL;
+    PyObject *_flags = NULL;
+    PyObject *_ignored = NULL;
     int i, j;
 
     if (!PyArg_ParseTupleAndKeywords(args, kwds, "|nbbOOnnbbO:Context", kwlist,
@@ -3451,83 +3750,96 @@
                                      &pyflags, &Emin, &Emax, &capitals, &clamp,
                                      &pyignored))
         return NULL;
-    
+
     if (pytraps == NULL) {
-        traps = PyDecimal_DefaultContext->traps;
-    } else if (!PyDict_Check(pytraps)) {
-        for (i = 0; i < NUMSIGNALS; i++) {
-            j = PySequence_Contains(pytraps, errors[i]);
-            if (j == -1)
-                return NULL;
-            else if (j == 1)
-                SETFLAG(traps, i);
-        }
+        _traps = PyDict_Copy(PyDecimal_DefaultContext->traps);
+        if (!_traps) goto err;
     } else {
-        for (i = 0; i < NUMSIGNALS; i++) {
-            j = PyDict_Contains(pytraps, errors[i]);
-            if (j == -1)
-                return NULL;
-            else if (j == 0)
-                continue;
-            tmp = PyDict_GetItem(pytraps, errors[i]);
-            if (!tmp)
-                return NULL;
-            j = PyObject_IsTrue(tmp);
-            if (j == -1)
-                return NULL;
-            else if (j == 1)
-                SETFLAG(traps, i);
+        _traps = PyDict_New();
+        if (!_traps) goto err;
+        if (!PyDict_Check(pytraps)) {
+            
+            for (i = 0; i < NUMSIGNALS; i++) {
+                j = PySequence_Contains(pytraps, errors[i]);
+                if (j == -1)
+                    goto err;
+                else if (j == 1)
+                    _set_flag(_traps, i, 1);
+            }
+        } else {
+            for (i = 0; i < NUMSIGNALS; i++) {
+                j = PyDict_Contains(pytraps, errors[i]);
+                if (j == -1)
+                    goto err;
+                else if (j == 0)
+                    continue;
+                tmp = PyDict_GetItem(pytraps, errors[i]);
+                if (!tmp)
+                    goto err;
+                j = PyObject_IsTrue(tmp);
+                if (j == -1)
+                    goto err;
+                else if (j == 1)
+                    _set_flag(_traps, i, 1);
+            }
         }
     }
 
+    _flags = PyDict_New();
+    if (!_flags) goto err;
+
     if (pyflags == NULL) {
         /* don't copy flags from default context */
     } else if (PyDict_Check(pyflags)) {
         for (i = 0; i < NUMSIGNALS; i++) {
             j = PyDict_Contains(pyflags, errors[i]);
             if (j == -1)
-                return NULL;
+                goto err;
             else if (j == 0)
                 continue;
             tmp = PyDict_GetItem(pyflags, errors[i]);
             if (!tmp)
-                return NULL;
+                goto err;
             j = PyObject_IsTrue(tmp);
             if (j == -1)
-                return NULL;
+                goto err;
             else if (j == 1)
-                SETFLAG(flags, i);
+                _set_flag(_flags, i, 1);
         }
     } else {
         PyErr_SetString(PyExc_TypeError, "initial flags must be a dict");
-        return NULL;
+        goto err;
     }
 
+
+    _ignored = PyDict_New();
+    if (!_ignored) goto err;
+    
     if (pyignored == NULL) {
         /* don't copy ignored flags from default context */
     } else if (!PyDict_Check(pyignored)) {
         for (i = 0; i < NUMSIGNALS; i++) {
             j = PySequence_Contains(pyignored, errors[i]);
             if (j == -1)
-                return NULL;
+                goto err;
             else if (j == 1)
-                SETFLAG(ignored, i);
+                _set_flag(_ignored, i, 1);
         }
     } else {
         for (i = 0; i < NUMSIGNALS; i++) {
             j = PyDict_Contains(pyignored, errors[i]);
             if (j == -1)
-                return NULL;
+                goto err;
             else if (j == 0)
                 continue;
             tmp = PyDict_GetItem(pyignored, errors[i]);
             if (!tmp)
-                return NULL;
+                goto err;
             j = PyObject_IsTrue(tmp);
             if (j == -1)
-                return NULL;
+                goto err;
             else if (j == 1)
-                SETFLAG(ignored, i);
+                _set_flag(_ignored, i, 1);
         }
     }
 
@@ -3559,9 +3871,14 @@
     
     clamp = clamp & 1;
 
-    return (PyObject *)_new_contextobj(prec, rounding, rounding_dec, traps,
-                                       flags, Emin, Emax, capitals, clamp,
-                                       ignored);
+    res = (PyObject *)_new_contextobj(prec, rounding, rounding_dec, _traps,
+                                      _flags, Emin, Emax, capitals, clamp,
+                                      _ignored, 0);
+  err:
+    Py_XDECREF(_flags);
+    Py_XDECREF(_traps);
+    Py_XDECREF(_ignored);
+    return res;
 }
 
 
@@ -3575,6 +3892,9 @@
     {"rounding", T_INT, OFF(rounding), 0},
     {"_rounding_decision", T_INT, OFF(rounding_dec), 0},
     {"_clamp", T_INT, OFF(clamp), 0},
+    {"flags", T_OBJECT_EX, OFF(flags), 0},
+    {"traps", T_OBJECT_EX, OFF(traps), 0},
+    {"_ignored", T_OBJECT_EX, OFF(ignored), 0},
     {NULL}
 };
 
@@ -3610,7 +3930,7 @@
     0,                          /* tp_iternext */
     context_methods,            /* tp_methods */
     context_members,            /* tp_members */
-    context_getset,             /* tp_getset */
+    0,                          /* tp_getset */
     0,                          /* tp_base */
     0,                          /* tp_dict */
     0,                          /* tp_descr_get */
@@ -3700,8 +4020,11 @@
     PyObject *m;	/* a module object */
     PyObject *tup;
     contextobject *ctx;
-    int traps = 0;
+    PyObject *traps;
 
+    traps = PyDict_New();
+    if (!traps) return;
+    
     m = Py_InitModule3(MODULE_NAME, module_methods,
                        "Fast implementation of decimal arithmetic.");
     if (m == NULL)
@@ -3718,12 +4041,53 @@
     Py_INCREF(&PyDecimal_DecimalContextType);
     PyModule_AddObject(m, "Context", (PyObject *) &PyDecimal_DecimalContextType);
 
+    ADD_CONST(m, ROUND_DOWN);
+    ADD_CONST(m, ROUND_UP);
+    ADD_CONST(m, ROUND_HALF_DOWN);
+    ADD_CONST(m, ROUND_HALF_EVEN);
+    ADD_CONST(m, ROUND_HALF_UP);
+    ADD_CONST(m, ROUND_FLOOR);
+    ADD_CONST(m, ROUND_CEILING);
+    ADD_CONST(m, ALWAYS_ROUND);
+    ADD_CONST(m, NEVER_ROUND);
+    
+    INIT_EXC(m, DecimalException, PyExc_ArithmeticError);
+    INIT_EXC(m, Clamped, DecimalException);
+    INIT_EXC(m, InvalidOperation, DecimalException);
+    INIT_EXC(m, ConversionSyntax, InvalidOperation);
+    INIT_EXC(m, DivisionImpossible, InvalidOperation);
+    INIT_EXC_WITH_2TUPLE(m, DivisionUndefined,
+                         InvalidOperation, PyExc_ZeroDivisionError);
+    INIT_EXC(m, InvalidContext, InvalidOperation);
+    INIT_EXC_WITH_2TUPLE(m, DivisionByZero,
+                         DecimalException, PyExc_ZeroDivisionError);
+    INIT_EXC(m, Inexact, DecimalException);
+    INIT_EXC(m, Rounded, DecimalException);
+    INIT_EXC(m, Subnormal, DecimalException);
+    INIT_EXC_WITH_2TUPLE(m, Overflow, Rounded, Inexact);
+    INIT_EXC_WITH_3TUPLE(m, Underflow,
+                         Rounded, Inexact, Subnormal);
+    
+    errors[S_INV_OPERATION] = InvalidOperation;
+    errors[S_DIV_BY_ZERO]   = DivisionByZero;
+    errors[S_CLAMPED]       = Clamped;
+    errors[S_INEXACT]       = Inexact;
+    errors[S_ROUNDED]       = Rounded;
+    errors[S_SUBNORMAL]     = Subnormal;
+    errors[S_OVERFLOW]      = Overflow;
+    errors[S_UNDERFLOW]     = Underflow;
+    errors[C_INV_CONTEXT]   = InvalidContext;
+    errors[C_CONV_SYNTAX]   = ConversionSyntax;
+    errors[C_DIV_IMPOSSIBLE]= DivisionImpossible;
+    errors[C_DIV_UNDEFINED] = DivisionUndefined;
+
     /* initialize default Context objects */
-    SETFLAG(traps, S_DIV_BY_ZERO);
-    SETFLAG(traps, S_OVERFLOW);
-    SETFLAG(traps, S_INV_OPERATION);
+    _set_flag(traps, S_DIV_BY_ZERO, 1);
+    _set_flag(traps, S_OVERFLOW, 1);
+    _set_flag(traps, S_INV_OPERATION, 1);
     PyDecimal_DefaultContext = _new_contextobj(28, ROUND_HALF_EVEN, ALWAYS_ROUND,
-                                    traps, 0, -999999999L, 999999999L, 1, 0, 0);
+                                               traps, NULL, -999999999L, 999999999L,
+                                               1, 0, NULL, 1);
     if (!PyDecimal_DefaultContext)
         return;
     if (PyModule_AddObject(m, "DefaultContext",
@@ -3731,11 +4095,12 @@
         return;
 
     /* add flags for BasicContext */
-    SETFLAG(traps, S_CLAMPED);
-    SETFLAG(traps, S_UNDERFLOW);
+    _set_flag(traps, S_CLAMPED, 1);
+    _set_flag(traps, S_UNDERFLOW, 1);
 
     PyDecimal_BasicContext = _new_contextobj(9, ROUND_HALF_UP, ALWAYS_ROUND,
-                                 traps, 0, -999999999L, 999999999L, 1, 0, 0);
+                                             traps, NULL, -999999999L, 999999999L,
+                                             1, 0, NULL, 1);
     if (!PyDecimal_BasicContext)
         return;
     if (PyModule_AddObject(m, "BasicContext",
@@ -3743,7 +4108,8 @@
         return;
 
     PyDecimal_ExtendedContext = _new_contextobj(9, ROUND_HALF_EVEN, ALWAYS_ROUND,
-                                     0, 0, -999999999L, 999999999L, 1, 0, 0);
+                                                NULL, NULL, -999999999L, 999999999L,
+                                                1, 0, NULL, 1);
     if (!PyDecimal_ExtendedContext)
         return;
     if (PyModule_AddObject(m, "ExtendedContext",
@@ -3769,43 +4135,4 @@
     if (PyModule_AddObject(m, "negInf", (PyObject *)PyDecimal_NegInf) < 0)
         return;
 
-    ADD_CONST(m, ROUND_DOWN);
-    ADD_CONST(m, ROUND_UP);
-    ADD_CONST(m, ROUND_HALF_DOWN);
-    ADD_CONST(m, ROUND_HALF_EVEN);
-    ADD_CONST(m, ROUND_HALF_UP);
-    ADD_CONST(m, ROUND_FLOOR);
-    ADD_CONST(m, ROUND_CEILING);
-    ADD_CONST(m, ALWAYS_ROUND);
-    ADD_CONST(m, NEVER_ROUND);
-    
-    INIT_EXC(m, DecimalException, PyExc_ArithmeticError);
-    INIT_EXC(m, Clamped, DecimalException);
-    INIT_EXC(m, InvalidOperation, DecimalException);
-    INIT_EXC(m, ConversionSyntax, InvalidOperation);
-    INIT_EXC(m, DivisionImpossible, InvalidOperation);
-    INIT_EXC_WITH_2TUPLE(m, DivisionUndefined,
-                         InvalidOperation, PyExc_ZeroDivisionError);
-    INIT_EXC(m, InvalidContext, InvalidOperation);
-    INIT_EXC_WITH_2TUPLE(m, DivisionByZero,
-                         DecimalException, PyExc_ZeroDivisionError);
-    INIT_EXC(m, Inexact, DecimalException);
-    INIT_EXC(m, Rounded, DecimalException);
-    INIT_EXC(m, Subnormal, DecimalException);
-    INIT_EXC_WITH_2TUPLE(m, Overflow, Rounded, Inexact);
-    INIT_EXC_WITH_3TUPLE(m, Underflow,
-                         Rounded, Inexact, Subnormal);
-    
-    errors[S_INV_OPERATION] = InvalidOperation;
-    errors[S_DIV_BY_ZERO]   = DivisionByZero;
-    errors[S_CLAMPED]       = Clamped;
-    errors[S_INEXACT]       = Inexact;
-    errors[S_ROUNDED]       = Rounded;
-    errors[S_SUBNORMAL]     = Subnormal;
-    errors[S_OVERFLOW]      = Overflow;
-    errors[S_UNDERFLOW]     = Underflow;
-    errors[C_INV_CONTEXT]   = InvalidContext;
-    errors[C_CONV_SYNTAX]   = ConversionSyntax;
-    errors[C_DIV_IMPOSSIBLE]= DivisionImpossible;
-    errors[C_DIV_UNDEFINED] = DivisionUndefined;
 }

Modified: sandbox/trunk/decimal-c/decimal.h
==============================================================================
--- sandbox/trunk/decimal-c/decimal.h	(original)
+++ sandbox/trunk/decimal-c/decimal.h	Fri May 26 11:35:31 2006
@@ -35,10 +35,10 @@
     long Emin;
     long Emax;
 
-    /* signal handling -- these are bit fields */
-    int traps;        /* if a signal is trapped */
-    int ignored;      /* if a signal is ignored completely */
-    int flags;        /* if a signal has occurred, but not been trapped */
+    /* signal handling -- these are dicts */
+    PyObject *traps;   /* if a signal is trapped */
+    PyObject *flags;   /* if a signal has occurred, but not been trapped */
+    PyObject *ignored; /* if a signal is ignored completely */
 } PyDecimalContextObject;
 
 static PyTypeObject PyDecimal_DecimalContextType;
@@ -57,9 +57,9 @@
 
 /* static constants **********************************************************/
 
-static PyObject *PyDecimal_NaN;
-static PyObject *PyDecimal_Inf;
-static PyObject *PyDecimal_NegInf;
+static PyDecimalObject *PyDecimal_NaN;
+static PyDecimalObject *PyDecimal_Inf;
+static PyDecimalObject *PyDecimal_NegInf;
 
 static PyDecimalContextObject *PyDecimal_DefaultContext;
 static PyDecimalContextObject *PyDecimal_BasicContext;


More information about the Python-checkins mailing list