o
    8Va[                      @   sx   d dl mZmZmZmZ d dlmZmZ d dlm	Z	 d dl
mZ d dlmZ d dlmZ d dlmZ G dd	 d	eZd
S )    )Ssympifyoodiff)FunctionArgumentIndexError)	fuzzy_not)Eq)im)	Piecewise)	Heavisidec                   @   sV   e Zd ZdZdZdddZedd Zdd	 Zd
d Z	dddZ
dddZe	Ze	ZdS )SingularityFunctionaL	  
    Singularity functions are a class of discontinuous functions.

    Explanation
    ===========

    Singularity functions take a variable, an offset, and an exponent as
    arguments. These functions are represented using Macaulay brackets as:

    SingularityFunction(x, a, n) := <x - a>^n

    The singularity function will automatically evaluate to
    ``Derivative(DiracDelta(x - a), x, -n - 1)`` if ``n < 0``
    and ``(x - a)**n*Heaviside(x - a)`` if ``n >= 0``.

    Examples
    ========

    >>> from sympy import SingularityFunction, diff, Piecewise, DiracDelta, Heaviside, Symbol
    >>> from sympy.abc import x, a, n
    >>> SingularityFunction(x, a, n)
    SingularityFunction(x, a, n)
    >>> y = Symbol('y', positive=True)
    >>> n = Symbol('n', nonnegative=True)
    >>> SingularityFunction(y, -10, n)
    (y + 10)**n
    >>> y = Symbol('y', negative=True)
    >>> SingularityFunction(y, 10, n)
    0
    >>> SingularityFunction(x, 4, -1).subs(x, 4)
    oo
    >>> SingularityFunction(x, 10, -2).subs(x, 10)
    oo
    >>> SingularityFunction(4, 1, 5)
    243
    >>> diff(SingularityFunction(x, 1, 5) + SingularityFunction(x, 1, 4), x)
    4*SingularityFunction(x, 1, 3) + 5*SingularityFunction(x, 1, 4)
    >>> diff(SingularityFunction(x, 4, 0), x, 2)
    SingularityFunction(x, 4, -2)
    >>> SingularityFunction(x, 4, 5).rewrite(Piecewise)
    Piecewise(((x - 4)**5, x - 4 > 0), (0, True))
    >>> expr = SingularityFunction(x, a, n)
    >>> y = Symbol('y', positive=True)
    >>> n = Symbol('n', nonnegative=True)
    >>> expr.subs({x: y, a: -10, n: n})
    (y + 10)**n

    The methods ``rewrite(DiracDelta)``, ``rewrite(Heaviside)``, and
    ``rewrite('HeavisideDiracDelta')`` returns the same output. One can use any
    of these methods according to their choice.

    >>> expr = SingularityFunction(x, 4, 5) + SingularityFunction(x, -3, -1) - SingularityFunction(x, 0, -2)
    >>> expr.rewrite(Heaviside)
    (x - 4)**5*Heaviside(x - 4) + DiracDelta(x + 3) - DiracDelta(x, 1)
    >>> expr.rewrite(DiracDelta)
    (x - 4)**5*Heaviside(x - 4) + DiracDelta(x + 3) - DiracDelta(x, 1)
    >>> expr.rewrite('HeavisideDiracDelta')
    (x - 4)**5*Heaviside(x - 4) + DiracDelta(x + 3) - DiracDelta(x, 1)

    See Also
    ========

    DiracDelta, Heaviside

    References
    ==========

    .. [1] https://en.wikipedia.org/wiki/Singularity_function

    T   c                 C   s~   |dkr:t | jd }t | jd }t | jd }|dks!|dkr*| |||d S |jr8|| |||d  S dS t| |)aK  
        Returns the first derivative of a DiracDelta Function.

        Explanation
        ===========

        The difference between ``diff()`` and ``fdiff()`` is: ``diff()`` is the
        user-level function and ``fdiff()`` is an object method. ``fdiff()`` is
        a convenience method available in the ``Function`` class. It returns
        the derivative of the function without considering the chain rule.
        ``diff(function, x)`` calls ``Function._eval_derivative`` which in turn
        calls ``fdiff()`` internally to compute the derivative of the function.

        r   r      N)r   argsfuncis_positiver   )selfZargindexxan r   O/usr/lib/python3/dist-packages/sympy/functions/special/singularity_functions.pyfdiffX   s   
zSingularityFunction.fdiffc                 C   s   t |}t |}t |}|| }tt|jrtdtt|jr&td|tju s0|tju r3tjS |d jr<td|jrBtj	S |j
rN|jrN|| | S |dksV|dkre|js\|jr_tj	S |jrgtjS dS dS )a  
        Returns a simplified form or a value of Singularity Function depending
        on the argument passed by the object.

        Explanation
        ===========

        The ``eval()`` method is automatically called when the
        ``SingularityFunction`` class is about to be instantiated and it
        returns either some simplified instance or the unevaluated instance
        depending on the argument passed. In other words, ``eval()`` method is
        not needed to be called explicitly, it is being called and evaluated
        once the object is called.

        Examples
        ========

        >>> from sympy import SingularityFunction, Symbol, nan
        >>> from sympy.abc import x, a, n
        >>> SingularityFunction(x, a, n)
        SingularityFunction(x, a, n)
        >>> SingularityFunction(5, 3, 2)
        4
        >>> SingularityFunction(x, a, nan)
        nan
        >>> SingularityFunction(x, 3, 0).subs(x, 3)
        1
        >>> SingularityFunction(x, a, n).eval(3, 5, 1)
        0
        >>> SingularityFunction(x, a, n).eval(4, 1, 5)
        243
        >>> x = Symbol('x', positive = True)
        >>> a = Symbol('a', negative = True)
        >>> n = Symbol('n', nonnegative = True)
        >>> SingularityFunction(x, a, n)
        (-a + x)**n
        >>> x = Symbol('x', negative = True)
        >>> a = Symbol('a', positive = True)
        >>> SingularityFunction(x, a, n)
        0

        z8Singularity Functions are defined only for Real Numbers.z>Singularity Functions are not defined for imaginary exponents.r   zASingularity Functions are not defined for exponents less than -2.r   N)r   r   r
   is_zero
ValueErrorr   ZNaNZis_negativeZis_extended_negativeZerois_nonnegativeZis_extended_nonnegativeZis_extended_positiveZInfinity)clsvariableoffsetZexponentr   r   r   shiftr   r   r   evals   s.   -
zSingularityFunction.evalc                 O   sr   | j d }| j d }t| j d }|dks|dkr%ttt|| dfdS |jr7t|| | || dkfdS dS )zV
        Converts a Singularity Function expression into its Piecewise form.

        r   r   r   r   r   )r   TN)r   r   r   r   r	   r   r   r   kwargsr   r   r   r   r   r   _eval_rewrite_as_Piecewise   s   

z.SingularityFunction._eval_rewrite_as_Piecewisec                 O   s   | j d }| j d }t| j d }|dkr"tt|| |j dS |dkr3tt|| |j dS |jrB|| | t||  S dS )z_
        Rewrites a Singularity Function expression using Heavisides and DiracDeltas.

        r   r   r   r   r   N)r   r   r   r   Zfree_symbolspopr   r%   r   r   r   _eval_rewrite_as_Heaviside   s   

z.SingularityFunction._eval_rewrite_as_HeavisideNr   c                 C   s^   | j \}}}|| |d}|dk rtjS |jr%|jr%|dkr"tjS tjS |jr,|| S tjS )Nr   r   )r   subsr   r   r   Oner   )r   r   logxcdirzr   r   r#   r   r   r   _eval_as_leading_term   s   z)SingularityFunction._eval_as_leading_termc                 C   sp   | j \}}}|| |d}|dk rtjS |jr%|jr%|dkr"tjS tjS |jr5|| | j||||dS tjS )Nr   r   )r,   r-   )r   r*   r   r   r   r+   r   _eval_nseries)r   r   r   r,   r-   r.   r   r#   r   r   r   r0      s   z!SingularityFunction._eval_nseries)r   )Nr   )__name__
__module____qualname____doc__Zis_realr   classmethodr$   r'   r)   r/   r0   Z_eval_rewrite_as_DiracDeltaZ$_eval_rewrite_as_HeavisideDiracDeltar   r   r   r   r      s    G

C

r   N)Z
sympy.corer   r   r   r   Zsympy.core.functionr   r   Zsympy.core.logicr   Zsympy.core.relationalr	   Z$sympy.functions.elementary.complexesr
   Z$sympy.functions.elementary.piecewiser   Z'sympy.functions.special.delta_functionsr   r   r   r   r   r   <module>   s    