123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875 |
- """Arithmetics for dense recursive polynomials in ``K[x]`` or ``K[X]``. """
- from sympy.polys.densebasic import (
- dup_slice,
- dup_LC, dmp_LC,
- dup_degree, dmp_degree,
- dup_strip, dmp_strip,
- dmp_zero_p, dmp_zero,
- dmp_one_p, dmp_one,
- dmp_ground, dmp_zeros)
- from sympy.polys.polyerrors import (ExactQuotientFailed, PolynomialDivisionFailed)
- def dup_add_term(f, c, i, K):
- """
- Add ``c*x**i`` to ``f`` in ``K[x]``.
- Examples
- ========
- >>> from sympy.polys import ring, ZZ
- >>> R, x = ring("x", ZZ)
- >>> R.dup_add_term(x**2 - 1, ZZ(2), 4)
- 2*x**4 + x**2 - 1
- """
- if not c:
- return f
- n = len(f)
- m = n - i - 1
- if i == n - 1:
- return dup_strip([f[0] + c] + f[1:])
- else:
- if i >= n:
- return [c] + [K.zero]*(i - n) + f
- else:
- return f[:m] + [f[m] + c] + f[m + 1:]
- def dmp_add_term(f, c, i, u, K):
- """
- Add ``c(x_2..x_u)*x_0**i`` to ``f`` in ``K[X]``.
- Examples
- ========
- >>> from sympy.polys import ring, ZZ
- >>> R, x,y = ring("x,y", ZZ)
- >>> R.dmp_add_term(x*y + 1, 2, 2)
- 2*x**2 + x*y + 1
- """
- if not u:
- return dup_add_term(f, c, i, K)
- v = u - 1
- if dmp_zero_p(c, v):
- return f
- n = len(f)
- m = n - i - 1
- if i == n - 1:
- return dmp_strip([dmp_add(f[0], c, v, K)] + f[1:], u)
- else:
- if i >= n:
- return [c] + dmp_zeros(i - n, v, K) + f
- else:
- return f[:m] + [dmp_add(f[m], c, v, K)] + f[m + 1:]
- def dup_sub_term(f, c, i, K):
- """
- Subtract ``c*x**i`` from ``f`` in ``K[x]``.
- Examples
- ========
- >>> from sympy.polys import ring, ZZ
- >>> R, x = ring("x", ZZ)
- >>> R.dup_sub_term(2*x**4 + x**2 - 1, ZZ(2), 4)
- x**2 - 1
- """
- if not c:
- return f
- n = len(f)
- m = n - i - 1
- if i == n - 1:
- return dup_strip([f[0] - c] + f[1:])
- else:
- if i >= n:
- return [-c] + [K.zero]*(i - n) + f
- else:
- return f[:m] + [f[m] - c] + f[m + 1:]
- def dmp_sub_term(f, c, i, u, K):
- """
- Subtract ``c(x_2..x_u)*x_0**i`` from ``f`` in ``K[X]``.
- Examples
- ========
- >>> from sympy.polys import ring, ZZ
- >>> R, x,y = ring("x,y", ZZ)
- >>> R.dmp_sub_term(2*x**2 + x*y + 1, 2, 2)
- x*y + 1
- """
- if not u:
- return dup_add_term(f, -c, i, K)
- v = u - 1
- if dmp_zero_p(c, v):
- return f
- n = len(f)
- m = n - i - 1
- if i == n - 1:
- return dmp_strip([dmp_sub(f[0], c, v, K)] + f[1:], u)
- else:
- if i >= n:
- return [dmp_neg(c, v, K)] + dmp_zeros(i - n, v, K) + f
- else:
- return f[:m] + [dmp_sub(f[m], c, v, K)] + f[m + 1:]
- def dup_mul_term(f, c, i, K):
- """
- Multiply ``f`` by ``c*x**i`` in ``K[x]``.
- Examples
- ========
- >>> from sympy.polys import ring, ZZ
- >>> R, x = ring("x", ZZ)
- >>> R.dup_mul_term(x**2 - 1, ZZ(3), 2)
- 3*x**4 - 3*x**2
- """
- if not c or not f:
- return []
- else:
- return [ cf * c for cf in f ] + [K.zero]*i
- def dmp_mul_term(f, c, i, u, K):
- """
- Multiply ``f`` by ``c(x_2..x_u)*x_0**i`` in ``K[X]``.
- Examples
- ========
- >>> from sympy.polys import ring, ZZ
- >>> R, x,y = ring("x,y", ZZ)
- >>> R.dmp_mul_term(x**2*y + x, 3*y, 2)
- 3*x**4*y**2 + 3*x**3*y
- """
- if not u:
- return dup_mul_term(f, c, i, K)
- v = u - 1
- if dmp_zero_p(f, u):
- return f
- if dmp_zero_p(c, v):
- return dmp_zero(u)
- else:
- return [ dmp_mul(cf, c, v, K) for cf in f ] + dmp_zeros(i, v, K)
- def dup_add_ground(f, c, K):
- """
- Add an element of the ground domain to ``f``.
- Examples
- ========
- >>> from sympy.polys import ring, ZZ
- >>> R, x = ring("x", ZZ)
- >>> R.dup_add_ground(x**3 + 2*x**2 + 3*x + 4, ZZ(4))
- x**3 + 2*x**2 + 3*x + 8
- """
- return dup_add_term(f, c, 0, K)
- def dmp_add_ground(f, c, u, K):
- """
- Add an element of the ground domain to ``f``.
- Examples
- ========
- >>> from sympy.polys import ring, ZZ
- >>> R, x,y = ring("x,y", ZZ)
- >>> R.dmp_add_ground(x**3 + 2*x**2 + 3*x + 4, ZZ(4))
- x**3 + 2*x**2 + 3*x + 8
- """
- return dmp_add_term(f, dmp_ground(c, u - 1), 0, u, K)
- def dup_sub_ground(f, c, K):
- """
- Subtract an element of the ground domain from ``f``.
- Examples
- ========
- >>> from sympy.polys import ring, ZZ
- >>> R, x = ring("x", ZZ)
- >>> R.dup_sub_ground(x**3 + 2*x**2 + 3*x + 4, ZZ(4))
- x**3 + 2*x**2 + 3*x
- """
- return dup_sub_term(f, c, 0, K)
- def dmp_sub_ground(f, c, u, K):
- """
- Subtract an element of the ground domain from ``f``.
- Examples
- ========
- >>> from sympy.polys import ring, ZZ
- >>> R, x,y = ring("x,y", ZZ)
- >>> R.dmp_sub_ground(x**3 + 2*x**2 + 3*x + 4, ZZ(4))
- x**3 + 2*x**2 + 3*x
- """
- return dmp_sub_term(f, dmp_ground(c, u - 1), 0, u, K)
- def dup_mul_ground(f, c, K):
- """
- Multiply ``f`` by a constant value in ``K[x]``.
- Examples
- ========
- >>> from sympy.polys import ring, ZZ
- >>> R, x = ring("x", ZZ)
- >>> R.dup_mul_ground(x**2 + 2*x - 1, ZZ(3))
- 3*x**2 + 6*x - 3
- """
- if not c or not f:
- return []
- else:
- return [ cf * c for cf in f ]
- def dmp_mul_ground(f, c, u, K):
- """
- Multiply ``f`` by a constant value in ``K[X]``.
- Examples
- ========
- >>> from sympy.polys import ring, ZZ
- >>> R, x,y = ring("x,y", ZZ)
- >>> R.dmp_mul_ground(2*x + 2*y, ZZ(3))
- 6*x + 6*y
- """
- if not u:
- return dup_mul_ground(f, c, K)
- v = u - 1
- return [ dmp_mul_ground(cf, c, v, K) for cf in f ]
- def dup_quo_ground(f, c, K):
- """
- Quotient by a constant in ``K[x]``.
- Examples
- ========
- >>> from sympy.polys import ring, ZZ, QQ
- >>> R, x = ring("x", ZZ)
- >>> R.dup_quo_ground(3*x**2 + 2, ZZ(2))
- x**2 + 1
- >>> R, x = ring("x", QQ)
- >>> R.dup_quo_ground(3*x**2 + 2, QQ(2))
- 3/2*x**2 + 1
- """
- if not c:
- raise ZeroDivisionError('polynomial division')
- if not f:
- return f
- if K.is_Field:
- return [ K.quo(cf, c) for cf in f ]
- else:
- return [ cf // c for cf in f ]
- def dmp_quo_ground(f, c, u, K):
- """
- Quotient by a constant in ``K[X]``.
- Examples
- ========
- >>> from sympy.polys import ring, ZZ, QQ
- >>> R, x,y = ring("x,y", ZZ)
- >>> R.dmp_quo_ground(2*x**2*y + 3*x, ZZ(2))
- x**2*y + x
- >>> R, x,y = ring("x,y", QQ)
- >>> R.dmp_quo_ground(2*x**2*y + 3*x, QQ(2))
- x**2*y + 3/2*x
- """
- if not u:
- return dup_quo_ground(f, c, K)
- v = u - 1
- return [ dmp_quo_ground(cf, c, v, K) for cf in f ]
- def dup_exquo_ground(f, c, K):
- """
- Exact quotient by a constant in ``K[x]``.
- Examples
- ========
- >>> from sympy.polys import ring, QQ
- >>> R, x = ring("x", QQ)
- >>> R.dup_exquo_ground(x**2 + 2, QQ(2))
- 1/2*x**2 + 1
- """
- if not c:
- raise ZeroDivisionError('polynomial division')
- if not f:
- return f
- return [ K.exquo(cf, c) for cf in f ]
- def dmp_exquo_ground(f, c, u, K):
- """
- Exact quotient by a constant in ``K[X]``.
- Examples
- ========
- >>> from sympy.polys import ring, QQ
- >>> R, x,y = ring("x,y", QQ)
- >>> R.dmp_exquo_ground(x**2*y + 2*x, QQ(2))
- 1/2*x**2*y + x
- """
- if not u:
- return dup_exquo_ground(f, c, K)
- v = u - 1
- return [ dmp_exquo_ground(cf, c, v, K) for cf in f ]
- def dup_lshift(f, n, K):
- """
- Efficiently multiply ``f`` by ``x**n`` in ``K[x]``.
- Examples
- ========
- >>> from sympy.polys import ring, ZZ
- >>> R, x = ring("x", ZZ)
- >>> R.dup_lshift(x**2 + 1, 2)
- x**4 + x**2
- """
- if not f:
- return f
- else:
- return f + [K.zero]*n
- def dup_rshift(f, n, K):
- """
- Efficiently divide ``f`` by ``x**n`` in ``K[x]``.
- Examples
- ========
- >>> from sympy.polys import ring, ZZ
- >>> R, x = ring("x", ZZ)
- >>> R.dup_rshift(x**4 + x**2, 2)
- x**2 + 1
- >>> R.dup_rshift(x**4 + x**2 + 2, 2)
- x**2 + 1
- """
- return f[:-n]
- def dup_abs(f, K):
- """
- Make all coefficients positive in ``K[x]``.
- Examples
- ========
- >>> from sympy.polys import ring, ZZ
- >>> R, x = ring("x", ZZ)
- >>> R.dup_abs(x**2 - 1)
- x**2 + 1
- """
- return [ K.abs(coeff) for coeff in f ]
- def dmp_abs(f, u, K):
- """
- Make all coefficients positive in ``K[X]``.
- Examples
- ========
- >>> from sympy.polys import ring, ZZ
- >>> R, x,y = ring("x,y", ZZ)
- >>> R.dmp_abs(x**2*y - x)
- x**2*y + x
- """
- if not u:
- return dup_abs(f, K)
- v = u - 1
- return [ dmp_abs(cf, v, K) for cf in f ]
- def dup_neg(f, K):
- """
- Negate a polynomial in ``K[x]``.
- Examples
- ========
- >>> from sympy.polys import ring, ZZ
- >>> R, x = ring("x", ZZ)
- >>> R.dup_neg(x**2 - 1)
- -x**2 + 1
- """
- return [ -coeff for coeff in f ]
- def dmp_neg(f, u, K):
- """
- Negate a polynomial in ``K[X]``.
- Examples
- ========
- >>> from sympy.polys import ring, ZZ
- >>> R, x,y = ring("x,y", ZZ)
- >>> R.dmp_neg(x**2*y - x)
- -x**2*y + x
- """
- if not u:
- return dup_neg(f, K)
- v = u - 1
- return [ dmp_neg(cf, v, K) for cf in f ]
- def dup_add(f, g, K):
- """
- Add dense polynomials in ``K[x]``.
- Examples
- ========
- >>> from sympy.polys import ring, ZZ
- >>> R, x = ring("x", ZZ)
- >>> R.dup_add(x**2 - 1, x - 2)
- x**2 + x - 3
- """
- if not f:
- return g
- if not g:
- return f
- df = dup_degree(f)
- dg = dup_degree(g)
- if df == dg:
- return dup_strip([ a + b for a, b in zip(f, g) ])
- else:
- k = abs(df - dg)
- if df > dg:
- h, f = f[:k], f[k:]
- else:
- h, g = g[:k], g[k:]
- return h + [ a + b for a, b in zip(f, g) ]
- def dmp_add(f, g, u, K):
- """
- Add dense polynomials in ``K[X]``.
- Examples
- ========
- >>> from sympy.polys import ring, ZZ
- >>> R, x,y = ring("x,y", ZZ)
- >>> R.dmp_add(x**2 + y, x**2*y + x)
- x**2*y + x**2 + x + y
- """
- if not u:
- return dup_add(f, g, K)
- df = dmp_degree(f, u)
- if df < 0:
- return g
- dg = dmp_degree(g, u)
- if dg < 0:
- return f
- v = u - 1
- if df == dg:
- return dmp_strip([ dmp_add(a, b, v, K) for a, b in zip(f, g) ], u)
- else:
- k = abs(df - dg)
- if df > dg:
- h, f = f[:k], f[k:]
- else:
- h, g = g[:k], g[k:]
- return h + [ dmp_add(a, b, v, K) for a, b in zip(f, g) ]
- def dup_sub(f, g, K):
- """
- Subtract dense polynomials in ``K[x]``.
- Examples
- ========
- >>> from sympy.polys import ring, ZZ
- >>> R, x = ring("x", ZZ)
- >>> R.dup_sub(x**2 - 1, x - 2)
- x**2 - x + 1
- """
- if not f:
- return dup_neg(g, K)
- if not g:
- return f
- df = dup_degree(f)
- dg = dup_degree(g)
- if df == dg:
- return dup_strip([ a - b for a, b in zip(f, g) ])
- else:
- k = abs(df - dg)
- if df > dg:
- h, f = f[:k], f[k:]
- else:
- h, g = dup_neg(g[:k], K), g[k:]
- return h + [ a - b for a, b in zip(f, g) ]
- def dmp_sub(f, g, u, K):
- """
- Subtract dense polynomials in ``K[X]``.
- Examples
- ========
- >>> from sympy.polys import ring, ZZ
- >>> R, x,y = ring("x,y", ZZ)
- >>> R.dmp_sub(x**2 + y, x**2*y + x)
- -x**2*y + x**2 - x + y
- """
- if not u:
- return dup_sub(f, g, K)
- df = dmp_degree(f, u)
- if df < 0:
- return dmp_neg(g, u, K)
- dg = dmp_degree(g, u)
- if dg < 0:
- return f
- v = u - 1
- if df == dg:
- return dmp_strip([ dmp_sub(a, b, v, K) for a, b in zip(f, g) ], u)
- else:
- k = abs(df - dg)
- if df > dg:
- h, f = f[:k], f[k:]
- else:
- h, g = dmp_neg(g[:k], u, K), g[k:]
- return h + [ dmp_sub(a, b, v, K) for a, b in zip(f, g) ]
- def dup_add_mul(f, g, h, K):
- """
- Returns ``f + g*h`` where ``f, g, h`` are in ``K[x]``.
- Examples
- ========
- >>> from sympy.polys import ring, ZZ
- >>> R, x = ring("x", ZZ)
- >>> R.dup_add_mul(x**2 - 1, x - 2, x + 2)
- 2*x**2 - 5
- """
- return dup_add(f, dup_mul(g, h, K), K)
- def dmp_add_mul(f, g, h, u, K):
- """
- Returns ``f + g*h`` where ``f, g, h`` are in ``K[X]``.
- Examples
- ========
- >>> from sympy.polys import ring, ZZ
- >>> R, x,y = ring("x,y", ZZ)
- >>> R.dmp_add_mul(x**2 + y, x, x + 2)
- 2*x**2 + 2*x + y
- """
- return dmp_add(f, dmp_mul(g, h, u, K), u, K)
- def dup_sub_mul(f, g, h, K):
- """
- Returns ``f - g*h`` where ``f, g, h`` are in ``K[x]``.
- Examples
- ========
- >>> from sympy.polys import ring, ZZ
- >>> R, x = ring("x", ZZ)
- >>> R.dup_sub_mul(x**2 - 1, x - 2, x + 2)
- 3
- """
- return dup_sub(f, dup_mul(g, h, K), K)
- def dmp_sub_mul(f, g, h, u, K):
- """
- Returns ``f - g*h`` where ``f, g, h`` are in ``K[X]``.
- Examples
- ========
- >>> from sympy.polys import ring, ZZ
- >>> R, x,y = ring("x,y", ZZ)
- >>> R.dmp_sub_mul(x**2 + y, x, x + 2)
- -2*x + y
- """
- return dmp_sub(f, dmp_mul(g, h, u, K), u, K)
- def dup_mul(f, g, K):
- """
- Multiply dense polynomials in ``K[x]``.
- Examples
- ========
- >>> from sympy.polys import ring, ZZ
- >>> R, x = ring("x", ZZ)
- >>> R.dup_mul(x - 2, x + 2)
- x**2 - 4
- """
- if f == g:
- return dup_sqr(f, K)
- if not (f and g):
- return []
- df = dup_degree(f)
- dg = dup_degree(g)
- n = max(df, dg) + 1
- if n < 100:
- h = []
- for i in range(0, df + dg + 1):
- coeff = K.zero
- for j in range(max(0, i - dg), min(df, i) + 1):
- coeff += f[j]*g[i - j]
- h.append(coeff)
- return dup_strip(h)
- else:
- # Use Karatsuba's algorithm (divide and conquer), see e.g.:
- # Joris van der Hoeven, Relax But Don't Be Too Lazy,
- # J. Symbolic Computation, 11 (2002), section 3.1.1.
- n2 = n//2
- fl, gl = dup_slice(f, 0, n2, K), dup_slice(g, 0, n2, K)
- fh = dup_rshift(dup_slice(f, n2, n, K), n2, K)
- gh = dup_rshift(dup_slice(g, n2, n, K), n2, K)
- lo, hi = dup_mul(fl, gl, K), dup_mul(fh, gh, K)
- mid = dup_mul(dup_add(fl, fh, K), dup_add(gl, gh, K), K)
- mid = dup_sub(mid, dup_add(lo, hi, K), K)
- return dup_add(dup_add(lo, dup_lshift(mid, n2, K), K),
- dup_lshift(hi, 2*n2, K), K)
- def dmp_mul(f, g, u, K):
- """
- Multiply dense polynomials in ``K[X]``.
- Examples
- ========
- >>> from sympy.polys import ring, ZZ
- >>> R, x,y = ring("x,y", ZZ)
- >>> R.dmp_mul(x*y + 1, x)
- x**2*y + x
- """
- if not u:
- return dup_mul(f, g, K)
- if f == g:
- return dmp_sqr(f, u, K)
- df = dmp_degree(f, u)
- if df < 0:
- return f
- dg = dmp_degree(g, u)
- if dg < 0:
- return g
- h, v = [], u - 1
- for i in range(0, df + dg + 1):
- coeff = dmp_zero(v)
- for j in range(max(0, i - dg), min(df, i) + 1):
- coeff = dmp_add(coeff, dmp_mul(f[j], g[i - j], v, K), v, K)
- h.append(coeff)
- return dmp_strip(h, u)
- def dup_sqr(f, K):
- """
- Square dense polynomials in ``K[x]``.
- Examples
- ========
- >>> from sympy.polys import ring, ZZ
- >>> R, x = ring("x", ZZ)
- >>> R.dup_sqr(x**2 + 1)
- x**4 + 2*x**2 + 1
- """
- df, h = len(f) - 1, []
- for i in range(0, 2*df + 1):
- c = K.zero
- jmin = max(0, i - df)
- jmax = min(i, df)
- n = jmax - jmin + 1
- jmax = jmin + n // 2 - 1
- for j in range(jmin, jmax + 1):
- c += f[j]*f[i - j]
- c += c
- if n & 1:
- elem = f[jmax + 1]
- c += elem**2
- h.append(c)
- return dup_strip(h)
- def dmp_sqr(f, u, K):
- """
- Square dense polynomials in ``K[X]``.
- Examples
- ========
- >>> from sympy.polys import ring, ZZ
- >>> R, x,y = ring("x,y", ZZ)
- >>> R.dmp_sqr(x**2 + x*y + y**2)
- x**4 + 2*x**3*y + 3*x**2*y**2 + 2*x*y**3 + y**4
- """
- if not u:
- return dup_sqr(f, K)
- df = dmp_degree(f, u)
- if df < 0:
- return f
- h, v = [], u - 1
- for i in range(0, 2*df + 1):
- c = dmp_zero(v)
- jmin = max(0, i - df)
- jmax = min(i, df)
- n = jmax - jmin + 1
- jmax = jmin + n // 2 - 1
- for j in range(jmin, jmax + 1):
- c = dmp_add(c, dmp_mul(f[j], f[i - j], v, K), v, K)
- c = dmp_mul_ground(c, K(2), v, K)
- if n & 1:
- elem = dmp_sqr(f[jmax + 1], v, K)
- c = dmp_add(c, elem, v, K)
- h.append(c)
- return dmp_strip(h, u)
- def dup_pow(f, n, K):
- """
- Raise ``f`` to the ``n``-th power in ``K[x]``.
- Examples
- ========
- >>> from sympy.polys import ring, ZZ
- >>> R, x = ring("x", ZZ)
- >>> R.dup_pow(x - 2, 3)
- x**3 - 6*x**2 + 12*x - 8
- """
- if not n:
- return [K.one]
- if n < 0:
- raise ValueError("Cannot raise polynomial to a negative power")
- if n == 1 or not f or f == [K.one]:
- return f
- g = [K.one]
- while True:
- n, m = n//2, n
- if m % 2:
- g = dup_mul(g, f, K)
- if not n:
- break
- f = dup_sqr(f, K)
- return g
- def dmp_pow(f, n, u, K):
- """
- Raise ``f`` to the ``n``-th power in ``K[X]``.
- Examples
- ========
- >>> from sympy.polys import ring, ZZ
- >>> R, x,y = ring("x,y", ZZ)
- >>> R.dmp_pow(x*y + 1, 3)
- x**3*y**3 + 3*x**2*y**2 + 3*x*y + 1
- """
- if not u:
- return dup_pow(f, n, K)
- if not n:
- return dmp_one(u, K)
- if n < 0:
- raise ValueError("Cannot raise polynomial to a negative power")
- if n == 1 or dmp_zero_p(f, u) or dmp_one_p(f, u, K):
- return f
- g = dmp_one(u, K)
- while True:
- n, m = n//2, n
- if m & 1:
- g = dmp_mul(g, f, u, K)
- if not n:
- break
- f = dmp_sqr(f, u, K)
- return g
- def dup_pdiv(f, g, K):
- """
- Polynomial pseudo-division in ``K[x]``.
- Examples
- ========
- >>> from sympy.polys import ring, ZZ
- >>> R, x = ring("x", ZZ)
- >>> R.dup_pdiv(x**2 + 1, 2*x - 4)
- (2*x + 4, 20)
- """
- df = dup_degree(f)
- dg = dup_degree(g)
- q, r, dr = [], f, df
- if not g:
- raise ZeroDivisionError("polynomial division")
- elif df < dg:
- return q, r
- N = df - dg + 1
- lc_g = dup_LC(g, K)
- while True:
- lc_r = dup_LC(r, K)
- j, N = dr - dg, N - 1
- Q = dup_mul_ground(q, lc_g, K)
- q = dup_add_term(Q, lc_r, j, K)
- R = dup_mul_ground(r, lc_g, K)
- G = dup_mul_term(g, lc_r, j, K)
- r = dup_sub(R, G, K)
- _dr, dr = dr, dup_degree(r)
- if dr < dg:
- break
- elif not (dr < _dr):
- raise PolynomialDivisionFailed(f, g, K)
- c = lc_g**N
- q = dup_mul_ground(q, c, K)
- r = dup_mul_ground(r, c, K)
- return q, r
- def dup_prem(f, g, K):
- """
- Polynomial pseudo-remainder in ``K[x]``.
- Examples
- ========
- >>> from sympy.polys import ring, ZZ
- >>> R, x = ring("x", ZZ)
- >>> R.dup_prem(x**2 + 1, 2*x - 4)
- 20
- """
- df = dup_degree(f)
- dg = dup_degree(g)
- r, dr = f, df
- if not g:
- raise ZeroDivisionError("polynomial division")
- elif df < dg:
- return r
- N = df - dg + 1
- lc_g = dup_LC(g, K)
- while True:
- lc_r = dup_LC(r, K)
- j, N = dr - dg, N - 1
- R = dup_mul_ground(r, lc_g, K)
- G = dup_mul_term(g, lc_r, j, K)
- r = dup_sub(R, G, K)
- _dr, dr = dr, dup_degree(r)
- if dr < dg:
- break
- elif not (dr < _dr):
- raise PolynomialDivisionFailed(f, g, K)
- return dup_mul_ground(r, lc_g**N, K)
- def dup_pquo(f, g, K):
- """
- Polynomial exact pseudo-quotient in ``K[X]``.
- Examples
- ========
- >>> from sympy.polys import ring, ZZ
- >>> R, x = ring("x", ZZ)
- >>> R.dup_pquo(x**2 - 1, 2*x - 2)
- 2*x + 2
- >>> R.dup_pquo(x**2 + 1, 2*x - 4)
- 2*x + 4
- """
- return dup_pdiv(f, g, K)[0]
- def dup_pexquo(f, g, K):
- """
- Polynomial pseudo-quotient in ``K[x]``.
- Examples
- ========
- >>> from sympy.polys import ring, ZZ
- >>> R, x = ring("x", ZZ)
- >>> R.dup_pexquo(x**2 - 1, 2*x - 2)
- 2*x + 2
- >>> R.dup_pexquo(x**2 + 1, 2*x - 4)
- Traceback (most recent call last):
- ...
- ExactQuotientFailed: [2, -4] does not divide [1, 0, 1]
- """
- q, r = dup_pdiv(f, g, K)
- if not r:
- return q
- else:
- raise ExactQuotientFailed(f, g)
- def dmp_pdiv(f, g, u, K):
- """
- Polynomial pseudo-division in ``K[X]``.
- Examples
- ========
- >>> from sympy.polys import ring, ZZ
- >>> R, x,y = ring("x,y", ZZ)
- >>> R.dmp_pdiv(x**2 + x*y, 2*x + 2)
- (2*x + 2*y - 2, -4*y + 4)
- """
- if not u:
- return dup_pdiv(f, g, K)
- df = dmp_degree(f, u)
- dg = dmp_degree(g, u)
- if dg < 0:
- raise ZeroDivisionError("polynomial division")
- q, r, dr = dmp_zero(u), f, df
- if df < dg:
- return q, r
- N = df - dg + 1
- lc_g = dmp_LC(g, K)
- while True:
- lc_r = dmp_LC(r, K)
- j, N = dr - dg, N - 1
- Q = dmp_mul_term(q, lc_g, 0, u, K)
- q = dmp_add_term(Q, lc_r, j, u, K)
- R = dmp_mul_term(r, lc_g, 0, u, K)
- G = dmp_mul_term(g, lc_r, j, u, K)
- r = dmp_sub(R, G, u, K)
- _dr, dr = dr, dmp_degree(r, u)
- if dr < dg:
- break
- elif not (dr < _dr):
- raise PolynomialDivisionFailed(f, g, K)
- c = dmp_pow(lc_g, N, u - 1, K)
- q = dmp_mul_term(q, c, 0, u, K)
- r = dmp_mul_term(r, c, 0, u, K)
- return q, r
- def dmp_prem(f, g, u, K):
- """
- Polynomial pseudo-remainder in ``K[X]``.
- Examples
- ========
- >>> from sympy.polys import ring, ZZ
- >>> R, x,y = ring("x,y", ZZ)
- >>> R.dmp_prem(x**2 + x*y, 2*x + 2)
- -4*y + 4
- """
- if not u:
- return dup_prem(f, g, K)
- df = dmp_degree(f, u)
- dg = dmp_degree(g, u)
- if dg < 0:
- raise ZeroDivisionError("polynomial division")
- r, dr = f, df
- if df < dg:
- return r
- N = df - dg + 1
- lc_g = dmp_LC(g, K)
- while True:
- lc_r = dmp_LC(r, K)
- j, N = dr - dg, N - 1
- R = dmp_mul_term(r, lc_g, 0, u, K)
- G = dmp_mul_term(g, lc_r, j, u, K)
- r = dmp_sub(R, G, u, K)
- _dr, dr = dr, dmp_degree(r, u)
- if dr < dg:
- break
- elif not (dr < _dr):
- raise PolynomialDivisionFailed(f, g, K)
- c = dmp_pow(lc_g, N, u - 1, K)
- return dmp_mul_term(r, c, 0, u, K)
- def dmp_pquo(f, g, u, K):
- """
- Polynomial exact pseudo-quotient in ``K[X]``.
- Examples
- ========
- >>> from sympy.polys import ring, ZZ
- >>> R, x,y = ring("x,y", ZZ)
- >>> f = x**2 + x*y
- >>> g = 2*x + 2*y
- >>> h = 2*x + 2
- >>> R.dmp_pquo(f, g)
- 2*x
- >>> R.dmp_pquo(f, h)
- 2*x + 2*y - 2
- """
- return dmp_pdiv(f, g, u, K)[0]
- def dmp_pexquo(f, g, u, K):
- """
- Polynomial pseudo-quotient in ``K[X]``.
- Examples
- ========
- >>> from sympy.polys import ring, ZZ
- >>> R, x,y = ring("x,y", ZZ)
- >>> f = x**2 + x*y
- >>> g = 2*x + 2*y
- >>> h = 2*x + 2
- >>> R.dmp_pexquo(f, g)
- 2*x
- >>> R.dmp_pexquo(f, h)
- Traceback (most recent call last):
- ...
- ExactQuotientFailed: [[2], [2]] does not divide [[1], [1, 0], []]
- """
- q, r = dmp_pdiv(f, g, u, K)
- if dmp_zero_p(r, u):
- return q
- else:
- raise ExactQuotientFailed(f, g)
- def dup_rr_div(f, g, K):
- """
- Univariate division with remainder over a ring.
- Examples
- ========
- >>> from sympy.polys import ring, ZZ
- >>> R, x = ring("x", ZZ)
- >>> R.dup_rr_div(x**2 + 1, 2*x - 4)
- (0, x**2 + 1)
- """
- df = dup_degree(f)
- dg = dup_degree(g)
- q, r, dr = [], f, df
- if not g:
- raise ZeroDivisionError("polynomial division")
- elif df < dg:
- return q, r
- lc_g = dup_LC(g, K)
- while True:
- lc_r = dup_LC(r, K)
- if lc_r % lc_g:
- break
- c = K.exquo(lc_r, lc_g)
- j = dr - dg
- q = dup_add_term(q, c, j, K)
- h = dup_mul_term(g, c, j, K)
- r = dup_sub(r, h, K)
- _dr, dr = dr, dup_degree(r)
- if dr < dg:
- break
- elif not (dr < _dr):
- raise PolynomialDivisionFailed(f, g, K)
- return q, r
- def dmp_rr_div(f, g, u, K):
- """
- Multivariate division with remainder over a ring.
- Examples
- ========
- >>> from sympy.polys import ring, ZZ
- >>> R, x,y = ring("x,y", ZZ)
- >>> R.dmp_rr_div(x**2 + x*y, 2*x + 2)
- (0, x**2 + x*y)
- """
- if not u:
- return dup_rr_div(f, g, K)
- df = dmp_degree(f, u)
- dg = dmp_degree(g, u)
- if dg < 0:
- raise ZeroDivisionError("polynomial division")
- q, r, dr = dmp_zero(u), f, df
- if df < dg:
- return q, r
- lc_g, v = dmp_LC(g, K), u - 1
- while True:
- lc_r = dmp_LC(r, K)
- c, R = dmp_rr_div(lc_r, lc_g, v, K)
- if not dmp_zero_p(R, v):
- break
- j = dr - dg
- q = dmp_add_term(q, c, j, u, K)
- h = dmp_mul_term(g, c, j, u, K)
- r = dmp_sub(r, h, u, K)
- _dr, dr = dr, dmp_degree(r, u)
- if dr < dg:
- break
- elif not (dr < _dr):
- raise PolynomialDivisionFailed(f, g, K)
- return q, r
- def dup_ff_div(f, g, K):
- """
- Polynomial division with remainder over a field.
- Examples
- ========
- >>> from sympy.polys import ring, QQ
- >>> R, x = ring("x", QQ)
- >>> R.dup_ff_div(x**2 + 1, 2*x - 4)
- (1/2*x + 1, 5)
- """
- df = dup_degree(f)
- dg = dup_degree(g)
- q, r, dr = [], f, df
- if not g:
- raise ZeroDivisionError("polynomial division")
- elif df < dg:
- return q, r
- lc_g = dup_LC(g, K)
- while True:
- lc_r = dup_LC(r, K)
- c = K.exquo(lc_r, lc_g)
- j = dr - dg
- q = dup_add_term(q, c, j, K)
- h = dup_mul_term(g, c, j, K)
- r = dup_sub(r, h, K)
- _dr, dr = dr, dup_degree(r)
- if dr < dg:
- break
- elif dr == _dr and not K.is_Exact:
- # remove leading term created by rounding error
- r = dup_strip(r[1:])
- dr = dup_degree(r)
- if dr < dg:
- break
- elif not (dr < _dr):
- raise PolynomialDivisionFailed(f, g, K)
- return q, r
- def dmp_ff_div(f, g, u, K):
- """
- Polynomial division with remainder over a field.
- Examples
- ========
- >>> from sympy.polys import ring, QQ
- >>> R, x,y = ring("x,y", QQ)
- >>> R.dmp_ff_div(x**2 + x*y, 2*x + 2)
- (1/2*x + 1/2*y - 1/2, -y + 1)
- """
- if not u:
- return dup_ff_div(f, g, K)
- df = dmp_degree(f, u)
- dg = dmp_degree(g, u)
- if dg < 0:
- raise ZeroDivisionError("polynomial division")
- q, r, dr = dmp_zero(u), f, df
- if df < dg:
- return q, r
- lc_g, v = dmp_LC(g, K), u - 1
- while True:
- lc_r = dmp_LC(r, K)
- c, R = dmp_ff_div(lc_r, lc_g, v, K)
- if not dmp_zero_p(R, v):
- break
- j = dr - dg
- q = dmp_add_term(q, c, j, u, K)
- h = dmp_mul_term(g, c, j, u, K)
- r = dmp_sub(r, h, u, K)
- _dr, dr = dr, dmp_degree(r, u)
- if dr < dg:
- break
- elif not (dr < _dr):
- raise PolynomialDivisionFailed(f, g, K)
- return q, r
- def dup_div(f, g, K):
- """
- Polynomial division with remainder in ``K[x]``.
- Examples
- ========
- >>> from sympy.polys import ring, ZZ, QQ
- >>> R, x = ring("x", ZZ)
- >>> R.dup_div(x**2 + 1, 2*x - 4)
- (0, x**2 + 1)
- >>> R, x = ring("x", QQ)
- >>> R.dup_div(x**2 + 1, 2*x - 4)
- (1/2*x + 1, 5)
- """
- if K.is_Field:
- return dup_ff_div(f, g, K)
- else:
- return dup_rr_div(f, g, K)
- def dup_rem(f, g, K):
- """
- Returns polynomial remainder in ``K[x]``.
- Examples
- ========
- >>> from sympy.polys import ring, ZZ, QQ
- >>> R, x = ring("x", ZZ)
- >>> R.dup_rem(x**2 + 1, 2*x - 4)
- x**2 + 1
- >>> R, x = ring("x", QQ)
- >>> R.dup_rem(x**2 + 1, 2*x - 4)
- 5
- """
- return dup_div(f, g, K)[1]
- def dup_quo(f, g, K):
- """
- Returns exact polynomial quotient in ``K[x]``.
- Examples
- ========
- >>> from sympy.polys import ring, ZZ, QQ
- >>> R, x = ring("x", ZZ)
- >>> R.dup_quo(x**2 + 1, 2*x - 4)
- 0
- >>> R, x = ring("x", QQ)
- >>> R.dup_quo(x**2 + 1, 2*x - 4)
- 1/2*x + 1
- """
- return dup_div(f, g, K)[0]
- def dup_exquo(f, g, K):
- """
- Returns polynomial quotient in ``K[x]``.
- Examples
- ========
- >>> from sympy.polys import ring, ZZ
- >>> R, x = ring("x", ZZ)
- >>> R.dup_exquo(x**2 - 1, x - 1)
- x + 1
- >>> R.dup_exquo(x**2 + 1, 2*x - 4)
- Traceback (most recent call last):
- ...
- ExactQuotientFailed: [2, -4] does not divide [1, 0, 1]
- """
- q, r = dup_div(f, g, K)
- if not r:
- return q
- else:
- raise ExactQuotientFailed(f, g)
- def dmp_div(f, g, u, K):
- """
- Polynomial division with remainder in ``K[X]``.
- Examples
- ========
- >>> from sympy.polys import ring, ZZ, QQ
- >>> R, x,y = ring("x,y", ZZ)
- >>> R.dmp_div(x**2 + x*y, 2*x + 2)
- (0, x**2 + x*y)
- >>> R, x,y = ring("x,y", QQ)
- >>> R.dmp_div(x**2 + x*y, 2*x + 2)
- (1/2*x + 1/2*y - 1/2, -y + 1)
- """
- if K.is_Field:
- return dmp_ff_div(f, g, u, K)
- else:
- return dmp_rr_div(f, g, u, K)
- def dmp_rem(f, g, u, K):
- """
- Returns polynomial remainder in ``K[X]``.
- Examples
- ========
- >>> from sympy.polys import ring, ZZ, QQ
- >>> R, x,y = ring("x,y", ZZ)
- >>> R.dmp_rem(x**2 + x*y, 2*x + 2)
- x**2 + x*y
- >>> R, x,y = ring("x,y", QQ)
- >>> R.dmp_rem(x**2 + x*y, 2*x + 2)
- -y + 1
- """
- return dmp_div(f, g, u, K)[1]
- def dmp_quo(f, g, u, K):
- """
- Returns exact polynomial quotient in ``K[X]``.
- Examples
- ========
- >>> from sympy.polys import ring, ZZ, QQ
- >>> R, x,y = ring("x,y", ZZ)
- >>> R.dmp_quo(x**2 + x*y, 2*x + 2)
- 0
- >>> R, x,y = ring("x,y", QQ)
- >>> R.dmp_quo(x**2 + x*y, 2*x + 2)
- 1/2*x + 1/2*y - 1/2
- """
- return dmp_div(f, g, u, K)[0]
- def dmp_exquo(f, g, u, K):
- """
- Returns polynomial quotient in ``K[X]``.
- Examples
- ========
- >>> from sympy.polys import ring, ZZ
- >>> R, x,y = ring("x,y", ZZ)
- >>> f = x**2 + x*y
- >>> g = x + y
- >>> h = 2*x + 2
- >>> R.dmp_exquo(f, g)
- x
- >>> R.dmp_exquo(f, h)
- Traceback (most recent call last):
- ...
- ExactQuotientFailed: [[2], [2]] does not divide [[1], [1, 0], []]
- """
- q, r = dmp_div(f, g, u, K)
- if dmp_zero_p(r, u):
- return q
- else:
- raise ExactQuotientFailed(f, g)
- def dup_max_norm(f, K):
- """
- Returns maximum norm of a polynomial in ``K[x]``.
- Examples
- ========
- >>> from sympy.polys import ring, ZZ
- >>> R, x = ring("x", ZZ)
- >>> R.dup_max_norm(-x**2 + 2*x - 3)
- 3
- """
- if not f:
- return K.zero
- else:
- return max(dup_abs(f, K))
- def dmp_max_norm(f, u, K):
- """
- Returns maximum norm of a polynomial in ``K[X]``.
- Examples
- ========
- >>> from sympy.polys import ring, ZZ
- >>> R, x,y = ring("x,y", ZZ)
- >>> R.dmp_max_norm(2*x*y - x - 3)
- 3
- """
- if not u:
- return dup_max_norm(f, K)
- v = u - 1
- return max([ dmp_max_norm(c, v, K) for c in f ])
- def dup_l1_norm(f, K):
- """
- Returns l1 norm of a polynomial in ``K[x]``.
- Examples
- ========
- >>> from sympy.polys import ring, ZZ
- >>> R, x = ring("x", ZZ)
- >>> R.dup_l1_norm(2*x**3 - 3*x**2 + 1)
- 6
- """
- if not f:
- return K.zero
- else:
- return sum(dup_abs(f, K))
- def dmp_l1_norm(f, u, K):
- """
- Returns l1 norm of a polynomial in ``K[X]``.
- Examples
- ========
- >>> from sympy.polys import ring, ZZ
- >>> R, x,y = ring("x,y", ZZ)
- >>> R.dmp_l1_norm(2*x*y - x - 3)
- 6
- """
- if not u:
- return dup_l1_norm(f, K)
- v = u - 1
- return sum([ dmp_l1_norm(c, v, K) for c in f ])
- def dup_l2_norm_squared(f, K):
- """
- Returns squared l2 norm of a polynomial in ``K[x]``.
- Examples
- ========
- >>> from sympy.polys import ring, ZZ
- >>> R, x = ring("x", ZZ)
- >>> R.dup_l2_norm_squared(2*x**3 - 3*x**2 + 1)
- 14
- """
- return sum([coeff**2 for coeff in f], K.zero)
- def dmp_l2_norm_squared(f, u, K):
- """
- Returns squared l2 norm of a polynomial in ``K[X]``.
- Examples
- ========
- >>> from sympy.polys import ring, ZZ
- >>> R, x,y = ring("x,y", ZZ)
- >>> R.dmp_l2_norm_squared(2*x*y - x - 3)
- 14
- """
- if not u:
- return dup_l2_norm_squared(f, K)
- v = u - 1
- return sum([ dmp_l2_norm_squared(c, v, K) for c in f ])
- def dup_expand(polys, K):
- """
- Multiply together several polynomials in ``K[x]``.
- Examples
- ========
- >>> from sympy.polys import ring, ZZ
- >>> R, x = ring("x", ZZ)
- >>> R.dup_expand([x**2 - 1, x, 2])
- 2*x**3 - 2*x
- """
- if not polys:
- return [K.one]
- f = polys[0]
- for g in polys[1:]:
- f = dup_mul(f, g, K)
- return f
- def dmp_expand(polys, u, K):
- """
- Multiply together several polynomials in ``K[X]``.
- Examples
- ========
- >>> from sympy.polys import ring, ZZ
- >>> R, x,y = ring("x,y", ZZ)
- >>> R.dmp_expand([x**2 + y**2, x + 1])
- x**3 + x**2 + x*y**2 + y**2
- """
- if not polys:
- return dmp_one(u, K)
- f = polys[0]
- for g in polys[1:]:
- f = dmp_mul(f, g, u, K)
- return f
|