From 1ba0d8c2fd23f8e1f6fbae3bb1e1ecd5b2ed7c62 Mon Sep 17 00:00:00 2001 From: "Viral B. Shah" Date: Thu, 10 Sep 2026 09:32:38 +0000 Subject: [PATCH 1/3] Define getrowval and getnzval for sparse vectors `rowvals` already covers `SparseVectorUnion`, but the `getrowval` and `getnzval` accessors used throughout linalg.jl only had matrix methods. Add the vector methods so both accessor families cover both types. Fixes #172 Co-Authored-By: Claude Fable 5.1 Claude-Session: https://claude.ai/code/session_01Lbrk9jqFT4HCx4ENQdtx6f --- src/sparsevector.jl | 2 ++ test/sparsevector.jl | 6 +++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/sparsevector.jl b/src/sparsevector.jl index 3af14f1f..bf9e55ce 100644 --- a/src/sparsevector.jl +++ b/src/sparsevector.jl @@ -184,6 +184,8 @@ function nonzeroinds(x::SparseVectorPartialView) end rowvals(x::SparseVectorUnion) = nonzeroinds(x) +getrowval(x::SparseVectorUnion) = nonzeroinds(x) +getnzval(x::SparseVectorUnion) = nonzeros(x) indtype(x::SparseColumnView) = indtype(parent(x)) indtype(x::Union{SparseVectorView, SparseVectorPartialView}) = indtype(parent(x)) diff --git a/test/sparsevector.jl b/test/sparsevector.jl index c6f2827a..994bbaf5 100644 --- a/test/sparsevector.jl +++ b/test/sparsevector.jl @@ -4,7 +4,7 @@ module SparseVectorTests using Test using SparseArrays -using SparseArrays: nonzeroinds, getcolptr +using SparseArrays: nonzeroinds, getcolptr, getrowval, getnzval using LinearAlgebra using Random include("forbidproperties.jl") @@ -32,6 +32,10 @@ x1_full[SparseArrays.nonzeroinds(spv_x1)] = nonzeros(spv_x1) @test nnz(x) == 3 @test SparseArrays.nonzeroinds(x) == [2, 5, 6] @test nonzeros(x) == [1.25, -0.75, 3.5] + @test getrowval(x) === rowvals(x) === nonzeroinds(x) + @test getnzval(x) === nonzeros(x) + @test getrowval(view(x, :)) == getrowval(view(sparse(x), :, 1)) == [2, 5, 6] + @test getnzval(view(x, :)) == getnzval(view(sparse(x), :, 1)) == [1.25, -0.75, 3.5] @test count(SparseVector(8, [2, 5, 6], [true,false,true])) == 2 @test count(SparseVector(8, [2, 5, 6], [true,false,true]), init=Int16(2))::Int16 == 4 y = SparseVector(8, Int128[4], [5]) From cd64088e9fcbe8e887002b87804dd801ece793ab Mon Sep 17 00:00:00 2001 From: "Viral B. Shah" Date: Thu, 10 Sep 2026 09:54:44 +0000 Subject: [PATCH 2/3] Document getrowval and getnzval as the preferred accessor names Add docstrings and docs entries for `getrowval` and `getnzval`, mark them `public`, and forward them through triangular wrappers like `rowvals` and `nonzeros` already are. Note in the `rowvals` and `nonzeros` docstrings that the new names match the `SparseMatrixCSC` fields and that the old names are likely to be deprecated. Co-Authored-By: Claude Fable 5.1 Claude-Session: https://claude.ai/code/session_01Lbrk9jqFT4HCx4ENQdtx6f --- docs/src/index.md | 2 + src/SparseArrays.jl | 2 +- src/sparsematrix.jl | 96 +++++++++++++++++++++++++++++++++++++++++--- test/sparsevector.jl | 2 + 4 files changed, 95 insertions(+), 7 deletions(-) diff --git a/docs/src/index.md b/docs/src/index.md index 4d0abc58..2dd4463a 100644 --- a/docs/src/index.md +++ b/docs/src/index.md @@ -235,6 +235,8 @@ SparseArrays.sparse_hvcat SparseArrays.blockdiag SparseArrays.sprand SparseArrays.sprandn +SparseArrays.getnzval +SparseArrays.getrowval SparseArrays.nonzeros SparseArrays.rowvals SparseArrays.nzrange diff --git a/src/SparseArrays.jl b/src/SparseArrays.jl index a82cfc42..70e8000d 100644 --- a/src/SparseArrays.jl +++ b/src/SparseArrays.jl @@ -35,7 +35,7 @@ export AbstractSparseArray, AbstractSparseMatrix, AbstractSparseVector, sprand, sprandn, spzeros, nnz, permute, findnz, fkeep!, ftranspose!, sparse_hcat, sparse_vcat, sparse_hvcat -public sparse!, spzeros! +public sparse!, spzeros!, getrowval, getnzval const LinAlgLeftQs = Union{HessenbergQ,QRCompactWYQ,QRPackedQ} diff --git a/src/sparsematrix.jl b/src/sparsematrix.jl index 3c7fb339..4417614a 100644 --- a/src/sparsematrix.jl +++ b/src/sparsematrix.jl @@ -194,10 +194,80 @@ const SparseMatrixCSCUnion2{Tv,Ti} = Union{AbstractSparseMatrixCSC{Tv,Ti}, Spars getcolptr(S::SorF) = getfield(S, :colptr) getcolptr(S::SparseMatrixCSCView) = view(getcolptr(parent(S)), first(S.indices[2]):(last(S.indices[2]) + 1)) getcolptr(S::SparseMatrixCSCColumnSubset) = error("getcolptr not well-defined for $(typeof(S))") +""" + getrowval(A) + +Return the vector of row indices of the structural nonzeros of sparse array `A`. +For a [`SparseMatrixCSC`](@ref) this is the `rowval` field; for a +[`SparseVector`](@ref) it is the `nzind` field. Any modifications to the returned +vector will mutate `A` as well. Providing access to how the row indices are +stored internally can be useful in conjunction with iterating over structural +nonzero values. See also [`getnzval`](@ref) and [`nzrange`](@ref). + +`getrowval` is the preferred name for this accessor; [`rowvals`](@ref) is +equivalent but is likely to be deprecated in a future release. + +# Examples +```jldoctest +julia> A = sparse(2I, 3, 3) +3×3 SparseMatrixCSC{Int64, Int64} with 3 stored entries: + 2 ⋅ ⋅ + ⋅ 2 ⋅ + ⋅ ⋅ 2 + +julia> SparseArrays.getrowval(A) +3-element Vector{Int64}: + 1 + 2 + 3 + +julia> SparseArrays.getrowval(sparsevec([2, 5], [3.0, 4.0])) +2-element Vector{Int64}: + 2 + 5 +``` +""" getrowval(S::AbstractSparseMatrixCSC) = rowvals(S) getrowval(S::SparseMatrixCSCColumnSubset) = rowvals(parent(S)) +getrowval(S::UpperTriangular{<:Any,<:SparseMatrixCSCUnion}) = rowvals(S.data) +getrowval(S::LowerTriangular{<:Any,<:SparseMatrixCSCUnion}) = rowvals(S.data) + +""" + getnzval(A) + +Return the vector of structural nonzero values of sparse array `A`, i.e. the `nzval` +field of a [`SparseMatrixCSC`](@ref) or [`SparseVector`](@ref). This includes zeros +that are explicitly stored in the sparse array. The returned vector points directly +to the internal nonzero storage of `A`, and any modifications to the returned vector +will mutate `A` as well. See also [`getrowval`](@ref) and [`nzrange`](@ref). + +`getnzval` is the preferred name for this accessor; [`nonzeros`](@ref) is +equivalent but is likely to be deprecated in a future release. + +# Examples +```jldoctest +julia> A = sparse(2I, 3, 3) +3×3 SparseMatrixCSC{Int64, Int64} with 3 stored entries: + 2 ⋅ ⋅ + ⋅ 2 ⋅ + ⋅ ⋅ 2 + +julia> SparseArrays.getnzval(A) +3-element Vector{Int64}: + 2 + 2 + 2 + +julia> SparseArrays.getnzval(sparsevec([2, 5], [3.0, 4.0])) +2-element Vector{Float64}: + 3.0 + 4.0 +``` +""" getnzval( S::AbstractSparseMatrixCSC) = nonzeros(S) getnzval( S::SparseMatrixCSCColumnSubset) = nonzeros(parent(S)) +getnzval( S::UpperTriangular{<:Any,<:SparseMatrixCSCUnion}) = nonzeros(S.data) +getnzval( S::LowerTriangular{<:Any,<:SparseMatrixCSCUnion}) = nonzeros(S.data) nzvalview(S::AbstractSparseMatrixCSC) = view(nonzeros(S), 1:nnz(S)) """ @@ -233,7 +303,14 @@ end nonzeros(A) Return a vector of the structural nonzero values in sparse array `A`. This -includes zeros that are explicitly stored in the sparse array. The returned +includes zeros that are explicitly stored in the sparse array. + +!!! note + [`getnzval`](@ref) is the preferred name for this accessor, matching the + `nzval` field of [`SparseMatrixCSC`](@ref). `nonzeros` is likely to be + deprecated in a future release. + +The returned vector points directly to the internal nonzero storage of `A`, and any modifications to the returned vector will mutate `A` as well. See [`rowvals`](@ref) and [`nzrange`](@ref). @@ -261,7 +338,14 @@ nonzeros(S::LowerTriangular{<:Any,<:SparseMatrixCSCUnion}) = nonzeros(S.data) """ rowvals(A) -Return a vector of the row indices of sparse array `A`. Any modifications to the returned +Return a vector of the row indices of sparse array `A`. + +!!! note + [`getrowval`](@ref) is the preferred name for this accessor, matching the + `rowval` field of [`SparseMatrixCSC`](@ref). `rowvals` is likely to be + deprecated in a future release. + +Any modifications to the returned vector will mutate `A` as well. Providing access to how the row indices are stored internally can be useful in conjunction with iterating over structural nonzero values. See also [`nonzeros`](@ref) and [`nzrange`](@ref). @@ -290,12 +374,12 @@ rowvals(S::LowerTriangular{<:Any,<:SparseMatrixCSCUnion}) = rowvals(S.data) nzrange(A, col::Integer) Return the range of indices to the structural nonzero values of column `col` -of sparse array `A`. In conjunction with [`nonzeros`](@ref) and -[`rowvals`](@ref), this allows for convenient iterating over a sparse matrix : +of sparse array `A`. In conjunction with [`getrowval`](@ref) and +[`getnzval`](@ref), this allows for convenient iterating over a sparse matrix : A = sparse(I,J,V) - rows = rowvals(A) - vals = nonzeros(A) + rows = SparseArrays.getrowval(A) + vals = SparseArrays.getnzval(A) m, n = size(A) for j = 1:n for i in nzrange(A, j) diff --git a/test/sparsevector.jl b/test/sparsevector.jl index 994bbaf5..045686af 100644 --- a/test/sparsevector.jl +++ b/test/sparsevector.jl @@ -36,6 +36,8 @@ x1_full[SparseArrays.nonzeroinds(spv_x1)] = nonzeros(spv_x1) @test getnzval(x) === nonzeros(x) @test getrowval(view(x, :)) == getrowval(view(sparse(x), :, 1)) == [2, 5, 6] @test getnzval(view(x, :)) == getnzval(view(sparse(x), :, 1)) == [1.25, -0.75, 3.5] + U = UpperTriangular(sparse(1.0I, 3, 3)) + @test getrowval(U) === rowvals(U) && getnzval(U) === nonzeros(U) @test count(SparseVector(8, [2, 5, 6], [true,false,true])) == 2 @test count(SparseVector(8, [2, 5, 6], [true,false,true]), init=Int16(2))::Int16 == 4 y = SparseVector(8, Int128[4], [5]) From e2219ef254cf98d5cb5ff7b1b98ff32bb013535d Mon Sep 17 00:00:00 2001 From: "Viral B. Shah" Date: Thu, 10 Sep 2026 10:06:25 +0000 Subject: [PATCH 3/3] Export getrowval and getnzval Co-Authored-By: Claude Fable 5.1 Claude-Session: https://claude.ai/code/session_01Lbrk9jqFT4HCx4ENQdtx6f --- src/SparseArrays.jl | 4 ++-- src/sparsematrix.jl | 12 ++++++------ test/sparsevector.jl | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/SparseArrays.jl b/src/SparseArrays.jl index 70e8000d..22722612 100644 --- a/src/SparseArrays.jl +++ b/src/SparseArrays.jl @@ -33,9 +33,9 @@ export AbstractSparseArray, AbstractSparseMatrix, AbstractSparseVector, SparseMatrixCSC, SparseVector, blockdiag, droptol!, dropzeros!, dropzeros, issparse, nonzeros, nzrange, rowvals, sparse, sparsevec, spdiagm, sprand, sprandn, spzeros, nnz, permute, findnz, fkeep!, ftranspose!, - sparse_hcat, sparse_vcat, sparse_hvcat + sparse_hcat, sparse_vcat, sparse_hvcat, getrowval, getnzval -public sparse!, spzeros!, getrowval, getnzval +public sparse!, spzeros! const LinAlgLeftQs = Union{HessenbergQ,QRCompactWYQ,QRPackedQ} diff --git a/src/sparsematrix.jl b/src/sparsematrix.jl index 4417614a..c71fbe9a 100644 --- a/src/sparsematrix.jl +++ b/src/sparsematrix.jl @@ -215,13 +215,13 @@ julia> A = sparse(2I, 3, 3) ⋅ 2 ⋅ ⋅ ⋅ 2 -julia> SparseArrays.getrowval(A) +julia> getrowval(A) 3-element Vector{Int64}: 1 2 3 -julia> SparseArrays.getrowval(sparsevec([2, 5], [3.0, 4.0])) +julia> getrowval(sparsevec([2, 5], [3.0, 4.0])) 2-element Vector{Int64}: 2 5 @@ -252,13 +252,13 @@ julia> A = sparse(2I, 3, 3) ⋅ 2 ⋅ ⋅ ⋅ 2 -julia> SparseArrays.getnzval(A) +julia> getnzval(A) 3-element Vector{Int64}: 2 2 2 -julia> SparseArrays.getnzval(sparsevec([2, 5], [3.0, 4.0])) +julia> getnzval(sparsevec([2, 5], [3.0, 4.0])) 2-element Vector{Float64}: 3.0 4.0 @@ -378,8 +378,8 @@ of sparse array `A`. In conjunction with [`getrowval`](@ref) and [`getnzval`](@ref), this allows for convenient iterating over a sparse matrix : A = sparse(I,J,V) - rows = SparseArrays.getrowval(A) - vals = SparseArrays.getnzval(A) + rows = getrowval(A) + vals = getnzval(A) m, n = size(A) for j = 1:n for i in nzrange(A, j) diff --git a/test/sparsevector.jl b/test/sparsevector.jl index 045686af..52fe30ea 100644 --- a/test/sparsevector.jl +++ b/test/sparsevector.jl @@ -4,7 +4,7 @@ module SparseVectorTests using Test using SparseArrays -using SparseArrays: nonzeroinds, getcolptr, getrowval, getnzval +using SparseArrays: nonzeroinds, getcolptr using LinearAlgebra using Random include("forbidproperties.jl")