原文: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)等。