// @(#)root/mathmore:$Id$
// Authors: L. Moneta, A. Zsenei   08/2005

 /**********************************************************************
  *                                                                    *
  * Copyright (c) 2004 ROOT Foundation,  CERN/PH-SFT                   *
  *                                                                    *
  * This library is free software; you can redistribute it and/or      *
  * modify it under the terms of the GNU General Public License        *
  * as published by the Free Software Foundation; either version 2     *
  * of the License, or (at your option) any later version.             *
  *                                                                    *
  * This library 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   *
  * General Public License for more details.                           *
  *                                                                    *
  * You should have received a copy of the GNU General Public License  *
  * along with this library (see file COPYING); if not, write          *
  * to the Free Software Foundation, Inc., 59 Temple Place, Suite      *
  * 330, Boston, MA 02111-1307 USA, or contact the author.             *
  *                                                                    *
  **********************************************************************/

// Header file for class RootFinder
//
// Created by: moneta  at Sun Nov 14 16:59:55 2004
//
// Last update: Sun Nov 14 16:59:55 2004
//
#ifndef ROOT_Math_RootFinder
#define ROOT_Math_RootFinder


#ifndef ROOT_Math_IFunctionfwd
#include "Math/IFunctionfwd.h"
#endif

#ifndef ROOT_Math_IRootFinderMethod
#include "Math/IRootFinderMethod.h"
#endif


/**
   @defgroup RootFinders One-dimensional Root-Finding algorithms
   Various implementation esists in MathCore and MathMore
   The user interacts with a proxy class ROOT::Math::RootFinder which creates behing
   the chosen algorithms which are implemented using the ROOT::Math::IRootFinderMethod interface

   @ingroup NumAlgo
*/


namespace ROOT {
   namespace Math {


//_____________________________________________________________________________________
      /**
         User Class to find the Root of one dimensional functions.
         The GSL Methods are implemented in MathMore and they are loaded automatically
         via the plug-in manager

         The possible types of Root-finding algorithms are:
         <ul>
         <li>Root Bracketing Algorithms which do not require function derivatives
         <ol>
         <li>RootFinder::kBRENT  (default method implemented in MathCore)
         <li>RootFinder::kGSL_BISECTION
         <li>RootFinder::kGSL_FALSE_POS
         <li>RootFinder::kGSL_BRENT
         </ol>
         <li>Root Finding Algorithms using Derivatives
         <ol>
         <li>RootFinder::kGSL_NEWTON
         <li>RootFinder::kGSL_SECANT
         <li>RootFinder::kGSL_STEFFENSON
         </ol>
         </ul>

         This class does not cupport copying

         @ingroup RootFinders

      */

      class RootFinder {

      public:

         enum EType { kBRENT,                                   // Methods from MathCore
                     kGSL_BISECTION, kGSL_FALSE_POS, kGSL_BRENT, // GSL Normal
                     kGSL_NEWTON, kGSL_SECANT, kGSL_STEFFENSON   // GSL Derivatives
         };

         /**
            Construct a Root-Finder algorithm
         */
         RootFinder(RootFinder::EType type = RootFinder::kBRENT);
         virtual ~RootFinder();

      private:
         // usually copying is non trivial, so we make this unaccessible
         RootFinder(const RootFinder & ) {}
         RootFinder & operator = (const RootFinder & rhs)
         {
            if (this == &rhs) return *this;  // time saving self-test
            return *this;
         }

      public:

         bool SetMethod(RootFinder::EType type = RootFinder::kBRENT);

         /**
            Provide to the solver the function and the initial search interval [xlow, xup]
            for algorithms not using derivatives (bracketing algorithms)
            The templated function f must be of a type implementing the \a operator() method,
            <em>  double  operator() (  double  x ) </em>
            Returns non zero if interval is not valid (i.e. does not contains a root)
         */

         bool SetFunction( const IGenFunction & f, double xlow, double xup) {
            return fSolver->SetFunction( f, xlow, xup);
         }


         /**
            Provide to the solver the function and an initial estimate of the root,
            for algorithms using derivatives.
            The templated function f must be of a type implementing the \a operator()
            and the \a Gradient() methods.
            <em>  double  operator() (  double  x ) </em>
            Returns non zero if starting point is not valid
         */

         bool  SetFunction( const IGradFunction & f, double xstart) {
            return fSolver->SetFunction( f, xstart);
         }

         template<class Function, class Derivative>
         bool Solve(Function &f, Derivative &d, double start,
                   int maxIter = 100, double absTol = 1E-8, double relTol = 1E-10);

         template<class Function>
         bool Solve(Function &f, double min, double max,
                   int maxIter = 100, double absTol = 1E-8, double relTol = 1E-10);

         /**
             Compute the roots iterating until the estimate of the Root is within the required tolerance returning
             the iteration Status
         */
         bool Solve( int maxIter = 100, double absTol = 1E-8, double relTol = 1E-10) {
            return fSolver->Solve( maxIter, absTol, relTol );
         }

         /**
             Return the number of iteration performed to find the Root.
         */
         int Iterations() const {
            return fSolver->Iterations();
         }

         /**
            Perform a single iteration and return the Status
         */
         int Iterate() {
            return fSolver->Iterate();
         }

         /**
            Return the current and latest estimate of the Root
         */
         double Root() const {
            return fSolver->Root();
         }

         /**
            Return the status of the last estimate of the Root
            = 0 OK, not zero failure
         */
         int Status() const {
            return fSolver->Status();
         }


         /**
            Return the current and latest estimate of the lower value of the Root-finding interval (for bracketing algorithms)
         */
/*   double XLower() const {  */
/*     return fSolver->XLower();  */
/*   } */

         /**
            Return the current and latest estimate of the upper value of the Root-finding interval (for bracketing algorithms)
         */
/*   double XUpper() const {  */
/*     return  fSolver->XUpper();  */
/*   } */

         /**
            Get Name of the Root-finding solver algorithm
         */
         const char * Name() const {
            return fSolver->Name();
         }


      protected:


      private:

         IRootFinderMethod* fSolver;   // type of algorithm to be used


      };

   } // namespace Math
} // namespace ROOT


#ifndef ROOT_Math_WrappedFunction
#include "Math/WrappedFunction.h"
#endif

#ifndef ROOT_Math_Functor
#include "Math/Functor.h"
#endif

template<class Function, class Derivative>
bool ROOT::Math::RootFinder::Solve(Function &f, Derivative &d, double start,
                                  int maxIter, double absTol, double relTol)
{
   if (!fSolver) return false;
   ROOT::Math::GradFunctor1D wf(f, d);
   bool ret = fSolver->SetFunction(wf, start);
   if (!ret) return false;
   return Solve(maxIter, absTol, relTol);
}

template<class Function>
bool ROOT::Math::RootFinder::Solve(Function &f, double min, double max,
                                  int maxIter, double absTol, double relTol)
{
   if (!fSolver) return false;
   ROOT::Math::WrappedFunction<Function &> wf(f);
   bool ret = fSolver->SetFunction(wf, min, max);
   if (!ret) return false;
   return Solve(maxIter, absTol, relTol);
}

#endif /* ROOT_Math_RootFinder */
 RootFinder.h:1
 RootFinder.h:2
 RootFinder.h:3
 RootFinder.h:4
 RootFinder.h:5
 RootFinder.h:6
 RootFinder.h:7
 RootFinder.h:8
 RootFinder.h:9
 RootFinder.h:10
 RootFinder.h:11
 RootFinder.h:12
 RootFinder.h:13
 RootFinder.h:14
 RootFinder.h:15
 RootFinder.h:16
 RootFinder.h:17
 RootFinder.h:18
 RootFinder.h:19
 RootFinder.h:20
 RootFinder.h:21
 RootFinder.h:22
 RootFinder.h:23
 RootFinder.h:24
 RootFinder.h:25
 RootFinder.h:26
 RootFinder.h:27
 RootFinder.h:28
 RootFinder.h:29
 RootFinder.h:30
 RootFinder.h:31
 RootFinder.h:32
 RootFinder.h:33
 RootFinder.h:34
 RootFinder.h:35
 RootFinder.h:36
 RootFinder.h:37
 RootFinder.h:38
 RootFinder.h:39
 RootFinder.h:40
 RootFinder.h:41
 RootFinder.h:42
 RootFinder.h:43
 RootFinder.h:44
 RootFinder.h:45
 RootFinder.h:46
 RootFinder.h:47
 RootFinder.h:48
 RootFinder.h:49
 RootFinder.h:50
 RootFinder.h:51
 RootFinder.h:52
 RootFinder.h:53
 RootFinder.h:54
 RootFinder.h:55
 RootFinder.h:56
 RootFinder.h:57
 RootFinder.h:58
 RootFinder.h:59
 RootFinder.h:60
 RootFinder.h:61
 RootFinder.h:62
 RootFinder.h:63
 RootFinder.h:64
 RootFinder.h:65
 RootFinder.h:66
 RootFinder.h:67
 RootFinder.h:68
 RootFinder.h:69
 RootFinder.h:70
 RootFinder.h:71
 RootFinder.h:72
 RootFinder.h:73
 RootFinder.h:74
 RootFinder.h:75
 RootFinder.h:76
 RootFinder.h:77
 RootFinder.h:78
 RootFinder.h:79
 RootFinder.h:80
 RootFinder.h:81
 RootFinder.h:82
 RootFinder.h:83
 RootFinder.h:84
 RootFinder.h:85
 RootFinder.h:86
 RootFinder.h:87
 RootFinder.h:88
 RootFinder.h:89
 RootFinder.h:90
 RootFinder.h:91
 RootFinder.h:92
 RootFinder.h:93
 RootFinder.h:94
 RootFinder.h:95
 RootFinder.h:96
 RootFinder.h:97
 RootFinder.h:98
 RootFinder.h:99
 RootFinder.h:100
 RootFinder.h:101
 RootFinder.h:102
 RootFinder.h:103
 RootFinder.h:104
 RootFinder.h:105
 RootFinder.h:106
 RootFinder.h:107
 RootFinder.h:108
 RootFinder.h:109
 RootFinder.h:110
 RootFinder.h:111
 RootFinder.h:112
 RootFinder.h:113
 RootFinder.h:114
 RootFinder.h:115
 RootFinder.h:116
 RootFinder.h:117
 RootFinder.h:118
 RootFinder.h:119
 RootFinder.h:120
 RootFinder.h:121
 RootFinder.h:122
 RootFinder.h:123
 RootFinder.h:124
 RootFinder.h:125
 RootFinder.h:126
 RootFinder.h:127
 RootFinder.h:128
 RootFinder.h:129
 RootFinder.h:130
 RootFinder.h:131
 RootFinder.h:132
 RootFinder.h:133
 RootFinder.h:134
 RootFinder.h:135
 RootFinder.h:136
 RootFinder.h:137
 RootFinder.h:138
 RootFinder.h:139
 RootFinder.h:140
 RootFinder.h:141
 RootFinder.h:142
 RootFinder.h:143
 RootFinder.h:144
 RootFinder.h:145
 RootFinder.h:146
 RootFinder.h:147
 RootFinder.h:148
 RootFinder.h:149
 RootFinder.h:150
 RootFinder.h:151
 RootFinder.h:152
 RootFinder.h:153
 RootFinder.h:154
 RootFinder.h:155
 RootFinder.h:156
 RootFinder.h:157
 RootFinder.h:158
 RootFinder.h:159
 RootFinder.h:160
 RootFinder.h:161
 RootFinder.h:162
 RootFinder.h:163
 RootFinder.h:164
 RootFinder.h:165
 RootFinder.h:166
 RootFinder.h:167
 RootFinder.h:168
 RootFinder.h:169
 RootFinder.h:170
 RootFinder.h:171
 RootFinder.h:172
 RootFinder.h:173
 RootFinder.h:174
 RootFinder.h:175
 RootFinder.h:176
 RootFinder.h:177
 RootFinder.h:178
 RootFinder.h:179
 RootFinder.h:180
 RootFinder.h:181
 RootFinder.h:182
 RootFinder.h:183
 RootFinder.h:184
 RootFinder.h:185
 RootFinder.h:186
 RootFinder.h:187
 RootFinder.h:188
 RootFinder.h:189
 RootFinder.h:190
 RootFinder.h:191
 RootFinder.h:192
 RootFinder.h:193
 RootFinder.h:194
 RootFinder.h:195
 RootFinder.h:196
 RootFinder.h:197
 RootFinder.h:198
 RootFinder.h:199
 RootFinder.h:200
 RootFinder.h:201
 RootFinder.h:202
 RootFinder.h:203
 RootFinder.h:204
 RootFinder.h:205
 RootFinder.h:206
 RootFinder.h:207
 RootFinder.h:208
 RootFinder.h:209
 RootFinder.h:210
 RootFinder.h:211
 RootFinder.h:212
 RootFinder.h:213
 RootFinder.h:214
 RootFinder.h:215
 RootFinder.h:216
 RootFinder.h:217
 RootFinder.h:218
 RootFinder.h:219
 RootFinder.h:220
 RootFinder.h:221
 RootFinder.h:222
 RootFinder.h:223
 RootFinder.h:224
 RootFinder.h:225
 RootFinder.h:226
 RootFinder.h:227
 RootFinder.h:228
 RootFinder.h:229
 RootFinder.h:230
 RootFinder.h:231
 RootFinder.h:232
 RootFinder.h:233
 RootFinder.h:234
 RootFinder.h:235
 RootFinder.h:236
 RootFinder.h:237
 RootFinder.h:238
 RootFinder.h:239
 RootFinder.h:240
 RootFinder.h:241
 RootFinder.h:242
 RootFinder.h:243
 RootFinder.h:244
 RootFinder.h:245
 RootFinder.h:246
 RootFinder.h:247
 RootFinder.h:248
 RootFinder.h:249
 RootFinder.h:250
 RootFinder.h:251
 RootFinder.h:252
 RootFinder.h:253