diff options
| -rw-r--r-- | luaconf.h | 18 | ||||
| -rw-r--r-- | lvm.c | 49 |
2 files changed, 43 insertions, 24 deletions
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: luaconf.h,v 1.227 2014/11/02 19:35:39 roberto Exp roberto $ | 2 | ** $Id: luaconf.h,v 1.228 2014/11/19 15:00:42 roberto Exp roberto $ |
| 3 | ** Configuration file for Lua | 3 | ** Configuration file for Lua |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -468,9 +468,23 @@ | |||
| 468 | /* the following operations need the math library */ | 468 | /* the following operations need the math library */ |
| 469 | #if defined(lobject_c) || defined(lvm_c) | 469 | #if defined(lobject_c) || defined(lvm_c) |
| 470 | #include <math.h> | 470 | #include <math.h> |
| 471 | |||
| 472 | /* floor division (defined as 'floor(a/b)') */ | ||
| 473 | #define luai_numidiv(L,a,b) ((void)L, l_mathop(floor)((a)/(b))) | ||
| 474 | |||
| 475 | /* | ||
| 476 | ** module: defined as 'a - floor(a/b)*b'; the previous definition gives | ||
| 477 | ** NaN when 'b' is huge, but the result should be 'a'. 'fmod' gives the | ||
| 478 | ** result of 'a - trunc(a/b)*b', and therefore must be corrected when | ||
| 479 | ** 'trunc(a/b) ~= floor(a/b)'. That happens when the division has a | ||
| 480 | ** non-integer negative result, which is equivalent to the test below | ||
| 481 | */ | ||
| 471 | #define luai_nummod(L,a,b,m) \ | 482 | #define luai_nummod(L,a,b,m) \ |
| 472 | { (m) = l_mathop(fmod)(a,b); if ((m) != 0 && (a)*(b) < 0) (m) += (b); } | 483 | { (m) = l_mathop(fmod)(a,b); if ((m)*(b) < 0) (m) += (b); } |
| 484 | |||
| 485 | /* exponentiation */ | ||
| 473 | #define luai_numpow(L,a,b) ((void)L, l_mathop(pow)(a,b)) | 486 | #define luai_numpow(L,a,b) ((void)L, l_mathop(pow)(a,b)) |
| 487 | |||
| 474 | #endif | 488 | #endif |
| 475 | 489 | ||
| 476 | /* these are quite standard operations */ | 490 | /* these are quite standard operations */ |
| @@ -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); |
