예제 #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));
            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]);
        }
예제 #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));
            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);
        }
예제 #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);
        }
        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);
        }
예제 #5
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);
        }
예제 #6
0
        private void ConsumeSumTwoToTheOmegaItems(int thread, BlockingCollection <WorkItem> queue, MobiusRange mobius, UInt128 x, ref int sum)
        {
            var values = new sbyte[blockSize];
            var item   = default(WorkItem);

            while (queue.TryTake(out item, Timeout.Infinite))
            {
                if (item.Max == item.Min + 1 && item.Min < (ulong)mobiusSmall.Length)
                {
                    values[0] = (sbyte)mobiusSmall[item.Min];
                }
                else
                {
                    mobius.GetValues((long)item.Min, (long)item.Max, values);
                }
                Interlocked.Add(ref sum, SumTwoToTheOmega(values, x, item.Min, item.Max));
            }
        }
예제 #7
0
        private int SumTwoToTheOmega(UInt128 x, ulong limit)
        {
            var sum = 0;

            ulong d;

            for (d = 1; d < singleLimit1; d++)
            {
                var mu = mobiusSmall[d];
                if (mu != 0)
                {
                    var tau = TauSumParallel(x / (d * d));
                    if (mu == 1)
                    {
                        sum += tau;
                    }
                    else
                    {
                        sum += 4 - tau;
                    }
                }
            }

            var mobius    = new MobiusRange((long)limit + 1, 0);
            var queue     = new BlockingCollection <WorkItem>();
            var units     = limit < (1 << 16) ? 1 : 100;
            var consumers = Math.Max(1, threads);
            var tasks     = new Task[consumers];

            for (var consumer = 0; consumer < consumers; consumer++)
            {
                var thread = consumer;
                tasks[consumer] = Task.Factory.StartNew(() => ConsumeSumTwoToTheOmegaItems(thread, queue, mobius, x, ref sum));
            }

            for (d = singleLimit1; d < singleLimit2; d++)
            {
                if (mobiusSmall[d] != 0)
                {
                    queue.Add(new WorkItem {
                        Min = d, Max = d + 1
                    });
                }
            }

            for (var unit = 0; unit < units; unit++)
            {
                var dmin = d;
                var dmax = unit == units - 1 ? limit + 1 : (ulong)Math.Exp((unit + 1) * Math.Log(limit + 1) / units);
                if (dmin >= dmax)
                {
                    continue;
                }
                if (dmax - dmin > blockSize)
                {
                    break;
                }
                queue.Add(new WorkItem {
                    Min = dmin, Max = dmax
                });
                d = dmax;
            }

            while (d < limit + 1)
            {
                var dmin = d;
                var dmax = Math.Min(dmin + blockSize, limit + 1);
                queue.Add(new WorkItem {
                    Min = dmin, Max = dmax
                });
                d = dmax;
            }

            queue.CompleteAdding();
            Task.WaitAll(tasks);
            return(sum & 3);
        }
        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]);
        }