summaryrefslogtreecommitdiffstats
path: root/Objects
diff options
context:
space:
mode:
authorGuido van Rossum <guido@python.org>1997-01-11 19:26:21 (GMT)
committerGuido van Rossum <guido@python.org>1997-01-11 19:26:21 (GMT)
commit919cf1aff1b28d784fa91e31994875aa91a9ed55 (patch)
tree242c09490dbe685e52cab8d0f72beeb4393c322f /Objects
parent265b5b3f038a0baa5924b3a312da1874e55587f2 (diff)
downloadcpython-919cf1aff1b28d784fa91e31994875aa91a9ed55.zip
cpython-919cf1aff1b28d784fa91e31994875aa91a9ed55.tar.gz
cpython-919cf1aff1b28d784fa91e31994875aa91a9ed55.tar.bz2
New, better hash for floating point and complex
Diffstat (limited to 'Objects')
-rw-r--r--Objects/complexobject.c36
-rw-r--r--Objects/floatobject.c11
2 files changed, 41 insertions, 6 deletions
diff --git a/Objects/complexobject.c b/Objects/complexobject.c
index 175933a..14661f1 100644
--- a/Objects/complexobject.c
+++ b/Objects/complexobject.c
@@ -294,7 +294,7 @@ complex_hash(v)
{
double intpart, fractpart;
int expo;
- long x;
+ long hipart, x;
/* This is designed so that Python numbers with the same
value hash to the same value, otherwise comparisons
of mapping keys will turn out weird */
@@ -309,7 +309,7 @@ complex_hash(v)
fractpart = modf(v->cval.real, &intpart);
#endif
- if (fractpart == 0.0) {
+ if (fractpart == 0.0 && v->cval.imag == 0.0) {
if (intpart > 0x7fffffffL || -intpart > 0x7fffffffL) {
/* Convert to long int and use its hash... */
object *w = dnewlongobject(v->cval.real);
@@ -323,8 +323,36 @@ complex_hash(v)
}
else {
fractpart = frexp(fractpart, &expo);
- fractpart = fractpart*2147483648.0; /* 2**31 */
- x = (long) (intpart + fractpart) ^ expo; /* Rather arbitrary */
+ fractpart = fractpart * 2147483648.0; /* 2**31 */
+ hipart = (long)fractpart; /* Take the top 32 bits */
+ fractpart = (fractpart - (double)hipart) * 2147483648.0;
+ /* Get the next 32 bits */
+ x = hipart + (long)fractpart + (long)intpart + (expo << 15);
+ /* Combine everything */
+
+ if (v->cval.imag != 0.0) { /* Hash the imaginary part */
+ /* XXX Note that this hashes complex(x, y)
+ to the same value as complex(y, x).
+ Still better than it used to be :-) */
+#ifdef MPW
+ {
+ extended e;
+ fractpart = modf(v->cval.imag, &e);
+ intpart = e;
+ }
+#else
+ fractpart = modf(v->cval.imag, &intpart);
+#endif
+ fractpart = frexp(fractpart, &expo);
+ fractpart = fractpart * 2147483648.0; /* 2**31 */
+ hipart = (long)fractpart; /* Take the top 32 bits */
+ fractpart =
+ (fractpart - (double)hipart) * 2147483648.0;
+ /* Get the next 32 bits */
+ x ^= hipart + (long)fractpart +
+ (long)intpart + (expo << 15);
+ /* Combine everything */
+ }
}
if (x == -1)
x = -2;
diff --git a/Objects/floatobject.c b/Objects/floatobject.c
index f61eaeb..1cebf8c 100644
--- a/Objects/floatobject.c
+++ b/Objects/floatobject.c
@@ -236,9 +236,16 @@ float_hash(v)
x = (long)intpart;
}
else {
+ /* Note -- if you change this code, also change the copy
+ in complexobject.c */
+ long hipart;
fractpart = frexp(fractpart, &expo);
- fractpart = fractpart*2147483648.0; /* 2**31 */
- x = (long) (intpart + fractpart) ^ expo; /* Rather arbitrary */
+ fractpart = fractpart * 2147483648.0; /* 2**31 */
+ hipart = (long)fractpart; /* Take the top 32 bits */
+ fractpart = (fractpart - (double)hipart) * 2147483648.0;
+ /* Get the next 32 bits */
+ x = hipart + (long)fractpart + (long)intpart + (expo << 15);
+ /* Combine everything */
}
if (x == -1)
x = -2;