如何使用 Eigen 在 Matrix 块上构造一个方便的迭代器

How to construct a convenient iterator over blocks of Matrix using Eigen

我想构建一个“按块列”迭代器,它遍历具有特征的密集矩阵的所有可能块。

#include <iostream>
#include <Eigen/Dense>

int main() {
    Eigen::MatrixXd A(4,4);
    A << 1,2,3,4,
        5,6,7,8,
        9,10,11,12,
        13,14,15,16;

    for (Eigen::Index k=0; k< ? ; ++k) {
       //?????
       Eigen::Iterator it.... ;
       std::cout<<it<<std::endl;
    }
}

输出应该是:

1 2
5 6

9 10
13 14

3 4
7 8

11 12
15 16

基本上,我正在搜索

的一个不错的版本
#include <iostream>
#include <Eigen/Dense>

int main() {
    Eigen::MatrixXd A(4,4);
    A << 1,2,3,4,
        5,6,7,8,
        9,10,11,12,
        13,14,15,16;

    int numberOfBlocksPerDir =2;
    for (int i = 0; i < numberOfBlocksPerDir ; i++) {
      for (int j = 0; j < numberOfBlocksPerDir ; j++) {
        Eigen::Block<Eigen::MatrixXd, 2, 2> currentBlock = A.block<2, 2>(numberOfBlocksPerDir * j, numberOfBlocksPerDir  * i);
        std::cout<<currentBlock <<std::endl;
      }
  }
}

是否可以使用 Eigen 内置函数实现类似的功能?如果不是,我自己完成这个的好方法是什么? (定义我自己的迭代器?)

我在 Eigen 文档中找不到任何内容,但是一个简单的前向迭代器不需要太多:

  • 等式运算符
  • 增量运算符
  • 取消引用运算符

这是我想出来的

template <Eigen::Index RowSize, Eigen::Index ColSize>
struct EigenBlockIt {
    using Self = EigenBlockIt<RowSize, ColSize>;

    // constructors for end()/begin() equivalents
    EigenBlockIt() : matrix(nullptr) , col(0), row(0) { }
    EigenBlockIt(const Eigen::MatrixXd& matrix) : matrix(&matrix) , col(0), row(0) { }

    // comparison
    friend bool operator ==(const Self& lhs, const Self& rhs) {
        return lhs.matrix == rhs.matrix && lhs.row == rhs.row && lhs.col == rhs.col;
    }
    friend bool operator !=(const Self& lhs, const Self& rhs) {
        return lhs.matrix != rhs.matrix || lhs.row != rhs.row || lhs.col != rhs.col;
    }

    // increment (postfix/prefix)
    Self& operator++() {
        row++;
        if (row >= matrix->rows() / RowSize) {
            row = 0;
            col++;
            if (col >= matrix->cols() / ColSize) {
                matrix = nullptr;
                row = 0;
                col = 0;
            }
        }
        return *this;
    }
    Self operator++(int) {
        EigenBlockIt it = *this;
        ++(*this);
        return it;
    }

    // dereference
    const Eigen::Block<const Eigen::MatrixXd, RowSize, ColSize> operator *() const {
        return matrix->block<RowSize, ColSize>((matrix->rows() / RowSize) * row, (matrix->cols() / ColSize) * col);
    }

    const Eigen::MatrixXd* matrix;
    Eigen::Index row;
    Eigen::Index col;
};

用法:

for (auto it = EigenBlockIt<2, 2>(A); it != EigenBlockIt<2, 2>(); ++it) {
    std::cout << *it << std::endl;
}

演示:https://godbolt.org/z/boz9xG