Шаблоны выражений в 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);