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); }
Poly2 operator*(const Poly2& a,const Poly2& b) { int i,d,dega,degb,deg; GF2m t; Poly2 prod; term2 *iptr,*pos; term2 *ptr=b.start; if (&a==&b) { // squaring - only diagonal terms count! pos=NULL; while (ptr!=NULL) { // diagonal terms pos=prod.addterm(ptr->an*ptr->an,ptr->n+ptr->n,pos); ptr=ptr->next; } return prod; } dega=degree(a); deg=dega; degb=degree(b); if (degb<dega) deg=degb; // deg is smallest if (deg>=KARAT_BREAK_EVEN) { // use fast method int len,m,inc; big *A,*B,*C,*T; deg=dega; if (dega<degb) deg=degb; // deg is biggest m=deg; inc=1; while (m!=0) { m/=2; inc++; } len=2*(deg+inc); A=(big *)mr_alloc(deg+1,sizeof(big)); B=(big *)mr_alloc(deg+1,sizeof(big)); C=(big *)mr_alloc(len,sizeof(big)); T=(big *)mr_alloc(len,sizeof(big)); char *memc=(char *)memalloc(len); char *memt=(char *)memalloc(len); for (i=0;i<len;i++) { C[i]=mirvar_mem(memc,i); T[i]=mirvar_mem(memt,i); } ptr=a.start; while (ptr!=NULL) { A[ptr->n]=getbig(ptr->an); ptr=ptr->next; } ptr=b.start; while (ptr!=NULL) { B[ptr->n]=getbig(ptr->an); ptr=ptr->next; } karmul2_poly(deg+1,T,A,B,C); pos=NULL; for (d=dega+degb;d>=0;d--) { t=C[d]; if (t.iszero()) continue; pos=prod.addterm(t,d,pos); } memkill(memc,len); memkill(memt,len); mr_free(T); mr_free(C); mr_free(B); mr_free(A); return prod; } while (ptr!=NULL) { pos=NULL; iptr=a.start; while (iptr!=NULL) { pos=prod.addterm(ptr->an*iptr->an,ptr->n+iptr->n,pos); iptr=iptr->next; } ptr=ptr->next; } return prod; }