Re: [eigen] On a flexible API for submatrices, slicing, indexing, masking, etc.

[ Thread Index | Date Index | More lists.tuxfamily.org/eigen Archives ]




On Thu, Jan 5, 2017 at 11:07 AM, Gael Guennebaud <gael.guennebaud@xxxxxxxxx> wrote:


On Thu, Jan 5, 2017 at 4:13 PM, Yuanchen Zhu <yuanchen.zhu@xxxxxxxxx> wrote:


On Thu, Jan 5, 2017 at 6:06 AM, Gael Guennebaud <gael.guennebaud@xxxxxxxxx> wrote:

I added a list of examples comparing aseq (inclusive), aseqn, a aseqX version with exclusive upper-bound, python, and the experimental "_expression_-based" API:


From these examples, having aseq inclusive still seems to be more handy, and the size-based aseqn function is still there for some simple cases for which an exclusive upper-bound is more handy.

They also show that having both a end and last "keyword" might be handy, but not mandatory..

Finally, these examples also reveal that the "_expression_-based" API outperforms all other alternatives, in all cases. For instance, can you guess the intent from the following python code:

A[:-(k-1)*s-2:-s] ?????

compared to:

A(last-iota(k)*s)

??

The solution is: "pick k elements from the last one with step s in descending order".

For the record, the aseq-based version is:

A(aseq(last,last-(k-1)*s,-s))

​Interesting. Note the identity

aseqn(a, n, d) == ​a + iota(n) * d

So the ideal way to write what you have, one uses aseqn:

A(aseqn(last, k, -s))


right, I made a mistake when writing the aseqn version.

 
This also means that iota easily covers usage case of aseqn. And this iota based _expression_ is not that more complex than aseqn.

On the other hand, aseq is not so easily implemented by iota, since iota requires the length to be known.

In the wiki, you seem to write

aseq(a, b, d) = a + iota * d <= b when (d > 0)

I am actually confused how you parse this. a + iota * d = [a, a + d, a + 2d, ....]. When you compare that with b, you get a boolean mask, no? By a + iota* d <= b, you really mean

x[x <= b] where x = (a + iota * d)

see some previous answer:

"Perhaps I should have better explained this notation. With 'lo <= expr <= hi', the generated values are the one produced by 'expr' that matches the given bounds. Omitted bounds are implicitly implied by the underlying vector/matrix. In 'Iota*2+1', the symbol 'Iota' is just a mean to say enumerate all integers in ascending order. '-Iota' == same but in descending order. Here 0-based indexing is very welcome because in -Iota the first element remains the same, otherwise it would be a complete mess! "
 

Is this iota comparison syntax standard in APL or elsewhere?

I don't know much about APL, I've been inspired by this post:


for the size-based version first+iota(size)*step, and then came up with the use of comparison operators to cover the aseq(first,last) version. Last Massimilliano's post seems to imply that APL also uses this strategy to define bounds...


Just from googling around, I couldn't confirm APL allows this.

We already established that iota is basically aseqn. I think the notational advantage is that you can omit the "first", "incr" parameter when they're not needed. Also you have a natural notation for the common case where incr is fixed<-1>, just put "-" in front of iota.

aseqn(0, n) = iota(n)
aseqn(0, n, fix<-1>) = -iota(n)
aseqn(0, n, s) = iota(n) * s 
aseqn(a, ....) = a + ...

We now just need a syntax to cover aseq. But I really don't think "<" is a good choice.

If we view the result of iota and iota(n) as a pseudo vector, then the meaning of iota < C should not be different from v < C where v is a regular vector. Assume we still want to allow boolean mask indexing of the form v[v >= 3 && v < 5] to work, then v < C is a boolean vector.

 
gael






Mail converted by MHonArc 2.6.19+ http://listengine.tuxfamily.org/