
    Ed8                         d Z ddlmZmZ ddlmZ ddlmZmZm	Z	m
Z
mZmZmZmZ ddlmZ ddlmZ ddZdd	Zd
 Zd Zd Zd Zd ZdS )zl
Convolution (using **FFT**, **NTT**, **FWHT**), Subset Convolution,
Covering Product, Intersecting Product
    )Ssympify
expand_mul)fftifftnttinttfwhtifwhtmobius_transforminverse_mobius_transform)iterable)as_intNc                    t          |          dk     rt          d          |rdnd}|rdnd}t          d |||fD                       dk    rt          d          3t	          | |          snfd	t                    D             S |rt          | |          n%|rt          | |          nt          | ||
          snfdt                    D             S )a  
    Performs convolution by determining the type of desired
    convolution using hints.

    Exactly one of ``dps``, ``prime``, ``dyadic``, ``subset`` arguments
    should be specified explicitly for identifying the type of convolution,
    and the argument ``cycle`` can be specified optionally.

    For the default arguments, linear convolution is performed using **FFT**.

    Parameters
    ==========

    a, b : iterables
        The sequences for which convolution is performed.
    cycle : Integer
        Specifies the length for doing cyclic convolution.
    dps : Integer
        Specifies the number of decimal digits for precision for
        performing **FFT** on the sequence.
    prime : Integer
        Prime modulus of the form `(m 2^k + 1)` to be used for
        performing **NTT** on the sequence.
    dyadic : bool
        Identifies the convolution type as dyadic (*bitwise-XOR*)
        convolution, which is performed using **FWHT**.
    subset : bool
        Identifies the convolution type as subset convolution.

    Examples
    ========

    >>> from sympy import convolution, symbols, S, I
    >>> u, v, w, x, y, z = symbols('u v w x y z')

    >>> convolution([1 + 2*I, 4 + 3*I], [S(5)/4, 6], dps=3)
    [1.25 + 2.5*I, 11.0 + 15.8*I, 24.0 + 18.0*I]
    >>> convolution([1, 2, 3], [4, 5, 6], cycle=3)
    [31, 31, 28]

    >>> convolution([111, 777], [888, 444], prime=19*2**10 + 1)
    [1283, 19351, 14219]
    >>> convolution([111, 777], [888, 444], prime=19*2**10 + 1, cycle=2)
    [15502, 19351]

    >>> convolution([u, v], [x, y, z], dyadic=True)
    [u*x + v*y, u*y + v*x, u*z, v*z]
    >>> convolution([u, v], [x, y, z], dyadic=True, cycle=2)
    [u*x + u*z + v*y, u*y + v*x + v*z]

    >>> convolution([u, v, w], [x, y, z], subset=True)
    [u*x, u*y + v*x, u*z + w*x, v*z + w*y]
    >>> convolution([u, v, w], [x, y, z], subset=True, cycle=3)
    [u*x + v*z + w*y, u*y + v*x, u*z + w*x]

    r   z6The length for cyclic convolution must be non-negativeTNc              3      K   | ]}|d uV  	d S N ).0xs     ;lib/python3.11/site-packages/sympy/discrete/convolutions.py	<genexpr>zconvolution.<locals>.<genexpr>P   s&      
?
?Q1D=
?
?
?
?
?
?       z0Ambiguity in determining the type of convolution)primec                 F    g | ]}t          |d                    z  S r   sum)r   iclsr   s     r   
<listcomp>zconvolution.<locals>.<listcomp>U   s.     I I I1R1X!6 I I Ir   )dpsc                 @    g | ]}t          |d                    S r   r   )r   r   r    r!   s     r   r"   zconvolution.<locals>.<listcomp>^   s)    ===qSADqD]]===r   )	r   
ValueErrorr   	TypeErrorconvolution_nttrangeconvolution_fwhtconvolution_subsetconvolution_fft)	abcycler#   r   dyadicsubsetr    r!   s	       `  @@r   convolutionr1      sQ   t 	uA1u 0 / 0 0 	0 %TTF%TTF

?
?5#vv">
?
?
???!C LJKKK JQ///Irr I I I I I Ia I I II ,a##	 ,1%%Qs+++=22=====E!HH====r   c                    | dd         |dd         }} t          |           t          |          z   dz
  x}}|dk    r||dz
  z  rd|                                z  }| t          j        g|t          |           z
  z  z  } |t          j        g|t          |          z
  z  z  }t	          | |          t	          ||          }} d t          | |          D             } t          | |          d|         } | S )a  
    Performs linear convolution using Fast Fourier Transform.

    Parameters
    ==========

    a, b : iterables
        The sequences for which convolution is performed.
    dps : Integer
        Specifies the number of decimal digits for precision.

    Examples
    ========

    >>> from sympy import S, I
    >>> from sympy.discrete.convolutions import convolution_fft

    >>> convolution_fft([2, 3], [4, 5])
    [8, 22, 15]
    >>> convolution_fft([2, 5], [6, 7, 3])
    [12, 44, 41, 15]
    >>> convolution_fft([1 + 2*I, 4 + 3*I], [S(5)/4, 6])
    [5/4 + 5*I/2, 11 + 63*I/4, 24 + 18*I]

    References
    ==========

    .. [1] https://en.wikipedia.org/wiki/Convolution_theorem
    .. [2] https://en.wikipedia.org/wiki/Discrete_Fourier_transform_(general%29

    Nr   r      c                 8    g | ]\  }}t          ||z            S r   r   r   r   ys      r   r"   z#convolution_fft.<locals>.<listcomp>   &    ///TQAaC///r   )len
bit_lengthr   Zeror   zipr   )r,   r-   r#   nms        r   r+   r+   g   s    B QQQ4111qAFFSVVOaA1u AE q||~~ !&1s1vv:	A!&1s1vv:	Aq#;;AsqA//SAYY///AQRaRAHr   c                    | dd         |dd         t          |          c} }t          |           t          |          z   dz
  x}}|dk    r||dz
  z  rd|                                z  }| dg|t          |           z
  z  z  } |dg|t          |          z
  z  z  }t          |           t          |          }} fdt	          | |          D             } t          |           d|         } | S )a=  
    Performs linear convolution using Number Theoretic Transform.

    Parameters
    ==========

    a, b : iterables
        The sequences for which convolution is performed.
    prime : Integer
        Prime modulus of the form `(m 2^k + 1)` to be used for performing
        **NTT** on the sequence.

    Examples
    ========

    >>> from sympy.discrete.convolutions import convolution_ntt
    >>> convolution_ntt([2, 3], [4, 5], prime=19*2**10 + 1)
    [8, 22, 15]
    >>> convolution_ntt([2, 5], [6, 7, 3], prime=19*2**10 + 1)
    [12, 44, 41, 15]
    >>> convolution_ntt([333, 555], [222, 666], prime=19*2**10 + 1)
    [15555, 14219, 19404]

    References
    ==========

    .. [1] https://en.wikipedia.org/wiki/Convolution_theorem
    .. [2] https://en.wikipedia.org/wiki/Discrete_Fourier_transform_(general%29

    Nr   r   r3   c                 &    g | ]\  }}||z  z  S r   r   )r   r   r6   ps      r   r"   z#convolution_ntt.<locals>.<listcomp>   s%    '''TQ1q'''r   )r   r8   r9   r	   r;   r
   )r,   r-   r   r<   r=   r@   s        @r   r'   r'      s   @ dAaaaD&--GAq!FFSVVOaA1u AE q||~~ !a#a&&j	A!a#a&&j	Aq!99c!QiiqA''''SAYY'''AQ

2A2AHr   c                    | r|sg S | dd         |dd         }} t          t          |           t          |                    }||dz
  z  rd|                                z  }| t          j        g|t          |           z
  z  z  } |t          j        g|t          |          z
  z  z  }t          |           t          |          }} d t          | |          D             } t          |           } | S )a  
    Performs dyadic (*bitwise-XOR*) convolution using Fast Walsh Hadamard
    Transform.

    The convolution 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
    ==========

    a, b : iterables
        The sequences for which convolution is performed.

    Examples
    ========

    >>> from sympy import symbols, S, I
    >>> from sympy.discrete.convolutions import convolution_fwht

    >>> u, v, x, y = symbols('u v x y')
    >>> convolution_fwht([u, v], [x, y])
    [u*x + v*y, u*y + v*x]

    >>> convolution_fwht([2, 3], [4, 5])
    [23, 22]
    >>> convolution_fwht([2, 5 + 4*I, 7], [6*I, 7, 3 + 4*I])
    [56 + 68*I, -10 + 30*I, 6 + 50*I, 48 + 32*I]

    >>> convolution_fwht([S(33)/7, S(55)/6, S(7)/4], [S(2)/3, 5])
    [2057/42, 1870/63, 7/6, 35/4]

    References
    ==========

    .. [1] https://www.radioeng.cz/fulltexts/2002/02_03_40_42.pdf
    .. [2] https://en.wikipedia.org/wiki/Hadamard_transform

    Nr   r3   c                 8    g | ]\  }}t          ||z            S r   r   r5   s      r   r"   z$convolution_fwht.<locals>.<listcomp>  r7   r   )maxr8   r9   r   r:   r   r;   r   r,   r-   r<   s      r   r)   r)      s    P  A 	QQQ4111qACFFCFFA!a%y q||~~ !&1s1vv:	A!&1s1vv:	A77DGGqA//SAYY///AaAHr   c           
         | r|sg S t          |           rt          |          st          d          d | D             } d |D             }t          t          |           t          |                    }||dz
  z  rd|                                z  }| t
          j        g|t          |           z
  z  z  } |t
          j        g|t          |          z
  z  z  }t
          j        g|z  }t          |          D ]v}|}|dk    r=||xx         t          | |         |||z           z            z  cc<   |dz
  |z  }|dk    =||xx         t          | |         |||z           z            z  cc<   w|S )a  
    Performs Subset Convolution of given sequences.

    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 based on bitmasks (indices) requires the size of
    sequence to be a power of 2.

    Parameters
    ==========

    a, b : iterables
        The sequences for which convolution is performed.

    Examples
    ========

    >>> from sympy import symbols, S
    >>> from sympy.discrete.convolutions import convolution_subset
    >>> u, v, x, y, z = symbols('u v x y z')

    >>> convolution_subset([u, v], [x, y])
    [u*x, u*y + v*x]
    >>> convolution_subset([u, v, x], [y, z])
    [u*y, u*z + v*y, x*y, x*z]

    >>> convolution_subset([1, S(2)/3], [3, 4])
    [3, 6]
    >>> convolution_subset([1, 3, S(5)/7], [7])
    [7, 21, 5, 0]

    References
    ==========

    .. [1] https://people.csail.mit.edu/rrw/presentations/subset-conv.pdf

    z3Expected a sequence of coefficients for convolutionc                 ,    g | ]}t          |          S r   r   r   args     r   r"   z&convolution_subset.<locals>.<listcomp>G      #######r   c                 ,    g | ]}t          |          S r   rG   rH   s     r   r"   z&convolution_subset.<locals>.<listcomp>H  rJ   r   r   r3   r   )	r   r&   rC   r8   r9   r   r:   r(   r   )r,   r-   r<   r    masksmasks         r   r*   r*     s   R  A 	A;; Ohqkk OMNNN#####A#####ACFFCFFA!a%y q||~~ !&1s1vv:	A!&1s1vv:	A	

Aa 8 8ai 	%dGGGz!E(QtEz]":;;;GGGQY$E ai 	% 	
$:ah4:6777Hr   c                    | r|sg S | dd         |dd         }} t          t          |           t          |                    }||dz
  z  rd|                                z  }| t          j        g|t          |           z
  z  z  } |t          j        g|t          |          z
  z  z  }t          |           t          |          }} d t          | |          D             } t          |           } | S )a  
    Returns the covering product of given sequences.

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

    The covering product of given sequences is a sequence which contains
    the sum of products of the elements of the given sequences grouped by
    the *bitwise-OR* of the corresponding indices.

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

    Parameters
    ==========

    a, b : iterables
        The sequences for which covering product is to be obtained.

    Examples
    ========

    >>> from sympy import symbols, S, I, covering_product
    >>> u, v, x, y, z = symbols('u v x y z')

    >>> covering_product([u, v], [x, y])
    [u*x, u*y + v*x + v*y]
    >>> covering_product([u, v, x], [y, z])
    [u*y, u*z + v*y + v*z, x*y, x*z]

    >>> covering_product([1, S(2)/3], [3, 4 + 5*I])
    [3, 26/3 + 25*I/3]
    >>> covering_product([1, 3, S(5)/7], [7, 8])
    [7, 53, 5, 40/7]

    References
    ==========

    .. [1] https://people.csail.mit.edu/rrw/presentations/subset-conv.pdf

    Nr   r3   c                 8    g | ]\  }}t          ||z            S r   r   r5   s      r   r"   z$covering_product.<locals>.<listcomp>  r7   r   rC   r8   r9   r   r:   r   r;   r   rD   s      r   covering_productrQ   e  s    X  A 	QQQ4111qACFFCFFA!a%y q||~~ !&1s1vv:	A!&1s1vv:	AA 0 3 3qA//SAYY///A ##AHr   c                    | r|sg S | dd         |dd         }} t          t          |           t          |                    }||dz
  z  rd|                                z  }| t          j        g|t          |           z
  z  z  } |t          j        g|t          |          z
  z  z  }t          | d          t          |d          }} d t          | |          D             } t          | d          } | S )a  
    Returns the intersecting product of given sequences.

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

    The intersecting product of given sequences is the sequence which
    contains the sum of products of the elements of the given sequences
    grouped by the *bitwise-AND* of the corresponding indices.

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

    Parameters
    ==========

    a, b : iterables
        The sequences for which intersecting product is to be obtained.

    Examples
    ========

    >>> from sympy import symbols, S, I, intersecting_product
    >>> u, v, x, y, z = symbols('u v x y z')

    >>> intersecting_product([u, v], [x, y])
    [u*x + u*y + v*x, v*y]
    >>> intersecting_product([u, v, x], [y, z])
    [u*y + u*z + v*y + x*y + x*z, v*z, 0, 0]

    >>> intersecting_product([1, S(2)/3], [3, 4 + 5*I])
    [9 + 5*I, 8/3 + 10*I/3]
    >>> intersecting_product([1, 3, S(5)/7], [7, 8])
    [327/7, 24, 0, 0]

    References
    ==========

    .. [1] https://people.csail.mit.edu/rrw/presentations/subset-conv.pdf

    Nr   r3   F)r0   c                 8    g | ]\  }}t          ||z            S r   r   r5   s      r   r"   z(intersecting_product.<locals>.<listcomp>  r7   r   rP   rD   s      r   intersecting_productrT     s   X  A 	QQQ4111qACFFCFFA!a%y q||~~ !&1s1vv:	A!&1s1vv:	AAe,,,.>q.O.O.OqA//SAYY///A 5111AHr   )r   NNNNr   )__doc__
sympy.corer   r   sympy.core.functionr   sympy.discrete.transformsr   r   r	   r
   r   r   r   r   sympy.utilities.iterablesr   sympy.utilities.miscr   r1   r+   r'   r)   r*   rQ   rT   r   r   r   <module>r[      sO   
 " ! ! ! ! ! ! ! * * * * * *0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 / . . . . . ' ' ' ' ' 'O> O> O> O>p/ / / /p. . .n9 9 9DD D DZ= = =L= = = = =r   