Skip to content

Commit 470d388

Browse files
authored
copy on A[Block(5)] (#135)
* use layout_getindex for blocks, use typed BlockRange * We should copy on getindex * fixes now that A[Block(1)] copies * Fill sub_materialize ambiguities * Update Project.toml * increase coverage
1 parent e5b71cf commit 470d388

File tree

8 files changed

+66
-14
lines changed

8 files changed

+66
-14
lines changed

Project.toml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name = "BlockArrays"
22
uuid = "8e7c35d0-a365-5155-bbbb-fb81a777f24e"
3-
version = "0.12.14"
3+
version = "0.13.0"
44

55
[deps]
66
ArrayLayouts = "4c555306-a7a7-4459-81d9-ec55ddd5c99a"
@@ -9,9 +9,9 @@ FillArrays = "1a297f60-69ca-5386-bcde-b61e274b549b"
99
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
1010

1111
[compat]
12-
ArrayLayouts = "0.4.8"
12+
ArrayLayouts = "0.4.12"
1313
Compat = "2.2, 3"
14-
FillArrays = "0.9.6, 0.10"
14+
FillArrays = "0.10.1"
1515
julia = "1.1"
1616

1717
[extras]

src/abstractblockarray.jl

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -195,11 +195,11 @@ end
195195
blockcheckbounds(A::AbstractArray{T, N}, i::Block{N}) where {T,N} = blockcheckbounds(A, i.n...)
196196

197197
# Convert to @generated...
198-
@propagate_inbounds Base.getindex( block_arr::AbstractBlockArray{T, N}, block::Block{N}) where {T,N} = getblock(block_arr, block.n...)
198+
@propagate_inbounds Base.getindex( block_arr::AbstractBlockArray{T, N}, block::Block{N}) where {T,N} = copy(getblock(block_arr, block.n...))
199199
@propagate_inbounds Base.setindex!(block_arr::AbstractBlockArray{T, N}, v, block::Block{N}) where {T,N} = setblock!(block_arr, v, block.n...)
200-
@propagate_inbounds Base.getindex( block_arr::AbstractBlockVector, block::Block{1}) = getblock(block_arr, block.n[1])
200+
@propagate_inbounds Base.getindex( block_arr::AbstractBlockVector, block::Block{1}) = copy(getblock(block_arr, block.n[1]))
201201
@propagate_inbounds Base.setindex!(block_arr::AbstractBlockVector, v, block::Block{1}) = setblock!(block_arr, v, block.n[1])
202-
@inline Base.getindex(block_arr::AbstractBlockArray{T,N}, block::Vararg{Block{1}, N}) where {T,N} = getblock(block_arr, (Block(block).n)...)
202+
@inline Base.getindex(block_arr::AbstractBlockArray{T,N}, block::Vararg{Block{1}, N}) where {T,N} = copy(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)...)
204204

205205
"""
@@ -236,3 +236,11 @@ function eachblock(A::AbstractBlockArray)
236236
blockinds = CartesianIndices(axes.(blocklasts.(axes(A)),1))
237237
(view(A, Block(Tuple(I))) for I in blockinds)
238238
end
239+
240+
# Use memory laout for sub-blocks
241+
@inline Base.getindex(A::AbstractMatrix, kr::Colon, jr::Block{1}) = ArrayLayouts.layout_getindex(A, kr, jr)
242+
@inline Base.getindex(A::AbstractMatrix, kr::Block{1}, jr::Colon) = ArrayLayouts.layout_getindex(A, kr, jr)
243+
@inline Base.getindex(A::AbstractMatrix, kr::Block{1}, jr::AbstractVector) = ArrayLayouts.layout_getindex(A, kr, jr)
244+
@inline Base.getindex(A::AbstractArray{T,N}, kr::Block{1}, jrs...) where {T,N} = ArrayLayouts.layout_getindex(A, kr, jrs...)
245+
@inline Base.getindex(A::AbstractArray{T,N}, block::Block{N}) where {T,N} = ArrayLayouts.layout_getindex(A, block)
246+
@inline Base.getindex(A::AbstractMatrix, kr::AbstractVector, jr::Block) = ArrayLayouts.layout_getindex(A, kr, jr)

src/blockindices.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -304,7 +304,7 @@ BlockRange(inds::Vararg{AbstractUnitRange{Int},N}) where {N} =
304304
(:)(start::Block{1}, stop::Block{1}) = BlockRange((first(start.n):first(stop.n),))
305305
(:)(start::Block, stop::Block) = throw(ArgumentError("Use `BlockRange` to construct a cartesian range of blocks"))
306306
Base.BroadcastStyle(::Type{<:BlockRange{1}}) = DefaultArrayStyle{1}()
307-
broadcasted(::DefaultArrayStyle{1}, ::Type{Block}, r::AbstractUnitRange) = Block(first(r)):Block(last(r))
307+
broadcasted(::DefaultArrayStyle{1}, ::Type{Block}, r::AbstractUnitRange) = BlockRange((r,))
308308
broadcasted(::DefaultArrayStyle{1}, ::Type{Int}, block_range::BlockRange{1}) = first(block_range.indices)
309309
broadcasted(::DefaultArrayStyle{0}, ::Type{Int}, block::Block{1}) = Int(block)
310310

src/blocklinalg.jl

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,12 +63,29 @@ sublayout(BL::BlockLayout{MLAY,BLAY}, ::Type{<:Tuple{<:BlockSlice{BlockRange{1,T
6363
sub_materialize(::AbstractBlockLayout, V, _) = BlockArray(V)
6464
sub_materialize(::AbstractBlockLayout, V, ::Tuple{<:BlockedUnitRange}) = BlockArray(V)
6565
sub_materialize(::AbstractBlockLayout, V, ::Tuple{<:BlockedUnitRange,<:BlockedUnitRange}) = BlockArray(V)
66-
# if it's not a block layout, best to use PseudoBlockArray
66+
sub_materialize(::AbstractBlockLayout, V, ::Tuple{<:AbstractUnitRange,<:BlockedUnitRange}) = BlockArray(V)
67+
sub_materialize(::AbstractBlockLayout, V, ::Tuple{<:BlockedUnitRange,<:AbstractUnitRange}) = BlockArray(V)
68+
69+
# if it's not a block layout, best to use PseudoBlockArray to take advantage of strideness
6770
sub_materialize(_, V, ::Tuple{<:BlockedUnitRange}) = PseudoBlockArray(V)
6871
sub_materialize(_, V, ::Tuple{<:BlockedUnitRange,<:BlockedUnitRange}) = PseudoBlockArray(V)
6972
sub_materialize(_, V, ::Tuple{<:AbstractUnitRange,<:BlockedUnitRange}) = PseudoBlockArray(V)
7073
sub_materialize(_, V, ::Tuple{<:BlockedUnitRange,<:AbstractUnitRange}) = PseudoBlockArray(V)
7174

75+
# Special for FillArrays.jl
76+
sub_materialize(::ArrayLayouts.AbstractFillLayout, V, ax::Tuple{<:BlockedUnitRange,<:AbstractUnitRange}) =
77+
Fill(FillArrays.getindex_value(V), ax)
78+
sub_materialize(::ArrayLayouts.OnesLayout, V, ax::Tuple{<:BlockedUnitRange,<:AbstractUnitRange}) =
79+
Ones{eltype(V)}(ax)
80+
sub_materialize(::ArrayLayouts.ZerosLayout, V, ax::Tuple{<:BlockedUnitRange,<:AbstractUnitRange}) =
81+
Zeros{eltype(V)}(ax)
82+
sub_materialize(::ArrayLayouts.AbstractFillLayout, V, ax::Tuple{<:AbstractUnitRange,<:BlockedUnitRange}) =
83+
Fill(FillArrays.getindex_value(V), ax)
84+
sub_materialize(::ArrayLayouts.OnesLayout, V, ax::Tuple{<:AbstractUnitRange,<:BlockedUnitRange}) =
85+
Ones{eltype(V)}(ax)
86+
sub_materialize(::ArrayLayouts.ZerosLayout, V, ax::Tuple{<:AbstractUnitRange,<:BlockedUnitRange}) =
87+
Zeros{eltype(V)}(ax)
88+
7289
conjlayout(::Type{T}, ::BlockLayout{MLAY,BLAY}) where {T<:Complex,MLAY,BLAY} = BlockLayout{MLAY,typeof(conjlayout(T,BLAY()))}()
7390
conjlayout(::Type{T}, ::BlockLayout{MLAY,BLAY}) where {T<:Real,MLAY,BLAY} = BlockLayout{MLAY,BLAY}()
7491

src/blocks.jl

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -79,19 +79,16 @@ Base.IteratorEltype(::Type{<:BlocksView}) = Base.EltypeUnknown()
7979
Base.size(a::BlocksView) = blocksize(a.array)
8080
Base.axes(a::BlocksView) = map(br -> only(br.indices), blockaxes(a.array))
8181

82-
@propagate_inbounds _view(a::PseudoBlockArray, i::Block) = a[i]
83-
@propagate_inbounds _view(a::AbstractBlockArray, i::Block) = view(a, i)
84-
8582
#=
8683
This is broken for now. See: https://github.com/JuliaArrays/BlockArrays.jl/issues/120
8784
# IndexLinear implementations
88-
@propagate_inbounds Base.getindex(a::BlocksView, i::Int) = _view(a.array, Block(i))
85+
@propagate_inbounds Base.getindex(a::BlocksView, i::Int) = view(a.array, Block(i))
8986
@propagate_inbounds Base.setindex!(a::BlocksView, b, i::Int) = copyto!(a[i], b)
9087
=#
9188

9289
# IndexCartesian implementations
9390
@propagate_inbounds Base.getindex(a::BlocksView{T,N}, i::Vararg{Int,N}) where {T,N} =
94-
_view(a.array, Block(i...))
91+
getblock(a.array, i...)
9592
@propagate_inbounds Base.setindex!(a::BlocksView{T,N}, b, i::Vararg{Int,N}) where {T,N} =
9693
copyto!(a[i...], b)
9794

src/views.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ _splatmap(f, t::Tuple) = (f(t[1])..., _splatmap(f, tail(t))...)
7171
A::BlockArray{<:Any, N},
7272
I::Vararg{BlockSlice{<:BlockIndexRange{1}}, N}) where {N}
7373
@_propagate_inbounds_meta
74-
B = A[map(x -> x.block.block, I)...]
74+
B = getblock(A, map(x -> Int(x.block.block), I)...)
7575
return view(B, _splatmap(x -> x.block.indices, I)...)
7676
end
7777

test/test_blockarrayinterface.jl

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,29 @@ end
127127
@test A[Block.(1:2)] isa Fill
128128
@test_broken 2A Fill(4,axes(A))
129129

130+
F = Fill(2, (blockedrange([1,2,2]),blockedrange(1:3)))
131+
@test F[Block(2,2)] F[Block(2),Block(2)] Fill(2, 2,2)
132+
@test F[Block(2),1:5] Fill(2, 2,5)
133+
@test F[1:5,Block(2)] Fill(2, 5,2)
134+
@test F[:,Block(2)] Fill(2, (axes(F,1),Base.OneTo(2)))
135+
@test F[Block(2),:] Fill(2, (Base.OneTo(2),axes(F,2)))
136+
@test F[Block.(1:2),Block.(1:2)] == Fill(2, (blockedrange([1,2]),blockedrange(1:2)))
137+
138+
O = Ones{Int}((blockedrange([1,2,2]),blockedrange(1:3)))
139+
@test O[Block(2,2)] O[Block(2),Block(2)] Ones{Int}(2,2)
140+
@test O[Block(2),1:5] Ones{Int}(2,5)
141+
@test O[1:5,Block(2)] Ones{Int}(5,2)
142+
@test O[:,Block(2)] Ones{Int}((axes(O,1),Base.OneTo(2)))
143+
@test O[Block(2),:] Ones{Int}((Base.OneTo(2),axes(O,2)))
144+
@test O[Block.(1:2),Block.(1:2)] == Ones{Int}((blockedrange([1,2]),blockedrange(1:2)))
145+
146+
Z = Zeros{Int}((blockedrange([1,2,2]),blockedrange(1:3)))
147+
@test Z[Block(2,2)] Z[Block(2),Block(2)] Zeros{Int}(2,2)
148+
@test Z[Block(2),1:5] Zeros{Int}(2,5)
149+
@test Z[1:5,Block(2)] Zeros{Int}(5,2)
150+
@test Z[:,Block(2)] Zeros{Int}((axes(Z,1),Base.OneTo(2)))
151+
@test Z[Block(2),:] Zeros{Int}((Base.OneTo(2),axes(Z,2)))
152+
@test Z[Block.(1:2),Block.(1:2)] == Zeros{Int}((blockedrange([1,2]),blockedrange(1:2)))
130153

131154
B = Eye((blockedrange([1,2]),))
132155
@test B[Block(2,2)] == Matrix(I,2,2)

test/test_blockviews.jl

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,4 +258,11 @@ using BlockArrays, Test, Base64
258258
@test A[1:3,Block.(1:2),1:3] isa BlockArray
259259
@test B[1:3,Block.(1:2),1:3] isa PseudoBlockArray
260260
end
261+
262+
@testset "BlockArray BlockRange view" begin
263+
a = BlockArray(randn(6), 1:3)
264+
v = view(a, Block(3)[1:2])
265+
v[1] = 5
266+
@test a[4] == 5
267+
end
261268
end

0 commit comments

Comments
 (0)