@@ -1911,6 +1911,72 @@ gmp_comb(PyObject *self, PyObject *const *args, Py_ssize_t nargs)
19111911 return NULL ;
19121912}
19131913
1914+ static PyObject *
1915+ gmp_perm (PyObject * self , PyObject * const * args , Py_ssize_t nargs )
1916+ {
1917+ if (nargs > 2 || nargs < 1 ) {
1918+ PyErr_SetString (PyExc_TypeError , "one or two arguments required" );
1919+ return NULL ;
1920+ }
1921+ if (nargs == 1 ) {
1922+ return gmp_fac (self , args [0 ]);
1923+ }
1924+
1925+ MPZ_Object * x , * y , * res = MPZ_new (0 );
1926+
1927+ if (!res ) {
1928+ return NULL ; /* LCOV_EXCL_LINE */
1929+ }
1930+ CHECK_OP_INT (x , args [0 ]);
1931+ CHECK_OP_INT (y , args [1 ]);
1932+ if (zz_isneg (& x -> z ) || zz_isneg (& y -> z )) {
1933+ PyErr_SetString (PyExc_ValueError ,
1934+ "perm() not defined for negative values" );
1935+ goto err ;
1936+ }
1937+
1938+ int64_t n , k ;
1939+
1940+ if ((zz_to_i64 (& x -> z , & n ) || n > ULONG_MAX )
1941+ || (zz_to_i64 (& y -> z , & k ) || k > ULONG_MAX ))
1942+ {
1943+ PyErr_Format (PyExc_OverflowError ,
1944+ "perm() arguments should not exceed %ld" ,
1945+ ULONG_MAX );
1946+ goto err ;
1947+ }
1948+ Py_XDECREF (x );
1949+ Py_XDECREF (y );
1950+ if (k > n ) {
1951+ return (PyObject * )res ;
1952+ }
1953+
1954+ MPZ_Object * den = MPZ_new (0 );
1955+
1956+ if (!den ) {
1957+ /* LCOV_EXCL_START */
1958+ PyErr_NoMemory ();
1959+ goto err ;
1960+ /* LCOV_EXCL_STOP */
1961+ }
1962+ if (zz_fac ((uint64_t )n , & res -> z )
1963+ || zz_fac ((uint64_t )(n - k ), & den -> z )
1964+ || zz_div (& res -> z , & den -> z , ZZ_RNDD , & res -> z , NULL ))
1965+ {
1966+ /* LCOV_EXCL_START */
1967+ Py_DECREF (den );
1968+ PyErr_NoMemory ();
1969+ goto err ;
1970+ /* LCOV_EXCL_STOP */
1971+ }
1972+ Py_DECREF (den );
1973+ return (PyObject * )res ;
1974+ err :
1975+ end :
1976+ Py_DECREF (res );
1977+ return NULL ;
1978+ }
1979+
19141980static zz_rnd
19151981get_round_mode (PyObject * rndstr )
19161982{
@@ -2124,6 +2190,9 @@ static PyMethodDef gmp_functions[] = {
21242190 ("comb($module, n, k, /)\n--\n\nNumber of ways to choose k"
21252191 " items from n items without repetition and order.\n\n"
21262192 "Also called the binomial coefficient." )},
2193+ {"perm" , (PyCFunction )gmp_perm , METH_FASTCALL ,
2194+ ("perm($module, n, k=None, /)\n--\n\nNumber of ways to choose k"
2195+ " items from n items without repetition and withorder." )},
21272196 {"_mpmath_normalize" , (PyCFunction )gmp__mpmath_normalize , METH_FASTCALL ,
21282197 NULL },
21292198 {"_mpmath_create" , (PyCFunction )gmp__mpmath_create , METH_FASTCALL , NULL },
@@ -2216,7 +2285,7 @@ gmp_exec(PyObject *m)
22162285 "numbers.Integral.register(gmp.mpz)\n"
22172286 "gmp.fac = gmp.factorial\n"
22182287 "gmp.__all__ = ['comb', 'factorial', 'gcd', 'isqrt',\n"
2219- " 'lcm', 'mpz']\n"
2288+ " 'lcm', 'mpz', 'perm' ]\n"
22202289 "gmp.__version__ = imp.version('python-gmp')\n" );
22212290
22222291 PyObject * res = PyRun_String (str , Py_file_input , ns , ns );
0 commit comments