8000 BUG: fix incorrect output descriptor in fancy indexing by ngoldbaum · Pull Request #27715 · numpy/numpy · GitHub
[go: up one dir, main page]

Skip to content

BUG: fix incorrect output descriptor in fancy indexing #27715

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Nov 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
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
12 changes: 7 additions & 5 deletions numpy/_core/src/multiarray/mapping.c
Original file line number Diff line number Diff line change
Expand Up @@ -1668,7 +1668,7 @@ array_subscript(PyArrayObject *self, PyObject *op)

if (PyArray_GetDTypeTransferFunction(1,
itemsize, itemsize,
PyArray_DESCR(self), PyArray_DESCR(self),
PyArray_DESCR(self), PyArray_DESCR(mit->extra_op),
0, &cast_info, &transfer_flags) != NPY_SUCCEED) {
goto finish;
}
Expand Down Expand Up @@ -2035,7 +2035,6 @@ array_assign_subscript(PyArrayObject *self, PyObject *ind, PyObject *op)
goto fail;
}

int allocated_array = 0;
if (tmp_arr == NULL) {
/* Fill extra op, need to swap first */
tmp_arr = mit->extra_op;
Expand All @@ -2049,7 +2048,11 @@ array_assign_subscript(PyArrayObject *self, PyObject *ind, PyObject *op)
if (PyArray_CopyObject(tmp_arr, op) < 0) {
goto fail;
}
allocated_array = 1;
/*
* In this branch we copy directly from a newly allocated array which
* may have a new descr:
*/
descr = PyArray_DESCR(tmp_arr);
}

if (PyArray_MapIterCheckIndices(mit) < 0) {
Expand Down Expand Up @@ -2097,8 +2100,7 @@ array_assign_subscript(PyArrayObject *self, PyObject *ind, PyObject *op)
// for non-REFCHK user DTypes. See gh-27057 for the prior discussion about this.
if (PyArray_GetDTypeTransferFunction(
1, itemsize, itemsize,
allocated_array ? PyArray_DESCR(mit->extra_op) : PyArray_DESCR(self),
PyArray_DESCR(self),
descr, PyArray_DESCR(self),
0, &cast_info, &transfer_flags) != NPY_SUCCEED) {
goto fail;
}
Expand Down
6 changes: 4 additions & 2 deletions numpy/_core/src/multiarray/nditer_constr.c
Original file line number Diff line number Diff line change
Expand Up @@ -1315,8 +1315,10 @@ npyiter_check_casting(int nop, PyArrayObject **op,
printf("\n");
#endif
/* If the types aren't equivalent, a cast is necessary */
if (op[iop] != NULL && !PyArray_EquivTypes(PyArray_DESCR(op[iop]),
op_dtype[iop])) {
npy_intp view_offset = NPY_MIN_INTP;
if (op[iop] != NULL && !(PyArray_SafeCast(
PyArray_DESCR(op[iop]), op_dtype[iop], &view_offset,
NPY_NO_CASTING, 1) && view_offset == 0)) {
Copy link
Member

Choose a reason for hiding this comment

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

I do wonder if we should have a clear way to spell it (up to changing the meaning of PyArray_EquivTypes to match this and changing the use where we want the meaning that allows string_dtype1 == string_dtype2 where needed).

/* Check read (op -> temp) casting */
if ((op_itflags[iop] & NPY_OP_ITFLAG_READ) &&
!PyArray_CanCastArrayTo(op[iop],
Expand Down
23 changes: 19 additions & 4 deletions numpy/_core/tests/test_stringdtype.py
Original file line number Diff line number Diff line change
Expand Up @@ -495,15 +495,30 @@ def test_fancy_indexing(string_list):
sarr = np.array(string_list, dtype="T")
assert_array_equal(sarr, sarr[np.arange(sarr.shape[0])])

inds = [
[True, True],
[0, 1],
...,
np.array([0, 1], dtype='uint8'),
]

lops = [
['a'*25, 'b'*25],
['', ''],
['hello', 'world'],
['hello', 'world'*25],
]

# see gh-27003 and gh-27053
for ind in [[True, True], [0, 1], ...]:
for lop in [['a'*16, 'b'*16], ['', '']]:
for ind in inds:
for lop in lops:
a = np.array(lop, dtype="T")
rop = ['d'*16, 'e'*16]
assert_array_equal(a[ind], a)
rop = ['d'*25, 'e'*25]
for b in [rop, np.array(rop, dtype="T")]:
a[ind] = b
assert_array_equal(a, b)
assert a[0] == 'd'*16
assert a[0] == 'd'*25


def test_creation_functions():
Expand Down
Loading
0