]>
Commit | Line | Data |
---|---|---|
4710c53d | 1 | import unittest\r |
2 | from test import test_support\r | |
3 | \r | |
4 | from random import random\r | |
5 | from math import atan2, isnan, copysign\r | |
6 | \r | |
7 | INF = float("inf")\r | |
8 | NAN = float("nan")\r | |
9 | # These tests ensure that complex math does the right thing\r | |
10 | \r | |
11 | class ComplexTest(unittest.TestCase):\r | |
12 | \r | |
13 | def assertAlmostEqual(self, a, b):\r | |
14 | if isinstance(a, complex):\r | |
15 | if isinstance(b, complex):\r | |
16 | unittest.TestCase.assertAlmostEqual(self, a.real, b.real)\r | |
17 | unittest.TestCase.assertAlmostEqual(self, a.imag, b.imag)\r | |
18 | else:\r | |
19 | unittest.TestCase.assertAlmostEqual(self, a.real, b)\r | |
20 | unittest.TestCase.assertAlmostEqual(self, a.imag, 0.)\r | |
21 | else:\r | |
22 | if isinstance(b, complex):\r | |
23 | unittest.TestCase.assertAlmostEqual(self, a, b.real)\r | |
24 | unittest.TestCase.assertAlmostEqual(self, 0., b.imag)\r | |
25 | else:\r | |
26 | unittest.TestCase.assertAlmostEqual(self, a, b)\r | |
27 | \r | |
28 | def assertCloseAbs(self, x, y, eps=1e-9):\r | |
29 | """Return true iff floats x and y "are close\""""\r | |
30 | # put the one with larger magnitude second\r | |
31 | if abs(x) > abs(y):\r | |
32 | x, y = y, x\r | |
33 | if y == 0:\r | |
34 | return abs(x) < eps\r | |
35 | if x == 0:\r | |
36 | return abs(y) < eps\r | |
37 | # check that relative difference < eps\r | |
38 | self.assertTrue(abs((x-y)/y) < eps)\r | |
39 | \r | |
40 | def assertFloatsAreIdentical(self, x, y):\r | |
41 | """assert that floats x and y are identical, in the sense that:\r | |
42 | (1) both x and y are nans, or\r | |
43 | (2) both x and y are infinities, with the same sign, or\r | |
44 | (3) both x and y are zeros, with the same sign, or\r | |
45 | (4) x and y are both finite and nonzero, and x == y\r | |
46 | \r | |
47 | """\r | |
48 | msg = 'floats {!r} and {!r} are not identical'\r | |
49 | \r | |
50 | if isnan(x) or isnan(y):\r | |
51 | if isnan(x) and isnan(y):\r | |
52 | return\r | |
53 | elif x == y:\r | |
54 | if x != 0.0:\r | |
55 | return\r | |
56 | # both zero; check that signs match\r | |
57 | elif copysign(1.0, x) == copysign(1.0, y):\r | |
58 | return\r | |
59 | else:\r | |
60 | msg += ': zeros have different signs'\r | |
61 | self.fail(msg.format(x, y))\r | |
62 | \r | |
63 | def assertClose(self, x, y, eps=1e-9):\r | |
64 | """Return true iff complexes x and y "are close\""""\r | |
65 | self.assertCloseAbs(x.real, y.real, eps)\r | |
66 | self.assertCloseAbs(x.imag, y.imag, eps)\r | |
67 | \r | |
68 | def check_div(self, x, y):\r | |
69 | """Compute complex z=x*y, and check that z/x==y and z/y==x."""\r | |
70 | z = x * y\r | |
71 | if x != 0:\r | |
72 | q = z / x\r | |
73 | self.assertClose(q, y)\r | |
74 | q = z.__div__(x)\r | |
75 | self.assertClose(q, y)\r | |
76 | q = z.__truediv__(x)\r | |
77 | self.assertClose(q, y)\r | |
78 | if y != 0:\r | |
79 | q = z / y\r | |
80 | self.assertClose(q, x)\r | |
81 | q = z.__div__(y)\r | |
82 | self.assertClose(q, x)\r | |
83 | q = z.__truediv__(y)\r | |
84 | self.assertClose(q, x)\r | |
85 | \r | |
86 | def test_div(self):\r | |
87 | simple_real = [float(i) for i in xrange(-5, 6)]\r | |
88 | simple_complex = [complex(x, y) for x in simple_real for y in simple_real]\r | |
89 | for x in simple_complex:\r | |
90 | for y in simple_complex:\r | |
91 | self.check_div(x, y)\r | |
92 | \r | |
93 | # A naive complex division algorithm (such as in 2.0) is very prone to\r | |
94 | # nonsense errors for these (overflows and underflows).\r | |
95 | self.check_div(complex(1e200, 1e200), 1+0j)\r | |
96 | self.check_div(complex(1e-200, 1e-200), 1+0j)\r | |
97 | \r | |
98 | # Just for fun.\r | |
99 | for i in xrange(100):\r | |
100 | self.check_div(complex(random(), random()),\r | |
101 | complex(random(), random()))\r | |
102 | \r | |
103 | self.assertRaises(ZeroDivisionError, complex.__div__, 1+1j, 0+0j)\r | |
104 | # FIXME: The following currently crashes on Alpha\r | |
105 | # self.assertRaises(OverflowError, pow, 1e200+1j, 1e200+1j)\r | |
106 | \r | |
107 | def test_truediv(self):\r | |
108 | self.assertAlmostEqual(complex.__truediv__(2+0j, 1+1j), 1-1j)\r | |
109 | self.assertRaises(ZeroDivisionError, complex.__truediv__, 1+1j, 0+0j)\r | |
110 | \r | |
111 | def test_floordiv(self):\r | |
112 | self.assertAlmostEqual(complex.__floordiv__(3+0j, 1.5+0j), 2)\r | |
113 | self.assertRaises(ZeroDivisionError, complex.__floordiv__, 3+0j, 0+0j)\r | |
114 | \r | |
115 | def test_coerce(self):\r | |
116 | self.assertRaises(OverflowError, complex.__coerce__, 1+1j, 1L<<10000)\r | |
117 | \r | |
118 | def test_no_implicit_coerce(self):\r | |
119 | # Python 2.7 removed implicit coercion from the complex type\r | |
120 | class A(object):\r | |
121 | def __coerce__(self, other):\r | |
122 | raise RuntimeError\r | |
123 | __hash__ = None\r | |
124 | def __cmp__(self, other):\r | |
125 | return -1\r | |
126 | \r | |
127 | a = A()\r | |
128 | self.assertRaises(TypeError, lambda: a + 2.0j)\r | |
129 | self.assertTrue(a < 2.0j)\r | |
130 | \r | |
131 | def test_richcompare(self):\r | |
132 | self.assertEqual(complex.__eq__(1+1j, 1L<<10000), False)\r | |
133 | self.assertEqual(complex.__lt__(1+1j, None), NotImplemented)\r | |
134 | self.assertIs(complex.__eq__(1+1j, 1+1j), True)\r | |
135 | self.assertIs(complex.__eq__(1+1j, 2+2j), False)\r | |
136 | self.assertIs(complex.__ne__(1+1j, 1+1j), False)\r | |
137 | self.assertIs(complex.__ne__(1+1j, 2+2j), True)\r | |
138 | self.assertRaises(TypeError, complex.__lt__, 1+1j, 2+2j)\r | |
139 | self.assertRaises(TypeError, complex.__le__, 1+1j, 2+2j)\r | |
140 | self.assertRaises(TypeError, complex.__gt__, 1+1j, 2+2j)\r | |
141 | self.assertRaises(TypeError, complex.__ge__, 1+1j, 2+2j)\r | |
142 | \r | |
143 | def test_richcompare_boundaries(self):\r | |
144 | def check(n, deltas, is_equal, imag = 0.0):\r | |
145 | for delta in deltas:\r | |
146 | i = n + delta\r | |
147 | z = complex(i, imag)\r | |
148 | self.assertIs(complex.__eq__(z, i), is_equal(delta))\r | |
149 | self.assertIs(complex.__ne__(z, i), not is_equal(delta))\r | |
150 | # For IEEE-754 doubles the following should hold:\r | |
151 | # x in [2 ** (52 + i), 2 ** (53 + i + 1)] -> x mod 2 ** i == 0\r | |
152 | # where the interval is representable, of course.\r | |
153 | for i in range(1, 10):\r | |
154 | pow = 52 + i\r | |
155 | mult = 2 ** i\r | |
156 | check(2 ** pow, range(1, 101), lambda delta: delta % mult == 0)\r | |
157 | check(2 ** pow, range(1, 101), lambda delta: False, float(i))\r | |
158 | check(2 ** 53, range(-100, 0), lambda delta: True)\r | |
159 | \r | |
160 | def test_mod(self):\r | |
161 | self.assertRaises(ZeroDivisionError, (1+1j).__mod__, 0+0j)\r | |
162 | \r | |
163 | a = 3.33+4.43j\r | |
164 | try:\r | |
165 | a % 0\r | |
166 | except ZeroDivisionError:\r | |
167 | pass\r | |
168 | else:\r | |
169 | self.fail("modulo parama can't be 0")\r | |
170 | \r | |
171 | def test_divmod(self):\r | |
172 | self.assertRaises(ZeroDivisionError, divmod, 1+1j, 0+0j)\r | |
173 | \r | |
174 | def test_pow(self):\r | |
175 | self.assertAlmostEqual(pow(1+1j, 0+0j), 1.0)\r | |
176 | self.assertAlmostEqual(pow(0+0j, 2+0j), 0.0)\r | |
177 | self.assertRaises(ZeroDivisionError, pow, 0+0j, 1j)\r | |
178 | self.assertAlmostEqual(pow(1j, -1), 1/1j)\r | |
179 | self.assertAlmostEqual(pow(1j, 200), 1)\r | |
180 | self.assertRaises(ValueError, pow, 1+1j, 1+1j, 1+1j)\r | |
181 | \r | |
182 | a = 3.33+4.43j\r | |
183 | self.assertEqual(a ** 0j, 1)\r | |
184 | self.assertEqual(a ** 0.+0.j, 1)\r | |
185 | \r | |
186 | self.assertEqual(3j ** 0j, 1)\r | |
187 | self.assertEqual(3j ** 0, 1)\r | |
188 | \r | |
189 | try:\r | |
190 | 0j ** a\r | |
191 | except ZeroDivisionError:\r | |
192 | pass\r | |
193 | else:\r | |
194 | self.fail("should fail 0.0 to negative or complex power")\r | |
195 | \r | |
196 | try:\r | |
197 | 0j ** (3-2j)\r | |
198 | except ZeroDivisionError:\r | |
199 | pass\r | |
200 | else:\r | |
201 | self.fail("should fail 0.0 to negative or complex power")\r | |
202 | \r | |
203 | # The following is used to exercise certain code paths\r | |
204 | self.assertEqual(a ** 105, a ** 105)\r | |
205 | self.assertEqual(a ** -105, a ** -105)\r | |
206 | self.assertEqual(a ** -30, a ** -30)\r | |
207 | \r | |
208 | self.assertEqual(0.0j ** 0, 1)\r | |
209 | \r | |
210 | b = 5.1+2.3j\r | |
211 | self.assertRaises(ValueError, pow, a, b, 0)\r | |
212 | \r | |
213 | def test_boolcontext(self):\r | |
214 | for i in xrange(100):\r | |
215 | self.assertTrue(complex(random() + 1e-6, random() + 1e-6))\r | |
216 | self.assertTrue(not complex(0.0, 0.0))\r | |
217 | \r | |
218 | def test_conjugate(self):\r | |
219 | self.assertClose(complex(5.3, 9.8).conjugate(), 5.3-9.8j)\r | |
220 | \r | |
221 | def test_constructor(self):\r | |
222 | class OS:\r | |
223 | def __init__(self, value): self.value = value\r | |
224 | def __complex__(self): return self.value\r | |
225 | class NS(object):\r | |
226 | def __init__(self, value): self.value = value\r | |
227 | def __complex__(self): return self.value\r | |
228 | self.assertEqual(complex(OS(1+10j)), 1+10j)\r | |
229 | self.assertEqual(complex(NS(1+10j)), 1+10j)\r | |
230 | self.assertRaises(TypeError, complex, OS(None))\r | |
231 | self.assertRaises(TypeError, complex, NS(None))\r | |
232 | \r | |
233 | self.assertAlmostEqual(complex("1+10j"), 1+10j)\r | |
234 | self.assertAlmostEqual(complex(10), 10+0j)\r | |
235 | self.assertAlmostEqual(complex(10.0), 10+0j)\r | |
236 | self.assertAlmostEqual(complex(10L), 10+0j)\r | |
237 | self.assertAlmostEqual(complex(10+0j), 10+0j)\r | |
238 | self.assertAlmostEqual(complex(1,10), 1+10j)\r | |
239 | self.assertAlmostEqual(complex(1,10L), 1+10j)\r | |
240 | self.assertAlmostEqual(complex(1,10.0), 1+10j)\r | |
241 | self.assertAlmostEqual(complex(1L,10), 1+10j)\r | |
242 | self.assertAlmostEqual(complex(1L,10L), 1+10j)\r | |
243 | self.assertAlmostEqual(complex(1L,10.0), 1+10j)\r | |
244 | self.assertAlmostEqual(complex(1.0,10), 1+10j)\r | |
245 | self.assertAlmostEqual(complex(1.0,10L), 1+10j)\r | |
246 | self.assertAlmostEqual(complex(1.0,10.0), 1+10j)\r | |
247 | self.assertAlmostEqual(complex(3.14+0j), 3.14+0j)\r | |
248 | self.assertAlmostEqual(complex(3.14), 3.14+0j)\r | |
249 | self.assertAlmostEqual(complex(314), 314.0+0j)\r | |
250 | self.assertAlmostEqual(complex(314L), 314.0+0j)\r | |
251 | self.assertAlmostEqual(complex(3.14+0j, 0j), 3.14+0j)\r | |
252 | self.assertAlmostEqual(complex(3.14, 0.0), 3.14+0j)\r | |
253 | self.assertAlmostEqual(complex(314, 0), 314.0+0j)\r | |
254 | self.assertAlmostEqual(complex(314L, 0L), 314.0+0j)\r | |
255 | self.assertAlmostEqual(complex(0j, 3.14j), -3.14+0j)\r | |
256 | self.assertAlmostEqual(complex(0.0, 3.14j), -3.14+0j)\r | |
257 | self.assertAlmostEqual(complex(0j, 3.14), 3.14j)\r | |
258 | self.assertAlmostEqual(complex(0.0, 3.14), 3.14j)\r | |
259 | self.assertAlmostEqual(complex("1"), 1+0j)\r | |
260 | self.assertAlmostEqual(complex("1j"), 1j)\r | |
261 | self.assertAlmostEqual(complex(), 0)\r | |
262 | self.assertAlmostEqual(complex("-1"), -1)\r | |
263 | self.assertAlmostEqual(complex("+1"), +1)\r | |
264 | self.assertAlmostEqual(complex("(1+2j)"), 1+2j)\r | |
265 | self.assertAlmostEqual(complex("(1.3+2.2j)"), 1.3+2.2j)\r | |
266 | self.assertAlmostEqual(complex("3.14+1J"), 3.14+1j)\r | |
267 | self.assertAlmostEqual(complex(" ( +3.14-6J )"), 3.14-6j)\r | |
268 | self.assertAlmostEqual(complex(" ( +3.14-J )"), 3.14-1j)\r | |
269 | self.assertAlmostEqual(complex(" ( +3.14+j )"), 3.14+1j)\r | |
270 | self.assertAlmostEqual(complex("J"), 1j)\r | |
271 | self.assertAlmostEqual(complex("( j )"), 1j)\r | |
272 | self.assertAlmostEqual(complex("+J"), 1j)\r | |
273 | self.assertAlmostEqual(complex("( -j)"), -1j)\r | |
274 | self.assertAlmostEqual(complex('1e-500'), 0.0 + 0.0j)\r | |
275 | self.assertAlmostEqual(complex('-1e-500j'), 0.0 - 0.0j)\r | |
276 | self.assertAlmostEqual(complex('-1e-500+1e-500j'), -0.0 + 0.0j)\r | |
277 | \r | |
278 | class complex2(complex): pass\r | |
279 | self.assertAlmostEqual(complex(complex2(1+1j)), 1+1j)\r | |
280 | self.assertAlmostEqual(complex(real=17, imag=23), 17+23j)\r | |
281 | self.assertAlmostEqual(complex(real=17+23j), 17+23j)\r | |
282 | self.assertAlmostEqual(complex(real=17+23j, imag=23), 17+46j)\r | |
283 | self.assertAlmostEqual(complex(real=1+2j, imag=3+4j), -3+5j)\r | |
284 | \r | |
285 | # check that the sign of a zero in the real or imaginary part\r | |
286 | # is preserved when constructing from two floats. (These checks\r | |
287 | # are harmless on systems without support for signed zeros.)\r | |
288 | def split_zeros(x):\r | |
289 | """Function that produces different results for 0. and -0."""\r | |
290 | return atan2(x, -1.)\r | |
291 | \r | |
292 | self.assertEqual(split_zeros(complex(1., 0.).imag), split_zeros(0.))\r | |
293 | self.assertEqual(split_zeros(complex(1., -0.).imag), split_zeros(-0.))\r | |
294 | self.assertEqual(split_zeros(complex(0., 1.).real), split_zeros(0.))\r | |
295 | self.assertEqual(split_zeros(complex(-0., 1.).real), split_zeros(-0.))\r | |
296 | \r | |
297 | c = 3.14 + 1j\r | |
298 | self.assertTrue(complex(c) is c)\r | |
299 | del c\r | |
300 | \r | |
301 | self.assertRaises(TypeError, complex, "1", "1")\r | |
302 | self.assertRaises(TypeError, complex, 1, "1")\r | |
303 | \r | |
304 | if test_support.have_unicode:\r | |
305 | self.assertEqual(complex(unicode(" 3.14+J ")), 3.14+1j)\r | |
306 | \r | |
307 | # SF bug 543840: complex(string) accepts strings with \0\r | |
308 | # Fixed in 2.3.\r | |
309 | self.assertRaises(ValueError, complex, '1+1j\0j')\r | |
310 | \r | |
311 | self.assertRaises(TypeError, int, 5+3j)\r | |
312 | self.assertRaises(TypeError, long, 5+3j)\r | |
313 | self.assertRaises(TypeError, float, 5+3j)\r | |
314 | self.assertRaises(ValueError, complex, "")\r | |
315 | self.assertRaises(TypeError, complex, None)\r | |
316 | self.assertRaises(ValueError, complex, "\0")\r | |
317 | self.assertRaises(ValueError, complex, "3\09")\r | |
318 | self.assertRaises(TypeError, complex, "1", "2")\r | |
319 | self.assertRaises(TypeError, complex, "1", 42)\r | |
320 | self.assertRaises(TypeError, complex, 1, "2")\r | |
321 | self.assertRaises(ValueError, complex, "1+")\r | |
322 | self.assertRaises(ValueError, complex, "1+1j+1j")\r | |
323 | self.assertRaises(ValueError, complex, "--")\r | |
324 | self.assertRaises(ValueError, complex, "(1+2j")\r | |
325 | self.assertRaises(ValueError, complex, "1+2j)")\r | |
326 | self.assertRaises(ValueError, complex, "1+(2j)")\r | |
327 | self.assertRaises(ValueError, complex, "(1+2j)123")\r | |
328 | if test_support.have_unicode:\r | |
329 | self.assertRaises(ValueError, complex, unicode("x"))\r | |
330 | self.assertRaises(ValueError, complex, "1j+2")\r | |
331 | self.assertRaises(ValueError, complex, "1e1ej")\r | |
332 | self.assertRaises(ValueError, complex, "1e++1ej")\r | |
333 | self.assertRaises(ValueError, complex, ")1+2j(")\r | |
334 | # the following three are accepted by Python 2.6\r | |
335 | self.assertRaises(ValueError, complex, "1..1j")\r | |
336 | self.assertRaises(ValueError, complex, "1.11.1j")\r | |
337 | self.assertRaises(ValueError, complex, "1e1.1j")\r | |
338 | \r | |
339 | if test_support.have_unicode:\r | |
340 | # check that complex accepts long unicode strings\r | |
341 | self.assertEqual(type(complex(unicode("1"*500))), complex)\r | |
342 | \r | |
343 | class EvilExc(Exception):\r | |
344 | pass\r | |
345 | \r | |
346 | class evilcomplex:\r | |
347 | def __complex__(self):\r | |
348 | raise EvilExc\r | |
349 | \r | |
350 | self.assertRaises(EvilExc, complex, evilcomplex())\r | |
351 | \r | |
352 | class float2:\r | |
353 | def __init__(self, value):\r | |
354 | self.value = value\r | |
355 | def __float__(self):\r | |
356 | return self.value\r | |
357 | \r | |
358 | self.assertAlmostEqual(complex(float2(42.)), 42)\r | |
359 | self.assertAlmostEqual(complex(real=float2(17.), imag=float2(23.)), 17+23j)\r | |
360 | self.assertRaises(TypeError, complex, float2(None))\r | |
361 | \r | |
362 | class complex0(complex):\r | |
363 | """Test usage of __complex__() when inheriting from 'complex'"""\r | |
364 | def __complex__(self):\r | |
365 | return 42j\r | |
366 | \r | |
367 | class complex1(complex):\r | |
368 | """Test usage of __complex__() with a __new__() method"""\r | |
369 | def __new__(self, value=0j):\r | |
370 | return complex.__new__(self, 2*value)\r | |
371 | def __complex__(self):\r | |
372 | return self\r | |
373 | \r | |
374 | class complex2(complex):\r | |
375 | """Make sure that __complex__() calls fail if anything other than a\r | |
376 | complex is returned"""\r | |
377 | def __complex__(self):\r | |
378 | return None\r | |
379 | \r | |
380 | self.assertAlmostEqual(complex(complex0(1j)), 42j)\r | |
381 | self.assertAlmostEqual(complex(complex1(1j)), 2j)\r | |
382 | self.assertRaises(TypeError, complex, complex2(1j))\r | |
383 | \r | |
384 | def test_subclass(self):\r | |
385 | class xcomplex(complex):\r | |
386 | def __add__(self,other):\r | |
387 | return xcomplex(complex(self) + other)\r | |
388 | __radd__ = __add__\r | |
389 | \r | |
390 | def __sub__(self,other):\r | |
391 | return xcomplex(complex(self) + other)\r | |
392 | __rsub__ = __sub__\r | |
393 | \r | |
394 | def __mul__(self,other):\r | |
395 | return xcomplex(complex(self) * other)\r | |
396 | __rmul__ = __mul__\r | |
397 | \r | |
398 | def __div__(self,other):\r | |
399 | return xcomplex(complex(self) / other)\r | |
400 | \r | |
401 | def __rdiv__(self,other):\r | |
402 | return xcomplex(other / complex(self))\r | |
403 | \r | |
404 | __truediv__ = __div__\r | |
405 | __rtruediv__ = __rdiv__\r | |
406 | \r | |
407 | def __floordiv__(self,other):\r | |
408 | return xcomplex(complex(self) // other)\r | |
409 | \r | |
410 | def __rfloordiv__(self,other):\r | |
411 | return xcomplex(other // complex(self))\r | |
412 | \r | |
413 | def __pow__(self,other):\r | |
414 | return xcomplex(complex(self) ** other)\r | |
415 | \r | |
416 | def __rpow__(self,other):\r | |
417 | return xcomplex(other ** complex(self) )\r | |
418 | \r | |
419 | def __mod__(self,other):\r | |
420 | return xcomplex(complex(self) % other)\r | |
421 | \r | |
422 | def __rmod__(self,other):\r | |
423 | return xcomplex(other % complex(self))\r | |
424 | \r | |
425 | infix_binops = ('+', '-', '*', '**', '%', '//', '/')\r | |
426 | xcomplex_values = (xcomplex(1), xcomplex(123.0),\r | |
427 | xcomplex(-10+2j), xcomplex(3+187j),\r | |
428 | xcomplex(3-78j))\r | |
429 | test_values = (1, 123.0, 10-19j, xcomplex(1+2j),\r | |
430 | xcomplex(1+87j), xcomplex(10+90j))\r | |
431 | \r | |
432 | for op in infix_binops:\r | |
433 | for x in xcomplex_values:\r | |
434 | for y in test_values:\r | |
435 | a = 'x %s y' % op\r | |
436 | b = 'y %s x' % op\r | |
437 | self.assertTrue(type(eval(a)) is type(eval(b)) is xcomplex)\r | |
438 | \r | |
439 | def test_hash(self):\r | |
440 | for x in xrange(-30, 30):\r | |
441 | self.assertEqual(hash(x), hash(complex(x, 0)))\r | |
442 | x /= 3.0 # now check against floating point\r | |
443 | self.assertEqual(hash(x), hash(complex(x, 0.)))\r | |
444 | \r | |
445 | def test_abs(self):\r | |
446 | nums = [complex(x/3., y/7.) for x in xrange(-9,9) for y in xrange(-9,9)]\r | |
447 | for num in nums:\r | |
448 | self.assertAlmostEqual((num.real**2 + num.imag**2) ** 0.5, abs(num))\r | |
449 | \r | |
450 | def test_repr(self):\r | |
451 | self.assertEqual(repr(1+6j), '(1+6j)')\r | |
452 | self.assertEqual(repr(1-6j), '(1-6j)')\r | |
453 | \r | |
454 | self.assertNotEqual(repr(-(1+0j)), '(-1+-0j)')\r | |
455 | \r | |
456 | self.assertEqual(1-6j,complex(repr(1-6j)))\r | |
457 | self.assertEqual(1+6j,complex(repr(1+6j)))\r | |
458 | self.assertEqual(-6j,complex(repr(-6j)))\r | |
459 | self.assertEqual(6j,complex(repr(6j)))\r | |
460 | \r | |
461 | self.assertEqual(repr(complex(1., INF)), "(1+infj)")\r | |
462 | self.assertEqual(repr(complex(1., -INF)), "(1-infj)")\r | |
463 | self.assertEqual(repr(complex(INF, 1)), "(inf+1j)")\r | |
464 | self.assertEqual(repr(complex(-INF, INF)), "(-inf+infj)")\r | |
465 | self.assertEqual(repr(complex(NAN, 1)), "(nan+1j)")\r | |
466 | self.assertEqual(repr(complex(1, NAN)), "(1+nanj)")\r | |
467 | self.assertEqual(repr(complex(NAN, NAN)), "(nan+nanj)")\r | |
468 | \r | |
469 | self.assertEqual(repr(complex(0, INF)), "infj")\r | |
470 | self.assertEqual(repr(complex(0, -INF)), "-infj")\r | |
471 | self.assertEqual(repr(complex(0, NAN)), "nanj")\r | |
472 | \r | |
473 | def test_neg(self):\r | |
474 | self.assertEqual(-(1+6j), -1-6j)\r | |
475 | \r | |
476 | def test_file(self):\r | |
477 | a = 3.33+4.43j\r | |
478 | b = 5.1+2.3j\r | |
479 | \r | |
480 | fo = None\r | |
481 | try:\r | |
482 | fo = open(test_support.TESTFN, "wb")\r | |
483 | print >>fo, a, b\r | |
484 | fo.close()\r | |
485 | fo = open(test_support.TESTFN, "rb")\r | |
486 | self.assertEqual(fo.read(), "%s %s\n" % (a, b))\r | |
487 | finally:\r | |
488 | if (fo is not None) and (not fo.closed):\r | |
489 | fo.close()\r | |
490 | test_support.unlink(test_support.TESTFN)\r | |
491 | \r | |
492 | def test_getnewargs(self):\r | |
493 | self.assertEqual((1+2j).__getnewargs__(), (1.0, 2.0))\r | |
494 | self.assertEqual((1-2j).__getnewargs__(), (1.0, -2.0))\r | |
495 | self.assertEqual((2j).__getnewargs__(), (0.0, 2.0))\r | |
496 | self.assertEqual((-0j).__getnewargs__(), (0.0, -0.0))\r | |
497 | self.assertEqual(complex(0, INF).__getnewargs__(), (0.0, INF))\r | |
498 | self.assertEqual(complex(INF, 0).__getnewargs__(), (INF, 0.0))\r | |
499 | \r | |
500 | if float.__getformat__("double").startswith("IEEE"):\r | |
501 | def test_plus_minus_0j(self):\r | |
502 | # test that -0j and 0j literals are not identified\r | |
503 | z1, z2 = 0j, -0j\r | |
504 | self.assertEqual(atan2(z1.imag, -1.), atan2(0., -1.))\r | |
505 | self.assertEqual(atan2(z2.imag, -1.), atan2(-0., -1.))\r | |
506 | \r | |
507 | @unittest.skipUnless(float.__getformat__("double").startswith("IEEE"),\r | |
508 | "test requires IEEE 754 doubles")\r | |
509 | def test_overflow(self):\r | |
510 | self.assertEqual(complex("1e500"), complex(INF, 0.0))\r | |
511 | self.assertEqual(complex("-1e500j"), complex(0.0, -INF))\r | |
512 | self.assertEqual(complex("-1e500+1.8e308j"), complex(-INF, INF))\r | |
513 | \r | |
514 | @unittest.skipUnless(float.__getformat__("double").startswith("IEEE"),\r | |
515 | "test requires IEEE 754 doubles")\r | |
516 | def test_repr_roundtrip(self):\r | |
517 | vals = [0.0, 1e-500, 1e-315, 1e-200, 0.0123, 3.1415, 1e50, INF, NAN]\r | |
518 | vals += [-v for v in vals]\r | |
519 | \r | |
520 | # complex(repr(z)) should recover z exactly, even for complex\r | |
521 | # numbers involving an infinity, nan, or negative zero\r | |
522 | for x in vals:\r | |
523 | for y in vals:\r | |
524 | z = complex(x, y)\r | |
525 | roundtrip = complex(repr(z))\r | |
526 | self.assertFloatsAreIdentical(z.real, roundtrip.real)\r | |
527 | self.assertFloatsAreIdentical(z.imag, roundtrip.imag)\r | |
528 | \r | |
529 | # if we predefine some constants, then eval(repr(z)) should\r | |
530 | # also work, except that it might change the sign of zeros\r | |
531 | inf, nan = float('inf'), float('nan')\r | |
532 | infj, nanj = complex(0.0, inf), complex(0.0, nan)\r | |
533 | for x in vals:\r | |
534 | for y in vals:\r | |
535 | z = complex(x, y)\r | |
536 | roundtrip = eval(repr(z))\r | |
537 | # adding 0.0 has no effect beside changing -0.0 to 0.0\r | |
538 | self.assertFloatsAreIdentical(0.0 + z.real,\r | |
539 | 0.0 + roundtrip.real)\r | |
540 | self.assertFloatsAreIdentical(0.0 + z.imag,\r | |
541 | 0.0 + roundtrip.imag)\r | |
542 | \r | |
543 | def test_format(self):\r | |
544 | # empty format string is same as str()\r | |
545 | self.assertEqual(format(1+3j, ''), str(1+3j))\r | |
546 | self.assertEqual(format(1.5+3.5j, ''), str(1.5+3.5j))\r | |
547 | self.assertEqual(format(3j, ''), str(3j))\r | |
548 | self.assertEqual(format(3.2j, ''), str(3.2j))\r | |
549 | self.assertEqual(format(3+0j, ''), str(3+0j))\r | |
550 | self.assertEqual(format(3.2+0j, ''), str(3.2+0j))\r | |
551 | \r | |
552 | # empty presentation type should still be analogous to str,\r | |
553 | # even when format string is nonempty (issue #5920).\r | |
554 | self.assertEqual(format(3.2+0j, '-'), str(3.2+0j))\r | |
555 | self.assertEqual(format(3.2+0j, '<'), str(3.2+0j))\r | |
556 | z = 4/7. - 100j/7.\r | |
557 | self.assertEqual(format(z, ''), str(z))\r | |
558 | self.assertEqual(format(z, '-'), str(z))\r | |
559 | self.assertEqual(format(z, '<'), str(z))\r | |
560 | self.assertEqual(format(z, '10'), str(z))\r | |
561 | z = complex(0.0, 3.0)\r | |
562 | self.assertEqual(format(z, ''), str(z))\r | |
563 | self.assertEqual(format(z, '-'), str(z))\r | |
564 | self.assertEqual(format(z, '<'), str(z))\r | |
565 | self.assertEqual(format(z, '2'), str(z))\r | |
566 | z = complex(-0.0, 2.0)\r | |
567 | self.assertEqual(format(z, ''), str(z))\r | |
568 | self.assertEqual(format(z, '-'), str(z))\r | |
569 | self.assertEqual(format(z, '<'), str(z))\r | |
570 | self.assertEqual(format(z, '3'), str(z))\r | |
571 | \r | |
572 | self.assertEqual(format(1+3j, 'g'), '1+3j')\r | |
573 | self.assertEqual(format(3j, 'g'), '0+3j')\r | |
574 | self.assertEqual(format(1.5+3.5j, 'g'), '1.5+3.5j')\r | |
575 | \r | |
576 | self.assertEqual(format(1.5+3.5j, '+g'), '+1.5+3.5j')\r | |
577 | self.assertEqual(format(1.5-3.5j, '+g'), '+1.5-3.5j')\r | |
578 | self.assertEqual(format(1.5-3.5j, '-g'), '1.5-3.5j')\r | |
579 | self.assertEqual(format(1.5+3.5j, ' g'), ' 1.5+3.5j')\r | |
580 | self.assertEqual(format(1.5-3.5j, ' g'), ' 1.5-3.5j')\r | |
581 | self.assertEqual(format(-1.5+3.5j, ' g'), '-1.5+3.5j')\r | |
582 | self.assertEqual(format(-1.5-3.5j, ' g'), '-1.5-3.5j')\r | |
583 | \r | |
584 | self.assertEqual(format(-1.5-3.5e-20j, 'g'), '-1.5-3.5e-20j')\r | |
585 | self.assertEqual(format(-1.5-3.5j, 'f'), '-1.500000-3.500000j')\r | |
586 | self.assertEqual(format(-1.5-3.5j, 'F'), '-1.500000-3.500000j')\r | |
587 | self.assertEqual(format(-1.5-3.5j, 'e'), '-1.500000e+00-3.500000e+00j')\r | |
588 | self.assertEqual(format(-1.5-3.5j, '.2e'), '-1.50e+00-3.50e+00j')\r | |
589 | self.assertEqual(format(-1.5-3.5j, '.2E'), '-1.50E+00-3.50E+00j')\r | |
590 | self.assertEqual(format(-1.5e10-3.5e5j, '.2G'), '-1.5E+10-3.5E+05j')\r | |
591 | \r | |
592 | self.assertEqual(format(1.5+3j, '<20g'), '1.5+3j ')\r | |
593 | self.assertEqual(format(1.5+3j, '*<20g'), '1.5+3j**************')\r | |
594 | self.assertEqual(format(1.5+3j, '>20g'), ' 1.5+3j')\r | |
595 | self.assertEqual(format(1.5+3j, '^20g'), ' 1.5+3j ')\r | |
596 | self.assertEqual(format(1.5+3j, '<20'), '(1.5+3j) ')\r | |
597 | self.assertEqual(format(1.5+3j, '>20'), ' (1.5+3j)')\r | |
598 | self.assertEqual(format(1.5+3j, '^20'), ' (1.5+3j) ')\r | |
599 | self.assertEqual(format(1.123-3.123j, '^20.2'), ' (1.1-3.1j) ')\r | |
600 | \r | |
601 | self.assertEqual(format(1.5+3j, '20.2f'), ' 1.50+3.00j')\r | |
602 | self.assertEqual(format(1.5+3j, '>20.2f'), ' 1.50+3.00j')\r | |
603 | self.assertEqual(format(1.5+3j, '<20.2f'), '1.50+3.00j ')\r | |
604 | self.assertEqual(format(1.5e20+3j, '<20.2f'), '150000000000000000000.00+3.00j')\r | |
605 | self.assertEqual(format(1.5e20+3j, '>40.2f'), ' 150000000000000000000.00+3.00j')\r | |
606 | self.assertEqual(format(1.5e20+3j, '^40,.2f'), ' 150,000,000,000,000,000,000.00+3.00j ')\r | |
607 | self.assertEqual(format(1.5e21+3j, '^40,.2f'), ' 1,500,000,000,000,000,000,000.00+3.00j ')\r | |
608 | self.assertEqual(format(1.5e21+3000j, ',.2f'), '1,500,000,000,000,000,000,000.00+3,000.00j')\r | |
609 | \r | |
610 | # alternate is invalid\r | |
611 | self.assertRaises(ValueError, (1.5+0.5j).__format__, '#f')\r | |
612 | \r | |
613 | # zero padding is invalid\r | |
614 | self.assertRaises(ValueError, (1.5+0.5j).__format__, '010f')\r | |
615 | \r | |
616 | # '=' alignment is invalid\r | |
617 | self.assertRaises(ValueError, (1.5+3j).__format__, '=20')\r | |
618 | \r | |
619 | # integer presentation types are an error\r | |
620 | for t in 'bcdoxX':\r | |
621 | self.assertRaises(ValueError, (1.5+0.5j).__format__, t)\r | |
622 | \r | |
623 | # make sure everything works in ''.format()\r | |
624 | self.assertEqual('*{0:.3f}*'.format(3.14159+2.71828j), '*3.142+2.718j*')\r | |
625 | \r | |
626 | # issue 3382: 'f' and 'F' with inf's and nan's\r | |
627 | self.assertEqual('{0:f}'.format(INF+0j), 'inf+0.000000j')\r | |
628 | self.assertEqual('{0:F}'.format(INF+0j), 'INF+0.000000j')\r | |
629 | self.assertEqual('{0:f}'.format(-INF+0j), '-inf+0.000000j')\r | |
630 | self.assertEqual('{0:F}'.format(-INF+0j), '-INF+0.000000j')\r | |
631 | self.assertEqual('{0:f}'.format(complex(INF, INF)), 'inf+infj')\r | |
632 | self.assertEqual('{0:F}'.format(complex(INF, INF)), 'INF+INFj')\r | |
633 | self.assertEqual('{0:f}'.format(complex(INF, -INF)), 'inf-infj')\r | |
634 | self.assertEqual('{0:F}'.format(complex(INF, -INF)), 'INF-INFj')\r | |
635 | self.assertEqual('{0:f}'.format(complex(-INF, INF)), '-inf+infj')\r | |
636 | self.assertEqual('{0:F}'.format(complex(-INF, INF)), '-INF+INFj')\r | |
637 | self.assertEqual('{0:f}'.format(complex(-INF, -INF)), '-inf-infj')\r | |
638 | self.assertEqual('{0:F}'.format(complex(-INF, -INF)), '-INF-INFj')\r | |
639 | \r | |
640 | self.assertEqual('{0:f}'.format(complex(NAN, 0)), 'nan+0.000000j')\r | |
641 | self.assertEqual('{0:F}'.format(complex(NAN, 0)), 'NAN+0.000000j')\r | |
642 | self.assertEqual('{0:f}'.format(complex(NAN, NAN)), 'nan+nanj')\r | |
643 | self.assertEqual('{0:F}'.format(complex(NAN, NAN)), 'NAN+NANj')\r | |
644 | \r | |
645 | def test_main():\r | |
646 | with test_support.check_warnings(("complex divmod.., // and % are "\r | |
647 | "deprecated", DeprecationWarning)):\r | |
648 | test_support.run_unittest(ComplexTest)\r | |
649 | \r | |
650 | if __name__ == "__main__":\r | |
651 | test_main()\r |