diff options
| -rw-r--r-- | lvm.c | 121 |
1 files changed, 69 insertions, 52 deletions
| @@ -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 | */ |
| 240 | static int LTintfloat (lua_Integer i, lua_Number f, int neg) { | 267 | static 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 | */ |
| 268 | static int LEintfloat (lua_Integer i, lua_Number f, int neg) { | 286 | static 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 | ||
