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;
            }
        }