00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include "Math/BrentRootFinder.h"
00012 #include "Math/BrentMethods.h"
00013 #include <cmath>
00014
00015 #ifndef ROOT_Math_Error
00016 #include "Math/Error.h"
00017 #endif
00018
00019 namespace ROOT {
00020 namespace Math {
00021
00022
00023 static int gDefaultNpx = 100;
00024 static int gDefaultNSearch = 10;
00025
00026 BrentRootFinder::BrentRootFinder() : fFunction(0),
00027 fLogScan(false), fNIter(0),
00028 fNpx(0), fStatus(-1),
00029 fXMin(0), fXMax(0), fRoot(0)
00030 {
00031
00032 fNpx = gDefaultNpx;
00033 }
00034
00035 void BrentRootFinder::SetDefaultNpx(int n) { gDefaultNpx = n; }
00036
00037 void BrentRootFinder::SetDefaultNSearch(int n) { gDefaultNSearch = n; }
00038
00039
00040 bool BrentRootFinder::SetFunction(const ROOT::Math::IGenFunction& f, double xlow, double xup)
00041 {
00042
00043
00044 fFunction = &f;
00045
00046 fStatus = -1;
00047
00048 if (xlow >= xup)
00049 {
00050 double tmp = xlow;
00051 xlow = xup;
00052 xup = tmp;
00053 }
00054 fXMin = xlow;
00055 fXMax = xup;
00056
00057 return true;
00058 }
00059
00060 const char* BrentRootFinder::Name() const
00061 { return "BrentRootFinder"; }
00062
00063
00064 bool BrentRootFinder::Solve(int maxIter, double absTol, double relTol)
00065 {
00066
00067
00068 if (!fFunction) {
00069 MATH_ERROR_MSG("BrentRootFinder::Solve", "Function has not been set");
00070 return false;
00071 }
00072
00073 if (fLogScan && fXMin <= 0) {
00074 MATH_ERROR_MSG("BrentRootFinder::Solve", "xmin is < 0 and log scan is set - disable it");
00075 fLogScan = false;
00076 }
00077
00078
00079 const double fy = 0;
00080 fNIter = 0;
00081 fStatus = -1;
00082
00083 double xmin = fXMin;
00084 double xmax = fXMax;
00085
00086 int maxIter1 = gDefaultNSearch;
00087 int maxIter2 = maxIter;
00088
00089 int niter1 = 0;
00090 int niter2 = 0;
00091 bool ok = false;
00092 while (!ok){
00093 if (niter1 > maxIter1){
00094 MATH_ERROR_MSG("BrentRootFinder::Solve", "Search didn't converge");
00095 fStatus = -2;
00096 return false;
00097 }
00098 double x = BrentMethods::MinimStep(fFunction, 4, xmin, xmax, fy, fNpx,fLogScan);
00099 x = BrentMethods::MinimBrent(fFunction, 4, xmin, xmax, x, fy, ok, niter2, absTol, relTol, maxIter2);
00100 fNIter += niter2;
00101 niter1++;
00102 fRoot = x;
00103 }
00104
00105 fStatus = 0;
00106 return true;
00107 }
00108
00109 }
00110 }