aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2015-02-13 11:05:34 -0200
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2015-02-13 11:05:34 -0200
commite0306e386fdaa1b1f18f0c293a4b14de8b8a8536 (patch)
treef94331011a045342b320757ebfbe5318ef3d1faf
parent2e6e53c7ccb8634f21598b151413292c472ab432 (diff)
downloadlua-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.c29
1 files changed, 21 insertions, 8 deletions
diff --git a/ltable.c b/ltable.c
index 26b1f773..b3771d0a 100644
--- a/ltable.c
+++ b/ltable.c
@@ -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*/
101static Node *hashfloat (const Table *t, lua_Number n) { 111static 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}