a
    kh)                     @   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rdgZedkrddlZejd^ZZZeeeefdk rdZndZdd Zd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                    sd   t j  tjtjzd W n ty<   Y dS 0  fdd}fdd}||fS )Nr   )NNc                    s2   z| W S  t y,    |  Y S 0 d S N	TypeErrorx)indexmodnmod M/var/www/auris/lib/python3.9/site-packages/sympy/polys/domains/finitefield.pyctx/   s    z&_modular_int_factory_nmod.<locals>.ctxc                    s
   |  S r   r   cs)r   	nmod_polyr   r   poly_ctx5   s    z+_modular_int_factory_nmod.<locals>.poly_ctx)operatorr   r   r   r   OverflowErrorr   r   r   r   )r   r   r   r   r   _modular_int_factory_nmod"   s    r#   c                    sD   t jt|  t| tj fdd}fdd}||fS )Nc                    s.   z
 | W S  t y(    |  Y S 0 d S r   r   r   )fctxr   r   r   r   A   s    
z*_modular_int_factory_fmpz_mod.<locals>.ctxc                    s
   |  S r   r   r   )	fctx_polyfmpz_mod_polyr   r   r   H   s    z/_modular_int_factory_fmpz_mod.<locals>.poly_ctx)r    r   r   Zfmpz_mod_ctxZfmpz_mod_poly_ctxr&   r"   r   )r$   r%   r&   r   r   _modular_int_factory_fmpz_mod;   s    

r'   c                 C   s   z| | } W n ty,   td|  Y n0 d\}}}td url|  rld}t| \}}|d u rlt| \}}|d u rt| |||}d }|||fS )Nz"modulus must be an integer, got %s)NNFT)convertr
   
ValueErrorr   Zis_primer#   r'   r   )r   dom	symmetricselfr   r   is_flintr   r   r   _modular_int_factoryN   s    
r.   pythonZ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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 dAd,d-Z!dBd.d/Z"dCd0d1Z#dDd2d3Z$dEd4d5Z%d6d7 Z&d8d9 Z'd:d; Z(dS )Fr   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   s   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   )Zsympy.polys.domainsr2   r)   r.   dtypeZ	_poly_ctxZ	_is_flintzerooner*   r   symtype_tp)r,   r   r+   r2   r*   r   r   r-   r   r   r   __init__   s    zFiniteField.__init__c                 C   s   | j S r   )r9   r,   r   r   r   tp   s    zFiniteField.tpc                 C   s4   t | dd }|d u r0ddlm} || j | _}|S )N	_is_fieldr   )isprime)getattrZsympy.ntheory.primetestr>   r   r=   )r,   Zis_fieldr>   r   r   r   is_Field   s
    zFiniteField.is_Fieldc                 C   s
   d| j  S )NzGF(%s)r   r;   r   r   r   __str__   s    zFiniteField.__str__c                 C   s   t | jj| j| j| jfS r   )hash	__class____name__r4   r   r*   r;   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   s   | j S )z*Return the characteristic of this domain. rA   r;   r   r   r   characteristic   s    zFiniteField.characteristicc                 C   s   | S )z*Returns a field associated with ``self``. r   r;   r   r   r   	get_field  s    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   sJ   |j r| | jt|S t|r:| | jt|S td| dS )z0Convert SymPy's Integer to SymPy's ``Integer``. zexpected an integer, got %sN)Z
is_Integerr4   r*   intr   r
   rM   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.    )rP   r7   r   )r,   rN   Zavalr   r   r   rL     s    
zFiniteField.to_intc                 C   s   t |S )z#Returns True if ``a`` is positive. )boolrM   r   r   r   is_positive  s    zFiniteField.is_positivec                 C   s   dS )z'Returns True if ``a`` is non-negative. Tr   rM   r   r   r   is_nonnegative  s    zFiniteField.is_nonnegativec                 C   s   dS )z#Returns True if ``a`` is negative. Fr   rM   r   r   r   is_negative"  s    zFiniteField.is_negativec                 C   s   | S )z'Returns True if ``a`` is non-positive. r   rM   r   r   r   is_nonpositive&  s    zFiniteField.is_nonpositivec                 C   s   |  | jt||jS z.Convert ``ModularInteger(int)`` to ``dtype``. )r4   r*   from_ZZrP   K1rN   K0r   r   r   from_FF*  s    zFiniteField.from_FFc                 C   s   |  | jt||jS rX   )r4   r*   from_ZZ_pythonrP   rZ   r   r   r   from_FF_python.  s    zFiniteField.from_FF_pythonc                 C   s   |  | j||S z'Convert Python's ``int`` to ``dtype``. r4   r*   r^   rZ   r   r   r   rY   2  s    zFiniteField.from_ZZc                 C   s   |  | j||S r`   ra   rZ   r   r   r   r^   6  s    zFiniteField.from_ZZ_pythonc                 C   s   |j dkr| |jS dS z,Convert Python's ``Fraction`` to ``dtype``. r3   Ndenominatorr^   	numeratorrZ   r   r   r   from_QQ:  s    
zFiniteField.from_QQc                 C   s   |j dkr| |jS dS rb   rc   rZ   r   r   r   from_QQ_python?  s    
zFiniteField.from_QQ_pythonc                 C   s   |  | j|j|jS )z.Convert ``ModularInteger(mpz)`` to ``dtype``. )r4   r*   from_ZZ_gmpyvalrZ   r   r   r   from_FF_gmpyD  s    zFiniteField.from_FF_gmpyc                 C   s   |  | j||S )z%Convert GMPY's ``mpz`` to ``dtype``. )r4   r*   rh   rZ   r   r   r   rh   H  s    zFiniteField.from_ZZ_gmpyc                 C   s   |j dkr| |jS dS )z%Convert GMPY's ``mpq`` to ``dtype``. r3   N)rd   rh   re   rZ   r   r   r   from_QQ_gmpyL  s    
zFiniteField.from_QQ_gmpyc                 C   s,   | |\}}|dkr(| | j|S dS )z'Convert mpmath's ``mpf`` to ``dtype``. r3   N)Zto_rationalr4   r*   )r[   rN   r\   pqr   r   r   from_RealFieldQ  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   s   g | ]}t |qS r   rP   .0r   r   r   r   
<listcomp>[      z)FiniteField.is_square.<locals>.<listcomp>)r6   r5   r	   r   r*   )r,   rN   polyr   r   r   	is_squareX  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 ]4}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``.
        rR   r   c                 S   s   g | ]}t |qS r   ro   rp   r   r   r   rr   i  rs   z&FiniteField.exsqrt.<locals>.<listcomp>r3   N)r   r6   r5   r   r*   lenr4   )r,   rN   rt   Zfactorr   r   r   exsqrt^  s    zFiniteField.exsqrt)T)N)N)N)N)N)N)N)N)N))rE   
__module____qualname____doc__repaliasZis_FiniteFieldZis_FFZis_NumericalZhas_assoc_RingZhas_assoc_Fieldr*   r   r:   propertyr<   r@   rB   rF   rI   rJ   rK   rO   rQ   rL   rT   rU   rV   rW   r]   r_   rY   r^   rf   rg   rj   rh   rk   rn   ru   rw   r   r   r   r   r   l   sL   X


	








)%rz   r    Zsympy.external.gmpyr   Zsympy.utilities.decoratorr   Zsympy.core.numbersr   Zsympy.polys.domains.fieldr   Z"sympy.polys.domains.modularintegerr   Z sympy.polys.domains.simpledomainr   Zsympy.polys.galoistoolsr   r	   Zsympy.polys.polyerrorsr
   Zsympy.utilitiesr   Zsympy.polys.domains.groundtypesr   Z__doctest_skip__r   __version__splitZ_majorZ_minor_rP   r#   r'   r.   r   r1   ZGFr   r   r   r   <module>   s8     