Repository: sympy/sympy

Issue:
Integral of tan(x) from 0 to pi/2 returns complex infinity
``` python
In [23]: integrate(tan(x), (x, 0, pi/2))
Out[23]: zoo
```

why complex? (`x` has `real=True` assumption)


Discussion:

Patch:
diff --git a/sympy/core/expr.py b/sympy/core/expr.py
index bda6b2ca87..421e6cd8e6 100644
--- a/sympy/core/expr.py
+++ b/sympy/core/expr.py
@@ -807,7 +807,8 @@ def _eval_interval(self, x, a, b):
 
         self.subs(x, b) - self.subs(x, a),
 
-        possibly using limit() if NaN is returned from subs.
+        possibly using limit() if NaN is returned from subs, or if
+        singularities are found between a and b.
 
         If b or a is None, it only evaluates -self.subs(x, a) or self.subs(b, x),
         respectively.
@@ -816,6 +817,7 @@ def _eval_interval(self, x, a, b):
         from sympy.series import limit, Limit
         from sympy.solvers.solveset import solveset
         from sympy.sets.sets import Interval
+        from sympy.functions.elementary.exponential import log
 
         if (a is None and b is None):
             raise ValueError('Both interval ends cannot be None.')
@@ -861,11 +863,21 @@ def _eval_interval(self, x, a, b):
                 domain = Interval(a, b)
             else:
                 domain = Interval(b, a)
-            singularities = list(solveset(self.cancel().as_numer_denom()[1], x, domain = domain))
+            # check the singularities of self within the interval
+            singularities = solveset(self.cancel().as_numer_denom()[1], x,
+                domain=domain)
+            for logterm in self.atoms(log):
+                singularities = singularities | solveset(logterm.args[0], x,
+                    domain=domain)
             for s in singularities:
-                if a < s < b:
+                if value is S.NaN:
+                    # no need to keep adding, it will stay NaN
+                    break
+                if not s.is_comparable:
+                    continue
+                if (a < s) == (s < b) == True:
                     value += -limit(self, x, s, "+") + limit(self, x, s, "-")
-                elif b < s < a:
+                elif (b < s) == (s < a) == True:
                     value += limit(self, x, s, "+") - limit(self, x, s, "-")
 
         return value


Test patch:
diff --git a/sympy/integrals/tests/test_integrals.py b/sympy/integrals/tests/test_integrals.py
index 7a9a83164e..4e160debdb 100644
--- a/sympy/integrals/tests/test_integrals.py
+++ b/sympy/integrals/tests/test_integrals.py
@@ -1276,3 +1276,15 @@ def test_issue_14064():
 def test_issue_14027():
     assert integrate(1/(1 + exp(x - S(1)/2)/(1 + exp(x))), x) == \
         x - exp(S(1)/2)*log(exp(x) + exp(S(1)/2)/(1 + exp(S(1)/2)))/(exp(S(1)/2) + E)
+
+def test_issue_8170():
+    assert integrate(tan(x), (x, 0, pi/2)) == S.Infinity
+
+def test_issue_8440_14040():
+    assert integrate(1/x, (x, -1, 1)) == S.NaN
+    assert integrate(1/(x + 1), (x, -2, 3)) == S.NaN
+
+def test_issue_14096():
+    assert integrate(1/(x + y)**2, (x, 0, 1)) == -1/(y + 1) + 1/y
+    assert integrate(1/(1 + x + y + z)**2, (x, 0, 1), (y, 0, 1), (z, 0, 1)) == \
+        -4*log(4) - 6*log(2) + 9*log(3)