summaryrefslogtreecommitdiffstats
path: root/Objects/setobject.c
diff options
context:
space:
mode:
authorRaymond Hettinger <python@rcn.com>2003-11-23 02:49:05 (GMT)
committerRaymond Hettinger <python@rcn.com>2003-11-23 02:49:05 (GMT)
commit49ba4c39c49ff6b1db666e6c90365fc1361c4a64 (patch)
tree442b73b24c7d6590eb24f4b4d3b1a95465a23c23 /Objects/setobject.c
parentbaf0f8f24da7a541a403cd9848cebc451beb069d (diff)
downloadcpython-49ba4c39c49ff6b1db666e6c90365fc1361c4a64.zip
cpython-49ba4c39c49ff6b1db666e6c90365fc1361c4a64.tar.gz
cpython-49ba4c39c49ff6b1db666e6c90365fc1361c4a64.tar.bz2
* Simplify hash function and add test to show effectiveness of the hash
function. * Add a better test for deepcopying. * Add tests to show the __init__() function works like it does for list and tuple. Add related test. * Have shallow copies of frozensets return self. Add related test. * Have frozenset(f) return f if f is already a frozenset. Add related test. * Beefed-up some existing tests.
Diffstat (limited to 'Objects/setobject.c')
-rw-r--r--Objects/setobject.c40
1 files changed, 26 insertions, 14 deletions
diff --git a/Objects/setobject.c b/Objects/setobject.c
index be73954..fab07fb 100644
--- a/Objects/setobject.c
+++ b/Objects/setobject.c
@@ -64,6 +64,10 @@ frozenset_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
if (!PyArg_UnpackTuple(args, type->tp_name, 0, 1, &iterable))
return NULL;
+ if (iterable != NULL && iterable->ob_type == &PyFrozenSet_Type) {
+ Py_INCREF(iterable);
+ return iterable;
+ }
return make_new_set(type, iterable);
}
@@ -154,6 +158,16 @@ set_copy(PySetObject *so)
return (PyObject *)newso;
}
+static PyObject *
+frozenset_copy(PySetObject *so)
+{
+ if (so->ob_type == &PyFrozenSet_Type) {
+ Py_INCREF(so);
+ return (PyObject *)so;
+ }
+ return set_copy(so);
+}
+
PyDoc_STRVAR(copy_doc, "Return a shallow copy of a set.");
static PyObject *
@@ -686,7 +700,7 @@ frozenset_hash(PyObject *self)
{
PyObject *it, *item;
PySetObject *so = (PySetObject *)self;
- long hash = 0, x;
+ long hash = 0;
if (so->hash != -1)
return so->hash;
@@ -696,14 +710,12 @@ frozenset_hash(PyObject *self)
return -1;
while ((item = PyIter_Next(it)) != NULL) {
- x = PyObject_Hash(item);
- /* Applying x*(x+1) breaks-up linear relationships so that
- h(1) ^ h(2) will be less likely to coincide with hash(3).
- Multiplying by a large prime increases the dispersion
- between consecutive hashes. Adding one bit from the
- original restores the one bit lost during the multiply
- (all the products are even numbers). */
- hash ^= (x * (x+1) * 3644798167) | (x&1);
+ /* Multiplying by a large prime increases 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. */
+ hash ^= PyObject_Hash(item) * 3644798167;
Py_DECREF(item);
}
Py_DECREF(it);
@@ -1096,17 +1108,17 @@ PyTypeObject PySet_Type = {
static PyMethodDef frozenset_methods[] = {
- {"copy", (PyCFunction)set_copy, METH_NOARGS,
+ {"copy", (PyCFunction)frozenset_copy, METH_NOARGS,
copy_doc},
- {"__copy__", (PyCFunction)set_copy, METH_NOARGS,
+ {"__copy__", (PyCFunction)frozenset_copy, METH_NOARGS,
copy_doc},
- {"difference",(PyCFunction)set_difference, METH_O,
+ {"difference", (PyCFunction)set_difference, METH_O,
difference_doc},
{"intersection",(PyCFunction)set_intersection, METH_O,
intersection_doc},
- {"issubset",(PyCFunction)set_issubset, METH_O,
+ {"issubset", (PyCFunction)set_issubset, METH_O,
issubset_doc},
- {"issuperset",(PyCFunction)set_issuperset, METH_O,
+ {"issuperset", (PyCFunction)set_issuperset, METH_O,
issuperset_doc},
{"__reduce__", (PyCFunction)set_reduce, METH_NOARGS,
reduce_doc},