Преобразовать собственную матрицу в массив C - PullRequest
47 голосов
/ 09 декабря 2011

Библиотека 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);

Мой вопрос: как мы можем получить массив c (например, float [] a) из собственной матрицы (например, Matrix3f m)?Каково это реальное расположение собственной матрицы?Реальные данные хранятся как в обычном массиве c?

Ответы [ 6 ]

50 голосов
/ 09 декабря 2011

Вы можете использовать функцию-член data () класса Eigen Matrix. По умолчанию макет является основным по столбцу, а не основным по строкам, как многомерный массив C (макет можно выбрать при создании объекта Matrix). Для разреженных матриц предыдущее предложение, очевидно, неприменимо.

Пример:

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.
15 голосов
/ 25 апреля 2015

Чтобы преобразовать обычный тип данных в собственный тип матрицы

  double *X; // non-NULL pointer to some data

Вы можете создать двойную матрицу размера nRows x nCols, используя функциональность Map, например:

  MatrixXd eigenX = Map<MatrixXd>( 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;

Таким образом, вы можете входить и выходить из собственной матрицы.Полные кредиты идут на http://dovgalecs.com/blog/eigen-how-to-get-in-and-out-data-from-eigen-matrix/

3 голосов
/ 07 февраля 2018

Если массив двумерный, нужно обратить внимание на порядок хранения.По умолчанию Eigen хранит матрицы в главном порядке столбцов.Однако порядок прямого ряда необходим для прямого преобразования массива в собственную матрицу.Если такие преобразования часто выполняются в коде, было бы полезно использовать соответствующие typedef.

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

. С таким определением можно получить собственную матрицу из массива простым и компактным способом., сохраняя при этом порядок исходного массива.

Из массива C в Eigen :: Matrix

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

В обратном направлении элементы собственной матрицыможет быть передан непосредственно в массив в стиле C с помощью Map.

От Eigen :: Matrix до C array

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 

Обратите внимание, что в этом случае исходную матрицу eig не нужно хранить в мажорной строкераскладка.Достаточно указать основной порядок строк в Map.

3 голосов
/ 19 июня 2012

Вам нужно снова использовать функцию карты. Пожалуйста, посмотрите пример здесь: http://forum.kde.org/viewtopic.php?f=74&t=95457

1 голос
/ 26 октября 2016

Решение с картой выше segfaults при попытке (см. Комментарий выше).

Вместо этого вот решение, которое работает для меня, копируя данные в std :: vector из Eigen :: Matrix. Я предварительно выделяю место в векторе для хранения результата Map / copy.

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
0 голосов
/ 13 декабря 2013
ComplexEigenSolver < MyMatrix > es;
complex<double> *eseig;
es.compute(H);
es.eigenvalues().transpose();
eseig=(complex<double> *)es.eigenvalues().data();
...