GT PFC::miller_loop(const G2& QQ,const G1& PP) { GT z; Big n; int i,j,nb,nbw,nzs; ECn2 A,KA,Q; ECn P; ZZn Px,Py; BOOL precomp; ZZn12 r; Big X=*x; Q=QQ.g; P=PP.g; precomp=FALSE; if (QQ.ptable!=NULL) precomp=TRUE; else Q.norm(); normalise(P); extract(P,Px,Py); if (X<0) n=-(6*X+2); else n=6*X+2; A=Q; nb=bits(n); r=1; // Short Miller loop r.mark_as_miller(); j=0; for (i=nb-2;i>=0;i--) { r*=r; if (precomp) r*=gp(QQ.ptable,j,Px,Py); else r*=g(A,A,Px,Py); if (bit(n,i)) { if (precomp) r*=gp(QQ.ptable,j,Px,Py); else r*=g(A,Q,Px,Py); } } // Combining ideas due to Longa, Aranha et al. and Naehrig KA=Q; q_power_frobenius(KA,*frob); if (X<0) {A=-A; r.conj();} if (precomp) r*=gp(QQ.ptable,j,Px,Py); else r*=g(A,KA,Px,Py); q_power_frobenius(KA,*frob); KA=-KA; if (precomp) r*=gp(QQ.ptable,j,Px,Py); else r*=g(A,KA,Px,Py); z.g=r; return z; }
int PFC::precomp_for_pairing(G2& w) { int i,j,nb,len; ECn2 A,Q,B,KA; ZZn2 lam,x1,y1; Big n; Big X=*x; A=w.g; A.norm(); B=A; KA=A; if (X<0) n=-(6*X+2); else n=6*X+2; nb=bits(n); j=0; len=2*(nb+ham(n)); // ** w.ptable=new ZZn2[len]; get_mip()->coord=MR_AFFINE; // switch to affine for (i=nb-2;i>=0;i--) { Q=A; // Evaluate line from A to A+A A.add(A,lam); Q.get(x1,y1); w.ptable[j++]=-lam; w.ptable[j++]=lam*x1-y1; if (bit(n,i)==1) { Q=A; A.add(B,lam); Q.get(x1,y1); w.ptable[j++]=-lam; w.ptable[j++]=lam*x1-y1; } } q_power_frobenius(KA,*frob); if (X<0) A=-A; Q=A; A.add(KA,lam); KA.get(x1,y1); w.ptable[j++]=-lam; w.ptable[j++]=lam*x1-y1; q_power_frobenius(KA,*frob); KA=-KA; Q=A; A.add(KA,lam); KA.get(x1,y1); w.ptable[j++]=-lam; w.ptable[j++]=lam*x1-y1; get_mip()->coord=MR_PROJECTIVE; return len; }
G2 PFC::mult(const G2& w,const Big& k) { G2 z; Big X=*x; if (w.mtable!=NULL) { // we have precomputed values Big e=k; if (k<0) e=-e; int i,j,t=w.mtbits; //MR_ROUNDUP(2*S,WINDOW_SIZE); j=recode(e,t,WINDOW_SIZE,t-1); z.g=w.mtable[j]; for (i=t-2;i>=0;i--) { j=recode(e,t,WINDOW_SIZE,i); z.g+=z.g; if (j>0) z.g+=w.mtable[j]; } if (k<0) z.g=-z.g; } else { ECn3 v=w.g; q_power_frobenius(v,*frob); z.g=mul(v,k/X,w.g,k%X); } return z; }
ECn3 G2_mul(ECn3& P,Big& k,Big& x,ZZn2& X) { ECn3 V=P; q_power_frobenius(V,X); V=mul(V,k/x,P,k%x); return V; }
void map(ECn2& S,Big &x,ZZn2 &F) { ECn2 T,K; T=S; T*=x; // one multiplication by x only T.norm(); K=(T+T); K+=T; K.norm(); q_power_frobenius(K,F); q_power_frobenius(S,F); q_power_frobenius(S,F); q_power_frobenius(S,F); S+=T; S+=K; q_power_frobenius(T,F); q_power_frobenius(T,F); S+=T; S.norm(); }
G2 PFC::mult(const G2& w,const Big& k) { G2 z; int i; if (w.mtable!=NULL) { // we have precomputed values Big e=k; if (k<0) e=-e; int i,j,t=w.mtbits; //MR_ROUNDUP(2*S,WINDOW_SIZE); j=recode(e,t,WINDOW_SIZE,t-1); z.g=w.mtable[j]; for (i=t-2;i>=0;i--) { j=recode(e,t,WINDOW_SIZE,i); z.g+=z.g; if (j>0) z.g+=w.mtable[j]; } if (k<0) z.g=-z.g; } else { ECn2 Q[4]; Big u[4]; BOOL small=TRUE; galscott(k,*ord,WB,BB,u); Q[0]=w.g; Q[0].norm(); for (i=1;i<4;i++) { if (u[i]!=0) { small=FALSE; break; } } if (small) { if (u[0]<0) { u[0]=-u[0]; Q[0]=-Q[0]; } z.g=Q[0]; z.g*=u[0]; z.g.norm(); return z; } for (i=1;i<4;i++) { Q[i]=Q[i-1]; q_power_frobenius(Q[i],*frob); } // deal with -ve multipliers for (i=0;i<4;i++) { if (u[i]<0) {u[i]=-u[i];Q[i]=-Q[i];} } // simple multi-addition z.g= mul(4,Q,u); } z.g.norm(); return z; }
GT PFC::multi_miller(int n,G2** QQ,G1** PP) { GT z; ZZn *Px,*Py; int i,j,*k,nb; ECn2 *Q,*A; ECn P; ZZn12 res; Big m; Big X=*x; Px=new ZZn[n]; Py=new ZZn[n]; Q=new ECn2[n]; A=new ECn2[n]; k=new int[n]; if (X<0) m=-(6*X+2); else m=6*X+2; nb=bits(m); res=1; for (j=0;j<n;j++) { k[j]=0; P=PP[j]->g; normalise(P); Q[j]=QQ[j]->g; Q[j].norm(); extract(P,Px[j],Py[j]); } for (j=0;j<n;j++) A[j]=Q[j]; for (i=nb-2;i>=0;i--) { res*=res; for (j=0;j<n;j++) { if (QQ[j]->ptable==NULL) res*=g(A[j],A[j],Px[j],Py[j]); else res*=gp(QQ[j]->ptable,k[j],Px[j],Py[j]); } if (bit(m,i)==1) for (j=0;j<n;j++) { if (QQ[j]->ptable==NULL) res*=g(A[j],Q[j],Px[j],Py[j]); else res*=gp(QQ[j]->ptable,k[j],Px[j],Py[j]); } if (res.iszero()) return 0; } if (X<0) res.conj(); for (j=0;j<n;j++) { q_power_frobenius(Q[j],*frob); if (QQ[j]->ptable==NULL) { if (X<0) A[j]=-A[j]; res*=g(A[j],Q[j],Px[j],Py[j]); } else res*=gp(QQ[j]->ptable,k[j],Px[j],Py[j]); q_power_frobenius(Q[j],*frob); if (QQ[j]->ptable==NULL) { Q[j]=-Q[j]; res*=g(A[j],Q[j],Px[j],Py[j]); } else res*=gp(QQ[j]->ptable,k[j],Px[j],Py[j]); } delete [] k; delete [] A; delete [] Q; delete [] Py; delete [] Px; z.g=res; return z; }