public long Evaluate(long n) { if (n <= 0) { return(0); } this.n = n; u = Math.Max((long)IntegerMath.FloorPower((BigInteger)n, 2, 3) * C1 / C2, IntegerMath.CeilingSquareRoot(n)); imax = n / u; this.mobius = new MobiusRange(u + 1, threads); var batchSize = Math.Min(u, maximumBatchSize); mu = new sbyte[imax + 1]; m = new int[batchSize]; sum = 0; mobius.GetValues(0, imax + 1, mu); var m0 = 0; for (var x = (long)1; x <= u; x += maximumBatchSize) { var xstart = x; var xend = Math.Min(xstart + maximumBatchSize - 1, u); m0 = mobius.GetSums(xstart, xend + 1, m, m0); ProcessBatch(xstart, xend); } return(-sum); }
private void ConsumeSumTwoToTheOmegaItems(int thread, BlockingCollection <WorkItem> queue, MobiusRange mobius, UInt128 x, ref int sum) { var values = new sbyte[blockSize]; var item = default(WorkItem); while (queue.TryTake(out item, Timeout.Infinite)) { if (item.Max == item.Min + 1 && item.Min < (ulong)mobiusSmall.Length) { values[0] = (sbyte)mobiusSmall[item.Min]; } else { mobius.GetValues((long)item.Min, (long)item.Max, values); } Interlocked.Add(ref sum, SumTwoToTheOmega(values, x, item.Min, item.Max)); } }
private long EvaluateBatch(long x1, long x2, sbyte[] values, long[] m, long m0) { var x = x2; mobius.GetValues(x1, x2 + 1, values); if (!simple) { x = S1(x1, x, values); } x = S3(x1, x, values); var s = m0; var kmax = x2 - x1; for (var k = 0; k <= kmax; k++) { s += values[k]; m[k] = s; } UpdateMx(m, x1, x2); return(s); }