
    \hG                         S r SSKJrJrJr  SSKJr  SSKJrJ	r	J
r
JrJrJrJrJr  SSKJrJr  SSKJr  SSKJr  SS	 jrSS
 jrS rS rS rS rS rS rg)zl
Convolution (using **FFT**, **NTT**, **FWHT**), Subset Convolution,
Covering Product, Intersecting Product
    )SsympifyRational)
expand_mul)fftifftnttinttfwhtifwhtmobius_transforminverse_mobius_transform)MPZlcm)iterable)as_intNc           	         [        U5      nUS:  a  [        S5      eU(       a  SOSnU(       a  SOSn[        S XCXV4 5       5      S:  a  [        S5      eUb@  [	        XUS9nU(       d  U$ [        U5       V	s/ s H  n	[        XSU2   5      U-  PM     sn	$ U(       a  [        X5      nOxU(       a  [        X5      nOeS	 n
SnU
" U 5      nUbF  U
" U5      nUb;  Xsu  pu  nnUU-  n[        X5      nUS:w  a  U V	s/ s H  n	[        U	U5      PM     nn	Uc  [        XU5      nU(       d  U$ [        U5       V	s/ s H  n	[        XSU2   5      PM     sn	$ s  sn	f s  sn	f s  sn	f )
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   (   #    U  H  oS Lv   M
     g 7fN ).0xs     S/var/www/auris/envauris/lib/python3.13/site-packages/sympy/discrete/convolutions.py	<genexpr>convolution.<locals>.<genexpr>Q   s     
?">QD=">s      z0Ambiguity in determining the type of convolution)primec                    / nU  H`  n[        U[        5      (       a1  UR                  S-
  (       a  UR                  UR                  5        MI  [        U[        5      (       a  M`    g    U(       aL  [        U6 nU  Vs/ s H4  n[        U5      [        L a  X#-  OUR                  X2R                  -  -  PM6     snU4$ U S4$ s  snf )Nr   )
isinstancer   qappendintr   typep)adensils       r   loopconvolution.<locals>.loop]   s    Da**qssQwKK$#As++	 
 JIJKAtAw#~13333<?KQNNa4K Ls   <;C )r   
ValueErrorsum	TypeErrorconvolution_nttrangeconvolution_fwhtconvolution_subsetconvolution_intr   convolution_fft)r%   bcycledpsr   dyadicsubsetclsr'   r)   dadbiamaibmbdens                     r   convolutionrB      sw   t 	uA1u / 0 	0 TFTF

?5v">
??!CJKKQ/rIa I1R1X!6 IIa#	%	 !W>aB~%'"(2re$R,!8467Bq(1c*BB7: s+B2=E!H=HqSDqD]H==A !J8 8 >s   9E=E:E!c                    U SS USS p[        U 5      [        U5      -   S-
  =p4US:  a  X3S-
  -  (       a  SUR                  5       -  nU [        R                  /U[        U 5      -
  -  -  n U[        R                  /U[        U5      -
  -  -  n[	        X5      [	        X5      p[        X5       VVs/ s H  u  pV[        XV-  5      PM     n nn[        X5      SU n U $ s  snnf )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      )len
bit_lengthr   Zeror   zipr   r   )r%   r4   r6   nmr   ys          r   r3   r3      s    B Q41qFSVOaA1uEq||~ !&&1s1v:	A!&&1s1v:	Aq;Aq%(Y/YTQACYA/QRaAH 	0s   3Cc                    U SS USS [        U5      p1n [        U 5      [        U5      -   S-
  =pEUS:  a  XDS-
  -  (       a  SUR                  5       -  nU S/U[        U 5      -
  -  -  n US/U[        U5      -
  -  -  n[        X5      [        X5      p[	        X5       VVs/ s H  u  pgXg-  U-  PM     n nn[        X5      SU n U $ s  snnf )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   rD   )r   rE   rF   r	   rH   r
   )r%   r4   r   r$   rI   rJ   r   rK   s           r   r.   r.      s    @ dAaD&-!AFSVOaA1uEq||~ !a#a&j	A!a#a&j	Aq9c!iq Y'YTQqYA'Q
2AAH 	(s   "Cc                    U (       a  U(       d  / $ U SS USS p[        [        U 5      [        U5      5      nX"S-
  -  (       a  SUR                  5       -  nU [        R                  /U[        U 5      -
  -  -  n U[        R                  /U[        U5      -
  -  -  n[        U 5      [        U5      p[        X5       VVs/ s H  u  p4[        X4-  5      PM     n nn[        U 5      n U $ s  snnf )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   rD   )	maxrE   rF   r   rG   r   rH   r   r   r%   r4   rI   r   rK   s        r   r0   r0      s    P A	Q41qCFCFAa%yq||~ !&&1s1v:	A!&&1s1v:	A7DGq%(Y/YTQACYA/aAH 	0    C)c           
         U (       a  U(       d  / $ [        U 5      (       a  [        U5      (       d  [        S5      eU  Vs/ s H  n[        U5      PM     n nU Vs/ s H  n[        U5      PM     nn[        [	        U 5      [	        U5      5      nX3S-
  -  (       a  SUR                  5       -  nU [        R                  /U[	        U 5      -
  -  -  n U[        R                  /U[	        U5      -
  -  -  n[        R                  /U-  n[        U5       HY  nUnUS:  a/  XE==   [        X   XU-     -  5      -  ss'   US-
  U-  nUS:  a  M/  XE==   [        X   XU-     -  5      -  ss'   M[     U$ s  snf s  snf )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 convolutionr   rD   r   )
r   r-   r   rN   rE   rF   r   rG   r/   r   )r%   r4   argrI   r9   masksmasks          r   r1   r1   0  sR   R A	A;;hqkkMNN!"##A#!"##A#CFCFAa%yq||~ !&&1s1v:	A!&&1s1v:	A	

AaaiGz!(QEz]":;;GQY$E ai 	
:ah:677  H+ 	$#s    E3E8c                    U (       a  U(       d  / $ U SS USS p[        [        U 5      [        U5      5      nX"S-
  -  (       a  SUR                  5       -  nU [        R                  /U[        U 5      -
  -  -  n U[        R                  /U[        U5      -
  -  -  n[        U 5      [        U5      p[        X5       VVs/ s H  u  p4[        X4-  5      PM     n nn[        U 5      n U $ s  snnf )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   rD   	rN   rE   rF   r   rG   r   rH   r   r   rO   s        r   covering_productrW   }  s    X A	Q41qCFCFAa%yq||~ !&&1s1v:	A!&&1s1v:	AA 0 3q%(Y/YTQACYA/ #AH 	0rP   c                    U (       a  U(       d  / $ U SS USS p[        [        U 5      [        U5      5      nX"S-
  -  (       a  SUR                  5       -  nU [        R                  /U[        U 5      -
  -  -  n U[        R                  /U[        U5      -
  -  -  n[        U SS9[        USS9p[        X5       VVs/ s H  u  p4[        X4-  5      PM     n nn[        U SS9n U $ s  snnf )ak  
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   rD   F)r8   rV   rO   s        r   intersecting_productrY     s    X A	Q41qCFCFAa%yq||~ !&&1s1v:	A!&&1s1v:	AAe,.>q.Oq%(Y/YTQACYA/ 51AH 	0s   >C&c                   ^ [        S U  5       5      [        S U 5       5      -  S[        [        U 5      S-
  [        U5      S-
  5      -   -  n[        S5      SsnmUSU-  ::  a  US-  nTS-  mUSU-  ::  a  M  U4S jnU" U 5      U" U5      su  pVu  pxXh-  n	XW-  n
US-
  US-	  S/ 4u  ppU	(       d  U(       aH  X-  U-   nU	T-  n	X:  nUR	                  U
[        X:  a  UOX-
  5      -  5        U	(       a  M?  U(       a  MH  U=(       d    S/$ )a@  Return the convolution of two sequences as a list.

The iterables must consist solely of integers.

Parameters
==========

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

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

This function performs the convolution of ``a`` and ``b`` by packing
each into a single integer, multiplying them together, and then
unpacking the result from the product.  The intuition behind this is
that if we evaluate some polynomial [1]:

.. math ::
    1156x^6 + 3808x^5 + 8440x^4 + 14856x^3 + 16164x^2 + 14040x + 8100

at say $x = 10^5$ we obtain $1156038080844014856161641404008100$.
Note we can read of the coefficients for each term every five digits.
If the $x$ we chose to evaluate at is large enough, the same will hold
for the product.

The idea now is since big integer multiplication in libraries such
as GMP is highly optimised, this will be reasonably fast.

Examples
========

>>> from sympy.discrete.convolutions import convolution_int

>>> convolution_int([2, 3], [4, 5])
[8, 22, 15]
>>> convolution_int([1, 1, -1], [1, 1])
[1, 2, 0, -1]

References
==========

.. [1] Fateman, Richard J.
       Can you save time in multiplying polynomials by encoding them as integers?
       University of California, Berkeley, California (2004).
       https://people.eecs.berkeley.edu/~fateman/papers/polysbyGMP.pdf
c              3   8   #    U  H  n[        U5      v   M     g 7fr   absr   r9   s     r   r   "convolution_int.<locals>.<genexpr>;  s     AqCFFA   c              3   8   #    U  H  n[        U5      v   M     g 7fr   r\   r^   s     r   r   r_   ;  s     "51a3q661r`   r   r   rD   c                    > [        S5      Sp![        U 5       H0  nU(       a  U(       d
  US:  a  SOSnUT-  nX[        U5      -  -  nM2     X!4$ )Nr   r   )r   reversedr"   )polyrI   mulr9   powers       r   
to_integer#convolution_int.<locals>.to_integerA  sN    Q3$A!a%BQc%KASVOA   v    )rN   minrE   r   r!   r"   )r%   r4   Br   rh   a_mula_packedb_mulb_packedresultrf   rS   halfborrowre   coeffrg   s                   @r   r2   r2   	  s'   d 	As"51"555q3s1vz3q6TU:;V7VWA1vqHAu
!*	a
 !* ,6a=*Q-(U( F -C 1ua1fa3D
F&(5C#u|eCCD	 &FF
 ;A3rj   )r   NNNNr   )__doc__
sympy.corer   r   r   sympy.core.functionr   sympy.discrete.transformsr   r   r	   r
   r   r   r   r   sympy.external.gmpyr   r   sympy.utilities.iterablesr   sympy.utilities.miscr   rB   r3   r.   r0   r1   rW   rY   r2   r   rj   r   <module>r|      sa   
 , + *0 0 0 ) . 'f>^/p.n9DDZ=L=LLrj   