Skip to content

Commit e120c61

Browse files
committed
simplify sum, prod behaviour
1 parent df2820a commit e120c61

File tree

1 file changed

+39
-31
lines changed

1 file changed

+39
-31
lines changed

base/reduce.jl

Lines changed: 39 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,13 @@ end
1515
# Certain reductions like sum and prod may wish to promote the items being reduced over to
1616
# an appropriate size. Note we need x + zero(x) because some types like Bool have their sum
1717
# lie in a larger type.
18-
promote_sys_size(T::Type) = T
19-
promote_sys_size(::Type{<:SmallSigned}) = Int
20-
promote_sys_size(::Type{<:SmallUnsigned}) = UInt
18+
add_tosys(x,y) = x + y
19+
add_tosys(x::SmallSigned,y::SmallSigned) = Int(x) + Int(y)
20+
add_tosys(x::SmallUnsigned,y::SmallUnsigned) = UInt(x) + UInt(y)
2121

22-
promote_sys_size_add(x) = convert(promote_sys_size(typeof(x + zero(x))), x)
23-
promote_sys_size_mul(x) = convert(promote_sys_size(typeof(x * one(x))), x)
24-
const _PromoteSysSizeFunction = Union{typeof(promote_sys_size_add),
25-
typeof(promote_sys_size_mul)}
22+
mul_tosys(x,y) = x * y
23+
mul_tosys(x::SmallSigned,y::SmallSigned) = Int(x) * Int(y)
24+
mul_tosys(x::SmallUnsigned,y::SmallUnsigned) = UInt(x) * UInt(y)
2625

2726
## foldl && mapfoldl
2827

@@ -253,6 +252,12 @@ reduce_empty(::typeof(*), T) = one(T)
253252
reduce_empty(::typeof(&), ::Type{Bool}) = true
254253
reduce_empty(::typeof(|), ::Type{Bool}) = false
255254

255+
reduce_empty(::typeof(add_tosys), T) = zero(T)
256+
reduce_empty(::typeof(add_tosys), ::Type{T}) where {T<:SmallSigned} = zero(Int)
257+
reduce_empty(::typeof(add_tosys), ::Type{T}) where {T<:SmallUnsigned} = zero(UInt)
258+
reduce_empty(::typeof(mul_tosys), T) = one(T)
259+
reduce_empty(::typeof(mul_tosys), ::Type{T}) where {T<:SmallSigned} = one(Int)
260+
reduce_empty(::typeof(mul_tosys), ::Type{T}) where {T<:SmallUnsigned} = one(UInt)
256261

257262
"""
258263
Base.mapreduce_empty(f, op, T)
@@ -263,39 +268,42 @@ array with element type of `T`.
263268
If not defined, this will throw an `ArgumentError`.
264269
"""
265270
mapreduce_empty(f, op, T) = _empty_reduce_error()
266-
mapreduce_empty(::typeof(identity), op, T) = reduce_empty(op, T)
267-
mapreduce_empty(f::_PromoteSysSizeFunction, op, T) =
268-
f(mapreduce_empty(identity, op, T))
269-
mapreduce_empty(::typeof(abs), ::typeof(+), T) = abs(zero(T))
270-
mapreduce_empty(::typeof(abs2), ::typeof(+), T) = abs2(zero(T))
271-
mapreduce_empty(::typeof(abs), ::Union{typeof(scalarmax), typeof(max)}, T) =
272-
abs(zero(T))
273-
mapreduce_empty(::typeof(abs2), ::Union{typeof(scalarmax), typeof(max)}, T) =
274-
abs2(zero(T))
275-
276-
# Allow mapreduce_empty to “see through” promote_sys_size
277-
let ComposedFunction = typename(typeof(identity identity)).wrapper
278-
global mapreduce_empty(f::ComposedFunction{<:_PromoteSysSizeFunction}, op, T) =
279-
f.f(mapreduce_empty(f.g, op, T))
280-
end
271+
mapreduce_empty(f::typeof(identity), op, T) = f(reduce_empty(op, T))
272+
mapreduce_empty(f::typeof(abs), op, T) = f(reduce_empty(op, T))
273+
mapreduce_empty(f::typeof(abs2), op, T) = f(reduce_empty(op, T))
274+
275+
mapreduce_empty(f::typeof(abs), ::Union{typeof(scalarmax), typeof(max)}, T) = abs(zero(T))
276+
mapreduce_empty(f::typeof(abs2), ::Union{typeof(scalarmax), typeof(max)}, T) = abs2(zero(T))
281277

282278
mapreduce_empty_iter(f, op, itr, ::HasEltype) = mapreduce_empty(f, op, eltype(itr))
283279
mapreduce_empty_iter(f, op::typeof(&), itr, ::EltypeUnknown) = true
284280
mapreduce_empty_iter(f, op::typeof(|), itr, ::EltypeUnknown) = false
285281
mapreduce_empty_iter(f, op, itr, ::EltypeUnknown) = _empty_reduce_error()
286282

287283
# handling of single-element iterators
284+
"""
285+
Base.reduce_single(f, op, x)
286+
287+
The value to be returned when calling [`reduce`] with `op` over an iterator which contains
288+
a single element `x`.
289+
290+
The default is `x`.
291+
"""
292+
reduce_single(op, x) = x
293+
reduce_single(::typeof(add_tosys), x::SmallSigned) = Int(x)
294+
reduce_single(::typeof(add_tosys), x::SmallUnsigned) = UInt(x)
295+
reduce_single(::typeof(mul_tosys), x::SmallSigned) = Int(x)
296+
reduce_single(::typeof(mul_tosys), x::SmallUnsigned) = UInt(x)
297+
288298
"""
289299
Base.mapreduce_single(f, op, x)
290300
291301
The value to be returned when calling [`mapreduce`] with `f` and `op` over an iterator
292302
which contains a single element `x`.
293303
294-
The default is `f(x)`.
304+
The default is `f(reduce_single(op, x))`.
295305
"""
296-
mapreduce_single(f, op, x) = f(x)
297-
298-
306+
mapreduce_single(f, op, x) = f(reduce_single(op, x))
299307

300308
_mapreduce(f, op, A::AbstractArray) = _mapreduce(f, op, IndexStyle(A), A)
301309

@@ -325,7 +333,7 @@ end
325333
_mapreduce(f, op, ::IndexCartesian, A::AbstractArray) = mapfoldl(f, op, A)
326334

327335
mapreduce(f, op, A::AbstractArray) = _mapreduce(f, op, IndexStyle(A), A)
328-
mapreduce(f, op, a::Number) = f(a)
336+
mapreduce(f, op, a::Number) = mapreduce_single(f, op, a)
329337

330338
"""
331339
reduce(op, v0, itr)
@@ -403,7 +411,7 @@ In the former case, the integers are widened to system word size and therefore
403411
the result is 128. In the latter case, no such widening happens and integer
404412
overflow results in -128.
405413
"""
406-
sum(f::Callable, a) = mapreduce(promote_sys_size_add f, +, a)
414+
sum(f, a) = mapreduce(f, add_tosys, a)
407415

408416
"""
409417
sum(itr)
@@ -419,7 +427,7 @@ julia> sum(1:20)
419427
210
420428
```
421429
"""
422-
sum(a) = mapreduce(promote_sys_size_add, +, a)
430+
sum(a) = sum(identity, a)
423431
sum(a::AbstractArray{Bool}) = count(a)
424432

425433
## prod
@@ -437,7 +445,7 @@ julia> prod(abs2, [2; 3; 4])
437445
576
438446
```
439447
"""
440-
prod(f::Callable, a) = mapreduce(promote_sys_size_mul f, *, a)
448+
prod(f::Callable, a) = mapreduce(f, mul_tosys, a)
441449

442450
"""
443451
prod(itr)
@@ -453,7 +461,7 @@ julia> prod(1:20)
453461
2432902008176640000
454462
```
455463
"""
456-
prod(a) = mapreduce(promote_sys_size_mul, *, a)
464+
prod(a) = mapreduce(identity, mul_tosys, a)
457465

458466
## maximum & minimum
459467

0 commit comments

Comments
 (0)