public static bool SmallPrimeSppTest( BigInteger bi, ConfidenceFactor confidence ) { int Rounds = GetSPPRounds(bi, confidence); // calculate values of s and thread BigInteger p_sub1 = bi - 1; int s = p_sub1.LowestSetBit(); BigInteger t = p_sub1 >> s; BigInteger.ModulusRing 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^thread mod p = 1 bool result = false; for ( int j = 0; j < s; j++ ) { if ( b == p_sub1 ) { // a^((2^k)*thread) mod p = p-1 for some 0 <= k <= 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="bi" 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 bi, ConfidenceFactor confidence ) { int Rounds = GetSPPRounds(bi, confidence); // calculate values of s and thread BigInteger p_sub1 = bi - 1; int s = p_sub1.LowestSetBit(); BigInteger t = p_sub1 >> s; int bits = bi.BitCount(); BigInteger a = null; BigInteger.ModulusRing mr = new BigInteger.ModulusRing(bi); // Applying optimization from HAC section 4.50 (base == 2) // not a really random base but an interesting (and speedy) one BigInteger b = mr.Pow(2, t); if ( b != 1 ) { bool result = false; for ( int j = 0; j < s; j++ ) { if ( b == p_sub1 ) { // a^((2^k)*thread) mod p = p-1 for some 0 <= k <= s-1 result = true; break; } b = ( b * b ) % bi; } if ( !result ) return false; } // still here ? start at round 1 (round 0 was a == 2) for ( int round = 1; round < Rounds; round++ ) { while ( true ) { // generate a < n a = BigInteger.GenerateRandom(bits); // make sure "a" is not 0 (and not 2 as we have already tested that) if ( a > 2 && a < bi ) break; } if ( a.GCD(bi) != 1 ) return false; b = mr.Pow(a, t); if ( b == 1 ) continue; // a^thread mod p = 1 bool result = false; for ( int j = 0; j < s; j++ ) { if ( b == p_sub1 ) { // a^((2^k)*thread) mod p = p-1 for some 0 <= k <= s-1 result = true; break; } b = ( b * b ) % bi; } if ( !result ) return false; } return true; }