From c1f81548c38f9a397060d5408b93e89455b56202 Mon Sep 17 00:00:00 2001 From: Sheehan Olver Date: Tue, 29 Sep 2026 17:09:16 +0100 Subject: [PATCH] Fix bandwidths of blocks of banded matrices bandwidths(view(A, Block(K), Block(J))) returned subblockbandwidths(A) for any parent, ignoring the offset of the block from the diagonal. For a banded (not block-banded) parent this was inconsistent with bandeddata, so indexing off-diagonal blocks threw a BoundsError, and for lazy infinite banded matrices it called subblockbandwidths, which fails on infinite axes. Co-Authored-By: Claude Opus 5.5 --- Project.toml | 2 +- src/BandedBlockBandedMatrix.jl | 8 +++++++- test/test_misc.jl | 8 ++++++++ 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/Project.toml b/Project.toml index b8c8f39..d04df31 100644 --- a/Project.toml +++ b/Project.toml @@ -1,6 +1,6 @@ name = "BlockBandedMatrices" uuid = "ffab5731-97b5-5995-9138-79e8c1846df0" -version = "0.13.7" +version = "0.13.8" [deps] ArrayLayouts = "4c555306-a7a7-4459-81d9-ec55ddd5c99a" diff --git a/src/BandedBlockBandedMatrix.jl b/src/BandedBlockBandedMatrix.jl index 4a6ce40..9abf558 100644 --- a/src/BandedBlockBandedMatrix.jl +++ b/src/BandedBlockBandedMatrix.jl @@ -514,10 +514,16 @@ function getindex(A::BandedBlockBandedMatrix{T}, KR::BlockRange{1}, JR::BlockRan _BandedBlockBandedMatrix(A.data[:,JR], axes(axes(A,1)[KR],1), (l-sh, u+sh), subblockbandwidths(A)) end -@inline function bandwidths(V::SubArray{T,2,<:AbstractMatrix,<:Tuple{BlockSlice1,BlockSlice1}}) where T +@inline bandwidths(V::SubArray{T,2,<:AbstractMatrix,<:Tuple{BlockSlice1,BlockSlice1}}) where T = _block_bandwidths(MemoryLayout(parent(V)), V) + +@inline function _blockbanded_block_bandwidths(V) inblockbands(V) && return subblockbandwidths(parent(V)) (-720,-720) end +@inline _block_bandwidths(_, V) = _blockbanded_block_bandwidths(V) +@inline _block_bandwidths(::DiagonalLayout, V) = _blockbanded_block_bandwidths(V) +# a block of a banded matrix is banded with the bandwidths shifted by the offset of the block from the diagonal +@inline _block_bandwidths(::AbstractBandedLayout, V) = min.(size(V) .- 1, bandwidths(parent(V)) .+ (-1,1) .* bandshift(V)) function bandwidths(V::SubArray{T,2,<:AbstractMatrix,<:Tuple{BlockSlice{<:BlockIndexRange1},BlockSlice{<:BlockIndexRange1}}}) where T B = parentblock(V) diff --git a/test/test_misc.jl b/test/test_misc.jl index d670aad..47bdafa 100644 --- a/test/test_misc.jl +++ b/test/test_misc.jl @@ -204,6 +204,14 @@ Base.size(F::FiniteDifference) = (F.n,F.n) @test Q isa BandedMatrix @test blockrowsupport(Q,Block(1)) == Block.(2:2) + @test bandwidths(view(B, Block(2), Block(1))) == (1,0) + @test all(B[Block(K,J)] == Matrix(B)[a[Block(K)], a[Block(J)]] for K=1:5, J=1:5) + + # blocks of a banded matrix with blocked axes, including blocks where the bandwidths are shifted + B = _BandedMatrix(BlockedArray(randn(5,6), (Base.OneTo(5), blockedrange(1:3))), blockedrange(1:2), 2, 2) + @test bandwidths(view(B, Block(2), Block(3))) == (1,0) + @test all(B[Block(K,J)] == Matrix(B)[axes(B,1)[Block(K)], axes(B,2)[Block(J)]] for K=1:2, J=1:3) + @testset "constant blocks" begin a = blockedrange(Fill(2,5)) Q = Eye((a,))[:,Block(2)]