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

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





On Mon, Jan 9, 2017 at 9:33 AM, Massimiliano Janes <max..jns@xxxxxxxxx> wrote:

thinking about it, here is yet another variation on the theme of _expression_ based api,
similar to iota but with the benefit of more closely following elementary math notation
, allowing multidimensional generalizations, matrix operations via Einstein-like summation
convention, and possibly a new initialization syntax:

skipping about the details, regarding Einstein-like summation, there is this PR for the Tensor module:

https://bitbucket.org/eigen/eigen/pull-requests/124/einstein-notation-for-tensor-module/diff

Then, this approach also reminds me Blitz++ that also supports this placeholder approach for both:

1 - products/contractions, but without implicit contraction, so the standard matrix product is:

Array<double,2> A, B, C;
using blitz::tensor::i;
using blitz::tensor::j;
using blitz::tensor::k;
C = sum(A(i,k) * B(k,j), k);

2 - and initialization:

using blitz::tensor::i;
Array<double,1> A;
A = sin(2 * M_PI * i / 16.);

but not for slicing where it uses a standard Range(from,to[,stride]).


gael


 

given 'letter' symbols ( ala std::placeholders )

_i,_j,_k,...
_iN,_jN,_kN...

ans a set of allowed 'arithmetic' expressions f(_i,_iN)

_i*2+1, -1 -_i, ...

generating the intersection of { f(i,N) % N |0<=i<N} && {0<=i<N}, where N is the deduced size of the target object

and a set of allowed 'boolean' expressions g(_i,_iN)

generating { 0<=i<N | g(i,N) }, where N is the deduced size of the target object

and compound expressions (f|g)

generating the intersection of the results f and g

we can write ( with obvious meaning )

A(_i)
A(_i<k)
A(2+_i | _i<k)
A(2+_i*3 | _i<k)
A(_i|_i<=_iN-k) // up to last kth, no special convention, follows from definition
A(-1-_i) // the reverse of A, the -1 follows from the definition; less natural than just '-iota', but ok IMO
A(-1-2*_i) // even reverse *starting* form last
A( -1 -_i | _i%2 == 0 ) // even indices in reverse, this is not the same as the above

// multidimensional

A(_i,_j) // as A
A(_i,_i) // as A.diagonal()

// operation ( assuming column indices as covariant, and *operator as lowering indices )

A(_i,_j) * A(_j,_k) // matrix product
A(_i) * A(*_i) // vector dot product
A(_i,_i) * A(*_i,_*i) // matrix trace

// boolean expressions with lambdas

A( _i | []( auto i ){ return i >= 3 && i <= i.N - 5; } ) // runtime only, the 'i' being an index wrapper with obvious member N ( _iN <-> i.N )
A( _i | [](auto i){ return boolean_fun(i,i.n()); } )

// initialization

Vector3f{ _i << 2.f } // as Vector3f::Constant
Vector3f{ _i << _iN - 2 * _i } // linear epressions
Vector3f{ _i << []( auto i ){ return i.n() - 2 * i; } } // lambdas
Matrix3f{ (_i,_j) << 2.f } // as Matrix3f::Constant
Matrix3f{ (_i,_j) << []( auto i, auto j ){ return i == j ? 0.f : 1.f; } } // Dirac's and friends ...

… more ?

unless I'm missing somthing, this should be implementable ( it's till to decide what expressions are to be allowed
where, when to allow compile/run time evaluation or not, etc… ) and require no special convention apart remembering
the i,j,iN,,… placeholders and the simple generating rules aforementioned.

what do you think ?






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