From 9afbcfb31000d2cee6715181e15eeaa4b9cd6698 Mon Sep 17 00:00:00 2001 From: Sergey B Kirpichev Date: Tue, 19 Aug 2025 04:56:02 +0300 Subject: [PATCH 1/4] gh-73487: Convert _decimal to use Argument Clinic (part 4) --- Modules/_decimal/_decimal.c | 387 ++++++++++++--- Modules/_decimal/clinic/_decimal.c.h | 674 ++++++++++++++++++++++++++- Modules/_decimal/docstrings.h | 125 ----- 3 files changed, 983 insertions(+), 203 deletions(-) diff --git a/Modules/_decimal/_decimal.c b/Modules/_decimal/_decimal.c index f10ddef6c8c04b..e9ded43b039be3 100644 --- a/Modules/_decimal/_decimal.c +++ b/Modules/_decimal/_decimal.c @@ -923,14 +923,34 @@ context_getallcr(PyObject *self, void *Py_UNUSED(closure)) } #endif +/*[clinic input] +_decimal.Context.Etiny + +Return a value equal to Emin - prec + 1. + +This is the minimum exponent value for subnormal results. When +underflow occurs, the exponent is set to Etiny. +[clinic start generated code]*/ + static PyObject * -context_getetiny(PyObject *self, PyObject *Py_UNUSED(dummy)) +_decimal_Context_Etiny_impl(PyObject *self) +/*[clinic end generated code: output=c9a4a1a3e3575289 input=1274040f303f2244]*/ { return PyLong_FromSsize_t(mpd_etiny(CTX(self))); } +/*[clinic input] +_decimal.Context.Etop + +Return a value equal to Emax - prec + 1. + +This is the maximum exponent if the _clamp field of the context is set +to 1 (IEEE clamp mode). Etop() must not be negative. +[clinic start generated code]*/ + static PyObject * -context_getetop(PyObject *self, PyObject *Py_UNUSED(dummy)) +_decimal_Context_Etop_impl(PyObject *self) +/*[clinic end generated code: output=f0a3f6e1b829074e input=838a4409316ec728]*/ { return PyLong_FromSsize_t(mpd_etop(CTX(self))); } @@ -3149,17 +3169,25 @@ PyDec_FromObject(PyObject *v, PyObject *context) } } +/*[clinic input] +@classmethod +_decimal.Decimal.__new__ as dec_new + + value as v: object(c_default="NULL") = "0" + context: object = None + +Construct a new Decimal object. + +value can be an integer, string, tuple, or another Decimal object. If +no value is given, return Decimal('0'). The context does not affect +the conversion and is only passed to determine if the InvalidOperation +trap is active. +[clinic start generated code]*/ + static PyObject * -dec_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +dec_new_impl(PyTypeObject *type, PyObject *v, PyObject *context) +/*[clinic end generated code: output=5371cbce41508fe7 input=6353a3563bea247b]*/ { - static char *kwlist[] = {"value", "context", NULL}; - PyObject *v = NULL; - PyObject *context = Py_None; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OO", kwlist, - &v, &context)) { - return NULL; - } decimal_state *state = get_module_state_by_def(type); CONTEXT_CHECK_VA(state, context); @@ -4105,20 +4133,24 @@ PyDec_AsFloat(PyObject *dec) return f; } +/*[clinic input] +_decimal.Decimal.__round__ + + self as dec: self + ndigits as x: object(c_default="NULL") = None + +Return the Integral closest to self, rounding half toward even. +[clinic start generated code]*/ + static PyObject * -PyDec_Round(PyObject *dec, PyObject *args) +_decimal_Decimal___round___impl(PyObject *dec, PyObject *x) +/*[clinic end generated code: output=5089b98ed18bb5e3 input=a3986615e1ad5b2a]*/ { PyObject *result; - PyObject *x = NULL; uint32_t status = 0; PyObject *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 (x) { mpd_uint_t dq[1] = {1}; mpd_t q = {MPD_STATIC|MPD_CONST_DATA,0,1,1,1,dq}; @@ -4316,8 +4348,6 @@ nm_##MPDFUNC(PyObject *self, PyObject *other) \ /* Boolean function without a context arg. */ #define Dec_BoolFunc(MPDFUNC) \ -static PyObject * \ -dec_##MPDFUNC(PyObject *self, PyObject *Py_UNUSED(dummy)) \ { \ return MPDFUNC(MPD(self)) ? incr_true() : incr_false(); \ } @@ -4391,19 +4421,9 @@ dec_##MPDFUNC(PyObject *self, PyObject *Py_UNUSED(dummy)) \ 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) \ -static PyObject * \ -dec_##MPDFUNC(PyObject *self, PyObject *args, PyObject *kwds) \ { \ - static char *kwlist[] = {"other", "context", NULL}; \ - PyObject *context = Py_None; \ - PyObject *other; \ PyObject *a, *b; \ PyObject *result; \ - \ - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|O", kwlist, \ - &other, &context)) { \ - return NULL; \ - } \ decimal_state *state = \ get_module_state_by_def(Py_TYPE(self)); \ CONTEXT_CHECK_VA(state, context); \ @@ -4826,13 +4846,98 @@ _decimal_Decimal_fma_impl(PyObject *self, PyObject *other, PyObject *third, Dec_TernaryFuncVA(mpd_qfma) /* Boolean functions, no context arg */ + +/*[clinic input] +_decimal.Decimal.is_canonical + +Return True if the argument is canonical and False otherwise. + +Currently, a Decimal instance is always canonical, so this operation +always returns True. +[clinic start generated code]*/ + +static PyObject * +_decimal_Decimal_is_canonical_impl(PyObject *self) +/*[clinic end generated code: output=b29668684f45443e input=b3b3e6878ccf40b8]*/ Dec_BoolFunc(mpd_iscanonical) + +/*[clinic input] +_decimal.Decimal.is_finite + +Return True if the argument is a finite number, and False otherwise. +[clinic start generated code]*/ + +static PyObject * +_decimal_Decimal_is_finite_impl(PyObject *self) +/*[clinic end generated code: output=537306fbfc9131f8 input=e9b8b5866704bae6]*/ Dec_BoolFunc(mpd_isfinite) + +/*[clinic input] +_decimal.Decimal.is_infinite + +Return True if the argument is infinite, and False otherwise. +[clinic start generated code]*/ + +static PyObject * +_decimal_Decimal_is_infinite_impl(PyObject *self) +/*[clinic end generated code: output=31b775ff28f05ce2 input=8f3937a790ee4ec2]*/ Dec_BoolFunc(mpd_isinfinite) + +/*[clinic input] +_decimal.Decimal.is_nan + +Return True if the argument is a (quiet or signaling) NaN, else False. +[clinic start generated code]*/ + +static PyObject * +_decimal_Decimal_is_nan_impl(PyObject *self) +/*[clinic end generated code: output=b704e8b49a164388 input=795e5dac85976994]*/ Dec_BoolFunc(mpd_isnan) + +/*[clinic input] +_decimal.Decimal.is_qnan + +Return True if the argument is a quiet NaN, and False otherwise. +[clinic start generated code]*/ + +static PyObject * +_decimal_Decimal_is_qnan_impl(PyObject *self) +/*[clinic end generated code: output=85b5241f43798376 input=00485f3c3cfae0af]*/ Dec_BoolFunc(mpd_isqnan) + +/*[clinic input] +_decimal.Decimal.is_snan + +Return True if the argument is a signaling NaN and False otherwise. +[clinic start generated code]*/ + +static PyObject * +_decimal_Decimal_is_snan_impl(PyObject *self) +/*[clinic end generated code: output=50de9ec6507e4a4f input=f3b0f8592c921879]*/ Dec_BoolFunc(mpd_issnan) + +/*[clinic input] +_decimal.Decimal.is_signed + +Return True if the argument has a negative sign and False otherwise. + +Note that both zeros and NaNs can carry signs. +[clinic start generated code]*/ + +static PyObject * +_decimal_Decimal_is_signed_impl(PyObject *self) +/*[clinic end generated code: output=8ec7bc85d8e755e4 input=97c3437ab5dffecc]*/ Dec_BoolFunc(mpd_issigned) + +/*[clinic input] +_decimal.Decimal.is_zero + +Return True if the argument is a zero and False otherwise. +[clinic start generated code]*/ + +static PyObject * +_decimal_Decimal_is_zero_impl(PyObject *self) +/*[clinic end generated code: output=2d87ea1b15879112 input=ae616674cd050a51]*/ Dec_BoolFunc(mpd_iszero) /* Boolean functions, optional context arg */ @@ -5112,7 +5217,57 @@ _decimal_Decimal_to_eng_string_impl(PyObject *self, PyObject *context) } /* Binary functions, optional context arg for conversion errors */ + +/*[clinic input] +_decimal.Decimal.compare_total = _decimal.Decimal.compare + +Compare two operands using their abstract representation. + +Similar to the compare() method, but the result +gives a total ordering on Decimal instances. Two Decimal instances with +the same numeric value but different representations compare unequal +in this ordering: + + >>> Decimal('12.0').compare_total(Decimal('12')) + Decimal('-1') + +Quiet and signaling NaNs are also included in the total ordering. The +result of this function is Decimal('0') if both operands have the same +representation, Decimal('-1') if the first operand is lower in the +total order than the second, and Decimal('1') if the first operand is +higher in the total order than the second operand. See the +specification for details of the total order. + +This operation is unaffected by context and is quiet: no flags are +changed and no rounding is performed. As an exception, the C version +may raise InvalidOperation if the second operand cannot be converted +exactly. +[clinic start generated code]*/ + +static PyObject * +_decimal_Decimal_compare_total_impl(PyObject *self, PyObject *other, + PyObject *context) +/*[clinic end generated code: output=dca119b5e881a83e input=6f3111ec5fdbf3c1]*/ Dec_BinaryFuncVA_NO_CTX(mpd_compare_total) + +/*[clinic input] +_decimal.Decimal.compare_total_mag = _decimal.Decimal.compare + +As compare_total(), but ignores the sign of each operand. + +x.compare_total_mag(y) is equivalent to +x.copy_abs().compare_total(y.copy_abs()). + +This operation is unaffected by context and is quiet: no flags are +changed and no rounding is performed. As an exception, the C version +may raise InvalidOperation if the second operand cannot be converted +exactly. +[clinic start generated code]*/ + +static PyObject * +_decimal_Decimal_compare_total_mag_impl(PyObject *self, PyObject *other, + PyObject *context) +/*[clinic end generated code: output=6bf1b3419112d0dd input=eba17c4c24eb2833]*/ Dec_BinaryFuncVA_NO_CTX(mpd_compare_total_mag) /*[clinic input] @@ -5418,9 +5573,15 @@ dec_richcompare(PyObject *v, PyObject *w, int op) return PyBool_FromLong(r); } -/* __ceil__ */ +/*[clinic input] +_decimal.Decimal.__ceil__ + +Return the ceiling as an Integral. +[clinic start generated code]*/ + static PyObject * -dec_ceil(PyObject *self, PyObject *Py_UNUSED(dummy)) +_decimal_Decimal___ceil___impl(PyObject *self) +/*[clinic end generated code: output=e755a6fb7bceac19 input=4a18ef307ac57da0]*/ { PyObject *context; @@ -5429,9 +5590,15 @@ dec_ceil(PyObject *self, PyObject *Py_UNUSED(dummy)) return dec_as_long(self, context, MPD_ROUND_CEILING); } -/* __complex__ */ +/*[clinic input] +_decimal.Decimal.__complex__ + +Convert this value to exact type complex. +[clinic start generated code]*/ + static PyObject * -dec_complex(PyObject *self, PyObject *Py_UNUSED(dummy)) +_decimal_Decimal___complex___impl(PyObject *self) +/*[clinic end generated code: output=c9b5b4a9fdebc912 input=6b11c6f20af7061a]*/ { PyObject *f; double x; @@ -5450,16 +5617,42 @@ dec_complex(PyObject *self, PyObject *Py_UNUSED(dummy)) return PyComplex_FromDoubles(x, 0); } -/* __copy__ (METH_NOARGS) and __deepcopy__ (METH_O) */ +/*[clinic input] +_decimal.Decimal.__copy__ + +[clinic start generated code]*/ + +static PyObject * +_decimal_Decimal___copy___impl(PyObject *self) +/*[clinic end generated code: output=8eb3656c0250762b input=3dfd30a3e1493c01]*/ +{ + return Py_NewRef(self); +} + +/*[clinic input] +_decimal.Decimal.__deepcopy__ + + memo: object + / + +[clinic start generated code]*/ + static PyObject * -dec_copy(PyObject *self, PyObject *Py_UNUSED(dummy)) +_decimal_Decimal___deepcopy__(PyObject *self, PyObject *memo) +/*[clinic end generated code: output=988fb34e0136b376 input=f95598c6f43233aa]*/ { return Py_NewRef(self); } -/* __floor__ */ +/*[clinic input] +_decimal.Decimal.__floor__ + +Return the floor as an Integral. +[clinic start generated code]*/ + static PyObject * -dec_floor(PyObject *self, PyObject *Py_UNUSED(dummy)) +_decimal_Decimal___floor___impl(PyObject *self) +/*[clinic end generated code: output=56767050ac1a1d5a input=cabcc5618564548b]*/ { PyObject *context; @@ -5595,9 +5788,15 @@ dec_hash(PyObject *op) return self->hash; } -/* __reduce__ */ +/*[clinic input] +_decimal.Decimal.__reduce__ + +Return state information for pickling. +[clinic start generated code]*/ + static PyObject * -dec_reduce(PyObject *self, PyObject *Py_UNUSED(dummy)) +_decimal_Decimal___reduce___impl(PyObject *self) +/*[clinic end generated code: output=84fa6648a496a8d2 input=0345ea951d9b986f]*/ { PyObject *result, *str; @@ -5612,9 +5811,17 @@ dec_reduce(PyObject *self, PyObject *Py_UNUSED(dummy)) return result; } -/* __sizeof__ */ +/*[clinic input] +_decimal.Decimal.__sizeof__ + + self as v: self + +Returns size in memory, in bytes +[clinic start generated code]*/ + static PyObject * -dec_sizeof(PyObject *v, PyObject *Py_UNUSED(dummy)) +_decimal_Decimal___sizeof___impl(PyObject *v) +/*[clinic end generated code: output=f16de05097c62b79 input=a557db538cfddbb7]*/ { size_t res = _PyObject_SIZE(Py_TYPE(v)); if (mpd_isdynamic_data(MPD(v))) { @@ -5623,9 +5830,15 @@ dec_sizeof(PyObject *v, PyObject *Py_UNUSED(dummy)) return PyLong_FromSize_t(res); } -/* __trunc__ */ +/*[clinic input] +_decimal.Decimal.__trunc__ + +Return the Integral closest to x between 0 and x. +[clinic start generated code]*/ + static PyObject * -dec_trunc(PyObject *self, PyObject *Py_UNUSED(dummy)) +_decimal_Decimal___trunc___impl(PyObject *self) +/*[clinic end generated code: output=9ef59578960f80c0 input=a965a61096dcefeb]*/ { PyObject *context; @@ -5693,14 +5906,14 @@ static PyMethodDef dec_methods [] = _DECIMAL_DECIMAL_FMA_METHODDEF /* Boolean functions, no context arg */ - { "is_canonical", dec_mpd_iscanonical, METH_NOARGS, doc_is_canonical }, - { "is_finite", dec_mpd_isfinite, METH_NOARGS, doc_is_finite }, - { "is_infinite", dec_mpd_isinfinite, METH_NOARGS, doc_is_infinite }, - { "is_nan", dec_mpd_isnan, METH_NOARGS, doc_is_nan }, - { "is_qnan", dec_mpd_isqnan, METH_NOARGS, doc_is_qnan }, - { "is_snan", dec_mpd_issnan, METH_NOARGS, doc_is_snan }, - { "is_signed", dec_mpd_issigned, METH_NOARGS, doc_is_signed }, - { "is_zero", dec_mpd_iszero, METH_NOARGS, doc_is_zero }, + _DECIMAL_DECIMAL_IS_CANONICAL_METHODDEF + _DECIMAL_DECIMAL_IS_FINITE_METHODDEF + _DECIMAL_DECIMAL_IS_INFINITE_METHODDEF + _DECIMAL_DECIMAL_IS_NAN_METHODDEF + _DECIMAL_DECIMAL_IS_QNAN_METHODDEF + _DECIMAL_DECIMAL_IS_SNAN_METHODDEF + _DECIMAL_DECIMAL_IS_SIGNED_METHODDEF + _DECIMAL_DECIMAL_IS_ZERO_METHODDEF /* Boolean functions, optional context arg */ _DECIMAL_DECIMAL_IS_NORMAL_METHODDEF @@ -5723,8 +5936,8 @@ static PyMethodDef dec_methods [] = _DECIMAL_DECIMAL_TO_ENG_STRING_METHODDEF /* Binary functions, optional context arg for conversion errors */ - { "compare_total", _PyCFunction_CAST(dec_mpd_compare_total), METH_VARARGS|METH_KEYWORDS, doc_compare_total }, - { "compare_total_mag", _PyCFunction_CAST(dec_mpd_compare_total_mag), METH_VARARGS|METH_KEYWORDS, doc_compare_total_mag }, + _DECIMAL_DECIMAL_COMPARE_TOTAL_METHODDEF + _DECIMAL_DECIMAL_COMPARE_TOTAL_MAG_METHODDEF _DECIMAL_DECIMAL_COPY_SIGN_METHODDEF _DECIMAL_DECIMAL_SAME_QUANTUM_METHODDEF @@ -5743,16 +5956,16 @@ static PyMethodDef dec_methods [] = _DECIMAL_DECIMAL_AS_INTEGER_RATIO_METHODDEF /* Special methods */ - { "__copy__", dec_copy, METH_NOARGS, NULL }, - { "__deepcopy__", dec_copy, METH_O, NULL }, + _DECIMAL_DECIMAL___COPY___METHODDEF + _DECIMAL_DECIMAL___DEEPCOPY___METHODDEF _DECIMAL_DECIMAL___FORMAT___METHODDEF - { "__reduce__", dec_reduce, METH_NOARGS, NULL }, - { "__round__", PyDec_Round, METH_VARARGS, NULL }, - { "__ceil__", dec_ceil, METH_NOARGS, NULL }, - { "__floor__", dec_floor, METH_NOARGS, NULL }, - { "__trunc__", dec_trunc, METH_NOARGS, NULL }, - { "__complex__", dec_complex, METH_NOARGS, NULL }, - { "__sizeof__", dec_sizeof, METH_NOARGS, NULL }, + _DECIMAL_DECIMAL___REDUCE___METHODDEF + _DECIMAL_DECIMAL___ROUND___METHODDEF + _DECIMAL_DECIMAL___CEIL___METHODDEF + _DECIMAL_DECIMAL___FLOOR___METHODDEF + _DECIMAL_DECIMAL___TRUNC___METHODDEF + _DECIMAL_DECIMAL___COMPLEX___METHODDEF + _DECIMAL_DECIMAL___SIZEOF___METHODDEF { NULL, NULL, 1 } }; @@ -5765,7 +5978,7 @@ static PyType_Slot dec_slots[] = { {Py_tp_repr, dec_repr}, {Py_tp_hash, dec_hash}, {Py_tp_str, dec_str}, - {Py_tp_doc, (void *)doc_decimal}, + {Py_tp_doc, (void *)dec_new__doc__}, {Py_tp_richcompare, dec_richcompare}, {Py_tp_methods, dec_methods}, {Py_tp_getset, dec_getsets}, @@ -5932,18 +6145,11 @@ ctx_##MPDFUNC(PyObject *context, PyObject *args) \ /* Ternary context method. */ #define DecCtx_TernaryFunc(MPDFUNC) \ -static PyObject * \ -ctx_##MPDFUNC(PyObject *context, PyObject *args) \ { \ - PyObject *v, *w, *x; \ PyObject *a, *b, *c; \ PyObject *result; \ uint32_t status = 0; \ \ - if (!PyArg_ParseTuple(args, "OOO", &v, &w, &x)) { \ - return NULL; \ - } \ - \ CONVERT_TERNOP_RAISE(&a, &b, &c, v, w, x, context); \ decimal_state *state = get_module_state_from_ctx(context); \ if ((result = dec_alloc(state)) == NULL) { \ @@ -6116,11 +6322,38 @@ _decimal_Context_power_impl(PyObject *context, PyObject *base, PyObject *exp, } /* Ternary arithmetic functions */ + +/*[clinic input] +_decimal.Context.fma + + self as context: self + x as v: object + y as w: object + z as x: object + / + +Return x multiplied by y, plus z. +[clinic start generated code]*/ + +static PyObject * +_decimal_Context_fma_impl(PyObject *context, PyObject *v, PyObject *w, + PyObject *x) +/*[clinic end generated code: output=0664d24f7e4b4aac input=9f3abeaa9a47ea61]*/ DecCtx_TernaryFunc(mpd_qfma) /* No argument */ + +/*[clinic input] +_decimal.Context.radix + + self as context: self + +Return 10. +[clinic start generated code]*/ + static PyObject * -ctx_mpd_radix(PyObject *context, PyObject *dummy) +_decimal_Context_radix_impl(PyObject *context) +/*[clinic end generated code: output=9218fa309e0fcaa1 input=faeaa5b71f838c38]*/ { decimal_state *state = get_module_state_from_ctx(context); return _dec_mpd_radix(state); @@ -6400,12 +6633,12 @@ static PyMethodDef context_methods [] = _DECIMAL_CONTEXT_POWER_METHODDEF /* Ternary arithmetic functions */ - { "fma", ctx_mpd_qfma, METH_VARARGS, doc_ctx_fma }, + _DECIMAL_CONTEXT_FMA_METHODDEF /* No argument */ - { "Etiny", context_getetiny, METH_NOARGS, doc_ctx_Etiny }, - { "Etop", context_getetop, METH_NOARGS, doc_ctx_Etop }, - { "radix", ctx_mpd_radix, METH_NOARGS, doc_ctx_radix }, + _DECIMAL_CONTEXT_ETINY_METHODDEF + _DECIMAL_CONTEXT_ETOP_METHODDEF + _DECIMAL_CONTEXT_RADIX_METHODDEF /* Boolean functions */ { "is_canonical", ctx_iscanonical, METH_O, doc_ctx_is_canonical }, @@ -6932,7 +7165,7 @@ static struct PyModuleDef_Slot _decimal_slots[] = { static struct PyModuleDef _decimal_module = { PyModuleDef_HEAD_INIT, .m_name = "decimal", - .m_doc = doc__decimal, + .m_doc = "C decimal arithmetic module", .m_size = sizeof(decimal_state), .m_methods = _decimal_methods, .m_slots = _decimal_slots, diff --git a/Modules/_decimal/clinic/_decimal.c.h b/Modules/_decimal/clinic/_decimal.c.h index 7541a3ed79549d..ee2d261972020b 100644 --- a/Modules/_decimal/clinic/_decimal.c.h +++ b/Modules/_decimal/clinic/_decimal.c.h @@ -9,6 +9,48 @@ preserve #include "pycore_abstract.h" // _PyNumber_Index() #include "pycore_modsupport.h" // _PyArg_UnpackKeywords() +PyDoc_STRVAR(_decimal_Context_Etiny__doc__, +"Etiny($self, /)\n" +"--\n" +"\n" +"Return a value equal to Emin - prec + 1.\n" +"\n" +"This is the minimum exponent value for subnormal results. When\n" +"underflow occurs, the exponent is set to Etiny."); + +#define _DECIMAL_CONTEXT_ETINY_METHODDEF \ + {"Etiny", (PyCFunction)_decimal_Context_Etiny, METH_NOARGS, _decimal_Context_Etiny__doc__}, + +static PyObject * +_decimal_Context_Etiny_impl(PyObject *self); + +static PyObject * +_decimal_Context_Etiny(PyObject *self, PyObject *Py_UNUSED(ignored)) +{ + return _decimal_Context_Etiny_impl(self); +} + +PyDoc_STRVAR(_decimal_Context_Etop__doc__, +"Etop($self, /)\n" +"--\n" +"\n" +"Return a value equal to Emax - prec + 1.\n" +"\n" +"This is the maximum exponent if the _clamp field of the context is set\n" +"to 1 (IEEE clamp mode). Etop() must not be negative."); + +#define _DECIMAL_CONTEXT_ETOP_METHODDEF \ + {"Etop", (PyCFunction)_decimal_Context_Etop, METH_NOARGS, _decimal_Context_Etop__doc__}, + +static PyObject * +_decimal_Context_Etop_impl(PyObject *self); + +static PyObject * +_decimal_Context_Etop(PyObject *self, PyObject *Py_UNUSED(ignored)) +{ + return _decimal_Context_Etop_impl(self); +} + PyDoc_STRVAR(_decimal_IEEEContext__doc__, "IEEEContext($module, bits, /)\n" "--\n" @@ -269,6 +311,80 @@ _decimal_Decimal_from_number(PyObject *type, PyObject *number) return return_value; } +PyDoc_STRVAR(dec_new__doc__, +"Decimal(value=\'0\', context=None)\n" +"--\n" +"\n" +"Construct a new Decimal object.\n" +"\n" +"value can be an integer, string, tuple, or another Decimal object. If\n" +"no value is given, return Decimal(\'0\'). The context does not affect\n" +"the conversion and is only passed to determine if the InvalidOperation\n" +"trap is active."); + +static PyObject * +dec_new_impl(PyTypeObject *type, PyObject *v, PyObject *context); + +static PyObject * +dec_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 2 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + Py_hash_t ob_hash; + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_hash = -1, + .ob_item = { &_Py_ID(value), &_Py_ID(context), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"value", "context", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "Decimal", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[2]; + PyObject * const *fastargs; + Py_ssize_t nargs = PyTuple_GET_SIZE(args); + Py_ssize_t noptargs = nargs + (kwargs ? PyDict_GET_SIZE(kwargs) : 0) - 0; + PyObject *v = NULL; + PyObject *context = Py_None; + + fastargs = _PyArg_UnpackKeywords(_PyTuple_CAST(args)->ob_item, nargs, kwargs, NULL, &_parser, + /*minpos*/ 0, /*maxpos*/ 2, /*minkw*/ 0, /*varpos*/ 0, argsbuf); + if (!fastargs) { + goto exit; + } + if (!noptargs) { + goto skip_optional_pos; + } + if (fastargs[0]) { + v = fastargs[0]; + if (!--noptargs) { + goto skip_optional_pos; + } + } + context = fastargs[1]; +skip_optional_pos: + return_value = dec_new_impl(type, v, context); + +exit: + return return_value; +} + PyDoc_STRVAR(_decimal_Decimal___format____doc__, "__format__($self, format_spec, override=, /)\n" "--\n" @@ -554,6 +670,69 @@ _decimal_Decimal_to_integral_exact(PyObject *self, PyObject *const *args, Py_ssi return return_value; } +PyDoc_STRVAR(_decimal_Decimal___round____doc__, +"__round__($self, /, ndigits=None)\n" +"--\n" +"\n" +"Return the Integral closest to self, rounding half toward even."); + +#define _DECIMAL_DECIMAL___ROUND___METHODDEF \ + {"__round__", _PyCFunction_CAST(_decimal_Decimal___round__), METH_FASTCALL|METH_KEYWORDS, _decimal_Decimal___round____doc__}, + +static PyObject * +_decimal_Decimal___round___impl(PyObject *dec, PyObject *x); + +static PyObject * +_decimal_Decimal___round__(PyObject *dec, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 1 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + Py_hash_t ob_hash; + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_hash = -1, + .ob_item = { &_Py_ID(ndigits), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"ndigits", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "__round__", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[1]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0; + PyObject *x = NULL; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, + /*minpos*/ 0, /*maxpos*/ 1, /*minkw*/ 0, /*varpos*/ 0, argsbuf); + if (!args) { + goto exit; + } + if (!noptargs) { + goto skip_optional_pos; + } + x = args[0]; +skip_optional_pos: + return_value = _decimal_Decimal___round___impl(dec, x); + +exit: + return return_value; +} + PyDoc_STRVAR(_decimal_Decimal_as_tuple__doc__, "as_tuple($self, /)\n" "--\n" @@ -1655,6 +1834,155 @@ _decimal_Decimal_fma(PyObject *self, PyObject *const *args, Py_ssize_t nargs, Py return return_value; } +PyDoc_STRVAR(_decimal_Decimal_is_canonical__doc__, +"is_canonical($self, /)\n" +"--\n" +"\n" +"Return True if the argument is canonical and False otherwise.\n" +"\n" +"Currently, a Decimal instance is always canonical, so this operation\n" +"always returns True."); + +#define _DECIMAL_DECIMAL_IS_CANONICAL_METHODDEF \ + {"is_canonical", (PyCFunction)_decimal_Decimal_is_canonical, METH_NOARGS, _decimal_Decimal_is_canonical__doc__}, + +static PyObject * +_decimal_Decimal_is_canonical_impl(PyObject *self); + +static PyObject * +_decimal_Decimal_is_canonical(PyObject *self, PyObject *Py_UNUSED(ignored)) +{ + return _decimal_Decimal_is_canonical_impl(self); +} + +PyDoc_STRVAR(_decimal_Decimal_is_finite__doc__, +"is_finite($self, /)\n" +"--\n" +"\n" +"Return True if the argument is a finite number, and False otherwise."); + +#define _DECIMAL_DECIMAL_IS_FINITE_METHODDEF \ + {"is_finite", (PyCFunction)_decimal_Decimal_is_finite, METH_NOARGS, _decimal_Decimal_is_finite__doc__}, + +static PyObject * +_decimal_Decimal_is_finite_impl(PyObject *self); + +static PyObject * +_decimal_Decimal_is_finite(PyObject *self, PyObject *Py_UNUSED(ignored)) +{ + return _decimal_Decimal_is_finite_impl(self); +} + +PyDoc_STRVAR(_decimal_Decimal_is_infinite__doc__, +"is_infinite($self, /)\n" +"--\n" +"\n" +"Return True if the argument is infinite, and False otherwise."); + +#define _DECIMAL_DECIMAL_IS_INFINITE_METHODDEF \ + {"is_infinite", (PyCFunction)_decimal_Decimal_is_infinite, METH_NOARGS, _decimal_Decimal_is_infinite__doc__}, + +static PyObject * +_decimal_Decimal_is_infinite_impl(PyObject *self); + +static PyObject * +_decimal_Decimal_is_infinite(PyObject *self, PyObject *Py_UNUSED(ignored)) +{ + return _decimal_Decimal_is_infinite_impl(self); +} + +PyDoc_STRVAR(_decimal_Decimal_is_nan__doc__, +"is_nan($self, /)\n" +"--\n" +"\n" +"Return True if the argument is a (quiet or signaling) NaN, else False."); + +#define _DECIMAL_DECIMAL_IS_NAN_METHODDEF \ + {"is_nan", (PyCFunction)_decimal_Decimal_is_nan, METH_NOARGS, _decimal_Decimal_is_nan__doc__}, + +static PyObject * +_decimal_Decimal_is_nan_impl(PyObject *self); + +static PyObject * +_decimal_Decimal_is_nan(PyObject *self, PyObject *Py_UNUSED(ignored)) +{ + return _decimal_Decimal_is_nan_impl(self); +} + +PyDoc_STRVAR(_decimal_Decimal_is_qnan__doc__, +"is_qnan($self, /)\n" +"--\n" +"\n" +"Return True if the argument is a quiet NaN, and False otherwise."); + +#define _DECIMAL_DECIMAL_IS_QNAN_METHODDEF \ + {"is_qnan", (PyCFunction)_decimal_Decimal_is_qnan, METH_NOARGS, _decimal_Decimal_is_qnan__doc__}, + +static PyObject * +_decimal_Decimal_is_qnan_impl(PyObject *self); + +static PyObject * +_decimal_Decimal_is_qnan(PyObject *self, PyObject *Py_UNUSED(ignored)) +{ + return _decimal_Decimal_is_qnan_impl(self); +} + +PyDoc_STRVAR(_decimal_Decimal_is_snan__doc__, +"is_snan($self, /)\n" +"--\n" +"\n" +"Return True if the argument is a signaling NaN and False otherwise."); + +#define _DECIMAL_DECIMAL_IS_SNAN_METHODDEF \ + {"is_snan", (PyCFunction)_decimal_Decimal_is_snan, METH_NOARGS, _decimal_Decimal_is_snan__doc__}, + +static PyObject * +_decimal_Decimal_is_snan_impl(PyObject *self); + +static PyObject * +_decimal_Decimal_is_snan(PyObject *self, PyObject *Py_UNUSED(ignored)) +{ + return _decimal_Decimal_is_snan_impl(self); +} + +PyDoc_STRVAR(_decimal_Decimal_is_signed__doc__, +"is_signed($self, /)\n" +"--\n" +"\n" +"Return True if the argument has a negative sign and False otherwise.\n" +"\n" +"Note that both zeros and NaNs can carry signs."); + +#define _DECIMAL_DECIMAL_IS_SIGNED_METHODDEF \ + {"is_signed", (PyCFunction)_decimal_Decimal_is_signed, METH_NOARGS, _decimal_Decimal_is_signed__doc__}, + +static PyObject * +_decimal_Decimal_is_signed_impl(PyObject *self); + +static PyObject * +_decimal_Decimal_is_signed(PyObject *self, PyObject *Py_UNUSED(ignored)) +{ + return _decimal_Decimal_is_signed_impl(self); +} + +PyDoc_STRVAR(_decimal_Decimal_is_zero__doc__, +"is_zero($self, /)\n" +"--\n" +"\n" +"Return True if the argument is a zero and False otherwise."); + +#define _DECIMAL_DECIMAL_IS_ZERO_METHODDEF \ + {"is_zero", (PyCFunction)_decimal_Decimal_is_zero, METH_NOARGS, _decimal_Decimal_is_zero__doc__}, + +static PyObject * +_decimal_Decimal_is_zero_impl(PyObject *self); + +static PyObject * +_decimal_Decimal_is_zero(PyObject *self, PyObject *Py_UNUSED(ignored)) +{ + return _decimal_Decimal_is_zero_impl(self); +} + PyDoc_STRVAR(_decimal_Decimal_is_normal__doc__, "is_normal($self, /, context=None)\n" "--\n" @@ -2187,6 +2515,166 @@ _decimal_Decimal_to_eng_string(PyObject *self, PyObject *const *args, Py_ssize_t return return_value; } +PyDoc_STRVAR(_decimal_Decimal_compare_total__doc__, +"compare_total($self, /, other, context=None)\n" +"--\n" +"\n" +"Compare two operands using their abstract representation.\n" +"\n" +"Similar to the compare() method, but the result\n" +"gives a total ordering on Decimal instances. Two Decimal instances with\n" +"the same numeric value but different representations compare unequal\n" +"in this ordering:\n" +"\n" +" >>> Decimal(\'12.0\').compare_total(Decimal(\'12\'))\n" +" Decimal(\'-1\')\n" +"\n" +"Quiet and signaling NaNs are also included in the total ordering. The\n" +"result of this function is Decimal(\'0\') if both operands have the same\n" +"representation, Decimal(\'-1\') if the first operand is lower in the\n" +"total order than the second, and Decimal(\'1\') if the first operand is\n" +"higher in the total order than the second operand. See the\n" +"specification for details of the total order.\n" +"\n" +"This operation is unaffected by context and is quiet: no flags are\n" +"changed and no rounding is performed. As an exception, the C version\n" +"may raise InvalidOperation if the second operand cannot be converted\n" +"exactly."); + +#define _DECIMAL_DECIMAL_COMPARE_TOTAL_METHODDEF \ + {"compare_total", _PyCFunction_CAST(_decimal_Decimal_compare_total), METH_FASTCALL|METH_KEYWORDS, _decimal_Decimal_compare_total__doc__}, + +static PyObject * +_decimal_Decimal_compare_total_impl(PyObject *self, PyObject *other, + PyObject *context); + +static PyObject * +_decimal_Decimal_compare_total(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 2 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + Py_hash_t ob_hash; + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_hash = -1, + .ob_item = { &_Py_ID(other), &_Py_ID(context), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"other", "context", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "compare_total", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[2]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; + PyObject *other; + PyObject *context = Py_None; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, + /*minpos*/ 1, /*maxpos*/ 2, /*minkw*/ 0, /*varpos*/ 0, argsbuf); + if (!args) { + goto exit; + } + other = args[0]; + if (!noptargs) { + goto skip_optional_pos; + } + context = args[1]; +skip_optional_pos: + return_value = _decimal_Decimal_compare_total_impl(self, other, context); + +exit: + return return_value; +} + +PyDoc_STRVAR(_decimal_Decimal_compare_total_mag__doc__, +"compare_total_mag($self, /, other, context=None)\n" +"--\n" +"\n" +"As compare_total(), but ignores the sign of each operand.\n" +"\n" +"x.compare_total_mag(y) is equivalent to\n" +"x.copy_abs().compare_total(y.copy_abs()).\n" +"\n" +"This operation is unaffected by context and is quiet: no flags are\n" +"changed and no rounding is performed. As an exception, the C version\n" +"may raise InvalidOperation if the second operand cannot be converted\n" +"exactly."); + +#define _DECIMAL_DECIMAL_COMPARE_TOTAL_MAG_METHODDEF \ + {"compare_total_mag", _PyCFunction_CAST(_decimal_Decimal_compare_total_mag), METH_FASTCALL|METH_KEYWORDS, _decimal_Decimal_compare_total_mag__doc__}, + +static PyObject * +_decimal_Decimal_compare_total_mag_impl(PyObject *self, PyObject *other, + PyObject *context); + +static PyObject * +_decimal_Decimal_compare_total_mag(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 2 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + Py_hash_t ob_hash; + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_hash = -1, + .ob_item = { &_Py_ID(other), &_Py_ID(context), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"other", "context", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "compare_total_mag", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[2]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; + PyObject *other; + PyObject *context = Py_None; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, + /*minpos*/ 1, /*maxpos*/ 2, /*minkw*/ 0, /*varpos*/ 0, argsbuf); + if (!args) { + goto exit; + } + other = args[0]; + if (!noptargs) { + goto skip_optional_pos; + } + context = args[1]; +skip_optional_pos: + return_value = _decimal_Decimal_compare_total_mag_impl(self, other, context); + +exit: + return return_value; +} + PyDoc_STRVAR(_decimal_Decimal_copy_sign__doc__, "copy_sign($self, /, other, context=None)\n" "--\n" @@ -2841,6 +3329,139 @@ _decimal_Decimal_quantize(PyObject *self, PyObject *const *args, Py_ssize_t narg return return_value; } +PyDoc_STRVAR(_decimal_Decimal___ceil____doc__, +"__ceil__($self, /)\n" +"--\n" +"\n" +"Return the ceiling as an Integral."); + +#define _DECIMAL_DECIMAL___CEIL___METHODDEF \ + {"__ceil__", (PyCFunction)_decimal_Decimal___ceil__, METH_NOARGS, _decimal_Decimal___ceil____doc__}, + +static PyObject * +_decimal_Decimal___ceil___impl(PyObject *self); + +static PyObject * +_decimal_Decimal___ceil__(PyObject *self, PyObject *Py_UNUSED(ignored)) +{ + return _decimal_Decimal___ceil___impl(self); +} + +PyDoc_STRVAR(_decimal_Decimal___complex____doc__, +"__complex__($self, /)\n" +"--\n" +"\n" +"Convert this value to exact type complex."); + +#define _DECIMAL_DECIMAL___COMPLEX___METHODDEF \ + {"__complex__", (PyCFunction)_decimal_Decimal___complex__, METH_NOARGS, _decimal_Decimal___complex____doc__}, + +static PyObject * +_decimal_Decimal___complex___impl(PyObject *self); + +static PyObject * +_decimal_Decimal___complex__(PyObject *self, PyObject *Py_UNUSED(ignored)) +{ + return _decimal_Decimal___complex___impl(self); +} + +PyDoc_STRVAR(_decimal_Decimal___copy____doc__, +"__copy__($self, /)\n" +"--\n" +"\n"); + +#define _DECIMAL_DECIMAL___COPY___METHODDEF \ + {"__copy__", (PyCFunction)_decimal_Decimal___copy__, METH_NOARGS, _decimal_Decimal___copy____doc__}, + +static PyObject * +_decimal_Decimal___copy___impl(PyObject *self); + +static PyObject * +_decimal_Decimal___copy__(PyObject *self, PyObject *Py_UNUSED(ignored)) +{ + return _decimal_Decimal___copy___impl(self); +} + +PyDoc_STRVAR(_decimal_Decimal___deepcopy____doc__, +"__deepcopy__($self, memo, /)\n" +"--\n" +"\n"); + +#define _DECIMAL_DECIMAL___DEEPCOPY___METHODDEF \ + {"__deepcopy__", (PyCFunction)_decimal_Decimal___deepcopy__, METH_O, _decimal_Decimal___deepcopy____doc__}, + +PyDoc_STRVAR(_decimal_Decimal___floor____doc__, +"__floor__($self, /)\n" +"--\n" +"\n" +"Return the floor as an Integral."); + +#define _DECIMAL_DECIMAL___FLOOR___METHODDEF \ + {"__floor__", (PyCFunction)_decimal_Decimal___floor__, METH_NOARGS, _decimal_Decimal___floor____doc__}, + +static PyObject * +_decimal_Decimal___floor___impl(PyObject *self); + +static PyObject * +_decimal_Decimal___floor__(PyObject *self, PyObject *Py_UNUSED(ignored)) +{ + return _decimal_Decimal___floor___impl(self); +} + +PyDoc_STRVAR(_decimal_Decimal___reduce____doc__, +"__reduce__($self, /)\n" +"--\n" +"\n" +"Return state information for pickling."); + +#define _DECIMAL_DECIMAL___REDUCE___METHODDEF \ + {"__reduce__", (PyCFunction)_decimal_Decimal___reduce__, METH_NOARGS, _decimal_Decimal___reduce____doc__}, + +static PyObject * +_decimal_Decimal___reduce___impl(PyObject *self); + +static PyObject * +_decimal_Decimal___reduce__(PyObject *self, PyObject *Py_UNUSED(ignored)) +{ + return _decimal_Decimal___reduce___impl(self); +} + +PyDoc_STRVAR(_decimal_Decimal___sizeof____doc__, +"__sizeof__($self, /)\n" +"--\n" +"\n" +"Returns size in memory, in bytes"); + +#define _DECIMAL_DECIMAL___SIZEOF___METHODDEF \ + {"__sizeof__", (PyCFunction)_decimal_Decimal___sizeof__, METH_NOARGS, _decimal_Decimal___sizeof____doc__}, + +static PyObject * +_decimal_Decimal___sizeof___impl(PyObject *v); + +static PyObject * +_decimal_Decimal___sizeof__(PyObject *v, PyObject *Py_UNUSED(ignored)) +{ + return _decimal_Decimal___sizeof___impl(v); +} + +PyDoc_STRVAR(_decimal_Decimal___trunc____doc__, +"__trunc__($self, /)\n" +"--\n" +"\n" +"Return the Integral closest to x between 0 and x."); + +#define _DECIMAL_DECIMAL___TRUNC___METHODDEF \ + {"__trunc__", (PyCFunction)_decimal_Decimal___trunc__, METH_NOARGS, _decimal_Decimal___trunc____doc__}, + +static PyObject * +_decimal_Decimal___trunc___impl(PyObject *self); + +static PyObject * +_decimal_Decimal___trunc__(PyObject *self, PyObject *Py_UNUSED(ignored)) +{ + return _decimal_Decimal___trunc___impl(self); +} + PyDoc_STRVAR(_decimal_Context_power__doc__, "power($self, /, a, b, modulo=None)\n" "--\n" @@ -2922,4 +3543,55 @@ _decimal_Context_power(PyObject *context, PyObject *const *args, Py_ssize_t narg exit: return return_value; } -/*[clinic end generated code: output=9bbde3e723166dd3 input=a9049054013a1b77]*/ + +PyDoc_STRVAR(_decimal_Context_fma__doc__, +"fma($self, x, y, z, /)\n" +"--\n" +"\n" +"Return x multiplied by y, plus z."); + +#define _DECIMAL_CONTEXT_FMA_METHODDEF \ + {"fma", _PyCFunction_CAST(_decimal_Context_fma), METH_FASTCALL, _decimal_Context_fma__doc__}, + +static PyObject * +_decimal_Context_fma_impl(PyObject *context, PyObject *v, PyObject *w, + PyObject *x); + +static PyObject * +_decimal_Context_fma(PyObject *context, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + PyObject *v; + PyObject *w; + PyObject *x; + + if (!_PyArg_CheckPositional("fma", nargs, 3, 3)) { + goto exit; + } + v = args[0]; + w = args[1]; + x = args[2]; + return_value = _decimal_Context_fma_impl(context, v, w, x); + +exit: + return return_value; +} + +PyDoc_STRVAR(_decimal_Context_radix__doc__, +"radix($self, /)\n" +"--\n" +"\n" +"Return 10."); + +#define _DECIMAL_CONTEXT_RADIX_METHODDEF \ + {"radix", (PyCFunction)_decimal_Context_radix, METH_NOARGS, _decimal_Context_radix__doc__}, + +static PyObject * +_decimal_Context_radix_impl(PyObject *context); + +static PyObject * +_decimal_Context_radix(PyObject *context, PyObject *Py_UNUSED(ignored)) +{ + return _decimal_Context_radix_impl(context); +} +/*[clinic end generated code: output=63e062762bcfe6e6 input=a9049054013a1b77]*/ diff --git a/Modules/_decimal/docstrings.h b/Modules/_decimal/docstrings.h index 3ebac0a9b1e80a..9a65403c72ea6c 100644 --- a/Modules/_decimal/docstrings.h +++ b/Modules/_decimal/docstrings.h @@ -10,108 +10,6 @@ #include "pymacro.h" - -/******************************************************************************/ -/* Module */ -/******************************************************************************/ - - -PyDoc_STRVAR(doc__decimal, -"C decimal arithmetic module"); - -/******************************************************************************/ -/* Decimal Object and Methods */ -/******************************************************************************/ - -PyDoc_STRVAR(doc_decimal, -"Decimal(value=\"0\", context=None)\n--\n\n\ -Construct a new Decimal object. 'value' can be an integer, string, tuple,\n\ -or another Decimal object. If no value is given, return Decimal('0'). The\n\ -context does not affect the conversion and is only passed to determine if\n\ -the InvalidOperation trap is active.\n\ -\n"); - -PyDoc_STRVAR(doc_compare_total, -"compare_total($self, /, other, context=None)\n--\n\n\ -Compare two operands using their abstract representation rather than\n\ -their numerical value. Similar to the compare() method, but the result\n\ -gives a total ordering on Decimal instances. Two Decimal instances with\n\ -the same numeric value but different representations compare unequal\n\ -in this ordering:\n\ -\n\ - >>> Decimal('12.0').compare_total(Decimal('12'))\n\ - Decimal('-1')\n\ -\n\ -Quiet and signaling NaNs are also included in the total ordering. The result\n\ -of this function is Decimal('0') if both operands have the same representation,\n\ -Decimal('-1') if the first operand is lower in the total order than the second,\n\ -and Decimal('1') if the first operand is higher in the total order than the\n\ -second operand. See the specification for details of the total order.\n\ -\n\ -This operation is unaffected by context and is quiet: no flags are changed\n\ -and no rounding is performed. As an exception, the C version may raise\n\ -InvalidOperation if the second operand cannot be converted exactly.\n\ -\n"); - -PyDoc_STRVAR(doc_compare_total_mag, -"compare_total_mag($self, /, other, context=None)\n--\n\n\ -Compare two operands using their abstract representation rather than their\n\ -value as in compare_total(), but ignoring the sign of each operand.\n\ -\n\ -x.compare_total_mag(y) is equivalent to x.copy_abs().compare_total(y.copy_abs()).\n\ -\n\ -This operation is unaffected by context and is quiet: no flags are changed\n\ -and no rounding is performed. As an exception, the C version may raise\n\ -InvalidOperation if the second operand cannot be converted exactly.\n\ -\n"); - -PyDoc_STRVAR(doc_is_canonical, -"is_canonical($self, /)\n--\n\n\ -Return True if the argument is canonical and False otherwise. Currently,\n\ -a Decimal instance is always canonical, so this operation always returns\n\ -True.\n\ -\n"); - -PyDoc_STRVAR(doc_is_finite, -"is_finite($self, /)\n--\n\n\ -Return True if the argument is a finite number, and False if the argument\n\ -is infinite or a NaN.\n\ -\n"); - -PyDoc_STRVAR(doc_is_infinite, -"is_infinite($self, /)\n--\n\n\ -Return True if the argument is either positive or negative infinity and\n\ -False otherwise.\n\ -\n"); - -PyDoc_STRVAR(doc_is_nan, -"is_nan($self, /)\n--\n\n\ -Return True if the argument is a (quiet or signaling) NaN and False\n\ -otherwise.\n\ -\n"); - -PyDoc_STRVAR(doc_is_qnan, -"is_qnan($self, /)\n--\n\n\ -Return True if the argument is a quiet NaN, and False otherwise.\n\ -\n"); - -PyDoc_STRVAR(doc_is_signed, -"is_signed($self, /)\n--\n\n\ -Return True if the argument has a negative sign and False otherwise.\n\ -Note that both zeros and NaNs can carry signs.\n\ -\n"); - -PyDoc_STRVAR(doc_is_snan, -"is_snan($self, /)\n--\n\n\ -Return True if the argument is a signaling NaN and False otherwise.\n\ -\n"); - -PyDoc_STRVAR(doc_is_zero, -"is_zero($self, /)\n--\n\n\ -Return True if the argument is a (positive or negative) zero and False\n\ -otherwise.\n\ -\n"); - /******************************************************************************/ /* Context Object and Methods */ /******************************************************************************/ @@ -169,19 +67,6 @@ Create a new Decimal instance from float f. Unlike the Decimal.from_float()\n\ class method, this function observes the context limits.\n\ \n"); -PyDoc_STRVAR(doc_ctx_Etiny, -"Etiny($self, /)\n--\n\n\ -Return a value equal to Emin - prec + 1, which is the minimum exponent value\n\ -for subnormal results. When underflow occurs, the exponent is set to Etiny.\n\ -\n"); - -PyDoc_STRVAR(doc_ctx_Etop, -"Etop($self, /)\n--\n\n\ -Return a value equal to Emax - prec + 1. This is the maximum exponent\n\ -if the _clamp field of the context is set to 1 (IEEE clamp mode). Etop()\n\ -must not be negative.\n\ -\n"); - PyDoc_STRVAR(doc_ctx_abs, "abs($self, x, /)\n--\n\n\ Return the absolute value of x.\n\ @@ -252,11 +137,6 @@ PyDoc_STRVAR(doc_ctx_exp, Return e ** x.\n\ \n"); -PyDoc_STRVAR(doc_ctx_fma, -"fma($self, x, y, z, /)\n--\n\n\ -Return x multiplied by y, plus z.\n\ -\n"); - PyDoc_STRVAR(doc_ctx_is_canonical, "is_canonical($self, x, /)\n--\n\n\ Return True if x is canonical, False otherwise.\n\ @@ -409,11 +289,6 @@ PyDoc_STRVAR(doc_ctx_quantize, Return a value equal to x (rounded), having the exponent of y.\n\ \n"); -PyDoc_STRVAR(doc_ctx_radix, -"radix($self, /)\n--\n\n\ -Return 10.\n\ -\n"); - PyDoc_STRVAR(doc_ctx_remainder, "remainder($self, x, y, /)\n--\n\n\ Return the remainder from integer division. The sign of the result,\n\ From 8bb963fc458fc30ebaafb16750a0876eb2f30f4e Mon Sep 17 00:00:00 2001 From: Sergey B Kirpichev Date: Tue, 19 Aug 2025 11:43:15 +0300 Subject: [PATCH 2/4] + rename parameters --- Modules/_decimal/_decimal.c | 41 ++++++++++++++-------------- Modules/_decimal/clinic/_decimal.c.h | 36 ++++++++++++------------ 2 files changed, 38 insertions(+), 39 deletions(-) diff --git a/Modules/_decimal/_decimal.c b/Modules/_decimal/_decimal.c index e9ded43b039be3..77d46eb38a5f1c 100644 --- a/Modules/_decimal/_decimal.c +++ b/Modules/_decimal/_decimal.c @@ -3173,7 +3173,7 @@ PyDec_FromObject(PyObject *v, PyObject *context) @classmethod _decimal.Decimal.__new__ as dec_new - value as v: object(c_default="NULL") = "0" + value: object(c_default="NULL") = "0" context: object = None Construct a new Decimal object. @@ -3185,13 +3185,13 @@ trap is active. [clinic start generated code]*/ static PyObject * -dec_new_impl(PyTypeObject *type, PyObject *v, PyObject *context) -/*[clinic end generated code: output=5371cbce41508fe7 input=6353a3563bea247b]*/ +dec_new_impl(PyTypeObject *type, PyObject *value, PyObject *context) +/*[clinic end generated code: output=35f48a40c65625ba input=5f8a0892d3fcef80]*/ { decimal_state *state = get_module_state_by_def(type); CONTEXT_CHECK_VA(state, context); - return PyDecType_FromObjectExact(type, v, context); + return PyDecType_FromObjectExact(type, value, context); } static PyObject * @@ -4136,33 +4136,32 @@ PyDec_AsFloat(PyObject *dec) /*[clinic input] _decimal.Decimal.__round__ - self as dec: self - ndigits as x: object(c_default="NULL") = None + ndigits: object(c_default="NULL") = None Return the Integral closest to self, rounding half toward even. [clinic start generated code]*/ static PyObject * -_decimal_Decimal___round___impl(PyObject *dec, PyObject *x) -/*[clinic end generated code: output=5089b98ed18bb5e3 input=a3986615e1ad5b2a]*/ +_decimal_Decimal___round___impl(PyObject *self, PyObject *ndigits) +/*[clinic end generated code: output=ca6b3570a8df0c91 input=9327698ac2d9cc48]*/ { PyObject *result; uint32_t status = 0; PyObject *context; - decimal_state *state = get_module_state_by_def(Py_TYPE(dec)); + decimal_state *state = get_module_state_by_def(Py_TYPE(self)); CURRENT_CONTEXT(state, context); - if (x) { + if (ndigits) { mpd_uint_t dq[1] = {1}; mpd_t q = {MPD_STATIC|MPD_CONST_DATA,0,1,1,1,dq}; mpd_ssize_t y; - if (!PyLong_Check(x)) { + if (!PyLong_Check(ndigits)) { PyErr_SetString(PyExc_TypeError, "optional arg must be an integer"); return NULL; } - y = PyLong_AsSsize_t(x); + y = PyLong_AsSsize_t(ndigits); if (y == -1 && PyErr_Occurred()) { return NULL; } @@ -4172,7 +4171,7 @@ _decimal_Decimal___round___impl(PyObject *dec, PyObject *x) } q.exp = (y == MPD_SSIZE_MIN) ? MPD_SSIZE_MAX : -y; - mpd_qquantize(MPD(result), MPD(dec), &q, CTX(context), &status); + mpd_qquantize(MPD(result), MPD(self), &q, CTX(context), &status); if (dec_addstatus(context, status)) { Py_DECREF(result); return NULL; @@ -4181,7 +4180,7 @@ _decimal_Decimal___round___impl(PyObject *dec, PyObject *x) return result; } else { - return dec_as_long(dec, context, MPD_ROUND_HALF_EVEN); + return dec_as_long(self, context, MPD_ROUND_HALF_EVEN); } } @@ -6150,7 +6149,7 @@ ctx_##MPDFUNC(PyObject *context, PyObject *args) \ PyObject *result; \ uint32_t status = 0; \ \ - CONVERT_TERNOP_RAISE(&a, &b, &c, v, w, x, context); \ + CONVERT_TERNOP_RAISE(&a, &b, &c, x, y, z, context); \ decimal_state *state = get_module_state_from_ctx(context); \ if ((result = dec_alloc(state)) == NULL) { \ Py_DECREF(a); \ @@ -6327,18 +6326,18 @@ _decimal_Context_power_impl(PyObject *context, PyObject *base, PyObject *exp, _decimal.Context.fma self as context: self - x as v: object - y as w: object - z as x: object + x: object + y: object + z: object / Return x multiplied by y, plus z. [clinic start generated code]*/ static PyObject * -_decimal_Context_fma_impl(PyObject *context, PyObject *v, PyObject *w, - PyObject *x) -/*[clinic end generated code: output=0664d24f7e4b4aac input=9f3abeaa9a47ea61]*/ +_decimal_Context_fma_impl(PyObject *context, PyObject *x, PyObject *y, + PyObject *z) +/*[clinic end generated code: output=2d6174716faaf4e1 input=80479612da3333d1]*/ DecCtx_TernaryFunc(mpd_qfma) /* No argument */ diff --git a/Modules/_decimal/clinic/_decimal.c.h b/Modules/_decimal/clinic/_decimal.c.h index ee2d261972020b..079cede8bbb9b8 100644 --- a/Modules/_decimal/clinic/_decimal.c.h +++ b/Modules/_decimal/clinic/_decimal.c.h @@ -323,7 +323,7 @@ PyDoc_STRVAR(dec_new__doc__, "trap is active."); static PyObject * -dec_new_impl(PyTypeObject *type, PyObject *v, PyObject *context); +dec_new_impl(PyTypeObject *type, PyObject *value, PyObject *context); static PyObject * dec_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) @@ -360,7 +360,7 @@ dec_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) PyObject * const *fastargs; Py_ssize_t nargs = PyTuple_GET_SIZE(args); Py_ssize_t noptargs = nargs + (kwargs ? PyDict_GET_SIZE(kwargs) : 0) - 0; - PyObject *v = NULL; + PyObject *value = NULL; PyObject *context = Py_None; fastargs = _PyArg_UnpackKeywords(_PyTuple_CAST(args)->ob_item, nargs, kwargs, NULL, &_parser, @@ -372,14 +372,14 @@ dec_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) goto skip_optional_pos; } if (fastargs[0]) { - v = fastargs[0]; + value = fastargs[0]; if (!--noptargs) { goto skip_optional_pos; } } context = fastargs[1]; skip_optional_pos: - return_value = dec_new_impl(type, v, context); + return_value = dec_new_impl(type, value, context); exit: return return_value; @@ -680,10 +680,10 @@ PyDoc_STRVAR(_decimal_Decimal___round____doc__, {"__round__", _PyCFunction_CAST(_decimal_Decimal___round__), METH_FASTCALL|METH_KEYWORDS, _decimal_Decimal___round____doc__}, static PyObject * -_decimal_Decimal___round___impl(PyObject *dec, PyObject *x); +_decimal_Decimal___round___impl(PyObject *self, PyObject *ndigits); static PyObject * -_decimal_Decimal___round__(PyObject *dec, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +_decimal_Decimal___round__(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) @@ -715,7 +715,7 @@ _decimal_Decimal___round__(PyObject *dec, PyObject *const *args, Py_ssize_t narg #undef KWTUPLE PyObject *argsbuf[1]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0; - PyObject *x = NULL; + PyObject *ndigits = NULL; args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, /*minpos*/ 0, /*maxpos*/ 1, /*minkw*/ 0, /*varpos*/ 0, argsbuf); @@ -725,9 +725,9 @@ _decimal_Decimal___round__(PyObject *dec, PyObject *const *args, Py_ssize_t narg if (!noptargs) { goto skip_optional_pos; } - x = args[0]; + ndigits = args[0]; skip_optional_pos: - return_value = _decimal_Decimal___round___impl(dec, x); + return_value = _decimal_Decimal___round___impl(self, ndigits); exit: return return_value; @@ -3554,24 +3554,24 @@ PyDoc_STRVAR(_decimal_Context_fma__doc__, {"fma", _PyCFunction_CAST(_decimal_Context_fma), METH_FASTCALL, _decimal_Context_fma__doc__}, static PyObject * -_decimal_Context_fma_impl(PyObject *context, PyObject *v, PyObject *w, - PyObject *x); +_decimal_Context_fma_impl(PyObject *context, PyObject *x, PyObject *y, + PyObject *z); static PyObject * _decimal_Context_fma(PyObject *context, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; - PyObject *v; - PyObject *w; PyObject *x; + PyObject *y; + PyObject *z; if (!_PyArg_CheckPositional("fma", nargs, 3, 3)) { goto exit; } - v = args[0]; - w = args[1]; - x = args[2]; - return_value = _decimal_Context_fma_impl(context, v, w, x); + x = args[0]; + y = args[1]; + z = args[2]; + return_value = _decimal_Context_fma_impl(context, x, y, z); exit: return return_value; @@ -3594,4 +3594,4 @@ _decimal_Context_radix(PyObject *context, PyObject *Py_UNUSED(ignored)) { return _decimal_Context_radix_impl(context); } -/*[clinic end generated code: output=63e062762bcfe6e6 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=4d6ae05a07c26d90 input=a9049054013a1b77]*/ From b778703b7579492a4f4cff7318adb3e625d60c87 Mon Sep 17 00:00:00 2001 From: Sergey B Kirpichev Date: Tue, 19 Aug 2025 12:42:39 +0300 Subject: [PATCH 3/4] Update Modules/_decimal/_decimal.c Co-authored-by: Serhiy Storchaka --- Modules/_decimal/_decimal.c | 5 +-- Modules/_decimal/clinic/_decimal.c.h | 47 +++++----------------------- 2 files changed, 11 insertions(+), 41 deletions(-) diff --git a/Modules/_decimal/_decimal.c b/Modules/_decimal/_decimal.c index 77d46eb38a5f1c..54c06e6b26f78f 100644 --- a/Modules/_decimal/_decimal.c +++ b/Modules/_decimal/_decimal.c @@ -4136,14 +4136,15 @@ PyDec_AsFloat(PyObject *dec) /*[clinic input] _decimal.Decimal.__round__ - ndigits: object(c_default="NULL") = None + ndigits: object = NULL + / Return the Integral closest to self, rounding half toward even. [clinic start generated code]*/ static PyObject * _decimal_Decimal___round___impl(PyObject *self, PyObject *ndigits) -/*[clinic end generated code: output=ca6b3570a8df0c91 input=9327698ac2d9cc48]*/ +/*[clinic end generated code: output=ca6b3570a8df0c91 input=dc72084114f59380]*/ { PyObject *result; uint32_t status = 0; diff --git a/Modules/_decimal/clinic/_decimal.c.h b/Modules/_decimal/clinic/_decimal.c.h index 079cede8bbb9b8..df42463d82c869 100644 --- a/Modules/_decimal/clinic/_decimal.c.h +++ b/Modules/_decimal/clinic/_decimal.c.h @@ -671,62 +671,31 @@ _decimal_Decimal_to_integral_exact(PyObject *self, PyObject *const *args, Py_ssi } PyDoc_STRVAR(_decimal_Decimal___round____doc__, -"__round__($self, /, ndigits=None)\n" +"__round__($self, ndigits=, /)\n" "--\n" "\n" "Return the Integral closest to self, rounding half toward even."); #define _DECIMAL_DECIMAL___ROUND___METHODDEF \ - {"__round__", _PyCFunction_CAST(_decimal_Decimal___round__), METH_FASTCALL|METH_KEYWORDS, _decimal_Decimal___round____doc__}, + {"__round__", _PyCFunction_CAST(_decimal_Decimal___round__), METH_FASTCALL, _decimal_Decimal___round____doc__}, static PyObject * _decimal_Decimal___round___impl(PyObject *self, PyObject *ndigits); static PyObject * -_decimal_Decimal___round__(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +_decimal_Decimal___round__(PyObject *self, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 1 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - Py_hash_t ob_hash; - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_hash = -1, - .ob_item = { &_Py_ID(ndigits), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"ndigits", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "__round__", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[1]; - Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0; PyObject *ndigits = NULL; - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, - /*minpos*/ 0, /*maxpos*/ 1, /*minkw*/ 0, /*varpos*/ 0, argsbuf); - if (!args) { + if (!_PyArg_CheckPositional("__round__", nargs, 0, 1)) { goto exit; } - if (!noptargs) { - goto skip_optional_pos; + if (nargs < 1) { + goto skip_optional; } ndigits = args[0]; -skip_optional_pos: +skip_optional: return_value = _decimal_Decimal___round___impl(self, ndigits); exit: @@ -3594,4 +3563,4 @@ _decimal_Context_radix(PyObject *context, PyObject *Py_UNUSED(ignored)) { return _decimal_Context_radix_impl(context); } -/*[clinic end generated code: output=4d6ae05a07c26d90 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=9bc7d4c6f86a2a54 input=a9049054013a1b77]*/ From aa2918657ba240103842212e072b4cab70021c69 Mon Sep 17 00:00:00 2001 From: Sergey B Kirpichev Date: Wed, 20 Aug 2025 12:26:39 +0300 Subject: [PATCH 4/4] address review: revert macro changes --- Modules/_decimal/_decimal.c | 195 +++------------ Modules/_decimal/clinic/_decimal.c.h | 344 +-------------------------- Modules/_decimal/docstrings.h | 86 +++++++ 3 files changed, 118 insertions(+), 507 deletions(-) diff --git a/Modules/_decimal/_decimal.c b/Modules/_decimal/_decimal.c index 54c06e6b26f78f..806a3192e2dc96 100644 --- a/Modules/_decimal/_decimal.c +++ b/Modules/_decimal/_decimal.c @@ -4348,6 +4348,8 @@ nm_##MPDFUNC(PyObject *self, PyObject *other) \ /* Boolean function without a context arg. */ #define Dec_BoolFunc(MPDFUNC) \ +static PyObject * \ +dec_##MPDFUNC(PyObject *self, PyObject *Py_UNUSED(dummy)) \ { \ return MPDFUNC(MPD(self)) ? incr_true() : incr_false(); \ } @@ -4421,9 +4423,19 @@ nm_##MPDFUNC(PyObject *self, PyObject *other) \ 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) \ +static PyObject * \ +dec_##MPDFUNC(PyObject *self, PyObject *args, PyObject *kwds) \ { \ + static char *kwlist[] = {"other", "context", NULL}; \ + PyObject *context = Py_None; \ + PyObject *other; \ PyObject *a, *b; \ PyObject *result; \ + \ + if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|O", kwlist, \ + &other, &context)) { \ + return NULL; \ + } \ decimal_state *state = \ get_module_state_by_def(Py_TYPE(self)); \ CONTEXT_CHECK_VA(state, context); \ @@ -4846,98 +4858,13 @@ _decimal_Decimal_fma_impl(PyObject *self, PyObject *other, PyObject *third, Dec_TernaryFuncVA(mpd_qfma) /* Boolean functions, no context arg */ - -/*[clinic input] -_decimal.Decimal.is_canonical - -Return True if the argument is canonical and False otherwise. - -Currently, a Decimal instance is always canonical, so this operation -always returns True. -[clinic start generated code]*/ - -static PyObject * -_decimal_Decimal_is_canonical_impl(PyObject *self) -/*[clinic end generated code: output=b29668684f45443e input=b3b3e6878ccf40b8]*/ Dec_BoolFunc(mpd_iscanonical) - -/*[clinic input] -_decimal.Decimal.is_finite - -Return True if the argument is a finite number, and False otherwise. -[clinic start generated code]*/ - -static PyObject * -_decimal_Decimal_is_finite_impl(PyObject *self) -/*[clinic end generated code: output=537306fbfc9131f8 input=e9b8b5866704bae6]*/ Dec_BoolFunc(mpd_isfinite) - -/*[clinic input] -_decimal.Decimal.is_infinite - -Return True if the argument is infinite, and False otherwise. -[clinic start generated code]*/ - -static PyObject * -_decimal_Decimal_is_infinite_impl(PyObject *self) -/*[clinic end generated code: output=31b775ff28f05ce2 input=8f3937a790ee4ec2]*/ Dec_BoolFunc(mpd_isinfinite) - -/*[clinic input] -_decimal.Decimal.is_nan - -Return True if the argument is a (quiet or signaling) NaN, else False. -[clinic start generated code]*/ - -static PyObject * -_decimal_Decimal_is_nan_impl(PyObject *self) -/*[clinic end generated code: output=b704e8b49a164388 input=795e5dac85976994]*/ Dec_BoolFunc(mpd_isnan) - -/*[clinic input] -_decimal.Decimal.is_qnan - -Return True if the argument is a quiet NaN, and False otherwise. -[clinic start generated code]*/ - -static PyObject * -_decimal_Decimal_is_qnan_impl(PyObject *self) -/*[clinic end generated code: output=85b5241f43798376 input=00485f3c3cfae0af]*/ Dec_BoolFunc(mpd_isqnan) - -/*[clinic input] -_decimal.Decimal.is_snan - -Return True if the argument is a signaling NaN and False otherwise. -[clinic start generated code]*/ - -static PyObject * -_decimal_Decimal_is_snan_impl(PyObject *self) -/*[clinic end generated code: output=50de9ec6507e4a4f input=f3b0f8592c921879]*/ Dec_BoolFunc(mpd_issnan) - -/*[clinic input] -_decimal.Decimal.is_signed - -Return True if the argument has a negative sign and False otherwise. - -Note that both zeros and NaNs can carry signs. -[clinic start generated code]*/ - -static PyObject * -_decimal_Decimal_is_signed_impl(PyObject *self) -/*[clinic end generated code: output=8ec7bc85d8e755e4 input=97c3437ab5dffecc]*/ Dec_BoolFunc(mpd_issigned) - -/*[clinic input] -_decimal.Decimal.is_zero - -Return True if the argument is a zero and False otherwise. -[clinic start generated code]*/ - -static PyObject * -_decimal_Decimal_is_zero_impl(PyObject *self) -/*[clinic end generated code: output=2d87ea1b15879112 input=ae616674cd050a51]*/ Dec_BoolFunc(mpd_iszero) /* Boolean functions, optional context arg */ @@ -5217,57 +5144,7 @@ _decimal_Decimal_to_eng_string_impl(PyObject *self, PyObject *context) } /* Binary functions, optional context arg for conversion errors */ - -/*[clinic input] -_decimal.Decimal.compare_total = _decimal.Decimal.compare - -Compare two operands using their abstract representation. - -Similar to the compare() method, but the result -gives a total ordering on Decimal instances. Two Decimal instances with -the same numeric value but different representations compare unequal -in this ordering: - - >>> Decimal('12.0').compare_total(Decimal('12')) - Decimal('-1') - -Quiet and signaling NaNs are also included in the total ordering. The -result of this function is Decimal('0') if both operands have the same -representation, Decimal('-1') if the first operand is lower in the -total order than the second, and Decimal('1') if the first operand is -higher in the total order than the second operand. See the -specification for details of the total order. - -This operation is unaffected by context and is quiet: no flags are -changed and no rounding is performed. As an exception, the C version -may raise InvalidOperation if the second operand cannot be converted -exactly. -[clinic start generated code]*/ - -static PyObject * -_decimal_Decimal_compare_total_impl(PyObject *self, PyObject *other, - PyObject *context) -/*[clinic end generated code: output=dca119b5e881a83e input=6f3111ec5fdbf3c1]*/ Dec_BinaryFuncVA_NO_CTX(mpd_compare_total) - -/*[clinic input] -_decimal.Decimal.compare_total_mag = _decimal.Decimal.compare - -As compare_total(), but ignores the sign of each operand. - -x.compare_total_mag(y) is equivalent to -x.copy_abs().compare_total(y.copy_abs()). - -This operation is unaffected by context and is quiet: no flags are -changed and no rounding is performed. As an exception, the C version -may raise InvalidOperation if the second operand cannot be converted -exactly. -[clinic start generated code]*/ - -static PyObject * -_decimal_Decimal_compare_total_mag_impl(PyObject *self, PyObject *other, - PyObject *context) -/*[clinic end generated code: output=6bf1b3419112d0dd input=eba17c4c24eb2833]*/ Dec_BinaryFuncVA_NO_CTX(mpd_compare_total_mag) /*[clinic input] @@ -5906,14 +5783,14 @@ static PyMethodDef dec_methods [] = _DECIMAL_DECIMAL_FMA_METHODDEF /* Boolean functions, no context arg */ - _DECIMAL_DECIMAL_IS_CANONICAL_METHODDEF - _DECIMAL_DECIMAL_IS_FINITE_METHODDEF - _DECIMAL_DECIMAL_IS_INFINITE_METHODDEF - _DECIMAL_DECIMAL_IS_NAN_METHODDEF - _DECIMAL_DECIMAL_IS_QNAN_METHODDEF - _DECIMAL_DECIMAL_IS_SNAN_METHODDEF - _DECIMAL_DECIMAL_IS_SIGNED_METHODDEF - _DECIMAL_DECIMAL_IS_ZERO_METHODDEF + { "is_canonical", dec_mpd_iscanonical, METH_NOARGS, doc_is_canonical }, + { "is_finite", dec_mpd_isfinite, METH_NOARGS, doc_is_finite }, + { "is_infinite", dec_mpd_isinfinite, METH_NOARGS, doc_is_infinite }, + { "is_nan", dec_mpd_isnan, METH_NOARGS, doc_is_nan }, + { "is_qnan", dec_mpd_isqnan, METH_NOARGS, doc_is_qnan }, + { "is_snan", dec_mpd_issnan, METH_NOARGS, doc_is_snan }, + { "is_signed", dec_mpd_issigned, METH_NOARGS, doc_is_signed }, + { "is_zero", dec_mpd_iszero, METH_NOARGS, doc_is_zero }, /* Boolean functions, optional context arg */ _DECIMAL_DECIMAL_IS_NORMAL_METHODDEF @@ -5936,8 +5813,8 @@ static PyMethodDef dec_methods [] = _DECIMAL_DECIMAL_TO_ENG_STRING_METHODDEF /* Binary functions, optional context arg for conversion errors */ - _DECIMAL_DECIMAL_COMPARE_TOTAL_METHODDEF - _DECIMAL_DECIMAL_COMPARE_TOTAL_MAG_METHODDEF + { "compare_total", _PyCFunction_CAST(dec_mpd_compare_total), METH_VARARGS|METH_KEYWORDS, doc_compare_total }, + { "compare_total_mag", _PyCFunction_CAST(dec_mpd_compare_total_mag), METH_VARARGS|METH_KEYWORDS, doc_compare_total_mag }, _DECIMAL_DECIMAL_COPY_SIGN_METHODDEF _DECIMAL_DECIMAL_SAME_QUANTUM_METHODDEF @@ -6145,12 +6022,19 @@ ctx_##MPDFUNC(PyObject *context, PyObject *args) \ /* Ternary context method. */ #define DecCtx_TernaryFunc(MPDFUNC) \ +static PyObject * \ +ctx_##MPDFUNC(PyObject *context, PyObject *args) \ { \ + PyObject *v, *w, *x; \ PyObject *a, *b, *c; \ PyObject *result; \ uint32_t status = 0; \ \ - CONVERT_TERNOP_RAISE(&a, &b, &c, x, y, z, context); \ + if (!PyArg_ParseTuple(args, "OOO", &v, &w, &x)) { \ + return NULL; \ + } \ + \ + CONVERT_TERNOP_RAISE(&a, &b, &c, v, w, x, context); \ decimal_state *state = get_module_state_from_ctx(context); \ if ((result = dec_alloc(state)) == NULL) { \ Py_DECREF(a); \ @@ -6322,23 +6206,6 @@ _decimal_Context_power_impl(PyObject *context, PyObject *base, PyObject *exp, } /* Ternary arithmetic functions */ - -/*[clinic input] -_decimal.Context.fma - - self as context: self - x: object - y: object - z: object - / - -Return x multiplied by y, plus z. -[clinic start generated code]*/ - -static PyObject * -_decimal_Context_fma_impl(PyObject *context, PyObject *x, PyObject *y, - PyObject *z) -/*[clinic end generated code: output=2d6174716faaf4e1 input=80479612da3333d1]*/ DecCtx_TernaryFunc(mpd_qfma) /* No argument */ @@ -6633,7 +6500,7 @@ static PyMethodDef context_methods [] = _DECIMAL_CONTEXT_POWER_METHODDEF /* Ternary arithmetic functions */ - _DECIMAL_CONTEXT_FMA_METHODDEF + { "fma", ctx_mpd_qfma, METH_VARARGS, doc_ctx_fma }, /* No argument */ _DECIMAL_CONTEXT_ETINY_METHODDEF diff --git a/Modules/_decimal/clinic/_decimal.c.h b/Modules/_decimal/clinic/_decimal.c.h index df42463d82c869..224c24574554f3 100644 --- a/Modules/_decimal/clinic/_decimal.c.h +++ b/Modules/_decimal/clinic/_decimal.c.h @@ -1803,155 +1803,6 @@ _decimal_Decimal_fma(PyObject *self, PyObject *const *args, Py_ssize_t nargs, Py return return_value; } -PyDoc_STRVAR(_decimal_Decimal_is_canonical__doc__, -"is_canonical($self, /)\n" -"--\n" -"\n" -"Return True if the argument is canonical and False otherwise.\n" -"\n" -"Currently, a Decimal instance is always canonical, so this operation\n" -"always returns True."); - -#define _DECIMAL_DECIMAL_IS_CANONICAL_METHODDEF \ - {"is_canonical", (PyCFunction)_decimal_Decimal_is_canonical, METH_NOARGS, _decimal_Decimal_is_canonical__doc__}, - -static PyObject * -_decimal_Decimal_is_canonical_impl(PyObject *self); - -static PyObject * -_decimal_Decimal_is_canonical(PyObject *self, PyObject *Py_UNUSED(ignored)) -{ - return _decimal_Decimal_is_canonical_impl(self); -} - -PyDoc_STRVAR(_decimal_Decimal_is_finite__doc__, -"is_finite($self, /)\n" -"--\n" -"\n" -"Return True if the argument is a finite number, and False otherwise."); - -#define _DECIMAL_DECIMAL_IS_FINITE_METHODDEF \ - {"is_finite", (PyCFunction)_decimal_Decimal_is_finite, METH_NOARGS, _decimal_Decimal_is_finite__doc__}, - -static PyObject * -_decimal_Decimal_is_finite_impl(PyObject *self); - -static PyObject * -_decimal_Decimal_is_finite(PyObject *self, PyObject *Py_UNUSED(ignored)) -{ - return _decimal_Decimal_is_finite_impl(self); -} - -PyDoc_STRVAR(_decimal_Decimal_is_infinite__doc__, -"is_infinite($self, /)\n" -"--\n" -"\n" -"Return True if the argument is infinite, and False otherwise."); - -#define _DECIMAL_DECIMAL_IS_INFINITE_METHODDEF \ - {"is_infinite", (PyCFunction)_decimal_Decimal_is_infinite, METH_NOARGS, _decimal_Decimal_is_infinite__doc__}, - -static PyObject * -_decimal_Decimal_is_infinite_impl(PyObject *self); - -static PyObject * -_decimal_Decimal_is_infinite(PyObject *self, PyObject *Py_UNUSED(ignored)) -{ - return _decimal_Decimal_is_infinite_impl(self); -} - -PyDoc_STRVAR(_decimal_Decimal_is_nan__doc__, -"is_nan($self, /)\n" -"--\n" -"\n" -"Return True if the argument is a (quiet or signaling) NaN, else False."); - -#define _DECIMAL_DECIMAL_IS_NAN_METHODDEF \ - {"is_nan", (PyCFunction)_decimal_Decimal_is_nan, METH_NOARGS, _decimal_Decimal_is_nan__doc__}, - -static PyObject * -_decimal_Decimal_is_nan_impl(PyObject *self); - -static PyObject * -_decimal_Decimal_is_nan(PyObject *self, PyObject *Py_UNUSED(ignored)) -{ - return _decimal_Decimal_is_nan_impl(self); -} - -PyDoc_STRVAR(_decimal_Decimal_is_qnan__doc__, -"is_qnan($self, /)\n" -"--\n" -"\n" -"Return True if the argument is a quiet NaN, and False otherwise."); - -#define _DECIMAL_DECIMAL_IS_QNAN_METHODDEF \ - {"is_qnan", (PyCFunction)_decimal_Decimal_is_qnan, METH_NOARGS, _decimal_Decimal_is_qnan__doc__}, - -static PyObject * -_decimal_Decimal_is_qnan_impl(PyObject *self); - -static PyObject * -_decimal_Decimal_is_qnan(PyObject *self, PyObject *Py_UNUSED(ignored)) -{ - return _decimal_Decimal_is_qnan_impl(self); -} - -PyDoc_STRVAR(_decimal_Decimal_is_snan__doc__, -"is_snan($self, /)\n" -"--\n" -"\n" -"Return True if the argument is a signaling NaN and False otherwise."); - -#define _DECIMAL_DECIMAL_IS_SNAN_METHODDEF \ - {"is_snan", (PyCFunction)_decimal_Decimal_is_snan, METH_NOARGS, _decimal_Decimal_is_snan__doc__}, - -static PyObject * -_decimal_Decimal_is_snan_impl(PyObject *self); - -static PyObject * -_decimal_Decimal_is_snan(PyObject *self, PyObject *Py_UNUSED(ignored)) -{ - return _decimal_Decimal_is_snan_impl(self); -} - -PyDoc_STRVAR(_decimal_Decimal_is_signed__doc__, -"is_signed($self, /)\n" -"--\n" -"\n" -"Return True if the argument has a negative sign and False otherwise.\n" -"\n" -"Note that both zeros and NaNs can carry signs."); - -#define _DECIMAL_DECIMAL_IS_SIGNED_METHODDEF \ - {"is_signed", (PyCFunction)_decimal_Decimal_is_signed, METH_NOARGS, _decimal_Decimal_is_signed__doc__}, - -static PyObject * -_decimal_Decimal_is_signed_impl(PyObject *self); - -static PyObject * -_decimal_Decimal_is_signed(PyObject *self, PyObject *Py_UNUSED(ignored)) -{ - return _decimal_Decimal_is_signed_impl(self); -} - -PyDoc_STRVAR(_decimal_Decimal_is_zero__doc__, -"is_zero($self, /)\n" -"--\n" -"\n" -"Return True if the argument is a zero and False otherwise."); - -#define _DECIMAL_DECIMAL_IS_ZERO_METHODDEF \ - {"is_zero", (PyCFunction)_decimal_Decimal_is_zero, METH_NOARGS, _decimal_Decimal_is_zero__doc__}, - -static PyObject * -_decimal_Decimal_is_zero_impl(PyObject *self); - -static PyObject * -_decimal_Decimal_is_zero(PyObject *self, PyObject *Py_UNUSED(ignored)) -{ - return _decimal_Decimal_is_zero_impl(self); -} - PyDoc_STRVAR(_decimal_Decimal_is_normal__doc__, "is_normal($self, /, context=None)\n" "--\n" @@ -2484,166 +2335,6 @@ _decimal_Decimal_to_eng_string(PyObject *self, PyObject *const *args, Py_ssize_t return return_value; } -PyDoc_STRVAR(_decimal_Decimal_compare_total__doc__, -"compare_total($self, /, other, context=None)\n" -"--\n" -"\n" -"Compare two operands using their abstract representation.\n" -"\n" -"Similar to the compare() method, but the result\n" -"gives a total ordering on Decimal instances. Two Decimal instances with\n" -"the same numeric value but different representations compare unequal\n" -"in this ordering:\n" -"\n" -" >>> Decimal(\'12.0\').compare_total(Decimal(\'12\'))\n" -" Decimal(\'-1\')\n" -"\n" -"Quiet and signaling NaNs are also included in the total ordering. The\n" -"result of this function is Decimal(\'0\') if both operands have the same\n" -"representation, Decimal(\'-1\') if the first operand is lower in the\n" -"total order than the second, and Decimal(\'1\') if the first operand is\n" -"higher in the total order than the second operand. See the\n" -"specification for details of the total order.\n" -"\n" -"This operation is unaffected by context and is quiet: no flags are\n" -"changed and no rounding is performed. As an exception, the C version\n" -"may raise InvalidOperation if the second operand cannot be converted\n" -"exactly."); - -#define _DECIMAL_DECIMAL_COMPARE_TOTAL_METHODDEF \ - {"compare_total", _PyCFunction_CAST(_decimal_Decimal_compare_total), METH_FASTCALL|METH_KEYWORDS, _decimal_Decimal_compare_total__doc__}, - -static PyObject * -_decimal_Decimal_compare_total_impl(PyObject *self, PyObject *other, - PyObject *context); - -static PyObject * -_decimal_Decimal_compare_total(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 2 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - Py_hash_t ob_hash; - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_hash = -1, - .ob_item = { &_Py_ID(other), &_Py_ID(context), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"other", "context", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "compare_total", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[2]; - Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; - PyObject *other; - PyObject *context = Py_None; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, - /*minpos*/ 1, /*maxpos*/ 2, /*minkw*/ 0, /*varpos*/ 0, argsbuf); - if (!args) { - goto exit; - } - other = args[0]; - if (!noptargs) { - goto skip_optional_pos; - } - context = args[1]; -skip_optional_pos: - return_value = _decimal_Decimal_compare_total_impl(self, other, context); - -exit: - return return_value; -} - -PyDoc_STRVAR(_decimal_Decimal_compare_total_mag__doc__, -"compare_total_mag($self, /, other, context=None)\n" -"--\n" -"\n" -"As compare_total(), but ignores the sign of each operand.\n" -"\n" -"x.compare_total_mag(y) is equivalent to\n" -"x.copy_abs().compare_total(y.copy_abs()).\n" -"\n" -"This operation is unaffected by context and is quiet: no flags are\n" -"changed and no rounding is performed. As an exception, the C version\n" -"may raise InvalidOperation if the second operand cannot be converted\n" -"exactly."); - -#define _DECIMAL_DECIMAL_COMPARE_TOTAL_MAG_METHODDEF \ - {"compare_total_mag", _PyCFunction_CAST(_decimal_Decimal_compare_total_mag), METH_FASTCALL|METH_KEYWORDS, _decimal_Decimal_compare_total_mag__doc__}, - -static PyObject * -_decimal_Decimal_compare_total_mag_impl(PyObject *self, PyObject *other, - PyObject *context); - -static PyObject * -_decimal_Decimal_compare_total_mag(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 2 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - Py_hash_t ob_hash; - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_hash = -1, - .ob_item = { &_Py_ID(other), &_Py_ID(context), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"other", "context", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "compare_total_mag", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[2]; - Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; - PyObject *other; - PyObject *context = Py_None; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, - /*minpos*/ 1, /*maxpos*/ 2, /*minkw*/ 0, /*varpos*/ 0, argsbuf); - if (!args) { - goto exit; - } - other = args[0]; - if (!noptargs) { - goto skip_optional_pos; - } - context = args[1]; -skip_optional_pos: - return_value = _decimal_Decimal_compare_total_mag_impl(self, other, context); - -exit: - return return_value; -} - PyDoc_STRVAR(_decimal_Decimal_copy_sign__doc__, "copy_sign($self, /, other, context=None)\n" "--\n" @@ -3513,39 +3204,6 @@ _decimal_Context_power(PyObject *context, PyObject *const *args, Py_ssize_t narg return return_value; } -PyDoc_STRVAR(_decimal_Context_fma__doc__, -"fma($self, x, y, z, /)\n" -"--\n" -"\n" -"Return x multiplied by y, plus z."); - -#define _DECIMAL_CONTEXT_FMA_METHODDEF \ - {"fma", _PyCFunction_CAST(_decimal_Context_fma), METH_FASTCALL, _decimal_Context_fma__doc__}, - -static PyObject * -_decimal_Context_fma_impl(PyObject *context, PyObject *x, PyObject *y, - PyObject *z); - -static PyObject * -_decimal_Context_fma(PyObject *context, PyObject *const *args, Py_ssize_t nargs) -{ - PyObject *return_value = NULL; - PyObject *x; - PyObject *y; - PyObject *z; - - if (!_PyArg_CheckPositional("fma", nargs, 3, 3)) { - goto exit; - } - x = args[0]; - y = args[1]; - z = args[2]; - return_value = _decimal_Context_fma_impl(context, x, y, z); - -exit: - return return_value; -} - PyDoc_STRVAR(_decimal_Context_radix__doc__, "radix($self, /)\n" "--\n" @@ -3563,4 +3221,4 @@ _decimal_Context_radix(PyObject *context, PyObject *Py_UNUSED(ignored)) { return _decimal_Context_radix_impl(context); } -/*[clinic end generated code: output=9bc7d4c6f86a2a54 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=ffc58f98fffed531 input=a9049054013a1b77]*/ diff --git a/Modules/_decimal/docstrings.h b/Modules/_decimal/docstrings.h index 9a65403c72ea6c..7b286987d1b8e8 100644 --- a/Modules/_decimal/docstrings.h +++ b/Modules/_decimal/docstrings.h @@ -10,6 +10,53 @@ #include "pymacro.h" +PyDoc_STRVAR(doc_is_canonical, +"is_canonical($self, /)\n--\n\n\ +Return True if the argument is canonical and False otherwise. Currently,\n\ +a Decimal instance is always canonical, so this operation always returns\n\ +True.\n\ +\n"); + +PyDoc_STRVAR(doc_is_finite, +"is_finite($self, /)\n--\n\n\ +Return True if the argument is a finite number, and False if the argument\n\ +is infinite or a NaN.\n\ +\n"); + +PyDoc_STRVAR(doc_is_infinite, +"is_infinite($self, /)\n--\n\n\ +Return True if the argument is either positive or negative infinity and\n\ +False otherwise.\n\ +\n"); + +PyDoc_STRVAR(doc_is_nan, +"is_nan($self, /)\n--\n\n\ +Return True if the argument is a (quiet or signaling) NaN and False\n\ +otherwise.\n\ +\n"); + +PyDoc_STRVAR(doc_is_qnan, +"is_qnan($self, /)\n--\n\n\ +Return True if the argument is a quiet NaN, and False otherwise.\n\ +\n"); + +PyDoc_STRVAR(doc_is_signed, +"is_signed($self, /)\n--\n\n\ +Return True if the argument has a negative sign and False otherwise.\n\ +Note that both zeros and NaNs can carry signs.\n\ +\n"); + +PyDoc_STRVAR(doc_is_snan, +"is_snan($self, /)\n--\n\n\ +Return True if the argument is a signaling NaN and False otherwise.\n\ +\n"); + +PyDoc_STRVAR(doc_is_zero, +"is_zero($self, /)\n--\n\n\ +Return True if the argument is a (positive or negative) zero and False\n\ +otherwise.\n\ +\n"); + /******************************************************************************/ /* Context Object and Methods */ /******************************************************************************/ @@ -137,6 +184,45 @@ PyDoc_STRVAR(doc_ctx_exp, Return e ** x.\n\ \n"); +PyDoc_STRVAR(doc_ctx_fma, +"fma($self, x, y, z, /)\n--\n\n\ +Return x multiplied by y, plus z.\n\ +\n"); + +PyDoc_STRVAR(doc_compare_total, +"compare_total($self, /, other, context=None)\n--\n\n\ +Compare two operands using their abstract representation rather than\n\ +their numerical value. Similar to the compare() method, but the result\n\ +gives a total ordering on Decimal instances. Two Decimal instances with\n\ +the same numeric value but different representations compare unequal\n\ +in this ordering:\n\ +\n\ + >>> Decimal('12.0').compare_total(Decimal('12'))\n\ + Decimal('-1')\n\ +\n\ +Quiet and signaling NaNs are also included in the total ordering. The result\n\ +of this function is Decimal('0') if both operands have the same representation,\n\ +Decimal('-1') if the first operand is lower in the total order than the second,\n\ +and Decimal('1') if the first operand is higher in the total order than the\n\ +second operand. See the specification for details of the total order.\n\ +\n\ +This operation is unaffected by context and is quiet: no flags are changed\n\ +and no rounding is performed. As an exception, the C version may raise\n\ +InvalidOperation if the second operand cannot be converted exactly.\n\ +\n"); + +PyDoc_STRVAR(doc_compare_total_mag, +"compare_total_mag($self, /, other, context=None)\n--\n\n\ +Compare two operands using their abstract representation rather than their\n\ +value as in compare_total(), but ignoring the sign of each operand.\n\ +\n\ +x.compare_total_mag(y) is equivalent to x.copy_abs().compare_total(y.copy_abs()).\n\ +\n\ +This operation is unaffected by context and is quiet: no flags are changed\n\ +and no rounding is performed. As an exception, the C version may raise\n\ +InvalidOperation if the second operand cannot be converted exactly.\n\ +\n"); + PyDoc_STRVAR(doc_ctx_is_canonical, "is_canonical($self, x, /)\n--\n\n\ Return True if x is canonical, False otherwise.\n\