1from test.support import requires_IEEE_754, cpython_only, import_helper 2from test.support.testcase import ComplexesAreIdenticalMixin 3from test.test_math import parse_testfile, test_file 4import test.test_math as test_math 5import unittest 6import cmath, math 7from cmath import phase, polar, rect, pi 8import platform 9import sys 10 11 12INF = float('inf') 13NAN = float('nan') 14 15complex_zeros = [complex(x, y) for x in [0.0, -0.0] for y in [0.0, -0.0]] 16complex_infinities = [complex(x, y) for x, y in [ 17 (INF, 0.0), # 1st quadrant 18 (INF, 2.3), 19 (INF, INF), 20 (2.3, INF), 21 (0.0, INF), 22 (-0.0, INF), # 2nd quadrant 23 (-2.3, INF), 24 (-INF, INF), 25 (-INF, 2.3), 26 (-INF, 0.0), 27 (-INF, -0.0), # 3rd quadrant 28 (-INF, -2.3), 29 (-INF, -INF), 30 (-2.3, -INF), 31 (-0.0, -INF), 32 (0.0, -INF), # 4th quadrant 33 (2.3, -INF), 34 (INF, -INF), 35 (INF, -2.3), 36 (INF, -0.0) 37 ]] 38complex_nans = [complex(x, y) for x, y in [ 39 (NAN, -INF), 40 (NAN, -2.3), 41 (NAN, -0.0), 42 (NAN, 0.0), 43 (NAN, 2.3), 44 (NAN, INF), 45 (-INF, NAN), 46 (-2.3, NAN), 47 (-0.0, NAN), 48 (0.0, NAN), 49 (2.3, NAN), 50 (INF, NAN) 51 ]] 52 53class CMathTests(ComplexesAreIdenticalMixin, unittest.TestCase): 54 # list of all functions in cmath 55 test_functions = [getattr(cmath, fname) for fname in [ 56 'acos', 'acosh', 'asin', 'asinh', 'atan', 'atanh', 57 'cos', 'cosh', 'exp', 'log', 'log10', 'sin', 'sinh', 58 'sqrt', 'tan', 'tanh']] 59 # test first and second arguments independently for 2-argument log 60 test_functions.append(lambda x : cmath.log(x, 1729. + 0j)) 61 test_functions.append(lambda x : cmath.log(14.-27j, x)) 62 63 def setUp(self): 64 self.test_values = open(test_file, encoding="utf-8") 65 66 def tearDown(self): 67 self.test_values.close() 68 69 def rAssertAlmostEqual(self, a, b, rel_err = 2e-15, abs_err = 5e-323, 70 msg=None): 71 """Fail if the two floating-point numbers are not almost equal. 72 73 Determine whether floating-point values a and b are equal to within 74 a (small) rounding error. The default values for rel_err and 75 abs_err are chosen to be suitable for platforms where a float is 76 represented by an IEEE 754 double. They allow an error of between 77 9 and 19 ulps. 78 """ 79 80 # special values testing 81 if math.isnan(a): 82 if math.isnan(b): 83 return 84 self.fail(msg or '{!r} should be nan'.format(b)) 85 86 if math.isinf(a): 87 if a == b: 88 return 89 self.fail(msg or 'finite result where infinity expected: ' 90 'expected {!r}, got {!r}'.format(a, b)) 91 92 # if both a and b are zero, check whether they have the same sign 93 # (in theory there are examples where it would be legitimate for a 94 # and b to have opposite signs; in practice these hardly ever 95 # occur). 96 if not a and not b: 97 if math.copysign(1., a) != math.copysign(1., b): 98 self.fail(msg or 'zero has wrong sign: expected {!r}, ' 99 'got {!r}'.format(a, b)) 100 101 # if a-b overflows, or b is infinite, return False. Again, in 102 # theory there are examples where a is within a few ulps of the 103 # max representable float, and then b could legitimately be 104 # infinite. In practice these examples are rare. 105 try: 106 absolute_error = abs(b-a) 107 except OverflowError: 108 pass 109 else: 110 # test passes if either the absolute error or the relative 111 # error is sufficiently small. The defaults amount to an 112 # error of between 9 ulps and 19 ulps on an IEEE-754 compliant 113 # machine. 114 if absolute_error <= max(abs_err, rel_err * abs(a)): 115 return 116 self.fail(msg or 117 '{!r} and {!r} are not sufficiently close'.format(a, b)) 118 119 def test_constants(self): 120 e_expected = 2.71828182845904523536 121 pi_expected = 3.14159265358979323846 122 self.assertAlmostEqual(cmath.pi, pi_expected, places=9, 123 msg="cmath.pi is {}; should be {}".format(cmath.pi, pi_expected)) 124 self.assertAlmostEqual(cmath.e, e_expected, places=9, 125 msg="cmath.e is {}; should be {}".format(cmath.e, e_expected)) 126 127 def test_infinity_and_nan_constants(self): 128 self.assertEqual(cmath.inf.real, math.inf) 129 self.assertEqual(cmath.inf.imag, 0.0) 130 self.assertEqual(cmath.infj.real, 0.0) 131 self.assertEqual(cmath.infj.imag, math.inf) 132 133 self.assertTrue(math.isnan(cmath.nan.real)) 134 self.assertEqual(cmath.nan.imag, 0.0) 135 self.assertEqual(cmath.nanj.real, 0.0) 136 self.assertTrue(math.isnan(cmath.nanj.imag)) 137 # Also check that the sign of all of these is positive: 138 self.assertEqual(math.copysign(1., cmath.nan.real), 1.) 139 self.assertEqual(math.copysign(1., cmath.nan.imag), 1.) 140 self.assertEqual(math.copysign(1., cmath.nanj.real), 1.) 141 self.assertEqual(math.copysign(1., cmath.nanj.imag), 1.) 142 143 # Check consistency with reprs. 144 self.assertEqual(repr(cmath.inf), "inf") 145 self.assertEqual(repr(cmath.infj), "infj") 146 self.assertEqual(repr(cmath.nan), "nan") 147 self.assertEqual(repr(cmath.nanj), "nanj") 148 149 def test_user_object(self): 150 # Test automatic calling of __complex__ and __float__ by cmath 151 # functions 152 153 # some random values to use as test values; we avoid values 154 # for which any of the functions in cmath is undefined 155 # (i.e. 0., 1., -1., 1j, -1j) or would cause overflow 156 cx_arg = 4.419414439 + 1.497100113j 157 flt_arg = -6.131677725 158 159 # a variety of non-complex numbers, used to check that 160 # non-complex return values from __complex__ give an error 161 non_complexes = ["not complex", 1, 5, 2., None, 162 object(), NotImplemented] 163 164 # Now we introduce a variety of classes whose instances might 165 # end up being passed to the cmath functions 166 167 # usual case: new-style class implementing __complex__ 168 class MyComplex: 169 def __init__(self, value): 170 self.value = value 171 def __complex__(self): 172 return self.value 173 174 # classes for which __complex__ raises an exception 175 class SomeException(Exception): 176 pass 177 class MyComplexException: 178 def __complex__(self): 179 raise SomeException 180 181 # some classes not providing __float__ or __complex__ 182 class NeitherComplexNorFloat(object): 183 pass 184 class Index: 185 def __int__(self): return 2 186 def __index__(self): return 2 187 class MyInt: 188 def __int__(self): return 2 189 190 # other possible combinations of __float__ and __complex__ 191 # that should work 192 class FloatAndComplex: 193 def __float__(self): 194 return flt_arg 195 def __complex__(self): 196 return cx_arg 197 class JustFloat: 198 def __float__(self): 199 return flt_arg 200 201 for f in self.test_functions: 202 # usual usage 203 self.assertEqual(f(MyComplex(cx_arg)), f(cx_arg)) 204 # other combinations of __float__ and __complex__ 205 self.assertEqual(f(FloatAndComplex()), f(cx_arg)) 206 self.assertEqual(f(JustFloat()), f(flt_arg)) 207 self.assertEqual(f(Index()), f(int(Index()))) 208 # TypeError should be raised for classes not providing 209 # either __complex__ or __float__, even if they provide 210 # __int__ or __index__: 211 self.assertRaises(TypeError, f, NeitherComplexNorFloat()) 212 self.assertRaises(TypeError, f, MyInt()) 213 # non-complex return value from __complex__ -> TypeError 214 for bad_complex in non_complexes: 215 self.assertRaises(TypeError, f, MyComplex(bad_complex)) 216 # exceptions in __complex__ should be propagated correctly 217 self.assertRaises(SomeException, f, MyComplexException()) 218 219 def test_input_type(self): 220 # ints should be acceptable inputs to all cmath 221 # functions, by virtue of providing a __float__ method 222 for f in self.test_functions: 223 for arg in [2, 2.]: 224 self.assertEqual(f(arg), f(arg.__float__())) 225 226 # but strings should give a TypeError 227 for f in self.test_functions: 228 for arg in ["a", "long_string", "0", "1j", ""]: 229 self.assertRaises(TypeError, f, arg) 230 231 def test_cmath_matches_math(self): 232 # check that corresponding cmath and math functions are equal 233 # for floats in the appropriate range 234 235 # test_values in (0, 1) 236 test_values = [0.01, 0.1, 0.2, 0.5, 0.9, 0.99] 237 238 # test_values for functions defined on [-1., 1.] 239 unit_interval = test_values + [-x for x in test_values] + \ 240 [0., 1., -1.] 241 242 # test_values for log, log10, sqrt 243 positive = test_values + [1.] + [1./x for x in test_values] 244 nonnegative = [0.] + positive 245 246 # test_values for functions defined on the whole real line 247 real_line = [0.] + positive + [-x for x in positive] 248 249 test_functions = { 250 'acos' : unit_interval, 251 'asin' : unit_interval, 252 'atan' : real_line, 253 'cos' : real_line, 254 'cosh' : real_line, 255 'exp' : real_line, 256 'log' : positive, 257 'log10' : positive, 258 'sin' : real_line, 259 'sinh' : real_line, 260 'sqrt' : nonnegative, 261 'tan' : real_line, 262 'tanh' : real_line} 263 264 for fn, values in test_functions.items(): 265 float_fn = getattr(math, fn) 266 complex_fn = getattr(cmath, fn) 267 for v in values: 268 z = complex_fn(v) 269 self.rAssertAlmostEqual(float_fn(v), z.real) 270 self.assertEqual(0., z.imag) 271 272 # test two-argument version of log with various bases 273 for base in [0.5, 2., 10.]: 274 for v in positive: 275 z = cmath.log(v, base) 276 self.rAssertAlmostEqual(math.log(v, base), z.real) 277 self.assertEqual(0., z.imag) 278 279 @requires_IEEE_754 280 def test_specific_values(self): 281 # Some tests need to be skipped on ancient OS X versions. 282 # See issue #27953. 283 SKIP_ON_TIGER = {'tan0064'} 284 285 osx_version = None 286 if sys.platform == 'darwin': 287 version_txt = platform.mac_ver()[0] 288 try: 289 osx_version = tuple(map(int, version_txt.split('.'))) 290 except ValueError: 291 pass 292 293 def rect_complex(z): 294 """Wrapped version of rect that accepts a complex number instead of 295 two float arguments.""" 296 return cmath.rect(z.real, z.imag) 297 298 def polar_complex(z): 299 """Wrapped version of polar that returns a complex number instead of 300 two floats.""" 301 return complex(*polar(z)) 302 303 for id, fn, ar, ai, er, ei, flags in parse_testfile(test_file): 304 arg = complex(ar, ai) 305 expected = complex(er, ei) 306 307 # Skip certain tests on OS X 10.4. 308 if osx_version is not None and osx_version < (10, 5): 309 if id in SKIP_ON_TIGER: 310 continue 311 312 if fn == 'rect': 313 function = rect_complex 314 elif fn == 'polar': 315 function = polar_complex 316 else: 317 function = getattr(cmath, fn) 318 if 'divide-by-zero' in flags or 'invalid' in flags: 319 try: 320 actual = function(arg) 321 except ValueError: 322 continue 323 else: 324 self.fail('ValueError not raised in test ' 325 '{}: {}(complex({!r}, {!r}))'.format(id, fn, ar, ai)) 326 327 if 'overflow' in flags: 328 try: 329 actual = function(arg) 330 except OverflowError: 331 continue 332 else: 333 self.fail('OverflowError not raised in test ' 334 '{}: {}(complex({!r}, {!r}))'.format(id, fn, ar, ai)) 335 336 actual = function(arg) 337 338 if 'ignore-real-sign' in flags: 339 actual = complex(abs(actual.real), actual.imag) 340 expected = complex(abs(expected.real), expected.imag) 341 if 'ignore-imag-sign' in flags: 342 actual = complex(actual.real, abs(actual.imag)) 343 expected = complex(expected.real, abs(expected.imag)) 344 345 # for the real part of the log function, we allow an 346 # absolute error of up to 2e-15. 347 if fn in ('log', 'log10'): 348 real_abs_err = 2e-15 349 else: 350 real_abs_err = 5e-323 351 352 error_message = ( 353 '{}: {}(complex({!r}, {!r}))\n' 354 'Expected: complex({!r}, {!r})\n' 355 'Received: complex({!r}, {!r})\n' 356 'Received value insufficiently close to expected value.' 357 ).format(id, fn, ar, ai, 358 expected.real, expected.imag, 359 actual.real, actual.imag) 360 self.rAssertAlmostEqual(expected.real, actual.real, 361 abs_err=real_abs_err, 362 msg=error_message) 363 self.rAssertAlmostEqual(expected.imag, actual.imag, 364 msg=error_message) 365 366 def check_polar(self, func): 367 def check(arg, expected): 368 got = func(arg) 369 for e, g in zip(expected, got): 370 self.rAssertAlmostEqual(e, g) 371 check(0, (0., 0.)) 372 check(1, (1., 0.)) 373 check(-1, (1., pi)) 374 check(1j, (1., pi / 2)) 375 check(-3j, (3., -pi / 2)) 376 inf = float('inf') 377 check(complex(inf, 0), (inf, 0.)) 378 check(complex(-inf, 0), (inf, pi)) 379 check(complex(3, inf), (inf, pi / 2)) 380 check(complex(5, -inf), (inf, -pi / 2)) 381 check(complex(inf, inf), (inf, pi / 4)) 382 check(complex(inf, -inf), (inf, -pi / 4)) 383 check(complex(-inf, inf), (inf, 3 * pi / 4)) 384 check(complex(-inf, -inf), (inf, -3 * pi / 4)) 385 nan = float('nan') 386 check(complex(nan, 0), (nan, nan)) 387 check(complex(0, nan), (nan, nan)) 388 check(complex(nan, nan), (nan, nan)) 389 check(complex(inf, nan), (inf, nan)) 390 check(complex(-inf, nan), (inf, nan)) 391 check(complex(nan, inf), (inf, nan)) 392 check(complex(nan, -inf), (inf, nan)) 393 394 def test_polar(self): 395 self.check_polar(polar) 396 397 @cpython_only 398 def test_polar_errno(self): 399 # Issue #24489: check a previously set C errno doesn't disturb polar() 400 _testcapi = import_helper.import_module('_testcapi') 401 def polar_with_errno_set(z): 402 _testcapi.set_errno(11) 403 try: 404 return polar(z) 405 finally: 406 _testcapi.set_errno(0) 407 self.check_polar(polar_with_errno_set) 408 409 def test_phase(self): 410 self.assertAlmostEqual(phase(0), 0.) 411 self.assertAlmostEqual(phase(1.), 0.) 412 self.assertAlmostEqual(phase(-1.), pi) 413 self.assertAlmostEqual(phase(-1.+1E-300j), pi) 414 self.assertAlmostEqual(phase(-1.-1E-300j), -pi) 415 self.assertAlmostEqual(phase(1j), pi/2) 416 self.assertAlmostEqual(phase(-1j), -pi/2) 417 418 # zeros 419 self.assertEqual(phase(complex(0.0, 0.0)), 0.0) 420 self.assertEqual(phase(complex(0.0, -0.0)), -0.0) 421 self.assertEqual(phase(complex(-0.0, 0.0)), pi) 422 self.assertEqual(phase(complex(-0.0, -0.0)), -pi) 423 424 # infinities 425 self.assertAlmostEqual(phase(complex(-INF, -0.0)), -pi) 426 self.assertAlmostEqual(phase(complex(-INF, -2.3)), -pi) 427 self.assertAlmostEqual(phase(complex(-INF, -INF)), -0.75*pi) 428 self.assertAlmostEqual(phase(complex(-2.3, -INF)), -pi/2) 429 self.assertAlmostEqual(phase(complex(-0.0, -INF)), -pi/2) 430 self.assertAlmostEqual(phase(complex(0.0, -INF)), -pi/2) 431 self.assertAlmostEqual(phase(complex(2.3, -INF)), -pi/2) 432 self.assertAlmostEqual(phase(complex(INF, -INF)), -pi/4) 433 self.assertEqual(phase(complex(INF, -2.3)), -0.0) 434 self.assertEqual(phase(complex(INF, -0.0)), -0.0) 435 self.assertEqual(phase(complex(INF, 0.0)), 0.0) 436 self.assertEqual(phase(complex(INF, 2.3)), 0.0) 437 self.assertAlmostEqual(phase(complex(INF, INF)), pi/4) 438 self.assertAlmostEqual(phase(complex(2.3, INF)), pi/2) 439 self.assertAlmostEqual(phase(complex(0.0, INF)), pi/2) 440 self.assertAlmostEqual(phase(complex(-0.0, INF)), pi/2) 441 self.assertAlmostEqual(phase(complex(-2.3, INF)), pi/2) 442 self.assertAlmostEqual(phase(complex(-INF, INF)), 0.75*pi) 443 self.assertAlmostEqual(phase(complex(-INF, 2.3)), pi) 444 self.assertAlmostEqual(phase(complex(-INF, 0.0)), pi) 445 446 # real or imaginary part NaN 447 for z in complex_nans: 448 self.assertTrue(math.isnan(phase(z))) 449 450 def test_abs(self): 451 # zeros 452 for z in complex_zeros: 453 self.assertEqual(abs(z), 0.0) 454 455 # infinities 456 for z in complex_infinities: 457 self.assertEqual(abs(z), INF) 458 459 # real or imaginary part NaN 460 self.assertEqual(abs(complex(NAN, -INF)), INF) 461 self.assertTrue(math.isnan(abs(complex(NAN, -2.3)))) 462 self.assertTrue(math.isnan(abs(complex(NAN, -0.0)))) 463 self.assertTrue(math.isnan(abs(complex(NAN, 0.0)))) 464 self.assertTrue(math.isnan(abs(complex(NAN, 2.3)))) 465 self.assertEqual(abs(complex(NAN, INF)), INF) 466 self.assertEqual(abs(complex(-INF, NAN)), INF) 467 self.assertTrue(math.isnan(abs(complex(-2.3, NAN)))) 468 self.assertTrue(math.isnan(abs(complex(-0.0, NAN)))) 469 self.assertTrue(math.isnan(abs(complex(0.0, NAN)))) 470 self.assertTrue(math.isnan(abs(complex(2.3, NAN)))) 471 self.assertEqual(abs(complex(INF, NAN)), INF) 472 self.assertTrue(math.isnan(abs(complex(NAN, NAN)))) 473 474 475 @requires_IEEE_754 476 def test_abs_overflows(self): 477 # result overflows 478 self.assertRaises(OverflowError, abs, complex(1.4e308, 1.4e308)) 479 480 def assertCEqual(self, a, b): 481 eps = 1E-7 482 if abs(a.real - b[0]) > eps or abs(a.imag - b[1]) > eps: 483 self.fail((a ,b)) 484 485 def test_rect(self): 486 self.assertCEqual(rect(0, 0), (0, 0)) 487 self.assertCEqual(rect(1, 0), (1., 0)) 488 self.assertCEqual(rect(1, -pi), (-1., 0)) 489 self.assertCEqual(rect(1, pi/2), (0, 1.)) 490 self.assertCEqual(rect(1, -pi/2), (0, -1.)) 491 492 def test_isfinite(self): 493 real_vals = [float('-inf'), -2.3, -0.0, 494 0.0, 2.3, float('inf'), float('nan')] 495 for x in real_vals: 496 for y in real_vals: 497 z = complex(x, y) 498 self.assertEqual(cmath.isfinite(z), 499 math.isfinite(x) and math.isfinite(y)) 500 501 def test_isnan(self): 502 self.assertFalse(cmath.isnan(1)) 503 self.assertFalse(cmath.isnan(1j)) 504 self.assertFalse(cmath.isnan(INF)) 505 self.assertTrue(cmath.isnan(NAN)) 506 self.assertTrue(cmath.isnan(complex(NAN, 0))) 507 self.assertTrue(cmath.isnan(complex(0, NAN))) 508 self.assertTrue(cmath.isnan(complex(NAN, NAN))) 509 self.assertTrue(cmath.isnan(complex(NAN, INF))) 510 self.assertTrue(cmath.isnan(complex(INF, NAN))) 511 512 def test_isinf(self): 513 self.assertFalse(cmath.isinf(1)) 514 self.assertFalse(cmath.isinf(1j)) 515 self.assertFalse(cmath.isinf(NAN)) 516 self.assertTrue(cmath.isinf(INF)) 517 self.assertTrue(cmath.isinf(complex(INF, 0))) 518 self.assertTrue(cmath.isinf(complex(0, INF))) 519 self.assertTrue(cmath.isinf(complex(INF, INF))) 520 self.assertTrue(cmath.isinf(complex(NAN, INF))) 521 self.assertTrue(cmath.isinf(complex(INF, NAN))) 522 523 @requires_IEEE_754 524 def testTanhSign(self): 525 for z in complex_zeros: 526 self.assertComplexesAreIdentical(cmath.tanh(z), z) 527 528 # The algorithm used for atan and atanh makes use of the system 529 # log1p function; If that system function doesn't respect the sign 530 # of zero, then atan and atanh will also have difficulties with 531 # the sign of complex zeros. 532 @requires_IEEE_754 533 def testAtanSign(self): 534 for z in complex_zeros: 535 self.assertComplexesAreIdentical(cmath.atan(z), z) 536 537 @requires_IEEE_754 538 def testAtanhSign(self): 539 for z in complex_zeros: 540 self.assertComplexesAreIdentical(cmath.atanh(z), z) 541 542 543class IsCloseTests(test_math.IsCloseTests): 544 isclose = cmath.isclose 545 546 def test_reject_complex_tolerances(self): 547 with self.assertRaises(TypeError): 548 self.isclose(1j, 1j, rel_tol=1j) 549 550 with self.assertRaises(TypeError): 551 self.isclose(1j, 1j, abs_tol=1j) 552 553 with self.assertRaises(TypeError): 554 self.isclose(1j, 1j, rel_tol=1j, abs_tol=1j) 555 556 def test_complex_values(self): 557 # test complex values that are close to within 12 decimal places 558 complex_examples = [(1.0+1.0j, 1.000000000001+1.0j), 559 (1.0+1.0j, 1.0+1.000000000001j), 560 (-1.0+1.0j, -1.000000000001+1.0j), 561 (1.0-1.0j, 1.0-0.999999999999j), 562 ] 563 564 self.assertAllClose(complex_examples, rel_tol=1e-12) 565 self.assertAllNotClose(complex_examples, rel_tol=1e-13) 566 567 def test_complex_near_zero(self): 568 # test values near zero that are near to within three decimal places 569 near_zero_examples = [(0.001j, 0), 570 (0.001, 0), 571 (0.001+0.001j, 0), 572 (-0.001+0.001j, 0), 573 (0.001-0.001j, 0), 574 (-0.001-0.001j, 0), 575 ] 576 577 self.assertAllClose(near_zero_examples, abs_tol=1.5e-03) 578 self.assertAllNotClose(near_zero_examples, abs_tol=0.5e-03) 579 580 self.assertIsClose(0.001-0.001j, 0.001+0.001j, abs_tol=2e-03) 581 self.assertIsNotClose(0.001-0.001j, 0.001+0.001j, abs_tol=1e-03) 582 583 def test_complex_special(self): 584 self.assertIsNotClose(INF, INF*1j) 585 self.assertIsNotClose(INF*1j, INF) 586 self.assertIsNotClose(INF, -INF) 587 self.assertIsNotClose(-INF, INF) 588 self.assertIsNotClose(0, INF) 589 self.assertIsNotClose(0, INF*1j) 590 591 592if __name__ == "__main__": 593 unittest.main() 594