Skip to content

Commit 0d30a97

Browse files
authored
Support integers in similar, blockedindexing of Matrix (#196)
* Support integers in similar, blockedindexing of Matrix * Remove QR test to support ArrayLayouts v0.7.7 change to LU * resize! for PseudoBlockVector, avoid `@inbounds` * add docs, increase cov
1 parent 4d1e02f commit 0d30a97

File tree

7 files changed

+81
-58
lines changed

7 files changed

+81
-58
lines changed

Project.toml

Lines changed: 1 addition & 1 deletion
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.16.8"
3+
version = "0.16.9"
44

55
[deps]
66
ArrayLayouts = "4c555306-a7a7-4459-81d9-ec55ddd5c99a"

docs/src/lib/public.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ Base.popfirst!
6666

6767
```@docs
6868
PseudoBlockArray
69+
Base.resize!
6970
```
7071

7172

src/BlockArrays.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ import Base: @propagate_inbounds, Array, to_indices, to_index,
2828
RangeIndex, Int, Integer, Number,
2929
+, -, *, /, \, min, max, isless, in, copy, copyto!, axes, @deprecate,
3030
BroadcastStyle, checkbounds, throw_boundserror,
31-
ones, zeros, intersect, Slice
31+
ones, zeros, intersect, Slice, resize!
3232
using Base: ReshapedArray, dataids
3333

3434

src/blockarray.jl

Lines changed: 15 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -351,31 +351,29 @@ end
351351
###########################
352352

353353

354-
@inline Base.similar(block_array::AbstractArray, ::Type{T}, axes::Tuple{BlockedUnitRange,Vararg{AbstractUnitRange{Int}}}) where T =
355-
BlockArray{T}(undef, axes)
356-
@inline Base.similar(block_array::AbstractArray, ::Type{T}, axes::Tuple{BlockedUnitRange,BlockedUnitRange,Vararg{AbstractUnitRange{Int}}}) where T =
357-
BlockArray{T}(undef, axes)
358-
@inline Base.similar(block_array::AbstractArray, ::Type{T}, axes::Tuple{AbstractUnitRange{Int},BlockedUnitRange,Vararg{AbstractUnitRange{Int}}}) where T =
359-
BlockArray{T}(undef, axes)
360-
@inline Base.similar(block_array::AbstractArray, ::Type{T}, axes::Tuple{Int,BlockedUnitRange,Vararg{AbstractUnitRange{Int}}}) where T =
361-
similar(block_array, T, (Base.OneTo(axes[1]), tail(axes)...))
362-
363-
@inline Base.similar(block_array::Type{<:AbstractArray{T}}, axes::Tuple{BlockedUnitRange,Vararg{AbstractUnitRange{Int}}}) where T =
364-
BlockArray{T}(undef, axes)
365-
@inline Base.similar(block_array::Type{<:AbstractArray{T}}, axes::Tuple{BlockedUnitRange,BlockedUnitRange,Vararg{AbstractUnitRange{Int}}}) where T =
366-
BlockArray{T}(undef, axes)
367-
@inline Base.similar(block_array::Type{<:AbstractArray{T}}, axes::Tuple{AbstractUnitRange{Int},BlockedUnitRange,Vararg{AbstractUnitRange{Int}}}) where T =
368-
BlockArray{T}(undef, axes)
354+
@inline Base.similar(block_array::AbstractArray, ::Type{T}, axes::Tuple{BlockedUnitRange,Vararg{Union{AbstractUnitRange{Int},Integer}}}) where T =
355+
BlockArray{T}(undef, map(to_axes,axes))
356+
@inline Base.similar(block_array::AbstractArray, ::Type{T}, axes::Tuple{BlockedUnitRange,BlockedUnitRange,Vararg{Union{AbstractUnitRange{Int},Integer}}}) where T =
357+
BlockArray{T}(undef, map(to_axes,axes))
358+
@inline Base.similar(block_array::AbstractArray, ::Type{T}, axes::Tuple{Union{AbstractUnitRange{Int},Integer},BlockedUnitRange,Vararg{Union{AbstractUnitRange{Int},Integer}}}) where T =
359+
BlockArray{T}(undef, map(to_axes,axes))
360+
361+
@inline Base.similar(block_array::Type{<:AbstractArray{T}}, axes::Tuple{BlockedUnitRange,Vararg{Union{AbstractUnitRange{Int},Integer}}}) where T =
362+
BlockArray{T}(undef, map(to_axes,axes))
363+
@inline Base.similar(block_array::Type{<:AbstractArray{T}}, axes::Tuple{BlockedUnitRange,BlockedUnitRange,Vararg{Union{AbstractUnitRange{Int},Integer}}}) where T =
364+
BlockArray{T}(undef, map(to_axes,axes))
365+
@inline Base.similar(block_array::Type{<:AbstractArray{T}}, axes::Tuple{Union{AbstractUnitRange{Int},Integer},BlockedUnitRange,Vararg{Union{AbstractUnitRange{Int},Integer}}}) where T =
366+
BlockArray{T}(undef, map(to_axes,axes))
369367

370368
const OffsetAxis = Union{Integer, UnitRange, Base.OneTo, Base.IdentityUnitRange}
371369

372370
# avoid ambiguities
373371
@inline Base.similar(block_array::BlockArray, ::Type{T}, dims::NTuple{N,Int}) where {T,N} =
374372
Array{T}(undef, dims)
375373
@inline Base.similar(block_array::BlockArray, ::Type{T}, axes::Tuple{OffsetAxis,Vararg{OffsetAxis}}) where T =
376-
BlockArray{T}(undef, axes)
374+
BlockArray{T}(undef, map(to_axes,axes))
377375
@inline Base.similar(block_array::BlockArray, ::Type{T}, axes::Tuple{Base.OneTo{Int},Vararg{Base.OneTo{Int}}}) where T =
378-
BlockArray{T}(undef, axes)
376+
BlockArray{T}(undef, map(to_axes,axes))
379377

380378
@inline function Base.getindex(block_arr::BlockArray{T, N}, i::Vararg{Integer, N}) where {T,N}
381379
@boundscheck checkbounds(block_arr, i...)

src/pseudo_blockarray.jl

Lines changed: 39 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -145,39 +145,32 @@ function Base.similar(block_array::PseudoBlockArray{T,N}, ::Type{T2}) where {T,N
145145
PseudoBlockArray(similar(block_array.blocks, T2), axes(block_array))
146146
end
147147

148-
@inline Base.similar(block_array::Type{<:Array{T}}, axes::Tuple{BlockedUnitRange,Vararg{AbstractUnitRange{Int}}}) where T =
149-
PseudoBlockArray{T}(undef, axes)
150-
@inline Base.similar(block_array::Type{<:Array{T}}, axes::Tuple{BlockedUnitRange,BlockedUnitRange,Vararg{AbstractUnitRange{Int}}}) where T =
151-
PseudoBlockArray{T}(undef, axes)
152-
@inline Base.similar(block_array::Type{<:Array{T}}, axes::Tuple{AbstractUnitRange{Int},BlockedUnitRange,Vararg{AbstractUnitRange{Int}}}) where T =
153-
PseudoBlockArray{T}(undef, axes)
154-
155-
@inline Base.similar(block_array::Array, ::Type{T}, axes::Tuple{BlockedUnitRange,Vararg{AbstractUnitRange{Int}}}) where T =
156-
PseudoBlockArray{T}(undef, axes)
157-
@inline Base.similar(block_array::Array, ::Type{T}, axes::Tuple{BlockedUnitRange,BlockedUnitRange,Vararg{AbstractUnitRange{Int}}}) where T =
158-
PseudoBlockArray{T}(undef, axes)
159-
@inline Base.similar(block_array::Array, ::Type{T}, axes::Tuple{AbstractUnitRange{Int},BlockedUnitRange,Vararg{AbstractUnitRange{Int}}}) where T =
160-
PseudoBlockArray{T}(undef, axes)
161-
162-
@inline Base.similar(block_array::PseudoBlockArray, ::Type{T}, axes::Tuple{BlockedUnitRange,Vararg{AbstractUnitRange{Int}}}) where T =
163-
PseudoBlockArray{T}(undef, axes)
164-
@inline Base.similar(block_array::PseudoBlockArray, ::Type{T}, axes::Tuple{BlockedUnitRange,BlockedUnitRange,Vararg{AbstractUnitRange{Int}}}) where T =
165-
PseudoBlockArray{T}(undef, axes)
166-
@inline Base.similar(block_array::PseudoBlockArray, ::Type{T}, axes::Tuple{AbstractUnitRange{Int},BlockedUnitRange,Vararg{AbstractUnitRange{Int}}}) where T =
167-
PseudoBlockArray{T}(undef, axes)
168-
169-
@inline function Base.getindex(block_arr::PseudoBlockArray{T, N}, i::Vararg{Integer, N}) where {T,N}
170-
@boundscheck checkbounds(block_arr, i...)
171-
@inbounds v = block_arr.blocks[i...]
172-
return v
173-
end
174-
175-
176-
@inline function Base.setindex!(block_arr::PseudoBlockArray{T, N}, v, i::Vararg{Integer, N}) where {T,N}
177-
@boundscheck checkbounds(block_arr, i...)
178-
@inbounds block_arr.blocks[i...] = v
179-
return block_arr
180-
end
148+
to_axes(r::AbstractUnitRange) = r
149+
to_axes(n::Integer) = Base.oneto(n)
150+
151+
@inline Base.similar(block_array::Type{<:Array{T}}, axes::Tuple{BlockedUnitRange,Vararg{Union{Integer,AbstractUnitRange{Int}}}}) where T =
152+
PseudoBlockArray{T}(undef, map(to_axes,axes))
153+
@inline Base.similar(block_array::Type{<:Array{T}}, axes::Tuple{BlockedUnitRange,BlockedUnitRange,Vararg{Union{Integer,AbstractUnitRange{Int}}}}) where T =
154+
PseudoBlockArray{T}(undef, map(to_axes,axes))
155+
@inline Base.similar(block_array::Type{<:Array{T}}, axes::Tuple{Union{Integer,AbstractUnitRange{Int}},BlockedUnitRange,Vararg{Union{Integer,AbstractUnitRange{Int}}}}) where T =
156+
PseudoBlockArray{T}(undef, map(to_axes,axes))
157+
158+
@inline Base.similar(block_array::Array, ::Type{T}, axes::Tuple{BlockedUnitRange,Vararg{Union{Integer,AbstractUnitRange{Int}}}}) where T =
159+
PseudoBlockArray{T}(undef, map(to_axes,axes))
160+
@inline Base.similar(block_array::Array, ::Type{T}, axes::Tuple{BlockedUnitRange,BlockedUnitRange,Vararg{Union{Integer,AbstractUnitRange{Int}}}}) where T =
161+
PseudoBlockArray{T}(undef, map(to_axes,axes))
162+
@inline Base.similar(block_array::Array, ::Type{T}, axes::Tuple{Union{Integer,AbstractUnitRange{Int}},BlockedUnitRange,Vararg{Union{Integer,AbstractUnitRange{Int}}}}) where T =
163+
PseudoBlockArray{T}(undef, map(to_axes,axes))
164+
165+
@inline Base.similar(block_array::PseudoBlockArray, ::Type{T}, axes::Tuple{BlockedUnitRange,Vararg{Union{Integer,AbstractUnitRange{Int}}}}) where T =
166+
PseudoBlockArray{T}(undef, map(to_axes,axes))
167+
@inline Base.similar(block_array::PseudoBlockArray, ::Type{T}, axes::Tuple{BlockedUnitRange,BlockedUnitRange,Vararg{Union{Integer,AbstractUnitRange{Int}}}}) where T =
168+
PseudoBlockArray{T}(undef, map(to_axes,axes))
169+
@inline Base.similar(block_array::PseudoBlockArray, ::Type{T}, axes::Tuple{Union{Integer,AbstractUnitRange{Int}},BlockedUnitRange,Vararg{Union{Integer,AbstractUnitRange{Int}}}}) where T =
170+
PseudoBlockArray{T}(undef, map(to_axes,axes))
171+
172+
@inline Base.@propagate_inbounds Base.getindex(block_arr::PseudoBlockArray{T, N}, i::Vararg{Integer, N}) where {T,N} = block_arr.blocks[i...]
173+
@inline Base.@propagate_inbounds Base.setindex!(block_arr::PseudoBlockArray{T, N}, v, i::Vararg{Integer, N}) where {T,N} = setindex!(block_arr.blocks, v, i...)
181174

182175
################################
183176
# AbstractBlockArray Interface #
@@ -193,11 +186,9 @@ end
193186
return view(block_arr.blocks, range...)
194187
end
195188

196-
@inline function _pseudoblockindex_getindex(block_arr, blockindex)
189+
@inline Base.@propagate_inbounds function _pseudoblockindex_getindex(block_arr, blockindex)
197190
I = getindex.(axes(block_arr), getindex.(Block.(blockindex.I), blockindex.α))
198-
@boundscheck checkbounds(block_arr.blocks, I...)
199-
@inbounds v = block_arr.blocks[I...]
200-
return v
191+
block_arr.blocks[I...]
201192
end
202193

203194
@inline Base.getindex(block_arr::PseudoBlockArray{T,N}, blockindex::BlockIndex{N}) where {T,N} =
@@ -258,6 +249,17 @@ function Base.showarg(io::IO, A::PseudoBlockArray, toplevel::Bool)
258249
print(io, '}')
259250
end
260251
end
252+
"""
253+
resize!(a::PseudoBlockVector, N::Block) -> PseudoBlockVector
254+
255+
Resize `a` to contain the first `N` blocks, returning a new `PseudoBlockVector` sharing
256+
memory with `a`. If `N` is smaller than the current
257+
collection block length, the first `N` blocks will be retained. `N` is not allowed to be larger.
258+
"""
259+
function resize!(a::PseudoBlockVector, N::Block{1})
260+
ax = axes(a,1)
261+
PseudoBlockVector(resize!(a.blocks, last(ax[N])), (ax[Block.(Base.OneTo(Int(N)))],))
262+
end
261263

262264

263265
###########################

test/test_blockarrays.jl

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,13 +98,17 @@ end
9898

9999
@testset "similar" begin
100100
ret = BlockArray{Float64}(undef, 1:3)
101+
@test similar(ret, Float64, (3,)) isa Vector
101102
@test similar(typeof(ret), axes(ret)) isa BlockArray
102103
@test similar(typeof(ret), (Base.OneTo(6),)) isa Array
103104
@test similar(Array{Float64}, axes(ret)) isa PseudoBlockArray
104105
@test similar(Vector{Float64}, axes(ret)) isa PseudoBlockArray
105106
@test similar(randn(5,5), Float64, axes(ret)) isa PseudoBlockArray
106107
@test similar(ret, Float64, (Base.IdentityUnitRange(1:3),)) isa BlockArray
107108

109+
ret = PseudoBlockArray{Float64}(undef, 1:3)
110+
@test similar(ret, Float64, (blockedrange(1:3),)) isa PseudoBlockArray
111+
108112
ret = BlockArray{Float64}(undef, 1:3, 1:3)
109113
@test similar(typeof(ret), axes(ret)) isa BlockArray
110114
@test similar(typeof(ret), (Base.OneTo(6),axes(ret,2))) isa BlockArray
@@ -113,6 +117,9 @@ end
113117
@test similar(Array{Float64}, (Base.OneTo(5), axes(ret,2))) isa PseudoBlockArray
114118
@test similar(randn(5,5), Float64, axes(ret)) isa PseudoBlockArray
115119
@test similar(randn(5,5), Float64, (Base.OneTo(5), axes(ret,2))) isa PseudoBlockArray
120+
121+
@test similar(randn(6,5), Float64, (blockedrange(1:3),3)) isa PseudoBlockMatrix
122+
@test similar(randn(6,5), Float64, (3,blockedrange(1:3))) isa PseudoBlockMatrix
116123
end
117124

118125
@test_throws DimensionMismatch BlockArray([1,2,3],[1,1])
@@ -584,4 +591,20 @@ end
584591
s2 = String(take!(io))
585592
@test s1 == s2
586593
end
594+
595+
@testset "Array indexing" begin
596+
a = randn(6)
597+
A = randn(6,3)
598+
@test a[blockedrange(1:3)] isa PseudoBlockVector
599+
@test A[blockedrange(1:3),:] isa PseudoBlockMatrix
600+
@test A[:,blockedrange(1:2)] isa PseudoBlockMatrix
601+
@test A[blockedrange(1:3),blockedrange(1:2)] isa PseudoBlockMatrix
602+
end
603+
604+
@testset "resize!" begin
605+
a = PseudoBlockVector(collect(1:6), 1:3)
606+
b = resize!(a,Block(2))
607+
@test b == 1:3
608+
@test_throws BoundsError a[4] # length of a.blocks has changed
609+
end
587610
end

test/test_blocklinalg.jl

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -182,8 +182,7 @@ import ArrayLayouts: DenseRowMajor, ColumnMajor, StridedLayout
182182
@testset "inv" begin
183183
A = PseudoBlockArray{Float64}(randn(6,6), fill(2,3), 1:3)
184184
F = factorize(A)
185-
# Defaults to QR for generality
186-
@test F isa LinearAlgebra.QRCompactWY
185+
187186
B = randn(6,6)
188187
@test ldiv!(F, copy(B)) Matrix(A) \ B
189188
= PseudoBlockArray(copy(B),1:3,fill(2,3))

0 commit comments

Comments
 (0)