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