Skip to content

Commit a4e544e

Browse files
authored
Support views involving vectors of blocks, Fixes #184 and #358 (#445)
1 parent 6e54660 commit a4e544e

6 files changed

+43
-4
lines changed

Project.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name = "BlockArrays"
22
uuid = "8e7c35d0-a365-5155-bbbb-fb81a777f24e"
3-
version = "1.3.0"
3+
version = "1.4.0"
44

55
[deps]
66
ArrayLayouts = "4c555306-a7a7-4459-81d9-ec55ddd5c99a"

src/blockaxis.jl

+5
Original file line numberDiff line numberDiff line change
@@ -397,6 +397,11 @@ end
397397

398398
@propagate_inbounds getindex(b::AbstractBlockedUnitRange, KR::BlockSlice) = b[KR.block]
399399

400+
getindex(b::AbstractBlockedUnitRange, KR::AbstractVector{<:Block{1}}) = mortar([b[K] for K in KR])
401+
getindex(b::AbstractBlockedUnitRange, KR::AbstractVector{<:BlockIndexRange{1}}) = mortar([b[K] for K in KR])
402+
getindex(b::AbstractBlockedUnitRange, KR::AbstractVector{<:BlockIndex{1}}) = [b[K] for K in KR]
403+
getindex(b::AbstractBlockedUnitRange, Kkr::BlockIndexRange{1}) = b[block(Kkr)][Kkr.indices...]
404+
400405
_searchsortedfirst(a::AbstractVector, k) = searchsortedfirst(a, k)
401406
function _searchsortedfirst(a::Tuple, k)
402407
k first(a) && return 1

src/blockindices.jl

+2-2
Original file line numberDiff line numberDiff line change
@@ -252,9 +252,9 @@ Block(bs::BlockIndexRange) = bs.block
252252

253253

254254
"""
255-
BlockSlice(indices)
255+
BlockSlice(block, indices)
256256
257-
Represent an AbstractUnitRange of indices that attaches a block.
257+
Represent an AbstractUnitRange{<:Integer} of indices that attaches a block.
258258
259259
Upon calling `to_indices()`, Blocks are converted to BlockSlice objects to represent
260260
the indices over which the Block spans.

src/views.jl

+15-1
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,12 @@ Returns the indices associated with a block as a `BlockSlice`.
77
"""
88
function unblock(A, inds, I)
99
B = first(I)
10-
BlockSlice(B,inds[1][B])
10+
_blockslice(B, inds[1][B])
1111
end
12+
13+
_blockslice(B, a::AbstractUnitRange) = BlockSlice(B, a)
14+
_blockslice(B, a) = a # drop block structure
15+
1216
# Allow `ones(2)[Block(1)[1:1], Block(1)[1:1]]` which is
1317
# similar to `ones(2)[1:1, 1:1]`.
1418
# Need to check the length of I in case its empty
@@ -28,6 +32,13 @@ to_index(::BlockRange) = throw(ArgumentError("BlockRange must be converted by to
2832
(inds[1][I[1]], to_indices(A, _maybetail(inds), tail(I))...)
2933
@inline to_indices(A, inds, I::Tuple{BlockIndexRange{1,R}, Vararg{Any}}) where R =
3034
(unblock(A, inds, I), to_indices(A, _maybetail(inds), tail(I))...)
35+
@inline to_indices(A, inds, I::Tuple{AbstractVector{Block{1,R}}, Vararg{Any}}) where R =
36+
(unblock(A, inds, I), to_indices(A, _maybetail(inds), tail(I))...)
37+
@inline to_indices(A, inds, I::Tuple{AbstractVector{<:BlockIndex{1}}, Vararg{Any}}) =
38+
(unblock(A, inds, I), to_indices(A, _maybetail(inds), tail(I))...)
39+
@inline to_indices(A, inds, I::Tuple{AbstractVector{<:BlockIndexRange{1}}, Vararg{Any}}) =
40+
(unblock(A, inds, I), to_indices(A, _maybetail(inds), tail(I))...)
41+
3142

3243
# splat out higher dimensional blocks
3344
# this mimics view of a CartesianIndex
@@ -44,6 +55,9 @@ to_index(::BlockRange) = throw(ArgumentError("BlockRange must be converted by to
4455
@inline to_indices(A, I::Tuple{BlockIndexRange, Vararg{Any}}) = to_indices(A, axes(A), I)
4556
@inline to_indices(A, I::Tuple{Block, Vararg{Any}}) = to_indices(A, axes(A), I)
4657
@inline to_indices(A, I::Tuple{BlockRange, Vararg{Any}}) = to_indices(A, axes(A), I)
58+
@inline to_indices(A, I::Tuple{AbstractVector{<:Block{1}}, Vararg{Any}}) = to_indices(A, axes(A), I)
59+
@inline to_indices(A, I::Tuple{AbstractVector{<:BlockIndex{1}}, Vararg{Any}}) = to_indices(A, axes(A), I)
60+
@inline to_indices(A, I::Tuple{AbstractVector{<:BlockIndexRange{1}}, Vararg{Any}}) = to_indices(A, axes(A), I)
4761

4862
@propagate_inbounds reindex(idxs::Tuple{BlockSlice{<:BlockRange}, Vararg{Any}},
4963
subidxs::Tuple{BlockSlice{<:BlockIndexRange}, Vararg{Any}}) =

test/test_blockarrays.jl

+15
Original file line numberDiff line numberDiff line change
@@ -924,6 +924,21 @@ end
924924
@test_throws BoundsError a[:,Block.(1:2)]
925925
@test size(a[:,1]) == (8,)
926926
end
927+
928+
@testset "Block-vector indexing (#184)" begin
929+
a = BlockArray(1:6, [1,2,2,1])
930+
@test a[Block.(2:3)] == a[collect(Block.(2:3))]
931+
932+
for B in (BlockArray(I, fill(2,4), fill(2,5)), BlockedArray(I, fill(2,4), fill(2,5)))
933+
@test B[[Block(1),Block(2)], [Block(1),Block(2)]] == view(B, [Block(1),Block(2)], [Block(1), Block(2)]) == view(B, Block.(1:2), [Block(1), Block(2)]) == view(B, Block.(1:2), Block.(1:2))
934+
@test B[[Block(1),Block(3)], [Block(1), Block(5)]] == view(B, [Block(1),Block(3)], [Block(1), Block(5)])
935+
end
936+
end
937+
@testset "BlockIndex-vector indexing (#358)" begin
938+
a = BlockArray(randn(6, 6), [3, 3], [3, 3])
939+
@test a[[Block(1)[1:2], Block(2)[1:2]], [Block(1)[1:2], Block(2)[1:2]]] == [a[Block(1,1)[1:2,1:2]] a[Block(1,2)[1:2,1:2]]; a[Block(2,1)[1:2,1:2]] a[Block(2,2)[1:2,1:2]]]
940+
@test a[[Block(1)[1], Block(2)[2]], [Block(1)[1:2], Block(2)[1:2]]] == [a[Block(1)[1],Block(1)[1:2]]' a[Block(1)[1], Block(2)[1:2]]'; a[Block(2)[2],Block(1)[1:2]]' a[Block(2)[2], Block(2)[1:2]]']
941+
end
927942
end
928943

929944
end # module

test/test_blockindices.jl

+5
Original file line numberDiff line numberDiff line change
@@ -888,4 +888,9 @@ end
888888
@test !blockisequal(axv, axB)
889889
end
890890

891+
@testset "BlockIndices" begin
892+
a = BlockedOneTo(1:3)
893+
@test a[[Block(1),Block(3)]] == a[Block.(1:2:3)] == [1,3]
894+
end
895+
891896
end # module

0 commit comments

Comments
 (0)