Skip to content

Commit 2ce8d26

Browse files
authored
Index into a CartesianIndices with a Block (#354)
* View into ranges/CartesianIndices with BlockSlices * Index into a CartesianIndices with a Block * Preserve indexing of Blocks in BlockSlice * Block{1} indexing * Add BlockSlice type test
1 parent 96f8156 commit 2ce8d26

File tree

2 files changed

+63
-2
lines changed

2 files changed

+63
-2
lines changed

src/blockindices.jl

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,16 @@ function Base.show(io::IO, B::Block{N,Int}) where N
113113
print(io, ")")
114114
end
115115

116+
# Some views may be computed eagerly without the SubArray wrapper
117+
Base.@propagate_inbounds Base.view(r::AbstractRange, B::Block{1}) = r[to_indices(r, (B,))...]
118+
Base.@propagate_inbounds function Base.view(C::CartesianIndices{N}, b1::Block{1}, B::Block{1}...) where {N}
119+
blk = Block((b1, B...))
120+
view(C, to_indices(C, (blk,))...)
121+
end
122+
Base.@propagate_inbounds function Base.view(C::CartesianIndices{N}, B::Block{N}) where {N}
123+
view(C, to_indices(C, (B,))...)
124+
end
125+
116126
"""
117127
BlockIndex{N}
118128
@@ -289,11 +299,19 @@ for f in (:axes, :unsafe_indices, :axes1, :first, :last, :size, :length,
289299
@eval $f(S::BlockSlice) = $f(S.indices)
290300
end
291301

302+
_indices(B::BlockSlice) = B.indices
303+
_indices(B) = B
304+
292305
@propagate_inbounds getindex(S::BlockSlice, i::Integer) = getindex(S.indices, i)
293-
@propagate_inbounds getindex(S::BlockSlice{<:Block}, k::AbstractUnitRange{Int}) = BlockSlice(S.block[k],S.indices[k])
294-
@propagate_inbounds getindex(S::BlockSlice{<:BlockIndexRange}, k::AbstractUnitRange{Int}) = BlockSlice(S.block[k],S.indices[k])
306+
@propagate_inbounds getindex(S::BlockSlice{<:Block{1}}, k::AbstractUnitRange{Int}) =
307+
BlockSlice(S.block[_indices(k)], S.indices[_indices(k)])
308+
@propagate_inbounds getindex(S::BlockSlice{<:BlockIndexRange{1}}, k::AbstractUnitRange{Int}) =
309+
BlockSlice(S.block[_indices(k)], S.indices[_indices(k)])
295310
show(io::IO, r::BlockSlice) = print(io, "BlockSlice(", r.block, ",", r.indices, ")")
296311

312+
# Avoid creating a SubArray wrapper in certain non-allocating cases
313+
Base.@propagate_inbounds Base.view(C::CartesianIndices{N}, bs::Vararg{BlockSlice,N}) where {N} = view(C, map(x->x.indices, bs)...)
314+
297315
Block(bs::BlockSlice{<:BlockIndexRange}) = Block(bs.block)
298316

299317

test/test_blockindices.jl

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,37 @@ import BlockArrays: BlockIndex, BlockIndexRange, BlockSlice
103103
@test intersect(Block.(2:5), Block.(3:6)) Block.(3:5)
104104
end
105105

106+
@testset "view into CartesianIndices/ranges" begin
107+
r = 2:10
108+
@test view(r, Block(1)) === r
109+
@test_throws BlockBoundsError view(r, Block(2))
110+
C = CartesianIndices((2:10, 2:10))
111+
=== VERSION >= v"1.10" ? (===) : (==)
112+
113+
@test view(C, Block(1,1)) ==ᵥ C
114+
@test view(C, Block(1), Block(1)) == C
115+
@test_throws BlockBoundsError view(C, Block(1), Block(2))
116+
@test_throws BlockBoundsError view(C, Block(1,2))
117+
118+
B = BlockArray([1:3;], [2,1])
119+
Cb = CartesianIndices(B)
120+
@test view(Cb, Block(1)) ==ᵥ Cb[Block(1)] ==CartesianIndices((1:2,))
121+
@test view(Cb, Block(2)) ==ᵥ Cb[Block(2)] ==CartesianIndices((3:3,))
122+
123+
B = BlockArray(reshape([1:9;],3,3), [2,1], [2,1])
124+
Cb = CartesianIndices(B)
125+
@test view(Cb, Block(1,1)) ==ᵥ Cb[Block(1,1)] ==CartesianIndices((1:2,1:2))
126+
@test view(Cb, Block(1,2)) ==ᵥ Cb[Block(1,2)] ==CartesianIndices((1:2, 3:3))
127+
@test view(Cb, Block(2,1)) ==ᵥ Cb[Block(2,1)] ==CartesianIndices((3:3,1:2))
128+
@test view(Cb, Block(2,2)) ==ᵥ Cb[Block(2,2)] ==CartesianIndices((3:3, 3:3))
129+
for i in 1:2, j in 1:2
130+
@test view(Cb, Block(j), Block(i)) ==view(Cb, Block(j, i))
131+
end
132+
# ensure that calls with mismatched ndims don't error
133+
@test view(Cb, Block(1)) == view(Cb, to_indices(Cb, (Block(1),))...)
134+
@test reshape(view(Cb, Block(1), Block(1), Block(1)), 2, 2) == view(Cb, Block(1), Block(1))
135+
end
136+
106137
@testset "print" begin
107138
@test sprint(show, "text/plain", Block()) == "Block()"
108139
@test sprint(show, "text/plain", Block(1)) == "Block(1)"
@@ -405,6 +436,8 @@ end
405436

406437
@testset "BlockSlice" begin
407438
b = BlockSlice(Block(5),1:3)
439+
@test b[b] == b
440+
@test b[b] isa BlockSlice{<:BlockIndexRange}
408441
@test b[Base.Slice(1:3)] b
409442
@test b[1:2] b[1:2][1:2] BlockSlice(Block(5)[1:2],1:2)
410443
@test Block(b) Block(5)
@@ -414,6 +447,16 @@ end
414447
@test convert(typeof(b), Base.OneTo(1)) b
415448
end
416449
end
450+
451+
@testset "view into CartesianIndices/ranges" begin
452+
C = CartesianIndices((1:3,))
453+
r = 1:2
454+
b = BlockSlice(Block(1), r)
455+
@test view(C, b) === view(C, r)
456+
@test view(1:10, b) === view(1:10, r)
457+
C = CartesianIndices((1:3, 1:3))
458+
@test view(C, b, b) === view(C, r, r)
459+
end
417460
end
418461

419462
#=

0 commit comments

Comments
 (0)