diff options
Diffstat (limited to 'ltablib.c')
-rw-r--r-- | ltablib.c | 27 |
1 files changed, 22 insertions, 5 deletions
@@ -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 | |||
237 | static void set2 (lua_State *L, int i, int j) { | 236 | static 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 | */ | ||
300 | static 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 | |||
297 | static void auxsort (lua_State *L, int lo, int up) { | 310 | static 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 | |||
341 | static int sort (lua_State *L) { | 358 | static 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 */ |