对官方文档的直简译,以后自查方便点,顺便加深印象,部分添加了自己的理解
Content
1.The first three template parameters of Matrix
Matrix类有六个模板参数,目前学前三个参数足矣,后三个有默认值
Matrix<typename Scalar, int RowsAtCompileTime, int ColsAtCompileTime>
Scalar
是数据类型RowsAtCompileTime
和ColsAtCompileTime
是行数和列数(在编译时已知)
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不局限于维度在编译时已知的矩阵,RowsAtCompileTime
和ColsAtCompileTime
两个模板参数可以采用特殊值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>
MaxRowsAtCompileTime
和MaxColsAtCompileTime
在当你不清楚矩阵的具体大小但知道矩阵尺寸的上下边界(最大值最小值)时将非常有用,这么做的最大原因是你可以避免动态内存分配:
Matrix<float, Dynamic, Dynamic, 0, 3, 4>
11.Convenience typedefs
- MatrixNt for Matrix<type, N, N>. For example,
MatrixXi
forMatrix<int, Dynamic, Dynamic>
. - VectorNt for Matrix<type, N, 1>. For example,
Vector2f
forMatrix<float, 2, 1>
. - RowVectorNt for Matrix<type, 1, N>. For example,
RowVector3d
forMatrix<double, 1, 3>
.