55# ##### Generic (map)reduce functions ######
66
77if Int === Int32
8- const SmallSigned = Union{Int8,Int16}
9- const SmallUnsigned = Union{UInt8,UInt16}
8+ const SmallSigned = Union{Int8,Int16}
9+ const SmallUnsigned = Union{UInt8,UInt16}
1010else
11- const SmallSigned = Union{Int8,Int16,Int32}
12- const SmallUnsigned = Union{UInt8,UInt16,UInt32}
11+ const SmallSigned = Union{Int8,Int16,Int32}
12+ const SmallUnsigned = Union{UInt8,UInt16,UInt32}
1313end
1414
15- const CommonReduceResult = Union{UInt64,UInt128,Int64,Int128,Float16,Float32,Float64}
16- const WidenReduceResult = Union{SmallSigned, SmallUnsigned}
17-
18- promote_sys_size {T} (:: Type{T} ) = T
19- promote_sys_size {T<:SmallSigned} (:: Type{T} ) = Int
20- promote_sys_size {T<:SmallUnsigned} (:: Type{T} ) = UInt
21- # r_promote_type: promote T to the type of reduce(op, ::Array{T})
22- # (some "extra" methods are required here to avoid ambiguity warnings)
23- r_promote_type (op, :: Type{T} ) where {T} = T
24- r_promote_type (op, :: Type{T} ) where {T<: WidenReduceResult } = promote_sys_size (T)
25- r_promote_type (:: typeof (+ ), :: Type{T} ) where {T<: WidenReduceResult } = promote_sys_size (T)
26- r_promote_type (:: typeof (* ), :: Type{T} ) where {T<: WidenReduceResult } = promote_sys_size (T)
27- r_promote_type (:: typeof (+ ), :: Type{T} ) where {T<: Number } = typeof (zero (T)+ zero (T))
28- r_promote_type (:: typeof (* ), :: Type{T} ) where {T<: Number } = typeof (one (T)* one (T))
29- r_promote_type (:: typeof (scalarmax), :: Type{T} ) where {T<: WidenReduceResult } = T
30- r_promote_type (:: typeof (scalarmin), :: Type{T} ) where {T<: WidenReduceResult } = T
31- r_promote_type (:: typeof (max), :: Type{T} ) where {T<: WidenReduceResult } = T
32- r_promote_type (:: typeof (min), :: Type{T} ) where {T<: WidenReduceResult } = T
33-
34- # r_promote: promote x to the type of reduce(op, [x])
35- r_promote (op, x:: T ) where {T} = convert (r_promote_type (op, T), x)
15+ # Certain reductions like sum and prod may wish to promote the items being
16+ # reduced over to an appropriate size.
17+ promote_sys_size (x) = x
18+ promote_sys_size (x:: SmallSigned ) = Int (x)
19+ promote_sys_size (x:: SmallUnsigned ) = UInt (x)
3620
3721# # foldl && mapfoldl
3822
3923@noinline function mapfoldl_impl (f, op, v0, itr, i)
4024 # Unroll the while loop once; if v0 is known, the call to op may
4125 # be evaluated at compile time
4226 if done (itr, i)
43- return r_promote (op, v0)
27+ return v0
4428 else
4529 (x, i) = next (itr, i)
46- v = op (r_promote (op, v0) , f (x))
30+ v = op (v0 , f (x))
4731 while ! done (itr, i)
4832 @inbounds (x, i) = next (itr, i)
4933 v = op (v, f (x))
@@ -108,10 +92,10 @@ function mapfoldr_impl(f, op, v0, itr, i::Integer)
10892 # Unroll the while loop once; if v0 is known, the call to op may
10993 # be evaluated at compile time
11094 if isempty (itr) || i == 0
111- return r_promote (op, v0)
95+ return v0
11296 else
11397 x = itr[i]
114- v = op (f (x), r_promote (op, v0) )
98+ v = op (f (x), v0 )
11599 while i > 1
116100 x = itr[i -= 1 ]
117101 v = op (f (x), v)
@@ -180,12 +164,12 @@ foldr(op, itr) = mapfoldr(identity, op, itr)
180164@noinline function mapreduce_impl (f, op, A:: AbstractArray , ifirst:: Integer , ilast:: Integer , blksize:: Int )
181165 if ifirst == ilast
182166 @inbounds a1 = A[ifirst]
183- return r_promote (op, f (a1) )
167+ return f (a1)
184168 elseif ifirst + blksize > ilast
185169 # sequential portion
186170 @inbounds a1 = A[ifirst]
187171 @inbounds a2 = A[ifirst+ 1 ]
188- v = op (r_promote (op, f (a1)), r_promote (op, f (a2) ))
172+ v = op (f (a1), f (a2))
189173 @simd for i = ifirst + 2 : ilast
190174 @inbounds ai = A[i]
191175 v = op (v, f (ai))
@@ -245,13 +229,14 @@ pairwise_blocksize(::typeof(abs2), ::typeof(+)) = 4096
245229# handling empty arrays
246230_empty_reduce_error () = throw (ArgumentError (" reducing over an empty collection is not allowed" ))
247231mr_empty (f, op, T) = _empty_reduce_error ()
248- # use zero(T)::T to improve type information when zero(T) is not defined
249- mr_empty (:: typeof (identity), op:: typeof (+ ), T) = r_promote (op, zero (T):: T )
250- mr_empty (:: typeof (abs), op:: typeof (+ ), T) = r_promote (op, abs (zero (T):: T ))
251- mr_empty (:: typeof (abs2), op:: typeof (+ ), T) = r_promote (op, abs2 (zero (T):: T ))
252- mr_empty (:: typeof (identity), op:: typeof (* ), T) = r_promote (op, one (T):: T )
253- mr_empty (:: typeof (abs), op:: typeof (scalarmax), T) = abs (zero (T):: T )
254- mr_empty (:: typeof (abs2), op:: typeof (scalarmax), T) = abs2 (zero (T):: T )
232+ mr_empty (:: typeof (identity), op:: typeof (+ ), T) = zero (T)
233+ mr_empty (:: typeof (abs), op:: typeof (+ ), T) = abs (zero (T))
234+ mr_empty (:: typeof (abs2), op:: typeof (+ ), T) = abs2 (zero (T))
235+ mr_empty (:: typeof (identity), op:: typeof (* ), T) = one (T)
236+ mr_empty (:: typeof (promote_sys_size), op, T) =
237+ promote_sys_size (mr_empty (identity, op, T))
238+ mr_empty (:: typeof (abs), op:: typeof (scalarmax), T) = abs (zero (T))
239+ mr_empty (:: typeof (abs2), op:: typeof (scalarmax), T) = abs2 (zero (T))
255240mr_empty (:: typeof (abs), op:: typeof (max), T) = mr_empty (abs, scalarmax, T)
256241mr_empty (:: typeof (abs2), op:: typeof (max), T) = mr_empty (abs2, scalarmax, T)
257242mr_empty (f, op:: typeof (& ), T) = true
@@ -271,12 +256,12 @@ function _mapreduce(f, op, ::IndexLinear, A::AbstractArray{T}) where T
271256 return mr_empty (f, op, T)
272257 elseif n == 1
273258 @inbounds a1 = A[inds[1 ]]
274- return r_promote (op, f (a1) )
259+ return f (a1)
275260 elseif n < 16 # process short array here, avoid mapreduce_impl() compilation
276261 @inbounds i = inds[1 ]
277262 @inbounds a1 = A[i]
278263 @inbounds a2 = A[i+= 1 ]
279- s = op (r_promote (op, f (a1)), r_promote (op, f (a2) ))
264+ s = op (f (a1), f (a2))
280265 while i < last (inds)
281266 @inbounds Ai = A[i+= 1 ]
282267 s = op (s, f (Ai))
@@ -352,7 +337,7 @@ julia> sum(abs2, [2; 3; 4])
35233729
353338```
354339"""
355- sum (f:: Callable , a) = mapreduce (f, + , a)
340+ sum (f:: Callable , a) = mapreduce (promote_sys_size ∘ f, + , a)
356341
357342"""
358343 sum(itr)
@@ -364,7 +349,7 @@ julia> sum(1:20)
364349210
365350```
366351"""
367- sum (a) = mapreduce (identity , + , a)
352+ sum (a) = mapreduce (promote_sys_size , + , a)
368353sum (a:: AbstractArray{Bool} ) = countnz (a)
369354
370355
@@ -379,7 +364,7 @@ summation algorithm for additional accuracy.
379364"""
380365function sum_kbn (A)
381366 T = _default_eltype (typeof (A))
382- c = r_promote ( + , zero (T):: T )
367+ c = promote_sys_size ( zero (T):: T )
383368 i = start (A)
384369 if done (A, i)
385370 return c
@@ -410,7 +395,7 @@ julia> prod(abs2, [2; 3; 4])
410395576
411396```
412397"""
413- prod (f:: Callable , a) = mapreduce (f, * , a)
398+ prod (f:: Callable , a) = mapreduce (promote_sys_size ∘ f, * , a)
414399
415400"""
416401 prod(itr)
@@ -422,7 +407,7 @@ julia> prod(1:20)
4224072432902008176640000
423408```
424409"""
425- prod (a) = mapreduce (identity , * , a)
410+ prod (a) = mapreduce (promote_sys_size , * , a)
426411
427412# # maximum & minimum
428413
0 commit comments