Beispiel #1
0
        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));
        }
Beispiel #2
0
        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);
        }
Beispiel #3
0
        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);
        }