/* quick and dirty check for common factor with n */ public bool cfactor(int s) { int r, n = length; int g; FF x = new FF(n); FF y = new FF(n); y.set(s); x.copy(this); x.norm(); do { x.sub(y); x.norm(); while (!x.iszilch() && x.parity() == 0) { x.shr(); } } while (comp(x, y) > 0); g = (int)x.v[0].get(0); r = igcd(s, g); if (r > 1) { return(true); } return(false); }
/* Set return=1/this mod p. Binary method - a<p on entry */ public void invmodp(FF p) { int n = p.length; FF u = new FF(n); FF v = new FF(n); FF x1 = new FF(n); FF x2 = new FF(n); FF t = new FF(n); FF one = new FF(n); one.one(); u.copy(this); v.copy(p); x1.copy(one); x2.zero(); // reduce n in here as well! while (comp(u, one) != 0 && comp(v, one) != 0) { while (u.parity() == 0) { u.shr(); if (x1.parity() != 0) { x1.add(p); x1.norm(); } x1.shr(); } while (v.parity() == 0) { v.shr(); if (x2.parity() != 0) { x2.add(p); x2.norm(); } x2.shr(); } if (comp(u, v) >= 0) { u.sub(v); u.norm(); if (comp(x1, x2) >= 0) { x1.sub(x2); } else { t.copy(p); t.sub(x2); x1.add(t); } x1.norm(); } else { v.sub(u); v.norm(); if (comp(x2, x1) >= 0) { x2.sub(x1); } else { t.copy(p); t.sub(x1); x2.add(t); } x2.norm(); } } if (comp(u, one) == 0) { copy(x1); } else { copy(x2); } }
/* Miller-Rabin test for primality. Slow. */ public static bool prime(FF p, RAND rng) { int i, j, s = 0, n = p.length; bool loop; FF d = new FF(n); FF x = new FF(n); FF unity = new FF(n); FF nm1 = new FF(n); int sf = 4849845; // 3*5*.. *19 p.norm(); if (p.cfactor(sf)) { return(false); } unity.one(); nm1.copy(p); nm1.sub(unity); nm1.norm(); d.copy(nm1); while (d.parity() == 0) { d.shr(); s++; } if (s == 0) { return(false); } for (i = 0; i < 10; i++) { x.randomnum(p, rng); x.pow(d, p); if (comp(x, unity) == 0 || comp(x, nm1) == 0) { continue; } loop = false; for (j = 1; j < s; j++) { x.power(2, p); if (comp(x, unity) == 0) { return(false); } if (comp(x, nm1) == 0) { loop = true; break; } } if (loop) { continue; } return(false); } return(true); }