Re: [eigen] still the solve() API debate

[ Thread Index | Date Index | More Archives ]

2009/9/10 Keir Mierle <mierle@xxxxxxxxx>:
> On Thu, Sep 10, 2009 at 2:47 PM, Gael Guennebaud <gael.guennebaud@xxxxxxxxx>
> wrote:
>> oh, actually we can even write a single
>> SolveReturnType<DecomositionType, DerivedB> class inheriting
>> ReturnByValue which would be used for all x = solve(b) functions.
> I am not convinced the added complexity justifies the benefits. What about
> using the result in an expression?
> y = M*A.solve(b); // Parts of my code could use this today.

My understanding is that Gael is now proposing a ReturnByValue class
that inherits MatrixBase, so that one could use that in any
expression. That's a departure from my assumption that he was
proposing ReturnByValue not inheriting MatrixBase.

Gael : is that right?

> x.start(3) = A.solve(b) // Never used this.
> Not saying that the 2nd use case isn't justified, just that I personally
> haven't needed it. Can others speak to this?

Same here, I don't think use cases are common. I can think of one:
when implementing a blocked algorithm (e.g. block LU), sometimes some
of the blocks can be obtained as a matrix solve.

However, for such complex use cases, I think that it wasn't too bad
(although not wonderful either) to force using named xpr objects
instead of temporaries.

As Keir notes, here we're giving a lot of weight to a quite unusual
use case. I don't think it's worth going for option 4 just for that
use case, as that would make the API heavier for everybody just to
make it lighter in that unusual use case.

>> On Thu, Sep 10, 2009 at 11:37 PM, Gael Guennebaud
>> <gael.guennebaud@xxxxxxxxx> wrote:
>> > you forgot the main advantage of sol 3 and 4 that is to be able to use
>> > temporary proxy object without having to declare them, e.g.:
>> >
>> > opt 3:  x.start(n) = A.solve(b);        // works without temporary

You're right, I was forgetting about that unusual use case, but again,
i've never met it outside of the implementation of blocked algorithms.

Now it's true that it has intrinsic value, and that it's a good goal
for our API design to fully support the seamless implementation of
blocked algorithms.

My main concern, like Keir, was that this option 3 wouldn't allow the
result of solve() to be used in expressions, because you earlier said
that ReturnByValue shouldn't inherit MatrixBase. Now I didn't think as
much as you did about this, but now you say,

>> >
>> > So why not giving a try to opt. 3 ? Indeed, actually the multiple
>> > matrix products are now implemented using something very very similar
>> > to opt 3 with a ReturnByValue inheriting MatrixBase, and they are not
>> > that heavy.

Ah OK, so now we're again discussing a ReturnByValue that inherits
MatrixBase. So option 3 indeed looks pretty good, can be used in any

>> > What I mean is that all the limitations of opt.3 with a
>> > ReturnByValue inheriting MatrixBase already exists with the matrix
>> > products...  (the limitation is tha the NestByValue flag *must* be
>> > honored, otherwise you have a weird (currently) compilation error).

OK, that's not too bad, especially as, as you said, this issue already
exists with all the products (and there it really is the best solution

At least we'll have some uniformity. What's needed then is a good dox
page on writing functions that take MatrixBase as argument.

>> > Now, honestly I don't really like to use pointers for return types,
>> > unless they are optional.

Do you mean: as opposed to natural syntax, result = function() ? As in option 3.
Then I can understand. Me too, i prefer natural syntax!

Or do you mean: as opposed to function(result.ref()) or passing by c++
reference? Then I need to ask, why? What is bad about pointer, as
opposed to references or custom structs? OK custom structs allow
passing temporaries, but are you also saying that you prefer c++
references over pointers? Then I really would like to know why.


Mail converted by MHonArc 2.6.19+