diff options
author | Sergey B Kirpichev <skirpichev@gmail.com> | 2023-11-07 11:40:58 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-11-07 11:40:58 (GMT) |
commit | a077b2fbb88f5192bb47e514334f760bf08d0295 (patch) | |
tree | 24b0e3ee605ea6d5006d3118f6848d905ee44ff3 /Lib/test/test_capi/test_float.py | |
parent | 931f4438c92ec0eb2aa894092a91749f1d5bd216 (diff) | |
download | cpython-a077b2fbb88f5192bb47e514334f760bf08d0295.zip cpython-a077b2fbb88f5192bb47e514334f760bf08d0295.tar.gz cpython-a077b2fbb88f5192bb47e514334f760bf08d0295.tar.bz2 |
gh-111765: Move old PyFloat_* tests to Lib/test/test_capi/test_float.py (GH-111766)
Diffstat (limited to 'Lib/test/test_capi/test_float.py')
-rw-r--r-- | Lib/test/test_capi/test_float.py | 65 |
1 files changed, 65 insertions, 0 deletions
diff --git a/Lib/test/test_capi/test_float.py b/Lib/test/test_capi/test_float.py index 95635e8..cb94d56 100644 --- a/Lib/test/test_capi/test_float.py +++ b/Lib/test/test_capi/test_float.py @@ -12,6 +12,19 @@ _testcapi = import_helper.import_module('_testcapi') NULL = None +# For PyFloat_Pack/Unpack* +BIG_ENDIAN = 0 +LITTLE_ENDIAN = 1 +EPSILON = { + 2: 2.0 ** -11, # binary16 + 4: 2.0 ** -24, # binary32 + 8: 2.0 ** -53, # binary64 +} + +HAVE_IEEE_754 = float.__getformat__("double").startswith("IEEE") +INF = float("inf") +NAN = float("nan") + class CAPIFloatTest(unittest.TestCase): def test_check(self): @@ -112,6 +125,58 @@ class CAPIFloatTest(unittest.TestCase): self.assertEqual(getmin(), sys.float_info.min) + def test_pack(self): + # Test PyFloat_Pack2(), PyFloat_Pack4() and PyFloat_Pack8() + pack = _testcapi.float_pack + + self.assertEqual(pack(2, 1.5, BIG_ENDIAN), b'>\x00') + self.assertEqual(pack(4, 1.5, BIG_ENDIAN), b'?\xc0\x00\x00') + self.assertEqual(pack(8, 1.5, BIG_ENDIAN), + b'?\xf8\x00\x00\x00\x00\x00\x00') + self.assertEqual(pack(2, 1.5, LITTLE_ENDIAN), b'\x00>') + self.assertEqual(pack(4, 1.5, LITTLE_ENDIAN), b'\x00\x00\xc0?') + self.assertEqual(pack(8, 1.5, LITTLE_ENDIAN), + b'\x00\x00\x00\x00\x00\x00\xf8?') + + def test_unpack(self): + # Test PyFloat_Unpack2(), PyFloat_Unpack4() and PyFloat_Unpack8() + unpack = _testcapi.float_unpack + + self.assertEqual(unpack(b'>\x00', BIG_ENDIAN), 1.5) + self.assertEqual(unpack(b'?\xc0\x00\x00', BIG_ENDIAN), 1.5) + self.assertEqual(unpack(b'?\xf8\x00\x00\x00\x00\x00\x00', BIG_ENDIAN), + 1.5) + self.assertEqual(unpack(b'\x00>', LITTLE_ENDIAN), 1.5) + self.assertEqual(unpack(b'\x00\x00\xc0?', LITTLE_ENDIAN), 1.5) + self.assertEqual(unpack(b'\x00\x00\x00\x00\x00\x00\xf8?', LITTLE_ENDIAN), + 1.5) + + def test_pack_unpack_roundtrip(self): + pack = _testcapi.float_pack + unpack = _testcapi.float_unpack + + 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 = pack(size, value, endian) + value2 = unpack(data, endian) + if math.isnan(value): + self.assertTrue(math.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() |