commit 06865aa01d1a8bfcf9f2f4b5a71e37a2561eeea6
parent 465b47489910c8660f7d8f9869ffacdbb2d5d292
Author: Roberto Ierusalimschy <roberto@inf.puc-rio.br>
Date: Wed, 21 Feb 2018 10:46:36 -0300
simpler implementation for 'LTintfloat'/'LEintfloat'
+ 'LTfloatint'/'LEfloatint'
Diffstat:
M | lvm.c | | | 116 | ++++++++++++++++++++++++++++++++++++++++++++++++------------------------------- |
1 file changed, 71 insertions(+), 45 deletions(-)
diff --git a/lvm.c b/lvm.c
@@ -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));
}
}