From 3b0fa4c90fc3a4dd2813e459a98a029e0c07a88c Mon Sep 17 00:00:00 2001 From: Anton Volkov Date: Wed, 5 Mar 2025 11:53:35 +0100 Subject: [PATCH 01/11] Add uint64 as supported sample type --- .../extensions/statistics/bincount.cpp | 21 ++++++++++++------- .../extensions/statistics/bincount.hpp | 8 +++---- 2 files changed, 17 insertions(+), 12 deletions(-) diff --git a/dpnp/backend/extensions/statistics/bincount.cpp b/dpnp/backend/extensions/statistics/bincount.cpp index 71a37ba055e4..fa5a3c8cf80c 100644 --- a/dpnp/backend/extensions/statistics/bincount.cpp +++ b/dpnp/backend/extensions/statistics/bincount.cpp @@ -72,7 +72,7 @@ struct BincountEdges template bool in_bounds(const dT *val, const boundsT &bounds) const { - return check_in_bounds(val[0], std::get<0>(bounds), + return check_in_bounds(static_cast(val[0]), std::get<0>(bounds), std::get<1>(bounds)); } @@ -81,13 +81,15 @@ struct BincountEdges T max; }; -template +using DefaultHistType = int64_t; + +template struct BincountF { static sycl::event impl(sycl::queue &exec_q, const void *vin, - const int64_t min, - const int64_t max, + const uint64_t min, + const uint64_t max, const void *vweights, void *vout, const size_t, @@ -145,9 +147,12 @@ struct BincountF } }; -using SupportedTypes = std::tuple, +using SupportedTypes = std::tuple, + std::tuple, std::tuple, - std::tuple>; + std::tuple, + std::tuple, + std::tuple>; } // namespace @@ -158,8 +163,8 @@ Bincount::Bincount() : dispatch_table("sample", "histogram") std::tuple Bincount::call( const dpctl::tensor::usm_ndarray &sample, - const int64_t min, - const int64_t max, + const uint64_t min, + const uint64_t max, const std::optional &weights, dpctl::tensor::usm_ndarray &histogram, const std::vector &depends) diff --git a/dpnp/backend/extensions/statistics/bincount.hpp b/dpnp/backend/extensions/statistics/bincount.hpp index ab36e290674e..598e1fdbd397 100644 --- a/dpnp/backend/extensions/statistics/bincount.hpp +++ b/dpnp/backend/extensions/statistics/bincount.hpp @@ -39,8 +39,8 @@ struct Bincount { using FnT = sycl::event (*)(sycl::queue &, const void *, - const int64_t, - const int64_t, + const uint64_t, + const uint64_t, const void *, void *, const size_t, @@ -53,8 +53,8 @@ struct Bincount std::tuple call(const dpctl::tensor::usm_ndarray &input, - const int64_t min, - const int64_t max, + const uint64_t min, + const uint64_t max, const std::optional &weights, dpctl::tensor::usm_ndarray &output, const std::vector &depends); From 870583146337f6c92f901554eeccc36ac9354627 Mon Sep 17 00:00:00 2001 From: Anton Volkov Date: Wed, 5 Mar 2025 11:55:32 +0100 Subject: [PATCH 02/11] Add an alias on default histogram dtype --- .../extensions/statistics/histogram.cpp | 45 ++++++++++--------- 1 file changed, 24 insertions(+), 21 deletions(-) diff --git a/dpnp/backend/extensions/statistics/histogram.cpp b/dpnp/backend/extensions/statistics/histogram.cpp index b8f0d90467b8..1ee0d818a620 100644 --- a/dpnp/backend/extensions/statistics/histogram.cpp +++ b/dpnp/backend/extensions/statistics/histogram.cpp @@ -106,7 +106,9 @@ using CachedEdges = HistogramEdges>; template using UncachedEdges = HistogramEdges>; -template +using DefaultHistType = int64_t; + +template struct HistogramF { static sycl::event impl(sycl::queue &exec_q, @@ -186,26 +188,27 @@ using HistogramF_ = HistogramF; } // namespace -using SupportedTypes = std::tuple, - std::tuple, - std::tuple, - std::tuple, - std::tuple, - std::tuple, - std::tuple>, - std::tuple>, - std::tuple>, - std::tuple>, - std::tuple, - std::tuple, - std::tuple, - std::tuple, - std::tuple>, - std::tuple>, - std::tuple, int64_t>, - std::tuple, int64_t>, - std::tuple, float>, - std::tuple, double>>; +using SupportedTypes = + std::tuple, + std::tuple, + std::tuple, + std::tuple, + std::tuple, + std::tuple, + std::tuple>, + std::tuple>, + std::tuple>, + std::tuple>, + std::tuple, + std::tuple, + std::tuple, + std::tuple, + std::tuple>, + std::tuple>, + std::tuple, DefaultHistType>, + std::tuple, DefaultHistType>, + std::tuple, float>, + std::tuple, double>>; Histogram::Histogram() : dispatch_table("sample", "histogram") { From 3ae94c302cd1c37b82f0260dd77b9f8b3586c84f Mon Sep 17 00:00:00 2001 From: Anton Volkov Date: Wed, 5 Mar 2025 11:57:15 +0100 Subject: [PATCH 03/11] Explicitly copy max/min values to the host memory --- dpnp/dpnp_iface_histograms.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dpnp/dpnp_iface_histograms.py b/dpnp/dpnp_iface_histograms.py index 8f5975c074fe..51832671eabf 100644 --- a/dpnp/dpnp_iface_histograms.py +++ b/dpnp/dpnp_iface_histograms.py @@ -293,8 +293,8 @@ def _bincount_run_native( mem_ev, bc_ev = statistics_ext.bincount( x_usm, - min_v, - max_v, + min_v.item(), + max_v.item(), weights_usm, n_usm, depends=_manager.submitted_events, From 3f0e79ce79df1d1bce2447bc0759f7754de309b6 Mon Sep 17 00:00:00 2001 From: Anton Volkov Date: Wed, 5 Mar 2025 12:00:39 +0100 Subject: [PATCH 04/11] No need to print function name while raising ValueError exception --- dpnp/dpnp_iface_histograms.py | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/dpnp/dpnp_iface_histograms.py b/dpnp/dpnp_iface_histograms.py index 51832671eabf..dc78b41eece7 100644 --- a/dpnp/dpnp_iface_histograms.py +++ b/dpnp/dpnp_iface_histograms.py @@ -391,10 +391,8 @@ def bincount(x, weights=None, minlength=0): if x_casted_dtype is None or ntype_casted is None: # pragma: no cover raise ValueError( - f"function '{bincount}' does not support input types " - f"({x.dtype}, {ntype}), " - "and the inputs could not be coerced to any " - "supported types" + f"Input types ({x.dtype}, {ntype}) are not supported, " + "and the inputs could not be coerced to any supported types" ) x_casted = dpnp.asarray(x, dtype=x_casted_dtype, order="C") @@ -611,9 +609,8 @@ def histogram(a, bins=10, range=None, density=None, weights=None): if a_bin_dtype is None or hist_dtype is None: # pragma: no cover raise ValueError( - f"function '{histogram}' does not support input types " - f"({a.dtype}, {bin_edges.dtype}, {ntype}), " - "and the inputs could not be coerced to any " + f"Input types ({a.dtype}, {bin_edges.dtype}, {ntype}) " + "are not supported, and the inputs could not be coerced to any " "supported types" ) From cc0e3658e3e11012566e9900b5cae8de287f24e8 Mon Sep 17 00:00:00 2001 From: Anton Volkov Date: Wed, 5 Mar 2025 12:05:05 +0100 Subject: [PATCH 05/11] Remove unused argument passing to bincount callback --- dpnp/backend/extensions/statistics/bincount.cpp | 7 +++---- dpnp/backend/extensions/statistics/bincount.hpp | 1 - 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/dpnp/backend/extensions/statistics/bincount.cpp b/dpnp/backend/extensions/statistics/bincount.cpp index fa5a3c8cf80c..14b94297be22 100644 --- a/dpnp/backend/extensions/statistics/bincount.cpp +++ b/dpnp/backend/extensions/statistics/bincount.cpp @@ -92,7 +92,6 @@ struct BincountF const uint64_t max, const void *vweights, void *vout, - const size_t, const size_t size, const std::vector &depends) { @@ -186,9 +185,9 @@ std::tuple Bincount::call( void *weights_ptr = weights.has_value() ? weights.value().get_data() : nullptr; - auto ev = bincount_func(exec_q, sample.get_data(), min, max, weights_ptr, - histogram.get_data(), histogram.get_shape(0), - sample.get_shape(0), depends); + auto ev = + bincount_func(exec_q, sample.get_data(), min, max, weights_ptr, + histogram.get_data(), histogram.get_size(), depends); sycl::event args_ev; if (weights.has_value()) { diff --git a/dpnp/backend/extensions/statistics/bincount.hpp b/dpnp/backend/extensions/statistics/bincount.hpp index 598e1fdbd397..ec65c5399e7e 100644 --- a/dpnp/backend/extensions/statistics/bincount.hpp +++ b/dpnp/backend/extensions/statistics/bincount.hpp @@ -44,7 +44,6 @@ struct Bincount const void *, void *, const size_t, - const size_t, const std::vector &); common::DispatchTable2 dispatch_table; From c41d72881236f57d37c910d5b3c85d71ba0e3083 Mon Sep 17 00:00:00 2001 From: Anton Volkov Date: Wed, 5 Mar 2025 12:16:25 +0100 Subject: [PATCH 06/11] Add a sysynchronization warning to docstring of histogram-like functions --- dpnp/dpnp_iface_histograms.py | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/dpnp/dpnp_iface_histograms.py b/dpnp/dpnp_iface_histograms.py index dc78b41eece7..fc19d05bac0c 100644 --- a/dpnp/dpnp_iface_histograms.py +++ b/dpnp/dpnp_iface_histograms.py @@ -313,6 +313,11 @@ def bincount(x, weights=None, minlength=0): For full documentation refer to :obj:`numpy.bincount`. + Warning + ------- + This function synchronizes in order to calculate binning edges. + This may harm performance in some applications. + Parameters ---------- x : {dpnp.ndarray, usm_ndarray} @@ -506,6 +511,11 @@ def histogram(a, bins=10, range=None, density=None, weights=None): For full documentation refer to :obj:`numpy.histogram`. + Warning + ------- + This function may synchronize in order to check a monotonically increasing + array of bin edges. This may harm performance in some applications. + Parameters ---------- a : {dpnp.ndarray, usm_ndarray} @@ -672,6 +682,11 @@ def histogram_bin_edges(a, bins=10, range=None, weights=None): For full documentation refer to :obj:`numpy.histogram_bin_edges`. + Warning + ------- + This function may synchronize in order to check a monotonically increasing + array of bin edges. This may harm performance in some applications. + Parameters ---------- a : {dpnp.ndarray, usm_ndarray} @@ -757,6 +772,13 @@ def histogram2d(x, y, bins=10, range=None, density=None, weights=None): """ Compute the bi-dimensional histogram of two data samples. + For full documentation refer to :obj:`numpy.histogram2d`. + + Warning + ------- + This function may synchronize in order to check a monotonically increasing + array of bin edges. This may harm performance in some applications. + Parameters ---------- x : {dpnp.ndarray, usm_ndarray} of shape (N,) @@ -1085,6 +1107,11 @@ def histogramdd(sample, bins=10, range=None, density=None, weights=None): For full documentation refer to :obj:`numpy.histogramdd`. + Warning + ------- + This function may synchronize in order to check a monotonically increasing + array of bin edges. This may harm performance in some applications. + Parameters ---------- sample : {dpnp.ndarray, usm_ndarray} From 2945b532a1d8427e56857155eaaac19844e06a18 Mon Sep 17 00:00:00 2001 From: Anton Volkov Date: Wed, 5 Mar 2025 12:36:37 +0100 Subject: [PATCH 07/11] Needs to pass a size of sample (no histogram) into bincount callback --- dpnp/backend/extensions/statistics/bincount.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/dpnp/backend/extensions/statistics/bincount.cpp b/dpnp/backend/extensions/statistics/bincount.cpp index 14b94297be22..79dafc6ec5d9 100644 --- a/dpnp/backend/extensions/statistics/bincount.cpp +++ b/dpnp/backend/extensions/statistics/bincount.cpp @@ -185,9 +185,8 @@ std::tuple Bincount::call( void *weights_ptr = weights.has_value() ? weights.value().get_data() : nullptr; - auto ev = - bincount_func(exec_q, sample.get_data(), min, max, weights_ptr, - histogram.get_data(), histogram.get_size(), depends); + auto ev = bincount_func(exec_q, sample.get_data(), min, max, weights_ptr, + histogram.get_data(), sample.get_size(), depends); sycl::event args_ev; if (weights.has_value()) { From 4c861480b7eafadae1e6207f62660632bafc93cd Mon Sep 17 00:00:00 2001 From: Anton Volkov Date: Wed, 5 Mar 2025 12:47:23 +0100 Subject: [PATCH 08/11] Add latest chnages to histogram third party tests --- .../cupy/statistics_tests/test_histogram.py | 106 +++++++++++++++++- 1 file changed, 102 insertions(+), 4 deletions(-) diff --git a/dpnp/tests/third_party/cupy/statistics_tests/test_histogram.py b/dpnp/tests/third_party/cupy/statistics_tests/test_histogram.py index 16f96417ab3c..7090bb660691 100644 --- a/dpnp/tests/third_party/cupy/statistics_tests/test_histogram.py +++ b/dpnp/tests/third_party/cupy/statistics_tests/test_histogram.py @@ -337,9 +337,107 @@ def test_bincount_too_small_minlength(self, dtype): xp.bincount(x, minlength=-1) -# TODO(leofang): we temporarily remove CUB histogram support for now, -# see cupy/cupy#7698. When it's ready, revert the commit that checked -# in this comment to restore the support. +# This class compares CUB results against NumPy's +@unittest.skipUnless(False, "The CUB routine is not enabled") +class TestCubHistogram(unittest.TestCase): + + def setUp(self): + self.old_accelerators = _accelerator.get_routine_accelerators() + _accelerator.set_routine_accelerators(["cub"]) + + def tearDown(self): + _accelerator.set_routine_accelerators(self.old_accelerators) + + @testing.for_all_dtypes(no_bool=True, no_complex=True) + @testing.numpy_cupy_array_equal() + def test_histogram(self, xp, dtype): + x = testing.shaped_arange((10,), xp, dtype) + + if xp is numpy: + return xp.histogram(x) + + # xp is cupy, first ensure we really use CUB + cub_func = "cupy._statistics.histogram.cub.device_histogram" + with testing.AssertFunctionIsCalled(cub_func): + xp.histogram(x) + # ...then perform the actual computation + return xp.histogram(x) + + @testing.for_all_dtypes(no_bool=True, no_complex=True) + @testing.numpy_cupy_array_equal() + def test_histogram_range_float(self, xp, dtype): + a = testing.shaped_arange((10,), xp, dtype) + h, b = xp.histogram(a, testing.shaped_arange((10,), xp, numpy.float64)) + assert int(h.sum()) == 10 + return h, b + + @testing.for_all_dtypes_combination( + ["dtype_a", "dtype_b"], no_bool=True, no_complex=True + ) + @testing.numpy_cupy_array_equal() + def test_histogram_with_bins(self, xp, dtype_a, dtype_b): + x = testing.shaped_arange((10,), xp, dtype_a) + bins = testing.shaped_arange((4,), xp, dtype_b) + + if xp is numpy: + return xp.histogram(x, bins)[0] + + # xp is cupy, first ensure we really use CUB + cub_func = "cupy._statistics.histogram.cub.device_histogram" + with testing.AssertFunctionIsCalled(cub_func): + xp.histogram(x, bins) + # ...then perform the actual computation + return xp.histogram(x, bins)[0] + + @testing.for_all_dtypes_combination( + ["dtype_a", "dtype_b"], no_bool=True, no_complex=True + ) + @testing.numpy_cupy_array_equal() + def test_histogram_with_bins2(self, xp, dtype_a, dtype_b): + x = testing.shaped_arange((10,), xp, dtype_a) + bins = testing.shaped_arange((4,), xp, dtype_b) + + if xp is numpy: + return xp.histogram(x, bins)[1] + + # xp is cupy, first ensure we really use CUB + cub_func = "cupy._statistics.histogram.cub.device_histogram" + with testing.AssertFunctionIsCalled(cub_func): + xp.histogram(x, bins) + # ...then perform the actual computation + return xp.histogram(x, bins)[1] + + @testing.slow + @testing.numpy_cupy_array_equal() + def test_no_oom(self, xp): + # ensure the workaround for NVIDIA/cub#613 kicks in + amax = 28854312 + A = xp.linspace( + 0, amax, num=amax, endpoint=True, retstep=False, dtype=xp.int32 + ) + out = xp.histogram(A, bins=amax, range=[0, amax]) + return out + + @testing.for_int_dtypes("dtype", no_bool=True) + @testing.numpy_cupy_array_equal() + def test_bincount_gh7698(self, xp, dtype): + dtype = xp.dtype(dtype) + max_val = xp.iinfo(dtype).max if dtype.itemsize < 4 else 65536 + if dtype == xp.uint64: + pytest.skip("only numpy raises exception on uint64 input") + + # https://github.com/cupy/cupy/issues/7698 + x = xp.arange(max_val, dtype=dtype) + + if xp is numpy: + return xp.bincount(x) + + # xp is cupy, first ensure we really use CUB + cub_func = "cupy._statistics.histogram.cub.device_histogram" + with testing.AssertFunctionIsCalled(cub_func): + xp.bincount(x) + # ...then perform the actual computation + return xp.bincount(x) @testing.parameterize( @@ -560,7 +658,7 @@ def test_histogramdd_disallow_arraylike_bins(self): *testing.product( { "weights": [None, 1, 2], - "weights_dtype": [numpy.int32, numpy.float32], + "weights_dtype": [numpy.int32, cupy.default_float_type()], "density": [True, False], "bins": [10, (8, 16), (16, 8), "array_list", "array"], "range": [None, ((20, 50), (10, 100))], From 0579afa71181fcb717f57dd8e0a1c58dd7f4e195 Mon Sep 17 00:00:00 2001 From: Anton Volkov Date: Wed, 5 Mar 2025 12:54:32 +0100 Subject: [PATCH 09/11] Add testing bincount with uint64 since numpy 2.2.4 --- .../third_party/cupy/statistics_tests/test_histogram.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/dpnp/tests/third_party/cupy/statistics_tests/test_histogram.py b/dpnp/tests/third_party/cupy/statistics_tests/test_histogram.py index 7090bb660691..fbc22032aba2 100644 --- a/dpnp/tests/third_party/cupy/statistics_tests/test_histogram.py +++ b/dpnp/tests/third_party/cupy/statistics_tests/test_histogram.py @@ -9,7 +9,7 @@ from dpnp.tests.third_party.cupy import testing # Note that numpy.bincount does not support uint64 on 64-bit environment -# as it casts an input array to intp. +# as it casts an input array to intp (planned to support since 2.2.4). # And it does not support uint32, int64 and uint64 on 32-bit environment. _all_types = ( numpy.float16, @@ -28,6 +28,9 @@ _all_types = _all_types + (numpy.int64, numpy.uint32) _signed_types = _signed_types + (numpy.int64,) +if numpy_version() > "2.2.3": + _all_types = _all_types + (numpy.uint64,) + def for_all_dtypes_bincount(name="dtype"): return testing.for_dtypes(_all_types, name=name) From a50c806fed1ad53ea2453acd4dc00d874804b56f Mon Sep 17 00:00:00 2001 From: Anton Volkov Date: Wed, 5 Mar 2025 13:54:55 +0100 Subject: [PATCH 10/11] Update bincount tests --- dpnp/tests/test_histogram.py | 94 +++++++++++++++++++----------------- 1 file changed, 50 insertions(+), 44 deletions(-) diff --git a/dpnp/tests/test_histogram.py b/dpnp/tests/test_histogram.py index 4b7155073f02..cca696bde25f 100644 --- a/dpnp/tests/test_histogram.py +++ b/dpnp/tests/test_histogram.py @@ -12,8 +12,11 @@ from .helper import ( assert_dtype_allclose, + generate_random_numpy_array, get_abs_array, get_all_dtypes, + get_complex_dtypes, + get_float_complex_dtypes, get_float_dtypes, get_integer_dtypes, has_support_aspect64, @@ -532,34 +535,29 @@ def test_range(self, range, dtype): class TestBincount: - @pytest.mark.parametrize("dtype", get_integer_dtypes()) - def test_rand_data(self, dtype): - n = 100 - upper_bound = 10 if dtype != dpnp.bool_ else 1 - v = numpy.random.randint(0, upper_bound, size=n, dtype=dtype) + @pytest.mark.parametrize("dt", get_integer_dtypes() + [numpy.bool_]) + def test_rand_data(self, dt): + v = generate_random_numpy_array(100, dtype=dt, low=0) iv = dpnp.array(v) - if numpy.issubdtype(dtype, numpy.uint64): - # discussed in numpy issue 17760 - assert_raises(TypeError, numpy.bincount, v) - assert_raises(ValueError, dpnp.bincount, iv) - else: - expected_hist = numpy.bincount(v) - result_hist = dpnp.bincount(iv) - assert_array_equal(result_hist, expected_hist) + if numpy.issubdtype(dt, numpy.uint64) and numpy_version() < "2.2.4": + v = v.astype(numpy.int64) - @pytest.mark.parametrize("dtype", get_integer_dtypes()) - def test_arange_data(self, dtype): - v = numpy.arange(100).astype(dtype) + expected_hist = numpy.bincount(v) + result_hist = dpnp.bincount(iv) + assert_array_equal(result_hist, expected_hist) + + @pytest.mark.parametrize("dt", get_integer_dtypes()) + def test_arange_data(self, dt): + v = numpy.arange(100, dtype=dt) iv = dpnp.array(v) - if numpy.issubdtype(dtype, numpy.uint64): - assert_raises(TypeError, numpy.bincount, v) - assert_raises(ValueError, dpnp.bincount, iv) - else: - expected_hist = numpy.bincount(v) - result_hist = dpnp.bincount(iv) - assert_array_equal(result_hist, expected_hist) + if numpy.issubdtype(dt, numpy.uint64) and numpy_version() < "2.2.4": + v = v.astype(numpy.int64) + + expected_hist = numpy.bincount(v) + result_hist = dpnp.bincount(iv) + assert_array_equal(result_hist, expected_hist) @pytest.mark.parametrize("xp", [numpy, dpnp]) def test_negative_values(self, xp): @@ -581,11 +579,17 @@ def test_weights_another_sycl_queue(self): dpnp.bincount(v, weights=w) @pytest.mark.parametrize("xp", [numpy, dpnp]) - def test_weights_unsupported_dtype(self, xp): - v = dpnp.arange(5) - w = dpnp.arange(5, dtype=dpnp.complex64) - with assert_raises(ValueError): - dpnp.bincount(v, weights=w) + @pytest.mark.parametrize("dt", get_float_complex_dtypes()) + def test_data_unsupported_dtype(self, xp, dt): + v = xp.arange(5, dtype=dt) + assert_raises(TypeError, xp.bincount, v) + + @pytest.mark.parametrize("xp", [numpy, dpnp]) + @pytest.mark.parametrize("dt", get_complex_dtypes()) + def test_weights_unsupported_dtype(self, xp, dt): + v = xp.arange(5) + w = xp.arange(5, dtype=dt) + assert_raises((TypeError, ValueError), xp.bincount, v, weights=w) @pytest.mark.parametrize( "bins_count", @@ -606,11 +610,11 @@ def test_different_bins_amount(self, bins_count): ) @pytest.mark.parametrize("minlength", [0, 1, 3, 5]) def test_minlength(self, array, minlength): - np_a = numpy.array(array) - dpnp_a = dpnp.array(array) + a = numpy.array(array) + ia = dpnp.array(a) - expected = numpy.bincount(np_a, minlength=minlength) - result = dpnp.bincount(dpnp_a, minlength=minlength) + expected = numpy.bincount(a, minlength=minlength) + result = dpnp.bincount(ia, minlength=minlength) assert_allclose(result, expected) @pytest.mark.filterwarnings("ignore::DeprecationWarning") @@ -639,21 +643,23 @@ def test_minlength_none(self, xp): ) @pytest.mark.parametrize( - "array", [[1, 2, 2, 1, 2, 4]], ids=["[1, 2, 2, 1, 2, 4]"] + "weights", + [None, [0.3, 0.5, 0, 0.7, 1.0, -0.6], [2, 2, 2, 2, 2, 2]], + ids=["None", "float_data", "int_data"], ) @pytest.mark.parametrize( - "weights", - [None, [0.3, 0.5, 0.2, 0.7, 1.0, -0.6], [2, 2, 2, 2, 2, 2]], - ids=["None", "[0.3, 0.5, 0.2, 0.7, 1., -0.6]", "[2, 2, 2, 2, 2, 2]"], + "dt", get_all_dtypes(no_none=True, no_complex=True) ) - def test_weights(self, array, weights): - np_a = numpy.array(array) - np_weights = numpy.array(weights) if weights is not None else weights - dpnp_a = dpnp.array(array) - dpnp_weights = dpnp.array(weights) if weights is not None else weights - - expected = numpy.bincount(np_a, weights=np_weights) - result = dpnp.bincount(dpnp_a, weights=dpnp_weights) + def test_weights(self, weights, dt): + a = numpy.array([1, 2, 2, 1, 2, 4]) + ia = dpnp.array(a) + w = iw = None + if weights is not None: + w = numpy.array(weights, dtype=dt) + iw = dpnp.array(w) + + expected = numpy.bincount(a, weights=w) + result = dpnp.bincount(ia, weights=iw) assert_allclose(result, expected) @pytest.mark.parametrize( From 543eb9a267d32eb625b73f505681520f5d4766d8 Mon Sep 17 00:00:00 2001 From: Anton Volkov Date: Wed, 5 Mar 2025 14:07:07 +0100 Subject: [PATCH 11/11] Add an entry to the changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e22f568bda97..e7f38a6c5753 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed +* Allowed input array of `uint64` dtype in `dpnp.bincount` [#2361](https://github.com/IntelPython/dpnp/pull/2361) + ### Fixed