示例#1
0
def test_contains_4():
    assert Order(sin(1 / x**2)).contains(Order(cos(1 / x**2))) is True
    assert Order(cos(1 / x**2)).contains(Order(sin(1 / x**2))) is True
示例#2
0
def test_Order():
    assert precedence(Order(x)) == PRECEDENCE["Atom"]
示例#3
0
def test_contains_3():
    assert Order(x * y**2).contains(Order(x**2 * y)) is None
    assert Order(x**2 * y).contains(Order(x * y**2)) is None
示例#4
0
def test_free_symbols():
    assert Order(1).free_symbols == set()
    assert Order(x).free_symbols == {x}
    assert Order(1, x).free_symbols == {x}
    assert Order(x * y).free_symbols == {x, y}
    assert Order(x, x, y).free_symbols == {x, y}
示例#5
0
def test_simple_1():
    o = Rational(0)
    assert Order(2 * x) == Order(x)
    assert Order(x) * 3 == Order(x)
    assert -28 * Order(x) == Order(x)
    assert Order(Order(x)) == Order(x)
    assert Order(Order(x), y) == Order(Order(x), x, y)
    assert Order(-23) == Order(1)
    assert Order(exp(x)) == Order(1, x)
    assert Order(exp(1 / x)).expr == exp(1 / x)
    assert Order(x * exp(1 / x)).expr == x * exp(1 / x)
    assert Order(x**(o / 3)).expr == x**(o / 3)
    assert Order(x**(o * Rational(5, 3))).expr == x**(o * Rational(5, 3))
    assert Order(x**2 + x + y, x) == O(1, x)
    assert Order(x**2 + x + y, y) == O(1, y)
    raises(ValueError, lambda: Order(exp(x), x, x))
    raises(TypeError, lambda: Order(x, 2 - x))
示例#6
0
def test_multivar_0a():
    assert Order(exp(1 / x) * exp(1 / y)).expr == exp(1 / x) * exp(1 / y)
示例#7
0
def test_multivar_mul_1():
    assert Order(x + y) * x == Order(x**2 + y * x, x, y)
示例#8
0
    def doit(self, **hints):
        """Evaluates the limit.

        Parameters
        ==========

        deep : bool, optional (default: True)
            Invoke the ``doit`` method of the expressions involved before
            taking the limit.

        hints : optional keyword arguments
            To be passed to ``doit`` methods; only used if deep is True.
        """
        from sympy.functions import RisingFactorial

        e, z, z0, dir = self.args

        if z0 is S.ComplexInfinity:
            raise NotImplementedError("Limits at complex "
                                      "infinity are not implemented")

        if hints.get('deep', True):
            e = e.doit(**hints)
            z = z.doit(**hints)
            z0 = z0.doit(**hints)

        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_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)
                    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

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

        l = None

        try:
            if str(dir) == '+-':
                r = gruntz(e, z, z0, '+')
                l = gruntz(e, z, z0, '-')
                if l != r:
                    raise ValueError(
                        "The limit does not exist since "
                        "left hand limit = %s and right hand limit = %s" %
                        (l, r))
            else:
                r = gruntz(e, z, z0, dir)
            if r is S.NaN or l is S.NaN:
                raise PoleError()
        except (PoleError, ValueError):
            if l is not None:
                raise
            r = heuristics(e, z, z0, dir)
            if r is None:
                return self

        return r
示例#9
0
    def truncate(self, n=6):
        ffps = self.ffps
        pt_xk = ffps.xk.coeff(n)
        x, x0 = ffps.x, ffps.x0

        return self.polynomial(n) + Order(pt_xk, (x, x0))
示例#10
0
    def doit(self, **hints):
        """Evaluates limit"""
        from sympy.series.limitseq import limit_seq
        from sympy.functions import RisingFactorial

        e, z, z0, dir = self.args

        if hints.get('deep', True):
            e = e.doit(**hints)
            z = z.doit(**hints)
            z0 = z0.doit(**hints)

        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, RisingFactorial], gamma)

        if e.is_Mul:
            if abs(z0) is S.Infinity:
                e = factor_terms(e)
                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=(z0 is S.Infinity))
                    inve = e.subs(z, 1 / u)
                    r = limit(inve.as_leading_term(u), u, S.Zero,
                              "+" if z0 is S.Infinity else "-")
                    if isinstance(r, Limit):
                        return self
                    else:
                        return r

        if e.is_Order:
            return 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)
            if r is None:
                return self
        except NotImplementedError:
            # Trying finding limits of sequences
            if hints.get('sequence', True) and z0 is S.Infinity:
                trials = hints.get('trials', 5)
                r = limit_seq(e, z, trials)
                if r is None:
                    raise NotImplementedError()
            else:
                raise NotImplementedError()

        return r
示例#11
0
def test_series():
    e = Symbol("e")
    x = Symbol("x")
    for c in (Limit, Limit(e, x, 1), Order, Order(e)):
        check(c)
示例#12
0
    def doit(self, **hints):
        """Evaluates the limit.

        Parameters
        ==========

        deep : bool, optional (default: True)
            Invoke the ``doit`` method of the expressions involved before
            taking the limit.

        hints : optional keyword arguments
            To be passed to ``doit`` methods; only used if deep is True.
        """

        e, z, z0, dir = self.args

        if z0 is S.ComplexInfinity:
            raise NotImplementedError("Limits at complex "
                                    "infinity are not implemented")

        if hints.get('deep', True):
            e = e.doit(**hints)
            z = z.doit(**hints)
            z0 = z0.doit(**hints)

        if e == z:
            return z0

        if not e.has(z):
            return e

        if z0 is S.NaN:
            return S.NaN

        if e.has(*_illegal):
            return self

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

        cdir = 0
        if str(dir) == "+":
            cdir = 1
        elif str(dir) == "-":
            cdir = -1

        def set_signs(expr):
            if not expr.args:
                return expr
            newargs = tuple(set_signs(arg) for arg in expr.args)
            if newargs != expr.args:
                expr = expr.func(*newargs)
            abs_flag = isinstance(expr, Abs)
            sign_flag = isinstance(expr, sign)
            if abs_flag or sign_flag:
                sig = limit(expr.args[0], z, z0, dir)
                if sig.is_zero:
                    sig = limit(1/expr.args[0], z, z0, dir)
                if sig.is_extended_real:
                    if (sig < 0) == True:
                        return -expr.args[0] if abs_flag else S.NegativeOne
                    elif (sig > 0) == True:
                        return expr.args[0] if abs_flag else S.One
            return expr

        if e.has(Float):
            # Convert floats like 0.5 to exact SymPy numbers like S.Half, to
            # prevent rounding errors which can lead to unexpected execution
            # of conditional blocks that work on comparisons
            # Also see comments in https://github.com/sympy/sympy/issues/19453
            from sympy.simplify.simplify import nsimplify
            e = nsimplify(e)
        e = set_signs(e)


        if e.is_meromorphic(z, z0):
            if abs(z0) is S.Infinity:
                newe = e.subs(z, 1/z)
                # cdir changes sign as oo- should become 0+
                cdir = -cdir
            else:
                newe = e.subs(z, z + z0)
            try:
                coeff, ex = newe.leadterm(z, cdir=cdir)
            except ValueError:
                pass
            else:
                if ex > 0:
                    return S.Zero
                elif ex == 0:
                    return coeff
                if cdir == 1 or not(int(ex) & 1):
                    return S.Infinity*sign(coeff)
                elif cdir == -1:
                    return S.NegativeInfinity*sign(coeff)
                else:
                    return S.ComplexInfinity

        if abs(z0) is S.Infinity:
            if e.is_Mul:
                e = factor_terms(e)
            newe = e.subs(z, 1/z)
            # cdir changes sign as oo- should become 0+
            cdir = -cdir
        else:
            newe = e.subs(z, z + z0)
        try:
            coeff, ex = newe.leadterm(z, cdir=cdir)
        except (ValueError, NotImplementedError, PoleError):
            # The NotImplementedError catching is for custom functions
            from sympy.simplify.powsimp import powsimp
            e = powsimp(e)
            if e.is_Pow:
                r = self.pow_heuristics(e)
                if r is not None:
                    return r
        else:
            if coeff.has(S.Infinity, S.NegativeInfinity, S.ComplexInfinity):
                return self
            if not coeff.has(z):
                if ex.is_positive:
                    return S.Zero
                elif ex == 0:
                    return coeff
                elif ex.is_negative:
                    if ex.is_integer:
                        if cdir == 1 or ex.is_even:
                            return S.Infinity*sign(coeff)
                        elif cdir == -1:
                            return S.NegativeInfinity*sign(coeff)
                        else:
                            return S.ComplexInfinity
                    else:
                        if cdir == 1:
                            return S.Infinity*sign(coeff)
                        elif cdir == -1:
                            return S.Infinity*sign(coeff)*S.NegativeOne**ex
                        else:
                            return S.ComplexInfinity

        # 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, gamma)

        l = None

        try:
            if str(dir) == '+-':
                r = gruntz(e, z, z0, '+')
                l = gruntz(e, z, z0, '-')
                if l != r:
                    raise ValueError("The limit does not exist since "
                            "left hand limit = %s and right hand limit = %s"
                            % (l, r))
            else:
                r = gruntz(e, z, z0, dir)
            if r is S.NaN or l is S.NaN:
                raise PoleError()
        except (PoleError, ValueError):
            if l is not None:
                raise
            r = heuristics(e, z, z0, dir)
            if r is None:
                return self

        return r
示例#13
0
def test_basic1():
    assert limit(x, x, oo) is oo
    assert limit(x, x, -oo) is -oo
    assert limit(-x, x, oo) is -oo
    assert limit(x**2, x, -oo) is oo
    assert limit(-x**2, x, oo) is -oo
    assert limit(x * log(x), x, 0, dir="+") == 0
    assert limit(1 / x, x, oo) == 0
    assert limit(exp(x), x, oo) is oo
    assert limit(-exp(x), x, oo) is -oo
    assert limit(exp(x) / x, x, oo) is oo
    assert limit(1 / x - exp(-x), x, oo) == 0
    assert limit(x + 1 / x, x, oo) is oo
    assert limit(x - x**2, x, oo) is -oo
    assert limit((1 + x)**(1 + sqrt(2)), x, 0) == 1
    assert limit((1 + x)**oo, x, 0) == Limit((x + 1)**oo, x, 0)
    assert limit((1 + x)**oo, x, 0, dir='-') == Limit((x + 1)**oo,
                                                      x,
                                                      0,
                                                      dir='-')
    assert limit((1 + x + y)**oo, x, 0, dir='-') == Limit((x + y + 1)**oo,
                                                          x,
                                                          0,
                                                          dir='-')
    assert limit(y / x / log(x), x, 0) == -oo * sign(y)
    assert limit(cos(x + y) / x, x, 0) == sign(cos(y)) * oo
    assert limit(gamma(1 / x + 3), x, oo) == 2
    assert limit(S.NaN, x, -oo) is S.NaN
    assert limit(Order(2) * x, x, S.NaN) is S.NaN
    assert limit(1 / (x - 1), x, 1, dir="+") is oo
    assert limit(1 / (x - 1), x, 1, dir="-") is -oo
    assert limit(1 / (5 - x)**3, x, 5, dir="+") is -oo
    assert limit(1 / (5 - x)**3, x, 5, dir="-") is oo
    assert limit(1 / sin(x), x, pi, dir="+") is -oo
    assert limit(1 / sin(x), x, pi, dir="-") is oo
    assert limit(1 / cos(x), x, pi / 2, dir="+") is -oo
    assert limit(1 / cos(x), x, pi / 2, dir="-") is oo
    assert limit(1 / tan(x**3), x, (2 * pi)**Rational(1, 3), dir="+") is oo
    assert limit(1 / tan(x**3), x, (2 * pi)**Rational(1, 3), dir="-") is -oo
    assert limit(1 / cot(x)**3, x, (pi * Rational(3, 2)), dir="+") is -oo
    assert limit(1 / cot(x)**3, x, (pi * Rational(3, 2)), dir="-") is oo

    # test bi-directional limits
    assert limit(sin(x) / x, x, 0, dir="+-") == 1
    assert limit(x**2, x, 0, dir="+-") == 0
    assert limit(1 / x**2, x, 0, dir="+-") is oo

    # test failing bi-directional limits
    assert limit(1 / x, x, 0, dir="+-") is zoo
    # approaching 0
    # from dir="+"
    assert limit(1 + 1 / x, x, 0) is oo
    # from dir='-'
    # Add
    assert limit(1 + 1 / x, x, 0, dir='-') is -oo
    # Pow
    assert limit(x**(-2), x, 0, dir='-') is oo
    assert limit(x**(-3), x, 0, dir='-') is -oo
    assert limit(1 / sqrt(x), x, 0, dir='-') == (-oo) * I
    assert limit(x**2, x, 0, dir='-') == 0
    assert limit(sqrt(x), x, 0, dir='-') == 0
    assert limit(x**-pi, x, 0, dir='-') == oo * sign((-1)**(-pi))
    assert limit((1 + cos(x))**oo, x, 0) == Limit((cos(x) + 1)**oo, x, 0)
示例#14
0
    def doit(self, **hints):
        """Evaluates the limit.

        Parameters
        ==========

        deep : bool, optional (default: True)
            Invoke the ``doit`` method of the expressions involved before
            taking the limit.

        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

        if z0 is S.ComplexInfinity:
            raise NotImplementedError("Limits at complex "
                                    "infinity are not implemented")

        if hints.get('deep', True):
            e = e.doit(**hints)
            z = z.doit(**hints)
            z0 = z0.doit(**hints)

        if e == z:
            return z0

        if not e.has(z):
            return e

        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)
            try:
                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)
                    else:
                        return S.ComplexInfinity
            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 and abs(z0) is S.Infinity:
            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:
                        return r
            except (ValueError, NotImplementedError, PoleError):
                pass

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

        l = None

        try:
            if str(dir) == '+-':
                r = gruntz(e, z, z0, '+')
                l = gruntz(e, z, z0, '-')
                if l != r:
                    raise ValueError("The limit does not exist since "
                            "left hand limit = %s and right hand limit = %s"
                            % (l, r))
            else:
                r = gruntz(e, z, z0, dir)
            if r is S.NaN or l is S.NaN:
                raise PoleError()
        except (PoleError, ValueError):
            if l is not None:
                raise
            r = heuristics(e, z, z0, dir)
            if r is None:
                return self

        return r
示例#15
0
def test_contains():
    assert Order(1, x) not in Order(1)
    assert Order(1) in Order(1, x)
    raises(TypeError, lambda: Order(x * y**2) in Order(x**2 * y))
示例#16
0
def test_order_oo():
    x = Symbol('x', positive=True)
    assert Order(x)*oo != Order(1, x)
    assert limit(oo/(x**2 - 4), x, oo) is oo
示例#17
0
def test_add_1():
    assert Order(x + x) == Order(x)
    assert Order(3 * x - 2 * x**2) == Order(x)
    assert Order(1 + x) == Order(1, x)
    assert Order(1 + 1 / x) == Order(1 / x)
    assert Order(log(x) + 1 / log(x)) == Order(log(x))
    assert Order(exp(1 / x) + x) == Order(exp(1 / x))
    assert Order(exp(1 / x) + 1 / x**20) == Order(exp(1 / x))
示例#18
0
def test_as_expr_variables():
    assert Order(x).as_expr_variables(None) == (x, ((x, 0), ))
    assert Order(x).as_expr_variables(((x, 0), )) == (x, ((x, 0), ))
    assert Order(y).as_expr_variables(((x, 0), )) == (y, ((x, 0), (y, 0)))
    assert Order(y).as_expr_variables(
        ((x, 0), (y, 0))) == (y, ((x, 0), (y, 0)))
示例#19
0
def test_multivar_2():
    assert Order(x**2 * y + y**2 * x, x, y).expr == x**2 * y + y**2 * x
示例#20
0
def test_contains_0():
    assert Order(1, x).contains(Order(1, x))
    assert Order(1, x).contains(Order(1))
    assert Order(1).contains(Order(1, x)) is False
示例#21
0
def test_multivar_3():
    assert (Order(x) + Order(y)).args in [(Order(x), Order(y)),
                                          (Order(y), Order(x))]
    assert Order(x) + Order(y) + Order(x + y) == Order(x + y)
    assert (Order(x**2 * y) + Order(y**2 * x)).args in [
        (Order(x * y**2), Order(y * x**2)), (Order(y * x**2), Order(x * y**2))
    ]
    assert (Order(x**2 * y) + Order(y * x)) == Order(x * y)
示例#22
0
def test_contains_1():
    assert Order(x).contains(Order(x))
    assert Order(x).contains(Order(x**2))
    assert not Order(x**2).contains(Order(x))
    assert not Order(x).contains(Order(1 / x))
    assert not Order(1 / x).contains(Order(exp(1 / x)))
    assert not Order(x).contains(Order(exp(1 / x)))
    assert Order(1 / x).contains(Order(x))
    assert Order(exp(1 / x)).contains(Order(x))
    assert Order(exp(1 / x)).contains(Order(1 / x))
    assert Order(exp(1 / x)).contains(Order(exp(1 / x)))
    assert Order(exp(2 / x)).contains(Order(exp(1 / x)))
    assert not Order(exp(1 / x)).contains(Order(exp(2 / x)))
示例#23
0
def test_eval():
    assert Order(x).subs(Order(x), 1) == 1
    assert Order(x).subs(x, y) == Order(y)
    assert Order(x).subs(y, x) == Order(x)
    assert Order(x).subs(x, x + y) == Order(x + y, (x, -y))
    assert (O(1)**x).is_Pow
示例#24
0
def test_contains_2():
    assert Order(x).contains(Order(y)) is None
    assert Order(x).contains(Order(y * x))
    assert Order(y * x).contains(Order(x))
    assert Order(y).contains(Order(x * y))
    assert Order(x).contains(Order(y**2 * x))
示例#25
0
def test_order_conjugate_transpose():
    x = Symbol('x', real=True)
    y = Symbol('y', imaginary=True)
    assert conjugate(Order(x)) == Order(conjugate(x))
    assert conjugate(Order(y)) == Order(conjugate(y))
    assert conjugate(Order(x**2)) == Order(conjugate(x)**2)
    assert conjugate(Order(y**2)) == Order(conjugate(y)**2)
    assert transpose(Order(x)) == Order(transpose(x))
    assert transpose(Order(y)) == Order(transpose(y))
    assert transpose(Order(x**2)) == Order(transpose(x)**2)
    assert transpose(Order(y**2)) == Order(transpose(y)**2)
示例#26
0
    def doit(self, **hints):
        """Evaluates the limit.

        Parameters
        ==========

        deep : bool, optional (default: True)
            Invoke the ``doit`` method of the expressions involved before
            taking the limit.

        hints : optional keyword arguments
            To be passed to ``doit`` methods; only used if deep is True.
        """
        from sympy import Abs, exp, log, sign
        from sympy.calculus.util import AccumBounds
        from sympy.functions import RisingFactorial

        e, z, z0, dir = self.args

        if z0 is S.ComplexInfinity:
            raise NotImplementedError("Limits at complex "
                                    "infinity are not implemented")

        if hints.get('deep', True):
            e = e.doit(**hints)
            z = z.doit(**hints)
            z0 = z0.doit(**hints)

        if e == z:
            return z0

        if not e.has(z):
            return e

        cdir = 0
        if str(dir) == "+":
            cdir = 1
        elif str(dir) == "-":
            cdir = -1

        def remove_abs(expr):
            if not expr.args:
                return expr
            newargs = tuple(remove_abs(arg) for arg in expr.args)
            if newargs != expr.args:
                expr = expr.func(*newargs)
            if isinstance(expr, Abs):
                sig = limit(expr.args[0], z, z0, dir)
                if sig.is_zero:
                    sig = limit(1/expr.args[0], z, z0, dir)
                if sig.is_extended_real:
                    if (sig < 0) == True:
                        return -expr.args[0]
                    elif (sig > 0) == True:
                        return expr.args[0]
            return expr

        e = remove_abs(e)

        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)
            try:
                coeff, ex = newe.leadterm(z, cdir)
            except ValueError:
                pass
            else:
                if ex > 0:
                    return S.Zero
                elif ex == 0:
                    return coeff
                if str(dir) == "+" or not(int(ex) & 1):
                    return S.Infinity*sign(coeff)
                elif str(dir) == "-":
                    return S.NegativeInfinity*sign(coeff)
                else:
                    return S.ComplexInfinity

        # 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 and abs(z0) is S.Infinity:
            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).gammasimp()
                if f.is_meromorphic(u, S.Zero):
                    r = limit(f, u, S.Zero, "+")
                    if isinstance(r, Limit):
                        return self
                    else:
                        return r
            except (ValueError, NotImplementedError, PoleError):
                pass

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

        if e.is_Pow:
            if e.has(S.Infinity, S.NegativeInfinity, S.ComplexInfinity, S.NaN):
                return self

            b1, e1 = e.base, e.exp
            f1 = e1*log(b1)
            if f1.is_meromorphic(z, z0):
                res = limit(f1, z, z0)
                return exp(res)

            ex_lim = limit(e1, z, z0)
            base_lim = limit(b1, z, z0)

            if base_lim is S.One:
                if ex_lim in (S.Infinity, S.NegativeInfinity):
                    res = limit(e1*(b1 - 1), z, z0)
                    return exp(res)
                elif ex_lim.is_real:
                    return S.One

            if base_lim in (S.Zero, S.Infinity, S.NegativeInfinity) and ex_lim is S.Zero:
                res = limit(f1, z, z0)
                return exp(res)

            if base_lim is S.NegativeInfinity:
                if ex_lim is S.NegativeInfinity:
                    return S.Zero
                if ex_lim is S.Infinity:
                    return S.ComplexInfinity

            if not isinstance(base_lim, AccumBounds) and not isinstance(ex_lim, AccumBounds):
                res = base_lim**ex_lim
                if res is not S.ComplexInfinity and not res.is_Pow:
                    return res

        l = None

        try:
            if str(dir) == '+-':
                r = gruntz(e, z, z0, '+')
                l = gruntz(e, z, z0, '-')
                if l != r:
                    raise ValueError("The limit does not exist since "
                            "left hand limit = %s and right hand limit = %s"
                            % (l, r))
            else:
                r = gruntz(e, z, z0, dir)
            if r is S.NaN or l is S.NaN:
                raise PoleError()
        except (PoleError, ValueError):
            if l is not None:
                raise
            r = heuristics(e, z, z0, dir)
            if r is None:
                return self

        return r