Eigen学习笔记5:块操作

块是Matrix或Array的矩形部分。块表达式既可以用作右值,也可以用作左值。

使用块操作

The most general block operation in Eigen is called .block() 有两个版本,其语法如下:

操作版本:构造一个动态大小的块表达式版本:构造一个固定大小的块表达式
块大小(p,q),从开始(i,j)
matrix.block(i,j,p,q);
matrix.block <p,q>(i,j);

Eigen一样,索引从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 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

在上面的示例中,.block()用作右值,即仅从中读取。

但是,块也可以用作左值,这意味着您可以分配给块。

在下面的示例中对此进行了说明。此示例还演示了数组中的块,其工作原理与上述矩阵中的块完全相同。

#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()方法可用于任何块操作,但还有一些其他特殊情况的方法,providing more specialized API and/or better performance.

关于性能,最重要的是在编译时为Eigen提供尽可能多的信息。For example, if your block is a single whole column in a matrix, using the specialized .col() function described below lets Eigen know that, which can give it optimization opportunities.

列和行

单独的列和行是块的特殊情况。Eigen提供了可以轻松解决它们的方法:.col().row()

块操作方法
ith row *
matrix.row(i);
jth column *
matrix.col(j);

对自变量col()row()将被访问的列或行的索引。与Eigen一样,索引从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

 That example also demonstrates that block expressions (here columns) can be used in arithmetic like any other expression.

与角相关的操作

Eigen also provides special methods for blocks that are flushed against one of the corners or sides of a matrix or array.

For instance, .topLeftCorner() 可用于引用矩阵左上角的块。

下表总结了各种可能性:

操作版本:构造一个动态大小的块表达式版本:构造一个固定大小的块表达式
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 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、付费专栏及课程。

余额充值