C++ 将特征矩阵转换为C数组

C++ 将特征矩阵转换为C数组,c++,arrays,matrix,eigen,C++,Arrays,Matrix,Eigen,该库可以将现有内存映射为特征矩阵 float array[3]; Map<Vector3f>(array, 3).fill(10); int data[4] = 1, 2, 3, 4; Matrix2i mat2x2(data); MatrixXi mat2x2 = Map<Matrix2i>(data); MatrixXi mat2x2 = Map<MatrixXi>(data, 2, 2); float数组[3]; 地图(数组,3)。填充(10); in

该库可以将现有内存映射为特征矩阵

float array[3];
Map<Vector3f>(array, 3).fill(10);
int data[4] = 1, 2, 3, 4;
Matrix2i mat2x2(data);
MatrixXi mat2x2 = Map<Matrix2i>(data);
MatrixXi mat2x2 = Map<MatrixXi>(data, 2, 2);
float数组[3];
地图(数组,3)。填充(10);
int data[4]=1,2,3,4;
Matrix2i mat2x2(数据);
MatrixXi mat2x2=地图(数据);
MatrixXi mat2x2=地图(数据,2,2);
我的问题是,如何从特征矩阵(如Matrix3f m)中得到c数组(如float[]a)?特征矩阵的实际布局是什么?真实数据是否存储在普通c数组中?

您可以使用特征矩阵类的成员函数。默认情况下,布局是列主视图,而不是行主视图,作为多维C数组(可以在创建矩阵对象时选择布局)。对于稀疏矩阵,前面的句子显然不适用

例如:

ArrayXf v = ArrayXf::LinSpaced(11, 0.f, 10.f);
// vc is the corresponding C array. Here's how you can use it yourself:
float *vc = v.data();
cout << vc[3] << endl;  // 3.0
// Or you can give it to some C api call that takes a C array:
some_c_api_call(vc, v.size());
// Be careful not to use this pointer after v goes out of scope! If
// you still need the data after this point, you must copy vc. This can
// be done using in the usual C manner, or with Eigen's Map<> class.
ArrayXf v=ArrayXf::LinSpaced(11,0.f,10.f);
//vc是对应的C数组。以下是您自己如何使用它:
float*vc=v.data();

cout您需要再次使用Map函数。请参见此处的示例:
ComplexEigenSolveres;
复合物*eseig;
es.计算(H);
特征值()转置();
eseig=(复数*)es.特征值().数据();

将普通数据类型转换为特征矩阵类型

  double *X; // non-NULL pointer to some data
您可以使用以下映射功能创建nRows x nCols大小的双矩阵:

  MatrixXd eigenX = Map<MatrixXd>( X, nRows, nCols );
MatrixXd-eigenX=Map(X,nRows,nCols);
将特征矩阵类型转换为正规数据类型

  MatrixXd resultEigen;   // Eigen matrix with some result (non NULL!)
  double *resultC;        // NULL pointer <-- WRONG INFO from the site. resultC must be preallocated!
  Map<MatrixXd>( resultC, resultEigen.rows(), resultEigen.cols() ) =   resultEigen;
MatrixXd结果生成;//具有某些结果的特征矩阵(非空!)

双精度*resultC;//空指针当我尝试它时,上面有Map的解决方案会出现错误(请参见上面的注释)

相反,这里有一个适合我的解决方案,将数据从一个特征::矩阵复制到一个std::向量中。我在向量中预先分配空间来存储映射/复制的结果

Eigen::MatrixXf m(2, 2);
m(0, 0) = 3;
m(1, 0) = 2.5;
m(0, 1) = -1;
m(1, 1) = 0;

cout << m << "\n";

// Output:
//    3  -1
// 2.5   0

// Segfaults with this code: 
//
// float* p = nullptr;
// Eigen::Map<Eigen::MatrixXf>(p, m.rows(), m.cols()) = m;

// Better code, which also copies into a std::vector:

// Note that I initialize vec with the matrix size to begin with:
std::vector<float> vec(m.size());
Eigen::Map<Eigen::MatrixXf>(vec.data(), m.rows(), m.cols()) = m;

for (const auto& x : vec)
  cout << x << ", ";
cout << "\n";

// Output: 3, 2.5, -1, 0
Eigen::matrixxfm(2,2);
m(0,0)=3;
m(1,0)=2.5;
m(0,1)=-1;
m(1,1)=0;

cout如果阵列是二维的,则需要注意存储顺序。默认情况下,Eigen按列主顺序存储矩阵。然而,将阵列直接转换为特征矩阵需要行主阶。如果在代码中频繁执行此类转换,则使用相应的
typedef
可能会有所帮助

using namespace Eigen;
typedef Matrix<int, Dynamic, Dynamic, RowMajor> RowMatrixXi;

注意,在这种情况下,原始矩阵
eig
不需要存储在行主布局中。在
Map

中指定行的主要顺序就足够了。我尝试了以下方法:在(0,0)处传递元素的地址并向前迭代

Eigen::Matrix<double, 3, 8> coordinates3d;
coordinates3d <<    0.0,  0.0,  1.0,  1.0,  0.0,  0.0,  1.0,  1.0,
                    0.0,  1.0,  1.0,  0.0,  0.0,  1.0,  1.0,  0.0,
                    1.0,  1.0,  1.0,  1.0,  0.0,  0.0,  0.0,  0.0;
double *p = &coordinates3d(0,0);
std::vector<double> x2y2;
x2y2.assign(p, p + coordinates3d.size());

for(int i=0;i < coordinates3d.size(); i++) {
    std::cout <<x2y2[i];
}
Eigen::矩阵坐标3d;

这些不是标准的数据类型。“Eigen”是该库的名称,还是对数学基础的引用?如果是后者,类型来自哪个库?另外,C没有模板类型。既然矩阵是二维的,那么在普通数组中你到底想要什么呢?一个特定的行或列,或者整个矩阵被重塑为一维?@outis-Eigen指的是A。@ChristianRau:可以,但我想绝对确定lil指的就是这个。@ChristianRau是的,我指的是第二部分没有意义。Eigen::Map如何神奇地获取空指针(resultC)并将数据复制到它??事实上,正如您所期望的,我用一个示例2x2矩阵和地图segfaults尝试了上面的代码。只需使用不正确的信息从站点中ctrl+c ctrl+v即可!这是行不通的。有人能纠正这个答案吗?这里也一样@eraoul@eraoul第一部分也没有意义。这个答案产生了错误的结果,因为它没有考虑到特征值和特征值中不同的存储顺序C@Pedro77对于未来的人:
Eigen::Matrix顶点这很奇怪,但是data()成员函数由于某种原因没有文档记录。我在看:@谜物理学家:哦,在那里。谢谢,@janneb。计算特征值和特征向量与这个问题有什么关系?我只想在这里指出,这是预期注释掉的代码会出错
Map
不分配内存,因此您试图将数据复制到
nullptr
中。
int nrow = 2, ncol = 3;
int arr[nrow][ncol] =  { {1 ,2, 3},  {4, 5, 6} }; 
Map<RowMatrixXi> eig(&arr[0][0], nrow, ncol);

std::cout << "Eigen matrix:\n" << eig << std::endl;

// Eigen matrix:
// 1 2 3
// 4 5 6
int arr2[nrow][ncol];
Map<RowMatrixXi>(&arr2[0][0], nrow, ncol) = eig;

std::cout << "C array:\n";
for (int i = 0; i < nrow; ++i) {
  for (int j = 0; j < ncol; ++j) {
    std::cout << arr2[i][j] << " ";
  }
  std::cout << "\n";
}

// C array:
// 1 2 3 
// 4 5 6 
Eigen::Matrix<double, 3, 8> coordinates3d;
coordinates3d <<    0.0,  0.0,  1.0,  1.0,  0.0,  0.0,  1.0,  1.0,
                    0.0,  1.0,  1.0,  0.0,  0.0,  1.0,  1.0,  0.0,
                    1.0,  1.0,  1.0,  1.0,  0.0,  0.0,  0.0,  0.0;
double *p = &coordinates3d(0,0);
std::vector<double> x2y2;
x2y2.assign(p, p + coordinates3d.size());

for(int i=0;i < coordinates3d.size(); i++) {
    std::cout <<x2y2[i];
}