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) })); }
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); } }
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)); }
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); }
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); } }
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)); }
static void MpirCalcs() { mpz a = new mpz(12345678901234567890); mpz b = new mpz(9876543210987654321); mpz c = a * b; System.Console.WriteLine("{0}", c); }
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] }
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); }
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 }); }
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); }
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)); }
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); }
/* * 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); }
public static mpq PiQ(mpz digits) { return(new mpq(PiZ(digits), mpz.Ten.Power(digits))); }
/* * 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); }
public override mpz Multiply(mpz x) { mpir.mpz_mul(this, this, x); return(this); }
public override mpz SubtractFrom(mpz x) { mpir.mpz_sub(this, x, this); return(this); }
public override mpz Xor(mpz x) { mpir.mpz_xor(this, this, x); return(this); }
public override mpz And(mpz x) { mpir.mpz_and(this, this, x); return(this); }
public override bool InverseModExists(mpz mod) { mpz result; return(AsImmutable().TryInvertMod(mod, out result)); }
public override mpz Lcm(mpz x) { mpir.mpz_lcm(this, this, x); return(this); }
public override mpfr Power(mpz exponent, RoundingMode?roundingMode = null) { mpir.mpfr_pow_z(this, this, exponent, (int)roundingMode.GetValueOrDefault(DefaultRoundingMode)); return(this); }
public static mpf PiF(mpz digits) { return(PiQ(digits).ToMpf()); }
public override mpfr SubtractFrom(mpz x, RoundingMode?roundingMode = null) { mpir.mpfr_z_sub(this, x, this, (int)roundingMode.GetValueOrDefault(DefaultRoundingMode)); return(this); }
public override mpz RemoveFactor(mpz factor, out ulong count) { count = mpir.mpz_remove(this, this, factor); return(this); }
public override mpfr Add(mpz x, RoundingMode?roundingMode = null) { mpir.mpfr_add_z(this, this, x, (int)roundingMode.GetValueOrDefault(DefaultRoundingMode)); return(this); }
public override mpz Gcd(mpz x) { mpir.mpz_gcd(this, this, x); return(this); }