简介

本文介绍一下Dense Matrix如何与c/C++的数组进行交互操作,这在引入其他的库中的vector向量和矩阵到Eigen中时要使用到的技术。

有时,你有一些定义好的数据,可能是数组,你需要在Eigen内使用它。一个可选的方法是你拷贝一份数据,在添加到Eigen中,这样会有些工程的问题,数据的一致性等问题。幸运的是,Eigen内为此提供了Map类,提供了便利的使用方法。

Map在Eigen的四元数quarternion、排列permutation等都有应用。

Map类型及变量

在Eigen内,Map对象的模板类型定义如下:

Map<Matrix<typename Scalar, int RowsAtCompileTime, int ColsAtCompileTime> >

构造器

首先,需要了解的一点是: Map没有缺省的构造器。这里使用示例来介绍Map的变量定义/构造方法。

要构造一个Map变量,需要提供另外的2个其他的信息给Eigen: 想要得到的具体的矩阵或者向量、一个指向存储了系数的数组的地址指针。比如,要定义一个编译时即知道尺寸大小的浮点矩阵,其中pf是一个指向浮点类型数组的指针。可以这样做:

Map<MatrixXf> mf(pf,rows,columns);

一个固定尺寸大小的只读整形向量的Map类型,可以通过一个int * p指针,通过构造器,这样定义:
Map<const Vector4i> mi(pi);
在这里,看起来没有传递给构造器尺寸大小,这是因为已经在模板参数Vector4i中隐含指定了。

类Map提供了足够的灵活性,以满足多种数据形式。这里提供了有2个模板参数的定义:

Map<typename MatrixType,int MapOptions,typename StrideType>

这里简单介绍一下:

  • MapOptions: 指定指针是否对齐(Aligned),或者不对齐(Unaligned);缺省值为不对齐(Unaligned)。
  • StrideType: 让使用者指定内存中数组的布局,类型为class Stride。下面的例子指定其数据数组使用行优先(row-major)格式。

示例:

//matrix_map1.cpp
#include <iostream>
#include <Eigen/Dense>using namespace std;
using namespace Eigen;int main()
{int array[9];for(int i = 0; i < 9; ++i) array[i] = i;Map<VectorXi>  vi(array,9);Map<const Vector4i> fixed_v(array);    // unknown type name 'Vector5i' -- 这种模式size不能大于4cout<< "vector vi: "<< endl << vi << endl<< endl;cout<< "fixed-vector : "<< endl << fixed_v << endl<< endl;cout << "Column-major:\n" << Map<Matrix<int,2,4> >(array) << endl;cout << "Row-major:\n" << Map<Matrix<int,2,4,RowMajor> >(array) << endl;cout << "Row-major using stride:\n" <<Map<Matrix<int,2,4>, Unaligned, Stride<1,4> >(array) << endl;
}

执行结果:

$ g++   -I /usr/local/include/eigen3 matrix_map1.cpp -o matrix_map1
$ ./matrix_map1
vector vi:
0
1
2
3
4
5
6
7
8fixed-vector :
0
1
2
3Column-major:
0 2 4 6
1 3 5 7
Row-major:
0 1 2 3
4 5 6 7
Row-major using stride:
0 1 2 3
4 5 6 7

从结果可以看到,Map()进行映射时,缺省时列有先column-major,或者安装Eigen中的设定执行。

其实, Stride提供了更大的灵活性,具体信息可以查询Map和Stride的说明文档。

使用Map变量

对Map变量的使用,就和其映射的类型一致。比如Map到一个矩阵,则和使用矩阵对象一样。如果是向量,则按照向量的类型进行访问。

直接看Eigen中的示例。

//matrix_map2.cpp
#include <iostream>
#include <Eigen/Dense>using namespace std;
using namespace Eigen;typedef Matrix<float,1,Dynamic> MatrixType;
typedef Map<MatrixType> MapType;
typedef Map<const MatrixType> MapTypeConst;   // a read-only map
const int n_dims = 5;int main()
{MatrixType m1(n_dims), m2(n_dims);m1.setRandom();m2.setRandom();float *p = &m2(0);  // get the address storing the data for m2MapType m2map(p,m2.size());   // m2map shares data with m2MapTypeConst m2mapconst(p,m2.size());  // a read-only accessor for m2cout << "m1: " << m1 << endl;cout << "m2: " << m2 << endl;cout << "Squared euclidean distance: " << (m1-m2).squaredNorm() << endl;cout << "Squared euclidean distance, using map: " << (m1-m2map).squaredNorm() << endl;m2map(3) = 7;   // this will change m2, since they share the same arraycout << "Updated m2: " << m2 << endl;cout << "m2 coefficient 2, constant accessor: " << m2mapconst(2) << endl;//m2mapconst(2) = 5;    // compile-time error: expression is not assignablecout << endl;}

执行结果:

$ g++   -I /usr/local/include/eigen3 matrix_map2.cpp -o matrix_map2
$
$ ./matrix_map2
m1:  -0.999984  -0.736924   0.511211 -0.0826997  0.0655345
m2: -0.562082 -0.905911  0.357729  0.358593  0.869386
Squared euclidean distance: 1.08479
Squared euclidean distance, using map: 1.08479
Updated m2: -0.562082 -0.905911  0.357729         7  0.869386
m2 coefficient 2, constant accessor: 0.357729

可以看到,对系数的访问,使用括号运算符(int index),矩阵的一些计算保持不变。
但这里有一个限制:你自己定义的函数,使用Eigen的类型时,如果使用了Map,这和其对应的密集矩阵类Matrix可不一致了,因为它们是不同的类型Class。

使用placement new修改映射的数组

Map映射后得到的Matrix或者vector对象,也可以被修改。但这需要使用C++的placement new语法。

这里先对C++的Placemet new做一下说明,这涉及到3种不同的new: new、operator new、placement new

placement new是在用户指定的内存位置上构建新的对象,那么这样构建时,就不需要再额外分配内存空间,只需要调用对象的构造函数。就是这样!因为内存和数据都已经在那里了。其语法如此这样:new(&p) constructor(......)

下面看Eigen内的一下Map相关的示例:

//matrix_map3.cpp
#include <iostream>
#include <Eigen/Dense>using namespace std;
using namespace Eigen;int main()
{int data[] = {1,2,3,4,5,6,7,8,9};Map<RowVectorXi> ov(data,9);cout << "Origin data: " << ov << endl; Map<RowVectorXi> v(data,4);cout << "The mapped vector v is: " << v << "\n";// placement new new (&v) Map<RowVectorXi>(data+4,5);cout << "Changed, Now v is: " << v << "\n";cout << "Again origin data: " << ov << endl;
}

执行结果:

$ g++   -I /usr/local/include/eigen3 matrix_map3.cpp -o matrix_map3
promote:eigen david$ ./matrix_map3
Origin data: 1 2 3 4 5 6 7 8 9
The mapped vector v is: 1 2 3 4
Changed, Now v is: 5 6 7 8 9
Again origin data: 1 2 3 4 5 6 7 8 9

使用这种placement new语法,可以声明一个Map对象,而不用先分配内存,也无需知道具体真实的数据。
比如:

//matrix_map4.cpp
#include <iostream>
#include <Eigen/Dense>using namespace std;
using namespace Eigen;int n_matrices = 3;
int data[] = {1,2,3,4,5,6,7,8,9};int* get_matrix_pointer(int i)
{return data+3*i;
}int main()
{Map<Matrix3i> A(NULL);  // // 此时对数据一无所知VectorXi b(n_matrices);for (int i = 0; i < n_matrices; i++){int * pp = get_matrix_pointer(i);cout << "point : " << pp << " : data " << *pp << endl;//new (&A) Map<Matrix3i>( pp );cout<< "Matrix A: "<< endl<<A<<endl;b(i) = A.trace();}cout<< "vector b : "<< endl<<b<<endl;
}

执行结果:

$ g++   -I /usr/local/include/eigen3 matrix_map4.cpp -o matrix_map4
$ ./matrix_map4
point : 0x106cb7880 : data 1
Matrix A:
1 4 7
2 5 8
3 6 9
point : 0x106cb788c : data 4
Matrix A:
4 7 0
5 8 0
6 9 0
point : 0x106cb7898 : data 7
Matrix A:
7 0 0
8 0 0
9 0 0
vector b :
15
127

Eigen入门之密集矩阵 7 - Map class:连接Eigen与C++的数据相关推荐

  1. Eigen入门之密集矩阵 9 - 别名混乱Aliasing

    简介 别名混乱Aliasing是指在赋值表达式中,一个Eigen对象(矩阵.数组.向量)同时出现在左值和右值表达式中,比如v = v*2; m = m.transpose();; 别名混乱会引起错误, ...

  2. Eigen入门之密集矩阵 6 - Reductions, visitors and broadcasting

    简介 本文介绍一下Dense Matrix的3中操作: reduction, visitor, broadcasting. 归约计算reduction. Eigen的归约计算是这样的一类计算,它是对矩 ...

  3. Eigen入门之密集矩阵 5 - 再谈Matrix初始化

    简介 这里将讨论一下高级些的矩阵初始化方法. comma-initializer 逗号初始化器 comma-initializer方法很简单,可以一下把矩阵/向量的系数全部设置完.语法很简单,使用逗号 ...

  4. Eigen入门之密集矩阵 4 - 块操作

    简介 Eigen 中Matrix/Array提供了.block()来进行block区块操作,这是面向系数提供的操作功能. 语法 Eigen中提供了2种语法,针对产生的结果是一致的.但存在性能上的不同, ...

  5. Eigen入门之密集矩阵 8 - resharp slicing切片

    简介 Eigen还没有提供resharp或者slicing的处理函数,但是,可以使用Map 类来实现这些功能. 实现resharp 操作Resharp及修改Matrix的维度大小,而其系数保持不变.R ...

  6. Eigen入门之密集矩阵 10 - 矩阵的行优先及列优先存储

    简介 本篇介绍Eigen中矩阵及二维数组的系数存储顺序–行优先及列优先,已经如何指定优先顺序. 行优先(row-majoe). 列优先(column-majoe) 矩阵的系数条目组成了一个二维的结构, ...

  7. Eigen入门之密集矩阵 3 - Array操作

    简介 在Eigen内,有Matrix,vector进行线性代数的相关运算,但也需要执行对矩阵内的系数的相关操作时,这是正常的功能需求.Eigen中的Array类就是满足此需求的. Array 定义 和 ...

  8. Eigen入门之密集矩阵 2-- Matrix及Vector的计算方法

    简介 Eigen内的Matrix和Vector提供了类似C++的运算符,如+,-,*:也提供了编程的函数方法,如点乘和叉乘的dot(), cross(),如此等等. 在Eigen的Matrix类,代表 ...

  9. Eigen入门之密集矩阵 1 -- 类Matrix介绍

    简介 本篇介绍Eigen中的Matrix类.在Eigen中,矩阵和向量的类型都用Matrix来表示.向量是一种特殊的矩阵,其只有一行或者一列. Matrix构造 在Matrix.h中,定义了Matri ...

最新文章

  1. Python错误:AttributeError: 'generator' object has no attribute 'next'解决办法
  2. shell中执行脚本并显示到终端和保存到日志文件中
  3. android switcher控件,Android ViewSwitcher 的功能与用法
  4. 7-27 冒泡法排序 (C语言)
  5. 管理邮件用户(附图)---Michaelf
  6. 啊~ 五环 你比四环多一环 啊~ 五环 你比六环少一环
  7. affine工程难点、亮点汇总
  8. yum nginx最新版安装
  9. VS错误之error LNK2019: 无法解析的外部符号
  10. expect免互交 常用编辑文本
  11. php mysql 读取数据_PHP MySQL 读取数据
  12. Android开发中如何调用摄像头的功能
  13. 创建Vue实例对象基础语法模板
  14. 【股票】股票是什么?什么情况下股票会涨?
  15. 计算机专业学生该如何提高自己?提升自己的专业技能?
  16. torch.Tensor
  17. 给我一篇假论文,我能骗倒半个地球
  18. 我的世界服务器修改spawn,《我的世界》1.8命令方块原版/spawn指令教程
  19. 【asp.net core 系列】5 布局页和静态资源
  20. 关于触摸屏的一些硬件知识

热门文章

  1. Javascript设计模式
  2. 彻底理解链接器:二,符号决议
  3. 手把手教你撸一个简易的 webpack
  4. Eclipse中10个最有用的快捷键组合(转)
  5. DotNet4应用程序打包工具(把DotNet4安装程序打包进你的应用程序;WINAPI开发,无dotNet环境也可顺利执行)【一】整体思路...
  6. iptables详解以及企业常用案例
  7. Shell 命令大全Xhell入门
  8. 基于MUI框架的HTML5+的二维码扫描实现
  9. python12个基本语法_12-25python基本语法
  10. stm32怎么调用for循环内部的变量_循环中的异步amp;amp;循环中的闭包