/* z=x*y. Assumes x and y are of same length. */ public static FF mul(FF x, FF y) { int n = x.length; FF z = new FF(2 * n); FF t = new FF(2 * n); z.karmul(0, x, 0, y, 0, t, 0, n); return(z); }
private void karsqr(int vp, FF x, int xp, FF t, int tp, int n) { int nd2; if (n == 1) { DBIG d = BIG.sqr(x.v[xp]); v[vp + 1].copy(d.Split(8 * ROM.MODBYTES)); v[vp].copy(d); return; } nd2 = n / 2; karsqr(vp, x, xp, t, tp + n, nd2); karsqr(vp + n, x, xp + nd2, t, tp + n, nd2); t.karmul(tp, x, xp, x, xp + nd2, t, tp + n, nd2); rinc(vp + nd2, t, tp, n); rinc(vp + nd2, t, tp, n); rnorm(vp + nd2, n); }
private void karmul_upper(FF x, FF y, FF t, int n) { // Calculates Most Significant upper half of x*y, given lower part int nd2; nd2 = n / 2; radd(n, x, 0, x, nd2, nd2); radd(n + nd2, y, 0, y, nd2, nd2); t.karmul(0, this, n + nd2, this, n, t, n, nd2); // t = (a0+a1)(b0+b1) karmul(n, x, nd2, y, nd2, t, n, nd2); // z[n]= a1*b1 /* z[0-nd2]=l(a0b0) z[nd2-n]= h(a0b0)+l(t)-l(a0b0)-l(a1b1) */ t.rdec(0, this, n, n); // t=t-a1b1 rinc(nd2, this, 0, nd2); // z[nd2-n]+=l(a0b0) = h(a0b0)+l(t)-l(a1b1) rdec(nd2, t, 0, nd2); // z[nd2-n]=h(a0b0)+l(t)-l(a1b1)-l(t-a1b1)=h(a0b0) rnorm(0, -n); // a0b0 now in z - truncate it t.rdec(0, this, 0, n); // (a0+a1)(b0+b1) - a0b0 rinc(nd2, t, 0, n); rnorm(nd2, n); }
/* z=x*y, t is workspace */ private void karmul(int vp, FF x, int xp, FF y, int yp, FF t, int tp, int n) { int nd2; if (n == 1) { DBIG d = BIG.mul(x.v[xp], y.v[yp]); v[vp + 1] = d.Split(8 * ROM.MODBYTES); v[vp].copy(d); return; } nd2 = n / 2; radd(vp, x, xp, x, xp + nd2, nd2); //rnorm(vp,nd2); radd(vp + nd2, y, yp, y, yp + nd2, nd2); //rnorm(vp+nd2,nd2); t.karmul(tp, this, vp, this, vp + nd2, t, tp + n, nd2); karmul(vp, x, xp, y, yp, t, tp + n, nd2); karmul(vp + n, x, xp + nd2, y, yp + nd2, t, tp + n, nd2); t.rdec(tp, this, vp, n); t.rdec(tp, this, vp + n, n); rinc(vp + nd2, t, tp, n); rnorm(vp, 2 * n); }