diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2015-06-02 16:11:24 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2015-06-02 16:11:24 -0300 |
commit | ed1fe28bb8c98382412eab8cfe24fe3dc5adf8f3 (patch) | |
tree | 69e88feb16169f9c24e13fcffbf860e83f87add0 | |
parent | 6645bb2df44d4fc6c7aea8347a559357b657f80a (diff) | |
download | lua-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.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 | ||