diff options
author | Guido van Rossum <guido@python.org> | 1997-01-11 19:26:21 (GMT) |
---|---|---|
committer | Guido van Rossum <guido@python.org> | 1997-01-11 19:26:21 (GMT) |
commit | 919cf1aff1b28d784fa91e31994875aa91a9ed55 (patch) | |
tree | 242c09490dbe685e52cab8d0f72beeb4393c322f /Objects | |
parent | 265b5b3f038a0baa5924b3a312da1874e55587f2 (diff) | |
download | cpython-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.c | 36 | ||||
-rw-r--r-- | Objects/floatobject.c | 11 |
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; |