K iLJdZddlmZddlmZddlmZddlmZddl m Z ddl m Z ddl mZdd lmZdd lmZdd lmZdd lmZGd deZGddeZGddeZGddZGddeeZexZe_GddeeZexZe_y)zDomains of Gaussian type.) annotations)I)DMP)CoercionFailed)ZZ)QQ)AlgebraicField)Domain) DomainElement)Field)RingceZdZUdZded<ded<dZddZefdZdZ d Z d Z d Z d Z d ZdZdZedZdZeZdZdZdZeZdZdZdZdZdZdZdZdZdZ xZ!S)GaussianElementz1Base class for elements of Gaussian type domains.r base_parent)xycj|jj}|j||||SN)rconvertnew)clsrrconvs i/mnt/ssd/data/python-lab/Trading/venv/lib/python3.12/site-packages/sympy/polys/domains/gaussiandomains.py__new__zGaussianElement.__new__s*xxwwtAwQ((cBt||}||_||_|S)z0Create a new GaussianElement of the same domain.)superrrr)rrrobj __class__s rrzGaussianElement.news&goc" rc|jS)z4The domain that this is an element of (ZZ_I or QQ_I))rselfs rparentzGaussianElement.parent#s ||rcDt|j|jfSr)hashrrr"s r__hash__zGaussianElement.__hash__'sTVVTVV$%%rct||jr4|j|jk(xr|j|jk(StSr) isinstancer rrNotImplementedr#others r__eq__zGaussianElement.__eq__*s; eT^^ ,66UWW$:577): :! !rct|tstS|j|jg|j|jgkSr)r)rr*rrr+s r__lt__zGaussianElement.__lt__0s7%1! !577EGG"444rc|Srr"s r__pos__zGaussianElement.__pos__5s rcR|j|j |j Srrrrr"s r__neg__zGaussianElement.__neg__8sxx$&&))rch|jjd|jd|jdS)N(z, ))rreprrr"s r__repr__zGaussianElement.__repr__;s!#||//@@rcJt|jj|Sr)strrto_sympyr"s r__str__zGaussianElement.__str__>s4<<((.//rct||s |jj|}|j|j fS#t$rYywxYw)N)NN)r)rrrrr)rr,s r_get_xyzGaussianElement._get_xyAsN%% " ++E2ww" "! "sA A  A c|j|\}}|,|j|j|z|j|zStSrr@rrrr*r#r,rrs r__add__zGaussianElement.__add__J@||E"1 =88DFFQJ 3 3! !rc|j|\}}|,|j|j|z |j|z StSrrBrCs r__sub__zGaussianElement.__sub__SrErc|j|\}}|,|j||jz ||jz StSrrBrCs r__rsub__zGaussianElement.__rsub__Zs@||E"1 =88AJDFF 3 3! !rc|j|\}}|L|j|j|z|j|zz |j|z|j|zzStSrrBrCs r__mul__zGaussianElement.__mul__asZ||E"1 =88DFF1Htvvax/DFF1H1DE E! !rc|dk(r|jddS|dkrd|z | }}|dk(r|S|}|dzr|n|jj}|dz}|r||z}|dzr||z}|dz}|r|S)Nr)rrone)r#exppow2prods r__pow__zGaussianElement.__pow__js !888Aq> ! 7$#D !8KQwtDLL$4$4   DLDQw  AIC   rcZt|jxst|jSr)boolrrr"s r__bool__zGaussianElement.__bool__{sDFF|+tDFF|+rc|jdkDr|jdkDrdSdS|jdkr|jdkrdSdS|jdk\rdSdS)zIReturn quadrant index 0-3. 0 is included in quadrant 0. rrMrN)rrr"s rquadrantzGaussianElement.quadrant~sY 66A: 1 ) ) VVaZ 1 ) )! 1 * *rc |jj|}|j|S#t$r tcYSwxYwr)rr __divmod__rr*r+s r __rdivmod__zGaussianElement.__rdivmod__sE *LL((/E##D) ) "! ! "s.AAcz tj|}|j|S#t$r tcYSwxYwr)QQ_Ir __truediv__rr*r+s r __rtruediv__zGaussianElement.__rtruediv__s? +LL'E$$T* * "! ! "s (::cB|j|}|tur|S|dSNrr[r*r#r,qrs r __floordiv__zGaussianElement.__floordiv__& __U #>)r4r!u4rcB|j|}|tur|S|dSrbr\r*rds r __rfloordiv__zGaussianElement.__rfloordiv__(   e $>)r4r!u4rcB|j|}|tur|S|dSNrMrcrds r__mod__zGaussianElement.__mod__rgrcB|j|}|tur|S|dSrmrirds r__rmod__zGaussianElement.__rmod__rkr)r)"__name__ __module__ __qualname____doc____annotations__ __slots__r classmethodrr$r'r-r/r2r5r:r>r@rD__radd__rGrIrK__rmul__rSrVrYr\r`rfrjrnrp __classcell__)r s@rrrs; L OI)&" 5 *A0  "H"""H", +*+5555rrc eZdZdZeZdZdZy)GaussianIntegerzGaussian integer: domain element for :ref:`ZZ_I` >>> from sympy import ZZ_I >>> z = ZZ_I(2, 3) >>> z (2 + 3*I) >>> type(z) c2tj||z S)Return a Gaussian rational.)r^rr+s rr_zGaussianInteger.__truediv__s||D!%''rcj|stdj||j|\}}|tS|j|z|j |zz|j |z|j |zz}}||z||zz}d|z|zd|zz}d|z|zd|zz}t ||} | || |zz fS)Nz divmod({}, 0)rN)ZeroDivisionErrorformatr@r*rrr|) r#r,rrabcqxqyqs rr[zGaussianInteger.__divmod__s#O$:$:4$@A A||E"1 9! !vvax$&&("TVVGAIq$81 aC!A#IcAg1Q3 cAg1Q3  B #$5.  rN)rqrrrsrtrrr_r[r1rrr|r|s D(!rr|c eZdZdZeZdZdZy)GaussianRationalaGaussian rational: domain element for :ref:`QQ_I` >>> from sympy import QQ_I, QQ >>> z = QQ_I(QQ(2, 3), QQ(4, 5)) >>> z (2/3 + 4/5*I) >>> type(z) c"|stdj||j|\}}|tS||z||zz}t |j |z|j |zz|z |j |z|j |zz|z S)r~z{} / 0)rrr@r*rrr)r#r,rrrs rr_zGaussianRational.__truediv__s#HOOD$9: :||E"1 9! ! aC!A#IDFF1H!4a 7"&&&TVVAX!5q 8: :rc |jj|}|st dj |||z t jfS#t$r tcYSwxYw)Nz{} % 0)rrrr*rrr^zeror+s rr[zGaussianRational.__divmod__s^ "LL((/E#HOOD$9: ::tyy( (  "! ! "sAA A N)rqrrrsrtrrr_r[r1rrrrs D :)rrceZdZUdZded<dZdZdZdZdZ dZ dZ dZ d Z d Zd Zd Zd ZdZdZdZdZdZdZy)GaussianDomainz Base class for Gaussian domains.r domTc|jj}||jt||jzzS)z!Convert ``a`` to a SymPy object. )rr=rrr)r#rrs rr=zGaussianDomain.to_sympys0xx  ACCy1T!##Y;&&rcJ|j\}}|jj|}|s|j|dS|j \}}|jj|}|t ur|j||St dj|)z)Convert a SymPy object to ``self.dtype``.rz{} is not Gaussian) as_coeff_Addr from_sympyr as_coeff_Mulrrr)r#rrrrrs rrzGaussianDomain.from_sympys~~1 HH   "88Aq> !~~1 HH   " 688Aq> ! !5!rrc|jjdtk(r |j|j |Sy)z9Convert an element from ZZ or QQ to ``self.dtype``.rN)extargsrrr=rs rfrom_AlgebraicFieldz"GaussianDomain.from_AlgebraicFieldBs2 66;;q>Q ==Q0 0 rN)rqrrrsrtru is_Numericalis_Exacthas_assoc_Ringhas_assoc_Fieldr=rrrrrrrrrrrrrrr1rrrrsj* KLHNO' A%1rrcbeZdZdZeZeejejejgeZ e Z e ededZe ededZe ededZ ee e e fZ dZdZdZdZdZdZdZed Zd Zd Zd Zd ZdZdZdZdZdZy)GaussianIntegerRinga{ Ring of Gaussian integers ``ZZ_I`` The :ref:`ZZ_I` domain represents the `Gaussian integers`_ `\mathbb{Z}[i]` as a :py:class:`~.Domain` in the domain system (see :ref:`polys-domainsintro`). By default a :py:class:`~.Poly` created from an expression with coefficients that are combinations of integers and ``I`` (`\sqrt{-1}`) will have the domain :ref:`ZZ_I`. >>> from sympy import Poly, Symbol, I >>> x = Symbol('x') >>> p = Poly(x**2 + I) >>> p Poly(x**2 + I, x, domain='ZZ_I') >>> p.domain ZZ_I The :ref:`ZZ_I` domain can be used to factorise polynomials that are reducible over the Gaussian integers. >>> from sympy import factor >>> factor(x**2 + 1) x**2 + 1 >>> factor(x**2 + 1, domain='ZZ_I') (x - I)*(x + I) The corresponding `field of fractions`_ is the domain of the Gaussian rationals :ref:`QQ_I`. Conversely :ref:`ZZ_I` is the `ring of integers`_ of :ref:`QQ_I`. >>> from sympy import ZZ_I, QQ_I >>> ZZ_I.get_field() QQ_I >>> QQ_I.get_ring() ZZ_I When using the domain directly :ref:`ZZ_I` can be used as a constructor. >>> ZZ_I(3, 4) (3 + 4*I) >>> ZZ_I(5) (5 + 0*I) The domain elements of :ref:`ZZ_I` are instances of :py:class:`~.GaussianInteger` which support the rings operations ``+,-,*,**``. >>> z1 = ZZ_I(5, 1) >>> z2 = ZZ_I(2, 3) >>> z1 (5 + 1*I) >>> z2 (2 + 3*I) >>> z1 + z2 (7 + 4*I) >>> z1 * z2 (7 + 17*I) >>> z1 ** 2 (24 + 10*I) Both floor (``//``) and modulo (``%``) division work with :py:class:`~.GaussianInteger` (see the :py:meth:`~.Domain.div` method). >>> z3, z4 = ZZ_I(5), ZZ_I(1, 3) >>> z3 // z4 # floor division (1 + -1*I) >>> z3 % z4 # modulo division (remainder) (1 + -2*I) >>> (z3//z4)*z4 + z3%z4 == z3 True True division (``/``) in :ref:`ZZ_I` gives an element of :ref:`QQ_I`. The :py:meth:`~.Domain.exquo` method can be used to divide in :ref:`ZZ_I` when exact division is possible. >>> z1 / z2 (1 + -1*I) >>> ZZ_I.exquo(z1, z2) (1 + -1*I) >>> z3 / z4 (1/2 + -3/2*I) >>> ZZ_I.exquo(z3, z4) Traceback (most recent call last): ... ExactQuotientFailed: (1 + 3*I) does not divide (5 + 0*I) in ZZ_I The :py:meth:`~.Domain.gcd` method can be used to compute the `gcd`_ of any two elements. >>> ZZ_I.gcd(ZZ_I(10), ZZ_I(2)) (2 + 0*I) >>> ZZ_I.gcd(ZZ_I(5), ZZ_I(2, 1)) (2 + 1*I) .. _Gaussian integers: https://en.wikipedia.org/wiki/Gaussian_integer .. _gcd: https://en.wikipedia.org/wiki/Greatest_common_divisor rrMZZ_ITcy)zFor constructing ZZ_I.Nr1r"s r__init__zGaussianIntegerRing.__init__rc0t|trytSz0Returns ``True`` if two domains are equivalent. T)r)rr*r+s rr-zGaussianIntegerRing.__eq__s e0 1! !rctdS)Compute hash code of ``self``. rr&r"s rr'zGaussianIntegerRing.__hash__ F|rcyNTr1r"s rhas_CharacteristicZeroz*GaussianIntegerRing.has_CharacteristicZerorcyrbr1r"s rcharacteristicz"GaussianIntegerRing.characteristicrc|Sz)Returns a ring associated with ``self``. r1r"s rget_ringzGaussianIntegerRing.get_ring rctSz*Returns a field associated with ``self``. )r^r"s r get_fieldzGaussianIntegerRing.get_field rcl|j||z}tfd|D}|r|f|zS|S)zReturn first quadrant element associated with ``d``. Also multiply the other arguments by the same power of i. c3(K|] }|z ywrr1).0rrs r z0GaussianIntegerRing.normalize..s*QtV*s)rtuple)r#rrrs @r normalizezGaussianIntegerRing.normalizesA ""1% T *T**"td{))rc<|r |||z}}|r |j|S)z-Greatest common divisor of a and b over ZZ_I.)rr#rrs rgcdzGaussianIntegerRing.gcds&a!eqA~~a  rc|j}|j}|j}|j}|r&||z}||||zz }}||||zz }}||||zz }}|r&|j|||\}}}|||fS)z6Return x, y, g such that x * a + y * b = g = gcd(a, b))rOrr)r#rrx_ax_by_ay_brs rgcdexzGaussianIntegerRing.gcdexshhiiiihhQAa!a%iqAC!c'MCC!c'MC  nnQS1 3C{rc2||z|j||zS)z+Least common multiple of a and b over ZZ_I.)rrs rlcmzGaussianIntegerRing.lcmsA$((1a.((rc|S)zConvert a ZZ_I element to ZZ_I.r1rs rfrom_GaussianIntegerRingz,GaussianIntegerRing.from_GaussianIntegerRingrc|jtj|jtj|jS)zConvert a QQ_I element to ZZ_I.)rrrrrrs rfrom_GaussianRationalFieldz.GaussianIntegerRing.from_GaussianRationalFields+vvbjjorzz!##77rN) rqrrrsrtrrrrOrmodr|dtype imag_unitrr9is_GaussianRingis_ZZ_Iis_PIDrr-r'propertyrrrrrrrrrrr1rrrrHsbF C rvvrww' ,C E A1 D 1r!u CbeRU#I )cTI: .E COG F%"*! )8rrc^eZdZdZeZeejejejgeZ e Z e ededZe ededZe ededZ ee e e fZ dZdZdZdZdZdZed Zd Zd Zd Zd ZdZdZdZdZdZy)GaussianRationalFielda Field of Gaussian rationals ``QQ_I`` The :ref:`QQ_I` domain represents the `Gaussian rationals`_ `\mathbb{Q}(i)` as a :py:class:`~.Domain` in the domain system (see :ref:`polys-domainsintro`). By default a :py:class:`~.Poly` created from an expression with coefficients that are combinations of rationals and ``I`` (`\sqrt{-1}`) will have the domain :ref:`QQ_I`. >>> from sympy import Poly, Symbol, I >>> x = Symbol('x') >>> p = Poly(x**2 + I/2) >>> p Poly(x**2 + I/2, x, domain='QQ_I') >>> p.domain QQ_I The polys option ``gaussian=True`` can be used to specify that the domain should be :ref:`QQ_I` even if the coefficients do not contain ``I`` or are all integers. >>> Poly(x**2) Poly(x**2, x, domain='ZZ') >>> Poly(x**2 + I) Poly(x**2 + I, x, domain='ZZ_I') >>> Poly(x**2/2) Poly(1/2*x**2, x, domain='QQ') >>> Poly(x**2, gaussian=True) Poly(x**2, x, domain='QQ_I') >>> Poly(x**2 + I, gaussian=True) Poly(x**2 + I, x, domain='QQ_I') >>> Poly(x**2/2, gaussian=True) Poly(1/2*x**2, x, domain='QQ_I') The :ref:`QQ_I` domain can be used to factorise polynomials that are reducible over the Gaussian rationals. >>> from sympy import factor, QQ_I >>> factor(x**2/4 + 1) (x**2 + 4)/4 >>> factor(x**2/4 + 1, domain='QQ_I') (x - 2*I)*(x + 2*I)/4 >>> factor(x**2/4 + 1, domain=QQ_I) (x - 2*I)*(x + 2*I)/4 It is also possible to specify the :ref:`QQ_I` domain explicitly with polys functions like :py:func:`~.apart`. >>> from sympy import apart >>> apart(1/(1 + x**2)) 1/(x**2 + 1) >>> apart(1/(1 + x**2), domain=QQ_I) I/(2*(x + I)) - I/(2*(x - I)) The corresponding `ring of integers`_ is the domain of the Gaussian integers :ref:`ZZ_I`. Conversely :ref:`QQ_I` is the `field of fractions`_ of :ref:`ZZ_I`. >>> from sympy import ZZ_I, QQ_I, QQ >>> ZZ_I.get_field() QQ_I >>> QQ_I.get_ring() ZZ_I When using the domain directly :ref:`QQ_I` can be used as a constructor. >>> QQ_I(3, 4) (3 + 4*I) >>> QQ_I(5) (5 + 0*I) >>> QQ_I(QQ(2, 3), QQ(4, 5)) (2/3 + 4/5*I) The domain elements of :ref:`QQ_I` are instances of :py:class:`~.GaussianRational` which support the field operations ``+,-,*,**,/``. >>> z1 = QQ_I(5, 1) >>> z2 = QQ_I(2, QQ(1, 2)) >>> z1 (5 + 1*I) >>> z2 (2 + 1/2*I) >>> z1 + z2 (7 + 3/2*I) >>> z1 * z2 (19/2 + 9/2*I) >>> z2 ** 2 (15/4 + 2*I) True division (``/``) in :ref:`QQ_I` gives an element of :ref:`QQ_I` and is always exact. >>> z1 / z2 (42/17 + -2/17*I) >>> QQ_I.exquo(z1, z2) (42/17 + -2/17*I) >>> z1 == (z1/z2)*z2 True Both floor (``//``) and modulo (``%``) division can be used with :py:class:`~.GaussianRational` (see :py:meth:`~.Domain.div`) but division is always exact so there is no remainder. >>> z1 // z2 (42/17 + -2/17*I) >>> z1 % z2 (0 + 0*I) >>> QQ_I.div(z1, z2) ((42/17 + -2/17*I), (0 + 0*I)) >>> (z1//z2)*z2 + z1%z2 == z1 True .. _Gaussian rationals: https://en.wikipedia.org/wiki/Gaussian_rational rrMr^Tcy)zFor constructing QQ_I.Nr1r"s rrzGaussianRationalField.__init__rrc0t|trytSr)r)rr*r+s rr-zGaussianRationalField.__eq__s e2 3! !rctdS)rr^rr"s rr'zGaussianRationalField.__hash__rrcyrr1r"s rrz,GaussianRationalField.has_CharacteristicZerorrcyrbr1r"s rrz$GaussianRationalField.characteristicrrctSr)rr"s rrzGaussianRationalField.get_ringrrc|Srr1r"s rrzGaussianRationalField.get_fieldrrc6t|jtS)z0Get equivalent domain as an ``AlgebraicField``. )r rrr"s ras_AlgebraicFieldz'GaussianRationalField.as_AlgebraicFieldsdhh**rch|j}|j||j|zS)zGet the numerator of ``a``.)rrdenom)r#rrs rnumerzGaussianRationalField.numers)}}||A 1 -..rc"|jj}|j}|j}|j|j|j|j|j }|||j S)zGet the denominator of ``a``.)rrrr rrr)r#rrrrdenom_ZZs rr zGaussianRationalField.denomsg XX    XX}}266("((133-!##7Hbgg&&rcN|j|j|jS)zConvert a ZZ_I element to QQ_I.r4rs rrz.GaussianRationalField.from_GaussianIntegerRingsvvacc133rc|S)zConvert a QQ_I element to QQ_I.r1rs rrz0GaussianRationalField.from_GaussianRationalFieldrrc|jtj|jtj|jS)z'Convert a ComplexField element to QQ_I.)rrrrealimagrs rfrom_ComplexFieldz'GaussianRationalField.from_ComplexFields-vvbjj("**QVV*<==rN)rqrrrsrtrrrrOrrrrrrr9is_GaussianFieldis_QQ_Irr-r'rrrrrrr r rrrr1rrrrssh C rvvrww' ,C E A1 D 1r!u CbeRU#I )cTI: .E CG%"+/ ' >rrN) rt __future__rsympy.core.numbersrsympy.polys.polyclassesrsympy.polys.polyerrorsrsympy.polys.domains.integerringr!sympy.polys.domains.rationalfieldr"sympy.polys.domains.algebraicfieldr sympy.polys.domains.domainr !sympy.polys.domains.domainelementr sympy.polys.domains.fieldr sympy.polys.domains.ringr rr|rrrrrrr^r1rrr s" '1.0=-;+)X5mX5v%!o%!P ) )FO1O1dx8.$x8t"5!66z>NEz>z#8"99r