mirror of
https://github.com/lua/lua
synced 2024-11-22 12:51:30 +03:00
'x//y' extended to floats + more comments about module and floor
division operations
This commit is contained in:
parent
5d628519d3
commit
049cf14cf9
18
luaconf.h
18
luaconf.h
@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: luaconf.h,v 1.227 2014/11/02 19:35:39 roberto Exp roberto $
|
||||
** $Id: luaconf.h,v 1.228 2014/11/19 15:00:42 roberto Exp roberto $
|
||||
** Configuration file for Lua
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
@ -468,9 +468,23 @@
|
||||
/* the following operations need the math library */
|
||||
#if defined(lobject_c) || defined(lvm_c)
|
||||
#include <math.h>
|
||||
|
||||
/* floor division (defined as 'floor(a/b)') */
|
||||
#define luai_numidiv(L,a,b) ((void)L, l_mathop(floor)((a)/(b)))
|
||||
|
||||
/*
|
||||
** module: defined as 'a - floor(a/b)*b'; the previous definition gives
|
||||
** NaN when 'b' is huge, but the result should be 'a'. 'fmod' gives the
|
||||
** result of 'a - trunc(a/b)*b', and therefore must be corrected when
|
||||
** 'trunc(a/b) ~= floor(a/b)'. That happens when the division has a
|
||||
** non-integer negative result, which is equivalent to the test below
|
||||
*/
|
||||
#define luai_nummod(L,a,b,m) \
|
||||
{ (m) = l_mathop(fmod)(a,b); if ((m) != 0 && (a)*(b) < 0) (m) += (b); }
|
||||
{ (m) = l_mathop(fmod)(a,b); if ((m)*(b) < 0) (m) += (b); }
|
||||
|
||||
/* exponentiation */
|
||||
#define luai_numpow(L,a,b) ((void)L, l_mathop(pow)(a,b))
|
||||
|
||||
#endif
|
||||
|
||||
/* these are quite standard operations */
|
||||
|
49
lvm.c
49
lvm.c
@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: lvm.c,v 2.228 2014/11/03 20:07:47 roberto Exp roberto $
|
||||
** $Id: lvm.c,v 2.229 2014/11/19 15:05:15 roberto Exp roberto $
|
||||
** Lua virtual machine
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
@ -428,8 +428,10 @@ void luaV_objlen (lua_State *L, StkId ra, const TValue *rb) {
|
||||
|
||||
|
||||
/*
|
||||
** Integer division; return 'm // n'. (Assume that C division with
|
||||
** negative operands follows C99 behavior.)
|
||||
** Integer division; return 'm // n', that is, floor(m/n).
|
||||
** C division truncates its result (rounds towards zero).
|
||||
** 'floor(q) == trunc(q)' when 'q >= 0' or when 'q' is integer,
|
||||
** otherwise 'floor(q) == trunc(q) - 1'.
|
||||
*/
|
||||
lua_Integer luaV_div (lua_State *L, lua_Integer m, lua_Integer n) {
|
||||
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) {
|
||||
return intop(-, 0, m); /* n==-1; avoid overflow with 0x80000...//-1 */
|
||||
}
|
||||
else {
|
||||
lua_Integer d = m / n; /* perform division */
|
||||
if ((m ^ n) >= 0 || m % n == 0) /* same signal or no rest? */
|
||||
return d;
|
||||
else
|
||||
return d - 1; /* correct 'div' for negative case */
|
||||
lua_Integer q = m / n; /* perform C division */
|
||||
if ((m ^ n) < 0 && m % n != 0) /* 'm/n' would be negative non-integer? */
|
||||
q -= 1; /* correct result for different rounding */
|
||||
return q;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Integer modulus; return 'm % n'. (Assume that C '%' with
|
||||
** negative operands follows C99 behavior.)
|
||||
** negative operands follows C99 behavior. See previous comment
|
||||
** about luaV_div.)
|
||||
*/
|
||||
lua_Integer luaV_mod (lua_State *L, lua_Integer m, lua_Integer n) {
|
||||
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) {
|
||||
}
|
||||
else {
|
||||
lua_Integer r = m % n;
|
||||
if (r == 0 || (m ^ n) >= 0) /* no rest or same signal? */
|
||||
return r;
|
||||
else
|
||||
return r + n; /* correct 'mod' for negative case */
|
||||
if (r != 0 && (m ^ n) < 0) /* 'm/n' would be non-integer negative? */
|
||||
r += n; /* correct result for different rounding */
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
@ -778,15 +779,6 @@ void luaV_execute (lua_State *L) {
|
||||
}
|
||||
else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_DIV)); }
|
||||
)
|
||||
vmcase(OP_IDIV, /* integer division */
|
||||
TValue *rb = RKB(i);
|
||||
TValue *rc = RKC(i);
|
||||
lua_Integer ib; lua_Integer ic;
|
||||
if (tointeger(rb, &ib) && tointeger(rc, &ic)) {
|
||||
setivalue(ra, luaV_div(L, ib, ic));
|
||||
}
|
||||
else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_IDIV)); }
|
||||
)
|
||||
vmcase(OP_BAND,
|
||||
TValue *rb = RKB(i);
|
||||
TValue *rc = RKC(i);
|
||||
@ -847,6 +839,19 @@ void luaV_execute (lua_State *L) {
|
||||
}
|
||||
else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_MOD)); }
|
||||
)
|
||||
vmcase(OP_IDIV, /* floor division */
|
||||
TValue *rb = RKB(i);
|
||||
TValue *rc = RKC(i);
|
||||
lua_Number nb; lua_Number nc;
|
||||
if (ttisinteger(rb) && ttisinteger(rc)) {
|
||||
lua_Integer ib = ivalue(rb); lua_Integer ic = ivalue(rc);
|
||||
setivalue(ra, luaV_div(L, ib, ic));
|
||||
}
|
||||
else if (tonumber(rb, &nb) && tonumber(rc, &nc)) {
|
||||
setfltvalue(ra, luai_numidiv(L, nb, nc));
|
||||
}
|
||||
else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_IDIV)); }
|
||||
)
|
||||
vmcase(OP_POW,
|
||||
TValue *rb = RKB(i);
|
||||
TValue *rc = RKC(i);
|
||||
|
Loading…
Reference in New Issue
Block a user