Ok, so I finally got down to this. A patch is attached. Maybe someone
can have a look first, since I changed some some other things aswell. I
think it might be good to also do some mixing for pointers, even though
its quite unlikely to generate datasets where the lower 32 bits of many
pointers have the same value. I was playing around with some more
complex fixed width mixing functions, but my tests suggested that they
perform badly when using modulo prime in hash tables. Therefore, this
patch simply uses XOR.
I was thinking that using hash_svalue on nan should produce an error
because I dont see how nan can be used hash tables in any reasonable
way. Opinions?
arne
diff --git a/src/svalue.c b/src/svalue.c
index 3139abf..59d53e7 100644
--- a/src/svalue.c
+++ b/src/svalue.c
@@ -478,14 +478,38 @@ PMOD_EXPORT unsigned INT32 hash_svalue(const struct
svalue *s)
/* FALL THROUGH */
default:
#if SIZEOF_CHAR_P > 4
- q=DO_NOT_WARN((unsigned INT32)(PTR_TO_INT(s->u.refs) >> 2));
+ q=DO_NOT_WARN((unsigned INT32)(PTR_TO_INT(s->u.ptr) >> 2));
#else
- q=DO_NOT_WARN((unsigned INT32)(PTR_TO_INT(s->u.refs)));
+ q=DO_NOT_WARN((unsigned INT32)(PTR_TO_INT(s->u.ptr)));
+#endif
+ break;
+ case T_INT:
+ q=(unsigned INT32) s->u.integer;
+#if SIZEOF_INT_TYPE == 8
+ q^=(unsigned INT32)(s->u.integer >> 32);
#endif
break;
- case T_INT: q=s->u.integer; break;
case T_FLOAT:
- q=DO_NOT_WARN((unsigned INT32)(s->u.float_number * 16843009.731757771173));
+ /* this is true for both +0.0 and -0.0 */
+ if (s->u.float_number == 0.0) {
+ q = 0;
+ } else {
+ union {
+ FLOAT_TYPE f;
+#if SIZEOF_FLOAT_TYPE == 8
+ unsigned INT64 i;
+#elif SIZEOF_FLOAT_TYPE == 4
+ unsigned INT32 i;
+#else
+#error Size of FLOAT_TYPE not supported.
+#endif
+ } ufloat;
+ ufloat.f = s->u.float_number;
+ q = (unsigned INT32)ufloat.i;
+#if SIZEOF_FLOAT_TYPE == 8
+ q ^= (unsigned INT32)(ufloat.i >> 32);
+#endif
+ }
break;
}
#if 0