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 def almostEqualF(a
, b
, rel_err
=2e-15, abs_err
= 5e-323):
50 """Determine whether floating-point values a and b are equal to within
51 a (small) rounding error. The default values for rel_err and
52 abs_err are chosen to be suitable for platforms where a float is
53 represented by an IEEE 754 double. They allow an error of between
56 # special values testing
62 # if both a and b are zero, check whether they have the same sign
63 # (in theory there are examples where it would be legitimate for a
64 # and b to have opposite signs; in practice these hardly ever
67 return math
.copysign(1., a
) == math
.copysign(1., b
)
69 # if a-b overflows, or b is infinite, return False. Again, in
70 # theory there are examples where a is within a few ulps of the
71 # max representable float, and then b could legitimately be
72 # infinite. In practice these examples are rare.
74 absolute_error
= abs(b
-a
)
78 return absolute_error
<= max(abs_err
, rel_err
* abs(a
))
80 class CMathTests(unittest
.TestCase
):
81 # list of all functions in cmath
82 test_functions
= [getattr(cmath
, fname
) for fname
in [
83 'acos', 'acosh', 'asin', 'asinh', 'atan', 'atanh',
84 'cos', 'cosh', 'exp', 'log', 'log10', 'sin', 'sinh',
85 'sqrt', 'tan', 'tanh']]
86 # test first and second arguments independently for 2-argument log
87 test_functions
.append(lambda x
: cmath
.log(x
, 1729. + 0j
))
88 test_functions
.append(lambda x
: cmath
.log(14.-27j
, x
))
91 self
.test_values
= open(test_file
)
94 self
.test_values
.close()
96 def rAssertAlmostEqual(self
, a
, b
, rel_err
= 2e-15, abs_err
= 5e-323):
97 """Check that two floating-point numbers are almost equal."""
99 # special values testing
103 self
.fail("%s should be nan" % repr(b
))
108 self
.fail("finite result where infinity excpected: "
109 "expected %s, got %s" % (repr(a
), repr(b
)))
112 if math
.atan2(a
, -1.) != math
.atan2(b
, -1.):
113 self
.fail("zero has wrong sign: expected %s, got %s" %
116 # test passes if either the absolute error or the relative
117 # error is sufficiently small. The defaults amount to an
118 # error of between 9 ulps and 19 ulps on an IEEE-754 compliant
122 absolute_error
= abs(b
-a
)
123 except OverflowError:
126 if absolute_error
<= max(abs_err
, rel_err
* abs(a
)):
128 self
.fail("%s and %s are not sufficiently close" % (repr(a
), repr(b
)))
130 def test_constants(self
):
131 e_expected
= 2.71828182845904523536
132 pi_expected
= 3.14159265358979323846
133 self
.rAssertAlmostEqual(cmath
.pi
, pi_expected
, 9,
134 "cmath.pi is %s; should be %s" % (cmath
.pi
, pi_expected
))
135 self
.rAssertAlmostEqual(cmath
.e
, e_expected
, 9,
136 "cmath.e is %s; should be %s" % (cmath
.e
, e_expected
))
138 def test_user_object(self
):
139 # Test automatic calling of __complex__ and __float__ by cmath
142 # some random values to use as test values; we avoid values
143 # for which any of the functions in cmath is undefined
144 # (i.e. 0., 1., -1., 1j, -1j) or would cause overflow
145 cx_arg
= 4.419414439 + 1.497100113j
146 flt_arg
= -6.131677725
148 # a variety of non-complex numbers, used to check that
149 # non-complex return values from __complex__ give an error
150 non_complexes
= ["not complex", 1, 5L, 2., None,
151 object(), NotImplemented]
153 # Now we introduce a variety of classes whose instances might
154 # end up being passed to the cmath functions
156 # usual case: new-style class implementing __complex__
157 class MyComplex(object):
158 def __init__(self
, value
):
160 def __complex__(self
):
163 # old-style class implementing __complex__
165 def __init__(self
, value
):
167 def __complex__(self
):
170 # classes for which __complex__ raises an exception
171 class SomeException(Exception):
173 class MyComplexException(object):
174 def __complex__(self
):
176 class MyComplexExceptionOS
:
177 def __complex__(self
):
180 # some classes not providing __float__ or __complex__
181 class NeitherComplexNorFloat(object):
183 class NeitherComplexNorFloatOS
:
186 def __int__(self
): return 2
187 def __long__(self
): return 2L
188 def __index__(self
): return 2
190 def __int__(self
): return 2
191 def __long__(self
): return 2L
192 def __index__(self
): return 2
194 # other possible combinations of __float__ and __complex__
196 class FloatAndComplex(object):
199 def __complex__(self
):
201 class FloatAndComplexOS
:
204 def __complex__(self
):
206 class JustFloat(object):
213 for f
in self
.test_functions
:
215 self
.assertEqual(f(MyComplex(cx_arg
)), f(cx_arg
))
216 self
.assertEqual(f(MyComplexOS(cx_arg
)), f(cx_arg
))
217 # other combinations of __float__ and __complex__
218 self
.assertEqual(f(FloatAndComplex()), f(cx_arg
))
219 self
.assertEqual(f(FloatAndComplexOS()), f(cx_arg
))
220 self
.assertEqual(f(JustFloat()), f(flt_arg
))
221 self
.assertEqual(f(JustFloatOS()), f(flt_arg
))
222 # TypeError should be raised for classes not providing
223 # either __complex__ or __float__, even if they provide
224 # __int__, __long__ or __index__. An old-style class
225 # currently raises AttributeError instead of a TypeError;
226 # this could be considered a bug.
227 self
.assertRaises(TypeError, f
, NeitherComplexNorFloat())
228 self
.assertRaises(TypeError, f
, MyInt())
229 self
.assertRaises(Exception, f
, NeitherComplexNorFloatOS())
230 self
.assertRaises(Exception, f
, MyIntOS())
231 # non-complex return value from __complex__ -> TypeError
232 for bad_complex
in non_complexes
:
233 self
.assertRaises(TypeError, f
, MyComplex(bad_complex
))
234 self
.assertRaises(TypeError, f
, MyComplexOS(bad_complex
))
235 # exceptions in __complex__ should be propagated correctly
236 self
.assertRaises(SomeException
, f
, MyComplexException())
237 self
.assertRaises(SomeException
, f
, MyComplexExceptionOS())
239 def test_input_type(self
):
240 # ints and longs should be acceptable inputs to all cmath
241 # functions, by virtue of providing a __float__ method
242 for f
in self
.test_functions
:
243 for arg
in [2, 2L, 2.]:
244 self
.assertEqual(f(arg
), f(arg
.__float
__()))
246 # but strings should give a TypeError
247 for f
in self
.test_functions
:
248 for arg
in ["a", "long_string", "0", "1j", ""]:
249 self
.assertRaises(TypeError, f
, arg
)
251 def test_cmath_matches_math(self
):
252 # check that corresponding cmath and math functions are equal
253 # for floats in the appropriate range
255 # test_values in (0, 1)
256 test_values
= [0.01, 0.1, 0.2, 0.5, 0.9, 0.99]
258 # test_values for functions defined on [-1., 1.]
259 unit_interval
= test_values
+ [-x
for x
in test_values
] + \
262 # test_values for log, log10, sqrt
263 positive
= test_values
+ [1.] + [1./x
for x
in test_values
]
264 nonnegative
= [0.] + positive
266 # test_values for functions defined on the whole real line
267 real_line
= [0.] + positive
+ [-x
for x
in positive
]
270 'acos' : unit_interval
,
271 'asin' : unit_interval
,
280 'sqrt' : nonnegative
,
284 for fn
, values
in test_functions
.items():
285 float_fn
= getattr(math
, fn
)
286 complex_fn
= getattr(cmath
, fn
)
289 self
.rAssertAlmostEqual(float_fn(v
), z
.real
)
290 self
.assertEqual(0., z
.imag
)
292 # test two-argument version of log with various bases
293 for base
in [0.5, 2., 10.]:
295 z
= cmath
.log(v
, base
)
296 self
.rAssertAlmostEqual(math
.log(v
, base
), z
.real
)
297 self
.assertEqual(0., z
.imag
)
299 def test_specific_values(self
):
300 if not float.__getformat
__("double").startswith("IEEE"):
304 """Wrapped version of rect that accepts a complex number instead of
305 two float arguments."""
306 return cmath
.rect(z
.real
, z
.imag
)
308 def polar_complex(z
):
309 """Wrapped version of polar that returns a complex number instead of
311 return complex(*polar(z
))
313 for id, fn
, ar
, ai
, er
, ei
, flags
in parse_testfile(test_file
):
314 arg
= complex(ar
, ai
)
315 expected
= complex(er
, ei
)
317 function
= rect_complex
319 function
= polar_complex
321 function
= getattr(cmath
, fn
)
322 if 'divide-by-zero' in flags
or 'invalid' in flags
:
324 actual
= function(arg
)
328 test_str
= "%s: %s(complex(%r, %r))" % (id, fn
, ar
, ai
)
329 self
.fail('ValueError not raised in test %s' % test_str
)
331 if 'overflow' in flags
:
333 actual
= function(arg
)
334 except OverflowError:
337 test_str
= "%s: %s(complex(%r, %r))" % (id, fn
, ar
, ai
)
338 self
.fail('OverflowError not raised in test %s' % test_str
)
340 actual
= function(arg
)
342 if 'ignore-real-sign' in flags
:
343 actual
= complex(abs(actual
.real
), actual
.imag
)
344 expected
= complex(abs(expected
.real
), expected
.imag
)
345 if 'ignore-imag-sign' in flags
:
346 actual
= complex(actual
.real
, abs(actual
.imag
))
347 expected
= complex(expected
.real
, abs(expected
.imag
))
349 # for the real part of the log function, we allow an
350 # absolute error of up to 2e-15.
351 if fn
in ('log', 'log10'):
354 real_abs_err
= 5e-323
356 if not (almostEqualF(expected
.real
, actual
.real
,
357 abs_err
= real_abs_err
) and
358 almostEqualF(expected
.imag
, actual
.imag
)):
360 "%s: %s(complex(%r, %r))\n" % (id, fn
, ar
, ai
) +
361 "Expected: complex(%r, %r)\n" %
362 (expected
.real
, expected
.imag
) +
363 "Received: complex(%r, %r)\n" %
364 (actual
.real
, actual
.imag
) +
365 "Received value insufficiently close to expected value.")
366 self
.fail(error_message
)
368 def assertCISEqual(self
, a
, b
):
370 if abs(a
[0] - b
[0]) > eps
or abs(a
[1] - b
[1]) > eps
:
373 def test_polar(self
):
374 self
.assertCISEqual(polar(0), (0., 0.))
375 self
.assertCISEqual(polar(1.), (1., 0.))
376 self
.assertCISEqual(polar(-1.), (1., pi
))
377 self
.assertCISEqual(polar(1j
), (1., pi
/2))
378 self
.assertCISEqual(polar(-1j
), (1., -pi
/2))
380 def test_phase(self
):
381 self
.assertAlmostEqual(phase(0), 0.)
382 self
.assertAlmostEqual(phase(1.), 0.)
383 self
.assertAlmostEqual(phase(-1.), pi
)
384 self
.assertAlmostEqual(phase(-1.+1E-300j
), pi
)
385 self
.assertAlmostEqual(phase(-1.-1E-300j
), -pi
)
386 self
.assertAlmostEqual(phase(1j
), pi
/2)
387 self
.assertAlmostEqual(phase(-1j
), -pi
/2)
390 self
.assertEqual(phase(complex(0.0, 0.0)), 0.0)
391 self
.assertEqual(phase(complex(0.0, -0.0)), -0.0)
392 self
.assertEqual(phase(complex(-0.0, 0.0)), pi
)
393 self
.assertEqual(phase(complex(-0.0, -0.0)), -pi
)
396 self
.assertAlmostEqual(phase(complex(-INF
, -0.0)), -pi
)
397 self
.assertAlmostEqual(phase(complex(-INF
, -2.3)), -pi
)
398 self
.assertAlmostEqual(phase(complex(-INF
, -INF
)), -0.75*pi
)
399 self
.assertAlmostEqual(phase(complex(-2.3, -INF
)), -pi
/2)
400 self
.assertAlmostEqual(phase(complex(-0.0, -INF
)), -pi
/2)
401 self
.assertAlmostEqual(phase(complex(0.0, -INF
)), -pi
/2)
402 self
.assertAlmostEqual(phase(complex(2.3, -INF
)), -pi
/2)
403 self
.assertAlmostEqual(phase(complex(INF
, -INF
)), -pi
/4)
404 self
.assertEqual(phase(complex(INF
, -2.3)), -0.0)
405 self
.assertEqual(phase(complex(INF
, -0.0)), -0.0)
406 self
.assertEqual(phase(complex(INF
, 0.0)), 0.0)
407 self
.assertEqual(phase(complex(INF
, 2.3)), 0.0)
408 self
.assertAlmostEqual(phase(complex(INF
, INF
)), pi
/4)
409 self
.assertAlmostEqual(phase(complex(2.3, INF
)), pi
/2)
410 self
.assertAlmostEqual(phase(complex(0.0, INF
)), pi
/2)
411 self
.assertAlmostEqual(phase(complex(-0.0, INF
)), pi
/2)
412 self
.assertAlmostEqual(phase(complex(-2.3, INF
)), pi
/2)
413 self
.assertAlmostEqual(phase(complex(-INF
, INF
)), 0.75*pi
)
414 self
.assertAlmostEqual(phase(complex(-INF
, 2.3)), pi
)
415 self
.assertAlmostEqual(phase(complex(-INF
, 0.0)), pi
)
417 # real or imaginary part NaN
418 for z
in complex_nans
:
419 self
.assertTrue(math
.isnan(phase(z
)))
423 for z
in complex_zeros
:
424 self
.assertEqual(abs(z
), 0.0)
427 for z
in complex_infinities
:
428 self
.assertEqual(abs(z
), INF
)
430 # real or imaginary part NaN
431 self
.assertEqual(abs(complex(NAN
, -INF
)), INF
)
432 self
.assertTrue(math
.isnan(abs(complex(NAN
, -2.3))))
433 self
.assertTrue(math
.isnan(abs(complex(NAN
, -0.0))))
434 self
.assertTrue(math
.isnan(abs(complex(NAN
, 0.0))))
435 self
.assertTrue(math
.isnan(abs(complex(NAN
, 2.3))))
436 self
.assertEqual(abs(complex(NAN
, INF
)), INF
)
437 self
.assertEqual(abs(complex(-INF
, NAN
)), INF
)
438 self
.assertTrue(math
.isnan(abs(complex(-2.3, NAN
))))
439 self
.assertTrue(math
.isnan(abs(complex(-0.0, NAN
))))
440 self
.assertTrue(math
.isnan(abs(complex(0.0, NAN
))))
441 self
.assertTrue(math
.isnan(abs(complex(2.3, NAN
))))
442 self
.assertEqual(abs(complex(INF
, NAN
)), INF
)
443 self
.assertTrue(math
.isnan(abs(complex(NAN
, NAN
))))
446 if float.__getformat
__("double").startswith("IEEE"):
447 self
.assertRaises(OverflowError, abs, complex(1.4e308
, 1.4e308
))
449 def assertCEqual(self
, a
, b
):
451 if abs(a
.real
- b
[0]) > eps
or abs(a
.imag
- b
[1]) > eps
:
455 self
.assertCEqual(rect(0, 0), (0, 0))
456 self
.assertCEqual(rect(1, 0), (1., 0))
457 self
.assertCEqual(rect(1, -pi
), (-1., 0))
458 self
.assertCEqual(rect(1, pi
/2), (0, 1.))
459 self
.assertCEqual(rect(1, -pi
/2), (0, -1.))
461 def test_isnan(self
):
462 self
.assertFalse(cmath
.isnan(1))
463 self
.assertFalse(cmath
.isnan(1j
))
464 self
.assertFalse(cmath
.isnan(INF
))
465 self
.assertTrue(cmath
.isnan(NAN
))
466 self
.assertTrue(cmath
.isnan(complex(NAN
, 0)))
467 self
.assertTrue(cmath
.isnan(complex(0, NAN
)))
468 self
.assertTrue(cmath
.isnan(complex(NAN
, NAN
)))
469 self
.assertTrue(cmath
.isnan(complex(NAN
, INF
)))
470 self
.assertTrue(cmath
.isnan(complex(INF
, NAN
)))
472 def test_isinf(self
):
473 self
.assertFalse(cmath
.isinf(1))
474 self
.assertFalse(cmath
.isinf(1j
))
475 self
.assertFalse(cmath
.isinf(NAN
))
476 self
.assertTrue(cmath
.isinf(INF
))
477 self
.assertTrue(cmath
.isinf(complex(INF
, 0)))
478 self
.assertTrue(cmath
.isinf(complex(0, INF
)))
479 self
.assertTrue(cmath
.isinf(complex(INF
, INF
)))
480 self
.assertTrue(cmath
.isinf(complex(NAN
, INF
)))
481 self
.assertTrue(cmath
.isinf(complex(INF
, NAN
)))
485 run_unittest(CMathTests
)
487 if __name__
== "__main__":