@@ -3001,10 +3001,11 @@ math_prod_impl(PyObject *module, PyObject *iterable, PyObject *start)
3001
3001
/*[clinic input]
3002
3002
math.comb
3003
3003
3004
- n: object(subclass_of='&PyLong_Type')
3005
- k: object(subclass_of='&PyLong_Type')
3004
+ n: object
3005
+ k: object
3006
+ /
3006
3007
3007
- Number of ways to choose *k* items from *n* items without repetition and without order.
3008
+ Number of ways to choose k items from n items without repetition and without order.
3008
3009
3009
3010
Also called the binomial coefficient. It is mathematically equal to the expression
3010
3011
n! / (k! * (n - k)!). It is equivalent to the coefficient of k-th term in
@@ -3017,103 +3018,109 @@ Raises ValueError if the arguments are negative or if k > n.
3017
3018
3018
3019
static PyObject *
3019
3020
math_comb_impl (PyObject * module , PyObject * n , PyObject * k )
3020
- /*[clinic end generated code: output=bd2cec8d854f3493 input=565f340f98efb5b5 ]*/
3021
+ /*[clinic end generated code: output=bd2cec8d854f3493 input=2f336ac9ec8242f9 ]*/
3021
3022
{
3022
- PyObject * val = NULL ,
3023
- * temp_obj1 = NULL ,
3024
- * temp_obj2 = NULL ,
3025
- * dump_var = NULL ;
3023
+ PyObject * result = NULL , * factor = NULL , * temp ;
3026
3024
int overflow , cmp ;
3027
- long long i , terms ;
3025
+ long long i , factors ;
3028
3026
3029
- cmp = PyObject_RichCompareBool ( n , k , Py_LT );
3030
- if (cmp < 0 ) {
3031
- goto fail_comb ;
3027
+ n = PyNumber_Index ( n );
3028
+ if (n == NULL ) {
3029
+ return NULL ;
3032
3030
}
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 ;
3031
+ k = PyNumber_Index ( k );
3032
+ if ( k == NULL ) {
3033
+ Py_DECREF ( n );
3034
+ return NULL ;
3037
3035
}
3038
3036
3039
- /* b = min(b, a - b) */
3040
- dump_var = PyNumber_Subtract ( n , k );
3041
- if ( dump_var == NULL ) {
3042
- goto fail_comb ;
3037
+ if ( Py_SIZE ( n ) < 0 ) {
3038
+ PyErr_SetString ( PyExc_ValueError ,
3039
+ "n must be a non-negative integer" );
3040
+ goto error ;
3043
3041
}
3044
- cmp = PyObject_RichCompareBool (k , dump_var , Py_GT );
3045
- if (cmp < 0 ) {
3046
- goto fail_comb ;
3042
+ /* k = min(k, n - k) */
3043
+ temp = PyNumber_Subtract (n , k );
3044
+ if (temp == NULL ) {
3045
+ goto error ;
3047
3046
}
3048
- else if (cmp > 0 ) {
3049
- k = dump_var ;
3050
- dump_var = NULL ;
3047
+ if (Py_SIZE (temp ) < 0 ) {
3048
+ Py_DECREF (temp );
3049
+ PyErr_SetString (PyExc_ValueError ,
3050
+ "k must be an integer less than or equal to n" );
3051
+ goto error ;
3052
+ }
3053
+ cmp = PyObject_RichCompareBool (k , temp , Py_GT );
3054
+ if (cmp > 0 ) {
3055
+ Py_SETREF (k , temp );
3051
3056
}
3052
3057
else {
3053
- Py_DECREF (dump_var );
3054
- dump_var = NULL ;
3058
+ Py_DECREF (temp );
3059
+ if (cmp < 0 ) {
3060
+ goto error ;
3061
+ }
3055
3062
}
3056
3063
3057
- terms = PyLong_AsLongLongAndOverflow (k , & overflow );
3058
- if (terms < 0 && PyErr_Occurred ()) {
3059
- goto fail_comb ;
3060
- }
3061
- else if (overflow > 0 ) {
3064
+ factors = PyLong_AsLongLongAndOverflow (k , & overflow );
3065
+ if (overflow > 0 ) {
3062
3066
PyErr_Format (PyExc_OverflowError ,
3063
- "minimum (n - k, k) must not exceed %lld" ,
3067
+ "min (n - k, k) must not exceed %lld" ,
3064
3068
LLONG_MAX );
3065
- goto fail_comb ;
3069
+ goto error ;
3066
3070
}
3067
- else if (overflow < 0 || terms < 0 ) {
3068
- PyErr_Format (PyExc_ValueError ,
3069
- "k must be a positive integer" );
3070
- goto fail_comb ;
3071
+ else if (overflow < 0 || factors < 0 ) {
3072
+ if (!PyErr_Occurred ()) {
3073
+ PyErr_SetString (PyExc_ValueError ,
3074
+ "k must be a non-negative integer" );
3075
+ }
3076
+ goto error ;
3071
3077
}
3072
3078
3073
- if (terms == 0 ) {
3074
- return PyNumber_Long (_PyLong_One );
3079
+ if (factors == 0 ) {
3080
+ result = PyLong_FromLong (1 );
3081
+ goto done ;
3075
3082
}
3076
3083
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 ;
3084
+ result = n ;
3085
+ Py_INCREF (result );
3086
+ if (factors == 1 ) {
3087
+ goto done ;
3088
+ }
3089
+
3090
+ factor = n ;
3091
+ Py_INCREF (factor );
3092
+ for (i = 1 ; i < factors ; ++ i ) {
3093
+ Py_SETREF (factor , PyNumber_Subtract (factor , _PyLong_One ));
3094
+ if (factor == NULL ) {
3095
+ goto error ;
3086
3096
}
3087
- dump_var = val ;
3088
- val = PyNumber_Multiply (val , temp_obj2 );
3089
- if (val == NULL ) {
3090
- goto fail_comb ;
3097
+ Py_SETREF (result , PyNumber_Multiply (result , factor ));
3098
+ if (result == NULL ) {
3099
+ goto error ;
3091
3100
}
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 ;
3101
+
3102
+ temp = PyLong_FromUnsignedLongLong ((unsigned long long )i + 1 );
3103
+ if (temp == NULL ) {
3104
+ goto error ;
3098
3105
}
3099
- dump_var = val ;
3100
- val = PyNumber_FloorDivide ( val , temp_obj2 );
3101
- if (val == NULL ) {
3102
- goto fail_comb ;
3106
+ Py_SETREF ( result , PyNumber_FloorDivide ( result , temp )) ;
3107
+ Py_DECREF ( temp );
3108
+ if (result == NULL ) {
3109
+ goto error ;
3103
3110
}
3104
- Py_DECREF (dump_var );
3105
- Py_DECREF (temp_obj1 );
3106
- Py_DECREF (temp_obj2 );
3107
3111
}
3112
+ Py_DECREF (factor );
3108
3113
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 );
3114
+ done :
3115
+ Py_DECREF (n );
3116
+ Py_DECREF (k );
3117
+ return result ;
3116
3118
3119
+ error :
3120
+ Py_XDECREF (factor );
3121
+ Py_XDECREF (result );
3122
+ Py_DECREF (n );
3123
+ Py_DECREF (k );
3117
3124
return NULL ;
3118
3125
}
3119
3126
0 commit comments