
On Nov 9, 12:53 pm, Alfredo Correa <alfredo.cor...@gmail.com> wrote:
On Tue, Nov 9, 2010 at 5:45 AM, Larry Evans <cppljev...@suddenlink.net>wrote:
On 11/09/10 05:02, Alfredo Correa wrote: [snip]
I hope this helps somebody else, having named derivatives like in mathematical notation is a blessing for my code.
You might try repeating the process on a derivative. IOW, take a derivative of a derivative.
yes, yes. Even crossed derivatives, partial<q>(partial<p>(h))(make_set(1.,2.))
Last night I tryed this and works with some limitations on the way passing parameters to the second derivative.
for the monent I can't use it as partial<q>(partial<p>(h))(uno, dos)
In fact the other threads in the Boost group I opened are to solve this. In a few words, for derivative to have the same interface as H (the model functor) (and automatically generated), I need it to be "fused" and "unfused" at the same time. Which is problematic.
I achieved concatenated (repeated) derivative notation by using variadic templates: given an original functor that can be called as h(1.,2.); //or h(make_map<p,q>(1.,2.)); you can define the second derivative by repeatedly calling partial<p>(partial<q>(h))(1.,2.); //crossed derivative // or partial<p>(partial<q>(h))(make_map<p,q>(1.,2.)) partial<p>(partial<p>(h))(1.,2.); //second derivative partial<q>(partial<q>(h))(1.,2.); //another second derivative Note 1: calculating second derivatives in this way is not efficient or numerically stable, there are more efficient ways to calculate second derivatives than. Note 2: fortunatelly partial<...> can be specialized for certain function objects, therefore can contain the *explicit* first derivative of the functor) below is the implementation, the addition with respect to the old is using a variadic operator(): --- using namespace boost::fusion; template< class FusionMap, // e.g. fusion::map<T1,T2,...Tn> class Functor, // double(FreeFunction)(FusionMap const&), class FreeArgumentMapKey
struct bind_free_at{ mutable FusionMap m; Functor f; bind_free_at(Functor const& f, FusionMap const& fm) : m(fm), f(f){} //bind_free_at(bind_free_at const& other) : FusionMap((FusionMap const&)other), f(other.f){} double operator()(typename result_of::value_at_key<FusionMap, FreeArgumentMapKey>::type const& free_value) const{ at_key<FreeArgumentMapKey>(m) = free_value; return f(m); } }; template<class ParameterKey, class Functor, class Args=typename Functor::mapped_arguments> //, class FusionMap> struct d_{ Functor f; d_(Functor const& f) : f(f){} template <class Seq> struct result{typedef double type;}; typedef typename Functor::mapped_arguments mapped_arguments; double operator()(mapped_arguments args) const{ bind_free_at<Args, Functor, ParameterKey> bf(f, args); double x = at_key<ParameterKey>(args); return gsl::derivative::central(bf, x); } template<class... DomainTypeS> double operator()(DomainTypeS ... domainS) const{ //BOOST_STATIC_ASSERT((sizeof...(DomainTypeS))>1); return (*this)(mapped_arguments(domainS ... )); } }; template<class ParameterKey, class Functor, class Args=typename Functor::mapped_arguments> d_<ParameterKey, Functor, Args> partial(Functor const& f){ return d_<ParameterKey, Functor, Args>(f); }; still TODO: improve notation for second derivatives: partial<p, 2>(h)(1.,2.); //second derivative with respect to p