Skip to content

Commit

Permalink
Deprecate Base.SparseArrays.broadcast_zpreserving[!].
Browse files Browse the repository at this point in the history
Generic sparse broadcast[!] now provides most of Base.SparseArrays.broadcast_zpreserving[!]'s functionality.
  • Loading branch information
Sacha0 committed Dec 25, 2016
1 parent 4793e88 commit 08ed837
Show file tree
Hide file tree
Showing 2 changed files with 128 additions and 111 deletions.
124 changes: 124 additions & 0 deletions base/deprecated.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1168,4 +1168,128 @@ for (dep, f, op) in [(:sumabs!, :sum!, :abs),
end
end

## Deprecate broadcast_zpreserving[!] (wasn't exported, but might as well be friendly)
function gen_broadcast_function_sparse(genbody::Function, f::Function, is_first_sparse::Bool)
body = genbody(f, is_first_sparse)
@eval let
local _F_
function _F_{Tv,Ti}(B::SparseMatrixCSC{Tv,Ti}, A_1, A_2)
$body
end
_F_
end
end
function gen_broadcast_body_zpreserving(f::Function, is_first_sparse::Bool)
F = Expr(:quote, f)
if is_first_sparse
A1 = :(A_1)
A2 = :(A_2)
op1 = :(val1)
op2 = :(val2)
else
A1 = :(A_2)
A2 = :(A_1)
op1 = :(val2)
op2 = :(val1)
end
quote
Base.Broadcast.check_broadcast_indices(indices(B), $A1)
Base.Broadcast.check_broadcast_indices(indices(B), $A2)

nnzB = isempty(B) ? 0 :
nnz($A1) * div(B.n, ($A1).n) * div(B.m, ($A1).m)
if length(B.rowval) < nnzB
resize!(B.rowval, nnzB)
end
if length(B.nzval) < nnzB
resize!(B.nzval, nnzB)
end
z = zero(Tv)

ptrB = 1
B.colptr[1] = 1

@inbounds for col = 1:B.n
ptr1::Int = ($A1).n == 1 ? ($A1).colptr[1] : ($A1).colptr[col]
stop1::Int = ($A1).n == 1 ? ($A1).colptr[2] : ($A1).colptr[col+1]
col2 = size($A2, 2) == 1 ? 1 : col
row = 1
while ptr1 < stop1 && row <= B.m
if ($A1).m != 1
row = ($A1).rowval[ptr1]
end
row2 = size($A2, 1) == 1 ? 1 : row
val1 = ($A1).nzval[ptr1]
val2 = ($A2)[row2,col2]
res = ($F)($op1, $op2)
if res != z
B.rowval[ptrB] = row
B.nzval[ptrB] = res
ptrB += 1
end
if ($A1).m != 1
ptr1 += 1
else
row += 1
end
end
B.colptr[col+1] = ptrB
end
deleteat!(B.rowval, B.colptr[end]:length(B.rowval))
deleteat!(B.nzval, B.colptr[end]:length(B.nzval))
nothing
end
end
for (Bsig, A1sig, A2sig, gbb, funcname) in
(
(SparseMatrixCSC , SparseMatrixCSC , Array, :gen_broadcast_body_zpreserving, :_broadcast_zpreserving!),
(SparseMatrixCSC , Array , SparseMatrixCSC, :gen_broadcast_body_zpreserving, :_broadcast_zpreserving!),
(SparseMatrixCSC , Number , SparseMatrixCSC, :gen_broadcast_body_zpreserving, :_broadcast_zpreserving!),
(SparseMatrixCSC , SparseMatrixCSC , Number, :gen_broadcast_body_zpreserving, :_broadcast_zpreserving!),
(SparseMatrixCSC , BitArray , SparseMatrixCSC, :gen_broadcast_body_zpreserving, :_broadcast_zpreserving!),
(SparseMatrixCSC , SparseMatrixCSC , BitArray, :gen_broadcast_body_zpreserving, :_broadcast_zpreserving!),
)
@eval let cache = Dict{Function,Function}()
global $funcname
function $funcname(f::Function, B::$Bsig, A1::$A1sig, A2::$A2sig)
func = @get! cache f gen_broadcast_function_sparse($gbb, f, ($A1sig) <: SparseMatrixCSC)
# need eval because func was just created by gen_broadcast_function_sparse
# TODO: convert this to a generated function
eval(current_module(), Expr(:body, Expr(:return, Expr(:call, QuoteNode(func), QuoteNode(B), QuoteNode(A1), QuoteNode(A2)))))
return B
end
end # let broadcast_cache
end
_broadcast_zpreserving!(args...) = broadcast!(args...)
_broadcast_zpreserving(args...) = Base.Broadcast.broadcast_elwise_op(args...)
_broadcast_zpreserving{Tv1,Ti1,Tv2,Ti2}(f::Function, A_1::SparseMatrixCSC{Tv1,Ti1}, A_2::SparseMatrixCSC{Tv2,Ti2}) =
_broadcast_zpreserving!(f, spzeros(promote_type(Tv1, Tv2), promote_type(Ti1, Ti2), Base.to_shape(Base.Broadcast.broadcast_indices(A_1, A_2))), A_1, A_2)
_broadcast_zpreserving{Tv,Ti}(f::Function, A_1::SparseMatrixCSC{Tv,Ti}, A_2::Union{Array,BitArray,Number}) =
_broadcast_zpreserving!(f, spzeros(promote_eltype(A_1, A_2), Ti, Base.to_shape(Base.Broadcast.broadcast_indices(A_1, A_2))), A_1, A_2)
_broadcast_zpreserving{Tv,Ti}(f::Function, A_1::Union{Array,BitArray,Number}, A_2::SparseMatrixCSC{Tv,Ti}) =
_broadcast_zpreserving!(f, spzeros(promote_eltype(A_1, A_2), Ti, Base.to_shape(Base.Broadcast.broadcast_indices(A_1, A_2))), A_1, A_2)

function _depstring_bczpres()
return string("broadcast_zpreserving[!] is deprecated. Generic sparse broadcast[!] ",
"provides most of broadcast_zpreserving[!]'s functionality. If you have a use case ",
"that generic sparse broadcast[!] does not cover, please describe your use case in ",
" issue #19533 (https://github.com/JuliaLang/julia/issues/19533).")
end
function _depwarn_bczpres(f, args...)
depwarn(_depstring_bczpres(), :broadcast_zpreserving)
return _broadcast_zpreserving(f, args...)
end
function _depwarn_bczpres!(f, args...)
depwarn(_depstring_bczpres(), :broadcast_zpreserving!)
return _broadcast_zpreserving!(f, args...)
end
import Base.SparseArrays: broadcast_zpreserving, broadcast_zpreserving!
broadcast_zpreserving(f, args...) = _depwarn_bczpres(f, args...)
broadcast_zpreserving(f, A::SparseMatrixCSC, B::SparseMatrixCSC) = _depwarn_bczpres(f, A, B)
broadcast_zpreserving(f, A::SparseMatrixCSC, B::Union{Array,BitArray,Number}) = _depwarn_bczpres(f, A, B)
broadcast_zpreserving(f, A::Union{Array,BitArray,Number}, B::SparseMatrixCSC) = _depwarn_bczpres(f, A, B)
broadcast_zpreserving!(f, args...) = _depwarn_bczpres!(f, args...)
broadcast_zpreserving!(f, C::SparseMatrixCSC, A::SparseMatrixCSC, B::Union{Array,BitArray,Number}) = _depwarn_bczpres!(f, C, A, B)
broadcast_zpreserving!(f, C::SparseMatrixCSC, A::Union{Array,BitArray,Number}, B::SparseMatrixCSC) = _depwarn_bczpres!(f, C, A, B)

# End deprecations scheduled for 0.6
115 changes: 4 additions & 111 deletions base/sparse/sparsematrix.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2160,117 +2160,6 @@ broadcast{Tf,T}(f::Tf, ::Type{T}, A::SparseMatrixCSC) = broadcast(y -> f(T, y),
broadcast{Tf,T}(f::Tf, A::SparseMatrixCSC, ::Type{T}) = broadcast(x -> f(x, T), A)


## Define unexported broadcast_zpreserving[!] methods
# TODO: Sort out what to do with broadcast_zpreserving and dependencies

function gen_broadcast_function_sparse(genbody::Function, f::Function, is_first_sparse::Bool)
body = genbody(f, is_first_sparse)
@eval let
local _F_
function _F_{Tv,Ti}(B::SparseMatrixCSC{Tv,Ti}, A_1, A_2)
$body
end
_F_
end
end

# Operations with zero result if any operand is zero
# A_1 or A_2 (or both) are sparse.
# is_first_sparse == true => A_1 is sparse
# is_first_sparse == false => A_2 is sparse
function gen_broadcast_body_zpreserving(f::Function, is_first_sparse::Bool)
F = Expr(:quote, f)
if is_first_sparse
A1 = :(A_1)
A2 = :(A_2)
op1 = :(val1)
op2 = :(val2)
else
A1 = :(A_2)
A2 = :(A_1)
op1 = :(val2)
op2 = :(val1)
end
quote
Base.Broadcast.check_broadcast_indices(indices(B), $A1)
Base.Broadcast.check_broadcast_indices(indices(B), $A2)

nnzB = isempty(B) ? 0 :
nnz($A1) * div(B.n, ($A1).n) * div(B.m, ($A1).m)
if length(B.rowval) < nnzB
resize!(B.rowval, nnzB)
end
if length(B.nzval) < nnzB
resize!(B.nzval, nnzB)
end
z = zero(Tv)

ptrB = 1
B.colptr[1] = 1

@inbounds for col = 1:B.n
ptr1::Int = ($A1).n == 1 ? ($A1).colptr[1] : ($A1).colptr[col]
stop1::Int = ($A1).n == 1 ? ($A1).colptr[2] : ($A1).colptr[col+1]
col2 = size($A2, 2) == 1 ? 1 : col
row = 1
while ptr1 < stop1 && row <= B.m
if ($A1).m != 1
row = ($A1).rowval[ptr1]
end
row2 = size($A2, 1) == 1 ? 1 : row
val1 = ($A1).nzval[ptr1]
val2 = ($A2)[row2,col2]
res = ($F)($op1, $op2)
if res != z
B.rowval[ptrB] = row
B.nzval[ptrB] = res
ptrB += 1
end
if ($A1).m != 1
ptr1 += 1
else
row += 1
end
end
B.colptr[col+1] = ptrB
end
deleteat!(B.rowval, B.colptr[end]:length(B.rowval))
deleteat!(B.nzval, B.colptr[end]:length(B.nzval))
nothing
end
end

for (Bsig, A1sig, A2sig, gbb, funcname) in
(
(SparseMatrixCSC , SparseMatrixCSC , Array, :gen_broadcast_body_zpreserving, :broadcast_zpreserving!),
(SparseMatrixCSC , Array , SparseMatrixCSC, :gen_broadcast_body_zpreserving, :broadcast_zpreserving!),
(SparseMatrixCSC , Number , SparseMatrixCSC, :gen_broadcast_body_zpreserving, :broadcast_zpreserving!),
(SparseMatrixCSC , SparseMatrixCSC , Number, :gen_broadcast_body_zpreserving, :broadcast_zpreserving!),
(SparseMatrixCSC , BitArray , SparseMatrixCSC, :gen_broadcast_body_zpreserving, :broadcast_zpreserving!),
(SparseMatrixCSC , SparseMatrixCSC , BitArray, :gen_broadcast_body_zpreserving, :broadcast_zpreserving!),
)
@eval let cache = Dict{Function,Function}()
global $funcname
function $funcname(f::Function, B::$Bsig, A1::$A1sig, A2::$A2sig)
func = @get! cache f gen_broadcast_function_sparse($gbb, f, ($A1sig) <: SparseMatrixCSC)
# need eval because func was just created by gen_broadcast_function_sparse
# TODO: convert this to a generated function
eval(current_module(), Expr(:body, Expr(:return, Expr(:call, QuoteNode(func), QuoteNode(B), QuoteNode(A1), QuoteNode(A2)))))
return B
end
end # let broadcast_cache
end

@inline broadcast_zpreserving!(args...) = broadcast!(args...)
@inline broadcast_zpreserving(args...) = Base.Broadcast.broadcast_elwise_op(args...)
broadcast_zpreserving{Tv1,Ti1,Tv2,Ti2}(f::Function, A_1::SparseMatrixCSC{Tv1,Ti1}, A_2::SparseMatrixCSC{Tv2,Ti2}) =
broadcast_zpreserving!(f, spzeros(promote_type(Tv1, Tv2), promote_type(Ti1, Ti2), to_shape(broadcast_indices(A_1, A_2))), A_1, A_2)
broadcast_zpreserving{Tv,Ti}(f::Function, A_1::SparseMatrixCSC{Tv,Ti}, A_2::Union{Array,BitArray,Number}) =
broadcast_zpreserving!(f, spzeros(promote_eltype(A_1, A_2), Ti, to_shape(broadcast_indices(A_1, A_2))), A_1, A_2)
broadcast_zpreserving{Tv,Ti}(f::Function, A_1::Union{Array,BitArray,Number}, A_2::SparseMatrixCSC{Tv,Ti}) =
broadcast_zpreserving!(f, spzeros(promote_eltype(A_1, A_2), Ti, to_shape(broadcast_indices(A_1, A_2))), A_1, A_2)


# TODO: More appropriate location?
conj!(A::SparseMatrixCSC) = (broadcast!(conj, A.nzval, A.nzval); A)
(-)(A::SparseMatrixCSC) = SparseMatrixCSC(A.m, A.n, copy(A.colptr), copy(A.rowval), map(-, A.nzval))
Expand All @@ -2281,6 +2170,10 @@ floor{To}(::Type{To}, A::SparseMatrixCSC) = floor.(To, A)
trunc{To}(::Type{To}, A::SparseMatrixCSC) = trunc.(To, A)
round{To}(::Type{To}, A::SparseMatrixCSC) = round.(To, A)

# broadcast_zpreserving[!] deprecated in 0.6. Wasn't exported prior, so need these
# definitions for the deprecation to serve its purpose. Remove after 0.6.
function broadcast_zpreserving end
function broadcast_zpreserving! end

## Binary arithmetic and boolean operators
(+)(A::SparseMatrixCSC, B::SparseMatrixCSC) = map(+, A, B)
Expand Down

0 comments on commit 08ed837

Please sign in to comment.