PageRenderTime 42ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

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

#
C++ | 124 lines | 91 code | 11 blank | 22 comment | 2 complexity | 1b6c90f52185ce85438a4912f0c7b3d6 MD5 | raw file
Possible License(s): GPL-2.0
  1. // factorial().
  2. // General includes.
  3. #include "base/cl_sysdep.h"
  4. // Specification.
  5. #include "cln/integer.h"
  6. // Implementation.
  7. #include "integer/cl_I.h"
  8. #include "integer/misc/combin/cl_I_combin.h"
  9. namespace cln {
  10. // Methode:
  11. // n <= 10 -> Ergebnis (Fixnum) aus Tabelle
  12. // Sonst:
  13. // Zweierpotenzen extra am Schluß durch einen Shift um
  14. // ord2(n!) = sum(k>=1, floor(n/2^k) ) = n - logcount(n) Bits.
  15. // Für k>=1 wird jede ungerade Zahl m im Intervall n/2^k < m <= n/2^(k-1)
  16. // genau k mal gebraucht (als ungerader Anteil von m*2^0,...,m*2^(k-1) ).
  17. // Zur Bestimmung des Produkts aller ungeraden Zahlen in einem Intervall
  18. // a < m <= b verwenden wir eine rekursive Funktion, die nach Divide-and-
  19. // Conquer das Produkt über die Intervalle a < m <= c und c < m <= b
  20. // (c := floor((a+b)/2)) bestimmt und beide zusammenmultipliziert. Dies
  21. // vermeidet, daß oft große Zahlen mit ganz kleinen Zahlen multipliziert
  22. // werden.
  23. const cl_I factorial (uintL n) // assume n >= 0 small
  24. {
  25. static uintV const fakul_table [] = {
  26. 1,
  27. 1UL,
  28. 1UL*2,
  29. #if (cl_value_len>=4)
  30. 1UL*2*3,
  31. #if (cl_value_len>=6)
  32. 1UL*2*3*4,
  33. #if (cl_value_len>=8)
  34. 1UL*2*3*4*5,
  35. #if (cl_value_len>=11)
  36. 1UL*2*3*4*5*6,
  37. #if (cl_value_len>=14)
  38. 1UL*2*3*4*5*6*7,
  39. #if (cl_value_len>=17)
  40. 1UL*2*3*4*5*6*7*8,
  41. #if (cl_value_len>=20)
  42. 1UL*2*3*4*5*6*7*8*9,
  43. #if (cl_value_len>=23)
  44. 1UL*2*3*4*5*6*7*8*9*10,
  45. #if (cl_value_len>=27)
  46. 1UL*2*3*4*5*6*7*8*9*10*11,
  47. #if (cl_value_len>=30)
  48. 1UL*2*3*4*5*6*7*8*9*10*11*12,
  49. #if (cl_value_len>=34)
  50. 1UL*2*3*4*5*6*7*8*9*10*11*12*13,
  51. #if (cl_value_len>=38)
  52. 1UL*2*3*4*5*6*7*8*9*10*11*12*13*14,
  53. #if (cl_value_len>=42)
  54. 1UL*2*3*4*5*6*7*8*9*10*11*12*13*14*15,
  55. #if (cl_value_len>=46)
  56. 1UL*2*3*4*5*6*7*8*9*10*11*12*13*14*15*16,
  57. #if (cl_value_len>=50)
  58. 1UL*2*3*4*5*6*7*8*9*10*11*12*13*14*15*16*17,
  59. #if (cl_value_len>=54)
  60. 1UL*2*3*4*5*6*7*8*9*10*11*12*13*14*15*16*17*18,
  61. #if (cl_value_len>=58)
  62. 1UL*2*3*4*5*6*7*8*9*10*11*12*13*14*15*16*17*18*19,
  63. #if (cl_value_len>=63)
  64. 1UL*2*3*4*5*6*7*8*9*10*11*12*13*14*15*16*17*18*19*20,
  65. #if (cl_value_len>=67)
  66. ...
  67. #endif
  68. #endif
  69. #endif
  70. #endif
  71. #endif
  72. #endif
  73. #endif
  74. #endif
  75. #endif
  76. #endif
  77. #endif
  78. #endif
  79. #endif
  80. #endif
  81. #endif
  82. #endif
  83. #endif
  84. #endif
  85. #endif
  86. };
  87. if (n < sizeof(fakul_table)/sizeof(cl_I))
  88. { return UV_to_I(fakul_table[n]); }
  89. else
  90. { var cl_I prod = 1; // bisheriges Produkt := 1
  91. var uintL k = 1;
  92. var uintL A = n;
  93. var uintL B = n; // obere Intervallgrenze floor(n/2^(k-1))
  94. loop
  95. { // 'A' enthält floor(n/2^(k-1)).
  96. A = A >> 1; // untere Grenze floor(n/2^k)
  97. // 'A' enthält floor(n/2^k).
  98. // Bilde Teilprodukt prod(A < i <= B & oddp(i), i)
  99. // = prod(floor((A-1)/2) < i <= floor((B-1)/2), 2*i+1)
  100. // wobei B = floor(n/2^(k-1)), A = floor(n/2^k) = floor(B/2).
  101. { var uintL b = floor(B-1,2);
  102. if (b==0) break; // B=2 oder B=1 -> Produkt fertig
  103. var uintL a = floor(A-1,2);
  104. prod = expt_pos(cl_I_prod_ungerade(a,b),k) * prod; // aufmultiplizieren
  105. }
  106. k = k+1;
  107. B = A;
  108. }
  109. return prod << (n - logcount(n));
  110. }
  111. }
  112. // Bit complexity (N := n): O(log(N)^2*M(N)).
  113. } // namespace cln