简介
Eigen 中Matrix/Array提供了.block()
来进行block区块操作,这是面向系数提供的操作功能。
语法
Eigen中提供了2种语法,针对产生的结果是一致的。但存在性能上的不同,任何时候,使用fixed-size模式都会得到更好地性能优化。
分类 | 语法 | 说明 |
---|---|---|
dynamic-size | matrix.block(i,j,p,q); | 执行时才知道维度大小(p,q)。 |
fixed-size | matrix.block<p,q>(i,j); | 编译时指定维度大小(p,q)。 |
解释: 区块的维度大小尺寸:(p,q), 起始的位置:(i,j)。同样的,位置索引从0开始。
查看一个简单的示例:
//matrix_block1.cpp
#include <Eigen/Dense>
#include <iostream>
using namespace Eigen;
using namespace std;
int main()
{
Eigen::MatrixXf m(4,4);
m << 1, 2, 3, 4,
5, 6, 7, 8,
9,10,11,12,
13,14,15,16;
cout << "matrix m:" << endl << m <<endl<<endl;
cout<<"-----------------"<<endl;
cout << "Block in the middle -- m.block<2,2>(1,1)" << endl;
cout << m.block<2,2>(1,1) << endl << endl;
cout<<"-----------------"<<endl;
for (int i = 1; i <= 3; ++i)
{
cout << "Get from (0,0), Block of size " << i << "x" << i << endl;
cout << m.block(0,0,i,i) << endl << endl;
}
cout<<"-----------------"<<endl;
for (int i = 1; i <= 3; ++i)
{
cout << "Get from (1,1), Block of size " << i << "x" << i << endl;
cout << m.block(1,1,i,i) << endl << endl;
}
}
执行的结果:
$ g++ -I /usr/local/include/eigen3 matrix_block1.cpp -o matrix_block1
$
$ ./matrix_block1
matrix m:
1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 16
-----------------
Block in the middle -- m.block<2,2>(1,1)
6 7
10 11
-----------------
Get from (0,0), Block of size 1x1
1
Get from (0,0), Block of size 2x2
1 2
5 6
Get from (0,0), Block of size 3x3
1 2 3
5 6 7
9 10 11
-----------------
Get from (1,1), Block of size 1x1
6
Get from (1,1), Block of size 2x2
6 7
10 11
Get from (1,1), Block of size 3x3
6 7 8
10 11 12
14 15 16
block()
不仅可以用于右值,也可以用于左值。下面来个Array的简单示例。
//matrix_block2.cpp
#include <Eigen/Dense>
#include <iostream>
using namespace std;
using namespace Eigen;
int main()
{
Array22f m;
m << 1,2,
3,4;
Array44f a = Array44f::Constant(0.6);
cout << "Here is the array a:" << endl << a << endl << endl;
a.block<2,2>(1,1) = m;
cout << "Here is now a with m copied into its central 2x2 block:" << endl << a << endl << endl;
a.block(0,0,2,3) = a.block(2,1,2,3);
cout << "Here is now a with bottom-right 2x3 block copied into top-left 2x2 block:" << endl << a << endl << endl;
}
此示例中,在一个4X4的常量二维数组中,修改(2,2,1,1)区块的系数,此次修改操作对应大小指定为1X1了,取值来源区块为2X2数组。
执行结果如下,最后划线的部分是最后一次block区块替换的部分:
$ g++ -I /usr/local/include/eigen3 matrix_block2.cpp -o matrix_block2
$
$ ./matrix_block2
Here is the array a:
0.6 0.6 0.6 0.6
0.6 0.6 0.6 0.6
0.6 0.6 0.6 0.6
0.6 0.6 0.6 0.6
Here is now a with m copied into its central 2x2 block:
0.6 0.6 0.6 0.6
0.6 1 2 0.6
0.6 3 4 0.6
0.6 0.6 0.6 0.6
Here is now a with bottom-right 2x3 block copied into top-left 2x2 block:
3 4 0.6 0.6
-----------
0.6 0.6 0.6 0.6
-----------
0.6 3 4 0.6
0.6 0.6 0.6 0.6
行和列的操作
单个的行或者列操作是block
的一种特殊形式,Eigen中提供了更好地API方法col(), row()
。
- matrix.row(i) : 第 i 行;
- matrix.col(j) : 第 j 列;
示例:
//matrix_block3.cpp
#include <Eigen/Dense>
#include <iostream>
using namespace std;
int main()
{
Eigen::MatrixXf m(3,3);
m << 1,2,3,
4,5,6,
7,8,9;
cout << "Here is the matrix m:" << endl << m << endl;
cout << "2nd Row: " << m.row(1) << endl;
m.col(2) += 3 * m.col(0);
cout << "After m.col(2) += 3 * m.col(0), the matrix m is:\n";
cout << m << endl;
}
执行:
$ g++ -I /usr/local/include/eigen3 matrix_block3.cpp -o matrix_block3
promote:eigen david$ ./matrix_block3
Here is the matrix m:
1 2 3
4 5 6
7 8 9
2nd Row: 4 5 6
After m.col(2) += 3 * m.col(0), the matrix m is:
1 2 6
4 5 18
7 8 30
边角操作
有时候,需要对矩阵的边角进行操作。Matrix提供了对应的方法函数,可以很变量地进行操作。
target | 动态 | 固定尺寸 |
---|---|---|
左上 | matrix.topLeftCorner(p,q); | matrix.topLeftCorner<p,q> (); |
左下 | matrix.bottomLeftCorner(p,q); | matrix.bottomLeftCorner<p,q> (); |
右上 | matrix.topRightCorner(p,q); | matrix.topRightCorner<p,q> (); |
右上 | matrix.bottomRightCorner(p,q); | matrix.bottomRightCorner<p,q> (); |
顶部q行 | matrix.topRows(q); | matrix.topRows(); |
底部q行 | matrix.bottomRows(q); | matrix.bottomRows(); |
左边p列 | matrix.leftCols§; | matrix.leftCols (); |
右边p列 | matrix.rightCols(q); | matrix.rightCols(); |
向量的block块操作
准对向量、一维数组,Eigen还提供了一组特别的块操作。
操作 | Dynamic 模式 | fixed_size 模式 |
---|---|---|
头部n个 | vector.head(n); | vector.head(); |
尾部n个 | vector.tail(n); | vector.tail(); |
自i起始的n个 | vector.segment(i,n); | vector.segment(i); |
示例
//matrix_block4.cpp
#include <Eigen/Dense>
#include <iostream>
using namespace std;
int main()
{
Eigen::ArrayXf v(6);
v << 1, 2, 3, 4, 5, 6;
Eigen::ArrayXf vv = v.head(3) ;
cout << "v.head(3) =" << endl << vv << endl << endl;
Eigen::ArrayXf vvv = v.tail<3>() ;
cout << "v.tail<3>() = " << endl << vvv << endl << endl;
v.segment(1,4) *= 2;
cout << "after 'v.segment(1,4) *= 2', v =" << endl << v << endl;
}
执行:
$ g++ -I /usr/local/include/eigen3 matrix_block4.cpp -o matrix_block4
promote:eigen david$ ./matrix_block4
v.head(3) =
1
2
3
v.tail<3>() =
4
5
6
after 'v.segment(1,4) *= 2', v =
1
4
6
8
10
6