private void karmul_lower(int vp, FF x, int xp, FF y, int yp, FF t, int tp, int n) { // Calculates Least Significant bottom half of x*y int nd2; if (n == 1) { // only calculate bottom half of product v[vp].copy(BIG.smul(x.v[xp], y.v[yp])); return; } nd2 = n / 2; karmul(vp, x, xp, y, yp, t, tp + n, nd2); t.karmul_lower(tp, x, xp + nd2, y, yp, t, tp + n, nd2); rinc(vp + nd2, t, tp, nd2); t.karmul_lower(tp, x, xp, y, yp + nd2, t, tp + n, nd2); rinc(vp + nd2, t, tp, nd2); rnorm(vp + nd2, -nd2); // truncate it }
/* return This mod modulus, N is modulus, ND is Montgomery Constant */ public FF reduce(FF N, FF ND) { // fast karatsuba Montgomery reduction int n = N.length; FF t = new FF(2 * n); FF r = new FF(n); FF m = new FF(n); r.sducopy(this); m.karmul_lower(0, this, 0, ND, 0, t, 0, n); karmul_upper(N, m, t, n); m.sducopy(this); r.add(N); r.sub(m); r.norm(); return(r); }