aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2014-11-21 10:15:00 -0200
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2014-11-21 10:15:00 -0200
commit049cf14cf9f82a07387df4d0c9bdba5ba2fef22f (patch)
tree8f8ab9e865710858c816bef0f45db94a26a48a2b
parent5d628519d37a70b56be610cc4c256b3accc2f72c (diff)
downloadlua-049cf14cf9f82a07387df4d0c9bdba5ba2fef22f.tar.gz
lua-049cf14cf9f82a07387df4d0c9bdba5ba2fef22f.tar.bz2
lua-049cf14cf9f82a07387df4d0c9bdba5ba2fef22f.zip
'x//y' extended to floats + more comments about module and floor
division operations
-rw-r--r--luaconf.h18
-rw-r--r--lvm.c49
2 files changed, 43 insertions, 24 deletions
diff --git a/luaconf.h b/luaconf.h
index 78dde74a..5b61e4a2 100644
--- a/luaconf.h
+++ b/luaconf.h
@@ -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 */
diff --git a/lvm.c b/lvm.c
index 28a3aab8..5e7764bd 100644
--- a/lvm.c
+++ b/lvm.c
@@ -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*/
434lua_Integer luaV_div (lua_State *L, lua_Integer m, lua_Integer n) { 436lua_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*/
454lua_Integer luaV_mod (lua_State *L, lua_Integer m, lua_Integer n) { 456lua_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);