/* P=u0.Q0+u1*Q1+u2*Q2+u3*Q3 */ public static ECP2 mul4(ECP2[] Q, BIG[] u) { int i, j, nb; int[] a = new int[4]; ECP2 T = new ECP2(); ECP2 C = new ECP2(); ECP2 P = new ECP2(); ECP2[] W = new ECP2[8]; BIG mt = new BIG(); BIG[] t = new BIG[4]; sbyte[] w = new sbyte[ROM.NLEN * ROM.BASEBITS + 1]; for (i = 0; i < 4; i++) { t[i] = new BIG(u[i]); Q[i].affine(); } /* precompute table */ W[0] = new ECP2(); W[0].copy(Q[0]); W[0].sub(Q[1]); W[1] = new ECP2(); W[1].copy(W[0]); W[2] = new ECP2(); W[2].copy(W[0]); W[3] = new ECP2(); W[3].copy(W[0]); W[4] = new ECP2(); W[4].copy(Q[0]); W[4].add(Q[1]); W[5] = new ECP2(); W[5].copy(W[4]); W[6] = new ECP2(); W[6].copy(W[4]); W[7] = new ECP2(); W[7].copy(W[4]); T.copy(Q[2]); T.sub(Q[3]); W[1].sub(T); W[2].add(T); W[5].sub(T); W[6].add(T); T.copy(Q[2]); T.add(Q[3]); W[0].sub(T); W[3].add(T); W[4].sub(T); W[7].add(T); multiaffine(8, W); /* if multiplier is even add 1 to multiplier, and add P to correction */ mt.zero(); C.inf(); for (i = 0; i < 4; i++) { if (t[i].parity() == 0) { t[i].inc(1); t[i].norm(); C.add(Q[i]); } mt.add(t[i]); mt.norm(); } nb = 1 + mt.nbits(); /* convert exponent to signed 1-bit window */ for (j = 0; j < nb; j++) { for (i = 0; i < 4; i++) { a[i] = (sbyte)(t[i].lastbits(2) - 2); t[i].dec(a[i]); t[i].norm(); t[i].fshr(1); } w[j] = (sbyte)(8 * a[0] + 4 * a[1] + 2 * a[2] + a[3]); } w[nb] = (sbyte)(8 * t[0].lastbits(2) + 4 * t[1].lastbits(2) + 2 * t[2].lastbits(2) + t[3].lastbits(2)); P.copy(W[(w[nb] - 1) / 2]); for (i = nb - 1; i >= 0; i--) { T.select(W, w[i]); P.dbl(); P.add(T); } P.sub(C); // apply correction P.affine(); return(P); }