/** \file num_diff.hpp \brief performing n-dim differential operation on func objects \author Junhua Gu */ #ifndef NUMDIFF_HPP #define NUMDIFF_HPP #define OPT_HEADER #include #include #include #include #include namespace opt_utilities { /** calculate the numerical differential of a func_obj */ template class diff_func_obj :public func_obj { private: virtual pT do_gradient(const pT& p)=0; public: pT gradient(const pT& p) { return do_gradient(p); } }; template rT gradient(func_obj& f,pT& p,size_t n) { rT ep=std::sqrt(std::numeric_limits::epsilon()); rT result; typename element_type_trait::element_type old_value=get_element(p,n); typename element_type_trait::element_type h= std::max(get_element(p,n),rT(1))*ep; set_element(p,n,old_value+h); rT v2=f(p); set_element(p,n,old_value-h); rT v1=f(p); set_element(p,n,old_value); result=(v2-v1)/h/2; return result; } template pT gradient(func_obj& f,pT& p) { diff_func_obj* pdfo=0; if(pdfo=dynamic_cast*>(&f)) { return pdfo->gradient(p); } pT result; resize(result,get_size(p)); for(int i=0;i rT hessian(func_obj& f,const pT& p,size_t m,size_t n) { rT ep=std::sqrt(std::numeric_limits::epsilon()); typename element_type_trait::element_type hn= std::max(get_element(p,n),rT(1))*ep; typename element_type_trait::element_type hm= std::max(get_element(p,m),rT(1))*ep; pT p11; resize(p11,get_size(p)); pT p00; resize(p00,get_size(p)); pT p10; resize(p10,get_size(p)); pT p01; resize(p01,get_size(p)); for(size_t i=0;i rT div(func_obj& f,const pT& p) { rT result=0; for(int i=0;i