原文:Eigen官网-The Matrix class
在Eigen中,所有的矩阵Matrix和向量Vector都是由Matrix类构造的。向量只不过是矩阵的特殊形式,只有一列(列向量)或者一行(行向量)。
Matrix类的参数
Matrix有6个模板参数,主要使用前三个参数,剩下的三个参数有默认值。
Matrix<typename Scalar, int RowsAtCompileTime, int ColsAtCompileTime>
- Scalar是表示元素的类型,取值可以是 float ,int, double 等;
- RowsAtCompileTime为矩阵的行,在程序编译的时候就已经知道的;
- ColsAtCompileTime为矩阵的列,在程序编译的时候就已经知道的。
Eigen 提供了一些常用的 定义好的类型。比如,Matrix4f表示一个类型为float的4*4矩阵,在Eigen中定义如下:
typedef Matrix<float, 4, 4> Matrix4f;
Vectors向量
列向量是默认向量。
Eigen中定义的包含3个float元素的列向量如下:
typedef Matrix<float, 3, 1> Vector3f;
行向量定义如下:
typedef Matrix<int, 1, 2> RowVector2i;
Dynamic
Eigen并没有限制矩阵的尺寸必须在编译的时候就要确定下来。如果矩阵的尺寸在编译的时候是不确定的,而在运行的时候才能确定,Eigen提供了定义动态大小的方法,称为dynamic size ;将在编译时候就能确定的尺寸称为fixed size.
MatrixXd表示一个具有动态大小的矩阵,定义如下:
typedef Matrix<double, Dynamic, Dynamic> MatrixXd;
VectorXi表示一个具有动态大小的向量,定义如下:
typedef Matrix<int, Dynamic, 1> VectorXi;
还可以定义行数固定而列数是动态大小的矩阵:
Matrix<float, 3, Dynamic>
构造函数
(1)默认的构造函数不执行任何空间分配,也不初始化矩阵的元素。
Matrix3f a;
MatrixXf b;
- a是一个3*3的矩阵,分配了float[9]的空间,但未初始化内部元素;
- b是一个动态大小的矩阵,现在它的尺寸是0*0,还未分配空间。
(2)带参数的构造函数。
对于矩阵,行数在列数前面,对于向量,只有向量的大小。当对矩阵或向量指定大小时,只是分配相应大小的空间,未初始化元素。
MatrixXf a(10,15);
VectorXf b(30);
- a是一个10*15的动态大小的矩阵,分配了空间但未初始化元素;
- b是一个30大小的向量,同样分配空间未初始化元素。
(3)为了对固定大小和动态大小的矩阵提供统一的API,对指定大小的Matrix传递sizes也是合法的(传递也被忽略)。
Matrix3f a(3,3);
(4)可以用构造函数提供4以内尺寸的vector的初始化。
Vector2d a(5.0, 6.0);
Vector3d b(5.0, 6.0, 7.0);
Vector4d c(5.0, 6.0, 7.0, 8.0);
元素获取器
Eigen中通过对括号进行重载实现元素的获取。对于矩阵是:(行,列);对于向量,只是传递它的索引。索引都是以0为起始的。
m(index)也可以用于获取矩阵元素,但取决于matrix的存储顺序,默认是按列存储的(即一列一列的进行存储),当然也可以改为按行。
[]操作符可以用于向量元素的获取,但是不能用于matrix,因为C++中[]不能传递超过一个参数。
#include <iostream>
#include <Eigen/Dense>
using namespace Eigen;
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);
std::cout << "Here is the matrix m:\\n" << m << std::endl;
std::cout << "m(2):\\n" << m(2) << std::endl;
}
结果:
Here is the matrix m:
3 -1
2.5 1.5
m(2):
-1
逗号初始化
可以使用逗号初始化方式(comma-initializer)给矩阵和向量赋值。例如:
Matrix3f m;
m << 1, 2, 3,
4, 5, 6,
7, 8, 9;
std::cout << m;
结果如下:
1 2 3
4 5 6
7 8 9
这样就将上述值赋给了矩阵,在Eigen中矩阵默认的存储方式是行优先,就是先存储行。
Resizing
rows() , cols() , size() 方法分别返回行数,列数和 元素的个数。
Eigen支持对动态大小的矩阵和向量重新指定大小,通过resize() 实现。
#include <iostream>
#include <Eigen/Dense>
using namespace Eigen;
int main()
{
MatrixXd m(2,5);
m.resize(4,3);
std::cout << "The matrix m is of size "
<< m.rows() << "x" << m.cols() << std::endl;
std::cout << "It has " << m.size() << " coefficients" << std::endl;
VectorXd v(2);
v.resize(5);
std::cout << "The vector v is of size " << v.size() << std::endl;
std::cout << "As a matrix, v is of size "
<< v.rows() << "x" << v.cols() << std::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
如果matrix的实际大小不改变,resize函数不做任何操作;否则resize操作是具有破坏性的,矩阵中元素的值会被改变,如果不想改变元素的值可以执行 conservativeResize()。
为了统一API,所有的操作可用于固定大小的matrix,当然,实际中它不会改变大小。尝试去改变一个固定大小的matrix到一个不同的值,会出发警告失败。只有如下是合法的。
#include <iostream>
#include <Eigen/Dense>
using namespace Eigen;
int main()
{
Matrix4d m;
m.resize(4,4); // no operation
std::cout << "The matrix m is of size "
<< m.rows() << "x" << m.cols() << std::endl;
}
Assignment and resizing
assignment(分配)是复制一个矩阵到另外一个,通过操作符“=”实现。Eigen会自动resize左变量的大小以等于右侧变量的大小。
当然,如果左边变量是固定大小的,resizing是不允许的。
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
固定尺寸VS动态尺寸
实际中,应该使用固定尺寸还是动态尺寸,简单的答案是:对于小尺寸的矩阵,使用固定大小的方式,对于大尺寸的矩阵,使用动态大小的方式。
Matrix4f mymatrix;
等价于 float mymatrix[16]
;
MatrixXf mymatrix(rows,columns);
等价于float *mymatrix = new float[rows*columns];
使用固定尺寸可以避免动态内存的开辟,固定尺寸只是一个普通数组。
使用固定尺寸(<=4*4)需要编译前知道矩阵大小,而且对于足够大的尺寸,如大于32,固定尺寸的收益可以忽略不计,相反,很可能会导致栈崩溃,因为Eigen尝试将数组自动分配为局部变量,这通常在堆栈上完成。而且基于环境,Eigen会对动态尺寸做优化(类似于std::vector)。
Matrix类的其他模板参数
如下石Matrix类的完整参数列表:
Matrix<typename Scalar,
int RowsAtCompileTime,
int ColsAtCompileTime,
int Options = 0,
int MaxRowsAtCompileTime = RowsAtCompileTime,
int MaxColsAtCompileTime = ColsAtCompileTime>
- Options是一个比特标志位,这里,我们只介绍一种标志位:RowMajor,它表明matrix使用按行存储(row-major),默认情况下是按列存储(column-major)。
Matrix<float, 3, 3, RowMajor>
表示一个按行存储的3*3矩阵。 - MaxRowsAtCompileTime和MaxColsAtCompileTime表示在编译阶段矩阵的上限。主要是避免动态内存分配,使用数组。
一些方便的类型定义
Eigen定义了一些Matrix的类型:
- MatrixNt for Matrix<type, N, N>.
- VectorNt for Matrix<type, N, 1>.
- RowVectorNt for Matrix<type, 1, N>.
其中,N可以是2,3,4或X(Dynamic);
t可以是i(int)、f(float)、d(double)、cf(complex)、cd(complex)等。
暂无评论内容