diff Objects/complexobject.c @ 61787:d6016fa58df6

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.
author Mark Dickinson <dickinsm@gmail.com>
date Fri, 21 May 2010 14:55:26 +0000
parents cab14be0ada1
children 0bc8ffe6ba9a
line wrap: on
line diff
--- a/Objects/complexobject.c	Fri May 21 10:52:08 2010 +0000
+++ b/Objects/complexobject.c	Fri May 21 14:55:26 2010 +0000
@@ -620,22 +620,58 @@
 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 *