cpython/Modules/_decimal/_decimal.c

/*
 * Copyright (c) 2008-2012 Stefan Krah. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

#ifndef Py_BUILD_CORE_BUILTIN
#define Py_BUILD_CORE_MODULE
#endif

#include <Python.h>
#include "pycore_long.h"          // _PyLong_IsZero()
#include "pycore_pystate.h"       // _PyThreadState_GET()
#include "pycore_typeobject.h"
#include "complexobject.h"

#include <mpdecimal.h>

// Reuse config from mpdecimal.h if present.
#if defined(MPD_CONFIG_64)
  #ifndef CONFIG_64
    #define CONFIG_64
  #endif
#elif defined(MPD_CONFIG_32)
  #ifndef CONFIG_32
    #define CONFIG_32
  #endif
#endif

#include <ctype.h>                // isascii()
#include <stdlib.h>

#include "docstrings.h"

#ifdef EXTRA_FUNCTIONALITY
  #define _PY_DEC_ROUND_GUARD
#else
  #define _PY_DEC_ROUND_GUARD
#endif

struct PyDecContextObject;
struct DecCondMap;

decimal_state;

static inline decimal_state *
get_module_state(PyObject *mod)
{}

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)
{}

static inline decimal_state *
find_state_left_or_right(PyObject *left, PyObject *right)
{}


#if !defined(MPD_VERSION_HEX) || MPD_VERSION_HEX < 0x02050000
  #error "libmpdec version >= 2.5.0 required"
#endif


/*
 * Type sizes with assertions in mpdecimal.h and pyport.h:
 *    sizeof(size_t) == sizeof(Py_ssize_t)
 *    sizeof(size_t) == sizeof(mpd_uint_t) == sizeof(mpd_ssize_t)
 */

#ifdef TEST_COVERAGE
  #undef Py_LOCAL_INLINE
  #define Py_LOCAL_INLINE
#endif

#define MPD_Float_operation

#define BOUNDS_CHECK(x, MIN, MAX)

/* _Py_DEC_MINALLOC >= MPD_MINALLOC */
#define _Py_DEC_MINALLOC

PyDecObject;

PyDecSignalDictObject;

PyDecContextObject;

PyDecContextManagerObject;

#undef MPD
#undef CTX
#define PyDec_CheckExact(st, v)
#define PyDec_Check(st, v)
#define PyDecSignalDict_Check(st, v)
#define PyDecContext_Check(st, v)
#define MPD(v)
#define SdFlagAddr(v)
#define SdFlags(v)
#define CTX(v)
#define CtxCaps(v)

static inline decimal_state *
get_module_state_from_ctx(PyObject *v)
{}


Py_LOCAL_INLINE(PyObject *)
incr_true(void)
{}

Py_LOCAL_INLINE(PyObject *)
incr_false(void)
{}

/* Error codes for functions that return signals or conditions */
#define DEC_INVALID_SIGNALS
#define DEC_ERR_OCCURRED
#define DEC_ERRORS

DecCondMap;

/* Exceptions that correspond to IEEE signals */
#define SUBNORMAL
#define INEXACT
#define ROUNDED
#define SIGNAL_MAP_LEN
static DecCondMap signal_map_template[] =;

/* Exceptions that inherit from InvalidOperation */
static DecCondMap cond_map_template[] =;

/* Return a duplicate of DecCondMap template */
static inline DecCondMap *
dec_cond_map_init(DecCondMap *template, Py_ssize_t size)
{}

static const char *dec_signal_string[MPD_NUM_FLAGS] =;

static const char *invalid_rounding_err =;

static const char *invalid_signals_err =;

#ifdef EXTRA_FUNCTIONALITY
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]";
#endif

static int
value_error_int(const char *mesg)
{}

static PyObject *
value_error_ptr(const char *mesg)
{}

static int
type_error_int(const char *mesg)
{}

static int
runtime_error_int(const char *mesg)
{}
#define INTERNAL_ERROR_INT(funcname)

static PyObject *
runtime_error_ptr(const char *mesg)
{}
#define INTERNAL_ERROR_PTR(funcname)

static void
dec_traphandler(mpd_context_t *Py_UNUSED(ctx)) /* GCOV_NOT_REACHED */
{}

static PyObject *
flags_as_exception(decimal_state *state, uint32_t flags)
{}

Py_LOCAL_INLINE(uint32_t)
exception_as_flag(decimal_state *state, PyObject *ex)
{}

static PyObject *
flags_as_list(decimal_state *state, uint32_t flags)
{}

static PyObject *
signals_as_list(decimal_state *state, uint32_t flags)
{}

static uint32_t
list_as_flags(decimal_state *state, PyObject *list)
{}

static PyObject *
flags_as_dict(decimal_state *state, uint32_t flags)
{}

static uint32_t
dict_as_flags(decimal_state *state, PyObject *val)
{}

#ifdef EXTRA_FUNCTIONALITY
static uint32_t
long_as_flags(PyObject *v)
{
    long x;

    x = PyLong_AsLong(v);
    if (x == -1 && PyErr_Occurred()) {
        return DEC_ERR_OCCURRED;
    }
    if (x < 0 || x > (long)MPD_Max_status) {
        PyErr_SetString(PyExc_TypeError, invalid_flags_err);
        return DEC_INVALID_SIGNALS;
    }

    return x;
}
#endif

static int
dec_addstatus(PyObject *context, uint32_t status)
{}

static int
getround(decimal_state *state, PyObject *v)
{}


/******************************************************************************/
/*                            SignalDict Object                               */
/******************************************************************************/

/* The SignalDict is a MutableMapping that provides access to the
   mpd_context_t flags, which reside in the context object. When a
   new context is created, context.traps and context.flags are
   initialized to new SignalDicts. Once a SignalDict is tied to
   a context, it cannot be deleted. */

static const char *INVALID_SIGNALDICT_ERROR_MSG =;

static int
signaldict_init(PyObject *self,
                PyObject *Py_UNUSED(args), PyObject *Py_UNUSED(kwds))
{}

static Py_ssize_t
signaldict_len(PyObject *self)
{}

static PyObject *
signaldict_iter(PyObject *self)
{}

static PyObject *
signaldict_getitem(PyObject *self, PyObject *key)
{}

static int
signaldict_setitem(PyObject *self, PyObject *key, PyObject *value)
{}

static int
signaldict_traverse(PyObject *self, visitproc visit, void *arg)
{}

static void
signaldict_dealloc(PyObject *self)
{}

static PyObject *
signaldict_repr(PyObject *self)
{}

static PyObject *
signaldict_richcompare(PyObject *v, PyObject *w, int op)
{}

static PyObject *
signaldict_copy(PyObject *self, PyObject *Py_UNUSED(dummy))
{}


static PyMethodDef signaldict_methods[] =;


static PyType_Slot signaldict_slots[] =;

static PyType_Spec signaldict_spec =;


/******************************************************************************/
/*                         Context Object, Part 1                             */
/******************************************************************************/

#define Dec_CONTEXT_GET_SSIZE(mem)

#define Dec_CONTEXT_GET_ULONG(mem)

Dec_CONTEXT_GET_SSIZE()
Dec_CONTEXT_GET_SSIZE()
Dec_CONTEXT_GET_SSIZE()
Dec_CONTEXT_GET_SSIZE()

#ifdef EXTRA_FUNCTIONALITY
Dec_CONTEXT_GET_ULONG(traps)
Dec_CONTEXT_GET_ULONG(status)
#endif

static PyObject *
context_getround(PyObject *self, void *Py_UNUSED(closure))
{}

static PyObject *
context_getcapitals(PyObject *self, void *Py_UNUSED(closure))
{}

#ifdef EXTRA_FUNCTIONALITY
static PyObject *
context_getallcr(PyObject *self, void *Py_UNUSED(closure))
{
    return PyLong_FromLong(mpd_getcr(CTX(self)));
}
#endif

static PyObject *
context_getetiny(PyObject *self, PyObject *Py_UNUSED(dummy))
{}

static PyObject *
context_getetop(PyObject *self, PyObject *Py_UNUSED(dummy))
{}

static int
context_setprec(PyObject *self, PyObject *value, void *Py_UNUSED(closure))
{}

static int
context_setemin(PyObject *self, PyObject *value, void *Py_UNUSED(closure))
{}

static int
context_setemax(PyObject *self, PyObject *value, void *Py_UNUSED(closure))
{}

#ifdef CONFIG_32
static PyObject *
context_unsafe_setprec(PyObject *self, PyObject *value)
{
    mpd_context_t *ctx = CTX(self);
    mpd_ssize_t x;

    x = PyLong_AsSsize_t(value);
    if (x == -1 && PyErr_Occurred()) {
        return NULL;
    }

    if (x < 1 || x > 1070000000L) {
        return value_error_ptr(
            "valid range for unsafe prec is [1, 1070000000]");
    }

    ctx->prec = x;
    Py_RETURN_NONE;
}

static PyObject *
context_unsafe_setemin(PyObject *self, PyObject *value)
{
    mpd_context_t *ctx = CTX(self);
    mpd_ssize_t x;

    x = PyLong_AsSsize_t(value);
    if (x == -1 && PyErr_Occurred()) {
        return NULL;
    }

    if (x < -1070000000L || x > 0) {
        return value_error_ptr(
            "valid range for unsafe emin is [-1070000000, 0]");
    }

    ctx->emin = x;
    Py_RETURN_NONE;
}

static PyObject *
context_unsafe_setemax(PyObject *self, PyObject *value)
{
    mpd_context_t *ctx = CTX(self);
    mpd_ssize_t x;

    x = PyLong_AsSsize_t(value);
    if (x == -1 && PyErr_Occurred()) {
        return NULL;
    }

    if (x < 0 || x > 1070000000L) {
        return value_error_ptr(
            "valid range for unsafe emax is [0, 1070000000]");
    }

    ctx->emax = x;
    Py_RETURN_NONE;
}
#endif

static int
context_setround(PyObject *self, PyObject *value, void *Py_UNUSED(closure))
{}

static int
context_setcapitals(PyObject *self, PyObject *value, void *Py_UNUSED(closure))
{}

#ifdef EXTRA_FUNCTIONALITY
static int
context_settraps(PyObject *self, PyObject *value, void *Py_UNUSED(closure))
{
    mpd_context_t *ctx;
    uint32_t flags;

    flags = long_as_flags(value);
    if (flags & DEC_ERRORS) {
        return -1;
    }

    ctx = CTX(self);
    if (!mpd_qsettraps(ctx, flags)) {
        INTERNAL_ERROR_INT("context_settraps");
    }

    return 0;
}
#endif

static int
context_settraps_list(PyObject *self, PyObject *value)
{}

static int
context_settraps_dict(PyObject *self, PyObject *value)
{}

#ifdef EXTRA_FUNCTIONALITY
static int
context_setstatus(PyObject *self, PyObject *value, void *Py_UNUSED(closure))
{
    mpd_context_t *ctx;
    uint32_t flags;

    flags = long_as_flags(value);
    if (flags & DEC_ERRORS) {
        return -1;
    }

    ctx = CTX(self);
    if (!mpd_qsetstatus(ctx, flags)) {
        INTERNAL_ERROR_INT("context_setstatus");
    }

    return 0;
}
#endif

static int
context_setstatus_list(PyObject *self, PyObject *value)
{}

static int
context_setstatus_dict(PyObject *self, PyObject *value)
{}

static int
context_setclamp(PyObject *self, PyObject *value, void *Py_UNUSED(closure))
{}

#ifdef EXTRA_FUNCTIONALITY
static int
context_setallcr(PyObject *self, PyObject *value, void *Py_UNUSED(closure))
{
    mpd_context_t *ctx;
    mpd_ssize_t x;

    x = PyLong_AsSsize_t(value);
    if (x == -1 && PyErr_Occurred()) {
        return -1;
    }
    BOUNDS_CHECK(x, INT_MIN, INT_MAX);

    ctx = CTX(self);
    if (!mpd_qsetcr(ctx, (int)x)) {
        return value_error_int("valid values for _allcr are 0 or 1");
    }

    return 0;
}
#endif

static PyObject *
context_getattr(PyObject *self, PyObject *name)
{}

static int
context_setattr(PyObject *self, PyObject *name, PyObject *value)
{}

static int
context_setattrs(PyObject *self, PyObject *prec, PyObject *rounding,
                 PyObject *emin, PyObject *emax, PyObject *capitals,
                 PyObject *clamp, PyObject *status, PyObject *traps) {}

static PyObject *
context_clear_traps(PyObject *self, PyObject *Py_UNUSED(dummy))
{}

static PyObject *
context_clear_flags(PyObject *self, PyObject *Py_UNUSED(dummy))
{}

#define DEC_DFLT_EMAX
#define DEC_DFLT_EMIN

static mpd_context_t dflt_ctx =;

static PyObject *
context_new(PyTypeObject *type,
            PyObject *Py_UNUSED(args), PyObject *Py_UNUSED(kwds))
{}

static int
context_traverse(PyDecContextObject *self, visitproc visit, void *arg)
{}

static int
context_clear(PyDecContextObject *self)
{}

static void
context_dealloc(PyDecContextObject *self)
{}

static int
context_init(PyObject *self, PyObject *args, PyObject *kwds)
{}

static PyObject *
context_repr(PyDecContextObject *self)
{}

static void
init_basic_context(PyObject *v)
{}

static void
init_extended_context(PyObject *v)
{}

#ifdef EXTRA_FUNCTIONALITY
/* Factory function for creating IEEE interchange format contexts */
static PyObject *
ieee_context(PyObject *module, PyObject *v)
{
    PyObject *context;
    mpd_ssize_t bits;
    mpd_context_t ctx;

    bits = PyLong_AsSsize_t(v);
    if (bits == -1 && PyErr_Occurred()) {
        return NULL;
    }
    if (bits <= 0 || bits > INT_MAX) {
        goto error;
    }
    if (mpd_ieee_context(&ctx, (int)bits) < 0) {
        goto error;
    }

    decimal_state *state = get_module_state(module);
    context = PyObject_CallObject((PyObject *)state->PyDecContext_Type, NULL);
    if (context == NULL) {
        return NULL;
    }
    *CTX(context) = ctx;

    return context;

error:
    PyErr_Format(PyExc_ValueError,
        "argument must be a multiple of 32, with a maximum of %d",
        MPD_IEEE_CONTEXT_MAX_BITS);

    return NULL;
}
#endif

static PyObject *
context_copy(PyObject *self, PyObject *Py_UNUSED(dummy))
{}

static PyObject *
context_reduce(PyObject *self, PyObject *Py_UNUSED(dummy))
{}


static PyGetSetDef context_getsets [] =;


#define CONTEXT_CHECK(state, obj)

#define CONTEXT_CHECK_VA(state, obj)


/******************************************************************************/
/*                Global, thread local and temporary contexts                 */
/******************************************************************************/

/*
 * Thread local storage currently has a speed penalty of about 4%.
 * All functions that map Python's arithmetic operators to mpdecimal
 * functions have to look up the current context for each and every
 * operation.
 */

#ifndef WITH_DECIMAL_CONTEXTVAR
/* Get the context from the thread state dictionary. */
static PyObject *
current_context_from_dict(decimal_state *modstate)
{
    PyThreadState *tstate = _PyThreadState_GET();
#ifdef Py_DEBUG
    // The caller must hold the GIL
    _Py_EnsureTstateNotNULL(tstate);
#endif

    PyObject *dict = _PyThreadState_GetDict(tstate);
    if (dict == NULL) {
        PyErr_SetString(PyExc_RuntimeError,
            "cannot get thread state");
        return NULL;
    }

    PyObject *tl_context;
    tl_context = PyDict_GetItemWithError(dict, modstate->tls_context_key);
    if (tl_context != NULL) {
        /* We already have a thread local context. */
        CONTEXT_CHECK(modstate, tl_context);
    }
    else {
        if (PyErr_Occurred()) {
            return NULL;
        }

        /* Set up a new thread local context. */
        tl_context = context_copy(modstate->default_context_template, NULL);
        if (tl_context == NULL) {
            return NULL;
        }
        CTX(tl_context)->status = 0;

        if (PyDict_SetItem(dict, modstate->tls_context_key, tl_context) < 0) {
            Py_DECREF(tl_context);
            return NULL;
        }
        Py_DECREF(tl_context);
    }

    /* Cache the context of the current thread, assuming that it
     * will be accessed several times before a thread switch. */
    Py_XSETREF(modstate->cached_context,
               (PyDecContextObject *)Py_NewRef(tl_context));
    modstate->cached_context->tstate = tstate;

    /* Borrowed reference with refcount==1 */
    return tl_context;
}

/* Return borrowed reference to thread local context. */
static PyObject *
current_context(decimal_state *modstate)
{
    PyThreadState *tstate = _PyThreadState_GET();
    if (modstate->cached_context && modstate->cached_context->tstate == tstate) {
        return (PyObject *)(modstate->cached_context);
    }

    return current_context_from_dict(modstate);
}

/* ctxobj := borrowed reference to the current context */
#define CURRENT_CONTEXT

/* Return a new reference to the current context */
static PyObject *
PyDec_GetCurrentContext(PyObject *self, PyObject *Py_UNUSED(dummy))
{
    PyObject *context;
    decimal_state *state = get_module_state(self);

    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, PyObject *v)
{
    PyObject *dict;

    decimal_state *state = get_module_state(self);
    CONTEXT_CHECK(state, v);

    dict = PyThreadState_GetDict();
    if (dict == NULL) {
        PyErr_SetString(PyExc_RuntimeError,
            "cannot get thread state");
        return NULL;
    }

    /* If the new context is one of the templates, make a copy.
     * This is the current behavior of decimal.py. */
    if (v == state->default_context_template ||
        v == state->basic_context_template ||
        v == state->extended_context_template) {
        v = context_copy(v, NULL);
        if (v == NULL) {
            return NULL;
        }
        CTX(v)->status = 0;
    }
    else {
        Py_INCREF(v);
    }

    Py_CLEAR(state->cached_context);
    if (PyDict_SetItem(dict, state->tls_context_key, v) < 0) {
        Py_DECREF(v);
        return NULL;
    }

    Py_DECREF(v);
    Py_RETURN_NONE;
}
#else
static PyObject *
init_current_context(decimal_state *state)
{}

static inline PyObject *
current_context(decimal_state *state)
{}

/* ctxobj := borrowed reference to the current context */
#define CURRENT_CONTEXT(STATE, CTXOBJ)

/* Return a new reference to the current context */
static PyObject *
PyDec_GetCurrentContext(PyObject *self, PyObject *Py_UNUSED(dummy))
{}

/* Set the thread local context to a new context, decrement old reference */
static PyObject *
PyDec_SetCurrentContext(PyObject *self, PyObject *v)
{}
#endif

/* Context manager object for the 'with' statement. The manager
 * owns one reference to the global (outer) context and one
 * to the local (inner) context. */
static PyObject *
ctxmanager_new(PyObject *m, PyObject *args, PyObject *kwds)
{}

static int
ctxmanager_traverse(PyDecContextManagerObject *self, visitproc visit,
                    void *arg)
{}

static int
ctxmanager_clear(PyDecContextManagerObject *self)
{}

static void
ctxmanager_dealloc(PyDecContextManagerObject *self)
{}

static PyObject *
ctxmanager_set_local(PyDecContextManagerObject *self,
                     PyObject *Py_UNUSED(dummy))
{}

static PyObject *
ctxmanager_restore_global(PyDecContextManagerObject *self,
                          PyObject *Py_UNUSED(args))
{}


static PyMethodDef ctxmanager_methods[] =;

static PyType_Slot ctxmanager_slots[] =;

static PyType_Spec ctxmanager_spec =;


/******************************************************************************/
/*                           New Decimal Object                               */
/******************************************************************************/

static PyObject *
PyDecType_New(decimal_state *state, PyTypeObject *type)
{}
#define dec_alloc(st)

static int
dec_traverse(PyObject *dec, visitproc visit, void *arg)
{}

static void
dec_dealloc(PyObject *dec)
{}


/******************************************************************************/
/*                           Conversions to Decimal                           */
/******************************************************************************/

Py_LOCAL_INLINE(int)
is_space(int kind, const void *data, Py_ssize_t pos)
{}

/* Return the ASCII representation of a numeric Unicode string. The numeric
   string may contain ascii characters in the range [1, 127], any Unicode
   space and any unicode digit. If strip_ws is true, leading and trailing
   whitespace is stripped. If ignore_underscores is true, underscores are
   ignored.

   Return NULL if malloc fails and an empty string if invalid characters
   are found. */
static char *
numeric_as_ascii(PyObject *u, int strip_ws, int ignore_underscores)
{}

/* Return a new PyDecObject or a subtype from a C string. Use the context
   during conversion. */
static PyObject *
PyDecType_FromCString(PyTypeObject *type, const char *s,
                      PyObject *context)
{}

/* Return a new PyDecObject or a subtype from a C string. Attempt exact
   conversion. If the operand cannot be converted exactly, set
   InvalidOperation. */
static PyObject *
PyDecType_FromCStringExact(PyTypeObject *type, const char *s,
                           PyObject *context)
{}

/* Return a new PyDecObject or a subtype from a PyUnicodeObject. */
static PyObject *
PyDecType_FromUnicode(PyTypeObject *type, PyObject *u,
                      PyObject *context)
{}

/* Return a new PyDecObject or a subtype from a PyUnicodeObject. Attempt exact
 * conversion. If the conversion is not exact, fail with InvalidOperation.
 * Allow leading and trailing whitespace in the input operand. */
static PyObject *
PyDecType_FromUnicodeExactWS(PyTypeObject *type, PyObject *u,
                             PyObject *context)
{}

/* Set PyDecObject from triple without any error checking. */
Py_LOCAL_INLINE(void)
_dec_settriple(PyObject *dec, uint8_t sign, uint32_t v, mpd_ssize_t exp)
{}

/* Return a new PyDecObject from an mpd_ssize_t. */
static PyObject *
PyDecType_FromSsize(PyTypeObject *type, mpd_ssize_t v, PyObject *context)
{}

/* Return a new PyDecObject from an mpd_ssize_t. Conversion is exact. */
static PyObject *
PyDecType_FromSsizeExact(PyTypeObject *type, mpd_ssize_t v, PyObject *context)
{}

/* Convert from a PyLongObject. The context is not modified; flags set
   during conversion are accumulated in the status parameter. */
static PyObject *
dec_from_long(decimal_state *state, PyTypeObject *type, PyObject *v,
              const mpd_context_t *ctx, uint32_t *status)
{}

/* Return a new PyDecObject from a PyLongObject. Use the context for
   conversion. */
static PyObject *
PyDecType_FromLong(PyTypeObject *type, PyObject *v, PyObject *context)
{}

/* Return a new PyDecObject from a PyLongObject. Use a maximum context
   for conversion. If the conversion is not exact, set InvalidOperation. */
static PyObject *
PyDecType_FromLongExact(PyTypeObject *type, PyObject *v,
                        PyObject *context)
{}

/* Return a PyDecObject or a subtype from a PyFloatObject.
   Conversion is exact. */
static PyObject *
PyDecType_FromFloatExact(PyTypeObject *type, PyObject *v,
                         PyObject *context)
{}

static PyObject *
PyDecType_FromFloat(PyTypeObject *type, PyObject *v,
                    PyObject *context)
{}

/* Return a new PyDecObject or a subtype from a Decimal. */
static PyObject *
PyDecType_FromDecimalExact(PyTypeObject *type, PyObject *v, PyObject *context)
{}

static PyObject *
sequence_as_tuple(PyObject *v, PyObject *ex, const char *mesg)
{}

/* Return a new C string representation of a DecimalTuple. */
static char *
dectuple_as_str(PyObject *dectuple)
{}

/* Currently accepts tuples and lists. */
static PyObject *
PyDecType_FromSequence(PyTypeObject *type, PyObject *v,
                       PyObject *context)
{}

/* Currently accepts tuples and lists. */
static PyObject *
PyDecType_FromSequenceExact(PyTypeObject *type, PyObject *v,
                            PyObject *context)
{}

#define PyDec_FromCString(st, str, context)
#define PyDec_FromCStringExact(st, str, context)

#define PyDec_FromUnicode(st, unicode, context)
#define PyDec_FromUnicodeExact(st, unicode, context)
#define PyDec_FromUnicodeExactWS(st, unicode, context)

#define PyDec_FromSsize(st, v, context)
#define PyDec_FromSsizeExact(st, v, context)

#define PyDec_FromLong(st, pylong, context)
#define PyDec_FromLongExact(st, pylong, context)

#define PyDec_FromFloat(st, pyfloat, context)
#define PyDec_FromFloatExact(st, pyfloat, context)

#define PyDec_FromSequence(st, sequence, context)
#define PyDec_FromSequenceExact(st, sequence, context)

/* class method */
static PyObject *
dec_from_float(PyObject *type, PyObject *pyfloat)
{}

/* 'v' can have any numeric type accepted by the Decimal constructor. Attempt
   an exact conversion. If the result does not meet the restrictions
   for an mpd_t, fail with InvalidOperation. */
static PyObject *
PyDecType_FromNumberExact(PyTypeObject *type, PyObject *v, PyObject *context)
{}

/* class method */
static PyObject *
dec_from_number(PyObject *type, PyObject *number)
{}

/* create_decimal_from_float */
static PyObject *
ctx_from_float(PyObject *context, PyObject *v)
{}

/* Apply the context to the input operand. Return a new PyDecObject. */
static PyObject *
dec_apply(PyObject *v, PyObject *context)
{}

/* 'v' can have any type accepted by the Decimal constructor. Attempt
   an exact conversion. If the result does not meet the restrictions
   for an mpd_t, fail with InvalidOperation. */
static PyObject *
PyDecType_FromObjectExact(PyTypeObject *type, PyObject *v, PyObject *context)
{}

/* The context is used during conversion. This function is the
   equivalent of context.create_decimal(). */
static PyObject *
PyDec_FromObject(PyObject *v, PyObject *context)
{}

static PyObject *
dec_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{}

static PyObject *
ctx_create_decimal(PyObject *context, PyObject *args)
{}


/******************************************************************************/
/*                        Implicit conversions to Decimal                     */
/******************************************************************************/

/* Try to convert PyObject v to a new PyDecObject conv. If the conversion
   fails, set conv to NULL (exception is set). If the conversion is not
   implemented, set conv to Py_NotImplemented. */
#define NOT_IMPL
#define TYPE_ERR
Py_LOCAL_INLINE(int)
convert_op(int type_err, PyObject **conv, PyObject *v, PyObject *context)
{}

/* Return NotImplemented for unsupported types. */
#define CONVERT_OP(a, v, context)

#define CONVERT_BINOP(a, b, v, w, context)

#define CONVERT_TERNOP(a, b, c, v, w, x, context)

/* Raise TypeError for unsupported types. */
#define CONVERT_OP_RAISE(a, v, context)

#define CONVERT_BINOP_RAISE(a, b, v, w, context)

#define CONVERT_TERNOP_RAISE(a, b, c, v, w, x, context)


/******************************************************************************/
/*              Implicit conversions to Decimal for comparison                */
/******************************************************************************/

static PyObject *
multiply_by_denominator(PyObject *v, PyObject *r, PyObject *context)
{}

static PyObject *
numerator_as_decimal(PyObject *r, PyObject *context)
{}

/* Convert v and w for comparison. v is a Decimal. If w is a Rational, both
   v and w have to be transformed. Return 1 for success, with new references
   to the converted objects in vcmp and wcmp. Return 0 for failure. In that
   case wcmp is either NULL or Py_NotImplemented (new reference) and vcmp
   is undefined. */
static int
convert_op_cmp(PyObject **vcmp, PyObject **wcmp, PyObject *v, PyObject *w,
               int op, PyObject *context)
{}

#define CONVERT_BINOP_CMP(vcmp, wcmp, v, w, op, ctx)                                                  \


/******************************************************************************/
/*                          Conversions from decimal                          */
/******************************************************************************/

static PyObject *
unicode_fromascii(const char *s, Py_ssize_t size)
{}

/* PyDecObject as a string. The default module context is only used for
   the value of 'capitals'. */
static PyObject *
dec_str(PyObject *dec)
{}

/* Representation of a PyDecObject. */
static PyObject *
dec_repr(PyObject *dec)
{}

/* Return a duplicate of src, copy embedded null characters. */
static char *
dec_strdup(const char *src, Py_ssize_t size)
{}

static void
dec_replace_fillchar(char *dest)
{}

/* Convert decimal_point or thousands_sep, which may be multibyte or in
   the range [128, 255], to a UTF8 string. */
static PyObject *
dotsep_as_utf8(const char *s)
{}

static int
dict_get_item_string(PyObject *dict, const char *key, PyObject **valueobj, const char **valuestr)
{}

/*
 * Fallback _pydecimal formatting for new format specifiers that mpdecimal does
 * not yet support. As documented, libmpdec follows the PEP-3101 format language:
 * https://www.bytereef.org/mpdecimal/doc/libmpdec/assign-convert.html#to-string
 */
static PyObject *
pydec_format(PyObject *dec, PyObject *context, PyObject *fmt, decimal_state *state)
{}

/* Formatted representation of a PyDecObject. */
static PyObject *
dec_format(PyObject *dec, PyObject *args)
{}

/* Return a PyLongObject from a PyDecObject, using the specified rounding
 * mode. The context precision is not observed. */
static PyObject *
dec_as_long(PyObject *dec, PyObject *context, int round)
{}

/* Convert a Decimal to its exact integer ratio representation. */
static PyObject *
dec_as_integer_ratio(PyObject *self, PyObject *Py_UNUSED(dummy))
{}

static PyObject *
PyDec_ToIntegralValue(PyObject *dec, PyObject *args, PyObject *kwds)
{}

static PyObject *
PyDec_ToIntegralExact(PyObject *dec, PyObject *args, PyObject *kwds)
{}

static PyObject *
PyDec_AsFloat(PyObject *dec)
{}

static PyObject *
PyDec_Round(PyObject *dec, PyObject *args)
{}

/* Return the DecimalTuple representation of a PyDecObject. */
static PyObject *
PyDec_AsTuple(PyObject *dec, PyObject *Py_UNUSED(dummy))
{}


/******************************************************************************/
/*         Macros for converting mpdecimal functions to Decimal methods       */
/******************************************************************************/

/* Unary number method that uses the default module context. */
#define Dec_UnaryNumberMethod(MPDFUNC)

/* Binary number method that uses default module context. */
#define Dec_BinaryNumberMethod(MPDFUNC)

/* Boolean function without a context arg. */
#define Dec_BoolFunc(MPDFUNC)

/* Boolean function with an optional context arg. */
#define Dec_BoolFuncVA(MPDFUNC)

/* Unary function with an optional context arg. */
#define Dec_UnaryFuncVA(MPDFUNC)

/* Binary function with an optional context arg. */
#define Dec_BinaryFuncVA(MPDFUNC)

/* Binary function with an optional context arg. Actual MPDFUNC does
   NOT take a context. The context is used to record InvalidOperation
   if the second operand cannot be converted exactly. */
#define Dec_BinaryFuncVA_NO_CTX(MPDFUNC)

/* Ternary function with an optional context arg. */
#define Dec_TernaryFuncVA(MPDFUNC)


/**********************************************/
/*              Number methods                */
/**********************************************/

Dec_UnaryNumberMethod()
Dec_UnaryNumberMethod()
Dec_UnaryNumberMethod()

Dec_BinaryNumberMethod()
Dec_BinaryNumberMethod()
Dec_BinaryNumberMethod()
Dec_BinaryNumberMethod()
Dec_BinaryNumberMethod()
Dec_BinaryNumberMethod()

static PyObject *
nm_dec_as_long(PyObject *dec)
{}

static int
nm_nonzero(PyObject *v)
{}

static PyObject *
nm_mpd_qdivmod(PyObject *v, PyObject *w)
{}

static PyObject *
nm_mpd_qpow(PyObject *base, PyObject *exp, PyObject *mod)
{}


/******************************************************************************/
/*                             Decimal Methods                                */
/******************************************************************************/

/* Unary arithmetic functions, optional context arg */
Dec_UnaryFuncVA()
Dec_UnaryFuncVA()
Dec_UnaryFuncVA()
Dec_UnaryFuncVA()
Dec_UnaryFuncVA()
Dec_UnaryFuncVA()
Dec_UnaryFuncVA()

/* Binary arithmetic functions, optional context arg */
Dec_BinaryFuncVA()
Dec_BinaryFuncVA()
Dec_BinaryFuncVA()
Dec_BinaryFuncVA()
Dec_BinaryFuncVA()
Dec_BinaryFuncVA()
Dec_BinaryFuncVA()
Dec_BinaryFuncVA()

/* Ternary arithmetic functions, optional context arg */
Dec_TernaryFuncVA()

/* Boolean functions, no context arg */
Dec_BoolFunc()
Dec_BoolFunc()
Dec_BoolFunc()
Dec_BoolFunc()
Dec_BoolFunc()
Dec_BoolFunc()
Dec_BoolFunc()
Dec_BoolFunc()

/* Boolean functions, optional context arg */
Dec_BoolFuncVA()
Dec_BoolFuncVA()

/* Unary functions, no context arg */
static PyObject *
dec_mpd_adjexp(PyObject *self, PyObject *Py_UNUSED(dummy))
{}

static PyObject *
dec_canonical(PyObject *self, PyObject *Py_UNUSED(dummy))
{}

static PyObject *
dec_conjugate(PyObject *self, PyObject *Py_UNUSED(dummy))
{}

static inline PyObject *
_dec_mpd_radix(decimal_state *state)
{}

static PyObject *
dec_mpd_radix(PyObject *self, PyObject *Py_UNUSED(dummy))
{}

static PyObject *
dec_mpd_qcopy_abs(PyObject *self, PyObject *Py_UNUSED(dummy))
{}

static PyObject *
dec_mpd_qcopy_negate(PyObject *self, PyObject *Py_UNUSED(dummy))
{}

/* Unary functions, optional context arg */
Dec_UnaryFuncVA()
Dec_UnaryFuncVA()

static PyObject *
dec_mpd_class(PyObject *self, PyObject *args, PyObject *kwds)
{}

static PyObject *
dec_mpd_to_eng(PyObject *self, PyObject *args, PyObject *kwds)
{}

/* Binary functions, optional context arg for conversion errors */
Dec_BinaryFuncVA_NO_CTX()
Dec_BinaryFuncVA_NO_CTX()

static PyObject *
dec_mpd_qcopy_sign(PyObject *self, PyObject *args, PyObject *kwds)
{}

static PyObject *
dec_mpd_same_quantum(PyObject *self, PyObject *args, PyObject *kwds)
{}

/* Binary functions, optional context arg */
Dec_BinaryFuncVA()
Dec_BinaryFuncVA()
Dec_BinaryFuncVA()

Dec_BinaryFuncVA()
Dec_BinaryFuncVA()
Dec_BinaryFuncVA()

static PyObject *
dec_mpd_qquantize(PyObject *v, PyObject *args, PyObject *kwds)
{}

/* Special methods */
static PyObject *
dec_richcompare(PyObject *v, PyObject *w, int op)
{}

/* __ceil__ */
static PyObject *
dec_ceil(PyObject *self, PyObject *Py_UNUSED(dummy))
{}

/* __complex__ */
static PyObject *
dec_complex(PyObject *self, PyObject *Py_UNUSED(dummy))
{}

/* __copy__ (METH_NOARGS) and __deepcopy__ (METH_O) */
static PyObject *
dec_copy(PyObject *self, PyObject *Py_UNUSED(dummy))
{}

/* __floor__ */
static PyObject *
dec_floor(PyObject *self, PyObject *Py_UNUSED(dummy))
{}

/* Always uses the module context */
static Py_hash_t
_dec_hash(PyDecObject *v)
{}

static Py_hash_t
dec_hash(PyDecObject *self)
{}

/* __reduce__ */
static PyObject *
dec_reduce(PyObject *self, PyObject *Py_UNUSED(dummy))
{}

/* __sizeof__ */
static PyObject *
dec_sizeof(PyObject *v, PyObject *Py_UNUSED(dummy))
{}

/* __trunc__ */
static PyObject *
dec_trunc(PyObject *self, PyObject *Py_UNUSED(dummy))
{}

/* real and imag */
static PyObject *
dec_real(PyObject *self, void *Py_UNUSED(closure))
{}

static PyObject *
dec_imag(PyObject *self, void *Py_UNUSED(closure))
{}


static PyGetSetDef dec_getsets [] =;

static PyMethodDef dec_methods [] =;

static PyType_Slot dec_slots[] =;


static PyType_Spec dec_spec =;


/******************************************************************************/
/*                         Context Object, Part 2                             */
/******************************************************************************/


/************************************************************************/
/*     Macros for converting mpdecimal functions to Context methods     */
/************************************************************************/

/* Boolean context method. */
#define DecCtx_BoolFunc(MPDFUNC)

/* Boolean context method. MPDFUNC does NOT use a context. */
#define DecCtx_BoolFunc_NO_CTX(MPDFUNC)

/* Unary context method. */
#define DecCtx_UnaryFunc(MPDFUNC)

/* Binary context method. */
#define DecCtx_BinaryFunc(MPDFUNC)

/*
 * Binary context method. The context is only used for conversion.
 * The actual MPDFUNC does NOT take a context arg.
 */
#define DecCtx_BinaryFunc_NO_CTX(MPDFUNC)

/* Ternary context method. */
#define DecCtx_TernaryFunc(MPDFUNC)


/* Unary arithmetic functions */
DecCtx_UnaryFunc()
DecCtx_UnaryFunc()
DecCtx_UnaryFunc()
DecCtx_UnaryFunc()
DecCtx_UnaryFunc()
DecCtx_UnaryFunc()
DecCtx_UnaryFunc()
DecCtx_UnaryFunc()
DecCtx_UnaryFunc()
DecCtx_UnaryFunc()
DecCtx_UnaryFunc()
DecCtx_UnaryFunc()

/* Binary arithmetic functions */
DecCtx_BinaryFunc()
DecCtx_BinaryFunc()
DecCtx_BinaryFunc()
DecCtx_BinaryFunc()
DecCtx_BinaryFunc()
DecCtx_BinaryFunc()
DecCtx_BinaryFunc()
DecCtx_BinaryFunc()
DecCtx_BinaryFunc()
DecCtx_BinaryFunc()
DecCtx_BinaryFunc()
DecCtx_BinaryFunc()
DecCtx_BinaryFunc()
DecCtx_BinaryFunc()
DecCtx_BinaryFunc()

static PyObject *
ctx_mpd_qdivmod(PyObject *context, PyObject *args)
{}

/* Binary or ternary arithmetic functions */
static PyObject *
ctx_mpd_qpow(PyObject *context, PyObject *args, PyObject *kwds)
{}

/* Ternary arithmetic functions */
DecCtx_TernaryFunc()

/* No argument */
static PyObject *
ctx_mpd_radix(PyObject *context, PyObject *dummy)
{}

/* Boolean functions: single decimal argument */
DecCtx_BoolFunc()
DecCtx_BoolFunc()
DecCtx_BoolFunc_NO_CTX()
DecCtx_BoolFunc_NO_CTX()
DecCtx_BoolFunc_NO_CTX()
DecCtx_BoolFunc_NO_CTX()
DecCtx_BoolFunc_NO_CTX()
DecCtx_BoolFunc_NO_CTX()
DecCtx_BoolFunc_NO_CTX()

static PyObject *
ctx_iscanonical(PyObject *context, PyObject *v)
{}

/* Functions with a single decimal argument */
static PyObject *
PyDecContext_Apply(PyObject *context, PyObject *v)
{}

static PyObject *
ctx_canonical(PyObject *context, PyObject *v)
{}

static PyObject *
ctx_mpd_qcopy_abs(PyObject *context, PyObject *v)
{}

static PyObject *
ctx_copy_decimal(PyObject *context, PyObject *v)
{}

static PyObject *
ctx_mpd_qcopy_negate(PyObject *context, PyObject *v)
{}

DecCtx_UnaryFunc()
DecCtx_UnaryFunc()

static PyObject *
ctx_mpd_class(PyObject *context, PyObject *v)
{}

static PyObject *
ctx_mpd_to_sci(PyObject *context, PyObject *v)
{}

static PyObject *
ctx_mpd_to_eng(PyObject *context, PyObject *v)
{}

/* Functions with two decimal arguments */
DecCtx_BinaryFunc_NO_CTX()
DecCtx_BinaryFunc_NO_CTX()

static PyObject *
ctx_mpd_qcopy_sign(PyObject *context, PyObject *args)
{}

DecCtx_BinaryFunc()
DecCtx_BinaryFunc()
DecCtx_BinaryFunc()

DecCtx_BinaryFunc()
DecCtx_BinaryFunc()
DecCtx_BinaryFunc()

static PyObject *
ctx_mpd_same_quantum(PyObject *context, PyObject *args)
{}


static PyMethodDef context_methods [] =;

static PyType_Slot context_slots[] =;

static PyType_Spec context_spec =;


static PyMethodDef _decimal_methods [] =;


struct ssize_constmap {};
static struct ssize_constmap ssize_constants [] =;

struct int_constmap {};
static struct int_constmap int_constants [] =;


#define CHECK_INT(expr)
#define ASSIGN_PTR(result, expr)
#define CHECK_PTR(expr)


static PyCFunction
cfunc_noargs(PyTypeObject *t, const char *name)
{}

static int minalloc_is_set =;

static int
_decimal_exec(PyObject *m)
{}

static int
decimal_traverse(PyObject *module, visitproc visit, void *arg)
{}

static int
decimal_clear(PyObject *module)
{}

static void
decimal_free(void *module)
{}

static struct PyModuleDef_Slot _decimal_slots[] =;

static struct PyModuleDef _decimal_module =;

PyMODINIT_FUNC
PyInit__decimal(void)
{}