Repository: numba/numba

Issue:
numpy array_equal implementaton
hi folks, could the array_equal function be implemented with @numba.jit ?

it compare shapes are equal, and if all values are equal

https://github.com/numpy/numpy/blob/v1.17.0/numpy/core/numeric.py#L2299-L2339


Discussion:
@rspadim thanks for submitting this! I will label it as a feature request accordingly. Also here is a minimal reproducer to show that it is indeed not yet implemented.

```python
from numba import njit
import numpy as np

@njit
def func(a,b):
    np.array_equal(a, b)

c = np.zeros((3,4))
d = np.zeros((3,4))

func(c,d)
```

As a temporary workaround, maybe you could use the following construct?

```python
from numba import njit
import numpy as np

@njit
def func(a,b):
    return np.all(a == b)

c = np.zeros((3,4))
d = np.zeros((3,4))

print(func(c,d))
```
Also, it should be possible to implement this using `@overload` --- here is some documentation to get started, should you feel the inclination:

https://numba.pydata.org/numba-doc/dev/extending/overloading-guide.html

just include the shape sizes check too
```
@njit
def func(a,b):
    if a.shape!=b.shape:
        return False
    return np.all(a == b)
```

Resolving patch:
diff --git a/numba/targets/arraymath.py b/numba/targets/arraymath.py
--- a/numba/targets/arraymath.py
+++ b/numba/targets/arraymath.py
@@ -3118,6 +3118,28 @@ def diff_impl(a, n=1):
     return diff_impl
 
 
+@overload(np.array_equal)
+def np_array_equal(a, b):
+
+    if not (type_can_asarray(a) and type_can_asarray(b)):
+        raise TypingError('Both arguments to "array_equals" must be array-like')
+
+    accepted = (types.Boolean, types.Number)
+    if isinstance(a, accepted) and isinstance(b, accepted):
+        # special case
+        def impl(a, b):
+            return a == b
+    else:
+        def impl(a, b):
+            a = np.asarray(a)
+            b = np.asarray(b)
+            if a.shape == b.shape:
+                return np.all(a == b)
+            return False
+
+    return impl
+
+
 def validate_1d_array_like(func_name, seq):
     if isinstance(seq, types.Array):
         if seq.ndim != 1:


Test patch:
diff --git a/numba/tests/test_np_functions.py b/numba/tests/test_np_functions.py
--- a/numba/tests/test_np_functions.py
+++ b/numba/tests/test_np_functions.py
@@ -33,6 +33,10 @@ def angle2(x, deg):
     return np.angle(x, deg)
 
 
+def array_equal(a, b):
+    return np.array_equal(a, b)
+
+
 def append(arr, values, axis):
     return np.append(arr, values, axis=axis)
 
@@ -387,6 +391,43 @@ def check(x_types, x_values):
         x_types = [types.complex64, types.complex128]
         check(x_types, x_values)
 
+    def test_array_equal(self):
+        def arrays():
+            yield np.array([]), np.array([])
+            yield np.array([1, 2]), np.array([1, 2])
+            yield np.array([]), np.array([1])
+            x = np.arange(10).reshape(5, 2)
+            x[1][1] = 30
+            yield np.arange(10).reshape(5, 2), x
+            yield x, x
+            yield (1, 2, 3), (1, 2, 3)
+            yield 2, 2
+            yield 3, 2
+            yield True, True
+            yield True, False
+            yield True, 2
+            yield True, 1
+            yield False, 0
+
+        pyfunc = array_equal
+        cfunc = jit(nopython=True)(pyfunc)
+
+        for arr, obj in arrays():
+            expected = pyfunc(arr, obj)
+            got = cfunc(arr, obj)
+            self.assertPreciseEqual(expected, got)
+
+    def test_array_equal_exception(self):
+        pyfunc = array_equal
+        cfunc = jit(nopython=True)(pyfunc)
+
+        with self.assertRaises(TypingError) as raises:
+            cfunc(np.arange(3 * 4).reshape(3, 4), None)
+        self.assertIn(
+            'Both arguments to "array_equals" must be array-like',
+            str(raises.exception)
+        )
+
     @unittest.skipIf(np_version < (1, 12), "NumPy Unsupported")
     def test_count_nonzero(self):