/* * Grace - Graphics for Exploratory Data Analysis * * Home page: http://plasma-gate.weizmann.ac.il/Grace/ * * Copyright (c) 1991-95 Paul J Turner, Portland, OR * Copyright (c) 1996-98 GRACE Development Team * * Maintained by Evgeny Stambulchik * * * All Rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* -- translated by f2c (version 19960717). */ #include #include #include "f2c.h" /* Table of constant values */ static integer c__1 = 1; static logical c_true = TRUE_; static integer c__2 = 2; /* Subroutine */ int qrfac_(integer *m, integer *n, doublereal *a, integer * lda, logical *pivot, integer *ipvt, integer *lipvt, doublereal *rdiag, doublereal *acnorm, doublereal *wa); /* Subroutine */ int lmpar_(integer *n, doublereal *r__, integer *ldr, integer *ipvt, doublereal *diag, doublereal *qtb, doublereal *delta, doublereal *par, doublereal *x, doublereal *sdiag, doublereal *wa1, doublereal *wa2); /* Subroutine */ int qrsolv_(integer *n, doublereal *r__, integer *ldr, integer *ipvt, doublereal *diag, doublereal *qtb, doublereal *x, doublereal *sdiag, doublereal *wa); doublereal dpmpar_(integer *i) { switch ((int) *i) { case 1: return (doublereal) MACHEP; break; case 2: return (doublereal) UFLOWTHRESH; break; case 3: return (doublereal) MAXNUM; break; default: return (doublereal) 0; } } doublereal enorm_(integer *n, doublereal *x) { /* Initialized data */ static doublereal one = 1.; static doublereal zero = 0.; static doublereal rdwarf = 3.834e-20; static doublereal rgiant = 1.304e19; /* System generated locals */ integer i__1; doublereal ret_val = 0.0, d__1; /* Local variables */ static integer i__; static doublereal s1, s2, s3, xabs, x1max, x3max, agiant, floatn; /* ********** */ /* function enorm */ /* given an n-vector x, this function calculates the */ /* euclidean norm of x. */ /* the euclidean norm is computed by accumulating the sum of */ /* squares in three different sums. the sums of squares for the */ /* small and large components are scaled so that no overflows */ /* occur. non-destructive underflows are permitted. underflows */ /* and overflows do not occur in the computation of the unscaled */ /* sum of squares for the intermediate components. */ /* the definitions of small, intermediate and large components */ /* depend on two constants, rdwarf and rgiant. the main */ /* restrictions on these constants are that rdwarf**2 not */ /* underflow and rgiant**2 not overflow. the constants */ /* given here are suitable for every known computer. */ /* the function statement is */ /* double precision function enorm(n,x) */ /* where */ /* n is a positive integer input variable. */ /* x is an input array of length n. */ /* subprograms called */ /* fortran-supplied ... dabs,dsqrt */ /* argonne national laboratory. minpack project. march 1980. */ /* burton s. garbow, kenneth e. hillstrom, jorge j. more */ /* ********** */ /* Parameter adjustments */ --x; /* Function Body */ s1 = zero; s2 = zero; s3 = zero; x1max = zero; x3max = zero; floatn = (doublereal) (*n); agiant = rgiant / floatn; i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { xabs = (d__1 = x[i__], abs(d__1)); if (xabs > rdwarf && xabs < agiant) { goto L70; } if (xabs <= rdwarf) { goto L30; } /* sum for large components. */ if (xabs <= x1max) { goto L10; } /* Computing 2nd power */ d__1 = x1max / xabs; s1 = one + s1 * (d__1 * d__1); x1max = xabs; goto L20; L10: /* Computing 2nd power */ d__1 = xabs / x1max; s1 += d__1 * d__1; L20: goto L60; L30: /* sum for small components. */ if (xabs <= x3max) { goto L40; } /* Computing 2nd power */ d__1 = x3max / xabs; s3 = one + s3 * (d__1 * d__1); x3max = xabs; goto L50; L40: if (xabs != zero) { /* Computing 2nd power */ d__1 = xabs / x3max; s3 += d__1 * d__1; } L50: L60: goto L80; L70: /* sum for intermediate components. */ /* Computing 2nd power */ d__1 = xabs; s2 += d__1 * d__1; L80: /* L90: */ ; } /* calculation of norm. */ if (s1 == zero) { goto L100; } ret_val = x1max * sqrt(s1 + s2 / x1max / x1max); goto L130; L100: if (s2 == zero) { goto L110; } if (s2 >= x3max) { ret_val = sqrt(s2 * (one + x3max / s2 * (x3max * s3))); } if (s2 < x3max) { ret_val = sqrt(x3max * (s2 / x3max + x3max * s3)); } goto L120; L110: ret_val = x3max * sqrt(s3); L120: L130: return ret_val; /* last card of function enorm. */ } /* enorm_ */ /* Subroutine */ int fdjac2_(S_fp fcn, integer *m, integer *n, doublereal *x, doublereal *fvec, doublereal *fjac, integer *ldfjac, integer *iflag, doublereal *epsfcn, doublereal *wa) { /* Initialized data */ static doublereal zero = 0.; /* System generated locals */ integer fjac_dim1, fjac_offset, i__1, i__2; /* Local variables */ static doublereal h__; static integer i__, j; static doublereal eps, temp, epsmch; /* ********** */ /* subroutine fdjac2 */ /* this subroutine computes a forward-difference approximation */ /* to the m by n jacobian matrix associated with a specified */ /* problem of m functions in n variables. */ /* the subroutine statement is */ /* subroutine fdjac2(fcn,m,n,x,fvec,fjac,ldfjac,iflag,epsfcn,wa) */ /* where */ /* fcn is the name of the user-supplied subroutine which */ /* calculates the functions. fcn must be declared */ /* in an external statement in the user calling */ /* program, and should be written as follows. */ /* subroutine fcn(m,n,x,fvec,iflag) */ /* integer m,n,iflag */ /* double precision x(n),fvec(m) */ /* ---------- */ /* calculate the functions at x and */ /* return this vector in fvec. */ /* ---------- */ /* return */ /* end */ /* the value of iflag should not be changed by fcn unless */ /* the user wants to terminate execution of fdjac2. */ /* in this case set iflag to a negative integer. */ /* m is a positive integer input variable set to the number */ /* of functions. */ /* n is a positive integer input variable set to the number */ /* of variables. n must not exceed m. */ /* x is an input array of length n. */ /* fvec is an input array of length m which must contain the */ /* functions evaluated at x. */ /* fjac is an output m by n array which contains the */ /* approximation to the jacobian matrix evaluated at x. */ /* ldfjac is a positive integer input variable not less than m */ /* which specifies the leading dimension of the array fjac. */ /* iflag is an integer variable which can be used to terminate */ /* the execution of fdjac2. see description of fcn. */ /* epsfcn is an input variable used in determining a suitable */ /* step length for the forward-difference approximation. this */ /* approximation assumes that the relative errors in the */ /* functions are of the order of epsfcn. if epsfcn is less */ /* than the machine precision, it is assumed that the relative */ /* errors in the functions are of the order of the machine */ /* precision. */ /* wa is a work array of length m. */ /* subprograms called */ /* user-supplied ...... fcn */ /* minpack-supplied ... dpmpar */ /* fortran-supplied ... dabs,dmax1,dsqrt */ /* argonne national laboratory. minpack project. march 1980. */ /* burton s. garbow, kenneth e. hillstrom, jorge j. more */ /* ********** */ /* Parameter adjustments */ --wa; --fvec; --x; fjac_dim1 = *ldfjac; fjac_offset = fjac_dim1 + 1; fjac -= fjac_offset; /* Function Body */ /* epsmch is the machine precision. */ epsmch = dpmpar_(&c__1); eps = sqrt((max(*epsfcn,epsmch))); i__1 = *n; for (j = 1; j <= i__1; ++j) { temp = x[j]; h__ = eps * abs(temp); if (h__ == zero) { h__ = eps; } x[j] = temp + h__; (*fcn)(m, n, &x[1], &wa[1], iflag); if (*iflag < 0) { goto L30; } x[j] = temp; i__2 = *m; for (i__ = 1; i__ <= i__2; ++i__) { fjac[i__ + j * fjac_dim1] = (wa[i__] - fvec[i__]) / h__; /* L10: */ } /* L20: */ } L30: return 0; /* last card of subroutine fdjac2. */ } /* fdjac2_ */ /* Subroutine */ int lmdif_(S_fp fcn, integer *m, integer *n, doublereal *x, doublereal *fvec, doublereal *ftol, doublereal *xtol, doublereal * gtol, integer *maxfev, doublereal *epsfcn, doublereal *diag, integer * mode, doublereal *factor, integer *nprint, integer *info, integer * nfev, doublereal *fjac, integer *ldfjac, integer *ipvt, doublereal * qtf, doublereal *wa1, doublereal *wa2, doublereal *wa3, doublereal * wa4) { /* Initialized data */ static doublereal one = 1.; static doublereal p1 = .1; static doublereal p5 = .5; static doublereal p25 = .25; static doublereal p75 = .75; static doublereal p0001 = 1e-4; static doublereal zero = 0.; /* System generated locals */ integer fjac_dim1, fjac_offset, i__1, i__2; doublereal d__1, d__2, d__3; /* Local variables */ static integer i__, j, l; static doublereal par, sum; static integer iter; static doublereal temp, temp1, temp2; static integer iflag; static doublereal delta; static doublereal ratio; static doublereal fnorm, gnorm; static doublereal pnorm, xnorm, fnorm1, actred, dirder, epsmch, prered; /* ********** */ /* subroutine lmdif */ /* the purpose of lmdif is to minimize the sum of the squares of */ /* m nonlinear functions in n variables by a modification of */ /* the levenberg-marquardt algorithm. the user must provide a */ /* subroutine which calculates the functions. the jacobian is */ /* then calculated by a forward-difference approximation. */ /* the subroutine statement is */ /* subroutine lmdif(fcn,m,n,x,fvec,ftol,xtol,gtol,maxfev,epsfcn, */ /* diag,mode,factor,nprint,info,nfev,fjac, */ /* ldfjac,ipvt,qtf,wa1,wa2,wa3,wa4) */ /* where */ /* fcn is the name of the user-supplied subroutine which */ /* calculates the functions. fcn must be declared */ /* in an external statement in the user calling */ /* program, and should be written as follows. */ /* subroutine fcn(m,n,x,fvec,iflag) */ /* integer m,n,iflag */ /* double precision x(n),fvec(m) */ /* ---------- */ /* calculate the functions at x and */ /* return this vector in fvec. */ /* ---------- */ /* return */ /* end */ /* the value of iflag should not be changed by fcn unless */ /* the user wants to terminate execution of lmdif. */ /* in this case set iflag to a negative integer. */ /* m is a positive integer input variable set to the number */ /* of functions. */ /* n is a positive integer input variable set to the number */ /* of variables. n must not exceed m. */ /* x is an array of length n. on input x must contain */ /* an initial estimate of the solution vector. on output x */ /* contains the final estimate of the solution vector. */ /* fvec is an output array of length m which contains */ /* the functions evaluated at the output x. */ /* ftol is a nonnegative input variable. termination */ /* occurs when both the actual and predicted relative */ /* reductions in the sum of squares are at most ftol. */ /* therefore, ftol measures the relative error desired */ /* in the sum of squares. */ /* xtol is a nonnegative input variable. termination */ /* occurs when the relative error between two consecutive */ /* iterates is at most xtol. therefore, xtol measures the */ /* relative error desired in the approximate solution. */ /* gtol is a nonnegative input variable. termination */ /* occurs when the cosine of the angle between fvec and */ /* any column of the jacobian is at most gtol in absolute */ /* value. therefore, gtol measures the orthogonality */ /* desired between the function vector and the columns */ /* of the jacobian. */ /* maxfev is a positive integer input variable. termination */ /* occurs when the number of calls to fcn is at least */ /* maxfev by the end of an iteration. */ /* epsfcn is an input variable used in determining a suitable */ /* step length for the forward-difference approximation. this */ /* approximation assumes that the relative errors in the */ /* functions are of the order of epsfcn. if epsfcn is less */ /* than the machine precision, it is assumed that the relative */ /* errors in the functions are of the order of the machine */ /* precision. */ /* diag is an array of length n. if mode = 1 (see */ /* below), diag is internally set. if mode = 2, diag */ /* must contain positive entries that serve as */ /* multiplicative scale factors for the variables. */ /* mode is an integer input variable. if mode = 1, the */ /* variables will be scaled internally. if mode = 2, */ /* the scaling is specified by the input diag. other */ /* values of mode are equivalent to mode = 1. */ /* factor is a positive input variable used in determining the */ /* initial step bound. this bound is set to the product of */ /* factor and the euclidean norm of diag*x if nonzero, or else */ /* to factor itself. in most cases factor should lie in the */ /* interval (.1,100.). 100. is a generally recommended value. */ /* nprint is an integer input variable that enables controlled */ /* printing of iterates if it is positive. in this case, */ /* fcn is called with iflag = 0 at the beginning of the first */ /* iteration and every nprint iterations thereafter and */ /* immediately prior to return, with x and fvec available */ /* for printing. if nprint is not positive, no special calls */ /* of fcn with iflag = 0 are made. */ /* info is an integer output variable. if the user has */ /* terminated execution, info is set to the (negative) */ /* value of iflag. see description of fcn. otherwise, */ /* info is set as follows. */ /* info = 0 improper input parameters. */ /* info = 1 both actual and predicted relative reductions */ /* in the sum of squares are at most ftol. */ /* info = 2 relative error between two consecutive iterates */ /* is at most xtol. */ /* info = 3 conditions for info = 1 and info = 2 both hold. */ /* info = 4 the cosine of the angle between fvec and any */ /* column of the jacobian is at most gtol in */ /* absolute value. */ /* info = 5 number of calls to fcn has reached or */ /* exceeded maxfev. */ /* info = 6 ftol is too small. no further reduction in */ /* the sum of squares is possible. */ /* info = 7 xtol is too small. no further improvement in */ /* the approximate solution x is possible. */ /* info = 8 gtol is too small. fvec is orthogonal to the */ /* columns of the jacobian to machine precision. */ /* nfev is an integer output variable set to the number of */ /* calls to fcn. */ /* fjac is an output m by n array. the upper n by n submatrix */ /* of fjac contains an upper triangular matrix r with */ /* diagonal elements of nonincreasing magnitude such that */ /* t t t */ /* p *(jac *jac)*p = r *r, */ /* where p is a permutation matrix and jac is the final */ /* calculated jacobian. column j of p is column ipvt(j) */ /* (see below) of the identity matrix. the lower trapezoidal */ /* part of fjac contains information generated during */ /* the computation of r. */ /* ldfjac is a positive integer input variable not less than m */ /* which specifies the leading dimension of the array fjac. */ /* ipvt is an integer output array of length n. ipvt */ /* defines a permutation matrix p such that jac*p = q*r, */ /* where jac is the final calculated jacobian, q is */ /* orthogonal (not stored), and r is upper triangular */ /* with diagonal elements of nonincreasing magnitude. */ /* column j of p is column ipvt(j) of the identity matrix. */ /* qtf is an output array of length n which contains */ /* the first n elements of the vector (q transpose)*fvec. */ /* wa1, wa2, and wa3 are work arrays of length n. */ /* wa4 is a work array of length m. */ /* subprograms called */ /* user-supplied ...... fcn */ /* minpack-supplied ... dpmpar,enorm,fdjac2,lmpar,qrfac */ /* fortran-supplied ... dabs,dmax1,dmin1,dsqrt,mod */ /* argonne national laboratory. minpack project. march 1980. */ /* burton s. garbow, kenneth e. hillstrom, jorge j. more */ /* ********** */ /* Parameter adjustments */ --wa4; --fvec; --wa3; --wa2; --wa1; --qtf; --ipvt; --diag; --x; fjac_dim1 = *ldfjac; fjac_offset = fjac_dim1 + 1; fjac -= fjac_offset; /* Function Body */ /* epsmch is the machine precision. */ epsmch = dpmpar_(&c__1); *info = 0; iflag = 0; *nfev = 0; /* check the input parameters for errors. */ if (*n <= 0 || *m < *n || *ldfjac < *m || *ftol < zero || *xtol < zero || *gtol < zero || *maxfev <= 0 || *factor <= zero) { goto L300; } if (*mode != 2) { goto L20; } i__1 = *n; for (j = 1; j <= i__1; ++j) { if (diag[j] <= zero) { goto L300; } /* L10: */ } L20: /* evaluate the function at the starting point */ /* and calculate its norm. */ iflag = 1; (*fcn)(m, n, &x[1], &fvec[1], &iflag); *nfev = 1; if (iflag < 0) { goto L300; } fnorm = enorm_(m, &fvec[1]); /* initialize levenberg-marquardt parameter and iteration counter. */ par = zero; iter = 1; /* beginning of the outer loop. */ L30: /* calculate the jacobian matrix. */ iflag = 2; fdjac2_((S_fp)fcn, m, n, &x[1], &fvec[1], &fjac[fjac_offset], ldfjac, & iflag, epsfcn, &wa4[1]); *nfev += *n; if (iflag < 0) { goto L300; } /* if requested, call fcn to enable printing of iterates. */ if (*nprint <= 0) { goto L40; } iflag = 0; if ((iter - 1) % *nprint == 0) { (*fcn)(m, n, &x[1], &fvec[1], &iflag); } if (iflag < 0) { goto L300; } L40: /* compute the qr factorization of the jacobian. */ qrfac_(m, n, &fjac[fjac_offset], ldfjac, &c_true, &ipvt[1], n, &wa1[1], & wa2[1], &wa3[1]); /* on the first iteration and if mode is 1, scale according */ /* to the norms of the columns of the initial jacobian. */ if (iter != 1) { goto L80; } if (*mode == 2) { goto L60; } i__1 = *n; for (j = 1; j <= i__1; ++j) { diag[j] = wa2[j]; if (wa2[j] == zero) { diag[j] = one; } /* L50: */ } L60: /* on the first iteration, calculate the norm of the scaled x */ /* and initialize the step bound delta. */ i__1 = *n; for (j = 1; j <= i__1; ++j) { wa3[j] = diag[j] * x[j]; /* L70: */ } xnorm = enorm_(n, &wa3[1]); delta = *factor * xnorm; if (delta == zero) { delta = *factor; } L80: /* form (q transpose)*fvec and store the first n components in */ /* qtf. */ i__1 = *m; for (i__ = 1; i__ <= i__1; ++i__) { wa4[i__] = fvec[i__]; /* L90: */ } i__1 = *n; for (j = 1; j <= i__1; ++j) { if (fjac[j + j * fjac_dim1] == zero) { goto L120; } sum = zero; i__2 = *m; for (i__ = j; i__ <= i__2; ++i__) { sum += fjac[i__ + j * fjac_dim1] * wa4[i__]; /* L100: */ } temp = -sum / fjac[j + j * fjac_dim1]; i__2 = *m; for (i__ = j; i__ <= i__2; ++i__) { wa4[i__] += fjac[i__ + j * fjac_dim1] * temp; /* L110: */ } L120: fjac[j + j * fjac_dim1] = wa1[j]; qtf[j] = wa4[j]; /* L130: */ } /* compute the norm of the scaled gradient. */ gnorm = zero; if (fnorm == zero) { goto L170; } i__1 = *n; for (j = 1; j <= i__1; ++j) { l = ipvt[j]; if (wa2[l] == zero) { goto L150; } sum = zero; i__2 = j; for (i__ = 1; i__ <= i__2; ++i__) { sum += fjac[i__ + j * fjac_dim1] * (qtf[i__] / fnorm); /* L140: */ } /* Computing MAX */ d__2 = gnorm, d__3 = (d__1 = sum / wa2[l], abs(d__1)); gnorm = max(d__2,d__3); L150: /* L160: */ ; } L170: /* test for convergence of the gradient norm. */ if (gnorm <= *gtol) { *info = 4; } if (*info != 0) { goto L300; } /* rescale if necessary. */ if (*mode == 2) { goto L190; } i__1 = *n; for (j = 1; j <= i__1; ++j) { /* Computing MAX */ d__1 = diag[j], d__2 = wa2[j]; diag[j] = max(d__1,d__2); /* L180: */ } L190: /* beginning of the inner loop. */ 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. */ i__1 = *n; for (j = 1; j <= i__1; ++j) { wa1[j] = -wa1[j]; wa2[j] = x[j] + wa1[j]; wa3[j] = diag[j] * wa1[j]; /* L210: */ } pnorm = enorm_(n, &wa3[1]); /* on the first iteration, adjust the initial step bound. */ if (iter == 1) { delta = min(delta,pnorm); } /* evaluate the function at x + p and calculate its norm. */ iflag = 1; (*fcn)(m, n, &wa2[1], &wa4[1], &iflag); ++(*nfev); if (iflag < 0) { goto L300; } fnorm1 = enorm_(m, &wa4[1]); /* compute the scaled actual reduction. */ actred = -one; 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. */ i__1 = *n; for (j = 1; j <= i__1; ++j) { wa3[j] = zero; l = ipvt[j]; temp = wa1[l]; i__2 = j; for (i__ = 1; i__ <= i__2; ++i__) { wa3[i__] += fjac[i__ + j * fjac_dim1] * temp; /* L220: */ } /* L230: */ } temp1 = enorm_(n, &wa3[1]) / fnorm; temp2 = sqrt(par) * pnorm / fnorm; /* Computing 2nd power */ d__1 = temp1; /* Computing 2nd power */ d__2 = temp2; prered = d__1 * d__1 + d__2 * d__2 / p5; /* 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; if (prered != zero) { ratio = actred / prered; } /* update the step bound. */ if (ratio > p25) { goto L240; } if (actred >= zero) { temp = p5; } if (actred < zero) { temp = p5 * dirder / (dirder + p5 * actred); } if (p1 * fnorm1 >= fnorm || temp < p1) { temp = p1; } /* Computing MIN */ d__1 = delta, d__2 = pnorm / p1; delta = temp * min(d__1,d__2); par /= temp; goto L260; L240: if (par != zero && ratio < p75) { goto L250; } delta = pnorm / p5; par = p5 * par; L250: L260: /* test for successful iteration. */ if (ratio < p0001) { goto L290; } /* successful iteration. update x, fvec, and their norms. */ i__1 = *n; for (j = 1; j <= i__1; ++j) { x[j] = wa2[j]; wa2[j] = diag[j] * x[j]; /* L270: */ } i__1 = *m; for (i__ = 1; i__ <= i__1; ++i__) { fvec[i__] = wa4[i__]; /* L280: */ } xnorm = enorm_(n, &wa2[1]); fnorm = fnorm1; ++iter; L290: /* tests for convergence. */ if (abs(actred) <= *ftol && prered <= *ftol && p5 * ratio <= one) { *info = 1; } if (delta <= *xtol * xnorm) { *info = 2; } if (abs(actred) <= *ftol && prered <= *ftol && p5 * ratio <= one && *info == 2) { *info = 3; } if (*info != 0) { goto L300; } /* tests for termination and stringent tolerances. */ if (*nfev >= *maxfev) { *info = 5; } if (abs(actred) <= epsmch && prered <= epsmch && p5 * ratio <= one) { *info = 6; } if (delta <= epsmch * xnorm) { *info = 7; } if (gnorm <= epsmch) { *info = 8; } if (*info != 0) { goto L300; } /* end of the inner loop. repeat if iteration unsuccessful. */ if (ratio < p0001) { goto L200; } /* end of the outer loop. */ goto L30; L300: /* termination, either normal or user imposed. */ if (iflag < 0) { *info = iflag; } iflag = 0; if (*nprint > 0) { (*fcn)(m, n, &x[1], &fvec[1], &iflag); } return 0; /* last card of subroutine lmdif. */ } /* lmdif_ */ /* Subroutine */ int lmpar_(integer *n, doublereal *r__, integer *ldr, integer *ipvt, doublereal *diag, doublereal *qtb, doublereal *delta, doublereal *par, doublereal *x, doublereal *sdiag, doublereal *wa1, doublereal *wa2) { /* Initialized data */ static doublereal p1 = .1; static doublereal p001 = .001; static doublereal zero = 0.; /* System generated locals */ integer r_dim1, r_offset, i__1, i__2; doublereal d__1, d__2; /* Local variables */ static integer i__, j, k, l; static doublereal fp; static integer jm1, jp1; static doublereal sum, parc, parl; static integer iter; static doublereal temp, paru, dwarf; static integer nsing; static doublereal gnorm; static doublereal dxnorm; /* ********** */ /* subroutine lmpar */ /* given an m by n matrix a, an n by n nonsingular diagonal */ /* matrix d, an m-vector b, and a positive number delta, */ /* the problem is to determine a value for the parameter */ /* par such that if x solves the system */ /* a*x = b , sqrt(par)*d*x = 0 , */ /* in the least squares sense, and dxnorm is the euclidean */ /* norm of d*x, then either par is zero and */ /* (dxnorm-delta) .le. 0.1*delta , */ /* or par is positive and */ /* abs(dxnorm-delta) .le. 0.1*delta . */ /* this subroutine completes the solution of the problem */ /* if it is provided with the necessary information from the */ /* qr factorization, with column pivoting, of a. that is, if */ /* a*p = q*r, where p is a permutation matrix, q has orthogonal */ /* columns, and r is an upper triangular matrix with diagonal */ /* elements of nonincreasing magnitude, then lmpar expects */ /* the full upper triangle of r, the permutation matrix p, */ /* and the first n components of (q transpose)*b. on output */ /* lmpar also provides an upper triangular matrix s such that */ /* t t t */ /* p *(a *a + par*d*d)*p = s *s . */ /* s is employed within lmpar and may be of separate interest. */ /* only a few iterations are generally needed for convergence */ /* of the algorithm. if, however, the limit of 10 iterations */ /* is reached, then the output par will contain the best */ /* value obtained so far. */ /* the subroutine statement is */ /* subroutine lmpar(n,r,ldr,ipvt,diag,qtb,delta,par,x,sdiag, */ /* wa1,wa2) */ /* where */ /* n is a positive integer input variable set to the order of r. */ /* r is an n by n array. on input the full upper triangle */ /* must contain the full upper triangle of the matrix r. */ /* on output the full upper triangle is unaltered, and the */ /* strict lower triangle contains the strict upper triangle */ /* (transposed) of the upper triangular matrix s. */ /* ldr is a positive integer input variable not less than n */ /* which specifies the leading dimension of the array r. */ /* ipvt is an integer input array of length n which defines the */ /* permutation matrix p such that a*p = q*r. column j of p */ /* is column ipvt(j) of the identity matrix. */ /* diag is an input array of length n which must contain the */ /* diagonal elements of the matrix d. */ /* qtb is an input array of length n which must contain the first */ /* n elements of the vector (q transpose)*b. */ /* delta is a positive input variable which specifies an upper */ /* bound on the euclidean norm of d*x. */ /* par is a nonnegative variable. on input par contains an */ /* initial estimate of the levenberg-marquardt parameter. */ /* on output par contains the final estimate. */ /* x is an output array of length n which contains the least */ /* squares solution of the system a*x = b, sqrt(par)*d*x = 0, */ /* for the output par. */ /* sdiag is an output array of length n which contains the */ /* diagonal elements of the upper triangular matrix s. */ /* wa1 and wa2 are work arrays of length n. */ /* subprograms called */ /* minpack-supplied ... dpmpar,enorm,qrsolv */ /* fortran-supplied ... dabs,dmax1,dmin1,dsqrt */ /* argonne national laboratory. minpack project. march 1980. */ /* burton s. garbow, kenneth e. hillstrom, jorge j. more */ /* ********** */ /* Parameter adjustments */ --wa2; --wa1; --sdiag; --x; --qtb; --diag; --ipvt; r_dim1 = *ldr; r_offset = r_dim1 + 1; r__ -= r_offset; /* Function Body */ /* dwarf is the smallest positive magnitude. */ dwarf = dpmpar_(&c__2); /* compute and store in x the gauss-newton direction. if the */ /* jacobian is rank-deficient, obtain a least squares solution. */ nsing = *n; i__1 = *n; for (j = 1; j <= i__1; ++j) { wa1[j] = qtb[j]; if (r__[j + j * r_dim1] == zero && nsing == *n) { nsing = j - 1; } if (nsing < *n) { wa1[j] = zero; } /* L10: */ } if (nsing < 1) { goto L50; } i__1 = nsing; for (k = 1; k <= i__1; ++k) { j = nsing - k + 1; wa1[j] /= r__[j + j * r_dim1]; temp = wa1[j]; jm1 = j - 1; if (jm1 < 1) { goto L30; } i__2 = jm1; for (i__ = 1; i__ <= i__2; ++i__) { wa1[i__] -= r__[i__ + j * r_dim1] * temp; /* L20: */ } L30: /* L40: */ ; } L50: i__1 = *n; for (j = 1; j <= i__1; ++j) { l = ipvt[j]; x[l] = wa1[j]; /* L60: */ } /* initialize the iteration counter. */ /* evaluate the function at the origin, and test */ /* for acceptance of the gauss-newton direction. */ iter = 0; i__1 = *n; for (j = 1; j <= i__1; ++j) { wa2[j] = diag[j] * x[j]; /* L70: */ } dxnorm = enorm_(n, &wa2[1]); fp = dxnorm - *delta; if (fp <= p1 * *delta) { goto L220; } /* if the jacobian is not rank deficient, the newton */ /* step provides a lower bound, parl, for the zero of */ /* the function. otherwise set this bound to zero. */ parl = zero; if (nsing < *n) { goto L120; } i__1 = *n; for (j = 1; j <= i__1; ++j) { l = ipvt[j]; wa1[j] = diag[l] * (wa2[l] / dxnorm); /* L80: */ } i__1 = *n; for (j = 1; j <= i__1; ++j) { sum = zero; jm1 = j - 1; if (jm1 < 1) { goto L100; } i__2 = jm1; for (i__ = 1; i__ <= i__2; ++i__) { sum += r__[i__ + j * r_dim1] * wa1[i__]; /* L90: */ } L100: wa1[j] = (wa1[j] - sum) / r__[j + j * r_dim1]; /* L110: */ } temp = enorm_(n, &wa1[1]); parl = fp / *delta / temp / temp; L120: /* calculate an upper bound, paru, for the zero of the function. */ i__1 = *n; for (j = 1; j <= i__1; ++j) { sum = zero; i__2 = j; for (i__ = 1; i__ <= i__2; ++i__) { sum += r__[i__ + j * r_dim1] * qtb[i__]; /* L130: */ } l = ipvt[j]; wa1[j] = sum / diag[l]; /* L140: */ } gnorm = enorm_(n, &wa1[1]); paru = gnorm / *delta; if (paru == zero) { paru = dwarf / min(*delta,p1); } /* if the input par lies outside of the interval (parl,paru), */ /* set par to the closer endpoint. */ *par = max(*par,parl); *par = min(*par,paru); if (*par == zero) { *par = gnorm / dxnorm; } /* beginning of an iteration. */ L150: ++iter; /* evaluate the function at the current value of par. */ if (*par == zero) { /* Computing MAX */ d__1 = dwarf, d__2 = p001 * paru; *par = max(d__1,d__2); } temp = sqrt(*par); i__1 = *n; for (j = 1; j <= i__1; ++j) { wa1[j] = temp * diag[j]; /* L160: */ } qrsolv_(n, &r__[r_offset], ldr, &ipvt[1], &wa1[1], &qtb[1], &x[1], &sdiag[ 1], &wa2[1]); i__1 = *n; for (j = 1; j <= i__1; ++j) { wa2[j] = diag[j] * x[j]; /* L170: */ } dxnorm = enorm_(n, &wa2[1]); temp = fp; fp = dxnorm - *delta; /* if the function is small enough, accept the current value */ /* of par. also test for the exceptional cases where parl */ /* is zero or the number of iterations has reached 10. */ if (abs(fp) <= p1 * *delta || (parl == zero && fp <= temp && temp < zero) || iter == 10) { goto L220; } /* compute the newton correction. */ i__1 = *n; for (j = 1; j <= i__1; ++j) { l = ipvt[j]; wa1[j] = diag[l] * (wa2[l] / dxnorm); /* L180: */ } i__1 = *n; for (j = 1; j <= i__1; ++j) { wa1[j] /= sdiag[j]; temp = wa1[j]; jp1 = j + 1; if (*n < jp1) { goto L200; } i__2 = *n; for (i__ = jp1; i__ <= i__2; ++i__) { wa1[i__] -= r__[i__ + j * r_dim1] * temp; /* L190: */ } L200: /* L210: */ ; } temp = enorm_(n, &wa1[1]); parc = fp / *delta / temp / temp; /* depending on the sign of the function, update parl or paru. */ if (fp > zero) { parl = max(parl,*par); } if (fp < zero) { paru = min(paru,*par); } /* compute an improved estimate for par. */ /* Computing MAX */ d__1 = parl, d__2 = *par + parc; *par = max(d__1,d__2); /* end of an iteration. */ goto L150; L220: /* termination. */ if (iter == 0) { *par = zero; } return 0; /* last card of subroutine lmpar. */ } /* lmpar_ */ /* Subroutine */ int qrfac_(integer *m, integer *n, doublereal *a, integer * lda, logical *pivot, integer *ipvt, integer *lipvt, doublereal *rdiag, doublereal *acnorm, doublereal *wa) { /* Initialized data */ static doublereal one = 1.; static doublereal p05 = .05; static doublereal zero = 0.; /* System generated locals */ integer a_dim1, a_offset, i__1, i__2, i__3; doublereal d__1, d__2, d__3; /* Local variables */ static integer i__, j, k, jp1; static doublereal sum; static integer kmax; static doublereal temp; static integer minmn; static doublereal epsmch; static doublereal ajnorm; /* ********** */ /* subroutine qrfac */ /* this subroutine uses householder transformations with column */ /* pivoting (optional) to compute a qr factorization of the */ /* m by n matrix a. that is, qrfac determines an orthogonal */ /* matrix q, a permutation matrix p, and an upper trapezoidal */ /* matrix r with diagonal elements of nonincreasing magnitude, */ /* such that a*p = q*r. the householder transformation for */ /* column k, k = 1,2,...,min(m,n), is of the form */ /* t */ /* i - (1/u(k))*u*u */ /* where u has zeros in the first k-1 positions. the form of */ /* this transformation and the method of pivoting first */ /* appeared in the corresponding linpack subroutine. */ /* the subroutine statement is */ /* subroutine qrfac(m,n,a,lda,pivot,ipvt,lipvt,rdiag,acnorm,wa) */ /* where */ /* m is a positive integer input variable set to the number */ /* of rows of a. */ /* n is a positive integer input variable set to the number */ /* of columns of a. */ /* a is an m by n array. on input a contains the matrix for */ /* which the qr factorization is to be computed. on output */ /* the strict upper trapezoidal part of a contains the strict */ /* upper trapezoidal part of r, and the lower trapezoidal */ /* part of a contains a factored form of q (the non-trivial */ /* elements of the u vectors described above). */ /* lda is a positive integer input variable not less than m */ /* which specifies the leading dimension of the array a. */ /* pivot is a logical input variable. if pivot is set true, */ /* then column pivoting is enforced. if pivot is set false, */ /* then no column pivoting is done. */ /* ipvt is an integer output array of length lipvt. ipvt */ /* defines the permutation matrix p such that a*p = q*r. */ /* column j of p is column ipvt(j) of the identity matrix. */ /* if pivot is false, ipvt is not referenced. */ /* lipvt is a positive integer input variable. if pivot is false, */ /* then lipvt may be as small as 1. if pivot is true, then */ /* lipvt must be at least n. */ /* rdiag is an output array of length n which contains the */ /* diagonal elements of r. */ /* acnorm is an output array of length n which contains the */ /* norms of the corresponding columns of the input matrix a. */ /* if this information is not needed, then acnorm can coincide */ /* with rdiag. */ /* wa is a work array of length n. if pivot is false, then wa */ /* can coincide with rdiag. */ /* subprograms called */ /* minpack-supplied ... dpmpar,enorm */ /* fortran-supplied ... dmax1,dsqrt,min0 */ /* argonne national laboratory. minpack project. march 1980. */ /* burton s. garbow, kenneth e. hillstrom, jorge j. more */ /* ********** */ /* Parameter adjustments */ --wa; --acnorm; --rdiag; a_dim1 = *lda; a_offset = a_dim1 + 1; a -= a_offset; --ipvt; /* Function Body */ /* epsmch is the machine precision. */ epsmch = dpmpar_(&c__1); /* compute the initial column norms and initialize several arrays. */ i__1 = *n; for (j = 1; j <= i__1; ++j) { acnorm[j] = enorm_(m, &a[j * a_dim1 + 1]); rdiag[j] = acnorm[j]; wa[j] = rdiag[j]; if (*pivot) { ipvt[j] = j; } /* L10: */ } /* reduce a to r with householder transformations. */ minmn = min(*m,*n); i__1 = minmn; for (j = 1; j <= i__1; ++j) { if (! (*pivot)) { goto L40; } /* bring the column of largest norm into the pivot position. */ kmax = j; i__2 = *n; for (k = j; k <= i__2; ++k) { if (rdiag[k] > rdiag[kmax]) { kmax = k; } /* L20: */ } if (kmax == j) { goto L40; } i__2 = *m; for (i__ = 1; i__ <= i__2; ++i__) { temp = a[i__ + j * a_dim1]; a[i__ + j * a_dim1] = a[i__ + kmax * a_dim1]; a[i__ + kmax * a_dim1] = temp; /* L30: */ } rdiag[kmax] = rdiag[j]; wa[kmax] = wa[j]; k = ipvt[j]; ipvt[j] = ipvt[kmax]; ipvt[kmax] = k; L40: /* compute the householder transformation to reduce the */ /* j-th column of a to a multiple of the j-th unit vector. */ i__2 = *m - j + 1; ajnorm = enorm_(&i__2, &a[j + j * a_dim1]); if (ajnorm == zero) { goto L100; } if (a[j + j * a_dim1] < zero) { ajnorm = -ajnorm; } i__2 = *m; for (i__ = j; i__ <= i__2; ++i__) { a[i__ + j * a_dim1] /= ajnorm; /* L50: */ } a[j + j * a_dim1] += one; /* apply the transformation to the remaining columns */ /* and update the norms. */ jp1 = j + 1; if (*n < jp1) { goto L100; } i__2 = *n; for (k = jp1; k <= i__2; ++k) { sum = zero; i__3 = *m; for (i__ = j; i__ <= i__3; ++i__) { sum += a[i__ + j * a_dim1] * a[i__ + k * a_dim1]; /* L60: */ } temp = sum / a[j + j * a_dim1]; i__3 = *m; for (i__ = j; i__ <= i__3; ++i__) { a[i__ + k * a_dim1] -= temp * a[i__ + j * a_dim1]; /* L70: */ } if (! (*pivot) || rdiag[k] == zero) { goto L80; } temp = a[j + k * a_dim1] / rdiag[k]; /* Computing MAX */ /* Computing 2nd power */ d__3 = temp; d__1 = zero, d__2 = one - d__3 * d__3; rdiag[k] *= sqrt((max(d__1,d__2))); /* Computing 2nd power */ d__1 = rdiag[k] / wa[k]; if (p05 * (d__1 * d__1) > epsmch) { goto L80; } i__3 = *m - j; rdiag[k] = enorm_(&i__3, &a[jp1 + k * a_dim1]); wa[k] = rdiag[k]; L80: /* L90: */ ; } L100: rdiag[j] = -ajnorm; /* L110: */ } return 0; /* last card of subroutine qrfac. */ } /* qrfac_ */ /* Subroutine */ int qrsolv_(integer *n, doublereal *r__, integer *ldr, integer *ipvt, doublereal *diag, doublereal *qtb, doublereal *x, doublereal *sdiag, doublereal *wa) { /* Initialized data */ static doublereal p5 = .5; static doublereal p25 = .25; static doublereal zero = 0.; /* System generated locals */ integer r_dim1, r_offset, i__1, i__2, i__3; doublereal d__1, d__2; /* Local variables */ static integer i__, j, k, l, jp1, kp1; static doublereal tan__, cos__, sin__, sum, temp, cotan; static integer nsing; static doublereal qtbpj; /* ********** */ /* subroutine qrsolv */ /* given an m by n matrix a, an n by n diagonal matrix d, */ /* and an m-vector b, the problem is to determine an x which */ /* solves the system */ /* a*x = b , d*x = 0 , */ /* in the least squares sense. */ /* this subroutine completes the solution of the problem */ /* if it is provided with the necessary information from the */ /* qr factorization, with column pivoting, of a. that is, if */ /* a*p = q*r, where p is a permutation matrix, q has orthogonal */ /* columns, and r is an upper triangular matrix with diagonal */ /* elements of nonincreasing magnitude, then qrsolv expects */ /* the full upper triangle of r, the permutation matrix p, */ /* and the first n components of (q transpose)*b. the system */ /* a*x = b, d*x = 0, is then equivalent to */ /* t t */ /* r*z = q *b , p *d*p*z = 0 , */ /* where x = p*z. if this system does not have full rank, */ /* then a least squares solution is obtained. on output qrsolv */ /* also provides an upper triangular matrix s such that */ /* t t t */ /* p *(a *a + d*d)*p = s *s . */ /* s is computed within qrsolv and may be of separate interest. */ /* the subroutine statement is */ /* subroutine qrsolv(n,r,ldr,ipvt,diag,qtb,x,sdiag,wa) */ /* where */ /* n is a positive integer input variable set to the order of r. */ /* r is an n by n array. on input the full upper triangle */ /* must contain the full upper triangle of the matrix r. */ /* on output the full upper triangle is unaltered, and the */ /* strict lower triangle contains the strict upper triangle */ /* (transposed) of the upper triangular matrix s. */ /* ldr is a positive integer input variable not less than n */ /* which specifies the leading dimension of the array r. */ /* ipvt is an integer input array of length n which defines the */ /* permutation matrix p such that a*p = q*r. column j of p */ /* is column ipvt(j) of the identity matrix. */ /* diag is an input array of length n which must contain the */ /* diagonal elements of the matrix d. */ /* qtb is an input array of length n which must contain the first */ /* n elements of the vector (q transpose)*b. */ /* x is an output array of length n which contains the least */ /* squares solution of the system a*x = b, d*x = 0. */ /* sdiag is an output array of length n which contains the */ /* diagonal elements of the upper triangular matrix s. */ /* wa is a work array of length n. */ /* subprograms called */ /* fortran-supplied ... dabs,dsqrt */ /* argonne national laboratory. minpack project. march 1980. */ /* burton s. garbow, kenneth e. hillstrom, jorge j. more */ /* ********** */ /* Parameter adjustments */ --wa; --sdiag; --x; --qtb; --diag; --ipvt; r_dim1 = *ldr; r_offset = r_dim1 + 1; r__ -= r_offset; /* Function Body */ /* copy r and (q transpose)*b to preserve input and initialize s. */ /* in particular, save the diagonal elements of r in x. */ i__1 = *n; for (j = 1; j <= i__1; ++j) { i__2 = *n; for (i__ = j; i__ <= i__2; ++i__) { r__[i__ + j * r_dim1] = r__[j + i__ * r_dim1]; /* L10: */ } x[j] = r__[j + j * r_dim1]; wa[j] = qtb[j]; /* L20: */ } /* eliminate the diagonal matrix d using a givens rotation. */ i__1 = *n; for (j = 1; j <= i__1; ++j) { /* prepare the row of d to be eliminated, locating the */ /* diagonal element using p from the qr factorization. */ l = ipvt[j]; if (diag[l] == zero) { goto L90; } i__2 = *n; for (k = j; k <= i__2; ++k) { sdiag[k] = zero; /* L30: */ } sdiag[j] = diag[l]; /* the transformations to eliminate the row of d */ /* modify only a single element of (q transpose)*b */ /* beyond the first n, which is initially zero. */ qtbpj = zero; i__2 = *n; for (k = j; k <= i__2; ++k) { /* determine a givens rotation which eliminates the */ /* appropriate element in the current row of d. */ if (sdiag[k] == zero) { goto L70; } if ((d__1 = r__[k + k * r_dim1], abs(d__1)) >= (d__2 = sdiag[k], abs(d__2))) { goto L40; } cotan = r__[k + k * r_dim1] / sdiag[k]; /* Computing 2nd power */ d__1 = cotan; sin__ = p5 / sqrt(p25 + p25 * (d__1 * d__1)); cos__ = sin__ * cotan; goto L50; L40: tan__ = sdiag[k] / r__[k + k * r_dim1]; /* Computing 2nd power */ d__1 = tan__; cos__ = p5 / sqrt(p25 + p25 * (d__1 * d__1)); sin__ = cos__ * tan__; L50: /* compute the modified diagonal element of r and */ /* the modified element of ((q transpose)*b,0). */ r__[k + k * r_dim1] = cos__ * r__[k + k * r_dim1] + sin__ * sdiag[ k]; temp = cos__ * wa[k] + sin__ * qtbpj; qtbpj = -sin__ * wa[k] + cos__ * qtbpj; wa[k] = temp; /* accumulate the tranformation in the row of s. */ kp1 = k + 1; if (*n < kp1) { goto L70; } i__3 = *n; for (i__ = kp1; i__ <= i__3; ++i__) { temp = cos__ * r__[i__ + k * r_dim1] + sin__ * sdiag[i__]; sdiag[i__] = -sin__ * r__[i__ + k * r_dim1] + cos__ * sdiag[ i__]; r__[i__ + k * r_dim1] = temp; /* L60: */ } L70: /* L80: */ ; } L90: /* store the diagonal element of s and restore */ /* the corresponding diagonal element of r. */ sdiag[j] = r__[j + j * r_dim1]; r__[j + j * r_dim1] = x[j]; /* L100: */ } /* solve the triangular system for z. if the system is */ /* singular, then obtain a least squares solution. */ nsing = *n; i__1 = *n; for (j = 1; j <= i__1; ++j) { if (sdiag[j] == zero && nsing == *n) { nsing = j - 1; } if (nsing < *n) { wa[j] = zero; } /* L110: */ } if (nsing < 1) { goto L150; } i__1 = nsing; for (k = 1; k <= i__1; ++k) { j = nsing - k + 1; sum = zero; jp1 = j + 1; if (nsing < jp1) { goto L130; } i__2 = nsing; for (i__ = jp1; i__ <= i__2; ++i__) { sum += r__[i__ + j * r_dim1] * wa[i__]; /* L120: */ } L130: wa[j] = (wa[j] - sum) / sdiag[j]; /* L140: */ } L150: /* permute the components of z back to components of x. */ i__1 = *n; for (j = 1; j <= i__1; ++j) { l = ipvt[j]; x[l] = wa[j]; /* L160: */ } return 0; /* last card of subroutine qrsolv. */ } /* qrsolv_ */