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_ROOT_H
00024 #define O2SCL_ROOT_H
00025
00026 #include <iostream>
00027 #include <cmath>
00028 #include <o2scl/err_hnd.h>
00029 #include <o2scl/collection.h>
00030 #include <o2scl/funct.h>
00031
00032 #ifndef DOXYGENP
00033 namespace o2scl {
00034 #endif
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044 template<class param_t, class func_t, class dfunc_t=func_t>
00045 class root {
00046
00047 public:
00048
00049 root() {
00050 ntrial=100;
00051 tolf=1.0e-8;
00052 verbose=0;
00053 tolx=1.0e-12;
00054 deriv_eps=0.0;
00055 last_ntrial=0;
00056 }
00057
00058 virtual ~root() {}
00059
00060
00061
00062
00063 double tolf;
00064
00065
00066
00067
00068 double tolx;
00069
00070
00071 int verbose;
00072
00073
00074 int ntrial;
00075
00076
00077 bool over_bkt;
00078
00079
00080 bool over_de;
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092 double deriv_eps;
00093
00094
00095 int last_ntrial;
00096
00097
00098 virtual const char *type() { return "root"; }
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112 virtual int print_iter(double x, double y, int iter, double value=0.0,
00113 double limit=0.0, std::string comment="") {
00114 if (verbose<=0) return gsl_success;
00115
00116 char ch;
00117
00118 std::cout << comment << " Iteration: " << iter << std::endl;
00119 if (x<0) std::cout << x << " ";
00120 else std::cout << " " << x << " ";
00121 if (y<0) std::cout << y << " ";
00122 else std::cout << " " << y << " ";
00123 if (value<0) std::cout << value << " ";
00124 else std::cout << " " << value << " ";
00125 if (limit<0) std::cout << limit << std::endl;
00126 else std::cout << " " << limit << std::endl;
00127 if (verbose>1) {
00128 std::cout << "Press a key and type enter to continue. ";
00129 std::cin >> ch;
00130 }
00131
00132 return gsl_success;
00133 }
00134
00135
00136
00137
00138 virtual int solve(double &x, param_t &pa, func_t &func) {
00139
00140 if (over_bkt) {
00141 double x2=0.0, dx, fx, fx2;
00142 int i=0;
00143 bool done=false;
00144
00145 while(done==false && i<10) {
00146
00147 func(x,fx,pa);
00148 func(x*(1.0+deriv_eps),fx2,pa);
00149
00150 dx=(fx2-fx)/(deriv_eps*x);
00151 x2=x-2.0*fx/dx;
00152
00153 func(x2,fx2,pa);
00154
00155 if (fx*fx2<0.0) {
00156 done=true;
00157 } else {
00158 x=(x2+x)/2.0;
00159 }
00160
00161 i++;
00162 }
00163 if (done==false) {
00164 set_err_ret("Failed to bracket function in root::solve().",
00165 o2scl::gsl_emaxiter);
00166 }
00167 return solve_bkt(x,x2,pa,func);
00168 }
00169
00170 return 0;
00171 }
00172
00173
00174
00175
00176 virtual int solve_bkt(double &x1, double x2, param_t &pa,
00177 func_t &func)
00178 {
00179 return solve(x1,pa,func);
00180 }
00181
00182
00183
00184
00185 virtual int solve_de(double &x, param_t &pa, func_t &func, dfunc_t &df) {
00186
00187 if (over_bkt) {
00188 double x2=0.0, dx, fx, fx2;
00189 int i=0;
00190 bool done=false;
00191
00192
00193 while(done==false && i<10) {
00194
00195 func(x,fx,pa);
00196 df(x,dx,pa);
00197
00198 x2=x-2.0*fx/dx;
00199
00200 func(x2,fx2,pa);
00201
00202 if (fx*fx2<0.0) {
00203 done=true;
00204 } else {
00205 x=(x2+x)/2.0;
00206 }
00207 i++;
00208 }
00209
00210 if (done==false) {
00211 set_err_ret("Failed to bracket function in root::solve_de().",
00212 o2scl::gsl_efailed);
00213 }
00214
00215 return solve_bkt(x,x2,pa,func);
00216 }
00217
00218 return solve(x,pa,func);
00219 }
00220
00221 };
00222
00223 #ifndef DOXYGENP
00224 template<> int io_tlate<root<void *,funct<void *> > >::input
00225 (cinput *co, in_file_format *ins, root<void *, funct<void *> > *ro);
00226 template<> int io_tlate<root<void *,funct<void *> > >::output
00227 (coutput *co, out_file_format *outs, root<void *, funct<void *> > *ro);
00228 template<> const char *io_tlate<root<void *,funct<void *> > >::type();
00229 #endif
00230
00231 typedef io_tlate<root<void *,funct<void *> > > root_io_type;
00232
00233 #ifndef DOXYGENP
00234 }
00235 #endif
00236
00237 #endif
00238