Commit 963eb0f4 authored by Raymond Hettinger's avatar Raymond Hettinger Committed by GitHub

bpo-35431: Drop the k <= n requirement (GH-13798)

parent 0fd2c300
...@@ -41,12 +41,15 @@ Number-theoretic and representation functions ...@@ -41,12 +41,15 @@ Number-theoretic and representation functions
Return the number of ways to choose *k* items from *n* items without repetition Return the number of ways to choose *k* items from *n* items without repetition
and without order. and without order.
Also called the binomial coefficient. It is mathematically equal to the expression Evaluates to ``n! / (k! * (n - k)!)`` when ``k <= n`` and evaluates
``n! / (k! (n - k)!)``. It is equivalent to the coefficient of the *k*-th term in the to zero when ``k > n``.
polynomial expansion of the expression ``(1 + x) ** n``.
Raises :exc:`TypeError` if the arguments not integers. Also called the binomial coefficient because it is equivalent
Raises :exc:`ValueError` if the arguments are negative or if *k* > *n*. to the coefficient of k-th term in polynomial expansion of the
expression ``(1 + x) ** n``.
Raises :exc:`TypeError` if either of the arguments not integers.
Raises :exc:`ValueError` if either of the arguments are negative.
.. versionadded:: 3.8 .. versionadded:: 3.8
...@@ -212,10 +215,11 @@ Number-theoretic and representation functions ...@@ -212,10 +215,11 @@ Number-theoretic and representation functions
Return the number of ways to choose *k* items from *n* items Return the number of ways to choose *k* items from *n* items
without repetition and with order. without repetition and with order.
It is mathematically equal to the expression ``n! / (n - k)!``. Evaluates to ``n! / (n - k)!`` when ``k <= n`` and evaluates
to zero when ``k > n``.
Raises :exc:`TypeError` if the arguments not integers. Raises :exc:`TypeError` if either of the arguments not integers.
Raises :exc:`ValueError` if the arguments are negative or if *k* > *n*. Raises :exc:`ValueError` if either of the arguments are negative.
.. versionadded:: 3.8 .. versionadded:: 3.8
......
...@@ -1904,9 +1904,9 @@ class IsCloseTests(unittest.TestCase): ...@@ -1904,9 +1904,9 @@ class IsCloseTests(unittest.TestCase):
self.assertRaises(ValueError, perm, 1, -1) self.assertRaises(ValueError, perm, 1, -1)
self.assertRaises(ValueError, perm, 1, -2**1000) self.assertRaises(ValueError, perm, 1, -2**1000)
# Raises value error if k is greater than n # Returns zero if k is greater than n
self.assertRaises(ValueError, perm, 1, 2) self.assertEqual(perm(1, 2), 0)
self.assertRaises(ValueError, perm, 1, 2**1000) self.assertEqual(perm(1, 2**1000), 0)
n = 2**1000 n = 2**1000
self.assertEqual(perm(n, 0), 1) self.assertEqual(perm(n, 0), 1)
...@@ -1970,9 +1970,9 @@ class IsCloseTests(unittest.TestCase): ...@@ -1970,9 +1970,9 @@ class IsCloseTests(unittest.TestCase):
self.assertRaises(ValueError, comb, 1, -1) self.assertRaises(ValueError, comb, 1, -1)
self.assertRaises(ValueError, comb, 1, -2**1000) self.assertRaises(ValueError, comb, 1, -2**1000)
# Raises value error if k is greater than n # Returns zero if k is greater than n
self.assertRaises(ValueError, comb, 1, 2) self.assertEqual(comb(1, 2), 0)
self.assertRaises(ValueError, comb, 1, 2**1000) self.assertEqual(comb(1, 2**1000), 0)
n = 2**1000 n = 2**1000
self.assertEqual(comb(n, 0), 1) self.assertEqual(comb(n, 0), 1)
......
...@@ -644,10 +644,11 @@ PyDoc_STRVAR(math_perm__doc__, ...@@ -644,10 +644,11 @@ PyDoc_STRVAR(math_perm__doc__,
"\n" "\n"
"Number of ways to choose k items from n items without repetition and with order.\n" "Number of ways to choose k items from n items without repetition and with order.\n"
"\n" "\n"
"It is mathematically equal to the expression n! / (n - k)!.\n" "Evaluates to n! / (n - k)! when k <= n and evaluates\n"
"to zero when k > n.\n"
"\n" "\n"
"Raises TypeError if the arguments are not integers.\n" "Raises TypeError if either of the arguments are not integers.\n"
"Raises ValueError if the arguments are negative or if k > n."); "Raises ValueError if either of the arguments are negative.");
#define MATH_PERM_METHODDEF \ #define MATH_PERM_METHODDEF \
{"perm", (PyCFunction)(void(*)(void))math_perm, METH_FASTCALL, math_perm__doc__}, {"perm", (PyCFunction)(void(*)(void))math_perm, METH_FASTCALL, math_perm__doc__},
...@@ -679,12 +680,15 @@ PyDoc_STRVAR(math_comb__doc__, ...@@ -679,12 +680,15 @@ PyDoc_STRVAR(math_comb__doc__,
"\n" "\n"
"Number of ways to choose k items from n items without repetition and without order.\n" "Number of ways to choose k items from n items without repetition and without order.\n"
"\n" "\n"
"Also called the binomial coefficient. It is mathematically equal to the expression\n" "Evaluates to n! / (k! * (n - k)!) when k <= n and evaluates\n"
"n! / (k! * (n - k)!). It is equivalent to the coefficient of k-th term in\n" "to zero when k > n.\n"
"polynomial expansion of the expression (1 + x)**n.\n"
"\n" "\n"
"Raises TypeError if the arguments are not integers.\n" "Also called the binomial coefficient because it is equivalent\n"
"Raises ValueError if the arguments are negative or if k > n."); "to the coefficient of k-th term in polynomial expansion of the\n"
"expression (1 + x)**n.\n"
"\n"
"Raises TypeError if either of the arguments are not integers.\n"
"Raises ValueError if either of the arguments are negative.");
#define MATH_COMB_METHODDEF \ #define MATH_COMB_METHODDEF \
{"comb", (PyCFunction)(void(*)(void))math_comb, METH_FASTCALL, math_comb__doc__}, {"comb", (PyCFunction)(void(*)(void))math_comb, METH_FASTCALL, math_comb__doc__},
...@@ -709,4 +713,4 @@ math_comb(PyObject *module, PyObject *const *args, Py_ssize_t nargs) ...@@ -709,4 +713,4 @@ math_comb(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
exit: exit:
return return_value; return return_value;
} }
/*[clinic end generated code: output=a82b0e705b6d0ec0 input=a9049054013a1b77]*/ /*[clinic end generated code: output=5004266613284dcc input=a9049054013a1b77]*/
...@@ -3007,15 +3007,16 @@ math.perm ...@@ -3007,15 +3007,16 @@ math.perm
Number of ways to choose k items from n items without repetition and with order. Number of ways to choose k items from n items without repetition and with order.
It is mathematically equal to the expression n! / (n - k)!. Evaluates to n! / (n - k)! when k <= n and evaluates
to zero when k > n.
Raises TypeError if the arguments are not integers. Raises TypeError if either of the arguments are not integers.
Raises ValueError if the arguments are negative or if k > n. Raises ValueError if either of the arguments are negative.
[clinic start generated code]*/ [clinic start generated code]*/
static PyObject * static PyObject *
math_perm_impl(PyObject *module, PyObject *n, PyObject *k) math_perm_impl(PyObject *module, PyObject *n, PyObject *k)
/*[clinic end generated code: output=e021a25469653e23 input=f71ee4f6ff26be24]*/ /*[clinic end generated code: output=e021a25469653e23 input=b2e7729d9a1949cf]*/
{ {
PyObject *result = NULL, *factor = NULL; PyObject *result = NULL, *factor = NULL;
int overflow, cmp; int overflow, cmp;
...@@ -3052,8 +3053,8 @@ math_perm_impl(PyObject *module, PyObject *n, PyObject *k) ...@@ -3052,8 +3053,8 @@ math_perm_impl(PyObject *module, PyObject *n, PyObject *k)
cmp = PyObject_RichCompareBool(n, k, Py_LT); cmp = PyObject_RichCompareBool(n, k, Py_LT);
if (cmp != 0) { if (cmp != 0) {
if (cmp > 0) { if (cmp > 0) {
PyErr_SetString(PyExc_ValueError, result = PyLong_FromLong(0);
"k must be an integer less than or equal to n"); goto done;
} }
goto error; goto error;
} }
...@@ -3121,18 +3122,21 @@ math.comb ...@@ -3121,18 +3122,21 @@ math.comb
Number of ways to choose k items from n items without repetition and without order. Number of ways to choose k items from n items without repetition and without order.
Also called the binomial coefficient. It is mathematically equal to the expression Evaluates to n! / (k! * (n - k)!) when k <= n and evaluates
n! / (k! * (n - k)!). It is equivalent to the coefficient of k-th term in to zero when k > n.
polynomial expansion of the expression (1 + x)**n.
Also called the binomial coefficient because it is equivalent
to the coefficient of k-th term in polynomial expansion of the
expression (1 + x)**n.
Raises TypeError if the arguments are not integers. Raises TypeError if either of the arguments are not integers.
Raises ValueError if the arguments are negative or if k > n. Raises ValueError if either of the arguments are negative.
[clinic start generated code]*/ [clinic start generated code]*/
static PyObject * static PyObject *
math_comb_impl(PyObject *module, PyObject *n, PyObject *k) math_comb_impl(PyObject *module, PyObject *n, PyObject *k)
/*[clinic end generated code: output=bd2cec8d854f3493 input=2f336ac9ec8242f9]*/ /*[clinic end generated code: output=bd2cec8d854f3493 input=9a05315af2518709]*/
{ {
PyObject *result = NULL, *factor = NULL, *temp; PyObject *result = NULL, *factor = NULL, *temp;
int overflow, cmp; int overflow, cmp;
...@@ -3173,9 +3177,8 @@ math_comb_impl(PyObject *module, PyObject *n, PyObject *k) ...@@ -3173,9 +3177,8 @@ math_comb_impl(PyObject *module, PyObject *n, PyObject *k)
} }
if (Py_SIZE(temp) < 0) { if (Py_SIZE(temp) < 0) {
Py_DECREF(temp); Py_DECREF(temp);
PyErr_SetString(PyExc_ValueError, result = PyLong_FromLong(0);
"k must be an integer less than or equal to n"); goto done;
goto error;
} }
cmp = PyObject_RichCompareBool(temp, k, Py_LT); cmp = PyObject_RichCompareBool(temp, k, Py_LT);
if (cmp > 0) { if (cmp > 0) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment