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; }
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; */ }