+
    ii                     :   ^ RI Ht ^ RIHt ^ RIHt ^ RIHt ^ RIH	t	H
t
HtHtHt ^ RIHt ^ RIHt ^ RItR	 tR
 tR tR tR tR tR tR tR tR tR tR)R ltR tR t R t!R t"R t#R t$R t%R t&R t'R*R lt(R t)R  t*R! t+R" t,R# t-R$ t.R% t/R& t0R' t1R( t2R# )+    )Dummy)	nextprimecrt)PolynomialRing)gf_gcdgf_from_dictgf_gcdexgf_divgf_lcm)ModularGCDFailed)sqrtNc                   V P                   pV '       g,   V'       g$   VP                  VP                  VP                  3# V '       gY   VP                  VP                  P                  8  d   V) VP                  VP                  ) 3# WP                  VP                  3# V'       gY   V P                  VP                  P                  8  d   V ) VP                  ) VP                  3# WP                  VP                  3# R# )zb
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   && v/Users/tonyclaw/.openclaw/workspace/skills/math-calculator/venv/lib/python3.14/site-packages/sympy/polys/modulargcd.py_trivial_gcdr      s    
 66Dyy$))TYY..44$++"""2tyy488)++ii))44$++"""2y$))++hh		))    c                   V P                   P                  pV'       d   T pVP                  4       pVP                  VP                  V4      p VP                  4       pWu8  d   MNWAP                  Wu,
          34      P                  WdP                  ,          4      ,
          P                  V4      pKf  Tp TpK  V P                  VP                  V P                  V4      4      P                  V4      # )zE
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
iik

255!$ZZ\F|v|o6AA%&&.QQ__`abC==BEE1-.;;A>>r   c                D   V P                   P                  P                  V P                  VP                  4      p^p\	        V4      pW#,          ^ 8X  d   \	        V4      pK  V P                  V4      pVP                  V4      p\        WEV4      pVP                  4       pV# )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   gcdr   r   r   r(   r   )r   r   gammar"   r    r!   hpdeghps   &&      r   _degree_bound_univariater.   :   s~    & FFMMaddADD)E	A!A
)q.aL	
	B	
	B		BIIKELr   c           	     h   V P                  4       pV P                  P                  ^ ,          pV P                  P                  p\	        V^,           4       FH  p\        W#.V P                  WW,          4      VP                  WW,          4      .RR7      ^ ,          Wg3&   KJ  	  VP                  4        V# )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

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1Q3Z!$!$ @DQRSTD	  NNJr   c                *   V P                   VP                   8X  d'   V P                   P                  P                  '       g   Q h\        W4      pVe   V# V P                   pV P	                  4       w  r@VP	                  4       w  rQVP                  P                  WE4      p\        W4      pV^ 8X  d6   V! V4      V P                  WF,          4      VP                  WV,          4      3# VP                  P                  V P                  VP                  4      p^p	^p
 \        V
4      p
W,          ^ 8X  d   \        V
4      p
K  V P                  V
4      pVP                  V
4      p\        WV
4      pVP                  4       pW8  d   Kl  W8  d   ^p	TpKx  VP                  V4      P                  V
4      pV	^8X  d   T
p	TpK  \        VXW4      pW,          p	VV8X  g   TpK  VP                  VP                  4       4      pV P!                  V4      w  ppVP!                  V4      w  ppV'       d   EK  V'       d   EK"  VP                  ^ 8  d   V) pVP                  V4      pVP                  WF,          4      pVP                  WV,          4      pVVV3# )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   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_univariaterR      s   F 66QVV 3 3 333!F66DKKMEBKKMEB		 B$Q*EzBxbh/bh1GGGKKOOADD!$$'E	A	A
aLi1n!A^^A^^ARQ		=]AE]]5!..q16AF9"faK	V|FMM"**,'UU1X
dUU1X
dtDDttaxSR A//"(+C//"(+Cc3;r   c           	        V P                   pVP                  pVP                  p/ pV P                  4        F+  w  rgVRR V9  d   / WVRR &   WuVRR ,          VR,          &   K-  	  . p\	        VP                  4       4       F  p\        V\        WqV4      W4      pK  	  VP                  VP                  V^,
          ,          R7      p	V	P                  V4      P                  V4      p
WP                  V
P                  V4      4      3# )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symbols)r   r   ngens	itertermsitervaluesr   r	   clonerU   
from_denser   quoset_ring)r   r"   r   r#   kcoeffsmonomr4   contyringcontfs   &&         r   
_primitivere     s    R 66D
++C

AF":V#!#F":(-uSbz59% &
 Dfmmo&dL37@ ' JJt||AaC0J1ET"//2E%%t,---r   c                    V P                   P                  pRV^,
          ,          pV P                  4        F  pVRR V8  g   K  VRR pK  	  V# )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)

N)r   rV   )r   rW   
itermonoms)r   r_   degfra   s   &   r   _degri   Z  sO    P 	
A1Q3<D":":D   Kr   c                `   V P                   pVP                  pVP                  VP                  V^,
          ,          R7      pVP                  ^ ,          p\        V 4      pVP                  pV P                  4        F-  w  rxVRR V8X  g   K  WhWGR,          ,          ,          ,          pK/  	  V# )ag  
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

rT   NrV   )r   rW   r[   rU   r2   ri   r   rX   )	r   r   r_   rc   yrh   lcfra   r4   s	   &        r   _LCrm     s    P 66D

AJJt||AaC0J1E

1A7D
**C":"I%%C & Jr   c                    V P                   pVP                  pV P                  4        F,  w  rEWA,          3VRV ,           WA^,           R ,           pWSV&   K.  	  V# )zK
Make the variable `x_i` the leading one in a multivariate polynomial `f`.
N)r   r   rX   )r   r;   r   fswapra   r4   	monomswaps   &&     r   _swaprq     sX     66DIIEXK%)+eaCDk9	 i & Lr   c                   V P                   pVP                  P                  V P                  VP                  4      pVP                  P                  \	        V ^4      P                  \	        V^4      P                  4      pW4,          p^p\        V4      pWV,          ^ 8X  d   \        V4      pK  V P                  V4      pVP                  V4      p\        Wv4      w  r\        W4      w  r\        WV4      pVP                  4       p\        \        V4      \        V4      V4      p\        V4       F  pVP                  ^ V4      V,          '       g   K$  VP                  ^V4      P                  V4      pVP                  ^V4      P                  V4      p\        VVV4      pVP                  4       pVV3u # 	  \        VP                  4       VP                  4       4      V3# )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   rq   r   r   re   r(   r   rm   r3   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 66D[[__QTT144(F[[__U1a[^^U1a[^^<FI	A!A
-1
aL	
	B	
	BB"JFB"JFVQ'FJ CGSWa(E1X~~a#a''kk!Q,,Q/kk!Q,,Q/c3"z!!  ryy{BIIK(*44r   c                ^  a \        V P                  4       4      p\        VP                  4       4      pVP                  V4      pVP                  V4       VP                  V4       V P                  P
                  oSP                  pV P                  P                  p\        V P                  P
                  \        4      '       d   \        p	MV3R lp	V F  p
V	! W
,          W,          W#4      W&   K  	  V F  p
V	! W
,          WrV4      W&   K  	  V F  p
V	! WqV
,          W#4      W&   K  	  V# )aj  
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                 >   < S! \        W#.W.R R7      ^ ,          4      # )Tr0   r   )cpcqr"   r7   r   s   &&&&r   crt_<_chinese_remainder_reconstruction_multivariate.<locals>.crt_l  s     #qfrh$?BCCr   )
setmonomsintersectiondifference_updater   r   r   
isinstancer   ._chinese_remainder_reconstruction_multivariate)r,   r6   r"   r7   hpmonomshqmonomsr   r   r:   r   ra   r   s   &&&&       @r   r   r     s    P 299;H299;H""8,Fv&v&WW^^F;;D
'',,C"''...11=	D ")RY5
 ")Ta0
 $5	10
  Jr   c                (   VP                   pV'       d5   VP                  P                  pVP                  P                  V,          pMVP                  pVP                  V,          p\        W4       F  w  rVP                  pVP                  pV  F)  pW8X  d   K  WV,
          ,          pWV,
          ,          pK+  	  VP                  W4      pVP                  V4      pWjP                  V4      V,          ,          pK  	  VP                  V4      # )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   r2   zipr   r   r   r^   r   )
evalpointshpevalr   r;   r"   groundr,   r   rk   r}   r   numerdenombr4   s   &&&&&&         r   _interpolate_multivariater   y  s    N 
B##KKQIIaLj)

AvUNEUNE  e'  '
ll4 5(( * ??1r   c                &   V P                   VP                   8X  d'   V P                   P                  P                  '       g   Q h\        W4      pVe   V# V P                   pV P	                  4       w  r@VP	                  4       w  rQVP                  P                  WE4      p\        W4      w  rxYxu;8X  d   ^ 8X  d9   M M5V! V4      V P                  WF,          4      VP                  WV,          4      3# \        V ^4      p	\        V^4      p
V	P                  4       pV
P                  4       p\        W4      w  rYu;8X  d   ^ 8X  d9   M M5V! V4      V P                  WF,          4      VP                  WV,          4      3# VP                  P                  V P                  VP                  4      pVP                  P                  V	P                  V
P                  4      pVV,          p^p^p \        V4      pVV,          ^ 8X  d   \        V4      pK  V P                  V4      pVP                  V4      p\        VV4      w  pp\        VV4      w  pp\        VVV4      pVP                  4       pVV8  d   K  VV8  d   ^pTpK  \        \        V4      \        V4      V4      pVP                  4       pVP                  4       pVP                  4       p\!        VV,
          VV,
          W,
          V,           4      ^,           pVV8  d   EK"  ^ p. p . p!Rp"\#        V4       F  p#VP%                  ^ V#4      p$V$V,          '       g   K&  VP%                  ^V#4      P                  V4      p%VP%                  ^V#4      P                  V4      p&\        V%V&V4      p'V'P                  4       p(V(V8  d   K  V(V8  d	   ^pT(pRp" MXV'P                  V$4      P                  V4      p'V P'                  V#4       V!P'                  V'4       V^,          pVV8X  g   K   M	  V"'       d   EK5  VV8  d   EK?  \)        V V!V^V4      p)\        V)V4      ^,          p)V)VP+                  V4      ,          p)V)P                  ^4      p*V*V8  d   EK  V*V8  d   ^pT*pEK  V)P                  V4      P                  V4      p)V^8X  d   TpT)p+EK  \-        V)X+VV4      p,VV,          pV,V+8X  g   T,p+EK  V,P/                  V,P1                  4       4      p-V P3                  V-4      w  p.p/VP3                  V-4      w  p0p1V/'       d   EKE  V1'       d   EKP  V-P                  ^ 8  d   V) pV-P                  V4      p-V.P                  WF,          4      p2V0P                  WV,          4      p3V-V2V33# )aI  
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]_

TF)r   r   r>   r   r?   r*   r   r   rq   r   r   r   r   re   r(   rm   rt   r3   rs   appendr   r^   r   r@   rA   rB   )4r   r   rC   r   rD   rE   rF   r   r{   ro   gswapdegyfdegygybound
xcontboundru   rv   rw   rH   r"   r    r!   rx   ry   rz   	degconthpr|   	degcontfp	degcontgpdegdeltaNr8   r   r   unluckyr}   deltaar~   r   r   deghpar,   degyhprI   rJ   rK   rL   rM   rN   rO   rP   rQ   s4   &&                                                  r   modgcd_bivariater     s   R 66QVV 3 3 333!F66DKKMEBKKMEB		 B06F q Bxbh/bh1GGG!QKE!QKELLNELLNE0>F q Bxbh/bh1GGG [[__QTT144(F[[__UXXuxx0FI	A	A
aL!mq !A^^A^^AA&
A&
+MMO	z!#A"J BR!,MMO	MMO	<<>	!59#4(*,./0 q5
qA^^Aq)FA::++a#003C++a#003C#sA&CZZ\F&..(55a8Ca MM#FAAv1 4 q5&z64AFAq!&//$''1F?F?AF]]6"//26AF;B1M	QV|FMM"**,'UU1X
dUU1X
dtDDttaxSR A//"(+C//"(+Cc3;r   c                \   V P                   pVP                  pV^8X  dT   \        WV4      P                  V4      pVP	                  4       pW^ ,          8  d   R# W^ ,          8  d   W^ &   \
        hV# V P	                  V^,
          4      p	VP	                  V^,
          4      p
\        W4      w  r\        W4      w  r\        WV4      pVP	                  4       pVP	                  4       pVP	                  4       pVWF^,
          ,          8  d   R# VWF^,
          ,          8  d   VWF^,
          &   \
        h\        V 4      p\        V4      p\        VVV4      pTp\        V^,
          4       F=  pV\        \        \        V V4      4      \        \        VV4      4      V4      ,          pK?  	  VP	                  4       p\        W,
          W,
          W6^,
          ,          WF^,
          ,          ,
          V,           4      ^,           pVV8  d   R# ^ p^ p. p. p\        \        V4      4      pV'       Ed   \        P                  ! V^4      ^ ,          pVP                  V4       VP                  ^ V4      V,          '       g   KY  VP                  ^ V4      V,          pV P                  V^,
          V4      P                  V4      pVP                  V^,
          V4      P                  V4      p \!        VV W#V4      p!V!f   V^,          pVV8  d   R# K  V!P"                  '       d#   VP%                  V4      P                  V4      pV# V!P'                  V4      P                  V4      p!VP)                  V4       VP)                  V!4       V^,          pVV8X  g   EKq  \+        VVWV^,
          V4      p\        Wr4      ^,          VP%                  V4      ,          pVP	                  V^,
          4      p"V"W6^,
          ,          8  d   R# V"W6^,
          ,          8  d   V"W6^,
          &   \
        hV# R# )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]_

N)r   rW   r(   r   r   r   re   rm   r3   rq   rt   listrandomsampleremovers   _modgcd_multivariate_p	is_groundr^   r   r   r   )#r   r   r"   degbound	contboundr   r_   rK   deghr   r   rd   contgconthdegcontfdegcontgdegconthrl   lcgr|   evaltestr;   r   r   r8   dr   hevalpointsr}   r   fagahadegyhs#   &&&&&                              r   r   r     st   ` 66D

AAvA!))!,xxz1+1+QK""HHQqSMEHHQqSME!HE!HEE!$E||~H||~H||~H)aC. )aC. !	A#
a&C
a&CCa EH1Q3ZGCa,c%1+.>BB  ||~HEe.qSMIcN*X5	79:	;A 	1u	A	AJE%(^F
&MM&!$Q'a  A&**1%)ZZ!Q,,Q/ZZ!Q,,Q/ $BAC:FA1u<<<t$11!4AH]]6"//2!R	Q6)*eTQ3JA1 #ennT&::AHHQqSMEx!}$x!}$ %1&&Hr   c           	     &   V P                   VP                   8X  d'   V P                   P                  P                  '       g   Q h\        W4      pVe   V# V P                   pVP                  pV P                  4       w  rPVP                  4       w  raVP                  P                  WV4      pVP                  P                  V P                  VP                  4      pVP                  P                  p	\        V4       FK  p
WP                  P                  \        W
4      P                  \        W4      P                  4      ,          p	KM  	  \        V P                  4       VP                  4       4       UUu. uF  w  r\        W4      NK  	  ppp\        V4      p^p^p \        V4      pV	V,          ^ 8X  d   \        V4      pK  V P!                  V4      pVP!                  V4      p \#        VVVW4      pTf   K^  TP'                  T4      P!                  T4      pT^8X  d   TpTpK  \)        TXTT4      pTT,          pTT8X  g   TpK  TP                  4       ^,          pT P+                  T4      w  ppTP+                  T4      w  ppT'       d   K  T'       d   EK  TP                  ^ 8  d   T) pTP'                  T4      pTP'                  YW,          4      pTP'                  Yg,          4      pTTT3# u uppi   \$         d    ^p EKp  i ; i)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   rW   r?   r*   r   r   r3   rq   r   degreesrt   r   r   r   r   r   r   r   rB   )r   r   rC   r   r_   rD   rE   rF   r+   rw   r;   fdeggdegr   r   rH   r"   r    r!   r,   rI   rJ   rK   rL   rM   rN   rO   rP   rQ   s   &&                           r   modgcd_multivariater   '  s}   \ 66QVV 3 3 333!F66D

A KKMEBKKMEB		 BKKOOADD!$$'EI1X[[__U1[^^U1[^^DD	  36aiik199;2OP2OJDD2OHPXI	A	A
aL!mq !A^^A^^A	'B8GB
 :]]5!..q16AF;B1M	QV|FLLN1UU1X
dUU1X
dtDDttaxSR A//"(+C//"(+Cc3;] Q"   	A	s   7K8)K> >LLc                    V P                   p\        V P                  4       VP                  4       W#P                  4      w  rEVP	                  V4      VP	                  V4      3# )zS
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     sK    
 66D

ajjlA{{KH??8$dooh&???r   c                   V P                   pVP                  pVP                  4       pV^,          pWV,
          ^,
          pY#P                  rYP                  rV
P                  4       V8  dR   \        WV4      ^ ,          pYW,          ,
          P                  V4      rYW,          ,
          P                  V4      rKf  YrVP                  4       V8  g   \        WV4      ^8w  d   R# VP                  pV^8w  dR   VP                  W4      pVP                  V4      P                  V4      pVP                  V4      P                  V4      pVP                  4       pV! V4      V! V4      ,          # )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]_

N)r   r   r   r   r   r   r   r(   r   r   r   to_field)cr"   rH   r   r   Mr   Dr0s0r1s1r]   r}   r   lcr&   fields   &&&               r   !_rational_function_reconstructionr     s#   J 66D[[F	
A	QA		A		
))+/ba #36k//2B36k//2BqxxzA~q)Q.	
B	Qwb$LL,,Q/LL,,Q/MMOE8eAhr   c                J   VP                   pV P                  4        F  w  rgV^ 8X  d   \        WqV4      pV'       g    R# MZVP                  P                   pVP	                  V4      P                  4        F!  w  r\        WV4      pV'       g     R# WV	&   K#  	  WV&   K  	  V# )au  
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

N)r   rX   r   r   drop_to_ground)rJ   r"   rH   r   r_   rK   ra   r4   coeffhmonr   rF   s   &&&&&       r   $_rational_reconstruction_func_coeffsr     s    \ 			A66uCF  [[%%F..q1;;=6qQ? s > %# '& Hr   c                    V P                   p\        V P                  4       VP                  4       W#P                  4      w  rEpVP	                  V4      VP	                  V4      VP	                  V4      3# )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trK   s   &&&    r   	_gf_gcdexr   L  sW     66Dqzz|QZZ\1kkBGA!??1tq14??13EEEr   c                    V P                   pVP                  V4      pVP                  V4      pV P                  V4      P	                  W.4      P                  V4      # )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  sR    0 66Dt$G		B>>!  '/<<Q??r   c                B   V P                   p\        WV4      p \        WV4      pV'       d   T pVP                  ^ 4      p\        VP	                  V4      W#4      w  rxp	V	^8X  g   R#  VP                  ^ 4      p
W8  d   MXWtP	                  V4      ,          P                  V4      p\        WQP                  W,
          ^ 34      V,          ,
          W#4      pKq  Tp TpK  \        VP	                  V 4      W#4      ^ ,          P                  V4      p\        W,          W#4      # )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]`

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 66Dq1Aq1A
hhqk!$++a.'=#axZZ]F|;;s++55d;C{{FL!+<=cAA7NCt{{1~w215>>tDF!*g))r   c                   V P                   pVP                  VP                  ^,          VP                  ^ ,          3R7      pVP                  V4      pT pVP	                  4       pVP	                  4       pVP	                  ^4      p	\        V4      P                  V4      p
VP                  pV'       Ed%   Wx8  Ed   \        V4      P                  V4      pWj,          VP                  Wx,
          ^ 34      V,          ,
          pV'       d   VP                  V4      pVP	                  ^4      pV'       d   Wy8  d   \        VP                  V4      4      P                  V4      pVP                  V4      VP                  ^ Wy,
          34      V,          ,
          pV'       d   VP                  V4      pVP	                  ^4      pK  VP	                  4       pEK-  V# )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]_

rT   )
r   r[   rU   r^   r   rm   r   r   r   r   )r   rK   r   r"   r   zxringr$   r'   r   degmlchlcmlcrems   &&&&         r   _trial_divisionr     sd   B 66DZZa$,,q/ BZCFt$G
CZZ\F88:D>>!D
a&//$
C
**C
#&.C!!$'gV]A$67==""1%CAfnV,-66t<E..%(9(91fm:L(Me(SSC&&q)ZZ]FJr   c                   V P                   P                  V P                   P                  P                   P                  V4      R7      pVP                  pV P                  4        F  w  rVVP                  W4      WE&   K  	  V# )zO
Evaluate a polynomial `f` at `a` in the `i`-th variable of the ground
domain.
r   )r   r[   r   dropr   rX   rs   )r   r;   r}   r   r   ra   r4   s   &&&    r   _evaluate_groundr     sc    
 66<<qvv}}1166q9<:D	BNN1(	 & Ir   c           
     @   V P                   pVP                  p\        V\        4      '       d   VP                  pM\        WW#4      # V^8X  d   VP                   P                  4       pMVVP                   P                  V^,
          4      pVP                  VP                  P                   P                  4       R7      pVP                  VR7      p^p	^p
VP                  V 4      VP                  V4      ,          pVP                  p. p. p. p\        \        V4      4      pV'       Ed   \        P                  ! V^4      ^ ,          pVP                  V4       V^8X  d%   VP!                  V^,
          V4      V,          ^ 8H  pM+VP!                  V^,
          V4      P#                  V4      ^ 8H  pV'       d   K  \%        W^,
          V4      p\%        W&^,
          V4      pVP'                  VVP                  V4      .4      ^ 8X  d   K  \%        W^,
          V4      p\%        W^,
          V4      p\)        VVVV4      pVf   V
^,          p
W8  d   R# EK3  V^8X  d   V# VP+                  4       .^ .V^,
          ,          ,           pV^8  dd   VP-                  4        FO  w  ppV^ ,          V^ ,          8X  g   K  VP.                  \1        VR,          4      8  g   K@  VP.                  VR&   KQ  	  V.pV.pV^8X  d&   VP                  P3                  4       P4                  pM.VP                  P                  P3                  4       P4                  pVP                   P6                  ^ ,          p\9        WV4       FB  w  pp p!V!V8X  g   K  VP;                  V4       VP;                  V 4       VVV,
          ,          pKD  	  VP#                  V4      pVP;                  V4       VP;                  V4       VP;                  V4       V	^,          p	\=        VVWF^,
          VRR7      p"\?        V"VVW^,
          4      p"V"f   EK  V^8X  d   VP                  P@                  p#V#P                   P4                  p$V"PC                  4        FZ  pV#P                   PE                  \G        V$PI                  4       VPJ                  PI                  4       VV#P                  4      4      p$K\  	  MVP                  P                  P@                  p#V#P                   P4                  p$V"PC                  4        Fq  pVPC                  4        FZ  p%V#P                   PE                  \G        V$PI                  4       V%PJ                  PI                  4       VV#P                  4      4      p$K\  	  Ks  	  VPM                  V$P#                  V4      4      p$V! V"PO                  V$4      PQ                  4       4      P#                  V4      p"\S        V V"W#4      '       d   EK  \S        VV"W#4      '       d   EK  V"# R# )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   N   NNT)r   )*r   r   r   r   rW   r   r   r   r[   r   r   r   r3   r   r   r   rs   r   r   r$   _func_field_modgcd_pr   rX   LMtupleget_ringr   r2   r   r   r   r   r   
itercoeffsr\   r   r   r   
domain_newr   as_exprr   )&r   r   r   r"   r   r   r_   qdomainqringr8   r   r+   r|   r   r   LMlistr   r}   testgammaaminpolyar   r   r   r   ra   r4   evalpoints_aheval_arH   r   r   hbLMhbrK   r#   denr   s&   &&&&                                  r   r   r     s   T 66D[[F&.))LL#A'55Av++&&(++,,QU3--w~~':':'C'C'E-FJJgJ&E	A	A KKNT[[^+EJJEJEF%(^F
&MM&!$Q'a6>>!A#q)A-2D>>!A#q)66q9Q>D!%1a0#GqS!4::xQ01Q6a1a(a1a( ""b(A6:FAu7Iiik]aS!A#Y&q5 "u8r!u$E"R&M)A"XXBrF !/ s$6%%'++A##,,.22AFFKKNz&9KAr4rz##A&r"a!e	 : NN1!Rb	Q &lGTQ3RVW 1Aq%1E96,,$$C((,,Chh))&AUAUAW3::+' ( (
 ,,%%++C((,,C))+A((--fS\\^QWWEUEUEWszz/+ ,C , (
 s//23c"**,-::1=q!W00Aw9Z9ZHr   c                   V ^ 8  d	   W,          p YP                   rCYP                  re\        V^,          4      p\        V4      V8  d)   W5,          pYSW,          ,
          rSYdW,          ,
          rdK8  \	        \        V4      4      V8  d   R# V^ 8  d   V) V) rMV^ 8  d   YVrMR# VP                  4       pV! V	4      V! V
4      ,          # )ap  
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]_

N)r   r   r   intabs	get_field)r   rH   r   r   r   r   r   rG   r]   r}   r   r   s   &&&         r    _integer_rational_reconstructionr    s    H 	1u	

QKE
b'U
h#&[B#&[B
3r7|u	AvsRC1	a1E8eAhr   c                2   VP                   p\        VP                  \        4      '       d   \        pVP                  P
                  pM\        pV P
                  P                  pV P                  4        F  w  rgV! WqV4      pV'       g    R# WV&   K  	  V# )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  rX   )	rJ   rH   r   rK   reconstructionr   ra   r4   r   s	   &&&      r   r  r    sw    R 			A$++~..<!!9&1% ' Hr   c                   V P                   pVP                  p\        V\        4      '       dT   VP                  pVP                   P                  VP                  P                  4       R7      pVP                  VR7      pM,^ pVP                  VP                  P                  4       R7      pV P                  4       w  rVP                  4       w  rVP                  V 4      VP                  V4      ,          p
VP                  p^p. p. p. p \        V4      pV
P                  V4      ^ 8X  d   K$  V^ 8X  d   W,          ^ 8H  pMVP                  V4      ^ 8H  pV'       d   KU  V P                  V4      pVP                  V4      pVP                  V4      p\        VVVV4      pVf   K  V^8X  d   VP                  # VP                  4       .^ .V,          ,           pV^ 8  dd   VP                  4        FO  w  ppV^ ,          V^ ,          8X  g   K  VP                   \#        VR,          4      8  g   K@  VP                   VR&   KQ  	  TpTp\%        WV4       F'  w  pppVV8X  g   K  \'        VVVV4      pVV,          pK)  	  VP)                  V4       VP)                  V4       VP)                  V4       \+        VVV4      pVf   EK  V^ 8X  d   VP-                  4       ^,          pMoVP                  P                  pVP/                  4        F4  pVP                  P1                  VVP-                  4       ^ ,          4      pK6  	  VP3                  V4      pVP5                  V4      pVP                  4       ^,          p\7        V P3                  V4      VV4      '       d   EK  \7        VP3                  V	4      VV4      '       d   EK  V# )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   r   r   r   rW   r[   r  r?   r   r   r   r   r   r   r   rX   r   r   r   r   r   r  clear_denomsr   r   r   r^   r   )r   r   r   r   r   r_   QQdomainQQringrD   rE   r+   r|   r"   primeshplistr  r  r    r!   minpolypr,   r   ra   r4   rJ   rH   r7   r6   LMhqrK   r  s   &&&                            r   _func_field_modgcd_mr  '  s   D 66D[[F&.))LL;;$$FMM,C,C,E$F8,4;;#8#8#:;KKMEBKKMEB KKNT[[^+EJJE	AFFF
aLa A%6IND&&q)Q.D^^A^^A''*!"b(A6:788Oiik]aSU"q5 "u8r!u$E"R&M)A"XXBrF !/ vv6KAr4rzCBAqQQ 7
 	abb0Q?:6!!$A--##Cmm''U-?-?-A!-DE )c"A JJtKKM!R 0!W==ALL,a99Hr   c                   VP                   p\        VP                  \        4      '       d   VP                  P                  pMVP                  pVP                  pV P                  4        F?  pVP                  4        F(  pV'       g   K  VP                  WFP                  4      pK*  	  KA  	  V P                  4        EF  w  ruVP                  4       pVP                  P                  p\        VP                  \        4      '       d   VP                  VR,          4      p\        V4      p	\        V	4       F  p
WZ,          '       g   K  VP                  WZ,          V,          4      V,          pV^ ,          W,
          ^,
          3V9  d   WbV^ ,          W,
          ^,
          3&   Kq  W'^ ,          W,
          ^,
          3;;,          V,          uu&   K  	  EK  	  V# )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   )r   r   r   r   r   r   to_listr   denominatorrX   r   lenr3   convert)r   r   f_r   r  r4   r   ra   rH   r8   r;   s   &&         r   _to_ZZ_polyr#    sN   2 
B$++~..##
**CAqjjmm4 !  
 KKOOdkk>22E"I&AJqAxxNN58c>2Q6!Hac!e$B.,-a!#a%()a!#a%()Q.)  &  Ir   c                   VP                   pVP                  p\        V P                  P                   \        4      '       d   V P                  4        F}  w  rEVP                  4        Fd  w  rgV^ ,          3V,           pV! VP                  V4      .^ .V^,          ,          ,           4      p	W9  d   WV&   KP  W8;;,          V	,          uu&   Kf  	  K  	  V# V P                  4        F]  w  rEV^ ,          3pV! VP                  V4      .^ .V^,          ,          ,           4      p	W9  d   WV&   KI  W8;;,          V	,          uu&   K_  	  V# )a.  
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   rX   )
r   r   r   r"  ra   r4   r   coefrH   r   s
   &&        r   _to_ANP_polyr&    s   0 [[F	B!&&--00KKMLE"__.	1XK#%FMM$/0A3uQx<?@;qEEQJE / *( I KKMLEqAe,-E!H<=A{1
 * Ir   c                v    VP                   pV P                  4        F  w  r4VP                  V4      W#&   K  	  V# )zc
Change representation of the minimal polynomial from ``DMP`` to
``PolyElement`` for a given ring.
)r   termsr   )r   r   minpoly_ra   r4   s   &&   r   _minpoly_from_denser*  0  s6    
 yyH++e, ( Or   c                   V P                   pVP                  ! \        ^VP                  4      !  pVP                  P                   pV! V P                  4       4      pVP                  pVP                  4        F*  p\        WV4      ^ ,          pWSP                  8X  g   K'  WP3u # 	  WPP                  VP                  V4      4      3# )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   r3   rW   r   r   r   r   func_field_modgcdr   r]   r^   )r   fringr   r#   r"  rb   r4   s   &      r   _primitive_in_x0r.  =  s     FFEq%++!67D
++

C	aiik	B88D -a077?7N !
 t}}U+,,,r   c                n   V P                   pVP                  pVP                  pW!P                   8X  d   VP                  '       g   Q h\	        W4      pVe   V# \        R4      pVP                  VP                  V3,           VP                  P                  4       R7      pV^8X  dg   \        W4      p\        W4      p	VP                  ^ 4      P                  VP                  P                  4       4      p
\        WV
4      p\        W4      pM\!        V 4      w  r\!        V4      w  r\#        W4      ^ ,          pVP$                  ! \'        ^V4      !  p\        W4      p\        W4      p	\)        VP                  VP                  ^ 4      4      p
\        WV
4      p\        W4      p\!        V4      w  ppWP+                  V4      ,          pWP+                  V4      ,          p WP+                  V4      ,          pVP-                  VP.                  4      pWP1                  V4      VP1                  V4      3# )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)rU   r   )r   r   rW   is_Algebraicr   r   r[   rU   r   r#  r   r\   modr  r  r&  r.  r,  r   r3   r*  r^   r@   r   r]   )r   r   r   r   r8   rC   r0  ZZringr"  g_r   rK   contx0fcontx0gcontx0hZZring_contx0h_s   &&               r   r,  r,  R  s   P 66D[[F

A66>f11111!Fc
AZZt 3FMM<R<R<TZUFAv##++a.++FJJ,>,>,@A 1! &a(
%a(
#G5a8''q!5$$%fjj',,q/B 1!&q)!	d##	d##	d##	QTTAeeAh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<   rR   re   ri   rm   rq   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>rB     s    # # % .4 4 3  ,?.B>B~B:.z-`2j	H5V`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   