#include "TMVA/RootFinder.h"
#include "Riostream.h"
#include "TMath.h"
ClassImp(TMVA::RootFinder)
TMVA::RootFinder::RootFinder( Double_t (*rootVal)( Double_t ),
                              Double_t rootMin, 
                              Double_t rootMax,
                              Int_t maxIterations, 
                              Double_t absTolerance )
   : fRootMin( rootMin ),
     fRootMax( rootMax ),
     fMaxIter( maxIterations ),
     fAbsTol ( absTolerance  ),
     fLogger ( "RootFinder" )
{
   
   fGetRootVal = rootVal;
}
TMVA::RootFinder::~RootFinder( void )
{
   
}
Double_t TMVA::RootFinder::Root( Double_t refValue  )
{
   
   Double_t a  = fRootMin, b = fRootMax;
   Double_t fa = (*fGetRootVal)( a ) - refValue;
   Double_t fb = (*fGetRootVal)( b ) - refValue;
   if (fb*fa > 0) {
      fLogger << kWARNING << "<Root> initial interval w/o root: "
              << "(a=" << a << ", b=" << b << "),"
              << " (Eff_a=" << (*fGetRootVal)( a ) 
              << ", Eff_b=" << (*fGetRootVal)( b ) << "), "
              << "(fa=" << fa << ", fb=" << fb << "), "
              << "refValue = " << refValue << Endl;
      return 1;
   }
   Bool_t   ac_equal(kFALSE);
   Double_t fc = fb;
   Double_t c  = 0, d = 0, e = 0;
   for (Int_t iter= 0; iter <= fMaxIter; iter++) {
      if ((fb < 0 && fc < 0) || (fb > 0 && fc > 0)) {
         
         ac_equal = kTRUE;
         c  = a; fc = fa;
         d  = b - a; e  = b - a;
      }
  
      if (TMath::Abs(fc) < TMath::Abs(fb)) {
         ac_equal = kTRUE;
         a  = b;  b  = c;  c  = a;
         fa = fb; fb = fc; fc = fa;
      }
      Double_t tol = 0.5 * 2.2204460492503131e-16 * TMath::Abs(b);
      Double_t m   = 0.5 * (c - b);
      if (fb == 0 || TMath::Abs(m) <= tol || TMath::Abs(fb) < fAbsTol) return b;
  
      
      if (TMath::Abs (e) < tol || TMath::Abs (fa) <= TMath::Abs (fb)) { d = m; e = m; }      
      else {
         
         Double_t p, q, r;
         Double_t s = fb / fa;
      
         if (ac_equal) { p = 2 * m * s; q = 1 - s; }
         else {
            q = fa / fc; r = fb / fc;
            p = s * (2 * m * q * (q - r) - (b - a) * (r - 1));
            q = (q - 1) * (r - 1) * (s - 1);
         }
         
         if (p > 0) q = -q;
         else       p = -p;
      
         Double_t min1 = 3 * m * q - TMath::Abs (tol * q);
         Double_t min2 = TMath::Abs (e * q);
         if (2 * p < (min1 < min2 ? min1 : min2)) {
            
            e = d;        d = p / q;
         }
         else { d = m; e = m; } 
      }
      
      a  = b; fa = fb;
      
      if (TMath::Abs(d) > tol) b += d;
      else                     b += (m > 0 ? +tol : -tol);
      fb = (*fGetRootVal)( b ) - refValue;
   }
   
   fLogger << kWARNING << "<Root> maximum iterations (" << fMaxIter 
           << ") reached before convergence" << Endl;
   return b;
}
This page has been automatically generated. If you have any comments or suggestions about the page layout send a mail to ROOT support, or contact the developers with any questions or problems regarding ROOT.