in src/ecp8.js [880:1050]
ECP8.mul16 = function(Q, u) {
var W = new ECP8(),
P = new ECP8(),
T1 = [],
T2 = [],
T3 = [],
T4 = [],
mt = new ctx.BIG(),
t = [],
w1 = [],
s1 = [],
w2 = [],
s2 = [],
w3 = [],
s3 = [],
w4 = [],
s4 = [],
F=ECP8.frob_constants(),
i, j, k, nb, bt, pb1, pb2, pb3, pb4;
for (i = 0; i < 16; i++) {
t[i] = new ctx.BIG(u[i]); t[i].norm();
//Q[i].affine();
}
T1[0] = new ECP8(); T1[0].copy(Q[0]); // Q[0]
T1[1] = new ECP8(); T1[1].copy(T1[0]); T1[1].add(Q[1]); // Q[0]+Q[1]
T1[2] = new ECP8(); T1[2].copy(T1[0]); T1[2].add(Q[2]); // Q[0]+Q[2]
T1[3] = new ECP8(); T1[3].copy(T1[1]); T1[3].add(Q[2]); // Q[0]+Q[1]+Q[2]
T1[4] = new ECP8(); T1[4].copy(T1[0]); T1[4].add(Q[3]); // Q[0]+Q[3]
T1[5] = new ECP8(); T1[5].copy(T1[1]); T1[5].add(Q[3]); // Q[0]+Q[1]+Q[3]
T1[6] = new ECP8(); T1[6].copy(T1[2]); T1[6].add(Q[3]); // Q[0]+Q[2]+Q[3]
T1[7] = new ECP8(); T1[7].copy(T1[3]); T1[7].add(Q[3]); // Q[0]+Q[1]+Q[2]+Q[3]
// Use Frobenius
for (i=0;i<8;i++) {
T2[i] = new ECP8(); T2[i].copy(T1[i]);
T2[i].frob(F,4);
T3[i] = new ECP8(); T3[i].copy(T2[i]);
T3[i].frob(F,4);
T4[i] = new ECP8(); T4[i].copy(T3[i]);
T4[i].frob(F,4);
}
// Make it odd
pb1=1-t[0].parity();
t[0].inc(pb1);
t[0].norm();
pb2=1-t[4].parity();
t[4].inc(pb2);
t[4].norm();
pb3=1-t[8].parity();
t[8].inc(pb3);
t[8].norm();
pb4=1-t[12].parity();
t[12].inc(pb4);
t[12].norm();
// Number of bits
mt.zero();
for (i=0;i<16;i++) {
mt.or(t[i]);
}
nb=1+mt.nbits();
// Sign pivot
s1[nb-1]=1;
s2[nb-1]=1;
s3[nb-1]=1;
s4[nb-1]=1;
for (i=0;i<nb-1;i++) {
t[0].fshr(1);
s1[i]=2*t[0].parity()-1;
t[4].fshr(1);
s2[i]=2*t[4].parity()-1;
t[8].fshr(1);
s3[i]=2*t[8].parity()-1;
t[12].fshr(1);
s4[i]=2*t[12].parity()-1;
}
// Recoded exponent
for (i=0; i<nb; i++) {
w1[i]=0;
k=1;
for (j=1; j<4; j++) {
bt=s1[i]*t[j].parity();
t[j].fshr(1);
t[j].dec(bt>>1);
t[j].norm();
w1[i]+=bt*k;
k*=2;
}
w2[i]=0;
k=1;
for (j=5; j<8; j++) {
bt=s2[i]*t[j].parity();
t[j].fshr(1);
t[j].dec(bt>>1);
t[j].norm();
w2[i]+=bt*k;
k*=2;
}
w3[i]=0;
k=1;
for (j=9; j<12; j++) {
bt=s3[i]*t[j].parity();
t[j].fshr(1);
t[j].dec(bt>>1);
t[j].norm();
w3[i]+=bt*k;
k*=2;
}
w4[i]=0;
k=1;
for (j=13; j<16; j++) {
bt=s4[i]*t[j].parity();
t[j].fshr(1);
t[j].dec(bt>>1);
t[j].norm();
w4[i]+=bt*k;
k*=2;
}
}
// Main loop
P.select(T1,2*w1[nb-1]+1);
W.select(T2,2*w2[nb-1]+1);
P.add(W);
W.select(T3,2*w3[nb-1]+1);
P.add(W);
W.select(T4,2*w4[nb-1]+1);
P.add(W);
for (i=nb-2;i>=0;i--) {
P.dbl();
W.select(T1,2*w1[i]+s1[i]);
P.add(W);
W.select(T2,2*w2[i]+s2[i]);
P.add(W);
W.select(T3,2*w3[i]+s3[i]);
P.add(W);
W.select(T4,2*w4[i]+s4[i]);
P.add(W);
}
// apply correction
W.copy(P);
W.sub(Q[0]);
P.cmove(W,pb1);
W.copy(P);
W.sub(Q[4]);
P.cmove(W,pb2);
W.copy(P);
W.sub(Q[8]);
P.cmove(W,pb3);
W.copy(P);
W.sub(Q[12]);
P.cmove(W,pb4);
P.affine();
return P;
};