Skip to content

Commit e69d525

Browse files
authored
Merge branch 'master' into generalize_blockedunitrange
2 parents c685cf6 + f87ad0c commit e69d525

9 files changed

+131
-104
lines changed

.github/workflows/downstream.yml

+1
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ jobs:
3131
os: [ubuntu-latest]
3232
package:
3333
- {repo: BlockBandedMatrices.jl, group: JuliaLinearAlgebra}
34+
- {repo: ApproxFunBase.jl, group: JuliaApproximation}
3435
# - {repo: InfiniteLinearAlgebra.jl, group: JuliaLinearAlgebra}
3536

3637
steps:

Project.toml

+2-2
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.39"
3+
version = "0.16.40"
44

55
[deps]
66
ArrayLayouts = "4c555306-a7a7-4459-81d9-ec55ddd5c99a"
@@ -10,7 +10,7 @@ LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
1010
[compat]
1111
Aqua = "0.8"
1212
ArrayLayouts = "1.0.8"
13-
Documenter = "0.27"
13+
Documenter = "1"
1414
FillArrays = "1"
1515
LinearAlgebra = "1.6"
1616
OffsetArrays = "1"

docs/src/man/blockarrays.md

+49-47
Original file line numberDiff line numberDiff line change
@@ -2,32 +2,32 @@
22

33
```@meta
44
DocTestSetup = quote
5-
using BlockArrays
6-
using Random
7-
Random.seed!(1234)
5+
using BlockArrays, SparseArrays
86
end
97
```
108

119
## Creating `BlockArray`s from an array
1210

1311
An `AbstractArray` can be repacked into a `BlockArray` with `BlockArray(array, block_sizes...)`. The block sizes are each an `AbstractVector{Int}` which determines the size of the blocks in that dimension (so the sum of `block_sizes` in every dimension must match the size of `array` in that dimension).
1412

15-
```julia
16-
julia> BlockArray(rand(4, 4), [2,2], [1,1,2])
17-
2×3-blocked 4×4 BlockMatrix{Float64}:
18-
0.703930.5687030.0137366 0.953038
19-
0.249570.1459240.884324 0.134155
20-
──────────┼────────────┼─────────────────────
21-
0.4081330.7077230.467458 0.326718
22-
0.8443140.7942790.0421491 0.683791
23-
24-
julia> block_array_sparse = BlockArray(sprand(4, 5, 0.7), [1,3], [2,3])
25-
2×2-blocked 4×5 BlockMatrix{Float64, Matrix{SparseMatrixCSC{Float64, Int64}}, Tuple{BlockedUnitRange{Int64, Vector{Int64}}, BlockedUnitRange{Int64, Vector{Int64}}}}:
26-
0.0341601 0.3741870.0118196 0.299058 0.0
27-
----------------------------------------------------
28-
0.0945445 0.9311150.0460428 0.0 0.0
29-
0.314926 0.4389390.496169 0.0 0.0
30-
0.12781 0.2468620.732 0.449182 0.875096
13+
```jldoctest
14+
julia> BlockArray(Array(reshape(1:16, 4, 4)), [2,2], [1,1,2])
15+
2×3-blocked 4×4 BlockMatrix{Int64}:
16+
1 │ 5 │ 9 13
17+
2 │ 6 │ 10 14
18+
───┼─────┼────────
19+
3 │ 7 │ 11 15
20+
4 │ 8 │ 12 16
21+
22+
julia> S = spzeros(4,5); S[1,2] = S[4,3] = 1;
23+
24+
julia> block_array_sparse = BlockArray(S, [1,3], [2,3])
25+
2×2-blocked 4×5 BlockMatrix{Float64, Matrix{SparseMatrixCSC{Float64, Int64}}, Tuple{BlockedUnitRange{Vector{Int64}}, BlockedUnitRange{Vector{Int64}}}}:
26+
⋅ 1.0 │ ⋅ ⋅ ⋅
27+
──────────┼───────────────
28+
⋅ ⋅ │ ⋅ ⋅ ⋅
29+
⋅ ⋅ │ ⋅ ⋅ ⋅
30+
⋅ ⋅ │ 1.0 ⋅ ⋅
3131
```
3232

3333

@@ -65,11 +65,11 @@ julia> BlockArray{Float32}(undef_blocks, [1,2], [3,2])
6565

6666
The `block_type` should be an array type. It specifies the internal block type, which defaults to an `Array` of the according dimension. We can also use a `SparseVector` or any other user defined array type:
6767

68-
```julia
68+
```jldoctest
6969
julia> BlockArray(undef_blocks, SparseVector{Float64, Int}, [1,2])
7070
2-blocked 3-element BlockVector{Float64, Vector{SparseVector{Float64, Int64}}, Tuple{BlockedUnitRange{Int64, Vector{Int64}}}}:
7171
#undef
72-
------
72+
──────
7373
#undef
7474
#undef
7575
```
@@ -78,10 +78,9 @@ julia> BlockArray(undef_blocks, SparseVector{Float64, Int}, [1,2])
7878

7979
Note that accessing an undefined block will throw an "access to undefined reference"-error! If you create an array with undefined blocks, you _have_ to [initialize it block-wise](@ref setting_and_getting)); whole-array functions like `fill!` will not work:
8080

81-
```julia
81+
```jldoctest
8282
julia> fill!(BlockArray{Float32}(undef_blocks, [1,2], [3,2]), 0)
8383
ERROR: UndefRefError: access to undefined reference
84-
8584
```
8685

8786
## [Setting and getting blocks and values](@id setting_and_getting)
@@ -164,32 +163,35 @@ julia> view(A, Block.(1:2))
164163

165164
An array can be repacked into a `BlockArray` with `BlockArray(array, block_sizes...)`:
166165

167-
```jl
168-
julia> block_array_sparse = BlockArray(sprand(4, 5, 0.7), [1,3], [2,3])
169-
2×2-blocked 4×5 BlockArray{Float64, 2, Matrix{SparseMatrixCSC{Float64, Int64}}, Tuple{BlockedUnitRange{Int64, Vector{Int64}}, BlockedUnitRange{Int64, Vector{Int64}}}}:
170-
0.0341601 0.3741870.0118196 0.299058 0.0
171-
----------------------------------------------------
172-
0.0945445 0.9311150.0460428 0.0 0.0
173-
0.314926 0.4389390.496169 0.0 0.0
174-
0.12781 0.2468620.732 0.449182 0.875096
166+
```jldoctest repack
167+
julia> S = spzeros(4,5); S[1,2] = S[4,3] = 1;
168+
169+
julia> block_array_sparse = BlockArray(S, [1,3], [2,3])
170+
2×2-blocked 4×5 BlockMatrix{Float64, Matrix{SparseMatrixCSC{Float64, Int64}}, Tuple{BlockedUnitRange{Vector{Int64}}, BlockedUnitRange{Vector{Int64}}}}:
171+
⋅ 1.0 │ ⋅ ⋅ ⋅
172+
──────────┼───────────────
173+
⋅ ⋅ │ ⋅ ⋅ ⋅
174+
⋅ ⋅ │ ⋅ ⋅ ⋅
175+
⋅ ⋅ │ 1.0 ⋅ ⋅
175176
```
176177

177-
To get back the underlying array use `Array`:
178+
To get back the underlying sparse array, use `sparse`:
178179

179-
```jl
180+
```jldoctest repack
181+
julia> sparse(block_array_sparse)
182+
4×5 SparseMatrixCSC{Float64, Int64} with 2 stored entries:
183+
⋅ 1.0 ⋅ ⋅ ⋅
184+
⋅ ⋅ ⋅ ⋅ ⋅
185+
⋅ ⋅ ⋅ ⋅ ⋅
186+
⋅ ⋅ 1.0 ⋅ ⋅
187+
```
188+
189+
To get a dense array, use `Array`:
190+
```jldoctest repack
180191
julia> Array(block_array_sparse)
181-
4×5 SparseMatrixCSC{Float64,Int64} with 13 stored entries:
182-
[1, 1] = 0.30006
183-
[2, 1] = 0.451742
184-
[3, 1] = 0.243174
185-
[4, 1] = 0.156468
186-
[1, 2] = 0.94057
187-
[3, 2] = 0.544175
188-
[4, 2] = 0.598345
189-
[3, 3] = 0.737486
190-
[4, 3] = 0.929512
191-
[1, 4] = 0.539601
192-
[3, 4] = 0.757658
193-
[4, 4] = 0.44709
194-
[2, 5] = 0.514679
192+
4×5 Matrix{Float64}:
193+
0.0 1.0 0.0 0.0 0.0
194+
0.0 0.0 0.0 0.0 0.0
195+
0.0 0.0 0.0 0.0 0.0
196+
0.0 0.0 1.0 0.0 0.0
195197
```

src/blockaxis.jl

+34-34
Original file line numberDiff line numberDiff line change
@@ -74,21 +74,21 @@ _blocklengths2blocklasts(blocks::Fill) = cumsum(blocks)
7474
_blocklengths2blocklasts(blocks::Ones) = cumsum(blocks)
7575
@inline blockedrange(blocks::Union{Tuple,AbstractVector}) = _BlockedUnitRange(_blocklengths2blocklasts(blocks))
7676

77-
@inline blockfirsts(a::BlockedUnitRange) = [a.first; @views(a.lasts[1:end-1]) .+ 1]
77+
@inline blockfirsts(a::BlockedUnitRange) = [first(a); @views(blocklasts(a)[1:end-1]) .+ 1]
7878
# optimize common cases
79-
@inline function blockfirsts(a::BlockedUnitRange{<:Integer, <:Union{Vector, RangeCumsum{<:Any, <:UnitRange}}})
80-
v = Vector{eltype(a)}(undef, length(a.lasts))
81-
v[1] = a.first
82-
v[2:end] .= @views(a.lasts[oneto(end-1)]) .+ 1
79+
@inline function blockfirsts(a::BlockedUnitRange{<:Union{Vector, RangeCumsum{<:Any, <:UnitRange}}})
80+
v = Vector{eltype(a)}(undef, length(blocklasts(a)))
81+
v[1] = first(a)
82+
v[2:end] .= @views(blocklasts(a)[oneto(end-1)]) .+ 1
8383
return v
8484
end
8585
@inline blocklasts(a::BlockedUnitRange) = a.lasts
8686

8787
_diff(a::AbstractVector) = diff(a)
8888
_diff(a::Tuple) = diff(collect(a))
89-
@inline blocklengths(a::BlockedUnitRange) = isempty(a.lasts) ? [_diff(a.lasts);] : [first(a.lasts)-a.first+one(eltype(a)); _diff(a.lasts)]
89+
@inline blocklengths(a::BlockedUnitRange) = isempty(blocklasts(a)) ? [_diff(blocklasts(a));] : [first(blocklasts(a))-first(a)+one(eltype(a)); _diff(blocklasts(a))]
9090

91-
length(a::BlockedUnitRange) = isempty(a.lasts) ? zero(eltype(a)) : Integer(last(a.lasts)-a.first+one(eltype(a)))
91+
length(a::BlockedUnitRange) = isempty(blocklasts(a)) ? zero(eltype(a)) : Integer(last(blocklasts(a))-first(a)+one(eltype(a)))
9292

9393
"""
9494
blockisequal(a::AbstractUnitRange{Int}, b::AbstractUnitRange{Int})
@@ -142,7 +142,7 @@ Base.unitrange(b::BlockedUnitRange) = first(b):last(b)
142142
Base.promote_rule(::Type{BlockedUnitRange{T, CS}}, ::Type{Base.OneTo{Int}}) where {T, CS} = UnitRange{T}
143143

144144
"""
145-
blockaxes(A)
145+
blockaxes(A::AbstractArray)
146146
147147
Return the tuple of valid block indices for array `A`.
148148
@@ -169,19 +169,19 @@ julia> blockaxes(B)
169169
(BlockRange(Base.OneTo(2)), BlockRange(Base.OneTo(3)))
170170
```
171171
"""
172-
blockaxes(b::BlockedUnitRange) = _blockaxes(b.lasts)
172+
blockaxes(b::BlockedUnitRange) = _blockaxes(blocklasts(b))
173173
_blockaxes(b::AbstractVector) = (Block.(axes(b,1)),)
174174
_blockaxes(b::Tuple) = (Block.(Base.OneTo(length(b))),)
175175
blockaxes(b) = blockaxes.(axes(b), 1)
176176

177177
"""
178-
blockaxes(A, d)
178+
blockaxes(A::AbstractArray, d::Int)
179179
180180
Return the valid range of block indices for array `A` along dimension `d`.
181181
182182
# Examples
183183
```jldoctest
184-
julia> A = BlockArray([1,2,3],[2,1])
184+
julia> A = BlockArray([1,2,3], [2,1])
185185
2-blocked 3-element BlockVector{Int64}:
186186
1
187187
2
@@ -202,8 +202,8 @@ julia> blockaxes(A,1) |> collect
202202
end
203203

204204
"""
205-
blocksize(A)
206-
blocksize(A,i)
205+
blocksize(A::AbstractArray)
206+
blocksize(A::AbstractArray, i::Int)
207207
208208
Return the tuple of the number of blocks along each
209209
dimension. See also size and blocksizes.
@@ -229,8 +229,8 @@ blocksize(A,i) = length(blockaxes(A,i))
229229
@inline blocklength(t) = prod(blocksize(t))
230230

231231
"""
232-
blocksizes(A)
233-
blocksizes(A,i)
232+
blocksizes(A::AbstractArray)
233+
blocksizes(A::AbstractArray, i::Int)
234234
235235
Return the tuple of the sizes of blocks along each
236236
dimension. See also size and blocksize.
@@ -352,8 +352,8 @@ Return the first index of each block of `a`.
352352
353353
# Examples
354354
```jldoctest
355-
julia> b = blockedrange(1:3)
356-
3-blocked 6-element BlockedUnitRange{Int64, ArrayLayouts.RangeCumsum{Int64, UnitRange{Int64}}}:
355+
julia> b = blockedrange([1,2,3])
356+
3-blocked 6-element BlockedUnitRange{Int64, Vector{Int64}}:
357357
1
358358
359359
2
@@ -378,8 +378,8 @@ Return the last index of each block of `a`.
378378
379379
# Examples
380380
```jldoctest
381-
julia> b = blockedrange(1:3)
382-
3-blocked 6-element BlockedUnitRange{Int64, ArrayLayouts.RangeCumsum{Int64, UnitRange{Int64}}}:
381+
julia> b = blockedrange([1,2,3])
382+
3-blocked 6-element BlockedUnitRange{Int64, Vector{Int64}}:
383383
1
384384
385385
2
@@ -390,7 +390,7 @@ julia> b = blockedrange(1:3)
390390
6
391391
392392
julia> blocklasts(b)
393-
3-element ArrayLayouts.RangeCumsum{Int64, UnitRange{Int64}}:
393+
3-element Vector{Int64}:
394394
1
395395
3
396396
6
@@ -404,8 +404,8 @@ Return the length of each block of `a`.
404404
405405
# Examples
406406
```jldoctest
407-
julia> b = blockedrange(1:3)
408-
3-blocked 6-element BlockedUnitRange{Int64, ArrayLayouts.RangeCumsum{Int64, UnitRange{Int64}}}:
407+
julia> b = blockedrange([1,2,3])
408+
3-blocked 6-element BlockedUnitRange{Int64, Vector{Int64}}:
409409
1
410410
411411
2
@@ -453,24 +453,24 @@ Base.BroadcastStyle(::Type{BlockedUnitRange{T, R}}) where {T, R} = Base.Broadcas
453453

454454
_blocklengths2blocklasts(blocks::AbstractRange) = RangeCumsum(blocks)
455455
function blockfirsts(a::BlockedUnitRange{<:Integer, <:Base.OneTo})
456-
a.first == 1 || error("Offset axes not supported")
457-
Base.OneTo{eltype(a)}(length(a.lasts))
456+
first(a) == 1 || error("Offset axes not supported")
457+
Base.OneTo{eltype(a)}(length(blocklasts(a)))
458458
end
459459
function blocklengths(a::BlockedUnitRange{<:Integer, <:Base.OneTo})
460-
a.first == 1 || error("Offset axes not supported")
461-
Ones{eltype(a)}(length(a.lasts))
460+
first(a) == 1 || error("Offset axes not supported")
461+
Ones{eltype(a)}(length(blocklasts(a)))
462462
end
463463
function blockfirsts(a::BlockedUnitRange{<:Integer, <:AbstractRange})
464-
st = step(a.lasts)
465-
a.first == 1 || error("Offset axes not supported")
466-
@assert first(a.lasts)-a.first+1 == st
467-
range(one(eltype(a)); step=st, length=eltype(a)(length(a.lasts)))
464+
st = step(blocklasts(a))
465+
first(a) == 1 || error("Offset axes not supported")
466+
@assert first(blocklasts(a))-first(a)+1 == st
467+
range(one(eltype(a)); step=st, length=eltype(a)(length(blocklasts(a))))
468468
end
469469
function blocklengths(a::BlockedUnitRange{<:Integer, <:AbstractRange})
470-
st = step(a.lasts)
471-
a.first == 1 || error("Offset axes not supported")
472-
@assert first(a.lasts)-a.first+1 == st
473-
Fill(st,length(a.lasts))
470+
st = step(blocklasts(a))
471+
first(a) == 1 || error("Offset axes not supported")
472+
@assert first(blocklasts(a))-first(a)+1 == st
473+
Fill(st,length(blocklasts(a)))
474474
end
475475

476476

src/blockbroadcast.jl

+1-1
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ julia> import BlockArrays: SubBlockIterator, BlockIndexRange
6767
6868
julia> A = BlockArray(1:6, 1:3);
6969
70-
julia> subblock_lasts = axes(A, 1).lasts;
70+
julia> subblock_lasts = blocklasts(axes(A, 1));
7171
7272
julia> @assert subblock_lasts == [1, 3, 6];
7373

0 commit comments

Comments
 (0)