Re: [eigen] Re: VectorBase issue

[ Thread Index | Date Index | More Archives ]

ok, so I quickly tried that:

// some constants:
const int CommonMethods = 0;
const int VectorMethods = 1;
const int MatrixMethods = 2;
const int QuaternionMethods = 3;

// forward declarartion of the xpr base class:

template<typename Derived,
  int XprClass =
      ei_traits<Derived>::Flags&QuaternionBit ? QuaternionMethods
    :   (ei_traits<Derived>::RowsAtCompileTime==1
      || ei_traits<Derived>::ColsAtCompileTime==1) ? VectorMethods
    : MatrixMethods
> class XprBase;

// specialisations:

template<typename Derived> class XprBase;<Derived,CommonMethods>
// the actual MatrixBase from which we could remove very matrix specific stuff like QR, eigenvalues, inverse, etc...

template<typename Derived>
class XprBase<Derived,MatrixMethods> : public XprBase<Derived,CommonMethods>
// could contains very matrix specific stuff like QR, eigenvalues, inverse, etc...

Note that XprBase inherits itself !

template<typename Derived>
class XprBase<Derived,VectorMethods> : public XprBase<Derived,CommonMethods>
// vector code coeff, block, dot, norm, etc...

template<typename Derived>
class XprBase<Derived,QuaternionMethods> : public XprBase<Derived,VectorMethods>
// the quaternion implementation inherits vector's methods and overloads and can safely define its own overloads, e.g.:
Cross<Block<Derived,3,1>,Block<Derived,3,1> >
cross(const XprBase<OtherDerived,QuaternionMethods>& other) { return start<3>().cross(other.start<3>()); }

I currently have a problem with the generic constructors and operator= of Matrix and XprBase... but I guess it's because I'm doing something wrong.

I practice it seems that slightly increases the compilation time :( .... not that much but I will investigate that, maybe it can be cut down again.
On the other hand I think that's by far the best solution to allow proper method overloading as required by Quaternion and probably the homogeneous stuff...
 (other solutions are:
   1 - add some kind of "if(quaternion)" inside the method definitions
   2 - duplicate codes and forgot xpr template for them (or duplicate the whole ET framework !) )

maybe, if the MatrixMethods variant is kept empty, matrix xpr would direclty inherits the common XprBase class such that the compilation time should be less affected... maybe ...

Regarding the documentation, you should bet one page per specialization that sounds good to me.

Gael, very happy since he gets an INRIA researcher position in Bordeaux :-)

On Wed, Jun 4, 2008 at 6:27 PM, Gael Guennebaud <gael.guennebaud@xxxxxxxxx> wrote:

ok so let me summaries the situation with the following proposal:

 keep VectorMethods as initially described with a duplication of derived().
 the conflicting method name issue is resolved with the "using" keywords in MatrixBase
 and a list of corresponding enum in VectorMethods<Derived,false>.
 Using enums seems lighter than empty methods with a static assertions, and it's much better since the behavior is exactly what we want.
 (the compiler won't try to do anything with these enums even if you write "cout << m.block;" ...

this time I don't see any drawbacks....

now what about splitting Matrix to Matrix and Vector ? This sounds interesting because in Matrix there is almost no intersection between vector specific method and matrix specific methods (there is only the assignment operators defined using macros, so no big deal)

The problem I see is with respect to the evaluation mechanism that may become more complicated....

On the other hand we more or less already have such problems with quaternion: (q0+q1).eval() is not a quaternion anymore.... well, the pb is even more general:  (q0+q1).conjugate() won't work, instead you have to write : Quaternion<>(q0+q1).conjugate() that requires an additional evaluation...
This problem suggest a QuaternionBit flag that would be inherited, plus a QuaternionMethods base class inherited by MatrixBase if the flag is presents. This would work for slerp()  (spherical interpolation) because it is not defined in MatrixBase but not for conjugate that is overloaded in MatrixBase.... So what about the following class hierarchy:

Common<Derived> ----- VectorMethods<Derived> ----- XprBase<Derived> ----- Matrix / Quaternion / AnyExpression....
Common<Derived> ----- QuaternionMethods<Derived>

Basically, Common corresponds to the actual MatrixBase and XprBase would be a selector.... for that scheme works, it is very important that the methods in Common<> call .derived().....

This does not address the evaluation pb, but this is a first step towards the overkillification ;)


On Wed, Jun 4, 2008 at 4:46 PM, Gael Guennebaud <gael.guennebaud@xxxxxxxxx> wrote:

On Wed, Jun 4, 2008 at 3:51 PM, Benoît Jacob <jacob@xxxxxxxxxxxxxxx> wrote:
OK I can see now that you had mentioned this as solution 2c:

> c - define the overload in 2D matrix specific base class, i.e. in
> VectorBase<Derived,false>:
>       class VectorBase<Derived,false> {
>        Scalar coeff(int,int);
>        etc.
>       };
>    However this approach makes impossible to write generic code on
> fixed-size matrix that might degenerate to vector of even 1x1 matrices...

It took me a while to sort my thoughts on this issue!

hm.. yes that wasn't very explicit, sorry.

I found something that might help:

if you declare in MatrixBase:

using VectorBase<Derived>::block;
using VectorBase<Derived>::coeff;

then it's almost OK. the last remaining pb is that VectorBase<Derived,false> doesnot provide any block or coeff methods... adding them would be somehow stupid... but maybe a last trick will show up, let's wait for the illumination !

You know what.... nothing prevents us from implementing coeff(int,int) also in
VectorBase, with an assert!

Does that solve this issue?



Mail converted by MHonArc 2.6.19+