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_GSL_ROOT_BRENT_H
00024 #define O2SCL_GSL_ROOT_BRENT_H
00025
00026 #include <gsl/gsl_math.h>
00027 #include <gsl/gsl_roots.h>
00028 #include <o2scl/funct.h>
00029 #include <o2scl/root.h>
00030
00031 #ifndef DOXYGENP
00032 namespace o2scl {
00033 #endif
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053 template<class param_t, class func_t=funct<void *>, class dfunc_t=func_t>
00054 class gsl_root_brent : public root<param_t,func_t,dfunc_t>
00055
00056 {
00057
00058 public:
00059
00060 gsl_root_brent() {
00061 test_form=0;
00062 this->over_bkt=true;
00063 }
00064
00065
00066 virtual const char *type() { return "gsl_root_brent"; }
00067
00068
00069
00070
00071
00072
00073
00074 int iterate(func_t &f) {
00075
00076 double tol, m;
00077
00078 int ac_equal = 0;
00079
00080 if ((fb < 0 && fc < 0) || (fb > 0 && fc > 0)) {
00081 ac_equal = 1;
00082 c = a;
00083 fc = fa;
00084 d = b - a;
00085 e = b - a;
00086 }
00087
00088 if (fabs (fc) < fabs (fb)) {
00089 ac_equal = 1;
00090 a = b;
00091 b = c;
00092 c = a;
00093 fa = fb;
00094 fb = fc;
00095 fc = fa;
00096 }
00097
00098 tol = 0.5 * GSL_DBL_EPSILON * fabs (b);
00099 m = 0.5 * (c - b);
00100
00101 if (fb == 0) {
00102 root = b;
00103 x_lower = b;
00104 x_upper = b;
00105
00106 return o2scl::gsl_success;
00107 }
00108 if (fabs (m) <= tol) {
00109 root = b;
00110
00111 if (b < c) {
00112 x_lower = b;
00113 x_upper = c;
00114 } else {
00115 x_lower = c;
00116 x_upper = b;
00117 }
00118
00119 return o2scl::gsl_success;
00120 }
00121
00122 if (fabs (e) < tol || fabs (fa) <= fabs (fb)) {
00123 d = m;
00124 e = m;
00125 } else {
00126 double p, q, r;
00127 double s = fb / fa;
00128
00129 if (ac_equal) {
00130 p = 2 * m * s;
00131 q = 1 - s;
00132 } else {
00133 q = fa / fc;
00134 r = fb / fc;
00135 p = s * (2 * m * q * (q - r) - (b - a) * (r - 1));
00136 q = (q - 1) * (r - 1) * (s - 1);
00137 }
00138
00139 if (p > 0) {
00140 q = -q;
00141 } else {
00142 p = -p;
00143 }
00144 if (2 * p < GSL_MIN (3 * m * q - fabs (tol * q), fabs (e * q))) {
00145 e = d;
00146 d = p / q;
00147 } else {
00148
00149
00150 d = m;
00151 e = m;
00152 }
00153 }
00154
00155 a = b;
00156 fa = fb;
00157
00158 if (fabs (d) > tol) {
00159 b += d;
00160 } else {
00161 b += (m > 0 ? +tol : -tol);
00162 }
00163
00164 f(b,fb,*params);
00165
00166
00167
00168
00169 root = b;
00170
00171 if ((fb < 0 && fc < 0) || (fb > 0 && fc > 0)) {
00172 c = a;
00173 }
00174 if (b < c) {
00175 x_lower = b;
00176 x_upper = c;
00177 } else {
00178 x_lower = c;
00179 x_upper = b;
00180 }
00181
00182 return o2scl::gsl_success;
00183 }
00184
00185
00186 virtual int solve_bkt(double &x1, double x2, param_t &pa,
00187 func_t &f) {
00188
00189 int status, iter=0;
00190
00191 set(f,x1,x2,pa);
00192
00193 if (test_form==0) {
00194
00195
00196 status=GSL_CONTINUE;
00197 while (status==GSL_CONTINUE && iter<this->ntrial) {
00198
00199 iter++;
00200 iterate(f);
00201 status=gsl_root_test_interval(x_lower,x_upper,0.0,this->tolx);
00202
00203 if (this->verbose>0) {
00204 double y;
00205
00206 f(root,y,pa);
00207
00208 print_iter(root,y,iter,fabs(x_upper-x_lower),this->tolx,
00209 "gsl_root_brent");
00210 }
00211 }
00212
00213 } else if (test_form==1) {
00214
00215
00216 status=GSL_CONTINUE;
00217 while (status==GSL_CONTINUE && iter<this->ntrial) {
00218
00219 iter++;
00220 iterate(f);
00221
00222 double y;
00223
00224 f(root,y,pa);
00225
00226 if (fabs(y)<this->tolf) status=o2scl::gsl_success;
00227
00228 status=gsl_root_test_interval(x_lower,x_upper,0.0,this->tolx);
00229
00230 if (this->verbose>0) {
00231 print_iter(root,y,iter,fabs(x_upper-x_lower),this->tolx,
00232 "gsl_root_brent");
00233 }
00234 }
00235
00236
00237 } else {
00238
00239
00240 status=GSL_CONTINUE;
00241 while (status==GSL_CONTINUE && iter<this->ntrial) {
00242
00243 iter++;
00244 iterate(f);
00245 status=gsl_root_test_interval(x_lower,x_upper,0.0,this->tolx);
00246
00247 if (status==o2scl::gsl_success) {
00248 double y;
00249
00250 f(root,y,pa);
00251
00252 if (fabs(y)>=this->tolf) status=GSL_CONTINUE;
00253 }
00254
00255 if (this->verbose>0) {
00256 double y;
00257
00258 f(root,y,pa);
00259
00260 print_iter(root,y,iter,fabs(x_upper-x_lower),this->tolx,
00261 "gsl_root_brent");
00262 }
00263 }
00264
00265 }
00266
00267 x1=root;
00268
00269 if (status!=o2scl::gsl_success) {
00270 int ret=o2scl::err_hnd->get_errno();
00271 return ret;
00272 }
00273 if (iter>=this->ntrial) {
00274 set_err_ret("solve_bkt() exceeded maximum number of iterations.",
00275 o2scl::gsl_emaxiter);
00276 }
00277
00278 return o2scl::gsl_success;
00279 }
00280
00281
00282 int test_form;
00283
00284
00285 double get_root() { return root; }
00286
00287
00288 double get_lower() { return x_lower; }
00289
00290
00291 double get_upper() { return x_upper; }
00292
00293
00294
00295
00296
00297
00298 int set(func_t &ff, double lower, double upper, param_t &pa) {
00299
00300 if (lower > upper) {
00301 set_err_ret("Invalid interval in gsl_root_brent::set().",
00302 o2scl::gsl_einval);
00303 }
00304
00305 params=&pa;
00306
00307 x_lower=lower;
00308 x_upper=upper;
00309 root=0.5*(lower+upper);
00310
00311 double f_lower, f_upper;
00312
00313 ff(x_lower,f_lower,pa);
00314 ff(x_upper,f_upper,pa);
00315
00316 a = x_lower;
00317 fa = f_lower;
00318
00319 b = x_upper;
00320 fb = f_upper;
00321
00322 c = x_upper;
00323 fc = f_upper;
00324
00325 d = x_upper - x_lower;
00326 e = x_upper - x_lower;
00327
00328 if ((f_lower < 0.0 && f_upper < 0.0) ||
00329 (f_lower > 0.0 && f_upper > 0.0)) {
00330 set_err_ret
00331 ("Endpoints don't straddle y=0 in gsl_root_brent::set().",
00332 o2scl::gsl_einval);
00333 }
00334
00335 return o2scl::gsl_success;
00336
00337 }
00338
00339 #ifndef DOXYGEN_INTERNAL
00340
00341 protected:
00342
00343
00344 double root;
00345
00346 double x_lower;
00347
00348 double x_upper;
00349
00350 param_t *params;
00351
00352
00353
00354 double a, b, c, d, e;
00355 double fa, fb, fc;
00356
00357
00358 #endif
00359
00360 };
00361
00362 #ifndef DOXYGENP
00363 template<> int io_tlate<gsl_root_brent<void *,funct<void *> > >::input
00364 (cinput *co, in_file_format *ins,
00365 gsl_root_brent<void *, funct<void *> > *ro);
00366 template<> int io_tlate<gsl_root_brent<void *,funct<void *> > >::output
00367 (coutput *co, out_file_format *outs,
00368 gsl_root_brent<void *, funct<void *> > *ro);
00369 template<> const char *io_tlate<gsl_root_brent<void *,
00370 funct<void *> > >::type();
00371 #endif
00372
00373 typedef io_tlate<gsl_root_brent<void *,funct<void *> > >
00374 gsl_root_brent_io_type;
00375
00376 #ifndef DOXYGENP
00377 }
00378 #endif
00379
00380 #endif