Repository: sympy/sympy

Issue:
oo**I raises RunTimeError
```
gxyd@swap:~/Public/sympy$ python3.4
Python 3.4.3 (default, Jul 28 2015, 18:20:59) 
[GCC 4.8.4] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from sympy import *
>>> oo**I
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/gxyd/Public/sympy/sympy/core/decorators.py", line 77, in __sympifyit_wrapper
    return func(a, b)
  File "/home/gxyd/Public/sympy/sympy/core/decorators.py", line 118, in binary_op_wrapper
    return func(self, other)
  File "/home/gxyd/Public/sympy/sympy/core/expr.py", line 151, in __pow__
    return Pow(self, other)
  File "/home/gxyd/Public/sympy/sympy/core/cache.py", line 93, in wrapper
    retval = cfunc(*args, **kwargs)
  File "/usr/lib/python3.4/functools.py", line 472, in wrapper
    result = user_function(*args, **kwds)
  File "/home/gxyd/Public/sympy/sympy/core/power.py", line 192, in __new__
    obj = b._eval_power(e)
  File "/home/gxyd/Public/sympy/sympy/core/numbers.py", line 2474, in _eval_power
    return self**expt.evalf()
  File "/home/gxyd/Public/sympy/sympy/core/decorators.py", line 77, in __sympifyit_wrapper
    return func(a, b)
  File "/home/gxyd/Public/sympy/sympy/core/decorators.py", line 118, in binary_op_wrapper
    return func(self, other)
  File "/home/gxyd/Public/sympy/sympy/core/expr.py", line 151, in __pow__
    return Pow(self, other)
  File "/home/gxyd/Public/sympy/sympy/core/cache.py", line 93, in wrapper
    retval = cfunc(*args, **kwargs)
  File "/usr/lib/python3.4/functools.py", line 472, in wrapper
    result = user_function(*args, **kwds)
  File "/home/gxyd/Public/sympy/sympy/core/power.py", line 192, in __new__
    obj = b._eval_power(e)
  File "/home/gxyd/Public/sympy/sympy/core/numbers.py", line 2474, in _eval_power
    return self**expt.evalf()
  File "/home/gxyd/Public/sympy/sympy/core/decorators.py", line 77, in __sympifyit_wrapper
    return func(a, b)
  File "/home/gxyd/Public/sympy/sympy/core/decorators.py", line 118, in binary_op_wrapper
    return func(self, other)
  File "/home/gxyd/Public/sympy/sympy/core/expr.py", line 151, in __pow__
    return Pow(self, other)
  File "/home/gxyd/Public/sympy/sympy/core/cache.py", line 93, in wrapper
    retval = cfunc(*args, **kwargs)
  File "/usr/lib/python3.4/functools.py", line 472, in wrapper
    result = user_function(*args, **kwds)
  File "/home/gxyd/Public/sympy/sympy/core/power.py", line 192, in __new__
    obj = b._eval_power(e)
  File "/home/gxyd/Public/sympy/sympy/core/numbers.py", line 2474, in _eval_power
    return self**expt.evalf()
  File "/home/gxyd/Public/sympy/sympy/core/decorators.py", line 77, in __sympifyit_wrapper
    return func(a, b)
  File "/home/gxyd/Public/sympy/sympy/core/decorators.py", line 118, in binary_op_wrapper
    return func(self, other)
  File "/home/gxyd/Public/sympy/sympy/core/expr.py", line 151, in __pow__
    return Pow(self, other)
  File "/home/gxyd/Public/sympy/sympy/core/cache.py", line 93, in wrapper
    retval = cfunc(*args, **kwargs)
  File "/usr/lib/python3.4/functools.py", line 472, in wrapper
    result = user_function(*args, **kwds)
  File "/home/gxyd/Public/sympy/sympy/core/power.py", line 192, in __new__
    obj = b._eval_power(e)
  File "/home/gxyd/Public/sympy/sympy/core/numbers.py", line 2474, in _eval_power
    return self**expt.evalf()
  File "/home/gxyd/Public/sympy/sympy/core/decorators.py", line 77, in __sympifyit_wrapper
    return func(a, b)
  File "/home/gxyd/Public/sympy/sympy/core/decorators.py", line 118, in binary_op_wrapper
    return func(self, other)
  File "/home/gxyd/Public/sympy/sympy/core/expr.py", line 151, in __pow__
    return Pow(self, other)
  File "/home/gxyd/Public/sympy/sympy/core/cache.py", line 93, in wrapper
    retval = cfunc(*args, **kwargs)
  File "/usr/lib/python3.4/functools.py", line 472, in wrapper
    result = user_function(*args, **kwds)
  File "/home/gxyd/Public/sympy/sympy/core/power.py", line 192, in __new__
    obj = b._eval_power(e)
  File "/home/gxyd/Public/sympy/sympy/core/numbers.py", line 2474, in _eval_power
    return self**expt.evalf()
  File "/home/gxyd/Public/sympy/sympy/core/decorators.py", line 77, in __sympifyit_wrapper
    return func(a, b)
  File "/home/gxyd/Public/sympy/sympy/core/decorators.py", line 118, in binary_op_wrapper
    return func(self, other)
  File "/home/gxyd/Public/sympy/sympy/core/expr.py", line 151, in __pow__
    return Pow(self, other)
  File "/home/gxyd/Public/sympy/sympy/core/cache.py", line 93, in wrapper
    retval = cfunc(*args, **kwargs)
  File "/usr/lib/python3.4/functools.py", line 472, in wrapper
    result = user_function(*args, **kwds)
  File "/home/gxyd/Public/sympy/sympy/core/power.py", line 192, in __new__
    obj = b._eval_power(e)
  File "/home/gxyd/Public/sympy/sympy/core/numbers.py", line 2474, in _eval_power
    return self**expt.evalf()
  File "/home/gxyd/Public/sympy/sympy/core/decorators.py", line 77, in __sympifyit_wrapper
    return func(a, b)
  File "/home/gxyd/Public/sympy/sympy/core/decorators.py", line 118, in binary_op_wrapper
    return func(self, other)
  File "/home/gxyd/Public/sympy/sympy/core/expr.py", line 151, in __pow__
    return Pow(self, other)
  File "/home/gxyd/Public/sympy/sympy/core/cache.py", line 93, in wrapper
    retval = cfunc(*args, **kwargs)
  File "/usr/lib/python3.4/functools.py", line 472, in wrapper
    result = user_function(*args, **kwds)
  File "/home/gxyd/Public/sympy/sympy/core/power.py", line 192, in __new__
    obj = b._eval_power(e)
  File "/home/gxyd/Public/sympy/sympy/core/numbers.py", line 2474, in _eval_power
    return self**expt.evalf()
  File "/home/gxyd/Public/sympy/sympy/core/decorators.py", line 77, in __sympifyit_wrapper
    return func(a, b)
  File "/home/gxyd/Public/sympy/sympy/core/decorators.py", line 118, in binary_op_wrapper
    return func(self, other)
  File "/home/gxyd/Public/sympy/sympy/core/expr.py", line 151, in __pow__
    return Pow(self, other)
  File "/home/gxyd/Public/sympy/sympy/core/cache.py", line 93, in wrapper
    retval = cfunc(*args, **kwargs)
  File "/usr/lib/python3.4/functools.py", line 472, in wrapper
    result = user_function(*args, **kwds)
  File "/home/gxyd/Public/sympy/sympy/core/power.py", line 192, in __new__
    obj = b._eval_power(e)
  File "/home/gxyd/Public/sympy/sympy/core/numbers.py", line 2474, in _eval_power
    return self**expt.evalf()
  File "/home/gxyd/Public/sympy/sympy/core/decorators.py", line 77, in __sympifyit_wrapper
    return func(a, b)
  File "/home/gxyd/Public/sympy/sympy/core/decorators.py", line 118, in binary_op_wrapper
    return func(self, other)
  File "/home/gxyd/Public/sympy/sympy/core/expr.py", line 151, in __pow__
    return Pow(self, other)
  File "/home/gxyd/Public/sympy/sympy/core/cache.py", line 93, in wrapper
    retval = cfunc(*args, **kwargs)
  File "/usr/lib/python3.4/functools.py", line 472, in wrapper
    result = user_function(*args, **kwds)
  File "/home/gxyd/Public/sympy/sympy/core/power.py", line 192, in __new__
    obj = b._eval_power(e)
  File "/home/gxyd/Public/sympy/sympy/core/numbers.py", line 2474, in _eval_power
    return self**expt.evalf()
  File "/home/gxyd/Public/sympy/sympy/core/decorators.py", line 77, in __sympifyit_wrapper
    return func(a, b)
  File "/home/gxyd/Public/sympy/sympy/core/decorators.py", line 118, in binary_op_wrapper
    return func(self, other)
  File "/home/gxyd/Public/sympy/sympy/core/expr.py", line 151, in __pow__
    return Pow(self, other)
  File "/home/gxyd/Public/sympy/sympy/core/cache.py", line 93, in wrapper
    retval = cfunc(*args, **kwargs)
  File "/usr/lib/python3.4/functools.py", line 472, in wrapper
    result = user_function(*args, **kwds)
  File "/home/gxyd/Public/sympy/sympy/core/power.py", line 192, in __new__
    obj = b._eval_power(e)
  File "/home/gxyd/Public/sympy/sympy/core/numbers.py", line 2474, in _eval_power
    return self**expt.evalf()
  File "/home/gxyd/Public/sympy/sympy/core/decorators.py", line 77, in __sympifyit_wrapper
    return func(a, b)
  File "/home/gxyd/Public/sympy/sympy/core/decorators.py", line 118, in binary_op_wrapper
    return func(self, other)
  File "/home/gxyd/Public/sympy/sympy/core/expr.py", line 151, in __pow__
    return Pow(self, other)
  File "/home/gxyd/Public/sympy/sympy/core/cache.py", line 93, in wrapper
    retval = cfunc(*args, **kwargs)
  File "/usr/lib/python3.4/functools.py", line 472, in wrapper
    result = user_function(*args, **kwds)
  File "/home/gxyd/Public/sympy/sympy/core/power.py", line 192, in __new__
    obj = b._eval_power(e)
  File "/home/gxyd/Public/sympy/sympy/core/numbers.py", line 2474, in _eval_power
    return self**expt.evalf()
  File "/home/gxyd/Public/sympy/sympy/core/decorators.py", line 77, in __sympifyit_wrapper
    return func(a, b)
  File "/home/gxyd/Public/sympy/sympy/core/decorators.py", line 118, in binary_op_wrapper
    return func(self, other)
  File "/home/gxyd/Public/sympy/sympy/core/expr.py", line 151, in __pow__
    return Pow(self, other)
  File "/home/gxyd/Public/sympy/sympy/core/cache.py", line 93, in wrapper
    retval = cfunc(*args, **kwargs)
  File "/usr/lib/python3.4/functools.py", line 472, in wrapper
    result = user_function(*args, **kwds)
  File "/home/gxyd/Public/sympy/sympy/core/power.py", line 192, in __new__
    obj = b._eval_power(e)
  File "/home/gxyd/Public/sympy/sympy/core/numbers.py", line 2474, in _eval_power
    return self**expt.evalf()
  File "/home/gxyd/Public/sympy/sympy/core/decorators.py", line 77, in __sympifyit_wrapper
    return func(a, b)
  File "/home/gxyd/Public/sympy/sympy/core/decorators.py", line 118, in binary_op_wrapper
    return func(self, other)
  File "/home/gxyd/Public/sympy/sympy/core/expr.py", line 151, in __pow__
    return Pow(self, other)
  File "/home/gxyd/Public/sympy/sympy/core/cache.py", line 93, in wrapper
    retval = cfunc(*args, **kwargs)
  File "/usr/lib/python3.4/functools.py", line 472, in wrapper
    result = user_function(*args, **kwds)
  File "/home/gxyd/Public/sympy/sympy/core/power.py", line 192, in __new__
    obj = b._eval_power(e)
  File "/home/gxyd/Public/sympy/sympy/core/numbers.py", line 2474, in _eval_power
    return self**expt.evalf()
  File "/home/gxyd/Public/sympy/sympy/core/decorators.py", line 77, in __sympifyit_wrapper
    return func(a, b)
  File "/home/gxyd/Public/sympy/sympy/core/decorators.py", line 118, in binary_op_wrapper
    return func(self, other)
  File "/home/gxyd/Public/sympy/sympy/core/expr.py", line 151, in __pow__
    return Pow(self, other)
  File "/home/gxyd/Public/sympy/sympy/core/cache.py", line 93, in wrapper
    retval = cfunc(*args, **kwargs)
  File "/usr/lib/python3.4/functools.py", line 472, in wrapper
    result = user_function(*args, **kwds)
  File "/home/gxyd/Public/sympy/sympy/core/power.py", line 192, in __new__
    obj = b._eval_power(e)
  File "/home/gxyd/Public/sympy/sympy/core/numbers.py", line 2474, in _eval_power
    return self**expt.evalf()
  File "/home/gxyd/Public/sympy/sympy/core/decorators.py", line 77, in __sympifyit_wrapper
    return func(a, b)
  File "/home/gxyd/Public/sympy/sympy/core/decorators.py", line 118, in binary_op_wrapper
    return func(self, other)
  File "/home/gxyd/Public/sympy/sympy/core/expr.py", line 151, in __pow__
    return Pow(self, other)
  File "/home/gxyd/Public/sympy/sympy/core/cache.py", line 93, in wrapper
    retval = cfunc(*args, **kwargs)
  File "/usr/lib/python3.4/functools.py", line 472, in wrapper
    result = user_function(*args, **kwds)
  File "/home/gxyd/Public/sympy/sympy/core/power.py", line 192, in __new__
    obj = b._eval_power(e)
  File "/home/gxyd/Public/sympy/sympy/core/numbers.py", line 2474, in _eval_power
    return self**expt.evalf()
  File "/home/gxyd/Public/sympy/sympy/core/decorators.py", line 77, in __sympifyit_wrapper
    return func(a, b)
  File "/home/gxyd/Public/sympy/sympy/core/decorators.py", line 118, in binary_op_wrapper
    return func(self, other)
  File "/home/gxyd/Public/sympy/sympy/core/expr.py", line 151, in __pow__
    return Pow(self, other)
  File "/home/gxyd/Public/sympy/sympy/core/cache.py", line 93, in wrapper
    retval = cfunc(*args, **kwargs)
  File "/usr/lib/python3.4/functools.py", line 472, in wrapper
    result = user_function(*args, **kwds)
  File "/home/gxyd/Public/sympy/sympy/core/power.py", line 192, in __new__
    obj = b._eval_power(e)
  File "/home/gxyd/Public/sympy/sympy/core/numbers.py", line 2474, in _eval_power
    return self**expt.evalf()
  File "/home/gxyd/Public/sympy/sympy/core/decorators.py", line 77, in __sympifyit_wrapper
    return func(a, b)
  File "/home/gxyd/Public/sympy/sympy/core/decorators.py", line 118, in binary_op_wrapper
    return func(self, other)
  File "/home/gxyd/Public/sympy/sympy/core/expr.py", line 151, in __pow__
    return Pow(self, other)
  File "/home/gxyd/Public/sympy/sympy/core/cache.py", line 93, in wrapper
    retval = cfunc(*args, **kwargs)
  File "/usr/lib/python3.4/functools.py", line 472, in wrapper
    result = user_function(*args, **kwds)
  File "/home/gxyd/Public/sympy/sympy/core/power.py", line 192, in __new__
    obj = b._eval_power(e)
  File "/home/gxyd/Public/sympy/sympy/core/numbers.py", line 2474, in _eval_power
    return self**expt.evalf()
  File "/home/gxyd/Public/sympy/sympy/core/decorators.py", line 77, in __sympifyit_wrapper
    return func(a, b)
  File "/home/gxyd/Public/sympy/sympy/core/decorators.py", line 118, in binary_op_wrapper
    return func(self, other)
  File "/home/gxyd/Public/sympy/sympy/core/expr.py", line 151, in __pow__
    return Pow(self, other)
  File "/home/gxyd/Public/sympy/sympy/core/cache.py", line 93, in wrapper
    retval = cfunc(*args, **kwargs)
  File "/usr/lib/python3.4/functools.py", line 472, in wrapper
    result = user_function(*args, **kwds)
  File "/home/gxyd/Public/sympy/sympy/core/power.py", line 192, in __new__
    obj = b._eval_power(e)
  File "/home/gxyd/Public/sympy/sympy/core/numbers.py", line 2474, in _eval_power
    return self**expt.evalf()
  File "/home/gxyd/Public/sympy/sympy/core/decorators.py", line 77, in __sympifyit_wrapper
    return func(a, b)
RuntimeError: maximum recursion depth exceeded while calling a Python object
```

Some part of traceback has been removed to keep it short

Discussion:
jksuom: ``oo**e`` could probably be best thought of as the limit of ``x**e`` for real ``x`` tending to ``oo``. If ``e`` is ``I``, then the limit does not exists, and ``nan`` could be used to indicate that. However, there are other values for which the limit exists. If the real part of ``e`` is positive, then the limit of ``|x**e|`` is ``oo``; so the limit of ``x**e`` is ``zoo``. If the real part of ``e`` is negative, then the limit is 0.
gxyd: I was thinking in terms of consider examples:
if `re(e) > 0` (for ex. `e = 1 + I`) then `oo**(1 + I)` should be equal to `oo**1*oo**I` now `oo**I` is `nan` then `oo*nan` is `nan`. Similarly for the `re(e) < 0` (for ex. `e = -1 + I`), `oo**(-1 + I)` should be equal to `oo**(-1)*oo**I = nan/0` equals `nan`.
gxyd: Ok, may be in terms of what i thought would not apply here. Since it involves `oo`. Probably approach looks good.
gxyd: Sorry, i have just updated it with one-more commit. :)
leosartaj: No problem. :smile:
asmeurer: I'm not a fan of seeing even more assumptions in the core, but this does fix a bug. 
gxyd: Is there any problem in the latest changes to the `docs` that i have made? Tests still seem to fail, only in `python2.7` perhaps.
asmeurer: The is_number looks good. Perhaps you should just go ahead and move this in the direction of https://github.com/sympy/sympy/pull/9731 (and similar PRs by @debugger22) and only do automatic simplification from assumptions on things with is_number or is_Symbol, and move the more general simplification to `_eval_refine`. 
gxyd: Perhaps i am not very familiar with the assumptions in `SymPy`, so may be i will take a day, to understand what the code is doing. So i will get back in ASAP.
gxyd: @asmeurer I have added a `_eval_refine` function in `Infinity` class, probably the way you referred to in your comment.

Patch:
diff --git a/sympy/core/numbers.py b/sympy/core/numbers.py
index f01d3c683e..627a03a5d3 100644
--- a/sympy/core/numbers.py
+++ b/sympy/core/numbers.py
@@ -2464,6 +2464,8 @@ def _eval_power(self, expt):
         NegativeInfinity
 
         """
+        from sympy.functions import re
+
         if expt.is_positive:
             return S.Infinity
         if expt.is_negative:
@@ -2472,8 +2474,15 @@ def _eval_power(self, expt):
             return S.NaN
         if expt is S.ComplexInfinity:
             return S.NaN
+        if expt.is_real is False and expt.is_number:
+            expt_real = re(expt)
+            if expt_real.is_positive:
+                return S.ComplexInfinity
+            if expt_real.is_negative:
+                return S.Zero
+            if expt_real.is_zero:
+                return S.NaN
 
-        if expt.is_number:
             return self**expt.evalf()
 
     def _as_mpf_val(self, prec):
@@ -2673,7 +2682,7 @@ def _eval_power(self, expt):
         NaN
 
         """
-        if isinstance(expt, Number):
+        if expt.is_number:
             if expt is S.NaN or \
                 expt is S.Infinity or \
                     expt is S.NegativeInfinity:
diff --git a/sympy/core/power.py b/sympy/core/power.py
index 42f6fef6b1..358d7d467e 100644
--- a/sympy/core/power.py
+++ b/sympy/core/power.py
@@ -80,7 +80,7 @@ class Pow(Expr):
     """
     Defines the expression x**y as "x raised to a power y"
 
-    Singleton definitions involving (0, 1, -1, oo, -oo):
+    Singleton definitions involving (0, 1, -1, oo, -oo, I, -I):
 
     +--------------+---------+-----------------------------------------------+
     | expr         | value   | reason                                        |
@@ -124,6 +124,18 @@ class Pow(Expr):
     | (-oo)**oo    | nan     |                                               |
     | (-oo)**-oo   |         |                                               |
     +--------------+---------+-----------------------------------------------+
+    | oo**I        | nan     | oo**e could probably be best thought of as    |
+    | (-oo)**I     |         | the limit of x**e for real x as x tends to    |
+    |              |         | oo. If e is I, then the limit does not exist  |
+    |              |         | and nan is used to indicate that.             |
+    +--------------+---------+-----------------------------------------------+
+    | oo**(1+I)    | zoo     | If the real part of e is positive, then the   |
+    | (-oo)**(1+I) |         | limit of abs(x**e) is oo. So the limit value  |
+    |              |         | is zoo.                                       |
+    +--------------+---------+-----------------------------------------------+
+    | oo**(-1+I)   | 0       | If the real part of e is negative, then the   |
+    | -oo**(-1+I)  |         | limit is 0.                                   |
+    +--------------+---------+-----------------------------------------------+
 
     Because symbolic computations are more flexible that floating point
     calculations and we prefer to never return an incorrect answer,


Test patch:
diff --git a/sympy/core/tests/test_numbers.py b/sympy/core/tests/test_numbers.py
index 2dd3da28ef..3179711555 100644
--- a/sympy/core/tests/test_numbers.py
+++ b/sympy/core/tests/test_numbers.py
@@ -12,6 +12,7 @@
 from sympy.utilities.pytest import XFAIL, raises
 import mpmath
 
+t = Symbol('t', real=False)
 
 def same_and_same_prec(a, b):
     # stricter matching for Floats
@@ -1503,3 +1504,13 @@ def test_issue_9491():
 
 def test_issue_10063():
     assert 2**Float(3) == Float(8)
+
+
+def test_issue_10020():
+    assert oo**I is S.NaN
+    assert oo**(1 + I) is S.ComplexInfinity
+    assert oo**(-1 + I) is S.Zero
+    assert (-oo)**I is S.NaN
+    assert (-oo)**(-1 + I) is S.Zero
+    assert oo**t == Pow(oo, t, evaluate=False)
+    assert (-oo)**t == Pow(-oo, t, evaluate=False)