@@ -86,7 +86,7 @@ issorted(itr;
86
86
issorted (itr, ord (lt,by,rev,order))
87
87
88
88
function partialsort! (v:: AbstractVector , k:: Union{Integer,OrdinalRange} , o:: Ordering )
89
- _sort! (v, QuickerSort (k), o, (;))
89
+ _sort! (v, InitialOptimizations ( QuickerSort (k) ), o, (;))
90
90
maybeview (v, k)
91
91
end
92
92
@@ -566,8 +566,30 @@ function _sort!(v::AbstractVector, a::MissingOptimization, o::Ordering, kw)
566
566
if nonmissingtype (eltype (v)) != eltype (v) && o isa DirectOrdering
567
567
lo, hi = send_to_end! (ismissing, v, o; lo, hi)
568
568
_sort! (WithoutMissingVector (v, unsafe= true ), a. next, o, (;kw... , lo, hi))
569
- elseif eltype (v) <: Integer && o isa Perm{DirectOrdering} && nonmissingtype (eltype (o. data)) != eltype (o. data)
570
- lo, hi = send_to_end! (i -> ismissing (@inbounds o. data[i]), v, o)
569
+ elseif eltype (v) <: Integer && o isa Perm && o. order isa DirectOrdering &&
570
+ nonmissingtype (eltype (o. data)) != eltype (o. data) &&
571
+ all (i === j for (i,j) in zip (v, eachindex (o. data)))
572
+ # TODO make this branch known at compile time
573
+ # This uses a custom function because we need to ensure stability of both sides and
574
+ # we can assume v is equal to eachindex(o.data) which allows a copying partition
575
+ # without allocations.
576
+ lo_i, hi_i = lo, hi
577
+ for (i,x) in zip (eachindex (o. data), o. data)
578
+ if ismissing (x) == (o. order == Reverse) # should i go at the beginning?
579
+ v[lo_i] = i
580
+ lo_i += 1
581
+ else
582
+ v[hi_i] = i
583
+ hi_i -= 1
584
+ end
585
+ end
586
+ reverse! (v, lo_i, hi)
587
+ if o. order == Reverse
588
+ lo = lo_i
589
+ else
590
+ hi = hi_i
591
+ end
592
+
571
593
_sort! (v, a. next, Perm (o. order, WithoutMissingVector (o. data, unsafe= true )), (;kw... , lo, hi))
572
594
else
573
595
_sort! (v, a. next, o, kw)
@@ -1160,7 +1182,9 @@ end
1160
1182
"""
1161
1183
InitialOptimizations(next) <: Algorithm
1162
1184
1163
- Attempt to apply a suite of low-cost optimizations to the input vector before sorting.
1185
+ Attempt to apply a suite of low-cost optimizations to the input vector before sorting. These
1186
+ optimizations may be automatically applied by the `sort!` family of functions when
1187
+ `alg=InsertionSort`, `alg=MergeSort`, or `alg=QuickSort` is passed as an argument.
1164
1188
1165
1189
`InitialOptimizations` is an implementation detail and subject to change or removal in
1166
1190
future versions of Julia.
@@ -1347,7 +1371,7 @@ function sort!(v::AbstractVector{T};
1347
1371
rev:: Union{Bool,Nothing} = nothing ,
1348
1372
order:: Ordering = Forward,
1349
1373
scratch:: Union{Vector{T}, Nothing} = nothing ) where T
1350
- _sort! (v, alg, ord (lt,by,rev,order), (;scratch))
1374
+ _sort! (v, maybe_apply_initial_optimizations ( alg) , ord (lt,by,rev,order), (;scratch))
1351
1375
v
1352
1376
end
1353
1377
@@ -1474,7 +1498,7 @@ function partialsortperm!(ix::AbstractVector{<:Integer}, v::AbstractVector,
1474
1498
end
1475
1499
1476
1500
# do partial quicksort
1477
- _sort! (ix, QuickerSort (k), Perm (ord (lt, by, rev, order), v), (;))
1501
+ _sort! (ix, InitialOptimizations ( QuickerSort (k) ), Perm (ord (lt, by, rev, order), v), (;))
1478
1502
1479
1503
maybeview (ix, k)
1480
1504
end
@@ -1679,11 +1703,11 @@ function sort(A::AbstractArray{T};
1679
1703
pdims = (dim, setdiff (1 : ndims (A), dim)... ) # put the selected dimension first
1680
1704
Ap = permutedims (A, pdims)
1681
1705
Av = vec (Ap)
1682
- sort_chunks! (Av, n, alg, order, scratch)
1706
+ sort_chunks! (Av, n, maybe_apply_initial_optimizations ( alg) , order, scratch)
1683
1707
permutedims (Ap, invperm (pdims))
1684
1708
else
1685
1709
Av = A[:]
1686
- sort_chunks! (Av, n, alg, order, scratch)
1710
+ sort_chunks! (Av, n, maybe_apply_initial_optimizations ( alg) , order, scratch)
1687
1711
reshape (Av, axes (A))
1688
1712
end
1689
1713
end
@@ -1746,7 +1770,7 @@ function sort!(A::AbstractArray{T};
1746
1770
rev:: Union{Bool,Nothing} = nothing ,
1747
1771
order:: Ordering = Forward, # TODO stop eagerly over-allocating.
1748
1772
scratch:: Union{Vector{T}, Nothing} = similar (A, size (A, dims))) where T
1749
- __sort! (A, Val (dims), alg, ord (lt, by, rev, order), scratch)
1773
+ __sort! (A, Val (dims), maybe_apply_initial_optimizations ( alg) , ord (lt, by, rev, order), scratch)
1750
1774
end
1751
1775
function __sort! (A:: AbstractArray{T} , :: Val{K} ,
1752
1776
alg:: Algorithm ,
@@ -1911,6 +1935,11 @@ Characteristics:
1911
1935
"""
1912
1936
const MergeSort = MergeSortAlg ()
1913
1937
1938
+ maybe_apply_initial_optimizations (alg:: Algorithm ) = alg
1939
+ maybe_apply_initial_optimizations (alg:: QuickSortAlg ) = InitialOptimizations (alg)
1940
+ maybe_apply_initial_optimizations (alg:: MergeSortAlg ) = InitialOptimizations (alg)
1941
+ maybe_apply_initial_optimizations (alg:: InsertionSortAlg ) = InitialOptimizations (alg)
1942
+
1914
1943
# selectpivot!
1915
1944
#
1916
1945
# Given 3 locations in an array (lo, mi, and hi), sort v[lo], v[mi], v[hi]) and
0 commit comments