diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2015-02-13 11:05:34 -0200 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2015-02-13 11:05:34 -0200 |
commit | e0306e386fdaa1b1f18f0c293a4b14de8b8a8536 (patch) | |
tree | f94331011a045342b320757ebfbe5318ef3d1faf | |
parent | 2e6e53c7ccb8634f21598b151413292c472ab432 (diff) | |
download | lua-e0306e386fdaa1b1f18f0c293a4b14de8b8a8536.tar.gz lua-e0306e386fdaa1b1f18f0c293a4b14de8b8a8536.tar.bz2 lua-e0306e386fdaa1b1f18f0c293a4b14de8b8a8536.zip |
some changes in 'hashfloat' to avoid undefined (in ISO C) numerical
conversions
-rw-r--r-- | ltable.c | 29 |
1 files changed, 21 insertions, 8 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: ltable.c,v 2.100 2015/01/05 13:52:37 roberto Exp roberto $ | 2 | ** $Id: ltable.c,v 2.101 2015/01/16 16:54:37 roberto Exp roberto $ |
3 | ** Lua tables (hash) | 3 | ** Lua tables (hash) |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -96,16 +96,29 @@ static int numisinteger (lua_Number x, lua_Integer *p) { | |||
96 | 96 | ||
97 | 97 | ||
98 | /* | 98 | /* |
99 | ** hash for floating-point numbers | 99 | ** Hash for floating-point numbers. |
100 | ** The main computation should be just | ||
101 | ** n = frepx(n, &i); hash = (n * INT_MAX) + i | ||
102 | ** but there are some numerical subtleties. | ||
103 | ** In a two-complement representation, INT_MAX does not has an exact | ||
104 | ** representation as a float, but INT_MIN does; because the absolute | ||
105 | ** value of 'frexp' is smaller than 1 (unless 'n' is inf/NaN), the | ||
106 | ** absolute value of the product 'frexp * -INT_MIN' is smaller or equal | ||
107 | ** to INT_MAX. Next, the use of 'unsigned int' avoids overflows when | ||
108 | ** adding 'i'; the use of '~u' (instead of '-u') avoids problems with | ||
109 | ** INT_MIN. | ||
100 | */ | 110 | */ |
101 | static Node *hashfloat (const Table *t, lua_Number n) { | 111 | static Node *hashfloat (const Table *t, lua_Number n) { |
102 | int i; | 112 | int i; |
103 | n = l_mathop(frexp)(n, &i) * cast_num(INT_MAX - DBL_MAX_EXP); | 113 | lua_Integer ni; |
104 | i += cast_int(n); | 114 | n = l_mathop(frexp)(n, &i) * -cast_num(INT_MIN); |
105 | if (i < 0) { | 115 | if (!lua_numbertointeger(n, &ni)) { /* is 'n' inf/-inf/NaN? */ |
106 | if (cast(unsigned int, i) == 0u - i) /* use unsigned to avoid overflows */ | 116 | lua_assert(luai_numisnan(n) || l_mathop(fabs)(n) == HUGE_VAL); |
107 | i = 0; /* handle INT_MIN */ | 117 | i = 0; |
108 | i = -i; /* must be a positive value */ | 118 | } |
119 | else { /* normal case */ | ||
120 | unsigned int u = cast(unsigned int, i) + cast(unsigned int, ni); | ||
121 | i = (u <= cast(unsigned int, INT_MAX) ? u : ~u); | ||
109 | } | 122 | } |
110 | return hashmod(t, i); | 123 | return hashmod(t, i); |
111 | } | 124 | } |