Skip to content

Commit

Permalink
Merge pull request #19347 from charris/backport-19276
Browse files Browse the repository at this point in the history
BUG: Fix arr.flat.index for large arrays and big-endian machines
  • Loading branch information
charris committed Jun 25, 2021
2 parents a093bbb + dc5ec98 commit b5e4172
Show file tree
Hide file tree
Showing 5 changed files with 38 additions and 53 deletions.
6 changes: 1 addition & 5 deletions numpy/core/src/multiarray/conversion_utils.c
Expand Up @@ -1222,11 +1222,7 @@ PyArray_IntTupleFromIntp(int len, npy_intp const *vals)
goto fail;
}
for (i = 0; i < len; i++) {
#if NPY_SIZEOF_INTP <= NPY_SIZEOF_LONG
PyObject *o = PyLong_FromLong((long) vals[i]);
#else
PyObject *o = PyLong_FromLongLong((npy_longlong) vals[i]);
#endif
PyObject *o = PyArray_PyIntFromIntp(vals[i]);
if (!o) {
Py_DECREF(intTuple);
intTuple = NULL;
Expand Down
11 changes: 11 additions & 0 deletions numpy/core/src/multiarray/conversion_utils.h
Expand Up @@ -39,6 +39,17 @@ PyArray_IntpFromSequence(PyObject *seq, npy_intp *vals, int maxvals);
NPY_NO_EXPORT int
PyArray_TypestrConvert(int itemsize, int gentype);


static NPY_INLINE PyObject *
PyArray_PyIntFromIntp(npy_intp const value)
{
#if NPY_SIZEOF_INTP <= NPY_SIZEOF_LONG
return PyLong_FromLong((long)value);
#else
return PyLong_FromLongLong((npy_longlong)value);
#endif
}

NPY_NO_EXPORT PyObject *
PyArray_IntTupleFromIntp(int len, npy_intp const *vals);

Expand Down
24 changes: 2 additions & 22 deletions numpy/core/src/multiarray/getset.c
Expand Up @@ -419,33 +419,13 @@ array_itemsize_get(PyArrayObject *self)
static PyObject *
array_size_get(PyArrayObject *self)
{
npy_intp size=PyArray_SIZE(self);
#if NPY_SIZEOF_INTP <= NPY_SIZEOF_LONG
return PyLong_FromLong((long) size);
#else
if (size > NPY_MAX_LONG || size < NPY_MIN_LONG) {
return PyLong_FromLongLong(size);
}
else {
return PyLong_FromLong((long) size);
}
#endif
return PyArray_PyIntFromIntp(PyArray_SIZE(self));
}

static PyObject *
array_nbytes_get(PyArrayObject *self)
{
npy_intp nbytes = PyArray_NBYTES(self);
#if NPY_SIZEOF_INTP <= NPY_SIZEOF_LONG
return PyLong_FromLong((long) nbytes);
#else
if (nbytes > NPY_MAX_LONG || nbytes < NPY_MIN_LONG) {
return PyLong_FromLongLong(nbytes);
}
else {
return PyLong_FromLong((long) nbytes);
}
#endif
return PyArray_PyIntFromIntp(PyArray_NBYTES(self));
}


Expand Down
39 changes: 13 additions & 26 deletions numpy/core/src/multiarray/iterators.c
Expand Up @@ -15,6 +15,7 @@
#include "iterators.h"
#include "ctors.h"
#include "common.h"
#include "conversion_utils.h"
#include "array_coercion.h"

#define NEWAXIS_INDEX -1
Expand Down Expand Up @@ -1062,13 +1063,15 @@ static PyMemberDef iter_members[] = {
T_OBJECT,
offsetof(PyArrayIterObject, ao),
READONLY, NULL},
{"index",
T_INT,
offsetof(PyArrayIterObject, index),
READONLY, NULL},
{NULL, 0, 0, 0, NULL},
};

static PyObject *
iter_index_get(PyArrayIterObject *self)
{
return PyArray_PyIntFromIntp(self->index);
}

static PyObject *
iter_coords_get(PyArrayIterObject *self)
{
Expand All @@ -1095,10 +1098,12 @@ iter_coords_get(PyArrayIterObject *self)
}

static PyGetSetDef iter_getsets[] = {
{"index",
(getter)iter_index_get,
NULL, NULL, NULL},
{"coords",
(getter)iter_coords_get,
NULL,
NULL, NULL},
NULL, NULL, NULL},
{NULL, NULL, NULL, NULL, NULL},
};

Expand Down Expand Up @@ -1410,31 +1415,13 @@ arraymultiter_dealloc(PyArrayMultiIterObject *multi)
static PyObject *
arraymultiter_size_get(PyArrayMultiIterObject *self)
{
#if NPY_SIZEOF_INTP <= NPY_SIZEOF_LONG
return PyLong_FromLong((long) self->size);
#else
if (self->size < NPY_MAX_LONG) {
return PyLong_FromLong((long) self->size);
}
else {
return PyLong_FromLongLong((npy_longlong) self->size);
}
#endif
return PyArray_PyIntFromIntp(self->size);
}

static PyObject *
arraymultiter_index_get(PyArrayMultiIterObject *self)
{
#if NPY_SIZEOF_INTP <= NPY_SIZEOF_LONG
return PyLong_FromLong((long) self->index);
#else
if (self->size < NPY_MAX_LONG) {
return PyLong_FromLong((long) self->index);
}
else {
return PyLong_FromLongLong((npy_longlong) self->index);
}
#endif
return PyArray_PyIntFromIntp(self->index);
}

static PyObject *
Expand Down
11 changes: 11 additions & 0 deletions numpy/core/tests/test_multiarray.py
Expand Up @@ -5364,6 +5364,17 @@ def test_refcount(self):
assert_(abs(sys.getrefcount(ind) - rc_ind) < 50)
assert_(abs(sys.getrefcount(indtype) - rc_indtype) < 50)

def test_index_getset(self):
it = np.arange(10).reshape(2, 1, 5).flat
with pytest.raises(AttributeError):
it.index = 10

for _ in it:
pass
# Check the value of `.index` is updated correctly (see also gh-19153)
# If the type was incorrect, this would show up on big-endian machines
assert it.index == it.base.size


class TestResize:

Expand Down

0 comments on commit b5e4172

Please sign in to comment.