All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
root_bkt_cern.h
Go to the documentation of this file.
1 /*
2  -------------------------------------------------------------------
3 
4  Copyright (C) 2006-2014, Andrew W. Steiner
5 
6  This file is part of O2scl.
7 
8  O2scl is free software; you can redistribute it and/or modify
9  it under the terms of the GNU General Public License as published by
10  the Free Software Foundation; either version 3 of the License, or
11  (at your option) any later version.
12 
13  O2scl is distributed in the hope that it will be useful,
14  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  GNU General Public License for more details.
17 
18  You should have received a copy of the GNU General Public License
19  along with O2scl. If not, see <http://www.gnu.org/licenses/>.
20 
21  -------------------------------------------------------------------
22 */
23 /** \file root_bkt_cern.h
24  \brief File defining \ref o2scl::root_bkt_cern
25 */
26 #ifndef O2SCL_ROOT_BKT_CERN_H
27 #define O2SCL_ROOT_BKT_CERN_H
28 
29 #include <o2scl/root.h>
30 
31 #ifndef DOXYGEN_NO_O2NS
32 namespace o2scl {
33 #endif
34 
35  /** \brief One-dimensional root-finding routine (CERNLIB)
36 
37  This class attempts to find \f$ x_1 \f$ and \f$ x_2 \f$ in \f$
38  [a,b] \f$ such that:
39  - \f$ f(x_1) f(x_2) \leq 0 \f$,
40  - \f$ |f(x_1)| \leq|f(x_2)| \f$, and
41  - \f$ | x_1-x_2| \leq 2~\mathrm{tol\_abs}~(1+|x_0|) \f$.
42 
43  The function solve_bkt() requires inputs \c x1 and \c x2 such
44  that the first condition, \f$ f(x_1) f(x_2) \leq 0 \f$, already
45  holds.
46 
47  The variable root::tol_abs defaults to \f$ 10^{-8} \f$ and
48  root::ntrial defaults to 200.
49  \comment
50  I'm not sure why I chose these values for tol_abs and ntrial above,
51  as it doesn't seem to me that these values are suggested in
52  CERNLIB. However, they're reasonable so I'll leave them in for
53  now.
54  \endcomment
55 
56  The function solve_bkt() will call the error handler if the root
57  is not initially bracketed. If \ref root::err_nonconv is true
58  (as it is by default), then the error handler will also be
59  called if the number function evaluations is greater than
60  root::ntrial.
61 
62  After a call to \ref solve_bkt(), \ref root::last_ntrial
63  contains the total number of iterations which were used
64 
65 
66  See the \ref onedsolve_subsect section of the User's guide for
67  general information about \o2 solvers.
68 
69  Based on the CERNLIB routines RZEROX and DZEROX, which was
70  based on \ref Bus75 and is documented at
71  http://wwwasdoc.web.cern.ch/wwwasdoc/shortwrupsdir/c200/top.html
72  */
73  template<class func_t=funct11> class root_bkt_cern : public root_bkt<func_t> {
74 
75 #ifndef DOXYGEN_INTERNAL
76 
77  protected:
78 
79  /** \brief Internal storage for the mode
80 
81  This internal variable is actually defined to be smaller by
82  1 than the "mode" as it is defined in the CERNLIB
83  documentation in order to avoid needless subtraction in
84  solve_bkt().
85  */
86  int mode;
87 
88  /// FORTRAN-like function for sign
89  inline double sign(double a, double b) {
90  if (b>=0.0) return fabs(a);
91  return -fabs(a);
92  }
93 
94 #endif
95 
96  public:
97 
98  root_bkt_cern() {
99  mode=0;
100  this->tol_abs=1.0e-8;
101  this->ntrial=200;
102  }
103 
104  /** \brief Set mode of solution (1 or 2)
105 
106  - \c 1 should be used for simple functions where the cost is
107  inexpensive in comparison to one iteration of solve_bkt(),
108  or functions which have a pole near the root (this is the
109  default).
110  - \c 2 should be used for more time-consuming functions.
111 
112  If an integer other than \c 1 or \c 2 is specified,
113  the error handler is called.
114  */
115  int set_mode(int m) {
116  if (m!=1 && m!=2) {
117  O2SCL_ERR("Invalid mode in root_bkt_cern::set_mode().",
119  }
120  mode=m-1;
121  return 0;
122  }
123 
124  /// Return the type, \c "root_bkt_cern".
125  virtual const char *type() { return "root_bkt_cern"; }
126 
127  /** \brief Solve \c func in region \f$ x_1<x<x_2 \f$ returning
128  \f$ x_1 \f$.
129  */
130  virtual int solve_bkt(double &x1, double x2, func_t &func) {
131 
132  double im1[2]={2.0,3.0}, im2[2]={-1.0,3.0}, c=0.0, fa, fb;
133  double atl, a, b, mft;
134  double fc=0.0, d=0.0, fd=0.0, tol, h, hb, w, p, q, fdb, fda, f=0.0;
135  bool lmt[2];
136  int ie=0, loop, mf;
137  char ch;
138 
139  fb=func(x1);
140  fa=func(x2);
141 
142  if (fa*fb>0.0) {
143  O2SCL_ERR2("Endpoints don't bracket function in ",
144  "root_bkt_cern::solve_bkt().",exc_einval);
145  }
146 
147  atl=fabs(this->tol_abs);
148  b=x1;
149  a=x2;
150  lmt[1]=true;
151  mf=2;
152  loop=1;
153  do {
154  if (loop==1) {
155  c=a;
156  fc=fa;
157  ie=0;
158  } else if (loop==2) {
159  ie=0;
160  }
161  if (fabs(fc)<fabs(fb)) {
162  if (c!=a) {
163  d=a;
164  fd=fa;
165  }
166  a=b;
167  b=c;
168  c=a;
169  fa=fb;
170  fb=fc;
171  fc=fa;
172  }
173  tol=atl*(1.0+fabs(c));
174  h=0.5*(c+b);
175  hb=h-b;
176 
177  if (this->verbose>0) {
178  this->print_iter(c,fc,mf-2,fabs(hb),tol,"root_bkt_cern");
179  }
180 
181  if (fabs(hb)>tol) {
182  if (ie>im1[mode]) {
183  w=hb;
184  } else {
185  tol*=sign(1.0,hb);
186  p=(b-a)*fb;
187  lmt[0]=(ie<=1);
188  if (lmt[mode]) {
189  q=fa-fb;
190  lmt[1]=false;
191  } else {
192  fdb=(fd-fb)/(d-b);
193  fda=(fd-fa)/(d-a);
194  p*=fda;
195  q=fdb*fa-fda*fb;
196  }
197  if (p<0.0) {
198  p=-p;
199  q=-q;
200  }
201  if (ie==im2[mode]) p+=p;
202  if (p==0.0 || p<=q*tol) {
203  w=tol;
204  } else if (p<hb*q) {
205  w=p/q;
206  } else {
207  w=hb;
208  }
209  }
210  d=a;
211  a=b;
212  fd=fa;
213  fa=fb;
214  b+=w;
215  mf++;
216  if (mf>this->ntrial) {
217  this->last_ntrial=this->ntrial;
218  O2SCL_CONV2_RET("Too many function calls in ",
219  "root_bkt_cern::solve_bkt().",exc_emaxiter,
220  this->err_nonconv);
221  }
222 
223  fb=func(b);
224 
225  if (fb==0.0 || sign(1.0,fc)==sign(1.0,fb)) {
226  loop=1;
227  } else if (w==hb) {
228  loop=2;
229  } else {
230  ie++;
231  loop=3;
232  }
233  } else {
234  loop=0;
235  }
236  } while (loop>0);
237  x1=c;
238  this->last_ntrial=mf;
239  return o2scl::success;
240  }
241 
242  };
243 
244 #ifndef DOXYGEN_NO_O2NS
245 }
246 #endif
247 
248 #endif
One-dimensional root-finding routine (CERNLIB)
Definition: root_bkt_cern.h:73
int ntrial
Maximum number of iterations (default 100)
Definition: root.h:75
int mode
Internal storage for the mode.
Definition: root_bkt_cern.h:86
double tol_abs
The minimum allowable stepsize (default )
Definition: root.h:69
invalid argument supplied by user
Definition: err_hnd.h:59
exceeded max number of iterations
Definition: err_hnd.h:73
#define O2SCL_CONV2_RET(d, d2, n, b)
Set an error and return the error value, two-string version.
Definition: err_hnd.h:298
One-dimensional bracketing solver [abstract base].
Definition: root.h:144
bool err_nonconv
If true, call the error handler if the solver does not converge (default true)
Definition: root.h:80
virtual int solve_bkt(double &x1, double x2, func_t &func)
Solve func in region returning .
virtual int print_iter(double x, double y, int iter, double value=0.0, double limit=0.0, std::string comment="")
Print out iteration information.
Definition: root.h:98
#define O2SCL_ERR2(d, d2, n)
Set an error, two-string version.
Definition: err_hnd.h:281
int set_mode(int m)
Set mode of solution (1 or 2)
double sign(double a, double b)
FORTRAN-like function for sign.
Definition: root_bkt_cern.h:89
#define O2SCL_ERR(d, n)
Set an error with message d and code n.
Definition: err_hnd.h:273
int last_ntrial
The number of iterations used in the most recent solve.
Definition: root.h:83
static const double x2[5]
Definition: inte_qng_gsl.h:66
virtual const char * type()
Return the type, "root_bkt_cern".
static const double x1[5]
Definition: inte_qng_gsl.h:48
int verbose
Output control (default 0)
Definition: root.h:72
Success.
Definition: err_hnd.h:47

Documentation generated with Doxygen. Provided under the GNU Free Documentation License (see License Information).
Hosted at Get Object-oriented Scientific Computing
Lib at SourceForge.net. Fast, secure and Free Open Source software
downloads..