Documentation


brent.h

Go to the documentation of this file.
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             //std::cout<<"brent returns in "<<iter<<" iterations"<<std::endl;
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); //std::cout << "brent, *func = "<< fu <<std::endl;
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 } // end namespace nr
00091 
00092 #endif

Generated on Thu Dec 23 13:52:23 2004 by doxygen 1.3.6