Skip to content

Commit 1c050f3

Browse files
committed
tweaks to reduce.jl
1 parent 35c8313 commit 1c050f3

File tree

1 file changed

+52
-34
lines changed

1 file changed

+52
-34
lines changed

base/reduce.jl

Lines changed: 52 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,25 @@ else
1212
const SmallUnsigned = Union{UInt8,UInt16,UInt32}
1313
end
1414

15-
# Certain reductions like sum and prod may wish to promote the items being reduced over to
16-
# a wider type.
17-
add_tosys(x,y) = x + y
18-
add_tosys(x::SmallSigned,y::SmallSigned) = Int(x) + Int(y)
19-
add_tosys(x::SmallUnsigned,y::SmallUnsigned) = UInt(x) + UInt(y)
15+
"""
16+
Base.add_sum(x,y)
17+
18+
The reduction operator used in `sum`. The main difference from [`+`](@ref) is that small
19+
integers are promoted to `Int`/`UInt`.
20+
"""
21+
add_sum(x,y) = x + y
22+
add_sum(x::SmallSigned,y::SmallSigned) = Int(x) + Int(y)
23+
add_sum(x::SmallUnsigned,y::SmallUnsigned) = UInt(x) + UInt(y)
2024

21-
mul_tosys(x,y) = x * y
22-
mul_tosys(x::SmallSigned,y::SmallSigned) = Int(x) * Int(y)
23-
mul_tosys(x::SmallUnsigned,y::SmallUnsigned) = UInt(x) * UInt(y)
25+
"""
26+
Base.mul_prod(x,y)
27+
28+
The reduction operator used in `prod`. The main difference from [`*`](@ref) is that small
29+
integers are promoted to `Int`/`UInt`.
30+
"""
31+
mul_prod(x,y) = x * y
32+
mul_prod(x::SmallSigned,y::SmallSigned) = Int(x) * Int(y)
33+
mul_prod(x::SmallUnsigned,y::SmallUnsigned) = UInt(x) * UInt(y)
2434

2535
## foldl && mapfoldl
2636

@@ -240,36 +250,38 @@ _empty_reduce_error() = throw(ArgumentError("reducing over an empty collection i
240250
"""
241251
Base.reduce_empty(op, T)
242252
243-
The value to be returned when calling [`reduce`](@ref) with `op` over an empty array with
244-
element type of `T`.
253+
The value to be returned when calling [`reduce`](@ref), [`foldl`](@ref) or [`foldr`](@ref)
254+
with reduction `op` over an empty array with element type of `T`.
245255
246256
If not defined, this will throw an `ArgumentError`.
247257
"""
248258
reduce_empty(op, T) = _empty_reduce_error()
249259
reduce_empty(::typeof(+), T) = zero(T)
260+
reduce_empty(::typeof(+), ::Type{Bool}) = zero(Int)
250261
reduce_empty(::typeof(*), T) = one(T)
251262
reduce_empty(::typeof(&), ::Type{Bool}) = true
252263
reduce_empty(::typeof(|), ::Type{Bool}) = false
253264

254-
reduce_empty(::typeof(add_tosys), T) = zero(T)
255-
reduce_empty(::typeof(add_tosys), ::Type{T}) where {T<:SmallSigned} = zero(Int)
256-
reduce_empty(::typeof(add_tosys), ::Type{T}) where {T<:SmallUnsigned} = zero(UInt)
257-
reduce_empty(::typeof(mul_tosys), T) = one(T)
258-
reduce_empty(::typeof(mul_tosys), ::Type{T}) where {T<:SmallSigned} = one(Int)
259-
reduce_empty(::typeof(mul_tosys), ::Type{T}) where {T<:SmallUnsigned} = one(UInt)
265+
reduce_empty(::typeof(add_sum), T) = reduce_empty(+, T)
266+
reduce_empty(::typeof(add_sum), ::Type{T}) where {T<:SmallSigned} = zero(Int)
267+
reduce_empty(::typeof(add_sum), ::Type{T}) where {T<:SmallUnsigned} = zero(UInt)
268+
reduce_empty(::typeof(mul_prod), T) = reduce_empty(*, T)
269+
reduce_empty(::typeof(mul_prod), ::Type{T}) where {T<:SmallSigned} = one(Int)
270+
reduce_empty(::typeof(mul_prod), ::Type{T}) where {T<:SmallUnsigned} = one(UInt)
260271

261272
"""
262273
Base.mapreduce_empty(f, op, T)
263274
264-
The value to be returned when calling [`mapreduce`](@ref) with `f` and `op` over an empty
265-
array with element type of `T`.
275+
The value to be returned when calling [`mapreduce`](@ref), [`mapfoldl`](@ref`) or
276+
[`mapfoldr`](@ref) with map `f` and reduction `op` over an empty array with element type
277+
of `T`.
266278
267279
If not defined, this will throw an `ArgumentError`.
268280
"""
269281
mapreduce_empty(f, op, T) = _empty_reduce_error()
270-
mapreduce_empty(f::typeof(identity), op, T) = f(reduce_empty(op, T))
271-
mapreduce_empty(f::typeof(abs), op, T) = f(reduce_empty(op, T))
272-
mapreduce_empty(f::typeof(abs2), op, T) = f(reduce_empty(op, T))
282+
mapreduce_empty(::typeof(identity), op, T) = reduce_empty(op, T)
283+
mapreduce_empty(::typeof(abs), op, T) = abs(reduce_empty(op, T))
284+
mapreduce_empty(::typeof(abs2), op, T) = abs2(reduce_empty(op, T))
273285

274286
mapreduce_empty(f::typeof(abs), ::Union{typeof(scalarmax), typeof(max)}, T) = abs(zero(T))
275287
mapreduce_empty(f::typeof(abs2), ::Union{typeof(scalarmax), typeof(max)}, T) = abs2(zero(T))
@@ -283,26 +295,32 @@ mapreduce_empty_iter(f, op, itr, ::EltypeUnknown) = _empty_reduce_error()
283295
"""
284296
Base.reduce_single(f, op, x)
285297
286-
The value to be returned when calling [`reduce`] with `op` over an iterator which contains
287-
a single element `x`.
298+
The value to be returned when calling [`mapreduce`](@ref), [`mapfoldl`](@ref`) or
299+
[`mapfoldr`](@ref) with reduction `op` over an iterator which contains a single element
300+
`x`.
288301
289302
The default is `x`.
290303
"""
291304
reduce_single(op, x) = x
292-
reduce_single(::typeof(add_tosys), x::SmallSigned) = Int(x)
293-
reduce_single(::typeof(add_tosys), x::SmallUnsigned) = UInt(x)
294-
reduce_single(::typeof(mul_tosys), x::SmallSigned) = Int(x)
295-
reduce_single(::typeof(mul_tosys), x::SmallUnsigned) = UInt(x)
305+
reduce_single(::typeof(+), x::Bool) = Int(x)
306+
307+
reduce_single(::typeof(add_sum), x) = reduce_single(+, x)
308+
reduce_single(::typeof(add_sum), x::SmallSigned) = Int(x)
309+
reduce_single(::typeof(add_sum), x::SmallUnsigned) = UInt(x)
310+
reduce_single(::typeof(mul_prod), x) = reduce_single(*, x)
311+
reduce_single(::typeof(mul_prod), x::SmallSigned) = Int(x)
312+
reduce_single(::typeof(mul_prod), x::SmallUnsigned) = UInt(x)
296313

297314
"""
298315
Base.mapreduce_single(f, op, x)
299316
300-
The value to be returned when calling [`mapreduce`] with `f` and `op` over an iterator
301-
which contains a single element `x`.
317+
The value to be returned when calling [`mapreduce`](@ref), [`mapfoldl`](@ref`) or
318+
[`mapfoldr`](@ref) with map `f` and reduction `op` over an iterator which contains a
319+
single element `x`.
302320
303-
The default is `f(reduce_single(op, x))`.
321+
The default is `reduce_single(op, f(x))`.
304322
"""
305-
mapreduce_single(f, op, x) = f(reduce_single(op, x))
323+
mapreduce_single(f, op, x) = reduce_single(op, f(x))
306324

307325
_mapreduce(f, op, A::AbstractArray) = _mapreduce(f, op, IndexStyle(A), A)
308326

@@ -410,7 +428,7 @@ In the former case, the integers are widened to system word size and therefore
410428
the result is 128. In the latter case, no such widening happens and integer
411429
overflow results in -128.
412430
"""
413-
sum(f, a) = mapreduce(f, add_tosys, a)
431+
sum(f, a) = mapreduce(f, add_sum, a)
414432

415433
"""
416434
sum(itr)
@@ -444,7 +462,7 @@ julia> prod(abs2, [2; 3; 4])
444462
576
445463
```
446464
"""
447-
prod(f::Callable, a) = mapreduce(f, mul_tosys, a)
465+
prod(f::Callable, a) = mapreduce(f, mul_prod, a)
448466

449467
"""
450468
prod(itr)
@@ -460,7 +478,7 @@ julia> prod(1:20)
460478
2432902008176640000
461479
```
462480
"""
463-
prod(a) = mapreduce(identity, mul_tosys, a)
481+
prod(a) = mapreduce(identity, mul_prod, a)
464482

465483
## maximum & minimum
466484

0 commit comments

Comments
 (0)