def dmp_zz_collins_resultant(f, g, u, K): """ Collins's modular resultant algorithm in `Z[X]`. Examples ======== >>> from sympy.polys import ring, ZZ >>> R, x,y = ring("x,y", ZZ) >>> f = x + y + 2 >>> g = 2*x*y + x + 3 >>> R.dmp_zz_collins_resultant(f, g) -2*y**2 - 5*y + 1 """ n = dmp_degree(f, u) m = dmp_degree(g, u) if n < 0 or m < 0: return dmp_zero(u - 1) A = dmp_max_norm(f, u, K) B = dmp_max_norm(g, u, K) a = dmp_ground_LC(f, u, K) b = dmp_ground_LC(g, u, K) v = u - 1 B = K(2)*K.factorial(K(n + m))*A**m*B**n r, p, P = dmp_zero(v), K.one, K.one while P <= B: p = K(nextprime(p)) while not (a % p) or not (b % p): p = K(nextprime(p)) F = dmp_ground_trunc(f, p, u, K) G = dmp_ground_trunc(g, p, u, K) try: R = dmp_zz_modular_resultant(F, G, p, u, K) except HomomorphismFailed: continue if K.is_one(P): r = R else: r = dmp_apply_pairs(r, R, _collins_crt, (P, p, K), v, K) P *= p return r
def dmp_zz_collins_resultant(f, g, u, K): """ Collins's modular resultant algorithm in `Z[X]`. Examples ======== >>> from sympy.polys.domains import ZZ >>> from sympy.polys.euclidtools import dmp_zz_collins_resultant >>> f = ZZ.map([[1], [1, 2]]) >>> g = ZZ.map([[2, 1], [3]]) >>> dmp_zz_collins_resultant(f, g, 1, ZZ) [-2, -5, 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(n+m)*A**m*B**n r, p, P = dmp_zero(v), K.one, K.one while P <= B: p = K(nextprime(p)) while not (a % p) or not (b % p): p = K(nextprime(p)) F = dmp_ground_trunc(f, p, u, K) G = dmp_ground_trunc(g, p, u, K) try: R = dmp_zz_modular_resultant(F, G, p, u, K) except HomomorphismFailed: continue if K.is_one(P): r = R else: r = dmp_apply_pairs(r, R, _collins_crt, (P, p, K), v, K) P *= p return r
def _dmp_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_mul(f, g, u, K): """Multiply dense polynomials in `K[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 xrange(0, df+dg+1): coeff = dmp_zero(v) for j in xrange(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 h
def dmp_sqr(f, u, K): """Square dense polynomials in `K[X]`. """ 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 xrange(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 xrange(jmin, jmax+1): c = dmp_add(c, dmp_mul(f[j], f[i-j], v, K), v, K) c = dmp_mul_ground(c, 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 h
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_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 dmp_fateman_poly_F_1(n, K): """Fateman's GCD benchmark: trivial GCD """ u = [K(1), K(0)] for i in xrange(0, n): u = [dmp_one(i, K), u] v = [K(1), K(0), K(0)] for i in xrange(0, n): v = [dmp_one(i, K), dmp_zero(i), v] m = n - 1 U = dmp_add_term(u, dmp_ground(K(1), m), 0, n, K) V = dmp_add_term(u, dmp_ground(K(2), m), 0, n, K) f = [[-K(3), K(0)], [], [K(1), K(0), -K(1)]] W = dmp_add_term(v, dmp_ground(K(1), m), 0, n, K) Y = dmp_raise(f, m, 1, K) F = dmp_mul(U, V, n, K) G = dmp_mul(W, Y, n, K) H = dmp_one(n, K) return F, G, H
def dmp_eval_tail(f, A, u, K): """ Evaluate a polynomial at ``x_j = a_j, ...`` in ``K[X]``. Examples ======== >>> from sympy.polys import ring, ZZ >>> R, x,y = ring("x,y", ZZ) >>> f = 2*x*y + 3*x + y + 2 >>> R.dmp_eval_tail(f, [2]) 7*x + 4 >>> R.dmp_eval_tail(f, [2, 2]) 18 """ if not A: return f if dmp_zero_p(f, u): return dmp_zero(u - len(A)) e = _rec_eval_tail(f, 0, A, u, K) if u == len(A) - 1: return e else: return dmp_strip(e, u - len(A))
def dmp_sqr(f, u, K): """Square dense polynomials in `K[X]`. """ 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 xrange(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 xrange(jmin, jmax + 1): c = dmp_add(c, dmp_mul(f[j], f[i - j], v, K), v, K) c = dmp_mul_ground(c, 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 h
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 dmp_eval_tail(f, A, u, K): """ Evaluate a polynomial at ``x_j = a_j, ...`` in ``K[X]``. **Examples** >>> from sympy.polys.domains import ZZ >>> from sympy.polys.densetools import dmp_eval_tail >>> f = ZZ.map([[2, 3], [1, 2]]) >>> dmp_eval_tail(f, (2, 2), 1, ZZ) 18 >>> dmp_eval_tail(f, (2,), 1, ZZ) [7, 4] """ if not A: return f if dmp_zero_p(f, u): return dmp_zero(u - len(A)) e = _rec_eval_tail(f, 0, A, u, K) if u == len(A) - 1: return e else: return dmp_strip(e, u - len(A))
def dmp_fateman_poly_F_1(n, K): """Fateman's GCD benchmark: trivial GCD """ u = [K(1), K(0)] for i in range(n): u = [dmp_one(i, K), u] v = [K(1), K(0), K(0)] for i in range(0, n): v = [dmp_one(i, K), dmp_zero(i), v] m = n - 1 U = dmp_add_term(u, dmp_ground(K(1), m), 0, n, K) V = dmp_add_term(u, dmp_ground(K(2), m), 0, n, K) f = [[-K(3), K(0)], [], [K(1), K(0), -K(1)]] W = dmp_add_term(v, dmp_ground(K(1), m), 0, n, K) Y = dmp_raise(f, m, 1, K) F = dmp_mul(U, V, n, K) G = dmp_mul(W, Y, n, K) H = dmp_one(n, K) return F, G, H
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.domains import ZZ >>> from sympy.polys.densearith import dmp_mul_term >>> f = ZZ.map([[1, 0], [1], []]) >>> c = ZZ.map([3, 0]) >>> dmp_mul_term(f, c, 2, 1, ZZ) [[3, 0, 0], [3, 0], [], [], []] """ 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 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_quo(r, c, v, K)
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 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.domains import ZZ >>> from sympy.polys.densearith import dmp_mul_term >>> f = ZZ.map([[1, 0], [1], []]) >>> c = ZZ.map([3, 0]) >>> dmp_mul_term(f, c, 2, 1, ZZ) [[3, 0, 0], [3, 0], [], [], []] """ 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 dmp_mul(f, g, u, K): """Multiply dense polynomials in `K[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 xrange(0, df + dg + 1): coeff = dmp_zero(v) for j in xrange(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 h
def dmp_eval_tail(f, A, u, K): """ Evaluate a polynomial at ``x_j = a_j, ...`` in ``K[X]``. Examples ======== >>> from sympy.polys.domains import ZZ >>> from sympy.polys.densetools import dmp_eval_tail >>> f = ZZ.map([[2, 3], [1, 2]]) >>> dmp_eval_tail(f, (2, 2), 1, ZZ) 18 >>> dmp_eval_tail(f, (2,), 1, ZZ) [7, 4] """ if not A: return f if dmp_zero_p(f, u): return dmp_zero(u - len(A)) e = _rec_eval_tail(f, 0, A, u, K) if u == len(A) - 1: return e else: return dmp_strip(e, u - len(A))
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 dup_real_imag(f, K): """ Return bivariate polynomials ``f1`` and ``f2``, such that ``f = f1 + f2*I``. Examples ======== >>> from sympy.polys import ring, ZZ >>> R, x,y = ring("x,y", ZZ) >>> R.dup_real_imag(x**3 + x**2 + x + 1) (x**3 + x**2 - 3*x*y**2 + x - y**2 + 1, 3*x**2*y + 2*x*y - y**3 + y) """ if not K.is_ZZ and not K.is_QQ: raise DomainError( "computing real and imaginary parts is not supported over %s" % K) f1 = dmp_zero(1) f2 = dmp_zero(1) if not f: return f1, f2 g = [[[K.one, K.zero]], [[K.one], []]] h = dmp_ground(f[0], 2) for c in f[1:]: h = dmp_mul(h, g, 2, K) h = dmp_add_term(h, dmp_ground(c, 1), 0, 2, K) H = dup_to_raw_dict(h) for k, h in H.items(): m = k % 4 if not m: f1 = dmp_add(f1, h, 1, K) elif m == 1: f2 = dmp_add(f2, h, 1, K) elif m == 2: f1 = dmp_sub(f1, h, 1, K) else: f2 = dmp_sub(f2, h, 1, K) return f1, f2
def dup_real_imag(f, K): """ Return bivariate polynomials ``f1`` and ``f2``, such that ``f = f1 + f2*I``. Examples ======== >>> from sympy.polys.domains import ZZ >>> from sympy.polys.densetools import dup_real_imag >>> dup_real_imag([ZZ(1), ZZ(1), ZZ(1), ZZ(1)], ZZ) ([[1], [1], [-3, 0, 1], [-1, 0, 1]], [[3, 0], [2, 0], [-1, 0, 1, 0]]) """ if not K.is_ZZ and not K.is_QQ: raise DomainError( "computing real and imaginary parts is not supported over %s" % K) f1 = dmp_zero(1) f2 = dmp_zero(1) if not f: return f1, f2 g = [[[K.one, K.zero]], [[K.one], []]] h = dmp_ground(f[0], 2) for c in f[1:]: h = dmp_mul(h, g, 2, K) h = dmp_add_term(h, dmp_ground(c, 1), 0, 2, K) H = dup_to_raw_dict(h) for k, h in H.iteritems(): m = k % 4 if not m: f1 = dmp_add(f1, h, 1, K) elif m == 1: f2 = dmp_add(f2, h, 1, K) elif m == 2: f1 = dmp_sub(f1, h, 1, K) else: f2 = dmp_sub(f2, h, 1, K) return f1, f2
def dup_real_imag(f, K): """ Return bivariate polynomials ``f1`` and ``f2``, such that ``f = f1 + f2*I``. Examples ======== >>> from sympy.polys import ring, ZZ >>> R, x,y = ring("x,y", ZZ) >>> R.dup_real_imag(x**3 + x**2 + x + 1) (x**3 + x**2 - 3*x*y**2 + x - y**2 + 1, 3*x**2*y + 2*x*y - y**3 + y) """ if not K.is_ZZ and not K.is_QQ: raise DomainError("computing real and imaginary parts is not supported over %s" % K) f1 = dmp_zero(1) f2 = dmp_zero(1) if not f: return f1, f2 g = [[[K.one, K.zero]], [[K.one], []]] h = dmp_ground(f[0], 2) for c in f[1:]: h = dmp_mul(h, g, 2, K) h = dmp_add_term(h, dmp_ground(c, 1), 0, 2, K) H = dup_to_raw_dict(h) for k, h in H.items(): m = k % 4 if not m: f1 = dmp_add(f1, h, 1, K) elif m == 1: f2 = dmp_add(f2, h, 1, K) elif m == 2: f1 = dmp_sub(f1, h, 1, K) else: f2 = dmp_sub(f2, h, 1, K) return f1, f2
def dmp_pdiv(f, g, u, K): """ Polynomial pseudo-division in ``K[X]``. Examples ======== >>> from sympy.polys.domains import ZZ >>> from sympy.polys.densearith import dmp_pdiv >>> f = ZZ.map([[1], [1, 0], []]) >>> g = ZZ.map([[2], [2]]) >>> dmp_pdiv(f, g, 1, ZZ) ([[2], [2, -2]], [[-4, 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 = dmp_zero(u), f if df < dg: return q, r N = df - dg + 1 lc_g = dmp_LC(g, K) while True: dr = dmp_degree(r, u) if dr < dg: break 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) 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_pdiv(f, g, u, K): """ Polynomial pseudo-division in ``K[X]``. Examples ======== >>> from sympy.polys.domains import ZZ >>> from sympy.polys.densearith import dmp_pdiv >>> f = ZZ.map([[1], [1, 0], []]) >>> g = ZZ.map([[2], [2]]) >>> dmp_pdiv(f, g, 1, ZZ) ([[2], [2, -2]], [[-4, 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 = dmp_zero(u), f if df < dg: return q, r N = df - dg + 1 lc_g = dmp_LC(g, K) while True: dr = dmp_degree(r, u) if dr < dg: break 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) 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_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_ff_div(f, g, u, K): """ Polynomial division with remainder over a field. Examples ======== >>> from sympy.polys.domains import QQ >>> from sympy.polys.densearith import dmp_ff_div >>> f = QQ.map([[1], [1, 0], []]) >>> g = QQ.map([[2], [2]]) >>> dmp_ff_div(f, g, 1, QQ) ([[1/2], [1/2, -1/2]], [[-1/1, 1/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 = dmp_zero(u), f if df < dg: return q, r lc_g, v = dmp_LC(g, K), u - 1 while True: dr = dmp_degree(r, u) if dr < dg: break 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) return q, r
def dmp_ff_div(f, g, u, K): """ Polynomial division with remainder over a field. Examples ======== >>> from sympy.polys.domains import QQ >>> from sympy.polys.densearith import dmp_ff_div >>> f = QQ.map([[1], [1, 0], []]) >>> g = QQ.map([[2], [2]]) >>> dmp_ff_div(f, g, 1, QQ) ([[1/2], [1/2, -1/2]], [[-1/1, 1/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 = dmp_zero(u), f if df < dg: return q, r lc_g, v = dmp_LC(g, K), u-1 while True: dr = dmp_degree(r, u) if dr < dg: break 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) return q, r
def dmp_rr_div(f, g, u, K): """ Multivariate division with remainder over a ring. **Examples** >>> from sympy.polys.domains import ZZ >>> from sympy.polys.densearith import dmp_rr_div >>> f = ZZ.map([[1], [1, 0], []]) >>> g = ZZ.map([[2], [2]]) >>> dmp_rr_div(f, g, 1, ZZ) ([[]], [[1], [1, 0], []]) """ 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 = dmp_zero(u), f if df < dg: return q, r lc_g, v = dmp_LC(g, K), u - 1 while True: dr = dmp_degree(r, u) if dr < dg: break 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) return q, r
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 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 query('USE_SIMPLIFY_GCD'): return _dmp_simplify_gcd(f, g, u, K) else: return None
def dmp_rr_div(f, g, u, K): """ Multivariate division with remainder over a ring. **Examples** >>> from sympy.polys.domains import ZZ >>> from sympy.polys.densearith import dmp_rr_div >>> f = ZZ.map([[1], [1, 0], []]) >>> g = ZZ.map([[2], [2]]) >>> dmp_rr_div(f, g, 1, ZZ) ([[]], [[1], [1, 0], []]) """ 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 = dmp_zero(u), f if df < dg: return q, r lc_g, v = dmp_LC(g, K), u-1 while True: dr = dmp_degree(r, u) if dr < dg: break 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) return q, r
def dmp_mul_term(f, c, i, u, K): """Multiply `f` by `c(x_2..x_u)*x_0**i` in `K[X]`. """ 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 dmp_mul_term(f, c, i, u, K): """Multiply `f` by `c(x_2..x_u)*x_0**i` in `K[X]`. """ 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 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 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 = dmp_zero(u), f if df < dg: return q, r lc_g, v = dmp_LC(g, K), u - 1 while True: dr = dmp_degree(r, u) if dr < dg: break 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) return q, r
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_sqr(f, u, K): """ Square dense polynomials in ``K[X]``. Examples ======== >>> from sympy.polys.domains import ZZ >>> from sympy.polys.densearith import dmp_sqr >>> f = ZZ.map([[1], [1, 0], [1, 0, 0]]) >>> dmp_sqr(f, 1, ZZ) [[1], [2, 0], [3, 0, 0], [2, 0, 0, 0], [1, 0, 0, 0, 0]] """ 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 xrange(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 xrange(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 dmp_sqr(f, u, K): """ Square dense polynomials in ``K[X]``. Examples ======== >>> from sympy.polys.domains import ZZ >>> from sympy.polys.densearith import dmp_sqr >>> f = ZZ.map([[1], [1, 0], [1, 0, 0]]) >>> dmp_sqr(f, 1, ZZ) [[1], [2, 0], [3, 0, 0], [2, 0, 0, 0], [1, 0, 0, 0, 0]] """ 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 xrange(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 xrange(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 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 xrange(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 xrange(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 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 dmp_diff(f, m, u, K): """ ``m``-th order derivative in ``x_0`` of a polynomial in ``K[X]``. Examples ======== >>> from sympy.polys.domains import ZZ >>> from sympy.polys.densetools import dmp_diff >>> f = ZZ.map([[1, 2, 3], [2, 3, 1]]) >>> dmp_diff(f, 1, 1, ZZ) [[1, 2, 3]] >>> dmp_diff(f, 2, 1, ZZ) [[]] """ if not u: return dup_diff(f, m, K) if m <= 0: return f n = dmp_degree(f, u) if n < m: return dmp_zero(u) deriv, v = [], u - 1 if m == 1: for coeff in f[:-m]: deriv.append(dmp_mul_ground(coeff, K(n), v, K)) n -= 1 else: for coeff in f[:-m]: k = n for i in xrange(n - 1, n - m, -1): k *= i deriv.append(dmp_mul_ground(coeff, K(k), v, K)) n -= 1 return dmp_strip(deriv, u)
def dmp_diff(f, m, u, K): """ ``m``-th order derivative in ``x_0`` of a polynomial in ``K[X]``. Examples ======== >>> from sympy.polys import ring, ZZ >>> R, x,y = ring("x,y", ZZ) >>> f = x*y**2 + 2*x*y + 3*x + 2*y**2 + 3*y + 1 >>> R.dmp_diff(f, 1) y**2 + 2*y + 3 >>> R.dmp_diff(f, 2) 0 """ if not u: return dup_diff(f, m, K) if m <= 0: return f n = dmp_degree(f, u) if n < m: return dmp_zero(u) deriv, v = [], u - 1 if m == 1: for coeff in f[:-m]: deriv.append(dmp_mul_ground(coeff, K(n), v, K)) n -= 1 else: for coeff in f[:-m]: k = n for i in range(n - 1, n - m, -1): k *= i deriv.append(dmp_mul_ground(coeff, K(k), v, K)) n -= 1 return dmp_strip(deriv, u)
def dmp_mul(f, g, u, K): """ Multiply dense polynomials in ``K[X]``. Examples ======== >>> from sympy.polys.domains import ZZ >>> from sympy.polys.densearith import dmp_mul >>> f = ZZ.map([[1, 0], [1]]) >>> g = ZZ.map([[1], []]) >>> dmp_mul(f, g, 1, ZZ) [[1, 0], [1], []] """ 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 xrange(0, df+dg+1): coeff = dmp_zero(v) for j in xrange(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 dmp_mul(f, g, u, K): """ Multiply dense polynomials in ``K[X]``. Examples ======== >>> from sympy.polys.domains import ZZ >>> from sympy.polys.densearith import dmp_mul >>> f = ZZ.map([[1, 0], [1]]) >>> g = ZZ.map([[1], []]) >>> dmp_mul(f, g, 1, ZZ) [[1, 0], [1], []] """ 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 xrange(0, df + dg + 1): coeff = dmp_zero(v) for j in xrange(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 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 xrange(0, df + dg + 1): coeff = dmp_zero(v) for j in xrange(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 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 dmp_pdiv(f, g, u, K): """Polynomial pseudo-division in `K[X]`. """ 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 = dmp_zero(u), f if df < dg: return q, r N = df - dg + 1 lc_g = dmp_LC(g, K) while True: dr = dmp_degree(r, u) if dr < dg: break 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) 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_pdiv(f, g, u, K): """Polynomial pseudo-division in `K[X]`. """ 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 = dmp_zero(u), f if df < dg: return q, r N = df - dg + 1 lc_g = dmp_LC(g, K) while True: dr = dmp_degree(r, u) if dr < dg: break 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) 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_ff_div(f, g, u, K): """Polynomial division with remainder over a field. """ 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 = dmp_zero(u), f if df < dg: return q, r lc_g, v = dmp_LC(g, K), u - 1 while True: dr = dmp_degree(r, u) if dr < dg: break 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) return q, 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)