summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2015-05-20 13:22:55 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2015-05-20 13:22:55 -0300
commit0ec12c1bd1ff5f42450703bdbd48f29a2d5e78f8 (patch)
tree2f0d26c5bb3729a67e06bc86c03d30ed4ffba08f
parenta71c0ab8613bb8f14c91f9c3fc05e68c9a982206 (diff)
downloadlua-0ec12c1bd1ff5f42450703bdbd48f29a2d5e78f8.tar.gz
lua-0ec12c1bd1ff5f42450703bdbd48f29a2d5e78f8.tar.bz2
lua-0ec12c1bd1ff5f42450703bdbd48f29a2d5e78f8.zip
new semantics for numerical order (following math regardless
representation)
-rw-r--r--lvm.c118
1 files changed, 90 insertions, 28 deletions
diff --git a/lvm.c b/lvm.c
index ed32455c..d1aadd95 100644
--- a/lvm.c
+++ b/lvm.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lvm.c,v 2.239 2015/04/10 17:56:25 roberto Exp roberto $ 2** $Id: lvm.c,v 2.240 2015/04/29 18:27:16 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*/
@@ -35,22 +35,6 @@
35#define MAXTAGLOOP 2000 35#define MAXTAGLOOP 2000
36 36
37 37
38/*
39** Similar to 'tonumber', but does not attempt to convert strings and
40** ensure correct precision (no extra bits). Used in comparisons.
41*/
42static int tofloat (const TValue *obj, lua_Number *n) {
43 if (ttisfloat(obj)) *n = fltvalue(obj);
44 else if (ttisinteger(obj)) {
45 volatile lua_Number x = cast_num(ivalue(obj)); /* avoid extra precision */
46 *n = x;
47 }
48 else {
49 *n = 0; /* to avoid warnings */
50 return 0;
51 }
52 return 1;
53}
54 38
55 39
56/* 40/*
@@ -244,15 +228,96 @@ static int l_strcmp (const TString *ls, const TString *rs) {
244 228
245 229
246/* 230/*
231** Check whether integer 'i' is less than float 'f'. 'neg' true means
232** result will be later negated: NaN still must result in false after
233** inversion. The comparison is based on the equivalence:
234** i < f <--> i < ceil(f)
235** When 'f' is non-positive, 'ceil' is not necessary, because the
236** standard C truncation (when converting a float to an integer) does
237** the job.
238**
239*/
240static int LTintfloat (lua_Integer i, lua_Number f, int neg) {
241 if (f > 0) {
242 f = l_mathop(ceil)(f);
243 if (f >= -cast_num(LUA_MININTEGER)) /* -minint == maxint + 1 */
244 return 1; /* f >= maxint + 1; larger than all integers */
245 else { /* 0 < f < (maxint + 1) */
246 /* as f now has integral value, f <= maxint; cast is safe */
247 return (i < cast(lua_Integer, f));
248 }
249 }
250 else if (f > cast_num(LUA_MININTEGER)) { /* minint < f <= 0? */
251 return (i < cast(lua_Integer, f)); /* cast computes 'ceil' */
252 }
253 else if (luai_numisnan(f))
254 return neg; /* i < NaN: final result must be false */
255 else /* f <= minint */
256 return 0; /* 'f' cannot be larger than any int */
257}
258
259
260/*
261** 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
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*/
268static int LEintfloat (lua_Integer i, lua_Number f, int neg) {
269 if (f >= 0) {
270 if (f >= -cast_num(LUA_MININTEGER)) /* f >= (maxint + 1)? */
271 return 1; /* 'f' larger than all integers */
272 else { /* 0 <= f < (maxint + 1) */
273 /* truncation ensures that resulting value is <= maxint */
274 return (i <= cast(lua_Integer, f));
275 }
276 }
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 }
281 else if (luai_numisnan(f))
282 return neg; /* i <= NaN: final result must be false */
283 else /* f < minint */
284 return 0; /* 'f' is smaller than any int */
285}
286
287
288/*
289** Return 'l < r', for numbers. 'neg' means result will be negated
290** (that is, comparison is based on r <= l <--> not (l < r)).
291** In that case, comparisons with NaN must result in false after
292** being negated (so negate again the comparison).
293*/
294static int LTnum (const TValue *l, const TValue *r, int neg) {
295 if (ttisinteger(l)) {
296 lua_Integer li = ivalue(l);
297 if (ttisinteger(r))
298 return li < ivalue(r); /* both are integers */
299 else /* 'l' is int and 'r' is float */
300 return LTintfloat(li, fltvalue(r), neg); /* l < r ? */
301 }
302 else {
303 lua_Number lf = fltvalue(l); /* 'l' must be float */
304 if (ttisfloat(r)) { /* both are float */
305 lua_Number rf = fltvalue(r);
306 return (neg ? !luai_numle(rf, lf) : luai_numlt(lf, rf));
307 }
308 else /* 'r' is int and 'l' is float */
309 return !LEintfloat(ivalue(r), lf, !neg); /* not (r <= l) ? */
310 }
311}
312
313
314/*
247** Main operation less than; return 'l < r'. 315** Main operation less than; return 'l < r'.
248*/ 316*/
249int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r) { 317int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r) {
250 int res; 318 int res;
251 lua_Number nl, nr; 319 if (ttisnumber(l) && ttisnumber(r)) /* both operands are numbers? */
252 if (ttisinteger(l) && ttisinteger(r)) /* both operands are integers? */ 320 return LTnum(l, r, 0);
253 return (ivalue(l) < ivalue(r));
254 else if (tofloat(l, &nl) && tofloat(r, &nr)) /* both are numbers? */
255 return luai_numlt(nl, nr);
256 else if (ttisstring(l) && ttisstring(r)) /* both are strings? */ 321 else if (ttisstring(l) && ttisstring(r)) /* both are strings? */
257 return l_strcmp(tsvalue(l), tsvalue(r)) < 0; 322 return l_strcmp(tsvalue(l), tsvalue(r)) < 0;
258 else if ((res = luaT_callorderTM(L, l, r, TM_LT)) < 0) /* no metamethod? */ 323 else if ((res = luaT_callorderTM(L, l, r, TM_LT)) < 0) /* no metamethod? */
@@ -271,11 +336,8 @@ int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r) {
271*/ 336*/
272int luaV_lessequal (lua_State *L, const TValue *l, const TValue *r) { 337int luaV_lessequal (lua_State *L, const TValue *l, const TValue *r) {
273 int res; 338 int res;
274 lua_Number nl, nr; 339 if (ttisnumber(l) && ttisnumber(r)) /* both operands are numbers? */
275 if (ttisinteger(l) && ttisinteger(r)) /* both operands are integers? */ 340 return !LTnum(r, l, 1);
276 return (ivalue(l) <= ivalue(r));
277 else if (tofloat(l, &nl) && tofloat(r, &nr)) /* both are numbers? */
278 return luai_numle(nl, nr);
279 else if (ttisstring(l) && ttisstring(r)) /* both are strings? */ 341 else if (ttisstring(l) && ttisstring(r)) /* both are strings? */
280 return l_strcmp(tsvalue(l), tsvalue(r)) <= 0; 342 return l_strcmp(tsvalue(l), tsvalue(r)) <= 0;
281 else if ((res = luaT_callorderTM(L, l, r, TM_LE)) >= 0) /* try 'le' */ 343 else if ((res = luaT_callorderTM(L, l, r, TM_LE)) >= 0) /* try 'le' */
@@ -604,7 +666,7 @@ void luaV_finishOp (lua_State *L) {
604** some macros for common tasks in 'luaV_execute' 666** some macros for common tasks in 'luaV_execute'
605*/ 667*/
606 668
607#if !defined luai_runtimecheck 669#if !defined(luai_runtimecheck)
608#define luai_runtimecheck(L, c) /* void */ 670#define luai_runtimecheck(L, c) /* void */
609#endif 671#endif
610 672