Passing Eigen::Map<ArrayXd> to a function expecting ArrayXd&
Asked Answered
D

2

1

Some of my Eigen C++ methods need to be callable from plain C++, therefore I want to provide overloaded functions that accept c arrays and map them to ArrayXd using Eigen::Map.

The code I currently have looks like this:

bool Dmp::executeStep(double* position, double* velocity,
                  double* acceleration, const int len)
{
  Map<ArrayXd> posMap(position, len);
  Map<ArrayXd> velMap(velocity, len);
  Map<ArrayXd> accMap(acceleration, len);
  return executeStep(posMap, velMap, accMap);
}


bool Dmp::executeStep(ArrayXd& position, ArrayXd& velocity, ArrayXd& acceleration)
{
//Code that modifies position, velocity and acceleration
}

This does not work because there is no known conversation from Map<ArrayXd> to ArrayXd&. What is the correct way of doing this?

edit: The answer that luk32 pointed out below would work, however it involves moving my code to the header file which is something I would like to avoid if at all possible.

Divisor answered 5/3, 2014 at 9:26 Comment(2)
Eigen and c tag? Really ... what the heck.Subrogate
@Subrogate sorry, removed the c tagRobi
S
1

You should make the executeStep a template function. Or use their other facilities like Ref There is a whole comprehensive tutorial in docs on Writing Functions Taking Eigen Types as Parameters.

I am not sure if Map has a more direct parent than EigenBase (maybe Dense really not sure), but as it is most general it should work:

template <typename Derived>
void Dmp::executeStep(EigenBase<Derived>& pos,EigenBase<Derived>& vel, EigenBase<Derived>& acc )
{
// fun ...
}

Of course you need to declare it as a template member too.

I really highly suggest reading the whole tutorial.

Using Ref implementation. I am not sure however if there is a copy from Map to MyMatrix made. Ref do not accept Map objects as it seems to cast them to DenseMatrix.

#include <Eigen/Core>
#include <iostream>

using namespace Eigen;

typedef Matrix<int,2,4>  MyMatrix ;

void print_size(const Ref<const MyMatrix>& b)
{
  std::cout << "size (rows, cols): " << b.size() << " (" << b.rows()
            << ", " << b.cols() << ")" << "\n";
}

int main()
{
  int array[8];
  for(int i = 0; i < 8; ++i) array[i] = i;
  Map<MyMatrix> map(array);
  std::cout << "Column-major:\n" <<  map << "\n";
  print_size(map);
}
Subrogate answered 5/3, 2014 at 10:5 Comment(4)
Yes, this would work. However I would need to move my code to the header file which is something I would like to avoid if possible. If there is no other way I'll accept this answer.Robi
@ArneBöckmann Well I am not sure if you read the tutorial, but since 3.2.1 there is Ref facility.Subrogate
Introduced in 3.2.1? That explains why I couldn't find it in our current installation of eigen. I guess upgrading eigen is not an option right now :/ I ll accept this answer and try to persuade someone to upgrade the eigen version :DRobi
I had to update my eigen installation to check out the code too. Previously I had 3.1.x. Also I used the official releases, not repository stuff.Subrogate
N
3

This is exactly the purpose of the Ref<> class:

bool Dmp::executeStep(Ref<ArrayXd> position, Ref<ArrayXd> velocity, Ref<ArrayXd> acceleration)
{
}
Niccolite answered 5/3, 2014 at 10:52 Comment(0)
S
1

You should make the executeStep a template function. Or use their other facilities like Ref There is a whole comprehensive tutorial in docs on Writing Functions Taking Eigen Types as Parameters.

I am not sure if Map has a more direct parent than EigenBase (maybe Dense really not sure), but as it is most general it should work:

template <typename Derived>
void Dmp::executeStep(EigenBase<Derived>& pos,EigenBase<Derived>& vel, EigenBase<Derived>& acc )
{
// fun ...
}

Of course you need to declare it as a template member too.

I really highly suggest reading the whole tutorial.

Using Ref implementation. I am not sure however if there is a copy from Map to MyMatrix made. Ref do not accept Map objects as it seems to cast them to DenseMatrix.

#include <Eigen/Core>
#include <iostream>

using namespace Eigen;

typedef Matrix<int,2,4>  MyMatrix ;

void print_size(const Ref<const MyMatrix>& b)
{
  std::cout << "size (rows, cols): " << b.size() << " (" << b.rows()
            << ", " << b.cols() << ")" << "\n";
}

int main()
{
  int array[8];
  for(int i = 0; i < 8; ++i) array[i] = i;
  Map<MyMatrix> map(array);
  std::cout << "Column-major:\n" <<  map << "\n";
  print_size(map);
}
Subrogate answered 5/3, 2014 at 10:5 Comment(4)
Yes, this would work. However I would need to move my code to the header file which is something I would like to avoid if possible. If there is no other way I'll accept this answer.Robi
@ArneBöckmann Well I am not sure if you read the tutorial, but since 3.2.1 there is Ref facility.Subrogate
Introduced in 3.2.1? That explains why I couldn't find it in our current installation of eigen. I guess upgrading eigen is not an option right now :/ I ll accept this answer and try to persuade someone to upgrade the eigen version :DRobi
I had to update my eigen installation to check out the code too. Previously I had 3.1.x. Also I used the official releases, not repository stuff.Subrogate

© 2022 - 2024 — McMap. All rights reserved.