aboutsummaryrefslogtreecommitdiff
path: root/lvm.c
diff options
context:
space:
mode:
Diffstat (limited to 'lvm.c')
-rw-r--r--lvm.c116
1 files changed, 71 insertions, 45 deletions
diff --git a/lvm.c b/lvm.c
index a1b750dc..76ce2636 100644
--- a/lvm.c
+++ b/lvm.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lvm.c,v 2.342 2018/02/19 20:06:56 roberto Exp roberto $ 2** $Id: lvm.c,v 2.343 2018/02/21 12:54:26 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*/
@@ -31,17 +31,14 @@
31#include "lvm.h" 31#include "lvm.h"
32 32
33 33
34/* limit for table tag-method chains (to avoid loops) */ 34/* limit for table tag-method chains (to avoid infinite loops) */
35#define MAXTAGLOOP 2000 35#define MAXTAGLOOP 2000
36 36
37 37
38/* 38/*
39** 'l_intfitsf' checks whether a given integer can be converted to a 39** 'l_intfitsf' checks whether a given integer can be converted to a
40** float without rounding. Used in comparisons. Left undefined if 40** float without rounding. Used in comparisons.
41** all integers fit in a float precisely.
42*/ 41*/
43#if !defined(l_intfitsf)
44
45/* number of bits in the mantissa of a float */ 42/* number of bits in the mantissa of a float */
46#define NBM (l_mathlim(MANT_DIG)) 43#define NBM (l_mathlim(MANT_DIG))
47 44
@@ -58,7 +55,9 @@
58#define l_intfitsf(i) \ 55#define l_intfitsf(i) \
59 (-((lua_Integer)1 << NBM) <= (i) && (i) <= ((lua_Integer)1 << NBM)) 56 (-((lua_Integer)1 << NBM) <= (i) && (i) <= ((lua_Integer)1 << NBM))
60 57
61#endif 58#else /* all integers fit in a float precisely */
59
60#define l_intfitsf(i) 1
62 61
63#endif 62#endif
64 63
@@ -157,7 +156,7 @@ static int forlimit (const TValue *obj, lua_Integer *p, lua_Integer step,
157 *p = LUA_MAXINTEGER; 156 *p = LUA_MAXINTEGER;
158 if (step < 0) *stopnow = 1; 157 if (step < 0) *stopnow = 1;
159 } 158 }
160 else { /* float is smaller than min integer */ 159 else { /* float is less than min integer */
161 *p = LUA_MININTEGER; 160 *p = LUA_MININTEGER;
162 if (step >= 0) *stopnow = 1; 161 if (step >= 0) *stopnow = 1;
163 } 162 }
@@ -255,8 +254,8 @@ void luaV_finishset (lua_State *L, const TValue *t, TValue *key,
255 254
256 255
257/* 256/*
258** Compare two strings 'ls' x 'rs', returning an integer smaller-equal- 257** Compare two strings 'ls' x 'rs', returning an integer less-equal-
259** -larger than zero if 'ls' is smaller-equal-larger than 'rs'. 258** -greater than zero if 'ls' is less-equal-greater than 'rs'.
260** The code is a little tricky because it allows '\0' in the strings 259** The code is a little tricky because it allows '\0' in the strings
261** and it uses 'strcoll' (to respect locales) for each segments 260** and it uses 'strcoll' (to respect locales) for each segments
262** of the strings. 261** of the strings.
@@ -275,7 +274,7 @@ static int l_strcmp (const TString *ls, const TString *rs) {
275 if (len == lr) /* 'rs' is finished? */ 274 if (len == lr) /* 'rs' is finished? */
276 return (len == ll) ? 0 : 1; /* check 'ls' */ 275 return (len == ll) ? 0 : 1; /* check 'ls' */
277 else if (len == ll) /* 'ls' is finished? */ 276 else if (len == ll) /* 'ls' is finished? */
278 return -1; /* 'ls' is smaller than 'rs' ('rs' is not finished) */ 277 return -1; /* 'ls' is less than 'rs' ('rs' is not finished) */
279 /* both strings longer than 'len'; go on comparing after the '\0' */ 278 /* both strings longer than 'len'; go on comparing after the '\0' */
280 len++; 279 len++;
281 l += len; ll -= len; r += len; lr -= len; 280 l += len; ll -= len; r += len; lr -= len;
@@ -287,25 +286,24 @@ static int l_strcmp (const TString *ls, const TString *rs) {
287/* 286/*
288** Check whether integer 'i' is less than float 'f'. If 'i' has an 287** Check whether integer 'i' is less than float 'f'. If 'i' has an
289** exact representation as a float ('l_intfitsf'), compare numbers as 288** exact representation as a float ('l_intfitsf'), compare numbers as
290** floats. Otherwise, if 'f' is outside the range for integers, result 289** floats. Otherwise, use the equivalence 'i < f <=> i < ceil(f)'.
291** is trivial. Otherwise, compare them as integers. (When 'i' has no 290** If 'ceil(f)' is out of integer range, either 'f' is greater than
292** float representation, either 'f' is "far away" from 'i' or 'f' has 291** all integers or less than all integers.
293** no precision left for a fractional part; either way, how 'f' is 292** (The test with 'l_intfitsf' is only for performance; the else
294** truncated is irrelevant.) When 'f' is NaN, comparisons must result 293** case is correct for all values, but it is slow due to the conversion
295** in false. 294** from float to int.)
295** When 'f' is NaN, comparisons must result in false.
296*/ 296*/
297static int LTintfloat (lua_Integer i, lua_Number f) { 297static int LTintfloat (lua_Integer i, lua_Number f) {
298#if defined(l_intfitsf) 298 if (l_intfitsf(i))
299 if (!l_intfitsf(i)) { 299 return luai_numlt(cast_num(i), f); /* compare them as floats */
300 if (f >= -cast_num(LUA_MININTEGER)) /* -minint == maxint + 1 */ 300 else { /* i < f <=> i < ceil(f) */
301 return 1; /* f >= maxint + 1 > i */ 301 lua_Integer fi;
302 else if (f > cast_num(LUA_MININTEGER)) /* minint < f <= maxint ? */ 302 if (luaV_flttointeger(f, &fi, 2)) /* fi = ceil(f) */
303 return (i < cast(lua_Integer, f)); /* compare them as integers */ 303 return i < fi; /* compare them as integers */
304 else /* f <= minint <= i (or 'f' is NaN) --> not(i < f) */ 304 else /* 'f' is either greater or less than all integers */
305 return 0; 305 return f > 0; /* greater? */
306 } 306 }
307#endif
308 return luai_numlt(cast_num(i), f); /* compare them as floats */
309} 307}
310 308
311 309
@@ -314,17 +312,49 @@ static int LTintfloat (lua_Integer i, lua_Number f) {
314** See comments on previous function. 312** See comments on previous function.
315*/ 313*/
316static int LEintfloat (lua_Integer i, lua_Number f) { 314static int LEintfloat (lua_Integer i, lua_Number f) {
317#if defined(l_intfitsf) 315 if (l_intfitsf(i))
318 if (!l_intfitsf(i)) { 316 return luai_numle(cast_num(i), f); /* compare them as floats */
319 if (f >= -cast_num(LUA_MININTEGER)) /* -minint == maxint + 1 */ 317 else { /* i <= f <=> i <= floor(f) */
320 return 1; /* f >= maxint + 1 > i */ 318 lua_Integer fi;
321 else if (f >= cast_num(LUA_MININTEGER)) /* minint <= f <= maxint ? */ 319 if (luaV_flttointeger(f, &fi, 1)) /* fi = floor(f) */
322 return (i <= cast(lua_Integer, f)); /* compare them as integers */ 320 return i <= fi; /* compare them as integers */
323 else /* f < minint <= i (or 'f' is NaN) --> not(i <= f) */ 321 else /* 'f' is either greater or less than all integers */
324 return 0; 322 return f > 0; /* greater? */
323 }
324}
325
326
327/*
328** Check whether float 'f' is less than integer 'i'.
329** See comments on previous function.
330*/
331static int LTfloatint (lua_Number f, lua_Integer i) {
332 if (l_intfitsf(i))
333 return luai_numlt(f, cast_num(i)); /* compare them as floats */
334 else { /* f < i <=> floor(f) < i */
335 lua_Integer fi;
336 if (luaV_flttointeger(f, &fi, 1)) /* fi = floor(f) */
337 return fi < i; /* compare them as integers */
338 else /* 'f' is either greater or less than all integers */
339 return f < 0; /* less? */
340 }
341}
342
343
344/*
345** Check whether float 'f' is less than or equal to integer 'i'.
346** See comments on previous function.
347*/
348static int LEfloatint (lua_Number f, lua_Integer i) {
349 if (l_intfitsf(i))
350 return luai_numle(f, cast_num(i)); /* compare them as floats */
351 else { /* f <= i <=> ceil(f) <= i */
352 lua_Integer fi;
353 if (luaV_flttointeger(f, &fi, 2)) /* fi = ceil(f) */
354 return fi <= i; /* compare them as integers */
355 else /* 'f' is either greater or less than all integers */
356 return f < 0; /* less? */
325 } 357 }
326#endif
327 return luai_numle(cast_num(i), f); /* compare them as floats */
328} 358}
329 359
330 360
@@ -344,10 +374,8 @@ static int LTnum (const TValue *l, const TValue *r) {
344 lua_Number lf = fltvalue(l); /* 'l' must be float */ 374 lua_Number lf = fltvalue(l); /* 'l' must be float */
345 if (ttisfloat(r)) 375 if (ttisfloat(r))
346 return luai_numlt(lf, fltvalue(r)); /* both are float */ 376 return luai_numlt(lf, fltvalue(r)); /* both are float */
347 else if (luai_numisnan(lf)) /* 'r' is int and 'l' is float */ 377 else /* 'l' is float and 'r' is int */
348 return 0; /* NaN < i is always false */ 378 return LTfloatint(lf, ivalue(r));
349 else /* without NaN, (l < r) <--> not(r <= l) */
350 return !LEintfloat(ivalue(r), lf); /* not (r <= l) ? */
351 } 379 }
352} 380}
353 381
@@ -368,10 +396,8 @@ static int LEnum (const TValue *l, const TValue *r) {
368 lua_Number lf = fltvalue(l); /* 'l' must be float */ 396 lua_Number lf = fltvalue(l); /* 'l' must be float */
369 if (ttisfloat(r)) 397 if (ttisfloat(r))
370 return luai_numle(lf, fltvalue(r)); /* both are float */ 398 return luai_numle(lf, fltvalue(r)); /* both are float */
371 else if (luai_numisnan(lf)) /* 'r' is int and 'l' is float */ 399 else /* 'l' is float and 'r' is int */
372 return 0; /* NaN <= i is always false */ 400 return LEfloatint(lf, ivalue(r));
373 else /* without NaN, (l <= r) <--> not(r < l) */
374 return !LTintfloat(ivalue(r), lf); /* not (r < l) ? */
375 } 401 }
376} 402}
377 403