123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893 |
- """Euclidean algorithms, GCDs, LCMs and polynomial remainder sequences. """
- 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
- from sympy.ntheory import nextprime
- 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
|