Skip to content

Commit f66e799

Browse files
committed
Use function for core merging loop
... to eliminate redundant code.
1 parent a45a054 commit f66e799

File tree

1 file changed

+26
-45
lines changed

1 file changed

+26
-45
lines changed

src/SortingAlgorithms.jl

Lines changed: 26 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -737,6 +737,23 @@ function twoended_merge!(v::AbstractVector{T}, lo::Integer, m::Integer, hi::Inte
737737
end
738738
end
739739

740+
# core merging loop used throughout PagedMergeSort
741+
Base.@propagate_inbounds function merge!(f::Function,
742+
target::AbstractVector{T}, source_a::AbstractVector{T}, source_b::AbstractVector{T},
743+
o::Ordering, a::Integer, b::Integer, k::Integer) where T
744+
while f(a,b,k)
745+
if lt(o, source_b[b], source_a[a])
746+
target[k] = source_b[b]
747+
b += 1
748+
else
749+
target[k] = source_a[a]
750+
a += 1
751+
end
752+
k += 1
753+
end
754+
a,b,k
755+
end
756+
740757
# merge v[lo:m] and v[m+1:hi] using buffer t[1:1+m-lo]
741758
# based on Base.Sort MergeSort
742759
function merge!(v::AbstractVector{T}, lo::Integer, m::Integer, hi::Integer, o::Ordering, t::AbstractVector{T}) where T
@@ -749,16 +766,8 @@ function merge!(v::AbstractVector{T}, lo::Integer, m::Integer, hi::Integer, o::O
749766
end
750767
a, b = 1, m + 1
751768
k = lo
752-
while k < b <= hi
753-
if lt(o, v[b], t[a])
754-
v[k] = v[b]
755-
b += 1
756-
else
757-
v[k] = t[a]
758-
a += 1
759-
end
760-
k += 1
761-
end
769+
f(_,b,k) = k < b <= hi
770+
a,b,k = merge!(f,v,t,v,o,a,b,k)
762771
while k < b
763772
v[k] = t[a]
764773
k += 1
@@ -816,17 +825,7 @@ function pagedMerge!(v::AbstractVector{T}, lo::Integer, m::Integer, hi::Integer,
816825
# merge
817826
##################
818827
# merge into buf until full
819-
j = 1
820-
while j <= 3blocksize # cannot run out of input elements here
821-
if lt(o, v[b], v[a]) # -> merge! would have been used
822-
buf[j] = v[b]
823-
b += 1
824-
else
825-
buf[j] = v[a]
826-
a += 1
827-
end
828-
j += 1
829-
end
828+
a,b,k = merge!((_,_,k) -> k<=3blocksize,buf,v,v,o,a,b,1)
830829

831830
nextBlockA = 1
832831
nextBlockB = (m + blocksize-lo) ÷ blocksize + 1
@@ -837,38 +836,20 @@ function pagedMerge!(v::AbstractVector{T}, lo::Integer, m::Integer, hi::Integer,
837836
currentBlock = 0
838837
currentBlockIdx = 4
839838
# more efficient loop while more than blocksize elements of A and B are remaining
839+
while_condition1(offset) = (_,_,k) -> k <= offset + blocksize
840840
while a < m-blocksize && b < hi-blocksize
841841
@getNextBlock!
842-
offset = (currentBlock-1)*blocksize
843-
k = lo + offset
844-
while k <= blocksize+offset + lo - 1
845-
if lt(o, v[b], v[a])
846-
v[k] = v[b]
847-
b += 1
848-
else
849-
v[k] = v[a]
850-
a += 1
851-
end
852-
k += 1
853-
end
842+
offset = getBlockOffset(currentBlock)
843+
a,b,k = merge!(while_condition1(offset),v,v,v,o,a,b,offset+1)
854844
end
855845
# merge until either A or B is empty
856-
k_block = 1
846+
while_condition2(offset) = (a,b,k) -> k <= offset + blocksize && a <= m && b <= hi
857847
while a <= m && b <= hi
858848
@getNextBlock!
859-
k_block = 1
860849
offset = getBlockOffset(currentBlock)
861-
while k_block <= blocksize && a <= m && b <= hi
862-
if lt(o, v[b], v[a])
863-
v[offset+k_block] = v[b]
864-
b += 1
865-
else
866-
v[offset+k_block] = v[a]
867-
a += 1
868-
end
869-
k_block += 1
870-
end
850+
a,b,k = merge!(while_condition2(offset),v,v,v,o,a,b,offset+1)
871851
end
852+
k_block = k - getBlockOffset(currentBlock)
872853
# copy remaining elements
873854
# either A or B is empty
874855
# copy rest of A

0 commit comments

Comments
 (0)