Ë
    7^(hiå  ã                   ó4  — d dl mZ d dlmZ d dlmZ d dlmZ d dlm	Z	m
Z
mZmZmZ d dlmZ d dlmZ d dlZd	„ Zd
„ Zd„ Zd„ Zd„ Zd„ Zd„ Zd„ Zd„ Zd„ Zd„ Zd)d„Zd„ Zd„ Z d„ Z!d„ Z"d„ Z#d„ Z$d„ Z%d„ Z&d„ Z'd*d„Z(d„ Z)d „ Z*d!„ Z+d"„ Z,d#„ Z-d$„ Z.d%„ Z/d&„ Z0d'„ Z1d(„ Z2y)+é    )ÚDummy)Ú	nextprime©Úcrt)ÚPolynomialRing)Úgf_gcdÚgf_from_dictÚgf_gcdexÚgf_divÚgf_lcm)ÚModularGCDFailed)ÚsqrtNc                 óÎ  — | j                   }| s%|s#|j                  |j                  |j                  fS | sW|j                  |j                  j                  k  r| |j                  |j                   fS ||j                  |j                  fS |sW| j                  |j                  j                  k  r|  |j                   |j                  fS | |j                  |j                  fS y)zn
    Compute the GCD of two polynomials in trivial cases, i.e. when one
    or both polynomials are zero.
    N)ÚringÚzeroÚLCÚdomainÚone)ÚfÚgr   s      úT/var/www/skyplay_api_hub/venv/lib/python3.12/site-packages/sympy/polys/modulargcd.pyÚ_trivial_gcdr      s¼   € ð
 �6‰6€Dá‘Ø�y‰y˜$Ÿ)™) T§Y¡YÐ.Ð.ÙØ�4‰4�$—+‘+×"Ñ"Ò"Ø�2�t—y‘y 4§8¡8 )Ð+Ð+à�d—i‘i §¡Ð)Ð)ÙØ�4‰4�$—+‘+×"Ñ"Ò"Ø�2˜Ÿ™�y $§)¡)Ð+Ð+à�d—h‘h §	¡	Ð)Ð)Øó    c                 óÆ  — | j                   j                  }|r�| }|j                  «       }|j                  |j                  |«      }	 |j                  «       }||k  rnD||j                  ||z
  f«      j                  ||j                  z  «      z
  j                  |«      }ŒZ|} |}|rŒ�| j                  |j                  | j                  |«      «      j                  |«      S )zM
    Compute the GCD of two univariate polynomials in `\mathbb{Z}_p[x]`.
    )r   r   ÚdegreeÚinvertr   Ú	mul_monomÚ
mul_groundÚtrunc_ground)ÚfpÚgpÚpÚdomÚremÚdegÚlcinvÚdegrems           r   Ú_gf_gcdr(   #   sÉ   € ð �'‰'�.‰.€Cá
ØˆØ�i‰i‹kˆØ—
‘
˜2Ÿ5™5 !Ó$ˆàØ—Z‘Z“\ˆFØ˜Š|ØØ˜Ÿ™ v°¡| oÓ6×AÑAÀ%È#Ï&É&Á.ÓQÑQ×_Ñ_Ð`aÓbˆCð	 ð ˆØˆò ð �=‰=˜Ÿ™ B§E¡E¨1Ó-Ó.×;Ñ;¸AÓ>Ð>r   c                 óJ  — | j                   j                  j                  | j                  |j                  «      }d}t	        |«      }||z  dk(  rt	        |«      }||z  dk(  rŒ| j                  |«      }|j                  |«      }t        |||«      }|j                  «       }|S )aø  
    Compute an upper bound for the degree of the GCD of two univariate
    integer polynomials `f` and `g`.

    The function chooses a suitable prime `p` and computes the GCD of
    `f` and `g` in `\mathbb{Z}_p[x]`. The choice of `p` guarantees that
    the degree in `\mathbb{Z}_p[x]` is greater than or equal to the degree
    in `\mathbb{Z}[x]`.

    Parameters
    ==========

    f : PolyElement
        univariate integer polynomial
    g : PolyElement
        univariate integer polynomial

    é   r   )r   r   Úgcdr   r   r   r(   r   )r   r   Úgammar"   r    r!   ÚhpÚdeghps           r   Ú_degree_bound_univariater/   :   s‘   € ð& �F‰F�M‰M×Ñ˜aŸd™d A§D¡DÓ)€EØ	€Aä�!‹€AØ
�!‰)�qŠ.Ü�a‹Lˆð �!‰)�q‹.ð 
�‰˜Ó	€BØ	
�‰˜Ó	€BÜ	��R˜Ó	€BØ�I‰I‹K€EØ€Lr   c           	      óD  — | j                  «       }| j                  j                  d   }| j                  j                  }t	        |dz   «      D ]?  }t        ||g| j                  ||z  «      |j                  ||z  «      gd¬«      d   ||f<   ŒA |j                  «        |S )a�  
    Construct a polynomial `h_{pq}` in `\mathbb{Z}_{p q}[x]` such that

    .. math ::

        h_{pq} = h_p \; \mathrm{mod} \, p

        h_{pq} = h_q \; \mathrm{mod} \, q

    for relatively prime integers `p` and `q` and polynomials
    `h_p` and `h_q` in `\mathbb{Z}_p[x]` and `\mathbb{Z}_q[x]`
    respectively.

    The coefficients of the polynomial `h_{pq}` are computed with the
    Chinese Remainder Theorem. The symmetric representation in
    `\mathbb{Z}_p[x]`, `\mathbb{Z}_q[x]` and `\mathbb{Z}_{p q}[x]` is used.
    It is assumed that `h_p` and `h_q` have the same degree.

    Parameters
    ==========

    hp : PolyElement
        univariate integer polynomial with coefficients in `\mathbb{Z}_p`
    hq : PolyElement
        univariate integer polynomial with coefficients in `\mathbb{Z}_q`
    p : Integer
        modulus of `h_p`, relatively prime to `q`
    q : Integer
        modulus of `h_q`, relatively prime to `p`

    Examples
    ========

    >>> from sympy.polys.modulargcd import _chinese_remainder_reconstruction_univariate
    >>> from sympy.polys import ring, ZZ

    >>> R, x = ring("x", ZZ)
    >>> p = 3
    >>> q = 5

    >>> hp = -x**3 - 1
    >>> hq = 2*x**3 - 2*x**2 + x

    >>> hpq = _chinese_remainder_reconstruction_univariate(hp, hq, p, q)
    >>> hpq
    2*x**3 + 3*x**2 + 6*x + 5

    >>> hpq.trunc_ground(p) == hp
    True
    >>> hpq.trunc_ground(q) == hq
    True

    r   r*   T©Ú	symmetric)r   r   Úgensr   Úranger   ÚcoeffÚ
strip_zero)r-   Úhqr"   ÚqÚnÚxÚhpqÚis           r   Ú,_chinese_remainder_reconstruction_univariater=   [   s“   € ðl 	�	‰	‹€AØ
�‰�‰�Q‰€AØ
�'‰'�,‰,€Cä�1�Q‘3‹Zò UˆÜ˜˜A˜ §¡¨!¨Q©$£°·±¸!¸Q¹$³Ð @ÈDÔQÐRSÑTˆˆQˆDŠ	ðUð ‡N�NÔØ€Jr   c                 óÎ  — | j                   |j                   k(  r | j                   j                  j                  sJ ‚t        | |«      }|�|S | j                   }| j	                  «       \  }} |j	                  «       \  }}|j                  j                  ||«      }t        | |«      }|dk(  r/ ||«      | j                  ||z  «      |j                  ||z  «      fS |j                  j                  | j                  |j                  «      }d}	d}
	 t        |
«      }
||
z  dk(  rt        |
«      }
||
z  dk(  rŒ| j                  |
«      }|j                  |
«      }t        |||
«      }|j                  «       }||kD  rŒm||k  rd}	|}Œw|j                  |«      j                  |
«      }|	dk(  r|
}	|}Œ¡t        ||
|	«      }|	|
z  }	||k(  s|}Œ¼|j                  |j                  «       «      }| j!                  |«      \  }}|j!                  |«      \  }}|sR|sP|j                  dk  r| }|j                  |«      }|j                  ||z  «      }|j                  ||z  «      }|||fS �ŒX)a’  
    Computes the GCD of two polynomials in `\mathbb{Z}[x]` using a modular
    algorithm.

    The algorithm computes the GCD of two univariate integer polynomials
    `f` and `g` by computing the GCD in `\mathbb{Z}_p[x]` for suitable
    primes `p` and then reconstructing the coefficients with the Chinese
    Remainder Theorem. Trial division is only made for candidates which
    are very likely the desired GCD.

    Parameters
    ==========

    f : PolyElement
        univariate integer polynomial
    g : PolyElement
        univariate integer polynomial

    Returns
    =======

    h : PolyElement
        GCD of the polynomials `f` and `g`
    cff : PolyElement
        cofactor of `f`, i.e. `\frac{f}{h}`
    cfg : PolyElement
        cofactor of `g`, i.e. `\frac{g}{h}`

    Examples
    ========

    >>> from sympy.polys.modulargcd import modgcd_univariate
    >>> from sympy.polys import ring, ZZ

    >>> R, x = ring("x", ZZ)

    >>> f = x**5 - 1
    >>> g = x - 1

    >>> h, cff, cfg = modgcd_univariate(f, g)
    >>> h, cff, cfg
    (x - 1, x**4 + x**3 + x**2 + x + 1, 1)

    >>> cff * h == f
    True
    >>> cfg * h == g
    True

    >>> f = 6*x**2 - 6
    >>> g = 2*x**2 + 4*x + 2

    >>> h, cff, cfg = modgcd_univariate(f, g)
    >>> h, cff, cfg
    (2*x + 2, 3*x - 3, x + 1)

    >>> cff * h == f
    True
    >>> cfg * h == g
    True

    References
    ==========

    1. [Monagan00]_

    r   r*   )r   r   Úis_ZZr   Ú	primitiver+   r/   r   r   r   r   r(   r   r=   Ú
quo_groundÚcontentÚdiv)r   r   Úresultr   ÚcfÚcgÚchÚboundr,   Úmr"   r    r!   r-   r.   ÚhlastmÚhmÚhÚfquoÚfremÚgquoÚgremÚcffÚcfgs                           r   Úmodgcd_univariaterS   œ   sI  € ðF �6‰6�Q—V‘VÒ §¡§¡× 3Ò 3Ð3Ð3ä˜!˜QÓ€FØÐØˆà�6‰6€Dà�K‰K‹M�E€BˆØ�K‰K‹M�E€BˆØ	�‰�‰˜˜RÓ	 €Bä$ Q¨Ó*€EØ�‚zÙ�B‹x˜Ÿ™ b¨B¡hÓ/°·±¸bÀB¹hÓ1GÐGÐGà�K‰K�O‰O˜AŸD™D !§$¡$Ó'€EØ	€AØ	€Aà
Ü�a‹LˆØ�a‰i˜1ŠnÜ˜!“ˆAð �a‰i˜1‹nð �^‰^˜AÓˆØ�^‰^˜AÓˆÜ�R˜˜QÓˆØ—	‘	“ˆà�5Š=ØØ�UŠ]ØˆAØˆEØà�]‰]˜5Ó!×.Ñ.¨qÓ1ˆØ�Š6ØˆAØˆFØä9¸"¸fÀaÈÓKˆØ	ˆQ‰ˆà�VŠ|ØˆFØà�M‰M˜"Ÿ*™*›,Ó'ˆØ—U‘U˜1“X‰
ˆˆdØ—U‘U˜1“X‰
ˆˆdÙ™DØ�t‰t�aŠxØ�S�Ø—‘˜RÓ ˆAØ—/‘/ "¨¡(Ó+ˆCØ—/‘/ "¨¡(Ó+ˆCØ�c˜3�;ÐñO r   c           	      óò  — | j                   }|j                  }|j                  }i }| j                  «       D ]"  \  }}|dd |vri ||dd <   |||dd    |d   <   Œ$ g }t	        |j                  «       «      D ]  }t        |t        |||«      ||«      }Œ |j                  |j                  |dz
     ¬«      }	|	j                  |«      j                  |«      }
|
| j                  |
j                  |«      «      fS )a€  
    Compute the content and the primitive part of a polynomial in
    `\mathbb{Z}_p[x_0, \ldots, x_{k-2}, y] \cong \mathbb{Z}_p[y][x_0, \ldots, x_{k-2}]`.

    Parameters
    ==========

    f : PolyElement
        integer polynomial in `\mathbb{Z}_p[x0, \ldots, x{k-2}, y]`
    p : Integer
        modulus of `f`

    Returns
    =======

    contf : PolyElement
        integer polynomial in `\mathbb{Z}_p[y]`, content of `f`
    ppf : PolyElement
        primitive part of `f`, i.e. `\frac{f}{contf}`

    Examples
    ========

    >>> from sympy.polys.modulargcd import _primitive
    >>> from sympy.polys import ring, ZZ

    >>> R, x, y = ring("x, y", ZZ)
    >>> p = 3

    >>> f = x**2*y**2 + x**2*y - y**2 - y
    >>> _primitive(f, p)
    (y**2 + y, x**2 - 1)

    >>> R, x, y, z = ring("x, y, z", ZZ)

    >>> f = x*y*z - y**2*z**2
    >>> _primitive(f, p)
    (z, x*y - y**2*z)

    Néÿÿÿÿr*   ©Úsymbols)r   r   ÚngensÚ	itertermsÚiterÚvaluesr   r	   ÚclonerW   Ú
from_denser   ÚquoÚset_ring)r   r"   r   r#   ÚkÚcoeffsÚmonomr5   ÚcontÚyringÚcontfs              r   Ú
_primitiverf     s  € ðR �6‰6€DØ
�+‰+€CØ�
‰
€Aà€FØŸ™›ò .‰ˆˆuØ��"ˆ:˜VÑ#Ø!#ˆF�5˜˜"�:ÑØ(-ˆˆu�S�bˆzÑ˜5 ™9Ò%ð.ð
 €DÜ�f—m‘m“oÓ&ò AˆÜ�dœL¨°°3Ó7¸¸CÓ@‰ðAð �J‰J˜tŸ|™|¨A¨a©CÑ0ˆJÓ1€EØ×Ñ˜TÓ"×/Ñ/°Ó2€Eà�!—%‘%˜Ÿ™ tÓ,Ó-Ð-Ð-r   c                 óˆ   — | j                   j                  }d|dz
  z  }| j                  «       D ]  }|dd |kD  sŒ|dd }Œ |S )aÆ  
    Compute the degree of a multivariate polynomial
    `f \in K[x_0, \ldots, x_{k-2}, y] \cong K[y][x_0, \ldots, x_{k-2}]`.

    Parameters
    ==========

    f : PolyElement
        polynomial in `K[x_0, \ldots, x_{k-2}, y]`

    Returns
    =======

    degf : Integer tuple
        degree of `f` in `x_0, \ldots, x_{k-2}`

    Examples
    ========

    >>> from sympy.polys.modulargcd import _deg
    >>> from sympy.polys import ring, ZZ

    >>> R, x, y = ring("x, y", ZZ)

    >>> f = x**2*y**2 + x**2*y - 1
    >>> _deg(f)
    (2,)

    >>> R, x, y, z = ring("x, y, z", ZZ)

    >>> f = x**2*y**2 + x**2*y - 1
    >>> _deg(f)
    (2, 2)

    >>> f = x*y*z - y**2*z**2
    >>> _deg(f)
    (1, 1)

    )r   r*   NrU   )r   rX   Ú
itermonoms)r   r`   Údegfrb   s       r   Ú_degrj   Z  sT   € ðP 	
�‰�‰€AØ�1�Q‘3‰<€DØ—‘“ò ˆØ��"ˆ:˜ÓØ˜˜"�:‰Dðð €Kr   c                 ó$  — | j                   }|j                  }|j                  |j                  |dz
     ¬«      }|j                  d   }t        | «      }|j                  }| j                  «       D ]  \  }}|dd |k(  sŒ||||d   z  z  z  }Œ |S )aÏ  
    Compute the leading coefficient of a multivariate polynomial
    `f \in K[x_0, \ldots, x_{k-2}, y] \cong K[y][x_0, \ldots, x_{k-2}]`.

    Parameters
    ==========

    f : PolyElement
        polynomial in `K[x_0, \ldots, x_{k-2}, y]`

    Returns
    =======

    lcf : PolyElement
        polynomial in `K[y]`, leading coefficient of `f`

    Examples
    ========

    >>> from sympy.polys.modulargcd import _LC
    >>> from sympy.polys import ring, ZZ

    >>> R, x, y = ring("x, y", ZZ)

    >>> f = x**2*y**2 + x**2*y - 1
    >>> _LC(f)
    y**2 + y

    >>> R, x, y, z = ring("x, y, z", ZZ)

    >>> f = x**2*y**2 + x**2*y - 1
    >>> _LC(f)
    1

    >>> f = x*y*z - y**2*z**2
    >>> _LC(f)
    z

    r*   rV   r   NrU   )r   rX   r\   rW   r3   rj   r   rY   )	r   r   r`   rd   Úyri   Úlcfrb   r5   s	            r   Ú_LCrn   Š  s˜   € ðP �6‰6€DØ�
‰
€AØ�J‰J˜tŸ|™|¨A¨a©CÑ0ˆJÓ1€EØ�
‰
�1‰€AÜ�‹7€Dà
�*‰*€CØŸ™›ò &‰ˆˆuØ��"ˆ:˜ÓØ�5˜˜E "™I™Ñ%Ñ%‰Cð&ð €Jr   c                 óš   — | j                   }|j                  }| j                  «       D ]  \  }}||   f|d| z   ||dz   d z   }|||<   Œ! |S )zS
    Make the variable `x_i` the leading one in a multivariate polynomial `f`.
    Nr*   )r   r   rY   )r   r<   r   Úfswaprb   r5   Ú	monomswaps          r   Ú_swaprr   ¿  se   € ð �6‰6€DØ�I‰I€EØŸ™›ò !‰ˆˆuØ˜1‘X�K %¨¨ )Ñ+¨e°A°a±C°D¨kÑ9ˆ	Ø ˆˆiÒð!ð €Lr   c                 ó¾  — | j                   }|j                  j                  | j                  |j                  «      }|j                  j                  t	        | d«      j                  t	        |d«      j                  «      }||z  }d}t        |«      }||z  dk(  rt        |«      }||z  dk(  rŒ| j                  |«      }|j                  |«      }t        ||«      \  }	}t        ||«      \  }
}t        |	|
|«      }|j                  «       }t        t        |«      t        |«      |«      }t        |«      D ]|  }|j                  d|«      |z  sŒ|j                  d|«      j                  |«      }|j                  d|«      j                  |«      }t        |||«      }|j                  «       }||fc S  t        |j                  «       |j                  «       «      |fS )a§  
    Compute upper degree bounds for the GCD of two bivariate
    integer polynomials `f` and `g`.

    The GCD is viewed as a polynomial in `\mathbb{Z}[y][x]` and the
    function returns an upper bound for its degree and one for the degree
    of its content. This is done by choosing a suitable prime `p` and
    computing the GCD of the contents of `f \; \mathrm{mod} \, p` and
    `g \; \mathrm{mod} \, p`. The choice of `p` guarantees that the degree
    of the content in `\mathbb{Z}_p[y]` is greater than or equal to the
    degree in `\mathbb{Z}[y]`. To obtain the degree bound in the variable
    `x`, the polynomials are evaluated at `y = a` for a suitable
    `a \in \mathbb{Z}_p` and then their GCD in `\mathbb{Z}_p[x]` is
    computed. If no such `a` exists, i.e. the degree in `\mathbb{Z}_p[x]`
    is always smaller than the one in `\mathbb{Z}[y][x]`, then the bound is
    set to the minimum of the degrees of `f` and `g` in `x`.

    Parameters
    ==========

    f : PolyElement
        bivariate integer polynomial
    g : PolyElement
        bivariate integer polynomial

    Returns
    =======

    xbound : Integer
        upper bound for the degree of the GCD of the polynomials `f` and
        `g` in the variable `x`
    ycontbound : Integer
        upper bound for the degree of the content of the GCD of the
        polynomials `f` and `g` in the variable `y`

    References
    ==========

    1. [Monagan00]_

    r*   r   )r   r   r+   r   rr   r   r   rf   r(   r   rn   r4   ÚevaluateÚmin)r   r   r   Úgamma1Úgamma2Ú	badprimesr"   r    r!   ÚcontfpÚcontgpÚconthpÚ
ycontboundÚdeltaÚaÚfpaÚgpaÚhpaÚxbounds                      r   Ú_degree_bound_bivariaterƒ   Ë  sž  € ðT �6‰6€Dà�[‰[�_‰_˜QŸT™T 1§4¡4Ó(€FØ�[‰[�_‰_œU 1 a›[Ÿ^™^¬U°1°a«[¯^©^Ó<€FØ˜‘€IØ	€Aä�!‹€AØ
�a‰-˜1Ò
Ü�a‹Lˆð �a‰-˜1Ó
ð 
�‰˜Ó	€BØ	
�‰˜Ó	€BÜ˜B Ó"�J€FˆBÜ˜B Ó"�J€FˆBÜ�V˜V QÓ'€FØ—‘“€Jô ”C˜“GœS ›W aÓ(€Eä�1‹Xò "ˆØ�~‰~˜a Ó# aÒ'ØØ�k‰k˜!˜QÓ×,Ñ,¨QÓ/ˆØ�k‰k˜!˜QÓ×,Ñ,¨QÓ/ˆÜ�c˜3 Ó"ˆØ—‘“ˆØ�zÐ!Ò!ð"ô ˆr�y‰y‹{˜BŸI™I›KÓ(¨*Ð4Ð4r   c                 ó8  ‡— t        | j                  «       «      }t        |j                  «       «      }|j                  |«      }|j                  |«       |j                  |«       | j                  j
                  Š‰j                  }| j                  j                  }t        | j                  j
                  t        «      rt        }	nˆfd„}	|D ]  }
 |	| |
   ||
   ||«      ||
<   Œ |D ]  }
 |	| |
   |||«      ||
<   Œ |D ]  }
 |	|||
   ||«      ||
<   Œ |S )a:  
    Construct a polynomial `h_{pq}` in
    `\mathbb{Z}_{p q}[x_0, \ldots, x_{k-1}]` such that

    .. math ::

        h_{pq} = h_p \; \mathrm{mod} \, p

        h_{pq} = h_q \; \mathrm{mod} \, q

    for relatively prime integers `p` and `q` and polynomials
    `h_p` and `h_q` in `\mathbb{Z}_p[x_0, \ldots, x_{k-1}]` and
    `\mathbb{Z}_q[x_0, \ldots, x_{k-1}]` respectively.

    The coefficients of the polynomial `h_{pq}` are computed with the
    Chinese Remainder Theorem. The symmetric representation in
    `\mathbb{Z}_p[x_0, \ldots, x_{k-1}]`,
    `\mathbb{Z}_q[x_0, \ldots, x_{k-1}]` and
    `\mathbb{Z}_{p q}[x_0, \ldots, x_{k-1}]` is used.

    Parameters
    ==========

    hp : PolyElement
        multivariate integer polynomial with coefficients in `\mathbb{Z}_p`
    hq : PolyElement
        multivariate integer polynomial with coefficients in `\mathbb{Z}_q`
    p : Integer
        modulus of `h_p`, relatively prime to `q`
    q : Integer
        modulus of `h_q`, relatively prime to `p`

    Examples
    ========

    >>> from sympy.polys.modulargcd import _chinese_remainder_reconstruction_multivariate
    >>> from sympy.polys import ring, ZZ

    >>> R, x, y = ring("x, y", ZZ)
    >>> p = 3
    >>> q = 5

    >>> hp = x**3*y - x**2 - 1
    >>> hq = -x**3*y - 2*x*y**2 + 2

    >>> hpq = _chinese_remainder_reconstruction_multivariate(hp, hq, p, q)
    >>> hpq
    4*x**3*y + 5*x**2 + 3*x*y**2 + 2

    >>> hpq.trunc_ground(p) == hp
    True
    >>> hpq.trunc_ground(q) == hq
    True

    >>> R, x, y, z = ring("x, y, z", ZZ)
    >>> p = 6
    >>> q = 5

    >>> hp = 3*x**4 - y**3*z + z
    >>> hq = -2*x**4 + z

    >>> hpq = _chinese_remainder_reconstruction_multivariate(hp, hq, p, q)
    >>> hpq
    3*x**4 + 5*y**3*z + z

    >>> hpq.trunc_ground(p) == hp
    True
    >>> hpq.trunc_ground(q) == hq
    True

    c                 ó:   •—  ‰t        ||g| |gd¬«      d   «      S )NTr1   r   r   )ÚcpÚcqr"   r8   r   s       €r   Úcrt_z<_chinese_remainder_reconstruction_multivariate.<locals>.crt_l  s$   ø€ Ùœ#˜q !˜f r¨2 h¸$Ô?ÀÑBÓCÐCr   )
ÚsetÚmonomsÚintersectionÚdifference_updater   r   r   Ú
isinstancer   Ú._chinese_remainder_reconstruction_multivariate)r-   r7   r"   r8   ÚhpmonomsÚhqmonomsrŠ   r   r;   rˆ   rb   r   s              @r   rŽ   rŽ     s  ø€ ôP �2—9‘9“;Ó€HÜ�2—9‘9“;Ó€HØ×"Ñ" 8Ó,€FØ×Ñ˜vÔ&Ø×Ñ˜vÔ&à�W‰W�^‰^€FØ�;‰;€Dà
�'‰'�,‰,€Cä�"—'‘'—.‘.¤.Ô1Ü=‰ô	Dð ò 6ˆÙ˜"˜U™) R¨¡Y°°1Ó5ˆˆEŠ
ð6àò 1ˆÙ˜"˜U™) T¨1¨aÓ0ˆˆEŠ
ð1àò 1ˆÙ˜$  5¡	¨1¨aÓ0ˆˆEŠ
ð1ð €Jr   c                 óÜ  — |j                   }|r0|j                  j                  }|j                  j                  |   }n|j                  }|j                  |   }t        | |«      D ]t  \  }	}
|j                  }|j                  }| D ]  }||	k(  rŒ	|||z
  z  }||	|z
  z  }Œ |j                  ||«      }|j                  |«      }||
j                  |«      |z  z  }Œv |j                  |«      S )a  
    Reconstruct a polynomial `h_p` in `\mathbb{Z}_p[x_0, \ldots, x_{k-1}]`
    from a list of evaluation points in `\mathbb{Z}_p` and a list of
    polynomials in
    `\mathbb{Z}_p[x_0, \ldots, x_{i-1}, x_{i+1}, \ldots, x_{k-1}]`, which
    are the images of `h_p` evaluated in the variable `x_i`.

    It is also possible to reconstruct a parameter of the ground domain,
    i.e. if `h_p` is a polynomial over `\mathbb{Z}_p[x_0, \ldots, x_{k-1}]`.
    In this case, one has to set ``ground=True``.

    Parameters
    ==========

    evalpoints : list of Integer objects
        list of evaluation points in `\mathbb{Z}_p`
    hpeval : list of PolyElement objects
        list of polynomials in (resp. over)
        `\mathbb{Z}_p[x_0, \ldots, x_{i-1}, x_{i+1}, \ldots, x_{k-1}]`,
        images of `h_p` evaluated in the variable `x_i`
    ring : PolyRing
        `h_p` will be an element of this ring
    i : Integer
        index of the variable which has to be reconstructed
    p : Integer
        prime number, modulus of `h_p`
    ground : Boolean
        indicates whether `x_i` is in the ground domain, default is
        ``False``

    Returns
    =======

    hp : PolyElement
        interpolated polynomial in (resp. over)
        `\mathbb{Z}_p[x_0, \ldots, x_{k-1}]`

    )	r   r   r3   Úzipr   r   r   r_   r   )Ú
evalpointsÚhpevalr   r<   r"   Úgroundr-   r   rl   r~   r�   ÚnumerÚdenomÚbr5   s                  r   Ú_interpolate_multivariater™   y  sô   € ðN 
�‰€BáØ—‘×#Ñ#ˆØ�K‰K×Ñ˜QÑ‰à—‘ˆØ�I‰I�a‰Lˆä�j &Ó)ò )‰ˆˆ3Ø—‘ˆØ—
‘
ˆØò 	ˆAØ�AŠvØà�Q˜‘U‰NˆEØ�Q˜‘U‰N‰Eð	ð —‘˜e QÓ'ˆØ× Ñ  Ó'ˆØ
ˆc�l‰l˜4Ó  5Ñ(Ñ(‰ð)ð �?‰?˜1ÓÐr   c                 ó
  — | j                   |j                   k(  r | j                   j                  j                  sJ ‚t        | |«      }|�|S | j                   }| j	                  «       \  }} |j	                  «       \  }}|j                  j                  ||«      }t        | |«      \  }}||cxk(  rdk(  r2n n/ ||«      | j                  ||z  «      |j                  ||z  «      fS t        | d«      }	t        |d«      }
|	j                  «       }|
j                  «       }t        |	|
«      \  }}||cxk(  rdk(  r2n n/ ||«      | j                  ||z  «      |j                  ||z  «      fS |j                  j                  | j                  |j                  «      }|j                  j                  |	j                  |
j                  «      }||z  }d}d}	 t        |«      }||z  dk(  rt        |«      }||z  dk(  rŒ| j                  |«      }|j                  |«      }t        ||«      \  }}t        ||«      \  }}t        |||«      }|j                  «       }||kD  rŒ‹||k  rd}|}Œ•t        t        |«      t        |«      |«      }|j                  «       }|j                  «       }|j                  «       }t!        ||z
  ||z
  ||z
  |z   «      dz   }||k  r�Œd}g } g }!d}"t#        |«      D ]Ú  }#|j%                  d|#«      }$|$|z  sŒ|j%                  d|#«      j                  |«      }%|j%                  d|#«      j                  |«      }&t        |%|&|«      }'|'j                  «       }(|(|kD  rŒ€|(|k  rd}|(}d}" nP|'j                  |$«      j                  |«      }'| j'                  |#«       |!j'                  |'«       |dz  }||k(  sŒÚ n |"r�Œû||k  r�Œt)        | |!|d|«      })t        |)|«      d   })|)|j+                  |«      z  })|)j                  d«      }*|*|kD  r�ŒL|*|k  rd}|*}�ŒW|)j                  |«      j                  |«      })|dk(  r|}|)}+�Œ‚t-        |)+||«      },||z  }|,|+k(  s|,}+�Œž|,j/                  |,j1                  «       «      }-| j3                  |-«      \  }.}/|j3                  |-«      \  }0}1|/sR|1sP|-j                  dk  r| }|-j                  |«      }-|.j                  ||z  «      }2|0j                  ||z  «      }3|-|2|3fS �Œ:)a!  
    Computes the GCD of two polynomials in `\mathbb{Z}[x, y]` using a
    modular algorithm.

    The algorithm computes the GCD of two bivariate integer polynomials
    `f` and `g` by calculating the GCD in `\mathbb{Z}_p[x, y]` for
    suitable primes `p` and then reconstructing the coefficients with the
    Chinese Remainder Theorem. To compute the bivariate GCD over
    `\mathbb{Z}_p`, the polynomials `f \; \mathrm{mod} \, p` and
    `g \; \mathrm{mod} \, p` are evaluated at `y = a` for certain
    `a \in \mathbb{Z}_p` and then their univariate GCD in `\mathbb{Z}_p[x]`
    is computed. Interpolating those yields the bivariate GCD in
    `\mathbb{Z}_p[x, y]`. To verify the result in `\mathbb{Z}[x, y]`, trial
    division is done, but only for candidates which are very likely the
    desired GCD.

    Parameters
    ==========

    f : PolyElement
        bivariate integer polynomial
    g : PolyElement
        bivariate integer polynomial

    Returns
    =======

    h : PolyElement
        GCD of the polynomials `f` and `g`
    cff : PolyElement
        cofactor of `f`, i.e. `\frac{f}{h}`
    cfg : PolyElement
        cofactor of `g`, i.e. `\frac{g}{h}`

    Examples
    ========

    >>> from sympy.polys.modulargcd import modgcd_bivariate
    >>> from sympy.polys import ring, ZZ

    >>> R, x, y = ring("x, y", ZZ)

    >>> f = x**2 - y**2
    >>> g = x**2 + 2*x*y + y**2

    >>> h, cff, cfg = modgcd_bivariate(f, g)
    >>> h, cff, cfg
    (x + y, x - y, x + y)

    >>> cff * h == f
    True
    >>> cfg * h == g
    True

    >>> f = x**2*y - x**2 - 4*y + 4
    >>> g = x + 2

    >>> h, cff, cfg = modgcd_bivariate(f, g)
    >>> h, cff, cfg
    (x + 2, x*y - x - 2*y + 2, 1)

    >>> cff * h == f
    True
    >>> cfg * h == g
    True

    References
    ==========

    1. [Monagan00]_

    r   r*   TF)r   r   r?   r   r@   r+   rƒ   r   rr   r   r   r   r   rf   r(   rn   ru   r4   rt   Úappendr™   r_   rŽ   rA   rB   rC   )4r   r   rD   r   rE   rF   rG   r‚   r|   rp   ÚgswapÚdegyfÚdegygÚyboundÚ
xcontboundrv   rw   rx   rI   r"   r    r!   ry   rz   r{   Ú	degconthpr}   Ú	degcontfpÚ	degcontgpÚdegdeltaÚNr9   r“   r”   Úunluckyr~   Údeltaar   r€   r�   Údeghpar-   ÚdegyhprJ   rK   rL   rM   rN   rO   rP   rQ   rR   s4                                                       r   Úmodgcd_bivariaterª   º  sò  € ðR �6‰6�Q—V‘VÒ §¡§¡× 3Ò 3Ð3Ð3ä˜!˜QÓ€FØÐØˆà�6‰6€Dà�K‰K‹M�E€BˆØ�K‰K‹M�E€BˆØ	�‰�‰˜˜RÓ	 €Bä0°°AÓ6Ñ€FˆJØ�Ô ˜qÕ Ù�B‹x˜Ÿ™ b¨B¡hÓ/°·±¸bÀB¹hÓ1GÐGÐGä�!�Q‹K€EÜ�!�Q‹K€EØ�L‰L‹N€EØ�L‰L‹N€Eä0°¸Ó>Ñ€FˆJØ�Ô ˜qÕ Ù�B‹x˜Ÿ™ b¨B¡hÓ/°·±¸bÀB¹hÓ1GÐGÐGð �[‰[�_‰_˜QŸT™T 1§4¡4Ó(€FØ�[‰[�_‰_˜UŸX™X u§x¡xÓ0€FØ˜‘€IØ	€AØ	€Aà
Ü�a‹LˆØ˜!‰m˜qÒ Ü˜!“ˆAð ˜!‰m˜qÓ ð �^‰^˜AÓˆØ�^‰^˜AÓˆÜ  AÓ&‰
ˆ�Ü  AÓ&‰
ˆ�Ü˜ ¨Ó+ˆØ—M‘M“Oˆ	à�zÒ!ØØ˜Ò#ØˆAØ"ˆJØô œ˜B›¤ R£¨!Ó,ˆà—M‘M“Oˆ	Ø—M‘M“Oˆ	Ø—<‘<“>ˆä�˜	Ñ! 5¨9Ñ#4Ø�ZÑ (Ñ*ó,Ø./ñ0ˆð ˆqŠ5ÙàˆØˆ
ØˆØˆä�q“ò 	ˆAØ—^‘^ A qÓ)ˆFØ˜A’:Øà—+‘+˜a Ó#×0Ñ0°Ó3ˆCØ—+‘+˜a Ó#×0Ñ0°Ó3ˆCÜ˜#˜s AÓ&ˆCØ—Z‘Z“\ˆFà˜ŠØØ˜&’Ø�Ø�Ø�Ùà—.‘. Ó(×5Ñ5°aÓ8ˆCØ×Ñ˜aÔ Ø�M‰M˜#ÔØ�‰FˆAà�A‹vÙð1	ñ4 ÙØˆqŠ5Ùä& z°6¸4ÀÀAÓFˆä˜˜AÓ˜qÑ!ˆØ�&—/‘/ $Ó'Ñ'ˆØ—‘˜1“ˆà�FŠ?ÙØ�FŠ?ØˆAØˆFÙà�]‰]˜6Ó"×/Ñ/°Ó2ˆØ�Š6ØˆAØˆFÙä;¸BÀÈÈ1ÓMˆØ	ˆQ‰ˆà�VŠ|ØˆFÙà�M‰M˜"Ÿ*™*›,Ó'ˆØ—U‘U˜1“X‰
ˆˆdØ—U‘U˜1“X‰
ˆˆdÙ™DØ�t‰t�aŠxØ�S�Ø—‘˜RÓ ˆAØ—/‘/ "¨¡(Ó+ˆCØ—/‘/ "¨¡(Ó+ˆCØ�c˜3�;ÐñO r   c                 ó  — | j                   }|j                  }|dk(  rJt        | ||«      j                  |«      }|j	                  «       }||d   kD  ry||d   k  r||d<   t
        ‚|S | j	                  |dz
  «      }	|j	                  |dz
  «      }
t        | |«      \  }} t        ||«      \  }}t        |||«      }|j	                  «       }|j	                  «       }|j	                  «       }|||dz
     kD  ry|||dz
     k  r|||dz
  <   t
        ‚t        | «      }t        |«      }t        |||«      }|}t        |dz
  «      D ]8  }|t        t        t        | |«      «      t        t        ||«      «      |«      z  }Œ: |j	                  «       }t        |	|z
  |
|z
  ||dz
     ||dz
     z
  |z   «      dz   }||k  ryd}d}g }g }t        t        |«      «      }|�r¦t        j                  |d«      d   }|j                  |«       |j                  d|«      |z  sŒC|j                  d|«      |z  }| j                  |dz
  |«      j                  |«      }|j                  |dz
  |«      j                  |«      } t!        || |||«      }!|!€|dz  }||kD  ryŒ½|!j"                  r"|j%                  |«      j                  |«      }|S |!j'                  |«      j                  |«      }!|j)                  |«       |j)                  |!«       |dz  }||k(  rnt+        ||||dz
  |«      }t        ||«      d   |j%                  |«      z  }|j	                  |dz
  «      }"|"||dz
     kD  ry|"||dz
     k  r|"||dz
  <   t
        ‚|S |r�Œ¦y)a±  
    Compute the GCD of two polynomials in
    `\mathbb{Z}_p[x_0, \ldots, x_{k-1}]`.

    The algorithm reduces the problem step by step by evaluating the
    polynomials `f` and `g` at `x_{k-1} = a` for suitable
    `a \in \mathbb{Z}_p` and then calls itself recursively to compute the GCD
    in `\mathbb{Z}_p[x_0, \ldots, x_{k-2}]`. If these recursive calls are
    successful for enough evaluation points, the GCD in `k` variables is
    interpolated, otherwise the algorithm returns ``None``. Every time a GCD
    or a content is computed, their degrees are compared with the bounds. If
    a degree greater then the bound is encountered, then the current call
    returns ``None`` and a new evaluation point has to be chosen. If at some
    point the degree is smaller, the correspondent bound is updated and the
    algorithm fails.

    Parameters
    ==========

    f : PolyElement
        multivariate integer polynomial with coefficients in `\mathbb{Z}_p`
    g : PolyElement
        multivariate integer polynomial with coefficients in `\mathbb{Z}_p`
    p : Integer
        prime number, modulus of `f` and `g`
    degbound : list of Integer objects
        ``degbound[i]`` is an upper bound for the degree of the GCD of `f`
        and `g` in the variable `x_i`
    contbound : list of Integer objects
        ``contbound[i]`` is an upper bound for the degree of the content of
        the GCD in `\mathbb{Z}_p[x_i][x_0, \ldots, x_{i-1}]`,
        ``contbound[0]`` is not used can therefore be chosen
        arbitrarily.

    Returns
    =======

    h : PolyElement
        GCD of the polynomials `f` and `g` or ``None``

    References
    ==========

    1. [Monagan00]_
    2. [Brown71]_

    r*   r   N)r   rX   r(   r   r   r   rf   rn   r4   rr   ru   ÚlistÚrandomÚsampleÚremovert   Ú_modgcd_multivariate_pÚ	is_groundr_   r   r›   r™   )#r   r   r"   ÚdegboundÚ	contboundr   r`   rL   Údeghr�   rž   re   ÚcontgÚconthÚdegcontfÚdegcontgÚdegconthrm   Úlcgr}   Úevaltestr<   r¤   r¥   r9   Údr“   ÚhevalÚpointsr~   r§   ÚfaÚgaÚhaÚdegyhs#                                      r   r°   r°   Ž  s©  € ð` �6‰6€DØ�
‰
€AàˆA‚vÜ�A�q˜!Ó×)Ñ)¨!Ó,ˆØ�x‰x‹zˆà�(˜1‘+ÒØØ�(˜1‘+ÒØˆH�Q‰KÜ"Ð"àˆà�H‰H�Q�q‘S‹M€EØ�H‰H�Q�q‘S‹M€Eä˜!˜QÓ�H€Eˆ1Ü˜!˜QÓ�H€Eˆ1ä�E˜5 !Ó$€Eà�|‰|‹~€HØ�|‰|‹~€HØ�|‰|‹~€Hà�)˜A˜a™C‘.Ò ØØ�)˜A˜a™C‘.Ò Ø!ˆ	�!�A‘#‰ÜÐä
ˆa‹&€CÜ
ˆa‹&€Cä�C˜˜aÓ €Eà€Hä�1�Q‘3‹Zò CˆØ”GœC¤ a¨£Ó,¬c´%¸¸1³+Ó.>ÀÓBÑB‰ðCð �|‰|‹~€HäˆE�HÑ˜e hÑ.Ø�Q�q‘S‰M˜I a¨¡c™NÑ*¨XÑ5ó	7Ø9:ñ	;€Að 	ˆ1‚uØà	€AØ	€AØ€JØ€EÜ”%˜“(‹^€Fâ
Ü�M‰M˜& !Ó$ QÑ'ˆØ�‰�aÔà× Ñ   AÓ&¨Ò*Øà—‘  1Ó%¨Ñ)ˆà�Z‰Z˜˜!™˜QÓ×,Ñ,¨QÓ/ˆØ�Z‰Z˜˜!™˜QÓ×,Ñ,¨QÓ/ˆô $ B¨¨A¨x¸ÓCˆàˆ:Ø�‰FˆAØ�1ŠuØØà�<Š<Ø—‘˜tÓ$×1Ñ1°!Ó4ˆAØˆHà�]‰]˜6Ó"×/Ñ/°Ó2ˆà×Ñ˜!ÔØ�‰�RÔØ	ˆQ‰ˆà�Š6Ü)¨*°e¸TÀ1ÀQÁ3ÈÓJˆAä˜1˜aÓ  Ñ# e§n¡n°TÓ&:Ñ:ˆAØ—H‘H˜Q˜q™S“MˆEà�x  !¡‘}Ò$ØØ�x  !¡‘}Ò$Ø %�˜˜1™‘Ü&Ð&àˆHóW ðZ r   c           	      óÂ  — | j                   |j                   k(  r | j                   j                  j                  sJ ‚t        | |«      }|�|S | j                   }|j                  }| j                  «       \  }} |j                  «       \  }}|j                  j                  ||«      }|j                  j                  | j                  |j                  «      }|j                  j                  }	t        |«      D ]I  }
|	|j                  j                  t        | |
«      j                  t        ||
«      j                  «      z  }	ŒK t        | j                  «       |j                  «       «      D ��cg c]  \  }}t        ||«      ‘Œ }}}t        |«      }d}d}	 t        |«      }|	|z  dk(  rt        |«      }|	|z  dk(  rŒ| j!                  |«      }|j!                  |«      }	 t#        |||||«      }|€Œ]|j'                  |«      j!                  |«      }|dk(  r|}|}Œ‡t)        |||«      }||z  }||k(  s|}Œ¢|j                  «       d   }| j+                  |«      \  }}|j+                  |«      \  }}|sR|sP|j                  dk  r| }|j'                  |«      }|j'                  ||z  «      }|j'                  ||z  «      }|||fS �Œ2c c}}w # t$        $ r d}Y �ŒGw xY w)aþ  
    Compute the GCD of two polynomials in `\mathbb{Z}[x_0, \ldots, x_{k-1}]`
    using a modular algorithm.

    The algorithm computes the GCD of two multivariate integer polynomials
    `f` and `g` by calculating the GCD in
    `\mathbb{Z}_p[x_0, \ldots, x_{k-1}]` for suitable primes `p` and then
    reconstructing the coefficients with the Chinese Remainder Theorem. To
    compute the multivariate GCD over `\mathbb{Z}_p` the recursive
    subroutine :func:`_modgcd_multivariate_p` is used. To verify the result in
    `\mathbb{Z}[x_0, \ldots, x_{k-1}]`, trial division is done, but only for
    candidates which are very likely the desired GCD.

    Parameters
    ==========

    f : PolyElement
        multivariate integer polynomial
    g : PolyElement
        multivariate integer polynomial

    Returns
    =======

    h : PolyElement
        GCD of the polynomials `f` and `g`
    cff : PolyElement
        cofactor of `f`, i.e. `\frac{f}{h}`
    cfg : PolyElement
        cofactor of `g`, i.e. `\frac{g}{h}`

    Examples
    ========

    >>> from sympy.polys.modulargcd import modgcd_multivariate
    >>> from sympy.polys import ring, ZZ

    >>> R, x, y = ring("x, y", ZZ)

    >>> f = x**2 - y**2
    >>> g = x**2 + 2*x*y + y**2

    >>> h, cff, cfg = modgcd_multivariate(f, g)
    >>> h, cff, cfg
    (x + y, x - y, x + y)

    >>> cff * h == f
    True
    >>> cfg * h == g
    True

    >>> R, x, y, z = ring("x, y, z", ZZ)

    >>> f = x*z**2 - y*z**2
    >>> g = x**2*z + z

    >>> h, cff, cfg = modgcd_multivariate(f, g)
    >>> h, cff, cfg
    (z, x*z - y*z, x**2 + 1)

    >>> cff * h == f
    True
    >>> cfg * h == g
    True

    References
    ==========

    1. [Monagan00]_
    2. [Brown71]_

    See also
    ========

    _modgcd_multivariate_p

    r*   r   )r   r   r?   r   rX   r@   r+   r   r   r4   rr   r’   Údegreesru   r¬   r   r   r°   r   r   rŽ   rC   )r   r   rD   r   r`   rE   rF   rG   r,   rx   r<   ÚfdegÚgdegr²   r³   rI   r"   r    r!   r-   rJ   rK   rL   rM   rN   rO   rP   rQ   rR   s                                r   Úmodgcd_multivariaterÇ   '  s§  € ð\ �6‰6�Q—V‘VÒ §¡§¡× 3Ò 3Ð3Ð3ä˜!˜QÓ€FØÐØˆà�6‰6€DØ�
‰
€Að �K‰K‹M�E€BˆØ�K‰K‹M�E€BˆØ	�‰�‰˜˜RÓ	 €Bà�K‰K�O‰O˜AŸD™D !§$¡$Ó'€Eà—‘—‘€IÜ�1‹Xò EˆØ�T—[‘[—_‘_¤U¨1¨a£[§^¡^´U¸1¸a³[·^±^ÓDÑD‰	ðEô 36°a·i±i³kÀ1Ç9Á9Ã;Ó2O×P¡J D¨$”�D˜$•ÐP€HÑPÜ�X“€Ià	€AØ	€Aà
Ü�a‹LˆØ˜!‰m˜qÒ Ü˜!“ˆAð ˜!‰m˜qÓ ð �^‰^˜AÓˆØ�^‰^˜AÓˆð	ä'¨¨B°°8¸YÓGˆBð
 ˆ:Øà�]‰]˜5Ó!×.Ñ.¨qÓ1ˆØ�Š6ØˆAØˆFØä;¸BÀÈÈ1ÓMˆØ	ˆQ‰ˆà�VŠ|ØˆFØà�L‰L‹N˜1ÑˆØ—U‘U˜1“X‰
ˆˆdØ—U‘U˜1“X‰
ˆˆdÙ™DØ�t‰t�aŠxØ�S�Ø—‘˜RÓ ˆAØ—/‘/ "¨¡(Ó+ˆCØ—/‘/ "¨¡(Ó+ˆCØ�c˜3�;ÐñQ ùó Qøô"  ò 	ØˆAÚð	ús   Å.K	Ç!K ËKËKc                 óÌ   — | j                   }t        | j                  «       |j                  «       ||j                  «      \  }}|j	                  |«      |j	                  |«      fS )z_
    Compute `\frac f g` modulo `p` for two univariate polynomials over
    `\mathbb Z_p`.
    )r   r   Úto_denser   r]   )r   r   r"   r   ÚdensequoÚdenserems         r   Ú_gf_divrÌ   º  sO   € ð
 �6‰6€DÜ §
¡
£¨a¯j©j«l¸A¸t¿{¹{ÓKÑ€HˆhØ�?‰?˜8Ó$ d§o¡o°hÓ&?Ð?Ð?r   c                 óÎ  — | j                   }|j                  }|j                  «       }|dz  }||z
  dz
  }||j                  }	}| |j                  }}
|
j                  «       |kD  rVt        ||
|«      d   }|
|||
z  z
  j                  |«      }
}||	||z  z
  j                  |«      }}	|
j                  «       |kD  rŒV|
|}}|j                  «       |kD  st        |||«      dk7  ry|j                  }|dk7  rR|j                  ||«      }|j                  |«      j                  |«      }|j                  |«      j                  |«      }|j                  «       } ||«       ||«      z  S )a  
    Reconstruct a rational function `\frac a b` in `\mathbb Z_p(t)` from

    .. math::

        c = \frac a b \; \mathrm{mod} \, m,

    where `c` and `m` are polynomials in `\mathbb Z_p[t]` and `m` has
    positive degree.

    The algorithm is based on the Euclidean Algorithm. In general, `m` is
    not irreducible, so it is possible that `b` is not invertible modulo
    `m`. In that case ``None`` is returned.

    Parameters
    ==========

    c : PolyElement
        univariate polynomial in `\mathbb Z[t]`
    p : Integer
        prime number
    m : PolyElement
        modulus, not necessarily irreducible

    Returns
    =======

    frac : FracElement
        either `\frac a b` in `\mathbb Z(t)` or ``None``

    References
    ==========

    1. [Hoeij04]_

    é   r*   r   N)r   r   r   r   r   rÌ   r   r(   r   r   r   Úto_field)Úcr"   rI   r   r   ÚMr¥   ÚDÚr0Ús0Úr1Ús1r^   r~   r˜   Úlcr&   Úfields                     r   Ú!_rational_function_reconstructionrÙ   Ä  sT  € ðJ �6‰6€DØ�[‰[€FØ	�‰‹
€AØ	ˆQ‰€AØ	ˆA‰�‰	€Aà�—	‘	ˆ€BØ�—‘ˆ€Bà
�)‰)‹+˜Š/Ü�b˜"˜aÓ  Ñ#ˆØ�b˜3˜r™6‘k×/Ñ/°Ó2ˆBˆØ�b˜3˜r™6‘k×/Ñ/°Ó2ˆBˆð �)‰)‹+˜‹/ð
 ˆr€q€AØ‡x�xƒz�A‚~œ  A qÓ)¨QÒ.Øà	
�‰€BØ	ˆQ‚wØ—‘˜b !Ó$ˆØ�L‰L˜Ó×,Ñ,¨QÓ/ˆØ�L‰L˜Ó×,Ñ,¨QÓ/ˆà�M‰M‹O€Eá�‹8‘e˜A“hÑÐr   c                 ó,  — |j                   }| j                  «       D ]t  \  }}|dk(  rt        |||«      }|sV y|j                  j                   }|j	                  |«      j                  «       D ]  \  }	}
t        |
||«      }|s  y|||	<   Œ |||<   Œv |S )aù  
    Reconstruct every coefficient `c_h` of a polynomial `h` in
    `\mathbb Z_p(t_k)[t_1, \ldots, t_{k-1}][x, z]` from the corresponding
    coefficient `c_{h_m}` of a polynomial `h_m` in
    `\mathbb Z_p[t_1, \ldots, t_k][x, z] \cong \mathbb Z_p[t_k][t_1, \ldots, t_{k-1}][x, z]`
    such that

    .. math::

        c_{h_m} = c_h \; \mathrm{mod} \, m,

    where `m \in \mathbb Z_p[t]`.

    The reconstruction is based on the Euclidean Algorithm. In general, `m`
    is not irreducible, so it is possible that this fails for some
    coefficient. In that case ``None`` is returned.

    Parameters
    ==========

    hm : PolyElement
        polynomial in `\mathbb Z[t_1, \ldots, t_k][x, z]`
    p : Integer
        prime number, modulus of `\mathbb Z_p`
    m : PolyElement
        modulus, polynomial in `\mathbb Z[t]`, not necessarily irreducible
    ring : PolyRing
        `\mathbb Z(t_k)[t_1, \ldots, t_{k-1}][x, z]`, `h` will be an
        element of this ring
    k : Integer
        index of the parameter `t_k` which will be reconstructed

    Returns
    =======

    h : PolyElement
        reconstructed polynomial in
        `\mathbb Z(t_k)[t_1, \ldots, t_{k-1}][x, z]` or ``None``

    See also
    ========

    _rational_function_reconstruction

    r   N)r   rY   rÙ   r   Údrop_to_ground)rK   r"   rI   r   r`   rL   rb   r5   ÚcoeffhÚmonrÐ   rG   s               r   Ú$_rational_reconstruction_func_coeffsrÞ     s©   € ð\ 	�	‰	€AàŸ™›ò ‰ˆˆuØ�Š6Ü6°u¸aÀÓCˆFáÙð —[‘[×%Ñ%ˆFØ×.Ñ.¨qÓ1×;Ñ;Ó=ò !‘��QÜ6°q¸!¸QÓ?�áÚà ��s’ð!ð ˆˆ%Šð#ð& €Hr   c                 óî   — | j                   }t        | j                  «       |j                  «       ||j                  «      \  }}}|j	                  |«      |j	                  |«      |j	                  |«      fS )zÛ
    Extended Euclidean Algorithm for two univariate polynomials over
    `\mathbb Z_p`.

    Returns polynomials `s, t` and `h`, such that `h` is the GCD of `f` and
    `g` and `sf + tg = h \; \mathrm{mod} \, p`.

    )r   r
   rÉ   r   r]   )r   r   r"   r   ÚsÚtrL   s          r   Ú	_gf_gcdexrâ   L  s[   € ð �6‰6€DÜ�q—z‘z“| Q§Z¡Z£\°1°d·k±kÓB�G€A€qˆ!Ø�?‰?˜1Ó˜tŸ™¨qÓ1°4·?±?À1Ó3EÐEÐEr   c                 óÀ   — | j                   }|j                  |«      }|j                  |«      }| j                  |«      j	                  ||g«      j                  |«      S )a  
    Compute the reduced representation of a polynomial `f` in
    `\mathbb Z_p[z] / (\check m_{\alpha}(z))[x]`

    Parameters
    ==========

    f : PolyElement
        polynomial in `\mathbb Z[x, z]`
    minpoly : PolyElement
        polynomial `\check m_{\alpha} \in \mathbb Z[z]`, not necessarily
        irreducible
    p : Integer
        prime number, modulus of `\mathbb Z_p`

    Returns
    =======

    ftrunc : PolyElement
        polynomial in `\mathbb Z[x, z]`, reduced modulo
        `\check m_{\alpha}(z)` and `p`

    )r   r_   Ú
ground_newr   r$   )r   Úminpolyr"   r   Úp_s        r   Ú_truncrç   Z  sT   € ð0 �6‰6€DØ×Ñ˜tÓ$€GØ	�‰˜Ó	€Bà�>‰>˜!Ó× Ñ  '¨2 Ó/×<Ñ<¸QÓ?Ð?r   c                 ó  — | j                   }t        | ||«      } t        |||«      }|r£| }|j                  d«      }t        |j	                  |«      ||«      \  }}}	|	dk(  sy	 |j                  d«      }
|
|k  rnK||j	                  |«      z  j                  |«      }t        ||j                  |
|z
  df«      |z  z
  ||«      }Œb|} |}|rŒ£t        |j	                  | «      ||«      d   j                  |«      }t        | |z  ||«      S )a
  
    Compute the monic GCD of two univariate polynomials in
    `\mathbb{Z}_p[z]/(\check m_{\alpha}(z))[x]` with the Euclidean
    Algorithm.

    In general, `\check m_{\alpha}(z)` is not irreducible, so it is possible
    that some leading coefficient is not invertible modulo
    `\check m_{\alpha}(z)`. In that case ``None`` is returned.

    Parameters
    ==========

    f, g : PolyElement
        polynomials in `\mathbb Z[x, z]`
    minpoly : PolyElement
        polynomial in `\mathbb Z[z]`, not necessarily irreducible
    p : Integer
        prime number, modulus of `\mathbb Z_p`

    Returns
    =======

    h : PolyElement
        GCD of `f` and `g` in `\mathbb Z[z, x]` or ``None``, coefficients
        are in `\left[ -\frac{p-1} 2, \frac{p-1} 2 \right]`

    r   r*   N)r   rç   r   râ   Údmp_LCr_   r   )r   r   rå   r"   r   r$   r%   r&   Ú_r+   r'   r^   Úlcfinvs                r   Ú_euclidean_algorithmrì   y  s  € ð8 �6‰6€Däˆq�'˜1Ó€AÜˆq�'˜1Ó€Aá
ØˆØ�h‰h�q‹kˆÜ! $§+¡+¨a£.°'¸1Ó=‰ˆˆq�#à�aŠxØàØ—Z‘Z “]ˆFØ˜Š|ØØ˜4Ÿ;™; sÓ+Ñ+×5Ñ5°dÓ;ˆCÜ˜˜qŸ{™{¨F°S©L¸!Ð+<Ó=¸cÑAÑAÀ7ÈAÓNˆCð ð ˆØˆò! ô$ �t—{‘{ 1“~ w°Ó2°1Ñ5×>Ñ>¸tÓD€Fä�!�f‘*˜g qÓ)Ð)r   c                 óV  — | j                   }|j                  |j                  d   |j                  d   f¬«      }|j                  |«      }| }|j	                  «       }|j	                  «       }|j	                  d«      }	t        |«      j                  |«      }
|j                  }|�r||k\  rüt        |«      j                  |«      }||
z  |j                  ||z
  df«      |z  z
  }|r|j                  |«      }|j	                  d«      }|r…||	k\  r€t        |j                  |«      «      j                  |«      }|j                  |«      |j                  d||	z
  f«      |z  z
  }|r|j                  |«      }|j	                  d«      }|r||	k\  rŒ€|j	                  «       }|r||k\  rŒü|S )a=  
    Check if `h` divides `f` in
    `\mathbb K[t_1, \ldots, t_k][z]/(m_{\alpha}(z))`, where `\mathbb K` is
    either `\mathbb Q` or `\mathbb Z_p`.

    This algorithm is based on pseudo division and does not use any
    fractions. By default `\mathbb K` is `\mathbb Q`, if a prime number `p`
    is given, `\mathbb Z_p` is chosen instead.

    Parameters
    ==========

    f, h : PolyElement
        polynomials in `\mathbb Z[t_1, \ldots, t_k][x, z]`
    minpoly : PolyElement
        polynomial `m_{\alpha}(z)` in `\mathbb Z[t_1, \ldots, t_k][z]`
    p : Integer or None
        if `p` is given, `\mathbb K` is set to `\mathbb Z_p` instead of
        `\mathbb Q`, default is ``None``

    Returns
    =======

    rem : PolyElement
        remainder of `\frac f h`

    References
    ==========

    .. [1] [Hoeij02]_

    r*   r   rV   )
r   r\   rW   r_   r   rn   r   r   r   r   )r   rL   rå   r"   r   Úzxringr$   r'   r´   ÚdegmÚlchÚlcmÚlcrems                r   Ú_trial_divisionró   ±  s†  € ðB �6‰6€Dà�Z‰Z §¡¨a¡°$·,±,¸q±/Ð BˆZÓC€Fà×Ñ˜tÓ$€Gà
€Cà�Z‰Z‹\€FØ�8‰8‹:€DØ�>‰>˜!Ó€Dä
ˆa‹&�/‰/˜$Ó
€CØ
�*‰*€Câ
�&˜D’.ä�C“×!Ñ! $Ó'ˆØ�#‰g˜Ÿ™ V¨d¡]°AÐ$6Ó7¸Ñ=Ñ=ˆÙØ×"Ñ" 1Ó%ˆCØ—‘˜A“ˆá�f ’nä˜Ÿ™ VÓ,Ó-×6Ñ6°tÓ<ˆEØ—.‘. Ó%¨×(9Ñ(9¸1¸fÀt¹mÐ:LÓ(MÈeÑ(SÑSˆCÙØ×&Ñ& qÓ)�Ø—Z‘Z “]ˆFñ �f “nð —‘“ˆñ! �&˜D“.ð$ €Jr   c                 ó
  — | j                   j                  | j                   j                  j                   j                  |«      ¬«      }|j                  }| j                  «       D ]  \  }}|j                  ||«      ||<   Œ |S )z[
    Evaluate a polynomial `f` at `a` in the `i`-th variable of the ground
    domain.
    ©r   )r   r\   r   Údropr   rY   rt   )r   r<   r~   r   r¿   rb   r5   s          r   Ú_evaluate_groundr÷   ö  sn   € ð
 �6‰6�<‰<˜qŸv™vŸ}™}×1Ñ1×6Ñ6°qÓ9ˆ<Ó:€DØ	�‰€BàŸ™›ò )‰ˆˆuØ—N‘N 1 aÓ(ˆˆ5Š	ð)ð €Ir   c           
      ó  — | j                   }|j                  }t        |t        «      r|j                  }nt        | |||«      S |dk(  r|j                   j                  «       }nR|j                   j                  |dz
  «      }|j                  |j                  j                   j                  «       ¬«      }|j                  |¬«      }d}	d}
|j                  | «      |j                  |«      z  }|j                  }g }g }g }t        t        |«      «      }|�rht        j                  |d«      d   }|j                  |«       |dk(  r|j!                  |dz
  |«      |z  dk(  }n'|j!                  |dz
  |«      j#                  |«      dk(  }|rŒxt%        ||dz
  |«      }t%        ||dz
  |«      }|j'                  ||j                  |«      g«      dk(  rŒ¾t%        | |dz
  |«      }t%        ||dz
  |«      }t)        ||||«      }|€|
dz  }
|
|	kD  ryŒú|dk(  r|S |j+                  «       gdg|dz
  z  z   }|dkD  rO|j-                  «       D ]<  \  }}|d   |d   k(  sŒ|j.                  t1        |dd «      kD  sŒ.|j.                  |dd Œ> |g}|g}|dk(  r%|j                  j3                  «       j4                  }n.|j                  j                  j3                  «       j4                  }|j                   j6                  d   }t9        |||«      D ]6  \  }} }!|!|k(  sŒ|j;                  |«       |j;                  | «       |||z
  z  }Œ8 |j#                  |«      }|j;                  |«       |j;                  |«       |j;                  |«       |	dz  }	t=        ||||dz
  |d¬«      }"t?        |"||||dz
  «      }"|"€�Œ |dk(  r™|j                  j@                  }#|#j                   j4                  }$|"jC                  «       D ]Y  }|#j                   jE                  tG        |$jI                  «       |jJ                  jI                  «       ||#j                  «      «      }$Œ[ n·|j                  j                  j@                  }#|#j                   j4                  }$|"jC                  «       D ]n  }|jC                  «       D ]Y  }%|#j                   jE                  tG        |$jI                  «       |%jJ                  jI                  «       ||#j                  «      «      }$Œ[ Œp |jM                  |$j#                  |«      «      }$ ||"jO                  |$«      jQ                  «       «      j#                  |«      }"tS        | |"||«      stS        ||"||«      s|"S |r�Œhy)a—  
    Compute the GCD of two polynomials `f` and `g` in
    `\mathbb Z_p(t_1, \ldots, t_k)[z]/(\check m_\alpha(z))[x]`.

    The algorithm reduces the problem step by step by evaluating the
    polynomials `f` and `g` at `t_k = a` for suitable `a \in \mathbb Z_p`
    and then calls itself recursively to compute the GCD in
    `\mathbb Z_p(t_1, \ldots, t_{k-1})[z]/(\check m_\alpha(z))[x]`. If these
    recursive calls are successful, the GCD over `k` variables is
    interpolated, otherwise the algorithm returns ``None``. After
    interpolation, Rational Function Reconstruction is used to obtain the
    correct coefficients. If this fails, a new evaluation point has to be
    chosen, otherwise the desired polynomial is obtained by clearing
    denominators. The result is verified with a fraction free trial
    division.

    Parameters
    ==========

    f, g : PolyElement
        polynomials in `\mathbb Z[t_1, \ldots, t_k][x, z]`
    minpoly : PolyElement
        polynomial in `\mathbb Z[t_1, \ldots, t_k][z]`, not necessarily
        irreducible
    p : Integer
        prime number, modulus of `\mathbb Z_p`

    Returns
    =======

    h : PolyElement
        primitive associate in `\mathbb Z[t_1, \ldots, t_k][x, z]` of the
        GCD of the polynomials `f` and `g`  or ``None``, coefficients are
        in `\left[ -\frac{p-1} 2, \frac{p-1} 2 \right]`

    References
    ==========

    1. [Hoeij04]_

    r*   rõ   r   NT)r•   )*r   r   r�   r   rX   rì   rÏ   rÛ   r\   ré   r   r¬   r4   r­   r®   r¯   rt   r   r÷   r$   Ú_func_field_modgcd_pr   rY   ÚLMÚtupleÚget_ringr   r3   r’   r›   r™   rÞ   rØ   Ú
itercoeffsr]   r   rÉ   r—   Ú
domain_newr   Úas_exprró   )&r   r   rå   r"   r   r   r`   ÚqdomainÚqringr9   r¼   r,   r}   r“   r½   ÚLMlistr¾   r~   ÚtestÚgammaaÚminpolyar¿   rÀ   rÁ   rú   rb   r5   Úevalpoints_aÚheval_arI   rá   r˜   ÚhbÚLMhbrL   r#   ÚdenrÐ   s&                                         r   rù   rù     s  € ðT �6‰6€DØ�[‰[€Fä�&œ.Ô)Ø�L‰L‰ä# A q¨'°1Ó5Ð5àˆA‚vØ—+‘+×&Ñ&Ó(‰à—+‘+×,Ñ,¨Q°©UÓ3ˆØ—-‘- w§~¡~×':Ñ':×'CÑ'CÓ'E�-ÓFˆà�J‰J˜gˆJÓ&€Eà	€AØ	€Að �K‰K˜‹N˜TŸ[™[¨›^Ñ+€Eà�J‰J€Eà€JØ€EØ€FÜ”%˜“(‹^€Fâ
Ü�M‰M˜& !Ó$ QÑ'ˆØ�‰�aÔà�Š6Ø—>‘> ! A¡# qÓ)¨AÑ-°Ñ2‰Dà—>‘> ! A¡# qÓ)×6Ñ6°qÓ9¸QÑ>ˆDáØä! %¨¨1©¨aÓ0ˆÜ# G¨Q¨q©S°!Ó4ˆà�:‰:�x §¡¨Q£Ð0Ó1°QÒ6Øä˜a  1¡ aÓ(ˆÜ˜a  1¡ aÓ(ˆô " " b¨(°AÓ6ˆàˆ:Ø�‰FˆAØ�1ŠuØØà�Š7ØˆIà�i‰i‹kˆ]˜a˜S ! A¡#™YÑ&ˆØˆqŠ5Ø "§¡£ò &‘��uØ˜‘8˜r !™uÓ$¨¯©´E¸"¸Q¸R¸&³MÓ)AØ"ŸX™X�B�q�r‘Fð&ð �sˆØ�$ˆØ�Š6Ø—‘×%Ñ%Ó'×+Ñ+‰Aà—‘×#Ñ#×,Ñ,Ó.×2Ñ2ˆAà�F‰F�K‰K˜‰Nˆä˜z¨5°&Ó9ò 	‰KˆAˆr�4Ø�r‹zØ×#Ñ# AÔ&Ø—‘˜rÔ"Ø�a˜!‘e‘‘ð		ð �N‰N˜1ÓˆØ×Ñ˜!ÔØ�‰�RÔØ�‰�bÔØ	ˆQ‰ˆô & l°G¸TÀ1ÀQÁ3ÈÐRVÔWˆô 1°°A°q¸%ÀÀ1ÁÓEˆàˆ9Ùà�Š6Ø—,‘,×$Ñ$ˆCØ—(‘(—,‘,ˆCàŸ™›ò (�Ø—h‘h×)Ñ)¬&°·±³ÀÇÁ×AUÑAUÓAWØ˜3Ÿ:™:ó+'ó (‘ñ(ð
 —,‘,×%Ñ%×+Ñ+ˆCØ—(‘(—,‘,ˆCàŸ™›ò ,�Ø×)Ñ)Ó+ò ,�AØŸ(™(×-Ñ-¬f°S·\±\³^ÀQÇWÁW×EUÑEUÓEWØ˜sŸz™zó/+ó ,‘Cñ,ð,ð
 ×Ñ˜s×/Ñ/°Ó2Ó3ˆÙ�—‘˜cÓ"×*Ñ*Ó,Ó-×:Ñ:¸1Ó=ˆä˜q ! W¨aÔ0¼ÈÈAÈwÐXYÔ9ZØˆHóu ðx r   c                 óv  — | dk  r| |z  } ||j                   }}| |j                  }}t        |dz  «      }t        |«      |k\  r(||z  }||||z  z
  }}||||z  z
  }}t        |«      |k\  rŒ(t	        t        |«      «      |k\  ry|dk  r| | }
}	n|dkD  r||}
}	ny|j                  «       } ||	«       ||
«      z  S )aÌ  
    Reconstruct a rational number `\frac a b` from

    .. math::

        c = \frac a b \; \mathrm{mod} \, m,

    where `c` and `m` are integers.

    The algorithm is based on the Euclidean Algorithm. In general, `m` is
    not a prime number, so it is possible that `b` is not invertible modulo
    `m`. In that case ``None`` is returned.

    Parameters
    ==========

    c : Integer
        `c = \frac a b \; \mathrm{mod} \, m`
    m : Integer
        modulus, not necessarily prime
    domain : IntegerRing
        `a, b, c` are elements of ``domain``

    Returns
    =======

    frac : Rational
        either `\frac a b` in `\mathbb Q` or ``None``

    References
    ==========

    1. [Wang81]_

    r   rÎ   N)r   r   r   ÚintÚabsÚ	get_field)rÐ   rI   r   rÓ   rÔ   rÕ   rÖ   rH   r^   r~   r˜   rØ   s               r   Ú _integer_rational_reconstructionr  ª  sÞ   € ðH 	ˆ1‚uØ	ˆQ‰ˆà�—‘ˆ€BØ�—
‘
ˆ€Bä��Q‘‹K€Eä
ˆb‹'�UÒ
Ø�B‰hˆØ�R˜#˜b™&‘[ˆBˆØ�R˜#˜b™&‘[ˆBˆô ˆb‹'�UÓ
ô
 Œ3ˆr‹7ƒ|�uÒØà	ˆA‚vØˆs�R�Cˆ1‰Ø	ˆaŠØ�2ˆ1‰àà×ÑÓ€Eá�‹8‘e˜A“hÑÐr   c                 ó  — |j                   }t        |j                  t        «      rt        }|j                  j
                  }nt        }| j
                  j                  }| j                  «       D ]  \  }} ||||«      }|s y|||<   Œ |S )aù  
    Reconstruct every rational coefficient `c_h` of a polynomial `h` in
    `\mathbb Q[t_1, \ldots, t_k][x, z]` from the corresponding integer
    coefficient `c_{h_m}` of a polynomial `h_m` in
    `\mathbb Z[t_1, \ldots, t_k][x, z]` such that

    .. math::

        c_{h_m} = c_h \; \mathrm{mod} \, m,

    where `m \in \mathbb Z`.

    The reconstruction is based on the Euclidean Algorithm. In general,
    `m` is not a prime number, so it is possible that this fails for some
    coefficient. In that case ``None`` is returned.

    Parameters
    ==========

    hm : PolyElement
        polynomial in `\mathbb Z[t_1, \ldots, t_k][x, z]`
    m : Integer
        modulus, not necessarily prime
    ring : PolyRing
        `\mathbb Q[t_1, \ldots, t_k][x, z]`, `h` will be an element of this
        ring

    Returns
    =======

    h : PolyElement
        reconstructed polynomial in `\mathbb Q[t_1, \ldots, t_k][x, z]` or
        ``None``

    See also
    ========

    _integer_rational_reconstruction

    N)r   r�   r   r   Ú#_rational_reconstruction_int_coeffsr   r  rY   )	rK   rI   r   rL   Úreconstructionr   rb   r5   rÜ   s	            r   r  r  ê  s   € ðR 	�	‰	€Aä�$—+‘+œ~Ô.Ü<ˆØ—‘×!Ñ!‰ä9ˆØ—‘—‘ˆàŸ™›ò ‰ˆˆuÙ  q¨&Ó1ˆáÙàˆˆ%Šðð €Hr   c                 óÊ  — | j                   }|j                  }t        |t        «      rS|j                  }|j                   j                  |j                  j                  «       ¬«      }|j                  |¬«      }n,d}|j                  |j                  j                  «       ¬«      }| j                  «       \  }} |j                  «       \  }	}|j                  | «      |j                  |«      z  }
|j                  }d}g }g }g }	 t        |«      }|
j                  |«      dk(  rŒ!|dk(  r	||z  dk(  }n|j                  |«      dk(  }|rŒF| j                  |«      }|j                  |«      }|j                  |«      }t        ||||«      }|€ŒŠ|dk(  r|j                  S |j                  «       gdg|z  z   }|dkD  rO|j                  «       D ]<  \  }}|d   |d   k(  sŒ|j                   t#        |dd «      kD  sŒ.|j                   |dd Œ> |}|}t%        |||«      D ]  \  }}}||k(  sŒt'        ||||«      }||z  }Œ! |j)                  |«       |j)                  |«       |j)                  |«       t+        |||«      }|€�Œ~|dk(  r|j-                  «       d   }ni|j                  j                  }|j/                  «       D ]/  }|j                  j1                  ||j-                  «       d   «      }Œ1 |j3                  |«      }|j5                  |«      }|j                  «       d   }t7        | j3                  |«      ||«      st7        |j3                  |	«      ||«      s|S �Œ_)aí  
    Compute the GCD of two polynomials in
    `\mathbb Q(t_1, \ldots, t_k)[z]/(m_{\alpha}(z))[x]` using a modular
    algorithm.

    The algorithm computes the GCD of two polynomials `f` and `g` by
    calculating the GCD in
    `\mathbb Z_p(t_1, \ldots, t_k)[z] / (\check m_{\alpha}(z))[x]` for
    suitable primes `p` and the primitive associate `\check m_{\alpha}(z)`
    of `m_{\alpha}(z)`. Then the coefficients are reconstructed with the
    Chinese Remainder Theorem and Rational Reconstruction. To compute the
    GCD over `\mathbb Z_p(t_1, \ldots, t_k)[z] / (\check m_{\alpha})[x]`,
    the recursive subroutine ``_func_field_modgcd_p`` is used. To verify the
    result in `\mathbb Q(t_1, \ldots, t_k)[z] / (m_{\alpha}(z))[x]`, a
    fraction free trial division is used.

    Parameters
    ==========

    f, g : PolyElement
        polynomials in `\mathbb Z[t_1, \ldots, t_k][x, z]`
    minpoly : PolyElement
        irreducible polynomial in `\mathbb Z[t_1, \ldots, t_k][z]`

    Returns
    =======

    h : PolyElement
        the primitive associate in `\mathbb Z[t_1, \ldots, t_k][x, z]` of
        the GCD of `f` and `g`

    Examples
    ========

    >>> from sympy.polys.modulargcd import _func_field_modgcd_m
    >>> from sympy.polys import ring, ZZ

    >>> R, x, z = ring('x, z', ZZ)
    >>> minpoly = (z**2 - 2).drop(0)

    >>> f = x**2 + 2*x*z + 2
    >>> g = x + z
    >>> _func_field_modgcd_m(f, g, minpoly)
    x + z

    >>> D, t = ring('t', ZZ)
    >>> R, x, z = ring('x, z', D)
    >>> minpoly = (z**2-3).drop(0)

    >>> f = x**2 + (t + 1)*x*z + 3*t
    >>> g = x*z + 3*t
    >>> _func_field_modgcd_m(f, g, minpoly)
    x + t*z

    References
    ==========

    1. [Hoeij04]_

    See also
    ========

    _func_field_modgcd_p

    rõ   r   r*   N)r   r   r�   r   rX   r\   r  r@   ré   r   r   r   rù   r   r   rY   rú   rû   r’   rŽ   r›   r  Úclear_denomsrý   rñ   r   r_   ró   )r   r   rå   r   r   r`   ÚQQdomainÚQQringrE   rF   r,   r}   r"   ÚprimesÚhplistr  r  r    r!   Úminpolypr-   rú   rb   r5   rK   rI   r8   r7   ÚLMhqrL   r
  s                                  r   Ú_func_field_modgcd_mr  '  s3  € ðD �6‰6€DØ�[‰[€Fä�&œ.Ô)Ø�L‰LˆØ—;‘;×$Ñ$¨F¯M©M×,CÑ,CÓ,EÐ$ÓFˆØ—‘ 8�Ó,‰àˆØ—‘ 4§;¡;×#8Ñ#8Ó#:�Ó;ˆà�K‰K‹M�E€BˆØ�K‰K‹M�E€Bˆð �K‰K˜‹N˜TŸ[™[¨›^Ñ+€Eà�J‰J€Eà	€AØ€FØ€FØ€Fà
Ü�a‹Lˆà×Ñ˜aÓ  AÒ%Øà�Š6Ø˜A‘I ‘N‰Dà×&Ñ& qÓ)¨QÑ.ˆDáØà�^‰^˜AÓˆØ�^‰^˜AÓˆØ×'Ñ'¨Ó*ˆä! " b¨(°AÓ6ˆàˆ:Øà�Š7Ø—8‘8ˆOà�i‰i‹kˆ]˜a˜S ™UÑ"ˆØˆqŠ5Ø "§¡£ò &‘��uØ˜‘8˜r !™uÓ$¨¯©´E¸"¸Q¸R¸&³MÓ)AØ"ŸX™X�B�q�r‘Fð&ð ˆØˆä˜v v¨vÓ6ò 	‰KˆAˆr�4Ø�r‹zÜCÀBÈÈAÈqÓQ�Ø�Q‘‘ð	ð
 	�‰�aÔØ�‰�bÔØ�‰�bÔä0°°Q¸Ó?ˆàˆ:Ùà�Š6Ø—‘Ó! !Ñ$‰Aà—-‘-×#Ñ#ˆCØŸ™›ò F�Ø—m‘m×'Ñ'¨¨U×-?Ñ-?Ó-AÀ!Ñ-DÓE‘ðFà—‘˜cÓ"ˆAð �J‰J�tÓˆØ�K‰K‹M˜!Ñˆä §¡¨RÓ 0°!°WÔ=Ü˜AŸL™L¨Ó,¨a°Ô9ØˆHñ r   c                 ó   — |j                   }t        |j                  t        «      r|j                  j                  }n|j                  }|j                  }| j                  «       D ]6  }|j                  «       D ]!  }|sŒ|j                  ||j                  «      }Œ# Œ8 | j                  «       D ]Ì  \  }}|j                  «       }|j                  j                  }t        |j                  t        «      r|j                  |dd «      }t        |«      }	t        |	«      D ]Z  }
||
   sŒ	|j                  ||
   |z  «      |z  }|d   |	|
z
  dz
  f|vr|||d   |	|
z
  dz
  f<   ŒC||d   |	|
z
  dz
  fxx   |z  cc<   Œ\ ŒÎ |S )a‚  
    Compute an associate of a polynomial
    `f \in \mathbb Q(\alpha)[x_0, \ldots, x_{n-1}]` in
    `\mathbb Z[x_1, \ldots, x_{n-1}][z] / (\check m_{\alpha}(z))[x_0]`,
    where `\check m_{\alpha}(z) \in \mathbb Z[z]` is the primitive associate
    of the minimal polynomial `m_{\alpha}(z)` of `\alpha` over
    `\mathbb Q`.

    Parameters
    ==========

    f : PolyElement
        polynomial in `\mathbb Q(\alpha)[x_0, \ldots, x_{n-1}]`
    ring : PolyRing
        `\mathbb Z[x_1, \ldots, x_{n-1}][x_0, z]`

    Returns
    =======

    f_ : PolyElement
        associate of `f` in
        `\mathbb Z[x_1, \ldots, x_{n-1}][x_0, z]`

    r*   Nr   )r   r�   r   r   r   rý   Úto_listrñ   ÚdenominatorrY   r   Úlenr4   Úconvert)r   r   Úf_r   r
  r5   rÐ   rb   rI   r9   r<   s              r   Ú_to_ZZ_polyr"  Ã  sl  € ð2 
�‰€Bä�$—+‘+œ~Ô.Ø—‘×#Ñ#‰à—‘ˆà
�*‰*€Cà—‘“ò 5ˆØ—‘“ò 	5ˆAÚØ—j‘j  a§m¡mÓ4‘ñ	5ð5ð
 Ÿ™›ò /‰ˆˆuØ—‘“ˆØ�K‰K�O‰OˆÜ�d—k‘k¤>Ô2Ø—‘˜E ! "˜IÓ&ˆAÜ�‹Jˆä�q“ò 	/ˆAØ�Q‹xØ—N‘N 5¨¡8¨c¡>Ó2°QÑ6�à˜!‘H˜a ™c !™eÐ$¨BÑ.Ø,-�B˜˜a™ ! A¡# a¡%Ð(Ò)à˜˜a™ ! A¡# a¡%Ð(Ó)¨QÑ.Ô)ñ	/ð/ð  €Ir   c                 ó  — |j                   }|j                  }t        | j                  j                   t        «      rt| j                  «       D ]_  \  }}|j                  «       D ]G  \  }}|d   f|z   } ||j                  |«      gdg|d   z  z   «      }	||vr|	||<   Œ;||xx   |	z  cc<   ŒI Œa |S | j                  «       D ]D  \  }}|d   f} ||j                  |«      gdg|d   z  z   «      }	||vr|	||<   Œ8||xx   |	z  cc<   ŒF |S )ar  
    Convert a polynomial
    `f \in \mathbb Z[x_1, \ldots, x_{n-1}][z]/(\check m_{\alpha}(z))[x_0]`
    to a polynomial in `\mathbb Q(\alpha)[x_0, \ldots, x_{n-1}]`,
    where `\check m_{\alpha}(z) \in \mathbb Z[z]` is the primitive associate
    of the minimal polynomial `m_{\alpha}(z)` of `\alpha` over
    `\mathbb Q`.

    Parameters
    ==========

    f : PolyElement
        polynomial in `\mathbb Z[x_1, \ldots, x_{n-1}][x_0, z]`
    ring : PolyRing
        `\mathbb Q(\alpha)[x_0, \ldots, x_{n-1}]`

    Returns
    =======

    f_ : PolyElement
        polynomial in `\mathbb Q(\alpha)[x_0, \ldots, x_{n-1}]`

    r   r*   )r   r   r�   r   r   rY   )
r   r   r   r!  rb   r5   rÝ   ÚcoefrI   rÐ   s
             r   Ú_to_ANP_polyr%  ý  s#  € ð0 �[‰[€FØ	�‰€Bä�!—&‘&—-‘-¤Ô0ØŸK™K›Mò 	‰LˆE�5Ø"Ÿ_™_Ó.ò ‘	��TØ˜1‘X�K #Ñ%�Ù˜FŸM™M¨$Ó/Ð0°A°3°u¸Q±x±<Ñ?Ó@�à˜B‘;Ø�B�q’Eà�q“E˜Q‘J”Eñð	ð( €Ið ŸK™K›Mò 	‰LˆE�5Ø�q‘�ˆAÙ˜Ÿ™ eÓ,Ð-°°°E¸!±H±Ñ<Ó=ˆAà˜‰{Ø��1’à�1“˜‘
”ð	ð €Ir   c                 óv   — |j                   }| j                  «       D ]  \  }}|j                  |«      ||<   Œ |S )zo
    Change representation of the minimal polynomial from ``DMP`` to
    ``PolyElement`` for a given ring.
    )r   Útermsr   )rå   r   Úminpoly_rb   r5   s        r   Ú_minpoly_from_denser)  0  s?   € ð
 �y‰y€HàŸ™›ò -‰ˆˆuØŸ+™+ eÓ,ˆ�Šð-ð €Or   c                 ó†  — | j                   } |j                  t        d|j                  «      Ž }|j                  j                   } || j                  «       «      }|j                  }|j                  «       D ]&  }t        ||«      d   }||j                  k(  sŒ"|| fc S  || j                  |j                  |«      «      fS )z¿
    Compute the content in `x_0` and the primitive part of a polynomial `f`
    in
    `\mathbb Q(\alpha)[x_0, x_1, \ldots, x_{n-1}] \cong \mathbb Q(\alpha)[x_1, \ldots, x_{n-1}][x_0]`.
    r*   r   )r   rÛ   r4   rX   r   rÿ   r   rý   Úfunc_field_modgcdr   r^   r_   )r   Úfringr   r#   r!  rc   r5   s          r   Ú_primitive_in_x0r-  =  s«   € ð �F‰F€EØˆ5×Ñ¤ q¨%¯+©+Ó!6Ð7€DØ
�+‰+×
Ñ
€CÙ	ˆa�i‰i‹kÓ	€BØ�8‰8€Dà—‘“ò ˆÜ   uÓ-¨aÑ0ˆØ�3—7‘7‹?Ø˜�7ŠNðð
 �—‘�t—}‘} UÓ+Ó,Ð,Ð,r   c                 óN  — | j                   }|j                  }|j                  }||j                   k(  r|j                  sJ ‚t	        | |«      }|�|S t        d«      }|j                  |j                  |fz   |j                  j                  «       ¬«      }|dk(  rjt        | |«      }t        ||«      }	|j                  d«      j                  |j                  j                  «       «      }
t        ||	|
«      }t        ||«      }nät!        | «      \  }} t!        |«      \  }}t#        ||«      d   } |j$                  t'        d|«      Ž }t        | |«      }t        ||«      }	t)        |j                  |j                  d«      «      }
t        ||	|
«      }t        ||«      }t!        |«      \  }}||j+                  |«      z  }| |j+                  |«      z  } ||j+                  |«      z  }|j-                  |j.                  «      }|| j1                  |«      |j1                  |«      fS )a  
    Compute the GCD of two polynomials `f` and `g` in
    `\mathbb Q(\alpha)[x_0, \ldots, x_{n-1}]` using a modular algorithm.

    The algorithm first computes the primitive associate
    `\check m_{\alpha}(z)` of the minimal polynomial `m_{\alpha}` in
    `\mathbb{Z}[z]` and the primitive associates of `f` and `g` in
    `\mathbb{Z}[x_1, \ldots, x_{n-1}][z]/(\check m_{\alpha})[x_0]`. Then it
    computes the GCD in
    `\mathbb Q(x_1, \ldots, x_{n-1})[z]/(m_{\alpha}(z))[x_0]`.
    This is done by calculating the GCD in
    `\mathbb{Z}_p(x_1, \ldots, x_{n-1})[z]/(\check m_{\alpha}(z))[x_0]` for
    suitable primes `p` and then reconstructing the coefficients with the
    Chinese Remainder Theorem and Rational Reconstruction. The GCD over
    `\mathbb{Z}_p(x_1, \ldots, x_{n-1})[z]/(\check m_{\alpha}(z))[x_0]` is
    computed with a recursive subroutine, which evaluates the polynomials at
    `x_{n-1} = a` for suitable evaluation points `a \in \mathbb Z_p` and
    then calls itself recursively until the ground domain does no longer
    contain any parameters. For
    `\mathbb{Z}_p[z]/(\check m_{\alpha}(z))[x_0]` the Euclidean Algorithm is
    used. The results of those recursive calls are then interpolated and
    Rational Function Reconstruction is used to obtain the correct
    coefficients. The results, both in
    `\mathbb Q(x_1, \ldots, x_{n-1})[z]/(m_{\alpha}(z))[x_0]` and
    `\mathbb{Z}_p(x_1, \ldots, x_{n-1})[z]/(\check m_{\alpha}(z))[x_0]`, are
    verified by a fraction free trial division.

    Apart from the above GCD computation some GCDs in
    `\mathbb Q(\alpha)[x_1, \ldots, x_{n-1}]` have to be calculated,
    because treating the polynomials as univariate ones can result in
    a spurious content of the GCD. For this ``func_field_modgcd`` is
    called recursively.

    Parameters
    ==========

    f, g : PolyElement
        polynomials in `\mathbb Q(\alpha)[x_0, \ldots, x_{n-1}]`

    Returns
    =======

    h : PolyElement
        monic GCD of the polynomials `f` and `g`
    cff : PolyElement
        cofactor of `f`, i.e. `\frac f h`
    cfg : PolyElement
        cofactor of `g`, i.e. `\frac g h`

    Examples
    ========

    >>> from sympy.polys.modulargcd import func_field_modgcd
    >>> from sympy.polys import AlgebraicField, QQ, ring
    >>> from sympy import sqrt

    >>> A = AlgebraicField(QQ, sqrt(2))
    >>> R, x = ring('x', A)

    >>> f = x**2 - 2
    >>> g = x + sqrt(2)

    >>> h, cff, cfg = func_field_modgcd(f, g)

    >>> h == x + sqrt(2)
    True
    >>> cff * h == f
    True
    >>> cfg * h == g
    True

    >>> R, x, y = ring('x, y', A)

    >>> f = x**2 + 2*sqrt(2)*x*y + 2*y**2
    >>> g = x + sqrt(2)*y

    >>> h, cff, cfg = func_field_modgcd(f, g)

    >>> h == x + sqrt(2)*y
    True
    >>> cff * h == f
    True
    >>> cfg * h == g
    True

    >>> f = x + sqrt(2)*y
    >>> g = x + y

    >>> h, cff, cfg = func_field_modgcd(f, g)

    >>> h == R.one
    True
    >>> cff * h == f
    True
    >>> cfg * h == g
    True

    References
    ==========

    1. [Hoeij04]_

    Úz)rW   r   r*   r   )r   r   rX   Úis_Algebraicr   r   r\   rW   rü   r"  rö   r]   Úmodr  r  r%  r-  r+  rÛ   r4   r)  r_   rA   r   r^   )r   r   r   r   r9   rD   r/  ÚZZringr!  Úg_rå   rL   Úcontx0fÚcontx0gÚcontx0hÚZZring_Úcontx0h_s                    r   r+  r+  R  sî  € ðP �6‰6€DØ�[‰[€FØ�
‰
€Aà�1—6‘6Š>˜f×1Ò1Ð1Ð1ä˜!˜QÓ€FØÐØˆäˆc‹
€Aà�Z‰Z §¡°¨tÑ 3¸F¿M¹M×<RÑ<RÓ<TˆZÓU€FàˆA‚vÜ˜˜FÓ#ˆÜ˜˜FÓ#ˆØ—+‘+˜a“.×+Ñ+¨F¯J©J×,>Ñ,>Ó,@ÓAˆä   R¨Ó1ˆÜ˜˜DÓ!‰ô & aÓ(‰
ˆ�Ü% aÓ(‰
ˆ�Ü# G¨WÓ5°aÑ8ˆà'�&×'Ñ'¬¨q°!«Ð5ˆä˜˜GÓ$ˆÜ˜˜GÓ$ˆÜ% f§j¡j°'·,±,¸q³/ÓBˆä   R¨Ó1ˆÜ˜˜DÓ!ˆä& qÓ)‰ˆ�!Ø	ˆW×Ñ˜dÓ#Ñ#ˆØ	ˆW×Ñ˜dÓ#Ñ#ˆØ	ˆW×Ñ˜dÓ#Ñ#ˆà	�‰�Q—T‘TÓ€Aàˆa�e‰e�A‹h˜Ÿ™˜a›Ð Ð r   )F)N)3Úsympy.core.symbolr   Úsympy.ntheoryr   Úsympy.ntheory.modularr   Úsympy.polys.domainsr   Úsympy.polys.galoistoolsr   r	   r
   r   r   Úsympy.polys.polyerrorsr   Úmpmathr   r­   r   r(   r/   r=   rS   rf   rj   rn   rr   rƒ   rŽ   r™   rª   r°   rÇ   rÌ   rÙ   rÞ   râ   rç   rì   ró   r÷   rù   r  r  r  r"  r%  r)  r-  r+  © r   r   ú<module>rA     sè   ðÝ #Ý #Ý %Ý .÷4õ 4å 3å Û òò,?ò.òB>òB~òB:.òz-ò`2òj	òH5òV`óF>òBQòhVòrPòf@ò?òDCòLFò@ò>5*ópBòJòcòL=ò@:òzYòx7òt0òf
ò-ó*T!r   