From 2f432a303db60cb20962dd53b9e89f3b76098f69 Mon Sep 17 00:00:00 2001 From: Daniel VandenHeuvel <95613936+DanielVandH@users.noreply.github.com> Date: Mon, 20 Oct 2025 13:38:43 +0100 Subject: [PATCH 1/7] BandedRows --- src/banded/BandedMatrix.jl | 22 ++++++++++++++++++++++ test/test_banded.jl | 10 +++++++++- 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/src/banded/BandedMatrix.jl b/src/banded/BandedMatrix.jl index 15d15822..fa5d6ad0 100644 --- a/src/banded/BandedMatrix.jl +++ b/src/banded/BandedMatrix.jl @@ -264,6 +264,28 @@ BandedMatrix(A::AbstractMatrix) = _BandedMatrix(MemoryLayout(A), A) ## specialised # use bandeddata if possible _BandedMatrix(::BandedColumns, A::AbstractMatrix) = _BandedMatrix(copy(bandeddata(A)), axes(A,1), bandwidths(A)...) +function _BandedMatrix(::BandedRows, A::AbstractMatrix) + if A isa Union{<:Adjoint, <:Transpose} + B = parent(A) + bdata = bandeddata(B) + data = copy(bdata) + adj = A isa Adjoint ? adjoint : transpose + ℓ, u = bandwidths(B) + n = size(B, 1) + for j in axes(B, 2) # Construct the data for A by flipping bands + for i in max(1, j - u):min(n, j + ℓ) + arow = u + 1 + i - j + acol = j + brow = ℓ + 1 + j - i + bcol = i + data[brow, bcol] = adj(bdata[arow, acol]) + end + end + return _BandedMatrix(data, axes(A, 1), bandwidths(A)...) + else + return BandedMatrix(A, bandwidths(A)) + end +end function _BandedMatrix(::DiagonalLayout, A::AbstractMatrix{T}) where T m,n = size(A) dat = Matrix{T}(undef, 1, n) diff --git a/test/test_banded.jl b/test/test_banded.jl index e0ec9352..db7e2b43 100644 --- a/test/test_banded.jl +++ b/test/test_banded.jl @@ -600,6 +600,14 @@ include("mymatrix.jl") @test B2 == B @test typeof(B2) == typeof(B) end + + @testset "_BandedMatrix(::BandedRows)" begin + A = brand(5, 5, 2, 1) + @test BandedMatrices._BandedMatrix(MemoryLayout(A'), A') == A' + @test BandedMatrix(A') == A' + @test BandedMatrix(A') !== A' + @test BandedMatrices.bandeddata(BandedMatrix(A')) !== BandedMatrices.bandeddata(A) + end end -end # module +end # module \ No newline at end of file From adb86fe04ab5fc1419cf00f27727662ad5102649 Mon Sep 17 00:00:00 2001 From: Daniel VandenHeuvel <95613936+DanielVandH@users.noreply.github.com> Date: Mon, 20 Oct 2025 13:40:49 +0100 Subject: [PATCH 2/7] EOL --- test/test_banded.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test_banded.jl b/test/test_banded.jl index db7e2b43..c5812bbb 100644 --- a/test/test_banded.jl +++ b/test/test_banded.jl @@ -610,4 +610,4 @@ include("mymatrix.jl") end end -end # module \ No newline at end of file +end # module From f3cfaf090fc75d6c607a15785b3408bfcd3fc676 Mon Sep 17 00:00:00 2001 From: Daniel VandenHeuvel <95613936+DanielVandH@users.noreply.github.com> Date: Mon, 20 Oct 2025 14:01:22 +0100 Subject: [PATCH 3/7] Add new interface function --- Project.toml | 2 +- docs/src/index.md | 1 + src/banded/BandedMatrix.jl | 31 +++++++++++++------------------ src/interfaceimpl.jl | 3 +++ 4 files changed, 18 insertions(+), 19 deletions(-) diff --git a/Project.toml b/Project.toml index 410a66fa..8b65b742 100644 --- a/Project.toml +++ b/Project.toml @@ -1,6 +1,6 @@ name = "BandedMatrices" uuid = "aae01518-5342-5314-be14-df237901396f" -version = "1.9.5" +version = "1.10.0" [deps] ArrayLayouts = "4c555306-a7a7-4459-81d9-ec55ddd5c99a" diff --git a/docs/src/index.md b/docs/src/index.md index a041cecb..ba4a7beb 100644 --- a/docs/src/index.md +++ b/docs/src/index.md @@ -218,6 +218,7 @@ interface consists of the following: | `inbands_setindex!(A, v, k, j)` | Unsafe: set `A[k,j] = v`, without the need to check if we are inside the bands | | `BandedMatrices.MemoryLayout(A)` | Override to get banded lazy linear algebra, e.g. `y .= Mul(A,x)` | | `BandedMatrices.bandeddata(A)` | Override to return a matrix of the entries in BLAS format. Required if `MemoryLayout(A)` returns `BandedColumnMajor` | +| `BandedMatrices.bandedrowsdata(A)` | Override to return a matrix of the entries reshaped to a row-major format. Required if `MemoryLayout(A)` returns `BandedRowsMajor` | Note that certain `SubArray`s of `BandedMatrix` are also banded matrices. The banded matrix interface is implemented for such `SubArray`s to take advantage of this. diff --git a/src/banded/BandedMatrix.jl b/src/banded/BandedMatrix.jl index fa5d6ad0..b3b1a0fa 100644 --- a/src/banded/BandedMatrix.jl +++ b/src/banded/BandedMatrix.jl @@ -265,26 +265,21 @@ BandedMatrix(A::AbstractMatrix) = _BandedMatrix(MemoryLayout(A), A) # use bandeddata if possible _BandedMatrix(::BandedColumns, A::AbstractMatrix) = _BandedMatrix(copy(bandeddata(A)), axes(A,1), bandwidths(A)...) function _BandedMatrix(::BandedRows, A::AbstractMatrix) - if A isa Union{<:Adjoint, <:Transpose} - B = parent(A) - bdata = bandeddata(B) - data = copy(bdata) - adj = A isa Adjoint ? adjoint : transpose - ℓ, u = bandwidths(B) - n = size(B, 1) - for j in axes(B, 2) # Construct the data for A by flipping bands - for i in max(1, j - u):min(n, j + ℓ) - arow = u + 1 + i - j - acol = j - brow = ℓ + 1 + j - i - bcol = i - data[brow, bcol] = adj(bdata[arow, acol]) - end + bdata = transpose(bandedrowsdata(A)) + data = copy(bdata) + adj = A isa Adjoint ? adjoint : transpose + u, ℓ = bandwidths(A) + n = size(A, 2) + for j in axes(A, 1) # Construct the data for A by flipping bands + for i in max(1, j - u):min(n, j + ℓ) + arow = u + 1 + i - j + acol = j + brow = ℓ + 1 + j - i + bcol = i + data[brow, bcol] = adj(bdata[arow, acol]) end - return _BandedMatrix(data, axes(A, 1), bandwidths(A)...) - else - return BandedMatrix(A, bandwidths(A)) end + return _BandedMatrix(data, axes(A, 1), bandwidths(A)...) end function _BandedMatrix(::DiagonalLayout, A::AbstractMatrix{T}) where T m,n = size(A) diff --git a/src/interfaceimpl.jl b/src/interfaceimpl.jl index e8dfec5a..725ded38 100644 --- a/src/interfaceimpl.jl +++ b/src/interfaceimpl.jl @@ -30,6 +30,9 @@ function bandeddata(D::Union{Diagonal, Transpose{<:Any, <:Diagonal}, Adjoint{<:A permutedims(diagonaldata(D)) end +bandedrowsdata(Ac::Transpose) = transpose(bandeddata(parent(Ac))) +bandedrowsdata(Ac::Adjoint{<:Real}) = transpose(bandeddata(parent(Ac))) + # treat subinds as banded sublayout(::DiagonalLayout{L}, inds::Type) where L = sublayout(bandedcolumns(L()), inds) sublayout(::DiagonalLayout{L}, inds::Type{<:NTuple{2,AbstractUnitRange{Int}}}) where L = sublayout(bandedcolumns(L()), inds) From 6973d796634e521aa64d8576c62434546e7705b2 Mon Sep 17 00:00:00 2001 From: Daniel VandenHeuvel <95613936+DanielVandH@users.noreply.github.com> Date: Mon, 20 Oct 2025 14:13:22 +0100 Subject: [PATCH 4/7] Use permutedims; cleanup implementation a bit --- src/banded/BandedMatrix.jl | 11 +++-------- src/interfaceimpl.jl | 4 ++-- 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/src/banded/BandedMatrix.jl b/src/banded/BandedMatrix.jl index b3b1a0fa..4815b00a 100644 --- a/src/banded/BandedMatrix.jl +++ b/src/banded/BandedMatrix.jl @@ -265,18 +265,13 @@ BandedMatrix(A::AbstractMatrix) = _BandedMatrix(MemoryLayout(A), A) # use bandeddata if possible _BandedMatrix(::BandedColumns, A::AbstractMatrix) = _BandedMatrix(copy(bandeddata(A)), axes(A,1), bandwidths(A)...) function _BandedMatrix(::BandedRows, A::AbstractMatrix) - bdata = transpose(bandedrowsdata(A)) - data = copy(bdata) - adj = A isa Adjoint ? adjoint : transpose + bdata = bandedrowsdata(A) + data = similar(bdata, eltype(bdata), reverse(size(bdata))) u, ℓ = bandwidths(A) n = size(A, 2) for j in axes(A, 1) # Construct the data for A by flipping bands for i in max(1, j - u):min(n, j + ℓ) - arow = u + 1 + i - j - acol = j - brow = ℓ + 1 + j - i - bcol = i - data[brow, bcol] = adj(bdata[arow, acol]) + data[ℓ + 1 + j - i, i] = bdata[j, u+1+i-j] end end return _BandedMatrix(data, axes(A, 1), bandwidths(A)...) diff --git a/src/interfaceimpl.jl b/src/interfaceimpl.jl index 725ded38..36fc54da 100644 --- a/src/interfaceimpl.jl +++ b/src/interfaceimpl.jl @@ -30,8 +30,8 @@ function bandeddata(D::Union{Diagonal, Transpose{<:Any, <:Diagonal}, Adjoint{<:A permutedims(diagonaldata(D)) end -bandedrowsdata(Ac::Transpose) = transpose(bandeddata(parent(Ac))) -bandedrowsdata(Ac::Adjoint{<:Real}) = transpose(bandeddata(parent(Ac))) +bandedrowsdata(Ac::Transpose) = permutedims(bandeddata(parent(Ac))) +bandedrowsdata(Ac::Adjoint{<:Real}) = permutedims(bandeddata(parent(Ac))) # treat subinds as banded sublayout(::DiagonalLayout{L}, inds::Type) where L = sublayout(bandedcolumns(L()), inds) From 670e9e8ad7eaa78d074d2f62c0e2a2b3af40d0ec Mon Sep 17 00:00:00 2001 From: Daniel VandenHeuvel <95613936+DanielVandH@users.noreply.github.com> Date: Mon, 20 Oct 2025 14:16:36 +0100 Subject: [PATCH 5/7] Combine iterator --- src/banded/BandedMatrix.jl | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/banded/BandedMatrix.jl b/src/banded/BandedMatrix.jl index 4815b00a..fbe02300 100644 --- a/src/banded/BandedMatrix.jl +++ b/src/banded/BandedMatrix.jl @@ -269,10 +269,8 @@ function _BandedMatrix(::BandedRows, A::AbstractMatrix) data = similar(bdata, eltype(bdata), reverse(size(bdata))) u, ℓ = bandwidths(A) n = size(A, 2) - for j in axes(A, 1) # Construct the data for A by flipping bands - for i in max(1, j - u):min(n, j + ℓ) - data[ℓ + 1 + j - i, i] = bdata[j, u+1+i-j] - end + for j in axes(A, 1), i in max(1, j - u):min(n, j + ℓ) + data[ℓ + 1 + j - i, i] = bdata[j, u+1+i-j] end return _BandedMatrix(data, axes(A, 1), bandwidths(A)...) end From a53e5274e1d904709570525697f0bcd800b8aad9 Mon Sep 17 00:00:00 2001 From: Sheehan Olver Date: Mon, 20 Oct 2025 21:50:54 +0100 Subject: [PATCH 6/7] don't test on pre anymore --- .github/workflows/ci.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 35c3dd3e..e4045fce 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -45,7 +45,6 @@ jobs: version: - 'lts' - '1' - - 'pre' os: - ubuntu-latest - macOS-latest From 4b3f55213d4925a8978d596121dccb15e040bb96 Mon Sep 17 00:00:00 2001 From: Daniel VandenHeuvel <95613936+DanielVandH@users.noreply.github.com> Date: Tue, 21 Oct 2025 18:15:37 +0100 Subject: [PATCH 7/7] Test transpose as well --- test/test_banded.jl | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/test/test_banded.jl b/test/test_banded.jl index c5812bbb..7c11dbb7 100644 --- a/test/test_banded.jl +++ b/test/test_banded.jl @@ -603,10 +603,12 @@ include("mymatrix.jl") @testset "_BandedMatrix(::BandedRows)" begin A = brand(5, 5, 2, 1) - @test BandedMatrices._BandedMatrix(MemoryLayout(A'), A') == A' - @test BandedMatrix(A') == A' - @test BandedMatrix(A') !== A' - @test BandedMatrices.bandeddata(BandedMatrix(A')) !== BandedMatrices.bandeddata(A) + for B in (A', transpose(A)) + @test BandedMatrices._BandedMatrix(MemoryLayout(B), B) == B + @test BandedMatrix(B) == B + @test BandedMatrix(B) !== B + @test BandedMatrices.bandeddata(BandedMatrix(B)) !== BandedMatrices.bandeddata(A) + end end end