summaryrefslogtreecommitdiffstats
path: root/Objects/complexobject.c
diff options
context:
space:
mode:
authorTim Peters <tim.peters@gmail.com>2000-08-15 03:34:48 (GMT)
committerTim Peters <tim.peters@gmail.com>2000-08-15 03:34:48 (GMT)
commit39dce29365d287dc6b353b2a527dc11fe58dcfa6 (patch)
treef24a592be4c36c5d1888fb0881e8535bf023e41b /Objects/complexobject.c
parent7aced17437a6b05bc4b0b5ff93aa6a5d3a374d68 (diff)
downloadcpython-39dce29365d287dc6b353b2a527dc11fe58dcfa6.zip
cpython-39dce29365d287dc6b353b2a527dc11fe58dcfa6.tar.gz
cpython-39dce29365d287dc6b353b2a527dc11fe58dcfa6.tar.bz2
Fix for http://sourceforge.net/bugs/?func=detailbug&bug_id=111866&group_id=5470.
This was a misleading bug -- the true "bug" was that hash(x) gave an error return when x is an infinity. Fixed that. Added new Py_IS_INFINITY macro to pyport.h. Rearranged code to reduce growing duplication in hashing of float and complex numbers, pushing Trent's earlier stab at that to a logical conclusion. Fixed exceedingly rare bug where hashing of floats could return -1 even if there wasn't an error (didn't waste time trying to construct a test case, it was simply obvious from the code that it *could* happen). Improved complex hash so that hash(complex(x, y)) doesn't systematically equal hash(complex(y, x)) anymore.
Diffstat (limited to 'Objects/complexobject.c')
-rw-r--r--Objects/complexobject.c63
1 files changed, 17 insertions, 46 deletions
diff --git a/Objects/complexobject.c b/Objects/complexobject.c
index e8916d5..6f1cfea 100644
--- a/Objects/complexobject.c
+++ b/Objects/complexobject.c
@@ -242,52 +242,23 @@ complex_compare(PyComplexObject *v, PyComplexObject *w)
static long
complex_hash(PyComplexObject *v)
{
- double intpart, fractpart;
- long x;
- /* This is designed so that Python numbers with the same
- value hash to the same value, otherwise comparisons
- of mapping keys will turn out weird */
-
-#ifdef MPW /* MPW C modf expects pointer to extended as second argument */
-{
- extended e;
- fractpart = modf(v->cval.real, &e);
- intpart = e;
-}
-#else
- fractpart = modf(v->cval.real, &intpart);
-#endif
-
- if (fractpart == 0.0 && v->cval.imag == 0.0) {
- if (intpart > LONG_MAX || -intpart > LONG_MAX) {
- /* Convert to long int and use its hash... */
- PyObject *w = PyLong_FromDouble(v->cval.real);
- if (w == NULL)
- return -1;
- x = PyObject_Hash(w);
- Py_DECREF(w);
- return x;
- }
- x = (long)intpart;
- }
- else {
- x = _Py_HashDouble(v->cval.real);
- if (x == -1)
- return -1;
-
- if (v->cval.imag != 0.0) { /* Hash the imaginary part */
- /* XXX Note that this hashes complex(x, y)
- to the same value as complex(y, x).
- Still better than it used to be :-) */
- long y = _Py_HashDouble(v->cval.imag);
- if (y == -1)
- return -1;
- x += y;
- }
- }
- if (x == -1)
- x = -2;
- return x;
+ long hashreal, hashimag, combined;
+ hashreal = _Py_HashDouble(v->cval.real);
+ if (hashreal == -1)
+ return -1;
+ hashimag = _Py_HashDouble(v->cval.imag);
+ if (hashimag == -1)
+ return -1;
+ /* Note: if the imaginary part is 0, hashimag is 0 now,
+ * so the following returns hashreal unchanged. This is
+ * important because numbers of different types that
+ * compare equal must have the same hash value, so that
+ * hash(x + 0*j) must equal hash(x).
+ */
+ combined = hashreal + 1000003 * hashimag;
+ if (combined == -1)
+ combined = -2;
+ return combined;
}
static PyObject *