public static bool SmallPrimeSppTest(BigInteger bi, ConfidenceFactor confidence) { int Rounds = GetSPPRounds(bi, confidence); // calculate values of s and t BigInteger p_sub1 = bi - 1; int s = p_sub1.LowestSetBit(); BigInteger t = p_sub1 >> s; var mr = new BigInteger.ModulusRing(bi); for (int round = 0; round < Rounds; round++) { BigInteger b = mr.Pow(BigInteger.smallPrimes[round], t); if (b == 1) continue; // a^t mod p = 1 bool result = false; for (int j = 0; j < s; j++) { if (b == p_sub1) { // a^((2^j)*t) mod p = p-1 for some 0 <= j <= s-1 result = true; break; } b = (b*b)%bi; } if (result == false) return false; } return true; }
/// <summary> /// Probabilistic prime test based on Rabin-Miller's test /// </summary> /// <param name="n" type="BigInteger.BigInteger"> /// <para> /// The number to test. /// </para> /// </param> /// <param name="confidence" type="int"> /// <para> /// The number of chosen bases. The test has at least a /// 1/4^confidence chance of falsely returning True. /// </para> /// </param> /// <returns> /// <para> /// True if "this" is a strong pseudoprime to randomly chosen bases. /// </para> /// <para> /// False if "this" is definitely NOT prime. /// </para> /// </returns> public static bool RabinMillerTest(BigInteger n, ConfidenceFactor confidence) { int bits = n.BitCount(); int t = GetSPPRounds(bits, confidence); // n - 1 == 2^s * r, r is odd BigInteger n_minus_1 = n - 1; int s = n_minus_1.LowestSetBit(); BigInteger r = n_minus_1 >> s; var mr = new BigInteger.ModulusRing(n); // Applying optimization from HAC section 4.50 (base == 2) // not a really random base but an interesting (and speedy) one BigInteger y = null; // FIXME - optimization disable for small primes due to bug #81857 if (n.BitCount() > 100) y = mr.Pow(2, r); // still here ? start at round 1 (round 0 was a == 2) for (int round = 0; round < t; round++) { if ((round > 0) || (y == null)) { BigInteger a = null; // check for 2 <= a <= n - 2 // ...but we already did a == 2 previously as an optimization do { a = BigInteger.GenerateRandom(bits); } while ((a <= 2) && (a >= n_minus_1)); y = mr.Pow(a, r); } if (y == 1) continue; for (int j = 0; ((j < s) && (y != n_minus_1)); j++) { y = mr.Pow(y, 2); if (y == 1) return false; } if (y != n_minus_1) return false; } return true; }