public BigInteger Evaluate(BigInteger n) { t3Map.Clear(); var jmax = IntegerMath.FloorLog(n, 2); var dmax = IntegerMath.FloorRoot(n, 3); mobius = new MobiusCollection((int)(IntegerMath.Max(jmax, dmax) + 1), 0); return(Pi3(n)); }
public BigInteger Pi3(BigInteger n) { var kmax = IntegerMath.FloorLog(n, 2); var sum = (BigInteger)0; for (var k = 1; k <= kmax; k++) { if (k % 3 != 0 && mobius[k] != 0) { sum += k * mobius[k] * F3(IntegerMath.FloorRoot(n, k)); } } return((sum + 1) % 3); }
public static T PerfectPower <T>(T a) { // See: Sieve Algorithms for Perfect Power Testing, // E. Bach and J. Sorenson, Algorithmica 9 (1993) 313-328. // Algorithm B (modified). var absA = Number <T> .Abs(a); var bits = IntegerMath.FloorLog((T)absA, 2); var logA = Number <T> .Log(absA).Real; var smallPrimes = GetSmallPrimes(); foreach (var p in smallPrimes) { if (absA != a && p == 2) { continue; } var b = (Number <T>)p; if (b > bits) { break; } if (!IsPossiblePerfectPower(a, p)) { continue; } Number <T> power; var c = FloorRootCore <T>(absA, logA, b, out power); if (power == absA) { return(b * PerfectPower <T>(absA == a ? c : -c)); } } return(Number <T> .One); }
public int Evaluate(UInt128 n) { this.n = n; var sum = 0; sqrtn = (long)IntegerMath.FloorSquareRoot(n); kmax = (int)IntegerMath.FloorLog(n, 2); imax = (long)IntegerMath.FloorPower(n, 1, 5) * C1 / C2; xmax = DownToOdd(imax != 0 ? Xi(imax) : sqrtn); xmed = DownToOdd(Math.Min((long)(IntegerMath.FloorPower(n, 2, 7) * C3 / C4), xmax)); var dmax = (long)IntegerMath.Min(n / IntegerMath.Square((UInt128)xmed) + 1, n); mobius = new MobiusOddRangeAdditive((xmax + 2) | 1, threads); divisors = new DivisorOddRangeAdditive((dmax + 2) | 1, threads); xi = new long[imax + 1]; mx = new long[imax + 1]; // Initialize xi. for (var i = 1; i <= imax; i++) { xi[i] = Xi(i); } values = new sbyte[mobiusBatchSize >> 1]; m = new int[mobiusBatchSize >> 1]; m0 = 0; dsums = new ulong[divisorBatchSize >> 1]; d1 = d2 = 1; // Process small x values. for (var x = (long)1; x <= xmed; x += mobiusBatchSize) { var xfirst = x; var xlast = Math.Min(xmed, xfirst + mobiusBatchSize - 2); m0 = mobius.GetValuesAndSums(xfirst, xlast + 2, values, m, m0); sum += Pi2Small(xfirst, xlast); UpdateMx(xfirst, xlast); } // Process medium x values. #if true for (var x = xmed + 2; x <= xmax; x += mobiusBatchSize) { var xfirst = x; var xlast = Math.Min(xmax, xfirst + mobiusBatchSize - 2); m0 = mobius.GetValuesAndSums(xfirst, xlast + 2, values, m, m0); sum += Pi2Medium(xfirst, xlast); UpdateMx(xfirst, xlast); } #else for (var x = xmax; x > xmed; x -= mobiusBatchSize) { var xlast = x; var xfirst = Math.Max(xmed + 2, xlast - mobiusBatchSize + 2); m0 = mobius.GetValuesAndSums(xfirst, xlast + 2, values, m, m0); sum += Pi2Medium(xfirst, xlast); UpdateMx(xfirst, xlast); } #endif // Process large x values. sum += Pi2Large(); // Adjust for final parity of F2. sum -= IntegerMath.Mertens(kmax); // Compute final result. sum &= 3; Debug.Assert((sum & 1) == 0); sum >>= 1; return((sum + (n >= 2 ? 1 : 0)) % 2); }