Eigen学习(五)块操作

这节介绍块操作的必要性。块指的是矩阵或数组中的一个矩形区域,块表达式可以用于左值或者右值,同样不会耗费运行时间,由编译器优化。

使用块操作

Eigen中最常用的块操作是block()方法,共有两个版本

Block operationVersion constructing a 
dynamic-size block expression
Version constructing a 
fixed-size block expression
Block of size (p,q), starting at (i,j)
matrix.block(i,j,p,q);
matrix.block<p,q>(i,j);
索引从0开始。两个版本都可用于固定尺寸或者动态尺寸的矩阵和数组。这两个表达式语义上相同,唯一的区别是如果块的尺寸比较小的话固定尺寸版本的块操作运行更快,但是需要在编译阶段知道大小。
#include <Eigen/Dense>
#include <iostream>
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 << "Block in the middle" << endl;
  cout << m.block<2,2>(1,1) << endl << endl;
  for (int i = 1; i <= 3; ++i)
  {
    cout << "Block of size " << i << "x" << i << endl;
    cout << m.block(0,0,i,i) << endl << endl;
  }
}

输出为

Block in the middle
 6  7
10 11

Block of size 1x1
1

Block of size 2x2
1 2
5 6

Block of size 3x3
 1  2  3
 5  6  7
 9 10 11

上述例子中的块操作方法作为表达式的右值,意味着是只读形式的,然而,块操作也可以作为左值使用,意味着你可以给他赋值。下面的例子说明了这一点,当然对于矩阵的操作是一样的。

#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;
}
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()方法可用于任何形式的块操作,还是有特殊的方法API用于特殊情况的,主要是为了更好的性能。说到性能,最重要的是在编译阶段给Eigen尽可能多的信息。比如,如果你的块是一个矩阵中的一列,那么使用col()方法会更好。本节其余的介绍都是关于这些特殊的方法的。

行和列

行和列是一中特殊的块。Eigen提供了特殊的方法:col()和row()。

Block operationMethod
ith row *
matrix.row(i);
jth column *
matrix.col(j);
其中的参数是需要用到的行或者列的索引值,从0开始。
#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 adding 3 times the first column into the third column, the matrix m is:\n";
  cout << m << endl;
}

输出为

Here is the matrix m:
1 2 3
4 5 6
7 8 9
2nd Row: 4 5 6
After adding 3 times the first column into the third column, the matrix m is:
 1  2  6
 4  5 18
 7  8 30

边角相关的操作

Eigen同样提供了对于挨着矩阵或数组的边、角的特殊操作方法,比如topLeftCorner()方法可用于操作矩阵左上角的区域。总结如下:

Block operationVersion constructing a 
dynamic-size block expression
Version constructing a 
fixed-size block expression
Top-left p by q block *
matrix.topLeftCorner(p,q);
matrix.topLeftCorner<p,q>();
Bottom-left p by q block *
matrix.bottomLeftCorner(p,q);
matrix.bottomLeftCorner<p,q>();
Top-right p by q block *
matrix.topRightCorner(p,q);
matrix.topRightCorner<p,q>();
Bottom-right p by q block *
matrix.bottomRightCorner(p,q);
matrix.bottomRightCorner<p,q>();
Block containing the first q rows *
matrix.topRows(q);
matrix.topRows<q>();
Block containing the last q rows *
matrix.bottomRows(q);
matrix.bottomRows<q>();
Block containing the first p columns *
matrix.leftCols(p);
matrix.leftCols<p>();
Block containing the last q columns *
matrix.rightCols(q);
matrix.rightCols<q>();
#include <Eigen/Dense>
#include <iostream>
using namespace std;
int main()
{
  Eigen::Matrix4f m;
  m << 1, 2, 3, 4,
       5, 6, 7, 8,
       9, 10,11,12,
       13,14,15,16;
  cout << "m.leftCols(2) =" << endl << m.leftCols(2) << endl << endl;
  cout << "m.bottomRows<2>() =" << endl << m.bottomRows<2>() << endl << endl;
  m.topLeftCorner(1,3) = m.bottomRightCorner(3,1).transpose();
  cout << "After assignment, m = " << endl << m << endl;
}

输出为

m.leftCols(2) =
 1  2
 5  6
 9 10
13 14

m.bottomRows<2>() =
 9 10 11 12
13 14 15 16

After assignment, m = 
 8 12 16  4
 5  6  7  8
 9 10 11 12
13 14 15 16

对于向量的块操作

Eigen也提供了一些针对向量和一维数组的块操作方法:

Block operationVersion constructing a 
dynamic-size block expression
Version constructing a 
fixed-size block expression
Block containing the first n elements *
vector.head(n);
vector.head<n>();
Block containing the last n elements *
vector.tail(n);
vector.tail<n>();
Block containing n elements, starting at position i *
vector.segment(i,n);
vector.segment<n>(i);
#include <Eigen/Dense>
#include <iostream>
using namespace std;
int main()
{
  Eigen::ArrayXf v(6);
  v << 1, 2, 3, 4, 5, 6;
  cout << "v.head(3) =" << endl << v.head(3) << endl << endl;
  cout << "v.tail<3>() = " << endl << v.tail<3>() << endl << endl;
  v.segment(1,4) *= 2;
  cout << "after 'v.segment(1,4) *= 2', v =" << endl << v << endl;
}

输出为

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




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值