1: using Xint = System.Numerics.BigInteger;
2:
3:
4: namespace Luschny.Math.Factorial
5: {
6: public class FactorialSwingDouble : IFactorialFunction
7: {
8: public FactorialSwingDouble() { }
9:
10: public string Name
11: {
12: get { return "SwingDouble "; }
13: }
14:
15: private Xint f;
16: private long gN;
17:
18: public Xint Factorial(int n)
19: {
20: if (n < 0)
21: {
22: throw new System.ArgumentOutOfRangeException("n",
23: Name + ": n >= 0 required, but was " + n);
24: }
25:
26: gN = 1;
27: f = Xint.One;
28: return RecFactorial(n);
29: }
30:
31: private Xint RecFactorial(int n)
32: {
33: if (n < 2) return Xint.One;
34:
35: return Xint.Pow(RecFactorial(n / 2),2) * Swing(n);
36: }
37:
38: private Xint Swing(long n)
39: {
40: long s = gN - 1 + ((n - gN + 1) % 4);
41: bool oddN = (gN & 1) != 1;
42:
43: for (; gN <= s; gN++)
44: {
45: if (oddN = !oddN) f *= gN;
46: else f = (f * 4) / gN;
47: }
48:
49: if (oddN) for (; gN <= n; gN += 4)
50: {
51: long m = ((gN + 1) * (gN + 3)) << 1;
52: long d = (gN * (gN + 2)) >> 3;
53:
54: f = (f * m) / d;
55: }
56: else for (; gN <= n; gN += 4)
57: {
58: long m = (gN * (gN + 2)) << 1;
59: long d = ((gN + 1) * (gN + 3)) >> 3;
60:
61: f = (f * m) / d;
62: }
63:
64: return f;
65: }
66: }
67: } // endOfSwingDouble