public XInt Factorial(int n)
        {
            if (n < 0)
            {
                throw new ArithmeticException(
                          this.Name + ": " + nameof(n) + " >= 0 required, but was " + n);
            }

            this.oddFactNdiv4 = this.oddFactNdiv2 = XInt.One;

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

            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);
        }
        public XInt Factorial(int n)
        {
            if (n < 20)
            {
                return(XMath.Factorial(n));
            }

            var sieve = new PrimeSieve(n);

            var task2 = Task.Factory.StartNew <XInt>(() =>
            {
                this.results2       = new IAsyncResult[XMath.FloorLog2(n)];
                this.swingDelegate2 = Swing2;
                this.taskCounter2   = 0;

                var N = n;

                // -- It is more efficient to add the big swings
                // -- first and the small ones later!
                while (N >= Smallswing)
                {
                    this.results2[this.taskCounter2++] = this.swingDelegate2.BeginInvoke(sieve, N, null, null);
                    N >>= 1;
                }
                return(this.RecFactorial2(n));
            });

            this.results3       = new IAsyncResult[XMath.FloorLog2(n)];
            this.swingDelegate3 = Swing3;
            this.taskCounter3   = 0;

            var m = n;

            // -- It is more efficient to add the big swings
            // -- first and the small ones later!
            while (m >= Smallswing)
            {
                this.results3[this.taskCounter3++] = this.swingDelegate3.BeginInvoke(sieve, m, null, null);
                m >>= 1;
            }

            var task3Result = this.RecFactorial3(n);

            return((task2.Result * task3Result) << (n - XMath.BitCount(n)));
        }
        private static XInt Swing3(PrimeSieve sieve, int n)
        {
            var primorial = Task.Factory.StartNew <XInt>(() =>
            {
                var start = sieve.NextPrime(n / 2);
                start     = sieve.NextPrime(start);
                return(sieve.GetPrimorial(start, n, 2));
            });

            var count      = 0;
            var rootN      = XMath.FloorSqrt(n);
            var startPrime = sieve.NextPrime(rootN);

            startPrime = sieve.NextPrime(startPrime);
            var aPrimes   = sieve.GetPrimeCollectionEveryOther(5, rootN);
            var bPrimes   = sieve.GetPrimeCollectionEveryOther(startPrime, n / 3);
            var primeList = new int[aPrimes.NumberOfPrimes + bPrimes.NumberOfPrimes];

            foreach (var prime in aPrimes)
            {
                int q = n, p = 1;

                while ((q /= prime) > 0)
                {
                    if ((q & 1) == 1)
                    {
                        p *= prime;
                    }
                }

                if (p > 1)
                {
                    primeList[count++] = p;
                }
            }

            foreach (var prime in bPrimes.Where(prime => ((n / prime) & 1) == 1))
            {
                primeList[count++] = prime;
            }

            var primeProduct = XMath.Product(primeList, 0, count);

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

            var lgN = XMath.FloorLog2(n);
            var piN = 2 + (15 * n) / (8 * (lgN - 1));

            this.primeList = new int[piN];
            this.multiList = new int[piN];

            var len  = this.PrimeFactors(n);
            var exp2 = n - XMath.BitCount(n);

            return(this.NestedSquare(len) << exp2);
        }
示例#6
0
        XInt Swing(int n)
        {
            if (n < 33)
            {
                return(SmallOddSwing[n]);
            }

            var primorial = Task.Factory.StartNew <XInt>(() =>
                                                         this.sieve.GetPrimorial(n / 2 + 1, n));
            var count     = 0;
            var rootN     = XMath.FloorSqrt(n);
            var aPrimes   = this.sieve.GetPrimeCollection(3, rootN);
            var bPrimes   = this.sieve.GetPrimeCollection(rootN + 1, n / 3);
            var piN       = aPrimes.NumberOfPrimes + bPrimes.NumberOfPrimes;
            var primeList = new int[piN];

            foreach (var prime in aPrimes)
            {
                int q = n, p = 1;

                while ((q /= prime) > 0)
                {
                    if ((q & 1) == 1)
                    {
                        p *= prime;
                    }
                }

                if (p > 1)
                {
                    primeList[count++] = p;
                }
            }

            foreach (var prime in bPrimes.Where(prime => ((n / prime) & 1) == 1))
            {
                primeList[count++] = prime;
            }

            var primeProduct = XMath.Product(primeList, 0, count);

            return(primeProduct * primorial.Result);
        }
示例#7
0
        public XInt Factorial(int n)
        {
            if (n < 20)
            {
                return(XMath.Factorial(n));
            }

            this.sieve = new PrimeSieve(n);
            var log2N = XMath.FloorLog2(n);
            var source = new int[log2N];
            int h = 0, shift = 0, length = 0;

            // -- It is more efficient to add the big intervals
            // -- first and the small ones later! Is it?
            while (h != n)
            {
                shift += h;
                h      = n >> log2N--;
                if (h > 2)
                {
                    source[length++] = h;
                }
            }

            var results = new XInt[length];

            Parallel.For(0, length, currentIndex =>
                         results[currentIndex] = this.Swing(source[currentIndex])
                         );

            XInt p = XInt.One, r = XInt.One, rl = XInt.One;

            for (var i = 0; i < length; i++)
            {
                var t = rl * results[i];
                p  = p * t;
                rl = r;
                r  = r * p;
            }

            return(r << shift);
        }
        private XInt Swing(int n)
        {
            if (n < 33)
            {
                return(SmallOddSwing[n]);
            }

            int count = 0, rootN = XMath.FloorSqrt(n);

            var aPrimes = this.sieve.GetPrimeCollection(3, rootN);
            var bPrimes = this.sieve.GetPrimeCollection(rootN + 1, n / 3);

            foreach (var prime in aPrimes)
            {
                int q = n, p = 1;

                while ((q /= prime) > 0)
                {
                    if ((q & 1) == 1)
                    {
                        p *= prime;
                    }
                }

                if (p > 1)
                {
                    this.primeList[count++] = p;
                }
            }

            foreach (var prime in bPrimes.Where(prime => ((n / prime) & 1) == 1))
            {
                this.primeList[count++] = prime;
            }

            var primorial = this.sieve.GetPrimorial(n / 2 + 1, n);

            return(primorial * XMath.Product(this.primeList, 0, count));
        }
        private XInt NestedSquare(int len)
        {
            if (len == 0)
            {
                return(XInt.One);
            }

            var i    = 0;
            var mult = this.multiList[0];

            while (mult > 1)
            {
                if ((mult & 1) == 1)  // is mult odd ?
                {
                    this.primeList[len++] = this.primeList[i];
                }

                this.multiList[i++] = mult >> 1;
                mult = this.multiList[i];
            }

            return(XMath.Product(this.primeList, i, len - i)
                   * XInt.Pow(this.NestedSquare(i), 2));
        }
        public XInt Factorial(int n)
        {
            if (n < 20)
            {
                return(XMath.Factorial(n));
            }

            var rootN   = XMath.FloorSqrt(n);
            var log2N   = XMath.FloorLog2(n);
            var section = new XInt[log2N + 1];

            for (var i = 0; i < section.Length; i++)
            {
                section[i] = XInt.One;
            }

            var sieve  = new PrimeSieve(n);
            var primes = sieve.GetPrimeCollection(3, rootN);

            foreach (var prime in primes)
            {
                int k = 0, m = 0, q = n;

                do
                {
                    m += q /= prime;
                } while (q >= 1);

                while (m > 0)
                {
                    if ((m & 1) == 1)
                    {
                        section[k] *= prime;
                    }
                    m = m / 2;
                    k++;
                }
            }

            var j   = 2;
            var low = n;

            while (low != rootN)
            {
                var high = low;
                low = n / j++;

                if (low < rootN)
                {
                    low = rootN;
                }

                var primorial = sieve.GetPrimorial(low + 1, high);

                if (primorial != XInt.One)
                {
                    int k = 0, m = j - 2;

                    while (m > 0)
                    {
                        if ((m & 1) == 1)
                        {
                            section[k] *= primorial;
                        }
                        m = m / 2;
                        k++;
                    }
                }
            }

            var factorial = section[log2N];

            for (var i = log2N - 1; i >= 0; --i)
            {
                factorial = XInt.Pow(factorial, 2) * section[i];
            }

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

            return(factorial << exp2N);
        }