簡介
Eigen還沒有提供resharp或者slicing的處理函數,但是,可以使用Map 類來實現這些功能。
實現resharp
操作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
切片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 <iostream>
#include <Eigen/Dense>
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<Dynamic,3>(M3.outerStride(),3)
,M3 --(Map)-->M4
。
從輸出中,我們可以知道,在缺省未指定的情況下,Outstride的參數爲其對應的行(行優先)或者列(列優先)的元素數量。如M1的OuterStride爲3(每列3個元素),M3位8(每行8個列元素)。