1 from test
.test_support
import run_unittest
2 from test
.test_math
import parse_testfile
, test_file
5 from cmath
import phase
, polar
, rect
, pi
10 complex_zeros
= [complex(x
, y
) for x
in [0.0, -0.0] for y
in [0.0, -0.0]]
11 complex_infinities
= [complex(x
, y
) for x
, y
in [
12 (INF
, 0.0), # 1st quadrant
17 (-0.0, INF
), # 2nd quadrant
22 (-INF
, -0.0), # 3rd quadrant
27 (0.0, -INF
), # 4th quadrant
33 complex_nans
= [complex(x
, y
) for x
, y
in [
48 class CMathTests(unittest
.TestCase
):
49 # list of all functions in cmath
50 test_functions
= [getattr(cmath
, fname
) for fname
in [
51 'acos', 'acosh', 'asin', 'asinh', 'atan', 'atanh',
52 'cos', 'cosh', 'exp', 'log', 'log10', 'sin', 'sinh',
53 'sqrt', 'tan', 'tanh']]
54 # test first and second arguments independently for 2-argument log
55 test_functions
.append(lambda x
: cmath
.log(x
, 1729. + 0j
))
56 test_functions
.append(lambda x
: cmath
.log(14.-27j
, x
))
59 self
.test_values
= open(test_file
)
62 self
.test_values
.close()
64 def rAssertAlmostEqual(self
, a
, b
, rel_err
= 2e-15, abs_err
= 5e-323,
66 """Fail if the two floating-point numbers are not almost equal.
68 Determine whether floating-point values a and b are equal to within
69 a (small) rounding error. The default values for rel_err and
70 abs_err are chosen to be suitable for platforms where a float is
71 represented by an IEEE 754 double. They allow an error of between
75 # special values testing
79 self
.fail(msg
or '{!r} should be nan'.format(b
))
84 self
.fail(msg
or 'finite result where infinity expected: '
85 'expected {!r}, got {!r}'.format(a
, b
))
87 # if both a and b are zero, check whether they have the same sign
88 # (in theory there are examples where it would be legitimate for a
89 # and b to have opposite signs; in practice these hardly ever
92 if math
.copysign(1., a
) != math
.copysign(1., b
):
93 self
.fail(msg
or 'zero has wrong sign: expected {!r}, '
94 'got {!r}'.format(a
, b
))
96 # if a-b overflows, or b is infinite, return False. Again, in
97 # theory there are examples where a is within a few ulps of the
98 # max representable float, and then b could legitimately be
99 # infinite. In practice these examples are rare.
101 absolute_error
= abs(b
-a
)
102 except OverflowError:
105 # test passes if either the absolute error or the relative
106 # error is sufficiently small. The defaults amount to an
107 # error of between 9 ulps and 19 ulps on an IEEE-754 compliant
109 if absolute_error
<= max(abs_err
, rel_err
* abs(a
)):
112 '{!r} and {!r} are not sufficiently close'.format(a
, b
))
114 def test_constants(self
):
115 e_expected
= 2.71828182845904523536
116 pi_expected
= 3.14159265358979323846
117 self
.assertAlmostEqual(cmath
.pi
, pi_expected
, places
=9,
118 msg
="cmath.pi is {}; should be {}".format(cmath
.pi
, pi_expected
))
119 self
.assertAlmostEqual(cmath
.e
, e_expected
, places
=9,
120 msg
="cmath.e is {}; should be {}".format(cmath
.e
, e_expected
))
122 def test_user_object(self
):
123 # Test automatic calling of __complex__ and __float__ by cmath
126 # some random values to use as test values; we avoid values
127 # for which any of the functions in cmath is undefined
128 # (i.e. 0., 1., -1., 1j, -1j) or would cause overflow
129 cx_arg
= 4.419414439 + 1.497100113j
130 flt_arg
= -6.131677725
132 # a variety of non-complex numbers, used to check that
133 # non-complex return values from __complex__ give an error
134 non_complexes
= ["not complex", 1, 5L, 2., None,
135 object(), NotImplemented]
137 # Now we introduce a variety of classes whose instances might
138 # end up being passed to the cmath functions
140 # usual case: new-style class implementing __complex__
141 class MyComplex(object):
142 def __init__(self
, value
):
144 def __complex__(self
):
147 # old-style class implementing __complex__
149 def __init__(self
, value
):
151 def __complex__(self
):
154 # classes for which __complex__ raises an exception
155 class SomeException(Exception):
157 class MyComplexException(object):
158 def __complex__(self
):
160 class MyComplexExceptionOS
:
161 def __complex__(self
):
164 # some classes not providing __float__ or __complex__
165 class NeitherComplexNorFloat(object):
167 class NeitherComplexNorFloatOS
:
170 def __int__(self
): return 2
171 def __long__(self
): return 2L
172 def __index__(self
): return 2
174 def __int__(self
): return 2
175 def __long__(self
): return 2L
176 def __index__(self
): return 2
178 # other possible combinations of __float__ and __complex__
180 class FloatAndComplex(object):
183 def __complex__(self
):
185 class FloatAndComplexOS
:
188 def __complex__(self
):
190 class JustFloat(object):
197 for f
in self
.test_functions
:
199 self
.assertEqual(f(MyComplex(cx_arg
)), f(cx_arg
))
200 self
.assertEqual(f(MyComplexOS(cx_arg
)), f(cx_arg
))
201 # other combinations of __float__ and __complex__
202 self
.assertEqual(f(FloatAndComplex()), f(cx_arg
))
203 self
.assertEqual(f(FloatAndComplexOS()), f(cx_arg
))
204 self
.assertEqual(f(JustFloat()), f(flt_arg
))
205 self
.assertEqual(f(JustFloatOS()), f(flt_arg
))
206 # TypeError should be raised for classes not providing
207 # either __complex__ or __float__, even if they provide
208 # __int__, __long__ or __index__. An old-style class
209 # currently raises AttributeError instead of a TypeError;
210 # this could be considered a bug.
211 self
.assertRaises(TypeError, f
, NeitherComplexNorFloat())
212 self
.assertRaises(TypeError, f
, MyInt())
213 self
.assertRaises(Exception, f
, NeitherComplexNorFloatOS())
214 self
.assertRaises(Exception, f
, MyIntOS())
215 # non-complex return value from __complex__ -> TypeError
216 for bad_complex
in non_complexes
:
217 self
.assertRaises(TypeError, f
, MyComplex(bad_complex
))
218 self
.assertRaises(TypeError, f
, MyComplexOS(bad_complex
))
219 # exceptions in __complex__ should be propagated correctly
220 self
.assertRaises(SomeException
, f
, MyComplexException())
221 self
.assertRaises(SomeException
, f
, MyComplexExceptionOS())
223 def test_input_type(self
):
224 # ints and longs should be acceptable inputs to all cmath
225 # functions, by virtue of providing a __float__ method
226 for f
in self
.test_functions
:
227 for arg
in [2, 2L, 2.]:
228 self
.assertEqual(f(arg
), f(arg
.__float
__()))
230 # but strings should give a TypeError
231 for f
in self
.test_functions
:
232 for arg
in ["a", "long_string", "0", "1j", ""]:
233 self
.assertRaises(TypeError, f
, arg
)
235 def test_cmath_matches_math(self
):
236 # check that corresponding cmath and math functions are equal
237 # for floats in the appropriate range
239 # test_values in (0, 1)
240 test_values
= [0.01, 0.1, 0.2, 0.5, 0.9, 0.99]
242 # test_values for functions defined on [-1., 1.]
243 unit_interval
= test_values
+ [-x
for x
in test_values
] + \
246 # test_values for log, log10, sqrt
247 positive
= test_values
+ [1.] + [1./x
for x
in test_values
]
248 nonnegative
= [0.] + positive
250 # test_values for functions defined on the whole real line
251 real_line
= [0.] + positive
+ [-x
for x
in positive
]
254 'acos' : unit_interval
,
255 'asin' : unit_interval
,
264 'sqrt' : nonnegative
,
268 for fn
, values
in test_functions
.items():
269 float_fn
= getattr(math
, fn
)
270 complex_fn
= getattr(cmath
, fn
)
273 self
.rAssertAlmostEqual(float_fn(v
), z
.real
)
274 self
.assertEqual(0., z
.imag
)
276 # test two-argument version of log with various bases
277 for base
in [0.5, 2., 10.]:
279 z
= cmath
.log(v
, base
)
280 self
.rAssertAlmostEqual(math
.log(v
, base
), z
.real
)
281 self
.assertEqual(0., z
.imag
)
283 def test_specific_values(self
):
284 if not float.__getformat
__("double").startswith("IEEE"):
288 """Wrapped version of rect that accepts a complex number instead of
289 two float arguments."""
290 return cmath
.rect(z
.real
, z
.imag
)
292 def polar_complex(z
):
293 """Wrapped version of polar that returns a complex number instead of
295 return complex(*polar(z
))
297 for id, fn
, ar
, ai
, er
, ei
, flags
in parse_testfile(test_file
):
298 arg
= complex(ar
, ai
)
299 expected
= complex(er
, ei
)
301 function
= rect_complex
303 function
= polar_complex
305 function
= getattr(cmath
, fn
)
306 if 'divide-by-zero' in flags
or 'invalid' in flags
:
308 actual
= function(arg
)
312 self
.fail('ValueError not raised in test '
313 '{}: {}(complex({!r}, {!r}))'.format(id, fn
, ar
, ai
))
315 if 'overflow' in flags
:
317 actual
= function(arg
)
318 except OverflowError:
321 self
.fail('OverflowError not raised in test '
322 '{}: {}(complex({!r}, {!r}))'.format(id, fn
, ar
, ai
))
324 actual
= function(arg
)
326 if 'ignore-real-sign' in flags
:
327 actual
= complex(abs(actual
.real
), actual
.imag
)
328 expected
= complex(abs(expected
.real
), expected
.imag
)
329 if 'ignore-imag-sign' in flags
:
330 actual
= complex(actual
.real
, abs(actual
.imag
))
331 expected
= complex(expected
.real
, abs(expected
.imag
))
333 # for the real part of the log function, we allow an
334 # absolute error of up to 2e-15.
335 if fn
in ('log', 'log10'):
338 real_abs_err
= 5e-323
341 '{}: {}(complex({!r}, {!r}))\n'
342 'Expected: complex({!r}, {!r})\n'
343 'Received: complex({!r}, {!r})\n'
344 'Received value insufficiently close to expected value.'
345 ).format(id, fn
, ar
, ai
,
346 expected
.real
, expected
.imag
,
347 actual
.real
, actual
.imag
)
348 self
.rAssertAlmostEqual(expected
.real
, actual
.real
,
349 abs_err
=real_abs_err
,
351 self
.rAssertAlmostEqual(expected
.imag
, actual
.imag
,
354 def assertCISEqual(self
, a
, b
):
356 if abs(a
[0] - b
[0]) > eps
or abs(a
[1] - b
[1]) > eps
:
359 def test_polar(self
):
360 self
.assertCISEqual(polar(0), (0., 0.))
361 self
.assertCISEqual(polar(1.), (1., 0.))
362 self
.assertCISEqual(polar(-1.), (1., pi
))
363 self
.assertCISEqual(polar(1j
), (1., pi
/2))
364 self
.assertCISEqual(polar(-1j
), (1., -pi
/2))
366 def test_phase(self
):
367 self
.assertAlmostEqual(phase(0), 0.)
368 self
.assertAlmostEqual(phase(1.), 0.)
369 self
.assertAlmostEqual(phase(-1.), pi
)
370 self
.assertAlmostEqual(phase(-1.+1E-300j
), pi
)
371 self
.assertAlmostEqual(phase(-1.-1E-300j
), -pi
)
372 self
.assertAlmostEqual(phase(1j
), pi
/2)
373 self
.assertAlmostEqual(phase(-1j
), -pi
/2)
376 self
.assertEqual(phase(complex(0.0, 0.0)), 0.0)
377 self
.assertEqual(phase(complex(0.0, -0.0)), -0.0)
378 self
.assertEqual(phase(complex(-0.0, 0.0)), pi
)
379 self
.assertEqual(phase(complex(-0.0, -0.0)), -pi
)
382 self
.assertAlmostEqual(phase(complex(-INF
, -0.0)), -pi
)
383 self
.assertAlmostEqual(phase(complex(-INF
, -2.3)), -pi
)
384 self
.assertAlmostEqual(phase(complex(-INF
, -INF
)), -0.75*pi
)
385 self
.assertAlmostEqual(phase(complex(-2.3, -INF
)), -pi
/2)
386 self
.assertAlmostEqual(phase(complex(-0.0, -INF
)), -pi
/2)
387 self
.assertAlmostEqual(phase(complex(0.0, -INF
)), -pi
/2)
388 self
.assertAlmostEqual(phase(complex(2.3, -INF
)), -pi
/2)
389 self
.assertAlmostEqual(phase(complex(INF
, -INF
)), -pi
/4)
390 self
.assertEqual(phase(complex(INF
, -2.3)), -0.0)
391 self
.assertEqual(phase(complex(INF
, -0.0)), -0.0)
392 self
.assertEqual(phase(complex(INF
, 0.0)), 0.0)
393 self
.assertEqual(phase(complex(INF
, 2.3)), 0.0)
394 self
.assertAlmostEqual(phase(complex(INF
, INF
)), pi
/4)
395 self
.assertAlmostEqual(phase(complex(2.3, INF
)), pi
/2)
396 self
.assertAlmostEqual(phase(complex(0.0, INF
)), pi
/2)
397 self
.assertAlmostEqual(phase(complex(-0.0, INF
)), pi
/2)
398 self
.assertAlmostEqual(phase(complex(-2.3, INF
)), pi
/2)
399 self
.assertAlmostEqual(phase(complex(-INF
, INF
)), 0.75*pi
)
400 self
.assertAlmostEqual(phase(complex(-INF
, 2.3)), pi
)
401 self
.assertAlmostEqual(phase(complex(-INF
, 0.0)), pi
)
403 # real or imaginary part NaN
404 for z
in complex_nans
:
405 self
.assertTrue(math
.isnan(phase(z
)))
409 for z
in complex_zeros
:
410 self
.assertEqual(abs(z
), 0.0)
413 for z
in complex_infinities
:
414 self
.assertEqual(abs(z
), INF
)
416 # real or imaginary part NaN
417 self
.assertEqual(abs(complex(NAN
, -INF
)), INF
)
418 self
.assertTrue(math
.isnan(abs(complex(NAN
, -2.3))))
419 self
.assertTrue(math
.isnan(abs(complex(NAN
, -0.0))))
420 self
.assertTrue(math
.isnan(abs(complex(NAN
, 0.0))))
421 self
.assertTrue(math
.isnan(abs(complex(NAN
, 2.3))))
422 self
.assertEqual(abs(complex(NAN
, INF
)), INF
)
423 self
.assertEqual(abs(complex(-INF
, NAN
)), INF
)
424 self
.assertTrue(math
.isnan(abs(complex(-2.3, NAN
))))
425 self
.assertTrue(math
.isnan(abs(complex(-0.0, NAN
))))
426 self
.assertTrue(math
.isnan(abs(complex(0.0, NAN
))))
427 self
.assertTrue(math
.isnan(abs(complex(2.3, NAN
))))
428 self
.assertEqual(abs(complex(INF
, NAN
)), INF
)
429 self
.assertTrue(math
.isnan(abs(complex(NAN
, NAN
))))
432 if float.__getformat
__("double").startswith("IEEE"):
433 self
.assertRaises(OverflowError, abs, complex(1.4e308
, 1.4e308
))
435 def assertCEqual(self
, a
, b
):
437 if abs(a
.real
- b
[0]) > eps
or abs(a
.imag
- b
[1]) > eps
:
441 self
.assertCEqual(rect(0, 0), (0, 0))
442 self
.assertCEqual(rect(1, 0), (1., 0))
443 self
.assertCEqual(rect(1, -pi
), (-1., 0))
444 self
.assertCEqual(rect(1, pi
/2), (0, 1.))
445 self
.assertCEqual(rect(1, -pi
/2), (0, -1.))
447 def test_isnan(self
):
448 self
.assertFalse(cmath
.isnan(1))
449 self
.assertFalse(cmath
.isnan(1j
))
450 self
.assertFalse(cmath
.isnan(INF
))
451 self
.assertTrue(cmath
.isnan(NAN
))
452 self
.assertTrue(cmath
.isnan(complex(NAN
, 0)))
453 self
.assertTrue(cmath
.isnan(complex(0, NAN
)))
454 self
.assertTrue(cmath
.isnan(complex(NAN
, NAN
)))
455 self
.assertTrue(cmath
.isnan(complex(NAN
, INF
)))
456 self
.assertTrue(cmath
.isnan(complex(INF
, NAN
)))
458 def test_isinf(self
):
459 self
.assertFalse(cmath
.isinf(1))
460 self
.assertFalse(cmath
.isinf(1j
))
461 self
.assertFalse(cmath
.isinf(NAN
))
462 self
.assertTrue(cmath
.isinf(INF
))
463 self
.assertTrue(cmath
.isinf(complex(INF
, 0)))
464 self
.assertTrue(cmath
.isinf(complex(0, INF
)))
465 self
.assertTrue(cmath
.isinf(complex(INF
, INF
)))
466 self
.assertTrue(cmath
.isinf(complex(NAN
, INF
)))
467 self
.assertTrue(cmath
.isinf(complex(INF
, NAN
)))
471 run_unittest(CMathTests
)
473 if __name__
== "__main__":