Convert Eigen Matrix to C array

后端 未结 7 1925
深忆病人
深忆病人 2020-11-30 03:33

The Eigen library can map existing memory into Eigen matrices.

float array[3];
Map(array, 3).fill(10);
int data[4] = 1, 2, 3, 4;
Matrix2i mat         


        
相关标签:
7条回答
  • 2020-11-30 04:00

    If the array is two-dimensional, one needs to pay attention to the storage order. By default, Eigen stores matrices in column-major order. However, a row-major order is needed for the direct conversion of an array into an Eigen matrix. If such conversions are performed frequently in the code, it might be helpful to use a corresponding typedef.

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

    With such a definition one can obtain an Eigen matrix from an array in a simple and compact way, while preserving the order of the original array.

    From C array to 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
    

    In the opposite direction, the elements of an Eigen matrix can be transferred directly to a C-style array by using Map.

    From Eigen::Matrix to 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 
    

    Note that in this case the original matrix eig does not need to be stored in row-major layout. It is sufficient to specify the row-major order in Map.

    0 讨论(0)
  • 2020-11-30 04:04

    You can use the data() member function of the Eigen Matrix class. The layout by default is column-major, not row-major as a multidimensional C array (the layout can be chosen when creating a Matrix object). For sparse matrices the preceding sentence obviously doesn't apply.

    Example:

    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.
    
    0 讨论(0)
  • 2020-11-30 04:06

    You need to use the Map function again. Please see the example here: http://forum.kde.org/viewtopic.php?f=74&t=95457

    0 讨论(0)
  • 2020-11-30 04:11
    ComplexEigenSolver < MyMatrix > es;
    complex<double> *eseig;
    es.compute(H);
    es.eigenvalues().transpose();
    eseig=(complex<double> *)es.eigenvalues().data();
    
    0 讨论(0)
  • 2020-11-30 04:14

    The solution with Map above segfaults when I try it (see comment above).

    Instead, here's a solution that works for me, copying the data into a std::vector from an Eigen::Matrix. I pre-allocate space in the vector to store the result of the 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 讨论(0)
  • 2020-11-30 04:17

    To convert normal data type to eigen matrix type

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

    You can create an nRows x nCols size double matrix using the Map functionality like this:

      MatrixXd eigenX = Map<MatrixXd>( X, nRows, nCols );
    

    To convert eigen matrix type into normal data type

      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;
    

    In this way you can get in and out from eigen matrix. Full credits goes to http://dovgalecs.com/blog/eigen-how-to-get-in-and-out-data-from-eigen-matrix/

    0 讨论(0)
提交回复
热议问题