#pragma once #include <cgv/math/vec.h> namespace cgv { namespace math { /** interface class for multivariate function with two template arguments: - X defines the type of the independent variables and - T the type of range to which the function maps For example a function that maps from n double variables to an int would be declared as mfunc<double,int> */ template <typename X, typename T> class mfunc { public: /// points must have get_nr_independent_variables() components typedef cgv::math::vec<X> pnt_type; /// vectors must have get_nr_independent_variables() components typedef cgv::math::vec<X> vec_type; /// virtual destructor virtual ~mfunc() {} /// return the number of independent variables that are mapped by the function virtual unsigned get_nr_independent_variables() const = 0; /// interface for evaluation of the multivariate function virtual T evaluate(const pnt_type& p) const = 0; /** interface for evaluation of the gradient of the multivariate function. default implementation uses central differences to approximate the gradient, with an epsilon of 1e-5. */ virtual vec_type evaluate_gradient(const pnt_type& p) const { static X epsilon = (X)1e-5; static X inv_2_eps = (X)(0.5/epsilon); unsigned n = p.size(); vec_type g(n); pnt_type q(p); for (unsigned i=0; i<n; ++i) { q(i) += epsilon; g(i) = evaluate(q); q(i) = p(i)-epsilon; g(i) -= evaluate(q); g(i) *= inv_2_eps; q(i) = p(i); } return g; } }; /** specialization of a multivariate function to two independent variables, which only reimplements the method get_nr_independent_variables. */ template <typename X, typename T> class v2_func : public mfunc<X,T> { public: /// returns 2 unsigned int get_nr_independent_variables() const { return 2; } }; /** specialization of a multivariate function to three independent variables, which only reimplements the method get_nr_independent_variables. */ template <typename X, typename T> class v3_func : public mfunc<X,T> { public: /// returns 3 unsigned int get_nr_independent_variables() const { return 3; } }; } }