void force(ZZn& x,ZZn& y,ZZn& z,ECn& A) { // A=(x,y,z) copy(getbig(x),A.get_point()->X); copy(getbig(y),A.get_point()->Y); copy(getbig(z),A.get_point()->Z); A.get_point()->marker=MR_EPOINT_GENERAL; }
void endomorph(ECn &A,ZZn &Beta) { // apply endomorphism (x,y) = (Beta*x,y) where Beta is cube root of unity ZZn x; x=(A.get_point())->X; x*=Beta; copy(getbig(x),(A.get_point())->X); }
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); }
void force(ZZn& x,ZZn& y,ECn& A) { // A=(x,y) copy(getbig(x),A.get_point()->X); copy(getbig(y),A.get_point()->Y); A.get_point()->marker=MR_EPOINT_NORMALIZED; }
void setmod(const Poly2& p) { int i,n,m; Poly2 h; term2 *ptr; Modulus=p; n=degree(p); if (n<KARAT_BREAK_EVEN) return; h=reverse(p); h=invmodxn(h,n); h=reverse(h); // h=RECIP(f) m=degree(h); if (m<n-1) h=mulxn(h,n-1-m); if (GF!=NULL) { // kill last Modulus for (i=0;i<N+2;i++) { mr_free(GF[i]); mr_free(GRF[i]); mr_free(Q[i]); } for (i=0;i<2*(N+INC);i++) { mr_free(W[i]); mr_free(T[i]); } mr_free(GF); mr_free(GRF); mr_free(Q); mr_free(W); mr_free(T);; } N=n; m=N; INC=0; while (m!=0) { m/=2; INC++; } GF=(big *)mr_alloc(N+2,sizeof(big)); GRF=(big *)mr_alloc(N+2,sizeof(big)); Q=(big *)mr_alloc(N+2,sizeof(big)); W=(big *)mr_alloc(2*(N+INC),sizeof(big)); T=(big *)mr_alloc(2*(N+INC),sizeof(big)); for (i=0;i<N+2;i++) { GF[i]=mirvar(0); GRF[i]=mirvar(0); Q[i]=mirvar(0); } for (i=0;i<2*(N+INC);i++) { W[i]=mirvar(0); T[i]=mirvar(0); } ptr=p.start; while (ptr!=NULL) { copy(getbig(ptr->an),GF[ptr->n]); ptr=ptr->next; } ptr=h.start; while (ptr!=NULL) { copy(getbig(ptr->an),GRF[ptr->n]); ptr=ptr->next; } }
Poly2Mod compose(const Poly2Mod& q,const Poly2Mod& p) { // compose polynomials // assume P(x) = P3x^3 + P2x^2 + P1x^1 +P0 // Calculate P(Q(x)) = P3.(Q(x))^3 + P2.(Q(x))^2 .... Poly2Mod C,Q,T; big t; term2 *xptr,*yptr; int i,j,ik,L,n=degree(Modulus); int k=isqrt(n+1,1); if (k*k<n+1) k++; // step 1 Poly2Mod *P=new Poly2Mod[k+1]; P[0]=1; for (i=1;i<=k;i++) P[i]=(P[i-1]*p); big *x,*y; x=(big *)mr_alloc(k,sizeof(big)); y=(big *)mr_alloc(k,sizeof(big)); t=mirvar(0); T=1; for (i=0;i<k;i++) { ik=i*k; Q.clear(); for (L=0;L<=n;L++) { zero(t); xptr=q.p.start; while (xptr!=NULL) { if (xptr->n<=ik+k-1) break; xptr=xptr->next; } for (j=k-1;j>=0;j--) { x[j]=t; if (xptr!=NULL) { if (ik+j==xptr->n) { x[j]=getbig(xptr->an); xptr=xptr->next; } } // x[j]=q.coeff(i*k+j) y[j]=t; yptr=P[j].p.start; while (yptr!=NULL) { if (yptr->n<=L) { if (yptr->n==L) y[j]=getbig(yptr->an); break; } yptr=yptr->next; } } // y[j]=P[j].coeff(L) // Asymptotically slow, but fast in practise ... gf2m_dotprod(k,x,y,t); Q.addterm((GF2m)t,L); } C+=(Q*T); if (i<k-1) T*=P[k]; } mr_free(t); mr_free(y); mr_free(x); delete [] P; return C; }
Ps_ZZn operator*(Ps_ZZn& a,Ps_ZZn& b) { Ps_ZZn prod; ZZn t; term_ps_zzn *aptr,*bptr,*pos; int ka,kb,i,pa,pb,d,deg,g; if (a.IsInt()) { if (a.start==NULL) return prod; else return (a.start->an*b); } if (b.IsInt()) { if (b.start==NULL) return prod; else return (b.start->an*a); } g=igcd(a.pwr,b.pwr); deg=psN/g; #ifdef FFT if (deg>=FFT_BREAK_EVEN) { // use fast methods big *A,*B,*C; A=(big *)mr_alloc(deg,sizeof(big)); B=(big *)mr_alloc(deg,sizeof(big)); C=(big *)mr_alloc(deg,sizeof(big)); char *memc=(char *)memalloc(deg); for (i=0;i<deg;i++) C[i]=mirvar_mem(memc,i); ka=a.pwr/g; a.decompress(ka); aptr=a.start; while (aptr!=NULL) { d=aptr->n; if (d >= deg) break; A[d]=getbig(aptr->an); aptr=aptr->next; } kb=b.pwr/g; b.decompress(kb); bptr=b.start; while (bptr!=NULL) { d=bptr->n; if (d >= deg) break; B[d]=getbig(bptr->an); bptr=bptr->next; } mr_ps_zzn_mul(deg,A,B,C); pos=NULL; for (d=0;d<deg;d++) { t=C[d]; if (t.iszero()) continue; pos=prod.addterm(t,d*g,pos); } memkill(memc,deg); a.compress(ka); b.compress(kb); mr_free(C); mr_free(B); mr_free(A); } else { #endif bptr=b.start; while (bptr!=NULL) { aptr=a.start; pb=bptr->n*b.pwr-b.offset; pos=NULL; while (aptr!=NULL) { pa=aptr->n*a.pwr-a.offset; if (pb+pa>=psN) break; pos=prod.addterm(aptr->an*bptr->an,pa+pb,pos); aptr=aptr->next; } bptr=bptr->next; } #ifdef FFT } #endif if (prod.start!=NULL) prod.offset=a.offset+b.offset; return prod; }
Ps_ZZn& Ps_ZZn::operator*=(Ps_ZZn& b) { term_ps_zzn *ptr,*bptr; int g,d,deg,ka,kb; if (IsInt()) { if (start!=NULL) *this = start->an*b; return *this; } if (b.IsInt()) { if (b.start==NULL) clear(); else *this *=(b.start->an); return *this; } g=igcd(pwr,b.pwr); deg=psN/g; #ifdef FFT if (deg>=FFT_BREAK_EVEN) { big *A,*B; A=(big *)mr_alloc(deg,sizeof(big)); B=(big *)mr_alloc(deg,sizeof(big)); ka=pwr/g; decompress(ka); pad(); ptr=start; while (ptr!=NULL) { d=ptr->n; if (d>=deg) break; A[d]=getbig(ptr->an); ptr=ptr->next; } kb=b.pwr/g; b.decompress(kb); bptr=b.start; while (bptr!=NULL) { d=bptr->n; if (d>=deg) break; B[d]=getbig(bptr->an); bptr=bptr->next; } mr_ps_zzn_mul(deg,A,B,A); mr_free(B); mr_free(A); b.compress(kb); } else { #endif *this=*this*b; return *this; #ifdef FFT } #endif norm(); offset+=b.offset; return *this; }
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; }
Poly operator*(const Poly& a,const Poly& b) { int i,d,dega,degb,deg; BOOL squaring; ZZn t; Poly prod; term *iptr,*pos; term *ptr=b.start; squaring=FALSE; if (&a==&b) squaring=TRUE; dega=degree(a); deg=dega; if (!squaring) { degb=degree(b); if (degb<dega) deg=degb; } else degb=dega; if (deg>=FFT_BREAK_EVEN) /* deg is minimum - both must be less than FFT_BREAK_EVEN */ { // use fast methods big *A,*B,*C; deg=dega+degb; // degree of product A=(big *)mr_alloc(dega+1,sizeof(big)); if (!squaring) B=(big *)mr_alloc(degb+1,sizeof(big)); C=(big *)mr_alloc(deg+1,sizeof(big)); for (i=0;i<=deg;i++) C[i]=mirvar(0); ptr=a.start; while (ptr!=NULL) { A[ptr->n]=getbig(ptr->an); ptr=ptr->next; } if (!squaring) { ptr=b.start; while (ptr!=NULL) { B[ptr->n]=getbig(ptr->an); ptr=ptr->next; } mr_poly_mul(dega,A,degb,B,C); } else mr_poly_sqr(dega,A,C); pos=NULL; for (d=deg;d>=0;d--) { t=C[d]; mr_free(C[d]); if (t.iszero()) continue; pos=prod.addterm(t,d,pos); } mr_free(C); mr_free(A); if (!squaring) mr_free(B); return prod; } if (squaring) { // squaring pos=NULL; while (ptr!=NULL) { // diagonal terms pos=prod.addterm(ptr->an*ptr->an,ptr->n+ptr->n,pos); ptr=ptr->next; } ptr=b.start; while (ptr!=NULL) { // above the diagonal iptr=ptr->next; pos=NULL; while (iptr!=NULL) { t=ptr->an*iptr->an; pos=prod.addterm(t+t,ptr->n+iptr->n,pos); iptr=iptr->next; } ptr=ptr->next; } } else 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; }