📄 lmder.c
字号:
/* and initialize the step bound delta. */
/*< do 70 j = 1, n >*/
i__1 = *n;
for (j = 1; j <= i__1; ++j) {
/*< wa3(j) = diag(j)*x(j) >*/
wa3[j] = diag[j] * x[j];
/*< 70 continue >*/
/* L70: */
}
/*< xnorm = enorm(n,wa3) >*/
xnorm = enorm_(n, &wa3[1]);
/*< delta = factor*xnorm >*/
delta = *factor * xnorm;
/*< if (delta .eq. zero) delta = factor >*/
if (delta == zero) {
delta = *factor;
}
/*< 80 continue >*/
L80:
/* form (q transpose)*fvec and store the first n components in */
/* qtf. */
/*< do 90 i = 1, m >*/
i__1 = *m;
for (i__ = 1; i__ <= i__1; ++i__) {
/*< wa4(i) = fvec(i) >*/
wa4[i__] = fvec[i__];
/*< 90 continue >*/
/* L90: */
}
/*< do 130 j = 1, n >*/
i__1 = *n;
for (j = 1; j <= i__1; ++j) {
/*< if (fjac(j,j) .eq. zero) go to 120 >*/
if (fjac[j + j * fjac_dim1] == zero) {
goto L120;
}
/*< sum = zero >*/
sum = zero;
/*< do 100 i = j, m >*/
i__2 = *m;
for (i__ = j; i__ <= i__2; ++i__) {
/*< sum = sum + fjac(i,j)*wa4(i) >*/
sum += fjac[i__ + j * fjac_dim1] * wa4[i__];
/*< 100 continue >*/
/* L100: */
}
/*< temp = -sum/fjac(j,j) >*/
temp = -sum / fjac[j + j * fjac_dim1];
/*< do 110 i = j, m >*/
i__2 = *m;
for (i__ = j; i__ <= i__2; ++i__) {
/*< wa4(i) = wa4(i) + fjac(i,j)*temp >*/
wa4[i__] += fjac[i__ + j * fjac_dim1] * temp;
/*< 110 continue >*/
/* L110: */
}
/*< 120 continue >*/
L120:
/*< fjac(j,j) = wa1(j) >*/
fjac[j + j * fjac_dim1] = wa1[j];
/*< qtf(j) = wa4(j) >*/
qtf[j] = wa4[j];
/*< 130 continue >*/
/* L130: */
}
/* compute the norm of the scaled gradient. */
/*< gnorm = zero >*/
gnorm = zero;
/*< if (fnorm .eq. zero) go to 170 >*/
if (fnorm == zero) {
goto L170;
}
/*< do 160 j = 1, n >*/
i__1 = *n;
for (j = 1; j <= i__1; ++j) {
/*< l = ipvt(j) >*/
l = ipvt[j];
/*< if (wa2(l) .eq. zero) go to 150 >*/
if (wa2[l] == zero) {
goto L150;
}
/*< sum = zero >*/
sum = zero;
/*< do 140 i = 1, j >*/
i__2 = j;
for (i__ = 1; i__ <= i__2; ++i__) {
/*< sum = sum + fjac(i,j)*(qtf(i)/fnorm) >*/
sum += fjac[i__ + j * fjac_dim1] * (qtf[i__] / fnorm);
/*< 140 continue >*/
/* L140: */
}
/*< gnorm = dmax1(gnorm,dabs(sum/wa2(l))) >*/
/* Computing MAX */
d__2 = gnorm, d__3 = (d__1 = sum / wa2[l], abs(d__1));
gnorm = max(d__2,d__3);
/*< 150 continue >*/
L150:
/*< 160 continue >*/
/* L160: */
;
}
/*< 170 continue >*/
L170:
/* test for convergence of the gradient norm. */
/*< if (gnorm .le. gtol) info = 4 >*/
if (gnorm <= *gtol) {
*info = 4;
}
/*< if (info .ne. 0) go to 300 >*/
if (*info != 0) {
goto L300;
}
/* rescale if necessary. */
/*< if (mode .eq. 2) go to 190 >*/
if (*mode == 2) {
goto L190;
}
/*< do 180 j = 1, n >*/
i__1 = *n;
for (j = 1; j <= i__1; ++j) {
/*< diag(j) = dmax1(diag(j),wa2(j)) >*/
/* Computing MAX */
d__1 = diag[j], d__2 = wa2[j];
diag[j] = max(d__1,d__2);
/*< 180 continue >*/
/* L180: */
}
/*< 190 continue >*/
L190:
/* beginning of the inner loop. */
/*< 200 continue >*/
L200:
/* determine the levenberg-marquardt parameter. */
/*< >*/
lmpar_(n, &fjac[fjac_offset], ldfjac, &ipvt[1], &diag[1], &qtf[1], &delta,
&par, &wa1[1], &wa2[1], &wa3[1], &wa4[1]);
/* store the direction p and x + p. calculate the norm of p. */
/*< do 210 j = 1, n >*/
i__1 = *n;
for (j = 1; j <= i__1; ++j) {
/*< wa1(j) = -wa1(j) >*/
wa1[j] = -wa1[j];
/*< wa2(j) = x(j) + wa1(j) >*/
wa2[j] = x[j] + wa1[j];
/*< wa3(j) = diag(j)*wa1(j) >*/
wa3[j] = diag[j] * wa1[j];
/*< 210 continue >*/
/* L210: */
}
/*< pnorm = enorm(n,wa3) >*/
pnorm = enorm_(n, &wa3[1]);
/* on the first iteration, adjust the initial step bound. */
/*< if (iter .eq. 1) delta = dmin1(delta,pnorm) >*/
if (iter == 1) {
delta = min(delta,pnorm);
}
/* evaluate the function at x + p and calculate its norm. */
/*< iflag = 1 >*/
iflag = 1;
/*< call fcn(m,n,wa2,wa4,fjac,ldfjac,iflag) >*/
(*fcn)(m, n, &wa2[1], &wa4[1], &fjac[fjac_offset], ldfjac, &iflag,
userdata);
/*< nfev = nfev + 1 >*/
++(*nfev);
/*< if (iflag .lt. 0) go to 300 >*/
if (iflag < 0) {
goto L300;
}
/*< fnorm1 = enorm(m,wa4) >*/
fnorm1 = enorm_(m, &wa4[1]);
/* compute the scaled actual reduction. */
/*< actred = -one >*/
actred = -one;
/*< if (p1*fnorm1 .lt. fnorm) actred = one - (fnorm1/fnorm)**2 >*/
if (p1 * fnorm1 < fnorm) {
/* Computing 2nd power */
d__1 = fnorm1 / fnorm;
actred = one - d__1 * d__1;
}
/* compute the scaled predicted reduction and */
/* the scaled directional derivative. */
/*< do 230 j = 1, n >*/
i__1 = *n;
for (j = 1; j <= i__1; ++j) {
/*< wa3(j) = zero >*/
wa3[j] = zero;
/*< l = ipvt(j) >*/
l = ipvt[j];
/*< temp = wa1(l) >*/
temp = wa1[l];
/*< do 220 i = 1, j >*/
i__2 = j;
for (i__ = 1; i__ <= i__2; ++i__) {
/*< wa3(i) = wa3(i) + fjac(i,j)*temp >*/
wa3[i__] += fjac[i__ + j * fjac_dim1] * temp;
/*< 220 continue >*/
/* L220: */
}
/*< 230 continue >*/
/* L230: */
}
/*< temp1 = enorm(n,wa3)/fnorm >*/
temp1 = enorm_(n, &wa3[1]) / fnorm;
/*< temp2 = (dsqrt(par)*pnorm)/fnorm >*/
temp2 = sqrt(par) * pnorm / fnorm;
/*< prered = temp1**2 + temp2**2/p5 >*/
/* Computing 2nd power */
d__1 = temp1;
/* Computing 2nd power */
d__2 = temp2;
prered = d__1 * d__1 + d__2 * d__2 / p5;
/*< dirder = -(temp1**2 + temp2**2) >*/
/* Computing 2nd power */
d__1 = temp1;
/* Computing 2nd power */
d__2 = temp2;
dirder = -(d__1 * d__1 + d__2 * d__2);
/* compute the ratio of the actual to the predicted */
/* reduction. */
/*< ratio = zero >*/
ratio = zero;
/*< if (prered .ne. zero) ratio = actred/prered >*/
if (prered != zero) {
ratio = actred / prered;
}
/* update the step bound. */
/*< if (ratio .gt. p25) go to 240 >*/
if (ratio > p25) {
goto L240;
}
/*< if (actred .ge. zero) temp = p5 >*/
if (actred >= zero) {
temp = p5;
}
/*< >*/
if (actred < zero) {
temp = p5 * dirder / (dirder + p5 * actred);
}
/*< if (p1*fnorm1 .ge. fnorm .or. temp .lt. p1) temp = p1 >*/
if (p1 * fnorm1 >= fnorm || temp < p1) {
temp = p1;
}
/*< delta = temp*dmin1(delta,pnorm/p1) >*/
/* Computing MIN */
d__1 = delta, d__2 = pnorm / p1;
delta = temp * min(d__1,d__2);
/*< par = par/temp >*/
par /= temp;
/*< go to 260 >*/
goto L260;
/*< 240 continue >*/
L240:
/*< if (par .ne. zero .and. ratio .lt. p75) go to 250 >*/
if (par != zero && ratio < p75) {
goto L250;
}
/*< delta = pnorm/p5 >*/
delta = pnorm / p5;
/*< par = p5*par >*/
par = p5 * par;
/*< 250 continue >*/
L250:
/*< 260 continue >*/
L260:
/* test for successful iteration. */
/*< if (ratio .lt. p0001) go to 290 >*/
if (ratio < p0001) {
goto L290;
}
/* successful iteration. update x, fvec, and their norms. */
/*< do 270 j = 1, n >*/
i__1 = *n;
for (j = 1; j <= i__1; ++j) {
/*< x(j) = wa2(j) >*/
x[j] = wa2[j];
/*< wa2(j) = diag(j)*x(j) >*/
wa2[j] = diag[j] * x[j];
/*< 270 continue >*/
/* L270: */
}
/*< do 280 i = 1, m >*/
i__1 = *m;
for (i__ = 1; i__ <= i__1; ++i__) {
/*< fvec(i) = wa4(i) >*/
fvec[i__] = wa4[i__];
/*< 280 continue >*/
/* L280: */
}
/*< xnorm = enorm(n,wa2) >*/
xnorm = enorm_(n, &wa2[1]);
/*< fnorm = fnorm1 >*/
fnorm = fnorm1;
/*< iter = iter + 1 >*/
++iter;
/*< 290 continue >*/
L290:
/* tests for convergence. */
/*< >*/
if (abs(actred) <= *ftol && prered <= *ftol && p5 * ratio <= one) {
*info = 1;
}
/*< if (delta .le. xtol*xnorm) info = 2 >*/
if (delta <= *xtol * xnorm) {
*info = 2;
}
/*< >*/
if (abs(actred) <= *ftol && prered <= *ftol && p5 * ratio <= one && *info
== 2) {
*info = 3;
}
/*< if (info .ne. 0) go to 300 >*/
if (*info != 0) {
goto L300;
}
/* tests for termination and stringent tolerances. */
/*< if (nfev .ge. maxfev) info = 5 >*/
if (*nfev >= *maxfev) {
*info = 5;
}
/*< >*/
if (abs(actred) <= epsmch && prered <= epsmch && p5 * ratio <= one) {
*info = 6;
}
/*< if (delta .le. epsmch*xnorm) info = 7 >*/
if (delta <= epsmch * xnorm) {
*info = 7;
}
/*< if (gnorm .le. epsmch) info = 8 >*/
if (gnorm <= epsmch) {
*info = 8;
}
/*< if (info .ne. 0) go to 300 >*/
if (*info != 0) {
goto L300;
}
/* end of the inner loop. repeat if iteration unsuccessful. */
/*< if (ratio .lt. p0001) go to 200 >*/
if (ratio < p0001) {
goto L200;
}
/* end of the outer loop. */
/*< go to 30 >*/
goto L30;
/*< 300 continue >*/
L300:
/* termination, either normal or user imposed. */
/*< if (iflag .lt. 0) info = iflag >*/
if (iflag < 0) {
*info = iflag;
}
/*< iflag = 0 >*/
iflag = 0;
/*< if (nprint .gt. 0) call fcn(m,n,x,fvec,fjac,ldfjac,iflag) >*/
if (*nprint > 0) {
(*fcn)(m, n, &x[1], &fvec[1], &fjac[fjac_offset], ldfjac, &iflag,
userdata);
}
/*< return >*/
return 0;
/* last card of subroutine lmder. */
/*< end >*/
} /* lmder_ */
#ifdef __cplusplus
}
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -