|
@@ -1,5 +1,5 @@
|
|
|
/*
|
|
|
-** $Id: lvm.c,v 2.342 2018/02/19 20:06:56 roberto Exp roberto $
|
|
|
+** $Id: lvm.c,v 2.343 2018/02/21 12:54:26 roberto Exp roberto $
|
|
|
** Lua virtual machine
|
|
|
** See Copyright Notice in lua.h
|
|
|
*/
|
|
@@ -31,17 +31,14 @@
|
|
|
#include "lvm.h"
|
|
|
|
|
|
|
|
|
-/* limit for table tag-method chains (to avoid loops) */
|
|
|
+/* limit for table tag-method chains (to avoid infinite loops) */
|
|
|
#define MAXTAGLOOP 2000
|
|
|
|
|
|
|
|
|
/*
|
|
|
** 'l_intfitsf' checks whether a given integer can be converted to a
|
|
|
-** float without rounding. Used in comparisons. Left undefined if
|
|
|
-** all integers fit in a float precisely.
|
|
|
+** float without rounding. Used in comparisons.
|
|
|
*/
|
|
|
-#if !defined(l_intfitsf)
|
|
|
-
|
|
|
/* number of bits in the mantissa of a float */
|
|
|
#define NBM (l_mathlim(MANT_DIG))
|
|
|
|
|
@@ -58,7 +55,9 @@
|
|
|
#define l_intfitsf(i) \
|
|
|
(-((lua_Integer)1 << NBM) <= (i) && (i) <= ((lua_Integer)1 << NBM))
|
|
|
|
|
|
-#endif
|
|
|
+#else /* all integers fit in a float precisely */
|
|
|
+
|
|
|
+#define l_intfitsf(i) 1
|
|
|
|
|
|
#endif
|
|
|
|
|
@@ -157,7 +156,7 @@ static int forlimit (const TValue *obj, lua_Integer *p, lua_Integer step,
|
|
|
*p = LUA_MAXINTEGER;
|
|
|
if (step < 0) *stopnow = 1;
|
|
|
}
|
|
|
- else { /* float is smaller than min integer */
|
|
|
+ else { /* float is less than min integer */
|
|
|
*p = LUA_MININTEGER;
|
|
|
if (step >= 0) *stopnow = 1;
|
|
|
}
|
|
@@ -255,8 +254,8 @@ void luaV_finishset (lua_State *L, const TValue *t, TValue *key,
|
|
|
|
|
|
|
|
|
/*
|
|
|
-** Compare two strings 'ls' x 'rs', returning an integer smaller-equal-
|
|
|
-** -larger than zero if 'ls' is smaller-equal-larger than 'rs'.
|
|
|
+** Compare two strings 'ls' x 'rs', returning an integer less-equal-
|
|
|
+** -greater than zero if 'ls' is less-equal-greater than 'rs'.
|
|
|
** The code is a little tricky because it allows '\0' in the strings
|
|
|
** and it uses 'strcoll' (to respect locales) for each segments
|
|
|
** of the strings.
|
|
@@ -275,7 +274,7 @@ static int l_strcmp (const TString *ls, const TString *rs) {
|
|
|
if (len == lr) /* 'rs' is finished? */
|
|
|
return (len == ll) ? 0 : 1; /* check 'ls' */
|
|
|
else if (len == ll) /* 'ls' is finished? */
|
|
|
- return -1; /* 'ls' is smaller than 'rs' ('rs' is not finished) */
|
|
|
+ return -1; /* 'ls' is less than 'rs' ('rs' is not finished) */
|
|
|
/* both strings longer than 'len'; go on comparing after the '\0' */
|
|
|
len++;
|
|
|
l += len; ll -= len; r += len; lr -= len;
|
|
@@ -287,25 +286,24 @@ static int l_strcmp (const TString *ls, const TString *rs) {
|
|
|
/*
|
|
|
** Check whether integer 'i' is less than float 'f'. If 'i' has an
|
|
|
** exact representation as a float ('l_intfitsf'), compare numbers as
|
|
|
-** floats. Otherwise, if 'f' is outside the range for integers, result
|
|
|
-** is trivial. Otherwise, compare them as integers. (When 'i' has no
|
|
|
-** float representation, either 'f' is "far away" from 'i' or 'f' has
|
|
|
-** no precision left for a fractional part; either way, how 'f' is
|
|
|
-** truncated is irrelevant.) When 'f' is NaN, comparisons must result
|
|
|
-** in false.
|
|
|
+** floats. Otherwise, use the equivalence 'i < f <=> i < ceil(f)'.
|
|
|
+** If 'ceil(f)' is out of integer range, either 'f' is greater than
|
|
|
+** all integers or less than all integers.
|
|
|
+** (The test with 'l_intfitsf' is only for performance; the else
|
|
|
+** case is correct for all values, but it is slow due to the conversion
|
|
|
+** from float to int.)
|
|
|
+** When 'f' is NaN, comparisons must result in false.
|
|
|
*/
|
|
|
static int LTintfloat (lua_Integer i, lua_Number f) {
|
|
|
-#if defined(l_intfitsf)
|
|
|
- if (!l_intfitsf(i)) {
|
|
|
- if (f >= -cast_num(LUA_MININTEGER)) /* -minint == maxint + 1 */
|
|
|
- return 1; /* f >= maxint + 1 > i */
|
|
|
- else if (f > cast_num(LUA_MININTEGER)) /* minint < f <= maxint ? */
|
|
|
- return (i < cast(lua_Integer, f)); /* compare them as integers */
|
|
|
- else /* f <= minint <= i (or 'f' is NaN) --> not(i < f) */
|
|
|
- return 0;
|
|
|
+ if (l_intfitsf(i))
|
|
|
+ return luai_numlt(cast_num(i), f); /* compare them as floats */
|
|
|
+ else { /* i < f <=> i < ceil(f) */
|
|
|
+ lua_Integer fi;
|
|
|
+ if (luaV_flttointeger(f, &fi, 2)) /* fi = ceil(f) */
|
|
|
+ return i < fi; /* compare them as integers */
|
|
|
+ else /* 'f' is either greater or less than all integers */
|
|
|
+ return f > 0; /* greater? */
|
|
|
}
|
|
|
-#endif
|
|
|
- return luai_numlt(cast_num(i), f); /* compare them as floats */
|
|
|
}
|
|
|
|
|
|
|
|
@@ -314,17 +312,49 @@ static int LTintfloat (lua_Integer i, lua_Number f) {
|
|
|
** See comments on previous function.
|
|
|
*/
|
|
|
static int LEintfloat (lua_Integer i, lua_Number f) {
|
|
|
-#if defined(l_intfitsf)
|
|
|
- if (!l_intfitsf(i)) {
|
|
|
- if (f >= -cast_num(LUA_MININTEGER)) /* -minint == maxint + 1 */
|
|
|
- return 1; /* f >= maxint + 1 > i */
|
|
|
- else if (f >= cast_num(LUA_MININTEGER)) /* minint <= f <= maxint ? */
|
|
|
- return (i <= cast(lua_Integer, f)); /* compare them as integers */
|
|
|
- else /* f < minint <= i (or 'f' is NaN) --> not(i <= f) */
|
|
|
- return 0;
|
|
|
+ if (l_intfitsf(i))
|
|
|
+ return luai_numle(cast_num(i), f); /* compare them as floats */
|
|
|
+ else { /* i <= f <=> i <= floor(f) */
|
|
|
+ lua_Integer fi;
|
|
|
+ if (luaV_flttointeger(f, &fi, 1)) /* fi = floor(f) */
|
|
|
+ return i <= fi; /* compare them as integers */
|
|
|
+ else /* 'f' is either greater or less than all integers */
|
|
|
+ return f > 0; /* greater? */
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+/*
|
|
|
+** Check whether float 'f' is less than integer 'i'.
|
|
|
+** See comments on previous function.
|
|
|
+*/
|
|
|
+static int LTfloatint (lua_Number f, lua_Integer i) {
|
|
|
+ if (l_intfitsf(i))
|
|
|
+ return luai_numlt(f, cast_num(i)); /* compare them as floats */
|
|
|
+ else { /* f < i <=> floor(f) < i */
|
|
|
+ lua_Integer fi;
|
|
|
+ if (luaV_flttointeger(f, &fi, 1)) /* fi = floor(f) */
|
|
|
+ return fi < i; /* compare them as integers */
|
|
|
+ else /* 'f' is either greater or less than all integers */
|
|
|
+ return f < 0; /* less? */
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+/*
|
|
|
+** Check whether float 'f' is less than or equal to integer 'i'.
|
|
|
+** See comments on previous function.
|
|
|
+*/
|
|
|
+static int LEfloatint (lua_Number f, lua_Integer i) {
|
|
|
+ if (l_intfitsf(i))
|
|
|
+ return luai_numle(f, cast_num(i)); /* compare them as floats */
|
|
|
+ else { /* f <= i <=> ceil(f) <= i */
|
|
|
+ lua_Integer fi;
|
|
|
+ if (luaV_flttointeger(f, &fi, 2)) /* fi = ceil(f) */
|
|
|
+ return fi <= i; /* compare them as integers */
|
|
|
+ else /* 'f' is either greater or less than all integers */
|
|
|
+ return f < 0; /* less? */
|
|
|
}
|
|
|
-#endif
|
|
|
- return luai_numle(cast_num(i), f); /* compare them as floats */
|
|
|
}
|
|
|
|
|
|
|
|
@@ -344,10 +374,8 @@ static int LTnum (const TValue *l, const TValue *r) {
|
|
|
lua_Number lf = fltvalue(l); /* 'l' must be float */
|
|
|
if (ttisfloat(r))
|
|
|
return luai_numlt(lf, fltvalue(r)); /* both are float */
|
|
|
- else if (luai_numisnan(lf)) /* 'r' is int and 'l' is float */
|
|
|
- return 0; /* NaN < i is always false */
|
|
|
- else /* without NaN, (l < r) <--> not(r <= l) */
|
|
|
- return !LEintfloat(ivalue(r), lf); /* not (r <= l) ? */
|
|
|
+ else /* 'l' is float and 'r' is int */
|
|
|
+ return LTfloatint(lf, ivalue(r));
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -368,10 +396,8 @@ static int LEnum (const TValue *l, const TValue *r) {
|
|
|
lua_Number lf = fltvalue(l); /* 'l' must be float */
|
|
|
if (ttisfloat(r))
|
|
|
return luai_numle(lf, fltvalue(r)); /* both are float */
|
|
|
- else if (luai_numisnan(lf)) /* 'r' is int and 'l' is float */
|
|
|
- return 0; /* NaN <= i is always false */
|
|
|
- else /* without NaN, (l <= r) <--> not(r < l) */
|
|
|
- return !LTintfloat(ivalue(r), lf); /* not (r < l) ? */
|
|
|
+ else /* 'l' is float and 'r' is int */
|
|
|
+ return LEfloatint(lf, ivalue(r));
|
|
|
}
|
|
|
}
|
|
|
|