K iDdZddlmZmZmZddlmZm Z ddl m Z m Z m Z ddlmZddlmZddlmZdUd Zd Zd Zd Zd ZdZdZdZdZdZdZdVdZdZ dVdZ!dZ"dZ#dZ$dZ%dZ&dZ'dZ(dZ)dZ*d Z+d!Z,d"Z-d#Z.d$Z/d%Z0d&Z1d'Z2d(Z3d)Z4d*Z5d+Z6d,Z7d-Z8d.Z9d/Z:d0Z;d1Zd4Z?d5Z@d6ZAd7ZBd8ZCd9ZDd:ZEd;ZFd<ZGd=ZHeGeHd>ZId?ZJd@ZKdAZLdWdBZMdCZNdDZOdEZPdFZQdGZRdHZSdIZTdJZUdKZVePeUeVdLZWdUdMZXdNZYdOZZdPZ[dQZ\dUdRZ]dXdSZ^dTZ_y)YzADense univariate polynomials with coefficients in Galois fields. )ceilsqrtprod)uniform_randint) SYMPY_INTSMPZinvert)query)ExactQuotientFailed) _sort_factorsNct||j}|j}t||D].\}}||z}|j ||\}} } ||||z|zzz }0||zS)aH Chinese Remainder Theorem. Given a set of integer residues ``u_0,...,u_n`` and a set of co-prime integer moduli ``m_0,...,m_n``, returns an integer ``u``, such that ``u = u_i mod m_i`` for ``i = ``0,...,n``. Examples ======== Consider a set of residues ``U = [49, 76, 65]`` and a set of moduli ``M = [99, 97, 95]``. Then we have:: >>> from sympy.polys.domains import ZZ >>> from sympy.polys.galoistools import gf_crt >>> gf_crt([49, 76, 65], [99, 97, 95], ZZ) 639985 This is the correct result because:: >>> [639985 % m for m in [99, 97, 95]] [49, 76, 65] Note: this is a low-level routine with no error checking. See Also ======== sympy.ntheory.modular.crt : a higher level crt routine sympy.ntheory.modular.solve_congruence start)ronezerozipgcdex) UMKpvumes_s ]/mnt/ssd/data/python-lab/Trading/venv/lib/python3.12/site-packages/sympy/polys/galoistools.pygf_crtr svD QaeeA AAq 1 F''!Q-1a Q!a[ q5Lcgg}}t||j}|D]@}|j||z|j|j|d|d|zB|||fS)aP First part of the Chinese Remainder Theorem. Examples ======== >>> from sympy.polys.domains import ZZ >>> from sympy.polys.galoistools import gf_crt, gf_crt1, gf_crt2 >>> U = [49, 76, 65] >>> M = [99, 97, 95] The following two codes have the same result. >>> gf_crt(U, M, ZZ) 639985 >>> p, E, S = gf_crt1(M, ZZ) >>> gf_crt2(U, M, p, E, S, ZZ) 639985 However, it is faster when we want to fix ``M`` and compute for multiple U, i.e. the following cases: >>> p, E, S = gf_crt1(M, ZZ) >>> Us = [[49, 76, 65], [23, 42, 67]] >>> for U in Us: ... print(gf_crt2(U, M, p, E, S, ZZ)) 639985 236237 See Also ======== sympy.ntheory.modular.crt1 : a higher level crt routine sympy.polys.galoistools.gf_crt sympy.polys.galoistools.gf_crt2 rr)rrappendr)rrESrrs rgf_crt1r'9soN rqA QaeeA + a 2"1%)*+ a7Nr!cp|j}t||||D]\}}} } || || z|zzz }||zS)a Second part of the Chinese Remainder Theorem. See ``gf_crt1`` for usage. Examples ======== >>> from sympy.polys.domains import ZZ >>> from sympy.polys.galoistools import gf_crt2 >>> U = [49, 76, 65] >>> M = [99, 97, 95] >>> p = 912285 >>> E = [9215, 9405, 9603] >>> S = [62, 24, 12] >>> gf_crt2(U, M, p, E, S, ZZ) 639985 See Also ======== sympy.ntheory.modular.crt2 : a higher level crt routine sympy.polys.galoistools.gf_crt sympy.polys.galoistools.gf_crt1 )rr) rrrr%r&rrrrrrs rgf_crt2r)jsO: A!Q1o 1a Q!a[ q5Lr!c ||dzkr|S||z S)z Coerce ``a mod p`` to an integer in the range ``[-p/2, p/2]``. Examples ======== >>> from sympy.polys.galoistools import gf_int >>> gf_int(2, 7) 2 >>> gf_int(5, 7) -2 )ars rgf_intr.s AF{1u r!ct|dz S)z Return the leading degree of ``f``. Examples ======== >>> from sympy.polys.galoistools import gf_degree >>> gf_degree([1, 1, 2, 0]) 3 >>> gf_degree([]) -1 len)fs r gf_degreer4s q6A:r!c(|s |jS|dS)z Return the leading coefficient of ``f``. Examples ======== >>> from sympy.polys.domains import ZZ >>> from sympy.polys.galoistools import gf_LC >>> gf_LC([3, 0, 1], ZZ) 3 rrr3rs rgf_LCr8s vv t r!c(|s |jS|dS)z Return the trailing coefficient of ``f``. Examples ======== >>> from sympy.polys.domains import ZZ >>> from sympy.polys.galoistools import gf_TC >>> gf_TC([3, 0, 1], ZZ) 1 r#r6r7s rgf_TCr:s vv u r!cB|r|dr|Sd}|D] }|rn|dz } ||dS)z Remove leading zeros from ``f``. Examples ======== >>> from sympy.polys.galoistools import gf_strip >>> gf_strip([0, 0, 0, 3, 0, 1]) [3, 0, 1] rr0Nr,)r3kcoeffs rgf_stripr>sB ! A   FA  QR5Lr!cDt|Dcgc]}||z c}Scc}w)z Reduce all coefficients modulo ``p``. Examples ======== >>> from sympy.polys.galoistools import gf_trunc >>> gf_trunc([7, -2, 3], 5) [2, 3, 3] )r>)r3rr-s rgf_truncr@s! Q(a!e( ))(s c@ttt|||S)z Normalize all coefficients in ``K``. Examples ======== >>> from sympy.polys.domains import ZZ >>> from sympy.polys.galoistools import gf_normal >>> gf_normal([5, 10, 21, -3], 5, ZZ) [1, 2] )r@listmap)r3rrs r gf_normalrD s DQOQ ''r!c|t|jg}}t|trAt |ddD]0}|j |j ||j|z2nE|\}t |ddD]1}|j |j |f|j|z3t||S)a Create a ``GF(p)[x]`` polynomial from a dict. Examples ======== >>> from sympy.polys.domains import ZZ >>> from sympy.polys.galoistools import gf_from_dict >>> gf_from_dict({10: ZZ(4), 4: ZZ(33), 0: ZZ(-1)}, 5, ZZ) [4, 0, 0, 0, 0, 0, 3, 0, 0, 0, 4] r#) maxkeys isinstancerranger$getrr@)r3rrnhr<s r gf_from_dictrMs qvvx="qA!Z q"b! +A HHQUU1aff%) * +q"b! .A HHQUUA4(1, - . Aq>r!ct|i}}td|dzD]'}|rt|||z |}n|||z }|s#|||<)|S)aA Convert a ``GF(p)[x]`` polynomial to a dict. Examples ======== >>> from sympy.polys.galoistools import gf_to_dict >>> gf_to_dict([4, 0, 0, 0, 0, 0, 3, 0, 0, 0, 4], 5) {0: -1, 4: -2, 10: -1} >>> gf_to_dict([4, 0, 0, 0, 0, 0, 3, 0, 0, 0, 4], 5, symmetric=False) {0: 4, 4: 3, 10: 4} rr0)r4rIr.)r3r symmetricrKresultr<r-s r gf_to_dictrQ7sa! bvA 1a!e_ qQx#A!a%A F1I Mr!ct||S)z Create a ``GF(p)[x]`` polynomial from ``Z[x]``. Examples ======== >>> from sympy.polys.galoistools import gf_from_int_poly >>> gf_from_int_poly([7, -2, 3], 5) [2, 3, 3] )r@)r3rs rgf_from_int_polyrSTs Aq>r!cH|r|Dcgc]}t||c}S|Scc}w)a  Convert a ``GF(p)[x]`` polynomial to ``Z[x]``. Examples ======== >>> from sympy.polys.galoistools import gf_to_int_poly >>> gf_to_int_poly([2, 3, 3], 5) [2, -2, -2] >>> gf_to_int_poly([2, 3, 3], 5, symmetric=False) [2, 3, 3] )r.)r3rrOcs rgf_to_int_polyrVds( '(*!1**+sc4|Dcgc]}| |z c}Scc}w)z Negate a polynomial in ``GF(p)[x]``. Examples ======== >>> from sympy.polys.domains import ZZ >>> from sympy.polys.galoistools import gf_neg >>> gf_neg([3, 2, 1, 0], 5, ZZ) [2, 3, 4, 0] r,)r3rrr=s rgf_negrXzs&' (EeVaZ (( (s cd|s||z}n"|d|z|z}t|dkDr |dd|gzS|sgS|gS)a  Compute ``f + a`` where ``f`` in ``GF(p)[x]`` and ``a`` in ``GF(p)``. Examples ======== >>> from sympy.polys.domains import ZZ >>> from sympy.polys.galoistools import gf_add_ground >>> gf_add_ground([3, 2, 4], 2, 5, ZZ) [3, 2, 1] r#r0Nr1r3r-rrs r gf_add_groundr[sM E rUQY!O q6A:Sb6QC<   s r!cf|s| |z}n"|d|z |z}t|dkDr |dd|gzS|sgS|gS)a  Compute ``f - a`` where ``f`` in ``GF(p)[x]`` and ``a`` in ``GF(p)``. Examples ======== >>> from sympy.polys.domains import ZZ >>> from sympy.polys.galoistools import gf_sub_ground >>> gf_sub_ground([3, 2, 4], 2, 5, ZZ) [3, 2, 2] r#r0Nr1rZs r gf_sub_groundr]sO BF rUQY!O q6A:Sb6QC<   s r!c@|sgS|Dcgc] }||z|z c}Scc}w)a  Compute ``f * a`` where ``f`` in ``GF(p)[x]`` and ``a`` in ``GF(p)``. Examples ======== >>> from sympy.polys.domains import ZZ >>> from sympy.polys.galoistools import gf_mul_ground >>> gf_mul_ground([3, 2, 4], 2, 5, ZZ) [1, 4, 3] r,)r3r-rrbs r gf_mul_groundr`s(  $%'q!A#'''sc>t||j||||S)a Compute ``f/a`` where ``f`` in ``GF(p)[x]`` and ``a`` in ``GF(p)``. Examples ======== >>> from sympy.polys.domains import ZZ >>> from sympy.polys.galoistools import gf_quo_ground >>> gf_quo_ground(ZZ.map([3, 2, 4]), ZZ(2), 5, ZZ) [4, 1, 2] )r`r rZs r gf_quo_groundrbs AHHQNAq 11r!c\|s|S|s|St|}t|}||k(r.tt||Dcgc] \}}||z|zc}}St||z }||kDr |d|||d}} n |d|||d}} | t||Dcgc] \}}||z|zc}}zScc}}wcc}}w)z Add polynomials in ``GF(p)[x]``. Examples ======== >>> from sympy.polys.domains import ZZ >>> from sympy.polys.galoistools import gf_add >>> gf_add([3, 2, 4], [2, 2, 2], 5, ZZ) [4, 1] N)r4r>rabs r3grrdfdgr-r_r<rLs rgf_addris   1B 1B Rx#a)=$!Q1q5A+=>> RL 7Ra5!AB%qARa5!AB%qASAY8TQa!eq[888>9s B" B(c|s|S|s t|||St|}t|}||k(r.tt||Dcgc] \}}||z |zc}}St ||z }||kDr |d|||d}} nt|d|||||d}} | t||Dcgc] \}}||z |zc}}zScc}}wcc}}w)z Subtract polynomials in ``GF(p)[x]``. Examples ======== >>> from sympy.polys.domains import ZZ >>> from sympy.polys.galoistools import gf_sub >>> gf_sub([3, 2, 4], [2, 2, 2], 5, ZZ) [1, 0, 2] N)rXr4r>rrdres rgf_subrk s  aA 1B 1B Rx#a)=$!Q1q5A+=>> RL 7Ra5!AB%qA!BQ%A&!"qASAY8TQa!eq[888>9s B8 B>c(t|}t|}||z}dg|dzz}td|dzD]R}|j} ttd||z t ||dzD]} | || ||| z zz } | |z||<Tt |S)z Multiply polynomials in ``GF(p)[x]``. Examples ======== >>> from sympy.polys.domains import ZZ >>> from sympy.polys.galoistools import gf_mul >>> gf_mul([3, 2, 4], [2, 2, 2], 5, ZZ) [1, 0, 3, 2, 3] rr0r4rIrrFminr>) r3rfrrrgrhdhrLir=js rgf_mulrr.s 1B 1B bB R!V A 1b1f s1a"f~s1bzA~6 #A QqT!AE(] "E #qy!  A;r!ctt|}d|z}dg|dzz}td|dzD]}|j}td||z }t ||} | |z dz} || dzzdz } t|| dzD]} ||| ||| z zz }||z }| dzr|| dz} || dzz }||z||<t |S)z Square polynomials in ``GF(p)[x]``. Examples ======== >>> from sympy.polys.domains import ZZ >>> from sympy.polys.galoistools import gf_sqr >>> gf_sqr([3, 2, 4], 5, ZZ) [4, 2, 3, 1, 1] r+rr0rm) r3rrrgrorLrpr=jminjmaxrKrqelems rgf_sqrrwMs 1B 2B R!V A 1b1f 1a"f~1bz 4K!Oa1f}q tTAX& #A QqT!AE(] "E #  q5TAX;D T1W Eqy!'* A;r!c 6t|t||||||S)a Returns ``f + g*h`` where ``f``, ``g``, ``h`` in ``GF(p)[x]``. Examples ======== >>> from sympy.polys.domains import ZZ >>> from sympy.polys.galoistools import gf_add_mul >>> gf_add_mul([3, 2, 4], [2, 2, 2], [1, 4], 5, ZZ) [2, 3, 2, 2] )rirrr3rfrLrrs r gf_add_mulrzxs  !VAq!Q'A ..r!c 6t|t||||||S)a Compute ``f - g*h`` where ``f``, ``g``, ``h`` in ``GF(p)[x]``. Examples ======== >>> from sympy.polys.domains import ZZ >>> from sympy.polys.galoistools import gf_sub_mul >>> gf_sub_mul([3, 2, 4], [2, 2, 2], [1, 4], 5, ZZ) [3, 3, 2, 1] )rkrrrys r gf_sub_mulr|s  !VAq!Q'A ..r!ct|tr|\}}n |j}|g}|D]!\}}t||||}t ||||}#|S)a Expand results of :func:`~.factor` in ``GF(p)[x]``. Examples ======== >>> from sympy.polys.domains import ZZ >>> from sympy.polys.galoistools import gf_expand >>> gf_expand([([3, 2, 4], 1), ([2, 2], 2), ([3, 1], 3)], 5, ZZ) [4, 3, 0, 3, 0, 1, 4, 1] )rHtuplergf_powrr)Frrlcrfr3r<s r gf_expandrsa!UA UU A1 1aA  1aA  Hr!ct|}t|}|s td||krg|fS|j|d|}t|||z |dz } }}t d|dzD]^} || } t t d|| z t || z | dzD]} | || | z|z ||| z zz} | |kr| |z} | |z|| <`|d|dzt||dzdfS)a  Division with remainder in ``GF(p)[x]``. Given univariate polynomials ``f`` and ``g`` with coefficients in a finite field with ``p`` elements, returns polynomials ``q`` and ``r`` (quotient and remainder) such that ``f = q*g + r``. Consider polynomials ``x**3 + x + 1`` and ``x**2 + x`` in GF(2):: >>> from sympy.polys.domains import ZZ >>> from sympy.polys.galoistools import gf_div, gf_add_mul >>> gf_div(ZZ.map([1, 0, 1, 1]), ZZ.map([1, 1, 0]), 2, ZZ) ([1, 1], [1]) As result we obtained quotient ``x + 1`` and remainder ``1``, thus:: >>> gf_add_mul(ZZ.map([1]), ZZ.map([1, 1]), ZZ.map([1, 1, 0]), 2, ZZ) [1, 0, 1, 1] References ========== .. [1] [Monagan93]_ .. [2] [Gathen99]_ polynomial divisionrr0N)r4ZeroDivisionErrorr rBrIrFrnr> r3rfrrrgrhinvrLdqdrrpr=rqs rgf_divrs8 1B 1B  566 b1u ((1Q4 CQb"q&2rA 1b1f  !s1b1f~s262':; /A Qq1urz]QrAvY. .E / 7 SLEqy!  Wb1f:x"q&' + ++r!c$t||||dS)z Compute polynomial remainder in ``GF(p)[x]``. Examples ======== >>> from sympy.polys.domains import ZZ >>> from sympy.polys.galoistools import gf_rem >>> gf_rem(ZZ.map([1, 0, 1, 1]), ZZ.map([1, 1, 0]), 2, ZZ) [1] r0)rr3rfrrs rgf_remrs !Q1 a  r!ct|}t|}|s td||krgS|j|d|}|dd||z |dz } }}td|dzD]W} || } tt d|| z t || z | dzD]} | || | z|z ||| z zz} | |z|z|| <Y|d|dzS)aG Compute exact quotient in ``GF(p)[x]``. Examples ======== >>> from sympy.polys.domains import ZZ >>> from sympy.polys.galoistools import gf_quo >>> gf_quo(ZZ.map([1, 0, 1, 1]), ZZ.map([1, 1, 0]), 2, ZZ) [1, 1] >>> gf_quo(ZZ.map([1, 0, 3, 2, 3]), ZZ.map([2, 2, 2]), 5, ZZ) [3, 2, 4] rrNr0)r4rr rIrFrnrs rgf_quors 1B 1B  566 b ((1Q4 C!b2grAv2rA 1b1f !!s1b1f~s262':; /A Qq1urz]QrAvY. .E / q ! ! Wb1f:r!cDt||||\}}|s|St||)a Compute polynomial quotient in ``GF(p)[x]``. Examples ======== >>> from sympy.polys.domains import ZZ >>> from sympy.polys.galoistools import gf_exquo >>> gf_exquo(ZZ.map([1, 0, 3, 2, 3]), ZZ.map([2, 2, 2]), 5, ZZ) [3, 2, 4] >>> gf_exquo(ZZ.map([1, 0, 1, 1]), ZZ.map([1, 1, 0]), 2, ZZ) Traceback (most recent call last): ... ExactQuotientFailed: [1, 1, 0] does not divide [1, 0, 1, 1] )rr )r3rfrrqrs rgf_exquor"s-& !Q1 DAq !!Q''r!c0|s|S||jg|zzS)z Efficiently multiply ``f`` by ``x**n``. Examples ======== >>> from sympy.polys.domains import ZZ >>> from sympy.polys.galoistools import gf_lshift >>> gf_lshift([3, 2, 4], 4, ZZ) [3, 2, 4, 0, 0, 0, 0] r6r3rKrs r gf_lshiftr=s  AFF8A:~r!c&|s|gfS|d| || dfS)z Efficiently divide ``f`` by ``x**n``. Examples ======== >>> from sympy.polys.domains import ZZ >>> from sympy.polys.galoistools import gf_rshift >>> gf_rshift([1, 2, 3, 4, 0], 3, ZZ) ([1, 2], [3, 4, 0]) Nr,rs r gf_rshiftrQs* "u 1"vq!v~r!c|s |jgS|dk(r|S|dk(r t|||S|jg} |dzrt||||}|dz}|dz}|s |St|||}0)z Compute ``f**n`` in ``GF(p)[x]`` using repeated squaring. Examples ======== >>> from sympy.polys.domains import ZZ >>> from sympy.polys.galoistools import gf_pow >>> gf_pow([3, 2, 4], 3, 5, ZZ) [2, 4, 4, 2, 2, 1, 4] r0r+)rrwrr)r3rKrrrLs rrres w a aaA A  q5q!Q"A FA a  H 1aO r!ct|}|dk(rgSdg|z}dg|d<||kr7td|D]&}t||dz ||}t||||||<(|S|dkDrgt |j |j g|||||d<td|D]0}t||dz |d||||<t|||||||<2|S)ah return the list of ``x**(i*p) mod g in Z_p`` for ``i = 0, .., n - 1`` where ``n = gf_degree(g)`` Examples ======== >>> from sympy.polys.domains import ZZ >>> from sympy.polys.galoistools import gf_frobenius_monomial_base >>> g = ZZ.map([1, 0, 2, 1]) >>> gf_frobenius_monomial_base(g, 5, ZZ) [[1], [4, 4, 2], [1, 2]] rr0r+)r4rIrr gf_pow_modrrrr)rfrrrKr_rpmons rgf_frobenius_monomial_basers ! AAv AA 3AaD1uq! (AAa!eHa+C#q!Q'AaD ( H Q155!&&/1aA6!q! )A!AE(AaD!Q/AaD!A$1a(AaD ) Hr!ct|}t||k\rt||||}|sgSt|}|dg}td|dzD]'}t|||||z ||} t || ||})|S)aS compute gf_pow_mod(f, p, g, p, K) using the Frobenius map Parameters ========== f, g : polynomials in ``GF(p)[x]`` b : frobenius monomial base p : prime number K : domain Examples ======== >>> from sympy.polys.domains import ZZ >>> from sympy.polys.galoistools import gf_frobenius_monomial_base, gf_frobenius_map >>> f = ZZ.map([2, 1, 0, 1]) >>> g = ZZ.map([1, 0, 2, 1]) >>> p = 5 >>> b = gf_frobenius_monomial_base(g, p, ZZ) >>> r = gf_frobenius_map(f, g, b, p, ZZ) >>> gf_frobenius_map(f, g, b, p, ZZ) [4, 0, 3] r#r0)r4rrIr`ri) r3rfr_rrrrKsfrprs rgf_frobenius_maprs2 ! A|q 1aA   ! A B%B 1a!e_! !A$!a%!Q / B1a ! Ir!ct||||}|}|}td|D]-}t|||||}t||||}t||||}/t ||dz dz|||} | S)z utility function for ``gf_edf_zassenhaus`` Compute ``f**((p**n - 1) // 2)`` in ``GF(p)[x]/(g)`` ``f**((p**n - 1) // 2) = (f*f**p*...*f**(p**n - 1))**((p - 1) // 2)`` r0r+)rrIrrrr) r3rKrfr_rrrLrrpress r_gf_pow_pnm1d2rs q!QA A A 1a[ Q1a + 1aA  1aA  QQ Aq! ,C Jr!c6|s |jgS|dk(rt||||S|dk(rtt||||||S|jg} |dzr!t||||}t||||}|dz}|dz}|s |St|||}t||||}L)a* Compute ``f**n`` in ``GF(p)[x]/(g)`` using repeated squaring. Given polynomials ``f`` and ``g`` in ``GF(p)[x]`` and a non-negative integer ``n``, efficiently computes ``f**n (mod g)`` i.e. the remainder of ``f**n`` from division by ``g``, using the repeated squaring algorithm. Examples ======== >>> from sympy.polys.domains import ZZ >>> from sympy.polys.galoistools import gf_pow_mod >>> gf_pow_mod(ZZ.map([3, 2, 4]), 3, ZZ.map([1, 1]), 5, ZZ) [] References ========== .. [1] [Gathen99]_ r0r+)rrrwrr)r3rKrfrrrLs rrrs. w aaAq!! afQ1oq!Q// A  q5q!Q"Aq!Q"A FA a  H 1aO 1aA  r!cL|r|t||||}}|rt|||dS)z Euclidean Algorithm in ``GF(p)[x]``. Examples ======== >>> from sympy.polys.domains import ZZ >>> from sympy.polys.galoistools import gf_gcd >>> gf_gcd(ZZ.map([3, 2, 4]), ZZ.map([2, 2, 3]), 5, ZZ) [1, 3] r0)rgf_monicrs rgf_gcdrs6 &Aq!$1  Aq! Q r!c z|r|sgStt||||t||||||}t|||dS)z Compute polynomial LCM in ``GF(p)[x]``. Examples ======== >>> from sympy.polys.domains import ZZ >>> from sympy.polys.galoistools import gf_lcm >>> gf_lcm(ZZ.map([3, 2, 4]), ZZ.map([2, 2, 3]), 5, ZZ) [1, 2, 0, 4] r0)rrrrrr3rfrrrLs rgf_lcmr%sM A vaAq!aAq!1a )A Aq! Q r!cj|s|sgggfSt||||}|t||||t||||fS)a  Compute polynomial GCD and cofactors in ``GF(p)[x]``. Examples ======== >>> from sympy.polys.domains import ZZ >>> from sympy.polys.galoistools import gf_cofactors >>> gf_cofactors(ZZ.map([3, 2, 4]), ZZ.map([2, 2, 3]), 5, ZZ) ([1, 3], [3, 3], [2, 1]) )rrrs r gf_cofactorsr<sM QB|q!QA vaAq! 1aA   r!c|s|s|jgggfSt|||\}}t|||\}}|sg|j||g|fS|s|j||gg|fS|j||gg} }g|j||g} } t||||\} } | sndt| |||c\}}}|j||}t || | ||}t | | | ||}t ||||| }} t ||||| } } x| | |fS)a Extended Euclidean Algorithm in ``GF(p)[x]``. Given polynomials ``f`` and ``g`` in ``GF(p)[x]``, computes polynomials ``s``, ``t`` and ``h``, such that ``h = gcd(f, g)`` and ``s*f + t*g = h``. The typical application of EEA is solving polynomial diophantine equations. Consider polynomials ``f = (x + 7) (x + 1)``, ``g = (x + 7) (x**2 + 1)`` in ``GF(11)[x]``. Application of Extended Euclidean Algorithm gives:: >>> from sympy.polys.domains import ZZ >>> from sympy.polys.galoistools import gf_gcdex, gf_mul, gf_add >>> s, t, g = gf_gcdex(ZZ.map([1, 8, 7]), ZZ.map([1, 7, 1, 7]), 11, ZZ) >>> s, t, g ([5, 6], [6], [1, 7]) As result we obtained polynomials ``s = 5*x + 6`` and ``t = 6``, and additionally ``gcd(f, g) = x + 7``. This is correct because:: >>> S = gf_mul(s, ZZ.map([1, 8, 7]), 11, ZZ) >>> T = gf_mul(t, ZZ.map([1, 7, 1, 7]), 11, ZZ) >>> gf_add(S, T, 11, ZZ) == [1, 7] True References ========== .. [1] [Gathen99]_ )rrr rr|r`)r3rfrrp0r0p1r1s0s1t0t1QRrrrts rgf_gcdexrSsIB wB aA FB aA FB AHHRO$b(( Q "b((hhr1o B !((2q/"B b"a#1 1a(" R"hhr1o r2q!Q ' r2q!Q 'q#q!,bBq#q!,bB  r2:r!c|s|jgfS|d}|j|r |t|fS|t||||fS)z Compute LC and a monic polynomial in ``GF(p)[x]``. Examples ======== >>> from sympy.polys.domains import ZZ >>> from sympy.polys.galoistools import gf_monic >>> gf_monic(ZZ.map([3, 2, 4]), 5, ZZ) (3, [1, 4, 3]) r)ris_onerBrb)r3rrrs rrrsM vvrz qT 88B<tAw; }QAq11 1r!ct|}|jg|z|}}|ddD]!}|||z}||z}|r||||z <|dz}#t|S)z Differentiate polynomial in ``GF(p)[x]``. Examples ======== >>> from sympy.polys.domains import ZZ >>> from sympy.polys.galoistools import gf_diff >>> gf_diff([3, 2, 4], 5, ZZ) [1, 2] Nr#r0)r4rr>)r3rrrgrLrKr=s rgf_diffrsp 1B FF8B;qA3B 1    Ab1fI Q A;r!cJ|j}|D]}||z}||z }||z}|S)z Evaluate ``f(a)`` in ``GF(p)`` using Horner scheme. Examples ======== >>> from sympy.polys.domains import ZZ >>> from sympy.polys.galoistools import gf_eval >>> gf_eval([3, 2, 4], 2, 5, ZZ) 0 r6)r3r-rrrPrUs rgf_evalrs>VVF ! ! !  Mr!c D|Dcgc]}t||||c}Scc}w)a  Evaluate ``f(a)`` for ``a`` in ``[a_1, ..., a_n]``. Examples ======== >>> from sympy.polys.domains import ZZ >>> from sympy.polys.galoistools import gf_multi_eval >>> gf_multi_eval([3, 2, 4], [0, 1, 2, 3, 4], 5, ZZ) [4, 4, 0, 2, 0] )r)r3Arrr-s r gf_multi_evalrs#+, -QWQ1a -- -sc t|dkr"tt|t||||gS|sgS|dg}|ddD]}t ||||}t ||||} |S)a Compute polynomial composition ``f(g)`` in ``GF(p)[x]``. Examples ======== >>> from sympy.polys.domains import ZZ >>> from sympy.polys.galoistools import gf_compose >>> gf_compose([3, 2, 4], [2, 2, 2], 5, ZZ) [2, 4, 0, 3, 0] r0rN)r2r>rr8rrr[)r3rfrrrLrUs r gf_composers} 1v{E!QKA6788  1A qrU& 1aA  !Q1 %& Hr!c|sgS|dg}|ddD],}t||||}t||||}t||||}.|S)a& Compute polynomial composition ``g(h)`` in ``GF(p)[x]/(f)``. Examples ======== >>> from sympy.polys.domains import ZZ >>> from sympy.polys.galoistools import gf_compose_mod >>> gf_compose_mod(ZZ.map([3, 2, 4]), ZZ.map([2, 2, 2]), ZZ.map([4, 3]), 5, ZZ) [4] rr0N)rrr[r)rfrLr3rrcompr-s rgf_compose_modrsc  aD6D qrU%dAq!$T1a+dAq!$% Kr!c Jt|||||}|}|dzrt||||} |} n|} |} |dz}|rat|t|||||||}t|||||}|dzr*t| t|| |||||} t|| |||} |dz}|rat|| |||| fS)a Compute polynomial trace map in ``GF(p)[x]/(f)``. Given a polynomial ``f`` in ``GF(p)[x]``, polynomials ``a``, ``b``, ``c`` in the quotient ring ``GF(p)[x]/(f)`` such that ``b = c**t (mod f)`` for some positive power ``t`` of ``p``, and a positive integer ``n``, returns a mapping:: a -> a**t**n, a + a**t + a**t**2 + ... + a**t**n (mod f) In factorization context, ``b = x**p mod f`` and ``c = x mod f``. This way we can efficiently compute trace polynomials in equal degree factorization routine, much faster than with other methods, like iterated Frobenius algorithm, for large degrees. Examples ======== >>> from sympy.polys.domains import ZZ >>> from sympy.polys.galoistools import gf_trace_map >>> gf_trace_map([1, 2], [4, 4], [1, 1], 4, [3, 2, 4], 5, ZZ) ([1, 3], [1, 3]) References ========== .. [1] [Gathen92]_ r0)rri) r-r_rUrKr3rrrrrVs r gf_trace_mapr-s> q!Q1%A A1u 1aA    !GA 1nQ1a3Q : 1aAq ) q5q.Aq!Q7A>Aq!Q1-A a  !Q1a (! ++r!ct||||}|}|}td|D]-}t|||||}t||||}t||||}/|S)z& utility for ``gf_edf_shoup`` r0)rrIrri) r3rKrfr_rrrLrrps r _gf_trace_maprdsl q!QA A A 1a[ Q1a + 1aA  1aA  Hr!c t|}|jgtd|Dcgc]}|ttd|c}zScc}w)a Generate a random polynomial in ``GF(p)[x]`` of degree ``n``. Examples ======== >>> from sympy.polys.domains import ZZ >>> from sympy.polys.galoistools import gf_random >>> gf_random(10, 5, ZZ) #doctest: +SKIP [1, 2, 3, 2, 1, 1, 1, 2, 0, 4, 2] r)intrrIr)rKrrpirps r gf_randomrrsB QB EE7uQ{D!qWQ^,-D DDDs"A c> t|||}t|||r|S)a, Generate random irreducible polynomial of degree ``n`` in ``GF(p)[x]``. Examples ======== >>> from sympy.polys.domains import ZZ >>> from sympy.polys.galoistools import gf_irreducible >>> gf_irreducible(10, 5, ZZ) #doctest: +SKIP [1, 4, 2, 2, 3, 2, 4, 1, 4, 0, 4] )rgf_irreducible_p)rKrrr3s rgf_irreduciblers+  aA  Aq! $H r!ct|}|dkryt|||\}}|dkrt|j|jg||||x}}t d|dzD]S}t ||j|jg||}t|||||jgk(rt|||||}Syyt|||} t|j|jg|| ||x}}t d|dzD]S}t ||j|jg||}t|||||jgk(rt||| ||}Syy)a_ Ben-Or's polynomial irreducibility test over finite fields. Examples ======== >>> from sympy.polys.domains import ZZ >>> from sympy.polys.galoistools import gf_irred_p_ben_or >>> gf_irred_p_ben_or(ZZ.map([1, 4, 2, 2, 3, 2, 4, 1, 4, 0, 4]), 5, ZZ) True >>> gf_irred_p_ben_or(ZZ.map([3, 2, 4]), 5, ZZ) False r0Trr+F) r4rrrrrIrkrrrr) r3rrrKrHrLrprfr_s rgf_irred_p_ben_orrsV ! AAv Aq! DAq1uAEE166?Aq!Q77Aq!Q$ Aq155!&&/1a0AaAq!aeeW,"1aAq1  "  'q!Q / !%%!Q1==Aq!Q$ Aq155!&&/1a0AaAq!aeeW,$Q1a3   r!ct|}|dkryt|||\}}|j|jg}ddlm}||Dchc]}||z }}t |||} | d} td|D]A} | |vr,t| |||} t|| |||jgk7ryt| || ||} C| |k(Scc}w)a[ Rabin's polynomial irreducibility test over finite fields. Examples ======== >>> from sympy.polys.domains import ZZ >>> from sympy.polys.galoistools import gf_irred_p_rabin >>> gf_irred_p_rabin(ZZ.map([1, 4, 2, 2, 3, 2, 4, 1, 4, 0, 4]), 5, ZZ) True >>> gf_irred_p_rabin(ZZ.map([3, 2, 4]), 5, ZZ) False r0Tr factorintF) r4rrr sympy.ntheoryrrrIrkrr) r3rrrKrxrdindicesr_rLrprfs rgf_irred_p_rabinrs ! AAv Aq! DAq A''l,1,G,"1a+A !A 1a[, <q!Q"AaAq!aeeW, Q1a +, 6M-s B?)zben-orrabinc^td}|t||||}|St|||}|S)a[ Test irreducibility of a polynomial ``f`` in ``GF(p)[x]``. Examples ======== >>> from sympy.polys.domains import ZZ >>> from sympy.polys.galoistools import gf_irreducible_p >>> gf_irreducible_p(ZZ.map([1, 4, 2, 2, 3, 2, 4, 1, 4, 0, 4]), 5, ZZ) True >>> gf_irreducible_p(ZZ.map([3, 2, 4]), 5, ZZ) False GF_IRRED_METHOD)r _irred_methodsr)r3rrmethodirreds rrrsD $ %F v&q!Q/ L!Aq) Lr!cvt|||\}}|syt|t||||||jgk(S)a5 Return ``True`` if ``f`` is square-free in ``GF(p)[x]``. Examples ======== >>> from sympy.polys.domains import ZZ >>> from sympy.polys.galoistools import gf_sqf_p >>> gf_sqf_p(ZZ.map([3, 2, 4]), 5, ZZ) True >>> gf_sqf_p(ZZ.map([2, 4, 4, 2, 2, 1, 4]), 5, ZZ) False T)rrrr)r3rrrs rgf_sqf_prsA Aq! DAq aAq)1a0QUUG;;r!cpt|||\}}|jg}|D]\}}t||||}|S)a Return square-free part of a ``GF(p)[x]`` polynomial. Examples ======== >>> from sympy.polys.domains import ZZ >>> from sympy.polys.galoistools import gf_sqf_part >>> gf_sqf_part(ZZ.map([1, 1, 3, 0, 1, 0, 2, 2, 1]), 5, ZZ) [1, 4, 3] ) gf_sqf_listrrr)r3rrrsqfrfs r gf_sqf_partr&sKAq !FAs A1 1aA  Hr!cddgt|f\}}}}t|||\}}t|dkr|gfS t|||} | gk7rt || ||} t || ||} d} | |j gk7rft | | ||} t | | ||}t|dkDr|j|| |zft | | ||| | dz} } } | |j gk7rf| |j gk(rd}n| }|s;t||z}td|dzD] } || |z|| <|d|dz||z}}nn|r td||fS)a Return the square-free decomposition of a ``GF(p)[x]`` polynomial. Given a polynomial ``f`` in ``GF(p)[x]``, returns the leading coefficient of ``f`` and a square-free decomposition ``f_1**e_1 f_2**e_2 ... f_k**e_k`` such that all ``f_i`` are monic polynomials and ``(f_i, f_j)`` for ``i != j`` are co-prime and ``e_1 ... e_k`` are given in increasing order. All trivial terms (i.e. ``f_i = 1``) are not included in the output. Consider polynomial ``f = x**11 + 1`` over ``GF(11)[x]``:: >>> from sympy.polys.domains import ZZ >>> from sympy.polys.galoistools import ( ... gf_from_dict, gf_diff, gf_sqf_list, gf_pow, ... ) ... # doctest: +NORMALIZE_WHITESPACE >>> f = gf_from_dict({11: ZZ(1), 0: ZZ(1)}, 11, ZZ) Note that ``f'(x) = 0``:: >>> gf_diff(f, 11, ZZ) [] This phenomenon does not happen in characteristic zero. However we can still compute square-free decomposition of ``f`` using ``gf_sqf()``:: >>> gf_sqf_list(f, 11, ZZ) (1, [([1, 1], 11)]) We obtained factorization ``f = (x + 1)**11``. This is correct because:: >>> gf_pow([1, 1], 11, 11, ZZ) == f True References ========== .. [1] [Geddes92]_ r0FTrNz'all=True' is not supported yet) rrr4rrrrr$rI ValueError)r3rrallrKrfactorsrrrrfrLrpGrrs rrr>sVE2s1v-AsGQ Q1 EB|a2v  Aq!  7q!Q"Aq!Q"AAw,1aA&1aA&Q>> from sympy.polys.domains import ZZ >>> from sympy.polys.galoistools import gf_Qmatrix >>> gf_Qmatrix([3, 2, 4], 5, ZZ) [[1, 0], [3, 4]] >>> gf_Qmatrix([1, 0, 0, 0, 1], 5, ZZ) [[1, 0, 0, 0], [0, 4, 0, 0], [0, 0, 1, 0], [0, 0, 0, 4]] r0r#)r4rrrrBrIr$) r3rrrKrrrrpqqrUrqs r gf_Qmatrixrs* Q<QqA 166(AE""A a RD!a%L A 1q1uai!m $ R5&2,!#$aeAq! 4A IIqQx!Aqb1fI+-2 3 4A2hAadG   Hr!c~|Dcgc] }t|c}t|}}td|D] }||||jz |z|||<"td|D]}t||D] }|||s n|j ||||}td|D]}||||z|z|||<td|D] }|||} ||||||<| |||<"td|D]>}||k7s |||}td|D]}|||||||zz |z|||<!@td|D]I}td|D]8}||k(r|j|||z |z|||<'||| |z|||<:Kg} |D]}t |s| j |!| Scc}w)a_ Compute a basis of the kernel of ``Q``. Examples ======== >>> from sympy.polys.domains import ZZ >>> from sympy.polys.galoistools import gf_Qmatrix, gf_Qbasis >>> gf_Qbasis(gf_Qmatrix([1, 0, 0, 0, 1], 5, ZZ), 5, ZZ) [[1, 0, 0, 0], [0, 0, 1, 0]] >>> gf_Qbasis(gf_Qmatrix([3, 2, 4], 5, ZZ), 5, ZZ) [[1, 0]] r)rBr2rIrr anyr$) rrrrrKr<rprrqrbasiss r gf_Qbasisrs7" !T!W !3q6qA 1a[(Q47QUU?a'!Q(1a[8q! AtAw  hhqtAw"q! (AtAws{a'AaDG (q! A!QAd1gAaDGAaDG  q! 8AAvaDGq!8A tAw1a2a7AaDG8  8#801a[)q! )AAv551Q47?a/!QaDG8q.!Q  )) E  q6 LLO LU "sF:czt|||}t|||}t|D]%\}}tt t |||<'|g}t dt|D]}t |D]}|j} | |kst||| ||} t|| ||} | |jgk7r7| |k7r2|j|t|| ||}|j|| gt|t|k(rt|dccS| |jz } | |krt|dS)a Factor a square-free ``f`` in ``GF(p)[x]`` for small ``p``. Examples ======== >>> from sympy.polys.domains import ZZ >>> from sympy.polys.galoistools import gf_berlekamp >>> gf_berlekamp([1, 0, 0, 0, 1], 5, ZZ) [[1, 0, 2], [1, 0, 3]] r0Fmultiple)rr enumerater>rBreversedrIr2rr]rrremoverextendr ) r3rrrrrprrr<rrfrLs r gf_berlekamprs9 1aA!QA! +1Xa[)*!+cG 1c!f g AAa%!!A$1a01aA& 0`` and ``e_i > 0`` is an argument to the equal degree factorization routine. Consider the polynomial ``x**15 - 1`` in ``GF(11)[x]``:: >>> from sympy.polys.domains import ZZ >>> from sympy.polys.galoistools import gf_from_dict >>> f = gf_from_dict({15: ZZ(1), 0: ZZ(-1)}, 11, ZZ) Distinct degree factorization gives:: >>> from sympy.polys.galoistools import gf_ddf_zassenhaus >>> gf_ddf_zassenhaus(f, 11, ZZ) [([1, 0, 0, 0, 0, 10], 1), ([1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1], 2)] which means ``x**15 - 1 = (x**5 - 1) (x**10 + x**5 + 1)``. To obtain factorization into irreducibles, use equal degree factorization procedure (EDF) with each of the factors. References ========== .. [1] [Gathen99]_ .. [2] [Geddes92]_ r0r+) rrrr4rrrkr$rr)r3rrrprfrr_rLs rgf_ddf_zassenhausr)sFqvv'qA"1a+A A#1  Q1a + 1fQA61 = < NNAq6 "q!Q"Aq!Q"A*1a3A Q A#1  QUUG|1il+,,,r!c |g}t||kr|St||z}|dk7r t|||}|j|jg}t ||kr|dk(r^|x}} t |dz D]} t | d|||} t|| ||}!t||||} ||j|jgz }nGtd|zdz ||} t| ||||}t|t||j||||} | |jgk7r.| |k7r)t| |||tt|| |||||z}t ||krt|dS)a Cantor-Zassenhaus: Probabilistic Equal Degree Factorization Given a monic square-free polynomial ``f`` in ``GF(p)[x]`` and an integer ``n``, such that ``n`` divides ``deg(f)``, returns all irreducible factors ``f_1,...,f_d`` of ``f``, each of degree ``n``. EDF procedure gives complete factorization over Galois fields. Consider the square-free polynomial ``f = x**3 + x**2 + x + 1`` in ``GF(5)[x]``. Let's compute its irreducible factors of degree one:: >>> from sympy.polys.domains import ZZ >>> from sympy.polys.galoistools import gf_edf_zassenhaus >>> gf_edf_zassenhaus([1,1,1,1], 1, 5, ZZ) [[1, 1], [1, 2], [1, 3]] Notes ===== The case p == 2 is handled by Cohen's Algorithm 3.4.8. The case p odd is as in Geddes Algorithm 8.9 (or Cohen's Algorithm 3.4.6). References ========== .. [1] [Gathen99]_ .. [2] [Geddes92]_ Algorithm 8.9 .. [3] [Cohen93]_ Algorithm 3.4.8 r+r0Fr)r4rrrr2rIrrirrrr]gf_edf_zassenhausrr ) r3rKrrrNr_rrLrrprfs rrrbsw@cG|q! AAv &q!Q / A g,  6IA1q5\ 'q!Q1-1aA& 'q!Q"A !&&!&&! !A!a%!)Q*Aq!Q1a0Aq-155!Q7A>A  0`` and ``e_i > 0`` is an argument to the equal degree factorization routine. This algorithm is an improved version of Zassenhaus algorithm for large ``deg(f)`` and modulus ``p`` (especially for ``deg(f) ~ lg(p)``). Examples ======== >>> from sympy.polys.domains import ZZ >>> from sympy.polys.galoistools import gf_ddf_shoup, gf_from_dict >>> f = gf_from_dict({6: ZZ(1), 5: ZZ(-1), 4: ZZ(1), 3: ZZ(1), 1: ZZ(-1)}, 3, ZZ) >>> gf_ddf_shoup(f, 3, ZZ) [([1, 1, 0], 1), ([1, 1, 0, 1, 2], 2)] References ========== .. [1] [Kaltofen98]_ .. [2] [Shoup95]_ .. [3] [Gathen92]_ r+r0N)r4r_ceil_sqrtrrrrrIrrrkrrrrrrr$)r3rrrKr<r_rLrrprrrrqrrfrs r gf_ddf_shouprsE@ ! A E%1+ A"1a+A!%%!Q15A %%!xQ//A 1a!e_4!A#1a3!4 Q42AqA qvvhAA 1a[4aAh1a3!4G! -1wA1 #Aq!Q"Aq!Q"Aq!Q"A # 1aA  1aA ! -Aq!Q"Aq!Q"AQUUG|1a!e9q=12!Q1%q1uqA --( QUUG|9Q<() Nr!c t|t|}}|sgS||kr|gS|g|j|jg}}t |dz ||}|dk(r`t |||||} t || ||dz |||d} t|| ||} t|| ||} t| |||t| |||z}nt|||} t|||| ||} t | |dz dz|||} t|| ||} t|t| |j||||} t|t| | ||||}t| |||t| |||zt||||z}t|dS)a Gathen-Shoup: Probabilistic Equal Degree Factorization Given a monic square-free polynomial ``f`` in ``GF(p)[x]`` and integer ``n`` such that ``n`` divides ``deg(f)``, returns all irreducible factors ``f_1,...,f_d`` of ``f``, each of degree ``n``. This is a complete factorization over Galois fields. This algorithm is an improved version of Zassenhaus algorithm for large ``deg(f)`` and modulus ``p`` (especially for ``deg(f) ~ lg(p)``). Examples ======== >>> from sympy.polys.domains import ZZ >>> from sympy.polys.galoistools import gf_edf_shoup >>> gf_edf_shoup(ZZ.map([1, 2837, 2277]), 1, 2917, ZZ) [[1, 852], [1, 1985]] References ========== .. [1] [Shoup91]_ .. [2] [Gathen92]_ r0r+Fr)r4rrrrrrrr gf_edf_shouprrr]rrr )r3rKrrrrrrrrLrh1h2r_h3s rr r s8 Q<QqA  Avs quuaffoQG!a%AAAv q!Q1 % Aq!a%Aq 1! 4 Aq!Q  Ar1a r1a+2q!Q'( 'q!Q / !Q1a + q1q51*aA . Aq!Q  A}Qq!4a ; Avb"a+Q 2r1a+2q!Q'(2q!Q'( 5 11r!clg}t|||D]\}}|t||||z }t|dS)a Factor a square-free ``f`` in ``GF(p)[x]`` for medium ``p``. Examples ======== >>> from sympy.polys.domains import ZZ >>> from sympy.polys.galoistools import gf_zassenhaus >>> gf_zassenhaus(ZZ.map([1, 4, 3]), 5, ZZ) [[1, 1], [1, 3]] Fr)rrr r3rrrfactorrKs r gf_zassenhausr-sJG&q!Q/6 $VQ1556 5 11r!clg}t|||D]\}}|t||||z }t|dS)a Factor a square-free ``f`` in ``GF(p)[x]`` for large ``p``. Examples ======== >>> from sympy.polys.domains import ZZ >>> from sympy.polys.galoistools import gf_shoup >>> gf_shoup(ZZ.map([1, 4, 3]), 5, ZZ) [[1, 1], [1, 3]] Fr)rr r rs rgf_shouprCsIG!!Q*1 <1a001 5 11r!) berlekamp zassenhausshoupct|||\}}t|dkr|gfS|xs td}|t||||}||fSt |||}||fS)a  Factor a square-free polynomial ``f`` in ``GF(p)[x]``. Examples ======== >>> from sympy.polys.domains import ZZ >>> from sympy.polys.galoistools import gf_factor_sqf >>> gf_factor_sqf(ZZ.map([3, 2, 4]), 5, ZZ) (3, [[1, 1], [1, 3]]) r0GF_FACTOR_METHOD)rr4r _factor_methodsr)r3rrrrrs r gf_factor_sqfr_sz Q1 EB|a2v  0u/0F !&)!Q2 w; 1a( w;r!ct|||\}}t|dkr|gfSg}t|||dD]-\}}t|||dD]}|j ||f/|t |fS)a Factor (non square-free) polynomials in ``GF(p)[x]``. Given a possibly non square-free polynomial ``f`` in ``GF(p)[x]``, returns its complete factorization into irreducibles:: f_1(x)**e_1 f_2(x)**e_2 ... f_d(x)**e_d where each ``f_i`` is a monic polynomial and ``gcd(f_i, f_j) == 1``, for ``i != j``. The result is given as a tuple consisting of the leading coefficient of ``f`` and a list of factors of ``f`` with their multiplicities. The algorithm proceeds by first computing square-free decomposition of ``f`` and then iteratively factoring each of square-free factors. Consider a non square-free polynomial ``f = (7*x + 1) (x + 2)**2`` in ``GF(11)[x]``. We obtain its factorization into irreducibles as follows:: >>> from sympy.polys.domains import ZZ >>> from sympy.polys.galoistools import gf_factor >>> gf_factor(ZZ.map([5, 2, 7, 2]), 11, ZZ) (5, [([1, 2], 1), ([1, 8], 2)]) We arrived with factorization ``f = 5 (x + 2) (x + 8)**2``. We did not recover the exact form of the input polynomial because we requested to get monic factors of ``f`` and its leading coefficient separately. Square-free factors of ``f`` can be factored into irreducibles over ``GF(p)`` using three very different methods: Berlekamp efficient for very small values of ``p`` (usually ``p < 25``) Cantor-Zassenhaus efficient on average input and with "typical" ``p`` Shoup-Kaltofen-Gathen efficient with very large inputs and modulus If you want to use a specific factorization method, instead of the default one, set ``GF_FACTOR_METHOD`` with one of ``berlekamp``, ``zassenhaus`` or ``shoup`` values. References ========== .. [1] [Gathen99]_ r0)rr4rrr$r )r3rrrrrfrKrLs r gf_factorr|sd Q1 EB|a2v GAq!$Q'#1q!Q'* #A NNAq6 " ## }W% %%r!c,d}|D] }||z}||z }|S)z Value of polynomial 'f' at 'a' in field R. Examples ======== >>> from sympy.polys.galoistools import gf_value >>> gf_value([1, 7, 2, 4], 11) 2204 rr,)r3r-rPrUs rgf_valuers1F ! !  Mr!cddlm}||zdk(r||zdk(rtt|SgS|||\}}}||zdk7rgSt|Dcgc]}||z|z||z|zz|zc}Scc}w)a Returns the values of x satisfying a*x congruent b mod(m) Here m is positive integer and a, b are natural numbers. This function returns only those values of x which are distinct mod(m). Examples ======== >>> from sympy.polys.galoistools import linear_congruence >>> linear_congruence(3, 12, 15) [4, 9, 14] There are 3 solutions distinct mod(15) since gcd(a, m) = gcd(3, 15) = 3. References ========== .. [1] https://en.wikipedia.org/wiki/Linear_congruence_theorem r)r)sympy.polys.polytoolsrrBrI)r-r_rrrrrfrs rlinear_congruencer!s.,1uz q5A:a> !IAqkGAq!1uz 388 >> from sympy.polys.galoistools import _raise_mod_power >>> from sympy.polys.galoistools import csolve_prime These is the solutions of f(x) = x**2 + x + 7 cong 0 mod(3) >>> f = [1, 1, 7] >>> csolve_prime(f, 3) [1] >>> [ i for i in range(3) if not (i**2 + i + 7) % 3] [1] The solutions of f(x) cong 0 mod(9) are constructed from the values returned from _raise_mod_power: >>> x, s, p = 1, 1, 3 >>> V = _raise_mod_power(x, s, p, f) >>> [x + v * p**s for v in V] [1, 4, 7] And these are confirmed with the following: >>> [ i for i in range(3**2) if not (i**2 + i + 7) % 3**2] [1, 4, 7] rZZ)sympy.polys.domainsr$rrr!)rrrr3r$f_falphabetas r_raise_mod_powerr)sHB' !Q C S! E a^ q!t #D UD! ,,r!cn ddlm}ddlm}t |}t }t ddgdz ||}t|d|}t|||g}|rT|j}t|dkr"t|dk(r)|jt|d |dzzYt|dk(rYt|d} |d| zz  dzzzdz |j fd| dz|d| zz d D |ddz } t d| gdz dz||}t|d|}t|||}dt|cxkrt|kr5nn2|j||jt|||dn|rTt!|S) a* Solutions of `f(x) \equiv 0 \pmod{p}`, `f(0) \not\equiv 0 \pmod{p}`. Explanation =========== This algorithm is classified as the Las Vegas method. That is, it always returns the correct answer and solves the problem fast in many cases, but if it is unlucky, it does not answer forever. Suppose the polynomial f is not a zero polynomial. Assume further that it is of degree at most p-1 and `f(0)\not\equiv 0 \pmod{p}`. These assumptions are not an essential part of the algorithm, only that it is more convenient for the function calling this function to resolve them. Note that `x^{p-1} - 1 \equiv \prod_{a=1}^{p-1}(x - a) \pmod{p}`. Thus, the greatest common divisor with f is `\prod_{s \in S}(x - s)`, with S being the set of solutions to f. Furthermore, when a is randomly determined, `(x+a)^{(p-1)/2}-1` is a polynomial with (p-1)/2 randomly chosen solutions. The greatest common divisor of f may be a nontrivial factor of f. When p is large and the degree of f is small, it is faster than naive solution methods. Parameters ========== f : polynomial p : prime number Returns ======= list[int] a list of solutions, sorted in ascending order by integers in the range [1, p). The same value does not exist in the list even if there is a multiple solution. If no solution exists, returns []. Examples ======== >>> from sympy.polys.galoistools import _csolve_prime_las_vegas >>> _csolve_prime_las_vegas([1, 4, 3], 7) # x^2 + 4x + 3 = 0 (mod 7) [4, 6] >>> _csolve_prime_las_vegas([5, 7, 1, 9], 11) # 5x^3 + 7x^2 + x + 9 = 0 (mod 11) [1, 5, 8] References ========== .. [1] R. Crandall and C. Pomerance "Prime Numbers", 2nd Ed., Algorithm 2.3.10 rr#)sqrt_modr0r+c3.K|] }|z zywNr,).0rr_rs r z*_csolve_prime_las_vegas..g sHQ! HsT) all_roots)r%r$rr+rsetrr]rpopr2addr updater$rsorted) r3rseedr$r+randintrootrfrrr-r_s ` @r_csolve_prime_las_vegasr: sp'&tnG 5DAq61q5!Q+AaAr"AaAr"#G  KKM q6Q;  q6Q; HHfQqT1o%!,q0 1  q6Q;1q/C!s QAQ!a%[Q&A KKH A!s !2AFH H 1q5!AAq6AEa<Ar:AaAr*Aq!Q#A3q6"CF"q!vaAr2156 4 $<r!c ddlm}|Dcgc]}tt|}}t t ||z D]}|||zdz xx||z cc<d||<t ||}d}|t |krB|t ||z dz dk(r+|dz }|t |kr|t ||z dz dk(r+|r |d| }dg}ng}|gk(rtt |} nOt |dz|kr|t||z} n.|t |Dcgc]}t||||dk(s|c}z} |dk(r| Sg} tt| dgt | z} | rj| j\} } | |k(r| j| n=| dz}|| z}| jt| | ||Dcgc] }| ||zz|fc}| rjt| Scc}wcc}wcc}w)a Solutions of `f(x) \equiv 0 \pmod{p^e}`. Parameters ========== f : polynomial p : prime number e : positive integer Returns ======= list[int] a list of solutions, sorted in ascending order by integers in the range [1, p**e). The same value does not exist in the list even if there is a multiple solution. If no solution exists, returns []. Examples ======== >>> from sympy.polys.galoistools import csolve_prime >>> csolve_prime([1, 1, 7], 3, 1) [1] >>> csolve_prime([1, 1, 7], 3, 2) [1, 4, 7] Solutions [7, 4, 1] (mod 3**2) are generated by ``_raise_mod_power()`` from solution [1] (mod 3). rr#r0Nr+)r%r$r rrIr2r@rBr:rrr3r$rr)r6)r3rrr$rUrfrpr< root_zeroX1Xr&rrrpsrs r csolve_primer@x s>' SV A 3q6A:  !a%!) ! ! AA A c!f*3q6A:>*a/ Q c!f*3q6A:>*a/ crFC  Bw %(^ QQ0A6 6 U1XKAq"1E1J!K KAv  A SaSR[ !"A uuw1 6 HHQKQBAB HH.>q!Q.JKq1R4xnK L  !9G !,LLsGG+G0G c ddlm}ddlm}||}|j Dcgc]\}}t |||}}}t tt|}gg} |D]} | D cgc]} | D]} | | gz } } } |j Dcgc]\}}t||} }}t| Dcgc]}t|| |c}Scc}}wcc} } wcc}}wcc}w)a To solve f(x) congruent 0 mod(n). n is divided into canonical factors and f(x) cong 0 mod(p**e) will be solved for each factor. Applying the Chinese Remainder Theorem to the results returns the final answers. Examples ======== Solve [1, 1, 7] congruent 0 mod(189): >>> from sympy.polys.galoistools import gf_csolve >>> gf_csolve([1, 1, 7], 189) [13, 49, 76, 112, 139, 175] See Also ======== sympy.ntheory.residue_ntheory.polynomial_congruence : a higher level solving routine References ========== .. [1] 'An introduction to the Theory of Numbers' 5th Edition by Ivan Niven, Zuckerman and Montgomery. rr#r) r%r$rritemsr@rBrCr~powr6r )r3rKr$rPrrr>poolspermspoolry dist_factorspers r gf_csolverK s:''! A+,779541aaA 5A5 UA E DE7"'6Q6AaS6667*+'')4$!QC1I4L4 EBS6#|R0B CC 674BsC(CC6C#r.)T)F)r0)`__doc__mathrrrrrsympy.core.randomrrsympy.external.gmpyrr r sympy.polys.polyconfigr sympy.polys.polyerrorsr sympy.polys.polyutilsr r r'r)r.r4r8r:r>r@rDrMrQrSrVrXr[r]r`rbrirkrrrwrzr|rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr rrrrrrr!r)r:r@rKr,r!rrSsG33/77(6/*Z.b"J*$((8 * ("8:  ,)"88((2" 9F 9F>(V //" 83,l!"$N(6((# J @#J". b ( . .?D22<0." :65,n  E"&*Z)X  4<0 0Vr% P;|)2X6r=2@JX<2~2,2, :=&@( =F%-PZzCL&Dr!