diff --git a/base/deprecated.jl b/base/deprecated.jl index b22c1a3cc6523a..1c06e3b18d3ccd 100644 --- a/base/deprecated.jl +++ b/base/deprecated.jl @@ -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 diff --git a/base/sparse/sparsematrix.jl b/base/sparse/sparsematrix.jl index a6dc64e6111cd6..84eacd0c410cf7 100644 --- a/base/sparse/sparsematrix.jl +++ b/base/sparse/sparsematrix.jl @@ -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 @@ -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) @@ -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]) diff --git a/test/sparsedir/sparse.jl b/test/sparsedir/sparse.jl index e68d43039d50f1..a0c6453e33e5fa 100644 --- a/test/sparsedir/sparse.jl +++ b/test/sparsedir/sparse.jl @@ -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 @@ -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