From ab72dfc0afd7cd1c198945cbf3684ea1ffbf85d8 Mon Sep 17 00:00:00 2001 From: Ganesh Kathiresan Date: Sat, 3 Jul 2021 08:28:24 +0530 Subject: [PATCH] ENH: Object loop for `bit_count` [2/2] `popcount` object loop changes --- numpy/__init__.pyi | 2 +- numpy/core/code_generators/generate_umath.py | 1 + numpy/core/src/umath/funcs.inc.src | 32 ++++++++++++++++++++ 3 files changed, 34 insertions(+), 1 deletion(-) diff --git a/numpy/__init__.pyi b/numpy/__init__.pyi index ef8aa16eb4ea..f4e9d16baad7 100644 --- a/numpy/__init__.pyi +++ b/numpy/__init__.pyi @@ -3537,7 +3537,7 @@ arcsinh: _UFunc_Nin1_Nout1[L['arcsinh'], L[8], None] arctan2: _UFunc_Nin2_Nout1[L['arctan2'], L[5], None] arctan: _UFunc_Nin1_Nout1[L['arctan'], L[8], None] arctanh: _UFunc_Nin1_Nout1[L['arctanh'], L[8], None] -bit_count: _UFunc_Nin1_Nout1[L['bit_count'], L[10], None] +bit_count: _UFunc_Nin1_Nout1[L['bit_count'], L[11], None] bitwise_and: _UFunc_Nin2_Nout1[L['bitwise_and'], L[12], L[-1]] bitwise_not: _UFunc_Nin1_Nout1[L['invert'], L[12], None] bitwise_or: _UFunc_Nin2_Nout1[L['bitwise_or'], L[12], L[0]] diff --git a/numpy/core/code_generators/generate_umath.py b/numpy/core/code_generators/generate_umath.py index 513fe2b801db..dd9d93d167c7 100644 --- a/numpy/core/code_generators/generate_umath.py +++ b/numpy/core/code_generators/generate_umath.py @@ -960,6 +960,7 @@ def english_upper(s): docstrings.get('numpy.core.umath.bit_count'), None, TD(ints), + TD('O', f='npy_ObjectPopCount'), ), 'matmul' : Ufunc(2, 1, None, diff --git a/numpy/core/src/umath/funcs.inc.src b/numpy/core/src/umath/funcs.inc.src index 9b04dc77912e..387d4a8626db 100644 --- a/numpy/core/src/umath/funcs.inc.src +++ b/numpy/core/src/umath/funcs.inc.src @@ -267,6 +267,38 @@ npy_ObjectClip(PyObject *arr, PyObject *min, PyObject *max) { return o; } +static PyObject * +npy_ObjectPopCount(PyObject *obj) { + PyObject *result; + + /* Try to use inbuilt popcount if available */ + { + static PyObject *builtin_popcount_func = NULL; + + builtin_popcount_func = PyObject_GetAttrString(obj, "bit_count"); + if (builtin_popcount_func != NULL) { + result = PyObject_CallFunction(builtin_popcount_func, NULL); + return result; + } + /* silence errors, and fall back on pure-python `bit_count` */ + PyErr_Clear(); + } + + /* Otherwise, use our internal one, written in python */ + { + static PyObject *internal_popcount_func = NULL; + + npy_cache_import("numpy.core._internal", "_bit_count", &internal_popcount_func); + if (internal_popcount_func == NULL) { + return NULL; + } + + result = PyObject_CallFunction(internal_popcount_func, "O", obj); + + return result; + } +} + /* ***************************************************************************** ** COMPLEX FUNCTIONS **