Skip to content

Commit 756bf45

Browse files
authored
Handle empty input (#104)
* handle empty input (#87 etc) * changelog * fix error type
1 parent f41d082 commit 756bf45

File tree

3 files changed

+25
-12
lines changed

3 files changed

+25
-12
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
OhMyThreads.jl Changelog
22
=========================
33

4+
Version 0.5.2
5+
-------------
6+
- ![Enhancement][badge-enhancement] For empty input (e.g. `Float64[]` or `11:10`) behavior is now aligned with the serial functions in `Base`.
7+
48
Version 0.5.1
59
-------------
610
- ![Feature][badge-feature] Within a parallel `@tasks` block one can now mark a region with `@one_by_one`. This region will be run by one task at a time ("critical region").

src/implementation.jl

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -60,13 +60,9 @@ function tmapreduce(f, op, Arrs...;
6060
kwargs...)
6161
mapreduce_kwargs = isgiven(init) ? (; init) : (;)
6262
_scheduler = _scheduler_from_userinput(scheduler; kwargs...)
63-
if isempty(first(Arrs))
64-
isempty(mapreduce_kwargs) && reduce_empty_err()
65-
return mapreduce_kwargs.init
66-
end
6763

68-
# @show _scheduler
69-
if _scheduler isa SerialScheduler
64+
if _scheduler isa SerialScheduler || isempty(first(Arrs))
65+
# empty input collection → align with Base.mapreduce behavior
7066
mapreduce(f, op, Arrs...; mapreduce_kwargs...)
7167
else
7268
@noinline _tmapreduce(f, op, Arrs, outputtype, _scheduler, mapreduce_kwargs)
@@ -78,10 +74,6 @@ end
7874
throw(ArgumentError("Providing an explicit scheduler as well as direct keyword arguments (e.g. $(kwargstr)) is currently not supported."))
7975
end
8076

81-
@noinline function reduce_empty_err()
82-
throw(ArgumentError("reducing over an empty collection is not allowed; consider supplying `init`"))
83-
end
84-
8577
treducemap(op, f, A...; kwargs...) = tmapreduce(f, op, A...; kwargs...)
8678

8779
# DynamicScheduler: AbstractArray/Generic
@@ -357,7 +349,8 @@ function tmap(f,
357349
end
358350

359351
Arrs = (A, _Arrs...)
360-
if _scheduler isa SerialScheduler
352+
if _scheduler isa SerialScheduler || isempty(A)
353+
# empty input collection → align with Base.map behavior
361354
map(f, Arrs...; kwargs...)
362355
else
363356
check_all_have_same_indices(Arrs)

test/runtests.jl

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -364,14 +364,30 @@ end;
364364
end;
365365

366366
@testset "empty collections" begin
367+
@static if VERSION < v"1.11.0-"
368+
err = MethodError
369+
else
370+
err = ArgumentError
371+
end
367372
for empty_coll in (11:9, Float64[])
368373
for f in (sin, x -> im * x, identity)
369374
for op in (+, *, min)
370-
@test_throws ArgumentError tmapreduce(f, op, empty_coll)
375+
# mapreduce
371376
for init in (0.0, 0, 0.0 * im, 0.0f0)
372377
@test tmapreduce(f, op, empty_coll; init) == init
373378
end
379+
# foreach
374380
@test tforeach(f, empty_coll) |> isnothing
381+
# reduce
382+
if op != min
383+
@test treduce(op, empty_coll) == reduce(op, empty_coll)
384+
else
385+
@test_throws err treduce(op, empty_coll)
386+
end
387+
# map
388+
@test tmap(f, empty_coll) == map(f, empty_coll)
389+
# collect
390+
@test tcollect(empty_coll) == collect(empty_coll)
375391
end
376392
end
377393
end

0 commit comments

Comments
 (0)