Commit 2261e404 authored by Christoph Groth's avatar Christoph Groth
Browse files

fix hashing

parent 04498edb
......@@ -4,8 +4,6 @@ Roughly in order of importance:
* Implement indexing of sub-arrays (i.e. a[0] for a 2d-array), perhaps even slicing.
* Fix float hash on 32 bit machines. (A test fails.)
* Implement missing arithmetic operations.
* Implement missing comparisons.
......
......@@ -799,21 +799,37 @@ long hash(long x)
long hash(double x)
{
const double two_to_31st = 1L << 31;
const double two_to_31st = 2147483648.0;
double intpart, fractpart;
if (!std::isfinite(x)) {
if (std::isinf(x))
return x < 0 ? -271828 : 314159;
else
return 0;
}
fractpart = modf(x, &intpart);
if (fractpart == 0 &&
intpart >= std::numeric_limits<long>::min() &&
intpart <= std::numeric_limits<long>::max()) {
if (fractpart == 0) {
// This must return the same hash as an equal int or long.
if (intpart > std::numeric_limits<long>::max() ||
intpart < std::numeric_limits<long>::min()) {
// Convert to Python long and use its hash.
PyObject *plong = PyLong_FromDouble(x);
if (plong == NULL) return -1;
long result = PyObject_Hash(plong);
Py_DECREF(plong);
return result;
}
return hash(long(intpart));
}
int expo;
x = frexp(x, &expo) * two_to_31st;
long hipart = x; // Take the top 32 bits.
x = (x - double(hipart)) * two_to_31st; // Get the next 32 bits.
return hash(hipart + (long)x + (expo << 15));
long hipart = x; // Take the top 32 bits.
x = (x - double(hipart)) * two_to_31st; // Get the next 32 bits.
return hash(hipart + long(x) + (expo << 15));
}
long hash(Complex x)
......
......@@ -228,14 +228,17 @@ def test_as_dict_key():
def test_hash_equality():
for thing in [0, -1, -1.0, -1 + 0j, -0.3, 1.7, 0.4j,
-12.3j, 1 - 12.3j, 1.3 - 12.3j,
(), (-1,), (2,),
(0, 0), (-1, -1), (-5, 7), (3, -1, 0),
((0, 0), (0, 0)), (((-1,),),)]:
for thing in [float('nan'), float('inf'), float('-inf'),
0, -1, -1.0, -1 + 0j,
303, -312424, 2**31 - 1, 2**31, 2**53, 2**200,
-0.3, 1.7, 0.4j, -12.3j, 1 - 12.3j, 1.3 - 12.3j,
(), (-1,), (2,),
(0, 0), (-1, -1), (-5, 7), (3, -1, 0),
((0, 0), (0, 0)), (((-1,),),)]:
arr = ta.array(thing)
assert arr == thing
assert not (arr != thing)
if thing == thing:
assert arr == thing
assert not (arr != thing)
assert hash(arr) == hash(thing)
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment