o
    à8Va†  ã                   @   sn   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 e
G dd	„ d	eeƒƒZe ZZd
S )z.Implementation of :class:`FiniteField` class. é    )ÚField)ÚModularIntegerFactory)ÚSimpleDomain)ÚCoercionFailed)Úpublic)ÚSymPyIntegerc                   @   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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+d$d%„Zd+d&d'„Zd(d)„ ZdS ),ÚFiniteFielda	  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`. Howeer if the ``modulus=p``
    option is given the 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¡| _|| _|| _d S )Nr   )ÚZZz*modulus must be a positive integer, got %sé   )	Zsympy.polys.domainsr
   Ú
ValueErrorr   ÚdtypeZzeroZoneÚdomÚmod)Úselfr   Z	symmetricr
   r   © r   úA/usr/lib/python3/dist-packages/sympy/polys/domains/finitefield.pyÚ__init__r   s   
zFiniteField.__init__c                 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 ©N)ÚhashÚ	__class__Ú__name__r   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. r   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 t|ƒƒS )z!Convert ``a`` to a SymPy object. )r   Úint©r   Úar   r   r   Úto_sympy’   s   zFiniteField.to_sympyc                 C   sP   |j r|  | j t|ƒ¡¡S |jr"t|ƒ|kr"|  | j t|ƒ¡¡S td| ƒ‚)z0Convert SymPy's Integer to SymPy's ``Integer``. zexpected an integer, got %s)Z
is_Integerr   r   r!   Zis_Floatr   r"   r   r   r   Ú
from_sympy–   s
   zFiniteField.from_sympyc                 C   ó   |   | j |j|j¡¡S ©z.Convert ``ModularInteger(int)`` to ``dtype``. )r   r   Úfrom_ZZÚval©ÚK1r#   ÚK0r   r   r   Úfrom_FFŸ   ó   zFiniteField.from_FFc                 C   r&   r'   )r   r   Úfrom_ZZ_pythonr)   r*   r   r   r   Úfrom_FF_python£   r.   zFiniteField.from_FF_pythonc                 C   ó   |   | j ||¡¡S ©z'Convert Python's ``int`` to ``dtype``. ©r   r   r/   r*   r   r   r   r(   §   ó   zFiniteField.from_ZZc                 C   r1   r2   r3   r*   r   r   r   r/   «   r4   zFiniteField.from_ZZ_pythonc                 C   ó   |j dkr|  |j¡S dS ©z,Convert Python's ``Fraction`` to ``dtype``. r   N©Údenominatorr/   Ú	numeratorr*   r   r   r   Úfrom_QQ¯   ó   
ÿzFiniteField.from_QQc                 C   r5   r6   r7   r*   r   r   r   Úfrom_QQ_python´   r;   zFiniteField.from_QQ_pythonc                 C   r&   )z.Convert ``ModularInteger(mpz)`` to ``dtype``. )r   r   Úfrom_ZZ_gmpyr)   r*   r   r   r   Úfrom_FF_gmpy¹   r.   zFiniteField.from_FF_gmpyc                 C   r1   )z%Convert GMPY's ``mpz`` to ``dtype``. )r   r   r=   r*   r   r   r   r=   ½   r4   zFiniteField.from_ZZ_gmpyc                 C   r5   )z%Convert GMPY's ``mpq`` to ``dtype``. r   N)r8   r=   r9   r*   r   r   r   Úfrom_QQ_gmpyÁ   r;   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   )r+   r#   r,   ÚpÚqr   r   r   Úfrom_RealFieldÆ   s   ÿzFiniteField.from_RealField)Tr   )r   Ú
__module__Ú__qualname__Ú__doc__ZrepÚaliasZis_FiniteFieldZis_FFZis_NumericalZhas_assoc_RingZhas_assoc_Fieldr   r   r   r   r   r   r   r    r$   r%   r-   r0   r(   r/   r:   r<   r>   r=   r?   rB   r   r   r   r   r      s8    X

	







r   N)rE   Zsympy.polys.domains.fieldr   Z"sympy.polys.domains.modularintegerr   Z sympy.polys.domains.simpledomainr   Zsympy.polys.polyerrorsr   Zsympy.utilitiesr   Zsympy.polys.domains.groundtypesr   r   r	   ZGFr   r   r   r   Ú<module>   s     B