|
6 | 6 |
|
7 | 7 | from random import random |
8 | 8 | from math import atan2, isnan, copysign |
9 | | -from cmath import log, exp, isclose, isnan as cisnan |
10 | 9 | from functools import reduce |
11 | 10 | from itertools import combinations |
12 | 11 | import operator |
| 12 | +import _testcapi |
13 | 13 |
|
14 | 14 | INF = float("inf") |
15 | 15 | NAN = float("nan") |
@@ -345,18 +345,32 @@ def test_pow_with_small_integer_exponents(self): |
345 | 345 | except OverflowError: |
346 | 346 | continue |
347 | 347 | r_pro = reduce(lambda x, y: x*y, [z]*e) if e else 1+0j |
348 | | - test = str(r_pow) == str(r_pro) |
349 | | - if not test: |
350 | | - # We might fail here, because associativity of multiplication |
351 | | - # is broken already for floats. |
352 | | - # Consider z = 1-1j. Then z*z*z*z = ((z*z)*z)*z = -4+0j, |
353 | | - # while in the algorithm for pow() a diffenent grouping |
354 | | - # of operations is used: z**4 = (z*z)*(z*z) = -4-0j. |
355 | | - r_pro = exp(e*log(z)) |
356 | | - self.assertTrue(test or isclose(r_pow, r_pro)) |
357 | | - if not cisnan(r_pow): |
358 | | - self.assertEqual(copysign(1, r_pow.real), copysign(1, r_pro.real)) |
359 | | - self.assertEqual(copysign(1, r_pow.imag), copysign(1, r_pro.imag)) |
| 348 | + if str(r_pow) == str(r_pro): |
| 349 | + continue |
| 350 | + |
| 351 | + self.assertNotIn(z.real, {0.0, -0.0, INF, -INF, NAN}) |
| 352 | + self.assertNotIn(z.imag, {0.0, -0.0, INF, -INF, NAN}) |
| 353 | + |
| 354 | + # We might fail here, because associativity of multiplication |
| 355 | + # is broken already for floats. |
| 356 | + # Consider z = 1-1j. Then z*z*z*z = ((z*z)*z)*z = -4+0j, |
| 357 | + # while in the algorithm for pow() a diffenent grouping |
| 358 | + # of operations is used: z**4 = (z*z)*(z*z) = -4-0j. |
| 359 | + # |
| 360 | + # Fallback to the generic complex power algorithm. |
| 361 | + r_pro, r_pro_errno = _testcapi._py_c_pow(z, e) |
| 362 | + self.assertEqual(r_pro_errno, 0) |
| 363 | + self.assertClose(r_pow, r_pro) |
| 364 | + if not isnan(r_pow.real): |
| 365 | + self.assertEqual(copysign(1, r_pow.real), |
| 366 | + copysign(1, r_pro.real)) |
| 367 | + else: |
| 368 | + self.assertTrue(isnan(r_pro.real)) |
| 369 | + if not isnan(r_pow.imag): |
| 370 | + self.assertEqual(copysign(1, r_pow.imag), |
| 371 | + copysign(1, r_pro.imag)) |
| 372 | + else: |
| 373 | + self.assertTrue(isnan(r_pro.imag)) |
360 | 374 |
|
361 | 375 | def test_boolcontext(self): |
362 | 376 | for i in range(100): |
|
0 commit comments