Object-oriented Scientific Computing Library: Version 0.910
deriv.h
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
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

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

Get Object-oriented Scientific Computing
Lib at SourceForge.net. Fast, secure and Free Open Source software
downloads.