00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #ifndef O2SCL_CERN_ROOT_H
00024 #define O2SCL_CERN_ROOT_H
00025
00026 #include <o2scl/root.h>
00027
00028 #ifndef DOXYGENP
00029 namespace o2scl {
00030 #endif
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056 template<class param_t, class func_t=funct<param_t> >
00057 class cern_root : public root<param_t,func_t>
00058 {
00059
00060 #ifndef DOXYGEN_INTERNAL
00061
00062 protected:
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072 int mode;
00073
00074
00075 inline double sign(double a, double b) {
00076 if (b>=0.0) return fabs(a);
00077 return -fabs(a);
00078 }
00079
00080 friend class io_tlate<cern_root>;
00081
00082 #endif
00083
00084 public:
00085
00086 cern_root()
00087 {
00088 mode=0;
00089 this->tolx=1.0e-8;
00090 this->ntrial=200;
00091 this->over_bkt=true;
00092 }
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107 int set_mode(int m) {
00108 if (m!=1 && m!=2) {
00109 mode=0;
00110 set_err_ret("Invalid mode in cern_root::set_mode().",
00111 o2scl::gsl_einval);
00112 }
00113 mode=m-1;
00114 return 0;
00115 }
00116
00117
00118 virtual const char *type() { return "cern_root"; }
00119
00120
00121
00122
00123 virtual int solve_bkt(double &x1, double x2, param_t &pa,
00124 func_t &func)
00125 {
00126
00127 double im1[2]={2.0,3.0}, im2[2]={-1.0,3.0}, c=0.0, fa, fb;
00128 double atl, a, b, mft;
00129 double fc=0.0, d=0.0, fd=0.0, tol, h, hb, w, p, q, fdb, fda, f=0.0;
00130 bool lmt[2];
00131 int ie=0, loop, mf;
00132 char ch;
00133
00134 func(x1,fb,pa);
00135 func(x2,fa,pa);
00136
00137 if (fa*fb>0.0) {
00138 set_err_ret
00139 ("Endpoints don't bracket function in cern_root::solve_bkt().",
00140 o2scl::gsl_einval);
00141 }
00142
00143 atl=fabs(this->tolx);
00144 b=x1;
00145 a=x2;
00146 lmt[1]=true;
00147 mf=2;
00148 loop=1;
00149 do {
00150 if (loop==1) {
00151 c=a;
00152 fc=fa;
00153 ie=0;
00154 } else if (loop==2) {
00155 ie=0;
00156 }
00157 if (fabs(fc)<fabs(fb)) {
00158 if (c!=a) {
00159 d=a;
00160 fd=fa;
00161 }
00162 a=b;
00163 b=c;
00164 c=a;
00165 fa=fb;
00166 fb=fc;
00167 fc=fa;
00168 }
00169 tol=atl*(1.0+fabs(c));
00170 h=0.5*(c+b);
00171 hb=h-b;
00172
00173 if (this->verbose>0) {
00174 this->print_iter(c,fc,mf-2,fabs(hb),tol,"cern_root");
00175 }
00176
00177 if (fabs(hb)>tol) {
00178 if (ie>im1[mode]) {
00179 w=hb;
00180 } else {
00181 tol*=sign(1.0,hb);
00182 p=(b-a)*fb;
00183 lmt[0]=(ie<=1);
00184 if (lmt[mode]) {
00185 q=fa-fb;
00186 lmt[1]=false;
00187 } else {
00188 fdb=(fd-fb)/(d-b);
00189 fda=(fd-fa)/(d-a);
00190 p*=fda;
00191 q=fdb*fa-fda*fb;
00192 }
00193 if (p<0.0) {
00194 p=-p;
00195 q=-q;
00196 }
00197 if (ie==im2[mode]) p+=p;
00198 if (p==0.0 || p<=q*tol) {
00199 w=tol;
00200 } else if (p<hb*q) {
00201 w=p/q;
00202 } else {
00203 w=hb;
00204 }
00205 }
00206 d=a;
00207 a=b;
00208 fd=fa;
00209 fa=fb;
00210 b+=w;
00211 mf++;
00212 if (mf>this->ntrial) {
00213 set_err_ret
00214 ("Too many function calls in cern_root::solve_bkt().",
00215 o2scl::gsl_emaxiter);
00216 }
00217
00218 func(b,fb,pa);
00219
00220 if (fb==0.0 || sign(1.0,fc)==sign(1.0,fb)) {
00221 loop=1;
00222 } else if (w==hb) {
00223 loop=2;
00224 } else {
00225 ie++;
00226 loop=3;
00227 }
00228 } else {
00229 loop=0;
00230 }
00231 } while (loop>0);
00232 x1=c;
00233 this->last_ntrial=mf;
00234 return o2scl::gsl_success;
00235 }
00236
00237 };
00238
00239 #ifndef DOXYGENP
00240 template<> int io_tlate<cern_root<void *,funct<void *> > >::input
00241 (cinput *co, in_file_format *ins, cern_root<void *, funct<void *> > *ro);
00242 template<> int io_tlate<cern_root<void *,funct<void *> > >::output
00243 (coutput *co, out_file_format *outs,
00244 cern_root<void *, funct<void *> > *ro);
00245 template<> const char *io_tlate<cern_root<void *,funct<void *> > >::type();
00246 #endif
00247
00248 typedef io_tlate<cern_root<void *,funct<void *> > > cern_root_io_type;
00249
00250 #ifndef DOXYGENP
00251 }
00252 #endif
00253
00254 #endif