diff Lib/test/test_complex.py @ 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 255a401c19b0
children 2bc54da4b82c
line wrap: on
line diff
--- a/Lib/test/test_complex.py	Fri May 21 10:52:08 2010 +0000
+++ b/Lib/test/test_complex.py	Fri May 21 14:55:26 2010 +0000
@@ -110,12 +110,18 @@
         self.assertRaises(TypeError, complex.__floordiv__, 3+0j, 0+0j)
 
     def test_richcompare(self):
-        self.assertRaises(OverflowError, complex.__eq__, 1+1j, 1<<10000)
+        self.assertIs(complex.__eq__(1+1j, 1<<10000), False)
         self.assertIs(complex.__lt__(1+1j, None), NotImplemented)
         self.assertIs(complex.__eq__(1+1j, 1+1j), True)
         self.assertIs(complex.__eq__(1+1j, 2+2j), False)
         self.assertIs(complex.__ne__(1+1j, 1+1j), False)
         self.assertIs(complex.__ne__(1+1j, 2+2j), True)
+        for i in range(1, 100):
+            f = i / 100.0
+            self.assertIs(complex.__eq__(f+0j, f), True)
+            self.assertIs(complex.__ne__(f+0j, f), False)
+            self.assertIs(complex.__eq__(complex(f, f), f), False)
+            self.assertIs(complex.__ne__(complex(f, f), f), True)
         self.assertIs(complex.__lt__(1+1j, 2+2j), NotImplemented)
         self.assertIs(complex.__le__(1+1j, 2+2j), NotImplemented)
         self.assertIs(complex.__gt__(1+1j, 2+2j), NotImplemented)
@@ -129,6 +135,23 @@
         self.assertIs(operator.ne(1+1j, 1+1j), False)
         self.assertIs(operator.ne(1+1j, 2+2j), True)
 
+    def test_richcompare_boundaries(self):
+        def check(n, deltas, is_equal, imag = 0.0):
+            for delta in deltas:
+                i = n + delta
+                z = complex(i, imag)
+                self.assertIs(complex.__eq__(z, i), is_equal(delta))
+                self.assertIs(complex.__ne__(z, i), not is_equal(delta))
+        # For IEEE-754 doubles the following should hold:
+        #    x in [2 ** (52 + i), 2 ** (53 + i + 1)] -> x mod 2 ** i == 0
+        # where the interval is representable, of course.
+        for i in range(1, 10):
+            pow = 52 + i
+            mult = 2 ** i
+            check(2 ** pow, range(1, 101), lambda delta: delta % mult == 0)
+            check(2 ** pow, range(1, 101), lambda delta: False, float(i))
+        check(2 ** 53, range(-100, 0), lambda delta: True)
+
     def test_mod(self):
         # % is no longer supported on complex numbers
         self.assertRaises(TypeError, (1+1j).__mod__, 0+0j)