コード例 #1
0
ファイル: Primality.cs プロジェクト: bugbit/CASSharp
        /**
         * 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);
        }