C++矩阵运算库Eigen介绍

C++中的矩阵运算库常用的有Armadillo,Eigen,OpenCV,ViennaCL,PETSc等。我自己在网上搜了一下不同运算库的特点,最后选择了Eigen。主要原因是Eigen体积较小,不用安装也不用编译,库是以头文件的形式给出,直接将它扔到我们自己的工程文件中即可,移植起来也无压力。我们可以在Eigen官网下载源文件。

Eigen的HelloWorld

我这里使用的Eigen的版本为Eigen 3.3.3,源文件目录如下:

可以直接用记事本打开INSTALL文件,里面有编译和不编译时分别怎么使用。我这里使用的方法是不对文件进行编译。

  1. 找个地方新建一个工程目录,这里我在桌面上新建一个MatrixTest文件夹。
  2. 将Eigen目录中的Eigen文件夹拷贝到我们的MatrixTest目录中。
  3. 在MatrixTest中再建立一个main.cpp文件写入如下代码:
#include <iostream>
#include "Eigen\Core"//import most common Eigen types
using namespace Eigen;int main(int,char*[])
{Matrix3f m3;m3<<1,2,3,4,5,6,7,8,9;Matrix4f m4 = Matrix4f::Identity();Vector4i v4(1,2,3,4);std::cout<<"m3\n"<<m3<<"\nm4:\n"<<m4<<"\nv4:\n"<<v4<<std::endl;
}
  1. 在MatrixTest目录的地址栏中输入cmd,然后用g++ main.cpp对文件进行编译,再运行命令a。可以看到我们已经输出了我们的矩阵了。

Eigen常规矩阵定义

Eigen的使用在官网上有详细的介绍,这里对我学习过程中用到的基本操作进行介绍。首先是矩阵的定义。
在矩阵类的模板参数共有6个。一般情况下我们只需要关注前三个参数即可。前三个模板参数如下所示:

Matrix<typename Scalar,int RowsAtCompileTime,int ColsAtCompileTime>
  1. Scalar参数为矩阵元素的类型,该参数可以是int,float,double等。
  2. RowsAtCompileTime和ColsAtCompileTime是矩阵的行数和列数。

Matrix<float,4,4> M44是定义一个4×4的矩阵,矩阵元素以float类型存储。直接使用矩阵模板定义一个矩阵往往会觉得麻烦,Eigen提供了一些基本矩阵的别名定义,如typedef Matrix<float,4,4> Matrix4f.下面是一些内置的别名定义.来源于官方手册:

typedef Matrix< std::complex<double> , 2 , 2 > Matrix2cd
typedef Matrix< std::complex<float> , 2 , 2 > Matrix2cf
typedef Matrix< double , 2 , 2 > Matrix2d
typedef Matrix< float , 2 , 2 > Matrix2f
typedef Matrix< int , 2 , 2 > Matrix2i
typedef Matrix< std::complex<double> , 3 , 3 > Matrix3cd
typedef Matrix< std::complex<float> , 3 , 3 > Matrix3cf
typedef Matrix< double , 3 , 3 > Matrix3d
typedef Matrix< float , 3 , 3 > Matrix3f
typedef Matrix< int , 3 , 3 > Matrix3i
typedef Matrix< std::complex<double> , 4 , 4 > Matrix4cd
typedef Matrix< std::complex<float> , 4 , 4 > Matrix4cf
typedef Matrix< double , 4 , 4 > Matrix4d
typedef Matrix< float , 4 , 4 > Matrix4f
typedef Matrix< int , 4 , 4 > Matrix4i
typedef Matrix< std::complex<double> , Dynamic , Dynamic > MatrixXcd
typedef Matrix< std::complex<float> , Dynamic , Dynamic > MatrixXcf
typedef Matrix< double , Dynamic , Dynamic > MatrixXd
typedef Matrix< float , Dynamic , Dynamic > MatrixXf
typedef Matrix< int , Dynamic , Dynamic > MatrixXi
typedef Matrix< std::complex<double> , 1, 2 > RowVector2cd
typedef Matrix< std::complex<float> , 1, 2 > RowVector2cf
typedef Matrix< double , 1, 2 > RowVector2d
typedef Matrix< float , 1, 2 > RowVector2f
typedef Matrix< int , 1, 2 > RowVector2i
typedef Matrix< std::complex<double> , 1, 3 > RowVector3cd
typedef Matrix< std::complex<float> , 1, 3 > RowVector3cf
typedef Matrix< double , 1, 3 > RowVector3d
typedef Matrix< float , 1, 3 > RowVector3f
typedef Matrix< int , 1, 3 > RowVector3i
typedef Matrix< std::complex<double> , 1, 4 > RowVector4cd
typedef Matrix< std::complex<float> , 1, 4 > RowVector4cf
typedef Matrix< double , 1, 4 > RowVector4d
typedef Matrix< float , 1, 4 > RowVector4f
typedef Matrix< int , 1, 4 > RowVector4i
typedef Matrix< std::complex<double> , 1, Dynamic > RowVectorXcd
typedef Matrix< std::complex<float> , 1, Dynamic > RowVectorXcf
typedef Matrix< double , 1, Dynamic > RowVectorXd
typedef Matrix< float , 1, Dynamic > RowVectorXf
typedef Matrix< int , 1, Dynamic > RowVectorXi
typedef Matrix< std::complex<double> , 2 , 1> Vector2cd
typedef Matrix< std::complex<float> , 2 , 1> Vector2cf
typedef Matrix< double , 2 , 1> Vector2d
typedef Matrix< float , 2 , 1> Vector2f
typedef Matrix< int , 2 , 1> Vector2i
typedef Matrix< std::complex<double> , 3 , 1> Vector3cd
typedef Matrix< std::complex<float> , 3 , 1> Vector3cf
typedef Matrix< double , 3 , 1> Vector3d
typedef Matrix< float , 3 , 1> Vector3f
typedef Matrix< int , 3 , 1> Vector3i
typedef Matrix< std::complex<double> , 4 , 1> Vector4cd
typedef Matrix< std::complex<float> , 4 , 1> Vector4cf
typedef Matrix< double , 4 , 1> Vector4d
typedef Matrix< float , 4 , 1> Vector4f
typedef Matrix< int , 4 , 1> Vector4i
typedef Matrix< std::complex<double> , Dynamic , 1> VectorXcd
typedef Matrix< std::complex<float> , Dynamic , 1> VectorXcf
typedef Matrix< double , Dynamic , 1> VectorXd
typedef Matrix< float , Dynamic , 1> VectorXf
typedef Matrix< int , Dynamic , 1> VectorXi

2 向量

向量被作为一种特殊的矩阵进行处理,即要么行为一要么列为一。除非显式的说明为行向量,否则这里将向量默认为列向量。请看下面两个别名定义:

typedef Matrix<float,3,1> Vector3f;
typedef Matrix<int,1,2> RowVector2i;

3 矩阵的动态空间分配

很多时候在程序的编译阶段也许我们并不知道矩阵具体的行列数,这时候使用动态控件分配就显得很必要了。当我们给矩阵模板中参数RowsAtCompileTime或者ColsAtCompileTime参数指定为Dynamic时,表示该矩阵对应行或列为一个动态分配的值。下面是两个动态矩阵的别名定义:

typedef Matrix<double,Dynamic,Dynamic> MatrixXd;
typedef Matrix<int,Dynamic,1> VectorXi;

4 矩阵的构建

经过上面的介绍以后,我们应该能定义一些基本的矩阵了。如:

Matrix3f a;   //定义一个float类型3×3固定矩阵a
MatrixXf b;   //定义一个float类型动态矩阵b(0×0)
Matrix<int,Dynamic,3> b;  //定义一个int类型动态矩阵(0×3)

对应动态矩阵,我们也可以在构造的时候给出矩阵所占用的空间,比如:

MatrixXf a(10,15);  //定义float类型10×15动态矩阵
VectorXf b(30); //定义float类型30×1动态矩阵(列向量)

为了保持一致性,我们也可以使用上面构造函数的形式定义一个固定的矩阵,即Matrix3f a(3,3)也是允许的。

上面矩阵在构造的过程中并没有初始化,Eigen还为一些小的(列)向量提供了可以初始化的构造函数。如:

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 矩阵元素的访问

Eigen提供了矩阵元素的访问形式和matlab中矩阵的访问形式非常相似,最大的不同是matlab中元素从1开始,而Eigen的矩阵中元素是从0开始访问。对于矩阵,第一个参数为行索引,第二个参数为列索引。而对于向量只需要给出一个索引即可。

#include <iostream>
#include "Eigen\Core"//import most common Eigen types
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<<"Hear is the matrix m:\n"<<m<<std::endl;VectorXd v(2);v(0) = 4;v(1) = v(0) - 1;std::cout<<"Here is the vector v:\n"<<v<<std::endl;
}

输出结果如下:

Hear is the matrix m:3  -1
2.5 1.5
Here is the vector v:
4
3

m(index)这种访问形式并不仅限于向量之中,对于矩阵也可以这样访问。这一点和matlab相同,我们知道在matlab中定义一个矩阵a(3,4),如果我访问a(5)相当于访问a(2,2),这是因为在matlab中矩阵是按列存储的。这里比较灵活,默认矩阵元素也是按列存储的,但是我们也可以通过矩阵模板构造参数Options=RowMajor改变存储方式(这个参数是我们还没有提到的矩阵构造参数的第4个参数)。

6 一般初始化方法

对于矩阵的初始化,我们可以采用下面的方法方便且直观的进行:

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

7 矩阵的大小

Eigen提供了rows(),cols(),size()方法来获取矩阵的大小,同时也同了resize()方法从新改变动态数组的大小。

#include <iostream>
#include "Eigen\Core"using namespace Eigen;int main()
{MatrixXd m(2,5);m<<1,2,3,4,5,6,7,8,9,10;m.resize(4,3);std::cout<<"The matrix m is:\n"<<m<<std::endl;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<<1,2;v.resize(5);std::cout<<"The vector v is:\n"<<v<<std::endl;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:1            3            56            8           102            4 9.58787e-3157            9 1.17493e-309
The matrix m is of size 4x3
It has 12 coefficients
The vector v is:12
1.17477e-3097.0868e-3040
The vector v is of size 5
As a matrix,v is of size 5x1

可以看到我们可以把矩阵任意的resize,但是resize后矩阵的元素会改变,如果resize后的矩阵比之前的大会出现一些未初始化的元素。如果被resize的矩阵按列存储(默认),那么resize命令和matlab中的reshape执行结果相同,只是matlab要求reshape的矩阵前后元素必须相同,也就是不允许resize后不能出现未初始化的元素。
对于固定大小的矩阵虽然也支持resize命令,但是resize后的大小只能是它本身的大小,否则就会报错。因为resize前后如果矩阵大小一样,就不会执行resize。如果我们不想在resize后改变矩阵的对应元素,那么可以使用conservativeResize()方法。对应上面程序中的m矩阵我们调用m.conservativeResize(4,3)后得到结果如下。其中因为行数增加了,增加的行会以未初始化的形式出现。

The matrix m is:1            2            36            7            8
9.58787e-315   2.122e-314 1.52909e+2490            0 2.47039e+249

http://eigen.tuxfamily.org/dox/group__TutorialMatrixClass.html

8 赋值和大小变换

在Eigen中使用=可以直接将一个矩阵复制给另外一个矩阵,如果被复制的和赋值矩阵大小不一致,会自动对被复制矩阵执行resize函数。当然如果被复制的矩阵为固定矩阵当然就不会执行resize函数。当然也可以通过一些设置取消这个自动resize的过程。

using namespace Eigen;int main()
{MatrixXf a(2,2);MatrixXf b(3,3);b<<1,2,3,4,5,6,7,8,9;a = b;std::cout<<a<<std::endl;
}

输出结果:

1 2 3
4 5 6
7 8 9

9 固定矩阵和动态矩阵

什么时候使用固定矩阵什么时候使用动态矩阵呢?简单的说:当矩阵尺寸比较小时使用固定矩阵(一般小于16),当矩阵尺寸较大时使用动态矩阵(一般大于32)。使用固定矩阵有更好的表现,它可以避免重复的动态内存分配,固定矩阵实际上是一个array。即Matrix4f mymatrix;事实上是float mymatrix[16];。所以这个是真的不花费任何运行时间。相反动态矩阵的建立需要在
heap中分配空间。即MatrixXf mymatrix(rows,colums);实际上是float *mymatrix = new float[rows*colums];.此外动态矩阵还要保存行和列的值。
当然固定矩阵也存在着显而易见的弊端。当数组的大小过大时,固定数组的速度优势就不那么明显了,相反过大的固定数组有可能造成stack的溢出。这时候动态矩阵的灵活性就显得十分重要了。

10 其他模板参数

最开始我们已经提到了建立一个矩阵一共有6个模板参数,其中有3个我们还没有提到(其实第三个参数已经提到过了)。

Matrix<typename Scalar,int RowsAtCompileTime,int ColsAtCompileTime,int Options=0,int MaxRowsAtCompileTime = RowsAtCompileTime,int MaxColsAtCompileTime = ColsAtCompileTime>
  1. Options:这个参数决定了矩阵在存储过程中实际是按行还是按列存储。这个存储方式在前面我们提到的矩阵变换时必须要注意。默认是按列存储,我们可以显示的使用Options=RowMajor让矩阵实际按行存储。如Matrix<float,2,3,RowMajor> a;.
  2. MaxRowsAtCompileTime和MaxColsAtCompileTime:这两个值是设定动态矩阵在分配空间时最大的行数和列数。如Matrix<float,Dynamic,Dynamic,0,3,4>;.

11 常规的矩阵typedef

我们前面给出了一些常用的矩阵typedef.其实可以总结如下:

  1. MatrixNt对应的是Matrix<type,N,N>.比如MatrixXi对应的是Matrix<int,Dynamic,Dynamic>.
  2. VectorNt对应的是Matrix<type,N,1>.比如Vector2f对应的是Matrix<float,2,1>.
  3. RowVectorNt对应的是Matrix<type,1,N>.比如RowVector3d对应的是Matrix<double,1,3>.

其中:

  1. N可以是2,3,4或者X(表示Dynamic).
  2. t可以是i(int),f(float),d(double),cf(complex),cd(complex).只定义了这些类型的typedef并不表示只支持这些数据类型的运算。比如所有的整形类型的运算都支持(长的,短的,有符号的,无符号的)。

转载于:https://www.cnblogs.com/yabin/p/6435901.html

c++矩阵运算库Eigen简介相关推荐

  1. Eigen矩阵运算库快速上手

    目录 1. 配置 2. 初始化 2.1 Array类 2.2 Vector类 2.3 Matrix类 2.4 Vector赋值 2.5 高级初始化 3. 矩阵计算 3.1 矩阵基本计算 3.2 线性求 ...

  2. Eigen 矩阵运算库在实际项目中的使用

    Eigen 矩阵运算库在实际项目中的使用情况如何? 心血来潮,试了试纯模板技术写的 Eigen 并作了简单的性能测试,三个 1000 阶的方阵连乘运算 Eigen 比 MATLAB 快了一倍,比 Op ...

  3. 三阶矩阵的lu分解详细步骤_快速入门矩阵运算——开源库Eigen

    矩阵是数学中一个重要的工具,广泛应用于各种场景下的数值分析,例如,数字信号处理,图像处理等.我们如何在程序中使用矩阵进行运算呢?本文将为大家介绍一个开源的矩阵运算工具--Eigen. Eigen is ...

  4. eigen 列向量转矩阵_快速入门矩阵运算——开源库Eigen

    矩阵是数学中一个重要的工具,广泛应用于各种场景下的数值分析,例如,数字信号处理,图像处理等.我们如何在程序中使用矩阵进行运算呢?本文将为大家介绍一个开源的矩阵运算工具--Eigen. Eigen is ...

  5. C++矩阵运算库推荐

    Armadillo:C++下的Matlab替代品 Eigen3:强大且只需头文件 OpenCV:方便的计算机视觉计算库 ViennaCL:并行矩阵计算 PETSc:大规模并行科学计算 其他的矩阵计算库 ...

  6. apache madlib 教程_Apache顶级开源项目——机器学习库MADlib简介与应用实例

    原标题:Apache顶级开源项目--机器学习库MADlib简介与应用实例 Apache MADlib是Pivotal与UCBerkeley合作的一个开源机器学习库,提供了精确的数据并行实现.统计和机器 ...

  7. C语言矩阵运算库大起底

    GSL GNU Scientific Library自带的矩阵运算,据说速度一般. Blitz++ Blitz++ 与 MTL 都是基于 C++ template 高效数值计算程序库,不过他们专注于不 ...

  8. 超好用的纯C语言矩阵运算库

    超好用的纯C语言矩阵运算库 easyMatrix 最近开发基于异构传感器的异步定位数据的卡尔曼滤波,因为最终要用在一个老爷DSP上,已有代码都是C写的,不想研究这种老爷设备下的C++调用,Eigen这 ...

  9. Cuda矩阵运算库cuBLAS介绍

    文章目录 简介 cuBLAS库新特性 cuBLAS代码热身 cublasSetMatrix() cudaMalloc() cublasSscal() 源代码 cuBLAS 辅助函数 上下文管理 复制矩 ...

最新文章

  1. python的下载和安装步骤-下载及安装Python详细步骤
  2. tomcat 不支持put 高版本_「MG6_DCT280」湿式七档双离合版本-性价比并不高
  3. 应用市场中包名(package name)的唯一性
  4. aptitude 命令_C-命令行参数Aptitude问题与解答
  5. java selenium ie_Selenium webdriver Java 操作IE浏览器
  6. Go:Unresolved dependency
  7. EGE绘图之四 Gif动图播放
  8. 通过VBA在excel中实现多只股票基金实时交易数据查询(完整的excel原件可以在我的资源中下载)
  9. 数值分析Guass分解——错误讨论
  10. 收藏!常用的档案馆(室)检索工具及编制方法
  11. HTML5+CSS3笔记 (黑马pink老师)
  12. ionic学习(十一):页面下拉刷新(Refresher)
  13. Caffeine使用篇 - Cleanup
  14. html拖拽手势,h5实现手势操作放大缩小拖动等
  15. jQuery实现点击文本框弹出热门标签的提示示例
  16. 【C语言程序设计】实验 10
  17. 一个生成密保卡的程序
  18. es6 javascript的字符串对象新增团员方法
  19. 预算内资金 budgetary funds
  20. JS escape()和unescape()函数的介绍

热门文章

  1. RH Linux 企业5+apache+mysql+php+phpmyadmin的简单配置.
  2. [译].NET 4 中玩耍内存映射文件
  3. Elixir 1.7改进错误处理、日志和测试
  4. 未来已来?揭开量子计算机的神秘面纱
  5. 【LeetCode题解】二叉树的遍历
  6. SQL SERVER 自定义函数参数数量对调用时参数数量的影响
  7. 一个好的公司网站应怎么样去推广
  8. 非对称加密算法--RSA加密原理及运用
  9. Ubuntu安装teamviewer
  10. windows用户态程序的Dump