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