PageRenderTime 42ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 1ms

/cln-1.3.2/src/integer/misc/combin/cl_I_binomial.cc

#
C++ | 60 lines | 34 code | 8 blank | 18 comment | 6 complexity | 4f84da0bb019f3a36e55a6afd3a8da48 MD5 | raw file
Possible License(s): GPL-2.0
  1. // binomial().
  2. // General includes.
  3. #include "base/cl_sysdep.h"
  4. // Specification.
  5. #include "cln/integer.h"
  6. // Implementation.
  7. #include "integer/misc/combin/cl_I_combin.h"
  8. namespace cln {
  9. const cl_I binomial (uintL n, uintL k)
  10. {
  11. // Method:
  12. // Ensure 0 <= k <= n: If n<k, return 0.
  13. // Ensure 0 <= k <= n/2: If k>n/2, replace k by n-k.
  14. // Compute the product (n-k+1)...n and divide by k!.
  15. // When computing the product m < i <= n, split into the odd part
  16. // and the even part. The even part is 2^(ord2(n!)-ord2(m!)),
  17. // and recall that ord2(n!) = n - logcount(n). The odd part is
  18. // computed recursively: It is the product of the odd part of
  19. // m/2 < i <= n/2, times the product of m < 2*i+1 <= n. The
  20. // recursion goes until floor(m/2^j) = floor(n/2^j) or floor(n/2^j) < 2.
  21. if (n < k)
  22. return 0;
  23. // Now 0 <= k <= n.
  24. if (2*k > n)
  25. k = n-k;
  26. // Now 0 <= k <= n/2.
  27. var cl_I prod = 1;
  28. var uintL m = n-k;
  29. var uintL j = 0;
  30. {
  31. var uintL a = m;
  32. var uintL b = n;
  33. while (a < b && b > 1) {
  34. a = floor(a,2); b = floor(b,2);
  35. j++;
  36. }
  37. }
  38. while (j > 0) {
  39. j--;
  40. var uintL a = m>>j;
  41. var uintL b = n>>j;
  42. // Compute product(a < i <= b and i odd, i)
  43. a = floor(a-1,2);
  44. b = floor(b-1,2);
  45. // = product(a < i <= b, 2i+1)
  46. if (a < b)
  47. prod = prod * cl_I_prod_ungerade(a,b);
  48. }
  49. prod = prod << (k + logcount(m) - logcount(n));
  50. return exquopos(prod,factorial(k));
  51. }
  52. } // namespace cln