Skip to content
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
This release is compatible with NumPy 2.4.5.

### Added
* Added `dpnp.broadcast` class implementation [#2901](https://github.com/IntelPython/dpnp/pull/2901)

Comment thread
antonwolfy marked this conversation as resolved.
Outdated
* Added C API functions for `dpnp.tensor.usm_ndarray` setters and getters to avoid ABI breakage if `dpnp.tensor.usm_ndarray` is modified [gh-2866](https://github.com/IntelPython/dpnp/pull/2866)
* Added support for buffer protocol objects as advanced index keys in `dpnp.ndarray` [#2889](https://github.com/IntelPython/dpnp/pull/2889)
Expand Down
2 changes: 2 additions & 0 deletions dpnp/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,7 @@
unravel_index,
)
from .dpnp_flatiter import flatiter
from .dpnp_broadcast import broadcast

# -----------------------------------------------------------------------------
# Linear algebra
Expand Down Expand Up @@ -691,6 +692,7 @@
"atleast_1d",
"atleast_2d",
"atleast_3d",
"broadcast",
"broadcast_arrays",
"broadcast_to",
"column_stack",
Expand Down
171 changes: 171 additions & 0 deletions dpnp/dpnp_broadcast.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
# *****************************************************************************
# Copyright (c) 2026, Intel Corporation
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# - Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# - Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
# - Neither the name of the copyright holder nor the names of its contributors
# may be used to endorse or promote products derived from this software
# without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
# THE POSSIBILITY OF SUCH DAMAGE.
# *****************************************************************************

"""Implementation of broadcast class."""

import dpnp
from dpnp.tensor._manipulation_functions import _broadcast_shapes


class broadcast:
Comment thread
antonwolfy marked this conversation as resolved.
Outdated
"""
Produce an object that mimics broadcasting.

For full documentation refer to :obj:`numpy.broadcast`.

Parameters
----------
*args : {dpnp.ndarray, usm_ndarray}
Input arrays to broadcast against one another.

Returns
-------
broadcast : broadcast object
Broadcast the input parameters against one another, and
return an object that encapsulates the result.
Amongst others, it has ``shape`` and ``nd`` properties.

See Also
--------
:obj:`dpnp.broadcast_arrays` : Broadcast any number of arrays against
Comment thread
antonwolfy marked this conversation as resolved.
Outdated
each other.
:obj:`dpnp.broadcast_to` : Broadcast an array to a new shape.
:obj:`dpnp.broadcast_shapes` : Broadcast the input shapes into a single
shape.

Examples
--------
>>> import dpnp as np
>>> x = np.array([[1], [2], [3]])
>>> y = np.array([4, 5, 6])
>>> b = np.broadcast(x, y)
>>> b.shape
(3, 3)
>>> b.nd
2
>>> b.size
9

Limitations
Comment thread
antonwolfy marked this conversation as resolved.
Outdated
-----------
Input arrays are not coerced, so array-like objects and scalars are not
supported and ``TypeError`` exception will be raised.

Notes
-----
Iterator functionality is not supported.

"""

def __init__(self, *args):
dpnp.check_supported_arrays_type(*args)

self._arrays = tuple(args)

if len(self._arrays) == 0:
self._shape = ()
self._size = 1
self._nd = 0
return

# Compute the broadcasted shape using _broadcast_shapes
self._shape = _broadcast_shapes(*self._arrays)

# Calculate size and ndim
self._size = 1
for dim in self._shape:
self._size *= dim
Comment thread
antonwolfy marked this conversation as resolved.
Outdated
self._nd = len(self._shape)

@property
Comment thread
antonwolfy marked this conversation as resolved.
Outdated
def shape(self):
"""
Shape of the broadcasted result.

Returns
-------
out : tuple
A tuple containing the shape of the broadcasted result.

Comment thread
antonwolfy marked this conversation as resolved.
Outdated
"""
return self._shape

@property
def size(self):
"""
Total size of the broadcasted result.

Returns
-------
out : int
The total size (number of elements) of the broadcasted result.

"""
return self._size

@property
def nd(self):
Comment thread
antonwolfy marked this conversation as resolved.
Outdated
"""
Number of dimensions of the broadcasted result.

Returns
-------
out : int
The number of dimensions of the broadcasted result.

"""
return self._nd

@property
def ndim(self):
"""
Number of dimensions of the broadcasted result.

Returns
-------
out : int
The number of dimensions of the broadcasted result.

"""
return self._nd

@property
def numiter(self):
"""
Number of iterators possessed by the broadcast object.

Returns
-------
out : int
The number of iterators.

"""
return len(self._arrays)
Comment thread
antonwolfy marked this conversation as resolved.
Outdated

def __repr__(self):
return f"<broadcast shape={self.shape}, nd={self.nd}, size={self.size}>"
Loading
Loading