Skip to content

Commit 5032224

Browse files
committed
Treat non-AbstractArrays as scalars in broadcast
1 parent 858371f commit 5032224

File tree

5 files changed

+39
-10
lines changed

5 files changed

+39
-10
lines changed

base/abstractarray.jl

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -148,10 +148,11 @@ abstract IndicesBehavior
148148
immutable IndicesStartAt1 <: IndicesBehavior end # indices 1:size(A,d)
149149
immutable IndicesUnitRange <: IndicesBehavior end # arb UnitRange indices
150150
immutable IndicesList <: IndicesBehavior end # indices like (:cat, :dog, :mouse)
151+
immutable NoIndices <: IndicesBehavior end # default
151152

152153
indicesbehavior(A::AbstractArray) = indicesbehavior(typeof(A))
153154
indicesbehavior{T<:AbstractArray}(::Type{T}) = IndicesStartAt1()
154-
indicesbehavior(::Number) = IndicesStartAt1()
155+
indicesbehavior(::Any) = NoIndices()
155156

156157
abstract IndicesPerformance
157158
immutable IndicesFast1D <: IndicesPerformance end # indices(A, d) is fast
@@ -178,6 +179,8 @@ start at something different from 1), it is equivalent to `indices(A,
178179
d)`.
179180
"""
180181
shape(a, d) = shape(indicesbehavior(a), a, d)
182+
shape(::NoIndices, a) = (1,)
183+
shape(::NoIndices, a, d) = (1,)
181184
shape(::IndicesStartAt1, a) = size(a)
182185
shape(::IndicesStartAt1, a, d) = size(a, d)
183186
shape(::IndicesBehavior, a) = indices(a)
@@ -412,8 +415,9 @@ end
412415
promote_indices(a::AbstractArray, b::AbstractArray) = _promote_indices(indicesbehavior(a), indicesbehavior(b), a, b)
413416
_promote_indices(::IndicesStartAt1, ::IndicesStartAt1, a, b) = a
414417
_promote_indices(::IndicesBehavior, ::IndicesBehavior, a, b) = throw(ArgumentError("types $(typeof(a)) and $(typeof(b)) do not have promote_indices defined"))
415-
promote_indices(a::Number, b::AbstractArray) = b
416-
promote_indices(a::AbstractArray, b::Number) = a
418+
promote_indices(a, b::AbstractArray) = b
419+
promote_indices(a::AbstractArray, b) = a
420+
promote_indices(a, b) = a
417421

418422
# Strip off the index-changing container---this assumes that `parent`
419423
# performs such an operation. TODO: since few things in Base need this, it
@@ -1459,9 +1463,14 @@ end
14591463
promote_eltype_op(::Any) = (@_pure_meta; Bottom)
14601464
promote_eltype_op{T}(op, ::AbstractArray{T}) = (@_pure_meta; promote_op(op, T))
14611465
promote_eltype_op{T}(op, ::T ) = (@_pure_meta; promote_op(op, T))
1466+
promote_eltype_op{T}(op, Ts::AbstractArray{DataType}, ::AbstractArray{T}) = typejoin((promote_op(op, S, T) for S in Ts)...)
1467+
promote_eltype_op{T}(op, Ts::AbstractArray{DataType}, ::T ) = typejoin((promote_op(op, S, T) for S in Ts)...)
14621468
promote_eltype_op{R,S}(op, ::AbstractArray{R}, ::AbstractArray{S}) = (@_pure_meta; promote_op(op, R, S))
14631469
promote_eltype_op{R,S}(op, ::AbstractArray{R}, ::S) = (@_pure_meta; promote_op(op, R, S))
14641470
promote_eltype_op{R,S}(op, ::R, ::AbstractArray{S}) = (@_pure_meta; promote_op(op, R, S))
1471+
promote_eltype_op{R,S}(op, ::Type{R}, ::AbstractArray{S}) = (@_pure_meta; promote_op(op, R, S))
1472+
promote_eltype_op{R,S}(op, ::Type{R}, ::S) = (@_pure_meta; promote_op(op, S, R))
1473+
promote_eltype_op{R,S}(op, ::R, ::S) = (@_pure_meta; promote_op(op, S, R))
14651474
promote_eltype_op(op, A, B, C, D...) = (@_pure_meta; promote_op(op, eltype(A), promote_eltype_op(op, B, C, D...)))
14661475

14671476
## 1 argument

base/broadcast.jl

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,9 @@ export broadcast_getindex, broadcast_setindex!
1313
## Calculate the broadcast shape of the arguments, or error if incompatible
1414
# array inputs
1515
broadcast_shape() = ()
16-
broadcast_shape(A) = shape(A)
17-
@inline broadcast_shape(A, B...) = broadcast_shape((), shape(A), map(shape, B)...)
16+
broadcast_shape(A) = ()
17+
broadcast_shape(A::AbstractArray) = shape(A)
18+
@inline broadcast_shape(A, B...) = broadcast_shape((), broadcast_shape(A), map(broadcast_shape, B)...)
1819
# shape inputs
1920
broadcast_shape(shape::Tuple) = shape
2021
@inline broadcast_shape(shape::Tuple, shape1::Tuple, shapes::Tuple...) = broadcast_shape(_bcs((), shape, shape1), shapes...)
@@ -40,7 +41,7 @@ _bcsm(a::Number, b::Number) = a == b || b == 1
4041
## Check that all arguments are broadcast compatible with shape
4142
# comparing one input against a shape
4243
check_broadcast_shape(shp) = nothing
43-
check_broadcast_shape(shp, A) = check_broadcast_shape(shp, shape(A))
44+
check_broadcast_shape(shp, A) = check_broadcast_shape(shp, broadcast_shape(A))
4445
check_broadcast_shape(::Tuple{}, ::Tuple{}) = nothing
4546
check_broadcast_shape(shp, ::Tuple{}) = nothing
4647
check_broadcast_shape(::Tuple{}, Ashp::Tuple) = throw(DimensionMismatch("cannot broadcast array to have fewer dimensions"))
@@ -63,8 +64,8 @@ end
6364
@inline _newindex(out, I) = out # can truncate if indexmap is shorter than I
6465
@inline _newindex(out, I, keep::Bool, indexmap...) = _newindex((out..., ifelse(keep, I[1], 1)), tail(I), indexmap...)
6566

66-
newindexer(sz, x::Number) = ()
67-
@inline newindexer(sz, A) = _newindexer(sz, size(A))
67+
newindexer(sz, x) = ()
68+
@inline newindexer(sz, A::AbstractArray) = _newindexer(sz, size(A))
6869
@inline _newindexer(sz, szA::Tuple{}) = ()
6970
@inline _newindexer(sz, szA) = (sz[1] == szA[1], _newindexer(tail(sz), tail(szA))...)
7071

@@ -79,6 +80,10 @@ const bitcache_size = 64 * bitcache_chunks # do not change this
7980
dumpbitcache(Bc::Vector{UInt64}, bind::Int, C::Vector{Bool}) =
8081
Base.copy_to_bitarray_chunks!(Bc, ((bind - 1) << 6) + 1, C, 1, min(bitcache_size, (length(Bc)-bind+1) << 6))
8182

83+
# Since we can't make T[1] return T, use this inside `_broadcast!`
84+
@inline _broadcast_getvals(A, I) = A
85+
@inline _broadcast_getvals(A::AbstractArray, I) = A[I]
86+
8287
## Broadcasting core
8388
# nargs encodes the number of As arguments (which matches the number
8489
# of indexmaps). The first two type parameters are to ensure specialization.
@@ -92,7 +97,7 @@ dumpbitcache(Bc::Vector{UInt64}, bind::Int, C::Vector{Bool}) =
9297
# reverse-broadcast the indices
9398
@nexprs $nargs i->(I_i = newindex(I, imap_i))
9499
# extract array values
95-
@nexprs $nargs i->(@inbounds val_i = A_i[I_i])
100+
@nexprs $nargs i->(@inbounds val_i = _broadcast_getvals(A_i, I_i))
96101
# call the function and store the result
97102
@inbounds B[I] = @ncall $nargs f val
98103
end

base/float.jl

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,17 @@ promote_rule(::Type{Float64}, ::Type{Float32}) = Float64
199199
widen(::Type{Float16}) = Float32
200200
widen(::Type{Float32}) = Float64
201201

202+
promote_op{T<:Union{Float32,Float64}}(::typeof(trunc), ::Type{Signed}, ::Type{T}) = Int
203+
promote_op{T<:Union{Float32,Float64}}(::typeof(trunc), ::Type{Unsigned}, ::Type{T}) = UInt
204+
for Ti in (Int8, Int16, Int32, Int64, Int128, UInt8, UInt16, UInt32, UInt64, UInt128)
205+
for Tf in (Float32, Float64)
206+
@eval promote_op(::$(typeof(trunc)), ::Type{$Ti}, ::Type{$Tf}) = $Ti
207+
end
208+
end
209+
for f in (ceil, floor, round)
210+
@eval promote_op{R,S}(::$(typeof(f)), ::Type{R}, ::Type{S}) = promote_op($trunc, R, S)
211+
end
212+
202213
## floating point arithmetic ##
203214
-(x::Float32) = box(Float32,neg_float(unbox(Float32,x)))
204215
-(x::Float64) = box(Float64,neg_float(unbox(Float64,x)))

base/parse.jl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,3 +194,6 @@ function parse(str::AbstractString; raise::Bool=true)
194194
end
195195
return ex
196196
end
197+
198+
promote_op{R<:AbstractFloat,S<:AbstractString}(::typeof(parse), ::Type{R}, ::Type{S}) = R
199+
promote_op{R<:Integer,S<:Union{AbstractString,Char}}(::typeof(parse), ::Type{R}, ::Type{S}) = R

base/promotion.jl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -222,8 +222,9 @@ minmax(x::Real, y::Real) = minmax(promote(x, y)...)
222222
# for the multiplication of two types,
223223
# promote_op{R<:MyType,S<:MyType}(::typeof(*), ::Type{R}, ::Type{S}) = MyType{multype(R,S)}
224224
promote_op(::Any) = (@_pure_meta; Bottom)
225-
promote_op(::Any, T) = (@_pure_meta; T)
225+
promote_op(::Any, T) = (@_pure_meta; Bottom)
226226
promote_op{T}(::Type{T}, ::Any) = (@_pure_meta; T)
227+
promote_op{R,S}(::typeof(convert), ::Type{R}, ::Type{S}) = (@_pure_meta; R)
227228
promote_op{R,S}(::Any, ::Type{R}, ::Type{S}) = (@_pure_meta; promote_type(R, S))
228229
promote_op(op, T, S, U, V...) = (@_pure_meta; promote_op(op, T, promote_op(op, S, U, V...)))
229230

0 commit comments

Comments
 (0)