Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>This is my attempt at merging your approach with the solution linked in the comment. I have copied <code>stored_result_expression</code>, <code>do_wrap_expression</code> and <code>wrap_expression</code> from <a href="https://github.com/barche/eigen-proto/blob/master/eigen_calculator_solution.cpp" rel="nofollow">here</a>. The changes I've made to either your code or the one from the talk are marked with <code>//CHANGED</code>. </p> <pre><code>#include &lt;iostream&gt; #include &lt;boost/fusion/container.hpp&gt; #include &lt;boost/mpl/int.hpp&gt; #include &lt;boost/mpl/void.hpp&gt; #include &lt;boost/proto/proto.hpp&gt; #include &lt;boost/ref.hpp&gt; #include &lt;boost/type_traits/remove_const.hpp&gt; #include &lt;boost/type_traits/remove_reference.hpp&gt; #include &lt;boost/utility.hpp&gt; #include &lt;Eigen/Dense&gt; namespace fusion = boost::fusion; namespace mpl = boost::mpl; namespace proto = boost::proto; typedef Eigen::Matrix&lt;float, Eigen::Dynamic, Eigen::Dynamic&gt; matrix; // Placeholders const proto::terminal&lt;mpl::int_&lt;0&gt; &gt;::type I1 = {{}}; const proto::terminal&lt;mpl::int_&lt;1&gt; &gt;::type I2 = {{}}; const proto::terminal&lt;mpl::int_&lt;2&gt; &gt;::type I3 = {{}}; // Grammar template&lt;class Rule, class Callable = proto::callable&gt; struct External : proto::when&lt;Rule, proto::external_transform&gt; {}; struct matmul_transform : proto::callable { template&lt;class Sig&gt; struct result; template&lt;class This, class Expr, class MatrixExpr1, class MatrixExpr2&gt; struct result&lt;This(Expr, MatrixExpr1, MatrixExpr2)&gt; { typedef typename Eigen::MatrixBase&lt; typename Eigen::ProductReturnType&lt; typename boost::remove_const&lt;typename boost::remove_reference&lt;MatrixExpr1&gt;::type&gt;::type, typename boost::remove_const&lt;typename boost::remove_reference&lt;MatrixExpr2&gt;::type&gt;::type &gt;::Type &gt;::PlainObject&amp; type; //CHANGED - THIS IS THE TYPE THAT IS USED IN THE CODE OF THE TALK }; template&lt;class Expr, class MatrixExpr1, class MatrixExpr2&gt; typename result&lt;matmul_transform(Expr, MatrixExpr1, MatrixExpr2)&gt;::type operator()(Expr&amp; expr, const MatrixExpr1 &amp;a, const MatrixExpr2 &amp;b) const { //CHANGED - ADDED THE expr PARAMETER expr.value = a*b; return expr.value; } }; struct MatmulGrammar; struct InputPlaceholder : proto::terminal&lt;proto::_&gt; {}; struct MatrixMultiplication : proto::multiplies&lt;MatmulGrammar, MatmulGrammar&gt; {}; struct MatmulGrammar : proto::or_&lt; External&lt;InputPlaceholder&gt;, External&lt;MatrixMultiplication&gt; &gt; {}; struct matmul_transforms : proto::external_transforms&lt; proto::when&lt;MatrixMultiplication, matmul_transform(proto::_, MatmulGrammar(proto::_left), MatmulGrammar(proto::_right))&gt;, //CHANGED - ADAPTED TO THE NEW SIGNATURE OF matmul_transform proto::when&lt;InputPlaceholder, proto::functional::at(proto::_data, proto::_value)&gt; &gt; {}; // THE FOLLOWING CODE BLOCK IS COPIED FROM https://github.com/barche/eigen-proto/blob/master/eigen_calculator_solution.cpp //---------------------------------------------------------------------------------------------- /// Wraps a given expression, so the value that it represents can be stored inside the expression itself template&lt;typename ExprT, typename ValueT&gt; struct stored_result_expression : proto::extends&lt; ExprT, stored_result_expression&lt;ExprT, ValueT&gt; &gt; { EIGEN_MAKE_ALIGNED_OPERATOR_NEW typedef proto::extends&lt; ExprT, stored_result_expression&lt;ExprT, ValueT&gt; &gt; base_type; explicit stored_result_expression(ExprT const &amp;expr = ExprT()) : base_type(expr) { } /// Temporary storage for the result of the expression mutable ValueT value; }; struct do_wrap_expression : proto::transform&lt; do_wrap_expression &gt; { template&lt;typename ExprT, typename StateT, typename DataT&gt; struct impl : proto::transform_impl&lt;ExprT, StateT, DataT&gt; { typedef typename boost::result_of&lt;MatmulGrammar(ExprT, StateT, DataT)&gt;::type result_ref_type; //CHANGED - TO USE YOUR GRAMMAR typedef typename boost::remove_reference&lt;result_ref_type&gt;::type value_type; typedef typename boost::remove_const&lt;typename boost::remove_reference&lt;ExprT&gt;::type&gt;::type expr_val_type; typedef stored_result_expression&lt;expr_val_type, value_type&gt; result_type; result_type operator()(typename impl::expr_param expr, typename impl::state_param state, typename impl::data_param data) { return result_type(expr); } }; }; /// Wrap multiplies expressions so they can store a temporary result struct wrap_expression : proto::or_ &lt; proto::terminal&lt;proto::_&gt;, proto::when &lt; proto::multiplies&lt;proto::_, proto::_&gt;, do_wrap_expression( proto::functional::make_multiplies ( wrap_expression(proto::_left), wrap_expression(proto::_right) ), proto::_state, //CHANGED - THESE EXTRA PARAMETERS ARE NEEDED TO CALCULATE result_ref_type IN do_wrap_expression proto::_env ) &gt;, proto::nary_expr&lt; proto::_, proto::vararg&lt;wrap_expression&gt; &gt; &gt; { }; //-------------------------------------------------------------------------------------------------- int main() { matrix mat1(2,2), mat2(2,2), mat3(2,2), result(2,2); mat1 &lt;&lt; 1, 1, 0, 1; mat2 &lt;&lt; 1, 1, 0, 1; mat3 &lt;&lt; 1, 1, 0, 1; MatmulGrammar mmg; wrap_expression wrap; //THIS WORKS: result = mmg( //THIS IS REALLY HORRIBLE, BUT IT WORKS. IT SHOULD PROBABLY BE HIDDEN BEHIND A FUNCTION wrap( I1 * I2, mpl::void_(), ( proto::data = fusion::make_vector(boost::cref(mat1), boost::cref(mat2), boost::cref(mat3)), proto::transforms = matmul_transforms() ) ), mpl::void_(), ( proto::data = fusion::make_vector(boost::cref(mat1), boost::cref(mat2), boost::cref(mat3)), proto::transforms = matmul_transforms() ) ); std::cout &lt;&lt; result &lt;&lt; std::endl; // THIS DOESN'T CRASH ANYMORE: result = mmg( wrap( I1 * I2 * I3 * I1 * I2 * I3, mpl::void_(), ( proto::data = fusion::make_vector(boost::cref(mat1), boost::cref(mat2), boost::cref(mat3)), proto::transforms = matmul_transforms() ) ), mpl::void_(), ( proto::data = fusion::make_vector(boost::cref(mat1), boost::cref(mat2), boost::cref(mat3)), proto::transforms = matmul_transforms() ) ); std::cout &lt;&lt; result &lt;&lt; std::endl; return 0; } </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload