private static BigInteger[] findRandomStrongPrime(int primeBits, int orderBits, Rng random)
{
BigInteger one = new BigInteger(1);
ulong[] table_q, table_u, prime_table;
PrimeSieve sieve = new PrimeSieve(16000);
uint table_count = sieve.AvailablePrimes() - 1;
int i, j;
bool flag;
BigInteger prime = null, order = null;
order = BigInteger.GeneratePseudoPrime(orderBits);
prime_table = new ulong[table_count];
table_q = new ulong[table_count];
table_u = new ulong[table_count];
i = 0;
for (uint pN = 2; pN != 0; pN = sieve.getNextPrime(pN), i++) {
prime_table[i] = pN;
}
for (i = 0; i < table_count; i++) {
table_q[i] =
((AsUInt64(order % new BigInteger(prime_table[i]))) *
2UL) % prime_table[i];
}
while (true) {
BigInteger u = BigInteger.GenerateRandom(primeBits);
BigInteger aux = order << 1;
BigInteger aux2 = u % aux;
u = u - aux2;
u = u + one;
if (u.BitCount() <= (primeBits - 1))
continue;
for (j = 0; j < table_count; j++) {
table_u[j] =
AsUInt64(u % new BigInteger(prime_table[j]));
}
aux2 = order << 1;
for (i = 0; i < (1 << 24); i++) {
ulong cur_p;
ulong value;
flag = true;
for (j = 1; j < table_count; j++) {
cur_p = prime_table[j];
value = table_u[j];
if (value >= cur_p)
value -= cur_p;
if (value == 0)
flag = false;
table_u[j] = value + table_q[j];
}
if (!flag)
continue;
aux = aux2 * new BigInteger(i);
prime = u + aux;
if (prime.BitCount() > primeBits)
continue;
if (prime.IsProbablePrime())
break;
}
if (i < (1 << 24))
break;
}
return new BigInteger[] { prime, order };
}