
    Ed                         d Z ddlmZmZmZ ddlmZ ddlmZm	Z	 ddl
mZ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mZ ddlmZ ddlmZ e G d d                      ZdgZdS )z)Implementation of :class:`Domain` class.     )AnyOptionalType)AlgebraicNumber)Basicsympify)default_sort_keyordered)HAS_GMPY)DomainElement)lex)UnificationFailedCoercionFailedDomainError)_unify_gens_not_a_coeff)public)is_sequencec                      e Zd ZdZdZ	 dZ	 dZ	 dZ	 dZ	 dZ		 dZ
	 dxZZdxZZdxZZdxZZdxZZdxZZdxZZdxZZdxZZdxZZdxZZ dxZ!Z"dZ#dZ$dZ%dZ&dZ'dZ(	 dZ)dZ*dZ+d Z,d Z-d Z.d Z/d	 Z0e1d
             Z2d Z3d Z4d Z5d]dZ6d Z7d Z8d Z9d Z:d Z;d Z<d Z=d Z>d Z?d Z@d ZAd ZBd ZCd ZDd ZEd ZFd ZGd  ZHd! ZId" ZJd# ZKd$ ZLd% ZMd]d&ZNd' ZOd( ZPd) ZQd* ZRd+ ZSd, ZTd- ZUeVd.d/ZWeVd.d0ZXd1 ZYd2 ZZdd3d4Z[d^d6Z\d_d8Z]d9 Z^d: Z_d; Z`d< Zad= Zbd> Zcd? Zdd@ ZedA ZfdB ZgdC ZhdD ZidE ZjdF ZkdG ZldH ZmdI ZndJ ZodK ZpdL ZqdM ZrdN ZsdO ZtdP ZudQ ZvdR ZwdS ZxdT ZydU ZzdV Z{dW Z|d]dXZ}e}Z~dY ZdZ Zd]d[Zd\ ZdS )`Domainay  Superclass for all domains in the polys domains system.

    See :ref:`polys-domainsintro` for an introductory explanation of the
    domains system.

    The :py:class:`~.Domain` class is an abstract base class for all of the
    concrete domain types. There are many different :py:class:`~.Domain`
    subclasses each of which has an associated ``dtype`` which is a class
    representing the elements of the domain. The coefficients of a
    :py:class:`~.Poly` are elements of a domain which must be a subclass of
    :py:class:`~.Domain`.

    Examples
    ========

    The most common example domains are the integers :ref:`ZZ` and the
    rationals :ref:`QQ`.

    >>> from sympy import Poly, symbols, Domain
    >>> x, y = symbols('x, y')
    >>> p = Poly(x**2 + y)
    >>> p
    Poly(x**2 + y, x, y, domain='ZZ')
    >>> p.domain
    ZZ
    >>> isinstance(p.domain, Domain)
    True
    >>> Poly(x**2 + y/2)
    Poly(x**2 + 1/2*y, x, y, domain='QQ')

    The domains can be used directly in which case the domain object e.g.
    (:ref:`ZZ` or :ref:`QQ`) can be used as a constructor for elements of
    ``dtype``.

    >>> from sympy import ZZ, QQ
    >>> ZZ(2)
    2
    >>> ZZ.dtype  # doctest: +SKIP
    <class 'int'>
    >>> type(ZZ(2))  # doctest: +SKIP
    <class 'int'>
    >>> QQ(1, 2)
    1/2
    >>> type(QQ(1, 2))  # doctest: +SKIP
    <class 'sympy.polys.domains.pythonrational.PythonRational'>

    The corresponding domain elements can be used with the arithmetic
    operations ``+,-,*,**`` and depending on the domain some combination of
    ``/,//,%`` might be usable. For example in :ref:`ZZ` both ``//`` (floor
    division) and ``%`` (modulo division) can be used but ``/`` (true
    division) cannot. Since :ref:`QQ` is a :py:class:`~.Field` its elements
    can be used with ``/`` but ``//`` and ``%`` should not be used. Some
    domains have a :py:meth:`~.Domain.gcd` method.

    >>> ZZ(2) + ZZ(3)
    5
    >>> ZZ(5) // ZZ(2)
    2
    >>> ZZ(5) % ZZ(2)
    1
    >>> QQ(1, 2) / QQ(2, 3)
    3/4
    >>> ZZ.gcd(ZZ(4), ZZ(2))
    2
    >>> QQ.gcd(QQ(2,7), QQ(5,3))
    1/21
    >>> ZZ.is_Field
    False
    >>> QQ.is_Field
    True

    There are also many other domains including:

        1. :ref:`GF(p)` for finite fields of prime order.
        2. :ref:`RR` for real (floating point) numbers.
        3. :ref:`CC` for complex (floating point) numbers.
        4. :ref:`QQ(a)` for algebraic number fields.
        5. :ref:`K[x]` for polynomial rings.
        6. :ref:`K(x)` for rational function fields.
        7. :ref:`EX` for arbitrary expressions.

    Each domain is represented by a domain object and also an implementation
    class (``dtype``) for the elements of the domain. For example the
    :ref:`K[x]` domains are represented by a domain object which is an
    instance of :py:class:`~.PolynomialRing` and the elements are always
    instances of :py:class:`~.PolyElement`. The implementation class
    represents particular types of mathematical expressions in a way that is
    more efficient than a normal SymPy expression which is of type
    :py:class:`~.Expr`. The domain methods :py:meth:`~.Domain.from_sympy` and
    :py:meth:`~.Domain.to_sympy` are used to convert from :py:class:`~.Expr`
    to a domain element and vice versa.

    >>> from sympy import Symbol, ZZ, Expr
    >>> x = Symbol('x')
    >>> K = ZZ[x]           # polynomial ring domain
    >>> K
    ZZ[x]
    >>> type(K)             # class of the domain
    <class 'sympy.polys.domains.polynomialring.PolynomialRing'>
    >>> K.dtype             # class of the elements
    <class 'sympy.polys.rings.PolyElement'>
    >>> p_expr = x**2 + 1   # Expr
    >>> p_expr
    x**2 + 1
    >>> type(p_expr)
    <class 'sympy.core.add.Add'>
    >>> isinstance(p_expr, Expr)
    True
    >>> p_domain = K.from_sympy(p_expr)
    >>> p_domain            # domain element
    x**2 + 1
    >>> type(p_domain)
    <class 'sympy.polys.rings.PolyElement'>
    >>> K.to_sympy(p_domain) == p_expr
    True

    The :py:meth:`~.Domain.convert_from` method is used to convert domain
    elements from one domain to another.

    >>> from sympy import ZZ, QQ
    >>> ez = ZZ(2)
    >>> eq = QQ.convert_from(ez, ZZ)
    >>> type(ez)  # doctest: +SKIP
    <class 'int'>
    >>> type(eq)  # doctest: +SKIP
    <class 'sympy.polys.domains.pythonrational.PythonRational'>

    Elements from different domains should not be mixed in arithmetic or other
    operations: they should be converted to a common domain first.  The domain
    method :py:meth:`~.Domain.unify` is used to find a domain that can
    represent all the elements of two given domains.

    >>> from sympy import ZZ, QQ, symbols
    >>> x, y = symbols('x, y')
    >>> ZZ.unify(QQ)
    QQ
    >>> ZZ[x].unify(QQ)
    QQ[x]
    >>> ZZ[x].unify(QQ[y])
    QQ[x,y]

    If a domain is a :py:class:`~.Ring` then is might have an associated
    :py:class:`~.Field` and vice versa. The :py:meth:`~.Domain.get_field` and
    :py:meth:`~.Domain.get_ring` methods will find or create the associated
    domain.

    >>> from sympy import ZZ, QQ, Symbol
    >>> x = Symbol('x')
    >>> ZZ.has_assoc_Field
    True
    >>> ZZ.get_field()
    QQ
    >>> QQ.has_assoc_Ring
    True
    >>> QQ.get_ring()
    ZZ
    >>> K = QQ[x]
    >>> K
    QQ[x]
    >>> K.get_field()
    QQ(x)

    See also
    ========

    DomainElement: abstract base class for domain elements
    construct_domain: construct a minimal domain for some expressions

    NFTc                     t           NNotImplementedErrorselfs    :lib/python3.11/site-packages/sympy/polys/domains/domain.py__init__zDomain.__init__g  s    !!    c                     | j         S r   )repr   s    r   __str__zDomain.__str__j  s	    xr   c                      t          |           S r   )strr   s    r   __repr__zDomain.__repr__m      4yyr   c                 B    t          | j        j        | j        f          S r   )hash	__class____name__dtyper   s    r   __hash__zDomain.__hash__p  s    T^,dj9:::r   c                      | j         | S r   r+   r   argss     r   newz
Domain.news      tz4  r   c                     | j         S )z#Alias for :py:attr:`~.Domain.dtype`r.   r   s    r   tpz	Domain.tpv  s     zr   c                      | j         | S )z7Construct an element of ``self`` domain from ``args``. )r1   r/   s     r   __call__zDomain.__call__{  s    txr   c                      | j         | S r   r.   r/   s     r   normalzDomain.normal  r2   r   c           
          |j         d|j         z   }nd|j        j        z   }t          | |          }| |||          }||S t	          d|dt          |          d|d|           )z=Convert ``element`` to ``self.dtype`` given the base domain. Nfrom_Cannot convert 	 of type z from  to )aliasr)   r*   getattrr   type)r   elementbasemethod_convertresults         r   convert_fromzDomain.convert_from  s    : 	7tz)FFt~66F4(( 	Xgt,,F nWWWVZ[bVcVcVcVceieieikokopqqqr   c                    |7t          |          rt          d|z            |                     ||          S |                     |          r|S t          |          rt          d|z            ddlm}m}m}m} |                    |          r|                     ||          S t          |t                    r|                      ||          |          S t          rZ|}t          ||j                  r|                     ||          S |}t          ||j                  r|                     ||          S t          |t                    r+ |d          }	|                      |	|          |	          S t          |t                    r+ |d          }	|                      |	|          |	          S t          |t                    r(|                     ||                                          S | j        r8t%          |dd          r'|                     |                                          S t          |t*                    r-	 |                     |          S # t.          t0          f$ r Y ngw xY wt3          |          sT	 t5          |d	          }t          |t*                    r|                     |          S n# t.          t0          f$ r Y nw xY wt          d
|dt7          |          d|           )z'Convert ``element`` to ``self.dtype``. Nz%s is not in any domainr   )ZZQQ	RealFieldComplexFieldF)tol	is_groundT)strictr;   r<   r=   )r   r   rF   of_typesympy.polys.domainsrH   rI   rJ   rK   
isinstanceintr   r4   floatcomplexr   parentis_Numericalr?   convertLCr   
from_sympy	TypeError
ValueErrorr   r   r@   )
r   rA   rB   rH   rI   rJ   rK   integers	rationalsrU   s
             r   rW   zDomain.convert  sK     	4G$$ J$%>%HIII$$Wd333<<   	N   	F !:W!DEEEGGGGGGGGGGGG::g 	2$$Wb111gs## 	6$$RR[["555 	=H'8;// <(((;;;I'9<00 =(()<<<gu%% 	>Y5)))F$$VVG__f===gw'' 	>!\e,,,F$$VVG__f===g}-- 	@$$Wgnn.>.>???  	.+u!E!E 	.<<

---gu%% 	w///z*    w'' %gd;;;G!'511 8#w7778!:.   D nWWWdSZmmmm]a]abcccs$   I% %I98I9:K KKc                 ,    t          || j                  S )z%Check if ``a`` is of type ``dtype``. )rQ   r4   )r   rA   s     r   rO   zDomain.of_type  s    '47+++r   c                     	 t          |          rt          |                     |           n# t          $ r Y dS w xY wdS )z'Check if ``a`` belongs to this domain. FT)r   r   rW   r   as     r   __contains__zDomain.__contains__  sU    	A %$$LLOOOO 	 	 	55	 ts   +. 
<<c                     t           )a	  Convert domain element *a* to a SymPy expression (Expr).

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

        Convert a :py:class:`~.Domain` element *a* to :py:class:`~.Expr`. Most
        public SymPy functions work with objects of type :py:class:`~.Expr`.
        The elements of a :py:class:`~.Domain` have a different internal
        representation. It is not possible to mix domain elements with
        :py:class:`~.Expr` so each domain has :py:meth:`~.Domain.to_sympy` and
        :py:meth:`~.Domain.from_sympy` methods to convert its domain elements
        to and from :py:class:`~.Expr`.

        Parameters
        ==========

        a: domain element
            An element of this :py:class:`~.Domain`.

        Returns
        =======

        expr: Expr
            A normal SymPy expression of type :py:class:`~.Expr`.

        Examples
        ========

        Construct an element of the :ref:`QQ` domain and then convert it to
        :py:class:`~.Expr`.

        >>> from sympy import QQ, Expr
        >>> q_domain = QQ(2)
        >>> q_domain
        2
        >>> q_expr = QQ.to_sympy(q_domain)
        >>> q_expr
        2

        Although the printed forms look similar these objects are not of the
        same type.

        >>> isinstance(q_domain, Expr)
        False
        >>> isinstance(q_expr, Expr)
        True

        Construct an element of :ref:`K[x]` and convert to
        :py:class:`~.Expr`.

        >>> from sympy import Symbol
        >>> x = Symbol('x')
        >>> K = QQ[x]
        >>> x_domain = K.gens[0]  # generator x as a domain element
        >>> p_domain = x_domain**2/3 + 1
        >>> p_domain
        1/3*x**2 + 1
        >>> p_expr = K.to_sympy(p_domain)
        >>> p_expr
        x**2/3 + 1

        The :py:meth:`~.Domain.from_sympy` method is used for the opposite
        conversion from a normal SymPy expression to a domain element.

        >>> p_domain == p_expr
        False
        >>> K.from_sympy(p_expr) == p_domain
        True
        >>> K.to_sympy(p_domain) == p_expr
        True
        >>> K.from_sympy(K.to_sympy(p_domain)) == p_domain
        True
        >>> K.to_sympy(K.from_sympy(p_expr)) == p_expr
        True

        The :py:meth:`~.Domain.from_sympy` method makes it easier to construct
        domain elements interactively.

        >>> from sympy import Symbol
        >>> x = Symbol('x')
        >>> K = QQ[x]
        >>> K.from_sympy(x**2/3 + 1)
        1/3*x**2 + 1

        See also
        ========

        from_sympy
        convert_from
        r   r`   s     r   to_sympyzDomain.to_sympy  s    v "!r   c                     t           )a  Convert a SymPy expression to an element of this domain.

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

        See :py:meth:`~.Domain.to_sympy` for explanation and examples.

        Parameters
        ==========

        expr: Expr
            A normal SymPy expression of type :py:class:`~.Expr`.

        Returns
        =======

        a: domain element
            An element of this :py:class:`~.Domain`.

        See also
        ========

        to_sympy
        convert_from
        r   r`   s     r   rY   zDomain.from_sympy=  s
    4 "!r   c                      t          |          S r   )sumr/   s     r   rg   z
Domain.sumY  r&   r   c                     dS z.Convert ``ModularInteger(int)`` to ``dtype``. N K1ra   K0s      r   from_FFzDomain.from_FF\      tr   c                     dS ri   rj   rk   s      r   from_FF_pythonzDomain.from_FF_python`  ro   r   c                     dS )z.Convert a Python ``int`` object to ``dtype``. Nrj   rk   s      r   from_ZZ_pythonzDomain.from_ZZ_pythond  ro   r   c                     dS )z3Convert a Python ``Fraction`` object to ``dtype``. Nrj   rk   s      r   from_QQ_pythonzDomain.from_QQ_pythonh  ro   r   c                     dS )z.Convert ``ModularInteger(mpz)`` to ``dtype``. Nrj   rk   s      r   from_FF_gmpyzDomain.from_FF_gmpyl  ro   r   c                     dS )z,Convert a GMPY ``mpz`` object to ``dtype``. Nrj   rk   s      r   from_ZZ_gmpyzDomain.from_ZZ_gmpyp  ro   r   c                     dS )z,Convert a GMPY ``mpq`` object to ``dtype``. Nrj   rk   s      r   from_QQ_gmpyzDomain.from_QQ_gmpyt  ro   r   c                     dS )z,Convert a real element object to ``dtype``. Nrj   rk   s      r   from_RealFieldzDomain.from_RealFieldx  ro   r   c                     dS )z(Convert a complex element to ``dtype``. Nrj   rk   s      r   from_ComplexFieldzDomain.from_ComplexField|  ro   r   c                     dS )z*Convert an algebraic number to ``dtype``. Nrj   rk   s      r   from_AlgebraicFieldzDomain.from_AlgebraicField  ro   r   c                 T    |j         r |                     |j        |j                  S dS )#Convert a polynomial to ``dtype``. N)rM   rW   rX   domrk   s      r   from_PolynomialRingzDomain.from_PolynomialRing  s.    ; 	,::adBF+++	, 	,r   c                     dS )z*Convert a rational function to ``dtype``. Nrj   rk   s      r   from_FractionFieldzDomain.from_FractionField  ro   r   c                 B    |                      |j        |j                  S )z.Convert an ``ExtensionElement`` to ``dtype``. )rF   r!   ringrk   s      r   from_MonogenicFiniteExtensionz$Domain.from_MonogenicFiniteExtension  s    qubg...r   c                 6    |                      |j                  S z&Convert a ``EX`` object to ``dtype``. )rY   exrk   s      r   from_ExpressionDomainzDomain.from_ExpressionDomain  s    }}QT"""r   c                 ,    |                      |          S r   )rY   rk   s      r   from_ExpressionRawDomainzDomain.from_ExpressionRawDomain  s    }}Qr   c                     |                                 dk    r-|                     |                                |j                  S dS )r   r   N)degreerW   rX   r   rk   s      r   from_GlobalPolynomialRingz Domain.from_GlobalPolynomialRing  s>    88::? 	.::addffbf---	. 	.r   c                 .    |                      ||          S r   )r   rk   s      r   from_GeneralizedPolynomialRingz%Domain.from_GeneralizedPolynomialRing  s    $$Q+++r   c           
      $   | j         r$t          | j                  t          |          z  s+|j         rJt          |j                  t          |          z  r&t          d| d|dt	          |          d          |                     |          S )NzCannot unify z with z, given z generators)is_Compositesetsymbolsr   tupleunify)rm   rl   r   s      r   unify_with_symbolszDomain.unify_with_symbols  s    O 	oRZ3w<<!? 	obo 	o[^_a_i[j[jmpqxmymy[y 	o##VXVXVXZ\Z\Z\^cdk^l^l^l^l$mnnnxx||r   c                    ||                      ||          S | |k    r| S | j        r| S |j        r|S | j        r| S |j        r|S | j        s|j        r|j        r|| }} |j        rPt	          t          | j        |j        g                    d         | j        k    r|| }} |                    |           S |                    | j	                  }| j
                            |          }|                     |          S | j        s|j        r| j        r| j        n| }|j        r|j        n|}| j        r| j        nd}|j        r|j        nd}|                    |          }t          ||          }| j        r| j        n|j        }| j        r|j        s|j        r7| j        r0|j        r|j        s"|j        r|j        r|                                }| j        r|j        r| j        s|j        r| j        }	n|j        }	ddlm}
 |	|
k    r |	||          S  |	|||          S d }|j        r|| }} | j        r"|j        s|j        r || j        | |          S | S |j        r|| }} | j        rF|j        r || j        | |          S |j        s|j        rddlm}  || j        | j                   S | S |j!        r|| }} | j!        r|j        r|"                                }|j        r|#                                }|j!        rC | j        | j                            |j                  gt          | j$        |j$                  R  S | S | j        r| S |j        r|S | j        r|j%        r| "                                } | S |j        r| j%        r|"                                }|S | j%        r| S |j%        r|S | j&        r| S |j&        r|S | j'        r;|j'        r4|                     tQ          | j)        |j)        tT          	                    S dd
l+m,} |S )aZ  
        Construct a minimal domain that contains elements of ``K0`` and ``K1``.

        Known domains (from smallest to largest):

        - ``GF(p)``
        - ``ZZ``
        - ``QQ``
        - ``RR(prec, tol)``
        - ``CC(prec, tol)``
        - ``ALG(a, b, c)``
        - ``K[x, y, z]``
        - ``K(x, y, z)``
        - ``EX``

        N   rj   r   )GlobalPolynomialRingc                     t          |j        |j                  }t          |j        |j                  } | ||          S )NprecrL   )max	precision	tolerance)clsrm   rl   r   rL   s        r   	mkinexactzDomain.unify.<locals>.mkinexact  s=    r|R\22DblBL11C3Dc****r   )rK   r   )key)EX)-r   is_EXRAWis_EXis_FiniteExtensionlistr
   modulus
set_domaindropsymboldomainr   r   r   r   r   orderis_FractionFieldis_PolynomialRingis_Fieldhas_assoc_Ringget_ringr)   &sympy.polys.domains.old_polynomialringr   is_ComplexFieldis_RealFieldis_GaussianRingis_GaussianField sympy.polys.domains.complexfieldrK   r   r   is_AlgebraicField	get_fieldas_AlgebraicFieldorig_extis_RationalFieldis_IntegerRingis_FiniteFieldr   modr	   rP   r   )rm   rl   r   	K0_ground	K1_ground
K0_symbols
K1_symbolsr   r   r   r   r   rK   r   s                 r   r   zDomain.unify  s   "  	6((W5558 	I; 	I; 	I8 	I8 	I  	)B$9 	)$  RB$ 
) RZ 899::1=K $B}}R((( WWRY''Y__R((}}R(((? 	/bo 	/"$/9rI"$/9rI')>BJ')>BJ__Y//F!*j99G "=BHHRXE$ +)= +$+)+)=+(+090B+HN+ *+  ** # #2;N #RTRf #llSSSSSS** ,s67+++3vw...	+ 	+ 	+
  	B 	! R_  yr2666	? 	B? 	  yr2666# r': IIIIII#|2<HHHH	 	B 	! $\\^^" ,))++# #r|BFLL$8$8a;r{TVT_;`;`aaaa	 	I 	I 	" $\\^^I 	" $\\^^I 	I 	I 	I 	I 	K!2 	K<<BFBF8H I I IJJJ******	r   c                 L    t          |t                    o| j        |j        k    S )z0Returns ``True`` if two domains are equivalent. )rQ   r   r+   r   others     r   __eq__zDomain.__eq__5  s     %((FTZ5;-FFr   c                     | |k     S )z1Returns ``False`` if two domains are equivalent. rj   r   s     r   __ne__zDomain.__ne__9  s    5=  r   c                     g }|D ]^}t          |t                    r)|                    |                     |                     @|                     | |                     _|S )z5Rersively apply ``self`` to all elements of ``seq``. )rQ   r   appendmap)r   seqrE   elts       r   r   z
Domain.map=  si     	) 	)C#t$$ )dhhsmm,,,,dd3ii((((r   c                 &    t          d| z            )z)Returns a ring associated with ``self``. z#there is no ring associated with %sr   r   s    r   r   zDomain.get_ringI  s    ?$FGGGr   c                 &    t          d| z            )z*Returns a field associated with ``self``. z$there is no field associated with %sr   r   s    r   r   zDomain.get_fieldM  s    @4GHHHr   c                     | S )z2Returns an exact domain associated with ``self``. rj   r   s    r   	get_exactzDomain.get_exactQ  s    r   c                 `    t          |d          r
 | j        | S |                     |          S )z0The mathematical way to make a polynomial ring. __iter__)hasattr	poly_ringr   r   s     r   __getitem__zDomain.__getitem__U  s5    7J'' 	+!4>7++>>'***r   )r   c                (    ddl m}  || ||          S z(Returns a polynomial ring, i.e. `K[X]`. r   )PolynomialRing)"sympy.polys.domains.polynomialringr   )r   r   r   r   s       r   r   zDomain.poly_ring\  s(    EEEEEE~dGU333r   c                (    ddl m}  || ||          S z'Returns a fraction field, i.e. `K(X)`. r   )FractionField)!sympy.polys.domains.fractionfieldr   )r   r   r   r   s       r   
frac_fieldzDomain.frac_fielda  s(    CCCCCC}T7E222r   c                 &    ddl m}  || g|R i |S r   )r   r   )r   r   kwargsr   s       r   old_poly_ringzDomain.old_poly_ringf  s4    IIIIII~d7W777777r   c                 &    ddl m}  || g|R i |S r   )%sympy.polys.domains.old_fractionfieldr   )r   r   r   r   s       r   old_frac_fieldzDomain.old_frac_fieldk  s4    GGGGGG}T6G666v666r   r>   c                &    t          d| z            )z6Returns an algebraic field, i.e. `K(\alpha, \ldots)`. z%Cannot create algebraic field over %sr   )r   r>   	extensions      r   algebraic_fieldzDomain.algebraic_fieldp  s    ADHIIIr   c                 v    ddl m}  |||          }t          ||          }|                     ||          S )a  
        Convenience method to construct an algebraic extension on a root of a
        polynomial, chosen by root index.

        Parameters
        ==========

        poly : :py:class:`~.Poly`
            The polynomial whose root generates the extension.
        alias : str, optional (default=None)
            Symbol name for the generator of the extension.
            E.g. "alpha" or "theta".
        root_index : int, optional (default=-1)
            Specifies which root of the polynomial is desired. The ordering is
            as defined by the :py:class:`~.ComplexRootOf` class. The default of
            ``-1`` selects the most natural choice in the common cases of
            quadratic and cyclotomic fields (the square root on the positive
            real or imaginary axis, resp. $\mathrm{e}^{2\pi i/n}$).

        Examples
        ========

        >>> from sympy import QQ, Poly
        >>> from sympy.abc import x
        >>> f = Poly(x**2 - 2)
        >>> K = QQ.alg_field_from_poly(f)
        >>> K.ext.minpoly == f
        True
        >>> g = Poly(8*x**3 - 6*x - 1)
        >>> L = QQ.alg_field_from_poly(g, "alpha")
        >>> L.ext.minpoly == g
        True
        >>> L.to_sympy(L([1, 1, 1]))
        alpha**2 + alpha + 1

        r   )CRootOfr   )sympy.polys.rootoftoolsr   r   r   )r   polyr>   
root_indexr   rootalphas          r   alg_field_from_polyzDomain.alg_field_from_polyt  sS    J 	433333wtZ((E222##E#777r   zetac                 z    ddl m} |r|t          |          z  }|                      |||          ||          S )a  
        Convenience method to construct a cyclotomic field.

        Parameters
        ==========

        n : int
            Construct the nth cyclotomic field.
        ss : boolean, optional (default=False)
            If True, append *n* as a subscript on the alias string.
        alias : str, optional (default="zeta")
            Symbol name for the generator.
        gen : :py:class:`~.Symbol`, optional (default=None)
            Desired variable for the cyclotomic polynomial that defines the
            field. If ``None``, a dummy variable will be used.
        root_index : int, optional (default=-1)
            Specifies which root of the polynomial is desired. The ordering is
            as defined by the :py:class:`~.ComplexRootOf` class. The default of
            ``-1`` selects the root $\mathrm{e}^{2\pi i/n}$.

        Examples
        ========

        >>> from sympy import QQ, latex
        >>> K = QQ.cyclotomic_field(5)
        >>> K.to_sympy(K([-1, 1]))
        1 - zeta
        >>> L = QQ.cyclotomic_field(7, True)
        >>> a = L.to_sympy(L([-1, 1]))
        >>> print(a)
        1 - zeta7
        >>> print(latex(a))
        1 - \zeta_{7}

        r   )cyclotomic_poly)r>   r   )sympy.polys.specialpolysr   r$   r   )r   nssr>   genr   r   s          r   cyclotomic_fieldzDomain.cyclotomic_field  s^    H 	=<<<<< 	SVVOE''3(?(?u3= ( ? ? 	?r   c                     t           )z$Inject generators into this domain. r   r   s     r   injectzDomain.inject      !!r   c                 "    | j         r| S t          )z"Drop generators from this domain. )	is_Simpler   r   s     r   r   zDomain.drop  s    > 	K!!r   c                     | S )zReturns True if ``a`` is zero. rj   r`   s     r   is_zerozDomain.is_zero  s	    ur   c                     || j         k    S )zReturns True if ``a`` is one. )oner`   s     r   is_onezDomain.is_one  s    DH}r   c                     |dk    S )z#Returns True if ``a`` is positive. r   rj   r`   s     r   is_positivezDomain.is_positive      1ur   c                     |dk     S )z#Returns True if ``a`` is negative. r   rj   r`   s     r   is_negativezDomain.is_negative  r  r   c                     |dk    S )z'Returns True if ``a`` is non-positive. r   rj   r`   s     r   is_nonpositivezDomain.is_nonpositive      Avr   c                     |dk    S )z'Returns True if ``a`` is non-negative. r   rj   r`   s     r   is_nonnegativezDomain.is_nonnegative  r  r   c                 J    |                      |          r| j         S | j        S r   )r  r  r`   s     r   canonical_unitzDomain.canonical_unit  s)    A 	H98Or   c                      t          |          S )z.Absolute value of ``a``, implies ``__abs__``. )absr`   s     r   r  z
Domain.abs  s    1vvr   c                     | S )z,Returns ``a`` negated, implies ``__neg__``. rj   r`   s     r   negz
Domain.neg  	    r	r   c                     |
 S )z-Returns ``a`` positive, implies ``__pos__``. rj   r`   s     r   posz
Domain.pos  r  r   c                     ||z   S )z.Sum of ``a`` and ``b``, implies ``__add__``.  rj   r   ra   bs      r   addz
Domain.add      1ur   c                     ||z
  S )z5Difference of ``a`` and ``b``, implies ``__sub__``.  rj   r#  s      r   subz
Domain.sub   r&  r   c                     ||z  S )z2Product of ``a`` and ``b``, implies ``__mul__``.  rj   r#  s      r   mulz
Domain.mul  r&  r   c                     ||z  S )z2Raise ``a`` to power ``b``, implies ``__pow__``.  rj   r#  s      r   powz
Domain.pow  s    Avr   c                     t           )a  Exact quotient of *a* and *b*. Analogue of ``a / b``.

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

        This is essentially the same as ``a / b`` except that an error will be
        raised if the division is inexact (if there is any remainder) and the
        result will always be a domain element. When working in a
        :py:class:`~.Domain` that is not a :py:class:`~.Field` (e.g. :ref:`ZZ`
        or :ref:`K[x]`) ``exquo`` should be used instead of ``/``.

        The key invariant is that if ``q = K.exquo(a, b)`` (and ``exquo`` does
        not raise an exception) then ``a == b*q``.

        Examples
        ========

        We can use ``K.exquo`` instead of ``/`` for exact division.

        >>> from sympy import ZZ
        >>> ZZ.exquo(ZZ(4), ZZ(2))
        2
        >>> ZZ.exquo(ZZ(5), ZZ(2))
        Traceback (most recent call last):
            ...
        ExactQuotientFailed: 2 does not divide 5 in ZZ

        Over a :py:class:`~.Field` such as :ref:`QQ`, division (with nonzero
        divisor) is always exact so in that case ``/`` can be used instead of
        :py:meth:`~.Domain.exquo`.

        >>> from sympy import QQ
        >>> QQ.exquo(QQ(5), QQ(2))
        5/2
        >>> QQ(5) / QQ(2)
        5/2

        Parameters
        ==========

        a: domain element
            The dividend
        b: domain element
            The divisor

        Returns
        =======

        q: domain element
            The exact quotient

        Raises
        ======

        ExactQuotientFailed: if exact division is not possible.
        ZeroDivisionError: when the divisor is zero.

        See also
        ========

        quo: Analogue of ``a // b``
        rem: Analogue of ``a % b``
        div: Analogue of ``divmod(a, b)``

        Notes
        =====

        Since the default :py:attr:`~.Domain.dtype` for :ref:`ZZ` is ``int``
        (or ``mpz``) division as ``a / b`` should not be used as it would give
        a ``float``.

        >>> ZZ(4) / ZZ(2)
        2.0
        >>> ZZ(5) / ZZ(2)
        2.5

        Using ``/`` with :ref:`ZZ` will lead to incorrect results so
        :py:meth:`~.Domain.exquo` should be used instead.

        r   r#  s      r   exquozDomain.exquo  s    b "!r   c                     t           )aG  Quotient of *a* and *b*. Analogue of ``a // b``.

        ``K.quo(a, b)`` is equivalent to ``K.div(a, b)[0]``. See
        :py:meth:`~.Domain.div` for more explanation.

        See also
        ========

        rem: Analogue of ``a % b``
        div: Analogue of ``divmod(a, b)``
        exquo: Analogue of ``a / b``
        r   r#  s      r   quoz
Domain.quo_  
     "!r   c                     t           )aN  Modulo division of *a* and *b*. Analogue of ``a % b``.

        ``K.rem(a, b)`` is equivalent to ``K.div(a, b)[1]``. See
        :py:meth:`~.Domain.div` for more explanation.

        See also
        ========

        quo: Analogue of ``a // b``
        div: Analogue of ``divmod(a, b)``
        exquo: Analogue of ``a / b``
        r   r#  s      r   remz
Domain.remn  r1  r   c                     t           )a[	  Quotient and remainder for *a* and *b*. Analogue of ``divmod(a, b)``

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

        This is essentially the same as ``divmod(a, b)`` except that is more
        consistent when working over some :py:class:`~.Field` domains such as
        :ref:`QQ`. When working over an arbitrary :py:class:`~.Domain` the
        :py:meth:`~.Domain.div` method should be used instead of ``divmod``.

        The key invariant is that if ``q, r = K.div(a, b)`` then
        ``a == b*q + r``.

        The result of ``K.div(a, b)`` is the same as the tuple
        ``(K.quo(a, b), K.rem(a, b))`` except that if both quotient and
        remainder are needed then it is more efficient to use
        :py:meth:`~.Domain.div`.

        Examples
        ========

        We can use ``K.div`` instead of ``divmod`` for floor division and
        remainder.

        >>> from sympy import ZZ, QQ
        >>> ZZ.div(ZZ(5), ZZ(2))
        (2, 1)

        If ``K`` is a :py:class:`~.Field` then the division is always exact
        with a remainder of :py:attr:`~.Domain.zero`.

        >>> QQ.div(QQ(5), QQ(2))
        (5/2, 0)

        Parameters
        ==========

        a: domain element
            The dividend
        b: domain element
            The divisor

        Returns
        =======

        (q, r): tuple of domain elements
            The quotient and remainder

        Raises
        ======

        ZeroDivisionError: when the divisor is zero.

        See also
        ========

        quo: Analogue of ``a // b``
        rem: Analogue of ``a % b``
        exquo: Analogue of ``a / b``

        Notes
        =====

        If ``gmpy`` is installed then the ``gmpy.mpq`` type will be used as
        the :py:attr:`~.Domain.dtype` for :ref:`QQ`. The ``gmpy.mpq`` type
        defines ``divmod`` in a way that is undesirable so
        :py:meth:`~.Domain.div` should be used instead of ``divmod``.

        >>> a = QQ(1)
        >>> b = QQ(3, 2)
        >>> a               # doctest: +SKIP
        mpq(1,1)
        >>> b               # doctest: +SKIP
        mpq(3,2)
        >>> divmod(a, b)    # doctest: +SKIP
        (mpz(0), mpq(1,1))
        >>> QQ.div(a, b)    # doctest: +SKIP
        (mpq(2,3), mpq(0,1))

        Using ``//`` or ``%`` with :ref:`QQ` will lead to incorrect results so
        :py:meth:`~.Domain.div` should be used instead.

        r   r#  s      r   divz
Domain.div}  s    h "!r   c                     t           )z5Returns inversion of ``a mod b``, implies something. r   r#  s      r   invertzDomain.invert  r  r   c                     t           )z!Returns ``a**(-1)`` if possible. r   r`   s     r   revertzDomain.revert  r  r   c                     t           )zReturns numerator of ``a``. r   r`   s     r   numerzDomain.numer  r  r   c                     t           )zReturns denominator of ``a``. r   r`   s     r   denomzDomain.denom  r  r   c                 >    |                      ||          \  }}}||fS )z&Half extended GCD of ``a`` and ``b``. )gcdex)r   ra   r$  sths         r   
half_gcdexzDomain.half_gcdex  s$    **Q""1a!tr   c                     t           )z!Extended GCD of ``a`` and ``b``. r   r#  s      r   r?  zDomain.gcdex  r  r   c                     |                      ||          }|                     ||          }|                     ||          }|||fS )z.Returns GCD and cofactors of ``a`` and ``b``. )gcdr0  )r   ra   r$  rF  cfacfbs         r   	cofactorszDomain.cofactors  sE    hhq!nnhhq#hhq#C}r   c                     t           )z Returns GCD of ``a`` and ``b``. r   r#  s      r   rF  z
Domain.gcd  r  r   c                     t           )z Returns LCM of ``a`` and ``b``. r   r#  s      r   lcmz
Domain.lcm  r  r   c                     t           )z#Returns b-base logarithm of ``a``. r   r#  s      r   logz
Domain.log  r  r   c                     t           )zReturns square root of ``a``. r   r`   s     r   sqrtzDomain.sqrt  r  r   c                 D     |                      |          j        |fi |S )z*Returns numerical approximation of ``a``. )rd   evalf)r   ra   r   optionss       r   rR  zDomain.evalf  s)    %t}}Q%d66g666r   c                     |S r   rj   r`   s     r   realzDomain.real	  s    r   c                     | j         S r   )zeror`   s     r   imagzDomain.imag  s
    yr   c                     ||k    S )z+Check if ``a`` and ``b`` are almost equal. rj   )r   ra   r$  r   s       r   almosteqzDomain.almosteq  r  r   c                      t          d          )z*Return the characteristic of this domain. zcharacteristic()r   r   s    r   characteristiczDomain.characteristic  s    !"4555r   r   )Nr   )Fr   Nr   )r*   
__module____qualname____doc__r+   rW  r  is_Ringr   r   has_assoc_Fieldr   is_FFr   is_ZZr   is_QQr   is_ZZ_Ir   is_QQ_Ir   is_RRr   is_CCr   is_Algebraicr   is_Polyr   is_Fracis_SymbolicDomainr   is_SymbolicRawDomainr   r   is_ExactrV   r	  r   is_PIDhas_CharacteristicZeror!   r>   r   r"   r%   r,   r1   propertyr4   r6   r8   rF   rW   rO   rb   rd   rY   rg   rn   rq   rs   ru   rw   ry   r{   r}   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r  r  r   r  r  r  r  r  r  r  r  r  r!  r%  r(  r*  r,  r.  r0  r3  r5  r7  r9  r;  r=  rC  r?  rI  rF  rL  rN  rP  rR  r  rU  rX  rZ  r\  rj   r   r   r   r      s       h hT E, D C G$ H" N  O  #"NU""NU$$u %%Og!&&w  L5##Oe',,"''!&&w %%&++8HLILF" #
CE" " "    ; ; ;! ! !   X  ! ! !r r r"<d <d <d <d|, , ,	 	 	[" [" ["z" " "8                      , , ,
  / / /# # #     . . .
, , ,  L L L L\G G G! ! !
 
 
H H HI I I  + + + ), 4 4 4 4 4
 *- 3 3 3 3 3
8 8 8
7 7 7
 15 J J J J J(8 (8 (8 (8T(? (? (? (?T" " "" " "                            Q" Q" Q"f" " "" " "T" T" T"l" " "" " "" " "" " "  
" " "  " " "" " "" " "" " "7 7 7 7 	A       6 6 6 6 6r   r   N) r_  typingr   r   r   sympy.core.numbersr   
sympy.corer   r   sympy.core.sortingr	   r
   sympy.external.gmpyr   !sympy.polys.domains.domainelementr   sympy.polys.orderingsr   sympy.polys.polyerrorsr   r   r   sympy.polys.polyutilsr   r   sympy.utilitiesr   sympy.utilities.iterablesr   r   __all__rj   r   r   <module>r~     sG   / / ' & & & & & & & & & . . . . . . % % % % % % % % 8 8 8 8 8 8 8 8 ( ( ( ( ( ( ; ; ; ; ; ; % % % % % % Q Q Q Q Q Q Q Q Q Q ; ; ; ; ; ; ; ; " " " " " " 1 1 1 1 1 1 B6 B6 B6 B6 B6 B6 B6 B6J( *r   