00001 /* 00002 ------------------------------------------------------------------- 00003 00004 Copyright (C) 2006, 2007, 2008, 2009, Andrew W. Steiner 00005 00006 This file is part of O2scl. 00007 00008 O2scl is free software; you can redistribute it and/or modify 00009 it under the terms of the GNU General Public License as published by 00010 the Free Software Foundation; either version 3 of the License, or 00011 (at your option) any later version. 00012 00013 O2scl is distributed in the hope that it will be useful, 00014 but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00016 GNU General Public License for more details. 00017 00018 You should have received a copy of the GNU General Public License 00019 along with O2scl. If not, see <http://www.gnu.org/licenses/>. 00020 00021 ------------------------------------------------------------------- 00022 */ 00023 #ifndef O2SCL_DERIV_H 00024 #define O2SCL_DERIV_H 00025 00026 #include <iostream> 00027 #include <cmath> 00028 #include <o2scl/collection.h> 00029 #include <o2scl/funct.h> 00030 00031 #ifndef DOXYGENP 00032 namespace o2scl { 00033 #endif 00034 00035 /** 00036 \brief Numerical differentiation base [abstract base] 00037 00038 This base class does not perform any actual differentiation. 00039 Use one of the children cern_deriv, gsl_deriv, or eqi_deriv 00040 instead. 00041 00042 This base class contains some code to automatically apply 00043 the first derivative routines to compute second or third 00044 derivatives. The error estimates for these will likely 00045 be underestimated. 00046 00047 \note Because this class template aims to automatically provide 00048 second and third derivatives, one must overload either both 00049 calc() and calc_int() or both calc_err() and calc_err_int(). 00050 00051 \future Improve the methods for second and third derivatives 00052 00053 */ 00054 template<class param_t, class func_t> class deriv { 00055 00056 #ifndef DOXYGEN_INTERNAL 00057 00058 protected: 00059 00060 /// A structure for passing the function to second and third derivatives 00061 typedef struct { 00062 public: 00063 /// The pointer to the function 00064 func_t *func; 00065 /// The pointer to the user-specified parameters 00066 param_t *up; 00067 } dpars; 00068 00069 /// Avoids infinite loops in case the user calls the base class version 00070 bool from_calc; 00071 00072 #endif 00073 00074 public: 00075 00076 deriv() { 00077 verbose=0; 00078 from_calc=false; 00079 err_nonconv=true; 00080 } 00081 00082 virtual ~deriv() {} 00083 00084 /// If true, call the error handler if the routine does not "converge" 00085 bool err_nonconv; 00086 00087 /** 00088 \brief Calculate the first derivative of \c func w.r.t. x 00089 00090 After calling calc(), the error may be obtained from 00091 \ref get_err(). 00092 */ 00093 virtual double calc(double x, param_t &pa, func_t &func) { 00094 double dx; 00095 from_calc=true; 00096 calc_err(x,pa,func,dx,derr); 00097 from_calc=false; 00098 return dx; 00099 } 00100 00101 /** \brief Calculate the second derivative of \c func w.r.t. x 00102 */ 00103 virtual double calc2(double x, param_t &pa, func_t &func) { 00104 double val; 00105 dpars dp={&func,&pa}; 00106 funct_mfptr_noerr<deriv,dpars> mf(this,&deriv::derivfun); 00107 val=calc_int(x,dp,mf); 00108 // The error estimate is wrong, so we set it to zero 00109 derr=0.0; 00110 return val; 00111 } 00112 00113 /** \brief Calculate the third derivative of \c func w.r.t. x 00114 */ 00115 virtual double calc3(double x, param_t &pa, func_t &func) { 00116 double val; 00117 dpars dp={&func,&pa}; 00118 funct_mfptr_noerr<deriv,dpars> mf(this,&deriv::derivfun2); 00119 val=calc_int(x,dp,mf); 00120 // The error estimate is wrong, so we set it to zero 00121 derr=0.0; 00122 return val; 00123 } 00124 00125 /** \brief Get uncertainty of last calculation 00126 */ 00127 virtual double get_err() { 00128 return derr; 00129 } 00130 00131 /** \brief Output control 00132 */ 00133 int verbose; 00134 00135 /** \brief Calculate the first derivative of \c func w.r.t. x and the 00136 uncertainty 00137 */ 00138 virtual int calc_err(double x, param_t &pa, func_t &func, double &dfdx, 00139 double &err)=0; 00140 00141 /** \brief Calculate the second derivative of \c func w.r.t. x and the 00142 uncertainty 00143 */ 00144 virtual int calc2_err(double x, param_t &pa, func_t &func, 00145 double &d2fdx2, double &err) { 00146 int ret; 00147 dpars dp={&func,&pa}; 00148 funct_mfptr_noerr<deriv,dpars> mf(this,&deriv::derivfun); 00149 ret=calc_err_int(x,dp,mf,d2fdx2,err); 00150 // The error estimate is wrong, so we set it to zero 00151 err=0.0; 00152 return 0; 00153 } 00154 00155 /** \brief Calculate the third derivative of \c func w.r.t. x and the 00156 uncertainty 00157 */ 00158 virtual int calc3_err(double x, param_t &pa, func_t &func, 00159 double &d3fdx3, double &err) { 00160 int ret; 00161 dpars dp={&func,&pa}; 00162 funct_mfptr_noerr<deriv,dpars> mf(this,&deriv::derivfun2); 00163 ret=calc_err_int(x,dp,mf,d3fdx3,err); 00164 // The error estimate is wrong, so we set it to zero 00165 err=0.0; 00166 return 0; 00167 } 00168 00169 /// Return string denoting type ("deriv") 00170 virtual const char *type() { return "deriv"; } 00171 00172 protected: 00173 00174 #ifndef DOXYGEN_INTERNAL 00175 00176 /** 00177 \brief Calculate the first derivative of \c func w.r.t. x 00178 00179 This is an internal version of calc() which is used in 00180 computing second and third derivatives 00181 */ 00182 virtual double calc_int(double x, dpars &pa, o2scl::funct<dpars> &func) { 00183 double dx; 00184 from_calc=true; 00185 calc_err_int(x,pa,func,dx,derr); 00186 from_calc=false; 00187 return dx; 00188 } 00189 00190 /** \brief Calculate the first derivative of \c func w.r.t. x and the 00191 uncertainty 00192 00193 This is an internal version of calc_err() which is used in 00194 computing second and third derivatives 00195 */ 00196 virtual int calc_err_int(double x, dpars &pa, o2scl::funct<dpars> &func, 00197 double &dfdx, double &err)=0; 00198 00199 /// The uncertainity in the most recent derivative computation 00200 double derr; 00201 00202 /// The function for the second derivative 00203 double derivfun(double x, dpars &dp) { 00204 return calc(x,*(dp.up),*(dp.func)); 00205 } 00206 00207 /// The function for the third derivative 00208 double derivfun2(double x, dpars &dp) { 00209 funct_mfptr_noerr<deriv,dpars> mf(this,&deriv::derivfun); 00210 double val=calc_int(x,dp,mf); 00211 return val; 00212 } 00213 00214 #endif 00215 00216 }; 00217 00218 #ifndef DOXYGENP 00219 } 00220 #endif 00221 00222 #endif
Documentation generated with Doxygen and provided under the GNU Free Documentation License. See License Information for details.
Project hosting provided by
,
O2scl Sourceforge Project Page