Re: [eigen] Minimal ei_traits?

[ Thread Index | Date Index | More Archives ]

It would take long to discuss all this and I really don't have time,
but here's my main criticism:

You are letting HermitianMatrix inherit MatrixBase, which means that
you're saying that it's addressable as a dense expression, using
accessors like

    coeff(int row, int col)

but the problem is that such an accessor can't be implemented very
efficiently (it has to do some runtime branching). So, letting
HermitianMatrix be used as dense expressions would be quite
inefficient. Instead, I would go for handling a HermitianMatrix as a
very special object on which only a few specific operations are
supported. So my inheritance diagram would be, basically:

EigenBase <--- HermitianMatrix

For inspiration you could look at DiagonalMatrix or BandMatrix or

Yes that means that expression templates are not available for these
classes, but it's quite OK as it's not needed anyway and/or would have
to be completely different (e.g. scalar*hermitian is no longer
hermitian unless scalar is real).

Oh and in Eigen we have aligned our terminology on SelfAdjoint instead
of Hermitian :-)

Finally, I still don't see, in what you said, a reason to use ei_traits.


2010/6/30 Manoj Rajagopalan <rmanoj@xxxxxxxxx>:
> I am attempting a SymmetricMatrix implementation modeled on what Eigen already
> does - hence the ei_traits question. I need this class because I really want
> to store only the triangular part - my application runs out of memory
> quickly. I am trying the rectangular packed format that Gael pointed out in
> an earlier mail.
>   Any suggestions, particularly on the class hierarchy, would be welcome. I
> am attaching a graphviz-generated diagram for comments from everyone. Maybe I
> can even submit a patch if I get it working :-)
> Thanks,
> Manoj
> On Wednesday 30 June 2010 03:36:11 pm Benoit Jacob wrote:
>> There is, and you can find that in Macros.h, in
>> EIGEN_DENSE_PUBLIC_INTERFACE, which is basically where ei_traits are
>> used:
>>   typedef typename Eigen::ei_traits<Derived>::Scalar Scalar; /*!<
>> \brief Numeric type, e.g. float, double, int or std::complex<float>.
>> */ \
>>   typedef typename Eigen::NumTraits<Scalar>::Real RealScalar; /*!<
>> \brief The underlying numeric type for composed scalar types. \details
>> In cases where Scalar is e.g. std::complex<T>, T were corresponding to
>> RealScalar. */ \
>>   typedef typename Base::PacketScalar PacketScalar; \
>>   typedef typename Base::CoeffReturnType CoeffReturnType; /*!< \brief
>> The return type for coefficient access. \details Depending on whether
>> the object allows direct coefficient access (e.g. for a MatrixXd),
>> this type is either 'const Scalar&' or simply 'Scalar' for objects
>> that do not allow direct coefficient access. */ \
>>   typedef typename Eigen::ei_nested<Derived>::type Nested; \
>>   typedef typename Eigen::ei_traits<Derived>::StorageKind StorageKind; \
>>   typedef typename Eigen::ei_traits<Derived>::Index Index; \
>>   enum { RowsAtCompileTime = Eigen::ei_traits<Derived>::RowsAtCompileTime,
>> \ ColsAtCompileTime = Eigen::ei_traits<Derived>::ColsAtCompileTime, \
>> MaxRowsAtCompileTime =
>> Eigen::ei_traits<Derived>::MaxRowsAtCompileTime, \
>>         MaxColsAtCompileTime =
>> Eigen::ei_traits<Derived>::MaxColsAtCompileTime, \
>>         Flags = Eigen::ei_traits<Derived>::Flags, \
>>         CoeffReadCost = Eigen::ei_traits<Derived>::CoeffReadCost, \
>>         SizeAtCompileTime = Base::SizeAtCompileTime, \
>>         MaxSizeAtCompileTime = Base::MaxSizeAtCompileTime, \
>>         IsVectorAtCompileTime = Base::IsVectorAtCompileTime }; \
>>   using Base::derived; \
>>   using Base::const_cast_derived;
>> Notice that NOT all of the above lines refer to stuff in ei_traits.
>> Those that do, tell you what ei_traits must provide.
>> But let me take this occasion to insist that the ONLY place where you
>> have to use ei_traits, is if you are hacking Eigen and adding or
>> modifying some base class underneath some expression class. If you are
>> just trying to get compile-time information on a given Eigen
>> expression type (or even if you are just coding some new expression
>> class for Eigen), you can access these typedefs and enum values right
>> off this type:
>> do:
>>      enum { myvalue = Derived::RowsAtCompileTime };
>>      typedef typename Derived::Scalar mytype;
>> and NOT (unless you are hacking Eigen's own base classes):
>>      enum { myvalue = ei_traits<Derived>::RowsAtCompileTime };
>>      typedef typename ei_traits<Derived>::Scalar mytype;
>> The only case where you have to do the latter, is when Derived is not
>> fully defined. You might ask how could this possibly happen? This
>> happens when you are inside of a template Base<Derived> class and
>> Derived inherits Base<Derived>. See the link I just mentioned about
>> the CRTP.
>> Now I know that there are many places in Eigen where we use ei_traits,
>> and that's unnecessary, so that's bad. A patch fixing that is always
>> welcome. Only use ei_traits if it's needed in order to compile.
>> Benoit
>> 2010/6/30 Manoj Rajagopalan <rmanoj@xxxxxxxxx>:
>> > hi eigen developers,
>> >
>> >   It is a little difficult to trace the various ei_traits because of
>> > their distribution and levels of inheritance? Is there a minimum set of
>> > typedefs, enums etc. that any ei_traits must
>> > declare/define/statically-compute?
>> >
>> > thanks,
>> > Manoj

Mail converted by MHonArc 2.6.19+