Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

integrate: Correctly handle manual, meijerg, risch flags #14475

Merged
merged 1 commit into from Mar 12, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
33 changes: 23 additions & 10 deletions sympy/integrals/integrals.py
Expand Up @@ -385,6 +385,14 @@ def doit(self, **hints):
conds = hints.get('conds', 'piecewise')
risch = hints.get('risch', None)
manual = hints.get('manual', None)
if len(list(filter(None, (manual, meijerg, risch)))) > 1:
raise ValueError("At most one of manual, meijerg, risch can be True")
elif manual:
meijerg = risch = False
elif meijerg:
manual = risch = False
elif risch:
manual = meijerg = False
eval_kwargs = dict(meijerg=meijerg, risch=risch, manual=manual,
conds=conds)

Expand Down Expand Up @@ -458,8 +466,8 @@ def doit(self, **hints):
.rewrite(Piecewise).xreplace({xr: xab[0]}))
elif function.has(Min, Max):
function = function.rewrite(Piecewise)
if function.has(Piecewise) and \
not isinstance(function, Piecewise):
if (function.has(Piecewise) and
not isinstance(function, Piecewise)):
function = piecewise_fold(function)
if isinstance(function, Piecewise):
if len(xab) == 1:
Expand Down Expand Up @@ -830,7 +838,7 @@ def _eval_integral(self, f, x, meijerg=None, risch=None, manual=None,
# will return a sympy expression instead of a Polynomial.
#
# see Polynomial for details.
if isinstance(f, Poly) and not meijerg:
if isinstance(f, Poly) and not (manual or meijerg or risch):
return f.integrate(x)

# Piecewise antiderivatives need to call special integrate.
Expand All @@ -844,7 +852,7 @@ def _eval_integral(self, f, x, meijerg=None, risch=None, manual=None,

# try to convert to poly(x) and then integrate if successful (fast)
poly = f.as_poly(x)
if poly is not None and not meijerg:
if poly is not None and not (manual or meijerg or risch):
return poly.integrate().as_expr()

if risch is not False:
Expand Down Expand Up @@ -934,11 +942,11 @@ def _eval_integral(self, f, x, meijerg=None, risch=None, manual=None,
# poly(x)
# g(x) = -------
# poly(x)
if g.is_rational_function(x) and not meijerg:
if g.is_rational_function(x) and not (manual or meijerg or risch):
parts.append(coeff * ratint(g, x))
continue

if not meijerg:
if not (manual or meijerg or risch):
# g(x) = Mul(trig)
h = trigintegrate(g, x, conds=conds)
if h is not None:
Expand Down Expand Up @@ -1001,11 +1009,16 @@ def _eval_integral(self, f, x, meijerg=None, risch=None, manual=None,
try:
result = manualintegrate(g, x)
if result is not None and not isinstance(result, Integral):
if result.has(Integral):
# try to have other algorithms do the integrals
# manualintegrate can't handle
if result.has(Integral) and not manual:
# Try to have other algorithms do the integrals
# manualintegrate can't handle,
# unless we were asked to use manual only.
# Keep the rest of eval_kwargs in case another
# method was set to False already
new_eval_kwargs = eval_kwargs
new_eval_kwargs["manual"] = False
result = result.func(*[
arg.doit(manual=False) if
arg.doit(**new_eval_kwargs) if
arg.has(Integral) else arg
for arg in result.args
]).expand(multinomial=False,
Expand Down
12 changes: 12 additions & 0 deletions sympy/integrals/tests/test_integrals.py
Expand Up @@ -1150,6 +1150,18 @@ def test_powers():
assert integrate(2**x + 3**x, x) == 2**x/log(2) + 3**x/log(3)


def test_manual_option():
raises(ValueError, lambda: integrate(1/x, x, manual=True, meijerg=True))
# an example of a function that manual integration cannot handle
assert integrate(exp(x**2), x, manual=True) == Integral(exp(x**2), x)


def test_meijerg_option():
raises(ValueError, lambda: integrate(1/x, x, meijerg=True, risch=True))
# an example of a function that meijerg integration cannot handle
assert integrate(tan(x), x, meijerg=True) == Integral(tan(x), x)


def test_risch_option():
# risch=True only allowed on indefinite integrals
raises(ValueError, lambda: integrate(1/log(x), (x, 0, oo), risch=True))
Expand Down