Skip to content

Commit 105cb1a

Browse files
committed
add tests
1 parent 5e19676 commit 105cb1a

1 file changed

Lines changed: 42 additions & 10 deletions

File tree

Lib/test/test_capi/test_float.py

Lines changed: 42 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,21 @@
2929
NAN = float("nan")
3030

3131

32+
def make_nan(size, sign, quiet, payload):
33+
if size == 8:
34+
payload &= 0x7ffffffffffff
35+
i = (sign << 63) + (0x7ff << 52) + (quiet << 51) + payload
36+
elif size == 4:
37+
payload &= 0x3fffff
38+
i = (sign << 31) + (0xff << 23) + (quiet << 22) + payload
39+
elif size == 2:
40+
payload &= 0x1ff
41+
i = (sign << 15) + (0x1f << 10) + (quiet << 9) + payload
42+
else:
43+
raise ValueError("size must be either 2, 4, or 8")
44+
return i
45+
46+
3247
class CAPIFloatTest(unittest.TestCase):
3348
def test_check(self):
3449
# Test PyFloat_Check()
@@ -202,16 +217,8 @@ def test_pack_unpack_roundtrip_for_nans(self):
202217
# HP PA RISC uses 0 for quiet, see:
203218
# https://en.wikipedia.org/wiki/NaN#Encoding
204219
signaling = 1
205-
quiet = int(not signaling)
206-
if size == 8:
207-
payload = random.randint(signaling, 0x7ffffffffffff)
208-
i = (sign << 63) + (0x7ff << 52) + (quiet << 51) + payload
209-
elif size == 4:
210-
payload = random.randint(signaling, 0x3fffff)
211-
i = (sign << 31) + (0xff << 23) + (quiet << 22) + payload
212-
elif size == 2:
213-
payload = random.randint(signaling, 0x1ff)
214-
i = (sign << 15) + (0x1f << 10) + (quiet << 9) + payload
220+
payload = random.randint(signaling, 0xfffffffffffff)
221+
i = make_nan(size, sign, not signaling, payload)
215222
data = bytes.fromhex(f'{i:x}')
216223
for endian in (BIG_ENDIAN, LITTLE_ENDIAN):
217224
with self.subTest(data=data, size=size, endian=endian):
@@ -221,6 +228,31 @@ def test_pack_unpack_roundtrip_for_nans(self):
221228
self.assertTrue(math.isnan(value))
222229
self.assertEqual(data1, data2)
223230

231+
@unittest.skipUnless(HAVE_IEEE_754, "requires IEEE 754")
232+
def test_pack_unpack_nans_for_different_formats(self):
233+
pack = _testcapi.float_pack
234+
unpack = _testcapi.float_unpack
235+
236+
for endian in (BIG_ENDIAN, LITTLE_ENDIAN):
237+
with self.subTest(endian=endian):
238+
byteorder = "big" if endian == BIG_ENDIAN else "little"
239+
240+
# Convert sNaN to qNaN, if payload got truncated
241+
data = make_nan(8, 0, False, 0x80001).to_bytes(8, byteorder)
242+
snan_low = unpack(data, endian)
243+
qnan4 = make_nan(4, 0, True, 0).to_bytes(4, byteorder)
244+
qnan2 = make_nan(2, 0, True, 0).to_bytes(2, byteorder)
245+
self.assertEqual(pack(4, snan_low, endian), qnan4)
246+
self.assertEqual(pack(2, snan_low, endian), qnan2)
247+
248+
# Preserve NaN type, if payload not truncated
249+
data = make_nan(8, 0, False, 0x80000000001).to_bytes(8, byteorder)
250+
snan_high = unpack(data, endian)
251+
snan4 = make_nan(4, 0, False, 16384).to_bytes(4, byteorder)
252+
snan2 = make_nan(2, 0, False, 2).to_bytes(2, byteorder)
253+
self.assertEqual(pack(4, snan_high, endian), snan4)
254+
self.assertEqual(pack(2, snan_high, endian), snan2)
255+
224256

225257
if __name__ == "__main__":
226258
unittest.main()

0 commit comments

Comments
 (0)