Eigen还没有提供resharp或者slicing的处理函数,但是,可以使用Map 类来实现这些功能。
操作Resharp及修改Matrix的维度大小,而其系数保持不变。Resharp时,应该返回一个对象,而保留原对象不变。
Eigen提供了示例.
MatrixXf M1(3,3); // Column-major storage
M1 << 1, 2, 3,
4, 5, 6,
7, 8, 9;
Map<RowVectorXf> v1(M1.data(), M1.size());
cout << "v1:" << endl << v1 << endl;
Matrix<float,Dynamic,Dynamic,RowMajor> M2(M1);
Map<RowVectorXf> v2(M2.data(), M2.size());
cout << "v2:" << endl << v2 << endl;
cout << endl;
MatrixXf M1(2,6); // Column-major storage
M1 << 1, 2, 3, 4, 5, 6,
7, 8, 9, 10, 11, 12;
Map<MatrixXf> M2(M1.data(), 6,2);
cout << "M2:" << endl << M2 << endl;
执行结果:
v1:
1 4 7 2 5 8 3 6 9
v2:
1 2 3 4 5 6 7 8 9
M2:
1 4
7 10
2 5
8 11
3 6
9 12
上面示例,从一个3X3的矩阵,创建得到了1X9的矩阵。后续的操作,将列优先的2X6矩阵转换,得到6X2的矩阵,需要注意它们在内存中的系数的顺序。
切片slicing大致的操作如此: 在一个矩阵内,安装一定的间隔,取得一组的行、或者列、或部分元素。
下面示例使用Map来模拟:
For instance, one can skip every P elements in a vector:
RowVectorXf v = RowVectorXf::LinSpaced(20,0,19);
cout << "Input:" << endl << v << endl;
Map<RowVectorXf,0,InnerStride<2> > v2(v.data(), v.size()/2);
cout << "Even:" << v2 << endl;
查看结果:
Input:
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
Even: 0 2 4 6 8 10 12 14 16 18
也可以根据存储顺序,使用合适的outer-strider、inner-strider,来获取矩阵的某些列。
这里先看一下Stride的定义:
/** \class Stride
* \ingroup Core_Module
*
* \brief Holds strides information for Map
*
* This class holds the strides information for mapping arrays with strides with class Map.
*
* It holds two values: the inner stride and the outer stride.
*
* The inner stride is the pointer increment between two consecutive entries within a given row of a
* row-major matrix or within a given column of a column-major matrix.
*
* The outer stride is the pointer increment between two consecutive rows of a row-major matrix or
* between two consecutive columns of a column-major matrix.
*
* These two values can be passed either at compile-time as template parameters, or at runtime as
* arguments to the constructor.
*
* Indeed, this class takes two template parameters:
* \tparam _OuterStrideAtCompileTime the outer stride, or Dynamic if you want to specify it at runtime.
* \tparam _InnerStrideAtCompileTime the inner stride, or Dynamic if you want to specify it at runtime.
*
*
*/
... ...
/** \brief Convenience specialization of Stride to specify only an inner stride
* See class Map for some examples */
template<int Value>
class InnerStride : public Stride<0, Value>
{
typedef Stride<0, Value> Base;
public:
EIGEN_DEVICE_FUNC InnerStride() : Base() {}
EIGEN_DEVICE_FUNC InnerStride(Index v) : Base(0, v) {} // FIXME making this explicit could break valid code
};
/** \brief Convenience specialization of Stride to specify only an outer stride
* See class Map for some examples */
template<int Value>
class OuterStride : public Stride<Value, 0>
{
typedef Stride<Value, 0> Base;
public:
EIGEN_DEVICE_FUNC OuterStride() : Base() {}
EIGEN_DEVICE_FUNC OuterStride(Index v) : Base(v,0) {} // FIXME making this explicit could break valid code
};
可以看到,InnerStride是第一个参数,作用于某种优先存储模式的优先级上的实体,比如行优先时,作用于行上的实体;列优先时,作用于列实体。
而OuterStride作用于行矩阵的行或者列,如行优先时作用于行,而列优先时,作用于列。
这是示例程序:
//matrix_sliding.cpp
#include
#include
using namespace std;
using namespace Eigen;
int main()
{
MatrixXf M1 = MatrixXf::Random(3,8);
cout << "Column major input:" << endl << M1 << "\n";
cout << "M1's outerStride: " << M1.outerStride() << " -- M1.cols(): " << M1.cols() << endl;
Map<MatrixXf,0,OuterStride<> > M2(M1.data(), /*3*/ M1.rows(), /*3*/ (M1.cols()+2)/3, OuterStride<>(M1.outerStride()*3));
cout << "1 column over 3:" << endl << M2 << "\n";
typedef Matrix<float,Dynamic,Dynamic,RowMajor> RowMajorMatrixXf;
RowMajorMatrixXf M3(M1);
cout << "Row major input:" << endl << M3 << "\n";
cout << "M3.outerStride(): " << M3.outerStride() << endl;
Map<RowMajorMatrixXf,0,Stride<Dynamic,3> > M4(M3.data(), M3.rows(), (M3.cols()+2)/3,
Stride<Dynamic,3>(M3.outerStride(),3));
cout << "1 column over 3:" << endl << M4 << "\n";
}
执行结果:
$ g++ -I /usr/local/include/eigen3 matrix_sliding.cpp -o matrix_sliding
$
$ ./matrix_sliding
Column major input:
-0.999984 -0.0826997 -0.905911 0.869386 0.661931 0.0594004 -0.233169 0.373545
-0.736924 0.0655345 0.357729 -0.232996 -0.930856 0.342299 -0.866316 0.177953
0.511211 -0.562082 0.358593 0.0388328 -0.893077 -0.984604 -0.165028 0.860873
M1's outerStride: 3 -- M1.cols(): 8
1 column over 3:
-0.999984 0.869386 -0.233169
-0.736924 -0.232996 -0.866316
0.511211 0.0388328 -0.165028
Row major input:
-0.999984 -0.0826997 -0.905911 0.869386 0.661931 0.0594004 -0.233169 0.373545
-0.736924 0.0655345 0.357729 -0.232996 -0.930856 0.342299 -0.866316 0.177953
0.511211 -0.562082 0.358593 0.0388328 -0.893077 -0.984604 -0.165028 0.860873
M3.outerStride(): 8
1 column over 3:
-0.999984 0.869386 -0.233169
-0.736924 -0.232996 -0.866316
0.511211 0.0388328 -0.165028
示例里使用Outstride,M1是缺省的列优先。M2映射M1得到,指定了OuterStride,取1个列,然后跳过2个列,得到新的矩阵。M1 --(Map)-->M2
。
M3是指定了行优先,拷贝M1构建的矩阵,系数与M1相同。从M3 映射得到M4时,指定了Stride
,M3 --(Map)-->M4
。
从输出中,我们可以知道,在缺省未指定的情况下,Outstride的参数为其对应的行(行优先)或者列(列优先)的元素数量。如M1的OuterStride为3(每列3个元素),M3位8(每行8个列元素)。