예제 #1
0
파일: testfit.c 프로젝트: jfarrington/XRD
int fit( double *p0, int *info){

  int m, n, lwa, iwa[4], one=1;
  double tol, fnorm, x[4], fvec[64], wa[512];
  extern void fcn();
        /*Fits one set of intensities from threshold scan. ud is 1 for lower threshold scan,
        -1 for upper threshold scan. Returns intensity, centroid and width of best fit to
        erf() function. x is array of DAC values for intensities y_meas.
        p0[0...3] is initial guess for solution.*/
	
	tol = sqrt(dpmpar_(&one));
	m=NPOINTS;
	n=4;
	lwa=512;
	lmdif1_(&fcn, &m, &n, p0, fvec, &tol, info, iwa, wa, &lwa);

	}
예제 #2
0
int main()
{
  int m, n, ldfjac, info, lwa, ipvt[3], one=1;
  double tol, fnorm;
  double x[3], fvec[15], fjac[9], wa[30];

  m = 15;
  n = 3;

  /*     the following starting values provide a rough fit. */

  x[0] = 1.;
  x[1] = 1.;
  x[2] = 1.;

  ldfjac = 3;
  lwa = 30;

  /*     set tol to the square root of the machine precision.
     unless high precision solutions are required,
     this is the recommended setting. */

  tol = sqrt(dpmpar_(&one));

  lmstr1_(&fcn, &m, &n, 
	  x, fvec, fjac, &ldfjac, 
	  &tol, &info, ipvt, wa, &lwa);

  fnorm = enorm_(&m, fvec);

  printf("      FINAL L2 NORM OF THE RESIDUALS%15.7g\n\n", fnorm);
  printf("      EXIT PARAMETER                %10i\n\n", info);
  printf("      FINAL APPROXIMATE SOLUTION\n\n%15.7g%15.7g%15.7g\n",
	 x[0], x[1], x[2]);

  return 0;
}
예제 #3
0
/* Subroutine */ int r1updt_(integer *m, integer *n, doublereal *s, integer *
                             ls, doublereal *u, doublereal *v, doublereal *w, logical *sing)
{
    /* Initialized data */

    static doublereal one = 1.;
    static doublereal p5 = .5;
    static doublereal p25 = .25;
    static doublereal zero = 0.;

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

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

    /* Local variables */
    static integer i__, j, l, jj, nm1;
    static doublereal tan__;
    static integer nmj;
    static doublereal cos__, sin__, tau, temp, giant, cotan;
    extern doublereal dpmpar_(integer *);

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

    /*     subroutine r1updt */

    /*     given an m by n lower trapezoidal matrix s, an m-vector u, */
    /*     and an n-vector v, the problem is to determine an */
    /*     orthogonal matrix q such that */

    /*                   t */
    /*           (s + u*v )*q */

    /*     is again lower trapezoidal. */

    /*     this subroutine determines q as the product of 2*(n - 1) */
    /*     transformations */

    /*           gv(n-1)*...*gv(1)*gw(1)*...*gw(n-1) */

    /*     where gv(i), gw(i) are givens rotations in the (i,n) plane */
    /*     which eliminate elements in the i-th and n-th planes, */
    /*     respectively. q itself is not accumulated, rather the */
    /*     information to recover the gv, gw rotations is returned. */

    /*     the subroutine statement is */

    /*       subroutine r1updt(m,n,s,ls,u,v,w,sing) */

    /*     where */

    /*       m is a positive integer input variable set to the number */
    /*         of rows of s. */

    /*       n is a positive integer input variable set to the number */
    /*         of columns of s. n must not exceed m. */

    /*       s is an array of length ls. on input s must contain the lower */
    /*         trapezoidal matrix s stored by columns. on output s contains */
    /*         the lower trapezoidal matrix produced as described above. */

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

    /*       u is an input array of length m which must contain the */
    /*         vector u. */

    /*       v is an array of length n. on input v must contain the vector */
    /*         v. on output v(i) contains the information necessary to */
    /*         recover the givens rotation gv(i) described above. */

    /*       w is an output array of length m. w(i) contains information */
    /*         necessary to recover the givens rotation gw(i) described */
    /*         above. */

    /*       sing is a logical output variable. sing is set true if any */
    /*         of the diagonal elements of the output s are zero. otherwise */
    /*         sing is set false. */

    /*     subprograms called */

    /*       minpack-supplied ... dpmpar */

    /*       fortran-supplied ... dabs,dsqrt */

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

    /*     ********** */
    /* Parameter adjustments */
    --w;
    --u;
    --v;
    --s;

    /* Function Body */

    /*     giant is the largest magnitude. */

    giant = dpmpar_(&c__3);

    /*     initialize the diagonal element pointer. */

    jj = *n * ((*m << 1) - *n + 1) / 2 - (*m - *n);

    /*     move the nontrivial part of the last column of s into w. */

    l = jj;
    i__1 = *m;
    for (i__ = *n; i__ <= i__1; ++i__) {
        w[i__] = s[l];
        ++l;
        /* L10: */
    }

    /*     rotate the vector v into a multiple of the n-th unit vector */
    /*     in such a way that a spike is introduced into w. */

    nm1 = *n - 1;
    if (nm1 < 1) {
        goto L70;
    }
    i__1 = nm1;
    for (nmj = 1; nmj <= i__1; ++nmj) {
        j = *n - nmj;
        jj -= *m - j + 1;
        w[j] = zero;
        if (v[j] == zero) {
            goto L50;
        }

        /*        determine a givens rotation which eliminates the */
        /*        j-th element of v. */

        if ((d__1 = v[*n], abs(d__1)) >= (d__2 = v[j], abs(d__2))) {
            goto L20;
        }
        cotan = v[*n] / v[j];
        /* Computing 2nd power */
        d__1 = cotan;
        sin__ = p5 / sqrt(p25 + p25 * (d__1 * d__1));
        cos__ = sin__ * cotan;
        tau = one;
        if (abs(cos__) * giant > one) {
            tau = one / cos__;
        }
        goto L30;
L20:
        tan__ = v[j] / v[*n];
        /* Computing 2nd power */
        d__1 = tan__;
        cos__ = p5 / sqrt(p25 + p25 * (d__1 * d__1));
        sin__ = cos__ * tan__;
        tau = sin__;
L30:

        /*        apply the transformation to v and store the information */
        /*        necessary to recover the givens rotation. */

        v[*n] = sin__ * v[j] + cos__ * v[*n];
        v[j] = tau;

        /*        apply the transformation to s and extend the spike in w. */

        l = jj;
        i__2 = *m;
        for (i__ = j; i__ <= i__2; ++i__) {
            temp = cos__ * s[l] - sin__ * w[i__];
            w[i__] = sin__ * s[l] + cos__ * w[i__];
            s[l] = temp;
            ++l;
            /* L40: */
        }
L50:
        /* L60: */
        ;
    }
L70:

    /*     add the spike from the rank 1 update to w. */

    i__1 = *m;
    for (i__ = 1; i__ <= i__1; ++i__) {
        w[i__] += v[*n] * u[i__];
        /* L80: */
    }

    /*     eliminate the spike. */

    *sing = FALSE_;
    if (nm1 < 1) {
        goto L140;
    }
    i__1 = nm1;
    for (j = 1; j <= i__1; ++j) {
        if (w[j] == zero) {
            goto L120;
        }

        /*        determine a givens rotation which eliminates the */
        /*        j-th element of the spike. */

        if ((d__1 = s[jj], abs(d__1)) >= (d__2 = w[j], abs(d__2))) {
            goto L90;
        }
        cotan = s[jj] / w[j];
        /* Computing 2nd power */
        d__1 = cotan;
        sin__ = p5 / sqrt(p25 + p25 * (d__1 * d__1));
        cos__ = sin__ * cotan;
        tau = one;
        if (abs(cos__) * giant > one) {
            tau = one / cos__;
        }
        goto L100;
L90:
        tan__ = w[j] / s[jj];
        /* Computing 2nd power */
        d__1 = tan__;
        cos__ = p5 / sqrt(p25 + p25 * (d__1 * d__1));
        sin__ = cos__ * tan__;
        tau = sin__;
L100:

        /*        apply the transformation to s and reduce the spike in w. */

        l = jj;
        i__2 = *m;
        for (i__ = j; i__ <= i__2; ++i__) {
            temp = cos__ * s[l] + sin__ * w[i__];
            w[i__] = -sin__ * s[l] + cos__ * w[i__];
            s[l] = temp;
            ++l;
            /* L110: */
        }

        /*        store the information necessary to recover the */
        /*        givens rotation. */

        w[j] = tau;
L120:

        /*        test for zero diagonal elements in the output s. */

        if (s[jj] == zero) {
            *sing = TRUE_;
        }
        jj += *m - j + 1;
        /* L130: */
    }
L140:

    /*     move w back into the last column of the output s. */

    l = jj;
    i__1 = *m;
    for (i__ = *n; i__ <= i__1; ++i__) {
        s[l] = w[i__];
        ++l;
        /* L150: */
    }
    if (s[jj] == zero) {
        *sing = TRUE_;
    }
    return 0;

    /*     last card of subroutine r1updt. */

} /* r1updt_ */
예제 #4
0
/*     ********** */
/* Main program */ int MAIN__(void)
{
    /* Initialized data */

    static integer nread = 5;
    static integer nwrite = 6;
    static doublereal one = 1.;
    static doublereal ten = 10.;

    /* Format strings */
    static char fmt_50[] = "(3i5)";
    static char fmt_60[] = "(////5x,\002 PROBLEM\002,i5,5x,\002 DIMENSION"
	    "\002,i5,5x//)";
    static char fmt_70[] = "(5x,\002 INITIAL L2 NORM OF THE RESIDUALS\002,d1"
	    "5.7//5x,\002 FINAL L2 NORM OF THE RESIDUALS  \002,d15.7//5x,\002"
	    " NUMBER OF FUNCTION EVALUATIONS  \002,i10//5x,\002 EXIT PARAMETER"
	    "\002,18x,i10//5x,\002 FINAL APPROXIMATE SOLUTION\002//(5x,5d15.7"
	    "))";
    static char fmt_80[] = "(\0021SUMMARY OF \002,i3,\002 CALLS TO HYBRD1"
	    "\002/)";
    static char fmt_90[] = "(\002 NPROB   N    NFEV  INFO  FINAL L2 NORM\002"
	    "/)";
    static char fmt_100[] = "(i4,i6,i7,i6,1x,d15.7)";

    /* System generated locals */
    integer i__1, i__2;

    /* Builtin functions */
    double sqrt(doublereal);
    integer s_rsfe(cilist *), do_fio(integer *, char *, ftnlen), e_rsfe(void),
	     s_wsfe(cilist *), e_wsfe(void);
    /* Subroutine */ int s_stop(char *, ftnlen);

    /* Local variables */
    static integer i__, k, n;
    static doublereal x[40];
    static integer ic, na[60], nf[60];
    static doublereal wa[2660];
    static integer np[60], nx[60];
    extern /* Subroutine */ int fcn_();
    static doublereal fnm[60];
    static integer lwa;
    static doublereal tol, fvec[40];
    static integer info;
    extern doublereal enorm_(integer *, doublereal *);
    extern /* Subroutine */ int hybrd1_(U_fp, integer *, doublereal *, 
	    doublereal *, doublereal *, integer *, doublereal *, integer *);
    static doublereal fnorm1, fnorm2;
    extern /* Subroutine */ int vecfcn_(integer *, doublereal *, doublereal *,
	     integer *);
    static doublereal factor;
    extern doublereal dpmpar_(integer *);
    static integer ntries;
    extern /* Subroutine */ int initpt_(integer *, doublereal *, integer *, 
	    doublereal *);

    /* Fortran I/O blocks */
    static cilist io___8 = { 0, 0, 0, fmt_50, 0 };
    static cilist io___16 = { 0, 0, 0, fmt_60, 0 };
    static cilist io___25 = { 0, 0, 0, fmt_70, 0 };
    static cilist io___27 = { 0, 0, 0, fmt_80, 0 };
    static cilist io___28 = { 0, 0, 0, fmt_90, 0 };
    static cilist io___29 = { 0, 0, 0, fmt_100, 0 };



/*     LOGICAL INPUT UNIT IS ASSUMED TO BE NUMBER 5. */
/*     LOGICAL OUTPUT UNIT IS ASSUMED TO BE NUMBER 6. */


    tol = sqrt(dpmpar_(&c__1));
    lwa = 2660;
    ic = 0;
L10:
    io___8.ciunit = nread;
    s_rsfe(&io___8);
    do_fio(&c__1, (char *)&refnum_1.nprob, (ftnlen)sizeof(integer));
    do_fio(&c__1, (char *)&n, (ftnlen)sizeof(integer));
    do_fio(&c__1, (char *)&ntries, (ftnlen)sizeof(integer));
    e_rsfe();
    if (refnum_1.nprob <= 0) {
	goto L30;
    }
    factor = one;
    i__1 = ntries;
    for (k = 1; k <= i__1; ++k) {
	++ic;
	initpt_(&n, x, &refnum_1.nprob, &factor);
	vecfcn_(&n, x, fvec, &refnum_1.nprob);
	fnorm1 = enorm_(&n, fvec);
	io___16.ciunit = nwrite;
	s_wsfe(&io___16);
	do_fio(&c__1, (char *)&refnum_1.nprob, (ftnlen)sizeof(integer));
	do_fio(&c__1, (char *)&n, (ftnlen)sizeof(integer));
	e_wsfe();
	refnum_1.nfev = 0;
	hybrd1_((U_fp)fcn_, &n, x, fvec, &tol, &info, wa, &lwa);
	fnorm2 = enorm_(&n, fvec);
	np[ic - 1] = refnum_1.nprob;
	na[ic - 1] = n;
	nf[ic - 1] = refnum_1.nfev;
	nx[ic - 1] = info;
	fnm[ic - 1] = fnorm2;
	io___25.ciunit = nwrite;
	s_wsfe(&io___25);
	do_fio(&c__1, (char *)&fnorm1, (ftnlen)sizeof(doublereal));
	do_fio(&c__1, (char *)&fnorm2, (ftnlen)sizeof(doublereal));
	do_fio(&c__1, (char *)&refnum_1.nfev, (ftnlen)sizeof(integer));
	do_fio(&c__1, (char *)&info, (ftnlen)sizeof(integer));
	i__2 = n;
	for (i__ = 1; i__ <= i__2; ++i__) {
	    do_fio(&c__1, (char *)&x[i__ - 1], (ftnlen)sizeof(doublereal));
	}
	e_wsfe();
	factor = ten * factor;
/* L20: */
    }
    goto L10;
L30:
    io___27.ciunit = nwrite;
    s_wsfe(&io___27);
    do_fio(&c__1, (char *)&ic, (ftnlen)sizeof(integer));
    e_wsfe();
    io___28.ciunit = nwrite;
    s_wsfe(&io___28);
    e_wsfe();
    i__1 = ic;
    for (i__ = 1; i__ <= i__1; ++i__) {
	io___29.ciunit = nwrite;
	s_wsfe(&io___29);
	do_fio(&c__1, (char *)&np[i__ - 1], (ftnlen)sizeof(integer));
	do_fio(&c__1, (char *)&na[i__ - 1], (ftnlen)sizeof(integer));
	do_fio(&c__1, (char *)&nf[i__ - 1], (ftnlen)sizeof(integer));
	do_fio(&c__1, (char *)&nx[i__ - 1], (ftnlen)sizeof(integer));
	do_fio(&c__1, (char *)&fnm[i__ - 1], (ftnlen)sizeof(doublereal));
	e_wsfe();
/* L40: */
    }
    s_stop("", (ftnlen)0);

/*     LAST CARD OF DRIVER. */

    return 0;
} /* MAIN__ */
예제 #5
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_ */
예제 #6
0
/* 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;

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

    /* Local variables */
    static integer i__, j, k, jp1;
    static doublereal sum;
    static integer kmax;
    static doublereal temp;
    static integer minmn;
    extern doublereal enorm_(integer *, doublereal *);
    static doublereal epsmch;
    extern doublereal dpmpar_(integer *);
    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 = 1 + 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_ */
예제 #7
0
파일: lmdif.c 프로젝트: frsfnrrg/qtgr
/* 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;

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

    /* Local variables */
    static doublereal h__;
    static integer i__, j;
    static doublereal eps, temp, epsmch;
    extern doublereal dpmpar_(integer *);

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

/*     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_ */
예제 #8
0
파일: lmdif.c 프로젝트: frsfnrrg/qtgr
/* 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;

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

    /* 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;
    extern doublereal enorm_(integer *, doublereal *);
    static doublereal gnorm;
    extern doublereal dpmpar_(integer *);
    static doublereal dxnorm;
    extern /* Subroutine */ int qrsolv_(integer *, doublereal *, integer *, 
	    integer *, doublereal *, doublereal *, doublereal *, doublereal *,
	     doublereal *);

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

/*     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_ */
예제 #9
0
파일: qrfac.c 프로젝트: 151706061/ITK
/*<       subroutine qrfac(m,n,a,lda,pivot,ipvt,lipvt,rdiag,acnorm,wa) >*/
/* 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.; /* constant */
    static doublereal p05 = .05; /* constant */
    static doublereal zero = 0.; /* constant */

    /* System generated locals */
    integer a_dim1, a_offset, i__1, i__2, i__3;
    doublereal d__1, d__2, d__3;

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

    /* Local variables */
    integer i__, j, k, jp1;
    doublereal sum;
    integer kmax;
    doublereal temp;
    integer minmn;
    extern doublereal enorm_(integer *, doublereal *);
    doublereal epsmch;
    extern doublereal dpmpar_(integer *);
    doublereal ajnorm;

    (void)lipvt;

/*<       integer m,n,lda,lipvt >*/
/*<       integer ipvt(lipvt) >*/
/*<       logical pivot >*/
/*<       double precision a(lda,n),rdiag(n),acnorm(n),wa(n) >*/
/*     ********** */

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

/*     ********** */
/*<       integer i,j,jp1,k,kmax,minmn >*/
/*<       double precision ajnorm,epsmch,one,p05,sum,temp,zero >*/
/*<       double precision dpmpar,enorm >*/
/*<       data one,p05,zero /1.0d0,5.0d-2,0.0d0/ >*/
    /* Parameter adjustments */
    --wa;
    --acnorm;
    --rdiag;
    a_dim1 = *lda;
    a_offset = 1 + a_dim1;
    a -= a_offset;
    --ipvt;

    /* Function Body */

/*     epsmch is the machine precision. */

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

/*     compute the initial column norms and initialize several arrays. */

/*<       do 10 j = 1, n >*/
    i__1 = *n;
    for (j = 1; j <= i__1; ++j) {
/*<          acnorm(j) = enorm(m,a(1,j)) >*/
        acnorm[j] = enorm_(m, &a[j * a_dim1 + 1]);
/*<          rdiag(j) = acnorm(j) >*/
        rdiag[j] = acnorm[j];
/*<          wa(j) = rdiag(j) >*/
        wa[j] = rdiag[j];
/*<          if (pivot) ipvt(j) = j >*/
        if (*pivot) {
            ipvt[j] = j;
        }
/*<    10    continue >*/
/* L10: */
    }

/*     reduce a to r with householder transformations. */

/*<       minmn = min0(m,n) >*/
    minmn = min(*m,*n);
/*<       do 110 j = 1, minmn >*/
    i__1 = minmn;
    for (j = 1; j <= i__1; ++j) {
/*<          if (.not.pivot) go to 40 >*/
        if (! (*pivot)) {
            goto L40;
        }

/*        bring the column of largest norm into the pivot position. */

/*<          kmax = j >*/
        kmax = j;
/*<          do 20 k = j, n >*/
        i__2 = *n;
        for (k = j; k <= i__2; ++k) {
/*<             if (rdiag(k) .gt. rdiag(kmax)) kmax = k >*/
            if (rdiag[k] > rdiag[kmax]) {
                kmax = k;
            }
/*<    20       continue >*/
/* L20: */
        }
/*<          if (kmax .eq. j) go to 40 >*/
        if (kmax == j) {
            goto L40;
        }
/*<          do 30 i = 1, m >*/
        i__2 = *m;
        for (i__ = 1; i__ <= i__2; ++i__) {
/*<             temp = a(i,j) >*/
            temp = a[i__ + j * a_dim1];
/*<             a(i,j) = a(i,kmax) >*/
            a[i__ + j * a_dim1] = a[i__ + kmax * a_dim1];
/*<             a(i,kmax) = temp >*/
            a[i__ + kmax * a_dim1] = temp;
/*<    30       continue >*/
/* L30: */
        }
/*<          rdiag(kmax) = rdiag(j) >*/
        rdiag[kmax] = rdiag[j];
/*<          wa(kmax) = wa(j) >*/
        wa[kmax] = wa[j];
/*<          k = ipvt(j) >*/
        k = ipvt[j];
/*<          ipvt(j) = ipvt(kmax) >*/
        ipvt[j] = ipvt[kmax];
/*<          ipvt(kmax) = k >*/
        ipvt[kmax] = k;
/*<    40    continue >*/
L40:

/*        compute the householder transformation to reduce the */
/*        j-th column of a to a multiple of the j-th unit vector. */

/*<          ajnorm = enorm(m-j+1,a(j,j)) >*/
        i__2 = *m - j + 1;
        ajnorm = enorm_(&i__2, &a[j + j * a_dim1]);
/*<          if (ajnorm .eq. zero) go to 100 >*/
        if (ajnorm == zero) {
            goto L100;
        }
/*<          if (a(j,j) .lt. zero) ajnorm = -ajnorm >*/
        if (a[j + j * a_dim1] < zero) {
            ajnorm = -ajnorm;
        }
/*<          do 50 i = j, m >*/
        i__2 = *m;
        for (i__ = j; i__ <= i__2; ++i__) {
/*<             a(i,j) = a(i,j)/ajnorm >*/
            a[i__ + j * a_dim1] /= ajnorm;
/*<    50       continue >*/
/* L50: */
        }
/*<          a(j,j) = a(j,j) + one >*/
        a[j + j * a_dim1] += one;

/*        apply the transformation to the remaining columns */
/*        and update the norms. */

/*<          jp1 = j + 1 >*/
        jp1 = j + 1;
/*<          if (n .lt. jp1) go to 100 >*/
        if (*n < jp1) {
            goto L100;
        }
/*<          do 90 k = jp1, n >*/
        i__2 = *n;
        for (k = jp1; k <= i__2; ++k) {
/*<             sum = zero >*/
            sum = zero;
/*<             do 60 i = j, m >*/
            i__3 = *m;
            for (i__ = j; i__ <= i__3; ++i__) {
/*<                sum = sum + a(i,j)*a(i,k) >*/
                sum += a[i__ + j * a_dim1] * a[i__ + k * a_dim1];
/*<    60          continue >*/
/* L60: */
            }
/*<             temp = sum/a(j,j) >*/
            temp = sum / a[j + j * a_dim1];
/*<             do 70 i = j, m >*/
            i__3 = *m;
            for (i__ = j; i__ <= i__3; ++i__) {
/*<                a(i,k) = a(i,k) - temp*a(i,j) >*/
                a[i__ + k * a_dim1] -= temp * a[i__ + j * a_dim1];
/*<    70          continue >*/
/* L70: */
            }
/*<             if (.not.pivot .or. rdiag(k) .eq. zero) go to 80 >*/
            if (! (*pivot) || rdiag[k] == zero) {
                goto L80;
            }
/*<             temp = a(j,k)/rdiag(k) >*/
            temp = a[j + k * a_dim1] / rdiag[k];
/*<             rdiag(k) = rdiag(k)*dsqrt(dmax1(zero,one-temp**2)) >*/
/* 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)));
/*<             if (p05*(rdiag(k)/wa(k))**2 .gt. epsmch) go to 80 >*/
/* Computing 2nd power */
            d__1 = rdiag[k] / wa[k];
            if (p05 * (d__1 * d__1) > epsmch) {
                goto L80;
            }
/*<             rdiag(k) = enorm(m-j,a(jp1,k)) >*/
            i__3 = *m - j;
            rdiag[k] = enorm_(&i__3, &a[jp1 + k * a_dim1]);
/*<             wa(k) = rdiag(k) >*/
            wa[k] = rdiag[k];
/*<    80       continue >*/
L80:
/*<    90       continue >*/
/* L90: */
            ;
        }
/*<   100    continue >*/
L100:
/*<          rdiag(j) = -ajnorm >*/
        rdiag[j] = -ajnorm;
/*<   110    continue >*/
/* L110: */
    }
/*<       return >*/
    return 0;

/*     last card of subroutine qrfac. */

/*<       end >*/
} /* qrfac_ */
예제 #10
0
파일: lmder.c 프로젝트: 151706061/ITK
/*<    >*/
/* 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_ */
예제 #11
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_ */
예제 #12
0
/* Subroutine */ int dogleg_(integer *n, doublereal *r__, integer *lr, 
	doublereal *diag, doublereal *qtb, doublereal *delta, doublereal *x, 
	doublereal *wa1, doublereal *wa2)
{
    /* Initialized data */

    static doublereal one = 1.;
    static doublereal zero = 0.;

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

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

    /* Local variables */
    static integer i__, j, k, l, jj, jp1;
    static doublereal sum, temp, alpha, bnorm;
    extern doublereal enorm_(integer *, doublereal *);
    static doublereal gnorm, qnorm, epsmch;
    extern doublereal dpmpar_(integer *);
    static doublereal sgnorm;

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

/*     subroutine dogleg */

/*     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 the convex combination x of the */
/*     gauss-newton and scaled gradient directions that minimizes */
/*     (a*x - b) in the least squares sense, subject to the */
/*     restriction that the euclidean norm of d*x be at most delta. */

/*     this subroutine completes the solution of the problem */
/*     if it is provided with the necessary information from the */
/*     qr factorization of a. that is, if a = q*r, where q has */
/*     orthogonal columns and r is an upper triangular matrix, */
/*     then dogleg expects the full upper triangle of r and */
/*     the first n components of (q transpose)*b. */

/*     the subroutine statement is */

/*       subroutine dogleg(n,r,lr,diag,qtb,delta,x,wa1,wa2) */

/*     where */

/*       n is a positive integer input variable set to the order of r. */

/*       r is an input array of length lr which must contain the upper */
/*         triangular matrix r stored by rows. */

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

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

/*       x is an output array of length n which contains the desired */
/*         convex combination of the gauss-newton direction and the */
/*         scaled gradient direction. */

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

/*     subprograms called */

/*       minpack-supplied ... dpmpar,enorm */

/*       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;
    --x;
    --qtb;
    --diag;
    --r__;

    /* Function Body */

/*     epsmch is the machine precision. */

    epsmch = dpmpar_(&c__1);

/*     first, calculate the gauss-newton direction. */

    jj = *n * (*n + 1) / 2 + 1;
    i__1 = *n;
    for (k = 1; k <= i__1; ++k) {
	j = *n - k + 1;
	jp1 = j + 1;
	jj -= k;
	l = jj + 1;
	sum = zero;
	if (*n < jp1) {
	    goto L20;
	}
	i__2 = *n;
	for (i__ = jp1; i__ <= i__2; ++i__) {
	    sum += r__[l] * x[i__];
	    ++l;
/* L10: */
	}
L20:
	temp = r__[jj];
	if (temp != zero) {
	    goto L40;
	}
	l = j;
	i__2 = j;
	for (i__ = 1; i__ <= i__2; ++i__) {
/* Computing MAX */
	    d__2 = temp, d__3 = (d__1 = r__[l], abs(d__1));
	    temp = max(d__2,d__3);
	    l = l + *n - i__;
/* L30: */
	}
	temp = epsmch * temp;
	if (temp == zero) {
	    temp = epsmch;
	}
L40:
	x[j] = (qtb[j] - sum) / temp;
/* L50: */
    }

/*     test whether the gauss-newton direction is acceptable. */

    i__1 = *n;
    for (j = 1; j <= i__1; ++j) {
	wa1[j] = zero;
	wa2[j] = diag[j] * x[j];
/* L60: */
    }
    qnorm = enorm_(n, &wa2[1]);
    if (qnorm <= *delta) {
	goto L140;
    }

/*     the gauss-newton direction is not acceptable. */
/*     next, calculate the scaled gradient direction. */

    l = 1;
    i__1 = *n;
    for (j = 1; j <= i__1; ++j) {
	temp = qtb[j];
	i__2 = *n;
	for (i__ = j; i__ <= i__2; ++i__) {
	    wa1[i__] += r__[l] * temp;
	    ++l;
/* L70: */
	}
	wa1[j] /= diag[j];
/* L80: */
    }

/*     calculate the norm of the scaled gradient and test for */
/*     the special case in which the scaled gradient is zero. */

    gnorm = enorm_(n, &wa1[1]);
    sgnorm = zero;
    alpha = *delta / qnorm;
    if (gnorm == zero) {
	goto L120;
    }

/*     calculate the point along the scaled gradient */
/*     at which the quadratic is minimized. */

    i__1 = *n;
    for (j = 1; j <= i__1; ++j) {
	wa1[j] = wa1[j] / gnorm / diag[j];
/* L90: */
    }
    l = 1;
    i__1 = *n;
    for (j = 1; j <= i__1; ++j) {
	sum = zero;
	i__2 = *n;
	for (i__ = j; i__ <= i__2; ++i__) {
	    sum += r__[l] * wa1[i__];
	    ++l;
/* L100: */
	}
	wa2[j] = sum;
/* L110: */
    }
    temp = enorm_(n, &wa2[1]);
    sgnorm = gnorm / temp / temp;

/*     test whether the scaled gradient direction is acceptable. */

    alpha = zero;
    if (sgnorm >= *delta) {
	goto L120;
    }

/*     the scaled gradient direction is not acceptable. */
/*     finally, calculate the point along the dogleg */
/*     at which the quadratic is minimized. */

    bnorm = enorm_(n, &qtb[1]);
    temp = bnorm / gnorm * (bnorm / qnorm) * (sgnorm / *delta);
/* Computing 2nd power */
    d__1 = sgnorm / *delta;
/* Computing 2nd power */
    d__2 = temp - *delta / qnorm;
/* Computing 2nd power */
    d__3 = *delta / qnorm;
/* Computing 2nd power */
    d__4 = sgnorm / *delta;
    temp = temp - *delta / qnorm * (d__1 * d__1) + sqrt(d__2 * d__2 + (one - 
	    d__3 * d__3) * (one - d__4 * d__4));
/* Computing 2nd power */
    d__1 = sgnorm / *delta;
    alpha = *delta / qnorm * (one - d__1 * d__1) / temp;
L120:

/*     form appropriate convex combination of the gauss-newton */
/*     direction and the scaled gradient direction. */

    temp = (one - alpha) * min(sgnorm,*delta);
    i__1 = *n;
    for (j = 1; j <= i__1; ++j) {
	x[j] = temp * wa1[j] + alpha * x[j];
/* L130: */
    }
L140:
    return 0;

/*     last card of subroutine dogleg. */

} /* dogleg_ */
예제 #13
0
/* Subroutine */ void chkder_(const int *m, const int *n, const double *x, 
	double *fvec, double *fjac, const int *ldfjac, double *xp, 
	double *fvecp, const int *mode, double *err)
{
    /* Initialized data */

    const int c__1 = 1;

    /* System generated locals */
    int fjac_dim1, fjac_offset, i__1, i__2;

    /* Local variables */
    int i__, j;
    double eps, epsf, temp, epsmch;
    double epslog;

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

/*     subroutine chkder */

/*     this subroutine checks the gradients of m nonlinear functions */
/*     in n variables, evaluated at a point x, for consistency with */
/*     the functions themselves. the user must call chkder twice, */
/*     first with mode = 1 and then with mode = 2. */

/*     mode = 1. on input, x must contain the point of evaluation. */
/*               on output, xp is set to a neighboring point. */

/*     mode = 2. on input, fvec must contain the functions and the */
/*                         rows of fjac must contain the gradients */
/*                         of the respective functions each evaluated */
/*                         at x, and fvecp must contain the functions */
/*                         evaluated at xp. */
/*               on output, err contains measures of correctness of */
/*                          the respective gradients. */

/*     the subroutine does not perform reliably if cancellation or */
/*     rounding errors cause a severe loss of significance in the */
/*     evaluation of a function. therefore, none of the components */
/*     of x should be unusually small (in particular, zero) or any */
/*     other value which may cause loss of significance. */

/*     the subroutine statement is */

/*       subroutine chkder(m,n,x,fvec,fjac,ldfjac,xp,fvecp,mode,err) */

/*     where */

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

/*       x is an input array of length n. */

/*       fvec is an array of length m. on input when mode = 2, */
/*         fvec must contain the functions evaluated at x. */

/*       fjac is an m by n array. on input when mode = 2, */
/*         the rows of fjac must contain the gradients of */
/*         the respective functions evaluated at x. */

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

/*       xp is an array of length n. on output when mode = 1, */
/*         xp is set to a neighboring point of x. */

/*       fvecp is an array of length m. on input when mode = 2, */
/*         fvecp must contain the functions evaluated at xp. */

/*       mode is an integer input variable set to 1 on the first call */
/*         and 2 on the second. other values of mode are equivalent */
/*         to mode = 1. */

/*       err is an array of length m. on output when mode = 2, */
/*         err contains measures of correctness of the respective */
/*         gradients. if there is no severe loss of significance, */
/*         then if err(i) is 1.0 the i-th gradient is correct, */
/*         while if err(i) is 0.0 the i-th gradient is incorrect. */
/*         for values of err between 0.0 and 1.0, the categorization */
/*         is less certain. in general, a value of err(i) greater */
/*         than 0.5 indicates that the i-th gradient is probably */
/*         correct, while a value of err(i) less than 0.5 indicates */
/*         that the i-th gradient is probably incorrect. */

/*     subprograms called */

/*       minpack supplied ... dpmpar */

/*       fortran supplied ... dabs,dlog10,dsqrt */

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

/*     ********** */
    /* Parameter adjustments */
    --err;
    --fvecp;
    --fvec;
    --xp;
    --x;
    fjac_dim1 = *ldfjac;
    fjac_offset = 1 + fjac_dim1 * 1;
    fjac -= fjac_offset;

    /* Function Body */

/*     epsmch is the machine precision. */

    epsmch = dpmpar_(&c__1);

    eps = sqrt(epsmch);

    if (*mode == 2) {
	goto L20;
    }

/*        mode = 1. */

    i__1 = *n;
    for (j = 1; j <= i__1; ++j) {
	temp = eps * fabs(x[j]);
	if (temp == 0.) {
	    temp = eps;
	}
	xp[j] = x[j] + temp;
/* L10: */
    }
    /* goto L70; */
    return;
L20:

/*        mode = 2. */

    epsf = factor * epsmch;
    epslog = log10e * log(eps);
    i__1 = *m;
    for (i__ = 1; i__ <= i__1; ++i__) {
	err[i__] = 0.;
/* L30: */
    }
    i__1 = *n;
    for (j = 1; j <= i__1; ++j) {
	temp = fabs(x[j]);
	if (temp == 0.) {
	    temp = 1.;
	}
	i__2 = *m;
	for (i__ = 1; i__ <= i__2; ++i__) {
	    err[i__] += temp * fjac[i__ + j * fjac_dim1];
/* L40: */
	}
/* L50: */
    }
    i__1 = *m;
    for (i__ = 1; i__ <= i__1; ++i__) {
	temp = 1.;
	if (fvec[i__] != 0. && fvecp[i__] != 0. && fabs(fvecp[i__] - 
		fvec[i__]) >= epsf * fabs(fvec[i__]))
		 {
	    temp = eps * fabs((fvecp[i__] - fvec[i__]) / eps - err[i__]) 
		    / (fabs(fvec[i__]) +
                       fabs(fvecp[i__]));
	}
	err[i__] = 1.;
	if (temp > epsmch && temp < eps) {
	    err[i__] = (log10e * log(temp) - epslog) / epslog;
	}
	if (temp >= eps) {
	    err[i__] = 0.;
	}
/* L60: */
    }
/* L70: */

    /* return 0; */

/*     last card of subroutine chkder. */

} /* chkder_ */