Skip to content

Commit

Permalink
Transition vectorized unary functions over SparseMatrixCSCs to comp…
Browse files Browse the repository at this point in the history
…act broadcast syntax, accordingly revise and expand the associated tests, and add deprecations for the vectorized syntax.
  • Loading branch information
Sacha0 committed Jul 5, 2016
1 parent aad8624 commit 57ea2f9
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 38 deletions.
13 changes: 13 additions & 0 deletions base/deprecated.jl
Original file line number Diff line number Diff line change
Expand Up @@ -788,6 +788,19 @@ function symperm{Tv,Ti}(A::SparseMatrixCSC{Tv,Ti}, pinv::Vector{Ti})
"Pkg.add(\"SuiteSparse\") to install SuiteSparse on Julia v0.5."))
end

# Deprecate vectorized unary functions over sparse matrices in favor of compact broadcast syntax
for f in (:sin, :sinh, :sind, :asin, :asinh, :asind,
:tan, :tanh, :tand, :atan, :atanh, :atand,
:sinpi, :cosc, :ceil, :floor, :trunc, :round, :real, :imag,
:log1p, :expm1, :abs, :abs2, :conj,
:log, :log2, :log10, :exp, :exp2, :exp10, :sinc, :cospi,
:cos, :cosh, :cosd, :acos, :acosd,
:cot, :coth, :cotd, :acot, :acotd,
:sec, :sech, :secd, :asech,
:csc, :csch, :cscd, :acsch)
@eval @deprecate $f(A::SparseMatrixCSC) $f.(A)
end

# During the 0.5 development cycle, do not add any deprecations below this line
# To be deprecated in 0.6

Expand Down
22 changes: 11 additions & 11 deletions base/sparse/sparsematrix.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1036,12 +1036,12 @@ end
"""
Helper macro for the unary broadcast definitions below. Takes parent method `fp` and a set
of desired child methods `fcs`, and builds an expression defining each of the child methods
such that `fc(A::SparseMatrixCSC) = fp(fc, A)`.
such that `broadcast(::typeof(fc), A::SparseMatrixCSC) = fp(fc, A)`.
"""
macro _enumerate_childmethods(fp, fcs...)
fcexps = Expr(:block)
for fc in fcs
push!(fcexps.args, :( $(esc(fc))(A::SparseMatrixCSC) = $(esc(fp))($(esc(fc)), A) ) )
push!(fcexps.args, :( broadcast(::typeof($(esc(fc))), A::SparseMatrixCSC) = $(esc(fp))($(esc(fc)), A) ) )
end
return fcexps
end
Expand Down Expand Up @@ -1080,10 +1080,10 @@ end
sin, sinh, sind, asin, asinh, asind,
tan, tanh, tand, atan, atanh, atand,
sinpi, cosc, ceil, floor, trunc, round)
real(A::SparseMatrixCSC) = copy(A)
imag{Tv,Ti}(A::SparseMatrixCSC{Tv,Ti}) = spzeros(Tv, Ti, A.m, A.n)
real{TTv}(A::SparseMatrixCSC{Complex{TTv}}) = _broadcast_unary_nz2z_z2z_T(real, A, TTv)
imag{TTv}(A::SparseMatrixCSC{Complex{TTv}}) = _broadcast_unary_nz2z_z2z_T(imag, A, TTv)
broadcast(::typeof(real), A::SparseMatrixCSC) = copy(A)
broadcast{Tv,Ti}(::typeof(imag), A::SparseMatrixCSC{Tv,Ti}) = spzeros(Tv, Ti, A.m, A.n)
broadcast{TTv}(::typeof(real), A::SparseMatrixCSC{Complex{TTv}}) = _broadcast_unary_nz2z_z2z_T(real, A, TTv)
broadcast{TTv}(::typeof(imag), A::SparseMatrixCSC{Complex{TTv}}) = _broadcast_unary_nz2z_z2z_T(imag, A, TTv)
ceil{To}(::Type{To}, A::SparseMatrixCSC) = _broadcast_unary_nz2z_z2z_T(ceil, A, To)
floor{To}(::Type{To}, A::SparseMatrixCSC) = _broadcast_unary_nz2z_z2z_T(floor, A, To)
trunc{To}(::Type{To}, A::SparseMatrixCSC) = _broadcast_unary_nz2z_z2z_T(trunc, A, To)
Expand All @@ -1110,10 +1110,10 @@ function _broadcast_unary_nz2nz_z2z{Tv}(f::Function, A::SparseMatrixCSC{Tv})
end
@_enumerate_childmethods(_broadcast_unary_nz2nz_z2z,
log1p, expm1, abs, abs2, conj)
abs2{TTv}(A::SparseMatrixCSC{Complex{TTv}}) = _broadcast_unary_nz2nz_z2z_T(abs2, A, TTv)
abs{TTv}(A::SparseMatrixCSC{Complex{TTv}}) = _broadcast_unary_nz2nz_z2z_T(abs, A, TTv)
abs{TTv<:Integer}(A::SparseMatrixCSC{Complex{TTv}}) = _broadcast_unary_nz2nz_z2z_T(abs, A, Float64)
abs{TTv<:BigInt}(A::SparseMatrixCSC{Complex{TTv}}) = _broadcast_unary_nz2nz_z2z_T(abs, A, BigFloat)
broadcast{TTv}(::typeof(abs2), A::SparseMatrixCSC{Complex{TTv}}) = _broadcast_unary_nz2nz_z2z_T(abs2, A, TTv)
broadcast{TTv}(::typeof(abs), A::SparseMatrixCSC{Complex{TTv}}) = _broadcast_unary_nz2nz_z2z_T(abs, A, TTv)
broadcast{TTv<:Integer}(::typeof(abs), A::SparseMatrixCSC{Complex{TTv}}) = _broadcast_unary_nz2nz_z2z_T(abs, A, Float64)
broadcast{TTv<:BigInt}(::typeof(abs), A::SparseMatrixCSC{Complex{TTv}}) = _broadcast_unary_nz2nz_z2z_T(abs, A, BigFloat)
function conj!(A::SparseMatrixCSC)
@inbounds @simd for k in 1:nnz(A)
A.nzval[k] = conj(A.nzval[k])
Expand Down Expand Up @@ -1450,7 +1450,7 @@ end # macro
(.^)(A::SparseMatrixCSC, B::Number) =
B==0 ? sparse(ones(typeof(one(eltype(A)).^B), A.m, A.n)) :
SparseMatrixCSC(A.m, A.n, copy(A.colptr), copy(A.rowval), A.nzval .^ B)
(.^)(::Irrational{:e}, B::SparseMatrixCSC) = exp(B)
(.^)(::Irrational{:e}, B::SparseMatrixCSC) = exp.(B)
(.^)(A::Number, B::SparseMatrixCSC) = (.^)(A, full(B))
(.^)(A::SparseMatrixCSC, B::Array) = (.^)(full(A), B)
(.^)(A::Array, B::SparseMatrixCSC) = (.^)(A, full(B))
Expand Down
67 changes: 40 additions & 27 deletions test/sparsedir/sparse.jl
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,7 @@ end

# conj
cA = sprandn(5,5,0.2) + im*sprandn(5,5,0.2)
@test full(conj(cA)) == conj(full(cA))
@test full(conj.(cA)) == conj(full(cA))

# transpose of SubArrays
A = view(sprandn(10, 10, 0.3), 1:4, 1:4)
Expand Down Expand Up @@ -402,22 +402,47 @@ end
@test maximum(sparse(-ones(3,3))) == -1
@test minimum(sparse(ones(3,3))) == 1

# Unary functions
a = sprand(5,15, 0.5)
afull = full(a)
for op in (:sin, :cos, :tan, :ceil, :floor, :abs, :abs2)
@eval begin
@test ($op)(afull) == full($(op)(a))
end
end

for op in (:ceil, :floor)
@eval begin
@test ($op)(Int,afull) == full($(op)(Int,a))
# Test unary functions with specialized broadcast over SparseMatrixCSCs
let
A = sprand(5, 15, 0.5)
C = A + im*A
Afull = full(A)
Cfull = full(C)
# Test representatives of [unary functions that map zeros to zeros and may map nonzeros to zeros]
@test sin.(Afull) == full(sin.(A))
@test tan.(Afull) == full(tan.(A)) # should be redundant with sin test
@test ceil.(Afull) == full(ceil.(A))
@test floor.(Afull) == full(floor.(A)) # should be redundant with ceil test
@test real.(Afull) == full(real.(A))
@test imag.(Afull) == full(imag.(A))
@test real.(Cfull) == full(real.(C))
@test imag.(Cfull) == full(imag.(C))
# Test representatives of [unary functions that map zeros to zeros and nonzeros to nonzeros]
@test expm1.(Afull) == full(expm1.(A))
@test abs.(Afull) == full(abs.(A))
@test abs2.(Afull) == full(abs2.(A))
@test abs.(Cfull) == full(abs.(C))
@test abs2.(Cfull) == full(abs2.(C))
# Test representatives of [unary functions that map both zeros and nonzeros to nonzeros]
@test cos.(Afull) == full(cos.(A))
# Test representatives of remaining vectorized-nonbroadcast unary functions
@test ceil(Int, Afull) == full(ceil(Int, A))
@test floor(Int, Afull) == full(floor(Int, A))
# Tests of real, imag, abs, and abs2 for SparseMatrixCSC{Int,X}s previously elsewhere
for T in (Int, Float16, Float32, Float64, BigInt, BigFloat)
R = rand(T[1:100;], 2, 2)
I = rand(T[1:100;], 2, 2)
D = R + I*im
S = sparse(D)
@test R == real.(S)
@test I == imag.(S)
@test real.(sparse(R)) == R
@test nnz(imag.(sparse(R))) == 0
@test abs.(S) == abs(D)
@test abs2.(S) == abs2(D)
end
end


# getindex tests
ni = 23
nj = 32
Expand Down Expand Up @@ -696,7 +721,7 @@ end
@test_throws ArgumentError sparsevec(Dict(-1=>1,1=>2))

# issue #8976
@test conj(sparse([1im])) == sparse(conj([1im]))
@test conj.(sparse([1im])) == sparse(conj([1im]))
@test conj!(sparse([1im])) == sparse(conj!([1im]))

# issue #9525
Expand Down Expand Up @@ -862,18 +887,6 @@ end
x = speye(100)
@test_throws BoundsError x[-10:10]

for T in (Int, Float16, Float32, Float64, BigInt, BigFloat)
let R=rand(T[1:100;],2,2), I=rand(T[1:100;],2,2)
D = R + I*im
S = sparse(D)
@test R == real(S)
@test I == imag(S)
@test real(sparse(R)) == R
@test nnz(imag(sparse(R))) == 0
@test abs(S) == abs(D)
@test abs2(S) == abs2(D)
end
end

# issue #10407
@test maximum(spzeros(5, 5)) == 0.0
Expand Down

0 comments on commit 57ea2f9

Please sign in to comment.