Corrections in the implementation of '%' for floats. · lua/lua@5382a22 · GitHub
Skip to content

Commit 5382a22

Browse files
committed
Corrections in the implementation of '%' for floats.
The multiplication (m*b) used to test whether 'm' is non-zero and 'm' and 'b' have different signs can underflow for very small numbers, giving a wrong result. The use of explicit comparisons solves this problem. This commit also adds several new tests for '%' (both for floats and for integers) to exercise more corner cases, such as very large and very small values.
1 parent 8c8a91f commit 5382a22

5 files changed

Lines changed: 87 additions & 18 deletions

File tree

‎llimits.h‎

Lines changed: 8 additions & 6 deletions

‎lobject.c‎

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -106,11 +106,7 @@ static lua_Number numarith (lua_State *L, int op, lua_Number v1,
106106
case LUA_OPPOW: return luai_numpow(L, v1, v2);
107107
case LUA_OPIDIV: return luai_numidiv(L, v1, v2);
108108
case LUA_OPUNM: return luai_numunm(L, v1);
109-
case LUA_OPMOD: {
110-
lua_Number m;
111-
luai_nummod(L, v1, v2, m);
112-
return m;
113-
}
109+
case LUA_OPMOD: return luaV_modf(L, v1, v2);
114110
default: lua_assert(0); return 0;
115111
}
116112
}

‎lvm.c‎

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -655,6 +655,16 @@ lua_Integer luaV_mod (lua_State *L, lua_Integer m, lua_Integer n) {
655655
}
656656

657657

658+
/*
659+
** Float modulus
660+
*/
661+
lua_Number luaV_modf (lua_State *L, lua_Number m, lua_Number n) {
662+
lua_Number r;
663+
luai_nummod(L, m, n, r);
664+
return r;
665+
}
666+
667+
658668
/* number of bits in an integer */
659669
#define NBITS cast_int(sizeof(lua_Integer) * CHAR_BIT)
660670

@@ -1142,10 +1152,8 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
11421152
setivalue(s2v(ra), luaV_mod(L, ivalue(rb), ic));
11431153
}
11441154
else if (tonumberns(rb, nb)) {
1145-
lua_Number m;
11461155
lua_Number nc = cast_num(ic);
1147-
luai_nummod(L, nb, nc, m);
1148-
setfltvalue(s2v(ra), m);
1156+
setfltvalue(s2v(ra), luaV_modf(L, nb, nc));
11491157
}
11501158
else
11511159
Protect(luaT_trybiniTM(L, rb, ic, 0, ra, TM_MOD));
@@ -1370,9 +1378,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
13701378
setivalue(s2v(ra), luaV_mod(L, ib, ic));
13711379
}
13721380
else if (tonumberns(rb, nb) && tonumberns(rc, nc)) {
1373-
lua_Number m;
1374-
luai_nummod(L, nb, nc, m);
1375-
setfltvalue(s2v(ra), m);
1381+
setfltvalue(s2v(ra), luaV_modf(L, nb, nc));
13761382
}
13771383
else
13781384
Protect(luaT_trybinTM(L, rb, rc, ra, TM_MOD));

‎lvm.h‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@ LUAI_FUNC void luaV_execute (lua_State *L, CallInfo *ci);
116116
LUAI_FUNC void luaV_concat (lua_State *L, int total);
117117
LUAI_FUNC lua_Integer luaV_div (lua_State *L, lua_Integer x, lua_Integer y);
118118
LUAI_FUNC lua_Integer luaV_mod (lua_State *L, lua_Integer x, lua_Integer y);
119+
LUAI_FUNC lua_Number luaV_modf (lua_State *L, lua_Number x, lua_Number y);
119120
LUAI_FUNC lua_Integer luaV_shiftl (lua_Integer x, lua_Integer y);
120121
LUAI_FUNC void luaV_objlen (lua_State *L, StkId ra, const TValue *rb);
121122

‎testes/math.lua‎

Lines changed: 65 additions & 1 deletion

0 commit comments

Comments
 (0)