struct Linbcg { virtual void asolve(VecDoub_I &b, VecDoub_O &x, const Int itrnsp) = 0; virtual void atimes(VecDoub_I &x, VecDoub_O &r, const Int itrnsp) = 0; void solve(VecDoub_I &b, VecDoub_IO &x, const Int itol, const Doub tol, const Int itmax, Int &iter, Doub &err); Doub snrm(VecDoub_I &sx, const Int itol); }; void Linbcg::solve(VecDoub_I &b, VecDoub_IO &x, const Int itol, const Doub tol, const Int itmax, Int &iter, Doub &err) { Doub ak,akden,bk,bkden=1.0,bknum,bnrm,dxnrm,xnrm,zm1nrm,znrm; const Doub EPS=1.0e-14; Int j,n=b.size(); VecDoub p(n),pp(n),r(n),rr(n),z(n),zz(n); iter=0; atimes(x,r,0); for (j=0;j EPS*znrm) { dxnrm=abs(ak)*snrm(p,itol); err=znrm/abs(zm1nrm-znrm)*dxnrm; } else { err=znrm/bnrm; continue; } xnrm=snrm(x,itol); if (err <= 0.5*xnrm) err /= xnrm; else { err=znrm/bnrm; continue; } } if (err <= tol) break; } } Doub Linbcg::snrm(VecDoub_I &sx, const Int itol) { Int i,isamax,n=sx.size(); Doub ans; if (itol <= 3) { ans = 0.0; for (i=0;i abs(sx[isamax])) isamax=i; } return abs(sx[isamax]); } }