aboutsummaryrefslogtreecommitdiff
path: root/lvm.c
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2013-04-25 16:12:41 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2013-04-25 16:12:41 -0300
commite381c582de1b80a5f3df2c0d36fc25b415b48de0 (patch)
tree348d30377bfa6e89c1fb5bc1b8b7805bc4a82eb7 /lvm.c
parent9600c60df3e5a971ca642734470901775ef67ff9 (diff)
downloadlua-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.c84
1 files changed, 79 insertions, 5 deletions
diff --git a/lvm.c b/lvm.c
index 96628872..212583f6 100644
--- a/lvm.c
+++ b/lvm.c
@@ -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
151int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r) { 151int 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
163int luaV_lessequal (lua_State *L, const TValue *l, const TValue *r) { 165int 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
290lua_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
307lua_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
324lua_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
286void luaV_arith (lua_State *L, StkId ra, const TValue *rb, 338void 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);