(e, z, z0, dir="+")
return r
Compute the limit of e(z) at the point z0.

    z0 can be any expression, including oo and -oo.

    For dir="+" (default) it calculates the limit from the right
    (z->z0+) and for dir="-" the limit from the left (z->z0-). For infinite z0
    (oo or -oo), the dir argument doesn't matter.

    Examples
    ========

    >>> from sympy import limit, sin, Symbol, oo
    >>> from sympy.abc import x
    >>> limit(sin(x)/x, x, 0)
    1
    >>> limit(1/x, x, 0, dir="+")
    oo
    >>> limit(1/x, x, 0, dir="-")
    -oo
    >>> limit(1/x, x, oo)
    0

    Notes
    =====

    First we try some heuristics for easy and frequent cases like "x", "1/x",
    "x**2" and similar, so that it's fast. For all other cases, we use the
    Gruntz algorithm (see the gruntz() function).
Compute the limit of e(z) at the point z0.
Compute the limit of e ( z ) at the point z0 .
def limit(e, z, z0, dir="+"):
    """
    Compute the limit of e(z) at the point z0.

    z0 can be any expression, including oo and -oo.

    For dir="+" (default) it calculates the limit from the right
    (z->z0+) and for dir="-" the limit from the left (z->z0-). For infinite z0
    (oo or -oo), the dir argument doesn't matter.

    Examples
    ========

    >>> from sympy import limit, sin, Symbol, oo
    >>> from sympy.abc import x
    >>> limit(sin(x)/x, x, 0)
    1
    >>> limit(1/x, x, 0, dir="+")
    oo
    >>> limit(1/x, x, 0, dir="-")
    -oo
    >>> limit(1/x, x, oo)
    0

    Notes
    =====

    First we try some heuristics for easy and frequent cases like "x", "1/x",
    "x**2" and similar, so that it's fast. For all other cases, we use the
    Gruntz algorithm (see the gruntz() function).
    """
    e = sympify(e)
    z = sympify(z)
    z0 = sympify(z0)

    if e == z:
        return z0

    if not e.has(z):
        return e

    # 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_positive:
        e = e.rewrite(factorial, gamma)

    if e.is_Mul:
        if abs(z0) is S.Infinity:
            # XXX todo: this should probably be stated in the
            # negative -- i.e. to exclude expressions that should
            # not be handled this way but I'm not sure what that
            # condition is; when ok is True it means that the leading
            # term approach is going to succeed (hopefully)
            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 = C.Dummy(positive=(z0 is S.Infinity))
                inve = e.subs(z, 1/u)
                return limit(inve.as_leading_term(u), u,
                    S.Zero, "+" if z0 is S.Infinity else "-")

    if e.is_Order:
        return C.Order(limit(e.expr, z, z0), *e.args[1:])

    try:
        r = gruntz(e, z, z0, dir)
        if r is S.NaN:
            raise PoleError()
    except (PoleError, ValueError):
        r = heuristics(e, z, z0, dir)
    return r
def limit ( e , z , z0 , dir = "+" ) : e = sympify ( e ) z = sympify ( z ) z0 = sympify ( z0 ) if e == z : return z0 if not e . has ( z ) : return e # 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_positive : e = e . rewrite ( factorial , gamma ) if e . is_Mul : if abs ( z0 ) is S . Infinity : # XXX todo: this should probably be stated in the # negative -- i.e. to exclude expressions that should # not be handled this way but I'm not sure what that # condition is; when ok is True it means that the leading # term approach is going to succeed (hopefully) 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 = C . Dummy ( positive = ( z0 is S . Infinity ) ) inve = e . subs ( z , 1 / u ) return limit ( inve . as_leading_term ( u ) , u , S . Zero , "+" if z0 is S . Infinity else "-" ) if e . is_Order : return C . Order ( limit ( e . expr , z , z0 ) , * e . args [ 1 : ] ) try : r = gruntz ( e , z , z0 , dir ) if r is S . NaN : raise PoleError ( ) except ( PoleError , ValueError ) : r = heuristics ( e , z , z0 , dir ) return r