def test_dup_gcdex(): f = dup_normal([1, -2, -6, 12, 15], QQ) g = dup_normal([1, 1, -4, -4], QQ) s = [QQ(-1, 5), QQ(3, 5)] t = [QQ(1, 5), QQ(-6, 5), QQ(2)] h = [QQ(1), QQ(1)] assert dup_half_gcdex(f, g, QQ) == (s, h) assert dup_gcdex(f, g, QQ) == (s, t, h) f = dup_normal([1, 4, 0, -1, 1], QQ) g = dup_normal([1, 0, -1, 1], QQ) s, t, h = dup_gcdex(f, g, QQ) S, T, H = dup_gcdex(g, f, QQ) assert dup_add(dup_mul(s, f, QQ), dup_mul(t, g, QQ), QQ) == h assert dup_add(dup_mul(S, g, QQ), dup_mul(T, f, QQ), QQ) == H f = dup_normal([2, 0], QQ) g = dup_normal([1, 0, -16], QQ) s = [QQ(1, 32), QQ(0)] t = [QQ(-1, 16)] h = [QQ(1)] assert dup_half_gcdex(f, g, QQ) == (s, h) assert dup_gcdex(f, g, QQ) == (s, t, h)
def test_dup_gcdex(): f = dup_normal([1,-2,-6,12,15], QQ) g = dup_normal([1,1,-4,-4], QQ) s = [QQ(-1,5),QQ(3,5)] t = [QQ(1,5),QQ(-6,5),QQ(2)] h = [QQ(1),QQ(1)] assert dup_half_gcdex(f, g, QQ) == (s, h) assert dup_gcdex(f, g, QQ) == (s, t, h) f = dup_normal([1,4,0,-1,1], QQ) g = dup_normal([1,0,-1,1], QQ) s, t, h = dup_gcdex(f, g, QQ) S, T, H = dup_gcdex(g, f, QQ) assert dup_add(dup_mul(s, f, QQ), dup_mul(t, g, QQ), QQ) == h assert dup_add(dup_mul(S, g, QQ), dup_mul(T, f, QQ), QQ) == H f = dup_normal([2,0], QQ) g = dup_normal([1,0,-16], QQ) s = [QQ(1,32),QQ(0)] t = [QQ(-1,16)] h = [QQ(1)] assert dup_half_gcdex(f, g, QQ) == (s, h) assert dup_gcdex(f, g, QQ) == (s, t, h)
def dup_zz_hensel_step(m, f, g, h, s, t, K): """ One step in Hensel lifting in `Z[x]`. Given positive integer `m` and `Z[x]` polynomials `f`, `g`, `h`, `s` and `t` such that:: f == g*h (mod m) s*g + t*h == 1 (mod m) lc(f) is not a zero divisor (mod m) lc(h) == 1 deg(f) == deg(g) + deg(h) deg(s) < deg(h) deg(t) < deg(g) returns polynomials `G`, `H`, `S` and `T`, such that:: f == G*H (mod m**2) S*G + T**H == 1 (mod m**2) References ========== 1. [Gathen99]_ """ M = m**2 e = dup_sub_mul(f, g, h, K) e = dup_trunc(e, M, K) q, r = dup_div(dup_mul(s, e, K), h, K) q = dup_trunc(q, M, K) r = dup_trunc(r, M, K) u = dup_add(dup_mul(t, e, K), dup_mul(q, g, K), K) G = dup_trunc(dup_add(g, u, K), M, K) H = dup_trunc(dup_add(h, r, K), M, K) u = dup_add(dup_mul(s, G, K), dup_mul(t, H, K), K) b = dup_trunc(dup_sub(u, [K.one], K), M, K) c, d = dup_div(dup_mul(s, b, K), H, K) c = dup_trunc(c, M, K) d = dup_trunc(d, M, K) u = dup_add(dup_mul(t, b, K), dup_mul(c, G, K), K) S = dup_trunc(dup_sub(s, d, K), M, K) T = dup_trunc(dup_sub(t, u, K), M, K) return G, H, S, T
def test_dmp_add(): assert dmp_add([ZZ(1), ZZ(2)], [ZZ(1)], 0, ZZ) == dup_add([ZZ(1), ZZ(2)], [ZZ(1)], ZZ) assert dmp_add([QQ(1, 2), QQ(2, 3)], [QQ(1)], 0, QQ) == dup_add([QQ(1, 2), QQ(2, 3)], [QQ(1)], QQ) assert dmp_add([[[]]], [[[]]], 2, ZZ) == [[[]]] assert dmp_add([[[ZZ(1)]]], [[[]]], 2, ZZ) == [[[ZZ(1)]]] assert dmp_add([[[]]], [[[ZZ(1)]]], 2, ZZ) == [[[ZZ(1)]]] assert dmp_add([[[ZZ(2)]]], [[[ZZ(1)]]], 2, ZZ) == [[[ZZ(3)]]] assert dmp_add([[[ZZ(1)]]], [[[ZZ(2)]]], 2, ZZ) == [[[ZZ(3)]]] assert dmp_add([[[]]], [[[]]], 2, QQ) == [[[]]] assert dmp_add([[[QQ(1, 2)]]], [[[]]], 2, QQ) == [[[QQ(1, 2)]]] assert dmp_add([[[]]], [[[QQ(1, 2)]]], 2, QQ) == [[[QQ(1, 2)]]] assert dmp_add([[[QQ(2, 7)]]], [[[QQ(1, 7)]]], 2, QQ) == [[[QQ(3, 7)]]] assert dmp_add([[[QQ(1, 7)]]], [[[QQ(2, 7)]]], 2, QQ) == [[[QQ(3, 7)]]]
def dup_transform(f, p, q, K): """ Evaluate functional transformation ``q**n * f(p/q)`` in ``K[x]``. Examples ======== >>> from sympy.polys import ring, ZZ >>> R, x = ring("x", ZZ) >>> R.dup_transform(x**2 - 2*x + 1, x**2 + 1, x - 1) x**4 - 2*x**3 + 5*x**2 - 4*x + 4 """ if not f: return [] n = len(f) - 1 h, Q = [f[0]], [[K.one]] for i in range(0, n): Q.append(dup_mul(Q[-1], q, K)) for c, q in zip(f[1:], Q[1:]): h = dup_mul(h, p, K) q = dup_mul_ground(q, c, K) h = dup_add(h, q, K) return h
def dup_transform(f, p, q, K): """ Evaluate functional transformation ``q**n * f(p/q)`` in ``K[x]``. Examples ======== >>> from sympy.polys.domains import ZZ >>> from sympy.polys.densetools import dup_transform >>> f = ZZ.map([1, -2, 1]) >>> p = ZZ.map([1, 0, 1]) >>> q = ZZ.map([1, -1]) >>> dup_transform(f, p, q, ZZ) [1, -2, 5, -4, 4] """ if not f: return [] n = dup_degree(f) h, Q = [f[0]], [[K.one]] for i in xrange(0, n): Q.append(dup_mul(Q[-1], q, K)) for c, q in zip(f[1:], Q[1:]): h = dup_mul(h, p, K) q = dup_mul_ground(q, c, K) h = dup_add(h, q, K) return h
def test_dmp_add(): assert dmp_add([ZZ(1),ZZ(2)], [ZZ(1)], 0, ZZ) == \ dup_add([ZZ(1),ZZ(2)], [ZZ(1)], ZZ) assert dmp_add([QQ(1,2),QQ(2,3)], [QQ(1)], 0, QQ) == \ dup_add([QQ(1,2),QQ(2,3)], [QQ(1)], QQ) assert dmp_add([[[]]], [[[]]], 2, ZZ) == [[[]]] assert dmp_add([[[ZZ(1)]]], [[[]]], 2, ZZ) == [[[ZZ(1)]]] assert dmp_add([[[]]], [[[ZZ(1)]]], 2, ZZ) == [[[ZZ(1)]]] assert dmp_add([[[ZZ(2)]]], [[[ZZ(1)]]], 2, ZZ) == [[[ZZ(3)]]] assert dmp_add([[[ZZ(1)]]], [[[ZZ(2)]]], 2, ZZ) == [[[ZZ(3)]]] assert dmp_add([[[]]], [[[]]], 2, QQ) == [[[]]] assert dmp_add([[[QQ(1,2)]]], [[[]]], 2, QQ) == [[[QQ(1,2)]]] assert dmp_add([[[]]], [[[QQ(1,2)]]], 2, QQ) == [[[QQ(1,2)]]] assert dmp_add([[[QQ(2,7)]]], [[[QQ(1,7)]]], 2, QQ) == [[[QQ(3,7)]]] assert dmp_add([[[QQ(1,7)]]], [[[QQ(2,7)]]], 2, QQ) == [[[QQ(3,7)]]]
def dup_jacobi(n, a, b, K): """Low-level implementation of Jacobi polynomials. """ seq = [[K.one], [(a + b + K(2))/K(2), (a - b)/K(2)]] for i in range(2, n + 1): den = K(i)*(a + b + i)*(a + b + K(2)*i - K(2)) f0 = (a + b + K(2)*i - K.one) * (a*a - b*b) / (K(2)*den) f1 = (a + b + K(2)*i - K.one) * (a + b + K(2)*i - K(2)) * (a + b + K(2)*i) / (K(2)*den) f2 = (a + i - K.one)*(b + i - K.one)*(a + b + K(2)*i) / den p0 = dup_mul_ground(seq[-1], f0, K) p1 = dup_mul_ground(dup_lshift(seq[-1], 1, K), f1, K) p2 = dup_mul_ground(seq[-2], f2, K) seq.append(dup_sub(dup_add(p0, p1, K), p2, K)) return seq[n]
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_quo(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_quo_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 add(f, g): dom, per, F, G, mod = f.unify(g) return per(dup_add(F, G, dom))
def test_dup_add(): assert dup_add([], [], ZZ) == [] assert dup_add([ZZ(1)], [], ZZ) == [ZZ(1)] assert dup_add([], [ZZ(1)], ZZ) == [ZZ(1)] assert dup_add([ZZ(1)], [ZZ(1)], ZZ) == [ZZ(2)] assert dup_add([ZZ(1)], [ZZ(2)], ZZ) == [ZZ(3)] assert dup_add([ZZ(1),ZZ(2)], [ZZ(1)], ZZ) == [ZZ(1),ZZ(3)] assert dup_add([ZZ(1)], [ZZ(1),ZZ(2)], ZZ) == [ZZ(1),ZZ(3)] assert dup_add([ZZ(1),ZZ(2),ZZ(3)], [ZZ(8),ZZ(9),ZZ(10)], ZZ) == [ZZ(9),ZZ(11),ZZ(13)] assert dup_add([], [], QQ) == [] assert dup_add([QQ(1,2)], [], QQ) == [QQ(1,2)] assert dup_add([], [QQ(1,2)], QQ) == [QQ(1,2)] assert dup_add([QQ(1,4)], [QQ(1,4)], QQ) == [QQ(1,2)] assert dup_add([QQ(1,4)], [QQ(1,2)], QQ) == [QQ(3,4)] assert dup_add([QQ(1,2),QQ(2,3)], [QQ(1)], QQ) == [QQ(1,2),QQ(5,3)] assert dup_add([QQ(1)], [QQ(1,2),QQ(2,3)], QQ) == [QQ(1,2),QQ(5,3)] assert dup_add([QQ(1,7),QQ(2,7),QQ(3,7)], [QQ(8,7),QQ(9,7),QQ(10,7)], QQ) == [QQ(9,7),QQ(11,7),QQ(13,7)]
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_quo(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_quo_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