ZZn4 sqrt(const ZZn4& 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)) // sqrt(a) = x.sqrt(a/n) // where x*x=n ZZn4 w; ZZn2 a,s,t; if (x.iszero()) return w; x.get(a,s); if (s.iszero()) { if (qr(a)) { s=sqrt(a); w.set(s,0); } else { s=sqrt(txd(a)); w.set(0,s); } return w; } s*=s; a*=a; a-=txx(s); s=sqrt(a); if (s.iszero()) return w; x.get(t); if (qr((ZZn2)((t+s)/2))) { a=sqrt((t+s)/2); } else { a=sqrt((t-s)/2); if (a.iszero()) return w; } x.geth(t); w.set(a,t/(2*a)); return w; }
ZZn2 imaginary(const ZZn4 &x) { ZZn2 i; x.geth(i); return i; }