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 4, 2016
1 parent c9090ef commit b3b8350
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 36 deletions.
32 changes: 32 additions & 0 deletions base/deprecated.jl
Original file line number Diff line number Diff line change
Expand Up @@ -788,6 +788,38 @@ function symperm{Tv,Ti}(A::SparseMatrixCSC{Tv,Ti}, pinv::Vector{Ti})
"Pkg.add(\"SuiteSparse\") to install SuiteSparse on Julia v0.5."))
end

# needs to be a macro so that we can use ::@mime(s) in type declarations
eval(Multimedia, quote
export @MIME
macro MIME(s)
Base.warn_once("@MIME(\"\") is deprecated, use MIME\"\" instead.")
if isa(s,AbstractString)
:(MIME{$(Expr(:quote, Symbol(s)))})
else
:(MIME{Symbol($s)})
end
end
end)

# Deprecate vectorized unary functions over sparse matrices in favor of compact broadcast syntax
macro _enumerate_sparsemat_vectobroad_deps(fs...)
depset = Expr(:block)
for f in fs
push!(depset.args, :( @deprecate $(esc(f))(A::SparseMatrixCSC) $(esc(f)).(A) ) )
end
return depset
end
@_enumerate_sparsemat_vectobroad_deps(
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)

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

Expand Down
20 changes: 10 additions & 10 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
65 changes: 39 additions & 26 deletions test/sparsedir/sparse.jl
Original file line number Diff line number Diff line change
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))
end
# 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 @@ -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 b3b8350

Please sign in to comment.