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); m = new int[batchSize]; mx = new long[imax + 1]; 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); } ComputeMx(); return(mx[1]); }
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)); u = DownToOdd(u); imax = n / u; this.mobius = new MobiusRange(imax + 1, threads); this.mobiusOdd = new MobiusOddRange(u + 2, threads); var batchSize = Math.Min(u + 1, maximumBatchSize); mu = new sbyte[imax]; m = new int[batchSize >> 1]; sum = 0; mobius.GetValues(1, imax + 1, mu); var m0 = 0; for (var x = (long)1; x <= u; x += maximumBatchSize) { var xstart = x; var xend = Math.Min(xstart + maximumBatchSize - 2, u); m0 = mobiusOdd.GetSums(xstart, xend + 2, m, m0); ProcessBatch(xstart, xend); } return(mi1 - sum); }
public BigInteger Evaluate(BigInteger n) { this.n = n; if (n == 1) { return(1); } sum = 0; imax = (long)IntegerMath.FloorRoot(n, 5) / C1; xmax = imax != 0 ? Xi(imax) : (long)IntegerMath.FloorPower(n, 1, 2); mobius = new MobiusRange(xmax + 1, 0); mertens = new MertensRangeDR(mobius, Xi(1)); xi = new long[imax + 1]; mx = new long[imax + 1]; // Initialize xi (mx already initialized to zeros). for (var i = 1; i <= imax; i++) { xi[i] = Xi(i); } if (threads <= 1) { var values = new sbyte[maximumBatchSize]; var m = new long[maximumBatchSize]; Evaluate(1, xmax, values, m); } else { EvaluateParallel(1, xmax); } EvaluateTail(); return(sum); }
public MertensRangeBasic(MobiusRange mobius, long nmax) { this.mobius = mobius; this.nmax = nmax; threads = mobius.Threads; u = Math.Max((long)IntegerMath.FloorPower((BigInteger)nmax, 2, 3) * C1 / C2, IntegerMath.CeilingSquareRoot(nmax)); ulo = Math.Min(u, maximumBatchSize); mlo = new int[ulo]; mobius.GetSums(1, ulo + 1, mlo, 0); }
public MertensRangeDR(MobiusRange mobius, long nmax) { this.mobius = mobius; this.nmax = nmax; threads = mobius.Threads; u = Math.Max((long)IntegerMath.FloorPower((BigInteger)nmax, 2, 3) * C1 / C2, IntegerMath.CeilingSquareRoot(nmax)); ulo = Math.Max(Math.Min(u, maximumBatchSize), minimumLowSize); mlo = new int[ulo]; values = new sbyte[ulo]; mobius.GetValuesAndSums(1, ulo + 1, values, mlo, 0); }
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 int SumTwoToTheOmega(UInt128 x, ulong limit) { var sum = 0; ulong d; for (d = 1; d < singleLimit1; d++) { var mu = mobiusSmall[d]; if (mu != 0) { var tau = TauSumParallel(x / (d * d)); if (mu == 1) { sum += tau; } else { sum += 4 - tau; } } } var mobius = new MobiusRange((long)limit + 1, 0); var queue = new BlockingCollection <WorkItem>(); var units = limit < (1 << 16) ? 1 : 100; var consumers = Math.Max(1, threads); var tasks = new Task[consumers]; for (var consumer = 0; consumer < consumers; consumer++) { var thread = consumer; tasks[consumer] = Task.Factory.StartNew(() => ConsumeSumTwoToTheOmegaItems(thread, queue, mobius, x, ref sum)); } for (d = singleLimit1; d < singleLimit2; d++) { if (mobiusSmall[d] != 0) { queue.Add(new WorkItem { Min = d, Max = d + 1 }); } } for (var unit = 0; unit < units; unit++) { var dmin = d; var dmax = unit == units - 1 ? limit + 1 : (ulong)Math.Exp((unit + 1) * Math.Log(limit + 1) / units); if (dmin >= dmax) { continue; } if (dmax - dmin > blockSize) { break; } queue.Add(new WorkItem { Min = dmin, Max = dmax }); d = dmax; } while (d < limit + 1) { var dmin = d; var dmax = Math.Min(dmin + blockSize, limit + 1); queue.Add(new WorkItem { Min = dmin, Max = dmax }); d = dmax; } queue.CompleteAdding(); Task.WaitAll(tasks); return(sum & 3); }
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)); if (u <= wheelSize) { return(new MertensFunctionDR(threads).Evaluate(n)); } imax = (int)(n / u); mobius = new MobiusRange(u + 1, threads); var batchSize = Math.Min(u, maximumBatchSize); m = new int[batchSize]; mx = new long[imax + 1]; r = new int[imax + 1]; lmax = 0; for (var i = 1; i <= imax; i += 2) { if (wheelInclude[(i % wheelSize) >> 1]) { r[lmax++] = i; } } Array.Resize(ref r, lmax); if (threads > 1) { var costs = new double[threads]; var bucketLists = new List <int> [threads]; for (var thread = 0; thread < threads; thread++) { bucketLists[thread] = new List <int>(); } for (var l = 0; l < lmax; l++) { var i = r[l]; var cost = Math.Sqrt(n / i); var addto = 0; var mincost = costs[0]; for (var thread = 0; thread < threads; thread++) { if (costs[thread] < mincost) { mincost = costs[thread]; addto = thread; } } bucketLists[addto].Add(i); costs[addto] += cost; } buckets = new int[threads][]; for (var thread = 0; thread < threads; thread++) { buckets[thread] = bucketLists[thread].ToArray(); } } 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); } ComputeMx(); return(mx[1]); }