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

Returning a templated matrix

Tags: None
(comma "," separated)
damien_d
Registered Member
Posts
15
Karma
0

Returning a templated matrix

Thu Feb 16, 2012 8:02 am
Hello all,

I would like to write some generic functions returning a matrix type. I'm halfway there from the page: http://eigen.tuxfamily.org/dox/TopicFun ... Types.html

As an example:
Code: Select all
template <typename DerivedA,typename DerivedB>
typename DerivedA::Scalar squaredist(const Eigen::MatrixBase<DerivedA>& p1,
                 const Eigen::MatrixBase<DerivedB>& p2)
{
  return (p1-p2).squaredNorm();
}

template <typename DerivedReturn, typename DerivedA,typename DerivedB>
typename Eigen::MatrixBase<DerivedReturn> CalcDifference(const Eigen::MatrixBase<DerivedA>& p1,
                                     const Eigen::MatrixBase<DerivedB>& p2)
{
  return (p1-p2);
}

int main()
{
    Eigen::Vector3d v1(1, 2, 3);
    Eigen::Vector3d v2(4, 5, 6);
    std::cout << "Squared Distance = " << squaredist(v1,2*v2) << std::endl;
    std::cout << "Minus = " << CalcDifference(v1, v2);
}


Unfortunately, this does not compile:
Code: Select all
damien@damien-desktop:~/scratch/matlab/projects/UnscentedKalmanFilter$ g++ -O -o Test TestKK.cpp
TestKK.cpp: In function ‘int main()’:
TestKK.cpp:229:53: error: no matching function for call to ‘CalcDifference(Eigen::Vector3d&, Eigen::Vector3d&)’


I'm rather lost as what to do from here. Is there a simple way to do this, or is there an entirely different method that I need to follow?

-- Damien
User avatar
ggael
Moderator
Posts
3447
Karma
19
OS

Re: Returning a templated matrix  Topic is solved

Thu Feb 16, 2012 12:21 pm
first, in "typename Eigen::MatrixBase<DerivedReturn>", the typename does not make any sense. Second, Eigen::MatrixBase<DerivedReturn> is not a concrete type, you cannot create an object of that type. Third, your function has 3 template arguments and only two of them can be deduced by the compiler from the argument types.

I guess that your function will do some complex computations, and so you probably simply want to return a concrete matrix object. In that case , you could e.g., return a:

typename DerivedA::PlainObject
damien_d
Registered Member
Posts
15
Karma
0

Re: Returning a templated matrix

Thu Feb 16, 2012 11:08 pm
ggael wrote:I guess that your function will do some complex computations, and so you probably simply want to return a concrete matrix object. In that case , you could e.g., return a:

typename DerivedA::PlainObject


Exactly... I'm just trying to get my head around the template syntax first :)

Whilst I can see the DerivedA::PlainObject working for the same type as the first, what about if the matrix size is expected to change? For example, the multiply below:

Code: Select all
template <typename DerivedA,typename DerivedB>
typename DerivedA::Scalar squaredist(const Eigen::MatrixBase<DerivedA>& p1,
                 const Eigen::MatrixBase<DerivedB>& p2)
{
  return (p1-p2).squaredNorm();
}

template <typename DerivedA, typename DerivedB>
typename DerivedA::PlainObject Difference(const Eigen::MatrixBase<DerivedA>& p1,
                                          const Eigen::MatrixBase<DerivedB>& p2)
{
    return (p1 - p2);
}


template <typename DerivedA, typename DerivedB>
typename DerivedA::PlainObject Multiply(const Eigen::MatrixBase<DerivedA>& p1,
                                        const Eigen::MatrixBase<DerivedB>& p2)
{
    return (p1 * p2);
}

int main()
{
    Eigen::Matrix<double, 1, 3> v1(1, 2, 3);
    Eigen::Matrix<double, 1, 3> v2(4, 5, 6);
       
    std::cout << "Squared Distance  = " << squaredist(v1, 2*v2) << std::endl;
    std::cout << "Difference        = " << Difference(v1, 2*v2) << std::endl;
    std::cout << "Multiply Inline   = " << std::endl << v1.transpose() * v2 << std::endl;
    std::cout << "Multiply Function = " << std::endl <<  Multiply(v1.transpose(), v2) << std::endl;
}


Of course, the multiply function fails to compile, complaining of: "YOU_MIXED_MATRICES_OF_DIFFERENT_SIZES"

-- Damien
User avatar
ggael
Moderator
Posts
3447
Karma
19
OS

Re: Returning a templated matrix

Fri Feb 17, 2012 7:50 am
then you should return a Matrix<typename DerivedA::Scalar, ..., ...> where you replace the dots by the appropriate sizes computed using the DerivedA::RowsAtCompileTime, DerivedA::ColsAtCompileTime, etc. You have to be careful to correctly handle the cases where RowsAtCompileTime is Eigen::Dynamic, for instance if you have to multiply two dimensions....
damien_d
Registered Member
Posts
15
Karma
0

Re: Returning a templated matrix

Sun Feb 19, 2012 11:17 pm
Hi Gael,

The following seems to do the trick:

Code: Select all
template <typename DerivedA,typename DerivedB>
typename DerivedA::Scalar squaredist(const Eigen::MatrixBase<DerivedA>& p1,
                 const Eigen::MatrixBase<DerivedB>& p2)
{
  return (p1-p2).squaredNorm();
}

template <typename DerivedA, typename DerivedB>
typename DerivedA::PlainObject Difference(const Eigen::MatrixBase<DerivedA>& p1,
                                          const Eigen::MatrixBase<DerivedB>& p2)
{
    return (p1 - p2);
}


template <typename DerivedA, typename DerivedB>
Eigen::Matrix<typename DerivedA::Scalar, DerivedA::RowsAtCompileTime, DerivedB::ColsAtCompileTime>
Multiply(const Eigen::MatrixBase<DerivedA>& p1,
    const Eigen::MatrixBase<DerivedB>& p2)
{
    return (p1 * p2);
}

int main()
{
    Eigen::Matrix<double, 1, 3> v1(1, 2, 3);
    Eigen::Matrix<double, 1, 3> v2(4, 5, 6);
   
    // Set at compile time
    Eigen::MatrixXd m1(2, 3);
    Eigen::MatrixXd m2(3, 4);
   
    m1 << 6, 5, 4,
          3, 2, 1;
    
    m2 << 10, 11, 12, 13,
          14, 15, 16, 17,
     18, 19, 20, 21;
   
    Eigen::MatrixXd m3 = Multiply(m1, m2);
   
    // Re-size at run time
    m1.resize(3, 2);
    m2.resize(2, 4);
   
    m1 << 1, 2,
          3, 4,
     5, 6;
    
    m2 <<  7,  8,  9, 10,
          11, 12, 13, 14;
   
       
    std::cout << "Squared Distance  = " << squaredist(v1, 2*v2) << std::endl;
    std::cout << "Difference        = " << Difference(v1, 2*v2) << std::endl;
    std::cout << "Multiply Inline   = " << std::endl << v1.transpose() * v2 << std::endl;
    std::cout << "Multiply Function 0 = " << std::endl <<  m3 << std::endl;
    std::cout << "Multiply Function 1 = " << std::endl <<  Multiply(v1.transpose(), v2) << std::endl;
    std::cout << "Multiply Function 2 = " << std::endl <<  Multiply(m1, m2) << std::endl;
}


Thank you very much for your patience.

-- Damien
User avatar
ggael
Moderator
Posts
3447
Karma
19
OS

Re: Returning a templated matrix

Mon Feb 20, 2012 5:28 pm
you got it.


Bookmarks



Who is online

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