コード例 #1
0
        public long Evaluate(long n)
        {
            if (n <= 0)
            {
                return(0);
            }

            this.n         = n;
            u              = Math.Max((long)IntegerMath.FloorPower((BigInteger)n, 2, 3) * C1 / C2, IntegerMath.CeilingSquareRoot(n));
            u              = DownToOdd(u);
            imax           = n / u;
            this.mobius    = new MobiusRange(imax + 1, threads);
            this.mobiusOdd = new MobiusOddRange(u + 2, threads);
            var batchSize = Math.Min(u + 1, maximumBatchSize);

            mu = new sbyte[imax];
            m  = new int[batchSize >> 1];

            sum = 0;
            mobius.GetValues(1, imax + 1, mu);
            var m0 = 0;

            for (var x = (long)1; x <= u; x += maximumBatchSize)
            {
                var xstart = x;
                var xend   = Math.Min(xstart + maximumBatchSize - 2, u);
                m0 = mobiusOdd.GetSums(xstart, xend + 2, m, m0);
                ProcessBatch(xstart, xend);
            }
            return(mi1 - sum);
        }
コード例 #2
0
        public long Evaluate(long n)
        {
            if (n <= 0)
            {
                return(0);
            }

            this.n      = n;
            u           = Math.Max((long)IntegerMath.FloorPower((BigInteger)n, 2, 3) * C1 / C2, IntegerMath.CeilingSquareRoot(n));
            imax        = n / u;
            this.mobius = new MobiusRange(u + 1, threads);
            var batchSize = Math.Min(u, maximumBatchSize);

            m  = new int[batchSize];
            mx = new long[imax + 1];

            var m0 = 0;

            for (var x = (long)1; x <= u; x += maximumBatchSize)
            {
                var xstart = x;
                var xend   = Math.Min(xstart + maximumBatchSize - 1, u);
                m0 = mobius.GetSums(xstart, xend + 1, m, m0);
                ProcessBatch(xstart, xend);
            }
            ComputeMx();
            return(mx[1]);
        }
コード例 #3
0
        public BigInteger Evaluate(BigInteger n)
        {
            this.n = n;
            if (n == 1)
            {
                return(1);
            }
            sum     = 0;
            imax    = (long)IntegerMath.FloorRoot(n, 5) / C1;
            xmax    = imax != 0 ? Xi(imax) : (long)IntegerMath.FloorPower(n, 1, 2);
            mobius  = new MobiusRange(xmax + 1, 0);
            mertens = new MertensRangeDR(mobius, Xi(1));
            xi      = new long[imax + 1];
            mx      = new long[imax + 1];

            // Initialize xi (mx already initialized to zeros).
            for (var i = 1; i <= imax; i++)
            {
                xi[i] = Xi(i);
            }

            if (threads <= 1)
            {
                var values = new sbyte[maximumBatchSize];
                var m      = new long[maximumBatchSize];
                Evaluate(1, xmax, values, m);
            }
            else
            {
                EvaluateParallel(1, xmax);
            }
            EvaluateTail();
            return(sum);
        }
コード例 #4
0
        public BigInteger Evaluate(BigInteger n)
        {
            this.n = n;
            if (n == 1)
            {
                return(1);
            }
            sum    = 0;
            imax   = (long)IntegerMath.FloorRoot(n, 5) * C1 / C2;
            xmax   = imax != 0 ? Xi(imax) : (long)IntegerMath.FloorPower(n, 1, 2);
            mobius = new MobiusRangeAdditive(xmax + 1, threads);
            xi     = new long[imax + 1];
            mx     = new long[imax + 1];

            // Initialize xi.
            for (var i = 1; i <= imax; i++)
            {
                xi[i] = Xi(i);
            }

            values = new sbyte[maximumBatchSize];
            m      = new int[maximumBatchSize];
            m0     = 0;
            for (var x = (long)1; x <= xmax; x += maximumBatchSize)
            {
                m0 = EvaluateBatch(x, Math.Min(xmax, x + maximumBatchSize - 1));
            }

            EvaluateTail();
            return(sum);
        }
コード例 #5
0
        public MertensRangeBasic(MobiusRange mobius, long nmax)
        {
            this.mobius = mobius;
            this.nmax   = nmax;
            threads     = mobius.Threads;

            u   = Math.Max((long)IntegerMath.FloorPower((BigInteger)nmax, 2, 3) * C1 / C2, IntegerMath.CeilingSquareRoot(nmax));
            ulo = Math.Min(u, maximumBatchSize);
            mlo = new int[ulo];
            mobius.GetSums(1, ulo + 1, mlo, 0);
        }
コード例 #6
0
        private void ProduceItems(BlockingCollection <WorkItem> queue, long imin, long imax)
        {
#if false
            BatchRange(queue, imin, imax);
#else
            var split1 = (long)IntegerMath.FloorPower(n, 1, 5);
            var split2 = (long)IntegerMath.FloorPower(n, 1, 4);
            BatchRange(queue, imin, split1);
            BatchRange(queue, split1 + 1, split2);
            BatchRange(queue, split2 + 1, imax);
#endif
        }
コード例 #7
0
        public MertensRangeDR(MobiusRange mobius, long nmax)
        {
            this.mobius = mobius;
            this.nmax   = nmax;
            threads     = mobius.Threads;

            u      = Math.Max((long)IntegerMath.FloorPower((BigInteger)nmax, 2, 3) * C1 / C2, IntegerMath.CeilingSquareRoot(nmax));
            ulo    = Math.Max(Math.Min(u, maximumBatchSize), minimumLowSize);
            mlo    = new int[ulo];
            values = new sbyte[ulo];
            mobius.GetValuesAndSums(1, ulo + 1, values, mlo, 0);
        }
コード例 #8
0
        public int Evaluate(UInt128 n)
        {
            this.n = n;
            var sum = 0;

            sqrtn = (long)IntegerMath.FloorSquareRoot(n);
            kmax  = (int)IntegerMath.FloorLog(n, 2);
            imax  = (long)IntegerMath.FloorPower(n, 1, 5) * C1 / C2;
            xmax  = DownToOdd(imax != 0 ? Xi(imax) : sqrtn);
            xmed  = DownToOdd(Math.Min((long)(IntegerMath.FloorPower(n, 2, 7) * C3 / C4), xmax));
            var dmax = (long)IntegerMath.Min(n / IntegerMath.Square((UInt128)xmed) + 1, n);

            mobius   = new MobiusOddRangeAdditive((xmax + 2) | 1, threads);
            divisors = new DivisorOddRangeAdditive((dmax + 2) | 1, threads);
            xi       = new long[imax + 1];
            mx       = new long[imax + 1];

            // Initialize xi.
            for (var i = 1; i <= imax; i++)
            {
                xi[i] = Xi(i);
            }

            values = new sbyte[mobiusBatchSize >> 1];
            m      = new int[mobiusBatchSize >> 1];
            m0     = 0;
            dsums  = new ulong[divisorBatchSize >> 1];
            d1     = d2 = 1;

            // Process small x values.
            for (var x = (long)1; x <= xmed; x += mobiusBatchSize)
            {
                var xfirst = x;
                var xlast  = Math.Min(xmed, xfirst + mobiusBatchSize - 2);
                m0   = mobius.GetValuesAndSums(xfirst, xlast + 2, values, m, m0);
                sum += Pi2Small(xfirst, xlast);
                UpdateMx(xfirst, xlast);
            }

            // Process medium x values.
#if true
            for (var x = xmed + 2; x <= xmax; x += mobiusBatchSize)
            {
                var xfirst = x;
                var xlast  = Math.Min(xmax, xfirst + mobiusBatchSize - 2);
                m0   = mobius.GetValuesAndSums(xfirst, xlast + 2, values, m, m0);
                sum += Pi2Medium(xfirst, xlast);
                UpdateMx(xfirst, xlast);
            }
#else
            for (var x = xmax; x > xmed; x -= mobiusBatchSize)
            {
                var xlast  = x;
                var xfirst = Math.Max(xmed + 2, xlast - mobiusBatchSize + 2);
                m0   = mobius.GetValuesAndSums(xfirst, xlast + 2, values, m, m0);
                sum += Pi2Medium(xfirst, xlast);
                UpdateMx(xfirst, xlast);
            }
#endif

            // Process large x values.
            sum += Pi2Large();

            // Adjust for final parity of F2.
            sum -= IntegerMath.Mertens(kmax);

            // Compute final result.
            sum &= 3;
            Debug.Assert((sum & 1) == 0);
            sum >>= 1;
            return((sum + (n >= 2 ? 1 : 0)) % 2);
        }
コード例 #9
0
 public MertensRangeInverted(long nmax, int threads)
     : this(new MobiusRange((long)IntegerMath.FloorPower((BigInteger)nmax, 2, 3) + 1, threads), nmax)
 {
 }
コード例 #10
0
        public Int128 Evaluate(UInt128 n)
        {
            if (n == 0)
            {
                return(0);
            }

            this.n = n;
            u      = (long)IntegerMath.Max(IntegerMath.FloorPower(n, 2, 3) * C1 / C2, IntegerMath.CeilingSquareRoot(n));

            imax   = (int)(n / (ulong)u);
            mobius = new MobiusRangeAdditive(u + 1, threads);
            var batchSize = Math.Min(u, maximumBatchSize);

            mu = new sbyte[maximumSmallBatchSize];
            m  = new int[batchSize];
            mx = new Int128[imax + 1];
            r  = new int[imax + 1];
            var lmax = 0;

            for (var i = 1; i <= imax; i += 2)
            {
                if (wheelInclude[(i % wheelSize) >> 1])
                {
                    r[lmax++] = i;
                }
            }
            Array.Resize(ref r, lmax);

            niLarge = new UInt128[imax + 1];
            niSmall = new long[imax + 1];
            var buckets          = Math.Max(1, threads);
            var costs            = new double[buckets];
            var bucketListsLarge = Enumerable.Range(0, buckets).Select(i => new List <int>()).ToArray();
            var bucketListsSmall = Enumerable.Range(0, buckets).Select(i => new List <int>()).ToArray();

            for (var l = 0; l < lmax; l++)
            {
                var i       = r[l];
                var ni      = n / (uint)i;
                var large   = ni > largeLimit;
                var cost    = Math.Sqrt((double)n / i) * (large ? C7 : 1);
                var addto   = 0;
                var mincost = costs[0];
                for (var bucket = 0; bucket < buckets; bucket++)
                {
                    if (costs[bucket] < mincost)
                    {
                        mincost = costs[bucket];
                        addto   = bucket;
                    }
                }
                niLarge[i] = ni;
                if (large)
                {
                    bucketListsLarge[addto].Add(i);
                }
                else
                {
                    niSmall[i] = (long)ni;
                    bucketListsSmall[addto].Add(i);
                }
                costs[addto] += cost;
            }
            bucketsLarge = bucketListsLarge.Select(bucket => bucket.ToArray()).ToArray();
            bucketsSmall = bucketListsSmall.Select(bucket => bucket.ToArray()).ToArray();

            var m0   = 0;
            var xmed = Math.Min((long)IntegerMath.FloorRoot(n, 2) * C5 / C6, u);

            for (var x = (long)1; x <= xmed; x += maximumSmallBatchSize)
            {
                var xstart = x;
                var xend   = Math.Min(xstart + maximumSmallBatchSize - 1, xmed);
                m0 = mobius.GetValuesAndSums(xstart, xend + 1, mu, m, m0);
                ProcessBatch(xstart, xend);
            }
            for (var x = xmed + 1; x <= u; x += maximumBatchSize)
            {
                var xstart = x;
                var xend   = Math.Min(xstart + maximumBatchSize - 1, u);
                m0 = mobius.GetSums(xstart, xend + 1, m, m0);
                ProcessBatch(xstart, xend);
            }
            ComputeMx();
            return(mx[1]);
        }
コード例 #11
0
        public long Evaluate(long n)
        {
            if (n <= 0)
            {
                return(0);
            }

            this.n = n;
            u      = Math.Max((long)IntegerMath.FloorPower((BigInteger)n, 2, 3) * C1 / C2, IntegerMath.CeilingSquareRoot(n));

            if (u <= wheelSize)
            {
                return(new MertensFunctionDR(threads).Evaluate(n));
            }

            imax   = (int)(n / u);
            mobius = new MobiusRange(u + 1, threads);
            var batchSize = Math.Min(u, maximumBatchSize);

            m  = new int[batchSize];
            mx = new long[imax + 1];
            r  = new int[imax + 1];

            lmax = 0;
            for (var i = 1; i <= imax; i += 2)
            {
                if (wheelInclude[(i % wheelSize) >> 1])
                {
                    r[lmax++] = i;
                }
            }
            Array.Resize(ref r, lmax);

            if (threads > 1)
            {
                var costs       = new double[threads];
                var bucketLists = new List <int> [threads];
                for (var thread = 0; thread < threads; thread++)
                {
                    bucketLists[thread] = new List <int>();
                }
                for (var l = 0; l < lmax; l++)
                {
                    var i       = r[l];
                    var cost    = Math.Sqrt(n / i);
                    var addto   = 0;
                    var mincost = costs[0];
                    for (var thread = 0; thread < threads; thread++)
                    {
                        if (costs[thread] < mincost)
                        {
                            mincost = costs[thread];
                            addto   = thread;
                        }
                    }
                    bucketLists[addto].Add(i);
                    costs[addto] += cost;
                }
                buckets = new int[threads][];
                for (var thread = 0; thread < threads; thread++)
                {
                    buckets[thread] = bucketLists[thread].ToArray();
                }
            }

            var m0 = 0;

            for (var x = (long)1; x <= u; x += maximumBatchSize)
            {
                var xstart = x;
                var xend   = Math.Min(xstart + maximumBatchSize - 1, u);
                m0 = mobius.GetSums(xstart, xend + 1, m, m0);
                ProcessBatch(xstart, xend);
            }
            ComputeMx();
            return(mx[1]);
        }