예제 #1
0
        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);
        }
예제 #2
0
        public BigInteger T3Slow(BigInteger n)
        {
            var sum   = (BigInteger)0;
            var root3 = IntegerMath.FloorRoot(n, 3);

            if (threads == 0)
            {
                sum += T3Worker(n, root3, 0, 1);
            }
            else
            {
                var tasks = new Task[threads];
                for (var i = 0; i < threads; i++)
                {
                    var thread = i;
                    tasks[i] = new Task(() =>
                    {
                        var s = T3Worker(n, root3, thread, threads);
                        lock (this)
                            sum += s;
                    });
                    tasks[i].Start();
                }
                Task.WaitAll(tasks);
            }
            return(3 * sum + IntegerMath.Power(T1(root3), 3));
        }
        public BigInteger Evaluate(BigInteger n)
        {
            this.n = n;
            if (n == 1)
            {
                return(1);
            }
            sum    = 0;
            imax   = (long)IntegerMath.FloorRoot(n, 5) * C1 / C2;
            xmax   = imax != 0 ? Xi(imax) : (long)IntegerMath.FloorPower(n, 1, 2);
            mobius = new MobiusRangeAdditive(xmax + 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[maximumBatchSize];
            m      = new int[maximumBatchSize];
            m0     = 0;
            for (var x = (long)1; x <= xmax; x += maximumBatchSize)
            {
                m0 = EvaluateBatch(x, Math.Min(xmax, x + maximumBatchSize - 1));
            }

            EvaluateTail();
            return(sum);
        }
예제 #4
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));
        }
        private int Pi2Small(long x1, long x2)
        {
            var s = F2SmallParallel(x1, x2);

            for (var k = 2; k <= kmax; k++)
            {
                var mu = IntegerMath.Mobius(k);
                if (mu != 0)
                {
                    s += mu * F2Small((UInt128)IntegerMath.FloorRoot((BigInteger)n, k), x1, x2);
                }
            }
            return(s & 3);
        }
예제 #6
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);
        }
예제 #7
0
        public int PiWithPowers(int x)
        {
            var sum = Pi(x);

            for (int j = 2; true; j++)
            {
                var root = IntegerMath.FloorRoot(x, j);
                if (root == 1)
                {
                    break;
                }
                sum += Pi(root);
            }
            return(sum);
        }
        public BigInteger T3Slow(BigInteger n)
        {
            //Console.WriteLine("T3({0})", n);
            var sum   = (BigInteger)0;
            var root3 = IntegerMath.FloorRoot(n, 3);

            if (threads == 0)
            {
                for (var z = (BigInteger)1; z <= root3; z++)
                {
                    var nz     = n / z;
                    var sqrtnz = IntegerMath.FloorSquareRoot(nz);
                    var t      = hyperbolicSum[0].Evaluate(nz, (long)z + 1, (long)sqrtnz);
                    sum += 2 * t - sqrtnz * sqrtnz + nz / z;
                }
            }
            else
            {
                var tasks = new Task[threads];
                for (var i = 0; i < threads; i++)
                {
                    var thread = i;
                    tasks[i] = new Task(() =>
                    {
                        var s = (BigInteger)0;
                        for (var z = (BigInteger)1 + thread; z <= root3; z += threads)
                        {
                            var nz     = n / z;
                            var sqrtnz = IntegerMath.FloorSquareRoot(nz);
                            var t      = hyperbolicSum[thread].Evaluate(nz, (long)z + 1, (long)sqrtnz);
                            s         += 2 * t - sqrtnz * sqrtnz + nz / z;
                        }
                        lock (this)
                        {
                            sum += s;
                        }
                    });
                    tasks[i].Start();
                }
                Task.WaitAll(tasks);
            }
            sum = 3 * sum + root3 * root3 * root3;
            return(sum);
        }
예제 #9
0
        public BigInteger F3(BigInteger n)
        {
            //Console.WriteLine("F3({0})", n);
            var s    = (BigInteger)0;
            var dmax = IntegerMath.FloorRoot(n, 3);

            for (var d = 1; d <= dmax; d += 2)
            {
                var md = mobius[d];
                if (md == 0)
                {
                    continue;
                }
                var term = T3(n / IntegerMath.Power((BigInteger)d, 3));
                s += md * term;
            }
            Debug.Assert((s - 1) % 3 == 0);
            return((s - 1) / 3);
        }
예제 #10
0
        public int ParityOfPi(BigInteger x)
        {
            // pi(x) mod 2 = SumTwoToTheOmega(x)/2 mod 2- sum(pi(floor(x^(1/j)) mod 2)
            if (x < piSmall.Length)
            {
                return(piSmall[(int)x] % 2);
            }
            var parity = SumTwoToTheOmega(x) / 2 % 2;

            for (int j = 2; true; j++)
            {
                var root = IntegerMath.FloorRoot(x, j);
                if (root == 1)
                {
                    break;
                }
                parity ^= ParityOfPi(root);
            }
            return(parity);
        }
 private int Pi2Medium(long x1, long x2)
 {
     Debug.Assert(x1 > IntegerMath.FloorRoot(n, 4));
     return(F2Medium(n, x1, x2));
 }
        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]);
        }
예제 #13
0
        public Integer Evaluate(Integer n)
        {
            this.n = n;

            // Count lattice points under the hyperbola x*y = n.
            var sum = (Integer)0;

            // Compute the range of values over which we will apply the
            // geometric algorithm.
            xmax = IntegerMath.FloorRoot(n, 2);
            xmin = IntegerMath.Min(IntegerMath.FloorRoot(n, 3) * minimumMultiplier, xmax);

            // Calculate the line tangent to the hyperbola at the x = sqrt(n).
            var m2    = (Integer)1;
            var x2    = xmax;
            var y2    = n / x2;
            var r2    = y2 + m2 * x2;
            var width = x2 - xmin;

            Debug.Assert(r2 - m2 * x2 == y2);

            // Add the bottom rectangle.
            sum += (width + 1) * y2;

            // Add the isosceles right triangle corresponding to the initial
            // line L2 with -slope = 1.
            sum += width * (width + 1) / 2;

            // Process regions between tangent lines with integral slopes 1 & 2,
            // 2 & 3, etc. until we reach xmin.  This provides a first
            // approximation to the hyperbola and accounts for the majority
            // of the lattice points between xmin and max.  The remainder of
            // the points are computed by processing the regions bounded
            // by the two tangent lines and the hyperbola itself.
            while (true)
            {
                // Find the pair of points (x3, y3) and (x1, y1) where:
                // -H'(x3) >= the new slope
                // -H'(x1) <= the new slope
                // x1 = x3 + 1
                var m1 = m2 + 1;
                var x3 = IntegerMath.FloorSquareRoot(n / m1);
                var y3 = n / x3;
                var r3 = y3 + m1 * x3;
                var x1 = x3 + 1;
                var y1 = n / x1;
                var r1 = y1 + m1 * x1;
                Debug.Assert(r3 - m1 * x3 == y3);
                Debug.Assert(r1 - m1 * x1 == y1);

                // Handle left-overs.
                if (x3 < xmin)
                {
                    // Process the last few values above xmin as the number of
                    // points above the last L2.
                    for (var x = xmin; x < x2; x++)
                    {
                        sum += n / x - (r2 - m2 * x);
                    }
                    break;
                }

                // Invariants:
                // The value before x3 along L3 is on or below the hyperbola.
                // The value after x1 along L1 is on or below the hyperbola.
                // The new slope is one greater than the old slope.
                Debug.Assert((x3 - 1) * (r3 - m1 * (x3 - 1)) <= n);
                Debug.Assert((x1 + 1) * (r1 - m1 * (x1 + 1)) <= n);
                Debug.Assert(m1 - m2 == 1);

                // Add the triangular wedge above the previous slope and below the new one
                // and bounded on the left by xmin.
                var x0 = r3 - r2;
                width = x0 - xmin;
                sum  += width * (width + 1) / 2;

                // Account for a drop or rise from L3 to L1.
                if (r3 != r1 && x3 < x0)
                {
                    // Remove the old triangle and add the new triangle.
                    // The formula is (ow+dr)*(ow+dr+1)/2 - ow*(ow+1)/2.
                    var ow = x3 - x0;
                    var dr = r3 - r1;
                    sum += dr * (2 * ow + dr + 1) / 2;
                }

                // Determine intersection of L2 and L1.
                x0 = r1 - r2;
                var y0 = r2 - m2 * x0;
                Debug.Assert(r2 - m2 * x0 == r1 - m1 * x0);

                // Calculate width and height of parallelogram counting only lattice points.
                var w = (y2 - y0) + m1 * (x2 - x0);
                var h = (y1 - y0) + m2 * (x1 - x0);

                // Process the hyperbolic region bounded by L1 and L2.
                sum += ProcessRegion(w, h, m1, 1, m2, 1, x0, y0);

                // Advance to the next region.
                m2 = m1;
                x2 = x3;
                y2 = y3;
                r2 = r3;
            }

            // Process values one up to xmin.
            for (var x = (Integer)1; x < xmin; x++)
            {
                sum += n / x;
            }

            // Account for sqrt(n) < x <= n using the Dirichlet hyperbola method.
            sum = 2 * sum - xmax * xmax;

            return(sum);
        }
        public Integer Evaluate(Integer n, BigInteger xfirst, BigInteger xlast)
        {
            this.n = n;

            // Count lattice points under the hyperbola x*y = n.
            var sum = (Integer)0;

            // Compute the range of values over which we will apply the
            // geometric algorithm.
            xmax = (Integer)xlast;
            xmin = IntegerMath.Max(xfirst, IntegerMath.Min(IntegerMath.FloorRoot(n, 3) * minimumMultiplier, xmax));

            // Calculate the line tangent to the hyperbola at the x = sqrt(n).
            var m0 = (Integer)1;
            var x0 = xmax;
            var y0 = n / x0;
            var r0 = y0 + m0 * x0;

            Debug.Assert(r0 - m0 * x0 == y0);

            // Add the bottom rectangle.
            var width = x0 - xfirst;

            sum += (width + 1) * y0;

            // Add the isosceles right triangle corresponding to the initial
            // line L0 with -slope = 1.
            sum += width * (width + 1) / 2;

            // Process regions between tangent lines with integral slopes 1 & 2,
            // 2 & 3, etc. until we reach xmin.  This provides a first
            // approximation to the hyperbola and accounts for the majority
            // of the lattice points between xmin and max.  The remainder of
            // the points are computed by processing the regions bounded
            // by the two tangent lines and the hyperbola itself.
            while (true)
            {
                // Find the largest point (x1a, y1a) where -H'(X) >= the new slope.
                var m1  = m0 + 1;
                var x1a = IntegerMath.FloorSquareRoot(n / m1);
                var y1a = n / x1a;
                var r1a = y1a + m1 * x1a;
                var x1b = x1a + 1;
                var y1b = n / x1b;
                var r1b = y1b + m1 * x1b;
                Debug.Assert(r1a - m1 * x1a == y1a);
                Debug.Assert(r1b - m1 * x1b == y1b);

                // Handle left-overs.
                if (x1a < xmin)
                {
                    // Remove all the points we added between xfirst and x0.
                    var rest = x0 - xfirst;
                    sum -= (r0 - m0 * x0) * rest + m0 * rest * (rest + 1) / 2;
                    xmin = x0;
                    break;
                }

                // Invariants:
                // The value before x1a along L1a is on or below the hyperbola.
                // The value after x1b along L2b is on or below the hyperbola.
                // The new slope is one greater than the old slope.
                Debug.Assert((x1a - 1) * (r1a - m1 * (x1a - 1)) <= n);
                Debug.Assert((x1b + 1) * (r1b - m1 * (x1b + 1)) <= n);
                Debug.Assert(m1 - m0 == 1);

                // Add the triangular wedge above the previous slope and below the new one
                // and bounded on the left by xfirst.
                var x0a = r1a - r0;
                width = x0a - xfirst;
                sum  += width * (width + 1) / 2;

                // Account for a drop or rise from L1a to L1b.
                if (r1a != r1b && x1a < x0a)
                {
                    // Remove the old triangle and add the new triangle.
                    // The formula is (ow+dr)*(ow+dr+1)/2 - ow*(ow+1)/2.
                    var ow = x1a - x0a;
                    var dr = r1a - r1b;
                    sum += dr * (2 * ow + dr + 1) / 2;
                }

                // Determine intersection of L0 and L1b.
                var x0b = r1b - r0;
                var y0b = r0 - m0 * x0b;
                Debug.Assert(r0 - m0 * x0b == r1b - m1 * x0b);

                // Calculate width and height of parallelogram counting only lattice points.
                var w = (y0 - y0b) + m1 * (x0 - x0b);
                var h = (y1b - y0b) + m0 * (x1b - x0b);

                // Process the hyperbolic region bounded by L1b and L0.
                sum += ProcessRegion(w, h, m1, 1, m0, 1, x0b, y0b);

                // Advance to the next region.
                m0 = m1;
                x0 = x1a;
                y0 = y1a;
                r0 = r1a;
            }

            // Process values from xfirst up to xmin.
            sum += manualAlgorithm.Evaluate(n, xfirst, xmin - 1);

            return(sum);
        }