summaryrefslogtreecommitdiffstats
path: root/Lib/test/test_complex.py
diff options
context:
space:
mode:
authorWalter Dörwald <walter@livinglogic.de>2003-06-18 14:26:18 (GMT)
committerWalter Dörwald <walter@livinglogic.de>2003-06-18 14:26:18 (GMT)
commit5edd785bbb1825e8b4e89525b2dad0cec3a9394d (patch)
treeaef1f6d1f199651adac94048dfd1b71b524ab94f /Lib/test/test_complex.py
parent39c5d666c94f796e4cf0beadb75f5f248f19ee7c (diff)
downloadcpython-5edd785bbb1825e8b4e89525b2dad0cec3a9394d.zip
cpython-5edd785bbb1825e8b4e89525b2dad0cec3a9394d.tar.gz
cpython-5edd785bbb1825e8b4e89525b2dad0cec3a9394d.tar.bz2
Port test_complex.py to unittest.
Move the constructor tests from test_builtin to test_complex. Add a bunch of tests (code coverage is a 94%). From SF patch #736962.
Diffstat (limited to 'Lib/test/test_complex.py')
-rw-r--r--Lib/test/test_complex.py338
1 files changed, 249 insertions, 89 deletions
diff --git a/Lib/test/test_complex.py b/Lib/test/test_complex.py
index 8a02f7f..0963bcc 100644
--- a/Lib/test/test_complex.py
+++ b/Lib/test/test_complex.py
@@ -1,91 +1,251 @@
-from test.test_support import TestFailed, vereq
+import unittest
+from test import test_support
+
+import warnings
+warnings.filterwarnings(
+ "ignore",
+ category=DeprecationWarning,
+ message=".*complex divmod.*are deprecated"
+)
+
from random import random
-# These tests ensure that complex math does the right thing; tests of
-# the complex() function/constructor are in test_b1.py.
-
-# XXX need many, many more tests here.
-
-nerrors = 0
-
-def check_close_real(x, y, eps=1e-9):
- """Return true iff floats x and y "are close\""""
- # put the one with larger magnitude second
- if abs(x) > abs(y):
- x, y = y, x
- if y == 0:
- return abs(x) < eps
- if x == 0:
- return abs(y) < eps
- # check that relative difference < eps
- return abs((x-y)/y) < eps
-
-def check_close(x, y, eps=1e-9):
- """Return true iff complexes x and y "are close\""""
- return check_close_real(x.real, y.real, eps) and \
- check_close_real(x.imag, y.imag, eps)
-
-def test_div(x, y):
- """Compute complex z=x*y, and check that z/x==y and z/y==x."""
- global nerrors
- z = x * y
- if x != 0:
- q = z / x
- if not check_close(q, y):
- nerrors += 1
- print "%r / %r == %r but expected %r" % (z, x, q, y)
- if y != 0:
- q = z / y
- if not check_close(q, x):
- nerrors += 1
- print "%r / %r == %r but expected %r" % (z, y, q, x)
-
-simple_real = [float(i) for i in range(-5, 6)]
-simple_complex = [complex(x, y) for x in simple_real for y in simple_real]
-for x in simple_complex:
- for y in simple_complex:
- test_div(x, y)
-
-# A naive complex division algorithm (such as in 2.0) is very prone to
-# nonsense errors for these (overflows and underflows).
-test_div(complex(1e200, 1e200), 1+0j)
-test_div(complex(1e-200, 1e-200), 1+0j)
-
-# Just for fun.
-for i in range(100):
- test_div(complex(random(), random()),
- complex(random(), random()))
-
-for i in range(100):
- if not complex(random() + 1e-6, random() + 1e-6):
- raise TestFailed("complex(random(), random()) should be true")
-
-if complex(0.0, 0.0):
- raise TestFailed("complex(0.0, 0.0) should be false")
-
-vereq(complex(5.3, 9.8).conjugate(), 5.3-9.8j)
-
-try:
- print int(5+3j)
-except TypeError:
- pass
-else:
- raise TestFailed("int(complex()) didn't raise TypeError")
-
-try:
- print float(5+3j)
-except TypeError:
- pass
-else:
- raise TestFailed("float(complex()) didn't raise TypeError")
-
-try:
- z = 1.0 / (0+0j)
-except ZeroDivisionError:
- pass
-else:
- nerrors += 1
- raise TestFailed("Division by complex 0 didn't raise ZeroDivisionError")
-
-if nerrors:
- raise TestFailed("%d tests failed" % nerrors)
+# These tests ensure that complex math does the right thing
+
+class ComplexTest(unittest.TestCase):
+
+ def assertAlmostEqual(self, a, b):
+ if isinstance(a, complex):
+ if isinstance(b, complex):
+ unittest.TestCase.assertAlmostEqual(self, a.real, b.real)
+ unittest.TestCase.assertAlmostEqual(self, a.imag, b.imag)
+ else:
+ unittest.TestCase.assertAlmostEqual(self, a.real, b)
+ unittest.TestCase.assertAlmostEqual(self, a.imag, 0.)
+ else:
+ if isinstance(b, complex):
+ unittest.TestCase.assertAlmostEqual(self, a, b.real)
+ unittest.TestCase.assertAlmostEqual(self, 0., b.imag)
+ else:
+ unittest.TestCase.assertAlmostEqual(self, a, b)
+
+ def assertCloseAbs(self, x, y, eps=1e-9):
+ """Return true iff floats x and y "are close\""""
+ # put the one with larger magnitude second
+ if abs(x) > abs(y):
+ x, y = y, x
+ if y == 0:
+ return abs(x) < eps
+ if x == 0:
+ return abs(y) < eps
+ # check that relative difference < eps
+ self.assert_(abs((x-y)/y) < eps)
+
+ def assertClose(self, x, y, eps=1e-9):
+ """Return true iff complexes x and y "are close\""""
+ self.assertCloseAbs(x.real, y.real, eps)
+ self.assertCloseAbs(x.imag, y.imag, eps)
+
+ def assertIs(self, a, b):
+ self.assert_(a is b)
+
+ def check_div(self, x, y):
+ """Compute complex z=x*y, and check that z/x==y and z/y==x."""
+ z = x * y
+ if x != 0:
+ q = z / x
+ self.assertClose(q, y)
+ if y != 0:
+ q = z / y
+ self.assertClose(q, x)
+
+ def test_div(self):
+ simple_real = [float(i) for i in xrange(-5, 6)]
+ simple_complex = [complex(x, y) for x in simple_real for y in simple_real]
+ for x in simple_complex:
+ for y in simple_complex:
+ self.check_div(x, y)
+
+ # A naive complex division algorithm (such as in 2.0) is very prone to
+ # nonsense errors for these (overflows and underflows).
+ self.check_div(complex(1e200, 1e200), 1+0j)
+ self.check_div(complex(1e-200, 1e-200), 1+0j)
+
+ # Just for fun.
+ for i in xrange(100):
+ self.check_div(complex(random(), random()),
+ complex(random(), random()))
+
+ self.assertRaises(ZeroDivisionError, complex.__div__, 1+1j, 0+0j)
+ # FIXME: The following currently crashes on Alpha
+ # self.assertRaises(OverflowError, pow, 1e200+1j, 1e200+1j)
+
+ def test_truediv(self):
+ self.assertAlmostEqual(complex.__truediv__(2+0j, 1+1j), 1-1j)
+ self.assertRaises(ZeroDivisionError, complex.__truediv__, 1+1j, 0+0j)
+
+ def test_floordiv(self):
+ self.assertAlmostEqual(complex.__floordiv__(3+0j, 1.5+0j), 2)
+ self.assertRaises(ZeroDivisionError, complex.__floordiv__, 3+0j, 0+0j)
+
+ def test_coerce(self):
+ self.assertRaises(OverflowError, complex.__coerce__, 1+1j, 1L<<10000)
+
+ def test_richcompare(self):
+ self.assertRaises(OverflowError, complex.__eq__, 1+1j, 1L<<10000)
+ self.assertEqual(complex.__lt__(1+1j, None), NotImplemented)
+ self.assertIs(complex.__eq__(1+1j, 1+1j), True)
+ self.assertIs(complex.__eq__(1+1j, 2+2j), False)
+ self.assertIs(complex.__ne__(1+1j, 1+1j), False)
+ self.assertIs(complex.__ne__(1+1j, 2+2j), True)
+ self.assertRaises(TypeError, complex.__lt__, 1+1j, 2+2j)
+ self.assertRaises(TypeError, complex.__le__, 1+1j, 2+2j)
+ self.assertRaises(TypeError, complex.__gt__, 1+1j, 2+2j)
+ self.assertRaises(TypeError, complex.__ge__, 1+1j, 2+2j)
+
+ def test_mod(self):
+ self.assertRaises(ZeroDivisionError, (1+1j).__mod__, 0+0j)
+
+ def test_divmod(self):
+ self.assertRaises(ZeroDivisionError, divmod, 1+1j, 0+0j)
+
+ def test_pow(self):
+ self.assertAlmostEqual(pow(1+1j, 0+0j), 1.0)
+ self.assertAlmostEqual(pow(0+0j, 2+0j), 0.0)
+ self.assertRaises(ZeroDivisionError, pow, 0+0j, 1j)
+ self.assertAlmostEqual(pow(1j, -1), 1/1j)
+ self.assertAlmostEqual(pow(1j, 200), 1)
+ self.assertRaises(ValueError, pow, 1+1j, 1+1j, 1+1j)
+
+ def test_boolcontext(self):
+ for i in xrange(100):
+ self.assert_(complex(random() + 1e-6, random() + 1e-6))
+ self.assert_(not complex(0.0, 0.0))
+
+ def test_conjugate(self):
+ self.assertClose(complex(5.3, 9.8).conjugate(), 5.3-9.8j)
+
+ def test_constructor(self):
+ class OS:
+ def __init__(self, value): self.value = value
+ def __complex__(self): return self.value
+ class NS(object):
+ def __init__(self, value): self.value = value
+ def __complex__(self): return self.value
+ self.assertEqual(complex(OS(1+10j)), 1+10j)
+ self.assertEqual(complex(NS(1+10j)), 1+10j)
+ self.assertRaises(TypeError, complex, OS(None))
+ self.assertRaises(TypeError, complex, NS(None))
+
+ self.assertAlmostEqual(complex("1+10j"), 1+10j)
+ self.assertAlmostEqual(complex(10), 10+0j)
+ self.assertAlmostEqual(complex(10.0), 10+0j)
+ self.assertAlmostEqual(complex(10L), 10+0j)
+ self.assertAlmostEqual(complex(10+0j), 10+0j)
+ self.assertAlmostEqual(complex(1,10), 1+10j)
+ self.assertAlmostEqual(complex(1,10L), 1+10j)
+ self.assertAlmostEqual(complex(1,10.0), 1+10j)
+ self.assertAlmostEqual(complex(1L,10), 1+10j)
+ self.assertAlmostEqual(complex(1L,10L), 1+10j)
+ self.assertAlmostEqual(complex(1L,10.0), 1+10j)
+ self.assertAlmostEqual(complex(1.0,10), 1+10j)
+ self.assertAlmostEqual(complex(1.0,10L), 1+10j)
+ self.assertAlmostEqual(complex(1.0,10.0), 1+10j)
+ self.assertAlmostEqual(complex(3.14+0j), 3.14+0j)
+ self.assertAlmostEqual(complex(3.14), 3.14+0j)
+ self.assertAlmostEqual(complex(314), 314.0+0j)
+ self.assertAlmostEqual(complex(314L), 314.0+0j)
+ self.assertAlmostEqual(complex(3.14+0j, 0j), 3.14+0j)
+ self.assertAlmostEqual(complex(3.14, 0.0), 3.14+0j)
+ self.assertAlmostEqual(complex(314, 0), 314.0+0j)
+ self.assertAlmostEqual(complex(314L, 0L), 314.0+0j)
+ self.assertAlmostEqual(complex(0j, 3.14j), -3.14+0j)
+ self.assertAlmostEqual(complex(0.0, 3.14j), -3.14+0j)
+ self.assertAlmostEqual(complex(0j, 3.14), 3.14j)
+ self.assertAlmostEqual(complex(0.0, 3.14), 3.14j)
+ self.assertAlmostEqual(complex("1"), 1+0j)
+ self.assertAlmostEqual(complex("1j"), 1j)
+ self.assertAlmostEqual(complex(), 0)
+ self.assertAlmostEqual(complex("-1"), -1)
+ self.assertAlmostEqual(complex("+1"), +1)
+
+ class complex2(complex): pass
+ self.assertAlmostEqual(complex(complex2(1+1j)), 1+1j)
+ self.assertAlmostEqual(complex(real=17, imag=23), 17+23j)
+ self.assertAlmostEqual(complex(real=17+23j), 17+23j)
+ self.assertAlmostEqual(complex(real=17+23j, imag=23), 17+46j)
+ self.assertAlmostEqual(complex(real=1+2j, imag=3+4j), -3+5j)
+
+ c = 3.14 + 1j
+ self.assert_(complex(c) is c)
+ del c
+
+ self.assertRaises(TypeError, complex, "1", "1")
+ self.assertRaises(TypeError, complex, 1, "1")
+
+ self.assertEqual(complex(" 3.14+J "), 3.14+1j)
+ if test_support.have_unicode:
+ self.assertEqual(complex(unicode(" 3.14+J ")), 3.14+1j)
+
+ # SF bug 543840: complex(string) accepts strings with \0
+ # Fixed in 2.3.
+ self.assertRaises(ValueError, complex, '1+1j\0j')
+
+ self.assertRaises(TypeError, int, 5+3j)
+ self.assertRaises(TypeError, long, 5+3j)
+ self.assertRaises(TypeError, float, 5+3j)
+ self.assertRaises(ValueError, complex, "")
+ self.assertRaises(TypeError, complex, None)
+ self.assertRaises(ValueError, complex, "\0")
+ self.assertRaises(TypeError, complex, "1", "2")
+ self.assertRaises(TypeError, complex, "1", 42)
+ self.assertRaises(TypeError, complex, 1, "2")
+ self.assertRaises(ValueError, complex, "1+")
+ self.assertRaises(ValueError, complex, "1+1j+1j")
+ self.assertRaises(ValueError, complex, "--")
+ if test_support.have_unicode:
+ self.assertRaises(ValueError, complex, unicode("1"*500))
+ self.assertRaises(ValueError, complex, unicode("x"))
+
+ class EvilExc(Exception):
+ pass
+
+ class evilcomplex:
+ def __complex__(self):
+ raise EvilExc
+
+ self.assertRaises(EvilExc, complex, evilcomplex())
+
+ class float2:
+ def __init__(self, value):
+ self.value = value
+ def __float__(self):
+ return self.value
+
+ self.assertAlmostEqual(complex(float2(42.)), 42)
+ self.assertAlmostEqual(complex(real=float2(17.), imag=float2(23.)), 17+23j)
+ self.assertRaises(TypeError, complex, float2(None))
+
+ def test_hash(self):
+ for x in xrange(-30, 30):
+ self.assertEqual(hash(x), hash(complex(x, 0)))
+ x /= 3.0 # now check against floating point
+ self.assertEqual(hash(x), hash(complex(x, 0.)))
+
+ def test_abs(self):
+ nums = [complex(x/3., y/7.) for x in xrange(-9,9) for y in xrange(-9,9)]
+ for num in nums:
+ self.assertAlmostEqual((num.real**2 + num.imag**2) ** 0.5, abs(num))
+
+ def test_repr(self):
+ self.assertEqual(repr(1+6j), '(1+6j)')
+
+ def test_neg(self):
+ self.assertEqual(-(1+6j), -1-6j)
+
+
+def test_main():
+ test_support.run_unittest(ComplexTest)
+
+if __name__ == "__main__":
+ test_main()