U
    ZÊ¹jª%  ã                   @   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r–dgZedkrÒddlZej d¡^ZZZeeƒeeƒfdk rÖd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 k	rÂt j‰t j}tj‰z| ˆ¡‰W n  tk
rH   tdˆ ƒ‚Y nX z|ˆƒ W n tk
rr   ˆˆƒ‰Y nX zˆdˆƒ W n* t	k
r¬   |ˆƒ‰ ‡ ‡fdd„}Y nX ‡‡‡fdd„}|S t
ˆ|||ƒS )Nz"modulus must be an integer, got %sr   c                    s0   z
ˆ | ƒW S  t k
r*   ˆ ˆ| ƒƒ Y S X d S ©N©Ú	TypeError©Úx)ÚfctxÚindex© ú^/var/www/html/bwave/python/venv/lib/python3.8/site-packages/sympy/polys/domains/finitefield.pyÚctx=   s    
z!_modular_int_factory.<locals>.ctxc                    s4   zˆ| ˆƒW S  t k
r.   ˆˆ | ƒˆƒ Y S X d S 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"   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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!dAd.d/„Z"dBd0d1„Z#dCd2d3„Z$d4d5„ Z%d6d7„ Z&d8d9„ Z'dS )Dr   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é   )Z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   s   | j S r   )r0   ©r$   r   r   r   ÚtpÇ   s    zFiniteField.tpc                 C   s
   d| j  S )NzGF(%s)©r   r2   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"   r2   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. r4   r2   r   r   r   ÚcharacteristicÖ   s    zFiniteField.characteristicc                 C   s   | S )z*Returns a field associated with ``self``. r   r2   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_Integerr+   r"   Úintr   r
   r@   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. é   )rC   r.   r   )r$   rA   Zavalr   r   r   r?   ë   s    
zFiniteField.to_intc                 C   s   t |ƒS )z#Returns True if ``a`` is positive. )Úboolr@   r   r   r   Úis_positiveò   s    zFiniteField.is_positivec                 C   s   dS )z'Returns True if ``a`` is non-negative. Tr   r@   r   r   r   Úis_nonnegativeö   s    zFiniteField.is_nonnegativec                 C   s   dS )z#Returns True if ``a`` is negative. Fr   r@   r   r   r   Úis_negativeú   s    zFiniteField.is_negativec                 C   s   | S )z'Returns True if ``a`` is non-positive. r   r@   r   r   r   Úis_nonpositiveþ   s    zFiniteField.is_nonpositivec                 C   s   |   | j t|ƒ|j¡¡S ©z.Convert ``ModularInteger(int)`` to ``dtype``. )r+   r"   Úfrom_ZZrC   ©ÚK1rA   ÚK0r   r   r   Úfrom_FF  s    zFiniteField.from_FFc                 C   s   |   | j t|ƒ|j¡¡S rK   )r+   r"   Úfrom_ZZ_pythonrC   rM   r   r   r   Úfrom_FF_python  s    zFiniteField.from_FF_pythonc                 C   s   |   | j ||¡¡S ©z'Convert Python's ``int`` to ``dtype``. ©r+   r"   rQ   rM   r   r   r   rL   
  s    zFiniteField.from_ZZc                 C   s   |   | j ||¡¡S rS   rT   rM   r   r   r   rQ     s    zFiniteField.from_ZZ_pythonc                 C   s   |j dkr|  |j¡S dS ©z,Convert Python's ``Fraction`` to ``dtype``. r*   N©ÚdenominatorrQ   Ú	numeratorrM   r   r   r   Úfrom_QQ  s    
zFiniteField.from_QQc                 C   s   |j dkr|  |j¡S dS rU   rV   rM   r   r   r   Úfrom_QQ_python  s    
zFiniteField.from_QQ_pythonc                 C   s   |   | j |j|j¡¡S )z.Convert ``ModularInteger(mpz)`` to ``dtype``. )r+   r"   Úfrom_ZZ_gmpyÚvalrM   r   r   r   Úfrom_FF_gmpy  s    zFiniteField.from_FF_gmpyc                 C   s   |   | j ||¡¡S )z%Convert GMPY's ``mpz`` to ``dtype``. )r+   r"   r[   rM   r   r   r   r[      s    zFiniteField.from_ZZ_gmpyc                 C   s   |j dkr|  |j¡S dS )z%Convert GMPY's ``mpq`` to ``dtype``. r*   N)rW   r[   rX   rM   r   r   r   Úfrom_QQ_gmpy$  s    
zFiniteField.from_QQ_gmpyc                 C   s,   |  |¡\}}|dkr(|  | j |¡¡S dS )z'Convert mpmath's ``mpf`` to ``dtype``. r*   N)Zto_rationalr+   r"   )rN   rA   rO   Ú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   s   g | ]}t |ƒ‘qS r   ©rC   ©Ú.0r   r   r   r   Ú
<listcomp>3  s     z)FiniteField.is_square.<locals>.<listcomp>)r-   r,   r	   r   r"   )r$   rA   Ú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 ]4}t|ƒdkr@|d | j d kr@|  |d ¡  S q@dS )z·Square root modulo p of ``a`` if it is a quadratic residue.

        Explanation
        ===========
        Always returns the square root that is no larger than ``p // 2``.
        rE   r   c                 S   s   g | ]}t |ƒ‘qS r   rb   rc   r   r   r   re   A  s     z&FiniteField.exsqrt.<locals>.<listcomp>r*   N)r   r-   r,   r   r"   Úlenr+   )r$   rA   rf   Úfactorr   r   r   Úexsqrt6  s    zFiniteField.exsqrt)T)N)N)N)N)N)N)N)N)N)(r8   Ú
__module__Ú__qualname__Ú__doc__ÚrepÚaliasZis_FiniteFieldZis_FFZis_NumericalZhas_assoc_RingZhas_assoc_Fieldr"   r   r1   Úpropertyr3   r5   r9   r<   r=   r>   rB   rD   r?   rG   rH   rI   rJ   rP   rR   rL   rQ   rY   rZ   r]   r[   r^   ra   rg   rj   r   r   r   r   r   Q   sH   X

	








)#rm   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Ú_rC   r%   r   r(   ZGFr   r   r   r   Ú<module>   s2   / v