Skip to content

Commit d0a8d7a

Browse files
Rename BlockedSlice from JuliaArrays#459 to NoncontiguousBlockSlice (JuliaArrays#479)
This PR is split off from JuliaArrays#462, it renames `BlockedSlice` introduced in JuliaArrays#459 to `NoncontiguousBlockSlice` and also adds more functionality and tests so that it is as featureful as `BlockSlice`. The reason for the name change is that in JuliaArrays#462, this type will be used in slicing operations such as `V[[Block(1), Block(3)]]` and `V[Block(1)[[1, 3]]]`. In my opinion, `BlockedSlice` doesn't make a lot of sense as a name for the latter case. The more general concept is that it is a slice object constructed when there is a non-contiguous blockwise slice of some form (either non-contiguous blocks or non-contiguous within a block). I'm open to other name suggestions, `NoncontiguousBlockSlice` is the best I could come up with and there isn't really an analogous case for this in Base from what I've seen. Note the main reason why we can't just use `BlockSlice` for those cases is that `BlockSlice` is an `AbstractUnitRange` subtype and `NoncontiguousBlockSlice` covers cases where the slices aren't ranges, so maybe `BlockSliceVector` could work as a name to emphasize that point. --------- Co-authored-by: Sheehan Olver <[email protected]>
1 parent cc5eb23 commit d0a8d7a

File tree

6 files changed

+66
-23
lines changed

6 files changed

+66
-23
lines changed

docs/src/lib/internals.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ BlockRange
2525
BlockIndexRange
2626
BlockIndices
2727
BlockSlice
28+
NoncontiguousBlockSlice
2829
unblock
2930
SubBlockIterator
3031
blockcheckbounds_indices

src/blockindices.jl

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -419,26 +419,39 @@ _indices(B) = B
419419
@propagate_inbounds view(C::CartesianIndices{N}, bs::Vararg{BlockSlice,N}) where {N} = view(C, map(x->x.indices, bs)...)
420420

421421
"""
422-
BlockedSlice(blocks, indices)
422+
NoncontiguousBlockSlice(blocks, indices)
423423
424-
Represents blocked indices attached to a collection of corresponding blocks.
424+
Represents an AbstractVector of indices attached to a (potentially non-contiguous) subblock,
425+
set of blocks, or set of subblocks. This is the generalization of `BlockSlice` to
426+
non-contiguous slices.
425427
426-
Upon calling `to_indices()`, a collection of blocks are converted to BlockedSlice objects to represent
428+
Upon calling `to_indices()`, a collection of blocks are converted to NoncontiguousBlockSlice objects to represent
427429
the indices over which the blocks span.
428430
429431
This mimics the relationship between `Colon` and `Base.Slice`, `Block` and `BlockSlice`, etc.
430432
"""
431-
struct BlockedSlice{BB,T<:Integer,INDS<:AbstractVector{T}} <: AbstractVector{T}
432-
blocks::BB
433+
struct NoncontiguousBlockSlice{BB,T,INDS<:AbstractVector{T}} <: AbstractVector{T}
434+
block::BB
433435
indices::INDS
434436
end
435437

436-
for f in (:axes, :size)
437-
@eval $f(S::BlockedSlice) = $f(S.indices)
438+
Block(bs::NoncontiguousBlockSlice{<:Block}) = bs.block
439+
Block(bs::NoncontiguousBlockSlice{<:BlockIndexRange}) = Block(bs.block)
440+
441+
for f in (:axes, :unsafe_indices, :axes1, :first, :last, :size, :length,
442+
:unsafe_length, :start)
443+
@eval $f(S::NoncontiguousBlockSlice) = $f(S.indices)
438444
end
439445

440-
@propagate_inbounds getindex(S::BlockedSlice, i::Integer) = getindex(S.indices, i)
441-
@propagate_inbounds getindex(S::BlockedSlice, k::Block{1}) = BlockSlice(S.blocks[Int(k)], getindex(S.indices, k))
446+
_indices(B::NoncontiguousBlockSlice) = B.indices
447+
448+
@propagate_inbounds getindex(S::NoncontiguousBlockSlice, i::Integer) = getindex(S.indices, i)
449+
@propagate_inbounds getindex(S::NoncontiguousBlockSlice{<:Block{1}}, k::AbstractVector{<:Integer}) =
450+
NoncontiguousBlockSlice(S.block[_indices(k)], S.indices[_indices(k)])
451+
@propagate_inbounds getindex(S::NoncontiguousBlockSlice{<:BlockIndexRange{1,<:Tuple{AbstractVector}}}, k::AbstractVector{<:Integer}) =
452+
NoncontiguousBlockSlice(S.block[_indices(k)], S.indices[_indices(k)])
453+
@propagate_inbounds getindex(S::NoncontiguousBlockSlice{<:AbstractVector{<:Block{1}}}, k::Block{1}) =
454+
BlockSlice(S.block[Int(k)], getindex(S.indices, k))
442455

443456
struct BlockRange{N,R<:NTuple{N,AbstractUnitRange{<:Integer}}} <: AbstractArray{Block{N,Int},N}
444457
indices::R

src/views.jl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ function unblock(A, inds, I)
1111
end
1212

1313
_blockslice(B, a::AbstractUnitRange) = BlockSlice(B, a)
14-
_blockslice(B, a) = BlockedSlice(B, a)
14+
_blockslice(B, a) = NoncontiguousBlockSlice(B, a)
1515

1616
# Allow `ones(2)[Block(1)[1:1], Block(1)[1:1]]` which is
1717
# similar to `ones(2)[1:1, 1:1]`.
@@ -209,11 +209,11 @@ block(A::Block) = A
209209
@inline view(block_arr::AbstractBlockArray{<:Any,N}, blocks::Vararg{BlockSlice1, N}) where N =
210210
view(block_arr, map(block,blocks)...)
211211

212-
const BlockSlices = Union{Base.Slice,BlockSlice{<:BlockRange{1}},BlockedSlice}
212+
const BlockSlices = Union{Base.Slice,BlockSlice{<:BlockRange{1}},NoncontiguousBlockSlice{<:AbstractVector{<:Block{1}}}}
213213
# view(V::SubArray{<:Any,N,NTuple{N,BlockSlices}},
214214

215215
_block_reindex(b::BlockSlice, i::Block{1}) = b.block[Int(i)]
216-
_block_reindex(b::BlockedSlice, i::Block{1}) = b.blocks[Int(i)]
216+
_block_reindex(b::NoncontiguousBlockSlice, i::Block{1}) = b.block[Int(i)]
217217
_block_reindex(b::Slice, i::Block{1}) = i
218218

219219
@inline view(V::SubArray{<:Any,N,<:AbstractBlockArray,<:NTuple{N,BlockSlices}}, block::Block{N}) where N =

test/test_blockindices.jl

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ module TestBlockIndices
22

33
using BlockArrays, FillArrays, Test, StaticArrays, ArrayLayouts
44
using OffsetArrays
5-
import BlockArrays: BlockIndex, BlockIndexRange, BlockSlice, BlockedSlice
5+
import BlockArrays: BlockIndex, BlockIndexRange, BlockSlice, NoncontiguousBlockSlice
66

77
@testset "Blocks" begin
88
@test Int(Block(2)) === Integer(Block(2)) === Number(Block(2)) === 2
@@ -882,6 +882,9 @@ end
882882
@test b[1:2] b[1:2][1:2] BlockSlice(Block(5)[1:2],1:2)
883883
@test Block(b) Block(5)
884884

885+
bi = BlockSlice(Block(2)[2:4],3:5)
886+
@test Block(bi) Block(2)
887+
@test bi[2:3] BlockSlice(Block(2)[3:4],4:5)
885888
@test Block(BlockSlice(Block(2)[1:2], 3:4)) Block(2)
886889

887890
@testset "OneTo converts" begin
@@ -901,14 +904,24 @@ end
901904
end
902905
end
903906

904-
@testset "BlockedSlice" begin
905-
b = BlockedSlice([Block(2), Block(1)], mortar([3:5, 1:2]))
906-
@test length(b) == 5
907-
for i in eachindex(b.indices)
908-
@test b[i] === b.indices[i]
907+
@testset "NoncontiguousBlockSlice" begin
908+
bs = NoncontiguousBlockSlice([Block(2),Block(1)], mortar([3:5,1:2]))
909+
@test length(bs) 5
910+
for i in eachindex(bs.indices)
911+
@test bs[i] bs.indices[i]
909912
end
910-
@test b[Block(1)] === BlockSlice(Block(2), 3:5)
911-
@test b[Block(2)] === BlockSlice(Block(1), 1:2)
913+
@test bs[Block(1)] BlockSlice(Block(2), 3:5)
914+
@test bs[Block(2)] BlockSlice(Block(1), 1:2)
915+
@test BlockArrays._indices(bs) == mortar([3:5,1:2])
916+
917+
b = NoncontiguousBlockSlice(Block(3), 2:4)
918+
@test b[2:3] NoncontiguousBlockSlice(Block(3)[2:3], 3:4)
919+
@test Block(b) Block(3)
920+
@test BlockArrays._indices(b) 2:4
921+
922+
bir = NoncontiguousBlockSlice(Block(3)[3:5], 4:6)
923+
@test Block(bir) Block(3)
924+
@test bir[2:3] NoncontiguousBlockSlice(Block(3)[4:5], 5:6)
912925
end
913926

914927
#=

test/test_blockrange.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ using BlockArrays, Test
3232
V = view(A, [Block(3), Block(2)])
3333
@test V == [4, 5, 6, 2, 3]
3434
I = parentindices(V)[1]
35-
@test I isa BlockArrays.BlockedSlice{<:Vector{<:Block{1}}}
35+
@test I isa BlockArrays.NoncontiguousBlockSlice{<:Vector{<:Block{1}}}
3636
@test V[Block(1)] == 4:6
3737
@test V[Block(2)] == 2:3
3838
@test view(V, Block(1)) === view(A, Block(3))

test/test_blockviews.jl

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ module TestBlockViews
22

33
using BlockArrays, ArrayLayouts, Test
44
using FillArrays
5-
import BlockArrays: BlockedLogicalIndex
5+
import BlockArrays: BlockedLogicalIndex, NoncontiguousBlockSlice
66
import Base: LogicalIndex
77

88
# useds to force SubArray return
@@ -219,6 +219,22 @@ bview(a, b) = Base.invoke(view, Tuple{AbstractArray,Any}, a, b)
219219
@test A[Block.(2:3)] == A[2:end]
220220
end
221221

222+
@testset "getindex and view with Block-vector" begin
223+
A = BlockArray(reshape(collect(1:(6*12)),6,12), 1:3, 3:5)
224+
V = view(A, [Block(3),Block(2)], [Block(3),Block(2)])
225+
@test V[Block(1,1)] == A[Block(3,3)]
226+
@test V[Block(2,1)] == A[Block(2,3)]
227+
@test V[Block(1,2)] == A[Block(3,2)]
228+
@test V[Block(2,2)] == A[Block(2,2)]
229+
I = parentindices(V)
230+
@test I[1] isa NoncontiguousBlockSlice{<:Vector{<:Block{1}}}
231+
@test I[2] isa NoncontiguousBlockSlice{<:Vector{<:Block{1}}}
232+
@test view(V, Block(1,1)) === view(A, Block(3,3))
233+
@test view(V, Block(2,1)) === view(A, Block(2,3))
234+
@test view(V, Block(1,2)) === view(A, Block(3,2))
235+
@test view(V, Block(2,2)) === view(A, Block(2,2))
236+
end
237+
222238
@testset "non-allocation blocksize" begin
223239
A = BlockArray(randn(5050), 1:100)
224240
@test blocksize(A) == (100,)
@@ -316,7 +332,7 @@ bview(a, b) = Base.invoke(view, Tuple{AbstractArray,Any}, a, b)
316332
@test a[Block(1)[1:3]] view(a,Block(1)[1:3]) view(v,Block(1)[1:3]) 7:9
317333
end
318334

319-
@testset "blockrange-of-blockreange" begin
335+
@testset "blockrange-of-blockrange" begin
320336
a = mortar([7:9,5:6])
321337
v = view(a,Block.(1:2))
322338
@test view(v, Block(1)) 7:9

0 commit comments

Comments
 (0)