1: package de.luschny.math.factorial;
2:
3: import de.luschny.math.arithmetic.Xint;
4:
5: public class FactorialBoitenSplit implements IFactorialFunction
6: {
7:
8: public FactorialBoitenSplit()
9: {
10: }
11:
12: public String getName()
13: {
14: return "BoitenSplit ";
15: }
16:
17: public Xint factorial(int n)
18: {
19: if (n < 0)
20: {
21: throw new ArithmeticException("Factorial: n has to be >= 0, but was " + n);
22: }
23:
24: if (n < 2)
25: {
26: return Xint.ONE;
27: }
28:
29: Xint p = Xint.ONE;
30: Xint r = Xint.ONE;
31:
32: // log2n = floor(log2(n));
33: int log2n = 31 - Integer.numberOfLeadingZeros(n);
34: int h = 0, shift = 0, k = 1;
35:
36: while (h != n)
37: {
38: shift += h;
39: h = n >>> log2n--;
40: int high = (h & 1) == 1 ? h : h - 1;
41:
42: while (k != high)
43: {
44: k += 2;
45: p = p.multiply(k);
46: }
47: r = r.multiply(p);
48: }
49: return r.shiftLeft(shift);
50: }
51: } // endOfFactorialSplitBoiten