Expression templates in Eigen
Asked Answered
E

1

6

I would like to understand how expression templates work in Eigen. I understood that the sum of two dynamical double vectors is performed by something which looks like this :

CwiseBinaryOp< internal::scalar_sum_op<double>, VectorXd const, VectorXd const > operator+(VectorXd const & lhs, VectorXd const & rhs);

I also understood how the difference of two vectors is implemented.

I have two questions.

1. How does the product of a vector by a scalar work?

I have noticed that

CwiseBinaryOp< internal::scalar_product_op<double>, VectorXd const, VectorXd const > 

exists but I have the feeling that it is only designed to perform componentwise operations between two vectors. Does it mean that the product of a vector by a scalar correspond to a unary operator, say

CwiseUnaryOp< internal::scalar_product_op<double>, VectorXd const, VectorXd const > ?

2. Can template expressions be built from mixed operations?

For example, in an expression like

x = u + (2*v + (v-w))

is it true that these operations are performed in a nested way like this?

  • v-w leads to the construction of an instance of E1
  • 2*v leads to the construction of an instance of E2
  • 2*v + (v-w) leads to the construction of an instance of E3
  • u + (2*v + (u-w)) leads to the construction of an instance of E4
  • x = u + (2*v + (v-w)) calls

the constructor

VectorXd(E4 const &);

or the overloading

VectorXd & operator=(E4 const &);

which evaluates the tree built from the previous steps, with the following aliases:

using diff = internal::scalar_difference_op<double>;
using prod = internal::scalar_product_op<double>;
using sum = internal::scalar_sum_op<double>;

using E1 = CwiseBinaryOp< diff, VectorXd const, VectorXd const >;
using E2 = CwiseUnaryOp< prod, VectorXd const >;
using E3 = CwiseBinaryOp< sum, E1 const, E2 const >;
Earmuff answered 3/8, 2016 at 16:52 Comment(0)
N
6

1. How does the product of a vector by a scalar work?

In Eigen 3.2, it is implemented as a unary-operator, with a functor storing the value of the scalar factor. In Eigen 3.3, it is now implemented as a binary operator between the given matrix expression and a constant expression, something like:

CwiseBinaryOp<scalar_product_op<double,double>,
              VectorXd,
              CwiseNullaryOp<scalar_constant_op<double>, VectorXd> >

This approach permits to clearly distinguish between s*vec and vec*s, and the return type of, e.g., vec*s is equivalent to the one of vec*VectorxD::Constant(vec.size(),s).

2. Can template expressions be built from mixed operations?

Your understanding is correct: first the expressions E1 to E4 are created, then the evaluation starts from the overloaded operator= generating a code like:

for(i=0;i<x.size();++i)
  x[i] = E4.coeff(i);
Nyberg answered 3/8, 2016 at 21:14 Comment(1)
Thank you very much for your answer!Earmuff

© 2022 - 2024 — McMap. All rights reserved.