diff options
Diffstat (limited to 'ltablib.c')
| -rw-r--r-- | ltablib.c | 40 |
1 files changed, 23 insertions, 17 deletions
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: ltablib.c,v 1.86 2015/11/20 12:30:20 roberto Exp roberto $ | 2 | ** $Id: ltablib.c,v 1.87 2015/11/23 11:09:27 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 | */ |
| @@ -230,7 +230,7 @@ static int unpack (lua_State *L) { | |||
| 230 | ** ======================================================= | 230 | ** ======================================================= |
| 231 | */ | 231 | */ |
| 232 | 232 | ||
| 233 | static void set2 (lua_State *L, int i, int j) { | 233 | static void set2 (lua_State *L, unsigned int i, unsigned int j) { |
| 234 | lua_seti(L, 1, i); | 234 | lua_seti(L, 1, i); |
| 235 | lua_seti(L, 1, j); | 235 | lua_seti(L, 1, j); |
| 236 | } | 236 | } |
| @@ -258,9 +258,10 @@ static int sort_comp (lua_State *L, int a, int b) { | |||
| 258 | ** Pos-condition: a[lo .. i - 1] <= a[i] == P <= a[i + 1 .. up] | 258 | ** Pos-condition: a[lo .. i - 1] <= a[i] == P <= a[i + 1 .. up] |
| 259 | ** returns 'i'. | 259 | ** returns 'i'. |
| 260 | */ | 260 | */ |
| 261 | static int partition (lua_State *L, int lo, int up) { | 261 | static unsigned int partition (lua_State *L, unsigned int lo, |
| 262 | int i = lo; /* will be incremented before first use */ | 262 | unsigned int up) { |
| 263 | int j = up - 1; /* will be decremented before first use */ | 263 | unsigned int i = lo; /* will be incremented before first use */ |
| 264 | unsigned int j = up - 1; /* will be decremented before first use */ | ||
| 264 | /* loop invariant: a[lo .. i] <= P <= a[j .. up] */ | 265 | /* loop invariant: a[lo .. i] <= P <= a[j .. up] */ |
| 265 | for (;;) { | 266 | for (;;) { |
| 266 | /* next loop: repeat ++i while a[i] < P */ | 267 | /* next loop: repeat ++i while a[i] < P */ |
| @@ -292,28 +293,30 @@ static int partition (lua_State *L, int lo, int up) { | |||
| 292 | 293 | ||
| 293 | /* | 294 | /* |
| 294 | ** Choose a "random" pivot in the middle part of the interval [lo, up]. | 295 | ** Choose a "random" pivot in the middle part of the interval [lo, up]. |
| 295 | ** (If you don't want/need this "randomness", (lo+up)/2 is an excelent | 296 | ** (If you don't want/need this "randomness", (lo+up)/2 is an excellent |
| 296 | ** choice.) | 297 | ** choice.) |
| 297 | */ | 298 | */ |
| 298 | #if !defined(l_sortpivot) | 299 | #if !defined(l_sortpivot) |
| 299 | /* Use 'time' and 'clock' as sources of "randomness" */ | 300 | /* Use 'time' and 'clock' as sources of "randomness" */ |
| 301 | |||
| 300 | #include <time.h> | 302 | #include <time.h> |
| 301 | static int choosePivot (int lo, int up) { | 303 | |
| 304 | static unsigned int choosePivot (unsigned int lo, unsigned int up) { | ||
| 302 | unsigned int t = (unsigned int)(unsigned long)time(NULL); /* time */ | 305 | unsigned int t = (unsigned int)(unsigned long)time(NULL); /* time */ |
| 303 | unsigned int c = (unsigned int)(unsigned long)clock(); /* clock */ | 306 | unsigned int c = (unsigned int)(unsigned long)clock(); /* clock */ |
| 304 | unsigned int r4 = (unsigned int)(up - lo) / 4u; /* range/4 */ | 307 | unsigned int r4 = (unsigned int)(up - lo) / 4u; /* range/4 */ |
| 305 | unsigned int p = (c + t) % (r4 * 2) + (lo + r4); | 308 | unsigned int p = (c + t) % (r4 * 2) + (lo + r4); |
| 306 | lua_assert(lo + r4 <= p && p <= up - r4); | 309 | lua_assert(lo + r4 <= p && p <= up - r4); |
| 307 | return (int)p; | 310 | return p; |
| 308 | } | 311 | } |
| 309 | 312 | ||
| 310 | #define l_sortpivot(lo,up) choosePivot(lo,up) | 313 | #define l_sortpivot(lo,up) choosePivot(lo,up) |
| 311 | #endif | 314 | #endif |
| 312 | 315 | ||
| 313 | 316 | ||
| 314 | static void auxsort (lua_State *L, int lo, int up) { | 317 | static void auxsort (lua_State *L, unsigned int lo, unsigned int up) { |
| 315 | while (lo < up) { /* loop for tail recursion */ | 318 | while (lo < up) { /* loop for tail recursion */ |
| 316 | int p; /* Pivot index */ | 319 | unsigned int p; /* Pivot index */ |
| 317 | /* sort elements 'lo', 'p', and 'up' */ | 320 | /* sort elements 'lo', 'p', and 'up' */ |
| 318 | lua_geti(L, 1, lo); | 321 | lua_geti(L, 1, lo); |
| 319 | lua_geti(L, 1, up); | 322 | lua_geti(L, 1, up); |
| @@ -323,7 +326,7 @@ static void auxsort (lua_State *L, int lo, int up) { | |||
| 323 | lua_pop(L, 2); /* remove both values */ | 326 | lua_pop(L, 2); /* remove both values */ |
| 324 | if (up - lo == 1) /* only 2 elements? */ | 327 | if (up - lo == 1) /* only 2 elements? */ |
| 325 | return; /* already sorted */ | 328 | return; /* already sorted */ |
| 326 | if (up - lo < 100) /* small interval? */ | 329 | if (up - lo < 100u) /* small interval? */ |
| 327 | p = (lo + up)/2; /* middle element is a good pivot */ | 330 | p = (lo + up)/2; /* middle element is a good pivot */ |
| 328 | else /* for larger intervals, it is worth a random pivot */ | 331 | else /* for larger intervals, it is worth a random pivot */ |
| 329 | p = l_sortpivot(lo, up); | 332 | p = l_sortpivot(lo, up); |
| @@ -360,12 +363,15 @@ static void auxsort (lua_State *L, int lo, int up) { | |||
| 360 | 363 | ||
| 361 | 364 | ||
| 362 | static int sort (lua_State *L) { | 365 | static int sort (lua_State *L) { |
| 363 | int n = (int)aux_getn(L, 1, TAB_RW); | 366 | lua_Integer n = aux_getn(L, 1, TAB_RW); |
| 364 | luaL_checkstack(L, 50, ""); /* assume array is smaller than 2^50 */ | 367 | if (n > 1) { /* non-trivial interval? */ |
| 365 | if (!lua_isnoneornil(L, 2)) /* is there a 2nd argument? */ | 368 | luaL_argcheck(L, n < INT_MAX, 1, "array too big"); |
| 366 | luaL_checktype(L, 2, LUA_TFUNCTION); | 369 | luaL_checkstack(L, 40, ""); /* assume array is smaller than 2^40 */ |
| 367 | lua_settop(L, 2); /* make sure there are two arguments */ | 370 | if (!lua_isnoneornil(L, 2)) /* is there a 2nd argument? */ |
| 368 | auxsort(L, 1, n); | 371 | luaL_checktype(L, 2, LUA_TFUNCTION); /* must be a function */ |
| 372 | lua_settop(L, 2); /* make sure there are two arguments */ | ||
| 373 | auxsort(L, 1, (unsigned int)n); | ||
| 374 | } | ||
| 369 | return 0; | 375 | return 0; |
| 370 | } | 376 | } |
| 371 | 377 | ||
