diff --git a/base/sort.jl b/base/sort.jl index 1266da8a8c9df..669d2d97b2ac1 100644 --- a/base/sort.jl +++ b/base/sort.jl @@ -1560,8 +1560,14 @@ function sortperm(A::AbstractArray; order::Ordering=Forward, scratch::Union{Vector{<:Integer}, Nothing}=nothing, dims...) #to optionally specify dims argument - ordr = ord(lt,by,rev,order) - if ordr === Forward && isa(A,Vector) && eltype(A)<:Integer + if rev === true + _sortperm(A; alg, order=ord(lt, by, true, order), scratch, dims...) + else + _sortperm(A; alg, order=ord(lt, by, nothing, order), scratch, dims...) + end +end +function _sortperm(A::AbstractArray; alg, order, scratch, dims...) + if order === Forward && isa(A,Vector) && eltype(A)<:Integer n = length(A) if n > 1 min, max = extrema(A) @@ -1573,7 +1579,7 @@ function sortperm(A::AbstractArray; end end ix = copymutable(LinearIndices(A)) - sort!(ix; alg, order = Perm(ordr, vec(A)), scratch, dims...) + sort!(ix; alg, order = Perm(order, vec(A)), scratch, dims...) end @@ -1615,7 +1621,7 @@ julia> sortperm!(p, A; dims=2); p 2 4 ``` """ -function sortperm!(ix::AbstractArray{T}, A::AbstractArray; +@inline function sortperm!(ix::AbstractArray{T}, A::AbstractArray; alg::Algorithm=DEFAULT_UNSTABLE, lt=isless, by=identity, @@ -1630,7 +1636,12 @@ function sortperm!(ix::AbstractArray{T}, A::AbstractArray; if !initialized ix .= LinearIndices(A) end - sort!(ix; alg, order = Perm(ord(lt, by, rev, order), vec(A)), scratch, dims...) + + if rev === true + sort!(ix; alg, order=Perm(ord(lt, by, true, order), vec(A)), scratch, dims...) + else + sort!(ix; alg, order=Perm(ord(lt, by, nothing, order), vec(A)), scratch, dims...) + end end # sortperm for vectors of few unique integers diff --git a/test/sorting.jl b/test/sorting.jl index eb5020547c789..c4e324a61cde9 100644 --- a/test/sorting.jl +++ b/test/sorting.jl @@ -918,6 +918,28 @@ end @test bsqs() === bsqs(missing, missing, InsertionSort) end +function test_allocs() + v = rand(10) + i = randperm(length(v)) + @test 1 == @allocations sort(v) + @test 0 == @allocations sortperm!(i, v) + @test 0 == @allocations sort!(i) + @test 0 == @allocations sortperm!(i, v, rev=true) + @test 1 == @allocations sortperm(v, rev=true) + @test 1 == @allocations sortperm(v, rev=false) + @test 0 == @allocations sortperm!(i, v, order=Base.Reverse) + @test 1 == @allocations sortperm(v) + @test 1 == @allocations sortperm(i, by=sqrt) + @test 0 == @allocations sort!(v, lt=(a, b) -> hash(a) < hash(b)) + sort!(Int[], rev=false) # compile + @test 0 == @allocations sort!(i, rev=false) + rand!(i) + @test 0 == @allocations sort!(i, order=Base.Reverse) +end +@testset "Small calls do not unnecessarily allocate" begin + test_allocs() +end + # This testset is at the end of the file because it is slow. @testset "searchsorted" begin numTypes = [ Int8, Int16, Int32, Int64, Int128,