Repository: sympy/sympy

Issue:
Issue with `_eval_as_leading_term` function for inverse trig/hyperbolic functions
Consider the following limit 
```
>>> limit(atan(sin(x)/x), x, 0)
pi/4
```
Although we get the correct answer, I can see that we get the answer out of gruntz for this 
```
>>> gruntz(atan(sin(x)/x), x, 0)
pi/4
```
But this case should be addressed through the `_eval_as_leading_term` as pointed out through this comment (https://github.com/sympy/sympy/pull/25763#discussion_r1348583391) and we don't need to involve `gruntz` here. Hence as of now we have 
```
>>> atan(sin(x)/x).as_leading_term(x)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\Users\91989\sympy\sympy\sympy\core\cache.py", line 72, in wrapper
    retval = cfunc(*args, **kwargs)
  File "C:\Users\91989\sympy\sympy\sympy\core\expr.py", line 3490, in as_leading_term
    obj = self._eval_as_leading_term(x, logx=logx, cdir=cdir)
  File "C:\Users\91989\sympy\sympy\sympy\functions\elementary\trigonometric.py", line 2686, in _eval_as_leading_term
    raise PoleError()
sympy.core.function.PoleError
```
But we should expect `pi/4` in this case. 
Hence a fix is expected here and tests should be added to check the leading term outputs for all inverse trig/hyperbolic functions
```
    def _eval_as_leading_term(self, x, logx=None, cdir=0):  # atan
        arg = self.args[0]
        x0 = arg.subs(x, 0).cancel()
        if x0 is S.NaN:
            raise PoleError()
```

Discussion:

Patch:
diff --git a/.mailmap b/.mailmap
index 1f673809c7..cbc670d32c 100644
--- a/.mailmap
+++ b/.mailmap
@@ -1224,6 +1224,7 @@ Sagar Bharadwaj <sagarbharadwaj50@gmail.com>
 Sagar231 <sagarfeb298@gmail.com>
 Sahil Shekhawat <sahilshekhawat01@gmail.com>
 Sai Nikhil <tsnlegend@gmail.com>
+Saicharan <62512681+saicharan2804@users.noreply.github.com>
 Saicharan <saicharanhahaha@gmail.com>
 Saikat Das <saikatdchhe@gmail.com>
 Saket Kumar Singh <saketkumar1202@gmail.com>
diff --git a/sympy/functions/elementary/hyperbolic.py b/sympy/functions/elementary/hyperbolic.py
index d3ce7eff1c..845fe59128 100644
--- a/sympy/functions/elementary/hyperbolic.py
+++ b/sympy/functions/elementary/hyperbolic.py
@@ -1298,6 +1298,14 @@ def _eval_as_leading_term(self, x, logx=None, cdir=0):  # asinh
         x0 = arg.subs(x, 0).cancel()
         if x0.is_zero:
             return arg.as_leading_term(x)
+
+        if x0 is S.NaN:
+            expr = self.func(arg.as_leading_term(x))
+            if expr.is_finite:
+                return expr
+            else:
+                return self
+
         # Handling branch points
         if x0 in (-I, I, S.ComplexInfinity):
             return self.rewrite(log)._eval_as_leading_term(x, logx=logx, cdir=cdir)
@@ -1481,6 +1489,14 @@ def _eval_as_leading_term(self, x, logx=None, cdir=0):  # acosh
         # Handling branch points
         if x0 in (-S.One, S.Zero, S.One, S.ComplexInfinity):
             return self.rewrite(log)._eval_as_leading_term(x, logx=logx, cdir=cdir)
+
+        if x0 is S.NaN:
+            expr = self.func(arg.as_leading_term(x))
+            if expr.is_finite:
+                return expr
+            else:
+                return self
+
         # Handling points lying on branch cuts (-oo, 1)
         if (x0 - 1).is_negative:
             ndir = arg.dir(x, cdir if cdir else 1)
@@ -1640,6 +1656,13 @@ def _eval_as_leading_term(self, x, logx=None, cdir=0):  # atanh
         x0 = arg.subs(x, 0).cancel()
         if x0.is_zero:
             return arg.as_leading_term(x)
+        if x0 is S.NaN:
+            expr = self.func(arg.as_leading_term(x))
+            if expr.is_finite:
+                return expr
+            else:
+                return self
+
         # Handling branch points
         if x0 in (-S.One, S.One, S.ComplexInfinity):
             return self.rewrite(log)._eval_as_leading_term(x, logx=logx, cdir=cdir)
@@ -1785,6 +1808,13 @@ def _eval_as_leading_term(self, x, logx=None, cdir=0):  # acoth
         x0 = arg.subs(x, 0).cancel()
         if x0 is S.ComplexInfinity:
             return (1/arg).as_leading_term(x)
+        if x0 is S.NaN:
+            expr = self.func(arg.as_leading_term(x))
+            if expr.is_finite:
+                return expr
+            else:
+                return self
+
         # Handling branch points
         if x0 in (-S.One, S.One, S.Zero):
             return self.rewrite(log)._eval_as_leading_term(x, logx=logx, cdir=cdir)
@@ -1951,6 +1981,14 @@ def _eval_as_leading_term(self, x, logx=None, cdir=0):  # asech
         # Handling branch points
         if x0 in (-S.One, S.Zero, S.One, S.ComplexInfinity):
             return self.rewrite(log)._eval_as_leading_term(x, logx=logx, cdir=cdir)
+
+        if x0 is S.NaN:
+            expr = self.func(arg.as_leading_term(x))
+            if expr.is_finite:
+                return expr
+            else:
+                return self
+
         # Handling points lying on branch cuts (-oo, 0] U (1, oo)
         if x0.is_negative or (1 - x0).is_negative:
             ndir = arg.dir(x, cdir if cdir else 1)
@@ -2142,6 +2180,14 @@ def _eval_as_leading_term(self, x, logx=None, cdir=0):  # acsch
         # Handling branch points
         if x0 in (-I, I, S.Zero):
             return self.rewrite(log)._eval_as_leading_term(x, logx=logx, cdir=cdir)
+
+        if x0 is S.NaN:
+            expr = self.func(arg.as_leading_term(x))
+            if expr.is_finite:
+                return expr
+            else:
+                return self
+
         if x0 is S.ComplexInfinity:
             return (1/arg).as_leading_term(x)
         # Handling points lying on branch cuts (-I, I)
diff --git a/sympy/functions/elementary/trigonometric.py b/sympy/functions/elementary/trigonometric.py
index 369d7666ee..d350c948cb 100644
--- a/sympy/functions/elementary/trigonometric.py
+++ b/sympy/functions/elementary/trigonometric.py
@@ -2223,7 +2223,7 @@ def _eval_as_leading_term(self, x, logx=None, cdir=0):  # asin
         arg = self.args[0]
         x0 = arg.subs(x, 0).cancel()
         if x0 is S.NaN:
-            raise PoleError()
+            return self.func(arg.as_leading_term(x))
         if x0.is_zero:
             return arg.as_leading_term(x)
 
@@ -2442,7 +2442,7 @@ def _eval_as_leading_term(self, x, logx=None, cdir=0):  # acos
         arg = self.args[0]
         x0 = arg.subs(x, 0).cancel()
         if x0 is S.NaN:
-            raise PoleError()
+            return self.func(arg.as_leading_term(x))
         # Handling branch points
         if x0 == 1:
             return sqrt(2)*sqrt((S.One - arg).as_leading_term(x))
@@ -2683,7 +2683,7 @@ def _eval_as_leading_term(self, x, logx=None, cdir=0):  # atan
         arg = self.args[0]
         x0 = arg.subs(x, 0).cancel()
         if x0 is S.NaN:
-            raise PoleError()
+            return self.func(arg.as_leading_term(x))
         if x0.is_zero:
             return arg.as_leading_term(x)
         # Handling branch points
@@ -2900,7 +2900,7 @@ def _eval_as_leading_term(self, x, logx=None, cdir=0):  # acot
         arg = self.args[0]
         x0 = arg.subs(x, 0).cancel()
         if x0 is S.NaN:
-            raise PoleError()
+            return self.func(arg.as_leading_term(x))
         if x0 is S.ComplexInfinity:
             return (1/arg).as_leading_term(x)
         # Handling branch points
@@ -3115,7 +3115,7 @@ def _eval_as_leading_term(self, x, logx=None, cdir=0):  # asec
         arg = self.args[0]
         x0 = arg.subs(x, 0).cancel()
         if x0 is S.NaN:
-            raise PoleError()
+            return self.func(arg.as_leading_term(x))
         # Handling branch points
         if x0 == 1:
             return sqrt(2)*sqrt((arg - S.One).as_leading_term(x))
@@ -3325,7 +3325,7 @@ def _eval_as_leading_term(self, x, logx=None, cdir=0):  # acsc
         arg = self.args[0]
         x0 = arg.subs(x, 0).cancel()
         if x0 is S.NaN:
-            raise PoleError()
+            return self.func(arg.as_leading_term(x))
         # Handling branch points
         if x0 in (-S.One, S.One, S.Zero):
             return self.rewrite(log)._eval_as_leading_term(x, logx=logx, cdir=cdir).expand()


Test patch:
diff --git a/sympy/functions/elementary/tests/test_hyperbolic.py b/sympy/functions/elementary/tests/test_hyperbolic.py
index 642d0723d9..5b4365d821 100644
--- a/sympy/functions/elementary/tests/test_hyperbolic.py
+++ b/sympy/functions/elementary/tests/test_hyperbolic.py
@@ -11,7 +11,7 @@
 from sympy.series.order import O
 
 from sympy.core.expr import unchanged
-from sympy.core.function import ArgumentIndexError
+from sympy.core.function import ArgumentIndexError, PoleError
 from sympy.testing.pytest import raises
 
 
@@ -1512,3 +1512,31 @@ def test_sign_assumptions():
     assert sech(p).is_positive is True
     assert coth(n).is_negative is True
     assert coth(p).is_positive is True
+
+
+def test_issue_25847():
+    x = Symbol('x')
+
+    #atanh
+    assert atanh(sin(x)/x).as_leading_term(x) == atanh(sin(x)/x)
+    raises(PoleError, lambda: atanh(exp(1/x)).as_leading_term(x))
+
+    #asinh
+    assert asinh(sin(x)/x).as_leading_term(x) == log(1 + sqrt(2))
+    raises(PoleError, lambda: asinh(exp(1/x)).as_leading_term(x))
+
+    #acosh
+    assert acosh(sin(x)/x).as_leading_term(x) == 0
+    raises(PoleError, lambda: acosh(exp(1/x)).as_leading_term(x))
+
+    #acoth
+    assert acoth(sin(x)/x).as_leading_term(x) == acoth(sin(x)/x)
+    raises(PoleError, lambda: acoth(exp(1/x)).as_leading_term(x))
+
+    #asech
+    assert asech(sinh(x)/x).as_leading_term(x) == 0
+    raises(PoleError, lambda: asech(exp(1/x)).as_leading_term(x))
+
+    #acsch
+    assert acsch(sin(x)/x).as_leading_term(x) == log(1 + sqrt(2))
+    raises(PoleError, lambda: acsch(exp(1/x)).as_leading_term(x))
diff --git a/sympy/functions/elementary/tests/test_trigonometric.py b/sympy/functions/elementary/tests/test_trigonometric.py
index bce5950116..4541c0a760 100644
--- a/sympy/functions/elementary/tests/test_trigonometric.py
+++ b/sympy/functions/elementary/tests/test_trigonometric.py
@@ -24,7 +24,7 @@
 from sympy.sets.sets import (FiniteSet, Interval)
 from sympy.simplify.simplify import simplify
 from sympy.core.expr import unchanged
-from sympy.core.function import ArgumentIndexError
+from sympy.core.function import ArgumentIndexError, PoleError
 from sympy.core.relational import Ne, Eq
 from sympy.functions.elementary.piecewise import Piecewise
 from sympy.sets.setexpr import SetExpr
@@ -2166,3 +2166,29 @@ def test_issue_25833():
     assert limit(atan(x**2), x, oo) == pi/2
     assert limit(atan(x**2 - 1), x, oo) == pi/2
     assert limit(atan(log(2**x)/log(2*x)), x, oo) == pi/2
+
+
+def test_issue_25847():
+    #atan
+    assert atan(sin(x)/x).as_leading_term(x) == pi/4
+    raises(PoleError, lambda: atan(exp(1/x)).as_leading_term(x))
+
+    #asin
+    assert asin(sin(x)/x).as_leading_term(x) == pi/2
+    raises(PoleError, lambda: asin(exp(1/x)).as_leading_term(x))
+
+    #acos
+    assert acos(sin(x)/x).as_leading_term(x) == 0
+    raises(PoleError, lambda: acos(exp(1/x)).as_leading_term(x))
+
+    #acot
+    assert acot(sin(x)/x).as_leading_term(x) == pi/4
+    raises(PoleError, lambda: acot(exp(1/x)).as_leading_term(x))
+
+    #asec
+    assert asec(sin(x)/x).as_leading_term(x) == 0
+    raises(PoleError, lambda: asec(exp(1/x)).as_leading_term(x))
+
+    #acsc
+    assert acsc(sin(x)/x).as_leading_term(x) == pi/2
+    raises(PoleError, lambda: acsc(exp(1/x)).as_leading_term(x))
diff --git a/sympy/series/tests/test_limits.py b/sympy/series/tests/test_limits.py
index 78b9db9e61..7f34e56fef 100644
--- a/sympy/series/tests/test_limits.py
+++ b/sympy/series/tests/test_limits.py
@@ -10,7 +10,7 @@
 from sympy.functions.combinatorial.factorials import (binomial, factorial, subfactorial)
 from sympy.functions.elementary.complexes import (Abs, re, sign)
 from sympy.functions.elementary.exponential import (LambertW, exp, log)
-from sympy.functions.elementary.hyperbolic import (acosh, acoth, acsch, asech, atanh, sinh, tanh)
+from sympy.functions.elementary.hyperbolic import (atanh, asinh, acosh, acoth, acsch, asech, tanh, sinh)
 from sympy.functions.elementary.integers import (ceiling, floor, frac)
 from sympy.functions.elementary.miscellaneous import (cbrt, real_root, sqrt)
 from sympy.functions.elementary.piecewise import Piecewise
@@ -1331,3 +1331,65 @@ def test_issue_25582():
     assert limit(acot(exp(x)), x, oo, '-') == 0
     assert limit(asec(exp(x)), x, oo, '-') == pi/2
     assert limit(acsc(exp(x)), x, oo, '-') == 0
+
+
+def test_issue_25847():
+    #atan
+    assert limit(atan(sin(x)/x), x, 0, '+-') == pi/4
+    assert limit(atan(exp(1/x)), x, 0, '+') == pi/2
+    assert limit(atan(exp(1/x)), x, 0, '-') == 0
+
+    #asin
+    assert limit(asin(sin(x)/x), x, 0, '+-') == pi/2
+    assert limit(asin(exp(1/x)), x, 0, '+') == -oo*I
+    assert limit(asin(exp(1/x)), x, 0, '-') == 0
+
+    #acos
+    assert limit(acos(sin(x)/x), x, 0, '+-') == 0
+    assert limit(acos(exp(1/x)), x, 0, '+') == oo*I
+    assert limit(acos(exp(1/x)), x, 0, '-') == pi/2
+
+    #acot
+    assert limit(acot(sin(x)/x), x, 0, '+-') == pi/4
+    assert limit(acot(exp(1/x)), x, 0, '+') == 0
+    assert limit(acot(exp(1/x)), x, 0, '-') == pi/2
+
+    #asec
+    assert limit(asec(sin(x)/x), x, 0, '+-') == 0
+    assert limit(asec(exp(1/x)), x, 0, '+') == pi/2
+    assert limit(asec(exp(1/x)), x, 0, '-') == oo*I
+
+    #acsc
+    assert limit(acsc(sin(x)/x), x, 0, '+-') == pi/2
+    assert limit(acsc(exp(1/x)), x, 0, '+') == 0
+    assert limit(acsc(exp(1/x)), x, 0, '-') == -oo*I
+
+    #atanh
+    assert limit(atanh(sin(x)/x), x, 0, '+-') == oo
+    assert limit(atanh(exp(1/x)), x, 0, '+') == -I*pi/2
+    assert limit(atanh(exp(1/x)), x, 0, '-') == 0
+
+    #asinh
+    assert limit(asinh(sin(x)/x), x, 0, '+-') == log(1 + sqrt(2))
+    assert limit(asinh(exp(1/x)), x, 0, '+') == oo
+    assert limit(asinh(exp(1/x)), x, 0, '-') == 0
+
+    #acosh
+    assert limit(acosh(sin(x)/x), x, 0, '+-') == 0
+    assert limit(acosh(exp(1/x)), x, 0, '+') == oo
+    assert limit(acosh(exp(1/x)), x, 0, '-') == I*pi/2
+
+    #acoth
+    assert limit(acoth(sin(x)/x), x, 0, '+-') == oo
+    assert limit(acoth(exp(1/x)), x, 0, '+') == 0
+    assert limit(acoth(exp(1/x)), x, 0, '-') == -I*pi/2
+
+    #asech
+    assert limit(asech(sin(x)/x), x, 0, '+-') == 0
+    assert limit(asech(exp(1/x)), x, 0, '+') == I*pi/2
+    assert limit(asech(exp(1/x)), x, 0, '-') == oo
+
+    #acsch
+    assert limit(acsch(sin(x)/x), x, 0, '+-') == log(1 + sqrt(2))
+    assert limit(acsch(exp(1/x)), x, 0, '+') == 0
+    assert limit(acsch(exp(1/x)), x, 0, '-') == oo