private static Point CoordinateDescent(FunctionWrapper function, Point x0, double h0, double epsilon)
        {
            var h = new Vector(new double[x0.Length]);

            for (var i = 0; i < h.Length; i++)
            {
                h[i] = h0;
            }
            var   xInt = x0.Clone();
            Point xExt;

            do
            {
                xExt = xInt.Clone();
                for (var i = 0; i < xInt.Length; i++)
                {
                    Program.CountThisLoop();
                    var x  = xInt.Clone();
                    var y1 = x.Clone();
                    y1[i] += 3 * epsilon;
                    var y2 = x.Clone();
                    y2[i] -= 3 * epsilon;
                    var f1 = function.Eval(y1);
                    var f2 = function.Eval(y2);
                    var z  = Math.Sign(f2 - f1);
                    h[i]    = function.FindHForCoordinateDescent(xInt.Clone(), z, i, h[i], epsilon);
                    xInt[i] = x[i] + h[i] * z;
                }
            } while ((xInt - xExt).Normalize() >= epsilon);
            return(xInt);
        }