public bool isProbablePrime()
{
BigInteger thisVal;
if((this.data[maxLength-1] & 0x80000000) != 0) // negative
thisVal = -this;
else
thisVal = this;
if(thisVal.dataLength == 1)
{
// test small numbers
if(thisVal.data[0] == 0 || thisVal.data[0] == 1)
return false;
else if(thisVal.data[0] == 2 || thisVal.data[0] == 3)
return true;
}
if((thisVal.data[0] & 0x1) == 0) // even numbers
return false;
// test for divisibility by primes < 2000
for(int p = 0; p < primesBelow2000.Length; p++)
{
BigInteger divisor = primesBelow2000[p];
if(divisor >= thisVal)
break;
BigInteger resultNum = thisVal % divisor;
if(resultNum.IntValue() == 0)
{
//Console.WriteLine("Not prime! Divisible by {0}\n",
// primesBelow2000[p]);
return false;
}
}
// Perform BASE 2 Rabin-Miller Test
// calculate values of s and t
BigInteger p_sub1 = thisVal - (new BigInteger(1));
int s = 0;
for(int index = 0; index < p_sub1.dataLength; index++)
{
uint mask = 0x01;
for(int i = 0; i < 32; i++)
{
if((p_sub1.data[index] & mask) != 0)
{
index = p_sub1.dataLength; // to break the outer loop
break;
}
mask <<= 1;
s++;
}
}
BigInteger t = p_sub1 >> s;
int bits = thisVal.bitCount();
BigInteger a = 2;
// b = a^t mod p
BigInteger b = a.modPow(t, thisVal);
bool result = false;
if(b.dataLength == 1 && b.data[0] == 1) // a^t mod p = 1
result = true;
for(int j = 0; result == false && j < s; j++)
{
if(b == p_sub1) // a^((2^j)*t) mod p = p-1 for some 0 <= j <= s-1
{
result = true;
break;
}
b = (b * b) % thisVal;
}
// if number is strong pseudoprime to base 2, then do a strong lucas test
if(result)
result = LucasStrongTestHelper(thisVal);
return result;
}