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_exquo(cf, h, v, K) for cf in f] cfg = [dmp_exquo(cg, h, v, K) for cg in g] return [h], cff, cfg
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_exquo(cf, h, v, K) for cf in f ] cfg = [ dmp_exquo(cg, h, v, K) for cg in g ] return [h], cff, cfg
def dmp_sqf_part(f, u, K): """ Returns square-free part of a polynomial in ``K[X]``. **Examples** >>> from sympy.polys.domains import ZZ >>> from sympy.polys.sqfreetools import dmp_sqf_part >>> f = ZZ.map([[1], [2, 0], [1, 0, 0], []]) >>> dmp_sqf_part(f, 1, ZZ) [[1], [1, 0], []] """ if not u: return dup_sqf_part(f, K) if not K.has_CharacteristicZero: return dmp_gf_sqf_part(f, u, K) if dmp_zero_p(f, u): return f if K.is_negative(dmp_ground_LC(f, u, K)): f = dmp_neg(f, u, K) gcd = dmp_gcd(f, dmp_diff(f, 1, u, K), u, K) sqf = dmp_exquo(f, gcd, u, K) if K.has_Field or not K.is_Exact: return dmp_ground_monic(sqf, u, K) else: return dmp_ground_primitive(sqf, u, K)[1]
def dmp_rr_lcm(f, g, u, K): """ Computes polynomial LCM over a ring in ``K[X]``. **Examples** >>> from sympy.polys.domains import ZZ >>> from sympy.polys.euclidtools import dmp_rr_lcm >>> f = ZZ.map([[1], [2, 0], [1, 0, 0]]) >>> g = ZZ.map([[1], [1, 0], []]) >>> dmp_rr_lcm(f, g, 1, ZZ) [[1], [2, 0], [1, 0, 0], []] """ fc, f = dmp_ground_primitive(f, u, K) gc, g = dmp_ground_primitive(g, u, K) c = K.lcm(fc, gc) h = dmp_exquo(dmp_mul(f, g, u, K), dmp_gcd(f, g, u, K), u, K) return dmp_mul_ground(h, c, u, K)
def test_dmp_div(): f, g, q, r = [5,4,3,2,1], [1,2,3], [5,-6,0], [20,1] assert dmp_div(f, g, 0, ZZ) == (q, r) assert dmp_quo(f, g, 0, ZZ) == q assert dmp_rem(f, g, 0, ZZ) == r raises(ExactQuotientFailed, lambda: dmp_exquo(f, g, 0, ZZ)) f, g, q, r = [[[1]]], [[[2]],[1]], [[[]]], [[[1]]] assert dmp_div(f, g, 2, ZZ) == (q, r) assert dmp_quo(f, g, 2, ZZ) == q assert dmp_rem(f, g, 2, ZZ) == r raises(ExactQuotientFailed, lambda: dmp_exquo(f, g, 2, ZZ))
def dmp_discriminant(f, u, K): """ Computes discriminant of a polynomial in ``K[X]``. **Examples** >>> from sympy.polys.domains import ZZ >>> from sympy.polys.euclidtools import dmp_discriminant >>> f = ZZ.map([[[[1]], [[]]], [[[1], []]], [[[1, 0]]]]) >>> dmp_discriminant(f, 3, ZZ) [[[-4, 0]], [[1], [], []]] """ 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_exquo(r, c, v, K)
def dmp_discriminant(f, u, K): """ Computes discriminant of a polynomial in ``K[X]``. **Examples** >>> from sympy.polys.domains import ZZ >>> from sympy.polys.euclidtools import dmp_discriminant >>> f = ZZ.map([[[[1]], [[]]], [[[1], []]], [[[1, 0]]]]) >>> dmp_discriminant(f, 3, ZZ) [[[-4, 0]], [[1], [], []]] """ 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_exquo(r, c, v, K)
def exquo(f, g): """Computes polynomial exact quotient of ``f`` and ``g``. """ lev, dom, per, F, G = f.unify(g) res = per(dmp_exquo(F, G, lev, dom)) if f.ring and res not in f.ring: from sympy.polys.polyerrors import ExactQuotientFailed raise ExactQuotientFailed(f, g, f.ring) return res
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.domains import ZZ >>> from sympy.polys.euclidtools import dmp_rr_prs_gcd >>> f = ZZ.map([[1], [2, 0], [1, 0, 0]]) >>> g = ZZ.map([[1], [1, 0], []]) >>> dmp_rr_prs_gcd(f, g, 1, ZZ) ([[1], [1, 0]], [[1], [1, 0]], [[1], []]) """ 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_exquo(f, h, u, K) cfg = dmp_exquo(g, h, u, 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.domains import ZZ >>> from sympy.polys.euclidtools import dmp_rr_prs_gcd >>> f = ZZ.map([[1], [2, 0], [1, 0, 0]]) >>> g = ZZ.map([[1], [1, 0], []]) >>> dmp_rr_prs_gcd(f, g, 1, ZZ) ([[1], [1, 0]], [[1], [1, 0]], [[1], []]) """ 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_exquo(f, h, u, K) cfg = dmp_exquo(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.domains import QQ >>> from sympy.polys.euclidtools import dmp_ff_prs_gcd >>> f = [[QQ(1,2)], [QQ(1), QQ(0)], [QQ(1,2), QQ(0), QQ(0)]] >>> g = [[QQ(1)], [QQ(1), QQ(0)], []] >>> dmp_ff_prs_gcd(f, g, 1, QQ) ([[1/1], [1/1, 0/1]], [[1/2], [1/2, 0/1]], [[1/1], []]) """ 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_exquo(f, h, u, K) cfg = dmp_exquo(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.domains import QQ >>> from sympy.polys.euclidtools import dmp_ff_prs_gcd >>> f = [[QQ(1,2)], [QQ(1), QQ(0)], [QQ(1,2), QQ(0), QQ(0)]] >>> g = [[QQ(1)], [QQ(1), QQ(0)], []] >>> dmp_ff_prs_gcd(f, g, 1, QQ) ([[1/1], [1/1, 0/1]], [[1/2], [1/2, 0/1]], [[1/1], []]) """ 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_exquo(f, h, u, K) cfg = dmp_exquo(g, h, u, K) return h, cff, cfg
def dmp_ff_lcm(f, g, u, K): """ Computes polynomial LCM over a field in ``K[X]``. **Examples** >>> from sympy.polys.domains import QQ >>> from sympy.polys.euclidtools import dmp_ff_lcm >>> f = [[QQ(1,4)], [QQ(1), QQ(0)], [QQ(1), QQ(0), QQ(0)]] >>> g = [[QQ(1,2)], [QQ(1), QQ(0)], []] >>> dmp_ff_lcm(f, g, 1, QQ) [[1/1], [4/1, 0/1], [4/1, 0/1, 0/1], []] """ h = dmp_exquo(dmp_mul(f, g, u, K), dmp_gcd(f, g, u, K), u, K) return dmp_ground_monic(h, u, K)
def dmp_primitive(f, u, K): """ Returns multivariate content and a primitive polynomial. **Examples** >>> from sympy.polys.domains import ZZ >>> from sympy.polys.euclidtools import dmp_primitive >>> f = ZZ.map([[2, 6], [4, 12]]) >>> dmp_primitive(f, 1, ZZ) ([2, 6], [[1], [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_exquo(c, cont, v, K) for c in f ]
def dmp_primitive(f, u, K): """ Returns multivariate content and a primitive polynomial. **Examples** >>> from sympy.polys.domains import ZZ >>> from sympy.polys.euclidtools import dmp_primitive >>> f = ZZ.map([[2, 6], [4, 12]]) >>> dmp_primitive(f, 1, ZZ) ([2, 6], [[1], [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_exquo(c, cont, v, K) for c in f]
def dmp_prs_resultant(f, g, u, K): """ Resultant algorithm in ``K[X]`` using subresultant PRS. **Examples** >>> from sympy.polys.domains import ZZ >>> from sympy.polys.euclidtools import dmp_prs_resultant >>> f = ZZ.map([[3, 0], [], [-1, 0, 0, -4]]) >>> g = ZZ.map([[1], [1, 0, 0, 0], [-9]]) >>> a = ZZ.map([[3, 0, 0, 0, 0], [1, 0, -27, 4]]) >>> b = ZZ.map([[-3, 0, 0, -12, 1, 0, -54, 8, 729, -216, 16]]) >>> dmp_prs_resultant(f, g, 1, ZZ) == (b[0], [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, B, D = dmp_inner_subresultants(f, g, u, K) if dmp_degree(R[-1], u) > 0: return (dmp_zero(u-1), R) if dmp_one_p(R[-2], u, K): return (dmp_LC(R[-1], K), R) s, i, v = 1, 1, u-1 p = dmp_one(v, K) q = dmp_one(v, K) for b, d in zip(B, D)[:-1]: du = dmp_degree(R[i-1], u) dv = dmp_degree(R[i ], u) dw = dmp_degree(R[i+1], u) if du % 2 and dv % 2: s = -s lc, i = dmp_LC(R[i], K), i+1 p = dmp_mul(dmp_mul(p, dmp_pow(b, dv, v, K), v, K), dmp_pow(lc, du-dw, v, K), v, K) q = dmp_mul(q, dmp_pow(lc, dv*(1+d), v, K), v, K) _, p, q = dmp_inner_gcd(p, q, v, K) if s < 0: p = dmp_neg(p, v, K) i = dmp_degree(R[-2], u) res = dmp_pow(dmp_LC(R[-1], K), i, v, K) res = dmp_exquo(dmp_mul(res, p, v, K), q, v, K) return res, R
def dmp_inner_subresultants(f, g, u, K): """ Subresultant PRS algorithm in ``K[X]``. **Examples** >>> from sympy.polys.domains import ZZ >>> from sympy.polys.euclidtools import dmp_inner_subresultants >>> f = ZZ.map([[3, 0], [], [-1, 0, 0, -4]]) >>> g = ZZ.map([[1], [1, 0, 0, 0], [-9]]) >>> a = [[3, 0, 0, 0, 0], [1, 0, -27, 4]] >>> b = [[-3, 0, 0, -12, 1, 0, -54, 8, 729, -216, 16]] >>> R = ZZ.map([f, g, a, b]) >>> B = ZZ.map([[-1], [1], [9, 0, 0, 0, 0, 0, 0, 0, 0]]) >>> D = ZZ.map([0, 1, 1]) >>> dmp_inner_subresultants(f, g, 1, ZZ) == (R, B, D) 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 R = [f, g] d = n - m v = u - 1 b = dmp_pow(dmp_ground(-K.one, v), d+1, v, K) c = dmp_ground(-K.one, v) B, D = [b], [d] if dmp_zero_p(f, u) or dmp_zero_p(g, u): return R, B, D h = dmp_prem(f, g, u, K) h = dmp_mul_term(h, b, 0, u, K) while not dmp_zero_p(h, u): k = dmp_degree(h, u) R.append(h) lc = dmp_LC(g, K) p = dmp_pow(dmp_neg(lc, v, K), d, v, K) if not d: q = c else: q = dmp_pow(c, d-1, v, K) c = dmp_exquo(p, q, v, K) b = dmp_mul(dmp_neg(lc, v, K), dmp_pow(c, m-k, v, K), v, K) f, g, m, d = g, h, k, m-k B.append(b) D.append(d) h = dmp_prem(f, g, u, K) h = [ dmp_exquo(ch, b, v, K) for ch in h ] return R, B, D
def dmp_inner_subresultants(f, g, u, K): """ Subresultant PRS algorithm in ``K[X]``. **Examples** >>> from sympy.polys.domains import ZZ >>> from sympy.polys.euclidtools import dmp_inner_subresultants >>> f = ZZ.map([[3, 0], [], [-1, 0, 0, -4]]) >>> g = ZZ.map([[1], [1, 0, 0, 0], [-9]]) >>> a = [[3, 0, 0, 0, 0], [1, 0, -27, 4]] >>> b = [[-3, 0, 0, -12, 1, 0, -54, 8, 729, -216, 16]] >>> R = ZZ.map([f, g, a, b]) >>> B = ZZ.map([[-1], [1], [9, 0, 0, 0, 0, 0, 0, 0, 0]]) >>> D = ZZ.map([0, 1, 1]) >>> dmp_inner_subresultants(f, g, 1, ZZ) == (R, B, D) 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 R = [f, g] d = n - m v = u - 1 b = dmp_pow(dmp_ground(-K.one, v), d + 1, v, K) c = dmp_ground(-K.one, v) B, D = [b], [d] if dmp_zero_p(f, u) or dmp_zero_p(g, u): return R, B, D h = dmp_prem(f, g, u, K) h = dmp_mul_term(h, b, 0, u, K) while not dmp_zero_p(h, u): k = dmp_degree(h, u) R.append(h) lc = dmp_LC(g, K) p = dmp_pow(dmp_neg(lc, v, K), d, v, K) if not d: q = c else: q = dmp_pow(c, d - 1, v, K) c = dmp_exquo(p, q, v, K) b = dmp_mul(dmp_neg(lc, v, K), dmp_pow(c, m - k, v, K), v, K) f, g, m, d = g, h, k, m - k B.append(b) D.append(d) h = dmp_prem(f, g, u, K) h = [dmp_exquo(ch, b, v, K) for ch in h] return R, B, D
def dmp_prs_resultant(f, g, u, K): """ Resultant algorithm in ``K[X]`` using subresultant PRS. **Examples** >>> from sympy.polys.domains import ZZ >>> from sympy.polys.euclidtools import dmp_prs_resultant >>> f = ZZ.map([[3, 0], [], [-1, 0, 0, -4]]) >>> g = ZZ.map([[1], [1, 0, 0, 0], [-9]]) >>> a = ZZ.map([[3, 0, 0, 0, 0], [1, 0, -27, 4]]) >>> b = ZZ.map([[-3, 0, 0, -12, 1, 0, -54, 8, 729, -216, 16]]) >>> dmp_prs_resultant(f, g, 1, ZZ) == (b[0], [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, B, D = dmp_inner_subresultants(f, g, u, K) if dmp_degree(R[-1], u) > 0: return (dmp_zero(u - 1), R) if dmp_one_p(R[-2], u, K): return (dmp_LC(R[-1], K), R) s, i, v = 1, 1, u - 1 p = dmp_one(v, K) q = dmp_one(v, K) for b, d in zip(B, D)[:-1]: du = dmp_degree(R[i - 1], u) dv = dmp_degree(R[i], u) dw = dmp_degree(R[i + 1], u) if du % 2 and dv % 2: s = -s lc, i = dmp_LC(R[i], K), i + 1 p = dmp_mul(dmp_mul(p, dmp_pow(b, dv, v, K), v, K), dmp_pow(lc, du - dw, v, K), v, K) q = dmp_mul(q, dmp_pow(lc, dv * (1 + d), v, K), v, K) _, p, q = dmp_inner_gcd(p, q, v, K) if s < 0: p = dmp_neg(p, v, K) i = dmp_degree(R[-2], u) res = dmp_pow(dmp_LC(R[-1], K), i, v, K) res = dmp_exquo(dmp_mul(res, p, v, K), q, v, K) return res, R
def dmp_zz_diophantine(F, c, A, d, p, u, K): """Wang/EEZ: Solve multivariate Diophantine equations. """ if not A: S = [ [] for _ in F ] n = dup_degree(c) for i, coeff in enumerate(c): if not coeff: continue T = dup_zz_diophantine(F, n-i, p, K) for j, (s, t) in enumerate(zip(S, T)): t = dup_mul_ground(t, coeff, K) S[j] = dup_trunc(dup_add(s, t, K), p, K) else: n = len(A) e = dmp_expand(F, u, K) a, A = A[-1], A[:-1] B, G = [], [] for f in F: B.append(dmp_exquo(e, f, u, K)) G.append(dmp_eval_in(f, a, n, u, K)) C = dmp_eval_in(c, a, n, u, K) v = u - 1 S = dmp_zz_diophantine(G, C, A, d, p, v, K) S = [ dmp_raise(s, 1, v, K) for s in S ] for s, b in zip(S, B): c = dmp_sub_mul(c, s, b, u, K) c = dmp_ground_trunc(c, p, u, K) m = dmp_nest([K.one, -a], n, K) M = dmp_one(n, K) for k in xrange(0, d): if dmp_zero_p(c, u): break M = dmp_mul(M, m, u, K) C = dmp_diff_eval_in(c, k+1, a, n, u, K) if not dmp_zero_p(C, v): C = dmp_exquo_ground(C, K.factorial(k+1), v, K) T = dmp_zz_diophantine(G, C, A, d, p, v, K) for i, t in enumerate(T): T[i] = dmp_mul(dmp_raise(t, 1, v, K), M, u, K) for i, (s, t) in enumerate(zip(S, T)): S[i] = dmp_add(s, t, u, K) for t, b in zip(T, B): c = dmp_sub_mul(c, t, b, u, K) c = dmp_ground_trunc(c, p, u, K) S = [ dmp_ground_trunc(s, p, u, K) for s in S ] return S
def exquo(f, g): """Computes polynomial exact quotient of `f` and `g`. """ lev, dom, per, F, G = f.unify(g) return per(dmp_exquo(F, G, lev, dom))
def dmp_zz_diophantine(F, c, A, d, p, u, K): """Wang/EEZ: Solve multivariate Diophantine equations. """ if not A: S = [[] for _ in F] n = dup_degree(c) for i, coeff in enumerate(c): if not coeff: continue T = dup_zz_diophantine(F, n - i, p, K) for j, (s, t) in enumerate(zip(S, T)): t = dup_mul_ground(t, coeff, K) S[j] = dup_trunc(dup_add(s, t, K), p, K) else: n = len(A) e = dmp_expand(F, u, K) a, A = A[-1], A[:-1] B, G = [], [] for f in F: B.append(dmp_exquo(e, f, u, K)) G.append(dmp_eval_in(f, a, n, u, K)) C = dmp_eval_in(c, a, n, u, K) v = u - 1 S = dmp_zz_diophantine(G, C, A, d, p, v, K) S = [dmp_raise(s, 1, v, K) for s in S] for s, b in zip(S, B): c = dmp_sub_mul(c, s, b, u, K) c = dmp_ground_trunc(c, p, u, K) m = dmp_nest([K.one, -a], n, K) M = dmp_one(n, K) for k in xrange(0, d): if dmp_zero_p(c, u): break M = dmp_mul(M, m, u, K) C = dmp_diff_eval_in(c, k + 1, a, n, u, K) if not dmp_zero_p(C, v): C = dmp_exquo_ground(C, K.factorial(k + 1), v, K) T = dmp_zz_diophantine(G, C, A, d, p, v, K) for i, t in enumerate(T): T[i] = dmp_mul(dmp_raise(t, 1, v, K), M, u, K) for i, (s, t) in enumerate(zip(S, T)): S[i] = dmp_add(s, t, u, K) for t, b in zip(T, B): c = dmp_sub_mul(c, t, b, u, K) c = dmp_ground_trunc(c, p, u, K) S = [dmp_ground_trunc(s, p, u, K) for s in S] return S