Skip to content

Introduce BlockIndices that generalizes BlockIndexRange to non-contiguous slicing #483

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 4 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 @@ -23,6 +23,7 @@ BlockedOneTo
BlockedUnitRange
BlockRange
BlockIndexRange
BlockIndices
BlockSlice
unblock
SubBlockIterator
Expand Down
2 changes: 1 addition & 1 deletion src/BlockArrays.jl
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ using LinearAlgebra, ArrayLayouts, FillArrays
# AbstractBlockArray interface exports
export AbstractBlockArray, AbstractBlockMatrix, AbstractBlockVector, AbstractBlockVecOrMat
export Block, getblock, getblock!, setblock!, eachblock, blocks
export blockaxes, blocksize, blocklength, blockcheckbounds, BlockBoundsError, BlockIndex, BlockIndexRange
export blockaxes, blocksize, blocklength, blockcheckbounds, BlockBoundsError, BlockIndex, BlockIndexRange, BlockIndices
export blocksizes, blocklengths, blocklasts, blockfirsts, blockisequal, blockequals, blockisapprox
export eachblockaxes
export BlockRange, blockedrange, BlockedUnitRange, BlockedOneTo
Expand Down
14 changes: 7 additions & 7 deletions src/blockaxis.jl
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@
@propagate_inbounds getindex(b::AbstractArray, K::BlockIndex{1}, J::BlockIndex{1}...) =
b[BlockIndex(tuple(K, J...))]

@propagate_inbounds getindex(b::AbstractArray{T,N}, K::BlockIndexRange{N}) where {T,N} = b[block(K)][K.indices...]
@propagate_inbounds getindex(b::LayoutArray{T,N}, K::BlockIndexRange{N}) where {T,N} = b[block(K)][K.indices...]
@propagate_inbounds getindex(b::LayoutArray{T,1}, K::BlockIndexRange{1}) where {T} = b[block(K)][K.indices...]
@propagate_inbounds getindex(b::AbstractArray{T,N}, K::BlockIndices{N}) where {T,N} = b[block(K)][K.indices...]
@propagate_inbounds getindex(b::LayoutArray{T,N}, K::BlockIndices{N}) where {T,N} = b[block(K)][K.indices...]
@propagate_inbounds getindex(b::LayoutArray{T,1}, K::BlockIndices{1}) where {T} = b[block(K)][K.indices...]

function findblockindex(b::AbstractVector, k::Integer)
@boundscheck k in b || throw(BoundsError())
Expand Down Expand Up @@ -539,11 +539,11 @@ end

getindex(b::AbstractBlockedUnitRange, KR::AbstractVector{<:Block{1}}) = mortar([b[K] for K in KR])
getindex(b::AbstractBlockedUnitRange, KR::AbstractVector{<:AbstractVector{<:Block{1}}}) = mortar([b[K] for K in KR])
getindex(b::AbstractBlockedUnitRange, Kkr::BlockIndexRange{1}) = b[block(Kkr)][Kkr.indices...]
getindex(b::AbstractBlockedUnitRange, Kkr::BlockIndices{1}) = b[block(Kkr)][Kkr.indices...]
getindex(b::AbstractBlockedUnitRange, KR::AbstractVector{<:BlockIndex{1}}) = [b[K] for K in KR]
getindex(b::AbstractBlockedUnitRange, KR::AbstractVector{<:BlockIndexRange{1}}) = mortar([b[K] for K in KR])
getindex(b::AbstractBlockedUnitRange, KR::AbstractVector{<:BlockIndices{1}}) = mortar([b[K] for K in KR])
getindex(b::AbstractBlockedUnitRange, KR::AbstractVector{<:AbstractVector{<:BlockIndex{1}}}) = mortar([b[K] for K in KR])
getindex(b::AbstractBlockedUnitRange, KR::AbstractVector{<:AbstractVector{<:BlockIndexRange{1}}}) = mortar([b[K] for K in KR])
getindex(b::AbstractBlockedUnitRange, KR::AbstractVector{<:AbstractVector{<:BlockIndices{1}}}) = mortar([b[K] for K in KR])
getindex(b::AbstractBlockedUnitRange, KR::AbstractVector{<:AbstractVector{<:AbstractVector{<:BlockIndex{1}}}}) = mortar([b[K] for K in KR])

_searchsortedfirst(a::AbstractVector, k) = searchsortedfirst(a, k)
Expand All @@ -567,7 +567,7 @@ Base.dataids(b::AbstractBlockedUnitRange) = Base.dataids(blocklasts(b))
Base.checkindex(::Type{Bool}, b::BlockRange, K::Integer) = checkindex(Bool, Integer.(b), K)
Base.checkindex(::Type{Bool}, b::AbstractUnitRange{<:Integer}, K::Block{1}) = checkindex(Bool, blockaxes(b,1), Integer(K))

function Base.checkindex(::Type{Bool}, axis::AbstractBlockedUnitRange, ind::BlockIndexRange{1})
function Base.checkindex(::Type{Bool}, axis::AbstractBlockedUnitRange, ind::BlockIndices{1})
checkindex(Bool, axis, first(ind)) && checkindex(Bool, axis, last(ind))
end
function Base.checkindex(::Type{Bool}, axis::AbstractBlockedUnitRange, ind::BlockIndex{1})
Expand Down
104 changes: 77 additions & 27 deletions src/blockindices.jl
Original file line number Diff line number Diff line change
Expand Up @@ -207,19 +207,68 @@ end
checkbounds(::Type{Bool}, A::AbstractArray{<:Any,N}, I::AbstractArray{<:BlockIndex{N}}) where N =
all(i -> checkbounds(Bool, A, i), I)

struct BlockIndexRange{N,R<:Tuple{Vararg{AbstractUnitRange{<:Integer},N}},I<:Tuple{Vararg{Integer,N}},BI<:Integer} <: AbstractArray{BlockIndex{N,NTuple{N,BI},I},N}
struct BlockIndices{N,R<:Tuple{Vararg{AbstractVector,N}},I<:Tuple{Vararg{Any,N}},BI} <: AbstractArray{BlockIndex{N,NTuple{N,BI},I},N}
block::Block{N,BI}
indices::R
function BlockIndexRange(block::Block{N,BI}, inds::R) where {N,BI<:Integer,R<:Tuple{Vararg{AbstractUnitRange{<:Integer},N}}}
function BlockIndices(block::Block{N,BI}, inds::R) where {N,BI<:Integer,R<:Tuple{Vararg{AbstractVector,N}}}
I = Tuple{eltype.(inds)...}
return new{N,R,I,BI}(block,inds)
end
end

"""
BlockIndices(block, startind:stopind)
Represents a cartesian product of indices inside a block.
It can be constructed and used to index into `BlockArrays` in the following manner:
```jldoctest
julia> BlockIndices(Block(1,2), ([1,3],[2,4]))
Block(1, 2)[[1, 3], [2, 4]]

julia> Block(1)[[1,3]] == BlockIndices(Block(1), [1,3])
true

julia> Block(1,2)[[1,3],[2,4]] == BlockIndices(Block(1,2), ([1,3],[2,4]))
true

julia> BlockIndices((Block(1)[[1,3]], Block(2)[[2,4]]))
Block(1, 2)[[1, 3], [2, 4]]

julia> arr = Array(reshape(1:25, (5,5)));

julia> a = BlockedArray(arr, [3,2], [1,4])
2×2-blocked 5×5 BlockedMatrix{Int64}:
1 │ 6 11 16 21
2 │ 7 12 17 22
3 │ 8 13 18 23
───┼────────────────
4 │ 9 14 19 24
5 │ 10 15 20 25

julia> a[Block(1,2)[[1,3],[2,4]]]
2×2 Matrix{Int64}:
11 21
13 23

julia> a[Block(2,2)[[2],[2,4]]]
1×2 Matrix{Int64}:
15 25
```
"""
BlockIndices

BlockIndices(block::Block{N}, inds::Vararg{AbstractVector,N}) where {N} =
BlockIndices(block,inds)
function BlockIndices(inds::Tuple{BlockIndices{1},Vararg{BlockIndices{1}}})
BlockIndices(Block(block.(inds)), map(ind -> ind.indices[1], inds))
end

const BlockIndexRange{N,R<:Tuple{Vararg{AbstractUnitRange{<:Integer},N}},I<:Tuple{Vararg{Any,N}},BI} = BlockIndices{N,R,I,BI}

"""
BlockIndexRange(block, startind:stopind)

Represents a cartesian range inside a block.
Represents a cartesian range inside a block. Type alias for `BlockIndices` with
the indices constrained to ranges.

It can be constructed and used to index into `BlockArrays` in the following manner:

Expand Down Expand Up @@ -260,60 +309,62 @@ julia> a[Block(2,2)[1:2,3:4]]
"""
BlockIndexRange

BlockIndexRange(block::Block{N}, inds::Tuple{Vararg{AbstractUnitRange{<:Integer},N}}) where {N} =
BlockIndices(block, inds)
BlockIndexRange(block::Block{N}, inds::Vararg{AbstractUnitRange{<:Integer},N}) where {N} =
BlockIndexRange(block,inds)
BlockIndices(block,inds)

function BlockIndexRange(inds::Tuple{BlockIndexRange{1},Vararg{BlockIndexRange{1}}})
BlockIndexRange(Block(block.(inds)), map(ind -> ind.indices[1], inds))
end

block(R::BlockIndexRange) = R.block
block(R::BlockIndices) = R.block

copy(R::BlockIndexRange) = BlockIndexRange(R.block, map(copy, R.indices))
copy(R::BlockIndices) = BlockIndices(R.block, map(copy, R.indices))

getindex(::Block{0}) = BlockIndex()
getindex(B::Block{N}, inds::Vararg{Integer,N}) where N = BlockIndex(B,inds)
getindex(B::Block{N}, inds::Vararg{AbstractUnitRange{<:Integer},N}) where N = BlockIndexRange(B,inds)
getindex(B::Block{N}, inds::Vararg{AbstractVector,N}) where N = BlockIndices(B,inds)
getindex(B::Block{1}, inds::Colon) = B
getindex(B::Block{1}, inds::Base.Slice) = B

getindex(B::BlockIndexRange{0}) = B.block[]
@propagate_inbounds getindex(B::BlockIndexRange{N}, kr::Vararg{AbstractUnitRange{<:Integer},N}) where {N} = BlockIndexRange(B.block, map(getindex, B.indices, kr))
@propagate_inbounds getindex(B::BlockIndexRange{N}, inds::Vararg{Int,N}) where N = B.block[Base.reindex(B.indices, inds)...]
getindex(B::BlockIndices{0}) = B.block[]
@propagate_inbounds getindex(B::BlockIndices{N}, kr::Vararg{AbstractVector,N}) where {N} = BlockIndices(B.block, map(getindex, B.indices, kr))
@propagate_inbounds getindex(B::BlockIndices{N}, inds::Vararg{Int,N}) where N = B.block[Base.reindex(B.indices, inds)...]

eltype(R::BlockIndexRange) = eltype(typeof(R))
eltype(::Type{BlockIndexRange{N}}) where {N} = BlockIndex{N}
eltype(::Type{BlockIndexRange{N,R,I,BI}}) where {N,R,I,BI} = BlockIndex{N,NTuple{N,BI},I}
IteratorSize(::Type{<:BlockIndexRange}) = Base.HasShape{1}()
eltype(R::BlockIndices) = eltype(typeof(R))
eltype(::Type{BlockIndices{N}}) where {N} = BlockIndex{N}
eltype(::Type{BlockIndices{N,R,I,BI}}) where {N,R,I,BI} = BlockIndex{N,NTuple{N,BI},I}
IteratorSize(::Type{<:BlockIndices}) = Base.HasShape{1}()


first(iter::BlockIndexRange) = BlockIndex(iter.block.n, map(first, iter.indices))
last(iter::BlockIndexRange) = BlockIndex(iter.block.n, map(last, iter.indices))
first(iter::BlockIndices) = BlockIndex(iter.block.n, map(first, iter.indices))
last(iter::BlockIndices) = BlockIndex(iter.block.n, map(last, iter.indices))

@inline function iterate(iter::BlockIndexRange)
@inline function iterate(iter::BlockIndices)
iterfirst, iterlast = first(iter), last(iter)
if any(map(>, iterfirst.α, iterlast.α))
return nothing
end
iterfirst, iterfirst
end
@inline function iterate(iter::BlockIndexRange, state)
@inline function iterate(iter::BlockIndices, state)
nextstate = BlockIndex(state.I, inc(state.α, first(iter).α, last(iter).α))
nextstate.α[end] > last(iter.indices[end]) && return nothing
nextstate, nextstate
end

size(iter::BlockIndexRange) = map(dimlength, first(iter).α, last(iter).α)
length(iter::BlockIndexRange) = prod(size(iter))
size(iter::BlockIndices) = map(dimlength, first(iter).α, last(iter).α)
length(iter::BlockIndices) = prod(size(iter))


Block(bs::BlockIndexRange) = bs.block
Block(bs::BlockIndices) = bs.block

##
# checkindex
##

function checkbounds(::Type{Bool}, A::AbstractArray{<:Any,N}, I::BlockIndexRange{N}) where N
function checkbounds(::Type{Bool}, A::AbstractArray{<:Any,N}, I::BlockIndices{N}) where N
bl = block(I)
checkbounds(Bool, A, bl) || return false
# TODO: Replace with `eachblockaxes(A)[bl]` once that is defined.
Expand All @@ -334,10 +385,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,7 +399,7 @@ struct BlockSlice{BB,T<:Integer,INDS<:AbstractUnitRange{T}} <: AbstractUnitRange
end

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

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

for f in (:axes, :unsafe_indices, :axes1, :first, :last, :size, :length,
:unsafe_length, :start)
Expand All @@ -366,8 +418,6 @@ _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)

Expand Down
4 changes: 2 additions & 2 deletions src/show.jl
Original file line number Diff line number Diff line change
Expand Up @@ -186,13 +186,13 @@ function Base.show(io::IO, B::BlockIndex)
print(io, "]")
end

function Base.show(io::IO, B::BlockIndexRange)
function Base.show(io::IO, B::BlockIndices)
show(io, Block(B))
print(io, "[")
print_tuple_elements(io, B.indices)
print(io, "]")
end
Base.show(io::IO, ::MIME"text/plain", B::BlockIndexRange) = show(io, B)
Base.show(io::IO, ::MIME"text/plain", B::BlockIndices) = show(io, B)

Base.show(io::IO, mimetype::MIME"text/plain", a::AbstractBlockedUnitRange) =
Base.invoke(show, Tuple{typeof(io),MIME"text/plain",AbstractArray},io, mimetype, a)
Expand Down
36 changes: 18 additions & 18 deletions src/views.jl
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ unblock(A, ::Tuple{}, I) = BlockSlice(first(I),Base.OneTo(length(I[1])))

to_index(::Block) = throw(ArgumentError("Block must be converted by to_indices(...)"))
to_index(::BlockIndex) = throw(ArgumentError("BlockIndex must be converted by to_indices(...)"))
to_index(::BlockIndexRange) = throw(ArgumentError("BlockIndexRange must be converted by to_indices(...)"))
to_index(::BlockIndices) = throw(ArgumentError("BlockIndices must be converted by to_indices(...)"))
to_index(::BlockRange) = throw(ArgumentError("BlockRange must be converted by to_indices(...)"))


Expand All @@ -36,15 +36,15 @@ to_index(::BlockRange) = throw(ArgumentError("BlockRange must be converted by to
(unblock(A, inds, I), to_indices(A, _maybetail(inds), tail(I))...)
@inline to_indices(A, inds, I::Tuple{BlockIndex{1}, Vararg{Any}}) =
(inds[1][I[1]], to_indices(A, _maybetail(inds), tail(I))...)
@inline to_indices(A, inds, I::Tuple{BlockIndexRange{1}, Vararg{Any}}) =
@inline to_indices(A, inds, I::Tuple{BlockIndices{1}, Vararg{Any}}) =
(unblock(A, inds, I), to_indices(A, _maybetail(inds), tail(I))...)
@inline to_indices(A, inds, I::Tuple{AbstractVector{<:BlockIndex{1}}, Vararg{Any}}) =
(unblock(A, inds, I), to_indices(A, _maybetail(inds), tail(I))...)
@inline to_indices(A, inds, I::Tuple{AbstractVector{<:BlockIndexRange{1}}, Vararg{Any}}) =
@inline to_indices(A, inds, I::Tuple{AbstractVector{<:BlockIndices{1}}, Vararg{Any}}) =
(unblock(A, inds, I), to_indices(A, _maybetail(inds), tail(I))...)
@inline to_indices(A, inds, I::Tuple{AbstractVector{<:AbstractVector{<:BlockIndex{1}}}, Vararg{Any}}) =
(unblock(A, inds, I), to_indices(A, _maybetail(inds), tail(I))...)
@inline to_indices(A, inds, I::Tuple{AbstractVector{<:AbstractVector{<:BlockIndexRange{1}}}, Vararg{Any}}) =
@inline to_indices(A, inds, I::Tuple{AbstractVector{<:AbstractVector{<:BlockIndices{1}}}, Vararg{Any}}) =
(unblock(A, inds, I), to_indices(A, _maybetail(inds), tail(I))...)
@inline to_indices(A, inds, I::Tuple{AbstractVector{<:AbstractVector{<:AbstractVector{<:BlockIndex{1}}}}, Vararg{Any}}) =
(unblock(A, inds, I), to_indices(A, _maybetail(inds), tail(I))...)
Expand All @@ -58,21 +58,21 @@ to_index(::BlockRange) = throw(ArgumentError("BlockRange must be converted by to
to_indices(A, inds, (BlockRange.(tuple.(I[1].indices))..., tail(I)...))
@inline to_indices(A, inds, I::Tuple{BlockIndex, Vararg{Any}}) =
to_indices(A, inds, (BlockIndex.(I[1].I, I[1].α)..., tail(I)...))
@inline to_indices(A, inds, I::Tuple{BlockIndexRange, Vararg{Any}}) =
to_indices(A, inds, (BlockIndexRange.(Block.(I[1].block.n), tuple.(I[1].indices))..., tail(I)...))
@inline to_indices(A, inds, I::Tuple{BlockIndices, Vararg{Any}}) =
to_indices(A, inds, (BlockIndices.(Block.(I[1].block.n), tuple.(I[1].indices))..., tail(I)...))

# In 0.7, we need to override to_indices to avoid calling linearindices
@inline to_indices(A, I::Tuple{BlockIndexRange, Vararg{Any}}) = to_indices(A, axes(A), I)
@inline to_indices(A, I::Tuple{BlockIndices, Vararg{Any}}) = to_indices(A, axes(A), I)
@inline to_indices(A, I::Tuple{BlockIndex, Vararg{Any}}) = to_indices(A, axes(A), I)
@inline to_indices(A, I::Tuple{Block, Vararg{Any}}) = to_indices(A, axes(A), I)
@inline to_indices(A, I::Tuple{BlockRange, Vararg{Any}}) = to_indices(A, axes(A), I)
@inline to_indices(A, I::Tuple{AbstractVector{<:Block{1}}, Vararg{Any}}) = to_indices(A, axes(A), I)
@inline to_indices(A, I::Tuple{AbstractVector{<:BlockRange{1}}, Vararg{Any}}) = to_indices(A, axes(A), I)
@inline to_indices(A, I::Tuple{AbstractVector{<:AbstractVector{<:Block{1}}}, Vararg{Any}}) = to_indices(A, axes(A), I)
@inline to_indices(A, I::Tuple{AbstractVector{<:BlockIndex{1}}, Vararg{Any}}) = to_indices(A, axes(A), I)
@inline to_indices(A, I::Tuple{AbstractVector{<:BlockIndexRange{1}}, Vararg{Any}}) = to_indices(A, axes(A), I)
@inline to_indices(A, I::Tuple{AbstractVector{<:BlockIndices{1}}, Vararg{Any}}) = to_indices(A, axes(A), I)
@inline to_indices(A, I::Tuple{AbstractVector{<:AbstractVector{<:BlockIndex{1}}}, Vararg{Any}}) = to_indices(A, axes(A), I)
@inline to_indices(A, I::Tuple{AbstractVector{<:AbstractVector{<:BlockIndexRange{1}}}, Vararg{Any}}) = to_indices(A, axes(A), I)
@inline to_indices(A, I::Tuple{AbstractVector{<:AbstractVector{<:BlockIndices{1}}}, Vararg{Any}}) = to_indices(A, axes(A), I)
@inline to_indices(A, I::Tuple{AbstractVector{<:AbstractVector{<:AbstractVector{<:BlockIndex{1}}}}, Vararg{Any}}) = to_indices(A, axes(A), I)

## BlockedLogicalIndex
Expand Down Expand Up @@ -119,8 +119,8 @@ checkindex(::Type{Bool}, inds::AbstractUnitRange, i::BlockedLogicalIndex) = chec
(blockcollect(I[1]), ensure_indexable(tail(I))...)

@propagate_inbounds reindex(idxs::Tuple{BlockSlice{<:BlockRange}, Vararg{Any}},
subidxs::Tuple{BlockSlice{<:BlockIndexRange}, Vararg{Any}}) =
(BlockSlice(BlockIndexRange(Block(idxs[1].block.indices[1][Int(subidxs[1].block.block)]),
subidxs::Tuple{BlockSlice{<:BlockIndices}, Vararg{Any}}) =
(BlockSlice(BlockIndices(Block(idxs[1].block.indices[1][Int(subidxs[1].block.block)]),
subidxs[1].block.indices),
idxs[1].indices[subidxs[1].indices]),
reindex(tail(idxs), tail(subidxs))...)
Expand All @@ -143,36 +143,36 @@ _splatmap(f, t::Tuple) = (f(t[1])..., _splatmap(f, tail(t))...)
# path in `AbstractBlockStyle` broadcasting.
@propagate_inbounds function Base.unsafe_view(
A::BlockArray{<:Any, N},
I::Vararg{BlockSlice{<:BlockIndexRange{1}}, N}) where {N}
I::Vararg{BlockSlice{<:BlockIndices{1}}, N}) where {N}
B = view(A, map(block, I)...)
return view(B, _splatmap(x -> x.block.indices, I)...)
end

@propagate_inbounds function Base.unsafe_view(
A::BlockedArray{<:Any, N},
I::Vararg{BlockSlice{<:BlockIndexRange{1}}, N}) where {N}
I::Vararg{BlockSlice{<:BlockIndices{1}}, N}) where {N}
return view(A.blocks, map(x -> x.indices, I)...)
end

@propagate_inbounds function Base.unsafe_view(
A::ReshapedArray{<:Any, N, <:AbstractBlockArray{<:Any, M}},
I::Vararg{BlockSlice{<:BlockIndexRange{1}}, N}) where {N, M}
I::Vararg{BlockSlice{<:BlockIndices{1}}, N}) where {N, M}
# Note: assuming that I[M+1:end] are verified to be singletons
return reshape(view(A.parent, I[1:M]...), Val(N))
end

@propagate_inbounds function Base.unsafe_view(
A::Array,
I1::BlockSlice{<:BlockIndexRange{1}},
Is::Vararg{BlockSlice{<:BlockIndexRange{1}}},
I1::BlockSlice{<:BlockIndices{1}},
Is::Vararg{BlockSlice{<:BlockIndices{1}}},
)
I = (I1, Is...)
@assert ndims(A) == length(I)
return view(A, map(x -> x.indices, I)...)
end

# make sure we reindex correctrly
@inline function Base._maybe_reindex(V, I::Tuple{BlockSlice{<:BlockIndexRange{1}}, Vararg{Any}}, ::Tuple{})
# make sure we reindex correctly
@inline function Base._maybe_reindex(V, I::Tuple{BlockSlice{<:BlockIndices{1}}, Vararg{Any}}, ::Tuple{})
@inbounds idxs = to_indices(V.parent, reindex(V.indices, I))
view(V.parent, idxs...)
end
Expand Down
8 changes: 8 additions & 0 deletions test/test_blockarrays.jl
Original file line number Diff line number Diff line change
Expand Up @@ -998,6 +998,14 @@ end
@test A[Block(1)[1], Block(1)[1:1]] == BlockArray(A)[Block(1)[1], Block(1)[1:1]] == A[1,1:1]
end

@testset "BlockIndices" begin
a = BlockedArray(randn(5), [2,3])
@test a[Block(2)[[1,3]]] == a[[3,5]]
A = BlockedArray(randn(5,5), [2,3], [2,3])
@test A[Block(2,2)[[1,3],[2,3]]] == A[[3,5],[4,5]]
@test A[Block(2,2)[[1,3],1:2]] == A[[3,5],3:4]
end

@testset "BlockIndexRange blocks" begin
a = mortar([Block(1)[1:2], Block(3)[2:3]])
@test a[Block(1)] === Block(1)[1:2]
Expand Down
Loading
Loading