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