U
    ZÊ¹j¡-  ã                   @   s  d Z ddlmZmZmZ ddlmZ ddlmZm	Z	 ddl
mZmZ ddlmZmZ ddlmZmZ ddlmZ d$d
d„Zd%dd„Zd&dd„Zej e_ d'dd„Zdd„ Zdd„ Zej e_ d(dd„Zdd„ Zdd„ Zej e_ dd„ Zd)d d!„Zd*d"d#„Z ej e _ dS )+zd
Discrete Fourier Transform, Number Theoretic Transform,
Walsh Hadamard Transform, Mobius Transform
é    )ÚSÚSymbolÚsympify)Ú
expand_mul)ÚpiÚI)ÚsinÚcos)ÚisprimeÚprimitive_root)ÚibinÚiterable©Úas_intFc                    s  t | ƒstdƒ‚dd„ | D ƒ}tdd„ |D ƒƒr8tdƒ‚t|ƒ‰ˆdk rL|S ˆ ¡ d }ˆˆd @ rt|d7 }d| ‰|tjgˆt|ƒ  7 }tdˆƒD ]D}t	t
||d	d
�ddd… dƒ}||k r–|| ||  ||< ||< q–|rìdt ˆ n
dt ˆ ‰ ˆdk	�rˆ  ˆd ¡‰ ‡ fdd„tˆd ƒD ƒ}d}|ˆk�rÎ|d ˆ|  }	}
tdˆ|ƒD ]j}t|	ƒD ]Z}|||  t||| |	  ||
|   ƒ }}|| ||  ||| < ||| |	 < �qb�qV|d9 }�q.|�rˆdk	�rò‡‡fdd„|D ƒn‡fdd„|D ƒ}|S )z3Utility function for the Discrete Fourier TransformzAExpected a sequence of numeric coefficients for Fourier Transformc                 S   s   g | ]}t |ƒ‘qS © ©r   ©Ú.0Úargr   r   úX/var/www/html/bwave/python/venv/lib/python3.8/site-packages/sympy/discrete/transforms.pyÚ
<listcomp>   s     z&_fourier_transform.<locals>.<listcomp>c                 s   s   | ]}|  t¡V  qd S )N)Úhasr   ©r   Úxr   r   r   Ú	<genexpr>   s     z%_fourier_transform.<locals>.<genexpr>z"Expected non-symbolic coefficientsé   é   T©ÚstrNéÿÿÿÿéþÿÿÿc                    s(   g | ] }t ˆ | ƒttˆ | ƒ  ‘qS r   )r	   r   r   )r   Úi)Úangr   r   r   4   s     r   c                    s   g | ]}|ˆ   ˆ ¡‘qS r   )Úevalfr   )ÚdpsÚnr   r   r   @   s     c                    s   g | ]}|ˆ  ‘qS r   r   r   ©r%   r   r   r   A   s     )r   Ú	TypeErrorÚanyÚ
ValueErrorÚlenÚ
bit_lengthr   ÚZeroÚrangeÚintr   r   r#   r   )Úseqr$   ÚinverseÚaÚbr!   ÚjÚwÚhÚhfÚutÚuÚvr   )r"   r$   r%   r   Ú_fourier_transform   sD    

..ÿr:   Nc                 C   s   t | |d�S )am  
    Performs the Discrete Fourier Transform (**DFT**) in the complex domain.

    The sequence is automatically padded to the right with zeros, as the
    *radix-2 FFT* requires the number of sample points to be a power of 2.

    This method should be used with default arguments only for short sequences
    as the complexity of expressions increases with the size of the sequence.

    Parameters
    ==========

    seq : iterable
        The sequence on which **DFT** is to be applied.
    dps : Integer
        Specifies the number of decimal digits for precision.

    Examples
    ========

    >>> from sympy import fft, ifft

    >>> fft([1, 2, 3, 4])
    [10, -2 - 2*I, -2, -2 + 2*I]
    >>> ifft(_)
    [1, 2, 3, 4]

    >>> ifft([1, 2, 3, 4])
    [5/2, -1/2 + I/2, -1/2, -1/2 - I/2]
    >>> fft(_)
    [1, 2, 3, 4]

    >>> ifft([1, 7, 3, 4], dps=15)
    [3.75, -0.5 - 0.75*I, -1.75, -0.5 + 0.75*I]
    >>> fft(_)
    [1.0, 7.0, 3.0, 4.0]

    References
    ==========

    .. [1] https://en.wikipedia.org/wiki/Cooley%E2%80%93Tukey_FFT_algorithm
    .. [2] https://mathworld.wolfram.com/FastFourierTransform.html

    )r$   ©r:   ©r/   r$   r   r   r   ÚfftF   s    .r=   c                 C   s   t | |dd�S )NT)r$   r0   r;   r<   r   r   r   Úifftw   s    r>   c                    s4  t | ƒstdƒ‚t|ƒ‰ tˆ ƒs(tdƒ‚‡ fdd„| D ƒ}t|ƒ}|dk rN|S | ¡ d }||d @ rv|d7 }d| }ˆ d | rŠtdƒ‚|dg|t|ƒ  7 }td|ƒD ]D}tt	||d	d
�ddd… dƒ}||k rª|| ||  ||< ||< qªt
ˆ ƒ}t|ˆ d | ˆ ƒ}	|�r"t|	ˆ d ˆ ƒ}	dg|d  }
td|d ƒD ]}|
|d  |	 ˆ  |
|< �q>d}||k�r|d ||  }}td||ƒD ]n}t|ƒD ]^}|||  ||| |  |
||    }}|| ˆ  || ˆ   ||| < ||| | < �q–�qŠ|d9 }�qb|�r0t|ˆ d ˆ ƒ‰‡ ‡fdd„|D ƒ}|S )z3Utility function for the Number Theoretic TransformzJExpected a sequence of integer coefficients for Number Theoretic Transformz5Expected prime modulus for Number Theoretic Transformc                    s   g | ]}t |ƒˆ  ‘qS r   r   r   )Úpr   r   r   �   s     z/_number_theoretic_transform.<locals>.<listcomp>r   r   z/Expected prime modulus of the form (m*2**k + 1)r   Tr   Nr   c                    s   g | ]}|ˆ ˆ  ‘qS r   r   r   ©r?   Úrvr   r   r   ¸   s     )r   r'   r   r
   r)   r*   r+   r-   r.   r   r   Úpow)r/   Úprimer0   r1   r%   r2   r!   r3   ÚprÚrtr4   r5   r6   r7   r8   r9   r   r@   r   Ú_number_theoretic_transformƒ   sN    
*6rF   c                 C   s   t | |d�S )aR  
    Performs the Number Theoretic Transform (**NTT**), which specializes the
    Discrete Fourier Transform (**DFT**) over quotient ring `Z/pZ` for prime
    `p` instead of complex numbers `C`.

    The sequence is automatically padded to the right with zeros, as the
    *radix-2 NTT* requires the number of sample points to be a power of 2.

    Parameters
    ==========

    seq : iterable
        The sequence on which **DFT** is to be applied.
    prime : Integer
        Prime modulus of the form `(m 2^k + 1)` to be used for performing
        **NTT** on the sequence.

    Examples
    ========

    >>> from sympy import ntt, intt
    >>> ntt([1, 2, 3, 4], prime=3*2**8 + 1)
    [10, 643, 767, 122]
    >>> intt(_, 3*2**8 + 1)
    [1, 2, 3, 4]
    >>> intt([1, 2, 3, 4], prime=3*2**8 + 1)
    [387, 415, 384, 353]
    >>> ntt(_, prime=3*2**8 + 1)
    [1, 2, 3, 4]

    References
    ==========

    .. [1] http://www.apfloat.org/ntt.html
    .. [2] https://mathworld.wolfram.com/NumberTheoreticTransform.html
    .. [3] https://en.wikipedia.org/wiki/Discrete_Fourier_transform_(general%29

    )rC   ©rF   ©r/   rC   r   r   r   Úntt½   s    (rI   c                 C   s   t | |dd�S )NT)rC   r0   rG   rH   r   r   r   Úinttè   s    rJ   c           	         sþ   t | ƒstdƒ‚dd„ | D ƒ}t|ƒ‰ ˆ dk r2|S ˆ ˆ d @ rJdˆ  ¡  ‰ |tjgˆ t|ƒ  7 }d}|ˆ krä|d }tdˆ |ƒD ]V}t|ƒD ]H}|||  ||| |   }}|| ||  ||| < ||| | < qŽq‚|d9 }qf|rú‡ fdd„|D ƒ}|S )z1Utility function for the Walsh Hadamard Transformz@Expected a sequence of coefficients for Walsh Hadamard Transformc                 S   s   g | ]}t |ƒ‘qS r   r   r   r   r   r   r   û   s     z-_walsh_hadamard_transform.<locals>.<listcomp>r   r   r   c                    s   g | ]}|ˆ  ‘qS r   r   r   r&   r   r   r     s     ©r   r'   r*   r+   r   r,   r-   )	r/   r0   r1   r5   r6   r!   r3   r8   r9   r   r&   r   Ú_walsh_hadamard_transformô   s(    *
rL   c                 C   s   t | ƒS )aN  
    Performs the Walsh Hadamard Transform (**WHT**), and uses Hadamard
    ordering for the sequence.

    The sequence is automatically padded to the right with zeros, as the
    *radix-2 FWHT* requires the number of sample points to be a power of 2.

    Parameters
    ==========

    seq : iterable
        The sequence on which WHT is to be applied.

    Examples
    ========

    >>> from sympy import fwht, ifwht
    >>> fwht([4, 2, 2, 0, 0, 2, -2, 0])
    [8, 0, 8, 0, 8, 8, 0, 0]
    >>> ifwht(_)
    [4, 2, 2, 0, 0, 2, -2, 0]

    >>> ifwht([19, -1, 11, -9, -7, 13, -15, 5])
    [2, 0, 4, 0, 3, 10, 0, 0]
    >>> fwht(_)
    [19, -1, 11, -9, -7, 13, -15, 5]

    References
    ==========

    .. [1] https://en.wikipedia.org/wiki/Hadamard_transform
    .. [2] https://en.wikipedia.org/wiki/Fast_Walsh%E2%80%93Hadamard_transform

    ©rL   ©r/   r   r   r   Úfwht  s    $rO   c                 C   s   t | dd�S )NT)r0   rM   rN   r   r   r   Úifwht:  s    rP   c                 C   sþ   t | ƒstdƒ‚dd„ | D ƒ}t|ƒ}|dk r2|S ||d @ rJd| ¡  }|tjg|t|ƒ  7 }|r°d}||k rút|ƒD ](}||@ rz||  ||||A   7  < qz|d9 }qjnJd}||k rút|ƒD ]*}||@ rÒqÄ||  ||||A   7  < qÄ|d9 }q´|S )z\Utility function for performing Mobius Transform using
    Yate's Dynamic Programming methodz#Expected a sequence of coefficientsc                 S   s   g | ]}t |ƒ‘qS r   r   r   r   r   r   r   M  s     z%_mobius_transform.<locals>.<listcomp>r   r   rK   )r/   ÚsgnÚsubsetr1   r%   r!   r3   r   r   r   Ú_mobius_transformF  s0    
rS   Tc                 C   s   t | d|d�S )a
  
    Performs the Mobius Transform for subset lattice with indices of
    sequence as bitmasks.

    The indices of each argument, considered as bit strings, correspond
    to subsets of a finite set.

    The sequence is automatically padded to the right with zeros, as the
    definition of subset/superset based on bitmasks (indices) requires
    the size of sequence to be a power of 2.

    Parameters
    ==========

    seq : iterable
        The sequence on which Mobius Transform is to be applied.
    subset : bool
        Specifies if Mobius Transform is applied by enumerating subsets
        or supersets of the given set.

    Examples
    ========

    >>> from sympy import symbols
    >>> from sympy import mobius_transform, inverse_mobius_transform
    >>> x, y, z = symbols('x y z')

    >>> mobius_transform([x, y, z])
    [x, x + y, x + z, x + y + z]
    >>> inverse_mobius_transform(_)
    [x, y, z, 0]

    >>> mobius_transform([x, y, z], subset=False)
    [x + y + z, y, z, 0]
    >>> inverse_mobius_transform(_, subset=False)
    [x, y, z, 0]

    >>> mobius_transform([1, 2, 3, 4])
    [1, 3, 4, 10]
    >>> inverse_mobius_transform(_)
    [1, 2, 3, 4]
    >>> mobius_transform([1, 2, 3, 4], subset=False)
    [10, 6, 7, 4]
    >>> inverse_mobius_transform(_, subset=False)
    [1, 2, 3, 4]

    References
    ==========

    .. [1] https://en.wikipedia.org/wiki/M%C3%B6bius_inversion_formula
    .. [2] https://people.csail.mit.edu/rrw/presentations/subset-conv.pdf
    .. [3] https://arxiv.org/pdf/1211.0189.pdf

    r   ©rQ   rR   ©rS   ©r/   rR   r   r   r   Úmobius_transforml  s    8rW   c                 C   s   t | d|d�S )Nr   rT   rU   rV   r   r   r   Úinverse_mobius_transform¦  s    rX   )F)N)N)F)F)T)T)!Ú__doc__Z
sympy.corer   r   r   Zsympy.core.functionr   Zsympy.core.numbersr   r   Z(sympy.functions.elementary.trigonometricr   r	   Zsympy.ntheoryr
   r   Zsympy.utilities.iterablesr   r   Zsympy.utilities.miscr   r:   r=   r>   rF   rI   rJ   rL   rO   rP   rS   rW   rX   r   r   r   r   Ú<module>   s.   	
1
1
	
:+	
'	&
:
