00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include "Math/BrentMethods.h"
00012 #include "Math/IFunction.h"
00013
00014 #include <cmath>
00015 #include <algorithm>
00016
00017 #ifndef ROOT_Math_Error
00018 #include "Math/Error.h"
00019 #endif
00020
00021 #include <iostream>
00022
00023 namespace ROOT {
00024 namespace Math {
00025
00026 namespace BrentMethods {
00027
00028 double MinimStep(const IGenFunction* function, int type, double &xmin, double &xmax, double fy, int npx,bool logStep)
00029 {
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039 if (logStep) {
00040 xmin = std::log(xmin);
00041 xmax = std::log(xmax);
00042 }
00043
00044
00045 if (npx < 2) return 0.5*(xmax-xmin);
00046 double dx = (xmax-xmin)/(npx-1);
00047 double xxmin = (logStep) ? std::exp(xmin) : xmin;
00048 double yymin;
00049 if (type < 2)
00050 yymin = (*function)(xxmin);
00051 else if (type < 4)
00052 yymin = -(*function)(xxmin);
00053 else
00054 yymin = std::fabs((*function)(xxmin)-fy);
00055
00056 for (int i=1; i<=npx-1; i++) {
00057 double x = xmin + i*dx;
00058 if (logStep) x = std::exp(x);
00059 double y = 0;
00060 if (type < 2)
00061 y = (*function)(x);
00062 else if (type < 4)
00063 y = -(*function)(x);
00064 else
00065 y = std::fabs((*function)(x)-fy);
00066 if (y < yymin) {
00067 xxmin = x;
00068 yymin = y;
00069 }
00070 }
00071
00072 if (logStep) {
00073 xmin = std::exp(xmin);
00074 xmax = std::exp(xmax);
00075 }
00076
00077
00078 xmin = std::max(xmin,xxmin-dx);
00079 xmax = std::min(xmax,xxmin+dx);
00080
00081 return std::min(xxmin, xmax);
00082 }
00083
00084 double MinimBrent(const IGenFunction* function, int type, double &xmin, double &xmax, double xmiddle, double fy, bool &ok, int &niter, double epsabs, double epsrel, int itermax)
00085 {
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100 const double c = 3.81966011250105097e-01;
00101 double u, v, w, x, fv, fu, fw, fx, e, p, q, r, t2, d=0, m, tol;
00102 v = w = x = xmiddle;
00103 e=0;
00104
00105 double a=xmin;
00106 double b=xmax;
00107 if (type < 2)
00108 fv = fw = fx = (*function)(x);
00109 else if (type < 4)
00110 fv = fw = fx = -(*function)(x);
00111 else
00112 fv = fw = fx = std::fabs((*function)(x)-fy);
00113
00114 for (int i=0; i<itermax; i++){
00115 m=0.5*(a + b);
00116 tol = epsrel*(std::fabs(x))+epsabs;
00117 t2 = 2*tol;
00118
00119 if (std::fabs(x-m) <= (t2-0.5*(b-a))) {
00120
00121 ok=true;
00122 niter = i-1;
00123 if (type==1)
00124 return fx;
00125 else if (type==3)
00126 return -fx;
00127 else
00128 return x;
00129 }
00130
00131 if (std::fabs(e)>tol){
00132
00133 r = (x-w)*(fx-fv);
00134 q = (x-v)*(fx-fw);
00135 p = (x-v)*q - (x-w)*r;
00136 q = 2*(q-r);
00137 if (q>0) p=-p;
00138 else q=-q;
00139 r=e;
00140 e=d;
00141
00142
00143
00144
00145 if (std::fabs(p) >= std::fabs(0.5*q*r) || p <= q*(a-x) || p >= q*(b-x)) {
00146
00147 e=(x>=m ? a-x : b-x);
00148 d = c*e;
00149 } else {
00150
00151 d = p/q;
00152 u = x+d;
00153 if (u-a < t2 || b-u < t2)
00154
00155 d=(m-x >= 0) ? std::fabs(tol) : -std::fabs(tol);
00156 }
00157 } else {
00158 e=(x>=m ? a-x : b-x);
00159 d = c*e;
00160 }
00161 u = (std::fabs(d)>=tol ? x+d : x+ ((d >= 0) ? std::fabs(tol) : -std::fabs(tol)) );
00162 if (type < 2)
00163 fu = (*function)(u);
00164 else if (type < 4)
00165 fu = -(*function)(u);
00166 else
00167 fu = std::fabs((*function)(u)-fy);
00168
00169 if (fu<=fx){
00170 if (u<x) b=x;
00171 else a=x;
00172 v=w; fv=fw; w=x; fw=fx; x=u; fx=fu;
00173 } else {
00174 if (u<x) a=u;
00175 else b=u;
00176 if (fu<=fw || w==x){
00177 v=w; fv=fw; w=u; fw=fu;
00178 }
00179 else if (fu<=fv || v==x || v==w){
00180 v=u; fv=fu;
00181 }
00182 }
00183 }
00184
00185 ok = false;
00186 xmin = a;
00187 xmax = b;
00188 niter = itermax;
00189 return x;
00190
00191 }
00192
00193 }
00194 }
00195 }