diff --git a/Lib/_pydecimal.py b/Lib/_pydecimal.py index 9b8e42a2342536..97a629fe92ccec 100644 --- a/Lib/_pydecimal.py +++ b/Lib/_pydecimal.py @@ -3340,7 +3340,10 @@ def _fill_logical(self, context, opa, opb): return opa, opb def logical_and(self, other, context=None): - """Applies an 'and' operation between self and other's digits.""" + """Applies an 'and' operation between self and other's digits. + + Both self and other must be logical numbers. + """ if context is None: context = getcontext() @@ -3357,14 +3360,20 @@ def logical_and(self, other, context=None): return _dec_from_triple(0, result.lstrip('0') or '0', 0) def logical_invert(self, context=None): - """Invert all its digits.""" + """Invert all its digits. + + The self must be logical number. + """ if context is None: context = getcontext() return self.logical_xor(_dec_from_triple(0,'1'*context.prec,0), context) def logical_or(self, other, context=None): - """Applies an 'or' operation between self and other's digits.""" + """Applies an 'or' operation between self and other's digits. + + Both self and other must be logical numbers. + """ if context is None: context = getcontext() @@ -3381,7 +3390,10 @@ def logical_or(self, other, context=None): return _dec_from_triple(0, result.lstrip('0') or '0', 0) def logical_xor(self, other, context=None): - """Applies an 'xor' operation between self and other's digits.""" + """Applies an 'xor' operation between self and other's digits. + + Both self and other must be logical numbers. + """ if context is None: context = getcontext() diff --git a/Misc/NEWS.d/next/Library/2023-03-21-10-59-40.gh-issue-102431.eUDnf4.rst b/Misc/NEWS.d/next/Library/2023-03-21-10-59-40.gh-issue-102431.eUDnf4.rst new file mode 100644 index 00000000000000..e82ddb6e1011ad --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-03-21-10-59-40.gh-issue-102431.eUDnf4.rst @@ -0,0 +1,2 @@ +Clarify constraints for "logical" arguments in methods of +:class:`decimal.Context`. diff --git a/Modules/_decimal/_decimal.c b/Modules/_decimal/_decimal.c index 04b6695f8af06a..4e2a4953126360 100644 --- a/Modules/_decimal/_decimal.c +++ b/Modules/_decimal/_decimal.c @@ -5235,13 +5235,15 @@ _decimal_Decimal_copy_negate_impl(PyObject *self, PyTypeObject *cls) /*[clinic input] _decimal.Decimal.logical_invert = _decimal.Decimal.exp -Return the digit-wise inversion of the (logical) operand. +Invert all its digits. + +The self must be logical number. [clinic start generated code]*/ static PyObject * _decimal_Decimal_logical_invert_impl(PyObject *self, PyTypeObject *cls, PyObject *context) -/*[clinic end generated code: output=c626ed4b104a97b7 input=3531dac8b9548dad]*/ +/*[clinic end generated code: output=c626ed4b104a97b7 input=7158d5b525417955]*/ Dec_UnaryFuncVA(mpd_qinvert) /*[clinic input] @@ -5471,37 +5473,43 @@ _decimal_Decimal_same_quantum_impl(PyObject *self, PyTypeObject *cls, /*[clinic input] _decimal.Decimal.logical_and = _decimal.Decimal.compare -Return the digit-wise 'and' of the two (logical) operands. +Applies an 'and' operation between self and other's digits. + +Both self and other must be logical numbers. [clinic start generated code]*/ static PyObject * _decimal_Decimal_logical_and_impl(PyObject *self, PyTypeObject *cls, PyObject *other, PyObject *context) -/*[clinic end generated code: output=9a4cbb74c180b0bb input=2b319baee8970929]*/ +/*[clinic end generated code: output=9a4cbb74c180b0bb input=f22460f1285782d2]*/ Dec_BinaryFuncVA(mpd_qand) /*[clinic input] _decimal.Decimal.logical_or = _decimal.Decimal.compare -Return the digit-wise 'or' of the two (logical) operands. +Applies an 'or' operation between self and other's digits. + +Both self and other must be logical numbers. [clinic start generated code]*/ static PyObject * _decimal_Decimal_logical_or_impl(PyObject *self, PyTypeObject *cls, PyObject *other, PyObject *context) -/*[clinic end generated code: output=063c4de18dc41ecb input=75e0e1d4dd373b90]*/ +/*[clinic end generated code: output=063c4de18dc41ecb input=b5afa1e1fdebdfce]*/ Dec_BinaryFuncVA(mpd_qor) /*[clinic input] _decimal.Decimal.logical_xor = _decimal.Decimal.compare -Return the digit-wise 'xor' of the two (logical) operands. +Applies an 'xor' operation between self and other's digits. + +Both self and other must be logical numbers. [clinic start generated code]*/ static PyObject * _decimal_Decimal_logical_xor_impl(PyObject *self, PyTypeObject *cls, PyObject *other, PyObject *context) -/*[clinic end generated code: output=829b09cb49926ad7 input=a1ed8d6ac38c1c9e]*/ +/*[clinic end generated code: output=829b09cb49926ad7 input=84d722ada08a2da7]*/ Dec_BinaryFuncVA(mpd_qxor) /*[clinic input] @@ -7099,13 +7107,26 @@ DecCtx_UnaryFunc(mpd_qlogb) /*[clinic input] _decimal.Context.logical_invert = _decimal.Context.abs -Invert all digits of x. +Invert all the digits in the operand. + +The operand must be a logical number. + + >>> ExtendedContext.logical_invert(Decimal('0')) + Decimal('111111111') + >>> ExtendedContext.logical_invert(Decimal('1')) + Decimal('111111110') + >>> ExtendedContext.logical_invert(Decimal('111111111')) + Decimal('0') + >>> ExtendedContext.logical_invert(Decimal('101010101')) + Decimal('10101010') + >>> ExtendedContext.logical_invert(1101) + Decimal('111110010') [clinic start generated code]*/ static PyObject * _decimal_Context_logical_invert_impl(PyObject *context, PyTypeObject *cls, PyObject *x) -/*[clinic end generated code: output=97760277a958e2b0 input=1fa8dcc59c557fcc]*/ +/*[clinic end generated code: output=97760277a958e2b0 input=8e568f4c745ab596]*/ DecCtx_UnaryFunc(mpd_qinvert) /*[clinic input] @@ -7262,37 +7283,100 @@ _decimal_Context_copy_sign_impl(PyObject *context, PyTypeObject *cls, /*[clinic input] _decimal.Context.logical_and = _decimal.Context.add -Digit-wise and of x and y. +Applies the logical operation 'and' between each operand's digits. + +The operands must be both logical numbers. + + >>> ExtendedContext.logical_and(Decimal('0'), Decimal('0')) + Decimal('0') + >>> ExtendedContext.logical_and(Decimal('0'), Decimal('1')) + Decimal('0') + >>> ExtendedContext.logical_and(Decimal('1'), Decimal('0')) + Decimal('0') + >>> ExtendedContext.logical_and(Decimal('1'), Decimal('1')) + Decimal('1') + >>> ExtendedContext.logical_and(Decimal('1100'), Decimal('1010')) + Decimal('1000') + >>> ExtendedContext.logical_and(Decimal('1111'), Decimal('10')) + Decimal('10') + >>> ExtendedContext.logical_and(110, 1101) + Decimal('100') + >>> ExtendedContext.logical_and(Decimal(110), 1101) + Decimal('100') + >>> ExtendedContext.logical_and(110, Decimal(1101)) + Decimal('100') [clinic start generated code]*/ static PyObject * _decimal_Context_logical_and_impl(PyObject *context, PyTypeObject *cls, PyObject *x, PyObject *y) -/*[clinic end generated code: output=009dfa08ecaa2ac8 input=30ee33b5b365fd80]*/ +/*[clinic end generated code: output=009dfa08ecaa2ac8 input=bcb7d3d6ab7530de]*/ DecCtx_BinaryFunc(mpd_qand) /*[clinic input] _decimal.Context.logical_or = _decimal.Context.add -Digit-wise or of x and y. +Applies the logical operation 'or' between each operand's digits. + +The operands must be both logical numbers. + + >>> ExtendedContext.logical_or(Decimal('0'), Decimal('0')) + Decimal('0') + >>> ExtendedContext.logical_or(Decimal('0'), Decimal('1')) + Decimal('1') + >>> ExtendedContext.logical_or(Decimal('1'), Decimal('0')) + Decimal('1') + >>> ExtendedContext.logical_or(Decimal('1'), Decimal('1')) + Decimal('1') + >>> ExtendedContext.logical_or(Decimal('1100'), Decimal('1010')) + Decimal('1110') + >>> ExtendedContext.logical_or(Decimal('1110'), Decimal('10')) + Decimal('1110') + >>> ExtendedContext.logical_or(110, 1101) + Decimal('1111') + >>> ExtendedContext.logical_or(Decimal(110), 1101) + Decimal('1111') + >>> ExtendedContext.logical_or(110, Decimal(1101)) + Decimal('1111') [clinic start generated code]*/ static PyObject * _decimal_Context_logical_or_impl(PyObject *context, PyTypeObject *cls, PyObject *x, PyObject *y) -/*[clinic end generated code: output=eb38617e8d31bf12 input=3b1a6725d0262fb9]*/ +/*[clinic end generated code: output=eb38617e8d31bf12 input=47b45d296fb90846]*/ DecCtx_BinaryFunc(mpd_qor) /*[clinic input] _decimal.Context.logical_xor = _decimal.Context.add -Digit-wise xor of x and y. +Applies the logical operation 'xor' between each operand's digits. + +The operands must be both logical numbers. + + >>> ExtendedContext.logical_xor(Decimal('0'), Decimal('0')) + Decimal('0') + >>> ExtendedContext.logical_xor(Decimal('0'), Decimal('1')) + Decimal('1') + >>> ExtendedContext.logical_xor(Decimal('1'), Decimal('0')) + Decimal('1') + >>> ExtendedContext.logical_xor(Decimal('1'), Decimal('1')) + Decimal('0') + >>> ExtendedContext.logical_xor(Decimal('1100'), Decimal('1010')) + Decimal('110') + >>> ExtendedContext.logical_xor(Decimal('1111'), Decimal('10')) + Decimal('1101') + >>> ExtendedContext.logical_xor(110, 1101) + Decimal('1011') + >>> ExtendedContext.logical_xor(Decimal(110), 1101) + Decimal('1011') + >>> ExtendedContext.logical_xor(110, Decimal(1101)) + Decimal('1011') [clinic start generated code]*/ static PyObject * _decimal_Context_logical_xor_impl(PyObject *context, PyTypeObject *cls, PyObject *x, PyObject *y) -/*[clinic end generated code: output=23cd81fdcd865d5a input=5ebbbe8bb35da380]*/ +/*[clinic end generated code: output=23cd81fdcd865d5a input=fcaaf828c1d2d089]*/ DecCtx_BinaryFunc(mpd_qxor) /*[clinic input] diff --git a/Modules/_decimal/clinic/_decimal.c.h b/Modules/_decimal/clinic/_decimal.c.h index ccfbf63a7cead5..b09200845d12e9 100644 --- a/Modules/_decimal/clinic/_decimal.c.h +++ b/Modules/_decimal/clinic/_decimal.c.h @@ -2744,7 +2744,9 @@ PyDoc_STRVAR(_decimal_Decimal_logical_invert__doc__, "logical_invert($self, /, context=None)\n" "--\n" "\n" -"Return the digit-wise inversion of the (logical) operand."); +"Invert all its digits.\n" +"\n" +"The self must be logical number."); #define _DECIMAL_DECIMAL_LOGICAL_INVERT_METHODDEF \ {"logical_invert", _PyCFunction_CAST(_decimal_Decimal_logical_invert), METH_METHOD|METH_FASTCALL|METH_KEYWORDS, _decimal_Decimal_logical_invert__doc__}, @@ -3336,7 +3338,9 @@ PyDoc_STRVAR(_decimal_Decimal_logical_and__doc__, "logical_and($self, /, other, context=None)\n" "--\n" "\n" -"Return the digit-wise \'and\' of the two (logical) operands."); +"Applies an \'and\' operation between self and other\'s digits.\n" +"\n" +"Both self and other must be logical numbers."); #define _DECIMAL_DECIMAL_LOGICAL_AND_METHODDEF \ {"logical_and", _PyCFunction_CAST(_decimal_Decimal_logical_and), METH_METHOD|METH_FASTCALL|METH_KEYWORDS, _decimal_Decimal_logical_and__doc__}, @@ -3402,7 +3406,9 @@ PyDoc_STRVAR(_decimal_Decimal_logical_or__doc__, "logical_or($self, /, other, context=None)\n" "--\n" "\n" -"Return the digit-wise \'or\' of the two (logical) operands."); +"Applies an \'or\' operation between self and other\'s digits.\n" +"\n" +"Both self and other must be logical numbers."); #define _DECIMAL_DECIMAL_LOGICAL_OR_METHODDEF \ {"logical_or", _PyCFunction_CAST(_decimal_Decimal_logical_or), METH_METHOD|METH_FASTCALL|METH_KEYWORDS, _decimal_Decimal_logical_or__doc__}, @@ -3468,7 +3474,9 @@ PyDoc_STRVAR(_decimal_Decimal_logical_xor__doc__, "logical_xor($self, /, other, context=None)\n" "--\n" "\n" -"Return the digit-wise \'xor\' of the two (logical) operands."); +"Applies an \'xor\' operation between self and other\'s digits.\n" +"\n" +"Both self and other must be logical numbers."); #define _DECIMAL_DECIMAL_LOGICAL_XOR_METHODDEF \ {"logical_xor", _PyCFunction_CAST(_decimal_Decimal_logical_xor), METH_METHOD|METH_FASTCALL|METH_KEYWORDS, _decimal_Decimal_logical_xor__doc__}, @@ -6235,7 +6243,20 @@ PyDoc_STRVAR(_decimal_Context_logical_invert__doc__, "logical_invert($self, x, /)\n" "--\n" "\n" -"Invert all digits of x."); +"Invert all the digits in the operand.\n" +"\n" +"The operand must be a logical number.\n" +"\n" +" >>> ExtendedContext.logical_invert(Decimal(\'0\'))\n" +" Decimal(\'111111111\')\n" +" >>> ExtendedContext.logical_invert(Decimal(\'1\'))\n" +" Decimal(\'111111110\')\n" +" >>> ExtendedContext.logical_invert(Decimal(\'111111111\'))\n" +" Decimal(\'0\')\n" +" >>> ExtendedContext.logical_invert(Decimal(\'101010101\'))\n" +" Decimal(\'10101010\')\n" +" >>> ExtendedContext.logical_invert(1101)\n" +" Decimal(\'111110010\')"); #define _DECIMAL_CONTEXT_LOGICAL_INVERT_METHODDEF \ {"logical_invert", _PyCFunction_CAST(_decimal_Context_logical_invert), METH_METHOD|METH_FASTCALL|METH_KEYWORDS, _decimal_Context_logical_invert__doc__}, @@ -6556,7 +6577,28 @@ PyDoc_STRVAR(_decimal_Context_logical_and__doc__, "logical_and($self, x, y, /)\n" "--\n" "\n" -"Digit-wise and of x and y."); +"Applies the logical operation \'and\' between each operand\'s digits.\n" +"\n" +"The operands must be both logical numbers.\n" +"\n" +" >>> ExtendedContext.logical_and(Decimal(\'0\'), Decimal(\'0\'))\n" +" Decimal(\'0\')\n" +" >>> ExtendedContext.logical_and(Decimal(\'0\'), Decimal(\'1\'))\n" +" Decimal(\'0\')\n" +" >>> ExtendedContext.logical_and(Decimal(\'1\'), Decimal(\'0\'))\n" +" Decimal(\'0\')\n" +" >>> ExtendedContext.logical_and(Decimal(\'1\'), Decimal(\'1\'))\n" +" Decimal(\'1\')\n" +" >>> ExtendedContext.logical_and(Decimal(\'1100\'), Decimal(\'1010\'))\n" +" Decimal(\'1000\')\n" +" >>> ExtendedContext.logical_and(Decimal(\'1111\'), Decimal(\'10\'))\n" +" Decimal(\'10\')\n" +" >>> ExtendedContext.logical_and(110, 1101)\n" +" Decimal(\'100\')\n" +" >>> ExtendedContext.logical_and(Decimal(110), 1101)\n" +" Decimal(\'100\')\n" +" >>> ExtendedContext.logical_and(110, Decimal(1101))\n" +" Decimal(\'100\')"); #define _DECIMAL_CONTEXT_LOGICAL_AND_METHODDEF \ {"logical_and", _PyCFunction_CAST(_decimal_Context_logical_and), METH_METHOD|METH_FASTCALL|METH_KEYWORDS, _decimal_Context_logical_and__doc__}, @@ -6603,7 +6645,28 @@ PyDoc_STRVAR(_decimal_Context_logical_or__doc__, "logical_or($self, x, y, /)\n" "--\n" "\n" -"Digit-wise or of x and y."); +"Applies the logical operation \'or\' between each operand\'s digits.\n" +"\n" +"The operands must be both logical numbers.\n" +"\n" +" >>> ExtendedContext.logical_or(Decimal(\'0\'), Decimal(\'0\'))\n" +" Decimal(\'0\')\n" +" >>> ExtendedContext.logical_or(Decimal(\'0\'), Decimal(\'1\'))\n" +" Decimal(\'1\')\n" +" >>> ExtendedContext.logical_or(Decimal(\'1\'), Decimal(\'0\'))\n" +" Decimal(\'1\')\n" +" >>> ExtendedContext.logical_or(Decimal(\'1\'), Decimal(\'1\'))\n" +" Decimal(\'1\')\n" +" >>> ExtendedContext.logical_or(Decimal(\'1100\'), Decimal(\'1010\'))\n" +" Decimal(\'1110\')\n" +" >>> ExtendedContext.logical_or(Decimal(\'1110\'), Decimal(\'10\'))\n" +" Decimal(\'1110\')\n" +" >>> ExtendedContext.logical_or(110, 1101)\n" +" Decimal(\'1111\')\n" +" >>> ExtendedContext.logical_or(Decimal(110), 1101)\n" +" Decimal(\'1111\')\n" +" >>> ExtendedContext.logical_or(110, Decimal(1101))\n" +" Decimal(\'1111\')"); #define _DECIMAL_CONTEXT_LOGICAL_OR_METHODDEF \ {"logical_or", _PyCFunction_CAST(_decimal_Context_logical_or), METH_METHOD|METH_FASTCALL|METH_KEYWORDS, _decimal_Context_logical_or__doc__}, @@ -6650,7 +6713,28 @@ PyDoc_STRVAR(_decimal_Context_logical_xor__doc__, "logical_xor($self, x, y, /)\n" "--\n" "\n" -"Digit-wise xor of x and y."); +"Applies the logical operation \'xor\' between each operand\'s digits.\n" +"\n" +"The operands must be both logical numbers.\n" +"\n" +" >>> ExtendedContext.logical_xor(Decimal(\'0\'), Decimal(\'0\'))\n" +" Decimal(\'0\')\n" +" >>> ExtendedContext.logical_xor(Decimal(\'0\'), Decimal(\'1\'))\n" +" Decimal(\'1\')\n" +" >>> ExtendedContext.logical_xor(Decimal(\'1\'), Decimal(\'0\'))\n" +" Decimal(\'1\')\n" +" >>> ExtendedContext.logical_xor(Decimal(\'1\'), Decimal(\'1\'))\n" +" Decimal(\'0\')\n" +" >>> ExtendedContext.logical_xor(Decimal(\'1100\'), Decimal(\'1010\'))\n" +" Decimal(\'110\')\n" +" >>> ExtendedContext.logical_xor(Decimal(\'1111\'), Decimal(\'10\'))\n" +" Decimal(\'1101\')\n" +" >>> ExtendedContext.logical_xor(110, 1101)\n" +" Decimal(\'1011\')\n" +" >>> ExtendedContext.logical_xor(Decimal(110), 1101)\n" +" Decimal(\'1011\')\n" +" >>> ExtendedContext.logical_xor(110, Decimal(1101))\n" +" Decimal(\'1011\')"); #define _DECIMAL_CONTEXT_LOGICAL_XOR_METHODDEF \ {"logical_xor", _PyCFunction_CAST(_decimal_Context_logical_xor), METH_METHOD|METH_FASTCALL|METH_KEYWORDS, _decimal_Context_logical_xor__doc__}, @@ -6896,4 +6980,4 @@ _decimal_Context_same_quantum(PyObject *context, PyTypeObject *cls, PyObject *co #ifndef _DECIMAL_CONTEXT_APPLY_METHODDEF #define _DECIMAL_CONTEXT_APPLY_METHODDEF #endif /* !defined(_DECIMAL_CONTEXT_APPLY_METHODDEF) */ -/*[clinic end generated code: output=e938de3a355a353a input=a9049054013a1b77]*/ +/*[clinic end generated code: output=b288181c82fdc9f1 input=a9049054013a1b77]*/