/* * Miller-Rabin probabilistic test for composite numbers * as described in Corman/Leiserson/Rivest * * composite(n,d): returns false for all prime n, * and true for most composite n * (failure probability 1/2**d) * primebits(n,d): returns a random n-bit number k where !composite(k,d) * * Copyright © 1999 Bart Massey. * All Rights Reserved. See the file COPYING in this directory * for licensing information. * * Bart Massey 1999/1 */ autoload PRNG; namespace MillerRabin { int[*] primes = { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29 }; int nprimes = dim(primes); typedef struct { int pow, wit; } witness_result; /* * Modified version of bigpowmod() from numbers.5c. * Computes core of Miller-Rabin test * as suggested by Cormen/Leiserson/Rivest. */ witness_result witnessexp(int b, int e, int m) { switch (e) { case 0: return (witness_result){ .pow = 0, .wit = 1}; case 1: return (witness_result){ .pow = b % m, .wit = 0}; } witness_result tmp = witnessexp(b, e // 2, m); if (tmp.wit != 0) return tmp; int t = (tmp.pow * tmp.pow) % m; if (t == 1 && tmp.pow != 1 && tmp.pow != m - 1) { tmp.wit = tmp.pow; tmp.pow = t; return tmp; } if (e % 2 == 0) tmp.pow = t; else tmp.pow = (t * b) % m; return tmp; } /* Rest of Miller-Rabin test */ bool witness(int a, int n) { witness_result we = witnessexp(a, n - 1, n); if (we.wit != 0) return true; if (we.pow != 1) return true; return false; } /* Try small primes, then Miller-Rabin */ public bool composite(int n, int d) { int i, j; for (i = 0; i < nprimes && primes[i] < n; i++) if (n % primes[i] == 0) return true; for (j = 0; j < d; j++) { int a = 1 + PRNG::randint(n - 1); if (witness(a, n)) return true; } return false; } /* generate an n-bit prime (with probability 1-(2**-d)) number */ public int primebits(int n, int d) { while (true) { int q = PRNG::randbits(n - 1) + 2**(n - 1); bool why = composite(q, d); if (!why) return q; # printf("*\n"); } } }