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 return val; 00109 } 00110 00111 /** \brief Calculate the third derivative of \c func w.r.t. x 00112 */ 00113 virtual double calc3(double x, param_t &pa, func_t &func) { 00114 double val; 00115 dpars dp={&func,&pa}; 00116 funct_mfptr_noerr<deriv,dpars> mf(this,&deriv::derivfun2); 00117 val=calc_int(x,dp,mf); 00118 return val; 00119 } 00120 00121 /** \brief Get uncertainty of last calculation 00122 */ 00123 virtual double get_err() { 00124 return derr; 00125 } 00126 00127 /** \brief Output control 00128 */ 00129 int verbose; 00130 00131 /** \brief Calculate the first derivative of \c func w.r.t. x and the 00132 uncertainty 00133 */ 00134 virtual int calc_err(double x, param_t &pa, func_t &func, double &dfdx, 00135 double &err)=0; 00136 00137 /** \brief Calculate the second derivative of \c func w.r.t. x and the 00138 uncertainty 00139 */ 00140 virtual int calc2_err(double x, param_t &pa, func_t &func, 00141 double &d2fdx2, double &err) { 00142 int ret; 00143 dpars dp={&func,&pa}; 00144 funct_mfptr_noerr<deriv,dpars> mf(this,&deriv::derivfun); 00145 ret=calc_err_int(x,dp,mf,d2fdx2,err); 00146 return 0; 00147 } 00148 00149 /** \brief Calculate the third derivative of \c func w.r.t. x and the 00150 uncertainty 00151 */ 00152 virtual int calc3_err(double x, param_t &pa, func_t &func, 00153 double &d3fdx3, double &err) { 00154 int ret; 00155 dpars dp={&func,&pa}; 00156 funct_mfptr_noerr<deriv,dpars> mf(this,&deriv::derivfun2); 00157 ret=calc_err_int(x,dp,mf,d3fdx3,err); 00158 return 0; 00159 } 00160 00161 /// Return string denoting type ("deriv") 00162 virtual const char *type() { return "deriv"; } 00163 00164 protected: 00165 00166 #ifndef DOXYGEN_INTERNAL 00167 00168 /** 00169 \brief Calculate the first derivative of \c func w.r.t. x 00170 00171 This is an internal version of calc() which is used in 00172 computing second and third derivatives 00173 */ 00174 virtual double calc_int(double x, dpars &pa, o2scl::funct<dpars> &func) { 00175 double dx; 00176 from_calc=true; 00177 calc_err_int(x,pa,func,dx,derr); 00178 from_calc=false; 00179 return dx; 00180 } 00181 00182 /** \brief Calculate the first derivative of \c func w.r.t. x and the 00183 uncertainty 00184 00185 This is an internal version of calc_err() which is used in 00186 computing second and third derivatives 00187 */ 00188 virtual int calc_err_int(double x, dpars &pa, o2scl::funct<dpars> &func, 00189 double &dfdx, double &err)=0; 00190 00191 /// The uncertainity in the most recent derivative computation 00192 double derr; 00193 00194 /// The function for the second derivative 00195 double derivfun(double x, dpars &dp) { 00196 return calc(x,*(dp.up),*(dp.func)); 00197 } 00198 00199 /// The function for the third derivative 00200 double derivfun2(double x, dpars &dp) { 00201 funct_mfptr_noerr<deriv,dpars> mf(this,&deriv::derivfun); 00202 double val=calc_int(x,dp,mf); 00203 return val; 00204 } 00205 00206 #endif 00207 00208 }; 00209 00210 #ifndef DOXYGENP 00211 } 00212 #endif 00213 00214 #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