ó
    Š*£hE   ã                   óŽ   • 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
  SSKJrJrJr  SS	KJr  S
 rSS jrS r\
SS j5       rg)z,Computing integral bases for number fields. é    )ÚPoly)ÚAlgebraicField)ÚZZ)ÚQQ)Úpublicé   )ÚModuleEndomorphismÚModuleHomomorphismÚ
PowerBasis)Ú extract_fundamental_discriminantc                 ób  • U R                   n[        XS9nUR                  5       u  pEUS:X  d   e[        SX!S9nU H	  u  pxXg-  nM     X6-  n	[        U[        S9n
[        U	[        S9nX«-  U -
  U-  n[        XÁS9nUnXi4 H  nUR	                  U5      nM     X>-  nUR                  5       nUU4$ )zn
Apply the "Dedekind criterion" to test whether the order needs to be
enlarged relative to a given prime *p*.
©Úmodulusr   ©Údomain)Úgenr   Úfactor_listr   ÚgcdÚdegree)ÚTÚpÚxÚT_barÚlcÚflÚg_barÚti_barÚ_Úh_barÚgÚhÚfÚf_barÚZ_barÚbÚU_barÚms                     Ú[/home/mande/repo/quber/.venv/lib/python3.13/site-packages/sympy/polys/numberfields/basis.pyÚ_apply_Dedekind_criterionr)      sÃ   € ð
 	
�‰€AÜ�Ñ€EØ×ÑÓ �F€BØ�‹7€Nˆ7Ü��AÑ!€EÛ‰	ˆØ‰Šñ à‰N€EÜˆUœ2Ñ€AÜˆUœ2Ñ€AØ	
‰�‰�qÑ€AÜ�Ñ€EØ€EØ‹^ˆØ—	‘	˜!“Šñ à‰N€EØ�‰‹€AØ�!ˆ8€Oó    Nc                 óŠ   ^• U R                   nTc  UmTU:  a  TU-  mTU:  a  M  [        U U4S j5      nUR                  US9$ )a¦  
Compute the nilradical mod *p* for a given order *H*, and prime *p*.

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

This is the ideal $I$ in $H/pH$ consisting of all elements some positive
power of which is zero in this quotient ring, i.e. is a multiple of *p*.

Parameters
==========

H : :py:class:`~.Submodule`
    The given order.
p : int
    The rational prime.
q : int, optional
    If known, the smallest power of *p* that is $>=$ the dimension of *H*.
    If not provided, we compute it here.

Returns
=======

:py:class:`~.Module` representing the nilradical mod *p* in *H*.

References
==========

.. [1] Cohen, H. *A Course in Computational Algebraic Number Theory*.
(See Lemma 6.1.6.)

c                 ó   >• U T-  $ ©N© )r   Úqs    €r(   Ú<lambda>Ú"nilradical_mod_p.<locals>.<lambda>K   s	   ø€ ¨!¨Qª$r*   r   )Únr	   Úkernel)ÚHr   r/   r2   Úphis     `  r(   Únilradical_mod_pr6   %   sO   ø€ ðB 	
�‰€AØ�yØˆØ�!‹eØ�‰FˆAð �!�eä
˜Q¤Ó
/€CØ�:‰:˜aˆ:Ð Ð r*   c                 ó†  ^
• [        XUS9nU R                  R                  U R                  UR                  -  U R                  S9nXAU -  -   nUR                  5       m
[        U T
U
4S j5      nUR                  US9nU R                  R                  U R                  UR                  -  U R                  U-  S9nX€-   n	X“4$ )z<
Perform the second enlargement in the Round Two algorithm.
)r/   )Údenomc                 ó&   >• TR                  U 5      $ r-   )Úinner_endomorphism)r   ÚEs    €r(   r0   Ú%_second_enlargement.<locals>.<lambda>W   s   ø€ ¨Q×-AÑ-AÀ!Ô-Dr*   r   )r6   ÚparentÚsubmodule_from_matrixÚmatrixr8   Úendomorphism_ringr
   r3   )r4   r   r/   ÚIpÚBÚCr5   ÚgammaÚGÚH1r;   s             @r(   Ú_second_enlargementrG   O   s°   ø€ ô 
˜! !Ñ	$€BØ	�‰×&Ñ& q§x¡x°"·)±)Ñ';À1Ç7Á7Ð&ÐK€AØ	ˆa‰C‰€AØ	×ÑÓ€AÜ
˜Q Ô#DÓ
E€CØ�J‰J˜qˆJÐ!€EØ	�‰×&Ñ& q§x¡x°%·,±,Ñ'>ÀaÇgÁgÐPQÁkÐ&ÐR€AØ	
‰€BØˆ6€Mr*   c                 ó&  • Sn[        U [        5      (       a  X R                  R                  5       pU R                  (       a+  U R
                  (       a  U R                  [        [        4;  a  [        S5      eU R                  5       u  pU R                  5       nU R                  5       n[        R                  " [        U5      5      n[        U5      u  p7[!        U=(       d    U 5      nUR#                  5       n	Sn
U(       a¬  UR%                  5       u  p¼['        X5      u  pÞUS:X  a  M.  UR)                  [+        U[        S95      nU	R-                  Xû-  U	-  US9n	XÎ::  a  Mg  UnUU:  a  UU-  nUU:  a  M  [/        X›U5      u  nn
UU	:w  a  Un	[/        X›U5      u  nn
UU	:w  a  M  U(       a  M¬  U
b  [        U[0        5      (       a  X¡W'   U	nSUl        SUl        UUR6                  R9                  5       S-  -  UR:                  SU-  -  -  nUU4$ )aö
  
Zassenhaus's "Round 2" algorithm.

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

Carry out Zassenhaus's "Round 2" algorithm on an irreducible polynomial
*T* over :ref:`ZZ` or :ref:`QQ`. This computes an integral basis and the
discriminant for the field $K = \mathbb{Q}[x]/(T(x))$.

Alternatively, you may pass an :py:class:`~.AlgebraicField` instance, in
place of the polynomial *T*, in which case the algorithm is applied to the
minimal polynomial for the field's primitive element.

Ordinarily this function need not be called directly, as one can instead
access the :py:meth:`~.AlgebraicField.maximal_order`,
:py:meth:`~.AlgebraicField.integral_basis`, and
:py:meth:`~.AlgebraicField.discriminant` methods of an
:py:class:`~.AlgebraicField`.

Examples
========

Working through an AlgebraicField:

>>> from sympy import Poly, QQ
>>> from sympy.abc import x
>>> T = Poly(x ** 3 + x ** 2 - 2 * x + 8)
>>> K = QQ.alg_field_from_poly(T, "theta")
>>> print(K.maximal_order())
Submodule[[2, 0, 0], [0, 2, 0], [0, 1, 1]]/2
>>> print(K.discriminant())
-503
>>> print(K.integral_basis(fmt='sympy'))
[1, theta, theta/2 + theta**2/2]

Calling directly:

>>> from sympy import Poly
>>> from sympy.abc import x
>>> from sympy.polys.numberfields.basis import round_two
>>> T = Poly(x ** 3 + x ** 2 - 2 * x + 8)
>>> print(round_two(T))
(Submodule[[2, 0, 0], [0, 2, 0], [0, 1, 1]]/2, -503)

The nilradicals mod $p$ that are sometimes computed during the Round Two
algorithm may be useful in further calculations. Pass a dictionary under
`radicals` to receive these:

>>> T = Poly(x**3 + 3*x**2 + 5)
>>> rad = {}
>>> ZK, dK = round_two(T, radicals=rad)
>>> print(rad)
{3: Submodule[[-1, 1, 0], [-1, 0, 1]]}

Parameters
==========

T : :py:class:`~.Poly`, :py:class:`~.AlgebraicField`
    Either (1) the irreducible polynomial over :ref:`ZZ` or :ref:`QQ`
    defining the number field, or (2) an :py:class:`~.AlgebraicField`
    representing the number field itself.

radicals : dict, optional
    This is a way for any $p$-radicals (if computed) to be returned by
    reference. If desired, pass an empty dictionary. If the algorithm
    reaches the point where it computes the nilradical mod $p$ of the ring
    of integers $Z_K$, then an $\mathbb{F}_p$-basis for this ideal will be
    stored in this dictionary under the key ``p``. This can be useful for
    other algorithms, such as prime decomposition.

Returns
=======

Pair ``(ZK, dK)``, where:

    ``ZK`` is a :py:class:`~sympy.polys.numberfields.modules.Submodule`
    representing the maximal order.

    ``dK`` is the discriminant of the field $K = \mathbb{Q}[x]/(T(x))$.

See Also
========

.AlgebraicField.maximal_order
.AlgebraicField.integral_basis
.AlgebraicField.discriminant

References
==========

.. [1] Cohen, H. *A Course in Computational Algebraic Number Theory.*

NzDRound 2 requires an irreducible univariate polynomial over ZZ or QQ.r   r   )Úhnf_modulusTé   )Ú
isinstancer   ÚextÚminpoly_of_elementÚis_univariateÚis_irreducibler   r   r   Ú
ValueErrorÚ)make_monic_over_integers_by_scaling_rootsr   ÚdiscriminantÚ
from_sympyÚabsr   r   Úwhole_submoduleÚpopitemr)   Úelement_from_polyr   ÚaddrG   ÚdictÚ_starts_with_unityÚ_is_sq_maxrank_HNFr?   Údetr8   )r   ÚradicalsÚKr   r2   ÚDÚ	D_modulusÚFÚZthetar4   Únilradr   Úer&   r'   ÚUr/   rF   ÚZKÚdKs                       r(   Ú	round_tworh   ^   sß  € ð@ 	€AÜ�!”^×$Ñ$Ø—%‘%×*Ñ*Ó,ˆ1Ø��Ø××Ø�8‰8œB¤˜8Ó#ÜÐ_Ó`Ð`Ø×6Ñ6Ó8�D€AØ	�‰‹
€AØ	�‰Ó€AÜ—’œc !›fÓ%€Iô ,¨AÓ.�D€AÜ˜Ÿ˜QÓ€FØ×ÑÓ €AØ€FÞ
à�y‰y‹{‰ˆÜ,¨QÓ2‰ˆØ�‹6Ùð ×$Ñ$¤T¨%¼Ñ%;Ó<ˆð
 �E‰E�!‘&˜1‘*¨)ˆEÐ4ˆØ‹6Ùð ˆØ�!‹eØ�‰FˆAð �!�eä(¨¨qÓ1‰
ˆˆFØ�A‹gØˆAÜ,¨Q°1Ó5‰JˆB�ð �A�g÷- ˆ!ð@ Ñœj¨´4×8Ñ8Ø�‰Ø	
€Bà €BÔØ €BÔØ
ˆb�i‰i�m‰m‹o Ñ"Ñ
" r§x¡x°A¸±EÑ':Ñ	:€BØˆrˆ6€Mr*   r-   )Ú__doc__Úsympy.polys.polytoolsr   Ú"sympy.polys.domains.algebraicfieldr   Úsympy.polys.domains.integerringr   Ú!sympy.polys.domains.rationalfieldr   Úsympy.utilities.decoratorr   Úmodulesr	   r
   r   Ú	utilitiesr   r)   r6   rG   rh   r.   r*   r(   Ú<module>rq      sF   ðÙ 2å &Ý =Ý .Ý 0Ý ,ß GÑ GÝ 7òô2'!òTð óWó ñWr*   