class_docstr: Represents a piecewise function.
  
  Usage:
  
    Piecewise( (expr,cond), (expr,cond), ... )
      - Each argument is a 2-tuple defining an expression and condition
      - The conds are evaluated in turn returning the first that is True.
        If any of the evaluated conds are not explicitly False,
        e.g. ``x < 1``, the function is returned in symbolic form.
      - If the function is evaluated at a place where all conditions are False,
        nan will be returned.
      - Pairs where the cond is explicitly False, will be removed and no pair
        appearing after a True condition will ever be retained. If a single
        pair with a True condition remains, it will be returned, even when
        evaluation is False.
  
  Examples
  ========
  
  >>> from sympy import Piecewise, log, piecewise_fold
  >>> from sympy.abc import x, y
  >>> f = x**2
  >>> g = log(x)
  >>> p = Piecewise((0, x < -1), (f, x <= 1), (g, True))
  >>> p.subs(x,1)
  1
  >>> p.subs(x,5)
  log(5)
  
  Booleans can contain Piecewise elements:
  
  >>> cond = (x < y).subs(x, Piecewise((2, x < 0), (3, True))); cond
  Piecewise((2, x < 0), (3, True)) < y
  
  The folded version of this results in a Piecewise whose
  expressions are Booleans:
  
  >>> folded_cond = piecewise_fold(cond); folded_cond
  Piecewise((2 < y, x < 0), (3 < y, True))
  
  When a Boolean containing Piecewise (like cond) or a Piecewise
  with Boolean expressions (like folded_cond) is used as a condition,
  it is converted to an equivalent :class:`~.ITE` object:
  
  >>> Piecewise((1, folded_cond))
  Piecewise((1, ITE(x < 0, y > 2, y > 3)))
  
  When a condition is an ``ITE``, it will be converted to a simplified
  Boolean expression:
  
  >>> piecewise_fold(_)
  Piecewise((1, ((x >= 0) | (y > 2)) & ((y > 3) | (x < 0))))
  
  See Also
  ========
  
  piecewise_fold
  piecewise_exclusive
  ITE
docstr: Evaluates the function along the sym in a given interval [a, b]
docstr_tok: ["Evaluates","the","function","along","the","sym","in","a","given","interval","[","a",",","b","]"]
code: def _eval_interval(self, sym, a, b, _first=True):
      """Evaluates the function along the sym in a given interval [a, b]"""
      # FIXME: Currently complex intervals are not supported.  A possible
      # replacement algorithm, discussed in issue 5227, can be found in the
      # following papers;
      #     http://portal.acm.org/citation.cfm?id=281649
      #     http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.70.4127&rep=rep1&type=pdf
  
      if a is None or b is None:
          # In this case, it is just simple substitution
          return super()._eval_interval(sym, a, b)
      else:
          x, lo, hi = map(as_Basic, (sym, a, b))
  
      if _first:  # get only x-dependent relationals
  
          def handler(ipw):
              if isinstance(ipw, self.func):
                  return ipw._eval_interval(x, lo, hi, _first=None)
              else:
                  return ipw._eval_interval(x, lo, hi)
  
          irv = self._handle_irel(x, handler)
          if irv is not None:
              return irv
  
          if (lo < hi) is S.false or (
              lo is S.Infinity or hi is S.NegativeInfinity
          ):
              rv = self._eval_interval(x, hi, lo, _first=False)
              if isinstance(rv, Piecewise):
                  rv = Piecewise(*[(-e, c) for e, c in rv.args])
              else:
                  rv = -rv
              return rv
  
          if (lo < hi) is S.true or (
              hi is S.Infinity or lo is S.NegativeInfinity
          ):
              pass
          else:
              _a = Dummy("lo")
              _b = Dummy("hi")
              a = lo if lo.is_comparable else _a
              b = hi if hi.is_comparable else _b
              pos = self._eval_interval(x, a, b, _first=False)
              if a == _a and b == _b:
                  # it's purely symbolic so just swap lo and hi and
                  # change the sign to get the value for when lo > hi
                  neg, pos = (
                      -pos.xreplace({_a: hi, _b: lo}),
                      pos.xreplace({_a: lo, _b: hi}),
                  )
              else:
                  # at least one of the bounds was comparable, so allow
                  # _eval_interval to use that information when computing
                  # the interval with lo and hi reversed
                  neg, pos = (
                      -self._eval_interval(x, hi, lo, _first=False),
                      pos.xreplace({_a: lo, _b: hi}),
                  )
  
              # allow simplification based on ordering of lo and hi
              p = Dummy("", positive=True)
              if lo.is_Symbol:
                  pos = pos.xreplace({lo: hi - p}).xreplace(
                      {p: hi - lo}
                  )
                  neg = neg.xreplace({lo: hi + p}).xreplace(
                      {p: lo - hi}
                  )
              elif hi.is_Symbol:
                  pos = pos.xreplace({hi: lo + p}).xreplace(
                      {p: hi - lo}
                  )
                  neg = neg.xreplace({hi: lo - p}).xreplace(
                      {p: lo - hi}
                  )
              # evaluate limits that may have unevaluate Min/Max
              touch = lambda _: _.replace(
                  lambda x: isinstance(x, (Min, Max)),
                  lambda x: x.func(*x.args),
              )
              neg = touch(neg)
              pos = touch(pos)
              # assemble return expression; make the first condition be Lt
              # b/c then the first expression will look the same whether
              # the lo or hi limit is symbolic
              if a == _a:  # the lower limit was symbolic
                  rv = Piecewise((pos, lo < hi), (neg, True))
              else:
                  rv = Piecewise((neg, hi < lo), (pos, True))
  
              if rv == Undefined:
                  raise ValueError(
                      "Can't integrate across undefined region."
                  )
              if any(isinstance(i, Piecewise) for i in (pos, neg)):
                  rv = piecewise_fold(rv)
              return rv
  
      # handle a Piecewise with lo <= hi and no x-independent relationals
      # -----------------------------------------------------------------
      ok, abei = self._intervals(x)
      if not ok:
          from sympy.integrals.integrals import Integral
  
          # not being able to do the interval of f(x) can
          # be stated as not being able to do the integral
          # of f'(x) over the same range
          return Integral(self.diff(x), (x, lo, hi))  # unevaluated
  
      pieces = [(a, b) for a, b, _, _ in abei]
      done = [(lo, hi, -1)]
      oo = S.Infinity
      for k, p in enumerate(pieces):
          if p[:2] == (-oo, oo):
              # all undone intervals will get this key
              for j, (a, b, i) in enumerate(done):
                  if i == -1:
                      done[j] = a, b, k
              break  # nothing else to consider
          N = len(done) - 1
          for j, (a, b, i) in enumerate(reversed(done)):
              if i == -1:
                  j = N - j
                  done[j : j + 1] = _clip(p, (a, b), k)
      done = [(a, b, i) for a, b, i in done if a != b]
  
      # return the sum of the intervals
      sum = S.Zero
      upto = None
      for a, b, i in done:
          if i == -1:
              if upto is None:
                  return Undefined
              # TODO simplify hi <= upto
              return Piecewise((sum, hi <= upto), (Undefined, True))
          sum += abei[i][-2]._eval_interval(x, a, b)
          upto = b
      return sum
  
imports: from sympy.core import S, Function, diff, Tuple, Dummy, Mul
  from sympy.core.basic import Basic, as_Basic
  from sympy.core.numbers import Rational, NumberSymbol, _illegal
  from sympy.core.parameters import global_parameters
  from sympy.core.relational import Lt, Gt, Eq, Ne, Relational, _canonical, _canonical_coeff
  from sympy.core.sorting import ordered
  from sympy.functions.elementary.miscellaneous import Max, Min
  from sympy.logic.boolalg import And, Boolean, distribute_and_over_or, Not, true, false, Or, ITE, simplify_logic, to_cnf, distribute_or_over_and
  from sympy.utilities.iterables import uniq, sift, common_prefix
  from sympy.utilities.misc import filldedent, func_name
  from itertools import product
label_desc: Use image node_id 14 for calling the Piecewise obj's underlying member method code with example usage: obj._eval_interval(sym, a, b, _first) and returns: sum, super, Integral, irv, rv, rv, Piecewise, ipw, ipw, Undefined