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