K iGdZddlmZmZmZddlmZddlmZm Z m Z m Z m Z m Z mZmZddlmZmZddlmZddlmZdd Zdd Zd Zd Zd ZdZdZdZy)zl Convolution (using **FFT**, **NTT**, **FWHT**), Subset Convolution, Covering Product, Intersecting Product )SsympifyRational) expand_mul)fftifftnttinttfwhtifwhtmobius_transforminverse_mobius_transform)MPZlcm)iterable)as_intNc t|}|dkr td|rdnd}|rdnd}td||||fDdkDr td|=t |||}|s|St |D cgc]} t|| d||zc} S|r t ||}nq|r t||}nbd } d}| |} | D| |} | :| | c\} }\}}||z}t| |}|dk7r|D cgc]} t| |}} | t|||}|s|St |D cgc]} t|| d|c} Scc} wcc} wcc} w) 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] rz6The length for cyclic convolution must be non-negativeTNc3$K|]}|du ywN).0xs a/mnt/ssd/data/python-lab/Trading/venv/lib/python3.12/site-packages/sympy/discrete/convolutions.py zconvolution..Qs ?Q1D= ?sz0Ambiguity in determining the type of convolution)primecXg}|D]O}t|tr+|jdz r|j|j>t|trOy|rJt |}|Dcgc]4}t |tur||zn|j||jzz6c}|fS|dfScc}w)Nr) isinstancerqappendintrtypep)adensils rloopzconvolution..loop]sD a*qssQwKK$#As+   JIJKAtAw#~!133133<?KQNNa4KLs%9B') r ValueErrorsum TypeErrorconvolution_nttrangeconvolution_fwhtconvolution_subsetconvolution_intrconvolution_fft)r$bcycledpsrdyadicsubsetclsr&r(dadbiamaibmbdens r convolutionr@st u A1u/0 0TFTF ?5#vv"> ??!CJKK  Q /rIa I1R1X!6 II a #  1 %  !W >aB~%'"R(2re$R,!8467q(1c*7B7 : As+B2=E!H=qSADqD]==A!J88>s-D7'D<Ec|dd|dd}}t|t|zdz x}}|dkDr||dz zrd|jz}|tjg|t|z zz }|tjg|t|z zz }t ||t ||}}t ||Dcgc]\}}t ||z}}}t||d|}|Scc}}w)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 Nrr)len bit_lengthrZerorziprr)r$r2r4nmrys rr1r1sB Q41qA FSVOa A1uAE q||~ !&&1s1v: A!&&1s1v: A q#;As qA%(AY/TQAaC/A/ Q RaA H 0s4C c|dd|ddt|}}}t|t|zdz x}}|dkDr||dz zrd|jz}|dg|t|z zz }|dg|t|z zz }t||t||}}t ||Dcgc] \}}||z|z}}}t ||d|}|Scc}}w)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 NrrrB)rrCrDr rFr )r$r2rr#rGrHrrIs rr,r,s@dAaD&-!qA FSVOa A1uAE q||~ !a#a&j A!a#a&j A q!9c!QiqA AY'TQ1q'A' Q 2AA H (s#C c|r|sgS|dd|dd}}tt|t|}||dz zrd|jz}|tjg|t|z zz }|tjg|t|z zz }t |t |}}t ||Dcgc]\}}t||z}}}t|}|Scc}}w)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 NrrB) maxrCrDrrEr rFrr r$r2rGrrIs rr.r.sP A Q41qA CFCFA!a%y q||~ !&&1s1v: A!&&1s1v: A 7DGqA%(AY/TQAaC/A/ aA H 05Cc |r|sgSt|r t|s td|Dcgc] }t|}}|Dcgc] }t|}}tt |t |}||dz zrd|j z}|t jg|t |z zz }|t jg|t |z zz }t jg|z}t|D][}|}|dkDr0||xxt|||||z zz cc<|dz |z}|dkDr0||xxt|||||z zz cc<]|Scc}wcc}w)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 convolutionrrBr) rr+rrLrCrDrrEr-r)r$r2argrGr7masksmasks rr/r/0s_R A A;hqkMNN!"###A#!"###A# CFCFA!a%y q||~ !&&1s1v: A!&&1s1v: A  Aa8ai dGz!E(QtEz]":; ;GQY$Eai $:ah4:677 8 H+ $#s EEc|r|sgS|dd|dd}}tt|t|}||dz zrd|jz}|tjg|t|z zz }|tjg|t|z zz }t |t |}}t ||Dcgc]\}}t||z}}}t|}|Scc}}w)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 NrrB rLrCrDrrEr rFrrrMs rcovering_productrU}sX A Q41qA CFCFA!a%y q||~ !&&1s1v: A!&&1s1v: A A  0 3qA%(AY/TQAaC/A/ #A H 0rNc|r|sgS|dd|dd}}tt|t|}||dz zrd|jz}|tjg|t|z zz }|tjg|t|z zz }t |dt |d}}t ||Dcgc]\}}t||z}}}t|d}|Scc}}w)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 NrrBF)r6rTrMs rintersecting_productrWsX A Q41qA CFCFA!a%y q||~ !&&1s1v: A!&&1s1v: A Ae ,.>q.OqA%(AY/TQAaC/A/ 51A H 0s9C#ctd|Dtd|Dzdtt|dz t|dz zz}tddc}|d|zkr|dz}dz |d|zkrfd}||||c\}}\}}||z} ||z} |dz |dz dgf\} } } }| s| r?| | z| z}| z} || k\} |j | t || kr|n||z z| r<| r?|xsdgS)aReturn 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 c32K|]}t|ywrabsrr7s rrz"convolution_int..;s qCF c32K|]}t|ywrrZr\s rrz"convolution_int..;s"5a3q6"5r]rrrBctdd}}t|D]%}|r |s |dkrdnd}|z}||t|zz }'||fS)Nrr)rreversedr!)polyrGmulr7powers r to_integerz#convolution_int..to_integerAsYQ3$ A!a%BQc %KA SVOA Av )rLminrCrr r!)r$r2Brrea_mula_packedb_mulb_packedresultrcrQhalfborrowrbcoeffrds @rr0r0 s7d A s"51"555q3s1vz3q6TU:;V7VWA1vqHAu !* a   !*,6a=*Q-(UH(x  F %-C 1ua1fa3D$ F$&(5$ C#ut|eCCD F ;A3rf)rNNNNr)__doc__ sympy.corerrrsympy.core.functionrsympy.discrete.transformsrrr r r r r rsympy.external.gmpyrrsympy.utilities.iterablesrsympy.utilities.miscrr@r1r,r.r/rUrWr0rrfrrxsa ,+*000).'f>^/ p. n9 DD Z= L= LLrf