5
5
# ##### Generic (map)reduce functions ######
6
6
7
7
if 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}
10
10
else
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}
13
13
end
14
14
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)
36
20
37
21
# # foldl && mapfoldl
38
22
39
23
@noinline function mapfoldl_impl (f, op, v0, itr, i)
40
24
# Unroll the while loop once; if v0 is known, the call to op may
41
25
# be evaluated at compile time
42
26
if done (itr, i)
43
- return r_promote (op, v0)
27
+ return v0
44
28
else
45
29
(x, i) = next (itr, i)
46
- v = op (r_promote (op, v0) , f (x))
30
+ v = op (v0 , f (x))
47
31
while ! done (itr, i)
48
32
@inbounds (x, i) = next (itr, i)
49
33
v = op (v, f (x))
@@ -108,10 +92,10 @@ function mapfoldr_impl(f, op, v0, itr, i::Integer)
108
92
# Unroll the while loop once; if v0 is known, the call to op may
109
93
# be evaluated at compile time
110
94
if isempty (itr) || i == 0
111
- return r_promote (op, v0)
95
+ return v0
112
96
else
113
97
x = itr[i]
114
- v = op (f (x), r_promote (op, v0) )
98
+ v = op (f (x), v0 )
115
99
while i > 1
116
100
x = itr[i -= 1 ]
117
101
v = op (f (x), v)
@@ -180,12 +164,12 @@ foldr(op, itr) = mapfoldr(identity, op, itr)
180
164
@noinline function mapreduce_impl (f, op, A:: AbstractArray , ifirst:: Integer , ilast:: Integer , blksize:: Int )
181
165
if ifirst == ilast
182
166
@inbounds a1 = A[ifirst]
183
- return r_promote (op, f (a1) )
167
+ return f (a1)
184
168
elseif ifirst + blksize > ilast
185
169
# sequential portion
186
170
@inbounds a1 = A[ifirst]
187
171
@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))
189
173
@simd for i = ifirst + 2 : ilast
190
174
@inbounds ai = A[i]
191
175
v = op (v, f (ai))
@@ -245,13 +229,14 @@ pairwise_blocksize(::typeof(abs2), ::typeof(+)) = 4096
245
229
# handling empty arrays
246
230
_empty_reduce_error () = throw (ArgumentError (" reducing over an empty collection is not allowed" ))
247
231
mr_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))
255
240
mr_empty (:: typeof (abs), op:: typeof (max), T) = mr_empty (abs, scalarmax, T)
256
241
mr_empty (:: typeof (abs2), op:: typeof (max), T) = mr_empty (abs2, scalarmax, T)
257
242
mr_empty (f, op:: typeof (& ), T) = true
@@ -271,12 +256,12 @@ function _mapreduce(f, op, ::IndexLinear, A::AbstractArray{T}) where T
271
256
return mr_empty (f, op, T)
272
257
elseif n == 1
273
258
@inbounds a1 = A[inds[1 ]]
274
- return r_promote (op, f (a1) )
259
+ return f (a1)
275
260
elseif n < 16 # process short array here, avoid mapreduce_impl() compilation
276
261
@inbounds i = inds[1 ]
277
262
@inbounds a1 = A[i]
278
263
@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))
280
265
while i < last (inds)
281
266
@inbounds Ai = A[i+= 1 ]
282
267
s = op (s, f (Ai))
@@ -353,7 +338,7 @@ julia> sum(abs2, [2; 3; 4])
353
338
29
354
339
```
355
340
"""
356
- sum (f:: Callable , a) = mapreduce (f, + , a)
341
+ sum (f:: Callable , a) = mapreduce (promote_sys_size ∘ f, + , a)
357
342
358
343
"""
359
344
sum(itr)
@@ -365,7 +350,7 @@ julia> sum(1:20)
365
350
210
366
351
```
367
352
"""
368
- sum (a) = mapreduce (identity , + , a)
353
+ sum (a) = mapreduce (promote_sys_size , + , a)
369
354
sum (a:: AbstractArray{Bool} ) = countnz (a)
370
355
371
356
@@ -380,7 +365,7 @@ summation algorithm for additional accuracy.
380
365
"""
381
366
function sum_kbn (A)
382
367
T = _default_eltype (typeof (A))
383
- c = r_promote ( + , zero (T):: T )
368
+ c = promote_sys_size ( zero (T):: T )
384
369
i = start (A)
385
370
if done (A, i)
386
371
return c
@@ -411,7 +396,7 @@ julia> prod(abs2, [2; 3; 4])
411
396
576
412
397
```
413
398
"""
414
- prod (f:: Callable , a) = mapreduce (f, * , a)
399
+ prod (f:: Callable , a) = mapreduce (promote_sys_size ∘ f, * , a)
415
400
416
401
"""
417
402
prod(itr)
@@ -423,7 +408,7 @@ julia> prod(1:20)
423
408
2432902008176640000
424
409
```
425
410
"""
426
- prod (a) = mapreduce (identity , * , a)
411
+ prod (a) = mapreduce (promote_sys_size , * , a)
427
412
428
413
# # maximum & minimum
429
414
0 commit comments