00001 #ifndef NR_BRENT_H
00002 #define NR_BRENT_H
00003
00004 #include <math.h>
00005 #include <iostream>
00006 #include "mnbrak.h"
00007 #include "utils.h"
00008
00009 namespace nr {
00010
00016 template < class Real, class Func >
00017 Real brent (
00018 Real ax, Real bx, Real cx,
00019 Func (*func),
00020 Real tol,
00021 Real *xmin,
00022 unsigned int ITMAX = 100,
00023 Real ZEPS = 1.0e-10,
00024 Real CGOLD = 0.3819660
00025 )
00026 {
00027 #define SHFT(a,b,c,d) (a)=(b);(b)=(c);(c)=(d);
00028
00029 int iter;
00030 Real a,b,d,etemp,fu,fv,fw,fx,p,q,r,tol1,tol2,u,v,w,x,xm;
00031 Real e=0.0;
00032
00033 a=(ax < cx ? ax : cx);
00034 b=(ax > cx ? ax : cx);
00035 x=w=v=bx;
00036 fw=fv=fx=(*func)(x);
00037 for (iter=1;iter<=ITMAX;iter++) {
00038 xm=0.5*(a+b);
00039 tol2=2.0*(tol1=tol*fabs(x)+ZEPS);
00040 if (fabs(x-xm) <= (tol2-0.5*(b-a))) {
00041 *xmin=x;
00042
00043 return fx;
00044 }
00045 if (fabs(e) > tol1) {
00046 r=(x-w)*(fx-fv);
00047 q=(x-v)*(fx-fw);
00048 p=(x-v)*q-(x-w)*r;
00049 q=2.0*(q-r);
00050 if (q > 0.0) p = -p;
00051 q=fabs(q);
00052 etemp=e;
00053 e=d;
00054 if (fabs(p) >= fabs(0.5*q*etemp) || p <= q*(a-x) || p >= q*(b-x))
00055 d=CGOLD*(e=(x >= xm ? a-x : b-x));
00056 else {
00057 d=p/q;
00058 u=x+d;
00059 if (u-a < tol2 || b-u < tol2)
00060 d=SIGN(tol1,xm-x);
00061 }
00062 } else {
00063 d=CGOLD*(e=(x >= xm ? a-x : b-x));
00064 }
00065 u=(fabs(d) >= tol1 ? x+d : x+SIGN(tol1,d));
00066 fu=(*func)(u);
00067 if (fu <= fx) {
00068 if (u >= x) a=x; else b=x;
00069 SHFT(v,w,x,u)
00070 SHFT(fv,fw,fx,fu)
00071 } else {
00072 if (u < x) a=u; else b=u;
00073 if (fu <= fw || w == x) {
00074 v=w;
00075 w=u;
00076 fv=fw;
00077 fw=fu;
00078 } else if (fu <= fv || v == x || v == w) {
00079 v=u;
00080 fv=fu;
00081 }
00082 }
00083 }
00084 nrerror("Too many iterations in brent");
00085 (*xmin) = x;
00086 return fx;
00087 #undef SHFT
00088 }
00089
00090 }
00091
00092 #endif