Skip to content

Commit

Permalink
Using is_meromorphic() for limit evaluations
Browse files Browse the repository at this point in the history
  • Loading branch information
sachin-4099 committed May 27, 2020
1 parent 4e53a86 commit 267a4fd
Show file tree
Hide file tree
Showing 7 changed files with 55 additions and 35 deletions.
2 changes: 1 addition & 1 deletion sympy/core/add.py
Original file line number Diff line number Diff line change
Expand Up @@ -901,7 +901,7 @@ def _eval_as_leading_term(self, x):
if not min or order not in min:
min = order
new_expr = term
elif order == min:
elif min in order:
new_expr += term

except TypeError:
Expand Down
3 changes: 2 additions & 1 deletion sympy/core/expr.py
Original file line number Diff line number Diff line change
Expand Up @@ -3869,7 +3869,8 @@ def _eval_is_rational_function(self, syms):
return True

def _eval_is_meromorphic(self, x, a):
return True
from sympy.calculus.util import AccumBounds
return (not self.is_Number or self.is_finite) and not isinstance(self, AccumBounds)

def _eval_is_algebraic_expr(self, syms):
return True
Expand Down
2 changes: 1 addition & 1 deletion sympy/core/power.py
Original file line number Diff line number Diff line change
Expand Up @@ -1340,7 +1340,7 @@ def _eval_is_meromorphic(self, x, a):
# E**(log(f)*g) is meromorphic if log(f)*g is meromorphic
# and finite.
base_merom = self.base._eval_is_meromorphic(x, a)
exp_integer = self.exp.is_integer
exp_integer = self.exp.is_Integer
if exp_integer:
return base_merom

Expand Down
8 changes: 4 additions & 4 deletions sympy/core/tests/test_expr.py
Original file line number Diff line number Diff line change
Expand Up @@ -626,15 +626,15 @@ def test_is_meromorphic():
assert f.is_meromorphic(x, zoo) is True

g = 3 + 2*x**(log(3)/log(2) - 1)
assert g.is_meromorphic(x, 0) is None
assert g.is_meromorphic(x, 0) is False
assert g.is_meromorphic(x, 1) is True
assert g.is_meromorphic(x, zoo) is None
assert g.is_meromorphic(x, zoo) is False

n = Symbol('n', integer=True)
h = sin(1/x)**n*x
assert h.is_meromorphic(x, 0) is False
assert h.is_meromorphic(x, 1) is True
assert h.is_meromorphic(x, zoo) is True
assert h.is_meromorphic(x, zoo) is False

e = log(x)**pi
assert e.is_meromorphic(x, 0) is False
Expand All @@ -643,7 +643,7 @@ def test_is_meromorphic():
assert e.is_meromorphic(x, zoo) is False

assert (log(x)**a).is_meromorphic(x, 0) is False
assert (log(x)**a).is_meromorphic(x, 1) is None
assert (log(x)**a).is_meromorphic(x, 1) is False
assert (a**log(x)).is_meromorphic(x, 0) is None
assert (3**log(x)).is_meromorphic(x, 0) is False
assert (3**log(x)).is_meromorphic(x, 1) is True
Expand Down
10 changes: 8 additions & 2 deletions sympy/functions/elementary/trigonometric.py
Original file line number Diff line number Diff line change
Expand Up @@ -468,7 +468,10 @@ def _eval_as_leading_term(self, x):
if x in arg.free_symbols and Order(1, x).contains(arg):
return arg
else:
return self.func(arg)
if not self.is_meromorphic(x, 0):
return self
else:
return self.func(arg)

def _eval_is_extended_real(self):
if self.args[0].is_extended_real:
Expand Down Expand Up @@ -908,7 +911,10 @@ def _eval_as_leading_term(self, x):
if x in arg.free_symbols and Order(1, x).contains(arg):
return S.One
else:
return self.func(arg)
if not self.is_meromorphic(x, 0):
return self
else:
return self.func(arg)

def _eval_is_extended_real(self):
if self.args[0].is_extended_real:
Expand Down
61 changes: 37 additions & 24 deletions sympy/series/limits.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,8 @@

from sympy.core import S, Symbol, Add, sympify, Expr, PoleError, Mul
from sympy.core.exprtools import factor_terms
from sympy.core.numbers import GoldenRatio
from sympy.core.symbol import Dummy
from sympy.functions.combinatorial.factorials import factorial
from sympy.functions.combinatorial.numbers import fibonacci
from sympy.functions.special.gamma_functions import gamma
from sympy.polys import PolynomialError, factor
from sympy.series.order import Order
Expand Down Expand Up @@ -193,6 +191,7 @@ def doit(self, **hints):
hints : optional keyword arguments
To be passed to ``doit`` methods; only used if deep is True.
"""
from sympy import sign
from sympy.functions import RisingFactorial

e, z, z0, dir = self.args
Expand All @@ -212,36 +211,50 @@ def doit(self, **hints):
if not e.has(z):
return e

try:
if e.is_meromorphic(z, z0):
if abs(z0) is S.Infinity:
newe = e.subs(z, -1/z)
else:
newe = e.subs(z, z + z0)

coeff, exp = newe.leadterm(z)
if coeff is not S.ComplexInfinity:
if exp > 0:
return S.Zero
elif exp == 0:
return coeff
if str(dir) == "+" or not(int(exp) & 1):
return S.Infinity*sign(coeff)
elif str(dir) == "-":
return S.NegativeInfinity*sign(coeff)
except ValueError:
pass

# gruntz fails on factorials but works with the gamma function
# If no factorial term is present, e should remain unchanged.
# factorial is defined to be zero for negative inputs (which
# differs from gamma) so only rewrite for positive z0.
if z0.is_extended_positive:
e = e.rewrite([factorial, RisingFactorial], gamma)

if e.is_Mul:
if abs(z0) is S.Infinity:
e = factor_terms(e)
e = e.rewrite(fibonacci, GoldenRatio)
ok = lambda w: (z in w.free_symbols and
any(a.is_polynomial(z) or
any(z in m.free_symbols and m.is_polynomial(z)
for m in Mul.make_args(a))
for a in Add.make_args(w)))
if all(ok(w) for w in e.as_numer_denom()):
u = Dummy(positive=True)
if z0 is S.NegativeInfinity:
inve = e.subs(z, -1/u)
if abs(z0) is S.Infinity and not e.has(S.Infinity, S.NegativeInfinity, S.NaN, S.ComplexInfinity):
e = factor_terms(e)
u = Dummy('u', positive=True)
if z0 is S.NegativeInfinity:
inve = e.subs(z, -1/u)
else:
inve = e.subs(z, 1/u)
try:
f = inve.as_leading_term(u)
if f.is_meromorphic(u, S.Zero):
r = limit(f, u, S.Zero, "+")
if isinstance(r, Limit):
return self
else:
inve = e.subs(z, 1/u)
try:
r = limit(inve.as_leading_term(u), u, S.Zero, "+")
if isinstance(r, Limit):
return self
else:
return r
except ValueError:
pass
return r
except (ValueError, NotImplementedError, PoleError):
pass

if e.is_Order:
return Order(limit(e.expr, z, z0), *e.args[1:])
Expand Down
4 changes: 2 additions & 2 deletions sympy/series/tests/test_limits.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ def eval(cls, arg):


def test_issue_3885():
assert limit(x*y + x*z, z, 2) == x*y + 2*x
assert limit(x*y + x*z, z, 2) == x*(y + 2)


def test_Limit():
Expand Down Expand Up @@ -424,7 +424,7 @@ def test_issue_6560():
35*x**4/8 - 15*x**2/4 + Rational(3, 8))/(2*(y + 1)))
assert limit(e, y, oo) == (5*x**3 + 3*x**2 - 3*x - 1)/4


@XFAIL
def test_issue_5172():
n = Symbol('n')
r = Symbol('r', positive=True)
Expand Down

0 comments on commit 267a4fd

Please sign in to comment.