private IterationTolerances tols; // reference to iteration tolerances public MirroredFunction(Func <double, double> original, bool mirrored, IterationTolerances tolerances) { F = original; mirror = mirrored; tols = tolerances; }
public static double SegmentSearchMethod(Func <double, double> function, IterationTolerances tols) { double x0 = 0d; double f0 = function(x0); MirroredFunction mfobj = new MirroredFunction(function, f0 > 0d, tols); if (mfobj.IsMirrored) { f0 = -f0; } Func <double, double> f = mfobj.Delegate; double x1 = tols.xstepinitial; double f1 = f(x1); if (f1 < f0) { return(mfobj.BrentSolve("Negative initial gradient.")); } LblSkipRight: if (f1 > 0) { return(mfobj.LinearSolution(x0, f0, x1, f1)); } double x2 = Clamp <double>(x1 + tols.xstepsize, 0d, tols.rightedge); if (x2 == x1) { return(mfobj.BrentSolve("Reached far right edge.")); } double f2 = f(x2); if (f2 > f1) { // skip right x0 = x1; f0 = f1; x1 = x2; f1 = f2; goto LblSkipRight; } LblTriangle: if (f1 > 0) { return(mfobj.LinearSolution(x0, f0, x1, f1)); } if (x2 - x0 < tols.tol_triangle) { return(mfobj.BrentSolve("Local maximum is negative (search point x= " + x0 + ").")); } double x01 = (x0 + x1) / 2d; double x12 = (x1 + x2) / 2d; double f01 = f(x01); double f12 = f(x12); if (f01 >= f1 && f01 >= f12) { // maximum at x01 x1 = x01; f1 = f01; x2 = x1; f2 = f1; goto LblTriangle; } else if (f12 > f1 && f12 > f01) { // maximum at x12 x0 = x1; f0 = f1; x1 = x12; f1 = f12; goto LblTriangle; } else { // shrink around x1 x0 = x01; f0 = f01; x2 = x12; f2 = f12; goto LblTriangle; } }