diff options
author | Victor Stinner <vstinner@python.org> | 2020-06-08 14:30:33 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-06-08 14:30:33 (GMT) |
commit | c6b292cdeee689f0bfac6c1e2c2d4e4e01fa8d9e (patch) | |
tree | 4a7686465f3ed4a171382d4717ad558d82413951 /Modules/_testinternalcapi.c | |
parent | 301f0d4ff9b6bd60599eea0612904f65a92e6dd9 (diff) | |
download | cpython-c6b292cdeee689f0bfac6c1e2c2d4e4e01fa8d9e.zip cpython-c6b292cdeee689f0bfac6c1e2c2d4e4e01fa8d9e.tar.gz cpython-c6b292cdeee689f0bfac6c1e2c2d4e4e01fa8d9e.tar.bz2 |
bpo-29882: Add _Py_popcount32() function (GH-20518)
* Rename pycore_byteswap.h to pycore_bitutils.h.
* Move popcount_digit() to pycore_bitutils.h as _Py_popcount32().
* _Py_popcount32() uses GCC and clang builtin function if available.
* Add unit tests to _Py_popcount32().
Diffstat (limited to 'Modules/_testinternalcapi.c')
-rw-r--r-- | Modules/_testinternalcapi.c | 42 |
1 files changed, 41 insertions, 1 deletions
diff --git a/Modules/_testinternalcapi.c b/Modules/_testinternalcapi.c index 5f217dc..6d5af59 100644 --- a/Modules/_testinternalcapi.c +++ b/Modules/_testinternalcapi.c @@ -12,7 +12,7 @@ #define PY_SSIZE_T_CLEAN #include "Python.h" -#include "pycore_byteswap.h" // _Py_bswap32() +#include "pycore_bitutils.h" // _Py_bswap32() #include "pycore_initconfig.h" // _Py_GetConfigsAsDict() #include "pycore_hashtable.h" // _Py_hashtable_new() #include "pycore_gc.h" // PyGC_Head @@ -63,6 +63,45 @@ test_bswap(PyObject *self, PyObject *Py_UNUSED(args)) } +static int +check_popcount(uint32_t x, int expected) +{ + // Use volatile to prevent the compiler to optimize out the whole test + volatile uint32_t u = x; + int bits = _Py_popcount32(u); + if (bits != expected) { + PyErr_Format(PyExc_AssertionError, + "_Py_popcount32(%lu) returns %i, expected %i", + (unsigned long)x, bits, expected); + return -1; + } + return 0; +} + + +static PyObject* +test_popcount(PyObject *self, PyObject *Py_UNUSED(args)) +{ +#define CHECK(X, RESULT) \ + do { \ + if (check_popcount(X, RESULT) < 0) { \ + return NULL; \ + } \ + } while (0) + + CHECK(0, 0); + CHECK(1, 1); + CHECK(0x08080808, 4); + CHECK(0x10101010, 4); + CHECK(0x10204080, 4); + CHECK(0xDEADCAFE, 22); + CHECK(0xFFFFFFFF, 32); + Py_RETURN_NONE; + +#undef CHECK +} + + #define TO_PTR(ch) ((void*)(uintptr_t)ch) #define FROM_PTR(ptr) ((uintptr_t)ptr) #define VALUE(key) (1 + ((int)(key) - 'a')) @@ -157,6 +196,7 @@ static PyMethodDef TestMethods[] = { {"get_configs", get_configs, METH_NOARGS}, {"get_recursion_depth", get_recursion_depth, METH_NOARGS}, {"test_bswap", test_bswap, METH_NOARGS}, + {"test_popcount", test_popcount, METH_NOARGS}, {"test_hashtable", test_hashtable, METH_NOARGS}, {NULL, NULL} /* sentinel */ }; |