Шаблоны выражений в Eigen

я хотел бы понять, как шаблоны выражений работают в Eigen. Я понял, что сумма двух динамических двойных векторов выполняется чем-то, что выглядит следующим образом :

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

я также понял, как реализуется разница двух векторов.

у меня два вопроса.

1. Как работает произведение вектора на скаляр?

я заметил это

CwiseBinaryOp< internal::scalar_product_op<double>, VectorXd const, VectorXd const > 
но я такое ощущение, что он предназначен только для выполнения операций покомпонентного между двумя векторами. Означает ли это, что произведение вектора скаляром соответствует унарному оператору, скажем
CwiseUnaryOp< internal::scalar_product_op<double>, VectorXd const, VectorXd const > ?

2. Можно ли создавать выражения шаблонов из смешанных операций?

например, в выражениях типа

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

правда ли, что эти операции выполняются вложенным способом, как это?

  • v-w приводит к построению экземпляра E1
  • 2*v приводит к построению экземпляра E2
  • 2*v + (v-w) приводит к построению экземпляра E3
  • u + (2*v + (u-w)) приводит к построению экземпляра E4
  • x = u + (2*v + (v-w)) звонки

конструктор

VectorXd(E4 const &);

или перегрузки

VectorXd & operator=(E4 const &);

который оценивает дерево, построенное из предыдущих шагов, с помощью следующие псевдонимы:

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 >;

1 ответов


1. Как работает произведение вектора на скаляр?

в Eigen 3.2 он реализован как унарный оператор с функтором, хранящим значение скалярного фактора. В Eigen 3.3 он теперь реализован как двоичный оператор между заданным матричным выражением и постоянным выражением, что-то вроде:

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

этот подход позволяет четко различать s*vec и vec*s, и тип возврата, например,vec*s - это эквивалент к тому из vec*VectorxD::Constant(vec.size(),s).

2. Можно ли создавать выражения шаблонов из смешанных операций?

ваше понимание правильно: сначала создаются выражения E1-E4, затем оценка начинается с перегруженного operator= генерация кода:

for(i=0;i<x.size();++i)
  x[i] = E4.coeff(i);