private double GetFourierValue(function f, derivative2 d2, double min, double max, double val, int it)
        {
            it++;
            if (it > maxIterations)
            {
                //Console.WriteLine("Obtener Fourier Value: Mas de 30 iteraciones");
                return(GetValueInFourierInterval(f, d2, min, max, val));
            }
            double gMin   = f(min) - val;
            double gMax   = f(max) - val;
            double inter  = min + (max - min) / 2.0;
            double gInter = f(inter) - val;

            if (Math.Abs(gInter) < 0.02)
            {
                return(inter);
            }
            if (gMin * gInter < 0)
            {
                return(GetFourierValue(f, d2, min, inter, val, it));
            }
            else
            {
                return(GetFourierValue(f, d2, inter, max, val, it));
            }
        }
        /** Method:
         * Devuelve el punto de fourier con el que el metodo de Newton Raphson converge muy rapidamente
         * Fourier Convergence Conditions value. Returns zero if does not fit conditions
         * f(a)*f(b) less than 0   2) f" greater than 0 en [a,b]  val is for non roots (otherwise 0)
         * f - funcion mediante la cual se calcula el valor de dicha funcion
         * d2 - funcion mediante la cual se calcula el valor de la derivada segunda de dicha funcion
         * a - Valor minimo del intervalo en el cual busca la raiz o cero
         * b - Valor maximo del intervalo en el cual busca la raiz o cero
         * val - Valor para el cual se desea buscar la inversa de la función */
        private double GetValueInFourierInterval(function f, derivative2 d2, double a, double b, double val)
        {
            double posValue = 0;
            double negValue = 0;
            double ga       = f(a) - val;
            double gb       = f(b) - val;

            if (ga * gb >= 0)
            {
                return(0);
            }
            if (ga > 0)
            {
                posValue = a; negValue = b;
            }
            else
            {
                posValue = b; negValue = a;
            }

            //Second derivative constant in the interval (warning: sign is not verified on intermediate values)
            if (d2(a) > 0 && d2(b) > 0)
            {
                return(posValue);
            }
            else
            {
                return(negValue);
            }
        }
        /** Method:
         * Metodo Newton Raphson para encontrar una raiz o cero de una función
         * Si val es cero entonces encuantra la raiz de la funcion
         * si no, encuentra la inversa de la función <paramref name="f"/> en val
         * f -  function
         * d -  first derivative
         * d2 -  second derivative
         * min - min value of the interval
         * max -  max value of the interval
         * val -  value to add (0 if pure root search)
         * eps - epsilon for solution validation
         * maxIt - maximum of iterations */
        internal double NewtonRaphsonOneRoot(function f, derivative d, derivative2 d2, double min, double max, double val)
        {
            if ((f(min) - val) * f(max) - val > 0)
            {
                throw new ArgumentException("No zero between these values");
            }
            double nr = 0;
            double x;
            int    i = 0;

            while (nr == 0)
            {
                x  = GetFourierValue(f, d2, min, max, val);
                nr = NewtonRaphson(f, d, x, val);
                if (i > maxIterations)
                {
                    throw new Exception("Exceed the maximun iterations");
                }
                i++;
            }
            return(nr);
        }
        /** Method:
         * Metodo Steffenson, que es una forma mas rapida de encontrar una raiz o cero de una función
         * Si val es cero entonces encuantra la raiz de la funcion
         * si no, encuentra la inversa de la función
         * f -  function
         * d -  first derivative
         * d2 -  second derivative
         * min - min value of the interval
         * max -  max value of the interval
         * val -  value to add (0 if pure root search)
         * maxIterations -  maximum of iterations */
        internal double SteffensenAccOneRoot(function f, derivative d, derivative2 d2, double min, double max, double val, int maxIterations)
        {
            if ((f(min) - val) * f(max) - val > 0)
            {
                throw new Exception("No zero between these values");
            }
            double st = 0;
            double x;
            int    i = 0;

            while (st == 0)
            {
                x  = GetFourierValue(f, d2, min, max, val);
                st = SteffensenAcceleration(f, d, x, val);
                i++;
                if (i > maxIterations)
                {
                    throw new Exception("Exceed maximun iterations");
                }
            }
            //Console.WriteLine("val = " + val + " , st = " + st + " , it = " + i);
            return(st);
        }
        /** Method:
         * Encuentra el punto de fourier con el que el metodo de Newton Raphson converge muy rapidamente
         * Fourier Convergence Conditions value for functions with one root on interval
         * f - funcion mediante la cual se calcula el valor de dicha funcion
         * d2 - funcion mediante la cual se calcula el valor de la derivada segunda de dicha funcion
         * min - Valor minimo del intervalo en el cual busca la raiz o cero
         * max - Valor maximo del intervalo en el cual busca la raiz o cero
         * val - Valor para el cual se desea buscar la inversa de la función
         * Si no existe una raiz, entonces genera error
         * the calculated fourier value */
        internal double GetFourierVal(function f, derivative2 d2, double min, double max, double val)
        {
            double a = randGen.NextDouble(min, max);
            double b = randGen.NextDouble(min, max);
            int    i = 0;

            if (i > maxIterations - 1)
            {
                a = min;
                b = max;
            }
            double ga = f(a) - val;
            double gb = f(b) - val;

            if (ga * gb < 0)
            {
                return(GetValueInFourierInterval(f, d2, a, b, val));
            }

            while (true)
            {
                a  = randGen.NextDouble(min, max);
                b  = randGen.NextDouble(min, max);
                ga = f(a) - val;
                gb = f(b) - val;
                if (ga * gb < 0)
                {
                    return(GetValueInFourierInterval(f, d2, a, b, val));
                }
                if (i > maxIterations)
                {
                    throw new Exception("Exceed the maximun iterations");
                }
                i++;
            }
        }
 /** Method:
  * Encuentra el punto de fourier con el que el metodo de Newton Raphson converge muy rapidamente</para>
  * Fourier Convergence Conditions value for functions with one root on interval</para>
  * f - funcion mediante la cual se calcula el valor de dicha funcion
  * d2 - funcion mediante la cual se calcula el valor de la derivada segunda de dicha funcion
  * min - Valor minimo del intervalo en el cual busca la raiz o cero
  * max - Valor maximo del intervalo en el cual busca la raiz o cero
  * val - Valor para el cual se desea buscar la inversa de la función
  * Si no existe una raiz, entonces genera error
  * the calculated fourier value */
 internal double GetFourierValue(function f, derivative2 d2, double min, double max, double val)
 {
     return(GetFourierValue(f, d2, min, max, val, 0));
 }