/** * The Miller-Rabin primality test. * * @param n the input number to be tested. * @param t the number of trials. * @return {@code false} if the number is definitely compose, otherwise * {@code true} with probability {@code 1 - 4<sup>(-t)</sup>}. * @ar.org.fitc.ref "D. Knuth, The Art of Computer Programming Vo.2, Section * 4.5.4., Algorithm P" */ private static bool MillerRabin(BigInteger n, int t, CancellationToken argCancelToken) { argCancelToken.ThrowIfCancellationRequested(); // PRE: n >= 0, t >= 0 BigInteger x; // x := UNIFORM{2...n-1} BigInteger y; // y := x^(q * 2^j) mod n BigInteger n_minus_1 = n - BigInteger.One; // n-1 int bitLength = n_minus_1.BitLength; // ~ log2(n-1) // (q,k) such that: n-1 = q * 2^k and q is odd int k = n_minus_1.LowestSetBit; BigInteger q = n_minus_1 >> k; Random rnd = new Random(); for (int i = 0; i < t; i++) { argCancelToken.ThrowIfCancellationRequested(); // To generate a witness 'x', first it use the primes of table if (i < primes.Length) { x = BIprimes[i]; } else {/* * It generates random witness only if it's necesssary. Note * that all methods would call Miller-Rabin with t <= 50 so * this part is only to do more robust the algorithm */ do { argCancelToken.ThrowIfCancellationRequested(); x = new BigInteger(bitLength, rnd); } while ((x.CompareTo(n) >= BigInteger.EQUALS) || (x.Sign == 0) || x.IsOne); } y = BigMath.ModPow(x, q, n); if (y.IsOne || y.Equals(n_minus_1)) { continue; } for (int j = 1; j < k; j++) { argCancelToken.ThrowIfCancellationRequested(); if (y.Equals(n_minus_1)) { continue; } y = (y * y) % n; if (y.IsOne) { return(false); } } if (!y.Equals(n_minus_1)) { return(false); } } return(true); }