Browse Source

new hash for doubles based on frexp, to avoid low-level tricks

Roberto Ierusalimschy 16 years ago
parent
commit
f6ed285cf2
2 changed files with 37 additions and 12 deletions
  1. 7 8
      ltable.c
  2. 30 4
      luaconf.h

+ 7 - 8
ltable.c

@@ -1,5 +1,5 @@
 /*
-** $Id: ltable.c,v 2.40 2009/04/17 14:40:13 roberto Exp roberto $
+** $Id: ltable.c,v 2.41 2009/08/07 17:53:28 roberto Exp roberto $
 ** Lua tables (hash)
 ** See Copyright Notice in lua.h
 */
@@ -18,7 +18,6 @@
 ** Hence even when the load factor reaches 100%, performance remains good.
 */
 
-#include <math.h>
 #include <string.h>
 
 #define ltable_c
@@ -82,13 +81,13 @@ static const Node dummynode_ = {
 ** hash for lua_Numbers
 */
 static Node *hashnum (const Table *t, lua_Number n) {
-  unsigned int a[numints];
   int i;
-  if (luai_numeq(n, 0))  /* avoid problems with -0 */
-    return gnode(t, 0);
-  memcpy(a, &n, sizeof(a));
-  for (i = 1; i < numints; i++) a[0] += a[i];
-  return hashmod(t, a[0]);
+  luai_hashnum(i, n);
+  if (i < 0) {
+     i = -i;  /* must be a positive value */
+     if (i < 0) i = 0;  /* handle INT_MIN */
+  }
+  return hashmod(t, i);
 }
 
 

+ 30 - 4
luaconf.h

@@ -1,5 +1,5 @@
 /*
-** $Id: luaconf.h,v 1.110 2009/09/28 16:32:50 roberto Exp roberto $
+** $Id: luaconf.h,v 1.111 2009/10/11 20:02:19 roberto Exp roberto $
 ** Configuration file for Lua
 ** See Copyright Notice in lua.h
 */
@@ -500,14 +500,20 @@
 /*
 @@ The luai_num* macros define the primitive operations over numbers.
 */
-#if defined(LUA_CORE)
+
+/* the following operations need the math library */
+#if defined(lobject_c) || defined(lvm_c)
 #include <math.h>
+#define luai_nummod(L,a,b)	((a) - floor((a)/(b))*(b))
+#define luai_numpow(L,a,b)	(pow(a,b))
+#endif
+
+/* these are quite standard operations */
+#if defined(LUA_CORE)
 #define luai_numadd(L,a,b)	((a)+(b))
 #define luai_numsub(L,a,b)	((a)-(b))
 #define luai_nummul(L,a,b)	((a)*(b))
 #define luai_numdiv(L,a,b)	((a)/(b))
-#define luai_nummod(L,a,b)	((a) - floor((a)/(b))*(b))
-#define luai_numpow(L,a,b)	(pow(a,b))
 #define luai_numunm(L,a)	(-(a))
 #define luai_numeq(a,b)		((a)==(b))
 #define luai_numlt(L,a,b)	((a)<(b))
@@ -516,6 +522,7 @@
 #endif
 
 
+
 /*
 @@ LUA_INTEGER is the integral type used by lua_pushinteger/lua_tointeger.
 ** CHANGE that if ptrdiff_t is not adequate on your machine. (On most
@@ -574,6 +581,25 @@ union luai_Cast { double l_d; long l_l; };
 #define lua_uint2number(u)  \
 	((LUA_INT32)(u) < 0 ? (lua_Number)(u) : (lua_Number)(LUA_INT32)(u))
 
+
+/*
+@@ luai_hashnum is a macro do hash a lua_Number value into an integer.
+@* The hash must be deterministic and give reasonable values for
+@* both small and large values (outside the range of integers). 
+@* It is used only in ltable.c.
+*/
+
+#if defined(ltable_c)
+
+#include <float.h>
+#include <math.h>
+
+#define luai_hashnum(i,d) { int e;  \
+  d = frexp(d, &e) * (lua_Number)(INT_MAX - DBL_MAX_EXP);  \
+  lua_number2int(i, d); i += e; }
+
+#endif
+
 /* }================================================================== */