@@ -12,7 +12,7 @@
1212#definePY_SSIZE_T_CLEAN
13131414#include"Python.h"
15-#include"pycore_byteswap.h"// _Py_bswap32()
15+#include"pycore_bitutils.h"// _Py_bswap32()
1616#include"pycore_initconfig.h"// _Py_GetConfigsAsDict()
1717#include"pycore_hashtable.h"// _Py_hashtable_new()
1818#include"pycore_gc.h"// PyGC_Head
@@ -63,6 +63,45 @@ test_bswap(PyObject *self, PyObject *Py_UNUSED(args))
6363}
6464656566+staticint
67+check_popcount(uint32_tx, intexpected)
68+{
69+// Use volatile to prevent the compiler to optimize out the whole test
70+volatileuint32_tu=x;
71+intbits=_Py_popcount32(u);
72+if (bits!=expected) {
73+PyErr_Format(PyExc_AssertionError,
74+"_Py_popcount32(%lu) returns %i, expected %i",
75+ (unsigned long)x, bits, expected);
76+return-1;
77+ }
78+return0;
79+}
80+81+82+staticPyObject*
83+test_popcount(PyObject*self, PyObject*Py_UNUSED(args))
84+{
85+#defineCHECK(X, RESULT) \
86+ do { \
87+ if (check_popcount(X, RESULT) < 0) { \
88+ return NULL; \
89+ } \
90+ } while (0)
91+92+CHECK(0, 0);
93+CHECK(1, 1);
94+CHECK(0x08080808, 4);
95+CHECK(0x10101010, 4);
96+CHECK(0x10204080, 4);
97+CHECK(0xDEADCAFE, 22);
98+CHECK(0xFFFFFFFF, 32);
99+Py_RETURN_NONE;
100+101+#undef CHECK
102+}
103+104+66105#defineTO_PTR(ch) ((void*)(uintptr_t)ch)
67106#defineFROM_PTR(ptr) ((uintptr_t)ptr)
68107#defineVALUE(key) (1 + ((int)(key) - 'a'))
@@ -157,6 +196,7 @@ static PyMethodDef TestMethods[] = {
157196 {"get_configs", get_configs, METH_NOARGS},
158197 {"get_recursion_depth", get_recursion_depth, METH_NOARGS},
159198 {"test_bswap", test_bswap, METH_NOARGS},
199+ {"test_popcount", test_popcount, METH_NOARGS},
160200 {"test_hashtable", test_hashtable, METH_NOARGS},
161201 {NULL, NULL} /* sentinel */
162202};