Skip to content

Commit 9e9b454

Browse files
take tests from python#124243
Co-authored-by: Serhiy Storchaka <storchaka@gmail.com>
1 parent 8cc2a2b commit 9e9b454

1 file changed

Lines changed: 58 additions & 41 deletions

File tree

Lib/test/test_complex.py

Lines changed: 58 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,7 @@
99

1010
from random import random
1111
from math import isnan, copysign
12-
from functools import reduce
13-
from itertools import combinations_with_replacement
1412
import operator
15-
import _testcapi
1613

1714
INF = float("inf")
1815
NAN = float("nan")
@@ -92,6 +89,10 @@ def assertClose(self, x, y, eps=1e-9):
9289
self.assertCloseAbs(x.real, y.real, eps)
9390
self.assertCloseAbs(x.imag, y.imag, eps)
9491

92+
def assertSameSign(self, x, y):
93+
if copysign(1., x) != copysign(1., y):
94+
self.fail(f'{x!r} and {y!r} have different signs')
95+
9596
def check_div(self, x, y):
9697
"""Compute complex z=x*y, and check that z/x==y and z/y==x."""
9798
z = x * y
@@ -452,44 +453,60 @@ def test_pow_with_small_integer_exponents(self):
452453

453454
# Check that complex numbers with special components
454455
# are correctly handled.
455-
values = [complex(*_)
456-
for _ in combinations_with_replacement([1, -1, 0.0, 0, -0.0, 2,
457-
-3, INF, -INF, NAN], 2)]
458-
exponents = [0, 1, 2, 3, 4, 5, 6, 19]
459-
for z in values:
460-
for e in exponents:
461-
with self.subTest(value=z, exponent=e):
462-
try:
463-
r_pow = z**e
464-
except OverflowError:
465-
continue
466-
r_pro = reduce(lambda x, y: x*y, [z]*e) if e else 1+0j
467-
if str(r_pow) == str(r_pro):
468-
continue
469-
470-
self.assertNotIn(z.real, {0.0, -0.0, INF, -INF, NAN})
471-
self.assertNotIn(z.imag, {0.0, -0.0, INF, -INF, NAN})
472-
473-
# We might fail here, because associativity of multiplication
474-
# is broken already for floats.
475-
# Consider z = 1-1j. Then z*z*z*z = ((z*z)*z)*z = -4+0j,
476-
# while in the algorithm for pow() a diffenent grouping
477-
# of operations is used: z**4 = (z*z)*(z*z) = -4-0j.
478-
#
479-
# Fallback to the generic complex power algorithm.
480-
r_pro, r_pro_errno = _testcapi._py_c_pow(z, e)
481-
self.assertEqual(r_pro_errno, 0)
482-
self.assertClose(r_pow, r_pro)
483-
if isnan(r_pow.real):
484-
self.assertTrue(isnan(r_pro.real))
485-
else:
486-
self.assertEqual(copysign(1, r_pow.real),
487-
copysign(1, r_pro.real))
488-
if isnan(r_pow.imag):
489-
self.assertTrue(isnan(r_pro.imag))
490-
else:
491-
self.assertEqual(copysign(1, r_pow.imag),
492-
copysign(1, r_pro.imag))
456+
values = [complex(x, y)
457+
for x in [5, -5, +0.0, -0.0, INF, -INF, NAN]
458+
for y in [12, -12, +0.0, -0.0, INF, -INF, NAN]]
459+
for c in values:
460+
with self.subTest(value=c):
461+
self.assertComplexesAreIdentical(c**0, complex(1, +0.0))
462+
self.assertComplexesAreIdentical(c**1, c)
463+
self.assertComplexesAreIdentical(c**2, c*c)
464+
self.assertComplexesAreIdentical(c**3, c*(c*c))
465+
self.assertComplexesAreIdentical(c**3, (c*c)*c)
466+
if not c:
467+
continue
468+
for n in range(1, 9):
469+
with self.subTest(exponent=-n):
470+
self.assertComplexesAreIdentical(c**-n, 1/(c**n))
471+
472+
# Special cases for complex division.
473+
for x in [+2, -2]:
474+
for y in [+0.0, -0.0]:
475+
c = complex(x, y)
476+
with self.subTest(value=c):
477+
self.assertComplexesAreIdentical(c**-1, complex(1/x, -y))
478+
c = complex(y, x)
479+
with self.subTest(value=c):
480+
self.assertComplexesAreIdentical(c**-1, complex(y, -1/x))
481+
for x in [+INF, -INF]:
482+
for y in [+1, -1]:
483+
c = complex(x, y)
484+
with self.subTest(value=c):
485+
self.assertComplexesAreIdentical(c**-1, complex(1/x, -0.0*y))
486+
self.assertComplexesAreIdentical(c**-2, complex(0.0, -y/x))
487+
c = complex(y, x)
488+
with self.subTest(value=c):
489+
self.assertComplexesAreIdentical(c**-1, complex(+0.0*y, -1/x))
490+
self.assertComplexesAreIdentical(c**-2, complex(-0.0, -y/x))
491+
492+
# Test that zeroes has the same sign as small non-zero values.
493+
eps = 1e-8
494+
pairs = [(complex(x, y), complex(x, copysign(0.0, y)))
495+
for x in [+1, -1] for y in [+eps, -eps]]
496+
pairs += [(complex(y, x), complex(copysign(0.0, y), x))
497+
for x in [+1, -1] for y in [+eps, -eps]]
498+
for c1, c2 in pairs:
499+
for n in exponents:
500+
with self.subTest(value=c1, exponent=n):
501+
r1 = c1**n
502+
r2 = c2**n
503+
self.assertClose(r1, r2)
504+
self.assertSameSign(r1.real, r2.real)
505+
self.assertSameSign(r1.imag, r2.imag)
506+
self.assertNotEqual(r1.real, 0.0)
507+
if n != 0:
508+
self.assertNotEqual(r1.imag, 0.0)
509+
self.assertTrue(r2.real == 0.0 or r2.imag == 0.0)
493510

494511
def test_boolcontext(self):
495512
for i in range(100):

0 commit comments

Comments
 (0)