
    \hA                     &   S r SSKJr  SSKJr  SSKJr  SSKJr  SSK	J
r
Jr  SSKJr  SSKJr  SS	KJr  SS
KJrJr  SSKJr  SSKJrJrJr  SSKJr  SSKJr  S rS r S r!\SS.S j5       r"S r#S r$\SSSS.S jj5       r%\SSSS.S jj5       r&g)a@  
Functions in ``polys.numberfields.subfield`` solve the "Subfield Problem" and
allied problems, for algebraic number fields.

Following Cohen (see [Cohen93]_ Section 4.5), we can define the main problem as
follows:

* **Subfield Problem:**

  Given two number fields $\mathbb{Q}(\alpha)$, $\mathbb{Q}(\beta)$
  via the minimal polynomials for their generators $\alpha$ and $\beta$, decide
  whether one field is isomorphic to a subfield of the other.

From a solution to this problem flow solutions to the following problems as
well:

* **Primitive Element Problem:**

  Given several algebraic numbers
  $\alpha_1, \ldots, \alpha_m$, compute a single algebraic number $\theta$
  such that $\mathbb{Q}(\alpha_1, \ldots, \alpha_m) = \mathbb{Q}(\theta)$.

* **Field Isomorphism Problem:**

  Decide whether two number fields
  $\mathbb{Q}(\alpha)$, $\mathbb{Q}(\beta)$ are isomorphic.

* **Field Membership Problem:**

  Given two algebraic numbers $\alpha$,
  $\beta$, decide whether $\alpha \in \mathbb{Q}(\beta)$, and if so write
  $\alpha = f(\beta)$ for some $f(x) \in \mathbb{Q}[x]$.
    )Add)AlgebraicNumber)S)Dummy)sympify_sympify)sieve)dup_eval)QQ)_choose_factorminimal_polynomial)IsomorphismFailed)PolyPurePolyfactor_list)public)	MPContextc                 h   U R                   R                  5       nUR                   R                  5       nX2-  S:w  a  gX#:X  a  gU R                   R                  5       nUR                   R                  5       nSX2-  US-  pn [        U   n	X-  n
X:  a   gXI-  S-  (       a
  XZ-  (       d  gUS-  nM1  )z3Necessary but not sufficient test for isomorphism. r   FT      )minpolydegreediscriminantr	   )abnmdadbikhalfpPs              Y/var/www/auris/envauris/lib/python3.13/site-packages/sympy/polys/numberfields/subfield.pyis_isomorphism_possibler&   3   s    			A			Auzv	
			!B	
			!BAD"a%$A
!HD8  VqL26	Q     c                    U R                   R                  (       a  UR                   R                  (       d  [        S5      eU R                  nUR                  R	                  UR
                  5      nSUR                  R                  5       Spen[        5       n[        SS5       GH3  nU R                   R                  U5      n	UR                   R                  U5      n
SU
/[        SU5       Vs/ s H  oU-  PM	     sn-   U	* /-   nXGl
        UR                  USSS	9nUc    gX:w  a  UnO  gUSS
  Vs/ s H  n[        U5      US
   -  PM     nnUS
   (       d  UR                  5         US
   (       d  M  [        [        U5      5      n[!        XR
                  SS9nUR#                  U5      R%                  U5      R&                  (       a  Us  $ US-  nGM6     gs  snf s  snf )z2Construct field isomorphism using PSLQ algorithm. z)PSLQ doesn't support complex coefficientsd   Nr      r   l    d(	 i  )maxcoeffmaxstepsr   domain)rootis_realNotImplementedErrorr   replacegenr   r   rangeevalfdpspslqr   poplistreversedr   composeremis_zero)r   r   fgr   r   prevctxr    ABbasiscoeffschs                  r%   field_isomorphism_pslqrI   R   s   66>>!"MNN			A			!%% Aaii&&($$A
+C1a[FFLLOFFLLOAq!6Aa4661"=%&4@>> ; >D 2 % ,2#2;7;a!A$vbz/;7 *JJL ** hv&'t, 99Q<A&& MFAQ T M 7( 8s   1G6G$c                    [        U R                  US9u  p#U H  u  pBUR                  5       S:X  d  M  UR                  R	                  5       * nUR                  5       n[        U5      S-
  / p[        U5       H'  u  pUR                  XR                  Xy-
  -  -  5        M)     [        U6 nU R                  R                  X5      (       d  M  Us  $    g)z/Construct field isomorphism via factorization. 	extensionr   N)r   r   r   repTCto_sympy_listlen	enumerateappendr0   r   	same_root)r   r   _factorsr?   rG   rF   dtermsr    coeffrs               r%   field_isomorphism_factorrZ      s    QYY!4JA88:? A__&F6{Qu%f-U66AE?23 .UAyy""1(( $ r'   T)fastc                   [        U 5      [        U5      pU R                  (       d  [        U 5      n UR                  (       d  [        U5      nU R                  5       n UR                  5       nX:X  a  U R	                  5       $ U R
                  R                  5       nUR
                  R                  5       nUS:X  a  U R                  /$ XC-  S:w  a  gU(       a   [        X5      nUb  U$  [        X5      $ ! [         a     Nf = f)aL  
Find an embedding of one number field into another.

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

This function looks for an isomorphism from $\mathbb{Q}(a)$ onto some
subfield of $\mathbb{Q}(b)$. Thus, it solves the Subfield Problem.

Examples
========

>>> from sympy import sqrt, field_isomorphism, I
>>> print(field_isomorphism(3, sqrt(2)))  # doctest: +SKIP
[3]
>>> print(field_isomorphism( I*sqrt(3), I*sqrt(3)/2))  # doctest: +SKIP
[2, 0]

Parameters
==========

a : :py:class:`~.Expr`
    Any expression representing an algebraic number.
b : :py:class:`~.Expr`
    Any expression representing an algebraic number.
fast : boolean, optional (default=True)
    If ``True``, we first attempt a potentially faster way of computing the
    isomorphism, falling back on a slower method if this fails. If
    ``False``, we go directly to the slower method, which is guaranteed to
    return a result.

Returns
=======

List of rational numbers, or None
    If $\mathbb{Q}(a)$ is not isomorphic to some subfield of
    $\mathbb{Q}(b)$, then return ``None``. Otherwise, return a list of
    rational numbers representing an element of $\mathbb{Q}(b)$ to which
    $a$ may be mapped, in order to define a monomorphism, i.e. an
    isomorphism from $\mathbb{Q}(a)$ to some subfield of $\mathbb{Q}(b)$.
    The elements of the list are the coefficients of falling powers of $b$.

r   r   N)r   is_AlgebraicNumberr   to_primitive_elementrF   r   r   r0   rI   r2   rZ   )r   r   r[   r   r   results         r%   field_isomorphismr`      s    Z 1:wqzqAA	 A	 Avxxz			A			AAvxuz	+A1F! "
 $A)) # 		s   C7 7
DDc                     U R                   R                  5       nUR                  USS9nU R                  X0R                  S   5      $ )NT)frontr   )rM   injectejectnewgens)r@   Kfrephreps       r%   _switch_domainrj      s<     55<<>D::at:$D55vvay!!r'   c                 F    U R                   R                  5       u  pU* U-  $ N)rM   to_list)r#   rG   rV   s      r%   	_linsolvern      s    55==?DA2a4Kr'   NF)expolysc          	      v   U (       d  [        S5      eU  Vs/ s H  n[        U5      PM     n nUb  [        U5      [        pQO[	        S5      [
        pQS nU(       d  U S   S/p[        XqSS9n	U SS  Hk  nUR                  (       a  UR                  S5        M'  [        XS	9u  p[        XU5      n	U	R                  5       u  u  pn	X|U-  -  nUR                  U5        Mm     U" U	5      n	U(       d  U	R                  5       U4$ U" U	5      U4$ U S   S/p[        XqSS9n[        R                  " X45      nUR                  /nU SS  GH-  nUR                  (       a3  UR                  S5        UR                  UR!                  U5      5        MH  [        XASS9n[        R                  " UU45      n[        UUS
9u  p[        XU5      nUR                  5       u  u  pnX|U-  -  nUR                  U5        [        R                  " X45      n[#        X5      n[%        UR'                  U5      5      nUR                  UU-  -
  nU V
s/ s H  n
[)        U
R+                  5       UU5      PM      sn
U/-   nGM0     UR,                  R.                  R                  (       aE  U  V
s/ s H  oR!                  U
5      R0                  PM     nn
S/[3        U 5      -  nU" U[        S
9nOU V
s/ s H  oR+                  5       PM     nn
U" U5      nU(       d  UR                  5       UU4$ XU4$ s  snf s  sn
f s  sn
f s  sn
f )a  
Find a single generator for a number field given by several generators.

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

The basic problem is this: Given several algebraic numbers
$\alpha_1, \alpha_2, \ldots, \alpha_n$, find a single algebraic number
$\theta$ such that
$\mathbb{Q}(\alpha_1, \alpha_2, \ldots, \alpha_n) = \mathbb{Q}(\theta)$.

This function actually guarantees that $\theta$ will be a linear
combination of the $\alpha_i$, with non-negative integer coefficients.

Furthermore, if desired, this function will tell you how to express each
$\alpha_i$ as a $\mathbb{Q}$-linear combination of the powers of $\theta$.

Examples
========

>>> from sympy import primitive_element, sqrt, S, minpoly, simplify
>>> from sympy.abc import x
>>> f, lincomb, reps = primitive_element([sqrt(2), sqrt(3)], x, ex=True)

Then ``lincomb`` tells us the primitive element as a linear combination of
the given generators ``sqrt(2)`` and ``sqrt(3)``.

>>> print(lincomb)
[1, 1]

This means the primtiive element is $\sqrt{2} + \sqrt{3}$.
Meanwhile ``f`` is the minimal polynomial for this primitive element.

>>> print(f)
x**4 - 10*x**2 + 1
>>> print(minpoly(sqrt(2) + sqrt(3), x))
x**4 - 10*x**2 + 1

Finally, ``reps`` (which was returned only because we set keyword arg
``ex=True``) tells us how to recover each of the generators $\sqrt{2}$ and
$\sqrt{3}$ as $\mathbb{Q}$-linear combinations of the powers of the
primitive element $\sqrt{2} + \sqrt{3}$.

>>> print([S(r) for r in reps[0]])
[1/2, 0, -9/2, 0]
>>> theta = sqrt(2) + sqrt(3)
>>> print(simplify(theta**3/2 - 9*theta/2))
sqrt(2)
>>> print([S(r) for r in reps[1]])
[-1/2, 0, 11/2, 0]
>>> print(simplify(-theta**3/2 + 11*theta/2))
sqrt(3)

Parameters
==========

extension : list of :py:class:`~.Expr`
    Each expression must represent an algebraic number $\alpha_i$.
x : :py:class:`~.Symbol`, optional (default=None)
    The desired symbol to appear in the computed minimal polynomial for the
    primitive element $\theta$. If ``None``, we use a dummy symbol.
ex : boolean, optional (default=False)
    If and only if ``True``, compute the representation of each $\alpha_i$
    as a $\mathbb{Q}$-linear combination over the powers of $\theta$.
polys : boolean, optional (default=False)
    If ``True``, return the minimal polynomial as a :py:class:`~.Poly`.
    Otherwise return it as an :py:class:`~.Expr`.

Returns
=======

Pair (f, coeffs) or triple (f, coeffs, reps), where:
    ``f`` is the minimal polynomial for the primitive element.
    ``coeffs`` gives the primitive element as a linear combination of the
    given generators.
    ``reps`` is present if and only if argument ``ex=True`` was passed,
    and is a list of lists of rational numbers. Each list gives the
    coefficients of falling powers of the primitive element, to recover
    one of the original, given generators.

z4Cannot compute primitive element for empty extensionNxc                 X    U R                  5       u  pU R                  5       S:  a  U * n U $ )Nr   )	primitiveLC)r?   rT   s     r%   _canonicalize(primitive_element.<locals>._canonicalize^  s(    {{}446A:Ar'   r   r   Trp   rK   r.   )
ValueErrorr   r   r   r   r   r   is_RationalrR   r   r   sqf_normas_exprr   algebraic_fieldunitconvertrj   rn   gcdr
   rm   extr0   rM   rP   )rL   rr   ro   rp   r   clsrv   r4   rF   r@   rT   rU   sr?   rg   repsr#   LrH   erepogenHs                         r%   primitive_elementr     s   f OPP*34)3#)I4}T3sX3 lQCVsT2QR=Ca $Q6JAw3/A

ICQAS5LCMM! ! !99;&&q66>!A,3.A
A8$AFF8D}??MM!KK		#'sT23x( 1-
7s+JJL	uax(1 q"vv$8<=1dA.=F! $ 	uuzz'01y!YYq\y1S^#""&'$QYY[$'aAyy{FA%%!|C 5h > 2 (s   L'%L,!$L1&L6r4   aliasc                   [        U S5      (       a  [        U 5      n OU /n [        U 5      S:X  a%  [        U S   [        5      (       a  [        U S   US9$ [        XSS9u  pE[        S [        XP5       5       5      nUc  [        XF4US9$ [        U5      nUR                  (       d
  [        XUS9n[        Xa5      nUb
  [        XUS9$ [        U< S	UR                  < 35      e)
a	  
Express one algebraic number in the field generated by another.

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

Given two algebraic numbers $\eta, \theta$, this function either expresses
$\eta$ as an element of $\mathbb{Q}(\theta)$, or else raises an exception
if $\eta \not\in \mathbb{Q}(\theta)$.

This function is essentially just a convenience, utilizing
:py:func:`~.field_isomorphism` (our solution of the Subfield Problem) to
solve this, the Field Membership Problem.

As an additional convenience, this function allows you to pass a list of
algebraic numbers $\alpha_1, \alpha_2, \ldots, \alpha_n$ instead of $\eta$.
It then computes $\eta$ for you, as a solution of the Primitive Element
Problem, using :py:func:`~.primitive_element` on the list of $\alpha_i$.

Examples
========

>>> from sympy import sqrt, to_number_field
>>> eta = sqrt(2)
>>> theta = sqrt(2) + sqrt(3)
>>> a = to_number_field(eta, theta)
>>> print(type(a))
<class 'sympy.core.numbers.AlgebraicNumber'>
>>> a.root
sqrt(2) + sqrt(3)
>>> print(a)
sqrt(2)
>>> a.coeffs()
[1/2, 0, -9/2, 0]

We get an :py:class:`~.AlgebraicNumber`, whose ``.root`` is $\theta$, whose
value is $\eta$, and whose ``.coeffs()`` show how to write $\eta$ as a
$\mathbb{Q}$-linear combination in falling powers of $\theta$.

Parameters
==========

extension : :py:class:`~.Expr` or list of :py:class:`~.Expr`
    Either the algebraic number that is to be expressed in the other field,
    or else a list of algebraic numbers, a primitive element for which is
    to be expressed in the other field.
theta : :py:class:`~.Expr`, None, optional (default=None)
    If an :py:class:`~.Expr` representing an algebraic number, behavior is
    as described under **Explanation**. If ``None``, then this function
    reduces to a shorthand for calling :py:func:`~.primitive_element` on
    ``extension`` and turning the computed primitive element into an
    :py:class:`~.AlgebraicNumber`.
gen : :py:class:`~.Symbol`, None, optional (default=None)
    If provided, this will be used as the generator symbol for the minimal
    polynomial in the returned :py:class:`~.AlgebraicNumber`.
alias : str, :py:class:`~.Symbol`, None, optional (default=None)
    If provided, this will be used as the alias symbol for the returned
    :py:class:`~.AlgebraicNumber`.

Returns
=======

AlgebraicNumber
    Belonging to $\mathbb{Q}(\theta)$ and equaling $\eta$.

Raises
======

IsomorphismFailed
    If $\eta \not\in \mathbb{Q}(\theta)$.

See Also
========

field_isomorphism
primitive_element

__iter__r   r   )r   Trx   c              3   .   #    U  H  u  pX-  v   M     g 7frl    ).0rX   r   s      r%   	<genexpr>"to_number_field.<locals>.<genexpr>  s     B+AZUuy+As   r   z is not in a subfield of )hasattrr:   rP   
isinstancetupler   r   sumzipr   r]   r`   r   r0   )rL   thetar4   r   r   rF   r0   s          r%   to_number_fieldr     s    ` y*%%O	K	
9~z)A,>>y|599'	dCOGB3v+ABBD}e<<''#E%@E"4/"5>>#37DF Fr'   rl   )'__doc__sympy.core.addr   sympy.core.numbersr   sympy.core.singletonr   sympy.core.symbolr   sympy.core.sympifyr   r   sympy.ntheoryr	   sympy.polys.densetoolsr
   sympy.polys.domainsr    sympy.polys.numberfields.minpolyr   r   sympy.polys.polyerrorsr   sympy.polys.polytoolsr   r   r   sympy.utilitiesr   mpmathr   r&   rI   rZ   r`   rj   rn   r   r   r   r'   r%   <module>r      s    D  . " # 0  + " O 4 = = " >5p0 $( L* L*^" UuE U Up hF$d hF hFr'   