deriv.h
Go to the documentation of this file.
1 /*
2  -------------------------------------------------------------------
3 
4  Copyright (C) 2006-2020, 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=funct, class fp_t=double> 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  typedef std::function<fp_t(fp_t)> internal_func_t;
85 
86 #endif
87 
88  public:
89 
90  deriv_base() {
91  verbose=0;
92  from_deriv=false;
93  err_nonconv=true;
94  }
95 
96  virtual ~deriv_base() {}
97 
98  /// If true, call the error handler if the routine does not "converge"
100 
101  /** \brief Calculate the first derivative of \c func w.r.t. x
102 
103  After calling deriv(), the error may be obtained from
104  \ref get_err().
105  */
106  virtual fp_t deriv(fp_t x, func_t &func) {
107  // There were some uninitialized variable warnings on OSX, so we
108  // prevent those by setting the derivative equal to zero.
109  fp_t dx=0.0;
110  from_deriv=true;
111  deriv_err(x,func,dx,derr);
112  from_deriv=false;
113  return dx;
114  }
115 
116  /** \brief Calculate the second derivative of \c func w.r.t. x
117  */
118  virtual fp_t deriv2(fp_t x, func_t &func) {
119  fp_t val;
120 
121  internal_func_t mf=
122  std::bind(std::mem_fn<fp_t(fp_t,func_t *)>(&deriv_base::derivfun),
123  this,std::placeholders::_1,&func);
124 
125  val=deriv_int(x,mf);
126  // The error estimate is unavailable, so we set it to zero
127  derr=0.0;
128  return val;
129  }
130 
131  /** \brief Calculate the third derivative of \c func w.r.t. x
132  */
133  virtual fp_t deriv3(fp_t x, func_t &func) {
134  fp_t val;
135 
136  internal_func_t mf=
137  std::bind(std::mem_fn<fp_t(fp_t,func_t *)>(&deriv_base::derivfun2),
138  this,std::placeholders::_1,&func);
139 
140  val=deriv_int(x,mf);
141  // The error estimate is unavailable, so we set it to zero
142  derr=0.0;
143  return val;
144  }
145 
146  /** \brief Get uncertainty of last calculation
147  */
148  virtual fp_t get_err() {
149  return derr;
150  }
151 
152  /** \brief Output control
153  */
154  int verbose;
155 
156  /** \brief Calculate the first derivative of \c func w.r.t. x and the
157  uncertainty
158  */
159  virtual int deriv_err(fp_t x, func_t &func, fp_t &dfdx,
160  fp_t &err)=0;
161 
162  /** \brief Calculate the second derivative of \c func w.r.t. x and the
163  uncertainty
164  */
165  virtual int deriv2_err(fp_t x, func_t &func,
166  fp_t &d2fdx2, fp_t &err) {
167  internal_func_t mf=
168  std::bind(std::mem_fn<fp_t(fp_t,func_t *)>(&deriv_base::derivfun),
169  this,std::placeholders::_1,&func);
170 
171  int ret=deriv_err_int(x,mf,d2fdx2,err);
172  // The error estimate is unavailable, so we set it to zero
173  err=0.0;
174  return ret;
175  }
176 
177  /** \brief Calculate the third derivative of \c func w.r.t. x and the
178  uncertainty
179  */
180  virtual int deriv3_err(fp_t x, func_t &func,
181  fp_t &d3fdx3, fp_t &err) {
182  internal_func_t mf=
183  std::bind(std::mem_fn<fp_t(fp_t,func_t *)>(&deriv_base::derivfun2),
184  this,std::placeholders::_1,&func);
185 
186  int ret=deriv_err_int(x,mf,d3fdx3,err);
187  // The error estimate is unavailable, so we set it to zero
188  err=0.0;
189  return ret;
190  }
191 
192 #ifdef O2SCL_NEVER_DEFINED
193  }{
194 #endif
195 
196  /// Return string denoting type ("deriv")
197  virtual const char *type() { return "deriv"; }
198 
199  protected:
200 
201 #ifndef DOXYGEN_INTERNAL
202 
203  /** \brief Calculate the first derivative of \c func w.r.t. x
204 
205  This is an internal version of deriv() which is used in
206  computing second and third derivatives
207  */
208  virtual fp_t deriv_int(fp_t x, internal_func_t &func) {
209  fp_t dx;
210  from_deriv=true;
211  deriv_err_int(x,func,dx,derr);
212  from_deriv=false;
213  return dx;
214  }
215 
216  /** \brief Calculate the first derivative of \c func w.r.t. x and the
217  uncertainty
218 
219  This is an internal version of deriv_err() which is used in
220  computing second and third derivatives
221  */
222  virtual int deriv_err_int(fp_t x, internal_func_t &func,
223  fp_t &dfdx, fp_t &err)=0;
224 
225  /// The uncertainity in the most recent derivative computation
226  fp_t derr;
227 
228  /// The function for the second derivative
229  fp_t derivfun(fp_t x, func_t *fp) {
230  return deriv(x,*fp);
231  }
232 
233  /// The function for the third derivative
234  fp_t derivfun2(fp_t x, func_t *fp) {
235  internal_func_t mf=
236  std::bind(std::mem_fn<fp_t(fp_t,func_t *)>(&deriv_base::derivfun),
237  this,std::placeholders::_1,fp);
238  fp_t val=deriv_int(x,mf);
239  return val;
240  }
241 
242 #endif
243 
244  };
245 
246 #ifndef DOXYGEN_NO_O2NS
247 }
248 #endif
249 
250 #endif
o2scl::deriv_base::dpars
A structure for passing the function to second and third derivatives [protected].
Definition: deriv.h:72
o2scl::deriv_base::derivfun
fp_t derivfun(fp_t x, func_t *fp)
The function for the second derivative.
Definition: deriv.h:229
o2scl::deriv_base::verbose
int verbose
Output control.
Definition: deriv.h:154
o2scl::deriv_base::deriv2_err
virtual int deriv2_err(fp_t x, func_t &func, fp_t &d2fdx2, fp_t &err)
Calculate the second derivative of func w.r.t. x and the uncertainty.
Definition: deriv.h:165
o2scl::deriv_base::get_err
virtual fp_t get_err()
Get uncertainty of last calculation.
Definition: deriv.h:148
o2scl
The main O<span style='position: relative; top: 0.3em; font-size: 0.8em'>2</span>scl O$_2$scl names...
Definition: anneal.h:42
o2scl::deriv_base
Numerical differentiation base [abstract base].
Definition: deriv.h:63
o2scl::deriv_base::dpars::func
func_t * func
The pointer to the function.
Definition: deriv.h:77
o2scl::deriv_base::deriv_err
virtual int deriv_err(fp_t x, func_t &func, fp_t &dfdx, fp_t &err)=0
Calculate the first derivative of func w.r.t. x and the uncertainty.
o2scl::deriv_base::err_nonconv
bool err_nonconv
If true, call the error handler if the routine does not "converge".
Definition: deriv.h:99
o2scl::deriv_base::derr
fp_t derr
The uncertainity in the most recent derivative computation.
Definition: deriv.h:226
o2scl::deriv_base::derivfun2
fp_t derivfun2(fp_t x, func_t *fp)
The function for the third derivative.
Definition: deriv.h:234
o2scl::deriv_base::deriv3
virtual fp_t deriv3(fp_t x, func_t &func)
Calculate the third derivative of func w.r.t. x.
Definition: deriv.h:133
o2scl::deriv_base::deriv_int
virtual fp_t deriv_int(fp_t x, internal_func_t &func)
Calculate the first derivative of func w.r.t. x.
Definition: deriv.h:208
o2scl::deriv_base::deriv3_err
virtual int deriv3_err(fp_t x, func_t &func, fp_t &d3fdx3, fp_t &err)
Calculate the third derivative of func w.r.t. x and the uncertainty.
Definition: deriv.h:180
o2scl::deriv_base::from_deriv
bool from_deriv
Avoids infinite loops in case the user calls the base class version.
Definition: deriv.h:82
o2scl::deriv_base::type
virtual const char * type()
Return string denoting type ("deriv")
Definition: deriv.h:197
o2scl::deriv_base::deriv_err_int
virtual int deriv_err_int(fp_t x, internal_func_t &func, fp_t &dfdx, fp_t &err)=0
Calculate the first derivative of func w.r.t. x and the uncertainty.
o2scl::deriv_base::deriv
virtual fp_t deriv(fp_t x, func_t &func)
Calculate the first derivative of func w.r.t. x.
Definition: deriv.h:106
o2scl::deriv_base::deriv2
virtual fp_t deriv2(fp_t x, func_t &func)
Calculate the second derivative of func w.r.t. x.
Definition: deriv.h:118

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