public XInt Factorial(int n)
        {
            if (n < 20)
            {
                return(XMath.Factorial(n));
            }

            var log2N = XMath.FloorLog2(n);
            var j     = log2N;
            var hN    = n;

            this.primeList  = new int[log2N][];
            this.listLength = new int[log2N];
            this.bound      = new int[log2N];
            this.tower      = new int[log2N + 1];

            while (true)
            {
                this.tower[j] = hN;
                if (hN == 1)
                {
                    break;
                }
                this.bound[--j] = hN / 3;
                var pLen = hN < 4 ? 6 : (int)(2.0 * (XMath.FloorSqrt(hN)
                                                     + (double)hN / (XMath.Log2(hN) - 1)));
                this.primeList[j] = new int[pLen];
                hN >>= 1;
            }

            this.tower[0] = 2;
            this.PrimeFactors(n);

            var init         = this.listLength[0] == 0 ? 1 : 3;
            var oddFactorial = new XInt(init);

            var results = new XInt[log2N];

            Parallel.For(1, log2N, i =>
                         results[i] = XMath.Product(this.primeList[i], 0, this.listLength[i])
                         );

            for (var i = 1; i < log2N; i++)
            {
                oddFactorial = XInt.Pow(oddFactorial, 2);
                oddFactorial = oddFactorial * results[i];
            }

            return(oddFactorial << (n - XMath.BitCount(n)));
        }
Пример #2
0
        public XInt Factorial(int n)
        {
            if (n < 20)
            {
                return(XMath.Factorial(n));
            }

            this.cache = new Dictionary <int, CachedPrimorial>();
            this.sieve = new PrimeSieve(n);

            var pLen = (int)(2.0 * (XMath.FloorSqrt(n)
                                    + (double)n / (XMath.Log2(n) - 1)));

            this.primeList = new int[pLen];

            var exp2 = n - XMath.BitCount(n);

            return(this.RecFactorial(n) << exp2);
        }