Note that there are some explanatory texts on larger screens.

plurals
  1. POConstructing Eigen expression templates with Boost.Proto
    primarykey
    data
    text
    <p>I'd like to use Boost.Proto to transform an embedded domain-specific language into a series of matrix operations implemented with the Eigen library. Since efficiency is important, I want proto to generate Eigen expression templates and avoid premature evaluation.</p> <p>I've implemented a simple grammar that can generate matrix multiplication expressions. The code below compiles without warnings (on g++ 4.8.0 and Intel C++ 2013.3, with Boost 1.54.0 and Eigen 3.1.3) and works as long as my expression only has a single multiplication operation. As soon as I add more multiplications to the chain, it crashes. Valgrind tells me that this is because one of the Eigen::GeneralProduct expression template temporaries gets destroyed before the evaluation is completed.</p> <p>I don't understand why this happens, or what I can do to prevent it. All help is appreciated!</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 MatrixExpr1, class MatrixExpr2&gt; struct result&lt;This(MatrixExpr1, MatrixExpr2)&gt; { typedef 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 type; }; template&lt;class MatrixExpr1, class MatrixExpr2&gt; typename result&lt;matmul_transform(MatrixExpr1, MatrixExpr2)&gt;::type operator()(const MatrixExpr1 &amp;a, const MatrixExpr2 &amp;b) const { return a * b; } }; 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(MatmulGrammar(proto::_left), MatmulGrammar(proto::_right))&gt;, proto::when&lt;InputPlaceholder, proto::functional::at(proto::_data, proto::_value)&gt; &gt; {}; int main() { matrix mat1(2,2), mat2(2,2), mat3(2,2), result(2,2); mat1 &lt;&lt; 1, 2, 3, 4; mat2 &lt;&lt; 5, 6, 7, 8; mat3 &lt;&lt; 1, 3, 6, 9; MatmulGrammar mmg; // THIS WORKS: result = mmg(I1 * I2, 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 CRASHES: result = mmg(I1 * I2 * I3, 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.
 

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