From b9792f1bf41ca78b908491a969e2994e2a150d50 Mon Sep 17 00:00:00 2001 From: GiggleLiu Date: Mon, 16 Jun 2025 20:48:46 +0800 Subject: [PATCH] Aqua pass, tests fixed --- Project.toml | 10 ++++++++-- src/IMatrix.jl | 4 ++-- src/LuxurySparse.jl | 2 +- src/PermMatrix.jl | 6 +++--- src/broadcast.jl | 24 ++++++++++++------------ src/iterate.jl | 2 +- src/kronecker.jl | 13 ++++++------- src/linalg.jl | 35 +++++++++++++++++++++-------------- src/promotions.jl | 4 ++-- src/staticize.jl | 11 +---------- src/utils.jl | 5 +---- test/IMatrix.jl | 3 +-- test/PermMatrix.jl | 4 ++-- test/PermMatrixCSC.jl | 4 ++-- test/broadcast.jl | 2 +- test/kronecker.jl | 10 +++++----- test/linalg.jl | 14 +++++++++++--- test/runtests.jl | 6 +++++- 18 files changed, 85 insertions(+), 74 deletions(-) diff --git a/Project.toml b/Project.toml index d29d3be..bd22cbb 100644 --- a/Project.toml +++ b/Project.toml @@ -10,11 +10,17 @@ SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf" StaticArrays = "90137ffa-7385-5640-81b9-e52037218182" [compat] +Aqua = "0.8" +LinearAlgebra = "1" +Random = "1" +SparseArrays = "1" StaticArrays = "1" -julia = "1" +Test = "1" +julia = "1.10" [extras] Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" +Aqua = "4c88cf16-eb10-579e-8560-4a9242c79595" [targets] -test = ["Test"] +test = ["Test", "Aqua"] diff --git a/src/IMatrix.jl b/src/IMatrix.jl index 7325fc8..64d6ded 100644 --- a/src/IMatrix.jl +++ b/src/IMatrix.jl @@ -47,5 +47,5 @@ end LinearAlgebra.ishermitian(D::IMatrix) = true ####### sparse matrix ###### -nnz(M::IMatrix) = M.n -findnz(M::IMatrix{T}) where {T} = (collect(1:M.n), collect(1:M.n), ones(T, M.n)) +SparseArrays.nnz(M::IMatrix) = M.n +SparseArrays.findnz(M::IMatrix{T}) where {T} = (collect(1:M.n), collect(1:M.n), ones(T, M.n)) diff --git a/src/LuxurySparse.jl b/src/LuxurySparse.jl index d4afcf3..266de74 100644 --- a/src/LuxurySparse.jl +++ b/src/LuxurySparse.jl @@ -6,7 +6,7 @@ using SparseArrays: SparseMatrixCSC using SparseArrays.HigherOrderFns using Base: @propagate_inbounds using LinearAlgebra -import SparseArrays: findnz, nnz +import LinearAlgebra: Diagonal using LinearAlgebra: StructuredMatrixStyle using Base.Broadcast: BroadcastStyle, AbstractArrayStyle, Broadcasted, DefaultArrayStyle, materialize! diff --git a/src/PermMatrix.jl b/src/PermMatrix.jl index 732a13b..aec9755 100644 --- a/src/PermMatrix.jl +++ b/src/PermMatrix.jl @@ -162,6 +162,6 @@ end Base.hash(pm::AbstractPermMatrix) = hash((pm.perm, pm.vals)) ######### sparse array interfaces ######### -nnz(M::AbstractPermMatrix) = length(M.vals) -findnz(M::PermMatrix) = (collect(1:size(M, 1)), M.perm, M.vals) -findnz(M::PermMatrixCSC) = (M.perm, collect(1:size(M, 1)), M.vals) +SparseArrays.nnz(M::AbstractPermMatrix) = length(M.vals) +SparseArrays.findnz(M::PermMatrix) = (collect(1:size(M, 1)), M.perm, M.vals) +SparseArrays.findnz(M::PermMatrixCSC) = (M.perm, collect(1:size(M, 1)), M.vals) diff --git a/src/broadcast.jl b/src/broadcast.jl index faccf73..05ff0b2 100644 --- a/src/broadcast.jl +++ b/src/broadcast.jl @@ -76,19 +76,19 @@ Broadcast.broadcasted(::AbstractArrayStyle{2}, ::typeof(*), A::Diagonal, B::Abst # TODO: commit this upstream # specialize Diagonal .* SparseMatrixCSC -Broadcast.broadcasted( - ::AbstractArrayStyle{2}, - ::typeof(*), - A::Diagonal, - B::SparseMatrixCSC, -) = Broadcast.broadcasted(*, A, Diagonal(B)) +# Broadcast.broadcasted( +# ::AbstractArrayStyle{2}, +# ::typeof(*), +# A::Diagonal, +# B::SparseMatrixCSC, +# ) = Broadcast.broadcasted(*, A, Diagonal(B)) -Broadcast.broadcasted( - ::AbstractArrayStyle{2}, - ::typeof(*), - A::SparseMatrixCSC, - B::Diagonal, -) = Broadcast.broadcasted(*, Diagonal(A), B) +# Broadcast.broadcasted( +# ::AbstractArrayStyle{2}, +# ::typeof(*), +# A::SparseMatrixCSC, +# B::Diagonal, +# ) = Broadcast.broadcasted(*, Diagonal(A), B) Broadcast.broadcasted( ::AbstractArrayStyle{2}, diff --git a/src/iterate.jl b/src/iterate.jl index d2d61ca..0dab589 100644 --- a/src/iterate.jl +++ b/src/iterate.jl @@ -3,7 +3,7 @@ struct IterNz{MT} end Base.length(nz::IterNz{<:AbstractMatrix}) = length(nz.A) -Base.length(nz::IterNz{<:AbstractSparseMatrix}) = nnz(nz.A) +Base.length(nz::IterNz{<:AbstractSparseMatrix}) = SparseArrays.nnz(nz.A) Base.length(nz::IterNz{<:Adjoint}) = length(IterNz(nz.A.parent)) Base.length(nz::IterNz{<:Transpose}) = length(IterNz(nz.A.parent)) Base.length(nz::IterNz{<:Diagonal}) = size(nz.A, 1) diff --git a/src/kronecker.jl b/src/kronecker.jl index eb2b608..10a20b1 100644 --- a/src/kronecker.jl +++ b/src/kronecker.jl @@ -24,19 +24,18 @@ function orepeat(v::AbstractVector, n::Int) end -# TODO: since 0.7 transpose is different, we don't take transpose serious here. ####### kronecker product ########### +fastkron(a, b) = kron(a, b) +fastkron(A::Diagonal{<:Number}, B::SparseMatrixCSC{<:Number}) = kron(PermMatrixCSC(A), B) +fastkron(A::SparseMatrixCSC{<:Number}, B::Diagonal{<:Number}) = kron(A, PermMatrixCSC(B)) +fastkron(A::Diagonal{<:Number}, B::StridedMatrix{<:Number}) = kron(PermMatrixCSC(A), B) +fastkron(A::StridedMatrix{<:Number}, B::Diagonal{<:Number}) = kron(A, PermMatrixCSC(B)) + LinearAlgebra.kron(A::IMatrix{Ta}, B::IMatrix{Tb}) where {Ta<:Number,Tb<:Number} = IMatrix{promote_type(Ta, Tb)}(A.n * B.n) LinearAlgebra.kron(A::IMatrix{<:Number}, B::Diagonal{<:Number}) = A.n == 1 ? B : Diagonal(orepeat(B.diag, A.n)) LinearAlgebra.kron(B::Diagonal{<:Number}, A::IMatrix) = A.n == 1 ? B : Diagonal(irepeat(B.diag, A.n)) -####### diagonal kron ######## -LinearAlgebra.kron(A::StridedMatrix{<:Number}, B::Diagonal{<:Number}) = kron(A, PermMatrixCSC(B)) -LinearAlgebra.kron(A::Diagonal{<:Number}, B::StridedMatrix{<:Number}) = kron(PermMatrixCSC(A), B) -LinearAlgebra.kron(A::Diagonal{<:Number}, B::SparseMatrixCSC{<:Number}) = kron(PermMatrixCSC(A), B) -LinearAlgebra.kron(A::SparseMatrixCSC{<:Number}, B::Diagonal{<:Number}) = kron(A, PermMatrixCSC(B)) - function LinearAlgebra.kron(A::AbstractMatrix{Tv}, B::IMatrix) where {Tv<:Number} B.n == 1 && return A mA, nA = size(A) diff --git a/src/linalg.jl b/src/linalg.jl index cf696cb..912c7dc 100644 --- a/src/linalg.jl +++ b/src/linalg.jl @@ -108,6 +108,14 @@ function LinearAlgebra.mul!(C::AbstractMatrix, X::AbstractMatrix, A::AbstractPer AC = PermMatrixCSC(A) C .= C .* beta .+ reshape(AC.vals, 1, :) .* view(X, :, AC.perm) .* alpha end +function LinearAlgebra.mul!(C::AbstractMatrix, A::AbstractPermMatrix, B::AbstractPermMatrix, alpha::Number, beta::Number) + size(C, 1) == size(C, 2) == size(A, 1) == size(B, 1) || throw(DimensionMismatch()) + res = A * B + for (i, j, v) in IterNz(res) + C[i, j] = v * alpha + beta * C[i, j] + end + return C +end # NOTE: this is just a temperory fix for v0.7. We should overload mul! in # the future (when we start to drop v0.6) to enable buildin lazy evaluation. @@ -187,19 +195,18 @@ Base.:/(A::SparseMatrixCOO, B::Int) = rdiv!(copy(A), B) Base.:-(ii::IMatrix) = (-1) * ii Base.:-(pm::AbstractPermMatrix) = (-1) * pm -for FUNC in [:randn!, :rand!] - @eval function Random.$FUNC(m::Diagonal) - $FUNC(m.diag) - return m - end - - @eval function Random.$FUNC(m::SparseMatrixCSC) - $FUNC(m.nzval) - return m - end +randomize!(m::AbstractArray) = randn!(m) +function randomize!(m::Diagonal) + randomize!(m.diag) + return m +end - @eval function Random.$FUNC(m::AbstractPermMatrix) - $FUNC(m.vals) - return m - end +function randomize!(m::SparseMatrixCSC) + randomize!(m.nzval) + return m end + +function randomize!(m::AbstractPermMatrix) + randomize!(m.vals) + return m +end \ No newline at end of file diff --git a/src/promotions.jl b/src/promotions.jl index b6bf658..4889552 100644 --- a/src/promotions.jl +++ b/src/promotions.jl @@ -1,6 +1,6 @@ # SparseMatrixCSC -Base.promote_rule(::Type{SparseMatrixCSC{Tv,Ti}}, ::Type{Matrix{T}}) where {Tv,Ti,T} = - Matrix{promote_type(T, Tv)} +#Base.promote_rule(::Type{SparseMatrixCSC{Tv,Ti}}, ::Type{Matrix{T}}) where {Tv,Ti,T} = +# Matrix{promote_type(T, Tv)} # IMatrix for MT in [:PermMatrix, :PermMatrixCSC] diff --git a/src/staticize.jl b/src/staticize.jl index fdfce58..944237a 100644 --- a/src/staticize.jl +++ b/src/staticize.jl @@ -55,13 +55,4 @@ dynamicize(A::PermMatrix) = PermMatrix(Vector(A.perm), Vector(A.vals)) dynamicize(A::PermMatrixCSC) = PermMatrixCSC(Vector(A.perm), Vector(A.vals)) function dynamicize(A::SSparseMatrixCSC) SparseMatrixCSC(A.m, A.n, Vector(A.colptr), Vector(A.rowval), Vector(A.nzval)) -end - -function findnz(M::SDMatrix) - cis = CartesianIndices(size(M)) - vec(getindex.(cis, 1)), vec(getindex.(cis, 2)), vec(M) -end -nnz(M::SDMatrix) = length(M) - -findnz(sp::AbstractSparseMatrix) = SparseArrays.findnz(sp) -nnz(M::AbstractSparseMatrix) = SparseArrays.nnz(M) +end \ No newline at end of file diff --git a/src/utils.jl b/src/utils.jl index 38f79d0..f60c2fe 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -4,7 +4,4 @@ function fast_invperm(order) v[order[i]] = i end v -end - -findnz(M::Diagonal) = (collect(1:size(M, 1)), collect(1:size(M, 1)), M.diag) -nnz(M::Diagonal) = length(M.diag) +end \ No newline at end of file diff --git a/test/IMatrix.jl b/test/IMatrix.jl index 67284f8..a516aad 100644 --- a/test/IMatrix.jl +++ b/test/IMatrix.jl @@ -41,8 +41,7 @@ end @testset "sparse" begin @show p1 - @test LuxurySparse.nnz(p1) == 4 - @test length(LuxurySparse.findnz(p1)[3]) == 4 + @test LuxurySparse.length(IterNz(p1)) == 4 end @testset "linalg" begin diff --git a/test/PermMatrix.jl b/test/PermMatrix.jl index c43afcd..fc66af7 100644 --- a/test/PermMatrix.jl +++ b/test/PermMatrix.jl @@ -88,8 +88,8 @@ end @testset "identity sparse" begin p1 = Diagonal(randn(10)) - @test LuxurySparse.nnz(p1) == 10 - @test LuxurySparse.findnz(p1)[3] == p1.diag + @test length(LuxurySparse.IterNz(p1)) == 10 + @test map(x -> x[3], LuxurySparse.IterNz(p1)) == p1.diag end @testset "setindex" begin diff --git a/test/PermMatrixCSC.jl b/test/PermMatrixCSC.jl index 0ad045b..69ddf64 100644 --- a/test/PermMatrixCSC.jl +++ b/test/PermMatrixCSC.jl @@ -90,8 +90,8 @@ end @testset "identity sparse" begin p1 = Diagonal(randn(10)) - @test LuxurySparse.nnz(p1) == 10 - @test LuxurySparse.findnz(p1)[3] == p1.diag + @test length(LuxurySparse.IterNz(p1)) == 10 + @test map(x -> x[3], LuxurySparse.IterNz(p1)) == p1.diag end @testset "setindex" begin diff --git a/test/broadcast.jl b/test/broadcast.jl index 4879b70..f152fc0 100644 --- a/test/broadcast.jl +++ b/test/broadcast.jl @@ -60,7 +60,7 @@ using SparseArrays d = Diagonal(rand(3)) sp = sprand(3, 3, 0.5) @test d .* sp ≈ Matrix(d) .* Matrix(sp) - @test typeof(d .* sp) <: Diagonal + @test_broken typeof(d .* sp) <: Diagonal @testset "Number .* $(nameof(typeof(M)))" for M in Any[pmrand(3), Diagonal(randn(3))] @test 3.0 .* M ≈ 3.0 .* Matrix(M) && M .* 3.0 ≈ Matrix(M) .* 3.0 diff --git a/test/kronecker.jl b/test/kronecker.jl index 9df3c20..2732a05 100644 --- a/test/kronecker.jl +++ b/test/kronecker.jl @@ -1,5 +1,5 @@ using Test, Random, SparseArrays, LinearAlgebra -import LuxurySparse: IMatrix, PermMatrix, PermMatrixCSC, basetype, AbstractPermMatrix +import LuxurySparse: IMatrix, PermMatrix, PermMatrixCSC, basetype, AbstractPermMatrix, fastkron @testset "kron" begin Random.seed!(2) @@ -17,10 +17,10 @@ import LuxurySparse: IMatrix, PermMatrix, PermMatrixCSC, basetype, AbstractPermM if source isa AbstractPermMatrix && target isa AbstractPermMatrix && basetype(source) != basetype(target) continue end - lres = kron(source, target) - rres = kron(target, source) - flres = kron(Matrix(source), Matrix(target)) - frres = kron(Matrix(target), Matrix(source)) + lres = fastkron(source, target) + rres = fastkron(target, source) + flres = fastkron(Matrix(source), Matrix(target)) + frres = fastkron(Matrix(target), Matrix(source)) @test lres == flres @test rres == frres @test eltype(lres) == eltype(flres) diff --git a/test/linalg.jl b/test/linalg.jl index a00332d..ebd91d0 100644 --- a/test/linalg.jl +++ b/test/linalg.jl @@ -92,10 +92,10 @@ end for m in Any[pmrand(T, 5), Diagonal(randn(T, 5))] zm = zero(m) @test zm ≈ zeros(T, 5, 5) - rand!(zm) + LuxurySparse.randomize!(zm) @test !(zm ≈ zeros(T, 5, 5)) zm = zero(m) - randn!(zm) + LuxurySparse.randomize!(zm) @test !(zm ≈ zeros(T, 5, 5)) end end @@ -111,7 +111,7 @@ end for m in Any[p1, sp, ds, dv, pm] for _m in Any[m, staticize(m)] out = zeros(eltype(m), size(m)...) - for (i, j, v) in zip(LuxurySparse.findnz(_m)...) + for (i, j, v) in LuxurySparse.IterNz(_m) out[i, j] = v end @test out ≈ m @@ -129,4 +129,12 @@ end pop = sparse([2, 3], [4, 5], [1, √2], 5, 5) zop = Diagonal([0, 1 / 2, 1, -1 / 2, 0]) @test (pop*zop)[2, 4] == -0.5 +end + +@testset "extra" begin + out = zeros(ComplexF64, 4, 4) + a = pmrand(4) + b = pmrand(4) + mul!(out, a, b, 1, 0) + @test out ≈ Matrix(a) * Matrix(b) end \ No newline at end of file diff --git a/test/runtests.jl b/test/runtests.jl index 17fca67..3fd1852 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -1,7 +1,11 @@ using Test -using LinearAlgebra, SparseArrays +using Aqua using LuxurySparse +@testset "Aqua" begin + Aqua.test_all(LuxurySparse) +end + @testset "IMatrix" begin include("IMatrix.jl") end