|
|
@ -231,10 +231,18 @@ static int tunpack (lua_State *L) { |
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
|
|
/* type for array indices */ |
|
|
|
/*
|
|
|
|
** Type for array indices. These indices are always limited by INT_MAX, |
|
|
|
** so it is safe to cast them to lua_Integer even for Lua 32 bits. |
|
|
|
*/ |
|
|
|
typedef unsigned int IdxT; |
|
|
|
|
|
|
|
|
|
|
|
/* Versions of lua_seti/lua_geti specialized for IdxT */ |
|
|
|
#define geti(L,idt,idx) lua_geti(L, idt, l_castU2S(idx)) |
|
|
|
#define seti(L,idt,idx) lua_seti(L, idt, l_castU2S(idx)) |
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
** Produce a "random" 'unsigned int' to randomize pivot choice. This |
|
|
|
** macro is used only when 'sort' detects a big imbalance in the result |
|
|
@ -251,8 +259,8 @@ typedef unsigned int IdxT; |
|
|
|
|
|
|
|
|
|
|
|
static void set2 (lua_State *L, IdxT i, IdxT j) { |
|
|
|
lua_seti(L, 1, i); |
|
|
|
lua_seti(L, 1, j); |
|
|
|
seti(L, 1, i); |
|
|
|
seti(L, 1, j); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -289,14 +297,14 @@ static IdxT partition (lua_State *L, IdxT lo, IdxT up) { |
|
|
|
/* loop invariant: a[lo .. i] <= P <= a[j .. up] */ |
|
|
|
for (;;) { |
|
|
|
/* next loop: repeat ++i while a[i] < P */ |
|
|
|
while ((void)lua_geti(L, 1, ++i), sort_comp(L, -1, -2)) { |
|
|
|
while ((void)geti(L, 1, ++i), sort_comp(L, -1, -2)) { |
|
|
|
if (l_unlikely(i == up - 1)) /* a[i] < P but a[up - 1] == P ?? */ |
|
|
|
luaL_error(L, "invalid order function for sorting"); |
|
|
|
lua_pop(L, 1); /* remove a[i] */ |
|
|
|
} |
|
|
|
/* after the loop, a[i] >= P and a[lo .. i - 1] < P */ |
|
|
|
/* next loop: repeat --j while P < a[j] */ |
|
|
|
while ((void)lua_geti(L, 1, --j), sort_comp(L, -3, -1)) { |
|
|
|
while ((void)geti(L, 1, --j), sort_comp(L, -3, -1)) { |
|
|
|
if (l_unlikely(j < i)) /* j < i but a[j] > P ?? */ |
|
|
|
luaL_error(L, "invalid order function for sorting"); |
|
|
|
lua_pop(L, 1); /* remove a[j] */ |
|
|
@ -335,8 +343,8 @@ static void auxsort (lua_State *L, IdxT lo, IdxT up, unsigned rnd) { |
|
|
|
IdxT p; /* Pivot index */ |
|
|
|
IdxT n; /* to be used later */ |
|
|
|
/* sort elements 'lo', 'p', and 'up' */ |
|
|
|
lua_geti(L, 1, lo); |
|
|
|
lua_geti(L, 1, up); |
|
|
|
geti(L, 1, lo); |
|
|
|
geti(L, 1, up); |
|
|
|
if (sort_comp(L, -1, -2)) /* a[up] < a[lo]? */ |
|
|
|
set2(L, lo, up); /* swap a[lo] - a[up] */ |
|
|
|
else |
|
|
@ -347,13 +355,13 @@ static void auxsort (lua_State *L, IdxT lo, IdxT up, unsigned rnd) { |
|
|
|
p = (lo + up)/2; /* middle element is a good pivot */ |
|
|
|
else /* for larger intervals, it is worth a random pivot */ |
|
|
|
p = choosePivot(lo, up, rnd); |
|
|
|
lua_geti(L, 1, p); |
|
|
|
lua_geti(L, 1, lo); |
|
|
|
geti(L, 1, p); |
|
|
|
geti(L, 1, lo); |
|
|
|
if (sort_comp(L, -2, -1)) /* a[p] < a[lo]? */ |
|
|
|
set2(L, p, lo); /* swap a[p] - a[lo] */ |
|
|
|
else { |
|
|
|
lua_pop(L, 1); /* remove a[lo] */ |
|
|
|
lua_geti(L, 1, up); |
|
|
|
geti(L, 1, up); |
|
|
|
if (sort_comp(L, -1, -2)) /* a[up] < a[p]? */ |
|
|
|
set2(L, p, up); /* swap a[up] - a[p] */ |
|
|
|
else |
|
|
@ -361,9 +369,9 @@ static void auxsort (lua_State *L, IdxT lo, IdxT up, unsigned rnd) { |
|
|
|
} |
|
|
|
if (up - lo == 2) /* only 3 elements? */ |
|
|
|
return; /* already sorted */ |
|
|
|
lua_geti(L, 1, p); /* get middle element (Pivot) */ |
|
|
|
geti(L, 1, p); /* get middle element (Pivot) */ |
|
|
|
lua_pushvalue(L, -1); /* push Pivot */ |
|
|
|
lua_geti(L, 1, up - 1); /* push a[up - 1] */ |
|
|
|
geti(L, 1, up - 1); /* push a[up - 1] */ |
|
|
|
set2(L, p, up - 1); /* swap Pivot (a[p]) with a[up - 1] */ |
|
|
|
p = partition(L, lo, up); |
|
|
|
/* a[lo .. p - 1] <= a[p] == P <= a[p + 1 .. up] */ |
|
|
|