Skip to content

Commit 7b2a653

Browse files
committed
Make variable names and function signatures more consistent
- always use lo, m, hi in function signatures - rename array indices - use two variables instead of one to clarify if index is absolute or in current block (oIdx -> k, k_block)
1 parent d9fcaef commit 7b2a653

File tree

1 file changed

+110
-116
lines changed

1 file changed

+110
-116
lines changed

src/SortingAlgorithms.jl

Lines changed: 110 additions & 116 deletions
Original file line numberDiff line numberDiff line change
@@ -681,70 +681,66 @@ else
681681
end
682682

683683
###
684-
# ThreadedPagedMergeSort
684+
# PagedMergeSort
685685
###
686686

687-
# merge v[lo:hiA] and v[hiA+1:hi] ([A;B]) using buffer t[1:1 + hi-lo]
687+
# merge v[lo:m] and v[m+1:hi] ([A;B]) using buffer t[1:1+hi-lo]
688688
# this is faster than merge! but requires twice as much auxiliary memory.
689-
function twoended_merge!(v::AbstractVector{T}, lo::Integer, hiA::Integer, hi::Integer, o::Ordering, t::AbstractVector{T}) where T
690-
@assert lo <= hiA <= hi
691-
loA = lo
692-
loB = hiA + 1
693-
hiB = hi
694-
695-
# output array indices
696-
oL = 1
697-
oR = 1 + hi - lo
689+
function twoended_merge!(v::AbstractVector{T}, lo::Integer, m::Integer, hi::Integer, o::Ordering, t::AbstractVector{T}) where T
690+
@assert lo <= m <= hi
698691

699692
# input array indices
700-
iAL = loA
701-
iBL = loB
702-
iAR = hiA
703-
iBR = hiB
693+
a_lo = lo
694+
a_hi = m
695+
b_lo = m + 1
696+
b_hi = hi
697+
# output array indices
698+
k_lo = 1
699+
k_hi = 1 + hi - lo
704700

705701
@inbounds begin
706702
# two ended merge
707703
# while at least 2 elements remain in both A and B
708-
while iAL < iAR && iBL < iBR
709-
if lt(o,v[iBL], v[iAL])
710-
t[oL] = v[iBL]
711-
iBL += 1
704+
while a_lo < a_hi && b_lo < b_hi
705+
if lt(o, v[b_lo], v[a_lo])
706+
t[k_lo] = v[b_lo]
707+
b_lo += 1
712708
else
713-
t[oL] = v[iAL]
714-
iAL += 1
709+
t[k_lo] = v[a_lo]
710+
a_lo += 1
715711
end
716-
oL +=1
717-
if !lt(o,v[iBR], v[iAR])
718-
t[oR] = v[iBR]
719-
iBR -= 1
712+
k_lo +=1
713+
if !lt(o, v[b_hi], v[a_hi])
714+
t[k_hi] = v[b_hi]
715+
b_hi -= 1
720716
else
721-
t[oR] = v[iAR]
722-
iAR -= 1
717+
t[k_hi] = v[a_hi]
718+
a_hi -= 1
723719
end
724-
oR -=1
720+
k_hi -=1
725721
end
726722
# regular merge
727723
# until either A or B runs out
728-
while iAL <= iAR && iBL <= iBR
729-
if lt(o,v[iBL], v[iAL])
730-
t[oL] = v[iBL]
731-
iBL += 1
724+
while a_lo <= a_hi && b_lo <= b_hi
725+
if lt(o, v[b_lo], v[a_lo])
726+
t[k_lo] = v[b_lo]
727+
b_lo += 1
732728
else
733-
t[oL] = v[iAL]
734-
iAL += 1
729+
t[k_lo] = v[a_lo]
730+
a_lo += 1
735731
end
736-
oL += 1
732+
k_lo += 1
737733
end
738734
# either A or B is empty -> copy remaining items
739-
while iAL <= iAR
740-
t[oL] = v[iAL]
741-
iAL += 1
742-
oL += 1
735+
while a_lo <= a_hi
736+
t[k_lo] = v[a_lo]
737+
a_lo += 1
738+
k_lo += 1
743739
end
744-
while iBL <= iBR
745-
t[oL] = v[iBL]
746-
iBL += 1
747-
oL += 1
740+
while b_lo <= b_hi
741+
t[k_lo] = v[b_lo]
742+
b_lo += 1
743+
k_lo += 1
748744
end
749745
# copy back from t to v
750746
offset = lo-1
@@ -755,34 +751,32 @@ function twoended_merge!(v::AbstractVector{T}, lo::Integer, hiA::Integer, hi::In
755751
end
756752
end
757753

758-
# merge v[lo:lo+lenA-1] and v[lo+lenA:hi] using buffer t[1:lenA]
754+
# merge v[lo:m] and v[m+1:hi] using buffer t[1:1+m-lo]
759755
# based on Base.Sort MergeSort
760-
function merge!(v::AbstractVector{T}, lo::Integer, hi::Integer, lenA::Integer, o::Ordering, t::AbstractVector{T}) where T
756+
function merge!(v::AbstractVector{T}, lo::Integer, m::Integer, hi::Integer, o::Ordering, t::AbstractVector{T}) where T
761757
@inbounds begin
762-
i = 1
763-
j = lo
764-
while i <= lenA
758+
i, j = 1, lo
759+
while j <= m
765760
t[i] = v[j]
766761
i +=1
767762
j +=1
768763
end
769-
iA = 1
764+
a, b = 1, m + 1
770765
k = lo
771-
iB = lo + lenA
772-
while k < iB <= hi
773-
if lt(o,v[iB], t[iA])
774-
v[k] = v[iB]
775-
iB += 1
766+
while k < b <= hi
767+
if lt(o, v[b], t[a])
768+
v[k] = v[b]
769+
b += 1
776770
else
777-
v[k] = t[iA]
778-
iA += 1
771+
v[k] = t[a]
772+
a += 1
779773
end
780774
k += 1
781775
end
782-
while iA <= lenA
783-
v[k] = t[iA]
776+
while k < b
777+
v[k] = t[a]
784778
k += 1
785-
iA += 1
779+
a += 1
786780
end
787781
end
788782
end
@@ -792,7 +786,7 @@ end
792786
# otherwise use next block in B
793787
macro getNextBlock!()
794788
quote
795-
if iA > nextBlockA * blocksize + lo
789+
if a > nextBlockA * blocksize + lo
796790
currentBlock = nextBlockA
797791
nextBlockA += 1
798792
else
@@ -804,18 +798,17 @@ macro getNextBlock!()
804798
end |> esc
805799
end
806800

807-
# merge v[lo:hiA] and v[hiA+1:hi] using buffer buf in O(sqrt(n)) space
808-
function pagedMerge!(v::AbstractVector{T}, lo::Integer, hiA::Integer, hi::Integer, o::Ordering, buf::AbstractVector{T}, blockLocation::AbstractVector{<:Integer}) where T
809-
@assert lo < hiA < hi
810-
iA = lo
811-
iB = hiA + 1
812-
hiB = hi
813-
lenA = hiA + 1 - lo
814-
lenB = hiB - hiA
801+
# merge v[lo:m] and v[m+1:hi] using buffer buf in O(sqrt(n)) space
802+
function pagedMerge!(v::AbstractVector{T}, lo::Integer, m::Integer, hi::Integer, o::Ordering, buf::AbstractVector{T}, blockLocation::AbstractVector{<:Integer}) where T
803+
@assert lo < m < hi
804+
a = lo
805+
b = m + 1
806+
lenA = 1 + m - lo
807+
lenB = hi - m
815808

816809
# regular merge if buffer is big enough
817810
if lenA <= length(buf)
818-
merge!(v, lo, hi, lenA, o, buf)
811+
merge!(v, lo, m, hi, o, buf)
819812
return
820813
elseif lenB <= length(buf)
821814
# TODO ?
@@ -824,11 +817,11 @@ function pagedMerge!(v::AbstractVector{T}, lo::Integer, hiA::Integer, hi::Intege
824817
return
825818
end
826819

827-
len = hi + 1 - lo
820+
len = lenA + lenB
828821
blocksize = isqrt(len)
829822
nBlocks = len ÷ blocksize
830823
@assert length(buf) >= 3blocksize
831-
@assert length(blockLocation) >= nBlocks+1
824+
@assert length(blockLocation) >= nBlocks + 1
832825

833826
@inline getBlockOffset(block) = (block-1)*blocksize + lo - 1
834827

@@ -837,92 +830,93 @@ function pagedMerge!(v::AbstractVector{T}, lo::Integer, hiA::Integer, hi::Intege
837830
# merge
838831
##################
839832
# merge into buf until full
840-
oBuf = 1
841-
while oBuf <= 3blocksize # cannot run out of input elements here
842-
if lt(o, v[iB], v[iA]) # -> merge! would have been used
843-
buf[oBuf] = v[iB]
844-
iB += 1
833+
j = 1
834+
while j <= 3blocksize # cannot run out of input elements here
835+
if lt(o, v[b], v[a]) # -> merge! would have been used
836+
buf[j] = v[b]
837+
b += 1
845838
else
846-
buf[oBuf] = v[iA]
847-
iA += 1
839+
buf[j] = v[a]
840+
a += 1
848841
end
849-
oBuf += 1
842+
j += 1
850843
end
851844

852845
nextBlockA = 1
853-
nextBlockB = (hiA+blocksize-lo) ÷ blocksize + 1
846+
nextBlockB = (m + blocksize-lo) ÷ blocksize + 1
854847
blockLocation .= 0
855848
blockLocation[1:3] = -1:-1:-3
856849

857-
oIdx = 1
850+
k = 1
858851
currentBlock = 0
859852
currentBlockIdx = 4
860853
# more efficient loop while more than blocksize elements of A and B are remaining
861-
while iA < hiA-blocksize && iB < hiB-blocksize
854+
while a < m-blocksize && b < hi-blocksize
862855
@getNextBlock!
863856
offset = (currentBlock-1)*blocksize
864-
oIdx = lo + offset
865-
while oIdx <= blocksize+offset + lo - 1
866-
if lt(o, v[iB], v[iA])
867-
v[oIdx] = v[iB]
868-
iB += 1
857+
k = lo + offset
858+
while k <= blocksize+offset + lo - 1
859+
if lt(o, v[b], v[a])
860+
v[k] = v[b]
861+
b += 1
869862
else
870-
v[oIdx] = v[iA]
871-
iA += 1
863+
v[k] = v[a]
864+
a += 1
872865
end
873-
oIdx += 1
866+
k += 1
874867
end
875868
end
876869
# merge until either A or B is empty
877-
while iA <= hiA && iB <= hiB
870+
k_block = 1
871+
while a <= m && b <= hi
878872
@getNextBlock!
879-
oIdx = 1
873+
k_block = 1
880874
offset = getBlockOffset(currentBlock)
881-
while oIdx <= blocksize && iA <= hiA && iB <= hiB
882-
if lt(o, v[iB], v[iA])
883-
v[offset+oIdx] = v[iB]
884-
iB += 1
875+
while k_block <= blocksize && a <= m && b <= hi
876+
if lt(o, v[b], v[a])
877+
v[offset+k_block] = v[b]
878+
b += 1
885879
else
886-
v[offset+oIdx] = v[iA]
887-
iA += 1
880+
v[offset+k_block] = v[a]
881+
a += 1
888882
end
889-
oIdx += 1
883+
k_block += 1
890884
end
891885
end
892886
# copy remaining elements
893887
# either A or B is empty
894888
# copy rest of A
895-
while iA <= hiA
896-
if oIdx > blocksize
889+
while a <= m
890+
if k_block > blocksize
897891
@getNextBlock!
898-
oIdx = 1
892+
k_block = 1
899893
end
900894
offset = getBlockOffset(currentBlock)
901-
while oIdx <= blocksize && iA <= hiA
902-
v[offset + oIdx] = v[iA]
903-
iA += 1
904-
oIdx += 1
895+
while k_block <= blocksize && a <= m
896+
v[offset + k_block] = v[a]
897+
a += 1
898+
k_block += 1
905899
end
906900
end
907901
# copy rest of B
908-
while iB <= hiB
909-
if oIdx > blocksize
902+
while b <= hi
903+
if k_block > blocksize
910904
@getNextBlock!
911-
oIdx = 1
905+
k_block = 1
912906
end
913907
offset = getBlockOffset(currentBlock)
914-
while oIdx <= blocksize && iB <= hiB
915-
v[offset + oIdx] = v[iB]
916-
iB += 1
917-
oIdx += 1
908+
while k_block <= blocksize && b <= hi
909+
v[offset + k_block] = v[b]
910+
b += 1
911+
k_block += 1
918912
end
919913
end
920914
# copy last partial block to end
921-
partialBlockPresent = oIdx <= blocksize
915+
partialBlockPresent = k_block <= blocksize
922916
if partialBlockPresent
923917
offset = getBlockOffset(currentBlock)
924918
offset2 = nBlocks*blocksize + lo - 1
925-
for j = 1:oIdx-1
919+
for j = 1:k_block-1
926920
v[offset2 + j] = v[offset + j]
927921
end
928922
blockLocation[currentBlockIdx-1] = 0
@@ -1048,7 +1042,7 @@ function threaded_pagedmergesort!(v::AbstractVector, lo::Integer, hi::Integer, o
10481042
pagedmergesort!(v, m+1, hi, o, buf, blockLocation)
10491043
end
10501044
if len <= length(buf)
1051-
twoended_merge!(v, lo, hi, m, o, buf)
1045+
twoended_merge!(v, lo, m, hi, o, buf)
10521046
else
10531047
pagedMerge!(v, lo, m, hi, o, buf, blockLocation)
10541048
end

0 commit comments

Comments
 (0)