Пример #1
0
/* Subroutine */ void lmstr_(void (*fcn)(const int *m, const int *n, const double *x, double *fvec,
			  double *fjrow, int *iflag ), const int *m, const int *n, double *x, 
	double *fvec, double *fjac, const int *ldfjac, const double *ftol,
	const double *xtol, const double *gtol, const int *maxfev, double *
	diag, const int *mode, const double *factor, const int *nprint, int *
	info, int *nfev, int *njev, int *ipvt, double *qtf, 
	double *wa1, double *wa2, double *wa3, double *wa4)
{
    /* Table of constant values */

    const int c__1 = 1;
    const int c_true = TRUE_;

    /* Initialized data */

#define p1 .1
#define p5 .5
#define p25 .25
#define p75 .75
#define p0001 1e-4

    /* System generated locals */
    int fjac_dim1, fjac_offset, i__1, i__2;
    double d__1, d__2, d__3;

    /* Local variables */
    int i__, j, l;
    double par, sum;
    int sing;
    int iter;
    double temp, temp1, temp2;
    int iflag;
    double delta;
    double ratio;
    double fnorm, gnorm, pnorm, xnorm, fnorm1, actred, dirder, 
	    epsmch, prered;

/*     ********** */

/*     subroutine lmstr */

/*     the purpose of lmstr is to minimize the sum of the squares of */
/*     m nonlinear functions in n variables by a modification of */
/*     the levenberg-marquardt algorithm which uses minimal storage. */
/*     the user must provide a subroutine which calculates the */
/*     functions and the rows of the jacobian. */

/*     the subroutine statement is */

/*       subroutine lmstr(fcn,m,n,x,fvec,fjac,ldfjac,ftol,xtol,gtol, */
/*                        maxfev,diag,mode,factor,nprint,info,nfev, */
/*                        njev,ipvt,qtf,wa1,wa2,wa3,wa4) */

/*     where */

/*       fcn is the name of the user-supplied subroutine which */
/*         calculates the functions and the rows of the jacobian. */
/*         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,fjrow,iflag) */
/*         integer m,n,iflag */
/*         double precision x(n),fvec(m),fjrow(n) */
/*         ---------- */
/*         if iflag = 1 calculate the functions at x and */
/*         return this vector in fvec. */
/*         if iflag = i calculate the (i-1)-st row of the */
/*         jacobian at x and return this vector in fjrow. */
/*         ---------- */
/*         return */
/*         end */

/*         the value of iflag should not be changed by fcn unless */
/*         the user wants to terminate execution of lmstr. */
/*         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. */

/*       fjac is an output n by n array. the upper triangle of fjac */
/*         contains an upper triangular matrix r 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 triangular */
/*         part of fjac contains information generated during */
/*         the computation of r. */

/*       ldfjac is a positive integer input variable not less than n */
/*         which specifies the leading dimension of the array fjac. */

/*       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 with iflag = 1 */
/*         has reached maxfev. */

/*       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 with iflag = 1 has */
/*                   reached 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 with iflag = 1. */

/*       njev is an integer output variable set to the number of */
/*         calls to fcn with iflag = 2. */

/*       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. */
/*         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,lmpar,qrfac,rwupdt */

/*       fortran-supplied ... dabs,dmax1,dmin1,dsqrt,mod */

/*     argonne national laboratory. minpack project. march 1980. */
/*     burton s. garbow, dudley v. goetschel, kenneth e. hillstrom, */
/*     jorge j. more */

/*     ********** */
    /* Parameter adjustments */
    --wa4;
    --fvec;
    --wa3;
    --wa2;
    --wa1;
    --qtf;
    --ipvt;
    --diag;
    --x;
    fjac_dim1 = *ldfjac;
    fjac_offset = 1 + fjac_dim1 * 1;
    fjac -= fjac_offset;

    /* Function Body */

/*     epsmch is the machine precision. */

    epsmch = dpmpar_(&c__1);

    *info = 0;
    iflag = 0;
    *nfev = 0;
    *njev = 0;

/*     check the input parameters for errors. */

    if (*n <= 0 || *m < *n || *ldfjac < *n || *ftol < 0. || *xtol < 0. || 
	    *gtol < 0. || *maxfev <= 0 || *factor <= 0.) {
	goto L340;
    }
    if (*mode != 2) {
	goto L20;
    }
    i__1 = *n;
    for (j = 1; j <= i__1; ++j) {
	if (diag[j] <= 0.) {
	    goto L340;
	}
/* L10: */
    }
L20:

/*     evaluate the function at the starting point */
/*     and calculate its norm. */

    iflag = 1;
    (*fcn)(m, n, &x[1], &fvec[1], &wa3[1], &iflag);
    *nfev = 1;
    if (iflag < 0) {
	goto L340;
    }
    fnorm = enorm_(m, &fvec[1]);

/*     initialize levenberg-marquardt parameter and iteration counter. */

    par = 0.;
    iter = 1;

/*     beginning of the outer loop. */

L30:

/*        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], &wa3[1], &iflag);
    }
    if (iflag < 0) {
	goto L340;
    }
L40:

/*        compute the qr factorization of the jacobian matrix */
/*        calculated one row at a time, while simultaneously */
/*        forming (q transpose)*fvec and storing the first */
/*        n components in qtf. */

    i__1 = *n;
    for (j = 1; j <= i__1; ++j) {
	qtf[j] = 0.;
	i__2 = *n;
	for (i__ = 1; i__ <= i__2; ++i__) {
	    fjac[i__ + j * fjac_dim1] = 0.;
/* L50: */
	}
/* L60: */
    }
    iflag = 2;
    i__1 = *m;
    for (i__ = 1; i__ <= i__1; ++i__) {
	(*fcn)(m, n, &x[1], &fvec[1], &wa3[1], &iflag);
	if (iflag < 0) {
	    goto L340;
	}
	temp = fvec[i__];
	rwupdt_(n, &fjac[fjac_offset], ldfjac, &wa3[1], &qtf[1], &temp, &wa1[
		1], &wa2[1]);
	++iflag;
/* L70: */
    }
    ++(*njev);

/*        if the jacobian is rank deficient, call qrfac to */
/*        reorder its columns and update the components of qtf. */

    sing = FALSE_;
    i__1 = *n;
    for (j = 1; j <= i__1; ++j) {
	if (fjac[j + j * fjac_dim1] == 0.) {
	    sing = TRUE_;
	}
	ipvt[j] = j;
	wa2[j] = enorm_(&j, &fjac[j * fjac_dim1 + 1]);
/* L80: */
    }
    if (! sing) {
	goto L130;
    }
    qrfac_(n, n, &fjac[fjac_offset], ldfjac, &c_true, &ipvt[1], n, &wa1[1], &
	    wa2[1], &wa3[1]);
    i__1 = *n;
    for (j = 1; j <= i__1; ++j) {
	if (fjac[j + j * fjac_dim1] == 0.) {
	    goto L110;
	}
	sum = 0.;
	i__2 = *n;
	for (i__ = j; i__ <= i__2; ++i__) {
	    sum += fjac[i__ + j * fjac_dim1] * qtf[i__];
/* L90: */
	}
	temp = -sum / fjac[j + j * fjac_dim1];
	i__2 = *n;
	for (i__ = j; i__ <= i__2; ++i__) {
	    qtf[i__] += fjac[i__ + j * fjac_dim1] * temp;
/* L100: */
	}
L110:
	fjac[j + j * fjac_dim1] = wa1[j];
/* L120: */
    }
L130:

/*        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 L170;
    }
    if (*mode == 2) {
	goto L150;
    }
    i__1 = *n;
    for (j = 1; j <= i__1; ++j) {
	diag[j] = wa2[j];
	if (wa2[j] == 0.) {
	    diag[j] = 1.;
	}
/* L140: */
    }
L150:

/*        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];
/* L160: */
    }
    xnorm = enorm_(n, &wa3[1]);
    delta = *factor * xnorm;
    if (delta == 0.) {
	delta = *factor;
    }
L170:

/*        compute the norm of the scaled gradient. */

    gnorm = 0.;
    if (fnorm == 0.) {
	goto L210;
    }
    i__1 = *n;
    for (j = 1; j <= i__1; ++j) {
	l = ipvt[j];
	if (wa2[l] == 0.) {
	    goto L190;
	}
	sum = 0.;
	i__2 = j;
	for (i__ = 1; i__ <= i__2; ++i__) {
	    sum += fjac[i__ + j * fjac_dim1] * (qtf[i__] / fnorm);
/* L180: */
	}
/* Computing MAX */
	d__2 = gnorm, d__3 = (d__1 = sum / wa2[l], abs(d__1));
	gnorm = max(d__2,d__3);
L190:
/* L200: */
	;
    }
L210:

/*        test for convergence of the gradient norm. */

    if (gnorm <= *gtol) {
	*info = 4;
    }
    if (*info != 0) {
	goto L340;
    }

/*        rescale if necessary. */

    if (*mode == 2) {
	goto L230;
    }
    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);
/* L220: */
    }
L230:

/*        beginning of the inner loop. */

L240:

/*           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];
/* L250: */
    }
    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], &wa3[1], &iflag);
    ++(*nfev);
    if (iflag < 0) {
	goto L340;
    }
    fnorm1 = enorm_(m, &wa4[1]);

/*           compute the scaled actual reduction. */

    actred = -1.;
    if (p1 * fnorm1 < fnorm) {
/* Computing 2nd power */
	d__1 = fnorm1 / fnorm;
	actred = 1. - 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] = 0.;
	l = ipvt[j];
	temp = wa1[l];
	i__2 = j;
	for (i__ = 1; i__ <= i__2; ++i__) {
	    wa3[i__] += fjac[i__ + j * fjac_dim1] * temp;
/* L260: */
	}
/* L270: */
    }
    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 = 0.;
    if (prered != 0.) {
	ratio = actred / prered;
    }

/*           update the step bound. */

    if (ratio > p25) {
	goto L280;
    }
    if (actred >= 0.) {
	temp = p5;
    }
    if (actred < 0.) {
	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 L300;
L280:
    if (par != 0. && ratio < p75) {
	goto L290;
    }
    delta = pnorm / p5;
    par = p5 * par;
L290:
L300:

/*           test for successful iteration. */

    if (ratio < p0001) {
	goto L330;
    }

/*           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];
/* L310: */
    }
    i__1 = *m;
    for (i__ = 1; i__ <= i__1; ++i__) {
	fvec[i__] = wa4[i__];
/* L320: */
    }
    xnorm = enorm_(n, &wa2[1]);
    fnorm = fnorm1;
    ++iter;
L330:

/*           tests for convergence. */

    if (abs(actred) <= *ftol && prered <= *ftol && p5 * ratio <= 1.) {
	*info = 1;
    }
    if (delta <= *xtol * xnorm) {
	*info = 2;
    }
    if (abs(actred) <= *ftol && prered <= *ftol && p5 * ratio <= 1. && *info 
	    == 2) {
	*info = 3;
    }
    if (*info != 0) {
	goto L340;
    }

/*           tests for termination and stringent tolerances. */

    if (*nfev >= *maxfev) {
	*info = 5;
    }
    if (abs(actred) <= epsmch && prered <= epsmch && p5 * ratio <= 1.) {
	*info = 6;
    }
    if (delta <= epsmch * xnorm) {
	*info = 7;
    }
    if (gnorm <= epsmch) {
	*info = 8;
    }
    if (*info != 0) {
	goto L340;
    }

/*           end of the inner loop. repeat if iteration unsuccessful. */

    if (ratio < p0001) {
	goto L240;
    }

/*        end of the outer loop. */

    goto L30;
L340:

/*     termination, either normal or user imposed. */

    if (iflag < 0) {
	*info = iflag;
    }
    iflag = 0;
    if (*nprint > 0) {
	(*fcn)(m, n, &x[1], &fvec[1], &wa3[1], &iflag);
    }
    return;

/*     last card of subroutine lmstr. */

} /* lmstr_ */
Пример #2
0
/* Subroutine */ int _omc_hybrd_(S_fp fcn, integer *n, doublereal *x, doublereal *
  fvec, doublereal *xtol, integer *maxfev, integer *ml, integer *mu,
  doublereal *epsfcn, doublereal *diag, integer *mode, doublereal *
  factor, integer *nprint, integer *info, integer *nfev, doublereal *
  fjac, doublereal * fjacobian, integer *ldfjac, doublereal *r__, integer *lr, doublereal *qtf,
  doublereal *wa1, doublereal *wa2, doublereal *wa3, doublereal *wa4, void* userdata)
{
    /* Initialized data */

    static doublereal one = 1.;
    static doublereal p1 = .1;
    static doublereal p5 = .5;
    static doublereal p001 = .001;
    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;

    /* Local variables */
    integer i__, j, l, jm1, iwa[1];
    doublereal sum;
    logical sing;
    integer iter;
    doublereal temp;
    integer msum, iflag;
    doublereal delta;
    extern /* Subroutine */ int qrfac_(integer *, integer *, doublereal *,
      integer *, logical *, integer *, integer *, doublereal *,
      doublereal *, doublereal *);
    logical jeval;
    integer ncsuc;
    doublereal ratio;
    extern doublereal enorm_(integer *, doublereal *);
    doublereal fnorm;
    extern /* Subroutine */ int qform_(integer *, integer *, doublereal *,
      integer *, doublereal *), fdjac1_(S_fp, integer *, doublereal *,
      doublereal *, doublereal *, integer *, integer *, integer *,
      integer *, doublereal *, doublereal *, doublereal *, void *);
    doublereal pnorm, xnorm, fnorm1;
    extern /* Subroutine */ int r1updt_(integer *, integer *, doublereal *,
      integer *, doublereal *, doublereal *, doublereal *, logical *);
    integer nslow1, nslow2;
    extern /* Subroutine */ int r1mpyq_(integer *, integer *, doublereal *,
      integer *, doublereal *, doublereal *);
    integer ncfail;
    extern /* Subroutine */ int dogleg_(integer *, doublereal *, integer *,
      doublereal *, doublereal *, doublereal *, doublereal *,
      doublereal *, doublereal *);
    doublereal actred, epsmch, prered;
    extern doublereal dpmpar_(integer *);

/*     ********** */

/*     subroutine hybrd */

/*     the purpose of hybrd is to find a zero of a system of */
/*     n nonlinear functions in n variables by a modification */
/*     of the powell hybrid method. 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 hybrd(fcn,n,x,fvec,xtol,maxfev,ml,mu,epsfcn, */
/*                        diag,mode,factor,nprint,info,nfev,fjac,fjac, */
/*                        ldfjac,r,lr,qtf,wa1,wa2,wa3,wa4, userdata) */

/*     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(n,x,fvec,iflag) */
/*         integer n,iflag */
/*         double precision x(n),fvec(n) */
/*         ---------- */
/*         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 hybrd. */
/*         in this case set iflag to a negative integer. */

/*       n is a positive integer input variable set to the number */
/*         of functions and variables. */

/*       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 n which contains */
/*         the functions evaluated at the output x. */

/*       xtol is a nonnegative input variable. termination */
/*         occurs when the relative error between two consecutive */
/*         iterates is at most xtol. */

/*       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. */

/*       ml is a nonnegative integer input variable which specifies */
/*         the number of subdiagonals within the band of the */
/*         jacobian matrix. if the jacobian is not banded, set */
/*         ml to at least n - 1. */

/*       mu is a nonnegative integer input variable which specifies */
/*         the number of superdiagonals within the band of the */
/*         jacobian matrix. if the jacobian is not banded, set */
/*         mu to at least n - 1. */

/*       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   relative error between two consecutive iterates */
/*                    is at most xtol. */

/*         info = 2   number of calls to fcn has reached or exceeded */
/*                    maxfev. */

/*         info = 3   xtol is too small. no further improvement in */
/*                    the approximate solution x is possible. */

/*         info = 4   iteration is not making good progress, as */
/*                    measured by the improvement from the last */
/*                    five jacobian evaluations. */

/*         info = 5   iteration is not making good progress, as */
/*                    measured by the improvement from the last */
/*                    ten iterations. */

/*       nfev is an integer output variable set to the number of */
/*         calls to fcn. */

/*       fjac is an output n by n array which contains the */
/*         orthogonal matrix q produced by the qr factorization */
/*         of the final approximate jacobian. */

/*       fjacobian is an output n by n array which contains the */
/*         of the final approximate jacobian. */

/*       ldfjac is a positive integer input variable not less than n */
/*         which specifies the leading dimension of the array fjac. */

/*       r is an output array of length lr which contains the */
/*         upper triangular matrix produced by the qr factorization */
/*         of the final approximate jacobian, stored rowwise. */

/*       lr is a positive integer input variable not less than */
/*         (n*(n+1))/2. */

/*       qtf is an output array of length n which contains */
/*         the vector (q transpose)*fvec. */

/*       wa1, wa2, wa3, and wa4 are work arrays of length n. */

/*     subprograms called */

/*       user-supplied ...... fcn */

/*       minpack-supplied ... dogleg,dpmpar,enorm,fdjac1, */
/*                            qform,qrfac,r1mpyq,r1updt */

/*       fortran-supplied ... dabs,dmax1,dmin1,min0,mod */

/*     argonne national laboratory. minpack project. march 1980. */
/*     burton s. garbow, kenneth e. hillstrom, jorge j. more */

/*     ********** */
    /* Parameter adjustments */
    --wa4;
    --wa3;
    --wa2;
    --wa1;
    --qtf;
    --diag;
    --fvec;
    --x;
    fjac_dim1 = *ldfjac;
    fjac_offset = 1 + fjac_dim1;
    fjac -= fjac_offset;
    --fjacobian;
    --r__;

    /* 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 || *xtol < zero || *maxfev <= 0 || *ml < 0 || *mu < 0 || *
      factor <= zero || *ldfjac < *n || *lr < *n * (*n + 1) / 2) {
  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)(n, &x[1], &fvec[1], &iflag, userdata);


    *nfev = 1;

    if(iflag < 0) {
  goto L300;
    }
    fnorm = enorm_(n, &fvec[1]);

/*     determine the number of calls to fcn needed to compute */
/*     the jacobian matrix. */

/* Computing MIN */
    i__1 = *ml + *mu + 1;
    msum = min(i__1,*n);

/*     initialize iteration counter and monitors. */

    iter = 1;
    ncsuc = 0;
    ncfail = 0;
    nslow1 = 0;
    nslow2 = 0;

/*     beginning of the outer loop. */

L30:
    jeval = TRUE_;

/*        calculate the jacobian matrix. */

    iflag = 2;
    fdjac1_((S_fp)fcn, n, &x[1], &fvec[1], &fjac[fjac_offset], ldfjac, &iflag,
       ml, mu, epsfcn, &wa1[1], &wa2[1], userdata);
    *nfev += msum;
/*        store the calculate jacobain matrix   */
/*        added by wbraun for scaling residuals */

    {
      int l = fjac_offset;
      int k = 1;
      for(j = 1; j <= *n; ++j){
        for(i__ = 1; i__<= *n; ++i__, l++, k++){
          fjacobian[k] = fjac[l];
        }
      }
    }

    if(iflag < 0) {
  goto L300;
    }

/*        compute the qr factorization of the jacobian. */

    qrfac_(n, n, &fjac[fjac_offset], ldfjac, &c_false, iwa, &c__1, &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 L70;
    }
    if(*mode == 2) {
  goto L50;
    }
    i__1 = *n;
    for(j = 1; j <= i__1; ++j) {
  diag[j] = wa2[j];
  if(wa2[j] == zero) {
      diag[j] = one;
  }
/* L40: */
    }
L50:

/*        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];
/* L60: */
    }
    xnorm = enorm_(n, &wa3[1]);
    delta = *factor * xnorm;
    if(delta == zero) {
  delta = *factor;
    }
L70:

/*        form (q transpose)*fvec and store in qtf. */

    i__1 = *n;
    for(i__ = 1; i__ <= i__1; ++i__) {
  qtf[i__] = fvec[i__];
/* L80: */
    }
    i__1 = *n;
    for(j = 1; j <= i__1; ++j) {
  if(fjac[j + j * fjac_dim1] == zero) {
      goto L110;
  }
  sum = zero;
  i__2 = *n;
  for(i__ = j; i__ <= i__2; ++i__) {
      sum += fjac[i__ + j * fjac_dim1] * qtf[i__];
/* L90: */
  }
  temp = -sum / fjac[j + j * fjac_dim1];
  i__2 = *n;
  for(i__ = j; i__ <= i__2; ++i__) {
      qtf[i__] += fjac[i__ + j * fjac_dim1] * temp;
/* L100: */
  }
L110:
/* L120: */
  ;
    }

/*        copy the triangular factor of the qr factorization into r. */

    sing = FALSE_;
    i__1 = *n;
    for(j = 1; j <= i__1; ++j) {
  l = j;
  jm1 = j - 1;
  if(jm1 < 1) {
      goto L140;
  }
  i__2 = jm1;
  for(i__ = 1; i__ <= i__2; ++i__) {
      r__[l] = fjac[i__ + j * fjac_dim1];
      l = l + *n - i__;
/* L130: */
  }
L140:
  r__[l] = wa1[j];
  if(wa1[j] == zero) {
      sing = TRUE_;
  }
/* L150: */
    }

/*        accumulate the orthogonal factor in fjac. */

    qform_(n, n, &fjac[fjac_offset], ldfjac, &wa1[1]);

/*        rescale if necessary. */

    if(*mode == 2) {
  goto L170;
    }
    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);
/* L160: */
    }
L170:

/*        beginning of the inner loop. */

L180:

/*           if requested, call fcn to enable printing of iterates. */

    if(*nprint <= 0) {
  goto L190;
    }
    iflag = 0;
    if((iter - 1) % *nprint == 0) {
  (*fcn)(n, &x[1], &fvec[1], &iflag, userdata);
    }
    if(iflag < 0) {
  goto L300;
    }
L190:

/*           determine the direction p. */

    dogleg_(n, &r__[1], lr, &diag[1], &qtf[1], &delta, &wa1[1], &wa2[1], &wa3[
      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];
/* L200: */
    }
    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)(n, &wa2[1], &wa4[1], &iflag, userdata);
    ++(*nfev);

/*           Scaling Residual vector  */
/*           added by wbraun          */
    /*
    {
      for(i__=1;i__<*n;i__++)
        wa4[i__] = diagres[i__] * wa4[i__];
    }
    */


    if(iflag < 0) {
  goto L300;
    }
    fnorm1 = enorm_(n, &wa4[1]);

/*           compute the scaled actual reduction. */

    actred = -one;
    if(fnorm1 < fnorm) {
/* Computing 2nd power */
  d__1 = fnorm1 / fnorm;
  actred = one - d__1 * d__1;
    }

/*           compute the scaled predicted reduction. */

    l = 1;
    i__1 = *n;
    for(i__ = 1; i__ <= i__1; ++i__) {
  sum = zero;
  i__2 = *n;
  for(j = i__; j <= i__2; ++j) {
      sum += r__[l] * wa1[j];
      ++l;
/* L210: */
  }
  wa3[i__] = qtf[i__] + sum;
/* L220: */
    }
    temp = enorm_(n, &wa3[1]);
    prered = zero;
    if(temp < fnorm) {
/* Computing 2nd power */
  d__1 = temp / fnorm;
  prered = one - d__1 * d__1;
    }

/*           compute the ratio of the actual to the predicted */
/*           reduction. */

    ratio = zero;
    if(prered > zero) {
  ratio = actred / prered;
    }

/*           update the step bound. */

    if(ratio >= p1) {
  goto L230;
    }
    ncsuc = 0;
    ++ncfail;
    delta = p5 * delta;
    goto L240;
L230:
    ncfail = 0;
    ++ncsuc;
    if(ratio >= p5 || ncsuc > 1) {
/* Computing MAX */
  d__1 = delta, d__2 = pnorm / p5;
  delta = max(d__1,d__2);
    }
    if((d__1 = ratio - one, abs(d__1)) <= p1) {
  delta = pnorm / p5;
    }
L240:

/*           test for successful iteration. */

    if(ratio < p0001) {
  goto L260;
    }

/*           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];
  fvec[j] = wa4[j];
/* L250: */
    }
    xnorm = enorm_(n, &wa2[1]);
    fnorm = fnorm1;
    ++iter;
L260:

/*           determine the progress of the iteration. */

    ++nslow1;
    if(actred >= p001) {
  nslow1 = 0;
    }
    if(jeval) {
  ++nslow2;
    }
    if(actred >= p1) {
  nslow2 = 0;
    }

/*           test for convergence. */

    if(delta <= *xtol * xnorm || fnorm == zero) {
  *info = 1;
    }
    if(*info != 0) {
  goto L300;
    }

/*           tests for termination and stringent tolerances. */

    if(*nfev >= *maxfev) {
  *info = 2;
    }
/* Computing MAX */
    d__1 = p1 * delta;
    if(p1 * max(d__1,pnorm) <= epsmch * xnorm) {
  *info = 3;
    }
    if(nslow2 == 5) {
  *info = 4;
    }
    if(nslow1 == 10) {
  *info = 5;
    }
    if(*info != 0) {
  goto L300;
    }

/*           criterion for recalculating jacobian approximation */
/*           by forward differences. */

    if(ncfail == 2) {
  goto L290;
    }

/*           calculate the rank one modification to the jacobian */
/*           and update qtf if necessary. */

    i__1 = *n;
    for(j = 1; j <= i__1; ++j) {
  sum = zero;
  i__2 = *n;
  for(i__ = 1; i__ <= i__2; ++i__) {
      sum += fjac[i__ + j * fjac_dim1] * wa4[i__];
/* L270: */
  }
  wa2[j] = (sum - wa3[j]) / pnorm;
  wa1[j] = diag[j] * (diag[j] * wa1[j] / pnorm);
  if(ratio >= p0001) {
      qtf[j] = sum;
  }
/* L280: */
    }

/*           compute the qr factorization of the updated jacobian. */

    r1updt_(n, n, &r__[1], lr, &wa1[1], &wa2[1], &wa3[1], &sing);
    r1mpyq_(n, n, &fjac[fjac_offset], ldfjac, &wa2[1], &wa3[1]);
    r1mpyq_(&c__1, n, &qtf[1], &c__1, &wa2[1], &wa3[1]);

/*           end of the inner loop. */

    jeval = FALSE_;
    goto L180;
L290:

/*        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)(n, &x[1], &fvec[1], &iflag, userdata);
    }
    return 0;

/*     last card of subroutine hybrd. */

} /* _omc_hybrd_ */
Пример #3
0
/*<    >*/
/* Subroutine */ int lmder_(
  void (*fcn)(v3p_netlib_integer*,
              v3p_netlib_integer*,
              v3p_netlib_doublereal*,
              v3p_netlib_doublereal*,
              v3p_netlib_doublereal*,
              v3p_netlib_integer*,
              v3p_netlib_integer*,
              void*),
        integer *m, integer *n, doublereal *x,
        doublereal *fvec, doublereal *fjac, integer *ldfjac, doublereal *ftol,
         doublereal *xtol, doublereal *gtol, integer *maxfev, doublereal *
        diag, integer *mode, doublereal *factor, integer *nprint, integer *
        info, integer *nfev, integer *njev, integer *ipvt, doublereal *qtf, 
        doublereal *wa1, doublereal *wa2, doublereal *wa3, doublereal *wa4,
        void* userdata)
{
    /* Initialized data */

    static doublereal one = 1.; /* constant */
    static doublereal p1 = .1; /* constant */
    static doublereal p5 = .5; /* constant */
    static doublereal p25 = .25; /* constant */
    static doublereal p75 = .75; /* constant */
    static doublereal p0001 = 1e-4; /* constant */
    static doublereal zero = 0.; /* constant */

    /* System generated locals */
    integer fjac_dim1, fjac_offset, i__1, i__2;
    doublereal d__1, d__2, d__3;

    /* Builtin functions */
    double sqrt(doublereal);

    /* Local variables */
    integer i__, j, l;
    doublereal par, sum;
    integer iter;
    doublereal temp=0, temp1, temp2;
    integer iflag;
    doublereal delta;
    extern /* Subroutine */ int qrfac_(integer *, integer *, doublereal *, 
            integer *, logical *, integer *, integer *, doublereal *, 
            doublereal *, doublereal *), lmpar_(integer *, doublereal *, 
            integer *, integer *, doublereal *, doublereal *, doublereal *, 
            doublereal *, doublereal *, doublereal *, doublereal *, 
            doublereal *);
    doublereal ratio;
    extern doublereal enorm_(integer *, doublereal *);
    doublereal fnorm, gnorm, pnorm, xnorm=0, fnorm1, actred, dirder, epsmch, 
            prered;
    extern doublereal dpmpar_(integer *);

/*<       integer m,n,ldfjac,maxfev,mode,nprint,info,nfev,njev >*/
/*<       integer ipvt(n) >*/
/*<       double precision ftol,xtol,gtol,factor >*/
/*<    >*/
/*     ********** */

/*     subroutine lmder */

/*     the purpose of lmder 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 and the jacobian. */

/*     the subroutine statement is */

/*       subroutine lmder(fcn,m,n,x,fvec,fjac,ldfjac,ftol,xtol,gtol, */
/*                        maxfev,diag,mode,factor,nprint,info,nfev, */
/*                        njev,ipvt,qtf,wa1,wa2,wa3,wa4) */

/*     where */

/*       fcn is the name of the user-supplied subroutine which */
/*         calculates the functions and the jacobian. 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,fjac,ldfjac,iflag) */
/*         integer m,n,ldfjac,iflag */
/*         double precision x(n),fvec(m),fjac(ldfjac,n) */
/*         ---------- */
/*         if iflag = 1 calculate the functions at x and */
/*         return this vector in fvec. do not alter fjac. */
/*         if iflag = 2 calculate the jacobian at x and */
/*         return this matrix in fjac. do not alter fvec. */
/*         ---------- */
/*         return */
/*         end */

/*         the value of iflag should not be changed by fcn unless */
/*         the user wants to terminate execution of lmder. */
/*         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. */

/*       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. */

/*       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 with iflag = 1 */
/*         has reached maxfev. */

/*       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, fvec, and fjac */
/*         available for printing. fvec and fjac should not be */
/*         altered. 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 with iflag = 1 has */
/*                   reached 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 with iflag = 1. */

/*       njev is an integer output variable set to the number of */
/*         calls to fcn with iflag = 2. */

/*       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,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 */

/*     ********** */
/*<       integer i,iflag,iter,j,l >*/
/*<    >*/
/*<       double precision dpmpar,enorm >*/
/*<    >*/
    /* Parameter adjustments */
    --wa4;
    --fvec;
    --wa3;
    --wa2;
    --wa1;
    --qtf;
    --ipvt;
    --diag;
    --x;
    fjac_dim1 = *ldfjac;
    fjac_offset = 1 + fjac_dim1;
    fjac -= fjac_offset;

    /* Function Body */

/*     epsmch is the machine precision. */

/*<       epsmch = dpmpar(1) >*/
    epsmch = dpmpar_(&c__1);

/*<       info = 0 >*/
    *info = 0;
/*<       iflag = 0 >*/
    iflag = 0;
/*<       nfev = 0 >*/
    *nfev = 0;
/*<       njev = 0 >*/
    *njev = 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 .ne. 2) go to 20 >*/
    if (*mode != 2) {
        goto L20;
    }
/*<       do 10 j = 1, n >*/
    i__1 = *n;
    for (j = 1; j <= i__1; ++j) {
/*<          if (diag(j) .le. zero) go to 300 >*/
        if (diag[j] <= zero) {
            goto L300;
        }
/*<    10    continue >*/
/* L10: */
    }
/*<    20 continue >*/
L20:

/*     evaluate the function at the starting point */
/*     and calculate its norm. */

/*<       iflag = 1 >*/
    iflag = 1;
/*<       call fcn(m,n,x,fvec,fjac,ldfjac,iflag) >*/
    (*fcn)(m, n, &x[1], &fvec[1], &fjac[fjac_offset], ldfjac, &iflag,
           userdata);
/*<       nfev = 1 >*/
    *nfev = 1;
/*<       if (iflag .lt. 0) go to 300 >*/
    if (iflag < 0) {
        goto L300;
    }
/*<       fnorm = enorm(m,fvec) >*/
    fnorm = enorm_(m, &fvec[1]);

/*     initialize levenberg-marquardt parameter and iteration counter. */

/*<       par = zero >*/
    par = zero;
/*<       iter = 1 >*/
    iter = 1;

/*     beginning of the outer loop. */

/*<    30 continue >*/
L30:

/*        calculate the jacobian matrix. */

/*<          iflag = 2 >*/
    iflag = 2;
/*<          call fcn(m,n,x,fvec,fjac,ldfjac,iflag) >*/
    (*fcn)(m, n, &x[1], &fvec[1], &fjac[fjac_offset], ldfjac, &iflag,
           userdata);
/*<          njev = njev + 1 >*/
    ++(*njev);
/*<          if (iflag .lt. 0) go to 300 >*/
    if (iflag < 0) {
        goto L300;
    }

/*        if requested, call fcn to enable printing of iterates. */

/*<          if (nprint .le. 0) go to 40 >*/
    if (*nprint <= 0) {
        goto L40;
    }
/*<          iflag = 0 >*/
    iflag = 0;
/*<    >*/
    if ((iter - 1) % *nprint == 0) {
        (*fcn)(m, n, &x[1], &fvec[1], &fjac[fjac_offset], ldfjac, &iflag,
               userdata);
    }
/*<          if (iflag .lt. 0) go to 300 >*/
    if (iflag < 0) {
        goto L300;
    }
/*<    40    continue >*/
L40:

/*        compute the qr factorization of the jacobian. */

/*<          call qrfac(m,n,fjac,ldfjac,.true.,ipvt,n,wa1,wa2,wa3) >*/
    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 .ne. 1) go to 80 >*/
    if (iter != 1) {
        goto L80;
    }
/*<          if (mode .eq. 2) go to 60 >*/
    if (*mode == 2) {
        goto L60;
    }
/*<          do 50 j = 1, n >*/
    i__1 = *n;
    for (j = 1; j <= i__1; ++j) {
/*<             diag(j) = wa2(j) >*/
        diag[j] = wa2[j];
/*<             if (wa2(j) .eq. zero) diag(j) = one >*/
        if (wa2[j] == zero) {
            diag[j] = one;
        }
/*<    50       continue >*/
/* L50: */
    }
/*<    60    continue >*/
L60:

/*        on the first iteration, calculate the norm of the scaled x */
/*        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_ */
Пример #4
0
/* DECK SCOV */
/* Subroutine */ int scov_(S_fp fcn, integer *iopt, integer *m, integer *n, 
	real *x, real *fvec, real *r__, integer *ldr, integer *info, real *
	wa1, real *wa2, real *wa3, real *wa4)
{
    /* Initialized data */

    static real zero = 0.f;
    static real one = 1.f;

    /* System generated locals */
    integer r_dim1, r_offset, i__1, i__2, i__3;

    /* Local variables */
    static integer i__, j, k, kp1, nm1, idum;
    static logical sing;
    static real temp;
    static integer nrow, iflag;
    extern /* Subroutine */ int qrfac_(integer *, integer *, real *, integer *
	    , logical *, integer *, integer *, real *, real *, real *);
    static real sigma;
    extern doublereal enorm_(integer *, real *);
    extern /* Subroutine */ int fdjac3_(S_fp, integer *, integer *, real *, 
	    real *, real *, integer *, integer *, real *, real *), xermsg_(
	    char *, char *, char *, integer *, integer *, ftnlen, ftnlen, 
	    ftnlen), rwupdt_(integer *, real *, integer *, real *, real *, 
	    real *, real *, real *);

/* ***BEGIN PROLOGUE  SCOV */
/* ***PURPOSE  Calculate the covariance matrix for a nonlinear data */
/*            fitting problem.  It is intended to be used after a */
/*            successful return from either SNLS1 or SNLS1E. */
/* ***LIBRARY   SLATEC */
/* ***CATEGORY  K1B1 */
/* ***TYPE      SINGLE PRECISION (SCOV-S, DCOV-D) */
/* ***KEYWORDS  COVARIANCE MATRIX, NONLINEAR DATA FITTING, */
/*             NONLINEAR LEAST SQUARES */
/* ***AUTHOR  Hiebert, K. L., (SNLA) */
/* ***DESCRIPTION */

/*  1. Purpose. */

/*     SCOV calculates the covariance matrix for a nonlinear data */
/*     fitting problem.  It is intended to be used after a */
/*     successful return from either SNLS1 or SNLS1E. SCOV */
/*     and SNLS1 (and SNLS1E) have compatible parameters.  The */
/*     required external subroutine, FCN, is the same */
/*     for all three codes, SCOV, SNLS1, and SNLS1E. */

/*  2. Subroutine and Type Statements. */

/*     SUBROUTINE SCOV(FCN,IOPT,M,N,X,FVEC,R,LDR,INFO, */
/*                     WA1,WA2,WA3,WA4) */
/*     INTEGER IOPT,M,N,LDR,INFO */
/*     REAL X(N),FVEC(M),R(LDR,N),WA1(N),WA2(N),WA3(N),WA4(M) */
/*     EXTERNAL FCN */

/*  3. Parameters. */

/*       FCN is the name of the user-supplied subroutine which calculates */
/*         the functions.  If the user wants to supply the Jacobian */
/*         (IOPT=2 or 3), then FCN must be written to calculate the */
/*         Jacobian, as well as the functions.  See the explanation */
/*         of the IOPT argument below.  FCN must be declared in an */
/*         EXTERNAL statement in the calling program and should be */
/*         written as follows. */

/*         SUBROUTINE FCN(IFLAG,M,N,X,FVEC,FJAC,LDFJAC) */
/*         INTEGER IFLAG,LDFJAC,M,N */
/*         REAL X(N),FVEC(M) */
/*         ---------- */
/*         FJAC and LDFJAC may be ignored     , if IOPT=1. */
/*         REAL FJAC(LDFJAC,N)                , if IOPT=2. */
/*         REAL FJAC(N)                       , if IOPT=3. */
/*         ---------- */
/*           IFLAG will never be zero when FCN is called by SCOV. */
/*         RETURN */
/*         ---------- */
/*           If IFLAG=1, calculate the functions at X and return */
/*           this vector in FVEC. */
/*         RETURN */
/*         ---------- */
/*           If IFLAG=2, calculate the full Jacobian at X and return */
/*           this matrix in FJAC.  Note that IFLAG will never be 2 unless */
/*           IOPT=2.  FVEC contains the function values at X and must */
/*           not be altered.  FJAC(I,J) must be set to the derivative */
/*           of FVEC(I) with respect to X(J). */
/*         RETURN */
/*         ---------- */
/*           If IFLAG=3, calculate the LDFJAC-th row of the Jacobian */
/*           and return this vector in FJAC.  Note that IFLAG will */
/*           never be 3 unless IOPT=3.  FJAC(J) must be set to */
/*           the derivative of FVEC(LDFJAC) with respect to X(J). */
/*         RETURN */
/*         ---------- */
/*         END */


/*         The value of IFLAG should not be changed by FCN unless the */
/*         user wants to terminate execution of SCOV.  In this case, set */
/*         IFLAG to a negative integer. */


/*    IOPT is an input variable which specifies how the Jacobian will */
/*         be calculated.  If IOPT=2 or 3, then the user must supply the */
/*         Jacobian, as well as the function values, through the */
/*         subroutine FCN.  If IOPT=2, the user supplies the full */
/*         Jacobian with one call to FCN.  If IOPT=3, the user supplies */
/*         one row of the Jacobian with each call.  (In this manner, */
/*         storage can be saved because the full Jacobian is not stored.) */
/*         If IOPT=1, the code will approximate the Jacobian by forward */
/*         differencing. */

/*       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 the value */
/*         at which the covariance matrix is to be evaluated.  This is */
/*         usually the value for X returned from a successful run of */
/*         SNLS1 (or SNLS1E).  The value of X will not be changed. */

/*    FVEC is an output array of length M which contains the functions */
/*         evaluated at X. */

/*       R is an output array.  For IOPT=1 and 2, R is an M by N array. */
/*         For IOPT=3, R is an N by N array.  On output, if INFO=1, */
/*         the upper N by N submatrix of R contains the covariance */
/*         matrix evaluated at X. */

/*     LDR is a positive integer input variable which specifies */
/*         the leading dimension of the array R.  For IOPT=1 and 2, */
/*         LDR must not be less than M.  For IOPT=3, LDR must not */
/*         be less than N. */

/*    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 (M.LE.0 or N.LE.0). */

/*         INFO = 1 Successful return.  The covariance matrix has been */
/*                  calculated and stored in the upper N by N */
/*                  submatrix of R. */

/*         INFO = 2 The Jacobian matrix is singular for the input value */
/*                  of X.  The covariance matrix cannot be calculated. */
/*                  The upper N by N submatrix of R contains the QR */
/*                  factorization of the Jacobian (probably not of */
/*                  interest to the user). */

/*     WA1 is a work array of length N. */
/*     WA2 is a work array of length N. */
/*     WA3 is a work array of length N. */
/*     WA4 is a work array of length M. */

/* ***REFERENCES  (NONE) */
/* ***ROUTINES CALLED  ENORM, FDJAC3, QRFAC, RWUPDT, XERMSG */
/* ***REVISION HISTORY  (YYMMDD) */
/*   810522  DATE WRITTEN */
/*   890505  REVISION DATE from Version 3.2 */
/*   891214  Prologue converted to Version 4.0 format.  (BAB) */
/*   900315  CALLs to XERROR changed to CALLs to XERMSG.  (THJ) */
/*   900510  Fixed an error message.  (RWC) */
/* ***END PROLOGUE  SCOV */

/*     REVISED 820707-1100 */
/*     REVISED YYMMDD HHMM */

    /* Parameter adjustments */
    --x;
    --fvec;
    r_dim1 = *ldr;
    r_offset = 1 + r_dim1;
    r__ -= r_offset;
    --wa1;
    --wa2;
    --wa3;
    --wa4;

    /* Function Body */
/* ***FIRST EXECUTABLE STATEMENT  SCOV */
    sing = FALSE_;
    iflag = 0;
    if (*m <= 0 || *n <= 0) {
	goto L300;
    }

/*     CALCULATE SIGMA = (SUM OF THE SQUARED RESIDUALS) / (M-N) */
    iflag = 1;
    (*fcn)(&iflag, m, n, &x[1], &fvec[1], &r__[r_offset], ldr);
    if (iflag < 0) {
	goto L300;
    }
    temp = enorm_(m, &fvec[1]);
    sigma = one;
    if (*m != *n) {
	sigma = temp * temp / (*m - *n);
    }

/*     CALCULATE THE JACOBIAN */
    if (*iopt == 3) {
	goto L200;
    }

/*     STORE THE FULL JACOBIAN USING M*N STORAGE */
    if (*iopt == 1) {
	goto L100;
    }

/*     USER SUPPLIES THE JACOBIAN */
    iflag = 2;
    (*fcn)(&iflag, m, n, &x[1], &fvec[1], &r__[r_offset], ldr);
    goto L110;

/*     CODE APPROXIMATES THE JACOBIAN */
L100:
    fdjac3_((S_fp)fcn, m, n, &x[1], &fvec[1], &r__[r_offset], ldr, &iflag, &
	    zero, &wa4[1]);
L110:
    if (iflag < 0) {
	goto L300;
    }

/*     COMPUTE THE QR DECOMPOSITION */
    qrfac_(m, n, &r__[r_offset], ldr, &c_false, &idum, &c__1, &wa1[1], &wa1[1]
	    , &wa1[1]);
    i__1 = *n;
    for (i__ = 1; i__ <= i__1; ++i__) {
/* L120: */
	r__[i__ + i__ * r_dim1] = wa1[i__];
    }
    goto L225;

/*     COMPUTE THE QR FACTORIZATION OF THE JACOBIAN MATRIX CALCULATED ONE */
/*     ROW AT A TIME AND STORED IN THE UPPER TRIANGLE OF R. */
/*     ( (Q TRANSPOSE)*FVEC IS ALSO CALCULATED BUT NOT USED.) */
L200:
    i__1 = *n;
    for (j = 1; j <= i__1; ++j) {
	wa2[j] = zero;
	i__2 = *n;
	for (i__ = 1; i__ <= i__2; ++i__) {
	    r__[i__ + j * r_dim1] = zero;
/* L205: */
	}
/* L210: */
    }
    iflag = 3;
    i__1 = *m;
    for (i__ = 1; i__ <= i__1; ++i__) {
	nrow = i__;
	(*fcn)(&iflag, m, n, &x[1], &fvec[1], &wa1[1], &nrow);
	if (iflag < 0) {
	    goto L300;
	}
	temp = fvec[i__];
	rwupdt_(n, &r__[r_offset], ldr, &wa1[1], &wa2[1], &temp, &wa3[1], &
		wa4[1]);
/* L220: */
    }

/*     CHECK IF R IS SINGULAR. */
L225:
    i__1 = *n;
    for (i__ = 1; i__ <= i__1; ++i__) {
	if (r__[i__ + i__ * r_dim1] == zero) {
	    sing = TRUE_;
	}
/* L230: */
    }
    if (sing) {
	goto L300;
    }

/*     R IS UPPER TRIANGULAR.  CALCULATE (R TRANSPOSE) INVERSE AND STORE */
/*     IN THE UPPER TRIANGLE OF R. */
    if (*n == 1) {
	goto L275;
    }
    nm1 = *n - 1;
    i__1 = nm1;
    for (k = 1; k <= i__1; ++k) {

/*     INITIALIZE THE RIGHT-HAND SIDE (WA1(*)) AS THE K-TH COLUMN OF THE */
/*     IDENTITY MATRIX. */
	i__2 = *n;
	for (i__ = 1; i__ <= i__2; ++i__) {
	    wa1[i__] = zero;
/* L240: */
	}
	wa1[k] = one;

	r__[k + k * r_dim1] = wa1[k] / r__[k + k * r_dim1];
	kp1 = k + 1;
	i__2 = *n;
	for (i__ = kp1; i__ <= i__2; ++i__) {

/*     SUBTRACT R(K,I-1)*R(I-1,*) FROM THE RIGHT-HAND SIDE, WA1(*). */
	    i__3 = *n;
	    for (j = i__; j <= i__3; ++j) {
		wa1[j] -= r__[k + (i__ - 1) * r_dim1] * r__[i__ - 1 + j * 
			r_dim1];
/* L250: */
	    }
	    r__[k + i__ * r_dim1] = wa1[i__] / r__[i__ + i__ * r_dim1];
/* L260: */
	}
/* L270: */
    }
L275:
    r__[*n + *n * r_dim1] = one / r__[*n + *n * r_dim1];

/*     CALCULATE R-INVERSE * (R TRANSPOSE) INVERSE AND STORE IN THE UPPER */
/*     TRIANGLE OF R. */
    i__1 = *n;
    for (i__ = 1; i__ <= i__1; ++i__) {
	i__2 = *n;
	for (j = i__; j <= i__2; ++j) {
	    temp = zero;
	    i__3 = *n;
	    for (k = j; k <= i__3; ++k) {
		temp += r__[i__ + k * r_dim1] * r__[j + k * r_dim1];
/* L280: */
	    }
	    r__[i__ + j * r_dim1] = temp * sigma;
/* L290: */
	}
    }
    *info = 1;

L300:
    if (*m <= 0 || *n <= 0) {
	*info = 0;
    }
    if (iflag < 0) {
	*info = iflag;
    }
    if (sing) {
	*info = 2;
    }
    if (*info < 0) {
	xermsg_("SLATEC", "SCOV", "EXECUTION TERMINATED BECAUSE USER SET IFL"
		"AG NEGATIVE.", &c__1, &c__1, (ftnlen)6, (ftnlen)4, (ftnlen)53)
		;
    }
    if (*info == 0) {
	xermsg_("SLATEC", "SCOV", "INVALID INPUT PARAMETER.", &c__2, &c__1, (
		ftnlen)6, (ftnlen)4, (ftnlen)24);
    }
    if (*info == 2) {
	xermsg_("SLATEC", "SCOV", "SINGULAR JACOBIAN MATRIX, COVARIANCE MATR"
		"IX CANNOT BE CALCULATED.", &c__1, &c__1, (ftnlen)6, (ftnlen)4,
		 (ftnlen)65);
    }
    return 0;
} /* scov_ */