aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2015-06-02 16:11:24 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2015-06-02 16:11:24 -0300
commited1fe28bb8c98382412eab8cfe24fe3dc5adf8f3 (patch)
tree69e88feb16169f9c24e13fcffbf860e83f87add0
parent6645bb2df44d4fc6c7aea8347a559357b657f80a (diff)
downloadlua-ed1fe28bb8c98382412eab8cfe24fe3dc5adf8f3.tar.gz
lua-ed1fe28bb8c98382412eab8cfe24fe3dc5adf8f3.tar.bz2
lua-ed1fe28bb8c98382412eab8cfe24fe3dc5adf8f3.zip
When comparing integers with floats, use float as common type when
possible (i.e., when integer fits in a float without losses); seems to be more efficient in architectures with native support for used Lua numbers
-rw-r--r--lvm.c121
1 files changed, 69 insertions, 52 deletions
diff --git a/lvm.c b/lvm.c
index 27cb9957..19bd24be 100644
--- a/lvm.c
+++ b/lvm.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lvm.c,v 2.242 2015/05/20 18:19:11 roberto Exp roberto $ 2** $Id: lvm.c,v 2.243 2015/05/22 17:48:19 roberto Exp roberto $
3** Lua virtual machine 3** Lua virtual machine
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -9,7 +9,7 @@
9 9
10#include "lprefix.h" 10#include "lprefix.h"
11 11
12 12#include <float.h>
13#include <limits.h> 13#include <limits.h>
14#include <math.h> 14#include <math.h>
15#include <stdio.h> 15#include <stdio.h>
@@ -36,6 +36,34 @@
36 36
37 37
38 38
39/*
40** 'l_intfitsf' checks whether a given integer can be converted to a
41** float without rounding. Used in comparisons. Left undefined if
42** all integers fit in a float precisely.
43*/
44#if !defined(l_intfitsf)
45
46/* number of bits in the mantissa of a float */
47#define NBM (l_mathlim(MANT_DIG))
48
49/*
50** Check whether some integers may not fit in a float, that is, whether
51** (maxinteger >> NBM) > 0 (that implies (1 << NBM) <= maxinteger).
52** (The shifts are done in parts to avoid shifting by more than the size
53** of an integer. In a worst case, NBM == 113 for long double and
54** sizeof(integer) == 32.)
55*/
56#if ((((LUA_MAXINTEGER >> (NBM / 4)) >> (NBM / 4)) >> (NBM / 4)) \
57 >> (NBM - (3 * (NBM / 4)))) > 0
58
59#define l_intfitsf(i) \
60 (-((lua_Integer)1 << NBM) <= (i) && (i) <= ((lua_Integer)1 << NBM))
61
62#endif
63
64#endif
65
66
39 67
40/* 68/*
41** Try to convert a value to a float. The float case is already handled 69** Try to convert a value to a float. The float case is already handled
@@ -228,60 +256,45 @@ static int l_strcmp (const TString *ls, const TString *rs) {
228 256
229 257
230/* 258/*
231** Check whether integer 'i' is less than float 'f'. 'neg' true means 259** Check whether integer 'i' is less than float 'f'. If 'i' has an
232** result will be later negated: NaN still must result in false after 260** exact representation as a float ('l_intfitsf'), compare numbers as
233** inversion. The comparison is based on the equivalence: 261** floats. Otherwise, if 'f' is outside the range for integers, result
234** i < f <--> i < ceil(f) 262** is trivial. Otherwise, compare them as integers. (When 'i' has no
235** When 'f' is non-positive, 'ceil' is not necessary, because the 263** float representation, either 'f' is "far away" from 'i' or 'f' has
236** standard C truncation (when converting a float to an integer) does 264** no precision left for a fractional part; either way, how 'f' is
237** the job. 265** truncated is irrelevant.)
238**
239*/ 266*/
240static int LTintfloat (lua_Integer i, lua_Number f, int neg) { 267static int LTintfloat (lua_Integer i, lua_Number f) {
241 if (f > 0) { 268#if defined(l_intfitsf)
242 f = l_mathop(ceil)(f); 269 if (!l_intfitsf(i)) {
243 if (f >= -cast_num(LUA_MININTEGER)) /* -minint == maxint + 1 */ 270 if (f >= -cast_num(LUA_MININTEGER)) /* -minint == maxint + 1 */
244 return 1; /* f >= maxint + 1; larger than all integers */ 271 return 1; /* f >= maxint + 1 > i */
245 else { /* 0 < f < (maxint + 1) */ 272 else if (f <= cast_num(LUA_MININTEGER)) /* f <= minint */
246 /* as f now has integral value, f <= maxint; cast is safe */ 273 return 0; /* f <= minint <= i --> not(i < f) */
247 return (i < cast(lua_Integer, f)); 274 else /* minint < f <= maxint */
248 } 275 return (i < cast(lua_Integer, f)); /* compare them as integers */
249 }
250 else if (f > cast_num(LUA_MININTEGER)) { /* minint < f <= 0? */
251 return (i < cast(lua_Integer, f)); /* cast computes 'ceil' */
252 } 276 }
253 else if (luai_numisnan(f)) 277#endif
254 return neg; /* i < NaN: final result must be false */ 278 return luai_numlt(cast_num(i), f); /* compare them as floats */
255 else /* f <= minint */
256 return 0; /* 'f' cannot be larger than any int */
257} 279}
258 280
259 281
260/* 282/*
261** Check whether integer 'i' is less than or equal to float 'f'. 283** Check whether integer 'i' is less than or equal to float 'f'.
262** 'neg' is like in previous function. The comparison is based on the 284** See comments on previous function.
263** equivalence:
264** i <= f <--> i <= floor(f)
265** When f is non-negative, 'floor' is not necessary (C truncation does
266** the job).
267*/ 285*/
268static int LEintfloat (lua_Integer i, lua_Number f, int neg) { 286static int LEintfloat (lua_Integer i, lua_Number f) {
269 if (f >= 0) { 287#if defined(l_intfitsf)
270 if (f >= -cast_num(LUA_MININTEGER)) /* f >= (maxint + 1)? */ 288 if (!l_intfitsf(i)) {
271 return 1; /* 'f' larger than all integers */ 289 if (f >= -cast_num(LUA_MININTEGER)) /* -minint == maxint + 1 */
272 else { /* 0 <= f < (maxint + 1) */ 290 return 1; /* f >= maxint + 1 > i */
273 /* truncation ensures that resulting value is <= maxint */ 291 else if (f < cast_num(LUA_MININTEGER)) /* f < minint */
274 return (i <= cast(lua_Integer, f)); 292 return 0; /* f < minint <= i --> not(i <= f) */
275 } 293 else /* minint <= f <= maxint */
276 } 294 return (i <= cast(lua_Integer, f)); /* compare them as integers */
277 else if (f >= cast_num(LUA_MININTEGER)) { /* minint <= f < 0? */
278 /* f >= minint --> floor(f) >= minint */
279 return (i <= cast(lua_Integer, l_floor(f)));
280 } 295 }
281 else if (luai_numisnan(f)) 296#endif
282 return neg; /* i <= NaN: final result must be false */ 297 return luai_numle(cast_num(i), f); /* compare them as floats */
283 else /* f < minint */
284 return 0; /* 'f' is smaller than any int */
285} 298}
286 299
287 300
@@ -294,14 +307,16 @@ static int LTnum (const TValue *l, const TValue *r) {
294 if (ttisinteger(r)) 307 if (ttisinteger(r))
295 return li < ivalue(r); /* both are integers */ 308 return li < ivalue(r); /* both are integers */
296 else /* 'l' is int and 'r' is float */ 309 else /* 'l' is int and 'r' is float */
297 return LTintfloat(li, fltvalue(r), 0); /* l < r ? */ 310 return LTintfloat(li, fltvalue(r)); /* l < r ? */
298 } 311 }
299 else { 312 else {
300 lua_Number lf = fltvalue(l); /* 'l' must be float */ 313 lua_Number lf = fltvalue(l); /* 'l' must be float */
301 if (ttisfloat(r)) 314 if (ttisfloat(r))
302 return luai_numlt(lf, fltvalue(r)); /* both are float */ 315 return luai_numlt(lf, fltvalue(r)); /* both are float */
303 else /* 'r' is int and 'l' is float */ 316 else if (luai_numisnan(lf)) /* 'r' is int and 'l' is float */
304 return !LEintfloat(ivalue(r), lf, 1); /* not (r <= l) ? */ 317 return 0; /* NaN < i is always false */
318 else /* without NaN, (l < r) <--> not(r <= l) */
319 return !LEintfloat(ivalue(r), lf); /* not (r <= l) ? */
305 } 320 }
306} 321}
307 322
@@ -315,14 +330,16 @@ static int LEnum (const TValue *l, const TValue *r) {
315 if (ttisinteger(r)) 330 if (ttisinteger(r))
316 return li <= ivalue(r); /* both are integers */ 331 return li <= ivalue(r); /* both are integers */
317 else /* 'l' is int and 'r' is float */ 332 else /* 'l' is int and 'r' is float */
318 return LEintfloat(li, fltvalue(r), 0); /* l <= r ? */ 333 return LEintfloat(li, fltvalue(r)); /* l <= r ? */
319 } 334 }
320 else { 335 else {
321 lua_Number lf = fltvalue(l); /* 'l' must be float */ 336 lua_Number lf = fltvalue(l); /* 'l' must be float */
322 if (ttisfloat(r)) 337 if (ttisfloat(r))
323 return luai_numle(lf, fltvalue(r)); /* both are float */ 338 return luai_numle(lf, fltvalue(r)); /* both are float */
324 else /* 'r' is int and 'l' is float */ 339 else if (luai_numisnan(lf)) /* 'r' is int and 'l' is float */
325 return !LTintfloat(ivalue(r), lf, 1); /* not (r < l) ? */ 340 return 0; /* NaN <= i is always false */
341 else /* without NaN, (l <= r) <--> not(r < l) */
342 return !LTintfloat(ivalue(r), lf); /* not (r < l) ? */
326 } 343 }
327} 344}
328 345