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 | ||
