mirror of
https://github.com/python/cpython.git
synced 2024-11-24 17:47:13 +01:00
This commit is contained in:
parent
beee91cdcc
commit
8ef8354ef1
@ -1,3 +1,6 @@
|
|||||||
|
from math import copysign, isnan
|
||||||
|
|
||||||
|
|
||||||
class ExceptionIsLikeMixin:
|
class ExceptionIsLikeMixin:
|
||||||
def assertExceptionIsLike(self, exc, template):
|
def assertExceptionIsLike(self, exc, template):
|
||||||
"""
|
"""
|
||||||
@ -23,3 +26,40 @@ class ExceptionIsLikeMixin:
|
|||||||
self.assertEqual(len(exc.exceptions), len(template.exceptions))
|
self.assertEqual(len(exc.exceptions), len(template.exceptions))
|
||||||
for e, t in zip(exc.exceptions, template.exceptions):
|
for e, t in zip(exc.exceptions, template.exceptions):
|
||||||
self.assertExceptionIsLike(e, t)
|
self.assertExceptionIsLike(e, t)
|
||||||
|
|
||||||
|
|
||||||
|
class FloatsAreIdenticalMixin:
|
||||||
|
def assertFloatsAreIdentical(self, x, y):
|
||||||
|
"""Fail unless floats x and y are identical, in the sense that:
|
||||||
|
(1) both x and y are nans, or
|
||||||
|
(2) both x and y are infinities, with the same sign, or
|
||||||
|
(3) both x and y are zeros, with the same sign, or
|
||||||
|
(4) x and y are both finite and nonzero, and x == y
|
||||||
|
|
||||||
|
"""
|
||||||
|
msg = 'floats {!r} and {!r} are not identical'
|
||||||
|
|
||||||
|
if isnan(x) or isnan(y):
|
||||||
|
if isnan(x) and isnan(y):
|
||||||
|
return
|
||||||
|
elif x == y:
|
||||||
|
if x != 0.0:
|
||||||
|
return
|
||||||
|
# both zero; check that signs match
|
||||||
|
elif copysign(1.0, x) == copysign(1.0, y):
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
msg += ': zeros have different signs'
|
||||||
|
self.fail(msg.format(x, y))
|
||||||
|
|
||||||
|
|
||||||
|
class ComplexesAreIdenticalMixin(FloatsAreIdenticalMixin):
|
||||||
|
def assertComplexesAreIdentical(self, x, y):
|
||||||
|
"""Fail unless complex numbers x and y have equal values and signs.
|
||||||
|
|
||||||
|
In particular, if x and y both have real (or imaginary) part
|
||||||
|
zero, but the zeros have different signs, this test will fail.
|
||||||
|
|
||||||
|
"""
|
||||||
|
self.assertFloatsAreIdentical(x.real, y.real)
|
||||||
|
self.assertFloatsAreIdentical(x.imag, y.imag)
|
||||||
|
@ -6,6 +6,7 @@ from test import support
|
|||||||
from test.support import import_helper
|
from test.support import import_helper
|
||||||
from test.support import script_helper
|
from test.support import script_helper
|
||||||
from test.support import warnings_helper
|
from test.support import warnings_helper
|
||||||
|
from test.support.testcase import FloatsAreIdenticalMixin
|
||||||
# Skip this test if the _testcapi module isn't available.
|
# Skip this test if the _testcapi module isn't available.
|
||||||
_testcapi = import_helper.import_module('_testcapi')
|
_testcapi = import_helper.import_module('_testcapi')
|
||||||
from _testcapi import getargs_keywords, getargs_keyword_only
|
from _testcapi import getargs_keywords, getargs_keyword_only
|
||||||
@ -436,11 +437,7 @@ class LongLong_TestCase(unittest.TestCase):
|
|||||||
self.assertEqual(VERY_LARGE & ULLONG_MAX, getargs_K(VERY_LARGE))
|
self.assertEqual(VERY_LARGE & ULLONG_MAX, getargs_K(VERY_LARGE))
|
||||||
|
|
||||||
|
|
||||||
class Float_TestCase(unittest.TestCase):
|
class Float_TestCase(unittest.TestCase, FloatsAreIdenticalMixin):
|
||||||
def assertEqualWithSign(self, actual, expected):
|
|
||||||
self.assertEqual(actual, expected)
|
|
||||||
self.assertEqual(math.copysign(1, actual), math.copysign(1, expected))
|
|
||||||
|
|
||||||
def test_f(self):
|
def test_f(self):
|
||||||
from _testcapi import getargs_f
|
from _testcapi import getargs_f
|
||||||
self.assertEqual(getargs_f(4.25), 4.25)
|
self.assertEqual(getargs_f(4.25), 4.25)
|
||||||
@ -462,10 +459,10 @@ class Float_TestCase(unittest.TestCase):
|
|||||||
self.assertEqual(getargs_f(DBL_MAX), INF)
|
self.assertEqual(getargs_f(DBL_MAX), INF)
|
||||||
self.assertEqual(getargs_f(-DBL_MAX), -INF)
|
self.assertEqual(getargs_f(-DBL_MAX), -INF)
|
||||||
if FLT_MIN > DBL_MIN:
|
if FLT_MIN > DBL_MIN:
|
||||||
self.assertEqualWithSign(getargs_f(DBL_MIN), 0.0)
|
self.assertFloatsAreIdentical(getargs_f(DBL_MIN), 0.0)
|
||||||
self.assertEqualWithSign(getargs_f(-DBL_MIN), -0.0)
|
self.assertFloatsAreIdentical(getargs_f(-DBL_MIN), -0.0)
|
||||||
self.assertEqualWithSign(getargs_f(0.0), 0.0)
|
self.assertFloatsAreIdentical(getargs_f(0.0), 0.0)
|
||||||
self.assertEqualWithSign(getargs_f(-0.0), -0.0)
|
self.assertFloatsAreIdentical(getargs_f(-0.0), -0.0)
|
||||||
r = getargs_f(NAN)
|
r = getargs_f(NAN)
|
||||||
self.assertNotEqual(r, r)
|
self.assertNotEqual(r, r)
|
||||||
|
|
||||||
@ -494,8 +491,8 @@ class Float_TestCase(unittest.TestCase):
|
|||||||
self.assertEqual(getargs_d(x), x)
|
self.assertEqual(getargs_d(x), x)
|
||||||
self.assertRaises(OverflowError, getargs_d, 1<<DBL_MAX_EXP)
|
self.assertRaises(OverflowError, getargs_d, 1<<DBL_MAX_EXP)
|
||||||
self.assertRaises(OverflowError, getargs_d, -1<<DBL_MAX_EXP)
|
self.assertRaises(OverflowError, getargs_d, -1<<DBL_MAX_EXP)
|
||||||
self.assertEqualWithSign(getargs_d(0.0), 0.0)
|
self.assertFloatsAreIdentical(getargs_d(0.0), 0.0)
|
||||||
self.assertEqualWithSign(getargs_d(-0.0), -0.0)
|
self.assertFloatsAreIdentical(getargs_d(-0.0), -0.0)
|
||||||
r = getargs_d(NAN)
|
r = getargs_d(NAN)
|
||||||
self.assertNotEqual(r, r)
|
self.assertNotEqual(r, r)
|
||||||
|
|
||||||
@ -519,10 +516,10 @@ class Float_TestCase(unittest.TestCase):
|
|||||||
self.assertEqual(getargs_D(c), c)
|
self.assertEqual(getargs_D(c), c)
|
||||||
c = complex(1.0, x)
|
c = complex(1.0, x)
|
||||||
self.assertEqual(getargs_D(c), c)
|
self.assertEqual(getargs_D(c), c)
|
||||||
self.assertEqualWithSign(getargs_D(complex(0.0, 1.0)).real, 0.0)
|
self.assertFloatsAreIdentical(getargs_D(complex(0.0, 1.0)).real, 0.0)
|
||||||
self.assertEqualWithSign(getargs_D(complex(-0.0, 1.0)).real, -0.0)
|
self.assertFloatsAreIdentical(getargs_D(complex(-0.0, 1.0)).real, -0.0)
|
||||||
self.assertEqualWithSign(getargs_D(complex(1.0, 0.0)).imag, 0.0)
|
self.assertFloatsAreIdentical(getargs_D(complex(1.0, 0.0)).imag, 0.0)
|
||||||
self.assertEqualWithSign(getargs_D(complex(1.0, -0.0)).imag, -0.0)
|
self.assertFloatsAreIdentical(getargs_D(complex(1.0, -0.0)).imag, -0.0)
|
||||||
|
|
||||||
|
|
||||||
class Paradox:
|
class Paradox:
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
from test.support import requires_IEEE_754, cpython_only, import_helper
|
from test.support import requires_IEEE_754, cpython_only, import_helper
|
||||||
|
from test.support.testcase import ComplexesAreIdenticalMixin
|
||||||
from test.test_math import parse_testfile, test_file
|
from test.test_math import parse_testfile, test_file
|
||||||
import test.test_math as test_math
|
import test.test_math as test_math
|
||||||
import unittest
|
import unittest
|
||||||
@ -49,7 +50,7 @@ complex_nans = [complex(x, y) for x, y in [
|
|||||||
(INF, NAN)
|
(INF, NAN)
|
||||||
]]
|
]]
|
||||||
|
|
||||||
class CMathTests(unittest.TestCase):
|
class CMathTests(ComplexesAreIdenticalMixin, unittest.TestCase):
|
||||||
# list of all functions in cmath
|
# list of all functions in cmath
|
||||||
test_functions = [getattr(cmath, fname) for fname in [
|
test_functions = [getattr(cmath, fname) for fname in [
|
||||||
'acos', 'acosh', 'asin', 'asinh', 'atan', 'atanh',
|
'acos', 'acosh', 'asin', 'asinh', 'atan', 'atanh',
|
||||||
@ -65,39 +66,6 @@ class CMathTests(unittest.TestCase):
|
|||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
self.test_values.close()
|
self.test_values.close()
|
||||||
|
|
||||||
def assertFloatIdentical(self, x, y):
|
|
||||||
"""Fail unless floats x and y are identical, in the sense that:
|
|
||||||
(1) both x and y are nans, or
|
|
||||||
(2) both x and y are infinities, with the same sign, or
|
|
||||||
(3) both x and y are zeros, with the same sign, or
|
|
||||||
(4) x and y are both finite and nonzero, and x == y
|
|
||||||
|
|
||||||
"""
|
|
||||||
msg = 'floats {!r} and {!r} are not identical'
|
|
||||||
|
|
||||||
if math.isnan(x) or math.isnan(y):
|
|
||||||
if math.isnan(x) and math.isnan(y):
|
|
||||||
return
|
|
||||||
elif x == y:
|
|
||||||
if x != 0.0:
|
|
||||||
return
|
|
||||||
# both zero; check that signs match
|
|
||||||
elif math.copysign(1.0, x) == math.copysign(1.0, y):
|
|
||||||
return
|
|
||||||
else:
|
|
||||||
msg += ': zeros have different signs'
|
|
||||||
self.fail(msg.format(x, y))
|
|
||||||
|
|
||||||
def assertComplexIdentical(self, x, y):
|
|
||||||
"""Fail unless complex numbers x and y have equal values and signs.
|
|
||||||
|
|
||||||
In particular, if x and y both have real (or imaginary) part
|
|
||||||
zero, but the zeros have different signs, this test will fail.
|
|
||||||
|
|
||||||
"""
|
|
||||||
self.assertFloatIdentical(x.real, y.real)
|
|
||||||
self.assertFloatIdentical(x.imag, y.imag)
|
|
||||||
|
|
||||||
def rAssertAlmostEqual(self, a, b, rel_err = 2e-15, abs_err = 5e-323,
|
def rAssertAlmostEqual(self, a, b, rel_err = 2e-15, abs_err = 5e-323,
|
||||||
msg=None):
|
msg=None):
|
||||||
"""Fail if the two floating-point numbers are not almost equal.
|
"""Fail if the two floating-point numbers are not almost equal.
|
||||||
@ -555,7 +523,7 @@ class CMathTests(unittest.TestCase):
|
|||||||
@requires_IEEE_754
|
@requires_IEEE_754
|
||||||
def testTanhSign(self):
|
def testTanhSign(self):
|
||||||
for z in complex_zeros:
|
for z in complex_zeros:
|
||||||
self.assertComplexIdentical(cmath.tanh(z), z)
|
self.assertComplexesAreIdentical(cmath.tanh(z), z)
|
||||||
|
|
||||||
# The algorithm used for atan and atanh makes use of the system
|
# The algorithm used for atan and atanh makes use of the system
|
||||||
# log1p function; If that system function doesn't respect the sign
|
# log1p function; If that system function doesn't respect the sign
|
||||||
@ -564,12 +532,12 @@ class CMathTests(unittest.TestCase):
|
|||||||
@requires_IEEE_754
|
@requires_IEEE_754
|
||||||
def testAtanSign(self):
|
def testAtanSign(self):
|
||||||
for z in complex_zeros:
|
for z in complex_zeros:
|
||||||
self.assertComplexIdentical(cmath.atan(z), z)
|
self.assertComplexesAreIdentical(cmath.atan(z), z)
|
||||||
|
|
||||||
@requires_IEEE_754
|
@requires_IEEE_754
|
||||||
def testAtanhSign(self):
|
def testAtanhSign(self):
|
||||||
for z in complex_zeros:
|
for z in complex_zeros:
|
||||||
self.assertComplexIdentical(cmath.atanh(z), z)
|
self.assertComplexesAreIdentical(cmath.atanh(z), z)
|
||||||
|
|
||||||
|
|
||||||
class IsCloseTests(test_math.IsCloseTests):
|
class IsCloseTests(test_math.IsCloseTests):
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import unittest
|
import unittest
|
||||||
import sys
|
import sys
|
||||||
from test import support
|
from test import support
|
||||||
|
from test.support.testcase import ComplexesAreIdenticalMixin
|
||||||
from test.test_grammar import (VALID_UNDERSCORE_LITERALS,
|
from test.test_grammar import (VALID_UNDERSCORE_LITERALS,
|
||||||
INVALID_UNDERSCORE_LITERALS)
|
INVALID_UNDERSCORE_LITERALS)
|
||||||
|
|
||||||
@ -52,7 +53,7 @@ class WithComplex:
|
|||||||
def __complex__(self):
|
def __complex__(self):
|
||||||
return self.value
|
return self.value
|
||||||
|
|
||||||
class ComplexTest(unittest.TestCase):
|
class ComplexTest(ComplexesAreIdenticalMixin, unittest.TestCase):
|
||||||
|
|
||||||
def assertAlmostEqual(self, a, b):
|
def assertAlmostEqual(self, a, b):
|
||||||
if isinstance(a, complex):
|
if isinstance(a, complex):
|
||||||
@ -81,33 +82,6 @@ class ComplexTest(unittest.TestCase):
|
|||||||
# check that relative difference < eps
|
# check that relative difference < eps
|
||||||
self.assertTrue(abs((x-y)/y) < eps)
|
self.assertTrue(abs((x-y)/y) < eps)
|
||||||
|
|
||||||
def assertFloatsAreIdentical(self, x, y):
|
|
||||||
"""assert that floats x and y are identical, in the sense that:
|
|
||||||
(1) both x and y are nans, or
|
|
||||||
(2) both x and y are infinities, with the same sign, or
|
|
||||||
(3) both x and y are zeros, with the same sign, or
|
|
||||||
(4) x and y are both finite and nonzero, and x == y
|
|
||||||
|
|
||||||
"""
|
|
||||||
msg = 'floats {!r} and {!r} are not identical'
|
|
||||||
|
|
||||||
if isnan(x) or isnan(y):
|
|
||||||
if isnan(x) and isnan(y):
|
|
||||||
return
|
|
||||||
elif x == y:
|
|
||||||
if x != 0.0:
|
|
||||||
return
|
|
||||||
# both zero; check that signs match
|
|
||||||
elif copysign(1.0, x) == copysign(1.0, y):
|
|
||||||
return
|
|
||||||
else:
|
|
||||||
msg += ': zeros have different signs'
|
|
||||||
self.fail(msg.format(x, y))
|
|
||||||
|
|
||||||
def assertComplexesAreIdentical(self, x, y):
|
|
||||||
self.assertFloatsAreIdentical(x.real, y.real)
|
|
||||||
self.assertFloatsAreIdentical(x.imag, y.imag)
|
|
||||||
|
|
||||||
def assertClose(self, x, y, eps=1e-9):
|
def assertClose(self, x, y, eps=1e-9):
|
||||||
"""Return true iff complexes x and y "are close"."""
|
"""Return true iff complexes x and y "are close"."""
|
||||||
self.assertCloseAbs(x.real, y.real, eps)
|
self.assertCloseAbs(x.real, y.real, eps)
|
||||||
@ -829,8 +803,7 @@ class ComplexTest(unittest.TestCase):
|
|||||||
for y in vals:
|
for y in vals:
|
||||||
z = complex(x, y)
|
z = complex(x, y)
|
||||||
roundtrip = complex(repr(z))
|
roundtrip = complex(repr(z))
|
||||||
self.assertFloatsAreIdentical(z.real, roundtrip.real)
|
self.assertComplexesAreIdentical(z, roundtrip)
|
||||||
self.assertFloatsAreIdentical(z.imag, roundtrip.imag)
|
|
||||||
|
|
||||||
# if we predefine some constants, then eval(repr(z)) should
|
# if we predefine some constants, then eval(repr(z)) should
|
||||||
# also work, except that it might change the sign of zeros
|
# also work, except that it might change the sign of zeros
|
||||||
|
@ -4,12 +4,12 @@ import struct
|
|||||||
import sys
|
import sys
|
||||||
import unittest
|
import unittest
|
||||||
from itertools import combinations
|
from itertools import combinations
|
||||||
from math import copysign, isnan
|
|
||||||
from operator import truth
|
from operator import truth
|
||||||
from ctypes import (byref, sizeof, alignment,
|
from ctypes import (byref, sizeof, alignment,
|
||||||
c_char, c_byte, c_ubyte, c_short, c_ushort, c_int, c_uint,
|
c_char, c_byte, c_ubyte, c_short, c_ushort, c_int, c_uint,
|
||||||
c_long, c_ulong, c_longlong, c_ulonglong,
|
c_long, c_ulong, c_longlong, c_ulonglong,
|
||||||
c_float, c_double, c_longdouble, c_bool)
|
c_float, c_double, c_longdouble, c_bool)
|
||||||
|
from test.support.testcase import ComplexesAreIdenticalMixin
|
||||||
|
|
||||||
|
|
||||||
def valid_ranges(*types):
|
def valid_ranges(*types):
|
||||||
@ -62,34 +62,7 @@ INF = float("inf")
|
|||||||
NAN = float("nan")
|
NAN = float("nan")
|
||||||
|
|
||||||
|
|
||||||
class NumberTestCase(unittest.TestCase):
|
class NumberTestCase(unittest.TestCase, ComplexesAreIdenticalMixin):
|
||||||
# from Lib/test/test_complex.py
|
|
||||||
def assertFloatsAreIdentical(self, x, y):
|
|
||||||
"""assert that floats x and y are identical, in the sense that:
|
|
||||||
(1) both x and y are nans, or
|
|
||||||
(2) both x and y are infinities, with the same sign, or
|
|
||||||
(3) both x and y are zeros, with the same sign, or
|
|
||||||
(4) x and y are both finite and nonzero, and x == y
|
|
||||||
|
|
||||||
"""
|
|
||||||
msg = 'floats {!r} and {!r} are not identical'
|
|
||||||
|
|
||||||
if isnan(x) or isnan(y):
|
|
||||||
if isnan(x) and isnan(y):
|
|
||||||
return
|
|
||||||
elif x == y:
|
|
||||||
if x != 0.0:
|
|
||||||
return
|
|
||||||
# both zero; check that signs match
|
|
||||||
elif copysign(1.0, x) == copysign(1.0, y):
|
|
||||||
return
|
|
||||||
else:
|
|
||||||
msg += ': zeros have different signs'
|
|
||||||
self.fail(msg.format(x, y))
|
|
||||||
|
|
||||||
def assertComplexesAreIdentical(self, x, y):
|
|
||||||
self.assertFloatsAreIdentical(x.real, y.real)
|
|
||||||
self.assertFloatsAreIdentical(x.imag, y.imag)
|
|
||||||
|
|
||||||
def test_default_init(self):
|
def test_default_init(self):
|
||||||
# default values are set to zero
|
# default values are set to zero
|
||||||
|
@ -8,6 +8,7 @@ import time
|
|||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
from test import support
|
from test import support
|
||||||
|
from test.support.testcase import FloatsAreIdenticalMixin
|
||||||
from test.test_grammar import (VALID_UNDERSCORE_LITERALS,
|
from test.test_grammar import (VALID_UNDERSCORE_LITERALS,
|
||||||
INVALID_UNDERSCORE_LITERALS)
|
INVALID_UNDERSCORE_LITERALS)
|
||||||
from math import isinf, isnan, copysign, ldexp
|
from math import isinf, isnan, copysign, ldexp
|
||||||
@ -1093,21 +1094,14 @@ class InfNanTest(unittest.TestCase):
|
|||||||
|
|
||||||
fromHex = float.fromhex
|
fromHex = float.fromhex
|
||||||
toHex = float.hex
|
toHex = float.hex
|
||||||
class HexFloatTestCase(unittest.TestCase):
|
class HexFloatTestCase(FloatsAreIdenticalMixin, unittest.TestCase):
|
||||||
MAX = fromHex('0x.fffffffffffff8p+1024') # max normal
|
MAX = fromHex('0x.fffffffffffff8p+1024') # max normal
|
||||||
MIN = fromHex('0x1p-1022') # min normal
|
MIN = fromHex('0x1p-1022') # min normal
|
||||||
TINY = fromHex('0x0.0000000000001p-1022') # min subnormal
|
TINY = fromHex('0x0.0000000000001p-1022') # min subnormal
|
||||||
EPS = fromHex('0x0.0000000000001p0') # diff between 1.0 and next float up
|
EPS = fromHex('0x0.0000000000001p0') # diff between 1.0 and next float up
|
||||||
|
|
||||||
def identical(self, x, y):
|
def identical(self, x, y):
|
||||||
# check that floats x and y are identical, or that both
|
self.assertFloatsAreIdentical(x, y)
|
||||||
# are NaNs
|
|
||||||
if isnan(x) or isnan(y):
|
|
||||||
if isnan(x) == isnan(y):
|
|
||||||
return
|
|
||||||
elif x == y and (x != 0.0 or copysign(1.0, x) == copysign(1.0, y)):
|
|
||||||
return
|
|
||||||
self.fail('%r not identical to %r' % (x, y))
|
|
||||||
|
|
||||||
def test_ends(self):
|
def test_ends(self):
|
||||||
self.identical(self.MIN, ldexp(1.0, -1022))
|
self.identical(self.MIN, ldexp(1.0, -1022))
|
||||||
|
Loading…
Reference in New Issue
Block a user