From da943c196d892cfca32fd3d9c1bcf1885233076d Mon Sep 17 00:00:00 2001 From: matbesancon Date: Fri, 8 Aug 2025 09:14:31 +0200 Subject: [PATCH 01/19] fast quadratic form for dense matrix, sparse vectorsd --- src/linalg.jl | 28 ++++++++++++++++++++++++++++ test/linalg.jl | 2 ++ 2 files changed, 30 insertions(+) diff --git a/src/linalg.jl b/src/linalg.jl index f2c74101..e2c7631d 100644 --- a/src/linalg.jl +++ b/src/linalg.jl @@ -723,6 +723,34 @@ function dot(x::AbstractSparseVector, D::Diagonal, y::AbstractSparseVector) return s end +function dot( + a::AbstractSparseVector, + Q::Union{DenseMatrixUnion,WrapperMatrixTypes{<:Any,DenseMatrixUnion}}, + b::AbstractSparseVector, +) + n = length(a) + m = length(b) + if size(Q) != (n, m) + throw(DimensionMismatch("Matrix has a size $(size(Q)) but vectors have length $n, $m")) + end + anzind = nonzeroinds(a) + bnzind = nonzeroinds(b) + anzval = nonzeros(a) + bnzval = nonzeros(b) + s = zero(Base.promote_eltype(a, Q, b)) + if isempty(anzind) || isempty(bnzind) + return s + end + @inbounds for a_idx in eachindex(anzind) + for b_idx in eachindex(bnzind) + ia = anzind[a_idx] + ib = bnzind[b_idx] + s += dot(anzval[a_idx], Q[ia, ib], bnzval[b_idx]) + end + end + return s +end + ## triangular sparse handling ## triangular multiplication function LinearAlgebra.generic_trimatmul!(C::StridedVecOrMat, uploc, isunitc, tfun::Function, A::SparseMatrixCSCUnion, B::AbstractVecOrMat) diff --git a/test/linalg.jl b/test/linalg.jl index b21bdfea..e851586f 100644 --- a/test/linalg.jl +++ b/test/linalg.jl @@ -952,6 +952,8 @@ end y = sprand(ComplexF64, 15, 0.5) @test dot(x, A, y) ≈ dot(Vector(x), A, Vector(y)) ≈ (Vector(x)' * Matrix(A)) * Vector(y) @test dot(x, A, y) ≈ dot(x, Av, y) + @test dot(x, collect(A), y) ≈ dot(x, A, y) + @test dot(y, collect(A)', x) ≈ dot(y, A', x) end for (T, trans) in ((Float64, Symmetric), (ComplexF64, Hermitian)), uplo in (:U, :L) From 7c46a3e102d17ce60244f392b7e8229551151e4a Mon Sep 17 00:00:00 2001 From: matbesancon Date: Fri, 8 Aug 2025 09:22:09 +0200 Subject: [PATCH 02/19] specializations --- src/linalg.jl | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/linalg.jl b/src/linalg.jl index e2c7631d..a4fc1ed0 100644 --- a/src/linalg.jl +++ b/src/linalg.jl @@ -728,6 +728,30 @@ function dot( Q::Union{DenseMatrixUnion,WrapperMatrixTypes{<:Any,DenseMatrixUnion}}, b::AbstractSparseVector, ) + return _dot_quadratic_form(a, Q, b) +end + +function dot( + a::AbstractSparseVector, + Q::LinearAlgebra.Transpose{<:Real, Union{StridedMatrix, BitMatrix}}, + b::AbstractSparseVector, +) + return _dot_quadratic_form(a, Q, b) +end + +function dot( + a::AbstractSparseVector, + Q::Union{ + LinearAlgebra.Hermitian{<:Real, Union{StridedMatrix, BitMatrix}}, + LinearAlgebra.Hermitian{Complex{<:Real}, Union{StridedMatrix, BitMatrix}}, + LinearAlgebra.Symmetric{<:Real, Union{StridedMatrix, BitMatrix}} + }, + b::AbstractSparseVector) + return _dot_quadratic_form(a, Q, b) +end + +# actual function implementation called by the method dispatch +function _dot_quadratic_form(a, Q, b) n = length(a) m = length(b) if size(Q) != (n, m) From 30501187737009641919c950f6d451c85f554a7c Mon Sep 17 00:00:00 2001 From: matbesancon Date: Fri, 8 Aug 2025 09:31:12 +0200 Subject: [PATCH 03/19] fix ambiguities --- src/linalg.jl | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/linalg.jl b/src/linalg.jl index a4fc1ed0..803ecf0d 100644 --- a/src/linalg.jl +++ b/src/linalg.jl @@ -733,7 +733,7 @@ end function dot( a::AbstractSparseVector, - Q::LinearAlgebra.Transpose{<:Real, Union{StridedMatrix, BitMatrix}}, + Q::LinearAlgebra.Transpose{<:Real}, b::AbstractSparseVector, ) return _dot_quadratic_form(a, Q, b) @@ -741,11 +741,7 @@ end function dot( a::AbstractSparseVector, - Q::Union{ - LinearAlgebra.Hermitian{<:Real, Union{StridedMatrix, BitMatrix}}, - LinearAlgebra.Hermitian{Complex{<:Real}, Union{StridedMatrix, BitMatrix}}, - LinearAlgebra.Symmetric{<:Real, Union{StridedMatrix, BitMatrix}} - }, + Q::LinearAlgebra.RealHermSymComplexHerm, b::AbstractSparseVector) return _dot_quadratic_form(a, Q, b) end From 0f58a2b6c2bcf20c05b45b8479f37505f7421059 Mon Sep 17 00:00:00 2001 From: matbesancon Date: Fri, 8 Aug 2025 09:46:07 +0200 Subject: [PATCH 04/19] attempt to fix ambiguities --- src/linalg.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/linalg.jl b/src/linalg.jl index 803ecf0d..6f5f08ac 100644 --- a/src/linalg.jl +++ b/src/linalg.jl @@ -733,7 +733,7 @@ end function dot( a::AbstractSparseVector, - Q::LinearAlgebra.Transpose{<:Real}, + Q::LinearAlgebra.Transpose{<:Any, Union{DenseMatrixUnion,WrapperMatrixTypes{<:Any,DenseMatrixUnion}}}, b::AbstractSparseVector, ) return _dot_quadratic_form(a, Q, b) @@ -741,7 +741,7 @@ end function dot( a::AbstractSparseVector, - Q::LinearAlgebra.RealHermSymComplexHerm, + Q::LinearAlgebra.RealHermSymComplexHerm{<:Any, DenseMatrixUnion}, b::AbstractSparseVector) return _dot_quadratic_form(a, Q, b) end From a3c21dc2fc2708e6018870fb243799a19d5ca97e Mon Sep 17 00:00:00 2001 From: matbesancon Date: Fri, 8 Aug 2025 09:50:13 +0200 Subject: [PATCH 05/19] attempt to fix ambiguities --- src/linalg.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/linalg.jl b/src/linalg.jl index 6f5f08ac..ecd0450a 100644 --- a/src/linalg.jl +++ b/src/linalg.jl @@ -733,7 +733,7 @@ end function dot( a::AbstractSparseVector, - Q::LinearAlgebra.Transpose{<:Any, Union{DenseMatrixUnion,WrapperMatrixTypes{<:Any,DenseMatrixUnion}}}, + Q::LinearAlgebra.Transpose{<:Any, DenseMatrixUnion}, b::AbstractSparseVector, ) return _dot_quadratic_form(a, Q, b) From 2f9efdb2acd97b4058ceedba95e791c7028ca8e4 Mon Sep 17 00:00:00 2001 From: matbesancon Date: Fri, 8 Aug 2025 09:51:26 +0200 Subject: [PATCH 06/19] attempt to fix ambiguities --- src/linalg.jl | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/linalg.jl b/src/linalg.jl index ecd0450a..503fbc04 100644 --- a/src/linalg.jl +++ b/src/linalg.jl @@ -739,6 +739,14 @@ function dot( return _dot_quadratic_form(a, Q, b) end +function dot( + a::AbstractSparseVector, + Q::LinearAlgebra.Transpose{<:Any, WrapperMatrixTypes{<:Real,DenseMatrixUnion}}, + b::AbstractSparseVector, +) + return _dot_quadratic_form(a, Q, b) +end + function dot( a::AbstractSparseVector, Q::LinearAlgebra.RealHermSymComplexHerm{<:Any, DenseMatrixUnion}, From d00768785a10976154e8fd4f0252f6c7cee0e153 Mon Sep 17 00:00:00 2001 From: matbesancon Date: Fri, 8 Aug 2025 09:52:56 +0200 Subject: [PATCH 07/19] attempt to fix ambiguities --- src/linalg.jl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/linalg.jl b/src/linalg.jl index 503fbc04..00f524a8 100644 --- a/src/linalg.jl +++ b/src/linalg.jl @@ -725,7 +725,7 @@ end function dot( a::AbstractSparseVector, - Q::Union{DenseMatrixUnion,WrapperMatrixTypes{<:Any,DenseMatrixUnion}}, + Q::Union{DenseMatrixUnion,WrapperMatrixTypes{<:Real,DenseMatrixUnion}}, b::AbstractSparseVector, ) return _dot_quadratic_form(a, Q, b) @@ -733,7 +733,7 @@ end function dot( a::AbstractSparseVector, - Q::LinearAlgebra.Transpose{<:Any, DenseMatrixUnion}, + Q::LinearAlgebra.Transpose{<:Real, DenseMatrixUnion}, b::AbstractSparseVector, ) return _dot_quadratic_form(a, Q, b) @@ -741,7 +741,7 @@ end function dot( a::AbstractSparseVector, - Q::LinearAlgebra.Transpose{<:Any, WrapperMatrixTypes{<:Real,DenseMatrixUnion}}, + Q::LinearAlgebra.Transpose{<:Real, WrapperMatrixTypes{<:Real,DenseMatrixUnion}}, b::AbstractSparseVector, ) return _dot_quadratic_form(a, Q, b) @@ -749,7 +749,7 @@ end function dot( a::AbstractSparseVector, - Q::LinearAlgebra.RealHermSymComplexHerm{<:Any, DenseMatrixUnion}, + Q::LinearAlgebra.RealHermSymComplexHerm{<:Real, DenseMatrixUnion}, b::AbstractSparseVector) return _dot_quadratic_form(a, Q, b) end From a7513cb9bd877484f3a32304a8ab23fc694a61be Mon Sep 17 00:00:00 2001 From: matbesancon Date: Fri, 8 Aug 2025 09:57:41 +0200 Subject: [PATCH 08/19] attempt to fix ambiguities --- src/linalg.jl | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/linalg.jl b/src/linalg.jl index 00f524a8..4097be80 100644 --- a/src/linalg.jl +++ b/src/linalg.jl @@ -754,6 +754,13 @@ function dot( return _dot_quadratic_form(a, Q, b) end +function dot( + a::AbstractSparseVector, + Q::LinearAlgebra.Hermitian{<:Real, DenseMatrixUnion}, + b::AbstractSparseVector) + return _dot_quadratic_form(a, Q, b) +end + # actual function implementation called by the method dispatch function _dot_quadratic_form(a, Q, b) n = length(a) From 60ed5f1ffaccf07c3106e18b30ea9abd0eb49af1 Mon Sep 17 00:00:00 2001 From: matbesancon Date: Fri, 8 Aug 2025 10:32:52 +0200 Subject: [PATCH 09/19] attempt to fix ambiguities --- src/linalg.jl | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/linalg.jl b/src/linalg.jl index 4097be80..4860556b 100644 --- a/src/linalg.jl +++ b/src/linalg.jl @@ -761,6 +761,17 @@ function dot( return _dot_quadratic_form(a, Q, b) end +function dot( + a::AbstractSparseVector, + Q::Union{ + LinearAlgebra.Hermitian{<:Real, DenseMatrixUnion}, LinearAlgebra.Symmetric{<:Real, DenseMatrixUnion} + }, + b::AbstractSparseVector) + return _dot_quadratic_form(a, Q, b) +end + +dot(::SparseArrays.AbstractSparseVector, ::Union{LinearAlgebra.Hermitian{<:Real, Union{StridedMatrix, BitMatrix}}, LinearAlgebra.Symmetric{<:Real, Union{StridedMatrix, BitMatrix}}}, ::SparseArrays.AbstractSparseVector) + # actual function implementation called by the method dispatch function _dot_quadratic_form(a, Q, b) n = length(a) From 7897df75a54c5720e7d0e9adbcbc1747a334769e Mon Sep 17 00:00:00 2001 From: matbesancon Date: Fri, 8 Aug 2025 10:34:55 +0200 Subject: [PATCH 10/19] fix typo --- src/linalg.jl | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/linalg.jl b/src/linalg.jl index 4860556b..fb0f0238 100644 --- a/src/linalg.jl +++ b/src/linalg.jl @@ -770,8 +770,6 @@ function dot( return _dot_quadratic_form(a, Q, b) end -dot(::SparseArrays.AbstractSparseVector, ::Union{LinearAlgebra.Hermitian{<:Real, Union{StridedMatrix, BitMatrix}}, LinearAlgebra.Symmetric{<:Real, Union{StridedMatrix, BitMatrix}}}, ::SparseArrays.AbstractSparseVector) - # actual function implementation called by the method dispatch function _dot_quadratic_form(a, Q, b) n = length(a) From b5792f5d579ffd5f43ed00fe03c60bcb18213802 Mon Sep 17 00:00:00 2001 From: matbesancon Date: Fri, 8 Aug 2025 10:43:39 +0200 Subject: [PATCH 11/19] attempt to remove methods --- src/linalg.jl | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/src/linalg.jl b/src/linalg.jl index fb0f0238..0a61e993 100644 --- a/src/linalg.jl +++ b/src/linalg.jl @@ -725,7 +725,7 @@ end function dot( a::AbstractSparseVector, - Q::Union{DenseMatrixUnion,WrapperMatrixTypes{<:Real,DenseMatrixUnion}}, + Q::AbstractMatrix{<:Number}, b::AbstractSparseVector, ) return _dot_quadratic_form(a, Q, b) @@ -754,13 +754,6 @@ function dot( return _dot_quadratic_form(a, Q, b) end -function dot( - a::AbstractSparseVector, - Q::LinearAlgebra.Hermitian{<:Real, DenseMatrixUnion}, - b::AbstractSparseVector) - return _dot_quadratic_form(a, Q, b) -end - function dot( a::AbstractSparseVector, Q::Union{ From d1a240ed2ae58719dfec7f17243098d8508fe170 Mon Sep 17 00:00:00 2001 From: matbesancon Date: Fri, 8 Aug 2025 10:46:02 +0200 Subject: [PATCH 12/19] back to dense --- src/linalg.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/linalg.jl b/src/linalg.jl index 0a61e993..5c53119d 100644 --- a/src/linalg.jl +++ b/src/linalg.jl @@ -725,7 +725,7 @@ end function dot( a::AbstractSparseVector, - Q::AbstractMatrix{<:Number}, + Q::Union{DenseMatrixUnion,WrapperMatrixTypes{<:Real,DenseMatrixUnion}}, b::AbstractSparseVector, ) return _dot_quadratic_form(a, Q, b) From bba7ac9d311b30e1dca8ca212702c7e8b2129e04 Mon Sep 17 00:00:00 2001 From: matbesancon Date: Fri, 8 Aug 2025 11:07:05 +0200 Subject: [PATCH 13/19] lighten ambiguity checks --- src/linalg.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/linalg.jl b/src/linalg.jl index 5c53119d..10a8d7e3 100644 --- a/src/linalg.jl +++ b/src/linalg.jl @@ -605,7 +605,7 @@ function dot(x::AbstractVector{T1}, A::AbstractSparseMatrixCSC{T2}, y::AbstractV end return s end -function dot(x::SparseVector, A::AbstractSparseMatrixCSC, y::SparseVector) +function dot(x::AbstractSparseVector, A::AbstractSparseMatrixCSC, y::AbstractSparseVector) m, n = size(A) length(x) == m && n == length(y) || throw(DimensionMismatch("x has length $(length(x)), A has size ($m, $n), y has length $(length(y))")) @@ -725,7 +725,7 @@ end function dot( a::AbstractSparseVector, - Q::Union{DenseMatrixUnion,WrapperMatrixTypes{<:Real,DenseMatrixUnion}}, + Q::AbstractMatrix, b::AbstractSparseVector, ) return _dot_quadratic_form(a, Q, b) From 16ea1b7bb96d7e8ff158d762924be4c8efe0e6fd Mon Sep 17 00:00:00 2001 From: matbesancon Date: Fri, 8 Aug 2025 11:17:04 +0200 Subject: [PATCH 14/19] revert lightening ambiguities --- src/linalg.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/linalg.jl b/src/linalg.jl index 10a8d7e3..bd0f6280 100644 --- a/src/linalg.jl +++ b/src/linalg.jl @@ -725,7 +725,7 @@ end function dot( a::AbstractSparseVector, - Q::AbstractMatrix, + Q::Union{DenseMatrixUnion,WrapperMatrixTypes{<:Real,DenseMatrixUnion}}, b::AbstractSparseVector, ) return _dot_quadratic_form(a, Q, b) From 29deb015eb9cd1ded25a060ad691c8911db219cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mathieu=20Besan=C3=A7on?= Date: Fri, 8 Aug 2025 15:36:41 +0200 Subject: [PATCH 15/19] Apply suggestions from code review Co-authored-by: Daniel Karrasch --- src/linalg.jl | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/linalg.jl b/src/linalg.jl index bd0f6280..19f9f371 100644 --- a/src/linalg.jl +++ b/src/linalg.jl @@ -725,7 +725,7 @@ end function dot( a::AbstractSparseVector, - Q::Union{DenseMatrixUnion,WrapperMatrixTypes{<:Real,DenseMatrixUnion}}, + Q::Union{DenseMatrixUnion,WrapperMatrixTypes{<:Real,<:DenseMatrixUnion}}, b::AbstractSparseVector, ) return _dot_quadratic_form(a, Q, b) @@ -733,7 +733,7 @@ end function dot( a::AbstractSparseVector, - Q::LinearAlgebra.Transpose{<:Real, DenseMatrixUnion}, + Q::LinearAlgebra.Transpose{<:Real,<:DenseMatrixUnion}, b::AbstractSparseVector, ) return _dot_quadratic_form(a, Q, b) @@ -741,7 +741,7 @@ end function dot( a::AbstractSparseVector, - Q::LinearAlgebra.Transpose{<:Real, WrapperMatrixTypes{<:Real,DenseMatrixUnion}}, + Q::LinearAlgebra.Transpose{<:Real,<:WrapperMatrixTypes{<:Real,<:DenseMatrixUnion}}, b::AbstractSparseVector, ) return _dot_quadratic_form(a, Q, b) @@ -749,7 +749,7 @@ end function dot( a::AbstractSparseVector, - Q::LinearAlgebra.RealHermSymComplexHerm{<:Real, DenseMatrixUnion}, + Q::LinearAlgebra.RealHermSymComplexHerm{<:Real,<:DenseMatrixUnion}, b::AbstractSparseVector) return _dot_quadratic_form(a, Q, b) end @@ -757,7 +757,7 @@ end function dot( a::AbstractSparseVector, Q::Union{ - LinearAlgebra.Hermitian{<:Real, DenseMatrixUnion}, LinearAlgebra.Symmetric{<:Real, DenseMatrixUnion} + LinearAlgebra.Hermitian{<:Real,<:DenseMatrixUnion}, LinearAlgebra.Symmetric{<:Real,<:DenseMatrixUnion} }, b::AbstractSparseVector) return _dot_quadratic_form(a, Q, b) From aedf60aae47a9c02ef8a79deb9619195a41b7a0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mathieu=20Besan=C3=A7on?= Date: Sat, 9 Aug 2025 15:43:21 +0200 Subject: [PATCH 16/19] Update src/linalg.jl Co-authored-by: Daniel Karrasch --- src/linalg.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/linalg.jl b/src/linalg.jl index 19f9f371..c4c929ec 100644 --- a/src/linalg.jl +++ b/src/linalg.jl @@ -725,7 +725,7 @@ end function dot( a::AbstractSparseVector, - Q::Union{DenseMatrixUnion,WrapperMatrixTypes{<:Real,<:DenseMatrixUnion}}, + Q::Union{DenseMatrixUnion,WrapperMatrixTypes{<:Any,<:DenseMatrixUnion}}, b::AbstractSparseVector, ) return _dot_quadratic_form(a, Q, b) From 4a1ffdf5e57f4f5988e5a681ab670aea9c44e8ca Mon Sep 17 00:00:00 2001 From: matbesancon Date: Sat, 9 Aug 2025 16:39:31 +0200 Subject: [PATCH 17/19] added wrapper tests --- test/linalg.jl | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test/linalg.jl b/test/linalg.jl index e851586f..83dbf803 100644 --- a/test/linalg.jl +++ b/test/linalg.jl @@ -954,6 +954,11 @@ end @test dot(x, A, y) ≈ dot(x, Av, y) @test dot(x, collect(A), y) ≈ dot(x, A, y) @test dot(y, collect(A)', x) ≈ dot(y, A', x) + @test dot(y, transpose(collect(A)), x) ≈ dot(y, transpose(A), x) + @test dot(y, Hermitian(collect(A)' * collect(A)), y) ≈ dot(y, Hermitian(A' * A), y) + @test dot(y, Symmetric(collect(A)' * collect(A)), y) ≈ dot(y, Symmetric(A' * A), y) + B = BitMatrix(rand(Bool, 10, 15)) + @test dot(x, A, y) ≈ dot(x, Matrix(A), y) end for (T, trans) in ((Float64, Symmetric), (ComplexF64, Hermitian)), uplo in (:U, :L) From d8fc973c121834f27832343ade0e18b83fd9424e Mon Sep 17 00:00:00 2001 From: Daniel Karrasch Date: Sun, 10 Aug 2025 11:54:24 +0200 Subject: [PATCH 18/19] Improve code coverage --- test/linalg.jl | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/linalg.jl b/test/linalg.jl index d600c134..9f40f51f 100644 --- a/test/linalg.jl +++ b/test/linalg.jl @@ -959,6 +959,9 @@ end @test dot(y, Symmetric(collect(A)' * collect(A)), y) ≈ dot(y, Symmetric(A' * A), y) B = BitMatrix(rand(Bool, 10, 15)) @test dot(x, A, y) ≈ dot(x, Matrix(A), y) + @test_throws DimensionMismatch dot([x, x], A, y) + @test_throws DimensionMismatch dot(x, A, [y, y]) + @test iszero(dot(spzeros(length(x)), A, y) end for T in (Float64, ComplexF64, Quaternion{Float64}), trans in (Symmetric, Hermitian), uplo in (:U, :L) From 4c71b6ba5f6e4897eff108ea383683c19b65c169 Mon Sep 17 00:00:00 2001 From: Daniel Karrasch Date: Sun, 10 Aug 2025 12:05:32 +0200 Subject: [PATCH 19/19] Update test/linalg.jl --- test/linalg.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/linalg.jl b/test/linalg.jl index 9f40f51f..ce4f4e31 100644 --- a/test/linalg.jl +++ b/test/linalg.jl @@ -961,7 +961,7 @@ end @test dot(x, A, y) ≈ dot(x, Matrix(A), y) @test_throws DimensionMismatch dot([x, x], A, y) @test_throws DimensionMismatch dot(x, A, [y, y]) - @test iszero(dot(spzeros(length(x)), A, y) + @test iszero(dot(spzeros(length(x)), A, y)) end for T in (Float64, ComplexF64, Quaternion{Float64}), trans in (Symmetric, Hermitian), uplo in (:U, :L)