[Python-checkins] r46471 - sandbox/trunk/decimal-c/Makefile sandbox/trunk/decimal-c/_decimal.c sandbox/trunk/decimal-c/decimal.py

georg.brandl python-checkins at python.org
Sat May 27 17:38:58 CEST 2006


Author: georg.brandl
Date: Sat May 27 17:38:57 2006
New Revision: 46471

Modified:
   sandbox/trunk/decimal-c/Makefile
   sandbox/trunk/decimal-c/_decimal.c
   sandbox/trunk/decimal-c/decimal.py
Log:
Add (hopefully) helpful comments for Mateusz.



Modified: sandbox/trunk/decimal-c/Makefile
==============================================================================
--- sandbox/trunk/decimal-c/Makefile	(original)
+++ sandbox/trunk/decimal-c/Makefile	Sat May 27 17:38:57 2006
@@ -1,11 +1,16 @@
 # change PYTHON_25 to point to a 2.5 HEAD build
-PYTHON_25=../python-rw/python
+# (a fairly recent HEAD is necessary)
+PYTHON_25=../../../python/python
 
-all: module test
+all: module run
 module:
 	$(PYTHON_25) setup.py build
 	cp build/lib*/_decimal.so .
 clean:
 	rm -rf build/
-test:
+test: module
 	$(PYTHON_25) test_decimal.py
+run: module
+	$(PYTHON_25) -i -c "import _decimal; CD = _decimal.Decimal; import decimal; D = decimal.Decimal"
+debug: module
+	ddd $(PYTHON_25) 

Modified: sandbox/trunk/decimal-c/_decimal.c
==============================================================================
--- sandbox/trunk/decimal-c/_decimal.c	(original)
+++ sandbox/trunk/decimal-c/_decimal.c	Sat May 27 17:38:57 2006
@@ -2,20 +2,65 @@
  *
  *  Partly written for the Need for Speed sprint in
  *  Iceland by Georg Brandl and Jack Diederich.
+ *
+ *  Copyrighted to the Python Software Foundation.
  */
 
 /* Notable incompatibilities between this and the original decimal.py:
 
    - Rounding constants are integers.
    - There's no handle method on the exceptions.
+   - Context methods don't accept keyword arguments (they're all
+     called a and b anyways).
    - 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.
-*/
+   - In principle, exponents and the number of digits are unbounded in
+     Python decimals, since they could use long integers. While that's
+     praiseworthy, it's also not very speedy ;)
+   - The Python version sometimes gets the context in the middle of
+     a method which leads to some calls succeeding even if there is
+     no valid context.
+
+   Notable kludges necessary retain some compatibility:
+
+   - decimal.py Contexts used to have three dicts, traps, flags and
+     _ignored, to store whether an error occurred or whether to
+     raise an exception in this case. I started with them being bitmasks
+     until we realized that Python code expects them to be dicts and
+     wants to modify those, so we added back dictobjects to decimalobject.
+     I guess that this causes slowdown here and there, and the proper way
+     to do this is to subclass dict to call back some method on assignment.
+     (This is better done in Python code, I guess.)
+   - Some internal methods (names starting with underscores) have been
+     added as a method to the C objects to allow the overlay Python
+     module to use them. They should be removed from that list, along
+     with the wrapper functions parsing the Python arguments, once every-
+     thing is coded in C.
+   - Some special (__xxx__) methods in the Python code took additional
+     arguments used internally. Since that's not possible, there's a
+     _do_decimal_xxx along with a decimal_xxx, see below.
+
+   
+   This is not yet optimized C code, but mostly translated Python that
+   was not really made for translating, though it originally should have been.
+
+   Areas which need improvement are marked with XXX throughout the code.
+
+   The functions could use some more comments, I sometimes didn't even transfer
+   every comment in the Python version. Refcounting and more complicated
+   structure make even more comments necessary.
+
+   Each function whose name doesn't start with an underscore is supposed to be
+   stowed in some TypeObject struct.
+
+   Note that the argument and return types of functions are also not very
+   consistent. Casting things around is necessary, but I'm not always sure
+   where the right place for that to happen is. (If anyone calls C a strongly
+   typed language again, hit him on the head.)
 
-/* This is not yet optimized C code, but mostly translated
-   Python that was not really made for translating, though
-   it originally should have been.
+   We were undecided whether to offer a public C API (PyDecimal_FromString etc.)
+   If you want to do this, look at the datetime module.
 */
 
 #include "Python.h"
@@ -25,6 +70,7 @@
 
 /* helpful macros ************************************************************/
 
+/* if we later decide to call this module "squeaky" */
 #define MODULE_NAME   "_decimal"
 #define INITFUNC_NAME init_decimal
 
@@ -44,7 +90,7 @@
 
 /* Exponent calculations */
 
-/* XXX: overflow? */
+/* XXX: overflow checking? */
 #define ETINY(ctx) ((ctx)->Emin - (ctx)->prec + 1)
 #define ETOP(ctx)  ((ctx)->Emax - (ctx)->prec + 1)
 #define ADJUSTED(dec) ((dec)->exp + (dec)->ob_size - 1)
@@ -53,6 +99,9 @@
 
 /* sign values */
 
+/* Since we do (decimal->sign & 1) all over the place, it is important
+   that negative signs have the first bit set. */
+
 #define SIGN_POS     0
 #define SIGN_NEG     1
 
@@ -82,6 +131,9 @@
 
 /* Context signals */
 
+/* The naming (conditions vs. signals vs. errors vs. exceptions)
+   is not very consistent. */
+
 #define NUMSIGNALS      8
 
 #define S_CLAMPED       0
@@ -95,7 +147,7 @@
 
 /* Other conditions. If they occur and raise an exception,
    it will be InvalidOperation. Also, context->flags, ->traps and
-   ->ignored will only contain bits for the signals defined above.
+   ->ignored will only contain entries for the signals defined above.
 */
 
 #define NUMCONDITIONS    4
@@ -163,6 +215,8 @@
 
 /* Forwarding ****************************************************************/
 
+/* some of them could be removed if the functions were declared
+   in the right order */
 static contextobject *getcontext(void);
 static int setcontext(contextobject *);
 static PyObject *context_new(PyTypeObject *, PyObject *, PyObject *);
@@ -181,7 +235,9 @@
 
 /* Exception handlers *********************************************************/
 
-/* Raise the exception if signal is trapped and not ignored. */
+/* Raise the exception with expl if cond is trapped and not ignored.
+   When raising, return onerror.
+*/
 #define HANDLE_ERROR(ctx, cond, expl, onerror)                         \
     int err = (cond >= NUMSIGNALS ? S_INV_OPERATION : cond);           \
     if (! _is_flag_set(ctx->ignored, err)) {                           \
@@ -352,6 +408,13 @@
 
 /* Decimal object methods *****************************************************/
 
+/* NB: "type" is the real type of the object we're creating here.
+
+   The first version didn't take a "type" arg and just used
+   &PyDecimal_DecimalType instead. That's a bad idea since it doesn't allow
+   for subclassing, so we're forced to carry around a typeobject everywhere
+   where we might create new decimalobjects.
+*/
 
 static decimalobject *
 _new_decimalobj(PyTypeObject *type, long ndigits, char sign, long exp)
@@ -520,7 +583,7 @@
 }
 
 /* Actually round half up. Returns a new reference, either on tmp
- * or a new decimalobject, and steals one reference on tmp in turn
+ * or a new decimalobject, but steals one reference on tmp in turn
  * if it was passed in so that you can just return _do_round_half_up(...)
  * without DECREFing tmp afterwards.
  */
@@ -623,13 +686,15 @@
         return _round_down(self, prec, expdiff, ctx);
 }
 
+/* Mapping rounding constants to functions. Since in C this can be indexed with
+   any value, it's important to check the rounding constants before! */
 typedef decimalobject*(*round_func)(decimalobject *, long, long, contextobject *);
 static round_func round_funcs[] = {
     _round_down, _round_up, _round_half_down, _round_half_even,
     _round_half_up, _round_floor, _round_ceiling
 };
 
-/* default: prec=-1, rounding=-1 (use context), see the ROUND_* constants */
+/* default: prec=-1, rounding=-1 (use context values), see the ROUND_* constants */
 static decimalobject *
 _decimal_round(decimalobject *self, long prec, contextobject *ctx, int rounding)
 {
@@ -973,9 +1038,13 @@
     return Py_NotImplemented;
 }
 
+/* Often-used context lists. */
 static char *ctxkwlist[] = {"context", 0};
 static char *decctxkwlist[] = {"other", "context", 0};
 
+
+/* Make sure that dec is a decimal. Needs to have a contextobject named
+   "ctx" around. */
 #define ENSURE_DECIMAL(methname, dec, type)                             \
     dec = (decimalobject *)_convert_to_decimal(type, (PyObject *)dec, ctx, 1); \
     if (!dec) {                                                         \
@@ -983,6 +1052,8 @@
         return NULL;                                                    \
     }
 
+/* Make sure that ctx is a valid context. This is commonly used after a
+   PyArg_Parse... which might leave ctx NULL. */
 #define ENSURE_CONTEXT(methname, ctx)                                   \
     if (ctx == NULL) {                                                  \
         if (!(ctx = getcontext())) return NULL;                         \
@@ -991,6 +1062,16 @@
         return NULL;                                                    \
     }
 
+/* Define some wrappers that parse Python arguments and call the respective
+   C functions. Unfortunately, that's not possible for methods that have a
+   strange signature.
+
+   XXX: should the _do_... functions be declared inline? (there actually
+   is a new macro called Py_LOCAL for this).
+*/
+
+/* Define a Decimal method with one argument (the context).
+   The _do_* version is then called with a valid context. */
 #define DECIMAL_UNARY_FUNC(methname)                               \
     static PyObject *                                                   \
     decimal_##methname(decimalobject *self, PyObject *args, PyObject *kwds) \
@@ -1002,6 +1083,10 @@
         return (PyObject *)_do_decimal_##methname(self, ctx);           \
     }
 
+/* Define a Decimal method with two arguments (another decimal which might
+   also be an integer and a context).
+   The _do_* version is then called with an actual decimalobject and the
+   context. */
 #define DECIMAL_BINARY_FUNC(methname)                                   \
     static PyObject *                                                   \
     decimal_##methname(decimalobject *self, PyObject *args, PyObject *kwds) \
@@ -1021,7 +1106,7 @@
 
 
 /* Returns -1, 0, 1. No special error return code, must check
-   PyErr_Occurred() */
+   for that with PyErr_Occurred(). */
 static int
 _do_real_decimal_compare(decimalobject *self, decimalobject *other,
                          contextobject *ctx)
@@ -1172,10 +1257,11 @@
             return nan;
     }
 
-        
+    /* XXX */
 }
 DECIMAL_BINARY_FUNC(max)
 
+
 static decimalobject *
 _do_decimal_min(decimalobject *self, decimalobject *other,
                 contextobject *ctx)
@@ -1185,6 +1271,7 @@
 }
 DECIMAL_BINARY_FUNC(min)
 
+
 /* strip trailing 0s, change anything equal to 0 to 0e0 */
 static decimalobject *
 _do_decimal_normalize(decimalobject *self, contextobject *ctx)
@@ -1218,8 +1305,8 @@
 }
 DECIMAL_UNARY_FUNC(normalize)
 
-/* Quantize self so that its exponent is the same as the exponent of another. */
 
+/* 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)
@@ -1242,6 +1329,7 @@
     return _decimal_rescale(self, other->exp, ctx, rounding, watchexp);
 }
 
+
 static decimalobject *
 decimal_quantize(decimalobject *self, PyObject *args, PyObject *kwds)
 {
@@ -1274,6 +1362,7 @@
 _do_decimal_remainder_near(decimalobject *self, decimalobject *other,
                            contextobject *ctx)
 {
+    /* XXX */
     Py_RETURN_NONE;
 }
 DECIMAL_BINARY_FUNC(remainder_near)
@@ -1364,6 +1453,7 @@
     return ans;
 }
 
+
 static PyObject *
 decimal_to_integral(decimalobject *self, PyObject *args, PyObject *kwds)
 {
@@ -1405,6 +1495,8 @@
     return self;
 }
 
+
+/* Contents of Decimal are also immutable. */
 static PyObject *
 decimal_deepcopy(PyObject *self, PyObject *memo)
 {
@@ -1412,8 +1504,8 @@
     return self;
 }
 
-/* For internal use, this does what Python code achieves
-   with "Decimal(self)". */
+
+/* For internal use; this does what Python code achieves with "Decimal(self)". */
 static decimalobject *
 _decimal_get_copy(decimalobject *self)
 {
@@ -1428,6 +1520,7 @@
     return new;
 }
 
+
 static PyObject *
 decimal_adjusted(decimalobject *self)
 {
@@ -1438,6 +1531,7 @@
     return PyInt_FromSsize_t(ADJUSTED(self));
 }
 
+
 static PyObject *
 decimal_as_tuple(decimalobject *self)
 {
@@ -1459,12 +1553,15 @@
     return res;
 }
 
+
+/* Stringizing and formatting handling */
+
 /*
   max length of output is len(str(max_long)) + len(str(max_long)) + 
   len(".") + len("-")
 */
 #define FORMAT_SIZE 50
-#define SANITY_CHECK(x) assert((x) < end);
+#define SANITY_CHECK(x) assert((x) < end)
 
 static PyObject *
 decimal_special_str(decimalobject *d)
@@ -1501,6 +1598,7 @@
     return PyString_FromString(outbuf);
 }
 
+
 static PyObject *
 decimal_eng_zero_str(decimalobject *d, contextobject *context)
 {
@@ -1548,18 +1646,21 @@
     return PyString_FromString(p);
 }
 
+
 PyObject *
 PyDecimal_Str(PyObject *self, PyObject *args, PyObject *kwds)
 {
     return _do_decimal_str((decimalobject *)self, NULL, 0);
 }
 
+
 static PyObject *
 decimal_str(decimalobject *d)
 {
     return _do_decimal_str(d, NULL, 0);
 }
 
+
 static PyObject *
 _do_decimal_str(decimalobject *d, contextobject *context, int engineering)
 {
@@ -1684,9 +1785,9 @@
 }
 #undef SANITY_CHECK
 
-/* XXX */
+
 static PyObject *
-decimal_round(decimalobject *self, PyObject *args)
+decimal_XXX_round(decimalobject *self, PyObject *args)
 {
     contextobject *ctx = NULL;
     long prec = -1, rnd = -1;
@@ -1774,17 +1875,22 @@
      METH_NOARGS},
     {"__deepcopy__",    decimal_deepcopy,
      METH_O},
-    /* XXX */
-    {"_round",          (PyCFunction)decimal_round,
+    /* XXX: only helper methods below */
+    {"_round",          (PyCFunction)decimal_XXX_round,
      METH_VARARGS},
     {"abs__", (PyCFunction)decimal_XXX_abs, METH_VARARGS},
     {NULL, NULL}
 };
 
+
 static char decimal_doc[] =
 PyDoc_STR("Floating point class for decimal arithmetic.");
 
 
+/* Declare a "special" (double-underscore) method with two arguments for use
+   in PyNumberMethods slots. As this can take any objects, but other code
+   in this module wants to call some of those methods too, this wrapper
+   is a convenience  */
 #define DECIMAL_SPECIAL_2FUNC(func)                                     \
     static PyObject *                                                   \
     func (PyObject *self, PyObject *other) {                            \
@@ -1799,6 +1905,7 @@
         return (PyObject *)res;                                         \
     }
 
+/* Same for one-argument methods. */
 #define DECIMAL_SPECIAL_1FUNC(func)                                 \
     static PyObject *                                               \
     func (PyObject *self) {                                         \
@@ -1918,6 +2025,7 @@
 _do_decimal_multiply(decimalobject *self, decimalobject *other,
                      contextobject *ctx)
 {
+    /* XXX */
     Py_RETURN_NONE;
 }
 DECIMAL_SPECIAL_2FUNC(decimal_multiply)
@@ -1927,6 +2035,7 @@
 _do_decimal_divide(decimalobject *self, decimalobject *other,
                    contextobject *ctx)
 {
+    /* XXX */
     Py_RETURN_NONE;
 }
 DECIMAL_SPECIAL_2FUNC(decimal_divide)
@@ -1936,6 +2045,7 @@
 _do_decimal_floor_div(decimalobject *self, decimalobject *other,
                       contextobject *ctx)
 {
+    /* XXX */
     Py_RETURN_NONE;
 }
 DECIMAL_SPECIAL_2FUNC(decimal_floor_div)
@@ -1945,6 +2055,7 @@
 _do_decimal_true_div(decimalobject *self, decimalobject *other,
                      contextobject *ctx)
 {
+    /* XXX */
     Py_RETURN_NONE;
 }
 DECIMAL_SPECIAL_2FUNC(decimal_true_div)
@@ -1954,6 +2065,7 @@
 _do_decimal_remainder(decimalobject *self, decimalobject *other,
                       contextobject *ctx)
 {
+    /* XXX */
     Py_RETURN_NONE;
 }
 DECIMAL_SPECIAL_2FUNC(decimal_remainder)
@@ -1963,6 +2075,7 @@
 _do_decimal_divmod(decimalobject *self, decimalobject *other,
                    contextobject *ctx)
 {
+    /* XXX */
     Py_RETURN_NONE;
 }
 DECIMAL_SPECIAL_2FUNC(decimal_divmod)
@@ -1972,6 +2085,7 @@
 _do_decimal_power(decimalobject *self, decimalobject *other,
                   decimalobject *modulo, contextobject *ctx)
 {
+    /* XXX */
     Py_RETURN_NONE;
 }
 
@@ -2199,6 +2313,8 @@
 }
 
 
+/* Trying to avoid casting if not necessary prevents wrong function
+   signatures. */
 static PyNumberMethods decimal_as_number = {
     decimal_add,         /* nb_add */
     decimal_subtract,    /* nb_subtract */
@@ -2327,11 +2443,13 @@
 }
 
 
+/* Possible spellings for Infinity. (The first character decides the sign) */
 static char *infinities[] = {
     "inf", "infinity", "+inf", "+infinity",
     "-inf", "-infinity", 0
 };
 
+/* Decimal constructing functions. */
 
 static decimalobject *
 _decimal_fromliteralinfinity(PyTypeObject *type, char *str)
@@ -2411,8 +2529,7 @@
             goto err;
     } while (*++p);
 
-calculate:
-    
+  calculate:
     if (dend < len)
         exp = atol(str + dend + 1);
     if (dpos >= 0)
@@ -2430,7 +2547,7 @@
     /* it's a zero */
     dend = (dpos == ipos ? ipos+2 : ipos+1);
 
-finish:
+  finish:
     ndigits = dend - ipos - (dpos<0 ? 0 : 1);
     new = _new_decimalobj(type, ndigits, sign, exp);
     if (!new)
@@ -2443,10 +2560,11 @@
     }
     return new;
 
-err:
+  err:
     return handle_ConversionSyntax(type, ctx, "invalid literal for Decimal");
 }
 
+
 static PyObject *
 decimal_from_string(PyTypeObject *type, char *buffer,
                     long buf_len, contextobject *ctx)
@@ -2464,12 +2582,14 @@
     return (PyObject *)_decimal_fromliteral(type, buffer, buf_len, ctx);
 }
 
+
 PyObject *
 PyDecimal_FromString(char *buffer, long buf_len, contextobject *ctx)
 {
     return decimal_from_string(&PyDecimal_DecimalType, buffer, buf_len, ctx);
 }
 
+
 static PyObject *
 decimal_from_long(PyTypeObject *type, long value)
 {
@@ -2752,7 +2872,7 @@
 }
 
 
-/* XXX: just for debugging? */
+/* XXX: just for debugging, or should we keep those? */
 static PyMemberDef _decimal_members[] = {
     {"_sign", T_INT, offsetof(decimalobject, sign), 0},
     {"_exp", T_LONG, offsetof(decimalobject, exp), 0},
@@ -2844,7 +2964,7 @@
     &decimal_as_number,          /* tp_as_number */
     0,                           /* tp_as_sequence */
     0,                           /* tp_as_mapping */
-    (hashfunc)decimal_hash,                /* tp_hash */
+    (hashfunc)decimal_hash,      /* tp_hash */
     0,                           /* tp_call */
     (reprfunc)decimal_str,       /* tp_str */
     PyObject_GenericGetAttr,     /* tp_getattro */
@@ -2878,7 +2998,13 @@
 
 #ifdef WITH_THREAD
 
-/* Get the context for the current thread. This returns a borrowed reference. */
+/* XXX: No idea if it's actually that easy to get a thread-local context object
+   working. I intended to let Tim Peters double-check this, but now it's
+   your turn ;)
+*/
+
+/* Get the context for the current thread. This returns a borrowed reference
+   since we don't have to DECREF it in about every function then. */
 static contextobject *
 getcontext(void)
 {
@@ -2914,6 +3040,7 @@
     return ctx;        
 }
 
+
 static int
 setcontext(contextobject *ctx)
 {
@@ -2931,7 +3058,7 @@
     return 0;
 }
 
-#else
+#else /* WITH_THREAD */
 
 static PyObject *current_context;
 
@@ -2966,6 +3093,8 @@
 
 /* Context object ************************************************************/
 
+/* XXX: This is not safe for subclassing yet. */
+
 static contextobject *
 _new_contextobj(long prec, int rounding, int rounding_dec, PyObject *traps,
                 PyObject *flags, long Emin, long Emax, int capitals,
@@ -2974,7 +3103,8 @@
     contextobject *new;
     PyObject *f = NULL, *t = NULL, *i = NULL;
 
-    new = (contextobject *)PyObject_NEW(contextobject, &PyDecimal_DecimalContextType);
+    new = (contextobject *)PyObject_NEW(contextobject,
+                                        &PyDecimal_DecimalContextType);
     if (new == NULL)
         return NULL;
 
@@ -3040,19 +3170,22 @@
 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);
+    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, 1);
+    return _new_contextobj(ctx->prec, ctx->rounding, ctx->rounding_dec,
+                           ctx->traps, ctx->flags, ctx->Emin, ctx->Emax,
+                           ctx->capitals, ctx->clamp, ctx->ignored, 1);
+    /* Note the difference:                                         ^ */
 }
 
+
 static decimalobject *
 context_create_decimal(contextobject *self, PyObject *args, PyObject *kwds)
 {
@@ -3100,12 +3233,16 @@
     return PyInt_FromSsize_t(ETINY(self));
 }
 
+
 static PyObject *
 context_Etop(contextobject *self)
 {
     return PyInt_FromSsize_t(ETOP(self));
 }
 
+
+/* Define context functions that just call Decimal methods with a
+   context argument of self. */
 #define CONTEXT_UNARY_FUNC(name, decname)               \
     static PyObject *                                   \
     context_##name(contextobject *self, PyObject *a) {  \
@@ -3119,6 +3256,7 @@
         return res;                                             \
     }
 
+
 #define CONTEXT_BINARY_FUNC(name, decname)                          \
     static PyObject *                                               \
     context_##name(contextobject *self, PyObject *args) {           \
@@ -3137,6 +3275,7 @@
         return res;                                                 \
     }
 
+
 /* 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)
@@ -3296,6 +3435,7 @@
 static PyObject *
 context_reduce(contextobject *self)
 {
+    /* Yes, it seems to be as simple as that. */
     return Py_BuildValue("(O(liiOOlliiO))", self->ob_type,
                          self->prec, self->rounding,
                          self->rounding_dec, self->traps, self->flags,
@@ -3303,6 +3443,7 @@
                          self->clamp, self->ignored);
 }
 
+
 static PyObject *
 context_ignore_flags(contextobject *self, PyObject *args)
 {
@@ -3340,6 +3481,7 @@
     return ret_flags;
 }
 
+
 static PyObject *
 context_ignore_all_flags(contextobject *self)
 {
@@ -3360,6 +3502,7 @@
     return res;
 }
 
+
 static PyObject *
 context_regard_flags(contextobject *self, PyObject *args)
 {
@@ -3392,6 +3535,7 @@
     Py_RETURN_NONE;
 }
 
+
 static PyObject *
 context_set_rounding_decision(contextobject *self, PyObject *args)
 {
@@ -3409,6 +3553,7 @@
     return PyInt_FromLong((long)old_dec);
 }
 
+
 static PyObject *
 context_set_rounding(contextobject *self, PyObject *args)
 {
@@ -3425,6 +3570,10 @@
     return PyInt_FromLong((long)old_round);
 }
 
+
+/* XXX: context_raise_error and friends should really vanish after there's
+   no more Python code calling them. */
+
 static PyObject *
 _do_context_error_dispatch(int flag, PyObject *args)
 {
@@ -3561,6 +3710,16 @@
     PyErr_SetString(handler, PyString_AsString(explanation));
     return NULL;
 }
+
+
+/* XXX: no docstrings here, yet. The doctests of the original Python
+   Context methods must be transferred to some
+   other test module, because keeping them in here is a mess.
+   There might actually be a doctest function that does this.
+*/
+
+/* XXX: all that PyCFunction casting might not be necessary */
+
 static PyMethodDef context_methods[] = {
     {"clear_flags",     (PyCFunction)context_clear_flags,
      METH_NOARGS},
@@ -3636,6 +3795,7 @@
     {NULL, NULL}
 };
 
+
 static char context_doc[] =
 PyDoc_STR("Contains the context for a Decimal instance.");
 
@@ -3649,6 +3809,7 @@
     c->ob_type->tp_free(c);
 }
 
+
 #define TEST_AND_CAT(num, name)                 \
     if (_is_flag_set(self->flags, num)) {          \
         strcat(flags, name);                    \
@@ -3722,6 +3883,7 @@
 
 #undef TEST_AND_CAT
 
+
 static long
 context_hash(PyObject *c)
 {
@@ -3729,6 +3891,7 @@
     return -1;
 }
 
+
 static PyObject *
 context_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 {
@@ -3898,6 +4061,9 @@
     {NULL}
 };
 
+
+/* XXX: If the dicts stay, Context might need to become a GC type */
+
 static PyTypeObject PyDecimal_DecimalContextType = {
     PyObject_HEAD_INIT(NULL)
     0,                          /* ob_size */
@@ -3954,6 +4120,7 @@
     return ctx;
 }
 
+
 static PyObject *
 module_setcontext(PyObject *self, PyObject *args, PyObject *kwds)
 {
@@ -3985,6 +4152,7 @@
     else Py_RETURN_NONE;
 }
 
+
 static PyMethodDef module_methods[] = {
     {"getcontext", (PyCFunction)module_getcontext, METH_NOARGS},
     {"setcontext", (PyCFunction)module_setcontext, METH_VARARGS | METH_KEYWORDS},
@@ -4136,3 +4304,5 @@
         return;
 
 }
+
+/* Yay! */

Modified: sandbox/trunk/decimal-c/decimal.py
==============================================================================
--- sandbox/trunk/decimal-c/decimal.py	(original)
+++ sandbox/trunk/decimal-c/decimal.py	Sat May 27 17:38:57 2006
@@ -1,119 +1,3 @@
-# Copyright (c) 2004 Python Software Foundation.
-# All rights reserved.
-
-# Written by Eric Price <eprice at tjhsst.edu>
-#    and Facundo Batista <facundo at taniquetil.com.ar>
-#    and Raymond Hettinger <python at rcn.com>
-#    and Aahz <aahz at pobox.com>
-#    and Tim Peters
-
-# This module is currently Py2.3 compatible and should be kept that way
-# unless a major compelling advantage arises.  IOW, 2.3 compatibility is
-# strongly preferred, but not guaranteed.
-
-# Also, this module should be kept in sync with the latest updates of
-# the IBM specification as it evolves.  Those updates will be treated
-# as bug fixes (deviation from the spec is a compatibility, usability
-# bug) and will be backported.  At this point the spec is stabilizing
-# and the updates are becoming fewer, smaller, and less significant.
-
-"""
-This is a Py2.3 implementation of decimal floating point arithmetic based on
-the General Decimal Arithmetic Specification:
-
-    www2.hursley.ibm.com/decimal/decarith.html
-
-and IEEE standard 854-1987:
-
-    www.cs.berkeley.edu/~ejr/projects/754/private/drafts/854-1987/dir.html
-
-Decimal floating point has finite precision with arbitrarily large bounds.
-
-The purpose of the module is to support arithmetic using familiar
-"schoolhouse" rules and to avoid the some of tricky representation
-issues associated with binary floating point.  The package is especially
-useful for financial applications or for contexts where users have
-expectations that are at odds with binary floating point (for instance,
-in binary floating point, 1.00 % 0.1 gives 0.09999999999999995 instead
-of the expected Decimal("0.00") returned by decimal floating point).
-
-Here are some examples of using the decimal module:
-
->>> from decimal import *
->>> setcontext(ExtendedContext)
->>> Decimal(0)
-Decimal("0")
->>> Decimal("1")
-Decimal("1")
->>> Decimal("-.0123")
-Decimal("-0.0123")
->>> Decimal(123456)
-Decimal("123456")
->>> Decimal("123.45e12345678901234567890")
-Decimal("1.2345E+12345678901234567892")
->>> Decimal("1.33") + Decimal("1.27")
-Decimal("2.60")
->>> Decimal("12.34") + Decimal("3.87") - Decimal("18.41")
-Decimal("-2.20")
->>> dig = Decimal(1)
->>> print dig / Decimal(3)
-0.333333333
->>> getcontext().prec = 18
->>> print dig / Decimal(3)
-0.333333333333333333
->>> print dig.sqrt()
-1
->>> print Decimal(3).sqrt()
-1.73205080756887729
->>> print Decimal(3) ** 123
-4.85192780976896427E+58
->>> inf = Decimal(1) / Decimal(0)
->>> print inf
-Infinity
->>> neginf = Decimal(-1) / Decimal(0)
->>> print neginf
--Infinity
->>> print neginf + inf
-NaN
->>> print neginf * inf
--Infinity
->>> print dig / 0
-Infinity
->>> getcontext().traps[DivisionByZero] = 1
->>> print dig / 0
-Traceback (most recent call last):
-  ...
-  ...
-  ...
-DivisionByZero: x / 0
->>> c = Context()
->>> c.traps[InvalidOperation] = 0
->>> print c.flags[InvalidOperation]
-0
->>> c.divide(Decimal(0), Decimal(0))
-Decimal("NaN")
->>> c.traps[InvalidOperation] = 1
->>> print c.flags[InvalidOperation]
-1
->>> c.flags[InvalidOperation] = 0
->>> print c.flags[InvalidOperation]
-0
->>> print c.divide(Decimal(0), Decimal(0))
-Traceback (most recent call last):
-  ...
-  ...
-  ...
-InvalidOperation: 0 / 0
->>> print c.flags[InvalidOperation]
-1
->>> c.flags[InvalidOperation] = 0
->>> c.traps[InvalidOperation] = 0
->>> print c.divide(Decimal(0), Decimal(0))
-NaN
->>> print c.flags[InvalidOperation]
-1
->>>
-"""
 
 __all__ = [
     # Two major classes
@@ -136,14 +20,7 @@
 
 import copy as _copy
 
-# #Rounding
-# ROUND_DOWN = 'ROUND_DOWN'
-# ROUND_HALF_UP = 'ROUND_HALF_UP'
-# ROUND_HALF_EVEN = 'ROUND_HALF_EVEN'
-# ROUND_CEILING = 'ROUND_CEILING'
-# ROUND_FLOOR = 'ROUND_FLOOR'
-# ROUND_UP = 'ROUND_UP'
-# ROUND_HALF_DOWN = 'ROUND_HALF_DOWN'
+import _decimal
 
 # #Rounding decision (not part of the public API)
 # NEVER_ROUND = 'NEVER_ROUND'    # Round in division (non-divmod), sqrt ONLY
@@ -384,89 +261,14 @@
      ROUND_HALF_DOWN, ROUND_HALF_EVEN, ROUND_FLOOR, \
      ROUND_CEILING, ALWAYS_ROUND, NEVER_ROUND
 
-##### Context Functions #######################################
 
-# The getcontext() and setcontext() function manage access to a thread-local
-# current context.  Py2.4 offers direct support for thread locals.  If that
-# is not available, use threading.currentThread() which is slower but will
-# work for older Pythons.  If threads are not part of the build, create a
-# mock threading object with threading.local() returning the module namespace.
-
-#try:
-#    import threading
-#except ImportError:
-#    # Python was compiled without threads; create a mock object instead
-#    import sys
-#    class MockThreading:
-#        def local(self, sys=sys):
-#            return sys.modules[__name__]
-#    threading = MockThreading()
-#    del sys, MockThreading
-#
-#try:
-#    threading.local
-#
-#except AttributeError:
-#
-#    #To fix reloading, force it to create a new context
-#    #Old contexts have different exceptions in their dicts, making problems.
-#    if hasattr(threading.currentThread(), '__decimal_context__'):
-#        del threading.currentThread().__decimal_context__
-#
-#    def setcontext(context):
-#        """Set this thread's context to context."""
-#        if context in (DefaultContext, BasicContext, ExtendedContext):
-#            context = context.copy()
-#            context.clear_flags()
-#        threading.currentThread().__decimal_context__ = context
-#
-#    def getcontext():
-#        """Returns this thread's context.
-#
-#        If this thread does not yet have a context, returns
-#        a new context and sets this thread's context.
-#        New contexts are copies of DefaultContext.
-#        """
-#        try:
-#            return threading.currentThread().__decimal_context__
-#        except AttributeError:
-#            context = Context()
-#            threading.currentThread().__decimal_context__ = context
-#            return context
-#
-#else:
-#
-#    local = threading.local()
-#    if hasattr(local, '__decimal_context__'):
-#        del local.__decimal_context__
-#
-#    def getcontext(_local=local):
-#        """Returns this thread's context.
-#
-#        If this thread does not yet have a context, returns
-#        a new context and sets this thread's context.
-#        New contexts are copies of DefaultContext.
-#        """
-#        try:
-#            return _local.__decimal_context__
-#        except AttributeError:
-#            context = Context()
-#            _local.__decimal_context__ = context
-#            return context
-#
-#    def setcontext(context, _local=local):
-#        """Set this thread's context to context."""
-#        if context in (DefaultContext, BasicContext, ExtendedContext):
-#            context = context.copy()
-#            context.clear_flags()
-#        _local.__decimal_context__ = context
-#
-#    del threading, local        # Don't contaminate the namespace
-#
+# ##### Useful Constants (internal use only) ####################
 
-##### Decimal class ###########################################
+from _decimal import Inf, negInf, NaN
 
-import _decimal
+Infsign = (Inf, negInf)
+
+##### Decimal class ###########################################
 
 getcontext = _decimal.getcontext
 setcontext = _decimal.setcontext
@@ -474,150 +276,13 @@
 class Decimal(_decimal.Decimal):
     """Floating point class for decimal arithmetic."""
 
-    # Generally, the value of the Decimal instance is given by
-    #  (-1)**_sign * _int * 10**_exp
-    # Special values are signified by _is_special == True
-
-    # HACK: to get support for converting WorkRep instances
+    # to get support for converting WorkRep instances
     def __new__(cls, value="0", context=None):
         if isinstance(value, _WorkRep):
             value = (value.sign, tuple(map(int, str(value.int))), int(value.exp))
             
         return _decimal.Decimal.__new__(cls, value, context)
 
-
-#    # We're immutable, so use __new__ not __init__
-#    def __new__(cls, value="0", context=None):
-#        """Create a decimal point instance.
-#
-#        >>> Decimal('3.14')              # string input
-#        Decimal("3.14")
-#        >>> Decimal((0, (3, 1, 4), -2))  # tuple input (sign, digit_tuple, exponent)
-#        Decimal("3.14")
-#        >>> Decimal(314)                 # int or long
-#        Decimal("314")
-#        >>> Decimal(Decimal(314))        # another decimal instance
-#        Decimal("314")
-#        """
-#
-#        self = _decimal.Decimal.__new__(cls)
-#        self._is_special = False
-#
-#        # From an internal working value
-#        if isinstance(value, _WorkRep):
-#            self._sign = value.sign
-#            self._int = tuple(map(int, str(value.int)))
-#            self._exp = int(value.exp)
-#            return self
-#
-#        # From another decimal
-#        if isinstance(value, Decimal):
-#            self._exp  = value._exp
-#            self._sign = value._sign
-#            self._int  = value._int
-#            self._is_special  = value._is_special
-#            return self
-#
-#        # From an integer
-#        if isinstance(value, (int,long)):
-#            if value >= 0:
-#                self._sign = 0
-#            else:
-#                self._sign = 1
-#            self._exp = 0
-#            self._int = tuple(map(int, str(abs(value))))
-#            return self
-#
-#        # tuple/list conversion (possibly from as_tuple())
-#        if isinstance(value, (list,tuple)):
-#            if len(value) != 3:
-#                raise ValueError, 'Invalid arguments'
-#            if value[0] not in (0,1):
-#                raise ValueError, 'Invalid sign'
-#            for digit in value[1]:
-#                if not isinstance(digit, (int,long)) or digit < 0:
-#                    raise ValueError, "The second value in the tuple must be composed of non negative integer elements."
-#
-#            self._sign = value[0]
-#            self._int  = tuple(value[1])
-#            if value[2] in ('F','n','N'):
-#                self._exp = value[2]
-#                self._is_special = True
-#            else:
-#                self._exp  = int(value[2])
-#            return self
-#
-#        if isinstance(value, float):
-#            raise TypeError("Cannot convert float to Decimal.  " +
-#                            "First convert the float to a string")
-#
-#        # Other argument types may require the context during interpretation
-#        if context is None:
-#            context = getcontext()
-#
-#        # From a string
-#        # REs insist on real strings, so we can too.
-#        if isinstance(value, basestring):
-#            if _isinfinity(value):
-#                self._exp = 'F'
-#                self._int = (0,)
-#                self._is_special = True
-#                if _isinfinity(value) == 1:
-#                    self._sign = 0
-#                else:
-#                    self._sign = 1
-#                return self
-#            if _isnan(value):
-#                sig, sign, diag = _isnan(value)
-#                self._is_special = True
-#                if len(diag) > context.prec: #Diagnostic info too long
-#                    self._sign, self._int, self._exp = \
-#                                context._raise_error(ConversionSyntax)
-#                    return self
-#                if sig == 1:
-#                    self._exp = 'n' #qNaN
-#                else: #sig == 2
-#                    self._exp = 'N' #sNaN
-#                self._sign = sign
-#                self._int = tuple(map(int, diag)) #Diagnostic info
-#                return self
-#            try:
-#                self._sign, self._int, self._exp = _string2exact(value)
-#            except ValueError:
-#                self._is_special = True
-#                self._sign, self._int, self._exp = context._raise_error(ConversionSyntax)
-#            return self
-#
-#        raise TypeError("Cannot convert %r to Decimal" % value)
-
-#     def _isnan(self):
-#         """Returns whether the number is not actually one.
-
-#         0 if a number
-#         1 if NaN
-#         2 if sNaN
-#         """
-#         if self._is_special:
-#             exp = self._exp
-#             if exp == 'n':
-#                 return 1
-#             elif exp == 'N':
-#                 return 2
-#         return 0
-
-#     def _isinfinity(self):
-#         """Returns whether the number is infinite
-
-#         0 if finite or not a number
-#         1 if +INF
-#         -1 if -INF
-#         """
-#         if self._exp == 'F':
-#             if self._sign:
-#                 return -1
-#             return 1
-#         return 0
-
     def _isnan(self):
         if self._sign in (4, 5): return 1
         if self._sign in (6, 7): return 2
@@ -658,198 +323,188 @@
             return other
         return 0
 
-    def __nonzero__(self):
-        """Is the number non-zero?
-
-        0 if self == 0
-        1 if self != 0
-        """
-        if self._is_special:
-            return 1
-        return sum(self._int) != 0
-
-    def __cmp__(self, other, context=None):
-        other = _convert_other(other)
-        if other is NotImplemented:
-            return other
-
-        if self._is_special or other._is_special:
-            ans = self._check_nans(other, context)
-            if ans:
-                return 1 # Comparison involving NaN's always reports self > other
-
-            # INF = INF
-            return cmp(self._isinfinity(), other._isinfinity())
-
-        if not self and not other:
-            return 0 #If both 0, sign comparison isn't certain.
-
-        #If different signs, neg one is less
-        if other._sign < self._sign:
-            return -1
-        if self._sign < other._sign:
-            return 1
-
-        self_adjusted = self.adjusted()
-        other_adjusted = other.adjusted()
-        if self_adjusted == other_adjusted and \
-           self._int + (0,)*(self._exp - other._exp) == \
-           other._int + (0,)*(other._exp - self._exp):
-            return 0 #equal, except in precision. ([0]*(-x) = [])
-        elif self_adjusted > other_adjusted and self._int[0] != 0:
-            return (-1)**self._sign
-        elif self_adjusted < other_adjusted and other._int[0] != 0:
-            return -((-1)**self._sign)
-
-        # Need to round, so make sure we have a valid context
-        if context is None:
-            context = getcontext()
-
-        context = context._shallow_copy()
-        rounding = context._set_rounding(ROUND_UP) #round away from 0
-
-        flags = context._ignore_all_flags()
-        res = self.__sub__(other, context=context)
-
-        context._regard_flags(*flags)
-
-        context.rounding = rounding
-
-        if not res:
-            return 0
-        elif res._sign:
-            return -1
-        return 1
-
-    def __eq__(self, other):
-        if not isinstance(other, (Decimal, int, long)):
-            return NotImplemented
-        return self.__cmp__(other) == 0
-
-    def __ne__(self, other):
-        if not isinstance(other, (Decimal, int, long)):
-            return NotImplemented
-        return self.__cmp__(other) != 0
-
-    def compare(self, other, context=None):
-        """Compares one to another.
-
-        -1 => a < b
-        0  => a = b
-        1  => a > b
-        NaN => one is NaN
-        Like __cmp__, but returns Decimal instances.
-        """
-        other = _convert_other(other)
-        if other is NotImplemented:
-            return other
-
-        #compare(NaN, NaN) = NaN
-        if (self._is_special or other and other._is_special):
-            ans = self._check_nans(other, context)
-            if ans:
-                return ans
-
-        return Decimal(self.__cmp__(other, context))
-
-    def __hash__(self):
-        """x.__hash__() <==> hash(x)"""
-        # Decimal integers must hash the same as the ints
-        # Non-integer decimals are normalized and hashed as strings
-        # Normalization assures that hash(100E-1) == hash(10)
-        if self._is_special:
-            if self._isnan():
-                raise TypeError('Cannot hash a NaN value.')
-            return hash(str(self))
-        i = int(self)
-        if self == Decimal(i):
-            return hash(i)
-        assert self.__nonzero__()   # '-0' handled by integer case
-        return hash(str(self.normalize()))
-
-    def as_tuple(self):
-        """Represents the number as a triple tuple.
-
-        To show the internals exactly as they are.
-        """
-        return (self._sign, self._int, self._exp)
-
-    def __repr__(self):
-        """Represents the number as an instance of Decimal."""
-        # Invariant:  eval(repr(d)) == d
-        return 'Decimal("%s")' % str(self)
-
-    def __neg__(self, context=None):
-        """Returns a copy with the sign switched.
-
-        Rounds, if it has reason.
-        """
-        if self._is_special:
-            ans = self._check_nans(context=context)
-            if ans:
-                return ans
+#     def __cmp__(self, other, context=None):
+#         other = _convert_other(other)
+#         if other is NotImplemented:
+#             return other
+
+#         if self._is_special or other._is_special:
+#             ans = self._check_nans(other, context)
+#             if ans:
+#                 return 1 # Comparison involving NaN's always reports self > other
+
+#             # INF = INF
+#             return cmp(self._isinfinity(), other._isinfinity())
+
+#         if not self and not other:
+#             return 0 #If both 0, sign comparison isn't certain.
+
+#         #If different signs, neg one is less
+#         if other._sign < self._sign:
+#             return -1
+#         if self._sign < other._sign:
+#             return 1
 
-        if not self:
-            # -Decimal('0') is Decimal('0'), not Decimal('-0')
-            sign = 0
-        elif self._sign:
-            sign = 0
-        else:
-            sign = 1
+#         self_adjusted = self.adjusted()
+#         other_adjusted = other.adjusted()
+#         if self_adjusted == other_adjusted and \
+#            self._int + (0,)*(self._exp - other._exp) == \
+#            other._int + (0,)*(other._exp - self._exp):
+#             return 0 #equal, except in precision. ([0]*(-x) = [])
+#         elif self_adjusted > other_adjusted and self._int[0] != 0:
+#             return (-1)**self._sign
+#         elif self_adjusted < other_adjusted and other._int[0] != 0:
+#             return -((-1)**self._sign)
+
+#         # Need to round, so make sure we have a valid context
+#         if context is None:
+#             context = getcontext()
+
+#         context = context._shallow_copy()
+#         rounding = context._set_rounding(ROUND_UP) #round away from 0
+
+#         flags = context._ignore_all_flags()
+#         res = self.__sub__(other, context=context)
+
+#         context._regard_flags(*flags)
+
+#         context.rounding = rounding
+
+#         if not res:
+#             return 0
+#         elif res._sign:
+#             return -1
+#         return 1
+
+#     def __eq__(self, other):
+#         if not isinstance(other, (Decimal, int, long)):
+#             return NotImplemented
+#         return self.__cmp__(other) == 0
+
+#     def __ne__(self, other):
+#         if not isinstance(other, (Decimal, int, long)):
+#             return NotImplemented
+#         return self.__cmp__(other) != 0
+
+#     def compare(self, other, context=None):
+#         """Compares one to another.
+
+#         -1 => a < b
+#         0  => a = b
+#         1  => a > b
+#         NaN => one is NaN
+#         Like __cmp__, but returns Decimal instances.
+#         """
+#         other = _convert_other(other)
+#         if other is NotImplemented:
+#             return other
+
+#         #compare(NaN, NaN) = NaN
+#         if (self._is_special or other and other._is_special):
+#             ans = self._check_nans(other, context)
+#             if ans:
+#                 return ans
+
+#         return Decimal(self.__cmp__(other, context))
+
+#     def __hash__(self):
+#         """x.__hash__() <==> hash(x)"""
+#         # Decimal integers must hash the same as the ints
+#         # Non-integer decimals are normalized and hashed as strings
+#         # Normalization assures that hash(100E-1) == hash(10)
+#         if self._is_special:
+#             if self._isnan():
+#                 raise TypeError('Cannot hash a NaN value.')
+#             return hash(str(self))
+#         i = int(self)
+#         if self == Decimal(i):
+#             return hash(i)
+#         assert self.__nonzero__()   # '-0' handled by integer case
+#         return hash(str(self.normalize()))
 
-        if context is None:
-            context = getcontext()
-        if context._rounding_decision == ALWAYS_ROUND:
-            return Decimal((sign, self._int, self._exp))._fix(context)
-        return Decimal( (sign, self._int, self._exp))
+#     def as_tuple(self):
+#         """Represents the number as a triple tuple.
 
-    def __pos__(self, context=None):
-        """Returns a copy, unless it is a sNaN.
+#         To show the internals exactly as they are.
+#         """
+#         return (self._sign, self._int, self._exp)
 
-        Rounds the number (if more then precision digits)
-        """
-        if self._is_special:
-            ans = self._check_nans(context=context)
-            if ans:
-                return ans
+#     def __repr__(self):
+#         """Represents the number as an instance of Decimal."""
+#         # Invariant:  eval(repr(d)) == d
+#         return 'Decimal("%s")' % str(self)
 
-        sign = self._sign
-        if not self:
-            # + (-0) = 0
-            sign = 0
+#     def __neg__(self, context=None):
+#         """Returns a copy with the sign switched.
 
-        if context is None:
-            context = getcontext()
+#         Rounds, if it has reason.
+#         """
+#         if self._is_special:
+#             ans = self._check_nans(context=context)
+#             if ans:
+#                 return ans
+
+#         if not self:
+#             # -Decimal('0') is Decimal('0'), not Decimal('-0')
+#             sign = 0
+#         elif self._sign:
+#             sign = 0
+#         else:
+#             sign = 1
+
+#         if context is None:
+#             context = getcontext()
+#         if context._rounding_decision == ALWAYS_ROUND:
+#             return Decimal((sign, self._int, self._exp))._fix(context)
+#         return Decimal( (sign, self._int, self._exp))
 
-        if context._rounding_decision == ALWAYS_ROUND:
-            ans = self._fix(context)
-        else:
-            ans = Decimal(self)
-        ans._sign = sign
-        return ans
+#     def __pos__(self, context=None):
+#         """Returns a copy, unless it is a sNaN.
 
-    def __abs__(self, round=1, context=None):
-        """Returns the absolute value of self.
+#         Rounds the number (if more then precision digits)
+#         """
+#         if self._is_special:
+#             ans = self._check_nans(context=context)
+#             if ans:
+#                 return ans
+
+#         sign = self._sign
+#         if not self:
+#             # + (-0) = 0
+#             sign = 0
+
+#         if context is None:
+#             context = getcontext()
+
+#         if context._rounding_decision == ALWAYS_ROUND:
+#             ans = self._fix(context)
+#         else:
+#             ans = Decimal(self)
+#         ans._sign = sign
+#         return ans
 
-        If the second argument is 0, do not round.
-        """
-        if self._is_special:
-            ans = self._check_nans(context=context)
-            if ans:
-                return ans
+#     def __abs__(self, round=1, context=None):
+#         """Returns the absolute value of self.
 
-        if not round:
-            if context is None:
-                context = getcontext()
-            context = context._shallow_copy()
-            context._set_rounding_decision(NEVER_ROUND)
-
-        if self._sign:
-            ans = self.__neg__(context=context)
-        else:
-            ans = self.__pos__(context=context)
+#         If the second argument is 0, do not round.
+#         """
+#         if self._is_special:
+#             ans = self._check_nans(context=context)
+#             if ans:
+#                 return ans
+
+#         if not round:
+#             if context is None:
+#                 context = getcontext()
+#             context = context._shallow_copy()
+#             context._set_rounding_decision(NEVER_ROUND)
+
+#         if self._sign:
+#             ans = self.__neg__(context=context)
+#         else:
+#             ans = self.__pos__(context=context)
 
-        return ans
+#         return ans
 
     def __add__(self, other, context=None):
         """Returns self + other.
@@ -1160,7 +815,7 @@
 
         #If we're dividing into ints, and self < other, stop.
         #self.__abs__(0) does not round.
-        if divmod and (self.__abs__(0, context) < other.__abs__(0, context)):
+        if divmod and (self.abs__(0, context) < other.abs__(0, context)):
 
             if divmod == 1 or divmod == 3:
                 exp = min(self._exp, other._exp)
@@ -1343,7 +998,7 @@
 
         decrease = not side._iseven()
         rounding = context._set_rounding_decision(NEVER_ROUND)
-        side = side.__abs__(context=context)
+        side = side.abs__(-1, context)
         context._set_rounding_decision(rounding)
 
         s1, s2 = r._sign, comparison._sign
@@ -1375,33 +1030,33 @@
             return other
         return other.__floordiv__(self, context=context)
 
-    def __float__(self):
-        """Float representation."""
-        return float(str(self))
+#     def __float__(self):
+#         """Float representation."""
+#         return float(str(self))
 
-    def __int__(self):
-        """Converts self to an int, truncating if necessary."""
-        if self._is_special:
-            if self._isnan():
-                context = getcontext()
-                return context._raise_error(InvalidContext)
-            elif self._isinfinity():
-                raise OverflowError, "Cannot convert infinity to long"
-        if self._exp >= 0:
-            s = ''.join(map(str, self._int)) + '0'*self._exp
-        else:
-            s = ''.join(map(str, self._int))[:self._exp]
-        if s == '':
-            s = '0'
-        sign = '-'*self._sign
-        return int(sign + s)
+#     def __int__(self):
+#         """Converts self to an int, truncating if necessary."""
+#         if self._is_special:
+#             if self._isnan():
+#                 context = getcontext()
+#                 return context._raise_error(InvalidContext)
+#             elif self._isinfinity():
+#                 raise OverflowError, "Cannot convert infinity to long"
+#         if self._exp >= 0:
+#             s = ''.join(map(str, self._int)) + '0'*self._exp
+#         else:
+#             s = ''.join(map(str, self._int))[:self._exp]
+#         if s == '':
+#             s = '0'
+#         sign = '-'*self._sign
+#         return int(sign + s)
 
-    def __long__(self):
-        """Converts to a long.
+#     def __long__(self):
+#         """Converts to a long.
 
-        Equivalent to long(int(self))
-        """
-        return long(self.__int__())
+#         Equivalent to long(int(self))
+#         """
+#         return long(self.__int__())
 
     def _fix(self, context):
         """Round if it is necessary to keep self within prec precision.
@@ -1419,7 +1074,7 @@
         prec = context.prec
         ans = self._fixexponents(context)
         if len(ans._int) > prec:
-            ans = ans._round(prec, context=context)
+            ans = ans._round(prec, -1, context)
             ans = ans._fixexponents(context)
         return ans
 
@@ -1466,156 +1121,156 @@
                     return context._raise_error(Overflow, 'above Emax', ans._sign)
         return ans
 
-    def _round(self, prec=None, rounding=None, context=None):
-        """Returns a rounded version of self.
-
-        You can specify the precision or rounding method.  Otherwise, the
-        context determines it.
-        """
-
-        if self._is_special:
-            ans = self._check_nans(context=context)
-            if ans:
-                return ans
-
-            if self._isinfinity():
-                return Decimal(self)
-
-        if context is None:
-            context = getcontext()
-
-        if rounding is None:
-            rounding = context.rounding
-        if prec is None:
-            prec = context.prec
-
-        if not self:
-            if prec <= 0:
-                dig = (0,)
-                exp = len(self._int) - prec + self._exp
-            else:
-                dig = (0,) * prec
-                exp = len(self._int) + self._exp - prec
-            ans = Decimal((self._sign, dig, exp))
-            context._raise_error(Rounded)
-            return ans
-
-        if prec == 0:
-            temp = Decimal(self)
-            temp._int = (0,)+temp._int
-            prec = 1
-        elif prec < 0:
-            exp = self._exp + len(self._int) - prec - 1
-            temp = Decimal( (self._sign, (0, 1), exp))
-            prec = 1
-        else:
-            temp = Decimal(self)
+#     def _round(self, prec=None, rounding=-1, context=None):
+#         """Returns a rounded version of self.
 
-        numdigits = len(temp._int)
-        if prec == numdigits:
-            return temp
-
-        # See if we need to extend precision
-        expdiff = prec - numdigits
-        if expdiff > 0:
-            tmp = list(temp._int)
-            tmp.extend([0] * expdiff)
-            ans =  Decimal( (temp._sign, tmp, temp._exp - expdiff))
-            return ans
-
-        #OK, but maybe all the lost digits are 0.
-        lostdigits = self._int[expdiff:]
-        if lostdigits == (0,) * len(lostdigits):
-            ans = Decimal( (temp._sign, temp._int[:prec], temp._exp - expdiff))
-            #Rounded, but not Inexact
-            context._raise_error(Rounded)
-            return ans
-
-        # Okay, let's round and lose data
-
-        this_function = getattr(temp, self._pick_rounding_function[rounding])
-        #Now we've got the rounding function
-
-        if prec != context.prec:
-            context = context._shallow_copy()
-            context.prec = prec
-        ans = this_function(prec, expdiff, context)
-        context._raise_error(Rounded)
-        context._raise_error(Inexact, 'Changed in rounding')
-
-        return ans
-
-    _pick_rounding_function = {}
-
-    def _round_down(self, prec, expdiff, context):
-        """Also known as round-towards-0, truncate."""
-        return Decimal( (self._sign, self._int[:prec], self._exp - expdiff) )
-
-    def _round_half_up(self, prec, expdiff, context, tmp = None):
-        """Rounds 5 up (away from 0)"""
-
-        if tmp is None:
-            tmp = Decimal( (self._sign,self._int[:prec], self._exp - expdiff))
-        if self._int[prec] >= 5:
-            tmp = tmp._increment(round=0, context=context)
-            if len(tmp._int) > prec:
-                return Decimal( (tmp._sign, tmp._int[:-1], tmp._exp + 1))
-        return tmp
-
-    def _round_half_even(self, prec, expdiff, context):
-        """Round 5 to even, rest to nearest."""
-
-        tmp = Decimal( (self._sign, self._int[:prec], self._exp - expdiff))
-        half = (self._int[prec] == 5)
-        if half:
-            for digit in self._int[prec+1:]:
-                if digit != 0:
-                    half = 0
-                    break
-        if half:
-            if self._int[prec-1] & 1 == 0:
-                return tmp
-        return self._round_half_up(prec, expdiff, context, tmp)
-
-    def _round_half_down(self, prec, expdiff, context):
-        """Round 5 down"""
-
-        tmp = Decimal( (self._sign, self._int[:prec], self._exp - expdiff))
-        half = (self._int[prec] == 5)
-        if half:
-            for digit in self._int[prec+1:]:
-                if digit != 0:
-                    half = 0
-                    break
-        if half:
-            return tmp
-        return self._round_half_up(prec, expdiff, context, tmp)
-
-    def _round_up(self, prec, expdiff, context):
-        """Rounds away from 0."""
-        tmp = Decimal( (self._sign, self._int[:prec], self._exp - expdiff) )
-        for digit in self._int[prec:]:
-            if digit != 0:
-                tmp = tmp._increment(round=1, context=context)
-                if len(tmp._int) > prec:
-                    return Decimal( (tmp._sign, tmp._int[:-1], tmp._exp + 1))
-                else:
-                    return tmp
-        return tmp
-
-    def _round_ceiling(self, prec, expdiff, context):
-        """Rounds up (not away from 0 if negative.)"""
-        if self._sign:
-            return self._round_down(prec, expdiff, context)
-        else:
-            return self._round_up(prec, expdiff, context)
+#         You can specify the precision or rounding method.  Otherwise, the
+#         context determines it.
+#         """
 
-    def _round_floor(self, prec, expdiff, context):
-        """Rounds down (not towards 0 if negative)"""
-        if not self._sign:
-            return self._round_down(prec, expdiff, context)
-        else:
-            return self._round_up(prec, expdiff, context)
+#         if self._is_special:
+#             ans = self._check_nans(context=context)
+#             if ans:
+#                 return ans
+
+#             if self._isinfinity():
+#                 return Decimal(self)
+
+#         if context is None:
+#             context = getcontext()
+
+#         if rounding is None:
+#             rounding = context.rounding
+#         if prec is None:
+#             prec = context.prec
+
+#         if not self:
+#             if prec <= 0:
+#                 dig = (0,)
+#                 exp = len(self._int) - prec + self._exp
+#             else:
+#                 dig = (0,) * prec
+#                 exp = len(self._int) + self._exp - prec
+#             ans = Decimal((self._sign, dig, exp))
+#             context._raise_error(Rounded)
+#             return ans
+
+#         if prec == 0:
+#             temp = Decimal(self)
+#             temp._int = (0,)+temp._int
+#             prec = 1
+#         elif prec < 0:
+#             exp = self._exp + len(self._int) - prec - 1
+#             temp = Decimal( (self._sign, (0, 1), exp))
+#             prec = 1
+#         else:
+#             temp = Decimal(self)
+
+#         numdigits = len(temp._int)
+#         if prec == numdigits:
+#             return temp
+
+#         # See if we need to extend precision
+#         expdiff = prec - numdigits
+#         if expdiff > 0:
+#             tmp = list(temp._int)
+#             tmp.extend([0] * expdiff)
+#             ans =  Decimal( (temp._sign, tmp, temp._exp - expdiff))
+#             return ans
+
+#         #OK, but maybe all the lost digits are 0.
+#         lostdigits = self._int[expdiff:]
+#         if lostdigits == (0,) * len(lostdigits):
+#             ans = Decimal( (temp._sign, temp._int[:prec], temp._exp - expdiff))
+#             #Rounded, but not Inexact
+#             context._raise_error(Rounded)
+#             return ans
+
+#         # Okay, let's round and lose data
+
+#         this_function = getattr(temp, self._pick_rounding_function[rounding])
+#         #Now we've got the rounding function
+
+#         if prec != context.prec:
+#             context = context._shallow_copy()
+#             context.prec = prec
+#         ans = this_function(prec, expdiff, context)
+#         context._raise_error(Rounded)
+#         context._raise_error(Inexact, 'Changed in rounding')
+
+#         return ans
+
+#     _pick_rounding_function = {}
+
+#     def _round_down(self, prec, expdiff, context):
+#         """Also known as round-towards-0, truncate."""
+#         return Decimal( (self._sign, self._int[:prec], self._exp - expdiff) )
+
+#     def _round_half_up(self, prec, expdiff, context, tmp = None):
+#         """Rounds 5 up (away from 0)"""
+
+#         if tmp is None:
+#             tmp = Decimal( (self._sign,self._int[:prec], self._exp - expdiff))
+#         if self._int[prec] >= 5:
+#             tmp = tmp._increment(round=0, context=context)
+#             if len(tmp._int) > prec:
+#                 return Decimal( (tmp._sign, tmp._int[:-1], tmp._exp + 1))
+#         return tmp
+
+#     def _round_half_even(self, prec, expdiff, context):
+#         """Round 5 to even, rest to nearest."""
+
+#         tmp = Decimal( (self._sign, self._int[:prec], self._exp - expdiff))
+#         half = (self._int[prec] == 5)
+#         if half:
+#             for digit in self._int[prec+1:]:
+#                 if digit != 0:
+#                     half = 0
+#                     break
+#         if half:
+#             if self._int[prec-1] & 1 == 0:
+#                 return tmp
+#         return self._round_half_up(prec, expdiff, context, tmp)
+
+#     def _round_half_down(self, prec, expdiff, context):
+#         """Round 5 down"""
+
+#         tmp = Decimal( (self._sign, self._int[:prec], self._exp - expdiff))
+#         half = (self._int[prec] == 5)
+#         if half:
+#             for digit in self._int[prec+1:]:
+#                 if digit != 0:
+#                     half = 0
+#                     break
+#         if half:
+#             return tmp
+#         return self._round_half_up(prec, expdiff, context, tmp)
+
+#     def _round_up(self, prec, expdiff, context):
+#         """Rounds away from 0."""
+#         tmp = Decimal( (self._sign, self._int[:prec], self._exp - expdiff) )
+#         for digit in self._int[prec:]:
+#             if digit != 0:
+#                 tmp = tmp._increment(round=1, context=context)
+#                 if len(tmp._int) > prec:
+#                     return Decimal( (tmp._sign, tmp._int[:-1], tmp._exp + 1))
+#                 else:
+#                     return tmp
+#         return tmp
+
+#     def _round_ceiling(self, prec, expdiff, context):
+#         """Rounds up (not away from 0 if negative.)"""
+#         if self._sign:
+#             return self._round_down(prec, expdiff, context)
+#         else:
+#             return self._round_up(prec, expdiff, context)
+
+#     def _round_floor(self, prec, expdiff, context):
+#         """Rounds down (not towards 0 if negative)"""
+#         if not self._sign:
+#             return self._round_down(prec, expdiff, context)
+#         else:
+#             return self._round_up(prec, expdiff, context)
 
     def __pow__(self, n, modulo = None, context=None):
         """Return self ** n (mod modulo)
@@ -1715,60 +1370,60 @@
             return other
         return other.__pow__(self, context=context)
 
-    def normalize(self, context=None):
-        """Normalize- strip trailing 0s, change anything equal to 0 to 0e0"""
-
-        if self._is_special:
-            ans = self._check_nans(context=context)
-            if ans:
-                return ans
-
-        dup = self._fix(context)
-        if dup._isinfinity():
-            return dup
-
-        if not dup:
-            return Decimal( (dup._sign, (0,), 0) )
-        end = len(dup._int)
-        exp = dup._exp
-        while dup._int[end-1] == 0:
-            exp += 1
-            end -= 1
-        return Decimal( (dup._sign, dup._int[:end], exp) )
+#     def normalize(self, context=None):
+#         """Normalize- strip trailing 0s, change anything equal to 0 to 0e0"""
 
+#         if self._is_special:
+#             ans = self._check_nans(context=context)
+#             if ans:
+#                 return ans
+
+#         dup = self._fix(context)
+#         if dup._isinfinity():
+#             return dup
+
+#         if not dup:
+#             return Decimal( (dup._sign, (0,), 0) )
+#         end = len(dup._int)
+#         exp = dup._exp
+#         while dup._int[end-1] == 0:
+#             exp += 1
+#             end -= 1
+#         return Decimal( (dup._sign, dup._int[:end], exp) )
 
-    def quantize(self, exp, rounding=None, context=None, watchexp=1):
-        """Quantize self so its exponent is the same as that of exp.
 
-        Similar to self._rescale(exp._exp) but with error checking.
-        """
-        if self._is_special or exp._is_special:
-            ans = self._check_nans(exp, context)
-            if ans:
-                return ans
+#     def quantize(self, exp, rounding=-1, context=None, watchexp=1):
+#         """Quantize self so its exponent is the same as that of exp.
 
-            if exp._isinfinity() or self._isinfinity():
-                if exp._isinfinity() and self._isinfinity():
-                    return self  #if both are inf, it is OK
-                if context is None:
-                    context = getcontext()
-                return context._raise_error(InvalidOperation,
-                                        'quantize with one INF')
-        return self._rescale(exp._exp, rounding, context, watchexp)
+#         Similar to self._rescale(exp._exp) but with error checking.
+#         """
+#         if self._is_special or exp._is_special:
+#             ans = self._check_nans(exp, context)
+#             if ans:
+#                 return ans
+
+#             if exp._isinfinity() or self._isinfinity():
+#                 if exp._isinfinity() and self._isinfinity():
+#                     return self  #if both are inf, it is OK
+#                 if context is None:
+#                     context = getcontext()
+#                 return context._raise_error(InvalidOperation,
+#                                         'quantize with one INF')
+#         return self._rescale(exp._exp, rounding, context, watchexp)
 
-    def same_quantum(self, other):
-        """Test whether self and other have the same exponent.
+#     def same_quantum(self, other):
+#         """Test whether self and other have the same exponent.
 
-        same as self._exp == other._exp, except NaN == sNaN
-        """
-        if self._is_special or other._is_special:
-            if self._isnan() or other._isnan():
-                return self._isnan() and other._isnan() and True
-            if self._isinfinity() or other._isinfinity():
-                return self._isinfinity() and other._isinfinity() and True
-        return self._exp == other._exp
+#         same as self._exp == other._exp, except NaN == sNaN
+#         """
+#         if self._is_special or other._is_special:
+#             if self._isnan() or other._isnan():
+#                 return self._isnan() and other._isnan() and True
+#             if self._isinfinity() or other._isinfinity():
+#                 return self._isinfinity() and other._isinfinity() and True
+#         return self._exp == other._exp
 
-    def _rescale(self, exp, rounding=None, context=None, watchexp=1):
+    def _rescale(self, exp, rounding=-1, context=None, watchexp=1):
         """Rescales so that the exponent is exp.
 
         exp = exp to scale to (an integer)
@@ -1810,7 +1465,7 @@
             tmp._exp = -digits + tmp._exp
             tmp._int = (0,1)
             digits = 1
-        tmp = tmp._round(digits, rounding, context=context)
+        tmp = tmp._round(digits, rounding, context)
 
         if tmp._int[0] == 0 and len(tmp._int) > 1:
             tmp._int = tmp._int[1:]
@@ -1823,20 +1478,20 @@
             return context._raise_error(InvalidOperation, 'rescale(a, INF)')
         return tmp
 
-    def to_integral(self, rounding=None, context=None):
-        """Rounds to the nearest integer, without raising inexact, rounded."""
-        if self._is_special:
-            ans = self._check_nans(context=context)
-            if ans:
-                return ans
-        if self._exp >= 0:
-            return self
-        if context is None:
-            context = getcontext()
-        flags = context._ignore_flags(Rounded, Inexact)
-        ans = self._rescale(0, rounding, context=context)
-        context._regard_flags(flags)
-        return ans
+    #def to_integral(self, rounding=None, context=None):
+    #    """Rounds to the nearest integer, without raising inexact, rounded."""
+    #    if self._is_special:
+    #        ans = self._check_nans(context=context)
+    #        if ans:
+    #            return ans
+    #    if self._exp >= 0:
+    #        return self
+    #    if context is None:
+    #        context = getcontext()
+    #    flags = context._ignore_flags(Rounded, Inexact)
+    #    ans = self._rescale(0, rounding, context=context)
+    #    context._regard_flags(flags)
+    #    return ans
 
     def sqrt(self, context=None):
         """Return the square root of self.
@@ -2071,40 +1726,28 @@
             return 1
         return self._int[-1+self._exp] & 1 == 0
 
-    def adjusted(self):
-        """Return the adjusted exponent of self"""
-        try:
-            return self._exp + len(self._int) - 1
-        #If NaN or Infinity, self._exp is string
-        except TypeError:
-            return 0
+#     def adjusted(self):
+#         """Return the adjusted exponent of self"""
+#         try:
+#             return self._exp + len(self._int) - 1
+#         #If NaN or Infinity, self._exp is string
+#         except TypeError:
+#             return 0
 
-    # support for pickling, copy, and deepcopy
-    def __reduce__(self):
-        return (self.__class__, (str(self),))
-
-    def __copy__(self):
-        if type(self) == Decimal:
-            return self     # I'm immutable; therefore I am my own clone
-        return self.__class__(str(self))
-
-    def __deepcopy__(self, memo):
-        if type(self) == Decimal:
-            return self     # My components are also immutable
-        return self.__class__(str(self))
 
 ##### Context class ###########################################
 
+from _decimal import Context
 
-# get rounding method function:
-rounding_functions = [name for name in Decimal.__dict__.keys() if name.startswith('_round_')]
-for name in rounding_functions:
-    #name is like _round_half_even, goes to the global ROUND_HALF_EVEN value.
-    globalname = name[1:].upper()
-    val = globals()[globalname]
-    Decimal._pick_rounding_function[val] = name
+# # get rounding method function:
+# rounding_functions = [name for name in Decimal.__dict__.keys() if name.startswith('_round_')]
+# for name in rounding_functions:
+#     #name is like _round_half_even, goes to the global ROUND_HALF_EVEN value.
+#     globalname = name[1:].upper()
+#     val = globals()[globalname]
+#     Decimal._pick_rounding_function[val] = name
 
-del name, val, globalname, rounding_functions
+# del name, val, globalname, rounding_functions
 
 class ContextManager(object):
     """Helper class to simplify Context management.
@@ -2130,504 +1773,6 @@
     def __exit__(self, t, v, tb):
         setcontext(self.saved_context)
 
-class Context(_decimal.Context):
-    """Contains the context for a Decimal instance.
-
-    Contains:
-    prec - precision (for use in rounding, division, square roots..)
-    rounding - rounding type. (how you round)
-    _rounding_decision - ALWAYS_ROUND, NEVER_ROUND -- do you round?
-    traps - If traps[exception] = 1, then the exception is
-                    raised when it is caused.  Otherwise, a value is
-                    substituted in.
-    flags  - When an exception is caused, flags[exception] is incremented.
-             (Whether or not the trap_enabler is set)
-             Should be reset by user of Decimal instance.
-    Emin -   Minimum exponent
-    Emax -   Maximum exponent
-    capitals -      If 1, 1*10^1 is printed as 1E+1.
-                    If 0, printed as 1e1
-    _clamp - If 1, change exponents if too high (Default 0)
-    """
-
-    def __repr__(self):
-        """Show the current context."""
-        s = []
-        s.append('Context(prec=%(prec)d, rounding=%(rounding)s, Emin=%(Emin)d, Emax=%(Emax)d, capitals=%(capitals)d' % vars(self))
-        s.append('flags=[' + ', '.join([f.__name__ for f, v in self.flags.items() if v]) + ']')
-        s.append('traps=[' + ', '.join([t.__name__ for t, v in self.traps.items() if v]) + ']')
-        return ', '.join(s) + ')'
-
-    def create_decimal(self, num='0'):
-        """Creates a new Decimal instance but using self as context."""
-        d = Decimal(num, context=self)
-        return d._fix(self)
-
-    #Methods
-    def abs(self, a):
-        """Returns the absolute value of the operand.
-
-        If the operand is negative, the result is the same as using the minus
-        operation on the operand. Otherwise, the result is the same as using
-        the plus operation on the operand.
-
-        >>> ExtendedContext.abs(Decimal('2.1'))
-        Decimal("2.1")
-        >>> ExtendedContext.abs(Decimal('-100'))
-        Decimal("100")
-        >>> ExtendedContext.abs(Decimal('101.5'))
-        Decimal("101.5")
-        >>> ExtendedContext.abs(Decimal('-101.5'))
-        Decimal("101.5")
-        """
-        return a.__abs__(context=self)
-
-    def add(self, a, b):
-        """Return the sum of the two operands.
-
-        >>> ExtendedContext.add(Decimal('12'), Decimal('7.00'))
-        Decimal("19.00")
-        >>> ExtendedContext.add(Decimal('1E+2'), Decimal('1.01E+4'))
-        Decimal("1.02E+4")
-        """
-        return a.__add__(b, context=self)
-
-    def _apply(self, a):
-        return str(a._fix(self))
-
-    def compare(self, a, b):
-        """Compares values numerically.
-
-        If the signs of the operands differ, a value representing each operand
-        ('-1' if the operand is less than zero, '0' if the operand is zero or
-        negative zero, or '1' if the operand is greater than zero) is used in
-        place of that operand for the comparison instead of the actual
-        operand.
-
-        The comparison is then effected by subtracting the second operand from
-        the first and then returning a value according to the result of the
-        subtraction: '-1' if the result is less than zero, '0' if the result is
-        zero or negative zero, or '1' if the result is greater than zero.
-
-        >>> ExtendedContext.compare(Decimal('2.1'), Decimal('3'))
-        Decimal("-1")
-        >>> ExtendedContext.compare(Decimal('2.1'), Decimal('2.1'))
-        Decimal("0")
-        >>> ExtendedContext.compare(Decimal('2.1'), Decimal('2.10'))
-        Decimal("0")
-        >>> ExtendedContext.compare(Decimal('3'), Decimal('2.1'))
-        Decimal("1")
-        >>> ExtendedContext.compare(Decimal('2.1'), Decimal('-3'))
-        Decimal("1")
-        >>> ExtendedContext.compare(Decimal('-3'), Decimal('2.1'))
-        Decimal("-1")
-        """
-        return a.compare(b, context=self)
-
-    def divide(self, a, b):
-        """Decimal division in a specified context.
-
-        >>> ExtendedContext.divide(Decimal('1'), Decimal('3'))
-        Decimal("0.333333333")
-        >>> ExtendedContext.divide(Decimal('2'), Decimal('3'))
-        Decimal("0.666666667")
-        >>> ExtendedContext.divide(Decimal('5'), Decimal('2'))
-        Decimal("2.5")
-        >>> ExtendedContext.divide(Decimal('1'), Decimal('10'))
-        Decimal("0.1")
-        >>> ExtendedContext.divide(Decimal('12'), Decimal('12'))
-        Decimal("1")
-        >>> ExtendedContext.divide(Decimal('8.00'), Decimal('2'))
-        Decimal("4.00")
-        >>> ExtendedContext.divide(Decimal('2.400'), Decimal('2.0'))
-        Decimal("1.20")
-        >>> ExtendedContext.divide(Decimal('1000'), Decimal('100'))
-        Decimal("10")
-        >>> ExtendedContext.divide(Decimal('1000'), Decimal('1'))
-        Decimal("1000")
-        >>> ExtendedContext.divide(Decimal('2.40E+6'), Decimal('2'))
-        Decimal("1.20E+6")
-        """
-        return a.__div__(b, context=self)
-
-    def divide_int(self, a, b):
-        """Divides two numbers and returns the integer part of the result.
-
-        >>> ExtendedContext.divide_int(Decimal('2'), Decimal('3'))
-        Decimal("0")
-        >>> ExtendedContext.divide_int(Decimal('10'), Decimal('3'))
-        Decimal("3")
-        >>> ExtendedContext.divide_int(Decimal('1'), Decimal('0.3'))
-        Decimal("3")
-        """
-        return a.__floordiv__(b, context=self)
-
-    def divmod(self, a, b):
-        return a.__divmod__(b, context=self)
-
-    def max(self, a,b):
-        """max compares two values numerically and returns the maximum.
-
-        If either operand is a NaN then the general rules apply.
-        Otherwise, the operands are compared as as though by the compare
-        operation. If they are numerically equal then the left-hand operand
-        is chosen as the result. Otherwise the maximum (closer to positive
-        infinity) of the two operands is chosen as the result.
-
-        >>> ExtendedContext.max(Decimal('3'), Decimal('2'))
-        Decimal("3")
-        >>> ExtendedContext.max(Decimal('-10'), Decimal('3'))
-        Decimal("3")
-        >>> ExtendedContext.max(Decimal('1.0'), Decimal('1'))
-        Decimal("1")
-        >>> ExtendedContext.max(Decimal('7'), Decimal('NaN'))
-        Decimal("7")
-        """
-        return a.max(b, context=self)
-
-    def min(self, a,b):
-        """min compares two values numerically and returns the minimum.
-
-        If either operand is a NaN then the general rules apply.
-        Otherwise, the operands are compared as as though by the compare
-        operation. If they are numerically equal then the left-hand operand
-        is chosen as the result. Otherwise the minimum (closer to negative
-        infinity) of the two operands is chosen as the result.
-
-        >>> ExtendedContext.min(Decimal('3'), Decimal('2'))
-        Decimal("2")
-        >>> ExtendedContext.min(Decimal('-10'), Decimal('3'))
-        Decimal("-10")
-        >>> ExtendedContext.min(Decimal('1.0'), Decimal('1'))
-        Decimal("1.0")
-        >>> ExtendedContext.min(Decimal('7'), Decimal('NaN'))
-        Decimal("7")
-        """
-        return a.min(b, context=self)
-
-    def minus(self, a):
-        """Minus corresponds to unary prefix minus in Python.
-
-        The operation is evaluated using the same rules as subtract; the
-        operation minus(a) is calculated as subtract('0', a) where the '0'
-        has the same exponent as the operand.
-
-        >>> ExtendedContext.minus(Decimal('1.3'))
-        Decimal("-1.3")
-        >>> ExtendedContext.minus(Decimal('-1.3'))
-        Decimal("1.3")
-        """
-        return a.__neg__(context=self)
-
-    def multiply(self, a, b):
-        """multiply multiplies two operands.
-
-        If either operand is a special value then the general rules apply.
-        Otherwise, the operands are multiplied together ('long multiplication'),
-        resulting in a number which may be as long as the sum of the lengths
-        of the two operands.
-
-        >>> ExtendedContext.multiply(Decimal('1.20'), Decimal('3'))
-        Decimal("3.60")
-        >>> ExtendedContext.multiply(Decimal('7'), Decimal('3'))
-        Decimal("21")
-        >>> ExtendedContext.multiply(Decimal('0.9'), Decimal('0.8'))
-        Decimal("0.72")
-        >>> ExtendedContext.multiply(Decimal('0.9'), Decimal('-0'))
-        Decimal("-0.0")
-        >>> ExtendedContext.multiply(Decimal('654321'), Decimal('654321'))
-        Decimal("4.28135971E+11")
-        """
-        return a.__mul__(b, context=self)
-
-    def normalize(self, a):
-        """normalize reduces an operand to its simplest form.
-
-        Essentially a plus operation with all trailing zeros removed from the
-        result.
-
-        >>> ExtendedContext.normalize(Decimal('2.1'))
-        Decimal("2.1")
-        >>> ExtendedContext.normalize(Decimal('-2.0'))
-        Decimal("-2")
-        >>> ExtendedContext.normalize(Decimal('1.200'))
-        Decimal("1.2")
-        >>> ExtendedContext.normalize(Decimal('-120'))
-        Decimal("-1.2E+2")
-        >>> ExtendedContext.normalize(Decimal('120.00'))
-        Decimal("1.2E+2")
-        >>> ExtendedContext.normalize(Decimal('0.00'))
-        Decimal("0")
-        """
-        return a.normalize(context=self)
-
-    def plus(self, a):
-        """Plus corresponds to unary prefix plus in Python.
-
-        The operation is evaluated using the same rules as add; the
-        operation plus(a) is calculated as add('0', a) where the '0'
-        has the same exponent as the operand.
-
-        >>> ExtendedContext.plus(Decimal('1.3'))
-        Decimal("1.3")
-        >>> ExtendedContext.plus(Decimal('-1.3'))
-        Decimal("-1.3")
-        """
-        return a.__pos__(context=self)
-
-    def power(self, a, b, modulo=None):
-        """Raises a to the power of b, to modulo if given.
-
-        The right-hand operand must be a whole number whose integer part (after
-        any exponent has been applied) has no more than 9 digits and whose
-        fractional part (if any) is all zeros before any rounding. The operand
-        may be positive, negative, or zero; if negative, the absolute value of
-        the power is used, and the left-hand operand is inverted (divided into
-        1) before use.
-
-        If the increased precision needed for the intermediate calculations
-        exceeds the capabilities of the implementation then an Invalid operation
-        condition is raised.
-
-        If, when raising to a negative power, an underflow occurs during the
-        division into 1, the operation is not halted at that point but
-        continues.
-
-        >>> ExtendedContext.power(Decimal('2'), Decimal('3'))
-        Decimal("8")
-        >>> ExtendedContext.power(Decimal('2'), Decimal('-3'))
-        Decimal("0.125")
-        >>> ExtendedContext.power(Decimal('1.7'), Decimal('8'))
-        Decimal("69.7575744")
-        >>> ExtendedContext.power(Decimal('Infinity'), Decimal('-2'))
-        Decimal("0")
-        >>> ExtendedContext.power(Decimal('Infinity'), Decimal('-1'))
-        Decimal("0")
-        >>> ExtendedContext.power(Decimal('Infinity'), Decimal('0'))
-        Decimal("1")
-        >>> ExtendedContext.power(Decimal('Infinity'), Decimal('1'))
-        Decimal("Infinity")
-        >>> ExtendedContext.power(Decimal('Infinity'), Decimal('2'))
-        Decimal("Infinity")
-        >>> ExtendedContext.power(Decimal('-Infinity'), Decimal('-2'))
-        Decimal("0")
-        >>> ExtendedContext.power(Decimal('-Infinity'), Decimal('-1'))
-        Decimal("-0")
-        >>> ExtendedContext.power(Decimal('-Infinity'), Decimal('0'))
-        Decimal("1")
-        >>> ExtendedContext.power(Decimal('-Infinity'), Decimal('1'))
-        Decimal("-Infinity")
-        >>> ExtendedContext.power(Decimal('-Infinity'), Decimal('2'))
-        Decimal("Infinity")
-        >>> ExtendedContext.power(Decimal('0'), Decimal('0'))
-        Decimal("NaN")
-        """
-        return a.__pow__(b, modulo, context=self)
-
-    def quantize(self, a, b):
-        """Returns a value equal to 'a' (rounded) and having the exponent of 'b'.
-
-        The coefficient of the result is derived from that of the left-hand
-        operand. It may be rounded using the current rounding setting (if the
-        exponent is being increased), multiplied by a positive power of ten (if
-        the exponent is being decreased), or is unchanged (if the exponent is
-        already equal to that of the right-hand operand).
-
-        Unlike other operations, if the length of the coefficient after the
-        quantize operation would be greater than precision then an Invalid
-        operation condition is raised. This guarantees that, unless there is an
-        error condition, the exponent of the result of a quantize is always
-        equal to that of the right-hand operand.
-
-        Also unlike other operations, quantize will never raise Underflow, even
-        if the result is subnormal and inexact.
-
-        >>> ExtendedContext.quantize(Decimal('2.17'), Decimal('0.001'))
-        Decimal("2.170")
-        >>> ExtendedContext.quantize(Decimal('2.17'), Decimal('0.01'))
-        Decimal("2.17")
-        >>> ExtendedContext.quantize(Decimal('2.17'), Decimal('0.1'))
-        Decimal("2.2")
-        >>> ExtendedContext.quantize(Decimal('2.17'), Decimal('1e+0'))
-        Decimal("2")
-        >>> ExtendedContext.quantize(Decimal('2.17'), Decimal('1e+1'))
-        Decimal("0E+1")
-        >>> ExtendedContext.quantize(Decimal('-Inf'), Decimal('Infinity'))
-        Decimal("-Infinity")
-        >>> ExtendedContext.quantize(Decimal('2'), Decimal('Infinity'))
-        Decimal("NaN")
-        >>> ExtendedContext.quantize(Decimal('-0.1'), Decimal('1'))
-        Decimal("-0")
-        >>> ExtendedContext.quantize(Decimal('-0'), Decimal('1e+5'))
-        Decimal("-0E+5")
-        >>> ExtendedContext.quantize(Decimal('+35236450.6'), Decimal('1e-2'))
-        Decimal("NaN")
-        >>> ExtendedContext.quantize(Decimal('-35236450.6'), Decimal('1e-2'))
-        Decimal("NaN")
-        >>> ExtendedContext.quantize(Decimal('217'), Decimal('1e-1'))
-        Decimal("217.0")
-        >>> ExtendedContext.quantize(Decimal('217'), Decimal('1e-0'))
-        Decimal("217")
-        >>> ExtendedContext.quantize(Decimal('217'), Decimal('1e+1'))
-        Decimal("2.2E+2")
-        >>> ExtendedContext.quantize(Decimal('217'), Decimal('1e+2'))
-        Decimal("2E+2")
-        """
-        return a.quantize(b, context=self)
-
-    def remainder(self, a, b):
-        """Returns the remainder from integer division.
-
-        The result is the residue of the dividend after the operation of
-        calculating integer division as described for divide-integer, rounded to
-        precision digits if necessary. The sign of the result, if non-zero, is
-        the same as that of the original dividend.
-
-        This operation will fail under the same conditions as integer division
-        (that is, if integer division on the same two operands would fail, the
-        remainder cannot be calculated).
-
-        >>> ExtendedContext.remainder(Decimal('2.1'), Decimal('3'))
-        Decimal("2.1")
-        >>> ExtendedContext.remainder(Decimal('10'), Decimal('3'))
-        Decimal("1")
-        >>> ExtendedContext.remainder(Decimal('-10'), Decimal('3'))
-        Decimal("-1")
-        >>> ExtendedContext.remainder(Decimal('10.2'), Decimal('1'))
-        Decimal("0.2")
-        >>> ExtendedContext.remainder(Decimal('10'), Decimal('0.3'))
-        Decimal("0.1")
-        >>> ExtendedContext.remainder(Decimal('3.6'), Decimal('1.3'))
-        Decimal("1.0")
-        """
-        return a.__mod__(b, context=self)
-
-    def remainder_near(self, a, b):
-        """Returns to be "a - b * n", where n is the integer nearest the exact
-        value of "x / b" (if two integers are equally near then the even one
-        is chosen). If the result is equal to 0 then its sign will be the
-        sign of a.
-
-        This operation will fail under the same conditions as integer division
-        (that is, if integer division on the same two operands would fail, the
-        remainder cannot be calculated).
-
-        >>> ExtendedContext.remainder_near(Decimal('2.1'), Decimal('3'))
-        Decimal("-0.9")
-        >>> ExtendedContext.remainder_near(Decimal('10'), Decimal('6'))
-        Decimal("-2")
-        >>> ExtendedContext.remainder_near(Decimal('10'), Decimal('3'))
-        Decimal("1")
-        >>> ExtendedContext.remainder_near(Decimal('-10'), Decimal('3'))
-        Decimal("-1")
-        >>> ExtendedContext.remainder_near(Decimal('10.2'), Decimal('1'))
-        Decimal("0.2")
-        >>> ExtendedContext.remainder_near(Decimal('10'), Decimal('0.3'))
-        Decimal("0.1")
-        >>> ExtendedContext.remainder_near(Decimal('3.6'), Decimal('1.3'))
-        Decimal("-0.3")
-        """
-        return a.remainder_near(b, context=self)
-
-    def same_quantum(self, a, b):
-        """Returns True if the two operands have the same exponent.
-
-        The result is never affected by either the sign or the coefficient of
-        either operand.
-
-        >>> ExtendedContext.same_quantum(Decimal('2.17'), Decimal('0.001'))
-        False
-        >>> ExtendedContext.same_quantum(Decimal('2.17'), Decimal('0.01'))
-        True
-        >>> ExtendedContext.same_quantum(Decimal('2.17'), Decimal('1'))
-        False
-        >>> ExtendedContext.same_quantum(Decimal('Inf'), Decimal('-Inf'))
-        True
-        """
-        return a.same_quantum(b)
-
-    def sqrt(self, a):
-        """Returns the square root of a non-negative number to context precision.
-
-        If the result must be inexact, it is rounded using the round-half-even
-        algorithm.
-
-        >>> ExtendedContext.sqrt(Decimal('0'))
-        Decimal("0")
-        >>> ExtendedContext.sqrt(Decimal('-0'))
-        Decimal("-0")
-        >>> ExtendedContext.sqrt(Decimal('0.39'))
-        Decimal("0.624499800")
-        >>> ExtendedContext.sqrt(Decimal('100'))
-        Decimal("10")
-        >>> ExtendedContext.sqrt(Decimal('1'))
-        Decimal("1")
-        >>> ExtendedContext.sqrt(Decimal('1.0'))
-        Decimal("1.0")
-        >>> ExtendedContext.sqrt(Decimal('1.00'))
-        Decimal("1.0")
-        >>> ExtendedContext.sqrt(Decimal('7'))
-        Decimal("2.64575131")
-        >>> ExtendedContext.sqrt(Decimal('10'))
-        Decimal("3.16227766")
-        >>> ExtendedContext.prec
-        9
-        """
-        return a.sqrt(context=self)
-
-    def subtract(self, a, b):
-        """Return the difference between the two operands.
-
-        >>> ExtendedContext.subtract(Decimal('1.3'), Decimal('1.07'))
-        Decimal("0.23")
-        >>> ExtendedContext.subtract(Decimal('1.3'), Decimal('1.30'))
-        Decimal("0.00")
-        >>> ExtendedContext.subtract(Decimal('1.3'), Decimal('2.07'))
-        Decimal("-0.77")
-        """
-        return a.__sub__(b, context=self)
-
-    def to_eng_string(self, a):
-        """Converts a number to a string, using scientific notation.
-
-        The operation is not affected by the context.
-        """
-        return a.to_eng_string(context=self)
-
-    def to_sci_string(self, a):
-        """Converts a number to a string, using scientific notation.
-
-        The operation is not affected by the context.
-        """
-        return a.__str__(context=self)
-
-    def to_integral(self, a):
-        """Rounds to an integer.
-
-        When the operand has a negative exponent, the result is the same
-        as using the quantize() operation using the given operand as the
-        left-hand-operand, 1E+0 as the right-hand-operand, and the precision
-        of the operand as the precision setting, except that no flags will
-        be set. The rounding mode is taken from the context.
-
-        >>> ExtendedContext.to_integral(Decimal('2.1'))
-        Decimal("2")
-        >>> ExtendedContext.to_integral(Decimal('100'))
-        Decimal("100")
-        >>> ExtendedContext.to_integral(Decimal('100.0'))
-        Decimal("100")
-        >>> ExtendedContext.to_integral(Decimal('101.5'))
-        Decimal("102")
-        >>> ExtendedContext.to_integral(Decimal('-101.5'))
-        Decimal("-102")
-        >>> ExtendedContext.to_integral(Decimal('10E+5'))
-        Decimal("1.0E+6")
-        >>> ExtendedContext.to_integral(Decimal('7.89E+77'))
-        Decimal("7.89E+77")
-        >>> ExtendedContext.to_integral(Decimal('-Inf'))
-        Decimal("-Infinity")
-        """
-        return a.to_integral(context=self)
 
 from _decimal import BasicContext, ExtendedContext, \
      DefaultContext
@@ -2662,7 +1807,6 @@
     __str__ = __repr__
 
 
-
 def _normalize(op1, op2, shouldround = 0, prec = 0):
     """Normalizes op1, op2 to have the same exp and length of coefficient.
 
@@ -2783,125 +1927,3 @@
         return (2, sign, num[4:].lstrip('0'))
     return 0
 
-
-# ##### Setup Specific Contexts ################################
-
-# # The default context prototype used by Context()
-# # Is mutable, so that new contexts can have different default values
-
-# DefaultContext = Context(
-#         prec=28, rounding=ROUND_HALF_EVEN,
-#         traps=[DivisionByZero, Overflow, InvalidOperation],
-#         flags=[],
-#         _rounding_decision=ALWAYS_ROUND,
-#         Emax=999999999,
-#         Emin=-999999999,
-#         capitals=1
-# )
-
-# # Pre-made alternate contexts offered by the specification
-# # Don't change these; the user should be able to select these
-# # contexts and be able to reproduce results from other implementations
-# # of the spec.
-
-# BasicContext = Context(
-#         prec=9, rounding=ROUND_HALF_UP,
-#         traps=[DivisionByZero, Overflow, InvalidOperation, Clamped, Underflow],
-#         flags=[],
-# )
-
-# ExtendedContext = Context(
-#         prec=9, rounding=ROUND_HALF_EVEN,
-#         traps=[],
-#         flags=[],
-# )
-
-
-# ##### Useful Constants (internal use only) ####################
-
-from _decimal import Inf, negInf, NaN
-
-# #Reusable defaults
-# Inf = Decimal('Inf')
-# negInf = Decimal('-Inf')
-
-# #Infsign[sign] is infinity w/ that sign
-Infsign = (Inf, negInf)
-
-# NaN = Decimal('NaN')
-
-
-
-
-# ##### crud for parsing strings #################################
-# import re
-
-# # There's an optional sign at the start, and an optional exponent
-# # at the end.  The exponent has an optional sign and at least one
-# # digit.  In between, must have either at least one digit followed
-# # by an optional fraction, or a decimal point followed by at least
-# # one digit.  Yuck.
-
-# _parser = re.compile(r"""
-# #    \s*
-#     (?P<sign>[-+])?
-#     (
-#         (?P<int>\d+) (\. (?P<frac>\d*))?
-#     |
-#         \. (?P<onlyfrac>\d+)
-#     )
-#     ([eE](?P<exp>[-+]? \d+))?
-# #    \s*
-#     $
-# """, re.VERBOSE).match #Uncomment the \s* to allow leading or trailing spaces.
-
-# del re
-
-# # return sign, n, p s.t. float string value == -1**sign * n * 10**p exactly
-
-# def _string2exact(s):
-#     m = _parser(s)
-#     if m is None:
-#         raise ValueError("invalid literal for Decimal: %r" % s)
-
-#     if m.group('sign') == "-":
-#         sign = 1
-#     else:
-#         sign = 0
-
-#     exp = m.group('exp')
-#     if exp is None:
-#         exp = 0
-#     else:
-#         exp = int(exp)
-
-#     intpart = m.group('int')
-#     if intpart is None:
-#         intpart = ""
-#         fracpart = m.group('onlyfrac')
-#     else:
-#         fracpart = m.group('frac')
-#         if fracpart is None:
-#             fracpart = ""
-
-#     exp -= len(fracpart)
-
-#     mantissa = intpart + fracpart
-#     tmp = map(int, mantissa)
-#     backup = tmp
-#     while tmp and tmp[0] == 0:
-#         del tmp[0]
-
-#     # It's a zero
-#     if not tmp:
-#         if backup:
-#             return (sign, tuple(backup), exp)
-#         return (sign, (0,), exp)
-#     mantissa = tuple(tmp)
-
-#     return (sign, mantissa, exp)
-
-
-if __name__ == '__main__':
-    import doctest, sys
-    doctest.testmod(sys.modules[__name__])


More information about the Python-checkins mailing list