00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
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
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
00053
00054
00055
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
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
00098 result= b;
00099 _function->restoreXVec() ;
00100 return kTRUE;
00101 }
00102
00103 if (fabs (e) < tol || fabs (fa) <= fabs (fb)) {
00104
00105 d = m;
00106 e = m;
00107 }
00108 else {
00109
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
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
00135 e = d;
00136 d = p / q;
00137 }
00138 else {
00139
00140 d = m;
00141 e = m;
00142 }
00143 }
00144
00145 a = b;
00146 fa = fb;
00147
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
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 }