// binomial(). // General includes. #include "cl_sysdep.h" // Specification. #include "cln/integer.h" // Implementation. #include "cl_I_combin.h" namespace cln { const cl_I binomial (uintL n, uintL k) { // Method: // Ensure 0 <= k <= n: If nn/2, replace k by n-k. // Compute the product (n-k+1)...n and divide by k!. // When computing the product m < i <= n, split into the odd part // and the even part. The even part is 2^(ord2(n!)-ord2(m!)), // and recall that ord2(n!) = n - logcount(n). The odd part is // computed recursively: It is the product of the odd part of // m/2 < i <= n/2, times the product of m < 2*i+1 <= n. The // recursion goes until floor(m/2^j) = floor(n/2^j) or floor(n/2^j) < 2. if (n < k) return 0; // Now 0 <= k <= n. if (2*k > n) k = n-k; // Now 0 <= k <= n/2. var cl_I prod = 1; var uintL m = n-k; var uintL j = 0; { var uintL a = m; var uintL b = n; while (a < b && b > 1) { a = floor(a,2); b = floor(b,2); j++; } } while (j > 0) { j--; var uintL a = m>>j; var uintL b = n>>j; // Compute product(a < i <= b and i odd, i) a = floor(a-1,2); b = floor(b-1,2); // = product(a < i <= b, 2i+1) if (a < b) prod = prod * cl_I_prod_ungerade(a,b); } prod = prod << (k + logcount(m) - logcount(n)); return exquopos(prod,factorial(k)); } } // namespace cln