This forum has been archived. All content is frozen. Please use KDE Discuss instead.

Passing MatrixXd blocks into functions

Tags: None
(comma "," separated)
xhlhxjj
Registered Member
Posts
4
Karma
0
Hi,

I am trying to pass Matrix blocks into functions so that they can perform read/write operations on the blocks.

I am creating the blocks by calling the MatrixXd.block(a,b,c,d) method.

However when I try to pass the result to a method, I keep getting compile time conversion errors. Most of the errors were to the effect of
Code: Select all
cannot convert parameter 1 from 'Eigen::Block<MatrixType,BlockRows,BlockCols>' to 'Eigen::MatrixXd &'


I went thru the below web-page which talks about passing EigenTypes between functions and the following sentence stood out:

http://eigen.tuxfamily.org/dox-devel/To ... Types.html

the compiler will fail, because it is not possible to convert the expression returned by MatrixXf::block() in a non-const MatrixXf&. This is the case because the compiler wants to protect you from writing your result to a temporary object. In this special case this protection is not intended -- we want to write to a temporary object. So how can we overcome this problem? There are two possible solutions depending on the type of compiler you are using.


the article then talked about using a 'hack of the form'
Code: Select all
template <typename Derived>
int myfunction(MatrixBase<Derived> EIGEN_REF_TO_TEMPORARY variable)
{
...
}


Which did not work for me. Now in addition to the original conversion error, I am getting the following error
Code: Select all
syntax error : missing ',' before identifier 'variable'


My compiler is VC++ 2010.

Can someone please advise me on how to do this.

Thanks.
Hauke
Registered Member
Posts
109
Karma
3
OS
Hi,

over here, the following self contained example is working with VS2010

Code: Select all
#include <iostream>

#include <Eigen/Core>

using namespace Eigen;

template <typename Derived>
int myfunction(MatrixBase<Derived> EIGEN_REF_TO_TEMPORARY variable)
{
  std::cout << variable << std::endl;
  return 0;
}

template <typename Derived>
int myfunction_not_backwardcompatible(MatrixBase<Derived>&& variable)
{
  std::cout << variable << std::endl;
  return 0;
}

int main()
{
  MatrixXd m = MatrixXd::Random(50,50);

  myfunction(m.block(5,5,10,10));
  myfunction_not_backwardcompatible(m.block(5,5,10,10));

  myfunction(m);
  myfunction_not_backwardcompatible(std::move(m));

  return 1;
}


Which version are you using?

Regards,
Hauke
xhlhxjj
Registered Member
Posts
4
Karma
0
Hi Hauke,

Thanks for the help. I was using the following method:
Code: Select all
template <typename Derived>
int myfunction(MatrixBase<Derived> EIGEN_REF_TO_TEMPORARY variable)


During my attempt at debugging the problem, I copy/pasted your code into vc++ and got the following build errors:
Code: Select all
1>------ Build started: Project: NumericalMethods, Configuration: Debug Win32 ------
1>  main.cpp
1>c:\users\deinesh\documents\visual studio 2010\projects\numericalmethods\numericalmethods\main.cpp(8): error C2146: syntax error : missing ',' before identifier 'variable'
1>c:\eigen\eigen\src\core\cwisenullaryop.h(51): error C2039: 'IsRepeatable' : is not a member of 'Eigen::ei_functor_traits<T>'
1>          with
1>          [
1>              T=Eigen::ei_scalar_random_op<double>
1>          ]
1>          c:\eigen\eigen\src\core\matrixbase.h(62) : see reference to class template instantiation 'Eigen::ei_traits<T>' being compiled
1>          with
1>          [
1>              T=Eigen::CwiseNullaryOp<Eigen::ei_scalar_random_op<double>,Eigen::Matrix<double,10000,10000>>
1>          ]
1>          c:\eigen\eigen\src\core\cwisenullaryop.h(59) : see reference to class template instantiation 'Eigen::MatrixBase<Derived>' being compiled
1>          with
1>          [
1>              Derived=Eigen::CwiseNullaryOp<Eigen::ei_scalar_random_op<double>,Eigen::Matrix<double,10000,10000>>
1>          ]
1>          c:\users\deinesh\documents\visual studio 2010\projects\numericalmethods\numericalmethods\main.cpp(23) : see reference to class template instantiation 'Eigen::CwiseNullaryOp<NullaryOp,MatrixType>' being compiled
1>          with
1>          [
1>              NullaryOp=Eigen::ei_scalar_random_op<double>,
1>              MatrixType=Eigen::Matrix<double,10000,10000>
1>          ]
1>c:\eigen\eigen\src\core\cwisenullaryop.h(51): error C2065: 'IsRepeatable' : undeclared identifier
1>c:\eigen\eigen\src\core\cwisenullaryop.h(51): error C2057: expected constant expression
1>c:\eigen\eigen\src\core\cwisenullaryop.h(104): error C2079: 'Eigen::CwiseNullaryOp<NullaryOp,MatrixType>::m_functor' uses undefined struct 'Eigen::ei_scalar_random_op<Scalar>'
1>          with
1>          [
1>              NullaryOp=Eigen::ei_scalar_random_op<double>,
1>              MatrixType=Eigen::Matrix<double,10000,10000>
1>          ]
1>          and
1>          [
1>              Scalar=double
1>          ]
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========



It looks like I might be using a different version or have some configuration problem.

To check to see if the Eigen library was installed correctly, I compiled and ran the following code succesfully:
Code: Select all
#include <iostream>

#include <Eigen/Core>

using namespace Eigen;

int main()
{
  MatrixXd m = MatrixXd::Zero(3,3);
  m<<1, 2, 3, 4, 5, 6, 7, 8, 9;

  std::cout<<m<<std::endl;
  return 0;
}


Any thoughts as to whats going on?
Hauke
Registered Member
Posts
109
Karma
3
OS
It seems your problem is of a different nature. In case you can post a simple failing example, we can most likely help you.

The version of Eigen can be determined by looking for these macros in the Macros.h header file:

Code: Select all
#define EIGEN_WORLD_VERSION 2
#define EIGEN_MAJOR_VERSION 91
#define EIGEN_MINOR_VERSION 0


Regards,
Hauke
xhlhxjj
Registered Member
Posts
4
Karma
0
Hauke,

Sorry for the delay, I was been busy at work.

I downloaded the latest version of eigen (2.0.15) and the errors persisted.

The code that generated the errors that I posted in my previous post, was exactly the code that you posted.

That said, I played around with the code you posted and found that the code you posted did not include <Eigen/Array> which is apparently necessary for using Random.

Anyways, the code now looks like this:
Code: Select all
#include <iostream>

#include <Eigen/Core>
#include <Eigen/Array>

using namespace Eigen;

template <typename Derived>
int myfunction(MatrixBase<Derived> EIGEN_REF_TO_TEMPORARY variable)
{
  std::cout << variable << std::endl;
  return 0;
}


template <typename Derived>
int myfunction_not_backwardcompatible(MatrixBase<Derived>&& variable)
{
  std::cout << variable << std::endl;
  return 0;
}

int main()
{

   MatrixXd m = MatrixXd::Random(50,50);

   myfunction(m.block(1,1,2,2));
   myfunction_not_backwardcompatible(m.block(1,1,2,2));

   myfunction(m);
   myfunction_not_backwardcompatible(std::move(m));
   return 1;
}


And the only compile time error I am getting is the following:
Code: Select all
1>c:\users\deinesh\documents\visual studio 2010\projects\numericalmethods\numericalmethods\main.cpp(9): error C2146: syntax error : missing ',' before identifier 'variable'


which is caused by the below line:
Code: Select all
template <typename Derived>
int myfunction(MatrixBase<Derived> EIGEN_REF_TO_TEMPORARY variable)


Thanks again for the interest and I hope you can figure this out.

Thanks.
Hauke
Registered Member
Posts
109
Karma
3
OS
I don't recall all the changes since version 2 but the tutorial is for Eigen 3.0. We have a beta download ready at

http://eigen.tuxfamily.org/index.php?title=3.0-beta1

but you may as well try out the most recent version from the default branch. One of the changes is that <Eigen/Core> is now automatically including the array module which explains the error you have seen earlier. The other thing is that EIGEN_REF_TO_TEMPORARY does not exist in Eigen 2. If you need to stick to version 2, you can define it yourself as
Code: Select all
#define EIGEN_REF_TO_TEMPORARY const &


Good luck,
- Hauke
User avatar
bjacob
Registered Member
Posts
658
Karma
3
We really need to make it (even) more clear that the docs under dox-devel/ are for Eigen3: this is at least the second time that this has caused confusion!

Confirming that apparently the only thing you need is to replace EIGEN_REF_TO_TEMPORARY by const&


Join us on Eigen's IRC channel: #eigen on irc.freenode.net
Have a serious interest in Eigen? Then join the mailing list!
xhlhxjj
Registered Member
Posts
4
Karma
0
Thank you. You were most helpful.


Bookmarks



Who is online

Registered users: Bing [Bot], blue_bullet, Google [Bot], rockscient, Yahoo [Bot]