Skip to content
Open
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
9 changes: 5 additions & 4 deletions cupy/_core/_routines_indexing.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ from libcpp cimport vector

from cupy._core._carray cimport shape_t
from cupy._core._carray cimport strides_t
from cupy._core._dtype cimport _raise_if_invalid_cast
from cupy._core cimport core
from cupy._core cimport _routines_math as _math
from cupy._core cimport _routines_manipulation as _manipulation
Expand Down Expand Up @@ -576,13 +577,13 @@ out = a[out_i];
_take_kernel = ElementwiseKernel(
'raw T a, S indices, int64 ldim_, int64 cdim_, int64 rdim_, '
'int64 index_range_',
'T out', _take_kernel_core, 'cupy_take')
'U out', _take_kernel_core, 'cupy_take')


_take_kernel_scalar = ElementwiseKernel(
'raw T a, int64 indices, int64 ldim_, int64 cdim_, int64 rdim_, '
'int64 index_range_',
'T out', _take_kernel_core, 'cupy_take_scalar')
'U out', _take_kernel_core, 'cupy_take_scalar')


_choose_kernel = ElementwiseKernel(
Expand Down Expand Up @@ -881,8 +882,8 @@ cdef _ndarray_base _take(
if out is None:
out = core.ndarray(out_shape, dtype=a.dtype)
else:
if out.dtype != a.dtype:
raise TypeError('Output dtype mismatch')
_raise_if_invalid_cast(
a.dtype, out.dtype, 'same_kind', 'output operand')
if out.shape != out_shape:
raise ValueError('Output shape mismatch')
if a.size == 0 and out.size != 0:
Expand Down
41 changes: 29 additions & 12 deletions tests/cupy_tests/core_tests/test_ndarray.py
Original file line number Diff line number Diff line change
Expand Up @@ -507,22 +507,39 @@ def test_shape_mismatch(self):
{'shape': (3, 4, 5), 'indices': (2, 3), 'out_shape': (2, 3)},
{'shape': (), 'indices': (), 'out_shape': ()}
)
class TestNdarrayTakeErrorTypeMismatch(unittest.TestCase):
class TestNdarrayTakeTypeMismatch(unittest.TestCase):
# NOTE(seberg): Historically cupy was always fully restrictive
# while NumPy was just wrong: https://github.com/numpy/numpy/pull/30615
# As of CuPy 14.2, CuPy uses 2.5+ (future) behavior.

def test_output_type_mismatch(self):
@testing.with_requires('numpy>=2.5')
@testing.numpy_cupy_array_equal()
# incorrectly given by numpy (presumably until Deprecation is finalized)
@pytest.mark.filterwarnings('ignore::numpy.exceptions.ComplexWarning')
def test_output_dtype_same_kind_ok(self, xp):
# After NumPy 2.5, NumPy gets the cast safety right, the following
# is OK under same-kind casting rules.
a = testing.shaped_arange(self.shape, xp, numpy.int64)
i = testing.shaped_arange(self.indices, xp, numpy.int32) % 3
results = []
for out_dtype in (numpy.complex64, numpy.int32):
o = testing.shaped_arange(self.out_shape, xp, out_dtype)
results.append(wrap_take(a, i, out=o))
return results

@pytest.mark.filterwarnings(
'error:Implicit casting of output dtype:DeprecationWarning')
def test_output_dtype_unsafe_rejected(self):
for xp in (numpy, cupy):
a = testing.shaped_arange(self.shape, xp, numpy.int32)
a = testing.shaped_arange(self.shape, xp, numpy.float32)
i = testing.shaped_arange(self.indices, xp, numpy.int32) % 3
o = testing.shaped_arange(self.out_shape, xp, numpy.float32)
if (xp is numpy
and numpy.lib.NumpyVersion(numpy.__version__)
>= '2.5.0'):
# numpy>=2.5 permits safe casting of the take() out= dtype,
# so it no longer raises; cupy still enforces a match.
o = testing.shaped_arange(self.out_shape, xp, numpy.int32)
# As of NumPy 2.5 this is a deprecation warning, but CuPy never
# allowed it (so no deprecation required)
if xp is numpy and not testing.numpy_satisfies('>=2.5'):
continue
with pytest.raises((TypeError, DeprecationWarning)):
wrap_take(a, i, out=o)
else:
with pytest.raises(TypeError):
wrap_take(a, i, out=o)


@testing.parameterize(
Expand Down