使用现代C++在 Eigen3 矩阵上使用 for 循环进行元素操作的优雅方式



我想根据每个元素的位置对矩阵中的元素进行一些操作。

我知道默认情况下,特征矩阵是列主矩阵,所以要遍历矩阵,外部 for 循环用于每列,内部 for 循环用于每一行。我有 4 种表达式要分配给m(r,c),具体取决于rc的值。一些伪代码如下所示:

if c == some_c
if r == some_r
m(r,c) = some expression A
else
m(r,c) = some expression B
else
if r == some_r
m(r,c) = some expression C
else
m(r,c) = some expression D 

我还在下面制作了详细的 c++ 代码。我不是C++专家,所以我不确定我的代码是否优雅。你能告诉我如何改进它吗?我更喜欢使用可能的现代 C++14 或 C++17 功能。

#include <Eigen/Dense>
using Matrix = Eigen::MatrixXd
void some_operation_on_matrix(Matrix& m, size_t some_r, size_t some_c)
{
for (size_t c = 0; c < m.cols(); c++) {
for (size_t r = 0; r < m.rows(); r++) {
if (c == some_c) {
if (r == some_r) {
// m(r,c) = some expression A
}
else {
// m(r,c) = some expression B
}
}
else {
if (r == some_r) {
// m(r,c) = some expression C
}
else {
// m(r,c) = some expression D
}
}
}
}
}

下面是使用 lambda 函子的解决方案:

void some_operation_on_matrix(Eigen::MatrixXd& out, int some_r, int some_c)
{
out = Eigen::MatrixXd::NullaryExpr(out.rows(), out.cols(),
[&](Eigen::Index r, Eigen::Index c)
{
if(c == some_c)
if(r == some_r)
return 1.0; // some expr A
else
return 2.0; // some expr B
else
if(r == some_r)
return 3.0; // some expr C
else
return 4.0; // some expr D 
});
}

可能更有效(如果所有表达式都是常量(将是

out.setConstant(D);
out.row(some_r).setConstant(C);
out.col(some_c).setConstant(B);
out(some_r, some_c) = A;

我会稍微改变一下循环的逻辑

void some_operation_on_matrix(Matrix& m, size_t some_r, size_t some_c)
{
for (size_t c = 0; c < m.cols(); c++) {
if (c == some_c) {
for (size_t r = 0; r < m.rows(); r++) {
if (r == some_r) {
// m(r,c) = some expression A
}
else {
// m(r,c) = some expression B
}
}
else {
for (size_t r = 0; r < m.rows(); r++) {
if (r == some_r) {
// m(r,c) = some expression C
}
else {
// m(r,c) = some expression D
}
}
}
}
}

因此,只需要为所有m.cols计算 if 语句if (c == some_c),而不必为所有m.cols * m.rows计算。

您可以在函数中提取第二个 for 循环

void innerLoop(Matrix &m, const size_t some_r, std::function expression1, std::function expression2)
{
for (size_t r = 0; r < m.rows(); r++) {
if (r == some_r) {
m(r,c) = expression1(...);
}
else {
m(r,c) = expression2(...);
}
}
}

void some_operation_on_matrix(Matrix& m, size_t some_r, size_t some_c)
{
for (size_t c = 0; c < m.cols(); c++) {
if (c == some_c) {
innerLoop(m, some_r, expressionA, expressionB);
else {
innerLoop(m, some_r, expressionC, expressionC);           
}
}
}

相关内容

  • 没有找到相关文章

最新更新