Eigen教程(一)-The Matrix Class

对官方文档的直简译,以后自查方便点,顺便加深印象,部分添加了自己的理解


1.The first three template parameters of Matrix

Matrix类有六个模板参数,目前学前三个参数足矣,后三个有默认值

Matrix<typename Scalar, int RowsAtCompileTime, int ColsAtCompileTime>
  • Scalar是数据类型
  • RowsAtCompileTimeColsAtCompileTime是行数和列数(在编译时已知)

Eigen提供了许多方便的typedef,例Matrix4f是一个4x4的浮点矩阵,下面展示Eigen是如何定义它的:

typedef Matrix<float, 4, 4> Matrix4f;

2.Vectors

在Eigen中,向量是矩阵的特殊情况,它只有一行或一列,拥有一列的向量是最常见的,这样的向量被称为列向量,通常简称为向量;只有一行的向量称为行向量。
例如,Vector3f是一个三维浮点列向量,在Eigen中的定义如下:

typedef Matrix<float, 3, 1> Vector3f;

Eigen中同时提供了对行向量的定义,如:

typedef Matrix<int, 1, 2> RowVector2i;

3.The special value Dynamic

Eigen不局限于维度在编译时已知的矩阵,RowsAtCompileTimeColsAtCompileTime两个模板参数可以采用特殊值Dynamic来表示在编译时是未知的,只有在运行时(run-time)对矩阵大小进行确定,如MatrixXd表示一个动态大小的浮点矩阵,其定义如下:

typedef Matrix<double, Dynamic, Dynamic> MatrixXd;

同样的,VectorXi的定义也就不言自明了:

typedef Matrix<int, Dynamic, 1> VectorXi;

4.Constructors

默认构造函数不执行任何动态内存分配,不初始化矩阵系数:

Matrix3f a;
MatrixXf b;

其中,a是一个3x3矩阵,等价于一个float[9]的未初始化系数的数组;b是一个动态矩阵,当前的大小是0x0,数组内系数还未被分配内存。

也可以通过带参构造函数的方式,对矩阵而言,行数总是第一个参数,对向量而言,只需要传向量大小:

MatrixXf a(10, 15);
VectorXf b(30);

为了向固定大小(fixed-size)动态大小(dynamic-size) 提供统一的接口,利用上述构造函数对固定大小的矩阵进行构造是合法的,尽管在这种情况下传进去的尺寸参数是无用的:

Matrix3f a(3, 3);

注意,上述操作事实上是一个空操作。以下是一些向量的构造函数:

Vector2d a(5.0, 6.0);
Vector3d b(5.0, 6.0, 7.0);
Vector4d c(5.0, 6.0, 7.0, 8.0);

5.Coefficient accessors

Eigen中主要的元素赋值和修改都是利用重载括号运算符() 进行实现,对矩阵而言,行索引总是第一个传进去的,对于向量而言,只需要传进一个参数,索引从0开始:

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

using namespace Eigen;
using namespace std;

int main()
{
	MatrixXd m(2, 2);
	m(0, 0) = 3;
	m(1, 0) = 2.5;
	m(0, 1) = -1;
	m(1, 1) = m(1, 0) + m(0, 1);
	cout << "Here is the matrix m:\n" << m << endl;
	VectorXd v(2);
	v(0) = 4;
	v(1) = v(0) - 1;
	cout << "Here is the vector v:\n:" << v << endl;
}

输出如下:

Here is the matrix m:
  3  -1
2.5 1.5
Here is the vector v:
4
3
  • 注意语句 m(index) 不局限于向量,对矩阵而言这意味着在系数数组中进行基于索引的访问,不过这依赖于矩阵的存储顺序,所有的矩阵默认都是按列顺序进行存储(可以改)
  • []也被重载用于向量中基于索引的访问,但请记住,C++ 不允许 []接受多个参数,因此Eigen将[]限制适用范围仅为向量

6.Comma-initialization

矩阵和向量系数可以使用所谓的 逗号初始化(Comma-initialization) 语法方便地设置。

Matrix3f m;
m << 1, 2, 3, 
	 4, 5, 6,
	 7, 8, 9;
cout << m:

输出如下:

1 2 3
4 5 6
7 8 9

7.Resizing

矩阵的当前大小可以通过 rows()cols()size() 检索。这些方法分别返回行数列数元素数。调整动态大小矩阵的大小是通过 resize() 方法完成的。

#include <iostream>
#include <Eigen/Dense>
 
using namespace Eigen;
using namespace std;
 
int main()
{
  MatrixXd m(2,5);
  m.resize(4,3);
  cout << "The matrix m is of size "
       << m.rows() << "x" << m.cols() << endl;
  cout << "It has " << m.size() << " coefficients" << endl;
  VectorXd v(2);
  v.resize(5);
  cout << "The vector v is of size " << v.size() << endl;
  cout << "As a matrix, v is of size "
       << v.rows() << "x" << v.cols() << endl;
}

输出如下:

The matrix m is of size 4x3
It has 12 coefficients
The vector v is of size 5
As a matrix, v is of size 5x1

如果矩阵的实际大小不改变,resize()函数不做任何操作;否则该操作是带有“破坏性的”:元素的值会被改变,如果不想改变执行 conservativeResize()

上面这句话摘自Eigen官方教程,找了一下,没有具体对这句话的含义做出明确的解释?(挖个坑,以后再补)
下面具体看一下是如何进行resize的,这里首先要介绍一下Eigen中的Storage Order:
A = [ 8 2 2 9 9 1 4 4 3 5 4 5 ] . A = \begin{bmatrix} 8 & 2 & 2 & 9 \\ 9 & 1 & 4 & 4 \\ 3 & 5 & 4 & 5 \end{bmatrix}. A=893215244945.
如果说矩阵A是按行存储,那么A在内存中的存储就是:
[8 2 2 9 9 1 4 4 3 5 4 5 ]
同理按列存储就是
[8 9 3 2 1 5 2 4 4 9 4 5 ]
Eigen中的Matrix类提供的第四个参数Options指示了矩阵的存储顺序,默认是按列存储。

    MatrixXd o(3, 4);
    o << 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12;
    cout << "o before resize: " << o << endl;
    o.resize(4, 3);
    cout << "o after resize: " << o << endl;

o中,数据的存储按列,即[1 5 9 2 6 10 3 7 11 4 8 12]resize()的结果如下:

o before resize: 
 1  2  3  4
 5  6  7  8
 9 10 11 12
o after resize: 
 1  6 11
 5 10  4
 9  3  8
 2  7 12

可见,转换后的矩阵仍然按列存储。


8.Assignment and resizing

利用=可以进行矩阵的赋值操作,如果=两边的矩阵大小不一致,那么Eigen将自动调整等号左边的矩阵至右边矩阵的大小:

MatrixXf a(2,2);
std::cout << "a is of size " << a.rows() << "x" << a.cols() << std::endl;
MatrixXf b(3,3);
a = b;
std::cout << "a is now of size " << a.rows() << "x" << a.cols() << std::endl;

输出如下:

a is of size 2x2
a is now of size 3x3

9.Fixed vs. Dynamic size

什么时候应该用固定大小(如Matrix4f),什么时候应该用动态大小(如MatrixXd)?Eigen给出的答案是:当矩阵大小小于16(大概),使用固定大小能避免手动开辟动态内存从而带来优异的性能表现,但是,当矩阵太大时(大于32),可能导致栈溢出。事实上,以下语句

Matrix4f m;

相当于

float m[16];

相反的,动态矩阵总是在堆区开辟内存:

MatrixXd m(rows, cols);

相当于

float *m = new float[rows * cols];

10.Optional template parameters

目前为止,我们只对Matrix类的前三个模板参数进行了详细讨论,接下来讨论三个可选的模板参数,完整的模板参数如下:

Matrix<typename Scalar,
       int RowsAtCompileTime,
       int ColsAtCompileTime,
       int Options = 0,
       int MaxRowsAtCompileTime = RowsAtCompileTime,
       int MaxColsAtCompileTime = ColsAtCompileTime>
  • Options是一个位域,我们只讨论一位的情况:RowMajor,它指出矩阵是按照行进行元素存储的,下面的例子展示了一个3x3的按行存储的矩阵:
Matrix<float, 3, 3, RowMajor>
  • MaxRowsAtCompileTimeMaxColsAtCompileTime在当你不清楚矩阵的具体大小但知道矩阵尺寸的上下边界(最大值最小值)时将非常有用,这么做的最大原因是你可以避免动态内存分配:
Matrix<float, Dynamic, Dynamic, 0, 3, 4>

11.Convenience typedefs

  • MatrixNt for Matrix<type, N, N>. For example, MatrixXi for Matrix<int, Dynamic, Dynamic>.
  • VectorNt for Matrix<type, N, 1>. For example, Vector2f for Matrix<float, 2, 1>.
  • RowVectorNt for Matrix<type, 1, N>. For example, RowVector3d for Matrix<double, 1, 3>.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值