private int F2SmallParallel(long x1, long x2)
        {
            var xmin = UpToOdd(Math.Max(1, x1));
            var xmax = DownToOdd(Math.Min((long)IntegerMath.FloorSquareRoot(n), x2));

            if (threads <= 1)
            {
                return(F2SmallParallel(0, xmin, xmax, x1, 2));
            }

            var xsmall = DownToOdd(Math.Max(xmin, Math.Min(smallCutoff, xmax)));
            var s      = 0;

            for (var x = xmin; x < xsmall; x += 2)
            {
                s += IntegerMath.Mobius(x) * T2Parallel(n / ((UInt128)x * (UInt128)x));
            }
            var tasks     = new Task <int> [threads];
            var increment = 2 * threads;

            for (var thread = 0; thread < threads; thread++)
            {
                var worker = thread;
                var offset = 2 * thread;
                tasks[thread] = Task.Factory.StartNew(() => F2SmallParallel(worker, xsmall + offset, xmax, x1, increment));
            }
            Task.WaitAll(tasks);
            s += tasks.Select(task => task.Result).Sum();
            return(s & 3);
        }
        private int Pi2Small(long x1, long x2)
        {
            var s = F2SmallParallel(x1, x2);

            for (var k = 2; k <= kmax; k++)
            {
                var mu = IntegerMath.Mobius(k);
                if (mu != 0)
                {
                    s += mu * F2Small((UInt128)IntegerMath.FloorRoot((BigInteger)n, k), x1, x2);
                }
            }
            return(s & 3);
        }
Exemplo n.º 3
0
        private int FinishBlock(long k0, int length, sbyte[] products, sbyte[] values, long kmin, int[] sums, int sum0)
        {
            // Each product of a squareful number is less than zero.
            // Each product of a square-free number can have at most one
            // more prime factor.  It has that factor if the value of
            // the product is less half than the full value.
            var k    = k0;
            var kmax = k + 2 * length;
            var log2 = IntegerMath.CeilingLogBaseTwo(k) - 1;
            var next = Math.Min((long)1 << (log2 + 1), kmax - 2);

            if (sums == null)
            {
                while (k < kmax)
                {
                    while (k <= next)
                    {
                        // Look ma, no branching.
                        Debug.Assert(log2 == IntegerMath.CeilingLogBaseTwo(k) - 1);
                        var p    = (int)products[(k - k0) >> 1];
                        var flip = (log2 - p) >> 31; // flip = -1 if log2 < p, zero otherwise
                        values[(k - kmin) >> 1] = (sbyte)((((((p & 1) << 1) - 1) ^ flip) - flip) & ~(p >> 31));
                        Debug.Assert(values[(k - kmin) >> 1] == (sbyte)(p <0 ? 0 : p> log2 ? 1 - 2 * (p & 1) : 2 * (p & 1) - 1));
                        k += 2;
                    }
                    ++log2;
                    next = Math.Min(next << 1, kmax - 2);
                }
            }
            else if (values == null)
            {
                while (k < kmax)
                {
                    while (k <= next)
                    {
                        // Look ma, no branching.
                        Debug.Assert(log2 == IntegerMath.CeilingLogBaseTwo(k) - 1);
                        var p    = (int)products[(k - k0) >> 1];
                        var flip = (log2 - p) >> 31; // flip = -1 if log2 < p, zero otherwise
                        sums[(k - kmin) >> 1] = sum0 += (((((p & 1) << 1) - 1) ^ flip) - flip) & ~(p >> 31);
                        Debug.Assert(k == k0 || sums[(k - kmin) >> 1] - sums[(k - kmin - 2) >> 1] == (sbyte)(p <0 ? 0 : p> log2 ? 1 - 2 * (p & 1) : 2 * (p & 1) - 1));
                        k += 2;
                    }
                    ++log2;
                    next = Math.Min(next << 1, kmax - 2);
                }
            }
            else
            {
                while (k < kmax)
                {
                    while (k <= next)
                    {
                        // Look ma, no branching.
                        Debug.Assert(log2 == IntegerMath.CeilingLogBaseTwo(k) - 1);
                        var p     = (int)products[(k - k0) >> 1];
                        var flip  = (log2 - p) >> 31; // flip = -1 if log2 < p, zero otherwise
                        var value = (((((p & 1) << 1) - 1) ^ flip) - flip) & ~(p >> 31);
                        var kk    = (k - kmin) >> 1;
                        sums[kk]   = sum0 += value;
                        values[kk] = (sbyte)value;
                        Debug.Assert(values[(k - kmin) >> 1] == (sbyte)(p <0 ? 0 : p> log2 ? 1 - 2 * (p & 1) : 2 * (p & 1) - 1));
                        Debug.Assert(values[(k - kmin) >> 1] == IntegerMath.Mobius(k));
                        k += 2;
                    }
                    ++log2;
                    next = Math.Min(next << 1, kmax - 2);
                }
            }
            return(sum0);
        }
        public MertensFunctionWheel(int threads)
        {
            this.threads  = threads;
            wheelSubtotal = new int[wheelSize];
            wheelInclude  = new bool[wheelSize >> 1];
            wheelNext     = new byte[wheelSize >> 1];
            wheelPrev     = new byte[wheelSize >> 1];
            var total = 0;

            for (var i = 0; i < wheelSize; i++)
            {
                var include = IntegerMath.GreatestCommonDivisor(i, wheelSize) == 1;
                if (include)
                {
                    ++total;
                }
                wheelSubtotal[i]     = total;
                wheelInclude[i >> 1] = include;
            }
            Debug.Assert(total == wheelCount);
            var next = 0;

            for (var i = (wheelSize >> 1) - 1; i >= 0; i--)
            {
                next        += 2;
                wheelNext[i] = (byte)next;
                if (wheelInclude[i])
                {
                    next = 0;
                }
            }
            var prev = 0;

            for (var i = 0; i < (wheelSize >> 1); i++)
            {
                prev        += 2;
                wheelPrev[i] = (byte)prev;
                if (wheelInclude[i])
                {
                    prev = 0;
                }
            }
#if DEBUG
            for (var i = 1; i < wheelSize; i += 2)
            {
                var skip = wheelNext[i >> 1];
                for (var j = 2; j < skip; j += 2)
                {
                    if (wheelInclude[((i + j) % wheelSize) >> 1])
                    {
                        Debugger.Break();
                    }
                }
                if (!wheelInclude[((i + skip) % wheelSize) >> 1])
                {
                    Debugger.Break();
                }
            }
            for (var i = 1; i < wheelSize; i += 2)
            {
                var skip = wheelPrev[i >> 1];
                for (var j = 2; j < skip; j += 2)
                {
                    if (wheelInclude[((i - j + wheelSize) % wheelSize) >> 1])
                    {
                        Debugger.Break();
                    }
                }
                if (!wheelInclude[((i - skip + wheelSize) % wheelSize) >> 1])
                {
                    Debugger.Break();
                }
            }
#endif

            wheelFactors = IntegerMath.Factors(wheelSize).ToArray();
            wheelMobius  = wheelFactors.Select(factor => IntegerMath.Mobius(factor)).ToArray();
        }