Beispiel #1
0
 public static mpz Ln2Z(mpz digits)
 {
     return(Transcendental.ArctanhOfInverseSeriesSumZ(
                digits,
                new[] { new mpz(26), new mpz(4801), new mpz(8749) },
                new[] { new mpz(18), new mpz(-2), new mpz(8) }));
 }
Beispiel #2
0
 internal static unsafe void Mpir_mpz_import(mpz rop, uint count, int order, uint size, int endian, uint nails, byte[] op)
 {
     fixed(void *srcPtr = op)
     {
         mpir.Mpir_internal_mpz_import(rop.Val, count, order, size, endian, nails, srcPtr);
     }
 }
Beispiel #3
0
        public static mpz ArctanhOfInverseSeriesSumZ(mpz digits, IList <mpz> args, IList <mpz> factors = null, mpz commonFactor = null)
        {
            var pq  = ArctanhOfInverseSeriesSum(digits + _ARCTAN_OF_INVERSE_SERIES_SUM_DIGITS_SURCHARGE, args, factors, commonFactor);
            var one = mpz.Ten.Power(digits);

            return(pq.P * one / pq.Q);
        }
        // ReSharper restore InconsistentNaming

        /*
         * http://numbers.computation.free.fr/Constants/Algorithms/splitting.html
         */
        public static T BinarySplitting <T>(mpz a, mpz b, Func <mpz, mpz, T> directlyCompute, Func <T, T, T> recursivelyCombine, int rangeThreshold = _BINARY_SPLITTING_RECURSION_THRESHOLD)
        {
            if (a == null)
            {
                throw new ArgumentNullException("a");
            }
            if (b == null)
            {
                throw new ArgumentNullException("b");
            }
            if (a < 0)
            {
                throw new ArgumentOutOfRangeException("a");
            }
            if (b <= a)
            {
                throw new ArgumentOutOfRangeException("b");
            }
            if (directlyCompute == null)
            {
                throw new ArgumentNullException("directlyCompute");
            }
            if (recursivelyCombine == null)
            {
                throw new ArgumentNullException("recursivelyCombine");
            }
            if (rangeThreshold < 1)
            {
                throw new ArgumentOutOfRangeException("rangeThreshold");
            }

            return(BinarySplittingImpl(a, b, directlyCompute, recursivelyCombine, rangeThreshold));
        }
Beispiel #5
0
        public virtual mpc Power(mpz exponent, RoundingMode?roundingMode = null)
        {
            var c = new mpc(precisionRe: PrecisionRe, precisionIm: PrecisionIm);

            mpir.mpc_pow_z(c, this, exponent, (int)roundingMode.GetValueOrDefault(DefaultRoundingMode));
            return(c);
        }
Beispiel #6
0
 internal static unsafe void Mpir_mpz_import_by_offset(mpz rop, int startOffset, int endOffset, int order, uint size, int endian, uint nails, byte[] op)
 {
     fixed(byte *srcPtr = op)
     {
         mpir.Mpir_internal_mpz_import(rop.Val, (uint)(endOffset - startOffset + 1), order, size, endian, nails, srcPtr + startOffset);
     }
 }
Beispiel #7
0
        public static mpz InverseSqrtZ(ulong n, mpz digits)
        {
            mpz e;
            var r_dash = InverseSqrtImpl(n, digits, out e);

            // (r' / 2^e) * 10^digits
            return((r_dash * new mpz(5).Power(digits)).ShiftRight(e - digits));
        }
Beispiel #8
0
    static void MpirCalcs()
    {
        mpz a = new mpz(12345678901234567890);
        mpz b = new mpz(9876543210987654321);
        mpz c = a * b;

        System.Console.WriteLine("{0}", c);
    }
Beispiel #9
0
 static void Bar()
 {
     // [using-sample]
     using (mpz a = new mpz(12345678901234567890))
         using (mpz b = new mpz(9876543210987654321))
             using (mpz c = a * b)
             {
                 System.Console.WriteLine("{0}", c.ToString());
             }
     // [/using-sample]
 }
Beispiel #10
0
        public static mpz BinarySearch(mpz a, mpz b, mpz reference, Func <mpz, mpz> f, bool isInDescendingOrder = false, int rangeThreshold = _BINARY_SEARCH_RECURSION_THRESHOLD, bool returnMinimumOfRange = false)
        {
            if (a == null)
            {
                throw new ArgumentNullException("a");
            }
            if (b == null)
            {
                throw new ArgumentNullException("b");
            }
            if (reference == null)
            {
                throw new ArgumentNullException("reference");
            }
            if (b < a)
            {
                throw new ArgumentOutOfRangeException("b");
            }
            if (f == null)
            {
                throw new ArgumentNullException("f");
            }
            if (rangeThreshold < 0)
            {
                throw new ArgumentOutOfRangeException("rangeThreshold");
            }

            while ((b - a) > rangeThreshold)
            {
                // m is the midpoint of a and b
                var m = (a + b) >> 1;

                var compare = isInDescendingOrder
                                        ? -f(m).CompareTo(reference)
                                        : f(m).CompareTo(reference);

                switch (compare)
                {
                case -1:
                    a = m + 1;
                    break;

                case 0:
                    return(m);

                case 1:
                    b = m - 1;
                    break;
                }
            }

            return((returnMinimumOfRange ^ isInDescendingOrder) ? a : b);
        }
Beispiel #11
0
        private static Series.PQ ArctanOfInverse(mpz digits, mpz x, bool isHyperbolic)
        {
            if (digits == null)
            {
                throw new ArgumentNullException("digits");
            }
            if (digits <= 0)
            {
                throw new ArgumentOutOfRangeException("digits");
            }
            if (x == null)
            {
                throw new ArgumentNullException("x");
            }
            if (x <= 1)
            {
                throw new ArgumentOutOfRangeException("x");
            }

            // http://numbers.computation.free.fr/Constants/Algorithms/splitting.html
            Func <mpz, mpz, Series.PQT> directlyCompute = (a, b) =>
            {
                var t = 2 * a + 3;
                var q = t * x.Square();
                var p = (!isHyperbolic && a.IsEven()) ? mpz.NegativeOne : mpz.One;
                return(new Series.PQT {
                    P = p, Q = q, T = t
                });
            };
            Func <Series.PQT, Series.PQT, Series.PQT> recursivelyCombine = (am, mb) => new Series.PQT {
                P = mb.Q * am.P + am.T * mb.P, Q = am.Q * mb.Q, T = am.T * mb.T
            };

            // How many terms to compute

            /*
             *         x^(2k+1) > 10^digits
             * => (2k+1) log(x) > digits * log(10)
             * =>        2k + 1 > digits * log(10) / log(x)
             * =>            2k > digits * log(10) / log(x)
             * =>             k > [digits * log(10) / log(x)] / 2
             */
            var n = (digits.ToMpf() * Math.Log(10, (double)x) / 2).ToMpz() + _ARCTAN_OF_INVERSE_NUMBER_OF_TERMS_SURCHARGE;

            // Calclate P(0,N), Q(0,N) and T(0,N)
            var pqt = Series.BinarySplitting(0, n, directlyCompute, recursivelyCombine);

            return(new Series.PQ {
                P = pqt.P + pqt.Q, Q = x * pqt.Q
            });
        }
Beispiel #12
0
        public static mpz InverseSqrtImpl(ulong x, mpz digits, out mpz e)
        {
            if (digits == null)
            {
                throw new ArgumentNullException("digits");
            }
            if (digits <= 0)
            {
                throw new ArgumentOutOfRangeException("digits");
            }

            var r_i_dash = new mpz((1UL << _SQRT_INITIAL_GUESS_BITS) / Math.Sqrt(x));
            var e_i      = new mpz(_SQRT_INITIAL_GUESS_BITS);

            var targetPrecision = digits << 2;             // bits per digit = log(10)/log(2) ~ 3.3

            while (e_i <= targetPrecision)
            {
                var e_previ = e_i;
                e_i = e_i << 1;
                var one_i = mpz.One.ShiftLeft(e_i);

                /*
                 * http://www.numberworld.org/y-cruncher/algorithms/invsqrt.html
                 * http://cs.stackexchange.com/a/37645
                 *
                 * w_i+1 = r_i^2
                 *       = r_i'^2 / 2^(2*e_i)
                 *  => w_i+1' = r_i'^2
                 *
                 * d_i+1 = 1 - w_i+1 * x
                 *       = 1 - r_i'^2 / 2^(2*e_i) * x
                 *       = (2^(2*e_i) - r_i'^2 * x) / 2^(2*e_i)
                 *  => d_i+1' = 2^(2*e_i) - w_i+1' * x
                 *
                 * r_i+1 = r_i * (1 + d_i+1 / 2)
                 *       = r_i' / 2^e_i * (1 + (d_i+1' / 2) / 2^(2*e_i))
                 *       = r_i' / 2^e_i * (2^(2*e_i) + d_i+1' / 2) / 2^(2*e_i)
                 *       = r_i' * (2^(2*e_i) + d_i+1' / 2) / 2^e_i / 2^(2*e_i)
                 *  => r_i+1' = r_i' * (2^(2*e_i) + d_i+1' / 2) / 2^e_i
                 */
                var w_i_dash = r_i_dash * r_i_dash;
                var d_i_dash = one_i - w_i_dash * x;
                r_i_dash = (r_i_dash * (one_i + (d_i_dash >> 1))).ShiftRight(e_previ);
            }

            e = e_i;
            return(r_i_dash);
        }
Beispiel #13
0
        public override bool TryInvertMod(mpz mod, out mpz result)
        {
            using (var z = new mpz())
            {
                var ans = mpir.mpz_invert(z, this, mod);
                if (ans == 0)
                {
                    result = null;
                    return(false);
                }

                mpir.mpz_set(this, z);
                result = this;
                return(true);
            }
        }
        private static T BinarySplittingImpl <T>(mpz a, mpz b, Func <mpz, mpz, T> directlyCompute, Func <T, T, T> recursivelyCombine, int rangeThreshold)
        {
            // Directly compute e.g. P(a, a + rangeThreshold) and Q(a, a + rangeThreshold)
            if ((b - a) <= rangeThreshold)
            {
                return(directlyCompute(a, b));
            }

            // Recursively compute e.g. P(a, b) and Q(a, b)

            // m is the midpoint of a and b
            var m = (a + b) >> 1;

            // Recursively calculate e.g. P(a, m) and Q(a, m)
            var am = BinarySplittingImpl(a, m, directlyCompute, recursivelyCombine, rangeThreshold);
            // Recursively calculate e.g. P(m, b) and Q(m, b)
            var mb = BinarySplittingImpl(m, b, directlyCompute, recursivelyCombine, rangeThreshold);

            // Now combine
            return(recursivelyCombine(am, mb));
        }
Beispiel #15
0
        public static mpz InverseImpl(ulong x, mpz digits, out mpz e)
        {
            if (digits == null)
            {
                throw new ArgumentNullException("digits");
            }
            if (digits <= 0)
            {
                throw new ArgumentOutOfRangeException("digits");
            }

            var r_i_dash = new mpz((1UL << _INVERSE_INITIAL_GUESS_BITS) / ((double)x));
            var e_i      = new mpz(_INVERSE_INITIAL_GUESS_BITS);

            var targetPrecision = digits << 2;             // bits per digit = log(10)/log(2) ~ 3.3

            while (e_i <= targetPrecision)
            {
                var e_previ = e_i;
                e_i = e_i << 1;
                var one_i = mpz.One.ShiftLeft(e_i);

                /*
                 * http://www.numberworld.org/y-cruncher/algorithms/division.html
                 *
                 * d_i+1 = r_i * x - 1
                 *       = (r_i' * x - 2^e_i) / 2^e_i
                 *       = (r_i' * x * 2^e_i - 2^(2*e_i)) / 2^(2*e_i)
                 *
                 * r_i+1 = r_i * (1 - d_i+1)
                 *       = r_i' / 2^e_i * (1 - d_i+1' / 2^(2*e_i))
                 *       = r_i' * (2^(2*e_i) - d_i+1') / 2^e_i / 2^(2*e_i)
                 */
                var d_i_dash = (r_i_dash * x).ShiftLeft(e_previ) - one_i;
                r_i_dash = (r_i_dash * (one_i - d_i_dash)).ShiftRight(e_previ);
            }

            e = e_i;
            return(r_i_dash);
        }
Beispiel #16
0
        /*
         * Compute int(e * 10^digits)
         *
         * This is done using Taylor series of exp(1) with binary splitting
         */
        public static mpz eZ(mpz digits)
        {
            if (digits == null)
            {
                throw new ArgumentNullException("digits");
            }
            if (digits <= 0)
            {
                throw new ArgumentOutOfRangeException("digits");
            }

            Func <mpz, mpz, Series.PQ> directlyCompute = (a, b) => new Series.PQ {
                P = mpz.One, Q = b
            };
            Func <Series.PQ, Series.PQ, Series.PQ> recursivelyCombine = (am, mb) => new Series.PQ {
                P = am.P * mb.Q + mb.P, Q = am.Q * mb.Q
            };

            // How many terms to compute

            /*
             * http://www.johndcook.com/blog/2011/06/10/stirling-approximation/
             *
             *             k! > 10^digits
             * =>      log k! > digits
             * => k log k - k > digits
             *
             * with log n! = sum_k=1^n log k
             *            >= int_x=1^n log x dx
             *             = n log n - n + 1
             *             > n log n - n
             */
            var n = Series.BinarySearch(0, digits, digits + 1, x => (x * ((int)x.Length(10) - _MPZ_DIGITS_IN_BASE_10_UNDERESTIMATION) - x), false, 1);

            // Calculate P(0, N) and Q(0, N)
            var pq  = Series.BinarySplitting(0, n, directlyCompute, recursivelyCombine);
            var one = mpz.Ten.Power(digits);

            return(one + (one * pq.P) / pq.Q);
        }
Beispiel #17
0
 public static mpq PiQ(mpz digits)
 {
     return(new mpq(PiZ(digits), mpz.Ten.Power(digits)));
 }
Beispiel #18
0
        /*
         * Compute int(pi * 10^digits)
         *
         * This is done using Chudnovsky's series with binary splitting
         */
        public static mpz PiZ(mpz digits)
        {
            if (digits == null)
            {
                throw new ArgumentNullException("digits");
            }
            if (digits <= 0)
            {
                throw new ArgumentOutOfRangeException("digits");
            }

            const long C          = 640320;
            const long C3_OVER_24 = C * C * C / 24;

            /*
             * Source: http://www.craig-wood.com/nick/articles/pi-chudnovsky/
             *
             * Computes the terms for binary splitting the Chudnovsky infinite series
             *
             * a(a) = +/- (13591409 + 545140134*a)
             * p(a) = (6*a-5)*(2*a-1)*(6*a-1)
             * b(a) = 1
             * q(a) = a*a*a*C3_OVER_24
             */
            Func <mpz, mpz, Series.PQT> directlyCompute = (a, b) =>
            {
                mpz Pab, Qab;
                if (a == 0)
                {
                    Pab = Qab = mpz.One;
                }
                else
                {
                    var a2 = a << 1;
                    var a6 = a2 * 3;
                    Pab = (a6 - 5) * (a2 - 1) * (a6 - 1);
                    Qab = a.Power(3U) * C3_OVER_24;
                }

                // t(a) = p(a) * a(a)
                var Tab = Pab * (13591409 + 545140134 * a);
                if (a.IsOdd())
                {
                    Tab = -Tab;
                }

                return(new Series.PQT {
                    P = Pab, Q = Qab, T = Tab
                });
            };
            Func <Series.PQT, Series.PQT, Series.PQT> recursivelyCombine = (am, mb) => new Series.PQT
            {
                P = am.P * mb.P,
                Q = am.Q * mb.Q,
                T = mb.Q * am.T + am.P * mb.T
            };

            // How many terms to compute
            var digitsPerTerm = Math.Log10(C3_OVER_24 / 6 / 2 / 6);
            var n             = (digits.ToMpf() / digitsPerTerm).ToMpz() + _PI_NUMBER_OF_TERMS_SURCHARGE;

            // Calculate P(0, N), Q(0, N) and T(0, N)
            var pqt        = Series.BinarySplitting(0, n, directlyCompute, recursivelyCombine);
            var oneSquared = mpz.Ten.Power(digits << 1);
            var sqrtC      = (10005 * oneSquared).Sqrt();

            return((pqt.Q * 426880 * sqrtC) / pqt.T);
        }
Beispiel #19
0
 public override mpz Multiply(mpz x)
 {
     mpir.mpz_mul(this, this, x);
     return(this);
 }
Beispiel #20
0
 public override mpz SubtractFrom(mpz x)
 {
     mpir.mpz_sub(this, x, this);
     return(this);
 }
Beispiel #21
0
 public override mpz Xor(mpz x)
 {
     mpir.mpz_xor(this, this, x);
     return(this);
 }
Beispiel #22
0
 public override mpz And(mpz x)
 {
     mpir.mpz_and(this, this, x);
     return(this);
 }
Beispiel #23
0
        public override bool InverseModExists(mpz mod)
        {
            mpz result;

            return(AsImmutable().TryInvertMod(mod, out result));
        }
Beispiel #24
0
 public override mpz Lcm(mpz x)
 {
     mpir.mpz_lcm(this, this, x);
     return(this);
 }
Beispiel #25
0
 public override mpfr Power(mpz exponent, RoundingMode?roundingMode = null)
 {
     mpir.mpfr_pow_z(this, this, exponent, (int)roundingMode.GetValueOrDefault(DefaultRoundingMode));
     return(this);
 }
Beispiel #26
0
 public static mpf PiF(mpz digits)
 {
     return(PiQ(digits).ToMpf());
 }
Beispiel #27
0
 public override mpfr SubtractFrom(mpz x, RoundingMode?roundingMode = null)
 {
     mpir.mpfr_z_sub(this, x, this, (int)roundingMode.GetValueOrDefault(DefaultRoundingMode));
     return(this);
 }
Beispiel #28
0
 public override mpz RemoveFactor(mpz factor, out ulong count)
 {
     count = mpir.mpz_remove(this, this, factor);
     return(this);
 }
Beispiel #29
0
 public override mpfr Add(mpz x, RoundingMode?roundingMode = null)
 {
     mpir.mpfr_add_z(this, this, x, (int)roundingMode.GetValueOrDefault(DefaultRoundingMode));
     return(this);
 }
Beispiel #30
0
 public override mpz Gcd(mpz x)
 {
     mpir.mpz_gcd(this, this, x);
     return(this);
 }