/// <summary> /// Determines whether <paramref name="n"/> is probably a prime number. Uses the /// [Miller–Rabin primality test](https://en.wikipedia.org/wiki/Miller%E2%80%93Rabin_primality_test). /// </summary> /// <remarks>This is a probabilistic test. The probability to return <b>true</b> for a composite number /// is 4^(−<paramref name="k"/>). </remarks> /// <param name="n">Number to test (must be odd).</param> /// <param name="k">The number of random tests to do.</param> /// <param name="rand">The random number generator to use.</param> /// <returns> /// <b>true</b> if the number <paramref name="n"/> is probable a prime number; <b>false</b>, if the number is composite. /// </returns> public static bool IsProbablyPrime_MillerRabinTest(BigInteger n, BigInteger k, RandomXorShift rand) { var n1 = n - 1; var d = FactorPow2(n1, out long r); for (int i = 0; i < k; i++) { var a = rand.NextValue(n - 3) + 2; var x = IntegerMath.PowMod(a, d, n); if (x == 1 || x == n1) { continue; } bool continueI = false; for (int j = 0; j < r - 1; j++) { x = IntegerMath.PowMod(x, 2, n); if (x == 1) { return(false); } if (x == n1) { continueI = true; break; } } if (continueI) { continue; } return(false); } return(true); }
/// <summary> /// Guesses a prime factor of the number <paramref name="num"/>. /// </summary> /// <param name="num">The number.</param> /// <returns>A possible prime factor.</returns> public static BigInteger GuessPrimeFactor(BigInteger num) { var d = FactorPow2(num - 1, out long r); var pm = IntegerMath.PowMod(2, d, num); var gcd = IntegerMath.Gcd(pm - 1, num); return(gcd); }
/// <summary> /// Deterministic Miller Rabin test for primality. /// </summary> /// <param name="n">Number to test (must be odd).</param> /// <param name="b">Base to test.</param> /// <returns> /// <b>true</b> if the number <paramref name="n"/> is probable a prime number; <b>false</b>, if the number is composite. /// </returns> public static bool SPRP(BigInteger n, BigInteger b) { var nMinus1 = n - 1; var t = FactorPow2(nMinus1, out long r); var test = IntegerMath.PowMod(b, t, n); if (test == 1 || test == nMinus1) { return(true); } while (--r > 0) { test = IntegerMath.MulMod(test, test, n); if (test == nMinus1) { return(true); } } return(false); }