public static BigNumber operator +(BigNumber c1, BigNumber c2) { BigNumber res = new BigNumber(); BigNumber.Add(c1, c2, res); return(res); }
static void M_log_basic_iteration(BigNumber nn, BigNumber rr, int places) { BigNumber tmp0, tmp1, tmp2, tmpX; if (places < 360) { BigNumber.M_log_solve_cubic(nn, rr, places); } else { tmp0 = new BigNumber(); tmp1 = new BigNumber(); tmp2 = new BigNumber(); tmpX = new BigNumber(); BigNumber.M_log_solve_cubic(nn, tmpX, 110); BigNumber.Neg(tmpX, tmp0); BigNumber.Exp(tmp0, tmp1, (places + 8)); BigNumber.Mul(tmp1, nn, tmp2); BigNumber.Sub(tmp2, BigNumber.One, tmp1); BigNumber.M_log_near_1(tmp1, tmp0, (places - 104)); BigNumber.Add(tmpX, tmp0, tmp1); BigNumber.Round(tmp1, rr, places); } }
static public void Round(BigNumber src, BigNumber dst, int places) { BigNumber t0_5 = new BigNumber(); BigNumber.Copy(Five, t0_5); int ii = places + 1; if (src.dataLength <= ii) { Copy(src, dst); return; } t0_5.exponent = src.exponent - ii; if (src.signum > 0) { BigNumber.Add(src, t0_5, dst); } else { BigNumber.Sub(src, t0_5, dst); } dst.dataLength = ii; BigNumber.Normalize(dst); }
public static BigNumber operator +(BigNumber c1, long c2) { BigNumber res = new BigNumber(); BigNumber C2 = c2; BigNumber.Add(c1, C2, res); return(res); }
static void M_log_solve_cubic(BigNumber nn, BigNumber rr, int places) { BigNumber tmp0, tmp1, tmp2, tmp3, guess; int ii, maxp, tolerance, local_precision; guess = new BigNumber(); tmp0 = new BigNumber(); tmp1 = new BigNumber(); tmp2 = new BigNumber(); tmp3 = new BigNumber(); BigNumber.M_get_log_guess(nn, guess); tolerance = -(places + 4); maxp = places + 16; local_precision = 18; ii = 0; while (true) { BigNumber.Exp(guess, tmp1, local_precision); BigNumber.Sub(tmp1, nn, tmp3); BigNumber.Add(tmp1, nn, tmp2); BigNumber.Div(tmp3, tmp2, tmp1, local_precision); BigNumber.Mul(BigNumber.Two, tmp1, tmp0); BigNumber.Sub(guess, tmp0, tmp3); if (ii != 0) { if (((3 * tmp0.exponent) < tolerance) || (tmp0.signum == 0)) { break; } } BigNumber.Round(tmp3, guess, local_precision); local_precision *= 3; if (local_precision > maxp) { local_precision = maxp; } ii = 1; } BigNumber.Round(tmp3, rr, places); }
/****************************************************************************/ /* * Calculate PI using the AGM (Arithmetic-Geometric Mean) * * Init : A0 = 1 * B0 = 1 / sqrt(2) * Sum = 1 * * Iterate: n = 1... * * * A = 0.5 * [ A + B ] * n n-1 n-1 * * * B = sqrt [ A * B ] * n n-1 n-1 * * * C = 0.5 * [ A - B ] * n n-1 n-1 * * * 2 n+1 * Sum = Sum - C * 2 * n * * * At the end when C is 'small enough' : * n * * 2 * PI = 4 * A / Sum * n+1 * * -OR- * * 2 * PI = ( A + B ) / Sum * n n * */ static private void CalculatePiAGM(BigNumber outv, int places) { int dplaces, nn; BigNumber tmp1 = new BigNumber(); BigNumber tmp2 = new BigNumber(); BigNumber a0 = new BigNumber(); BigNumber b0 = new BigNumber(); BigNumber c0 = new BigNumber(); BigNumber a1 = new BigNumber(); BigNumber b1 = new BigNumber(); BigNumber sum = new BigNumber(); BigNumber pow_2 = new BigNumber(); dplaces = places + 16; BigNumber.Copy(BigNumber.One, a0); BigNumber.Copy(BigNumber.One, sum); BigNumber.Copy(BigNumber.Four, pow_2); BigNumber.Sqrt(BigNumber.BN_OneHalf, b0, dplaces); while (true) { BigNumber.Add(a0, b0, tmp1); BigNumber.Mul(tmp1, BigNumber.BN_OneHalf, a1); BigNumber.Mul(a0, b0, tmp1); BigNumber.Sqrt(tmp1, b1, dplaces); BigNumber.Sub(a0, b0, tmp1); BigNumber.Mul(BigNumber.BN_OneHalf, tmp1, c0); BigNumber.Mul(c0, c0, tmp1); BigNumber.Mul(tmp1, pow_2, tmp2); BigNumber.Sub(sum, tmp2, tmp1); BigNumber.Round(tmp1, sum, dplaces); nn = -4 * c0.exponent; if (nn >= dplaces) { break; } BigNumber.Copy(a1, a0); BigNumber.Copy(b1, b0); BigNumber.Mul(pow_2, BigNumber.Two, tmp1); BigNumber.Copy(tmp1, pow_2); } BigNumber.Add(a1, b1, tmp1); BigNumber.Mul(tmp1, tmp1, tmp2); BigNumber.Div(tmp2, sum, tmp1, dplaces); BigNumber.Round(tmp1, outv, places); }
/****************************************************************************/ /* * calculate log (1 + x) with the following series: * * x * y = ----- ( |y| < 1 ) * x + 2 * * * [ 1 + y ] y^3 y^5 y^7 * log [-------] = 2 * [ y + --- + --- + --- ... ] * [ 1 - y ] 3 5 7 * */ static void M_log_near_1(BigNumber xx, BigNumber rr, int places) { BigNumber tmp0, tmp1, tmp2, tmpS, term; int tolerance, dplaces, local_precision; long m1; tmp0 = new BigNumber(); tmp1 = new BigNumber(); tmp2 = new BigNumber(); tmpS = new BigNumber(); term = new BigNumber(); tolerance = xx.exponent - (places + 6); dplaces = (places + 12) - xx.exponent; BigNumber.Add(xx, BigNumber.Two, tmp0); BigNumber.Div(xx, tmp0, tmpS, (dplaces + 6)); BigNumber.Copy(tmpS, term); BigNumber.Mul(tmpS, tmpS, tmp0); BigNumber.Round(tmp0, tmp2, (dplaces + 6)); m1 = 3L; while (true) { BigNumber.Mul(term, tmp2, tmp0); if ((tmp0.exponent < tolerance) || (tmp0.signum == 0)) { break; } local_precision = dplaces + tmp0.exponent; if (local_precision < 20) { local_precision = 20; } BigNumber.SetFromLong(tmp1, m1); BigNumber.Round(tmp0, term, local_precision); BigNumber.Div(term, tmp1, tmp0, local_precision); BigNumber.Add(tmpS, tmp0, tmp1); BigNumber.Copy(tmp1, tmpS); m1 += 2; } BigNumber.Mul(BigNumber.Two, tmpS, tmp0); BigNumber.Round(tmp0, rr, places); }
static private void M_raw_exp(BigNumber xx, BigNumber rr, int places) { BigNumber tmp0, digit, term; int tolerance, local_precision, prev_exp; long m1; tmp0 = new BigNumber(); term = new BigNumber(); digit = new BigNumber(); local_precision = places + 8; tolerance = -(places + 4); prev_exp = 0; BigNumber.Add(BigNumber.One, xx, rr); BigNumber.Copy(xx, term); m1 = 2L; while (true) { BigNumber.SetFromLong(digit, m1); BigNumber.Mul(term, xx, tmp0); BigNumber.Div(tmp0, digit, term, local_precision); BigNumber.Add(rr, term, tmp0); BigNumber.Copy(tmp0, rr); if ((term.exponent < tolerance) || (term.signum == 0)) { break; } if (m1 != 2L) { local_precision = local_precision + term.exponent - prev_exp; if (local_precision < 20) { local_precision = 20; } } prev_exp = term.exponent; m1++; } }
static void Floor(BigNumber dst, BigNumber src) { BigNumber.Copy(src, dst); if (BigNumber.IsInteger(dst) > 0) { return; } if (dst.exponent <= 0) /* if |bb| < 1, result is -1 or 0 */ { if (dst.signum < 0) { BigNumber.Neg(BigNumber.One, dst); } else { BigNumber.SetZero(dst); } return; } if (dst.signum < 0) { BigNumber mtmp = new BigNumber(); BigNumber.Neg(dst, mtmp); mtmp.dataLength = mtmp.exponent; BigNumber.Normalize(mtmp); BigNumber.Add(mtmp, BigNumber.One, dst); dst.signum = -1; } else { dst.dataLength = dst.exponent; BigNumber.Normalize(dst); } }
static void Ceil(BigNumber dst, BigNumber src) { BigNumber mtmp; BigNumber.Copy(src, dst); if (IsInteger(dst) > 0) /* if integer, we're done */ { return; } if (dst.exponent <= 0) /* if |bb| < 1, result is 0 or 1 */ { if (dst.signum < 0) { BigNumber.SetZero(dst); } else { BigNumber.Copy(BigNumber.One, dst); } return; } if (dst.signum < 0) { dst.dataLength = dst.exponent; BigNumber.Normalize(dst); } else { mtmp = new BigNumber(); BigNumber.Copy(dst, mtmp); mtmp.dataLength = mtmp.exponent; BigNumber.Normalize(mtmp); BigNumber.Add(mtmp, BigNumber.One, dst); } }
static int M_exp_compute_nn(ref int n, BigNumber b, BigNumber a) { BigNumber tmp0, tmp1; String cp = ""; int kk; n = 0; tmp0 = new BigNumber(); tmp1 = new BigNumber(); BigNumber.Mul(BN_exp_log2R, a, tmp1); if (tmp1.signum >= 0) { BigNumber.Add(tmp1, BigNumber.BN_OneHalf, tmp0); BigNumber.Floor(tmp1, tmp0); } else { BigNumber.Sub(tmp1, BigNumber.BN_OneHalf, tmp0); BigNumber.Ceil(tmp1, tmp0); } kk = tmp1.exponent; cp = BigNumber.ToIntString(tmp1); n = Convert.ToInt32(cp); BigNumber.SetFromLong(b, (long)(n)); kk = BigNumber.Compare(b, tmp1); return(kk); }
static private void Exp(BigNumber src, BigNumber dst, int places) { BigNumber A = 0, B = 0, C = 0; int dplaces, nn = 0, ii = 0; if (src.signum == 0) { BigNumber.Copy(BigNumber.One, dst); return; } if (src.exponent <= -3) { M_raw_exp(src, C, (places + 6)); BigNumber.Round(C, dst, places); return; } if (M_exp_compute_nn(ref nn, A, src) != 0) { throw new BigNumberException("'Exp', Input too large, Overflow"); } dplaces = places + 8; BigNumber.CheckLogPlaces(dplaces); BigNumber.Mul(A, BN_lc_log2, B); BigNumber.Sub(src, B, A); while (true) { if (A.signum != 0) { if (A.exponent == 0) { break; } } if (A.signum >= 0) { nn++; BigNumber.Sub(A, BN_lc_log2, B); BigNumber.Copy(B, A); } else { nn--; BigNumber.Add(A, BN_lc_log2, B); BigNumber.Copy(B, A); } } BigNumber.Mul(A, BN_exp_512R, C); M_raw_exp(C, B, dplaces); ii = 9; while (true) { BigNumber.Mul(B, B, C); BigNumber.Round(C, B, dplaces); if (--ii == 0) { break; } } BigNumber.IntPow(dplaces, BigNumber.Two, nn, A); BigNumber.Mul(A, B, C); BigNumber.Round(C, dst, places); }
static void Log(BigNumber src, BigNumber dst, int places) { BigNumber tmp0, tmp1, tmp2; int mexp, dplaces; if (src.signum <= 0) { throw new BigNumberException(" 'Log', Negative argument"); } tmp0 = new BigNumber(); tmp1 = new BigNumber(); tmp2 = new BigNumber(); dplaces = places + 8; mexp = src.exponent; if (mexp == 0 || mexp == 1) { BigNumber.Sub(src, BigNumber.One, tmp0); if (tmp0.signum == 0) /* is input exactly 1 ?? */ { /* if so, result is 0 */ BigNumber.SetZero(dst); return; } if (tmp0.exponent <= -4) { M_log_near_1(tmp0, dst, places); return; } } /* make sure our log(10) is accurate enough for this calculation */ /* (and log(2) which is called from M_log_basic_iteration) */ BigNumber.CheckLogPlaces(dplaces + 25); if (Math.Abs(mexp) <= 3) { M_log_basic_iteration(src, dst, places); } else { /* * use log (x * y) = log(x) + log(y) * * here we use y = exponent of our base 10 number. * * let 'C' = log(10) = 2.3025850929940.... * * then log(x * y) = log(x) + ( C * base_10_exponent ) */ BigNumber.Copy(src, tmp2); mexp = tmp2.exponent - 2; tmp2.exponent = 2; M_log_basic_iteration(tmp2, tmp0, dplaces); BigNumber.SetFromLong(tmp1, (long)mexp); BigNumber.Mul(tmp1, BN_lc_log10, tmp2); BigNumber.Add(tmp2, tmp0, tmp1); BigNumber.Round(tmp1, dst, places); } }
/****************************************************************************/ /* * define a notation for a function 'R' : * * * * 1 * R (a0, b0) = ------------------------------ * * ---- * \ * \ n-1 2 2 * 1 - | 2 * (a - b ) * / n n * / * ---- * n >= 0 * * * where a, b are the classic AGM iteration : * * * a = 0.5 * (a + b ) * n+1 n n * * * b = sqrt(a * b ) * n+1 n n * * * * define a variable 'c' for more efficient computation : * * 2 2 2 * c = 0.5 * (a - b ) , c = a - b * n+1 n n n n n * */ /****************************************************************************/ static void LogAGMRFunc(BigNumber aa, BigNumber bb, BigNumber rr, int places) { BigNumber tmp1, tmp2, tmp3, tmp4, tmpC2, sum, pow_2, tmpA0, tmpB0; int tolerance, dplaces; tmpA0 = new BigNumber(); tmpB0 = new BigNumber(); tmpC2 = new BigNumber(); tmp1 = new BigNumber(); tmp2 = new BigNumber(); tmp3 = new BigNumber(); tmp4 = new BigNumber(); sum = new BigNumber(); pow_2 = new BigNumber(); tolerance = places + 8; dplaces = places + 16; BigNumber.Copy(aa, tmpA0); BigNumber.Copy(bb, tmpB0); BigNumber.Copy(BigNumber.BN_OneHalf, pow_2); BigNumber.Mul(aa, aa, tmp1); /* 0.5 * [ a ^ 2 - b ^ 2 ] */ BigNumber.Mul(bb, bb, tmp2); BigNumber.Sub(tmp1, tmp2, tmp3); BigNumber.Mul(BigNumber.BN_OneHalf, tmp3, sum); while (true) { BigNumber.Sub(tmpA0, tmpB0, tmp1); /* C n+1 = 0.5 * [ An - Bn ] */ BigNumber.Mul(BigNumber.BN_OneHalf, tmp1, tmp4); /* C n+1 */ BigNumber.Mul(tmp4, tmp4, tmpC2); /* C n+1 ^ 2 */ /* do the AGM */ BigNumber.Add(tmpA0, tmpB0, tmp1); BigNumber.Mul(BigNumber.BN_OneHalf, tmp1, tmp3); BigNumber.Mul(tmpA0, tmpB0, tmp2); BigNumber.Sqrt(tmp2, tmpB0, dplaces); BigNumber.Round(tmp3, tmpA0, dplaces); /* end AGM */ BigNumber.Mul(BigNumber.Two, pow_2, tmp2); BigNumber.Copy(tmp2, pow_2); BigNumber.Mul(tmpC2, pow_2, tmp1); BigNumber.Add(sum, tmp1, tmp3); if ((tmp1.signum == 0) || ((-2 * tmp1.exponent) > tolerance)) { break; } BigNumber.Round(tmp3, sum, dplaces); } BigNumber.Sub(BigNumber.One, tmp3, tmp4); BigNumber.Reziprocal(tmp4, rr, places); }