~ubuntu-branches/ubuntu/maverick/python3.1/maverick

« back to all changes in this revision

Viewing changes to Lib/test/test_complex.py

  • Committer: Bazaar Package Importer
  • Author(s): Matthias Klose
  • Date: 2009-03-23 00:01:27 UTC
  • Revision ID: james.westby@ubuntu.com-20090323000127-5fstfxju4ufrhthq
Tags: upstream-3.1~a1+20090322
ImportĀ upstreamĀ versionĀ 3.1~a1+20090322

Show diffs side-by-side

added added

removed removed

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