/* ** QuickSort algorithm (recursive function) */ static void auxsort (lua_State *L, IdxT lo, IdxT up, unsigned int rnd) { while (lo < up) { /* loop for tail recursion */ 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); if (sort_comp(L, -1, -2)) /* a[up] < a[lo]? */ set2(L, lo, up); /* swap a[lo] - a[up] */ else lua_pop(L, 2); /* remove both values */ if (up - lo == 1) /* only 2 elements? */ return; /* already sorted */ if (up - lo < RANLIMIT || rnd == 0) /* small interval or no randomize? */ 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); 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); if (sort_comp(L, -1, -2)) /* a[up] < a[p]? */ set2(L, p, up); /* swap a[up] - a[p] */ else lua_pop(L, 2); } if (up - lo == 2) /* only 3 elements? */ return; /* already sorted */ lua_geti(L, 1, p); /* get middle element (Pivot) */ lua_pushvalue(L, -1); /* push Pivot */ lua_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] */ if (p - lo < up - p) { /* lower interval is smaller? */ auxsort(L, lo, p - 1, rnd); /* call recursively for lower interval */ n = p - lo; /* size of smaller interval */ lo = p + 1; /* tail call for [p + 1 .. up] (upper interval) */ } else { auxsort(L, p + 1, up, rnd); /* call recursively for upper interval */ n = up - p; /* size of smaller interval */ up = p - 1; /* tail call for [lo .. p - 1] (lower interval) */ } if ((up - lo) / 128 > n) /* partition too imbalanced? */ rnd = l_randomizePivot(); /* try a new randomization */ } /* tail call auxsort(L, lo, up, rnd) */ }
static int libE_sort (lua_State *L) { int n = aux_getn(L, 1); luaL_checkstack(L, 40, ""); /* assume array is smaller than 2^40 */ if (!lua_isnoneornil(L, 2)) /* is there a 2nd argument? */ luaL_checktype(L, 2, LUA_TFUNCTION); lua_settop(L, 2); /* make sure there is two arguments */ auxsort(L, 1, n); return 0; }
static int sort (killa_State *L) { int n = aux_getn(L, 1) + KILLA_BASE - 1; killaL_checkstack(L, 40, ""); /* assume array is smaller than 2^40 */ if (!killa_isnoneornull(L, 2)) /* is there a 2nd argument? */ killaL_checktype(L, 2, KILLA_TFUNCTION); killa_settop(L, 2); /* make sure there is two arguments */ auxsort(L, KILLA_BASE, n); return 0; }
static int sort (lua_State *L) { TabA ta; int n = (int)aux_getn(L, 1, &ta); luaL_checkstack(L, 50, ""); /* assume array is smaller than 2^50 */ if (!lua_isnoneornil(L, 2)) /* is there a 2nd argument? */ luaL_checktype(L, 2, LUA_TFUNCTION); lua_settop(L, 2); /* make sure there are two arguments */ auxsort(L, &ta, 1, n); return 0; }
static int luaB_sort (lua_State *L) { int n; luaL_checktype(L, 1, LUA_TTABLE); n = lua_getn(L, 1); if (!lua_isnull(L, 2)) /* is there a 2nd argument? */ luaL_checktype(L, 2, LUA_TFUNCTION); lua_settop(L, 2); /* make sure there is two arguments */ auxsort(L, 1, n); return 0; }
static int sort (lv_State *L) { lv_clearFirstTableValue(L); int n = aux_getn(L, 1); lvL_checkstack(L, 40, ""); /* assume array is smaller than 2^40 */ if (!lv_isnoneornil(L, 2)) /* is there a 2nd argument? */ lvL_checktype(L, 2, LV_TFUNCTION); lv_settop(L, 2); /* make sure there is two arguments */ auxsort(L, 1, n); return 0; }
static int sort (lua_State *L) { lua_Integer n = aux_getn(L, 1, TAB_RW); if (n > 1) { /* non-trivial interval? */ luaL_argcheck(L, n < INT_MAX, 1, "array too big"); if (!lua_isnoneornil(L, 2)) /* is there a 2nd argument? */ luaL_checktype(L, 2, LUA_TFUNCTION); /* must be a function */ lua_settop(L, 2); /* make sure there are two arguments */ auxsort(L, 1, (IdxT)n, 0); } return 0; }
static void luaB_sort (void) { lua_Object t = lua_getparam(1); Hash *a = gethash(1); int n = (int)getnarg(a); lua_Object func = lua_getparam(2); luaL_arg_check(func == LUA_NOOBJECT || lua_isfunction(func), 2, "function expected"); luaD_checkstack(4); /* for Pivot, f, a, b (sort_comp) */ auxsort(a, 1, n, func); lua_pushobject(t); }
LUACLLIB_API void luaC_sortlist(lua_State* L, int tabix, int funcix /*=0*/) { luaL_checkstack(L, 41, ""); luaL_checktype(L, tabix, LUA_TTABLE); int t = lua_gettop(L); int ix = tabix; if (ix < 0) ix = t + (ix + 1); if (funcix == 0) lua_pushnil(L); else lua_pushvalue(L, funcix); int n = aux_getn(L, ix); auxsort(L, 1, n, ix, t + 1); lua_settop(L, t); }
static void auxsort (Hash *a, int l, int u, lua_Object f) { while (l < u) { /* for tail recursion */ TObject *P; int i, j; /* sort elements a[l], a[(l+u)/2] and a[u] */ if (sort_comp(f, luaH_getint(a, u), luaH_getint(a, l))) /* a[l]>a[u]? */ swap(a, l, u); if (u-l == 1) break; /* only 2 elements */ i = (l+u)/2; P = luaH_getint(a, i); if (sort_comp(f, P, luaH_getint(a, l))) /* a[l]>a[i]? */ swap(a, l, i); else if (sort_comp(f, luaH_getint(a, u), P)) /* a[i]>a[u]? */ swap(a, i, u); if (u-l == 2) break; /* only 3 elements */ P = L->stack.top++; *P = *luaH_getint(a, i); /* save pivot on stack (for GC) */ swap(a, i, u-1); /* put median element as pivot (a[u-1]) */ /* a[l] <= P == a[u-1] <= a[u], only needs to sort from l+1 to u-2 */ i = l; j = u-1; for (;;) { /* invariant: a[l..i] <= P <= a[j..u] */ while (sort_comp(f, luaH_getint(a, ++i), P)) /* stop when a[i] >= P */ if (i>u) lua_error("invalid order function for sorting"); while (sort_comp(f, P, luaH_getint(a, --j))) /* stop when a[j] <= P */ if (j<l) lua_error("invalid order function for sorting"); if (j<i) break; swap(a, i, j); } swap(a, u-1, i); /* swap pivot (a[u-1]) with a[i] */ L->stack.top--; /* remove pivot from stack */ /* a[l..i-1] <= a[i] == P <= a[i+1..u] */ /* adjust so that smaller "half" is in [j..i] and larger one in [l..u] */ if (i-l < u-i) { j=l; i=i-1; l=i+2; } else { j=i+1; i=u; u=j-2; } auxsort(a, j, i, f); /* call recursively the smaller one */ } /* repeat the routine for the larger one */ }
static void auxsort (lua_State *L, TabA *ta, int l, int u) { while (l < u) { /* for tail recursion */ int i, j; /* sort elements a[l], a[(l+u)/2] and a[u] */ (*ta->geti)(L, 1, l); (*ta->geti)(L, 1, u); if (sort_comp(L, -1, -2)) /* a[u] < a[l]? */ set2(L, ta, l, u); /* swap a[l] - a[u] */ else lua_pop(L, 2); if (u-l == 1) break; /* only 2 elements */ i = (l+u)/2; (*ta->geti)(L, 1, i); (*ta->geti)(L, 1, l); if (sort_comp(L, -2, -1)) /* a[i]<a[l]? */ set2(L, ta, i, l); else { lua_pop(L, 1); /* remove a[l] */ (*ta->geti)(L, 1, u); if (sort_comp(L, -1, -2)) /* a[u]<a[i]? */ set2(L, ta, i, u); else lua_pop(L, 2); } if (u-l == 2) break; /* only 3 elements */ (*ta->geti)(L, 1, i); /* Pivot */ lua_pushvalue(L, -1); (*ta->geti)(L, 1, u-1); set2(L, ta, i, u-1); /* a[l] <= P == a[u-1] <= a[u], only need to sort from l+1 to u-2 */ i = l; j = u-1; for (;;) { /* invariant: a[l..i] <= P <= a[j..u] */ /* repeat ++i until a[i] >= P */ while ((*ta->geti)(L, 1, ++i), sort_comp(L, -1, -2)) { if (i>=u) luaL_error(L, "invalid order function for sorting"); lua_pop(L, 1); /* remove a[i] */ } /* repeat --j until a[j] <= P */ while ((*ta->geti)(L, 1, --j), sort_comp(L, -3, -1)) { if (j<=l) luaL_error(L, "invalid order function for sorting"); lua_pop(L, 1); /* remove a[j] */ } if (j<i) { lua_pop(L, 3); /* pop pivot, a[i], a[j] */ break; } set2(L, ta, i, j); } (*ta->geti)(L, 1, u-1); (*ta->geti)(L, 1, i); set2(L, ta, u-1, i); /* swap pivot (a[u-1]) with a[i] */ /* a[l..i-1] <= a[i] == P <= a[i+1..u] */ /* adjust so that smaller half is in [j..i] and larger one in [l..u] */ if (i-l < u-i) { j=l; i=i-1; l=i+2; } else { j=i+1; i=u; u=j-2; } auxsort(L, ta, j, i); /* call recursively the smaller one */ } /* repeat the routine for the larger one */ }