summaryrefslogtreecommitdiffstats
path: root/Modules
diff options
context:
space:
mode:
authorVictor Stinner <vstinner@python.org>2020-06-08 14:30:33 (GMT)
committerGitHub <noreply@github.com>2020-06-08 14:30:33 (GMT)
commitc6b292cdeee689f0bfac6c1e2c2d4e4e01fa8d9e (patch)
tree4a7686465f3ed4a171382d4717ad558d82413951 /Modules
parent301f0d4ff9b6bd60599eea0612904f65a92e6dd9 (diff)
downloadcpython-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')
-rw-r--r--Modules/_ctypes/cfield.c2
-rw-r--r--Modules/_testinternalcapi.c42
-rw-r--r--Modules/sha256module.c2
-rw-r--r--Modules/sha512module.c2
4 files changed, 44 insertions, 4 deletions
diff --git a/Modules/_ctypes/cfield.c b/Modules/_ctypes/cfield.c
index 32a2bee..3a9b711 100644
--- a/Modules/_ctypes/cfield.c
+++ b/Modules/_ctypes/cfield.c
@@ -1,5 +1,5 @@
#include "Python.h"
-#include "pycore_byteswap.h" // _Py_bswap32()
+#include "pycore_bitutils.h" // _Py_bswap32()
#include <ffi.h>
#ifdef MS_WIN32
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 */
};
diff --git a/Modules/sha256module.c b/Modules/sha256module.c
index 8edb1d5..261f9da 100644
--- a/Modules/sha256module.c
+++ b/Modules/sha256module.c
@@ -17,7 +17,7 @@
/* SHA objects */
#include "Python.h"
-#include "pycore_byteswap.h" // _Py_bswap32()
+#include "pycore_bitutils.h" // _Py_bswap32()
#include "structmember.h" // PyMemberDef
#include "hashlib.h"
#include "pystrhex.h"
diff --git a/Modules/sha512module.c b/Modules/sha512module.c
index 561ef8e..aa2aeed 100644
--- a/Modules/sha512module.c
+++ b/Modules/sha512module.c
@@ -17,7 +17,7 @@
/* SHA objects */
#include "Python.h"
-#include "pycore_byteswap.h" // _Py_bswap32()
+#include "pycore_bitutils.h" // _Py_bswap32()
#include "structmember.h" // PyMemberDef
#include "hashlib.h"
#include "pystrhex.h"