#### /Lib/test/test_complex.py

Python | 398 lines | 391 code | 6 blank | 1 comment | 3 complexity | 2d3b675df939f2cdd180b82aa5fc4a3f MD5 | raw file
```  1import unittest, os
2from test import test_support
3
4import warnings
5warnings.filterwarnings(
6    "ignore",
7    category=DeprecationWarning,
8    message=".*complex divmod.*are deprecated"
9)
10
11from random import random
12from math import atan2
13
14INF = float("inf")
15NAN = float("nan")
16# These tests ensure that complex math does the right thing
17
18class ComplexTest(unittest.TestCase):
19
20    def assertAlmostEqual(self, a, b):
21        if isinstance(a, complex):
22            if isinstance(b, complex):
23                unittest.TestCase.assertAlmostEqual(self, a.real, b.real)
24                unittest.TestCase.assertAlmostEqual(self, a.imag, b.imag)
25            else:
26                unittest.TestCase.assertAlmostEqual(self, a.real, b)
27                unittest.TestCase.assertAlmostEqual(self, a.imag, 0.)
28        else:
29            if isinstance(b, complex):
30                unittest.TestCase.assertAlmostEqual(self, a, b.real)
31                unittest.TestCase.assertAlmostEqual(self, 0., b.imag)
32            else:
33                unittest.TestCase.assertAlmostEqual(self, a, b)
34
35    def assertCloseAbs(self, x, y, eps=1e-9):
36        """Return true iff floats x and y "are close\""""
37        # put the one with larger magnitude second
38        if abs(x) > abs(y):
39            x, y = y, x
40        if y == 0:
41            return abs(x) < eps
42        if x == 0:
43            return abs(y) < eps
44        # check that relative difference < eps
45        self.assert_(abs((x-y)/y) < eps)
46
47    def assertClose(self, x, y, eps=1e-9):
48        """Return true iff complexes x and y "are close\""""
49        self.assertCloseAbs(x.real, y.real, eps)
50        self.assertCloseAbs(x.imag, y.imag, eps)
51
52    def assertIs(self, a, b):
53        self.assert_(a is b)
54
55    def check_div(self, x, y):
56        """Compute complex z=x*y, and check that z/x==y and z/y==x."""
57        z = x * y
58        if x != 0:
59            q = z / x
60            self.assertClose(q, y)
61            q = z.__div__(x)
62            self.assertClose(q, y)
63            q = z.__truediv__(x)
64            self.assertClose(q, y)
65        if y != 0:
66            q = z / y
67            self.assertClose(q, x)
68            q = z.__div__(y)
69            self.assertClose(q, x)
70            q = z.__truediv__(y)
71            self.assertClose(q, x)
72
73    def test_div(self):
74        simple_real = [float(i) for i in xrange(-5, 6)]
75        simple_complex = [complex(x, y) for x in simple_real for y in simple_real]
76        for x in simple_complex:
77            for y in simple_complex:
78                self.check_div(x, y)
79
80        # A naive complex division algorithm (such as in 2.0) is very prone to
81        # nonsense errors for these (overflows and underflows).
82        self.check_div(complex(1e200, 1e200), 1+0j)
83        self.check_div(complex(1e-200, 1e-200), 1+0j)
84
85        # Just for fun.
86        for i in xrange(100):
87            self.check_div(complex(random(), random()),
88                           complex(random(), random()))
89
90        self.assertRaises(ZeroDivisionError, complex.__div__, 1+1j, 0+0j)
91        # FIXME: The following currently crashes on Alpha
92        # self.assertRaises(OverflowError, pow, 1e200+1j, 1e200+1j)
93
94    def test_truediv(self):
95        self.assertAlmostEqual(complex.__truediv__(2+0j, 1+1j), 1-1j)
96        self.assertRaises(ZeroDivisionError, complex.__truediv__, 1+1j, 0+0j)
97
98    def test_floordiv(self):
99        self.assertAlmostEqual(complex.__floordiv__(3+0j, 1.5+0j), 2)
100        self.assertRaises(ZeroDivisionError, complex.__floordiv__, 3+0j, 0+0j)
101
102    def test_coerce(self):
103        self.assertRaises(OverflowError, complex.__coerce__, 1+1j, 1L<<10000)
104
105    def test_richcompare(self):
106        self.assertRaises(OverflowError, complex.__eq__, 1+1j, 1L<<10000)
107        self.assertEqual(complex.__lt__(1+1j, None), NotImplemented)
108        self.assertIs(complex.__eq__(1+1j, 1+1j), True)
109        self.assertIs(complex.__eq__(1+1j, 2+2j), False)
110        self.assertIs(complex.__ne__(1+1j, 1+1j), False)
111        self.assertIs(complex.__ne__(1+1j, 2+2j), 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
117    def test_mod(self):
118        self.assertRaises(ZeroDivisionError, (1+1j).__mod__, 0+0j)
119
120        a = 3.33+4.43j
121        try:
122            a % 0
123        except ZeroDivisionError:
124            pass
125        else:
126            self.fail("modulo parama can't be 0")
127
128    def test_divmod(self):
129        self.assertRaises(ZeroDivisionError, divmod, 1+1j, 0+0j)
130
131    def test_pow(self):
132        self.assertAlmostEqual(pow(1+1j, 0+0j), 1.0)
133        self.assertAlmostEqual(pow(0+0j, 2+0j), 0.0)
134        self.assertRaises(ZeroDivisionError, pow, 0+0j, 1j)
135        self.assertAlmostEqual(pow(1j, -1), 1/1j)
136        self.assertAlmostEqual(pow(1j, 200), 1)
137        self.assertRaises(ValueError, pow, 1+1j, 1+1j, 1+1j)
138
139        a = 3.33+4.43j
140        self.assertEqual(a ** 0j, 1)
141        self.assertEqual(a ** 0.+0.j, 1)
142
143        self.assertEqual(3j ** 0j, 1)
144        self.assertEqual(3j ** 0, 1)
145
146        try:
147            0j ** a
148        except ZeroDivisionError:
149            pass
150        else:
151            self.fail("should fail 0.0 to negative or complex power")
152
153        try:
154            0j ** (3-2j)
155        except ZeroDivisionError:
156            pass
157        else:
158            self.fail("should fail 0.0 to negative or complex power")
159
160        # The following is used to exercise certain code paths
161        self.assertEqual(a ** 105, a ** 105)
162        self.assertEqual(a ** -105, a ** -105)
163        self.assertEqual(a ** -30, a ** -30)
164
165        self.assertEqual(0.0j ** 0, 1)
166
167        b = 5.1+2.3j
168        self.assertRaises(ValueError, pow, a, b, 0)
169
170    def test_boolcontext(self):
171        for i in xrange(100):
172            self.assert_(complex(random() + 1e-6, random() + 1e-6))
173        self.assert_(not complex(0.0, 0.0))
174
175    def test_conjugate(self):
176        self.assertClose(complex(5.3, 9.8).conjugate(), 5.3-9.8j)
177
178    def test_constructor(self):
179        class OS:
180            def __init__(self, value): self.value = value
181            def __complex__(self): return self.value
182        class NS(object):
183            def __init__(self, value): self.value = value
184            def __complex__(self): return self.value
185        self.assertEqual(complex(OS(1+10j)), 1+10j)
186        self.assertEqual(complex(NS(1+10j)), 1+10j)
187        self.assertRaises(TypeError, complex, OS(None))
188        self.assertRaises(TypeError, complex, NS(None))
189
190        self.assertAlmostEqual(complex("1+10j"), 1+10j)
191        self.assertAlmostEqual(complex(10), 10+0j)
192        self.assertAlmostEqual(complex(10.0), 10+0j)
193        self.assertAlmostEqual(complex(10L), 10+0j)
194        self.assertAlmostEqual(complex(10+0j), 10+0j)
195        self.assertAlmostEqual(complex(1,10), 1+10j)
196        self.assertAlmostEqual(complex(1,10L), 1+10j)
197        self.assertAlmostEqual(complex(1,10.0), 1+10j)
198        self.assertAlmostEqual(complex(1L,10), 1+10j)
199        self.assertAlmostEqual(complex(1L,10L), 1+10j)
200        self.assertAlmostEqual(complex(1L,10.0), 1+10j)
201        self.assertAlmostEqual(complex(1.0,10), 1+10j)
202        self.assertAlmostEqual(complex(1.0,10L), 1+10j)
203        self.assertAlmostEqual(complex(1.0,10.0), 1+10j)
204        self.assertAlmostEqual(complex(3.14+0j), 3.14+0j)
205        self.assertAlmostEqual(complex(3.14), 3.14+0j)
206        self.assertAlmostEqual(complex(314), 314.0+0j)
207        self.assertAlmostEqual(complex(314L), 314.0+0j)
208        self.assertAlmostEqual(complex(3.14+0j, 0j), 3.14+0j)
209        self.assertAlmostEqual(complex(3.14, 0.0), 3.14+0j)
210        self.assertAlmostEqual(complex(314, 0), 314.0+0j)
211        self.assertAlmostEqual(complex(314L, 0L), 314.0+0j)
212        self.assertAlmostEqual(complex(0j, 3.14j), -3.14+0j)
213        self.assertAlmostEqual(complex(0.0, 3.14j), -3.14+0j)
214        self.assertAlmostEqual(complex(0j, 3.14), 3.14j)
215        self.assertAlmostEqual(complex(0.0, 3.14), 3.14j)
216        self.assertAlmostEqual(complex("1"), 1+0j)
217        self.assertAlmostEqual(complex("1j"), 1j)
218        self.assertAlmostEqual(complex(),  0)
219        self.assertAlmostEqual(complex("-1"), -1)
220        self.assertAlmostEqual(complex("+1"), +1)
221        self.assertAlmostEqual(complex("(1+2j)"), 1+2j)
222        self.assertAlmostEqual(complex("(1.3+2.2j)"), 1.3+2.2j)
223        self.assertAlmostEqual(complex("1E-500"), 1e-500+0j)
224        self.assertAlmostEqual(complex("1e-500J"), 1e-500j)
225        self.assertAlmostEqual(complex("+1e-315-1e-400j"), 1e-315-1e-400j)
226
227        class complex2(complex): pass
228        self.assertAlmostEqual(complex(complex2(1+1j)), 1+1j)
229        self.assertAlmostEqual(complex(real=17, imag=23), 17+23j)
230        self.assertAlmostEqual(complex(real=17+23j), 17+23j)
231        self.assertAlmostEqual(complex(real=17+23j, imag=23), 17+46j)
232        self.assertAlmostEqual(complex(real=1+2j, imag=3+4j), -3+5j)
233
234        # check that the sign of a zero in the real or imaginary part
235        # is preserved when constructing from two floats.  (These checks
236        # are harmless on systems without support for signed zeros.)
237        def split_zeros(x):
238            """Function that produces different results for 0. and -0."""
239            return atan2(x, -1.)
240
241        self.assertEqual(split_zeros(complex(1., 0.).imag), split_zeros(0.))
242        self.assertEqual(split_zeros(complex(1., -0.).imag), split_zeros(-0.))
243        self.assertEqual(split_zeros(complex(0., 1.).real), split_zeros(0.))
244        self.assertEqual(split_zeros(complex(-0., 1.).real), split_zeros(-0.))
245
246        c = 3.14 + 1j
247        self.assert_(complex(c) is c)
248        del c
249
250        self.assertRaises(TypeError, complex, "1", "1")
251        self.assertRaises(TypeError, complex, 1, "1")
252
253        self.assertEqual(complex("  3.14+J  "), 3.14+1j)
254        if test_support.have_unicode:
255            self.assertEqual(complex(unicode("  3.14+J  ")), 3.14+1j)
256
257        # SF bug 543840:  complex(string) accepts strings with \0
258        # Fixed in 2.3.
259        self.assertRaises(ValueError, complex, '1+1j\0j')
260
261        self.assertRaises(TypeError, int, 5+3j)
262        self.assertRaises(TypeError, long, 5+3j)
263        self.assertRaises(TypeError, float, 5+3j)
264        self.assertRaises(ValueError, complex, "")
265        self.assertRaises(TypeError, complex, None)
266        self.assertRaises(ValueError, complex, "\0")
267        self.assertRaises(ValueError, complex, "3\09")
268        self.assertRaises(TypeError, complex, "1", "2")
269        self.assertRaises(TypeError, complex, "1", 42)
270        self.assertRaises(TypeError, complex, 1, "2")
271        self.assertRaises(ValueError, complex, "1+")
272        self.assertRaises(ValueError, complex, "1+1j+1j")
273        self.assertRaises(ValueError, complex, "--")
274        self.assertRaises(ValueError, complex, "(1+2j")
275        self.assertRaises(ValueError, complex, "1+2j)")
276        self.assertRaises(ValueError, complex, "1+(2j)")
277        self.assertRaises(ValueError, complex, "(1+2j)123")
278        if test_support.have_unicode:
279            self.assertRaises(ValueError, complex, unicode("1"*500))
280            self.assertRaises(ValueError, complex, unicode("x"))
281
282        class EvilExc(Exception):
283            pass
284
285        class evilcomplex:
286            def __complex__(self):
287                raise EvilExc
288
289        self.assertRaises(EvilExc, complex, evilcomplex())
290
291        class float2:
292            def __init__(self, value):
293                self.value = value
294            def __float__(self):
295                return self.value
296
297        self.assertAlmostEqual(complex(float2(42.)), 42)
298        self.assertAlmostEqual(complex(real=float2(17.), imag=float2(23.)), 17+23j)
299        self.assertRaises(TypeError, complex, float2(None))
300
301        class complex0(complex):
302            """Test usage of __complex__() when inheriting from 'complex'"""
303            def __complex__(self):
304                return 42j
305
306        class complex1(complex):
307            """Test usage of __complex__() with a __new__() method"""
308            def __new__(self, value=0j):
309                return complex.__new__(self, 2*value)
310            def __complex__(self):
311                return self
312
313        class complex2(complex):
314            """Make sure that __complex__() calls fail if anything other than a
315            complex is returned"""
316            def __complex__(self):
317                return None
318
319        self.assertAlmostEqual(complex(complex0(1j)), 42j)
320        self.assertAlmostEqual(complex(complex1(1j)), 2j)
321        self.assertRaises(TypeError, complex, complex2(1j))
322
323    def test_hash(self):
324        for x in xrange(-30, 30):
325            self.assertEqual(hash(x), hash(complex(x, 0)))
326            x /= 3.0    # now check against floating point
327            self.assertEqual(hash(x), hash(complex(x, 0.)))
328
329    def test_abs(self):
330        nums = [complex(x/3., y/7.) for x in xrange(-9,9) for y in xrange(-9,9)]
331        for num in nums:
332            self.assertAlmostEqual((num.real**2 + num.imag**2)  ** 0.5, abs(num))
333
334    def test_repr(self):
335        self.assertEqual(repr(1+6j), '(1+6j)')
336        self.assertEqual(repr(1-6j), '(1-6j)')
337
338        self.assertNotEqual(repr(-(1+0j)), '(-1+-0j)')
339
340        self.assertEqual(1-6j,complex(repr(1-6j)))
341        self.assertEqual(1+6j,complex(repr(1+6j)))
342        self.assertEqual(-6j,complex(repr(-6j)))
343        self.assertEqual(6j,complex(repr(6j)))
344
345        self.assertEqual(repr(complex(1., INF)), "(1+inf*j)")
346        self.assertEqual(repr(complex(1., -INF)), "(1-inf*j)")
347        self.assertEqual(repr(complex(INF, 1)), "(inf+1j)")
348        self.assertEqual(repr(complex(-INF, INF)), "(-inf+inf*j)")
349        self.assertEqual(repr(complex(NAN, 1)), "(nan+1j)")
350        self.assertEqual(repr(complex(1, NAN)), "(1+nan*j)")
351        self.assertEqual(repr(complex(NAN, NAN)), "(nan+nan*j)")
352
353        self.assertEqual(repr(complex(0, INF)), "inf*j")
354        self.assertEqual(repr(complex(0, -INF)), "-inf*j")
355        self.assertEqual(repr(complex(0, NAN)), "nan*j")
356
357    def test_neg(self):
358        self.assertEqual(-(1+6j), -1-6j)
359
360    def test_file(self):
361        a = 3.33+4.43j
362        b = 5.1+2.3j
363
364        fo = None
365        try:
366            fo = open(test_support.TESTFN, "wb")
367            print >>fo, a, b
368            fo.close()
369            fo = open(test_support.TESTFN, "rb")
370            self.assertEqual(fo.read(), "%s %s\n" % (a, b))
371        finally:
372            if (fo is not None) and (not fo.closed):
373                fo.close()
374            try:
375                os.remove(test_support.TESTFN)
376            except (OSError, IOError):
377                pass
378
379    def test_getnewargs(self):
380        self.assertEqual((1+2j).__getnewargs__(), (1.0, 2.0))
381        self.assertEqual((1-2j).__getnewargs__(), (1.0, -2.0))
382        self.assertEqual((2j).__getnewargs__(), (0.0, 2.0))
383        self.assertEqual((-0j).__getnewargs__(), (0.0, -0.0))
384        self.assertEqual(complex(0, INF).__getnewargs__(), (0.0, INF))
385        self.assertEqual(complex(INF, 0).__getnewargs__(), (INF, 0.0))
386
387    if float.__getformat__("double").startswith("IEEE"):
388        def test_plus_minus_0j(self):
389            # test that -0j and 0j literals are not identified
390            z1, z2 = 0j, -0j
391            self.assertEquals(atan2(z1.imag, -1.), atan2(0., -1.))
392            self.assertEquals(atan2(z2.imag, -1.), atan2(-0., -1.))
393
394def test_main():
395    test_support.run_unittest(ComplexTest)
396
397if __name__ == "__main__":
398    test_main()
```