|
8 | 8 | import unittest
|
9 | 9 |
|
10 | 10 | from test import support
|
11 |
| -from test.support import import_helper |
| 11 | +from test.support.testcase import FloatsAreIdenticalMixin |
12 | 12 | from test.test_grammar import (VALID_UNDERSCORE_LITERALS,
|
13 | 13 | INVALID_UNDERSCORE_LITERALS)
|
14 | 14 | from math import isinf, isnan, copysign, ldexp
|
|
19 | 19 | except ImportError:
|
20 | 20 | _testcapi = None
|
21 | 21 |
|
22 |
| -HAVE_IEEE_754 = float.__getformat__("double").startswith("IEEE") |
23 | 22 | INF = float("inf")
|
24 | 23 | NAN = float("nan")
|
25 | 24 |
|
@@ -742,8 +741,13 @@ def test_format_testfile(self):
|
742 | 741 |
|
743 | 742 | lhs, rhs = map(str.strip, line.split('->'))
|
744 | 743 | fmt, arg = lhs.split()
|
745 |
| - self.assertEqual(fmt % float(arg), rhs) |
746 |
| - self.assertEqual(fmt % -float(arg), '-' + rhs) |
| 744 | + f = float(arg) |
| 745 | + self.assertEqual(fmt % f, rhs) |
| 746 | + self.assertEqual(fmt % -f, '-' + rhs) |
| 747 | + if fmt != '%r': |
| 748 | + fmt2 = fmt[1:] |
| 749 | + self.assertEqual(format(f, fmt2), rhs) |
| 750 | + self.assertEqual(format(-f, fmt2), '-' + rhs) |
747 | 751 |
|
748 | 752 | def test_issue5864(self):
|
749 | 753 | self.assertEqual(format(123.456, '.4'), '123.5')
|
@@ -833,7 +837,7 @@ def test_short_repr(self):
|
833 | 837 | self.assertEqual(repr(float(negs)), str(float(negs)))
|
834 | 838 |
|
835 | 839 | @support.requires_IEEE_754
|
836 |
| -class RoundTestCase(unittest.TestCase): |
| 840 | +class RoundTestCase(unittest.TestCase, FloatsAreIdenticalMixin): |
837 | 841 |
|
838 | 842 | def test_inf_nan(self):
|
839 | 843 | self.assertRaises(OverflowError, round, INF)
|
@@ -863,10 +867,10 @@ def test_large_n(self):
|
863 | 867 |
|
864 | 868 | def test_small_n(self):
|
865 | 869 | for n in [-308, -309, -400, 1-2**31, -2**31, -2**31-1, -2**100]:
|
866 |
| - self.assertEqual(round(123.456, n), 0.0) |
867 |
| - self.assertEqual(round(-123.456, n), -0.0) |
868 |
| - self.assertEqual(round(1e300, n), 0.0) |
869 |
| - self.assertEqual(round(1e-320, n), 0.0) |
| 870 | + self.assertFloatsAreIdentical(round(123.456, n), 0.0) |
| 871 | + self.assertFloatsAreIdentical(round(-123.456, n), -0.0) |
| 872 | + self.assertFloatsAreIdentical(round(1e300, n), 0.0) |
| 873 | + self.assertFloatsAreIdentical(round(1e-320, n), 0.0) |
870 | 874 |
|
871 | 875 | def test_overflow(self):
|
872 | 876 | self.assertRaises(OverflowError, round, 1.6e308, -308)
|
@@ -1053,32 +1057,22 @@ def test_inf_signs(self):
|
1053 | 1057 | self.assertEqual(copysign(1.0, float('inf')), 1.0)
|
1054 | 1058 | self.assertEqual(copysign(1.0, float('-inf')), -1.0)
|
1055 | 1059 |
|
1056 |
| - @unittest.skipUnless(getattr(sys, 'float_repr_style', '') == 'short', |
1057 |
| - "applies only when using short float repr style") |
1058 | 1060 | def test_nan_signs(self):
|
1059 |
| - # When using the dtoa.c code, the sign of float('nan') should |
1060 |
| - # be predictable. |
| 1061 | + # The sign of float('nan') should be predictable. |
1061 | 1062 | self.assertEqual(copysign(1.0, float('nan')), 1.0)
|
1062 | 1063 | self.assertEqual(copysign(1.0, float('-nan')), -1.0)
|
1063 | 1064 |
|
1064 | 1065 |
|
1065 | 1066 | fromHex = float.fromhex
|
1066 | 1067 | toHex = float.hex
|
1067 |
| -class HexFloatTestCase(unittest.TestCase): |
| 1068 | +class HexFloatTestCase(FloatsAreIdenticalMixin, unittest.TestCase): |
1068 | 1069 | MAX = fromHex('0x.fffffffffffff8p+1024') # max normal
|
1069 | 1070 | MIN = fromHex('0x1p-1022') # min normal
|
1070 | 1071 | TINY = fromHex('0x0.0000000000001p-1022') # min subnormal
|
1071 | 1072 | EPS = fromHex('0x0.0000000000001p0') # diff between 1.0 and next float up
|
1072 | 1073 |
|
1073 | 1074 | def identical(self, x, y):
|
1074 |
| - # check that floats x and y are identical, or that both |
1075 |
| - # are NaNs |
1076 |
| - if isnan(x) or isnan(y): |
1077 |
| - if isnan(x) == isnan(y): |
1078 |
| - return |
1079 |
| - elif x == y and (x != 0.0 or copysign(1.0, x) == copysign(1.0, y)): |
1080 |
| - return |
1081 |
| - self.fail('%r not identical to %r' % (x, y)) |
| 1075 | + self.assertFloatsAreIdentical(x, y) |
1082 | 1076 |
|
1083 | 1077 | def test_ends(self):
|
1084 | 1078 | self.identical(self.MIN, ldexp(1.0, -1022))
|
@@ -1517,69 +1511,5 @@ def __init__(self, value):
|
1517 | 1511 | self.assertEqual(getattr(f, 'foo', 'none'), 'bar')
|
1518 | 1512 |
|
1519 | 1513 |
|
1520 |
| -# Test PyFloat_Pack2(), PyFloat_Pack4() and PyFloat_Pack8() |
1521 |
| -# Test PyFloat_Unpack2(), PyFloat_Unpack4() and PyFloat_Unpack8() |
1522 |
| -BIG_ENDIAN = 0 |
1523 |
| -LITTLE_ENDIAN = 1 |
1524 |
| -EPSILON = { |
1525 |
| - 2: 2.0 ** -11, # binary16 |
1526 |
| - 4: 2.0 ** -24, # binary32 |
1527 |
| - 8: 2.0 ** -53, # binary64 |
1528 |
| -} |
1529 |
| - |
1530 |
| -@unittest.skipIf(_testcapi is None, 'needs _testcapi') |
1531 |
| -class PackTests(unittest.TestCase): |
1532 |
| - def test_pack(self): |
1533 |
| - self.assertEqual(_testcapi.float_pack(2, 1.5, BIG_ENDIAN), |
1534 |
| - b'>\x00') |
1535 |
| - self.assertEqual(_testcapi.float_pack(4, 1.5, BIG_ENDIAN), |
1536 |
| - b'?\xc0\x00\x00') |
1537 |
| - self.assertEqual(_testcapi.float_pack(8, 1.5, BIG_ENDIAN), |
1538 |
| - b'?\xf8\x00\x00\x00\x00\x00\x00') |
1539 |
| - self.assertEqual(_testcapi.float_pack(2, 1.5, LITTLE_ENDIAN), |
1540 |
| - b'\x00>') |
1541 |
| - self.assertEqual(_testcapi.float_pack(4, 1.5, LITTLE_ENDIAN), |
1542 |
| - b'\x00\x00\xc0?') |
1543 |
| - self.assertEqual(_testcapi.float_pack(8, 1.5, LITTLE_ENDIAN), |
1544 |
| - b'\x00\x00\x00\x00\x00\x00\xf8?') |
1545 |
| - |
1546 |
| - def test_unpack(self): |
1547 |
| - self.assertEqual(_testcapi.float_unpack(b'>\x00', BIG_ENDIAN), |
1548 |
| - 1.5) |
1549 |
| - self.assertEqual(_testcapi.float_unpack(b'?\xc0\x00\x00', BIG_ENDIAN), |
1550 |
| - 1.5) |
1551 |
| - self.assertEqual(_testcapi.float_unpack(b'?\xf8\x00\x00\x00\x00\x00\x00', BIG_ENDIAN), |
1552 |
| - 1.5) |
1553 |
| - self.assertEqual(_testcapi.float_unpack(b'\x00>', LITTLE_ENDIAN), |
1554 |
| - 1.5) |
1555 |
| - self.assertEqual(_testcapi.float_unpack(b'\x00\x00\xc0?', LITTLE_ENDIAN), |
1556 |
| - 1.5) |
1557 |
| - self.assertEqual(_testcapi.float_unpack(b'\x00\x00\x00\x00\x00\x00\xf8?', LITTLE_ENDIAN), |
1558 |
| - 1.5) |
1559 |
| - |
1560 |
| - def test_roundtrip(self): |
1561 |
| - large = 2.0 ** 100 |
1562 |
| - values = [1.0, 1.5, large, 1.0/7, math.pi] |
1563 |
| - if HAVE_IEEE_754: |
1564 |
| - values.extend((INF, NAN)) |
1565 |
| - for value in values: |
1566 |
| - for size in (2, 4, 8,): |
1567 |
| - if size == 2 and value == large: |
1568 |
| - # too large for 16-bit float |
1569 |
| - continue |
1570 |
| - rel_tol = EPSILON[size] |
1571 |
| - for endian in (BIG_ENDIAN, LITTLE_ENDIAN): |
1572 |
| - with self.subTest(value=value, size=size, endian=endian): |
1573 |
| - data = _testcapi.float_pack(size, value, endian) |
1574 |
| - value2 = _testcapi.float_unpack(data, endian) |
1575 |
| - if isnan(value): |
1576 |
| - self.assertTrue(isnan(value2), (value, value2)) |
1577 |
| - elif size < 8: |
1578 |
| - self.assertTrue(math.isclose(value2, value, rel_tol=rel_tol), |
1579 |
| - (value, value2)) |
1580 |
| - else: |
1581 |
| - self.assertEqual(value2, value) |
1582 |
| - |
1583 |
| - |
1584 | 1514 | if __name__ == '__main__':
|
1585 | 1515 | unittest.main()
|
0 commit comments