diff options
| author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2014-11-21 10:15:00 -0200 |
|---|---|---|
| committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2014-11-21 10:15:00 -0200 |
| commit | 049cf14cf9f82a07387df4d0c9bdba5ba2fef22f (patch) | |
| tree | 8f8ab9e865710858c816bef0f45db94a26a48a2b /lvm.c | |
| parent | 5d628519d37a70b56be610cc4c256b3accc2f72c (diff) | |
| download | lua-049cf14cf9f82a07387df4d0c9bdba5ba2fef22f.tar.gz lua-049cf14cf9f82a07387df4d0c9bdba5ba2fef22f.tar.bz2 lua-049cf14cf9f82a07387df4d0c9bdba5ba2fef22f.zip | |
'x//y' extended to floats + more comments about module and floor
division operations
Diffstat (limited to 'lvm.c')
| -rw-r--r-- | lvm.c | 49 |
1 files changed, 27 insertions, 22 deletions
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lvm.c,v 2.228 2014/11/03 20:07:47 roberto Exp roberto $ | 2 | ** $Id: lvm.c,v 2.229 2014/11/19 15:05:15 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 | */ |
| @@ -428,8 +428,10 @@ void luaV_objlen (lua_State *L, StkId ra, const TValue *rb) { | |||
| 428 | 428 | ||
| 429 | 429 | ||
| 430 | /* | 430 | /* |
| 431 | ** Integer division; return 'm // n'. (Assume that C division with | 431 | ** Integer division; return 'm // n', that is, floor(m/n). |
| 432 | ** negative operands follows C99 behavior.) | 432 | ** C division truncates its result (rounds towards zero). |
| 433 | ** 'floor(q) == trunc(q)' when 'q >= 0' or when 'q' is integer, | ||
| 434 | ** otherwise 'floor(q) == trunc(q) - 1'. | ||
| 433 | */ | 435 | */ |
| 434 | lua_Integer luaV_div (lua_State *L, lua_Integer m, lua_Integer n) { | 436 | lua_Integer luaV_div (lua_State *L, lua_Integer m, lua_Integer n) { |
| 435 | if (l_castS2U(n) + 1u <= 1u) { /* special cases: -1 or 0 */ | 437 | if (l_castS2U(n) + 1u <= 1u) { /* special cases: -1 or 0 */ |
| @@ -438,18 +440,18 @@ lua_Integer luaV_div (lua_State *L, lua_Integer m, lua_Integer n) { | |||
| 438 | return intop(-, 0, m); /* n==-1; avoid overflow with 0x80000...//-1 */ | 440 | return intop(-, 0, m); /* n==-1; avoid overflow with 0x80000...//-1 */ |
| 439 | } | 441 | } |
| 440 | else { | 442 | else { |
| 441 | lua_Integer d = m / n; /* perform division */ | 443 | lua_Integer q = m / n; /* perform C division */ |
| 442 | if ((m ^ n) >= 0 || m % n == 0) /* same signal or no rest? */ | 444 | if ((m ^ n) < 0 && m % n != 0) /* 'm/n' would be negative non-integer? */ |
| 443 | return d; | 445 | q -= 1; /* correct result for different rounding */ |
| 444 | else | 446 | return q; |
| 445 | return d - 1; /* correct 'div' for negative case */ | ||
| 446 | } | 447 | } |
| 447 | } | 448 | } |
| 448 | 449 | ||
| 449 | 450 | ||
| 450 | /* | 451 | /* |
| 451 | ** Integer modulus; return 'm % n'. (Assume that C '%' with | 452 | ** Integer modulus; return 'm % n'. (Assume that C '%' with |
| 452 | ** negative operands follows C99 behavior.) | 453 | ** negative operands follows C99 behavior. See previous comment |
| 454 | ** about luaV_div.) | ||
| 453 | */ | 455 | */ |
| 454 | lua_Integer luaV_mod (lua_State *L, lua_Integer m, lua_Integer n) { | 456 | lua_Integer luaV_mod (lua_State *L, lua_Integer m, lua_Integer n) { |
| 455 | if (l_castS2U(n) + 1u <= 1u) { /* special cases: -1 or 0 */ | 457 | if (l_castS2U(n) + 1u <= 1u) { /* special cases: -1 or 0 */ |
| @@ -459,10 +461,9 @@ lua_Integer luaV_mod (lua_State *L, lua_Integer m, lua_Integer n) { | |||
| 459 | } | 461 | } |
| 460 | else { | 462 | else { |
| 461 | lua_Integer r = m % n; | 463 | lua_Integer r = m % n; |
| 462 | if (r == 0 || (m ^ n) >= 0) /* no rest or same signal? */ | 464 | if (r != 0 && (m ^ n) < 0) /* 'm/n' would be non-integer negative? */ |
| 463 | return r; | 465 | r += n; /* correct result for different rounding */ |
| 464 | else | 466 | return r; |
| 465 | return r + n; /* correct 'mod' for negative case */ | ||
| 466 | } | 467 | } |
| 467 | } | 468 | } |
| 468 | 469 | ||
| @@ -778,15 +779,6 @@ void luaV_execute (lua_State *L) { | |||
| 778 | } | 779 | } |
| 779 | else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_DIV)); } | 780 | else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_DIV)); } |
| 780 | ) | 781 | ) |
| 781 | vmcase(OP_IDIV, /* integer division */ | ||
| 782 | TValue *rb = RKB(i); | ||
| 783 | TValue *rc = RKC(i); | ||
| 784 | lua_Integer ib; lua_Integer ic; | ||
| 785 | if (tointeger(rb, &ib) && tointeger(rc, &ic)) { | ||
| 786 | setivalue(ra, luaV_div(L, ib, ic)); | ||
| 787 | } | ||
| 788 | else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_IDIV)); } | ||
| 789 | ) | ||
| 790 | vmcase(OP_BAND, | 782 | vmcase(OP_BAND, |
| 791 | TValue *rb = RKB(i); | 783 | TValue *rb = RKB(i); |
| 792 | TValue *rc = RKC(i); | 784 | TValue *rc = RKC(i); |
| @@ -847,6 +839,19 @@ void luaV_execute (lua_State *L) { | |||
| 847 | } | 839 | } |
| 848 | else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_MOD)); } | 840 | else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_MOD)); } |
| 849 | ) | 841 | ) |
| 842 | vmcase(OP_IDIV, /* floor division */ | ||
| 843 | TValue *rb = RKB(i); | ||
| 844 | TValue *rc = RKC(i); | ||
| 845 | lua_Number nb; lua_Number nc; | ||
| 846 | if (ttisinteger(rb) && ttisinteger(rc)) { | ||
| 847 | lua_Integer ib = ivalue(rb); lua_Integer ic = ivalue(rc); | ||
| 848 | setivalue(ra, luaV_div(L, ib, ic)); | ||
| 849 | } | ||
| 850 | else if (tonumber(rb, &nb) && tonumber(rc, &nc)) { | ||
| 851 | setfltvalue(ra, luai_numidiv(L, nb, nc)); | ||
| 852 | } | ||
| 853 | else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_IDIV)); } | ||
| 854 | ) | ||
| 850 | vmcase(OP_POW, | 855 | vmcase(OP_POW, |
| 851 | TValue *rb = RKB(i); | 856 | TValue *rb = RKB(i); |
| 852 | TValue *rc = RKC(i); | 857 | TValue *rc = RKC(i); |
