From 27b73543e028e013138e4ae2d2b1968019bffab5 Mon Sep 17 00:00:00 2001 From: Max Cahill <1bardesign@gmail.com> Date: Tue, 10 Mar 2020 13:14:26 +1100 Subject: [PATCH] [modified] clean up source of stable_sort.lua --- stable_sort.lua | 54 +++++++++++++++++++++++++------------------------ 1 file changed, 28 insertions(+), 26 deletions(-) diff --git a/stable_sort.lua b/stable_sort.lua index 0f6686b..09e9a8d 100644 --- a/stable_sort.lua +++ b/stable_sort.lua @@ -43,13 +43,13 @@ local _sort_core = {} --tunable size for _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 local k = first local v = array[i] for j = i, first + 1, -1 do - if less( v, array[j-1] ) then - array[j] = array[j-1] + if less(v, array[j - 1]) then + array[j] = array[j - 1] else k = j break @@ -59,12 +59,12 @@ function _sort_core.insertion_sort_impl( array, first, last, less ) 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 i = 1 -- copy first half of array to auxiliary array for j = low, middle do - workspace[ i ] = array[ j ] + workspace[i] = array[j] i = i + 1 end -- sieve through @@ -75,18 +75,18 @@ function _sort_core.merge( array, workspace, low, middle, high, less ) if (k >= j) or (j > high) then break end - if less( array[ j ], workspace[ i ] ) then - array[ k ] = array[ j ] + if less(array[j], workspace[i]) then + array[k] = array[j] j = j + 1 else - array[ k ] = workspace[ i ] + array[k] = workspace[i] i = i + 1 end k = k + 1 end -- copy back any remaining elements of first half - for k = k, j-1 do - array[ k ] = workspace[ i ] + for k = k, j - 1 do + array[k] = workspace[i] i = i + 1 end end @@ -94,30 +94,31 @@ end function _sort_core.merge_sort_impl(array, workspace, low, high, less) 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 - local middle = math.floor((low + high)/2) - _sort_core.merge_sort_impl( array, workspace, low, middle, less ) - _sort_core.merge_sort_impl( array, workspace, middle + 1, high, less ) - _sort_core.merge( array, workspace, low, middle, high, less ) + local middle = math.floor((low + high) / 2) + _sort_core.merge_sort_impl(array, workspace, low, middle, less) + _sort_core.merge_sort_impl(array, workspace, middle + 1, high, less) + _sort_core.merge(array, workspace, low, middle, high, less) end end +function default_less(a, b) + return a < b +end + --inline common setup stuff function _sort_core.sort_setup(array, less) + --default less + less = less or default_less + -- local n = #array - local trivial = false --trivial cases; empty or 1 element - if n <= 1 then - trivial = true - else - --default less - less = less or function (a, b) - return a < b - end + local trivial = (n <= 1) + if not trivial then --check less 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 --setup complete @@ -128,9 +129,10 @@ function _sort_core.stable_sort(array, less) --setup local trivial, n, less = _sort_core.sort_setup(array, less) if not trivial then - --temp storage + --temp storage; allocate ahead of time local workspace = {} - workspace[ math.floor( (n+1)/2 ) ] = array[1] + local middle = math.ceil(n / 2) + workspace[middle] = array[1] --dive in _sort_core.merge_sort_impl( array, workspace, 1, n, less ) end