Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

There and back again: a block indexing tale #346

Open
mtfishman opened this issue Mar 21, 2024 · 2 comments
Open

There and back again: a block indexing tale #346

mtfishman opened this issue Mar 21, 2024 · 2 comments

Comments

@mtfishman
Copy link
Collaborator

I think a helpful abstraction could be a BlockIndices type, analogous to the CartesianIndices type in Base Julia, to aid with converting back and forth between cartesian indices and block indices. I would find that very helpful for advanced slicing operations, for example when performing slicing operations across block arrays with mismatched blocking structures.

As a minimal demonstration:

using BlockArrays

struct BlockIndices{N,R<:NTuple{N,OrdinalRange{Int,Int}}} <: AbstractArray{BlockIndex{N},N}
  indices::R
end

BlockIndices(a::AbstractArray) = BlockIndices(axes(a))

function Base.getindex(a::BlockIndices{N}, index::Vararg{Integer,N}) where {N}
  return BlockIndex(findblockindex.(a.indices, index))
end

which would allow for this syntax for converting back and forth between cartesian indices and block indices:

julia> a = BlockArray(randn(4, 4), [2, 2], [2, 2])
2×2-blocked 4×4 BlockMatrix{Float64}:
  1.05776   -0.193320.804285  -0.0377738
 -1.00564    0.3686721.26819    1.02757  
 ──────────────────────┼───────────────────────
  0.37596   -1.433350.280084  -1.06666  
  0.996146  -1.04132-1.21102    0.661257 

julia> CartesianIndices(a)[Block(1, 2)[2, 1]]
CartesianIndex(2, 3)

julia> BlockIndices(a)[2, 3]
Block(1, 2)[2, 1]

I found it interesting that indexing into CartesianIndices with a BlockIndex already works, I assume it is because the CartesianIndices object gets the same blocked axes as the BlockArray.

Something that doesn't work right now is indexing into CartesianIndices with a Block and getting back out a CartesianIndices, for example:

julia> CartesianIndices(a)[Block(1, 2)]
2×2 Matrix{CartesianIndex{2}}:
 CartesianIndex(1, 3)  CartesianIndex(1, 4)
 CartesianIndex(2, 3)  CartesianIndex(2, 4)

but that should be simple to fix.

We may be able to make BlockIndices a subtype of AbstractBlockArray and automatically inherit a lot of AbstractBlockArray behavior, since it will have blocked axes.

@jishnub
Copy link
Member

jishnub commented Mar 26, 2024

I quite like this idea, and I think this would certainly lead to code that is easier to reason about. Would you mind submitting a PR implementing this?

@mtfishman
Copy link
Collaborator Author

Sure, happy to make a PR with a basic implementation of BlockIndices.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants