
\c           @   s  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	 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 e  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#   Z0 d$   Z1 d%   Z2 d&   Z3 d'   Z4 d(   Z5 d)   Z6 d	 S(*   i(   t   Dummy(   t   range(   t	   nextprime(   t   crt(   t   PolynomialRing(   t   gf_gcdt   gf_from_dictt   gf_gcdext   gf_divt   gf_lcm(   t   ModularGCDFailed(   t   sqrtNc         C   s   |  j  } |  p | s+ | j | j | j f S|  sq | j | j j k  r[ | | j | j f S| | j | j f SnF | s |  j | j j k  r |  | j | j f S|  | j | j f Sn  d S(   sn   
    Compute the GCD of two polynomials in trivial cases, i.e. when one
    or both polynomials are zero.
    N(   t   ringt   zerot   LCt   domaint   onet   None(   t   ft   gR   (    (    s5   lib/python2.7/site-packages/sympy/polys/modulargcd.pyt   _trivial_gcd   s    	c         C   s   |  j  j } x | r |  } | j   } | j | j |  } xY t r | j   } | | k  ra Pn  | | j | | f  j | | j  j |  } q? W| }  | } q W|  j | j |  j |   j |  S(   sM   
    Compute the GCD of two univariate polynomials in `\mathbb{Z}_p[x]`.
    (	   R   R   t   degreet   invertR   t   Truet	   mul_monomt
   mul_groundt   trunc_ground(   t   fpt   gpt   pt   domt   remt   degt   lcinvt   degrem(    (    s5   lib/python2.7/site-packages/sympy/polys/modulargcd.pyt   _gf_gcd$   s    		7
c         C   s   |  j  j j |  j | j  } d } t |  } x  | | d k rR t |  } q3 W|  j |  } | j |  } t | | |  } | j   } | S(   s  
    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

    i   i    (   R   R   t   gcdR   R   R   R#   R   (   R   R   t   gammaR   R   R   t   hpt   deghp(    (    s5   lib/python2.7/site-packages/sympy/polys/modulargcd.pyt   _degree_bound_univariate;   s    c         C   s   |  j    } |  j j d } |  j j } x^ t | d  D]L } t | | g |  j | |  | j | |  g d t d | | f <q9 W| j   | S(   s  
    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

    i    i   t	   symmetric(	   R   R   t   gensR   R   R   t   coeffR   t
   strip_zero(   R&   t   hqR   t   qt   nt   xt   hpqt   i(    (    s5   lib/python2.7/site-packages/sympy/polys/modulargcd.pyt,   _chinese_remainder_reconstruction_univariate\   s    6J
c         C   s  |  j  | j  k r! |  j  j j s' t  t |  |  } | d k	 rF | S|  j  } |  j   \ } }  | j   \ } } | j j | |  } t |  |  } | d k r | |  |  j	 | |  | j	 | |  f S| j j |  j
 | j
  } d }	 d }
 xt rt |
  }
 x  | |
 d k r.t |
  }
 qW|  j |
  } | j |
  } t | | |
  } | j   } | | k r}q n | | k  rd }	 | } q n  | j	 |  j |
  } |	 d k r|
 }	 | } q n  t | | |
 |	  } |	 |
 9}	 | | k s| } q n  | j | j    } |  j |  \ } } | j |  \ } } | r | r | j
 d k  rn| } n  | j	 |  } | j	 | |  } | j	 | |  } | | | f Sq Wd S(   s  
    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]_

    i    i   N(   R   R   t   is_ZZt   AssertionErrorR   R   t	   primitiveR$   R(   R   R   R   R   R   R#   R   R3   t
   quo_groundt   contentt   div(   R   R   t   resultR   t   cft   cgt   cht   boundR%   t   mR   R   R   R&   R'   t   hlastmt   hmt   ht   fquot   fremt   gquot   gremt   cfft   cfg(    (    s5   lib/python2.7/site-packages/sympy/polys/modulargcd.pyt   modgcd_univariate   s`    C'	-	

c         C   s
  |  j  } | j } | j } i  } xQ |  j   D]C \ } } | d  | k r[ i  | | d  <n  | | | d  | d <q. Wg  } x; t | j    D]' } t | t | | |  | |  } q W| j d | j	 | d  }	 |	 j
 |  j |  }
 |
 |  j |
 j |   f S(   s  
    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)

    it   symbolsi   (   R   R   t   ngenst	   itertermst   itert   valuesR   R   t   cloneRJ   t
   from_denseR   t   quot   set_ring(   R   R   R   R   t   kt   coeffst   monomR+   t   contt   yringt   contf(    (    s5   lib/python2.7/site-packages/sympy/polys/modulargcd.pyt
   _primitive  s    )			%c         C   sR   |  j  j } d | d } x1 |  j   D]# } | d  | k r' | d  } q' q' W| S(   s  
    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)

    i    i   i(   i    (   R   RK   t
   itermonoms(   R   RS   t   degfRU   (    (    s5   lib/python2.7/site-packages/sympy/polys/modulargcd.pyt   _deg[  s    (c   	      C   s   |  j  } | j } | j d | j | d  } | j d } t |   } | j } xC |  j   D]5 \ } } | d  | k r^ | | | | d 7} q^ q^ W| S(   s  
    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

    RJ   i   i    i(   R   RK   RO   RJ   R*   R\   R   RL   (	   R   R   RS   RW   t   yR[   t   lcfRU   R+   (    (    s5   lib/python2.7/site-packages/sympy/polys/modulargcd.pyt   _LC  s    (			c         C   s^   |  j  } | j } xE |  j   D]7 \ } } | | f | |  | | d } | | | <q W| S(   sS   
    Make the variable `x_i` the leading one in a multivariate polynomial `f`.
    i   (   R   R   RL   (   R   R2   R   t   fswapRU   R+   t	   monomswap(    (    s5   lib/python2.7/site-packages/sympy/polys/modulargcd.pyt   _swap  s    		!c         C   s  |  j  } | j j |  j | j  } | j j t |  d  j t | d  j  } | | } d } t |  } x  | | d k r t |  } qp W|  j |  } | j |  } t | |  \ }	 } t | |  \ }
 } t |	 |
 |  } | j	   } t t
 |  t
 |  |  } x t |  D]} } | j d |  | sCq!n  | j d |  j |  } | j d |  j |  } t | | |  } | j	   } | | f SWt | j	   | j	    | f S(   s  
    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]_

    i   i    (   R   R   R$   R   Rb   R   R   RY   R#   R   R_   R   t   evaluatet   min(   R   R   R   t   gamma1t   gamma2t	   badprimesR   R   R   t   contfpt   contgpt   conthpt
   ycontboundt   deltat   at   fpat   gpat   hpat   xbound(    (    s5   lib/python2.7/site-packages/sympy/polys/modulargcd.pyt   _degree_bound_bivariate  s0    *	-
c         C   s!  t  |  j    } t  | j    } | j |  } | j |  | j |  |  j j j } |  j j } t |  j j t  r t	 }	 n	 d   }	 x/ | D]' }
 |	 |  |
 | |
 | |  | |
 <q Wx+ | D]# }
 |	 |  |
 | | |  | |
 <q Wx+ | D]# }
 |	 | | |
 | |  | |
 <q W| S(   s:  
    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   s#   t  | | g |  | g d t d S(   NR)   i    (   R   R   (   t   cpt   cqR   R.   (    (    s5   lib/python2.7/site-packages/sympy/polys/modulargcd.pyt   crt_l  s    (
   t   sett   monomst   intersectiont   difference_updateR   R   R   t
   isinstanceR   t.   _chinese_remainder_reconstruction_multivariate(   R&   R-   R   R.   t   hpmonomst   hqmonomsRw   R   R1   Ru   RU   (    (    s5   lib/python2.7/site-packages/sympy/polys/modulargcd.pyR{     s"    H		%!!c         C   s   | j  } | r. | j j } | j j | } n | j } | j | } x t |  |  D] \ }	 }
 | j } | j } x< |  D]4 } | |	 k r qy n  | | | 9} | |	 | 9} qy W| j | |  } | j |  } | |
 j |  | 7} qT W| j |  S(   s  
    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   R*   t   zipR   R   R   RR   R   (   t
   evalpointst   hpevalR   R2   R   t   groundR&   R   R]   Rm   Rp   t   numert   denomt   bR+   (    (    s5   lib/python2.7/site-packages/sympy/polys/modulargcd.pyt   _interpolate_multivariatey  s$    '				c   4      C   s  |  j  | j  k r! |  j  j j s' t  t |  |  } | d k	 rF | S|  j  } |  j   \ } }  | j   \ } } | j j | |  } t |  |  \ } } | | k o d k n r | |  |  j	 | |  | j	 | |  f St
 |  d  }	 t
 | d  }
 |	 j   } |
 j   } t |	 |
  \ } } | | k oHd k n rz| |  |  j	 | |  | j	 | |  f S| j j |  j | j  } | j j |	 j |
 j  } | | } d } d } xt rt |  } x  | | d k rt |  } qW|  j |  } | j |  } t | |  \ } } t | |  \ } } t | | |  } | j   } | | k rvqn | | k  rd } | } qn  t t |  t |  |  } | j   } | j   } | j   } t | | | | | | |  d } | | k  rqn  d } g  }  g  }! t }" x
t |  D] }# | j d |#  }$ |$ | s[q3n  | j d |#  j |  }% | j d |#  j |  }& t |% |& |  }' |' j   }( |( | k rq3n" |( | k  rd } |( } t }" Pn  |' j	 |$  j |  }' |  j |#  |! j |'  | d 7} | | k r3Pq3q3W|" r?qn  | | k  rQqn  t |  |! | d |  }) t |) |  d }) |) | j |  }) |) j d  }* |* | k rqn  |* | k  rd } |* } qn  |) j	 |  j |  }) | d k r| } |) }+ qn  t |) |+ | |  }, | | 9} |, |+ k s;|, }+ qn  |, j |, j    }- |  j |-  \ }. }/ | j |-  \ }0 }1 |/ r|1 r|- j d k  r| } n  |- j	 |  }- |. j	 | |  }2 |0 j	 | |  }3 |- |2 |3 f SqWd S(   s!  
    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]_

    i    i   N(   R   R   R4   R5   R   R   R6   R$   Rr   R   Rb   R   R   R   R   R   RY   R#   R_   Rd   t   FalseR   Rc   t   appendR   RR   R{   R7   R8   R9   (4   R   R   R:   R   R;   R<   R=   Rq   Rk   R`   t   gswapt   degyft   degygt   yboundt
   xcontboundRe   Rf   Rg   R?   R   R   R   Rh   Ri   Rj   t	   degconthpRl   t	   degcontfpt	   degcontgpt   degdeltat   NR/   R   R   t   unluckyRm   t   deltaaRn   Ro   Rp   t   deghpaR&   t   degyhpR@   RA   RB   RC   RD   RE   RF   RG   RH   (    (    s5   lib/python2.7/site-packages/sympy/polys/modulargcd.pyt   modgcd_bivariate  s    I'	--
	



c   #      C   s/  |  j  } | j } | d k r t |  | |  j |  } | j   } | | d k rY d S| | d k  r| | | d <t  n  | S|  j | d  }	 | j | d  }
 t |  |  \ } }  t | |  \ } } t | | |  } | j   } | j   } | j   } | | | d k rd S| | | d k  rI| | | d <t  n  t |   } t |  } t | | |  } | } xL t	 | d  D]: } | t t t
 |  |   t t
 | |   |  9} qW| j   } t |	 | |
 | | | d | | d |  d } | | k  rd Sd } d } g  } g  } t t	 |   } x| r*t j | d  d } | j |  | j d |  | sqGn  | j d |  | } |  j | d |  j |  } | j | d |  j |  }  t | |  | | |  }! |! d k r$| d 7} | | k rGd SqGn  |! j rI| j |  j |  } | S|! j |  j |  }! | j |  | j |!  | d 7} | | k rGt | | | | d |  } t | |  d | j |  } | j | d  }" |" | | d k rd S|" | | d k  r#|" | | d <t  n  | SqGWd S(   s  
    Compute the GCD of two polynomials in
    `\mathbb{Z}_p[x0, \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
    succsessful 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]_

    i   i    N(   R   RK   R#   R   R   R   R
   RY   R_   R   Rb   Rd   Rv   t   randomt   samplet   removeRc   t   _modgcd_multivariate_pt	   is_groundRR   R   R   R   (#   R   R   R   t   degboundt	   contboundR   RS   RB   t   deghR   R   RX   t   contgt   contht   degcontft   degcontgt   degconthR^   t   lcgRl   t   evaltestR2   R   R   R/   t   dR   t   hevalt   pointsRm   R   t   fat   gat   hat   degyh(    (    s5   lib/python2.7/site-packages/sympy/polys/modulargcd.pyR     s    0		
		8%	
	
 	c         C   s  |  j  | j  k r! |  j  j j s' t  t |  |  } | d k	 rF | S|  j  } | j } |  j   \ } }  | j   \ } } | j j | |  } | j j |  j	 | j	  } | j j
 }	 xE t |  D]7 }
 |	 | j j t |  |
  j	 t | |
  j	  9}	 q Wg  t |  j   | j    D] \ } } t | |  ^ q} t |  } d } d } xt r	t |  } x  |	 | d k rt |  } qmW|  j |  } | j |  } y t | | | | |  } Wn t k
 rd } qXn X| d k rqXn  | j |  j |  } | d k r,| } | } qXn  t | | | |  } | | 9} | | k sc| } qXn  | j   d } |  j |  \ } } | j |  \ } } | rX| rX| j	 d k  r| } n  | j |  } | j | |  } | j | |  } | | | f SqXWd S(   s  
    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 ``_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

    i   i    N(   R   R   R4   R5   R   R   RK   R6   R$   R   R   R   Rb   R~   t   degreesRd   t   listR   R   R   R   R
   R   R{   R9   (   R   R   R:   R   RS   R;   R<   R=   R%   Rg   R2   t   fdegt   gdegR   R   R?   R   R   R   R&   R@   RA   RB   RC   RD   RE   RF   RG   RH   (    (    s5   lib/python2.7/site-packages/sympy/polys/modulargcd.pyt   modgcd_multivariate'  sd    N'		5=	

c         C   sO   |  j  } t |  j   | j   | | j  \ } } | j |  | j |  f S(   s_   
    Compute `\frac f g` modulo `p` for two univariate polynomials over
    `\mathbb Z_p`.
    (   R   R   t   to_denseR   RP   (   R   R   R   R   t   densequot   denserem(    (    s5   lib/python2.7/site-packages/sympy/polys/modulargcd.pyt   _gf_div  s    	*c         C   sv  |  j  } | j } | j   } | d } | | d } | | j } }	 |  | j }
 } xh |
 j   | k r t | |
 |  d } |
 | | |
 j |  } }
 | |	 | | j |  }	 } qY W|
 | } } | j   | k s t | | |  d k r d S| j	 } | d k rV| j
 | |  } | j |  j |  } | j |  j |  } n  | j   } | |  | |  S(   s  
    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]_

    i   i   i    N(   R   R   R   R   R   R   R   R#   R   R   R   R   t   to_field(   t   cR   R?   R   R   t   MR   t   Dt   r0t   s0t   r1t   s1RQ   Rm   R   t   lcR!   t   field(    (    s5   lib/python2.7/site-packages/sympy/polys/modulargcd.pyt!   _rational_function_reconstruction  s*    %		
"*	c         C   s   | j  } x |  j   D] \ } } | d k rM t | | |  } | s d SnX | j j  } xI | j |  j   D]2 \ }	 }
 t |
 | |  } | s d S| | |	 <qo W| | | <q W| S(   s  
    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

    i    N(   R   RL   R   R   R   t   drop_to_ground(   RA   R   R?   R   RS   RB   RU   R+   t   coeffht   monR   R=   (    (    s5   lib/python2.7/site-packages/sympy/polys/modulargcd.pyt$   _rational_reconstruction_func_coeffs  s    .	"c         C   s^   |  j  } t |  j   | j   | | j  \ } } } | j |  | j |  | j |  f S(   s   
    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   RP   (   R   R   R   R   t   st   tRB   (    (    s5   lib/python2.7/site-packages/sympy/polys/modulargcd.pyt	   _gf_gcdexL  s    		-c         C   sL   |  j  } | j |  } | j |  } |  j |  j | | g  j |  S(   s  
    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   RR   t
   ground_newR   R   (   R   t   minpolyR   R   t   p_(    (    s5   lib/python2.7/site-packages/sympy/polys/modulargcd.pyt   _truncZ  s    	c         C   s@  |  j  } t |  | |  }  t | | |  } x | r|  } | j d  } t | j |  | |  \ } } }	 |	 d k s d Sxr t r | j d  }
 |
 | k  r Pn  | | j |  j |  } t | | j |
 | d f  | | |  } q W| }  | } q0 Wt | j |   | |  d j |  } t |  | | |  S(   s
  
    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]`

    i    i   N(	   R   R   R   R   t   dmp_LCR   R   RR   R   (   R   R   R   R   R   R   R    R!   t   _R$   R"   RQ   t   lcfinv(    (    s5   lib/python2.7/site-packages/sympy/polys/modulargcd.pyt   _euclidean_algorithmy  s&    		$	1
(c         C   s  |  j  } | j d | j d | j d f  } | j |  } |  } | j   } | j   } | j d  }	 t |  j |  }
 | j } x| r| | k rt |  j |  } | |
 | j | | d f  | } | r | j |  } n  | j d  } x | r| |	 k rt | j |   j |  } | j	 |  | j d | |	 f  | } | rt| j |  } n  | j d  } qW| j   } q W| S(   s=  
    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]_

    RJ   i   i    (
   R   RO   RJ   RR   R   R_   R   R   R   R   (   R   RB   R   R   R   t   zxringR   R"   R   t   degmt   lcht   lcmt   lcrem(    (    s5   lib/python2.7/site-packages/sympy/polys/modulargcd.pyt   _trial_division  s.    !	&	%*c         C   sg   |  j  j d |  j  j j  j |   } | j } x0 |  j   D]" \ } } | j | |  | | <q= W| S(   s[   
    Evaluate a polynomial `f` at `a` in the `i`-th variable of the ground
    domain.
    R   (   R   RO   R   t   dropR   RL   Rc   (   R   R2   Rm   R   R   RU   R+   (    (    s5   lib/python2.7/site-packages/sympy/polys/modulargcd.pyt   _evaluate_ground  s
    '	c   &      C   s  |  j  } | j } t | t  r- | j } n t |  | | |  S| d k r^ | j  j   } n4 | j  j | d  } | j d | j j  j    } | j d |  } d }	 d }
 | j	 |   | j	 |  } | j
 } g  } g  } g  } t t |   } x| rt j | d  d } | j |  | d k rT| j | d |  | d k } n% | j | d |  j |  d k } | rq n  t | | d |  } t | | d |  } | j | | j  |  g  d k rq n  t |  | d |  } t | | d |  } t | | | |  } | d k rH|
 d 7}
 |
 |	 k r d Sq n  | d k rX| S| j   g d g | d } | d k rxZ | j   D]I \ } } | d | d k r| j t | d  k r| j | d )qqWn  | g } | g } | d k r| j j   j } n | j j j   j } | j  j d } xZ t | | |  D]F \ } }  }! |! | k rJ| j |  | j |   | | | 9} qJqJW| j |  } | j |  | j |  | j |  |	 d 7}	 t | | | | d | d t  }" t! |" | | | | d  }" |" d k r$q n  | d k r| j j" }# |# j  j }$ x |" j#   D]9 } |# j  j$ t% |$ j&   | j' j&   | |# j   }$ qUWn| | j j j" }# |# j  j }$ x^ |" j#   D]P } xG | j#   D]9 }% |# j  j$ t% |$ j&   |% j' j&   | |# j   }$ qWqW| j( |$ j |   }$ | |" j) |$  j*    j |  }" t+ |  |" | |  r t+ | |" | |  r |" Sq Wd S(   s  
    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]_

    i   R   i    R   N(,   R   R   Rz   R   RK   R   R   R   RO   R   R   Rv   R   R   R   R   Rc   R   R   R   t   _func_field_modgcd_pR   R   RL   t   LMt   tuplet   get_ringR   R*   R~   R   R   R   R   R   t
   itercoeffsRP   R	   R   R   t
   domain_newR   t   as_exprR   (&   R   R   R   R   R   R   RS   t   qdomaint   qringR/   R   R%   Rl   R   R   t   LMlistR   Rm   t   testt   gammaat   minpolyaR   R   R   R   RU   R+   t   evalpoints_at   heval_aR?   R   R   t   hbt   LMhbRB   R   t   denR   (    (    s5   lib/python2.7/site-packages/sympy/polys/modulargcd.pyR     s    *				#%$
-		"
"!!$,c         C   s  |  d k  r |  | 7}  n  | | j  } } |  | j } } t | d  } xD | | k r | | } | | | | } } | | | | } } qL Wt |  | k r d S| d k  r | | }	 }
 n  | d k r | | }	 }
 n d S| j   } | |	  | |
  S(   s  
    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]_

    i    i   N(   R   R   R   t   absR   t	   get_field(   R   R?   R   R   R   R   R   R>   RQ   Rm   R   R   (    (    s5   lib/python2.7/site-packages/sympy/polys/modulargcd.pyt    _integer_rational_reconstruction  s$    $
c   	      C   s   | j  } t | j t  r0 t } | j j } n t } |  j j } x@ |  j   D]2 \ } } | | | |  } | sw d S| | | <qO W| S(   s  
    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   Rz   R   R   t#   _rational_reconstruction_int_coeffsR   R   RL   R   (	   RA   R?   R   RB   t   reconstructionR   RU   R+   R   (    (    s5   lib/python2.7/site-packages/sympy/polys/modulargcd.pyR     s    )	c         C   s  |  j  } | j } t | t  r] | j } | j  j d | j j    } | j d |  } n! d } | j d | j j    } |  j   \ } }  | j   \ }	 } | j |   | j |  }
 | j	 } d } g  } g  } g  } xt
 rt |  } |
 j |  d k rq n  | d k r.| | d k } n | j |  d k } | rOq n  |  j |  } | j |  } | j |  } t | | | |  } | d k rq n  | d k r| j S| j   g d g | } | d k r9xZ | j   D]I \ } } | d | d k r| j t | d  k r| j | d )qqWn  | } | } xQ t | | |  D]= \ } } } | | k rXt | | | |  } | | 9} qXqXW| j |  | j |  | j |  t | | |  } | d k rq n  | d k r| j   d } nQ | j j } x3 | j   D]% } | j j | | j   d  } qW| j |  } | j |  } | j   d } t |  j |  | |  pt | j |	  | |  s | Sq Wd S(   s  
    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   i    i   N(   R   R   Rz   R   RK   RO   R   R6   R   R   R   R   R   R   R   R   R   RL   R   R   R~   R{   R   R   t   clear_denomsR   R   R   RR   R   (   R   R   R   R   R   RS   t   QQdomaint   QQringR;   R<   R%   Rl   R   t   primest   hplistR   R   R   R   t   minpolypR&   R   RU   R+   RA   R?   R.   R-   t   LMhqRB   R   (    (    s5   lib/python2.7/site-packages/sympy/polys/modulargcd.pyt   _func_field_modgcd_m'  sz    B					-"#c         C   s  | j  } t | j t  r* | j j } n	 | j } | j } xF |  j   D]8 } x/ | j D]$ } | rY | j | | j  } qY qY WqI Wx |  j	   D] \ } } | j } | j j } t | j t  r | j
 | d  } n  t |  }	 x t |	  D] }
 | |
 r | | |
 |  | } | d |	 |
 d f | k rY| | | d |	 |
 d f <q~| | d |	 |
 d f c | 7<q q Wq W| S(   s  
    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]`

    i   i    (   R   Rz   R   R   R   R   t   repR   t   denominatorRL   R   t   lenR   (   R   R   t   f_R   R   R+   R   RU   R?   R/   R2   (    (    s5   lib/python2.7/site-packages/sympy/polys/modulargcd.pyt   _to_ZZ_poly  s,    			 	
-c   
      C   sC  | j  } | j } t |  j j  t  r x|  j   D] \ } } x{ | j   D]m \ } } | d f | } | | j  |  g d g | d  }	 | | k r |	 | | <qM | | c |	 7<qM Wq4 Wnz xw |  j   D]i \ } } | d f } | | j  |  g d g | d  }	 | | k r+|	 | | <q | | c |	 7<q W| S(   sr  
    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}]`

    i    i   (   R   R   Rz   R   R   RL   (
   R   R   R   R   RU   R+   R   t   coefR?   R   (    (    s5   lib/python2.7/site-packages/sympy/polys/modulargcd.pyt   _to_ANP_poly  s"    		''c         C   s=   | j  } x- |  j   D] \ } } | j |  | | <q W| S(   so   
    Change representation of the minimal polynomial from ``DMP`` to
    ``PolyElement`` for a given ring.
    (   R   t   termsR   (   R   R   t   minpoly_RU   R+   (    (    s5   lib/python2.7/site-packages/sympy/polys/modulargcd.pyt   _minpoly_from_dense0  s    	c         C   s   |  j  } | j t d | j    } | j j  } | |  j    } | j } x@ | j   D]2 } t | |  d } | | j	 k rX | |  f SqX W| |  j
 | j |   f S(   s   
    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]`.
    i   i    (   R   R   R   RK   R   R   R   R   t   func_field_modgcdR   RQ   RR   (   R   t   fringR   R   R   RV   R+   (    (    s5   lib/python2.7/site-packages/sympy/polys/modulargcd.pyt   _primitive_in_x0=  s    		c         C   s   |  j  } | j } | j } | | j  k r3 | j s9 t  t |  |  } | d k	 rX | St d  } | j d | j	 | f d | j j
    } | d k r t |  |  } 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 |  9} |  | j |  9}  | | j |  9} | j | j  } | |  j |  | j |  f S(   s  
    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 Reconstuction. 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]_

    t   zRJ   R   i   i    N(   R   R   RK   t   is_AlgebraicR5   R   R   R    RO   RJ   R   R   R   RP   t   modR   R   R   R  R  R   R   R   RR   R7   R   RQ   (   R   R   R   R   R/   R:   R  t   ZZringR   t   g_R   RB   t   contx0ft   contx0gt   contx0ht   ZZring_t   contx0h_(    (    s5   lib/python2.7/site-packages/sympy/polys/modulargcd.pyR  R  s<    h			+(7   t   sympyR    t   sympy.core.compatibilityR   t   sympy.ntheoryR   t   sympy.ntheory.modularR   t   sympy.polys.domainsR   t   sympy.polys.galoistoolsR   R   R   R   R	   t   sympy.polys.polyerrorsR
   t   mpmathR   R   R   R#   R(   R3   RI   RY   R\   R_   Rb   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  (    (    (    s5   lib/python2.7/site-packages/sympy/polys/modulargcd.pyt   <module>   sP   (			!	A		=	0	5		K	bA				
	B	F			8E			@	=		:	3		