Repository: ivy-llc/ivy

Issue:
broad



Discussion:

Resolving patch:
diff --git a/ivy/functional/frontends/numpy/__init__.py b/ivy/functional/frontends/numpy/__init__.py
--- a/ivy/functional/frontends/numpy/__init__.py
+++ b/ivy/functional/frontends/numpy/__init__.py
@@ -490,6 +490,8 @@ def promote_types_of_numpy_inputs(
 from .matrix import *
 from . import random
 from .random import *
+from . import broadcast
+from .broadcast import *
 
 from . import ma
 from . import fft
diff --git a/ivy/functional/frontends/numpy/broadcast/__init__.py b/ivy/functional/frontends/numpy/broadcast/__init__.py
new file mode 100644
--- /dev/null
+++ b/ivy/functional/frontends/numpy/broadcast/__init__.py
@@ -0,0 +1,2 @@
+from . import methods
+from .methods import *
diff --git a/ivy/functional/frontends/numpy/broadcast/methods.py b/ivy/functional/frontends/numpy/broadcast/methods.py
new file mode 100644
--- /dev/null
+++ b/ivy/functional/frontends/numpy/broadcast/methods.py
@@ -0,0 +1,56 @@
+# local
+import ivy
+from ivy.functional.frontends.numpy.func_wrapper import to_ivy_arrays_and_back
+
+
+class broadcast:
+    @to_ivy_arrays_and_back
+    def __init__(self, *args):
+        data = ivy.broadcast_arrays(*map(ivy.array, args))
+        self._shape = data[0].shape
+        self._ndim = data[0].ndim
+        self._index = 0
+        self._numiter = len(data)
+        self._size = data[0].size
+        self._data = tuple((*zip(*(ivy.flatten(i) for i in data)),))
+        self._iters = tuple((iter(ivy.flatten(i)) for i in data))
+
+    @property
+    def shape(self):
+        return self._shape
+
+    @property
+    def ndim(self):
+        return self._ndim
+
+    @property
+    def nd(self):
+        return self._ndim
+
+    @property
+    def numiter(self):
+        return self._numiter
+
+    @property
+    def size(self):
+        return self._size
+
+    @property
+    def iters(self):
+        return self._iters
+
+    @property
+    def index(self):
+        return self._index
+
+    def __next__(self):
+        if self.index < self.size:
+            self._index += 1
+            return self._data[self.index - 1]
+        raise StopIteration
+
+    def __iter__(self):
+        return self
+
+    def reset(self):
+        self._index = 0


Test patch:
diff --git a/ivy_tests/test_ivy/test_frontends/test_numpy/test_broadcast/__init__.py b/ivy_tests/test_ivy/test_frontends/test_numpy/test_broadcast/__init__.py
new file mode 100644
diff --git a/ivy_tests/test_ivy/test_frontends/test_numpy/test_broadcast/test_methods.py b/ivy_tests/test_ivy/test_frontends/test_numpy/test_broadcast/test_methods.py
new file mode 100644
--- /dev/null
+++ b/ivy_tests/test_ivy/test_frontends/test_numpy/test_broadcast/test_methods.py
@@ -0,0 +1,109 @@
+# global
+from hypothesis import strategies as st
+import numpy as np
+
+# local
+import ivy
+from ivy.functional.frontends.numpy import broadcast
+import ivy_tests.test_ivy.helpers as helpers
+from ivy_tests.test_ivy.helpers import handle_frontend_test
+
+
+@st.composite
+def _broadcastable_arrays(draw):
+    num_of_array = draw(st.integers(1, 3))
+    shapes = draw(helpers.mutually_broadcastable_shapes(num_shapes=num_of_array))
+    xs = []
+    for i in range(num_of_array):
+        xs.append(
+            draw(
+                helpers.array_values(dtype=helpers.get_dtypes("valid"), shape=shapes[i])
+            )
+        )
+    return xs
+
+
+@handle_frontend_test(
+    fn_tree="numpy.add",  # dummy fn_tree
+    args=_broadcastable_arrays(),
+)
+def test_numpy_broadcast_property_shape(args):
+    ret = broadcast(*args)
+    ret_gt = np.broadcast(*args)
+    assert ret.shape == ret_gt.shape
+
+
+@handle_frontend_test(
+    fn_tree="numpy.add",  # dummy fn_tree
+    args=_broadcastable_arrays(),
+)
+def test_numpy_broadcast_property_size(args):
+    ret = broadcast(*args)
+    ret_gt = np.broadcast(*args)
+    assert ret.size == ret_gt.size
+
+
+@handle_frontend_test(
+    fn_tree="numpy.add",  # dummy fn_tree
+    args=_broadcastable_arrays(),
+)
+def test_numpy_broadcast_property_nd(args):
+    ret = broadcast(*args)
+    ret_gt = np.broadcast(*args)
+    assert ret.nd == ret_gt.nd
+
+
+@handle_frontend_test(
+    fn_tree="numpy.add",  # dummy fn_tree
+    args=_broadcastable_arrays(),
+)
+def test_numpy_broadcast_property_ndim(args):
+    ret = broadcast(*args)
+    ret_gt = np.broadcast(*args)
+    assert ret.ndim == ret_gt.ndim
+
+
+@handle_frontend_test(
+    fn_tree="numpy.add",  # dummy fn_tree
+    args=_broadcastable_arrays(),
+)
+def test_numpy_broadcast_property_numiter(args):
+    ret = broadcast(*args)
+    ret_gt = np.broadcast(*args)
+    assert ret.numiter == ret_gt.numiter
+
+
+@handle_frontend_test(
+    fn_tree="numpy.add",  # dummy fn_tree
+    args=_broadcastable_arrays(),
+)
+def test_numpy_broadcast_property_index(args):
+    ret = broadcast(*args)
+    ret_gt = np.broadcast(*args)
+    assert ret.index == ret_gt.index
+    for _ in zip(ret, ret_gt):
+        assert ret.index == ret_gt.index
+
+
+@handle_frontend_test(
+    fn_tree="numpy.add",  # dummy fn_tree
+    args=_broadcastable_arrays(),
+)
+def test_numpy_broadcast_property_iters(args):
+    ret = list(map(list, broadcast(*args).iters))
+    ret_gt = np.array(list(map(list, np.broadcast(*args).iters)))
+    assert ivy.all(ret == ret_gt)
+
+
+@handle_frontend_test(
+    fn_tree="numpy.add",  # dummy fn_tree
+    args=_broadcastable_arrays(),
+)
+def test_numpy_broadcast_method_reset(args):
+    ret = broadcast(*args)
+    ret_gt = np.broadcast(*args)
+    for _ in zip(ret, ret_gt):
+        pass
+    ret.reset()
+    ret_gt.reset()
+    assert ret.index == ret_gt.index