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
00027
00028 #include "TMath.h"
00029
00030 #include "TMVA/RootFinder.h"
00031 #include "TMVA/MsgLogger.h"
00032
00033 ClassImp(TMVA::RootFinder)
00034
00035
00036 TMVA::RootFinder::RootFinder( Double_t (*rootVal)( Double_t ),
00037 Double_t rootMin,
00038 Double_t rootMax,
00039 Int_t maxIterations,
00040 Double_t absTolerance )
00041 : fRootMin( rootMin ),
00042 fRootMax( rootMax ),
00043 fMaxIter( maxIterations ),
00044 fAbsTol ( absTolerance ),
00045 fLogger ( new MsgLogger("RootFinder") )
00046 {
00047
00048 fGetRootVal = rootVal;
00049 }
00050
00051
00052 TMVA::RootFinder::~RootFinder( void )
00053 {
00054
00055 delete fLogger;
00056 }
00057
00058
00059 Double_t TMVA::RootFinder::Root( Double_t refValue )
00060 {
00061
00062 Double_t a = fRootMin, b = fRootMax;
00063 Double_t fa = (*fGetRootVal)( a ) - refValue;
00064 Double_t fb = (*fGetRootVal)( b ) - refValue;
00065 if (fb*fa > 0) {
00066 Log() << kWARNING << "<Root> initial interval w/o root: "
00067 << "(a=" << a << ", b=" << b << "),"
00068 << " (Eff_a=" << (*fGetRootVal)( a )
00069 << ", Eff_b=" << (*fGetRootVal)( b ) << "), "
00070 << "(fa=" << fa << ", fb=" << fb << "), "
00071 << "refValue = " << refValue << Endl;
00072 return 1;
00073 }
00074
00075 Bool_t ac_equal(kFALSE);
00076 Double_t fc = fb;
00077 Double_t c = 0, d = 0, e = 0;
00078 for (Int_t iter= 0; iter <= fMaxIter; iter++) {
00079 if ((fb < 0 && fc < 0) || (fb > 0 && fc > 0)) {
00080
00081
00082 ac_equal = kTRUE;
00083 c = a; fc = fa;
00084 d = b - a; e = b - a;
00085 }
00086
00087 if (TMath::Abs(fc) < TMath::Abs(fb)) {
00088 ac_equal = kTRUE;
00089 a = b; b = c; c = a;
00090 fa = fb; fb = fc; fc = fa;
00091 }
00092
00093 Double_t tol = 0.5 * 2.2204460492503131e-16 * TMath::Abs(b);
00094 Double_t m = 0.5 * (c - b);
00095 if (fb == 0 || TMath::Abs(m) <= tol || TMath::Abs(fb) < fAbsTol) return b;
00096
00097
00098 if (TMath::Abs (e) < tol || TMath::Abs (fa) <= TMath::Abs (fb)) { d = m; e = m; }
00099 else {
00100
00101 Double_t p, q, r;
00102 Double_t s = fb / fa;
00103
00104 if (ac_equal) { p = 2 * m * s; q = 1 - s; }
00105 else {
00106 q = fa / fc; r = fb / fc;
00107 p = s * (2 * m * q * (q - r) - (b - a) * (r - 1));
00108 q = (q - 1) * (r - 1) * (s - 1);
00109 }
00110
00111 if (p > 0) q = -q;
00112 else p = -p;
00113
00114 Double_t min1 = 3 * m * q - TMath::Abs (tol * q);
00115 Double_t min2 = TMath::Abs (e * q);
00116 if (2 * p < (min1 < min2 ? min1 : min2)) {
00117
00118 e = d; d = p / q;
00119 }
00120 else { d = m; e = m; }
00121 }
00122
00123 a = b; fa = fb;
00124
00125 if (TMath::Abs(d) > tol) b += d;
00126 else b += (m > 0 ? +tol : -tol);
00127
00128 fb = (*fGetRootVal)( b ) - refValue;
00129
00130 }
00131
00132
00133 Log() << kWARNING << "<Root> maximum iterations (" << fMaxIter
00134 << ") reached before convergence" << Endl;
00135
00136 return b;
00137 }
00138