Piecewise functions - Functions

Skip to content
Back to top
View this page
Edit this page

# Piecewise functions

This module implement piecewise functions in a single variable. See `sage.sets.real_set` for more information about how to construct subsets of the real line for the domains.

EXAMPLES:

Sage

    sage: f = piecewise([((0,1), x^3), ([-1,0], -x^2)]);  f
    piecewise(x|-->x^3 on (0, 1), x|-->-x^2 on [-1, 0]; x)
    sage: 2*f
    2*piecewise(x|-->x^3 on (0, 1), x|-->-x^2 on [-1, 0]; x)
    sage: f(x=1/2)
    1/8
    sage: plot(f)    # not tested

Python

    >>> from sage.all import *
    >>> f = piecewise([((Integer(0),Integer(1)), x**Integer(3)), ([-Integer(1),Integer(0)], -x**Integer(2))]);  f
    piecewise(x|-->x^3 on (0, 1), x|-->-x^2 on [-1, 0]; x)
    >>> Integer(2)*f
    2*piecewise(x|-->x^3 on (0, 1), x|-->-x^2 on [-1, 0]; x)
    >>> f(x=Integer(1)/Integer(2))
    1/8
    >>> plot(f)    # not tested

Todo

Implement max/min location and values,

AUTHORS:

- David Joyner (2006-04): initial version

- David Joyner (2006-09): added __eq__, extend_by_zero_to, unextend, convolution, trapezoid, trapezoid_integral_approximation, riemann_sum, riemann_sum_integral_approximation, tangent_line fixed bugs in __mul__, __add__

- David Joyner (2007-03): adding Hann filter for FS, added general FS filter methods for computing and plotting, added options to plotting of FS (eg, specifying rgb values are now allowed). Fixed bug in documentation reported by Pablo De Napoli.

- David Joyner (2007-09): bug fixes due to behaviour of SymbolicArithmetic

- David Joyner (2008-04): fixed docstring bugs reported by J Morrow; added support for Laplace transform of functions with infinite support.

- David Joyner (2008-07): fixed a left multiplication bug reported by C. Boncelet (by defining __rmul__ = __mul__).

- Paul Butler (2009-01): added indefinite integration and default_variable

- Volker Braun (2013): Complete rewrite

- Ralf Stephan (2015): Rewrite of convolution() and other calculus functions; many doctest adaptations

- Eric Gourgoulhon (2017): Improve documentation and user interface of Fourier series

class sage.functions.piecewise.PiecewiseFunction

  Bases: `BuiltinFunction`

  Piecewise function.

  EXAMPLES:

  Sage

      sage: var('x, y')
      (x, y)
      sage: f = piecewise([((0,1), x^2*y), ([-1,0], -x*y^2)], var=x);  f
      piecewise(x|-->x^2*y on (0, 1), x|-->-x*y^2 on [-1, 0]; x)
      sage: f(1/2)
      1/4*y
      sage: f(-1/2)
      1/2*y^2

  Python

      >>> from sage.all import *
      >>> var('x, y')
      (x, y)
      >>> f = piecewise([((Integer(0),Integer(1)), x**Integer(2)*y), ([-Integer(1),Integer(0)], -x*y**Integer(2))], var=x);  f
      piecewise(x|-->x^2*y on (0, 1), x|-->-x*y^2 on [-1, 0]; x)
      >>> f(Integer(1)/Integer(2))
      1/4*y
      >>> f(-Integer(1)/Integer(2))
      1/2*y^2

  class EvaluationMethods

    Bases: `object`

    convolution(parameters, variable, other)

      Return the convolution function, \(f*g(t)=\int_{-\infty}^\infty f(u)g(t-u)du\), for compactly supported \(f,g\).

      EXAMPLES:

      Sage

          sage: x = PolynomialRing(QQ, 'x').gen()

      Python

          >>> from sage.all import *
          >>> x = PolynomialRing(QQ, 'x').gen()

      Example 0:

      Sage

          sage: f = piecewise([[[0,1], 1]])
          sage: g = f.convolution(f); g
          piecewise(x|-->x on (0, 1],
                    x|-->-x + 2 on (1, 2]; x)
          sage: h = f.convolution(g); h
          piecewise(x|-->1/2*x^2 on (0, 1],
                    x|-->-x^2 + 3*x - 3/2 on (1, 2],
                    x|-->1/2*x^2 - 3*x + 9/2 on (2, 3]; x)

      [Python]

          >>> from sage.all import *
          >>> f = piecewise([[[Integer(0),Integer(1)], Integer(1)]])
          >>> g = f.convolution(f); g
          piecewise(x|-->x on (0, 1],
                    x|-->-x + 2 on (1, 2]; x)
          >>> h = f.convolution(g); h
          piecewise(x|-->1/2*x^2 on (0, 1],
                    x|-->-x^2 + 3*x - 3/2 on (1, 2],
                    x|-->1/2*x^2 - 3*x + 9/2 on (2, 3]; x)

      Example 1:

      Sage

          sage: f = piecewise([[(0,1), 1], [(1,2), 2], [(2,3), 1]])
          sage: g = f.convolution(f)
          sage: h = f.convolution(g); h
          piecewise(x|-->1/2*x^2 on (0, 1],
                    x|-->2*x^2 - 3*x + 3/2 on (1, 3],
                    x|-->-2*x^2 + 21*x - 69/2 on (3, 4],
                    x|-->-5*x^2 + 45*x - 165/2 on (4, 5],
                    x|-->-2*x^2 + 15*x - 15/2 on (5, 6],
                    x|-->2*x^2 - 33*x + 273/2 on (6, 8],
                    x|-->1/2*x^2 - 9*x + 81/2 on (8, 9]; x)

      Python

          >>> from sage.all import *
          >>> f = piecewise([[(Integer(0),Integer(1)), Integer(1)], [(Integer(1),Integer(2)), Integer(2)], [(Integer(2),Integer(3)), Integer(1)]])
          >>> g = f.convolution(f)
          >>> h = f.convolution(g); h
          piecewise(x|-->1/2*x^2 on (0, 1],
                    x|-->2*x^2 - 3*x + 3/2 on (1, 3],
                    x|-->-2*x^2 + 21*x - 69/2 on (3, 4],
                    x|-->-5*x^2 + 45*x - 165/2 on (4, 5],
                    x|-->-2*x^2 + 15*x - 15/2 on (5, 6],
                    x|-->2*x^2 - 33*x + 273/2 on (6, 8],
                    x|-->1/2*x^2 - 9*x + 81/2 on (8, 9]; x)

      Example 2:

      Sage

          sage: f = piecewise([[(-1,1), 1]])
          sage: g = piecewise([[(0,3), x]])
          sage: f.convolution(g)
          piecewise(x|-->1/2*x^2 + x + 1/2 on (-1, 1],
                    x|-->2*x on (1, 2],
                    x|-->-1/2*x^2 + x + 4 on (2, 4]; x)
          sage: g = piecewise([[(0,3), 1], [(3,4), 2]])
          sage: f.convolution(g)
          piecewise(x|-->x + 1 on (-1, 1],
                    x|-->2 on (1, 2],
                    x|-->x on (2, 3],
                    x|-->-x + 6 on (3, 4],
                    x|-->-2*x + 10 on (4, 5]; x)

      [Python]

          >>> from sage.all import *
          >>> f = piecewise([[(-Integer(1),Integer(1)), Integer(1)]])
          >>> g = piecewise([[(Integer(0),Integer(3)), x]])
          >>> f.convolution(g)
          piecewise(x|-->1/2*x^2 + x + 1/2 on (-1, 1],
                    x|-->2*x on (1, 2],
                    x|-->-1/2*x^2 + x + 4 on (2, 4]; x)
          >>> g = piecewise([[(Integer(0),Integer(3)), Integer(1)], [(Integer(3),Integer(4)), Integer(2)]])
          >>> f.convolution(g)
          piecewise(x|-->x + 1 on (-1, 1],
                    x|-->2 on (1, 2],
                    x|-->x on (2, 3],
                    x|-->-x + 6 on (3, 4],
                    x|-->-2*x + 10 on (4, 5]; x)

      Some unbounded but convergent cases now work:

      Sage

          sage: p = piecewise([[(2,oo),exp(-x)]])
          sage: q = piecewise([[[2,3],x]])
          sage: p.convolution(q)
          piecewise(x|-->(x - 3)*e^(-2) - e^(-x + 2) on (4, 5]; x)
          sage: q.convolution(p)
          piecewise(x|-->(x - 3)*e^(-2) - e^(-x + 2) on (4, 5]; x)

      Python

          >>> from sage.all import *
          >>> p = piecewise([[(Integer(2),oo),exp(-x)]])
          >>> q = piecewise([[[Integer(2),Integer(3)],x]])
          >>> p.convolution(q)
          piecewise(x|-->(x - 3)*e^(-2) - e^(-x + 2) on (4, 5]; x)
          >>> q.convolution(p)
          piecewise(x|-->(x - 3)*e^(-2) - e^(-x + 2) on (4, 5]; x)

    critical_points(parameters, variable)

      Return the critical points of this piecewise function.

      EXAMPLES:

      Sage

          sage: R.<x> = QQ[]
          sage: f1 = x^0
          sage: f2 = 10*x - x^2
          sage: f3 = 3*x^4 - 156*x^3 + 3036*x^2 - 26208*x
          sage: f = piecewise([[(0,3), f1], [(3,10), f2], [(10,20), f3]])
          sage: expected = [5, 12, 13, 14]
          sage: all(abs(e-a) < 0.001 for e,a in zip(expected, f.critical_points()))
          True

      Python

          >>> from sage.all import *
          >>> R = QQ['x']; (x,) = R._first_ngens(1)
          >>> f1 = x**Integer(0)
          >>> f2 = Integer(10)*x - x**Integer(2)
          >>> f3 = Integer(3)*x**Integer(4) - Integer(156)*x**Integer(3) + Integer(3036)*x**Integer(2) - Integer(26208)*x
          >>> f = piecewise([[(Integer(0),Integer(3)), f1], [(Integer(3),Integer(10)), f2], [(Integer(10),Integer(20)), f3]])
          >>> expected = [Integer(5), Integer(12), Integer(13), Integer(14)]
          >>> all(abs(e-a) < RealNumber('0.001') for e,a in zip(expected, f.critical_points()))
          True

    domain(parameters, variable)

      Return the domain.

      OUTPUT:

      The union of the domains of the individual pieces as a `RealSet`.

      EXAMPLES:

      Sage

          sage: f = piecewise([([0,0], sin(x)), ((0,2), cos(x))]);  f
          piecewise(x|-->sin(x) on {0}, x|-->cos(x) on (0, 2); x)
          sage: f.domain()
          [0, 2)

      Python

          >>> from sage.all import *
          >>> f = piecewise([([Integer(0),Integer(0)], sin(x)), ((Integer(0),Integer(2)), cos(x))]);  f
          piecewise(x|-->sin(x) on {0}, x|-->cos(x) on (0, 2); x)
          >>> f.domain()
          [0, 2)

    domains(parameters, variable)

      Return the individual domains.

      See also `expressions()`.

      OUTPUT:

      The collection of domains of the component functions as a tuple of `RealSet`.

      EXAMPLES:

      Sage

          sage: f = piecewise([([0,0], sin(x)), ((0,2), cos(x))]);  f
          piecewise(x|-->sin(x) on {0}, x|-->cos(x) on (0, 2); x)
          sage: f.domains()
          ({0}, (0, 2))

      Python

          >>> from sage.all import *
          >>> f = piecewise([([Integer(0),Integer(0)], sin(x)), ((Integer(0),Integer(2)), cos(x))]);  f
          piecewise(x|-->sin(x) on {0}, x|-->cos(x) on (0, 2); x)
          >>> f.domains()
          ({0}, (0, 2))

    end_points(parameters, variable)

      Return a list of all interval endpoints for this function.

      EXAMPLES:

      Sage

          sage: f1(x) = 1
          sage: f2(x) = 1 - x
          sage: f3(x) = x^2 - 5
          sage: f = piecewise([[(0,1), f1], [(1,2), f2], [(2,3), f3]])
          sage: f.end_points()
          [0, 1, 2, 3]
          sage: f = piecewise([([0,0], sin(x)), ((0,2), cos(x))]);  f
          piecewise(x|-->sin(x) on {0}, x|-->cos(x) on (0, 2); x)
          sage: f.end_points()
          [0, 2]

      Python

          >>> from sage.all import *
          >>> __tmp__=var("x"); f1 = symbolic_expression(Integer(1)).function(x)
          >>> __tmp__=var("x"); f2 = symbolic_expression(Integer(1) - x).function(x)
          >>> __tmp__=var("x"); f3 = symbolic_expression(x**Integer(2) - Integer(5)).function(x)
          >>> f = piecewise([[(Integer(0),Integer(1)), f1], [(Integer(1),Integer(2)), f2], [(Integer(2),Integer(3)), f3]])
          >>> f.end_points()
          [0, 1, 2, 3]
          >>> f = piecewise([([Integer(0),Integer(0)], sin(x)), ((Integer(0),Integer(2)), cos(x))]);  f
          piecewise(x|-->sin(x) on {0}, x|-->cos(x) on (0, 2); x)
          >>> f.end_points()
          [0, 2]

    expression_at(parameters, variable, point)

      Return the expression defining the piecewise function at `value`.

      INPUT:

      - `point` – a real number

      OUTPUT:

      The symbolic expression defining the function value at the given `point`.

      EXAMPLES:

      Sage

          sage: f = piecewise([([0,0], sin(x)), ((0,2), cos(x))]);  f
          piecewise(x|-->sin(x) on {0}, x|-->cos(x) on (0, 2); x)
          sage: f.expression_at(0)
          sin(x)
          sage: f.expression_at(1)
          cos(x)
          sage: f.expression_at(2)
          Traceback (most recent call last):
          ...
          ValueError: point is not in the domain

      Python

          >>> from sage.all import *
          >>> f = piecewise([([Integer(0),Integer(0)], sin(x)), ((Integer(0),Integer(2)), cos(x))]);  f
          piecewise(x|-->sin(x) on {0}, x|-->cos(x) on (0, 2); x)
          >>> f.expression_at(Integer(0))
          sin(x)
          >>> f.expression_at(Integer(1))
          cos(x)
          >>> f.expression_at(Integer(2))
          Traceback (most recent call last):
          ...
          ValueError: point is not in the domain

    expressions(parameters, variable)

      Return the individual domains.

      See also `domains()`.

      OUTPUT: the collection of expressions of the component functions

      EXAMPLES:

      Sage

          sage: f = piecewise([([0,0], sin(x)), ((0,2), cos(x))]);  f
          piecewise(x|-->sin(x) on {0}, x|-->cos(x) on (0, 2); x)
          sage: f.expressions()
          (sin(x), cos(x))

      Python

          >>> from sage.all import *
          >>> f = piecewise([([Integer(0),Integer(0)], sin(x)), ((Integer(0),Integer(2)), cos(x))]);  f
          piecewise(x|-->sin(x) on {0}, x|-->cos(x) on (0, 2); x)
          >>> f.expressions()
          (sin(x), cos(x))

    extension(parameters, variable, extension, extension_domain=None)

      Extend the function.

      INPUT:

      - `extension` – a symbolic expression

      - `extension_domain` – a `RealSet` or `None` (default). The domain of the extension. By default, the entire complement of the current domain.

      EXAMPLES:

      Sage

          sage: f = piecewise([((-1,1), x)]);  f
          piecewise(x|-->x on (-1, 1); x)
          sage: f(3)
          Traceback (most recent call last):
          ...
          ValueError: point 3 is not in the domain

          sage: g = f.extension(0);  g
          piecewise(x|-->x on (-1, 1), x|-->0 on (-oo, -1] ∪ [1, +oo); x)
          sage: g(3)
          0

          sage: h = f.extension(1, RealSet.unbounded_above_closed(1));  h
          piecewise(x|-->x on (-1, 1), x|-->1 on [1, +oo); x)
          sage: h(3)
          1

      Python

          >>> from sage.all import *
          >>> f = piecewise([((-Integer(1),Integer(1)), x)]);  f
          piecewise(x|-->x on (-1, 1); x)
          >>> f(Integer(3))
          Traceback (most recent call last):
          ...
          ValueError: point 3 is not in the domain

          >>> g = f.extension(Integer(0));  g
          piecewise(x|-->x on (-1, 1), x|-->0 on (-oo, -1] ∪ [1, +oo); x)
          >>> g(Integer(3))
          0

          >>> h = f.extension(Integer(1), RealSet.unbounded_above_closed(Integer(1)));  h
          piecewise(x|-->x on (-1, 1), x|-->1 on [1, +oo); x)
          >>> h(Integer(3))
          1

    fourier_series_cosine_coefficient(parameters, variable, n, L=None)

      Return the \(n\)-th cosine coefficient of the Fourier series of the periodic function \(f\) extending the piecewise-defined function `self`.

      Given an integer \(n\geq 0\), the \(n\)-th cosine coefficient of the Fourier series of \(f\) is defined by

      \[a_n = \frac{1}{L}\int_{-L}^L f(x)\cos\left(\frac{n\pi x}{L}\right) dx,\]

      where \(L\) is the half-period of \(f\). For \(n\geq 1\), \(a_n\) is the coefficient of \(\cos(n\pi x/L)\) in the Fourier series of \(f\), while \(a_0\) is twice the coefficient of the constant term \(\cos(0 x)\), i.e. twice the mean value of \(f\) over one period (cf. `fourier_series_partial_sum()`).

      INPUT:

      - `n` – nonnegative integer

      - `L` – (default: `None`) the half-period of \(f\); if none is provided, \(L\) is assumed to be the half-width of the domain of `self`

      OUTPUT: the Fourier coefficient \(a_n\), as defined above

      EXAMPLES:

      A triangle wave function of period 2:

      Sage

          sage: f = piecewise([((0,1), x), ((1,2), 2 - x)])
          sage: f.fourier_series_cosine_coefficient(0)
          1
          sage: f.fourier_series_cosine_coefficient(3)
          -4/9/pi^2

      Python

          >>> from sage.all import *
          >>> f = piecewise([((Integer(0),Integer(1)), x), ((Integer(1),Integer(2)), Integer(2) - x)])
          >>> f.fourier_series_cosine_coefficient(Integer(0))
          1
          >>> f.fourier_series_cosine_coefficient(Integer(3))
          -4/9/pi^2

      If the domain of the piecewise-defined function encompasses more than one period, the half-period must be passed as the second argument; for instance:

      Sage

          sage: f2 = piecewise([((0,1), x), ((1,2), 2 - x),
          ....:                 ((2,3), x - 2), ((3,4), 2 - (x-2))])
          sage: bool(f2.restriction((0,2)) == f)  # f2 extends f on (0,4)
          True
          sage: f2.fourier_series_cosine_coefficient(3, 1)  # half-period = 1
          -4/9/pi^2

      [Python]

          >>> from sage.all import *
          >>> f2 = piecewise([((Integer(0),Integer(1)), x), ((Integer(1),Integer(2)), Integer(2) - x),
          ...                 ((Integer(2),Integer(3)), x - Integer(2)), ((Integer(3),Integer(4)), Integer(2) - (x-Integer(2)))])
          >>> bool(f2.restriction((Integer(0),Integer(2))) == f)  # f2 extends f on (0,4)
          True
          >>> f2.fourier_series_cosine_coefficient(Integer(3), Integer(1))  # half-period = 1
          -4/9/pi^2

      The default half-period is 2 and one has:

      Sage

          sage: f2.fourier_series_cosine_coefficient(3)     # half-period = 2
          0

      Python

          >>> from sage.all import *
          >>> f2.fourier_series_cosine_coefficient(Integer(3))     # half-period = 2
          0

      The Fourier coefficient \(-4/(9\pi^2)\) obtained above is actually recovered for \(n=6\):

      Sage

          sage: f2.fourier_series_cosine_coefficient(6)
          -4/9/pi^2

      [Python]

          >>> from sage.all import *
          >>> f2.fourier_series_cosine_coefficient(Integer(6))
          -4/9/pi^2

      Other examples:

      Sage

          sage: f(x) = x^2
          sage: f = piecewise([[(-1,1), f]])
          sage: f.fourier_series_cosine_coefficient(2)
          pi^(-2)
          sage: f1(x) = -1
          sage: f2(x) = 2
          sage: f = piecewise([[(-pi, pi/2), f1], [(pi/2, pi), f2]])
          sage: f.fourier_series_cosine_coefficient(5, pi)
          -3/5/pi

      Python

          >>> from sage.all import *
          >>> __tmp__=var("x"); f = symbolic_expression(x**Integer(2)).function(x)
          >>> f = piecewise([[(-Integer(1),Integer(1)), f]])
          >>> f.fourier_series_cosine_coefficient(Integer(2))
          pi^(-2)
          >>> __tmp__=var("x"); f1 = symbolic_expression(-Integer(1)).function(x)
          >>> __tmp__=var("x"); f2 = symbolic_expression(Integer(2)).function(x)
          >>> f = piecewise([[(-pi, pi/Integer(2)), f1], [(pi/Integer(2), pi), f2]])
          >>> f.fourier_series_cosine_coefficient(Integer(5), pi)
          -3/5/pi

    fourier_series_partial_sum(parameters, variable, N, L=None)

      Return the partial sum up to a given order of the Fourier series of the periodic function \(f\) extending the piecewise-defined function `self`.

      The Fourier partial sum of order \(N\) is defined as

      \[S_{N}(x) = \frac{a_0}{2} + \sum_{n=1}^{N} \left[ a_n\cos\left(\frac{n\pi x}{L}\right) + b_n\sin\left(\frac{n\pi x}{L}\right)\right],\]

      where \(L\) is the half-period of \(f\) and the \(a_n\)’s and \(b_n\)’s are respectively the cosine coefficients and sine coefficients of the Fourier series of \(f\) (cf. `fourier_series_cosine_coefficient()` and `fourier_series_sine_coefficient()`).

      INPUT:

      - `N` – positive integer; the order of the partial sum

      - `L` – (default: `None`) the half-period of \(f\); if none is provided, \(L\) is assumed to be the half-width of the domain of `self`

      OUTPUT:

      - the partial sum \(S_{N}(x)\), as a symbolic expression

      EXAMPLES:

      A square wave function of period 2:

      Sage

          sage: f = piecewise([((-1,0), -1), ((0,1), 1)])
          sage: f.fourier_series_partial_sum(5)
          4/5*sin(5*pi*x)/pi + 4/3*sin(3*pi*x)/pi + 4*sin(pi*x)/pi

      Python

          >>> from sage.all import *
          >>> f = piecewise([((-Integer(1),Integer(0)), -Integer(1)), ((Integer(0),Integer(1)), Integer(1))])
          >>> f.fourier_series_partial_sum(Integer(5))
          4/5*sin(5*pi*x)/pi + 4/3*sin(3*pi*x)/pi + 4*sin(pi*x)/pi

      If the domain of the piecewise-defined function encompasses more than one period, the half-period must be passed as the second argument; for instance:

      Sage

          sage: f2 = piecewise([((-1,0), -1), ((0,1), 1),
          ....:                 ((1,2), -1), ((2,3), 1)])
          sage: bool(f2.restriction((-1,1)) == f)  # f2 extends f on (-1,3)
          True
          sage: f2.fourier_series_partial_sum(5, 1)  # half-period = 1
          4/5*sin(5*pi*x)/pi + 4/3*sin(3*pi*x)/pi + 4*sin(pi*x)/pi
          sage: bool(f2.fourier_series_partial_sum(5, 1) ==
          ....:      f.fourier_series_partial_sum(5))
          True

      [Python]

          >>> from sage.all import *
          >>> f2 = piecewise([((-Integer(1),Integer(0)), -Integer(1)), ((Integer(0),Integer(1)), Integer(1)),
          ...                 ((Integer(1),Integer(2)), -Integer(1)), ((Integer(2),Integer(3)), Integer(1))])
          >>> bool(f2.restriction((-Integer(1),Integer(1))) == f)  # f2 extends f on (-1,3)
          True
          >>> f2.fourier_series_partial_sum(Integer(5), Integer(1))  # half-period = 1
          4/5*sin(5*pi*x)/pi + 4/3*sin(3*pi*x)/pi + 4*sin(pi*x)/pi
          >>> bool(f2.fourier_series_partial_sum(Integer(5), Integer(1)) ==
          ...      f.fourier_series_partial_sum(Integer(5)))
          True

      The default half-period is 2, so that skipping the second argument yields a different result:

      Sage

          sage: f2.fourier_series_partial_sum(5)  # half-period = 2
          4*sin(pi*x)/pi

      Python

          >>> from sage.all import *
          >>> f2.fourier_series_partial_sum(Integer(5))  # half-period = 2
          4*sin(pi*x)/pi

      An example of partial sum involving both cosine and sine terms:

      Sage

          sage: f = piecewise([((-1,0), 0), ((0,1/2), 2*x),
          ....:                ((1/2,1), 2*(1-x))])
          sage: f.fourier_series_partial_sum(5)
          -2*cos(2*pi*x)/pi^2 + 4/25*sin(5*pi*x)/pi^2
           - 4/9*sin(3*pi*x)/pi^2 + 4*sin(pi*x)/pi^2 + 1/4

      [Python]

          >>> from sage.all import *
          >>> f = piecewise([((-Integer(1),Integer(0)), Integer(0)), ((Integer(0),Integer(1)/Integer(2)), Integer(2)*x),
          ...                ((Integer(1)/Integer(2),Integer(1)), Integer(2)*(Integer(1)-x))])
          >>> f.fourier_series_partial_sum(Integer(5))
          -2*cos(2*pi*x)/pi^2 + 4/25*sin(5*pi*x)/pi^2
           - 4/9*sin(3*pi*x)/pi^2 + 4*sin(pi*x)/pi^2 + 1/4

    fourier_series_sine_coefficient(parameters, variable, n, L=None)

      Return the \(n\)-th sine coefficient of the Fourier series of the periodic function \(f\) extending the piecewise-defined function `self`.

      Given an integer \(n\geq 0\), the \(n\)-th sine coefficient of the Fourier series of \(f\) is defined by

      \[b_n = \frac{1}{L}\int_{-L}^L f(x)\sin\left(\frac{n\pi x}{L}\right) dx,\]

      where \(L\) is the half-period of \(f\). The number \(b_n\) is the coefficient of \(\sin(n\pi x/L)\) in the Fourier series of \(f\) (cf. `fourier_series_partial_sum()`).

      INPUT:

      - `n` – nonnegative integer

      - `L` – (default: `None`) the half-period of \(f\); if none is provided, \(L\) is assumed to be the half-width of the domain of `self`

      OUTPUT: the Fourier coefficient \(b_n\), as defined above

      EXAMPLES:

      A square wave function of period 2:

      Sage

          sage: f = piecewise([((-1,0), -1), ((0,1), 1)])
          sage: f.fourier_series_sine_coefficient(1)
          4/pi
          sage: f.fourier_series_sine_coefficient(2)
          0
          sage: f.fourier_series_sine_coefficient(3)
          4/3/pi

      Python

          >>> from sage.all import *
          >>> f = piecewise([((-Integer(1),Integer(0)), -Integer(1)), ((Integer(0),Integer(1)), Integer(1))])
          >>> f.fourier_series_sine_coefficient(Integer(1))
          4/pi
          >>> f.fourier_series_sine_coefficient(Integer(2))
          0
          >>> f.fourier_series_sine_coefficient(Integer(3))
          4/3/pi

      If the domain of the piecewise-defined function encompasses more than one period, the half-period must be passed as the second argument; for instance:

      Sage

          sage: f2 = piecewise([((-1,0), -1), ((0,1), 1),
          ....:                 ((1,2), -1), ((2,3), 1)])
          sage: bool(f2.restriction((-1,1)) == f)  # f2 extends f on (-1,3)
          True
          sage: f2.fourier_series_sine_coefficient(1, 1)  # half-period = 1
          4/pi
          sage: f2.fourier_series_sine_coefficient(3, 1)  # half-period = 1
          4/3/pi

      [Python]

          >>> from sage.all import *
          >>> f2 = piecewise([((-Integer(1),Integer(0)), -Integer(1)), ((Integer(0),Integer(1)), Integer(1)),
          ...                 ((Integer(1),Integer(2)), -Integer(1)), ((Integer(2),Integer(3)), Integer(1))])
          >>> bool(f2.restriction((-Integer(1),Integer(1))) == f)  # f2 extends f on (-1,3)
          True
          >>> f2.fourier_series_sine_coefficient(Integer(1), Integer(1))  # half-period = 1
          4/pi
          >>> f2.fourier_series_sine_coefficient(Integer(3), Integer(1))  # half-period = 1
          4/3/pi

      The default half-period is 2 and one has:

      Sage

          sage: f2.fourier_series_sine_coefficient(1)  # half-period = 2
          0
          sage: f2.fourier_series_sine_coefficient(3)  # half-period = 2
          0

      Python

          >>> from sage.all import *
          >>> f2.fourier_series_sine_coefficient(Integer(1))  # half-period = 2
          0
          >>> f2.fourier_series_sine_coefficient(Integer(3))  # half-period = 2
          0

      The Fourier coefficients obtained from `f` are actually recovered for \(n=2\) and \(n=6\) respectively:

      Sage

          sage: f2.fourier_series_sine_coefficient(2)
          4/pi
          sage: f2.fourier_series_sine_coefficient(6)
          4/3/pi

      [Python]

          >>> from sage.all import *
          >>> f2.fourier_series_sine_coefficient(Integer(2))
          4/pi
          >>> f2.fourier_series_sine_coefficient(Integer(6))
          4/3/pi

    integral(parameters, variable, x=None, a=None, b=None, definite=False, **kwds)

      By default, return the indefinite integral of the function.

      If `definite=True` is given, returns the definite integral.

      AUTHOR:

      - Paul Butler

      EXAMPLES:

      Sage

          sage: f1(x) = 1 - x
          sage: f = piecewise([((0,1), 1), ((1,2), f1)])
          sage: f.integral(definite=True)
          1/2

      Python

          >>> from sage.all import *
          >>> __tmp__=var("x"); f1 = symbolic_expression(Integer(1) - x).function(x)
          >>> f = piecewise([((Integer(0),Integer(1)), Integer(1)), ((Integer(1),Integer(2)), f1)])
          >>> f.integral(definite=True)
          1/2

      Sage

          sage: f1(x) = -1
          sage: f2(x) = 2
          sage: f = piecewise([((0,pi/2), f1), ((pi/2,pi), f2)])
          sage: f.integral(definite=True)
          1/2*pi

          sage: f1(x) = 2
          sage: f2(x) = 3 - x
          sage: f = piecewise([[(-2, 0), f1], [(0, 3), f2]])
          sage: f.integral()
          piecewise(x|-->2*x + 4 on (-2, 0),
                    x|-->-1/2*x^2 + 3*x + 4 on (0, 3); x)

          sage: f1(y) = -1
          sage: f2(y) = y + 3
          sage: f3(y) = -y - 1
          sage: f4(y) = y^2 - 1
          sage: f5(y) = 3
          sage: f = piecewise([[[-4,-3], f1], [(-3,-2), f2], [[-2,0], f3],
          ....:                [(0,2), f4], [[2,3], f5]])
          sage: F = f.integral(y); F
          piecewise(y|-->-y - 4 on [-4, -3],
                    y|-->1/2*y^2 + 3*y + 7/2 on (-3, -2),
                    y|-->-1/2*y^2 - y - 1/2 on [-2, 0],
                    y|-->1/3*y^3 - y - 1/2 on (0, 2),
                    y|-->3*y - 35/6 on [2, 3]; y)

      [Python]

          >>> from sage.all import *
          >>> __tmp__=var("x"); f1 = symbolic_expression(-Integer(1)).function(x)
          >>> __tmp__=var("x"); f2 = symbolic_expression(Integer(2)).function(x)
          >>> f = piecewise([((Integer(0),pi/Integer(2)), f1), ((pi/Integer(2),pi), f2)])
          >>> f.integral(definite=True)
          1/2*pi

          >>> __tmp__=var("x"); f1 = symbolic_expression(Integer(2)).function(x)
          >>> __tmp__=var("x"); f2 = symbolic_expression(Integer(3) - x).function(x)
          >>> f = piecewise([[(-Integer(2), Integer(0)), f1], [(Integer(0), Integer(3)), f2]])
          >>> f.integral()
          piecewise(x|-->2*x + 4 on (-2, 0),
                    x|-->-1/2*x^2 + 3*x + 4 on (0, 3); x)

          >>> __tmp__=var("y"); f1 = symbolic_expression(-Integer(1)).function(y)
          >>> __tmp__=var("y"); f2 = symbolic_expression(y + Integer(3)).function(y)
          >>> __tmp__=var("y"); f3 = symbolic_expression(-y - Integer(1)).function(y)
          >>> __tmp__=var("y"); f4 = symbolic_expression(y**Integer(2) - Integer(1)).function(y)
          >>> __tmp__=var("y"); f5 = symbolic_expression(Integer(3)).function(y)
          >>> f = piecewise([[[-Integer(4),-Integer(3)], f1], [(-Integer(3),-Integer(2)), f2], [[-Integer(2),Integer(0)], f3],
          ...                [(Integer(0),Integer(2)), f4], [[Integer(2),Integer(3)], f5]])
          >>> F = f.integral(y); F
          piecewise(y|-->-y - 4 on [-4, -3],
                    y|-->1/2*y^2 + 3*y + 7/2 on (-3, -2),
                    y|-->-1/2*y^2 - y - 1/2 on [-2, 0],
                    y|-->1/3*y^3 - y - 1/2 on (0, 2),
                    y|-->3*y - 35/6 on [2, 3]; y)

      Ensure results are consistent with FTC:

      Sage

          sage: F(-3) - F(-4)
          -1
          sage: F(-1) - F(-3)
          1
          sage: F(2) - F(0)
          2/3
          sage: f.integral(y, 0, 2)
          2/3
          sage: F(3) - F(-4)
          19/6
          sage: f.integral(y, -4, 3)
          19/6
          sage: f.integral(definite=True)
          19/6

      Python

          >>> from sage.all import *
          >>> F(-Integer(3)) - F(-Integer(4))
          -1
          >>> F(-Integer(1)) - F(-Integer(3))
          1
          >>> F(Integer(2)) - F(Integer(0))
          2/3
          >>> f.integral(y, Integer(0), Integer(2))
          2/3
          >>> F(Integer(3)) - F(-Integer(4))
          19/6
          >>> f.integral(y, -Integer(4), Integer(3))
          19/6
          >>> f.integral(definite=True)
          19/6

      Sage

          sage: f1(y) = (y+3)^2
          sage: f2(y) = y+3
          sage: f3(y) = 3
          sage: f = piecewise([[(-infinity, -3), f1], [(-3, 0), f2],
          ....:                [(0, infinity), f3]])
          sage: f.integral()
          piecewise(y|-->1/3*y^3 + 3*y^2 + 9*y + 9 on (-oo, -3),
                    y|-->1/2*y^2 + 3*y + 9/2 on (-3, 0),
                    y|-->3*y + 9/2 on (0, +oo); y)

      [Python]

          >>> from sage.all import *
          >>> __tmp__=var("y"); f1 = symbolic_expression((y+Integer(3))**Integer(2)).function(y)
          >>> __tmp__=var("y"); f2 = symbolic_expression(y+Integer(3)).function(y)
          >>> __tmp__=var("y"); f3 = symbolic_expression(Integer(3)).function(y)
          >>> f = piecewise([[(-infinity, -Integer(3)), f1], [(-Integer(3), Integer(0)), f2],
          ...                [(Integer(0), infinity), f3]])
          >>> f.integral()
          piecewise(y|-->1/3*y^3 + 3*y^2 + 9*y + 9 on (-oo, -3),
                    y|-->1/2*y^2 + 3*y + 9/2 on (-3, 0),
                    y|-->3*y + 9/2 on (0, +oo); y)

      The output from this can change a bit depending on the version of Maxima used, so we test for equality with a known result on the sole piece:

      Sage

          sage: # long time
          sage: f1(x) = e^(-abs(x))
          sage: f = piecewise([[(-infinity, infinity), f1]])
          sage: result = f.integral(definite=True)
          ...
          sage: result
          2
          sage: actual = f.integral().expression_at(0) # only one piece
          sage: expected = -1/2*e^(-x)*sgn(x) - 1/2*e^x*sgn(x) - 1/2*e^(-x) + 1/2*e^x + sgn(x) - 1
          sage: bool(actual == expected)
          True

      Python

          >>> from sage.all import *
          >>> # long time
          >>> __tmp__=var("x"); f1 = symbolic_expression(e**(-abs(x))).function(x)
          >>> f = piecewise([[(-infinity, infinity), f1]])
          >>> result = f.integral(definite=True)
          ...
          >>> result
          2
          >>> actual = f.integral().expression_at(Integer(0)) # only one piece
          >>> expected = -Integer(1)/Integer(2)*e**(-x)*sgn(x) - Integer(1)/Integer(2)*e**x*sgn(x) - Integer(1)/Integer(2)*e**(-x) + Integer(1)/Integer(2)*e**x + sgn(x) - Integer(1)
          >>> bool(actual == expected)
          True

      Sage

          sage: f = piecewise([((0, 5), cos(x))])
          sage: f.integral()
          piecewise(x|-->sin(x) on (0, 5); x)

      [Python]

          >>> from sage.all import *
          >>> f = piecewise([((Integer(0), Integer(5)), cos(x))])
          >>> f.integral()
          piecewise(x|-->sin(x) on (0, 5); x)

    items(parameters, variable)

      Iterate over the pieces of the piecewise function.

      Note

      You should probably use `pieces()` instead, which offers a nicer interface.

      OUTPUT:

      This method iterates over pieces of the piecewise function, each represented by a pair. The first element is the support, and the second the function over that support.

      EXAMPLES:

      Sage

          sage: f = piecewise([([0,0], sin(x)), ((0,2), cos(x))])
          sage: for support, function in f.items():
          ....:     print('support is {0}, function is {1}'.format(support, function))
          support is {0}, function is sin(x)
          support is (0, 2), function is cos(x)

      Python

          >>> from sage.all import *
          >>> f = piecewise([([Integer(0),Integer(0)], sin(x)), ((Integer(0),Integer(2)), cos(x))])
          >>> for support, function in f.items():
          ...     print('support is {0}, function is {1}'.format(support, function))
          support is {0}, function is sin(x)
          support is (0, 2), function is cos(x)

    laplace(parameters, variable, x='x', s='t')

      Return the Laplace transform of `self` with respect to the variable var.

      INPUT:

      - `x` – variable of `self`

      - `s` – variable of Laplace transform

      We assume that a piecewise function is 0 outside of its domain and that the left-most endpoint of the domain is 0.

      EXAMPLES:

      Sage

          sage: x, s, w = var('x, s, w')
          sage: f = piecewise([[(0,1), 1], [[1,2], 1 - x]])
          sage: f.laplace(x, s)
          -e^(-s)/s + (s + 1)*e^(-2*s)/s^2 + 1/s - e^(-s)/s^2
          sage: f.laplace(x, w)
          -e^(-w)/w + (w + 1)*e^(-2*w)/w^2 + 1/w - e^(-w)/w^2

      Python

          >>> from sage.all import *
          >>> x, s, w = var('x, s, w')
          >>> f = piecewise([[(Integer(0),Integer(1)), Integer(1)], [[Integer(1),Integer(2)], Integer(1) - x]])
          >>> f.laplace(x, s)
          -e^(-s)/s + (s + 1)*e^(-2*s)/s^2 + 1/s - e^(-s)/s^2
          >>> f.laplace(x, w)
          -e^(-w)/w + (w + 1)*e^(-2*w)/w^2 + 1/w - e^(-w)/w^2

      Sage

          sage: y, t = var('y, t')
          sage: f = piecewise([[[1,2], 1 - y]])
          sage: f.laplace(y, t)
          (t + 1)*e^(-2*t)/t^2 - e^(-t)/t^2

      [Python]

          >>> from sage.all import *
          >>> y, t = var('y, t')
          >>> f = piecewise([[[Integer(1),Integer(2)], Integer(1) - y]])
          >>> f.laplace(y, t)
          (t + 1)*e^(-2*t)/t^2 - e^(-t)/t^2

      Sage

          sage: s = var('s')
          sage: t = var('t')
          sage: f1(t) = -t
          sage: f2(t) = 2
          sage: f = piecewise([[[0,1], f1], [(1,infinity), f2]])
          sage: f.laplace(t, s)
          (s + 1)*e^(-s)/s^2 + 2*e^(-s)/s - 1/s^2

      Python

          >>> from sage.all import *
          >>> s = var('s')
          >>> t = var('t')
          >>> __tmp__=var("t"); f1 = symbolic_expression(-t).function(t)
          >>> __tmp__=var("t"); f2 = symbolic_expression(Integer(2)).function(t)
          >>> f = piecewise([[[Integer(0),Integer(1)], f1], [(Integer(1),infinity), f2]])
          >>> f.laplace(t, s)
          (s + 1)*e^(-s)/s^2 + 2*e^(-s)/s - 1/s^2

    pieces(parameters, variable)

      Return the “pieces”.

      OUTPUT:

      A tuple of piecewise functions, each having only a single expression.

      EXAMPLES:

      Sage

          sage: p = piecewise([((-1, 0), -x), ([0, 1], x)], var=x)
          sage: p.pieces()
          (piecewise(x|-->-x on (-1, 0); x),
           piecewise(x|-->x on [0, 1]; x))

      Python

          >>> from sage.all import *
          >>> p = piecewise([((-Integer(1), Integer(0)), -x), ([Integer(0), Integer(1)], x)], var=x)
          >>> p.pieces()
          (piecewise(x|-->-x on (-1, 0); x),
           piecewise(x|-->x on [0, 1]; x))

    piecewise_add(parameters, variable, other)

      Return a new piecewise function with domain the union of the original domains and functions summed. Undefined intervals in the union domain get function value \(0\).

      EXAMPLES:

      Sage

          sage: f = piecewise([([0,1], 1), ((2,3), x)])
          sage: g = piecewise([((1/2, 2), x)])
          sage: f.piecewise_add(g).unextend_zero()
          piecewise(x|-->1 on (0, 1/2],
                    x|-->x + 1 on (1/2, 1],
                    x|-->x on (1, 2) ∪ (2, 3); x)

      Python

          >>> from sage.all import *
          >>> f = piecewise([([Integer(0),Integer(1)], Integer(1)), ((Integer(2),Integer(3)), x)])
          >>> g = piecewise([((Integer(1)/Integer(2), Integer(2)), x)])
          >>> f.piecewise_add(g).unextend_zero()
          piecewise(x|-->1 on (0, 1/2],
                    x|-->x + 1 on (1/2, 1],
                    x|-->x on (1, 2) ∪ (2, 3); x)

    restriction(parameters, variable, restricted_domain)

      Restrict the domain.

      INPUT:

      - `restricted_domain` – a `RealSet` or something that defines one.

      OUTPUT: a new piecewise function obtained by restricting the domain

      EXAMPLES:

      Sage

          sage: f = piecewise([((-oo, oo), x)]);  f
          piecewise(x|-->x on (-oo, +oo); x)
          sage: f.restriction([[-1,1], [3,3]])
          piecewise(x|-->x on [-1, 1] ∪ {3}; x)

      Python

          >>> from sage.all import *
          >>> f = piecewise([((-oo, oo), x)]);  f
          piecewise(x|-->x on (-oo, +oo); x)
          >>> f.restriction([[-Integer(1),Integer(1)], [Integer(3),Integer(3)]])
          piecewise(x|-->x on [-1, 1] ∪ {3}; x)

    trapezoid(parameters, variable, N)

      Return the piecewise line function defined by the trapezoid rule for numerical integration based on a subdivision of each domain interval into N subintervals.

      EXAMPLES:

      Sage

          sage: f = piecewise([[[0,1], x^2],
          ....:                [RealSet.open_closed(1,2), 5 - x^2]])
          sage: f.trapezoid(2)
          piecewise(x|-->1/2*x on (0, 1/2),
                    x|-->3/2*x - 1/2 on (1/2, 1),
                    x|-->7/2*x - 5/2 on (1, 3/2),
                    x|-->-7/2*x + 8 on (3/2, 2); x)
          sage: f = piecewise([[[-1,1], 1 - x^2]])
          sage: f.trapezoid(4).integral(definite=True)
          5/4
          sage: f = piecewise([[[-1,1], 1/2 + x - x^3]])          ## example 3
          sage: f.trapezoid(6).integral(definite=True)
          1

      Python

          >>> from sage.all import *
          >>> f = piecewise([[[Integer(0),Integer(1)], x**Integer(2)],
          ...                [RealSet.open_closed(Integer(1),Integer(2)), Integer(5) - x**Integer(2)]])
          >>> f.trapezoid(Integer(2))
          piecewise(x|-->1/2*x on (0, 1/2),
                    x|-->3/2*x - 1/2 on (1/2, 1),
                    x|-->7/2*x - 5/2 on (1, 3/2),
                    x|-->-7/2*x + 8 on (3/2, 2); x)
          >>> f = piecewise([[[-Integer(1),Integer(1)], Integer(1) - x**Integer(2)]])
          >>> f.trapezoid(Integer(4)).integral(definite=True)
          5/4
          >>> f = piecewise([[[-Integer(1),Integer(1)], Integer(1)/Integer(2) + x - x**Integer(3)]])          ## example 3
          >>> f.trapezoid(Integer(6)).integral(definite=True)
          1

    unextend_zero(parameters, variable)

      Remove zero pieces.

      EXAMPLES:

      Sage

          sage: f = piecewise([((-1,1), x)]);  f
          piecewise(x|-->x on (-1, 1); x)
          sage: g = f.extension(0);  g
          piecewise(x|-->x on (-1, 1), x|-->0 on (-oo, -1] ∪ [1, +oo); x)
          sage: g(3)
          0
          sage: h = g.unextend_zero()
          sage: bool(h == f)
          True

      Python

          >>> from sage.all import *
          >>> f = piecewise([((-Integer(1),Integer(1)), x)]);  f
          piecewise(x|-->x on (-1, 1); x)
          >>> g = f.extension(Integer(0));  g
          piecewise(x|-->x on (-1, 1), x|-->0 on (-oo, -1] ∪ [1, +oo); x)
          >>> g(Integer(3))
          0
          >>> h = g.unextend_zero()
          >>> bool(h == f)
          True

    which_function(parameters, variable, point)

      alias of `expression_at()`.

  static in_operands(ex)

    Return whether a symbolic expression contains a piecewise function as operand.

    INPUT:

    - `ex` – a symbolic expression

    OUTPUT: boolean

    EXAMPLES:

    Sage

        sage: f = piecewise([([0,0], sin(x)), ((0,2), cos(x))]);  f
        piecewise(x|-->sin(x) on {0}, x|-->cos(x) on (0, 2); x)
        sage: piecewise.in_operands(f)
        True
        sage: piecewise.in_operands(1+sin(f))
        True
        sage: piecewise.in_operands(1+sin(0*f))
        False

    Python

        >>> from sage.all import *
        >>> f = piecewise([([Integer(0),Integer(0)], sin(x)), ((Integer(0),Integer(2)), cos(x))]);  f
        piecewise(x|-->sin(x) on {0}, x|-->cos(x) on (0, 2); x)
        >>> piecewise.in_operands(f)
        True
        >>> piecewise.in_operands(Integer(1)+sin(f))
        True
        >>> piecewise.in_operands(Integer(1)+sin(Integer(0)*f))
        False

  static simplify(ex)

    Combine piecewise operands into single piecewise function.

    OUTPUT:

    A piecewise function whose operands are not piecewise if possible, that is, as long as the piecewise variable is the same.

    EXAMPLES:

    Sage

        sage: f = piecewise([([0,0], sin(x)), ((0,2), cos(x))])
        sage: piecewise.simplify(f)
        Traceback (most recent call last):
        ...
        NotImplementedError

    Python

        >>> from sage.all import *
        >>> f = piecewise([([Integer(0),Integer(0)], sin(x)), ((Integer(0),Integer(2)), cos(x))])
        >>> piecewise.simplify(f)
        Traceback (most recent call last):
        ...
        NotImplementedError