template void lnsrch(VecDoub_I &xold, const Doub fold, VecDoub_I &g, VecDoub_IO &p, VecDoub_O &x, Doub &f, const Doub stpmax, Bool &check, T &func) { const Doub ALF=1.0e-4, TOLX=numeric_limits::epsilon(); Doub a,alam,alam2=0.0,alamin,b,disc,f2=0.0; Doub rhs1,rhs2,slope=0.0,sum=0.0,temp,test,tmplam; Int i,n=xold.size(); check=false; for (i=0;i stpmax) for (i=0;i= 0.0) throw("Roundoff problem in lnsrch."); test=0.0; for (i=0;i test) test=temp; } alamin=TOLX/test; alam=1.0; for (;;) { for (i=0;i0.5*alam) tmplam=0.5*alam; } } alam2=alam; f2 = f; alam=MAX(tmplam,0.1*alam); } } template struct NRfdjac { const Doub EPS; T &func; NRfdjac(T &funcc) : EPS(1.0e-8),func(funcc) {} MatDoub operator() (VecDoub_I &x, VecDoub_I &fvec) { Int n=x.size(); MatDoub df(n,n); VecDoub xh=x; for (Int j=0;j struct NRfmin { VecDoub fvec; T &func; Int n; NRfmin(T &funcc) : func(funcc){} Doub operator() (VecDoub_I &x) { n=x.size(); Doub sum=0; fvec=func(x); for (Int i=0;i void newt(VecDoub_IO &x, Bool &check, T &vecfunc) { const Int MAXITS=200; const Doub TOLF=1.0e-8,TOLMIN=1.0e-12,STPMX=100.0; const Doub TOLX=numeric_limits::epsilon(); Int i,j,its,n=x.size(); Doub den,f,fold,stpmax,sum,temp,test; VecDoub g(n),p(n),xold(n); MatDoub fjac(n,n); NRfmin fmin(vecfunc); NRfdjac fdjac(vecfunc); VecDoub &fvec=fmin.fvec; f=fmin(x); test=0.0; for (i=0;i test) test=abs(fvec[i]); if (test < 0.01*TOLF) { check=false; return; } sum=0.0; for (i=0;i test) test=abs(fvec[i]); if (test < TOLF) { check=false; return; } if (check) { test=0.0; den=MAX(f,0.5*n); for (i=0;i test) test=temp; } check=(test < TOLMIN); return; } test=0.0; for (i=0;i test) test=temp; } if (test < TOLX) return; } throw("MAXITS exceeded in newt"); } template void broydn(VecDoub_IO &x, Bool &check, T &vecfunc) { const Int MAXITS=200; const Doub EPS=numeric_limits::epsilon(); const Doub TOLF=1.0e-8, TOLX=EPS, STPMX=100.0, TOLMIN=1.0e-12; Bool restrt,skip; Int i,its,j,n=x.size(); Doub den,f,fold,stpmax,sum,temp,test; VecDoub fvcold(n),g(n),p(n),s(n),t(n),w(n),xold(n); QRdcmp *qr; NRfmin fmin(vecfunc); NRfdjac fdjac(vecfunc); VecDoub &fvec=fmin.fvec; f=fmin(x); test=0.0; for (i=0;i test) test=abs(fvec[i]); if (test < 0.01*TOLF) { check=false; return; } for (sum=0.0,i=0;ising) { MatDoub one(n,n,0.0); for (i=0;ir[i][j]*s[j]; t[i]=sum; } skip=true; for (i=0;iqt[j][i]*t[j]; w[i]=fvec[i]-fvcold[i]-sum; if (abs(w[i]) >= EPS*(abs(fvec[i])+abs(fvcold[i]))) skip=false; else w[i]=0.0; } if (!skip) { qr->qtmult(w,t); for (den=0.0,i=0;iupdate(t,s); if (qr->sing) throw("singular update in broydn"); } } qr->qtmult(fvec,p); for (i=0;i=0;i--) { for (sum=0.0,j=0;j<=i;j++) sum -= qr->r[j][i]*p[j]; g[i]=sum; } for (i=0;irsolve(p,p); Doub slope=0.0; for (i=0;i= 0.0) { restrt=true; continue; } lnsrch(xold,fold,g,p,x,f,stpmax,check,fmin); test=0.0; for (i=0;i test) test=abs(fvec[i]); if (test < TOLF) { check=false; delete qr; return; } if (check) { if (restrt) { delete qr; return; } else { test=0.0; den=MAX(f,0.5*n); for (i=0;i test) test=temp; } if (test < TOLMIN) { delete qr; return; } else restrt=true; } } else { restrt=false; test=0.0; for (i=0;i test) test=temp; } if (test < TOLX) { delete qr; return; } } } throw("MAXITS exceeded in broydn"); }