Skip to content

Commit

Permalink
treat dot operators as dot calls, e.g. x .+ y --> (+).(x,y)
Browse files Browse the repository at this point in the history
syntax deprecation for .op method definitions, and removed these deprecations from Base

use range + 1, not range .+ 1, to make sure we call the specialized + method that produces a range (not an array)

add depwarn for using .+ etc as function objects

support dotted pipe operators

eliminate most broadcast(::typeof(func), ...) methods, since fusion makes them ~useless; make broadcast produce a BitArray if a Bool array is expected

test for .op loop fusion

docs for new broadcasting dot-operator behavior

define broadcast! earlier (fixes JuliaLang#18462)

use specialized code for non-fusing array ± scalar, for performance

work around slight slowdown in Diagonal due to broadcast vs. broadcast_elwise_op

closes JuliaLang#11053
  • Loading branch information
stevengj committed Dec 18, 2016
1 parent 1f8006d commit 2c4e353
Show file tree
Hide file tree
Showing 45 changed files with 495 additions and 893 deletions.
15 changes: 14 additions & 1 deletion NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ New language features
Language changes
----------------

* Multiline and singleline nonstandard command literals have been added. A
* Multi-line and single-line nonstandard command literals have been added. A
nonstandard command literal is like a nonstandard string literal, but the
syntax uses backquotes (``` ` ```) instead of double quotes, and the
resulting macro called is suffixed with `_cmd`. For instance, the syntax
Expand All @@ -17,6 +17,11 @@ Language changes
module. For instance, `Base.r"x"` is now parsed as `Base.@r_str "x"`.
Previously, this syntax parsed as an implicit multiplication. ([#18690])

* For every binary operator ``, `a .⨳ b` is now automatically equivalent to
the `broadcast` call `(⨳).(a, b)`. Hence, one no longer defines methods
for `.*` etcetera. This also means that "dot operations" automatically
fuse into a single loop, along with other dot calls `f.(x)`. ([#17623])

Breaking changes
----------------

Expand All @@ -34,6 +39,14 @@ This section lists changes that do not have deprecation warnings.
* `broadcast` now handles tuples, and treats any argument that is not a tuple
or an array as a "scalar" ([#16986]).

* `broadcast` now produces a `BitArray` instead of `Array{Bool}` for
functions yielding a boolean result. If you want `Array{Bool}`, use
`broadcast!` or `.=` ([#17623]).

* Operations like `.+` and `.*` on `Range` objects are now generic
`broadcast` calls (see above) and produce an `Array`. If you want
a `Range` result, use `+` and `*`, etcetera ([#17623]).

Library improvements
--------------------

Expand Down
2 changes: 1 addition & 1 deletion base/LineEdit.jl
Original file line number Diff line number Diff line change
Expand Up @@ -437,7 +437,7 @@ function splice_buffer!{T<:Integer}(buf::IOBuffer, r::UnitRange{T}, ins::Abstrac
elseif pos > last(r)
seek(buf, pos - length(r))
end
splice!(buf.data, r .+ 1, ins.data) # position(), etc, are 0-indexed
splice!(buf.data, r + 1, ins.data) # position(), etc, are 0-indexed
buf.size = buf.size + sizeof(ins) - length(r)
seek(buf, position(buf) + sizeof(ins))
end
Expand Down
9 changes: 0 additions & 9 deletions base/abstractarraymath.jl
Original file line number Diff line number Diff line change
Expand Up @@ -91,15 +91,6 @@ imag{T<:Real}(x::AbstractArray{T}) = zero(x)
+{T<:Number}(x::AbstractArray{T}) = x
*{T<:Number}(x::AbstractArray{T,2}) = x

## Binary arithmetic operators ##

*(A::Number, B::AbstractArray) = A .* B
*(A::AbstractArray, B::Number) = A .* B

/(A::AbstractArray, B::Number) = A ./ B

\(A::Number, B::AbstractArray) = B ./ A

# index A[:,:,...,i,:,:,...] where "i" is in dimension "d"

"""
Expand Down
28 changes: 10 additions & 18 deletions base/arraymath.jl
Original file line number Diff line number Diff line change
Expand Up @@ -60,10 +60,10 @@ end
promote_array_type(F, ::Type, ::Type, T::Type) = T
promote_array_type{S<:Real, A<:AbstractFloat}(F, ::Type{S}, ::Type{A}, ::Type) = A
promote_array_type{S<:Integer, A<:Integer}(F, ::Type{S}, ::Type{A}, ::Type) = A
promote_array_type{S<:Integer, A<:Integer}(::typeof(./), ::Type{S}, ::Type{A}, T::Type) = T
promote_array_type{S<:Integer, A<:Integer}(::typeof(.\), ::Type{S}, ::Type{A}, T::Type) = T
promote_array_type{S<:Integer}(::typeof(./), ::Type{S}, ::Type{Bool}, T::Type) = T
promote_array_type{S<:Integer}(::typeof(.\), ::Type{S}, ::Type{Bool}, T::Type) = T
promote_array_type{S<:Integer, A<:Integer}(::typeof(/), ::Type{S}, ::Type{A}, T::Type) = T
promote_array_type{S<:Integer, A<:Integer}(::typeof(\), ::Type{S}, ::Type{A}, T::Type) = T
promote_array_type{S<:Integer}(::typeof(/), ::Type{S}, ::Type{Bool}, T::Type) = T
promote_array_type{S<:Integer}(::typeof(\), ::Type{S}, ::Type{Bool}, T::Type) = T
promote_array_type{S<:Integer}(F, ::Type{S}, ::Type{Bool}, T::Type) = T

for f in (:+, :-, :div, :mod, :&, :|, :xor)
Expand All @@ -89,9 +89,9 @@ function _elementwise{T}(op, ::Type{T}, A::AbstractArray, B::AbstractArray)
return F
end

for f in (:.+, :.-, :.*, :./, :.\, :.^, :, :.%, :.<<, :.>>, :div, :mod, :rem, :&, :|, :xor)
@eval begin
function ($f){T}(A::Number, B::AbstractArray{T})
for f in (:div, :mod, :rem, :&, :|, :xor, :/, :\, :*, :+, :-)
if f != :/
@eval function ($f){T}(A::Number, B::AbstractArray{T})
R = promote_op($f, typeof(A), T)
S = promote_array_type($f, typeof(A), T, R)
S === Any && return [($f)(A, b) for b in B]
Expand All @@ -108,7 +108,9 @@ for f in (:.+, :.-, :.*, :./, :.\, :.^, :.÷, :.%, :.<<, :.>>, :div, :mod, :rem,
end
return F
end
function ($f){T}(A::AbstractArray{T}, B::Number)
end
if f != :\
@eval function ($f){T}(A::AbstractArray{T}, B::Number)
R = promote_op($f, T, typeof(B))
S = promote_array_type($f, typeof(B), T, R)
S === Any && return [($f)(a, B) for a in A]
Expand All @@ -128,16 +130,6 @@ for f in (:.+, :.-, :.*, :./, :.\, :.^, :.÷, :.%, :.<<, :.>>, :div, :mod, :rem,
end
end

# familiar aliases for broadcasting operations of array ± scalar (#7226):
(+)(A::AbstractArray{Bool},x::Bool) = A .+ x
(+)(x::Bool,A::AbstractArray{Bool}) = x .+ A
(-)(A::AbstractArray{Bool},x::Bool) = A .- x
(-)(x::Bool,A::AbstractArray{Bool}) = x .- A
(+)(A::AbstractArray,x::Number) = A .+ x
(+)(x::Number,A::AbstractArray) = x .+ A
(-)(A::AbstractArray,x::Number) = A .- x
(-)(x::Number,A::AbstractArray) = x .- A

## data movement ##

function flipdim{T}(A::Array{T}, d::Integer)
Expand Down
97 changes: 0 additions & 97 deletions base/bitarray.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1136,9 +1136,6 @@ function empty!(B::BitVector)
return B
end

## Misc functions
broadcast(::typeof(abs), B::BitArray) = copy(B)

## Unary operators ##

function (-)(B::BitArray)
Expand Down Expand Up @@ -1232,35 +1229,6 @@ for f in (:+, :-)
end
end

for (f) in (:.+, :.-)
for (arg1, arg2, T, t) in ((:(B::BitArray), :(x::Bool) , Int , (:b, :x)),
(:(B::BitArray), :(x::Number) , :(Bool, typeof(x)), (:b, :x)),
(:(x::Bool) , :(B::BitArray), Int , (:x, :b)),
(:(x::Number) , :(B::BitArray), :(typeof(x), Bool), (:x, :b)))
@eval function ($f)($arg1, $arg2)
$(if T === Int
quote
r = Array{Int}(size(B))
end
else
quote
T = promote_op($f, $(T.args[1]), $(T.args[2]))
T === Any && return [($f)($(t[1]), $(t[2])) for b in B]
r = Array{T}(size(B))
end
end)
bi = start(B)
ri = 1
while !done(B, bi)
b, bi = next(B, bi)
@inbounds r[ri] = ($f)($(t[1]), $(t[2]))
ri += 1
end
return r
end
end
end

for f in (:/, :\)
@eval begin
($f)(A::BitArray, B::BitArray) = ($f)(Array(A), Array(B))
Expand Down Expand Up @@ -1359,71 +1327,6 @@ for f in (:&, :|, :xor)
end
end

function (.^)(B::BitArray, x::Bool)
x ? copy(B) : trues(size(B))
end
function (.^)(x::Bool, B::BitArray)
x ? trues(size(B)) : ~B
end
function (.^)(x::Number, B::BitArray)
z = x ^ false
u = x ^ true
reshape([ B[i] ? u : z for i = 1:length(B) ], size(B))
end
function (.^)(B::BitArray, x::Integer)
x == 0 && return trues(size(B))
x < 0 && throw(DomainError())
return copy(B)
end
function (.^){T<:Number}(B::BitArray, x::T)
x == 0 && return ones(typeof(true ^ x), size(B))
T <: Real && x > 0 && return convert(Array{T}, B)

z = nothing
u = nothing
zerr = nothing
uerr = nothing
try
z = false^x
catch err
zerr = err
end
try
u = true^x
catch err
uerr = err
end
if zerr === nothing && uerr === nothing
t = promote_type(typeof(z), typeof(u))
elseif zerr === nothing
t = typeof(z)
else
t = typeof(u)
end
F = Array{t}(size(B))
for i = 1:length(B)
if B[i]
if uerr === nothing
F[i] = u
else
throw(uerr)
end
else
if zerr === nothing
F[i] = z
else
throw(zerr)
end
end
end
return F
end

(.*)(x::Bool, B::BitArray) = x & B
(.*)(B::BitArray, x::Bool) = B & x
(.*)(x::Number, B::BitArray) = x .* Array(B)
(.*)(B::BitArray, x::Number) = Array(B) .* x

## promotion to complex ##

# TODO?
Expand Down
Loading

0 comments on commit 2c4e353

Please sign in to comment.