[Python-checkins] r86318 - in python/branches/py3k-cdecimal/Modules/cdecimal: bits.h cdecimal.c constants.h context.c convolute.c crt.c difradix2.c error.c fnt.c fnt.h fourstep.c fourstep.h io.c memory.c mpdecimal.c mpdecimal32.h mpdecimal64.h mpsignal.c mptest.h mptypes.h numbertheory.h sixstep.c sixstep.h transpose.c typearith.h umodarith.h vccompat.h vcdiv64.asm

stefan.krah python-checkins at python.org
Mon Nov 8 15:12:50 CET 2010


Author: stefan.krah
Date: Mon Nov  8 15:12:49 2010
New Revision: 86318

Log:
Sync cdecimal with the next version of mpdecimal (2.0):

  1) New hash function and float operations.

  2) Implement FloatOperation signal to detect accidental float operations.

  3) New tests have 100% code coverage for the library and 85% for the module.



Added:
   python/branches/py3k-cdecimal/Modules/cdecimal/mpsignal.c   (contents, props changed)
Modified:
   python/branches/py3k-cdecimal/Modules/cdecimal/bits.h
   python/branches/py3k-cdecimal/Modules/cdecimal/cdecimal.c
   python/branches/py3k-cdecimal/Modules/cdecimal/constants.h
   python/branches/py3k-cdecimal/Modules/cdecimal/context.c
   python/branches/py3k-cdecimal/Modules/cdecimal/convolute.c
   python/branches/py3k-cdecimal/Modules/cdecimal/crt.c
   python/branches/py3k-cdecimal/Modules/cdecimal/difradix2.c
   python/branches/py3k-cdecimal/Modules/cdecimal/error.c
   python/branches/py3k-cdecimal/Modules/cdecimal/fnt.c
   python/branches/py3k-cdecimal/Modules/cdecimal/fnt.h
   python/branches/py3k-cdecimal/Modules/cdecimal/fourstep.c
   python/branches/py3k-cdecimal/Modules/cdecimal/fourstep.h
   python/branches/py3k-cdecimal/Modules/cdecimal/io.c
   python/branches/py3k-cdecimal/Modules/cdecimal/memory.c
   python/branches/py3k-cdecimal/Modules/cdecimal/mpdecimal.c
   python/branches/py3k-cdecimal/Modules/cdecimal/mpdecimal32.h
   python/branches/py3k-cdecimal/Modules/cdecimal/mpdecimal64.h
   python/branches/py3k-cdecimal/Modules/cdecimal/mptest.h
   python/branches/py3k-cdecimal/Modules/cdecimal/mptypes.h
   python/branches/py3k-cdecimal/Modules/cdecimal/numbertheory.h
   python/branches/py3k-cdecimal/Modules/cdecimal/sixstep.c
   python/branches/py3k-cdecimal/Modules/cdecimal/sixstep.h
   python/branches/py3k-cdecimal/Modules/cdecimal/transpose.c
   python/branches/py3k-cdecimal/Modules/cdecimal/typearith.h
   python/branches/py3k-cdecimal/Modules/cdecimal/umodarith.h
   python/branches/py3k-cdecimal/Modules/cdecimal/vccompat.h
   python/branches/py3k-cdecimal/Modules/cdecimal/vcdiv64.asm

Modified: python/branches/py3k-cdecimal/Modules/cdecimal/bits.h
==============================================================================
--- python/branches/py3k-cdecimal/Modules/cdecimal/bits.h	(original)
+++ python/branches/py3k-cdecimal/Modules/cdecimal/bits.h	Mon Nov  8 15:12:49 2010
@@ -19,12 +19,13 @@
 	return n != 0 && (n & (n-1)) == 0;
 }
 
+#if defined(ANSI)
 /*
  * Returns the most significant bit position of n from 0 to 32 (64).
  * Caller has to make sure that n is not 0.
  */
 static inline int
-std_bsr(mpd_size_t n)
+mpd_bsr(mpd_size_t n)
 {
 	int pos = 0;
 	mpd_size_t tmp;
@@ -47,13 +48,12 @@
 	return pos + (int)n - 1;
 }
 
-
 /*
  * Returns the least significant bit position of n from 0 to 32 (64).
  * Caller has to make sure that n is not 0.
  */
 static inline int
-std_bsf(mpd_size_t n)
+mpd_bsf(mpd_size_t n)
 {
 	int pos;
 
@@ -75,15 +75,15 @@
 #endif
 	return pos;
 }
+/* END ANSI */
 
-
-#if defined(__GNUC__) && (defined(__x86_64__) || defined(__i386__))
+#elif defined(ASM)
 /*
  * Bit scan reverse.
  * Caller has to make sure that a is not 0.
  */
 static inline int
-x86_bsr(mpd_size_t a) 
+mpd_bsr(mpd_size_t a) 
 {
 	mpd_size_t retval;
 
@@ -106,7 +106,7 @@
  * Caller has to make sure that a is not 0.
  */
 static inline int
-x86_bsf(mpd_size_t a) 
+mpd_bsf(mpd_size_t a) 
 {
 	mpd_size_t retval;
 
@@ -123,17 +123,16 @@
 
 	return (int)retval;
 }
-#endif /* __GNUC__ (amd64|i386) */
+/* END ASM */
 
-
-#ifdef _MSC_VER
+#elif defined(MASM)
 #include <intrin.h>
 /*
  * Bit scan reverse.
  * Caller has to make sure that a is not 0.
  */
 static inline int __cdecl
-x86_bsr(mpd_size_t a) 
+mpd_bsr(mpd_size_t a) 
 {
 	unsigned long retval;
 
@@ -151,7 +150,7 @@
  * Caller has to make sure that a is not 0.
  */
 static inline int __cdecl
-x86_bsf(mpd_size_t a) 
+mpd_bsf(mpd_size_t a) 
 {
 	unsigned long retval;
 
@@ -163,7 +162,10 @@
 
 	return (int)retval;
 }
-#endif /* _MSC_VER */
+/* END MASM (_MSC_VER) */
+#else
+  #error "missing preprocessor definitions"
+#endif /* BSR/BSF */
 
 
 #endif /* BITS_H */

Modified: python/branches/py3k-cdecimal/Modules/cdecimal/cdecimal.c
==============================================================================
--- python/branches/py3k-cdecimal/Modules/cdecimal/cdecimal.c	(original)
+++ python/branches/py3k-cdecimal/Modules/cdecimal/cdecimal.c	Mon Nov  8 15:12:49 2010
@@ -17,6 +17,10 @@
 #include "mptypes.h"
 
 
+#if PY_VERSION_HEX < 0x03000000
+  #error "Python versions < 3.0 not supported."
+#endif
+
 #if defined(_MSC_VER) && defined (CONFIG_64)
   #define _PyLong_AsMpdSsize PyLong_AsLongLong
   #define _PyLong_FromMpdSsize PyLong_FromSsize_t
@@ -25,14 +29,13 @@
   #define _PyLong_FromMpdSsize PyLong_FromLong
 #endif
 
-
-#if PY_VERSION_HEX < 0x03000000
-  #error "Python versions < 3.0 not supported"
-#endif
-
 #define Dec_INCREF_TRUE (Py_INCREF(Py_True), Py_True)
 #define Dec_INCREF_FALSE (Py_INCREF(Py_False), Py_False)
 
+#define MPD_Float_operation MPD_Not_implemented
+
+#define BOUNDS_CHECK(x, MIN, MAX) x = (x < MIN || MAX < x) ? MAX : x
+
 
 typedef struct {
 	PyObject_HEAD
@@ -103,6 +106,7 @@
 /* Exceptions that correspond to IEEE signals; inherit from DecimalException */
 static DecCondMap signal_map[] = {
   {"InvalidOperation", "cdecimal.InvalidOperation", MPD_IEEE_Invalid_operation, NULL},
+  {"FloatOperation", "cdecimal.FloatOperation", MPD_Float_operation, NULL},
   {"DivisionByZero", "cdecimal.DivisionByZero", MPD_Division_by_zero, NULL},
   {"Overflow", "cdecimal.Overflow", MPD_Overflow, NULL},
   {"Underflow", "cdecimal.Underflow", MPD_Underflow, NULL},
@@ -136,16 +140,70 @@
 	"InvalidOperation",
 	"InvalidOperation",
 	"InvalidOperation",
-	"NotImplemented",
+	"FloatOperation",
 	"Overflow",
 	"Rounded",
 	"Subnormal",
 	"Underflow",
 };
 
-static void
-dec_traphandler(mpd_context_t *ctx UNUSED)
+static const char *invalid_rounding_err =
+"valid values for rounding are:\n\
+  [ROUND_CEILING, ROUND_FLOOR, ROUND_UP, ROUND_DOWN,\n\
+   ROUND_HALF_UP, ROUND_HALF_DOWN, ROUND_HALF_EVEN,\n\
+   ROUND_05UP].";
+
+static const char *invalid_signals_err =
+"valid values for signals are:\n\
+  [InvalidOperation, FloatOperation, DivisionByZero,\n\
+   Overflow, Underflow, Subnormal, Inexact, Rounded,\n\
+   Clamped].";
+
+static const char *invalid_flags_err =
+"valid values for _flags or _traps are:\n\
+  signals:\n\
+    [DecIEEEInvalidOperation, DecFloatOperation, DecDivisionByZero,\n\
+     DecOverflow, DecUnderflow, DecSubnormal, DecInexact, DecRounded,\n\
+     DecClamped]\n\
+  conditions which trigger DecIEEEInvalidOperation:\n\
+    [DecInvalidOperation, DecConversionSyntax, DecDivisionImpossible,\n\
+     DecDivisionUndefined, DecFpuError, DecInvalidContext, DecMallocError]";
+
+static int
+value_error_int(const char *mesg)
+{
+	PyErr_SetString(PyExc_ValueError, mesg);
+	return -1;
+}
+
+static PyObject *
+value_error_ptr(const char *mesg)
 {
+	PyErr_SetString(PyExc_ValueError, mesg);
+	return NULL;
+}
+
+static int
+runtime_error_int(const char *mesg)
+{ /* GCOV_NOT_REACHED */
+	PyErr_SetString(PyExc_RuntimeError, mesg); /* GCOV_NOT_REACHED */
+	return -1; /* GCOV_NOT_REACHED */
+}
+#define INTERNAL_ERROR_INT(funcname) \
+    return runtime_error_int("internal error in " funcname ".")
+
+static PyObject *
+runtime_error_ptr(const char *mesg)
+{ /* GCOV_NOT_REACHED */
+	PyErr_SetString(PyExc_RuntimeError, mesg); /* GCOV_NOT_REACHED */
+	return NULL; /* GCOV_NOT_REACHED */
+}
+#define INTERNAL_ERROR_PTR(funcname) \
+    return runtime_error_ptr("internal error in " funcname ".")
+
+static void
+dec_traphandler(mpd_context_t *ctx UNUSED) /* GCOV_NOT_REACHED */
+{ /* GCOV_NOT_REACHED */
 	return;
 }
 
@@ -160,8 +218,7 @@
 		}
 	}
 
-	PyErr_SetString(PyExc_ValueError, "invalid flag value");
-	return NULL;
+	INTERNAL_ERROR_PTR("flags_as_exception"); /* GCOV_NOT_REACHED */
 }
 
 static uint32_t
@@ -175,7 +232,7 @@
 		}
 	}
 
-	PyErr_SetString(PyExc_ValueError, "invalid signal value");
+	PyErr_SetString(PyExc_ValueError, invalid_signals_err);
 	return UINT32_MAX;
 }
 
@@ -186,21 +243,29 @@
 	DecCondMap *cm;
 
 	if ((list = PyList_New(0)) == NULL) {
-		return NULL;
+		return NULL; /* GCOV_UNLIKELY */
 	}
 
 	for (cm = cond_map; cm->name != NULL; cm++) {
 		if (flags&cm->mpd_cond) {
-			PyList_Append(list, cm->dec_cond);
+			if (PyList_Append(list, cm->dec_cond) < 0) {
+				goto error; /* GCOV_UNLIKELY */
+			}
 		}
 	}
 	for (cm = signal_map+1; cm->name != NULL; cm++) {
 		if (flags&cm->mpd_cond) {
-			PyList_Append(list, cm->dec_cond);
+			if (PyList_Append(list, cm->dec_cond) < 0) {
+				goto error; /* GCOV_UNLIKELY */
+			}
 		}
 	}
 
 	return list;
+
+error: /* GCOV_UNLIKELY */
+	Py_DECREF(list); /* GCOV_UNLIKELY */
+	return NULL; /* GCOV_UNLIKELY */
 }
 
 static uint32_t
@@ -211,7 +276,8 @@
 	ssize_t n, j;
 
 	if (!PyList_Check(list)) {
-		PyErr_SetString(PyExc_TypeError, "argument must be a signal list");
+		PyErr_SetString(PyExc_TypeError,
+		    "argument must be a list of signals.");
 		return UINT32_MAX;
 	}
 
@@ -238,19 +304,19 @@
 
 	if (!PyDict_Check(val)) {
 		PyErr_SetString(PyExc_TypeError,
-		                "argument must be a signal dict");
+		    "argument must be a signal dict.");
 		return -1;
 	}
 
 	for (cm = signal_map; cm->name != NULL; cm++) {
 		if ((b = PyDict_GetItem(val, cm->dec_cond)) == NULL) {
 			PyErr_SetString(PyExc_ValueError,
-			                "incomplete signal dict");
+			    "incomplete signal dict.");
 			return UINT32_MAX;
 		}
 
 		if ((x = PyObject_IsTrue(b)) < 0) {
-			return UINT32_MAX;
+			return UINT32_MAX; /* GCOV_UNLIKELY */
 		}
 		if (x == 1) {
 			flags |= cm->mpd_cond;
@@ -263,18 +329,14 @@
 static uint32_t
 PyLong_AsMpdFlags(PyObject *v)
 {
-	int overflow;
 	long x;
 
-	if (!PyLong_Check(v)) {
-		PyErr_SetString(PyExc_TypeError, "integer argument required");
+	x = PyLong_AsLong(v);
+	if (PyErr_Occurred()) {
 		return UINT32_MAX;
 	}
-
-	overflow = 0;
-	x = PyLong_AsLongAndOverflow(v, &overflow);
-	if (overflow != 0 || x < 0 || x > (long)MPD_Max_status) {
-		PyErr_SetString(PyExc_ValueError, "invalid flag value");
+	if (x < 0 || x > (long)MPD_Max_status) {
+		PyErr_SetString(PyExc_ValueError, invalid_flags_err);
 		return UINT32_MAX;
 	}
 
@@ -284,14 +346,11 @@
 static mpd_ssize_t
 PyLong_AsMpdSsize(PyObject *v)
 {
-#if MPD_SIZE_MAX == SIZE_MAX
 	mpd_ssize_t x;
-#else
-	int64_t x;
-#endif
 
 	if (!PyLong_Check(v)) {
-		PyErr_SetString(PyExc_TypeError, "integer argument required");
+		PyErr_SetString(PyExc_TypeError,
+		    "integer argument required.");
 		return MPD_SSIZE_MAX;
 	}
 
@@ -299,12 +358,6 @@
 	if (PyErr_Occurred()) {
 		return MPD_SSIZE_MAX;
 	}
-#if MPD_SIZE_MAX < SIZE_MAX
-	if (x < MPD_SSIZE_MIN || x > MPD_SSIZE_MAX) {
-		PyErr_SetString(PyExc_ValueError, "argument out of range");
-		return MPD_SSIZE_MAX;
-	}
-#endif
 
 	return x;
 }
@@ -316,11 +369,13 @@
 	if (ctx->traps&status) {
 		PyObject *ex, *siglist;
 
- 		if ((ex = flags_as_exception(ctx->traps&status)) == NULL) {
-			return 1;
-		}
-		if ((siglist = flags_as_list(ctx->traps&status)) == NULL) {
-			return 1;
+ 		ex = flags_as_exception(ctx->traps&status);
+		if (ex == NULL) {
+			return 1; /* GCOV_NOT_REACHED */
+		}
+		siglist = flags_as_list(ctx->traps&status);
+		if (siglist == NULL) {
+			return 1; /* GCOV_UNLIKELY */
 		}
 
 		PyErr_SetObject(ex, siglist);
@@ -339,7 +394,7 @@
 signaldict_init(PyObject *self, PyObject *args, PyObject *kwds)
 {
 	if (PyDict_Type.tp_init(self, args, kwds) < 0) {
-		return -1;
+		return -1; /* GCOV_UNLIKELY */
 	}
 
 	SdFlagAddr(self) = NULL;
@@ -372,7 +427,7 @@
 
 	for (cm = signal_map; cm->name != NULL; cm++) {
 		if (PyDict_SetItem(self, cm->dec_cond, Py_False) < 0) {
-			return -1;
+			return -1; /* GCOV_UNLIKELY */
 		}
 	}
 	return 0;
@@ -389,7 +444,7 @@
 	}
 
 	if ((x = PyObject_IsTrue(value)) < 0) {
-		return -1;
+		return -1; /* GCOV_UNLIKELY */
 	}
 	if (x == 1) {
 		SdFlags(self) |= flag;
@@ -404,35 +459,10 @@
 }
 
 static PyObject *
-signaldict_call_unary(PyObject *self, const char *name)
+signaldict_call_unary(PyObject *self, char *name)
 {
-	PyObject *result, *s;
-
-	if ((s = Py_BuildValue("s", name)) == NULL) {
-		return NULL;
-	}
-
 	signaldict_update(self);
-	result = PyObject_CallMethodObjArgs(self, s, NULL);
-
-	Py_DECREF(s);
-	return result;
-}
-
-static PyObject *
-signaldict_call_binary(PyObject *self, const char *name, PyObject *arg)
-{
-	PyObject *result, *s;
-
-	if ((s = Py_BuildValue("s", name)) == NULL) {
-		return NULL;
-	}
-
-	signaldict_update(self);
-	result = PyObject_CallMethodObjArgs(self, s, arg, NULL);
-
-	Py_DECREF(s);
-	return result;
+	return PyObject_CallMethod((PyObject *)&PyDict_Type, name, "O", self);
 }
 
 static PyObject *
@@ -464,13 +494,26 @@
 static PyObject *
 signaldict_get(PyObject *self, PyObject *args)
 {
-	return signaldict_call_binary(self, "get", args);
+	PyObject *key = NULL, *failobj = NULL;
+	if (!PyArg_ParseTuple(args, "O|O", &key, &failobj)) {
+		return NULL; /* GCOV_NOT_REACHED (why?) */
+	}
+	signaldict_update(self);
+	if (failobj) {
+		return PyObject_CallMethod((PyObject *)&PyDict_Type, "get",
+		                           "OOO", self, key, failobj);
+	}
+	return PyObject_CallMethod((PyObject *)&PyDict_Type, "get",
+		                   "OO", self, key);
 }
 
 static PyObject *
 signaldict_has_key(PyObject *self, PyObject *key)
 {
-	return signaldict_call_binary(self, "has_key", key);
+	int ret;
+	signaldict_update(self);
+	ret = PyDict_Contains(self, key);
+	return ret < 0 ? NULL : PyBool_FromLong(ret);
 }
 
 static PyObject *
@@ -483,28 +526,11 @@
 static PyObject *
 signaldict_iter(PyObject *self)
 {
+	signaldict_update(self);
 	return PyDict_Type.tp_iter(self);
 }
 
 static PyObject *
-signaldict_iterkeys(PyObject *self)
-{
-	return signaldict_call_unary(self, "iterkeys");
-}
-
-static PyObject *
-signaldict_itervalues(PyObject *self)
-{
-	return signaldict_call_unary(self, "itervalues");
-}
-
-static PyObject *
-signaldict_iteritems(PyObject *self)
-{
-	return signaldict_call_unary(self, "iteritems");
-}
-
-static PyObject *
 signaldict_keys(PyObject *self)
 {
 	signaldict_update(self);
@@ -519,10 +545,10 @@
 }
 
 static int
-signaldict_print(PyObject *self, FILE *fp, int flags)
-{
-	signaldict_update(self);
-	return PyDict_Type.tp_print(self, fp, flags);
+signaldict_print(PyObject *self, FILE *fp, int flags) /* GCOV_UNLIKELY */
+{ /* GCOV_UNLIKELY */
+	signaldict_update(self); /* GCOV_UNLIKELY */
+	return PyDict_Type.tp_print(self, fp, flags); /* GCOV_UNLIKELY */
 }
 
 static PyObject *
@@ -542,9 +568,7 @@
 signaldict_ass_sub(PyObject *self, PyObject *v, PyObject *w)
 {
 	if (w == NULL) {
-		PyErr_SetString(PyExc_ValueError,
-		                "signal keys cannot be deleted");
-		return -1;
+		return value_error_int("signal keys cannot be deleted.");
 	}
 	else {
 		return signaldict_setitem(self, v, w);
@@ -595,9 +619,6 @@
   {"items",        (PyCFunction)signaldict_items,      METH_NOARGS,         NULL},
   {"values",       (PyCFunction)signaldict_values,     METH_NOARGS,         NULL},
   {"copy",         (PyCFunction)signaldict_copy,       METH_NOARGS,         NULL},
-  {"iterkeys",     (PyCFunction)signaldict_iterkeys,   METH_NOARGS,         NULL},
-  {"itervalues",   (PyCFunction)signaldict_itervalues, METH_NOARGS,         NULL},
-  {"iteritems",    (PyCFunction)signaldict_iteritems,  METH_NOARGS,         NULL},
   {NULL, NULL}
 };
 
@@ -748,15 +769,15 @@
 	mpd_context_t *ctx;
 	mpd_ssize_t x;
 
-	if ((x = PyLong_AsMpdSsize(value)) == MPD_SSIZE_MAX) {
+	x = PyLong_AsMpdSsize(value);
+	if (PyErr_Occurred()) {
 		return -1;
 	}
 
 	ctx = CtxAddr(self);
 	if (!mpd_qsetprec(ctx, x)) {
-		if (dec_addstatus(ctx, MPD_Invalid_context)) {
-			return -1;
-		}
+		return value_error_int(
+		    "valid range for prec is [0, MAX_PREC].");
 	}
 
 	return 0;
@@ -768,15 +789,15 @@
 	mpd_context_t *ctx;
 	mpd_ssize_t x;
 
-	if ((x = PyLong_AsMpdSsize(value)) == MPD_SSIZE_MAX) {
+	x = PyLong_AsMpdSsize(value);
+	if (PyErr_Occurred()) {
 		return -1;
 	}
 
 	ctx = CtxAddr(self);
 	if (!mpd_qsetemin(ctx, x)) {
-		if (dec_addstatus(ctx, MPD_Invalid_context)) {
-			return -1;
-		}
+		return value_error_int(
+		    "valid range for Emin is [MIN_EMIN, 0].");
 	}
 
 	return 0;
@@ -788,15 +809,15 @@
 	mpd_context_t *ctx;
 	mpd_ssize_t x;
 
-	if ((x = PyLong_AsMpdSsize(value)) == MPD_SSIZE_MAX) {
+	x = PyLong_AsMpdSsize(value);
+	if (PyErr_Occurred()) {
 		return -1;
 	}
 
 	ctx = CtxAddr(self);
 	if (!mpd_qsetemax(ctx, x)) {
-		if (dec_addstatus(ctx, MPD_Invalid_context)) {
-			return -1;
-		}
+		return value_error_int(
+		    "valid range for Emax is [0, MAX_EMAX].");
 	}
 
 	return 0;
@@ -807,7 +828,8 @@
 {
 	mpd_context_t *ctx = CtxAddr(self);
 
-	if ((ctx->prec = PyLong_AsMpdSsize(value)) == MPD_SSIZE_MAX) {
+	ctx->prec = PyLong_AsMpdSsize(value);
+	if (PyErr_Occurred()) {
 		return NULL;
 	}
 
@@ -819,7 +841,8 @@
 {
 	mpd_context_t *ctx = CtxAddr(self);
 
-	if ((ctx->emin = PyLong_AsMpdSsize(value)) == MPD_SSIZE_MAX) {
+	ctx->emin = PyLong_AsMpdSsize(value);
+	if (PyErr_Occurred()) {
 		return NULL;
 	}
 
@@ -831,7 +854,8 @@
 {
 	mpd_context_t *ctx = CtxAddr(self);
 
-	if ((ctx->emax = PyLong_AsMpdSsize(value)) == MPD_SSIZE_MAX) {
+	ctx->emax = PyLong_AsMpdSsize(value);
+	if (PyErr_Occurred()) {
 		return NULL;
 	}
 
@@ -844,20 +868,15 @@
 	mpd_context_t *ctx;
 	mpd_ssize_t x;
 
-	if ((x = PyLong_AsMpdSsize(value)) == MPD_SSIZE_MAX) {
-		return -1;
-	}
-	if (x < 0 || x >= MPD_ROUND_GUARD) {
-		PyErr_SetString(PyExc_ValueError,
-		                "invalid value for context.round");
+	x = PyLong_AsMpdSsize(value);
+	if (PyErr_Occurred()) {
 		return -1;
 	}
+	BOUNDS_CHECK(x, INT_MIN, INT_MAX);
 
 	ctx = CtxAddr(self);
 	if (!mpd_qsetround(ctx, (int)x)) {
-		if (dec_addstatus(ctx, MPD_Invalid_context)) {
-			return -1;
-		}
+		return value_error_int(invalid_rounding_err);
 	}
 
 	return 0;
@@ -868,15 +887,16 @@
 {
 	mpd_ssize_t x;
 
-	if ((x = PyLong_AsMpdSsize(value)) == MPD_SSIZE_MAX) {
+	x = PyLong_AsMpdSsize(value);
+	if (PyErr_Occurred()) {
 		return -1;
 	}
+	BOUNDS_CHECK(x, INT_MIN, INT_MAX);
+
 	if (x != 0 && x != 1) {
-		PyErr_SetString(PyExc_ValueError,
-		                "invalid value for context.capitals");
-		return -1;
+		return value_error_int(
+		    "valid values for capitals are 0 or 1.");
 	}
-
 	CtxCaps(self) = (int)x;
 
 	return 0;
@@ -894,10 +914,8 @@
 	}
 
 	ctx = CtxAddr(self);
-	if (!mpd_qsettraps(ctx, (uint32_t)flags)) {
-		if (dec_addstatus(ctx, MPD_Invalid_context)) {
-			return -1;
-		}
+	if (!mpd_qsettraps(ctx, flags)) {
+		INTERNAL_ERROR_INT("context_settraps"); /* GCOV_NOT_REACHED */
 	}
 
 	return 0;
@@ -909,15 +927,14 @@
 	mpd_context_t *ctx;
 	uint32_t flags;
 
-	if ((flags = list_as_flags(value)) == UINT32_MAX) {
+	flags = list_as_flags(value);
+	if (flags == UINT32_MAX) {
 		return -1;
 	}
 
 	ctx = CtxAddr(self);
 	if (!mpd_qsettraps(ctx, flags)) {
-		if (dec_addstatus(ctx, MPD_Invalid_context)) {
-			return -1;
-		}
+		INTERNAL_ERROR_INT("context_settraps_list"); /* GCOV_NOT_REACHED */
 	}
 
 	return 0;
@@ -929,15 +946,14 @@
 	mpd_context_t *ctx;
 	uint32_t flags;
 
-	if ((flags = dict_as_flags(value)) == UINT32_MAX) {
+	flags = dict_as_flags(value);
+	if (flags == UINT32_MAX) {
 		return -1;
 	}
 
 	ctx = CtxAddr(self);
 	if (!mpd_qsettraps(ctx, flags)) {
-		if (dec_addstatus(ctx, MPD_Invalid_context)) {
-			return -1;
-		}
+		INTERNAL_ERROR_INT("context_settraps_dict"); /* GCOV_NOT_REACHED */
 	}
 
 	return 0;
@@ -955,10 +971,8 @@
 	}
 
 	ctx = CtxAddr(self);
-	if (!mpd_qsetstatus(ctx, (uint32_t)flags)) {
-		if (dec_addstatus(ctx, MPD_Invalid_context)) {
-			return -1;
-		}
+	if (!mpd_qsetstatus(ctx, flags)) {
+		INTERNAL_ERROR_INT("context_setstatus"); /* GCOV_NOT_REACHED */
 	}
 
 	return 0;
@@ -970,15 +984,14 @@
 	mpd_context_t *ctx;
 	uint32_t flags;
 
-	if ((flags = list_as_flags(value)) == UINT32_MAX) {
+	flags = list_as_flags(value);
+	if (flags == UINT32_MAX) {
 		return -1;
 	}
 
 	ctx = CtxAddr(self);
 	if (!mpd_qsetstatus(ctx, flags)) {
-		if (dec_addstatus(ctx, MPD_Invalid_context)) {
-			return -1;
-		}
+		INTERNAL_ERROR_INT("context_setstatus_list"); /* GCOV_NOT_REACHED */
 	}
 
 	return 0;
@@ -990,15 +1003,14 @@
 	mpd_context_t *ctx;
 	uint32_t flags;
 
-	if ((flags = dict_as_flags(value)) == UINT32_MAX) {
+	flags = dict_as_flags(value);
+	if (flags == UINT32_MAX) {
 		return -1;
 	}
 
 	ctx = CtxAddr(self);
 	if (!mpd_qsetstatus(ctx, flags)) {
-		if (dec_addstatus(ctx, MPD_Invalid_context)) {
-			return -1;
-		}
+		INTERNAL_ERROR_INT("context_setstatus_dict"); /* GCOV_NOT_REACHED */
 	}
 
 	return 0;
@@ -1010,15 +1022,15 @@
 	mpd_context_t *ctx;
 	mpd_ssize_t x;
 
-	if ((x = PyLong_AsMpdSsize(value)) == MPD_SSIZE_MAX) {
+	x = PyLong_AsMpdSsize(value);
+	if (PyErr_Occurred()) {
 		return -1;
 	}
+	BOUNDS_CHECK(x, INT_MIN, INT_MAX);
 
 	ctx = CtxAddr(self);
 	if (!mpd_qsetclamp(ctx, (int)x)) {
-		if (dec_addstatus(ctx, MPD_Invalid_context)) {
-			return -1;
-		}
+		return value_error_int("valid values for clamp are 0 or 1.");
 	}
 
 	return 0;
@@ -1030,15 +1042,15 @@
 	mpd_context_t *ctx;
 	mpd_ssize_t x;
 
-	if ((x = PyLong_AsMpdSsize(value)) == MPD_SSIZE_MAX) {
+	x = PyLong_AsMpdSsize(value);
+	if (PyErr_Occurred()) {
 		return -1;
 	}
+	BOUNDS_CHECK(x, INT_MIN, INT_MAX);
 
 	ctx = CtxAddr(self);
 	if (!mpd_qsetcr(ctx, (int)x)) {
-		if (dec_addstatus(ctx, MPD_Invalid_context)) {
-			return -1;
-		}
+		return value_error_int("valid values for _allcr are 0 or 1.");
 	}
 
 	return 0;
@@ -1050,10 +1062,10 @@
 	PyObject *retval;
 
 	if (!PyUnicode_Check(name)) {
-		PyErr_Format(PyExc_TypeError,
+		PyErr_Format(PyExc_TypeError, /* GCOV_NOT_REACHED (why?) */
 		             "attribute name must be string, not '%.200s'",
-		             name->ob_type->tp_name);
-		return NULL;
+		             name->ob_type->tp_name); /* GCOV_NOT_REACHED */
+		return NULL; /* GCOV_NOT_REACHED */
 	}
 
 	if (PyUnicode_CompareWithASCIIString(name, "traps") == 0) {
@@ -1075,25 +1087,21 @@
 context_setattr(PyObject *self, PyObject *name, PyObject *value)
 {
 	if (!PyUnicode_Check(name)) {
-		PyErr_Format(PyExc_TypeError,
+		PyErr_Format(PyExc_TypeError, /* GCOV_NOT_REACHED (why?) */
 		             "attribute name must be string, not '%.200s'",
-		             name->ob_type->tp_name);
-		return -1;
+		             name->ob_type->tp_name); /* GCOV_NOT_REACHED */
+		return -1; /* GCOV_NOT_REACHED */
 	}
 
 	if (PyUnicode_CompareWithASCIIString(name, "traps") == 0) {
 		if (value == NULL) {
-			PyErr_SetString(PyExc_ValueError,
-			                "traps cannot be deleted");
-			return -1;
+			return value_error_int("traps cannot be deleted.");
 		}
 		return context_settraps_dict(self, value);
 	}
 	else if (PyUnicode_CompareWithASCIIString(name, "flags") == 0) {
 		if (value == NULL) {
-			PyErr_SetString(PyExc_ValueError,
-			                "flags cannot be deleted");
-			return -1;
+			return value_error_int("flags cannot be deleted.");
 		}
 		return context_setstatus_dict(self, value);
 	}
@@ -1108,7 +1116,7 @@
 	PyDecContextObject *decctx = (PyDecContextObject *)self;
 
 	if (signaldict_clear_all(decctx->traps) < 0) {
-		return NULL;
+		return NULL; /* GCOV_UNLIKELY */
 	}
 	Py_RETURN_NONE;
 }
@@ -1119,7 +1127,7 @@
 	PyDecContextObject *decctx = (PyDecContextObject *)self;
 
 	if (signaldict_clear_all(decctx->flags) < 0) {
-		return NULL;
+		return NULL; /* GCOV_UNLIKELY */
 	}
 	Py_RETURN_NONE;
 }
@@ -1133,18 +1141,18 @@
 
 	self = PyObject_New(PyDecContextObject, &PyDecContext_Type);
 	if (self == NULL) {
-		return NULL;
+		return NULL; /* GCOV_UNLIKELY */
 	}
 	self->traps = PyObject_CallObject((PyObject *)&PyDecSignalDict_Type, NULL);
 	if (self->traps == NULL) {
-		Py_DECREF(self);
-		return NULL;
+		Py_DECREF(self); /* GCOV_UNLIKELY */
+		return NULL; /* GCOV_UNLIKELY */
 	}
 	self->flags = PyObject_CallObject((PyObject *)&PyDecSignalDict_Type, NULL);
 	if (self->flags == NULL) {
-		Py_DECREF(self->traps);
-		Py_DECREF(self);
-		return NULL;
+		Py_DECREF(self->traps); /* GCOV_UNLIKELY */
+		Py_DECREF(self); /* GCOV_UNLIKELY */
+		return NULL; /* GCOV_UNLIKELY */
 	}
 
 	ctx = CtxAddr(self);
@@ -1187,6 +1195,7 @@
 	PyObject *status = NULL;
 	mpd_context_t *ctx, t=dflt_ctx;
 	int capitals = 1;
+	int ret;
 
 	assert(PyTuple_Check(args));
 	ctx = CtxAddr(self);
@@ -1212,43 +1221,47 @@
 	    !mpd_qsetstatus(ctx, t.status) ||
 	    !mpd_qsetclamp(ctx, t.clamp) ||
 	    !mpd_qsetcr(ctx, t.allcr)) {
-		PyErr_SetString(PyExc_ValueError, "invalid context");
-		return -1;
+		return value_error_int("invalid context.");
 	}
 
 	if (capitals != 0 && capitals != 1) {
-		PyErr_SetString(PyExc_ValueError, "invalid context");
-		return -1;
+		return value_error_int("invalid context.");
 	}
 	CtxCaps(self) = capitals;
 
 	if (traps != NULL) {
 		if (PyLong_Check(traps)) {
-			return context_settraps(self, traps, NULL);
+			ret = context_settraps(self, traps, NULL);
 		}
 		else if (PyList_Check(traps)) {
-			return context_settraps_list(self, traps);
+			ret = context_settraps_list(self, traps);
 		}
 		else {
-			return context_settraps_dict(self, traps);
+			ret = context_settraps_dict(self, traps);
+		}
+		if (ret < 0) {
+			return ret;
 		}
 	}
 	if (status != NULL) {
 		if (PyLong_Check(status)) {
-			return context_setstatus(self, status, NULL);
+			ret = context_setstatus(self, status, NULL);
 		}
 		else if (PyList_Check(status)) {
-			return context_setstatus_list(self, status);
+			ret = context_setstatus_list(self, status);
 		}
 		else {
-			return context_setstatus_dict(self, status);
+			ret = context_setstatus_dict(self, status);
+		}
+		if (ret < 0) {
+			return ret;
 		}
 	}
 
 	return 0;
 }
 
-#define FD_CTX_LEN 400
+#define FD_CTX_LEN 432
 static PyObject *
 context_repr(PyDecContextObject *self)
 {
@@ -1288,9 +1301,8 @@
 
 	return PyUnicode_FromString(s);
 
-error:
-	PyErr_SetString(PyExc_RuntimeError, "internal error in context_repr");
-	return NULL;
+error: /* GCOV_NOT_REACHED */
+	INTERNAL_ERROR_PTR("context_repr"); /* GCOV_NOT_REACHED */
 }
 
 static void
@@ -1339,7 +1351,7 @@
 
 	ctxobj = PyObject_CallObject((PyObject *)&PyDecContext_Type, NULL);
 	if (ctxobj == NULL) {
-		return NULL;
+		return NULL; /* GCOV_UNLIKELY */
 	}
 	*CtxAddr(ctxobj) = ctx;
 
@@ -1347,8 +1359,8 @@
 
 error:
 	PyErr_Format(PyExc_ValueError,
-	             "argument must be a multiple of 32, with a maximum of %d",
-	             MPD_IEEE_CONTEXT_MAX_BITS
+	    "argument must be a multiple of 32, with a maximum of %d.",
+	    MPD_IEEE_CONTEXT_MAX_BITS
 	);
 	return NULL;
 }
@@ -1361,7 +1373,7 @@
 
 	newob = PyObject_CallObject((PyObject *)&PyDecContext_Type, NULL);
 	if (newob == NULL) {
-		return NULL;
+		return NULL; /* GCOV_UNLIKELY */
 	}
 
 	ctx = CtxAddr(newob);
@@ -1423,15 +1435,15 @@
 
 #define CONTEXT_CHECK(obj) \
         if (!PyDecContext_Check(obj)) {             \
-                PyErr_SetString( PyExc_TypeError,   \
-                    "argument must be a context" ); \
+                PyErr_SetString(PyExc_TypeError,    \
+                    "argument must be a context."); \
                 return NULL;                        \
         }
 
 #define CONTEXT_CHECK_VA(obj) \
         if (!PyDecContext_Check(obj)) {                      \
-                PyErr_SetString( PyExc_TypeError,            \
-                    "optional argument must be a context" ); \
+                PyErr_SetString(PyExc_TypeError,             \
+                    "optional argument must be a context."); \
                 return NULL;                                 \
         }
 
@@ -1520,8 +1532,9 @@
 
 	dict = PyThreadState_GetDict();
 	if (dict == NULL) {
-		PyErr_SetString(PyExc_RuntimeError, "cannot get thread state");
-		return NULL;
+		PyErr_SetString(PyExc_RuntimeError, /* GCOV_UNLIKELY */
+		    "cannot get thread state."); /* GCOV_UNLIKELY */
+		return NULL; /* GCOV_UNLIKELY */
 	}
 
 	tl_context = PyDict_GetItem(dict, tls_context_key);
@@ -1535,11 +1548,11 @@
 	/* Otherwise, set up a new thread local context. */
 	tl_context = (PyObject *)context_copy(default_context_template);
 	if (tl_context == NULL) {
-		return NULL;
+		return NULL; /* GCOV_UNLIKELY */
 	}
 	if (PyDict_SetItem(dict, tls_context_key, tl_context) < 0) {
-		Py_DECREF(tl_context);
-		return NULL;
+		Py_DECREF(tl_context); /* GCOV_UNLIKELY */
+		return NULL; /* GCOV_UNLIKELY */
 	}
 	Py_DECREF(tl_context);
 
@@ -1569,7 +1582,7 @@
 	PyObject *obj;
 
 	if ((obj = current_context()) == NULL) {
-		return NULL;
+		return NULL; /* GCOV_UNLIKELY */
 	}
 
 	Py_INCREF(obj);
@@ -1586,8 +1599,9 @@
 
 	dict = PyThreadState_GetDict();
 	if (dict == NULL) {
-		PyErr_SetString(PyExc_RuntimeError, "cannot get thread state");
-		return NULL;
+		PyErr_SetString(PyExc_RuntimeError, /* GCOV_UNLIKELY */
+		    "cannot get thread state."); /* GCOV_UNLIKELY */
+		return NULL; /* GCOV_UNLIKELY */
 	}
 
 	/* If the new context is one of the templates, make a copy.
@@ -1596,7 +1610,7 @@
 	    v == basic_context_template ||
 	    v == extended_context_template) {
 		if ((v = context_copy(v)) == NULL) {
-			return NULL;
+			return NULL; /* GCOV_UNLIKELY */
 		}
 	}
 	else {
@@ -1604,7 +1618,7 @@
 	}
 
 	if (PyDict_SetItem(dict, tls_context_key, v) < 0) {
-		return NULL;
+		return NULL; /* GCOV_UNLIKELY */
 	}
 
 	Py_DECREF(v);
@@ -1625,20 +1639,20 @@
 	CURRENT_CONTEXT(global);
 	local = global;
 	if (!PyArg_ParseTuple(args, "|O", &local)) {
-		return NULL;
+		return NULL; /* GCOV_NOT_REACHED */
 	}
 	CONTEXT_CHECK_VA(local);
 
 	self = PyObject_New(PyDecContextManagerObject,
 	                    &PyDecContextManager_Type);
 	if (self == NULL) {
-		return NULL;
+		return NULL; /* GCOV_UNLIKELY */
 	}
 
 	self->local = context_copy(local);
 	if (self->local == NULL) {
-		Py_DECREF(self);
-		return NULL;
+		Py_DECREF(self); /* GCOV_UNLIKELY */
+		return NULL; /* GCOV_UNLIKELY */
 	}
 	self->global = global;
 	Py_INCREF(self->global);
@@ -1661,7 +1675,7 @@
 
 	ret = PyDec_SetCurrentContext(NULL, self->local);
 	if (ret == NULL) {
-		return NULL;
+		return NULL; /* GCOV_UNLIKELY */
 	}
 	Py_DECREF(ret);
 
@@ -1677,7 +1691,7 @@
 
 	ret = PyDec_SetCurrentContext(NULL, self->global);
 	if (ret == NULL) {
-		return NULL;
+		return NULL; /* GCOV_UNLIKELY */
 	}
 	Py_DECREF(ret);
 
@@ -1734,12 +1748,12 @@
 	PyDecObject * self;
 
 	if ((self = PyObject_New(PyDecObject, &PyDec_Type)) == NULL) {
-		return NULL;
+		return NULL; /* GCOV_UNLIKELY */
 	}
 	if ((self->dec = mpd_qnew()) == NULL) {
-		PyErr_NoMemory();
-		PyObject_Del(self);
-		return NULL;
+		PyErr_NoMemory(); /* GCOV_UNLIKELY */
+		PyObject_Del(self); /* GCOV_UNLIKELY */
+		return NULL; /* GCOV_UNLIKELY */
 	}
 
 	return self;
@@ -1766,19 +1780,19 @@
 	char *cp;
 
 	if((newob = dec_alloc()) == NULL) {
-		return NULL;
+		return NULL; /* GCOV_UNLIKELY */
 	}
 	if ((cp = PyMem_Malloc(PyUnicode_GET_SIZE(v)+1)) == NULL) {
-		Py_DECREF(newob);
-		PyErr_NoMemory();
-		return NULL;
+		Py_DECREF(newob); /* GCOV_UNLIKELY */
+		PyErr_NoMemory(); /* GCOV_UNLIKELY */
+		return NULL; /* GCOV_UNLIKELY */
 	}
 	if (PyUnicode_EncodeDecimal(PyUnicode_AS_UNICODE(v),
 	                            PyUnicode_GET_SIZE(v),
 	                            cp, NULL)) {
-		Py_DECREF(newob);
-		PyMem_Free(cp);
-		return NULL;
+		Py_DECREF(newob); /* GCOV_UNLIKELY */
+		PyMem_Free(cp); /* GCOV_UNLIKELY */
+		return NULL; /* GCOV_UNLIKELY */
 	}
 
 	mpd_qset_string(newob->dec, cp, ctx, &status);
@@ -1803,7 +1817,7 @@
 	uint8_t sign;
 
 	if((newob = dec_alloc()) == NULL) {
-		return NULL;
+		return NULL; /* GCOV_UNLIKELY */
 	}
 
 	ob_size = Py_SIZE(l);
@@ -1831,7 +1845,7 @@
 	mpd_qimport_u16(newob->dec, l->ob_digit, len, sign, PyLong_BASE,
 	                ctx, &status);
 #else
-  #error "PYLONG_BITS_IN_DIGIT should be 15 or 30"
+  #error "PYLONG_BITS_IN_DIGIT should be 15 or 30."
 #endif
 	if (dec_addstatus(ctx, status)) {
 		Py_DECREF(newob);
@@ -1867,7 +1881,7 @@
 	if (s != x || t != y) {
 		n = t-s;
 		if ((y = PyMem_Malloc(n+1)) == NULL) {
-			return NULL;
+			return NULL; /* GCOV_UNLIKELY */
 		}
 		strncpy(y, s, n);
 		y[n] = '\0';
@@ -1887,27 +1901,27 @@
 	char *cp, *stripped;
 
 	if((newob = dec_alloc()) == NULL) {
-		return NULL;
+		return NULL; /* GCOV_UNLIKELY */
 	}
 	if ((cp = PyMem_Malloc(PyUnicode_GET_SIZE(v)+1)) == NULL) {
-		Py_DECREF(newob);
-		PyErr_NoMemory();
-		return NULL;
+		Py_DECREF(newob); /* GCOV_UNLIKELY */
+		PyErr_NoMemory(); /* GCOV_UNLIKELY */
+		return NULL; /* GCOV_UNLIKELY */
 	}
 	if (PyUnicode_EncodeDecimal(PyUnicode_AS_UNICODE(v),
 	                            PyUnicode_GET_SIZE(v),
 	                            cp, NULL)) {
-		Py_DECREF(newob);
-		PyMem_Free(cp);
-		return NULL;
+		Py_DECREF(newob); /* GCOV_UNLIKELY */
+		PyMem_Free(cp); /* GCOV_UNLIKELY */
+		return NULL; /* GCOV_UNLIKELY */
 	}
 
 	mpd_maxcontext(&maxctx);
 	if ((stripped = strip_ws(cp)) == NULL) {
-		Py_DECREF(newob);
-		PyMem_Free(cp);
-		PyErr_NoMemory();
-		return NULL;
+		Py_DECREF(newob); /* GCOV_UNLIKELY */
+		PyMem_Free(cp); /* GCOV_UNLIKELY */
+		PyErr_NoMemory(); /* GCOV_UNLIKELY */
+		return NULL; /* GCOV_UNLIKELY */
 	}
 
 	mpd_qset_string(newob->dec, stripped, &maxctx, &status);
@@ -1921,8 +1935,8 @@
 	}
 	status &= MPD_Errors;
 	if (dec_addstatus(ctx, status)) {
-		Py_DECREF(newob);
-		return NULL;
+		Py_DECREF(newob); /* GCOV_UNLIKELY */
+		return NULL; /* GCOV_UNLIKELY */
 	}
 
 	return (PyObject *)newob;
@@ -1941,7 +1955,7 @@
 	uint8_t sign;
 
 	if((newob = dec_alloc()) == NULL) {
-		return NULL;
+		return NULL; /* GCOV_UNLIKELY */
 	}
 
 	ob_size = Py_SIZE(l);
@@ -1971,17 +1985,17 @@
 	mpd_qimport_u16(newob->dec, l->ob_digit, len, sign, PyLong_BASE,
 	                &maxctx, &status);
 #else
-  #error "PYLONG_BITS_IN_DIGIT should be 15 or 30"
+  #error "PYLONG_BITS_IN_DIGIT should be 15 or 30."
 #endif
 
 	if (status&(MPD_Inexact|MPD_Rounded)) {
 		/* we want exact results */
-		mpd_seterror(newob->dec, MPD_Invalid_operation, &status);
+		mpd_seterror(newob->dec, MPD_Invalid_operation, &status); /* GCOV_UNLIKELY */
 	}
 	status &= MPD_Errors;
 	if (dec_addstatus(ctx, status)) {
-		Py_DECREF(newob);
-		return NULL;
+		Py_DECREF(newob); /* GCOV_UNLIKELY */
+		return NULL; /* GCOV_UNLIKELY */
 	}
 
 	return (PyObject *)newob;
@@ -2000,22 +2014,18 @@
 	int n;
 
 	if (PyTuple_Size(v) != 3) {
-		PyErr_SetString(PyExc_ValueError,
-		                "argument must be a tuple of length 3");
-		return NULL;
+		return value_error_ptr(
+		    "argument must be a tuple of length 3.");
 	}
 
 	tmp = PyTuple_GET_ITEM(v, 0);
 	if (!PyLong_Check(tmp)) {
-		PyErr_SetString(PyExc_TypeError,
-		                "sign must be 0 or 1");
+		PyErr_SetString(PyExc_TypeError, "sign must be 0 or 1.");
 		return NULL;
 	}
 	sign = PyLong_AsLong(tmp);
 	if (sign != 0 && sign != 1) {
-		PyErr_SetString(PyExc_ValueError,
-		                "sign must be 0 or 1");
-		return NULL;
+		return value_error_ptr("sign must be 0 or 1.");
 	}
 	sign_special[0] = sign ? '-' : '+';
 	sign_special[1] = '\0';
@@ -2032,10 +2042,9 @@
 			strcat(sign_special, "sNaN");
 		}
 		else {
-			PyErr_SetString(PyExc_ValueError,
-			                "string argument in the third position "
-			                "must be 'F', 'n' or 'N'");
-			return NULL;
+			return value_error_ptr(
+			    "string argument in the third position "
+			    "must be 'F', 'n' or 'N'.");
 		}
 	}
 	else {
@@ -2048,7 +2057,7 @@
 	dtuple = PyTuple_GET_ITEM(v, 1);
 	if (!PyTuple_Check(dtuple)) {
 		PyErr_SetString(PyExc_TypeError,
-		                "coefficient must be a tuple of digits");
+		    "coefficient must be a tuple of digits.");
 		return NULL;
 	}
 
@@ -2057,8 +2066,8 @@
 	mem = 1 + tsize + 3 + MPD_EXPDIGITS + 2;
 	cp = decstring = PyMem_Malloc(mem);
 	if (decstring == NULL) {
-		PyErr_NoMemory();
-		return NULL;
+		PyErr_NoMemory(); /* GCOV_UNLIKELY */
+		return NULL; /* GCOV_UNLIKELY */
 	}
 
 	n = snprintf(cp, mem, "%s", sign_special);
@@ -2074,15 +2083,14 @@
 		if (!PyLong_Check(tmp)) {
 			PyMem_Free(decstring);
 			PyErr_SetString(PyExc_TypeError,
-			                "coefficient must be a tuple of digits");
+			    "coefficient must be a tuple of digits.");
 			return NULL;
 		}
 		l = PyLong_AsLong(tmp);
 		if (l < 0 || l > 9) {
 			PyMem_Free(decstring);
-			PyErr_SetString(PyExc_ValueError,
-			                "coefficient must be a tuple of digits");
-			return NULL;
+			return value_error_ptr(
+			    "coefficient must be a tuple of digits.");
 		}
 		*cp++ = (char)l + '0';
 	}
@@ -2131,6 +2139,145 @@
 	return result;
 }
 
+static PyObject *
+_PyDec_FromFloat_Max(PyObject *self, PyObject *v)
+{
+	PyObject *result, *tmp;
+	PyObject *n, *d, *n_d;
+	mpd_ssize_t k;
+	double x;
+	int sign;
+	mpd_t *d1, *d2;
+	uint32_t status = 0;
+	mpd_context_t *ctx, maxctx;
+
+
+	CURRENT_CONTEXT_ADDR(ctx);
+	if (PyLong_Check(v)) {
+		return _PyDec_FromLong_Max(v, ctx);
+	}
+
+	x = PyFloat_AsDouble(v);
+	if (x == -1.0 && PyErr_Occurred()) {
+		return NULL;
+	}
+	sign = (copysign(1.0, x) == 1.0) ? 0 : 1;
+
+	if (Py_IS_NAN(x) || Py_IS_INFINITY(x)) {
+		result = PyObject_CallObject(self, NULL);
+		if (result == NULL) {
+			return NULL; /* GCOV_UNLIKELY */
+		}
+		if (Py_IS_NAN(x)) {
+			/* decimal.py calls repr(float(+-nan)),
+			 * which always gives a positive result. */
+			mpd_setspecial(DecAddr(result), MPD_POS, MPD_NAN);
+		}
+		else {
+			mpd_setspecial(DecAddr(result), sign, MPD_INF);
+		}
+		return result;
+	}
+
+	if ((tmp = PyObject_CallMethod(v, "__abs__", NULL)) == NULL) {
+		return NULL; /* GCOV_UNLIKELY */
+	}
+	n_d = PyObject_CallMethod(tmp, "as_integer_ratio", NULL);
+	Py_DECREF(tmp);
+	if (n_d == NULL) {
+		return NULL; /* GCOV_UNLIKELY */
+	}
+	if ((n = PyTuple_GetItem(n_d, 0)) == NULL) {
+		Py_DECREF(n_d); /* GCOV_UNLIKELY */
+		return NULL; /* GCOV_UNLIKELY */
+	}
+	if ((d = PyTuple_GetItem(n_d, 1)) == NULL) {
+		Py_DECREF(n_d); /* GCOV_UNLIKELY */
+		return NULL; /* GCOV_UNLIKELY */
+	}
+
+
+	if ((tmp = PyObject_CallMethod(d, "bit_length", NULL)) == NULL) {
+		Py_DECREF(n_d); /* GCOV_UNLIKELY */
+		return NULL; /* GCOV_UNLIKELY */
+	}
+	k = PyLong_AsMpdSsize(tmp);
+	Py_DECREF(tmp);
+	if (k == MPD_SSIZE_MAX) {
+		Py_DECREF(n_d); /* GCOV_UNLIKELY */
+		return NULL; /* GCOV_UNLIKELY */
+	}
+	k--;
+
+	if ((d1 = mpd_qnew()) == NULL) { 
+		Py_DECREF(n_d); /* GCOV_UNLIKELY */
+		return NULL; /* GCOV_UNLIKELY */
+	}
+	if ((d2 = mpd_qnew()) == NULL) { 
+		mpd_del(d1); /* GCOV_UNLIKELY */
+		Py_DECREF(n_d); /* GCOV_UNLIKELY */
+		return NULL; /* GCOV_UNLIKELY */
+	}
+
+	mpd_maxcontext(&maxctx);
+	mpd_qset_uint(d1, 5, &maxctx, &status);
+	mpd_qset_ssize(d2, k, &maxctx, &status);
+	mpd_qpow(d1, d1, d2, &maxctx, &status);
+	if (dec_addstatus(ctx, status)) {
+		mpd_del(d1); /* GCOV_UNLIKELY */
+		mpd_del(d2); /* GCOV_UNLIKELY */
+		Py_DECREF(n_d); /* GCOV_UNLIKELY */
+		return NULL; /* GCOV_UNLIKELY */
+	}
+
+	tmp = Py_BuildValue("(O)", n);
+	result = PyObject_CallObject(self, tmp);
+	Py_DECREF(tmp);
+	Py_DECREF(n_d);
+	if (result == NULL) {
+		mpd_del(d1); /* GCOV_UNLIKELY */
+		mpd_del(d2); /* GCOV_UNLIKELY */
+		return NULL; /* GCOV_UNLIKELY */
+	}
+
+	/* result = n * 5**k */
+	mpd_qmul(DecAddr(result), DecAddr(result), d1, &maxctx, &status);
+	mpd_del(d1);
+	mpd_del(d2);
+	if (dec_addstatus(ctx, status)) {
+		Py_DECREF(result); /* GCOV_UNLIKELY */
+		return NULL; /* GCOV_UNLIKELY */
+	}
+	/* result = +- n * 5**k * 10**-k */
+	mpd_set_sign(DecAddr(result), sign);
+	DecAddr(result)->exp = -k;
+
+	return result;
+}
+
+static PyObject *
+PyDecContext_FromFloat(PyObject *self, PyObject *v)
+{
+	PyObject *result;
+	mpd_context_t *ctx;
+	uint32_t status = 0;
+
+	ctx = CtxAddr(self);
+
+	result = _PyDec_FromFloat_Max((PyObject *)&PyDec_Type, v);
+	if (result == NULL) {
+		return NULL; /* GCOV_UNLIKELY */
+	}
+
+	mpd_qfinalize(DecAddr(result), ctx, &status);
+	if (dec_addstatus(ctx, status)) {
+		Py_DECREF(result);
+		return NULL;
+	}
+
+	return result;
+}
+
 /* Caller guarantees types. */
 static PyObject *
 dec_apply(PyObject *v, mpd_context_t *ctx)
@@ -2139,13 +2286,13 @@
 	uint32_t status = 0;
 
 	if((newob = dec_alloc()) == NULL) {
-		return NULL;
+		return NULL; /* GCOV_UNLIKELY */
 	}
 
 	mpd_qcopy(newob->dec, ((PyDecObject *)v)->dec, &status);
 	if (dec_addstatus(ctx, status)) {
-		Py_DECREF(newob);
-		return NULL;
+		Py_DECREF(newob); /* GCOV_UNLIKELY */
+		return NULL; /* GCOV_UNLIKELY */
 	}
 
 	mpd_qfinalize(newob->dec, ctx, &status);
@@ -2180,7 +2327,8 @@
 	mpd_context_t *ctx;
 
 	if (!PyDec_Check(decobj)) {
-		PyErr_SetString(PyExc_TypeError, "argument must be a Decimal");
+		PyErr_SetString(PyExc_TypeError,
+		    "argument must be a Decimal.");
 		return NULL;
 	}
 
@@ -2201,19 +2349,19 @@
 	if (PyDec_Check(v)) {
 		*a = (PyDecObject *) v;
 		Py_INCREF(v);
+		return 1;
 	}
-	else if (PyLong_Check(v)) {
-		if ((*a = (PyDecObject *) _PyDec_FromLong_Max(v, ctx)) == NULL) {
-			return 0;
+	if (PyLong_Check(v)) {
+		*a = (PyDecObject *) _PyDec_FromLong_Max(v, ctx);
+		if (*a == NULL) {
+			return 0; /* GCOV_UNLIKELY */
 		}
-	}
-	else {
-		Py_INCREF(Py_NotImplemented);
-		*a = (PyDecObject *) Py_NotImplemented;
-		return 0;
+		return 1;
 	}
 
-	return 1;
+	Py_INCREF(Py_NotImplemented);
+	*a = (PyDecObject *) Py_NotImplemented;
+	return 0;
 }
 
 #define CONVERT_OP(v, a, ctx) \
@@ -2245,6 +2393,54 @@
         }
 
 
+/* Convert for comparison */
+static int
+convert_op_cmp(PyObject *v, PyDecObject **a, int op, mpd_context_t *ctx)
+{
+	if (PyDec_Check(v)) {
+		*a = (PyDecObject *) v;
+		Py_INCREF(v);
+		return 1;
+	}
+	if (PyLong_Check(v)) {
+		*a = (PyDecObject *) _PyDec_FromLong_Max(v, ctx);
+		if (*a == NULL) {
+			return 0; /* GCOV_UNLIKELY */
+		}
+		return 1;
+	}
+	if (PyFloat_Check(v)) {
+		ctx->status |= MPD_Float_operation;
+		if (op != Py_EQ && op != Py_NE &&
+		    dec_addstatus(ctx, MPD_Float_operation)) {
+			*a = NULL;
+			return 0;
+		}
+#if PY_VERSION_HEX >= 0x03020000
+		*a = (PyDecObject *) _PyDec_FromFloat_Max(
+		                         (PyObject *)&PyDec_Type, v);
+		if (*a == NULL) {
+			return 0; /* GCOV_UNLIKELY */
+		}
+		return 1;
+#endif
+	}
+
+	Py_INCREF(Py_NotImplemented);
+	*a = (PyDecObject *) Py_NotImplemented;
+	return 0;
+}
+
+#define CONVERT_BINOP_CMP(v, w, a, b, op, ctx) \
+        if (!convert_op_cmp(v, a, op, ctx)) {  \
+                return (PyObject *) *(a);      \
+        }                                      \
+        if (!convert_op_cmp(w, b, op, ctx)) {  \
+                Py_DECREF(*(a));               \
+                return (PyObject *) *(b);      \
+        }
+
+
 /* Same as convert_op(), but set an error instead of returning
  * NotImplemented. */
 static int
@@ -2254,19 +2450,20 @@
 	if (PyDec_Check(v)) {
 		*a = (PyDecObject *) v;
 		Py_INCREF(v);
+		return 1;
 	}
-	else if (PyLong_Check(v)) {
-		if ((*a = (PyDecObject *) _PyDec_FromLong_Max(v, ctx)) == NULL) {
-			return 0;
+	if (PyLong_Check(v)) {
+		*a = (PyDecObject *) _PyDec_FromLong_Max(v, ctx);
+		if (*a == NULL) {
+			return 0; /* GCOV_UNLIKELY */
 		}
-	}
-	else {
-		PyErr_Format(PyExc_TypeError, "conversion from %s to Decimal is"
-		             " not supported", v->ob_type->tp_name);
-		return 0;
+		return 1;
 	}
 
-	return 1;
+	PyErr_Format(PyExc_TypeError,
+	    "conversion from %s to Decimal is not supported.",
+	    v->ob_type->tp_name);
+	return 0;
 }
 
 #define CONVERT_OP_SET(v, a, ctx) \
@@ -2297,6 +2494,7 @@
                 return NULL;                      \
         }
 
+
 static PyObject *dec_subtype_new(PyTypeObject *type, PyObject *args,
                                  PyObject *kwds);
 
@@ -2311,240 +2509,119 @@
 		return dec_subtype_new(type, args, kwds);
 	}
 
-	CURRENT_CONTEXT(ctxobj);
-	if (!PyArg_ParseTuple(args, "|OO", &v, &ctxobj)) {
-		return NULL;
-	}
-
-	if (v == NULL) {
-		v = PyLong_FromLong(0);
-		Py_DECREF(v);
-	}
-
-	CONTEXT_CHECK_VA(ctxobj);
-	ctx = CtxAddr(ctxobj);
-
-	if (PyDec_Check(v)) {
-		Py_INCREF(v);
-		return v;
-	}
-	else if (PyUnicode_Check(v)) {
-		return _PyDec_FromUnicode_Max(v, ctx);
-	}
-	else if (PyLong_Check(v)) {
-		return _PyDec_FromLong_Max(v, ctx);
-	}
-	else if (PyTuple_Check(v)) {
-		return _PyDec_FromTuple_Max(v, ctx);
-	}
-	else {
-		PyErr_Format(PyExc_TypeError, "conversion from %s to Decimal is"
-		             " not supported", v->ob_type->tp_name);
-		return NULL;
-	}
-}
-
-static PyObject *
-dec_subtype_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
-{
-	PyObject *tmp, *newobj;
-
-	assert(PyType_IsSubtype(type, &PyDec_Type));
-	tmp = dec_new(&PyDec_Type, args, kwds);
-	if (tmp == NULL) {
-		return NULL;
-	}
-
-	newobj = type->tp_alloc(type, 0);
-	if (newobj == NULL) {
-		Py_DECREF(tmp);
-		return NULL;
-	}
-
-	DecAddr(newobj) = mpd_qncopy(DecAddr(tmp));
-	if (DecAddr(newobj) == NULL) {
-		PyErr_NoMemory();
-		Py_DECREF(tmp);
-		return NULL;
-	}
-
-	Py_DECREF(tmp);
-	return (PyObject *)newobj;
-}
-
-static PyObject *
-PyDecContext_CreateDecimal(PyObject *self, PyObject *args)
-{
-	PyObject *v = NULL;
-	mpd_context_t *ctx;
-
-	if (!PyArg_ParseTuple(args, "|O", &v)) {
-		return NULL;
-	}
-
-	if (v == NULL) {
-		v = PyLong_FromLong(0);
-		Py_DECREF(v);
-	}
-
-	ctx = CtxAddr(self);
-
-	if (PyDec_Check(v)) {
-		return dec_apply(v, ctx);
-	}
-	else if (PyUnicode_Check(v)) {
-		return _PyDec_FromUnicode(v, ctx);
-	}
-	else if (PyLong_Check(v)) {
-		return _PyDec_FromLong(v, ctx);
-	}
-	else if (PyTuple_Check(v)) {
-		return _PyDec_FromTuple(v, ctx);
-	}
-	else {
-		PyErr_Format(PyExc_TypeError, "conversion from %s to Decimal is"
-		             " not supported", v->ob_type->tp_name);
-		return NULL;
-	}
-}
-
-static PyObject *
-_PyDec_FromFloat_Max(PyObject *self, PyObject *v)
-{
-	PyObject *result, *tmp;
-	PyObject *n, *d, *n_d;
-	mpd_ssize_t k;
-	double x;
-	int sign;
-	mpd_t *d1, *d2;
-	uint32_t status = 0;
-	mpd_context_t *ctx, maxctx;
-
-
-	CURRENT_CONTEXT_ADDR(ctx);
-	if (PyLong_Check(v)) {
-		return _PyDec_FromLong_Max(v, ctx);
-	}
-
-	x = PyFloat_AsDouble(v);
-	if (x == -1.0 && PyErr_Occurred()) {
-		return NULL;
-	}
-	sign = (copysign(1.0, x) == 1.0) ? 0 : 1;
-
-	if (Py_IS_NAN(x) || Py_IS_INFINITY(x)) {
-		result = PyObject_CallObject(self, NULL);
-		if (result == NULL) {
-			return NULL;
-		}
-		if (Py_IS_NAN(x)) {
-			/* decimal.py calls repr(float(+-nan)),
-			 * which always gives a positive result */
-			mpd_setspecial(DecAddr(result), MPD_POS, MPD_NAN);
-		}
-		else {
-			mpd_setspecial(DecAddr(result), sign, MPD_INF);
-		}
-		return result;
-	}
-
-	if ((tmp = PyObject_CallMethod(v, "__abs__", NULL)) == NULL) {
-		return NULL;
-	}
-	n_d = PyObject_CallMethod(tmp, "as_integer_ratio", NULL);
-	Py_DECREF(tmp);
-	if (n_d == NULL) {
-		return NULL;
-	}
-	if ((n = PyTuple_GetItem(n_d, 0)) == NULL) {
-		Py_DECREF(n_d);
+	CURRENT_CONTEXT(ctxobj);
+	if (!PyArg_ParseTuple(args, "|OO", &v, &ctxobj)) {
 		return NULL;
 	}
-	if ((d = PyTuple_GetItem(n_d, 1)) == NULL) {
-		Py_DECREF(n_d);
-		return NULL;
+
+	if (v == NULL) {
+		v = PyLong_FromLong(0);
+		Py_DECREF(v);
 	}
 
+	CONTEXT_CHECK_VA(ctxobj);
+	ctx = CtxAddr(ctxobj);
 
-	if ((tmp = PyObject_CallMethod(d, "bit_length", NULL)) == NULL) {
-		Py_DECREF(n_d);
-		return NULL;
+	if (PyDec_Check(v)) {
+		Py_INCREF(v);
+		return v;
 	}
-	k = PyLong_AsMpdSsize(tmp);
-	Py_DECREF(tmp);
-	if (k == MPD_SSIZE_MAX) {
-		Py_DECREF(n_d);
-		return NULL;
+	else if (PyUnicode_Check(v)) {
+		return _PyDec_FromUnicode_Max(v, ctx);
 	}
-	k--;
-
-	if ((d1 = mpd_qnew()) == NULL) { 
-		Py_DECREF(n_d);
-		return NULL;
+	else if (PyLong_Check(v)) {
+		return _PyDec_FromLong_Max(v, ctx);
 	}
-	if ((d2 = mpd_qnew()) == NULL) { 
-		mpd_del(d1);
-		Py_DECREF(n_d);
+	else if (PyTuple_Check(v)) {
+		return _PyDec_FromTuple_Max(v, ctx);
+	}
+#if PY_VERSION_HEX >= 0x03020000
+	else if (PyFloat_Check(v)) {
+		if (dec_addstatus(ctx, MPD_Float_operation)) {
+			return NULL;
+		}
+		return _PyDec_FromFloat_Max((PyObject *)&PyDec_Type, v);
+	}
+#endif
+	else {
+		PyErr_Format(PyExc_TypeError,
+		    "conversion from %s to Decimal is not supported.",
+		    v->ob_type->tp_name);
 		return NULL;
 	}
+}
 
-	mpd_maxcontext(&maxctx);
-	mpd_qset_uint(d1, 5, &maxctx, &status);
-	mpd_qset_ssize(d2, k, &maxctx, &status);
-	mpd_qpow(d1, d1, d2, &maxctx, &status);
-	if (dec_addstatus(ctx, status)) {
-		mpd_del(d1);
-		mpd_del(d2);
-		Py_DECREF(n_d);
-		return NULL;
+static PyObject *
+dec_subtype_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+{
+	PyObject *tmp, *newobj;
+
+	assert(PyType_IsSubtype(type, &PyDec_Type));
+	tmp = dec_new(&PyDec_Type, args, kwds);
+	if (tmp == NULL) {
+		return NULL; /* GCOV_UNLIKELY */
 	}
 
-	tmp = Py_BuildValue("(O)", n);
-	result = PyObject_CallObject(self, tmp);
-	Py_DECREF(tmp);
-	Py_DECREF(n_d);
-	if (result == NULL) {
-		mpd_del(d1);
-		mpd_del(d2);
-		return NULL;
+	newobj = type->tp_alloc(type, 0);
+	if (newobj == NULL) {
+		Py_DECREF(tmp); /* GCOV_UNLIKELY */
+		return NULL; /* GCOV_UNLIKELY */
 	}
 
-	/* result = n * 5**k */
-	mpd_qmul(DecAddr(result), DecAddr(result), d1, &maxctx, &status);
-	mpd_del(d1);
-	mpd_del(d2);
-	if (dec_addstatus(ctx, status)) {
-		Py_DECREF(result);
-		return NULL;
+	DecAddr(newobj) = mpd_qncopy(DecAddr(tmp));
+	if (DecAddr(newobj) == NULL) {
+		PyErr_NoMemory(); /* GCOV_UNLIKELY */
+		Py_DECREF(tmp); /* GCOV_UNLIKELY */
+		return NULL; /* GCOV_UNLIKELY */
 	}
-	/* result = +- n * 5**k * 10**-k */
-	mpd_set_sign(DecAddr(result), sign);
-	DecAddr(result)->exp = -k;
 
-	return result;
+	Py_DECREF(tmp);
+	return (PyObject *)newobj;
 }
 
 static PyObject *
-PyDecContext_FromFloat(PyObject *self, PyObject *v)
+PyDecContext_CreateDecimal(PyObject *self, PyObject *args)
 {
-	PyObject *result;
+	PyObject *v = NULL;
 	mpd_context_t *ctx;
-	uint32_t status = 0;
-
-	ctx = CtxAddr(self);
 
-	result = _PyDec_FromFloat_Max((PyObject *)&PyDec_Type, v);
-	if (result == NULL) {
+	if (!PyArg_ParseTuple(args, "|O", &v)) {
 		return NULL;
 	}
 
-	mpd_qfinalize(DecAddr(result), ctx, &status);
-	if (dec_addstatus(ctx, status)) {
-		Py_DECREF(result);
-		return NULL;
+	if (v == NULL) {
+		v = PyLong_FromLong(0);
+		Py_DECREF(v);
 	}
 
-	return result;
+	ctx = CtxAddr(self);
+
+	if (PyDec_Check(v)) {
+		return dec_apply(v, ctx);
+	}
+	else if (PyUnicode_Check(v)) {
+		return _PyDec_FromUnicode(v, ctx);
+	}
+	else if (PyLong_Check(v)) {
+		return _PyDec_FromLong(v, ctx);
+	}
+	else if (PyTuple_Check(v)) {
+		return _PyDec_FromTuple(v, ctx);
+	}
+#if PY_VERSION_HEX >= 0x03020000
+	else if (PyFloat_Check(v)) {
+		if (dec_addstatus(ctx, MPD_Float_operation)) {
+			return NULL;
+		}
+		return PyDecContext_FromFloat(self, v);
+	}
+#endif
+	else {
+		PyErr_Format(PyExc_TypeError,
+		    "conversion from %s to Decimal is not supported.",
+		    v->ob_type->tp_name);
+		return NULL;
+	}
 }
 
 
@@ -2566,50 +2643,52 @@
 	if (mpd_isspecial(self->dec)) {
 		if (mpd_isnan(self->dec)) {
 			PyErr_SetString(PyExc_ValueError,
-			                "cannot convert NaN to integer");
+			    "cannot convert NaN to integer.");
 		}
 		else {
 			PyErr_SetString(PyExc_OverflowError,
-			                "cannot convert Infinity to integer");
+			    "cannot convert Infinity to integer.");
 		}
 		return NULL;
 	}
 
 	if ((intdec = mpd_qnew()) == NULL) {
-		PyErr_NoMemory();
-		return NULL;
+		PyErr_NoMemory(); /* GCOV_UNLIKELY */
+		return NULL; /* GCOV_UNLIKELY */
 	}
 	workctx = *ctx;
 	workctx.round = round;
 	mpd_qround_to_int(intdec, self->dec, &workctx, &status);
 	if (dec_addstatus(ctx, status)) {
-		mpd_del(intdec);
-		return NULL;
+		mpd_del(intdec); /* GCOV_UNLIKELY */
+		return NULL; /* GCOV_UNLIKELY */
 	}
 
 	maxsize = mpd_sizeinbase(intdec, PyLong_BASE);
 	if (maxsize > PY_SSIZE_T_MAX) {
-		PyErr_NoMemory();
-		mpd_del(intdec);
-		return NULL;
+		PyErr_NoMemory(); /* GCOV_UNLIKELY */
+		mpd_del(intdec); /* GCOV_UNLIKELY */
+		return NULL; /* GCOV_UNLIKELY */
 	}
 	if ((newob = _PyLong_New(maxsize)) == NULL) {
-		mpd_del(intdec);
-		return NULL;
+		mpd_del(intdec); /* GCOV_UNLIKELY */
+		return NULL; /* GCOV_UNLIKELY */
 	}
 
 	status = 0;
 #if PYLONG_BITS_IN_DIGIT == 30
-	n = mpd_qexport_u32(newob->ob_digit, maxsize, PyLong_BASE, intdec, &status);
+	n = mpd_qexport_u32(newob->ob_digit, maxsize, PyLong_BASE,
+	                    intdec, &status);
 #elif PYLONG_BITS_IN_DIGIT == 15
-	n = mpd_qexport_u16(newob->ob_digit, maxsize, PyLong_BASE, intdec, &status);
+	n = mpd_qexport_u16(newob->ob_digit, maxsize, PyLong_BASE,
+	                    intdec, &status);
 #else
-  #error "PYLONG_BITS_IN_DIGIT should be 15 or 30"
+  #error "PYLONG_BITS_IN_DIGIT should be 15 or 30."
 #endif
 	if (dec_addstatus(ctx, status)) {
-		Py_DECREF((PyObject *) newob);
-		mpd_del(intdec);
-		return NULL;
+		Py_DECREF((PyObject *) newob); /* GCOV_UNLIKELY */
+		mpd_del(intdec); /* GCOV_UNLIKELY */
+		return NULL; /* GCOV_UNLIKELY */
 	}
 
 	i = n;
@@ -2635,12 +2714,14 @@
 	return _PyInt_FromDec(self, ctx, MPD_ROUND_DOWN);
 }
 
+#if PY_VERSION_HEX < 0x03020000
 /* Caller guarantees type */
 static PyObject *
 PyLong_FromDecCtx(PyDecObject *self, mpd_context_t *ctx)
 {
 	return _PyInt_FromDec(self, ctx, MPD_ROUND_DOWN);
 }
+#endif
 
 /* Caller guarantees type. Uses default module context. */
 static PyObject *
@@ -2671,11 +2752,11 @@
 	}
 	if (!PyDecContext_Check(ctxobj)) {
 		PyErr_SetString(PyExc_TypeError,
-		                "optional second arg must be a context");
+		    "optional second arg must be a context.");
 		return NULL;
 	}
 	if ((result = dec_alloc()) == NULL) {
-		return NULL;
+		return NULL; /* GCOV_UNLIKELY */
 	}
 
 	ctx = CtxAddr(ctxobj);
@@ -2686,8 +2767,8 @@
 
 	mpd_qround_to_int(result->dec, DecAddr(self), &workctx, &status);
 	if (dec_addstatus(ctx, status)) {
-		Py_DECREF(result);
-		return NULL;
+		Py_DECREF(result); /* GCOV_UNLIKELY */
+		return NULL; /* GCOV_UNLIKELY */
 	}
 
 	return (PyObject *)result;
@@ -2712,11 +2793,11 @@
 	}
 	if (!PyDecContext_Check(ctxobj)) {
 		PyErr_SetString(PyExc_TypeError,
-		                "optional second arg must be a context");
+		    "optional second arg must be a context.");
 		return NULL;
 	}
 	if ((result = dec_alloc()) == NULL) {
-		return NULL;
+		return NULL; /* GCOV_UNLIKELY */
 	}
 
 	ctx = CtxAddr(ctxobj);
@@ -2749,8 +2830,8 @@
 
 
 	if ((selfcpy = mpd_qncopy(DecAddr(self))) == NULL) {
-		PyErr_NoMemory();
-		goto error;
+		PyErr_NoMemory(); /* GCOV_UNLIKELY */
+		goto error; /* GCOV_UNLIKELY */
 	}
 
 	o_sign = Py_BuildValue("i", mpd_sign(DecAddr(self)));
@@ -2758,10 +2839,10 @@
 
 	if (mpd_isinfinite(selfcpy)) {
 		if ((o_exp = Py_BuildValue("s", "F")) == NULL) {
-			goto error;
+			goto error; /* GCOV_UNLIKELY */
 		}
 		if ((o_coeff = PyTuple_New(0)) == NULL) {
-			goto error;
+			goto error; /* GCOV_UNLIKELY */
 		}
 	}
 	else {
@@ -2784,13 +2865,13 @@
 			mpd_clear_flags(selfcpy);
 			intstring = mpd_to_sci(selfcpy, 1);
 			if (intstring == NULL) {
-				PyErr_NoMemory();
-				goto error;
+				PyErr_NoMemory(); /* GCOV_UNLIKELY */
+				goto error; /* GCOV_UNLIKELY */
 			}
 
 			intlen = strlen(intstring);
 			if ((o_coeff = PyTuple_New(intlen)) == NULL) {
-				goto error;
+				goto error; /* GCOV_UNLIKELY */
 			}
 
 			for (i = 0; i < intlen; i++) {
@@ -2801,13 +2882,13 @@
 		}
 		else {
 			if ((o_coeff = PyTuple_New(0)) == NULL) {
-				goto error;
+				goto error; /* GCOV_UNLIKELY */
 			}
 		}
 	}
 
 	if ((o_tuple = PyTuple_New(3)) == NULL) {
-		goto error;
+		goto error; /* GCOV_UNLIKELY */
 	}
 	PyTuple_SET_ITEM(o_tuple, 0, o_sign);
 	PyTuple_SET_ITEM(o_tuple, 1, o_coeff);
@@ -2819,11 +2900,11 @@
 	if (intstring) mpd_free(intstring);
 	return o_tuple;
 
-error:
-	if (o_sign) { Py_DECREF(o_sign); }
-	if (o_coeff) { Py_DECREF(o_coeff); }
-	if (o_exp) { Py_DECREF(o_exp); }
-	goto out;
+error: /* GCOV_UNLIKELY */
+	if (o_sign) { Py_DECREF(o_sign); } /* GCOV_UNLIKELY */
+	if (o_coeff) { Py_DECREF(o_coeff); } /* GCOV_UNLIKELY */
+	if (o_exp) { Py_DECREF(o_exp); } /* GCOV_UNLIKELY */
+	goto out; /* GCOV_UNLIKELY */
 }
 
 /* Caller guarantees type. Uses default module context. */
@@ -2836,8 +2917,8 @@
 	CURRENT_CONTEXT(c);
 	res = mpd_to_sci(self->dec, CtxCaps(c));
 	if (res == NULL) {
-		PyErr_NoMemory();
-		return NULL;
+		PyErr_NoMemory(); /* GCOV_UNLIKELY */
+		return NULL; /* GCOV_UNLIKELY */
 	}
 
 	s = PyUnicode_FromString(res);
@@ -2861,17 +2942,17 @@
 	CURRENT_CONTEXT(c);
 	cp = mpd_to_sci(self->dec, CtxCaps(c));
 	if (cp == NULL) {
-		PyErr_NoMemory();
-		return NULL;
+		PyErr_NoMemory(); /* GCOV_UNLIKELY */
+		return NULL; /* GCOV_UNLIKELY */
 	}
 	declen = strlen(cp);
 
 	err = 0;
 	cp = mpd_realloc(cp, (mpd_size_t)(declen+dtaglen+3), sizeof *cp, &err);
 	if (err) {
-		mpd_free(cp);
-		PyErr_NoMemory();
-		return NULL;
+		mpd_free(cp); /* GCOV_UNLIKELY */
+		PyErr_NoMemory(); /* GCOV_UNLIKELY */
+		return NULL; /* GCOV_UNLIKELY */
 	}
 
 	memmove(cp+dtaglen, cp, declen);
@@ -2893,7 +2974,7 @@
 	PyObject *f, *s;
 
 	if ((s = dec_str(self)) == NULL) {
-		return NULL;
+		return NULL; /* GCOV_UNLIKELY */
 	}
 
 	f = PyFloat_FromString(s);
@@ -2924,19 +3005,19 @@
 
 		if (!PyLong_Check(x)) {
 			PyErr_SetString(PyExc_TypeError,
-			                "optional arg must be an integer");
+			    "optional arg must be an integer.");
 			return NULL;
 		}
 
 		y = PyLong_AsMpdSsize(x);
-		if (y == MPD_SSIZE_MAX || y == MPD_SSIZE_MIN) {
+		if (PyErr_Occurred()) {
 			return NULL;
 		}
 		if ((result = dec_alloc()) == NULL) {
-			return NULL;
+			return NULL; /* GCOV_UNLIKELY */
 		}
 
-		q.exp = -y;
+		q.exp = (y == MPD_SSIZE_MIN) ? MPD_SSIZE_MAX : -y;
 		mpd_qquantize(result->dec, a->dec, &q, ctx, &status);
 		if (dec_addstatus(ctx, status)) {
 			Py_DECREF(result);
@@ -2974,45 +3055,46 @@
 	}
 
 	if (PyBytes_Check(fmtarg)) {
-		fmt = fmtarg;
+		fmt = fmtarg; /* GCOV_NOT_REACHED */
 	}
 	else if (PyUnicode_Check(fmtarg)) {
 		if ((fmt = PyUnicode_AsUTF8String(fmtarg)) == NULL) {
-			return NULL;
+			return NULL; /* GCOV_UNLIKELY */
 		}
 	}
 	else {
-		PyErr_SetString(PyExc_TypeError, "format requires bytes or "
-		                                 "unicode arg");
+		PyErr_SetString(PyExc_TypeError,
+		    "format requires bytes or unicode arg.");
 		return NULL;
 	}
 
 	if (!mpd_parse_fmt_str(&spec, PyBytes_AS_STRING(fmt),
 	                       CtxCaps(ctxobj))) {
-		PyErr_SetString(PyExc_ValueError, "invalid format string");
+		PyErr_SetString(PyExc_ValueError,
+		    "invalid format string.");
 		goto finish;
 	}
 	if (override) {
 		if (!PyDict_Check(override)) {
-			PyErr_SetString(PyExc_TypeError, "optional argument "
-			                "must be a dict");
+			PyErr_SetString(PyExc_TypeError,
+			    "optional argument must be a dict.");
 			goto finish;
 		}
 		if ((dot = PyDict_GetItemString(override, "decimal_point"))) {
 			if ((dot = PyUnicode_AsUTF8String(dot)) == NULL) {
-				goto finish;
+				goto finish; /* GCOV_UNLIKELY */
 			}
 			spec.dot = PyBytes_AS_STRING(dot);
 		}
 		if ((sep = PyDict_GetItemString(override, "thousands_sep"))) {
 			if ((sep = PyUnicode_AsUTF8String(sep)) == NULL) {
-				goto finish;
+				goto finish; /* GCOV_UNLIKELY */
 			}
 			spec.sep = PyBytes_AS_STRING(sep);
 		}
 		if ((grouping = PyDict_GetItemString(override, "grouping"))) {
 			if ((grouping = PyUnicode_AsUTF8String(grouping)) == NULL) {
-				goto finish;
+				goto finish; /* GCOV_UNLIKELY */
 			}
 			spec.grouping = PyBytes_AS_STRING(grouping);
 		}
@@ -3020,38 +3102,38 @@
 	else {
 		n = strlen(spec.dot);
 		if (n > 1 || (n == 1 && !isascii((uchar)spec.dot[0]))) {
-			n = mbstowcs(buf, spec.dot, 2);
-			if (n != 1) {
-				PyErr_SetString(PyExc_ValueError,
-				      "invalid decimal point or unsupported "
-				      "combination of LC_CTYPE and LC_NUMERIC");
-				goto finish;
+			n = mbstowcs(buf, spec.dot, 2); /* GCOV_UNLIKELY */
+			if (n != 1) { /* GCOV_UNLIKELY */
+				PyErr_SetString(PyExc_ValueError, /* GCOV_UNLIKELY */
+				    "invalid decimal point or unsupported "
+				    "combination of LC_CTYPE and LC_NUMERIC.");
+				goto finish; /* GCOV_UNLIKELY */
 			}
-			if ((tmp = PyUnicode_FromWideChar(buf, n)) == NULL) {
-				goto finish;
+			if ((tmp = PyUnicode_FromWideChar(buf, n)) == NULL) { /* GCOV_UNLIKELY */
+				goto finish; /* GCOV_UNLIKELY */
 			}
-			if ((dot = PyUnicode_AsUTF8String(tmp)) == NULL) {
-				Py_DECREF(tmp);
-				goto finish;
+			if ((dot = PyUnicode_AsUTF8String(tmp)) == NULL) { /* GCOV_UNLIKELY */
+				Py_DECREF(tmp); /* GCOV_UNLIKELY */
+				goto finish; /* GCOV_UNLIKELY */
 			}
-			spec.dot = PyBytes_AS_STRING(dot);
-			Py_DECREF(tmp);
+			spec.dot = PyBytes_AS_STRING(dot); /* GCOV_UNLIKELY */
+			Py_DECREF(tmp); /* GCOV_UNLIKELY */
 		}
 		n = strlen(spec.sep);
 		if (n > 1 || (n == 1 && !isascii((uchar)spec.sep[0]))) {
 			n = mbstowcs(buf, spec.sep, 2);
 			if (n != 1) {
-				PyErr_SetString(PyExc_ValueError,
-				      "invalid thousands separator or unsupported "
-				      "combination of LC_CTYPE and LC_NUMERIC");
-				goto finish;
+				PyErr_SetString(PyExc_ValueError, /* GCOV_UNLIKELY */
+				    "invalid thousands separator or unsupported "
+				    "combination of LC_CTYPE and LC_NUMERIC.");
+				goto finish; /* GCOV_UNLIKELY */
 			}
 			if ((tmp = PyUnicode_FromWideChar(buf, n)) == NULL) {
-				goto finish;
+				goto finish; /* GCOV_UNLIKELY */
 			}
 			if ((sep = PyUnicode_AsUTF8String(tmp)) == NULL) {
-				Py_DECREF(tmp);
-				goto finish;
+				Py_DECREF(tmp); /* GCOV_UNLIKELY */
+				goto finish; /* GCOV_UNLIKELY */
 			}
 			spec.sep = PyBytes_AS_STRING(sep);
 			Py_DECREF(tmp);
@@ -3399,15 +3481,15 @@
 	CONVERT_BINOP(v, w, &a, &b, ctx);
 
 	if ((q = dec_alloc()) == NULL) {
-		Py_DECREF(a);
-		Py_DECREF(b);
-		return NULL;
+		Py_DECREF(a); /* GCOV_UNLIKELY */
+		Py_DECREF(b); /* GCOV_UNLIKELY */
+		return NULL; /* GCOV_UNLIKELY */
 	}
 	if ((r = dec_alloc()) == NULL) {
-		Py_DECREF(a);
-		Py_DECREF(b);
-		Py_DECREF(q);
-		return NULL;
+		Py_DECREF(a); /* GCOV_UNLIKELY */
+		Py_DECREF(b); /* GCOV_UNLIKELY */
+		Py_DECREF(q); /* GCOV_UNLIKELY */
+		return NULL; /* GCOV_UNLIKELY */
 	}
 
 	mpd_qdivmod(q->dec, r->dec, a->dec, b->dec, ctx, &status);
@@ -3442,7 +3524,7 @@
 	}
 
 	if ((result = dec_alloc()) == NULL) {
-		return NULL;
+		return NULL; /* GCOV_UNLIKELY */
 	}
  
 	if (c == NULL) {
@@ -3526,13 +3608,13 @@
 
 	CURRENT_CONTEXT_ADDR(ctx);
 	if ((result = dec_alloc()) == NULL) {
-		return NULL;
+		return NULL; /* GCOV_UNLIKELY */
 	}
 
 	mpd_qcopy_abs(result->dec, a->dec, &status);
 	if (dec_addstatus(ctx, status)) {
-		Py_DECREF(result);
-		return NULL;
+		Py_DECREF(result); /* GCOV_UNLIKELY */
+		return NULL; /* GCOV_UNLIKELY */
 	}
 
 	return (PyObject *) result;
@@ -3548,13 +3630,13 @@
 
 	CURRENT_CONTEXT_ADDR(ctx);
 	if ((result = dec_alloc()) == NULL) {
-		return NULL;
+		return NULL; /* GCOV_UNLIKELY */
 	}
 
 	mpd_qcopy_negate(result->dec, a->dec, &status);
 	if (dec_addstatus(ctx, status)) {
-		Py_DECREF(result);
-		return NULL;
+		Py_DECREF(result); /* GCOV_UNLIKELY */
+		return NULL; /* GCOV_UNLIKELY */
 	}
 
 	return (PyObject *) result;
@@ -3578,17 +3660,17 @@
 	CONVERT_BINOP_SET(v, w, &a, &b, ctx);
 
 	if ((result = dec_alloc()) == NULL) {
-		Py_DECREF(a);
-		Py_DECREF(b);
-		return NULL;
+		Py_DECREF(a); /* GCOV_UNLIKELY */
+		Py_DECREF(b); /* GCOV_UNLIKELY */
+		return NULL; /* GCOV_UNLIKELY */
 	}
 
 	mpd_qcopy_sign(result->dec, a->dec, b->dec, &status);
 	Py_DECREF(a);
 	Py_DECREF(b);
 	if (dec_addstatus(ctx, status)) {
-		Py_DECREF(result);
-		return NULL;
+		Py_DECREF(result); /* GCOV_UNLIKELY */
+		return NULL; /* GCOV_UNLIKELY */
 	}
 
 	return (PyObject *) result;
@@ -3656,15 +3738,15 @@
 	CONVERT_BINOP_SET(v, w, &a, &b, ctx);
 
 	if ((q = dec_alloc()) == NULL) {
-		Py_DECREF(a);
-		Py_DECREF(b);
-		return NULL;
+		Py_DECREF(a); /* GCOV_UNLIKELY */
+		Py_DECREF(b); /* GCOV_UNLIKELY */
+		return NULL; /* GCOV_UNLIKELY */
 	}
 	if ((r = dec_alloc()) == NULL) {
-		Py_DECREF(a);
-		Py_DECREF(b);
-		Py_DECREF(q);
-		return NULL;
+		Py_DECREF(a); /* GCOV_UNLIKELY */
+		Py_DECREF(b); /* GCOV_UNLIKELY */
+		Py_DECREF(q); /* GCOV_UNLIKELY */
+		return NULL; /* GCOV_UNLIKELY */
 	}
 
 	mpd_qdivmod(q->dec, r->dec, a->dec, b->dec, ctx, &status);
@@ -3733,8 +3815,8 @@
 
 	s = mpd_to_sci(a->dec, CtxCaps(c));
 	if (s == NULL) {
-		PyErr_NoMemory();
-		return NULL;
+		PyErr_NoMemory(); /* GCOV_UNLIKELY */
+		return NULL; /* GCOV_UNLIKELY */
 	}
 
 	result = PyUnicode_FromString(s);
@@ -3758,8 +3840,8 @@
 
 	s = mpd_to_eng(a->dec, CtxCaps(c));
 	if (s == NULL) {
-		PyErr_NoMemory();
-		return NULL;
+		PyErr_NoMemory(); /* GCOV_UNLIKELY */
+		return NULL; /* GCOV_UNLIKELY */
 	}
 
 	result = PyUnicode_FromString(s);
@@ -3779,7 +3861,7 @@
 	int r;
 
 	CURRENT_CONTEXT_ADDR(ctx);
-	CONVERT_BINOP(v, w, &a, &b, ctx);
+	CONVERT_BINOP_CMP(v, w, &a, &b, op, ctx);
 
 	a_issnan = mpd_issnan(a->dec);
 	b_issnan = mpd_issnan(b->dec);
@@ -3823,6 +3905,7 @@
 	return PyBool_FromLong(r);
 }
 
+#if PY_VERSION_HEX < 0x03020000
 /* Always uses the module context */
 static long
 dec_hash(PyObject *v)
@@ -3850,25 +3933,25 @@
 	long result;
 
 	if ((a = dec_alloc()) == NULL) {
-		PyErr_NoMemory();
-		return -1;
+		PyErr_NoMemory(); /* GCOV_UNLIKELY */
+		return -1; /* GCOV_UNLIKELY */
 	}
-	if (!mpd_qcopy(a->dec, ((PyDecObject *) v)->dec, &status)) {
-		PyErr_NoMemory();
-		result = -1;
-		goto finish;
+	if (!mpd_qcopy(a->dec, DecAddr(v), &status)) {
+		PyErr_NoMemory(); /* GCOV_UNLIKELY */
+		result = -1; /* GCOV_UNLIKELY */
+		goto finish; /* GCOV_UNLIKELY */
 	}
 
 	if (mpd_isspecial(a->dec)) {
 		if (mpd_isnan(a->dec)) {
 			PyErr_SetString(PyExc_ValueError,
-			                "cannot hash a NaN value");
+			    "cannot hash a NaN value");
 			result = -1;
 		}
 		else {
 			if ((obj = dec_str(a)) == NULL) {
-				result = -1;
-				goto finish;
+				result = -1; /* GCOV_UNLIKELY */
+				goto finish; /* GCOV_UNLIKELY */
 			}
 			result = PyObject_Hash(obj);
 		}
@@ -3880,16 +3963,16 @@
 		PyObject *ctxobj = current_context();
 		mpd_context_t *ctx;
 		if (ctxobj == NULL) {
-			result = -1;
-			goto finish;
+			result = -1; /* GCOV_UNLIKELY */
+			goto finish; /* GCOV_UNLIKELY */
 		}
 		ctx = CtxAddr(ctxobj);
 		mpd_maxcontext(&maxcontext);
 
 		if ((tmp = mpd_qnew()) == NULL) {
-			PyErr_NoMemory();
-			result = -1;
-			goto finish;
+			PyErr_NoMemory(); /* GCOV_UNLIKELY */
+			result = -1; /* GCOV_UNLIKELY */
+			goto finish; /* GCOV_UNLIKELY */
 		}
 
 		/* clobbering a function scope object */
@@ -3900,15 +3983,15 @@
 		mpd_qmul(a->dec, a->dec, tmp, &maxcontext, &status);
 
 		if (status&MPD_Errors) {
-			if (dec_addstatus(ctx, status)) {
-				result = -1;
-				goto finish;
+			if (dec_addstatus(ctx, status)) { /* GCOV_UNLIKELY */
+				result = -1; /* GCOV_UNLIKELY */
+				goto finish; /* GCOV_UNLIKELY */
 			}
 		}
 
 		if ((obj = PyLong_FromDecCtx(a, &maxcontext)) == NULL) {
-			result = -1;
-			goto finish;
+			result = -1; /* GCOV_UNLIKELY */
+			goto finish; /* GCOV_UNLIKELY */
 		}
 		result = PyObject_Hash(obj);
 	}
@@ -3924,13 +4007,13 @@
 
 		mpd_qshiftr_inplace(a->dec, tz);
 		a->dec->exp = 0;
-		a->dec->flags = MPD_POS;
+		mpd_set_flags(a->dec, MPD_POS);
 
 		cp = mpd_to_sci(a->dec, 1);
 		obj = Py_BuildValue("(i"CONV_mpd_ssize_t"s)", sign, exp, cp);
 		if (obj == NULL) {
-			result = -1;
-			goto finish;
+			result = -1; /* GCOV_UNLIKELY */
+			goto finish; /* GCOV_UNLIKELY */
 		}
 		result =  PyObject_Hash(obj);
 	}
@@ -3943,6 +4026,120 @@
 	if (cp) mpd_free(cp);
 	return result;
 }
+#else
+/* Always uses the module context */
+static Py_hash_t
+dec_hash(PyObject *v)
+{
+#if defined(CONFIG_64) && _PyHASH_BITS == 61
+	/* 2**61 - 1 */
+	mpd_uint_t p_data[1] = {2305843009213693951ULL};
+	mpd_t p = {MPD_POS|MPD_STATIC|MPD_CONST_DATA, 0, 19, 1, 1, p_data};
+	/* Inverse of 10 modulo p */
+	mpd_uint_t inv10_p_data[2] = {2075258708292324556ULL};
+	mpd_t inv10_p = {MPD_POS|MPD_STATIC|MPD_CONST_DATA,
+	                 0, 19, 1, 1, inv10_p_data};
+#elif defined(CONFIG_32) && _PyHASH_BITS == 31
+	/* 2**31 - 1 */
+	mpd_uint_t p_data[2] = {147483647UL, 2};
+	mpd_t p = {MPD_POS|MPD_STATIC|MPD_CONST_DATA, 0, 10, 2, 2, p_data};
+	/* Inverse of 10 modulo p */
+	mpd_uint_t inv10_p_data[2] = {503238553UL, 1};
+	mpd_t inv10_p = {MPD_POS|MPD_STATIC|MPD_CONST_DATA,
+	                 0, 10, 2, 2, inv10_p_data};
+#else
+	#error "No valid combination of CONFIG_64, CONFIG_32 and _PyHASH_BITS."
+#endif
+	const Py_hash_t py_hash_inf = 314159;
+	const Py_hash_t py_hash_nan = 0;
+	mpd_uint_t ten_data[1] = {10};
+	mpd_t ten = {MPD_POS|MPD_STATIC|MPD_CONST_DATA,
+	             0, 2, 1, 1, ten_data};
+	Py_hash_t result;
+	mpd_t *exp_hash = NULL;
+	mpd_t *tmp = NULL;
+	mpd_ssize_t exp;
+	uint32_t status = 0;
+	mpd_context_t *ctx, maxcontext;
+	PyObject *ctxobj;
+
+
+	ctxobj = current_context();
+	if (ctxobj == NULL) {
+		return -1; /* GCOV_UNLIKELY */
+	}
+	ctx = CtxAddr(ctxobj);
+
+	if (mpd_isspecial(DecAddr(v))) {
+		if (mpd_issnan(DecAddr(v))) {
+			return value_error_int(
+			    "Cannot hash a signaling NaN value.");
+		}
+		else if (mpd_isnan(DecAddr(v))) {
+			return py_hash_nan;
+		}
+		else {
+			return py_hash_inf * mpd_arith_sign(DecAddr(v));
+		}
+	}
+
+	mpd_maxcontext(&maxcontext);
+	if ((exp_hash = mpd_qnew()) == NULL) {
+		goto malloc_error; /* GCOV_UNLIKELY */
+	}
+	if ((tmp = mpd_qnew()) == NULL) {
+		goto malloc_error; /* GCOV_UNLIKELY */
+	}
+
+	/*
+	 * exp(v): exponent of v
+	 * int(v): coefficient of v
+	 */
+	exp = DecAddr(v)->exp;
+	if (exp >= 0) {
+		/* 10**exp(v) % p */
+		mpd_qsset_ssize(tmp, exp, &maxcontext, &status);
+		mpd_qpowmod(exp_hash, &ten, tmp, &p, &maxcontext, &status);
+	}
+	else {
+		/* inv10_p**(-exp(v)) % p */
+		mpd_qsset_ssize(tmp, -exp, &maxcontext, &status);
+		mpd_qpowmod(exp_hash, &inv10_p, tmp, &p, &maxcontext, &status);
+	}
+
+	/* hash = (int(v) * exp_hash) % p */
+	if (!mpd_qcopy(tmp, DecAddr(v), &status)) {
+		goto malloc_error; /* GCOV_UNLIKELY */
+	}
+	tmp->exp = 0;
+	mpd_set_positive(tmp);
+	mpd_qmul(tmp, tmp, exp_hash, &maxcontext, &status);
+	mpd_qrem(tmp, tmp, &p, &maxcontext, &status);
+
+	result = mpd_qget_ssize(tmp, &status);
+	result = mpd_ispositive(DecAddr(v)) ? result : -result;
+	result = (result == -1) ? -2 : result;
+
+	if (status != 0) {
+		status |= MPD_Invalid_operation; /* GCOV_UNLIKELY */
+		if (dec_addstatus(ctx, status)) { /* GCOV_UNLIKELY */
+			result = -1; /* GCOV_UNLIKELY */
+			goto finish; /* GCOV_UNLIKELY */
+		}
+	}
+
+
+finish:
+	if (exp_hash) mpd_del(exp_hash);
+	if (tmp) mpd_del(tmp);
+	return result;
+
+malloc_error: /* GCOV_UNLIKELY */
+	PyErr_NoMemory(); /* GCOV_UNLIKELY */
+	result = -1; /* GCOV_UNLIKELY */
+	goto finish; /* GCOV_UNLIKELY */
+}
+#endif
 
 static PyObject *
 dec_reduce(PyObject *self, PyObject *dummy UNUSED)
@@ -3950,7 +4147,7 @@
 	PyObject *newob, *mpd_str;
 
 	if ((mpd_str = dec_str((PyDecObject *)self)) == NULL) {
-		return NULL;
+		return NULL; /* GCOV_UNLIKELY */
 	}
 
 	newob = Py_BuildValue("O(N)", Py_TYPE(self), mpd_str);
@@ -3997,111 +4194,111 @@
 
 static PyMethodDef dec_methods [] =
 {
-	/* Unary arithmetic functions */
-	{ "abs", _DecOpt_mpd_qabs, METH_VARARGS, doc_abs },
-	{ "exp", _DecOpt_mpd_qexp, METH_VARARGS, doc_exp },
-	{ "invroot", _DecOpt_mpd_qinvroot, METH_VARARGS, doc_invroot },
-	{ "ln", _DecOpt_mpd_qln, METH_VARARGS, doc_ln },
-	{ "log10", _DecOpt_mpd_qlog10, METH_VARARGS, doc_log10 },
-	{ "minus", _DecOpt_mpd_qminus, METH_VARARGS, doc_minus },
-	{ "next_minus", _DecOpt_mpd_qnext_minus, METH_VARARGS, doc_next_minus },
-	{ "next_plus", _DecOpt_mpd_qnext_plus, METH_VARARGS, doc_next_plus },
-	{ "normalize", _DecOpt_mpd_qreduce, METH_VARARGS, doc_normalize }, /* alias for reduce */
-	{ "plus", _DecOpt_mpd_qplus, METH_VARARGS, doc_plus },
-	{ "reduce", _DecOpt_mpd_qreduce, METH_VARARGS, doc_reduce },
-	{ "to_integral", (PyCFunction)PyDec_ToIntegralValue, METH_VARARGS|METH_KEYWORDS, doc_to_integral },
-	{ "to_integral_exact", (PyCFunction)PyDec_ToIntegralExact, METH_VARARGS|METH_KEYWORDS, doc_to_integral_exact },
-	{ "to_integral_value", (PyCFunction)PyDec_ToIntegralValue, METH_VARARGS|METH_KEYWORDS, doc_to_integral_value },
-	{ "sqrt", _DecOpt_mpd_qsqrt, METH_VARARGS, doc_sqrt },
-
-	/* Binary arithmetic functions */
-	{ "add", _DecOpt_mpd_qadd, METH_VARARGS, doc_add },
-	{ "compare", _DecOpt_mpd_qcompare, METH_VARARGS, doc_compare },
-	{ "compare_signal", _DecOpt_mpd_qcompare_signal, METH_VARARGS, doc_compare_signal },
-	{ "div", _DecOpt_mpd_qdiv, METH_VARARGS, doc_div }, /* alias for divide */
-	{ "divide", _DecOpt_mpd_qdiv, METH_VARARGS, doc_divide },
-	{ "divide_int", _DecOpt_mpd_qdivint, METH_VARARGS, doc_divide_int },
-	{ "divint", _DecOpt_mpd_qdivint, METH_VARARGS, doc_divint }, /* alias for divide_int */
-	{ "divmod", _DecOpt_mpd_qdivmod, METH_VARARGS, doc_divmod },
-	{ "max", _DecOpt_mpd_qmax, METH_VARARGS, doc_max },
-	{ "max_mag", _DecOpt_mpd_qmax_mag, METH_VARARGS, doc_max_mag },
-	{ "min", _DecOpt_mpd_qmin, METH_VARARGS, doc_min },
-	{ "min_mag", _DecOpt_mpd_qmin_mag, METH_VARARGS, doc_min_mag },
-	{ "mul", _DecOpt_mpd_qmul, METH_VARARGS, doc_mul }, /* alias for multiply */
-	{ "multiply", _DecOpt_mpd_qmul, METH_VARARGS, doc_multiply },
-	{ "next_toward", _DecOpt_mpd_qnext_toward, METH_VARARGS, doc_next_toward },
-	{ "pow", _DecOpt_mpd_qpow, METH_VARARGS, doc_pow }, /* alias for power */
-	{ "power", _DecOpt_mpd_qpow, METH_VARARGS, doc_power },
-	{ "quantize", _DecOpt_mpd_qquantize, METH_VARARGS, doc_quantize },
-	{ "rem", _DecOpt_mpd_qrem, METH_VARARGS, doc_rem }, /* alias for remainder */
-	{ "remainder", _DecOpt_mpd_qrem, METH_VARARGS, doc_remainder },
-	{ "remainder_near", _DecOpt_mpd_qrem_near, METH_VARARGS, doc_remainder_near },
-	{ "sub", _DecOpt_mpd_qsub, METH_VARARGS, doc_sub }, /* alias for subtract */
-	{ "subtract", _DecOpt_mpd_qsub, METH_VARARGS, doc_subtract },
-
-	/* Ternary arithmetic functions */
-	{ "fma", _DecOpt_mpd_qfma, METH_VARARGS, doc_fma },
-	{ "powmod", _DecOpt_mpd_qpowmod, METH_VARARGS, doc_powmod },
-
-	/* Boolean functions, no context arg */
-	{ "is_canonical", _Dec_CFunc_mpd_iscanonical, METH_NOARGS, doc_is_canonical },
-	{ "is_finite", _Dec_CFunc_mpd_isfinite, METH_NOARGS, doc_is_finite },
-	{ "is_infinite", _Dec_CFunc_mpd_isinfinite, METH_NOARGS, doc_is_infinite },
-	{ "is_integer", _Dec_CFunc_mpd_isinteger, METH_NOARGS, doc_is_integer },
-	{ "is_nan", _Dec_CFunc_mpd_isnan, METH_NOARGS, doc_is_nan },
-	{ "is_qnan", _Dec_CFunc_mpd_isqnan, METH_NOARGS, doc_is_qnan },
-	{ "is_snan", _Dec_CFunc_mpd_issnan, METH_NOARGS, doc_is_snan },
-	{ "is_signed", _Dec_CFunc_mpd_issigned, METH_NOARGS, doc_is_signed },
-	{ "is_special", _Dec_CFunc_mpd_isspecial, METH_NOARGS, doc_is_special },
-	{ "is_zero", _Dec_CFunc_mpd_iszero, METH_NOARGS, doc_is_zero },
-
-	/* Boolean functions, optional context arg */
-	{ "is_normal", _DecOpt_mpd_isnormal, METH_VARARGS, doc_is_normal },
-	{ "is_subnormal", _DecOpt_mpd_issubnormal, METH_VARARGS, doc_is_subnormal },
-
-	/* Unary functions, no context arg */
-	{ "adjusted", _Dec_mpd_adjexp, METH_NOARGS, doc_adjusted },
-	{ "canonical", _Dec_canonical, METH_NOARGS, doc_canonical },
-	{ "copy_abs", _Dec_mpd_qcopy_abs, METH_NOARGS, doc_copy_abs },
-	{ "copy_negate", _Dec_mpd_qcopy_negate, METH_NOARGS, doc_copy_negate },
-	{ "radix", _Dec_mpd_radix, METH_NOARGS, doc_radix },
-	{ "sign", _Dec_mpd_sign, METH_NOARGS, doc_sign },
-
-	/* Unary functions, optional context arg */
-	{ "apply", PyDec_Apply, METH_VARARGS, doc_apply },
-	{ "logb", _DecOpt_mpd_qlogb, METH_VARARGS, doc_logb },
-	{ "logical_invert", _DecOpt_mpd_qinvert, METH_VARARGS, doc_logical_invert },
-	{ "number_class", _DecOpt_mpd_class, METH_VARARGS, doc_number_class },
-	{ "to_sci", _Dec_mpd_to_sci, METH_VARARGS, doc_to_sci }, /* alias for to_sci_string */
-	{ "to_sci_string", _Dec_mpd_to_sci, METH_VARARGS, doc_to_sci_string },
-	{ "to_eng", _Dec_mpd_to_eng, METH_VARARGS, doc_to_eng }, /* alias for to_eng_string */
-	{ "to_eng_string", _Dec_mpd_to_eng, METH_VARARGS, doc_to_eng_string },
-
-	/* Binary functions, optional context arg */
-	{ "compare_total", _DecOpt_mpd_compare_total, METH_VARARGS, doc_compare_total },
-	{ "compare_total_mag", _DecOpt_mpd_compare_total_mag, METH_VARARGS, doc_compare_total_mag },
-	{ "copy_sign", _Dec_mpd_qcopy_sign, METH_O, doc_copy_sign },
-	{ "logical_and", _DecOpt_mpd_qand, METH_VARARGS, doc_logical_and },
-	{ "logical_or", _DecOpt_mpd_qor, METH_VARARGS, doc_logical_or },
-	{ "logical_xor", _DecOpt_mpd_qxor, METH_VARARGS, doc_logical_xor },
-	{ "rotate", _DecOpt_mpd_qrotate, METH_VARARGS, doc_rotate },
-	{ "same_quantum", _Dec_mpd_same_quantum, METH_VARARGS, doc_same_quantum },
-	{ "scaleb", _DecOpt_mpd_qscaleb, METH_VARARGS, doc_scaleb },
-	{ "shift", _DecOpt_mpd_qshift, METH_VARARGS, doc_shift },
-
-	/* Miscellaneous */
-	{ "from_float", _PyDec_FromFloat_Max, METH_O|METH_CLASS, doc_from_float },
-	{ "as_tuple", PyDec_AsTuple, METH_NOARGS, doc_as_tuple },
-
-	/* Generic stuff */
-	{ "__copy__", dec_copy, METH_NOARGS, NULL },
-	{ "__deepcopy__", dec_copy, METH_VARARGS, NULL },
-	{ "__format__", dec_format, METH_VARARGS, NULL },
-	{ "__reduce__", dec_reduce, METH_NOARGS, NULL },
-	{ "__round__", PyDec_Round, METH_VARARGS, NULL },
-	{ "__trunc__", PyDec_Trunc, METH_NOARGS, NULL },
+  /* Unary arithmetic functions */
+  { "abs", _DecOpt_mpd_qabs, METH_VARARGS, doc_abs },
+  { "exp", _DecOpt_mpd_qexp, METH_VARARGS, doc_exp },
+  { "invroot", _DecOpt_mpd_qinvroot, METH_VARARGS, doc_invroot },
+  { "ln", _DecOpt_mpd_qln, METH_VARARGS, doc_ln },
+  { "log10", _DecOpt_mpd_qlog10, METH_VARARGS, doc_log10 },
+  { "minus", _DecOpt_mpd_qminus, METH_VARARGS, doc_minus },
+  { "next_minus", _DecOpt_mpd_qnext_minus, METH_VARARGS, doc_next_minus },
+  { "next_plus", _DecOpt_mpd_qnext_plus, METH_VARARGS, doc_next_plus },
+  { "normalize", _DecOpt_mpd_qreduce, METH_VARARGS, doc_normalize }, /* alias for reduce */
+  { "plus", _DecOpt_mpd_qplus, METH_VARARGS, doc_plus },
+  { "reduce", _DecOpt_mpd_qreduce, METH_VARARGS, doc_reduce },
+  { "to_integral", (PyCFunction)PyDec_ToIntegralValue, METH_VARARGS|METH_KEYWORDS, doc_to_integral },
+  { "to_integral_exact", (PyCFunction)PyDec_ToIntegralExact, METH_VARARGS|METH_KEYWORDS, doc_to_integral_exact },
+  { "to_integral_value", (PyCFunction)PyDec_ToIntegralValue, METH_VARARGS|METH_KEYWORDS, doc_to_integral_value },
+  { "sqrt", _DecOpt_mpd_qsqrt, METH_VARARGS, doc_sqrt },
+
+  /* Binary arithmetic functions */
+  { "add", _DecOpt_mpd_qadd, METH_VARARGS, doc_add },
+  { "compare", _DecOpt_mpd_qcompare, METH_VARARGS, doc_compare },
+  { "compare_signal", _DecOpt_mpd_qcompare_signal, METH_VARARGS, doc_compare_signal },
+  { "div", _DecOpt_mpd_qdiv, METH_VARARGS, doc_div }, /* alias for divide */
+  { "divide", _DecOpt_mpd_qdiv, METH_VARARGS, doc_divide },
+  { "divide_int", _DecOpt_mpd_qdivint, METH_VARARGS, doc_divide_int },
+  { "divint", _DecOpt_mpd_qdivint, METH_VARARGS, doc_divint }, /* alias for divide_int */
+  { "divmod", _DecOpt_mpd_qdivmod, METH_VARARGS, doc_divmod },
+  { "max", _DecOpt_mpd_qmax, METH_VARARGS, doc_max },
+  { "max_mag", _DecOpt_mpd_qmax_mag, METH_VARARGS, doc_max_mag },
+  { "min", _DecOpt_mpd_qmin, METH_VARARGS, doc_min },
+  { "min_mag", _DecOpt_mpd_qmin_mag, METH_VARARGS, doc_min_mag },
+  { "mul", _DecOpt_mpd_qmul, METH_VARARGS, doc_mul }, /* alias for multiply */
+  { "multiply", _DecOpt_mpd_qmul, METH_VARARGS, doc_multiply },
+  { "next_toward", _DecOpt_mpd_qnext_toward, METH_VARARGS, doc_next_toward },
+  { "pow", _DecOpt_mpd_qpow, METH_VARARGS, doc_pow }, /* alias for power */
+  { "power", _DecOpt_mpd_qpow, METH_VARARGS, doc_power },
+  { "quantize", _DecOpt_mpd_qquantize, METH_VARARGS, doc_quantize },
+  { "rem", _DecOpt_mpd_qrem, METH_VARARGS, doc_rem }, /* alias for remainder */
+  { "remainder", _DecOpt_mpd_qrem, METH_VARARGS, doc_remainder },
+  { "remainder_near", _DecOpt_mpd_qrem_near, METH_VARARGS, doc_remainder_near },
+  { "sub", _DecOpt_mpd_qsub, METH_VARARGS, doc_sub }, /* alias for subtract */
+  { "subtract", _DecOpt_mpd_qsub, METH_VARARGS, doc_subtract },
+
+  /* Ternary arithmetic functions */
+  { "fma", _DecOpt_mpd_qfma, METH_VARARGS, doc_fma },
+  { "powmod", _DecOpt_mpd_qpowmod, METH_VARARGS, doc_powmod },
+
+  /* Boolean functions, no context arg */
+  { "is_canonical", _Dec_CFunc_mpd_iscanonical, METH_NOARGS, doc_is_canonical },
+  { "is_finite", _Dec_CFunc_mpd_isfinite, METH_NOARGS, doc_is_finite },
+  { "is_infinite", _Dec_CFunc_mpd_isinfinite, METH_NOARGS, doc_is_infinite },
+  { "is_integer", _Dec_CFunc_mpd_isinteger, METH_NOARGS, doc_is_integer },
+  { "is_nan", _Dec_CFunc_mpd_isnan, METH_NOARGS, doc_is_nan },
+  { "is_qnan", _Dec_CFunc_mpd_isqnan, METH_NOARGS, doc_is_qnan },
+  { "is_snan", _Dec_CFunc_mpd_issnan, METH_NOARGS, doc_is_snan },
+  { "is_signed", _Dec_CFunc_mpd_issigned, METH_NOARGS, doc_is_signed },
+  { "is_special", _Dec_CFunc_mpd_isspecial, METH_NOARGS, doc_is_special },
+  { "is_zero", _Dec_CFunc_mpd_iszero, METH_NOARGS, doc_is_zero },
+
+  /* Boolean functions, optional context arg */
+  { "is_normal", _DecOpt_mpd_isnormal, METH_VARARGS, doc_is_normal },
+  { "is_subnormal", _DecOpt_mpd_issubnormal, METH_VARARGS, doc_is_subnormal },
+
+  /* Unary functions, no context arg */
+  { "adjusted", _Dec_mpd_adjexp, METH_NOARGS, doc_adjusted },
+  { "canonical", _Dec_canonical, METH_NOARGS, doc_canonical },
+  { "copy_abs", _Dec_mpd_qcopy_abs, METH_NOARGS, doc_copy_abs },
+  { "copy_negate", _Dec_mpd_qcopy_negate, METH_NOARGS, doc_copy_negate },
+  { "radix", _Dec_mpd_radix, METH_NOARGS, doc_radix },
+  { "sign", _Dec_mpd_sign, METH_NOARGS, doc_sign },
+
+  /* Unary functions, optional context arg */
+  { "apply", PyDec_Apply, METH_VARARGS, doc_apply },
+  { "logb", _DecOpt_mpd_qlogb, METH_VARARGS, doc_logb },
+  { "logical_invert", _DecOpt_mpd_qinvert, METH_VARARGS, doc_logical_invert },
+  { "number_class", _DecOpt_mpd_class, METH_VARARGS, doc_number_class },
+  { "to_sci", _Dec_mpd_to_sci, METH_VARARGS, doc_to_sci }, /* alias for to_sci_string */
+  { "to_sci_string", _Dec_mpd_to_sci, METH_VARARGS, doc_to_sci_string },
+  { "to_eng", _Dec_mpd_to_eng, METH_VARARGS, doc_to_eng }, /* alias for to_eng_string */
+  { "to_eng_string", _Dec_mpd_to_eng, METH_VARARGS, doc_to_eng_string },
+
+  /* Binary functions, optional context arg */
+  { "compare_total", _DecOpt_mpd_compare_total, METH_VARARGS, doc_compare_total },
+  { "compare_total_mag", _DecOpt_mpd_compare_total_mag, METH_VARARGS, doc_compare_total_mag },
+  { "copy_sign", _Dec_mpd_qcopy_sign, METH_O, doc_copy_sign },
+  { "logical_and", _DecOpt_mpd_qand, METH_VARARGS, doc_logical_and },
+  { "logical_or", _DecOpt_mpd_qor, METH_VARARGS, doc_logical_or },
+  { "logical_xor", _DecOpt_mpd_qxor, METH_VARARGS, doc_logical_xor },
+  { "rotate", _DecOpt_mpd_qrotate, METH_VARARGS, doc_rotate },
+  { "same_quantum", _Dec_mpd_same_quantum, METH_VARARGS, doc_same_quantum },
+  { "scaleb", _DecOpt_mpd_qscaleb, METH_VARARGS, doc_scaleb },
+  { "shift", _DecOpt_mpd_qshift, METH_VARARGS, doc_shift },
+
+  /* Miscellaneous */
+  { "from_float", _PyDec_FromFloat_Max, METH_O|METH_CLASS, doc_from_float },
+  { "as_tuple", PyDec_AsTuple, METH_NOARGS, doc_as_tuple },
+
+  /* Generic stuff */
+  { "__copy__", dec_copy, METH_NOARGS, NULL },
+  { "__deepcopy__", dec_copy, METH_VARARGS, NULL },
+  { "__format__", dec_format, METH_VARARGS, NULL },
+  { "__reduce__", dec_reduce, METH_NOARGS, NULL },
+  { "__round__", PyDec_Round, METH_VARARGS, NULL },
+  { "__trunc__", PyDec_Trunc, METH_NOARGS, NULL },
 
-	{ NULL, NULL, 1 }
+  { NULL, NULL, 1 }
 };
 
 static PyTypeObject PyDec_Type =
@@ -4405,15 +4602,15 @@
 	CONVERT_OP_SET(v, &a, ctx);
 
 	if ((result = dec_alloc()) == NULL) {
-		Py_DECREF(a);
-		return NULL;
+		Py_DECREF(a); /* GCOV_UNLIKELY */
+		return NULL; /* GCOV_UNLIKELY */
 	}
 
 	mpd_qcopy_abs(result->dec, a->dec, &status);
 	Py_DECREF(a);
 	if (dec_addstatus(ctx, status)) {
-		Py_DECREF(result);
-		return NULL;
+		Py_DECREF(result); /* GCOV_UNLIKELY */
+		return NULL; /* GCOV_UNLIKELY */
 	}
 
 	return (PyObject *) result;
@@ -4430,15 +4627,15 @@
 	CONVERT_OP_SET(v, &a, ctx);
 
 	if ((result = dec_alloc()) == NULL) {
-		Py_DECREF(a);
-		return NULL;
+		Py_DECREF(a); /* GCOV_UNLIKELY */
+		return NULL; /* GCOV_UNLIKELY */
 	}
 
 	mpd_qcopy_negate(result->dec, a->dec, &status);
 	Py_DECREF(a);
 	if (dec_addstatus(ctx, status)) {
-		Py_DECREF(result);
-		return NULL;
+		Py_DECREF(result); /* GCOV_UNLIKELY */
+		return NULL; /* GCOV_UNLIKELY */
 	}
 
 	return (PyObject *) result;
@@ -4467,17 +4664,17 @@
 	CONVERT_BINOP_SET(v, w, &a, &b, ctx);
 
 	if ((result = dec_alloc()) == NULL) {
-		Py_DECREF(a);
-		Py_DECREF(b);
-		return NULL;
+		Py_DECREF(a); /* GCOV_UNLIKELY */
+		Py_DECREF(b); /* GCOV_UNLIKELY */
+		return NULL; /* GCOV_UNLIKELY */
 	}
 
 	mpd_qcopy_sign(result->dec, a->dec, b->dec, &status);
 	Py_DECREF(a);
 	Py_DECREF(b);
 	if (dec_addstatus(ctx, status)) {
-		Py_DECREF(result);
-		return NULL;
+		Py_DECREF(result); /* GCOV_UNLIKELY */
+		return NULL; /* GCOV_UNLIKELY */
 	}
 
 	return (PyObject *) result;
@@ -4495,7 +4692,8 @@
 _DecCtx_iscanonical(PyObject *self UNUSED, PyObject *v)
 {
 	if (!PyDec_Check(v)) {
-		PyErr_SetString(PyExc_TypeError, "argument must be a Decimal");
+		PyErr_SetString(PyExc_TypeError,
+		    "argument must be a Decimal.");
 		return NULL;
 	}
 
@@ -4506,7 +4704,8 @@
 _DecCtx_canonical(PyObject *self UNUSED, PyObject *v)
 {
 	if (!PyDec_Check(v)) {
-		PyErr_SetString(PyExc_TypeError, "argument must be a Decimal");
+		PyErr_SetString(PyExc_TypeError,
+		    "argument must be a Decimal.");
 		return NULL;
 	}
 
@@ -4547,15 +4746,15 @@
 	CONVERT_BINOP_SET(v, w, &a, &b, ctx);
 
 	if ((q = dec_alloc()) == NULL) {
-		Py_DECREF(a);
-		Py_DECREF(b);
-		return NULL;
+		Py_DECREF(a); /* GCOV_UNLIKELY */
+		Py_DECREF(b); /* GCOV_UNLIKELY */
+		return NULL; /* GCOV_UNLIKELY */
 	}
 	if ((r = dec_alloc()) == NULL) {
-		Py_DECREF(a);
-		Py_DECREF(b);
-		Py_DECREF(q);
-		return NULL;
+		Py_DECREF(a); /* GCOV_UNLIKELY */
+		Py_DECREF(b); /* GCOV_UNLIKELY */
+		Py_DECREF(q); /* GCOV_UNLIKELY */
+		return NULL; /* GCOV_UNLIKELY */
 	}
 
 	mpd_qdivmod(q->dec, r->dec, a->dec, b->dec, ctx, &status);
@@ -4584,8 +4783,8 @@
 	s = mpd_to_sci(a->dec, CtxCaps(self));
 	Py_DECREF(a);
 	if (s == NULL) {
-		PyErr_NoMemory();
-		return NULL;
+		PyErr_NoMemory(); /* GCOV_UNLIKELY */
+		return NULL; /* GCOV_UNLIKELY */
 	}
 
 	result = PyUnicode_FromString(s);
@@ -4608,8 +4807,8 @@
 	s = mpd_to_eng(a->dec, CtxCaps(self));
 	Py_DECREF(a);
 	if (s == NULL) {
-		PyErr_NoMemory();
-		return NULL;
+		PyErr_NoMemory(); /* GCOV_UNLIKELY */
+		return NULL; /* GCOV_UNLIKELY */
 	}
 
 	result = PyUnicode_FromString(s);
@@ -4650,115 +4849,115 @@
 
 static PyMethodDef context_methods [] =
 {
-	/* Unary arithmetic functions */
-	{ "abs", _DecCtx_mpd_qabs, METH_O, doc_ctx_abs },
-	{ "exp", _DecCtx_mpd_qexp, METH_O, doc_ctx_exp },
-	{ "invroot", _DecCtx_mpd_qinvroot, METH_O, doc_ctx_invroot },
-	{ "ln", _DecCtx_mpd_qln, METH_O, doc_ctx_ln },
-	{ "log10", _DecCtx_mpd_qlog10, METH_O, doc_ctx_log10 },
-	{ "minus", _DecCtx_mpd_qminus, METH_O, doc_ctx_minus },
-	{ "next_minus", _DecCtx_mpd_qnext_minus, METH_O, doc_ctx_next_minus },
-	{ "next_plus", _DecCtx_mpd_qnext_plus, METH_O, doc_ctx_next_plus },
-	{ "normalize", _DecCtx_mpd_qreduce, METH_O, doc_ctx_normalize }, /* alias for reduce */
-	{ "plus", _DecCtx_mpd_qplus, METH_O, doc_ctx_plus },
-	{ "reduce", _DecCtx_mpd_qreduce, METH_O, doc_ctx_reduce },
-	{ "to_integral", _DecCtx_mpd_qround_to_int, METH_O, doc_ctx_to_integral },
-	{ "to_integral_exact", _DecCtx_mpd_qround_to_intx, METH_O, doc_ctx_to_integral_exact },
-	{ "to_integral_value", _DecCtx_mpd_qround_to_int, METH_O, doc_ctx_to_integral_value },
-	{ "sqrt", _DecCtx_mpd_qsqrt, METH_O, doc_ctx_sqrt },
-
-	/* Binary arithmetic functions */
-	{ "add", _DecCtx_mpd_qadd, METH_VARARGS, doc_ctx_add },
-	{ "compare", _DecCtx_mpd_qcompare, METH_VARARGS, doc_ctx_compare },
-	{ "compare_signal", _DecCtx_mpd_qcompare_signal, METH_VARARGS, doc_ctx_compare_signal },
-	{ "div", _DecCtx_mpd_qdiv, METH_VARARGS, doc_ctx_div }, /* alias for divide */
-	{ "divide", _DecCtx_mpd_qdiv, METH_VARARGS, doc_ctx_divide },
-	{ "divide_int", _DecCtx_mpd_qdivint, METH_VARARGS, doc_ctx_divide_int },
-	{ "divint", _DecCtx_mpd_qdivint, METH_VARARGS, doc_ctx_divint }, /* alias for divide_int */
-	{ "divmod", _DecCtx_mpd_qdivmod, METH_VARARGS, doc_ctx_divmod },
-	{ "max", _DecCtx_mpd_qmax, METH_VARARGS, doc_ctx_max },
-	{ "max_mag", _DecCtx_mpd_qmax_mag, METH_VARARGS, doc_ctx_max_mag },
-	{ "min", _DecCtx_mpd_qmin, METH_VARARGS, doc_ctx_min },
-	{ "min_mag", _DecCtx_mpd_qmin_mag, METH_VARARGS, doc_ctx_min_mag },
-	{ "mul", _DecCtx_mpd_qmul, METH_VARARGS, doc_ctx_mul }, /* alias for multiply */
-	{ "multiply", _DecCtx_mpd_qmul, METH_VARARGS, doc_ctx_multiply },
-	{ "next_toward", _DecCtx_mpd_qnext_toward, METH_VARARGS, doc_ctx_next_toward },
-	{ "pow", _DecCtx_mpd_qpow, METH_VARARGS, doc_ctx_pow }, /* alias for power */
-	{ "power", _DecCtx_mpd_qpow, METH_VARARGS, doc_ctx_power },
-	{ "quantize", _DecCtx_mpd_qquantize, METH_VARARGS, doc_ctx_quantize },
-	{ "rem", _DecCtx_mpd_qrem, METH_VARARGS, doc_ctx_rem }, /* alias for remainder */
-	{ "remainder", _DecCtx_mpd_qrem, METH_VARARGS, doc_ctx_remainder },
-	{ "remainder_near", _DecCtx_mpd_qrem_near, METH_VARARGS, doc_ctx_remainder_near },
-	{ "sub", _DecCtx_mpd_qsub, METH_VARARGS, doc_ctx_sub }, /* alias for subtract */
-	{ "subtract", _DecCtx_mpd_qsub, METH_VARARGS, doc_ctx_subtract },
-
-	/* Ternary arithmetic functions */
-	{ "fma", _DecCtx_mpd_qfma, METH_VARARGS, doc_ctx_fma },
-	{ "powmod", _DecCtx_mpd_qpowmod, METH_VARARGS, doc_ctx_powmod },
-
-	/* No argument */
-	{ "Etiny", context_getetiny, METH_NOARGS, doc_ctx_Etiny },
-	{ "Etop", context_getetop, METH_NOARGS, doc_ctx_Etop },
-	{ "radix", _DecCtx_mpd_radix, METH_NOARGS, doc_ctx_radix },
-
-	/* Boolean functions */
-	{ "is_canonical", _DecCtx_iscanonical, METH_O, doc_ctx_is_canonical },
-	{ "is_finite", _DecCtx_mpd_isfinite, METH_O, doc_ctx_is_finite },
-	{ "is_infinite", _DecCtx_mpd_isinfinite, METH_O, doc_ctx_is_infinite },
-	{ "is_nan", _DecCtx_mpd_isnan, METH_O, doc_ctx_is_nan },
-	{ "is_normal", _DecCtx_mpd_isnormal, METH_O, doc_ctx_is_normal },
-	{ "is_qnan", _DecCtx_mpd_isqnan, METH_O, doc_ctx_is_qnan },
-	{ "is_signed", _DecCtx_mpd_issigned, METH_O, doc_ctx_is_signed },
-	{ "is_snan", _DecCtx_mpd_issnan, METH_O, doc_ctx_is_snan },
-	{ "is_subnormal", _DecCtx_mpd_issubnormal, METH_O, doc_ctx_is_subnormal },
-	{ "is_zero", _DecCtx_mpd_iszero, METH_O, doc_ctx_is_zero },
-
-	/* Functions with a single decimal argument */
-	{ "_apply", PyDecContext_Apply, METH_O, NULL }, /* alias for apply */
-	{ "apply", PyDecContext_Apply, METH_O, doc_ctx_apply },
-	{ "canonical", _DecCtx_canonical, METH_O, doc_ctx_canonical },
-	{ "copy_abs", _DecCtx_mpd_qcopy_abs, METH_O, doc_ctx_copy_abs },
-	{ "copy_decimal", _DecCtx_copy_decimal, METH_O, doc_ctx_copy_decimal },
-	{ "copy_negate", _DecCtx_mpd_qcopy_negate, METH_O, doc_ctx_copy_negate },
-	{ "logb", _DecCtx_mpd_qlogb, METH_O, doc_ctx_logb },
-	{ "logical_invert", _DecCtx_mpd_qinvert, METH_O, doc_ctx_logical_invert },
-	{ "number_class", _DecCtx_mpd_class, METH_O, doc_ctx_number_class },
-	{ "to_sci", _DecCtx_mpd_to_sci, METH_O, doc_ctx_to_sci }, /* alias for to_sci_string */
-	{ "to_sci_string", _DecCtx_mpd_to_sci, METH_O, doc_ctx_to_sci_string },
-	{ "to_eng", _DecCtx_mpd_to_eng, METH_O, doc_ctx_to_eng }, /* alias for to_eng_string */
-	{ "to_eng_string", _DecCtx_mpd_to_eng, METH_O, doc_ctx_to_eng_string },
-
-	/* Functions with two decimal arguments */
-	{ "compare_total", _DecCtx_mpd_compare_total, METH_VARARGS, doc_ctx_compare_total },
-	{ "compare_total_mag", _DecCtx_mpd_compare_total_mag, METH_VARARGS, doc_ctx_compare_total_mag },
-	{ "copy_sign", _DecCtx_mpd_qcopy_sign, METH_VARARGS, doc_ctx_copy_sign },
-	{ "logical_and", _DecCtx_mpd_qand, METH_VARARGS, doc_ctx_logical_and },
-	{ "logical_or", _DecCtx_mpd_qor, METH_VARARGS, doc_ctx_logical_or },
-	{ "logical_xor", _DecCtx_mpd_qxor, METH_VARARGS, doc_ctx_logical_xor },
-	{ "rotate", _DecCtx_mpd_qrotate, METH_VARARGS, doc_ctx_rotate },
-	{ "same_quantum", _DecCtx_mpd_same_quantum, METH_VARARGS, doc_ctx_same_quantum },
-	{ "scaleb", _DecCtx_mpd_qscaleb, METH_VARARGS, doc_ctx_scaleb },
-	{ "shift", _DecCtx_mpd_qshift, METH_VARARGS, doc_ctx_shift },
-
-	/* Set context values */
-	{ "setflags", PyDec_SetStatusFromList, METH_O, doc_ctx_setflags },
-	{ "settraps", PyDec_SetTrapsFromList, METH_O, doc_ctx_settraps },
-	{ "clear_flags", context_clear_flags, METH_NOARGS, doc_ctx_clear_flags },
-	{ "clear_traps", context_clear_traps, METH_NOARGS, doc_ctx_clear_traps },
-
-	/* Unsafe set functions with no range checks */
-	{ "unsafe_setprec", context_unsafe_setprec, METH_O, NULL },
-	{ "unsafe_setemin", context_unsafe_setemin, METH_O, NULL },
-	{ "unsafe_setemax", context_unsafe_setemax, METH_O, NULL },
-
-	/* Miscellaneous */
-	{ "__copy__", (PyCFunction)context_copy, METH_NOARGS, NULL },
-	{ "__reduce__", context_reduce, METH_NOARGS, NULL },
-	{ "copy", (PyCFunction)context_copy, METH_NOARGS, doc_ctx_copy },
-	{ "create_decimal", PyDecContext_CreateDecimal, METH_VARARGS, doc_ctx_create_decimal },
-	{ "create_decimal_from_float", PyDecContext_FromFloat, METH_O, doc_ctx_create_decimal_from_float },
+  /* Unary arithmetic functions */
+  { "abs", _DecCtx_mpd_qabs, METH_O, doc_ctx_abs },
+  { "exp", _DecCtx_mpd_qexp, METH_O, doc_ctx_exp },
+  { "invroot", _DecCtx_mpd_qinvroot, METH_O, doc_ctx_invroot },
+  { "ln", _DecCtx_mpd_qln, METH_O, doc_ctx_ln },
+  { "log10", _DecCtx_mpd_qlog10, METH_O, doc_ctx_log10 },
+  { "minus", _DecCtx_mpd_qminus, METH_O, doc_ctx_minus },
+  { "next_minus", _DecCtx_mpd_qnext_minus, METH_O, doc_ctx_next_minus },
+  { "next_plus", _DecCtx_mpd_qnext_plus, METH_O, doc_ctx_next_plus },
+  { "normalize", _DecCtx_mpd_qreduce, METH_O, doc_ctx_normalize }, /* alias for reduce */
+  { "plus", _DecCtx_mpd_qplus, METH_O, doc_ctx_plus },
+  { "reduce", _DecCtx_mpd_qreduce, METH_O, doc_ctx_reduce },
+  { "to_integral", _DecCtx_mpd_qround_to_int, METH_O, doc_ctx_to_integral },
+  { "to_integral_exact", _DecCtx_mpd_qround_to_intx, METH_O, doc_ctx_to_integral_exact },
+  { "to_integral_value", _DecCtx_mpd_qround_to_int, METH_O, doc_ctx_to_integral_value },
+  { "sqrt", _DecCtx_mpd_qsqrt, METH_O, doc_ctx_sqrt },
+
+  /* Binary arithmetic functions */
+  { "add", _DecCtx_mpd_qadd, METH_VARARGS, doc_ctx_add },
+  { "compare", _DecCtx_mpd_qcompare, METH_VARARGS, doc_ctx_compare },
+  { "compare_signal", _DecCtx_mpd_qcompare_signal, METH_VARARGS, doc_ctx_compare_signal },
+  { "div", _DecCtx_mpd_qdiv, METH_VARARGS, doc_ctx_div }, /* alias for divide */
+  { "divide", _DecCtx_mpd_qdiv, METH_VARARGS, doc_ctx_divide },
+  { "divide_int", _DecCtx_mpd_qdivint, METH_VARARGS, doc_ctx_divide_int },
+  { "divint", _DecCtx_mpd_qdivint, METH_VARARGS, doc_ctx_divint }, /* alias for divide_int */
+  { "divmod", _DecCtx_mpd_qdivmod, METH_VARARGS, doc_ctx_divmod },
+  { "max", _DecCtx_mpd_qmax, METH_VARARGS, doc_ctx_max },
+  { "max_mag", _DecCtx_mpd_qmax_mag, METH_VARARGS, doc_ctx_max_mag },
+  { "min", _DecCtx_mpd_qmin, METH_VARARGS, doc_ctx_min },
+  { "min_mag", _DecCtx_mpd_qmin_mag, METH_VARARGS, doc_ctx_min_mag },
+  { "mul", _DecCtx_mpd_qmul, METH_VARARGS, doc_ctx_mul }, /* alias for multiply */
+  { "multiply", _DecCtx_mpd_qmul, METH_VARARGS, doc_ctx_multiply },
+  { "next_toward", _DecCtx_mpd_qnext_toward, METH_VARARGS, doc_ctx_next_toward },
+  { "pow", _DecCtx_mpd_qpow, METH_VARARGS, doc_ctx_pow }, /* alias for power */
+  { "power", _DecCtx_mpd_qpow, METH_VARARGS, doc_ctx_power },
+  { "quantize", _DecCtx_mpd_qquantize, METH_VARARGS, doc_ctx_quantize },
+  { "rem", _DecCtx_mpd_qrem, METH_VARARGS, doc_ctx_rem }, /* alias for remainder */
+  { "remainder", _DecCtx_mpd_qrem, METH_VARARGS, doc_ctx_remainder },
+  { "remainder_near", _DecCtx_mpd_qrem_near, METH_VARARGS, doc_ctx_remainder_near },
+  { "sub", _DecCtx_mpd_qsub, METH_VARARGS, doc_ctx_sub }, /* alias for subtract */
+  { "subtract", _DecCtx_mpd_qsub, METH_VARARGS, doc_ctx_subtract },
+
+  /* Ternary arithmetic functions */
+  { "fma", _DecCtx_mpd_qfma, METH_VARARGS, doc_ctx_fma },
+  { "powmod", _DecCtx_mpd_qpowmod, METH_VARARGS, doc_ctx_powmod },
+
+  /* No argument */
+  { "Etiny", context_getetiny, METH_NOARGS, doc_ctx_Etiny },
+  { "Etop", context_getetop, METH_NOARGS, doc_ctx_Etop },
+  { "radix", _DecCtx_mpd_radix, METH_NOARGS, doc_ctx_radix },
+
+  /* Boolean functions */
+  { "is_canonical", _DecCtx_iscanonical, METH_O, doc_ctx_is_canonical },
+  { "is_finite", _DecCtx_mpd_isfinite, METH_O, doc_ctx_is_finite },
+  { "is_infinite", _DecCtx_mpd_isinfinite, METH_O, doc_ctx_is_infinite },
+  { "is_nan", _DecCtx_mpd_isnan, METH_O, doc_ctx_is_nan },
+  { "is_normal", _DecCtx_mpd_isnormal, METH_O, doc_ctx_is_normal },
+  { "is_qnan", _DecCtx_mpd_isqnan, METH_O, doc_ctx_is_qnan },
+  { "is_signed", _DecCtx_mpd_issigned, METH_O, doc_ctx_is_signed },
+  { "is_snan", _DecCtx_mpd_issnan, METH_O, doc_ctx_is_snan },
+  { "is_subnormal", _DecCtx_mpd_issubnormal, METH_O, doc_ctx_is_subnormal },
+  { "is_zero", _DecCtx_mpd_iszero, METH_O, doc_ctx_is_zero },
+
+  /* Functions with a single decimal argument */
+  { "_apply", PyDecContext_Apply, METH_O, NULL }, /* alias for apply */
+  { "apply", PyDecContext_Apply, METH_O, doc_ctx_apply },
+  { "canonical", _DecCtx_canonical, METH_O, doc_ctx_canonical },
+  { "copy_abs", _DecCtx_mpd_qcopy_abs, METH_O, doc_ctx_copy_abs },
+  { "copy_decimal", _DecCtx_copy_decimal, METH_O, doc_ctx_copy_decimal },
+  { "copy_negate", _DecCtx_mpd_qcopy_negate, METH_O, doc_ctx_copy_negate },
+  { "logb", _DecCtx_mpd_qlogb, METH_O, doc_ctx_logb },
+  { "logical_invert", _DecCtx_mpd_qinvert, METH_O, doc_ctx_logical_invert },
+  { "number_class", _DecCtx_mpd_class, METH_O, doc_ctx_number_class },
+  { "to_sci", _DecCtx_mpd_to_sci, METH_O, doc_ctx_to_sci }, /* alias for to_sci_string */
+  { "to_sci_string", _DecCtx_mpd_to_sci, METH_O, doc_ctx_to_sci_string },
+  { "to_eng", _DecCtx_mpd_to_eng, METH_O, doc_ctx_to_eng }, /* alias for to_eng_string */
+  { "to_eng_string", _DecCtx_mpd_to_eng, METH_O, doc_ctx_to_eng_string },
+
+  /* Functions with two decimal arguments */
+  { "compare_total", _DecCtx_mpd_compare_total, METH_VARARGS, doc_ctx_compare_total },
+  { "compare_total_mag", _DecCtx_mpd_compare_total_mag, METH_VARARGS, doc_ctx_compare_total_mag },
+  { "copy_sign", _DecCtx_mpd_qcopy_sign, METH_VARARGS, doc_ctx_copy_sign },
+  { "logical_and", _DecCtx_mpd_qand, METH_VARARGS, doc_ctx_logical_and },
+  { "logical_or", _DecCtx_mpd_qor, METH_VARARGS, doc_ctx_logical_or },
+  { "logical_xor", _DecCtx_mpd_qxor, METH_VARARGS, doc_ctx_logical_xor },
+  { "rotate", _DecCtx_mpd_qrotate, METH_VARARGS, doc_ctx_rotate },
+  { "same_quantum", _DecCtx_mpd_same_quantum, METH_VARARGS, doc_ctx_same_quantum },
+  { "scaleb", _DecCtx_mpd_qscaleb, METH_VARARGS, doc_ctx_scaleb },
+  { "shift", _DecCtx_mpd_qshift, METH_VARARGS, doc_ctx_shift },
+
+  /* Set context values */
+  { "setflags", PyDec_SetStatusFromList, METH_O, doc_ctx_setflags },
+  { "settraps", PyDec_SetTrapsFromList, METH_O, doc_ctx_settraps },
+  { "clear_flags", context_clear_flags, METH_NOARGS, doc_ctx_clear_flags },
+  { "clear_traps", context_clear_traps, METH_NOARGS, doc_ctx_clear_traps },
+
+  /* Unsafe set functions with no range checks */
+  { "unsafe_setprec", context_unsafe_setprec, METH_O, NULL },
+  { "unsafe_setemin", context_unsafe_setemin, METH_O, NULL },
+  { "unsafe_setemax", context_unsafe_setemax, METH_O, NULL },
+
+  /* Miscellaneous */
+  { "__copy__", (PyCFunction)context_copy, METH_NOARGS, NULL },
+  { "__reduce__", context_reduce, METH_NOARGS, NULL },
+  { "copy", (PyCFunction)context_copy, METH_NOARGS, doc_ctx_copy },
+  { "create_decimal", PyDecContext_CreateDecimal, METH_VARARGS, doc_ctx_create_decimal },
+  { "create_decimal_from_float", PyDecContext_FromFloat, METH_O, doc_ctx_create_decimal_from_float },
 
-	{ NULL, NULL, 1 }
+  { NULL, NULL, 1 }
 };
 
 static PyTypeObject PyDecContext_Type =
@@ -4807,11 +5006,11 @@
 
 static PyMethodDef cdecimal_methods [] =
 {
-	{ "getcontext", (PyCFunction)PyDec_GetCurrentContext, METH_NOARGS, doc_getcontext},
-	{ "setcontext", (PyCFunction)PyDec_SetCurrentContext, METH_O, doc_setcontext},
-	{ "localcontext", (PyCFunction)ctxmanager_new, METH_VARARGS, doc_localcontext},
-	{ "IEEEContext", (PyCFunction)ieee_context, METH_O, doc_ieee_context},
-	{ NULL, NULL, 1, NULL }
+  { "getcontext", (PyCFunction)PyDec_GetCurrentContext, METH_NOARGS, doc_getcontext},
+  { "setcontext", (PyCFunction)PyDec_SetCurrentContext, METH_O, doc_setcontext},
+  { "localcontext", (PyCFunction)ctxmanager_new, METH_VARARGS, doc_localcontext},
+  { "IEEEContext", (PyCFunction)ieee_context, METH_O, doc_ieee_context},
+  { NULL, NULL, 1, NULL }
 };
 
 static struct PyModuleDef cdecimal_module = {
@@ -4845,56 +5044,56 @@
 
 
 	if (PyType_Ready(&PyDec_Type) < 0) {
-		goto error;
+		goto error; /* GCOV_UNLIKELY */
 	}
 	if (PyType_Ready(&PyDecContext_Type) < 0) {
-		goto error;
+		goto error; /* GCOV_UNLIKELY */
 	}
 	if (PyType_Ready(&PyDecSignalDict_Type) < 0) {
-		goto error;
+		goto error; /* GCOV_UNLIKELY */
 	}
 	if (PyType_Ready(&PyDecContextManager_Type) < 0) {
-		goto error;
+		goto error; /* GCOV_UNLIKELY */
 	}
 
 
 	if ((obj = PyUnicode_FromString("cdecimal")) == NULL) {
-		goto error;
+		goto error; /* GCOV_UNLIKELY */
 	}
 	if (PyDict_SetItemString(PyDec_Type.tp_dict, "__module__", obj) < 0) {
-		Py_DECREF(obj);
-		goto error;
+		Py_DECREF(obj); /* GCOV_UNLIKELY */
+		goto error; /* GCOV_UNLIKELY */
 	}
 	if (PyDict_SetItemString(PyDecContext_Type.tp_dict, "__module__", obj) < 0) {
-		Py_DECREF(obj);
-		goto error;
+		Py_DECREF(obj); /* GCOV_UNLIKELY */
+		goto error; /* GCOV_UNLIKELY */
 	}
 	Py_DECREF(obj);
 
 
 	if ((_numbers = PyImport_ImportModule("numbers")) == NULL) {
-		goto error;
+		goto error; /* GCOV_UNLIKELY */
 	}
 	if ((_Number = PyObject_GetAttrString(_numbers, "Number")) == NULL) {
-		goto error;
+		goto error; /* GCOV_UNLIKELY */
 	}
 	if ((obj = Py_BuildValue("O",  &PyDec_Type)) == NULL) {
-		goto error;
+		goto error; /* GCOV_UNLIKELY */
 	}
 	if ((s = Py_BuildValue("s", "register")) == NULL) {
-		goto error;
+		goto error; /* GCOV_UNLIKELY */
 	}
 	if ((ret = PyObject_CallMethodObjArgs(_Number, s, obj, NULL)) == NULL) {
-		Py_DECREF(s);
-		Py_DECREF(obj);
-		goto error;
+		Py_DECREF(s); /* GCOV_UNLIKELY */
+		Py_DECREF(obj); /* GCOV_UNLIKELY */
+		goto error; /* GCOV_UNLIKELY */
 	}
 	Py_DECREF(s);
 	Py_DECREF(obj);
 	Py_DECREF(ret);
 
 	if ((m = PyModule_Create(&cdecimal_module)) == NULL) {
-		goto error;
+		goto error; /* GCOV_UNLIKELY */
 	}
 
 	mpd_traphandler = dec_traphandler;
@@ -4946,7 +5145,7 @@
 	/* Default context template */
 	ctxobj = PyObject_CallObject((PyObject *)&PyDecContext_Type, NULL);
 	if (ctxobj == NULL) {
-		goto error;
+		goto error; /* GCOV_UNLIKELY */
 	}
 	default_context_template = ctxobj;
 	Py_INCREF(ctxobj);
@@ -4956,14 +5155,14 @@
 	/* Module context */
 	ctxobj = PyObject_CallObject((PyObject *)&PyDecContext_Type, NULL);
 	if (ctxobj == NULL) {
-		goto error;
+		goto error; /* GCOV_UNLIKELY */
 	}
 	module_context = ctxobj;
 	PyModule_AddIntConstant(m, "HAVE_THREADS", 0);
 #else
 	tls_context_key = Py_BuildValue("s", "__CDECIMAL_CTX__");
 	if (tls_context_key == NULL) {
-		goto error;
+		goto error; /* GCOV_UNLIKELY */
 	}
 	PyModule_AddIntConstant(m, "HAVE_THREADS", 1);
 #endif
@@ -4971,7 +5170,7 @@
 	/* Basic context template */
 	ctxobj = PyObject_CallObject((PyObject *)&PyDecContext_Type, NULL);
 	if (ctxobj == NULL) {
-		goto error;
+		goto error; /* GCOV_UNLIKELY */
 	}
 	init_basic_context(ctxobj);
 	basic_context_template = ctxobj;
@@ -4981,7 +5180,7 @@
 	/* Extended context template */
 	ctxobj = PyObject_CallObject((PyObject *)&PyDecContext_Type, NULL);
 	if (ctxobj == NULL) {
-		goto error;
+		goto error; /* GCOV_UNLIKELY */
 	}
 	init_extended_context(ctxobj);
 	extended_context_template = ctxobj;
@@ -5022,7 +5221,7 @@
 	PyModule_AddIntConstant(m, "DecInvalidOperation", MPD_Invalid_operation);
 	PyModule_AddIntConstant(m, "DecIEEEInvalidOperation", MPD_IEEE_Invalid_operation);
 	PyModule_AddIntConstant(m, "DecMallocError", MPD_Malloc_error);
-	PyModule_AddIntConstant(m, "DecNotImplemented", MPD_Not_implemented);
+	PyModule_AddIntConstant(m, "DecFloatOperation", MPD_Float_operation);
 	PyModule_AddIntConstant(m, "DecOverflow", MPD_Overflow);
 	PyModule_AddIntConstant(m, "DecRounded", MPD_Rounded);
 	PyModule_AddIntConstant(m, "DecSubnormal", MPD_Subnormal);
@@ -5033,20 +5232,20 @@
 
 	return m;
 
-error:
-	if (_numbers) Py_DECREF(_numbers);
-	if (_Number) Py_DECREF(_Number);
+error: /* GCOV_UNLIKELY */
+	if (_numbers) Py_DECREF(_numbers); /* GCOV_UNLIKELY */
+	if (_Number) Py_DECREF(_Number); /* GCOV_UNLIKELY */
 #ifdef WITHOUT_THREADS
-	if (module_context) Py_DECREF(module_context);
+	if (module_context) Py_DECREF(module_context); /* GCOV_UNLIKELY */
 #else
-	if (default_context_template) Py_DECREF(default_context_template);
-	if (tls_context_key) Py_DECREF(tls_context_key);
+	if (default_context_template) Py_DECREF(default_context_template); /* GCOV_UNLIKELY */
+	if (tls_context_key) Py_DECREF(tls_context_key); /* GCOV_UNLIKELY */
 #endif
-	if (basic_context_template) Py_DECREF(basic_context_template);
-	if (extended_context_template) Py_DECREF(extended_context_template);
-	if (m) Py_DECREF(m);
+	if (basic_context_template) Py_DECREF(basic_context_template); /* GCOV_UNLIKELY */
+	if (extended_context_template) Py_DECREF(extended_context_template); /* GCOV_UNLIKELY */
+	if (m) Py_DECREF(m); /* GCOV_UNLIKELY */
 
-	return NULL;
+	return NULL; /* GCOV_UNLIKELY */
 }
 
 

Modified: python/branches/py3k-cdecimal/Modules/cdecimal/constants.h
==============================================================================
--- python/branches/py3k-cdecimal/Modules/cdecimal/constants.h	(original)
+++ python/branches/py3k-cdecimal/Modules/cdecimal/constants.h	Mon Nov  8 15:12:49 2010
@@ -20,14 +20,6 @@
   #define POWMOD(base, exp) x64_powmod(base, exp, umod)
   #define SETMODULUS(modnum) std_setmodulus(modnum, &umod)
   #define SIZE3_NTT(x0, x1, x2, w3table) std_size3_ntt(x0, x1, x2, w3table, umod)
-
-  #if defined(__x86_64__)
-    #define BSR(a) x86_bsr(a)
-    #define BSF(a) x86_bsf(a)
-  #else
-    #define BSR(a) std_bsr(a)
-    #define BSF(a) std_bsf(a)
-  #endif
 #elif defined(PPRO)
 /* PentiumPro (or later) gcc inline asm */
   #define MULMOD(a, b) ppro_mulmod(a, b, &dmod, dinvmod)
@@ -36,9 +28,6 @@
   #define POWMOD(base, exp) ppro_powmod(base, exp, &dmod, dinvmod)
   #define SETMODULUS(modnum) ppro_setmodulus(modnum, &umod, &dmod, dinvmod)
   #define SIZE3_NTT(x0, x1, x2, w3table) ppro_size3_ntt(x0, x1, x2, w3table, umod, &dmod, dinvmod)
-
-  #define BSR(a) x86_bsr(a)
-  #define BSF(a) x86_bsf(a)
 #else
   /* ANSI C99 */
   #define MULMOD(a, b) std_mulmod(a, b, umod)
@@ -47,9 +36,6 @@
   #define POWMOD(base, exp) std_powmod(base, exp, umod)
   #define SETMODULUS(modnum) std_setmodulus(modnum, &umod)
   #define SIZE3_NTT(x0, x1, x2, w3table) std_size3_ntt(x0, x1, x2, w3table, umod)
-
-  #define BSR(a) std_bsr(a)
-  #define BSF(a) std_bsf(a)
 #endif
 
 /* PentiumPro (or later) gcc inline asm */
@@ -57,7 +43,6 @@
 extern const uint32_t mpd_invmoduli[3][3];
 
 enum {P1, P2, P3};
-enum {UNORDERED, ORDERED};
 
 extern const mpd_uint_t mpd_moduli[];
 extern const mpd_uint_t mpd_roots[];

Modified: python/branches/py3k-cdecimal/Modules/cdecimal/context.c
==============================================================================
--- python/branches/py3k-cdecimal/Modules/cdecimal/context.c	(original)
+++ python/branches/py3k-cdecimal/Modules/cdecimal/context.c	Mon Nov  8 15:12:49 2010
@@ -10,7 +10,7 @@
 #include <signal.h>
 
 
-static void
+void
 mpd_dflt_traphandler(mpd_context_t *ctx UNUSED)
 {
 	raise(SIGFPE);
@@ -30,7 +30,7 @@
 		return;
 	}
 	if (n < MPD_MINALLOC_MIN || n > MPD_MINALLOC_MAX) {
-		mpd_err_fatal("illegal value for MPD_MINALLOC");
+		mpd_err_fatal("illegal value for MPD_MINALLOC"); /* GCOV_NOT_REACHED */
 	}
 	MPD_MINALLOC = n;
 	minalloc_is_set = 1;
@@ -70,6 +70,20 @@
 }
 
 void
+mpd_maxcontext_plus(mpd_context_t *workctx, const mpd_context_t *ctx)
+{
+	workctx->prec = ctx->prec > MPD_MAX_PREC ? ctx->prec : MPD_MAX_PREC;
+	workctx->emax = ctx->emax > MPD_MAX_EMAX ? ctx->emax : MPD_MAX_EMAX;
+	workctx->emin = ctx->emin < MPD_MIN_EMIN ? ctx->emin : MPD_MIN_EMIN;
+	workctx->round=MPD_ROUND_HALF_EVEN;
+	workctx->traps=MPD_Traps;
+	workctx->status=0;
+	workctx->newtrap=0;
+	workctx->clamp=0;
+	workctx->allcr=1;
+}
+
+void
 mpd_defaultcontext(mpd_context_t *ctx)
 {
 	ctx->prec=2*MPD_RDIGITS;

Modified: python/branches/py3k-cdecimal/Modules/cdecimal/convolute.c
==============================================================================
--- python/branches/py3k-cdecimal/Modules/cdecimal/convolute.c	(original)
+++ python/branches/py3k-cdecimal/Modules/cdecimal/convolute.c	Mon Nov  8 15:12:49 2010
@@ -20,8 +20,8 @@
 int
 fnt_convolute(mpd_uint_t *c1, mpd_uint_t *c2, mpd_size_t n, int modnum)
 {
-	int (*fnt)(mpd_uint_t *, mpd_size_t, int, int);
-	int (*inv_fnt)(mpd_uint_t *, mpd_size_t, int, int);
+	int (*fnt)(mpd_uint_t *, mpd_size_t, int);
+	int (*inv_fnt)(mpd_uint_t *, mpd_size_t, int);
 #ifdef PPRO
 	double dmod;
 	uint32_t dinvmod[3];
@@ -48,10 +48,10 @@
 		inv_fnt = inv_four_step_fnt;
 	}
 
-	if (!fnt(c1, n, modnum, UNORDERED)) {
+	if (!fnt(c1, n, modnum)) {
 		return 0;
 	}
-	if (!fnt(c2, n, modnum, UNORDERED)) {
+	if (!fnt(c2, n, modnum)) {
 		return 0;
 	}
 	for (i = 0; i < n-1; i += 2) {
@@ -64,7 +64,7 @@
 		c1[i+1] = x1;
 	}
 
-	if (!inv_fnt(c1, n, modnum, UNORDERED)) {
+	if (!inv_fnt(c1, n, modnum)) {
 		return 0;
 	}
 	for (i = 0; i < n-3; i += 4) {
@@ -87,8 +87,8 @@
 int
 fnt_autoconvolute(mpd_uint_t *c1, mpd_size_t n, int modnum)
 {
-	int (*fnt)(mpd_uint_t *, mpd_size_t, int, int);
-	int (*inv_fnt)(mpd_uint_t *, mpd_size_t, int, int);
+	int (*fnt)(mpd_uint_t *, mpd_size_t, int);
+	int (*inv_fnt)(mpd_uint_t *, mpd_size_t, int);
 #ifdef PPRO
 	double dmod;
 	uint32_t dinvmod[3];
@@ -115,7 +115,7 @@
 		inv_fnt = inv_four_step_fnt;
 	}
 
-	if (!fnt(c1, n, modnum, UNORDERED)) {
+	if (!fnt(c1, n, modnum)) {
 		return 0;
 	}
 	for (i = 0; i < n-1; i += 2) {
@@ -126,7 +126,7 @@
 		c1[i+1] = x1;
 	}
 
-	if (!inv_fnt(c1, n, modnum, UNORDERED)) {
+	if (!inv_fnt(c1, n, modnum)) {
 		return 0;
 	}
 	for (i = 0; i < n-3; i += 4) {

Modified: python/branches/py3k-cdecimal/Modules/cdecimal/crt.c
==============================================================================
--- python/branches/py3k-cdecimal/Modules/cdecimal/crt.c	(original)
+++ python/branches/py3k-cdecimal/Modules/cdecimal/crt.c	Mon Nov  8 15:12:49 2010
@@ -63,7 +63,7 @@
 		w[2] = 0;
 	}
 	else {
-		_mpd_div_word(&w[2], &r1, u[2], v);
+		_mpd_div_word(&w[2], &r1, u[2], v); /* GCOV_NOT_REACHED */
 	}
 
 	_mpd_div_words(&w[1], &r2, r1, u[1], v);

Modified: python/branches/py3k-cdecimal/Modules/cdecimal/difradix2.c
==============================================================================
--- python/branches/py3k-cdecimal/Modules/cdecimal/difradix2.c	(original)
+++ python/branches/py3k-cdecimal/Modules/cdecimal/difradix2.c	Mon Nov  8 15:12:49 2010
@@ -32,7 +32,7 @@
 			a[r] = t;
 		}
 		x += 1;
-		r ^= (n - (n >> (BSF(x)+1)));
+		r ^= (n - (n >> (mpd_bsf(x)+1)));
 	} while (x < n);
 }
 

Modified: python/branches/py3k-cdecimal/Modules/cdecimal/error.c
==============================================================================
--- python/branches/py3k-cdecimal/Modules/cdecimal/error.c	(original)
+++ python/branches/py3k-cdecimal/Modules/cdecimal/error.c	Mon Nov  8 15:12:49 2010
@@ -19,7 +19,7 @@
 	va_end(ap);
 
 	if (action == MPD_ERR_EXIT) {
-		exit(EXIT_FAILURE);
+		exit(EXIT_FAILURE); /* GCOV_NOT_REACHED */
 	}
 }
 

Modified: python/branches/py3k-cdecimal/Modules/cdecimal/fnt.c
==============================================================================
--- python/branches/py3k-cdecimal/Modules/cdecimal/fnt.c	(original)
+++ python/branches/py3k-cdecimal/Modules/cdecimal/fnt.c	Mon Nov  8 15:12:49 2010
@@ -16,7 +16,7 @@
 
 /* forward transform, sign = -1 */
 int
-std_fnt(mpd_uint_t *a, mpd_size_t n, int modnum, int ordered UNUSED)
+std_fnt(mpd_uint_t *a, mpd_size_t n, int modnum)
 {
 	struct fnt_params *tparams;
 
@@ -35,7 +35,7 @@
 
 /* reverse transform, sign = 1 */
 int
-std_inv_fnt(mpd_uint_t *a, mpd_size_t n, int modnum, int ordered UNUSED)
+std_inv_fnt(mpd_uint_t *a, mpd_size_t n, int modnum)
 {
 	struct fnt_params *tparams;
 

Modified: python/branches/py3k-cdecimal/Modules/cdecimal/fnt.h
==============================================================================
--- python/branches/py3k-cdecimal/Modules/cdecimal/fnt.h	(original)
+++ python/branches/py3k-cdecimal/Modules/cdecimal/fnt.h	Mon Nov  8 15:12:49 2010
@@ -12,8 +12,8 @@
 #include <stdio.h>
 
 
-int std_fnt(mpd_uint_t a[], mpd_size_t n, int modnum, int ordered UNUSED);
-int std_inv_fnt(mpd_uint_t a[], mpd_size_t n, int modnum, int ordered UNUSED);
+int std_fnt(mpd_uint_t a[], mpd_size_t n, int modnum);
+int std_inv_fnt(mpd_uint_t a[], mpd_size_t n, int modnum);
 
 
 #endif

Modified: python/branches/py3k-cdecimal/Modules/cdecimal/fourstep.c
==============================================================================
--- python/branches/py3k-cdecimal/Modules/cdecimal/fourstep.c	(original)
+++ python/branches/py3k-cdecimal/Modules/cdecimal/fourstep.c	Mon Nov  8 15:12:49 2010
@@ -118,7 +118,7 @@
 
 /* forward transform, sign = -1; transform length = 3 * 2^n */
 int
-four_step_fnt(mpd_uint_t *a, mpd_size_t n, int modnum, int ordered)
+four_step_fnt(mpd_uint_t *a, mpd_size_t n, int modnum)
 {
 	mpd_size_t R = 3; /* number of rows */
 	mpd_size_t C = n / 3; /* number of columns */
@@ -163,21 +163,24 @@
 
 	/* transform rows */
 	for (s = a; s < a+n; s += C) {
-		if (!six_step_fnt(s, C, modnum, ordered)) {
+		if (!six_step_fnt(s, C, modnum)) {
 			return 0;
 		}
 	}
 
+#if 0
+	/* An unordered transform is sufficient for convolution. */
 	if (ordered) {
 		transpose_3xpow2(a, R, C);
 	}
+#endif
 
 	return 1;
 }
 
 /* backward transform, sign = 1; transform length = 3 * 2^n */
 int
-inv_four_step_fnt(mpd_uint_t *a, mpd_size_t n, int modnum, int ordered)
+inv_four_step_fnt(mpd_uint_t *a, mpd_size_t n, int modnum)
 {
 	mpd_size_t R = 3; /* number of rows */
 	mpd_size_t C = n / 3; /* number of columns */
@@ -196,13 +199,16 @@
 	assert(n <= 3*MPD_MAXTRANSFORM_2N);
 
 
+#if 0
+	/* An unordered transform is sufficient for convolution. */
 	if (ordered) {
 		transpose_3xpow2(a, C, R);
 	}
+#endif
 
 	/* transform rows */
 	for (s = a; s < a+n; s += C) {
-		if (!inv_six_step_fnt(s, C, modnum, ordered)) {
+		if (!inv_six_step_fnt(s, C, modnum)) {
 			return 0;
 		}
 	}

Modified: python/branches/py3k-cdecimal/Modules/cdecimal/fourstep.h
==============================================================================
--- python/branches/py3k-cdecimal/Modules/cdecimal/fourstep.h	(original)
+++ python/branches/py3k-cdecimal/Modules/cdecimal/fourstep.h	Mon Nov  8 15:12:49 2010
@@ -12,8 +12,8 @@
 #include <stdio.h>
 
 
-int four_step_fnt(mpd_uint_t *a, mpd_size_t n, int modnum, int ordered);
-int inv_four_step_fnt(mpd_uint_t *a, mpd_size_t n, int modnum, int ordered);
+int four_step_fnt(mpd_uint_t *a, mpd_size_t n, int modnum);
+int inv_four_step_fnt(mpd_uint_t *a, mpd_size_t n, int modnum);
 
 
 #endif

Modified: python/branches/py3k-cdecimal/Modules/cdecimal/io.c
==============================================================================
--- python/branches/py3k-cdecimal/Modules/cdecimal/io.c	(original)
+++ python/branches/py3k-cdecimal/Modules/cdecimal/io.c	Mon Nov  8 15:12:49 2010
@@ -161,13 +161,13 @@
 mpd_qset_string(mpd_t *dec, const char *s, const mpd_context_t *ctx,
                 uint32_t *status)
 {
-	mpd_ssize_t q, r, declen;
+	mpd_ssize_t q, r, len;
 	const char *coeff, *end;
 	const char *dpoint = NULL, *exp = NULL;
-	size_t len;
+	size_t digits;
 	uint8_t sign = MPD_POS;
 
-	dec->flags = 0;
+	mpd_set_flags(dec, 0);
 	dec->len = 0;
 	dec->exp = 0;
 
@@ -192,9 +192,9 @@
 		/* payload consists entirely of zeros */
 		if (*coeff == '\0')
 			return;
-		len = end - coeff;
+		digits = end - coeff;
 		/* prec >= 1, clamp is 0 or 1 */
-		if (len > (size_t)(ctx->prec-ctx->clamp))
+		if (digits > (size_t)(ctx->prec-ctx->clamp))
 			goto conversion_error;
 	} /* sNaN */
 	else if (_mpd_strneq(s, "snan", "SNAN", 4)) {
@@ -208,8 +208,8 @@
 		/* payload consists entirely of zeros */
 		if (*coeff == '\0')
 			return;
-		len = end - coeff;
-		if (len > (size_t)(ctx->prec-ctx->clamp))
+		digits = end - coeff;
+		if (digits > (size_t)(ctx->prec-ctx->clamp))
 			goto conversion_error;
 	}
 	else if (_mpd_strneq(s, "inf", "INF", 3)) {
@@ -231,39 +231,50 @@
 			/* exponent-part */
 			end = exp; exp++;
 			dec->exp = strtoexp(exp);
-			if (errno == EINVAL)
-				goto conversion_error;
-			if ((errno == ERANGE && dec->exp == MPD_SSIZE_MAX)
-			    || dec->exp > MPD_EXP_INF)
-				dec->exp = MPD_EXP_INF;
-			else if ((errno == ERANGE && dec->exp == MPD_SSIZE_MIN)
-			         || dec->exp < MPD_EXP_CLAMP)
-				dec->exp = MPD_EXP_CLAMP;
+			if (errno) {
+				if (!(errno == ERANGE &&
+				     (dec->exp == MPD_SSIZE_MAX ||
+				      dec->exp == MPD_SSIZE_MIN)))
+					goto conversion_error;
+			}
 		}
 
-	        len = end - coeff;
+	        digits = end - coeff;
 		if (dpoint) {
-			dec->exp -= (end-dpoint-1);
-			if (dpoint > coeff) len--;
+			size_t fracdigits = end-dpoint-1;
+			if (dpoint > coeff) digits--;
+
+			if (fracdigits > MPD_MAX_PREC) {
+				goto conversion_error;
+			}
+ 			if (dec->exp < (MPD_SSIZE_MIN+1)+(mpd_ssize_t)fracdigits) {
+				dec->exp = MPD_SSIZE_MIN+1;
+			}
+			else {
+				dec->exp -= (mpd_ssize_t)fracdigits;
+			}
 		}
-		if (len > MPD_MAX_PREC) {
+		if (digits > MPD_MAX_PREC) {
 			goto conversion_error;
 		}
+		if (dec->exp > MPD_EXP_INF) {
+			dec->exp = MPD_EXP_INF;
+		}
 	}
 
-	_mpd_idiv_word(&q, &r, (mpd_ssize_t)len, MPD_RDIGITS);
+	_mpd_idiv_word(&q, &r, (mpd_ssize_t)digits, MPD_RDIGITS);
 
-	declen = (r == 0) ? q : q+1;
-	if (declen == 0) {
-		goto conversion_error;
+	len = (r == 0) ? q : q+1;
+	if (len == 0) {
+		goto conversion_error; /* GCOV_NOT_REACHED */
 	}
-	if (!mpd_qresize(dec, declen, status)) {
+	if (!mpd_qresize(dec, len, status)) {
 		mpd_seterror(dec, MPD_Malloc_error, status);
 		return;
 	}
-	dec->len = declen;
+	dec->len = len;
 
-	string_to_coeff(dec->data, coeff, dpoint, (int)r, declen);
+	string_to_coeff(dec->data, coeff, dpoint, (int)r, len);
 
 	mpd_setdigits(dec);
 	mpd_qfinalize(dec, ctx, status);
@@ -440,7 +451,7 @@
 			cp += 8;
 		}
 		else { /* debug */
-			abort();
+			abort(); /* GCOV_NOT_REACHED */
 		}
 	}
 	else {
@@ -859,15 +870,16 @@
 	int pad = 0;
 
 	n_sign = sign ? 1 : 0;
-	n_sep = strlen(spec->sep);
+	n_sep = (mpd_ssize_t)strlen(spec->sep);
 	g = spec->grouping;
 	dest->cur = dest->nbytes;
 	dest->nbytes = dest->nchars = 0;
 
-	_mbstr_copy_ascii(dest, rest, strlen(rest));
+	/* rest <= MPD_MAX_PREC */
+	_mbstr_copy_ascii(dest, rest, (mpd_ssize_t)strlen(rest));
 	
 	if (dot) {
-		_mbstr_copy_char(dest, dot, strlen(dot));
+		_mbstr_copy_char(dest, dot, (mpd_ssize_t)strlen(dot));
 	}
 
 	consume = *g;
@@ -920,7 +932,7 @@
 	const char *sign = NULL, *intpart = NULL;
 	const char *dot = NULL, *rest = NULL;
 	const char *dp;
-	size_t n_int;
+	mpd_ssize_t n_int;
 
 	assert(result->data == NULL);
 
@@ -935,14 +947,14 @@
 		while (isdigit((uchar)*dp)) {
 			dp++;
 		}
-		n_int = dp-intpart;
+		n_int = (mpd_ssize_t)(dp-intpart);
 	}
 	if (*dp == '.') {
 		if (*spec->dot == '\0') {
 		        /* decimal point must be present */
-			*status |= MPD_Invalid_operation;
-			mpd_free(decstring);
-			return;
+			*status |= MPD_Invalid_operation; /* GCOV_NOT_REACHED */
+			mpd_free(decstring); /* GCOV_NOT_REACHED */
+			return; /* GCOV_NOT_REACHED */
 		}
 		dp++; dot = spec->dot;
 	}
@@ -951,7 +963,7 @@
 
 	if (!dot && !(intpart && *spec->sep && *spec->grouping)) {
 		result->data = decstring;
-		result->nbytes = result->nchars = strlen(decstring);
+		result->nbytes = result->nchars = (mpd_ssize_t)strlen(decstring);
 		return;
 	}
 
@@ -976,16 +988,16 @@
 _mpd_add_pad(mpd_mbstr_t *result, mpd_spec_t *spec, uint32_t *status)
 {
 	if (result->nchars < spec->min_width) {
+		mpd_ssize_t add_chars, add_bytes;
 		size_t lpad = 0, rpad = 0;
-		size_t add_chars, add_bytes, n_fill;
-		size_t len, i, j;
+		size_t n_fill, len, i, j;
 		uint8_t err = 0;
 		char *cp;
 
 		n_fill = strlen(spec->fill);
 		add_chars = (spec->min_width - result->nchars);
 		/* max value: MPD_MAX_PREC * 4 */
-		add_bytes = add_chars * n_fill;
+		add_bytes = add_chars * (mpd_ssize_t)n_fill;
 
 		cp = result->data = mpd_realloc(result->data,
 		                                result->nbytes+add_bytes+1,
@@ -993,6 +1005,7 @@
 		if (err) {
 			*status |= MPD_Malloc_error;
 			mpd_free(result->data);
+			result->data = NULL;
 			return;
 		}
 
@@ -1057,6 +1070,7 @@
 
 
 	if (spec->min_width > MPD_MAX_PREC) {
+		*status |= MPD_Invalid_operation;
 		return NULL;
 	}
 
@@ -1081,7 +1095,7 @@
 		flags |= MPD_FMT_SIGN_PLUS;
 	}
 
-	mpd_maxcontext(&workctx);
+	mpd_maxcontext_plus(&workctx, ctx);
 	workctx.round = ctx->round;
 	if (mpd_isspecial(&tmp)) {
 		/* no percent formatting */
@@ -1148,7 +1162,8 @@
 
 	if (spec->min_width) {
 		if (result.nbytes == 0) {
-			result.nbytes = result.nchars = strlen(result.data);
+			result.nbytes = result.nchars =
+			        (mpd_ssize_t)strlen(result.data);
 		}
 		_mpd_add_pad(&result, spec, status);
 	}
@@ -1328,6 +1343,7 @@
 	return (int)(cp-dest); /* strlen, without NUL terminator */
 }
 
+/* The following two functions are mainly intended for debugging. */
 void
 mpd_fprint(FILE *file, const mpd_t *dec)
 {
@@ -1339,7 +1355,7 @@
 		mpd_free(decstring);
 	}
 	else {
-		fputs("mpd_fprint: output error\n", file);
+		fputs("mpd_fprint: output error\n", file); /* GCOV_NOT_REACHED */
 	}
 }
 
@@ -1354,7 +1370,7 @@
 		mpd_free(decstring);
 	}
 	else {
-		fputs("mpd_fprint: output error", stderr);
+		fputs("mpd_fprint: output error\n", stderr); /* GCOV_NOT_REACHED */
 	}
 }
 

Modified: python/branches/py3k-cdecimal/Modules/cdecimal/memory.c
==============================================================================
--- python/branches/py3k-cdecimal/Modules/cdecimal/memory.c	(original)
+++ python/branches/py3k-cdecimal/Modules/cdecimal/memory.c	Mon Nov  8 15:12:49 2010
@@ -19,6 +19,7 @@
 void (* mpd_free)(void *ptr) = free;
 
 
+
 /* emulate calloc if it is not available */
 void *
 mpd_callocfunc_em(size_t nmemb, size_t size)
@@ -27,11 +28,11 @@
 	size_t req;
 
 #if MPD_SIZE_MAX < SIZE_MAX
-	if (size > MPD_SIZE_MAX) {
+	if (nmemb > MPD_SIZE_MAX || size > MPD_SIZE_MAX) {
 		return NULL;
 	}
 #endif
-	req = mul_size_t(nmemb, size);
+	req = mul_size_t((mpd_size_t)nmemb, (mpd_size_t)size);
 	if ((ptr = mpd_mallocfunc(req)) == NULL) {
 		return NULL;
 	}
@@ -102,40 +103,6 @@
 	return ptr;
 }
 
-/* mpd_callocfunc must have overflow checking */
-void *
-mpd_sh_calloc(mpd_size_t struct_size, mpd_size_t nmemb, mpd_size_t size)
-{
-	void *ptr;
-	mpd_size_t req;
-
-	req = mul_size_t(nmemb, size);
-	req = add_size_t(req, struct_size);
-	if ((ptr = mpd_callocfunc(req, 1)) == NULL) {
-		return NULL;
-	}
-
-	return ptr;
-}
-
-/* struct hack realloc with overflow checking */
-void *
-mpd_sh_realloc(void *ptr, mpd_size_t struct_size, mpd_size_t nmemb,
-               mpd_size_t size, uint8_t *err)
-{
-	void *new;
-	mpd_size_t req;
-
-	req = mul_size_t(nmemb, size);
-	req = add_size_t(req, struct_size);
-	if ((new = mpd_reallocfunc(ptr, req)) == NULL) {
-		*err = 1;
-		return ptr;
-	}
-
-	return new;
-}
-
 
 /* Allocate a new decimal with data-size 'size'.
  * In case of an error the return value is NULL.

Modified: python/branches/py3k-cdecimal/Modules/cdecimal/mpdecimal.c
==============================================================================
--- python/branches/py3k-cdecimal/Modules/cdecimal/mpdecimal.c	(original)
+++ python/branches/py3k-cdecimal/Modules/cdecimal/mpdecimal.c	Mon Nov  8 15:12:49 2010
@@ -32,16 +32,21 @@
   #endif
 #endif
 
-#if defined(__GLIBC__) && !defined(__INTEL_COMPILER)
-  #define HAVE_80BIT_LONG_DOUBLE
+#if defined(__x86_64__) && defined(__GLIBC__) && !defined(__INTEL_COMPILER)
+  #define USE_80BIT_LONG_DOUBLE
 #endif
 
 #if defined(_MSC_VER)
   #define ALWAYS_INLINE __forceinline
 #else
-  #define ALWAYS_INLINE inline __attribute__ ((always_inline))
+  #ifdef TEST_COVERAGE
+    #define ALWAYS_INLINE
+  #else
+    #define ALWAYS_INLINE inline __attribute__ ((always_inline))
+  #endif
 #endif
 
+
 #define MPD_NEWTONDIV_CUTOFF 1024L
 
 #define MPD_NEW_STATIC(name, flags, exp, digits, len) \
@@ -81,7 +86,7 @@
 static inline void _mpd_qpow_uint(mpd_t *result, mpd_t *base, mpd_uint_t exp,
                 uint8_t resultsign, const mpd_context_t *ctx, uint32_t *status);
 
-static mpd_uint_t mpd_qsshiftr(mpd_t *result, const mpd_t *a, mpd_ssize_t n);
+mpd_uint_t mpd_qsshiftr(mpd_t *result, const mpd_t *a, mpd_ssize_t n);
 
 
 /******************************************************************************/
@@ -152,7 +157,7 @@
 ALWAYS_INLINE mpd_ssize_t
 mpd_adjexp(const mpd_t *dec)
 {
-	return dec->exp + dec->digits - 1;
+	return (dec->exp + dec->digits) - 1;
 }
 
 /* Etiny */
@@ -692,7 +697,7 @@
 	result->data[0] = 0;
 }
 
-/* Set the coefficient to all nines. Does not raise. */
+/* Set the coefficient to all nines. */
 void
 mpd_qmaxcoeff(mpd_t *result, const mpd_context_t *ctx, uint32_t *status)
 {
@@ -1108,7 +1113,7 @@
 #ifdef CONFIG_32
 /* set a decimal from a uint64_t */
 static void
-_c32setu64(mpd_t *result, uint64_t u, uint32_t *status)
+_c32setu64(mpd_t *result, uint64_t u, uint8_t sign, uint32_t *status)
 {
 	mpd_uint_t w[3];
 	uint64_t q;
@@ -1128,6 +1133,7 @@
 		result->data[i] = w[i];
 	}
 
+	mpd_set_sign(result, sign);
 	result->exp = 0;
 	result->len = len;
 	mpd_setdigits(result);
@@ -1137,7 +1143,7 @@
 _c32_qset_u64(mpd_t *result, uint64_t a, const mpd_context_t *ctx,
               uint32_t *status)
 {
-	_c32setu64(result, a, status);
+	_c32setu64(result, a, MPD_POS, status);
 	mpd_qfinalize(result, ctx, status);
 }
 
@@ -1161,8 +1167,7 @@
 	else {
 		u = a;
 	}
-	_c32setu64(result, u, status);
-	mpd_set_sign(result, sign);
+	_c32setu64(result, u, sign, status);
 	mpd_qfinalize(result, ctx, status);
 }
 #endif /* CONFIG_32 */
@@ -1199,8 +1204,8 @@
  *
  * If the operation is impossible, MPD_Invalid_operation is set.
  */
-mpd_uint_t
-mpd_qget_uint(const mpd_t *a, uint32_t *status)
+static mpd_uint_t
+_mpd_qget_uint(int use_sign, const mpd_t *a, uint32_t *status)
 {
 	mpd_t tmp;
 	mpd_uint_t tmp_data[2];
@@ -1210,12 +1215,14 @@
 		*status |= MPD_Invalid_operation;
 		return MPD_UINT_MAX;
 	}
-
-	assert(a->len > 0);
-
 	if (mpd_iszero(a)) {
 		return 0;
 	}
+	if (use_sign && mpd_isnegative(a)) {
+		*status |= MPD_Invalid_operation;
+		return MPD_UINT_MAX;
+	}
+
 	if (a->digits+a->exp > MPD_RDIGITS+1) {
 		*status |= MPD_Invalid_operation;
 		return MPD_UINT_MAX;
@@ -1252,6 +1259,26 @@
 	return lo;
 }
 
+/*
+ * Sets Invalid_operation for:
+ *   - specials
+ *   - negative numbers (except negative zero)
+ *   - non-integers
+ *   - overflow
+ */
+mpd_uint_t
+mpd_qget_uint(const mpd_t *a, uint32_t *status)
+{
+	return _mpd_qget_uint(1, a, status);
+}
+
+/* Same as above, but gets the absolute value, i.e. the sign is ignored. */
+mpd_uint_t
+mpd_qabs_uint(const mpd_t *a, uint32_t *status)
+{
+	return _mpd_qget_uint(0, a, status);
+}
+
 /* quietly get an mpd_ssize_t from a decimal */
 mpd_ssize_t
 mpd_qget_ssize(const mpd_t *a, uint32_t *status)
@@ -1259,7 +1286,7 @@
 	mpd_uint_t u;
 	int isneg;
 
-	u = mpd_qget_uint(a, status);
+	u = mpd_qabs_uint(a, status);
 	if (*status&MPD_Invalid_operation) {
 		return MPD_SSIZE_MAX;
 	}
@@ -1421,7 +1448,7 @@
 		return (!(rnd == 0) && (ld == 0 || ld == 5));
 	default:
 		/* Without a valid context, further results will be undefined. */
-		return 0;
+		return 0; /* GCOV_NOT_REACHED */
 	}
 }
 
@@ -1558,7 +1585,7 @@
 			}
 			break;
 		default: /* debug */
-			abort();
+			abort(); /* GCOV_NOT_REACHED */
 		}
 
 		*status |= MPD_Overflow|MPD_Inexact|MPD_Rounded;
@@ -1570,6 +1597,9 @@
 		(void)mpd_qshiftl(dec, dec, shift, status);
 		dec->exp -= shift;
 		*status |= MPD_Clamped;
+		if (adjexp < ctx->emin) {
+			*status |= MPD_Subnormal;
+		}
 	}
 	else if (adjexp < ctx->emin) {
 
@@ -1588,7 +1618,7 @@
 		if (dec->exp < etiny) {
 			/* At this point adjexp=exp+digits-1 < emin and exp < etiny=emin-prec+1,
 			 * so shift=emin-prec+1-exp > digits-prec, so digits-shift < prec.
-			 * [acl2 proof: checkexp-1] */
+			 * [ACL2 proof: checkexp-1] */
 			shift = etiny - dec->exp;
 			rnd = (int)mpd_qshiftr_inplace(dec, shift);
 			dec->exp = etiny;
@@ -1680,7 +1710,6 @@
 
 /*
  * Copy a decimal. In case of an error, status is set to MPD_Malloc_error.
- * Does not raise.
  */
 int
 mpd_qcopy(mpd_t *result, const mpd_t *a, uint32_t *status)
@@ -1720,7 +1749,6 @@
 /*
  * Return a newly allocated copy of the operand. In case of an error,
  * status is set to MPD_Malloc_error and the return value is NULL.
- * Does not raise.
  */
 mpd_t *
 mpd_qncopy(const mpd_t *a)
@@ -2174,8 +2202,7 @@
 	assert(n >= 0);
 
 	if (mpd_iszerocoeff(a) || n == 0) {
-		mpd_qcopy(result, a, status);
-		return 1;
+		return mpd_qcopy(result, a, status);
 	}
 
 	size = mpd_digits_to_size(a->digits+n);
@@ -2220,7 +2247,7 @@
  * caller's responsibility to make sure that the array is big enough.
  * The function cannot fail.
  */ 
-static mpd_uint_t
+mpd_uint_t
 mpd_qsshiftr(mpd_t *result, const mpd_t *a, mpd_ssize_t n)
 {
 	mpd_uint_t rnd;
@@ -2678,7 +2705,8 @@
 
 	if (a->digits > ctx->prec) {
 		if (!mpd_qcopy(&tmp, a, status)) {
-			return;
+			mpd_seterror(result, MPD_Malloc_error, status);
+			goto finish;
 		}
 		_mpd_cap(&tmp, ctx);
 		a = &tmp;
@@ -2726,7 +2754,7 @@
 		return;
 	}
 
-	n = mpd_qget_uint(b, &workstatus);
+	n = mpd_qabs_uint(b, &workstatus);
 	/* the spec demands this */
 	maxjump = 2 * (ctx->emax + ctx->prec);
 
@@ -3103,7 +3131,7 @@
 _mpd_qsub(mpd_t *result, const mpd_t *a, const mpd_t *b,
          const mpd_context_t *ctx, uint32_t *status)
 {
-	_mpd_qaddsub(result, a, b, !mpd_sign(b), ctx, status);
+	 _mpd_qaddsub(result, a, b, !mpd_sign(b), ctx, status);
 }
 
 /* Add a and b. */
@@ -3234,6 +3262,40 @@
 }
 #endif
 
+/* Subtract int32_t from decimal. */
+void
+mpd_qsub_i32(mpd_t *result, const mpd_t *a, int32_t b,
+             const mpd_context_t *ctx, uint32_t *status)
+{
+	mpd_qsub_ssize(result, a, b, ctx, status);
+}
+
+/* Subtract uint32_t from decimal. */
+void
+mpd_qsub_u32(mpd_t *result, const mpd_t *a, uint32_t b,
+             const mpd_context_t *ctx, uint32_t *status)
+{
+	mpd_qsub_uint(result, a, b, ctx, status);
+}
+
+#ifdef CONFIG_64
+/* Subtract int64_t from decimal. */
+void
+mpd_qsub_i64(mpd_t *result, const mpd_t *a, int64_t b,
+             const mpd_context_t *ctx, uint32_t *status)
+{
+	mpd_qsub_ssize(result, a, b, ctx, status);
+}
+
+/* Subtract uint64_t from decimal. */
+void
+mpd_qsub_u64(mpd_t *result, const mpd_t *a, uint64_t b,
+             const mpd_context_t *ctx, uint32_t *status)
+{
+	mpd_qsub_uint(result, a, b, ctx, status);
+}
+#endif
+
 
 /* Divide infinities. */
 static void
@@ -3260,7 +3322,7 @@
           const mpd_context_t *ctx, uint32_t *status)
 {
 	MPD_NEW_STATIC(aligned,0,0,0,0);
-	mpd_uint_t ld, carry = 0;
+	mpd_uint_t ld;
 	mpd_ssize_t shift, exp, tz;
 	mpd_ssize_t newsize;
 	mpd_ssize_t ideal_exp;
@@ -3338,6 +3400,10 @@
 	else {
 		MPD_NEW_STATIC(r,0,0,0,0);
 		_mpd_qbarrett_divmod(q, &r, a, b, status);
+		if (mpd_isspecial(q) || mpd_isspecial(&r)) {
+			mpd_del(&r);
+			goto finish;
+		}
 		rem = !mpd_iszerocoeff(&r);
 		mpd_del(&r);
 		newsize = q->len;
@@ -3353,14 +3419,7 @@
 	if (rem) {
 		ld = mpd_lsd(q->data[0]);
 		if (ld == 0 || ld == 5) {
-			carry = _mpd_baseincr(q->data, q->len);
-			if (carry) {
-				if (!mpd_qresize(q, q->len+1, status)) {
-					mpd_seterror(q, MPD_Malloc_error, status);
-					goto finish;
-				}
-				q->data[q->len] = 1;
-			}
+			q->data[0] += 1;
 		}
 	}
 	else if (action == SET_IDEAL_EXP && shift > 0) {
@@ -3402,7 +3461,7 @@
 	ideal_exp = (a->exp > b->exp) ?  b->exp : a->exp;
 	if (mpd_iszerocoeff(a)) {
 		if (!mpd_qcopy(r, a, status)) {
-			goto nanresult;
+			goto nanresult; /* GCOV_NOT_REACHED */
 		}
 		r->exp = ideal_exp;
 		_settriple(q, sign_ab, 0, 0);
@@ -3493,6 +3552,9 @@
 	}
 	else {
 		_mpd_qbarrett_divmod(q, r, a, b, status);
+		if (mpd_isspecial(q) || mpd_isspecial(r)) {
+			goto nanresult;
+		}
 		if (mpd_isinfinite(q) || q->digits > ctx->prec) {
 			*status |= MPD_Division_impossible;
 			goto nanresult;
@@ -3564,7 +3626,7 @@
 			return;
 		}
 		/* debug */
-		abort();
+		abort(); /* GCOV_NOT_REACHED */
 	}
 	if (mpd_iszerocoeff(b)) {
 		if (mpd_iszerocoeff(a)) {
@@ -3609,7 +3671,7 @@
 			return;
 		}
 		/* debug */
-		abort();
+		abort(); /* GCOV_NOT_REACHED */
 	}
 	if (mpd_iszerocoeff(b)) {
 		if (mpd_iszerocoeff(a)) {
@@ -3711,7 +3773,7 @@
 	f = ((double)msdigits + 1) / mpd_pow10[mpd_word_digits(msdigits)];
 
 #ifdef CONFIG_64
-  #if defined(__x86_64__) && defined(HAVE_80BIT_LONG_DOUBLE)
+  #ifdef USE_80BIT_LONG_DOUBLE
 	return ceill((1.435*(long double)prec - 1.182)
 	             / log10l((long double)prec/f));
   #else
@@ -3753,6 +3815,8 @@
 	MPD_NEW_CONST(word,0,0,0,1,1,1);
 	mpd_ssize_t j, n, t;
 
+	assert(!mpd_isspecial(a));
+
 	/*
 	 * We are calculating e^x = e^(r*10^t) = (e^r)^(10^t), where r < 1 and t >= 0.
 	 *
@@ -3766,10 +3830,10 @@
 	 *       will occur when (e^-1)^(10^t) < 10^(etiny-1). If we consider MIN_ETINY,
 	 *       this will also happen for t > 10 (32 bit) or (t > 19) (64 bit).
 	 */
-#ifdef CONFIG_32
+#if defined(CONFIG_64)
+ 	#define MPD_EXP_MAX_T 19
+#elif defined(CONFIG_32)
 	#define MPD_EXP_MAX_T 10
-#elif defined(CONFIG_64)
-	#define MPD_EXP_MAX_T 19
 #endif
 	t = a->digits + a->exp;
 	t = (t > 0) ? t : 0;
@@ -3792,8 +3856,8 @@
 	workctx.round = MPD_ROUND_HALF_EVEN;
 
 	if ((n = _mpd_get_exp_iterations(a, workctx.prec)) == MPD_SSIZE_MAX) {
-		mpd_seterror(result, MPD_Invalid_operation, status);
-		goto finish;
+		mpd_seterror(result, MPD_Invalid_operation, status); /* GCOV_UNLIKELY */
+		goto finish; /* GCOV_UNLIKELY */
 	}
 
 	if (!mpd_qcopy(result, a, status)) {
@@ -3811,6 +3875,9 @@
 		mpd_qadd(&sum, &sum, &one, &workctx, &workctx.status);
 	}
 
+#ifdef CONFIG_64
+	_mpd_qpow_uint(result, &sum, mpd_pow10[t], MPD_POS, &workctx, status);
+#else
 	if (t <= MPD_MAX_POW10) {
 		_mpd_qpow_uint(result, &sum, mpd_pow10[t], MPD_POS, &workctx, status);
 	}
@@ -3820,6 +3887,7 @@
 		               &workctx, status);
 		_mpd_qpow_uint(result, &tmp, mpd_pow10[t], MPD_POS, &workctx, status);
 	}
+#endif
 
 
 finish:
@@ -3864,7 +3932,10 @@
 		mpd_ssize_t prec;
 
 		if (result == a) {
-			mpd_qcopy(&aa, a, status);
+			if (!mpd_qcopy(&aa, a, status)) {
+				mpd_seterror(result, MPD_Malloc_error, status);
+				return;
+			}
 			a = &aa;
 		}
 
@@ -3948,18 +4019,38 @@
 #if MPD_RDIGITS != 19
   #error "mpdecimal.c: MPD_RDIGITS must be 19."
 #endif
-static mpd_uint_t mpd_ln10data[MPD_MINALLOC_MAX] = {
+static mpd_uint_t mpd_ln10_data[MPD_MINALLOC_MAX] = {
+  179914546843642076, 2302585092994045684
+};
+static mpd_uint_t mpd_ln10_init[2] = {
   179914546843642076, 2302585092994045684
 };
 #else
 #if MPD_RDIGITS != 9
   #error "mpdecimal.c: MPD_RDIGITS must be 9."
 #endif
-static mpd_uint_t mpd_ln10data[MPD_MINALLOC_MAX] = {299404568, 230258509};
+static mpd_uint_t mpd_ln10_data[MPD_MINALLOC_MAX] = {299404568, 230258509};
+static mpd_uint_t mpd_ln10_init[2] = {299404568, 230258509};
 #endif
 /* mpd_ln10 is cached in order to speed up computations */
 mpd_t mpd_ln10 = {MPD_STATIC|MPD_STATIC_DATA, -(2*MPD_RDIGITS-1),
-                  2*MPD_RDIGITS, 2, MPD_MINALLOC_MAX, mpd_ln10data};
+                  2*MPD_RDIGITS, 2, MPD_MINALLOC_MAX, mpd_ln10_data};
+
+static void
+mpd_reset_ln10(void)
+{
+	if (mpd_isdynamic_data(&mpd_ln10)) {
+		mpd_free(mpd_ln10.data);
+	}
+	mpd_ln10.data = mpd_ln10_data;
+	mpd_ln10_data[0] = mpd_ln10_init[0];
+	mpd_ln10_data[1] = mpd_ln10_init[1];
+	mpd_ln10.flags = MPD_STATIC|MPD_STATIC_DATA;
+	mpd_ln10.exp = -(2*MPD_RDIGITS-1);
+	mpd_ln10.digits = 2*MPD_RDIGITS;
+	mpd_ln10.len = 2;
+	mpd_ln10.alloc = MPD_MINALLOC_MAX;
+}
 
 /*
  * Initializes or updates mpd_ln10. If mpd_ln10 is cached and has exactly the
@@ -3977,13 +4068,17 @@
 	mpd_ssize_t klist[MPD_MAX_PREC_LOG2];
 	int i;
 
-	if (mpd_ln10.digits > maxprec+2*MPD_RDIGITS) {
+	if (mpd_isspecial(&mpd_ln10)) {
+		mpd_reset_ln10();
+	}
+
+	if (mpd_ln10.digits > maxprec) {
 		/* shift to smaller cannot fail */
 		mpd_qshiftr_inplace(&mpd_ln10, mpd_ln10.digits-maxprec);
 		mpd_ln10.exp = -(mpd_ln10.digits-1);
 		return;
 	}
-	else if (mpd_ln10.digits >= maxprec) {
+	else if (mpd_ln10.digits == maxprec) {
 		return;
 	}
 
@@ -4000,6 +4095,9 @@
 		mpd_qmul(&tmp, &static10, &tmp, &varcontext, status);
 		mpd_qsub(&tmp, &tmp, &one, &maxcontext, status);
 		mpd_qadd(&mpd_ln10, &mpd_ln10, &tmp, &maxcontext, status);
+		if (mpd_isspecial(&mpd_ln10)) {
+			break;
+		}
 	}
 
 	mpd_del(&tmp);
@@ -4091,6 +4189,8 @@
 	mpd_uint_t dummy, x;
 	int i;
 
+	assert(!mpd_isspecial(a) && !mpd_iszerocoeff(a));
+
 	/*
 	 * We are calculating ln(a) = ln(v * 10^t) = ln(v) + t*ln(10),
 	 * where 0.5 < v <= 5.
@@ -4184,6 +4284,9 @@
 
 		mpd_qsub(&tmp, &tmp, &one, &maxcontext, status);
 		mpd_qadd(z, z, &tmp, &maxcontext, status);
+		if (mpd_isspecial(z)) {
+			break;
+		}
 	}
 
 postloop:
@@ -4259,7 +4362,10 @@
 		mpd_ssize_t prec;
 
 		if (result == a) {
-			mpd_qcopy(&aa, a, status);
+			if (!mpd_qcopy(&aa, a, status)) {
+				mpd_seterror(result, MPD_Malloc_error, status);
+				return;
+			}
 			a = &aa;
 		}
 
@@ -4344,7 +4450,7 @@
 	}
 	if (mpd_coeff_ispow10(a)) {
 		uint8_t sign = 0;
-		mpd_ssize_t adjexp = mpd_adjexp(a);
+		adjexp = mpd_adjexp(a);
 		if (adjexp < 0) {
 			sign = 1;
 			adjexp = -adjexp;
@@ -4376,7 +4482,10 @@
 		mpd_ssize_t prec;
 
 		if (result == a) {
-			mpd_qcopy(&aa, a, status);
+			if (!mpd_qcopy(&aa, a, status)) {
+				mpd_seterror(result, MPD_Malloc_error, status);
+				return;
+			}
 			a = &aa;
 		}
 
@@ -4709,7 +4818,7 @@
 	mpd_size_t x, step;
 
 	assert(rsize >= 4);
-	log2rsize = BSR(rsize);
+	log2rsize = mpd_bsr(rsize);
 
 	if (rsize <= 1024) {
 		x = ONE_UM<<log2rsize;
@@ -4813,10 +4922,11 @@
 	memcpy(c3, u, ulen * (sizeof *c3));
 
 	if (u == v) {
-
-		fnt_autoconvolute(c1, n, P1);
-		fnt_autoconvolute(c2, n, P2);
-		fnt_autoconvolute(c3, n, P3);
+		if (!fnt_autoconvolute(c1, n, P1) ||
+		    !fnt_autoconvolute(c2, n, P2) ||
+		    !fnt_autoconvolute(c3, n, P3)) {
+			goto malloc_error;
+		}
 	}
 	else {
 		if ((vtmp = mpd_calloc(sizeof *vtmp, n)) == NULL) {
@@ -4824,15 +4934,24 @@
 		}
 
 		memcpy(vtmp, v, vlen * (sizeof *vtmp));
-		fnt_convolute(c1, vtmp, n, P1);
+		if (!fnt_convolute(c1, vtmp, n, P1)) {
+			mpd_free(vtmp);
+			goto malloc_error;
+		}
 
 		memcpy(vtmp, v, vlen * (sizeof *vtmp));
 		mpd_uint_zero(vtmp+vlen, n-vlen);
-		fnt_convolute(c2, vtmp, n, P2);
+		if (!fnt_convolute(c2, vtmp, n, P2)) {
+			mpd_free(vtmp);
+			goto malloc_error;
+		}
 
 		memcpy(vtmp, v, vlen * (sizeof *vtmp));
 		mpd_uint_zero(vtmp+vlen, n-vlen);
-		fnt_convolute(c3, vtmp, n, P3);
+		if (!fnt_convolute(c3, vtmp, n, P3)) {
+			mpd_free(vtmp);
+			goto malloc_error;
+		}
 
 		mpd_free(vtmp);
 	}
@@ -4893,14 +5012,14 @@
 			lt = lb + lb + 1;       // space needed for result array
 			mpd_uint_zero(w, lt);   // clear result array
 			if (!_karatsuba_rec_fnt(w, b, a+m, w+lt, lb, la-m)) { // b*ah
-				return 0;
+				return 0; /* GCOV_UNLIKELY */
 			}
 		}
 		else {
 			lt = (la-m) + (la-m) + 1;  // space needed for result array
 			mpd_uint_zero(w, lt);      // clear result array
 			if (!_karatsuba_rec_fnt(w, a+m, b, w+lt, la-m, lb)) { // ah*b
-				return 0;
+				return 0; /* GCOV_UNLIKELY */
 			}
 		}
 		_mpd_baseaddto(c+m, w, (la-m)+lb); // add ah*b*B**m
@@ -4908,7 +5027,7 @@
 		lt = m + m + 1;         // space needed for the result array
 		mpd_uint_zero(w, lt);   // clear result array
 		if (!_karatsuba_rec_fnt(w, a, b, w+lt, m, lb)) {  // al*b
-			return 0;
+			return 0; /* GCOV_UNLIKELY */
 		}
 		_mpd_baseaddto(c, w, m+lb);       // add al*b
 
@@ -4925,14 +5044,14 @@
 	_mpd_baseaddto(w+(m+1), b+m, lb-m);
 
 	if (!_karatsuba_rec_fnt(c+m, w, w+(m+1), w+2*(m+1), m+1, m+1)) {
-		return 0;
+		return 0; /* GCOV_UNLIKELY */
 	}
 
 	lt = (la-m) + (la-m) + 1;
 	mpd_uint_zero(w, lt);
 
 	if (!_karatsuba_rec_fnt(w, a+m, b+m, w+lt, la-m, lb-m)) {
-		return 0;
+		return 0; /* GCOV_UNLIKELY */
 	}
 
 	_mpd_baseaddto(c+2*m, w, (la-m) + (lb-m));
@@ -4942,7 +5061,7 @@
 	mpd_uint_zero(w, lt);
 
 	if (!_karatsuba_rec_fnt(w, a, b, w+lt, m, m)) {
-		return 0;
+		return 0; /* GCOV_UNLIKELY */
 	}
 	_mpd_baseaddto(c, w, m+m);
 	_mpd_basesubfrom(c+m, w, m+m);
@@ -4973,8 +5092,8 @@
 
 	m = _kmul_worksize(ulen, 3*(MPD_MAXTRANSFORM_2N/2));
 	if (m && ((w = mpd_calloc(m, sizeof *w)) == NULL)) {
-		mpd_free(result);
-		return NULL;
+		mpd_free(result); /* GCOV_UNLIKELY */
+		return NULL; /* GCOV_UNLIKELY */
 	}
 
 	if (!_karatsuba_rec_fnt(result, u, v, w, ulen, vlen)) {
@@ -5065,28 +5184,14 @@
 	}
 
 
-	if (big->len == 2) {
-		if ((rdata = mpd_calloc(rsize, sizeof *rdata)) == NULL) {
-			mpd_seterror(result, MPD_Malloc_error, status);
-			return;
-		}
-		_mpd_mul_2_le2(rdata, big->data, small->data, small->len);
-	}
-	else if (small->len == 1) {
+	if (small->len == 1) {
 		if ((rdata = mpd_calloc(rsize, sizeof *rdata)) == NULL) {
 			mpd_seterror(result, MPD_Malloc_error, status);
 			return;
 		}
 		_mpd_shortmul(rdata, big->data, big->len, small->data[0]);
 	}
-	else if (small->len <= 16 && rsize <= 64) {
-		if ((rdata = mpd_calloc(rsize, sizeof *rdata)) == NULL) {
-			mpd_seterror(result, MPD_Malloc_error, status);
-			return;
-		}
-		_mpd_basemul(rdata, small->data, big->data, small->len, big->len);
-	}
-	else if (small->len <= 256 && rsize <= 1024) {
+	else if (rsize <= 1024) {
 		rdata = _mpd_kmul(big->data, small->data, big->len, small->len, &rsize);
 		if (rdata == NULL) {
 			mpd_seterror(result, MPD_Malloc_error, status);
@@ -5103,8 +5208,8 @@
 	else {
 		rdata = _mpd_kmul_fnt(big->data, small->data, big->len, small->len, &rsize);
 		if (rdata == NULL) {
-			mpd_seterror(result, MPD_Malloc_error, status);
-			return;
+			mpd_seterror(result, MPD_Malloc_error, status); /* GCOV_UNLIKELY */
+			return; /* GCOV_UNLIKELY */
 		}
 	}
 
@@ -5254,17 +5359,17 @@
 				return;
 			}
 			else {
+				mpd_clear_flags(result);
 				mpd_qmaxcoeff(result, ctx, status);
 				if (mpd_isnan(result)) {
 					return;
 				}
-				mpd_clear_flags(result);
 				result->exp = ctx->emax - ctx->prec + 1;
 				return;
 			}
 		}
-		/* should not be reached */
-		abort();
+		/* debug */
+		abort(); /* GCOV_NOT_REACHED */
 	}
 
 	mpd_workcontext(&workctx, ctx);
@@ -5276,6 +5381,7 @@
 
 	mpd_qfinalize(result, &workctx, &workctx.status);
 	if (workctx.status&(MPD_Inexact|MPD_Errors)) {
+		*status |= (workctx.status&MPD_Errors);
 		return;
 	}
 
@@ -5301,6 +5407,7 @@
 				mpd_qcopy(result, a, status);
 			}
 			else {
+				mpd_clear_flags(result);
 				mpd_qmaxcoeff(result, ctx, status);
 				if (mpd_isnan(result)) {
 					return;
@@ -5315,12 +5422,13 @@
 	mpd_workcontext(&workctx, ctx);
 	workctx.round = MPD_ROUND_CEILING;
 
-	if (!mpd_qcopy(result, a, &workctx.status)) {
+	if (!mpd_qcopy(result, a, status)) {
 		return;
 	}
 
 	mpd_qfinalize(result, &workctx, &workctx.status);
 	if (workctx.status & (MPD_Inexact|MPD_Errors)) {
+		*status |= (workctx.status&MPD_Errors);
 		return;
 	}
 
@@ -5380,15 +5488,15 @@
 	mpd_uint_t n;
 
 	if (exp == 0) {
-		_settriple(result, resultsign, 1, 0);
-		return;
+		_settriple(result, resultsign, 1, 0); /* GCOV_NOT_REACHED */
+		return; /* GCOV_NOT_REACHED */
 	}
 
 	if (!mpd_qcopy(result, base, status)) {
 		return;
 	}
 
-	n = mpd_bits[BSR(exp)];
+	n = mpd_bits[mpd_bsr(exp)];
 	while (n >>= 1) {
 		mpd_qmul(result, result, result, ctx, &workstatus);
 		if (exp & n) {
@@ -5418,9 +5526,8 @@
 
 	mpd_maxcontext(&maxctx);
 
-	if (!mpd_qcopy(result, &one, status)) {
-		return;
-	}
+	/* resize to smaller cannot fail */
+	mpd_qcopy(result, &one, status);
 
 	while (!mpd_iszero(texp)) {
 		if (mpd_isodd(texp)) {
@@ -5432,8 +5539,8 @@
 		}
 		mpd_qmul(tbase, tbase, tbase, ctx, &workstatus);
 		mpd_qdivint(texp, texp, &two, &maxctx, &workstatus);
-		if (mpd_isnan(texp)) {
-			mpd_seterror(result, MPD_Division_undefined, status);
+		if (mpd_isnan(tbase) || mpd_isnan(texp)) {
+			mpd_seterror(result, workstatus&MPD_Errors, status);
 			return;
 		}
 	}
@@ -5472,11 +5579,11 @@
 		}
 	}
 
-	n = mpd_qget_uint(exp, &workctx.status);
+	n = mpd_qabs_uint(exp, &workctx.status);
 	if (workctx.status&MPD_Invalid_operation) {
 		if (!mpd_qcopy(&texp, exp, status)) {
-			mpd_setspecial(result, MPD_POS, MPD_NAN);
-			goto finish;
+			mpd_setspecial(result, MPD_POS, MPD_NAN); /* GCOV_UNLIKELY */
+			goto finish; /* GCOV_UNLIKELY */
 		}
 		_mpd_qpow_mpd(result, &tbase, &texp, resultsign, &workctx, status);
 	}
@@ -5540,9 +5647,13 @@
 			}
 			/* 1.000**3 = 1.000000000 */
 			mpd_qmul_ssize(result, exp, -base->exp, ctx, &workstatus);
+			if (workstatus&MPD_Errors) {
+				*status |= (workstatus&MPD_Errors);
+				return 0;
+			}
 			/* digits-1 after exponentiation */
 			shift = mpd_qget_ssize(result, &workstatus);
-			/* MPD_SSIZE_MAX on failure */
+			/* shift is MPD_SSIZE_MAX if result is too large */
 			if (shift > ctx->prec-1) {
 				shift = ctx->prec-1;
 				*status |= MPD_Rounded;
@@ -5553,9 +5664,11 @@
 			*status |= (MPD_Inexact|MPD_Rounded);
 		}
 		else {
-			return -2;
+			return -2; /* GCOV_NOT_REACHED */
+		}
+		if (!mpd_qshiftl(result, &one, shift, status)) {
+			return 0;
 		}
-		mpd_qshiftl(result, &one, shift, status);
 		result->exp = -shift;
 		mpd_set_flags(result, resultsign);
 	}
@@ -5563,131 +5676,140 @@
 	return cmp;
 }
 
+/*
+ * Detect certain over/underflow of x**y.
+ * ACL2 proof: pow_bounds.lisp.
+ *
+ *   Symbols:
+ *
+ *     e: EXP_INF or EXP_CLAMP
+ *     x: base
+ *     y: exponent
+ *
+ *     omega(e) = log10(abs(e))
+ *     zeta(x)  = log10(abs(log10(x)))
+ *     theta(y) = log10(abs(y))
+ *
+ *   Upper and lower bounds:
+ *
+ *     ub_omega(e) = ceil(log10(abs(e)))
+ *     lb_theta(y) = floor(log10(abs(y)))
+ *
+ *                  | floor(log10(floor(abs(log10(x))))) if x < 1/10 or x >= 10
+ *     lb_zeta(x) = | floor(log10(abs(x-1)/10)) if 1/10 <= x < 1
+ *                  | floor(log10(abs((x-1)/100))) if 1 < x < 10
+ *
+ *   ub_omega(e) and lb_theta(y) are obviously upper and lower bounds
+ *   for omega(e) and theta(y).
+ *
+ *   lb_zeta is a lower bound for zeta(x):
+ *
+ *     x < 1/10 or x >= 10:
+ *
+ *       abs(log10(x)) >= 1, so the outer log10 is well defined. Since log10
+ *       is strictly increasing, the end result is a lower bound.
+ *
+ *     1/10 <= x < 1:
+ *
+ *       We use: log10(x) <= (x-1)/log(10)
+ *               abs(log10(x)) >= abs(x-1)/log(10)
+ *               abs(log10(x)) >= abs(x-1)/10
+ *
+ *     1 < x < 10:
+ *
+ *       We use: (x-1)/(x*log(10)) < log10(x)
+ *               abs((x-1)/100) < abs(log10(x))
+ *
+ *       XXX: abs((x-1)/10) would work, need ACL2 proof.
+ *
+ *
+ *   Let (0 < x < 1 and y < 0) or (x > 1 and y > 0).                  (H1)
+ *   Let ub_omega(exp_inf) < lb_zeta(x) + lb_theta(y)                 (H2)
+ *
+ *   Then:
+ *       log10(abs(exp_inf)) < log10(abs(log10(x))) + log10(abs(y)).   (1)
+ *                   exp_inf < log10(x) * y                            (2)
+ *               10**exp_inf < x**y                                    (3)
+ *
+ *   Let (0 < x < 1 and y > 0) or (x > 1 and y < 0).                  (H3)
+ *   Let ub_omega(exp_clamp) < lb_zeta(x) + lb_theta(y)               (H4)
+ *                 
+ *   Then:
+ *     log10(abs(exp_clamp)) < log10(abs(log10(x))) + log10(abs(y)).   (4)
+ *              log10(x) * y < exp_clamp                               (5)
+ *                      x**y < 10**exp_clamp                           (6)
+ *
+ */
 static mpd_ssize_t
-_qlog10_exp_bound(const mpd_t *x, uint32_t *status)
+_lower_bound_zeta(const mpd_t *x, uint32_t *status)
 {
 	mpd_context_t maxctx;
 	MPD_NEW_STATIC(scratch,0,0,0,0);
-	MPD_NEW_CONST(tmp,0,0,1,1,1,1);
-	mpd_ssize_t t, numdigits, dendigits;
+	mpd_ssize_t t, u;
 
-	/*
-	 * This function is designed to weed out cases where x**y will clearly
-	 * over/underflow. The chain of implications is written as a stack, i.e.
-	 * each line implies the line above it.
-	 *
-	 *    (1)  x**y > 10**(emax+1)       /\     x**y < 10**(etiny-1)
-	 *
-	 *    (2)  log10(x) * y > emax+1     /\     log10(x) * y < etiny-1
-	 *
-	 * The lhs of the conjunction can only be true if the factors have the
-	 * same sign, the rhs only if the factors differ. These two hypotheses
-	 * are implied from now on.
-	 *
-	 *    (3) |log10(x)| * |y| > emax+1  /\  |log10(x)| * |y| > |etiny-1|  
-	 *
-	 *    (4)    log10(|log10(x)|) + log10(|y|) > log10(emax+1)
-	 *        /\ log10(|log10(x)|) + log10(|y|) > log10(|etiny-1|)
-	 *
-	 * Now, (4) clearly must be true if it is true for the following estimates
-	 * for the terms:
-	 *
-	 *    est(log10(emax+1)| >= log10(emax+1)
-	 *    est(log10(|etiny-1|)| >= log10(|etiny-1|)
-	 *
-	 *    est(log10(|y|)) <= log10(|y|)
-	 *
-	 *    0 < est(log10(x)) <= log10(x), if x > 1
-	 *    log10(x) <= est(log10(x)) < 0, if x < 1
-	 *
-	 *
-	 * Estimate for log10(x):
-	 *
-	 * log10(x) = log10(v * 10**t) = log10(v) + t, where 1 <= v < 10.
-	 * Thus, t is adjexp(x).
-	 *
-	 * If t > 0, 0 < t <= log10(x), so we are done.
-	 * 
-	 * If t < -1, log10(x) <= t+1 < 0, so we are done.
-	 *
-	 * If t == -1 or t == 0, then 0.1 <= base < 10. We assume x != 1 and
-	 * use:
-	 *
-	 * 1-1/x < ln(x) < x-1   (Abramowitz&Stegun, 4.1.33)
-	 *
-	 * Then, if 1 < x < 10:
-	 *   
-	 *   0 < (1-1/x) / 2.31 < log10(x)
-	 *   0 < (1-1/x) / 10   < log10(x)
-	 *   0 < (x-1) / (10*x) < log10(x)
-	 *   Multiply by (10**-x->exp), c is the coefficient:
-	 *   0 < (c - 10**(-x->exp)) / (10*c) < log10(x)
-	 *
-	 * Then, if 0.1 <= x < 1:
-	 *
-	 *   log10(x) <= (1-x) / 2.31 < 0
-	 *   log10(x) <= (1-x) / 10   < 0
-	 *   Multiply by (10**-x->exp), c is the coefficient:
-	 *   log10(x) < (10**(-x->exp) - c) / 10**(-x->exp+1) < 0
-	 *	
-	 */
 	t = mpd_adjexp(x);
 	if (t > 0) {
+                /* x >= 10 -> floor(log10(floor(abs(log10(x))))) */
 		return mpd_exp_digits(t) - 1;
 	}
 	else if (t < -1) {
+		/* x < 1/10 -> floor(log10(floor(abs(log10(x))))) */
 		return mpd_exp_digits(t+1) - 1;
 	}
 	else {
 		mpd_maxcontext(&maxctx);
-		tmp.exp = -x->exp;
-		if (!mpd_qcopy_abs(&scratch, x, status)) {
-			*status |= MPD_Malloc_error;
+		mpd_qsub(&scratch, x, &one, &maxctx, status);
+		if (mpd_isspecial(&scratch)) {
+			mpd_del(&scratch);
 			return MPD_SSIZE_MAX;
 		}
-		scratch.exp = 0;
-		if (t == 0) {
-			mpd_qsub(&scratch, &scratch, &tmp, &maxctx, status);
-			numdigits = scratch.digits;
-			dendigits = x->digits + 1;
-		}
-		else {
-			mpd_qsub(&scratch, &tmp, &scratch, &maxctx, status);
-			numdigits = scratch.digits;
-			if (-x->exp+1 < 0) {
-				numdigits += (-x->exp+1);
-				dendigits = 1;
-			}
-			else {
-				dendigits = -x->exp+1;
-			}
-		}
+		u = mpd_adjexp(&scratch);
 		mpd_del(&scratch);
-		return numdigits-dendigits-(numdigits<dendigits) - 1;
+
+		/* t == -1, 1/10 <= x < 1 -> floor(log10(abs(x-1)/10))
+		 * t == 0,  1 < x < 10    -> floor(log10(abs(x-1)/100)) */
+		return (t == 0) ? u-2 : u-1;
 	}
 }
 
-/* Detect cases of certain overflow/underflow in the power function. */
+/*
+ * Detect cases of certain overflow/underflow in the power function.
+ * Assumptions: x != 1, y != 0. The proof above is for positive x.
+ * If x is negative and y is an odd integer, x**y == -(abs(x)**y),
+ * so the analysis does not change.
+ */
 static int
-_qcheck_pow_bounds(mpd_t *result, const mpd_t *base, const mpd_t *exp,
+_qcheck_pow_bounds(mpd_t *result, const mpd_t *x, const mpd_t *y,
                    uint8_t resultsign,
                    const mpd_context_t *ctx, uint32_t *status)
 {
-	mpd_ssize_t bound;
+	MPD_NEW_SHARED(abs_x, x);
+	mpd_ssize_t ub_omega, lb_zeta, lb_theta;
 	uint8_t sign;
 
-	bound = _qlog10_exp_bound(base, status) + mpd_adjexp(exp);
+	mpd_set_positive(&abs_x);
 
-	sign = (mpd_adjexp(base) < 0) ^ mpd_sign(exp);
+	lb_theta = mpd_adjexp(y);
+	lb_zeta = _lower_bound_zeta(&abs_x, status);
+	if (lb_zeta == MPD_SSIZE_MAX) {
+		mpd_seterror(result, MPD_Malloc_error, status);
+		return 1;
+	}
+
+	sign = (mpd_adjexp(&abs_x) < 0) ^ mpd_sign(y);
 	if (sign == 0) {
-		if (bound >= mpd_exp_digits(ctx->emax)) {
+		/* (0 < |x| < 1 and y < 0) or (|x| > 1 and y > 0) */
+		ub_omega = mpd_exp_digits(ctx->emax);
+		if (ub_omega < lb_zeta + lb_theta) {
 			_settriple(result, resultsign, 1, MPD_EXP_INF);
 			mpd_qfinalize(result, ctx, status);
 			return 1;
 		}
 	}
 	else {
-		if (bound >= mpd_exp_digits(mpd_etiny(ctx))) {
+                /* (0 < |x| < 1 and y > 0) or (|x| > 1 and y < 0). */
+		ub_omega = mpd_exp_digits(mpd_etiny(ctx));
+		if (ub_omega < lb_zeta + lb_theta) {
 			_settriple(result, resultsign, 1, mpd_etiny(ctx)-1);
 			mpd_qfinalize(result, ctx, status);
 			return 1;
@@ -5821,7 +5943,7 @@
 	}
 	else {
 		_mpd_qpow_real(result, base, exp, ctx, status);
-		if (_mpd_cmp(result, &one) == 0) {
+		if (!mpd_isspecial(result) && _mpd_cmp(result, &one) == 0) {
 			mpd_ssize_t shift = ctx->prec-1;
 			mpd_qshiftl(result, &one, shift, status);
 			result->exp = -shift;
@@ -5846,9 +5968,8 @@
 
 	mpd_maxcontext(&maxcontext);
 
-	if (!mpd_qcopy(result, &one, status)) {
-		return;
-	}
+	/* resize to smaller cannot fail */
+	mpd_qcopy(result, &one, status);
 
 	while (exp > 0) {
 		if (exp & 1) {
@@ -5921,8 +6042,7 @@
 	}
 
 	if (!mpd_qcopy(&tmod, mod, status)) {
-		mpd_seterror(result, MPD_Malloc_error, status);
-		goto finish;
+		goto mpd_errors;
 	}
 	mpd_set_positive(&tmod);
 
@@ -5943,6 +6063,11 @@
 	mpd_qrem(result, result, &tmod, &maxcontext, status);
 	mpd_qmul(&tbase, &tbase, result, &maxcontext, status);
 	mpd_qrem(&tbase, &tbase, &tmod, &maxcontext, status);
+	if (mpd_isspecial(&tbase) ||
+	    mpd_isspecial(&texp) ||
+	    mpd_isspecial(&tmod)) {
+		goto mpd_errors;
+	}
 
 	for (i = 0; i < texp_exp; i++) {
 		_mpd_qpowmod_uint(&tmp, &tbase, 10, &tmod, status);
@@ -5950,10 +6075,13 @@
 		tmp = tbase;
 		tbase = t;
 	}
+	if (mpd_isspecial(&tbase)) {
+		goto mpd_errors; /* GCOV_UNLIKELY */
+	}
 
-	/* possible resize will be to smaller */
+	/* resize to smaller cannot fail */
 	mpd_qcopy(result, &one, status);
-	while (!mpd_iszero(&texp)) {
+	while (mpd_isfinite(&texp) && !mpd_iszero(&texp)) {
 		if (mpd_isodd(&texp)) {
 			mpd_qmul(result, result, &tbase, &maxcontext, status);
 			mpd_qrem(result, result, &tmod, &maxcontext, status);
@@ -5961,20 +6089,27 @@
 		mpd_qmul(&tbase, &tbase, &tbase, &maxcontext, status);
 		mpd_qrem(&tbase, &tbase, &tmod, &maxcontext, status);
 		mpd_qdivint(&texp, &texp, &two, &maxcontext, status);
-		if (mpd_isnan(&texp)) {
-			mpd_setspecial(result, MPD_POS, MPD_NAN);
-			goto finish;
-		}
+	}
+	if (mpd_isspecial(&texp) || mpd_isspecial(&tbase) || 
+            mpd_isspecial(&tmod) || mpd_isspecial(result)) {
+		/* MPD_Malloc_error */
+		goto mpd_errors;
+	}
+	else {
+		mpd_set_sign(result, sign);
 	}
 
-
-finish:
+out:
 	mpd_del(&tbase);
 	mpd_del(&texp);
 	mpd_del(&tmod);
 	mpd_del(&tmp);
-	mpd_set_flags(result, sign);
 	mpd_qfinalize(result, ctx, status);
+	return;
+
+mpd_errors:
+	mpd_setspecial(result, MPD_POS, MPD_NAN);
+	goto out;
 }
 
 void
@@ -6028,6 +6163,9 @@
 		 * so the shift before an increment will fit in prec. */
 		shift = -expdiff;
 		rnd = mpd_qshiftr(result, a, shift, status);
+		if (rnd == MPD_UINT_MAX) {
+			return;
+		}
 		result->exp = b_exp;
 		if (!_mpd_apply_round_fit(result, rnd, ctx, status)) {
 			return;
@@ -6105,7 +6243,7 @@
 			return;
 		}
 		/* debug */
-		abort();
+		abort(); /* GCOV_NOT_REACHED */
 	}
 	if (mpd_iszerocoeff(b)) {
 		if (mpd_iszerocoeff(a)) {
@@ -6146,7 +6284,7 @@
 			return;
 		}
 		/* debug */
-		abort();
+		abort(); /* GCOV_NOT_REACHED */
 	}
 	if (mpd_iszerocoeff(b)) {
 		if (mpd_iszerocoeff(a)) {
@@ -6184,7 +6322,7 @@
 	expdiff = mpd_adjexp(b) - mpd_adjexp(r);
 	if (-1 <= expdiff && expdiff <= 1) {
 
-		mpd_qfloor(&q, &q, &workctx, &workctx.status);
+		mpd_qtrunc(&q, &q, &workctx, &workctx.status);
 		allnine = mpd_coeff_isallnine(&q);
 		floordigits = q.digits;
 		isodd = mpd_isodd(&q);
@@ -6192,9 +6330,17 @@
 		mpd_maxcontext(&workctx);
 		if (mpd_sign(a) == mpd_sign(b)) {
 			_mpd_qsub(&q, r, b, &workctx, &workctx.status);
+			if (workctx.status&MPD_Errors) {
+				mpd_seterror(r, workctx.status&MPD_Errors, status);
+				goto finish;
+			}
 		}
 		else {
 			_mpd_qadd(&q, r, b, &workctx, &workctx.status);
+			if (workctx.status&MPD_Errors) {
+				mpd_seterror(r, workctx.status&MPD_Errors, status);
+				goto finish;
+			}
 		}
 
 		cmp = mpd_cmp_total_mag(&q, r);
@@ -6253,6 +6399,9 @@
 	else {
 		shift = -expdiff;
 		rnd = mpd_qshiftr(result, a, shift, status);
+		if (rnd == MPD_UINT_MAX) {
+			return;
+		}
 		result->exp = exp;
 		_mpd_apply_round_excess(result, rnd, ctx, status);
 		*status |= MPD_Rounded;
@@ -6267,7 +6416,7 @@
 }
 
 /* Round to an integer according to 'action' and ctx->round. */
-enum {TO_INT_EXACT, TO_INT_SILENT, TO_INT_FLOOR, TO_INT_CEIL};
+enum {TO_INT_EXACT, TO_INT_SILENT, TO_INT_TRUNC, TO_INT_FLOOR, TO_INT_CEIL};
 static void
 _mpd_qround_to_integral(int action, mpd_t *result, const mpd_t *a,
                         const mpd_context_t *ctx, uint32_t *status)
@@ -6291,6 +6440,9 @@
 	}
 
 	rnd = mpd_qshiftr(result, a, -a->exp, status);
+	if (rnd == MPD_UINT_MAX) {
+		return;
+	}
 	result->exp = 0;
 
 	if (action == TO_INT_EXACT || action == TO_INT_SILENT) {
@@ -6302,9 +6454,14 @@
 			}
 		}
 	}
+	else if (action == TO_INT_FLOOR) {
+		if (rnd && mpd_isnegative(result)) {
+			_mpd_qsub(result, result, &one, ctx, status);
+		}
+	}
 	else if (action == TO_INT_CEIL) {
-		if (rnd) {
-			mpd_qadd(result, result, &one, ctx, status);
+		if (rnd && mpd_ispositive(result)) {
+			_mpd_qadd(result, result, &one, ctx, status);
 		}
 	}
 }
@@ -6324,6 +6481,13 @@
 }
 
 void
+mpd_qtrunc(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx,
+              uint32_t *status)
+{
+	(void)_mpd_qround_to_integral(TO_INT_TRUNC, result, a, ctx, status);
+}
+
+void
 mpd_qfloor(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx,
            uint32_t *status)
 {
@@ -6411,8 +6575,9 @@
 
 	v = &vtmp;
 	if (result == a) {
-		if ((v = mpd_qncopy(a)) == NULL) {
-			goto finish;
+		if ((v = mpd_qncopy(a)) == NULL) { /* GCOV_NOT_REACHED */
+			mpd_seterror(result, MPD_Malloc_error, status); /* GCOV_NOT_REACHED */
+			goto finish; /* GCOV_NOT_REACHED */
 		}
 	}
 
@@ -6448,9 +6613,10 @@
 		mpd_qsub(z, &s, &t, &maxcontext, status);
 	}
 
-	z->exp -= adj;
-	mpd_set_flags(z, sign);
-
+	if (!mpd_isspecial(z)) {
+		z->exp -= adj;
+		mpd_set_flags(z, sign);
+	}
 
 finish:
 	mpd_del(&s);
@@ -6486,11 +6652,13 @@
 
 	if (q == a || q == b) {
 		if ((qq = mpd_qnew()) == NULL) {
+			*status |= MPD_Malloc_error;
 			goto nanresult;
 		}
 	}
 	if (r == a || r == b) {
 		if ((rr = mpd_qnew()) == NULL) {
+			*status |= MPD_Malloc_error;
 			goto nanresult;
 		}
 	}
@@ -6501,7 +6669,7 @@
 	_mpd_qreciprocal(rr, &bb, &workctx, &workctx.status);
 
 	mpd_qmul(qq, &aa, rr, &workctx, &workctx.status);
-	mpd_qfloor(qq, qq, &workctx, &workctx.status);
+	mpd_qtrunc(qq, qq, &workctx, &workctx.status);
 
 	workctx.prec = aa.digits + 3;
 	/* get the remainder */
@@ -6510,9 +6678,13 @@
 
 	/* Fix the result. Algorithm from: Karl Hasselstrom, Fast Division of Large Integers */
 	for (k = 0;; k++) {
+		if (mpd_isspecial(rr)) {
+			*status |= (workctx.status&MPD_Errors);
+			goto nanresult;
+		}
 		if (k > 2) {
-			mpd_err_warn("_mpd_barrett_divmod: k > 2 in correcting loop");
-			abort(); /* debug */
+			mpd_err_warn("_mpd_barrett_divmod: k > 2 in correcting loop"); /* GCOV_NOT_REACHED */
+			abort(); /* GCOV_NOT_REACHED */
 		}
 		else if (_mpd_cmp(&zero, rr) == 1) {
 			mpd_qadd(rr, rr, &bb, &workctx, &workctx.status);
@@ -6528,11 +6700,15 @@
 	}
 
 	if (qq != q) {
-		mpd_qcopy(q, qq, status);
+		if (!mpd_qcopy(q, qq, status)) {
+			goto nanresult; /* GCOV_UNLIKELY */
+		}
 		mpd_del(qq);
 	}
 	if (rr != r) {
-		mpd_qcopy(r, rr, status);
+		if (!mpd_qcopy(r, rr, status)) {
+			goto nanresult; /* GCOV_UNLIKELY */
+		}
 		mpd_del(rr);
 	}
 
@@ -6541,9 +6717,9 @@
 
 
 nanresult:
-	if (qq) mpd_del(qq);
-	if (rr) mpd_del(rr);
-	mpd_seterror(q, MPD_Malloc_error, status);
+	if (qq && qq != q) mpd_del(qq);
+	if (rr && rr != r) mpd_del(rr);
+	mpd_setspecial(q, MPD_POS, MPD_NAN);
 	mpd_setspecial(r, MPD_POS, MPD_NAN);
 }
 
@@ -6634,7 +6810,8 @@
 	v = &vtmp;
 	if (result == a) {
 		if ((v = mpd_qncopy(a)) == NULL) {
-			goto finish;
+			mpd_seterror(result, MPD_Malloc_error, status);
+			return;
 		}
 	}
 
@@ -6696,7 +6873,6 @@
 	}
 
 
-finish:
 	mpd_del(&s);
 	mpd_del(&t);
 	if (v != &vtmp) mpd_del(v);
@@ -6753,7 +6929,11 @@
 	u.exp = u.digits - ctx->prec + result->exp - 1;
 
 	_mpd_qsub(tmp, result, &u, &maxctx, status);
+	if (*status&MPD_Errors)	goto nanresult;
+
 	_mpd_qmul(tmp, tmp, tmp, &maxctx, status);
+	if (*status&MPD_Errors)	goto nanresult;
+
 	if (_mpd_cmp(tmp, a) == 1) {
 		u.exp += 1;
 		u.data[0] = 1;
@@ -6761,13 +6941,22 @@
 	}
 	else {
 		_mpd_qadd(tmp, result, &u, &maxctx, status);
+		if (*status&MPD_Errors)	goto nanresult;
+
 		_mpd_qmul(tmp, tmp, tmp, &maxctx, status);
+		if (*status&MPD_Errors)	goto nanresult;
+
 		if (_mpd_cmp(tmp, a) == -1) {
 			u.exp += 1;
 			u.data[0] = 1;
 			_mpd_qadd(result, result, &u, &maxctx, status);
 		}
 	}
+
+	return;
+
+nanresult:
+	mpd_setspecial(result, MPD_POS, MPD_NAN);
 }
 
 void
@@ -6780,9 +6969,9 @@
 	MPD_NEW_STATIC(v,0,0,0,0); /* a, normalized to a number between 1 and 10 */
 	MPD_NEW_STATIC(vtmp,0,0,0,0);
 	MPD_NEW_STATIC(tmp,0,0,0,0);
-	MPD_NEW_STATIC(aa,0,0,0,0);
 	mpd_ssize_t ideal_exp, shift;
 	mpd_ssize_t target_prec, fracdigits;
+	mpd_ssize_t a_exp, a_digits;
 	mpd_ssize_t adj, tz;
 	mpd_uint_t dummy, t;
 	int exact = 0;
@@ -6814,16 +7003,12 @@
 	}
 
 	if (!mpd_qcopy(&v, a, status)) {
-		mpd_seterror(result, MPD_Invalid_operation, status);
+		mpd_seterror(result, MPD_Malloc_error, status);
 		goto finish;
 	}
-	if (result == a) {
-		if (!mpd_qcopy(&aa, a, status)) {
-			mpd_seterror(result, MPD_Invalid_operation, status);
-			goto finish;
-		}
-		a = &aa;
-	}
+
+	a_exp = a->exp;
+	a_digits = a->digits;
 
 	/* normalize a to 1 <= v < 100 */
 	if ((v.digits+v.exp) & 1) {
@@ -6841,11 +7026,11 @@
 		t = t < 1000 ? t*10 : t;
 		t = t < 1000 ? t*10 : t;
 	}
-	adj = (a->exp-v.exp) / 2;
+	adj = (a_exp-v.exp) / 2;
 
 
 	/* use excess digits */
-	target_prec = (a->digits > ctx->prec) ? a->digits : ctx->prec;
+	target_prec = (a_digits > ctx->prec) ? a_digits : ctx->prec;
 	target_prec += 2;
 	varcontext.prec = target_prec + 3;
 
@@ -6859,12 +7044,17 @@
 	tz = mpd_trail_zeros(result);
 	if ((result->digits-tz)*2-1 <= v.digits) {
 		_mpd_qmul(&tmp, result, result, &varcontext, &workstatus);
+		if (workstatus&MPD_Errors) {
+			mpd_seterror(result, workstatus&MPD_Errors, status);
+			goto finish;
+		}
 		exact = (_mpd_cmp(&tmp, &v) == 0);
 	}
 	*status |= (workstatus&MPD_Errors);
 
 	if (!exact && !mpd_isspecial(result) && !mpd_iszero(result)) {
 		_mpd_fix_sqrt(result, &v, &tmp, &varcontext, status);
+		if (mpd_isspecial(result)) goto finish;
 		*status |= (MPD_Rounded|MPD_Inexact);
 	}
 
@@ -6914,7 +7104,7 @@
 	x = a->digits+a->exp;
 
 #ifdef CONFIG_64
-  #if defined(__x86_64__) && defined(HAVE_80BIT_LONG_DOUBLE)
+  #ifdef USE_80BIT_LONG_DOUBLE
 	return (long double)x / log10(base) + 3;
   #else
 	/* x > floor(((1ULL<<53)-3) * log10(2)) */
@@ -6938,7 +7128,7 @@
 _mpd_importsize(size_t srclen, uint32_t base)
 {
 #if SIZE_MAX == UINT64_MAX
-  #if defined(__x86_64__) && defined(HAVE_80BIT_LONG_DOUBLE)
+  #ifdef USE_80BIT_LONG_DOUBLE
 	long double x = (long double)srclen * (log10(base)/MPD_RDIGITS) + 3;
   #else
 	double x;
@@ -6977,7 +7167,7 @@
 
 static inline void
 _from_base_u16(mpd_uint_t *w, mpd_ssize_t wlen,
-               const mpd_uint_t *u, size_t ulen, uint16_t ubase)
+               const mpd_uint_t *u, size_t ulen, uint32_t ubase)
 {
 	mpd_ssize_t m = 1;
 	mpd_uint_t carry;
@@ -7074,11 +7264,13 @@
 
 	if (src->exp >= 0) {
 		if (!mpd_qshiftl(tsrc, src, src->exp, status)) {
+			mpd_del(tsrc);
 			return SIZE_MAX;
 		}
 	}
 	else {
 		if (mpd_qshiftr(tsrc, src, -src->exp, status) == MPD_UINT_MAX) {
+			mpd_del(tsrc);
 			return SIZE_MAX;
 		}
 	}
@@ -7126,11 +7318,13 @@
 
 	if (src->exp >= 0) {
 		if (!mpd_qshiftl(tsrc, src, src->exp, status)) {
+			mpd_del(tsrc);
 			return SIZE_MAX;
 		}
 	}
 	else {
 		if (mpd_qshiftr(tsrc, src, -src->exp, status) == MPD_UINT_MAX) {
+			mpd_del(tsrc);
 			return SIZE_MAX;
 		}
 	}
@@ -7277,12 +7471,12 @@
 /*                   Testcases for Newton Division                   */
 /*********************************************************************/
 
-void
+static void
 mpd_qtest_newtondiv(mpd_t *q, const mpd_t *a, const mpd_t *b,
                     const mpd_context_t *ctx, uint32_t *status)
 {
 	MPD_NEW_STATIC(aligned,0,0,0,0);
-	mpd_uint_t ld, carry = 0;
+	mpd_uint_t ld;
 	mpd_ssize_t shift, exp, tz;
 	mpd_ssize_t newsize;
 	mpd_uint_t rem;
@@ -7346,6 +7540,10 @@
 	{
 		MPD_NEW_STATIC(r,0,0,0,0);
 		_mpd_qbarrett_divmod(q, &r, a, b, status);
+		if (mpd_isspecial(q) || mpd_isspecial(&r)) {
+			mpd_del(&r);
+			goto finish;
+		}
 		rem = !mpd_iszerocoeff(&r);
 		mpd_del(&r);
 		newsize = q->len;
@@ -7361,14 +7559,7 @@
 	if (rem) {
 		ld = mpd_lsd(q->data[0]);
 		if (ld == 0 || ld == 5) {
-			carry = _mpd_baseincr(q->data, q->len);
-			if (carry) {
-				if (!mpd_qresize(q, q->len+1, status)) {
-					mpd_seterror(q, MPD_Malloc_error, status);
-					goto finish;
-				}
-				q->data[q->len] = 1;
-			}
+			q->data[0] += 1;
 		}
 	}
 	else if (1) { /* SET_IDEAL_EXP */
@@ -7388,7 +7579,7 @@
 	mpd_qfinalize(q, ctx, status);
 }
 
-void
+static void
 _mpd_qtest_barrett_divmod(mpd_t *q, mpd_t *r, const mpd_t *a, const mpd_t *b,
                           const mpd_context_t *ctx, uint32_t *status)
 {
@@ -7402,7 +7593,7 @@
 	ideal_exp = (a->exp > b->exp) ?  b->exp : a->exp;
 	if (mpd_iszerocoeff(a)) {
 		if (!mpd_qcopy(r, a, status)) {
-			goto nanresult;
+			goto nanresult; /* GCOV_NOT_REACHED */
 		}
 		r->exp = ideal_exp;
 		_settriple(q, sign_ab, 0, 0);
@@ -7474,6 +7665,9 @@
 	}
 
 	_mpd_qbarrett_divmod(q, r, a, b, status);
+	if (mpd_isspecial(q) || mpd_isspecial(r)) {
+		goto nanresult;
+	}
 	if (mpd_isinfinite(q) || q->digits > ctx->prec) {
 		*status |= MPD_Division_impossible;
 		goto nanresult;
@@ -7489,8 +7683,8 @@
 	mpd_set_flags(q, sign_ab);
 	q->exp = 0;
 	if (q->digits > ctx->prec) {
-		*status |= MPD_Division_impossible;
-		goto nanresult;
+		*status |= MPD_Division_impossible; /* GCOV_NOT_REACHED */
+		goto nanresult; /* GCOV_NOT_REACHED */
 	}
 
 	rsize = _mpd_real_size(r->data, rsize);
@@ -7511,11 +7705,11 @@
 	goto out;
 }
 
-void
+static void
 mpd_qtest_newtondivint(mpd_t *q, const mpd_t *a, const mpd_t *b,
                        const mpd_context_t *ctx, uint32_t *status)
 {
-	mpd_t *r;
+	MPD_NEW_STATIC(r,0,0,0,0);
 	uint8_t sign = mpd_sign(a)^mpd_sign(b);
 
 	if (mpd_isspecial(a) || mpd_isspecial(b)) {
@@ -7535,7 +7729,7 @@
 			return;
 		}
 		/* debug */
-		abort();
+		abort(); /* GCOV_NOT_REACHED */
 	}
 	if (mpd_iszerocoeff(b)) {
 		if (mpd_iszerocoeff(a)) {
@@ -7548,17 +7742,16 @@
 		return;
 	}
 
-	r = mpd_qnew();
-	_mpd_qtest_barrett_divmod(q, r, a, b, ctx, status);
-	mpd_del(r);
+	_mpd_qtest_barrett_divmod(q, &r, a, b, ctx, status);
+	mpd_del(&r);
 	mpd_qfinalize(q, ctx, status);
 }
 
-void
+static void
 mpd_qtest_newtonrem(mpd_t *r, const mpd_t *a, const mpd_t *b,
                     const mpd_context_t *ctx, uint32_t *status)
 {
-	mpd_t *q;
+	MPD_NEW_STATIC(q,0,0,0,0);
 
 	if (mpd_isspecial(a) || mpd_isspecial(b)) {
 		if (mpd_qcheck_nans(r, a, b, ctx, status)) {
@@ -7573,7 +7766,7 @@
 			return;
 		}
 		/* debug */
-		abort();
+		abort(); /* GCOV_NOT_REACHED */
 	}
 	if (mpd_iszerocoeff(b)) {
 		if (mpd_iszerocoeff(a)) {
@@ -7585,13 +7778,12 @@
 		return;
 	}
 
-	q = mpd_qnew();
-	_mpd_qtest_barrett_divmod(q, r, a, b, ctx, status);
-	mpd_del(q);
+	_mpd_qtest_barrett_divmod(&q, r, a, b, ctx, status);
+	mpd_del(&q);
 	mpd_qfinalize(r, ctx, status);
 }
 
-void
+static void
 mpd_qtest_newtondivmod(mpd_t *q, mpd_t *r, const mpd_t *a, const mpd_t *b,
                        const mpd_context_t *ctx, uint32_t *status)
 {
@@ -7619,7 +7811,7 @@
 			return;
 		}
 		/* debug */
-		abort();
+		abort(); /* GCOV_NOT_REACHED */
 	}
 	if (mpd_iszerocoeff(b)) {
 		if (mpd_iszerocoeff(a)) {
@@ -7640,5 +7832,36 @@
 	mpd_qfinalize(r, ctx, status);
 }
 
+void
+mpd_test_newtondiv(mpd_t *q, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx)
+{
+	uint32_t status = 0;
+	mpd_qtest_newtondiv(q, a, b, ctx, &status);
+	mpd_addstatus_raise(ctx, status);
+}
+
+void
+mpd_test_newtondivint(mpd_t *q, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx)
+{
+	uint32_t status = 0;
+	mpd_qtest_newtondivint(q, a, b, ctx, &status);
+	mpd_addstatus_raise(ctx, status);
+}
+
+void
+mpd_test_newtonrem(mpd_t *r, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx)
+{
+	uint32_t status = 0;
+	mpd_qtest_newtonrem(r, a, b, ctx, &status);
+	mpd_addstatus_raise(ctx, status);
+}
+
+void
+mpd_test_newtondivmod(mpd_t *q, mpd_t *r, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx)
+{
+	uint32_t status = 0;
+	mpd_qtest_newtondivmod(q, r, a, b, ctx, &status);
+	mpd_addstatus_raise(ctx, status);
+}
 
 

Modified: python/branches/py3k-cdecimal/Modules/cdecimal/mpdecimal32.h
==============================================================================
--- python/branches/py3k-cdecimal/Modules/cdecimal/mpdecimal32.h	(original)
+++ python/branches/py3k-cdecimal/Modules/cdecimal/mpdecimal32.h	Mon Nov  8 15:12:49 2010
@@ -34,9 +34,8 @@
 typedef uint64_t mpd_uuint_t; /* double width unsigned mod type */
 #endif
 
-/* enable CONFIG_32+ANSI on 64-bit platforms without resorting to -m32 */
-#define MPD_SIZE_MAX UINT32_MAX
-typedef uint32_t mpd_size_t; /* unsigned size type */
+#define MPD_SIZE_MAX SIZE_MAX
+typedef size_t mpd_size_t; /* unsigned size type */
 
 /* type for dec->len, dec->exp, ctx->prec */
 #define MPD_SSIZE_MAX INT32_MAX
@@ -62,8 +61,8 @@
 #define MPD_MAXIMPORT 94444445L      /* ceil((2*MPD_MAX_PREC)/MPD_RDIGITS) */
 
 
-#if SIZE_MAX < MPD_SIZE_MAX
-  #error "unsupported platform: need size_t >= mpd_size_t"
+#if MPD_SIZE_MAX != MPD_UINT_MAX
+  #error "unsupported platform: need mpd_size_t == mpd_uint_t"
 #endif
 
 
@@ -154,11 +153,13 @@
 #define MPD_MINALLOC_MAX 64
 extern mpd_ssize_t MPD_MINALLOC;
 extern void (* mpd_traphandler)(mpd_context_t *);
+void mpd_dflt_traphandler(mpd_context_t *);
 
 void mpd_setminalloc(mpd_ssize_t n);
 void mpd_init(mpd_context_t *ctx, mpd_ssize_t prec);
 
 void mpd_maxcontext(mpd_context_t *ctx);
+void mpd_maxcontext_plus(mpd_context_t *workctx, const mpd_context_t *ctx);
 void mpd_defaultcontext(mpd_context_t *ctx);
 void mpd_basiccontext(mpd_context_t *ctx);
 int mpd_ieee_context(mpd_context_t *ctx, int bits);
@@ -265,9 +266,9 @@
 /* quietly assign a C integer type to an mpd_t */
 void mpd_qset_ssize(mpd_t *result, mpd_ssize_t a, const mpd_context_t *ctx, uint32_t *status);
 void mpd_qset_i32(mpd_t *result, int32_t a, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qset_i64(mpd_t *result, int64_t a, const mpd_context_t *ctx, uint32_t *status);
 void mpd_qset_uint(mpd_t *result, mpd_uint_t a, const mpd_context_t *ctx, uint32_t *status);
 void mpd_qset_u32(mpd_t *result, uint32_t a, const mpd_context_t *ctx, uint32_t *status);
-void mpd_qset_i64(mpd_t *result, int64_t a, const mpd_context_t *ctx, uint32_t *status);
 void mpd_qset_u64(mpd_t *result, uint64_t a, const mpd_context_t *ctx, uint32_t *status);
 
 /* quietly assign a C integer type to an mpd_t with a static coefficient */
@@ -280,6 +281,7 @@
 mpd_ssize_t mpd_qget_ssize(const mpd_t *dec, uint32_t *status);
 int32_t mpd_qget_i32(const mpd_t *dec, uint32_t *status);
 mpd_uint_t mpd_qget_uint(const mpd_t *dec, uint32_t *status);
+mpd_uint_t mpd_qabs_uint(const mpd_t *dec, uint32_t *status);
 uint32_t mpd_qget_u32(const mpd_t *dec, uint32_t *status);
 
 
@@ -321,6 +323,7 @@
 
 void mpd_qround_to_intx(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
 void mpd_qround_to_int(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qtrunc(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
 void mpd_qfloor(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
 void mpd_qceil(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
 
@@ -386,6 +389,106 @@
 
 
 /******************************************************************************/
+/*                           Signalling functions                             */
+/******************************************************************************/
+
+char * mpd_format(const mpd_t *dec, const char *fmt, mpd_context_t *ctx);
+void mpd_import_u16(mpd_t *result, const uint16_t *srcdata, size_t srclen, uint8_t srcsign, uint32_t base, mpd_context_t *ctx);
+void mpd_import_u32(mpd_t *result, const uint32_t *srcdata, size_t srclen, uint8_t srcsign, uint32_t base, mpd_context_t *ctx);
+size_t mpd_export_u16(uint16_t *rdata, size_t rlen, uint32_t base, const mpd_t *src, mpd_context_t *ctx);
+size_t mpd_export_u32(uint32_t *rdata, size_t rlen, uint32_t base, const mpd_t *src, mpd_context_t *ctx);
+void mpd_finalize(mpd_t *result, mpd_context_t *ctx);
+int mpd_check_nan(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+int mpd_check_nans(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+void mpd_set_string(mpd_t *result, const char *s, mpd_context_t *ctx);
+void mpd_maxcoeff(mpd_t *result, mpd_context_t *ctx);
+void mpd_sset_ssize(mpd_t *result, mpd_ssize_t a, mpd_context_t *ctx);
+void mpd_sset_i32(mpd_t *result, int32_t a, mpd_context_t *ctx);
+void mpd_sset_uint(mpd_t *result, mpd_uint_t a, mpd_context_t *ctx);
+void mpd_sset_u32(mpd_t *result, uint32_t a, mpd_context_t *ctx);
+void mpd_set_ssize(mpd_t *result, mpd_ssize_t a, mpd_context_t *ctx);
+void mpd_set_i32(mpd_t *result, int32_t a, mpd_context_t *ctx);
+void mpd_set_i64(mpd_t *result, int64_t a, mpd_context_t *ctx);
+void mpd_set_uint(mpd_t *result, mpd_uint_t a, mpd_context_t *ctx);
+void mpd_set_u32(mpd_t *result, uint32_t a, mpd_context_t *ctx);
+void mpd_set_u64(mpd_t *result, uint64_t a, mpd_context_t *ctx);
+mpd_ssize_t mpd_get_ssize(const mpd_t *a, mpd_context_t *ctx);
+int32_t mpd_get_i32(const mpd_t *a, mpd_context_t *ctx);
+mpd_uint_t mpd_get_uint(const mpd_t *a, mpd_context_t *ctx);
+mpd_uint_t mpd_abs_uint(const mpd_t *a, mpd_context_t *ctx);
+uint32_t mpd_get_u32(const mpd_t *a, mpd_context_t *ctx);
+void mpd_and(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+void mpd_copy(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+void mpd_canonical(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+void mpd_copy_abs(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+void mpd_copy_negate(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+void mpd_copy_sign(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+void mpd_invert(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+void mpd_logb(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+void mpd_or(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+void mpd_rotate(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+void mpd_scaleb(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+void mpd_shiftl(mpd_t *result, const mpd_t *a, mpd_ssize_t n, mpd_context_t *ctx);
+mpd_uint_t mpd_shiftr(mpd_t *result, const mpd_t *a, mpd_ssize_t n, mpd_context_t *ctx);
+void mpd_shiftn(mpd_t *result, const mpd_t *a, mpd_ssize_t n, mpd_context_t *ctx);
+void mpd_shift(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+void mpd_xor(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+void mpd_abs(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+int mpd_cmp(const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+int mpd_compare(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+int mpd_compare_signal(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+void mpd_add(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+void mpd_add_ssize(mpd_t *result, const mpd_t *a, mpd_ssize_t b, mpd_context_t *ctx);
+void mpd_add_i32(mpd_t *result, const mpd_t *a, int32_t b, mpd_context_t *ctx);
+void mpd_add_uint(mpd_t *result, const mpd_t *a, mpd_uint_t b, mpd_context_t *ctx);
+void mpd_add_u32(mpd_t *result, const mpd_t *a, uint32_t b, mpd_context_t *ctx);
+void mpd_sub(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+void mpd_sub_ssize(mpd_t *result, const mpd_t *a, mpd_ssize_t b, mpd_context_t *ctx);
+void mpd_sub_i32(mpd_t *result, const mpd_t *a, int32_t b, mpd_context_t *ctx);
+void mpd_sub_uint(mpd_t *result, const mpd_t *a, mpd_uint_t b, mpd_context_t *ctx);
+void mpd_sub_u32(mpd_t *result, const mpd_t *a, uint32_t b, mpd_context_t *ctx);
+void mpd_div(mpd_t *q, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+void mpd_div_ssize(mpd_t *result, const mpd_t *a, mpd_ssize_t b, mpd_context_t *ctx);
+void mpd_div_i32(mpd_t *result, const mpd_t *a, int32_t b, mpd_context_t *ctx);
+void mpd_div_uint(mpd_t *result, const mpd_t *a, mpd_uint_t b, mpd_context_t *ctx);
+void mpd_div_u32(mpd_t *result, const mpd_t *a, uint32_t b, mpd_context_t *ctx);
+void mpd_divmod(mpd_t *q, mpd_t *r, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+void mpd_divint(mpd_t *q, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+void mpd_exp(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+void mpd_fma(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_t *c, mpd_context_t *ctx);
+void mpd_ln(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+void mpd_log10(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+void mpd_max(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+void mpd_max_mag(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+void mpd_min(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+void mpd_min_mag(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+void mpd_minus(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+void mpd_mul(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+void mpd_mul_ssize(mpd_t *result, const mpd_t *a, mpd_ssize_t b, mpd_context_t *ctx);
+void mpd_mul_i32(mpd_t *result, const mpd_t *a, int32_t b, mpd_context_t *ctx);
+void mpd_mul_uint(mpd_t *result, const mpd_t *a, mpd_uint_t b, mpd_context_t *ctx);
+void mpd_mul_u32(mpd_t *result, const mpd_t *a, uint32_t b, mpd_context_t *ctx);
+void mpd_next_minus(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+void mpd_next_plus(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+void mpd_next_toward(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+void mpd_plus(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+void mpd_pow(mpd_t *result, const mpd_t *base, const mpd_t *exp, mpd_context_t *ctx);
+void mpd_powmod(mpd_t *result, const mpd_t *base, const mpd_t *exp, const mpd_t *mod, mpd_context_t *ctx);
+void mpd_quantize(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+void mpd_rescale(mpd_t *result, const mpd_t *a, mpd_ssize_t exp, mpd_context_t *ctx);
+void mpd_reduce(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+void mpd_rem(mpd_t *r, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+void mpd_rem_near(mpd_t *r, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+void mpd_round_to_intx(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+void mpd_round_to_int(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+void mpd_trunc(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+void mpd_floor(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+void mpd_ceil(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+void mpd_sqrt(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+void mpd_invroot(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+
+
+/******************************************************************************/
 /*                       Get attributes of a decimal                          */
 /******************************************************************************/
 
@@ -473,7 +576,7 @@
 #define mpd_err_fatal(format, ...) \
 	mpd_err_doit(MPD_ERR_EXIT, "%s:%d: error: " format, __FILE__, __LINE__, ##__VA_ARGS__)
 #define mpd_err_warn(format, ...) \
-	mpd_err_doit(MPD_ERR_WARN, "%s:%d: error: " format, __FILE__, __LINE__, ##__VA_ARGS__)
+	mpd_err_doit(MPD_ERR_WARN, "%s:%d: warning: " format, __FILE__, __LINE__, ##__VA_ARGS__)
 
 void mpd_err_doit(int action, const char *fmt, ...);
 
@@ -493,8 +596,6 @@
 void *mpd_calloc(mpd_size_t nmemb, mpd_size_t size);
 void *mpd_realloc(void *ptr, mpd_size_t nmemb, mpd_size_t size, uint8_t *err);
 void *mpd_sh_alloc(mpd_size_t struct_size, mpd_size_t nmemb, mpd_size_t size);
-void *mpd_sh_calloc(mpd_size_t struct_size, mpd_size_t nmemb, mpd_size_t size);
-void *mpd_sh_realloc(void *ptr, mpd_size_t struct_size, mpd_size_t nmemb, mpd_size_t size, uint8_t *err);
 
 mpd_t *mpd_qnew(void);
 mpd_t *mpd_new(mpd_context_t *ctx);

Modified: python/branches/py3k-cdecimal/Modules/cdecimal/mpdecimal64.h
==============================================================================
--- python/branches/py3k-cdecimal/Modules/cdecimal/mpdecimal64.h	(original)
+++ python/branches/py3k-cdecimal/Modules/cdecimal/mpdecimal64.h	Mon Nov  8 15:12:49 2010
@@ -29,7 +29,6 @@
 #define MPD_BITS_PER_UINT 64
 typedef uint64_t mpd_uint_t;  /* unsigned mod type */
 
-/* enable CONFIG_32+ANSI on 64-bit platforms without resorting to -m32 */
 #define MPD_SIZE_MAX SIZE_MAX
 typedef size_t mpd_size_t; /* unsigned size type */
 
@@ -52,9 +51,9 @@
 #define MPD_MAX_EMAX   999999999999999999LL    /* ELIMIT-1 */
 #define MPD_MIN_EMIN  (-999999999999999999LL)  /* -EMAX */
 #define MPD_MIN_ETINY (MPD_MIN_EMIN-(MPD_MAX_PREC-1))
-#define MPD_EXP_INF (MPD_ELIMIT+1)
-#define MPD_EXP_CLAMP (2*MPD_MIN_ETINY)
-#define MPD_MAXIMPORT 105263157894736842L /* (2*MPD_MAX_PREC)/MPD_RDIGITS */
+#define MPD_EXP_INF 2000000000000000001LL
+#define MPD_EXP_CLAMP (-4000000000000000001LL)
+#define MPD_MAXIMPORT 105263157894736842L /* ceil((2*MPD_MAX_PREC)/MPD_RDIGITS) */
 
 
 #if MPD_SIZE_MAX != MPD_UINT_MAX
@@ -149,11 +148,13 @@
 #define MPD_MINALLOC_MAX 64
 extern mpd_ssize_t MPD_MINALLOC;
 extern void (* mpd_traphandler)(mpd_context_t *);
+void mpd_dflt_traphandler(mpd_context_t *);
 
 void mpd_setminalloc(mpd_ssize_t n);
 void mpd_init(mpd_context_t *ctx, mpd_ssize_t prec);
 
 void mpd_maxcontext(mpd_context_t *ctx);
+void mpd_maxcontext_plus(mpd_context_t *workctx, const mpd_context_t *ctx);
 void mpd_defaultcontext(mpd_context_t *ctx);
 void mpd_basiccontext(mpd_context_t *ctx);
 int mpd_ieee_context(mpd_context_t *ctx, int bits);
@@ -277,6 +278,7 @@
 mpd_ssize_t mpd_qget_ssize(const mpd_t *dec, uint32_t *status);
 int64_t mpd_qget_i64(const mpd_t *dec, uint32_t *status);
 mpd_uint_t mpd_qget_uint(const mpd_t *dec, uint32_t *status);
+mpd_uint_t mpd_qabs_uint(const mpd_t *dec, uint32_t *status);
 uint64_t mpd_qget_u64(const mpd_t *dec, uint32_t *status);
 
 
@@ -318,6 +320,7 @@
 
 void mpd_qround_to_intx(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
 void mpd_qround_to_int(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
+void mpd_qtrunc(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
 void mpd_qfloor(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
 void mpd_qceil(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
 
@@ -391,6 +394,116 @@
 
 
 /******************************************************************************/
+/*                           Signalling functions                             */
+/******************************************************************************/
+
+char * mpd_format(const mpd_t *dec, const char *fmt, mpd_context_t *ctx);
+void mpd_import_u16(mpd_t *result, const uint16_t *srcdata, size_t srclen, uint8_t srcsign, uint32_t base, mpd_context_t *ctx);
+void mpd_import_u32(mpd_t *result, const uint32_t *srcdata, size_t srclen, uint8_t srcsign, uint32_t base, mpd_context_t *ctx);
+size_t mpd_export_u16(uint16_t *rdata, size_t rlen, uint32_t base, const mpd_t *src, mpd_context_t *ctx);
+size_t mpd_export_u32(uint32_t *rdata, size_t rlen, uint32_t base, const mpd_t *src, mpd_context_t *ctx);
+void mpd_finalize(mpd_t *result, mpd_context_t *ctx);
+int mpd_check_nan(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+int mpd_check_nans(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+void mpd_set_string(mpd_t *result, const char *s, mpd_context_t *ctx);
+void mpd_maxcoeff(mpd_t *result, mpd_context_t *ctx);
+void mpd_sset_ssize(mpd_t *result, mpd_ssize_t a, mpd_context_t *ctx);
+void mpd_sset_i32(mpd_t *result, int32_t a, mpd_context_t *ctx);
+void mpd_sset_i64(mpd_t *result, int64_t a, mpd_context_t *ctx);
+void mpd_sset_uint(mpd_t *result, mpd_uint_t a, mpd_context_t *ctx);
+void mpd_sset_u32(mpd_t *result, uint32_t a, mpd_context_t *ctx);
+void mpd_sset_u64(mpd_t *result, uint64_t a, mpd_context_t *ctx);
+void mpd_set_ssize(mpd_t *result, mpd_ssize_t a, mpd_context_t *ctx);
+void mpd_set_i32(mpd_t *result, int32_t a, mpd_context_t *ctx);
+void mpd_set_i64(mpd_t *result, int64_t a, mpd_context_t *ctx);
+void mpd_set_uint(mpd_t *result, mpd_uint_t a, mpd_context_t *ctx);
+void mpd_set_u32(mpd_t *result, uint32_t a, mpd_context_t *ctx);
+void mpd_set_u64(mpd_t *result, uint64_t a, mpd_context_t *ctx);
+mpd_ssize_t mpd_get_ssize(const mpd_t *a, mpd_context_t *ctx);
+int64_t mpd_get_i64(const mpd_t *a, mpd_context_t *ctx);
+mpd_uint_t mpd_get_uint(const mpd_t *a, mpd_context_t *ctx);
+mpd_uint_t mpd_abs_uint(const mpd_t *a, mpd_context_t *ctx);
+uint64_t mpd_get_u64(const mpd_t *a, mpd_context_t *ctx);
+void mpd_and(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+void mpd_copy(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+void mpd_canonical(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+void mpd_copy_abs(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+void mpd_copy_negate(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+void mpd_copy_sign(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+void mpd_invert(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+void mpd_logb(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+void mpd_or(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+void mpd_rotate(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+void mpd_scaleb(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+void mpd_shiftl(mpd_t *result, const mpd_t *a, mpd_ssize_t n, mpd_context_t *ctx);
+mpd_uint_t mpd_shiftr(mpd_t *result, const mpd_t *a, mpd_ssize_t n, mpd_context_t *ctx);
+void mpd_shiftn(mpd_t *result, const mpd_t *a, mpd_ssize_t n, mpd_context_t *ctx);
+void mpd_shift(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+void mpd_xor(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+void mpd_abs(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+int mpd_cmp(const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+int mpd_compare(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+int mpd_compare_signal(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+void mpd_add(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+void mpd_add_ssize(mpd_t *result, const mpd_t *a, mpd_ssize_t b, mpd_context_t *ctx);
+void mpd_add_i32(mpd_t *result, const mpd_t *a, int32_t b, mpd_context_t *ctx);
+void mpd_add_i64(mpd_t *result, const mpd_t *a, int64_t b, mpd_context_t *ctx);
+void mpd_add_uint(mpd_t *result, const mpd_t *a, mpd_uint_t b, mpd_context_t *ctx);
+void mpd_add_u32(mpd_t *result, const mpd_t *a, uint32_t b, mpd_context_t *ctx);
+void mpd_add_u64(mpd_t *result, const mpd_t *a, uint64_t b, mpd_context_t *ctx);
+void mpd_sub(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+void mpd_sub_ssize(mpd_t *result, const mpd_t *a, mpd_ssize_t b, mpd_context_t *ctx);
+void mpd_sub_i32(mpd_t *result, const mpd_t *a, int32_t b, mpd_context_t *ctx);
+void mpd_sub_i64(mpd_t *result, const mpd_t *a, int64_t b, mpd_context_t *ctx);
+void mpd_sub_uint(mpd_t *result, const mpd_t *a, mpd_uint_t b, mpd_context_t *ctx);
+void mpd_sub_u32(mpd_t *result, const mpd_t *a, uint32_t b, mpd_context_t *ctx);
+void mpd_sub_u64(mpd_t *result, const mpd_t *a, uint64_t b, mpd_context_t *ctx);
+void mpd_div(mpd_t *q, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+void mpd_div_ssize(mpd_t *result, const mpd_t *a, mpd_ssize_t b, mpd_context_t *ctx);
+void mpd_div_i32(mpd_t *result, const mpd_t *a, int32_t b, mpd_context_t *ctx);
+void mpd_div_i64(mpd_t *result, const mpd_t *a, int64_t b, mpd_context_t *ctx);
+void mpd_div_uint(mpd_t *result, const mpd_t *a, mpd_uint_t b, mpd_context_t *ctx);
+void mpd_div_u32(mpd_t *result, const mpd_t *a, uint32_t b, mpd_context_t *ctx);
+void mpd_div_u64(mpd_t *result, const mpd_t *a, uint64_t b, mpd_context_t *ctx);
+void mpd_divmod(mpd_t *q, mpd_t *r, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+void mpd_divint(mpd_t *q, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+void mpd_exp(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+void mpd_fma(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_t *c, mpd_context_t *ctx);
+void mpd_ln(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+void mpd_log10(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+void mpd_max(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+void mpd_max_mag(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+void mpd_min(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+void mpd_min_mag(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+void mpd_minus(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+void mpd_mul(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+void mpd_mul_ssize(mpd_t *result, const mpd_t *a, mpd_ssize_t b, mpd_context_t *ctx);
+void mpd_mul_i32(mpd_t *result, const mpd_t *a, int32_t b, mpd_context_t *ctx);
+void mpd_mul_i64(mpd_t *result, const mpd_t *a, int64_t b, mpd_context_t *ctx);
+void mpd_mul_uint(mpd_t *result, const mpd_t *a, mpd_uint_t b, mpd_context_t *ctx);
+void mpd_mul_u32(mpd_t *result, const mpd_t *a, uint32_t b, mpd_context_t *ctx);
+void mpd_mul_u64(mpd_t *result, const mpd_t *a, uint64_t b, mpd_context_t *ctx);
+void mpd_next_minus(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+void mpd_next_plus(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+void mpd_next_toward(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+void mpd_plus(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+void mpd_pow(mpd_t *result, const mpd_t *base, const mpd_t *exp, mpd_context_t *ctx);
+void mpd_powmod(mpd_t *result, const mpd_t *base, const mpd_t *exp, const mpd_t *mod, mpd_context_t *ctx);
+void mpd_quantize(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+void mpd_rescale(mpd_t *result, const mpd_t *a, mpd_ssize_t exp, mpd_context_t *ctx);
+void mpd_reduce(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+void mpd_rem(mpd_t *r, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+void mpd_rem_near(mpd_t *r, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+void mpd_round_to_intx(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+void mpd_round_to_int(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+void mpd_trunc(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+void mpd_floor(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+void mpd_ceil(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+void mpd_sqrt(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+void mpd_invroot(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
+
+
+/******************************************************************************/
 /*                       Get attributes of a decimal                          */
 /******************************************************************************/
 
@@ -478,7 +591,7 @@
 #define mpd_err_fatal(format, ...) \
 	mpd_err_doit(MPD_ERR_EXIT, "%s:%d: error: " format, __FILE__, __LINE__, ##__VA_ARGS__)
 #define mpd_err_warn(format, ...) \
-	mpd_err_doit(MPD_ERR_WARN, "%s:%d: error: " format, __FILE__, __LINE__, ##__VA_ARGS__)
+	mpd_err_doit(MPD_ERR_WARN, "%s:%d: warning: " format, __FILE__, __LINE__, ##__VA_ARGS__)
 
 void mpd_err_doit(int action, const char *fmt, ...);
 
@@ -498,8 +611,6 @@
 void *mpd_calloc(mpd_size_t nmemb, mpd_size_t size);
 void *mpd_realloc(void *ptr, mpd_size_t nmemb, mpd_size_t size, uint8_t *err);
 void *mpd_sh_alloc(mpd_size_t struct_size, mpd_size_t nmemb, mpd_size_t size);
-void *mpd_sh_calloc(mpd_size_t struct_size, mpd_size_t nmemb, mpd_size_t size);
-void *mpd_sh_realloc(void *ptr, mpd_size_t struct_size, mpd_size_t nmemb, mpd_size_t size, uint8_t *err);
 
 mpd_t *mpd_qnew(void);
 mpd_t *mpd_new(mpd_context_t *ctx);

Added: python/branches/py3k-cdecimal/Modules/cdecimal/mpsignal.c
==============================================================================
--- (empty file)
+++ python/branches/py3k-cdecimal/Modules/cdecimal/mpsignal.c	Mon Nov  8 15:12:49 2010
@@ -0,0 +1,932 @@
+#include "mpdecimal.h"
+
+
+char *
+mpd_format(const mpd_t *dec, const char *fmt, mpd_context_t *ctx)
+{
+	char *ret;
+	uint32_t status = 0;
+	ret = mpd_qformat(dec, fmt, ctx, &status);
+	mpd_addstatus_raise(ctx, status);
+	return ret;
+}
+
+void
+mpd_import_u16(mpd_t *result, const uint16_t *srcdata, size_t srclen,
+               uint8_t srcsign, uint32_t base, mpd_context_t *ctx)
+{
+	uint32_t status = 0;
+	mpd_qimport_u16(result, srcdata, srclen, srcsign, base, ctx, &status);
+	mpd_addstatus_raise(ctx, status);
+}
+
+void
+mpd_import_u32(mpd_t *result, const uint32_t *srcdata, size_t srclen,
+               uint8_t srcsign, uint32_t base, mpd_context_t *ctx)
+{
+	uint32_t status = 0;
+	mpd_qimport_u32(result, srcdata, srclen, srcsign, base, ctx, &status);
+	mpd_addstatus_raise(ctx, status);
+}
+
+size_t
+mpd_export_u16(uint16_t *rdata, size_t rlen, uint32_t base, const mpd_t *src,
+               mpd_context_t *ctx)
+{
+	size_t n;
+	uint32_t status = 0;
+	n = mpd_qexport_u16(rdata, rlen, base, src, &status);
+	mpd_addstatus_raise(ctx, status);
+	return n;
+}
+
+size_t
+mpd_export_u32(uint32_t *rdata, size_t rlen, uint32_t base, const mpd_t *src,
+               mpd_context_t *ctx)
+{
+	size_t n;
+	uint32_t status = 0;
+	n = mpd_qexport_u32(rdata, rlen, base, src, &status);
+	mpd_addstatus_raise(ctx, status);
+	return n;
+}
+
+void
+mpd_finalize(mpd_t *result, mpd_context_t *ctx)
+{
+	uint32_t status = 0;
+	mpd_qfinalize(result, ctx, &status);
+	mpd_addstatus_raise(ctx, status);
+}
+
+int
+mpd_check_nan(mpd_t *result, const mpd_t *a, mpd_context_t *ctx)
+{
+	uint32_t status = 0;
+	if (mpd_qcheck_nan(result, a, ctx, &status)) {
+		mpd_addstatus_raise(ctx, status);
+		return 1;
+	}
+	return 0;
+}
+
+int
+mpd_check_nans(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx)
+{
+	uint32_t status = 0;
+	if (mpd_qcheck_nans(result, a, b, ctx, &status)) {
+		mpd_addstatus_raise(ctx, status);
+		return 1;
+	}
+	return 0;
+}
+
+void
+mpd_set_string(mpd_t *result, const char *s, mpd_context_t *ctx)
+{
+	uint32_t status = 0;
+	mpd_qset_string(result, s, ctx, &status);
+	mpd_addstatus_raise(ctx, status);
+}
+
+void
+mpd_maxcoeff(mpd_t *result, mpd_context_t *ctx)
+{
+	uint32_t status = 0;
+	mpd_qmaxcoeff(result, ctx, &status);
+	mpd_addstatus_raise(ctx, status);
+}
+
+/* set static mpd from signed integer */
+void
+mpd_sset_ssize(mpd_t *result, mpd_ssize_t a, mpd_context_t *ctx)
+{
+	uint32_t status = 0;
+	mpd_qsset_ssize(result, a, ctx, &status);
+	mpd_addstatus_raise(ctx, status);
+}
+
+void
+mpd_sset_i32(mpd_t *result, int32_t a, mpd_context_t *ctx)
+{
+	uint32_t status = 0;
+	mpd_qsset_i32(result, a, ctx, &status);
+	mpd_addstatus_raise(ctx, status);
+}
+
+#ifdef CONFIG_64
+void
+mpd_sset_i64(mpd_t *result, int64_t a, mpd_context_t *ctx)
+{
+	uint32_t status = 0;
+	mpd_qsset_i64(result, a, ctx, &status);
+	mpd_addstatus_raise(ctx, status);
+}
+#endif
+
+/* set static mpd from unsigned integer */
+void
+mpd_sset_uint(mpd_t *result, mpd_uint_t a, mpd_context_t *ctx)
+{
+	uint32_t status = 0;
+	mpd_qsset_uint(result, a, ctx, &status);
+	mpd_addstatus_raise(ctx, status);
+}
+
+void
+mpd_sset_u32(mpd_t *result, uint32_t a, mpd_context_t *ctx)
+{
+	uint32_t status = 0;
+	mpd_qsset_u32(result, a, ctx, &status);
+	mpd_addstatus_raise(ctx, status);
+}
+
+#ifdef CONFIG_64
+void
+mpd_sset_u64(mpd_t *result, uint64_t a, mpd_context_t *ctx)
+{
+	uint32_t status = 0;
+	mpd_qsset_u64(result, a, ctx, &status);
+	mpd_addstatus_raise(ctx, status);
+}
+#endif
+
+/* set mpd from signed integer */
+void
+mpd_set_ssize(mpd_t *result, mpd_ssize_t a, mpd_context_t *ctx)
+{
+	uint32_t status = 0;
+	mpd_qset_ssize(result, a, ctx, &status);
+	mpd_addstatus_raise(ctx, status);
+}
+
+void
+mpd_set_i32(mpd_t *result, int32_t a, mpd_context_t *ctx)
+{
+	uint32_t status = 0;
+	mpd_qset_i32(result, a, ctx, &status);
+	mpd_addstatus_raise(ctx, status);
+}
+
+void
+mpd_set_i64(mpd_t *result, int64_t a, mpd_context_t *ctx)
+{
+	uint32_t status = 0;
+	mpd_qset_i64(result, a, ctx, &status);
+	mpd_addstatus_raise(ctx, status);
+}
+
+/* set mpd from unsigned integer */
+void
+mpd_set_uint(mpd_t *result, mpd_uint_t a, mpd_context_t *ctx)
+{
+	uint32_t status = 0;
+	mpd_qset_uint(result, a, ctx, &status);
+	mpd_addstatus_raise(ctx, status);
+}
+
+void
+mpd_set_u32(mpd_t *result, uint32_t a, mpd_context_t *ctx)
+{
+	uint32_t status = 0;
+	mpd_qset_u32(result, a, ctx, &status);
+	mpd_addstatus_raise(ctx, status);
+}
+
+void
+mpd_set_u64(mpd_t *result, uint64_t a, mpd_context_t *ctx)
+{
+	uint32_t status = 0;
+	mpd_qset_u64(result, a, ctx, &status);
+	mpd_addstatus_raise(ctx, status);
+}
+
+/* convert mpd to signed integer */
+mpd_ssize_t
+mpd_get_ssize(const mpd_t *a, mpd_context_t *ctx)
+{
+	uint32_t status = 0;
+	mpd_ssize_t ret;
+
+	ret = mpd_qget_ssize(a, &status);
+	mpd_addstatus_raise(ctx, status);
+	return ret;
+}
+
+#ifdef CONFIG_32
+int32_t
+mpd_get_i32(const mpd_t *a, mpd_context_t *ctx)
+{
+	uint32_t status = 0;
+	int32_t ret;
+
+	ret = mpd_qget_i32(a, &status);
+	mpd_addstatus_raise(ctx, status);
+	return ret;
+}
+#else
+int64_t
+mpd_get_i64(const mpd_t *a, mpd_context_t *ctx)
+{
+	uint32_t status = 0;
+	int64_t ret;
+
+	ret = mpd_qget_i64(a, &status);
+	mpd_addstatus_raise(ctx, status);
+	return ret;
+}
+#endif
+
+mpd_uint_t
+mpd_get_uint(const mpd_t *a, mpd_context_t *ctx)
+{
+	uint32_t status = 0;
+	mpd_uint_t ret;
+
+	ret = mpd_qget_uint(a, &status);
+	mpd_addstatus_raise(ctx, status);
+	return ret;
+}
+
+mpd_uint_t
+mpd_abs_uint(const mpd_t *a, mpd_context_t *ctx)
+{
+	uint32_t status = 0;
+	mpd_uint_t ret;
+
+	ret = mpd_qabs_uint(a, &status);
+	mpd_addstatus_raise(ctx, status);
+	return ret;
+}
+
+#ifdef CONFIG_32
+uint32_t
+mpd_get_u32(const mpd_t *a, mpd_context_t *ctx)
+{
+	uint32_t status = 0;
+	uint32_t ret;
+
+	ret = mpd_qget_u32(a, &status);
+	mpd_addstatus_raise(ctx, status);
+	return ret;
+}
+#else
+uint64_t
+mpd_get_u64(const mpd_t *a, mpd_context_t *ctx)
+{
+	uint32_t status = 0;
+	uint64_t ret;
+
+	ret = mpd_qget_u64(a, &status);
+	mpd_addstatus_raise(ctx, status);
+	return ret;
+}
+#endif
+
+void
+mpd_and(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx)
+{
+	uint32_t status = 0;
+	mpd_qand(result, a, b, ctx, &status);
+	mpd_addstatus_raise(ctx, status);
+}
+
+void
+mpd_copy(mpd_t *result, const mpd_t *a, mpd_context_t *ctx)
+{
+	uint32_t status = 0;
+	if (!mpd_qcopy(result, a, &status)) {
+		mpd_addstatus_raise(ctx, status);
+	}
+}
+
+void
+mpd_canonical(mpd_t *result, const mpd_t *a, mpd_context_t *ctx)
+{
+	mpd_copy(result, a, ctx);
+}
+
+void
+mpd_copy_abs(mpd_t *result, const mpd_t *a, mpd_context_t *ctx)
+{
+	uint32_t status = 0;
+	if (!mpd_qcopy_abs(result, a, &status)) {
+		mpd_addstatus_raise(ctx, status);
+	}
+}
+
+void
+mpd_copy_negate(mpd_t *result, const mpd_t *a, mpd_context_t *ctx)
+{
+	uint32_t status = 0;
+	if (!mpd_qcopy_negate(result, a, &status)) {
+		mpd_addstatus_raise(ctx, status);
+	}
+}
+
+void
+mpd_copy_sign(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx)
+{
+	uint32_t status = 0;
+	if (!mpd_qcopy_sign(result, a, b, &status)) {
+		mpd_addstatus_raise(ctx, status);
+	}
+}
+
+void
+mpd_invert(mpd_t *result, const mpd_t *a, mpd_context_t *ctx)
+{
+	uint32_t status = 0;
+	mpd_qinvert(result, a, ctx, &status);
+	mpd_addstatus_raise(ctx, status);
+}
+
+void
+mpd_logb(mpd_t *result, const mpd_t *a, mpd_context_t *ctx)
+{
+	uint32_t status = 0;
+	mpd_qlogb(result, a, ctx, &status);
+	mpd_addstatus_raise(ctx, status);
+}
+
+void
+mpd_or(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx)
+{
+	uint32_t status = 0;
+	mpd_qor(result, a, b, ctx, &status);
+	mpd_addstatus_raise(ctx, status);
+}
+
+void
+mpd_rotate(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx)
+{
+	uint32_t status = 0;
+	mpd_qrotate(result, a, b, ctx, &status);
+	mpd_addstatus_raise(ctx, status);
+}
+
+void
+mpd_scaleb(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx)
+{
+	uint32_t status = 0;
+	mpd_qscaleb(result, a, b, ctx, &status);
+	mpd_addstatus_raise(ctx, status);
+}
+
+void
+mpd_shiftl(mpd_t *result, const mpd_t *a, mpd_ssize_t n, mpd_context_t *ctx)
+{
+	uint32_t status = 0;
+	mpd_qshiftl(result, a, n, &status);
+	mpd_addstatus_raise(ctx, status);
+}
+
+mpd_uint_t
+mpd_shiftr(mpd_t *result, const mpd_t *a, mpd_ssize_t n, mpd_context_t *ctx)
+{
+	uint32_t status = 0;
+	mpd_uint_t rnd;
+
+	rnd = mpd_qshiftr(result, a, n, &status);
+	mpd_addstatus_raise(ctx, status);
+	return rnd;
+}
+
+void
+mpd_shiftn(mpd_t *result, const mpd_t *a, mpd_ssize_t n, mpd_context_t *ctx)
+{
+	uint32_t status = 0;
+	mpd_qshiftn(result, a, n, ctx, &status);
+	mpd_addstatus_raise(ctx, status);
+}
+
+void
+mpd_shift(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx)
+{
+	uint32_t status = 0;
+	mpd_qshift(result, a, b, ctx, &status);
+	mpd_addstatus_raise(ctx, status);
+}
+
+void
+mpd_xor(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx)
+{
+	uint32_t status = 0;
+	mpd_qxor(result, a, b, ctx, &status);
+	mpd_addstatus_raise(ctx, status);
+}
+
+void
+mpd_abs(mpd_t *result, const mpd_t *a, mpd_context_t *ctx)
+{
+	uint32_t status = 0;
+	mpd_qabs(result, a, ctx, &status);
+	mpd_addstatus_raise(ctx, status);
+}
+
+int
+mpd_cmp(const mpd_t *a, const mpd_t *b, mpd_context_t *ctx)
+{
+	uint32_t status = 0;
+	int c;
+	c = mpd_qcmp(a, b, &status);
+	mpd_addstatus_raise(ctx, status);
+	return c;
+}
+
+int
+mpd_compare(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx)
+{
+	uint32_t status = 0;
+	int c;
+	c = mpd_qcompare(result, a, b, ctx, &status);
+	mpd_addstatus_raise(ctx, status);
+	return c;
+}
+
+int
+mpd_compare_signal(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx)
+{
+	uint32_t status = 0;
+	int c;
+	c = mpd_qcompare_signal(result, a, b, ctx, &status);
+	mpd_addstatus_raise(ctx, status);
+	return c;
+}
+
+void
+mpd_add(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx)
+{
+	uint32_t status = 0;
+	mpd_qadd(result, a, b, ctx, &status);
+	mpd_addstatus_raise(ctx, status);
+}
+
+void
+mpd_sub(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx)
+{
+	uint32_t status = 0;
+	mpd_qsub(result, a, b, ctx, &status);
+	mpd_addstatus_raise(ctx, status);
+}
+
+void
+mpd_add_ssize(mpd_t *result, const mpd_t *a, mpd_ssize_t b, mpd_context_t *ctx)
+{
+	uint32_t status = 0;
+	mpd_qadd_ssize(result, a, b, ctx, &status);
+	mpd_addstatus_raise(ctx, status);
+}
+
+void
+mpd_add_i32(mpd_t *result, const mpd_t *a, int32_t b, mpd_context_t *ctx)
+{
+	uint32_t status = 0;
+	mpd_qadd_i32(result, a, b, ctx, &status);
+	mpd_addstatus_raise(ctx, status);
+}
+
+#ifdef CONFIG_64
+void
+mpd_add_i64(mpd_t *result, const mpd_t *a, int64_t b, mpd_context_t *ctx)
+{
+	uint32_t status = 0;
+	mpd_qadd_i64(result, a, b, ctx, &status);
+	mpd_addstatus_raise(ctx, status);
+}
+#endif
+
+void
+mpd_add_uint(mpd_t *result, const mpd_t *a, mpd_uint_t b, mpd_context_t *ctx)
+{
+	uint32_t status = 0;
+	mpd_qadd_uint(result, a, b, ctx, &status);
+	mpd_addstatus_raise(ctx, status);
+}
+
+void
+mpd_add_u32(mpd_t *result, const mpd_t *a, uint32_t b, mpd_context_t *ctx)
+{
+	uint32_t status = 0;
+	mpd_qadd_u32(result, a, b, ctx, &status);
+	mpd_addstatus_raise(ctx, status);
+}
+
+#ifdef CONFIG_64
+void
+mpd_add_u64(mpd_t *result, const mpd_t *a, uint64_t b, mpd_context_t *ctx)
+{
+	uint32_t status = 0;
+	mpd_qadd_u64(result, a, b, ctx, &status);
+	mpd_addstatus_raise(ctx, status);
+}
+#endif
+
+void
+mpd_sub_ssize(mpd_t *result, const mpd_t *a, mpd_ssize_t b, mpd_context_t *ctx)
+{
+	uint32_t status = 0;
+	mpd_qsub_ssize(result, a, b, ctx, &status);
+	mpd_addstatus_raise(ctx, status);
+}
+
+void
+mpd_sub_i32(mpd_t *result, const mpd_t *a, int32_t b, mpd_context_t *ctx)
+{
+	uint32_t status = 0;
+	mpd_qsub_i32(result, a, b, ctx, &status);
+	mpd_addstatus_raise(ctx, status);
+}
+
+#ifdef CONFIG_64
+void
+mpd_sub_i64(mpd_t *result, const mpd_t *a, int64_t b, mpd_context_t *ctx)
+{
+	uint32_t status = 0;
+	mpd_qsub_i64(result, a, b, ctx, &status);
+	mpd_addstatus_raise(ctx, status);
+}
+#endif
+
+void
+mpd_sub_uint(mpd_t *result, const mpd_t *a, mpd_uint_t b, mpd_context_t *ctx)
+{
+	uint32_t status = 0;
+	mpd_qsub_uint(result, a, b, ctx, &status);
+	mpd_addstatus_raise(ctx, status);
+}
+
+void
+mpd_sub_u32(mpd_t *result, const mpd_t *a, uint32_t b, mpd_context_t *ctx)
+{
+	uint32_t status = 0;
+	mpd_qsub_u32(result, a, b, ctx, &status);
+	mpd_addstatus_raise(ctx, status);
+}
+
+#ifdef CONFIG_64
+void
+mpd_sub_u64(mpd_t *result, const mpd_t *a, uint64_t b, mpd_context_t *ctx)
+{
+	uint32_t status = 0;
+	mpd_qsub_u64(result, a, b, ctx, &status);
+	mpd_addstatus_raise(ctx, status);
+}
+#endif
+
+void
+mpd_div(mpd_t *q, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx)
+{
+	uint32_t status = 0;
+	mpd_qdiv(q, a, b, ctx, &status);
+	mpd_addstatus_raise(ctx, status);
+}
+
+void
+mpd_div_ssize(mpd_t *result, const mpd_t *a, mpd_ssize_t b, mpd_context_t *ctx)
+{
+	uint32_t status = 0;
+	mpd_qdiv_ssize(result, a, b, ctx, &status);
+	mpd_addstatus_raise(ctx, status);
+}
+
+void
+mpd_div_i32(mpd_t *result, const mpd_t *a, int32_t b, mpd_context_t *ctx)
+{
+	uint32_t status = 0;
+	mpd_qdiv_i32(result, a, b, ctx, &status);
+	mpd_addstatus_raise(ctx, status);
+}
+
+#ifdef CONFIG_64
+void
+mpd_div_i64(mpd_t *result, const mpd_t *a, int64_t b, mpd_context_t *ctx)
+{
+	uint32_t status = 0;
+	mpd_qdiv_i64(result, a, b, ctx, &status);
+	mpd_addstatus_raise(ctx, status);
+}
+#endif
+
+void
+mpd_div_uint(mpd_t *result, const mpd_t *a, mpd_uint_t b, mpd_context_t *ctx)
+{
+	uint32_t status = 0;
+	mpd_qdiv_uint(result, a, b, ctx, &status);
+	mpd_addstatus_raise(ctx, status);
+}
+
+void
+mpd_div_u32(mpd_t *result, const mpd_t *a, uint32_t b, mpd_context_t *ctx)
+{
+	uint32_t status = 0;
+	mpd_qdiv_u32(result, a, b, ctx, &status);
+	mpd_addstatus_raise(ctx, status);
+}
+
+#ifdef CONFIG_64
+void
+mpd_div_u64(mpd_t *result, const mpd_t *a, uint64_t b, mpd_context_t *ctx)
+{
+	uint32_t status = 0;
+	mpd_qdiv_u64(result, a, b, ctx, &status);
+	mpd_addstatus_raise(ctx, status);
+}
+#endif
+
+void
+mpd_divmod(mpd_t *q, mpd_t *r, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx)
+{
+	uint32_t status = 0;
+	mpd_qdivmod(q, r, a, b, ctx, &status);
+	mpd_addstatus_raise(ctx, status);
+}
+
+void
+mpd_divint(mpd_t *q, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx)
+{
+	uint32_t status = 0;
+	mpd_qdivint(q, a, b, ctx, &status);
+	mpd_addstatus_raise(ctx, status);
+}
+
+void
+mpd_exp(mpd_t *result, const mpd_t *a, mpd_context_t *ctx)
+{
+	uint32_t status = 0;
+	mpd_qexp(result, a, ctx, &status);
+	mpd_addstatus_raise(ctx, status);
+}
+
+void
+mpd_fma(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_t *c,
+        mpd_context_t *ctx)
+{
+	uint32_t status = 0;
+	mpd_qfma(result, a, b, c, ctx, &status);
+	mpd_addstatus_raise(ctx, status);
+}
+
+void
+mpd_ln(mpd_t *result, const mpd_t *a, mpd_context_t *ctx)
+{
+	uint32_t status = 0;
+	mpd_qln(result, a, ctx, &status);
+	mpd_addstatus_raise(ctx, status);
+}
+
+void
+mpd_log10(mpd_t *result, const mpd_t *a, mpd_context_t *ctx)
+{
+	uint32_t status = 0;
+	mpd_qlog10(result, a, ctx, &status);
+	mpd_addstatus_raise(ctx, status);
+}
+
+void
+mpd_max(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx)
+{
+	uint32_t status = 0;
+	mpd_qmax(result, a, b, ctx, &status);
+	mpd_addstatus_raise(ctx, status);
+}
+
+void
+mpd_max_mag(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx)
+{
+	uint32_t status = 0;
+	mpd_qmax_mag(result, a, b, ctx, &status);
+	mpd_addstatus_raise(ctx, status);
+}
+
+void
+mpd_min(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx)
+{
+	uint32_t status = 0;
+	mpd_qmin(result, a, b, ctx, &status);
+	mpd_addstatus_raise(ctx, status);
+}
+
+void
+mpd_min_mag(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx)
+{
+	uint32_t status = 0;
+	mpd_qmin_mag(result, a, b, ctx, &status);
+	mpd_addstatus_raise(ctx, status);
+}
+
+void
+mpd_minus(mpd_t *result, const mpd_t *a, mpd_context_t *ctx)
+{
+	uint32_t status = 0;
+	mpd_qminus(result, a, ctx, &status);
+	mpd_addstatus_raise(ctx, status);
+}
+
+void
+mpd_mul(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx)
+{
+	uint32_t status = 0;
+	mpd_qmul(result, a, b, ctx, &status);
+	mpd_addstatus_raise(ctx, status);
+}
+
+void
+mpd_mul_ssize(mpd_t *result, const mpd_t *a, mpd_ssize_t b, mpd_context_t *ctx)
+{
+	uint32_t status = 0;
+	mpd_qmul_ssize(result, a, b, ctx, &status);
+	mpd_addstatus_raise(ctx, status);
+}
+
+void
+mpd_mul_i32(mpd_t *result, const mpd_t *a, int32_t b, mpd_context_t *ctx)
+{
+	uint32_t status = 0;
+	mpd_qmul_i32(result, a, b, ctx, &status);
+	mpd_addstatus_raise(ctx, status);
+}
+
+#ifdef CONFIG_64
+void
+mpd_mul_i64(mpd_t *result, const mpd_t *a, int64_t b, mpd_context_t *ctx)
+{
+	uint32_t status = 0;
+	mpd_qmul_i64(result, a, b, ctx, &status);
+	mpd_addstatus_raise(ctx, status);
+}
+#endif
+
+void
+mpd_mul_uint(mpd_t *result, const mpd_t *a, mpd_uint_t b, mpd_context_t *ctx)
+{
+	uint32_t status = 0;
+	mpd_qmul_uint(result, a, b, ctx, &status);
+	mpd_addstatus_raise(ctx, status);
+}
+
+void
+mpd_mul_u32(mpd_t *result, const mpd_t *a, uint32_t b, mpd_context_t *ctx)
+{
+	uint32_t status = 0;
+	mpd_qmul_u32(result, a, b, ctx, &status);
+	mpd_addstatus_raise(ctx, status);
+}
+
+#ifdef CONFIG_64
+void
+mpd_mul_u64(mpd_t *result, const mpd_t *a, uint64_t b, mpd_context_t *ctx)
+{
+	uint32_t status = 0;
+	mpd_qmul_u64(result, a, b, ctx, &status);
+	mpd_addstatus_raise(ctx, status);
+}
+#endif
+
+void
+mpd_next_minus(mpd_t *result, const mpd_t *a, mpd_context_t *ctx)
+{
+	uint32_t status = 0;
+	mpd_qnext_minus(result, a, ctx, &status);
+	mpd_addstatus_raise(ctx, status);
+}
+
+void
+mpd_next_plus(mpd_t *result, const mpd_t *a, mpd_context_t *ctx)
+{
+	uint32_t status = 0;
+	mpd_qnext_plus(result, a, ctx, &status);
+	mpd_addstatus_raise(ctx, status);
+}
+
+void
+mpd_next_toward(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx)
+{
+	uint32_t status = 0;
+	mpd_qnext_toward(result, a, b, ctx, &status);
+	mpd_addstatus_raise(ctx, status);
+}
+
+void
+mpd_plus(mpd_t *result, const mpd_t *a, mpd_context_t *ctx)
+{
+	uint32_t status = 0;
+	mpd_qplus(result, a, ctx, &status);
+	mpd_addstatus_raise(ctx, status);
+}
+
+void
+mpd_pow(mpd_t *result, const mpd_t *base, const mpd_t *exp, mpd_context_t *ctx)
+{
+	uint32_t status = 0;
+	mpd_qpow(result, base, exp, ctx, &status);
+	mpd_addstatus_raise(ctx, status);
+}
+
+void
+mpd_powmod(mpd_t *result, const mpd_t *base, const mpd_t *exp, const mpd_t *mod,
+           mpd_context_t *ctx)
+{
+	uint32_t status = 0;
+	mpd_qpowmod(result, base, exp, mod, ctx, &status);
+	mpd_addstatus_raise(ctx, status);
+}
+
+void
+mpd_quantize(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx)
+{
+	uint32_t status = 0;
+	mpd_qquantize(result, a, b, ctx, &status);
+	mpd_addstatus_raise(ctx, status);
+}
+
+void
+mpd_rescale(mpd_t *result, const mpd_t *a, mpd_ssize_t exp, mpd_context_t *ctx)
+{
+	uint32_t status = 0;
+	mpd_qrescale(result, a, exp, ctx, &status);
+	mpd_addstatus_raise(ctx, status);
+}
+
+void
+mpd_reduce(mpd_t *result, const mpd_t *a, mpd_context_t *ctx)
+{
+	uint32_t status = 0;
+	mpd_qreduce(result, a, ctx, &status);
+	mpd_addstatus_raise(ctx, status);
+}
+
+void
+mpd_rem(mpd_t *r, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx)
+{
+	uint32_t status = 0;
+	mpd_qrem(r, a, b, ctx, &status);
+	mpd_addstatus_raise(ctx, status);
+}
+
+void
+mpd_rem_near(mpd_t *r, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx)
+{
+	uint32_t status = 0;
+	mpd_qrem_near(r, a, b, ctx, &status);
+	mpd_addstatus_raise(ctx, status);
+}
+
+void
+mpd_round_to_intx(mpd_t *result, const mpd_t *a, mpd_context_t *ctx)
+{
+	uint32_t status = 0;
+	mpd_qround_to_intx(result, a, ctx, &status);
+	mpd_addstatus_raise(ctx, status);
+}
+
+void
+mpd_round_to_int(mpd_t *result, const mpd_t *a, mpd_context_t *ctx)
+{
+	uint32_t status = 0;
+	mpd_qround_to_int(result, a, ctx, &status);
+	mpd_addstatus_raise(ctx, status);
+}
+
+void
+mpd_trunc(mpd_t *result, const mpd_t *a, mpd_context_t *ctx)
+{
+	uint32_t status = 0;
+	mpd_qtrunc(result, a, ctx, &status);
+	mpd_addstatus_raise(ctx, status);
+}
+
+void
+mpd_floor(mpd_t *result, const mpd_t *a, mpd_context_t *ctx)
+{
+	uint32_t status = 0;
+	mpd_qfloor(result, a, ctx, &status);
+	mpd_addstatus_raise(ctx, status);
+}
+
+void
+mpd_ceil(mpd_t *result, const mpd_t *a, mpd_context_t *ctx)
+{
+	uint32_t status = 0;
+	mpd_qceil(result, a, ctx, &status);
+	mpd_addstatus_raise(ctx, status);
+}
+
+void
+mpd_sqrt(mpd_t *result, const mpd_t *a, mpd_context_t *ctx)
+{
+	uint32_t status = 0;
+	mpd_qsqrt(result, a, ctx, &status);
+	mpd_addstatus_raise(ctx, status);
+}
+
+void
+mpd_invroot(mpd_t *result, const mpd_t *a, mpd_context_t *ctx)
+{
+	uint32_t status = 0;
+	mpd_qinvroot(result, a, ctx, &status);
+	mpd_addstatus_raise(ctx, status);
+}
+
+
+

Modified: python/branches/py3k-cdecimal/Modules/cdecimal/mptest.h
==============================================================================
--- python/branches/py3k-cdecimal/Modules/cdecimal/mptest.h	(original)
+++ python/branches/py3k-cdecimal/Modules/cdecimal/mptest.h	Mon Nov  8 15:12:49 2010
@@ -9,21 +9,24 @@
 
 
 #include "mpdecimal.h"
+#ifndef _MSC_VER
+  #define IMPORTEXPORT
+#endif
 
 
 /* newton division undergoes the same rigorous tests as standard division */
-void mpd_qtest_newtondiv(mpd_t *q, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
-void mpd_qtest_newtondivint(mpd_t *q, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
-void mpd_qtest_newtonrem(mpd_t *r, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
-void mpd_qtest_newtondivmod(mpd_t *q, mpd_t *r, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
+IMPORTEXPORT void mpd_test_newtondiv(mpd_t *q, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_test_newtondivint(mpd_t *q, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_test_newtonrem(mpd_t *r, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
+IMPORTEXPORT void mpd_test_newtondivmod(mpd_t *q, mpd_t *r, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
 
 /* fenv */
-unsigned int mpd_set_fenv(void);
-void mpd_restore_fenv(unsigned int);
+IMPORTEXPORT unsigned int mpd_set_fenv(void);
+IMPORTEXPORT void mpd_restore_fenv(unsigned int);
 
-mpd_uint_t *_mpd_fntmul(const mpd_uint_t *u, const mpd_uint_t *v, mpd_size_t ulen, mpd_size_t vlen, mpd_size_t *rsize);
-mpd_uint_t *_mpd_kmul(const mpd_uint_t *u, const mpd_uint_t *v, mpd_size_t ulen, mpd_size_t vlen, mpd_size_t *rsize);
-mpd_uint_t *_mpd_kmul_fnt(const mpd_uint_t *u, const mpd_uint_t *v, mpd_size_t ulen, mpd_size_t vlen, mpd_size_t *rsize);
+IMPORTEXPORT mpd_uint_t *_mpd_fntmul(const mpd_uint_t *u, const mpd_uint_t *v, mpd_size_t ulen, mpd_size_t vlen, mpd_size_t *rsize);
+IMPORTEXPORT mpd_uint_t *_mpd_kmul(const mpd_uint_t *u, const mpd_uint_t *v, mpd_size_t ulen, mpd_size_t vlen, mpd_size_t *rsize);
+IMPORTEXPORT mpd_uint_t *_mpd_kmul_fnt(const mpd_uint_t *u, const mpd_uint_t *v, mpd_size_t ulen, mpd_size_t vlen, mpd_size_t *rsize);
 
 
 #endif

Modified: python/branches/py3k-cdecimal/Modules/cdecimal/mptypes.h
==============================================================================
--- python/branches/py3k-cdecimal/Modules/cdecimal/mptypes.h	(original)
+++ python/branches/py3k-cdecimal/Modules/cdecimal/mptypes.h	Mon Nov  8 15:12:49 2010
@@ -7,6 +7,12 @@
 #ifndef MPTYPES_H
 #define MPTYPES_H
 
+#if defined(_MSC_VER)
+  #define PRIi64 "lld"
+  #define PRIu64 "llu"
+  #define PRIi32 "d"
+  #define PRIu32 "u"
+#endif
 
 #if defined(CONFIG_64)
   #if defined(_MSC_VER) || defined(__OpenBSD__)

Modified: python/branches/py3k-cdecimal/Modules/cdecimal/numbertheory.h
==============================================================================
--- python/branches/py3k-cdecimal/Modules/cdecimal/numbertheory.h	(original)
+++ python/branches/py3k-cdecimal/Modules/cdecimal/numbertheory.h	Mon Nov  8 15:12:49 2010
@@ -27,13 +27,6 @@
 void _mpd_init_w3table(mpd_uint_t w3table[3], int sign, int modnum);
 
 
-static inline void
-std_setmodulus(int modnum, mpd_uint_t *umod)
-{
-	*umod =  mpd_moduli[modnum];
-}
-
-
 #ifdef PPRO
 static inline void
 ppro_setmodulus(int modnum, mpd_uint_t *umod, double *dmod, uint32_t dinvmod[3])
@@ -43,6 +36,12 @@
 	dinvmod[1] = mpd_invmoduli[modnum][1];
 	dinvmod[2] = mpd_invmoduli[modnum][2];
 }
+#else
+static inline void
+std_setmodulus(int modnum, mpd_uint_t *umod)
+{
+	*umod =  mpd_moduli[modnum];
+}
 #endif
 
 

Modified: python/branches/py3k-cdecimal/Modules/cdecimal/sixstep.c
==============================================================================
--- python/branches/py3k-cdecimal/Modules/cdecimal/sixstep.c	(original)
+++ python/branches/py3k-cdecimal/Modules/cdecimal/sixstep.c	Mon Nov  8 15:12:49 2010
@@ -29,7 +29,7 @@
 
 /* forward transform with sign = -1 */
 int
-six_step_fnt(mpd_uint_t *a, mpd_size_t n, int modnum, int ordered)
+six_step_fnt(mpd_uint_t *a, mpd_size_t n, int modnum)
 {
 	struct fnt_params *tparams;
 	mpd_size_t log2n, C, R;
@@ -47,12 +47,15 @@
 	assert(n >= 16);
 	assert(n <= MPD_MAXTRANSFORM_2N);
 
-	log2n = BSR(n);
+	log2n = mpd_bsr(n);
 	C = (ONE_UM << (log2n / 2));  /* number of columns */
 	R = (ONE_UM << (log2n - (log2n / 2))); /* number of rows */
 
 
-	transpose_pow2(a, R, C); /* view a as a RxC matrix, tranpose */
+	/* view 'a' as an RxC matrix, transpose */
+	if (!transpose_pow2(a, R, C)) {
+		return 0;
+	}
 
 	if ((tparams = _mpd_init_fnt_params(R, -1, modnum)) == NULL) {
 		return 0;
@@ -61,7 +64,10 @@
 		fnt_dif2(x, R, tparams);
 	}
 
-	transpose_pow2(a, C, R);
+	if (!transpose_pow2(a, C, R)) {
+		mpd_free(tparams);
+		return 0;
+	}
 
 
 	SETMODULUS(modnum);
@@ -93,9 +99,14 @@
 	mpd_free(tparams);
 
 
+#if 0
+	/* An unordered transform is sufficient for convolution. */
 	if (ordered) {
-		transpose_pow2(a, R, C);
+		if (!transpose_pow2(a, R, C)) {
+			return 0;
+		}
 	}
+#endif
 
 	return 1;
 }
@@ -103,7 +114,7 @@
 
 /* reverse transform, sign = 1 */
 int
-inv_six_step_fnt(mpd_uint_t *a, mpd_size_t n, int modnum, int ordered)
+inv_six_step_fnt(mpd_uint_t *a, mpd_size_t n, int modnum)
 {
 	struct fnt_params *tparams;
 	mpd_size_t log2n, C, R;
@@ -121,14 +132,19 @@
 	assert(n >= 16);
 	assert(n <= MPD_MAXTRANSFORM_2N);
 
-	log2n = BSR(n);
+	log2n = mpd_bsr(n);
 	C = (ONE_UM << (log2n / 2)); /* number of columns */
 	R = (ONE_UM << (log2n - (log2n / 2))); /* number of rows */
 
 
+#if 0
+	/* An unordered transform is sufficient for convolution. */
 	if (ordered) {
-		transpose_pow2(a, C, R);
+		if (!transpose_pow2(a, C, R)) {
+			return 0;
+		}
 	}
+#endif
 
 	if ((tparams = _mpd_init_fnt_params(C, 1, modnum)) == NULL) {
 		return 0;
@@ -137,7 +153,10 @@
 		fnt_dif2(x, C, tparams);
 	}
 
-	transpose_pow2(a, R, C);
+	if (!transpose_pow2(a, R, C)) {
+		mpd_free(tparams);
+		return 0;
+	}
 
 
 	SETMODULUS(modnum);
@@ -168,7 +187,9 @@
 	}
 	mpd_free(tparams);
 
-	transpose_pow2(a, C, R);
+	if (!transpose_pow2(a, C, R)) {
+		return 0;
+	}
 
 	return 1;
 }

Modified: python/branches/py3k-cdecimal/Modules/cdecimal/sixstep.h
==============================================================================
--- python/branches/py3k-cdecimal/Modules/cdecimal/sixstep.h	(original)
+++ python/branches/py3k-cdecimal/Modules/cdecimal/sixstep.h	Mon Nov  8 15:12:49 2010
@@ -12,8 +12,8 @@
 #include <stdio.h>
 
 
-int six_step_fnt(mpd_uint_t *a, mpd_size_t n, int modnum, int ordered);
-int inv_six_step_fnt(mpd_uint_t *a, mpd_size_t n, int modnum, int ordered);
+int six_step_fnt(mpd_uint_t *a, mpd_size_t n, int modnum);
+int inv_six_step_fnt(mpd_uint_t *a, mpd_size_t n, int modnum);
 
 
 #endif

Modified: python/branches/py3k-cdecimal/Modules/cdecimal/transpose.c
==============================================================================
--- python/branches/py3k-cdecimal/Modules/cdecimal/transpose.c	(original)
+++ python/branches/py3k-cdecimal/Modules/cdecimal/transpose.c	Mon Nov  8 15:12:49 2010
@@ -66,7 +66,7 @@
 		r = 2;
 	}
 	else {
-		mpd_err_fatal("swap_halfrows_pow2: illegal argument for \"dir\"");
+		abort(); /* GCOV_NOT_REACHED */
 	}
 
 	m = cols - 1;
@@ -241,7 +241,7 @@
 		}
 	}
 	else {
-		mpd_err_fatal("transpose_pow2: illegal matrix size");
+		abort(); /* GCOV_NOT_REACHED */
 	}
 
 	return 1;

Modified: python/branches/py3k-cdecimal/Modules/cdecimal/typearith.h
==============================================================================
--- python/branches/py3k-cdecimal/Modules/cdecimal/typearith.h	(original)
+++ python/branches/py3k-cdecimal/Modules/cdecimal/typearith.h	Mon Nov  8 15:12:49 2010
@@ -22,7 +22,164 @@
  */
 
 #if defined(CONFIG_64)
-#if defined(__GNUC__) && defined(__x86_64__) && !defined(TEST_UINT128_T)
+#if defined(ANSI)
+#if defined(HAVE_UINT128_T)
+static inline void
+_mpd_mul_words(mpd_uint_t *hi, mpd_uint_t *lo, mpd_uint_t a, mpd_uint_t b)
+{
+	__uint128_t hl;
+
+	hl = (__uint128_t)a * b;
+
+	*hi = hl >> 64;
+	*lo = (mpd_uint_t)hl;
+}
+
+static inline void
+_mpd_div_words(mpd_uint_t *q, mpd_uint_t *r, mpd_uint_t hi, mpd_uint_t lo,
+               mpd_uint_t d)
+{
+	__uint128_t hl;
+
+	hl = ((__uint128_t)hi<<64) + lo;
+	*q = (mpd_uint_t)(hl / d); /* quotient is known to fit */
+	*r = (mpd_uint_t)(hl - (__uint128_t)(*q) * d);
+}
+#else
+static inline void
+_mpd_mul_words(mpd_uint_t *hi, mpd_uint_t *lo, mpd_uint_t a, mpd_uint_t b)
+{
+	uint32_t w[4], carry;
+	uint32_t ah, al, bh, bl;
+	uint64_t hl;
+
+	ah = (uint32_t)(a>>32); al = (uint32_t)a;
+	bh = (uint32_t)(b>>32); bl = (uint32_t)b;
+
+	hl = (uint64_t)al * bl;
+	w[0] = (uint32_t)hl;
+	carry = (uint32_t)(hl>>32);
+
+	hl = (uint64_t)ah * bl + carry;
+	w[1] = (uint32_t)hl;
+	w[2] = (uint32_t)(hl>>32);
+
+	hl = (uint64_t)al * bh + w[1];
+	w[1] = (uint32_t)hl;
+	carry = (uint32_t)(hl>>32);
+
+	hl = ((uint64_t)ah * bh + w[2]) + carry;
+	w[2] = (uint32_t)hl;
+	w[3] = (uint32_t)(hl>>32);
+
+	*hi = ((uint64_t)w[3]<<32) + w[2];
+	*lo = ((uint64_t)w[1]<<32) + w[0];
+}
+
+/*
+ * By Henry S. Warren: http://www.hackersdelight.org/HDcode/divlu.c.txt
+ * http://www.hackersdelight.org/permissions.htm:
+ * "You are free to use, copy, and distribute any of the code on this web
+ *  site, whether modified by you or not. You need not give attribution."
+ *
+ * Slightly modified, comments are mine.
+ */
+static inline int
+nlz(uint64_t x)
+{
+	int n;
+
+	if (x == 0) return(64);
+
+	n = 0;
+	if (x <= 0x00000000FFFFFFFF) {n = n +32; x = x <<32;}
+	if (x <= 0x0000FFFFFFFFFFFF) {n = n +16; x = x <<16;}
+	if (x <= 0x00FFFFFFFFFFFFFF) {n = n + 8; x = x << 8;}
+	if (x <= 0x0FFFFFFFFFFFFFFF) {n = n + 4; x = x << 4;}
+	if (x <= 0x3FFFFFFFFFFFFFFF) {n = n + 2; x = x << 2;}
+	if (x <= 0x7FFFFFFFFFFFFFFF) {n = n + 1;}
+
+	return n;
+}
+
+static inline void
+_mpd_div_words(mpd_uint_t *q, mpd_uint_t *r, mpd_uint_t u1, mpd_uint_t u0,
+               mpd_uint_t v)
+{
+	const mpd_uint_t b = 4294967296;
+	mpd_uint_t un1, un0,
+	           vn1, vn0,
+	           q1, q0,
+	           un32, un21, un10,
+	           rhat, t;
+	int s;
+
+	assert(u1 < v);
+
+	s = nlz(v);
+	v = v << s;
+	vn1 = v >> 32;
+	vn0 = v & 0xFFFFFFFF;
+
+	t = (s == 0) ? 0 : u0 >> (64 - s);
+	un32 = (u1 << s) | t;
+	un10 = u0 << s;
+
+	un1 = un10 >> 32;
+	un0 = un10 & 0xFFFFFFFF;
+
+	q1 = un32 / vn1;
+	rhat = un32 - q1*vn1;
+again1:
+	if (q1 >= b || q1*vn0 > b*rhat + un1) {
+		q1 = q1 - 1;
+		rhat = rhat + vn1;
+		if (rhat < b) goto again1;
+	}
+
+	/*
+	 *  Before again1 we had:
+	 *      (1) q1*vn1   + rhat         = un32
+	 *      (2) q1*vn1*b + rhat*b + un1 = un32*b + un1
+	 *
+	 *  The statements inside the if-clause do not change the value
+	 *  of the left-hand side of (2), and the loop is only exited
+	 *  if q1*vn0 <= rhat*b + un1, so:
+	 *
+	 *      (3) q1*vn1*b + q1*vn0 <= un32*b + un1
+	 *      (4)              q1*v <= un32*b + un1
+	 *      (5)                 0 <= un32*b + un1 - q1*v
+	 *
+	 *  By (5) we are certain that the possible add-back step from
+	 *  Knuth's algorithm D is never required.
+	 *
+	 *  Since the final quotient is less than 2**64, the following
+	 *  must be true:
+	 *
+	 *      (6) un32*b + un1 - q1*v <= UINT64_MAX
+	 *
+	 *  This means that in the following line, the high words
+	 *  of un32*b and q1*v can be discarded without any effect
+	 *  on the result.
+	 */
+	un21 = un32*b + un1 - q1*v;
+
+	q0 = un21 / vn1;
+	rhat = un21 - q0*vn1;
+again2:
+	if (q0 >= b || q0*vn0 > b*rhat + un0) {
+		q0 = q0 - 1;
+		rhat = rhat + vn1;
+		if (rhat < b) goto again2;
+	}
+
+	*q = q1*b + q0;
+	*r = (un21*b + un0 - q0*v) >> s;
+}
+#endif
+
+/* END ANSI */
+#elif defined(ASM)
 static inline void
 _mpd_mul_words(mpd_uint_t *hi, mpd_uint_t *lo, mpd_uint_t a, mpd_uint_t b)
 {
@@ -53,31 +210,8 @@
 	*q = qq;
 	*r = rr;
 }
-/* END __GNUC__ (amd64) */
-#elif defined(HAVE_UINT128_T)
-static inline void
-_mpd_mul_words(mpd_uint_t *hi, mpd_uint_t *lo, mpd_uint_t a, mpd_uint_t b)
-{
-	__uint128_t hl;
-
-	hl = (__uint128_t)a * b;
-
-	*hi = hl >> 64;
-	*lo = (mpd_uint_t)hl;
-}
-
-static inline void
-_mpd_div_words(mpd_uint_t *q, mpd_uint_t *r, mpd_uint_t hi, mpd_uint_t lo,
-               mpd_uint_t d)
-{
-	__uint128_t hl;
-
-	hl = ((__uint128_t)hi<<64) + lo;
-	*q = (mpd_uint_t)(hl / d); /* quotient is known to fit */
-	*r = (mpd_uint_t)(hl - (__uint128_t)(*q) * d);
-}
-/* END HAVE_UINT128_T */
-#elif defined(_MSC_VER)
+/* END GCC ASM */
+#elif defined(MASM)
 #include <intrin.h>
 #pragma intrinsic(_umul128)
 
@@ -89,8 +223,8 @@
 
 void _mpd_div_words(mpd_uint_t *q, mpd_uint_t *r, mpd_uint_t hi, mpd_uint_t lo,
                     mpd_uint_t d);
-/* END _MSC_VER (amd64) */
 
+/* END MASM (_MSC_VER) */
 #else
   #error "need platform specific 128 bit multiplication and division"
 #endif
@@ -98,51 +232,51 @@
 static inline void
 _mpd_divmod_pow10(mpd_uint_t *q, mpd_uint_t *r, mpd_uint_t v, mpd_uint_t exp)
 {
-	assert(exp <= 19);
+  assert(exp <= 19);
 
-	if (exp <= 9) {
-		if (exp <= 4) {
-			switch (exp) {
-			case 0: *q = v; *r = 0; break;
-			case 1: *q = v / 10ULL; *r = v - *q * 10ULL; break;
-			case 2: *q = v / 100ULL; *r = v - *q * 100ULL; break;
-			case 3: *q = v / 1000ULL; *r = v - *q * 1000ULL; break;
-			case 4: *q = v / 10000ULL; *r = v - *q * 10000ULL; break;
-			}
-		}
-		else {
-			switch (exp) {
-			case 5: *q = v / 100000ULL; *r = v - *q * 100000ULL; break;
-			case 6: *q = v / 1000000ULL; *r = v - *q * 1000000ULL; break;
-			case 7: *q = v / 10000000ULL; *r = v - *q * 10000000ULL; break;
-			case 8: *q = v / 100000000ULL; *r = v - *q * 100000000ULL; break;
-			case 9: *q = v / 1000000000ULL; *r = v - *q * 1000000000ULL; break;
-			}
-		}
-	}
-	else {
-		if (exp <= 14) {
-			switch (exp) {
-			case 10: *q = v / 10000000000ULL; *r = v - *q * 10000000000ULL; break;
-			case 11: *q = v / 100000000000ULL; *r = v - *q * 100000000000ULL; break;
-			case 12: *q = v / 1000000000000ULL; *r = v - *q * 1000000000000ULL; break;
-			case 13: *q = v / 10000000000000ULL; *r = v - *q * 10000000000000ULL; break;
-			case 14: *q = v / 100000000000000ULL; *r = v - *q * 100000000000000ULL; break;
-			}
-		}
-		else {
-			switch (exp) {
-			case 15: *q = v / 1000000000000000ULL; *r = v - *q * 1000000000000000ULL; break;
-			case 16: *q = v / 10000000000000000ULL; *r = v - *q * 10000000000000000ULL; break;
-			case 17: *q = v / 100000000000000000ULL; *r = v - *q * 100000000000000000ULL; break;
-			case 18: *q = v / 1000000000000000000ULL; *r = v - *q * 1000000000000000000ULL; break;
-			case 19: *q = v / 10000000000000000000ULL; *r = v - *q * 10000000000000000000ULL; break;
-			}
-		}
-	}
+  if (exp <= 9) {
+    if (exp <= 4) {
+      switch (exp) {
+      case 0: *q = v; *r = 0; break;
+      case 1: *q = v / 10ULL; *r = v - *q * 10ULL; break;
+      case 2: *q = v / 100ULL; *r = v - *q * 100ULL; break;
+      case 3: *q = v / 1000ULL; *r = v - *q * 1000ULL; break;
+      case 4: *q = v / 10000ULL; *r = v - *q * 10000ULL; break;
+      }
+    }
+    else {
+      switch (exp) {
+      case 5: *q = v / 100000ULL; *r = v - *q * 100000ULL; break;
+      case 6: *q = v / 1000000ULL; *r = v - *q * 1000000ULL; break;
+      case 7: *q = v / 10000000ULL; *r = v - *q * 10000000ULL; break;
+      case 8: *q = v / 100000000ULL; *r = v - *q * 100000000ULL; break;
+      case 9: *q = v / 1000000000ULL; *r = v - *q * 1000000000ULL; break;
+      }
+    }
+  }
+  else {
+    if (exp <= 14) {
+      switch (exp) {
+      case 10: *q = v / 10000000000ULL; *r = v - *q * 10000000000ULL; break;
+      case 11: *q = v / 100000000000ULL; *r = v - *q * 100000000000ULL; break;
+      case 12: *q = v / 1000000000000ULL; *r = v - *q * 1000000000000ULL; break;
+      case 13: *q = v / 10000000000000ULL; *r = v - *q * 10000000000000ULL; break;
+      case 14: *q = v / 100000000000000ULL; *r = v - *q * 100000000000000ULL; break;
+      }
+    }
+    else {
+      switch (exp) {
+      case 15: *q = v / 1000000000000000ULL; *r = v - *q * 1000000000000000ULL; break;
+      case 16: *q = v / 10000000000000000ULL; *r = v - *q * 10000000000000000ULL; break;
+      case 17: *q = v / 100000000000000000ULL; *r = v - *q * 100000000000000000ULL; break;
+      case 18: *q = v / 1000000000000000000ULL; *r = v - *q * 1000000000000000000ULL; break;
+      case 19: *q = v / 10000000000000000000ULL; *r = v - *q * 10000000000000000000ULL; break; /* GCOV_NOT_REACHED */
+      }
+    }
+  }
 }
-/* END CONFIG_64 */
 
+/* END CONFIG_64 */
 #elif defined(CONFIG_32)
 #if defined(ANSI)
 #if !defined(LEGACY_COMPILER)
@@ -179,19 +313,19 @@
 	ah = (uint16_t)(a>>16); al = (uint16_t)a;
 	bh = (uint16_t)(b>>16); bl = (uint16_t)b;
 
-	hl = al * bl;
+	hl = (uint32_t)al * bl;
 	w[0] = (uint16_t)hl;
 	carry = (uint16_t)(hl>>16);
 
-	hl = ah * bl + carry;
+	hl = (uint32_t)ah * bl + carry;
 	w[1] = (uint16_t)hl;
 	w[2] = (uint16_t)(hl>>16);
 
-	hl = al * bh + w[1];
+	hl = (uint32_t)al * bh + w[1];
 	w[1] = (uint16_t)hl;
 	carry = (uint16_t)(hl>>16);
 
-	hl = ah * bh + w[2] + carry;
+	hl = ((uint32_t)ah * bh + w[2]) + carry;
 	w[2] = (uint16_t)hl;
 	w[3] = (uint16_t)(hl>>16);
 
@@ -200,7 +334,7 @@
 }
 
 /*
- * By Henry S. Warren: http://www.hackersdelight.org/HDcode/divlu.c
+ * By Henry S. Warren: http://www.hackersdelight.org/HDcode/divlu.c.txt
  * http://www.hackersdelight.org/permissions.htm:
  * "You are free to use, copy, and distribute any of the code on this web
  *  site, whether modified by you or not. You need not give attribution."
@@ -233,7 +367,7 @@
 	           vn1, vn0,
 	           q1, q0,
 	           un32, un21, un10,
-	           rhat;
+	           rhat, t;
 	int s;
 
 	assert(u1 < v);
@@ -243,7 +377,8 @@
 	vn1 = v >> 16;
 	vn0 = v & 0xFFFF;
 
-	un32 = (u1 << s) | (u0 >> (32 - s));
+	t = (s == 0) ? 0 : u0 >> (32 - s);
+	un32 = (u1 << s) | t;
 	un10 = u0 << s;
 
 	un1 = un10 >> 16;
@@ -300,14 +435,13 @@
 #endif /* END ANSI + LEGACY_COMPILER */
 
 /* END ANSI */
-
-#elif defined(__GNUC__) && defined(__i386__)
+#elif defined(ASM)
 static inline void
 _mpd_mul_words(mpd_uint_t *hi, mpd_uint_t *lo, mpd_uint_t a, mpd_uint_t b)
 {
 	mpd_uint_t h, l;
 
-	asm(	"mull %3\n\t"\
+	asm (	"mull %3\n\t"\
 		: "=d" (h), "=a" (l)\
 		: "%a" (a), "rm" (b)\
 		: "cc"
@@ -332,9 +466,8 @@
 	*q = qq;
 	*r = rr;
 }
-/* END __GNUC__ (i386) */
-
-#elif defined(_MSC_VER)
+/* END GCC ASM */
+#elif defined(MASM)
 static inline void __cdecl
 _mpd_mul_words(mpd_uint_t *hi, mpd_uint_t *lo, mpd_uint_t a, mpd_uint_t b)
 {
@@ -368,8 +501,7 @@
 	*q = qq;
 	*r = rr;
 }
-/* END _MSC_VER (i386) */
-
+/* END MASM (_MSC_VER) */
 #else
   #error "need platform specific 64 bit multiplication and division"
 #endif
@@ -377,26 +509,26 @@
 static inline void
 _mpd_divmod_pow10(mpd_uint_t *q, mpd_uint_t *r, mpd_uint_t v, mpd_uint_t exp)
 {
-	assert(exp <= 9);
+  assert(exp <= 9);
 
-	if (exp <= 4) {
-		switch (exp) {
-		case 0: *q = v; *r = 0; break;
-		case 1: *q = v / 10ULL; *r = v - *q * 10ULL; break;
-		case 2: *q = v / 100ULL; *r = v - *q * 100ULL; break;
-		case 3: *q = v / 1000ULL; *r = v - *q * 1000ULL; break;
-		case 4: *q = v / 10000ULL; *r = v - *q * 10000ULL; break;
-		}
-	}
-	else {
-		switch (exp) {
-		case 5: *q = v / 100000ULL; *r = v - *q * 100000ULL; break;
-		case 6: *q = v / 1000000ULL; *r = v - *q * 1000000ULL; break;
-		case 7: *q = v / 10000000ULL; *r = v - *q * 10000000ULL; break;
-		case 8: *q = v / 100000000ULL; *r = v - *q * 100000000ULL; break;
-		case 9: *q = v / 1000000000ULL; *r = v - *q * 1000000000ULL; break;
-		}
-	}
+  if (exp <= 4) {
+    switch (exp) {
+    case 0: *q = v; *r = 0; break;
+    case 1: *q = v / 10ULL; *r = v - *q * 10ULL; break;
+    case 2: *q = v / 100ULL; *r = v - *q * 100ULL; break;
+    case 3: *q = v / 1000ULL; *r = v - *q * 1000ULL; break;
+    case 4: *q = v / 10000ULL; *r = v - *q * 10000ULL; break;
+    }
+  }
+  else {
+    switch (exp) {
+    case 5: *q = v / 100000ULL; *r = v - *q * 100000ULL; break;
+    case 6: *q = v / 1000000ULL; *r = v - *q * 1000000ULL; break;
+    case 7: *q = v / 10000000ULL; *r = v - *q * 10000000ULL; break;
+    case 8: *q = v / 100000000ULL; *r = v - *q * 100000000ULL; break;
+    case 9: *q = v / 1000000000ULL; *r = v - *q * 1000000000ULL; break; /* GCOV_NOT_REACHED */
+    }
+  }
 }
 /* END CONFIG_32 */
 
@@ -429,7 +561,7 @@
 add_size_t(mpd_size_t a, mpd_size_t b)
 {
 	if (a > MPD_SIZE_MAX - b) {
-		mpd_err_fatal("add_size_t(): overflow: check the context");
+		mpd_err_fatal("add_size_t(): overflow: check the context"); /* GCOV_NOT_REACHED */
 	}
 	return a + b;
 }
@@ -438,7 +570,7 @@
 sub_size_t(mpd_size_t a, mpd_size_t b)
 {
 	if (b > a) {
-		mpd_err_fatal("sub_size_t(): overflow: check the context");
+		mpd_err_fatal("sub_size_t(): overflow: check the context"); /* GCOV_NOT_REACHED */
 	}
 	return a - b;
 }
@@ -454,7 +586,7 @@
 
 	_mpd_mul_words(&hi, &lo, (mpd_uint_t)a, (mpd_uint_t)b);
 	if (hi) {
-		mpd_err_fatal("mul_size_t(): overflow: check the context");
+		mpd_err_fatal("mul_size_t(): overflow: check the context"); /* GCOV_NOT_REACHED */
 	}
 	return lo;
 }

Modified: python/branches/py3k-cdecimal/Modules/cdecimal/umodarith.h
==============================================================================
--- python/branches/py3k-cdecimal/Modules/cdecimal/umodarith.h	(original)
+++ python/branches/py3k-cdecimal/Modules/cdecimal/umodarith.h	Mon Nov  8 15:12:49 2010
@@ -92,87 +92,19 @@
 	return d;
 }
 
-
-#if defined(ANSI)
-#if !defined(LEGACY_COMPILER)
-/* HAVE_UINT64_T */
-static inline
-mpd_uint_t std_mulmod(mpd_uint_t a, mpd_uint_t b, mpd_uint_t m)
-{
-	return ((mpd_uuint_t) a * b) % m;
-}
-
-static inline void
-std_mulmod2c(mpd_uint_t *a, mpd_uint_t *b, mpd_uint_t w, mpd_uint_t m)
-{
-	*a = ((mpd_uuint_t) *a * w) % m;
-	*b = ((mpd_uuint_t) *b * w) % m;
-}
-
-static inline void
-std_mulmod2(mpd_uint_t *a0, mpd_uint_t b0, mpd_uint_t *a1, mpd_uint_t b1,
-            mpd_uint_t m)
-{
-	*a0 = ((mpd_uuint_t) *a0 * b0) % m;
-	*a1 = ((mpd_uuint_t) *a1 * b1) % m;
-}
-/* END HAVE_UINT64_T */
-#else
-/* LEGACY_COMPILER */
-static inline
-mpd_uint_t std_mulmod(mpd_uint_t a, mpd_uint_t b, mpd_uint_t m)
-{
-	mpd_uint_t hi, lo, q, r;
-	_mpd_mul_words(&hi, &lo, a, b);
-	_mpd_div_words(&q, &r, hi, lo, m);
-	return r;
-}
-
-static inline void
-std_mulmod2c(mpd_uint_t *a, mpd_uint_t *b, mpd_uint_t w, mpd_uint_t m)
-{
-	*a = std_mulmod(*a, w, m);
-	*b = std_mulmod(*b, w, m);
-}
-
-static inline void
-std_mulmod2(mpd_uint_t *a0, mpd_uint_t b0, mpd_uint_t *a1, mpd_uint_t b1,
-            mpd_uint_t m)
-{
-	*a0 = std_mulmod(*a0, b0, m);
-	*a1 = std_mulmod(*a1, b1, m);
-}
-#endif /* LEGACY_COMPILER */
-
-static inline
-mpd_uint_t std_powmod(mpd_uint_t base, mpd_uint_t exp, mpd_uint_t umod)
-{
-	mpd_uint_t r = 1;
-
-	while (exp > 0) {
-		if (exp & 1)
-			r = std_mulmod(r, base, umod);
-		base = std_mulmod(base, base, umod);
-		exp >>= 1;
-	}
-
-	return r;
-}
-#endif /* ANSI */
-
+#ifdef CONFIG_64
 
 /**************************************************************************/
-/*                        x64 modular arithmetic                          */
+/*                        64-bit modular arithmetic                       */
 /**************************************************************************/
 
 /*
- * Description of the algorithm in apfloat.pdf, Chapter 7.1.1, by Mikko Tommila.
- * http://www.apfloat.org/apfloat/2.41/
+ * Description of the algorithm in apfloat.pdf, Chapter 7.1.1,
+ * by Mikko Tommila:  http://www.apfloat.org/apfloat/2.41/
  *
  * ACL2 proof: umodarith.lisp: section "Fast modular reduction"
- */ 
+ */
 
-#ifdef CONFIG_64
 static inline mpd_uint_t
 x64_mulmod(mpd_uint_t a, mpd_uint_t b, mpd_uint_t m)
 {
@@ -298,8 +230,8 @@
 	*a1 = x64_mulmod(*a1, b1, m);
 }
 
-static inline
-mpd_uint_t x64_powmod(mpd_uint_t base, mpd_uint_t exp, mpd_uint_t umod)
+static inline mpd_uint_t
+x64_powmod(mpd_uint_t base, mpd_uint_t exp, mpd_uint_t umod)
 {
 	mpd_uint_t r = 1;
 
@@ -312,8 +244,83 @@
 
 	return r;
 }
+
+/* END CONFIG_64 */
+#else /* CONFIG_32 */
+
+
+/**************************************************************************/
+/*                        32-bit modular arithmetic                       */
+/**************************************************************************/
+
+#if defined(ANSI)
+#if !defined(LEGACY_COMPILER)
+/* HAVE_UINT64_T */
+static inline mpd_uint_t
+std_mulmod(mpd_uint_t a, mpd_uint_t b, mpd_uint_t m)
+{
+	return ((mpd_uuint_t) a * b) % m;
+}
+
+static inline void
+std_mulmod2c(mpd_uint_t *a, mpd_uint_t *b, mpd_uint_t w, mpd_uint_t m)
+{
+	*a = ((mpd_uuint_t) *a * w) % m;
+	*b = ((mpd_uuint_t) *b * w) % m;
+}
+
+static inline void
+std_mulmod2(mpd_uint_t *a0, mpd_uint_t b0, mpd_uint_t *a1, mpd_uint_t b1,
+            mpd_uint_t m)
+{
+	*a0 = ((mpd_uuint_t) *a0 * b0) % m;
+	*a1 = ((mpd_uuint_t) *a1 * b1) % m;
+}
+/* END HAVE_UINT64_T */
+#else
+/* LEGACY_COMPILER */
+static inline mpd_uint_t
+std_mulmod(mpd_uint_t a, mpd_uint_t b, mpd_uint_t m)
+{
+	mpd_uint_t hi, lo, q, r;
+	_mpd_mul_words(&hi, &lo, a, b);
+	_mpd_div_words(&q, &r, hi, lo, m);
+	return r;
+}
+
+static inline void
+std_mulmod2c(mpd_uint_t *a, mpd_uint_t *b, mpd_uint_t w, mpd_uint_t m)
+{
+	*a = std_mulmod(*a, w, m);
+	*b = std_mulmod(*b, w, m);
+}
+
+static inline void
+std_mulmod2(mpd_uint_t *a0, mpd_uint_t b0, mpd_uint_t *a1, mpd_uint_t b1,
+            mpd_uint_t m)
+{
+	*a0 = std_mulmod(*a0, b0, m);
+	*a1 = std_mulmod(*a1, b1, m);
+}
+/* END LEGACY_COMPILER */
 #endif
 
+static inline mpd_uint_t
+std_powmod(mpd_uint_t base, mpd_uint_t exp, mpd_uint_t umod)
+{
+	mpd_uint_t r = 1;
+
+	while (exp > 0) {
+		if (exp & 1)
+			r = std_mulmod(r, base, umod);
+		base = std_mulmod(base, base, umod);
+		exp >>= 1;
+	}
+
+	return r;
+}
+#endif /* ANSI CONFIG_32 */
+
 
 /**************************************************************************/
 /*                    Pentium Pro modular arithmetic                      */
@@ -332,8 +339,8 @@
  *   - random tests are provided in tests/extended/ppro_mulmod.c
  */
 
-#ifdef PPRO
-#ifdef __GNUC__
+#if defined(PPRO)
+#if defined(ASM)
 
 /* all operands < dmod */
 static inline mpd_uint_t
@@ -440,8 +447,8 @@
 	);
 
 }
-/* END PPRO __GNUC__ */
-#elif defined (_MSC_VER)
+/* END PPRO GCC ASM */
+#elif defined(MASM)
 
 /* all operands < dmod */
 static inline mpd_uint_t __cdecl
@@ -546,7 +553,7 @@
 		fistp	DWORD PTR [eax]
 	}
 }
-#endif /* PPRO _MSC_VER */
+#endif /* PPRO MASM (_MSC_VER) */
 
 
 /* all operands < dmod */
@@ -565,6 +572,7 @@
 	return r;
 }
 #endif /* PPRO */
+#endif /* CONFIG_32 */
 
 
 #endif /* UMODARITH_H */

Modified: python/branches/py3k-cdecimal/Modules/cdecimal/vccompat.h
==============================================================================
--- python/branches/py3k-cdecimal/Modules/cdecimal/vccompat.h	(original)
+++ python/branches/py3k-cdecimal/Modules/cdecimal/vccompat.h	Mon Nov  8 15:12:49 2010
@@ -26,6 +26,7 @@
   #define strcasecmp _stricmp
   #undef strtoll
   #define strtoll _strtoi64
+  #define strdup _strdup
 #endif
 
 

Modified: python/branches/py3k-cdecimal/Modules/cdecimal/vcdiv64.asm
==============================================================================
--- python/branches/py3k-cdecimal/Modules/cdecimal/vcdiv64.asm	(original)
+++ python/branches/py3k-cdecimal/Modules/cdecimal/vcdiv64.asm	Mon Nov  8 15:12:49 2010
@@ -21,8 +21,6 @@
 	ret	0
 _mpd_div_words ENDP
 _TEXT	ENDS
-
-
-end
+END
 
 


More information about the Python-checkins mailing list