Skip to content

Commit

Permalink
Default reduce promotion to system default
Browse files Browse the repository at this point in the history
  • Loading branch information
felixrehren authored and JeffBezanson committed Oct 15, 2017
1 parent b76c0fa commit e2b9834
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 20 deletions.
28 changes: 17 additions & 11 deletions base/reduce.jl
Expand Up @@ -12,15 +12,18 @@ const SmallSigned = Union{Int8,Int16,Int32}
const SmallUnsigned = Union{UInt8,UInt16,UInt32}
end

const CommonReduceResult = Union{UInt64,UInt128,Int64,Int128,Float32,Float64}
const WidenReduceResult = Union{SmallSigned, SmallUnsigned, Float16}
const CommonReduceResult = Union{UInt64,UInt128,Int64,Int128,Float16,Float32,Float64}
const WidenReduceResult = Union{SmallSigned, SmallUnsigned}

promote_sys_size{T}(::Type{T}) = T
promote_sys_size{T<:SmallSigned}(::Type{T}) = Int
promote_sys_size{T<:SmallUnsigned}(::Type{T}) = UInt
# r_promote_type: promote T to the type of reduce(op, ::Array{T})
# (some "extra" methods are required here to avoid ambiguity warnings)
r_promote_type(op, ::Type{T}) where {T} = T
r_promote_type(op, ::Type{T}) where {T<:WidenReduceResult} = widen(T)
r_promote_type(::typeof(+), ::Type{T}) where {T<:WidenReduceResult} = widen(T)
r_promote_type(::typeof(*), ::Type{T}) where {T<:WidenReduceResult} = widen(T)
r_promote_type(op, ::Type{T}) where {T<:WidenReduceResult} = promote_sys_size(T)
r_promote_type(::typeof(+), ::Type{T}) where {T<:WidenReduceResult} = promote_sys_size(T)
r_promote_type(::typeof(*), ::Type{T}) where {T<:WidenReduceResult} = promote_sys_size(T)
r_promote_type(::typeof(+), ::Type{T}) where {T<:Number} = typeof(zero(T)+zero(T))
r_promote_type(::typeof(*), ::Type{T}) where {T<:Number} = typeof(one(T)*one(T))
r_promote_type(::typeof(scalarmax), ::Type{T}) where {T<:WidenReduceResult} = T
Expand Down Expand Up @@ -296,21 +299,24 @@ mapreduce(f, op, a::Number) = f(a)
"""
reduce(op, v0, itr)
Reduce the given collection `ìtr` with the given binary operator `op`. `v0` must be a
Reduce the given collection `itr` with the given binary operator `op`. `v0` must be a
neutral element for `op` that will be returned for empty collections. It is unspecified
whether `v0` is used for non-empty collections.
Reductions for certain commonly-used operators have special implementations which should be
used instead: `maximum(itr)`, `minimum(itr)`, `sum(itr)`, `prod(itr)`, `any(itr)`,
`all(itr)`.
The return type is `Int` (`UInt`) for (un)signed integers of less than system word size.
For all other arguments, a common return type is found to which all arguments are promoted.
Reductions for certain commonly-used operators may have special implementations, and
should be used instead: `maximum(itr)`, `minimum(itr)`, `sum(itr)`, `prod(itr)`,
`any(itr)`, `all(itr)`.
The associativity of the reduction is implementation dependent. This means that you can't
use non-associative operations like `-` because it is undefined whether `reduce(-,[1,2,3])`
should be evaluated as `(1-2)-3` or `1-(2-3)`. Use [`foldl`](@ref) or
[`foldr`](@ref) instead for guaranteed left or right associativity.
Some operations accumulate error, and parallelism will also be easier if the reduction can
be executed in groups. Future versions of Julia might change the algorithm. Note that the
Some operations accumulate error. Parallelism will be easier if the reduction can be
executed in groups. Future versions of Julia might change the algorithm. Note that the
elements are not reordered if you use an ordered collection.
# Examples
Expand Down
18 changes: 9 additions & 9 deletions test/reduce.jl
Expand Up @@ -2,7 +2,7 @@

# fold(l|r) & mapfold(l|r)
@test foldl(+, Int64[]) === Int64(0) # In reference to issues #7465/#20144 (PR #20160)
@test foldl(+, Int16[]) === Int32(0)
@test foldl(+, Int16[]) === Int(0)
@test foldl(-, 1:5) == -13
@test foldl(-, 10, 1:5) == -5

Expand All @@ -19,7 +19,7 @@
@test Base.mapfoldl((x)-> x true, |, false, [true false true false false]) == true

@test foldr(+, Int64[]) === Int64(0) # In reference to issue #20144 (PR #20160)
@test foldr(+, Int16[]) === Int32(0)
@test foldr(+, Int16[]) === Int(0)
@test foldr(-, 1:5) == 3
@test foldr(-, 10, 1:5) == -7
@test foldr(+, [1]) == 1 # Issue #21493
Expand All @@ -29,7 +29,7 @@

# reduce
@test reduce(+, Int64[]) === Int64(0) # In reference to issue #20144 (PR #20160)
@test reduce(+, Int16[]) === Int32(0)
@test reduce(+, Int16[]) === Int(0)
@test reduce((x,y)->"($x+$y)", 9:11) == "((9+10)+11)"
@test reduce(max, [8 6 7 5 3 0 9]) == 9
@test reduce(+, 1000, 1:5) == (1000 + 1 + 2 + 3 + 4 + 5)
Expand Down Expand Up @@ -70,15 +70,15 @@

# sum

@test sum(Int8[]) === Int32(0)
@test sum(Int8[]) === Int(0)
@test sum(Int[]) === Int(0)
@test sum(Float64[]) === 0.0

@test sum(Int8(3)) === Int8(3)
@test sum(3) === 3
@test sum(3.0) === 3.0

@test sum([Int8(3)]) === Int32(3)
@test sum([Int8(3)]) === Int(3)
@test sum([3]) === 3
@test sum([3.0]) === 3.0

Expand Down Expand Up @@ -138,11 +138,11 @@ end
# prod

@test prod(Int[]) === 1
@test prod(Int8[]) === Int32(1)
@test prod(Int8[]) === Int(1)
@test prod(Float64[]) === 1.0

@test prod([3]) === 3
@test prod([Int8(3)]) === Int32(3)
@test prod([Int8(3)]) === Int(3)
@test prod([3.0]) === 3.0

@test prod(z) === 120
Expand All @@ -157,8 +157,8 @@ end
prod2(itr) = invoke(prod, Tuple{Any}, itr)
@test prod(Int[]) === prod2(Int[]) === 1
@test prod(Int[7]) === prod2(Int[7]) === 7
@test typeof(prod(Int8[])) == typeof(prod(Int8[1])) == typeof(prod(Int8[1, 7])) == Int32
@test typeof(prod2(Int8[])) == typeof(prod2(Int8[1])) == typeof(prod2(Int8[1 7])) == Int32
@test typeof(prod(Int8[])) == typeof(prod(Int8[1])) == typeof(prod(Int8[1, 7])) == Int
@test typeof(prod2(Int8[])) == typeof(prod2(Int8[1])) == typeof(prod2(Int8[1 7])) == Int

# maximum & minimum & extrema

Expand Down

0 comments on commit e2b9834

Please sign in to comment.