diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2013-04-25 16:12:41 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2013-04-25 16:12:41 -0300 |
commit | e381c582de1b80a5f3df2c0d36fc25b415b48de0 (patch) | |
tree | 348d30377bfa6e89c1fb5bc1b8b7805bc4a82eb7 /lvm.c | |
parent | 9600c60df3e5a971ca642734470901775ef67ff9 (diff) | |
download | lua-e381c582de1b80a5f3df2c0d36fc25b415b48de0.tar.gz lua-e381c582de1b80a5f3df2c0d36fc25b415b48de0.tar.bz2 lua-e381c582de1b80a5f3df2c0d36fc25b415b48de0.zip |
integer handling for order comparisons, power, and modulo operations
Diffstat (limited to 'lvm.c')
-rw-r--r-- | lvm.c | 84 |
1 files changed, 79 insertions, 5 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lvm.c,v 2.159 2013/04/25 15:59:42 roberto Exp roberto $ | 2 | ** $Id: lvm.c,v 2.160 2013/04/25 16:07:52 roberto Exp roberto $ |
3 | ** Lua virtual machine | 3 | ** Lua virtual machine |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -150,7 +150,9 @@ static int l_strcmp (const TString *ls, const TString *rs) { | |||
150 | 150 | ||
151 | int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r) { | 151 | int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r) { |
152 | int res; | 152 | int res; |
153 | if (ttisnumber(l) && ttisnumber(r)) | 153 | if (ttisinteger(l) && ttisinteger(r)) |
154 | return (ivalue(l) < ivalue(r)); | ||
155 | else if (ttisnumber(l) && ttisnumber(r)) | ||
154 | return luai_numlt(L, nvalue(l), nvalue(r)); | 156 | return luai_numlt(L, nvalue(l), nvalue(r)); |
155 | else if (ttisstring(l) && ttisstring(r)) | 157 | else if (ttisstring(l) && ttisstring(r)) |
156 | return l_strcmp(rawtsvalue(l), rawtsvalue(r)) < 0; | 158 | return l_strcmp(rawtsvalue(l), rawtsvalue(r)) < 0; |
@@ -162,7 +164,9 @@ int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r) { | |||
162 | 164 | ||
163 | int luaV_lessequal (lua_State *L, const TValue *l, const TValue *r) { | 165 | int luaV_lessequal (lua_State *L, const TValue *l, const TValue *r) { |
164 | int res; | 166 | int res; |
165 | if (ttisnumber(l) && ttisnumber(r)) | 167 | if (ttisinteger(l) && ttisinteger(r)) |
168 | return (ivalue(l) <= ivalue(r)); | ||
169 | else if (ttisnumber(l) && ttisnumber(r)) | ||
166 | return luai_numle(L, nvalue(l), nvalue(r)); | 170 | return luai_numle(L, nvalue(l), nvalue(r)); |
167 | else if (ttisstring(l) && ttisstring(r)) | 171 | else if (ttisstring(l) && ttisstring(r)) |
168 | return l_strcmp(rawtsvalue(l), rawtsvalue(r)) <= 0; | 172 | return l_strcmp(rawtsvalue(l), rawtsvalue(r)) <= 0; |
@@ -283,6 +287,54 @@ void luaV_objlen (lua_State *L, StkId ra, const TValue *rb) { | |||
283 | } | 287 | } |
284 | 288 | ||
285 | 289 | ||
290 | lua_Integer luaV_div (lua_State *L, lua_Integer x, lua_Integer y) { | ||
291 | if (cast_unsigned(y) + 1 <= 1U) { /* special cases: -1 or 0 */ | ||
292 | if (y == 0) | ||
293 | luaG_runerror(L, "attempt to divide by zero"); | ||
294 | else /* -1 */ | ||
295 | return -x; /* avoid overflow with 0x80000... */ | ||
296 | } | ||
297 | else { | ||
298 | lua_Integer d = x / y; /* perform division */ | ||
299 | if ((x ^ y) >= 0 || x % y == 0) /* same signal or no rest? */ | ||
300 | return d; | ||
301 | else | ||
302 | return d - 1; /* correct 'div' for negative case */ | ||
303 | } | ||
304 | } | ||
305 | |||
306 | |||
307 | lua_Integer luaV_mod (lua_State *L, lua_Integer x, lua_Integer y) { | ||
308 | if (cast_unsigned(y) + 1 <= 1U) { /* special cases: -1 or 0 */ | ||
309 | if (y == 0) | ||
310 | luaG_runerror(L, "attempt to divide by zero (in '%%')"); | ||
311 | else /* -1 */ | ||
312 | return 0; /* avoid overflow with 0x80000... */ | ||
313 | } | ||
314 | else { | ||
315 | lua_Integer r = x % y; | ||
316 | if (r == 0 || (x ^ y) >= 0) | ||
317 | return r; | ||
318 | else | ||
319 | return r + y; /* correct 'mod' for negative case */ | ||
320 | } | ||
321 | } | ||
322 | |||
323 | |||
324 | lua_Integer luaV_pow (lua_Integer x, lua_Integer y) { | ||
325 | lua_Integer r = 1; | ||
326 | lua_assert(y >= 0); | ||
327 | if (y == 0) return r; | ||
328 | for (; y > 1; y >>= 1) { | ||
329 | if (y & 1) | ||
330 | r = cast_integer(cast_unsigned(r) * cast_unsigned(x)); | ||
331 | x = cast_integer(cast_unsigned(x) * cast_unsigned(x)); | ||
332 | } | ||
333 | r = cast_integer(cast_unsigned(r) * cast_unsigned(x)); | ||
334 | return r; | ||
335 | } | ||
336 | |||
337 | |||
286 | void luaV_arith (lua_State *L, StkId ra, const TValue *rb, | 338 | void luaV_arith (lua_State *L, StkId ra, const TValue *rb, |
287 | const TValue *rc, TMS op) { | 339 | const TValue *rc, TMS op) { |
288 | TValue tempb, tempc; | 340 | TValue tempb, tempc; |
@@ -589,10 +641,32 @@ void luaV_execute (lua_State *L) { | |||
589 | else { Protect(luaV_arith(L, ra, rb, rc, TM_DIV)); } | 641 | else { Protect(luaV_arith(L, ra, rb, rc, TM_DIV)); } |
590 | ) | 642 | ) |
591 | vmcase(OP_MOD, | 643 | vmcase(OP_MOD, |
592 | arith_op(luai_nummod, TM_MOD); | 644 | TValue *rb = RKB(i); |
645 | TValue *rc = RKC(i); | ||
646 | if (ttisinteger(rb) && ttisinteger(rc)) { | ||
647 | lua_Integer ib = ivalue(rb); lua_Integer ic = ivalue(rc); | ||
648 | setivalue(ra, luaV_mod(L, ib, ic)); | ||
649 | } | ||
650 | else if (ttisnumber(rb) && ttisnumber(rc)) { | ||
651 | lua_Number nb = nvalue(rb); lua_Number nc = nvalue(rc); | ||
652 | setnvalue(ra, luai_nummod(L, nb, nc)); | ||
653 | } | ||
654 | else { Protect(luaV_arith(L, ra, rb, rc, TM_MOD)); } | ||
593 | ) | 655 | ) |
594 | vmcase(OP_POW, | 656 | vmcase(OP_POW, |
595 | arith_op(luai_numpow, TM_POW); | 657 | TValue *rb = RKB(i); |
658 | TValue *rc = RKC(i); | ||
659 | lua_Integer ic; | ||
660 | if (ttisinteger(rb) && ttisinteger(rc) && | ||
661 | (ic = ivalue(rc)) >= 0) { | ||
662 | lua_Integer ib = ivalue(rb); | ||
663 | setivalue(ra, luaV_pow(ib, ic)); | ||
664 | } | ||
665 | else if (ttisnumber(rb) && ttisnumber(rc)) { | ||
666 | lua_Number nb = nvalue(rb); lua_Number nc = nvalue(rc); | ||
667 | setnvalue(ra, luai_numpow(L, nb, nc)); | ||
668 | } | ||
669 | else { Protect(luaV_arith(L, ra, rb, rc, TM_POW)); } | ||
596 | ) | 670 | ) |
597 | vmcase(OP_UNM, | 671 | vmcase(OP_UNM, |
598 | TValue *rb = RB(i); | 672 | TValue *rb = RB(i); |