diff --git a/base/broadcast.jl b/base/broadcast.jl index fbeb15b1a3542c..92dbd6839fb471 100644 --- a/base/broadcast.jl +++ b/base/broadcast.jl @@ -3,7 +3,7 @@ module Broadcast using Base.Cartesian -using Base: @pure, promote_eltype_op, _promote_op, linearindices, tail, OneTo, to_shape, +using Base: promote_eltype_op, linearindices, tail, OneTo, to_shape, _msk_end, unsafe_bitgetindex, bitcache_chunks, bitcache_size, dumpbitcache import Base: .+, .-, .*, ./, .\, .//, .==, .<, .!=, .<=, .รท, .%, .<<, .>>, .^ import Base: broadcast @@ -257,13 +257,23 @@ end @inline broadcast_elwise_op(f, As...) = broadcast!(f, similar(Array{promote_eltype_op(f, As...)}, broadcast_indices(As...)), As...) -@pure typestuple(a) = Tuple{eltype(a)} -@pure typestuple(T::Type) = Tuple{Type{T}} -@pure typestuple(a, b...) = Tuple{typestuple(a).types..., typestuple(b...).types...} +typestuple(a) = (Base.@_pure_meta; Tuple{eltype(a)}) +typestuple(T::Type) = (Base.@_pure_meta; Tuple{Type{T}}) +typestuple(a, b...) = (Base.@_pure_meta; Tuple{typestuple(a).types..., typestuple(b...).types...}) + +ftype(f, A) = typeof(a->f(a)) +ftype(f, A...) = typeof(a->f(a...)) +ftype(T::Type, A...) = Type{T} +ziptype(A) = (Base.@_pure_meta; Tuple{eltype(A)}) +ziptype(A, B) = (Base.@_pure_meta; Iterators.Zip2{ziptype(A), ziptype(B)}) +@inline ziptype(A, B, C, D...) = Iterators.Zip{ziptype(A),ziptype(B, C, D...)} + +_broadcast_type(f, T::Type, As...) = Base._return_type(f, typestuple(T, As...)) +_broadcast_type(f, A, Bs...) = Base._default_eltype(Base.Generator{ziptype(A, Bs...), ftype(f, A, Bs...)}) # broadcast methods that dispatch on the type of the final container @inline function broadcast_c(f, ::Type{Array}, A, Bs...) - T = _promote_op(f, typestuple(A, Bs...)) + T = _broadcast_type(f, A, Bs...) shape = broadcast_indices(A, Bs...) iter = CartesianRange(shape) if isleaftype(T) diff --git a/base/promotion.jl b/base/promotion.jl index 9b639d84c16d3c..6bc1aa88f84390 100644 --- a/base/promotion.jl +++ b/base/promotion.jl @@ -223,21 +223,22 @@ minmax(x::Real, y::Real) = minmax(promote(x, y)...) _default_type(T::Type) = (@_pure_meta; T) if isdefined(Core, :Inference) - _promote_op(f::ANY, t::ANY) = Core.Inference.return_type(f, t) + _return_type(f::ANY, t::ANY) = Core.Inference.return_type(f, t) else - _promote_op(f::ANY, t::ANY) = Any + _return_type(f::ANY, t::ANY) = Any end -promote_op(::Any...) = (@_pure_meta; Any) function promote_op{S}(f, ::Type{S}) @_inline_meta - T = _promote_op(f, Tuple{_default_type(S)}) + Z = Tuple{_default_type(S)} + T = _default_eltype(Generator{Z, typeof(f)}) isleaftype(S) && return isleaftype(T) ? T : Any return typejoin(S, T) end function promote_op{R,S}(f, ::Type{R}, ::Type{S}) @_inline_meta - T = _promote_op(f, Tuple{_default_type(R), _default_type(S)}) + Z = Iterators.Zip2{Tuple{_default_type(R)}, Tuple{_default_type(S)}} + T = _default_eltype(Generator{Z, typeof(a -> f(a...))}) isleaftype(R) && isleaftype(S) && return isleaftype(T) ? T : Any return typejoin(R, S, T) end diff --git a/base/sparse/sparse.jl b/base/sparse/sparse.jl index a1b86b7fa3f9e4..29b591225c91dc 100644 --- a/base/sparse/sparse.jl +++ b/base/sparse/sparse.jl @@ -26,7 +26,7 @@ import Base: @get!, acos, acosd, acot, acotd, acsch, asech, asin, asind, asinh, rotl90, rotr90, round, scale!, setindex!, similar, size, transpose, tril, triu, vec, permute!, map, map! -import Base.Broadcast: broadcast_indices +import Base.Broadcast: _broadcast_type, broadcast_indices export AbstractSparseArray, AbstractSparseMatrix, AbstractSparseVector, SparseMatrixCSC, SparseVector, blkdiag, dense, droptol!, dropzeros!, dropzeros, diff --git a/base/sparse/sparsematrix.jl b/base/sparse/sparsematrix.jl index 31dda9535f4366..1d81eb94c4a0aa 100644 --- a/base/sparse/sparsematrix.jl +++ b/base/sparse/sparsematrix.jl @@ -1464,7 +1464,6 @@ _maxnnzfrom(Cm, Cn, A) = nnz(A) * div(Cm, A.m) * div(Cn, A.n) @inline _maxnnzfrom_each(Cm, Cn, As) = (_maxnnzfrom(Cm, Cn, first(As)), _maxnnzfrom_each(Cm, Cn, tail(As))...) @inline _unchecked_maxnnzbcres(Cm, Cn, As) = min(Cm * Cn, sum(_maxnnzfrom_each(Cm, Cn, As))) @inline _checked_maxnnzbcres(Cm, Cn, As...) = Cm != 0 && Cn != 0 ? _unchecked_maxnnzbcres(Cm, Cn, As) : 0 -_broadcast_type(f, As...) = Base._promote_op(f, Base.Broadcast.typestuple(As...)) # _map_zeropres!/_map_notzeropres! specialized for a single sparse matrix "Stores only the nonzero entries of `map(f, Matrix(A))` in `C`." diff --git a/test/broadcast.jl b/test/broadcast.jl index bd20d69c5a20c3..9727f48f06bada 100644 --- a/test/broadcast.jl +++ b/test/broadcast.jl @@ -355,3 +355,7 @@ StrangeType18623(x,y) = (x,y) # 19419 @test @inferred(broadcast(round, Int, [1])) == [1] + +let f(A, n) = broadcast(x -> +(x, n), A) + @test @inferred(f([1.0], 1)) == [2.0] +end