test_complex.py 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476
  1. import unittest
  2. from random import random
  3. from math import atan2, isnan, copysign
  4. import operator
  5. INF = float("inf")
  6. NAN = float("nan")
  7. # These tests ensure that complex math does the right thing
  8. class ComplexTest(unittest.TestCase):
  9. def assertAlmostEqual(self, a, b):
  10. if isinstance(a, complex):
  11. if isinstance(b, complex):
  12. unittest.TestCase.assertAlmostEqual(self, a.real, b.real)
  13. unittest.TestCase.assertAlmostEqual(self, a.imag, b.imag)
  14. else:
  15. unittest.TestCase.assertAlmostEqual(self, a.real, b)
  16. unittest.TestCase.assertAlmostEqual(self, a.imag, 0.)
  17. else:
  18. if isinstance(b, complex):
  19. unittest.TestCase.assertAlmostEqual(self, a, b.real)
  20. unittest.TestCase.assertAlmostEqual(self, 0., b.imag)
  21. else:
  22. unittest.TestCase.assertAlmostEqual(self, a, b)
  23. def assertCloseAbs(self, x, y, eps=1e-9):
  24. """Return true iff floats x and y "are close"."""
  25. # put the one with larger magnitude second
  26. if abs(x) > abs(y):
  27. x, y = y, x
  28. if y == 0:
  29. return abs(x) < eps
  30. if x == 0:
  31. return abs(y) < eps
  32. # check that relative difference < eps
  33. self.assertTrue(abs((x-y)/y) < eps)
  34. def assertFloatsAreIdentical(self, x, y):
  35. """assert that floats x and y are identical, in the sense that:
  36. (1) both x and y are nans, or
  37. (2) both x and y are infinities, with the same sign, or
  38. (3) both x and y are zeros, with the same sign, or
  39. (4) x and y are both finite and nonzero, and x == y
  40. """
  41. msg = 'floats {!r} and {!r} are not identical'
  42. if isnan(x) or isnan(y):
  43. if isnan(x) and isnan(y):
  44. return
  45. elif x == y:
  46. if x != 0.0:
  47. return
  48. # both zero; check that signs match
  49. elif copysign(1.0, x) == copysign(1.0, y):
  50. return
  51. else:
  52. msg += ': zeros have different signs'
  53. self.fail(msg.format(x, y))
  54. def assertClose(self, x, y, eps=1e-9):
  55. """Return true iff complexes x and y "are close"."""
  56. self.assertCloseAbs(x.real, y.real, eps)
  57. self.assertCloseAbs(x.imag, y.imag, eps)
  58. def check_div(self, x, y):
  59. """Compute complex z=x*y, and check that z/x==y and z/y==x."""
  60. z = x * y
  61. if x != 0:
  62. q = z / x
  63. self.assertClose(q, y)
  64. q = z.__truediv__(x)
  65. self.assertClose(q, y)
  66. if y != 0:
  67. q = z / y
  68. self.assertClose(q, x)
  69. q = z.__truediv__(y)
  70. self.assertClose(q, x)
  71. def test_truediv(self):
  72. simple_real = [float(i) for i in range(-5, 6)]
  73. simple_complex = [complex(x, y) for x in simple_real for y in simple_real]
  74. for x in simple_complex:
  75. for y in simple_complex:
  76. self.check_div(x, y)
  77. # A naive complex division algorithm (such as in 2.0) is very prone to
  78. # nonsense errors for these (overflows and underflows).
  79. self.check_div(complex(1e200, 1e200), 1+0j)
  80. self.check_div(complex(1e-200, 1e-200), 1+0j)
  81. # Just for fun.
  82. for i in range(100):
  83. self.check_div(complex(random(), random()),
  84. complex(random(), random()))
  85. self.assertRaises(ZeroDivisionError, complex.__truediv__, 1+1j, 0+0j)
  86. # FIXME: The following currently crashes on Alpha
  87. # self.assertRaises(OverflowError, pow, 1e200+1j, 1e200+1j)
  88. self.assertAlmostEqual(complex.__truediv__(2+0j, 1+1j), 1-1j)
  89. self.assertRaises(ZeroDivisionError, complex.__truediv__, 1+1j, 0+0j)
  90. for denom_real, denom_imag in [(0, NAN), (NAN, 0), (NAN, NAN)]:
  91. z = complex(0, 0) / complex(denom_real, denom_imag)
  92. self.assertTrue(isnan(z.real))
  93. self.assertTrue(isnan(z.imag))
  94. def test_floordiv(self):
  95. self.assertRaises(TypeError, complex.__floordiv__, 3+0j, 1.5+0j)
  96. self.assertRaises(TypeError, complex.__floordiv__, 3+0j, 0+0j)
  97. def test_richcompare(self):
  98. self.assertIs(complex.__eq__(1+1j, 1 << 10000), False)
  99. self.assertRaises(TypeError, complex.__lt__, 1+1j, None)
  100. self.assertIs(complex.__eq__(1+1j, 1+1j), True)
  101. self.assertIs(complex.__eq__(1+1j, 2+2j), False)
  102. self.assertIs(complex.__ne__(1+1j, 1+1j), False)
  103. self.assertIs(complex.__ne__(1+1j, 2+2j), True)
  104. self.assertFalse(complex.__eq__(1j, None), False)
  105. self.assertFalse(complex.__eq__(1j, NotImplemented), False)
  106. for i in range(1, 100):
  107. f = i / 100.0
  108. self.assertIs(complex.__eq__(f+0j, f), True)
  109. self.assertIs(complex.__ne__(f+0j, f), False)
  110. self.assertIs(complex.__eq__(complex(f, f), f), False)
  111. self.assertIs(complex.__ne__(complex(f, f), f), True)
  112. self.assertRaises(TypeError, complex.__lt__, 1+1j, 2+2j)
  113. self.assertRaises(TypeError, complex.__le__, 1+1j, 2+2j)
  114. self.assertRaises(TypeError, complex.__gt__, 1+1j, 2+2j)
  115. self.assertRaises(TypeError, complex.__ge__, 1+1j, 2+2j)
  116. self.assertRaises(TypeError, operator.lt, 1+1j, 2+2j)
  117. self.assertRaises(TypeError, operator.le, 1+1j, 2+2j)
  118. self.assertRaises(TypeError, operator.gt, 1+1j, 2+2j)
  119. self.assertRaises(TypeError, operator.ge, 1+1j, 2+2j)
  120. self.assertIs(operator.eq(1+1j, 1+1j), True)
  121. self.assertIs(operator.eq(1+1j, 2+2j), False)
  122. self.assertIs(operator.ne(1+1j, 1+1j), False)
  123. self.assertIs(operator.ne(1+1j, 2+2j), True)
  124. #def test_richcompare_boundaries(self):
  125. #def check(n, deltas, is_equal, imag=0.0):
  126. #for delta in deltas:
  127. # i = n + delta
  128. #z = complex(i, imag)
  129. #self.assertIs(complex.__eq__(z, i), is_equal(delta))
  130. #self.assertIs(complex.__ne__(z, i), not is_equal(delta))
  131. # currently failing, though normal ones are working, maybe due to
  132. # currently buggy div operation
  133. # For IEEE-754 doubles the following should hold:
  134. # x in [2 ** (52 + i), 2 ** (53 + i + 1)] -> x mod 2 ** i == 0
  135. # where the interval is representable, of course.
  136. #for i in range(1, 10):
  137. # pow = 52 + i
  138. # mult = 2 ** i
  139. # check(2 ** pow, range(1, 101), lambda delta: delta % mult == 0)
  140. # check(2 ** pow, range(1, 101), lambda delta: False, float(i))
  141. #check(2 ** 53, range(-100, 0), lambda delta: True)
  142. def test_mod(self):
  143. # % is no longer supported on complex numbers
  144. self.assertRaises(TypeError, (1+1j).__mod__, 0+0j)
  145. self.assertRaises(TypeError, lambda: (3.33+4.43j) % 0)
  146. self.assertRaises(TypeError, (1+1j).__mod__, 4.3j)
  147. def test_divmod(self):
  148. # actually divmod is deprecated, though we have still the impl.
  149. #self.assertRaises(TypeError, divmod, 1+1j, 1+0j)
  150. #self.assertRaises(TypeError, divmod, 1+1j, 0+0j)
  151. # dummy test
  152. c = 1+1j
  153. self.assertEqual(str(c.__divmod__), "<bound method complex.<native JS> of (1.0000000000000000+1.0000000000000000j)>")
  154. def test_pow(self):
  155. self.assertAlmostEqual(pow(1+1j, 0+0j), 1.0)
  156. self.assertAlmostEqual(pow(0+0j, 2+0j), 0.0)
  157. self.assertRaises(ZeroDivisionError, pow, 0+0j, 1j)
  158. self.assertAlmostEqual(pow(1j, -1), 1/1j)
  159. self.assertAlmostEqual(pow(1j, 200), 1)
  160. self.assertRaises(ValueError, pow, 1+1j, 1+1j, 1+1j)
  161. a = 3.33+4.43j
  162. self.assertEqual(a ** 0j, 1)
  163. self.assertEqual(a ** 0.+0.j, 1)
  164. self.assertEqual(3j ** 0j, 1)
  165. self.assertEqual(3j ** 0, 1)
  166. try:
  167. 0j ** a
  168. except ZeroDivisionError:
  169. pass
  170. else:
  171. self.fail("should fail 0.0 to negative or complex power")
  172. try:
  173. 0j ** (3-2j)
  174. except ZeroDivisionError:
  175. pass
  176. else:
  177. self.fail("should fail 0.0 to negative or complex power")
  178. # The following is used to exercise certain code paths
  179. self.assertEqual(a ** 105, a ** 105)
  180. self.assertEqual(a ** -105, a ** -105)
  181. self.assertEqual(a ** -30, a ** -30)
  182. self.assertEqual(0.0j ** 0, 1)
  183. b = 5.1+2.3j
  184. self.assertRaises(ValueError, pow, a, b, 0)
  185. def test_boolcontext(self):
  186. for i in range(100):
  187. self.assertTrue(complex(random() + 1e-6, random() + 1e-6))
  188. self.assertTrue(not complex(0.0, 0.0))
  189. def test_conjugate(self):
  190. self.assertClose(complex(5.3, 9.8).conjugate(), 5.3-9.8j)
  191. def test_constructor(self):
  192. class OS:
  193. def __init__(self, value): self.value = value
  194. def __complex__(self): return self.value
  195. class NS(object):
  196. def __init__(self, value): self.value = value
  197. def __complex__(self): return self.value
  198. self.assertEqual(complex(OS(1+10j)), 1+10j)
  199. self.assertEqual(complex(NS(1+10j)), 1+10j)
  200. self.assertRaises(TypeError, complex, OS(None))
  201. self.assertRaises(TypeError, complex, NS(None))
  202. self.assertRaises(TypeError, complex, {})
  203. self.assertRaises(TypeError, complex, NS(1.5))
  204. self.assertRaises(TypeError, complex, NS(1))
  205. self.assertAlmostEqual(complex("1+10j"), 1+10j)
  206. self.assertAlmostEqual(complex(10), 10+0j)
  207. self.assertAlmostEqual(complex(10.0), 10+0j)
  208. self.assertAlmostEqual(complex(10), 10+0j)
  209. self.assertAlmostEqual(complex(10+0j), 10+0j)
  210. self.assertAlmostEqual(complex(1, 10), 1+10j)
  211. self.assertAlmostEqual(complex(1, 10), 1+10j)
  212. self.assertAlmostEqual(complex(1, 10.0), 1+10j)
  213. self.assertAlmostEqual(complex(1, 10), 1+10j)
  214. self.assertAlmostEqual(complex(1, 10), 1+10j)
  215. self.assertAlmostEqual(complex(1, 10.0), 1+10j)
  216. self.assertAlmostEqual(complex(1.0, 10), 1+10j)
  217. self.assertAlmostEqual(complex(1.0, 10), 1+10j)
  218. self.assertAlmostEqual(complex(1.0, 10.0), 1+10j)
  219. self.assertAlmostEqual(complex(3.14+0j), 3.14+0j)
  220. self.assertAlmostEqual(complex(3.14), 3.14+0j)
  221. self.assertAlmostEqual(complex(314), 314.0+0j)
  222. self.assertAlmostEqual(complex(314), 314.0+0j)
  223. self.assertAlmostEqual(complex(3.14+0j, 0j), 3.14+0j)
  224. self.assertAlmostEqual(complex(3.14, 0.0), 3.14+0j)
  225. self.assertAlmostEqual(complex(314, 0), 314.0+0j)
  226. self.assertAlmostEqual(complex(314, 0), 314.0+0j)
  227. self.assertAlmostEqual(complex(0j, 3.14j), -3.14+0j)
  228. self.assertAlmostEqual(complex(0.0, 3.14j), -3.14+0j)
  229. self.assertAlmostEqual(complex(0j, 3.14), 3.14j)
  230. self.assertAlmostEqual(complex(0.0, 3.14), 3.14j)
  231. self.assertAlmostEqual(complex("1"), 1+0j)
  232. self.assertAlmostEqual(complex("1j"), 1j)
  233. self.assertAlmostEqual(complex(), 0)
  234. self.assertAlmostEqual(complex("-1"), -1)
  235. self.assertAlmostEqual(complex("+1"), +1)
  236. self.assertAlmostEqual(complex("(1+2j)"), 1+2j)
  237. self.assertAlmostEqual(complex("(1.3+2.2j)"), 1.3+2.2j)
  238. self.assertAlmostEqual(complex("3.14+1J"), 3.14+1j)
  239. self.assertAlmostEqual(complex(" ( +3.14-6J )"), 3.14-6j)
  240. self.assertAlmostEqual(complex(" ( +3.14-J )"), 3.14-1j)
  241. self.assertAlmostEqual(complex(" ( +3.14+j )"), 3.14+1j)
  242. self.assertAlmostEqual(complex("J"), 1j)
  243. self.assertAlmostEqual(complex("( j )"), 1j)
  244. self.assertAlmostEqual(complex("+J"), 1j)
  245. self.assertAlmostEqual(complex("( -j)"), -1j)
  246. self.assertAlmostEqual(complex('1e-500'), 0.0 + 0.0j)
  247. self.assertAlmostEqual(complex('-1e-500j'), 0.0 - 0.0j)
  248. self.assertAlmostEqual(complex('-1e-500+1e-500j'), -0.0 + 0.0j)
  249. # class complex2(complex): pass
  250. # self.assertAlmostEqual(complex(complex2(1+1j)), 1+1j)
  251. # currently no support for keyword arguments
  252. #self.assertAlmostEqual(complex(real=17, imag=23), 17+23j)
  253. #self.assertAlmostEqual(complex(real=17+23j), 17+23j)
  254. #self.assertAlmostEqual(complex(real=17+23j, imag=23), 17+46j)
  255. #self.assertAlmostEqual(complex(real=1+2j, imag=3+4j), -3+5j)
  256. # check that the sign of a zero in the real or imaginary part
  257. # is preserved when constructing from two floats. (These checks
  258. # are harmless on systems without support for signed zeros.)
  259. def split_zeros(x):
  260. """Function that produces different results for 0. and -0."""
  261. return atan2(x, -1.)
  262. self.assertEqual(split_zeros(complex(1., 0.).imag), split_zeros(0.))
  263. self.assertEqual(split_zeros(complex(1., -0.).imag), split_zeros(-0.))
  264. self.assertEqual(split_zeros(complex(0., 1.).real), split_zeros(0.))
  265. self.assertEqual(split_zeros(complex(-0., 1.).real), split_zeros(-0.))
  266. c = 3.14 + 1j
  267. self.assertTrue(complex(c) is c)
  268. del c
  269. self.assertRaises(TypeError, complex, "1", "1")
  270. self.assertRaises(TypeError, complex, 1, "1")
  271. # SF bug 543840: complex(string) accepts strings with \0
  272. # Fixed in 2.3.
  273. self.assertRaises(ValueError, complex, '1+1j\0j')
  274. self.assertRaises(TypeError, int, 5+3j)
  275. self.assertRaises(TypeError, int, 5+3j)
  276. self.assertRaises(TypeError, float, 5+3j)
  277. self.assertRaises(ValueError, complex, "")
  278. self.assertRaises(TypeError, complex, None)
  279. #self.assertRaisesRegex(TypeError, "not 'NoneType'", complex, None)
  280. self.assertRaises(ValueError, complex, "\0")
  281. self.assertRaises(ValueError, complex, "3\09")
  282. self.assertRaises(TypeError, complex, "1", "2")
  283. self.assertRaises(TypeError, complex, "1", 42)
  284. self.assertRaises(TypeError, complex, 1, "2")
  285. self.assertRaises(ValueError, complex, "1+")
  286. self.assertRaises(ValueError, complex, "1+1j+1j")
  287. self.assertRaises(ValueError, complex, "--")
  288. self.assertRaises(ValueError, complex, "(1+2j")
  289. self.assertRaises(ValueError, complex, "1+2j)")
  290. self.assertRaises(ValueError, complex, "1+(2j)")
  291. self.assertRaises(ValueError, complex, "(1+2j)123")
  292. self.assertRaises(ValueError, complex, "x")
  293. self.assertRaises(ValueError, complex, "1j+2")
  294. self.assertRaises(ValueError, complex, "1e1ej")
  295. self.assertRaises(ValueError, complex, "1e++1ej")
  296. self.assertRaises(ValueError, complex, ")1+2j(")
  297. # the following three are accepted by Python 2.6
  298. self.assertRaises(ValueError, complex, "1..1j")
  299. self.assertRaises(ValueError, complex, "1.11.1j")
  300. self.assertRaises(ValueError, complex, "1e1.1j")
  301. # check that complex accepts long unicode strings
  302. self.assertEqual(type(complex("1"*500)), complex)
  303. # check whitespace processing
  304. # self.assertEqual(complex('\N{EM SPACE}(\N{EN SPACE}1+1j ) '), 1+1j)
  305. # FIXME: subclassing exceptions is not really working!
  306. #class EvilExc(Exception):
  307. # pass
  308. #
  309. #class evilcomplex:
  310. # def __complex__(self):
  311. # raise EvilExc
  312. #self.assertRaises(EvilExc, complex, evilcomplex())
  313. class float2:
  314. def __init__(self, value):
  315. self.value = value
  316. def __float__(self):
  317. return self.value
  318. # FIXME: currently complex does not call internal __float__ method
  319. # FIXME: complex does not support keyword args
  320. self.assertAlmostEqual(complex(float2(42.)), 42)
  321. #self.assertAlmostEqual(complex(real=float2(17.), imag=float2(23.)), 17+23j)
  322. #self.assertRaises(TypeError, complex, float2(None))
  323. #class complex0(complex):
  324. # """Test usage of __complex__() when inheriting from 'complex'"""
  325. # def __complex__(self):
  326. # return 42j
  327. #class complex1(complex):
  328. # """Test usage of __complex__() with a __new__() method"""
  329. # def __new__(self, value=0j):
  330. # return complex.__new__(self, 2*value)
  331. # def __complex__(self):
  332. # return self
  333. #class complex2(complex):
  334. # """Make sure that __complex__() calls fail if anything other than a
  335. # complex is returned"""
  336. # def __complex__(self):
  337. # return None
  338. #self.assertAlmostEqual(complex(complex0(1j)), 42j)
  339. #self.assertAlmostEqual(complex(complex1(1j)), 2j)
  340. #self.assertRaises(TypeError, complex, complex2(1j))
  341. def test_hash(self):
  342. for x in range(-30, 30):
  343. self.assertEqual(hash(x), hash(complex(x, 0)))
  344. x /= 3.0 # now check against floating point
  345. self.assertEqual(hash(x), hash(complex(x, 0.)))
  346. def test_abs(self):
  347. nums = [complex(x/3., y/7.) for x in range(-9, 9) for y in range(-9, 9)]
  348. for num in nums:
  349. self.assertAlmostEqual((num.real**2 + num.imag**2) ** 0.5, abs(num))
  350. def test_repr_str(self):
  351. # this test case is actually working but failing nevertheless o.O?
  352. #self.assertNotEqual(len(str(-(1+0j))), len('(-1+-0j)'))
  353. self.assertEqual(str(complex(1., INF)), "(1+infj)")
  354. self.assertEqual(str(complex(1., -INF)), "(1-infj)")
  355. self.assertEqual(str(complex(INF, 1)), "(inf+1j)")
  356. self.assertEqual(str(complex(-INF, INF)), "(-inf+infj)")
  357. self.assertEqual(str(complex(NAN, 1)), "(nan+1j)")
  358. self.assertEqual(str(complex(1, NAN)), "(1+nanj)")
  359. self.assertEqual(str(complex(NAN, NAN)), "(nan+nanj)")
  360. self.assertEqual(str(complex(0, INF)), "infj")
  361. self.assertEqual(str(complex(0, -INF)), "-infj")
  362. self.assertEqual(str(complex(0, NAN)), "nanj")
  363. def test_neg(self):
  364. self.assertEqual(-(1+6j), -1-6j)
  365. def test_getnewargs(self):
  366. self.assertEqual((1+2j).__getnewargs__(), (1.0, 2.0))
  367. self.assertEqual((1-2j).__getnewargs__(), (1.0, -2.0))
  368. self.assertEqual((2j).__getnewargs__(), (0.0, 2.0))
  369. self.assertEqual((-0j).__getnewargs__(), (0.0, -0.0))
  370. self.assertEqual(complex(0, INF).__getnewargs__(), (0.0, INF))
  371. self.assertEqual(complex(INF, 0).__getnewargs__(), (INF, 0.0))
  372. def test_plus_minus_0j(self):
  373. # test that -0j and 0j literals are not identified
  374. z1, z2 = 0j, -0j
  375. self.assertEqual(atan2(z1.imag, -1.), atan2(0., -1.))
  376. self.assertEqual(atan2(z2.imag, -1.), atan2(-0., -1.))
  377. def test_negated_imaginary_literal(self):
  378. z0 = -0j
  379. z1 = -7j
  380. z2 = -1e1000j
  381. # Note: In versions of Python < 3.2, a negated imaginary literal
  382. # accidentally ended up with real part 0.0 instead of -0.0, thanks to a
  383. # modification during CST -> AST translation (see issue #9011). That's
  384. # fixed in Python 3.2.
  385. self.assertFloatsAreIdentical(z0.real, -0.0)
  386. self.assertFloatsAreIdentical(z0.imag, -0.0)
  387. self.assertFloatsAreIdentical(z1.real, -0.0)
  388. self.assertFloatsAreIdentical(z1.imag, -7.0)
  389. self.assertFloatsAreIdentical(z2.real, -0.0)
  390. self.assertFloatsAreIdentical(z2.imag, -INF)
  391. def test_overflow(self):
  392. self.assertEqual(complex("1e500"), complex(INF, 0.0))
  393. self.assertEqual(complex("-1e500j"), complex(0.0, -INF))
  394. self.assertEqual(complex("-1e500+1.8e308j"), complex(-INF, INF))
  395. def test_repr_roundtrip(self):
  396. vals = [0.0, 1e-500, 1e-315, 1e-200, 0.0123, 3.1415, 1e50, INF, NAN]
  397. vals += [-v for v in vals]
  398. # complex(repr(z)) should recover z exactly, even for complex
  399. # numbers involving an infinity, nan, or negative zero
  400. for x in vals:
  401. for y in vals:
  402. z = complex(x, y)
  403. roundtrip = complex(repr(z))
  404. self.assertFloatsAreIdentical(z.real, roundtrip.real)
  405. self.assertFloatsAreIdentical(z.imag, roundtrip.imag)
  406. # Removed some tests that require eval()
  407. def test_main():
  408. unittest.main()
  409. if __name__ == "__main__":
  410. test_main()