Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/fix-negative-offset-array' into …
Browse files Browse the repository at this point in the history
…stabilize-quicksort
  • Loading branch information
Lilith Hafner authored and Lilith Hafner committed Jun 4, 2022
2 parents 5ee7b06 + f06107e commit ab83655
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 42 deletions.
20 changes: 10 additions & 10 deletions base/sort.jl
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ module Sort
import ..@__MODULE__, ..parentmodule
const Base = parentmodule(@__MODULE__)
using .Base.Order
using .Base: length, first, last, axes, firstindex, lastindex, eltype, elsize,
using .Base: length, first, last, axes, firstindex, lastindex, eltype, elsize, checkbounds,
similar, iterate, keytype, copymutable, fill, eachindex, zip,
copyto!, reverse!, resize!, require_one_based_indexing,
AbstractVector, Vector, AbstractRange, OrdinalRange, UnitRange, LinearIndices,
Expand Down Expand Up @@ -632,7 +632,7 @@ function sort!(v::AbstractVector{T}, lo::Integer, hi::Integer, a::MergeSortAlg,
hi-lo <= SMALL_THRESHOLD && return sort!(v, lo, hi, SMALL_ALGORITHM, o)

m = midpoint(lo, hi)
t = workspace(v, t0, m-lo+1)
t = workspace(v, t0, Base.OneTo(m-lo+1))

sort!(v, lo, m, a, o, t)
sort!(v, m+1, hi, a, o, t)
Expand Down Expand Up @@ -684,7 +684,7 @@ function radix_sort!(v::AbstractVector{U}, lo::Integer, hi::Integer, bits::Unsig
t::AbstractVector{U}, chunk_size=radix_chunk_size_heuristic(lo, hi, bits)) where U <: Unsigned
# bits is unsigned for performance reasons.
mask = UInt(1) << chunk_size - 1
counts = Vector{UInt}(undef, mask+2)
counts = Vector{Int}(undef, mask+2)

@inbounds for shift in 0:chunk_size:bits-1

Expand Down Expand Up @@ -733,7 +733,7 @@ end

# For AbstractVector{Bool}, counting sort is always best.
# This is an implementation of counting sort specialized for Bools.
function sort!(v::AbstractVector{B}, lo::Integer, hi::Integer, ::AdaptiveSort, o::Ordering,
function sort!(v::AbstractVector{B}, lo::Integer, hi::Integer, ::AdaptiveSortAlg, o::Ordering,
t::Union{AbstractVector{B}, Nothing}=nothing) where {B <: Bool}
first = lt(o, false, true) ? false : lt(o, true, false) ? true : return v
count = 0
Expand All @@ -747,9 +747,9 @@ function sort!(v::AbstractVector{B}, lo::Integer, hi::Integer, ::AdaptiveSort, o
v
end

workspace(v::AbstractVector, ::Nothing, len::Integer) = similar(v, len)
function workspace(v::AbstractVector{T}, t::AbstractVector{T}, len::Integer) where T
length(t) < len ? resize!(t, len) : t
workspace(v::AbstractVector, ::Nothing, indices::AbstractUnitRange=eachindex(v)) = similar(v, indices)
function workspace(v::AbstractVector{T}, t::AbstractVector{T}, indices::AbstractUnitRange=eachindex(v)) where T
checkbounds(Bool, t, indices) ? t : similar(t, indices)
end
maybe_unsigned(x::Integer) = x # this is necessary to avoid calling unsigned on BigInt
maybe_unsigned(x::BitSigned) = unsigned(x)
Expand All @@ -762,12 +762,12 @@ function _extrema(v::AbstractVector, lo::Integer, hi::Integer, o::Ordering)
end
mn, mx
end
function sort!(v::AbstractVector{T}, lo::Integer, hi::Integer, ::AdaptiveSort, o::Ordering,
function sort!(v::AbstractVector{T}, lo::Integer, hi::Integer, ::AdaptiveSortAlg, o::Ordering,
t::Union{AbstractVector{T}, Nothing}=nothing) where T
# if the sorting task is not UIntMappable, then we can't radix sort or sort_int_range!
# so we skip straight to the fallback algorithm which is comparison based.
U = UIntMappable(T, o)
U === nothing && return sort!(v, lo, hi, a.fallback, o)
U === nothing && return sort!(v, lo, hi, QuickSort, o)

# to avoid introducing excessive detection costs for the trivial sorting problem
# and to avoid overflow, we check for small inputs before any other runtime checks
Expand Down Expand Up @@ -856,7 +856,7 @@ function sort!(v::AbstractVector{T}, lo::Integer, hi::Integer, ::AdaptiveSort, o
u[i] -= u_min
end

u2 = radix_sort!(u, lo, hi, bits, reinterpret(U, workspace(v, t, hi)))
u2 = radix_sort!(u, lo, hi, bits, reinterpret(U, workspace(v, t)))
uint_unmap!(v, u2, lo, hi, o, u_min)
end

Expand Down
69 changes: 37 additions & 32 deletions test/sorting.jl
Original file line number Diff line number Diff line change
Expand Up @@ -532,6 +532,16 @@ end
@test issorted(a)
end

@testset "sort!(::OffsetVector)" begin
for length in vcat(0:5, [10, 300, 500, 1000])
for offset in [-100000, -10, -1, 0, 1, 17, 1729]
x = OffsetVector(rand(length), offset)
sort!(x)
@test issorted(x)
end
end
end

@testset "sort!(::OffsetMatrix; dims)" begin
x = OffsetMatrix(rand(5,5), 5, -5)
sort!(x; dims=1)
Expand Down Expand Up @@ -673,11 +683,36 @@ end
end
end

<<<<<<< HEAD
@testset "workspace()" begin
for v in [[1, 2, 3], [0.0]]
for t0 in vcat([nothing], [similar(v,i) for i in 1:5]), axes in [0:5, 1:3, Base.OneTo(7), 3:2, -1:0]
t = Base.Sort.workspace(v, t0, axes)
@test eltype(t) == eltype(v)
@test checkbounds(Bool, t, axes)
end
end
end

@testset "sort(x; workspace=w) " begin
for n in [1,10,100,1000]
v = rand(n)
w = [0.0]
@test sort(v) == sort(v; workspace=w)
@test sort!(copy(v)) == sort!(copy(v); workspace=w)
@test sortperm(v) == sortperm(v; workspace=[4])
@test sortperm!(Vector{Int}(undef, n), v) == sortperm!(Vector{Int}(undef, n), v; workspace=[4])

n > 100 && continue
M = rand(n, n)
@test sort(M; dims=2) == sort(M; dims=2, workspace=w)
@test sort!(copy(M); dims=1) == sort!(copy(M); dims=1, workspace=w)
end
end

@testset "invalid lt (#11429)" begin
# lt must be a total linear order (e.g. < not <=) so this usage is
# not allowed. Consequently, none of the behavior tested in this
# testset is gaurunteed to work in future minor versions of Julia.
# testset is guaranteed to work in future minor versions of Julia.

n = 1000
v = rand(1:5, n);
Expand Down Expand Up @@ -712,36 +747,6 @@ end
end

# This testset is at the end of the file because it is slow
=======
@testset "workspace()" begin
for v in [[1, 2, 3], [0.0]]
for t0 in vcat([nothing], [similar(v,i) for i in 1:5]), len in 0:5
t = Base.Sort.workspace(v, t0, len)
@test eltype(t) == eltype(v)
@test length(t) >= len
@test firstindex(t) == 1
end
end
end

@testset "sort(x; workspace=w) " begin
for n in [1,10,100,1000]
v = rand(n)
w = [0.0]
@test sort(v) == sort(v; workspace=w)
@test sort!(copy(v)) == sort!(copy(v); workspace=w)
@test sortperm(v) == sortperm(v; workspace=[4])
@test sortperm!(Vector{Int}(undef, n), v) == sortperm!(Vector{Int}(undef, n), v; workspace=[4])

n > 100 && continue
M = rand(n, n)
@test sort(M; dims=2) == sort(M; dims=2, workspace=w)
@test sort!(copy(M); dims=1) == sort!(copy(M); dims=1, workspace=w)
end
end


>>>>>>> master
@testset "searchsorted" begin
numTypes = [ Int8, Int16, Int32, Int64, Int128,
UInt8, UInt16, UInt32, UInt64, UInt128,
Expand Down

0 comments on commit ab83655

Please sign in to comment.