2

I want to use Eigen to do some calculation in some C-style code, the function interface has a raw pointer as below,

#include <iostream>
#include <memory>
#include <Eigen/Dense>

using namespace Eigen;  
typedef Eigen::Matrix<double, -1, -1, Eigen::RowMajor> Mrow;

    void compute_with_Eigen(double * p_data, int row, int col)
    {       
    // Q1: is there any data copy here?
    Eigen::MatrixXd Mc = Eigen::Map<Mrow>(p_data, row, col);

    // do computations with Mc, for example
    auto M_temp = Mc.inverse();
    Mc = M_temp;

    // Q2: why is this assign-back necessary?
    Eigen::Map<Mrow>( p_data, row, col ) =   Mc;   
    }

int main()
{

std::unique_ptr<double[]> p(new double[10]);
for (int i = 0; i < 9; ++i)
{
p[i]=i+1.0;
std::cout<<p[i]<<std::endl;
}

compute_with_Eigen(p.get(),3,3);

std::cout<<"after inverse\n";
for (int i = 0; i < 10; ++i)
    std::cout<<p[i]<<std::endl;
}

I have Question1 because the accepted answer in this thread suggests there are some copy, however, in principle a "view" shouldn't copy anything.

I have Question2 because otherwise the result is not as expected, however this is not like a "view"(also see this answer) if I really have to assign back

Community
  • 1
  • 1
seam
  • 43
  • 4

2 Answers2

3

Ad Q1:

Eigen::MatrixXd Mc = Eigen::Map<Mrow>(p_data, row, col);

This copies a temporary Map into a dynamic Matrix Mc. If you want to avoid that copy, you can write:

Eigen::Map<Mrow> Mc(p_data, row, col);

Ad Q2: You can avoid that copy, if you declare Mc as a map (as above). As you wrote it, you are copying back the values from the MatrixXd Mc to a temporary Map.

Btw, writing

    auto M_temp = Mc.inverse();
    Mc = M_temp;

Is almost equivalent to directly writing

    Mc = Mc.inverse();

because auto M_temp is not actually a Matrix, but an Expression template which will calculate an inverse once it is assigned to an actual matrix (or M_temp.eval() is called.

chtz
  • 17,329
  • 4
  • 26
  • 56
  • thanks! But if Mc is a map/view, then in real computation is it row-major or col-major "matrix"? In my code I can specify the map itself is row-major, and the matrix Mc is column-major, which is clear to me. – seam Dec 06 '16 at 20:03
  • If you declare `Eigen::Map Mc(...)` with `Mrow` as above, then `Mc` is row-major. And as long as you are not mixing row- and column-major matrices in an expression, all computations will be performed row-major (there may be exceptions for some decompositions). – chtz Dec 06 '16 at 20:12
  • You should avoid using `auto` with Eigen: https://eigen.tuxfamily.org/dox/TopicPitfalls.html My code compiled, but returned the wrong result, and auto was the culprit that time. – Hannes Ovrén Mar 29 '17 at 05:55
0

The short answer is that construct a map object usually does not copy. However, the computations that follows may create copies or temporaries or both.

Yan Zhou
  • 2,709
  • 2
  • 22
  • 37