예제 #1
0
        /// <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);
        }
예제 #2
0
        /// <summary>
        /// Tests a number for primality. The result is always exact.
        /// </summary>
        /// <param name="num">The number to test.</param>
        /// <returns><b>true</b> if the number is a prime number; <b>false</b> if it is composite.</returns>
        public static bool IsPrime(this long num)
        {
            if (num <= 1)
            {
                return(false);
            }
            if (num <= 3)
            {
                return(true);
            }
            if ((num & 1) == 0)
            {
                return(false);
            }
            var end = IntegerMath.IntSqrt(num);

            for (int i = 2; i < SmallPrimes.Length; i++)
            {
                var testNum = SmallPrimes[i];
                if (testNum > end)
                {
                    return(true);
                }
                if (num % testNum == 0)
                {
                    return(false);
                }
            }
            return(SPRPLong(num));
        }
예제 #3
0
        /// <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);
        }
예제 #4
0
        /// <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);
        }