diff options
Diffstat (limited to '')
| -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 */ |
