private static void dcsrch(double f, double g, ref double stp, double ftol,
double gtol, double xtol, double stpmin, double stpmax, ref string task,
int[] isave, int _isave_offset, double[] dsave, int _dsave_offset)
{
bool brackt = false;
int stage = 0;
double finit = 0.0d;
double ftest = 0.0d;
double fm = 0.0d;
double fx = 0.0d;
double fxm = 0.0d;
double fy = 0.0d;
double fym = 0.0d;
double ginit = 0.0d;
double gtest = 0.0d;
double gm = 0.0d;
double gx = 0.0d;
double gxm = 0.0d;
double gy = 0.0d;
double gym = 0.0d;
double stx = 0.0d;
double sty = 0.0d;
double stmin = 0.0d;
double stmax = 0.0d;
double width = 0.0d;
double width1 = 0.0d;
if ((task.StartsWith("START", StringComparison.OrdinalIgnoreCase)))
{
//
// Check the input arguments for errors.
//
if ((stp < stpmin))
{
task = "ERROR: STP .LT. STPMIN";
}
if ((stp > stpmax))
{
task = "ERROR: STP .GT. STPMAX";
}
if ((g >= 0.0))
{
task = "ERROR: INITIAL G .GE. ZERO";
}
if ((ftol < 0.0))
{
task = "ERROR: FTOL .LT. ZERO";
}
if ((gtol < 0.0))
{
task = "ERROR: GTOL .LT. ZERO";
}
if ((xtol < 0.0))
{
task = "ERROR: XTOL .LT. ZERO";
}
if ((stpmin < 0.0))
{
task = "ERROR: STPMIN .LT. ZERO";
}
if ((stpmax < stpmin))
{
task = "ERROR: STPMAX .LT. STPMIN";
}
//
// c Exit if there are errors on input.
//
if ((task.StartsWith("ERROR", StringComparison.OrdinalIgnoreCase)))
{
return;
}
//
// Initialize local variables.
//
brackt = false;
stage = 1;
finit = f;
ginit = g;
gtest = (ftol * ginit);
width = (stpmax - stpmin);
width1 = (width / 0.5);
//
// The variables stx, fx, gx contain the values of the step,
// function, and derivative at the best step.
// The variables sty, fy, gy contain the value of the step,
// function, and derivative at sty.
// The variables stp, f, g contain the values of the step,
// function, and derivative at stp.
//
stx = 0.0;
fx = finit;
gx = ginit;
sty = 0.0;
fy = finit;
gy = ginit;
stmin = 0.0;
stmax = (stp + (4.0 * stp));
task = "FG";
goto L1000;
}
else
{
//
// Restore local variables.
//
if ((isave[(1 - (1)) + _isave_offset] == 1))
{
brackt = true;
}
else
{
brackt = false;
}
stage = isave[(2 - (1)) + _isave_offset];
ginit = dsave[(1 - (1)) + _dsave_offset];
gtest = dsave[(2 - (1)) + _dsave_offset];
gx = dsave[(3 - (1)) + _dsave_offset];
gy = dsave[(4 - (1)) + _dsave_offset];
finit = dsave[(5 - (1)) + _dsave_offset];
fx = dsave[(6 - (1)) + _dsave_offset];
fy = dsave[(7 - (1)) + _dsave_offset];
stx = dsave[(8 - (1)) + _dsave_offset];
sty = dsave[(9 - (1)) + _dsave_offset];
stmin = dsave[(10 - (1)) + _dsave_offset];
stmax = dsave[(11 - (1)) + _dsave_offset];
width = dsave[(12 - (1)) + _dsave_offset];
width1 = dsave[(13 - (1)) + _dsave_offset];
}
//
// c If psi(stp) <= 0 and f'(stp) >= 0 for some step, then the
// c algorithm enters the second stage.
//
ftest = (finit + (stp * gtest));
if ((((stage == 1) && (f <= ftest)) && (g >= 0.0)))
{
stage = 2;
}
//
// c Test for warnings.
//
if ((brackt && (((stp <= stmin) || (stp >= stmax)))))
{
task = "WARNING: ROUNDING ERRORS PREVENT PROGRESS";
}
if ((brackt && ((stmax - stmin) <= (xtol * stmax))))
{
task = "WARNING: XTOL TEST SATISFIED";
}
if ((((stp == stpmax) && (f <= ftest)) && (g <= gtest)))
{
task = "WARNING: STP = STPMAX";
}
if (((stp == stpmin) && (((f > ftest) || (g >= gtest)))))
{
task = "WARNING: STP = STPMIN";
}
//
// c Test for convergence.
//
if (((f <= ftest) && (System.Math.Abs(g) <= (gtol * ((-(ginit)))))))
{
task = "CONVERGENCE";
}
//
// c Test for termination.
//
if (((task.StartsWith("WARN", StringComparison.OrdinalIgnoreCase)) ||
(task.StartsWith("CONV", StringComparison.OrdinalIgnoreCase))))
{
goto L1000;
}
//
// c A modified function is used to predict the step during the
// c first stage if a lower function value has been obtained but
// c the decrease is not sufficient.
//
if ((((stage == 1) && (f <= fx)) && (f > ftest)))
{
//
// c Define the modified function and derivative values.
//
fm = (f - (stp * gtest));
fxm = (fx - (stx * gtest));
fym = (fy - (sty * gtest));
gm = (g - gtest);
gxm = (gx - gtest);
gym = (gy - gtest);
//
// Call dcstep to update stx, sty, and to compute the new step.
//
dcstep(ref stx, ref fxm, ref gxm, ref sty, ref fym, ref gym,
ref stp, fm, gm, ref brackt, stmin, stmax);
//
// Reset the function and derivative values for f.
//
fx = (fxm + (stx * gtest));
fy = (fym + (sty * gtest));
gx = (gxm + gtest);
gy = (gym + gtest);
//
}
else
{
//
// Call dcstep to update stx, sty, and to compute the new step.
//
dcstep(ref stx, ref fx, ref gx, ref sty, ref fy, ref gy,
ref stp, f, g, ref brackt, stmin, stmax);
}
//
// c Decide if a bisection step is needed.
//
if (brackt)
{
if ((System.Math.Abs((sty - stx)) >= (0.6600000000000000310862446895043831318617 * width1)))
{
stp = (stx + (0.5 * ((sty - stx))));
}
width1 = width;
width = System.Math.Abs((sty - stx));
}
//
// c Set the minimum and maximum steps allowed for stp.
//
if (brackt)
{
stmin = System.Math.Min(stx, sty);
stmax = System.Math.Max(stx, sty);
}
else
{
stmin = (stp + (1.100000000000000088817841970012523233891 * ((stp - stx))));
stmax = (stp + (4.0 * ((stp - stx))));
}
//
// c Force the step to be within the bounds stpmax and stpmin.
//
stp = System.Math.Max(stp, stpmin);
stp = System.Math.Min(stp, stpmax);
//
// c If further progress is not possible, let stp be the best
// c point obtained during the search.
//
if (((brackt && (((stp <= stmin) || (stp >= stmax)))) || ((brackt && ((stmax - stmin) <= (xtol * stmax))))))
{
stp = stx;
}
//
// c Obtain another function and derivative.
//
task = "FG";
//
L1000:
//
// c Save local variables.
//
if (brackt)
{
isave[(1 - (1)) + _isave_offset] = 1;
}
else
{
isave[(1 - (1)) + _isave_offset] = 0;
}
isave[(2 - (1)) + _isave_offset] = stage;
dsave[(1 - (1)) + _dsave_offset] = ginit;
dsave[(2 - (1)) + _dsave_offset] = gtest;
dsave[(3 - (1)) + _dsave_offset] = gx;
dsave[(4 - (1)) + _dsave_offset] = gy;
dsave[(5 - (1)) + _dsave_offset] = finit;
dsave[(6 - (1)) + _dsave_offset] = fx;
dsave[(7 - (1)) + _dsave_offset] = fy;
dsave[(8 - (1)) + _dsave_offset] = stx;
dsave[(9 - (1)) + _dsave_offset] = sty;
dsave[(10 - (1)) + _dsave_offset] = stmin;
dsave[(11 - (1)) + _dsave_offset] = stmax;
dsave[(12 - (1)) + _dsave_offset] = width;
dsave[(13 - (1)) + _dsave_offset] = width1;
}