00001 /* 00002 ------------------------------------------------------------------- 00003 00004 Copyright (C) 2006, 2007, 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 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 } 00080 00081 virtual ~deriv() {} 00082 00083 /** 00084 \brief Calculate the first derivative of \c func w.r.t. x 00085 00086 After calling calc(), the error may be obtained from 00087 \ref get_err(). 00088 */ 00089 virtual double calc(double x, param_t &pa, func_t &func) { 00090 double dx; 00091 from_calc=true; 00092 calc_err(x,pa,func,dx,derr); 00093 from_calc=false; 00094 return dx; 00095 } 00096 00097 /** \brief Calculate the second derivative of \c func w.r.t. x 00098 */ 00099 virtual double calc2(double x, param_t &pa, func_t &func) { 00100 double val; 00101 dpars dp={&func,&pa}; 00102 funct_mfptr_noerr<deriv,dpars> mf(this,&deriv::derivfun); 00103 val=calc_int(x,dp,mf); 00104 return val; 00105 } 00106 00107 /** \brief Calculate the third derivative of \c func w.r.t. x 00108 */ 00109 virtual double calc3(double x, param_t &pa, func_t &func) { 00110 double val; 00111 dpars dp={&func,&pa}; 00112 funct_mfptr_noerr<deriv,dpars> mf(this,&deriv::derivfun2); 00113 val=calc_int(x,dp,mf); 00114 return val; 00115 } 00116 00117 /** \brief Get uncertainty of last calculation 00118 */ 00119 virtual double get_err() { 00120 return derr; 00121 } 00122 00123 /** \brief Output control 00124 */ 00125 int verbose; 00126 00127 /** \brief Calculate the first derivative of \c func w.r.t. x and the 00128 uncertainty 00129 */ 00130 virtual int calc_err(double x, param_t &pa, func_t &func, double &dfdx, 00131 double &err) { 00132 if (from_calc==true) { 00133 set_err_ret("No method specified in calc_err().",gsl_nobase); 00134 } 00135 dfdx=calc(x,pa,func); 00136 err=0.0; 00137 return 0; 00138 } 00139 00140 /** \brief Calculate the second derivative of \c func w.r.t. x and the 00141 uncertainty 00142 */ 00143 virtual int calc2_err(double x, param_t &pa, func_t &func, 00144 double &d2fdx2, double &err) { 00145 int ret; 00146 dpars dp={&func,&pa}; 00147 funct_mfptr_noerr<deriv,dpars> mf(this,&deriv::derivfun); 00148 ret=calc_err_int(x,dp,mf,d2fdx2,err); 00149 return 0; 00150 } 00151 00152 /** \brief Calculate the third derivative of \c func w.r.t. x and the 00153 uncertainty 00154 */ 00155 virtual int calc3_err(double x, param_t &pa, func_t &func, 00156 double &d3fdx3, double &err) { 00157 int ret; 00158 dpars dp={&func,&pa}; 00159 funct_mfptr_noerr<deriv,dpars> mf(this,&deriv::derivfun2); 00160 ret=calc_err_int(x,dp,mf,d3fdx3,err); 00161 return 0; 00162 } 00163 00164 /// Return string denoting type ("deriv") 00165 virtual const char *type() { return "deriv"; } 00166 00167 protected: 00168 00169 #ifndef DOXYGEN_INTERNAL 00170 00171 /** 00172 \brief Calculate the first derivative of \c func w.r.t. x 00173 00174 This is an internal version of calc() which is used in 00175 computing second and third derivatives 00176 */ 00177 virtual double calc_int(double x, dpars &pa, o2scl::funct<dpars> &func) { 00178 double dx; 00179 from_calc=true; 00180 calc_err_int(x,pa,func,dx,derr); 00181 from_calc=false; 00182 return dx; 00183 } 00184 00185 /** \brief Calculate the first derivative of \c func w.r.t. x and the 00186 uncertainty 00187 00188 This is an internal version of calc_err() which is used in 00189 computing second and third derivatives 00190 */ 00191 virtual int calc_err_int(double x, dpars &pa, o2scl::funct<dpars> &func, 00192 double &dfdx, double &err) { 00193 if (from_calc==true) { 00194 set_err_ret("No method specified in calc_err_int().",gsl_nobase); 00195 } 00196 dfdx=calc_int(x,pa,func); 00197 err=0.0; 00198 return 0; 00199 } 00200 00201 /// The uncertainity in the most recent derivative computation 00202 double derr; 00203 00204 /// The function for the second derivative 00205 double derivfun(double x, dpars &dp) { 00206 return calc(x,*(dp.up),*(dp.func)); 00207 } 00208 00209 /// The function for the third derivative 00210 double derivfun2(double x, dpars &dp) { 00211 funct_mfptr_noerr<deriv,dpars> mf(this,&deriv::derivfun); 00212 double val=calc_int(x,dp,mf); 00213 return val; 00214 } 00215 00216 #endif 00217 00218 }; 00219 00220 #ifndef DOXYGENP 00221 } 00222 #endif 00223 00224 #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