https://github.com/python/cpython/commit/70730ad0414e4661d2e94710d865edf1f7f164a1
commit: 70730ad0414e4661d2e94710d865edf1f7f164a1
branch: main
author: Sergey B Kirpichev <skirpic...@gmail.com>
committer: vstinner <vstin...@python.org>
date: 2025-08-13T14:41:57+02:00
summary:

gh-73487: Convert `_decimal` to use Argument Clinic (part 1) (#137606)

Co-authored-by: Adam Turner <9087854+aa-tur...@users.noreply.github.com>

files:
A Misc/NEWS.d/next/Library/2025-08-13-10-50-22.gh-issue-73487.DUHbBq.rst
A Modules/_decimal/clinic/_decimal.c.h
M Include/internal/pycore_global_objects_fini_generated.h
M Include/internal/pycore_global_strings.h
M Include/internal/pycore_runtime_init_generated.h
M Include/internal/pycore_unicodeobject_generated.h
M Modules/_decimal/_decimal.c
M Modules/_decimal/docstrings.h

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                           
*/

_______________________________________________
Python-checkins mailing list -- python-checkins@python.org
To unsubscribe send an email to python-checkins-le...@python.org
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: arch...@mail-archive.com

Reply via email to