博客
关于我
Eigen库入门:数组与块
阅读量:270 次
发布时间:2019-03-01

本文共 8198 字,大约阅读时间需要 27 分钟。

前言

在上一篇博文中,博主记录了如何使用Eigen进行矩阵、向量的基础运算。本篇博文将在此基础上进一步记录数组类型和块操作。

一、数组类型

与用于线性代数Matrix类不同,Array类提供了一种通用数组。此类数组不具备线性代数的含义但提供了部分更为便捷的运算方式。

1.定义Array数组

同定义Matrix类一样,Array类提供了一个六个参数的类模板,其中前三个参数是必须填写的。

//    数据类型           行数                         列数Array

例如,定义一个3行1列的float类型的Array数组。

Array
array_31f

同Matrix一样,Array类也存在大量好用的TypeDef用于快速定义数组。

不同的是在Matrix模板类中,一维的矩阵称为列向量(Vector)行向量(RowVector),二维的矩阵则被定义为矩阵(Matrix)。而在Array中则不存在此类规定,故而采用如下方式进行定义:

Type Typedef
Array<float,Dynamic,1> ArrayXf
Array<float,3,1> Array3f
Array<float,Dynamic,Dynamic> ArrayXXf
Array<float,2,3> Array23f

2.输入输出数组元素

同Matrix类相同,不展开说明。

#include 
#include
using namespace Eigen;using namespace std; int main(){ // 定义数组 ArrayXXf m(2,2); // 逐个赋予元素 m(0,0) = 1.0; m(0,1) = 2.0; m(1,0) = 3.0; m(1,1) = m(0,1) + m(1,0); // 输出数组元素 cout << m << endl ; // 输入数组 m << 1.0,2.0, 3.0,4.0; // 输出 cout << m << endl;}

3.数组的四则运算

和Matrix不同,数组的加法支持将标量添加到数组中的每个元素。如若将矩阵与标量相加则会产生报错。

#include 
#include
using namespace Eigen;using namespace std; int main(){ ArrayXXf a(3,3); ArrayXXf b(3,3); a << 1,2,3, 4,5,6, 7,8,9; b << 1,2,3, 1,2,3, 1,2,3; // 数组间相加减 cout << "a + b = \n" << endl << a + b << endl << endl; /*输出如下: * a + b = * 2 4 6 * 5 7 9 * 8 10 12 */ // 数组与标量间相加减 cout << "a - 2 = \n" << endl << a - 2 << endl; /*输出如下: * a - 2 = * -1 0 1 * 2 3 4 * 5 6 7 */}

在Matrix中,乘法被定义为矩阵间乘法;而在数组中则将乘法定义为对应元素(索引相同)相乘。在数组中两个相乘的数组必须满足**大小(size)**相同。

#include 
#include
using namespace Eigen;using namespace std; int main(){ ArrayXXf a(2,2); ArrayXXf b(2,2); a << 1,2, 3,4; b << 5,6, 7,8; cout << "a * b = " << endl << a * b << endl; /*输出如下: * a * b = * 5 12 * 21 32 */}

4.数组的运算API

在数组中支持大量的数学运算API,在使用时只需调用规定的API即可实现所需功能。

// API							数学含义array1.abs2()				  abs(array1)^2array1.abs()                  abs(array1)array1.sqrt()                 sqrt(array1)array1.log()                  log(array1)array1.log10()                log10(array1)array1.exp()                  exp(array1)array1.pow(array2)            pow(array1,array2)array1.pow(scalar)            pow(array1,scalar)                              pow(scalar,array2)array1.square()array1.cube()array1.inverse() array1.sin()                  sin(array1)array1.cos()                  cos(array1)array1.tan()                  tan(array1)array1.asin()                 asin(array1)array1.acos()                 acos(array1)array1.atan()                 atan(array1)array1.sinh()                 sinh(array1)array1.cosh()                 cosh(array1)array1.tanh()                 tanh(array1)array1.arg()                  arg(array1) array1.floor()                floor(array1)array1.ceil()                 ceil(array1)array1.round()                round(aray1) array1.isFinite()             isfinite(array1)array1.isInf()                isinf(array1)array1.isNaN()                isnan(array1)

5.数组与矩阵的转换

在Eigen中,当需要进行线性代数运算应使用矩阵;当需要进行元素运算应使用数组。如需要同时使用Matrix和Array操作,需要将数组与矩阵进行相互转换。这样,无论选择将对象声明为数组还是矩阵,都可以访问所有操作。

对于Matrix类型数据,使用其 .array()方法 可转换为Array类型数据,同样对于 Array类型数据具有 .matrix()方法.array()和.matrix()可被用作右值或左值。

Eigen禁止在表达式中混用矩阵和数组。例如,不能直接将矩阵和数组进行相加,必须将其转换为同一类型后再进行计算。但同时,Eigen库允许将Matrix数据类型赋值给Array或相反。

#include 
#include
using namespace Eigen;using namespace std; int main(){ MatrixXf m(2,2); MatrixXf n(2,2); MatrixXf result(2,2); m << 1,2, 3,4; n << 5,6, 7,8; // 矩阵乘法 result = m * n; cout << "-- Matrix m*n: --" << endl << result << endl << endl; /* * 输出结果如下: * -- Matrix m*n: -- * 19 22 * 43 50 */ // 数组乘法 result = m.array() * n.array(); cout << "-- Array m*n: --" << endl << result << endl << endl; /* * 输出结果如下: * --- Array m*n: -- * 5 12 * 21 32 */ // cwiseProduct方法实现数组乘法 result = m.cwiseProduct(n); cout << "-- With cwiseProduct: --" << endl << result << endl << endl; /* * 输出结果如下: * --- With cwiseProduct: -- * 5 12 * 21 32 */ // 数组加法 result = m.array() + 4; cout << "-- Array m + 4: --" << endl << result << endl << endl; /* * 输出结果如下: * -- Array m + 4: -- * 5 6 * 7 8 */ // 复合运算1 result = (m.array() + 4).matrix() * m; cout << "-- Combination 1: --" << endl << result << endl << endl; /* * 输出结果如下: * -- Combination 1: -- * 23 34 * 31 46 */ // 复合运算2 result = (m.array() * n.array()).matrix() * m; cout << "-- Combination 2: --" << endl << result << endl << endl; /* * 输出结果如下: * -- Combination 2: -- * 41 58 * 117 170 */}

二、块操作

块是矩阵或阵列的矩形部分。块表达式既可以用作右值,也可以用作左值。

1.定义块

构造一个块需要使用 .block()方法 ,其用法如下:

// 固定大小的块matrix.block
(i,j)// 动态大小的块matrix.block(i,j,p,q)

其中参数具体含义如下:

  • 块大小(行):p
  • 块大小(列):q
  • 起始索引位置(行):i
  • 起始索引位置(列):j

即从原有矩阵的第i行第j列的元素开始起,构建一个p行q列的块。需要注意,在Eigen库中,索引从0开始。

#include 
#include
using namespace std; int main(){ // 定义一个4*4的矩阵 Eigen::MatrixXf m(4,4); m << 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12, 13,14,15,16; //新建一个块 cout << "Block in the middle" << endl; cout << m.block<2,2>(1,1) << endl << endl; /* * 输出结果如下: * Block in the middle * 6 7 * 10 11 */ for (int i = 1; i <= 3; ++i) { cout << "Block of size " << i << "x" << i << endl; cout << m.block(0,0,i,i) << endl << endl; } /* * 输出结果如下: * Block of size 1x1 * 1 * Block of size 2x2 * 1 2 * 5 6 * Block of size 3x3 * 1 2 3 * 5 6 7 * 9 10 11 */}

同样,块操作可以运用在Array类型上:

#include 
#include
using namespace std;using namespace Eigen; int main(){ // 定义一个数组 Array22f m; m << 1,2, 3,4; // 定义一个数组并初始化其值为0.6 Array44f a = Array44f::Constant(0.6); cout << "Here is the array a:" << endl << a << endl << endl; /* * 输出结果如下: * Here is the array a: * 0.6 0.6 0.6 0.6 * 0.6 0.6 0.6 0.6 * 0.6 0.6 0.6 0.6 * 0.6 0.6 0.6 0.6 */ // 将a中指定块的内容重新赋值 a.block<2,2>(1,1) = m; cout << "Here is now a with m copied into its central 2x2 block:" << endl << a << endl << endl; /* * 输出结果如下: * Here is now a with m copied into its central 2x2 block: * 0.6 0.6 0.6 0.6 * 0.6 1 2 0.6 * 0.6 3 4 0.6 * 0.6 0.6 0.6 0.6 */ // 将a中指定块的内容赋值为另一块的内容 a.block(0,0,2,3) = a.block(2,1,2,3); cout << "Here is now a with bottom-right 2x3 block copied into top-left 2x3 block:" << endl << a << endl << endl; /* * 输出结果如下: * Here is now a with bottom-right 2x3 block copied into top-left 2x3 block: * 3 4 0.6 0.6 * 0.6 0.6 0.6 0.6 * 0.6 3 4 0.6 * 0.6 0.6 0.6 0.6 */ }

2.单行与单列

虽然使用块进行操作已经十分方便,但是为了获取到更好的性能,对于特殊的情况最好使用特定的API进行操作。例如在获取一个矩阵或数组的单列或单行时,可以使用方法 .col().row()

#include 
#include
using namespace std; int main(){ Eigen::MatrixXf m(3,3); m << 1,2,3, 4,5,6, 7,8,9; // 输出矩阵 cout << "Here is the matrix m:" << endl << m << endl; /* * 输出结果如下: * Here is the matrix m: * 1 2 3 * 4 5 6 * 7 8 9 */ // 获取第二行 cout << "2nd Row: " << m.row(1) << endl; /* * 输出结果如下: * 2nd Row: 4 5 6 */ // 第三行修改为第一行的三倍 m.col(2) += 3 * m.col(0); cout << "After adding 3 times the first column into the third column, the matrix m is:\n"; cout << m << endl; /* * 输出结果如下: * After adding 3 times the first column into the third column, the matrix m is: * 1 2 6 * 4 5 18 * 7 8 30 */}

3.向量的块操作

在Eigen中针对向量和一维数组设计了一些便捷的API用于块操作。

#include 
#include
using namespace std; int main(){ Eigen::ArrayXf v(6); v << 1, 2, 3, 4, 5, 6; //输出向量的前三个元素 cout << v.head(3) << endl; /* * 输出结果如下: * 1 * 2 * 3 */ // 输出向量的后三个元素 cout << v.tail(3) << endl ; /* * 输出结果如下: * 4 * 5 * 6 */ v.segment(1,4) *= 2; // 将向量从第二元素起后四个(包含第二元素)扩大至两倍 cout << "after 'v.segment(1,4) *= 2', v = \n" << v << endl; /* * 输出结果如下: * 1 * 4 * 6 * 8 * 10 * 6 */}

转载地址:http://opnv.baihongyu.com/

你可能感兴趣的文章
MyPython
查看>>
MTD技术介绍
查看>>
MySQL
查看>>
MySQL
查看>>
mysql
查看>>
MTK Android 如何获取系统权限
查看>>
MySQL - 4种基本索引、聚簇索引和非聚索引、索引失效情况、SQL 优化
查看>>
MySQL - ERROR 1406
查看>>
mysql - 视图
查看>>
MySQL - 解读MySQL事务与锁机制
查看>>
MTTR、MTBF、MTTF的大白话理解
查看>>
mt_rand
查看>>
mysql -存储过程
查看>>
mysql /*! 50100 ... */ 条件编译
查看>>
mysql 1045解决方法
查看>>
mudbox卸载/完美解决安装失败/如何彻底卸载清除干净mudbox各种残留注册表和文件的方法...
查看>>
mysql 1264_关于mysql 出现 1264 Out of range value for column 错误的解决办法
查看>>
mysql 1593_Linux高可用(HA)之MySQL主从复制中出现1593错误码的低级错误
查看>>
mysql 5.6 修改端口_mysql5.6.24怎么修改端口号
查看>>
mui折叠面板点击事件跳转
查看>>