void elliptic_add(Poly2Mod& XT,Poly2Mod& XTy,Poly2Mod& YT,Poly2Mod& YTy,Poly2Mod& ZT,Poly2Mod& X,Poly2Mod& Y,Poly2Mod& Yy) { // add (X,Y,Z) to (XT,YT,ZT) on an elliptic curve // The point Y is of the form A(x)+B(x).y Poly2Mod ZT2,ZT3,W1,W2,W3,W4,W5,W5y,W6,W6y,W7,W8,W8y,W9,W9y; ZT2=(ZT*ZT); W3=XT+X*ZT2; ZT3=ZT2*ZT; W5=ZT3*Y; W5y=ZT3*Yy; W6=YT+W5; W6y=YTy+W5y; if (iszero(W3)) { if (iszero(W6) && iszero(W6y)) { // should have doubled! elliptic_dup(XT,YT,YTy,ZT); XTy=0; return; } ZT.clear(); return; } ZT*=W3; W8=W6*X+ZT*Y; W8y=W6y*X+ZT*Yy; W9=W6+ZT; W1=ZT*ZT; W2=W6y*W6y; XT=A*W1+W3*W3*W3+W6*W9+W2*MFX; XTy=W9*W6y+W6y*W6+W2*XX; W2=W6y*XTy; YT=W9*XT+W2*MFX+W8*W1; YTy=XT*W6y+W9*XTy+W2*XX+W1*W8y; }
void reduce(const Poly2& p,Poly2Mod& rem) { int m,d; GF2m t; big *G; term2 *ptr,*pos=NULL; int n=degree(p); int degm=degree(Modulus); if (n-degm < KARAT_BREAK_EVEN) { rem=(Poly2Mod)p; return; } G=(big *)mr_alloc(2*(N+2),sizeof(big)); ptr=p.start; while (ptr!=NULL) { G[ptr->n]=getbig(ptr->an); ptr=ptr->next; } karmul2_poly(N,T,GRF,&G[N],W); // W=(G/x^n) * h for (d=N-1;d<2*N;d++) copy(W[d],Q[d-N+1]); m=N+1; if(m%2==1) m=N+2; // make sure m is even - pad if necessary for (d=m;d<2*m;d++) copy(G[d],W[d]); karmul2_poly_upper(m,T,GF,Q,W); pos=NULL; rem.clear(); for (d=N-1;d>=0;d--) { add2(W[d],G[d],W[d]); t=W[d]; if (t.iszero()) continue; pos=rem.addterm(t,d,pos); } mr_free(G); }