blob: 035f52403c3f4b8918fd32bcbb103ca4d022eeba [file] [log] [blame]
Walter Dörwald5301d9c2003-08-05 15:55:38 +00001import unittest, os
Walter Dörwald5edd7852003-06-18 14:26:18 +00002from test import test_support
3
4import warnings
5warnings.filterwarnings(
6 "ignore",
7 category=DeprecationWarning,
8 message=".*complex divmod.*are deprecated"
9)
10
Tim Peters0f336042001-03-18 08:21:57 +000011from random import random
12
Walter Dörwald5edd7852003-06-18 14:26:18 +000013# These tests ensure that complex math does the right thing
Fred Drake68773e72001-12-13 19:57:53 +000014
Walter Dörwald5edd7852003-06-18 14:26:18 +000015class ComplexTest(unittest.TestCase):
Tim Peters0f336042001-03-18 08:21:57 +000016
Walter Dörwald5edd7852003-06-18 14:26:18 +000017 def assertAlmostEqual(self, a, b):
18 if isinstance(a, complex):
19 if isinstance(b, complex):
20 unittest.TestCase.assertAlmostEqual(self, a.real, b.real)
21 unittest.TestCase.assertAlmostEqual(self, a.imag, b.imag)
22 else:
23 unittest.TestCase.assertAlmostEqual(self, a.real, b)
24 unittest.TestCase.assertAlmostEqual(self, a.imag, 0.)
25 else:
26 if isinstance(b, complex):
27 unittest.TestCase.assertAlmostEqual(self, a, b.real)
28 unittest.TestCase.assertAlmostEqual(self, 0., b.imag)
29 else:
30 unittest.TestCase.assertAlmostEqual(self, a, b)
Tim Peters0f336042001-03-18 08:21:57 +000031
Walter Dörwald5edd7852003-06-18 14:26:18 +000032 def assertCloseAbs(self, x, y, eps=1e-9):
33 """Return true iff floats x and y "are close\""""
34 # put the one with larger magnitude second
35 if abs(x) > abs(y):
36 x, y = y, x
37 if y == 0:
38 return abs(x) < eps
39 if x == 0:
40 return abs(y) < eps
41 # check that relative difference < eps
42 self.assert_(abs((x-y)/y) < eps)
Tim Petersc5b235c2001-09-06 23:00:21 +000043
Walter Dörwald5edd7852003-06-18 14:26:18 +000044 def assertClose(self, x, y, eps=1e-9):
45 """Return true iff complexes x and y "are close\""""
46 self.assertCloseAbs(x.real, y.real, eps)
47 self.assertCloseAbs(x.imag, y.imag, eps)
Tim Peters0f336042001-03-18 08:21:57 +000048
Walter Dörwald5edd7852003-06-18 14:26:18 +000049 def assertIs(self, a, b):
50 self.assert_(a is b)
Tim Peters0f336042001-03-18 08:21:57 +000051
Walter Dörwald5edd7852003-06-18 14:26:18 +000052 def check_div(self, x, y):
53 """Compute complex z=x*y, and check that z/x==y and z/y==x."""
54 z = x * y
55 if x != 0:
56 q = z / x
57 self.assertClose(q, y)
Walter Dörwaldb27cca62003-08-05 15:34:34 +000058 q = z.__truediv__(x)
59 self.assertClose(q, y)
Walter Dörwald5edd7852003-06-18 14:26:18 +000060 if y != 0:
61 q = z / y
62 self.assertClose(q, x)
Walter Dörwaldb27cca62003-08-05 15:34:34 +000063 q = z.__truediv__(y)
64 self.assertClose(q, x)
Tim Peters0f336042001-03-18 08:21:57 +000065
Neal Norwitzbcc0db82006-03-24 08:14:36 +000066 def test_truediv(self):
Walter Dörwald5edd7852003-06-18 14:26:18 +000067 simple_real = [float(i) for i in xrange(-5, 6)]
68 simple_complex = [complex(x, y) for x in simple_real for y in simple_real]
69 for x in simple_complex:
70 for y in simple_complex:
71 self.check_div(x, y)
Tim Peters0f336042001-03-18 08:21:57 +000072
Walter Dörwald5edd7852003-06-18 14:26:18 +000073 # A naive complex division algorithm (such as in 2.0) is very prone to
74 # nonsense errors for these (overflows and underflows).
75 self.check_div(complex(1e200, 1e200), 1+0j)
76 self.check_div(complex(1e-200, 1e-200), 1+0j)
Tim Peters0f336042001-03-18 08:21:57 +000077
Walter Dörwald5edd7852003-06-18 14:26:18 +000078 # Just for fun.
79 for i in xrange(100):
80 self.check_div(complex(random(), random()),
81 complex(random(), random()))
Neal Norwitzfc37af82001-12-29 01:02:21 +000082
Neal Norwitzbcc0db82006-03-24 08:14:36 +000083 self.assertRaises(ZeroDivisionError, complex.__truediv__, 1+1j, 0+0j)
Walter Dörwald5edd7852003-06-18 14:26:18 +000084 # FIXME: The following currently crashes on Alpha
85 # self.assertRaises(OverflowError, pow, 1e200+1j, 1e200+1j)
Neal Norwitzfc37af82001-12-29 01:02:21 +000086
Walter Dörwald5edd7852003-06-18 14:26:18 +000087 def test_truediv(self):
88 self.assertAlmostEqual(complex.__truediv__(2+0j, 1+1j), 1-1j)
89 self.assertRaises(ZeroDivisionError, complex.__truediv__, 1+1j, 0+0j)
Neal Norwitz5a0f0102001-12-29 14:31:46 +000090
Walter Dörwald5edd7852003-06-18 14:26:18 +000091 def test_floordiv(self):
92 self.assertAlmostEqual(complex.__floordiv__(3+0j, 1.5+0j), 2)
93 self.assertRaises(ZeroDivisionError, complex.__floordiv__, 3+0j, 0+0j)
Neal Norwitzfc37af82001-12-29 01:02:21 +000094
Walter Dörwald5edd7852003-06-18 14:26:18 +000095 def test_coerce(self):
96 self.assertRaises(OverflowError, complex.__coerce__, 1+1j, 1L<<10000)
Neal Norwitzfc37af82001-12-29 01:02:21 +000097
Walter Dörwald5edd7852003-06-18 14:26:18 +000098 def test_richcompare(self):
99 self.assertRaises(OverflowError, complex.__eq__, 1+1j, 1L<<10000)
100 self.assertEqual(complex.__lt__(1+1j, None), NotImplemented)
101 self.assertIs(complex.__eq__(1+1j, 1+1j), True)
102 self.assertIs(complex.__eq__(1+1j, 2+2j), False)
103 self.assertIs(complex.__ne__(1+1j, 1+1j), False)
104 self.assertIs(complex.__ne__(1+1j, 2+2j), True)
105 self.assertRaises(TypeError, complex.__lt__, 1+1j, 2+2j)
106 self.assertRaises(TypeError, complex.__le__, 1+1j, 2+2j)
107 self.assertRaises(TypeError, complex.__gt__, 1+1j, 2+2j)
108 self.assertRaises(TypeError, complex.__ge__, 1+1j, 2+2j)
Tim Peters0f336042001-03-18 08:21:57 +0000109
Walter Dörwald5edd7852003-06-18 14:26:18 +0000110 def test_mod(self):
111 self.assertRaises(ZeroDivisionError, (1+1j).__mod__, 0+0j)
112
Walter Dörwaldf393fc62003-07-15 18:47:27 +0000113 a = 3.33+4.43j
114 try:
115 a % 0
116 except ZeroDivisionError:
117 pass
118 else:
119 self.fail("modulo parama can't be 0")
120
Walter Dörwald5edd7852003-06-18 14:26:18 +0000121 def test_divmod(self):
122 self.assertRaises(ZeroDivisionError, divmod, 1+1j, 0+0j)
123
124 def test_pow(self):
125 self.assertAlmostEqual(pow(1+1j, 0+0j), 1.0)
126 self.assertAlmostEqual(pow(0+0j, 2+0j), 0.0)
127 self.assertRaises(ZeroDivisionError, pow, 0+0j, 1j)
128 self.assertAlmostEqual(pow(1j, -1), 1/1j)
129 self.assertAlmostEqual(pow(1j, 200), 1)
130 self.assertRaises(ValueError, pow, 1+1j, 1+1j, 1+1j)
131
Walter Dörwaldf393fc62003-07-15 18:47:27 +0000132 a = 3.33+4.43j
133 self.assertEqual(a ** 0j, 1)
134 self.assertEqual(a ** 0.+0.j, 1)
135
136 self.assertEqual(3j ** 0j, 1)
137 self.assertEqual(3j ** 0, 1)
138
139 try:
140 0j ** a
141 except ZeroDivisionError:
142 pass
143 else:
144 self.fail("should fail 0.0 to negative or complex power")
145
146 try:
147 0j ** (3-2j)
148 except ZeroDivisionError:
149 pass
150 else:
151 self.fail("should fail 0.0 to negative or complex power")
152
153 # The following is used to exercise certain code paths
154 self.assertEqual(a ** 105, a ** 105)
155 self.assertEqual(a ** -105, a ** -105)
156 self.assertEqual(a ** -30, a ** -30)
157
158 self.assertEqual(0.0j ** 0, 1)
159
160 b = 5.1+2.3j
161 self.assertRaises(ValueError, pow, a, b, 0)
162
Walter Dörwald5edd7852003-06-18 14:26:18 +0000163 def test_boolcontext(self):
164 for i in xrange(100):
165 self.assert_(complex(random() + 1e-6, random() + 1e-6))
166 self.assert_(not complex(0.0, 0.0))
167
168 def test_conjugate(self):
169 self.assertClose(complex(5.3, 9.8).conjugate(), 5.3-9.8j)
170
171 def test_constructor(self):
172 class OS:
173 def __init__(self, value): self.value = value
174 def __complex__(self): return self.value
175 class NS(object):
176 def __init__(self, value): self.value = value
177 def __complex__(self): return self.value
178 self.assertEqual(complex(OS(1+10j)), 1+10j)
179 self.assertEqual(complex(NS(1+10j)), 1+10j)
180 self.assertRaises(TypeError, complex, OS(None))
181 self.assertRaises(TypeError, complex, NS(None))
182
183 self.assertAlmostEqual(complex("1+10j"), 1+10j)
184 self.assertAlmostEqual(complex(10), 10+0j)
185 self.assertAlmostEqual(complex(10.0), 10+0j)
186 self.assertAlmostEqual(complex(10L), 10+0j)
187 self.assertAlmostEqual(complex(10+0j), 10+0j)
188 self.assertAlmostEqual(complex(1,10), 1+10j)
189 self.assertAlmostEqual(complex(1,10L), 1+10j)
190 self.assertAlmostEqual(complex(1,10.0), 1+10j)
191 self.assertAlmostEqual(complex(1L,10), 1+10j)
192 self.assertAlmostEqual(complex(1L,10L), 1+10j)
193 self.assertAlmostEqual(complex(1L,10.0), 1+10j)
194 self.assertAlmostEqual(complex(1.0,10), 1+10j)
195 self.assertAlmostEqual(complex(1.0,10L), 1+10j)
196 self.assertAlmostEqual(complex(1.0,10.0), 1+10j)
197 self.assertAlmostEqual(complex(3.14+0j), 3.14+0j)
198 self.assertAlmostEqual(complex(3.14), 3.14+0j)
199 self.assertAlmostEqual(complex(314), 314.0+0j)
200 self.assertAlmostEqual(complex(314L), 314.0+0j)
201 self.assertAlmostEqual(complex(3.14+0j, 0j), 3.14+0j)
202 self.assertAlmostEqual(complex(3.14, 0.0), 3.14+0j)
203 self.assertAlmostEqual(complex(314, 0), 314.0+0j)
204 self.assertAlmostEqual(complex(314L, 0L), 314.0+0j)
205 self.assertAlmostEqual(complex(0j, 3.14j), -3.14+0j)
206 self.assertAlmostEqual(complex(0.0, 3.14j), -3.14+0j)
207 self.assertAlmostEqual(complex(0j, 3.14), 3.14j)
208 self.assertAlmostEqual(complex(0.0, 3.14), 3.14j)
209 self.assertAlmostEqual(complex("1"), 1+0j)
210 self.assertAlmostEqual(complex("1j"), 1j)
211 self.assertAlmostEqual(complex(), 0)
212 self.assertAlmostEqual(complex("-1"), -1)
213 self.assertAlmostEqual(complex("+1"), +1)
214
215 class complex2(complex): pass
216 self.assertAlmostEqual(complex(complex2(1+1j)), 1+1j)
217 self.assertAlmostEqual(complex(real=17, imag=23), 17+23j)
218 self.assertAlmostEqual(complex(real=17+23j), 17+23j)
219 self.assertAlmostEqual(complex(real=17+23j, imag=23), 17+46j)
220 self.assertAlmostEqual(complex(real=1+2j, imag=3+4j), -3+5j)
221
222 c = 3.14 + 1j
223 self.assert_(complex(c) is c)
224 del c
225
226 self.assertRaises(TypeError, complex, "1", "1")
227 self.assertRaises(TypeError, complex, 1, "1")
228
229 self.assertEqual(complex(" 3.14+J "), 3.14+1j)
230 if test_support.have_unicode:
231 self.assertEqual(complex(unicode(" 3.14+J ")), 3.14+1j)
232
233 # SF bug 543840: complex(string) accepts strings with \0
234 # Fixed in 2.3.
235 self.assertRaises(ValueError, complex, '1+1j\0j')
236
237 self.assertRaises(TypeError, int, 5+3j)
238 self.assertRaises(TypeError, long, 5+3j)
239 self.assertRaises(TypeError, float, 5+3j)
240 self.assertRaises(ValueError, complex, "")
241 self.assertRaises(TypeError, complex, None)
242 self.assertRaises(ValueError, complex, "\0")
243 self.assertRaises(TypeError, complex, "1", "2")
244 self.assertRaises(TypeError, complex, "1", 42)
245 self.assertRaises(TypeError, complex, 1, "2")
246 self.assertRaises(ValueError, complex, "1+")
247 self.assertRaises(ValueError, complex, "1+1j+1j")
248 self.assertRaises(ValueError, complex, "--")
249 if test_support.have_unicode:
250 self.assertRaises(ValueError, complex, unicode("1"*500))
251 self.assertRaises(ValueError, complex, unicode("x"))
252
253 class EvilExc(Exception):
Tim Peters478c1052003-06-29 05:46:54 +0000254 pass
Walter Dörwald5edd7852003-06-18 14:26:18 +0000255
256 class evilcomplex:
257 def __complex__(self):
258 raise EvilExc
259
260 self.assertRaises(EvilExc, complex, evilcomplex())
261
262 class float2:
263 def __init__(self, value):
264 self.value = value
265 def __float__(self):
266 return self.value
267
268 self.assertAlmostEqual(complex(float2(42.)), 42)
269 self.assertAlmostEqual(complex(real=float2(17.), imag=float2(23.)), 17+23j)
270 self.assertRaises(TypeError, complex, float2(None))
271
Brett Cannonc3647ac2005-04-26 03:45:26 +0000272 class complex0(complex):
273 """Test usage of __complex__() when inheriting from 'complex'"""
274 def __complex__(self):
275 return 42j
276
277 class complex1(complex):
278 """Test usage of __complex__() with a __new__() method"""
279 def __new__(self, value=0j):
280 return complex.__new__(self, 2*value)
281 def __complex__(self):
282 return self
283
284 class complex2(complex):
285 """Make sure that __complex__() calls fail if anything other than a
286 complex is returned"""
287 def __complex__(self):
288 return None
289
290 self.assertAlmostEqual(complex(complex0(1j)), 42j)
291 self.assertAlmostEqual(complex(complex1(1j)), 2j)
292 self.assertRaises(TypeError, complex, complex2(1j))
293
Walter Dörwald5edd7852003-06-18 14:26:18 +0000294 def test_hash(self):
295 for x in xrange(-30, 30):
296 self.assertEqual(hash(x), hash(complex(x, 0)))
297 x /= 3.0 # now check against floating point
298 self.assertEqual(hash(x), hash(complex(x, 0.)))
299
300 def test_abs(self):
301 nums = [complex(x/3., y/7.) for x in xrange(-9,9) for y in xrange(-9,9)]
302 for num in nums:
303 self.assertAlmostEqual((num.real**2 + num.imag**2) ** 0.5, abs(num))
304
305 def test_repr(self):
306 self.assertEqual(repr(1+6j), '(1+6j)')
Martin v. Löwis70aa1f22004-08-22 21:09:15 +0000307 self.assertEqual(repr(1-6j), '(1-6j)')
Walter Dörwald5edd7852003-06-18 14:26:18 +0000308
Georg Brandl9e281072005-09-17 07:51:15 +0000309 self.assertNotEqual(repr(-(1+0j)), '(-1+-0j)')
310
Walter Dörwald5edd7852003-06-18 14:26:18 +0000311 def test_neg(self):
312 self.assertEqual(-(1+6j), -1-6j)
313
Walter Dörwaldf393fc62003-07-15 18:47:27 +0000314 def test_file(self):
315 a = 3.33+4.43j
316 b = 5.1+2.3j
317
318 fo = None
319 try:
320 fo = open(test_support.TESTFN, "wb")
321 print >>fo, a, b
322 fo.close()
323 fo = open(test_support.TESTFN, "rb")
324 self.assertEqual(fo.read(), "%s %s\n" % (a, b))
325 finally:
326 if (fo is not None) and (not fo.closed):
327 fo.close()
328 try:
329 os.remove(test_support.TESTFN)
330 except (OSError, IOError):
331 pass
Walter Dörwald5edd7852003-06-18 14:26:18 +0000332
333def test_main():
334 test_support.run_unittest(ComplexTest)
335
336if __name__ == "__main__":
337 test_main()