예제 #1
0
        public MobiusOddRangeAdditive(long size, int threads)
        {
            this.size    = size;
            this.threads = threads;
            var limit = (int)Math.Ceiling(Math.Sqrt(size));

            primes    = new PrimeCollection(limit, 0).Select(p => (int)p).ToArray();
            logPrimes = primes.Select(p => (sbyte)(IntegerMath.CeilingLogBaseTwo(p) | 1)).ToArray();
            CreateCycle();
            var arrayLength = Math.Max(1, threads);

            queue = new ConcurrentQueue <Data>();
        }
예제 #2
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);
        }
예제 #3
0
        private ulong FinishBlock(long k0, int length, sbyte[] products, ushort[] values, long kmin, ulong[] sums, long smin, ulong sum0, bool onlySums)
        {
            // Each product can have at most one more prime factor.
            // It has that factor if the value of the product is
            // less than the full value.
            var k    = k0;
            var kmax = k + 2 * length;
            var log2 = IntegerMath.CeilingLogBaseTwo(k);
            var next = Math.Min((long)1 << log2, kmax - 2);

            if (onlySums)
            {
                var kk = 0;
                while (k < kmax)
                {
                    while (k <= next)
                    {
                        // Look ma, no branching.
                        Debug.Assert(log2 == IntegerMath.CeilingLogBaseTwo(k));
                        var value = (uint)values[kk];
                        sums[(k - smin) >> 1] = sum0 += value + ((uint)((products[kk] - log2) >> 31) & value);
                        Debug.Assert(k == k0 || (int)(sums[(k - smin) >> 1] - sums[(k - smin - 2) >> 1]) == (products[kk] > log2 - 1 ? value : 2 * value));
                        k += 2;
                        ++kk;
                    }
                    ++log2;
                    next = Math.Min(next << 1, kmax - 2);
                }
            }
            else if (sums == null)
            {
                while (k < kmax)
                {
                    while (k <= next)
                    {
                        // Look ma, no branching.
                        Debug.Assert(log2 == IntegerMath.CeilingLogBaseTwo(k));
                        var kk    = (k - kmin) >> 1;
                        var value = (uint)values[kk];
                        sum0 += values[kk] = (ushort)(value + ((uint)((products[(k - k0) >> 1] - log2) >> 31) & value));
                        Debug.Assert(values[kk] == (products[(k - k0) >> 1] > log2 - 1 ? value : 2 * value));
                        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));
                        var kk    = (k - kmin) >> 1;
                        var value = (uint)values[kk];
                        sums[(k - smin) >> 1] = sum0 += values[kk] = (ushort)(value + ((uint)((products[(k - k0) >> 1] - log2) >> 31) & value));
                        Debug.Assert(values[kk] == (products[(k - k0) >> 1] > log2 - 1 ? value : 2 * value));
                        Debug.Assert(k == k0 || (int)(sums[(k - smin) >> 1] - sums[(k - smin - 2) >> 1]) == (products[(k - k0) >> 1] > log2 - 1 ? value : 2 * value));
                        k += 2;
                    }
                    ++log2;
                    next = Math.Min(next << 1, kmax - 2);
                }
            }
            return(sum0);
        }