blob: 20ae1deeb7ab0dd68e4436c54974f6afa0521e3a [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.__div__(x)
59 self.assertClose(q, y)
60 q = z.__truediv__(x)
61 self.assertClose(q, y)
Walter Dörwald5edd7852003-06-18 14:26:18 +000062 if y != 0:
63 q = z / y
64 self.assertClose(q, x)
Walter Dörwaldb27cca62003-08-05 15:34:34 +000065 q = z.__div__(y)
66 self.assertClose(q, x)
67 q = z.__truediv__(y)
68 self.assertClose(q, x)
Tim Peters0f336042001-03-18 08:21:57 +000069
Walter Dörwald5edd7852003-06-18 14:26:18 +000070 def test_div(self):
71 simple_real = [float(i) for i in xrange(-5, 6)]
72 simple_complex = [complex(x, y) for x in simple_real for y in simple_real]
73 for x in simple_complex:
74 for y in simple_complex:
75 self.check_div(x, y)
Tim Peters0f336042001-03-18 08:21:57 +000076
Walter Dörwald5edd7852003-06-18 14:26:18 +000077 # 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)
Tim Peters0f336042001-03-18 08:21:57 +000081
Walter Dörwald5edd7852003-06-18 14:26:18 +000082 # Just for fun.
83 for i in xrange(100):
84 self.check_div(complex(random(), random()),
85 complex(random(), random()))
Neal Norwitzfc37af82001-12-29 01:02:21 +000086
Walter Dörwald5edd7852003-06-18 14:26:18 +000087 self.assertRaises(ZeroDivisionError, complex.__div__, 1+1j, 0+0j)
88 # FIXME: The following currently crashes on Alpha
89 # self.assertRaises(OverflowError, pow, 1e200+1j, 1e200+1j)
Neal Norwitzfc37af82001-12-29 01:02:21 +000090
Walter Dörwald5edd7852003-06-18 14:26:18 +000091 def test_truediv(self):
92 self.assertAlmostEqual(complex.__truediv__(2+0j, 1+1j), 1-1j)
93 self.assertRaises(ZeroDivisionError, complex.__truediv__, 1+1j, 0+0j)
Neal Norwitz5a0f0102001-12-29 14:31:46 +000094
Walter Dörwald5edd7852003-06-18 14:26:18 +000095 def test_floordiv(self):
96 self.assertAlmostEqual(complex.__floordiv__(3+0j, 1.5+0j), 2)
97 self.assertRaises(ZeroDivisionError, complex.__floordiv__, 3+0j, 0+0j)
Neal Norwitzfc37af82001-12-29 01:02:21 +000098
Walter Dörwald5edd7852003-06-18 14:26:18 +000099 def test_coerce(self):
100 self.assertRaises(OverflowError, complex.__coerce__, 1+1j, 1L<<10000)
Neal Norwitzfc37af82001-12-29 01:02:21 +0000101
Walter Dörwald5edd7852003-06-18 14:26:18 +0000102 def test_richcompare(self):
103 self.assertRaises(OverflowError, complex.__eq__, 1+1j, 1L<<10000)
104 self.assertEqual(complex.__lt__(1+1j, None), NotImplemented)
105 self.assertIs(complex.__eq__(1+1j, 1+1j), True)
106 self.assertIs(complex.__eq__(1+1j, 2+2j), False)
107 self.assertIs(complex.__ne__(1+1j, 1+1j), False)
108 self.assertIs(complex.__ne__(1+1j, 2+2j), True)
109 self.assertRaises(TypeError, complex.__lt__, 1+1j, 2+2j)
110 self.assertRaises(TypeError, complex.__le__, 1+1j, 2+2j)
111 self.assertRaises(TypeError, complex.__gt__, 1+1j, 2+2j)
112 self.assertRaises(TypeError, complex.__ge__, 1+1j, 2+2j)
Tim Peters0f336042001-03-18 08:21:57 +0000113
Walter Dörwald5edd7852003-06-18 14:26:18 +0000114 def test_mod(self):
115 self.assertRaises(ZeroDivisionError, (1+1j).__mod__, 0+0j)
116
Walter Dörwaldf393fc62003-07-15 18:47:27 +0000117 a = 3.33+4.43j
118 try:
119 a % 0
120 except ZeroDivisionError:
121 pass
122 else:
123 self.fail("modulo parama can't be 0")
124
Walter Dörwald5edd7852003-06-18 14:26:18 +0000125 def test_divmod(self):
126 self.assertRaises(ZeroDivisionError, divmod, 1+1j, 0+0j)
127
128 def test_pow(self):
129 self.assertAlmostEqual(pow(1+1j, 0+0j), 1.0)
130 self.assertAlmostEqual(pow(0+0j, 2+0j), 0.0)
131 self.assertRaises(ZeroDivisionError, pow, 0+0j, 1j)
132 self.assertAlmostEqual(pow(1j, -1), 1/1j)
133 self.assertAlmostEqual(pow(1j, 200), 1)
134 self.assertRaises(ValueError, pow, 1+1j, 1+1j, 1+1j)
135
Walter Dörwaldf393fc62003-07-15 18:47:27 +0000136 a = 3.33+4.43j
137 self.assertEqual(a ** 0j, 1)
138 self.assertEqual(a ** 0.+0.j, 1)
139
140 self.assertEqual(3j ** 0j, 1)
141 self.assertEqual(3j ** 0, 1)
142
143 try:
144 0j ** a
145 except ZeroDivisionError:
146 pass
147 else:
148 self.fail("should fail 0.0 to negative or complex power")
149
150 try:
151 0j ** (3-2j)
152 except ZeroDivisionError:
153 pass
154 else:
155 self.fail("should fail 0.0 to negative or complex power")
156
157 # The following is used to exercise certain code paths
158 self.assertEqual(a ** 105, a ** 105)
159 self.assertEqual(a ** -105, a ** -105)
160 self.assertEqual(a ** -30, a ** -30)
161
162 self.assertEqual(0.0j ** 0, 1)
163
164 b = 5.1+2.3j
165 self.assertRaises(ValueError, pow, a, b, 0)
166
Walter Dörwald5edd7852003-06-18 14:26:18 +0000167 def test_boolcontext(self):
168 for i in xrange(100):
169 self.assert_(complex(random() + 1e-6, random() + 1e-6))
170 self.assert_(not complex(0.0, 0.0))
171
172 def test_conjugate(self):
173 self.assertClose(complex(5.3, 9.8).conjugate(), 5.3-9.8j)
174
175 def test_constructor(self):
176 class OS:
177 def __init__(self, value): self.value = value
178 def __complex__(self): return self.value
179 class NS(object):
180 def __init__(self, value): self.value = value
181 def __complex__(self): return self.value
182 self.assertEqual(complex(OS(1+10j)), 1+10j)
183 self.assertEqual(complex(NS(1+10j)), 1+10j)
184 self.assertRaises(TypeError, complex, OS(None))
185 self.assertRaises(TypeError, complex, NS(None))
186
187 self.assertAlmostEqual(complex("1+10j"), 1+10j)
188 self.assertAlmostEqual(complex(10), 10+0j)
189 self.assertAlmostEqual(complex(10.0), 10+0j)
190 self.assertAlmostEqual(complex(10L), 10+0j)
191 self.assertAlmostEqual(complex(10+0j), 10+0j)
192 self.assertAlmostEqual(complex(1,10), 1+10j)
193 self.assertAlmostEqual(complex(1,10L), 1+10j)
194 self.assertAlmostEqual(complex(1,10.0), 1+10j)
195 self.assertAlmostEqual(complex(1L,10), 1+10j)
196 self.assertAlmostEqual(complex(1L,10L), 1+10j)
197 self.assertAlmostEqual(complex(1L,10.0), 1+10j)
198 self.assertAlmostEqual(complex(1.0,10), 1+10j)
199 self.assertAlmostEqual(complex(1.0,10L), 1+10j)
200 self.assertAlmostEqual(complex(1.0,10.0), 1+10j)
201 self.assertAlmostEqual(complex(3.14+0j), 3.14+0j)
202 self.assertAlmostEqual(complex(3.14), 3.14+0j)
203 self.assertAlmostEqual(complex(314), 314.0+0j)
204 self.assertAlmostEqual(complex(314L), 314.0+0j)
205 self.assertAlmostEqual(complex(3.14+0j, 0j), 3.14+0j)
206 self.assertAlmostEqual(complex(3.14, 0.0), 3.14+0j)
207 self.assertAlmostEqual(complex(314, 0), 314.0+0j)
208 self.assertAlmostEqual(complex(314L, 0L), 314.0+0j)
209 self.assertAlmostEqual(complex(0j, 3.14j), -3.14+0j)
210 self.assertAlmostEqual(complex(0.0, 3.14j), -3.14+0j)
211 self.assertAlmostEqual(complex(0j, 3.14), 3.14j)
212 self.assertAlmostEqual(complex(0.0, 3.14), 3.14j)
213 self.assertAlmostEqual(complex("1"), 1+0j)
214 self.assertAlmostEqual(complex("1j"), 1j)
215 self.assertAlmostEqual(complex(), 0)
216 self.assertAlmostEqual(complex("-1"), -1)
217 self.assertAlmostEqual(complex("+1"), +1)
218
219 class complex2(complex): pass
220 self.assertAlmostEqual(complex(complex2(1+1j)), 1+1j)
221 self.assertAlmostEqual(complex(real=17, imag=23), 17+23j)
222 self.assertAlmostEqual(complex(real=17+23j), 17+23j)
223 self.assertAlmostEqual(complex(real=17+23j, imag=23), 17+46j)
224 self.assertAlmostEqual(complex(real=1+2j, imag=3+4j), -3+5j)
225
226 c = 3.14 + 1j
227 self.assert_(complex(c) is c)
228 del c
229
230 self.assertRaises(TypeError, complex, "1", "1")
231 self.assertRaises(TypeError, complex, 1, "1")
232
233 self.assertEqual(complex(" 3.14+J "), 3.14+1j)
234 if test_support.have_unicode:
235 self.assertEqual(complex(unicode(" 3.14+J ")), 3.14+1j)
236
237 # SF bug 543840: complex(string) accepts strings with \0
238 # Fixed in 2.3.
239 self.assertRaises(ValueError, complex, '1+1j\0j')
240
241 self.assertRaises(TypeError, int, 5+3j)
242 self.assertRaises(TypeError, long, 5+3j)
243 self.assertRaises(TypeError, float, 5+3j)
244 self.assertRaises(ValueError, complex, "")
245 self.assertRaises(TypeError, complex, None)
246 self.assertRaises(ValueError, complex, "\0")
247 self.assertRaises(TypeError, complex, "1", "2")
248 self.assertRaises(TypeError, complex, "1", 42)
249 self.assertRaises(TypeError, complex, 1, "2")
250 self.assertRaises(ValueError, complex, "1+")
251 self.assertRaises(ValueError, complex, "1+1j+1j")
252 self.assertRaises(ValueError, complex, "--")
253 if test_support.have_unicode:
254 self.assertRaises(ValueError, complex, unicode("1"*500))
255 self.assertRaises(ValueError, complex, unicode("x"))
256
257 class EvilExc(Exception):
Tim Peters478c1052003-06-29 05:46:54 +0000258 pass
Walter Dörwald5edd7852003-06-18 14:26:18 +0000259
260 class evilcomplex:
261 def __complex__(self):
262 raise EvilExc
263
264 self.assertRaises(EvilExc, complex, evilcomplex())
265
266 class float2:
267 def __init__(self, value):
268 self.value = value
269 def __float__(self):
270 return self.value
271
272 self.assertAlmostEqual(complex(float2(42.)), 42)
273 self.assertAlmostEqual(complex(real=float2(17.), imag=float2(23.)), 17+23j)
274 self.assertRaises(TypeError, complex, float2(None))
275
276 def test_hash(self):
277 for x in xrange(-30, 30):
278 self.assertEqual(hash(x), hash(complex(x, 0)))
279 x /= 3.0 # now check against floating point
280 self.assertEqual(hash(x), hash(complex(x, 0.)))
281
282 def test_abs(self):
283 nums = [complex(x/3., y/7.) for x in xrange(-9,9) for y in xrange(-9,9)]
284 for num in nums:
285 self.assertAlmostEqual((num.real**2 + num.imag**2) ** 0.5, abs(num))
286
287 def test_repr(self):
288 self.assertEqual(repr(1+6j), '(1+6j)')
289
290 def test_neg(self):
291 self.assertEqual(-(1+6j), -1-6j)
292
Walter Dörwaldf393fc62003-07-15 18:47:27 +0000293 def test_file(self):
294 a = 3.33+4.43j
295 b = 5.1+2.3j
296
297 fo = None
298 try:
299 fo = open(test_support.TESTFN, "wb")
300 print >>fo, a, b
301 fo.close()
302 fo = open(test_support.TESTFN, "rb")
303 self.assertEqual(fo.read(), "%s %s\n" % (a, b))
304 finally:
305 if (fo is not None) and (not fo.closed):
306 fo.close()
307 try:
308 os.remove(test_support.TESTFN)
309 except (OSError, IOError):
310 pass
Walter Dörwald5edd7852003-06-18 14:26:18 +0000311
312def test_main():
313 test_support.run_unittest(ComplexTest)
314
315if __name__ == "__main__":
316 test_main()