in native/src/seal/util/numth.cpp [179:275]
bool is_prime(const Modulus &modulus, size_t num_rounds)
{
uint64_t value = modulus.value();
// First check the simplest cases.
if (value < 2)
{
return false;
}
if (2 == value)
{
return true;
}
if (0 == (value & 0x1))
{
return false;
}
if (3 == value)
{
return true;
}
if (0 == (value % 3))
{
return false;
}
if (5 == value)
{
return true;
}
if (0 == (value % 5))
{
return false;
}
if (7 == value)
{
return true;
}
if (0 == (value % 7))
{
return false;
}
if (11 == value)
{
return true;
}
if (0 == (value % 11))
{
return false;
}
if (13 == value)
{
return true;
}
if (0 == (value % 13))
{
return false;
}
// Second, Miller-Rabin test.
// Find r and odd d that satisfy value = 2^r * d + 1.
uint64_t d = value - 1;
uint64_t r = 0;
while (0 == (d & 0x1))
{
d >>= 1;
r++;
}
if (r == 0)
{
return false;
}
// 1) Pick a = 2, check a^(value - 1).
// 2) Pick a randomly from [3, value - 1], check a^(value - 1).
// 3) Repeat 2) for another num_rounds - 2 times.
random_device rand;
uniform_int_distribution<unsigned long long> dist(3, value - 1);
for (size_t i = 0; i < num_rounds; i++)
{
uint64_t a = i ? dist(rand) : 2;
uint64_t x = exponentiate_uint_mod(a, d, modulus);
if (x == 1 || x == value - 1)
{
continue;
}
uint64_t count = 0;
do
{
x = multiply_uint_mod(x, x, modulus);
count++;
} while (x != value - 1 && count < r - 1);
if (x != value - 1)
{
return false;
}
}
return true;
}