mirror of
https://github.com/python/cpython.git
synced 2025-09-25 17:59:57 +00:00
* Bring lookkey() and lookkey_string() closer to dict version.
* Use set_next() for looping in issubset() and frozenset_hash(). * Re-order the presentation of cmp and hash functions.
This commit is contained in:
parent
00148226df
commit
ed6c1ef8c3
1 changed files with 77 additions and 93 deletions
|
@ -61,6 +61,7 @@ set_lookkey(PySetObject *so, PyObject *key, register long hash)
|
||||||
setentry *table = so->table;
|
setentry *table = so->table;
|
||||||
register setentry *entry;
|
register setentry *entry;
|
||||||
register int restore_error;
|
register int restore_error;
|
||||||
|
register int checked_error;
|
||||||
register int cmp;
|
register int cmp;
|
||||||
PyObject *err_type, *err_value, *err_tb;
|
PyObject *err_type, *err_value, *err_tb;
|
||||||
PyObject *startkey;
|
PyObject *startkey;
|
||||||
|
@ -70,11 +71,13 @@ set_lookkey(PySetObject *so, PyObject *key, register long hash)
|
||||||
if (entry->key == NULL || entry->key == key)
|
if (entry->key == NULL || entry->key == key)
|
||||||
return entry;
|
return entry;
|
||||||
|
|
||||||
restore_error = 0;
|
restore_error = checked_error = 0;
|
||||||
if (entry->key == dummy)
|
if (entry->key == dummy)
|
||||||
freeslot = entry;
|
freeslot = entry;
|
||||||
else {
|
else {
|
||||||
if (entry->hash == hash) {
|
if (entry->hash == hash) {
|
||||||
|
/* error can't have been checked yet */
|
||||||
|
checked_error = 1;
|
||||||
if (_PyErr_OCCURRED()) {
|
if (_PyErr_OCCURRED()) {
|
||||||
restore_error = 1;
|
restore_error = 1;
|
||||||
PyErr_Fetch(&err_type, &err_value, &err_tb);
|
PyErr_Fetch(&err_type, &err_value, &err_tb);
|
||||||
|
@ -111,11 +114,14 @@ set_lookkey(PySetObject *so, PyObject *key, register long hash)
|
||||||
if (entry->key == key)
|
if (entry->key == key)
|
||||||
break;
|
break;
|
||||||
if (entry->hash == hash && entry->key != dummy) {
|
if (entry->hash == hash && entry->key != dummy) {
|
||||||
|
if (!checked_error) {
|
||||||
|
checked_error = 1;
|
||||||
if (_PyErr_OCCURRED()) {
|
if (_PyErr_OCCURRED()) {
|
||||||
restore_error = 1;
|
restore_error = 1;
|
||||||
PyErr_Fetch(&err_type, &err_value,
|
PyErr_Fetch(&err_type, &err_value,
|
||||||
&err_tb);
|
&err_tb);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
startkey = entry->key;
|
startkey = entry->key;
|
||||||
cmp = PyObject_RichCompareBool(startkey, key, Py_EQ);
|
cmp = PyObject_RichCompareBool(startkey, key, Py_EQ);
|
||||||
if (cmp < 0)
|
if (cmp < 0)
|
||||||
|
@ -174,7 +180,6 @@ set_lookkey_string(PySetObject *so, PyObject *key, register long hash)
|
||||||
entry = &table[i];
|
entry = &table[i];
|
||||||
if (entry->key == NULL || entry->key == key)
|
if (entry->key == NULL || entry->key == key)
|
||||||
return entry;
|
return entry;
|
||||||
if (so->fill != so->used) {
|
|
||||||
if (entry->key == dummy)
|
if (entry->key == dummy)
|
||||||
freeslot = entry;
|
freeslot = entry;
|
||||||
else {
|
else {
|
||||||
|
@ -198,21 +203,6 @@ set_lookkey_string(PySetObject *so, PyObject *key, register long hash)
|
||||||
if (entry->key == dummy && freeslot == NULL)
|
if (entry->key == dummy && freeslot == NULL)
|
||||||
freeslot = entry;
|
freeslot = entry;
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
/* Simplified loop when there are no dummy entries. */
|
|
||||||
if (entry->hash == hash && _PyString_Eq(entry->key, key))
|
|
||||||
return entry;
|
|
||||||
for (perturb = hash; ; perturb >>= PERTURB_SHIFT) {
|
|
||||||
i = (i << 2) + i + perturb + 1;
|
|
||||||
entry = &table[i & mask];
|
|
||||||
if (entry->key == NULL)
|
|
||||||
return entry;
|
|
||||||
if (entry->key == key
|
|
||||||
|| (entry->hash == hash
|
|
||||||
&& _PyString_Eq(entry->key, key)))
|
|
||||||
return entry;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1369,11 +1359,11 @@ set_ixor(PySetObject *so, PyObject *other)
|
||||||
static PyObject *
|
static PyObject *
|
||||||
set_issubset(PySetObject *so, PyObject *other)
|
set_issubset(PySetObject *so, PyObject *other)
|
||||||
{
|
{
|
||||||
PyObject *tmp, *result;
|
setentry *entry;
|
||||||
register setentry *entry;
|
int pos = 0;
|
||||||
register int i;
|
|
||||||
|
|
||||||
if (!PyAnySet_Check(other)) {
|
if (!PyAnySet_Check(other)) {
|
||||||
|
PyObject *tmp, *result;
|
||||||
tmp = make_new_set(&PySet_Type, other);
|
tmp = make_new_set(&PySet_Type, other);
|
||||||
if (tmp == NULL)
|
if (tmp == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -1384,10 +1374,7 @@ set_issubset(PySetObject *so, PyObject *other)
|
||||||
if (set_len((PyObject *)so) > set_len(other))
|
if (set_len((PyObject *)so) > set_len(other))
|
||||||
Py_RETURN_FALSE;
|
Py_RETURN_FALSE;
|
||||||
|
|
||||||
entry = &so->table[0];
|
while (set_next(so, &pos, &entry)) {
|
||||||
for (i=so->used ; i ; entry++, i--) {
|
|
||||||
while (entry->key == NULL || entry->key==dummy)
|
|
||||||
entry++;
|
|
||||||
if (!set_contains_entry((PySetObject *)other, entry))
|
if (!set_contains_entry((PySetObject *)other, entry))
|
||||||
Py_RETURN_FALSE;
|
Py_RETURN_FALSE;
|
||||||
}
|
}
|
||||||
|
@ -1414,51 +1401,6 @@ set_issuperset(PySetObject *so, PyObject *other)
|
||||||
|
|
||||||
PyDoc_STRVAR(issuperset_doc, "Report whether this set contains another set.");
|
PyDoc_STRVAR(issuperset_doc, "Report whether this set contains another set.");
|
||||||
|
|
||||||
static long
|
|
||||||
set_nohash(PyObject *self)
|
|
||||||
{
|
|
||||||
PyErr_SetString(PyExc_TypeError, "set objects are unhashable");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
set_nocmp(PyObject *self)
|
|
||||||
{
|
|
||||||
PyErr_SetString(PyExc_TypeError, "cannot compare sets using cmp()");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static long
|
|
||||||
frozenset_hash(PyObject *self)
|
|
||||||
{
|
|
||||||
PySetObject *so = (PySetObject *)self;
|
|
||||||
long h, hash = 1927868237L;
|
|
||||||
setentry *entry;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
if (so->hash != -1)
|
|
||||||
return so->hash;
|
|
||||||
|
|
||||||
hash *= set_len(self) + 1;
|
|
||||||
entry = &so->table[0];
|
|
||||||
for (i=so->used ; i ; entry++, i--) {
|
|
||||||
while (entry->key == NULL || entry->key==dummy)
|
|
||||||
entry++;
|
|
||||||
/* Work to increase the bit dispersion for closely spaced hash
|
|
||||||
values. The is important because some use cases have many
|
|
||||||
combinations of a small number of elements with nearby
|
|
||||||
hashes so that many distinct combinations collapse to only
|
|
||||||
a handful of distinct hash values. */
|
|
||||||
h = entry->hash;
|
|
||||||
hash ^= (h ^ (h << 16) ^ 89869747L) * 3644798167u;
|
|
||||||
}
|
|
||||||
hash = hash * 69069L + 907133923L;
|
|
||||||
if (hash == -1)
|
|
||||||
hash = 590923713L;
|
|
||||||
so->hash = hash;
|
|
||||||
return hash;
|
|
||||||
}
|
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
set_richcompare(PySetObject *v, PyObject *w, int op)
|
set_richcompare(PySetObject *v, PyObject *w, int op)
|
||||||
{
|
{
|
||||||
|
@ -1502,6 +1444,48 @@ set_richcompare(PySetObject *v, PyObject *w, int op)
|
||||||
return Py_NotImplemented;
|
return Py_NotImplemented;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
set_nocmp(PyObject *self)
|
||||||
|
{
|
||||||
|
PyErr_SetString(PyExc_TypeError, "cannot compare sets using cmp()");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static long
|
||||||
|
frozenset_hash(PyObject *self)
|
||||||
|
{
|
||||||
|
PySetObject *so = (PySetObject *)self;
|
||||||
|
long h, hash = 1927868237L;
|
||||||
|
setentry *entry;
|
||||||
|
int pos = 0;
|
||||||
|
|
||||||
|
if (so->hash != -1)
|
||||||
|
return so->hash;
|
||||||
|
|
||||||
|
hash *= set_len(self) + 1;
|
||||||
|
while (set_next(so, &pos, &entry)) {
|
||||||
|
/* Work to increase the bit dispersion for closely spaced hash
|
||||||
|
values. The is important because some use cases have many
|
||||||
|
combinations of a small number of elements with nearby
|
||||||
|
hashes so that many distinct combinations collapse to only
|
||||||
|
a handful of distinct hash values. */
|
||||||
|
h = entry->hash;
|
||||||
|
hash ^= (h ^ (h << 16) ^ 89869747L) * 3644798167u;
|
||||||
|
}
|
||||||
|
hash = hash * 69069L + 907133923L;
|
||||||
|
if (hash == -1)
|
||||||
|
hash = 590923713L;
|
||||||
|
so->hash = hash;
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
static long
|
||||||
|
set_nohash(PyObject *self)
|
||||||
|
{
|
||||||
|
PyErr_SetString(PyExc_TypeError, "set objects are unhashable");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
set_repr(PySetObject *so)
|
set_repr(PySetObject *so)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue