Provide more flexibility for selections

Issue #221 resolved
gergol created an issue

Hi Klaus!

I'm using Blaze for creating audio-applications. For my use-case (but I also think, that this could be a super useful feature for other users), it would be extremely helpful to be able to create matrix views based on index-functors rather on index-data as in the current implementation.

To clarify here are two examples to show what i mean:.

DenseMatrix<float> buffer(8, 1024); // signal buffer with 8 channels and 1024 samples.

auto even_channels = rows(buffer, [](size_t idx){ return idx*2;});

auto rotate = [](auto& x; int shift) {
     size_t size = x.columns();
    return columns( x, [=](size_t idx){
         return  ( idx + shift) % size;
    }
};

auto rotated = rotate(x, -1); // useful e.g. for circular buffers, delay-lines etc...

I've tried a little bit to figure out, how this could be done and I think it should not to be too complex. As far as I understand, the RowsData and ColumnsData would have to be specialised to take a functor instead of the T* and size. Additionally the size() function of the Rows (Columns) Datahad to be changed to return the correct size. Probably this would require to either pass a second functor that calculates the size based on the underlying matrix. Alternatively, a struct with an idx and a size function could be used.

What do you think about this? Is this viable and realistic to get in the near future? Of course I can help with the implementation, if I can :)

Best regards

Gerald

Comments (5)

  1. Klaus Iglberger

    Hi Gerald!

    Thanks a lot for sharing this idea. The idea is great and will very likely be useful for many Blaze users. My current impression is that it should be relatively straight forward to extend the current implementation, so I will see what I can do to make this happen as soon as possible. Thanks again,

    Best regards,

    Klaus!

  2. gergol reporter

    Hi Klaus! That's great to read. Please let me know if I can help you with the implementation. Best regards Gerald

  3. Klaus Iglberger

    Summary

    The feature has been implemented, tested, optimized, and documented as required. It is immediately available via cloning the Blaze repository and will be officially released in Blaze 3.5.

    Element Selections

    With commit e184cc0 it is now possible to pass a callable such as a lambda or functor that produces the indices for an element selection. In addition, it is necessary to pass the total number of indices:

    blaze::DynamicVector<double,blaze::rowVector> x{ 1, 2, 3, 4, 5, 6, 7, 8, 9 };
    
    // Selecting all even elements of the vector, i.e. selecting (1,3,5,7,9)
    auto e1 = elements( x, []( size_t i ){ return i*2UL; }, 5UL );
    
    // Selecting all odd elements of the vector, i.e. selecting (2,4,6,8)
    auto e2 = elements( x, []( size_t i ){ return i*2UL+1UL; }, 4UL );
    
    // Reversing the elements of the vector, i.e. selecting (9,8,7,6,5,4,3,2,1)
    auto e3 = elements( v, [max=v.size()-1UL]( size_t i ){ return max-i; }, 9UL );
    

    Row Selections

    With commit ec6b0c8 it is now possible to pass a callable such as a lambda or functor that produces the indices for a row selection. In addition, it is necessary to pass the total number of indices:

    blaze::DynamicMatrix<double,blaze::rowMajor> A( 9UL, 18UL );
    
    // Selecting all even rows of the matrix, i.e. selecting the rows 0, 2, 4, 6, and 8
    auto rs1 = rows( A, []( size_t i ){ return i*2UL; }, 5UL );
    
    // Selecting all odd rows of the matrix, i.e. selecting the rows 1, 3, 5, and 7
    auto rs2 = rows( x, []( size_t i ){ return i*2UL+1UL; }, 4UL );
    
    // Reversing the rows of the matrix, i.e. selecting the rows 8, 7, 6, 5, 4, 3, 2, 1, and 0
    auto rs3 = rows( v, [max=A.rows()-1UL]( size_t i ){ return max-i; }, 9UL );
    

    Column Selections

    With commit 9e6e783 it is now possible to pass a callable such as a lambda or functor that produces the indices for a column selection. In addition, it is necessary to pass the total number of indices:

    blaze::DynamicMatrix<double,blaze::columnMajor> A( 18UL, 9UL );
    
    // Selecting all even columns of the matrix, i.e. selecting the columns 0, 2, 4, 6, and 8
    auto cs1 = columns( A, []( size_t i ){ return i*2UL; }, 5UL );
    
    // Selecting all odd columns of the matrix, i.e. selecting the columns 1, 3, 5, and 7
    auto cs2 = columns( x, []( size_t i ){ return i*2UL+1UL; }, 4UL );
    
    // Reversing the columns of the matrix, i.e. selecting the columns 8, 7, 6, 5, 4, 3, 2, 1, and 0
    auto cs3 = columns( v, [max=A.columns()-1UL]( size_t i ){ return max-i; }, 9UL );
    
  4. Log in to comment