diff --git a/base/arraymath.jl b/base/arraymath.jl index 799079cbb7178..235bffe676296 100644 --- a/base/arraymath.jl +++ b/base/arraymath.jl @@ -35,26 +35,19 @@ function !(A::AbstractArray{Bool}) end ## Binary arithmetic operators ## - -promote_array_type{Scalar, Arry}(F, ::Type{Scalar}, ::Type{Arry}) = promote_op(F, Scalar, Arry) -promote_array_type{S<:Real, A<:AbstractFloat}(F, ::Type{S}, ::Type{A}) = A -promote_array_type{S<:Integer, A<:Integer}(F, ::Type{S}, ::Type{A}) = A -promote_array_type{S<:Integer}(F, ::Type{S}, ::Type{Bool}) = S -promote_array_type(F, ::Type{Bool}, ::Type{Bool}) = promote_op(F, Bool, Bool) - -# Handle operations that return different types -./(x::Number, Y::AbstractArray) = - reshape([ x ./ y for y in Y ], size(Y)) -./(X::AbstractArray, y::Number) = - reshape([ x ./ y for x in X ], size(X)) -.\(x::Number, Y::AbstractArray) = - reshape([ x .\ y for y in Y ], size(Y)) -.\(X::AbstractArray, y::Number) = - reshape([ x .\ y for x in X ], size(X)) -.^(x::Number, Y::AbstractArray) = - reshape([ x ^ y for y in Y ], size(Y)) -.^(X::AbstractArray, y::Number ) = - reshape([ x ^ y for x in X ], size(X)) +@pure promote_array_type{S<:Number, A<:AbstractArray}(F, ::Type{S}, ::Type{A}) = + promote_array_type(F, S, eltype(A), promote_op(F, S, eltype(A))) +@pure promote_array_type{S<:Number, A<:AbstractArray}(F, ::Type{A}, ::Type{S}) = + promote_array_type(F, S, eltype(A), promote_op(F, eltype(A), S)) + +@pure promote_array_type{S, A, P}(F, ::Type{S}, ::Type{A}, ::Type{P}) = P +@pure promote_array_type{S<:Real, A<:AbstractFloat, P}(F, ::Type{S}, ::Type{A}, ::Type{P}) = A +@pure promote_array_type{S<:Integer, A<:Integer, P}(F::typeof(./), ::Type{S}, ::Type{A}, ::Type{P}) = P +@pure promote_array_type{S<:Integer, A<:Integer, P}(F::typeof(.\), ::Type{S}, ::Type{A}, ::Type{P}) = P +@pure promote_array_type{S<:Integer, A<:Integer, P}(F, ::Type{S}, ::Type{A}, ::Type{P}) = A +@pure promote_array_type{S<:Integer, P}(F::typeof(./), ::Type{S}, ::Type{Bool}, ::Type{P}) = P +@pure promote_array_type{S<:Integer, P}(F::typeof(.\), ::Type{S}, ::Type{Bool}, ::Type{P}) = P +@pure promote_array_type{S<:Integer, P}(F, ::Type{S}, ::Type{Bool}, ::Type{P}) = P for f in (:+, :-, :div, :mod, :&, :|, :$) @eval begin @@ -88,17 +81,17 @@ for f in (:+, :-, :div, :mod, :&, :|, :$) end end end -for f in (:.+, :.-, :.*, :.÷, :.%, :.<<, :.>>, :div, :mod, :rem, :&, :|, :$) +for f in (:.+, :.-, :.*, :./, :.\, :.^, :.÷, :.%, :.<<, :.>>, :div, :mod, :rem, :&, :|, :$) @eval begin function ($f){T}(A::Number, B::AbstractArray{T}) - F = similar(B, promote_array_type($f,typeof(A),T)) + F = similar(B, promote_array_type($f,typeof(A),typeof(B))) for (iF, iB) in zip(eachindex(F), eachindex(B)) @inbounds F[iF] = ($f)(A, B[iB]) end return F end function ($f){T}(A::AbstractArray{T}, B::Number) - F = similar(A, promote_array_type($f,typeof(B),T)) + F = similar(A, promote_array_type($f,typeof(A),typeof(B))) for (iF, iA) in zip(eachindex(F), eachindex(A)) @inbounds F[iF] = ($f)(A[iA], B) end diff --git a/base/bitarray.jl b/base/bitarray.jl index f49f53b8385cd..6e13c1c71130c 100644 --- a/base/bitarray.jl +++ b/base/bitarray.jl @@ -1041,9 +1041,9 @@ for f in (:+, :-) end for (f) in (:.+, :.-) for (arg1, arg2, T, fargs) in ((:(B::BitArray), :(x::Bool) , Int , :(b, x)), - (:(B::BitArray), :(x::Number) , :(promote_array_type($f, typeof(x), Bool)), :(b, x)), + (:(B::BitArray), :(x::Number) , :(promote_array_type($f, BitArray, typeof(x))), :(b, x)), (:(x::Bool) , :(B::BitArray), Int , :(x, b)), - (:(x::Number) , :(B::BitArray), :(promote_array_type($f, typeof(x), Bool)), :(x, b))) + (:(x::Number) , :(B::BitArray), :(promote_array_type($f, typeof(x), BitArray)), :(x, b))) @eval function ($f)($arg1, $arg2) r = Array($T, size(B)) bi = start(B) @@ -1082,7 +1082,7 @@ function div(x::Bool, B::BitArray) end function div(x::Number, B::BitArray) all(B) || throw(DivideError()) - pt = promote_array_type(div, typeof(x), Bool) + pt = promote_array_type(div, typeof(x), BitArray) y = div(x, true) reshape(pt[ y for i = 1:length(B) ], size(B)) end @@ -1103,7 +1103,7 @@ function mod(x::Bool, B::BitArray) end function mod(x::Number, B::BitArray) all(B) || throw(DivideError()) - pt = promote_array_type(mod, typeof(x), Bool) + pt = promote_array_type(mod, typeof(x), BitArray) y = mod(x, true) reshape(pt[ y for i = 1:length(B) ], size(B)) end @@ -1111,7 +1111,7 @@ end for f in (:div, :mod) @eval begin function ($f)(B::BitArray, x::Number) - F = Array(promote_array_type($f, typeof(x), Bool), size(B)) + F = Array(promote_array_type($f, BitArray, typeof(x)), size(B)) for i = 1:length(F) F[i] = ($f)(B[i], x) end diff --git a/base/complex.jl b/base/complex.jl index df112a2b21dc1..2e88f8efa75e0 100644 --- a/base/complex.jl +++ b/base/complex.jl @@ -32,6 +32,10 @@ promote_op{T<:Real,S<:Real}(op, ::Type{Complex{T}}, ::Type{S}) = Complex{promote_op(op,T,S)} promote_op{T<:Real,S<:Real}(op, ::Type{T}, ::Type{Complex{S}}) = Complex{promote_op(op,T,S)} +promote_op{T<:Integer,S<:Integer}(::typeof(^), ::Type{T}, ::Type{Complex{S}}) = + Complex{Float64} +promote_op{T<:Integer,S<:Integer}(::typeof(.^), ::Type{T}, ::Type{Complex{S}}) = + Complex{Float64} widen{T}(::Type{Complex{T}}) = Complex{widen(T)} @@ -803,7 +807,7 @@ big{T<:AbstractFloat,N}(A::AbstractArray{Complex{T},N}) = convert(AbstractArray{ ## promotion to complex ## -promote_array_type{S<:Union{Complex, Real}, AT<:AbstractFloat}(F, ::Type{S}, ::Type{Complex{AT}}) = Complex{AT} +promote_array_type{S<:Union{Complex, Real}, AT<:AbstractFloat, P}(F, ::Type{S}, ::Type{Complex{AT}}, ::Type{P}) = Complex{AT} function complex{S<:Real,T<:Real}(A::AbstractArray{S}, B::AbstractArray{T}) if size(A) != size(B); throw(DimensionMismatch()); end diff --git a/test/broadcast.jl b/test/broadcast.jl index 565160672b570..a3904ecc9a399 100644 --- a/test/broadcast.jl +++ b/test/broadcast.jl @@ -116,3 +116,14 @@ rt = Base.return_types(broadcast, Tuple{Function, Array{Float64, 3}, Array{Int, @test length(rt) == 1 && rt[1] == Array{Float64, 3} rt = Base.return_types(broadcast!, Tuple{Function, Array{Float64, 3}, Array{Float64, 3}, Array{Int, 1}}) @test length(rt) == 1 && rt[1] == Array{Float64, 3} + +# issue 14725 +let a = Number[2, 2.0, 4//2, 2+0im] / 2 + @test eltype(a) == Number +end +let a = Real[2, 2.0, 4//2] / 2 + @test eltype(a) == Real +end +let a = Real[2, 2.0, 4//2] / 2.0 + @test eltype(a) == Real +end