aboutsummaryrefslogtreecommitdiff
path: root/ltablib.c
diff options
context:
space:
mode:
Diffstat (limited to 'ltablib.c')
-rw-r--r--ltablib.c27
1 files changed, 22 insertions, 5 deletions
diff --git a/ltablib.c b/ltablib.c
index 7dae7049..c093187f 100644
--- a/ltablib.c
+++ b/ltablib.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: ltablib.c,v 1.83 2015/09/17 15:53:50 roberto Exp roberto $ 2** $Id: ltablib.c,v 1.84 2015/11/06 16:07:14 roberto Exp roberto $
3** Library for Table Manipulation 3** Library for Table Manipulation
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -233,7 +233,6 @@ static int unpack (lua_State *L) {
233** ======================================================= 233** =======================================================
234*/ 234*/
235 235
236
237static void set2 (lua_State *L, int i, int j) { 236static void set2 (lua_State *L, int i, int j) {
238 lua_seti(L, 1, i); 237 lua_seti(L, 1, i);
239 lua_seti(L, 1, j); 238 lua_seti(L, 1, j);
@@ -269,14 +268,14 @@ static int partition (lua_State *L, int lo, int up) {
269 for (;;) { 268 for (;;) {
270 /* next loop: repeat ++i while a[i] < P */ 269 /* next loop: repeat ++i while a[i] < P */
271 while (lua_geti(L, 1, ++i), sort_comp(L, -1, -2)) { 270 while (lua_geti(L, 1, ++i), sort_comp(L, -1, -2)) {
272 if (i >= up) 271 if (i == up - 1) /* a[i] < P but a[up - 1] == P ?? */
273 luaL_error(L, "invalid order function for sorting"); 272 luaL_error(L, "invalid order function for sorting");
274 lua_pop(L, 1); /* remove a[i] */ 273 lua_pop(L, 1); /* remove a[i] */
275 } 274 }
276 /* after the loop, a[i] >= P and a[lo .. i - 1] < P */ 275 /* after the loop, a[i] >= P and a[lo .. i - 1] < P */
277 /* next loop: repeat --j while P < a[j] */ 276 /* next loop: repeat --j while P < a[j] */
278 while (lua_geti(L, 1, --j), sort_comp(L, -3, -1)) { 277 while (lua_geti(L, 1, --j), sort_comp(L, -3, -1)) {
279 if (j < lo) 278 if (j < i) /* j < i but a[j] > P ?? */
280 luaL_error(L, "invalid order function for sorting"); 279 luaL_error(L, "invalid order function for sorting");
281 lua_pop(L, 1); /* remove a[j] */ 280 lua_pop(L, 1); /* remove a[j] */
282 } 281 }
@@ -294,6 +293,20 @@ static int partition (lua_State *L, int lo, int up) {
294} 293}
295 294
296 295
296/*
297** Choose a "random" pivot in the middle part of the interval [lo, up].
298** Use 'time' and 'clock' as sources of "randomness".
299*/
300static int choosePivot (int lo, int up) {
301 unsigned int t = (unsigned int)(unsigned long)time(NULL); /* time */
302 unsigned int c = (unsigned int)(unsigned long)clock(); /* clock */
303 unsigned int r4 = (unsigned int)(up - lo) / 4u; /* range/4 */
304 unsigned int p = (c + t) % (r4 * 2) + (lo + r4);
305 lua_assert(lo + r4 <= p && p <= up - r4);
306 return (int)p;
307}
308
309
297static void auxsort (lua_State *L, int lo, int up) { 310static void auxsort (lua_State *L, int lo, int up) {
298 while (lo < up) { /* loop for tail recursion */ 311 while (lo < up) { /* loop for tail recursion */
299 int p; 312 int p;
@@ -306,7 +319,10 @@ static void auxsort (lua_State *L, int lo, int up) {
306 lua_pop(L, 2); /* remove both values */ 319 lua_pop(L, 2); /* remove both values */
307 if (up - lo == 1) /* only 2 elements? */ 320 if (up - lo == 1) /* only 2 elements? */
308 return; /* already sorted */ 321 return; /* already sorted */
309 p = (lo + up)/2; 322 if (up - lo < 100) /* small interval? */
323 p = (lo + up)/2; /* middle element is a good pivot */
324 else /* for larger intervals, it is worth a random pivot */
325 p = choosePivot(lo, up);
310 lua_geti(L, 1, p); 326 lua_geti(L, 1, p);
311 lua_geti(L, 1, lo); 327 lua_geti(L, 1, lo);
312 if (sort_comp(L, -2, -1)) /* a[p] < a[lo]? */ 328 if (sort_comp(L, -2, -1)) /* a[p] < a[lo]? */
@@ -338,6 +354,7 @@ static void auxsort (lua_State *L, int lo, int up) {
338 } /* tail call auxsort(L, lo, up) */ 354 } /* tail call auxsort(L, lo, up) */
339} 355}
340 356
357
341static int sort (lua_State *L) { 358static int sort (lua_State *L) {
342 int n = (int)aux_getn(L, 1, TAB_RW); 359 int n = (int)aux_getn(L, 1, TAB_RW);
343 luaL_checkstack(L, 50, ""); /* assume array is smaller than 2^50 */ 360 luaL_checkstack(L, 50, ""); /* assume array is smaller than 2^50 */