|
10 | 10 |
|
11 | 11 | NULL = None
|
12 | 12 |
|
| 13 | + |
13 | 14 | class IntSubclass(int):
|
14 | 15 | pass
|
15 | 16 |
|
@@ -714,5 +715,95 @@ def test_long_asuint64(self):
|
714 | 715 | self.check_long_asint(as_uint64, 0, UINT64_MAX,
|
715 | 716 | negative_value_error=ValueError)
|
716 | 717 |
|
| 718 | + def test_long_layout(self): |
| 719 | + # Test PyLong_GetNativeLayout() |
| 720 | + int_info = sys.int_info |
| 721 | + layout = _testcapi.get_pylong_layout() |
| 722 | + expected = { |
| 723 | + 'bits_per_digit': int_info.bits_per_digit, |
| 724 | + 'digit_size': int_info.sizeof_digit, |
| 725 | + 'digits_order': -1, |
| 726 | + 'digit_endianness': -1 if sys.byteorder == 'little' else 1, |
| 727 | + } |
| 728 | + self.assertEqual(layout, expected) |
| 729 | + |
| 730 | + def test_long_export(self): |
| 731 | + # Test PyLong_Export() |
| 732 | + layout = _testcapi.get_pylong_layout() |
| 733 | + base = 2 ** layout['bits_per_digit'] |
| 734 | + |
| 735 | + pylong_export = _testcapi.pylong_export |
| 736 | + |
| 737 | + # value fits into int64_t |
| 738 | + self.assertEqual(pylong_export(0), 0) |
| 739 | + self.assertEqual(pylong_export(123), 123) |
| 740 | + self.assertEqual(pylong_export(-123), -123) |
| 741 | + self.assertEqual(pylong_export(IntSubclass(123)), 123) |
| 742 | + |
| 743 | + # use an array, doesn't fit into int64_t |
| 744 | + self.assertEqual(pylong_export(base**10 * 2 + 1), |
| 745 | + (0, [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2])) |
| 746 | + self.assertEqual(pylong_export(-(base**10 * 2 + 1)), |
| 747 | + (1, [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2])) |
| 748 | + self.assertEqual(pylong_export(IntSubclass(base**10 * 2 + 1)), |
| 749 | + (0, [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2])) |
| 750 | + |
| 751 | + self.assertRaises(TypeError, pylong_export, 1.0) |
| 752 | + self.assertRaises(TypeError, pylong_export, 0+1j) |
| 753 | + self.assertRaises(TypeError, pylong_export, "abc") |
| 754 | + |
| 755 | + def test_longwriter_create(self): |
| 756 | + # Test PyLongWriter_Create() |
| 757 | + layout = _testcapi.get_pylong_layout() |
| 758 | + base = 2 ** layout['bits_per_digit'] |
| 759 | + |
| 760 | + pylongwriter_create = _testcapi.pylongwriter_create |
| 761 | + self.assertRaises(ValueError, pylongwriter_create, 0, []) |
| 762 | + self.assertRaises(ValueError, pylongwriter_create, -123, []) |
| 763 | + self.assertEqual(pylongwriter_create(0, [0]), 0) |
| 764 | + self.assertEqual(pylongwriter_create(0, [123]), 123) |
| 765 | + self.assertEqual(pylongwriter_create(1, [123]), -123) |
| 766 | + self.assertEqual(pylongwriter_create(1, [1, 2]), |
| 767 | + -(base * 2 + 1)) |
| 768 | + self.assertEqual(pylongwriter_create(0, [1, 2, 3]), |
| 769 | + base**2 * 3 + base * 2 + 1) |
| 770 | + max_digit = base - 1 |
| 771 | + self.assertEqual(pylongwriter_create(0, [max_digit, max_digit, max_digit]), |
| 772 | + base**2 * max_digit + base * max_digit + max_digit) |
| 773 | + |
| 774 | + # normalize |
| 775 | + self.assertEqual(pylongwriter_create(0, [123, 0, 0]), 123) |
| 776 | + |
| 777 | + # test singletons + normalize |
| 778 | + for num in (-2, 0, 1, 5, 42, 100): |
| 779 | + self.assertIs(pylongwriter_create(bool(num < 0), [abs(num), 0]), |
| 780 | + num) |
| 781 | + |
| 782 | + def to_digits(num): |
| 783 | + digits = [] |
| 784 | + while True: |
| 785 | + num, digit = divmod(num, base) |
| 786 | + digits.append(digit) |
| 787 | + if not num: |
| 788 | + break |
| 789 | + return digits |
| 790 | + |
| 791 | + # round trip: Python int -> export -> Python int |
| 792 | + pylong_export = _testcapi.pylong_export |
| 793 | + numbers = [*range(0, 10), 12345, 0xdeadbeef, 2**100, 2**100-1] |
| 794 | + numbers.extend(-num for num in list(numbers)) |
| 795 | + for num in numbers: |
| 796 | + with self.subTest(num=num): |
| 797 | + data = pylong_export(num) |
| 798 | + if isinstance(data, tuple): |
| 799 | + negative, digits = data |
| 800 | + else: |
| 801 | + value = data |
| 802 | + negative = int(value < 0) |
| 803 | + digits = to_digits(abs(value)) |
| 804 | + self.assertEqual(pylongwriter_create(negative, digits), num, |
| 805 | + (negative, digits)) |
| 806 | + |
| 807 | + |
717 | 808 | if __name__ == "__main__":
|
718 | 809 | unittest.main()
|
0 commit comments