summaryrefslogtreecommitdiffstats
path: root/Objects/setobject.c
diff options
context:
space:
mode:
authorRaymond Hettinger <python@rcn.com>2005-08-13 08:28:03 (GMT)
committerRaymond Hettinger <python@rcn.com>2005-08-13 08:28:03 (GMT)
commited6c1ef8c3ca1b75579b5f451c38c15f990d2e28 (patch)
tree93426518c640094bfe140e680d6368e63f3dac4b /Objects/setobject.c
parent00148226df1af0f6ef120492c07fb5a8013087fc (diff)
downloadcpython-ed6c1ef8c3ca1b75579b5f451c38c15f990d2e28.zip
cpython-ed6c1ef8c3ca1b75579b5f451c38c15f990d2e28.tar.gz
cpython-ed6c1ef8c3ca1b75579b5f451c38c15f990d2e28.tar.bz2
* 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.
Diffstat (limited to 'Objects/setobject.c')
-rw-r--r--Objects/setobject.c170
1 files changed, 77 insertions, 93 deletions
diff --git a/Objects/setobject.c b/Objects/setobject.c
index 7cfd2a9..9f07cb1 100644
--- a/Objects/setobject.c
+++ b/Objects/setobject.c
@@ -61,6 +61,7 @@ set_lookkey(PySetObject *so, PyObject *key, register long hash)
setentry *table = so->table;
register setentry *entry;
register int restore_error;
+ register int checked_error;
register int cmp;
PyObject *err_type, *err_value, *err_tb;
PyObject *startkey;
@@ -70,11 +71,13 @@ set_lookkey(PySetObject *so, PyObject *key, register long hash)
if (entry->key == NULL || entry->key == key)
return entry;
- restore_error = 0;
+ restore_error = checked_error = 0;
if (entry->key == dummy)
freeslot = entry;
else {
if (entry->hash == hash) {
+ /* error can't have been checked yet */
+ checked_error = 1;
if (_PyErr_OCCURRED()) {
restore_error = 1;
PyErr_Fetch(&err_type, &err_value, &err_tb);
@@ -111,10 +114,13 @@ set_lookkey(PySetObject *so, PyObject *key, register long hash)
if (entry->key == key)
break;
if (entry->hash == hash && entry->key != dummy) {
- if (_PyErr_OCCURRED()) {
- restore_error = 1;
- PyErr_Fetch(&err_type, &err_value,
- &err_tb);
+ if (!checked_error) {
+ checked_error = 1;
+ if (_PyErr_OCCURRED()) {
+ restore_error = 1;
+ PyErr_Fetch(&err_type, &err_value,
+ &err_tb);
+ }
}
startkey = entry->key;
cmp = PyObject_RichCompareBool(startkey, key, Py_EQ);
@@ -174,44 +180,28 @@ set_lookkey_string(PySetObject *so, PyObject *key, register long hash)
entry = &table[i];
if (entry->key == NULL || entry->key == key)
return entry;
- if (so->fill != so->used) {
- if (entry->key == dummy)
- freeslot = entry;
- else {
- if (entry->hash == hash && _PyString_Eq(entry->key, key))
- return entry;
- freeslot = NULL;
- }
-
- /* In the loop, key == dummy is by far (factor of 100s) the
- least likely outcome, so test for that last. */
- for (perturb = hash; ; perturb >>= PERTURB_SHIFT) {
- i = (i << 2) + i + perturb + 1;
- entry = &table[i & mask];
- if (entry->key == NULL)
- return freeslot == NULL ? entry : freeslot;
- if (entry->key == key
- || (entry->hash == hash
- && entry->key != dummy
- && _PyString_Eq(entry->key, key)))
- return entry;
- if (entry->key == dummy && freeslot == NULL)
- freeslot = entry;
- }
- } else {
- /* Simplified loop when there are no dummy entries. */
+ if (entry->key == dummy)
+ freeslot = entry;
+ else {
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;
- }
+ freeslot = NULL;
+ }
+
+ /* In the loop, key == dummy is by far (factor of 100s) the
+ least likely outcome, so test for that last. */
+ for (perturb = hash; ; perturb >>= PERTURB_SHIFT) {
+ i = (i << 2) + i + perturb + 1;
+ entry = &table[i & mask];
+ if (entry->key == NULL)
+ return freeslot == NULL ? entry : freeslot;
+ if (entry->key == key
+ || (entry->hash == hash
+ && entry->key != dummy
+ && _PyString_Eq(entry->key, key)))
+ return entry;
+ if (entry->key == dummy && freeslot == NULL)
+ freeslot = entry;
}
}
@@ -1369,11 +1359,11 @@ set_ixor(PySetObject *so, PyObject *other)
static PyObject *
set_issubset(PySetObject *so, PyObject *other)
{
- PyObject *tmp, *result;
- register setentry *entry;
- register int i;
+ setentry *entry;
+ int pos = 0;
if (!PyAnySet_Check(other)) {
+ PyObject *tmp, *result;
tmp = make_new_set(&PySet_Type, other);
if (tmp == NULL)
return NULL;
@@ -1384,10 +1374,7 @@ set_issubset(PySetObject *so, PyObject *other)
if (set_len((PyObject *)so) > set_len(other))
Py_RETURN_FALSE;
- entry = &so->table[0];
- for (i=so->used ; i ; entry++, i--) {
- while (entry->key == NULL || entry->key==dummy)
- entry++;
+ while (set_next(so, &pos, &entry)) {
if (!set_contains_entry((PySetObject *)other, entry))
Py_RETURN_FALSE;
}
@@ -1414,51 +1401,6 @@ set_issuperset(PySetObject *so, PyObject *other)
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 *
set_richcompare(PySetObject *v, PyObject *w, int op)
{
@@ -1502,6 +1444,48 @@ set_richcompare(PySetObject *v, PyObject *w, int op)
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 *
set_repr(PySetObject *so)
{