o
    8VaT                     @   s  d Z ddlmZ ddlmZmZmZmZmZm	Z	m
Z
mZmZmZmZmZ ddlmZ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 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' ddl(m)Z) ddl*m+Z+m,Z,m-Z- ddl.m/Z/m0Z0m1Z1m2Z2m3Z3m4Z4m5Z5m6Z6m7Z7m8Z8 ddl9m:Z:m;Z; ddl<m=Z= ddl>m?Z? ddl@mAZA ddlBmCZC ddlDmEZE ddlFmGZGmHZH ddlImJZJ ddlKmLZL ddlMmNZNmOZOmPZPmQZQ ddlRmSZSmTZT e'ddfddZUd d! ZVd"d# ZWdZd%d&ZXd'd( ZYd)d* ZZd[d+d,Z[d-d. Z\d/d0 Z]d1d2 Z^d3d4 Z_d5d6 Z`d7d8 Zad9d: Zbd;d< ZcePd\d?d@ZddAdB ZeedZfdCdD ZgdEdF ZhePd[d>d>dGdHdIZidJdK ZjdLdM ZkdNdO ZlePd=dPdQdRZmePd[d$dSdTdUZnG dVdW dWeHeEZoePd]dXdYZpd$S )^z&Computational algebraic field theory.     )reduce)SRationalAlgebraicNumberGoldenRatioTribonacciConstantAddMulsympifyDummy
expand_mulIpi)sqrtcbrt)Factors)_mexpand)exp)cossintan)sieve)divisors)subsets)dup_eval)ZZQQ)dup_chebyshevt)IsomorphismFailedNotAlgebraicGeneratorsError)
PolyPurePolyinvertfactor_listgroebner	resultantdegreepoly_from_exprparallel_poly_from_exprlcm)dict_from_exprexpr_from_dict)rs_compose_add)ring)CRootOfcyclotomic_poly)LambdaPrinter)PythonCodePrinterMpmathPrinter)
_split_gcd_is_sum_surds)numbered_symbolslambdifypublicsift)pslqmp      c                    sF  ddl m  t| d trdd | D } t| dkr| d S di t|dr*|jng }|kr||js6|n|ifdd| D }t	t
|t|d	d
D ]D}t||D ]\}	}
|
|	< qWfddt|D }t fdd|D rxqPt|}|dd \\}}\}}||d kr| |   S qPd9 |ks0td| )ze
    Return a factor having root ``v``
    It is assumed that one of the factors has root ``v``.
    r   illegalc                 S   s   g | ]}|d  qS )r    .0frB   rB   :/usr/lib/python3/dist-packages/sympy/polys/numberfields.py
<listcomp>8       z"_choose_factor.<locals>.<listcomp>   
   symbolsc                    s   g | ]	}|   qS rB   )as_exprZxreplacerC   )xvrB   rF   rG   C       T)kZ
repetitionc                    s(   g | ]\}}t | |fqS rB   )abssubsn)rD   irE   )pointsprec1rB   rF   rG   K   s    c                 3   s    | ]	\}}| v V  qd S NrB   )rD   rS   _r@   rB   rF   	<genexpr>P   s    z!_choose_factor.<locals>.<genexpr>N   i@B z4multiple candidates for the minimal polynomial of %s)sympy.polys.polyutilsrA   
isinstancetuplelenhasattrrK   	is_numberrR   r   rangezip	enumerateanysortedNotImplementedError)factorsxvdomZprecZboundrK   ZferR   srS   Z
candidatesZcanaZixbrW   rB   )rA   rT   rU   rM   rF   _choose_factor0   s6   
rm   c                 C   s  ddl m} dd }g }| jD ]J}|jsB||r#|tj|d f n|jr/||tjf n|jr?|j	j
r?||tjf ntq||j|dd\}}|t| t| d f q|jdd	 d
 |d d tju rm| S dd |D }tt|D ]
}|| dkr nqzt||d  \}	}
}g }g }|D ]\}}||
v r|||tj   q|||tj   qt| }t| }t|d t|d  } | S )a7  
    helper function for ``_minimal_polynomial_sq``

    It selects a rational ``g`` such that the polynomial ``p``
    consists of a sum of terms whose surds squared have gcd equal to ``g``
    and a sum of terms with surds squared prime with ``g``;
    then it takes the field norm to eliminate ``sqrt(g)``

    See simplify.simplify.split_surds and polytools.sqf_norm.

    Examples
    ========

    >>> from sympy import sqrt
    >>> from sympy.abc import x
    >>> from sympy.polys.numberfields import _separate_sq
    >>> p= -x + sqrt(2) + sqrt(3) + sqrt(7)
    >>> p = _separate_sq(p); p
    -x**2 + 2*sqrt(3)*x + 2*sqrt(7)*x - 2*sqrt(21) - 8
    >>> p = _separate_sq(p); p
    -x**4 + 4*sqrt(7)*x**3 - 32*x**2 + 8*sqrt(7)*x + 20
    >>> p = _separate_sq(p); p
    -x**8 + 48*x**6 - 536*x**4 + 1728*x**2 - 400

    r   )r;   c                 S   s   | j o| jtju S rV   )is_Powr   r   Half)exprrB   rB   rF   is_sqrt|   s   z_separate_sq.<locals>.is_sqrtrY   T)binaryc                 S   s   | d S )NrI   rB   )zrB   rB   rF   <lambda>   s    z_separate_sq.<locals>.<lambda>)keyrI   c                 S   s   g | ]\}}|qS rB   rB   )rD   yrs   rB   rB   rF   rG      rH   z _separate_sq.<locals>.<listcomp>N)sympy.utilities.iterablesr;   argsis_Mulappendr   Oneis_Atomrn   r   
is_integerre   r	   sortr`   r]   r5   ro   r   r   )pr;   rq   rk   rw   TFZsurdsrS   gZb1Zb2Za1Za2rs   p1p2rB   rB   rF   _separate_sqa   sD   
r   c                 C   s   ddl m} t| } t|}|jr|dkr|| sdS | td| }| |8 } 	 t| }|| u r9|||| i} n|} q'|dkr[t| }| ||	| dk rS|  } | 
 d } | S t| d }t|||}|S )a  
    Returns the minimal polynomial for the ``nth-root`` of a sum of surds
    or ``None`` if it fails.

    Parameters
    ==========

    p : sum of surds
    n : positive integer
    x : variable of the returned polynomial

    Examples
    ========

    >>> from sympy.polys.numberfields import _minimal_polynomial_sq
    >>> from sympy import sqrt
    >>> from sympy.abc import x
    >>> q = 1 + sqrt(2) + sqrt(3)
    >>> _minimal_polynomial_sq(q, 3, x)
    x**12 - 4*x**9 - 4*x**6 + 16*x**3 - 8

    r   r6   NrI   )sympy.simplify.simplifyr7   r
   
is_Integerr   r   rQ   r!   coeffr'   	primitiver$   rm   )r   rR   rg   r7   Zpnr   rf   resultrB   rB   rF   _minimal_polynomial_sq   s.   r   Nc                 C   st  t t|}|du rt|||}|du rt|||}n|||i}| tu rZ|tkrBtdt\}}	|t|d }
|t|d }n't||| f||\\}
}}|
	|}|
 }n| tu ret|||}ntd| tu sq|tkr{t||||gd}nt|
|}t| |}t||}t||}| tu r|dks|dkr|S t|||d}| \}}t||| |||}|
 S )a  
    return the minimal polynomial for ``op(ex1, ex2)``

    Parameters
    ==========

    op : operation ``Add`` or ``Mul``
    ex1, ex2 : expressions for the algebraic elements
    x : indeterminate of the polynomials
    dom: ground domain
    mp1, mp2 : minimal polynomials for ``ex1`` and ``ex2`` or None

    Examples
    ========

    >>> from sympy import sqrt, Add, Mul, QQ
    >>> from sympy.polys.numberfields import _minpoly_op_algebraic_element
    >>> from sympy.abc import x, y
    >>> p1 = sqrt(sqrt(2) + 1)
    >>> p2 = sqrt(sqrt(2) - 1)
    >>> _minpoly_op_algebraic_element(Mul, p1, p2, x, QQ)
    x - 1
    >>> q1 = sqrt(y)
    >>> q2 = 1 / y
    >>> _minpoly_op_algebraic_element(Add, q1, q2, x, QQ.frac_field(y))
    x**2*y**2 - 2*x*y - y**3 + 1

    References
    ==========

    .. [1] https://en.wikipedia.org/wiki/Resultant
    .. [2] I.M. Isaacs, Proc. Amer. Math. Soc. 25 (1970), 638
           "Degrees of sums in a separable field extension".

    NXr   zoption not availablegensrI   domain)r   str_minpoly_composerQ   r   r   r.   r+   r)   composerL   r	   _mulyre   r&   r-   r,   Zas_expr_dictr'   r!   r$   rm   )opex1ex2rg   ri   mp1mp2rw   Rr   r   r   rW   rZmp1aZdeg1Zdeg2rf   resrB   rB   rF   _minpoly_op_algebraic_element   s:   $




r   c                    s6   t | d }t|  fdd| D }t| S )z@
    Returns ``expand_mul(x**degree(p, x)*p.subs(x, 1/x))``
    r   c                    s"   g | ]\\}}| |   qS rB   rB   rD   rS   crR   rg   rB   rF   rG   0  s   " z_invertx.<locals>.<listcomp>r(   r'   termsr   )r   rg   r   rk   rB   r   rF   _invertx)  s   r   c                    s8   t | d }t|  fdd| D }t| S )z8
    Returns ``_mexpand(y**deg*p.subs({x:x / y}))``
    r   c                    s*   g | ]\\}}||   |   qS rB   rB   r   rR   rg   rw   rB   rF   rG   ;  s   * z_muly.<locals>.<listcomp>r   )r   rg   rw   r   rk   rB   r   rF   r   4  s   r   c                 C   s   t |}|st| ||}|jstd|  |dk r5||kr#td|  t||}|dkr.|S | }d|  } tt|}|||i}|	 \}}t
t||| ||  |gd||d}| \}	}
t|
|| | |}| S )a  
    Returns ``minpoly(ex**pw, x)``

    Parameters
    ==========

    ex : algebraic element
    pw : rational number
    x : indeterminate of the polynomial
    dom: ground domain
    mp : minimal polynomial of ``p``

    Examples
    ========

    >>> from sympy import sqrt, QQ, Rational
    >>> from sympy.polys.numberfields import _minpoly_pow, minpoly
    >>> from sympy.abc import x, y
    >>> p = sqrt(1 + sqrt(2))
    >>> _minpoly_pow(p, 2, x, QQ)
    x**2 - 2*x - 1
    >>> minpoly(p**2, x)
    x**2 - 2*x - 1
    >>> _minpoly_pow(y, Rational(1, 3), x, QQ.frac_field(y))
    x**3 - y
    >>> minpoly(y**Rational(1, 3), x)
    x**3 - y

    *%s doesn't seem to be an algebraic elementr   z
%s is zerorv   rI   r   r   )r
   r   is_rationalr   ZeroDivisionErrorr   r   r   rQ   Zas_numer_denomr!   r&   r$   rm   rL   )exZpwrg   ri   r=   rw   rR   dr   rW   rf   rB   rB   rF   _minpoly_pow?  s(   
&r   c              	   G   sZ   t t|d |d | |}|d |d  }|dd D ]}t t||| ||d}|| }q|S )z.
    returns ``minpoly(Add(*a), dom, x)``
    r   rI   rY   Nr   )r   r   rg   ri   rk   r=   r   ZpxrB   rB   rF   _minpoly_addt     
r   c              	   G   sZ   t t|d |d | |}|d |d  }|dd D ]}t t||| ||d}|| }q|S )z.
    returns ``minpoly(Mul(*a), dom, x)``
    r   rI   rY   Nr   )r   r	   r   rB   rB   rF   _minpoly_mul  r   r   c           	         s(  | j d  \}  tu r|jr|jt}|jr.tt t	 fddt
D  S |jdkrK|dkrKdd  dd	   d
d   d S d dkrwtt  fddt
d D  t	  }t|\}}t|| }|S dtd| t  d tj }t|t}|S td|  )zt
    Returns the minimal polynomial of ``sin(ex)``
    see http://mathworld.wolfram.com/TrigonometryAngles.html
    r   c                    s$   g | ]}| d    |  qS )rI   rB   rD   rS   rk   rR   rg   rB   rF   rG        $ z _minpoly_sin.<locals>.<listcomp>rI   	   @      `      $   rY      c                        g | ]}|   |  qS rB   rB   r   r   rB   rF   rG          r   )ry   as_coeff_Mulr   r   qr
   is_primer   r   r   r`   r   r$   rm   r   r   ro   r   r   r   )	r   rg   r   r   r   rW   rf   r   rp   rB   r   rF   _minpoly_sin  s,   

(
r   c           
         s6  ddl m} | jd  \}  tu r|jr|jdkrD|jdkr2dd  dd   d  d S |jd	krCdd  d
  d S n!|jdkret|j}|j	ret
| }t||d d iS t|jtt  fddtd D  t  d|j  }t|\}}t|| }	|	S td|  )zt
    Returns the minimal polynomial of ``cos(ex)``
    see http://mathworld.wolfram.com/TrigonometryAngles.html
    r   )r   rI         r   r   rY   r   r   c                    r   rB   rB   r   r   rB   rF   rG     r   z _minpoly_cos.<locals>.<listcomp>rv   r   )sympyr   ry   r   r   r   r   r   r
   r   r   r   rQ   intr   r   r`   r   r$   rm   r   )
r   rg   r   r   r   rj   r   rW   rf   r   rB   r   rF   _minpoly_cos  s.   

$





r   c                 C   s   | j d  \}}|tu rf|jrf|d }t|j}|jd dkr"|nd}g }t|jd d |d dD ] }||||   ||| d  ||   |d |d   }q3t	| }t
|\}}	t|	|| }
|
S td|  )zk
    Returns the minimal polynomial of ``tan(ex)``
    see https://github.com/sympy/sympy/issues/21430
    r   rY   rI   r   )ry   r   r   r   r   r   r   r`   r{   r   r$   rm   r   )r   rg   r   rk   rR   r   rO   r   rW   rf   r   rB   rB   rF   _minpoly_tan  s   
,r   c           	         sR  | j d  \}}t|j}|tt kr|jr|jdks!|jdkr|dkr- d   d S |dkr7 d d S |dkrE d  d  d S |dkrO d d S |d	kr] d  d  d S |d
krs d  d   d   d  d S |jrd}t	|D ]	}|  | 7 }q||S  fddt
d| D }t| | }|S td|  td|  )z7
    Returns the minimal polynomial of ``exp(ex)``
    r   rI   rv   r   rY   r   r   r   r   rJ   c                    s   g | ]}t | qS rB   r0   r   rg   rB   rF   rG     s    z _minpoly_exp.<locals>.<listcomp>r   )ry   r   r
   r   r   r   r   r   r   r`   r   rm   r   )	r   rg   r   rk   r   rj   rS   rf   r=   rB   r   rF   _minpoly_exp  s6   
$r   c                 C   s:   | j }|| jjd |i}t||\}}t||| }|S )zA
    Returns the minimal polynomial of a ``CRootOf`` object.
    r   )rp   rQ   polyr   r$   rm   )r   rg   r   rW   rf   r   rB   rB   rF   _minpoly_rootof  s
   r   c              	      s  | j r| j| | j S | tu r,t|d d ||d\}}t|dkr(|d d S |t S | tu r[t|d | d ||d\}}t|dkrM|d | d S t||dtd d |dS | t	u rt|d |d  | d ||d\}}t|dkr|d |d  | d S dt
ddtd   t
ddtd   d }t||||dS t|d	r| |jv r||  S |jrt| r| |8 } 	 t| }|| u r| S |} q| jrt||g| jR  }|S | jrlt| j}t| d
d }	|	d r`|tkr`tdd |	d |	d  D  }t|	d }
dd |
 D }tt|d tj}|
 |tj!} fdd|
 D }t| }t"||}|j|   |j||     }|| |t#d   }t$t||||||d}|S t%||g| jR  }|S | j&r{t'| j(| j)||}|S | j*t+u rt,| |}|S | j*t-u rt.| |}|S | j*t/u rt0| |}|S | j*t)u rt1| |}|S | j*t2u rt3| |}|S t4d|  )a  
    Computes the minimal polynomial of an algebraic element
    using operations on minimal polynomials

    Examples
    ========

    >>> from sympy import minimal_polynomial, sqrt, Rational
    >>> from sympy.abc import x, y
    >>> minimal_polynomial(sqrt(2) + 3*Rational(1, 3), x, compose=True)
    x**2 - 2*x - 1
    >>> minimal_polynomial(sqrt(y) + 1/y, x, compose=True)
    x**2*y**2 - 2*x*y - y**3 + 1

    rY   rI   r   r?   )ri   r      !   rK   c                 S   s   | d j o	| d j S )Nr   rI   )is_Rational)ZitxrB   rB   rF   rt   O  rH   z"_minpoly_compose.<locals>.<lambda>Tc                 S   s   g | ]\}}|| qS rB   rB   )rD   Zbxr   rB   rB   rF   rG   Q      z$_minpoly_compose.<locals>.<listcomp>FNc                 S      g | ]}|j qS rB   )r   )rD   rw   rB   rB   rF   rG   S      c                    s$   g | ]\}}||j   |j  qS rB   )r   r   )rD   baserw   ZlcmdensrB   rF   rG   W  r   )r   r   r   )5r   r   r   r   r$   r]   r   rm   r   r   r   r^   rK   is_QQr7   r   is_Addr   ry   rz   r   rf   r;   itemsr   r	   dictvaluesr   r*   r   ZNegativeOnepopZZerominimal_polynomialr   r   r   rn   r   r   r   	__class__r   r   r   r   r   r   r   r/   r   r   )r   rg   ri   rW   rf   Zfacr   r   rE   r   Zr1ZdensZneg1Zexpn1Znumsr   r   r   rB   r   rF   r     s    &0&

 

	


r   TFc                 C   sV  ddl m} ddlm} ddlm} t| } | jrt| dd} || D ]	}|j	r,d} nq#|dur9t|t
}}	ntd	t}}	|sP| jrN|tt| j}nt}t|d
rb||jv rbtd||f |rt| ||}
|
 d }
|
|||
| }|jrt|
 }
|r|	|
|ddS |
|S |jstdt| ||	}
|r|	|
|ddS |
|S )a-  
    Computes the minimal polynomial of an algebraic element.

    Parameters
    ==========

    ex : Expr
        Element or expression whose minimal polynomial is to be calculated.

    x : Symbol, optional
        Independent variable of the minimal polynomial

    compose : boolean, optional (default=True)
        Method to use for computing minimal polynomial. If ``compose=True``
        (default) then ``_minpoly_compose`` is used, if ``compose=False`` then
        groebner bases are used.

    polys : boolean, optional (default=False)
        If ``True`` returns a ``Poly`` object else an ``Expr`` object.

    domain : Domain, optional
        Ground domain

    Notes
    =====

    By default ``compose=True``, the minimal polynomial of the subexpressions of ``ex``
    are computed, then the arithmetic operations on them are performed using the resultant
    and factorization.
    If ``compose=False``, a bottom-up algorithm is used with ``groebner``.
    The default algorithm stalls less frequently.

    If no ground domain is given, it will be generated automatically from the expression.

    Examples
    ========

    >>> from sympy import minimal_polynomial, sqrt, solve, QQ
    >>> from sympy.abc import x, y

    >>> minimal_polynomial(sqrt(2), x)
    x**2 - 2
    >>> minimal_polynomial(sqrt(2), x, domain=QQ.algebraic_field(sqrt(2)))
    x - sqrt(2)
    >>> minimal_polynomial(sqrt(2) + sqrt(3), x)
    x**4 - 10*x**2 + 1
    >>> minimal_polynomial(solve(x**3 + x + 3)[0], x)
    x**3 + x + 3
    >>> minimal_polynomial(sqrt(y), x)
    x**2 - y

    r   r'   )FractionField)preorder_traversalT)	recursiveFNrg   rK   z5the variable %s is an element of the ground domain %srI   )Zfieldz!groebner method only works for QQ)sympy.polys.polytoolsr'   sympy.polys.domainsr   Zsympy.core.basicr   r
   r_   r   is_AlgebraicNumberr!   r   r"   Zfree_symbolsr   listr^   rK   r    r   r   r   Zis_negativer   Zcollectr   re   _minpoly_groebner)r   rg   r   polysr   r'   r   r   rp   clsr   r   rB   rB   rF   r   u  sB   6
r   c                    s  ddl m} ddlm} tdtdi i dfdd	 fd	d
 dd }d}|| } | jr>| jS | j	rJ| j
 | j }nb|| }|rT| d } d}| jrld| j jrld| j }	t| j|	}nt| rwt| tj}|dur}|}|du r | }
|
 gt  }t|t g dd}t|d \}}t|| }|rt|}||| dk rt| }|S )a/  
    Computes the minimal polynomial of an algebraic number
    using Groebner bases

    Examples
    ========

    >>> from sympy import minimal_polynomial, sqrt, Rational
    >>> from sympy.abc import x
    >>> minimal_polynomial(sqrt(2) + 3*Rational(1, 3), x, compose=False)
    x**2 - 2*x - 1

    r   r   )expand_multinomialrk   )r   Nc                    s>   t  }|| < |d ur|| | | < |S ||| < |S rV   )nextrL   )r   r   r   rk   )	generatormappingrK   rB   rF   update_mapping  s   z)_minpoly_groebner.<locals>.update_mappingc                    sz  | j r| tju r| vr| ddS |  S | jr| S n| jr+t fdd| jD  S | jr:t fdd| jD  S | j	r| j
jr| j
dk rlt| j}t| }|| j }| j
dkrf |S || j
  } | j
js| j| j
j  td| j
j}}n| j| j
}} |}|| }|vr|d| | S | S n| jr| jvr| j| jS | j S td|  )	NrY   rI   c                       g | ]} |qS rB   rB   rD   r   bottom_up_scanrB   rF   rG     rH   z=_minpoly_groebner.<locals>.bottom_up_scan.<locals>.<listcomp>c                    r   rB   rB   r   r   rB   rF   rG      rH   r   rv   z)%s doesn't seem to be an algebraic number)r}   r   ZImaginaryUnitr   r   r   ry   rz   r	   rn   r   r   r   r#   rL   rQ   expandr   r   r   r   r   rootminpolyr   )r   Zminpoly_baseZinverseZbase_invr   r   rp   )r   r   r   rK   r   rg   rB   rF   r     sH   




z)_minpoly_groebner.<locals>.bottom_up_scanc                 S   st   | j rd| j jr| jdk r| jjrdS | jr8d}| jD ]}|jr$ dS |j r3|jjr3|jdkr3 dS q|r8dS dS )z
        Returns True if it is more likely that the minimal polynomial
        algorithm works better with the inverse
        rI   r   TF)rn   r   r~   r   r   rz   ry   )r   Zhitr   rB   rB   rF   simpler_inverse   s    
z*_minpoly_groebner.<locals>.simpler_inverseFrv   rI   Zlex)ZorderrV   )r   r'   sympy.core.functionr   r8   r   r   r   rL   r   r   r   rn   r   r   r   r   r7   r   r|   r   r   r%   r$   rm   r   r   r   )r   rg   r   r'   r   r   invertedr   r   rR   Zbusr   GrW   rf   rB   )r   r   r   r   rK   r   rg   rF   r     sF   
,


r   c                 C   s*   | j  }|j|dd}| || jd S )NT)Zfrontr   )repZinjectZejectnewr   )r   KZfrepZhreprB   rB   rF   _switch_domain^  s   
r   c                 C   s   | j j \}}| | S rV   r   )r   r   r   rB   rB   rF   	_linsolveh  s   
r   )r   r   c                   s  | st d|durt|t}}ntdt}}|sa| d dg}}t||dd}| dd D ]"}t||d\}	}
t|
||}| \}}	}||| 7 }|	| q0|s[|
 |fS |||fS | d dg}}t||dd}t||f  jg}| dd D ]W}t||dd}t||f}t||d	\}	}
t|
||}| \}}}||| 7 }|	| t||f t| }t||} j||   fd
d|D |g }qdd |D }|s|
 ||fS |||fS )z4Construct a common number field for all extensions. z3can't compute primitive element for empty extensionNrg   r   rI   Tr   	extensionr   c                    s   g | ]	}t |j qS rB   )r   r   rD   rW   r   ZogenrB   rF   rG     rN   z%primitive_element.<locals>.<listcomp>c                 S   r   rB   r   r   rB   rB   rF   rG     r   )
ValueErrorr
   r!   r   r"   r   r$   rm   Zsqf_normr{   rL   r   Zalgebraic_fieldZunitr   r   Zgcd)r   rg   r   r   r   gencoeffsr   extrW   rf   rj   rE   Zrepsr   LhZerepHrB   r   rF   primitive_elementn  sL   


r  c                 C   s   | j  }|j  }|| dkrdS ||krdS | j  }|j  }d|| |d }}}	 t| }	|	| }
|
|kr>	 dS ||	 d rJ||
 sJdS |d7 }q/)z5Returns `True` if there is a chance for isomorphism. r   FTrI   rY   )r   r'   Zdiscriminantr   )rk   rl   rR   mdaZdbrS   rO   Zhalfr   PrB   rB   rF   is_isomorphism_possible  s&   



r  c                    s  | j jr|j jstd| j}|j|j}d|j d}}}tddD ]}| j |}|j | d g fddtd|D  |g }	t	j
|}
t	_
t|	td	d
d|
t	_
du ra dS |krh}n dS fdddd D d s  d r|ttt|jdd}|||jrtd d}}tD ]\}}|| ||   7 }q|| dk rdd D   S   S || |jrdd D   S |d9 }q&dS )z2Construct field isomorphism using PSLQ algorithm. z)PSLQ doesn't support complex coefficientsd   NrI   r?   c                    s   g | ]} | qS rB   rB   r   )BrB   rF   rG     rH   z*field_isomorphism_pslq.<locals>.<listcomp>rY   g    _Bi  )ZmaxcoeffZmaxstepsc                    s   g | ]
}t | d   qS )rv   )r   rD   r   )r  rB   rF   rG     s    rv   r   r   r   c                 S      g | ]}| qS rB   rB   r  rB   rB   rF   rG     r   c                 S   r  rB   rB   r  rB   rB   rF   rG     r   )r   is_realre   r   replacer  r'   r`   evalfr=   dpsr<   r   r   r   reversedr!   r   ZremZis_zeror]   rb   )rk   rl   rE   r   rR   r	  prevrS   AZbasisr  r  r   Zapproxr   rB   )r  r  rF   field_isomorphism_pslq  sH   &
r  c                 C   s   t | j|d\}}|D ]V\}}| dkra|j  }t|d g }}t|D ]\}}	||	|j	||    q)t
| }
| j	|
 jdddkrM|  S | j	|
 jdddkradd |D   S qdS )	z/Construct field isomorphism via factorization. r   rI   T)Zchopr   c                 S   r  rB   rB   r  rB   rB   rF   rG     r   z,field_isomorphism_factor.<locals>.<listcomp>N)r$   r   r'   r   ZTCZto_sympy_listr]   rb   r{   r   r   r  )rk   rl   rW   rf   rE   r  r   r   rS   r   r   rB   rB   rF   field_isomorphism_factor  s   r  )fastc                C   s   t | t |} }| jst| } |jst|}| |kr|  S | j }|j }|dkr1| jgS || dkr9dS |rSzt| |}|durH|W S W n	 tyR   Y nw t	| |S )z4Construct an isomorphism between two number fields. rI   r   N)
r
   r   r   r  r   r'   r   r  re   r  )rk   rl   r  rR   r	  r   rB   rB   rF   field_isomorphism  s.   



r  r  c                C   s   t | dr
t| } n| g} t| dkr!t| d tu r!t| d S t| |dd\}}tdd t|| D }|du r@t||fS t	|}|j
sMt||d	}t||}|dur[t||S td
||jf )z7Express `extension` in the field generated by `theta`. __iter__rI   r   Tr   c                 S   s   g | ]\}}|| qS rB   rB   )rD   r   r  rB   rB   rF   rG   <  r   z#to_number_field.<locals>.<listcomp>Nr  z%s is not in a subfield of %s)r^   r   r]   typer\   r   r  sumra   r
   r   r  r   r   )r   Zthetar  r   r  r   rB   rB   rF   to_number_field0  s$   



r   c                       sD   e Zd ZdZ fddZ fddZ fddZ fdd	Z  ZS )
IntervalPrinterz?Use ``lambda`` printer but print numbers as ``mpi`` intervals. c                       dt t| | S Nz	mpi('%s'))superr3   _print_Integerselfrp   r   rB   rF   r%  R     zIntervalPrinter._print_Integerc                    r"  r#  r$  r3   _print_Rationalr&  r(  rB   rF   r+  U  r)  zIntervalPrinter._print_Rationalc                    r"  r#  r*  r&  r(  rB   rF   _print_HalfX  r)  zIntervalPrinter._print_Halfc                    s   t t| j|ddS )NT)Zrational)r$  r4   
_print_Powr&  r(  rB   rF   r-  [  r)  zIntervalPrinter._print_Pow)	__name__
__module____qualname____doc__r%  r+  r,  r-  __classcell__rB   rB   r(  rF   r!  O  s    r!  c           
      C   s   t | } | jr| | fS | jstdtd| dt d}t| dd}|jdd}tj	d}}z(|sQ| } |D ]\}}	|| j
krG| j|	krGd} nq5t j	d	9  _	|r0W |t_	n|t_	w |d
uri|j||	||d\}}	||	fS )z<Give a rational isolating interval for an algebraic number. z+complex algebraic numbers are not supportedrB   mpmath)modulesZprinterTr   )ZsqfFrY   N)epsr  )r
   r   r  re   r9   r!  r   	intervalsr=   r  rk   rl   Zrefine_root)
Zalgr5  r  funcr   r6  r  Zdonerk   rl   rB   rB   rF   isolate^  s4   
r8  )NNrV   )NTFN)NF)qr1  	functoolsr   r   r   r   r   r   r   r   r	   r
   r   r   r   r   Zsympy.functionsr   r   Zsympy.core.exprtoolsr   r   r   Z&sympy.functions.elementary.exponentialr   Z(sympy.functions.elementary.trigonometricr   r   r   Zsympy.ntheoryr   Zsympy.ntheory.factor_r   rx   r   Zsympy.polys.densetoolsr   r   r   r   Zsympy.polys.orthopolysr   Zsympy.polys.polyerrorsr   r   r    r   r!   r"   r#   r$   r%   r&   r'   r(   r)   r*   rZ   r+   r,   Zsympy.polys.ring_seriesr-   Zsympy.polys.ringsr.   Zsympy.polys.rootoftoolsr/   Zsympy.polys.specialpolysr1   Zsympy.printing.lambdareprr2   Zsympy.printing.pycoder3   r4   Zsympy.simplify.radsimpr5   r   r7   Zsympy.utilitiesr8   r9   r:   r;   r3  r<   r=   rm   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   r!  r8  rB   rB   rB   rF   <module>   sz    801A
8O
5& $\_ 
26"