diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2000-10-06 16:13:29 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2000-10-06 16:13:29 -0300 |
commit | f01e6c6f1dc8e82faa782020556de9073b683be7 (patch) | |
tree | d840fee29e8b2637c841e73012a0da20adfa7f50 | |
parent | ad3816d0d15b9e681a39dfe90b78ecd8e68aaec7 (diff) | |
download | lua-f01e6c6f1dc8e82faa782020556de9073b683be7.tar.gz lua-f01e6c6f1dc8e82faa782020556de9073b683be7.tar.bz2 lua-f01e6c6f1dc8e82faa782020556de9073b683be7.zip |
small optimization in `sort'
-rw-r--r-- | lbaselib.c | 88 |
1 files changed, 45 insertions, 43 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lbaselib.c,v 1.8 2000/10/02 20:10:55 roberto Exp roberto $ | 2 | ** $Id: lbaselib.c,v 1.9 2000/10/05 12:14:08 roberto Exp roberto $ |
3 | ** Basic library | 3 | ** Basic library |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -433,75 +433,78 @@ static int luaB_tremove (lua_State *L) { | |||
433 | */ | 433 | */ |
434 | 434 | ||
435 | 435 | ||
436 | static void swap (lua_State *L, int i, int j) { | 436 | static void set2 (lua_State *L, int i, int j) { |
437 | lua_rawgeti(L, 1, i); | ||
438 | lua_rawgeti(L, 1, j); | ||
439 | lua_rawseti(L, 1, i); | 437 | lua_rawseti(L, 1, i); |
440 | lua_rawseti(L, 1, j); | 438 | lua_rawseti(L, 1, j); |
441 | } | 439 | } |
442 | 440 | ||
443 | static int sort_comp (lua_State *L, int n, int r) { | 441 | static int sort_comp (lua_State *L, int a, int b) { |
444 | /* WARNING: the caller (auxsort) must ensure stack space */ | 442 | /* WARNING: the caller (auxsort) must ensure stack space */ |
445 | int res; | ||
446 | if (!lua_isnil(L, 2)) { /* function? */ | 443 | if (!lua_isnil(L, 2)) { /* function? */ |
444 | int res; | ||
447 | lua_pushvalue(L, 2); | 445 | lua_pushvalue(L, 2); |
448 | if (r) { | 446 | lua_pushvalue(L, a-1); /* -1 to compensate function */ |
449 | lua_rawgeti(L, 1, n); /* a[n] */ | 447 | lua_pushvalue(L, b-2); /* -2 to compensate function and `a' */ |
450 | lua_pushvalue(L, -3); /* pivot */ | ||
451 | } | ||
452 | else { | ||
453 | lua_pushvalue(L, -2); /* pivot */ | ||
454 | lua_rawgeti(L, 1, n); /* a[n] */ | ||
455 | } | ||
456 | lua_rawcall(L, 2, 1); | 448 | lua_rawcall(L, 2, 1); |
457 | res = !lua_isnil(L, -1); | 449 | res = !lua_isnil(L, -1); |
450 | lua_pop(L, 1); | ||
451 | return res; | ||
458 | } | 452 | } |
459 | else { /* a < b? */ | 453 | else /* a < b? */ |
460 | lua_rawgeti(L, 1, n); /* a[n] */ | 454 | return lua_lessthan(L, a, b); |
461 | if (r) | ||
462 | res = lua_lessthan(L, -1, -2); | ||
463 | else | ||
464 | res = lua_lessthan(L, -2, -1); | ||
465 | } | ||
466 | lua_pop(L, 1); | ||
467 | return res; | ||
468 | } | 455 | } |
469 | 456 | ||
470 | static void auxsort (lua_State *L, int l, int u) { | 457 | static void auxsort (lua_State *L, int l, int u) { |
471 | while (l < u) { /* for tail recursion */ | 458 | while (l < u) { /* for tail recursion */ |
472 | int i, j; | 459 | int i, j; |
473 | luaL_checkstack(L, 4, "array too large"); | ||
474 | /* sort elements a[l], a[(l+u)/2] and a[u] */ | 460 | /* sort elements a[l], a[(l+u)/2] and a[u] */ |
461 | lua_rawgeti(L, 1, l); | ||
475 | lua_rawgeti(L, 1, u); | 462 | lua_rawgeti(L, 1, u); |
476 | if (sort_comp(L, l, 0)) /* a[u] < a[l]? */ | 463 | if (sort_comp(L, -1, -2)) /* a[u] < a[l]? */ |
477 | swap(L, l, u); | 464 | set2(L, l, u); /* swap a[l] - a[u] */ |
478 | lua_pop(L, 1); | 465 | else |
466 | lua_pop(L, 2); | ||
479 | if (u-l == 1) break; /* only 2 elements */ | 467 | if (u-l == 1) break; /* only 2 elements */ |
480 | i = (l+u)/2; | 468 | i = (l+u)/2; |
481 | lua_rawgeti(L, 1, i); /* Pivot = a[i] */ | 469 | lua_rawgeti(L, 1, i); |
482 | if (sort_comp(L, l, 0)) /* a[i]<a[l]? */ | 470 | lua_rawgeti(L, 1, l); |
483 | swap(L, l, i); | 471 | if (sort_comp(L, -2, -1)) /* a[i]<a[l]? */ |
472 | set2(L, i, l); | ||
484 | else { | 473 | else { |
485 | if (sort_comp(L, u, 1)) /* a[u]<a[i]? */ | 474 | lua_pop(L, 1); /* remove a[l] */ |
486 | swap(L, i, u); | 475 | lua_rawgeti(L, 1, u); |
476 | if (sort_comp(L, -1, -2)) /* a[u]<a[i]? */ | ||
477 | set2(L, i, u); | ||
478 | else | ||
479 | lua_pop(L, 2); | ||
487 | } | 480 | } |
488 | lua_pop(L, 1); /* pop old a[i] */ | ||
489 | if (u-l == 2) break; /* only 3 elements */ | 481 | if (u-l == 2) break; /* only 3 elements */ |
490 | lua_rawgeti(L, 1, i); /* Pivot */ | 482 | lua_rawgeti(L, 1, i); /* Pivot */ |
491 | swap(L, i, u-1); /* put median element as pivot (a[u-1]) */ | 483 | lua_pushvalue(L, -1); |
492 | /* a[l] <= P == a[u-1] <= a[u], only needs to sort from l+1 to u-2 */ | 484 | lua_rawgeti(L, 1, u-1); |
485 | set2(L, i, u-1); | ||
486 | /* a[l] <= P == a[u-1] <= a[u], only need to sort from l+1 to u-2 */ | ||
493 | i = l; j = u-1; | 487 | i = l; j = u-1; |
494 | for (;;) { /* invariant: a[l..i] <= P <= a[j..u] */ | 488 | for (;;) { /* invariant: a[l..i] <= P <= a[j..u] */ |
495 | /* repeat i++ until a[i] >= P */ | 489 | /* repeat ++i until a[i] >= P */ |
496 | while (sort_comp(L, ++i, 1)) | 490 | while (lua_rawgeti(L, 1, ++i), sort_comp(L, -1, -2)) { |
497 | if (i>u) lua_error(L, "invalid order function for sorting"); | 491 | if (i>u) lua_error(L, "invalid order function for sorting"); |
498 | /* repeat j-- until a[j] <= P */ | 492 | lua_pop(L, 1); /* remove a[i] */ |
499 | while (sort_comp(L, --j, 0)) | 493 | } |
494 | /* repeat --j until a[j] <= P */ | ||
495 | while (lua_rawgeti(L, 1, --j), sort_comp(L, -3, -1)) { | ||
500 | if (j<l) lua_error(L, "invalid order function for sorting"); | 496 | if (j<l) lua_error(L, "invalid order function for sorting"); |
501 | if (j<i) break; | 497 | lua_pop(L, 1); /* remove a[j] */ |
502 | swap(L, i, j); | 498 | } |
499 | if (j<i) { | ||
500 | lua_pop(L, 3); /* pop pivot, a[i], a[j] */ | ||
501 | break; | ||
502 | } | ||
503 | set2(L, i, j); | ||
503 | } | 504 | } |
504 | swap(L, u-1, i); /* swap pivot (a[u-1]) with a[i] */ | 505 | lua_rawgeti(L, 1, u-1); |
506 | lua_rawgeti(L, 1, i); | ||
507 | set2(L, u-1, i); /* swap pivot (a[u-1]) with a[i] */ | ||
505 | /* a[l..i-1] <= a[i] == P <= a[i+1..u] */ | 508 | /* a[l..i-1] <= a[i] == P <= a[i+1..u] */ |
506 | /* adjust so that smaller "half" is in [j..i] and larger one in [l..u] */ | 509 | /* adjust so that smaller "half" is in [j..i] and larger one in [l..u] */ |
507 | if (i-l < u-i) { | 510 | if (i-l < u-i) { |
@@ -510,7 +513,6 @@ static void auxsort (lua_State *L, int l, int u) { | |||
510 | else { | 513 | else { |
511 | j=i+1; i=u; u=j-2; | 514 | j=i+1; i=u; u=j-2; |
512 | } | 515 | } |
513 | lua_pop(L, 1); /* remove pivot from stack */ | ||
514 | auxsort(L, j, i); /* call recursively the smaller one */ | 516 | auxsort(L, j, i); /* call recursively the smaller one */ |
515 | } /* repeat the routine for the larger one */ | 517 | } /* repeat the routine for the larger one */ |
516 | } | 518 | } |