PyCFunction _py_float_as_integer_ratio;
} decimal_state;
-static decimal_state global_state;
+static inline decimal_state *
+get_module_state(PyObject *mod)
+{
+ decimal_state *state = _PyModule_GetState(mod);
+ assert(state != NULL);
+ return state;
+}
+
+static struct PyModuleDef _decimal_module;
+
+static inline decimal_state *
+get_module_state_by_def(PyTypeObject *tp)
+{
+ PyObject *mod = PyType_GetModuleByDef(tp, &_decimal_module);
+ assert(mod != NULL);
+ return get_module_state(mod);
+}
+
+static inline decimal_state *
+find_state_left_or_right(PyObject *left, PyObject *right)
+{
+ PyObject *mod = PyType_GetModuleByDef(Py_TYPE(left), &_decimal_module);
+ if (mod == NULL) {
+ PyErr_Clear();
+ mod = PyType_GetModuleByDef(Py_TYPE(right), &_decimal_module);
+ }
+ assert(mod != NULL);
+ return get_module_state(mod);
+}
-#define GLOBAL_STATE() (&global_state)
#if !defined(MPD_VERSION_HEX) || MPD_VERSION_HEX < 0x02050000
#error "libmpdec version >= 2.5.0 required"
}
static PyObject *
-flags_as_exception(uint32_t flags)
+flags_as_exception(decimal_state *state, uint32_t flags)
{
DecCondMap *cm;
- decimal_state *state = GLOBAL_STATE();
for (cm = state->signal_map; cm->name != NULL; cm++) {
if (flags&cm->flag) {
}
Py_LOCAL_INLINE(uint32_t)
-exception_as_flag(PyObject *ex)
+exception_as_flag(decimal_state *state, PyObject *ex)
{
DecCondMap *cm;
- decimal_state *state = GLOBAL_STATE();
for (cm = state->signal_map; cm->name != NULL; cm++) {
if (cm->ex == ex) {
}
static PyObject *
-flags_as_list(uint32_t flags)
+flags_as_list(decimal_state *state, uint32_t flags)
{
PyObject *list;
DecCondMap *cm;
- decimal_state *state = GLOBAL_STATE();
list = PyList_New(0);
if (list == NULL) {
}
static PyObject *
-signals_as_list(uint32_t flags)
+signals_as_list(decimal_state *state, uint32_t flags)
{
PyObject *list;
DecCondMap *cm;
- decimal_state *state = GLOBAL_STATE();
list = PyList_New(0);
if (list == NULL) {
}
static uint32_t
-list_as_flags(PyObject *list)
+list_as_flags(decimal_state *state, PyObject *list)
{
PyObject *item;
uint32_t flags, x;
flags = 0;
for (j = 0; j < n; j++) {
item = PyList_GetItem(list, j);
- x = exception_as_flag(item);
+ x = exception_as_flag(state, item);
if (x & DEC_ERRORS) {
return x;
}
}
static PyObject *
-flags_as_dict(uint32_t flags)
+flags_as_dict(decimal_state *state, uint32_t flags)
{
DecCondMap *cm;
PyObject *dict;
- decimal_state *state = GLOBAL_STATE();
dict = PyDict_New();
if (dict == NULL) {
}
static uint32_t
-dict_as_flags(PyObject *val)
+dict_as_flags(decimal_state *state, PyObject *val)
{
PyObject *b;
DecCondMap *cm;
uint32_t flags = 0;
int x;
- decimal_state *state = GLOBAL_STATE();
if (!PyDict_Check(val)) {
PyErr_SetString(PyExc_TypeError,
dec_addstatus(PyObject *context, uint32_t status)
{
mpd_context_t *ctx = CTX(context);
+ decimal_state *state = get_module_state_by_def(Py_TYPE(context));
ctx->status |= status;
if (status & (ctx->traps|MPD_Malloc_error)) {
return 1;
}
- ex = flags_as_exception(ctx->traps&status);
+ ex = flags_as_exception(state, ctx->traps&status);
if (ex == NULL) {
return 1; /* GCOV_NOT_REACHED */
}
- siglist = flags_as_list(ctx->traps&status);
+ siglist = flags_as_list(state, ctx->traps&status);
if (siglist == NULL) {
return 1;
}
}
static int
-getround(PyObject *v)
+getround(decimal_state *state, PyObject *v)
{
int i;
- decimal_state *state = GLOBAL_STATE();
-
if (PyUnicode_Check(v)) {
for (i = 0; i < _PY_DEC_ROUND_GUARD; i++) {
if (v == state->round_map[i]) {
}
static PyObject *
-signaldict_iter(PyObject *self UNUSED)
+signaldict_iter(PyObject *self)
{
- decimal_state *state = GLOBAL_STATE();
+ decimal_state *state = get_module_state_by_def(Py_TYPE(self));
return PyTuple_Type.tp_iter(state->SignalTuple);
}
signaldict_getitem(PyObject *self, PyObject *key)
{
uint32_t flag;
+ decimal_state *state = get_module_state_by_def(Py_TYPE(self));
- flag = exception_as_flag(key);
+ flag = exception_as_flag(state, key);
if (flag & DEC_ERRORS) {
return NULL;
}
uint32_t flag;
int x;
+ decimal_state *state = get_module_state_by_def(Py_TYPE(self));
if (value == NULL) {
return value_error_int("signal keys cannot be deleted");
}
- flag = exception_as_flag(key);
+ flag = exception_as_flag(state, key);
if (flag & DEC_ERRORS) {
return -1;
}
assert(SIGNAL_MAP_LEN == 9);
- decimal_state *state = GLOBAL_STATE();
+ decimal_state *state = get_module_state_by_def(Py_TYPE(self));
for (cm=state->signal_map, i=0; cm->name != NULL; cm++, i++) {
n[i] = cm->fqname;
b[i] = SdFlags(self)&cm->flag ? "True" : "False";
{
PyObject *res = Py_NotImplemented;
- decimal_state *state = GLOBAL_STATE();
+ decimal_state *state = find_state_left_or_right(v, w);
assert(PyDecSignalDict_Check(state, v));
if (op == Py_EQ || op == Py_NE) {
res = (SdFlags(v)==SdFlags(w)) ^ (op==Py_NE) ? Py_True : Py_False;
}
else if (PyDict_Check(w)) {
- uint32_t flags = dict_as_flags(w);
+ uint32_t flags = dict_as_flags(state, w);
if (flags & DEC_ERRORS) {
if (flags & DEC_INVALID_SIGNALS) {
/* non-comparable: Py_NotImplemented */
static PyObject *
signaldict_copy(PyObject *self, PyObject *args UNUSED)
{
- return flags_as_dict(SdFlags(self));
+ decimal_state *state = get_module_state_by_def(Py_TYPE(self));
+ return flags_as_dict(state, SdFlags(self));
}
context_getround(PyObject *self, void *closure UNUSED)
{
int i = mpd_getround(CTX(self));
- decimal_state *state = GLOBAL_STATE();
+ decimal_state *state = get_module_state_by_def(Py_TYPE(self));
return Py_NewRef(state->round_map[i]);
}
mpd_context_t *ctx;
int x;
- x = getround(value);
+ decimal_state *state = get_module_state_by_def(Py_TYPE(self));
+ x = getround(state, value);
if (x == -1) {
return -1;
}
{
mpd_context_t *ctx;
uint32_t flags;
-
- flags = list_as_flags(value);
+ decimal_state *state = get_module_state_by_def(Py_TYPE(self));
+ flags = list_as_flags(state, value);
if (flags & DEC_ERRORS) {
return -1;
}
mpd_context_t *ctx;
uint32_t flags;
- decimal_state *state = GLOBAL_STATE();
+ decimal_state *state = get_module_state_by_def(Py_TYPE(self));
if (PyDecSignalDict_Check(state, value)) {
flags = SdFlags(value);
}
else {
- flags = dict_as_flags(value);
+ flags = dict_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));
- flags = list_as_flags(value);
+ flags = list_as_flags(state, value);
if (flags & DEC_ERRORS) {
return -1;
}
mpd_context_t *ctx;
uint32_t flags;
- decimal_state *state = GLOBAL_STATE();
+ decimal_state *state = get_module_state_by_def(Py_TYPE(self));
if (PyDecSignalDict_Check(state, value)) {
flags = SdFlags(value);
}
else {
- flags = dict_as_flags(value);
+ flags = dict_as_flags(state, value);
if (flags & DEC_ERRORS) {
return -1;
}
PyDecContextObject *self = NULL;
mpd_context_t *ctx;
- decimal_state *state = GLOBAL_STATE();
+ decimal_state *state = get_module_state_by_def(type);
if (type == state->PyDecContext_Type) {
self = PyObject_GC_New(PyDecContextObject, state->PyDecContext_Type);
}
PyTypeObject *tp = Py_TYPE(self);
PyObject_GC_UnTrack(self);
#ifndef WITH_DECIMAL_CONTEXTVAR
- decimal_state *state = GLOBAL_STATE();
+ decimal_state *state = get_module_state_by_def(Py_TYPE(self));
if (self == state->cached_context) {
state->cached_context = NULL;
}
int n, mem;
#ifdef Py_DEBUG
- decimal_state *state = GLOBAL_STATE();
+ decimal_state *state = get_module_state_by_def(Py_TYPE(self));
assert(PyDecContext_Check(state, self));
#endif
ctx = CTX(self);
goto error;
}
- decimal_state *state = GLOBAL_STATE();
+ decimal_state *state = get_module_state_by_def(Py_TYPE(v));
context = PyObject_CallObject((PyObject *)state->PyDecContext_Type, NULL);
if (context == NULL) {
return NULL;
{
PyObject *copy;
- decimal_state *state = GLOBAL_STATE();
+ decimal_state *state = get_module_state_by_def(Py_TYPE(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));
ctx = CTX(self);
- flags = signals_as_list(ctx->status);
+ flags = signals_as_list(state, ctx->status);
if (flags == NULL) {
return NULL;
}
- traps = signals_as_list(ctx->traps);
+ traps = signals_as_list(state, ctx->traps);
if (traps == NULL) {
Py_DECREF(flags);
return NULL;
#define CONTEXT_CHECK_VA(state, obj) \
if (obj == Py_None) { \
- CURRENT_CONTEXT(obj); \
+ CURRENT_CONTEXT(state, obj); \
} \
else if (!PyDecContext_Check(state, obj)) { \
PyErr_SetString(PyExc_TypeError, \
#ifndef WITH_DECIMAL_CONTEXTVAR
/* Get the context from the thread state dictionary. */
static PyObject *
-current_context_from_dict(void)
+current_context_from_dict(decimal_state *modstate)
{
PyThreadState *tstate = _PyThreadState_GET();
- decimal_state *modstate = GLOBAL_STATE();
#ifdef Py_DEBUG
// The caller must hold the GIL
_Py_EnsureTstateNotNULL(tstate);
/* Return borrowed reference to thread local context. */
static PyObject *
-current_context(void)
+current_context(decimal_state *modstate)
{
PyThreadState *tstate = _PyThreadState_GET();
- decimal_state *modstate = GLOBAL_STATE();
if (modstate->cached_context && modstate->cached_context->tstate == tstate) {
return (PyObject *)(modstate->cached_context);
}
- return current_context_from_dict();
+ return current_context_from_dict(modstate);
}
/* ctxobj := borrowed reference to the current context */
-#define CURRENT_CONTEXT(ctxobj) \
- ctxobj = current_context(); \
+#define CURRENT_CONTEXT(state, ctxobj) \
+ ctxobj = current_context(state); \
if (ctxobj == NULL) { \
return NULL; \
}
/* Return a new reference to the current context */
static PyObject *
-PyDec_GetCurrentContext(PyObject *self UNUSED, PyObject *args UNUSED)
+PyDec_GetCurrentContext(PyObject *self, PyObject *args UNUSED)
{
PyObject *context;
+ decimal_state *state = get_module_state(self);
- context = current_context();
- if (context == NULL) {
- return NULL;
- }
-
+ CURRENT_CONTEXT(state, context);
return Py_NewRef(context);
}
/* Set the thread local context to a new context, decrement old reference */
static PyObject *
-PyDec_SetCurrentContext(PyObject *self UNUSED, PyObject *v)
+PyDec_SetCurrentContext(PyObject *self, PyObject *v)
{
PyObject *dict;
- decimal_state *state = GLOBAL_STATE();
+ decimal_state *state = get_module_state(self);
CONTEXT_CHECK(state, v);
dict = PyThreadState_GetDict();
}
#else
static PyObject *
-init_current_context(void)
+init_current_context(decimal_state *state)
{
- decimal_state *state = GLOBAL_STATE();
PyObject *tl_context = context_copy(state->default_context_template, NULL);
if (tl_context == NULL) {
return NULL;
}
static inline PyObject *
-current_context(void)
+current_context(decimal_state *state)
{
PyObject *tl_context;
- decimal_state *state = GLOBAL_STATE();
if (PyContextVar_Get(state->current_context_var, NULL, &tl_context) < 0) {
return NULL;
}
return tl_context;
}
- return init_current_context();
+ return init_current_context(state);
}
/* ctxobj := borrowed reference to the current context */
-#define CURRENT_CONTEXT(ctxobj) \
- ctxobj = current_context(); \
+#define CURRENT_CONTEXT(state, ctxobj) \
+ ctxobj = current_context(state); \
if (ctxobj == NULL) { \
return NULL; \
} \
/* Return a new reference to the current context */
static PyObject *
-PyDec_GetCurrentContext(PyObject *self UNUSED, PyObject *args UNUSED)
+PyDec_GetCurrentContext(PyObject *self, PyObject *args UNUSED)
{
- return current_context();
+ decimal_state *state = get_module_state(self);
+ return current_context(state);
}
/* Set the thread local context to a new context, decrement old reference */
static PyObject *
-PyDec_SetCurrentContext(PyObject *self UNUSED, PyObject *v)
+PyDec_SetCurrentContext(PyObject *self, PyObject *v)
{
- decimal_state *state = GLOBAL_STATE();
+ decimal_state *state = get_module_state(self);
CONTEXT_CHECK(state, v);
/* If the new context is one of the templates, make a copy.
* owns one reference to the global (outer) context and one
* to the local (inner) context. */
static PyObject *
-ctxmanager_new(PyTypeObject *type UNUSED, PyObject *args, PyObject *kwds)
+ctxmanager_new(PyObject *m, PyObject *args, PyObject *kwds)
{
static char *kwlist[] = {
"ctx", "prec", "rounding",
PyObject *flags = Py_None;
PyObject *traps = Py_None;
- decimal_state *state = GLOBAL_STATE();
- CURRENT_CONTEXT(global);
+ decimal_state *state = get_module_state(m);
+ CURRENT_CONTEXT(state, global);
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOOOOOOOO", kwlist, &local,
&prec, &rounding, &Emin, &Emax, &capitals, &clamp, &flags, &traps)) {
return NULL;
{
PyObject *ret;
- ret = PyDec_SetCurrentContext(NULL, self->local);
+ ret = PyDec_SetCurrentContext(PyType_GetModule(Py_TYPE(self)), self->local);
if (ret == NULL) {
return NULL;
}
{
PyObject *ret;
- ret = PyDec_SetCurrentContext(NULL, self->global);
+ ret = PyDec_SetCurrentContext(PyType_GetModule(Py_TYPE(self)), self->global);
if (ret == NULL) {
return NULL;
}
{
PyDecObject *dec;
- decimal_state *state = GLOBAL_STATE();
+ decimal_state *state = get_module_state_by_def(type);
if (type == state->PyDec_Type) {
dec = PyObject_GC_New(PyDecObject, state->PyDec_Type);
}
mpd_t *d1, *d2;
uint32_t status = 0;
mpd_context_t maxctx;
+ decimal_state *state = get_module_state_by_def(type);
- decimal_state *state = GLOBAL_STATE();
#ifdef Py_DEBUG
assert(PyType_IsSubtype(type, state->PyDec_Type));
#endif
PyObject *dec;
uint32_t status = 0;
- decimal_state *state = GLOBAL_STATE();
+ decimal_state *state = get_module_state_by_def(type);
if (type == state->PyDec_Type && PyDec_CheckExact(state, v)) {
return Py_NewRef(v);
}
PyObject *context;
PyObject *result;
- CURRENT_CONTEXT(context);
- decimal_state *state = GLOBAL_STATE();
+ decimal_state *state = get_module_state_by_def((PyTypeObject *)type);
+ CURRENT_CONTEXT(state, context);
result = PyDecType_FromFloatExact(state->PyDec_Type, pyfloat, context);
if (type != (PyObject *)state->PyDec_Type && result != NULL) {
Py_SETREF(result, PyObject_CallFunctionObjArgs(type, result, NULL));
static PyObject *
ctx_from_float(PyObject *context, PyObject *v)
{
- decimal_state *state = GLOBAL_STATE();
+ decimal_state *state = get_module_state_by_def(Py_TYPE(context));
return PyDec_FromFloat(state, v, context);
}
PyObject *result;
uint32_t status = 0;
- decimal_state *state = GLOBAL_STATE();
+ decimal_state *state = get_module_state_by_def(Py_TYPE(context));
result = dec_alloc(state);
if (result == NULL) {
return NULL;
static PyObject *
PyDecType_FromObjectExact(PyTypeObject *type, PyObject *v, PyObject *context)
{
- decimal_state *state = GLOBAL_STATE();
+ decimal_state *state = get_module_state_by_def(type);
if (v == NULL) {
return PyDecType_FromSsizeExact(type, 0, context);
}
static PyObject *
PyDec_FromObject(PyObject *v, PyObject *context)
{
- decimal_state *state = GLOBAL_STATE();
+ decimal_state *state = get_module_state_by_def(Py_TYPE(context));
if (v == NULL) {
return PyDec_FromSsize(state, 0, context);
}
&v, &context)) {
return NULL;
}
- decimal_state *state = GLOBAL_STATE();
+ decimal_state *state = get_module_state_by_def(type);
CONTEXT_CHECK_VA(state, context);
return PyDecType_FromObjectExact(type, v, context);
Py_LOCAL_INLINE(int)
convert_op(int type_err, PyObject **conv, PyObject *v, PyObject *context)
{
- decimal_state *state = GLOBAL_STATE();
+ decimal_state *state = get_module_state_by_def(Py_TYPE(context));
if (PyDec_Check(state, v)) {
*conv = Py_NewRef(v);
return 1;
if (tmp == NULL) {
return NULL;
}
- decimal_state *state = GLOBAL_STATE();
+ decimal_state *state = get_module_state_by_def(Py_TYPE(context));
denom = PyDec_FromLongExact(state, tmp, context);
Py_DECREF(tmp);
if (denom == NULL) {
return NULL;
}
- decimal_state *state = GLOBAL_STATE();
+ decimal_state *state = get_module_state_by_def(Py_TYPE(context));
num = PyDec_FromLongExact(state, tmp, context);
Py_DECREF(tmp);
return num;
*vcmp = v;
- decimal_state *state = GLOBAL_STATE();
+ decimal_state *state = get_module_state_by_def(Py_TYPE(context));
if (PyDec_Check(state, w)) {
*wcmp = Py_NewRef(w);
}
mpd_ssize_t size;
char *cp;
- CURRENT_CONTEXT(context);
+ decimal_state *state = get_module_state_by_def(Py_TYPE(dec));
+ CURRENT_CONTEXT(state, context);
size = mpd_to_sci_size(&cp, MPD(dec), CtxCaps(context));
if (size < 0) {
PyErr_NoMemory();
{
PyObject *res, *context;
char *cp;
-
- CURRENT_CONTEXT(context);
+ decimal_state *state = get_module_state_by_def(Py_TYPE(dec));
+ CURRENT_CONTEXT(state, context);
cp = mpd_to_sci(MPD(dec), CtxCaps(context));
if (cp == NULL) {
PyErr_NoMemory();
mpd_t tmp = {MPD_STATIC|MPD_STATIC_DATA,0,0,0,MPD_MINALLOC_MAX,dt};
- CURRENT_CONTEXT(context);
+ decimal_state *state = get_module_state_by_def(Py_TYPE(dec));
+ CURRENT_CONTEXT(state, context);
if (!PyArg_ParseTuple(args, "O|O", &fmtarg, &override)) {
return NULL;
}
return NULL;
}
- CURRENT_CONTEXT(context);
+ decimal_state *state = get_module_state_by_def(Py_TYPE(self));
+ CURRENT_CONTEXT(state, context);
- decimal_state *state = GLOBAL_STATE();
tmp = dec_alloc(state);
if (tmp == NULL) {
return NULL;
&rounding, &context)) {
return NULL;
}
- decimal_state *state = GLOBAL_STATE();
+ decimal_state *state = get_module_state_by_def(Py_TYPE(dec));
CONTEXT_CHECK_VA(state, context);
workctx = *CTX(context);
if (rounding != Py_None) {
- int round = getround(rounding);
+ int round = getround(state, rounding);
if (round < 0) {
return NULL;
}
&rounding, &context)) {
return NULL;
}
- decimal_state *state = GLOBAL_STATE();
+ decimal_state *state = get_module_state_by_def(Py_TYPE(dec));
CONTEXT_CHECK_VA(state, context);
workctx = *CTX(context);
if (rounding != Py_None) {
- int round = getround(rounding);
+ int round = getround(state, rounding);
if (round < 0) {
return NULL;
}
uint32_t status = 0;
PyObject *context;
- CURRENT_CONTEXT(context);
+ decimal_state *state = get_module_state_by_def(Py_TYPE(dec));
+ CURRENT_CONTEXT(state, context);
if (!PyArg_ParseTuple(args, "|O", &x)) {
return NULL;
}
if (y == -1 && PyErr_Occurred()) {
return NULL;
}
- decimal_state *state = GLOBAL_STATE();
result = dec_alloc(state);
if (result == NULL) {
return NULL;
}
}
- decimal_state *state = GLOBAL_STATE();
+ decimal_state *state = get_module_state_by_def(Py_TYPE(dec));
result = PyObject_CallFunctionObjArgs((PyObject *)state->DecimalTuple,
sign, coeff, expt, NULL);
PyObject *context; \
uint32_t status = 0; \
\
- decimal_state *state = GLOBAL_STATE(); \
- CURRENT_CONTEXT(context); \
+ decimal_state *state = get_module_state_by_def(Py_TYPE(self)); \
+ CURRENT_CONTEXT(state, context); \
if ((result = dec_alloc(state)) == NULL) { \
return NULL; \
} \
PyObject *context; \
uint32_t status = 0; \
\
- decimal_state *state = GLOBAL_STATE(); \
- CURRENT_CONTEXT(context) ; \
+ decimal_state *state = find_state_left_or_right(self, other); \
+ CURRENT_CONTEXT(state, context) ; \
CONVERT_BINOP(&a, &b, self, other, context); \
\
if ((result = dec_alloc(state)) == NULL) { \
&context)) { \
return NULL; \
} \
- decimal_state *state = GLOBAL_STATE(); \
+ decimal_state *state = get_module_state_by_def(Py_TYPE(self)); \
CONTEXT_CHECK_VA(state, context); \
\
return MPDFUNC(MPD(self), CTX(context)) ? incr_true() : incr_false(); \
&context)) { \
return NULL; \
} \
- decimal_state *state = GLOBAL_STATE(); \
+ decimal_state *state = \
+ get_module_state_by_def(Py_TYPE(self)); \
CONTEXT_CHECK_VA(state, context); \
\
if ((result = dec_alloc(state)) == NULL) { \
&other, &context)) { \
return NULL; \
} \
- decimal_state *state = GLOBAL_STATE(); \
+ decimal_state *state = \
+ get_module_state_by_def(Py_TYPE(self)); \
CONTEXT_CHECK_VA(state, context); \
CONVERT_BINOP_RAISE(&a, &b, self, other, context); \
\
&other, &context)) { \
return NULL; \
} \
- decimal_state *state = GLOBAL_STATE(); \
+ decimal_state *state = \
+ get_module_state_by_def(Py_TYPE(self)); \
CONTEXT_CHECK_VA(state, context); \
CONVERT_BINOP_RAISE(&a, &b, self, other, context); \
\
&other, &third, &context)) { \
return NULL; \
} \
- decimal_state *state = GLOBAL_STATE(); \
+ decimal_state *state = get_module_state_by_def(Py_TYPE(self)); \
CONTEXT_CHECK_VA(state, context); \
CONVERT_TERNOP_RAISE(&a, &b, &c, self, other, third, context); \
\
nm_dec_as_long(PyObject *dec)
{
PyObject *context;
-
- CURRENT_CONTEXT(context);
+ decimal_state *state = get_module_state_by_def(Py_TYPE(dec));
+ CURRENT_CONTEXT(state, context);
return dec_as_long(dec, context, MPD_ROUND_DOWN);
}
uint32_t status = 0;
PyObject *ret;
- CURRENT_CONTEXT(context);
+ decimal_state *state = find_state_left_or_right(v, w);
+ CURRENT_CONTEXT(state, context);
CONVERT_BINOP(&a, &b, v, w, context);
- decimal_state *state = GLOBAL_STATE();
q = dec_alloc(state);
if (q == NULL) {
Py_DECREF(a);
PyObject *context;
uint32_t status = 0;
- CURRENT_CONTEXT(context);
+ decimal_state *state = find_state_left_or_right(base, exp);
+ CURRENT_CONTEXT(state, context);
CONVERT_BINOP(&a, &b, base, exp, context);
if (mod != Py_None) {
}
}
- decimal_state *state = GLOBAL_STATE();
result = dec_alloc(state);
if (result == NULL) {
Py_DECREF(a);
}
static PyObject *
-dec_mpd_radix(PyObject *self UNUSED, PyObject *dummy UNUSED)
+dec_mpd_radix(PyObject *self, PyObject *dummy UNUSED)
{
PyObject *result;
- decimal_state *state = GLOBAL_STATE();
+ decimal_state *state = get_module_state_by_def(Py_TYPE(self));
result = dec_alloc(state);
if (result == NULL) {
return NULL;
PyObject *result;
uint32_t status = 0;
- decimal_state *state = GLOBAL_STATE();
+ decimal_state *state = get_module_state_by_def(Py_TYPE(self));
if ((result = dec_alloc(state)) == NULL) {
return NULL;
}
PyObject *result;
uint32_t status = 0;
- decimal_state *state = GLOBAL_STATE();
+ decimal_state *state = get_module_state_by_def(Py_TYPE(self));
if ((result = dec_alloc(state)) == NULL) {
return NULL;
}
&context)) {
return NULL;
}
- decimal_state *state = GLOBAL_STATE();
+ decimal_state *state = get_module_state_by_def(Py_TYPE(self));
CONTEXT_CHECK_VA(state, context);
cp = mpd_class(MPD(self), CTX(context));
&context)) {
return NULL;
}
- decimal_state *state = GLOBAL_STATE();
+ decimal_state *state = get_module_state_by_def(Py_TYPE(self));
CONTEXT_CHECK_VA(state, context);
size = mpd_to_eng_size(&s, MPD(self), CtxCaps(context));
&other, &context)) {
return NULL;
}
- decimal_state *state = GLOBAL_STATE();
+ decimal_state *state = get_module_state_by_def(Py_TYPE(self));
CONTEXT_CHECK_VA(state, context);
CONVERT_BINOP_RAISE(&a, &b, self, other, context);
&other, &context)) {
return NULL;
}
- decimal_state *state = GLOBAL_STATE();
+ decimal_state *state = get_module_state_by_def(Py_TYPE(self));
CONTEXT_CHECK_VA(state, context);
CONVERT_BINOP_RAISE(&a, &b, self, other, context);
&w, &rounding, &context)) {
return NULL;
}
- decimal_state *state = GLOBAL_STATE();
+ decimal_state *state = get_module_state_by_def(Py_TYPE(v));
CONTEXT_CHECK_VA(state, context);
workctx = *CTX(context);
if (rounding != Py_None) {
- int round = getround(rounding);
+ int round = getround(state, rounding);
if (round < 0) {
return NULL;
}
uint32_t status = 0;
int a_issnan, b_issnan;
int r;
+ decimal_state *state = find_state_left_or_right(v, w);
#ifdef Py_DEBUG
- decimal_state *state = GLOBAL_STATE();
assert(PyDec_Check(state, v));
#endif
- CURRENT_CONTEXT(context);
+ CURRENT_CONTEXT(state, context);
CONVERT_BINOP_CMP(&a, &b, v, w, op, context);
a_issnan = mpd_issnan(MPD(a));
{
PyObject *context;
- CURRENT_CONTEXT(context);
+ decimal_state *state = get_module_state_by_def(Py_TYPE(self));
+ CURRENT_CONTEXT(state, context);
return dec_as_long(self, context, MPD_ROUND_CEILING);
}
{
PyObject *context;
- CURRENT_CONTEXT(context);
+ decimal_state *state = get_module_state_by_def(Py_TYPE(self));
+ CURRENT_CONTEXT(state, context);
return dec_as_long(self, context, MPD_ROUND_FLOOR);
}
{
PyObject *context;
- CURRENT_CONTEXT(context);
+ decimal_state *state = get_module_state_by_def(Py_TYPE(self));
+ CURRENT_CONTEXT(state, context);
return dec_as_long(self, context, MPD_ROUND_DOWN);
}
{
PyObject *result;
- decimal_state *state = GLOBAL_STATE();
+ decimal_state *state = get_module_state_by_def(Py_TYPE(self));
result = dec_alloc(state);
if (result == NULL) {
return NULL;
uint32_t status = 0; \
\
CONVERT_OP_RAISE(&a, v, context); \
- decimal_state *state = GLOBAL_STATE(); \
+ decimal_state *state = \
+ get_module_state_by_def(Py_TYPE(context)); \
if ((result = dec_alloc(state)) == NULL) { \
Py_DECREF(a); \
return NULL; \
} \
\
CONVERT_BINOP_RAISE(&a, &b, v, w, context); \
- decimal_state *state = GLOBAL_STATE(); \
+ decimal_state *state = \
+ get_module_state_by_def(Py_TYPE(context)); \
if ((result = dec_alloc(state)) == NULL) { \
Py_DECREF(a); \
Py_DECREF(b); \
} \
\
CONVERT_BINOP_RAISE(&a, &b, v, w, context); \
- decimal_state *state = GLOBAL_STATE(); \
+ decimal_state *state = \
+ get_module_state_by_def(Py_TYPE(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 = GLOBAL_STATE(); \
+ decimal_state *state = get_module_state_by_def(Py_TYPE(context)); \
if ((result = dec_alloc(state)) == NULL) { \
Py_DECREF(a); \
Py_DECREF(b); \
}
CONVERT_BINOP_RAISE(&a, &b, v, w, context);
- decimal_state *state = GLOBAL_STATE();
+ decimal_state *state = get_module_state_by_def(Py_TYPE(context));
q = dec_alloc(state);
if (q == NULL) {
Py_DECREF(a);
}
}
- decimal_state *state = GLOBAL_STATE();
+ decimal_state *state = get_module_state_by_def(Py_TYPE(context));
result = dec_alloc(state);
if (result == NULL) {
Py_DECREF(a);
DecCtx_BoolFunc_NO_CTX(mpd_iszero)
static PyObject *
-ctx_iscanonical(PyObject *context UNUSED, PyObject *v)
+ctx_iscanonical(PyObject *context, PyObject *v)
{
- decimal_state *state = GLOBAL_STATE();
+ decimal_state *state = get_module_state_by_def(Py_TYPE(context));
if (!PyDec_Check(state, v)) {
PyErr_SetString(PyExc_TypeError,
"argument must be a Decimal");
}
static PyObject *
-ctx_canonical(PyObject *context UNUSED, PyObject *v)
+ctx_canonical(PyObject *context, PyObject *v)
{
- decimal_state *state = GLOBAL_STATE();
+ decimal_state *state = get_module_state_by_def(Py_TYPE(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 = GLOBAL_STATE();
+ decimal_state *state = get_module_state_by_def(Py_TYPE(context));
result = dec_alloc(state);
if (result == NULL) {
Py_DECREF(a);
uint32_t status = 0;
CONVERT_OP_RAISE(&a, v, context);
- decimal_state *state = GLOBAL_STATE();
+ decimal_state *state = get_module_state_by_def(Py_TYPE(context));
result = dec_alloc(state);
if (result == NULL) {
Py_DECREF(a);
}
CONVERT_BINOP_RAISE(&a, &b, v, w, context);
- decimal_state *state = GLOBAL_STATE();
+ decimal_state *state = get_module_state_by_def(Py_TYPE(context));
result = dec_alloc(state);
if (result == NULL) {
Py_DECREF(a);
{ NULL, NULL, 1, NULL }
};
-static struct PyModuleDef _decimal_module = {
- PyModuleDef_HEAD_INIT,
- "decimal",
- doc__decimal,
- -1,
- _decimal_methods,
- NULL,
- NULL,
- NULL,
- NULL
-};
struct ssize_constmap { const char *name; mpd_ssize_t val; };
static struct ssize_constmap ssize_constants [] = {
}
-PyMODINIT_FUNC
-PyInit__decimal(void)
+static int
+_decimal_exec(PyObject *m)
{
- PyObject *m = NULL;
PyObject *numbers = NULL;
PyObject *Number = NULL;
PyObject *collections = NULL;
mpd_free = PyMem_Free;
mpd_setminalloc(_Py_DEC_MINALLOC);
- decimal_state *state = GLOBAL_STATE();
+ decimal_state *state = get_module_state(m);
/* Init external C-API functions */
state->_py_long_multiply = PyLong_Type.tp_as_number->nb_multiply;
Py_CLEAR(collections_abc);
Py_CLEAR(MutableMapping);
-
- /* Create the module */
- ASSIGN_PTR(m, PyModule_Create(&_decimal_module));
-
/* Add types to the module */
CHECK_INT(PyModule_AddType(m, state->PyDec_Type));
CHECK_INT(PyModule_AddType(m, state->PyDecContext_Type));
CHECK_INT(PyModule_AddStringConstant(m, "__version__", "1.70"));
CHECK_INT(PyModule_AddStringConstant(m, "__libmpdec_version__", mpd_version()));
-
- return m;
-
+ return 0;
error:
Py_CLEAR(obj); /* GCOV_NOT_REACHED */
Py_CLEAR(numbers); /* GCOV_NOT_REACHED */
Py_CLEAR(Number); /* GCOV_NOT_REACHED */
- Py_CLEAR(state->Rational); /* GCOV_NOT_REACHED */
Py_CLEAR(collections); /* GCOV_NOT_REACHED */
Py_CLEAR(collections_abc); /* GCOV_NOT_REACHED */
Py_CLEAR(MutableMapping); /* GCOV_NOT_REACHED */
- Py_CLEAR(state->SignalTuple); /* GCOV_NOT_REACHED */
- PyMem_Free(state->signal_map); /* GCOV_NOT_REACHED */
- PyMem_Free(state->cond_map); /* GCOV_NOT_REACHED */
- Py_CLEAR(state->DecimalTuple); /* GCOV_NOT_REACHED */
- Py_CLEAR(state->default_context_template); /* GCOV_NOT_REACHED */
+
+ return -1;
+}
+
+static int
+decimal_traverse(PyObject *module, visitproc visit, void *arg)
+{
+ decimal_state *state = get_module_state(module);
+ Py_VISIT(state->PyDecContextManager_Type);
+ Py_VISIT(state->PyDecContext_Type);
+ Py_VISIT(state->PyDecSignalDictMixin_Type);
+ Py_VISIT(state->PyDec_Type);
+ Py_VISIT(state->PyDecSignalDict_Type);
+ Py_VISIT(state->DecimalTuple);
+ Py_VISIT(state->DecimalException);
+
+#ifndef WITH_DECIMAL_CONTEXTVAR
+ Py_VISIT(state->tls_context_key);
+ Py_VISIT(state->cached_context);
+#else
+ Py_VISIT(state->current_context_var);
+#endif
+
+ Py_VISIT(state->default_context_template);
+ Py_VISIT(state->basic_context_template);
+ Py_VISIT(state->extended_context_template);
+ Py_VISIT(state->Rational);
+ Py_VISIT(state->SignalTuple);
+
+ return 0;
+}
+
+static int
+decimal_clear(PyObject *module)
+{
+ decimal_state *state = get_module_state(module);
+ Py_CLEAR(state->PyDecContextManager_Type);
+ Py_CLEAR(state->PyDecContext_Type);
+ Py_CLEAR(state->PyDecSignalDictMixin_Type);
+ Py_CLEAR(state->PyDec_Type);
+ Py_CLEAR(state->PyDecSignalDict_Type);
+ Py_CLEAR(state->DecimalTuple);
+ Py_CLEAR(state->DecimalException);
+
#ifndef WITH_DECIMAL_CONTEXTVAR
- Py_CLEAR(state->tls_context_key); /* GCOV_NOT_REACHED */
+ Py_CLEAR(state->tls_context_key);
+ Py_CLEAR(state->cached_context);
#else
- Py_CLEAR(state->current_context_var); /* GCOV_NOT_REACHED */
+ Py_CLEAR(state->current_context_var);
#endif
- Py_CLEAR(state->basic_context_template); /* GCOV_NOT_REACHED */
- Py_CLEAR(state->extended_context_template); /* GCOV_NOT_REACHED */
- Py_CLEAR(m); /* GCOV_NOT_REACHED */
- return NULL; /* GCOV_NOT_REACHED */
+ Py_CLEAR(state->default_context_template);
+ Py_CLEAR(state->basic_context_template);
+ Py_CLEAR(state->extended_context_template);
+ Py_CLEAR(state->Rational);
+ Py_CLEAR(state->SignalTuple);
+
+ PyMem_Free(state->signal_map);
+ PyMem_Free(state->cond_map);
+ return 0;
+}
+
+static void
+decimal_free(void *module)
+{
+ (void)decimal_clear((PyObject *)module);
+}
+
+static struct PyModuleDef_Slot _decimal_slots[] = {
+ {Py_mod_exec, _decimal_exec},
+ {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED},
+ {0, NULL},
+};
+
+static struct PyModuleDef _decimal_module = {
+ PyModuleDef_HEAD_INIT,
+ .m_name = "decimal",
+ .m_doc = doc__decimal,
+ .m_size = sizeof(decimal_state),
+ .m_methods = _decimal_methods,
+ .m_slots = _decimal_slots,
+ .m_traverse = decimal_traverse,
+ .m_clear = decimal_clear,
+ .m_free = decimal_free,
+};
+
+PyMODINIT_FUNC
+PyInit__decimal(void)
+{
+ return PyModuleDef_Init(&_decimal_module);
}