Advertisement
Guest User

sort.jl

a guest
Feb 16th, 2022
49
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Julia 42.08 KB | None | 0 0
  1. # This file is a part of Julia. License is MIT: https://julialang.org/license
  2.  
  3. module Sort
  4.  
  5. import ..@__MODULE__, ..parentmodule
  6. const Base = parentmodule(@__MODULE__)
  7. using .Base.Order
  8. using .Base: copymutable, LinearIndices, length, (:),
  9.     eachindex, axes, first, last, similar, zip, OrdinalRange,
  10.     AbstractVector, @inbounds, AbstractRange, @eval, @inline, Vector, @noinline,
  11.     AbstractMatrix, AbstractUnitRange, isless, identity, eltype, >, <, <=, >=, |, +, -, *, !,
  12.     extrema, sub_with_overflow, add_with_overflow, oneunit, div, getindex, setindex!,
  13.     length, resize!, fill, Missing, require_one_based_indexing, keytype,
  14.     UnitRange, max, min
  15.  
  16. using .Base: >>>, !==
  17.  
  18. import .Base:
  19.     sort,
  20.     sort!,
  21.     issorted,
  22.     sortperm,
  23.     to_indices
  24.  
  25. export # also exported by Base
  26.     # order-only:
  27.     issorted,
  28.     searchsorted,
  29.     searchsortedfirst,
  30.     searchsortedlast,
  31.     insorted,
  32.     # order & algorithm:
  33.     sort,
  34.     sort!,
  35.     sortperm,
  36.     sortperm!,
  37.     partialsort,
  38.     partialsort!,
  39.     partialsortperm,
  40.     partialsortperm!,
  41.     # algorithms:
  42.     InsertionSort,
  43.     QuickSort,
  44.     MergeSort,
  45.     PartialQuickSort
  46.  
  47. export # not exported by Base
  48.     Algorithm,
  49.     DEFAULT_UNSTABLE,
  50.     DEFAULT_STABLE,
  51.     SMALL_ALGORITHM,
  52.     SMALL_THRESHOLD
  53.  
  54.  
  55. ## functions requiring only ordering ##
  56.  
  57. function issorted(itr, order::Ordering)
  58.     y = iterate(itr)
  59.     y === nothing && return true
  60.     prev, state = y
  61.     y = iterate(itr, state)
  62.     while y !== nothing
  63.         this, state = y
  64.         lt(order, this, prev) && return false
  65.         prev = this
  66.         y = iterate(itr, state)
  67.     end
  68.     return true
  69. end
  70.  
  71. """
  72.    issorted(v, lt=isless, by=identity, rev::Bool=false, order::Ordering=Forward)
  73.  
  74. Test whether a vector is in sorted order. The `lt`, `by` and `rev` keywords modify what
  75. order is considered to be sorted just as they do for [`sort`](@ref).
  76.  
  77. # Examples
  78. ```jldoctest
  79. julia> issorted([1, 2, 3])
  80. true
  81.  
  82. julia> issorted([(1, "b"), (2, "a")], by = x -> x[1])
  83. true
  84.  
  85. julia> issorted([(1, "b"), (2, "a")], by = x -> x[2])
  86. false
  87.  
  88. julia> issorted([(1, "b"), (2, "a")], by = x -> x[2], rev=true)
  89. true
  90. ```
  91. """
  92. issorted(itr;
  93.     lt=isless, by=identity, rev::Union{Bool,Nothing}=nothing, order::Ordering=Forward) =
  94.     issorted(itr, ord(lt,by,rev,order))
  95.  
  96. function partialsort!(v::AbstractVector, k::Union{Integer,OrdinalRange}, o::Ordering)
  97.     inds = axes(v, 1)
  98.     sort!(v, first(inds), last(inds), PartialQuickSort(k), o)
  99.     maybeview(v, k)
  100. end
  101.  
  102. maybeview(v, k) = view(v, k)
  103. maybeview(v, k::Integer) = v[k]
  104.  
  105. """
  106.    partialsort!(v, k; by=<transform>, lt=<comparison>, rev=false)
  107.  
  108. Partially sort the vector `v` in place, according to the order specified by `by`, `lt` and
  109. `rev` so that the value at index `k` (or range of adjacent values if `k` is a range) occurs
  110. at the position where it would appear if the array were fully sorted via a non-stable
  111. algorithm. If `k` is a single index, that value is returned; if `k` is a range, an array of
  112. values at those indices is returned. Note that `partialsort!` does not fully sort the input
  113. array.
  114.  
  115. # Examples
  116. ```jldoctest
  117. julia> a = [1, 2, 4, 3, 4]
  118. 5-element Vector{Int64}:
  119. 1
  120. 2
  121. 4
  122. 3
  123. 4
  124.  
  125. julia> partialsort!(a, 4)
  126. 4
  127.  
  128. julia> a
  129. 5-element Vector{Int64}:
  130. 1
  131. 2
  132. 3
  133. 4
  134. 4
  135.  
  136. julia> a = [1, 2, 4, 3, 4]
  137. 5-element Vector{Int64}:
  138. 1
  139. 2
  140. 4
  141. 3
  142. 4
  143.  
  144. julia> partialsort!(a, 4, rev=true)
  145. 2
  146.  
  147. julia> a
  148. 5-element Vector{Int64}:
  149. 4
  150. 4
  151. 3
  152. 2
  153. 1
  154. ```
  155. """
  156. partialsort!(v::AbstractVector, k::Union{Integer,OrdinalRange};
  157.              lt=isless, by=identity, rev::Union{Bool,Nothing}=nothing, order::Ordering=Forward) =
  158.     partialsort!(v, k, ord(lt,by,rev,order))
  159.  
  160. """
  161.    partialsort(v, k, by=<transform>, lt=<comparison>, rev=false)
  162.  
  163. Variant of [`partialsort!`](@ref) which copies `v` before partially sorting it, thereby returning the
  164. same thing as `partialsort!` but leaving `v` unmodified.
  165. """
  166. partialsort(v::AbstractVector, k::Union{Integer,OrdinalRange}; kws...) =
  167.     partialsort!(copymutable(v), k; kws...)
  168.  
  169. # This implementation of `midpoint` is performance-optimized but safe
  170. # only if `lo <= hi`.
  171. midpoint(lo::T, hi::T) where T<:Integer = lo + ((hi - lo) >>> 0x01)
  172. midpoint(lo::Integer, hi::Integer) = midpoint(promote(lo, hi)...)
  173.  
  174. # reference on sorted binary search:
  175. #   http://www.tbray.org/ongoing/When/200x/2003/03/22/Binary
  176.  
  177. # index of the first value of vector a that is greater than or equal to x;
  178. # returns length(v)+1 if x is greater than all values in v.
  179. function searchsortedfirst(v::AbstractVector, x, lo::T, hi::T, o::Ordering)::keytype(v) where T<:Integer
  180.     u = T(1)
  181.     lo = lo - u
  182.     hi = hi + u
  183.     @inbounds while lo < hi - u
  184.         m = midpoint(lo, hi)
  185.         if lt(o, v[m], x)
  186.             lo = m
  187.         else
  188.             hi = m
  189.         end
  190.     end
  191.     return hi
  192. end
  193.  
  194. # index of the last value of vector a that is less than or equal to x;
  195. # returns 0 if x is less than all values of v.
  196. function searchsortedlast(v::AbstractVector, x, lo::T, hi::T, o::Ordering)::keytype(v) where T<:Integer
  197.     u = T(1)
  198.     lo = lo - u
  199.     hi = hi + u
  200.     @inbounds while lo < hi - u
  201.         m = midpoint(lo, hi)
  202.         if lt(o, x, v[m])
  203.             hi = m
  204.         else
  205.             lo = m
  206.         end
  207.     end
  208.     return lo
  209. end
  210.  
  211. # returns the range of indices of v equal to x
  212. # if v does not contain x, returns a 0-length range
  213. # indicating the insertion point of x
  214. function searchsorted(v::AbstractVector, x, ilo::T, ihi::T, o::Ordering)::UnitRange{keytype(v)} where T<:Integer
  215.     u = T(1)
  216.     lo = ilo - u
  217.     hi = ihi + u
  218.     @inbounds while lo < hi - u
  219.         m = midpoint(lo, hi)
  220.         if lt(o, v[m], x)
  221.             lo = m
  222.         elseif lt(o, x, v[m])
  223.             hi = m
  224.         else
  225.             a = searchsortedfirst(v, x, max(lo,ilo), m, o)
  226.             b = searchsortedlast(v, x, m, min(hi,ihi), o)
  227.             return a : b
  228.         end
  229.     end
  230.     return (lo + 1) : (hi - 1)
  231. end
  232.  
  233. function searchsortedlast(a::AbstractRange{<:Real}, x::Real, o::DirectOrdering)::keytype(a)
  234.     require_one_based_indexing(a)
  235.     f, h, l = first(a), step(a), last(a)
  236.     if lt(o, x, f)
  237.         0
  238.     elseif h == 0 || !lt(o, x, l)
  239.         length(a)
  240.     else
  241.         n = round(Integer, (x - f) / h + 1)
  242.         lt(o, x, a[n]) ? n - 1 : n
  243.     end
  244. end
  245.  
  246. function searchsortedfirst(a::AbstractRange{<:Real}, x::Real, o::DirectOrdering)::keytype(a)
  247.     require_one_based_indexing(a)
  248.     f, h, l = first(a), step(a), last(a)
  249.     if !lt(o, f, x)
  250.         1
  251.     elseif h == 0 || lt(o, l, x)
  252.         length(a) + 1
  253.     else
  254.         n = round(Integer, (x - f) / h + 1)
  255.         lt(o, a[n], x) ? n + 1 : n
  256.     end
  257. end
  258.  
  259. function searchsortedlast(a::AbstractRange{<:Integer}, x::Real, o::DirectOrdering)::keytype(a)
  260.     require_one_based_indexing(a)
  261.     f, h, l = first(a), step(a), last(a)
  262.     if lt(o, x, f)
  263.         0
  264.     elseif h == 0 || !lt(o, x, l)
  265.         length(a)
  266.     else
  267.         if o isa ForwardOrdering
  268.             fld(floor(Integer, x) - f, h) + 1
  269.         else
  270.             fld(ceil(Integer, x) - f, h) + 1
  271.         end
  272.     end
  273. end
  274.  
  275. function searchsortedfirst(a::AbstractRange{<:Integer}, x::Real, o::DirectOrdering)::keytype(a)
  276.     require_one_based_indexing(a)
  277.     f, h, l = first(a), step(a), last(a)
  278.     if !lt(o, f, x)
  279.         1
  280.     elseif h == 0 || lt(o, l, x)
  281.         length(a) + 1
  282.     else
  283.         if o isa ForwardOrdering
  284.             cld(ceil(Integer, x) - f, h) + 1
  285.         else
  286.             cld(floor(Integer, x) - f, h) + 1
  287.         end
  288.     end
  289. end
  290.  
  291. searchsorted(a::AbstractRange{<:Real}, x::Real, o::DirectOrdering) =
  292.     searchsortedfirst(a, x, o) : searchsortedlast(a, x, o)
  293.  
  294. for s in [:searchsortedfirst, :searchsortedlast, :searchsorted]
  295.     @eval begin
  296.         $s(v::AbstractVector, x, o::Ordering) = (inds = axes(v, 1); $s(v,x,first(inds),last(inds),o))
  297.         $s(v::AbstractVector, x;
  298.            lt=isless, by=identity, rev::Union{Bool,Nothing}=nothing, order::Ordering=Forward) =
  299.             $s(v,x,ord(lt,by,rev,order))
  300.     end
  301. end
  302.  
  303. """
  304.    searchsorted(a, x; by=<transform>, lt=<comparison>, rev=false)
  305.  
  306. Return the range of indices of `a` which compare as equal to `x` (using binary search)
  307. according to the order specified by the `by`, `lt` and `rev` keywords, assuming that `a`
  308. is already sorted in that order. Return an empty range located at the insertion point
  309. if `a` does not contain values equal to `x`.
  310.  
  311. See also: [`insorted`](@ref), [`searchsortedfirst`](@ref), [`sort`](@ref), [`findall`](@ref).
  312.  
  313. # Examples
  314. ```jldoctest
  315. julia> searchsorted([1, 2, 4, 5, 5, 7], 4) # single match
  316. 3:3
  317.  
  318. julia> searchsorted([1, 2, 4, 5, 5, 7], 5) # multiple matches
  319. 4:5
  320.  
  321. julia> searchsorted([1, 2, 4, 5, 5, 7], 3) # no match, insert in the middle
  322. 3:2
  323.  
  324. julia> searchsorted([1, 2, 4, 5, 5, 7], 9) # no match, insert at end
  325. 7:6
  326.  
  327. julia> searchsorted([1, 2, 4, 5, 5, 7], 0) # no match, insert at start
  328. 1:0
  329. ```
  330. """ searchsorted
  331.  
  332. """
  333.    searchsortedfirst(a, x; by=<transform>, lt=<comparison>, rev=false)
  334.  
  335. Return the index of the first value in `a` greater than or equal to `x`, according to the
  336. specified order. Return `lastindex(a) + 1` if `x` is greater than all values in `a`.
  337. `a` is assumed to be sorted.
  338.  
  339. See also: [`searchsortedlast`](@ref), [`searchsorted`](@ref), [`findfirst`](@ref).
  340.  
  341. # Examples
  342. ```jldoctest
  343. julia> searchsortedfirst([1, 2, 4, 5, 5, 7], 4) # single match
  344. 3
  345.  
  346. julia> searchsortedfirst([1, 2, 4, 5, 5, 7], 5) # multiple matches
  347. 4
  348.  
  349. julia> searchsortedfirst([1, 2, 4, 5, 5, 7], 3) # no match, insert in the middle
  350. 3
  351.  
  352. julia> searchsortedfirst([1, 2, 4, 5, 5, 7], 9) # no match, insert at end
  353. 7
  354.  
  355. julia> searchsortedfirst([1, 2, 4, 5, 5, 7], 0) # no match, insert at start
  356. 1
  357. ```
  358. """ searchsortedfirst
  359.  
  360. """
  361.    searchsortedlast(a, x; by=<transform>, lt=<comparison>, rev=false)
  362.  
  363. Return the index of the last value in `a` less than or equal to `x`, according to the
  364. specified order. Return `firstindex(a) - 1` if `x` is less than all values in `a`. `a` is
  365. assumed to be sorted.
  366.  
  367. # Examples
  368. ```jldoctest
  369. julia> searchsortedlast([1, 2, 4, 5, 5, 7], 4) # single match
  370. 3
  371.  
  372. julia> searchsortedlast([1, 2, 4, 5, 5, 7], 5) # multiple matches
  373. 5
  374.  
  375. julia> searchsortedlast([1, 2, 4, 5, 5, 7], 3) # no match, insert in the middle
  376. 2
  377.  
  378. julia> searchsortedlast([1, 2, 4, 5, 5, 7], 9) # no match, insert at end
  379. 6
  380.  
  381. julia> searchsortedlast([1, 2, 4, 5, 5, 7], 0) # no match, insert at start
  382. 0
  383. ```
  384. """ searchsortedlast
  385.  
  386. """
  387.    insorted(a, x; by=<transform>, lt=<comparison>, rev=false) -> Bool
  388.  
  389. Determine whether an item is in the given sorted collection, in the sense that
  390. it is [`==`](@ref) to one of the values of the collection according to the order
  391. specified by the `by`, `lt` and `rev` keywords, assuming that `a` is already
  392. sorted in that order, see [`sort`](@ref) for the keywords.
  393.  
  394. See also [`in`](@ref).
  395.  
  396. # Examples
  397. ```jldoctest
  398. julia> insorted(4, [1, 2, 4, 5, 5, 7]) # single match
  399. true
  400.  
  401. julia> insorted(5, [1, 2, 4, 5, 5, 7]) # multiple matches
  402. true
  403.  
  404. julia> insorted(3, [1, 2, 4, 5, 5, 7]) # no match
  405. false
  406.  
  407. julia> insorted(9, [1, 2, 4, 5, 5, 7]) # no match
  408. false
  409.  
  410. julia> insorted(0, [1, 2, 4, 5, 5, 7]) # no match
  411. false
  412. ```
  413.  
  414. !!! compat "Julia 1.6"
  415.     `insorted` was added in Julia 1.6.
  416. """
  417. function insorted end
  418. insorted(x, v::AbstractVector; kw...) = !isempty(searchsorted(v, x; kw...))
  419. insorted(x, r::AbstractRange) = in(x, r)
  420.  
  421. ## sorting algorithms ##
  422.  
  423. abstract type Algorithm end
  424.  
  425. struct InsertionSortAlg <: Algorithm end
  426. struct QuickSortAlg     <: Algorithm end
  427. struct MergeSortAlg     <: Algorithm end
  428.  
  429. """
  430.    PartialQuickSort{T <: Union{Integer,OrdinalRange}}
  431.  
  432. Indicate that a sorting function should use the partial quick sort
  433. algorithm. Partial quick sort returns the smallest `k` elements sorted from smallest
  434. to largest, finding them and sorting them using [`QuickSort`](@ref).
  435.  
  436. Characteristics:
  437.  * *not stable*: does not preserve the ordering of elements which
  438.    compare equal (e.g. "a" and "A" in a sort of letters which
  439.    ignores case).
  440.  * *in-place* in memory.
  441.  * *divide-and-conquer*: sort strategy similar to [`MergeSort`](@ref).
  442. """
  443. struct PartialQuickSort{T <: Union{Integer,OrdinalRange}} <: Algorithm
  444.     k::T
  445. end
  446.  
  447. """
  448. TODO
  449. """
  450. struct RadixSort2{Fallback <: Algorithm} <: Algorithm
  451.     fallback::Fallback
  452. end
  453.  
  454. """
  455.    InsertionSort
  456.  
  457. Indicate that a sorting function should use the insertion sort
  458. algorithm. Insertion sort traverses the collection one element
  459. at a time, inserting each element into its correct, sorted position in
  460. the output list.
  461.  
  462. Characteristics:
  463.  * *stable*: preserves the ordering of elements which
  464.    compare equal (e.g. "a" and "A" in a sort of letters
  465.    which ignores case).
  466.  * *in-place* in memory.
  467.  * *quadratic performance* in the number of elements to be sorted:
  468.    it is well-suited to small collections but should not be used for large ones.
  469. """
  470. const InsertionSort = InsertionSortAlg()
  471. """
  472.    QuickSort
  473.  
  474. Indicate that a sorting function should use the quick sort
  475. algorithm, which is *not* stable.
  476.  
  477. Characteristics:
  478.  * *not stable*: does not preserve the ordering of elements which
  479.    compare equal (e.g. "a" and "A" in a sort of letters which
  480.    ignores case).
  481.  * *in-place* in memory.
  482.  * *divide-and-conquer*: sort strategy similar to [`MergeSort`](@ref).
  483.  * *good performance* for large collections.
  484. """
  485. const QuickSort     = QuickSortAlg()
  486. """
  487.    MergeSort
  488.  
  489. Indicate that a sorting function should use the merge sort
  490. algorithm. Merge sort divides the collection into
  491. subcollections and repeatedly merges them, sorting each
  492. subcollection at each step, until the entire
  493. collection has been recombined in sorted form.
  494.  
  495. Characteristics:
  496.  * *stable*: preserves the ordering of elements which compare
  497.    equal (e.g. "a" and "A" in a sort of letters which ignores
  498.    case).
  499.  * *not in-place* in memory.
  500.  * *divide-and-conquer* sort strategy.
  501. """
  502. const MergeSort     = MergeSortAlg()
  503.  
  504. const DEFAULT_UNSTABLE = QuickSort
  505. const DEFAULT_STABLE   = MergeSort
  506. const SMALL_ALGORITHM  = InsertionSort
  507. const SMALL_THRESHOLD  = 20
  508.  
  509. function sort!(v::AbstractVector, lo::Integer, hi::Integer, ::InsertionSortAlg, o::Ordering)
  510.     @inbounds for i = lo+1:hi
  511.         j = i
  512.         x = v[i]
  513.         while j > lo
  514.             if lt(o, x, v[j-1])
  515.                 v[j] = v[j-1]
  516.                 j -= 1
  517.                 continue
  518.             end
  519.             break
  520.         end
  521.         v[j] = x
  522.     end
  523.     return v
  524. end
  525.  
  526. # selectpivot!
  527. #
  528. # Given 3 locations in an array (lo, mi, and hi), sort v[lo], v[mi], v[hi]) and
  529. # choose the middle value as a pivot
  530. #
  531. # Upon return, the pivot is in v[lo], and v[hi] is guaranteed to be
  532. # greater than the pivot
  533.  
  534. @inline function selectpivot!(v::AbstractVector, lo::Integer, hi::Integer, o::Ordering)
  535.     @inbounds begin
  536.         mi = midpoint(lo, hi)
  537.  
  538.         # sort v[mi] <= v[lo] <= v[hi] such that the pivot is immediately in place
  539.         if lt(o, v[lo], v[mi])
  540.             v[mi], v[lo] = v[lo], v[mi]
  541.         end
  542.  
  543.         if lt(o, v[hi], v[lo])
  544.             if lt(o, v[hi], v[mi])
  545.                 v[hi], v[lo], v[mi] = v[lo], v[mi], v[hi]
  546.             else
  547.                 v[hi], v[lo] = v[lo], v[hi]
  548.             end
  549.         end
  550.  
  551.         # return the pivot
  552.         return v[lo]
  553.     end
  554. end
  555.  
  556. # partition!
  557. #
  558. # select a pivot, and partition v according to the pivot
  559.  
  560. function partition!(v::AbstractVector, lo::Integer, hi::Integer, o::Ordering)
  561.     pivot = selectpivot!(v, lo, hi, o)
  562.     # pivot == v[lo], v[hi] > pivot
  563.     i, j = lo, hi
  564.     @inbounds while true
  565.         i += 1; j -= 1
  566.         while lt(o, v[i], pivot); i += 1; end;
  567.         while lt(o, pivot, v[j]); j -= 1; end;
  568.         i >= j && break
  569.         v[i], v[j] = v[j], v[i]
  570.     end
  571.     v[j], v[lo] = pivot, v[j]
  572.  
  573.     # v[j] == pivot
  574.     # v[k] >= pivot for k > j
  575.     # v[i] <= pivot for i < j
  576.     return j
  577. end
  578.  
  579. function sort!(v::AbstractVector, lo::Integer, hi::Integer, a::QuickSortAlg, o::Ordering)
  580.     @inbounds while lo < hi
  581.         hi-lo <= SMALL_THRESHOLD && return sort!(v, lo, hi, SMALL_ALGORITHM, o)
  582.         j = partition!(v, lo, hi, o)
  583.         if j-lo < hi-j
  584.             # recurse on the smaller chunk
  585.             # this is necessary to preserve O(log(n))
  586.             # stack space in the worst case (rather than O(n))
  587.             lo < (j-1) && sort!(v, lo, j-1, a, o)
  588.             lo = j+1
  589.         else
  590.             j+1 < hi && sort!(v, j+1, hi, a, o)
  591.             hi = j-1
  592.         end
  593.     end
  594.     return v
  595. end
  596.  
  597. function sort!(v::AbstractVector, lo::Integer, hi::Integer, a::MergeSortAlg, o::Ordering, t=similar(v,0))
  598.     @inbounds if lo < hi
  599.         hi-lo <= SMALL_THRESHOLD && return sort!(v, lo, hi, SMALL_ALGORITHM, o)
  600.  
  601.         m = midpoint(lo, hi)
  602.         (length(t) < m-lo+1) && resize!(t, m-lo+1)
  603.  
  604.         sort!(v, lo,  m,  a, o, t)
  605.         sort!(v, m+1, hi, a, o, t)
  606.  
  607.         i, j = 1, lo
  608.         while j <= m
  609.             t[i] = v[j]
  610.             i += 1
  611.             j += 1
  612.         end
  613.  
  614.         i, k = 1, lo
  615.         while k < j <= hi
  616.             if lt(o, v[j], t[i])
  617.                 v[k] = v[j]
  618.                 j += 1
  619.             else
  620.                 v[k] = t[i]
  621.                 i += 1
  622.             end
  623.             k += 1
  624.         end
  625.         while k < j
  626.             v[k] = t[i]
  627.             k += 1
  628.             i += 1
  629.         end
  630.     end
  631.  
  632.     return v
  633. end
  634.  
  635. function sort!(v::AbstractVector, lo::Integer, hi::Integer, a::PartialQuickSort,
  636.                o::Ordering)
  637.     @inbounds while lo < hi
  638.         hi-lo <= SMALL_THRESHOLD && return sort!(v, lo, hi, SMALL_ALGORITHM, o)
  639.         j = partition!(v, lo, hi, o)
  640.  
  641.         if j <= first(a.k)
  642.             lo = j+1
  643.         elseif j >= last(a.k)
  644.             hi = j-1
  645.         else
  646.             # recurse on the smaller chunk
  647.             # this is necessary to preserve O(log(n))
  648.             # stack space in the worst case (rather than O(n))
  649.             if j-lo < hi-j
  650.                 lo < (j-1) && sort!(v, lo, j-1, a, o)
  651.                 lo = j+1
  652.             else
  653.                 hi > (j+1) && sort!(v, j+1, hi, a, o)
  654.                 hi = j-1
  655.             end
  656.         end
  657.     end
  658.     return v
  659. end
  660.  
  661. function radix_sort!(v::AbstractVector{U}, lo::Integer, hi::Integer, bits::Unsigned,
  662.                ::Val{CHUNK_SIZE}, t::AbstractVector{U}) where {U <: Unsigned, CHUNK_SIZE}
  663.     #println("hi!")
  664.     MASK = UInt(1) << CHUNK_SIZE - 0x1
  665.     counts = Vector{unsigned(typeof(hi-lo))}(undef, MASK+2)
  666.  
  667.     @inbounds for shift in 0:CHUNK_SIZE:bits-1
  668.  
  669.         counts .= zero(eltype(counts))
  670.  
  671.         for k in lo:hi
  672.             x = v[k]
  673.             idx = (x >> shift)&MASK + 2
  674.             counts[idx] += one(eltype(counts))
  675.         end
  676.  
  677.         sum = lo-1
  678.         for i in 1:(MASK+1)
  679.             sum += counts[i]
  680.             counts[i] = sum
  681.         end
  682.         #accumulate!(+, counts, counts)
  683.  
  684.         for k in lo:hi # Is this iteration slower than it could be?
  685.             x = v[k]
  686.             i = (x >> shift)&MASK + 1
  687.             j = counts[i] += 1
  688.             t[j] = x
  689.             #sortperm here
  690.         end
  691.  
  692.         v, t = t, v
  693.  
  694.     end
  695.  
  696.     v
  697. end
  698.  
  699. used_bits(x::Union{Signed, Unsigned}) = sizeof(x)*8 - leading_zeros(x)
  700. function radix_heuristic(mn, mx, length)
  701.     #Skip sorting
  702.     mn == mx && return 0, 0, false
  703.  
  704.     #Dispatch to count sort
  705.     length + mn > mx && return 0, 0, true #TODO optimize
  706.  
  707.     bits = used_bits(mx-mn)
  708.  
  709.     guess = log(length)*3/4+3
  710.     chunk = Int(cld(bits, cld(bits, guess)))
  711.  
  712.     bits, chunk, false
  713. end
  714.  
  715. function sort!(v::AbstractVector, lo::Integer, hi::Integer, a::RadixSort2, o::Ordering)
  716.     #TODO needs review
  717.     #TODO Serialize Left and Right orderings
  718.     hi <= lo && return v
  719.  
  720.     (hi - lo < 500 || (hi - lo < 200_000 && sizeof(eltype(v)) == 16)) && return sort!(v, lo, hi, a.fallback, o)
  721.  
  722.     Serialize.Serializable(eltype(v), o) === nothing &&
  723.         return sort!(v, lo, hi, a.fallback, o)
  724.  
  725.     u, mn, mx = Serialize.serialize!(v, lo, hi, o)
  726.  
  727.     bits, chunk_size, count = radix_heuristic(mn, mx, hi-lo+1)
  728.  
  729.     if count
  730.         # This overflows and returns incorrect results if the range is more than typemax(Int)
  731.         # sourt_int_range! would need to allocate an array of more than typemax(Int) elements,
  732.         # so policy should never dispatch to sort_int_range! in that case.
  733.         u = sort_int_range!(u, 1+mx-mn, mn, identity) # 1 not one().
  734.         mn = zero(mn)
  735.     elseif bits > 0
  736.         #Type instability:
  737.         u .-= mn
  738.         u = radix_sort!(u, lo, hi, unsigned(bits), Val(UInt8(chunk_size)), similar(u))
  739.     else
  740.         mn = zero(mn)
  741.     end
  742.  
  743.     Serialize.deserialize!(v, u, lo, hi, o, mn)
  744. end
  745.  
  746. ## generic sorting methods ##
  747.  
  748. defalg(v::AbstractArray) = DEFAULT_STABLE
  749. defalg(v::AbstractArray{<:Union{Number, Missing}}) = DEFAULT_UNSTABLE
  750. defalg(v::AbstractArray{Missing}) = DEFAULT_UNSTABLE
  751. defalg(v::AbstractArray{Union{}}) = DEFAULT_UNSTABLE
  752.  
  753. function sort!(v::AbstractVector, alg::Algorithm, order::Ordering)
  754.     inds = axes(v,1)
  755.     sort!(v,first(inds),last(inds),alg,order)
  756. end
  757.  
  758. """
  759.    sort!(v; alg::Algorithm=defalg(v), lt=isless, by=identity, rev::Bool=false, order::Ordering=Forward)
  760.  
  761. Sort the vector `v` in place. [`QuickSort`](@ref) is used by default for numeric arrays while
  762. [`MergeSort`](@ref) is used for other arrays. You can specify an algorithm to use via the `alg`
  763. keyword (see [Sorting Algorithms](@ref) for available algorithms). The `by` keyword lets you provide
  764. a function that will be applied to each element before comparison; the `lt` keyword allows
  765. providing a custom "less than" function (note that for every `x` and `y`, only one of `lt(x,y)`
  766. and `lt(y,x)` can return `true`); use `rev=true` to reverse the sorting order. These
  767. options are independent and can be used together in all possible combinations: if both `by`
  768. and `lt` are specified, the `lt` function is applied to the result of the `by` function;
  769. `rev=true` reverses whatever ordering specified via the `by` and `lt` keywords.
  770.  
  771. # Examples
  772. ```jldoctest
  773. julia> v = [3, 1, 2]; sort!(v); v
  774. 3-element Vector{Int64}:
  775. 1
  776. 2
  777. 3
  778.  
  779. julia> v = [3, 1, 2]; sort!(v, rev = true); v
  780. 3-element Vector{Int64}:
  781. 3
  782. 2
  783. 1
  784.  
  785. julia> v = [(1, "c"), (3, "a"), (2, "b")]; sort!(v, by = x -> x[1]); v
  786. 3-element Vector{Tuple{Int64, String}}:
  787. (1, "c")
  788. (2, "b")
  789. (3, "a")
  790.  
  791. julia> v = [(1, "c"), (3, "a"), (2, "b")]; sort!(v, by = x -> x[2]); v
  792. 3-element Vector{Tuple{Int64, String}}:
  793. (3, "a")
  794. (2, "b")
  795. (1, "c")
  796. ```
  797. """
  798. function sort!(v::AbstractVector;
  799.                alg::Algorithm=defalg(v),
  800.                lt=isless,
  801.                by=identity,
  802.                rev::Union{Bool,Nothing}=nothing,
  803.                order::Ordering=Forward)
  804.     ordr = ord(lt,by,rev,order)
  805.     if (ordr === Forward || ordr === Reverse) && eltype(v)<:Integer
  806.         n = length(v)
  807.         if n > 1
  808.             min, max = extrema(v)
  809.             (diff, o1) = sub_with_overflow(max, min)
  810.             (rangelen, o2) = add_with_overflow(diff, oneunit(diff))
  811.             if !o1 && !o2 && rangelen < div(n,2)
  812.                 return sort_int_range!(v, rangelen, min, ordr === Reverse ? reverse : identity)
  813.             end
  814.         end
  815.     end
  816.     sort!(v, alg, ordr)
  817. end
  818.  
  819. # sort! for vectors of few unique integers
  820. function sort_int_range!(x::AbstractVector{<:Integer}, rangelen, minval, maybereverse)
  821.     offs = 1 - minval
  822.  
  823.     counts = fill(0, rangelen)
  824.     @inbounds for i = eachindex(x)
  825.         counts[x[i] + offs] += 1
  826.     end
  827.  
  828.     idx = firstindex(x)
  829.     @inbounds for i = maybereverse(1:rangelen)
  830.         lastidx = idx + counts[i] - 1
  831.         val = i-offs
  832.         for j = idx:lastidx
  833.             x[j] = val
  834.         end
  835.         idx = lastidx + 1
  836.     end
  837.  
  838.     return x
  839. end
  840.  
  841. """
  842.    sort(v; alg::Algorithm=defalg(v), lt=isless, by=identity, rev::Bool=false, order::Ordering=Forward)
  843.  
  844. Variant of [`sort!`](@ref) that returns a sorted copy of `v` leaving `v` itself unmodified.
  845.  
  846. # Examples
  847. ```jldoctest
  848. julia> v = [3, 1, 2];
  849.  
  850. julia> sort(v)
  851. 3-element Vector{Int64}:
  852. 1
  853. 2
  854. 3
  855.  
  856. julia> v
  857. 3-element Vector{Int64}:
  858. 3
  859. 1
  860. 2
  861. ```
  862. """
  863. sort(v::AbstractVector; kws...) = sort!(copymutable(v); kws...)
  864.  
  865. ## partialsortperm: the permutation to sort the first k elements of an array ##
  866.  
  867. """
  868.    partialsortperm(v, k; by=<transform>, lt=<comparison>, rev=false)
  869.  
  870. Return a partial permutation `I` of the vector `v`, so that `v[I]` returns values of a fully
  871. sorted version of `v` at index `k`. If `k` is a range, a vector of indices is returned; if
  872. `k` is an integer, a single index is returned. The order is specified using the same
  873. keywords as `sort!`. The permutation is stable, meaning that indices of equal elements
  874. appear in ascending order.
  875.  
  876. Note that this function is equivalent to, but more efficient than, calling `sortperm(...)[k]`.
  877.  
  878. # Examples
  879. ```jldoctest
  880. julia> v = [3, 1, 2, 1];
  881.  
  882. julia> v[partialsortperm(v, 1)]
  883. 1
  884.  
  885. julia> p = partialsortperm(v, 1:3)
  886. 3-element view(::Vector{Int64}, 1:3) with eltype Int64:
  887. 2
  888. 4
  889. 3
  890.  
  891. julia> v[p]
  892. 3-element Vector{Int64}:
  893. 1
  894. 1
  895. 2
  896. ```
  897. """
  898. partialsortperm(v::AbstractVector, k::Union{Integer,OrdinalRange}; kwargs...) =
  899.     partialsortperm!(similar(Vector{eltype(k)}, axes(v,1)), v, k; kwargs..., initialized=false)
  900.  
  901. """
  902.    partialsortperm!(ix, v, k; by=<transform>, lt=<comparison>, rev=false, initialized=false)
  903.  
  904. Like [`partialsortperm`](@ref), but accepts a preallocated index vector `ix` the same size as
  905. `v`, which is used to store (a permutation of) the indices of `v`.
  906.  
  907. If the index vector `ix` is initialized with the indices of `v` (or a permutation thereof), `initialized` should be set to
  908. `true`.
  909.  
  910. If `initialized` is `false` (the default), then `ix` is initialized to contain the indices of `v`.
  911.  
  912. If `initialized` is `true`, but `ix` does not contain (a permutation of) the indices of `v`, the behavior of
  913. `partialsortperm!` is undefined.
  914.  
  915. (Typically, the indices of `v` will be `1:length(v)`, although if `v` has an alternative array type
  916. with non-one-based indices, such as an `OffsetArray`, `ix` must also be an `OffsetArray` with the same
  917. indices, and must contain as values (a permutation of) these same indices.)
  918.  
  919. Upon return, `ix` is guaranteed to have the indices `k` in their sorted positions, such that
  920.  
  921. ```julia
  922. partialsortperm!(ix, v, k);
  923. v[ix[k]] == partialsort(v, k)
  924. ```
  925.  
  926. The return value is the `k`th element of `ix` if `k` is an integer, or view into `ix` if `k` is
  927. a range.
  928.  
  929. # Examples
  930. ```jldoctest
  931. julia> v = [3, 1, 2, 1];
  932.  
  933. julia> ix = Vector{Int}(undef, 4);
  934.  
  935. julia> partialsortperm!(ix, v, 1)
  936. 2
  937.  
  938. julia> ix = [1:4;];
  939.  
  940. julia> partialsortperm!(ix, v, 2:3, initialized=true)
  941. 2-element view(::Vector{Int64}, 2:3) with eltype Int64:
  942. 4
  943. 3
  944. ```
  945. """
  946. function partialsortperm!(ix::AbstractVector{<:Integer}, v::AbstractVector,
  947.                           k::Union{Integer, OrdinalRange};
  948.                           lt::Function=isless,
  949.                           by::Function=identity,
  950.                           rev::Union{Bool,Nothing}=nothing,
  951.                           order::Ordering=Forward,
  952.                           initialized::Bool=false)
  953.     if axes(ix,1) != axes(v,1)
  954.         throw(ArgumentError("The index vector is used as a workspace and must have the " *
  955.                             "same length/indices as the source vector, $(axes(ix,1)) != $(axes(v,1))"))
  956.     end
  957.     if !initialized
  958.         @inbounds for i = axes(ix,1)
  959.             ix[i] = i
  960.         end
  961.     end
  962.  
  963.     # do partial quicksort
  964.     sort!(ix, PartialQuickSort(k), Perm(ord(lt, by, rev, order), v))
  965.  
  966.     maybeview(ix, k)
  967. end
  968.  
  969. ## sortperm: the permutation to sort an array ##
  970.  
  971. """
  972.    sortperm(v; alg::Algorithm=DEFAULT_UNSTABLE, lt=isless, by=identity, rev::Bool=false, order::Ordering=Forward)
  973.  
  974. Return a permutation vector `I` that puts `v[I]` in sorted order. The order is specified
  975. using the same keywords as [`sort!`](@ref). The permutation is guaranteed to be stable even
  976. if the sorting algorithm is unstable, meaning that indices of equal elements appear in
  977. ascending order.
  978.  
  979. See also [`sortperm!`](@ref), [`partialsortperm`](@ref), [`invperm`](@ref), [`indexin`](@ref).
  980.  
  981. # Examples
  982. ```jldoctest
  983. julia> v = [3, 1, 2];
  984.  
  985. julia> p = sortperm(v)
  986. 3-element Vector{Int64}:
  987. 2
  988. 3
  989. 1
  990.  
  991. julia> v[p]
  992. 3-element Vector{Int64}:
  993. 1
  994. 2
  995. 3
  996. ```
  997. """
  998. function sortperm(v::AbstractVector;
  999.                   alg::Algorithm=DEFAULT_UNSTABLE,
  1000.                   lt=isless,
  1001.                   by=identity,
  1002.                   rev::Union{Bool,Nothing}=nothing,
  1003.                   order::Ordering=Forward)
  1004.     ordr = ord(lt,by,rev,order)
  1005.     if ordr === Forward && isa(v,Vector) && eltype(v)<:Integer
  1006.         n = length(v)
  1007.         if n > 1
  1008.             min, max = extrema(v)
  1009.             (diff, o1) = sub_with_overflow(max, min)
  1010.             (rangelen, o2) = add_with_overflow(diff, oneunit(diff))
  1011.             if !o1 && !o2 && rangelen < div(n,2)
  1012.                 return sortperm_int_range(v, rangelen, min)
  1013.             end
  1014.         end
  1015.     end
  1016.     ax = axes(v, 1)
  1017.     p = similar(Vector{eltype(ax)}, ax)
  1018.     for (i,ind) in zip(eachindex(p), ax)
  1019.         p[i] = ind
  1020.     end
  1021.     sort!(p, alg, Perm(ordr,v))
  1022. end
  1023.  
  1024.  
  1025. """
  1026.    sortperm!(ix, v; alg::Algorithm=DEFAULT_UNSTABLE, lt=isless, by=identity, rev::Bool=false, order::Ordering=Forward, initialized::Bool=false)
  1027.  
  1028. Like [`sortperm`](@ref), but accepts a preallocated index vector `ix`.  If `initialized` is `false`
  1029. (the default), `ix` is initialized to contain the values `1:length(v)`.
  1030.  
  1031. # Examples
  1032. ```jldoctest
  1033. julia> v = [3, 1, 2]; p = zeros(Int, 3);
  1034.  
  1035. julia> sortperm!(p, v); p
  1036. 3-element Vector{Int64}:
  1037. 2
  1038. 3
  1039. 1
  1040.  
  1041. julia> v[p]
  1042. 3-element Vector{Int64}:
  1043. 1
  1044. 2
  1045. 3
  1046. ```
  1047. """
  1048. function sortperm!(x::AbstractVector{<:Integer}, v::AbstractVector;
  1049.                    alg::Algorithm=DEFAULT_UNSTABLE,
  1050.                    lt=isless,
  1051.                    by=identity,
  1052.                    rev::Union{Bool,Nothing}=nothing,
  1053.                    order::Ordering=Forward,
  1054.                    initialized::Bool=false)
  1055.     if axes(x,1) != axes(v,1)
  1056.         throw(ArgumentError("index vector must have the same length/indices as the source vector, $(axes(x,1)) != $(axes(v,1))"))
  1057.     end
  1058.     if !initialized
  1059.         @inbounds for i = axes(v,1)
  1060.             x[i] = i
  1061.         end
  1062.     end
  1063.     sort!(x, alg, Perm(ord(lt,by,rev,order),v))
  1064. end
  1065.  
  1066. # sortperm for vectors of few unique integers
  1067. function sortperm_int_range(x::Vector{<:Integer}, rangelen, minval)
  1068.     offs = 1 - minval
  1069.     n = length(x)
  1070.  
  1071.     counts = fill(0, rangelen+1)
  1072.     counts[1] = 1
  1073.     @inbounds for i = 1:n
  1074.         counts[x[i] + offs + 1] += 1
  1075.     end
  1076.  
  1077.     #cumsum!(counts, counts)
  1078.     @inbounds for i = 2:length(counts)
  1079.         counts[i] += counts[i-1]
  1080.     end
  1081.  
  1082.     P = Vector{Int}(undef, n)
  1083.     @inbounds for i = 1:n
  1084.         label = x[i] + offs
  1085.         P[counts[label]] = i
  1086.         counts[label] += 1
  1087.     end
  1088.  
  1089.     return P
  1090. end
  1091.  
  1092. ## sorting multi-dimensional arrays ##
  1093.  
  1094. """
  1095.    sort(A; dims::Integer, alg::Algorithm=DEFAULT_UNSTABLE, lt=isless, by=identity, rev::Bool=false, order::Ordering=Forward)
  1096.  
  1097. Sort a multidimensional array `A` along the given dimension.
  1098. See [`sort!`](@ref) for a description of possible
  1099. keyword arguments.
  1100.  
  1101. To sort slices of an array, refer to [`sortslices`](@ref).
  1102.  
  1103. # Examples
  1104. ```jldoctest
  1105. julia> A = [4 3; 1 2]
  1106. 2×2 Matrix{Int64}:
  1107. 4  3
  1108. 1  2
  1109.  
  1110. julia> sort(A, dims = 1)
  1111. 2×2 Matrix{Int64}:
  1112. 1  2
  1113. 4  3
  1114.  
  1115. julia> sort(A, dims = 2)
  1116. 2×2 Matrix{Int64}:
  1117. 3  4
  1118. 1  2
  1119. ```
  1120. """
  1121. function sort(A::AbstractArray;
  1122.               dims::Integer,
  1123.               alg::Algorithm=DEFAULT_UNSTABLE,
  1124.               lt=isless,
  1125.               by=identity,
  1126.               rev::Union{Bool,Nothing}=nothing,
  1127.               order::Ordering=Forward)
  1128.     dim = dims
  1129.     order = ord(lt,by,rev,order)
  1130.     n = length(axes(A, dim))
  1131.     if dim != 1
  1132.         pdims = (dim, setdiff(1:ndims(A), dim)...)  # put the selected dimension first
  1133.         Ap = permutedims(A, pdims)
  1134.         Av = vec(Ap)
  1135.         sort_chunks!(Av, n, alg, order)
  1136.         permutedims(Ap, invperm(pdims))
  1137.     else
  1138.         Av = A[:]
  1139.         sort_chunks!(Av, n, alg, order)
  1140.         reshape(Av, axes(A))
  1141.     end
  1142. end
  1143.  
  1144. @noinline function sort_chunks!(Av, n, alg, order)
  1145.     inds = LinearIndices(Av)
  1146.     for s = first(inds):n:last(inds)
  1147.         sort!(Av, s, s+n-1, alg, order)
  1148.     end
  1149.     Av
  1150. end
  1151.  
  1152. """
  1153.    sort!(A; dims::Integer, alg::Algorithm=defalg(A), lt=isless, by=identity, rev::Bool=false, order::Ordering=Forward)
  1154.  
  1155. Sort the multidimensional array `A` along dimension `dims`.
  1156. See [`sort!`](@ref) for a description of possible keyword arguments.
  1157.  
  1158. To sort slices of an array, refer to [`sortslices`](@ref).
  1159.  
  1160. !!! compat "Julia 1.1"
  1161.    This function requires at least Julia 1.1.
  1162.  
  1163. # Examples
  1164. ```jldoctest
  1165. julia> A = [4 3; 1 2]
  1166. 2×2 Matrix{Int64}:
  1167. 4  3
  1168. 1  2
  1169.  
  1170. julia> sort!(A, dims = 1); A
  1171. 2×2 Matrix{Int64}:
  1172. 1  2
  1173. 4  3
  1174.  
  1175. julia> sort!(A, dims = 2); A
  1176. 2×2 Matrix{Int64}:
  1177. 1  2
  1178. 3  4
  1179. ```
  1180. """
  1181. function sort!(A::AbstractArray;
  1182.                dims::Integer,
  1183.                alg::Algorithm=defalg(A),
  1184.                lt=isless,
  1185.                by=identity,
  1186.                rev::Union{Bool,Nothing}=nothing,
  1187.                order::Ordering=Forward)
  1188.     ordr = ord(lt, by, rev, order)
  1189.     nd = ndims(A)
  1190.     k = dims
  1191.     1 <= k <= nd || throw(ArgumentError("dimension out of range"))
  1192.  
  1193.     remdims = ntuple(i -> i == k ? 1 : axes(A, i), nd)
  1194.     for idx in CartesianIndices(remdims)
  1195.         Av = view(A, ntuple(i -> i == k ? Colon() : idx[i], nd)...)
  1196.         sort!(Av, alg, ordr)
  1197.     end
  1198.     A
  1199. end
  1200.  
  1201. ## sorting serialization to alow radix sorting primitives other than UInts ##
  1202. module Serialize
  1203. using ...Order
  1204.  
  1205. """
  1206.    Serializable(T::Type, order::Ordering)
  1207.  
  1208. Return `Some(typeof(serialize(x::T, order)))` if [`serialize`](@ref) and
  1209. [`deserialize`](@ref) are implemented.
  1210.  
  1211. If either is not implemented, return nothing.
  1212. """
  1213. Serializable(T::Type, order::Ordering) = nothing
  1214.  
  1215. """
  1216.    serialize(x, order::Ordering)::Unsigned
  1217.  
  1218. Map `x` to an un unsigned integer, maintaining sort order.
  1219.  
  1220. The map should be reversible with [`deserialize`](@ref), so `isless(order, a, b)` must be
  1221. a linear ordering for `a, b <: typeof(x)`. Satisfies
  1222. `isless(order, a, b) === (serialize(order, a) < serialize(order, b))`
  1223. and `x === deserialize(typeof(x), serialize(order, x), order)`
  1224.  
  1225. See also: [`Serializable`](@ref) [`deserialize`](@ref)
  1226. """
  1227. function serialize end
  1228.  
  1229. """
  1230.    deserialize(T::Type, u::Unsigned, order::Ordering)
  1231.  
  1232. Reconstruct the unique value `x::T` that serializes to `u`. Satisfies
  1233. `x === deserialize(T, order, serialize(order, x::T))` for all `x <: T`.
  1234.  
  1235. See also: [`serialize`](@ref) [`Serializable`](@ref)
  1236. """
  1237. function deserialize end
  1238.  
  1239.  
  1240. ### Primitive Types
  1241.  
  1242. # Integers
  1243. serialize(x::Unsigned, ::ForwardOrdering) = x
  1244. deserialize(::Type{T}, u::T, ::ForwardOrdering) where T <: Unsigned = u
  1245.  
  1246. serialize(x::Signed, ::ForwardOrdering) =
  1247.     unsigned(xor(x, typemin(x)))
  1248. deserialize(::Type{T}, u::Unsigned, ::ForwardOrdering) where T <: Signed =
  1249.     xor(signed(u), typemin(T))
  1250.  
  1251. Serializable(T::Type{<:Union{Unsigned, Signed}}, ::ForwardOrdering) =
  1252.     isbitstype(T) ? Some(unsigned(T)) : nothing
  1253.  
  1254. # Floats are not Serializable under regular orderings because they fail on NaN edge cases.
  1255. # Float serialization is defined in ..Float, where the ordering guarantees that there are no NaN values
  1256.  
  1257. # Booleans
  1258. serialize(x::Bool, ::ForwardOrdering) = UInt8(x)
  1259. deserialize(::Type{Bool}, u::UInt8, ::ForwardOrdering) = Bool(u)
  1260. Serializable(::Type{Bool}, ::ForwardOrdering) = UInt8
  1261.  
  1262. # Chars
  1263. serialize(x::Char, ::ForwardOrdering) = reinterpret(UInt32, x)
  1264. deserialize(::Type{Char}, u::UInt32, ::ForwardOrdering) = reinterpret(Char, u)
  1265. Serializable(::Type{Char}, ::ForwardOrdering) = UInt32
  1266.  
  1267. ### Reverse orderings
  1268. serialize(x, rev::ReverseOrdering) = ~serialize(x, rev.fwd)
  1269. deserialize(T::Type, u::Unsigned, rev::ReverseOrdering) = deserialize(T, ~u, rev.fwd)
  1270. Serializable(T::Type, order::ReverseOrdering) = Serializable(T, order.fwd)
  1271.  
  1272.  
  1273. ### Vectors
  1274. """docstring"""
  1275. function serialize!(v::AbstractVector, lo::Integer, hi::Integer, order::Ordering)
  1276.     u = reinterpret(something(Serializable(eltype(v), order)), v)
  1277.     @inbounds u[lo] = mn = mx = serialize(v[lo], order)
  1278.     i = lo # rename lo -> i for clarity only
  1279.     @inbounds while i < hi
  1280.         i += 1
  1281.  
  1282.         ui = u[i] = serialize(v[i], order)
  1283.  
  1284.         mx = max(ui, mx)
  1285.         mn = min(ui, mn)
  1286.     end
  1287.     u, mn, mx
  1288. end
  1289.  
  1290. """docstring"""
  1291. function deserialize!(v::AbstractVector, u::AbstractVector{U},
  1292.     lo::Integer, hi::Integer, order::Ordering, offset::U) where U <: Unsigned
  1293.     @inbounds for i in lo:hi
  1294.         v[i] = deserialize(eltype(v), u[i]+offset, order)
  1295.     end
  1296.     v
  1297. end
  1298.  
  1299. end # module Sort.Serialize
  1300.  
  1301.  
  1302. ## fast clever sorting for floats ##
  1303.  
  1304. module Float
  1305. using ..Sort
  1306. using ...Order
  1307. using ..Base: @inbounds, AbstractVector, Vector, last, axes, Missing
  1308.  
  1309. import Core.Intrinsics: slt_int
  1310. import ..Sort: sort!
  1311. import ...Order: lt, DirectOrdering
  1312.  
  1313. const Floats = Union{Float32,Float64}
  1314. const FPSortable = Union{ # Mixed Float32 and Float64 are not allowed.
  1315.     AbstractVector{Union{Float32, Missing}},
  1316.     AbstractVector{Union{Float64, Missing}},
  1317.     AbstractVector{Float32},
  1318.     AbstractVector{Float64},
  1319.     AbstractVector{Missing}}
  1320.  
  1321. struct Left <: Ordering end
  1322. struct Right <: Ordering end
  1323.  
  1324. left(::DirectOrdering) = Left()
  1325. right(::DirectOrdering) = Right()
  1326.  
  1327. left(o::Perm) = Perm(left(o.order), o.data)
  1328. right(o::Perm) = Perm(right(o.order), o.data)
  1329.  
  1330. lt(::Left, x::T, y::T) where {T<:Floats} = slt_int(y, x)
  1331. lt(::Right, x::T, y::T) where {T<:Floats} = slt_int(x, y)
  1332.  
  1333. #TODO break FPSort into first, make nan/missing free, then maybe radix, then split by sign
  1334. # finally slt_int.
  1335. # use wrappers on Orderings to flag nan and sign free.
  1336.  
  1337. #=# BEGIN TODO
  1338. # If the ordering guarantees that there are no NaNs, then they work.
  1339. struct NaNFreeForwardOrdering2 <: Ordering end
  1340. nan_free(::ForwardOrdering) = NaNFreeForwardOrdering2()
  1341. nan_free(r::ReverseOrdering) = ReverseOrdering(nan_free(r.fwd))
  1342. nan_free_unwrap(o::Ordering) = o
  1343. nan_free_unwrap(::NaNFreeForwardOrdering2) = Forward
  1344. nan_free_unwrap(r::ReverseOrdering) = ReverseOrdering(nan_free_unwrap(r.fwd))
  1345.  
  1346. for (float, int) in ((Float16, Int16), (Float32, Int32), (Float64, Int64))
  1347.     @eval function serialize(::NaNFreeForwardOrdering2, x::$float)
  1348.         y = reinterpret($int, x)
  1349.         unsigned(y < 0 ? ~y : xor(y, typemin(y))) - ~reinterpret(unsigned($int), $float(-Inf))
  1350.     end
  1351.     @eval function deserialize(T::Type{$float}, ::NaNFreeForwardOrdering2, u::unsigned($int))
  1352.         y = reinterpret($int, u + ~reinterpret(unsigned($int), $float(-Inf)))
  1353.         reinterpret(T, y < 0 ? xor(y, typemin(y)) : ~y)
  1354.     end
  1355.     @eval Serializable(::NaNFreeForwardOrdering2, ::Type{$float}) = unsigned($int)
  1356. end
  1357. ## END TODO =#
  1358.  
  1359. isnan(o::DirectOrdering, x::Floats) = (x!=x)
  1360. isnan(o::DirectOrdering, x::Missing) = false
  1361. isnan(o::Perm, i::Integer) = isnan(o.order,o.data[i])
  1362.  
  1363. ismissing(o::DirectOrdering, x::Floats) = false
  1364. ismissing(o::DirectOrdering, x::Missing) = true
  1365. ismissing(o::Perm, i::Integer) = ismissing(o.order,o.data[i])
  1366.  
  1367. allowsmissing(::AbstractVector{T}, ::DirectOrdering) where {T} = T >: Missing
  1368. allowsmissing(::AbstractVector{<:Integer},
  1369.               ::Perm{<:DirectOrdering,<:AbstractVector{T}}) where {T} =
  1370.     T >: Missing
  1371.  
  1372. function specials2left!(testf::Function, v::AbstractVector, o::Ordering,
  1373.                         lo::Integer=first(axes(v,1)), hi::Integer=last(axes(v,1)))
  1374.     i = lo
  1375.     @inbounds while i <= hi && testf(o,v[i])
  1376.         i += 1
  1377.     end
  1378.     j = i + 1
  1379.     @inbounds while j <= hi
  1380.         if testf(o,v[j])
  1381.             v[i], v[j] = v[j], v[i]
  1382.             i += 1
  1383.         end
  1384.         j += 1
  1385.     end
  1386.     return i, hi
  1387. end
  1388. function specials2right!(testf::Function, v::AbstractVector, o::Ordering,
  1389.                          lo::Integer=first(axes(v,1)), hi::Integer=last(axes(v,1)))
  1390.     i = hi
  1391.     @inbounds while lo <= i && testf(o,v[i])
  1392.         i -= 1
  1393.     end
  1394.     j = i - 1
  1395.     @inbounds while lo <= j
  1396.         if testf(o,v[j])
  1397.             v[i], v[j] = v[j], v[i]
  1398.             i -= 1
  1399.         end
  1400.         j -= 1
  1401.     end
  1402.     return lo, i
  1403. end
  1404.  
  1405. function specials2left!(v::AbstractVector, a::Algorithm, o::Ordering)
  1406.     lo, hi = first(axes(v,1)), last(axes(v,1))
  1407.     if allowsmissing(v, o)
  1408.         i, _ = specials2left!((v, o) -> ismissing(v, o) || isnan(v, o), v, o, lo, hi)
  1409.         sort!(v, lo, i-1, a, o)
  1410.         return i, hi
  1411.     else
  1412.         return specials2left!(isnan, v, o, lo, hi)
  1413.     end
  1414. end
  1415. function specials2right!(v::AbstractVector, a::Algorithm, o::Ordering)
  1416.     lo, hi = first(axes(v,1)), last(axes(v,1))
  1417.     if allowsmissing(v, o)
  1418.         _, i = specials2right!((v, o) -> ismissing(v, o) || isnan(v, o), v, o, lo, hi)
  1419.         sort!(v, i+1, hi, a, o)
  1420.         return lo, i
  1421.     else
  1422.         return specials2right!(isnan, v, o, lo, hi)
  1423.     end
  1424. end
  1425.  
  1426. specials2end!(v::AbstractVector, a::Algorithm, o::ForwardOrdering) =
  1427.     specials2right!(v, a, o)
  1428. specials2end!(v::AbstractVector, a::Algorithm, o::ReverseOrdering) =
  1429.     specials2left!(v, a, o)
  1430. specials2end!(v::AbstractVector{<:Integer}, a::Algorithm, o::Perm{<:ForwardOrdering}) =
  1431.     specials2right!(v, a, o)
  1432. specials2end!(v::AbstractVector{<:Integer}, a::Algorithm, o::Perm{<:ReverseOrdering}) =
  1433.     specials2left!(v, a, o)
  1434.  
  1435. issignleft(o::ForwardOrdering, x::Floats) = lt(o, x, zero(x))
  1436. issignleft(o::ReverseOrdering, x::Floats) = lt(o, x, -zero(x))
  1437. issignleft(o::Perm, i::Integer) = issignleft(o.order, o.data[i])
  1438.  
  1439. function fpsort!(v::AbstractVector, a::Algorithm, o::Ordering)
  1440.     i, j = lo, hi = specials2end!(v,a,o)
  1441.     @inbounds while true
  1442.         while i <= j &&  issignleft(o,v[i]); i += 1; end
  1443.         while i <= j && !issignleft(o,v[j]); j -= 1; end
  1444.         i <= j || break
  1445.         v[i], v[j] = v[j], v[i]
  1446.         i += 1; j -= 1
  1447.     end
  1448.     sort!(v, lo, j,  a, left(o))
  1449.     sort!(v, i,  hi, a, right(o))
  1450.     return v
  1451. end
  1452.  
  1453.  
  1454. fpsort!(v::AbstractVector, a::Sort.PartialQuickSort, o::Ordering) =
  1455.     sort!(v, first(axes(v,1)), last(axes(v,1)), a, o)
  1456.  
  1457. #sort!(v::FPSortable, a::Algorithm, o::DirectOrdering) =
  1458. #    fpsort!(v, a, o)
  1459. #sort!(v::AbstractVector{<:Integer}, a::Algorithm, o::Perm{<:DirectOrdering,<:FPSortable}) =
  1460. #    fpsort!(v, a, o)
  1461.  
  1462. end # module Sort.Float
  1463.  
  1464. end # module Sort
  1465.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement