Repository: sympy/sympy

Issue:
rewrite im() in terms of re() and vice versa
There is a bug in the rewrite logic in ``complexes.py`` (see https://github.com/sympy/sympy/pull/8359#issuecomment-200560081 and https://github.com/sympy/sympy/pull/8359#issuecomment-200713532). 

The expected output should be:
```py
re(x).rewrite(im) == x - I*im(x)
im(x).rewrite(re) == -I*(x - re(x))
```

Discussion:
Nitin216: Someone review this PR
thisch: You need to fix the existing tests in https://github.com/sympy/sympy/pull/8359/files
Nitin216: @thisch  Got that working on it now.

Patch:
diff --git a/doc/src/modules/solvers/diophantine.rst b/doc/src/modules/solvers/diophantine.rst
index a738bdc433..743a28f1d4 100644
--- a/doc/src/modules/solvers/diophantine.rst
+++ b/doc/src/modules/solvers/diophantine.rst
@@ -135,7 +135,7 @@ For linear Diophantine equations, the customized parameter is the prefix used
 for each free variable in the solution. Consider the following example:
 
 >>> diop_solve(2*x + 3*y - 5*z + 7, m)
-(m_0, 9*m_0 + 5*m_1 + 14, 5*m_0 + 3*m_1 + 7)
+(m_0, -9*m_0 - 5*m_1 - 14, -5*m_0 - 3*m_1 - 7)
 
 In the solution above, m_0 and m_1 are independent free variables.
 
@@ -164,7 +164,7 @@ set()
 >>> diophantine(x**2 - 4*x*y + 4*y**2 - 3*x + 7*y - 5)
 set([(-2*t**2 - 7*t + 10, -t**2 - 3*t + 5)])
 >>> diophantine(x**2 + 2*x*y + y**2 - 3*x - 3*y)
-set([(t_0, -t_0 + 1), (t_0, -t_0 + 3)])
+set([(t_0, -t_0), (t_0, -t_0 + 3)])
 
 The most interesting case is when `\Delta > 0` and it is not a perfect square.
 In this case, the equation has either no solutions or an infinte number of
diff --git a/examples/beginner/basic.py b/examples/beginner/basic.py
index 9d5f7d0565..e2651f7615 100755
--- a/examples/beginner/basic.py
+++ b/examples/beginner/basic.py
@@ -5,18 +5,19 @@
 Demonstrates how to create symbols and print some algebra operations.
 """
 
-from sympy import Symbol, pprint
+import sympy
+from sympy import pprint
 
 
 def main():
-    a = Symbol('a')
-    b = Symbol('b')
-    c = Symbol('c')
+    a = sympy.Symbol('a')
+    b = sympy.Symbol('b')
+    c = sympy.Symbol('c')
     e = ( a*b*b + 2*b*a*b )**c
 
-    print('')
+    print
     pprint(e)
-    print('')
+    print
 
 if __name__ == "__main__":
     main()
diff --git a/examples/beginner/series.py b/examples/beginner/series.py
index 6ea50692fe..dc3a9d353f 100755
--- a/examples/beginner/series.py
+++ b/examples/beginner/series.py
@@ -12,17 +12,17 @@ def main():
     x = Symbol('x')
 
     e = 1/cos(x)
-    print('')
+    print()
     print("Series for sec(x):")
-    print('')
+    print()
     pprint(e.series(x, 0, 10))
     print("\n")
 
     e = 1/sin(x)
     print("Series for csc(x):")
-    print('')
+    print()
     pprint(e.series(x, 0, 4))
-    print('')
+    print()
 
 if __name__ == "__main__":
     main()
diff --git a/sympy/core/function.py b/sympy/core/function.py
index 94eb5128ff..3570998820 100644
--- a/sympy/core/function.py
+++ b/sympy/core/function.py
@@ -137,22 +137,6 @@ def __init__(cls, *args, **kwargs):
             nargs = (as_int(nargs),)
         cls._nargs = nargs
 
-    @property
-    def __signature__(self):
-        """
-        Allow Python 3's inspect.signature to give a useful signature for
-        Function subclasses.
-        """
-        # Python 3 only, but backports (like the one in IPython) still might
-        # call this.
-        try:
-            from inspect import signature
-        except ImportError:
-            return None
-
-        # TODO: Look at nargs
-        return signature(self.eval)
-
     @property
     def nargs(self):
         """Return a set of the allowed number of arguments for the function.
@@ -482,7 +466,7 @@ def _eval_evalf(self, prec):
         except (AttributeError, KeyError):
             try:
                 return Float(self._imp_(*self.args), prec)
-            except (AttributeError, TypeError, ValueError):
+            except (AttributeError, TypeError):
                 return
 
         # Convert all args to mpf or mpc
diff --git a/sympy/functions/combinatorial/factorials.py b/sympy/functions/combinatorial/factorials.py
index fc11ad04fa..48ea175555 100644
--- a/sympy/functions/combinatorial/factorials.py
+++ b/sympy/functions/combinatorial/factorials.py
@@ -853,9 +853,6 @@ def _eval_rewrite_as_gamma(self, n, k):
         from sympy import gamma
         return gamma(n + 1)/(gamma(k + 1)*gamma(n - k + 1))
 
-    def _eval_rewrite_as_tractable(self, n, k):
-        return self._eval_rewrite_as_gamma(n, k).rewrite('tractable')
-
     def _eval_rewrite_as_FallingFactorial(self, n, k):
         if k.is_integer:
             return ff(n, k) / factorial(k)
diff --git a/sympy/functions/elementary/complexes.py b/sympy/functions/elementary/complexes.py
index cc1c4d8d7b..fcec176d1d 100644
--- a/sympy/functions/elementary/complexes.py
+++ b/sympy/functions/elementary/complexes.py
@@ -100,7 +100,7 @@ def _eval_derivative(self, x):
                 * im(Derivative(self.args[0], x, evaluate=True))
 
     def _eval_rewrite_as_im(self, arg):
-        return self.args[0] - im(self.args[0])
+        return self.args[0] - S.ImaginaryUnit*im(self.args[0])
 
     def _eval_is_algebraic(self):
         return self.args[0].is_algebraic
@@ -203,7 +203,7 @@ def _sage_(self):
         return sage.imag_part(self.args[0]._sage_())
 
     def _eval_rewrite_as_re(self, arg):
-        return self.args[0] - re(self.args[0])
+        return -S.ImaginaryUnit*(self.args[0] - re(self.args[0]))
 
     def _eval_is_algebraic(self):
         return self.args[0].is_algebraic
diff --git a/sympy/printing/latex.py b/sympy/printing/latex.py
index 50a464f915..ba22308b1e 100644
--- a/sympy/printing/latex.py
+++ b/sympy/printing/latex.py
@@ -322,13 +322,9 @@ def _print_Float(self, expr):
             return str_real
 
     def _print_Mul(self, expr):
-        include_parens = False
         if _coeff_isneg(expr):
             expr = -expr
             tex = "- "
-            if expr.is_Add:
-                tex += "("
-                include_parens = True
         else:
             tex = ""
 
@@ -409,8 +405,6 @@ def convert(expr):
             else:
                 tex += r"\frac{%s}{%s}" % (snumer, sdenom)
 
-        if include_parens:
-            tex += ")"
         return tex
 
     def _print_Pow(self, expr):
@@ -1231,7 +1225,7 @@ def _print_Order(self, expr):
                 s += self._print(expr.variables)
             elif len(expr.variables):
                 s += self._print(expr.variables[0])
-            s += r'\rightarrow '
+            s += r'\rightarrow'
             if len(expr.point) > 1:
                 s += self._print(expr.point)
             else:


Test patch:
diff --git a/sympy/functions/elementary/tests/test_complexes.py b/sympy/functions/elementary/tests/test_complexes.py
index d74e2e317e..896197d190 100644
--- a/sympy/functions/elementary/tests/test_complexes.py
+++ b/sympy/functions/elementary/tests/test_complexes.py
@@ -68,8 +68,8 @@ def test_re():
     assert re((1 + sqrt(a + b*I))/2) == \
         (a**2 + b**2)**Rational(1, 4)*cos(atan2(b, a)/2)/2 + Rational(1, 2)
 
-    assert re(x).rewrite(im) == x - im(x)
-    assert (x + re(y)).rewrite(re, im) == x + y - im(y)
+    assert re(x).rewrite(im) == x - S.ImaginaryUnit*im(x)
+    assert (x + re(y)).rewrite(re, im) == x + y - S.ImaginaryUnit*im(y)
 
     a = Symbol('a', algebraic=True)
     t = Symbol('t', transcendental=True)
@@ -137,8 +137,8 @@ def test_im():
     assert im((1 + sqrt(a + b*I))/2) == \
         (a**2 + b**2)**Rational(1, 4)*sin(atan2(b, a)/2)/2
 
-    assert im(x).rewrite(re) == x - re(x)
-    assert (x + im(y)).rewrite(im, re) == x + y - re(y)
+    assert im(x).rewrite(re) == -S.ImaginaryUnit * (x - re(x))
+    assert (x + im(y)).rewrite(im, re) == x - S.ImaginaryUnit * (y - re(y))
 
     a = Symbol('a', algebraic=True)
     t = Symbol('t', transcendental=True)
diff --git a/sympy/printing/tests/test_latex.py b/sympy/printing/tests/test_latex.py
index 2bb6b15ce0..05eac5e4ae 100644
--- a/sympy/printing/tests/test_latex.py
+++ b/sympy/printing/tests/test_latex.py
@@ -27,7 +27,6 @@
 from sympy.functions import DiracDelta, Heaviside, KroneckerDelta, LeviCivita
 from sympy.logic import Implies
 from sympy.logic.boolalg import And, Or, Xor
-from sympy.physics.quantum import Commutator, Operator
 from sympy.core.trace import Tr
 from sympy.core.compatibility import range
 from sympy.combinatorics.permutations import Cycle, Permutation
@@ -264,11 +263,10 @@ def test_latex_functions():
     assert latex(Order(x)) == r"\mathcal{O}\left(x\right)"
     assert latex(Order(x, x)) == r"\mathcal{O}\left(x\right)"
     assert latex(Order(x, (x, 0))) == r"\mathcal{O}\left(x\right)"
-    assert latex(Order(x, (x, oo))) == r"\mathcal{O}\left(x; x\rightarrow \infty\right)"
-    assert latex(Order(x - y, (x, y))) == r"\mathcal{O}\left(x - y; x\rightarrow y\right)"
-    assert latex(Order(x, x, y)) == r"\mathcal{O}\left(x; \left ( x, \quad y\right )\rightarrow \left ( 0, \quad 0\right )\right)"
-    assert latex(Order(x, x, y)) == r"\mathcal{O}\left(x; \left ( x, \quad y\right )\rightarrow \left ( 0, \quad 0\right )\right)"
-    assert latex(Order(x, (x, oo), (y, oo))) == r"\mathcal{O}\left(x; \left ( x, \quad y\right )\rightarrow \left ( \infty, \quad \infty\right )\right)"
+    assert latex(Order(x, (x, oo))) == r"\mathcal{O}\left(x; x\rightarrow\infty\right)"
+    assert latex(Order(x, x, y)) == r"\mathcal{O}\left(x; \left ( x, \quad y\right )\rightarrow\left ( 0, \quad 0\right )\right)"
+    assert latex(Order(x, x, y)) == r"\mathcal{O}\left(x; \left ( x, \quad y\right )\rightarrow\left ( 0, \quad 0\right )\right)"
+    assert latex(Order(x, (x, oo), (y, oo))) == r"\mathcal{O}\left(x; \left ( x, \quad y\right )\rightarrow\left ( \infty, \quad \infty\right )\right)"
     assert latex(lowergamma(x, y)) == r'\gamma\left(x, y\right)'
     assert latex(uppergamma(x, y)) == r'\Gamma\left(x, y\right)'
 
@@ -603,12 +601,6 @@ def test_latex_AccumuBounds():
 def test_latex_emptyset():
     assert latex(S.EmptySet) == r"\emptyset"
 
-def test_latex_commutator():
-    A = Operator('A')
-    B = Operator('B')
-    comm = Commutator(B, A)
-    assert latex(comm.doit()) == r"- (A B - B A)"
-
 
 def test_latex_union():
     assert latex(Union(Interval(0, 1), Interval(2, 3))) == \
diff --git a/sympy/series/tests/test_limits.py b/sympy/series/tests/test_limits.py
index 09f972fcc2..174814b450 100644
--- a/sympy/series/tests/test_limits.py
+++ b/sympy/series/tests/test_limits.py
@@ -456,11 +456,6 @@ def test_issue_8730():
     assert limit(subfactorial(x), x, oo) == oo
 
 
-def test_issue_10801():
-    # make sure limits work with binomial
-    assert limit(16**k / (k * binomial(2*k, k)**2), k, oo) == pi
-
-
 def test_issue_9205():
     x, y, a = symbols('x, y, a')
     assert Limit(x, x, a).free_symbols == {a}
diff --git a/sympy/utilities/tests/test_lambdify.py b/sympy/utilities/tests/test_lambdify.py
index a6926c6dca..199a160b08 100644
--- a/sympy/utilities/tests/test_lambdify.py
+++ b/sympy/utilities/tests/test_lambdify.py
@@ -502,23 +502,6 @@ def test_imps():
     raises(ValueError, lambda: lambdify(x, f(f2(x))))
 
 
-def test_imps_errors():
-    # Test errors that implemented functions can return, and still be able to
-    # form expressions.
-    # See: https://github.com/sympy/sympy/issues/10810
-    for val, error_class in product((0, 0., 2, 2.0),
-                                    (AttributeError, TypeError, ValueError)):
-
-        def myfunc(a):
-            if a == 0:
-                raise error_class
-            return 1
-
-        f = implemented_function('f', myfunc)
-        expr = f(val)
-        assert expr == f(val)
-
-
 def test_imps_wrong_args():
     raises(ValueError, lambda: implemented_function(sin, lambda x: x))