// $Id: numRec.h 9652 2011-07-12 13:59:26Z rubi $ // version 1.00 // last modified 2 Nov 2002 #ifndef ___NUM_REC #define ___NUM_REC #include #include #include using namespace std; #include "definitions.h" #include "errorMsg.h" #include "uniformDistribution.h" #include "logFile.h" //#define VERBOS #define SIGN(a,b) ((b) >= 0.0 ? fabs(a) : -fabs(a)) //========================== function brent ========================================= template MDOUBLE brent(MDOUBLE ax, MDOUBLE bx, MDOUBLE cx, regF f, MDOUBLE tol, MDOUBLE *xmin) { const int ITMAX = 100; const MDOUBLE CGOLD = 0.3819660f; const MDOUBLE ZEPS = 1.0e-10f; int iter; MDOUBLE a,b,d=0.0,etemp,fu,fv,fw,fx,p,q,r,tol1,tol2,u,v,w,x,xm; MDOUBLE e=0.0; a=(ax < cx ? ax : cx); b=(ax > cx ? ax : cx); x=w=v=bx; fw=fv=fx=f(x); LOG(10,<<"brent, f("< tol1) { r=(x-w)*(fx-fv); q=(x-v)*(fx-fw); p=(x-v)*q-(x-w)*r; q=2.0*(q-r); if (q > 0.0) p = -p; q=fabs(q); etemp=e; e=d; if (fabs(p) >= fabs(0.5*q*etemp) || p <= q*(a-x) || p >= q*(b-x)) d=CGOLD*(e=(x >= xm ? a-x : b-x)); else { d=p/q; u=x+d; if (u-a < tol2 || b-u < tol2) d=SIGN(tol1,xm-x); } } else { d=CGOLD*(e=(x >= xm ? a-x : b-x)); } u=(fabs(d) >= tol1 ? x+d : x+SIGN(tol1,d)); fu=f(u); LOG(10,<<"brent, f("<= x) a=x; else b=x; v=w;w=x;x=u; fv=fw;fw=fx; fx=fu; } else { if (u < x) a=u; else b=u; if (fu <= fw || w == x) { v=w; w=u; fv=fw; fw=fu; } else if (fu <= fv || v == x || v == w) { v=u; fv=fu; } } } errorMsg::reportError(" too many iterations in function, brent. "); // also quit the program return -1; } /* //A doubleRep implementation of brent cause return type function overloading is forbidden in c++ template doubleRep brentDoubleRep(doubleRep ax, doubleRep bx, doubleRep cx, regF f, doubleRep tol, MDOUBLE *xmin) { const int ITMAX = 100; const doubleRep CGOLD(0.3819660f); const doubleRep ZEPS(1.0e-10f); doubleRep minusOne(-1.0); int iter; doubleRep fu,fv,fw,fx,a,b,etemp,p,q,r,u,v,w,x; doubleRep d(0.0); doubleRep e(0.0); doubleRep half(0.5); doubleRep two(2.0); doubleRep zero(0.0); a=(ax < cx ? ax : cx); b=(ax > cx ? ax : cx); x=w=v=bx; fw=fv=fx=f(convert(x)); LOG(10,<<"brent, f("< convert(tol1)) { r=(x+minusOne*w)*(fx+minusOne*fv); q=(x+minusOne*v)*(fx+minusOne*fw); p=(x+minusOne*v)*q+minusOne*(x+minusOne*w)*r; q=two*(q+minusOne*r); if (q > zero) p = minusOne*p; doubleRep newQ(fabs(convert(q))); q=newQ; etemp=e; e=d; if (fabs(convert(p)) >= fabs(convert(half*q*etemp)) || p <= q*(a+minusOne*x) || p >= q*(b+minusOne*x)) d=CGOLD*(e=(x >= xm ? a+minusOne*x : b+minusOne*x)); else { d=p/q; u=x+d; if (u+minusOne*a < tol2 || b+minusOne*u < tol2){ doubleRep newD(SIGN(convert(tol1),convert(xm+minusOne*x))); d=newD; } } } else { d=CGOLD*(e=(x >= xm ? a+minusOne*x : b+minusOne*x)); } u=(fabs(convert(d)) >= convert(tol1) ? x+d : x+SIGN(convert(tol1),convert(d))); fu=f(convert(u)); LOG(10,<<"brent, f("<= x) a=x; else b=x; v=w;w=x;x=u; fv=fw;fw=fx; fx=fu; } else { if (u < x) a=u; else b=u; if (fu <= fw || w == x) { v=w; w=u; fv=fw; fw=fu; } else if (fu <= fv || v == x || v == w) { v=u; fv=fu; } } } errorMsg::reportError(" too many iterations in function, brentDoubleRep. "); // also quit the program return minusOne; } */ // ===================================== function dbrent ======================================== /* The efficiency of this function for likelihood computations can be improved by replacing functors regF f and dF df with one objects that preforms the likelihood computation once and produces both L(t) and dL(t)/dt. This object will provide methods: MDOUBLE f(MDOUBLE x) MDOUBLE df(MDOUBLE x) */ #define ITMAX 100 #define ZEPS 1.0e-10 #define MOV3(a,b,c, d,e,f) (a)=(d);(b)=(e);(c)=(f); template MDOUBLE dbrent(MDOUBLE ax, MDOUBLE bx, MDOUBLE cx, regF f, dF df, MDOUBLE tol, MDOUBLE *xmin) { int iter,ok1,ok2; MDOUBLE a,b,d=0.0,d1,d2,du,dv,dw,dx,e=0.0; MDOUBLE fu,fv,fw,fx,olde,tol1,tol2,u,u1,u2,v,w,x,xm; a=(ax < cx ? ax : cx); b=(ax > cx ? ax : cx); //ensuring x is between a and b if (bx>b) { x=w=v=b;b=bx;} else if (bx10) cout<<"iteration: "< doubleRep dbrentDoubleRep(doubleRep ax, doubleRep bx, doubleRep cx, regF f, dF df, doubleRep tol, MDOUBLE *xmin) { int iter,ok1,ok2; doubleRep a,b,d1,d2; doubleRep d(0.0); doubleRep e(0.0); doubleRep olde,u,u1,u2,v,w,x,xm; doubleRep fu,fv,fw,fx,du,dv,dw,dx; doubleRep minusOne(-1.0); doubleRep half(0.5); doubleRep two(2.0); doubleRep zero(0.0); a=(ax < cx ? ax : cx); b=(ax > cx ? ax : cx); //ensuring x is between a and b if (bx>b) { x=w=v=b;b=bx;} else if (bx10) cout<<"iteration: "< MDOUBLE rtbis(regF func,MDOUBLE x1, MDOUBLE x2, MDOUBLE xacc) { const int max_number_of_iter = 100; MDOUBLE f = func(x1); MDOUBLE fmid = func(x2); if (f*fmid >=0.0) { errorMsg::reportError(" error in function rtbis, root must be bracketed for bisection in rtbis "); // also quit the program } MDOUBLE dx, rtb; if (f<0.0) { dx = x2-x1; rtb = x1; } else { dx = x1-x2; rtb = x2; } for (int j=1; j <= max_number_of_iter; ++j) { dx *= 0.5; MDOUBLE xmid = rtb+dx; MDOUBLE fmid = func(xmid); if (fmid <= 0.0) rtb = xmid; if ((fabs(dx) < xacc) || (fmid == 0.0)) return rtb; } errorMsg::reportError("Error in function rtbis..."); // also quit the program... return -1.0; } //Given a function func and an initial guessed range (x1,x2), the routine expands the range //geometrically until a root is bracketed by the returned values x1 and x2 (in which case zbrac retruns true) //or until the range becomes large unacceptably large (in which case zbrac return false). template bool zbrac(regF func, MDOUBLE &x1, MDOUBLE &x2) { const int NTRY=50; const MDOUBLE FACTOR= 1.6; int j; MDOUBLE f1,f2; if (x1 == x2) errorMsg::reportError("Bad initial range in zbrac"); f1 = func(x1); f2 = func(x2); for (j = 0; j < NTRY; j++) { if (f1 * f2 < 0.0) return true; if (fabs(f1) < fabs(f2)) f1=func(x1 += FACTOR*(x1-x2)); else f2=func(x2 += FACTOR*(x2-x1)); } return false; } // ================================ function brent new ====================================== int MyJacobi(VVdouble &Insym, VVdouble &RightEigenV, Vdouble &EigenValues); MDOUBLE sign(MDOUBLE a,MDOUBLE b); MDOUBLE pythag(const MDOUBLE a, const MDOUBLE b); void houseHolder(VVdouble &mat,VVdouble &Q); void tred2(VVdouble &a, Vdouble &d, Vdouble &e); void QL(Vdouble &d, Vdouble &e, VVdouble &z); void computeEigenSystem(VVdouble &symmetricMatrix,VVdouble &eigenVectros,Vdouble &diagonal); MDOUBLE performKSTest(const uniformDistribution& empiricalDist, Vdouble& observedDist); // perform Kolomogorov-Smirnoff test MDOUBLE computeProbForKS (const MDOUBLE QsParam); // function called only by performKSTest #endif