diff options
author | Lua Team <team@lua.org> | 2013-07-06 12:00:00 +0000 |
---|---|---|
committer | repogen <> | 2013-07-06 12:00:00 +0000 |
commit | 87cc247b6b22184fba47184c218a642ea7a49e96 (patch) | |
tree | 299ba8b72b95aa32336b5c810b7133f8efc4fb29 /src/ltable.c | |
parent | dc27609467d2699ac9252e89d632432ac5f798f2 (diff) | |
download | lua-github-5.3.0-work1.tar.gz |
Lua 5.3.0-work15.3.0-work1
Diffstat (limited to 'src/ltable.c')
-rw-r--r-- | src/ltable.c | 83 |
1 files changed, 50 insertions, 33 deletions
diff --git a/src/ltable.c b/src/ltable.c index 420391fc..4b39a8de 100644 --- a/src/ltable.c +++ b/src/ltable.c @@ -1,5 +1,5 @@ /* -** $Id: ltable.c,v 2.72 2012/09/11 19:37:16 roberto Exp $ +** $Id: ltable.c,v 2.78 2013/06/20 15:02:49 roberto Exp $ ** Lua tables (hash) ** See Copyright Notice in lua.h */ @@ -18,6 +18,8 @@ ** Hence even when the load factor reaches 100%, performance remains good. */ +#include <float.h> +#include <math.h> #include <string.h> #define ltable_c @@ -52,6 +54,7 @@ #define hashstr(t,str) hashpow2(t, (str)->tsv.hash) #define hashboolean(t,p) hashpow2(t, p) +#define hashint(t,i) hashpow2(t, i) /* @@ -64,6 +67,12 @@ #define hashpointer(t,p) hashmod(t, IntPoint(p)) +/* checks whether a float has a value representable as a lua_Integer + (and does the conversion if so) */ +#define numisinteger(x,i) \ + (((x) == l_floor(x)) && luaV_numtointeger(x, i)) + + #define dummynode (&dummynode_) #define isdummy(n) ((n) == dummynode) @@ -75,11 +84,12 @@ static const Node dummynode_ = { /* -** hash for lua_Numbers +** hash for floating-point numbers */ -static Node *hashnum (const Table *t, lua_Number n) { +static Node *hashfloat (const Table *t, lua_Number n) { int i; - luai_hashnum(i, n); + n = l_mathop(frexp)(n, &i) * cast_num(INT_MAX - DBL_MAX_EXP); + i += cast_int(n); if (i < 0) { if (cast(unsigned int, i) == 0u - i) /* use unsigned to avoid overflows */ i = 0; /* handle INT_MIN */ @@ -96,8 +106,12 @@ static Node *hashnum (const Table *t, lua_Number n) { */ static Node *mainposition (const Table *t, const TValue *key) { switch (ttype(key)) { - case LUA_TNUMBER: - return hashnum(t, nvalue(key)); + case LUA_TNUMINT: + return hashint(t, ivalue(key)); + case LUA_TNUMFLT: + return hashfloat(t, fltvalue(key)); + case LUA_TSHRSTR: + return hashstr(t, rawtsvalue(key)); case LUA_TLNGSTR: { TString *s = rawtsvalue(key); if (s->tsv.extra == 0) { /* no hash? */ @@ -106,8 +120,6 @@ static Node *mainposition (const Table *t, const TValue *key) { } return hashstr(t, rawtsvalue(key)); } - case LUA_TSHRSTR: - return hashstr(t, rawtsvalue(key)); case LUA_TBOOLEAN: return hashboolean(t, bvalue(key)); case LUA_TLIGHTUSERDATA: @@ -125,12 +137,10 @@ static Node *mainposition (const Table *t, const TValue *key) { ** the array part of the table, -1 otherwise. */ static int arrayindex (const TValue *key) { - if (ttisnumber(key)) { - lua_Number n = nvalue(key); - int k; - lua_number2int(k, n); - if (luai_numeq(cast_num(k), n)) - return k; + if (ttisinteger(key)) { + lua_Integer k = ivalue(key); + if (0 < k && k <= MAXASIZE) /* is `key' an appropriate array index? */ + return cast_int(k); } return -1; /* `key' did not match some condition */ } @@ -170,7 +180,7 @@ int luaH_next (lua_State *L, Table *t, StkId key) { int i = findindex(L, t, key); /* find original element */ for (i++; i < t->sizearray; i++) { /* try first array part */ if (!ttisnil(&t->array[i])) { /* a non-nil value? */ - setnvalue(key, cast_num(i+1)); + setivalue(key, i + 1); setobj2s(L, key+1, &t->array[i]); return 1; } @@ -217,7 +227,7 @@ static int computesizes (int nums[], int *narray) { static int countint (const TValue *key, int *nums) { int k = arrayindex(key); - if (0 < k && k <= MAXASIZE) { /* is `key' an appropriate array index? */ + if (k > 0) { /* is `key' an appropriate array index? */ nums[luaO_ceillog2(k)]++; /* count as such */ return 1; } @@ -404,9 +414,18 @@ static Node *getfreepos (Table *t) { */ TValue *luaH_newkey (lua_State *L, Table *t, const TValue *key) { Node *mp; + TValue aux; if (ttisnil(key)) luaG_runerror(L, "table index is nil"); - else if (ttisnumber(key) && luai_numisnan(L, nvalue(key))) - luaG_runerror(L, "table index is NaN"); + else if (ttisfloat(key)) { + lua_Number n = fltvalue(key); + lua_Integer k; + if (luai_numisnan(L, n)) + luaG_runerror(L, "table index is NaN"); + if (numisinteger(n, &k)) { /* index is int? */ + setivalue(&aux, k); + key = &aux; /* insert it as an integer */ + } + } mp = mainposition(t, key); if (!ttisnil(gval(mp)) || isdummy(mp)) { /* main position is taken? */ Node *othern; @@ -443,15 +462,14 @@ TValue *luaH_newkey (lua_State *L, Table *t, const TValue *key) { /* ** search function for integers */ -const TValue *luaH_getint (Table *t, int key) { +const TValue *luaH_getint (Table *t, lua_Integer key) { /* (1 <= key && key <= t->sizearray) */ - if (cast(unsigned int, key-1) < cast(unsigned int, t->sizearray)) - return &t->array[key-1]; + if (cast_unsigned(key - 1) < cast_unsigned(t->sizearray)) + return &t->array[key - 1]; else { - lua_Number nk = cast_num(key); - Node *n = hashnum(t, nk); + Node *n = hashint(t, key); do { /* check whether `key' is somewhere in the chain */ - if (ttisnumber(gkey(n)) && luai_numeq(nvalue(gkey(n)), nk)) + if (ttisinteger(gkey(n)) && ivalue(gkey(n)) == key) return gval(n); /* that's it */ else n = gnext(n); } while (n); @@ -481,12 +499,11 @@ const TValue *luaH_getstr (Table *t, TString *key) { const TValue *luaH_get (Table *t, const TValue *key) { switch (ttype(key)) { case LUA_TSHRSTR: return luaH_getstr(t, rawtsvalue(key)); + case LUA_TNUMINT: return luaH_getint(t, ivalue(key)); case LUA_TNIL: return luaO_nilobject; - case LUA_TNUMBER: { - int k; - lua_Number n = nvalue(key); - lua_number2int(k, n); - if (luai_numeq(cast_num(k), n)) /* index is int? */ + case LUA_TNUMFLT: { + lua_Integer k; + if (numisinteger(fltvalue(key), &k)) /* index is int? */ return luaH_getint(t, k); /* use specialized version */ /* else go through */ } @@ -515,14 +532,14 @@ TValue *luaH_set (lua_State *L, Table *t, const TValue *key) { } -void luaH_setint (lua_State *L, Table *t, int key, TValue *value) { +void luaH_setint (lua_State *L, Table *t, lua_Integer key, TValue *value) { const TValue *p = luaH_getint(t, key); TValue *cell; if (p != luaO_nilobject) cell = cast(TValue *, p); else { TValue k; - setnvalue(&k, cast_num(key)); + setivalue(&k, key); cell = luaH_newkey(L, t, &k); } setobj2t(L, cell, value); @@ -535,13 +552,13 @@ static int unbound_search (Table *t, unsigned int j) { /* find `i' and `j' such that i is present and j is not */ while (!ttisnil(luaH_getint(t, j))) { i = j; - j *= 2; - if (j > cast(unsigned int, MAX_INT)) { /* overflow? */ + if (j > cast(unsigned int, MAX_INT)/2) { /* overflow? */ /* table was built with bad purposes: resort to linear search */ i = 1; while (!ttisnil(luaH_getint(t, i))) i++; return i - 1; } + j *= 2; } /* now do a binary search between them */ while (j - i > 1) { |