deriv.h
Go to the documentation of this file.
1 /*
2  -------------------------------------------------------------------
3 
4  Copyright (C) 2006-2017, 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 #ifndef O2SCL_DERIV_H
24 #define O2SCL_DERIV_H
25 
26 /** \file deriv.h
27  \brief File defining \ref o2scl::deriv_base
28 */
29 
30 #include <iostream>
31 #include <cmath>
32 #include <o2scl/funct.h>
33 
34 #ifndef DOXYGEN_NO_O2NS
35 namespace o2scl {
36 #endif
37 
38  /** \brief Numerical differentiation base [abstract base]
39 
40  This base class does not perform any actual differentiation. Use
41  one of the children \ref o2scl::deriv_cern, \ref
42  o2scl::deriv_gsl, or \ref o2scl::deriv_eqi instead.
43 
44  This base class contains some code to automatically apply
45  the first derivative routines to compute second or third
46  derivatives. The error estimates for these will likely
47  be underestimated.
48 
49  \note Because this class template aims to automatically provide
50  second and third derivatives, one must overload either both
51  deriv() and deriv_int() or both deriv_err() and deriv_err_int().
52 
53  \note If \ref err_nonconv is set to false, and the derivative
54  computation fails, then the functions \ref deriv(),
55  \ref deriv2() and \ref deriv3() may return the wrong result
56  without warning. Similarly, if \ref err_nonconv is set to
57  false, it is the user's responsibility to check the
58  return value from \ref deriv_err(), \ref deriv2_err(), and
59  \ref deriv3_err() to see if an error occurred.
60 
61  \future Improve the methods for second and third derivatives
62  */
63  template<class func_t=funct11> class deriv_base {
64 
65 #ifndef DOXYGEN_INTERNAL
66 
67  protected:
68 
69  /** \brief A structure for passing the function to second and
70  third derivatives [protected]
71  */
72  typedef struct {
73 
74  public:
75 
76  /// The pointer to the function
77  func_t *func;
78 
79  } dpars;
80 
81  /// Avoids infinite loops in case the user calls the base class version
82  bool from_deriv;
83 
84 #endif
85 
86  public:
87 
88  deriv_base() {
89  verbose=0;
90  from_deriv=false;
91  err_nonconv=true;
92  }
93 
94  virtual ~deriv_base() {}
95 
96  /// If true, call the error handler if the routine does not "converge"
98 
99  /** \brief Calculate the first derivative of \c func w.r.t. x
100 
101  After calling deriv(), the error may be obtained from
102  \ref get_err().
103  */
104  virtual double deriv(double x, func_t &func) {
105  // There were some uninitialized variable warnings on OSX, so we
106  // prevent those by setting the derivative equal to zero.
107  double dx=0.0;
108  from_deriv=true;
109  deriv_err(x,func,dx,derr);
110  from_deriv=false;
111  return dx;
112  }
113 
114  /** \brief Calculate the second derivative of \c func w.r.t. x
115  */
116  virtual double deriv2(double x, func_t &func) {
117  double val;
118 
119  funct11 mf=
120  std::bind(std::mem_fn<double(double,func_t *)>(&deriv_base::derivfun),
121  this,std::placeholders::_1,&func);
122 
123  val=deriv_int(x,mf);
124  // The error estimate is unavailable, so we set it to zero
125  derr=0.0;
126  return val;
127  }
128 
129  /** \brief Calculate the third derivative of \c func w.r.t. x
130  */
131  virtual double deriv3(double x, func_t &func) {
132  double val;
133 
134  funct11 mf=
135  std::bind(std::mem_fn<double(double,func_t *)>(&deriv_base::derivfun2),
136  this,std::placeholders::_1,&func);
137 
138  val=deriv_int(x,mf);
139  // The error estimate is unavailable, so we set it to zero
140  derr=0.0;
141  return val;
142  }
143 
144  /** \brief Get uncertainty of last calculation
145  */
146  virtual double get_err() {
147  return derr;
148  }
149 
150  /** \brief Output control
151  */
152  int verbose;
153 
154  /** \brief Calculate the first derivative of \c func w.r.t. x and the
155  uncertainty
156  */
157  virtual int deriv_err(double x, func_t &func, double &dfdx,
158  double &err)=0;
159 
160  /** \brief Calculate the second derivative of \c func w.r.t. x and the
161  uncertainty
162  */
163  virtual int deriv2_err(double x, func_t &func,
164  double &d2fdx2, double &err) {
165  funct11 mf=
166  std::bind(std::mem_fn<double(double,func_t *)>(&deriv_base::derivfun),
167  this,std::placeholders::_1,&func);
168 
169  int ret=deriv_err_int(x,mf,d2fdx2,err);
170  // The error estimate is unavailable, so we set it to zero
171  err=0.0;
172  return ret;
173  }
174 
175  /** \brief Calculate the third derivative of \c func w.r.t. x and the
176  uncertainty
177  */
178  virtual int deriv3_err(double x, func_t &func,
179  double &d3fdx3, double &err) {
180  funct11 mf=
181  std::bind(std::mem_fn<double(double,func_t *)>(&deriv_base::derivfun2),
182  this,std::placeholders::_1,&func);
183 
184  int ret=deriv_err_int(x,mf,d3fdx3,err);
185  // The error estimate is unavailable, so we set it to zero
186  err=0.0;
187  return ret;
188  }
189 
190 #ifdef O2SCL_NEVER_DEFINED
191  }{
192 #endif
193 
194  /// Return string denoting type ("deriv")
195  virtual const char *type() { return "deriv"; }
196 
197  protected:
198 
199 #ifndef DOXYGEN_INTERNAL
200 
201  /** \brief Calculate the first derivative of \c func w.r.t. x
202 
203  This is an internal version of deriv() which is used in
204  computing second and third derivatives
205  */
206  virtual double deriv_int(double x, funct11 &func) {
207  double dx;
208  from_deriv=true;
209  deriv_err_int(x,func,dx,derr);
210  from_deriv=false;
211  return dx;
212  }
213 
214  /** \brief Calculate the first derivative of \c func w.r.t. x and the
215  uncertainty
216 
217  This is an internal version of deriv_err() which is used in
218  computing second and third derivatives
219  */
220  virtual int deriv_err_int(double x, funct11 &func,
221  double &dfdx, double &err)=0;
222 
223  /// The uncertainity in the most recent derivative computation
224  double derr;
225 
226  /// The function for the second derivative
227  double derivfun(double x, func_t *fp) {
228  return deriv(x,*fp);
229  }
230 
231  /// The function for the third derivative
232  double derivfun2(double x, func_t *fp) {
233  funct11 mf=
234  std::bind(std::mem_fn<double(double,func_t *)>(&deriv_base::derivfun),
235  this,std::placeholders::_1,fp);
236  double val=deriv_int(x,mf);
237  return val;
238  }
239 
240 #endif
241 
242  };
243 
244 #ifndef DOXYGEN_NO_O2NS
245 }
246 #endif
247 
248 #endif
double derr
The uncertainity in the most recent derivative computation.
Definition: deriv.h:224
The main O<span style=&#39;position: relative; top: 0.3em; font-size: 0.8em&#39;>2</span>scl O$_2$scl names...
Definition: anneal.h:42
virtual int deriv_err(double x, func_t &func, double &dfdx, double &err)=0
Calculate the first derivative of func w.r.t. x and the uncertainty.
std::function< double(double)> funct11
One-dimensional function typedef.
Definition: funct.h:44
virtual const char * type()
Return string denoting type ("deriv")
Definition: deriv.h:195
bool from_deriv
Avoids infinite loops in case the user calls the base class version.
Definition: deriv.h:82
virtual double deriv(double x, func_t &func)
Calculate the first derivative of func w.r.t. x.
Definition: deriv.h:104
virtual int deriv_err_int(double x, funct11 &func, double &dfdx, double &err)=0
Calculate the first derivative of func w.r.t. x and the uncertainty.
virtual double deriv3(double x, func_t &func)
Calculate the third derivative of func w.r.t. x.
Definition: deriv.h:131
virtual int deriv3_err(double x, func_t &func, double &d3fdx3, double &err)
Calculate the third derivative of func w.r.t. x and the uncertainty.
Definition: deriv.h:178
func_t * func
The pointer to the function.
Definition: deriv.h:77
virtual double deriv2(double x, func_t &func)
Calculate the second derivative of func w.r.t. x.
Definition: deriv.h:116
Numerical differentiation base [abstract base].
Definition: deriv.h:63
virtual double deriv_int(double x, funct11 &func)
Calculate the first derivative of func w.r.t. x.
Definition: deriv.h:206
bool err_nonconv
If true, call the error handler if the routine does not "converge".
Definition: deriv.h:97
virtual int deriv2_err(double x, func_t &func, double &d2fdx2, double &err)
Calculate the second derivative of func w.r.t. x and the uncertainty.
Definition: deriv.h:163
double derivfun(double x, func_t *fp)
The function for the second derivative.
Definition: deriv.h:227
int verbose
Output control.
Definition: deriv.h:152
A structure for passing the function to second and third derivatives [protected]. ...
Definition: deriv.h:72
virtual double get_err()
Get uncertainty of last calculation.
Definition: deriv.h:146
double derivfun2(double x, func_t *fp)
The function for the third derivative.
Definition: deriv.h:232

Documentation generated with Doxygen. Provided under the GNU Free Documentation License (see License Information).