本节介绍了operator()
索引行和列的子集所提供的众多可能性。此 API 已在 Eigen 3.4 中引入。它支持块 API提出的所有功能。特别是,它支持切片,包括获取一组行、列或元素,在矩阵内均匀分布或从索引数组索引。
所有上述操作都通过通用 DenseBase::operator()(const RowIndices&, const ColIndices&)
方法处理。每个参数可以是:
Eigen::all
表示按递增顺序排列的相应行或列的整个集合。Eigen::seq
、Eigen::seqN
或 Eigen::placeholders::lastN
函数构造的ArithmeticSequence
。int[N]
.更一般地说,它可以接受任何公开以下两个成员函数的对象:
<integral type> operator[](<integral type>) const;
<integral type> size() const;
其中Eigen::Index
代表任何整数类型。
通过Eigen::seq
或Eigen::seqN
函数获取一组在矩阵或向量中均匀分布的行、列或元素,其中“seq”代表算术序列。他们的签名总结如下:
功能 | 描述 | 例子 |
---|---|---|
seq(firstIdx,lastIdx)seq |
表示范围从firstIdx 到的整数序列lastIdx |
seq(2,5) <=> {2,3,4,5} |
seq(firstIdx,lastIdx,incr) |
与上同,但使用增量incr 从一个索引前进到下一个索引 |
seq(2,8,2)<=> {2,4,6,8} |
seqN (firstIdx,size) |
size 表示从开始的整数序列firstIdx |
seqN(2,5) <=> {2,3,4,5,6} |
seqN(firstIdx,size,incr) |
与上同,但使用增量incr 从一个索引前进到下一个索引 |
seqN(2,3,3) <=> {2,5,8} |
firstIdx
和参数也可以在 Eigen::last 符号的帮助下定义,该lastIdx
符号表示当算术序列通过 operator() 传递给它时,底层矩阵/向量的最后一行、列或元素的索引。以下是 2D array/matrixA
和 1D array/vector的一些示例v
。
意图 | 代码 | 块 API 等效性 |
---|---|---|
i 从有n 列的行开始的左下角 |
A( seg(i, last ), segN (0,n)) | A.bottomLeftCorner(A.rows()-i,n) |
从i ,j 开始的具有m 行和n 列的块 |
A( segN (i,m), segN (i,n)) | A.block(i,j,m,n) |
i0 从,j0 开始到 ,j1 结束i1 的块 |
A(seq(i0,i1),seq(j0,j1) | A.block(i0,j0,i1-i0+1,j1-j0+1) |
A的偶数列 | A(all,seq(0,last,2)) | |
第一个n 奇数行 A |
A( segN (1,n,2),all) | |
最后一栏 | A(all,last-1) | A.col(A.cols()-2) |
中间一排 | A(last/2,all) | A.row((A.rows()-1)/2) |
v 的最后一个元素从 i 开始 | v(seg (i, last )) | v.tail(v.size()-i) |
v 的最后一个n 元素 |
v(seg (last+1-n,last)) | v.tail(n) |
如上一个示例所示,引用最后 n 个元素(或行/列)编写起来有点麻烦。使用非默认增量,这变得更加棘手和容易出错。这里是Eigen::placeholders::lastN(size)
和Eigen::placeholders::lastN(size,incr)
:
意图 | 代码 | 块 API 等效性 |
---|---|---|
v 的最后一个n 元素 |
v(最后N(n)) | v.tail(n) |
m 大小乘以 A 的右下角n |
v(最后N(m), 最后N(n)) | A.bottomRightCorner(m,n) |
m 大小乘以 A 的右下角n |
v(最后N(m), 最后N(n)) | A.bottomRightCorner(m,n) |
最后一n 列占 1 列超过 3 |
A(all,最后N(n,3)) |
在性能方面,Eigen 和编译器可以利用编译时大小和增量。为此,您可以使用Eigen::fix
强制编译时参数。这样的编译时值可以与 Eigen::last
符号组合:
v( seg ( last -fix<7>, last -fix<2>))
这个例子中,Eigen 在编译时就知道返回的表达式有 6 个元素。它相当于:
v(seqN(last-7, fix<6>))
我们可以重新访问*A 示例的偶数列,*如下所示:
A(all, seq(0,last,fix<2>))
行/列索引也可以使用负增量按降序枚举。例如,从第 20 列到第 10 列中的 A 的两列中的一比一:
A( all , seg (20, 10, fix<-2>))
从最后n
一行开始的最后一行:
A( segN ( last , n, fix<-1>), all )
您还可以使用 ArithmeticSequence::reverse()
方法来反转其顺序。因此,前面的例子也可以写成:
A(lastN(n).reverse(),all)
泛型还可以将存储为a 、 a 、等operator()
的任意行或列索引列表作为输入。ArrayXi``std::vector
std::vector<int> ind{4,2,5,5,3};
MatrixXi A = MatrixXi::Random(4,6);
cout << "Initial matrix A:\n" << A << "\n\n";
cout << "A(all,ind):\n" << A(Eigen::placeholders::all,ind) << "\n\n";
Initial matrix A:
7 9 -5 -3 3 -10
-2 -6 1 0 5 -5
6 -3 0 9 -8 -8
6 6 3 9 2 6
A(all,ind):
3 -5 -10 -10 -3
5 1 -5 -5 0
-8 0 -8 -8 9
2 3 6 6 9
也可以直接传递静态数组:
Example: Output:
MatrixXi A = MatrixXi::Random(4,6);
cout << "Initial matrix A:\n" << A << "\n\n";
cout << "A(all,{4,2,5,5,3}):\n" << A(Eigen::placeholders::all,{4,2,5,5,3}) << "\n\n";
Initial matrix A:
7 9 -5 -3 3 -10
-2 -6 1 0 5 -5
6 -3 0 9 -8 -8
6 6 3 9 2 6
A(all,ind):
3 -5 -10 -10 -3
5 1 -5 -5 0
-8 0 -8 -8 9
2 3 6 6 9
或表达式:
ArrayXi ind(5); ind<<4,2,5,5,3;
MatrixXi A = MatrixXi::Random(4,6);
cout << "Initial matrix A:\n" << A << "\n\n";
cout << "A(all,ind-1):\n" << A(Eigen::placeholders::all,ind-1) << "\n\n";
# 输出:
Initial matrix A:
7 9 -5 -3 3 -10
-2 -6 1 0 5 -5
6 -3 0 9 -8 -8
6 6 3 9 2 6
A(all,ind-1):
-3 9 3 3 -5
0 -6 5 5 1
9 -3 -8 -8 0
9 6 2 2 3
当传递具有编译时大小(例如Array4i
、std::array
或静态数组)的对象时,返回的表达式也显示编译时维度。
更一般地说,operator()
可以接受与以下ind
类型T
兼容的任何对象作为输入:
Index s = ind.size(); or Index s = size(ind);
Index i;
i = ind[i];
这意味着您可以轻松构建自己的精美序列生成器并将其传递给operator()
. 这是一个扩大给定矩阵的示例,同时通过重复填充额外的第一行和列:
struct pad {
Index size() const { return out_size; }
Index operator[] (Index i) const { return std::max<Index>(0,i-(out_size-in_size)); }
Index in_size, out_size;
};
Matrix3i A;
A.reshaped() = VectorXi::LinSpaced(9,1,9);
cout << "Initial matrix A:\n" << A << "\n\n";
MatrixXi B(5,5);
B = A(pad{3,5}, pad{3,5});
cout << "A(pad{3,N}, pad{3,N}):\n" << B << "\n\n";
# 输出:
Initial matrix A:
1 4 7
2 5 8
3 6 9
A(pad{3,N}, pad{3,N}):
1 1 1 4 7
1 1 1 4 7
1 1 1 4 7
2 2 2 5 8
3 3 3 6 9