예제 #1
0
def test_square_wave():
    """Test if fourier_series approximates discontinuous function correctly."""
    square_wave = Piecewise((1, x < pi), (-1, True))
    s = fourier_series(square_wave, (x, 0, 2 * pi))

    assert s.truncate(3) == 4 / pi * sin(x) + 4 / (3 * pi) * sin(3 * x) + \
        4 / (5 * pi) * sin(5 * x)
    assert s.sigma_approximation(4) == 4 / pi * sin(x) * sinc(pi / 4) + \
        4 / (3 * pi) * sin(3 * x) * sinc(3 * pi / 4)
예제 #2
0
def test_optims_numpy_TODO():
    def check(d):
        for k, v in d.items():
            assert optimize(k, optims_numpy) == v

    x, y = map(Symbol, 'x y'.split())
    check({
        log(x * y) * sin(x * y) * log(x * y + 1) / (log(2) * x * y):
        log2(x * y) * sinc(x * y) * log1p(x * y),
        exp(x * sin(y) / y) - 1:
        expm1(x * sinc(y))
    })
예제 #3
0
def test_ccode_sinc():
    from sympy.functions.elementary.trigonometric import sinc
    expr = sinc(x)
    assert ccode(expr) == ("((x != 0) ? (\n"
                           "   sin(x)/x\n"
                           ")\n"
                           ": (\n"
                           "   1\n"
                           "))")
예제 #4
0
def test_optims_numpy():
    def check(d):
        for k, v in d.items():
            assert optimize(k, optims_numpy) == v

    x = Symbol('x')
    check({
        sin(2 * x) / (2 * x) + exp(2 * x) - 1: sinc(2 * x) + expm1(2 * x),
        log(x + 3) / log(2) + log(x**2 + 1): log1p(x**2) + log2(x + 3)
    })
예제 #5
0
def test_si():
    assert Si(I*x) == I*Shi(x)
    assert Shi(I*x) == I*Si(x)
    assert Si(-I*x) == -I*Shi(x)
    assert Shi(-I*x) == -I*Si(x)
    assert Si(-x) == -Si(x)
    assert Shi(-x) == -Shi(x)
    assert Si(exp_polar(2*pi*I)*x) == Si(x)
    assert Si(exp_polar(-2*pi*I)*x) == Si(x)
    assert Shi(exp_polar(2*pi*I)*x) == Shi(x)
    assert Shi(exp_polar(-2*pi*I)*x) == Shi(x)

    assert Si(oo) == pi/2
    assert Si(-oo) == -pi/2
    assert Shi(oo) is oo
    assert Shi(-oo) is -oo

    assert mytd(Si(x), sin(x)/x, x)
    assert mytd(Shi(x), sinh(x)/x, x)

    assert mytn(Si(x), Si(x).rewrite(Ei),
                -I*(-Ei(x*exp_polar(-I*pi/2))/2
               + Ei(x*exp_polar(I*pi/2))/2 - I*pi) + pi/2, x)
    assert mytn(Si(x), Si(x).rewrite(expint),
                -I*(-expint(1, x*exp_polar(-I*pi/2))/2 +
                    expint(1, x*exp_polar(I*pi/2))/2) + pi/2, x)
    assert mytn(Shi(x), Shi(x).rewrite(Ei),
                Ei(x)/2 - Ei(x*exp_polar(I*pi))/2 + I*pi/2, x)
    assert mytn(Shi(x), Shi(x).rewrite(expint),
                expint(1, x)/2 - expint(1, x*exp_polar(I*pi))/2 - I*pi/2, x)

    assert tn_arg(Si)
    assert tn_arg(Shi)

    assert Si(x).nseries(x, n=8) == \
        x - x**3/18 + x**5/600 - x**7/35280 + O(x**9)
    assert Shi(x).nseries(x, n=8) == \
        x + x**3/18 + x**5/600 + x**7/35280 + O(x**9)
    assert Si(sin(x)).nseries(x, n=5) == x - 2*x**3/9 + 17*x**5/450 + O(x**6)
    assert Si(x).nseries(x, 1, n=3) == \
        Si(1) + (x - 1)*sin(1) + (x - 1)**2*(-sin(1)/2 + cos(1)/2) + O((x - 1)**3, (x, 1))

    assert Si(x).series(x, oo) == pi/2 - (- 6/x**3 + 1/x \
        + O(x**(-7), (x, oo)))*sin(x)/x - (24/x**4 - 2/x**2 + 1 \
        + O(x**(-7), (x, oo)))*cos(x)/x

    t = Symbol('t', Dummy=True)
    assert Si(x).rewrite(sinc) == Integral(sinc(t), (t, 0, x))

    assert limit(Shi(x), x, S.NegativeInfinity) == -I*pi/2
예제 #6
0
def test_sinc_opts():
    def check(d):
        for k, v in d.items():
            assert optimize(k, sinc_opts) == v

    x = Symbol('x')
    check({
        sin(x) / x: sinc(x),
        sin(2 * x) / (2 * x): sinc(2 * x),
        sin(3 * x) / x: 3 * sinc(3 * x),
        x * sin(x): x * sin(x)
    })

    y = Symbol('y')
    check({
        sin(x * y) / (x * y): sinc(x * y),
        y * sin(x / y) / x: sinc(x / y),
        sin(sin(x)) / sin(x): sinc(sin(x)),
        sin(3 * sin(x)) / sin(x): 3 * sinc(3 * sin(x)),
        sin(x) / y: sin(x) / y
    })
예제 #7
0
    def sigma_approximation(self, n=3):
        r"""
        Return :math:`\sigma`-approximation of Fourier series with respect
        to order n.

        Sigma approximation adjusts a Fourier summation to eliminate the Gibbs
        phenomenon which would otherwise occur at discontinuities.
        A sigma-approximated summation for a Fourier series of a T-periodical
        function can be written as

        .. math::
            s(\theta) = \frac{1}{2} a_0 + \sum _{k=1}^{m-1}
            \operatorname{sinc} \Bigl( \frac{k}{m} \Bigr) \cdot
            \left[ a_k \cos \Bigl( \frac{2\pi k}{T} \theta \Bigr)
            + b_k \sin \Bigl( \frac{2\pi k}{T} \theta \Bigr) \right],

        where :math:`a_0, a_k, b_k, k=1,\ldots,{m-1}` are standard Fourier
        series coefficients and
        :math:`\operatorname{sinc} \Bigl( \frac{k}{m} \Bigr)` is a Lanczos
        :math:`\sigma` factor (expressed in terms of normalized
        :math:`\operatorname{sinc}` function).

        Parameters
        ==========
        n : int
            Highest order of the terms taken into account in approximation.

        Returns
        =======
        Expr
            Sigma approximation of function expanded into Fourier series.

        Examples
        ========

        >>> from sympy import fourier_series, pi
        >>> from sympy.abc import x
        >>> s = fourier_series(x, (x, -pi, pi))
        >>> s.sigma_approximation(4)
        2*sin(x)*sinc(pi/4) - 2*sin(2*x)/pi + 2*sin(3*x)*sinc(3*pi/4)/3

        See Also
        ========

        sympy.series.fourier.FourierSeries.truncate

        Notes
        =====

        The behaviour of
        :meth:`~sympy.series.fourier.FourierSeries.sigma_approximation`
        is different from :meth:`~sympy.series.fourier.FourierSeries.truncate`
        - it takes all nonzero terms of degree smaller than n, rather than
        first n nonzero ones.

        References
        ==========

        .. [1] https://en.wikipedia.org/wiki/Gibbs_phenomenon
        .. [2] https://en.wikipedia.org/wiki/Sigma_approximation
        """
        terms = [
            sinc(pi * i / n) * t for i, t in enumerate(self[:n])
            if t is not S.Zero
        ]
        return Add(*terms)
예제 #8
0
def test_meijerint():
    from sympy.core.function import expand
    from sympy.core.symbol import symbols
    from sympy.functions.elementary.complexes import arg
    s, t, mu = symbols('s t mu', real=True)
    assert integrate(
        meijerg([], [], [0], [], s * t) *
        meijerg([], [], [mu / 2], [-mu / 2], t**2 / 4),
        (t, 0, oo)).is_Piecewise
    s = symbols('s', positive=True)
    assert integrate(x**s*meijerg([[], []], [[0], []], x), (x, 0, oo)) == \
        gamma(s + 1)
    assert integrate(x**s * meijerg([[], []], [[0], []], x), (x, 0, oo),
                     meijerg=True) == gamma(s + 1)
    assert isinstance(
        integrate(x**s * meijerg([[], []], [[0], []], x), (x, 0, oo),
                  meijerg=False), Integral)

    assert meijerint_indefinite(exp(x), x) == exp(x)

    # TODO what simplifications should be done automatically?
    # This tests "extra case" for antecedents_1.
    a, b = symbols('a b', positive=True)
    assert simplify(meijerint_definite(x**a, x, 0, b)[0]) == \
        b**(a + 1)/(a + 1)

    # This tests various conditions and expansions:
    assert meijerint_definite((x + 1)**3 * exp(-x), x, 0, oo) == (16, True)

    # Again, how about simplifications?
    sigma, mu = symbols('sigma mu', positive=True)
    i, c = meijerint_definite(exp(-((x - mu) / (2 * sigma))**2), x, 0, oo)
    assert simplify(i) == sqrt(pi) * sigma * (2 - erfc(mu / (2 * sigma)))
    assert c == True

    i, _ = meijerint_definite(exp(-mu * x) * exp(sigma * x), x, 0, oo)
    # TODO it would be nice to test the condition
    assert simplify(i) == 1 / (mu - sigma)

    # Test substitutions to change limits
    assert meijerint_definite(exp(x), x, -oo, 2) == (exp(2), True)
    # Note: causes a NaN in _check_antecedents
    assert expand(meijerint_definite(exp(x), x, 0, I)[0]) == exp(I) - 1
    assert expand(meijerint_definite(exp(-x), x, 0, x)[0]) == \
        1 - exp(-exp(I*arg(x))*abs(x))

    # Test -oo to oo
    assert meijerint_definite(exp(-x**2), x, -oo, oo) == (sqrt(pi), True)
    assert meijerint_definite(exp(-abs(x)), x, -oo, oo) == (2, True)
    assert meijerint_definite(exp(-(2*x - 3)**2), x, -oo, oo) == \
        (sqrt(pi)/2, True)
    assert meijerint_definite(exp(-abs(2 * x - 3)), x, -oo, oo) == (1, True)
    assert meijerint_definite(
        exp(-((x - mu) / sigma)**2 / 2) / sqrt(2 * pi * sigma**2), x, -oo,
        oo) == (1, True)
    assert meijerint_definite(sinc(x)**2, x, -oo, oo) == (pi, True)

    # Test one of the extra conditions for 2 g-functinos
    assert meijerint_definite(exp(-x) * sin(x), x, 0, oo) == (S.Half, True)

    # Test a bug
    def res(n):
        return (1 / (1 + x**2)).diff(x, n).subs(x, 1) * (-1)**n

    for n in range(6):
        assert integrate(exp(-x)*sin(x)*x**n, (x, 0, oo), meijerg=True) == \
            res(n)

    # This used to test trigexpand... now it is done by linear substitution
    assert simplify(integrate(exp(-x) * sin(x + a), (x, 0, oo),
                              meijerg=True)) == sqrt(2) * sin(a + pi / 4) / 2

    # Test the condition 14 from prudnikov.
    # (This is besselj*besselj in disguise, to stop the product from being
    #  recognised in the tables.)
    a, b, s = symbols('a b s')
    from sympy.functions.elementary.complexes import re
    assert meijerint_definite(
        meijerg([], [], [a / 2], [-a / 2], x / 4) *
        meijerg([], [], [b / 2], [-b / 2], x / 4) * x**(s - 1), x, 0,
        oo) == ((4 * 2**(2 * s - 2) * gamma(-2 * s + 1) *
                 gamma(a / 2 + b / 2 + s) /
                 (gamma(-a / 2 + b / 2 - s + 1) *
                  gamma(a / 2 - b / 2 - s + 1) * gamma(a / 2 + b / 2 - s + 1)),
                 (re(s) < 1) & (re(s) < S(1) / 2) &
                 (re(a) / 2 + re(b) / 2 + re(s) > 0)))

    # test a bug
    assert integrate(sin(x**a)*sin(x**b), (x, 0, oo), meijerg=True) == \
        Integral(sin(x**a)*sin(x**b), (x, 0, oo))

    # test better hyperexpand
    assert integrate(exp(-x**2)*log(x), (x, 0, oo), meijerg=True) == \
        (sqrt(pi)*polygamma(0, S.Half)/4).expand()

    # Test hyperexpand bug.
    from sympy.functions.special.gamma_functions import lowergamma
    n = symbols('n', integer=True)
    assert simplify(integrate(exp(-x)*x**n, x, meijerg=True)) == \
        lowergamma(n + 1, x)

    # Test a bug with argument 1/x
    alpha = symbols('alpha', positive=True)
    assert meijerint_definite((2 - x)**alpha*sin(alpha/x), x, 0, 2) == \
        (sqrt(pi)*alpha*gamma(alpha + 1)*meijerg(((), (alpha/2 + S.Half,
        alpha/2 + 1)), ((0, 0, S.Half), (Rational(-1, 2),)), alpha**2/16)/4, True)

    # test a bug related to 3016
    a, s = symbols('a s', positive=True)
    assert simplify(integrate(x**s*exp(-a*x**2), (x, -oo, oo))) == \
        a**(-s/2 - S.Half)*((-1)**s + 1)*gamma(s/2 + S.Half)/2
예제 #9
0
def test_rcode_sinc():
    from sympy.functions.elementary.trigonometric import sinc
    expr = sinc(x)
    res = rcode(expr)
    ref = "ifelse(x != 0,sin(x)/x,1)"
    assert res == ref
예제 #10
0
def test_lambdify_cse():
    def dummy_cse(exprs):
        return (), exprs

    def minmem(exprs):
        from sympy.simplify.cse_main import cse_release_variables, cse
        return cse(exprs, postprocess=cse_release_variables)

    class Case:
        def __init__(self, *, args, exprs, num_args, requires_numpy=False):
            self.args = args
            self.exprs = exprs
            self.num_args = num_args
            subs_dict = dict(zip(self.args, self.num_args))
            self.ref = [e.subs(subs_dict).evalf() for e in exprs]
            self.requires_numpy = requires_numpy

        def lambdify(self, *, cse):
            return lambdify(self.args, self.exprs, cse=cse)

        def assertAllClose(self, result, *, abstol=1e-15, reltol=1e-15):
            if self.requires_numpy:
                assert all(
                    numpy.allclose(result[i],
                                   numpy.asarray(r, dtype=float),
                                   rtol=reltol,
                                   atol=abstol)
                    for i, r in enumerate(self.ref))
                return

            for i, r in enumerate(self.ref):
                abs_err = abs(result[i] - r)
                if r == 0:
                    assert abs_err < abstol
                else:
                    assert abs_err / abs(r) < reltol

    cases = [
        Case(args=(x, y, z),
             exprs=[
                 x + y + z,
                 x + y - z,
                 2 * x + 2 * y - z,
                 (x + y)**2 + (y + z)**2,
             ],
             num_args=(2., 3., 4.)),
        Case(args=(x, y, z),
             exprs=[
                 x + sympy.Heaviside(x), y + sympy.Heaviside(x),
                 z + sympy.Heaviside(x, 1), z / sympy.Heaviside(x, 1)
             ],
             num_args=(0., 3., 4.)),
        Case(args=(x, y, z),
             exprs=[x + sinc(y), y + sinc(y), z - sinc(y)],
             num_args=(0.1, 0.2, 0.3)),
        Case(args=(x, y, z),
             exprs=[
                 Matrix([[x, x * y], [sin(z) + 4, x**z]]),
                 x * y + sin(z) - x**z,
                 Matrix([x * x, sin(z), x**z])
             ],
             num_args=(1., 2., 3.),
             requires_numpy=True),
        Case(args=(x, y),
             exprs=[(x + y - 1)**2,
                    x, x + y, (x + y) / (2 * x + 1) + (x + y - 1)**2,
                    (2 * x + 1)**(x + y)],
             num_args=(1, 2))
    ]
    for case in cases:
        if not numpy and case.requires_numpy:
            continue
        for cse in [False, True, minmem, dummy_cse]:
            f = case.lambdify(cse=cse)
            result = f(*case.num_args)
            case.assertAllClose(result)
예제 #11
0
def test_sinc_mpmath():
    f = lambdify(x, sinc(x), "mpmath")
    assert Abs(f(1) - sinc(1)).n() < 1e-15
예제 #12
0
def test_issue_13642():
    if not numpy:
        skip("numpy not installed")
    f = lambdify(x, sinc(x))
    assert Abs(f(1) - sinc(1)).n() < 1e-15
예제 #13
0
파일: fourier.py 프로젝트: asmeurer/sympy
    def sigma_approximation(self, n=3):
        r"""
        Return :math:`\sigma`-approximation of Fourier series with respect
        to order n.

        Sigma approximation adjusts a Fourier summation to eliminate the Gibbs
        phenomenon which would otherwise occur at discontinuities.
        A sigma-approximated summation for a Fourier series of a T-periodical
        function can be written as

        .. math::
            s(\theta) = \frac{1}{2} a_0 + \sum _{k=1}^{m-1}
            \operatorname{sinc} \Bigl( \frac{k}{m} \Bigr) \cdot
            \left[ a_k \cos \Bigl( \frac{2\pi k}{T} \theta \Bigr)
            + b_k \sin \Bigl( \frac{2\pi k}{T} \theta \Bigr) \right],

        where :math:`a_0, a_k, b_k, k=1,\ldots,{m-1}` are standard Fourier
        series coefficients and
        :math:`\operatorname{sinc} \Bigl( \frac{k}{m} \Bigr)` is a Lanczos
        :math:`\sigma` factor (expressed in terms of normalized
        :math:`\operatorname{sinc}` function).

        Parameters
        ==========
        n : int
            Highest order of the terms taken into account in approximation.

        Returns
        =======
        Expr
            Sigma approximation of function expanded into Fourier series.

        Examples
        ========

        >>> from sympy import fourier_series, pi
        >>> from sympy.abc import x
        >>> s = fourier_series(x, (x, -pi, pi))
        >>> s.sigma_approximation(4)
        2*sin(x)*sinc(pi/4) - 2*sin(2*x)/pi + 2*sin(3*x)*sinc(3*pi/4)/3

        See Also
        ========

        sympy.series.fourier.FourierSeries.truncate

        Notes
        =====

        The behaviour of
        :meth:`~sympy.series.fourier.FourierSeries.sigma_approximation`
        is different from :meth:`~sympy.series.fourier.FourierSeries.truncate`
        - it takes all nonzero terms of degree smaller than n, rather than
        first n nonzero ones.

        References
        ==========

        .. [1] https://en.wikipedia.org/wiki/Gibbs_phenomenon
        .. [2] https://en.wikipedia.org/wiki/Sigma_approximation
        """
        terms = [sinc(pi * i / n) * t for i, t in enumerate(self[:n])
                 if t is not S.Zero]
        return Add(*terms)
예제 #14
0
            expr = new_expr
        else:
            expr = optim.cheapest(expr, new_expr)
    return expr


exp2_opt = ReplaceOptim(lambda p: p.is_Pow and p.base == 2,
                        lambda p: exp2(p.exp))

_d = Wild('d', properties=[lambda x: x.is_Dummy])
_u = Wild('u', properties=[lambda x: not x.is_number and not x.is_Add])
_v = Wild('v')
_w = Wild('w')
_n = Wild('n', properties=[lambda x: x.is_number])

sinc_opt1 = ReplaceOptim(sin(_w) / _w, sinc(_w))
sinc_opt2 = ReplaceOptim(sin(_n * _w) / _w, _n * sinc(_n * _w))
sinc_opts = (sinc_opt1, sinc_opt2)

log2_opt = ReplaceOptim(
    _v * log(_w) / log(2),
    _v * log2(_w),
    cost_function=lambda expr: expr.count(
        lambda e:
        (  # division & eval of transcendentals are expensive floating point operations...
            e.is_Pow and e.exp.is_negative  # division
            or (isinstance(e, (log, log2)) and not e.args[0].is_number)
        )  # transcendental
    ))

log2const_opt = ReplaceOptim(log(2) * log2(_w), log(_w))