/***************************************************************************
**
**  This file is part of QGpCoreMath.
**
**  This library is free software; you can redistribute it and/or
**  modify it under the terms of the GNU Lesser General Public
**  License as published by the Free Software Foundation; either
**  version 2.1 of the License, or (at your option) any later version.
**
**  This file is distributed in the hope that it will be useful, but WITHOUT
**  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
**  FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
**  License for more details.
**
**  You should have received a copy of the GNU Lesser General Public
**  License along with this library; if not, write to the Free Software
**  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
**
**  See http://www.geopsy.org for more information.
**
**  Created: 2004-04-28
**  Copyright: 2004-2019
**    Marc Wathelet
**    Marc Wathelet (ULg, Liège, Belgium)
**    Marc Wathelet (LGIT, Grenoble, France)
**
***************************************************************************/

#include <stdio.h>
#include <math.h>

#include "RootSolver.h"

namespace QGpCoreMath {

/*!
  \class RootSolverTemplate RootSearch.h
  \brief Template class to search roots of a 1D function

  The roots are searched in order provided that the search step is sufficiently
  small. The search step can be adaptative as it can defined by a ratio. For searching
  a root arround zero, the search step must be absolute. After bracketing a root, it can
  be refined by various algorithms: halving, Neville, or Newton-Raphson.

  The function values are calculated by the function class provided to the constructor.

  Before any call to a searching function, the search step and the polarity of the
  starting point must be set. The polarity is calculated by setPolarity(), inversePolarity().
  The step is accessed with searchStep(), setAbsoluteStep(), and setRelativeStep().

  After a successfull search, the current bracket() can be retrieved and passed
  to RootRefine to refine the root location down to an arbitrary precision.
*/

/*!
  \fn RootSolverTemplate::RootSolverTemplate(FunctionClass * values)

  Constructor

  The search step is set by default to one tenth of the tail value of the bracket
  (relative step). The default polarity is 1.
  The precision is the relative precision that will be achieved by halving(), neville(),
  or newtonRaphson(). The default value is 1e-7.
*/

/*!
  \fn RealType RootSolverTemplate::searchStep() const
  Returns the current step (ratio or absolute according to current type).
*/

/*!
  \fn void RootSolverTemplate::setAbsoluteStep(RealType step)
  Set the current step.
*/

/*!
  \fn void RootSolverTemplate::setRelativeStep(RealType step)
  Set the current step ratio. The absolute search step is defined by the product of the
  \a step and the current lower bound of the bracket interval.
*/

/*!
  \fn RootSolverTemplate::setPolarity(RealType x0)

  Calculate the initial polarity. x0 must be chosen so that the value of the
  function at x0 is representative of the sign of the function at positive std::numeric_limits<double>::infinity().
*/

/*!
  \fn void RootSolverTemplate::inversePolarity()
  Simply inverses the sign of the polarity, used to calculate the next root after a
  first successful solve().
*/

/*!
  \fn double RootSolverTemplate::precision() const
  Return the current relative precision.
*/

/*!
  \fn void RootSolverTemplate::setPrecision(double prec)
  Set the current relative precision used as a completion criterium for halving(), neville(),
  and newtonRaphson().
*/

/*!
  \fn RootSolverTemplate::setInterval(RealType min, RealType max)

  If the root is already localized, there is no need to search for a root before refining it.
  Set directly the interval limits and returns true if there is effectively a root in the range.
*/

/*!
  \fn RootSolverTemplate::searchUp(RealType from, RealType to)

  Searches for roots starting from \a from. If no root is found, it stops at \a to.
  \a from must be less than \a to.

  Returns true if a root is effectively found between \a from and \a to.
*/

/*!
  \fn RootSolverTemplate::searchDown(RealType from, RealType to)

  Searches for roots starting from \a from. If no root is found, it stops at \a to.
  \a from must be greater than \a to.

  Returns true if a root is effectively found between \a from and \a to.
*/

/*!
  \fn bool RootSolverTemplate::searchUp(double from, double min, double max, bool* ok)

  A root is searched by increasing the initial value \a from. It returns immediately if a root exists
  between \a from and \a min (function value at \a min is assumed to be of the same sign as the polarity).

  Returns true if a root is effectively found between \a min and \a max.

  \sa bool RootSolverTemplate::searchDown(RealType from, RealType min, RealType max)
*/

/*!
  \fn bool RootSolverTemplate::searchDown(double from, double min, double max, bool* ok)

  A root is searched by decreasing the initial value \a from. It returns immediately if a root exists
  between \a from and \a max (function value at \a max is assumed to be of the same sign as the polarity).

  Returns true if a root is effectively found between \a min and \a max.

  \sa bool RootSolverTemplate::searchUp(RealType from, RealType min, RealType max)
*/

/*!
  \fn bool RootSolverTemplate::searchUpSlope(RealType from, RealType min, RealType max)

  Overload function for oscillating functions. A root is searched by increasing the initial value \a from.

  If the initial sampling step is large, a minimum or a maximum may be missed, looking regularly
  at the slope of the curve helps: if the sign of the slope changes, the minimum or maximum is
  refined and the presence of hidden root is checked.

  Returns true if a root is effectively found between \a min and \a max.

  \sa bool RootSolverTemplate::searchDownSlope(RealType from, RealType min, RealType max)
*/

/*!
  \fn bool RootSolverTemplate::searchDownSlope(RealType from, RealType min, RealType max)

  Overload function for oscillating functions. A root is searched by decreasing the initial value \a from.

  Returns true if a root is effectively found between \a min and \a max.

  \sa bool RootSolverTemplate::searchUpSlope(RealType from, RealType min, RealType max)
*/

/*!
  \fn bool RootSolverTemplate::halving()

  Refines the current bracket interval down to precision set by setPrecision().
  The method is the most robust one. The interval is iteratively divided in two
  parts.
*/

/*!
  \fn bool RootSolverTemplate::neville()

  Refines the current bracket interval down to precision set by setPrecision().
  Interval halving is used where other schemes would be inefficient.
  Once a suitable region is found the Neville's algorithm (polynomial fit of x=x(y)
  at y=0) is used to find the root. The procedure alternates between the interval
  halving and Neville techniques using whichever is most efficient.

  The scheme of this function comes from FORTRAN 77 code written by
  D. R. Russell, R. B. Herrmann (Department of Earth and Atmospheric Sciences
  Saint Louis University 221 North Grand Boulevard St. Louis, Missouri 63103
  U. S. A. COPYRIGHT 1986, 1991). Recent optimizations to take advantage of the
  full power of the polynomial fit are due to Marc Wathelet. The main
  feature is a voluntary shift of the polynomial interpolation to maintain the
  order of magnitude of the function value at the limits of the current interval
  in the same range.

  See Numerical Recipes in C, chapter 3.1 for more details on Neville
*/

/*!
  \fn bool RootSolverTemplate::newtonRaphson()

  Refines the current bracket interval down to precision set by setPrecision().
  The method is based upon the derivative. The derivative is computed by the
  function class under derivative().
*/

/*!
  \fn RealType RootSolverTemplate::lower() const
  Returns the lower value of the current bracket interval.
*/

/*!
  \fn RealType RootSolverTemplate::upper() const
  Returns the upper value of the current bracket interval.
*/

} // namespace QGpCoreMath
