ZZn8 txd(const ZZn8& x) { ZZn4 u,v; x.get(u,v); u=txd(u); ZZn8 w(v,u); return w; }
ZZn8 sqrt(const ZZn8& x) { // sqrt(a+xb) = sqrt(a+sqrt(a*a-n*b*b)/2)+x.b/(2*sqrt(a+sqrt(a*a-n*b*b)/2)) // where x*x=n ZZn8 w; ZZn4 a,s; if (x.iszero()) return w; if (x.b.iszero()) { a=x.a; if (qr(a)) { s=sqrt(a); w.a=s; w.b=0; } else { s=sqrt(txd(a)); w.a=0; w.b=s; } return w; } s=x.b; s*=s; a=x.a; a*=a; a-=tx(s); s=sqrt(a); if (s.iszero()) return w; if (qr((x.a+s)/2)) { a=sqrt((x.a+s)/2); } else { a=sqrt((x.a-s)/2); if (a.iszero()) return w; } w.a=a; w.b=x.b/(2*a); return w; }
ZZn8 line(ECn& A,ECn& C,ZZn& slope,ZZn4& Qx,ZZn4& Qy) { ZZn8 w; ZZn4 m=Qx; ZZn x,y,z,t; #ifdef AFFINE extract(A,x,y); m-=x; m*=slope; w.set((ZZn4)-y,Qy); w-=m; #endif #ifdef PROJECTIVE extract(A,x,y,z); x*=z; t=z; z*=z; z*=t; x*=slope; t=slope*z; m*=t; m-=x; t=z; extract(C,x,x,z); m+=(z*y); t*=z; w.set(m,-Qy*t); #endif return w; }
BOOL qr(const ZZn8& x) { ZZn4 a,s; int qnr=get_mip()->qnr; if (x.iszero()) return TRUE; if (x.b.iszero()) return TRUE; s=x.b; s*=s; a=x.a; a*=a; a-=tx(s); if (!qr(a)) return FALSE; return TRUE; /* s=sqrt(a); if (qr((x.a+s)/2) || qr((x.a-s)/2)) return TRUE; return FALSE; */ }