Skip to content

Commit d430576

Browse files
authored
[RFC] Add each blockiterator, fixes #100 (#101)
* Add a simple eachblock iterator * Generate eachblock indices more safely (maybe?) * Add to docs * Add tests for eachblock * Move eachblock tests to test_blockindices.jl
1 parent 2919e9e commit d430576

File tree

4 files changed

+53
-2
lines changed

4 files changed

+53
-2
lines changed

docs/src/lib/public.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ blocksize
3636
blockfirsts
3737
blocklasts
3838
blocklengths
39+
eachblock
3940
getblock
4041
getblock!
4142
setblock!

src/BlockArrays.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ using LinearAlgebra
44

55
# AbstractBlockArray interface exports
66
export AbstractBlockArray, AbstractBlockMatrix, AbstractBlockVector, AbstractBlockVecOrMat
7-
export Block, getblock, getblock!, setblock!
7+
export Block, getblock, getblock!, setblock!, eachblock
88
export blockaxes, blocksize, blocklength, blockcheckbounds, BlockBoundsError, BlockIndex
99
export blocklengths, blocklasts, blockfirsts, blockisequal
1010
export BlockRange, blockedrange, BlockedUnitRange

src/abstractblockarray.jl

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,3 +201,38 @@ blockcheckbounds(A::AbstractArray{T, N}, i::Block{N}) where {T,N} = blockcheckbo
201201
@propagate_inbounds Base.setindex!(block_arr::AbstractBlockVector, v, block::Block{1}) = setblock!(block_arr, v, block.n[1])
202202
@inline Base.getindex(block_arr::AbstractBlockArray{T,N}, block::Vararg{Block{1}, N}) where {T,N} = getblock(block_arr, (Block(block).n)...)
203203
@inline Base.setindex!(block_arr::AbstractBlockArray{T,N}, v, block::Vararg{Block{1}, N}) where {T,N} = setblock!(block_arr, v, (Block(block).n)...)
204+
205+
"""
206+
eachblock(A::AbstractBlockArray)
207+
208+
Create a generator that iterates over each block of an `AbstractBlockArray`
209+
returning views.
210+
211+
```jldoctest; setup = quote using BlockArrays end
212+
julia> v = Array(reshape(1:6, (2, 3)))
213+
2×3 Array{Int64,2}:
214+
1 3 5
215+
2 4 6
216+
217+
julia> A = BlockArray(v, [1,1], [2,1])
218+
2×2-blocked 2×3 BlockArray{Int64,2}:
219+
1 3 │ 5
220+
──────┼───
221+
2 4 │ 6
222+
223+
julia> Matrix.(collect(eachblock(A)))
224+
2×2 Array{Array{Int64,2},2}:
225+
[1 3] [5]
226+
[2 4] [6]
227+
228+
julia> sum.(eachblock(A))
229+
2×2 Array{Int64,2}:
230+
4 5
231+
6 6
232+
```
233+
"""
234+
function eachblock(A::AbstractBlockArray)
235+
# blockinds = CartesianIndices(blocksize(A))
236+
blockinds = CartesianIndices(axes.(blocklasts.(axes(A)),1))
237+
(view(A, Block(Tuple(I))) for I in blockinds)
238+
end

test/test_blockindices.jl

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -271,4 +271,19 @@ end
271271
@test !BlockArrays.sortedin(2,v)
272272
@test !BlockArrays.sortedin(0,v)
273273
@test !BlockArrays.sortedin(5,v)
274-
end
274+
end
275+
276+
@testset "eachblock" begin
277+
v = Array(reshape(1:6, (2, 3)))
278+
A = BlockArray(v, [1,1], [2,1])
279+
B = PseudoBlockArray(v, [1,1], [2,1])
280+
281+
# test that contents match
282+
@test collect(eachblock(A)) == collect(eachblock(B)) == A.blocks
283+
284+
# test that eachblock returns views
285+
first(eachblock(A))[1,2] = 0
286+
@test A[1,2] == 0
287+
first(eachblock(B))[1,2] = 0
288+
@test B[1,2] == 0
289+
end

0 commit comments

Comments
 (0)