class_docstr: Represents unevaluated integral.
docstr: Calculate the anti-derivative to the function f(x).
  
  Explanation
  ===========
  
  The following algorithms are applied (roughly in this order):
  
  1. Simple heuristics (based on pattern matching and integral table):
  
     - most frequently used functions (e.g. polynomials, products of
       trig functions)
  
  2. Integration of rational functions:
  
     - A complete algorithm for integrating rational functions is
       implemented (the Lazard-Rioboo-Trager algorithm).  The algorithm
       also uses the partial fraction decomposition algorithm
       implemented in apart() as a preprocessor to make this process
       faster.  Note that the integral of a rational function is always
       elementary, but in general, it may include a RootSum.
  
  3. Full Risch algorithm:
  
     - The Risch algorithm is a complete decision
       procedure for integrating elementary functions, which means that
       given any elementary function, it will either compute an
       elementary antiderivative, or else prove that none exists.
       Currently, part of transcendental case is implemented, meaning
       elementary integrals containing exponentials, logarithms, and
       (soon!) trigonometric functions can be computed.  The algebraic
       case, e.g., functions containing roots, is much more difficult
       and is not implemented yet.
  
     - If the routine fails (because the integrand is not elementary, or
       because a case is not implemented yet), it continues on to the
       next algorithms below.  If the routine proves that the integrals
       is nonelementary, it still moves on to the algorithms below,
       because we might be able to find a closed-form solution in terms
       of special functions.  If risch=True, however, it will stop here.
  
  4. The Meijer G-Function algorithm:
  
     - This algorithm works by first rewriting the integrand in terms of
       very general Meijer G-Function (meijerg in SymPy), integrating
       it, and then rewriting the result back, if possible.  This
       algorithm is particularly powerful for definite integrals (which
       is actually part of a different method of Integral), since it can
       compute closed-form solutions of definite integrals even when no
       closed-form indefinite integral exists.  But it also is capable
       of computing many indefinite integrals as well.
  
     - Another advantage of this method is that it can use some results
       about the Meijer G-Function to give a result in terms of a
       Piecewise expression, which allows to express conditionally
       convergent integrals.
  
     - Setting meijerg=True will cause integrate() to use only this
       method.
  
  5. The "manual integration" algorithm:
  
     - This algorithm tries to mimic how a person would find an
       antiderivative by hand, for example by looking for a
       substitution or applying integration by parts. This algorithm
       does not handle as many integrands but can return results in a
       more familiar form.
  
     - Sometimes this algorithm can evaluate parts of an integral; in
       this case integrate() will try to evaluate the rest of the
       integrand using the other methods here.
  
     - Setting manual=True will cause integrate() to use only this
       method.
  
  6. The Heuristic Risch algorithm:
  
     - This is a heuristic version of the Risch algorithm, meaning that
       it is not deterministic.  This is tried as a last resort because
       it can be very slow.  It is still used because not enough of the
       full Risch algorithm is implemented, so that there are still some
       integrals that can only be computed using this method.  The goal
       is to implement enough of the Risch and Meijer G-function methods
       so that this can be deleted.
  
       Setting heurisch=True will cause integrate() to use only this
       method. Set heurisch=False to not use it.
docstr_tok: ["Calculate","the","anti-derivative","to","the","function","f","(","x",")",".","Explanation","===========","The","following","algorithms","are","applied","(","roughly","in","this","order",")",":","1",".","Simple","heuristics","(","based","on","pattern","matching","and","integral","table",")",":","-","most","frequently","used","functions","(","e.g",".","polynomials",",","products","of","trig","functions",")","2",".","Integration","of","rational","functions",":","-","A","complete","algorithm","for","integrating","rational","functions","is","implemented","(","the","Lazard-Rioboo-Trager","algorithm",")",".","The","algorithm","also","uses","the","partial","fraction","decomposition","algorithm","implemented","in","apart","(",")","as","a","preprocessor","to","make","this","process","faster",".","Note","that","the","integral","of","a","rational","function","is","always","elementary",",","but","in","general",",","it","may","include","a","RootSum",".","3",".","Full","Risch","algorithm",":","-","The","Risch","algorithm","is","a","complete","decision","procedure","for","integrating","elementary","functions",",","which","means","that","given","any","elementary","function",",","it","will","either","compute","an","elementary","antiderivative",",","or","else","prove","that","none","exists",".","Currently",",","part","of","transcendental","case","is","implemented",",","meaning","elementary","integrals","containing","exponentials",",","logarithms",",","and","(","soon","!",")","trigonometric","functions","can","be","computed",".","The","algebraic","case",",","e.g.",",","functions","containing","roots",",","is","much","more","difficult","and","is","not","implemented","yet",".","-","If","the","routine","fails","(","because","the","integrand","is","not","elementary",",","or","because","a","case","is","not","implemented","yet",")",",","it","continues","on","to","the","next","algorithms","below",".","If","the","routine","proves","that","the","integrals","is","nonelementary",",","it","still","moves","on","to","the","algorithms","below",",","because","we","might","be","able","to","find","a","closed-form","solution","in","terms","of","special","functions",".","If","risch=True",",","however",",","it","will","stop","here",".","4",".","The","Meijer","G-Function","algorithm",":","-","This","algorithm","works","by","first","rewriting","the","integrand","in","terms","of","very","general","Meijer","G-Function","(","meijerg","in","SymPy",")",",","integrating","it",",","and","then","rewriting","the","result","back",",","if","possible",".","This","algorithm","is","particularly","powerful","for","definite","integrals","(","which","is","actually","part","of","a","different","method","of","Integral",")",",","since","it","can","compute","closed-form","solutions","of","definite","integrals","even","when","no","closed-form","indefinite","integral","exists",".","But","it","also","is","capable","of","computing","many","indefinite","integrals","as","well",".","-","Another","advantage","of","this","method","is","that","it","can","use","some","results","about","the","Meijer","G-Function","to","give","a","result","in","terms","of","a","Piecewise","expression",",","which","allows","to","express","conditionally","convergent","integrals",".","-","Setting","meijerg=True","will","cause","integrate","(",")","to","use","only","this","method",".","5",".","The","``","manual","integration","''","algorithm",":","-","This","algorithm","tries","to","mimic","how","a","person","would","find","an","antiderivative","by","hand",",","for","example","by","looking","for","a","substitution","or","applying","integration","by","parts",".","This","algorithm","does","not","handle","as","many","integrands","but","can","return","results","in","a","more","familiar","form",".","-","Sometimes","this","algorithm","can","evaluate","parts","of","an","integral",";","in","this","case","integrate","(",")","will","try","to","evaluate","the","rest","of","the","integrand","using","the","other","methods","here",".","-","Setting","manual=True","will","cause","integrate","(",")","to","use","only","this","method",".","6",".","The","Heuristic","Risch","algorithm",":","-","This","is","a","heuristic","version","of","the","Risch","algorithm",",","meaning","that","it","is","not","deterministic",".","This","is","tried","as","a","last","resort","because","it","can","be","very","slow",".","It","is","still","used","because","not","enough","of","the","full","Risch","algorithm","is","implemented",",","so","that","there","are","still","some","integrals","that","can","only","be","computed","using","this","method",".","The","goal","is","to","implement","enough","of","the","Risch","and","Meijer","G-function","methods","so","that","this","can","be","deleted",".","Setting","heurisch=True","will","cause","integrate","(",")","to","use","only","this","method",".","Set","heurisch=False","to","not","use","it","."]
code: def _eval_integral(
      self,
      f,
      x,
      meijerg=None,
      risch=None,
      manual=None,
      heurisch=None,
      conds="piecewise",
      final=None,
  ):
      """
      Calculate the anti-derivative to the function f(x).
  
      Explanation
      ===========
  
      The following algorithms are applied (roughly in this order):
  
      1. Simple heuristics (based on pattern matching and integral table):
  
         - most frequently used functions (e.g. polynomials, products of
           trig functions)
  
      2. Integration of rational functions:
  
         - A complete algorithm for integrating rational functions is
           implemented (the Lazard-Rioboo-Trager algorithm).  The algorithm
           also uses the partial fraction decomposition algorithm
           implemented in apart() as a preprocessor to make this process
           faster.  Note that the integral of a rational function is always
           elementary, but in general, it may include a RootSum.
  
      3. Full Risch algorithm:
  
         - The Risch algorithm is a complete decision
           procedure for integrating elementary functions, which means that
           given any elementary function, it will either compute an
           elementary antiderivative, or else prove that none exists.
           Currently, part of transcendental case is implemented, meaning
           elementary integrals containing exponentials, logarithms, and
           (soon!) trigonometric functions can be computed.  The algebraic
           case, e.g., functions containing roots, is much more difficult
           and is not implemented yet.
  
         - If the routine fails (because the integrand is not elementary, or
           because a case is not implemented yet), it continues on to the
           next algorithms below.  If the routine proves that the integrals
           is nonelementary, it still moves on to the algorithms below,
           because we might be able to find a closed-form solution in terms
           of special functions.  If risch=True, however, it will stop here.
  
      4. The Meijer G-Function algorithm:
  
         - This algorithm works by first rewriting the integrand in terms of
           very general Meijer G-Function (meijerg in SymPy), integrating
           it, and then rewriting the result back, if possible.  This
           algorithm is particularly powerful for definite integrals (which
           is actually part of a different method of Integral), since it can
           compute closed-form solutions of definite integrals even when no
           closed-form indefinite integral exists.  But it also is capable
           of computing many indefinite integrals as well.
  
         - Another advantage of this method is that it can use some results
           about the Meijer G-Function to give a result in terms of a
           Piecewise expression, which allows to express conditionally
           convergent integrals.
  
         - Setting meijerg=True will cause integrate() to use only this
           method.
  
      5. The "manual integration" algorithm:
  
         - This algorithm tries to mimic how a person would find an
           antiderivative by hand, for example by looking for a
           substitution or applying integration by parts. This algorithm
           does not handle as many integrands but can return results in a
           more familiar form.
  
         - Sometimes this algorithm can evaluate parts of an integral; in
           this case integrate() will try to evaluate the rest of the
           integrand using the other methods here.
  
         - Setting manual=True will cause integrate() to use only this
           method.
  
      6. The Heuristic Risch algorithm:
  
         - This is a heuristic version of the Risch algorithm, meaning that
           it is not deterministic.  This is tried as a last resort because
           it can be very slow.  It is still used because not enough of the
           full Risch algorithm is implemented, so that there are still some
           integrals that can only be computed using this method.  The goal
           is to implement enough of the Risch and Meijer G-function methods
           so that this can be deleted.
  
           Setting heurisch=True will cause integrate() to use only this
           method. Set heurisch=False to not use it.
  
      """
  
      from sympy.integrals.risch import (
          risch_integrate,
          NonElementaryIntegral,
      )
      from sympy.integrals.manualintegrate import manualintegrate
  
      if risch:
          try:
              return risch_integrate(f, x, conds=conds)
          except NotImplementedError:
              return None
  
      if manual:
          try:
              result = manualintegrate(f, x)
              if result is not None and result.func != Integral:
                  return result
          except (ValueError, PolynomialError):
              pass
  
      eval_kwargs = {
          "meijerg": meijerg,
          "risch": risch,
          "manual": manual,
          "heurisch": heurisch,
          "conds": conds,
      }
  
      # if it is a poly(x) then let the polynomial integrate itself (fast)
      #
      # It is important to make this check first, otherwise the other code
      # will return a SymPy expression instead of a Polynomial.
      #
      # see Polynomial for details.
      if isinstance(f, Poly) and not (manual or meijerg or risch):
          # Note: this is deprecated, but the deprecation warning is already
          # issued in the Integral constructor.
          return f.integrate(x)
  
      # Piecewise antiderivatives need to call special integrate.
      if isinstance(f, Piecewise):
          return f.piecewise_integrate(x, **eval_kwargs)
  
      # let's cut it short if `f` does not depend on `x`; if
      # x is only a dummy, that will be handled below
      if not f.has(x):
          return f * x
  
      # try to convert to poly(x) and then integrate if successful (fast)
      poly = f.as_poly(x)
      if poly is not None and not (manual or meijerg or risch):
          return poly.integrate().as_expr()
  
      if risch is not False:
          try:
              result, i = risch_integrate(
                  f, x, separate_integral=True, conds=conds
              )
          except NotImplementedError:
              pass
          else:
              if i:
                  # There was a nonelementary integral. Try integrating it.
  
                  # if no part of the NonElementaryIntegral is integrated by
                  # the Risch algorithm, then use the original function to
                  # integrate, instead of re-written one
                  if result == 0:
                      return NonElementaryIntegral(f, x).doit(
                          risch=False
                      )
                  else:
                      return result + i.doit(risch=False)
              else:
                  return result
  
      # since Integral(f=g1+g2+...) == Integral(g1) + Integral(g2) + ...
      # we are going to handle Add terms separately,
      # if `f` is not Add -- we only have one term
  
      # Note that in general, this is a bad idea, because Integral(g1) +
      # Integral(g2) might not be computable, even if Integral(g1 + g2) is.
      # For example, Integral(x**x + x**x*log(x)).  But many heuristics only
      # work term-wise.  So we compute this step last, after trying
      # risch_integrate.  We also try risch_integrate again in this loop,
      # because maybe the integral is a sum of an elementary part and a
      # nonelementary part (like erf(x) + exp(x)).  risch_integrate() is
      # quite fast, so this is acceptable.
      from sympy.simplify.fu import sincos_to_sum
  
      parts = []
      args = Add.make_args(f)
      for g in args:
          coeff, g = g.as_independent(x)
  
          # g(x) = const
          if g is S.One and not meijerg:
              parts.append(coeff * x)
              continue
  
          # g(x) = expr + O(x**n)
          order_term = g.getO()
  
          if order_term is not None:
              h = self._eval_integral(g.removeO(), x, **eval_kwargs)
  
              if h is not None:
                  h_order_expr = self._eval_integral(
                      order_term.expr, x, **eval_kwargs
                  )
  
                  if h_order_expr is not None:
                      h_order_term = order_term.func(
                          h_order_expr, *order_term.variables
                      )
                      parts.append(coeff * (h + h_order_term))
                      continue
  
              # NOTE: if there is O(x**n) and we fail to integrate then
              # there is no point in trying other methods because they
              # will fail, too.
              return None
  
          #               c
          # g(x) = (a*x+b)
          if g.is_Pow and not g.exp.has(x) and not meijerg:
              a = Wild("a", exclude=[x])
              b = Wild("b", exclude=[x])
  
              M = g.base.match(a * x + b)
  
              if M is not None:
                  if g.exp == -1:
                      h = log(g.base)
                  elif conds != "piecewise":
                      h = g.base ** (g.exp + 1) / (g.exp + 1)
                  else:
                      h1 = log(g.base)
                      h2 = g.base ** (g.exp + 1) / (g.exp + 1)
                      h = Piecewise((h2, Ne(g.exp, -1)), (h1, True))
  
                  parts.append(coeff * h / M[a])
                  continue
  
          #        poly(x)
          # g(x) = -------
          #        poly(x)
          if g.is_rational_function(x) and not (
              manual or meijerg or risch
          ):
              parts.append(coeff * ratint(g, x))
              continue
  
          if not (manual or meijerg or risch):
              # g(x) = Mul(trig)
              h = trigintegrate(g, x, conds=conds)
              if h is not None:
                  parts.append(coeff * h)
                  continue
  
              # g(x) has at least a DiracDelta term
              h = deltaintegrate(g, x)
              if h is not None:
                  parts.append(coeff * h)
                  continue
  
              from .singularityfunctions import singularityintegrate
  
              # g(x) has at least a Singularity Function term
              h = singularityintegrate(g, x)
              if h is not None:
                  parts.append(coeff * h)
                  continue
  
              # Try risch again.
              if risch is not False:
                  try:
                      h, i = risch_integrate(
                          g, x, separate_integral=True, conds=conds
                      )
                  except NotImplementedError:
                      h = None
                  else:
                      if i:
                          h = h + i.doit(risch=False)
  
                      parts.append(coeff * h)
                      continue
  
              # fall back to heurisch
              if heurisch is not False:
                  from sympy.integrals.heurisch import (
                      heurisch as heurisch_,
                      heurisch_wrapper,
                  )
  
                  try:
                      if conds == "piecewise":
                          h = heurisch_wrapper(g, x, hints=[])
                      else:
                          h = heurisch_(g, x, hints=[])
                  except PolynomialError:
                      # XXX: this exception means there is a bug in the
                      # implementation of heuristic Risch integration
                      # algorithm.
                      h = None
          else:
              h = None
  
          if meijerg is not False and h is None:
              # rewrite using G functions
              try:
                  h = meijerint_indefinite(g, x)
              except NotImplementedError:
                  _debug("NotImplementedError from meijerint_definite")
              if h is not None:
                  parts.append(coeff * h)
                  continue
  
          if h is None and manual is not False:
              try:
                  result = manualintegrate(g, x)
                  if result is not None and not isinstance(
                      result, Integral
                  ):
                      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
                          new_eval_kwargs["final"] = False
                          result = result.func(
                              *[
                                  arg.doit(**new_eval_kwargs)
                                  if arg.has(Integral)
                                  else arg
                                  for arg in result.args
                              ]
                          ).expand(
                              multinomial=False,
                              log=False,
                              power_exp=False,
                              power_base=False,
                          )
                      if not result.has(Integral):
                          parts.append(coeff * result)
                          continue
              except (ValueError, PolynomialError):
                  # can't handle some SymPy expressions
                  pass
  
          # if we failed maybe it was because we had
          # a product that could have been expanded,
          # so let's try an expansion of the whole
          # thing before giving up; we don't try this
          # at the outset because there are things
          # that cannot be solved unless they are
          # NOT expanded e.g., x**x*(1+log(x)). There
          # should probably be a checker somewhere in this
          # routine to look for such cases and try to do
          # collection on the expressions if they are already
          # in an expanded form
          if not h and len(args) == 1:
              f = sincos_to_sum(f).expand(mul=True, deep=False)
              if f.is_Add:
                  # Note: risch will be identical on the expanded
                  # expression, but maybe it will be able to pick out parts,
                  # like x*(exp(x) + erf(x)).
                  return self._eval_integral(f, x, **eval_kwargs)
  
          if h is not None:
              parts.append(coeff * h)
          else:
              return None
  
      return Add(*parts)
  
imports: from typing import Tuple
  from sympy.concrete.expr_with_limits import AddWithLimits
  from sympy.core.add import Add
  from sympy.core.basic import Basic
  from sympy.core.containers import Tuple
  from sympy.core.expr import Expr
  from sympy.core.exprtools import factor_terms
  from sympy.core.function import diff
  from sympy.core.logic import fuzzy_bool
  from sympy.core.mul import Mul
  from sympy.core.numbers import oo, pi
  from sympy.core.relational import Ne
  from sympy.core.singleton import S
  from sympy.core.symbol import Dummy, Symbol, Wild
  from sympy.core.sympify import sympify
  from sympy.functions import Piecewise, sqrt, piecewise_fold, tan, cot, atan
  from sympy.functions.elementary.exponential import log
  from sympy.functions.elementary.integers import floor
  from sympy.functions.elementary.complexes import Abs, sign
  from sympy.functions.elementary.miscellaneous import Min, Max
  from sympy.functions.special.singularity_functions import Heaviside
  from .rationaltools import ratint
  from sympy.matrices import MatrixBase
  from sympy.polys import Poly, PolynomialError
  from sympy.series.formal import FormalPowerSeries
  from sympy.series.limits import limit
  from sympy.series.order import Order
  from sympy.tensor.functions import shape
  from sympy.utilities.exceptions import sympy_deprecation_warning
  from sympy.utilities.iterables import is_sequence
  from sympy.utilities.misc import filldedent
  from .deltafunctions import deltaintegrate
  from .meijerint import meijerint_definite, meijerint_indefinite, _debug
  from .trigonometry import trigintegrate
label_desc: Use image node_id 8 for calling the Integral obj's underlying member method code with example usage: obj._eval_integral(f, x, meijerg, risch, manual, heurisch, conds, final) and returns: Add, f, f, unknown, poly, risch_integrate, None, None, None, result, result, self, NonElementaryIntegral, unknown