
    Ed                          d 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
 ddlmZ dd	lmZmZmZ dd
lmZ d ZddZd Zedd            ZdS )z,Computing integral bases for number fields.     )Poly)AlgebraicField)ZZ)QQ)CoercionFailed)public   )ModuleEndomorphismModuleHomomorphism
PowerBasis) extract_fundamental_discriminantc                    | j         }t          | |          }|                                \  }}|dk    sJ t          d||          }|D ]
\  }}||z  }||z  }	t          |t                    }
t          |	t                    }|
|z  | z
  |z  }t          ||          }|}||	fD ]}|                    |          }||z  }|                                }||fS )zz
    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                     >lib/python3.11/site-packages/sympy/polys/numberfields/basis.py_apply_Dedekind_criterionr*      s
   
 	
AAE  FB7NNNAq!!!E  	UNEU2AU2A	
QqAAEEU^  		!UNEA!8O    Nc                     | j         }||k     r|z  |k     t          | fd          }|                    |          S )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.)

    Nc                     | z  S N )r   qs    r)   <lambda>z"nilradical_mod_p.<locals>.<lambda>L   s    !Q$ r+   r   )nr
   kernel)Hr   r0   r2   phis     `  r)   nilradical_mod_pr6   &   sf    B 	
A !e 	FA !e 	
Q
/
/C::a:   r+   c                   
 t          | ||          }| j                            | j        |j        z  | j                  }||| z  z   }|                                
t          | 

fd          }|                    |          }| j                            | j        |j        z  | j        |z            }|| z   }	|	|fS )zD
    Perform the second enlargement in the Round Two algorithm.
    )r0   )denomc                 .                         |           S r.   )inner_endomorphism)r   Es    r)   r1   z%_second_enlargement.<locals>.<lambda>X   s    Q-A-A!-D-D r+   r   )r6   parentsubmodule_from_matrixmatrixr8   endomorphism_ringr   r3   )r4   r   r0   IpBCr5   gammaGH1r;   s             @r)   _second_enlargementrF   P   s     
!Q!	$	$	$B	&&qx")';17&KKA	AaCA	A
Q#D#D#D#D
E
ECJJqJ!!E	&&qx%,'>agPQk&RRA	
QBr6Mr+   c                    d}t          | t                    r| | j                                        } }| j        t
          k    r(	 t          | t                    } n# t          $ r Y nw xY w| j	        r| j
        r| j        r| j        t          k    st          d          |                                 }|                                 }t          j        t!          |                    }t#          |          \  }}t%          |p|           }|                                }	d}
|r|                                \  }}t+          | |          \  }}|dk    r3|                    t          |t                              }|	                    ||z  |	z  |          }	||k    r|}||k     r||z  }||k     t1          |	||          \  }}
||	k    r|}	t1          |	||          \  }}
||	k    ||
t          |t2                    r|
||<   |	}d|_        d|_        ||j                                        dz  z  |j        d|z  z  z  }||fS )a  
    Zassenhaus's "Round 2" algorithm.

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

    Carry out Zassenhaus's "Round 2" algorithm on a monic irreducible
    polynomial *T* over :ref:`ZZ`. 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 monic polynomial over :ref:`ZZ` 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.*

    Nr   zCRound 2 requires a monic irreducible univariate polynomial over ZZ.r   )hnf_modulusT   )
isinstancer   extminpoly_of_elementr   r   r   r   r   is_univariateis_irreducibleis_monic
ValueErrorr   discriminant
from_sympyabsr   r   whole_submodulepopitemr*   element_from_polyaddrF   dict_starts_with_unity_is_sq_maxrank_HNFr>   detr8   )r   radicalsKr2   D	D_modulusr   FZthetar4   nilradr   er'   r(   Ur0   rE   ZKdKs                       r)   	round_tworg   _   s   @ 	A!^$$ -!%**,,1x2~ 	Qr"""AA 	 	 	D	 ``z` x2~` ^___	

A	Ac!ff%%I ,A..DAqQF  AF
 6yy{{1,Q22q6 	 $$T%%;%;%;<<
 EE!q&1*)E446 	 !e 	FA !e 	(Aq11
FAg 	6A,Q155JB Ag 	6-  6@  j488 	
B B B
bimmoo"
"rxAE':	:Br6Ms   A 
A('A(r.   )__doc__sympy.polys.polytoolsr   "sympy.polys.domains.algebraicfieldr   sympy.polys.domains.integerringr   !sympy.polys.domains.rationalfieldr   sympy.polys.polyerrorsr   sympy.utilities.decoratorr   modulesr
   r   r   	utilitiesr   r*   r6   rF   rg   r/   r+   r)   <module>rq      s
   2 2 & & & & & & = = = = = = . . . . . . 0 0 0 0 0 0 1 1 1 1 1 1 , , , , , , G G G G G G G G G G 7 7 7 7 7 7  2'! '! '! '!T   \ \ \ \ \ \r+   