Repository: sympy/sympy

Issue:
divmod should raise NotImplementedError for bad input
Issue #2010 comments indicate that divmod should raise a NotImplementedError not a TypeError for bad input:

```
>>> divmod(x,1)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for divmod(): 'Symbol' and 'int'
```


Discussion:

Patch:
diff --git a/doc/README.rst b/doc/README.rst
index c852f7c180..52a4bfdc9b 100644
--- a/doc/README.rst
+++ b/doc/README.rst
@@ -14,7 +14,7 @@ and do::
 
 and to view it, do::
 
-    firefox _build/html/index.html
+    epiphany _build/html/index.html
 
 Fedora
 ------
diff --git a/sympy/core/expr.py b/sympy/core/expr.py
index 7800aaf06b..8a5d27d68d 100644
--- a/sympy/core/expr.py
+++ b/sympy/core/expr.py
@@ -217,6 +217,19 @@ def __rfloordiv__(self, other):
         from sympy.functions.elementary.integers import floor
         return floor(other / self)
 
+
+    @_sympifyit('other', NotImplemented)
+    @call_highest_priority('__rdivmod__')
+    def __divmod__(self, other):
+        from sympy.functions.elementary.integers import floor
+        return floor(self / other), Mod(self, other)
+
+    @_sympifyit('other', NotImplemented)
+    @call_highest_priority('__divmod__')
+    def __rdivmod__(self, other):
+        from sympy.functions.elementary.integers import floor
+        return floor(other / self), Mod(other, self)
+
     def __int__(self):
         # Although we only need to round to the units position, we'll
         # get one more digit so the extra testing below can be avoided
diff --git a/sympy/matrices/matrices.py b/sympy/matrices/matrices.py
index ba5d3a75c9..5a6ff81c43 100644
--- a/sympy/matrices/matrices.py
+++ b/sympy/matrices/matrices.py
@@ -3938,20 +3938,8 @@ def pinv(self):
                 return AH * (A * AH).inv()
         except ValueError:
             # Matrix is not full rank, so A*AH cannot be inverted.
-            pass
-        try:
-            # However, A*AH is Hermitian, so we can diagonalize it.
-            if self.rows >= self.cols:
-                P, D = (AH * A).diagonalize(normalize=True)
-                D_pinv = D.applyfunc(lambda x: 0 if _iszero(x) else 1 / x)
-                return P * D_pinv * P.H * AH
-            else:
-                P, D = (A * AH).diagonalize(normalize=True)
-                D_pinv = D.applyfunc(lambda x: 0 if _iszero(x) else 1 / x)
-                return AH * P * D_pinv * P.H
-        except MatrixError:
-            raise NotImplementedError('pinv for rank-deficient matrices where diagonalization '
-                                      'of A.H*A fails is not supported yet.')
+            raise NotImplementedError('Rank-deficient matrices are not yet '
+                                      'supported.')
 
     def print_nonzero(self, symb="X"):
         """Shows location of non-zero entries for fast shape lookup.


Test patch:
diff --git a/sympy/core/tests/test_arit.py b/sympy/core/tests/test_arit.py
index 3bf9be5bd5..811cb8362e 100644
--- a/sympy/core/tests/test_arit.py
+++ b/sympy/core/tests/test_arit.py
@@ -1985,3 +1985,8 @@ def test_Add_is_zero():
 
 def test_issue_14392():
     assert (sin(zoo)**2).as_real_imag() == (nan, nan)
+
+def test_divmod():
+    assert divmod(x, y) == (x//y, x % y)
+    assert divmod(x, 3) == (x//3, x % 3)
+    assert divmod(3, x) == (3//x, 3 % x)
diff --git a/sympy/matrices/expressions/tests/test_kronecker.py b/sympy/matrices/expressions/tests/test_kronecker.py
index c41378e36a..1819e490f2 100644
--- a/sympy/matrices/expressions/tests/test_kronecker.py
+++ b/sympy/matrices/expressions/tests/test_kronecker.py
@@ -1,4 +1,4 @@
-from sympy import I, symbols, Matrix, eye
+from sympy import I, symbols, Matrix, eye, Mod, floor
 from sympy.matrices import ShapeError, MatrixSymbol, Identity
 from sympy.matrices.expressions import det, trace
 
@@ -10,7 +10,7 @@
 mat1 = Matrix([[1, 2 * I], [1 + I, 3]])
 mat2 = Matrix([[2 * I, 3], [4 * I, 2]])
 
-n, m, k, x = symbols('n,m,k,x')
+i, j, k, n, m, o, p, x = symbols('i,j,k,n,m,o,p,x')
 Z = MatrixSymbol('Z', n, n)
 W = MatrixSymbol('W', m, m)
 A = MatrixSymbol('A', n, m)
@@ -136,3 +136,9 @@ def test_KroneckerProduct_expand():
     assert KroneckerProduct(X + Y, Y + Z).expand(kroneckerproduct=True) == \
         KroneckerProduct(X, Y) + KroneckerProduct(X, Z) + \
         KroneckerProduct(Y, Y) + KroneckerProduct(Y, Z)
+
+def test_KroneckerProduct_entry():
+    A = MatrixSymbol('A', n, m)
+    B = MatrixSymbol('B', o, p)
+
+    assert KroneckerProduct(A, B)._entry(i, j) == A[Mod(floor(i/o), n), Mod(floor(j/p), m)]*B[Mod(i, o), Mod(j, p)]
diff --git a/sympy/matrices/tests/test_matrices.py b/sympy/matrices/tests/test_matrices.py
index a6d3d7b4b6..5ffb498deb 100644
--- a/sympy/matrices/tests/test_matrices.py
+++ b/sympy/matrices/tests/test_matrices.py
@@ -2786,11 +2786,11 @@ def test_pinv_solve():
     # Proof the solution is not exact.
     assert A * A.pinv() * B != B
 
+@XFAIL
 def test_pinv_rank_deficient():
     # Test the four properties of the pseudoinverse for various matrices.
     As = [Matrix([[1, 1, 1], [2, 2, 2]]),
-          Matrix([[1, 0], [0, 0]]),
-          Matrix([[1, 2], [2, 4], [3, 6]])]
+          Matrix([[1, 0], [0, 0]])]
     for A in As:
         A_pinv = A.pinv()
         AAp = A * A_pinv
@@ -2816,25 +2816,6 @@ def test_pinv_rank_deficient():
     assert solution == Matrix([3, w1])
     assert A * A.pinv() * B != B
 
-@XFAIL
-def test_pinv_rank_deficient_when_diagonalization_fails():
-    print('Test the four properties of the pseudoinverse for matrices when diagonalization of A.H*A fails.')
-    As = [Matrix([
-        [61, 89, 55, 20, 71, 0],
-        [62, 96, 85, 85, 16, 0],
-        [69, 56, 17,  4, 54, 0],
-        [10, 54, 91, 41, 71, 0],
-        [ 7, 30, 10, 48, 90, 0],
-        [0,0,0,0,0,0]])]
-    for A in As:
-        A_pinv = A.pinv()
-        AAp = A * A_pinv
-        ApA = A_pinv * A
-        assert simplify(AAp * A) == A
-        assert simplify(ApA * A_pinv) == A_pinv
-        assert AAp.H == AAp
-        assert ApA.H == ApA
-
 
 def test_gauss_jordan_solve():