ZZn6& ZZn6::powq(void) { ZZn X; copy(get_mip()->sru,X.getzzn()); a.powq(); b.powq(); b*=X; return *this; }
ostream& operator<<(ostream& s,const Ps_ZZn& p) { BOOL first=TRUE; ZZn a; term_ps_zzn *ptr=p.start; int pw; if (ptr==NULL) { s << "0"; return s; } while (ptr!=NULL) { a=ptr->an; if (a.iszero()) { ptr=ptr->next; continue; } if ((Big)a < get_modulus()/2) { a=(-a); s << " - "; } else if (!first) s << " + "; first=FALSE; pw=ptr->n*p.pwr-p.offset; if (pw==0) { s << a; ptr=ptr->next; continue; } if (a==(ZZn)1) s << "x"; else s << a << "*x"; if (pw!=1) s << "^" << pw; ptr=ptr->next; } return s; }
void ZZn3::get(ZZn& x) const {{copy(fn.a,x.getzzn());}}
void ZZn3::get(ZZn& x,ZZn& y,ZZn& z) const {copy(fn.a,x.getzzn()); copy(fn.b,y.getzzn()); copy(fn.c,z.getzzn());}
void ZZn2::get(ZZn& x,ZZn& y) const {{copy(fn.a,x.getzzn()); copy(fn.b,y.getzzn()); }}
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; }
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; }