Skip to content

Commit 8e720a0

Browse files
authored
Add BlockVector and BlockMatrix constructors (#90)
* Add BlockVector and BlockMatrix constructors * Improve block bounds errors, add support for Vectors of Block-indices * Test on 1.3 * Drop Julia v0.7 support * Delete deprecate.jl
1 parent 3390dd8 commit 8e720a0

11 files changed

+118
-57
lines changed

.travis.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@ os:
44
- linux
55
- osx
66
julia:
7-
- 0.7
87
- 1.0
98
- 1.1
109
- 1.2
10+
- 1.3
1111
- nightly
1212
matrix:
1313
allow_failures:

Project.toml

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

55
[deps]
66
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
77

88
[compat]
9-
julia = "0.7, 1"
9+
julia = "1"
1010

1111
[extras]
1212
Base64 = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f"

src/BlockArrays.jl

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ import Base: @propagate_inbounds, Array, to_indices, to_index,
2222
@_inline_meta, _maybetail, tail, @_propagate_inbounds_meta, reindex,
2323
RangeIndex, Int, Integer, Number,
2424
+, -, min, max, *, isless, in, copy, copyto!, axes, @deprecate,
25-
BroadcastStyle
25+
BroadcastStyle, checkbounds, throw_boundserror
2626
using Base: ReshapedArray, dataids
2727

2828

@@ -47,6 +47,5 @@ include("blockarrayinterface.jl")
4747
include("blockbroadcast.jl")
4848
# include("linalg.jl")
4949

50-
include("deprecate.jl")
5150

5251
end # module

src/abstractblockarray.jl

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -254,15 +254,15 @@ ERROR: BlockBoundsError: attempt to access 2×2-blocked 2×3 BlockArray{Float64,
254254
[...]
255255
```
256256
"""
257-
@inline function blockcheckbounds(A::AbstractBlockArray{T, N}, i::Vararg{Integer, N}) where {T,N}
257+
@inline function blockcheckbounds(A::AbstractArray{T, N}, i::Vararg{Integer, N}) where {T,N}
258258
if blockcheckbounds(Bool, A, i...)
259259
return
260260
else
261261
throw(BlockBoundsError(A, i))
262262
end
263263
end
264264

265-
@inline function blockcheckbounds(::Type{Bool}, A::AbstractBlockArray{T, N}, i::Vararg{Integer, N}) where {T,N}
265+
@inline function blockcheckbounds(::Type{Bool}, A::AbstractArray{T, N}, i::Vararg{Integer, N}) where {T,N}
266266
n = nblocks(A)
267267
k = 0
268268
for idx in 1:N # using enumerate here will allocate
@@ -275,6 +275,8 @@ end
275275
return true
276276
end
277277

278+
blockcheckbounds(A::AbstractArray{T, N}, i::Block{N}) where {T,N} = blockcheckbounds(A, i.n...)
279+
278280
# Convert to @generated...
279281
@propagate_inbounds Base.getindex( block_arr::AbstractBlockArray{T, N}, block::Block{N}) where {T,N} = getblock(block_arr, block.n...)
280282
@propagate_inbounds Base.setindex!(block_arr::AbstractBlockArray{T, N}, v, block::Block{N}) where {T,N} = setblock!(block_arr, v, block.n...)

src/blockarray.jl

Lines changed: 19 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -84,19 +84,17 @@ const BlockVecOrMat{T, R} = Union{BlockMatrix{T, R}, BlockVector{T, R}}
8484
# Constructors #
8585
################
8686

87-
@inline function _BlockArray(::Type{R}, block_sizes::Vararg{AbstractVector{Int}, N}) where {T, N, R<:AbstractArray{<:AbstractArray{T,N},N}}
87+
@inline _BlockArray(::Type{R}, block_sizes::Vararg{AbstractVector{Int}, N}) where {T, N, R<:AbstractArray{<:AbstractArray{T,N},N}} =
8888
_BlockArray(R, BlockSizes(block_sizes...))
89-
end
9089

9190
function _BlockArray(::Type{R}, block_sizes::BlockSizes{N}) where {T, N, R<:AbstractArray{<:AbstractArray{T,N},N}}
9291
n_blocks = nblocks(block_sizes)
9392
blocks = R(undef, n_blocks)
9493
_BlockArray(blocks, block_sizes)
9594
end
9695

97-
@inline function undef_blocks_BlockArray(::Type{R}, block_sizes::Vararg{AbstractVector{Int}, N}) where {T, N, R<:AbstractArray{<:AbstractArray{T,N},N}}
96+
@inline undef_blocks_BlockArray(::Type{R}, block_sizes::Vararg{AbstractVector{Int}, N}) where {T, N, R<:AbstractArray{<:AbstractArray{T,N},N}} =
9897
_BlockArray(R, block_sizes...)
99-
end
10098

10199
"""
102100
Constructs a `BlockArray` with uninitialized blocks from a block type `R` with sizes defind by `block_sizes`.
@@ -112,21 +110,17 @@ julia> BlockArray(undef_blocks, Matrix{Float64}, [1,3], [2,2])
112110
#undef │ #undef #undef #undef │
113111
```
114112
"""
115-
@inline function BlockArray(::UndefBlocksInitializer, ::Type{R}, block_sizes::Vararg{AbstractVector{Int}, N}) where {T, N, R<:AbstractArray{T,N}}
113+
@inline BlockArray(::UndefBlocksInitializer, ::Type{R}, block_sizes::Vararg{AbstractVector{Int}, N}) where {T, N, R<:AbstractArray{T,N}} =
116114
undef_blocks_BlockArray(Array{R,N}, block_sizes...)
117-
end
118115

119-
@inline function BlockArray{T}(::UndefBlocksInitializer, block_sizes::Vararg{AbstractVector{Int}, N}) where {T, N}
116+
@inline BlockArray{T}(::UndefBlocksInitializer, block_sizes::Vararg{AbstractVector{Int}, N}) where {T, N} =
120117
BlockArray(undef_blocks, Array{T,N}, block_sizes...)
121-
end
122118

123-
@inline function BlockArray{T,N}(::UndefBlocksInitializer, block_sizes::Vararg{AbstractVector{Int}, N}) where {T, N}
119+
@inline BlockArray{T,N}(::UndefBlocksInitializer, block_sizes::Vararg{AbstractVector{Int}, N}) where {T, N} =
124120
BlockArray(undef_blocks, Array{T,N}, block_sizes...)
125-
end
126121

127-
@inline function BlockArray{T,N,R}(::UndefBlocksInitializer, block_sizes::Vararg{AbstractVector{Int}, N}) where {T, N, R<:AbstractArray{<:AbstractArray{T,N},N}}
122+
@inline BlockArray{T,N,R}(::UndefBlocksInitializer, block_sizes::Vararg{AbstractVector{Int}, N}) where {T, N, R<:AbstractArray{<:AbstractArray{T,N},N}} =
128123
undef_blocks_BlockArray(R, block_sizes...)
129-
end
130124

131125

132126
@generated function initialized_blocks_BlockArray(::Type{R}, block_sizes::BlockSizes{N}) where R<:AbstractArray{V,N} where {T,N,V<:AbstractArray{T,N}}
@@ -142,33 +136,26 @@ end
142136
end
143137

144138

145-
function initialized_blocks_BlockArray(::Type{R}, block_sizes::Vararg{AbstractVector{Int}, N}) where {T, N, R<:AbstractArray{<:AbstractArray{T,N},N}}
139+
initialized_blocks_BlockArray(::Type{R}, block_sizes::Vararg{AbstractVector{Int}, N}) where {T, N, R<:AbstractArray{<:AbstractArray{T,N},N}} =
146140
initialized_blocks_BlockArray(R, BlockSizes(block_sizes...))
147-
end
148141

149-
@inline function BlockArray{T}(::UndefInitializer, block_sizes::BlockSizes{N}) where {T, N}
142+
@inline BlockArray{T}(::UndefInitializer, block_sizes::BlockSizes{N}) where {T, N} =
150143
initialized_blocks_BlockArray(Array{Array{T,N},N}, block_sizes)
151-
end
152144

153-
@inline function BlockArray{T, N}(::UndefInitializer, block_sizes::BlockSizes{N}) where {T, N}
145+
@inline BlockArray{T, N}(::UndefInitializer, block_sizes::BlockSizes{N}) where {T, N} =
154146
initialized_blocks_BlockArray(Array{Array{T,N},N}, block_sizes)
155-
end
156147

157-
@inline function BlockArray{T, N, R}(::UndefInitializer, block_sizes::BlockSizes{N}) where {T, N, R<:AbstractArray{<:AbstractArray{T,N},N}}
148+
@inline BlockArray{T, N, R}(::UndefInitializer, block_sizes::BlockSizes{N}) where {T, N, R<:AbstractArray{<:AbstractArray{T,N},N}} =
158149
initialized_blocks_BlockArray(R, block_sizes)
159-
end
160150

161-
@inline function BlockArray{T}(::UndefInitializer, block_sizes::Vararg{AbstractVector{Int}, N}) where {T, N}
151+
@inline BlockArray{T}(::UndefInitializer, block_sizes::Vararg{AbstractVector{Int}, N}) where {T, N} =
162152
initialized_blocks_BlockArray(Array{Array{T,N},N}, block_sizes...)
163-
end
164153

165-
@inline function BlockArray{T, N}(::UndefInitializer, block_sizes::Vararg{AbstractVector{Int}, N}) where {T, N}
154+
@inline BlockArray{T, N}(::UndefInitializer, block_sizes::Vararg{AbstractVector{Int}, N}) where {T, N} =
166155
initialized_blocks_BlockArray(Array{Array{T,N},N}, block_sizes...)
167-
end
168156

169-
@inline function BlockArray{T, N, R}(::UndefInitializer, block_sizes::Vararg{AbstractVector{Int}, N}) where {T, N, R<:AbstractArray{<:AbstractArray{T,N},N}}
157+
@inline BlockArray{T, N, R}(::UndefInitializer, block_sizes::Vararg{AbstractVector{Int}, N}) where {T, N, R<:AbstractArray{<:AbstractArray{T,N},N}} =
170158
initialized_blocks_BlockArray(R, block_sizes...)
171-
end
172159

173160
function BlockArray(arr::AbstractArray{T, N}, block_sizes::Vararg{AbstractVector{Int}, N}) where {T,N}
174161
for i in 1:N
@@ -192,6 +179,11 @@ end
192179
end
193180
end
194181

182+
BlockVector(blocks::AbstractVector, block_sizes::AbstractBlockSizes{1}) = BlockArray(blocks, block_sizes)
183+
BlockVector(blocks::AbstractVector, block_sizes::AbstractVector{Int}) = BlockArray(blocks, block_sizes)
184+
BlockMatrix(blocks::AbstractMatrix, block_sizes::AbstractBlockSizes{2}) = BlockArray(blocks, block_sizes)
185+
BlockMatrix(blocks::AbstractMatrix, block_sizes::Vararg{AbstractVector{Int},2}) = BlockArray(blocks, block_sizes...)
186+
195187
"""
196188
mortar(blocks::AbstractArray)
197189
mortar(blocks::AbstractArray{R, N}, sizes_1, sizes_2, ..., sizes_N)
@@ -308,7 +300,7 @@ copy(A::BlockArray) = _BlockArray(copy.(A.blocks), copy(A.block_sizes))
308300
end
309301

310302
@inline function Base.getindex(block_arr::BlockArray{T,N}, blockindex::BlockIndex{N}) where {T,N}
311-
@boundscheck checkbounds(block_arr.blocks, blockindex.I...)
303+
@boundscheck blockcheckbounds(block_arr, Block(blockindex.I))
312304
@inbounds block = getblock(block_arr, blockindex.I...)
313305
@boundscheck checkbounds(block, blockindex.α...)
314306
@inbounds v = block[blockindex.α...]

src/blockindexrange.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ BlockIndexRange(block::Block{N}, inds::NTuple{N,AbstractUnitRange{Int}}) where {
1515
BlockIndexRange(block::Block{N}, inds::Vararg{AbstractUnitRange{Int},N}) where {N} =
1616
BlockIndexRange(block,inds)
1717

18+
getindex(B::Block{N}, inds::Vararg{Int,N}) where N = BlockIndex(B,inds)
1819
getindex(B::Block{N}, inds::Vararg{AbstractUnitRange{Int},N}) where N = BlockIndexRange(B,inds)
1920

2021
eltype(R::BlockIndexRange) = eltype(typeof(R))

src/blockindices.jl

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,11 @@ struct BlockIndex{N}
3131
end
3232

3333
@inline BlockIndex(a::Int, b::Int) = BlockIndex((a,), (b,))
34-
@inline BlockIndex(a::NTuple, b::Int) = BlockIndex(a, (b,))
35-
@inline BlockIndex(a::Int, b::NTuple) = BlockIndex((a,), b)
34+
@inline BlockIndex(a::Tuple, b::Int) = BlockIndex(a, (b,))
35+
@inline BlockIndex(a::Int, b::Tuple) = BlockIndex((a,), b)
36+
37+
@inline BlockIndex(a::Block, b::Tuple) = BlockIndex(a.n, b)
38+
@inline BlockIndex(a::Block, b::Int) = BlockIndex(a, (b,))
3639

3740
@generated function BlockIndex(I::NTuple{N, Int}, α::NTuple{M, Int}) where {M,N}
3841
@assert M < N
@@ -94,3 +97,18 @@ end
9497
cumulsizes(block_sizes, 3, block_index.I[3]) + block_index.α[3] - 1)
9598
return v
9699
end
100+
101+
102+
##
103+
# checkindex
104+
##
105+
106+
@inline checkbounds(::Type{Bool}, A::AbstractArray{<:Any,N}, I::Block{N}) where N = blockcheckbounds(Bool, A, I.n...)
107+
@inline function checkbounds(::Type{Bool}, A::AbstractArray{<:Any,N}, I::BlockIndex{N}) where N
108+
checkbounds(Bool, A, Block(I.I)) || return false
109+
@inbounds block = getblock(A, I.I...)
110+
checkbounds(Bool, block, I.α...)
111+
end
112+
113+
checkbounds(::Type{Bool}, A::AbstractArray{<:Any,N}, I::AbstractVector{BlockIndex{N}}) where N =
114+
all(checkbounds.(Bool, Ref(A), I))

src/deprecate.jl

Whitespace-only changes.

src/pseudo_blockarray.jl

Lines changed: 17 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -52,41 +52,38 @@ const PseudoBlockVector{T} = PseudoBlockArray{T, 1}
5252
const PseudoBlockVecOrMat{T} = Union{PseudoBlockMatrix{T}, PseudoBlockVector{T}}
5353

5454
# Auxiliary outer constructors
55-
@inline function PseudoBlockArray(blocks::R, block_sizes::BS) where {T,N,R<:AbstractArray{T,N},BS<:AbstractBlockSizes{N}}
56-
return PseudoBlockArray{T, N, R,BS}(blocks, block_sizes)
57-
end
55+
@inline PseudoBlockArray(blocks::R, block_sizes::BS) where {T,N,R<:AbstractArray{T,N},BS<:AbstractBlockSizes{N}} =
56+
PseudoBlockArray{T, N, R,BS}(blocks, block_sizes)
5857

59-
@inline function PseudoBlockArray(blocks::R, block_sizes::Vararg{Vector{Int}, N}) where {T,N,R <: AbstractArray{T, N}}
60-
return PseudoBlockArray(blocks, BlockSizes(block_sizes...))
61-
end
58+
@inline PseudoBlockArray(blocks::AbstractArray{T, N}, block_sizes::Vararg{Vector{Int}, N}) where {T, N} =
59+
PseudoBlockArray(blocks, BlockSizes(block_sizes...))
6260

63-
PseudoBlockArray(blocks::R, block_sizes::Vararg{AbstractVector{Int}, N}) where {T, N, R <: AbstractArray{T, N}} =
61+
PseudoBlockArray(blocks::AbstractArray{T, N}, block_sizes::Vararg{AbstractVector{Int}, N}) where {T, N} =
6462
PseudoBlockArray(blocks, Vector{Int}.(block_sizes)...)
6563

66-
67-
@inline function PseudoBlockArray{T}(::UndefInitializer, block_sizes::BlockSizes{N}) where {T, N}
64+
@inline PseudoBlockArray{T}(::UndefInitializer, block_sizes::BlockSizes{N}) where {T, N} =
6865
PseudoBlockArray(similar(Array{T, N}, size(block_sizes)), block_sizes)
69-
end
7066

71-
@inline function PseudoBlockArray{T, N}(::UndefInitializer, block_sizes::BlockSizes{N}) where {T, N}
67+
@inline PseudoBlockArray{T, N}(::UndefInitializer, block_sizes::BlockSizes{N}) where {T, N} =
7268
PseudoBlockArray{T}(undef, block_sizes)
73-
end
7469

75-
@inline function PseudoBlockArray{T, N, R}(::UndefInitializer, block_sizes::BlockSizes{N}) where {T, N, R <: AbstractArray{T, N}}
70+
@inline PseudoBlockArray{T, N, R}(::UndefInitializer, block_sizes::BlockSizes{N}) where {T, N, R <: AbstractArray{T, N}} =
7671
PseudoBlockArray(similar(R, size(block_sizes)), block_sizes)
77-
end
7872

79-
@inline function PseudoBlockArray{T}(::UndefInitializer, block_sizes::Vararg{AbstractVector{Int}, N}) where {T, N}
73+
@inline PseudoBlockArray{T}(::UndefInitializer, block_sizes::Vararg{AbstractVector{Int}, N}) where {T, N} =
8074
PseudoBlockArray{T}(undef, BlockSizes(block_sizes...))
81-
end
8275

83-
@inline function PseudoBlockArray{T, N}(::UndefInitializer, block_sizes::Vararg{AbstractVector{Int}, N}) where {T, N}
76+
@inline PseudoBlockArray{T, N}(::UndefInitializer, block_sizes::Vararg{AbstractVector{Int}, N}) where {T, N} =
8477
PseudoBlockArray{T, N}(undef, BlockSizes(block_sizes...))
85-
end
8678

87-
@inline function PseudoBlockArray{T, N, R}(::UndefInitializer, block_sizes::Vararg{AbstractVector{Int}, N}) where {T, N, R <: AbstractArray{T, N}}
79+
@inline PseudoBlockArray{T, N, R}(::UndefInitializer, block_sizes::Vararg{AbstractVector{Int}, N}) where {T, N, R <: AbstractArray{T, N}} =
8880
PseudoBlockArray{T, N, R}(undef, BlockSizes(block_sizes...))
89-
end
81+
82+
83+
PseudoBlockVector(blocks::AbstractVector, block_sizes::AbstractBlockSizes{1}) = PseudoBlockArray(blocks, block_sizes)
84+
PseudoBlockVector(blocks::AbstractVector, block_sizes::AbstractVector{Int}) = PseudoBlockArray(blocks, block_sizes)
85+
PseudoBlockMatrix(blocks::AbstractMatrix, block_sizes::AbstractBlockSizes{2}) = PseudoBlockArray(blocks, block_sizes)
86+
PseudoBlockMatrix(blocks::AbstractMatrix, block_sizes::Vararg{AbstractVector{Int},2}) = PseudoBlockArray(blocks, block_sizes...)
9087

9188
# Convert AbstractArrays that conform to block array interface
9289
convert(::Type{PseudoBlockArray{T,N,R,BS}}, A::PseudoBlockArray{T,N,R,BS}) where {T,N,R,BS} = A

test/test_blockarrays.jl

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,42 @@ end
117117
(zeros(2, 3), zeros(111, 222)),
118118
)
119119
end
120+
121+
a_data = [1,2,3]
122+
a = BlockVector(a_data,[1,2])
123+
a[1] = 2
124+
@test a == [2,2,3]
125+
@test a_data == [1,2,3]
126+
a = BlockVector(a_data,BlockArrays.BlockSizes([1,2]))
127+
a[1] = 2
128+
@test a == [2,2,3]
129+
@test a_data == [1,2,3]
130+
a = PseudoBlockVector(a_data,[1,2])
131+
a[1] = 2
132+
@test a == [2,2,3]
133+
@test a_data == [2,2,3]
134+
a = PseudoBlockVector(a_data,BlockArrays.BlockSizes([1,2]))
135+
a[1] = 3
136+
@test a == [3,2,3]
137+
@test a_data == [3,2,3]
138+
139+
a_data = [1 2; 3 4]
140+
a = BlockMatrix(a_data,[1,1],[2])
141+
a[1] = 2
142+
@test a == [2 2; 3 4]
143+
@test a_data == [1 2; 3 4]
144+
a = BlockMatrix(a_data,BlockArrays.BlockSizes([1,1],[2]))
145+
a[1] = 2
146+
@test a == [2 2; 3 4]
147+
@test a_data == [1 2; 3 4]
148+
a = PseudoBlockMatrix(a_data,[1,1],[2])
149+
a[1] = 2
150+
@test a == [2 2; 3 4]
151+
@test a_data == [2 2; 3 4]
152+
a = PseudoBlockMatrix(a_data,BlockArrays.BlockSizes([1,1],[2]))
153+
a[1] = 3
154+
@test a == [3 2; 3 4]
155+
@test a_data == [3 2; 3 4]
120156
end
121157

122158
@testset "block indexing" begin

0 commit comments

Comments
 (0)