diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 1998-11-13 14:39:18 -0200 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 1998-11-13 14:39:18 -0200 |
commit | 8e3bd752bbd9a629cb6367db4a4237514709ca75 (patch) | |
tree | 3030d70162530089592562a6df162a7096f5cb9e | |
parent | a84bca67fcf74241570d7f6d51243aecce9e71a6 (diff) | |
download | lua-8e3bd752bbd9a629cb6367db4a4237514709ca75.tar.gz lua-8e3bd752bbd9a629cb6367db4a4237514709ca75.tar.bz2 lua-8e3bd752bbd9a629cb6367db4a4237514709ca75.zip |
small optimization in "sort" + new functions "getn" and "foreachi"
-rw-r--r-- | lbuiltin.c | 96 |
1 files changed, 63 insertions, 33 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lbuiltin.c,v 1.33 1998/07/12 16:16:43 roberto Exp roberto $ | 2 | ** $Id: lbuiltin.c,v 1.34 1998/08/21 17:43:44 roberto Exp roberto $ |
3 | ** Built-in functions | 3 | ** Built-in functions |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -36,6 +36,35 @@ static void pushstring (TaggedString *s) | |||
36 | } | 36 | } |
37 | 37 | ||
38 | 38 | ||
39 | static int getsize (TObject *t) { | ||
40 | int max = 0; | ||
41 | int i; | ||
42 | Hash *h = avalue(t); | ||
43 | LUA_ASSERT(ttype(t) == LUA_T_ARRAY, "table expected"); | ||
44 | for (i = 0; i<nhash(h); i++) { | ||
45 | Node *n = h->node+i; | ||
46 | if (ttype(ref(n)) == LUA_T_NUMBER && ttype(val(n)) != LUA_T_NIL && | ||
47 | (int)nvalue(ref(n)) > max) | ||
48 | max = nvalue(ref(n)); | ||
49 | } | ||
50 | return max; | ||
51 | } | ||
52 | |||
53 | |||
54 | static int getnarg (lua_Object table) { | ||
55 | lua_Object temp; | ||
56 | /* temp = table.n */ | ||
57 | lua_pushobject(table); lua_pushstring("n"); temp = lua_rawgettable(); | ||
58 | return (lua_isnumber(temp) ? lua_getnumber(temp) : | ||
59 | getsize(luaA_Address(table))); | ||
60 | } | ||
61 | |||
62 | |||
63 | static void getn (void) { | ||
64 | lua_pushnumber(getnarg(luaL_tablearg(1))); | ||
65 | } | ||
66 | |||
67 | |||
39 | static void nextvar (void) { | 68 | static void nextvar (void) { |
40 | TObject *o = luaA_Address(luaL_nonnullarg(1)); | 69 | TObject *o = luaA_Address(luaL_nonnullarg(1)); |
41 | TaggedString *g; | 70 | TaggedString *g; |
@@ -113,6 +142,26 @@ static void foreach (void) { | |||
113 | } | 142 | } |
114 | 143 | ||
115 | 144 | ||
145 | static void foreachi (void) { | ||
146 | lua_Object ot = luaL_tablearg(1); | ||
147 | Hash *t = avalue(luaA_Address(ot)); | ||
148 | TObject f = *luaA_Address(luaL_functionarg(2)); | ||
149 | int i; | ||
150 | int n = getnarg(ot); | ||
151 | luaD_checkstack(3); /* for f, ref, and val */ | ||
152 | for (i=1; i<=n; i++) { | ||
153 | *(L->stack.top++) = f; | ||
154 | ttype(L->stack.top) = LUA_T_NUMBER; | ||
155 | nvalue(L->stack.top++) = i; | ||
156 | *(L->stack.top++) = *luaH_getint(t, i); | ||
157 | luaD_calln(2, 1); | ||
158 | if (ttype(L->stack.top-1) != LUA_T_NIL) | ||
159 | return; | ||
160 | L->stack.top--; | ||
161 | } | ||
162 | } | ||
163 | |||
164 | |||
116 | static void internaldostring (void) | 165 | static void internaldostring (void) |
117 | { | 166 | { |
118 | long l; | 167 | long l; |
@@ -281,29 +330,6 @@ static void luatag (void) | |||
281 | } | 330 | } |
282 | 331 | ||
283 | 332 | ||
284 | static int getsize (TObject *t) { | ||
285 | int max = 0; | ||
286 | int i; | ||
287 | Hash *h = avalue(t); | ||
288 | LUA_ASSERT(ttype(t) == LUA_T_ARRAY, "table expected"); | ||
289 | for (i = 0; i<nhash(h); i++) { | ||
290 | Node *n = h->node+i; | ||
291 | if (ttype(ref(n)) == LUA_T_NUMBER && ttype(val(n)) != LUA_T_NIL && | ||
292 | (int)nvalue(ref(n)) > max) | ||
293 | max = nvalue(ref(n)); | ||
294 | } | ||
295 | return max; | ||
296 | } | ||
297 | |||
298 | |||
299 | static int getnarg (lua_Object table) { | ||
300 | lua_Object temp; | ||
301 | /* temp = table.n */ | ||
302 | lua_pushobject(table); lua_pushstring("n"); temp = lua_rawgettable(); | ||
303 | return (lua_isnumber(temp) ? lua_getnumber(temp) : | ||
304 | getsize(luaA_Address(table))); | ||
305 | } | ||
306 | |||
307 | static void luaI_call (void) { | 333 | static void luaI_call (void) { |
308 | lua_Object f = luaL_nonnullarg(1); | 334 | lua_Object f = luaL_nonnullarg(1); |
309 | lua_Object arg = luaL_tablearg(2); | 335 | lua_Object arg = luaL_tablearg(2); |
@@ -440,6 +466,7 @@ static int sort_comp (TObject *f, TObject *a, TObject *b) { | |||
440 | ** quicksort algorithm from "Programming Pearls", pg. 112 | 466 | ** quicksort algorithm from "Programming Pearls", pg. 112 |
441 | */ | 467 | */ |
442 | static void auxsort (Hash *a, int l, int u, TObject *f) { | 468 | static void auxsort (Hash *a, int l, int u, TObject *f) { |
469 | init: | ||
443 | if (u <= l) return; /* 0 or 1 element */ | 470 | if (u <= l) return; /* 0 or 1 element */ |
444 | luaD_checkstack(4); /* for pivot, f, a, b (sort_comp) */ | 471 | luaD_checkstack(4); /* for pivot, f, a, b (sort_comp) */ |
445 | if (u-l == 1) { /* only two elements? */ | 472 | if (u-l == 1) { /* only two elements? */ |
@@ -461,8 +488,14 @@ static void auxsort (Hash *a, int l, int u, TObject *f) { | |||
461 | L->stack.top--; /* remove pivot from stack */ | 488 | L->stack.top--; /* remove pivot from stack */ |
462 | swap(a, l, m); | 489 | swap(a, l, m); |
463 | /* a[l..m-1] < a[m] <= a[m+1..u] */ | 490 | /* a[l..m-1] < a[m] <= a[m+1..u] */ |
464 | auxsort(a, l, m-1, f); | 491 | if (m-l < u-m) { /* check which "half" is bigger */ |
465 | auxsort(a, m+1, u, f); | 492 | auxsort(a, l, m-1, f); /* call recursively the smaller one */ |
493 | l = m+1; goto init; /* auxsort(a, m+1, u, f); */ | ||
494 | } | ||
495 | else { | ||
496 | auxsort(a, m+1, u, f); | ||
497 | u = m-1; goto init; /* auxsort(a, l, m-1, f); */ | ||
498 | } | ||
466 | } | 499 | } |
467 | } | 500 | } |
468 | 501 | ||
@@ -471,13 +504,8 @@ static void luaB_sort (void) { | |||
471 | int n = getnarg(t); | 504 | int n = getnarg(t); |
472 | Hash *a = avalue(luaA_Address(t)); | 505 | Hash *a = avalue(luaA_Address(t)); |
473 | lua_Object func = lua_getparam(2); | 506 | lua_Object func = lua_getparam(2); |
474 | TObject *f; | 507 | TObject *f = luaA_Address(func); |
475 | if (func == LUA_NOOBJECT) | 508 | luaL_arg_check(!f || lua_isfunction(func), 2, "function expected"); |
476 | f = NULL; | ||
477 | else { | ||
478 | luaL_arg_check(lua_isfunction(func), 2, "function expected"); | ||
479 | f = luaA_Address(func); | ||
480 | } | ||
481 | auxsort(a, 1, n, f); | 509 | auxsort(a, 1, n, f); |
482 | lua_pushobject(t); | 510 | lua_pushobject(t); |
483 | } | 511 | } |
@@ -583,7 +611,9 @@ static struct luaL_reg int_funcs[] = { | |||
583 | {"error", luaI_error}, | 611 | {"error", luaI_error}, |
584 | {"_ERRORMESSAGE", error_message}, | 612 | {"_ERRORMESSAGE", error_message}, |
585 | {"foreach", foreach}, | 613 | {"foreach", foreach}, |
614 | {"foreachi", foreachi}, | ||
586 | {"foreachvar", foreachvar}, | 615 | {"foreachvar", foreachvar}, |
616 | {"getn", getn}, | ||
587 | {"getglobal", getglobal}, | 617 | {"getglobal", getglobal}, |
588 | {"newtag", newtag}, | 618 | {"newtag", newtag}, |
589 | {"next", next}, | 619 | {"next", next}, |