boolean restrt,skip;
int i,its,j,n=x.length;
double den,fold,stpmax,sum,temp,test;
doubleW f = new doubleW(0);
double[] fvcold =new double[n],g=new double[n],p=new double[n],s=new double[n],t=new double[n],w=new double[n],xold=new double[n];
QRdcmp qr=null;
NRfmin fmin = new NRfmin(vecfunc);
NRfdjac fdjac = new NRfdjac(vecfunc);
f.val=fmin.funk(x); // XXX init fmin.fvec first.
double[] fvec=fmin.fvec;
test=0.0;
for (i=0;i<n;i++)
if (abs(fvec[i]) > test) test=abs(fvec[i]);
if (test < 0.01*TOLF) {
check.val=false;
return;
}
for (sum=0.0,i=0;i<n;i++) sum += SQR(x[i]);
stpmax=STPMX*max(sqrt(sum),n);
restrt=true;
for (its=1;its<=MAXITS;its++) {
if (restrt) {
qr=new QRdcmp(fdjac.get(x,fvec));
if (qr.sing) {
double[][] one = new double[n][n];
for (i=0;i<n;i++) one[i][i]=1.0;
qr=new QRdcmp(one);
}
} else {
for (i=0;i<n;i++) s[i]=x[i]-xold[i];
for (i=0;i<n;i++) {
for (sum=0.0,j=i;j<n;j++) sum += qr.r[i][j]*s[j];
t[i]=sum;
}
skip=true;
for (i=0;i<n;i++) {
for (sum=0.0,j=0;j<n;j++) sum += qr.qt[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;i<n;i++) den += SQR(s[i]);
for (i=0;i<n;i++) s[i] /= den;
qr.update(t,s);
if (qr.sing) throw new IllegalArgumentException("singular update in broydn");
}
}
qr.qtmult(fvec,p);
for (i=0;i<n;i++)
p[i] = -p[i];
for (i=n-1;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;i<n;i++) {
xold[i]=x[i];
fvcold[i]=fvec[i];
}
fold=f.val;
qr.rsolve(p,p);
double slope=0.0;
for (i=0;i<n;i++) slope += g[i]*p[i];
if (slope >= 0.0) {
restrt=true;
continue;