|
| 1 | +import math |
1 | 2 | import sys |
2 | 3 | import unittest |
3 | 4 | from test.support import import_helper |
@@ -77,3 +78,46 @@ def python_hash_pointer(x): |
77 | 78 | # Py_HashPointer((void*)(uintptr_t)-1) doesn't return -1 but -2 |
78 | 79 | VOID_P_MAX = -1 & (2 ** (8 * SIZEOF_VOID_P) - 1) |
79 | 80 | self.assertEqual(hash_pointer(VOID_P_MAX), -2) |
| 81 | + |
| 82 | + def test_hash_double(self): |
| 83 | + # Test Py_HashDouble() |
| 84 | + hash_double = _testcapi.hash_double |
| 85 | + |
| 86 | + def check_number(value, expected): |
| 87 | + self.assertEqual(hash_double(value), (1, expected)) |
| 88 | + |
| 89 | + # test some integers |
| 90 | + integers = [ |
| 91 | + *range(1, 30), |
| 92 | + 2**30 - 1, |
| 93 | + 2 ** 233, |
| 94 | + int(sys.float_info.max), |
| 95 | + ] |
| 96 | + for x in integers: |
| 97 | + with self.subTest(x=x): |
| 98 | + check_number(float(x), hash(x)) |
| 99 | + check_number(float(-x), hash(-x)) |
| 100 | + |
| 101 | + # test positive and negative zeros |
| 102 | + check_number(float(0.0), 0) |
| 103 | + check_number(float(-0.0), 0) |
| 104 | + |
| 105 | + # test +inf and -inf |
| 106 | + inf = float("inf") |
| 107 | + check_number(inf, sys.hash_info.inf) |
| 108 | + check_number(-inf, -sys.hash_info.inf) |
| 109 | + |
| 110 | + # special float values: compare with Python hash() function |
| 111 | + special_values = ( |
| 112 | + math.nextafter(0.0, 1.0), # smallest positive subnormal number |
| 113 | + sys.float_info.min, # smallest positive normal number |
| 114 | + sys.float_info.epsilon, |
| 115 | + sys.float_info.max, # largest positive finite number |
| 116 | + ) |
| 117 | + for x in special_values: |
| 118 | + with self.subTest(x=x): |
| 119 | + check_number(x, hash(x)) |
| 120 | + check_number(-x, hash(-x)) |
| 121 | + |
| 122 | + # test not-a-number (NaN) |
| 123 | + self.assertEqual(hash_double(float('nan')), (0, sys.hash_info.nan)) |
0 commit comments