From 300d2dd888f8108142b76c769901917ce411ea5f Mon Sep 17 00:00:00 2001 From: mtfishman Date: Mon, 31 Jul 2023 13:53:05 -0400 Subject: [PATCH 1/4] sort for NTuple and iterables --- Project.toml | 2 +- README.md | 3 +++ src/Compat.jl | 36 ++++++++++++++++++++++++++++++++++++ test/runtests.jl | 33 +++++++++++++++++++++++++++++++++ 4 files changed, 73 insertions(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index 340e6788d..845596f96 100644 --- a/Project.toml +++ b/Project.toml @@ -1,6 +1,6 @@ name = "Compat" uuid = "34da2185-b29b-5c13-b0c7-acf172513d20" -version = "4.8.0" +version = "4.9.0" [deps] Dates = "ade2ca70-3891-5945-98fb-dc099432e06a" diff --git a/README.md b/README.md index ec4545f77..bebd60902 100644 --- a/README.md +++ b/README.md @@ -70,6 +70,8 @@ changes in `julia`. ## Supported features +* `sort` for `NTuple` and iterables. ([#46104]) (since Compat 4.9.0) + * `redirect_stdio`, for simple stream redirection. ([#37978]) (since Compat 4.8.0) * `trunc`, `floor`, `ceil`, and `round` to `Bool`. ([#25085]) (since Compat 4.7.0) @@ -168,4 +170,5 @@ Note that you should specify the correct minimum version for `Compat` in the [#43334]: https://github.com/JuliaLang/julia/issues/43334 [#43354]: https://github.com/JuliaLang/julia/issues/43354 [#43852]: https://github.com/JuliaLang/julia/issues/43852 +[#46104]: https://github.com/JuliaLang/julia/issues/46104 [#48038]: https://github.com/JuliaLang/julia/issues/48038 diff --git a/src/Compat.jl b/src/Compat.jl index b20a8ec4b..9b9e4644a 100644 --- a/src/Compat.jl +++ b/src/Compat.jl @@ -706,6 +706,42 @@ if VERSION < v"1.7.0-DEV.1187" export redirect_stdio end +# https://github.com/JuliaLang/julia/pull/46104 +if VERSION < v"1.10.0-DEV.1404" + import Base: sort, Ordering, Forward, ord, lt, tail, copymutable, DEFAULT_STABLE, IteratorSize, HasShape, IsInfinite + function sort(v; kws...) + size = IteratorSize(v) + size == HasShape{0}() && throw(ArgumentError("$v cannot be sorted")) + size == IsInfinite() && throw(ArgumentError("infinite iterator $v cannot be sorted")) + sort!(copymutable(v); kws...) + end + sort(::AbstractString; kws...) = + throw(ArgumentError("sort(::AbstractString) is not supported")) + sort(::Tuple; kws...) = + throw(ArgumentError("sort(::Tuple) is only supported for NTuples")) + + function sort(x::NTuple{N}; lt::Function=isless, by::Function=identity, + rev::Union{Bool,Nothing}=nothing, order::Ordering=Forward) where N + o = ord(lt,by,rev,order) + if N > 9 + v = sort!(copymutable(x), DEFAULT_STABLE, o) + tuple((v[i] for i in 1:N)...) + else + _sort(x, o) + end + end + _sort(x::Union{NTuple{0}, NTuple{1}}, o::Ordering) = x + function _sort(x::NTuple, o::Ordering) + a, b = Base.IteratorsMD.split(x, Val(length(x)>>1)) + merge(_sort(a, o), _sort(b, o), o) + end + merge(x::NTuple, y::NTuple{0}, o::Ordering) = x + merge(x::NTuple{0}, y::NTuple, o::Ordering) = y + merge(x::NTuple{0}, y::NTuple{0}, o::Ordering) = x # Method ambiguity + merge(x::NTuple, y::NTuple, o::Ordering) = + (lt(o, y[1], x[1]) ? (y[1], merge(x, tail(y), o)...) : (x[1], merge(tail(x), y, o)...)) +end + include("deprecated.jl") end # module Compat diff --git a/test/runtests.jl b/test/runtests.jl index b9da5d945..7c74c8976 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -691,3 +691,36 @@ end @test read(path_stdout, String) == content_stdout end end + +# https://github.com/JuliaLang/julia/pull/46104 +@testset "sort(iterable)" begin + function tuple_sort_test(x) + @test issorted(sort(x)) + length(x) > 9 && return # length > 9 uses a vector fallback + @test 0 == @allocated sort(x) + end + @testset "sort(::NTuple)" begin + @test sort((9,8,3,3,6,2,0,8)) == (0,2,3,3,6,8,8,9) + @test sort((9,8,3,3,6,2,0,8), by=x->x÷3) == (2,0,3,3,8,6,8,9) + for i in 1:40 + tuple_sort_test(tuple(rand(i)...)) + end + @test_throws ArgumentError sort((1,2,3.0)) + end + @testset "sort!(iterable)" begin + gen = (x % 7 + 0.1x for x in 1:50) + @test sort(gen) == sort!(collect(gen)) + gen = (x % 7 + 0.1y for x in 1:10, y in 1:5) + @test sort(gen; dims=1) == sort!(collect(gen); dims=1) + @test sort(gen; dims=2) == sort!(collect(gen); dims=2) + + @test_throws ArgumentError("dimension out of range") sort(gen; dims=3) + + @test_throws UndefKeywordError(:dims) sort(gen) + @test_throws UndefKeywordError(:dims) sort(collect(gen)) + @test_throws UndefKeywordError(:dims) sort!(collect(gen)) + + @test_throws ArgumentError sort("string") + @test_throws ArgumentError("1 cannot be sorted") sort(1) + end +end From b43a5af823db69b597a8c593c30c0f0c5963aaac Mon Sep 17 00:00:00 2001 From: mtfishman Date: Tue, 1 Aug 2023 09:16:51 -0400 Subject: [PATCH 2/4] Improve function import style --- README.md | 2 +- src/Compat.jl | 19 +++++++++---------- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index bebd60902..8ffb9d174 100644 --- a/README.md +++ b/README.md @@ -70,7 +70,7 @@ changes in `julia`. ## Supported features -* `sort` for `NTuple` and iterables. ([#46104]) (since Compat 4.9.0) +* `sort` for `NTuple` and other iterables. ([#46104]) (since Compat 4.9.0) * `redirect_stdio`, for simple stream redirection. ([#37978]) (since Compat 4.8.0) diff --git a/src/Compat.jl b/src/Compat.jl index 9b9e4644a..8bc244917 100644 --- a/src/Compat.jl +++ b/src/Compat.jl @@ -643,11 +643,10 @@ end # https://github.com/JuliaLang/julia/pull/25085 if VERSION < v"1.8.0-beta2.17" || v"1.9.0-" <= VERSION < v"1.9.0-DEV.94" - import Base: trunc, floor, ceil, round - trunc(::Type{Bool}, x::AbstractFloat) = (-1 < x < 2) ? 1 <= x : throw(InexactError(:trunc, Bool, x)) - floor(::Type{Bool}, x::AbstractFloat) = (0 <= x < 2) ? 1 <= x : throw(InexactError(:floor, Bool, x)) - ceil(::Type{Bool}, x::AbstractFloat) = (-1 < x <= 1) ? 0 < x : throw(InexactError(:ceil, Bool, x)) - round(::Type{Bool}, x::AbstractFloat) = (-0.5 <= x < 1.5) ? 0.5 < x : throw(InexactError(:round, Bool, x)) + Base.trunc(::Type{Bool}, x::AbstractFloat) = (-1 < x < 2) ? 1 <= x : throw(InexactError(:trunc, Bool, x)) + Base.floor(::Type{Bool}, x::AbstractFloat) = (0 <= x < 2) ? 1 <= x : throw(InexactError(:floor, Bool, x)) + Base.ceil(::Type{Bool}, x::AbstractFloat) = (-1 < x <= 1) ? 0 < x : throw(InexactError(:ceil, Bool, x)) + Base.round(::Type{Bool}, x::AbstractFloat) = (-0.5 <= x < 1.5) ? 0.5 < x : throw(InexactError(:round, Bool, x)) end # https://github.com/JuliaLang/julia/pull/37978 @@ -708,19 +707,19 @@ end # https://github.com/JuliaLang/julia/pull/46104 if VERSION < v"1.10.0-DEV.1404" - import Base: sort, Ordering, Forward, ord, lt, tail, copymutable, DEFAULT_STABLE, IteratorSize, HasShape, IsInfinite - function sort(v; kws...) + using Base: Ordering, Forward, ord, lt, tail, copymutable, DEFAULT_STABLE, IteratorSize, HasShape, IsInfinite + function Base.sort(v; kws...) size = IteratorSize(v) size == HasShape{0}() && throw(ArgumentError("$v cannot be sorted")) size == IsInfinite() && throw(ArgumentError("infinite iterator $v cannot be sorted")) sort!(copymutable(v); kws...) end - sort(::AbstractString; kws...) = + Base.sort(::AbstractString; kws...) = throw(ArgumentError("sort(::AbstractString) is not supported")) - sort(::Tuple; kws...) = + Base.sort(::Tuple; kws...) = throw(ArgumentError("sort(::Tuple) is only supported for NTuples")) - function sort(x::NTuple{N}; lt::Function=isless, by::Function=identity, + function Base.sort(x::NTuple{N}; lt::Function=isless, by::Function=identity, rev::Union{Bool,Nothing}=nothing, order::Ordering=Forward) where N o = ord(lt,by,rev,order) if N > 9 From dc7d33a468c38447fcbb8df87740b62728c5cc1e Mon Sep 17 00:00:00 2001 From: mtfishman Date: Tue, 1 Aug 2023 09:20:48 -0400 Subject: [PATCH 3/4] Add explicit sort(AbstractVector) definition --- src/Compat.jl | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Compat.jl b/src/Compat.jl index 8bc244917..3c0dc5a5a 100644 --- a/src/Compat.jl +++ b/src/Compat.jl @@ -714,6 +714,7 @@ if VERSION < v"1.10.0-DEV.1404" size == IsInfinite() && throw(ArgumentError("infinite iterator $v cannot be sorted")) sort!(copymutable(v); kws...) end + sort(v::AbstractVector; kws...) = sort!(copymutable(v); kws...) # for method disambiguation Base.sort(::AbstractString; kws...) = throw(ArgumentError("sort(::AbstractString) is not supported")) Base.sort(::Tuple; kws...) = From 38ed62b863dae429396632f7c1545081c815de50 Mon Sep 17 00:00:00 2001 From: Matt Fishman Date: Tue, 1 Aug 2023 10:29:23 -0400 Subject: [PATCH 4/4] Remove `sort(AbstractVector)` Co-authored-by: Martin Holters --- src/Compat.jl | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Compat.jl b/src/Compat.jl index 3c0dc5a5a..8bc244917 100644 --- a/src/Compat.jl +++ b/src/Compat.jl @@ -714,7 +714,6 @@ if VERSION < v"1.10.0-DEV.1404" size == IsInfinite() && throw(ArgumentError("infinite iterator $v cannot be sorted")) sort!(copymutable(v); kws...) end - sort(v::AbstractVector; kws...) = sort!(copymutable(v); kws...) # for method disambiguation Base.sort(::AbstractString; kws...) = throw(ArgumentError("sort(::AbstractString) is not supported")) Base.sort(::Tuple; kws...) =