#ifndef DEF_compile_time_derivative #define DEF_compile_time_derivative #include using namespace boost::proto; // Assuming derivative of one variable, the 'unknown' struct unknown {}; // Boost.Proto calls this the expression wrapper // elements of the EDSL will have this type template struct expression; // Boost.Proto calls this the domain struct derived_domain : domain> {}; // We will use a context to evaluate expression templates struct evaluation_context: callable_context { double value; explicit evaluation_context(double value) : value(value) {} typedef double result_type; double operator()(tag::terminal, unknown) const { return value; } }; // And now we can do: // evaluation_context context(42); // eval(expr, context); // to evaluate an expression as though the unknown had value 42 template struct expression: extends, derived_domain> { typedef extends, derived_domain> base_type; expression(Expr const& expr = Expr()) : base_type(expr) {} typedef double result_type; // We spare ourselves the need to write eval(expr, context) // Instead, expr(42) is available double operator()(double d) const { evaluation_context context(d); return eval(*this, context); } }; // Boost.Proto calls this a transform -- we use this to operate // on the expression templates struct Derivative : or_< when< terminal , boost::mpl::int_<1>() > , when< terminal<_> , boost::mpl::int_<0>() > , when< plus , _make_plus(Derivative(_left), Derivative(_right)) > , when< minus , _make_minus(Derivative(_left), Derivative(_right)) > , when< multiplies , _make_plus( _make_multiplies(Derivative(_left), _right) , _make_multiplies(_left, Derivative(_right)) ) > //* , when< divides , _make_divides ( _make_minus ( _make_multiplies ( _right, Derivative(_left) ), _make_multiplies ( _left, Derivative(_right) ) ), _make_multiplies ( _right, _right ) ) > , otherwise<_> > {}; #endif