// These routines were translated from lbfgs.f by f2c (version 20030320) // and modified by Curtis Janssen. #ifdef __GNUC__ #pragma implementation #endif #include #include #include static inline double min(double a, double b) { return (a, 0); MCSearch::MCSearch(const Ref& keyval) : LineOpt(keyval) { } MCSearch::~MCSearch() { } void MCSearch::mcinit() { info_ = 0; // work area wa_.reset(new double[function()->dimension()->n()]); } void MCSearch::init(RefSCVector& direction) { LineOpt::init(direction); mcinit(); } void MCSearch::init(RefSCVector& direction, Ref function) { LineOpt::init(direction, function); mcinit(); } int MCSearch::update() { int n = function()->dimension()->n(); // function coordinate auto_vec x(new double[n]); function()->get_x()->convert(x.get()); // gradient auto_vec g(new double[n]); function()->gradient()->convert(g.get()); // function value double f = function()->value(); // step direction auto_vec s(new double[n]); search_direction_->convert(s.get()); // step size; double stp; stp = 1.0; // value tolerance double ftol; ftol = 1.0e-4; // the machine precision double xtol; xtol = DBL_EPSILON; // maximum number of function evaluations int maxfev = 20; // number of function evaluations int nfev = 0; // controls accuracy of line search routine gtol_ = 0.9; // minimum step size stpmin_ = DBL_EPSILON; // maximum step size stpmax_ = 1.0e20; mcsrch(&n, x.get(), &f,g.get(), s.get(), &stp, &ftol, &xtol, &maxfev, &info_, &nfev, wa_.get()); // INFO = 0 IMPROPER INPUT PARAMETERS. if (info_ == 0) { throw ProgrammingError("error in MCSearch: info == 0", __FILE__, __LINE__, class_desc()); } // INFO =-1 A RETURN IS MADE TO COMPUTE THE FUNCTION AND GRADIENT. if (info_ == -1) { RefSCVector new_x = function()->get_x()->copy(); new_x->assign(x.get()); function()->set_x(new_x); return 0; } // INFO = 1 THE SUFFICIENT DECREASE CONDITION AND THE // DIRECTIONAL DERIVATIVE CONDITION HOLD. if (info_ == 1) { return 1; } // INFO = 2 RELATIVE WIDTH OF THE INTERVAL OF UNCERTAINTY // IS AT MOST XTOL. if (info_ == 2) { throw AlgorithmException("error in MCSearch: info == 2", __FILE__, __LINE__, class_desc()); return 1; } // INFO = 3 NUMBER OF CALLS TO FCN HAS REACHED MAXFEV. if (info_ == 3) { throw ProgrammingError("error in MCSearch: info == 3", __FILE__, __LINE__, class_desc()); return 1; } // INFO = 4 THE STEP IS AT THE LOWER BOUND STPMIN. if (info_ == 4) { throw AlgorithmException("error in MCSearch: info == 4", __FILE__, __LINE__, class_desc()); return 1; } // INFO = 5 THE STEP IS AT THE UPPER BOUND STPMAX. if (info_ == 5) { throw AlgorithmException("error in MCSearch: info == 5", __FILE__, __LINE__, class_desc()); return 1; } // INFO = 6 ROUNDING ERRORS PREVENT FURTHER PROGRESS. // THERE MAY NOT BE A STEP WHICH SATISFIES THE // SUFFICIENT DECREASE AND CURVATURE CONDITIONS. // TOLERANCES MAY BE TOO SMALL. if (info_ == 6) { throw AlgorithmException("error in MCSearch: info == 6", __FILE__, __LINE__, class_desc()); return 1; } throw ProgrammingError("error in MCSearch: unknown info", __FILE__, __LINE__, class_desc()); return 0; } // ************************** // LINE SEARCH ROUTINE MCSRCH // ************************** void MCSearch::mcsrch(int *n, double *x, double *f, double *g, double *s, double *stp, double *ftol, double *xtol, int *maxfev, int *info, int *nfev, double *wa) { // Initialized data const double p5 = .5; const double p66 = .66; const double xtrapf = 4.; const double zero = 0.; // System generated locals int i__1; double d__1; // SUBROUTINE MCSRCH // A slight modification of the subroutine CSRCH of More' and Thuente. // The changes are to allow reverse communication, and do not affect // the performance of the routine. // THE PURPOSE OF MCSRCH IS TO FIND A STEP WHICH SATISFIES // A SUFFICIENT DECREASE CONDITION AND A CURVATURE CONDITION. // AT EACH STAGE THE SUBROUTINE UPDATES AN INTERVAL OF // UNCERTAINTY WITH ENDPOINTS STX AND STY. THE INTERVAL OF // UNCERTAINTY IS INITIALLY CHOSEN SO THAT IT CONTAINS A // MINIMIZER OF THE MODIFIED FUNCTION // F(X+STP*S) - F(X) - FTOL*STP*(GRADF(X)'S). // IF A STEP IS OBTAINED FOR WHICH THE MODIFIED FUNCTION // HAS A NONPOSITIVE FUNCTION VALUE AND NONNEGATIVE DERIVATIVE, // THEN THE INTERVAL OF UNCERTAINTY IS CHOSEN SO THAT IT // CONTAINS A MINIMIZER OF F(X+STP*S). // THE ALGORITHM IS DESIGNED TO FIND A STEP WHICH SATISFIES // THE SUFFICIENT DECREASE CONDITION // F(X+STP*S) .LE. F(X) + FTOL*STP*(GRADF(X)'S), // AND THE CURVATURE CONDITION // ABS(GRADF(X+STP*S)'S)) .LE. GTOL*ABS(GRADF(X)'S). // IF FTOL IS LESS THAN GTOL AND IF, FOR EXAMPLE, THE FUNCTION // IS BOUNDED BELOW, THEN THERE IS ALWAYS A STEP WHICH SATISFIES // BOTH CONDITIONS. IF NO STEP CAN BE FOUND WHICH SATISFIES BOTH // CONDITIONS, THEN THE ALGORITHM USUALLY STOPS WHEN ROUNDING // ERRORS PREVENT FURTHER PROGRESS. IN THIS CASE STP ONLY // SATISFIES THE SUFFICIENT DECREASE CONDITION. // THE SUBROUTINE STATEMENT IS // SUBROUTINE MCSRCH(N,X,F,G,S,STP,FTOL,XTOL, MAXFEV,INFO,NFEV,WA) // WHERE // N IS A POSITIVE INTEGER INPUT VARIABLE SET TO THE NUMBER // OF VARIABLES. // X IS AN ARRAY OF LENGTH N. ON INPUT IT MUST CONTAIN THE // BASE POINT FOR THE LINE SEARCH. ON OUTPUT IT CONTAINS // X + STP*S. // F IS A VARIABLE. ON INPUT IT MUST CONTAIN THE VALUE OF F // AT X. ON OUTPUT IT CONTAINS THE VALUE OF F AT X + STP*S. // G IS AN ARRAY OF LENGTH N. ON INPUT IT MUST CONTAIN THE // GRADIENT OF F AT X. ON OUTPUT IT CONTAINS THE GRADIENT // OF F AT X + STP*S. // S IS AN INPUT ARRAY OF LENGTH N WHICH SPECIFIES THE // SEARCH DIRECTION. // STP IS A NONNEGATIVE VARIABLE. ON INPUT STP CONTAINS AN // INITIAL ESTIMATE OF A SATISFACTORY STEP. ON OUTPUT // STP CONTAINS THE FINAL ESTIMATE. // FTOL AND GTOL ARE NONNEGATIVE INPUT VARIABLES. (In this reverse // communication implementation GTOL is defined in a COMMON // statement.) TERMINATION OCCURS WHEN THE SUFFICIENT DECREASE // CONDITION AND THE DIRECTIONAL DERIVATIVE CONDITION ARE // SATISFIED. // XTOL IS A NONNEGATIVE INPUT VARIABLE. TERMINATION OCCURS // WHEN THE RELATIVE WIDTH OF THE INTERVAL OF UNCERTAINTY // IS AT MOST XTOL. // STPMIN AND STPMAX ARE NONNEGATIVE INPUT VARIABLES WHICH // SPECIFY LOWER AND UPPER BOUNDS FOR THE STEP. (In this reverse // communication implementatin they are defined in a COMMON // statement). // 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. // INFO IS AN INTEGER OUTPUT VARIABLE SET AS FOLLOWS: // INFO = 0 IMPROPER INPUT PARAMETERS. // INFO =-1 A RETURN IS MADE TO COMPUTE THE FUNCTION AND GRADIENT. // INFO = 1 THE SUFFICIENT DECREASE CONDITION AND THE // DIRECTIONAL DERIVATIVE CONDITION HOLD. // INFO = 2 RELATIVE WIDTH OF THE INTERVAL OF UNCERTAINTY // IS AT MOST XTOL. // INFO = 3 NUMBER OF CALLS TO FCN HAS REACHED MAXFEV. // INFO = 4 THE STEP IS AT THE LOWER BOUND STPMIN. // INFO = 5 THE STEP IS AT THE UPPER BOUND STPMAX. // INFO = 6 ROUNDING ERRORS PREVENT FURTHER PROGRESS. // THERE MAY NOT BE A STEP WHICH SATISFIES THE // SUFFICIENT DECREASE AND CURVATURE CONDITIONS. // TOLERANCES MAY BE TOO SMALL. // NFEV IS AN INTEGER OUTPUT VARIABLE SET TO THE NUMBER OF // CALLS TO FCN. // WA IS A WORK ARRAY OF LENGTH N. // SUBPROGRAMS CALLED // MCSTEP // FORTRAN-SUPPLIED...ABS,MAX,MIN // ARGONNE NATIONAL LABORATORY. MINPACK PROJECT. JUNE 1983 // JORGE J. MORE', DAVID J. THUENTE // ********** // Parameter adjustments --wa; --s; --g; --x; // Function Body if (*info == -1) { goto L45; } infoc = 1; // CHECK THE INPUT PARAMETERS FOR ERRORS. if (*n <= 0 || *stp <= zero || *ftol < zero || gtol_ < zero || *xtol < zero || stpmin_ < zero || stpmax_ < stpmin_ || * maxfev <= 0) { return; } // COMPUTE THE INITIAL GRADIENT IN THE SEARCH DIRECTION // AND CHECK THAT S IS A DESCENT DIRECTION. dginit = zero; i__1 = *n; for (int j = 1; j <= i__1; ++j) { dginit += g[j] * s[j]; // L10: } if (dginit >= zero) { ExEnv::out0() << indent << "MCSearch: " << "The search direction is not a descent direction" << std::endl; return; } // INITIALIZE LOCAL VARIABLES. brackt = false; stage1 = true; *nfev = 0; finit = *f; dgtest = *ftol * dginit; width = stpmax_ - stpmin_; width1 = width / p5; i__1 = *n; for (int j = 1; j <= i__1; ++j) { wa[j] = x[j]; // L20: } // THE VARIABLES STX, FX, DGX CONTAIN THE VALUES OF THE STEP, // FUNCTION, AND DIRECTIONAL DERIVATIVE AT THE BEST STEP. // THE VARIABLES STY, FY, DGY CONTAIN THE VALUE OF THE STEP, // FUNCTION, AND DERIVATIVE AT THE OTHER ENDPOINT OF // THE INTERVAL OF UNCERTAINTY. // THE VARIABLES STP, F, DG CONTAIN THE VALUES OF THE STEP, // FUNCTION, AND DERIVATIVE AT THE CURRENT STEP. stx = zero; fx = finit; dgx = dginit; sty = zero; fy = finit; dgy = dginit; // START OF ITERATION. L30: // SET THE MINIMUM AND MAXIMUM STEPS TO CORRESPOND // TO THE PRESENT INTERVAL OF UNCERTAINTY. if (brackt) { stmin = min(stx,sty); stmax = max(stx,sty); } else { stmin = stx; stmax = *stp + xtrapf * (*stp - stx); } // FORCE THE STEP TO BE WITHIN THE BOUNDS STPMAX AND STPMIN. *stp = max(*stp,stpmin_); *stp = min(*stp,stpmax_); // IF AN UNUSUAL TERMINATION IS TO OCCUR THEN LET // STP BE THE LOWEST POINT OBTAINED SO FAR. if (brackt && (*stp <= stmin || *stp >= stmax) || *nfev >= *maxfev - 1 || infoc == 0 || brackt && stmax - stmin <= *xtol * stmax) { *stp = stx; } // EVALUATE THE FUNCTION AND GRADIENT AT STP // AND COMPUTE THE DIRECTIONAL DERIVATIVE. // We return to main program to obtain F and G. i__1 = *n; for (int j = 1; j <= i__1; ++j) { x[j] = wa[j] + *stp * s[j]; // L40: } *info = -1; return; L45: *info = 0; ++(*nfev); dg = zero; i__1 = *n; for (int j = 1; j <= i__1; ++j) { dg += g[j] * s[j]; // L50: } ftest1 = finit + *stp * dgtest; // TEST FOR CONVERGENCE. if (brackt && (*stp <= stmin || *stp >= stmax) || infoc == 0) { *info = 6; } if (*stp == stpmax_ && *f <= ftest1 && dg <= dgtest) { *info = 5; } if (*stp == stpmin_ && (*f > ftest1 || dg >= dgtest)) { *info = 4; } if (*nfev >= *maxfev) { *info = 3; } if (brackt && stmax - stmin <= *xtol * stmax) { *info = 2; } if (*f <= ftest1 && fabs(dg) <= gtol_ * (-dginit)) { *info = 1; } // CHECK FOR TERMINATION. if (*info != 0) { return; } // IN THE FIRST STAGE WE SEEK A STEP FOR WHICH THE MODIFIED // FUNCTION HAS A NONPOSITIVE VALUE AND NONNEGATIVE DERIVATIVE. if (stage1 && *f <= ftest1 && dg >= min(*ftol,gtol_) * dginit) { stage1 = false; } // A MODIFIED FUNCTION IS USED TO PREDICT THE STEP ONLY IF // WE HAVE NOT OBTAINED A STEP FOR WHICH THE MODIFIED // FUNCTION HAS A NONPOSITIVE FUNCTION VALUE AND NONNEGATIVE // DERIVATIVE, AND IF A LOWER FUNCTION VALUE HAS BEEN // OBTAINED BUT THE DECREASE IS NOT SUFFICIENT. if (stage1 && *f <= fx && *f > ftest1) { // DEFINE THE MODIFIED FUNCTION AND DERIVATIVE VALUES. fm = *f - *stp * dgtest; fxm = fx - stx * dgtest; fym = fy - sty * dgtest; dgm = dg - dgtest; dgxm = dgx - dgtest; dgym = dgy - dgtest; // CALL CSTEP TO UPDATE THE INTERVAL OF UNCERTAINTY // AND TO COMPUTE THE NEW STEP. mcstep(&stx, &fxm, &dgxm, &sty, &fym, &dgym, stp, &fm, &dgm, &brackt, &stmin, &stmax, &infoc); // RESET THE FUNCTION AND GRADIENT VALUES FOR F. fx = fxm + stx * dgtest; fy = fym + sty * dgtest; dgx = dgxm + dgtest; dgy = dgym + dgtest; } else { // CALL MCSTEP TO UPDATE THE INTERVAL OF UNCERTAINTY // AND TO COMPUTE THE NEW STEP. mcstep(&stx, &fx, &dgx, &sty, &fy, &dgy, stp, f, &dg, &brackt, & stmin, &stmax, &infoc); } // FORCE A SUFFICIENT DECREASE IN THE SIZE OF THE // INTERVAL OF UNCERTAINTY. if (brackt) { if ((d__1 = sty - stx, fabs(d__1)) >= p66 * width1) { *stp = stx + p5 * (sty - stx); } width1 = width; width = (d__1 = sty - stx, fabs(d__1)); } // END OF ITERATION. goto L30; // LAST LINE OF SUBROUTINE MCSRCH. } // mcsrch_ void MCSearch::mcstep(double *stx, double *fx, double *dx, double *sty, double *fy, double *dy, double *stp, double *fp, double *dp, bool *brackt, double *stpmin, double *stpmax, int *info) { // System generated locals double d__1, d__2, d__3; // SUBROUTINE MCSTEP // THE PURPOSE OF MCSTEP IS TO COMPUTE A SAFEGUARDED STEP FOR // A LINESEARCH AND TO UPDATE AN INTERVAL OF UNCERTAINTY FOR // A MINIMIZER OF THE FUNCTION. // THE PARAMETER STX CONTAINS THE STEP WITH THE LEAST FUNCTION // VALUE. THE PARAMETER STP CONTAINS THE CURRENT STEP. IT IS // ASSUMED THAT THE DERIVATIVE AT STX IS NEGATIVE IN THE // DIRECTION OF THE STEP. IF BRACKT IS SET TRUE THEN A // MINIMIZER HAS BEEN BRACKETED IN AN INTERVAL OF UNCERTAINTY // WITH ENDPOINTS STX AND STY. // THE SUBROUTINE STATEMENT IS // SUBROUTINE MCSTEP(STX,FX,DX,STY,FY,DY,STP,FP,DP,BRACKT, // STPMIN,STPMAX,INFO) // WHERE // STX, FX, AND DX ARE VARIABLES WHICH SPECIFY THE STEP, // THE FUNCTION, AND THE DERIVATIVE AT THE BEST STEP OBTAINED // SO FAR. THE DERIVATIVE MUST BE NEGATIVE IN THE DIRECTION // OF THE STEP, THAT IS, DX AND STP-STX MUST HAVE OPPOSITE // SIGNS. ON OUTPUT THESE PARAMETERS ARE UPDATED APPROPRIATELY. // STY, FY, AND DY ARE VARIABLES WHICH SPECIFY THE STEP, // THE FUNCTION, AND THE DERIVATIVE AT THE OTHER ENDPOINT OF // THE INTERVAL OF UNCERTAINTY. ON OUTPUT THESE PARAMETERS ARE // UPDATED APPROPRIATELY. // STP, FP, AND DP ARE VARIABLES WHICH SPECIFY THE STEP, // THE FUNCTION, AND THE DERIVATIVE AT THE CURRENT STEP. // IF BRACKT IS SET TRUE THEN ON INPUT STP MUST BE // BETWEEN STX AND STY. ON OUTPUT STP IS SET TO THE NEW STEP. // BRACKT IS A LOGICAL VARIABLE WHICH SPECIFIES IF A MINIMIZER // HAS BEEN BRACKETED. IF THE MINIMIZER HAS NOT BEEN BRACKETED // THEN ON INPUT BRACKT MUST BE SET FALSE. IF THE MINIMIZER // IS BRACKETED THEN ON OUTPUT BRACKT IS SET TRUE. // STPMIN AND STPMAX ARE INPUT VARIABLES WHICH SPECIFY LOWER // AND UPPER BOUNDS FOR THE STEP. // INFO IS AN INTEGER OUTPUT VARIABLE SET AS FOLLOWS: // IF INFO = 1,2,3,4,5, THEN THE STEP HAS BEEN COMPUTED // ACCORDING TO ONE OF THE FIVE CASES BELOW. OTHERWISE // INFO = 0, AND THIS INDICATES IMPROPER INPUT PARAMETERS. // SUBPROGRAMS CALLED // FORTRAN-SUPPLIED ... ABS,MAX,MIN,SQRT // ARGONNE NATIONAL LABORATORY. MINPACK PROJECT. JUNE 1983 // JORGE J. MORE', DAVID J. THUENTE *info = 0; // CHECK THE INPUT PARAMETERS FOR ERRORS. if (*brackt && (*stp <= min(*stx,*sty) || *stp >= max(*stx,*sty)) || *dx * (*stp - *stx) >= 0.f || *stpmax < *stpmin) { return; } // DETERMINE IF THE DERIVATIVES HAVE OPPOSITE SIGN. sgnd = *dp * (*dx / fabs(*dx)); // FIRST CASE. A HIGHER FUNCTION VALUE. // THE MINIMUM IS BRACKETED. IF THE CUBIC STEP IS CLOSER // TO STX THAN THE QUADRATIC STEP, THE CUBIC STEP IS TAKEN, // ELSE THE AVERAGE OF THE CUBIC AND QUADRATIC STEPS IS TAKEN. if (*fp > *fx) { *info = 1; bound = true; theta = (*fx - *fp) * 3 / (*stp - *stx) + *dx + *dp; // Computing MAX d__1 = fabs(theta), d__2 = fabs(*dx), d__1 = max(d__1,d__2), d__2 = fabs( *dp); s = max(d__1,d__2); // Computing 2nd power d__1 = theta / s; gamma = s * sqrt(d__1 * d__1 - *dx / s * (*dp / s)); if (*stp < *stx) { gamma = -gamma; } p = gamma - *dx + theta; q = gamma - *dx + gamma + *dp; r__ = p / q; stpc = *stx + r__ * (*stp - *stx); stpq = *stx + *dx / ((*fx - *fp) / (*stp - *stx) + *dx) / 2 * (*stp - *stx); if ((d__1 = stpc - *stx, fabs(d__1)) < (d__2 = stpq - *stx, fabs(d__2))) { stpf = stpc; } else { stpf = stpc + (stpq - stpc) / 2; } *brackt = true; // SECOND CASE. A LOWER FUNCTION VALUE AND DERIVATIVES OF // OPPOSITE SIGN. THE MINIMUM IS BRACKETED. IF THE CUBIC // STEP IS CLOSER TO STX THAN THE QUADRATIC (SECANT) STEP, // THE CUBIC STEP IS TAKEN, ELSE THE QUADRATIC STEP IS TAKEN. } else if (sgnd < 0.f) { *info = 2; bound = false; theta = (*fx - *fp) * 3 / (*stp - *stx) + *dx + *dp; // Computing MAX d__1 = fabs(theta), d__2 = fabs(*dx), d__1 = max(d__1,d__2), d__2 = fabs( *dp); s = max(d__1,d__2); // Computing 2nd power d__1 = theta / s; gamma = s * sqrt(d__1 * d__1 - *dx / s * (*dp / s)); if (*stp > *stx) { gamma = -gamma; } p = gamma - *dp + theta; q = gamma - *dp + gamma + *dx; r__ = p / q; stpc = *stp + r__ * (*stx - *stp); stpq = *stp + *dp / (*dp - *dx) * (*stx - *stp); if ((d__1 = stpc - *stp, fabs(d__1)) > (d__2 = stpq - *stp, fabs(d__2))) { stpf = stpc; } else { stpf = stpq; } *brackt = true; // THIRD CASE. A LOWER FUNCTION VALUE, DERIVATIVES OF THE // SAME SIGN, AND THE MAGNITUDE OF THE DERIVATIVE DECREASES. // THE CUBIC STEP IS ONLY USED IF THE CUBIC TENDS TO INFINITY // IN THE DIRECTION OF THE STEP OR IF THE MINIMUM OF THE CUBIC // IS BEYOND STP. OTHERWISE THE CUBIC STEP IS DEFINED TO BE // EITHER STPMIN OR STPMAX. THE QUADRATIC (SECANT) STEP IS ALSO // COMPUTED AND IF THE MINIMUM IS BRACKETED THEN THE THE STEP // CLOSEST TO STX IS TAKEN, ELSE THE STEP FARTHEST AWAY IS TAKEN. } else if (fabs(*dp) < fabs(*dx)) { *info = 3; bound = true; theta = (*fx - *fp) * 3 / (*stp - *stx) + *dx + *dp; // Computing MAX d__1 = fabs(theta), d__2 = fabs(*dx), d__1 = max(d__1,d__2), d__2 = fabs( *dp); s = max(d__1,d__2); // THE CASE GAMMA = 0 ONLY ARISES IF THE CUBIC DOES NOT TEND // TO INFINITY IN THE DIRECTION OF THE STEP. // Computing MAX // Computing 2nd power d__3 = theta / s; d__1 = 0., d__2 = d__3 * d__3 - *dx / s * (*dp / s); gamma = s * sqrt((max(d__1,d__2))); if (*stp > *stx) { gamma = -gamma; } p = gamma - *dp + theta; q = gamma + (*dx - *dp) + gamma; r__ = p / q; if (r__ < 0.f && gamma != 0.f) { stpc = *stp + r__ * (*stx - *stp); } else if (*stp > *stx) { stpc = *stpmax; } else { stpc = *stpmin; } stpq = *stp + *dp / (*dp - *dx) * (*stx - *stp); if (*brackt) { if ((d__1 = *stp - stpc, fabs(d__1)) < (d__2 = *stp - stpq, fabs( d__2))) { stpf = stpc; } else { stpf = stpq; } } else { if ((d__1 = *stp - stpc, fabs(d__1)) > (d__2 = *stp - stpq, fabs( d__2))) { stpf = stpc; } else { stpf = stpq; } } // FOURTH CASE. A LOWER FUNCTION VALUE, DERIVATIVES OF THE // SAME SIGN, AND THE MAGNITUDE OF THE DERIVATIVE DOES // NOT DECREASE. IF THE MINIMUM IS NOT BRACKETED, THE STEP // IS EITHER STPMIN OR STPMAX, ELSE THE CUBIC STEP IS TAKEN. } else { *info = 4; bound = false; if (*brackt) { theta = (*fp - *fy) * 3 / (*sty - *stp) + *dy + *dp; // Computing MAX d__1 = fabs(theta), d__2 = fabs(*dy), d__1 = max(d__1,d__2), d__2 = fabs(*dp); s = max(d__1,d__2); // Computing 2nd power d__1 = theta / s; gamma = s * sqrt(d__1 * d__1 - *dy / s * (*dp / s)); if (*stp > *sty) { gamma = -gamma; } p = gamma - *dp + theta; q = gamma - *dp + gamma + *dy; r__ = p / q; stpc = *stp + r__ * (*sty - *stp); stpf = stpc; } else if (*stp > *stx) { stpf = *stpmax; } else { stpf = *stpmin; } } // UPDATE THE INTERVAL OF UNCERTAINTY. THIS UPDATE DOES NOT // DEPEND ON THE NEW STEP OR THE CASE ANALYSIS ABOVE. if (*fp > *fx) { *sty = *stp; *fy = *fp; *dy = *dp; } else { if (sgnd < 0.) { *sty = *stx; *fy = *fx; *dy = *dx; } *stx = *stp; *fx = *fp; *dx = *dp; } // COMPUTE THE NEW STEP AND SAFEGUARD IT. stpf = min(*stpmax,stpf); stpf = max(*stpmin,stpf); *stp = stpf; if (*brackt && bound) { if (*sty > *stx) { // Computing MIN d__1 = *stx + (*sty - *stx) * .66; *stp = min(d__1,*stp); } else { // Computing MAX d__1 = *stx + (*sty - *stx) * .66; *stp = max(d__1,*stp); } } return; // LAST LINE OF SUBROUTINE MCSTEP. } // mcstep_ }