internal bool RabinMillerTest(
int certainty,
Random random)
{
Debug.Assert(certainty > 0);
Debug.Assert(BitLength > 2);
Debug.Assert(TestBit(0));
// let n = 1 + d . 2^s
BigInteger n = this;
BigInteger nMinusOne = n.Subtract(One);
int s = nMinusOne.GetLowestSetBit();
BigInteger r = nMinusOne.ShiftRight(s);
Debug.Assert(s >= 1);
do
{
// TODO Make a method for random BigIntegers in range 0 < x < n)
// - Method can be optimized by only replacing examined bits at each trial
BigInteger a;
do
{
a = new BigInteger(n.BitLength, random);
}
while (a.CompareTo(One) <= 0 || a.CompareTo(nMinusOne) >= 0);
BigInteger y = a.ModPow(r, n);
if (!y.Equals(One))
{
int j = 0;
while (!y.Equals(nMinusOne))
{
if (++j == s)
return false;
y = y.ModPow(Two, n);
if (y.Equals(One))
return false;
}
}
certainty -= 2; // composites pass for only 1/4 possible 'a'
}
while (certainty > 0);
return true;
}