FPoly operator*(const FPoly& a,const FPoly& b) { FPoly prod; fterm *iptr,*pos; fterm *ptr=b.start; if (&a==&b) { // 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) { pos=prod.addterm(2*ptr->an*iptr->an,ptr->n+iptr->n,pos); iptr=iptr->next; } ptr=ptr->next; } } else while (ptr!=NULL) { FPoly t=a; t.multerm(ptr->an,ptr->n); ptr=ptr->next; prod+=t; } return prod; }
void class_poly(Complex& lam,Float *Fi2,Big A,Big B,Big C,Big D,BOOL conj,BOOL P1363) { Big ac,l,t; int i,j,k,g,e,m,n,dm8; Complex cinv; if (P1363) { g=1; if (D%3==0) g=3; ac=A*C; if (ac%2==1) { j=0; l=A-C+A*A*C; } if (C%2==0) j=1; if (A%2==0) j=2; if (A%2==0) { t=(C*C-1)/8; if (t%2==0) m=1; else m=-1; } else { t=(A*A-1)/8; if (t%2==0) m=1; else m=-1; } dm8=D%8; i=geti(D); k=getk(D); switch (dm8) { case 1: case 2: n=m; if (C%2==0) l=A+2*C-A*C*C; if (A%2==0) l=A-C-A*C*C; break; case 3: if (ac%2==1) n=1; else n=-m; if (C%2==0) l=A+2*C-A*C*C; if (A%2==0) l=A-C+5*A*C*C; break; case 5: n=1; if (C%2==0) l=A-C+A*A*C; if (A%2==0) l=A-C-A*C*C; break; case 6: n=m; if (C%2==0) l=A+2*C-A*C*C; if (A%2==0) l=A-C-A*C*C; break; case 7: if (ac%2==0) n=1; else n=m; if (C%2==0) l=A+2*C-A*C*C; if (A%2==0) l=A-C-A*C*C; break; default: break; } e=(k*B*l)%48; if (e<0) e+=48; cinv=pow(lam,e); cinv*=(n*Fi2[i]); cinv=pow(cinv*pow(F(j,A,B,C,D,0),k),g); } else { int N=getN(D); // adjust A and B if (N==2) { j=3; if (A%3!=0) { if (B%3!=0) { if ((B+A+A)%3!=0) B+=(4*A); else B+=(A+A); } } else { if (B%3!=0) { if (C%3!=0) { if ((C+B)%3!=0) B+=(4*A); else B+=(A+A); } } } A*=3; } else { j=4; if ((A%N)==0) { A=C; B=-B; } while (B%N!=0) B+=(A+A); A*=N; } cinv=F(j,A,B,C,D,N); } // multiply polynomial by new term(s) FPoly F; if (conj) { // conjugate pair // t^2-2a+(a^2+b^2) , where cinv=a+ib F.addterm((Float)1,2); F.addterm(-2*real(cinv),1); F.addterm(real(cinv)*real(cinv)+imaginary(cinv)*imaginary(cinv),0); } else { // t-cinv F.addterm((Float)1,1); F.addterm(-real(cinv),0); // store as a linear polynomial, or combine 2 to make a quadratic if (T[0].iszero()) { T[0]=F; return; } else { F=T[0]*F; // got a quadratic T[0].clear(); } } // accumulate Polynomial as 2^m degree components // This allows the use of karatsuba via the "special" function // This is the time critical bit.... for (i=1;;i++) { if (T[i].iszero()) { T[i]=F; // store this 2^i degree polynomial break; } else { F=special(T[i],F); // e.g. if i=1 two quadratics make a quartic.. T[i].clear(); } } }