From 6d3034c675e3d145f5f835d33f3a75159263f0ac Mon Sep 17 00:00:00 2001 From: mtfishman Date: Wed, 8 May 2024 19:42:07 -0400 Subject: [PATCH 01/12] Redefine blocksizes --- src/blockaxis.jl | 41 +++++++++++++---------------------------- 1 file changed, 13 insertions(+), 28 deletions(-) diff --git a/src/blockaxis.jl b/src/blockaxis.jl index a8ef8811..b9780332 100644 --- a/src/blockaxis.jl +++ b/src/blockaxis.jl @@ -331,7 +331,7 @@ end blocksize(A::AbstractArray, i::Int) Return the tuple of the number of blocks along each -dimension. See also size and blocksizes. +dimension. See also size. # Examples ```jldoctest @@ -353,34 +353,19 @@ blocksize(A) = map(length, blockaxes(A)) blocksize(A,i) = length(blockaxes(A,i)) @inline blocklength(t) = prod(blocksize(t)) -""" - blocksizes(A::AbstractArray) - blocksizes(A::AbstractArray, i::Int) - -Return the tuple of the sizes of blocks along each -dimension. See also size and blocksize. - -# Examples -```jldoctest -julia> A = BlockArray(ones(3,3),[2,1],[1,1,1]) -2×3-blocked 3×3 BlockMatrix{Float64}: - 1.0 │ 1.0 │ 1.0 - 1.0 │ 1.0 │ 1.0 - ─────┼───────┼───── - 1.0 │ 1.0 │ 1.0 - -julia> blocksizes(A) -([2, 1], [1, 1, 1]) +struct BlockSizes{N,A<:AbstractArray{<:Any,N}} <: AbstractArray{NTuple{N,Int},N} + array::A +end +Base.size(a::BlockSizes) = blocksize(a.array) +Base.axes(a::BlocksView) = map(br -> only(br.indices), blockaxes(a.array)) +Base.IteratorEltype(::Type{<:BlockSizes}) = Base.EltypeUnknown() +@propagate_inbounds getindex(a::BlockSizes{N}, i::Vararg{Int,N}) where {N} = + size(view(a.array, Block.(i)...)) +@propagate_inbounds function setindex!(a::BlockSizes{N}, b, i::Vararg{Int,N}) where {N} + error("Not implemented") +end -julia> blocksizes(A,2) -3-element Vector{Int64}: - 1 - 1 - 1 -``` -""" -blocksizes(A) = map(blocklengths, axes(A)) -blocksizes(A,i) = blocklengths(axes(A,i)) +blocksizes(a::AbstractArray) = BlockSizes(a) axes(b::AbstractBlockedUnitRange) = (BlockedOneTo(blocklasts(b) .- (first(b)-oneunit(eltype(b)))),) unsafe_indices(b::AbstractBlockedUnitRange) = axes(b) From 3b486a90ce85a2edeb729b58eb79c8c2dd5e526e Mon Sep 17 00:00:00 2001 From: mtfishman Date: Wed, 8 May 2024 19:45:56 -0400 Subject: [PATCH 02/12] Revert change to docstring --- src/blockaxis.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/blockaxis.jl b/src/blockaxis.jl index b9780332..114c66b0 100644 --- a/src/blockaxis.jl +++ b/src/blockaxis.jl @@ -331,7 +331,7 @@ end blocksize(A::AbstractArray, i::Int) Return the tuple of the number of blocks along each -dimension. See also size. +dimension. See also size and blocksizes. # Examples ```jldoctest From d27cc40f9be8372e3540c200cc97a36ee131a2c3 Mon Sep 17 00:00:00 2001 From: mtfishman Date: Thu, 9 May 2024 15:37:38 -0400 Subject: [PATCH 03/12] Add tests, fix some tests, add docstring --- src/blockaxis.jl | 28 ++++++++++++++++++++++++++-- test/test_blockarrayinterface.jl | 5 +++-- test/test_blockarrays.jl | 3 ++- test/test_blockindices.jl | 19 +++++++++++++++---- test/test_blocklinalg.jl | 6 ++++-- 5 files changed, 50 insertions(+), 11 deletions(-) diff --git a/src/blockaxis.jl b/src/blockaxis.jl index 114c66b0..9a4042ed 100644 --- a/src/blockaxis.jl +++ b/src/blockaxis.jl @@ -357,7 +357,7 @@ struct BlockSizes{N,A<:AbstractArray{<:Any,N}} <: AbstractArray{NTuple{N,Int},N} array::A end Base.size(a::BlockSizes) = blocksize(a.array) -Base.axes(a::BlocksView) = map(br -> only(br.indices), blockaxes(a.array)) +Base.axes(a::BlockSizes) = map(br -> only(br.indices), blockaxes(a.array)) Base.IteratorEltype(::Type{<:BlockSizes}) = Base.EltypeUnknown() @propagate_inbounds getindex(a::BlockSizes{N}, i::Vararg{Int,N}) where {N} = size(view(a.array, Block.(i)...)) @@ -365,7 +365,31 @@ Base.IteratorEltype(::Type{<:BlockSizes}) = Base.EltypeUnknown() error("Not implemented") end -blocksizes(a::AbstractArray) = BlockSizes(a) +""" + blocksizes(A::AbstractArray) + +Return an iterator over the sizes of each block. +See also size and blocksize. + +# Examples +```jldoctest +julia> A = BlockArray(ones(3,3),[2,1],[1,1,1]) +2×3-blocked 3×3 BlockMatrix{Float64}: + 1.0 │ 1.0 │ 1.0 + 1.0 │ 1.0 │ 1.0 + ─────┼───────┼───── + 1.0 │ 1.0 │ 1.0 + +julia> blocksizes(A) +2×3 BlockArrays.BlockSizes{2, BlockMatrix{Float64, Matrix{Matrix{Float64}}, Tuple{BlockedOneTo{Int64, Vector{Int64}}, BlockedOneTo{Int64, Vector{Int64}}}}}: + (2, 1) (2, 1) (2, 1) + (1, 1) (1, 1) (1, 1) + +julia> blocksizes(A)[2, 2] +(1, 1) +``` +""" +blocksizes(A::AbstractArray) = BlockSizes(A) axes(b::AbstractBlockedUnitRange) = (BlockedOneTo(blocklasts(b) .- (first(b)-oneunit(eltype(b)))),) unsafe_indices(b::AbstractBlockedUnitRange) = axes(b) diff --git a/test/test_blockarrayinterface.jl b/test/test_blockarrayinterface.jl index 3d2ee1ac..56a8f3d9 100644 --- a/test/test_blockarrayinterface.jl +++ b/test/test_blockarrayinterface.jl @@ -15,8 +15,9 @@ end A = randn(5) @test blocksize(A) == (1,) @test blocksize(A, 1) == 1 - @test blocksizes(A) == ([5],) - @test blocksizes(A, 1) == [5] + @test blocklengths.(axes(A)) == ([5],) + @test blocklengths(axes(A, 1)) == [5] + @test blocksizes(A) == [(5,)] @test A[Block(1)] == A view(A, Block(1))[1] = 2 @test A[1] == 2 diff --git a/test/test_blockarrays.jl b/test/test_blockarrays.jl index b26d3e26..a6275b76 100644 --- a/test/test_blockarrays.jl +++ b/test/test_blockarrays.jl @@ -109,7 +109,8 @@ end # test that BlockArrays may be created from immutable arrays B = BlockArray(reshape(1:9,3,3), [2,1], [2,1]) - @test blocksizes(B) == ([2,1], [2,1]) + @test blocklengths.(axes(B)) == ([2,1], [2,1]) + @test blocksizes(B) == [(2,2) (2,1); (1,2) (1,1)] @test B == reshape([1:9;],3,3) @test blocks(B) isa Matrix{Matrix{Int}} diff --git a/test/test_blockindices.jl b/test/test_blockindices.jl index 9b79aaa4..0cbea0ba 100644 --- a/test/test_blockindices.jl +++ b/test/test_blockindices.jl @@ -787,10 +787,21 @@ end end @testset "blocksizes" begin - x = blockedrange(2:4) - @test blocksizes(x,1) === 2:4 - y = blockedrange([2:4;]) - @test blocksizes(x,1) == blocksizes(y,1) + v = Array(reshape(1:20, (5, 4))) + A = BlockArray(v, [2, 3], [3, 1]) + @test blocklengths.(axes(A)) == ([2, 3], [3, 1]) + bs = blocksizes(A) + @test bs == [(2, 3) (2, 1); (3, 3) (3, 1)] + @test bs[1, 1] == (2, 3) + @test bs[2, 1] == (3, 3) + @test bs[1, 2] == (2, 1) + @test bs[2, 2] == (3, 1) + @test bs[1] == (2, 3) + @test bs[2] == (3, 3) + @test bs[3] == (2, 1) + @test bs[4] == (3, 1) + @test size(bs) == (2, 2) + @test axes(bs) == (1:2, 1:2) end @testset "show" begin diff --git a/test/test_blocklinalg.jl b/test/test_blocklinalg.jl index 116f98b1..788aeeac 100644 --- a/test/test_blocklinalg.jl +++ b/test/test_blocklinalg.jl @@ -101,12 +101,14 @@ bview(a, b) = Base.invoke(view, Tuple{AbstractArray,Any}, a, b) v = BlockArray(rand(6), 1:3) w = A * v @test w isa BlockArray - @test blocksizes(w,1) == fill(2, 3) + @test blocklengths(axes(w,1)) == fill(2, 3) + @test blocksizes(w) == [(2,), (2,), (2,)] @test w ≈ Array(A) * v ≈ A * Array(v) ≈ Array(A) * Array(v) z = A * w @test z isa BlockArray - @test blocksizes(z,1) == fill(2, 3) + @test blocklengths(axes(z,1)) == fill(2, 3) + @test blocksizes(z) == [(2,), (2,), (2,)] @test z ≈ Array(A) * w ≈ A * Array(w) ≈ Array(A) * Array(w) end From 6356134010cbbf70ea0d0f7a994c90a1e18a6b48 Mon Sep 17 00:00:00 2001 From: mtfishman Date: Thu, 9 May 2024 15:41:00 -0400 Subject: [PATCH 04/12] Fix more tests --- test/test_blockdeque.jl | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/test/test_blockdeque.jl b/test/test_blockdeque.jl index fe7e0ad4..2ea2d4bc 100644 --- a/test/test_blockdeque.jl +++ b/test/test_blockdeque.jl @@ -167,7 +167,8 @@ using BlockArrays, Test @test pop!(B) == 6 @test B == 1:5 @test !any(isempty, blocks(B)) - @test blocksizes(B,1) == [1,2,2] + @test blocklengths(axes(B,1)) == [1,2,2] + @test blocksizes(B) == [(1,), (2,), (2,)] end end @@ -183,13 +184,15 @@ using BlockArrays, Test A = BlockArray([1:6;], [2,2,2]) @test popfirst!(A) == 1 @test A == 2:6 - @test blocksizes(A,1) == [1,2,2] + @test blocklengths(axes(A,1)) == [1,2,2] + @test blocksizes(A) == [(1,), (2,), (2,)] @testset "empty blocks" begin B = BlockArray([1:6;], [0,0,1,2,3]) @test popfirst!(B) == 1 @test B == 2:6 - @test blocksizes(B,1) == [2,3] + @test blocklengths(axes(B,1)) == [2,3] + @test blocksizes(B) == [(2,), (3,)] @test !any(isempty, blocks(B)) end end From 5feb4768e44e337555cc743e664423332ee6b47e Mon Sep 17 00:00:00 2001 From: mtfishman Date: Thu, 9 May 2024 15:42:02 -0400 Subject: [PATCH 05/12] Add test Project.toml --- test/Project.toml | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 test/Project.toml diff --git a/test/Project.toml b/test/Project.toml new file mode 100644 index 00000000..fd4f08cd --- /dev/null +++ b/test/Project.toml @@ -0,0 +1,10 @@ +[deps] +Aqua = "4c88cf16-eb10-579e-8560-4a9242c79595" +ArrayLayouts = "4c555306-a7a7-4459-81d9-ec55ddd5c99a" +BandedMatrices = "aae01518-5342-5314-be14-df237901396f" +BlockArrays = "8e7c35d0-a365-5155-bbbb-fb81a777f24e" +Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4" +FillArrays = "1a297f60-69ca-5386-bcde-b61e274b549b" +InfiniteArrays = "4858937d-0d70-526a-a4dd-2d5cb5dd786c" +OffsetArrays = "6fe1bfb0-de20-5000-8ca7-80f57d26f881" +StaticArrays = "90137ffa-7385-5640-81b9-e52037218182" From a829f209a583b661e5a84fbaa4498174553f0c87 Mon Sep 17 00:00:00 2001 From: mtfishman Date: Thu, 9 May 2024 15:42:55 -0400 Subject: [PATCH 06/12] Git ignore vim temp files --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 4dae62ab..ca28dd4d 100644 --- a/.gitignore +++ b/.gitignore @@ -9,4 +9,5 @@ src/.DS_Store Manifest.toml Manifest-v*.*.toml .DS_Store +.*.swp build From f1dd36776938318a9a555078b604eadd80963d32 Mon Sep 17 00:00:00 2001 From: mtfishman Date: Thu, 9 May 2024 15:56:24 -0400 Subject: [PATCH 07/12] Fixes to test Project.toml --- test/Project.toml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/Project.toml b/test/Project.toml index fd4f08cd..d58010a4 100644 --- a/test/Project.toml +++ b/test/Project.toml @@ -2,9 +2,11 @@ Aqua = "4c88cf16-eb10-579e-8560-4a9242c79595" ArrayLayouts = "4c555306-a7a7-4459-81d9-ec55ddd5c99a" BandedMatrices = "aae01518-5342-5314-be14-df237901396f" -BlockArrays = "8e7c35d0-a365-5155-bbbb-fb81a777f24e" Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4" FillArrays = "1a297f60-69ca-5386-bcde-b61e274b549b" InfiniteArrays = "4858937d-0d70-526a-a4dd-2d5cb5dd786c" +LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" OffsetArrays = "6fe1bfb0-de20-5000-8ca7-80f57d26f881" +SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf" StaticArrays = "90137ffa-7385-5640-81b9-e52037218182" +Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" From 8198a0b950fc2a40362c37d2c02382beabed3f1b Mon Sep 17 00:00:00 2001 From: mtfishman Date: Thu, 9 May 2024 15:57:09 -0400 Subject: [PATCH 08/12] Another test Project.toml fix --- test/Project.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/test/Project.toml b/test/Project.toml index d58010a4..9c0fc8fa 100644 --- a/test/Project.toml +++ b/test/Project.toml @@ -7,6 +7,7 @@ FillArrays = "1a297f60-69ca-5386-bcde-b61e274b549b" InfiniteArrays = "4858937d-0d70-526a-a4dd-2d5cb5dd786c" LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" OffsetArrays = "6fe1bfb0-de20-5000-8ca7-80f57d26f881" +Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf" StaticArrays = "90137ffa-7385-5640-81b9-e52037218182" Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" From 83186240f63471f207f10c38f4698cbb59718382 Mon Sep 17 00:00:00 2001 From: mtfishman Date: Fri, 10 May 2024 13:55:08 -0400 Subject: [PATCH 09/12] Move code, change type design, better code coverage --- src/blockaxis.jl | 38 ------------------------------------- src/blocks.jl | 40 +++++++++++++++++++++++++++++++++++++++ test/test_blockindices.jl | 18 ------------------ test/test_blocks.jl | 33 ++++++++++++++++++++++++++++++++ 4 files changed, 73 insertions(+), 56 deletions(-) diff --git a/src/blockaxis.jl b/src/blockaxis.jl index 9a4042ed..1bfb3dd6 100644 --- a/src/blockaxis.jl +++ b/src/blockaxis.jl @@ -353,44 +353,6 @@ blocksize(A) = map(length, blockaxes(A)) blocksize(A,i) = length(blockaxes(A,i)) @inline blocklength(t) = prod(blocksize(t)) -struct BlockSizes{N,A<:AbstractArray{<:Any,N}} <: AbstractArray{NTuple{N,Int},N} - array::A -end -Base.size(a::BlockSizes) = blocksize(a.array) -Base.axes(a::BlockSizes) = map(br -> only(br.indices), blockaxes(a.array)) -Base.IteratorEltype(::Type{<:BlockSizes}) = Base.EltypeUnknown() -@propagate_inbounds getindex(a::BlockSizes{N}, i::Vararg{Int,N}) where {N} = - size(view(a.array, Block.(i)...)) -@propagate_inbounds function setindex!(a::BlockSizes{N}, b, i::Vararg{Int,N}) where {N} - error("Not implemented") -end - -""" - blocksizes(A::AbstractArray) - -Return an iterator over the sizes of each block. -See also size and blocksize. - -# Examples -```jldoctest -julia> A = BlockArray(ones(3,3),[2,1],[1,1,1]) -2×3-blocked 3×3 BlockMatrix{Float64}: - 1.0 │ 1.0 │ 1.0 - 1.0 │ 1.0 │ 1.0 - ─────┼───────┼───── - 1.0 │ 1.0 │ 1.0 - -julia> blocksizes(A) -2×3 BlockArrays.BlockSizes{2, BlockMatrix{Float64, Matrix{Matrix{Float64}}, Tuple{BlockedOneTo{Int64, Vector{Int64}}, BlockedOneTo{Int64, Vector{Int64}}}}}: - (2, 1) (2, 1) (2, 1) - (1, 1) (1, 1) (1, 1) - -julia> blocksizes(A)[2, 2] -(1, 1) -``` -""" -blocksizes(A::AbstractArray) = BlockSizes(A) - axes(b::AbstractBlockedUnitRange) = (BlockedOneTo(blocklasts(b) .- (first(b)-oneunit(eltype(b)))),) unsafe_indices(b::AbstractBlockedUnitRange) = axes(b) # ::Integer works around case where blocklasts might return different type diff --git a/src/blocks.jl b/src/blocks.jl index 3c2837a0..75c2e4d5 100644 --- a/src/blocks.jl +++ b/src/blocks.jl @@ -92,3 +92,43 @@ This is broken for now. See: https://github.com/JuliaArrays/BlockArrays.jl/issue copyto!(a[i...], b) a end + +""" + blocksizes(A::AbstractArray) + +Return an iterator over the sizes of each block. +See also size and blocksize. + +# Examples +```jldoctest +julia> A = BlockArray(ones(3,3),[2,1],[1,1,1]) +2×3-blocked 3×3 BlockMatrix{Float64}: + 1.0 │ 1.0 │ 1.0 + 1.0 │ 1.0 │ 1.0 + ─────┼───────┼───── + 1.0 │ 1.0 │ 1.0 + +julia> blocksizes(A) +2×3 BlockArrays.BlockSizes{2, BlockMatrix{Float64, Matrix{Matrix{Float64}}, Tuple{BlockedOneTo{Int64, Vector{Int64}}, BlockedOneTo{Int64, Vector{Int64}}}}}: + (2, 1) (2, 1) (2, 1) + (1, 1) (1, 1) (1, 1) + +julia> blocksizes(A)[2, 2] +(1, 1) +``` +""" +blocksizes(A::AbstractArray) = BlockSizes(A) + +struct BlockSizes{N,A<:AbstractArray{<:Any,N}} + array::A +end +Base.size(bs::BlockSizes) = blocksize(bs.array) +Base.length(bs::BlockSizes) = blocklength(bs.array) +Base.axes(bs::BlockSizes) = map(br -> only(br.indices), blockaxes(bs.array)) +Base.IteratorEltype(::Type{<:BlockSizes}) = Base.EltypeUnknown() +Base.IteratorSize(::Type{<:BlockSizes{N}}) where {N} = Base.HasShape{N}() +Base.iterate(bs::BlockSizes, i=1) = (@inline; (i - 1)%UInt < length(bs)%UInt ? (@inbounds bs[i], i + 1) : nothing) +@propagate_inbounds getindex(a::BlockSizes{N}, i::Vararg{Int,N}) where {N} = + size(view(a.array, Block.(i)...)) +@propagate_inbounds getindex(a::BlockSizes, i::Int) = + size(view(a.array, Block(i))) diff --git a/test/test_blockindices.jl b/test/test_blockindices.jl index 0cbea0ba..d85e1439 100644 --- a/test/test_blockindices.jl +++ b/test/test_blockindices.jl @@ -786,24 +786,6 @@ end @test eltype(blocklengths(r)) === UInt16 end - @testset "blocksizes" begin - v = Array(reshape(1:20, (5, 4))) - A = BlockArray(v, [2, 3], [3, 1]) - @test blocklengths.(axes(A)) == ([2, 3], [3, 1]) - bs = blocksizes(A) - @test bs == [(2, 3) (2, 1); (3, 3) (3, 1)] - @test bs[1, 1] == (2, 3) - @test bs[2, 1] == (3, 3) - @test bs[1, 2] == (2, 1) - @test bs[2, 2] == (3, 1) - @test bs[1] == (2, 3) - @test bs[2] == (3, 3) - @test bs[3] == (2, 1) - @test bs[4] == (3, 1) - @test size(bs) == (2, 2) - @test axes(bs) == (1:2, 1:2) - end - @testset "show" begin b = blockedrange([1,2]) @test repr(b) == "$BlockedOneTo($([1,3]))" diff --git a/test/test_blocks.jl b/test/test_blocks.jl index f3b02751..cb4ffc78 100644 --- a/test/test_blocks.jl +++ b/test/test_blocks.jl @@ -105,4 +105,37 @@ using Test, BlockArrays end end +@testset "blocksizes" begin + @testset "blocksizes" begin + v = Array(reshape(1:20, (5, 4))) + A = BlockArray(v, [2, 3], [3, 1]) + @test blocklengths.(axes(A)) == ([2, 3], [3, 1]) + bs = blocksizes(A) + @test size(bs) == (2, 2) + @test length(bs) == 4 + @test axes(bs) == (1:2, 1:2) + @test bs[1, 1] == (2, 3) + @test bs[2, 1] == (3, 3) + @test bs[1, 2] == (2, 1) + @test bs[2, 2] == (3, 1) + @test bs[1] == (2, 3) + @test bs[2] == (3, 3) + @test bs[3] == (2, 1) + @test bs[4] == (3, 1) + + # Iteration + @test Base.IteratorEltype(typeof(bs)) === Base.EltypeUnknown() + @test Base.IteratorSize(typeof(bs)) === Base.HasShape{2}() + for bs_mat in ( + collect(bs), + [b for b in bs] + ) + @test bs_mat isa Matrix{Tuple{Int,Int}} + @test bs_mat == [(2, 3) (2, 1); (3, 3) (3, 1)] + @test eltype(bs_mat) === Tuple{Int,Int} + @test size(bs_mat) == (2, 2) + end + end +end + end # module From 061eede56692fe1149eb0c74946176864f06c7f4 Mon Sep 17 00:00:00 2001 From: mtfishman Date: Fri, 10 May 2024 14:01:46 -0400 Subject: [PATCH 10/12] Backwards compatibility. Fix doctest. --- src/blocks.jl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/blocks.jl b/src/blocks.jl index 75c2e4d5..9f0d78c9 100644 --- a/src/blocks.jl +++ b/src/blocks.jl @@ -108,8 +108,8 @@ julia> A = BlockArray(ones(3,3),[2,1],[1,1,1]) ─────┼───────┼───── 1.0 │ 1.0 │ 1.0 -julia> blocksizes(A) -2×3 BlockArrays.BlockSizes{2, BlockMatrix{Float64, Matrix{Matrix{Float64}}, Tuple{BlockedOneTo{Int64, Vector{Int64}}, BlockedOneTo{Int64, Vector{Int64}}}}}: +julia> collect(blocksizes(A)) +2×3 Matrix{Tuple{Int64, Int64}}: (2, 1) (2, 1) (2, 1) (1, 1) (1, 1) (1, 1) @@ -127,7 +127,7 @@ Base.length(bs::BlockSizes) = blocklength(bs.array) Base.axes(bs::BlockSizes) = map(br -> only(br.indices), blockaxes(bs.array)) Base.IteratorEltype(::Type{<:BlockSizes}) = Base.EltypeUnknown() Base.IteratorSize(::Type{<:BlockSizes{N}}) where {N} = Base.HasShape{N}() -Base.iterate(bs::BlockSizes, i=1) = (@inline; (i - 1)%UInt < length(bs)%UInt ? (@inbounds bs[i], i + 1) : nothing) +Base.iterate(bs::BlockSizes, i=1) = ((i - 1)%UInt < length(bs)%UInt ? (@inbounds bs[i], i + 1) : nothing) @propagate_inbounds getindex(a::BlockSizes{N}, i::Vararg{Int,N}) where {N} = size(view(a.array, Block.(i)...)) @propagate_inbounds getindex(a::BlockSizes, i::Int) = From 9cd03668402f91d84c975129c2b2a37737e24453 Mon Sep 17 00:00:00 2001 From: mtfishman Date: Fri, 10 May 2024 14:07:23 -0400 Subject: [PATCH 11/12] Fix tests --- test/test_blockarrayinterface.jl | 2 +- test/test_blockarrays.jl | 2 +- test/test_blockdeque.jl | 6 +++--- test/test_blocklinalg.jl | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/test/test_blockarrayinterface.jl b/test/test_blockarrayinterface.jl index 56a8f3d9..69b73648 100644 --- a/test/test_blockarrayinterface.jl +++ b/test/test_blockarrayinterface.jl @@ -17,7 +17,7 @@ end @test blocksize(A, 1) == 1 @test blocklengths.(axes(A)) == ([5],) @test blocklengths(axes(A, 1)) == [5] - @test blocksizes(A) == [(5,)] + @test collect(blocksizes(A)) == [(5,)] @test A[Block(1)] == A view(A, Block(1))[1] = 2 @test A[1] == 2 diff --git a/test/test_blockarrays.jl b/test/test_blockarrays.jl index a6275b76..b2bc7340 100644 --- a/test/test_blockarrays.jl +++ b/test/test_blockarrays.jl @@ -110,7 +110,7 @@ end # test that BlockArrays may be created from immutable arrays B = BlockArray(reshape(1:9,3,3), [2,1], [2,1]) @test blocklengths.(axes(B)) == ([2,1], [2,1]) - @test blocksizes(B) == [(2,2) (2,1); (1,2) (1,1)] + @test collect(blocksizes(B)) == [(2,2) (2,1); (1,2) (1,1)] @test B == reshape([1:9;],3,3) @test blocks(B) isa Matrix{Matrix{Int}} diff --git a/test/test_blockdeque.jl b/test/test_blockdeque.jl index 2ea2d4bc..acde4796 100644 --- a/test/test_blockdeque.jl +++ b/test/test_blockdeque.jl @@ -168,7 +168,7 @@ using BlockArrays, Test @test B == 1:5 @test !any(isempty, blocks(B)) @test blocklengths(axes(B,1)) == [1,2,2] - @test blocksizes(B) == [(1,), (2,), (2,)] + @test collect(blocksizes(B)) == [(1,), (2,), (2,)] end end @@ -185,14 +185,14 @@ using BlockArrays, Test @test popfirst!(A) == 1 @test A == 2:6 @test blocklengths(axes(A,1)) == [1,2,2] - @test blocksizes(A) == [(1,), (2,), (2,)] + @test collect(blocksizes(A)) == [(1,), (2,), (2,)] @testset "empty blocks" begin B = BlockArray([1:6;], [0,0,1,2,3]) @test popfirst!(B) == 1 @test B == 2:6 @test blocklengths(axes(B,1)) == [2,3] - @test blocksizes(B) == [(2,), (3,)] + @test collect(blocksizes(B)) == [(2,), (3,)] @test !any(isempty, blocks(B)) end end diff --git a/test/test_blocklinalg.jl b/test/test_blocklinalg.jl index 788aeeac..fc97a388 100644 --- a/test/test_blocklinalg.jl +++ b/test/test_blocklinalg.jl @@ -102,13 +102,13 @@ bview(a, b) = Base.invoke(view, Tuple{AbstractArray,Any}, a, b) w = A * v @test w isa BlockArray @test blocklengths(axes(w,1)) == fill(2, 3) - @test blocksizes(w) == [(2,), (2,), (2,)] + @test collect(blocksizes(w)) == [(2,), (2,), (2,)] @test w ≈ Array(A) * v ≈ A * Array(v) ≈ Array(A) * Array(v) z = A * w @test z isa BlockArray @test blocklengths(axes(z,1)) == fill(2, 3) - @test blocksizes(z) == [(2,), (2,), (2,)] + @test collect(blocksizes(z)) == [(2,), (2,), (2,)] @test z ≈ Array(A) * w ≈ A * Array(w) ≈ Array(A) * Array(w) end From e56ca07acf065357b69fa740c3c113e526d3f648 Mon Sep 17 00:00:00 2001 From: mtfishman Date: Tue, 14 May 2024 09:56:39 -0400 Subject: [PATCH 12/12] Redesign BlockSizes to be AbstractArray subtype --- src/blocks.jl | 35 +++++++++++++++------------ test/Project.toml | 13 ---------- test/test_blockarrayinterface.jl | 2 +- test/test_blockarrays.jl | 2 +- test/test_blockdeque.jl | 6 ++--- test/test_blocklinalg.jl | 4 ++-- test/test_blocks.jl | 41 +++++++++++++------------------- 7 files changed, 43 insertions(+), 60 deletions(-) delete mode 100644 test/Project.toml diff --git a/src/blocks.jl b/src/blocks.jl index 9f0d78c9..711a182a 100644 --- a/src/blocks.jl +++ b/src/blocks.jl @@ -76,7 +76,7 @@ BlocksView(a::AbstractArray{S,N}) where {S,N} = Base.IteratorEltype(::Type{<:BlocksView}) = Base.EltypeUnknown() Base.size(a::BlocksView) = blocksize(a.array) -Base.axes(a::BlocksView) = map(br -> only(br.indices), blockaxes(a.array)) +Base.axes(a::BlocksView) = map(br -> Int.(br), blockaxes(a.array)) #= This is broken for now. See: https://github.com/JuliaArrays/BlockArrays.jl/issues/120 @@ -95,6 +95,7 @@ end """ blocksizes(A::AbstractArray) + blocksizes(A::AbstractArray, d::Integer) Return an iterator over the sizes of each block. See also size and blocksize. @@ -108,27 +109,31 @@ julia> A = BlockArray(ones(3,3),[2,1],[1,1,1]) ─────┼───────┼───── 1.0 │ 1.0 │ 1.0 -julia> collect(blocksizes(A)) -2×3 Matrix{Tuple{Int64, Int64}}: +julia> blocksizes(A) +2×3 BlockArrays.BlockSizes{Tuple{Int64, Int64}, 2, BlockMatrix{Float64, Matrix{Matrix{Float64}}, Tuple{BlockedOneTo{Int64, Vector{Int64}}, BlockedOneTo{Int64, Vector{Int64}}}}}: (2, 1) (2, 1) (2, 1) (1, 1) (1, 1) (1, 1) -julia> blocksizes(A)[2, 2] -(1, 1) +julia> blocksizes(A)[1,2] +(2, 1) + +julia> blocksizes(A,2) +3-element Vector{Int64}: + 1 + 1 + 1 ``` """ blocksizes(A::AbstractArray) = BlockSizes(A) +blocksizes(A::AbstractArray, d::Integer) = blocklengths(axes(A, d)) -struct BlockSizes{N,A<:AbstractArray{<:Any,N}} +struct BlockSizes{T,N,A<:AbstractArray{<:Any,N}} <: AbstractArray{T,N} array::A end -Base.size(bs::BlockSizes) = blocksize(bs.array) -Base.length(bs::BlockSizes) = blocklength(bs.array) -Base.axes(bs::BlockSizes) = map(br -> only(br.indices), blockaxes(bs.array)) -Base.IteratorEltype(::Type{<:BlockSizes}) = Base.EltypeUnknown() -Base.IteratorSize(::Type{<:BlockSizes{N}}) where {N} = Base.HasShape{N}() -Base.iterate(bs::BlockSizes, i=1) = ((i - 1)%UInt < length(bs)%UInt ? (@inbounds bs[i], i + 1) : nothing) -@propagate_inbounds getindex(a::BlockSizes{N}, i::Vararg{Int,N}) where {N} = +BlockSizes(a::AbstractArray{<:Any,N}) where {N} = + BlockSizes{Tuple{eltype.(axes(a))...},N,typeof(a)}(a) + +size(bs::BlockSizes) = blocksize(bs.array) +axes(bs::BlockSizes) = map(br -> Int.(br), blockaxes(bs.array)) +@propagate_inbounds getindex(a::BlockSizes{T,N}, i::Vararg{Int,N}) where {T,N} = size(view(a.array, Block.(i)...)) -@propagate_inbounds getindex(a::BlockSizes, i::Int) = - size(view(a.array, Block(i))) diff --git a/test/Project.toml b/test/Project.toml deleted file mode 100644 index 9c0fc8fa..00000000 --- a/test/Project.toml +++ /dev/null @@ -1,13 +0,0 @@ -[deps] -Aqua = "4c88cf16-eb10-579e-8560-4a9242c79595" -ArrayLayouts = "4c555306-a7a7-4459-81d9-ec55ddd5c99a" -BandedMatrices = "aae01518-5342-5314-be14-df237901396f" -Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4" -FillArrays = "1a297f60-69ca-5386-bcde-b61e274b549b" -InfiniteArrays = "4858937d-0d70-526a-a4dd-2d5cb5dd786c" -LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" -OffsetArrays = "6fe1bfb0-de20-5000-8ca7-80f57d26f881" -Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" -SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf" -StaticArrays = "90137ffa-7385-5640-81b9-e52037218182" -Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" diff --git a/test/test_blockarrayinterface.jl b/test/test_blockarrayinterface.jl index 69b73648..56a8f3d9 100644 --- a/test/test_blockarrayinterface.jl +++ b/test/test_blockarrayinterface.jl @@ -17,7 +17,7 @@ end @test blocksize(A, 1) == 1 @test blocklengths.(axes(A)) == ([5],) @test blocklengths(axes(A, 1)) == [5] - @test collect(blocksizes(A)) == [(5,)] + @test blocksizes(A) == [(5,)] @test A[Block(1)] == A view(A, Block(1))[1] = 2 @test A[1] == 2 diff --git a/test/test_blockarrays.jl b/test/test_blockarrays.jl index b2bc7340..a6275b76 100644 --- a/test/test_blockarrays.jl +++ b/test/test_blockarrays.jl @@ -110,7 +110,7 @@ end # test that BlockArrays may be created from immutable arrays B = BlockArray(reshape(1:9,3,3), [2,1], [2,1]) @test blocklengths.(axes(B)) == ([2,1], [2,1]) - @test collect(blocksizes(B)) == [(2,2) (2,1); (1,2) (1,1)] + @test blocksizes(B) == [(2,2) (2,1); (1,2) (1,1)] @test B == reshape([1:9;],3,3) @test blocks(B) isa Matrix{Matrix{Int}} diff --git a/test/test_blockdeque.jl b/test/test_blockdeque.jl index acde4796..2ea2d4bc 100644 --- a/test/test_blockdeque.jl +++ b/test/test_blockdeque.jl @@ -168,7 +168,7 @@ using BlockArrays, Test @test B == 1:5 @test !any(isempty, blocks(B)) @test blocklengths(axes(B,1)) == [1,2,2] - @test collect(blocksizes(B)) == [(1,), (2,), (2,)] + @test blocksizes(B) == [(1,), (2,), (2,)] end end @@ -185,14 +185,14 @@ using BlockArrays, Test @test popfirst!(A) == 1 @test A == 2:6 @test blocklengths(axes(A,1)) == [1,2,2] - @test collect(blocksizes(A)) == [(1,), (2,), (2,)] + @test blocksizes(A) == [(1,), (2,), (2,)] @testset "empty blocks" begin B = BlockArray([1:6;], [0,0,1,2,3]) @test popfirst!(B) == 1 @test B == 2:6 @test blocklengths(axes(B,1)) == [2,3] - @test collect(blocksizes(B)) == [(2,), (3,)] + @test blocksizes(B) == [(2,), (3,)] @test !any(isempty, blocks(B)) end end diff --git a/test/test_blocklinalg.jl b/test/test_blocklinalg.jl index fc97a388..788aeeac 100644 --- a/test/test_blocklinalg.jl +++ b/test/test_blocklinalg.jl @@ -102,13 +102,13 @@ bview(a, b) = Base.invoke(view, Tuple{AbstractArray,Any}, a, b) w = A * v @test w isa BlockArray @test blocklengths(axes(w,1)) == fill(2, 3) - @test collect(blocksizes(w)) == [(2,), (2,), (2,)] + @test blocksizes(w) == [(2,), (2,), (2,)] @test w ≈ Array(A) * v ≈ A * Array(v) ≈ Array(A) * Array(v) z = A * w @test z isa BlockArray @test blocklengths(axes(z,1)) == fill(2, 3) - @test collect(blocksizes(z)) == [(2,), (2,), (2,)] + @test blocksizes(z) == [(2,), (2,), (2,)] @test z ≈ Array(A) * w ≈ A * Array(w) ≈ Array(A) * Array(w) end diff --git a/test/test_blocks.jl b/test/test_blocks.jl index cb4ffc78..47b47423 100644 --- a/test/test_blocks.jl +++ b/test/test_blocks.jl @@ -110,31 +110,22 @@ end v = Array(reshape(1:20, (5, 4))) A = BlockArray(v, [2, 3], [3, 1]) @test blocklengths.(axes(A)) == ([2, 3], [3, 1]) - bs = blocksizes(A) - @test size(bs) == (2, 2) - @test length(bs) == 4 - @test axes(bs) == (1:2, 1:2) - @test bs[1, 1] == (2, 3) - @test bs[2, 1] == (3, 3) - @test bs[1, 2] == (2, 1) - @test bs[2, 2] == (3, 1) - @test bs[1] == (2, 3) - @test bs[2] == (3, 3) - @test bs[3] == (2, 1) - @test bs[4] == (3, 1) - - # Iteration - @test Base.IteratorEltype(typeof(bs)) === Base.EltypeUnknown() - @test Base.IteratorSize(typeof(bs)) === Base.HasShape{2}() - for bs_mat in ( - collect(bs), - [b for b in bs] - ) - @test bs_mat isa Matrix{Tuple{Int,Int}} - @test bs_mat == [(2, 3) (2, 1); (3, 3) (3, 1)] - @test eltype(bs_mat) === Tuple{Int,Int} - @test size(bs_mat) == (2, 2) - end + bs = @inferred(blocksizes(A)) + @test @inferred(size(bs)) == (2, 2) + @test @inferred(length(bs)) == 4 + @test @inferred(axes(bs)) == (1:2, 1:2) + @test @inferred(eltype(bs)) === Tuple{Int,Int} + @test bs == [(2, 3) (2, 1); (3, 3) (3, 1)] + @test @inferred(bs[1, 1]) == (2, 3) + @test @inferred(bs[2, 1]) == (3, 3) + @test @inferred(bs[1, 2]) == (2, 1) + @test @inferred(bs[2, 2]) == (3, 1) + @test @inferred(bs[1]) == (2, 3) + @test @inferred(bs[2]) == (3, 3) + @test @inferred(bs[3]) == (2, 1) + @test @inferred(bs[4]) == (3, 1) + @test blocksizes(A, 1) == [2, 3] + @test blocksizes(A, 2) == [3, 1] end end