-
Notifications
You must be signed in to change notification settings - Fork 34
Description
New syntax proposal for obtaining the size of a block
EDIT: TLDR: This proposal is to change the definition of blocksizes so that it acts like this:
julia> using BlockArrays
julia> a = BlockArray(randn(5, 5), [2, 3], [2, 3])
2×2-blocked 5×5 BlockMatrix{Float64}:
0.916747 1.45141 │ 0.740126 0.663479 0.17119
-0.563452 0.574973 │ 0.618916 -1.43895 1.40107
──────────────────────┼─────────────────────────────────
0.621363 2.86333 │ 0.0611178 -0.928277 1.48074
0.106673 -0.673614 │ -1.49219 0.158793 0.564433
0.017256 -1.10824 │ 0.768847 0.923508 0.362625
julia> blocksizes(a)[1, 2]
(2, 3)
julia> blocksizes(a)
2×2 BlockSizes{2, BlockMatrix{Float64, Matrix{Matrix{Float64}}, Tuple{BlockedUnitRange{Vector{Int64}}, BlockedUnitRange{Vector{Int64}}}}}:
(2, 2) (2, 3)
(3, 2) (3, 3)i.e. it acts like a collection of size blocksize(a), and indexing into it outputs the size of the corresponding block.
The current definition gives:
julia> blocksizes(a)
([2, 3], [2, 3])which is equivalent to:
julia> blocklengths.(axes(a))
([2, 3], [2, 3])so uses of the current blocksizes definition could switch to that, which I think is clearer anyway. See also the discussion in #255.
Summary of the current syntax for obtaining the size of a block
From what I can tell, these are the most compact ways of getting the size of a block right now, using public APIs:
julia> using BlockArrays
julia> a = BlockArray(randn(5, 5), [2, 3], [2, 3])
2×2-blocked 5×5 BlockMatrix{Float64}:
0.916747 1.45141 │ 0.740126 0.663479 0.17119
-0.563452 0.574973 │ 0.618916 -1.43895 1.40107
──────────────────────┼─────────────────────────────────
0.621363 2.86333 │ 0.0611178 -0.928277 1.48074
0.106673 -0.673614 │ -1.49219 0.158793 0.564433
0.017256 -1.10824 │ 0.768847 0.923508 0.362625
julia> size(view(a, Block(1, 2)))
(2, 3)
julia> size(@view(a[Block(1, 2)]))
(2, 3)
julia> getindex.(blocksizes(a), Int.(Tuple(Block(1, 2))))
(2, 3)
julia> getindex.(blocksizes(a), Int.((Block(1), Block(2))))
(2, 3)
julia> getindex.(blocksizes(a), (1, 2))
(2, 3)
julia> length.(getindex.(axes(a), Tuple(Block(1, 2))))
(2, 3)
julia> getindex.(blocklengths.(axes(a)), Int.(Tuple(Block(1, 2))))
(2, 3)(please correct me if I am wrong).
I think it would be nice to have something more convenient. The best I can come up with is overloading Base.size(a::AbstractArray, b::Block), for example:
julia> Base.size(a::AbstractArray{<:Any,N}, b::Block{N}) where {N} = size(@view(a[b]))
julia> size(a, Block(1, 2))
(2, 3)It feels like a slight abuse of Base.size, but seems along the same lines as being able to ask for the size in a certain dimension with size(a, 1).
I believe this would make sense for getting the axes of a block as well, i.e. axes(a, Block(1, 2)), however perhaps there is some ambiguity there if that is meant to be a slice of the axes of a, i.e.:
julia> getindex.(axes(a), Tuple(Block(1, 2)))
(1:2, 3:5)or the axes of the @view(a[Block(1, 2)]), i.e.:
julia> only.(axes.(getindex.(axes(a), Tuple(Block(1, 2)))))
(Base.OneTo(2), Base.OneTo(3))It is a bit unfortunate that blocksize is already taken and has a different meaning, I understand why that choice was made but I found that to be confusing at first and my initial thought was that it should be a way to get the size of a block.