Eigen教程(1)

本文介绍了Eigen库中的Matrix类,包括其基本模板参数(Scalar类型、编译时行列数)、向量特性和分类(如Vector3f和RowVector2i)、动态范围的使用、构造函数、系数访问与初始化,以及矩阵大小调整、赋值和大小选择原则。
摘要由CSDN通过智能技术生成

Eigen学习(1)

The Matrix class(Matrix的类)

在 Eigen 中,所有矩阵,向量都是 Matrix 模板类的对象。向量只是矩阵的一种特殊情况:1 行或1 列。

Matrix的前三个模板参数

Matrix 类在定义时采用六个模板参数,但在实际的使用中前三个参数就完全满足。其余后三个参数为默认值。

Matrix 的三个必需参数是:
Matrix<typename Scalar, int RowsAtCompileTime, int ColsAtCompileTime>

  1. Sclaar:为标量类型,也系数的类型。也就是说,支持 float ,double,std::complex
    std::complex ,long double 以及所有整数类型(例如 int,unsigned int,short 等),和
    bool 。在 x86-64 系统上,ong double permit to local 强制使用具有扩展精度的 x87 寄存器。
  2. RowsAtCompileTime 和 ColsAtCompileTime :RowsAtCompileTime 和 ColsAtCompileTime 是编译时已知的Matrix的行数和列数。
    Eigen提供很多方便的typedefs来涵盖常用的情况。Matrix4f 是一个 4x4 浮点数矩阵:
    eg:typedef Matrix<float, 4, 4> Matrix4f;
    Matrix4f a;

Vectors(向量)

在 Eigen 中,向量只是矩阵的一种特殊情况,具有 1 行或 1 列。有1列的情况的向量称为列向量,有 1 行,称为行向量。
例如,定义 Vector3f 是 3 个浮点数的(列)向量。在 Eigen 定义:
typedef Matrix<float, 3, 1> Vector3f;
行向量:
typedef Matrix<int, 1, 2> RowVector2i;

The special value Dynamic(动态值)

Eigen 不仅限于在编译时已知的矩阵。,RowsAtCompileTime 和 ColsAtCompileTime 参数可以采用动态值,在编译时值得大小是未知的,必须作为运行时变量处理。 在 Eigen中,这样的范围称为动态范围; 而在编译时已知的范围称为固定范围。 例如, MatrixXd 表示具有动态范围的双精度矩阵,定义:
typedef Matrix<double, Dynamic, Dynamic> MatrixXd;

同样,定义一个VectorXi 如下:
typedef Matrix<int, Dynamic, 1> VectorXi;

具有动态列数及固定行数:(实例化需要支持c++14)
Matrix<float, 3, Dynamic>

Constructors(构造函数)

默认构造函数始终可用,从不执行任何动态内存分配,并且从不初始化矩阵系数:
Matrix3f a;

MatrixXf b;

a 是一个 3×3 矩阵,具有未初始化系数的float[9] 数组,
b 是一个动态大小的矩阵,其大小当前为 0×0,其系数数组尚未分配。
207 / 5,000

在固定范围和动态范围的矩阵之间提供统一的 API,在固定范围的矩阵使用这些构造函数是合法的,即使在这种情况下传递大小是无用的:
Matrix3f a(3,3);

矩阵和向量也可以从系数列表中初始化。 在 C++11 之前,该功能仅限于固定范围的小的列或最大为 4 的向量:
Vector2d a(5.0, 6.0);
Vector3d b(5.0, 6.0, 7.0);
Vector4d c(5.0, 6.0, 7.0, 8.0);

在 C++11中,可以通过传递任意数量的系数来初始化任意大小的固定范围的列或行向量:
Vector2i a(1, 2); // A column vector containing the elements {1, 2}
Matrix<int, 5, 1> b {1, 2, 3, 4, 5}; // A row-vector containing the elements {1, 2, 3, 4, 5}
Matrix<int, 1, 5> c = {1, 2, 3, 4, 5}; // A column vector containing the elements {1, 2, 3, 4, 5}

在具有固定或运行时矩阵和向量的一般情况下,系数必须按行分组并作为初始化列表的初始化列表传递:
MatrixXi a { // construct a 2x2 matrix
{1, 2}, // first row
{3, 4} // second row
};
Matrix<double, 2, 3>b_10{ {2,3,4},{5,6,7} };
Matrix<double,2,2>a_1{{1,2},{3,4}};

对于列或行向量,允许隐式转置。 意味着可以从单行初始化列向量:
VectorXd a {{1.5, 2.5, 3.5}}; // A column-vector with 3 coefficients
RowVectorXd b {{1.0, 2.0, 3.0, 4.0}}; // A row-vector with 4 coefficients

Coefficient accessors(系数存取器)

Eigen 中的系数访问器和修改器是重载括号运算符。 对于矩阵,总是首先传递行索引。 对于向量,只需传递一个索引。 编号从 0 开始:
Eigen::MatrixXd m_2(2, 2);
m_2(0, 0) = 3;
m_2(1, 0) = 2.5;
m_2(0, 1) = 4;
m_2(1, 1) = 3.5;
m_2(1, 1) = m_2(1, 0) + m_2(0, 1);

m(index) 不限于向量,也可用于一般矩阵,在系数数组中进行基于索引的访问。 这取决于矩阵的存储顺序。 所有特征矩阵默认为列优先存储顺序,但这可以更改为行优先,。
operator[] 也为向量中基于索引的访问而重载,但C++ 不允许 operator[] 接受多个参数。 将 operator[] 限制为向量,因为 C++ 中的会使 matrix[i,j] 编译为与 matrix[j] 相同的东西

Comma-initialization(初始化)

矩阵和向量系数可以使用Comma初始化语法方便地设置:
Matrix3f m_3;
m_3 << 1, 2, 3,
4, 5, 6,
7, 8, 9;

Resizing(调整范围)

通过 rows()、cols() 和 size() 检索矩阵的当前大小。 这些方法分别返回行数、列数和系数数。 调整动态范围矩阵是通过 resize() 方法完成的。
Eigen::MatrixXd m_4(2, 5);
m_4.resize(4.3);

在实际矩阵大小没有改变,则 resize() 方法是无操作的; 否则它是破坏性的:系数的值可能会改变。

为了 API 的统一性,所有这些方法在固定范围的矩阵上仍然可用。 实际上无法调整固定范围矩阵的大小。 尝试将固定范围更改为实际不同的值将触发断言失败; 但以下代码是合理的:
Eigen::Matrix4d m_5;
m_5.resize(4, 4);

Assignment and resizing(分配和调整范围)

赋值操作的 operator= 将一个矩阵复制到另一个矩阵中。Eigen 会自动调整左侧矩阵的大小,使其与右侧大小的矩阵大小相匹配:
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;

当然,如果左侧是固定范围,则不允许调整大小。

Fixed vs. Dynamic size(固定范围与动态范围)

使用固定尺寸(例如 Matrix4f),什么时候应该使用动态尺寸(例如 MatrixXf)? 简单的是:尽可能对非常小的尺寸使用固定尺寸,并在较大尺寸或必须使用的地方使用动态尺寸。 对于小尺寸,尤其是小于(大约)16 的尺寸,使用固定尺寸对性能非常有利,因为 Eigen 避免动态内存分配和展开循环。 在内部,固定大小的特征矩阵只是一个普通数组,即做:
Matrix4f mymatrix;
float mymatrix[16];

相比之下,动态大小矩阵的数组总是在堆上分配:
MatrixXf mymatrix_1(rows,columns);
float mymatrix_1 = new float[rowscolumns];

除此之外,MatrixXf 对象将其行数和列数存储为成员变量。

当然,使用固定大小的限制是只有在编译时知道大小时才有可能。 此外,对于足够大的尺寸,例如大于(大约)32 的尺寸,使用固定尺寸的性能优势变得可以忽略不计。 更糟糕的是,尝试在函数内使用固定大小创建一个非常大的矩阵可能会导致堆栈溢出,因为 Eigen 会尝试将数组自动分配为局部变量,而这通常在堆栈上完成。 最后,根据情况,当使用动态大小时,Eigen 也可以更积极地尝试向量化。
Matrix<float, Dynamic, Dynamic, 0, 3, 4>;

Optional template parameters(可选模板参数)

在开头提到 Matrix 类有六个模板参数,但到目前为止只讨论了前三个。 其余三个参数是可选的。 以下是完整列表:
Matrix<typename Scalar,int RowsAtCompileTime,int ColsAtCompileTime,int Option=0,
int MaxRowsAtCompileTime=RowsAtCompileTime,
int MaxColsAtCompileTime=ColsAtCompileTime>

Options是一个位字段。 在这里:RowMajor。 它指定这种类型的矩阵使用行优先存储顺序; 默认情况下,存储顺序为列优先。 例如,这种类型表示行优先的 3x3 矩阵:
Matrix<float, 3, 3, RowMajor>;

MaxRowsAtCompileTime 和 MaxColsAtCompileTime 在指定时很有用,即使在编译时不知道矩阵的确切大小,但在编译时知道固定的上限。这样做的最大原因是避免动态内存分配。 例如,以下矩阵类型使用 12 个浮点数的普通数组,没有动态内存分配:
Matrix<float, Dynamic, Dynamic, 0, 3, 4>;

Optional template parameters(可选模板参数)

Eigen 定义了以下 Matrix 类型定义:
MatrixNt for Matrix<type, N, N>. For example, MatrixXi for Matrix<int, Dynamic, Dynamic>.
MatrixXNt for Matrix<type, Dynamic, N>. For example, MatrixX3i for Matrix<int, Dynamic, 3>.
MatrixNXt for Matrix<type, N, Dynamic>. For example, Matrix4Xd for Matrix<d, 4, Dynamic>.
VectorNt for Matrix<type, N, 1>. For example, Vector2f for Matrix<float, 2, 1>.
RowVectorNt for Matrix<type, 1, N>. For example, RowVector3d for Matrix<double, 1, 3>.

N 可以是 2、3、4 或 X(意思是动态)中的任何一个。
t 可以是 i(表示 int)、f(表示 float)、d(表示 double)、cf(表示 complex)或 cd(表示 complex)中的任何一个。 typedef 只为这五种类型定义的事实并不意味着它们是唯一受支持的标量类型。 。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值