mirror of https://github.com/python/cpython
follow up to #9778: define and use an unsigned hash type
This commit is contained in:
parent
2b9af63b4f
commit
8035bc5c04
|
@ -135,7 +135,7 @@ Used in: PY_LONG_LONG
|
||||||
#else
|
#else
|
||||||
#define _PyHASH_BITS 31
|
#define _PyHASH_BITS 31
|
||||||
#endif
|
#endif
|
||||||
#define _PyHASH_MODULUS ((1UL << _PyHASH_BITS) - 1)
|
#define _PyHASH_MODULUS (((size_t)1 << _PyHASH_BITS) - 1)
|
||||||
#define _PyHASH_INF 314159
|
#define _PyHASH_INF 314159
|
||||||
#define _PyHASH_NAN 0
|
#define _PyHASH_NAN 0
|
||||||
#define _PyHASH_IMAG 1000003UL
|
#define _PyHASH_IMAG 1000003UL
|
||||||
|
@ -179,6 +179,8 @@ typedef Py_intptr_t Py_ssize_t;
|
||||||
|
|
||||||
/* Py_hash_t is the same size as a pointer. */
|
/* Py_hash_t is the same size as a pointer. */
|
||||||
typedef Py_ssize_t Py_hash_t;
|
typedef Py_ssize_t Py_hash_t;
|
||||||
|
/* Py_uhash_t is the unsigned equivalent needed to calculate numeric hash. */
|
||||||
|
typedef size_t Py_uhash_t;
|
||||||
|
|
||||||
/* Largest possible value of size_t.
|
/* Largest possible value of size_t.
|
||||||
SIZE_MAX is part of C99, so it might be defined on some
|
SIZE_MAX is part of C99, so it might be defined on some
|
||||||
|
|
|
@ -397,12 +397,12 @@ complex_repr(PyComplexObject *v)
|
||||||
static Py_hash_t
|
static Py_hash_t
|
||||||
complex_hash(PyComplexObject *v)
|
complex_hash(PyComplexObject *v)
|
||||||
{
|
{
|
||||||
unsigned long hashreal, hashimag, combined;
|
Py_uhash_t hashreal, hashimag, combined;
|
||||||
hashreal = (unsigned long)_Py_HashDouble(v->cval.real);
|
hashreal = (Py_uhash_t)_Py_HashDouble(v->cval.real);
|
||||||
if (hashreal == (unsigned long)-1)
|
if (hashreal == (Py_uhash_t)-1)
|
||||||
return -1;
|
return -1;
|
||||||
hashimag = (unsigned long)_Py_HashDouble(v->cval.imag);
|
hashimag = (Py_uhash_t)_Py_HashDouble(v->cval.imag);
|
||||||
if (hashimag == (unsigned long)-1)
|
if (hashimag == (Py_uhash_t)-1)
|
||||||
return -1;
|
return -1;
|
||||||
/* Note: if the imaginary part is 0, hashimag is 0 now,
|
/* Note: if the imaginary part is 0, hashimag is 0 now,
|
||||||
* so the following returns hashreal unchanged. This is
|
* so the following returns hashreal unchanged. This is
|
||||||
|
@ -411,8 +411,8 @@ complex_hash(PyComplexObject *v)
|
||||||
* hash(x + 0*j) must equal hash(x).
|
* hash(x + 0*j) must equal hash(x).
|
||||||
*/
|
*/
|
||||||
combined = hashreal + _PyHASH_IMAG * hashimag;
|
combined = hashreal + _PyHASH_IMAG * hashimag;
|
||||||
if (combined == (unsigned long)-1)
|
if (combined == (Py_uhash_t)-1)
|
||||||
combined = (unsigned long)-2;
|
combined = (Py_uhash_t)-2;
|
||||||
return (Py_hash_t)combined;
|
return (Py_hash_t)combined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2555,7 +2555,7 @@ long_richcompare(PyObject *self, PyObject *other, int op)
|
||||||
static Py_hash_t
|
static Py_hash_t
|
||||||
long_hash(PyLongObject *v)
|
long_hash(PyLongObject *v)
|
||||||
{
|
{
|
||||||
unsigned long x;
|
Py_uhash_t x;
|
||||||
Py_ssize_t i;
|
Py_ssize_t i;
|
||||||
int sign;
|
int sign;
|
||||||
|
|
||||||
|
@ -2604,8 +2604,8 @@ long_hash(PyLongObject *v)
|
||||||
x -= _PyHASH_MODULUS;
|
x -= _PyHASH_MODULUS;
|
||||||
}
|
}
|
||||||
x = x * sign;
|
x = x * sign;
|
||||||
if (x == (unsigned long)-1)
|
if (x == (Py_uhash_t)-1)
|
||||||
x = (unsigned long)-2;
|
x = (Py_uhash_t)-2;
|
||||||
return (Py_hash_t)x;
|
return (Py_hash_t)x;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -692,7 +692,7 @@ _Py_HashDouble(double v)
|
||||||
{
|
{
|
||||||
int e, sign;
|
int e, sign;
|
||||||
double m;
|
double m;
|
||||||
unsigned long x, y;
|
Py_uhash_t x, y;
|
||||||
|
|
||||||
if (!Py_IS_FINITE(v)) {
|
if (!Py_IS_FINITE(v)) {
|
||||||
if (Py_IS_INFINITY(v))
|
if (Py_IS_INFINITY(v))
|
||||||
|
@ -716,7 +716,7 @@ _Py_HashDouble(double v)
|
||||||
x = ((x << 28) & _PyHASH_MODULUS) | x >> (_PyHASH_BITS - 28);
|
x = ((x << 28) & _PyHASH_MODULUS) | x >> (_PyHASH_BITS - 28);
|
||||||
m *= 268435456.0; /* 2**28 */
|
m *= 268435456.0; /* 2**28 */
|
||||||
e -= 28;
|
e -= 28;
|
||||||
y = (unsigned long)m; /* pull out integer part */
|
y = (Py_uhash_t)m; /* pull out integer part */
|
||||||
m -= y;
|
m -= y;
|
||||||
x += y;
|
x += y;
|
||||||
if (x >= _PyHASH_MODULUS)
|
if (x >= _PyHASH_MODULUS)
|
||||||
|
@ -728,8 +728,8 @@ _Py_HashDouble(double v)
|
||||||
x = ((x << e) & _PyHASH_MODULUS) | x >> (_PyHASH_BITS - e);
|
x = ((x << e) & _PyHASH_MODULUS) | x >> (_PyHASH_BITS - e);
|
||||||
|
|
||||||
x = x * sign;
|
x = x * sign;
|
||||||
if (x == (unsigned long)-1)
|
if (x == (Py_uhash_t)-1)
|
||||||
x = (unsigned long)-2;
|
x = (Py_uhash_t)-2;
|
||||||
return (Py_hash_t)x;
|
return (Py_hash_t)x;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -318,7 +318,7 @@ tuplehash(PyTupleObject *v)
|
||||||
register Py_hash_t x, y;
|
register Py_hash_t x, y;
|
||||||
register Py_ssize_t len = Py_SIZE(v);
|
register Py_ssize_t len = Py_SIZE(v);
|
||||||
register PyObject **p;
|
register PyObject **p;
|
||||||
long mult = 1000003L;
|
Py_hash_t mult = 1000003L;
|
||||||
x = 0x345678L;
|
x = 0x345678L;
|
||||||
p = v->ob_item;
|
p = v->ob_item;
|
||||||
while (--len >= 0) {
|
while (--len >= 0) {
|
||||||
|
@ -327,7 +327,7 @@ tuplehash(PyTupleObject *v)
|
||||||
return -1;
|
return -1;
|
||||||
x = (x ^ y) * mult;
|
x = (x ^ y) * mult;
|
||||||
/* the cast might truncate len; that doesn't change hash stability */
|
/* the cast might truncate len; that doesn't change hash stability */
|
||||||
mult += (long)(82520L + len + len);
|
mult += (Py_hash_t)(82520L + len + len);
|
||||||
}
|
}
|
||||||
x += 97531L;
|
x += 97531L;
|
||||||
if (x == -1)
|
if (x == -1)
|
||||||
|
|
|
@ -4314,14 +4314,14 @@ static PyObject *
|
||||||
wrap_hashfunc(PyObject *self, PyObject *args, void *wrapped)
|
wrap_hashfunc(PyObject *self, PyObject *args, void *wrapped)
|
||||||
{
|
{
|
||||||
hashfunc func = (hashfunc)wrapped;
|
hashfunc func = (hashfunc)wrapped;
|
||||||
long res;
|
Py_hash_t res;
|
||||||
|
|
||||||
if (!check_num_args(args, 0))
|
if (!check_num_args(args, 0))
|
||||||
return NULL;
|
return NULL;
|
||||||
res = (*func)(self);
|
res = (*func)(self);
|
||||||
if (res == -1 && PyErr_Occurred())
|
if (res == -1 && PyErr_Occurred())
|
||||||
return NULL;
|
return NULL;
|
||||||
return PyLong_FromLong(res);
|
return PyLong_FromSsize_t(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
|
|
|
@ -569,7 +569,7 @@ get_hash_info(void)
|
||||||
PyStructSequence_SET_ITEM(hash_info, field++,
|
PyStructSequence_SET_ITEM(hash_info, field++,
|
||||||
PyLong_FromLong(8*sizeof(Py_hash_t)));
|
PyLong_FromLong(8*sizeof(Py_hash_t)));
|
||||||
PyStructSequence_SET_ITEM(hash_info, field++,
|
PyStructSequence_SET_ITEM(hash_info, field++,
|
||||||
PyLong_FromLong(_PyHASH_MODULUS));
|
PyLong_FromSsize_t(_PyHASH_MODULUS));
|
||||||
PyStructSequence_SET_ITEM(hash_info, field++,
|
PyStructSequence_SET_ITEM(hash_info, field++,
|
||||||
PyLong_FromLong(_PyHASH_INF));
|
PyLong_FromLong(_PyHASH_INF));
|
||||||
PyStructSequence_SET_ITEM(hash_info, field++,
|
PyStructSequence_SET_ITEM(hash_info, field++,
|
||||||
|
|
Loading…
Reference in New Issue