从 Eigen3.4
开始,Eigen 发布了将矩阵或向量重塑为不同大小的便捷方法。所有的操作可以通过 DenseBase::reshaped(NRowsType,NColsType)
和 DenseBase::reshaped()
两个函数完成。这些函数并不直接改变原有的变量,而是返回一个重塑后的变量副本。
二维Reshape
更一般的 reshap
转换是通过 reshaped(nrows,ncols)
处理的。这是一个将 4x4
矩阵重塑为 2x8
矩阵的示例:
// 代码索引 3-8-1-1
Matrix4i m = Matrix4i::Random();
cout << "Here is the matrix m:" << endl << m << endl;
cout << "Here is m.reshaped(2, 8):" << endl << m.reshaped(2, 8) << endl;
输出:
Here is the matrix m:
7 9 -5 -3
-2 -6 1 0
6 -3 0 9
6 6 3 9
Here is m.reshaped(2, 8):
7 6 9 -3 -5 0 -3 9
-2 6 -6 6 1 3 0 9
默认情况下,无论输入表达式的存储顺序如何,输入元素始终按列优先顺序处理。有关排序、编译时大小和自动大小归约的更多信息,请参阅 DenseBase::reshaped(NRowsType,NColsType)
的文档,其中包含所有详细信息和许多示例(没找到文档,只找到源码,在Eigen/src/plugins/ReshapedMethods.h
中)。
一维线性Reshape
reshape的一个非常常见的用法是将给定的二维矩阵或表达式变为一维线性的形式。在这种情况下,可以计算出维度,因此可以省略相关传参,如下例所示:
// 代码索引 3-8-1-2
Matrix4i m = Matrix4i::Random();
cout << "Here is the matrix m:" << endl << m << endl;
cout << "Here is m.reshaped().transpose():" << endl << m.reshaped().transpose() << endl;
cout << "Here is m.reshaped<RowMajor>().transpose(): " << endl << m.reshaped<RowMajor>().transpose() << endl;
输出:
Here is the matrix m:
7 9 -5 -3
-2 -6 1 0
6 -3 0 9
6 6 3 9
Here is m.reshaped().transpose():
7 -2 6 6 9 -6 -3 6 -5 1 0 3 -3 0 9 9
Here is m.reshaped<RowMajor>().transpose():
7 9 -5 -3 -2 -6 1 0 6 -3 0 9 6 6 3 9
.transpose()
方法始终返回列向量,默认情况下,元素始终按列优先排序。同样,请参阅 DenseBase::reshaped()
的文档以获得对排序的更多信息。
原地Reshape
上述示例都是另外创建一个reshape对象,但怎么将一个给定矩阵原地reshape呢?这个操作只适用于具有运行时维度的矩阵和数组。通常这可以通过 PlainObjectBase::resize(Index,Index)
来完成:
// 代码索引 3-8-2-1
MatrixXi m = Matrix4i::Random();
cout << "Here is the matrix m:" << endl << m << endl;
cout << "Here is m.reshaped(2, 8):" << endl << m.reshaped(2, 8) << endl;
m.resize(2,8);
cout << "Here is the matrix m after m.resize(2,8):" << endl << m << endl;
输出:
Here is the matrix m:
7 9 -5 -3
-2 -6 1 0
6 -3 0 9
6 6 3 9
Here is m.reshaped(2, 8):
7 6 9 -3 -5 0 -3 9
-2 6 -6 6 1 3 0 9
Here is the matrix m after m.resize(2,8):
7 6 9 -3 -5 0 -3 9
-2 6 -6 6 1 3 0 9
但是请注意,与 reshaped
不同,resize
的结果取决于输入的存储顺序。因此它的行为类似于 reshaped<AutoOrder>
:
// 代码索引 3-8-2-2
Matrix<int,Dynamic,Dynamic,RowMajor> m = Matrix4i::Random();
cout << "Here is the matrix m:" << endl << m << endl;
cout << "Here is m.reshaped(2, 8):" << endl << m.reshaped(2, 8) << endl;
cout << "Here is m.reshaped<AutoOrder>(2, 8):" << endl << m.reshaped<AutoOrder>(2, 8) << endl;
m.resize(2,8);
cout << "Here is the matrix m after m.resize(2,8):" << endl << m << endl;
输出:
Here is the matrix m:
7 -2 6 6
9 -6 -3 6
-5 1 0 3
-3 0 9 9
Here is m.reshaped(2, 8):
7 -5 -2 1 6 0 6 3
9 -3 -6 0 -3 9 6 9
Here is m.reshaped<AutoOrder>(2, 8):
7 -2 6 6 9 -6 -3 6
-5 1 0 3 -3 0 9 9
Here is the matrix m after m.resize(2,8):
7 -2 6 6 9 -6 -3 6
-5 1 0 3 -3 0 9 9
最后,目前不支持将reshape处理后的矩阵分配给自身,也不支持由于别名而导致未定义的行为。禁止以下行为:
A = A.reshaped(2,8);
但这样是可以的:
A = A.reshaped(2,8).eval();