static struct PyModuleDef _decimal_module;
static PyType_Spec dec_spec;
+static PyType_Spec context_spec;
static inline decimal_state *
get_module_state_by_def(PyTypeObject *tp)
PyObject *flags;
int capitals;
PyThreadState *tstate;
+ decimal_state *modstate;
} PyDecContextObject;
typedef struct {
#define CTX(v) (&((PyDecContextObject *)v)->ctx)
#define CtxCaps(v) (((PyDecContextObject *)v)->capitals)
+static inline decimal_state *
+get_module_state_from_ctx(PyObject *v)
+{
+ assert(PyType_GetBaseByToken(Py_TYPE(v), &context_spec, NULL) == 1);
+ decimal_state *state = ((PyDecContextObject *)v)->modstate;
+ assert(state != NULL);
+ return state;
+}
+
Py_LOCAL_INLINE(PyObject *)
incr_true(void)
dec_addstatus(PyObject *context, uint32_t status)
{
mpd_context_t *ctx = CTX(context);
- decimal_state *state = get_module_state_by_def(Py_TYPE(context));
+ decimal_state *state = get_module_state_from_ctx(context);
ctx->status |= status;
if (status & (ctx->traps|MPD_Malloc_error)) {
context_getround(PyObject *self, void *Py_UNUSED(closure))
{
int i = mpd_getround(CTX(self));
- decimal_state *state = get_module_state_by_def(Py_TYPE(self));
+ decimal_state *state = get_module_state_from_ctx(self);
return Py_NewRef(state->round_map[i]);
}
mpd_context_t *ctx;
int x;
- decimal_state *state = get_module_state_by_def(Py_TYPE(self));
+ decimal_state *state = get_module_state_from_ctx(self);
x = getround(state, value);
if (x == -1) {
return -1;
{
mpd_context_t *ctx;
uint32_t flags;
- decimal_state *state = get_module_state_by_def(Py_TYPE(self));
+ decimal_state *state = get_module_state_from_ctx(self);
flags = list_as_flags(state, value);
if (flags & DEC_ERRORS) {
return -1;
mpd_context_t *ctx;
uint32_t flags;
- decimal_state *state = get_module_state_by_def(Py_TYPE(self));
+ decimal_state *state = get_module_state_from_ctx(self);
if (PyDecSignalDict_Check(state, value)) {
flags = SdFlags(value);
}
{
mpd_context_t *ctx;
uint32_t flags;
- decimal_state *state = get_module_state_by_def(Py_TYPE(self));
+ decimal_state *state = get_module_state_from_ctx(self);
flags = list_as_flags(state, value);
if (flags & DEC_ERRORS) {
mpd_context_t *ctx;
uint32_t flags;
- decimal_state *state = get_module_state_by_def(Py_TYPE(self));
+ decimal_state *state = get_module_state_from_ctx(self);
if (PyDecSignalDict_Check(state, value)) {
flags = SdFlags(value);
}
CtxCaps(self) = 1;
self->tstate = NULL;
+ self->modstate = state;
if (type == state->PyDecContext_Type) {
PyObject_GC_Track(self);
int n, mem;
#ifdef Py_DEBUG
- decimal_state *state = get_module_state_by_def(Py_TYPE(self));
+ decimal_state *state = get_module_state_from_ctx((PyObject *)self);
assert(PyDecContext_Check(state, self));
#endif
ctx = CTX(self);
{
PyObject *copy;
- decimal_state *state = get_module_state_by_def(Py_TYPE(self));
+ decimal_state *state = get_module_state_from_ctx(self);
copy = PyObject_CallObject((PyObject *)state->PyDecContext_Type, NULL);
if (copy == NULL) {
return NULL;
PyObject *traps;
PyObject *ret;
mpd_context_t *ctx;
- decimal_state *state = get_module_state_by_def(Py_TYPE(self));
+ decimal_state *state = get_module_state_from_ctx(self);
ctx = CTX(self);
/******************************************************************************/
static PyObject *
-PyDecType_New(PyTypeObject *type)
+PyDecType_New(decimal_state *state, PyTypeObject *type)
{
PyDecObject *dec;
- decimal_state *state = get_module_state_by_def(type);
if (type == state->PyDec_Type) {
dec = PyObject_GC_New(PyDecObject, state->PyDec_Type);
}
assert(PyObject_GC_IsTracked((PyObject *)dec));
return (PyObject *)dec;
}
-#define dec_alloc(st) PyDecType_New((st)->PyDec_Type)
+#define dec_alloc(st) PyDecType_New(st, (st)->PyDec_Type)
static int
dec_traverse(PyObject *dec, visitproc visit, void *arg)
PyObject *dec;
uint32_t status = 0;
- dec = PyDecType_New(type);
+ decimal_state *state = get_module_state_from_ctx(context);
+ dec = PyDecType_New(state, type);
if (dec == NULL) {
return NULL;
}
uint32_t status = 0;
mpd_context_t maxctx;
- dec = PyDecType_New(type);
+ decimal_state *state = get_module_state_from_ctx(context);
+ dec = PyDecType_New(state, type);
if (dec == NULL) {
return NULL;
}
PyObject *dec;
uint32_t status = 0;
- dec = PyDecType_New(type);
+ decimal_state *state = get_module_state_from_ctx(context);
+ dec = PyDecType_New(state, type);
if (dec == NULL) {
return NULL;
}
uint32_t status = 0;
mpd_context_t maxctx;
- dec = PyDecType_New(type);
+ decimal_state *state = get_module_state_from_ctx(context);
+ dec = PyDecType_New(state, type);
if (dec == NULL) {
return NULL;
}
/* Convert from a PyLongObject. The context is not modified; flags set
during conversion are accumulated in the status parameter. */
static PyObject *
-dec_from_long(PyTypeObject *type, PyObject *v,
+dec_from_long(decimal_state *state, PyTypeObject *type, PyObject *v,
const mpd_context_t *ctx, uint32_t *status)
{
PyObject *dec;
PyLongObject *l = (PyLongObject *)v;
- dec = PyDecType_New(type);
+ dec = PyDecType_New(state, type);
if (dec == NULL) {
return NULL;
}
return NULL;
}
- dec = dec_from_long(type, v, CTX(context), &status);
+ decimal_state *state = get_module_state_from_ctx(context);
+ dec = dec_from_long(state, type, v, CTX(context), &status);
if (dec == NULL) {
return NULL;
}
}
mpd_maxcontext(&maxctx);
- dec = dec_from_long(type, v, &maxctx, &status);
+ decimal_state *state = get_module_state_from_ctx(context);
+ dec = dec_from_long(state, type, v, &maxctx, &status);
if (dec == NULL) {
return NULL;
}
mpd_t *d1, *d2;
uint32_t status = 0;
mpd_context_t maxctx;
- decimal_state *state = get_module_state_by_def(type);
+ decimal_state *state = get_module_state_from_ctx(context);
#ifdef Py_DEBUG
assert(PyType_IsSubtype(type, state->PyDec_Type));
sign = (copysign(1.0, x) == 1.0) ? 0 : 1;
if (isnan(x) || isinf(x)) {
- dec = PyDecType_New(type);
+ dec = PyDecType_New(state, type);
if (dec == NULL) {
return NULL;
}
PyObject *dec;
uint32_t status = 0;
- decimal_state *state = get_module_state_by_def(type);
+ decimal_state *state = get_module_state_from_ctx(context);
if (type == state->PyDec_Type && PyDec_CheckExact(state, v)) {
return Py_NewRef(v);
}
- dec = PyDecType_New(type);
+ dec = PyDecType_New(state, type);
if (dec == NULL) {
return NULL;
}
static PyObject *
ctx_from_float(PyObject *context, PyObject *v)
{
- decimal_state *state = get_module_state_by_def(Py_TYPE(context));
+ decimal_state *state = get_module_state_from_ctx(context);
return PyDec_FromFloat(state, v, context);
}
PyObject *result;
uint32_t status = 0;
- decimal_state *state = get_module_state_by_def(Py_TYPE(context));
+ decimal_state *state = get_module_state_from_ctx(context);
result = dec_alloc(state);
if (result == NULL) {
return NULL;
static PyObject *
PyDecType_FromObjectExact(PyTypeObject *type, PyObject *v, PyObject *context)
{
- decimal_state *state = get_module_state_by_def(type);
+ decimal_state *state = get_module_state_from_ctx(context);
if (v == NULL) {
return PyDecType_FromSsizeExact(type, 0, context);
}
static PyObject *
PyDec_FromObject(PyObject *v, PyObject *context)
{
- decimal_state *state = get_module_state_by_def(Py_TYPE(context));
+ decimal_state *state = get_module_state_from_ctx(context);
if (v == NULL) {
return PyDec_FromSsize(state, 0, context);
}
Py_LOCAL_INLINE(int)
convert_op(int type_err, PyObject **conv, PyObject *v, PyObject *context)
{
- decimal_state *state = get_module_state_by_def(Py_TYPE(context));
+ decimal_state *state = get_module_state_from_ctx(context);
if (PyDec_Check(state, v)) {
*conv = Py_NewRef(v);
return 1;
if (tmp == NULL) {
return NULL;
}
- decimal_state *state = get_module_state_by_def(Py_TYPE(context));
+ decimal_state *state = get_module_state_from_ctx(context);
denom = PyDec_FromLongExact(state, tmp, context);
Py_DECREF(tmp);
if (denom == NULL) {
return NULL;
}
- decimal_state *state = get_module_state_by_def(Py_TYPE(context));
+ decimal_state *state = get_module_state_from_ctx(context);
num = PyDec_FromLongExact(state, tmp, context);
Py_DECREF(tmp);
return num;
*vcmp = v;
- decimal_state *state = get_module_state_by_def(Py_TYPE(context));
+ decimal_state *state = get_module_state_from_ctx(context);
if (PyDec_Check(state, w)) {
*wcmp = Py_NewRef(w);
}
return Py_NewRef(self);
}
-static PyObject *
-dec_mpd_radix(PyObject *self, PyObject *Py_UNUSED(dummy))
+static inline PyObject *
+_dec_mpd_radix(decimal_state *state)
{
PyObject *result;
- decimal_state *state = get_module_state_by_def(Py_TYPE(self));
result = dec_alloc(state);
if (result == NULL) {
return NULL;
return result;
}
+static PyObject *
+dec_mpd_radix(PyObject *self, PyObject *Py_UNUSED(dummy))
+{
+ decimal_state *state = get_module_state_by_def(Py_TYPE(self));
+ return _dec_mpd_radix(state);
+}
+
static PyObject *
dec_mpd_qcopy_abs(PyObject *self, PyObject *Py_UNUSED(dummy))
{
\
CONVERT_OP_RAISE(&a, v, context); \
decimal_state *state = \
- get_module_state_by_def(Py_TYPE(context)); \
+ get_module_state_from_ctx(context); \
if ((result = dec_alloc(state)) == NULL) { \
Py_DECREF(a); \
return NULL; \
\
CONVERT_BINOP_RAISE(&a, &b, v, w, context); \
decimal_state *state = \
- get_module_state_by_def(Py_TYPE(context)); \
+ get_module_state_from_ctx(context); \
if ((result = dec_alloc(state)) == NULL) { \
Py_DECREF(a); \
Py_DECREF(b); \
\
CONVERT_BINOP_RAISE(&a, &b, v, w, context); \
decimal_state *state = \
- get_module_state_by_def(Py_TYPE(context)); \
+ get_module_state_from_ctx(context); \
if ((result = dec_alloc(state)) == NULL) { \
Py_DECREF(a); \
Py_DECREF(b); \
} \
\
CONVERT_TERNOP_RAISE(&a, &b, &c, v, w, x, context); \
- decimal_state *state = get_module_state_by_def(Py_TYPE(context)); \
+ decimal_state *state = get_module_state_from_ctx(context); \
if ((result = dec_alloc(state)) == NULL) { \
Py_DECREF(a); \
Py_DECREF(b); \
}
CONVERT_BINOP_RAISE(&a, &b, v, w, context);
- decimal_state *state = get_module_state_by_def(Py_TYPE(context));
+ decimal_state *state = get_module_state_from_ctx(context);
q = dec_alloc(state);
if (q == NULL) {
Py_DECREF(a);
}
}
- decimal_state *state = get_module_state_by_def(Py_TYPE(context));
+ decimal_state *state = get_module_state_from_ctx(context);
result = dec_alloc(state);
if (result == NULL) {
Py_DECREF(a);
static PyObject *
ctx_mpd_radix(PyObject *context, PyObject *dummy)
{
- return dec_mpd_radix(context, dummy);
+ decimal_state *state = get_module_state_from_ctx(context);
+ return _dec_mpd_radix(state);
}
/* Boolean functions: single decimal argument */
static PyObject *
ctx_iscanonical(PyObject *context, PyObject *v)
{
- decimal_state *state = get_module_state_by_def(Py_TYPE(context));
+ decimal_state *state = get_module_state_from_ctx(context);
if (!PyDec_Check(state, v)) {
PyErr_SetString(PyExc_TypeError,
"argument must be a Decimal");
static PyObject *
ctx_canonical(PyObject *context, PyObject *v)
{
- decimal_state *state = get_module_state_by_def(Py_TYPE(context));
+ decimal_state *state = get_module_state_from_ctx(context);
if (!PyDec_Check(state, v)) {
PyErr_SetString(PyExc_TypeError,
"argument must be a Decimal");
uint32_t status = 0;
CONVERT_OP_RAISE(&a, v, context);
- decimal_state *state = get_module_state_by_def(Py_TYPE(context));
+ decimal_state *state = get_module_state_from_ctx(context);
result = dec_alloc(state);
if (result == NULL) {
Py_DECREF(a);
uint32_t status = 0;
CONVERT_OP_RAISE(&a, v, context);
- decimal_state *state = get_module_state_by_def(Py_TYPE(context));
+ decimal_state *state = get_module_state_from_ctx(context);
result = dec_alloc(state);
if (result == NULL) {
Py_DECREF(a);
}
CONVERT_BINOP_RAISE(&a, &b, v, w, context);
- decimal_state *state = get_module_state_by_def(Py_TYPE(context));
+ decimal_state *state = get_module_state_from_ctx(context);
result = dec_alloc(state);
if (result == NULL) {
Py_DECREF(a);
};
static PyType_Slot context_slots[] = {
+ {Py_tp_token, Py_TP_USE_SPEC},
{Py_tp_dealloc, context_dealloc},
{Py_tp_traverse, context_traverse},
{Py_tp_clear, context_clear},