锐单电子商城 , 一站式电子元器件采购平台!
  • 电话:400-990-0325

LMDIF_函数源码

时间:2023-10-23 18:37:01 l300继电器

函数源码:

/* lmdif.f -- translated by f2c (version 20020621). You must link the resulting object file with the libraries: -lf2c -lm (in that order) */  #include "minpack.h" #include  #include "minpackP.h"   __minpack_attr__ void __minpack_func__(lmdif)(__minpack_decl_fcn_mn__ const int *m, const int *n, real *x,   real *fvec, const real *ftol, const real *xtol, const real *  gtol, const int *maxfev, const real *epsfcn, real *diag, const int *  mode, const real *factor, const int *nprint, int *info, int *  nfev, real *fjac, const int *ldfjac, int *ipvt, real *  qtf, real *wa1, real *wa2, real *wa3, real *  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;
    real d__1, d__2, d__3;

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

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

/* subroutine lmdif */

/* the purpose of lmdif is to minimize the sum of the squares of */
/* m nonlinear functions in n variables by a modification of */
/* the levenberg-marquardt algorithm. the user must provide a */
/* subroutine which calculates the functions. the jacobian is */
/* then calculated by a forward-difference approximation. */

/* the subroutine statement is */

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

/* where */

/* fcn is the name of the user-supplied subroutine which */
/* calculates the functions. fcn must be declared */
/* in an external statement in the user calling */
/* program, and should be written as follows. */

/* subroutine fcn(m,n,x,fvec,iflag) */
/* integer m,n,iflag */
/* double precision x(n),fvec(m) */
/* ---------- */
/* calculate the functions at x and */
/* return this vector in fvec. */
/* ---------- */
/* return */
/* end */

/* the value of iflag should not be changed by fcn unless */
/* the user wants to terminate execution of lmdif. */
/* in this case set iflag to a negative integer. */

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

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

/* x is an array of length n. on input x must contain */
/* an initial estimate of the solution vector. on output x */
/* contains the final estimate of the solution vector. */

/* fvec is an output array of length m which contains */
/* the functions evaluated at the output x. */

/* ftol is a nonnegative input variable. termination */
/* occurs when both the actual and predicted relative */
/* reductions in the sum of squares are at most ftol. */
/* therefore, ftol measures the relative error desired */
/* in the sum of squares. */

/* xtol is a nonnegative input variable. termination */
/* occurs when the relative error between two consecutive */
/* iterates is at most xtol. therefore, xtol measures the */
/* relative error desired in the approximate solution. */

/* gtol is a nonnegative input variable. termination */
/* occurs when the cosine of the angle between fvec and */
/* any column of the jacobian is at most gtol in absolute */
/* value. therefore, gtol measures the orthogonality */
/* desired between the function vector and the columns */
/* of the jacobian. */

/* maxfev is a positive integer input variable. termination */
/* occurs when the number of calls to fcn is at least */
/* maxfev by the end of an iteration. */

/* epsfcn is an input variable used in determining a suitable */
/* step length for the forward-difference approximation. this */
/* approximation assumes that the relative errors in the */
/* functions are of the order of epsfcn. if epsfcn is less */
/* than the machine precision, it is assumed that the relative */
/* errors in the functions are of the order of the machine */
/* precision. */

/* diag is an array of length n. if mode = 1 (see */
/* below), diag is internally set. if mode = 2, diag */
/* must contain positive entries that serve as */
/* multiplicative scale factors for the variables. */

/* mode is an integer input variable. if mode = 1, the */
/* variables will be scaled internally. if mode = 2, */
/* the scaling is specified by the input diag. other */
/* values of mode are equivalent to mode = 1. */

/* factor is a positive input variable used in determining the */
/* initial step bound. this bound is set to the product of */
/* factor and the euclidean norm of diag*x if nonzero, or else */
/* to factor itself. in most cases factor should lie in the */
/* interval (.1,100.). 100. is a generally recommended value. */

/* nprint is an integer input variable that enables controlled */
/* printing of iterates if it is positive. in this case, */
/* fcn is called with iflag = 0 at the beginning of the first */
/* iteration and every nprint iterations thereafter and */
/* immediately prior to return, with x and fvec available */
/* for printing. if nprint is not positive, no special calls */
/* of fcn with iflag = 0 are made. */

/* info is an integer output variable. if the user has */
/* terminated execution, info is set to the (negative) */
/* value of iflag. see description of fcn. otherwise, */
/* info is set as follows. */

/* info = 0 improper input parameters. */

/* info = 1 both actual and predicted relative reductions */
/* in the sum of squares are at most ftol. */

/* info = 2 relative error between two consecutive iterates */
/* is at most xtol. */

/* info = 3 conditions for info = 1 and info = 2 both hold. */

/* info = 4 the cosine of the angle between fvec and any */
/* column of the jacobian is at most gtol in */
/* absolute value. */

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

/* info = 6 ftol is too small. no further reduction in */
/* the sum of squares is possible. */

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

/* info = 8 gtol is too small. fvec is orthogonal to the */
/* columns of the jacobian to machine precision. */

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

/* fjac is an output m by n array. the upper n by n submatrix */
/* of fjac contains an upper triangular matrix r with */
/* diagonal elements of nonincreasing magnitude such that */

/* t t t */
/* p *(jac *jac)*p = r *r, */

/* where p is a permutation matrix and jac is the final */
/* calculated jacobian. column j of p is column ipvt(j) */
/* (see below) of the identity matrix. the lower trapezoidal */
/* part of fjac contains information generated during */
/* the computation of r. */

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

/* ipvt is an integer output array of length n. ipvt */
/* defines a permutation matrix p such that jac*p = q*r, */
/* where jac is the final calculated jacobian, q is */
/* orthogonal (not stored), and r is upper triangular */
/* with diagonal elements of nonincreasing magnitude. */
/* column j of p is column ipvt(j) of the identity matrix. */

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

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

/* wa4 is a work array of length m. */

/* subprograms called */

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

/* minpack-supplied ... dpmpar,enorm,fdjac2,lmpar,qrfac */

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

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

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

    /* Function Body */

/* epsmch is the machine precision. */

    epsmch = __minpack_func__(dpmpar)(&c__1);

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

/* check the input parameters for errors. */

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

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

    iflag = 1;
    fcn_mn(m, n, &x[1], &fvec[1], &iflag);
    *nfev = 1;
    if (iflag < 0) { 
       
	goto L300;
    }
    fnorm = __minpack_func__(enorm)(m, &fvec[1]);

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

    par = 0.;
    iter = 1;

/* beginning of the outer loop. */

L30:

/* calculate the jacobian matrix. */

    iflag = 2;
    __minpack_func__(fdjac2)(__minpack_param_fcn_mn__ m, n, &x[1], &fvec[1], &fjac[fjac_offset], ldfjac, &
	    iflag, epsfcn, &wa4[1]);
    *nfev += *n;
    if (iflag < 0) { 
       
	goto L300;
    }

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

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

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

    __minpack_func__(qrfac)(m, n, &fjac[fjac_offset], ldfjac, &c_true, &ipvt[1], n, &wa1[1], &
	    wa2[1], &wa3[1]);

/* on the first iteration and if mode is 1, scale according */
/* to the norms of the columns of the initial jacobian. */

    if (iter != 1) { 
       
	goto L80;
    }
    if (*mode == 2) { 
       
	goto L60;
    }
    i__1 = *n;
    for (j = 1; j <= i__1; ++j) { 
       
	diag[j] = wa2[j];
	if (wa2[j] == 0.) { 
       
	    diag[j] = 1.;
	}
/* L50: */
    }
L60:

/* on the first iteration, calculate the norm of the scaled x */
/* and initialize the step bound delta. */

    i__1 = *n;
    for (j = 1; j <= i__1; ++j) { 
       
	wa3[j] = diag[j] * x[j];
/* L70: */
    }
    xnorm = __minpack_func__(enorm)(n, &wa3[1]);
    delta = *factor * xnorm;
    if (delta == 0.) { 
       
	delta = *factor;
    }
L80:

/* form (q transpose)*fvec and store the first n components in */
/* qtf. */

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

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

    gnorm = 0.;
    if (fnorm == 0.) { 
       
	goto L170;
    }
    i__1 = *n;
    for (j = 1; j <= i__1; ++j) { 
       
	l = ipvt[j];
	if (wa2[l] == 0.) { 
       
	    goto L150;
	}
	sum = 0.;
	i__2 = j;
	for (i__ = 1; i__ <= i__2; ++i__) { 
       
	    sum += fjac[i__ + j * fjac_dim1] * (qtf[i__] / fnorm);
/* L140: */
	}
/* Computing MAX */
	d__2 = gnorm, d__3 = fabs(sum / wa2[l]);
	gnorm = max(d__2,d__3);
L150:
/* L160: */
	;
    }
L170:

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

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

/* rescale if necessary. */

    if (*mode == 2) { 
       
	goto L190;
    }
    i__1 = *n;
    for (j = 1; j <= i__1; ++j) { 
       
/* Computing MAX */
	d__1 = diag[j], d__2 = wa2[j];
	diag[j] = max(d__1,d__2);
/* L180: */
    }
L190:

/* beginning of the inner loop. */

L200:

/* determine the levenberg-marquardt parameter. */

    __minpack_func__(lmpar)(n, &fjac[fjac_offset], ldfjac, &ipvt[1], &diag[1], &qtf[1], &delta,
	     &par, &wa1[1], &wa2[1], &wa3[1], &wa4[1]);

/* store the direction p and x + p. calculate the norm of p. */

    i__1 = *n;
    for (j = 1; j <= i__1; ++j) { 
       
	wa1[j] = -wa1[j];
	wa2[j] = x[j] + wa1[j];
	wa3[j] = diag[j] * wa1[j];
/* L210: */
    }
    pnorm = __minpack_func__(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_mn(m, n, &wa2[1], &wa4[1], &iflag);
    ++(*nfev);
    if (iflag < 0) { 
       
	goto L300;
    }
    fnorm1 = __minpack_func__(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;
/* L220: */
	}
/* L230: */
    }
    temp1 = __minpack_func__(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 L240;
    }
    if (actred >= 0.) { 
       
	temp = p5;
    } else { 
       
	temp = p5 * dirder / (dirder + p5 * actred);
    }
    if (p1 * fnorm1 >= fnorm || temp < p1) { 
       
	temp = p1;
    }
/* Computing MIN */
    d__1 = delta, d__2 = pnorm / p1;
    delta = temp * min(d__1,d__2);
    par /= temp;
    goto L260;
L240:
    if (par != 0. && ratio < p75) { 
       
	goto L250;
    }
    delta = pnorm / p5;
    par = p5 * par;
L250:
L260:

/* test for successful iteration. */

    if (ratio < p0001) { 
       
	goto L290;
    }

/* successful iteration. update x, fvec, and their norms. */

    i__1 = *n;
    for (j = 1; j <= i__1; ++j) { 
       
	x[j] = wa2[j];
	wa2[j] = diag[j] * x[j];
/* L270: */
    }
    i__1 = *m;
    for (i__ = 1; i__ <= i__1; ++i__) { 
       
	fvec[i__] = wa4[i__];
/* L280: */
    }
    xnorm = __minpack_func__(enorm)(n, &wa2[1]);
    fnorm = fnorm1;
    ++iter;
L290:

/* tests for convergence. */

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

/* tests for termination and stringent tolerances. */

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

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

    if (ratio < p0001) { 
       
	goto L200;
    }

/* end of the outer loop. */

    goto L30;
L300:

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

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

/* last card of subroutine lmdif. */

} /* lmdif_ */


锐单商城拥有海量元器件数据手册IC替代型号,打造电子元器件IC百科大全!

相关文章