diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 1999-01-04 10:55:09 -0200 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 1999-01-04 10:55:09 -0200 |
commit | 03d38b66fd60209f9e5219fac2429d762417723d (patch) | |
tree | dc0215c90d3da4dc1381d305b5ba76ffa2733151 | |
parent | b9c9ccfbb4ed9c6cf6177d20cfd376a0fcb7a959 (diff) | |
download | lua-03d38b66fd60209f9e5219fac2429d762417723d.tar.gz lua-03d38b66fd60209f9e5219fac2429d762417723d.tar.bz2 lua-03d38b66fd60209f9e5219fac2429d762417723d.zip |
new sort algorithm.
-rw-r--r-- | lbuiltin.c | 120 |
1 files changed, 66 insertions, 54 deletions
@@ -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) { | |||
45 | static real getsize (Hash *h) { | 45 | static 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 | /* }====================================================== */ | |
81 | static 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 | ||
425 | static void swap (Hash *a, int i, int j) { | 423 | static 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 | ||
433 | static int sort_comp (TObject *f, TObject *a, TObject *b) { | 429 | static 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 | ||
449 | static void auxsort (Hash *a, int l, int u, TObject *f) { | 447 | static 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 | ||