diff --git a/Include/internal/pycore_global_objects_fini_generated.h b/Include/internal/pycore_global_objects_fini_generated.h index d8fefa16faf70f..672537bfedc9af 100644 --- a/Include/internal/pycore_global_objects_fini_generated.h +++ b/Include/internal/pycore_global_objects_fini_generated.h @@ -1154,6 +1154,7 @@ _PyStaticObjects_CheckRefcnt(PyInterpreterState *interp) { _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(options)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(order)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(origin)); + _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(other)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(out_fd)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(outgoing)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(outpath)); @@ -1213,6 +1214,7 @@ _PyStaticObjects_CheckRefcnt(PyInterpreterState *interp) { _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(return)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(reverse)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(reversed)); + _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(rounding)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(salt)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(sched_priority)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(scheduler)); diff --git a/Include/internal/pycore_global_strings.h b/Include/internal/pycore_global_strings.h index b9207f46cd729d..ed767206ee7322 100644 --- a/Include/internal/pycore_global_strings.h +++ b/Include/internal/pycore_global_strings.h @@ -645,6 +645,7 @@ struct _Py_global_strings { STRUCT_FOR_ID(options) STRUCT_FOR_ID(order) STRUCT_FOR_ID(origin) + STRUCT_FOR_ID(other) STRUCT_FOR_ID(out_fd) STRUCT_FOR_ID(outgoing) STRUCT_FOR_ID(outpath) @@ -704,6 +705,7 @@ struct _Py_global_strings { STRUCT_FOR_ID(return) STRUCT_FOR_ID(reverse) STRUCT_FOR_ID(reversed) + STRUCT_FOR_ID(rounding) STRUCT_FOR_ID(salt) STRUCT_FOR_ID(sched_priority) STRUCT_FOR_ID(scheduler) diff --git a/Include/internal/pycore_runtime_init_generated.h b/Include/internal/pycore_runtime_init_generated.h index 254b02be1334bd..2f24a138fdbf0c 100644 --- a/Include/internal/pycore_runtime_init_generated.h +++ b/Include/internal/pycore_runtime_init_generated.h @@ -1152,6 +1152,7 @@ extern "C" { INIT_ID(options), \ INIT_ID(order), \ INIT_ID(origin), \ + INIT_ID(other), \ INIT_ID(out_fd), \ INIT_ID(outgoing), \ INIT_ID(outpath), \ @@ -1211,6 +1212,7 @@ extern "C" { INIT_ID(return), \ INIT_ID(reverse), \ INIT_ID(reversed), \ + INIT_ID(rounding), \ INIT_ID(salt), \ INIT_ID(sched_priority), \ INIT_ID(scheduler), \ diff --git a/Include/internal/pycore_unicodeobject_generated.h b/Include/internal/pycore_unicodeobject_generated.h index f1f6bc48fdf1a3..4f8866e729c51e 100644 --- a/Include/internal/pycore_unicodeobject_generated.h +++ b/Include/internal/pycore_unicodeobject_generated.h @@ -2368,6 +2368,10 @@ _PyUnicode_InitStaticStrings(PyInterpreterState *interp) { _PyUnicode_InternStatic(interp, &string); assert(_PyUnicode_CheckConsistency(string, 1)); assert(PyUnicode_GET_LENGTH(string) != 1); + string = &_Py_ID(other); + _PyUnicode_InternStatic(interp, &string); + assert(_PyUnicode_CheckConsistency(string, 1)); + assert(PyUnicode_GET_LENGTH(string) != 1); string = &_Py_ID(out_fd); _PyUnicode_InternStatic(interp, &string); assert(_PyUnicode_CheckConsistency(string, 1)); @@ -2604,6 +2608,10 @@ _PyUnicode_InitStaticStrings(PyInterpreterState *interp) { _PyUnicode_InternStatic(interp, &string); assert(_PyUnicode_CheckConsistency(string, 1)); assert(PyUnicode_GET_LENGTH(string) != 1); + string = &_Py_ID(rounding); + _PyUnicode_InternStatic(interp, &string); + assert(_PyUnicode_CheckConsistency(string, 1)); + assert(PyUnicode_GET_LENGTH(string) != 1); string = &_Py_ID(salt); _PyUnicode_InternStatic(interp, &string); assert(_PyUnicode_CheckConsistency(string, 1)); diff --git a/Misc/NEWS.d/next/Library/2025-08-13-10-50-22.gh-issue-73487.DUHbBq.rst b/Misc/NEWS.d/next/Library/2025-08-13-10-50-22.gh-issue-73487.DUHbBq.rst new file mode 100644 index 00000000000000..8cca50d91cd198 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2025-08-13-10-50-22.gh-issue-73487.DUHbBq.rst @@ -0,0 +1,3 @@ +Speedup processing arguments (up to 1.5x) in the :mod:`decimal` module +methods, that now using :c:macro:`METH_FASTCALL` calling convention. Patch +by Sergey B Kirpichev. diff --git a/Modules/_decimal/_decimal.c b/Modules/_decimal/_decimal.c index 602b23cfca8945..46cedf83df1f00 100644 --- a/Modules/_decimal/_decimal.c +++ b/Modules/_decimal/_decimal.c @@ -58,6 +58,14 @@ #define _PY_DEC_ROUND_GUARD (MPD_ROUND_GUARD-1) #endif +#include "clinic/_decimal.c.h" + +/*[clinic input] +module _decimal +class _decimal.Decimal "PyObject *" "&dec_spec" +[clinic start generated code]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=e0e1f68f1f413f5f]*/ + struct PyDecContextObject; struct DecCondMap; @@ -2869,18 +2877,41 @@ PyDecType_FromSequenceExact(PyTypeObject *type, PyObject *v, #define PyDec_FromSequenceExact(st, sequence, context) \ PyDecType_FromSequenceExact((st)->PyDec_Type, sequence, context) -/* class method */ +/*[clinic input] +@classmethod +_decimal.Decimal.from_float + + f as pyfloat: object + / + +Class method that converts a float to a decimal number, exactly. + +Since 0.1 is not exactly representable in binary floating point, +Decimal.from_float(0.1) is not the same as Decimal('0.1'). + + >>> Decimal.from_float(0.1) + Decimal('0.1000000000000000055511151231257827021181583404541015625') + >>> Decimal.from_float(float('nan')) + Decimal('NaN') + >>> Decimal.from_float(float('inf')) + Decimal('Infinity') + >>> Decimal.from_float(float('-inf')) + Decimal('-Infinity') +[clinic start generated code]*/ + static PyObject * -dec_from_float(PyObject *type, PyObject *pyfloat) +_decimal_Decimal_from_float_impl(PyTypeObject *type, PyObject *pyfloat) +/*[clinic end generated code: output=e62775271ac469e6 input=052036648342f8c8]*/ { PyObject *context; PyObject *result; - decimal_state *state = get_module_state_by_def((PyTypeObject *)type); + decimal_state *state = get_module_state_by_def(type); CURRENT_CONTEXT(state, context); result = PyDecType_FromFloatExact(state->PyDec_Type, pyfloat, context); - if (type != (PyObject *)state->PyDec_Type && result != NULL) { - Py_SETREF(result, PyObject_CallFunctionObjArgs(type, result, NULL)); + if (type != state->PyDec_Type && result != NULL) { + Py_SETREF(result, + PyObject_CallFunctionObjArgs((PyObject *)type, result, NULL)); } return result; @@ -2914,18 +2945,36 @@ PyDecType_FromNumberExact(PyTypeObject *type, PyObject *v, PyObject *context) } } -/* class method */ +/*[clinic input] +@classmethod +_decimal.Decimal.from_number + + number: object + / + +Class method that converts a real number to a decimal number, exactly. + + >>> Decimal.from_number(314) # int + Decimal('314') + >>> Decimal.from_number(0.1) # float + Decimal('0.1000000000000000055511151231257827021181583404541015625') + >>> Decimal.from_number(Decimal('3.14')) # another decimal instance + Decimal('3.14') +[clinic start generated code]*/ + static PyObject * -dec_from_number(PyObject *type, PyObject *number) +_decimal_Decimal_from_number_impl(PyTypeObject *type, PyObject *number) +/*[clinic end generated code: output=41885304e5beea0a input=c58b678e8916f66b]*/ { PyObject *context; PyObject *result; - decimal_state *state = get_module_state_by_def((PyTypeObject *)type); + decimal_state *state = get_module_state_by_def(type); CURRENT_CONTEXT(state, context); result = PyDecType_FromNumberExact(state->PyDec_Type, number, context); - if (type != (PyObject *)state->PyDec_Type && result != NULL) { - Py_SETREF(result, PyObject_CallFunctionObjArgs(type, result, NULL)); + if (type != state->PyDec_Type && result != NULL) { + Py_SETREF(result, + PyObject_CallFunctionObjArgs((PyObject *)type, result, NULL)); } return result; @@ -3750,9 +3799,18 @@ dec_as_long(PyObject *dec, PyObject *context, int round) return PyLongWriter_Finish(writer); } -/* Convert a Decimal to its exact integer ratio representation. */ +/*[clinic input] +_decimal.Decimal.as_integer_ratio + +Return a pair of integers whose ratio is exactly equal to the original. + +The ratio is in lowest terms and with a positive denominator. +Raise OverflowError on infinities and a ValueError on NaNs. +[clinic start generated code]*/ + static PyObject * -dec_as_integer_ratio(PyObject *self, PyObject *Py_UNUSED(dummy)) +_decimal_Decimal_as_integer_ratio_impl(PyObject *self) +/*[clinic end generated code: output=c5d88e900080c264 input=7861cb643f01525a]*/ { PyObject *numerator = NULL; PyObject *denominator = NULL; @@ -3854,21 +3912,29 @@ dec_as_integer_ratio(PyObject *self, PyObject *Py_UNUSED(dummy)) return result; } +/*[clinic input] +_decimal.Decimal.to_integral_value + + rounding: object = None + context: object = None + +Round to the nearest integer without signaling Inexact or Rounded. + +The rounding mode is determined by the rounding parameter if given, +else by the given context. If neither parameter is given, then the +rounding mode of the current default context is used. +[clinic start generated code]*/ + static PyObject * -PyDec_ToIntegralValue(PyObject *dec, PyObject *args, PyObject *kwds) +_decimal_Decimal_to_integral_value_impl(PyObject *self, PyObject *rounding, + PyObject *context) +/*[clinic end generated code: output=7301465765f48b6b input=04e2312d5ed19f77]*/ { - static char *kwlist[] = {"rounding", "context", NULL}; PyObject *result; - PyObject *rounding = Py_None; - PyObject *context = Py_None; uint32_t status = 0; mpd_context_t workctx; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OO", kwlist, - &rounding, &context)) { - return NULL; - } - decimal_state *state = get_module_state_by_def(Py_TYPE(dec)); + decimal_state *state = get_module_state_by_def(Py_TYPE(self)); CONTEXT_CHECK_VA(state, context); workctx = *CTX(context); @@ -3887,7 +3953,7 @@ PyDec_ToIntegralValue(PyObject *dec, PyObject *args, PyObject *kwds) return NULL; } - mpd_qround_to_int(MPD(result), MPD(dec), &workctx, &status); + mpd_qround_to_int(MPD(result), MPD(self), &workctx, &status); if (dec_addstatus(context, status)) { Py_DECREF(result); return NULL; @@ -3896,21 +3962,50 @@ PyDec_ToIntegralValue(PyObject *dec, PyObject *args, PyObject *kwds) return result; } +/*[clinic input] +_decimal.Decimal.to_integral + + rounding: object = None + context: object = None + +Identical to the to_integral_value() method. + +The to_integral() name has been kept for compatibility with older +versions. +[clinic start generated code]*/ + +static PyObject * +_decimal_Decimal_to_integral_impl(PyObject *self, PyObject *rounding, + PyObject *context) +/*[clinic end generated code: output=a0c7188686ee7f5c input=8eac6def038d13b9]*/ +{ + return _decimal_Decimal_to_integral_value_impl(self, rounding, context); +} + +/*[clinic input] +_decimal.Decimal.to_integral_exact + + rounding: object = None + context: object = None + +Round to the nearest integer. + +Decimal.to_integral_exact() signals Inexact or Rounded as appropriate +if rounding occurs. The rounding mode is determined by the rounding +parameter if given, else by the given context. If neither parameter is +given, then the rounding mode of the current default context is used. +[clinic start generated code]*/ + static PyObject * -PyDec_ToIntegralExact(PyObject *dec, PyObject *args, PyObject *kwds) +_decimal_Decimal_to_integral_exact_impl(PyObject *self, PyObject *rounding, + PyObject *context) +/*[clinic end generated code: output=8b004f9b45ac7746 input=c290166f59c1d6ab]*/ { - static char *kwlist[] = {"rounding", "context", NULL}; PyObject *result; - PyObject *rounding = Py_None; - PyObject *context = Py_None; uint32_t status = 0; mpd_context_t workctx; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OO", kwlist, - &rounding, &context)) { - return NULL; - } - decimal_state *state = get_module_state_by_def(Py_TYPE(dec)); + decimal_state *state = get_module_state_by_def(Py_TYPE(self)); CONTEXT_CHECK_VA(state, context); workctx = *CTX(context); @@ -3929,7 +4024,7 @@ PyDec_ToIntegralExact(PyObject *dec, PyObject *args, PyObject *kwds) return NULL; } - mpd_qround_to_intx(MPD(result), MPD(dec), &workctx, &status); + mpd_qround_to_intx(MPD(result), MPD(self), &workctx, &status); if (dec_addstatus(context, status)) { Py_DECREF(result); return NULL; @@ -4018,9 +4113,15 @@ PyDec_Round(PyObject *dec, PyObject *args) } } -/* Return the DecimalTuple representation of a PyDecObject. */ +/*[clinic input] +_decimal.Decimal.as_tuple + +Return a tuple representation of the number. +[clinic start generated code]*/ + static PyObject * -PyDec_AsTuple(PyObject *dec, PyObject *Py_UNUSED(dummy)) +_decimal_Decimal_as_tuple_impl(PyObject *self) +/*[clinic end generated code: output=c6e8e2420c515eca input=e26f2151d78ff59d]*/ { PyObject *result = NULL; PyObject *sign = NULL; @@ -4032,13 +4133,13 @@ PyDec_AsTuple(PyObject *dec, PyObject *Py_UNUSED(dummy)) Py_ssize_t intlen, i; - x = mpd_qncopy(MPD(dec)); + x = mpd_qncopy(MPD(self)); if (x == NULL) { PyErr_NoMemory(); goto out; } - sign = PyLong_FromUnsignedLong(mpd_sign(MPD(dec))); + sign = PyLong_FromUnsignedLong(mpd_sign(MPD(self))); if (sign == NULL) { goto out; } @@ -4059,7 +4160,7 @@ PyDec_AsTuple(PyObject *dec, PyObject *Py_UNUSED(dummy)) expt = PyUnicode_FromString(mpd_isqnan(x)?"n":"N"); } else { - expt = PyLong_FromSsize_t(MPD(dec)->exp); + expt = PyLong_FromSsize_t(MPD(self)->exp); } if (expt == NULL) { goto out; @@ -4100,7 +4201,7 @@ PyDec_AsTuple(PyObject *dec, PyObject *Py_UNUSED(dummy)) } } - decimal_state *state = get_module_state_by_def(Py_TYPE(dec)); + decimal_state *state = get_module_state_by_def(Py_TYPE(self)); result = PyObject_CallFunctionObjArgs((PyObject *)state->DecimalTuple, sign, coeff, expt, NULL); @@ -4504,8 +4605,16 @@ Dec_BoolFuncVA(mpd_isnormal) Dec_BoolFuncVA(mpd_issubnormal) /* Unary functions, no context arg */ + +/*[clinic input] +_decimal.Decimal.adjusted + +Return the adjusted exponent (exp + digits - 1) of the number. +[clinic start generated code]*/ + static PyObject * -dec_mpd_adjexp(PyObject *self, PyObject *Py_UNUSED(dummy)) +_decimal_Decimal_adjusted_impl(PyObject *self) +/*[clinic end generated code: output=21ea2c9f23994c52 input=8ba2029d8d906b18]*/ { mpd_ssize_t retval; @@ -4519,14 +4628,31 @@ dec_mpd_adjexp(PyObject *self, PyObject *Py_UNUSED(dummy)) return PyLong_FromSsize_t(retval); } +/*[clinic input] +_decimal.Decimal.canonical + +Return the canonical encoding of the argument. + +Currently, the encoding of a Decimal instance is always canonical, +so this operation returns its argument unchanged. +[clinic start generated code]*/ + static PyObject * -dec_canonical(PyObject *self, PyObject *Py_UNUSED(dummy)) +_decimal_Decimal_canonical_impl(PyObject *self) +/*[clinic end generated code: output=3cbeb47d91e6da2d input=8a4719d14c52d521]*/ { return Py_NewRef(self); } +/*[clinic input] +_decimal.Decimal.conjugate + +Return self. +[clinic start generated code]*/ + static PyObject * -dec_conjugate(PyObject *self, PyObject *Py_UNUSED(dummy)) +_decimal_Decimal_conjugate_impl(PyObject *self) +/*[clinic end generated code: output=9a37bf633f25a291 input=c7179975ef74fd84]*/ { return Py_NewRef(self); } @@ -4545,15 +4671,35 @@ _dec_mpd_radix(decimal_state *state) return result; } +/*[clinic input] +_decimal.Decimal.radix + +Return Decimal(10). + +This is the radix (base) in which the Decimal class does +all its arithmetic. Included for compatibility with the specification. +[clinic start generated code]*/ + static PyObject * -dec_mpd_radix(PyObject *self, PyObject *Py_UNUSED(dummy)) +_decimal_Decimal_radix_impl(PyObject *self) +/*[clinic end generated code: output=6b1db4c3fcdb5ee1 input=18b72393549ca8fd]*/ { decimal_state *state = get_module_state_by_def(Py_TYPE(self)); return _dec_mpd_radix(state); } +/*[clinic input] +_decimal.Decimal.copy_abs + +Return the absolute value of the argument. + +This operation is unaffected by context and is quiet: no flags are +changed and no rounding is performed. +[clinic start generated code]*/ + static PyObject * -dec_mpd_qcopy_abs(PyObject *self, PyObject *Py_UNUSED(dummy)) +_decimal_Decimal_copy_abs_impl(PyObject *self) +/*[clinic end generated code: output=fff53742cca94d70 input=a263c2e71d421f1b]*/ { PyObject *result; uint32_t status = 0; @@ -4573,8 +4719,18 @@ dec_mpd_qcopy_abs(PyObject *self, PyObject *Py_UNUSED(dummy)) return result; } +/*[clinic input] +_decimal.Decimal.copy_negate + +Return the negation of the argument. + +This operation is unaffected by context and is quiet: no flags are +changed and no rounding is performed. +[clinic start generated code]*/ + static PyObject * -dec_mpd_qcopy_negate(PyObject *self, PyObject *Py_UNUSED(dummy)) +_decimal_Decimal_copy_negate_impl(PyObject *self) +/*[clinic end generated code: output=8551bc26dbc5d01d input=13d47ed3a5d228b1]*/ { PyObject *result; uint32_t status = 0; @@ -4598,17 +4754,37 @@ dec_mpd_qcopy_negate(PyObject *self, PyObject *Py_UNUSED(dummy)) Dec_UnaryFuncVA(mpd_qinvert) Dec_UnaryFuncVA(mpd_qlogb) +/*[clinic input] +_decimal.Decimal.number_class + + context: object = None + +Return a string describing the class of the operand. + +The returned value is one of the following ten strings: + + * '-Infinity', indicating that the operand is negative infinity. + * '-Normal', indicating that the operand is a negative normal + number. + * '-Subnormal', indicating that the operand is negative and + subnormal. + * '-Zero', indicating that the operand is a negative zero. + * '+Zero', indicating that the operand is a positive zero. + * '+Subnormal', indicating that the operand is positive and + subnormal. + * '+Normal', indicating that the operand is a positive normal + number. + * '+Infinity', indicating that the operand is positive infinity. + * 'NaN', indicating that the operand is a quiet NaN (Not a Number). + * 'sNaN', indicating that the operand is a signaling NaN. +[clinic start generated code]*/ + static PyObject * -dec_mpd_class(PyObject *self, PyObject *args, PyObject *kwds) +_decimal_Decimal_number_class_impl(PyObject *self, PyObject *context) +/*[clinic end generated code: output=3044cd45966b4949 input=f3d6cdda603e8b89]*/ { - static char *kwlist[] = {"context", NULL}; - PyObject *context = Py_None; const char *cp; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O", kwlist, - &context)) { - return NULL; - } decimal_state *state = get_module_state_by_def(Py_TYPE(self)); CONTEXT_CHECK_VA(state, context); @@ -4616,19 +4792,30 @@ dec_mpd_class(PyObject *self, PyObject *args, PyObject *kwds) return PyUnicode_FromString(cp); } +/*[clinic input] +_decimal.Decimal.to_eng_string + + context: object = None + +Convert to an engineering-type string. + +Engineering notation has an exponent which is a multiple of 3, so there +are up to 3 digits left of the decimal place. For example, +Decimal('123E+1') is converted to Decimal('1.23E+3'). + +The value of context.capitals determines whether the exponent sign is +lower or upper case. Otherwise, the context does not affect the +operation. +[clinic start generated code]*/ + static PyObject * -dec_mpd_to_eng(PyObject *self, PyObject *args, PyObject *kwds) +_decimal_Decimal_to_eng_string_impl(PyObject *self, PyObject *context) +/*[clinic end generated code: output=d386194c25ffffa7 input=2e13e7c7c1bad2ad]*/ { - static char *kwlist[] = {"context", NULL}; PyObject *result; - PyObject *context = Py_None; mpd_ssize_t size; char *s; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O", kwlist, - &context)) { - return NULL; - } decimal_state *state = get_module_state_by_def(Py_TYPE(self)); CONTEXT_CHECK_VA(state, context); @@ -4648,20 +4835,34 @@ dec_mpd_to_eng(PyObject *self, PyObject *args, PyObject *kwds) Dec_BinaryFuncVA_NO_CTX(mpd_compare_total) Dec_BinaryFuncVA_NO_CTX(mpd_compare_total_mag) +/*[clinic input] +_decimal.Decimal.copy_sign + + other: object + context: object = None + +Return a copy of *self* with the sign of *other*. + +For example: + + >>> Decimal('2.3').copy_sign(Decimal('-1.5')) + Decimal('-2.3') + +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 * -dec_mpd_qcopy_sign(PyObject *self, PyObject *args, PyObject *kwds) +_decimal_Decimal_copy_sign_impl(PyObject *self, PyObject *other, + PyObject *context) +/*[clinic end generated code: output=72c62177763e012e input=8410238d533a06eb]*/ { - static char *kwlist[] = {"other", "context", NULL}; - PyObject *other; PyObject *a, *b; PyObject *result; - PyObject *context = Py_None; uint32_t status = 0; - 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); CONVERT_BINOP_RAISE(&a, &b, self, other, context); @@ -4684,19 +4885,28 @@ dec_mpd_qcopy_sign(PyObject *self, PyObject *args, PyObject *kwds) return result; } +/*[clinic input] +_decimal.Decimal.same_quantum + + other: object + context: object = None + +Test whether self and other have the same exponent or both are NaN. + +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 * -dec_mpd_same_quantum(PyObject *self, PyObject *args, PyObject *kwds) +_decimal_Decimal_same_quantum_impl(PyObject *self, PyObject *other, + PyObject *context) +/*[clinic end generated code: output=c0a3a046c662a7e2 input=3ae45df81d6edb73]*/ { - static char *kwlist[] = {"other", "context", NULL}; - PyObject *other; PyObject *a, *b; PyObject *result; - PyObject *context = Py_None; - 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); CONVERT_BINOP_RAISE(&a, &b, self, other, context); @@ -4717,22 +4927,48 @@ Dec_BinaryFuncVA(mpd_qrotate) Dec_BinaryFuncVA(mpd_qscaleb) Dec_BinaryFuncVA(mpd_qshift) +/*[clinic input] +_decimal.Decimal.quantize + + exp as w: object + rounding: object = None + context: object = None + +Quantize *self* so its exponent is the same as that of *exp*. + +Return a value equal to *self* after rounding, with the exponent +of *exp*. + + >>> Decimal('1.41421356').quantize(Decimal('1.000')) + Decimal('1.414') + +Unlike other operations, if the length of the coefficient after the +quantize operation would be greater than precision, then an +InvalidOperation is signaled. This guarantees that, unless there +is an error condition, the quantized exponent is always equal to +that of the right-hand operand. + +Also unlike other operations, quantize never signals Underflow, even +if the result is subnormal and inexact. + +If the exponent of the second operand is larger than that of the first, +then rounding may be necessary. In this case, the rounding mode is +determined by the rounding argument if given, else by the given context +argument; if neither argument is given, the rounding mode of the +current thread's context is used. +[clinic start generated code]*/ + static PyObject * -dec_mpd_qquantize(PyObject *v, PyObject *args, PyObject *kwds) +_decimal_Decimal_quantize_impl(PyObject *self, PyObject *w, + PyObject *rounding, PyObject *context) +/*[clinic end generated code: output=5e84581f96dc685c input=4c7d28d36948e9aa]*/ { - static char *kwlist[] = {"exp", "rounding", "context", NULL}; - PyObject *rounding = Py_None; - PyObject *context = Py_None; - PyObject *w, *a, *b; + PyObject *a, *b; PyObject *result; uint32_t status = 0; mpd_context_t workctx; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|OO", kwlist, - &w, &rounding, &context)) { - return NULL; - } - decimal_state *state = get_module_state_by_def(Py_TYPE(v)); + decimal_state *state = get_module_state_by_def(Py_TYPE(self)); CONTEXT_CHECK_VA(state, context); workctx = *CTX(context); @@ -4746,7 +4982,7 @@ dec_mpd_qquantize(PyObject *v, PyObject *args, PyObject *kwds) } } - CONVERT_BINOP_RAISE(&a, &b, v, w, context); + CONVERT_BINOP_RAISE(&a, &b, self, w, context); result = dec_alloc(state); if (result == NULL) { @@ -5081,9 +5317,9 @@ static PyMethodDef dec_methods [] = { "next_minus", _PyCFunction_CAST(dec_mpd_qnext_minus), METH_VARARGS|METH_KEYWORDS, doc_next_minus }, { "next_plus", _PyCFunction_CAST(dec_mpd_qnext_plus), METH_VARARGS|METH_KEYWORDS, doc_next_plus }, { "normalize", _PyCFunction_CAST(dec_mpd_qreduce), METH_VARARGS|METH_KEYWORDS, doc_normalize }, - { "to_integral", _PyCFunction_CAST(PyDec_ToIntegralValue), METH_VARARGS|METH_KEYWORDS, doc_to_integral }, - { "to_integral_exact", _PyCFunction_CAST(PyDec_ToIntegralExact), METH_VARARGS|METH_KEYWORDS, doc_to_integral_exact }, - { "to_integral_value", _PyCFunction_CAST(PyDec_ToIntegralValue), METH_VARARGS|METH_KEYWORDS, doc_to_integral_value }, + _DECIMAL_DECIMAL_TO_INTEGRAL_METHODDEF + _DECIMAL_DECIMAL_TO_INTEGRAL_EXACT_METHODDEF + _DECIMAL_DECIMAL_TO_INTEGRAL_VALUE_METHODDEF { "sqrt", _PyCFunction_CAST(dec_mpd_qsqrt), METH_VARARGS|METH_KEYWORDS, doc_sqrt }, /* Binary arithmetic functions, optional context arg */ @@ -5094,7 +5330,7 @@ static PyMethodDef dec_methods [] = { "min", _PyCFunction_CAST(dec_mpd_qmin), METH_VARARGS|METH_KEYWORDS, doc_min }, { "min_mag", _PyCFunction_CAST(dec_mpd_qmin_mag), METH_VARARGS|METH_KEYWORDS, doc_min_mag }, { "next_toward", _PyCFunction_CAST(dec_mpd_qnext_toward), METH_VARARGS|METH_KEYWORDS, doc_next_toward }, - { "quantize", _PyCFunction_CAST(dec_mpd_qquantize), METH_VARARGS|METH_KEYWORDS, doc_quantize }, + _DECIMAL_DECIMAL_QUANTIZE_METHODDEF { "remainder_near", _PyCFunction_CAST(dec_mpd_qrem_near), METH_VARARGS|METH_KEYWORDS, doc_remainder_near }, /* Ternary arithmetic functions, optional context arg */ @@ -5115,26 +5351,26 @@ static PyMethodDef dec_methods [] = { "is_subnormal", _PyCFunction_CAST(dec_mpd_issubnormal), METH_VARARGS|METH_KEYWORDS, doc_is_subnormal }, /* Unary functions, no context arg */ - { "adjusted", dec_mpd_adjexp, METH_NOARGS, doc_adjusted }, - { "canonical", dec_canonical, METH_NOARGS, doc_canonical }, - { "conjugate", dec_conjugate, METH_NOARGS, doc_conjugate }, - { "radix", dec_mpd_radix, METH_NOARGS, doc_radix }, + _DECIMAL_DECIMAL_ADJUSTED_METHODDEF + _DECIMAL_DECIMAL_CANONICAL_METHODDEF + _DECIMAL_DECIMAL_CONJUGATE_METHODDEF + _DECIMAL_DECIMAL_RADIX_METHODDEF /* Unary functions, optional context arg for conversion errors */ - { "copy_abs", dec_mpd_qcopy_abs, METH_NOARGS, doc_copy_abs }, - { "copy_negate", dec_mpd_qcopy_negate, METH_NOARGS, doc_copy_negate }, + _DECIMAL_DECIMAL_COPY_ABS_METHODDEF + _DECIMAL_DECIMAL_COPY_NEGATE_METHODDEF /* Unary functions, optional context arg */ { "logb", _PyCFunction_CAST(dec_mpd_qlogb), METH_VARARGS|METH_KEYWORDS, doc_logb }, { "logical_invert", _PyCFunction_CAST(dec_mpd_qinvert), METH_VARARGS|METH_KEYWORDS, doc_logical_invert }, - { "number_class", _PyCFunction_CAST(dec_mpd_class), METH_VARARGS|METH_KEYWORDS, doc_number_class }, - { "to_eng_string", _PyCFunction_CAST(dec_mpd_to_eng), METH_VARARGS|METH_KEYWORDS, doc_to_eng_string }, + _DECIMAL_DECIMAL_NUMBER_CLASS_METHODDEF + _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 }, - { "copy_sign", _PyCFunction_CAST(dec_mpd_qcopy_sign), METH_VARARGS|METH_KEYWORDS, doc_copy_sign }, - { "same_quantum", _PyCFunction_CAST(dec_mpd_same_quantum), METH_VARARGS|METH_KEYWORDS, doc_same_quantum }, + _DECIMAL_DECIMAL_COPY_SIGN_METHODDEF + _DECIMAL_DECIMAL_SAME_QUANTUM_METHODDEF /* Binary functions, optional context arg */ { "logical_and", _PyCFunction_CAST(dec_mpd_qand), METH_VARARGS|METH_KEYWORDS, doc_logical_and }, @@ -5145,10 +5381,10 @@ static PyMethodDef dec_methods [] = { "shift", _PyCFunction_CAST(dec_mpd_qshift), METH_VARARGS|METH_KEYWORDS, doc_shift }, /* Miscellaneous */ - { "from_float", dec_from_float, METH_O|METH_CLASS, doc_from_float }, - { "from_number", dec_from_number, METH_O|METH_CLASS, doc_from_number }, - { "as_tuple", PyDec_AsTuple, METH_NOARGS, doc_as_tuple }, - { "as_integer_ratio", dec_as_integer_ratio, METH_NOARGS, doc_as_integer_ratio }, + _DECIMAL_DECIMAL_FROM_FLOAT_METHODDEF + _DECIMAL_DECIMAL_FROM_NUMBER_METHODDEF + _DECIMAL_DECIMAL_AS_TUPLE_METHODDEF + _DECIMAL_DECIMAL_AS_INTEGER_RATIO_METHODDEF /* Special methods */ { "__copy__", dec_copy, METH_NOARGS, NULL }, diff --git a/Modules/_decimal/clinic/_decimal.c.h b/Modules/_decimal/clinic/_decimal.c.h new file mode 100644 index 00000000000000..441515edbf60f6 --- /dev/null +++ b/Modules/_decimal/clinic/_decimal.c.h @@ -0,0 +1,849 @@ +/*[clinic input] +preserve +[clinic start generated code]*/ + +#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) +# include "pycore_gc.h" // PyGC_Head +# include "pycore_runtime.h" // _Py_ID() +#endif +#include "pycore_modsupport.h" // _PyArg_UnpackKeywords() + +PyDoc_STRVAR(_decimal_Decimal_from_float__doc__, +"from_float($type, f, /)\n" +"--\n" +"\n" +"Class method that converts a float to a decimal number, exactly.\n" +"\n" +"Since 0.1 is not exactly representable in binary floating point,\n" +"Decimal.from_float(0.1) is not the same as Decimal(\'0.1\').\n" +"\n" +" >>> Decimal.from_float(0.1)\n" +" Decimal(\'0.1000000000000000055511151231257827021181583404541015625\')\n" +" >>> Decimal.from_float(float(\'nan\'))\n" +" Decimal(\'NaN\')\n" +" >>> Decimal.from_float(float(\'inf\'))\n" +" Decimal(\'Infinity\')\n" +" >>> Decimal.from_float(float(\'-inf\'))\n" +" Decimal(\'-Infinity\')"); + +#define _DECIMAL_DECIMAL_FROM_FLOAT_METHODDEF \ + {"from_float", (PyCFunction)_decimal_Decimal_from_float, METH_O|METH_CLASS, _decimal_Decimal_from_float__doc__}, + +static PyObject * +_decimal_Decimal_from_float_impl(PyTypeObject *type, PyObject *pyfloat); + +static PyObject * +_decimal_Decimal_from_float(PyObject *type, PyObject *pyfloat) +{ + PyObject *return_value = NULL; + + return_value = _decimal_Decimal_from_float_impl((PyTypeObject *)type, pyfloat); + + return return_value; +} + +PyDoc_STRVAR(_decimal_Decimal_from_number__doc__, +"from_number($type, number, /)\n" +"--\n" +"\n" +"Class method that converts a real number to a decimal number, exactly.\n" +"\n" +" >>> Decimal.from_number(314) # int\n" +" Decimal(\'314\')\n" +" >>> Decimal.from_number(0.1) # float\n" +" Decimal(\'0.1000000000000000055511151231257827021181583404541015625\')\n" +" >>> Decimal.from_number(Decimal(\'3.14\')) # another decimal instance\n" +" Decimal(\'3.14\')"); + +#define _DECIMAL_DECIMAL_FROM_NUMBER_METHODDEF \ + {"from_number", (PyCFunction)_decimal_Decimal_from_number, METH_O|METH_CLASS, _decimal_Decimal_from_number__doc__}, + +static PyObject * +_decimal_Decimal_from_number_impl(PyTypeObject *type, PyObject *number); + +static PyObject * +_decimal_Decimal_from_number(PyObject *type, PyObject *number) +{ + PyObject *return_value = NULL; + + return_value = _decimal_Decimal_from_number_impl((PyTypeObject *)type, number); + + return return_value; +} + +PyDoc_STRVAR(_decimal_Decimal_as_integer_ratio__doc__, +"as_integer_ratio($self, /)\n" +"--\n" +"\n" +"Return a pair of integers whose ratio is exactly equal to the original.\n" +"\n" +"The ratio is in lowest terms and with a positive denominator.\n" +"Raise OverflowError on infinities and a ValueError on NaNs."); + +#define _DECIMAL_DECIMAL_AS_INTEGER_RATIO_METHODDEF \ + {"as_integer_ratio", (PyCFunction)_decimal_Decimal_as_integer_ratio, METH_NOARGS, _decimal_Decimal_as_integer_ratio__doc__}, + +static PyObject * +_decimal_Decimal_as_integer_ratio_impl(PyObject *self); + +static PyObject * +_decimal_Decimal_as_integer_ratio(PyObject *self, PyObject *Py_UNUSED(ignored)) +{ + return _decimal_Decimal_as_integer_ratio_impl(self); +} + +PyDoc_STRVAR(_decimal_Decimal_to_integral_value__doc__, +"to_integral_value($self, /, rounding=None, context=None)\n" +"--\n" +"\n" +"Round to the nearest integer without signaling Inexact or Rounded.\n" +"\n" +"The rounding mode is determined by the rounding parameter if given,\n" +"else by the given context. If neither parameter is given, then the\n" +"rounding mode of the current default context is used."); + +#define _DECIMAL_DECIMAL_TO_INTEGRAL_VALUE_METHODDEF \ + {"to_integral_value", _PyCFunction_CAST(_decimal_Decimal_to_integral_value), METH_FASTCALL|METH_KEYWORDS, _decimal_Decimal_to_integral_value__doc__}, + +static PyObject * +_decimal_Decimal_to_integral_value_impl(PyObject *self, PyObject *rounding, + PyObject *context); + +static PyObject * +_decimal_Decimal_to_integral_value(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(rounding), &_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[] = {"rounding", "context", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "to_integral_value", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[2]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0; + PyObject *rounding = Py_None; + PyObject *context = Py_None; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, + /*minpos*/ 0, /*maxpos*/ 2, /*minkw*/ 0, /*varpos*/ 0, argsbuf); + if (!args) { + goto exit; + } + if (!noptargs) { + goto skip_optional_pos; + } + if (args[0]) { + rounding = args[0]; + if (!--noptargs) { + goto skip_optional_pos; + } + } + context = args[1]; +skip_optional_pos: + return_value = _decimal_Decimal_to_integral_value_impl(self, rounding, context); + +exit: + return return_value; +} + +PyDoc_STRVAR(_decimal_Decimal_to_integral__doc__, +"to_integral($self, /, rounding=None, context=None)\n" +"--\n" +"\n" +"Identical to the to_integral_value() method.\n" +"\n" +"The to_integral() name has been kept for compatibility with older\n" +"versions."); + +#define _DECIMAL_DECIMAL_TO_INTEGRAL_METHODDEF \ + {"to_integral", _PyCFunction_CAST(_decimal_Decimal_to_integral), METH_FASTCALL|METH_KEYWORDS, _decimal_Decimal_to_integral__doc__}, + +static PyObject * +_decimal_Decimal_to_integral_impl(PyObject *self, PyObject *rounding, + PyObject *context); + +static PyObject * +_decimal_Decimal_to_integral(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(rounding), &_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[] = {"rounding", "context", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "to_integral", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[2]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0; + PyObject *rounding = Py_None; + PyObject *context = Py_None; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, + /*minpos*/ 0, /*maxpos*/ 2, /*minkw*/ 0, /*varpos*/ 0, argsbuf); + if (!args) { + goto exit; + } + if (!noptargs) { + goto skip_optional_pos; + } + if (args[0]) { + rounding = args[0]; + if (!--noptargs) { + goto skip_optional_pos; + } + } + context = args[1]; +skip_optional_pos: + return_value = _decimal_Decimal_to_integral_impl(self, rounding, context); + +exit: + return return_value; +} + +PyDoc_STRVAR(_decimal_Decimal_to_integral_exact__doc__, +"to_integral_exact($self, /, rounding=None, context=None)\n" +"--\n" +"\n" +"Round to the nearest integer.\n" +"\n" +"Decimal.to_integral_exact() signals Inexact or Rounded as appropriate\n" +"if rounding occurs. The rounding mode is determined by the rounding\n" +"parameter if given, else by the given context. If neither parameter is\n" +"given, then the rounding mode of the current default context is used."); + +#define _DECIMAL_DECIMAL_TO_INTEGRAL_EXACT_METHODDEF \ + {"to_integral_exact", _PyCFunction_CAST(_decimal_Decimal_to_integral_exact), METH_FASTCALL|METH_KEYWORDS, _decimal_Decimal_to_integral_exact__doc__}, + +static PyObject * +_decimal_Decimal_to_integral_exact_impl(PyObject *self, PyObject *rounding, + PyObject *context); + +static PyObject * +_decimal_Decimal_to_integral_exact(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(rounding), &_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[] = {"rounding", "context", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "to_integral_exact", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[2]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0; + PyObject *rounding = Py_None; + PyObject *context = Py_None; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, + /*minpos*/ 0, /*maxpos*/ 2, /*minkw*/ 0, /*varpos*/ 0, argsbuf); + if (!args) { + goto exit; + } + if (!noptargs) { + goto skip_optional_pos; + } + if (args[0]) { + rounding = args[0]; + if (!--noptargs) { + goto skip_optional_pos; + } + } + context = args[1]; +skip_optional_pos: + return_value = _decimal_Decimal_to_integral_exact_impl(self, rounding, context); + +exit: + return return_value; +} + +PyDoc_STRVAR(_decimal_Decimal_as_tuple__doc__, +"as_tuple($self, /)\n" +"--\n" +"\n" +"Return a tuple representation of the number."); + +#define _DECIMAL_DECIMAL_AS_TUPLE_METHODDEF \ + {"as_tuple", (PyCFunction)_decimal_Decimal_as_tuple, METH_NOARGS, _decimal_Decimal_as_tuple__doc__}, + +static PyObject * +_decimal_Decimal_as_tuple_impl(PyObject *self); + +static PyObject * +_decimal_Decimal_as_tuple(PyObject *self, PyObject *Py_UNUSED(ignored)) +{ + return _decimal_Decimal_as_tuple_impl(self); +} + +PyDoc_STRVAR(_decimal_Decimal_adjusted__doc__, +"adjusted($self, /)\n" +"--\n" +"\n" +"Return the adjusted exponent (exp + digits - 1) of the number."); + +#define _DECIMAL_DECIMAL_ADJUSTED_METHODDEF \ + {"adjusted", (PyCFunction)_decimal_Decimal_adjusted, METH_NOARGS, _decimal_Decimal_adjusted__doc__}, + +static PyObject * +_decimal_Decimal_adjusted_impl(PyObject *self); + +static PyObject * +_decimal_Decimal_adjusted(PyObject *self, PyObject *Py_UNUSED(ignored)) +{ + return _decimal_Decimal_adjusted_impl(self); +} + +PyDoc_STRVAR(_decimal_Decimal_canonical__doc__, +"canonical($self, /)\n" +"--\n" +"\n" +"Return the canonical encoding of the argument.\n" +"\n" +"Currently, the encoding of a Decimal instance is always canonical,\n" +"so this operation returns its argument unchanged."); + +#define _DECIMAL_DECIMAL_CANONICAL_METHODDEF \ + {"canonical", (PyCFunction)_decimal_Decimal_canonical, METH_NOARGS, _decimal_Decimal_canonical__doc__}, + +static PyObject * +_decimal_Decimal_canonical_impl(PyObject *self); + +static PyObject * +_decimal_Decimal_canonical(PyObject *self, PyObject *Py_UNUSED(ignored)) +{ + return _decimal_Decimal_canonical_impl(self); +} + +PyDoc_STRVAR(_decimal_Decimal_conjugate__doc__, +"conjugate($self, /)\n" +"--\n" +"\n" +"Return self."); + +#define _DECIMAL_DECIMAL_CONJUGATE_METHODDEF \ + {"conjugate", (PyCFunction)_decimal_Decimal_conjugate, METH_NOARGS, _decimal_Decimal_conjugate__doc__}, + +static PyObject * +_decimal_Decimal_conjugate_impl(PyObject *self); + +static PyObject * +_decimal_Decimal_conjugate(PyObject *self, PyObject *Py_UNUSED(ignored)) +{ + return _decimal_Decimal_conjugate_impl(self); +} + +PyDoc_STRVAR(_decimal_Decimal_radix__doc__, +"radix($self, /)\n" +"--\n" +"\n" +"Return Decimal(10).\n" +"\n" +"This is the radix (base) in which the Decimal class does\n" +"all its arithmetic. Included for compatibility with the specification."); + +#define _DECIMAL_DECIMAL_RADIX_METHODDEF \ + {"radix", (PyCFunction)_decimal_Decimal_radix, METH_NOARGS, _decimal_Decimal_radix__doc__}, + +static PyObject * +_decimal_Decimal_radix_impl(PyObject *self); + +static PyObject * +_decimal_Decimal_radix(PyObject *self, PyObject *Py_UNUSED(ignored)) +{ + return _decimal_Decimal_radix_impl(self); +} + +PyDoc_STRVAR(_decimal_Decimal_copy_abs__doc__, +"copy_abs($self, /)\n" +"--\n" +"\n" +"Return the absolute value of the argument.\n" +"\n" +"This operation is unaffected by context and is quiet: no flags are\n" +"changed and no rounding is performed."); + +#define _DECIMAL_DECIMAL_COPY_ABS_METHODDEF \ + {"copy_abs", (PyCFunction)_decimal_Decimal_copy_abs, METH_NOARGS, _decimal_Decimal_copy_abs__doc__}, + +static PyObject * +_decimal_Decimal_copy_abs_impl(PyObject *self); + +static PyObject * +_decimal_Decimal_copy_abs(PyObject *self, PyObject *Py_UNUSED(ignored)) +{ + return _decimal_Decimal_copy_abs_impl(self); +} + +PyDoc_STRVAR(_decimal_Decimal_copy_negate__doc__, +"copy_negate($self, /)\n" +"--\n" +"\n" +"Return the negation of the argument.\n" +"\n" +"This operation is unaffected by context and is quiet: no flags are\n" +"changed and no rounding is performed."); + +#define _DECIMAL_DECIMAL_COPY_NEGATE_METHODDEF \ + {"copy_negate", (PyCFunction)_decimal_Decimal_copy_negate, METH_NOARGS, _decimal_Decimal_copy_negate__doc__}, + +static PyObject * +_decimal_Decimal_copy_negate_impl(PyObject *self); + +static PyObject * +_decimal_Decimal_copy_negate(PyObject *self, PyObject *Py_UNUSED(ignored)) +{ + return _decimal_Decimal_copy_negate_impl(self); +} + +PyDoc_STRVAR(_decimal_Decimal_number_class__doc__, +"number_class($self, /, context=None)\n" +"--\n" +"\n" +"Return a string describing the class of the operand.\n" +"\n" +"The returned value is one of the following ten strings:\n" +"\n" +" * \'-Infinity\', indicating that the operand is negative infinity.\n" +" * \'-Normal\', indicating that the operand is a negative normal\n" +" number.\n" +" * \'-Subnormal\', indicating that the operand is negative and\n" +" subnormal.\n" +" * \'-Zero\', indicating that the operand is a negative zero.\n" +" * \'+Zero\', indicating that the operand is a positive zero.\n" +" * \'+Subnormal\', indicating that the operand is positive and\n" +" subnormal.\n" +" * \'+Normal\', indicating that the operand is a positive normal\n" +" number.\n" +" * \'+Infinity\', indicating that the operand is positive infinity.\n" +" * \'NaN\', indicating that the operand is a quiet NaN (Not a Number).\n" +" * \'sNaN\', indicating that the operand is a signaling NaN."); + +#define _DECIMAL_DECIMAL_NUMBER_CLASS_METHODDEF \ + {"number_class", _PyCFunction_CAST(_decimal_Decimal_number_class), METH_FASTCALL|METH_KEYWORDS, _decimal_Decimal_number_class__doc__}, + +static PyObject * +_decimal_Decimal_number_class_impl(PyObject *self, PyObject *context); + +static PyObject * +_decimal_Decimal_number_class(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 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(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[] = {"context", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "number_class", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[1]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0; + PyObject *context = Py_None; + + 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; + } + context = args[0]; +skip_optional_pos: + return_value = _decimal_Decimal_number_class_impl(self, context); + +exit: + return return_value; +} + +PyDoc_STRVAR(_decimal_Decimal_to_eng_string__doc__, +"to_eng_string($self, /, context=None)\n" +"--\n" +"\n" +"Convert to an engineering-type string.\n" +"\n" +"Engineering notation has an exponent which is a multiple of 3, so there\n" +"are up to 3 digits left of the decimal place. For example,\n" +"Decimal(\'123E+1\') is converted to Decimal(\'1.23E+3\').\n" +"\n" +"The value of context.capitals determines whether the exponent sign is\n" +"lower or upper case. Otherwise, the context does not affect the\n" +"operation."); + +#define _DECIMAL_DECIMAL_TO_ENG_STRING_METHODDEF \ + {"to_eng_string", _PyCFunction_CAST(_decimal_Decimal_to_eng_string), METH_FASTCALL|METH_KEYWORDS, _decimal_Decimal_to_eng_string__doc__}, + +static PyObject * +_decimal_Decimal_to_eng_string_impl(PyObject *self, PyObject *context); + +static PyObject * +_decimal_Decimal_to_eng_string(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 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(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[] = {"context", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "to_eng_string", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[1]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0; + PyObject *context = Py_None; + + 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; + } + context = args[0]; +skip_optional_pos: + return_value = _decimal_Decimal_to_eng_string_impl(self, context); + +exit: + return return_value; +} + +PyDoc_STRVAR(_decimal_Decimal_copy_sign__doc__, +"copy_sign($self, /, other, context=None)\n" +"--\n" +"\n" +"Return a copy of *self* with the sign of *other*.\n" +"\n" +"For example:\n" +"\n" +" >>> Decimal(\'2.3\').copy_sign(Decimal(\'-1.5\'))\n" +" Decimal(\'-2.3\')\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_COPY_SIGN_METHODDEF \ + {"copy_sign", _PyCFunction_CAST(_decimal_Decimal_copy_sign), METH_FASTCALL|METH_KEYWORDS, _decimal_Decimal_copy_sign__doc__}, + +static PyObject * +_decimal_Decimal_copy_sign_impl(PyObject *self, PyObject *other, + PyObject *context); + +static PyObject * +_decimal_Decimal_copy_sign(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 = "copy_sign", + .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_copy_sign_impl(self, other, context); + +exit: + return return_value; +} + +PyDoc_STRVAR(_decimal_Decimal_same_quantum__doc__, +"same_quantum($self, /, other, context=None)\n" +"--\n" +"\n" +"Test whether self and other have the same exponent or both are NaN.\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_SAME_QUANTUM_METHODDEF \ + {"same_quantum", _PyCFunction_CAST(_decimal_Decimal_same_quantum), METH_FASTCALL|METH_KEYWORDS, _decimal_Decimal_same_quantum__doc__}, + +static PyObject * +_decimal_Decimal_same_quantum_impl(PyObject *self, PyObject *other, + PyObject *context); + +static PyObject * +_decimal_Decimal_same_quantum(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 = "same_quantum", + .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_same_quantum_impl(self, other, context); + +exit: + return return_value; +} + +PyDoc_STRVAR(_decimal_Decimal_quantize__doc__, +"quantize($self, /, exp, rounding=None, context=None)\n" +"--\n" +"\n" +"Quantize *self* so its exponent is the same as that of *exp*.\n" +"\n" +"Return a value equal to *self* after rounding, with the exponent\n" +"of *exp*.\n" +"\n" +" >>> Decimal(\'1.41421356\').quantize(Decimal(\'1.000\'))\n" +" Decimal(\'1.414\')\n" +"\n" +"Unlike other operations, if the length of the coefficient after the\n" +"quantize operation would be greater than precision, then an\n" +"InvalidOperation is signaled. This guarantees that, unless there\n" +"is an error condition, the quantized exponent is always equal to\n" +"that of the right-hand operand.\n" +"\n" +"Also unlike other operations, quantize never signals Underflow, even\n" +"if the result is subnormal and inexact.\n" +"\n" +"If the exponent of the second operand is larger than that of the first,\n" +"then rounding may be necessary. In this case, the rounding mode is\n" +"determined by the rounding argument if given, else by the given context\n" +"argument; if neither argument is given, the rounding mode of the\n" +"current thread\'s context is used."); + +#define _DECIMAL_DECIMAL_QUANTIZE_METHODDEF \ + {"quantize", _PyCFunction_CAST(_decimal_Decimal_quantize), METH_FASTCALL|METH_KEYWORDS, _decimal_Decimal_quantize__doc__}, + +static PyObject * +_decimal_Decimal_quantize_impl(PyObject *self, PyObject *w, + PyObject *rounding, PyObject *context); + +static PyObject * +_decimal_Decimal_quantize(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 3 + 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(exp), &_Py_ID(rounding), &_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[] = {"exp", "rounding", "context", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "quantize", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[3]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; + PyObject *w; + PyObject *rounding = Py_None; + PyObject *context = Py_None; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, + /*minpos*/ 1, /*maxpos*/ 3, /*minkw*/ 0, /*varpos*/ 0, argsbuf); + if (!args) { + goto exit; + } + w = args[0]; + if (!noptargs) { + goto skip_optional_pos; + } + if (args[1]) { + rounding = args[1]; + if (!--noptargs) { + goto skip_optional_pos; + } + } + context = args[2]; +skip_optional_pos: + return_value = _decimal_Decimal_quantize_impl(self, w, rounding, context); + +exit: + return return_value; +} +/*[clinic end generated code: output=f33166d1bf53e613 input=a9049054013a1b77]*/ diff --git a/Modules/_decimal/docstrings.h b/Modules/_decimal/docstrings.h index 77017a92252cb8..bd1c1d5295d717 100644 --- a/Modules/_decimal/docstrings.h +++ b/Modules/_decimal/docstrings.h @@ -57,32 +57,6 @@ context does not affect the conversion and is only passed to determine if\n\ the InvalidOperation trap is active.\n\ \n"); -PyDoc_STRVAR(doc_adjusted, -"adjusted($self, /)\n--\n\n\ -Return the adjusted exponent of the number. Defined as exp + digits - 1.\n\ -\n"); - -PyDoc_STRVAR(doc_as_tuple, -"as_tuple($self, /)\n--\n\n\ -Return a tuple representation of the number.\n\ -\n"); - -PyDoc_STRVAR(doc_as_integer_ratio, -"as_integer_ratio($self, /)\n--\n\n\ -Decimal.as_integer_ratio() -> (int, int)\n\ -\n\ -Return a pair of integers, whose ratio is exactly equal to the original\n\ -Decimal and with a positive denominator. The ratio is in lowest terms.\n\ -Raise OverflowError on infinities and a ValueError on NaNs.\n\ -\n"); - -PyDoc_STRVAR(doc_canonical, -"canonical($self, /)\n--\n\n\ -Return the canonical encoding of the argument. Currently, the encoding\n\ -of a Decimal instance is always canonical, so this operation returns its\n\ -argument unchanged.\n\ -\n"); - PyDoc_STRVAR(doc_compare, "compare($self, /, other, context=None)\n--\n\n\ Compare self to other. Return a decimal value:\n\ @@ -132,36 +106,6 @@ 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_conjugate, -"conjugate($self, /)\n--\n\n\ -Return self.\n\ -\n"); - -PyDoc_STRVAR(doc_copy_abs, -"copy_abs($self, /)\n--\n\n\ -Return the absolute value of the argument. This operation is unaffected by\n\ -context and is quiet: no flags are changed and no rounding is performed.\n\ -\n"); - -PyDoc_STRVAR(doc_copy_negate, -"copy_negate($self, /)\n--\n\n\ -Return the negation of the argument. This operation is unaffected by context\n\ -and is quiet: no flags are changed and no rounding is performed.\n\ -\n"); - -PyDoc_STRVAR(doc_copy_sign, -"copy_sign($self, /, other, context=None)\n--\n\n\ -Return a copy of the first operand with the sign set to be the same as the\n\ -sign of the second operand. For example:\n\ -\n\ - >>> Decimal('2.3').copy_sign(Decimal('-1.5'))\n\ - Decimal('-2.3')\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_exp, "exp($self, /, context=None)\n--\n\n\ Return the value of the (natural) exponential function e**x at the given\n\ @@ -169,36 +113,6 @@ number. The function always uses the ROUND_HALF_EVEN mode and the result\n\ is correctly rounded.\n\ \n"); -PyDoc_STRVAR(doc_from_float, -"from_float($type, f, /)\n--\n\n\ -Class method that converts a float to a decimal number, exactly.\n\ -Since 0.1 is not exactly representable in binary floating point,\n\ -Decimal.from_float(0.1) is not the same as Decimal('0.1').\n\ -\n\ - >>> Decimal.from_float(0.1)\n\ - Decimal('0.1000000000000000055511151231257827021181583404541015625')\n\ - >>> Decimal.from_float(float('nan'))\n\ - Decimal('NaN')\n\ - >>> Decimal.from_float(float('inf'))\n\ - Decimal('Infinity')\n\ - >>> Decimal.from_float(float('-inf'))\n\ - Decimal('-Infinity')\n\ -\n\ -\n"); - -PyDoc_STRVAR(doc_from_number, -"from_number($type, number, /)\n--\n\n\ -Class method that converts a real number to a decimal number, exactly.\n\ -\n\ - >>> Decimal.from_number(314) # int\n\ - Decimal('314')\n\ - >>> Decimal.from_number(0.1) # float\n\ - Decimal('0.1000000000000000055511151231257827021181583404541015625')\n\ - >>> Decimal.from_number(Decimal('3.14')) # another decimal instance\n\ - Decimal('3.14')\n\ -\n\ -\n"); - PyDoc_STRVAR(doc_fma, "fma($self, /, other, third, context=None)\n--\n\n\ Fused multiply-add. Return self*other+third with no rounding of the\n\ @@ -365,52 +279,6 @@ For example, Decimal('32.100') and Decimal('0.321000e+2') both normalize\n\ to the equivalent value Decimal('32.1').\n\ \n"); -PyDoc_STRVAR(doc_number_class, -"number_class($self, /, context=None)\n--\n\n\ -Return a string describing the class of the operand. The returned value\n\ -is one of the following ten strings:\n\ -\n\ - * '-Infinity', indicating that the operand is negative infinity.\n\ - * '-Normal', indicating that the operand is a negative normal number.\n\ - * '-Subnormal', indicating that the operand is negative and subnormal.\n\ - * '-Zero', indicating that the operand is a negative zero.\n\ - * '+Zero', indicating that the operand is a positive zero.\n\ - * '+Subnormal', indicating that the operand is positive and subnormal.\n\ - * '+Normal', indicating that the operand is a positive normal number.\n\ - * '+Infinity', indicating that the operand is positive infinity.\n\ - * 'NaN', indicating that the operand is a quiet NaN (Not a Number).\n\ - * 'sNaN', indicating that the operand is a signaling NaN.\n\ -\n\ -\n"); - -PyDoc_STRVAR(doc_quantize, -"quantize($self, /, exp, rounding=None, context=None)\n--\n\n\ -Return a value equal to the first operand after rounding and having the\n\ -exponent of the second operand.\n\ -\n\ - >>> Decimal('1.41421356').quantize(Decimal('1.000'))\n\ - Decimal('1.414')\n\ -\n\ -Unlike other operations, if the length of the coefficient after the quantize\n\ -operation would be greater than precision, then an InvalidOperation is signaled.\n\ -This guarantees that, unless there is an error condition, the quantized exponent\n\ -is always equal to that of the right-hand operand.\n\ -\n\ -Also unlike other operations, quantize never signals Underflow, even if the\n\ -result is subnormal and inexact.\n\ -\n\ -If the exponent of the second operand is larger than that of the first, then\n\ -rounding may be necessary. In this case, the rounding mode is determined by the\n\ -rounding argument if given, else by the given context argument; if neither\n\ -argument is given, the rounding mode of the current thread's context is used.\n\ -\n"); - -PyDoc_STRVAR(doc_radix, -"radix($self, /)\n--\n\n\ -Return Decimal(10), the radix (base) in which the Decimal class does\n\ -all its arithmetic. Included for compatibility with the specification.\n\ -\n"); - PyDoc_STRVAR(doc_remainder_near, "remainder_near($self, /, other, context=None)\n--\n\n\ Return the remainder from dividing self by other. This differs from\n\ @@ -434,15 +302,6 @@ length precision if necessary. The sign and exponent of the first operand are\n\ unchanged.\n\ \n"); -PyDoc_STRVAR(doc_same_quantum, -"same_quantum($self, /, other, context=None)\n--\n\n\ -Test whether self and other have the same exponent or whether both are NaN.\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_scaleb, "scaleb($self, /, other, context=None)\n--\n\n\ Return the first operand with the exponent adjusted the second. Equivalently,\n\ @@ -467,38 +326,6 @@ Return the square root of the argument to full precision. The result is\n\ correctly rounded using the ROUND_HALF_EVEN rounding mode.\n\ \n"); -PyDoc_STRVAR(doc_to_eng_string, -"to_eng_string($self, /, context=None)\n--\n\n\ -Convert to an engineering-type string. Engineering notation has an exponent\n\ -which is a multiple of 3, so there are up to 3 digits left of the decimal\n\ -place. For example, Decimal('123E+1') is converted to Decimal('1.23E+3').\n\ -\n\ -The value of context.capitals determines whether the exponent sign is lower\n\ -or upper case. Otherwise, the context does not affect the operation.\n\ -\n"); - -PyDoc_STRVAR(doc_to_integral, -"to_integral($self, /, rounding=None, context=None)\n--\n\n\ -Identical to the to_integral_value() method. The to_integral() name has been\n\ -kept for compatibility with older versions.\n\ -\n"); - -PyDoc_STRVAR(doc_to_integral_exact, -"to_integral_exact($self, /, rounding=None, context=None)\n--\n\n\ -Round to the nearest integer, signaling Inexact or Rounded as appropriate if\n\ -rounding occurs. The rounding mode is determined by the rounding parameter\n\ -if given, else by the given context. If neither parameter is given, then the\n\ -rounding mode of the current default context is used.\n\ -\n"); - -PyDoc_STRVAR(doc_to_integral_value, -"to_integral_value($self, /, rounding=None, context=None)\n--\n\n\ -Round to the nearest integer without signaling Inexact or Rounded. The\n\ -rounding mode is determined by the rounding parameter if given, else by\n\ -the given context. If neither parameter is given, then the rounding mode\n\ -of the current default context is used.\n\ -\n"); - /******************************************************************************/ /* Context Object and Methods */