K idZddlmZddlmZddlmZddlmZm Z ddl m Z ddl m Z ddlmZdd lmZdd lmZmZmZdd lmZmZdd lmZdd lmZeGddZdgZy)z)Implementation of :class:`Domain` class. ) annotations)Any)AlgebraicNumber)Basicsympify)ordered) GROUND_TYPES) DomainElement)lex)UnificationFailedCoercionFailed DomainError) _unify_gens _not_a_coeff)public) is_sequencec*eZdZUdZdZded< dZded< dZded< dZ dZ dZ dZ dxZ Z dxZZdxZZdxZZdxZZdxZZdxZZdxZZdxZZdxZZdxZ Z!dxZ"Z#dZ$d Z%dZ&dZ'dZ(dZ) dZ*dZ+d ed <dZ,d ed <d Z-dZ.dZ/dZ0dZ1e2dZ3dZ4dZ5dZ6dfdZ7dZ8dZ9dZ:dZ;dZdZ?dZ@d ZAd!ZBd"ZCd#ZDd$ZEd%ZFd&ZGd'ZHd(ZId)ZJd*ZKd+ZLd,ZMd-ZNd.ZOdfd/ZPd0ZQd1ZRd2ZSd3ZTd4ZUd5ZVd6ZWeXd7d8ZYeXd7d9ZZd:Z[d;Z\dd<d=Z]dgd>Z^dhd?Z_d@Z`dAZadBZbdCZcdDZddEZedFZfdGZgdHZhdIZidJZjdKZkdLZldMZmdNZndOZodPZpdQZqdRZrdSZsdTZtdUZudVZvdWZwdXZxdYZydZZzd[Z{d\Z|d]Z}d^Z~d_Zd`ZdfdaZeZdbZdcZdfddZdeZy)iDomainarSuperclass 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 >>> type(ZZ(2)) # doctest: +SKIP >>> QQ(1, 2) 1/2 >>> type(QQ(1, 2)) # doctest: +SKIP 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 >>> K.dtype # doctest: +SKIP >>> p_expr = x**2 + 1 # Expr >>> p_expr x**2 + 1 >>> type(p_expr) >>> isinstance(p_expr, Expr) True >>> p_domain = K.from_sympy(p_expr) >>> p_domain # domain element x**2 + 1 >>> type(p_domain) >>> 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 >>> type(eq) # doctest: +SKIP 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 Nz type | NonedtyperzerooneFTz str | NonerepaliasctNNotImplementedErrorselfs `/mnt/ssd/data/python-lab/Trading/venv/lib/python3.12/site-packages/sympy/polys/domains/domain.py__init__zDomain.__init__gs!!c|jSr)rrs r __str__zDomain.__str__js xxr"ct|Sr)strrs r __repr__zDomain.__repr__ms 4yr"cXt|jj|jfSr)hash __class____name__rrs r __hash__zDomain.__hash__ps T^^,,djj9::r"c |j|Srrrargss r newz Domain.newstzz4  r"c|jS)z#Alias for :py:attr:`~.Domain.dtype`r.rs r tpz Domain.tpvszzr"c |j|S)z7Construct an element of ``self`` domain from ``args``. )r1r/s r __call__zDomain.__call__{stxxr"c |j|Srr.r/s r normalz Domain.normalr2r"c |jd|jz}nd|jjz}t||}| |||}||St d|dt |d|d|)z=Convert ``element`` to ``self.dtype`` given the base domain. from_Cannot convert of type z from  to )rr*r+getattrr type)relementbasemethod_convertresults r convert_fromzDomain.convert_fromst :: !tzz)Ft~~666F4(  gt,F! WVZ[bVceikopqqr"c|+t|rtd|z|j||S|j|r|St|rtd|zddlm}m}m}m}|j|r|j||St|tr|j|||Stdk7rPt||jr|j||St||jr|j||St|tr|}|j|||St|tr|}|j|||St|j dk(r|}|j|||St|j dk(r|}|j|||St|t"r |j||j%S|j&r,t)|ddr|j+|j-St|t.r |j1|St7|s0 t9|d }t|t.r|j1|S td |d t|d |#t2t4f$rY.wxYw#t2t4f$rYCwxYw)z'Convert ``element`` to ``self.dtype``. z%s is not in any domainr)ZZQQ RealField ComplexFieldpythonmpfmpc is_groundFT)strictr;r<r=)rr rEof_typesympy.polys.domainsrGrHrIrJ isinstanceintr r4floatcomplexr?r+r parent is_Numericalr>convertLCr from_sympy TypeError ValueErrorrr)rr@rArGrHrIrJrVs r rXzDomain.converts  G$$%>%HII$$Wd3 3 << N   !:W!DE EGG ::g $$Wb1 1 gs #$$R["5 5 8 #'255)(("55'255)(("55 gu %[F$$VG_f= = gw '!^F$$VG_f= = = ! !U *[F$$VG_f= = = ! !U *!^F$$VG_f= = g} -$$Wgnn.>? ?   +u!E<< - - gu % w//w'%gd;G!'51#w772 WdSZm]abccz*  ":.s$J8,-K 8K  K  KKc.t||jS)z%Check if ``a`` is of type ``dtype``. )rRr4)rr@s r rPzDomain.of_types'477++r"ch t|rt|j|y#t$rYywxYw)z'Check if ``a`` belongs to this domain. FT)rr rXras r __contains__zDomain.__contains__s8 A$$ LLO  s "% 11ct)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 rr_s r to_sympyzDomain.to_sympys v"!r"ct)aConvert 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 rr_s r rZzDomain.from_sympyBs 4"!r"c0t||jS)N)start)sumrr/s r rgz Domain.sum^s4tyy))r"cyz.Convert ``ModularInteger(int)`` to ``dtype``. NK1r`K0s r from_FFzDomain.from_FFar"cyrirjrks r from_FF_pythonzDomain.from_FF_pythoneror"cy)z.Convert a Python ``int`` object to ``dtype``. Nrjrks r from_ZZ_pythonzDomain.from_ZZ_pythoniror"cy)z3Convert a Python ``Fraction`` object to ``dtype``. Nrjrks r from_QQ_pythonzDomain.from_QQ_pythonmror"cy)z.Convert ``ModularInteger(mpz)`` to ``dtype``. Nrjrks r from_FF_gmpyzDomain.from_FF_gmpyqror"cy)z,Convert a GMPY ``mpz`` object to ``dtype``. Nrjrks r from_ZZ_gmpyzDomain.from_ZZ_gmpyuror"cy)z,Convert a GMPY ``mpq`` object to ``dtype``. Nrjrks r from_QQ_gmpyzDomain.from_QQ_gmpyyror"cy)z,Convert a real element object to ``dtype``. Nrjrks r from_RealFieldzDomain.from_RealField}ror"cy)z(Convert a complex element to ``dtype``. Nrjrks r from_ComplexFieldzDomain.from_ComplexFieldror"cy)z*Convert an algebraic number to ``dtype``. Nrjrks r from_AlgebraicFieldzDomain.from_AlgebraicFieldror"ch|jr&|j|j|jSy)#Convert a polynomial to ``dtype``. N)rNrXrYdomrks r from_PolynomialRingzDomain.from_PolynomialRings' ;;::addBFF+ + r"cy)z*Convert a rational function to ``dtype``. Nrjrks r from_FractionFieldzDomain.from_FractionFieldror"cN|j|j|jS)z.Convert an ``ExtensionElement`` to ``dtype``. )rErringrks r from_MonogenicFiniteExtensionz$Domain.from_MonogenicFiniteExtensionsquubgg..r"c8|j|jSz&Convert a ``EX`` object to ``dtype``. )rZexrks r from_ExpressionDomainzDomain.from_ExpressionDomains}}QTT""r"c$|j|Sr)rZrks r from_ExpressionRawDomainzDomain.from_ExpressionRawDomains}}Qr"c~|jdkr*|j|j|jSy)rrN)degreerXrYrrks r from_GlobalPolynomialRingz Domain.from_GlobalPolynomialRings/ 88:?::addfbff- - r"c&|j||Sr)rrks r from_GeneralizedPolynomialRingz%Domain.from_GeneralizedPolynomialRings$$Q++r"c |jr!t|jt|zs-|jr?t|jt|zrtd|d|dt |d|j |S)N Cannot unify  with z, given z generators) is_Compositesetsymbolsr tupleunify)rmrlrs r unify_with_symbolszDomain.unify_with_symbolssf OORZZ3w,>FOO&&__&F ??BOOr7J7JbNbNb,,C,,C P & &vw' '67E**r"c||j||S||k(r|S|jr |jsC|j|jk7rtd|d||j |S|j r|S|j r|S|j r|S|j r|S|js |jr|jr||}}|jrOtt|j|jgd|jk(r||}}|j|S|j|j}|jj|}|j|S|j s |j r|j |S|j"r||}}|j"rN|j"s |j$r4|j&|j&k\r|Sddlm}||j&S|S|j$r||}}|j$r\|j$r|j&|j&k\r|S|S|j,s |j.rddlm}||j&S|S|j0r||}}|j0r|j,r|j3}|j.r|j5}|j0rT|j6|j8j|j8gt;|j<|j<S|S|j.r|S|j.r|S|j,r|j>r|j3}|S|j,r|j>r|j3}|S|j>r|S|j>r|S|j@r|S|j@r|Sddl!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`` rrr)rJ)prec)EX)#rhas_CharacteristicZerocharacteristicr ris_EXRAWis_EXis_FiniteExtensionlistrmodulus set_domaindropsymbolrrris_ComplexField is_RealField precision sympy.polys.domains.complexfieldrJis_GaussianRingis_GaussianFieldis_AlgebraicField get_fieldas_AlgebraicFieldr*rrorig_extis_RationalFieldis_IntegerRingrQr)rmrlrrJrs r rz Domain.unifysM"  ((W5 5 8I))b.G.G  "b&7&7&99'R(LMM %%b) ) ;;I ;;I 88I 88I B$9$9$$RB$$RZZ 89:1=KB}}R((WWRYY'YY__R(}}R(( ??boo%%b) )  B  !!R__<<2<</IM'R\\:: ??B ??<<2<</II##r':':I#66  B  !!\\^""))+###r||BFFLL$8a;r{{TVT_T_;`aa  I  I  ""\\^I  ""\\^I  I  I  I  I* r"cXt|txr|j|jk(S)z0Returns ``True`` if two domains are equivalent. )rRrrrothers r __eq__z Domain.__eq__Ns#%(FTZZ5;;-FFr"c||k( S)z1Returns ``False`` if two domains are equivalent. rjrs r __ne__z Domain.__ne__Ss5=  r"cg}|D]J}t|tr!|j|j|4|j||L|S)z5Rersively apply ``self`` to all elements of ``seq``. )rRrappendmap)rseqrDelts r rz Domain.mapWsK )C#t$ dhhsm, d3i(  )  r"ctd|z)z)Returns a ring associated with ``self``. z#there is no ring associated with %srrs r rzDomain.get_ringcs?$FGGr"ctd|z)z*Returns a field associated with ``self``. z$there is no field associated with %srrs r rzDomain.get_fieldgs@4GHHr"c|S)z2Returns an exact domain associated with ``self``. rjrs r get_exactzDomain.get_exactks r"cZt|dr|j|S|j|S)z0The mathematical way to make a polynomial ring. __iter__)hasattr poly_ringrrs r __getitem__zDomain.__getitem__os, 7J '!4>>7+ +>>'* *r")rc"ddlm}||||Sz(Returns a polynomial ring, i.e. `K[X]`. r)PolynomialRing)"sympy.polys.domains.polynomialringr)rrrrs r rzDomain.poly_ringvsEdGU33r"c"ddlm}||||Sz'Returns a fraction field, i.e. `K(X)`. r) FractionField)!sympy.polys.domains.fractionfieldr)rrrrs r frac_fieldzDomain.frac_field{sCT7E22r"c&ddlm}||g|i|Sr)rr)rrkwargsrs r old_poly_ringzDomain.old_poly_ringsId7W777r"c&ddlm}||g|i|Sr)%sympy.polys.domains.old_fractionfieldr)rrrrs r old_frac_fieldzDomain.old_frac_fieldsGT6G6v66r"rctd|z)z6Returns an algebraic field, i.e. `K(\alpha, \ldots)`. z%Cannot create algebraic field over %sr)rr extensions r algebraic_fieldzDomain.algebraic_fieldsADHIIr"c`ddlm}|||}t||}|j||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.rootoftoolsrrr)rpolyr root_indexrrootalphas r alg_field_from_polyzDomain.alg_field_from_polys6J 4tZ(E2##E#77r"cdddlm}|r|t|z }|j|||||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)rr)sympy.polys.specialpolysrr&r)rnssrgenrrs r cyclotomic_fieldzDomain.cyclotomic_fields>H = SVOE''3(?u3=(? ?r"ct)z$Inject generators into this domain. rrs r injectz Domain.inject!!r"c*|jr|St)z"Drop generators from this domain. ) is_Simplerrs r rz Domain.drops >>K!!r"c| S)zReturns True if ``a`` is zero. rjr_s r is_zerozDomain.is_zeros u r"c ||jk(S)zReturns True if ``a`` is one. )rr_s r is_onez Domain.is_onesDHH}r"c |dkDS)z#Returns True if ``a`` is positive. rrjr_s r is_positivezDomain.is_positive 1u r"c |dkS)z#Returns True if ``a`` is negative. rrjr_s r is_negativezDomain.is_negativer r"c |dkS)z'Returns True if ``a`` is non-positive. rrjr_s r is_nonpositivezDomain.is_nonpositive Av r"c |dk\S)z'Returns True if ``a`` is non-negative. rrjr_s r is_nonnegativezDomain.is_nonnegativerr"cV|j|r |j S|jSr)rrr_s r canonical_unitzDomain.canonical_units%   A HH9 88Or"ct|S)z.Absolute value of ``a``, implies ``__abs__``. )absr_s r rz Domain.abs s 1v r"c| S)z,Returns ``a`` negated, implies ``__neg__``. rjr_s r negz Domain.neg r r"c|S)z-Returns ``a`` positive, implies ``__pos__``. rjr_s r posz Domain.posrr"c ||zS)z.Sum of ``a`` and ``b``, implies ``__add__``. rjrr`bs r addz Domain.addr r"c ||z S)z5Difference of ``a`` and ``b``, implies ``__sub__``. rjrs r subz Domain.subr r"c ||zS)z2Product of ``a`` and ``b``, implies ``__mul__``. rjrs r mulz Domain.mulr r"c ||zS)z2Raise ``a`` to power ``b``, implies ``__pow__``. rjrs r powz Domain.pow"rr"ct)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`` which is not a domain element. >>> ZZ(4) / ZZ(2) # doctest: +SKIP 2.0 >>> ZZ(5) / ZZ(2) # doctest: +SKIP 2.5 On the other hand with `SYMPY_GROUND_TYPES=flint` elements of :ref:`ZZ` are ``flint.fmpz`` and division would raise an exception: >>> ZZ(4) / ZZ(2) # doctest: +SKIP Traceback (most recent call last): ... TypeError: unsupported operand type(s) for /: 'fmpz' and 'fmpz' Using ``/`` with :ref:`ZZ` will lead to incorrect results so :py:meth:`~.Domain.exquo` should be used instead. rrs r exquoz Domain.exquo&s r"!r"ct)aGQuotient 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`` rrs r quoz Domain.quo "!r"ct)aNModulo 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`` rrs r remz Domain.remr+r"ct)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. rrs r divz Domain.divs h"!r"ct)z5Returns inversion of ``a mod b``, implies something. rrs r invertz Domain.invertrr"ct)z!Returns ``a**(-1)`` if possible. rr_s r revertz Domain.revertrr"ct)zReturns numerator of ``a``. rr_s r numerz Domain.numerrr"ct)zReturns denominator of ``a``. rr_s r denomz Domain.denomrr"c6|j||\}}}||fS)z&Half extended GCD of ``a`` and ``b``. )gcdex)rr`rsths r half_gcdexzDomain.half_gcdexs!**Q"1a!t r"ct)z!Extended GCD of ``a`` and ``b``. rrs r r9z Domain.gcdex rr"cx|j||}|j||}|j||}|||fS)z.Returns GCD and cofactors of ``a`` and ``b``. )gcdr*)rr`rr@cfacfbs r cofactorszDomain.cofactorss=hhq!nhhq#hhq#C}r"ct)z Returns GCD of ``a`` and ``b``. rrs r r@z Domain.gcdrr"ct)z Returns LCM of ``a`` and ``b``. rrs r lcmz Domain.lcmrr"ct)z#Returns b-base logarithm of ``a``. rrs r logz Domain.logrr"ct)aJReturns a (possibly inexact) square root of ``a``. Explanation =========== There is no universal definition of "inexact square root" for all domains. It is not recommended to implement this method for domains other then :ref:`ZZ`. See also ======== exsqrt rr_s r sqrtz Domain.sqrt!r+r"ct)aReturns whether ``a`` is a square in the domain. Explanation =========== Returns ``True`` if there is an element ``b`` in the domain such that ``b * b == a``, otherwise returns ``False``. For inexact domains like :ref:`RR` and :ref:`CC`, a tiny difference in this equality can be tolerated. See also ======== exsqrt rr_s r is_squarezDomain.is_square0s "!r"ct)a'Principal square root of a within the domain if ``a`` is square. Explanation =========== The implementation of this method should return an element ``b`` in the domain such that ``b * b == a``, or ``None`` if there is no such ``b``. For inexact domains like :ref:`RR` and :ref:`CC`, a tiny difference in this equality can be tolerated. The choice of a "principal" square root should follow a consistent rule whenever possible. See also ======== sqrt, is_square rr_s r exsqrtz Domain.exsqrt@s "!r"c F|j|j|fi|S)z*Returns numerical approximation of ``a``. )rcevalf)rr`roptionss r rPz Domain.evalfQs#%t}}Q%%d6g66r"c|Srrjr_s r realz Domain.realWsr"c|jSr)rr_s r imagz Domain.imagZs yyr"c ||k(S)z+Check if ``a`` and ``b`` are almost equal. rj)rr`r tolerances r almosteqzDomain.almosteq]rr"ctd)z*Return the characteristic of this domain. zcharacteristic()rrs r rzDomain.characteristicas!"455r"r)N)FzetaNrZ)r+ __module__ __qualname____doc__r__annotations__rris_Ringrrhas_assoc_Fieldis_FiniteFieldis_FFris_ZZris_QQris_ZZ_Iris_QQ_Iris_RRris_CCr is_Algebraicris_Polyris_Fracis_SymbolicDomainris_SymbolicRawDomainrris_ExactrWrris_PIDrrrr!r$r'r,r1propertyr4r6r8rErXrPrarcrZrgrnrqrsrurwryr{r}rrrrrrrrrrrrrrrrrrrr rrrrrrrrrrr r rrrrrrrr r"r$r&r(r*r-r/r1r3r5r7r=r9rCr@rFrHrJrLrNrPrrSrUrXrrjr"r rrshTE;,D# CO G$H"N O #"NU""NU$$u %%Og!&&w  L5##Oe',, "''!&&w %%&++8HLIL F"#CE:";!!r"AdF, ["z"8*, /# . , +BBG ! HI+),4 *-3 8 7 15J(8T(?T""  Y"v " "T"l"""" """" "" ""7 A6r"rN)r^ __future__rtypingrsympy.core.numbersr sympy.corerrsympy.core.sortingrsympy.external.gmpyr !sympy.polys.domains.domainelementr sympy.polys.orderingsr sympy.polys.polyerrorsr r rsympy.polys.polyutilsrrsympy.utilitiesrsympy.utilities.iterablesrr__all__rjr"r rsU/".%&,;%QQ;"1P6P6P6f* *r"