[modified] clean up source of stable_sort.lua

This commit is contained in:
Max Cahill 2020-03-10 13:14:26 +11:00
parent 94005675e9
commit 27b73543e0

View File

@ -43,13 +43,13 @@ local _sort_core = {}
--tunable size for --tunable size for
_sort_core.max_chunk_size = 24 _sort_core.max_chunk_size = 24
function _sort_core.insertion_sort_impl( array, first, last, less ) function _sort_core.insertion_sort_impl(array, first, last, less)
for i = first + 1, last do for i = first + 1, last do
local k = first local k = first
local v = array[i] local v = array[i]
for j = i, first + 1, -1 do for j = i, first + 1, -1 do
if less( v, array[j-1] ) then if less(v, array[j - 1]) then
array[j] = array[j-1] array[j] = array[j - 1]
else else
k = j k = j
break break
@ -59,12 +59,12 @@ function _sort_core.insertion_sort_impl( array, first, last, less )
end end
end end
function _sort_core.merge( array, workspace, low, middle, high, less ) function _sort_core.merge(array, workspace, low, middle, high, less)
local i, j, k local i, j, k
i = 1 i = 1
-- copy first half of array to auxiliary array -- copy first half of array to auxiliary array
for j = low, middle do for j = low, middle do
workspace[ i ] = array[ j ] workspace[i] = array[j]
i = i + 1 i = i + 1
end end
-- sieve through -- sieve through
@ -75,18 +75,18 @@ function _sort_core.merge( array, workspace, low, middle, high, less )
if (k >= j) or (j > high) then if (k >= j) or (j > high) then
break break
end end
if less( array[ j ], workspace[ i ] ) then if less(array[j], workspace[i]) then
array[ k ] = array[ j ] array[k] = array[j]
j = j + 1 j = j + 1
else else
array[ k ] = workspace[ i ] array[k] = workspace[i]
i = i + 1 i = i + 1
end end
k = k + 1 k = k + 1
end end
-- copy back any remaining elements of first half -- copy back any remaining elements of first half
for k = k, j-1 do for k = k, j - 1 do
array[ k ] = workspace[ i ] array[k] = workspace[i]
i = i + 1 i = i + 1
end end
end end
@ -94,30 +94,31 @@ end
function _sort_core.merge_sort_impl(array, workspace, low, high, less) function _sort_core.merge_sort_impl(array, workspace, low, high, less)
if high - low <= _sort_core.max_chunk_size then if high - low <= _sort_core.max_chunk_size then
_sort_core.insertion_sort_impl( array, low, high, less ) _sort_core.insertion_sort_impl(array, low, high, less)
else else
local middle = math.floor((low + high)/2) local middle = math.floor((low + high) / 2)
_sort_core.merge_sort_impl( array, workspace, low, middle, less ) _sort_core.merge_sort_impl(array, workspace, low, middle, less)
_sort_core.merge_sort_impl( array, workspace, middle + 1, high, less ) _sort_core.merge_sort_impl(array, workspace, middle + 1, high, less)
_sort_core.merge( array, workspace, low, middle, high, less ) _sort_core.merge(array, workspace, low, middle, high, less)
end end
end end
function default_less(a, b)
return a < b
end
--inline common setup stuff --inline common setup stuff
function _sort_core.sort_setup(array, less) function _sort_core.sort_setup(array, less)
local n = #array
local trivial = false
--trivial cases; empty or 1 element
if n <= 1 then
trivial = true
else
--default less --default less
less = less or function (a, b) less = less or default_less
return a < b --
end local n = #array
--trivial cases; empty or 1 element
local trivial = (n <= 1)
if not trivial then
--check less --check less
if less(array[1], array[1]) then if less(array[1], array[1]) then
error("invalid order function for sorting") error("invalid order function for sorting; less(v, v) should not be true for any v.")
end end
end end
--setup complete --setup complete
@ -128,9 +129,10 @@ function _sort_core.stable_sort(array, less)
--setup --setup
local trivial, n, less = _sort_core.sort_setup(array, less) local trivial, n, less = _sort_core.sort_setup(array, less)
if not trivial then if not trivial then
--temp storage --temp storage; allocate ahead of time
local workspace = {} local workspace = {}
workspace[ math.floor( (n+1)/2 ) ] = array[1] local middle = math.ceil(n / 2)
workspace[middle] = array[1]
--dive in --dive in
_sort_core.merge_sort_impl( array, workspace, 1, n, less ) _sort_core.merge_sort_impl( array, workspace, 1, n, less )
end end