@@ -2998,6 +2998,126 @@ math_prod_impl(PyObject *module, PyObject *iterable, PyObject *start)
29982998}
29992999
30003000
3001+ /*[clinic input]
3002+ math.comb
3003+
3004+ n: object(subclass_of='&PyLong_Type')
3005+ k: object(subclass_of='&PyLong_Type')
3006+
3007+ Number of ways to choose *k* items from *n* items without repetition and without order.
3008+
3009+ Also called the binomial coefficient. It is mathematically equal to the expression
3010+ n! / (k! * (n - k)!). It is equivalent to the coefficient of k-th term in
3011+ polynomial expansion of the expression (1 + x)**n.
3012+
3013+ Raises TypeError if the arguments are not integers.
3014+ Raises ValueError if the arguments are negative or if k > n.
3015+
3016+ [clinic start generated code]*/
3017+
3018+ static PyObject *
3019+ math_comb_impl (PyObject * module , PyObject * n , PyObject * k )
3020+ /*[clinic end generated code: output=bd2cec8d854f3493 input=565f340f98efb5b5]*/
3021+ {
3022+ PyObject * val = NULL ,
3023+ * temp_obj1 = NULL ,
3024+ * temp_obj2 = NULL ,
3025+ * dump_var = NULL ;
3026+ int overflow , cmp ;
3027+ long long i , terms ;
3028+
3029+ cmp = PyObject_RichCompareBool (n , k , Py_LT );
3030+ if (cmp < 0 ) {
3031+ goto fail_comb ;
3032+ }
3033+ else if (cmp > 0 ) {
3034+ PyErr_Format (PyExc_ValueError ,
3035+ "n must be an integer greater than or equal to k" );
3036+ goto fail_comb ;
3037+ }
3038+
3039+ /* b = min(b, a - b) */
3040+ dump_var = PyNumber_Subtract (n , k );
3041+ if (dump_var == NULL ) {
3042+ goto fail_comb ;
3043+ }
3044+ cmp = PyObject_RichCompareBool (k , dump_var , Py_GT );
3045+ if (cmp < 0 ) {
3046+ goto fail_comb ;
3047+ }
3048+ else if (cmp > 0 ) {
3049+ k = dump_var ;
3050+ dump_var = NULL ;
3051+ }
3052+ else {
3053+ Py_DECREF (dump_var );
3054+ dump_var = NULL ;
3055+ }
3056+
3057+ terms = PyLong_AsLongLongAndOverflow (k , & overflow );
3058+ if (terms < 0 && PyErr_Occurred ()) {
3059+ goto fail_comb ;
3060+ }
3061+ else if (overflow > 0 ) {
3062+ PyErr_Format (PyExc_OverflowError ,
3063+ "minimum(n - k, k) must not exceed %lld" ,
3064+ LLONG_MAX );
3065+ goto fail_comb ;
3066+ }
3067+ else if (overflow < 0 || terms < 0 ) {
3068+ PyErr_Format (PyExc_ValueError ,
3069+ "k must be a positive integer" );
3070+ goto fail_comb ;
3071+ }
3072+
3073+ if (terms == 0 ) {
3074+ return PyNumber_Long (_PyLong_One );
3075+ }
3076+
3077+ val = PyNumber_Long (n );
3078+ for (i = 1 ; i < terms ; ++ i ) {
3079+ temp_obj1 = PyLong_FromSsize_t (i );
3080+ if (temp_obj1 == NULL ) {
3081+ goto fail_comb ;
3082+ }
3083+ temp_obj2 = PyNumber_Subtract (n , temp_obj1 );
3084+ if (temp_obj2 == NULL ) {
3085+ goto fail_comb ;
3086+ }
3087+ dump_var = val ;
3088+ val = PyNumber_Multiply (val , temp_obj2 );
3089+ if (val == NULL ) {
3090+ goto fail_comb ;
3091+ }
3092+ Py_DECREF (dump_var );
3093+ dump_var = NULL ;
3094+ Py_DECREF (temp_obj2 );
3095+ temp_obj2 = PyLong_FromUnsignedLongLong ((unsigned long long )(i + 1 ));
3096+ if (temp_obj2 == NULL ) {
3097+ goto fail_comb ;
3098+ }
3099+ dump_var = val ;
3100+ val = PyNumber_FloorDivide (val , temp_obj2 );
3101+ if (val == NULL ) {
3102+ goto fail_comb ;
3103+ }
3104+ Py_DECREF (dump_var );
3105+ Py_DECREF (temp_obj1 );
3106+ Py_DECREF (temp_obj2 );
3107+ }
3108+
3109+ return val ;
3110+
3111+ fail_comb :
3112+ Py_XDECREF (val );
3113+ Py_XDECREF (dump_var );
3114+ Py_XDECREF (temp_obj1 );
3115+ Py_XDECREF (temp_obj2 );
3116+
3117+ return NULL ;
3118+ }
3119+
3120+
30013121static PyMethodDef math_methods [] = {
30023122 {"acos" , math_acos , METH_O , math_acos_doc },
30033123 {"acosh" , math_acosh , METH_O , math_acosh_doc },
@@ -3047,6 +3167,7 @@ static PyMethodDef math_methods[] = {
30473167 {"tanh" , math_tanh , METH_O , math_tanh_doc },
30483168 MATH_TRUNC_METHODDEF
30493169 MATH_PROD_METHODDEF
3170+ MATH_COMB_METHODDEF
30503171 {NULL , NULL } /* sentinel */
30513172};
30523173
0 commit comments