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);

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

            sum = 0;
            mobius.GetValues(0, imax + 1, mu);
            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);
            }
            return(-sum);
        }
예제 #2
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));
            }
        }
예제 #3
0
        private long EvaluateBatch(long x1, long x2, sbyte[] values, long[] m, long m0)
        {
            var x = x2;

            mobius.GetValues(x1, x2 + 1, values);
            if (!simple)
            {
                x = S1(x1, x, values);
            }
            x = S3(x1, x, values);

            var s    = m0;
            var kmax = x2 - x1;

            for (var k = 0; k <= kmax; k++)
            {
                s   += values[k];
                m[k] = s;
            }
            UpdateMx(m, x1, x2);
            return(s);
        }