RooBrentRootFinder.cxx

Go to the documentation of this file.
00001 /*****************************************************************************
00002  * Project: RooFit                                                           *
00003  * Package: RooFitCore                                                       *
00004  * @(#)root/roofitcore:$Id: RooBrentRootFinder.cxx 31654 2009-12-08 13:38:37Z wouter $
00005  * Authors:                                                                  *
00006  *   WV, Wouter Verkerke, UC Santa Barbara, verkerke@slac.stanford.edu       *
00007  *   DK, David Kirkby,    UC Irvine,         dkirkby@uci.edu                 *
00008  *                                                                           *
00009  * Copyright (c) 2000-2005, Regents of the University of California          *
00010  *                          and Stanford University. All rights reserved.    *
00011  *                                                                           *
00012  * Redistribution and use in source and binary forms,                        *
00013  * with or without modification, are permitted according to the terms        *
00014  * listed in LICENSE (http://roofit.sourceforge.net/license.txt)             *
00015  *****************************************************************************/
00016 
00017 //////////////////////////////////////////////////////////////////////////////
00018 // 
00019 // BEGIN_HTML
00020 // Implement the abstract 1-dimensional root finding interface using
00021 // the Brent-Decker method. This implementation is based on the one
00022 // in the GNU scientific library (v0.99).
00023 // END_HTML
00024 //
00025 
00026 #include "RooFit.h"
00027 
00028 #include "RooBrentRootFinder.h"
00029 #include "RooBrentRootFinder.h"
00030 #include "RooAbsFunc.h"
00031 #include <math.h>
00032 #include "Riostream.h"
00033 #include "RooMsgService.h"
00034 
00035 ClassImp(RooBrentRootFinder)
00036 ;
00037 
00038 
00039 //_____________________________________________________________________________
00040 RooBrentRootFinder::RooBrentRootFinder(const RooAbsFunc& function) :
00041   RooAbsRootFinder(function),
00042   _tol(2.2204460492503131e-16)
00043 {
00044   // Constructor taking function binding as input
00045 }
00046 
00047 
00048 
00049 //_____________________________________________________________________________
00050 Bool_t RooBrentRootFinder::findRoot(Double_t &result, Double_t xlo, Double_t xhi, Double_t value) const
00051 {
00052   // Do the root finding using the Brent-Decker method. Returns a boolean status and
00053   // loads 'result' with our best guess at the root if true.
00054   // Prints a warning if the initial interval does not bracket a single
00055   // root or if the root is not found after a fixed number of iterations.
00056 
00057   _function->saveXVec() ;
00058 
00059   Double_t a(xlo),b(xhi);
00060   Double_t fa= (*_function)(&a) - value;
00061   Double_t fb= (*_function)(&b) - value;
00062   if(fb*fa > 0) {
00063     oocxcoutD((TObject*)0,Eval) << "RooBrentRootFinder::findRoot(" << _function->getName() << "): initial interval does not bracket a root: ("
00064                                 << a << "," << b << "), value = " << value << " f[xlo] = " << fa << " f[xhi] = " << fb << endl;
00065     return kFALSE;
00066   }
00067 
00068   Bool_t ac_equal(kFALSE);
00069   Double_t fc= fb;
00070   Double_t c(0),d(0),e(0);
00071   for(Int_t iter= 0; iter <= MaxIterations; iter++) {
00072 
00073     if ((fb < 0 && fc < 0) || (fb > 0 && fc > 0)) {
00074       // Rename a,b,c and adjust bounding interval d
00075       ac_equal = kTRUE;
00076       c = a;
00077       fc = fa;
00078       d = b - a;
00079       e = b - a;
00080     }
00081   
00082     if (fabs (fc) < fabs (fb)) {
00083       ac_equal = kTRUE;
00084       a = b;
00085       b = c;
00086       c = a;
00087       fa = fb;
00088       fb = fc;
00089       fc = fa;
00090     }
00091 
00092     Double_t tol = 0.5 * _tol * fabs(b);
00093     Double_t m = 0.5 * (c - b);
00094 
00095 
00096     if (fb == 0 || fabs(m) <= tol) {
00097       //cout << "RooBrentRootFinder: iter = " << iter << " m = " << m << " tol = " << tol << endl ;
00098       result= b;
00099       _function->restoreXVec() ;      
00100       return kTRUE;
00101     }
00102   
00103     if (fabs (e) < tol || fabs (fa) <= fabs (fb)) {
00104       // Bounds decreasing too slowly: use bisection
00105       d = m;
00106       e = m;
00107     }
00108     else {
00109       // Attempt inverse cubic interpolation
00110       Double_t p, q, r;
00111       Double_t s = fb / fa;
00112       
00113       if (ac_equal) {
00114         p = 2 * m * s;
00115         q = 1 - s;
00116       }
00117       else {
00118         q = fa / fc;
00119         r = fb / fc;
00120         p = s * (2 * m * q * (q - r) - (b - a) * (r - 1));
00121         q = (q - 1) * (r - 1) * (s - 1);
00122       }
00123       // Check whether we are in bounds
00124       if (p > 0) {
00125         q = -q;
00126       }
00127       else {
00128         p = -p;
00129       }
00130       
00131       Double_t min1= 3 * m * q - fabs (tol * q);
00132       Double_t min2= fabs (e * q);
00133       if (2 * p < (min1 < min2 ? min1 : min2)) {
00134         // Accept the interpolation
00135         e = d;
00136         d = p / q;
00137       }
00138       else {
00139         // Interpolation failed: use bisection.
00140         d = m;
00141         e = m;
00142       }
00143     }
00144     // Move last best guess to a
00145     a = b;
00146     fa = fb;
00147     // Evaluate new trial root
00148     if (fabs (d) > tol) {
00149       b += d;
00150     }
00151     else {
00152       b += (m > 0 ? +tol : -tol);
00153     }
00154     fb= (*_function)(&b) - value;
00155 
00156   }
00157   // Return our best guess if we run out of iterations
00158   oocoutE((TObject*)0,Eval) << "RooBrentRootFinder::findRoot(" << _function->getName() << "): maximum iterations exceeded." << endl;
00159   result= b;
00160 
00161   _function->restoreXVec() ;
00162 
00163   return kFALSE;
00164 }

Generated on Tue Jul 5 15:06:06 2011 for ROOT_528-00b_version by  doxygen 1.5.1