1 from test
.test_support
import run_unittest
2 from test
.test_math
import parse_testfile
, test_file
6 from cmath
import phase
, polar
, rect
, pi
11 complex_zeros
= [complex(x
, y
) for x
in [0.0, -0.0] for y
in [0.0, -0.0]]
12 complex_infinities
= [complex(x
, y
) for x
, y
in [
13 (INF
, 0.0), # 1st quadrant
18 (-0.0, INF
), # 2nd quadrant
23 (-INF
, -0.0), # 3rd quadrant
28 (0.0, -INF
), # 4th quadrant
34 complex_nans
= [complex(x
, y
) for x
, y
in [
49 class CMathTests(unittest
.TestCase
):
50 # list of all functions in cmath
51 test_functions
= [getattr(cmath
, fname
) for fname
in [
52 'acos', 'acosh', 'asin', 'asinh', 'atan', 'atanh',
53 'cos', 'cosh', 'exp', 'log', 'log10', 'sin', 'sinh',
54 'sqrt', 'tan', 'tanh']]
55 # test first and second arguments independently for 2-argument log
56 test_functions
.append(lambda x
: cmath
.log(x
, 1729. + 0j
))
57 test_functions
.append(lambda x
: cmath
.log(14.-27j
, x
))
60 self
.test_values
= open(test_file
)
63 self
.test_values
.close()
65 def rAssertAlmostEqual(self
, a
, b
, rel_err
= 2e-15, abs_err
= 5e-323,
67 """Fail if the two floating-point numbers are not almost equal.
69 Determine whether floating-point values a and b are equal to within
70 a (small) rounding error. The default values for rel_err and
71 abs_err are chosen to be suitable for platforms where a float is
72 represented by an IEEE 754 double. They allow an error of between
76 # special values testing
80 self
.fail(msg
or '{!r} should be nan'.format(b
))
85 self
.fail(msg
or 'finite result where infinity expected: '
86 'expected {!r}, got {!r}'.format(a
, b
))
88 # if both a and b are zero, check whether they have the same sign
89 # (in theory there are examples where it would be legitimate for a
90 # and b to have opposite signs; in practice these hardly ever
93 if math
.copysign(1., a
) != math
.copysign(1., b
):
94 self
.fail(msg
or 'zero has wrong sign: expected {!r}, '
95 'got {!r}'.format(a
, b
))
97 # if a-b overflows, or b is infinite, return False. Again, in
98 # theory there are examples where a is within a few ulps of the
99 # max representable float, and then b could legitimately be
100 # infinite. In practice these examples are rare.
102 absolute_error
= abs(b
-a
)
103 except OverflowError:
106 # test passes if either the absolute error or the relative
107 # error is sufficiently small. The defaults amount to an
108 # error of between 9 ulps and 19 ulps on an IEEE-754 compliant
110 if absolute_error
<= max(abs_err
, rel_err
* abs(a
)):
113 '{!r} and {!r} are not sufficiently close'.format(a
, b
))
115 def test_constants(self
):
116 e_expected
= 2.71828182845904523536
117 pi_expected
= 3.14159265358979323846
118 self
.assertAlmostEqual(cmath
.pi
, pi_expected
, places
=9,
119 msg
="cmath.pi is {}; should be {}".format(cmath
.pi
, pi_expected
))
120 self
.assertAlmostEqual(cmath
.e
, e_expected
, places
=9,
121 msg
="cmath.e is {}; should be {}".format(cmath
.e
, e_expected
))
123 def test_user_object(self
):
124 # Test automatic calling of __complex__ and __float__ by cmath
127 # some random values to use as test values; we avoid values
128 # for which any of the functions in cmath is undefined
129 # (i.e. 0., 1., -1., 1j, -1j) or would cause overflow
130 cx_arg
= 4.419414439 + 1.497100113j
131 flt_arg
= -6.131677725
133 # a variety of non-complex numbers, used to check that
134 # non-complex return values from __complex__ give an error
135 non_complexes
= ["not complex", 1, 5L, 2., None,
136 object(), NotImplemented]
138 # Now we introduce a variety of classes whose instances might
139 # end up being passed to the cmath functions
141 # usual case: new-style class implementing __complex__
142 class MyComplex(object):
143 def __init__(self
, value
):
145 def __complex__(self
):
148 # old-style class implementing __complex__
150 def __init__(self
, value
):
152 def __complex__(self
):
155 # classes for which __complex__ raises an exception
156 class SomeException(Exception):
158 class MyComplexException(object):
159 def __complex__(self
):
161 class MyComplexExceptionOS
:
162 def __complex__(self
):
165 # some classes not providing __float__ or __complex__
166 class NeitherComplexNorFloat(object):
168 class NeitherComplexNorFloatOS
:
171 def __int__(self
): return 2
172 def __long__(self
): return 2L
173 def __index__(self
): return 2
175 def __int__(self
): return 2
176 def __long__(self
): return 2L
177 def __index__(self
): return 2
179 # other possible combinations of __float__ and __complex__
181 class FloatAndComplex(object):
184 def __complex__(self
):
186 class FloatAndComplexOS
:
189 def __complex__(self
):
191 class JustFloat(object):
198 for f
in self
.test_functions
:
200 self
.assertEqual(f(MyComplex(cx_arg
)), f(cx_arg
))
201 self
.assertEqual(f(MyComplexOS(cx_arg
)), f(cx_arg
))
202 # other combinations of __float__ and __complex__
203 self
.assertEqual(f(FloatAndComplex()), f(cx_arg
))
204 self
.assertEqual(f(FloatAndComplexOS()), f(cx_arg
))
205 self
.assertEqual(f(JustFloat()), f(flt_arg
))
206 self
.assertEqual(f(JustFloatOS()), f(flt_arg
))
207 # TypeError should be raised for classes not providing
208 # either __complex__ or __float__, even if they provide
209 # __int__, __long__ or __index__. An old-style class
210 # currently raises AttributeError instead of a TypeError;
211 # this could be considered a bug.
212 self
.assertRaises(TypeError, f
, NeitherComplexNorFloat())
213 self
.assertRaises(TypeError, f
, MyInt())
214 self
.assertRaises(Exception, f
, NeitherComplexNorFloatOS())
215 self
.assertRaises(Exception, f
, MyIntOS())
216 # non-complex return value from __complex__ -> TypeError
217 for bad_complex
in non_complexes
:
218 self
.assertRaises(TypeError, f
, MyComplex(bad_complex
))
219 self
.assertRaises(TypeError, f
, MyComplexOS(bad_complex
))
220 # exceptions in __complex__ should be propagated correctly
221 self
.assertRaises(SomeException
, f
, MyComplexException())
222 self
.assertRaises(SomeException
, f
, MyComplexExceptionOS())
224 def test_input_type(self
):
225 # ints and longs should be acceptable inputs to all cmath
226 # functions, by virtue of providing a __float__ method
227 for f
in self
.test_functions
:
228 for arg
in [2, 2L, 2.]:
229 self
.assertEqual(f(arg
), f(arg
.__float
__()))
231 # but strings should give a TypeError
232 for f
in self
.test_functions
:
233 for arg
in ["a", "long_string", "0", "1j", ""]:
234 self
.assertRaises(TypeError, f
, arg
)
236 def test_cmath_matches_math(self
):
237 # check that corresponding cmath and math functions are equal
238 # for floats in the appropriate range
240 # test_values in (0, 1)
241 test_values
= [0.01, 0.1, 0.2, 0.5, 0.9, 0.99]
243 # test_values for functions defined on [-1., 1.]
244 unit_interval
= test_values
+ [-x
for x
in test_values
] + \
247 # test_values for log, log10, sqrt
248 positive
= test_values
+ [1.] + [1./x
for x
in test_values
]
249 nonnegative
= [0.] + positive
251 # test_values for functions defined on the whole real line
252 real_line
= [0.] + positive
+ [-x
for x
in positive
]
255 'acos' : unit_interval
,
256 'asin' : unit_interval
,
265 'sqrt' : nonnegative
,
269 for fn
, values
in test_functions
.items():
270 float_fn
= getattr(math
, fn
)
271 complex_fn
= getattr(cmath
, fn
)
274 self
.rAssertAlmostEqual(float_fn(v
), z
.real
)
275 self
.assertEqual(0., z
.imag
)
277 # test two-argument version of log with various bases
278 for base
in [0.5, 2., 10.]:
280 z
= cmath
.log(v
, base
)
281 self
.rAssertAlmostEqual(math
.log(v
, base
), z
.real
)
282 self
.assertEqual(0., z
.imag
)
284 def test_specific_values(self
):
285 if not float.__getformat
__("double").startswith("IEEE"):
289 """Wrapped version of rect that accepts a complex number instead of
290 two float arguments."""
291 return cmath
.rect(z
.real
, z
.imag
)
293 def polar_complex(z
):
294 """Wrapped version of polar that returns a complex number instead of
296 return complex(*polar(z
))
298 for id, fn
, ar
, ai
, er
, ei
, flags
in parse_testfile(test_file
):
299 arg
= complex(ar
, ai
)
300 expected
= complex(er
, ei
)
302 function
= rect_complex
304 function
= polar_complex
306 function
= getattr(cmath
, fn
)
307 if 'divide-by-zero' in flags
or 'invalid' in flags
:
309 actual
= function(arg
)
313 self
.fail('ValueError not raised in test '
314 '{}: {}(complex({!r}, {!r}))'.format(id, fn
, ar
, ai
))
316 if 'overflow' in flags
:
318 actual
= function(arg
)
319 except OverflowError:
322 self
.fail('OverflowError not raised in test '
323 '{}: {}(complex({!r}, {!r}))'.format(id, fn
, ar
, ai
))
325 actual
= function(arg
)
327 if 'ignore-real-sign' in flags
:
328 actual
= complex(abs(actual
.real
), actual
.imag
)
329 expected
= complex(abs(expected
.real
), expected
.imag
)
330 if 'ignore-imag-sign' in flags
:
331 actual
= complex(actual
.real
, abs(actual
.imag
))
332 expected
= complex(expected
.real
, abs(expected
.imag
))
334 # for the real part of the log function, we allow an
335 # absolute error of up to 2e-15.
336 if fn
in ('log', 'log10'):
339 real_abs_err
= 5e-323
342 '{}: {}(complex({!r}, {!r}))\n'
343 'Expected: complex({!r}, {!r})\n'
344 'Received: complex({!r}, {!r})\n'
345 'Received value insufficiently close to expected value.'
346 ).format(id, fn
, ar
, ai
,
347 expected
.real
, expected
.imag
,
348 actual
.real
, actual
.imag
)
349 self
.rAssertAlmostEqual(expected
.real
, actual
.real
,
350 abs_err
=real_abs_err
,
352 self
.rAssertAlmostEqual(expected
.imag
, actual
.imag
,
355 def assertCISEqual(self
, a
, b
):
357 if abs(a
[0] - b
[0]) > eps
or abs(a
[1] - b
[1]) > eps
:
360 def test_polar(self
):
361 self
.assertCISEqual(polar(0), (0., 0.))
362 self
.assertCISEqual(polar(1.), (1., 0.))
363 self
.assertCISEqual(polar(-1.), (1., pi
))
364 self
.assertCISEqual(polar(1j
), (1., pi
/2))
365 self
.assertCISEqual(polar(-1j
), (1., -pi
/2))
367 def test_phase(self
):
368 self
.assertAlmostEqual(phase(0), 0.)
369 self
.assertAlmostEqual(phase(1.), 0.)
370 self
.assertAlmostEqual(phase(-1.), pi
)
371 self
.assertAlmostEqual(phase(-1.+1E-300j
), pi
)
372 self
.assertAlmostEqual(phase(-1.-1E-300j
), -pi
)
373 self
.assertAlmostEqual(phase(1j
), pi
/2)
374 self
.assertAlmostEqual(phase(-1j
), -pi
/2)
377 self
.assertEqual(phase(complex(0.0, 0.0)), 0.0)
378 self
.assertEqual(phase(complex(0.0, -0.0)), -0.0)
379 self
.assertEqual(phase(complex(-0.0, 0.0)), pi
)
380 self
.assertEqual(phase(complex(-0.0, -0.0)), -pi
)
383 self
.assertAlmostEqual(phase(complex(-INF
, -0.0)), -pi
)
384 self
.assertAlmostEqual(phase(complex(-INF
, -2.3)), -pi
)
385 self
.assertAlmostEqual(phase(complex(-INF
, -INF
)), -0.75*pi
)
386 self
.assertAlmostEqual(phase(complex(-2.3, -INF
)), -pi
/2)
387 self
.assertAlmostEqual(phase(complex(-0.0, -INF
)), -pi
/2)
388 self
.assertAlmostEqual(phase(complex(0.0, -INF
)), -pi
/2)
389 self
.assertAlmostEqual(phase(complex(2.3, -INF
)), -pi
/2)
390 self
.assertAlmostEqual(phase(complex(INF
, -INF
)), -pi
/4)
391 self
.assertEqual(phase(complex(INF
, -2.3)), -0.0)
392 self
.assertEqual(phase(complex(INF
, -0.0)), -0.0)
393 self
.assertEqual(phase(complex(INF
, 0.0)), 0.0)
394 self
.assertEqual(phase(complex(INF
, 2.3)), 0.0)
395 self
.assertAlmostEqual(phase(complex(INF
, INF
)), pi
/4)
396 self
.assertAlmostEqual(phase(complex(2.3, INF
)), pi
/2)
397 self
.assertAlmostEqual(phase(complex(0.0, INF
)), pi
/2)
398 self
.assertAlmostEqual(phase(complex(-0.0, INF
)), pi
/2)
399 self
.assertAlmostEqual(phase(complex(-2.3, INF
)), pi
/2)
400 self
.assertAlmostEqual(phase(complex(-INF
, INF
)), 0.75*pi
)
401 self
.assertAlmostEqual(phase(complex(-INF
, 2.3)), pi
)
402 self
.assertAlmostEqual(phase(complex(-INF
, 0.0)), pi
)
404 # real or imaginary part NaN
405 for z
in complex_nans
:
406 self
.assertTrue(math
.isnan(phase(z
)))
410 for z
in complex_zeros
:
411 self
.assertEqual(abs(z
), 0.0)
414 for z
in complex_infinities
:
415 self
.assertEqual(abs(z
), INF
)
417 # real or imaginary part NaN
418 self
.assertEqual(abs(complex(NAN
, -INF
)), INF
)
419 self
.assertTrue(math
.isnan(abs(complex(NAN
, -2.3))))
420 self
.assertTrue(math
.isnan(abs(complex(NAN
, -0.0))))
421 self
.assertTrue(math
.isnan(abs(complex(NAN
, 0.0))))
422 self
.assertTrue(math
.isnan(abs(complex(NAN
, 2.3))))
423 self
.assertEqual(abs(complex(NAN
, INF
)), INF
)
424 self
.assertEqual(abs(complex(-INF
, NAN
)), INF
)
425 self
.assertTrue(math
.isnan(abs(complex(-2.3, NAN
))))
426 self
.assertTrue(math
.isnan(abs(complex(-0.0, NAN
))))
427 self
.assertTrue(math
.isnan(abs(complex(0.0, NAN
))))
428 self
.assertTrue(math
.isnan(abs(complex(2.3, NAN
))))
429 self
.assertEqual(abs(complex(INF
, NAN
)), INF
)
430 self
.assertTrue(math
.isnan(abs(complex(NAN
, NAN
))))
433 if float.__getformat
__("double").startswith("IEEE"):
434 self
.assertRaises(OverflowError, abs, complex(1.4e308
, 1.4e308
))
436 def assertCEqual(self
, a
, b
):
438 if abs(a
.real
- b
[0]) > eps
or abs(a
.imag
- b
[1]) > eps
:
442 self
.assertCEqual(rect(0, 0), (0, 0))
443 self
.assertCEqual(rect(1, 0), (1., 0))
444 self
.assertCEqual(rect(1, -pi
), (-1., 0))
445 self
.assertCEqual(rect(1, pi
/2), (0, 1.))
446 self
.assertCEqual(rect(1, -pi
/2), (0, -1.))
448 def test_isnan(self
):
449 self
.assertFalse(cmath
.isnan(1))
450 self
.assertFalse(cmath
.isnan(1j
))
451 self
.assertFalse(cmath
.isnan(INF
))
452 self
.assertTrue(cmath
.isnan(NAN
))
453 self
.assertTrue(cmath
.isnan(complex(NAN
, 0)))
454 self
.assertTrue(cmath
.isnan(complex(0, NAN
)))
455 self
.assertTrue(cmath
.isnan(complex(NAN
, NAN
)))
456 self
.assertTrue(cmath
.isnan(complex(NAN
, INF
)))
457 self
.assertTrue(cmath
.isnan(complex(INF
, NAN
)))
459 def test_isinf(self
):
460 self
.assertFalse(cmath
.isinf(1))
461 self
.assertFalse(cmath
.isinf(1j
))
462 self
.assertFalse(cmath
.isinf(NAN
))
463 self
.assertTrue(cmath
.isinf(INF
))
464 self
.assertTrue(cmath
.isinf(complex(INF
, 0)))
465 self
.assertTrue(cmath
.isinf(complex(0, INF
)))
466 self
.assertTrue(cmath
.isinf(complex(INF
, INF
)))
467 self
.assertTrue(cmath
.isinf(complex(NAN
, INF
)))
468 self
.assertTrue(cmath
.isinf(complex(INF
, NAN
)))
472 run_unittest(CMathTests
)
474 if __name__
== "__main__":