From f0b01446d2cd5fe1ff97e535fc145e4cbbbb1cca Mon Sep 17 00:00:00 2001 From: Vladislav Perevezentsev Date: Mon, 8 Jun 2026 04:55:15 -0700 Subject: [PATCH 1/5] Update dpt.broadcast_arrays to return a tuple --- dpnp/tensor/_manipulation_functions.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dpnp/tensor/_manipulation_functions.py b/dpnp/tensor/_manipulation_functions.py index 7347f62de115..4b7e2d131465 100644 --- a/dpnp/tensor/_manipulation_functions.py +++ b/dpnp/tensor/_manipulation_functions.py @@ -228,8 +228,8 @@ def broadcast_arrays(*args): broadcasted. Returns: - List[usm_ndarray]: - A list of broadcasted arrays. Each array + tuple[usm_ndarray, ...]: + A tuple of broadcasted arrays. Each array must have the same shape. Each array must have the same `dtype`, `device` and `usm_type` attributes as its corresponding input array. @@ -245,7 +245,7 @@ def broadcast_arrays(*args): if all(X.shape == shape for X in args): return args - return [broadcast_to(X, shape) for X in args] + return tuple(broadcast_to(X, shape) for X in args) def broadcast_to(X, /, shape): From 5e8ba63a7f68437959242ad2e1e1e6e0e1199116 Mon Sep 17 00:00:00 2001 From: Vladislav Perevezentsev Date: Mon, 8 Jun 2026 04:55:57 -0700 Subject: [PATCH 2/5] Update dpnp.broadcast_arrays to return a tuple --- dpnp/dpnp_iface_manipulation.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/dpnp/dpnp_iface_manipulation.py b/dpnp/dpnp_iface_manipulation.py index b96d36a40e6a..32d3742bf7b8 100644 --- a/dpnp/dpnp_iface_manipulation.py +++ b/dpnp/dpnp_iface_manipulation.py @@ -1060,8 +1060,8 @@ def broadcast_arrays(*args, subok=False): Returns ------- - out : list of dpnp.ndarray - A list of arrays which are views on the original arrays from `args`. + out : tuple of dpnp.ndarray + A tuple of arrays which are views on the original arrays from `args`. Limitations ----------- @@ -1078,9 +1078,9 @@ def broadcast_arrays(*args, subok=False): >>> x = np.array([[1, 2, 3]]) >>> y = np.array([[4], [5]]) >>> np.broadcast_arrays(x, y) - [array([[1, 2, 3], + (array([[1, 2, 3], [1, 2, 3]]), array([[4, 4, 4], - [5, 5, 5]])] + [5, 5, 5]])) """ @@ -1088,10 +1088,10 @@ def broadcast_arrays(*args, subok=False): raise NotImplementedError(f"subok={subok} is currently not supported") if len(args) == 0: - return [] + return () usm_arrays = dpt.broadcast_arrays(*[dpnp.get_usm_ndarray(a) for a in args]) - return [dpnp_array._create_from_usm_ndarray(a) for a in usm_arrays] + return tuple(dpnp_array._create_from_usm_ndarray(a) for a in usm_arrays) def broadcast_shapes(*args): From 2af8b5d8bd419d42c7e4d2d431eb2a113b03fda7 Mon Sep 17 00:00:00 2001 From: Vladislav Perevezentsev Date: Mon, 8 Jun 2026 04:56:38 -0700 Subject: [PATCH 3/5] Update test_broadcast_arrays_empty_input --- dpnp/tests/test_arraymanipulation.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dpnp/tests/test_arraymanipulation.py b/dpnp/tests/test_arraymanipulation.py index 25c454b97613..7ef31eac7034 100644 --- a/dpnp/tests/test_arraymanipulation.py +++ b/dpnp/tests/test_arraymanipulation.py @@ -289,7 +289,7 @@ def test_incompatible_shapes_raise_valueerror(self, shapes): self.assert_broadcast_arrays_raise(input_shapes[::-1]) def test_broadcast_arrays_empty_input(self): - assert dpnp.broadcast_arrays() == [] + assert dpnp.broadcast_arrays() == () def test_subok_error(self): x = dpnp.ones(4) From 826ee780cca2210bde2db71dd797a100886beeb7 Mon Sep 17 00:00:00 2001 From: Vladislav Perevezentsev Date: Mon, 8 Jun 2026 05:09:43 -0700 Subject: [PATCH 4/5] Update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4472233701e2..2a6129a8f80e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,7 @@ This release is compatible with NumPy 2.4.5. * Replaced `.pxi` includes in `dpnp.tensor` with modular `.pxd`/`.pyx` Cython imports [#2913](https://github.com/IntelPython/dpnp/pull/2913) * Reimplemented `dpnp.eye` and `dpnp.tensor.eye` with a branchless kernel [gh-2937](https://github.com/IntelPython/dpnp/pull/2937) * Cleaned up Python bindings for indexing functions, renaming `usm_ndarray_take` and `usm_ndarray_put` to `py_take` and `py_put` and refactoring validation [gh-2935](https://github.com/IntelPython/dpnp/pull/2935) +* Changed `dpnp.broadcast_arrays` and `dpnp.tensor.broadcast_arrays` to return a tuple instead of a list, aligning with NumPy 2.x behavior and 2025.12 version of the Python array API standard [#2944](https://github.com/IntelPython/dpnp/pull/2944) ### Deprecated From 3d7f9a7a478083c68eea7bd0f65bdd3bd2d02c79 Mon Sep 17 00:00:00 2001 From: Vladislav Perevezentsev Date: Fri, 24 Jul 2026 04:28:11 -0700 Subject: [PATCH 5/5] Apply remarks --- CHANGELOG.md | 2 +- dpnp/tests/tensor/test_usm_ndarray_manipulation.py | 8 ++++++++ dpnp/tests/test_arraymanipulation.py | 4 ++++ .../third_party/cupy/manipulation_tests/test_dims.py | 4 ++++ 4 files changed, 17 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ca5235dad12c..93ff8ceb29a6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -37,7 +37,7 @@ This release is compatible with NumPy 2.5. * Aligned the signature of `dpnp.tensor.expand_dims` with the Python array API by making `axis` a required argument [#2988](https://github.com/IntelPython/dpnp/pull/2988) * Removed dead code branches guarded by outdated oneMKL and DPC++ compiler version checks [#2999](https://github.com/IntelPython/dpnp/pull/2999) * Replaced the deprecated `nd_item::barrier()` member calls in the `accumulators` and `gemm` kernels with the SYCL 2020 `sycl::group_barrier()` free function [#3006](https://github.com/IntelPython/dpnp/pull/3006) -* Changed `dpnp.broadcast_arrays` and `dpnp.tensor.broadcast_arrays` to return a tuple instead of a list, aligning with NumPy 2.x behavior and 2025.12 version of the Python array API standard [#2944](https://github.com/IntelPython/dpnp/pull/2944) +* Changed `dpnp.broadcast_arrays` and `dpnp.tensor.broadcast_arrays` to return a tuple instead of a list, aligning with the 2025.12 Python array API spec [#2944](https://github.com/IntelPython/dpnp/pull/2944) ### Deprecated diff --git a/dpnp/tests/tensor/test_usm_ndarray_manipulation.py b/dpnp/tests/tensor/test_usm_ndarray_manipulation.py index bb0a99a537ff..3f45506c4082 100644 --- a/dpnp/tests/tensor/test_usm_ndarray_manipulation.py +++ b/dpnp/tests/tensor/test_usm_ndarray_manipulation.py @@ -464,6 +464,14 @@ def test_incompatible_shapes_raise_valueerror(shapes): assert_broadcast_arrays_raise(input_shapes[::-1]) +def test_broadcast_arrays_tuple(): + q = get_queue_or_skip() + out = dpt.broadcast_arrays( + dpt.ones((1, 3), sycl_queue=q), dpt.zeros((3, 1), sycl_queue=q) + ) + assert isinstance(out, tuple) + + def test_broadcast_arrays_no_args(): with pytest.raises(ValueError): dpt.broadcast_arrays() diff --git a/dpnp/tests/test_arraymanipulation.py b/dpnp/tests/test_arraymanipulation.py index fd34dc7a3032..f54740031d6c 100644 --- a/dpnp/tests/test_arraymanipulation.py +++ b/dpnp/tests/test_arraymanipulation.py @@ -294,6 +294,10 @@ def test_incompatible_shapes_raise_valueerror(self, shapes): self.assert_broadcast_arrays_raise(input_shapes) self.assert_broadcast_arrays_raise(input_shapes[::-1]) + def test_broadcast_arrays_tuple(self): + out = dpnp.broadcast_arrays(dpnp.ones((1, 3)), dpnp.zeros((3, 1))) + assert isinstance(out, tuple) + def test_broadcast_arrays_empty_input(self): assert dpnp.broadcast_arrays() == () diff --git a/dpnp/tests/third_party/cupy/manipulation_tests/test_dims.py b/dpnp/tests/third_party/cupy/manipulation_tests/test_dims.py index ae0f6ce18b47..8790d4cbcc6a 100644 --- a/dpnp/tests/third_party/cupy/manipulation_tests/test_dims.py +++ b/dpnp/tests/third_party/cupy/manipulation_tests/test_dims.py @@ -315,6 +315,10 @@ def test_broadcast_arrays(self, xp, dtype): arrays = [testing.shaped_arange(s, xp, dtype) for s in self.shapes] return xp.broadcast_arrays(*arrays) + def test_broadcast_arrays_tuple(self): + out = cupy.broadcast_arrays(cupy.ones(3), cupy.zeros(3)) + assert isinstance(out, tuple) + @testing.parameterize( {"shapes": [(3,), (2,)]},