12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892 |
- """Euclidean algorithms, GCDs, LCMs and polynomial remainder sequences. """
- from sympy.ntheory import nextprime
- from sympy.polys.densearith import (
- dup_sub_mul,
- dup_neg, dmp_neg,
- dmp_add,
- dmp_sub,
- dup_mul, dmp_mul,
- dmp_pow,
- dup_div, dmp_div,
- dup_rem,
- dup_quo, dmp_quo,
- dup_prem, dmp_prem,
- dup_mul_ground, dmp_mul_ground,
- dmp_mul_term,
- dup_quo_ground, dmp_quo_ground,
- dup_max_norm, dmp_max_norm)
- from sympy.polys.densebasic import (
- dup_strip, dmp_raise,
- dmp_zero, dmp_one, dmp_ground,
- dmp_one_p, dmp_zero_p,
- dmp_zeros,
- dup_degree, dmp_degree, dmp_degree_in,
- dup_LC, dmp_LC, dmp_ground_LC,
- dmp_multi_deflate, dmp_inflate,
- dup_convert, dmp_convert,
- dmp_apply_pairs)
- from sympy.polys.densetools import (
- dup_clear_denoms, dmp_clear_denoms,
- dup_diff, dmp_diff,
- dup_eval, dmp_eval, dmp_eval_in,
- dup_trunc, dmp_ground_trunc,
- dup_monic, dmp_ground_monic,
- dup_primitive, dmp_ground_primitive,
- dup_extract, dmp_ground_extract)
- from sympy.polys.galoistools import (
- gf_int, gf_crt)
- from sympy.polys.polyconfig import query
- from sympy.polys.polyerrors import (
- MultivariatePolynomialError,
- HeuristicGCDFailed,
- HomomorphismFailed,
- NotInvertible,
- DomainError)
- def dup_half_gcdex(f, g, K):
- """
- Half extended Euclidean algorithm in `F[x]`.
- Returns ``(s, h)`` such that ``h = gcd(f, g)`` and ``s*f = h (mod g)``.
- Examples
- ========
- >>> from sympy.polys import ring, QQ
- >>> R, x = ring("x", QQ)
- >>> f = x**4 - 2*x**3 - 6*x**2 + 12*x + 15
- >>> g = x**3 + x**2 - 4*x - 4
- >>> R.dup_half_gcdex(f, g)
- (-1/5*x + 3/5, x + 1)
- """
- if not K.is_Field:
- raise DomainError("Cannot compute half extended GCD over %s" % K)
- a, b = [K.one], []
- while g:
- q, r = dup_div(f, g, K)
- f, g = g, r
- a, b = b, dup_sub_mul(a, q, b, K)
- a = dup_quo_ground(a, dup_LC(f, K), K)
- f = dup_monic(f, K)
- return a, f
- def dmp_half_gcdex(f, g, u, K):
- """
- Half extended Euclidean algorithm in `F[X]`.
- Examples
- ========
- >>> from sympy.polys import ring, ZZ
- >>> R, x,y = ring("x,y", ZZ)
- """
- if not u:
- return dup_half_gcdex(f, g, K)
- else:
- raise MultivariatePolynomialError(f, g)
- def dup_gcdex(f, g, K):
- """
- Extended Euclidean algorithm in `F[x]`.
- Returns ``(s, t, h)`` such that ``h = gcd(f, g)`` and ``s*f + t*g = h``.
- Examples
- ========
- >>> from sympy.polys import ring, QQ
- >>> R, x = ring("x", QQ)
- >>> f = x**4 - 2*x**3 - 6*x**2 + 12*x + 15
- >>> g = x**3 + x**2 - 4*x - 4
- >>> R.dup_gcdex(f, g)
- (-1/5*x + 3/5, 1/5*x**2 - 6/5*x + 2, x + 1)
- """
- s, h = dup_half_gcdex(f, g, K)
- F = dup_sub_mul(h, s, f, K)
- t = dup_quo(F, g, K)
- return s, t, h
- def dmp_gcdex(f, g, u, K):
- """
- Extended Euclidean algorithm in `F[X]`.
- Examples
- ========
- >>> from sympy.polys import ring, ZZ
- >>> R, x,y = ring("x,y", ZZ)
- """
- if not u:
- return dup_gcdex(f, g, K)
- else:
- raise MultivariatePolynomialError(f, g)
- def dup_invert(f, g, K):
- """
- Compute multiplicative inverse of `f` modulo `g` in `F[x]`.
- Examples
- ========
- >>> from sympy.polys import ring, QQ
- >>> R, x = ring("x", QQ)
- >>> f = x**2 - 1
- >>> g = 2*x - 1
- >>> h = x - 1
- >>> R.dup_invert(f, g)
- -4/3
- >>> R.dup_invert(f, h)
- Traceback (most recent call last):
- ...
- NotInvertible: zero divisor
- """
- s, h = dup_half_gcdex(f, g, K)
- if h == [K.one]:
- return dup_rem(s, g, K)
- else:
- raise NotInvertible("zero divisor")
- def dmp_invert(f, g, u, K):
- """
- Compute multiplicative inverse of `f` modulo `g` in `F[X]`.
- Examples
- ========
- >>> from sympy.polys import ring, QQ
- >>> R, x = ring("x", QQ)
- """
- if not u:
- return dup_invert(f, g, K)
- else:
- raise MultivariatePolynomialError(f, g)
- def dup_euclidean_prs(f, g, K):
- """
- Euclidean polynomial remainder sequence (PRS) in `K[x]`.
- Examples
- ========
- >>> from sympy.polys import ring, QQ
- >>> R, x = ring("x", QQ)
- >>> f = x**8 + x**6 - 3*x**4 - 3*x**3 + 8*x**2 + 2*x - 5
- >>> g = 3*x**6 + 5*x**4 - 4*x**2 - 9*x + 21
- >>> prs = R.dup_euclidean_prs(f, g)
- >>> prs[0]
- x**8 + x**6 - 3*x**4 - 3*x**3 + 8*x**2 + 2*x - 5
- >>> prs[1]
- 3*x**6 + 5*x**4 - 4*x**2 - 9*x + 21
- >>> prs[2]
- -5/9*x**4 + 1/9*x**2 - 1/3
- >>> prs[3]
- -117/25*x**2 - 9*x + 441/25
- >>> prs[4]
- 233150/19773*x - 102500/6591
- >>> prs[5]
- -1288744821/543589225
- """
- prs = [f, g]
- h = dup_rem(f, g, K)
- while h:
- prs.append(h)
- f, g = g, h
- h = dup_rem(f, g, K)
- return prs
- def dmp_euclidean_prs(f, g, u, K):
- """
- Euclidean polynomial remainder sequence (PRS) in `K[X]`.
- Examples
- ========
- >>> from sympy.polys import ring, ZZ
- >>> R, x,y = ring("x,y", ZZ)
- """
- if not u:
- return dup_euclidean_prs(f, g, K)
- else:
- raise MultivariatePolynomialError(f, g)
- def dup_primitive_prs(f, g, K):
- """
- Primitive polynomial remainder sequence (PRS) in `K[x]`.
- Examples
- ========
- >>> from sympy.polys import ring, ZZ
- >>> R, x = ring("x", ZZ)
- >>> f = x**8 + x**6 - 3*x**4 - 3*x**3 + 8*x**2 + 2*x - 5
- >>> g = 3*x**6 + 5*x**4 - 4*x**2 - 9*x + 21
- >>> prs = R.dup_primitive_prs(f, g)
- >>> prs[0]
- x**8 + x**6 - 3*x**4 - 3*x**3 + 8*x**2 + 2*x - 5
- >>> prs[1]
- 3*x**6 + 5*x**4 - 4*x**2 - 9*x + 21
- >>> prs[2]
- -5*x**4 + x**2 - 3
- >>> prs[3]
- 13*x**2 + 25*x - 49
- >>> prs[4]
- 4663*x - 6150
- >>> prs[5]
- 1
- """
- prs = [f, g]
- _, h = dup_primitive(dup_prem(f, g, K), K)
- while h:
- prs.append(h)
- f, g = g, h
- _, h = dup_primitive(dup_prem(f, g, K), K)
- return prs
- def dmp_primitive_prs(f, g, u, K):
- """
- Primitive polynomial remainder sequence (PRS) in `K[X]`.
- Examples
- ========
- >>> from sympy.polys import ring, ZZ
- >>> R, x,y = ring("x,y", ZZ)
- """
- if not u:
- return dup_primitive_prs(f, g, K)
- else:
- raise MultivariatePolynomialError(f, g)
- def dup_inner_subresultants(f, g, K):
- """
- Subresultant PRS algorithm in `K[x]`.
- Computes the subresultant polynomial remainder sequence (PRS)
- and the non-zero scalar subresultants of `f` and `g`.
- By [1] Thm. 3, these are the constants '-c' (- to optimize
- computation of sign).
- The first subdeterminant is set to 1 by convention to match
- the polynomial and the scalar subdeterminants.
- If 'deg(f) < deg(g)', the subresultants of '(g,f)' are computed.
- Examples
- ========
- >>> from sympy.polys import ring, ZZ
- >>> R, x = ring("x", ZZ)
- >>> R.dup_inner_subresultants(x**2 + 1, x**2 - 1)
- ([x**2 + 1, x**2 - 1, -2], [1, 1, 4])
- References
- ==========
- .. [1] W.S. Brown, The Subresultant PRS Algorithm.
- ACM Transaction of Mathematical Software 4 (1978) 237-249
- """
- n = dup_degree(f)
- m = dup_degree(g)
- if n < m:
- f, g = g, f
- n, m = m, n
- if not f:
- return [], []
- if not g:
- return [f], [K.one]
- R = [f, g]
- d = n - m
- b = (-K.one)**(d + 1)
- h = dup_prem(f, g, K)
- h = dup_mul_ground(h, b, K)
- lc = dup_LC(g, K)
- c = lc**d
- # Conventional first scalar subdeterminant is 1
- S = [K.one, c]
- c = -c
- while h:
- k = dup_degree(h)
- R.append(h)
- f, g, m, d = g, h, k, m - k
- b = -lc * c**d
- h = dup_prem(f, g, K)
- h = dup_quo_ground(h, b, K)
- lc = dup_LC(g, K)
- if d > 1: # abnormal case
- q = c**(d - 1)
- c = K.quo((-lc)**d, q)
- else:
- c = -lc
- S.append(-c)
- return R, S
- def dup_subresultants(f, g, K):
- """
- Computes subresultant PRS of two polynomials in `K[x]`.
- Examples
- ========
- >>> from sympy.polys import ring, ZZ
- >>> R, x = ring("x", ZZ)
- >>> R.dup_subresultants(x**2 + 1, x**2 - 1)
- [x**2 + 1, x**2 - 1, -2]
- """
- return dup_inner_subresultants(f, g, K)[0]
- def dup_prs_resultant(f, g, K):
- """
- Resultant algorithm in `K[x]` using subresultant PRS.
- Examples
- ========
- >>> from sympy.polys import ring, ZZ
- >>> R, x = ring("x", ZZ)
- >>> R.dup_prs_resultant(x**2 + 1, x**2 - 1)
- (4, [x**2 + 1, x**2 - 1, -2])
- """
- if not f or not g:
- return (K.zero, [])
- R, S = dup_inner_subresultants(f, g, K)
- if dup_degree(R[-1]) > 0:
- return (K.zero, R)
- return S[-1], R
- def dup_resultant(f, g, K, includePRS=False):
- """
- Computes resultant of two polynomials in `K[x]`.
- Examples
- ========
- >>> from sympy.polys import ring, ZZ
- >>> R, x = ring("x", ZZ)
- >>> R.dup_resultant(x**2 + 1, x**2 - 1)
- 4
- """
- if includePRS:
- return dup_prs_resultant(f, g, K)
- return dup_prs_resultant(f, g, K)[0]
- def dmp_inner_subresultants(f, g, u, K):
- """
- Subresultant PRS algorithm in `K[X]`.
- Examples
- ========
- >>> from sympy.polys import ring, ZZ
- >>> R, x,y = ring("x,y", ZZ)
- >>> f = 3*x**2*y - y**3 - 4
- >>> g = x**2 + x*y**3 - 9
- >>> a = 3*x*y**4 + y**3 - 27*y + 4
- >>> b = -3*y**10 - 12*y**7 + y**6 - 54*y**4 + 8*y**3 + 729*y**2 - 216*y + 16
- >>> prs = [f, g, a, b]
- >>> sres = [[1], [1], [3, 0, 0, 0, 0], [-3, 0, 0, -12, 1, 0, -54, 8, 729, -216, 16]]
- >>> R.dmp_inner_subresultants(f, g) == (prs, sres)
- True
- """
- if not u:
- return dup_inner_subresultants(f, g, K)
- n = dmp_degree(f, u)
- m = dmp_degree(g, u)
- if n < m:
- f, g = g, f
- n, m = m, n
- if dmp_zero_p(f, u):
- return [], []
- v = u - 1
- if dmp_zero_p(g, u):
- return [f], [dmp_ground(K.one, v)]
- R = [f, g]
- d = n - m
- b = dmp_pow(dmp_ground(-K.one, v), d + 1, v, K)
- h = dmp_prem(f, g, u, K)
- h = dmp_mul_term(h, b, 0, u, K)
- lc = dmp_LC(g, K)
- c = dmp_pow(lc, d, v, K)
- S = [dmp_ground(K.one, v), c]
- c = dmp_neg(c, v, K)
- while not dmp_zero_p(h, u):
- k = dmp_degree(h, u)
- R.append(h)
- f, g, m, d = g, h, k, m - k
- b = dmp_mul(dmp_neg(lc, v, K),
- dmp_pow(c, d, v, K), v, K)
- h = dmp_prem(f, g, u, K)
- h = [ dmp_quo(ch, b, v, K) for ch in h ]
- lc = dmp_LC(g, K)
- if d > 1:
- p = dmp_pow(dmp_neg(lc, v, K), d, v, K)
- q = dmp_pow(c, d - 1, v, K)
- c = dmp_quo(p, q, v, K)
- else:
- c = dmp_neg(lc, v, K)
- S.append(dmp_neg(c, v, K))
- return R, S
- def dmp_subresultants(f, g, u, K):
- """
- Computes subresultant PRS of two polynomials in `K[X]`.
- Examples
- ========
- >>> from sympy.polys import ring, ZZ
- >>> R, x,y = ring("x,y", ZZ)
- >>> f = 3*x**2*y - y**3 - 4
- >>> g = x**2 + x*y**3 - 9
- >>> a = 3*x*y**4 + y**3 - 27*y + 4
- >>> b = -3*y**10 - 12*y**7 + y**6 - 54*y**4 + 8*y**3 + 729*y**2 - 216*y + 16
- >>> R.dmp_subresultants(f, g) == [f, g, a, b]
- True
- """
- return dmp_inner_subresultants(f, g, u, K)[0]
- def dmp_prs_resultant(f, g, u, K):
- """
- Resultant algorithm in `K[X]` using subresultant PRS.
- Examples
- ========
- >>> from sympy.polys import ring, ZZ
- >>> R, x,y = ring("x,y", ZZ)
- >>> f = 3*x**2*y - y**3 - 4
- >>> g = x**2 + x*y**3 - 9
- >>> a = 3*x*y**4 + y**3 - 27*y + 4
- >>> b = -3*y**10 - 12*y**7 + y**6 - 54*y**4 + 8*y**3 + 729*y**2 - 216*y + 16
- >>> res, prs = R.dmp_prs_resultant(f, g)
- >>> res == b # resultant has n-1 variables
- False
- >>> res == b.drop(x)
- True
- >>> prs == [f, g, a, b]
- True
- """
- if not u:
- return dup_prs_resultant(f, g, K)
- if dmp_zero_p(f, u) or dmp_zero_p(g, u):
- return (dmp_zero(u - 1), [])
- R, S = dmp_inner_subresultants(f, g, u, K)
- if dmp_degree(R[-1], u) > 0:
- return (dmp_zero(u - 1), R)
- return S[-1], R
- def dmp_zz_modular_resultant(f, g, p, u, K):
- """
- Compute resultant of `f` and `g` modulo a prime `p`.
- Examples
- ========
- >>> from sympy.polys import ring, ZZ
- >>> R, x,y = ring("x,y", ZZ)
- >>> f = x + y + 2
- >>> g = 2*x*y + x + 3
- >>> R.dmp_zz_modular_resultant(f, g, 5)
- -2*y**2 + 1
- """
- if not u:
- return gf_int(dup_prs_resultant(f, g, K)[0] % p, p)
- v = u - 1
- n = dmp_degree(f, u)
- m = dmp_degree(g, u)
- N = dmp_degree_in(f, 1, u)
- M = dmp_degree_in(g, 1, u)
- B = n*M + m*N
- D, a = [K.one], -K.one
- r = dmp_zero(v)
- while dup_degree(D) <= B:
- while True:
- a += K.one
- if a == p:
- raise HomomorphismFailed('no luck')
- F = dmp_eval_in(f, gf_int(a, p), 1, u, K)
- if dmp_degree(F, v) == n:
- G = dmp_eval_in(g, gf_int(a, p), 1, u, K)
- if dmp_degree(G, v) == m:
- break
- R = dmp_zz_modular_resultant(F, G, p, v, K)
- e = dmp_eval(r, a, v, K)
- if not v:
- R = dup_strip([R])
- e = dup_strip([e])
- else:
- R = [R]
- e = [e]
- d = K.invert(dup_eval(D, a, K), p)
- d = dup_mul_ground(D, d, K)
- d = dmp_raise(d, v, 0, K)
- c = dmp_mul(d, dmp_sub(R, e, v, K), v, K)
- r = dmp_add(r, c, v, K)
- r = dmp_ground_trunc(r, p, v, K)
- D = dup_mul(D, [K.one, -a], K)
- D = dup_trunc(D, p, K)
- return r
- def _collins_crt(r, R, P, p, K):
- """Wrapper of CRT for Collins's resultant algorithm. """
- return gf_int(gf_crt([r, R], [P, p], K), P*p)
- def dmp_zz_collins_resultant(f, g, u, K):
- """
- Collins's modular resultant algorithm in `Z[X]`.
- Examples
- ========
- >>> from sympy.polys import ring, ZZ
- >>> R, x,y = ring("x,y", ZZ)
- >>> f = x + y + 2
- >>> g = 2*x*y + x + 3
- >>> R.dmp_zz_collins_resultant(f, g)
- -2*y**2 - 5*y + 1
- """
- n = dmp_degree(f, u)
- m = dmp_degree(g, u)
- if n < 0 or m < 0:
- return dmp_zero(u - 1)
- A = dmp_max_norm(f, u, K)
- B = dmp_max_norm(g, u, K)
- a = dmp_ground_LC(f, u, K)
- b = dmp_ground_LC(g, u, K)
- v = u - 1
- B = K(2)*K.factorial(K(n + m))*A**m*B**n
- r, p, P = dmp_zero(v), K.one, K.one
- while P <= B:
- p = K(nextprime(p))
- while not (a % p) or not (b % p):
- p = K(nextprime(p))
- F = dmp_ground_trunc(f, p, u, K)
- G = dmp_ground_trunc(g, p, u, K)
- try:
- R = dmp_zz_modular_resultant(F, G, p, u, K)
- except HomomorphismFailed:
- continue
- if K.is_one(P):
- r = R
- else:
- r = dmp_apply_pairs(r, R, _collins_crt, (P, p, K), v, K)
- P *= p
- return r
- def dmp_qq_collins_resultant(f, g, u, K0):
- """
- Collins's modular resultant algorithm in `Q[X]`.
- Examples
- ========
- >>> from sympy.polys import ring, QQ
- >>> R, x,y = ring("x,y", QQ)
- >>> f = QQ(1,2)*x + y + QQ(2,3)
- >>> g = 2*x*y + x + 3
- >>> R.dmp_qq_collins_resultant(f, g)
- -2*y**2 - 7/3*y + 5/6
- """
- n = dmp_degree(f, u)
- m = dmp_degree(g, u)
- if n < 0 or m < 0:
- return dmp_zero(u - 1)
- K1 = K0.get_ring()
- cf, f = dmp_clear_denoms(f, u, K0, K1)
- cg, g = dmp_clear_denoms(g, u, K0, K1)
- f = dmp_convert(f, u, K0, K1)
- g = dmp_convert(g, u, K0, K1)
- r = dmp_zz_collins_resultant(f, g, u, K1)
- r = dmp_convert(r, u - 1, K1, K0)
- c = K0.convert(cf**m * cg**n, K1)
- return dmp_quo_ground(r, c, u - 1, K0)
- def dmp_resultant(f, g, u, K, includePRS=False):
- """
- Computes resultant of two polynomials in `K[X]`.
- Examples
- ========
- >>> from sympy.polys import ring, ZZ
- >>> R, x,y = ring("x,y", ZZ)
- >>> f = 3*x**2*y - y**3 - 4
- >>> g = x**2 + x*y**3 - 9
- >>> R.dmp_resultant(f, g)
- -3*y**10 - 12*y**7 + y**6 - 54*y**4 + 8*y**3 + 729*y**2 - 216*y + 16
- """
- if not u:
- return dup_resultant(f, g, K, includePRS=includePRS)
- if includePRS:
- return dmp_prs_resultant(f, g, u, K)
- if K.is_Field:
- if K.is_QQ and query('USE_COLLINS_RESULTANT'):
- return dmp_qq_collins_resultant(f, g, u, K)
- else:
- if K.is_ZZ and query('USE_COLLINS_RESULTANT'):
- return dmp_zz_collins_resultant(f, g, u, K)
- return dmp_prs_resultant(f, g, u, K)[0]
- def dup_discriminant(f, K):
- """
- Computes discriminant of a polynomial in `K[x]`.
- Examples
- ========
- >>> from sympy.polys import ring, ZZ
- >>> R, x = ring("x", ZZ)
- >>> R.dup_discriminant(x**2 + 2*x + 3)
- -8
- """
- d = dup_degree(f)
- if d <= 0:
- return K.zero
- else:
- s = (-1)**((d*(d - 1)) // 2)
- c = dup_LC(f, K)
- r = dup_resultant(f, dup_diff(f, 1, K), K)
- return K.quo(r, c*K(s))
- def dmp_discriminant(f, u, K):
- """
- Computes discriminant of a polynomial in `K[X]`.
- Examples
- ========
- >>> from sympy.polys import ring, ZZ
- >>> R, x,y,z,t = ring("x,y,z,t", ZZ)
- >>> R.dmp_discriminant(x**2*y + x*z + t)
- -4*y*t + z**2
- """
- if not u:
- return dup_discriminant(f, K)
- d, v = dmp_degree(f, u), u - 1
- if d <= 0:
- return dmp_zero(v)
- else:
- s = (-1)**((d*(d - 1)) // 2)
- c = dmp_LC(f, K)
- r = dmp_resultant(f, dmp_diff(f, 1, u, K), u, K)
- c = dmp_mul_ground(c, K(s), v, K)
- return dmp_quo(r, c, v, K)
- def _dup_rr_trivial_gcd(f, g, K):
- """Handle trivial cases in GCD algorithm over a ring. """
- if not (f or g):
- return [], [], []
- elif not f:
- if K.is_nonnegative(dup_LC(g, K)):
- return g, [], [K.one]
- else:
- return dup_neg(g, K), [], [-K.one]
- elif not g:
- if K.is_nonnegative(dup_LC(f, K)):
- return f, [K.one], []
- else:
- return dup_neg(f, K), [-K.one], []
- return None
- def _dup_ff_trivial_gcd(f, g, K):
- """Handle trivial cases in GCD algorithm over a field. """
- if not (f or g):
- return [], [], []
- elif not f:
- return dup_monic(g, K), [], [dup_LC(g, K)]
- elif not g:
- return dup_monic(f, K), [dup_LC(f, K)], []
- else:
- return None
- def _dmp_rr_trivial_gcd(f, g, u, K):
- """Handle trivial cases in GCD algorithm over a ring. """
- zero_f = dmp_zero_p(f, u)
- zero_g = dmp_zero_p(g, u)
- if_contain_one = dmp_one_p(f, u, K) or dmp_one_p(g, u, K)
- if zero_f and zero_g:
- return tuple(dmp_zeros(3, u, K))
- elif zero_f:
- if K.is_nonnegative(dmp_ground_LC(g, u, K)):
- return g, dmp_zero(u), dmp_one(u, K)
- else:
- return dmp_neg(g, u, K), dmp_zero(u), dmp_ground(-K.one, u)
- elif zero_g:
- if K.is_nonnegative(dmp_ground_LC(f, u, K)):
- return f, dmp_one(u, K), dmp_zero(u)
- else:
- return dmp_neg(f, u, K), dmp_ground(-K.one, u), dmp_zero(u)
- elif if_contain_one:
- return dmp_one(u, K), f, g
- elif query('USE_SIMPLIFY_GCD'):
- return _dmp_simplify_gcd(f, g, u, K)
- else:
- return None
- def _dmp_ff_trivial_gcd(f, g, u, K):
- """Handle trivial cases in GCD algorithm over a field. """
- zero_f = dmp_zero_p(f, u)
- zero_g = dmp_zero_p(g, u)
- if zero_f and zero_g:
- return tuple(dmp_zeros(3, u, K))
- elif zero_f:
- return (dmp_ground_monic(g, u, K),
- dmp_zero(u),
- dmp_ground(dmp_ground_LC(g, u, K), u))
- elif zero_g:
- return (dmp_ground_monic(f, u, K),
- dmp_ground(dmp_ground_LC(f, u, K), u),
- dmp_zero(u))
- elif query('USE_SIMPLIFY_GCD'):
- return _dmp_simplify_gcd(f, g, u, K)
- else:
- return None
- def _dmp_simplify_gcd(f, g, u, K):
- """Try to eliminate `x_0` from GCD computation in `K[X]`. """
- df = dmp_degree(f, u)
- dg = dmp_degree(g, u)
- if df > 0 and dg > 0:
- return None
- if not (df or dg):
- F = dmp_LC(f, K)
- G = dmp_LC(g, K)
- else:
- if not df:
- F = dmp_LC(f, K)
- G = dmp_content(g, u, K)
- else:
- F = dmp_content(f, u, K)
- G = dmp_LC(g, K)
- v = u - 1
- h = dmp_gcd(F, G, v, K)
- cff = [ dmp_quo(cf, h, v, K) for cf in f ]
- cfg = [ dmp_quo(cg, h, v, K) for cg in g ]
- return [h], cff, cfg
- def dup_rr_prs_gcd(f, g, K):
- """
- Computes polynomial GCD using subresultants over a ring.
- Returns ``(h, cff, cfg)`` such that ``a = gcd(f, g)``, ``cff = quo(f, h)``,
- and ``cfg = quo(g, h)``.
- Examples
- ========
- >>> from sympy.polys import ring, ZZ
- >>> R, x = ring("x", ZZ)
- >>> R.dup_rr_prs_gcd(x**2 - 1, x**2 - 3*x + 2)
- (x - 1, x + 1, x - 2)
- """
- result = _dup_rr_trivial_gcd(f, g, K)
- if result is not None:
- return result
- fc, F = dup_primitive(f, K)
- gc, G = dup_primitive(g, K)
- c = K.gcd(fc, gc)
- h = dup_subresultants(F, G, K)[-1]
- _, h = dup_primitive(h, K)
- c *= K.canonical_unit(dup_LC(h, K))
- h = dup_mul_ground(h, c, K)
- cff = dup_quo(f, h, K)
- cfg = dup_quo(g, h, K)
- return h, cff, cfg
- def dup_ff_prs_gcd(f, g, K):
- """
- Computes polynomial GCD using subresultants over a field.
- Returns ``(h, cff, cfg)`` such that ``a = gcd(f, g)``, ``cff = quo(f, h)``,
- and ``cfg = quo(g, h)``.
- Examples
- ========
- >>> from sympy.polys import ring, QQ
- >>> R, x = ring("x", QQ)
- >>> R.dup_ff_prs_gcd(x**2 - 1, x**2 - 3*x + 2)
- (x - 1, x + 1, x - 2)
- """
- result = _dup_ff_trivial_gcd(f, g, K)
- if result is not None:
- return result
- h = dup_subresultants(f, g, K)[-1]
- h = dup_monic(h, K)
- cff = dup_quo(f, h, K)
- cfg = dup_quo(g, h, K)
- return h, cff, cfg
- def dmp_rr_prs_gcd(f, g, u, K):
- """
- Computes polynomial GCD using subresultants over a ring.
- Returns ``(h, cff, cfg)`` such that ``a = gcd(f, g)``, ``cff = quo(f, h)``,
- and ``cfg = quo(g, h)``.
- Examples
- ========
- >>> from sympy.polys import ring, ZZ
- >>> R, x,y, = ring("x,y", ZZ)
- >>> f = x**2 + 2*x*y + y**2
- >>> g = x**2 + x*y
- >>> R.dmp_rr_prs_gcd(f, g)
- (x + y, x + y, x)
- """
- if not u:
- return dup_rr_prs_gcd(f, g, K)
- result = _dmp_rr_trivial_gcd(f, g, u, K)
- if result is not None:
- return result
- fc, F = dmp_primitive(f, u, K)
- gc, G = dmp_primitive(g, u, K)
- h = dmp_subresultants(F, G, u, K)[-1]
- c, _, _ = dmp_rr_prs_gcd(fc, gc, u - 1, K)
- if K.is_negative(dmp_ground_LC(h, u, K)):
- h = dmp_neg(h, u, K)
- _, h = dmp_primitive(h, u, K)
- h = dmp_mul_term(h, c, 0, u, K)
- cff = dmp_quo(f, h, u, K)
- cfg = dmp_quo(g, h, u, K)
- return h, cff, cfg
- def dmp_ff_prs_gcd(f, g, u, K):
- """
- Computes polynomial GCD using subresultants over a field.
- Returns ``(h, cff, cfg)`` such that ``a = gcd(f, g)``, ``cff = quo(f, h)``,
- and ``cfg = quo(g, h)``.
- Examples
- ========
- >>> from sympy.polys import ring, QQ
- >>> R, x,y, = ring("x,y", QQ)
- >>> f = QQ(1,2)*x**2 + x*y + QQ(1,2)*y**2
- >>> g = x**2 + x*y
- >>> R.dmp_ff_prs_gcd(f, g)
- (x + y, 1/2*x + 1/2*y, x)
- """
- if not u:
- return dup_ff_prs_gcd(f, g, K)
- result = _dmp_ff_trivial_gcd(f, g, u, K)
- if result is not None:
- return result
- fc, F = dmp_primitive(f, u, K)
- gc, G = dmp_primitive(g, u, K)
- h = dmp_subresultants(F, G, u, K)[-1]
- c, _, _ = dmp_ff_prs_gcd(fc, gc, u - 1, K)
- _, h = dmp_primitive(h, u, K)
- h = dmp_mul_term(h, c, 0, u, K)
- h = dmp_ground_monic(h, u, K)
- cff = dmp_quo(f, h, u, K)
- cfg = dmp_quo(g, h, u, K)
- return h, cff, cfg
- HEU_GCD_MAX = 6
- def _dup_zz_gcd_interpolate(h, x, K):
- """Interpolate polynomial GCD from integer GCD. """
- f = []
- while h:
- g = h % x
- if g > x // 2:
- g -= x
- f.insert(0, g)
- h = (h - g) // x
- return f
- def dup_zz_heu_gcd(f, g, K):
- """
- Heuristic polynomial GCD in `Z[x]`.
- Given univariate polynomials `f` and `g` in `Z[x]`, returns
- their GCD and cofactors, i.e. polynomials ``h``, ``cff`` and ``cfg``
- such that::
- h = gcd(f, g), cff = quo(f, h) and cfg = quo(g, h)
- The algorithm is purely heuristic which means it may fail to compute
- the GCD. This will be signaled by raising an exception. In this case
- you will need to switch to another GCD method.
- The algorithm computes the polynomial GCD by evaluating polynomials
- f and g at certain points and computing (fast) integer GCD of those
- evaluations. The polynomial GCD is recovered from the integer image
- by interpolation. The final step is to verify if the result is the
- correct GCD. This gives cofactors as a side effect.
- Examples
- ========
- >>> from sympy.polys import ring, ZZ
- >>> R, x = ring("x", ZZ)
- >>> R.dup_zz_heu_gcd(x**2 - 1, x**2 - 3*x + 2)
- (x - 1, x + 1, x - 2)
- References
- ==========
- .. [1] [Liao95]_
- """
- result = _dup_rr_trivial_gcd(f, g, K)
- if result is not None:
- return result
- df = dup_degree(f)
- dg = dup_degree(g)
- gcd, f, g = dup_extract(f, g, K)
- if df == 0 or dg == 0:
- return [gcd], f, g
- f_norm = dup_max_norm(f, K)
- g_norm = dup_max_norm(g, K)
- B = K(2*min(f_norm, g_norm) + 29)
- x = max(min(B, 99*K.sqrt(B)),
- 2*min(f_norm // abs(dup_LC(f, K)),
- g_norm // abs(dup_LC(g, K))) + 2)
- for i in range(0, HEU_GCD_MAX):
- ff = dup_eval(f, x, K)
- gg = dup_eval(g, x, K)
- if ff and gg:
- h = K.gcd(ff, gg)
- cff = ff // h
- cfg = gg // h
- h = _dup_zz_gcd_interpolate(h, x, K)
- h = dup_primitive(h, K)[1]
- cff_, r = dup_div(f, h, K)
- if not r:
- cfg_, r = dup_div(g, h, K)
- if not r:
- h = dup_mul_ground(h, gcd, K)
- return h, cff_, cfg_
- cff = _dup_zz_gcd_interpolate(cff, x, K)
- h, r = dup_div(f, cff, K)
- if not r:
- cfg_, r = dup_div(g, h, K)
- if not r:
- h = dup_mul_ground(h, gcd, K)
- return h, cff, cfg_
- cfg = _dup_zz_gcd_interpolate(cfg, x, K)
- h, r = dup_div(g, cfg, K)
- if not r:
- cff_, r = dup_div(f, h, K)
- if not r:
- h = dup_mul_ground(h, gcd, K)
- return h, cff_, cfg
- x = 73794*x * K.sqrt(K.sqrt(x)) // 27011
- raise HeuristicGCDFailed('no luck')
- def _dmp_zz_gcd_interpolate(h, x, v, K):
- """Interpolate polynomial GCD from integer GCD. """
- f = []
- while not dmp_zero_p(h, v):
- g = dmp_ground_trunc(h, x, v, K)
- f.insert(0, g)
- h = dmp_sub(h, g, v, K)
- h = dmp_quo_ground(h, x, v, K)
- if K.is_negative(dmp_ground_LC(f, v + 1, K)):
- return dmp_neg(f, v + 1, K)
- else:
- return f
- def dmp_zz_heu_gcd(f, g, u, K):
- """
- Heuristic polynomial GCD in `Z[X]`.
- Given univariate polynomials `f` and `g` in `Z[X]`, returns
- their GCD and cofactors, i.e. polynomials ``h``, ``cff`` and ``cfg``
- such that::
- h = gcd(f, g), cff = quo(f, h) and cfg = quo(g, h)
- The algorithm is purely heuristic which means it may fail to compute
- the GCD. This will be signaled by raising an exception. In this case
- you will need to switch to another GCD method.
- The algorithm computes the polynomial GCD by evaluating polynomials
- f and g at certain points and computing (fast) integer GCD of those
- evaluations. The polynomial GCD is recovered from the integer image
- by interpolation. The evaluation process reduces f and g variable by
- variable into a large integer. The final step is to verify if the
- interpolated polynomial is the correct GCD. This gives cofactors of
- the input polynomials as a side effect.
- Examples
- ========
- >>> from sympy.polys import ring, ZZ
- >>> R, x,y, = ring("x,y", ZZ)
- >>> f = x**2 + 2*x*y + y**2
- >>> g = x**2 + x*y
- >>> R.dmp_zz_heu_gcd(f, g)
- (x + y, x + y, x)
- References
- ==========
- .. [1] [Liao95]_
- """
- if not u:
- return dup_zz_heu_gcd(f, g, K)
- result = _dmp_rr_trivial_gcd(f, g, u, K)
- if result is not None:
- return result
- gcd, f, g = dmp_ground_extract(f, g, u, K)
- f_norm = dmp_max_norm(f, u, K)
- g_norm = dmp_max_norm(g, u, K)
- B = K(2*min(f_norm, g_norm) + 29)
- x = max(min(B, 99*K.sqrt(B)),
- 2*min(f_norm // abs(dmp_ground_LC(f, u, K)),
- g_norm // abs(dmp_ground_LC(g, u, K))) + 2)
- for i in range(0, HEU_GCD_MAX):
- ff = dmp_eval(f, x, u, K)
- gg = dmp_eval(g, x, u, K)
- v = u - 1
- if not (dmp_zero_p(ff, v) or dmp_zero_p(gg, v)):
- h, cff, cfg = dmp_zz_heu_gcd(ff, gg, v, K)
- h = _dmp_zz_gcd_interpolate(h, x, v, K)
- h = dmp_ground_primitive(h, u, K)[1]
- cff_, r = dmp_div(f, h, u, K)
- if dmp_zero_p(r, u):
- cfg_, r = dmp_div(g, h, u, K)
- if dmp_zero_p(r, u):
- h = dmp_mul_ground(h, gcd, u, K)
- return h, cff_, cfg_
- cff = _dmp_zz_gcd_interpolate(cff, x, v, K)
- h, r = dmp_div(f, cff, u, K)
- if dmp_zero_p(r, u):
- cfg_, r = dmp_div(g, h, u, K)
- if dmp_zero_p(r, u):
- h = dmp_mul_ground(h, gcd, u, K)
- return h, cff, cfg_
- cfg = _dmp_zz_gcd_interpolate(cfg, x, v, K)
- h, r = dmp_div(g, cfg, u, K)
- if dmp_zero_p(r, u):
- cff_, r = dmp_div(f, h, u, K)
- if dmp_zero_p(r, u):
- h = dmp_mul_ground(h, gcd, u, K)
- return h, cff_, cfg
- x = 73794*x * K.sqrt(K.sqrt(x)) // 27011
- raise HeuristicGCDFailed('no luck')
- def dup_qq_heu_gcd(f, g, K0):
- """
- Heuristic polynomial GCD in `Q[x]`.
- Returns ``(h, cff, cfg)`` such that ``a = gcd(f, g)``,
- ``cff = quo(f, h)``, and ``cfg = quo(g, h)``.
- Examples
- ========
- >>> from sympy.polys import ring, QQ
- >>> R, x = ring("x", QQ)
- >>> f = QQ(1,2)*x**2 + QQ(7,4)*x + QQ(3,2)
- >>> g = QQ(1,2)*x**2 + x
- >>> R.dup_qq_heu_gcd(f, g)
- (x + 2, 1/2*x + 3/4, 1/2*x)
- """
- result = _dup_ff_trivial_gcd(f, g, K0)
- if result is not None:
- return result
- K1 = K0.get_ring()
- cf, f = dup_clear_denoms(f, K0, K1)
- cg, g = dup_clear_denoms(g, K0, K1)
- f = dup_convert(f, K0, K1)
- g = dup_convert(g, K0, K1)
- h, cff, cfg = dup_zz_heu_gcd(f, g, K1)
- h = dup_convert(h, K1, K0)
- c = dup_LC(h, K0)
- h = dup_monic(h, K0)
- cff = dup_convert(cff, K1, K0)
- cfg = dup_convert(cfg, K1, K0)
- cff = dup_mul_ground(cff, K0.quo(c, cf), K0)
- cfg = dup_mul_ground(cfg, K0.quo(c, cg), K0)
- return h, cff, cfg
- def dmp_qq_heu_gcd(f, g, u, K0):
- """
- Heuristic polynomial GCD in `Q[X]`.
- Returns ``(h, cff, cfg)`` such that ``a = gcd(f, g)``,
- ``cff = quo(f, h)``, and ``cfg = quo(g, h)``.
- Examples
- ========
- >>> from sympy.polys import ring, QQ
- >>> R, x,y, = ring("x,y", QQ)
- >>> f = QQ(1,4)*x**2 + x*y + y**2
- >>> g = QQ(1,2)*x**2 + x*y
- >>> R.dmp_qq_heu_gcd(f, g)
- (x + 2*y, 1/4*x + 1/2*y, 1/2*x)
- """
- result = _dmp_ff_trivial_gcd(f, g, u, K0)
- if result is not None:
- return result
- K1 = K0.get_ring()
- cf, f = dmp_clear_denoms(f, u, K0, K1)
- cg, g = dmp_clear_denoms(g, u, K0, K1)
- f = dmp_convert(f, u, K0, K1)
- g = dmp_convert(g, u, K0, K1)
- h, cff, cfg = dmp_zz_heu_gcd(f, g, u, K1)
- h = dmp_convert(h, u, K1, K0)
- c = dmp_ground_LC(h, u, K0)
- h = dmp_ground_monic(h, u, K0)
- cff = dmp_convert(cff, u, K1, K0)
- cfg = dmp_convert(cfg, u, K1, K0)
- cff = dmp_mul_ground(cff, K0.quo(c, cf), u, K0)
- cfg = dmp_mul_ground(cfg, K0.quo(c, cg), u, K0)
- return h, cff, cfg
- def dup_inner_gcd(f, g, K):
- """
- Computes polynomial GCD and cofactors of `f` and `g` in `K[x]`.
- Returns ``(h, cff, cfg)`` such that ``a = gcd(f, g)``,
- ``cff = quo(f, h)``, and ``cfg = quo(g, h)``.
- Examples
- ========
- >>> from sympy.polys import ring, ZZ
- >>> R, x = ring("x", ZZ)
- >>> R.dup_inner_gcd(x**2 - 1, x**2 - 3*x + 2)
- (x - 1, x + 1, x - 2)
- """
- if not K.is_Exact:
- try:
- exact = K.get_exact()
- except DomainError:
- return [K.one], f, g
- f = dup_convert(f, K, exact)
- g = dup_convert(g, K, exact)
- h, cff, cfg = dup_inner_gcd(f, g, exact)
- h = dup_convert(h, exact, K)
- cff = dup_convert(cff, exact, K)
- cfg = dup_convert(cfg, exact, K)
- return h, cff, cfg
- elif K.is_Field:
- if K.is_QQ and query('USE_HEU_GCD'):
- try:
- return dup_qq_heu_gcd(f, g, K)
- except HeuristicGCDFailed:
- pass
- return dup_ff_prs_gcd(f, g, K)
- else:
- if K.is_ZZ and query('USE_HEU_GCD'):
- try:
- return dup_zz_heu_gcd(f, g, K)
- except HeuristicGCDFailed:
- pass
- return dup_rr_prs_gcd(f, g, K)
- def _dmp_inner_gcd(f, g, u, K):
- """Helper function for `dmp_inner_gcd()`. """
- if not K.is_Exact:
- try:
- exact = K.get_exact()
- except DomainError:
- return dmp_one(u, K), f, g
- f = dmp_convert(f, u, K, exact)
- g = dmp_convert(g, u, K, exact)
- h, cff, cfg = _dmp_inner_gcd(f, g, u, exact)
- h = dmp_convert(h, u, exact, K)
- cff = dmp_convert(cff, u, exact, K)
- cfg = dmp_convert(cfg, u, exact, K)
- return h, cff, cfg
- elif K.is_Field:
- if K.is_QQ and query('USE_HEU_GCD'):
- try:
- return dmp_qq_heu_gcd(f, g, u, K)
- except HeuristicGCDFailed:
- pass
- return dmp_ff_prs_gcd(f, g, u, K)
- else:
- if K.is_ZZ and query('USE_HEU_GCD'):
- try:
- return dmp_zz_heu_gcd(f, g, u, K)
- except HeuristicGCDFailed:
- pass
- return dmp_rr_prs_gcd(f, g, u, K)
- def dmp_inner_gcd(f, g, u, K):
- """
- Computes polynomial GCD and cofactors of `f` and `g` in `K[X]`.
- Returns ``(h, cff, cfg)`` such that ``a = gcd(f, g)``,
- ``cff = quo(f, h)``, and ``cfg = quo(g, h)``.
- Examples
- ========
- >>> from sympy.polys import ring, ZZ
- >>> R, x,y, = ring("x,y", ZZ)
- >>> f = x**2 + 2*x*y + y**2
- >>> g = x**2 + x*y
- >>> R.dmp_inner_gcd(f, g)
- (x + y, x + y, x)
- """
- if not u:
- return dup_inner_gcd(f, g, K)
- J, (f, g) = dmp_multi_deflate((f, g), u, K)
- h, cff, cfg = _dmp_inner_gcd(f, g, u, K)
- return (dmp_inflate(h, J, u, K),
- dmp_inflate(cff, J, u, K),
- dmp_inflate(cfg, J, u, K))
- def dup_gcd(f, g, K):
- """
- Computes polynomial GCD of `f` and `g` in `K[x]`.
- Examples
- ========
- >>> from sympy.polys import ring, ZZ
- >>> R, x = ring("x", ZZ)
- >>> R.dup_gcd(x**2 - 1, x**2 - 3*x + 2)
- x - 1
- """
- return dup_inner_gcd(f, g, K)[0]
- def dmp_gcd(f, g, u, K):
- """
- Computes polynomial GCD of `f` and `g` in `K[X]`.
- Examples
- ========
- >>> from sympy.polys import ring, ZZ
- >>> R, x,y, = ring("x,y", ZZ)
- >>> f = x**2 + 2*x*y + y**2
- >>> g = x**2 + x*y
- >>> R.dmp_gcd(f, g)
- x + y
- """
- return dmp_inner_gcd(f, g, u, K)[0]
- def dup_rr_lcm(f, g, K):
- """
- Computes polynomial LCM over a ring in `K[x]`.
- Examples
- ========
- >>> from sympy.polys import ring, ZZ
- >>> R, x = ring("x", ZZ)
- >>> R.dup_rr_lcm(x**2 - 1, x**2 - 3*x + 2)
- x**3 - 2*x**2 - x + 2
- """
- fc, f = dup_primitive(f, K)
- gc, g = dup_primitive(g, K)
- c = K.lcm(fc, gc)
- h = dup_quo(dup_mul(f, g, K),
- dup_gcd(f, g, K), K)
- return dup_mul_ground(h, c, K)
- def dup_ff_lcm(f, g, K):
- """
- Computes polynomial LCM over a field in `K[x]`.
- Examples
- ========
- >>> from sympy.polys import ring, QQ
- >>> R, x = ring("x", QQ)
- >>> f = QQ(1,2)*x**2 + QQ(7,4)*x + QQ(3,2)
- >>> g = QQ(1,2)*x**2 + x
- >>> R.dup_ff_lcm(f, g)
- x**3 + 7/2*x**2 + 3*x
- """
- h = dup_quo(dup_mul(f, g, K),
- dup_gcd(f, g, K), K)
- return dup_monic(h, K)
- def dup_lcm(f, g, K):
- """
- Computes polynomial LCM of `f` and `g` in `K[x]`.
- Examples
- ========
- >>> from sympy.polys import ring, ZZ
- >>> R, x = ring("x", ZZ)
- >>> R.dup_lcm(x**2 - 1, x**2 - 3*x + 2)
- x**3 - 2*x**2 - x + 2
- """
- if K.is_Field:
- return dup_ff_lcm(f, g, K)
- else:
- return dup_rr_lcm(f, g, K)
- def dmp_rr_lcm(f, g, u, K):
- """
- Computes polynomial LCM over a ring in `K[X]`.
- Examples
- ========
- >>> from sympy.polys import ring, ZZ
- >>> R, x,y, = ring("x,y", ZZ)
- >>> f = x**2 + 2*x*y + y**2
- >>> g = x**2 + x*y
- >>> R.dmp_rr_lcm(f, g)
- x**3 + 2*x**2*y + x*y**2
- """
- fc, f = dmp_ground_primitive(f, u, K)
- gc, g = dmp_ground_primitive(g, u, K)
- c = K.lcm(fc, gc)
- h = dmp_quo(dmp_mul(f, g, u, K),
- dmp_gcd(f, g, u, K), u, K)
- return dmp_mul_ground(h, c, u, K)
- def dmp_ff_lcm(f, g, u, K):
- """
- Computes polynomial LCM over a field in `K[X]`.
- Examples
- ========
- >>> from sympy.polys import ring, QQ
- >>> R, x,y, = ring("x,y", QQ)
- >>> f = QQ(1,4)*x**2 + x*y + y**2
- >>> g = QQ(1,2)*x**2 + x*y
- >>> R.dmp_ff_lcm(f, g)
- x**3 + 4*x**2*y + 4*x*y**2
- """
- h = dmp_quo(dmp_mul(f, g, u, K),
- dmp_gcd(f, g, u, K), u, K)
- return dmp_ground_monic(h, u, K)
- def dmp_lcm(f, g, u, K):
- """
- Computes polynomial LCM of `f` and `g` in `K[X]`.
- Examples
- ========
- >>> from sympy.polys import ring, ZZ
- >>> R, x,y, = ring("x,y", ZZ)
- >>> f = x**2 + 2*x*y + y**2
- >>> g = x**2 + x*y
- >>> R.dmp_lcm(f, g)
- x**3 + 2*x**2*y + x*y**2
- """
- if not u:
- return dup_lcm(f, g, K)
- if K.is_Field:
- return dmp_ff_lcm(f, g, u, K)
- else:
- return dmp_rr_lcm(f, g, u, K)
- def dmp_content(f, u, K):
- """
- Returns GCD of multivariate coefficients.
- Examples
- ========
- >>> from sympy.polys import ring, ZZ
- >>> R, x,y, = ring("x,y", ZZ)
- >>> R.dmp_content(2*x*y + 6*x + 4*y + 12)
- 2*y + 6
- """
- cont, v = dmp_LC(f, K), u - 1
- if dmp_zero_p(f, u):
- return cont
- for c in f[1:]:
- cont = dmp_gcd(cont, c, v, K)
- if dmp_one_p(cont, v, K):
- break
- if K.is_negative(dmp_ground_LC(cont, v, K)):
- return dmp_neg(cont, v, K)
- else:
- return cont
- def dmp_primitive(f, u, K):
- """
- Returns multivariate content and a primitive polynomial.
- Examples
- ========
- >>> from sympy.polys import ring, ZZ
- >>> R, x,y, = ring("x,y", ZZ)
- >>> R.dmp_primitive(2*x*y + 6*x + 4*y + 12)
- (2*y + 6, x + 2)
- """
- cont, v = dmp_content(f, u, K), u - 1
- if dmp_zero_p(f, u) or dmp_one_p(cont, v, K):
- return cont, f
- else:
- return cont, [ dmp_quo(c, cont, v, K) for c in f ]
- def dup_cancel(f, g, K, include=True):
- """
- Cancel common factors in a rational function `f/g`.
- Examples
- ========
- >>> from sympy.polys import ring, ZZ
- >>> R, x = ring("x", ZZ)
- >>> R.dup_cancel(2*x**2 - 2, x**2 - 2*x + 1)
- (2*x + 2, x - 1)
- """
- return dmp_cancel(f, g, 0, K, include=include)
- def dmp_cancel(f, g, u, K, include=True):
- """
- Cancel common factors in a rational function `f/g`.
- Examples
- ========
- >>> from sympy.polys import ring, ZZ
- >>> R, x,y = ring("x,y", ZZ)
- >>> R.dmp_cancel(2*x**2 - 2, x**2 - 2*x + 1)
- (2*x + 2, x - 1)
- """
- K0 = None
- if K.is_Field and K.has_assoc_Ring:
- K0, K = K, K.get_ring()
- cq, f = dmp_clear_denoms(f, u, K0, K, convert=True)
- cp, g = dmp_clear_denoms(g, u, K0, K, convert=True)
- else:
- cp, cq = K.one, K.one
- _, p, q = dmp_inner_gcd(f, g, u, K)
- if K0 is not None:
- _, cp, cq = K.cofactors(cp, cq)
- p = dmp_convert(p, u, K, K0)
- q = dmp_convert(q, u, K, K0)
- K = K0
- p_neg = K.is_negative(dmp_ground_LC(p, u, K))
- q_neg = K.is_negative(dmp_ground_LC(q, u, K))
- if p_neg and q_neg:
- p, q = dmp_neg(p, u, K), dmp_neg(q, u, K)
- elif p_neg:
- cp, p = -cp, dmp_neg(p, u, K)
- elif q_neg:
- cp, q = -cp, dmp_neg(q, u, K)
- if not include:
- return cp, cq, p, q
- p = dmp_mul_ground(p, cp, u, K)
- q = dmp_mul_ground(q, cq, u, K)
- return p, q
|