fix(lua): compare float with int strictly in equality (#7611)
Co-authored-by: Peter Feerick <peter.feerick@gmail.com> Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Peter Feerick
Claude Sonnet 5
parent
db18294f78
commit
34afae5a26
@@ -198,6 +198,46 @@ TEST(Lua, Switches)
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST(Lua, testFloatIntegerEquality)
|
||||
{
|
||||
// 0.5 is not an integer, so it must not equal 0 (regression #7587)
|
||||
// both directions asserted explicitly so the intent is obvious at a glance
|
||||
luaExecStr("if 0.5 == 0 then error('0.5 == 0') end");
|
||||
luaExecStr("if not (0.5 ~= 0) then error('0.5 ~= 0') end");
|
||||
luaExecStr("if 0.50 == 0 then error('0.50 == 0') end");
|
||||
luaExecStr("if not (0.50 ~= 0) then error('0.50 ~= 0') end");
|
||||
luaExecStr("if 0.50 == 0.0 then error('0.50 == 0.0') end");
|
||||
// ... even when the value comes from a variable, as in the reported issue
|
||||
luaExecStr("local v = 0.50; if v == 0 then error('v == 0') end");
|
||||
luaExecStr("local v = 0.50; if not (v ~= 0) then error('v ~= 0') end");
|
||||
// negative non-integral floats must not equal integers either
|
||||
luaExecStr("if -0.5 == 0 then error('-0.5 == 0') end");
|
||||
luaExecStr("if not (-0.5 ~= 0) then error('-0.5 ~= 0') end");
|
||||
luaExecStr("if not (-0.5 < 0) then error('-0.5 < 0') end");
|
||||
luaExecStr("if -0.5 > 0 then error('-0.5 > 0') end");
|
||||
// integral floats still compare equal to their integer counterpart
|
||||
luaExecStr("if 1.0 ~= 1 then error('1.0 ~= 1') end");
|
||||
luaExecStr("if 0.0 ~= 0 then error('0.0 ~= 0') end");
|
||||
luaExecStr("if -1.0 ~= -1 then error('-1.0 ~= -1') end");
|
||||
// order comparisons on the same values must remain consistent
|
||||
luaExecStr("if not (0.5 >= 0) then error('0.5 >= 0') end");
|
||||
luaExecStr("if 0.5 <= 0 then error('0.5 <= 0') end");
|
||||
luaExecStr("if not (0.5 > 0) then error('0.5 > 0') end");
|
||||
luaExecStr("if 0.5 < 0 then error('0.5 < 0') end");
|
||||
luaExecStr("if not (0.50 >= 0) then error('0.50 >= 0') end");
|
||||
luaExecStr("if 0.50 <= 0 then error('0.50 <= 0') end");
|
||||
luaExecStr("if not (1.0 >= 1) then error('1.0 >= 1') end");
|
||||
luaExecStr("if not (1.0 <= 1) then error('1.0 <= 1') end");
|
||||
luaExecStr("if not (0.0 >= 0) then error('0.0 >= 0') end");
|
||||
luaExecStr("if not (0.0 <= 0) then error('0.0 <= 0') end");
|
||||
// mixed arithmetic must still yield floats; the fix only affects equality
|
||||
luaExecStr("if math.type(0.5 + 0) ~= 'float' then error('0.5 + 0') end");
|
||||
luaExecStr("if math.type(1.0 + 1) ~= 'float' then error('1.0 + 1') end");
|
||||
luaExecStr("if math.type(1 / 2) ~= 'float' then error('1 / 2') end");
|
||||
luaExecStr("if math.type(7.5 % 2) ~= 'float' then error('7.5 % 2') end");
|
||||
luaExecStr("if math.type(0.5 * 2) ~= 'float' then error('0.5 * 2') end");
|
||||
}
|
||||
|
||||
TEST(Lua, testLegacyNames)
|
||||
{
|
||||
MODEL_RESET();
|
||||
|
||||
Vendored
+1
-1
@@ -401,7 +401,7 @@ int luaV_equalobj (lua_State *L, const TValue *t1, const TValue *t2) {
|
||||
return 0; /* only numbers can be equal with different variants */
|
||||
else { /* two numbers with different variants */
|
||||
lua_Integer i1, i2; /* compare them as integers */
|
||||
return (tointeger(t1, &i1) && tointeger(t2, &i2) && i1 == i2);
|
||||
return (tointegerexact(t1, &i1) && tointegerexact(t2, &i2) && i1 == i2);
|
||||
}
|
||||
}
|
||||
/* values have same type and same variant */
|
||||
|
||||
Vendored
+9
@@ -43,6 +43,15 @@
|
||||
#define tointeger(o,i) \
|
||||
(ttisinteger(o) ? (*(i) = ivalue(o), 1) : luaV_tointeger(o,i,LUA_FLOORN2I))
|
||||
|
||||
/* non-soft conversion: only integral values are converted.
|
||||
** This is the strict semantic used by equality ('==' and '~='), where a
|
||||
** non-integral float such as 0.5 must not compare equal to an integer.
|
||||
** 'tointeger' (soft, LUA_FLOORN2I) is intentionally kept for API argument
|
||||
** coercion so that EdgeTX API functions accept unrounded floats; do not
|
||||
** switch this macro back to the soft conversion. */
|
||||
#define tointegerexact(o,i) \
|
||||
(ttisinteger(o) ? (*(i) = ivalue(o), 1) : luaV_tointeger(o,i,0))
|
||||
|
||||
#define intop(op,v1,v2) l_castU2S(l_castS2U(v1) op l_castS2U(v2))
|
||||
|
||||
#define luaV_rawequalobj(t1,t2) luaV_equalobj(NULL,t1,t2)
|
||||
|
||||
Reference in New Issue
Block a user