|
12 | 12 | from test.test_grammar import (VALID_UNDERSCORE_LITERALS, |
13 | 13 | INVALID_UNDERSCORE_LITERALS) |
14 | 14 | from math import isinf, isnan, copysign, ldexp |
| 15 | +import math |
15 | 16 |
|
| 17 | +try: |
| 18 | + import _testcapi |
| 19 | +except ImportError: |
| 20 | + _testcapi = None |
| 21 | + |
| 22 | +HAVE_IEEE_754 = float.__getformat__("double").startswith("IEEE") |
16 | 23 | INF = float("inf") |
17 | 24 | NAN = float("nan") |
18 | 25 |
|
@@ -652,8 +659,9 @@ def test_float_specials_do_unpack(self): |
652 | 659 | struct.unpack(fmt, data) |
653 | 660 |
|
654 | 661 | @support.requires_IEEE_754 |
| 662 | + @unittest.skipIf(_testcapi is None, 'needs _testcapi') |
655 | 663 | def test_serialized_float_rounding(self): |
656 | | - FLT_MAX = import_helper.import_module('_testcapi').FLT_MAX |
| 664 | + FLT_MAX = _testcapi.FLT_MAX |
657 | 665 | self.assertEqual(struct.pack("<f", 3.40282356e38), struct.pack("<f", FLT_MAX)) |
658 | 666 | self.assertEqual(struct.pack("<f", -3.40282356e38), struct.pack("<f", -FLT_MAX)) |
659 | 667 |
|
@@ -1488,5 +1496,69 @@ def __init__(self, value): |
1488 | 1496 | self.assertEqual(getattr(f, 'foo', 'none'), 'bar') |
1489 | 1497 |
|
1490 | 1498 |
|
| 1499 | +# Test PyFloat_Pack2(), PyFloat_Pack4() and PyFloat_Pack8() |
| 1500 | +# Test PyFloat_Unpack2(), PyFloat_Unpack4() and PyFloat_Unpack8() |
| 1501 | +BIG_ENDIAN = 0 |
| 1502 | +LITTLE_ENDIAN = 1 |
| 1503 | +EPSILON = { |
| 1504 | + 2: 2.0 ** -11, # binary16 |
| 1505 | + 4: 2.0 ** -24, # binary32 |
| 1506 | + 8: 2.0 ** -53, # binary64 |
| 1507 | +} |
| 1508 | + |
| 1509 | +@unittest.skipIf(_testcapi is None, 'needs _testcapi') |
| 1510 | +class PackTests(unittest.TestCase): |
| 1511 | + def test_pack(self): |
| 1512 | + self.assertEqual(_testcapi.float_pack(2, 1.5, BIG_ENDIAN), |
| 1513 | + b'>\x00') |
| 1514 | + self.assertEqual(_testcapi.float_pack(4, 1.5, BIG_ENDIAN), |
| 1515 | + b'?\xc0\x00\x00') |
| 1516 | + self.assertEqual(_testcapi.float_pack(8, 1.5, BIG_ENDIAN), |
| 1517 | + b'?\xf8\x00\x00\x00\x00\x00\x00') |
| 1518 | + self.assertEqual(_testcapi.float_pack(2, 1.5, LITTLE_ENDIAN), |
| 1519 | + b'\x00>') |
| 1520 | + self.assertEqual(_testcapi.float_pack(4, 1.5, LITTLE_ENDIAN), |
| 1521 | + b'\x00\x00\xc0?') |
| 1522 | + self.assertEqual(_testcapi.float_pack(8, 1.5, LITTLE_ENDIAN), |
| 1523 | + b'\x00\x00\x00\x00\x00\x00\xf8?') |
| 1524 | + |
| 1525 | + def test_unpack(self): |
| 1526 | + self.assertEqual(_testcapi.float_unpack(b'>\x00', BIG_ENDIAN), |
| 1527 | + 1.5) |
| 1528 | + self.assertEqual(_testcapi.float_unpack(b'?\xc0\x00\x00', BIG_ENDIAN), |
| 1529 | + 1.5) |
| 1530 | + self.assertEqual(_testcapi.float_unpack(b'?\xf8\x00\x00\x00\x00\x00\x00', BIG_ENDIAN), |
| 1531 | + 1.5) |
| 1532 | + self.assertEqual(_testcapi.float_unpack(b'\x00>', LITTLE_ENDIAN), |
| 1533 | + 1.5) |
| 1534 | + self.assertEqual(_testcapi.float_unpack(b'\x00\x00\xc0?', LITTLE_ENDIAN), |
| 1535 | + 1.5) |
| 1536 | + self.assertEqual(_testcapi.float_unpack(b'\x00\x00\x00\x00\x00\x00\xf8?', LITTLE_ENDIAN), |
| 1537 | + 1.5) |
| 1538 | + |
| 1539 | + def test_roundtrip(self): |
| 1540 | + large = 2.0 ** 100 |
| 1541 | + values = [1.0, 1.5, large, 1.0/7, math.pi] |
| 1542 | + if HAVE_IEEE_754: |
| 1543 | + values.extend((INF, NAN)) |
| 1544 | + for value in values: |
| 1545 | + for size in (2, 4, 8,): |
| 1546 | + if size == 2 and value == large: |
| 1547 | + # too large for 16-bit float |
| 1548 | + continue |
| 1549 | + rel_tol = EPSILON[size] |
| 1550 | + for endian in (BIG_ENDIAN, LITTLE_ENDIAN): |
| 1551 | + with self.subTest(value=value, size=size, endian=endian): |
| 1552 | + data = _testcapi.float_pack(size, value, endian) |
| 1553 | + value2 = _testcapi.float_unpack(data, endian) |
| 1554 | + if isnan(value): |
| 1555 | + self.assertTrue(isnan(value2), (value, value2)) |
| 1556 | + elif size < 8: |
| 1557 | + self.assertTrue(math.isclose(value2, value, rel_tol=rel_tol), |
| 1558 | + (value, value2)) |
| 1559 | + else: |
| 1560 | + self.assertEqual(value2, value) |
| 1561 | + |
| 1562 | + |
1491 | 1563 | if __name__ == '__main__': |
1492 | 1564 | unittest.main() |
0 commit comments