summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2000-10-06 16:13:29 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2000-10-06 16:13:29 -0300
commitf01e6c6f1dc8e82faa782020556de9073b683be7 (patch)
treed840fee29e8b2637c841e73012a0da20adfa7f50
parentad3816d0d15b9e681a39dfe90b78ecd8e68aaec7 (diff)
downloadlua-f01e6c6f1dc8e82faa782020556de9073b683be7.tar.gz
lua-f01e6c6f1dc8e82faa782020556de9073b683be7.tar.bz2
lua-f01e6c6f1dc8e82faa782020556de9073b683be7.zip
small optimization in `sort'
-rw-r--r--lbaselib.c88
1 files changed, 45 insertions, 43 deletions
diff --git a/lbaselib.c b/lbaselib.c
index b66cf490..ffb47a2c 100644
--- a/lbaselib.c
+++ b/lbaselib.c
@@ -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
436static void swap (lua_State *L, int i, int j) { 436static 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
443static int sort_comp (lua_State *L, int n, int r) { 441static 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
470static void auxsort (lua_State *L, int l, int u) { 457static 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}