Repository: sympy/sympy
Pull request: [GSoC] Functions: Fixes limit evaluations related to uppergamma and besselk function
Fixes: #13571 
Fixes: #14874 

#### Brief description of what is fixed or changed

  1) Adds `_eval_is_meromorphic` method and  `_eval_aseries` to `class lowergamma` 
  2) Adds  `_eval_is_meromorphic` method and `_eval_rewrite_as_tractable` method to `class uppergamma`
  3) Rectifies `eval` method of `class besselk`


#### Other Comments
Regression Tests have been added.


#### Release Notes


<!-- BEGIN RELEASE NOTES -->
* functions
  * Adds `_eval_is_meromorphic` method and  `_eval_aseries` to `class lowergamma` 
  * Adds  `_eval_is_meromorphic` method and `_eval_rewrite_as_tractable` method to `class uppergamma`
  * Rectifies `eval` method of `class besselk`
<!-- END RELEASE NOTES -->

Problem statement:
Incorrect limit of uppergamma(n, 1) / gamma(n)
    >>> from sympy import *
    >>> from sympy.abc import n
    >>> limit(uppergamma(n, 1) / gamma(n), n, oo)
    0

The answer should be 1.

Limit x --> oo for besselk
When I try

    from sympy import symbols, besselk, limit, oo
    x = symbols("x", real=True)
    limit(besselk(0, x), x, oo)

I obtain the following

    besselk(0, oo)

instead of obtaining 0.

Hints from issue discussion:
How can I help in this issue ?

Commit message: Fixes limit evaluations related to uppergamma and besselk function

Patch to review:
diff --git a/sympy/functions/special/bessel.py b/sympy/functions/special/bessel.py
index ab04eeea24cf..aba153792479 100644
--- a/sympy/functions/special/bessel.py
+++ b/sympy/functions/special/bessel.py
@@ -464,6 +464,8 @@ def eval(cls, nu, z):
             return S.Zero
 
         if nu.is_integer:
+            if z is S.Infinity:
+                return S.Zero
             if nu.could_extract_minus_sign():
                 return besselk(-nu, z)
 
diff --git a/sympy/functions/special/gamma_functions.py b/sympy/functions/special/gamma_functions.py
index 888a02b2e9dd..f5ef7a0f914a 100644
--- a/sympy/functions/special/gamma_functions.py
+++ b/sympy/functions/special/gamma_functions.py
@@ -364,6 +364,16 @@ def _eval_conjugate(self):
         if x not in (S.Zero, S.NegativeInfinity):
             return self.func(self.args[0].conjugate(), x.conjugate())
 
+    def _eval_aseries(self, n, args0, x, logx):
+        from sympy import O
+        s, z = self.args
+        if args0[0] is S.Infinity and not z.has(x):
+            coeff = z**s*exp(-z)
+            sum_expr = sum(z**k/rf(s, k + 1) for k in range(n - 1))
+            o = O(s**(-n - 1))
+            return coeff*sum_expr + o
+        return super()._eval_aseries(n, args0, x, logx)
+
     def _eval_rewrite_as_uppergamma(self, s, x, **kwargs):
         return gamma(s) - uppergamma(s, x)
 
@@ -526,6 +536,9 @@ def _eval_conjugate(self):
     def _eval_rewrite_as_lowergamma(self, s, x, **kwargs):
         return gamma(s) - lowergamma(s, x)
 
+    def _eval_rewrite_as_tractable(self, s, x, **kwargs):
+        return exp(loggamma(s)) - lowergamma(s, x)
+
     def _eval_rewrite_as_expint(self, s, x, **kwargs):
         from sympy import expint
         return expint(1 - s, x)*x**s
diff --git a/sympy/functions/special/tests/test_gamma_functions.py b/sympy/functions/special/tests/test_gamma_functions.py
index 14ceb5c1aece..b38ad111bfdc 100644
--- a/sympy/functions/special/tests/test_gamma_functions.py
+++ b/sympy/functions/special/tests/test_gamma_functions.py
@@ -140,6 +140,9 @@ def test_lowergamma():
     assert conjugate(lowergamma(x, 0)) == 0
     assert unchanged(conjugate, lowergamma(x, -oo))
 
+    assert lowergamma(x, 1).series(x, oo, 3) == \
+        (1 + 1/(x + 1))*exp(-1)/x + O(x**(-3), (x, oo))
+
     assert lowergamma(
         x, y).rewrite(expint) == -y**x*expint(-x + 1, y) + gamma(x)
     k = Symbol('k', integer=True)
diff --git a/sympy/series/tests/test_limits.py b/sympy/series/tests/test_limits.py
index cca634856f93..61ed840506bc 100644
--- a/sympy/series/tests/test_limits.py
+++ b/sympy/series/tests/test_limits.py
@@ -5,8 +5,8 @@
     atan, Abs, gamma, Symbol, S, pi, Integral, Rational, I,
     tan, cot, integrate, Sum, sign, Function, subfactorial, symbols,
     binomial, simplify, frac, Float, sec, zoo, fresnelc, fresnels,
-    acos, erf, erfc, erfi, LambertW, factorial, digamma, Ei, EulerGamma,
-    asin, atanh, acot, acoth, asec, acsc, cbrt)
+    acos, erf, erfc, erfi, LambertW, factorial, digamma, uppergamma,
+    Ei, EulerGamma, asin, atanh, acot, acoth, asec, acsc, cbrt, besselk)
 
 from sympy.calculus.util import AccumBounds
 from sympy.core.add import Add
@@ -705,6 +705,10 @@ def test_issue_15984():
     assert limit((-x + log(exp(x) + 1))/x, x, oo, dir='-').doit() == 0
 
 
+def test_issue_13571():
+    assert limit(uppergamma(x, 1) / gamma(x), x, oo) == 1
+
+
 def test_issue_13575():
     assert limit(acos(erfi(x)), x, 1).cancel() == acos(-I*erf(I))
 
@@ -752,6 +756,10 @@ def test_issue_14811():
     assert limit(((1 + ((S(2)/3)**(x + 1)))**(2**x))/(2**((S(4)/3)**(x - 1))), x, oo) == oo
 
 
+def test_issue_14874():
+    assert limit(besselk(0, x), x, oo) == 0
+
+
 def test_issue_16222():
     assert limit(exp(x), x, 1000000000) == exp(1000000000)
 


Code review comments:
diff_hunk: @@ -464,6 +464,8 @@ def eval(cls, nu, z):
             return S.Zero
 
         if nu.is_integer:
+            if z is S.Infinity:
path: sympy/functions/special/bessel.py
text: @user1:
It is not necessary that nu be an integer, the limit at oo is 0 for all nu.

@author:
Yeah, will make the required change.