Skip to content

Rename BlockedSlice from #459 to NoncontiguousBlockSlice #479

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

Open
wants to merge 21 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/src/lib/internals.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ BlockedUnitRange
BlockRange
BlockIndexRange
BlockSlice
NoncontiguousBlockSlice
unblock
SubBlockIterator
blockcheckbounds_indices
Expand Down
39 changes: 26 additions & 13 deletions src/blockindices.jl
Original file line number Diff line number Diff line change
Expand Up @@ -334,10 +334,11 @@ end
"""
BlockSlice(block, indices)

Represent an AbstractUnitRange{<:Integer} of indices that attaches a block.
Represents an AbstractUnitRange{<:Integer} of indices attached to a block,
a subblock, or a range of blocks.

Upon calling `to_indices()`, Blocks are converted to BlockSlice objects to represent
the indices over which the Block spans.
the indices over which the block, subblock, or range of blocks spans.

This mimics the relationship between `Colon` and `Base.Slice`.
"""
Expand All @@ -347,6 +348,7 @@ struct BlockSlice{BB,T<:Integer,INDS<:AbstractUnitRange{T}} <: AbstractUnitRange
end

Block(bs::BlockSlice{<:Block}) = bs.block
Block(bs::BlockSlice{<:BlockIndexRange}) = Block(bs.block)


for f in (:axes, :unsafe_indices, :axes1, :first, :last, :size, :length,
Expand All @@ -366,29 +368,40 @@ _indices(B) = B
# Avoid creating a SubArray wrapper in certain non-allocating cases
@propagate_inbounds view(C::CartesianIndices{N}, bs::Vararg{BlockSlice,N}) where {N} = view(C, map(x->x.indices, bs)...)

Block(bs::BlockSlice{<:BlockIndexRange}) = Block(bs.block)

"""
BlockedSlice(blocks, indices)
NoncontiguousBlockSlice(blocks, indices)

Represents blocked indices attached to a collection of corresponding blocks.
Represents an AbstractVector of indices attached to a (potentially non-contiguous) subblock,
set of blocks, or set of subblocks. This is the generalization of `BlockSlice` to
non-contiguous slices.

Upon calling `to_indices()`, a collection of blocks are converted to BlockedSlice objects to represent
Upon calling `to_indices()`, a collection of blocks are converted to NoncontiguousBlockSlice objects to represent
the indices over which the blocks span.

This mimics the relationship between `Colon` and `Base.Slice`, `Block` and `BlockSlice`, etc.
"""
struct BlockedSlice{BB,T<:Integer,INDS<:AbstractVector{T}} <: AbstractVector{T}
blocks::BB
struct NoncontiguousBlockSlice{BB,T,INDS<:AbstractVector{T}} <: AbstractVector{T}
block::BB
indices::INDS
end

for f in (:axes, :size)
@eval $f(S::BlockedSlice) = $f(S.indices)
Block(bs::NoncontiguousBlockSlice{<:Block}) = bs.block
Block(bs::NoncontiguousBlockSlice{<:BlockIndexRange}) = Block(bs.block)

for f in (:axes, :unsafe_indices, :axes1, :first, :last, :size, :length,
:unsafe_length, :start)
@eval $f(S::NoncontiguousBlockSlice) = $f(S.indices)
end

@propagate_inbounds getindex(S::BlockedSlice, i::Integer) = getindex(S.indices, i)
@propagate_inbounds getindex(S::BlockedSlice, k::Block{1}) = BlockSlice(S.blocks[Int(k)], getindex(S.indices, k))
_indices(B::NoncontiguousBlockSlice) = B.indices

@propagate_inbounds getindex(S::NoncontiguousBlockSlice, i::Integer) = getindex(S.indices, i)
@propagate_inbounds getindex(S::NoncontiguousBlockSlice{<:Block{1}}, k::AbstractVector{<:Integer}) =
NoncontiguousBlockSlice(S.block[_indices(k)], S.indices[_indices(k)])
@propagate_inbounds getindex(S::NoncontiguousBlockSlice{<:BlockIndexRange{1,<:Tuple{AbstractVector}}}, k::AbstractVector{<:Integer}) =
NoncontiguousBlockSlice(S.block[_indices(k)], S.indices[_indices(k)])
@propagate_inbounds getindex(S::NoncontiguousBlockSlice{<:AbstractVector{<:Block{1}}}, k::Block{1}) =
BlockSlice(S.block[Int(k)], getindex(S.indices, k))

struct BlockRange{N,R<:NTuple{N,AbstractUnitRange{<:Integer}}} <: AbstractArray{Block{N,Int},N}
indices::R
Expand Down
6 changes: 3 additions & 3 deletions src/views.jl
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ function unblock(A, inds, I)
end

_blockslice(B, a::AbstractUnitRange) = BlockSlice(B, a)
_blockslice(B, a) = BlockedSlice(B, a)
_blockslice(B, a) = NoncontiguousBlockSlice(B, a)

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

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

_block_reindex(b::BlockSlice, i::Block{1}) = b.block[Int(i)]
_block_reindex(b::BlockedSlice, i::Block{1}) = b.blocks[Int(i)]
_block_reindex(b::NoncontiguousBlockSlice, i::Block{1}) = b.block[Int(i)]
_block_reindex(b::Slice, i::Block{1}) = i

@inline view(V::SubArray{<:Any,N,<:AbstractBlockArray,<:NTuple{N,BlockSlices}}, block::Block{N}) where N =
Expand Down
31 changes: 23 additions & 8 deletions test/test_blockindices.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ module TestBlockIndices

using BlockArrays, FillArrays, Test, StaticArrays, ArrayLayouts
using OffsetArrays
import BlockArrays: BlockIndex, BlockIndexRange, BlockSlice, BlockedSlice
import BlockArrays: BlockIndex, BlockIndexRange, BlockSlice, NoncontiguousBlockSlice

@testset "Blocks" begin
@test Int(Block(2)) === Integer(Block(2)) === Number(Block(2)) === 2
Expand Down Expand Up @@ -91,6 +91,7 @@ import BlockArrays: BlockIndex, BlockIndexRange, BlockSlice, BlockedSlice
@test Block(1,1)[1:2,1:2] == BlockIndexRange(Block(1,1),(1:2,1:2))
@test BlockIndexRange((Block(1)[1:2],Block(1)[1:2])) == BlockIndexRange(Block(1,1),(1:2,1:2))
@test Block(1)[1:3][1:2] == BlockIndexRange(Block(1),1:2)
@test Block(1,1)[1:3,1:3][1:2,1:2] == BlockIndexRange(Block(1,1),1:2,1:2)
@test Block(1,1)[2:4,2:4][2:3,2:3] == BlockIndexRange(Block(1,1),(3:4,3:4))
@test BlockIndexRange(Block(),())[] == BlockIndex()
@test BlockIndex((2,2,2),(2,)) == BlockIndex((2,2,2),(2,1,)) == BlockIndex((2,2,2),(2,1,1))
Expand Down Expand Up @@ -863,6 +864,10 @@ end
@test b[1:2] ≡ b[1:2][1:2] ≡ BlockSlice(Block(5)[1:2],1:2)
@test Block(b) ≡ Block(5)

bi = BlockSlice(Block(2)[2:4],3:5)
@test Block(bi) ≡ Block(2)
@test bi[2:3] ≡ BlockSlice(Block(2)[3:4],4:5)

@testset "OneTo converts" begin
for b in (BlockSlice(Block(1), 1:1), BlockSlice(Block.(1:1), 1:1), BlockSlice(Block(1)[1:1], 1:1))
@test convert(typeof(b), Base.OneTo(1)) ≡ b
Expand All @@ -880,14 +885,24 @@ end
end
end

@testset "BlockedSlice" begin
b = BlockedSlice([Block(2), Block(1)], mortar([3:5, 1:2]))
@test length(b) == 5
for i in eachindex(b.indices)
@test b[i] === b.indices[i]
@testset "NoncontiguousBlockSlice" begin
bs = NoncontiguousBlockSlice([Block(2),Block(1)], mortar([3:5,1:2]))
@test length(bs) ≡ 5
for i in eachindex(bs.indices)
@test bs[i] ≡ bs.indices[i]
end
@test b[Block(1)] === BlockSlice(Block(2), 3:5)
@test b[Block(2)] === BlockSlice(Block(1), 1:2)
@test bs[Block(1)] ≡ BlockSlice(Block(2), 3:5)
@test bs[Block(2)] ≡ BlockSlice(Block(1), 1:2)
@test BlockArrays._indices(bs) == mortar([3:5,1:2])

b = NoncontiguousBlockSlice(Block(3), 2:4)
@test b[2:3] ≡ NoncontiguousBlockSlice(Block(3)[2:3], 3:4)
@test Block(b) ≡ Block(3)
@test BlockArrays._indices(b) ≡ 2:4

bir = NoncontiguousBlockSlice(Block(3)[3:5], 4:6)
@test Block(bir) ≡ Block(3)
@test bir[2:3] ≡ NoncontiguousBlockSlice(Block(3)[4:5], 5:6)
end

#=
Expand Down
2 changes: 1 addition & 1 deletion test/test_blockrange.jl
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ using BlockArrays, Test
V = view(A, [Block(3), Block(2)])
@test V == [4, 5, 6, 2, 3]
I = parentindices(V)[1]
@test I isa BlockArrays.BlockedSlice{<:Vector{<:Block{1}}}
@test I isa BlockArrays.NoncontiguousBlockSlice{<:Vector{<:Block{1}}}
@test V[Block(1)] == 4:6
@test V[Block(2)] == 2:3
@test view(V, Block(1)) === view(A, Block(3))
Expand Down
20 changes: 18 additions & 2 deletions test/test_blockviews.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ module TestBlockViews

using BlockArrays, ArrayLayouts, Test
using FillArrays
import BlockArrays: BlockedLogicalIndex
import BlockArrays: BlockedLogicalIndex, NoncontiguousBlockSlice
import Base: LogicalIndex

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

@testset "getindex and view with Block-vector" begin
A = BlockArray(reshape(collect(1:(6*12)),6,12), 1:3, 3:5)
V = view(A, [Block(3),Block(2)], [Block(3),Block(2)])
@test V[Block(1,1)] == A[Block(3,3)]
@test V[Block(2,1)] == A[Block(2,3)]
@test V[Block(1,2)] == A[Block(3,2)]
@test V[Block(2,2)] == A[Block(2,2)]
I = parentindices(V)
@test I[1] isa NoncontiguousBlockSlice{<:Vector{<:Block{1}}}
@test I[2] isa NoncontiguousBlockSlice{<:Vector{<:Block{1}}}
@test view(V, Block(1,1)) === view(A, Block(3,3))
@test view(V, Block(2,1)) === view(A, Block(2,3))
@test view(V, Block(1,2)) === view(A, Block(3,2))
@test view(V, Block(2,2)) === view(A, Block(2,2))
end

@testset "non-allocation blocksize" begin
A = BlockArray(randn(5050), 1:100)
@test blocksize(A) == (100,)
Expand Down Expand Up @@ -316,7 +332,7 @@ bview(a, b) = Base.invoke(view, Tuple{AbstractArray,Any}, a, b)
@test a[Block(1)[1:3]] ≡ view(a,Block(1)[1:3]) ≡ view(v,Block(1)[1:3]) ≡ 7:9
end

@testset "blockrange-of-blockreange" begin
@testset "blockrange-of-blockrange" begin
a = mortar([7:9,5:6])
v = view(a,Block.(1:2))
@test view(v, Block(1)) ≡ 7:9
Expand Down
Loading