Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make DefaultStable and DefaultUnstable dispatchable and display without internals #56661

Merged
merged 12 commits into from
Nov 26, 2024
61 changes: 41 additions & 20 deletions base/sort.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1475,21 +1475,15 @@ InitialOptimizations(next) = SubArrayOptimization(
Small{10}(
IEEEFloatOptimization(
next)))))
"""
DEFAULT_STABLE

The default sorting algorithm.

This algorithm is guaranteed to be stable (i.e. it will not reorder elements that compare
equal). It makes an effort to be fast for most inputs.

The algorithms used by `DEFAULT_STABLE` are an implementation detail. See extended help
for the current dispatch system.
"""
struct DefaultStable <: Algorithm end

# Extended Help
`DefaultStable` is an algorithm which indicates that a fast, general purpose sorting
algorithm should be used, but does not specify exactly which algorithm.

`DEFAULT_STABLE` is composed of two parts: the [`InitialOptimizations`](@ref) and a hybrid
of Radix, Insertion, Counting, Quick sorts.
Currently, it is composed of two parts: the [`InitialOptimizations`](@ref) and a hybrid of
Radix, Insertion, Counting, Quick sorts.

We begin with MissingOptimization because it has no runtime cost when it is not
triggered and can enable other optimizations to be applied later. For example,
Expand Down Expand Up @@ -1549,7 +1543,39 @@ stage.
Finally, if the input has length less than 80, we dispatch to [`InsertionSort`](@ref) and
otherwise we dispatch to [`ScratchQuickSort`](@ref).
"""
const DEFAULT_STABLE = InitialOptimizations(
struct DefaultStable <: Algorithm end

"""
DEFAULT_STABLE

The default sorting algorithm.

This algorithm is guaranteed to be stable (i.e. it will not reorder elements that compare
equal). It makes an effort to be fast for most inputs.

The algorithms used by `DEFAULT_STABLE` are an implementation detail. See the docstring
of `Base.Sort.DefaultStable` for the current dispatch system.
"""
const DEFAULT_STABLE = DefaultStable()

"""
DefaultUnstable <: Algorithm

Like [`DefaultStable`](@ref), but does not guarantee stability.
"""
struct DefaultUnstable <: Algorithm end

"""
DEFAULT_UNSTABLE

An efficient sorting algorithm which may or may not be stable.

The algorithms used by `DEFAULT_UNSTABLE` are an implementation detail. They are currently
the same as those used by [`DEFAULT_STABLE`](@ref), but this is subject to change in future.
"""
const DEFAULT_UNSTABLE = DefaultUnstable()

const _DEFAULT_ALGORITHMS_FOR_VECTORS = InitialOptimizations(
IsUIntMappable(
Small{40}(
CheckSorted(
Expand All @@ -1560,15 +1586,10 @@ const DEFAULT_STABLE = InitialOptimizations(
ScratchQuickSort())))))),
StableCheckSorted(
ScratchQuickSort())))
"""
DEFAULT_UNSTABLE

An efficient sorting algorithm.
_sort!(v::AbstractVector, ::Union{DefaultStable, DefaultUnstable}, o::Ordering, kw) =
_sort!(v, _DEFAULT_ALGORITHMS_FOR_VECTORS, o, kw)

The algorithms used by `DEFAULT_UNSTABLE` are an implementation detail. They are currently
the same as those used by [`DEFAULT_STABLE`](@ref), but this is subject to change in future.
"""
const DEFAULT_UNSTABLE = DEFAULT_STABLE
const SMALL_THRESHOLD = 20

function Base.show(io::IO, alg::Algorithm)
Expand Down
15 changes: 9 additions & 6 deletions test/sorting.jl
Original file line number Diff line number Diff line change
Expand Up @@ -819,9 +819,9 @@ end
let
requires_uint_mappable = Union{Base.Sort.RadixSort, Base.Sort.ConsiderRadixSort,
Base.Sort.CountingSort, Base.Sort.ConsiderCountingSort,
typeof(Base.Sort.DEFAULT_STABLE.next.next.next.big.next.yes),
typeof(Base.Sort.DEFAULT_STABLE.next.next.next.big.next.yes.big),
typeof(Base.Sort.DEFAULT_STABLE.next.next.next.big.next.yes.big.next)}
typeof(Base.Sort._DEFAULT_ALGORITHMS_FOR_VECTORS.next.next.next.big.next.yes),
typeof(Base.Sort._DEFAULT_ALGORITHMS_FOR_VECTORS.next.next.next.big.next.yes.big),
typeof(Base.Sort._DEFAULT_ALGORITHMS_FOR_VECTORS.next.next.next.big.next.yes.big.next)}

function test_alg(kw, alg, float=true)
for order in [Base.Forward, Base.Reverse, Base.By(x -> x^2)]
Expand Down Expand Up @@ -861,15 +861,18 @@ end
end
end

test_alg_rec(Base.DEFAULT_STABLE)
test_alg_rec(Base.Sort._DEFAULT_ALGORITHMS_FOR_VECTORS)
end
end

@testset "show(::Algorithm)" begin
@test eval(Meta.parse(string(Base.DEFAULT_STABLE))) === Base.DEFAULT_STABLE
lines = split(string(Base.DEFAULT_STABLE), '\n')
@test eval(Meta.parse(string(Base.Sort._DEFAULT_ALGORITHMS_FOR_VECTORS))) === Base.Sort._DEFAULT_ALGORITHMS_FOR_VECTORS
lines = split(string(Base.Sort._DEFAULT_ALGORITHMS_FOR_VECTORS), '\n')
@test 10 < maximum(length, lines) < 100
@test 1 < length(lines) < 30

@test eval(Meta.parse(string(Base.DEFAULT_STABLE))) === Base.DEFAULT_STABLE
@test string(Base.DEFAULT_STABLE) == "Base.Sort.DefaultStable()"
end

@testset "Extensibility" begin
Expand Down