Repository: sympy/sympy

Issue:
Bug in limit
`limit(cos (x)**(1/x),x,oo)` should give `AccumBounds` instead of `1`.

Discussion:

Patch:
diff --git a/sympy/functions/elementary/exponential.py b/sympy/functions/elementary/exponential.py
index 64ddc04c51..3e0044e995 100644
--- a/sympy/functions/elementary/exponential.py
+++ b/sympy/functions/elementary/exponential.py
@@ -529,8 +529,18 @@ def _taylor(self, x, n):
         return Add(*l)
 
     def _eval_as_leading_term(self, x, logx=None, cdir=0):
+        from sympy.calculus.util import AccumBounds
         arg = self.args[0].cancel().as_leading_term(x, logx=logx)
         arg0 = arg.subs(x, 0)
+        if arg is S.NaN:
+            return S.NaN
+        if isinstance(arg0, AccumBounds):
+            # This check addresses a corner case involving AccumBounds.
+            # if isinstance(arg, AccumBounds) is True, then arg0 can either be 0,
+            # AccumBounds(-oo, 0) or AccumBounds(-oo, oo).
+            # Check out function: test_issue_18473() in test_exponential.py and
+            # test_limits.py for more information.
+            return exp(arg0)
         if arg0 is S.NaN:
             arg0 = arg.limit(x, 0)
         if arg0.is_infinite is False:
@@ -701,8 +711,10 @@ def eval(cls, arg, base=None):
         elif isinstance(arg, AccumBounds):
             if arg.min.is_positive:
                 return AccumBounds(log(arg.min), log(arg.max))
+            elif arg.min.is_zero:
+                return AccumBounds(S.NegativeInfinity, log(arg.max))
             else:
-                return
+                return S.NaN
         elif isinstance(arg, SetExpr):
             return arg._eval_func(cls)
 
@@ -1041,6 +1053,7 @@ def mul(d1, d2):
         return res + Order(x**n, x)
 
     def _eval_as_leading_term(self, x, logx=None, cdir=0):
+        from sympy.calculus.util import AccumBounds
         arg0 = self.args[0].together()
 
         arg = arg0.as_leading_term(x, cdir=cdir)
@@ -1055,6 +1068,8 @@ def _eval_as_leading_term(self, x, logx=None, cdir=0):
             cdir = arg0.dir(x, cdir)
         if x0.is_real and x0.is_negative and im(cdir).is_negative:
             return self.func(x0) - 2*I*S.Pi
+        if isinstance(arg, AccumBounds):
+            return log(arg)
         return self.func(arg)
 
 
diff --git a/sympy/series/limits.py b/sympy/series/limits.py
index 3e1470ad4a..e48adc9d75 100644
--- a/sympy/series/limits.py
+++ b/sympy/series/limits.py
@@ -315,7 +315,7 @@ def set_signs(expr):
         else:
             if isinstance(coeff, AccumBounds) and ex == S.Zero:
                 return coeff
-            if coeff.has(S.Infinity, S.NegativeInfinity, S.ComplexInfinity):
+            if coeff.has(S.Infinity, S.NegativeInfinity, S.ComplexInfinity, S.NaN):
                 return self
             if not coeff.has(z):
                 if ex.is_positive:


Test patch:
diff --git a/sympy/functions/elementary/tests/test_exponential.py b/sympy/functions/elementary/tests/test_exponential.py
index cbc0f15a62..9b53834298 100644
--- a/sympy/functions/elementary/tests/test_exponential.py
+++ b/sympy/functions/elementary/tests/test_exponential.py
@@ -11,7 +11,7 @@
 from sympy.functions.elementary.exponential import (LambertW, exp, exp_polar, log)
 from sympy.functions.elementary.hyperbolic import (cosh, sinh, tanh)
 from sympy.functions.elementary.miscellaneous import sqrt
-from sympy.functions.elementary.trigonometric import (cos, sin)
+from sympy.functions.elementary.trigonometric import (cos, sin, tan)
 from sympy.matrices.expressions.matexpr import MatrixSymbol
 from sympy.polys.polytools import gcd
 from sympy.series.order import O
@@ -536,6 +536,11 @@ def test_log_simplify():
 
 def test_log_AccumBounds():
     assert log(AccumBounds(1, E)) == AccumBounds(0, 1)
+    assert log(AccumBounds(0, E)) == AccumBounds(-oo, 1)
+    assert log(AccumBounds(-1, E)) == S.NaN
+    assert log(AccumBounds(0, oo)) == AccumBounds(-oo, oo)
+    assert log(AccumBounds(-oo, 0)) == S.NaN
+    assert log(AccumBounds(-oo, oo)) == S.NaN
 
 
 @_both_exp_pow
@@ -729,3 +734,20 @@ def test_log_expand_factor():
 def test_issue_9116():
     n = Symbol('n', positive=True, integer=True)
     assert log(n).is_nonnegative is True
+
+
+def test_issue_18473():
+    assert exp(x*log(cos(1/x))).as_leading_term(x) == S.NaN
+    assert exp(x*log(tan(1/x))).as_leading_term(x) == S.NaN
+    assert log(cos(1/x)).as_leading_term(x) == S.NaN
+    assert log(tan(1/x)).as_leading_term(x) == S.NaN
+    assert log(cos(1/x) + 2).as_leading_term(x) == AccumBounds(0, log(3))
+    assert exp(x*log(cos(1/x) + 2)).as_leading_term(x) == 1
+    assert log(cos(1/x) - 2).as_leading_term(x) == S.NaN
+    assert exp(x*log(cos(1/x) - 2)).as_leading_term(x) == S.NaN
+    assert log(cos(1/x) + 1).as_leading_term(x) == AccumBounds(-oo, log(2))
+    assert exp(x*log(cos(1/x) + 1)).as_leading_term(x) == AccumBounds(0, 1)
+    assert log(sin(1/x)**2).as_leading_term(x) == AccumBounds(-oo, 0)
+    assert exp(x*log(sin(1/x)**2)).as_leading_term(x) == AccumBounds(0, 1)
+    assert log(tan(1/x)**2).as_leading_term(x) == AccumBounds(-oo, oo)
+    assert exp(2*x*(log(tan(1/x)**2))).as_leading_term(x) == AccumBounds(0, oo)
diff --git a/sympy/series/tests/test_limits.py b/sympy/series/tests/test_limits.py
index 6cb5c65c09..d3d0ee0e10 100644
--- a/sympy/series/tests/test_limits.py
+++ b/sympy/series/tests/test_limits.py
@@ -929,6 +929,18 @@ def test_issue_18452():
     assert limit(abs(log(x))**x, x, 0, "-") == 1
 
 
+def test_issue_18473():
+    assert limit(sin(x)**(1/x), x, oo) == Limit(sin(x)**(1/x), x, oo, dir='-')
+    assert limit(cos(x)**(1/x), x, oo) == Limit(cos(x)**(1/x), x, oo, dir='-')
+    assert limit(tan(x)**(1/x), x, oo) == Limit(tan(x)**(1/x), x, oo, dir='-')
+    assert limit((cos(x) + 2)**(1/x), x, oo) == 1
+    assert limit((sin(x) + 10)**(1/x), x, oo) == 1
+    assert limit((cos(x) - 2)**(1/x), x, oo) == Limit((cos(x) - 2)**(1/x), x, oo, dir='-')
+    assert limit((cos(x) + 1)**(1/x), x, oo) == AccumBounds(0, 1)
+    assert limit((tan(x)**2)**(2/x) , x, oo) == AccumBounds(0, oo)
+    assert limit((sin(x)**2)**(1/x), x, oo) == AccumBounds(0, 1)
+
+
 def test_issue_18482():
     assert limit((2*exp(3*x)/(exp(2*x) + 1))**(1/x), x, oo) == exp(1)