Skip to content

Commit a45a054

Browse files
committed
Simplify twoended_merge!
...by exploiting the fact that the merge is always balanced.
1 parent 256d1ff commit a45a054

File tree

1 file changed

+15
-33
lines changed

1 file changed

+15
-33
lines changed

src/SortingAlgorithms.jl

Lines changed: 15 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,12 @@ struct CombSortAlg <: Algorithm end
1919
struct PagedMergeSortAlg <: Algorithm end
2020
struct ThreadedPagedMergeSortAlg <: Algorithm end
2121

22-
function maybe_optimize(x::Algorithm)
22+
function maybe_optimize(x::Algorithm)
2323
isdefined(Base.Sort, :InitialOptimizations) ? Base.Sort.InitialOptimizations(x) : x
24-
end
24+
end
2525
const HeapSort = maybe_optimize(HeapSortAlg())
2626
const TimSort = maybe_optimize(TimSortAlg())
27-
# Whenever InitialOptimizations is defined, RadixSort falls
27+
# Whenever InitialOptimizations is defined, RadixSort falls
2828
# back to Base.DEFAULT_STABLE which already incldues them.
2929
const RadixSort = RadixSortAlg()
3030

@@ -688,24 +688,23 @@ end
688688
# PagedMergeSort
689689
###
690690

691-
# merge v[lo:m] and v[m+1:hi] ([A;B]) using buffer t[1:1+hi-lo]
692-
# this is faster than merge! but requires twice as much auxiliary memory.
691+
# merge v[lo:m] and v[m+1:hi] ([A;B]) using buffer t[1:1+hi-lo]
692+
# This is faster than merge! but requires twice as much auxiliary memory.
693693
function twoended_merge!(v::AbstractVector{T}, lo::Integer, m::Integer, hi::Integer, o::Ordering, t::AbstractVector{T}) where T
694-
@assert lo <= m <= hi
695-
694+
@assert lo m hi
695+
@assert abs((m-lo) - (hi-(m+1))) 1 "twoended_merge! only supports balanced merges"
696+
len = 1 + hi - lo
696697
# input array indices
697698
a_lo = lo
698699
a_hi = m
699-
b_lo = m + 1
700+
b_lo = m + 1
700701
b_hi = hi
701702
# output array indices
702703
k_lo = 1
703-
k_hi = 1 + hi - lo
704-
704+
k_hi = len
705705
@inbounds begin
706706
# two ended merge
707-
# while at least 2 elements remain in both A and B
708-
while a_lo < a_hi && b_lo < b_hi
707+
while k_lo <= len ÷ 2
709708
if lt(o, v[b_lo], v[a_lo])
710709
t[k_lo] = v[b_lo]
711710
b_lo += 1
@@ -723,32 +722,15 @@ function twoended_merge!(v::AbstractVector{T}, lo::Integer, m::Integer, hi::Inte
723722
end
724723
k_hi -=1
725724
end
726-
# regular merge
727-
# until either A or B runs out
728-
while a_lo <= a_hi && b_lo <= b_hi
729-
if lt(o, v[b_lo], v[a_lo])
730-
t[k_lo] = v[b_lo]
731-
b_lo += 1
732-
else
733-
t[k_lo] = v[a_lo]
734-
a_lo += 1
735-
end
736-
k_lo += 1
737-
end
738-
# either A or B is empty -> copy remaining items
739-
while a_lo <= a_hi
725+
# if the input length is odd,
726+
# one item remains
727+
if a_lo <= a_hi
740728
t[k_lo] = v[a_lo]
741-
a_lo += 1
742-
k_lo += 1
743-
end
744-
while b_lo <= b_hi
729+
elseif b_lo <= b_hi
745730
t[k_lo] = v[b_lo]
746-
b_lo += 1
747-
k_lo += 1
748731
end
749732
# copy back from t to v
750733
offset = lo-1
751-
len = 1 + hi - lo
752734
for i = 1:len
753735
v[offset+i] = t[i]
754736
end

0 commit comments

Comments
 (0)