Skip to content
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Minor cleanups of the core code
  • Loading branch information
mdickinson committed May 27, 2020
commit 48084e75790a44f36bc61ab3488e0d118e52c476
25 changes: 14 additions & 11 deletions Objects/longobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -5447,30 +5447,33 @@ static PyObject *
int_bit_count_impl(PyObject *self)
/*[clinic end generated code: output=2e571970daf1e5c3 input=a428900d3e39a606]*/
{
Comment thread
mdickinson marked this conversation as resolved.
Py_ssize_t ndigits, i, bit_count = 0;
PyLongObject *result, *x, *y;

assert(self != NULL);
assert(PyLong_Check(self));

ndigits = Py_ABS(Py_SIZE(self));
PyLongObject *z = (PyLongObject *)self;
Py_ssize_t ndigits = Py_ABS(Py_SIZE(self));
Py_ssize_t bit_count = 0;

for (i = 0; i < ndigits && i < PY_SSIZE_T_MAX/PyLong_SHIFT; i++) {
bit_count += popcount_digit(((PyLongObject *)self)->ob_digit[i]);
/* Each digit has up to PyLong_SHIFT ones, so the accumulated bit count
from the first PY_SSIZE_T_MAX/PyLong_SHIFT digits can't overflow a
Py_ssize_t. */

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice comment, thanks! Before the comment, I was surprised by the two loops.

Py_ssize_t ndigits_fast = Py_MIN(ndigits, PY_SSIZE_T_MAX/PyLong_SHIFT);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I proposed to work use size_t for bit_count, but then I realzied that i is a Py_ssize_t, so it's better to leave the code as it is: work on Py_ssize_t for i and bit_count.

for (Py_ssize_t i = 0; i < ndigits_fast; i++) {
bit_count += popcount_digit(z->ob_digit[i]);
}

result = (PyLongObject *)PyLong_FromSsize_t(bit_count);
PyObject *result = PyLong_FromSsize_t(bit_count);
if (result == NULL) {
return NULL;
Comment thread
niklasf marked this conversation as resolved.
}

/* Use Python integers if bit_count would overflow. */
for (; i < ndigits; i++) {
x = (PyLongObject *)PyLong_FromLong(popcount_digit(((PyLongObject *)self)->ob_digit[i]));
for (Py_ssize_t i = ndigits_fast; i < ndigits; i++) {
PyObject *x = PyLong_FromLong(popcount_digit(z->ob_digit[i]));
if (x == NULL) {
goto error;
}
y = (PyLongObject *)long_add(result, x);
PyObject *y = long_add((PyLongObject *)result, (PyLongObject *)x);
Py_DECREF(x);
if (y == NULL) {
goto error;
Expand All @@ -5479,7 +5482,7 @@ int_bit_count_impl(PyObject *self)
result = y;
}

return (PyObject *)result;
return result;

error:
Py_DECREF(result);
Expand Down