Repository: sympy/sympy

Issue:
sympy.polys.polyerrors.CoercionFailed integration regressions?
Hello,

I have come across the following expressions (`f`) which can be integrated by SymPy 1.4 in the following way:

```
>>> from sympy import *
>>> x = Symbol('x', real=True, nonzero=True)
>>> f = (x+exp(3))/x**2
>>> integrate(f, x)
```

(The `F`'s below are the results returned by the integration) but the integration (`integrate(f, x)`) fails in SymPy 1.7.1, raising a `CoercionFailed` error:

```
...
File ".../python3.9/site-packages/sympy/polys/domains/domain.py", line 160, in convert
    raise CoercionFailed("can't convert %s of type %s to %s" % (element, type(element), self))
```

```
f = (x + exp(3))/x**2
F = log(x) - exp(3)/x

f = (x**2 + exp(5))/x
F = x**2/2 + exp(5)*log(x)

f = x/(2*x + tanh(1))
F = x/2 - log(2*x + tanh(1))*tanh(1)/4

f = x - sinh(4)/x
F = x**2/2 - log(x)*sinh(4)

f = log(x + exp(5)/x)
F = x*log(x + exp(5)/x) - x + 2*exp(5/2)*atan(x*exp(-5/2))

f = x**5/(x + E)
F = x**5/5 - E*x**4/4 + x**3*exp(2)/3 - x**2*exp(3)/2 + x*exp(4) - exp(5)*log(x + E)

f = 4*x/(x + sinh(5))
F = 4*x - 4*log(x + sinh(5))*sinh(5)

f = x**2/(2*x + sinh(2))
F = x**2/4 - x*sinh(2)/4 + (-1 + E)**2*(1 + E)**2*(1 + exp(2))**2*exp(-4)*log(2*x + sinh(2))/32

f = -x**2/(x + E)
F = -x**2/2 + E*x - exp(2)*log(x + E)

f = (2*x + 3)*exp(5)/x
F = 2*x*exp(5) + 3*exp(5)*log(x)

f = x + 2 + cosh(3)/x
F = x**2/2 + 2*x + log(x)*cosh(3)

f = x - tanh(1)/x**3
F = x**2/2 + tanh(1)/(2*x**2)

f = (3*x - exp(6))/x
F = 3*x - exp(6)*log(x)

f = x**4/(x + exp(5))**2 + x
F = x**3/3 + x**2*(1/2 - exp(5)) + 3*x*exp(10) - 4*exp(15)*log(x + exp(5)) - exp(20)/(x + exp(5))

f = x*(x + exp(10)/x**2) + x
F = x**3/3 + x**2/2 + exp(10)*log(x)

f = x + x/(5*x + sinh(3))
F = x**2/2 + x/5 - log(5*x + sinh(3))*sinh(3)/25

f = (x + exp(3))/(2*x**2 + 2*x)
F = exp(3)*log(x)/2 - (-1 + E)*(1 + E + exp(2))*log(x + ((-1 + E)*(1 + E + exp(2)) + exp(3))/(-1 + 2*exp(3)))/2

f = log(x + 4*sinh(4))
F = x*log(x + 4*sinh(4)) - x + 4*log(x + 4*sinh(4))*sinh(4)

f = -x + 20*(exp(-5) - atan(4)/x)**3*sin(4)/x
F = (-x**2*exp(15)/2 + 20*log(x)*sin(4) + (180*x**2*exp(5)*sin(4)*atan(4) - 90*x*exp(10)*sin(4)*atan(4)**2 + 20*exp(15)*sin(4)*atan(4)**3)/(3*x**3))*exp(-15)

f = 2*x**2*exp(-4) + 6/x
F_true = (2*x**3/3 + 6*exp(4)*log(x))*exp(-4)
```

I can provide more examples. Is this a regression, or the difference in the behaviour is due to some bug fixes in the development process between the library updates, or you cannot reproduce the problem and the issue is on my side?

Thank you

Discussion:

Patch:
diff --git a/sympy/polys/rings.py b/sympy/polys/rings.py
index ea4e7fd708..da86045922 100644
--- a/sympy/polys/rings.py
+++ b/sympy/polys/rings.py
@@ -380,10 +380,14 @@ def _rebuild(expr):
                 return reduce(add, list(map(_rebuild, expr.args)))
             elif expr.is_Mul:
                 return reduce(mul, list(map(_rebuild, expr.args)))
-            elif expr.is_Pow and expr.exp.is_Integer and expr.exp >= 0:
-                return _rebuild(expr.base)**int(expr.exp)
             else:
-                return self.ground_new(domain.convert(expr))
+                # XXX: Use as_base_exp() to handle Pow(x, n) and also exp(n)
+                # XXX: E can be a generator e.g. sring([exp(2)]) -> ZZ[E]
+                base, exp = expr.as_base_exp()
+                if exp.is_Integer and exp > 1:
+                    return _rebuild(base)**int(exp)
+                else:
+                    return self.ground_new(domain.convert(expr))
 
         return _rebuild(sympify(expr))
 


Test patch:
diff --git a/sympy/integrals/tests/test_integrals.py b/sympy/integrals/tests/test_integrals.py
index b3a54f6b8a..6f2ed9ef9b 100644
--- a/sympy/integrals/tests/test_integrals.py
+++ b/sympy/integrals/tests/test_integrals.py
@@ -1736,3 +1736,92 @@ def test_issue_21034():
 def test_issue_4187():
     assert integrate(log(x)*exp(-x), x) == Ei(-x) - exp(-x)*log(x)
     assert integrate(log(x)*exp(-x), (x, 0, oo)) == -EulerGamma
+
+
+def test_issue_21024():
+    x = Symbol('x', real=True, nonzero=True)
+    f = log(x)*log(4*x) + log(3*x + exp(2))
+    F = x*log(x)**2 + x*(1 - 2*log(2)) + (-2*x + 2*x*log(2))*log(x) + \
+        (x + exp(2)/6)*log(3*x + exp(2)) + exp(2)*log(3*x + exp(2))/6
+    assert F == integrate(f, x)
+
+    f = (x + exp(3))/x**2
+    F = log(x) - exp(3)/x
+    assert F == integrate(f, x)
+
+    f = (x**2 + exp(5))/x
+    F = x**2/2 + exp(5)*log(x)
+    assert F == integrate(f, x)
+
+    f = x/(2*x + tanh(1))
+    F = x/2 - log(2*x + tanh(1))*tanh(1)/4
+    assert F == integrate(f, x)
+
+    f = x - sinh(4)/x
+    F = x**2/2 - log(x)*sinh(4)
+    assert F == integrate(f, x)
+
+    f = log(x + exp(5)/x)
+    F = x*log(x + exp(5)/x) - x + 2*exp(Rational(5, 2))*atan(x*exp(Rational(-5, 2)))
+    assert F == integrate(f, x)
+
+    f = x**5/(x + E)
+    F = x**5/5 - E*x**4/4 + x**3*exp(2)/3 - x**2*exp(3)/2 + x*exp(4) - exp(5)*log(x + E)
+    assert F == integrate(f, x)
+
+    f = 4*x/(x + sinh(5))
+    F = 4*x - 4*log(x + sinh(5))*sinh(5)
+    assert F == integrate(f, x)
+
+    f = x**2/(2*x + sinh(2))
+    F = x**2/4 - x*sinh(2)/4 + log(2*x + sinh(2))*sinh(2)**2/8
+    assert F == integrate(f, x)
+
+    f = -x**2/(x + E)
+    F = -x**2/2 + E*x - exp(2)*log(x + E)
+    assert F == integrate(f, x)
+
+    f = (2*x + 3)*exp(5)/x
+    F = 2*x*exp(5) + 3*exp(5)*log(x)
+    assert F == integrate(f, x)
+
+    f = x + 2 + cosh(3)/x
+    F = x**2/2 + 2*x + log(x)*cosh(3)
+    assert F == integrate(f, x)
+
+    f = x - tanh(1)/x**3
+    F = x**2/2 + tanh(1)/(2*x**2)
+    assert F == integrate(f, x)
+
+    f = (3*x - exp(6))/x
+    F = 3*x - exp(6)*log(x)
+    assert F == integrate(f, x)
+
+    f = x**4/(x + exp(5))**2 + x
+    F = x**3/3 + x**2*(Rational(1, 2) - exp(5)) + 3*x*exp(10) - 4*exp(15)*log(x + exp(5)) - exp(20)/(x + exp(5))
+    assert F == integrate(f, x)
+
+    f = x*(x + exp(10)/x**2) + x
+    F = x**3/3 + x**2/2 + exp(10)*log(x)
+    assert F == integrate(f, x)
+
+    f = x + x/(5*x + sinh(3))
+    F = x**2/2 + x/5 - log(5*x + sinh(3))*sinh(3)/25
+    assert F == integrate(f, x)
+
+    f = (x + exp(3))/(2*x**2 + 2*x)
+    F = exp(3)*log(x)/2 + (Rational(1, 2) - exp(3)/2)*log(x + 1)
+    assert F == integrate(f, x)
+
+    f = log(x + 4*sinh(4))
+    F = x*log(x + 4*sinh(4)) - x + 4*log(x + 4*sinh(4))*sinh(4)
+    assert F == integrate(f, x)
+
+    f = -x + 20*(exp(-5) - atan(4)/x)**3*sin(4)/x
+    F = (-x**2*exp(15)/2 + 20*log(x)*sin(4) - (-180*x**2*exp(5)*sin(4)*atan(4) + 90*x*exp(10)*sin(4)*atan(4)**2 - \
+        20*exp(15)*sin(4)*atan(4)**3)/(3*x**3))*exp(-15)
+    assert F == integrate(f, x)
+
+    f = 2*x**2*exp(-4) + 6/x
+    F_true = (2*x**3/3 + 6*exp(4)*log(x))*exp(-4)
+    assert F_true == integrate(f, x)
diff --git a/sympy/polys/domains/tests/test_domains.py b/sympy/polys/domains/tests/test_domains.py
index b26af124ca..41cd8dd9b8 100644
--- a/sympy/polys/domains/tests/test_domains.py
+++ b/sympy/polys/domains/tests/test_domains.py
@@ -1,6 +1,6 @@
 """Tests for classes defining properties of ground domains, e.g. ZZ, QQ, ZZ[x] ... """
 
-from sympy import I, S, sqrt, sin, oo, Poly, Float, Integer, Rational, pi
+from sympy import I, S, sqrt, sin, oo, Poly, Float, Integer, Rational, pi, exp, E
 from sympy.abc import x, y, z
 
 from sympy.utilities.iterables import cartes
@@ -1180,3 +1180,10 @@ def test_Domain_is_nonpositive():
     a, b = [CC.convert(x) for x in (2 + I, 5)]
     assert CC.is_nonpositive(a) == False
     assert CC.is_nonpositive(b) == False
+
+
+def test_exponential_domain():
+    K = ZZ[E]
+    eK = K.from_sympy(E)
+    assert K.from_sympy(exp(3)) == eK ** 3
+    assert K.convert(exp(3)) == eK ** 3
diff --git a/sympy/polys/tests/test_rings.py b/sympy/polys/tests/test_rings.py
index 5e4e5e96eb..87d1702417 100644
--- a/sympy/polys/tests/test_rings.py
+++ b/sympy/polys/tests/test_rings.py
@@ -13,7 +13,7 @@
 from sympy.testing.pytest import raises
 from sympy.core import Symbol, symbols
 
-from sympy import sqrt, pi, oo
+from sympy import sqrt, pi, oo, exp
 
 def test_PolyRing___init__():
     x, y, z, t = map(Symbol, "xyzt")
@@ -276,6 +276,10 @@ def test_PolyElement_from_expr():
     f = R.from_expr(x**3*y*z + x**2*y**7 + 1)
     assert f == X**3*Y*Z + X**2*Y**7 + 1 and isinstance(f, R.dtype)
 
+    r, F = sring([exp(2)])
+    f = r.from_expr(exp(2))
+    assert f == F[0] and isinstance(f, r.dtype)
+
     raises(ValueError, lambda: R.from_expr(1/x))
     raises(ValueError, lambda: R.from_expr(2**x))
     raises(ValueError, lambda: R.from_expr(7*x + sqrt(2)))