summaryrefslogtreecommitdiffstats
path: root/Objects/sliceobject.c
diff options
context:
space:
mode:
authorFurkan Onder <furkanonder@protonmail.com>2023-02-19 00:22:02 (GMT)
committerGitHub <noreply@github.com>2023-02-19 00:22:02 (GMT)
commit61f1e67c6fcbf80eb9be2b75f7d62954e28c89e6 (patch)
tree74e32f1ed356fa4cb6cf6013c2cf2aca10046ff3 /Objects/sliceobject.c
parent5170caf3059fdacc92d7370eecb9fe4f0c5a1c76 (diff)
downloadcpython-61f1e67c6fcbf80eb9be2b75f7d62954e28c89e6.zip
cpython-61f1e67c6fcbf80eb9be2b75f7d62954e28c89e6.tar.gz
cpython-61f1e67c6fcbf80eb9be2b75f7d62954e28c89e6.tar.bz2
GH-84783: Make the slice object hashable (GH-101264)
Diffstat (limited to 'Objects/sliceobject.c')
-rw-r--r--Objects/sliceobject.c38
1 files changed, 37 insertions, 1 deletions
diff --git a/Objects/sliceobject.c b/Objects/sliceobject.c
index 5694bd9..5d2e6ad 100644
--- a/Objects/sliceobject.c
+++ b/Objects/sliceobject.c
@@ -628,6 +628,42 @@ slice_traverse(PySliceObject *v, visitproc visit, void *arg)
return 0;
}
+/* code based on tuplehash() of Objects/tupleobject.c */
+#if SIZEOF_PY_UHASH_T > 4
+#define _PyHASH_XXPRIME_1 ((Py_uhash_t)11400714785074694791ULL)
+#define _PyHASH_XXPRIME_2 ((Py_uhash_t)14029467366897019727ULL)
+#define _PyHASH_XXPRIME_5 ((Py_uhash_t)2870177450012600261ULL)
+#define _PyHASH_XXROTATE(x) ((x << 31) | (x >> 33)) /* Rotate left 31 bits */
+#else
+#define _PyHASH_XXPRIME_1 ((Py_uhash_t)2654435761UL)
+#define _PyHASH_XXPRIME_2 ((Py_uhash_t)2246822519UL)
+#define _PyHASH_XXPRIME_5 ((Py_uhash_t)374761393UL)
+#define _PyHASH_XXROTATE(x) ((x << 13) | (x >> 19)) /* Rotate left 13 bits */
+#endif
+
+static Py_hash_t
+slicehash(PySliceObject *v)
+{
+ Py_uhash_t acc = _PyHASH_XXPRIME_5;
+#define _PyHASH_SLICE_PART(com) { \
+ Py_uhash_t lane = PyObject_Hash(v->com); \
+ if(lane == (Py_uhash_t)-1) { \
+ return -1; \
+ } \
+ acc += lane * _PyHASH_XXPRIME_2; \
+ acc = _PyHASH_XXROTATE(acc); \
+ acc *= _PyHASH_XXPRIME_1; \
+}
+ _PyHASH_SLICE_PART(start);
+ _PyHASH_SLICE_PART(stop);
+ _PyHASH_SLICE_PART(step);
+#undef _PyHASH_SLICE_PART
+ if(acc == (Py_uhash_t)-1) {
+ return 1546275796;
+ }
+ return acc;
+}
+
PyTypeObject PySlice_Type = {
PyVarObject_HEAD_INIT(&PyType_Type, 0)
"slice", /* Name of this type */
@@ -642,7 +678,7 @@ PyTypeObject PySlice_Type = {
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
- PyObject_HashNotImplemented, /* tp_hash */
+ (hashfunc)slicehash, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
PyObject_GenericGetAttr, /* tp_getattro */