@@ -64,7 +64,7 @@ function mapfoldl(f, op, itr)
64
64
return Base. mapreduce_empty_iter (f, op, itr, iteratoreltype (itr))
65
65
end
66
66
(x, i) = next (itr, i)
67
- v0 = f ( x)
67
+ v0 = mapreduce_single (f, op, x)
68
68
mapfoldl_impl (f, op, v0, itr, i)
69
69
end
70
70
@@ -133,7 +133,7 @@ function mapfoldr(f, op, itr)
133
133
if isempty (itr)
134
134
return Base. mapreduce_empty_iter (f, op, itr, iteratoreltype (itr))
135
135
end
136
- return mapfoldr_impl (f, op, f ( itr[i]), itr, i- 1 )
136
+ return mapfoldr_impl (f, op, mapreduce_single (f, op, itr[i]), itr, i- 1 )
137
137
end
138
138
139
139
"""
@@ -174,7 +174,7 @@ foldr(op, itr) = mapfoldr(identity, op, itr)
174
174
@noinline function mapreduce_impl (f, op, A:: AbstractArray , ifirst:: Integer , ilast:: Integer , blksize:: Int )
175
175
if ifirst == ilast
176
176
@inbounds a1 = A[ifirst]
177
- return f ( a1)
177
+ return mapreduce_single (f, op, a1)
178
178
elseif ifirst + blksize > ilast
179
179
# sequential portion
180
180
@inbounds a1 = A[ifirst]
@@ -238,12 +238,30 @@ pairwise_blocksize(::typeof(abs2), ::typeof(+)) = 4096
238
238
239
239
# handling empty arrays
240
240
_empty_reduce_error () = throw (ArgumentError (" reducing over an empty collection is not allowed" ))
241
+
242
+ """
243
+ Base.reduce_empty(op, T)
244
+
245
+ The value to be returned when calling [`reduce`](@ref) with `op` over an empty array with
246
+ element type of `T`.
247
+
248
+ If not defined, this will throw an `ArgumentError`.
249
+ """
241
250
reduce_empty (op, T) = _empty_reduce_error ()
242
251
reduce_empty (:: typeof (+ ), T) = zero (T)
243
252
reduce_empty (:: typeof (* ), T) = one (T)
244
253
reduce_empty (:: typeof (& ), :: Type{Bool} ) = true
245
254
reduce_empty (:: typeof (| ), :: Type{Bool} ) = false
246
255
256
+
257
+ """
258
+ Base.mapreduce_empty(f, op, T)
259
+
260
+ The value to be returned when calling [`mapreduce`](@ref) with `f` and `op` over an empty
261
+ array with element type of `T`.
262
+
263
+ If not defined, this will throw an `ArgumentError`.
264
+ """
247
265
mapreduce_empty (f, op, T) = _empty_reduce_error ()
248
266
mapreduce_empty (:: typeof (identity), op, T) = reduce_empty (op, T)
249
267
mapreduce_empty (f:: _PromoteSysSizeFunction , op, T) =
@@ -266,6 +284,19 @@ mapreduce_empty_iter(f, op::typeof(&), itr, ::EltypeUnknown) = true
266
284
mapreduce_empty_iter (f, op:: typeof (| ), itr, :: EltypeUnknown ) = false
267
285
mapreduce_empty_iter (f, op, itr, :: EltypeUnknown ) = _empty_reduce_error ()
268
286
287
+ # handling of single-element iterators
288
+ """
289
+ Base.mapreduce_single(f, op, x)
290
+
291
+ The value to be returned when calling [`mapreduce`] with `f` and `op` over an iterator
292
+ which contains a single element `x`.
293
+
294
+ The default is `f(x)`.
295
+ """
296
+ mapreduce_single (f, op, x) = f (x)
297
+
298
+
299
+
269
300
_mapreduce (f, op, A:: AbstractArray ) = _mapreduce (f, op, IndexStyle (A), A)
270
301
271
302
function _mapreduce (f, op, :: IndexLinear , A:: AbstractArray{T} ) where T
@@ -275,7 +306,7 @@ function _mapreduce(f, op, ::IndexLinear, A::AbstractArray{T}) where T
275
306
return mapreduce_empty (f, op, T)
276
307
elseif n == 1
277
308
@inbounds a1 = A[inds[1 ]]
278
- return f ( a1)
309
+ return mapreduce_single (f, op, a1)
279
310
elseif n < 16 # process short array here, avoid mapreduce_impl() compilation
280
311
@inbounds i = inds[1 ]
281
312
@inbounds a1 = A[i]
0 commit comments