copy from cpython v3.12.7

This commit is contained in:
2024-11-29 08:50:52 +09:00
parent 848db340da
commit 044f66fba3

102
Lib/test/test_float.py vendored
View File

@@ -8,7 +8,7 @@ import time
import unittest
from test import support
from test.support import import_helper
from test.support.testcase import FloatsAreIdenticalMixin
from test.test_grammar import (VALID_UNDERSCORE_LITERALS,
INVALID_UNDERSCORE_LITERALS)
from math import isinf, isnan, copysign, ldexp
@@ -19,7 +19,6 @@ try:
except ImportError:
_testcapi = None
HAVE_IEEE_754 = float.__getformat__("double").startswith("IEEE")
INF = float("inf")
NAN = float("nan")
@@ -742,8 +741,13 @@ class FormatTestCase(unittest.TestCase):
lhs, rhs = map(str.strip, line.split('->'))
fmt, arg = lhs.split()
self.assertEqual(fmt % float(arg), rhs)
self.assertEqual(fmt % -float(arg), '-' + rhs)
f = float(arg)
self.assertEqual(fmt % f, rhs)
self.assertEqual(fmt % -f, '-' + rhs)
if fmt != '%r':
fmt2 = fmt[1:]
self.assertEqual(format(f, fmt2), rhs)
self.assertEqual(format(-f, fmt2), '-' + rhs)
def test_issue5864(self):
self.assertEqual(format(123.456, '.4'), '123.5')
@@ -833,7 +837,7 @@ class ReprTestCase(unittest.TestCase):
self.assertEqual(repr(float(negs)), str(float(negs)))
@support.requires_IEEE_754
class RoundTestCase(unittest.TestCase):
class RoundTestCase(unittest.TestCase, FloatsAreIdenticalMixin):
def test_inf_nan(self):
self.assertRaises(OverflowError, round, INF)
@@ -863,10 +867,10 @@ class RoundTestCase(unittest.TestCase):
def test_small_n(self):
for n in [-308, -309, -400, 1-2**31, -2**31, -2**31-1, -2**100]:
self.assertEqual(round(123.456, n), 0.0)
self.assertEqual(round(-123.456, n), -0.0)
self.assertEqual(round(1e300, n), 0.0)
self.assertEqual(round(1e-320, n), 0.0)
self.assertFloatsAreIdentical(round(123.456, n), 0.0)
self.assertFloatsAreIdentical(round(-123.456, n), -0.0)
self.assertFloatsAreIdentical(round(1e300, n), 0.0)
self.assertFloatsAreIdentical(round(1e-320, n), 0.0)
def test_overflow(self):
self.assertRaises(OverflowError, round, 1.6e308, -308)
@@ -1053,32 +1057,22 @@ class InfNanTest(unittest.TestCase):
self.assertEqual(copysign(1.0, float('inf')), 1.0)
self.assertEqual(copysign(1.0, float('-inf')), -1.0)
@unittest.skipUnless(getattr(sys, 'float_repr_style', '') == 'short',
"applies only when using short float repr style")
def test_nan_signs(self):
# When using the dtoa.c code, the sign of float('nan') should
# be predictable.
# The sign of float('nan') should be predictable.
self.assertEqual(copysign(1.0, float('nan')), 1.0)
self.assertEqual(copysign(1.0, float('-nan')), -1.0)
fromHex = float.fromhex
toHex = float.hex
class HexFloatTestCase(unittest.TestCase):
class HexFloatTestCase(FloatsAreIdenticalMixin, unittest.TestCase):
MAX = fromHex('0x.fffffffffffff8p+1024') # max normal
MIN = fromHex('0x1p-1022') # min normal
TINY = fromHex('0x0.0000000000001p-1022') # min subnormal
EPS = fromHex('0x0.0000000000001p0') # diff between 1.0 and next float up
def identical(self, x, y):
# check that floats x and y are identical, or that both
# 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))
self.assertFloatsAreIdentical(x, y)
def test_ends(self):
self.identical(self.MIN, ldexp(1.0, -1022))
@@ -1517,69 +1511,5 @@ class HexFloatTestCase(unittest.TestCase):
self.assertEqual(getattr(f, 'foo', 'none'), 'bar')
# Test PyFloat_Pack2(), PyFloat_Pack4() and PyFloat_Pack8()
# Test PyFloat_Unpack2(), PyFloat_Unpack4() and PyFloat_Unpack8()
BIG_ENDIAN = 0
LITTLE_ENDIAN = 1
EPSILON = {
2: 2.0 ** -11, # binary16
4: 2.0 ** -24, # binary32
8: 2.0 ** -53, # binary64
}
@unittest.skipIf(_testcapi is None, 'needs _testcapi')
class PackTests(unittest.TestCase):
def test_pack(self):
self.assertEqual(_testcapi.float_pack(2, 1.5, BIG_ENDIAN),
b'>\x00')
self.assertEqual(_testcapi.float_pack(4, 1.5, BIG_ENDIAN),
b'?\xc0\x00\x00')
self.assertEqual(_testcapi.float_pack(8, 1.5, BIG_ENDIAN),
b'?\xf8\x00\x00\x00\x00\x00\x00')
self.assertEqual(_testcapi.float_pack(2, 1.5, LITTLE_ENDIAN),
b'\x00>')
self.assertEqual(_testcapi.float_pack(4, 1.5, LITTLE_ENDIAN),
b'\x00\x00\xc0?')
self.assertEqual(_testcapi.float_pack(8, 1.5, LITTLE_ENDIAN),
b'\x00\x00\x00\x00\x00\x00\xf8?')
def test_unpack(self):
self.assertEqual(_testcapi.float_unpack(b'>\x00', BIG_ENDIAN),
1.5)
self.assertEqual(_testcapi.float_unpack(b'?\xc0\x00\x00', BIG_ENDIAN),
1.5)
self.assertEqual(_testcapi.float_unpack(b'?\xf8\x00\x00\x00\x00\x00\x00', BIG_ENDIAN),
1.5)
self.assertEqual(_testcapi.float_unpack(b'\x00>', LITTLE_ENDIAN),
1.5)
self.assertEqual(_testcapi.float_unpack(b'\x00\x00\xc0?', LITTLE_ENDIAN),
1.5)
self.assertEqual(_testcapi.float_unpack(b'\x00\x00\x00\x00\x00\x00\xf8?', LITTLE_ENDIAN),
1.5)
def test_roundtrip(self):
large = 2.0 ** 100
values = [1.0, 1.5, large, 1.0/7, math.pi]
if HAVE_IEEE_754:
values.extend((INF, NAN))
for value in values:
for size in (2, 4, 8,):
if size == 2 and value == large:
# too large for 16-bit float
continue
rel_tol = EPSILON[size]
for endian in (BIG_ENDIAN, LITTLE_ENDIAN):
with self.subTest(value=value, size=size, endian=endian):
data = _testcapi.float_pack(size, value, endian)
value2 = _testcapi.float_unpack(data, endian)
if isnan(value):
self.assertTrue(isnan(value2), (value, value2))
elif size < 8:
self.assertTrue(math.isclose(value2, value, rel_tol=rel_tol),
(value, value2))
else:
self.assertEqual(value2, value)
if __name__ == '__main__':
unittest.main()