Repository: pydata/sparse

Issue:
The error message on 0D matmul is obscure and does not match NumPy.
**Describe the bug**
The error message on 0D matmul is obscure and does not match NumPy.

**To Reproduce**
```python
Python 3.7.6 (default, Jan  8 2020, 13:42:34)
[Clang 4.0.1 (tags/RELEASE_401/final)] :: Anaconda, Inc. on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import sparse
>>> import numpy as np
>>> a = np.array(0)
>>> b = sparse.COO(a)
>>> b + b
0
>>> b
<COO: shape=(), dtype=int64, nnz=1, fill_value=0>
>>> b @ b
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/hameerabbasi/Quansight/sparse/sparse/_coo/core.py", line 1649, in __matmul__
    return matmul(self, other)
  File "/Users/hameerabbasi/Quansight/sparse/sparse/_coo/common.py", line 203, in matmul
    return dot(a, b)
  File "/Users/hameerabbasi/Quansight/sparse/sparse/_coo/common.py", line 287, in dot
    return tensordot(a, b, axes=(a_axis, b_axis))
  File "/Users/hameerabbasi/Quansight/sparse/sparse/_coo/common.py", line 131, in tensordot
    if as_[axes_a[k]] != bs[axes_b[k]]:
IndexError: tuple index out of range
>>> a @ a
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: matmul: Input operand 0 does not have enough dimensions (has 0, gufunc core with signature (n?,k),(k,m?)->(n?,m?) requires 1)
```

**Expected behavior**
The error message should match NumPy.

**System**
 - macOS 10.15.3
 - `sparse` version: `0.9.1+18.gc94927c`
 - NumPy version: 1.18.1
 - Numba version: '0.46.0'

**Additional context**
Add any other context about the problem here.


Discussion:
codecov[bot]: # [Codecov](https://codecov.io/gh/pydata/sparse/pull/333?src=pr&el=h1) Report
> Merging [#333](https://codecov.io/gh/pydata/sparse/pull/333?src=pr&el=desc) into [master](https://codecov.io/gh/pydata/sparse/commit/c94927ccb3cd6aceab3701e54a8ba244435fa576&el=desc) will **decrease** coverage by `0.07%`.
> The diff coverage is `33.33%`.


```diff
@@            Coverage Diff             @@
##           master     #333      +/-   ##
==========================================
- Coverage   93.96%   93.88%   -0.08%     
==========================================
  Files          19       19              
  Lines        2337     2340       +3     
==========================================
+ Hits         2196     2197       +1     
- Misses        141      143       +2     
```




Patch:
diff --git a/sparse/_coo/common.py b/sparse/_coo/common.py
index ff34078..3dee087 100644
--- a/sparse/_coo/common.py
+++ b/sparse/_coo/common.py
@@ -124,6 +124,9 @@ def tensordot(a, b, axes=2):
     bs = b.shape
     ndb = b.ndim
     equal = True
+    if nda == 0 or ndb == 0:
+        pos = int(nda != 0)
+        raise ValueError("Input {} operand does not have enough dimensions".format(pos))
     if na != nb:
         equal = False
     else:


Test patch:
diff --git a/sparse/tests/test_coo.py b/sparse/tests/test_coo.py
index c8c50f4..48f8f52 100644
--- a/sparse/tests/test_coo.py
+++ b/sparse/tests/test_coo.py
@@ -343,6 +343,14 @@ def test_tensordot_empty():
     assert_eq(np.tensordot(x1, x2), sparse.tensordot(s1, s2))
 
 
+def test_tensordot_valueerror():
+    x1 = sparse.COO(np.array(1))
+    x2 = sparse.COO(np.array(1))
+
+    with pytest.raises(ValueError):
+        x1 @ x2
+
+
 @pytest.mark.parametrize(
     "a_shape, b_shape",
     [