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

specific matlab operations in eigen

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

specific matlab operations in eigen

Thu Oct 14, 2010 6:39 pm
Hi,
I am new to libeigen and have recieved the task to port some matlab code snippets to C++.
I have read the Core Tutorialbut have some questions about how to reimplement few Matlab functions for use with eigen (if they are not already available..)

repmat [Link to Doc]
B = repmat(A,m,n) creates a large matrix B consisting of an m-by-n tiling of copies of A. The size of B is [size(A,1)*m, (size(A,2)*n]. The statement repmat(A,n) creates an n-by-n tiling.
I think in pseudocode it should be reproducable by something like ones(m,n).*.A , but what is the best way to do it in eigen, using VectorXf as example.

meshgrid [Link to Doc]
Is there a simpel way to reproduce a matlab call like [X,Y] = meshgrid(1:3,10:14) without loops or something? The first problem I see is returning 2 matrices from a function, the second is I haven't found the matlab ":" operator, and I think I can only emulate it using a loop.

reshape [Link to Doc]
B = reshape(A,m,n) returns the m-by-n matrix B whose elements are taken column-wise from A. An error results if A does not have m*n elements.

Is any of this functionality already present in eigen and could I only not find it? Or has anyone suggestions on how to implement them in an elegant way?

regards,
Ismael
User avatar
ggael
Moderator
Posts
3447
Karma
19
OS
repmat

e.g., dst = src.replicate(n,m);

see http://eigen.tuxfamily.org/dox-devel/cl ... 4e4b103032

meshgrid

you can mix LinSpaced and replicate:

X = RowVectorXd::LinSpaced(1,3,3).replicate(5,1);
Y = VectorXd::LinSpaced(10,14,5).replicate(1,3);

see: http://eigen.tuxfamily.org/dox-devel/cl ... a9c6ae34d8

reshape

Currently you can mimic it using Map:

B = Map<MatrixXd>(A.data(),m,n);
FMD
Registered Member
Posts
25
Karma
0
IsmaelNetzel
Registered Member
Posts
6
Karma
0
Thanks for your fast help and explanations FMD and ggael :)
The QuickReference is realy great.

One thing however I couldn't find out myself.
I have to work most of the time with dynamic-sized vectors and need
to do something like this in matlab (simplified example):
Code: Select all
 a = [a; ones(10, 1)*17];

so I can use VectorXi b = VectorXi::Ones(10,1)*17 or VectorXi b = VectorXi::Constant(10,1,17); to compute the second part.
But how can I then combine them to one?
I could not find anything in the QuickReference as it mostly shows operations with matrices.

Do I have to manually resize a to the length of a+b, and then copy the values over in a loop? This seems to be a costly operation, and since I have to do it thousand of times I would like to implement it the right way.

thanks,
Ismael
User avatar
bjacob
Registered Member
Posts
658
Karma
3
You can do:

Code: Select all
result << a , VectorXi::Constant(10,1,17);


if the result is not the same matrix as a. However if it is a itself that you are extending, with eigen 3, you can do this:

Code: Select all
a.conservativeResize(a.size() + 10);
a.tail(10) = VectorXi::Constant(10,1,17);


Join us on Eigen's IRC channel: #eigen on irc.freenode.net
Have a serious interest in Eigen? Then join the mailing list!
someguy
Registered Member
Posts
14
Karma
0
ggael wrote:reshape

Currently you can mimic it using Map:

B = Map<MatrixXd>(A.data(),m,n);


Looks like this is affected by the matrix order. If A uses column-major, I don't think that your technique will produce the desired result. Can you please confirm??
someguy
Registered Member
Posts
14
Karma
0
someguy wrote:
ggael wrote:reshape

Currently you can mimic it using Map:

B = Map<MatrixXd>(A.data(),m,n);


Looks like this is affected by the matrix order. If A uses column-major, I don't think that your technique will produce the desired result. Can you please confirm??

I'm including source code to show this is the case:

Code: Select all
$ cat test_eigen_reshape.cpp
#include <Eigen/Core>
#include <Eigen/Array>

USING_PART_OF_NAMESPACE_EIGEN

typedef Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic> EigenMatrixDbl;


int main(int argc, char** argv)
{
        EigenMatrixDbl m(3, 4);
        m << 1, 2, 3, 3.5,
             4, 5, 6, 6.5,
             7, 8, 9, 9.5;

        std::cout << m << std::endl;

        const EigenMatrixDbl::RowXpr &first_row = m.row(0);

        std::cout << first_row << std::endl;

        Eigen::Map<EigenMatrixDbl> B = Eigen::Map<EigenMatrixDbl>(first_row.data(),2,2);

        std::cout << B << std::endl;

        return 0;
}



Code: Select all
$ g++ -o test_eigen -I./eigen test_eigen_reshape.cpp && ./test_eigen
1 2 3 3.5
4 5 6 6.5
7 8 9 9.5

1 2 3 3.5

1 7
4 2


This is wrong. The last result should be:

Code: Select all
1 2
3 3.5


Instead of:

Code: Select all
1 7
4 2


Any clue on how to get the right result??
Hauke
Registered Member
Posts
109
Karma
3
OS
someguy wrote:Any clue on how to get the right result??


In Eigen3 you can make use of the Stride object

Stride<Dynamic,Dynamic> stride(3,6);
const auto B = EigenMatrixDbl::Map(m.data(), 2, 2, stride);

but again, your result will depend on the memory layout. Right now we don't have a "real" reshape.

- Hauke
someguy
Registered Member
Posts
14
Karma
0
Hauke wrote:In Eigen3 you can make use of the Stride object

Stride<Dynamic,Dynamic> stride(3,6);
const auto B = EigenMatrixDbl::Map(m.data(), 2, 2, stride);


Thanks, but I use 2.0.15. Version 3 is still in Beta.

Hauke wrote:but again, your result will depend on the memory layout. Right now we don't have a "real" reshape.


This is what I came up with:
Code: Select all
#include <Eigen/Core>
#include <Eigen/Array>

USING_PART_OF_NAMESPACE_EIGEN

typedef Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic> EigenMatrixDbl;
typedef Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor> EigenMatrixDblRowMajor;


int main(int argc, char** argv)
{
        EigenMatrixDbl m(3, 4);
        m << 1, 2, 3, 3.5,
             4, 5, 6, 6.5,
             7, 8, 9, 9.5;

        std::cout << m << std::endl << std::endl;

        const EigenMatrixDbl::RowXpr &first_row = m.row(0);
            
   std::cout << first_row << std::endl << std::endl;

   Eigen::Map<EigenMatrixDbl> B = Eigen::Map<EigenMatrixDbl>(first_row.data(),2,2);

   std::cout << B << std::endl << std::endl;

   EigenMatrixDblRowMajor n(1, m.cols());
   n << first_row;
            
   Eigen::Map<EigenMatrixDblRowMajor> C = Eigen::Map<EigenMatrixDblRowMajor>(n.data(),2,2);            
   std::cout << C << std::endl << std::endl;

        return 0;
}



Messy, but seems to work

More generically, for a matrix, the following code should give the correct reshape:
Code: Select all
#include <Eigen/Core>
#include <Eigen/Array>

USING_PART_OF_NAMESPACE_EIGEN

typedef Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic> EigenMatrixDbl;
typedef Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor> EigenMatrixDblRowMajor;

int main(int argc, char** argv)
{
        EigenMatrixDbl m(3, 4);
        m << 1, 2, 3, 3.5,
             4, 5, 6, 6.5,
             7, 8, 9, 9.5;

        std::cout << m << std::endl << std::endl;


        EigenMatrixDblRowMajor n(3, 4);
        n << m;
        std::cout << n << std::endl << std::endl;

        Eigen::Map<EigenMatrixDblRowMajor> B2 = Eigen::Map<EigenMatrixDblRowMajor>(n.data(),4,3);

        std::cout << B2 << std::endl << std::endl;

        return 0;
}
krisrose
Registered Member
Posts
6
Karma
0
Hi,

I too am looking for a conversion from Matlab to Eigen on repmat, specifically this line.

X = X ./ repmat( sum(X, 1), size(X, 1), 1 );

My initial thoughts were to use a cwiseQuotient and a replicate with the relevant eigen reduction calls but this doesn't seem to be working.

Any ideas would be great! :)

Thanks,
Kris
User avatar
ggael
Moderator
Posts
3447
Karma
19
OS
What about the following (not tested:
Code: Select all
X = X.array().rowise() / X.colwise().sum().array();


Bookmarks



Who is online

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