// 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 n<k, return 0.
// Ensure 0 <= k <= n/2: If k>n/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
syntax highlighted by Code2HTML, v. 0.9.1