Skip to content
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ This release is compatible with NumPy 2.5.
* Fixed `dpnp.median` and `dpnp.nanmedian` raising a `ValueError` for a tuple `axis` when a kept dimension has size 0 [#3081](https://github.com/IntelPython/dpnp/pull/3081)
* Fixed a `RuntimeError` raised by `dpnp.tensor` kernels launched over more than `INT_MAX` work-items when built with DPC++ compiler 2026.2 or newer, by also passing `-fno-sycl-id-queries-fit-in-int` to the linker [#3089](https://github.com/IntelPython/dpnp/pull/3089)
* Fixed `dpnp.__all__` missing `ndarray` and `__array_namespace_info__` and listing `mean`, `median` and `min` twice [#3100](https://github.com/IntelPython/dpnp/pull/3100)
* Fixed `dpnp.repeat` and `dpnp.tensor.repeat` silently returning wrong results for `uint64` repeats above the `int64` maximum [#3115](https://github.com/IntelPython/dpnp/pull/3115)

### Security

Expand Down
10 changes: 7 additions & 3 deletions dpnp/tensor/_manipulation_functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -638,8 +638,12 @@ def repeat(x, repeats, /, *, axis=None):
if not dpt.can_cast(repeats.dtype, dpt.int64, casting="same_kind"):
Comment thread
vlad-perevezentsev marked this conversation as resolved.
raise TypeError(
f"'repeats' data type {repeats.dtype} cannot be cast to "
"'int64' according to the casting rule ''safe.''"
"'int64' according to the casting rule ''same_kind.''"
)
err_msg = "`repeats` elements must be positive"
if repeats.dtype == dpt.uint64:
Comment thread
antonwolfy marked this conversation as resolved.
repeats = dpt.astype(repeats, dpt.int64)
err_msg = "`repeats` elements must not exceed the int64 maximum"
if repeats.size == 1:
scalar = True
# bring the single element to the host
Expand All @@ -650,15 +654,15 @@ def repeat(x, repeats, /, *, axis=None):
# since non-0D arrays can not be converted to scalars
repeats = int(repeats[0])
if repeats < 0:
raise ValueError("`repeats` elements must be positive")
raise ValueError(err_msg)
else:
if repeats.size != axis_size:
raise ValueError(
"'repeats' array must be broadcastable to the size of "
"the repeated axis"
)
if not dpt.all(repeats >= 0):
raise ValueError("'repeats' elements must be positive")
raise ValueError(err_msg)

elif isinstance(repeats, (tuple, list, range)):
usm_type = x.usm_type
Expand Down
8 changes: 8 additions & 0 deletions dpnp/tests/tensor/test_usm_ndarray_manipulation.py
Original file line number Diff line number Diff line change
Expand Up @@ -1509,6 +1509,14 @@ def test_repeat_arg_validation():
with pytest.raises(ValueError):
dpt.repeat(x, reps)

# u8 repeats above i8 max
reps = dpt.asarray(2**64 - 1, dtype="u8")
with pytest.raises(ValueError, match="int64 maximum"):
dpt.repeat(x, reps)
reps = dpt.asarray([1, 1, 2**64 - 1, 1, 1], dtype="u8")
with pytest.raises(ValueError, match="int64 maximum"):
dpt.repeat(x, reps)

# repeats must broadcastable to axis size
reps = dpt.arange(10, dtype="i8")
with pytest.raises(ValueError):
Expand Down
Loading