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 | |
| parent | 9600c60df3e5a971ca642734470901775ef67ff9 (diff) | |
| download | lua-e381c582de1b80a5f3df2c0d36fc25b415b48de0.tar.gz lua-e381c582de1b80a5f3df2c0d36fc25b415b48de0.tar.bz2 lua-e381c582de1b80a5f3df2c0d36fc25b415b48de0.zip | |
integer handling for order comparisons, power, and modulo operations
| -rw-r--r-- | lvm.c | 84 | ||||
| -rw-r--r-- | lvm.h | 5 |
2 files changed, 83 insertions, 6 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); |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lvm.h,v 2.17 2011/05/31 18:27:56 roberto Exp $ | 2 | ** $Id: lvm.h,v 2.19 2013/04/15 15:44:46 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 | */ |
| @@ -33,6 +33,9 @@ LUAI_FUNC void luaV_settable (lua_State *L, const TValue *t, TValue *key, | |||
| 33 | LUAI_FUNC void luaV_finishOp (lua_State *L); | 33 | LUAI_FUNC void luaV_finishOp (lua_State *L); |
| 34 | LUAI_FUNC void luaV_execute (lua_State *L); | 34 | LUAI_FUNC void luaV_execute (lua_State *L); |
| 35 | LUAI_FUNC void luaV_concat (lua_State *L, int total); | 35 | LUAI_FUNC void luaV_concat (lua_State *L, int total); |
| 36 | LUAI_FUNC lua_Integer luaV_div (lua_State *L, lua_Integer x, lua_Integer y); | ||
| 37 | LUAI_FUNC lua_Integer luaV_mod (lua_State *L, lua_Integer x, lua_Integer y); | ||
| 38 | LUAI_FUNC lua_Integer luaV_pow (lua_Integer x, lua_Integer y); | ||
| 36 | LUAI_FUNC void luaV_arith (lua_State *L, StkId ra, const TValue *rb, | 39 | LUAI_FUNC void luaV_arith (lua_State *L, StkId ra, const TValue *rb, |
| 37 | const TValue *rc, TMS op); | 40 | const TValue *rc, TMS op); |
| 38 | LUAI_FUNC void luaV_objlen (lua_State *L, StkId ra, const TValue *rb); | 41 | LUAI_FUNC void luaV_objlen (lua_State *L, StkId ra, const TValue *rb); |
