void DoTest(Candidate cand, int n, bool showFullValue, bool verbose)
        {
            this.watch.Reset();
            this.watch.Start();
            XInt nFact = cand.GetValue(n);

            this.watch.Stop();

            int checksum = nFact.GetHashCode();
            var ms       = this.watch.ElapsedMilliseconds;
            var eddms    = XMath.ExactDecimalDigitsPerMillisecond(n, ms);
            var res      = new Result(cand, ms, checksum, eddms);

            cand.Performance[n] = res;

            if (verbose)
            {
                this.winsole.WriteRed(string.Format(
                                          // "\nSUMMARY: Computed the factorial "
                                          "\n{0}! = {1}\nAlgorithm used: {2}\nCheckSum: <{3:X}>\nComputation in {4:D} ms.\nDecimal digits per ms {5}.\n",
                                          n, XMath.AsymptFactorial(n), cand.Name, checksum, ms, eddms));
            }

            if (showFullValue)
            {
                this.winsole.Write(nl + "Now converting to string. Note: It takes longer to convert than to compute!" + nl + nl);
                this.winsole.WriteLine(nFact.ToString());
            }
        }
        public void SanityCheck(int length)
        {
            bool ok = true;

            for (int n = 0; n < length; n++)
            {
                XInt r = Candidate.Reference.GetValue(n);

                foreach (Candidate cand in Candidate.Sanity)
                {
                    XInt t = cand.GetValue(n);
                    if (!t.Equals(r))
                    {
                        this.winsole.WriteLine(string.Format(
                                                   "\n{0}({1}) failed!", cand.Name.Trim(), n));
                        ok = false;
                    }
                }
                if ((n % 10) == 0)
                {
                    this.winsole.WriteFlush(" . ");
                }
                if ((n % 150) == 149)
                {
                    this.winsole.WriteLine();
                }
            }

            this.winsole.Write("\nWell, some values will" + (ok ? " " : " not ") +
                               "give correct results  " + (ok ? ";-)\n" : "~:(\n"));
        }
        private XInt RecFactorial(int n)
        {
            if (n < 2)
            {
                return(XInt.One);
            }

            return(XInt.Pow(this.RecFactorial(n / 2), 2) * this.Swing(n));
        }
        static XInt OddSwing(int n, XInt oddFactNdiv4)
        {
            if (n < Smallswing) return SmallOddSwing[n];

            var len = (n - 1) / 4;
            if ((n % 4) != 2) len++;
            var high = n - ((n + 1) & 1);

            return Product(high, len) / oddFactNdiv4;
        }
        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 < 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));
        }
        private XInt RecFactorial3(int n)
        {
            if (n < 2)
            {
                return(XInt.One);
            }

            var recFact = this.RecFactorial3(n / 2);
            var sqrFact = XInt.Pow(recFact, 2);
            var swing   = n < Smallswing
                      ? SmallOddSwing3[n]
                      : this.swingDelegate3.EndInvoke(this.results3[--this.taskCounter3]);

            return(sqrFact * swing);
        }
        static XInt OddSwing(int n, XInt oddFactNdiv4)
        {
            if (n < Smallswing)
            {
                return(SmallOddSwing[n]);
            }

            var len = (n - 1) / 4;

            if ((n % 4) != 2)
            {
                len++;
            }
            var high = n - ((n + 1) & 1);

            return(Product(high, len) / oddFactNdiv4);
        }
Beispiel #9
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 OddFactorial(int n)
        {
            XInt oddFact;

            if (n < Smallfact)
            {
                oddFact = SmallOddFactorial[n];
            }
            else
            {
                var sqrOddFact = this.OddFactorial(n / 2);
                var ndiv4      = n / 4;
                var oddFactNd4 = ndiv4 < Smallfact
                               ? SmallOddFactorial[ndiv4]
                               : this.oddFactNdiv4;

                oddFact = XInt.Pow(sqrOddFact, 2) * OddSwing(n, oddFactNd4);
            }

            this.oddFactNdiv4 = this.oddFactNdiv2;
            this.oddFactNdiv2 = oddFact;
            return(oddFact);
        }
        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 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;
        }
        private static XInt BigRecProduct(XInt[] s, int n, int m)
        {
            if (n > m)
            {
                return XInt.One;
            }
            if (n == m)
            {
                return s[n];
            }

            int k = (n + m) >> 1;
            return BigRecProduct(s, n, k) * BigRecProduct(s, k + 1, m);
        }
        public static XInt Product(XInt[] a, int start, int len)
        {
            int n = len - 1;
            if (len > ParallelThreshold)
            {
                var task = Task.Factory.StartNew<XInt>(() =>
                {
                    return BigRecProduct(a, start + n / 2 + 1, start + n);
                });

                var left = BigRecProduct(a, start, start + n / 2);
                return left * task.Result;
            }

            return BigRecProduct(a, start, n);
        }
        private XInt OddFactorial(int n)
        {
            XInt oddFact;

            if (n < Smallfact)
            {
                oddFact = SmallOddFactorial[n];
            }
            else
            {
                var sqrOddFact = this.OddFactorial(n / 2);
                var ndiv4 = n / 4;
                var oddFactNd4 = ndiv4 < Smallfact
                               ? SmallOddFactorial[ndiv4]
                               : this.oddFactNdiv4;

                oddFact = XInt.Pow(sqrOddFact, 2) * OddSwing(n, oddFactNd4);
            }

            this.oddFactNdiv4 = this.oddFactNdiv2;
            this.oddFactNdiv2 = oddFact;
            return oddFact;
        }
 public static XInt Product(XInt[] a)
 {
     return BigRecProduct(a, 0, a.Length - 1);
 }
        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);
        }