From 485fd4babbeaed76906e88b6adc97496346727de Mon Sep 17 00:00:00 2001 From: Daniel Karrasch Date: Thu, 24 Oct 2024 17:54:31 +0200 Subject: [PATCH 01/11] Inline sparse-times-dense in-place multiplication (#567) --- src/linalg.jl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/linalg.jl b/src/linalg.jl index af7fe50d..6a4728cd 100644 --- a/src/linalg.jl +++ b/src/linalg.jl @@ -47,11 +47,11 @@ for op ∈ (:+, :-) end end -generic_matmatmul!(C::StridedMatrix, tA, tB, A::SparseMatrixCSCUnion2, B::DenseMatrixUnion, alpha::Number, beta::Number) = +@inline generic_matmatmul!(C::StridedMatrix, tA, tB, A::SparseMatrixCSCUnion2, B::DenseMatrixUnion, alpha::Number, beta::Number) = spdensemul!(C, tA, tB, A, B, alpha, beta) -generic_matmatmul!(C::StridedMatrix, tA, tB, A::SparseMatrixCSCUnion2, B::AbstractTriangular, alpha::Number, beta::Number) = +@inline generic_matmatmul!(C::StridedMatrix, tA, tB, A::SparseMatrixCSCUnion2, B::AbstractTriangular, alpha::Number, beta::Number) = spdensemul!(C, tA, tB, A, B, alpha, beta) -generic_matvecmul!(C::StridedVecOrMat, tA, A::SparseMatrixCSCUnion2, B::DenseInputVector, alpha::Number, beta::Number) = +@inline generic_matvecmul!(C::StridedVecOrMat, tA, A::SparseMatrixCSCUnion2, B::DenseInputVector, alpha::Number, beta::Number) = spdensemul!(C, tA, 'N', A, B, alpha, beta) Base.@constprop :aggressive function spdensemul!(C, tA, tB, A, B, alpha, beta) From 8f02b7ff55aba096062c5b3693627282ce8bafed Mon Sep 17 00:00:00 2001 From: CyHan Date: Sat, 26 Oct 2024 22:29:08 +0800 Subject: [PATCH 02/11] doc: move solvers doc to `src\solvers.md` (#576) --- docs/src/index.md | 14 -------------- docs/src/solvers.md | 18 ++++++++++++++++++ 2 files changed, 18 insertions(+), 14 deletions(-) diff --git a/docs/src/index.md b/docs/src/index.md index 69b5a87a..225d5a0b 100644 --- a/docs/src/index.md +++ b/docs/src/index.md @@ -206,20 +206,6 @@ section of the standard library reference. | [`sprandn(m,n,d)`](@ref) | [`randn(m,n)`](@ref) | Creates a *m*-by-*n* random matrix (of density *d*) with iid non-zero elements distributed according to the standard normal (Gaussian) distribution. | | [`sprandn(rng,m,n,d)`](@ref) | [`randn(rng,m,n)`](@ref) | Creates a *m*-by-*n* random matrix (of density *d*) with iid non-zero elements generated with the `rng` random number generator | -## [Sparse Linear Algebra](@id stdlib-sparse-linalg) - -Sparse matrix solvers call functions from [SuiteSparse](http://suitesparse.com). The following factorizations are available: - -1. [`cholesky`](@ref SparseArrays.CHOLMOD.cholesky) -2. [`ldlt`](@ref SparseArrays.CHOLMOD.ldlt) -3. [`lu`](@ref SparseArrays.UMFPACK.lu) -4. [`qr`](@ref SparseArrays.SPQR.qr) - -| Type | Description | -|:----------------------|:--------------------------------------------- | -| `CHOLMOD.Factor` | Cholesky and LDLt factorizations | -| `UMFPACK.UmfpackLU` | LU factorization | -| `SPQR.QRSparse` | QR factorization | ```@meta DocTestSetup = nothing diff --git a/docs/src/solvers.md b/docs/src/solvers.md index 1c7c630d..c2624b81 100644 --- a/docs/src/solvers.md +++ b/docs/src/solvers.md @@ -4,6 +4,24 @@ DocTestSetup = :(using LinearAlgebra, SparseArrays) ``` +## [Sparse Linear Algebra](@id stdlib-sparse-linalg) + +Sparse matrix solvers call functions from [SuiteSparse](http://suitesparse.com). + +The following factorizations are available: + +1. [`cholesky`](@ref SparseArrays.CHOLMOD.cholesky) +2. [`ldlt`](@ref SparseArrays.CHOLMOD.ldlt) +3. [`lu`](@ref SparseArrays.UMFPACK.lu) +4. [`qr`](@ref SparseArrays.SPQR.qr) + +| Type | Description | +|:----------------------|:--------------------------------------------- | +| `CHOLMOD.Factor` | Cholesky and LDLt factorizations | +| `UMFPACK.UmfpackLU` | LU factorization | +| `SPQR.QRSparse` | QR factorization | + + ```@docs; canonical=false SparseArrays.CHOLMOD.cholesky SparseArrays.CHOLMOD.cholesky! From 33491e08611f81710373e6594bf8a178a65edc47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mathieu=20Besan=C3=A7on?= Date: Tue, 29 Oct 2024 15:46:17 +0100 Subject: [PATCH 03/11] added diagonal-sparse multiplication (#564) Co-authored-by: Daniel Karrasch --- src/linalg.jl | 17 +++++++++++++++++ test/linalg.jl | 15 +++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/src/linalg.jl b/src/linalg.jl index 6a4728cd..7747de64 100644 --- a/src/linalg.jl +++ b/src/linalg.jl @@ -188,6 +188,23 @@ function _A_mul_Bt_or_Bc!(tfun::Function, C::StridedMatrix, A::AbstractMatrix, B C end +function *(A::Diagonal, b::AbstractSparseVector) + if size(A, 2) != length(b) + throw( + DimensionMismatch(lazy"The dimension of the matrix A $(size(A)) and of the vector b $(length(b))") + ) + end + T = promote_eltype(A, b) + res = similar(b, T) + nzind_b = nonzeroinds(b) + nzval_b = nonzeros(b) + nzval_res = nonzeros(res) + for idx in eachindex(nzind_b) + nzval_res[idx] = A.diag[nzind_b[idx]] * nzval_b[idx] + end + return res +end + # Sparse matrix multiplication as described in [Gustavson, 1978]: # http://dl.acm.org/citation.cfm?id=355796 diff --git a/test/linalg.jl b/test/linalg.jl index afa6eb47..b6113c50 100644 --- a/test/linalg.jl +++ b/test/linalg.jl @@ -673,6 +673,21 @@ end end end +@testset "diagonal - sparse vector mutliplication" begin + for _ in 1:10 + b = spzeros(10) + b[1:3] .= 1:3 + A = Diagonal(randn(10)) + @test norm(A * b - A * Vector(b)) <= 10eps() + @test norm(A * b - Array(A) * b) <= 10eps() + Ac = Diagonal(randn(Complex{Float64}, 10)) + @test norm(Ac * b - Ac * Vector(b)) <= 10eps() + @test norm(Ac * b - Array(Ac) * b) <= 10eps() + @test_throws DimensionMismatch A * [b; 1] + @test_throws DimensionMismatch A * b[1:end-1] + end +end + @testset "sparse matrix * BitArray" begin A = sprand(5,5,0.3) MA = Array(A) From 07cf4a6bc0fba7dca14f7ca86a3d722d260c0d12 Mon Sep 17 00:00:00 2001 From: "Viral B. Shah" <744411+ViralBShah@users.noreply.github.com> Date: Sat, 2 Nov 2024 13:46:38 -0400 Subject: [PATCH 04/11] Update ci.yml (#578) * Update ci.yml --- .github/workflows/ci.yml | 20 ++++---------------- 1 file changed, 4 insertions(+), 16 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7ceb91e5..b6e14d0f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -23,34 +23,23 @@ jobs: os: - ubuntu-latest - windows-latest - - macOS-13 # intel julia-arch: - x64 - x86 - exclude: - - os: macOS-13 - julia-arch: x86 include: - os: macOS-latest julia-arch: aarch64 julia-version: 'nightly' - + - os: macOS-13 + julia-arch: x64 + julia-version: 'nightly' steps: - uses: actions/checkout@v4 - uses: julia-actions/setup-julia@v2 with: version: ${{ matrix.julia-version }} arch: ${{ matrix.julia-arch }} - - uses: actions/cache@v4 - env: - cache-name: cache-artifacts - with: - path: ~/.julia/artifacts - key: ${{ runner.os }}-test-${{ env.cache-name }}-${{ hashFiles('**/Project.toml') }} - restore-keys: | - ${{ runner.os }}-test-${{ env.cache-name }}- - ${{ runner.os }}-test-${{ matrix.os }} - ${{ runner.os }}- + - uses: julia-actions/cache@v2 - run: julia --color=yes .ci/test_and_change_uuid.jl - uses: julia-actions/julia-buildpkg@v1 - uses: julia-actions/julia-runtest@v1 @@ -91,7 +80,6 @@ jobs: - uses: actions/checkout@v4 - uses: julia-actions/setup-julia@v2 with: - # version: '1.6' version: 'nightly' - name: Generate docs run: | From 14333eae647464121150ae77d9f2dbe673aa244b Mon Sep 17 00:00:00 2001 From: William Moses Date: Mon, 11 Nov 2024 16:47:30 -0600 Subject: [PATCH 05/11] Break recursion (#579) --- src/sparsevector.jl | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/sparsevector.jl b/src/sparsevector.jl index a2102eff..b35c69db 100644 --- a/src/sparsevector.jl +++ b/src/sparsevector.jl @@ -1277,13 +1277,16 @@ function vcat(X1::_SparseConcatGroup, X::_SparseConcatGroup...) end return Base.typed_vcat(Base.promote_eltype(X1, X...), X1, X...) end -function hvcat(rows::Tuple{Vararg{Int}}, X1::_SparseConcatGroup, X::_SparseConcatGroup...) +function hvcat_internal(rows::Tuple{Vararg{Int}}, X1::_SparseConcatGroup, X::_SparseConcatGroup...) if anysparse(X1) || anysparse(X...) vcat(_hvcat_rows(rows, X1, X...)...) else Base.typed_hvcat(Base.promote_eltypeof(X1, X...), rows, X1, X...) end end +function hvcat(rows::Tuple{Vararg{Int}}, X1::_SparseConcatGroup, X::_SparseConcatGroup...) + return hvcat_internal(rows, X1, X...) +end function _hvcat_rows((row1, rows...)::Tuple{Vararg{Int}}, X::_SparseConcatGroup...) if row1 ≤ 0 throw(ArgumentError("length of block row must be positive, got $row1")) @@ -1304,9 +1307,8 @@ hcat(n1::Number, ns::Vararg{Number}) = invoke(hcat, Tuple{Vararg{Number}}, n1, n vcat(n1::Number, ns::Vararg{Number}) = invoke(vcat, Tuple{Vararg{Number}}, n1, ns...) hcat(n1::N, ns::Vararg{N}) where {N<:Number} = invoke(hcat, Tuple{Vararg{N}}, n1, ns...) vcat(n1::N, ns::Vararg{N}) where {N<:Number} = invoke(vcat, Tuple{Vararg{N}}, n1, ns...) -hvcat(rows::Tuple{Vararg{Int}}, n1::Number, ns::Vararg{Number}) = invoke(hvcat, Tuple{typeof(rows), Vararg{Number}}, rows, n1, ns...) -hvcat(rows::Tuple{Vararg{Int}}, n1::N, ns::Vararg{N}) where {N<:Number} = invoke(hvcat, Tuple{typeof(rows), Vararg{N}}, rows, n1, ns...) - +hvcat(rows::Tuple{Vararg{Int}}, n1::Number, ns::Vararg{Number}) = hvcat_internal(rows, n1, ns...) +hvcat(rows::Tuple{Vararg{Int}}, n1::N, ns::Vararg{N}) where {N<:Number} = hvcat_internal(rows, n1, ns...) ### Efficient repetition of sparse vectors From 1b4933ccc7b1f97427ff88bd7ba58950021f2c60 Mon Sep 17 00:00:00 2001 From: Keno Fischer Date: Tue, 19 Nov 2024 22:16:40 -0500 Subject: [PATCH 06/11] Make `allowscalar` a macro with auto-world-age-increment (#583) Goes along with https://github.com/JuliaLang/julia/pull/56509 --- src/abstractsparse.jl | 7 +++++++ test/allowscalar.jl | 8 ++++---- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/abstractsparse.jl b/src/abstractsparse.jl index 37f79e25..d23eebca 100644 --- a/src/abstractsparse.jl +++ b/src/abstractsparse.jl @@ -184,6 +184,13 @@ else end end +macro allowscalar(p) + quote + $(allowscalar)($(esc(p))) + @Core.latestworld + end +end + @inline _is_fixed(::AbstractArray) = false @inline _is_fixed(A::AbstractArray, Bs::Vararg{Any,N}) where N = _is_fixed(A) || (N > 0 && _is_fixed(Bs...)) macro if_move_fixed(a...) diff --git a/test/allowscalar.jl b/test/allowscalar.jl index fa35f35c..306689c5 100644 --- a/test/allowscalar.jl +++ b/test/allowscalar.jl @@ -4,10 +4,10 @@ using Test, SparseArrays A = sprandn(10, 20, 0.9) A[1, 1] = 2 @test A[1, 1] == 2 - SparseArrays.allowscalar(false) + SparseArrays.@allowscalar(false) @test_throws Any A[1, 1] @test_throws Any A[1, 1] = 2 - SparseArrays.allowscalar(true) + SparseArrays.@allowscalar(true) @test A[1, 1] == 2 A[1, 1] = 3 @test A[1, 1] == 3 @@ -15,9 +15,9 @@ using Test, SparseArrays B = sprandn(10, 0.9) B[1] = 2 @test B[1] == 2 - SparseArrays.allowscalar(false) + SparseArrays.@allowscalar(false) @test_throws Any B[1] - SparseArrays.allowscalar(true) + SparseArrays.@allowscalar(true) @test B[1] == 2 B[1] = 3 @test B[1] == 3 From 9731aef85c043a98d909f6e98841de9703e8b6d0 Mon Sep 17 00:00:00 2001 From: Kristoffer Carlsson Date: Fri, 22 Nov 2024 10:14:43 +0100 Subject: [PATCH 07/11] get rid of UUID changing stuff (#582) --- .ci/test_and_change_uuid.jl | 28 ---------------------------- .github/workflows/ci.yml | 5 +---- README.md | 10 ---------- 3 files changed, 1 insertion(+), 42 deletions(-) delete mode 100644 .ci/test_and_change_uuid.jl diff --git a/.ci/test_and_change_uuid.jl b/.ci/test_and_change_uuid.jl deleted file mode 100644 index cca5dc3f..00000000 --- a/.ci/test_and_change_uuid.jl +++ /dev/null @@ -1,28 +0,0 @@ -@static if Base.VERSION >= v"1.6" - using TOML - using Test -else - using Pkg: TOML - using Test -end - -# To generate the new UUID, we simply modify the first character of the original UUID -const original_uuid = "2f01184e-e22b-5df5-ae63-d93ebab69eaf" -const new_uuid = "4f01184e-e22b-5df5-ae63-d93ebab69eaf" - -# `@__DIR__` is the `.ci/` folder. -# Therefore, `dirname(@__DIR__)` is the repository root. -const project_filename = joinpath(dirname(@__DIR__), "Project.toml") - -@testset "Test that the UUID is unchanged" begin - project_dict = TOML.parsefile(project_filename) - @test project_dict["uuid"] == original_uuid -end - -write( - project_filename, - replace( - read(project_filename, String), - r"uuid = .*?\n" => "uuid = \"$(new_uuid)\"\n", - ), -) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b6e14d0f..7a6ff08c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -40,7 +40,6 @@ jobs: version: ${{ matrix.julia-version }} arch: ${{ matrix.julia-arch }} - uses: julia-actions/cache@v2 - - run: julia --color=yes .ci/test_and_change_uuid.jl - uses: julia-actions/julia-buildpkg@v1 - uses: julia-actions/julia-runtest@v1 - uses: julia-actions/julia-processcoverage@v1 @@ -69,7 +68,6 @@ jobs: version: ${{ matrix.julia-version }} arch: ${{ matrix.julia-arch }} - uses: julia-actions/cache@v2 - - run: julia --color=yes .ci/test_and_change_uuid.jl - uses: julia-actions/julia-buildpkg@v1 - uses: julia-actions/julia-runtest@v1 env: @@ -83,8 +81,7 @@ jobs: version: 'nightly' - name: Generate docs run: | - julia --color=yes -e 'write("Project.toml", replace(read("Project.toml", String), r"uuid = .*?\n" =>"uuid = \"3f01184e-e22b-5df5-ae63-d93ebab69eaf\"\n"));' - julia --project --color=yes -e 'using Pkg; Pkg.activate("docs"); Pkg.instantiate(); Pkg.develop(PackageSpec(path = pwd()))' + julia --project --color=yes -e 'using Pkg; Pkg.activate("docs"); Pkg.develop(PackageSpec(path = pwd()))' julia --project=docs --color=yes docs/make.jl pdf env: DOCUMENTER_KEY: ${{ secrets.DOCUMENTER_KEY }} diff --git a/README.md b/README.md index 66124503..01135b0c 100644 --- a/README.md +++ b/README.md @@ -20,16 +20,6 @@ This package ships as part of the Julia stdlib. SparseArrays.jl provides functionality for working with sparse arrays in Julia. -## Using development versions of this package - -To use a newer version of this package, you need to build Julia from scratch. The build process is the same as any other build except that you need to change the commit used in `stdlib/SparseArrays.version`. - -It's also possible to load a development version of the package using [the trick used in the Section named "Using the development version of Pkg.jl" in the `Pkg.jl` repo](https://github.com/JuliaLang/Pkg.jl#using-the-development-version-of-pkgjl), but the capabilities are limited as all other packages will depend on the stdlib version of the package and will not work with the modified package. - -The main environment may become inconsistent so you might need to run `Pkg.instantiate()` and/or `Pkg.resolve()` in the main or project environments if Julia complains about missing `Serialization.jl` in this package's dependencies. - -For older (1.8 and before) `SuiteSparse.jl` needs to be bumped too. - ## Updating SuiteSparse In order to upgrade SparseArrays.jl to use a new release of SuiteSparse, the following steps are necessary: From 268d3906e21d69ffd67429f5c052732749e7a2b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=C2=A0Tarasiuk?= <158573010+pawel-tarasiuk-quantumz@users.noreply.github.com> Date: Tue, 26 Nov 2024 20:20:26 +0100 Subject: [PATCH 08/11] QR: handle xtype/dtype returned from LibSuiteSparse that don't match matrix element type (#586) * QR: handle xtype/dtype other than input Tv * Set types by SparseMatrixCSC{Tv, Ti} when possible * One less forced copy --------- Co-authored-by: Viral B. Shah --- src/solvers/cholmod.jl | 9 +++++++++ src/solvers/spqr.jl | 8 ++++---- test/spqr.jl | 6 ++++++ 3 files changed, 19 insertions(+), 4 deletions(-) diff --git a/src/solvers/cholmod.jl b/src/solvers/cholmod.jl index 51688ce5..2770bf48 100644 --- a/src/solvers/cholmod.jl +++ b/src/solvers/cholmod.jl @@ -901,6 +901,15 @@ Dense(A::StridedVecOrMatInclAdjAndTrans{T}) where Dense(A::Sparse) = sparse_to_dense(A) +function Dense(ptr::Ptr{cholmod_dense}) + if ptr == C_NULL + throw(ArgumentError("dense matrix construction failed for " * + "unknown reasons. Please submit a bug report.")) + end + s = unsafe_load(ptr) + return Dense{jlxtype(s.xtype, s.dtype)}(ptr) +end + function Base.convert(::Type{Dense{Tnew}}, A::Dense{T}) where {Tnew, T} GC.@preserve A begin Ap = unsafe_load(pointer(A)) diff --git a/src/solvers/spqr.jl b/src/solvers/spqr.jl index 5f409463..cd1bdf6a 100644 --- a/src/solvers/spqr.jl +++ b/src/solvers/spqr.jl @@ -204,10 +204,10 @@ function LinearAlgebra.qr(A::SparseMatrixCSC{Tv, Ti}; tol=_default_tol(A), order C_NULL, C_NULL, C_NULL, C_NULL, R, E, H, HPinv, HTau) - R_ = SparseMatrixCSC(Sparse(R[])) - return QRSparse(SparseMatrixCSC(Sparse(H[])), - vec(Array(CHOLMOD.Dense{Tv}(HTau[]))), - SparseMatrixCSC(min(size(A)...), + R_ = SparseMatrixCSC{Tv, Ti}(Sparse(R[])) + return QRSparse(SparseMatrixCSC{Tv, Ti}(Sparse(H[])), + vec(Array{Tv}(CHOLMOD.Dense(HTau[]))), + SparseMatrixCSC{Tv, Ti}(min(size(A)...), size(R_, 2), getcolptr(R_), rowvals(R_), diff --git a/test/spqr.jl b/test/spqr.jl index 122741ce..285f3dc9 100644 --- a/test/spqr.jl +++ b/test/spqr.jl @@ -110,6 +110,12 @@ end @test (F.Q*F.R)::SparseMatrixCSC == A[F.prow,F.pcol] end +@testset "Issue #585 for element type: $eltyA" for eltyA in (Float64, Float32) + A = sparse(eltyA[1 0; 0 1]) + F = qr(A) + @test eltype(F.Q) == eltype(F.R) == eltyA +end + @testset "select ordering overdetermined" begin A = sparse([1:n; rand(1:m, nn - n)], [1:n; rand(1:n, nn - n)], randn(nn), m, n) b = randn(m) From 1beb0e4a4618b0399907b0000c43d9f66d34accc Mon Sep 17 00:00:00 2001 From: "Viral B. Shah" Date: Wed, 27 Nov 2024 11:00:26 -0500 Subject: [PATCH 09/11] Update LICENSE.md (#587) --- LICENSE.md | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/LICENSE.md b/LICENSE.md index b2543900..fdb1fe21 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -1,3 +1,22 @@ -The code in this repository is part of the Julia project. See the LICENSE file in the Julia project: +MIT License -https://github.com/JuliaLang/julia/blob/master/LICENSE.md +Copyright (c) 2018-2024 SparseArrays.jl contributors: +https://github.com/JuliaSparse/SparseArrays.jl/contributors + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. From 780c4de142aec4de051087864a5c2497fc647d8f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 1 Dec 2024 18:56:21 -0500 Subject: [PATCH 10/11] Bump codecov/codecov-action from 4 to 5 (#589) Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from 4 to 5. - [Release notes](https://github.com/codecov/codecov-action/releases) - [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/codecov/codecov-action/compare/v4...v5) --- updated-dependencies: - dependency-name: codecov/codecov-action dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7a6ff08c..77689df4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -43,7 +43,7 @@ jobs: - uses: julia-actions/julia-buildpkg@v1 - uses: julia-actions/julia-runtest@v1 - uses: julia-actions/julia-processcoverage@v1 - - uses: codecov/codecov-action@v4 + - uses: codecov/codecov-action@v5 with: file: lcov.info token: ${{ secrets.CODECOV_TOKEN }} From 4fd3aad5735e3b80eefe7b068f3407d7dd0c0924 Mon Sep 17 00:00:00 2001 From: Jishnu Bhattacharya Date: Thu, 5 Dec 2024 13:39:20 +0530 Subject: [PATCH 11/11] Generalize `istriu`/`istril` to accept a band index (#590) Currently, only `istriu(S)` and `istril(S)` are specialized for sparse matrices, and this PR generalizes these to accept the band index `k`. This improves performance. --- src/sparsematrix.jl | 10 ++++++---- test/sparsematrix_ops.jl | 13 +++++++++++++ 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/src/sparsematrix.jl b/src/sparsematrix.jl index 4fa2adf9..6d6d880d 100644 --- a/src/sparsematrix.jl +++ b/src/sparsematrix.jl @@ -4141,7 +4141,7 @@ function is_hermsym(A::AbstractSparseMatrixCSC, check::Function) return true end -function istriu(A::AbstractSparseMatrixCSC) +function istriu(A::AbstractSparseMatrixCSC, k::Integer=0) m, n = size(A) colptr = getcolptr(A) rowval = rowvals(A) @@ -4150,7 +4150,8 @@ function istriu(A::AbstractSparseMatrixCSC) for col = 1:min(n, m-1) l1 = colptr[col+1]-1 for i = 0 : (l1 - colptr[col]) - if rowval[l1-i] <= col + if rowval[l1-i] <= col - k + # rows preceeding the index would also lie above the band break end if _isnotzero(nzval[l1-i]) @@ -4161,7 +4162,7 @@ function istriu(A::AbstractSparseMatrixCSC) return true end -function istril(A::AbstractSparseMatrixCSC) +function istril(A::AbstractSparseMatrixCSC, k::Integer=0) m, n = size(A) colptr = getcolptr(A) rowval = rowvals(A) @@ -4169,7 +4170,8 @@ function istril(A::AbstractSparseMatrixCSC) for col = 2:n for i = colptr[col] : (colptr[col+1]-1) - if rowval[i] >= col + if rowval[i] >= col - k + # subsequent rows would also lie below the band break end if _isnotzero(nzval[i]) diff --git a/test/sparsematrix_ops.jl b/test/sparsematrix_ops.jl index 94e268e0..d99418a8 100644 --- a/test/sparsematrix_ops.jl +++ b/test/sparsematrix_ops.jl @@ -626,4 +626,17 @@ end @test_throws ArgumentError copytrito!(M, S, 'M') end +@testset "istriu/istril" begin + for T in Any[Tridiagonal(1:3, 1:4, 1:3), + Bidiagonal(1:4, 1:3, :U), Bidiagonal(1:4, 1:3, :L), + Diagonal(1:4), + diagm(-2=>1:2, 2=>1:2)] + S = sparse(T) + for k in -5:5 + @test istriu(S, k) == istriu(T, k) + @test istril(S, k) == istril(T, k) + end + end +end + end # module