Skip to content

Commit

Permalink
added sparse matrix inner product (#27470)
Browse files Browse the repository at this point in the history
  • Loading branch information
jebej authored and simonbyrne committed Jun 12, 2018
1 parent 188e350 commit 4420717
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 1 deletion.
3 changes: 3 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -694,6 +694,9 @@ Library improvements
* `Sys.which()` provides a cross-platform method to find executable files, similar to
the Unix `which` command. ([#26559])

* Added an optimized method of `vecdot` for taking the Frobenius inner product
of sparse matrices. ([#27470])

Compiler/Runtime improvements
-----------------------------

Expand Down
2 changes: 1 addition & 1 deletion stdlib/SparseArrays/src/SparseArrays.jl
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ using LinearAlgebra

import Base: +, -, *, \, /, &, |, xor, ==
import LinearAlgebra: mul!, ldiv!, rdiv!, chol, adjoint!, diag, dot, eigen,
issymmetric, istril, istriu, lu, tr, transpose!, tril!, triu!,
issymmetric, istril, istriu, lu, tr, transpose!, tril!, triu!, vecdot,
vecnorm, cond, diagm, factorize, ishermitian, norm, lmul!, rmul!, tril, triu

import Base: @get!, acos, acosd, acot, acotd, acsch, asech, asin, asind, asinh,
Expand Down
31 changes: 31 additions & 0 deletions stdlib/SparseArrays/src/linalg.jl
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,37 @@ function spmatmul(A::SparseMatrixCSC{Tv,Ti}, B::SparseMatrixCSC{Tv,Ti};
return C
end

# Frobenius inner product: trace(A'B)
function vecdot(A::SparseMatrixCSC{T1,S1},B::SparseMatrixCSC{T2,S2}) where {T1,T2,S1,S2}
m, n = size(A)
size(B) == (m,n) || throw(DimensionMismatch("matrices must have the same dimensions"))
r = vecdot(zero(T1), zero(T2))
@inbounds for j = 1:n
ia = A.colptr[j]; ia_nxt = A.colptr[j+1]
ib = B.colptr[j]; ib_nxt = B.colptr[j+1]
if ia < ia_nxt && ib < ib_nxt
ra = A.rowval[ia]; rb = B.rowval[ib]
while true
if ra < rb
ia += oneunit(S1)
ia < ia_nxt || break
ra = A.rowval[ia]
elseif ra > rb
ib += oneunit(S2)
ib < ib_nxt || break
rb = B.rowval[ib]
else # ra == rb
r += vecdot(A.nzval[ia], B.nzval[ib])
ia += oneunit(S1); ib += oneunit(S2)
ia < ia_nxt && ib < ib_nxt || break
ra = A.rowval[ia]; rb = B.rowval[ib]
end
end
end
end
return r
end

## solvers
function fwdTriSolve!(A::SparseMatrixCSCUnion, B::AbstractVecOrMat)
# forward substitution for CSC matrices
Expand Down
9 changes: 9 additions & 0 deletions stdlib/SparseArrays/test/sparse.jl
Original file line number Diff line number Diff line change
Expand Up @@ -327,6 +327,15 @@ end
end
end

@testset "sparse Frobenius inner product" begin
for i = 1:5
A = sprand(ComplexF64,10,15,0.4)
B = sprand(ComplexF64,10,15,0.5)
@test vecdot(A,B) vecdot(Matrix(A),Matrix(B))
end
@test_throws DimensionMismatch vecdot(sprand(5,5,0.2),sprand(5,6,0.2))
end

sA = sprandn(3, 7, 0.5)
sC = similar(sA)
dA = Array(sA)
Expand Down

0 comments on commit 4420717

Please sign in to comment.