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 @@ -77,6 +77,7 @@ This release is compatible with NumPy 2.5.
* Fixed `dpnp.interp` with an empty input array `x` to return an empty array with the correct dtype [#2985](https://github.com/IntelPython/dpnp/pull/2985)
* Fixed `dpnp.interp` returning `nan` when querying at an exact knot point whose adjacent `fp` value is `inf` [#2986](https://github.com/IntelPython/dpnp/pull/2986)
* Fixed missing strides validation in `dpnp.tensor.usm_ndarray` constructor when allocating new memory [#2927](https://github.com/IntelPython/dpnp/pull/2927)
* Fixed `dpnp.bincount` raising a `ValueError` on an empty input array instead of returning an empty `intp` array [#3018](https://github.com/IntelPython/dpnp/pull/3018)

### Security

Expand Down
4 changes: 4 additions & 0 deletions dpnp/dpnp_iface_histograms.py
Original file line number Diff line number Diff line change
Expand Up @@ -374,6 +374,10 @@ def bincount(x, weights=None, minlength=0):
queue = x.sycl_queue
device = queue.sycl_device

if x.size == 0:
# NumPy returns intp dtype for empty input even when weights is given
return dpnp.zeros_like(x, shape=int(minlength), dtype=dpnp.intp)

if weights is None:
ntype = dpnp.dtype(dpnp.intp)
else:
Expand Down
19 changes: 19 additions & 0 deletions dpnp/tests/third_party/cupy/statistics_tests/test_histogram.py
Original file line number Diff line number Diff line change
Expand Up @@ -339,6 +339,25 @@ def test_bincount_too_small_minlength(self, dtype):
with pytest.raises((ValueError, TypeError)):
xp.bincount(x, minlength=-1)

@for_all_dtypes_bincount()
@testing.numpy_cupy_allclose(accept_error=TypeError)
def test_bincount_empty(self, xp, dtype):
x = xp.array([], dtype=dtype)
return xp.bincount(x)

@for_all_dtypes_bincount()
@testing.numpy_cupy_allclose(accept_error=TypeError)
def test_bincount_empty_with_minlength(self, xp, dtype):
x = xp.array([], dtype=dtype)
return xp.bincount(x, minlength=2)

@for_all_dtypes_combination_bincount(names=["x_type", "w_type"])
@testing.numpy_cupy_allclose(accept_error=TypeError)
def test_bincount_empty_with_weight(self, xp, x_type, w_type):
x = xp.array([], dtype=x_type)
w = xp.array([], dtype=w_type)
return xp.bincount(x, weights=w, minlength=2)


# This class compares CUB results against NumPy's
@unittest.skipUnless(False, "The CUB routine is not enabled")
Expand Down
27 changes: 17 additions & 10 deletions dpnp/tests/third_party/cupy/testing/_loops.py
Original file line number Diff line number Diff line change
Expand Up @@ -991,6 +991,16 @@ def test_func(*args, **kw):
return decorator


def _dtype_supported_by_default_device(dtype):
"""Skip dtypes the default device cannot represent natively."""
dtype = numpy.dtype(dtype).type
if dtype in (numpy.float64, numpy.complex128):
return has_support_aspect64()
if dtype == numpy.float16:
return select_default_device().has_aspect_fp16
return True


def for_dtypes(dtypes, name="dtype", xfail_dtypes=None):
"""Decorator for parameterized dtype test.

Expand All @@ -1008,16 +1018,7 @@ def decorator(impl):
@_wraps_partial(impl, name)
def test_func(*args, **kw):
for dtype in dtypes:
if (
numpy.dtype(dtype).type in (numpy.float64, numpy.complex128)
and not has_support_aspect64()
):
continue

if (
numpy.dtype(dtype).type == numpy.float16
and not select_default_device().has_aspect_fp16
):
if not _dtype_supported_by_default_device(dtype):
continue

try:
Expand Down Expand Up @@ -1331,6 +1332,12 @@ def decorator(impl):
@_wraps_partial(impl, *names)
def test_func(*args, **kw):
for dtypes in combination:
if not all(
_dtype_supported_by_default_device(dtype)
for dtype in dtypes.values()
):
continue

kw_copy = kw.copy()
kw_copy.update(dtypes)

Expand Down
Loading