aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>1999-01-04 10:55:09 -0200
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>1999-01-04 10:55:09 -0200
commit03d38b66fd60209f9e5219fac2429d762417723d (patch)
treedc0215c90d3da4dc1381d305b5ba76ffa2733151
parentb9c9ccfbb4ed9c6cf6177d20cfd376a0fcb7a959 (diff)
downloadlua-03d38b66fd60209f9e5219fac2429d762417723d.tar.gz
lua-03d38b66fd60209f9e5219fac2429d762417723d.tar.bz2
lua-03d38b66fd60209f9e5219fac2429d762417723d.zip
new sort algorithm.
-rw-r--r--lbuiltin.c120
1 files changed, 66 insertions, 54 deletions
diff --git a/lbuiltin.c b/lbuiltin.c
index 7b67b9fc..8287a191 100644
--- a/lbuiltin.c
+++ b/lbuiltin.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lbuiltin.c,v 1.40 1998/12/27 20:22:36 roberto Exp roberto $ 2** $Id: lbuiltin.c,v 1.43 1998/12/30 13:16:50 roberto Exp $
3** Built-in functions 3** Built-in functions
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -28,7 +28,7 @@
28 28
29 29
30/* 30/*
31** ======================================================= 31** {======================================================
32** Auxliliar functions 32** Auxliliar functions
33** ======================================================= 33** =======================================================
34*/ 34*/
@@ -45,7 +45,6 @@ static void pushtagstring (TaggedString *s) {
45static real getsize (Hash *h) { 45static real getsize (Hash *h) {
46 real max = 0; 46 real max = 0;
47 int i; 47 int i;
48 LUA_ASSERT(ttype(t) == LUA_T_ARRAY, "table expected");
49 for (i = 0; i<nhash(h); i++) { 48 for (i = 0; i<nhash(h); i++) {
50 Node *n = h->node+i; 49 Node *n = h->node+i;
51 if (ttype(ref(n)) == LUA_T_NUMBER && 50 if (ttype(ref(n)) == LUA_T_NUMBER &&
@@ -77,15 +76,11 @@ static void luaB_getn (void) {
77 lua_pushnumber(getnarg(gethash(1))); 76 lua_pushnumber(getnarg(gethash(1)));
78} 77}
79 78
80 79/* }====================================================== */
81static void tablemove (Hash *a, int from, int to) {
82 TObject temp = *luaH_getint(a, from);
83 luaH_setint(a, to, &temp);
84}
85 80
86 81
87/* 82/*
88** ======================================================= 83** {======================================================
89** Functions that use only the official API 84** Functions that use only the official API
90** ======================================================= 85** =======================================================
91*/ 86*/
@@ -243,10 +238,11 @@ static void luaB_collectgarbage (void) {
243 lua_pushnumber(lua_collectgarbage(luaL_opt_int(1, 0))); 238 lua_pushnumber(lua_collectgarbage(luaL_opt_int(1, 0)));
244} 239}
245 240
241/* }====================================================== */
246 242
247 243
248/* 244/*
249** ======================================================= 245** {======================================================
250** Functions that could use only the official API but 246** Functions that could use only the official API but
251** do not, for efficiency. 247** do not, for efficiency.
252** ======================================================= 248** =======================================================
@@ -307,13 +303,16 @@ static void luaB_call (void) {
307 } 303 }
308} 304}
309 305
306/* }====================================================== */
310 307
311 308
312/* 309/*
313** ======================================================= 310** {======================================================
314** "Extra" functions 311** "Extra" functions
315** (These functions can be written in Lua, so you can 312** These functions can be written in Lua, so you can
316** delete them if you need a tiny Lua implementation.) 313** delete them if you need a tiny Lua implementation.
314** If you delete them, remove their entries in array
315** "builtin_funcs".
317** ======================================================= 316** =======================================================
318*/ 317*/
319 318
@@ -332,8 +331,7 @@ static void luaB_foreachi (void) {
332 luaD_checkstack(3); /* for f, ref, and val */ 331 luaD_checkstack(3); /* for f, ref, and val */
333 for (i=1; i<=n; i++) { 332 for (i=1; i<=n; i++) {
334 *(L->stack.top++) = f; 333 *(L->stack.top++) = f;
335 ttype(L->stack.top) = LUA_T_NUMBER; 334 ttype(L->stack.top) = LUA_T_NUMBER; nvalue(L->stack.top++) = i;
336 nvalue(L->stack.top++) = i;
337 *(L->stack.top++) = *luaH_getint(t, i); 335 *(L->stack.top++) = *luaH_getint(t, i);
338 luaD_calln(2, 1); 336 luaD_calln(2, 1);
339 if (ttype(L->stack.top-1) != LUA_T_NIL) 337 if (ttype(L->stack.top-1) != LUA_T_NIL)
@@ -400,7 +398,7 @@ static void luaB_tinsert (void) {
400 } 398 }
401 luaV_setn(a, n+1); /* increment field "n" */ 399 luaV_setn(a, n+1); /* increment field "n" */
402 for ( ;n>=pos; n--) 400 for ( ;n>=pos; n--)
403 tablemove(a, n, n+1); 401 luaH_move(a, n, n+1);
404 luaH_setint(a, pos, luaA_Address(v)); 402 luaH_setint(a, pos, luaA_Address(v));
405} 403}
406 404
@@ -413,69 +411,79 @@ static void luaB_tremove (void) {
413 if (n <= 0) return; /* table is "empty" */ 411 if (n <= 0) return; /* table is "empty" */
414 luaV_setn(a, n-1); /* decrement field "n" */ 412 luaV_setn(a, n-1); /* decrement field "n" */
415 for ( ;pos<n; pos++) 413 for ( ;pos<n; pos++)
416 tablemove(a, pos+1, pos); 414 luaH_move(a, pos+1, pos);
417 luaA_pushobject(&v); 415 luaA_pushobject(&v);
418} 416}
419 417
420 418
421/* 419/* {
422** Quicksort algorithm from "Programming Pearls", pg. 112 420** Quicksort
423*/ 421*/
424 422
425static void swap (Hash *a, int i, int j) { 423static void swap (Hash *a, int i, int j) {
426 /* notice: must use two temporary vars, because luaH_setint may cause a 424 TObject temp = *luaH_getint(a, i);
427 rehash and change the addresses of values in the array */ 425 luaH_move(a, j, i);
428 TObject ai = *luaH_getint(a, i); 426 luaH_setint(a, j, &temp);
429 tablemove(a, j, i);
430 luaH_setint(a, j, &ai);
431} 427}
432 428
433static int sort_comp (TObject *f, TObject *a, TObject *b) { 429static int sort_comp (TObject *f, TObject *a, TObject *b) {
434 /* notice: the caller (auxsort) must check stack space */ 430 /* notice: the caller (auxsort) must check stack space */
435 if (f) { 431 if (f) {
436 *(L->stack.top++) = *f; 432 *(L->stack.top) = *f;
437 *(L->stack.top++) = *a; 433 *(L->stack.top+1) = *a;
438 *(L->stack.top++) = *b; 434 *(L->stack.top+2) = *b;
435 L->stack.top += 3;
439 luaD_calln(2, 1); 436 luaD_calln(2, 1);
440 } 437 }
441 else { /* a < b? */ 438 else { /* a < b? */
442 *(L->stack.top++) = *a; 439 *(L->stack.top) = *a;
443 *(L->stack.top++) = *b; 440 *(L->stack.top+1) = *b;
441 L->stack.top += 2;
444 luaV_comparison(LUA_T_NUMBER, LUA_T_NIL, LUA_T_NIL, IM_LT); 442 luaV_comparison(LUA_T_NUMBER, LUA_T_NIL, LUA_T_NIL, IM_LT);
445 } 443 }
446 return ttype(--(L->stack.top)) != LUA_T_NIL; 444 return ttype(--(L->stack.top)) != LUA_T_NIL;
447} 445}
448 446
449static void auxsort (Hash *a, int l, int u, TObject *f) { 447static void auxsort (Hash *a, int l, int u, TObject *f) {
450 init: 448 init: /* using goto's to optimize tail recursion */
451 if (u <= l) return; /* 0 or 1 element */ 449 if (u <= l) return; /* 0 or 1 element */
452 luaD_checkstack(4); /* for pivot, f, a, b (sort_comp) */
453 if (u-l == 1) { /* only two elements? */
454 if (sort_comp(f, luaH_getint(a, u), luaH_getint(a, l))) /* a[u] < a[l]? */
455 swap(a, l, u);
456 }
457 else { 450 else {
458 int i; 451 TObject *P;
459 int m = l; 452 int i, j;
460 swap(a, l, (l+u)/2); /* put middle element as pivot (a[l]) */ 453 /* sort elements a[l], a[(l+u)/2] and a[u] */
461 *(L->stack.top++) = *luaH_getint(a, l); /* save pivot on stack (for GC) */ 454 if (sort_comp(f, luaH_getint(a, u), luaH_getint(a, l))) /* a[l]>a[u]? */
462 for (i=l+1; i<=u; i++) { 455 swap(a, l, u);
463 /* invariant: a[l+1..m] < P <= a[m+1..i-1] */ 456 if (u-l == 1) return; /* only 2 elements */
464 if (sort_comp(f, luaH_getint(a, i), L->stack.top-1)) { /* a[i] < P? */ 457 i = (l+u)/2;
465 m++; 458 if (sort_comp(f, luaH_getint(a, i), luaH_getint(a, l))) /* a[l]>a[i]? */
466 swap(a, m, i); 459 swap(a, l, i);
467 } 460 else if (sort_comp(f, luaH_getint(a, u), luaH_getint(a, i))) /* a[i]>a[u]? */
461 swap(a, i, u);
462 if (u-l == 2) return; /* only 3 elements */
463 P = L->stack.top++;
464 *P = *luaH_getint(a, i); /* save pivot on stack (for GC) */
465 swap(a, i, u-1); /* put median element as pivot (a[u-1]) */
466 /* a[l] <= P == a[u-1] <= a[u], only needs to sort from l+1 to u-2 */
467 i = l; j = u-1;
468 for (;;) {
469 /* invariant: a[l..i] <= P <= a[j..u] */
470 while (sort_comp(f, luaH_getint(a, ++i), P)) /* stop when a[i] >= P */
471 if (i>u) lua_error("invalid order function for sorting");
472 while (sort_comp(f, P, luaH_getint(a, --j))) /* stop when a[j] <= P */
473 if (j<l) lua_error("invalid order function for sorting");
474 if (j<i) break;
475 swap(a, i, j);
468 } 476 }
477 swap(a, u-1, i); /* swap pivot (a[u-1]) with a[i] */
469 L->stack.top--; /* remove pivot from stack */ 478 L->stack.top--; /* remove pivot from stack */
470 swap(a, l, m); /* swap pivot with a[m] */ 479 /* a[l..i-1] <= a[i] == P <= a[i+1..u] */
471 /* a[l..m-1] < a[m] <= a[m+1..u] */ 480 if (i-l < u-i) { /* check which "half" is bigger */
472 if (m-l < u-m) { /* check which "half" is bigger */ 481 auxsort(a, l, i-1, f); /* call recursively the smaller one */
473 auxsort(a, l, m-1, f); /* call recursively the smaller one */ 482 l = i+1; goto init; /* auxsort(a, i+1, u, f); */
474 l = m+1; goto init; /* auxsort(a, m+1, u, f); */
475 } 483 }
476 else { 484 else {
477 auxsort(a, m+1, u, f); 485 auxsort(a, i+1, u, f);
478 u = m-1; goto init; /* auxsort(a, l, m-1, f); */ 486 u = i-1; goto init; /* auxsort(a, l, i-1, f); */
479 } 487 }
480 } 488 }
481} 489}
@@ -487,14 +495,16 @@ static void luaB_sort (void) {
487 lua_Object func = lua_getparam(2); 495 lua_Object func = lua_getparam(2);
488 TObject *f = luaA_Address(func); 496 TObject *f = luaA_Address(func);
489 luaL_arg_check(!f || lua_isfunction(func), 2, "function expected"); 497 luaL_arg_check(!f || lua_isfunction(func), 2, "function expected");
498 luaD_checkstack(4); /* for Pivot, f, a, b (sort_comp) */
490 auxsort(a, 1, n, f); 499 auxsort(a, 1, n, f);
491 lua_pushobject(t); 500 lua_pushobject(t);
492} 501}
493 502
503/* }}===================================================== */
494 504
495 505
496/* 506/*
497** ======================================================= 507** {======================================================
498** Internal Functions. 508** Internal Functions.
499** These functions need access to internal structures 509** These functions need access to internal structures
500** to be implemented. 510** to be implemented.
@@ -576,12 +586,13 @@ static void luaB_type (void) {
576 lua_pushnumber(lua_tag(o)); 586 lua_pushnumber(lua_tag(o));
577} 587}
578 588
589/* }====================================================== */
579 590
580 591
581 592
582#ifdef DEBUG 593#ifdef DEBUG
583/* 594/*
584** ======================================================= 595** {======================================================
585** some DEBUG functions 596** some DEBUG functions
586** ======================================================= 597** =======================================================
587*/ 598*/
@@ -652,6 +663,7 @@ static void testC (void) {
652 } 663 }
653} 664}
654 665
666/* }====================================================== */
655#endif 667#endif
656 668
657 669