public Int128 Evaluate(UInt128 n) { if (n == 0) return 0; this.n = n; u = (long)IntegerMath.Max(IntegerMath.FloorPower(n, 2, 3) * C1 / C2, IntegerMath.CeilingSquareRoot(n)); imax = (int)(n / (ulong)u); mobius = new MobiusRangeAdditive(u + 1, threads); var batchSize = Math.Min(u, maximumBatchSize); mu = new sbyte[maximumSmallBatchSize]; m = new int[batchSize]; mx = new Int128[imax + 1]; r = new int[imax + 1]; var lmax = 0; for (var i = 1; i <= imax; i += 2) { if (wheelInclude[(i % wheelSize) >> 1]) r[lmax++] = i; } Array.Resize(ref r, lmax); niLarge = new UInt128[imax + 1]; niSmall = new long[imax + 1]; var buckets = Math.Max(1, threads); var costs = new double[buckets]; var bucketListsLarge = Enumerable.Range(0, buckets).Select(i => new List<int>()).ToArray(); var bucketListsSmall = Enumerable.Range(0, buckets).Select(i => new List<int>()).ToArray(); for (var l = 0; l < lmax; l++) { var i = r[l]; var ni = n / (uint)i; var large = ni > largeLimit; var cost = Math.Sqrt((double)n / i) * (large ? C7 : 1); var addto = 0; var mincost = costs[0]; for (var bucket = 0; bucket < buckets; bucket++) { if (costs[bucket] < mincost) { mincost = costs[bucket]; addto = bucket; } } niLarge[i] = ni; if (large) bucketListsLarge[addto].Add(i); else { niSmall[i] = (long)ni; bucketListsSmall[addto].Add(i); } costs[addto] += cost; } bucketsLarge = bucketListsLarge.Select(bucket => bucket.ToArray()).ToArray(); bucketsSmall = bucketListsSmall.Select(bucket => bucket.ToArray()).ToArray(); var m0 = 0; var xmed = Math.Min((long)IntegerMath.FloorRoot(n, 2) * C5 / C6, u); for (var x = (long)1; x <= xmed; x += maximumSmallBatchSize) { var xstart = x; var xend = Math.Min(xstart + maximumSmallBatchSize - 1, xmed); m0 = mobius.GetValuesAndSums(xstart, xend + 1, mu, m, m0); ProcessBatch(xstart, xend); } for (var x = xmed + 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 Int128 Evaluate(UInt128 n) { if (n == 0) { return(0); } this.n = n; u = (long)IntegerMath.Max(IntegerMath.FloorPower(n, 2, 3) * C1 / C2, IntegerMath.CeilingSquareRoot(n)); imax = (int)(n / (ulong)u); mobius = new MobiusRangeAdditive(u + 1, threads); var batchSize = Math.Min(u, maximumBatchSize); mu = new sbyte[maximumSmallBatchSize]; m = new int[batchSize]; mx = new Int128[imax + 1]; r = new int[imax + 1]; var lmax = 0; for (var i = 1; i <= imax; i += 2) { if (wheelInclude[(i % wheelSize) >> 1]) { r[lmax++] = i; } } Array.Resize(ref r, lmax); niLarge = new UInt128[imax + 1]; niSmall = new long[imax + 1]; var buckets = Math.Max(1, threads); var costs = new double[buckets]; var bucketListsLarge = Enumerable.Range(0, buckets).Select(i => new List <int>()).ToArray(); var bucketListsSmall = Enumerable.Range(0, buckets).Select(i => new List <int>()).ToArray(); for (var l = 0; l < lmax; l++) { var i = r[l]; var ni = n / (uint)i; var large = ni > largeLimit; var cost = Math.Sqrt((double)n / i) * (large ? C7 : 1); var addto = 0; var mincost = costs[0]; for (var bucket = 0; bucket < buckets; bucket++) { if (costs[bucket] < mincost) { mincost = costs[bucket]; addto = bucket; } } niLarge[i] = ni; if (large) { bucketListsLarge[addto].Add(i); } else { niSmall[i] = (long)ni; bucketListsSmall[addto].Add(i); } costs[addto] += cost; } bucketsLarge = bucketListsLarge.Select(bucket => bucket.ToArray()).ToArray(); bucketsSmall = bucketListsSmall.Select(bucket => bucket.ToArray()).ToArray(); var m0 = 0; var xmed = Math.Min((long)IntegerMath.FloorRoot(n, 2) * C5 / C6, u); for (var x = (long)1; x <= xmed; x += maximumSmallBatchSize) { var xstart = x; var xend = Math.Min(xstart + maximumSmallBatchSize - 1, xmed); m0 = mobius.GetValuesAndSums(xstart, xend + 1, mu, m, m0); ProcessBatch(xstart, xend); } for (var x = xmed + 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]); }