Issue #7554: Various fixups in test_cmath.py: remove code duplication,

use new-style formatting.  Thanks Florent Xicluna for the patch.
This commit is contained in:
Mark Dickinson 2009-12-20 20:34:44 +00:00
parent ed284991e1
commit 603ae9e371
1 changed files with 49 additions and 62 deletions

View File

@ -46,37 +46,6 @@ complex_nans = [complex(x, y) for x, y in [
(INF, NAN)
]]
def almostEqualF(a, b, rel_err=2e-15, abs_err = 5e-323):
"""Determine whether floating-point values a and b are equal to within
a (small) rounding error. The default values for rel_err and
abs_err are chosen to be suitable for platforms where a float is
represented by an IEEE 754 double. They allow an error of between
9 and 19 ulps."""
# special values testing
if math.isnan(a):
return math.isnan(b)
if math.isinf(a):
return a == b
# if both a and b are zero, check whether they have the same sign
# (in theory there are examples where it would be legitimate for a
# and b to have opposite signs; in practice these hardly ever
# occur).
if not a and not b:
return math.copysign(1., a) == math.copysign(1., b)
# if a-b overflows, or b is infinite, return False. Again, in
# theory there are examples where a is within a few ulps of the
# max representable float, and then b could legitimately be
# infinite. In practice these examples are rare.
try:
absolute_error = abs(b-a)
except OverflowError:
return False
else:
return absolute_error <= max(abs_err, rel_err * abs(a))
class CMathTests(unittest.TestCase):
# list of all functions in cmath
test_functions = [getattr(cmath, fname) for fname in [
@ -93,47 +62,63 @@ class CMathTests(unittest.TestCase):
def tearDown(self):
self.test_values.close()
def rAssertAlmostEqual(self, a, b, rel_err = 2e-15, abs_err = 5e-323):
"""Check that two floating-point numbers are almost equal."""
def rAssertAlmostEqual(self, a, b, rel_err = 2e-15, abs_err = 5e-323,
msg=None):
"""Fail if the two floating-point numbers are not almost equal.
Determine whether floating-point values a and b are equal to within
a (small) rounding error. The default values for rel_err and
abs_err are chosen to be suitable for platforms where a float is
represented by an IEEE 754 double. They allow an error of between
9 and 19 ulps.
"""
# special values testing
if math.isnan(a):
if math.isnan(b):
return
self.fail("%s should be nan" % repr(b))
self.fail(msg or '{!r} should be nan'.format(b))
if math.isinf(a):
if a == b:
return
self.fail("finite result where infinity excpected: "
"expected %s, got %s" % (repr(a), repr(b)))
self.fail(msg or 'finite result where infinity expected: '
'expected {!r}, got {!r}'.format(a, b))
# if both a and b are zero, check whether they have the same sign
# (in theory there are examples where it would be legitimate for a
# and b to have opposite signs; in practice these hardly ever
# occur).
if not a and not b:
if math.atan2(a, -1.) != math.atan2(b, -1.):
self.fail("zero has wrong sign: expected %s, got %s" %
(repr(a), repr(b)))
# test passes if either the absolute error or the relative
# error is sufficiently small. The defaults amount to an
# error of between 9 ulps and 19 ulps on an IEEE-754 compliant
# machine.
if math.copysign(1., a) != math.copysign(1., b):
self.fail(msg or 'zero has wrong sign: expected {!r}, '
'got {!r}'.format(a, b))
# if a-b overflows, or b is infinite, return False. Again, in
# theory there are examples where a is within a few ulps of the
# max representable float, and then b could legitimately be
# infinite. In practice these examples are rare.
try:
absolute_error = abs(b-a)
except OverflowError:
pass
else:
# test passes if either the absolute error or the relative
# error is sufficiently small. The defaults amount to an
# error of between 9 ulps and 19 ulps on an IEEE-754 compliant
# machine.
if absolute_error <= max(abs_err, rel_err * abs(a)):
return
self.fail("%s and %s are not sufficiently close" % (repr(a), repr(b)))
self.fail(msg or
'{!r} and {!r} are not sufficiently close'.format(a, b))
def test_constants(self):
e_expected = 2.71828182845904523536
pi_expected = 3.14159265358979323846
self.assertAlmostEqual(cmath.pi, pi_expected, places=9,
msg="cmath.pi is %s; should be %s" % (cmath.pi, pi_expected))
msg="cmath.pi is {}; should be {}".format(cmath.pi, pi_expected))
self.assertAlmostEqual(cmath.e, e_expected, places=9,
msg="cmath.e is %s; should be %s" % (cmath.e, e_expected))
msg="cmath.e is {}; should be {}".format(cmath.e, e_expected))
def test_user_object(self):
# Test automatic calling of __complex__ and __float__ by cmath
@ -325,8 +310,8 @@ class CMathTests(unittest.TestCase):
except ValueError:
continue
else:
test_str = "%s: %s(complex(%r, %r))" % (id, fn, ar, ai)
self.fail('ValueError not raised in test %s' % test_str)
self.fail('ValueError not raised in test '
'{}: {}(complex({!r}, {!r}))'.format(id, fn, ar, ai))
if 'overflow' in flags:
try:
@ -334,8 +319,8 @@ class CMathTests(unittest.TestCase):
except OverflowError:
continue
else:
test_str = "%s: %s(complex(%r, %r))" % (id, fn, ar, ai)
self.fail('OverflowError not raised in test %s' % test_str)
self.fail('OverflowError not raised in test '
'{}: {}(complex({!r}, {!r}))'.format(id, fn, ar, ai))
actual = function(arg)
@ -353,17 +338,19 @@ class CMathTests(unittest.TestCase):
else:
real_abs_err = 5e-323
if not (almostEqualF(expected.real, actual.real,
abs_err = real_abs_err) and
almostEqualF(expected.imag, actual.imag)):
error_message = (
"%s: %s(complex(%r, %r))\n" % (id, fn, ar, ai) +
"Expected: complex(%r, %r)\n" %
(expected.real, expected.imag) +
"Received: complex(%r, %r)\n" %
(actual.real, actual.imag) +
"Received value insufficiently close to expected value.")
self.fail(error_message)
error_message = (
'{}: {}(complex({!r}, {!r}))\n'
'Expected: complex({!r}, {!r})\n'
'Received: complex({!r}, {!r})\n'
'Received value insufficiently close to expected value.'
).format(id, fn, ar, ai,
expected.real, expected.imag,
actual.real, actual.imag)
self.rAssertAlmostEqual(expected.real, actual.real,
abs_err=real_abs_err,
msg=error_message)
self.rAssertAlmostEqual(expected.imag, actual.imag,
msg=error_message)
def assertCISEqual(self, a, b):
eps = 1E-7