> gael.
>
>>
>> Benoit
>>
>> > The
>> > problem is that in most cases you don't only want simple product, but
>> > you
>> > also want to be able to take the adjoint of the factors, do some scaling
>> > and
>> > maybe accumulate the result at the same time. This is not an hazard if
>> > the
>> > BLAS GEMM routine does all that in a single call. To make thing clear
>> > let me
>> > recall that GEMM allow to do:
>> >
>> > C = C + alpha * op(A) * op(B)
>> >
>> > However to support this kind of high level products we need to be able
>> > to
>> > build an _expression_ tree containing Transpose, CwiseUnaryOp, and
>> > Product.
>> > Whence the "no".
>> >
>> > Now let's consider an arbitrary fancy storage Foo. A funny thing with my
>> > proposal is that if you implement the product for the Foo storage as we
>> > did
>> > for the dense path (i.e., via a kind of GEMM routine), then you even
>> > don't
>> > need to implement the specialization of {Transpose|CwiseUnaryOp}Impl for
>> > the
>> > storage Foo ! Whence the "yes".
>> >
>> > Nevertheless, both Transpose and CwiseUnaryOp are usually trivial to
>> > implement. The most difficult ones are Block, CwiseBinary, and partial
>> > reductions which are less useful.
>> >
>> > Gael.
>> >
>> >>
>> >> I agree about all the rest. And it's true that your changes, which are
>> >> useful anyway, would also be the first thing to do if one wanted
>> >> arithmetic operators for special matrices. Finally, such operators and
>> >> _expression_ templates can be added at a later date.
>> >>
>> >> Benoit
>> >>
>> >> 2009/11/13 Gael Guennebaud <
gael.guennebaud@xxxxxxxxx>:
>> >> >
>> >> >
>> >> > On Fri, Nov 13, 2009 at 9:46 PM, Benoit Jacob
>> >> > <
jacob.benoit.1@xxxxxxxxx>
>> >> > wrote:
>> >> >>
>> >> >> 2009/11/13 Gael Guennebaud <
gael.guennebaud@xxxxxxxxx>:
>> >> >> >
>> >> >> >
>> >> >> > On Fri, Nov 13, 2009 at 8:58 PM, Benoit Jacob
>> >> >> > <
jacob.benoit.1@xxxxxxxxx>
>> >> >> > wrote:
>> >> >> >>
>> >> >> >> Hi,
>> >> >> >>
>> >> >> >> Wow, your mail took me a lot of effort to understand, I think
>> >> >> >> it's
>> >> >> >> mostly ok now...
>> >> >> >>
>> >> >> >
>> >> >> > sorry for that, I should have been more explicit.
>> >> >> >
>> >> >> >>
>> >> >> >> First of all, I agree with your summary of current limitations.
>> >> >> >> Yes,
>> >> >> >> I
>> >> >> >> agree we must take care of that before beta1.
>> >> >> >>
>> >> >> >> Let me rephrase some stuff in my own baby words to see if i got
>> >> >> >> it
>> >> >> >> right. The 2 basic problems you want to address are:
>> >> >> >> * code sharing between dense and sparse xpr
>> >> >> >> * in xpr trees, only the leaves should be affected by what the
>> >> >> >> leaves
>> >> >> >> actually are.
>> >> >> >>
>> >> >> >> The "naive" approach to that would probably be to let e.g.
>> >> >> >> Transpose
>> >> >> >> and SparseTranspose inherit a common base AnyTranspose, making it
>> >> >> >> a
>> >> >> >> curious base so AnyTranspose<Derived>... then .transpose()
>> >> >> >> methods
>> >> >> >> should return objects of AnyTranspose<Derived> which is ugly and
>> >> >> >> may
>> >> >> >> (out of empirical experience) give compiler warnings about strict
>> >> >> >> aliasing when casting the returned object to the derived type.
>> >> >> >>
>> >> >> >> So your solution, if I understand well, consists instead in
>> >> >> >> letting
>> >> >> >> Transpose itself be a template in one more integer parameter,
>> >> >> >> which
>> >> >> >> you call StorageType, which could have special values Dense,
>> >> >> >> Sparse,
>> >> >> >> Band...
>> >> >> >>
>> >> >> >> At this point, I think I have understood how you solve the "the
>> >> >> >> rest
>> >> >> >> of the tree doesn't completely change if the leaves are
>> >> >> >> different"
>> >> >> >> problem.
>> >> >> >>
>> >> >> >> But can you enlighten me as to how you solve the "code sharing"
>> >> >> >> problem? If Transpose<Dense> and Transpose<Sparse> can share
>> >> >> >> code,
>> >> >> >> where do you put that? In a common base class TransposeBase? So
>> >> >> >> that
>> >> >> >> problem and solution is actually completely orthogonal to the
>> >> >> >> above?
>> >> >> >
>> >> >> > What I suggest is a bit different. Let's pick an example:
>> >> >> >
>> >> >> > template<MatrixType> Transpose : public TransposeImpl<MatrixType,
>> >> >> > ei_traits<MatrixType>::StorageType>
>> >> >> > {
>> >> >> > int rows();
>> >> >> > int cols();
>> >> >> > MatrixType::Nested m_matrix;
>> >> >> > // etc.
>> >> >> > }
>> >> >> >
>> >> >> > then TranposeImpl<MatrixType,Dense> would inherit
>> >> >> > MatrixBase<Transpose<>
>> >> >> > >
>> >> >> > and implements the coeff() methods while
>> >> >> > TransposeImpl<MatrixType,Sparse>
>> >> >> > would inherit SparseMatrixBase<> and implement the InnerIterators
>> >> >> > mechanism.
>> >> >>
>> >> >> ok so actually in your scheme, the code sharing happens in the
>> >> >> derived
>> >> >> class Transpose, while the non-shared implementation happens in the
>> >> >> base class TransposeImpl.... clever!
>> >> >>
>> >> >> What I like the most here is that the class that is used as a node
>> >> >> in
>> >> >> the xpr tree, Transpose, doesn't get any additional template
>> >> >> parameter: our xpr trees were already complex enough like that...
>> >> >>
>> >> >> Are you going to set up a new fork for that? And add it to the
>> >> >> todo-3.0 page? It seems quite a long project to complete.
>> >> >
>> >> > yep, this is definitely not a trivial change, so of course I'll start
>> >> > a
>> >> > fork
>> >> > for that and we'll see!
>> >> >
>> >> > gael
>> >> >
>> >> >>
>> >> >> Benoit
>> >> >>
>> >> >>
>> >> >
>> >> >
>> >> >
>> >> >
>> >> >
>> >>
>> >>
>> >
>> >
>> >
>> >
>>
>>
>
>
>
>