
    \hM                     l   S r SSKJrJrJrJrJrJrJrJ	r	J
r
Jr  SSKJrJrJrJrJrJrJrJrJrJrJrJr  SSKJrJrJrJrJrJrJ r J!r!J"r"  SSK#J$r$J%r%J&r&J'r'J(r(J)r)  SSK*J+r+J,r,  SSK-J.r.J/r/  S r0S	 r1S
 r2S r3S r4S r5S r6S r7S r8S r9S r:S r;SS jr<SS jr=SS jr>SS jr?SS jr@SS jrAS rBS rCg)z8Square-free decomposition algorithms and related tools.     )
dup_negdmp_negdup_subdmp_subdup_muldmp_muldup_quodmp_quodup_mul_grounddmp_mul_ground)	dup_stripdup_LCdmp_ground_LC
dmp_zero_p
dmp_ground
dup_degree
dmp_degreedmp_degree_indmp_degree_list	dmp_raise
dmp_injectdup_convert)	dup_diffdmp_diffdmp_diff_in	dup_shift	dmp_shift	dup_monicdmp_ground_monicdup_primitivedmp_ground_primitive)dup_inner_gcddmp_inner_gcddup_gcddmp_gcddmp_resultantdmp_primitive)gf_sqf_listgf_sqf_part)MultivariatePolynomialErrorDomainErrorc                 J    [        S U 5       5      nU[        U 5      :X  d   eg)z=Sanity check the degrees of a computed factorization in K[x].c              3   B   #    U  H  u  pU[        U5      -  v   M     g 7f)N)r   ).0facks      O/var/www/auris/envauris/lib/python3.13/site-packages/sympy/polys/sqfreetools.py	<genexpr>%_dup_check_degrees.<locals>.<genexpr>$   s     9&hsa*S/!&s   N)sumr   )fresultdegs      r1   _dup_check_degreesr8   "   s$    
9&9
9C*Q-    c                     S/US-   -  nU H4  u  pE[        XA5      n[        X65       VVs/ s H  u  pxXuU-  -   PM     nnnM6     [        U5      [        X5      :X  d   egs  snnf )z=Sanity check the degrees of a computed factorization in K[X].r      N)r   ziptuple)	r5   ur6   degsr/   r0   degs_facd1d2s	            r1   _dmp_check_degreesrC   (   sj    3!a%=D"3**-d*=>*=V*=>  ;/!//// ?s   Ac           
      ^    U (       d  g[        [        U [        U SU5      U5      5      (       + $ )z
Return ``True`` if ``f`` is a square-free polynomial in ``K[x]``.

Examples
========

>>> from sympy.polys import ring, ZZ
>>> R, x = ring("x", ZZ)

>>> R.dup_sqf_p(x**2 - 2*x + 1)
False
>>> R.dup_sqf_p(x**2 - 1)
True

Tr;   )r   r$   r   )r5   Ks     r1   	dup_sqf_prF   1   s*      ga!Q):A>???r9   c                     [        X5      (       a  g[        US-   5       HA  n[        U SX1U5      n[        XA5      (       a  M#  [        XX5      n[	        XSU5      S:w  d  MA    g   g)z
Return ``True`` if ``f`` is a square-free polynomial in ``K[X]``.

Examples
========

>>> from sympy.polys import ring, ZZ
>>> R, x,y = ring("x,y", ZZ)

>>> R.dmp_sqf_p(x**2 + 2*x*y + y**2)
False
>>> R.dmp_sqf_p(x**2 + y**2)
True

Tr;   r   F)r   ranger   r%   r   )r5   r>   rE   ifpgcds         r1   	dmp_sqf_prL   G   se      !1Q3ZAqQ'baQ"#q(  r9   c                 `   UR                   (       d  [        S5      eS[        UR                  R	                  5       SSUR
                  5      p2 [        U SUSS9u  pE[        X4SUR
                  5      n[        XaR
                  5      (       a  O[        XR                  * U5      US-   p M]  X U4$ )a  
Find a shift of `f` in `K[x]` that has square-free norm.

The domain `K` must be an algebraic number field `k(a)` (see :ref:`QQ(a)`).

Returns `(s,g,r)`, such that `g(x)=f(x-sa)`, `r(x)=\text{Norm}(g(x))` and
`r` is a square-free polynomial over `k`.

Examples
========

We first create the algebraic number field `K=k(a)=\mathbb{Q}(\sqrt{3})`
and rings `K[x]` and `k[x]`:

>>> from sympy.polys import ring, QQ
>>> from sympy import sqrt

>>> K = QQ.algebraic_field(sqrt(3))
>>> R, x = ring("x", K)
>>> _, X = ring("x", QQ)

We can now find a square free norm for a shift of `f`:

>>> f = x**2 - 1
>>> s, g, r = R.dup_sqf_norm(f)

The choice of shift `s` is arbitrary and the particular values returned for
`g` and `r` are determined by `s`.

>>> s == 1
True
>>> g == x**2 - 2*sqrt(3)*x + 2
True
>>> r == X**4 - 8*X**2 + 4
True

The invariants are:

>>> g == f.shift(-s*K.unit)
True
>>> g.norm() == r
True
>>> r.is_squarefree
True

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

This is part of Trager's algorithm for factorizing polynomials over
algebraic number fields. In particular this function is algorithm
``sqfr_norm`` from [Trager76]_.

See Also
========

dmp_sqf_norm:
    Analogous function for multivariate polynomials over ``k(a)``.
dmp_norm:
    Computes the norm of `f` directly without any shift.
dup_ext_factor:
    Function implementing Trager's algorithm that uses this.
sympy.polys.polytools.sqf_norm:
    High-level interface for using this function.
ground domain must be algebraicr   r;   Tfront)is_Algebraicr+   r   modto_listdomr   r&   rF   r   unit)r5   rE   sgh_rs          r1   dup_sqf_normr[   i   s    B >>;<<iAquu5q
!Q.!155)QQ+QUq  7Nr9   c           	   #     #    US-   nS/U-  nX@4v   UR                   n[        X5      n[        [        U[	        US-   5      5      5       VVs/ s H  u  pxUS:  d  M  UPM     n	nnU	 H=  nUR                  5       n
SX'   U
 Vs/ s H  o* U-  PM
     nn[        XX5      nX4v   M?     Sn US-  nU/U-  nU* U-  /U-  n[        U UX5      nUU4v   M*  s  snnf s  snf 7f)z9Generate a sequence of candidate shifts for dmp_sqf_norm.r;   r   )rU   r   sortedr<   rH   copyr   )r5   r>   rE   ns0addirI   var_indicess1s1ia1f1jsjajfjs                     r1   _dmp_sqf_norm_shiftsrm      s
     	
AA
qB
%K 	
A 	A"(Qac
);"<G"<Q1"<KG WWY "#bf#qa#f  	
A
	QS1WbdVaZq"a#"f  H $s%   AC"CC$ C"CAC"c                    U(       d  [        X5      u  p4nU/XE4$ UR                  (       d  [        S5      e[        UR                  R                  5       US-   SUR                  5      n[        XU5       HI  u  p0[        XUSS9u  pg[        XFUS-   UR                  5      n[        XQUR                  5      (       d  MI    O   WU W4$ )aD  
Find a shift of ``f`` in ``K[X]`` that has square-free norm.

The domain `K` must be an algebraic number field `k(a)` (see :ref:`QQ(a)`).

Returns `(s,g,r)`, such that `g(x_1,x_2,\cdots)=f(x_1-s_1 a, x_2 - s_2 a,
\cdots)`, `r(x)=\text{Norm}(g(x))` and `r` is a square-free polynomial over
`k`.

Examples
========

We first create the algebraic number field `K=k(a)=\mathbb{Q}(i)` and rings
`K[x,y]` and `k[x,y]`:

>>> from sympy.polys import ring, QQ
>>> from sympy import I

>>> K = QQ.algebraic_field(I)
>>> R, x, y = ring("x,y", K)
>>> _, X, Y = ring("x,y", QQ)

We can now find a square free norm for a shift of `f`:

>>> f = x*y + y**2
>>> s, g, r = R.dmp_sqf_norm(f)

The choice of shifts ``s`` is arbitrary and the particular values returned
for ``g`` and ``r`` are determined by ``s``.

>>> s
[0, 1]
>>> g == x*y - I*x + y**2 - 2*I*y - 1
True
>>> r == X**2*Y**2 + X**2 + 2*X*Y**3 + 2*X*Y + Y**4 + 2*Y**2 + 1
True

The required invariants are:

>>> g == f.shift_list([-si*K.unit for si in s])
True
>>> g.norm() == r
True
>>> r.is_squarefree
True

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

This is part of Trager's algorithm for factorizing polynomials over
algebraic number fields. In particular this function is a multivariate
generalization of algorithm ``sqfr_norm`` from [Trager76]_.

See Also
========

dup_sqf_norm:
    Analogous function for univariate polynomials over ``k(a)``.
dmp_norm:
    Computes the norm of `f` directly without any shift.
dmp_ext_factor:
    Function implementing Trager's algorithm that uses this.
sympy.polys.polytools.sqf_norm:
    High-level interface for using this function.
rN   r;   r   TrO   )r[   rQ   r+   r   rR   rS   rT   rm   r   r&   rL   )r5   r>   rE   rV   rW   rZ   rX   rY   s           r1   dmp_sqf_normro      s    D q$asAy>>;<<!%%--/1q5!QUU3A$Q1-!.!Aquu-Q155!! . a7Nr9   c                     UR                   (       d  [        S5      e[        UR                  R	                  5       US-   SUR
                  5      n[        XUSS9u  pE[        X4US-   UR
                  5      $ )ai  
Norm of ``f`` in ``K[X]``, often not square-free.

The domain `K` must be an algebraic number field `k(a)` (see :ref:`QQ(a)`).

Examples
========

We first define the algebraic number field `K = k(a) = \mathbb{Q}(\sqrt{2})`:

>>> from sympy import QQ, sqrt
>>> from sympy.polys.sqfreetools import dmp_norm
>>> k = QQ
>>> K = k.algebraic_field(sqrt(2))

We can now compute the norm of a polynomial `p` in `K[x,y]`:

>>> p = [[K(1)], [K(1),K.unit]]                  # x + y + sqrt(2)
>>> N = [[k(1)], [k(2),k(0)], [k(1),k(0),k(-2)]] # x**2 + 2*x*y + y**2 - 2
>>> dmp_norm(p, 1, K) == N
True

In higher level functions that is:

>>> from sympy import expand, roots, minpoly
>>> from sympy.abc import x, y
>>> from math import prod
>>> a = sqrt(2)
>>> e = (x + y + a)
>>> e.as_poly([x, y], extension=a).norm()
Poly(x**2 + 2*x*y + y**2 - 2, x, y, domain='QQ')

This is equal to the product of the expressions `x + y + a_i` where the
`a_i` are the conjugates of `a`:

>>> pa = minpoly(a)
>>> pa
_x**2 - 2
>>> rs = roots(pa, multiple=True)
>>> rs
[sqrt(2), -sqrt(2)]
>>> n = prod(e.subs(a, r) for r in rs)
>>> n
(x + y - sqrt(2))*(x + y + sqrt(2))
>>> expand(n)
x**2 + 2*x*y + y**2 - 2

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

Given an algebraic number field `K = k(a)` any element `b` of `K` can be
represented as polynomial function `b=g(a)` where `g` is in `k[x]`. If the
minimal polynomial of `a` over `k` is `p_a` then the roots `a_1`, `a_2`,
`\cdots` of `p_a(x)` are the conjugates of `a`. The norm of `b` is the
product `g(a1) \times g(a2) \times \cdots` and is an element of `k`.

As in [Trager76]_ we extend this norm to multivariate polynomials over `K`.
If `b(x)` is a polynomial in `k(a)[X]` then we can think of `b` as being
alternately a function `g_X(a)` where `g_X` is an element of `k[X][y]` i.e.
a polynomial function with coefficients that are elements of `k[X]`. Then
the norm of `b` is the product `g_X(a1) \times g_X(a2) \times \cdots` and
will be an element of `k[X]`.

See Also
========

dmp_sqf_norm:
    Compute a shift of `f` so that the `\text{Norm}(f)` is square-free.
sympy.polys.polytools.Poly.norm:
    Higher-level function that calls this.
rN   r;   r   TrO   )rQ   r+   r   rR   rS   rT   r   r&   )r5   r>   rE   rW   rX   rY   s         r1   dmp_normrq   9  sa    P >>;<<!%%--/1q5!QUU3AaAT*DAq1uaee,,r9   c                     [        XUR                  5      n [        XR                  UR                  5      n[        X!R                  U5      $ )z3Compute square-free part of ``f`` in ``GF(p)[x]``. )r   rT   r)   rR   )r5   rE   rW   s      r1   dup_gf_sqf_partrs     s7    A!%% AAuuaee$Aq%%##r9   c                     [        S5      e)z3Compute square-free part of ``f`` in ``GF(p)[X]``. +multivariate polynomials over finite fieldsNotImplementedErrorr5   r>   rE   s      r1   dmp_gf_sqf_partry         
K
LLr9   c                 <   UR                   (       a  [        X5      $ U (       d  U $ UR                  [        X5      5      (       a  [	        X5      n [        U [        U SU5      U5      n[        XU5      nUR                  (       a  [        X15      $ [        X15      S   $ )z
Returns square-free part of a polynomial in ``K[x]``.

Examples
========

>>> from sympy.polys import ring, ZZ
>>> R, x = ring("x", ZZ)

>>> R.dup_sqf_part(x**3 - 3*x - 2)
x**2 - x - 2

See Also
========

sympy.polys.polytools.Poly.sqf_part
r;   )is_FiniteFieldrs   is_negativer   r   r$   r   r	   is_Fieldr   r    )r5   rE   rK   sqfs       r1   dup_sqf_partr     s    $ 	q$$}}VA\""AM
!XaA&
*C
!!
Czz  S$Q''r9   c                    U(       d  [        X5      $ UR                  (       a  [        XU5      $ [        X5      (       a  U $ UR	                  [        XU5      5      (       a  [        XU5      n U n[        US-   5       H  n[        U[        U SXAU5      X5      nM     [        XX5      nUR                  (       a  [        XQU5      $ [        XQU5      S   $ )z
Returns square-free part of a polynomial in ``K[X]``.

Examples
========

>>> from sympy.polys import ring, ZZ
>>> R, x,y = ring("x,y", ZZ)

>>> R.dmp_sqf_part(x**3 + 2*x**2*y + x*y**2)
x**2 + x*y

r;   )r   r|   ry   r   r}   r   r   rH   r%   r   r
   r~   r   r!   )r5   r>   rE   rK   rI   r   s         r1   dmp_sqf_partr     s     A!!qQ''!}}]1+,,A!
C1Q3Zc;q!Q15q< 
!!
Czz**#CA.q11r9   c                 &   U n[        XUR                  5      n [        XR                  UR                  US9u  pE[	        U5       H"  u  nu  p[        XR                  U5      U4XV'   M$     [        X55        UR                  XAR                  5      U4$ )z<Compute square-free decomposition of ``f`` in ``GF(p)[x]``. all)r   rT   r(   rR   	enumerater8   convert)r5   rE   r   f_origcoefffactorsrI   r0   s           r1   dup_gf_sqf_listr     s}    FA!%% A EE155c:NEw'	6A!!UUA.2
 ( v'99UEE"G++r9   c                     [        S5      e)z<Compute square-free decomposition of ``f`` in ``GF(p)[X]``. ru   rv   )r5   r>   rE   r   s       r1   dmp_gf_sqf_listr     rz   r9   c                 d   UR                   (       a
  [        XUS9$ U nUR                  (       a  [        X5      n[	        X5      n O:[        X5      u  p@UR                  [        X5      5      (       a  [        X5      n U* n[        U 5      S::  a  U/ 4$ / Spe[        U SU5      n[        XU5      u  pn
 [        U	SU5      n[        XU5      nU(       d  UR                  X45        O>[        XU5      u  pn
U(       d  [        U5      S:  a  UR                  X45        US-  nMq  [        X55        XE4$ )a  
Return square-free decomposition of a polynomial in ``K[x]``.

Uses Yun's algorithm from [Yun76]_.

Examples
========

>>> from sympy.polys import ring, ZZ
>>> R, x = ring("x", ZZ)

>>> f = 2*x**5 + 16*x**4 + 50*x**3 + 76*x**2 + 56*x + 16

>>> R.dup_sqf_list(f)
(2, [(x + 1, 2), (x + 2, 3)])
>>> R.dup_sqf_list(f, all=True)
(2, [(1, 1), (x + 1, 2), (x + 2, 3)])

See Also
========

dmp_sqf_list:
    Corresponding function for multivariate polynomials.
sympy.polys.polytools.sqf_list:
    High-level function for square-free factorization of expressions.
sympy.polys.polytools.Poly.sqf_list:
    Analogous method on :class:`~.Poly`.

References
==========

[Yun76]_
r   r   r;   )r|   r   r~   r   r   r    r}   r   r   r   r"   r   appendr8   )r5   rE   r   r   r   r6   rI   rX   rW   pqrb   s               r1   dup_sqf_listr     s    D 	q--FzzqaO &==&&AFE!}byAAAqAA!$GA!
Q1A!MM1&!a(a*Q-!#MM1&!	Q  v&=r9   c                     [        XUS9u  p4U(       a)  US   S   S:X  a  [        US   S   X15      nUS4/USS -   $ [        U/5      nUS4/U-   $ )aU  
Return square-free decomposition of a polynomial in ``K[x]``.

Examples
========

>>> from sympy.polys import ring, ZZ
>>> R, x = ring("x", ZZ)

>>> f = 2*x**5 + 16*x**4 + 50*x**3 + 76*x**2 + 56*x + 16

>>> R.dup_sqf_list_include(f)
[(2, 1), (x + 1, 2), (x + 2, 3)]
>>> R.dup_sqf_list_include(f, all=True)
[(2, 1), (x + 1, 2), (x + 2, 3)]

r   r   r;   N)r   r   r   )r5   rE   r   r   r   rW   s         r1   dup_sqf_list_includer   A  sl    $ "!C0NE71:a=A%71:a=%3Ax'!"+%%ugAx'!!r9   c                 `   U(       d
  [        XUS9$ UR                  (       a
  [        XX#S9$ U nUR                  (       a  [	        XU5      n[        XU5      n O=[        XU5      u  pPUR                  [	        XU5      5      (       a  [        XU5      n U* n[        X5      nUS:  a  U/ 4$ [        XU5      u  pp0 nUS:w  a}  [        U SX5      n	[        X	X5      u  pnSn [        USX5      n[        XX5      n	[        X5      (       a  XU'   O0[        XX5      u  pnU(       d  [        X5      S:  a  XU'   US-  nM^  [        XqS-
  X#S9u  nnX_-  nU H%  u  nnU/nX;   a  [!        X   UX5      X'   M!  UX'   M'     [#        U5       Vs/ s H	  oU   U4PM     nn[%        XAU5        XX4$ s  snf )a  
Return square-free decomposition of a polynomial in `K[X]`.

Examples
========

>>> from sympy.polys import ring, ZZ
>>> R, x,y = ring("x,y", ZZ)

>>> f = x**5 + 2*x**4*y + x**3*y**2

>>> R.dmp_sqf_list(f)
(1, [(x + y, 2), (x, 3)])
>>> R.dmp_sqf_list(f, all=True)
(1, [(1, 1), (x + y, 2), (x, 3)])

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

Uses Yun's algorithm for univariate polynomials from [Yun76]_ recursively.
The multivariate polynomial is treated as a univariate polynomial in its
leading variable. Then Yun's algorithm computes the square-free
factorization of the primitive and the content is factored recursively.

It would be better to use a dedicated algorithm for multivariate
polynomials instead.

See Also
========

dup_sqf_list:
    Corresponding function for univariate polynomials.
sympy.polys.polytools.sqf_list:
    High-level function for square-free factorization of expressions.
sympy.polys.polytools.Poly.sqf_list:
    Analogous method on :class:`~.Poly`.
r   r   r;   )r   r|   r   r~   r   r   r!   r}   r   r   r'   r   r#   r   r   dmp_sqf_listr   r]   rC   )r5   r>   rE   r   r   r   r7   contentr6   rX   rW   r   r   rI   rb   coeff_contentresult_contentr/   s                     r1   r   r   ]  s   L Ac**qQ00FzzaA&Q1%'a0==qQ/00a AFE
Q
C
Qwby qQ'JGF
axQ1 a+aAq$Aa#A!q	#A!/GA!j&*q	FA  %1A#q$J!M>	E !Qe;	35FIFI ! '-Vn5nay!nnF5v&)=	 6s   
F+c                     U(       d
  [        XUS9$ [        XX#S9u  pEU(       a*  US   S   S:X  a  [        US   S   XAU5      nUS4/USS -   $ [        XA5      nUS4/U-   $ )a<  
Return square-free decomposition of a polynomial in ``K[x]``.

Examples
========

>>> from sympy.polys import ring, ZZ
>>> R, x,y = ring("x,y", ZZ)

>>> f = x**5 + 2*x**4*y + x**3*y**2

>>> R.dmp_sqf_list_include(f)
[(1, 1), (x + y, 2), (x, 3)]
>>> R.dmp_sqf_list_include(f, all=True)
[(1, 1), (x + y, 2), (x, 3)]

r   r   r;   N)r   r   r   r   )r5   r>   rE   r   r   r   rW   s          r1   dmp_sqf_list_includer     s|    $ #Ac22!!3NE71:a=A%71:a=%A6Ax'!"+%%u Ax'!!r9   c           
      ~   U (       d  [        S5      e[        X5      n [        U 5      (       d  / $ [        U [	        XR
                  U5      U5      n[        X!5      n[        U5       H.  u  nu  pV[        U[	        XQ" U5      * U5      U5      nXVS-   4X4'   M0     [        XU5      n [        U 5      (       d  U$ U S4/U-   $ )z
Compute greatest factorial factorization of ``f`` in ``K[x]``.

Examples
========

>>> from sympy.polys import ring, ZZ
>>> R, x = ring("x", ZZ)

>>> R.dup_gff_list(x**5 + 2*x**4 - x**3 - 2*x**2)
[(x, 1), (x + 2, 4)]

zDgreatest factorial factorization doesn't exist for a zero polynomialr;   )

ValueErrorr   r   r$   r   onedup_gff_listr   r   r	   )r5   rE   rW   HrI   rX   r0   s          r1   r   r     s     _``!Aa==	AyEE1-q1"1IAv9Q1q115A1u:AD & A!!}}HF8a<r9   c                 <    U(       d  [        X5      $ [        U 5      e)z
Compute greatest factorial factorization of ``f`` in ``K[X]``.

Examples
========

>>> from sympy.polys import ring, ZZ
>>> R, x,y = ring("x,y", ZZ)

)r   r*   rx   s      r1   dmp_gff_listr     s     A!!)!,,r9   N)F)D__doc__sympy.polys.densearithr   r   r   r   r   r   r	   r
   r   r   sympy.polys.densebasicr   r   r   r   r   r   r   r   r   r   r   r   sympy.polys.densetoolsr   r   r   r   r   r   r   r    r!   sympy.polys.euclidtoolsr"   r#   r$   r%   r&   r'   sympy.polys.galoistoolsr(   r)   sympy.polys.polyerrorsr*   r+   r8   rC   rF   rL   r[   rm   ro   rq   rs   ry   r   r   r   r   r   r   r   r   r   r    r9   r1   <module>r      s    >$ $ $   ) ) )
" "
 0@,DOd%PSlN-b$M
!(H"2J, M
JZ"8iX">" J-r9   