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

Two questions from Eigen newbie

Tags: None
(comma "," separated)
p0wertripper
Registered Member
Posts
6
Karma
0

Two questions from Eigen newbie

Wed Dec 07, 2011 8:55 pm
I am a new eigen user. In fact, I am trying to make a move from MATLAB to C++. So, sorry in advance if these topics have been covered in some known source or the answers are really obvious.

1). I would like to know if dynamically allocated Eigen matrices can always be treated as normal C++ arrays when trying to read them using pointers. For example, will I always (even after resizing the matrix) be able to do something like this:

Code: Select all
MatrixXd X(3,3);
X(0,0)=...
...
double *p;
p=&X(0,0);
cout << *p << *(p+1) << ...//can all elements of the matrix can be accessed consequentially this way?


2). Does Eigen create a copy of the object that it returns from a function?

For example:

Code: Select all
VectorXd DampedOscillator(const VectorXd& v, const VectorXd& p) {
  VectorXd vdot(2);
  vdot(0)=v(1);
  vdot(1)=-2*p(0)*p(1)*v(1)-p(1)*p(1)*v(0);
  return vdot;
}


Then in main

Code: Select all
  VectorXd p(2);
  p(0)=1;
  p(1)=2;
 
  VectorXd v_0(2);
  v_0(0)=0;
  v_0(1)=1;
 
  VectorXd z(2);
  z(0)=1;
  z(1)=2;
 
  z=DampedOscillator(v_0,p);


Will only the reference be passed when function returns value to variable "z" or it will be copied into the place where previous z vector elements were? In case of the latter what is the best way of passing both the reference and size of the matrix/vector to avoid unnecessary copying?
Andre
Registered Member
Posts
90
Karma
1

Re: Two questions from Eigen newbie

Wed Dec 07, 2011 11:01 pm
Hi p0wertripper,

1) The short answer is no. The long answer is that it depends. First, there is a .data() method that returns a pointer to the data array. But Eigen uses different ways to store the data, both concerning the layout (ColumnMajor vs. RowMajor) and the memory itself. E.g. a sparse matrix is usually stored as three arrays instead of one. So if you are only using dense matrices and are sure of the storage order it should work afaik.

2) This will return by value, meaning that the values in z will be overwritten. You can pass in a reference that you modify, or return a reference of a variable you pass in. Of course you can also use pointers (to non-local variables).

> In case of the latter what is the best way of passing both the reference
> and size of the matrix/vector to avoid unnecessary copying?

If you pass the function a reference to the matrix, it will know its dimension at runtime anyway.

But more generally, you seem to know the dimension of your vectors/matrices. It is better to use the fixed size types than, e.g. Vector2d, Vector3d, Matrix2d, Matrix3d, etc. Eigen will be able to optimise the calculations on these objects much better than.


'And all those exclamation marks, you notice? Five? A sure sign of someone who wears his underpants on his head.' ~Terry Pratchett

'It's funny. All you have to do is say something nobody understands and they'll do practically anything you want them to.' ~J.D. Salinger
p0wertripper
Registered Member
Posts
6
Karma
0

Re: Two questions from Eigen newbie

Thu Dec 08, 2011 9:24 pm
Thanks for quick reply. However, I made a little mistake in one of my questions.

Andre wrote:If you pass the function a reference to the matrix, it will know its dimension at runtime anyway.

Sorry for ambiguity. My real question was what is the best way to return a pointer to an Eigen variable (for now lets concentrate on dense matrices) from a function? For example, I have a function where I create a matrix dynamically on heap. Does Eigen provide a standard procedure that can be used for returning a pointer to the matrix in such way as not to loose its dimensions?

The obvious way that I see for doing it is

Code: Select all
VectorXd* DampedOscillatorRef(const VectorXd& v, const VectorXd& p) { 
  VectorXd* vdot(NULL);
  vdot=new VectorXd(2);
  (*vdot)(0)=v(1);
  (*vdot)(1)=-2*p(0)*p(1)*v(1)-p(1)*p(1)*v(0); 
  return vdot;
}


and then in main:

Code: Select all
VectorXd* x;
  x=DampedOscillatorRef(v_0, p);
  cout << *x;


It works quite well. However, I am not sure if there is any potential danger in doing such thing (especially for large 2D matrices).

Is it in any way possible to return a pointer to a vector with the size unknown during the allocation? Can anything go wrong here?

Code: Select all
VectorXd* DampedOscillatorRef(const VectorXd& v, const VectorXd& p) { 
  VectorXd* vdot(NULL);
  vdot=new VectorXd;
  (*vdot).resize(2,1);
  (*vdot)(0)=v(1);
  (*vdot)(1)=-2*p(0)*p(1)*v(1)-p(1)*p(1)*v(0); 
  return vdot;
}
jitseniesen
Registered Member
Posts
204
Karma
2

Re: Two questions from Eigen newbie

Fri Dec 09, 2011 8:41 am
Variables of the type VectorXd (as well as the other Eigen types) contain both the dimensions and the entries of the vector. So returning a pointer to a VectorXd will not cause you to lose the dimension. Your code will work. The only problem is that you have a memory leak if you forget to delete the memory you allocated with new (and it is very easy to forget this). If you have large matrices and long simulations even small leaks can become disastrous. As Andre said, you can avoid this by passing a reference (or pointer) to the matrix you want to assign to:

Code: Select all
void DampedOscillatorRef(const VectorXd& v, const VectorXd& p, VectorXd& result)
mattd
Registered Member
Posts
28
Karma
0

Re: Two questions from Eigen newbie

Mon Dec 12, 2011 4:31 am
I've got a question related to #2 & #3 -- are the any plans to incorporate move-semantics as introduced in C++11 (but there's a portable way to support this in C++03-compliant compilers I believe, see below) -- in particular, to implement move constructors and move assignment operators for the relevant classes?

This would allow for the Eigen objects to be moved-out from the functions (instead of copied-out) while maintaining, from the client-code point of view, simple code that gives the illusion of returning by value, as in std::vector in C++11-compliant compilers: http://cpp-next.com/archive/2009/08/wan ... -by-value/

Incidentally, there might be a (N)RVO performed even in C++03-compliant compilers, so perhaps there's no need to use pointers or references even in cases such as DampedOscillatorRef and keep the code as in the first example of DampedOscillator?

Interestingly, as of Boost Version 1.48.0, there's a new library, Boost.Move which "emulates C++0x move semantics in C++03 compilers and allows writing portable code that works optimally in C++03 and C++0x compilers":
http://www.boost.org/doc/libs/release/d ... /move.html


Bookmarks



Who is online

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