对于 64 位值的 MR 测试有有效的deterministic variants - 不依赖于 GRH - 已经通过利用 GPU 和其他已知结果进行了详尽的测试。
我列出了我编写的用于测试任何 64 位值的素数的 C 程序的相关部分:(n > 1),使用 Jaeschke 和 Sinclair 的确定性 MR 变体的基础。它利用 gcc 和 clang 的 __int128 扩展类型进行求幂。如果不可用,则需要显式例程。也许其他人会觉得这很有用...
#include <inttypes.h>
/******************************************************************************/
static int sprp (uint64_t n, uint64_t a)
{
uint64_t m = n - 1, r, y;
unsigned int s = 1, j;
/* assert(n > 2 && (n & 0x1) != 0); */
while ((m & (UINT64_C(1) << s)) == 0) s++;
r = m >> s; /* r, s s.t. 2^s * r = n - 1, r in odd. */
if ((a %= n) == 0) /* else (0 < a < n) */
return (1);
{
unsigned __int128 u = 1, w = a;
while (r != 0)
{
if ((r & 0x1) != 0)
u = (u * w) % n; /* (mul-rdx) */
if ((r >>= 1) != 0)
w = (w * w) % n; /* (sqr-rdx) */
}
if ((y = (uint64_t) u) == 1)
return (1);
}
for (j = 1; j < s && y != m; j++)
{
unsigned __int128 u = y;
u = (u * u) % n; /* (sqr-rdx) */
if ((y = (uint64_t) u) <= 1) /* (n) is composite: */
return (0);
}
return (y == m);
}
/******************************************************************************/
static int is_prime (uint64_t n)
{
const uint32_t sprp32_base[] = /* (Jaeschke) */ {
2, 7, 61, 0};
const uint32_t sprp64_base[] = /* (Sinclair) */ {
2, 325, 9375, 28178, 450775, 9780504, 1795265022, 0};
const uint32_t *sprp_base;
/* assert(n > 1); */
if ((n & 0x1) == 0) /* even: */
return (n == 2);
sprp_base = (n <= UINT32_MAX) ? sprp32_base : sprp64_base;
for (; *sprp_base != 0; sprp_base++)
if (!sprp(n, *sprp_base)) return (0);
return (1); /* prime. */
}
/******************************************************************************/
请注意,MR (sprp) 测试稍作修改以通过值在基数是候选者的倍数的迭代中,如网站的“备注”部分所述
更新:虽然这比Niklas' 答案的基础测试更少,但重要的是要注意基础:{3, 5, 7, 11, 13, 17, 19, 23, 29} 提供了一种廉价的测试,使我们能够消除超过:29 * 29 = 841 的候选人-
只需使用 GCD。
对于(n > 29 * 29),我们可以清楚地消除任何偶数作为素数。小素数的乘积:(3 * 5 * 7 * 11 * 13 * 17 * 19 * 23 * 29} = 3234846615,非常适合 32 位无符号值。 gcd(n, 3234846615) 比 MR 测试便宜很多!如果结果不是(1),那么(n) > 841的系数很小。
Merten (?) 定理表明,这个简单的gcd(u64, u64) 测试消除了约 68% 的奇数候选(作为复合材料)。如果您使用 M-R 搜索素数(随机或增量),而不仅仅是“一次性”测试,那么这当然值得!