o
    jg%                     @   s  d Z ddl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 dd
lmZ ddlmZ ddlmZ edkrKdgZedkriddlZejd^ZZZeeeefdk rhdZndZdd ZeeddgdG dd de	eZ e  Z!Z"dS )z.Implementation of :class:`FiniteField` class.     N)GROUND_TYPES)doctest_depends_on)
int_valued)Field)ModularIntegerFactory)SimpleDomain)gf_zassenhausgf_irred_p_rabin)CoercionFailed)public)SymPyIntegerflintFiniteField.)r      c                    s   t d ur]t jt j}tjz|W n ty!   td w z| W n ty5   Y nw zd W n t	yR   |  fdd}Y |S w fdd}|S t
|||S )Nz"modulus must be an integer, got %sr   c                    s*   z | W S  t y    |  Y S w N	TypeErrorx)fctxindex W/var/www/html/zoom/venv/lib/python3.10/site-packages/sympy/polys/domains/finitefield.pyctx=   s
   
z!_modular_int_factory.<locals>.ctxc                    s.   z| W S  t y    |  Y S w r   r   r   )r   modnmodr   r   r   E   s
   )r   r   fmpz_mod_ctxoperatorr   convertr
   
ValueErrorr   OverflowErrorr   )r   dom	symmetricselfr   r   r   )r   r   r   r   r   _modular_int_factory"   s0   r%   pythongmpy)modulesc                   @   s  e Zd ZdZdZdZd ZZdZdZ	dZ
dZdZd:ddZedd	 Zd
d Zdd Zdd Zdd Zdd Zdd Zdd Zdd Zdd Zdd Zdd Zd d! Zd;d"d#Zd;d$d%Zd;d&d'Zd;d(d)Zd;d*d+Z d;d,d-Z!d;d.d/Z"d;d0d1Z#d;d2d3Z$d4d5 Z%d6d7 Z&d8d9 Z'dS )<r   a	  Finite field of prime order :ref:`GF(p)`

    A :ref:`GF(p)` domain represents a `finite field`_ `\mathbb{F}_p` of prime
    order as :py:class:`~.Domain` in the domain system (see
    :ref:`polys-domainsintro`).

    A :py:class:`~.Poly` created from an expression with integer
    coefficients will have the domain :ref:`ZZ`. However, if the ``modulus=p``
    option is given then the domain will be a finite field instead.

    >>> from sympy import Poly, Symbol
    >>> x = Symbol('x')
    >>> p = Poly(x**2 + 1)
    >>> p
    Poly(x**2 + 1, x, domain='ZZ')
    >>> p.domain
    ZZ
    >>> p2 = Poly(x**2 + 1, modulus=2)
    >>> p2
    Poly(x**2 + 1, x, modulus=2)
    >>> p2.domain
    GF(2)

    It is possible to factorise a polynomial over :ref:`GF(p)` using the
    modulus argument to :py:func:`~.factor` or by specifying the domain
    explicitly. The domain can also be given as a string.

    >>> from sympy import factor, GF
    >>> factor(x**2 + 1)
    x**2 + 1
    >>> factor(x**2 + 1, modulus=2)
    (x + 1)**2
    >>> factor(x**2 + 1, domain=GF(2))
    (x + 1)**2
    >>> factor(x**2 + 1, domain='GF(2)')
    (x + 1)**2

    It is also possible to use :ref:`GF(p)` with the :py:func:`~.cancel`
    and :py:func:`~.gcd` functions.

    >>> from sympy import cancel, gcd
    >>> cancel((x**2 + 1)/(x + 1))
    (x**2 + 1)/(x + 1)
    >>> cancel((x**2 + 1)/(x + 1), domain=GF(2))
    x + 1
    >>> gcd(x**2 + 1, x + 1)
    1
    >>> gcd(x**2 + 1, x + 1, domain=GF(2))
    x + 1

    When using the domain directly :ref:`GF(p)` can be used as a constructor
    to create instances which then support the operations ``+,-,*,**,/``

    >>> from sympy import GF
    >>> K = GF(5)
    >>> K
    GF(5)
    >>> x = K(3)
    >>> y = K(2)
    >>> x
    3 mod 5
    >>> y
    2 mod 5
    >>> x * y
    1 mod 5
    >>> x / y
    4 mod 5

    Notes
    =====

    It is also possible to create a :ref:`GF(p)` domain of **non-prime**
    order but the resulting ring is **not** a field: it is just the ring of
    the integers modulo ``n``.

    >>> K = GF(9)
    >>> z = K(3)
    >>> z
    3 mod 9
    >>> z**2
    0 mod 9

    It would be good to have a proper implementation of prime power fields
    (``GF(p**n)``) but these are not yet implemented in SymPY.

    .. _finite field: https://en.wikipedia.org/wiki/Finite_field
    FFTFNc                 C   sn   ddl m} |}|dkrtd| t|||| | _| d| _| d| _|| _|| _|| _	t
| j| _d S )Nr   )ZZz*modulus must be a positive integer, got %s   )sympy.polys.domainsr*   r    r%   dtypezerooner"   r   symtype_tp)r$   r   r#   r*   r"   r   r   r   __init__   s   zFiniteField.__init__c                 C      | j S r   )r2   r$   r   r   r   tp      zFiniteField.tpc                 C   s
   d| j  S )NzGF(%s)r   r5   r   r   r   __str__   s   
zFiniteField.__str__c                 C   s   t | jj| j| j| jfS r   )hash	__class____name__r-   r   r"   r5   r   r   r   __hash__   s   zFiniteField.__hash__c                 C   s"   t |to| j|jko| j|jkS )z0Returns ``True`` if two domains are equivalent. )
isinstancer   r   r"   )r$   otherr   r   r   __eq__   s
   


zFiniteField.__eq__c                 C   r4   )z*Return the characteristic of this domain. r8   r5   r   r   r   characteristic   r7   zFiniteField.characteristicc                 C   s   | S )z*Returns a field associated with ``self``. r   r5   r   r   r   	get_field      zFiniteField.get_fieldc                 C   s   t | |S )z!Convert ``a`` to a SymPy object. )r   to_intr$   ar   r   r   to_sympy   s   zFiniteField.to_sympyc                 C   sF   |j r| | jt|S t|r| | jt|S td| )z0Convert SymPy's Integer to SymPy's ``Integer``. zexpected an integer, got %s)
is_Integerr-   r"   intr   r
   rE   r   r   r   
from_sympy   s
   zFiniteField.from_sympyc                 C   s*   t |}| jr|| jd kr|| j8 }|S )z,Convert ``val`` to a Python ``int`` object.    )rI   r0   r   )r$   rF   avalr   r   r   rD      s   
zFiniteField.to_intc                 C   s   t |S )z#Returns True if ``a`` is positive. )boolrE   r   r   r   is_positive   s   zFiniteField.is_positivec                 C      dS )z'Returns True if ``a`` is non-negative. Tr   rE   r   r   r   is_nonnegative   rC   zFiniteField.is_nonnegativec                 C   rO   )z#Returns True if ``a`` is negative. Fr   rE   r   r   r   is_negative   rC   zFiniteField.is_negativec                 C   s   | S )z'Returns True if ``a`` is non-positive. r   rE   r   r   r   is_nonpositive   r7   zFiniteField.is_nonpositivec                 C      |  | jt||jS z.Convert ``ModularInteger(int)`` to ``dtype``. )r-   r"   from_ZZrI   K1rF   K0r   r   r   from_FF     zFiniteField.from_FFc                 C   rS   rT   )r-   r"   from_ZZ_pythonrI   rV   r   r   r   from_FF_python  rZ   zFiniteField.from_FF_pythonc                 C      |  | j||S z'Convert Python's ``int`` to ``dtype``. r-   r"   r[   rV   r   r   r   rU   
     zFiniteField.from_ZZc                 C   r]   r^   r_   rV   r   r   r   r[     r`   zFiniteField.from_ZZ_pythonc                 C      |j dkr| |jS dS z,Convert Python's ``Fraction`` to ``dtype``. r+   Ndenominatorr[   	numeratorrV   r   r   r   from_QQ     
zFiniteField.from_QQc                 C   ra   rb   rc   rV   r   r   r   from_QQ_python  rg   zFiniteField.from_QQ_pythonc                 C   s   |  | j|j|jS )z.Convert ``ModularInteger(mpz)`` to ``dtype``. )r-   r"   from_ZZ_gmpyvalrV   r   r   r   from_FF_gmpy  s   zFiniteField.from_FF_gmpyc                 C   r]   )z%Convert GMPY's ``mpz`` to ``dtype``. )r-   r"   ri   rV   r   r   r   ri      r`   zFiniteField.from_ZZ_gmpyc                 C   ra   )z%Convert GMPY's ``mpq`` to ``dtype``. r+   N)rd   ri   re   rV   r   r   r   from_QQ_gmpy$  rg   zFiniteField.from_QQ_gmpyc                 C   s,   | |\}}|dkr| | j|S dS )z'Convert mpmath's ``mpf`` to ``dtype``. r+   N)to_rationalr-   r"   )rW   rF   rX   pqr   r   r   from_RealField)  s   zFiniteField.from_RealFieldc                 C   s,   dd | j | j| fD }t|| j| j S )z7Returns True if ``a`` is a quadratic residue modulo p. c                 S      g | ]}t |qS r   rI   .0r   r   r   r   
<listcomp>3      z)FiniteField.is_square.<locals>.<listcomp>)r/   r.   r	   r   r"   )r$   rF   polyr   r   r   	is_square0  s   zFiniteField.is_squarec                 C   sz   | j dks	|dkr|S dd | j| j| fD }t|| j | jD ]}t|dkr:|d | j d kr:| |d   S q dS )zSquare root modulo p of ``a`` if it is a quadratic residue.

        Explanation
        ===========
        Always returns the square root that is no larger than ``p // 2``.
        rK   r   c                 S   rq   r   rr   rs   r   r   r   ru   A  rv   z&FiniteField.exsqrt.<locals>.<listcomp>r+   N)r   r/   r.   r   r"   lenr-   )r$   rF   rw   factorr   r   r   exsqrt6  s   zFiniteField.exsqrt)Tr   )(r<   
__module____qualname____doc__repaliasis_FiniteFieldis_FFis_Numericalhas_assoc_Ringhas_assoc_Fieldr"   r   r3   propertyr6   r9   r=   r@   rA   rB   rG   rJ   rD   rN   rP   rQ   rR   rY   r\   rU   r[   rf   rh   rk   ri   rl   rp   rx   r{   r   r   r   r   r   Q   sJ    X

	








)#r~   r   sympy.external.gmpyr   sympy.utilities.decoratorr   sympy.core.numbersr   sympy.polys.domains.fieldr   "sympy.polys.domains.modularintegerr    sympy.polys.domains.simpledomainr   sympy.polys.galoistoolsr   r	   sympy.polys.polyerrorsr
   sympy.utilitiesr   sympy.polys.domains.groundtypesr   __doctest_skip__r   __version__split_major_minor_rI   r%   r   r)   GFr   r   r   r   <module>   s6    / v