Repository: numpy/numpy

Issue:
array_equal fails on string dtypes
If I pass two ndarrays with string dtype to `array_equal`, it blows up:

```
In [151]: a = np.asarray(["a", "b"])

In [152]: a
Out[152]: 
array(['a', 'b'], 
      dtype='|S1')

In [153]: np.array_equal(a, a)
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-153-8f762db9db16> in <module>()
----> 1 np.array_equal(a, a)

/home/njs/.user-python2.7-64bit/lib/python2.7/site-packages/numpy/core/numeric.pyc in array_equal(a1, a2)
   1975     if a1.shape != a2.shape:
   1976         return False
-> 1977     return bool(logical_and.reduce(equal(a1,a2).ravel()))
   1978 
   1979 def array_equiv(a1, a2):

AttributeError: 'NotImplementedType' object has no attribute 'ravel'
```

Expected result: `True`

ENH: make array_equal+array_equiv work for record arrays/structured arrays
Implementation of http://projects.scipy.org/numpy/ticket/1941 with tests. Please comment if the behaviour of array_equiv in commit 4b896f8 or in HEAD is preferred.



Discussion:
(confirmed with 1.8.0.dev-17774a6)

That would make the difference between array_equal and array_equiv - but structure array comparison seems to behave similar to both, so maybe it's really a matter of taste:

``` python
>>> x = np.array([(0,1),(2,3)], dtype=[('a', 'i4'), ('b', 'i4')])
>>> y = np.array([(0,1),(2,3)], dtype=[('a', 'i4'), ('b', 'i4')]).reshape(1,-1)
>>> x == y
array([[ True,  True]], dtype=bool)
```

I was not aware that '==' did work already, so maybe most of the array_equal code could simply be replaced by 

``` python
return bool((a1 == a2).all())
```

?

I actually fixed the == in 1.6. It had already been implemented, but incorrectly. I think even just

```
return (a1 == a2).all()
```

should be fine, but it's worth having tests which confirm this. One thing to think about for the future, is that I think == for struct dtypes should return a struct dtype with matching names but all 'bool' dtypes, and all() should be extended to reduce the bool-struct to a single value as well... The above line of code would still work correctly with these changes, so that's good.

@dhomeier How does this story end?


Resolving patch:
diff --git a/numpy/core/numeric.py b/numpy/core/numeric.py
--- a/numpy/core/numeric.py
+++ b/numpy/core/numeric.py
@@ -2137,7 +2137,7 @@ def array_equal(a1, a2):
         return False
     if a1.shape != a2.shape:
         return False
-    return bool(equal(a1,a2).all())
+    return bool(asarray(a1 == a2).all())
 
 def array_equiv(a1, a2):
     """
@@ -2179,7 +2179,7 @@ def array_equiv(a1, a2):
     except:
         return False
     try:
-        return bool(equal(a1,a2).all())
+        return bool(asarray(a1 == a2).all())
     except ValueError:
         return False
 


Test patch:
diff --git a/numpy/core/tests/test_numeric.py b/numpy/core/tests/test_numeric.py
--- a/numpy/core/tests/test_numeric.py
+++ b/numpy/core/tests/test_numeric.py
@@ -656,6 +656,12 @@ def test_array_equal(self):
         res = array_equal(array([1,2]), array([1,3]))
         assert_(not res)
         assert_(type(res) is bool)
+        res = array_equal(array(['a'], dtype='S1'), array(['a'], dtype='S1'))
+        assert_(res)
+        assert_(type(res) is bool)
+        res = array_equal(array([('a',1)], dtype='S1,u4'), array([('a',1)], dtype='S1,u4'))
+        assert_(res)
+        assert_(type(res) is bool)
 
     def test_array_equiv(self):
         res = array_equiv(array([1,2]), array([1,2]))