减少基于特征的模板
reduction of eigen based templates
我正在尝试基于特征矩阵进行缩减。
#include <iostream>
#include <Eigen/Dense>
#include <type_traits>
template<typename T1, typename T2, int n1, int n2>
auto reduction(Eigen::Matrix<T1, n1, n2> &a1,
Eigen::Matrix<T2, n1, n2> &a2)
-> decltype(T1{}*T2{})
{
using BaseT3 =
typename std::remove_cv<typename std::remove_reference<decltype(T1{}*T2{})>::type>::type;
BaseT3 res = a1(0, 0)*a2(0, 0);
for (int i=0; i<n1; ++i)
for (int j=0; j<n2; ++j)
if (i+j)
res = res + a1(i, j)*a2(i, j);
return res;
}
int main()
{
Eigen::Matrix<double, 3, 3> m;
Eigen::Matrix<Eigen::Vector3d, 3, 3> n;
std::cout << reduction(m, n) << std::endl;
}
基本上,我试图得到 sum_{i, j} a1[i, j] * a2[i, j]
,其中 a1
和 a2
是一些本征数学,但我遇到了编译错误。我得到的错误是
error: no match for ‘operator=’ (operand types are ‘BaseT3 {aka
Eigen::CwiseUnaryOp<Eigen::internal::scalar_multiple_op<double>,
const Eigen::Matrix<double, 3, 1> >}’
and
‘const Eigen::CwiseBinaryOp<Eigen::internal::scalar_sum_op<double>,
const Eigen::CwiseUnaryOp<Eigen::internal::scalar_multiple_op<double>,
const Eigen::Matrix<double, 3, 1> >,
const Eigen::CwiseUnaryOp<Eigen::internal::scalar_multiple_op<double>,
const Eigen::Matrix<double, 3, 1> > >’)
res = res + a1(i, j)*a2(i, j);
^
如果我没记错的话,对于给定的 main
,键入 BaseT3
应该是 Eigen::Vector3d
。我还尝试进行静态转换,因此 operator=
应该不会失败,但随后出现其他错误。
这是c++11,我使用Eigen3,编译器是g++ 5.4.1。
T1 * T2 的 decltype 不是您在这里期望的类型 - Eigen 大量使用表达式模板。您的错误中的 CWiseUnaryOp 和 CWiseBinaryOp 类型表明了这一点。换句话说,"double * Vector3d" 的结果不是您所期望的(它不是 Vector3d,而是 cwisebinaryop)。
另请参阅:Writing functions taking Eigen Types。
在这种特定情况下,您可以通过为模板函数的第一个和第二个参数创建 Eigen 基本类型的部分特化来找到解决方案。
Eigen 使用表达式模板来优化操作链。
所以 MatrixA*MatrixB 是 不是 矩阵类型,而是表示 "when evaluated this will be the product of a MatrixA times a MatrixB".
的表达式
结果是 A*B+C*D
不会创建(至少一样多)临时矩阵,而是当存储在输出矩阵中时,结果会 "lazily" 直接计算到输出矩阵中。
现在,您正在对元素进行多重运算。但是您的一种元素类型又是矩阵。结果证明,Eigen 对标量时间向量进行了表达式模板优化。
您想要的类型是 std::decay_t<decltype((T1{}+T2{}).eval())>
(嗯,它的 C++11 详细版本)。
你可以写一个花哨的 SFINAE 东西来检查它是否可以被评估,如果可以的话就这样做。或者您可以测试 Eigen 表达式模板类型。
我正在尝试基于特征矩阵进行缩减。
#include <iostream>
#include <Eigen/Dense>
#include <type_traits>
template<typename T1, typename T2, int n1, int n2>
auto reduction(Eigen::Matrix<T1, n1, n2> &a1,
Eigen::Matrix<T2, n1, n2> &a2)
-> decltype(T1{}*T2{})
{
using BaseT3 =
typename std::remove_cv<typename std::remove_reference<decltype(T1{}*T2{})>::type>::type;
BaseT3 res = a1(0, 0)*a2(0, 0);
for (int i=0; i<n1; ++i)
for (int j=0; j<n2; ++j)
if (i+j)
res = res + a1(i, j)*a2(i, j);
return res;
}
int main()
{
Eigen::Matrix<double, 3, 3> m;
Eigen::Matrix<Eigen::Vector3d, 3, 3> n;
std::cout << reduction(m, n) << std::endl;
}
基本上,我试图得到 sum_{i, j} a1[i, j] * a2[i, j]
,其中 a1
和 a2
是一些本征数学,但我遇到了编译错误。我得到的错误是
error: no match for ‘operator=’ (operand types are ‘BaseT3 {aka
Eigen::CwiseUnaryOp<Eigen::internal::scalar_multiple_op<double>,
const Eigen::Matrix<double, 3, 1> >}’
and
‘const Eigen::CwiseBinaryOp<Eigen::internal::scalar_sum_op<double>,
const Eigen::CwiseUnaryOp<Eigen::internal::scalar_multiple_op<double>,
const Eigen::Matrix<double, 3, 1> >,
const Eigen::CwiseUnaryOp<Eigen::internal::scalar_multiple_op<double>,
const Eigen::Matrix<double, 3, 1> > >’)
res = res + a1(i, j)*a2(i, j);
^
如果我没记错的话,对于给定的 main
,键入 BaseT3
应该是 Eigen::Vector3d
。我还尝试进行静态转换,因此 operator=
应该不会失败,但随后出现其他错误。
这是c++11,我使用Eigen3,编译器是g++ 5.4.1。
T1 * T2 的 decltype 不是您在这里期望的类型 - Eigen 大量使用表达式模板。您的错误中的 CWiseUnaryOp 和 CWiseBinaryOp 类型表明了这一点。换句话说,"double * Vector3d" 的结果不是您所期望的(它不是 Vector3d,而是 cwisebinaryop)。
另请参阅:Writing functions taking Eigen Types。
在这种特定情况下,您可以通过为模板函数的第一个和第二个参数创建 Eigen 基本类型的部分特化来找到解决方案。
Eigen 使用表达式模板来优化操作链。
所以 MatrixA*MatrixB 是 不是 矩阵类型,而是表示 "when evaluated this will be the product of a MatrixA times a MatrixB".
的表达式结果是 A*B+C*D
不会创建(至少一样多)临时矩阵,而是当存储在输出矩阵中时,结果会 "lazily" 直接计算到输出矩阵中。
现在,您正在对元素进行多重运算。但是您的一种元素类型又是矩阵。结果证明,Eigen 对标量时间向量进行了表达式模板优化。
您想要的类型是 std::decay_t<decltype((T1{}+T2{}).eval())>
(嗯,它的 C++11 详细版本)。
你可以写一个花哨的 SFINAE 东西来检查它是否可以被评估,如果可以的话就这样做。或者您可以测试 Eigen 表达式模板类型。