From cc6a982de8b9030a04d85f69a29772bf6c3f442f Mon Sep 17 00:00:00 2001 From: Mark Dickinson Date: Fri, 21 May 2010 14:55:26 +0000 Subject: Issue #8748: Fix two issues with comparisons between complex and integer objects. (1) The comparison could incorrectly return True in some cases (2**53+1 == complex(2**53) == 2**53), breaking transivity of equality. (2) The comparison raised an OverflowError for large integers, leading to unpredictable exceptions when combining integers and complex objects in sets or dicts. Patch by Meador Inge. --- Objects/complexobject.c | 52 +++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 44 insertions(+), 8 deletions(-) (limited to 'Objects/complexobject.c') diff --git a/Objects/complexobject.c b/Objects/complexobject.c index ec26e0a700..9e1e217856 100644 --- a/Objects/complexobject.c +++ b/Objects/complexobject.c @@ -620,22 +620,58 @@ static PyObject * complex_richcompare(PyObject *v, PyObject *w, int op) { PyObject *res; - Py_complex i, j; - TO_COMPLEX(v, i); - TO_COMPLEX(w, j); + Py_complex i; + int equal; if (op != Py_EQ && op != Py_NE) { - Py_INCREF(Py_NotImplemented); - return Py_NotImplemented; + goto Unimplemented; } - if ((i.real == j.real && i.imag == j.imag) == (op == Py_EQ)) - res = Py_True; + assert(PyComplex_Check(v)); + TO_COMPLEX(v, i); + + if (PyLong_Check(w)) { + /* Check for 0.0 imaginary part first to avoid the rich + * comparison when possible. + */ + if (i.imag == 0.0) { + PyObject *j, *sub_res; + j = PyFloat_FromDouble(i.real); + if (j == NULL) + return NULL; + + sub_res = PyObject_RichCompare(j, w, op); + Py_DECREF(j); + return sub_res; + } + else { + equal = 0; + } + } + else if (PyFloat_Check(w)) { + equal = (i.real == PyFloat_AsDouble(w) && i.imag == 0.0); + } + else if (PyComplex_Check(w)) { + Py_complex j; + + TO_COMPLEX(w, j); + equal = (i.real == j.real && i.imag == j.imag); + } + else { + goto Unimplemented; + } + + if (equal == (op == Py_EQ)) + res = Py_True; else - res = Py_False; + res = Py_False; Py_INCREF(res); return res; + +Unimplemented: + Py_INCREF(Py_NotImplemented); + return Py_NotImplemented; } static PyObject * -- cgit v1.2.1