diff options
Diffstat (limited to '')
| -rw-r--r-- | lvm.c | 118 |
1 files changed, 90 insertions, 28 deletions
| @@ -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 | */ | ||
| 42 | static 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 | */ | ||
| 240 | static 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 | */ | ||
| 268 | static 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 | */ | ||
| 294 | static 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 | */ |
| 249 | int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r) { | 317 | int 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 | */ |
| 272 | int luaV_lessequal (lua_State *L, const TValue *l, const TValue *r) { | 337 | int 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 | ||
