Repository: numba/numba

Issue:
Numpy.dot o
Problem: numpy dot is throwing an exception, but the docs say it is supported.

Numba version: 0.38.0

Minimal Example:

```
import numpy as np
from numba import jit

@jit(nopython=True)
def matmul2(size: int):
    a = np.random.random((size, size))
    b = np.random.random((size, size))
    return a.dot(b)
```

Expected: Should work
Actual Result: Exception

```
Traceback (most recent call last):
  File "test.py", line 209, in <module>
    matmul2(1000)
  File "C:\Program Files\Python36\Lib\site-packages\numba\dispatcher.py", line 344, in _compile_for_args
    reraise(type(e), e, None)
  File "C:\Program Files\Python36\Lib\site-packages\numba\six.py", line 658, in reraise
    raise value.with_traceback(tb)
numba.errors.TypingError: Failed at nopython (nopython frontend)
Unknown attribute 'dot' of type array(float64, 2d, C)

File "test.py", line 204:
def matmul2(size: int):
    <source elided>
    b = np.random.random((size, size))
    return a.dot(b)
    ^

[1] During: typing of get attribute at test.py (204)

File "test.py", line 204:
def matmul2(size: int):
    <source elided>
    b = np.random.random((size, size))
    return a.dot(b)
    ^
```


Discussion:
If instead I use np.dot(a, b) I get a different error:

`scipy 0.16+ is required for linear algebra`

But the dot operator should give the same result

Resolving patch:
diff --git a/numba/targets/arrayobj.py b/numba/targets/arrayobj.py
--- a/numba/targets/arrayobj.py
+++ b/numba/targets/arrayobj.py
@@ -3565,7 +3565,6 @@ def take_impl(a, indices):
     res = context.compile_internal(builder, take_impl, sig, args)
     return impl_ret_new_ref(context, builder, sig.return_type, res)
 
-
 @lower_builtin(np.arange, types.Number)
 def numpy_arange_1(context, builder, sig, args):
     dtype = as_dtype(sig.return_type.dtype)
@@ -4569,6 +4568,7 @@ def np_vstack_impl(arrays):
 
         return context.compile_internal(builder, np_vstack_impl, sig, args)
 
+
 @extending.overload_method(types.Array, 'fill')
 def arr_fill(arr, val):
 
@@ -4578,6 +4578,14 @@ def fill_impl(arr, val):
 
     return fill_impl
 
+
+@extending.overload_method(types.Array, 'dot')
+def array_dot(arr, other):
+    def dot_impl(arr, other):
+        return np.dot(arr, other)
+
+    return dot_impl
+
 # -----------------------------------------------------------------------------
 # Sorting
 


Test patch:
diff --git a/numba/tests/test_array_methods.py b/numba/tests/test_array_methods.py
--- a/numba/tests/test_array_methods.py
+++ b/numba/tests/test_array_methods.py
@@ -170,6 +170,7 @@ def array_cumsum(a, *args):
 def array_cumsum_kws(a, axis):
     return a.cumsum(axis=axis)
 
+
 def array_real(a):
     return np.real(a)
 
@@ -177,10 +178,19 @@ def array_real(a):
 def array_imag(a):
     return np.imag(a)
 
+
 def np_unique(a):
     return np.unique(a)
 
 
+def array_dot(a, b):
+    return a.dot(b)
+
+
+def array_dot_chain(a, b):
+    return a.dot(b).dot(b)
+
+
 class TestArrayMethods(MemoryLeakMixin, TestCase):
     """
     Test various array methods and array-related functions.
@@ -743,7 +753,6 @@ def test_cumsum(self):
         with self.assertRaises(TypingError):
             cfunc(a, axis=1)
 
-
     def test_take(self):
         pyfunc = array_take
         cfunc = jit(nopython=True)(pyfunc)
@@ -809,7 +818,6 @@ def check(arr, ind):
         #exceptions leak refs
         self.disable_leak_check()
 
-
     def test_fill(self):
         pyfunc = array_fill
         cfunc = jit(nopython=True)(pyfunc)
@@ -872,6 +880,21 @@ def check(a):
         check(np.array([[3.1, 3.1], [1.7, 2.29], [3.3, 1.7]]))
         check(np.array([]))
 
+    def test_array_dot(self):
+        # just ensure that the dot impl dispatches correctly, do
+        # not test dot itself, this is done in test_linalg.
+        pyfunc = array_dot
+        cfunc = jit(nopython=True)(pyfunc)
+        a = np.arange(20.).reshape(4, 5)
+        b = np.arange(5.)
+        np.testing.assert_equal(pyfunc(a, b), cfunc(a, b))
+
+        # check that chaining works
+        pyfunc = array_dot_chain
+        cfunc = jit(nopython=True)(pyfunc)
+        a = np.arange(16.).reshape(4, 4)
+        np.testing.assert_equal(pyfunc(a, a), cfunc(a, a))
+
 
 class TestArrayComparisons(TestCase):