mirror of https://github.com/rusefi/lua.git
simpler implementation for 'LTintfloat'/'LEintfloat'
+ 'LTfloatint'/'LEfloatint'
This commit is contained in:
parent
465b474899
commit
06865aa01d
116
lvm.c
116
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));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue