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

Lost in templates when extending Eigen

Tags: None
(comma "," separated)
arennuit
Registered Member
Posts
28
Karma
0
Dear all,

I am currently in the process of extending Eigen for my specific needs (using the plugins mechanism and some classes). I must admit I am lost between the base classes, the main classes, the derived idiom... and when to use these depending on the cases.

I currently copy function signatures from Eigen and adapt them to my needs and when it does not compile I try something else. I am definitely not keen on this way of going forward as I do not perfectly understand what is going on behind the hood or even may it be good practices to apply.

For QuaternionBase return types of methods for example, when looking at the Eigen implementation, some functions return a type "Quaternion<Scalar>", others a type "Derived&" and yet others "QuaternionBase&"... I am not sure why this is so and infer what type to use in which case from these observations...

Another example involving QuaternionBase methods arguments: it seems that for any argument using an Eigen type another template argument needs to be defined for the method. i.e.

Code: Select all
template<typename Derived1, typename Derived2, typename Derived3>
Derived myFunc(const QuaternionBase<Derived1>& inQuat, const MatrixBase<Derived2>& inMat1, const MatrixBase<Derived3>& inMat2);


I am not sure why...

Currently I have the feeling I need to understand deeply how Eigen is coded in order to be able to extend it.

Of course I have read the documentation, though things are not clear yet to me. Any tip on this one?

Kind regards,

Antoine.
User avatar
ggael
Moderator
Posts
3447
Karma
19
OS
This way to declare myFunc permits to accept any but only objects for which QuaternionBase (or MatrixBase) is a base class. You could also declare it as:

template<typename QuatType, ...> ... myFunc(const QuatType &q, ...)

but then myFunc can be called on anything and the compilation errors will be less obvious if the actual QuatType is not compatible with QuaternionBase.

The other questions are a bit too vague, please be more specific on your concerns.
arennuit
Registered Member
Posts
28
Karma
0
Thanks Gael, I will separate things in several questions and sharpen my descriptions.

I would like to extend classes Matrix and Quaternion so they compute some additional functions with Matrix<Scalar, 3, 1> as 'this', arguments, and return values.

With The Quaternions extension I can had the function below to the file defined in EIGEN_QUATERNIONBASE_PLUGIN:

Code: Select all
Vector3 myQuatFunc(const Vector3& myVec)
{
   // ...
}


But when I want to extend the Matrix class (using EIGEN_MATRIXBASE_PLUGIN), also to work on Matrix<Scalar, 3, 1>, I need to do

Code: Select all
PlainObject myMatFunc(const MatrixBase<Derived1>& myVec)
{
   // ...
}


1) Is there a way to enforce at compile-time that myVec has size (3, 1), i.e. specifying a Matrix<Scalar, 3, 1> argument type for myMatFunc ?

2) Is there a way to enforce at compile-time that 'this' has size (3, 1)? Do we need to test it at run-time? It is the same problem for function 'cross' which can only work on 3D vectors, so how is it done in there? I had a look to the code but I must admit I got lost...

Kind regards,

Antoine.
User avatar
ggael
Moderator
Posts
3447
Karma
19
OS
The Eigen way is to add the following in the body of your function:
Code: Select all
template<typename OtherDerived>
PlainObject myMatFunc(const MatrixBase<OtherDerived>& myVec) {
  EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(Derived,3)
  EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(OtherDerived,3)
  ...
}

this will trigger a readable compilation error. An alternative is to use the enable_if mechanism, but that solution pollutes the prototype, e.g.:
Code: Select all
template<typename OtherDerived>
typename internal::enable_if<SizeAtCompileTime==3 && IsVectorAtCompileTime
                             && OtherDerived::SizeAtCompileTime==3 && OtherDerived::IsVectorAtCompileTime, PlainObject>::type
myMatFunc(const MatrixBase<OtherDerived>& myVec) { ... }
arennuit
Registered Member
Posts
28
Karma
0
Wow, this is really unusual to me... But that definitely does the trick, thanks!


Bookmarks



Who is online

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