From be66023e2e7111d02063a7e2a30aa7811e4490d3 Mon Sep 17 00:00:00 2001 From: Tamme Claus Date: Sat, 28 Jun 2025 00:23:15 +0200 Subject: [PATCH 1/5] fix + tests --- lib/cusparse/linalg.jl | 10 ++++++---- test/libraries/cusparse/linalg.jl | 8 ++++++++ 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/lib/cusparse/linalg.jl b/lib/cusparse/linalg.jl index 4be578e284..a5fe6095eb 100644 --- a/lib/cusparse/linalg.jl +++ b/lib/cusparse/linalg.jl @@ -82,7 +82,7 @@ function LinearAlgebra.kron(A::CuSparseMatrixCOO{T, Ti}, B::CuSparseMatrixCOO{T, sparse(row, col, data, out_shape..., fmt = :coo) end -function LinearAlgebra.kron(A::CuSparseMatrixCOO{T, Ti}, B::Diagonal) where {Ti, T} +function LinearAlgebra.kron(A::CuSparseMatrixCOO{T, Ti}, B::Diagonal{TB}) where {Ti, T, TB} mA,nA = size(A) mB,nB = size(B) out_shape = (mA * mB, nA * nB) @@ -102,12 +102,13 @@ function LinearAlgebra.kron(A::CuSparseMatrixCOO{T, Ti}, B::Diagonal) where {Ti, row .+= CuVector(repeat(0:nB-1, outer = Annz)) .+ 1 col .+= CuVector(repeat(0:nB-1, outer = Annz)) .+ 1 - data .*= repeat(CUDA.ones(T, nB), outer = Annz) + Bdiag = (TB == Bool) ? CUDA.ones(T, nB) : B.diag + data .*= repeat(Bdiag, outer = Annz) sparse(row, col, data, out_shape..., fmt = :coo) end -function LinearAlgebra.kron(A::Diagonal, B::CuSparseMatrixCOO{T, Ti}) where {Ti, T} +function LinearAlgebra.kron(A::Diagonal{TA}, B::CuSparseMatrixCOO{T, Ti}) where {Ti, T, TA} mA,nA = size(A) mB,nB = size(B) out_shape = (mA * mB, nA * nB) @@ -122,7 +123,8 @@ function LinearAlgebra.kron(A::Diagonal, B::CuSparseMatrixCOO{T, Ti}) where {Ti, row = CuVector(repeat(row, inner = Bnnz)) col = (0:nA-1) .* nB col = CuVector(repeat(col, inner = Bnnz)) - data = repeat(CUDA.ones(T, nA), inner = Bnnz) + Adiag = (TA == Bool) ? CUDA.ones(T, nA) : A.diag + data = repeat(Adiag, inner = Bnnz) row .+= repeat(B.rowInd .- 1, outer = Annz) .+ 1 col .+= repeat(B.colInd .- 1, outer = Annz) .+ 1 diff --git a/test/libraries/cusparse/linalg.jl b/test/libraries/cusparse/linalg.jl index 1f865e558c..4fa5481fc0 100644 --- a/test/libraries/cusparse/linalg.jl +++ b/test/libraries/cusparse/linalg.jl @@ -7,10 +7,12 @@ m = 10 B = sprand(T, m, m, 0.3) ZA = spzeros(T, m, m) C = I(div(m, 2)) + D = Diagonal(rand(T, m)) @testset "type = $typ" for typ in [CuSparseMatrixCSR, CuSparseMatrixCSC] dA = typ(A) dB = typ(B) dZA = typ(ZA) + dD = Diagonal(CuArray(D.diag)) @testset "opnorm and norm" begin @test opnorm(A, Inf) ≈ opnorm(dA, Inf) @test opnorm(A, 1) ≈ opnorm(dA, 1) @@ -42,6 +44,12 @@ m = 10 @test collect(kron(opa(dZA), C)) ≈ kron(opa(ZA), C) @test collect(kron(C, opa(dZA))) ≈ kron(C, opa(ZA)) end + @testset "kronecker product with Diagonal opa = $opa" for opa in (identity, transpose, adjoint) + @test collect(kron(opa(dA), dD)) ≈ kron(opa(A), D) + @test collect(kron(dD, opa(dA))) ≈ kron(D, opa(A)) + @test collect(kron(opa(dZA), dD)) ≈ kron(opa(ZA), D) + @test collect(kron(dD, opa(dZA))) ≈ kron(D, opa(ZA)) + end end end From 58123fa1cd95446eb6c600b95848fe63af19fd2e Mon Sep 17 00:00:00 2001 From: Tamme Claus Date: Mon, 30 Jun 2025 10:00:09 +0200 Subject: [PATCH 2/5] use adapt(..) --- test/libraries/cusparse/linalg.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/libraries/cusparse/linalg.jl b/test/libraries/cusparse/linalg.jl index 4fa5481fc0..dd609f1ee8 100644 --- a/test/libraries/cusparse/linalg.jl +++ b/test/libraries/cusparse/linalg.jl @@ -12,7 +12,7 @@ m = 10 dA = typ(A) dB = typ(B) dZA = typ(ZA) - dD = Diagonal(CuArray(D.diag)) + dD = adapt(CuArray, D) @testset "opnorm and norm" begin @test opnorm(A, Inf) ≈ opnorm(dA, Inf) @test opnorm(A, 1) ≈ opnorm(dA, 1) From 5e514229607e46e944ec8f055aa36d6e1428beb3 Mon Sep 17 00:00:00 2001 From: Tamme Claus Date: Mon, 14 Jul 2025 18:11:01 +0200 Subject: [PATCH 3/5] support adjoint(::Diagonal{<:CuVector{<:Complex}}) (e.g. mul! resulted in scalar-indexing) + test --- lib/cublas/linalg.jl | 2 ++ test/libraries/cublas/extensions.jl | 12 ++++++++++++ 2 files changed, 14 insertions(+) diff --git a/lib/cublas/linalg.jl b/lib/cublas/linalg.jl index 193b7c92dc..ce9acea787 100644 --- a/lib/cublas/linalg.jl +++ b/lib/cublas/linalg.jl @@ -339,6 +339,8 @@ function LinearAlgebra.inv(D::Diagonal{T, <:CuArray{T}}) where {T} Diagonal(Di) end +LinearAlgebra.adjoint(D::Diagonal{T, <:CuVector{T}}) where T <: Complex = Diagonal(map(adjoint, D.diag)) + LinearAlgebra.rdiv!(A::CuArray, D::Diagonal) = _rdiv!(A, A, D) Base.:/(A::CuArray, D::Diagonal) = _rdiv!(similar(A, typeof(oneunit(eltype(A)) / oneunit(eltype(D)))), A, D) diff --git a/test/libraries/cublas/extensions.jl b/test/libraries/cublas/extensions.jl index 7c34048672..027b9678e4 100644 --- a/test/libraries/cublas/extensions.jl +++ b/test/libraries/cublas/extensions.jl @@ -538,11 +538,23 @@ k = 13 mul!(d_XA, d_X, d_A) Array(d_XA) ≈ Diagonal(x) * A + XA = rand(elty,m,n) + d_XA = CuArray(XA) + d_X = Diagonal(d_x) + mul!(d_XA, d_X', d_A) + Array(d_XA) ≈ Diagonal(x)' * A + AY = rand(elty,m,n) d_AY = CuArray(AY) d_Y = Diagonal(d_y) mul!(d_AY, d_A, d_Y) Array(d_AY) ≈ A * Diagonal(y) + + AY = rand(elty,m,n) + d_AY = CuArray(AY) + d_Y = Diagonal(d_y) + mul!(d_AY, d_A, d_Y') + Array(d_AY) ≈ A * Diagonal(y)' YA = rand(elty,n,m) d_YA = CuArray(YA) From c12cd914cfb4ae025d4aa8e6a0872b24efc944eb Mon Sep 17 00:00:00 2001 From: Tamme Claus Date: Mon, 14 Jul 2025 18:17:05 +0200 Subject: [PATCH 4/5] Implement kron for {Adjoint, Transpose}(CuSparseMatrixCOO) and Diagonal + tests --- lib/cusparse/linalg.jl | 126 ++++++++++++++++-------------- test/libraries/cusparse/linalg.jl | 39 ++++++++- 2 files changed, 104 insertions(+), 61 deletions(-) diff --git a/lib/cusparse/linalg.jl b/lib/cusparse/linalg.jl index a5fe6095eb..803cfeed83 100644 --- a/lib/cusparse/linalg.jl +++ b/lib/cusparse/linalg.jl @@ -57,81 +57,87 @@ function Base.reshape(A::CuSparseMatrixCOO, dims::Dims) sparse(new_row, new_col, A.nzVal, dims[1], length(dims) == 1 ? 1 : dims[2], fmt = :coo) end -function LinearAlgebra.kron(A::CuSparseMatrixCOO{T, Ti}, B::CuSparseMatrixCOO{T, Ti}) where {Ti, T} - mA,nA = size(A) - mB,nB = size(B) - out_shape = (mA * mB, nA * nB) - Annz = Int64(A.nnz) - Bnnz = Int64(B.nnz) - - if Annz == 0 || Bnnz == 0 - return CuSparseMatrixCOO(CuVector{Ti}(undef, 0), CuVector{Ti}(undef, 0), CuVector{T}(undef, 0), out_shape) +# deprecate? CUSPARSE should not do this internally. +LinearAlgebra.kron(A::Union{CuSparseMatrixCOO{TvA, TiA}, Transpose{TvA, <:CuSparseMatrixCOO{TvA, TiA}}, Adjoint{TvA, <:CuSparseMatrixCOO{TvA, TiA}}}, B::Diagonal{TvB, <:Vector{TvB}}) where {TvA, TiA, TvB} = kron(A, adapt(CuArray, B)) +LinearAlgebra.kron(A::Diagonal{TvA, <:Vector{TvA}}, B::Union{CuSparseMatrixCOO{TvB, TiB}, Transpose{TvB, <:CuSparseMatrixCOO{TvB, TiB}}, Adjoint{TvB, <:CuSparseMatrixCOO{TvB, TiB}}}) where {TvA, TvB, TiB} = kron(adapt(CuArray, A), B) + +_kron_CuSparseMatrixCOO_components(A::CuSparseMatrixCOO) = A.rowInd, A.colInd, A.nzVal, identity, Int(A.nnz) +_kron_CuSparseMatrixCOO_components(At::Transpose{<:Number, <:CuSparseMatrixCOO}) = parent(At).colInd, parent(At).rowInd, parent(At).nzVal, transpose, Int(parent(At).nnz) +_kron_CuSparseMatrixCOO_components(Ah::Adjoint{<:Number, <:CuSparseMatrixCOO}) = parent(Ah).colInd, parent(Ah).rowInd, parent(Ah).nzVal, adjoint, Int(parent(Ah).nnz) + +function LinearAlgebra.kron( + A::Union{CuSparseMatrixCOO{TvA, TiA}, Transpose{TvA, <:CuSparseMatrixCOO{TvA, TiA}}, Adjoint{TvA, <:CuSparseMatrixCOO{TvA, TiA}}}, + B::Union{CuSparseMatrixCOO{TvB, TiB}, Transpose{TvB, <:CuSparseMatrixCOO{TvB, TiB}}, Adjoint{TvB, <:CuSparseMatrixCOO{TvB, TiB}}} + ) where {TvA, TiA, TvB, TiB} + mA, nA = size(A) + mB, nB = size(B) + Ti = promote_type(TiA, TiB) + Tv = typeof(oneunit(TvA)*oneunit(TvB)) + + A_rowInd, A_colInd, A_nzVal, A_nzOp, A_nnz = _kron_CuSparseMatrixCOO_components(A) + B_rowInd, B_colInd, B_nzVal, B_nzOp, B_nnz = _kron_CuSparseMatrixCOO_components(B) + + if A_nnz == 0 || B_nnz == 0 + return CuSparseMatrixCOO{Tv, Ti}(CuVector{Ti}(undef, 0), CuVector{Ti}(undef, 0), CuVector{Tv}(undef, 0), (mA * mB, nA * nB)) end - row = (A.rowInd .- 1) .* mB - row = repeat(row, inner = Bnnz) - col = (A.colInd .- 1) .* nB - col = repeat(col, inner = Bnnz) - data = repeat(A.nzVal, inner = Bnnz) + C_nnz = A_nnz * B_nnz + C_rowInd = reshape(B_rowInd .+ Ti(mB) .* (reshape(A_rowInd, (1, A_nnz)) .- one(Ti)), C_nnz) + C_colInd = reshape(B_colInd .+ Ti(nB) .* (reshape(A_colInd, (1, A_nnz)) .- one(Ti)), C_nnz) + C_nzVal = reshape(B_nzOp.(B_nzVal) .* A_nzOp.(reshape(A_nzVal, (1, A_nnz))), C_nnz) - row .+= repeat(B.rowInd .- 1, outer = Annz) .+ 1 - col .+= repeat(B.colInd .- 1, outer = Annz) .+ 1 - - data .*= repeat(B.nzVal, outer = Annz) - - sparse(row, col, data, out_shape..., fmt = :coo) + C = CuSparseMatrixCOO{Tv, Ti}(C_rowInd, C_colInd, C_nzVal, (mA * mB, nA * nB), C_nnz) + return sort_coo(C) end -function LinearAlgebra.kron(A::CuSparseMatrixCOO{T, Ti}, B::Diagonal{TB}) where {Ti, T, TB} - mA,nA = size(A) - mB,nB = size(B) - out_shape = (mA * mB, nA * nB) - Annz = Int64(A.nnz) - Bnnz = nB - - if Annz == 0 || Bnnz == 0 - return CuSparseMatrixCOO(CuVector{Ti}(undef, 0), CuVector{Ti}(undef, 0), CuVector{T}(undef, 0), out_shape) - end +function LinearAlgebra.kron( + A::Union{CuSparseMatrixCOO{TvA, TiA}, Transpose{TvA, <:CuSparseMatrixCOO{TvA, TiA}}, Adjoint{TvA, <:CuSparseMatrixCOO{TvA, TiA}}}, + B::Diagonal{TvB, <:CuVector{TvB}} + ) where {TvA, TiA, TvB} + mA, nA = size(A) + mB, nB = size(B) + Ti = TiA + Tv = typeof(oneunit(TvA)*oneunit(TvB)) - row = (A.rowInd .- 1) .* mB - row = repeat(row, inner = Bnnz) - col = (A.colInd .- 1) .* nB - col = repeat(col, inner = Bnnz) - data = repeat(A.nzVal, inner = Bnnz) + A_rowInd, A_colInd, A_nzVal, A_nzOp, A_nnz = _kron_CuSparseMatrixCOO_components(A) + B_rowInd, B_colInd, B_nzVal, B_nzOp, B_nnz = one(Ti):Ti(nB), one(Ti):Ti(nB), B.diag, identity, Int(nB) - row .+= CuVector(repeat(0:nB-1, outer = Annz)) .+ 1 - col .+= CuVector(repeat(0:nB-1, outer = Annz)) .+ 1 + if A_nnz == 0 || B_nnz == 0 + return CuSparseMatrixCOO{Tv, Ti}(CuVector{Ti}(undef, 0), CuVector{Ti}(undef, 0), CuVector{Tv}(undef, 0), (mA * mB, nA * nB)) + end - Bdiag = (TB == Bool) ? CUDA.ones(T, nB) : B.diag - data .*= repeat(Bdiag, outer = Annz) + C_nnz = A_nnz * B_nnz + C_rowInd = reshape(B_rowInd .+ Ti(mB) .* (reshape(A_rowInd, (1, A_nnz)) .- one(Ti)), C_nnz) + C_colInd = reshape(B_colInd .+ Ti(nB) .* (reshape(A_colInd, (1, A_nnz)) .- one(Ti)), C_nnz) + C_nzVal = reshape(B_nzOp.(B_nzVal) .* A_nzOp.(reshape(A_nzVal, (1, A_nnz))), C_nnz) - sparse(row, col, data, out_shape..., fmt = :coo) + C = CuSparseMatrixCOO{Tv, Ti}(C_rowInd, C_colInd, C_nzVal, (mA * mB, nA * nB), C_nnz) + return sort_coo(C) end -function LinearAlgebra.kron(A::Diagonal{TA}, B::CuSparseMatrixCOO{T, Ti}) where {Ti, T, TA} - mA,nA = size(A) - mB,nB = size(B) - out_shape = (mA * mB, nA * nB) - Annz = nA - Bnnz = Int64(B.nnz) - - if Annz == 0 || Bnnz == 0 - return CuSparseMatrixCOO(CuVector{Ti}(undef, 0), CuVector{Ti}(undef, 0), CuVector{T}(undef, 0), out_shape) - end +function LinearAlgebra.kron( + A::Diagonal{TvA, <:CuVector{TvA}}, + B::Union{CuSparseMatrixCOO{TvB, TiB}, Transpose{TvB, <:CuSparseMatrixCOO{TvB, TiB}}, Adjoint{TvB, <:CuSparseMatrixCOO{TvB, TiB}}} + ) where {TvA, TvB, TiB} + mA, nA = size(A) + mB, nB = size(B) + Ti = TiB + Tv = typeof(oneunit(TvA)*oneunit(TvB)) - row = (0:nA-1) .* mB - row = CuVector(repeat(row, inner = Bnnz)) - col = (0:nA-1) .* nB - col = CuVector(repeat(col, inner = Bnnz)) - Adiag = (TA == Bool) ? CUDA.ones(T, nA) : A.diag - data = repeat(Adiag, inner = Bnnz) + A_rowInd, A_colInd, A_nzVal, A_nzOp, A_nnz = one(Ti):Ti(nA), one(Ti):Ti(nA), A.diag, identity, Int(nA) + B_rowInd, B_colInd, B_nzVal, B_nzOp, B_nnz = _kron_CuSparseMatrixCOO_components(B) - row .+= repeat(B.rowInd .- 1, outer = Annz) .+ 1 - col .+= repeat(B.colInd .- 1, outer = Annz) .+ 1 + if A_nnz == 0 || B_nnz == 0 + return CuSparseMatrixCOO{Tv, Ti}(CuVector{Ti}(undef, 0), CuVector{Ti}(undef, 0), CuVector{Tv}(undef, 0), (mA * mB, nA * nB)) + end - data .*= repeat(B.nzVal, outer = Annz) + C_nnz = A_nnz * B_nnz + C_rowInd = reshape(B_rowInd .+ Ti(mB) .* (reshape(A_rowInd, (1, A_nnz)) .- one(Ti)), C_nnz) + C_colInd = reshape(B_colInd .+ Ti(nB) .* (reshape(A_colInd, (1, A_nnz)) .- one(Ti)), C_nnz) + C_nzVal = reshape(B_nzOp.(B_nzVal) .* A_nzOp.(reshape(A_nzVal, (1, A_nnz))), C_nnz) - sparse(row, col, data, out_shape..., fmt = :coo) + C = CuSparseMatrixCOO{Tv, Ti}(C_rowInd, C_colInd, C_nzVal, (mA * mB, nA * nB), C_nnz) + return sort_coo(C) end function LinearAlgebra.dot(y::CuVector{T}, A::CuSparseMatrixCSC{T}, x::CuVector{T}) where {T<:Union{BlasInt, BlasFloat}} diff --git a/test/libraries/cusparse/linalg.jl b/test/libraries/cusparse/linalg.jl index dd609f1ee8..1be5a97984 100644 --- a/test/libraries/cusparse/linalg.jl +++ b/test/libraries/cusparse/linalg.jl @@ -1,5 +1,5 @@ using CUDA.CUSPARSE -using LinearAlgebra, SparseArrays +using LinearAlgebra, SparseArrays, Adapt m = 10 @testset "T = $T" for T in [Float32, Float64, ComplexF32, ComplexF64] @@ -53,6 +53,43 @@ m = 10 end end +@testset "TvA = $TvA, TvB = $TvB" for TvA in [Bool, Float32, ComplexF32], TvB in [Float32, Float64] + mat_sizes = [(2, 3), (2, 2), (2, 0), (0, 2), (0, 0)] + + @testset "size(A) = ($(mA), $(nA))" for (mA, nA) in mat_sizes + A = sprand(TvA, mA, nA, 0.5) + A_diag = Diagonal(rand(TvA, mA)) + @testset "size(B) = ($(mB), $(nB))" for (mB, nB) in mat_sizes + B = sprand(TvB, mB, nB, 0.5) + + dA = CuSparseMatrixCOO{TvA}(A) + dA_diag = adapt(CuArray, A_diag) + dB = CuSparseMatrixCOO{TvB}(B) + + @testset "kronecker (COO ⊗ COO) opa = $opa, opb = $opb" for opa in (identity, transpose, adjoint), opb in (identity, transpose, adjoint) + dC = kron(opa(dA), opb(dB)) + @test collect(dC) ≈ kron(opa(A), opb(B)) + @test eltype(dC) == typeof(oneunit(TvA) * oneunit(TvB)) + @test dC isa CuSparseMatrixCOO + end + + @testset "kronecker (diagonal ⊗ COO) opa = $opa, opb = $opb" for opa in (adjoint, ), opb in (identity, transpose, adjoint) + dC = kron(opa(dA_diag), opb(dB)) + @test collect(dC) ≈ kron(opa(A_diag), opb(B)) + @test eltype(dC) == typeof(oneunit(TvA) * oneunit(TvB)) + @test dC isa CuSparseMatrixCOO + end + + @testset "kronecker (COO ⊗ diagonal) opa = $opa, opb = $opb" for opa in (identity, transpose, adjoint), opb in (adjoint, ) + dC = kron(opb(dB), opa(dA_diag)) + @test collect(dC) ≈ kron(opb(B), opa(A_diag)) + @test eltype(dC) == typeof(oneunit(TvA) * oneunit(TvB)) + @test dC isa CuSparseMatrixCOO + end + end + end +end + @testset "Reshape $typ (100,100) -> (20, 500) and droptol" for typ in [CuSparseMatrixCSR, CuSparseMatrixCSC] From fd04f1ca1e8d0b304ce126924848bc2b2f95b26b Mon Sep 17 00:00:00 2001 From: Tamme Claus Date: Mon, 14 Jul 2025 23:10:05 +0200 Subject: [PATCH 5/5] Reduce tests and test only Diagonal{Bool} --- test/libraries/cusparse/linalg.jl | 60 ++++++++++++++++--------------- 1 file changed, 31 insertions(+), 29 deletions(-) diff --git a/test/libraries/cusparse/linalg.jl b/test/libraries/cusparse/linalg.jl index 1be5a97984..9af0966faf 100644 --- a/test/libraries/cusparse/linalg.jl +++ b/test/libraries/cusparse/linalg.jl @@ -53,40 +53,42 @@ m = 10 end end -@testset "TvA = $TvA, TvB = $TvB" for TvA in [Bool, Float32, ComplexF32], TvB in [Float32, Float64] - mat_sizes = [(2, 3), (2, 2), (2, 0), (0, 2), (0, 0)] +@testset "T = $T" for T in [Float32, Float64, ComplexF32, ComplexF64] + mat_sizes = [(2, 3), (2, 0)] + @testset "size(A) = ($(mA), $(nA)), size(B) = ($(mB), $(nB))" for (mA, nA) in mat_sizes, (mB, nB) in mat_sizes + A = sprand(T, mA, nA, 0.5) + B = sprand(T, mB, nB, 0.5) - @testset "size(A) = ($(mA), $(nA))" for (mA, nA) in mat_sizes - A = sprand(TvA, mA, nA, 0.5) - A_diag = Diagonal(rand(TvA, mA)) - @testset "size(B) = ($(mB), $(nB))" for (mB, nB) in mat_sizes - B = sprand(TvB, mB, nB, 0.5) + dA = CuSparseMatrixCOO{T}(A) + dB = CuSparseMatrixCOO{T}(B) - dA = CuSparseMatrixCOO{TvA}(A) - dA_diag = adapt(CuArray, A_diag) - dB = CuSparseMatrixCOO{TvB}(B) + @testset "kronecker (COO ⊗ COO) opa = $opa, opb = $opb" for opa in (identity, transpose, adjoint), opb in (identity, transpose, adjoint) + dC = kron(opa(dA), opb(dB)) + @test collect(dC) ≈ kron(opa(A), opb(B)) + @test eltype(dC) == typeof(oneunit(T) * oneunit(T)) + @test dC isa CuSparseMatrixCOO + end + end +end - @testset "kronecker (COO ⊗ COO) opa = $opa, opb = $opb" for opa in (identity, transpose, adjoint), opb in (identity, transpose, adjoint) - dC = kron(opa(dA), opb(dB)) - @test collect(dC) ≈ kron(opa(A), opb(B)) - @test eltype(dC) == typeof(oneunit(TvA) * oneunit(TvB)) - @test dC isa CuSparseMatrixCOO - end +@testset "TA = $TA, TvB = $TvB" for TvB in [Float32, Float64, ComplexF32, ComplexF64], TA in [Bool, TvB] + A = Diagonal(rand(TA, 2)) + B = sprand(TvB, 3, 4, 0.5) + dA = adapt(CuArray, A) + dB = CuSparseMatrixCOO{TvB}(B) - @testset "kronecker (diagonal ⊗ COO) opa = $opa, opb = $opb" for opa in (adjoint, ), opb in (identity, transpose, adjoint) - dC = kron(opa(dA_diag), opb(dB)) - @test collect(dC) ≈ kron(opa(A_diag), opb(B)) - @test eltype(dC) == typeof(oneunit(TvA) * oneunit(TvB)) - @test dC isa CuSparseMatrixCOO - end + @testset "kronecker (diagonal ⊗ COO) opa = $opa, opb = $opb" for opa in (adjoint, ), opb in (identity, transpose, adjoint) + dC = kron(opa(dA), opb(dB)) + @test collect(dC) ≈ kron(opa(A), opb(B)) + @test eltype(dC) == typeof(oneunit(TA) * oneunit(TvB)) + @test dC isa CuSparseMatrixCOO + end - @testset "kronecker (COO ⊗ diagonal) opa = $opa, opb = $opb" for opa in (identity, transpose, adjoint), opb in (adjoint, ) - dC = kron(opb(dB), opa(dA_diag)) - @test collect(dC) ≈ kron(opb(B), opa(A_diag)) - @test eltype(dC) == typeof(oneunit(TvA) * oneunit(TvB)) - @test dC isa CuSparseMatrixCOO - end - end + @testset "kronecker (COO ⊗ diagonal) opa = $opa, opb = $opb" for opa in (identity, transpose, adjoint), opb in (adjoint, ) + dC = kron(opb(dB), opa(dA)) + @test collect(dC) ≈ kron(opb(B), opa(A)) + @test eltype(dC) == typeof(oneunit(TvB) * oneunit(TA)) + @test dC isa CuSparseMatrixCOO end end