Skip to content

Commit f349433

Browse files
[3.13] gh-144173: fix flaky test_complex.test_truediv() (GH-144355) (#145767)
gh-144173: fix flaky test_complex.test_truediv() (GH-144355) Previously, component-wise relative error bound was tested. However, such bound can't exist already for complex multiplication as one can be used to perform subtraction of floating-point numbers, e.g. x and y for z0=1+1j and z1=x+yj. ```pycon >>> x, y = 1e-9+1j, 1+1j >>> a = x*y*y.conjugate()/2;a (1.0000000272292198e-09+1j) >>> b = x*(y*y.conjugate()/2);b (1e-09+1j) >>> b == x True >>> (a.real-b.real)/math.ulp(b.real) 131672427.0 ``` (cherry picked from commit c4333a1) Co-authored-by: Sergey B Kirpichev <skirpichev@gmail.com>
1 parent b5082d8 commit f349433

File tree

1 file changed

+20
-21
lines changed

1 file changed

+20
-21
lines changed

Lib/test/test_complex.py

Lines changed: 20 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -62,8 +62,8 @@ def assertAlmostEqual(self, a, b):
6262
else:
6363
unittest.TestCase.assertAlmostEqual(self, a, b)
6464

65-
def assertCloseAbs(self, x, y, eps=1e-9):
66-
"""Return true iff floats x and y "are close"."""
65+
def assertClose(self, x, y, eps=1e-9):
66+
"""Return true iff complexes x and y "are close"."""
6767
# put the one with larger magnitude second
6868
if abs(x) > abs(y):
6969
x, y = y, x
@@ -72,26 +72,15 @@ def assertCloseAbs(self, x, y, eps=1e-9):
7272
if x == 0:
7373
return abs(y) < eps
7474
# check that relative difference < eps
75-
self.assertTrue(abs((x-y)/y) < eps)
76-
77-
def assertClose(self, x, y, eps=1e-9):
78-
"""Return true iff complexes x and y "are close"."""
79-
self.assertCloseAbs(x.real, y.real, eps)
80-
self.assertCloseAbs(x.imag, y.imag, eps)
75+
self.assertTrue(abs(x-y)/abs(y) < eps)
8176

8277
def check_div(self, x, y):
8378
"""Compute complex z=x*y, and check that z/x==y and z/y==x."""
8479
z = x * y
85-
if x != 0:
86-
q = z / x
87-
self.assertClose(q, y)
88-
q = z.__truediv__(x)
89-
self.assertClose(q, y)
90-
if y != 0:
91-
q = z / y
92-
self.assertClose(q, x)
93-
q = z.__truediv__(y)
94-
self.assertClose(q, x)
80+
if x:
81+
self.assertClose(z / x, y)
82+
if y:
83+
self.assertClose(z / y, x)
9584

9685
def test_truediv(self):
9786
simple_real = [float(i) for i in range(-5, 6)]
@@ -105,10 +94,20 @@ def test_truediv(self):
10594
self.check_div(complex(1e200, 1e200), 1+0j)
10695
self.check_div(complex(1e-200, 1e-200), 1+0j)
10796

97+
# Smith's algorithm has several sources of inaccuracy
98+
# for components of the result. In examples below,
99+
# it's cancellation of digits in computation of sum.
100+
self.check_div(1e-09+1j, 1+1j)
101+
self.check_div(8.289760544677449e-09+0.13257307440728516j,
102+
0.9059966714925808+0.5054864708672686j)
103+
108104
# Just for fun.
109105
for i in range(100):
110-
self.check_div(complex(random(), random()),
111-
complex(random(), random()))
106+
x = complex(random(), random())
107+
y = complex(random(), random())
108+
self.check_div(x, y)
109+
y = complex(1e10*y.real, y.imag)
110+
self.check_div(x, y)
112111

113112
self.assertAlmostEqual(complex.__truediv__(2+0j, 1+1j), 1-1j)
114113
self.assertRaises(TypeError, operator.truediv, 1j, None)
@@ -343,7 +342,7 @@ def test_boolcontext(self):
343342
self.assertTrue(1j)
344343

345344
def test_conjugate(self):
346-
self.assertClose(complex(5.3, 9.8).conjugate(), 5.3-9.8j)
345+
self.assertEqual(complex(5.3, 9.8).conjugate(), 5.3-9.8j)
347346

348347
def test_constructor(self):
349348
def check(z, x, y):

0 commit comments

Comments
 (0)