From fde3a83890fd8095e4db3460ca0da745ea4eccc8 Mon Sep 17 00:00:00 2001 From: Jishnu Bhattacharya Date: Thu, 17 Apr 2025 18:31:48 +0530 Subject: [PATCH] `dataview` to forward row and col views --- Project.toml | 2 +- src/banded/BandedMatrix.jl | 96 +++++++++++++++++++++++++++++++++++++- test/test_subarray.jl | 24 ++++++++++ 3 files changed, 120 insertions(+), 2 deletions(-) diff --git a/Project.toml b/Project.toml index 228c9bbb..80157283 100644 --- a/Project.toml +++ b/Project.toml @@ -1,6 +1,6 @@ name = "BandedMatrices" uuid = "aae01518-5342-5314-be14-df237901396f" -version = "1.9.3" +version = "1.10.0" [deps] ArrayLayouts = "4c555306-a7a7-4459-81d9-ec55ddd5c99a" diff --git a/src/banded/BandedMatrix.jl b/src/banded/BandedMatrix.jl index d2d8bd7f..47173318 100644 --- a/src/banded/BandedMatrix.jl +++ b/src/banded/BandedMatrix.jl @@ -460,6 +460,100 @@ end return r end +# view along a column +""" + BandedMatrixColView + +Type alias to represent a view of a `BandedMatrix` along a column. +""" +const BandedMatrixColView{T} = SubArray{T, 1, <:BandedMatrix{T}, <:Tuple{AbstractUnitRange{<:Integer}, Integer}, false} + +""" + dataview(Vcol::BandedMatrixColView) + +Forward a view along a column of a `BandedMatrix` to the underlying data. + +!!! warn + This will error if the indexing is out-of-bounds for the data matrix, even if it is inbounds + for the parent `BandedMatrix`. In other words, the indices of the view must correspond to + stored data. + +# Examples +```jldoctest +julia> B = BandedMatrix(0=>2:4, 1=>1:2) +3×3 BandedMatrix{$Int} with bandwidths (0, 1): + 2 1 ⋅ + ⋅ 3 2 + ⋅ ⋅ 4 + +julia> v = view(B, 2, 2:3) +2-element view(::BandedMatrix{$Int, Matrix{$Int}, Base.OneTo{$Int}}, 2, 2:3) with eltype $Int: + 3 + 2 + +julia> BandedMatrices.dataview(v) +2-element view(::Vector{$Int}, 4:1:5) with eltype $Int: + 3 + 2 +``` +""" +function dataview(Vcol::BandedMatrixColView) + rowinds, col = parentindices(Vcol) + B = parent(Vcol) + l, u = bandwidths(B) + data_rowinds_col = data_colrange(B, col) + rowinds_shifted = rowinds .- (col - u - 1) + data_rowinds_col_shifted = data_rowinds_col[rowinds_shifted] + view(B.data, data_rowinds_col_shifted) +end + +# view along a row +""" + BandedMatrixColView + +Type alias to represent a view of a `BandedMatrix` along a row. +""" +const BandedMatrixRowView{T} = SubArray{T, 1, <:BandedMatrix{T}, <:Tuple{Integer, AbstractUnitRange{<:Integer}}, false} + +""" + dataview(Vrow::BandedMatrixRowView) + +Forward a view along a row of a `BandedMatrix` to the underlying data. + +!!! warn + This will error if the indexing is out-of-bounds for the data matrix, even if it is inbounds + for the parent `BandedMatrix`. In other words, the indices of the view must correspond to + stored data. + +# Examples +```jldoctest +julia> B = BandedMatrix(0=>2:4, 1=>1:2) +3×3 BandedMatrix{$Int} with bandwidths (0, 1): + 2 1 ⋅ + ⋅ 3 2 + ⋅ ⋅ 4 + +julia> v = view(B, 1:2, 2) +2-element view(::BandedMatrix{$Int, Matrix{$Int}, Base.OneTo{$Int}}, 1:2, 2) with eltype $Int: + 1 + 3 + +julia> BandedMatrices.dataview(v) +2-element view(::Vector{$Int}, 3:4) with eltype $Int: + 1 + 3 +``` +""" +function dataview(Vrow::BandedMatrixRowView) + row, colinds = parentindices(Vrow) + B = parent(Vrow) + l, u = bandwidths(B) + data_colinds = data_rowrange(B, row) + colinds_shifted = colinds .- (row - l - 1) + data_colinds_row_shifted = data_colinds[colinds_shifted] + view(B.data, data_colinds_row_shifted) +end + # ~ indexing along a band # we reduce it to converting a View @@ -467,7 +561,7 @@ end """ BandedMatrixBand -Type to represent a view of a band of a `BandedMatrix` +Type alias to represent a view of a band of a `BandedMatrix` # Examples ```jldoctest diff --git a/test/test_subarray.jl b/test/test_subarray.jl index a5eddb4d..20df37e4 100644 --- a/test/test_subarray.jl +++ b/test/test_subarray.jl @@ -127,4 +127,28 @@ include("mymatrix.jl") end end +@testset "dataview" begin + @testset "(1,1)" begin + B = brand(4, 4, 1, 1) + Vband = view(B, Band(1)) + @test BandedMatrices.dataview(Vband) == Vband + Vcol = view(B, 2:4, 3) + @test BandedMatrices.dataview(Vcol) == Vcol + Vcol = view(B, 3:4, 3) + @test BandedMatrices.dataview(Vcol) == Vcol + Vrow = view(B, 3, 2:4) + @test BandedMatrices.dataview(Vrow) == Vrow + Vrow = view(B, 3, 3:4) + @test BandedMatrices.dataview(Vrow) == Vrow + end + + @testset "(-1,2)" begin + B = brand(4, 4, -1, 2) + Vcol = view(B, 1:2, 3) + @test BandedMatrices.dataview(Vcol) == Vcol + Vrow = view(B, 2, 4:4) + @test BandedMatrices.dataview(Vrow) == Vrow + end +end + end # module