From d58e889f002290e33217e78557b07606918e38e7 Mon Sep 17 00:00:00 2001 From: felix Date: Tue, 14 Feb 2017 08:36:09 +0000 Subject: [PATCH 1/4] promote type of `reduce` to system size --- base/reduce.jl | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/base/reduce.jl b/base/reduce.jl index eafd39bb173de..0d78fcb129fda 100644 --- a/base/reduce.jl +++ b/base/reduce.jl @@ -13,20 +13,23 @@ const SmallUnsigned = Union{UInt8,UInt16,UInt32} end const CommonReduceResult = Union{UInt64,UInt128,Int64,Int128,Float32,Float64} -const WidenReduceResult = Union{SmallSigned, SmallUnsigned, Float16} +const SmallReduceResult = Union{SmallSigned, SmallUnsigned, Float16} +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{T}(op, ::Type{T}) = T -r_promote_type{T<:WidenReduceResult}(op, ::Type{T}) = widen(T) -r_promote_type{T<:WidenReduceResult}(::typeof(+), ::Type{T}) = widen(T) -r_promote_type{T<:WidenReduceResult}(::typeof(*), ::Type{T}) = widen(T) +r_promote_type{T<:SmallReduceResult}(op, ::Type{T}) = promote_sys_size(T) +r_promote_type{T<:SmallReduceResult}(::typeof(+), ::Type{T}) = promote_sys_size(T) +r_promote_type{T<:SmallReduceResult}(::typeof(*), ::Type{T}) = promote_sys_size(T) r_promote_type{T<:Number}(::typeof(+), ::Type{T}) = typeof(zero(T)+zero(T)) r_promote_type{T<:Number}(::typeof(*), ::Type{T}) = typeof(one(T)*one(T)) -r_promote_type{T<:WidenReduceResult}(::typeof(scalarmax), ::Type{T}) = T -r_promote_type{T<:WidenReduceResult}(::typeof(scalarmin), ::Type{T}) = T -r_promote_type{T<:WidenReduceResult}(::typeof(max), ::Type{T}) = T -r_promote_type{T<:WidenReduceResult}(::typeof(min), ::Type{T}) = T +r_promote_type{T<:SmallReduceResult}(::typeof(scalarmax), ::Type{T}) = T +r_promote_type{T<:SmallReduceResult}(::typeof(scalarmin), ::Type{T}) = T +r_promote_type{T<:SmallReduceResult}(::typeof(max), ::Type{T}) = T +r_promote_type{T<:SmallReduceResult}(::typeof(min), ::Type{T}) = T # r_promote: promote x to the type of reduce(op, [x]) r_promote{T}(op, x::T) = convert(r_promote_type(op, T), x) From 0af7fe1954dbdbf086d64c2c3720f0360d9e683d Mon Sep 17 00:00:00 2001 From: felix Date: Tue, 14 Feb 2017 14:40:20 +0000 Subject: [PATCH 2/4] update tests --- test/reduce.jl | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/test/reduce.jl b/test/reduce.jl index 87bd3361cfe2a..95f59e3b3de2a 100644 --- a/test/reduce.jl +++ b/test/reduce.jl @@ -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 @@ -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 @@ -28,7 +28,7 @@ # reduce & mapreduce @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) @@ -39,7 +39,7 @@ # sum -@test sum(Int8[]) === Int32(0) +@test sum(Int8[]) === Int(0) @test sum(Int[]) === Int(0) @test sum(Float64[]) === 0.0 @@ -47,7 +47,7 @@ @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 @@ -107,11 +107,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 From 5632f804f1c3cb59c56f2049e7f93de811835b3b Mon Sep 17 00:00:00 2001 From: felix Date: Tue, 14 Feb 2017 16:20:31 +0000 Subject: [PATCH 3/4] tests, II --- test/reduce.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/reduce.jl b/test/reduce.jl index 95f59e3b3de2a..33275ebb73287 100644 --- a/test/reduce.jl +++ b/test/reduce.jl @@ -126,8 +126,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 From d2aeb2da1da4092c05f6c6265369282d6a5919c2 Mon Sep 17 00:00:00 2001 From: felix Date: Wed, 15 Feb 2017 09:26:47 +0000 Subject: [PATCH 4/4] Float16 bumped in status, docs changed --- base/reduce.jl | 33 ++++++++++++++++++--------------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/base/reduce.jl b/base/reduce.jl index 0d78fcb129fda..c9ccce1ec3ae7 100644 --- a/base/reduce.jl +++ b/base/reduce.jl @@ -12,8 +12,8 @@ const SmallSigned = Union{Int8,Int16,Int32} const SmallUnsigned = Union{UInt8,UInt16,UInt32} end -const CommonReduceResult = Union{UInt64,UInt128,Int64,Int128,Float32,Float64} -const SmallReduceResult = 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 @@ -21,15 +21,15 @@ 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{T}(op, ::Type{T}) = T -r_promote_type{T<:SmallReduceResult}(op, ::Type{T}) = promote_sys_size(T) -r_promote_type{T<:SmallReduceResult}(::typeof(+), ::Type{T}) = promote_sys_size(T) -r_promote_type{T<:SmallReduceResult}(::typeof(*), ::Type{T}) = promote_sys_size(T) +r_promote_type{T<:WidenReduceResult}(op, ::Type{T}) = promote_sys_size(T) +r_promote_type{T<:WidenReduceResult}(::typeof(+), ::Type{T}) = promote_sys_size(T) +r_promote_type{T<:WidenReduceResult}(::typeof(*), ::Type{T}) = promote_sys_size(T) r_promote_type{T<:Number}(::typeof(+), ::Type{T}) = typeof(zero(T)+zero(T)) r_promote_type{T<:Number}(::typeof(*), ::Type{T}) = typeof(one(T)*one(T)) -r_promote_type{T<:SmallReduceResult}(::typeof(scalarmax), ::Type{T}) = T -r_promote_type{T<:SmallReduceResult}(::typeof(scalarmin), ::Type{T}) = T -r_promote_type{T<:SmallReduceResult}(::typeof(max), ::Type{T}) = T -r_promote_type{T<:SmallReduceResult}(::typeof(min), ::Type{T}) = T +r_promote_type{T<:WidenReduceResult}(::typeof(scalarmax), ::Type{T}) = T +r_promote_type{T<:WidenReduceResult}(::typeof(scalarmin), ::Type{T}) = T +r_promote_type{T<:WidenReduceResult}(::typeof(max), ::Type{T}) = T +r_promote_type{T<:WidenReduceResult}(::typeof(min), ::Type{T}) = T # r_promote: promote x to the type of reduce(op, [x]) r_promote{T}(op, x::T) = convert(r_promote_type(op, T), x) @@ -283,21 +283,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