![]() |
Object-oriented Scientific Computing Library: Version 0.910
|
00001 /* 00002 ------------------------------------------------------------------- 00003 00004 Copyright (C) 2006-2012, 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/funct.h> 00029 00030 #ifndef DOXYGENP 00031 namespace o2scl { 00032 #endif 00033 00034 /** \brief Numerical differentiation base [abstract base] 00035 00036 This base class does not perform any actual differentiation. 00037 Use one of the children cern_deriv, gsl_deriv, or eqi_deriv 00038 instead. 00039 00040 This base class contains some code to automatically apply 00041 the first derivative routines to compute second or third 00042 derivatives. The error estimates for these will likely 00043 be underestimated. 00044 00045 \note Because this class template aims to automatically provide 00046 second and third derivatives, one must overload either both 00047 calc() and calc_int() or both calc_err() and calc_err_int(). 00048 00049 \future Improve the methods for second and third derivatives 00050 */ 00051 template<class func_t=funct> class deriv { 00052 00053 #ifndef DOXYGEN_INTERNAL 00054 00055 protected: 00056 00057 /** \brief A structure for passing the function to second and 00058 third derivatives [protected] 00059 */ 00060 typedef struct { 00061 00062 public: 00063 00064 /// The pointer to the function 00065 func_t *func; 00066 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 /** \brief Calculate the first derivative of \c func w.r.t. x 00088 00089 After calling calc(), the error may be obtained from 00090 \ref get_err(). 00091 */ 00092 virtual double calc(double x, func_t &func) { 00093 double dx; 00094 from_calc=true; 00095 calc_err(x,func,dx,derr); 00096 from_calc=false; 00097 return dx; 00098 } 00099 00100 /** \brief Calculate the second derivative of \c func w.r.t. x 00101 */ 00102 virtual double calc2(double x, func_t &func) { 00103 double val; 00104 dpars dp={&func}; 00105 funct_mfptr_param<deriv,dpars> mf(this,&deriv::derivfun,dp); 00106 val=calc_int(x,mf); 00107 // The error estimate is unavailable, so we set it to zero 00108 derr=0.0; 00109 return val; 00110 } 00111 00112 /** \brief Calculate the third derivative of \c func w.r.t. x 00113 */ 00114 virtual double calc3(double x, func_t &func) { 00115 double val; 00116 dpars dp={&func}; 00117 funct_mfptr_param<deriv,dpars> mf(this,&deriv::derivfun2,dp); 00118 val=calc_int(x,mf); 00119 // The error estimate is unavailable, so we set it to zero 00120 derr=0.0; 00121 return val; 00122 } 00123 00124 /** \brief Get uncertainty of last calculation 00125 */ 00126 virtual double get_err() { 00127 return derr; 00128 } 00129 00130 /** \brief Output control 00131 */ 00132 int verbose; 00133 00134 /** \brief Calculate the first derivative of \c func w.r.t. x and the 00135 uncertainty 00136 */ 00137 virtual int calc_err(double x, func_t &func, double &dfdx, 00138 double &err)=0; 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, func_t &func, 00144 double &d2fdx2, double &err) { 00145 int ret; 00146 dpars dp={&func}; 00147 funct_mfptr_param<deriv,dpars> mf(this,&deriv::derivfun,dp); 00148 ret=calc_err_int(x,mf,d2fdx2,err); 00149 // The error estimate is unavailable, so we set it to zero 00150 err=0.0; 00151 return 0; 00152 } 00153 00154 /** \brief Calculate the third derivative of \c func w.r.t. x and the 00155 uncertainty 00156 */ 00157 virtual int calc3_err(double x, func_t &func, 00158 double &d3fdx3, double &err) { 00159 int ret; 00160 dpars dp={&func}; 00161 funct_mfptr_param<deriv,dpars> mf(this,&deriv::derivfun2,dp); 00162 ret=calc_err_int(x,mf,d3fdx3,err); 00163 // The error estimate is unavailable, so we set it to zero 00164 err=0.0; 00165 return 0; 00166 } 00167 00168 /// Return string denoting type ("deriv") 00169 virtual const char *type() { return "deriv"; } 00170 00171 protected: 00172 00173 #ifndef DOXYGEN_INTERNAL 00174 00175 /** \brief Calculate the first derivative of \c func w.r.t. x 00176 00177 This is an internal version of calc() which is used in 00178 computing second and third derivatives 00179 */ 00180 virtual double calc_int(double x, funct &func) { 00181 double dx; 00182 from_calc=true; 00183 calc_err_int(x,func,dx,derr); 00184 from_calc=false; 00185 return dx; 00186 } 00187 00188 /** \brief Calculate the first derivative of \c func w.r.t. x and the 00189 uncertainty 00190 00191 This is an internal version of calc_err() which is used in 00192 computing second and third derivatives 00193 */ 00194 virtual int calc_err_int(double x, funct &func, 00195 double &dfdx, double &err)=0; 00196 00197 /// The uncertainity in the most recent derivative computation 00198 double derr; 00199 00200 /// The function for the second derivative 00201 double derivfun(double x, dpars &dp) { 00202 return calc(x,*(dp.func)); 00203 } 00204 00205 /// The function for the third derivative 00206 double derivfun2(double x, dpars &dp) { 00207 funct_mfptr_param<deriv,dpars> mf(this,&deriv::derivfun,dp); 00208 double val=calc_int(x,mf); 00209 return val; 00210 } 00211 00212 #endif 00213 00214 }; 00215 00216 #ifndef DOXYGENP 00217 } 00218 #endif 00219 00220 #endif
Documentation generated with Doxygen. Provided under the GNU Free Documentation License (see License Information).