Repository: sympy/sympy

Issue:
positive != -negative in some integrals
```
>>> a = Symbol('a', positive=True)
>>> b = Symbol('b', negative=True)
>>> laplace_transform(1/(I*t + a), t, s) 
(-I*exp(-I*a*s)*expint(1, a*s*exp_polar(-I*pi/2)), 0, True)
>>> laplace_transform(1/(I*t - b), t, s) 
LaplaceTransform(1/(-b + I*t), t, s)
```
It seems that a constant that is used to determine the convergence in `meijerint` is incorrectly evaluated in the latter case.

Discussion:

Patch:
diff --git a/doc/src/gotchas.rst b/doc/src/gotchas.rst
index bef1e794b0..7e2bad2e97 100644
--- a/doc/src/gotchas.rst
+++ b/doc/src/gotchas.rst
@@ -20,7 +20,7 @@ remainder of the SymPy Docs, and the `official Python Tutorial <https://docs.pyt
 
 If you are already familiar with C or Java, you might also want to look
 at this `4 minute Python tutorial
-<https://nerdparadise.com/programming/python4minutes/>`_.
+<http://www.nerdparadise.com/tech/python/4minutecrashcourse/>`_.
 
 Ignore ``#doctest: +SKIP`` in the examples.  That has to do with
 internal testing of the examples.
@@ -334,9 +334,9 @@ you don't have to worry about this problem:
     3.142857142857143
     >>> # One solution is to just assign the expression to a variable
     >>> # if we need to use it again.
-    >>> a = solve(7*x - 22, x)[0]
+    >>> a = solve(7*x - 22, x)
     >>> a
-    22/7
+    [22/7]
 
     The other solution is to put quotes around the expression
     and run it through S() (i.e., sympify it):
diff --git a/sympy/concrete/summations.py b/sympy/concrete/summations.py
index 318cca49ed..111b7abe83 100644
--- a/sympy/concrete/summations.py
+++ b/sympy/concrete/summations.py
@@ -1056,13 +1056,7 @@ def eval_sum_symbolic(f, limits):
         if not r in (None, S.NaN):
             return r
 
-    h = eval_sum_hyper(f_orig, (i, a, b))
-    if h is not None:
-        return h
-
-    factored = f_orig.factor()
-    if factored != f_orig:
-        return eval_sum_symbolic(factored, (i, a, b))
+    return eval_sum_hyper(f_orig, (i, a, b))
 
 
 def _eval_sum_hyper(f, i, a):
diff --git a/sympy/functions/elementary/complexes.py b/sympy/functions/elementary/complexes.py
index ebf0bc62c2..f451cdb038 100644
--- a/sympy/functions/elementary/complexes.py
+++ b/sympy/functions/elementary/complexes.py
@@ -978,8 +978,13 @@ def mr(expr):
                     return polar_lift(expr)
                 return expr
             pl = pl.replace(polar_lift, mr)
+            # Recompute unbranched argument
+            ub = periodic_argument(pl, oo)
             if not pl.has(polar_lift):
-                res = exp_polar(I*(barg - ub))*pl
+                if ub != barg:
+                    res = exp_polar(I*(barg - ub))*pl
+                else:
+                    res = pl
                 if not res.is_polar and not res.has(exp_polar):
                     res *= exp_polar(0)
                 return res
diff --git a/sympy/functions/elementary/piecewise.py b/sympy/functions/elementary/piecewise.py
index 09cc47a6fe..adb6db521a 100644
--- a/sympy/functions/elementary/piecewise.py
+++ b/sympy/functions/elementary/piecewise.py
@@ -986,53 +986,8 @@ def piecewise_fold(expr):
             else:
                 new_args.append((e, c))
     else:
-        from sympy.utilities.iterables import cartes, sift, common_prefix
-        # Given
-        #     P1 = Piecewise((e11, c1), (e12, c2), A)
-        #     P2 = Piecewise((e21, c1), (e22, c2), B)
-        #     ...
-        # the folding of f(P1, P2) is trivially
-        # Piecewise(
-        #   (f(e11, e21), c1),
-        #   (f(e12, e22), c2),
-        #   (f(Piecewise(A), Piecewise(B)), True))
-        # Certain objects end up rewriting themselves as thus, so
-        # we do that grouping before the more generic folding.
-        # The following applies this idea when f = Add or f = Mul
-        # (and the expression is commutative).
-        if expr.is_Add or expr.is_Mul and expr.is_commutative:
-            p, args = sift(expr.args, lambda x: x.is_Piecewise, binary=True)
-            pc = sift(p, lambda x: x.args[0].cond)
-            for c in pc:
-                if len(pc[c]) > 1:
-                    pargs = [list(i.args) for i in pc[c]]
-                    # the first one is the same; there may be more
-                    com = common_prefix(*[
-                        [i.cond for i in j] for j in pargs])
-                    n = len(com)
-                    collected = []
-                    for i in range(n):
-                        collected.append((
-                            expr.func(*[ai[i].expr for ai in pargs]),
-                            com[i]))
-                    remains = []
-                    for a in pargs:
-                        if n == len(a):  # no more args
-                            continue
-                        if a[n].cond == True:  # no longer Piecewise
-                            remains.append(a[n].expr)
-                        else:  # restore the remaining Piecewise
-                            remains.append(
-                                Piecewise(*a[n:], evaluate=False))
-                    if remains:
-                        collected.append((expr.func(*remains), True))
-                    args.append(Piecewise(*collected, evaluate=False))
-                    continue
-                args.extend(pc[c])
-        else:
-            args = expr.args
-        # fold
-        folded = list(map(piecewise_fold, args))
+        from sympy.utilities.iterables import cartes
+        folded = list(map(piecewise_fold, expr.args))
         for ec in cartes(*[
                 (i.args if isinstance(i, Piecewise) else
                  [(i, true)]) for i in folded]):


Test patch:
diff --git a/sympy/concrete/tests/test_sums_products.py b/sympy/concrete/tests/test_sums_products.py
index 6fc0e50b74..e68ed983eb 100644
--- a/sympy/concrete/tests/test_sums_products.py
+++ b/sympy/concrete/tests/test_sums_products.py
@@ -1012,39 +1012,17 @@ def test_issue_10156():
     assert e.factor() == \
         8*y**3*Sum(x, (x, 1, 3))*Sum(x**2, (x, 1, 9))
 
-
 def test_issue_14112():
     assert Sum((-1)**n/sqrt(n), (n, 1, oo)).is_absolutely_convergent() is S.false
     assert Sum((-1)**(2*n)/n, (n, 1, oo)).is_convergent() is S.false
     assert Sum((-2)**n + (-3)**n, (n, 1, oo)).is_convergent() is S.false
 
-
 def test_sin_times_absolutely_convergent():
     assert Sum(sin(n) / n**3, (n, 1, oo)).is_convergent() is S.true
     assert Sum(sin(n) * log(n) / n**3, (n, 1, oo)).is_convergent() is S.true
 
-
 def test_issue_14111():
     assert Sum(1/log(log(n)), (n, 22, oo)).is_convergent() is S.false
 
-
 def test_issue_14484():
     raises(NotImplementedError, lambda: Sum(sin(n)/log(log(n)), (n, 22, oo)).is_convergent())
-
-
-def test_issue_14640():
-    i, n = symbols("i n", integer=True)
-    a, b, c = symbols("a b c")
-
-    assert Sum(a**-i/(a - b), (i, 0, n)).doit() == Sum(
-        1/(a*a**i - a**i*b), (i, 0, n)).doit() == Piecewise(
-            (n + 1, Eq(1/a, 1)),
-            ((-a**(-n - 1) + 1)/(1 - 1/a), True))/(a - b)
-
-    assert Sum((b*a**i - c*a**i)**-2, (i, 0, n)).doit() == Piecewise(
-        (n + 1, Eq(a**(-2), 1)),
-        ((-a**(-2*n - 2) + 1)/(1 - 1/a**2), True))/(b - c)**2
-
-    s = Sum(i*(a**(n - i) - b**(n - i))/(a - b), (i, 0, n)).doit()
-    assert not s.has(Sum)
-    assert s.subs({a: 2, b: 3, n: 5}) == 122
diff --git a/sympy/functions/elementary/tests/test_complexes.py b/sympy/functions/elementary/tests/test_complexes.py
index d55e16f8b3..14b2128402 100644
--- a/sympy/functions/elementary/tests/test_complexes.py
+++ b/sympy/functions/elementary/tests/test_complexes.py
@@ -851,6 +851,9 @@ def test_principal_branch():
     assert principal_branch(exp_polar(3*pi*I)*x, 2*pi) == \
         principal_branch(exp_polar(I*pi)*x, 2*pi)
     assert principal_branch(neg*exp_polar(pi*I), 2*pi) == neg*exp_polar(-I*pi)
+    # related to issue #14692
+    assert principal_branch(exp_polar(-I*pi/2)/polar_lift(neg), 2*pi) == \
+        exp_polar(-I*pi/2)/neg
 
     assert N_equals(principal_branch((1 + I)**2, 2*pi), 2*I)
     assert N_equals(principal_branch((1 + I)**2, 3*pi), 2*I)
diff --git a/sympy/functions/elementary/tests/test_piecewise.py b/sympy/functions/elementary/tests/test_piecewise.py
index 14b6ab9bff..281828005f 100644
--- a/sympy/functions/elementary/tests/test_piecewise.py
+++ b/sympy/functions/elementary/tests/test_piecewise.py
@@ -3,7 +3,7 @@
     Integral, integrate, Interval, lambdify, log, Max, Min, oo, Or, pi,
     Piecewise, piecewise_fold, Rational, solve, symbols, transpose,
     cos, sin, exp, Abs, Ne, Not, Symbol, S, sqrt, Tuple, zoo,
-    factor_terms, DiracDelta, Heaviside, Add, Mul, factorial)
+    factor_terms, DiracDelta, Heaviside)
 from sympy.printing import srepr
 from sympy.utilities.pytest import XFAIL, raises
 
@@ -1080,21 +1080,3 @@ def _ITE(*args):
 
 def test_issue_14052():
     assert integrate(abs(sin(x)), (x, 0, 2*pi)) == 4
-
-
-def test_issue_14240():
-    assert piecewise_fold(
-        Piecewise((1, a), (2, b), (4, True)) +
-        Piecewise((8, a), (16, True))
-        ) == Piecewise((9, a), (18, b), (20, True))
-    assert piecewise_fold(
-        Piecewise((2, a), (3, b), (5, True)) *
-        Piecewise((7, a), (11, True))
-        ) == Piecewise((14, a), (33, b), (55, True))
-    # these will hang if naive folding is used
-    assert piecewise_fold(Add(*[
-        Piecewise((i, a), (0, True)) for i in range(40)])
-        ) == Piecewise((780, a), (0, True))
-    assert piecewise_fold(Mul(*[
-        Piecewise((i, a), (0, True)) for i in range(1, 41)])
-        ) == Piecewise((factorial(40), a), (0, True))
diff --git a/sympy/integrals/tests/test_transforms.py b/sympy/integrals/tests/test_transforms.py
index af8c3d224b..31a9fcb542 100644
--- a/sympy/integrals/tests/test_transforms.py
+++ b/sympy/integrals/tests/test_transforms.py
@@ -802,3 +802,9 @@ def test_issue_8514():
 def test_issue_12591():
     x, y = symbols("x y", real=True)
     assert fourier_transform(exp(x), x, y) == FourierTransform(exp(x), x, y)
+
+
+def test_issue_14692():
+    b = Symbol('b', negative=True)
+    assert laplace_transform(1/(I*x - b), x, s) == \
+        (-I*exp(I*b*s)*expint(1, b*s*exp_polar(I*pi/2)), 0, True)