#include <stdarg.h> #include <stdio.h> #include <stdlib.h> typedef long long int_t; int_t pow_(int_t b, int_t e); void do_error(const char *fmat, ...); int main(int argc, char **argv) { int_t n, r, s, a, j; if (argc <= 1) do_error("Usage: rabinmiller <possible-prime>");
Initialize n. Determine r and s such that
n = 2 r s+1
n = strtol(argv[1], NULL, 10); if (n % 2 == 0) do_error("n can't be even!"); s = n-1; for (r=0; (s % 2) == 0; ++r) s >>= 1;
Now, for each a with 1 ≤ a ≤ n-1, we say that n passes the test for that a if and only if as ≡ 1(modn) or a2js ≡ -1(modn) for some 0 ≤ j ≤ r-1. A prime will pass the tests for every a.
for (a = 1; a < n; ++a) { if (pow_(a, s) % n == 1) goto pass_test; for (j = 0; j < r; ++j) if (pow_(a, (1 << j)*s) % n == n-1) goto pass_test; goto fail_test; pass_test: continue; } printf("%ld passes the Rabin-Miller primality test!\n" "It may be a prime.\n", (long)n); return 0; fail_test: printf("%ld fails the Rabin-Miller test.\n" "It is not a prime.\n", (long)n); return 0; } int_t pow_(int_t b, int_t e) { if (e < 0) return 0; else if (e == 0) return 1; else if (e == 1) return b; else if (e == 2) return b*b; else return pow_(b, e/2) * pow_(b, e - e/2); } void do_error(const char *fmat, ...) { va_list ap; va_start(ap, fmat); vfprintf(stderr, fmat, ap); fprintf(stderr, "\n"); va_end(ap); exit(EXIT_FAILURE); }