def dmp_zz_wang_lead_coeffs(f, T, cs, E, H, A, u, K): """Wang/EEZ: Compute correct leading coefficients. """ C, J, v = [], [0]*len(E), u-1 for h in H: c = dmp_one(v, K) d = dup_LC(h, K)*cs for i in reversed(xrange(len(E))): k, e, (t, _) = 0, E[i], T[i] while not (d % e): d, k = d//e, k+1 if k != 0: c, J[i] = dmp_mul(c, dmp_pow(t, k, v, K), v, K), 1 C.append(c) if any([ not j for j in J ]): raise ExtraneousFactors # pragma: no cover CC, HH = [], [] for c, h in zip(C, H): d = dmp_eval_tail(c, A, v, K) lc = dup_LC(h, K) if K.is_one(cs): cc = lc//d else: g = K.gcd(lc, d) d, cc = d//g, lc//g h, cs = dup_mul_ground(h, d, K), cs//d c = dmp_mul_ground(c, cc, v, K) CC.append(c) HH.append(h) if K.is_one(cs): return f, HH, CC CCC, HHH = [], [] for c, h in zip(CC, HH): CCC.append(dmp_mul_ground(c, cs, v, K)) HHH.append(dmp_mul_ground(h, cs, 0, K)) f = dmp_mul_ground(f, cs**(len(H)-1), u, K) return f, HHH, CCC
def dmp_zz_wang_hensel_lifting(f, H, LC, A, p, u, K): """Wang/EEZ: Parallel Hensel lifting algorithm. """ S, n, v = [f], len(A), u-1 H = list(H) for i, a in enumerate(reversed(A[1:])): s = dmp_eval_in(S[0], a, n-i, u-i, K) S.insert(0, dmp_ground_trunc(s, p, v-i, K)) d = max(dmp_degree_list(f, u)[1:]) for j, s, a in zip(xrange(2, n+2), S, A): G, w = list(H), j-1 I, J = A[:j-2], A[j-1:] for i, (h, lc) in enumerate(zip(H, LC)): lc = dmp_ground_trunc(dmp_eval_tail(lc, J, v, K), p, w-1, K) H[i] = [lc] + dmp_raise(h[1:], 1, w-1, K) m = dmp_nest([K.one, -a], w, K) M = dmp_one(w, K) c = dmp_sub(s, dmp_expand(H, w, K), w, K) dj = dmp_degree_in(s, w, w) for k in xrange(0, dj): if dmp_zero_p(c, w): break M = dmp_mul(M, m, w, K) C = dmp_diff_eval_in(c, k+1, a, w, w, K) if not dmp_zero_p(C, w-1): C = dmp_quo_ground(C, K.factorial(k+1), w-1, K) T = dmp_zz_diophantine(G, C, I, d, p, w-1, K) for i, (h, t) in enumerate(zip(H, T)): h = dmp_add_mul(h, dmp_raise(t, 1, w-1, K), M, w, K) H[i] = dmp_ground_trunc(h, p, w, K) h = dmp_sub(s, dmp_expand(H, w, K), w, K) c = dmp_ground_trunc(h, p, w, K) if dmp_expand(H, u, K) != f: raise ExtraneousFactors # pragma: no cover else: return H
def dmp_zz_wang_test_points(f, T, ct, A, u, K): """Wang/EEZ: Test evaluation points for suitability. """ if not dmp_eval_tail(dmp_LC(f, K), A, u-1, K): raise EvaluationFailed('no luck') g = dmp_eval_tail(f, A, u, K) if not dup_sqf_p(g, K): raise EvaluationFailed('no luck') c, h = dup_primitive(g, K) if K.is_negative(dup_LC(h, K)): c, h = -c, dup_neg(h, K) v = u-1 E = [ dmp_eval_tail(t, A, v, K) for t, _ in T ] D = dmp_zz_wang_non_divisors(E, c, ct, K) if D is not None: return c, h, E else: raise EvaluationFailed('no luck')
def test_dmp_eval_tail(): assert dmp_eval_tail([[]], [1], 1, ZZ) == [] assert dmp_eval_tail([[[]]], [1], 2, ZZ) == [[]] assert dmp_eval_tail([[[]]], [1, 2], 2, ZZ) == [] assert dmp_eval_tail(f_0, [], 2, ZZ) == f_0 assert dmp_eval_tail(f_0, [1, -17, 8], 2, ZZ) == 84496 assert dmp_eval_tail(f_0, [-17, 8], 2, ZZ) == [-1409, 3, 85902] assert dmp_eval_tail(f_0, [8], 2, ZZ) == [[83, 2], [3], [302, 81, 1]] assert dmp_eval_tail(f_1, [-17, 8], 2, ZZ) == [-136, 15699, 9166, -27144] assert dmp_eval_tail( f_2, [-12, 3], 2, ZZ) == [-1377, 0, -702, -1224, 0, -624] assert dmp_eval_tail( f_3, [-12, 3], 2, ZZ) == [144, 82, -5181, -28872, -14868, -540] assert dmp_eval_tail( f_4, [25, -1], 2, ZZ) == [152587890625, 9765625, -59605407714843750, -3839159765625, -1562475, 9536712644531250, 610349546750, -4, 24414375000, 1562520] assert dmp_eval_tail(f_5, [25, -1], 2, ZZ) == [-1, -78, -2028, -17576] assert dmp_eval_tail(f_6, [0, 2, 4], 3, ZZ) == [5040, 0, 0, 4480]
def test_dmp_eval_tail(): assert dmp_eval_tail([[]], [1], 1, ZZ) == [] assert dmp_eval_tail([[[]]], [1], 2, ZZ) == [[]] assert dmp_eval_tail([[[]]], [1, 2], 2, ZZ) == [] assert dmp_eval_tail(f_0, [], 2, ZZ) == f_0 assert dmp_eval_tail(f_0, [1, -17, 8], 2, ZZ) == 84496 assert dmp_eval_tail(f_0, [-17, 8], 2, ZZ) == [-1409, 3, 85902] assert dmp_eval_tail(f_0, [8], 2, ZZ) == [[83, 2], [3], [302, 81, 1]] assert dmp_eval_tail(f_1, [-17, 8], 2, ZZ) == [-136, 15699, 9166, -27144] assert dmp_eval_tail(f_2, [-12, 3], 2, ZZ) == [-1377, 0, -702, -1224, 0, -624] assert dmp_eval_tail(f_3, [-12, 3], 2, ZZ) == [144, 82, -5181, -28872, -14868, -540] assert dmp_eval_tail(f_4, [25, -1], 2, ZZ) == [ 152587890625, 9765625, -59605407714843750, -3839159765625, -1562475, 9536712644531250, 610349546750, -4, 24414375000, 1562520 ] assert dmp_eval_tail(f_5, [25, -1], 2, ZZ) == [-1, -78, -2028, -17576] assert dmp_eval_tail(f_6, [0, 2, 4], 3, ZZ) == [5040, 0, 0, 4480]
def test_dmp_zz_wang(): p = ZZ(nextprime(dmp_zz_mignotte_bound(w_1, 2, ZZ))) assert p == ZZ(6291469) t_1, k_1, e_1 = dmp_normal([[1], []], 1, ZZ), 1, ZZ(-14) t_2, k_2, e_2 = dmp_normal([[1, 0]], 1, ZZ), 2, ZZ(3) t_3, k_3, e_3 = dmp_normal([[1], [1, 0]], 1, ZZ), 2, ZZ(-11) t_4, k_4, e_4 = dmp_normal([[1], [-1, 0]], 1, ZZ), 1, ZZ(-17) T = [t_1, t_2, t_3, t_4] K = [k_1, k_2, k_3, k_4] E = [e_1, e_2, e_3, e_4] T = zip(T, K) A = [ZZ(-14), ZZ(3)] S = dmp_eval_tail(w_1, A, 2, ZZ) cs, s = dup_primitive(S, ZZ) assert cs == 1 and s == S == \ dup_normal([1036728, 915552, 55748, 105621, -17304, -26841, -644], ZZ) assert dmp_zz_wang_non_divisors(E, cs, 4, ZZ) == [7, 3, 11, 17] assert dup_sqf_p(s, ZZ) and dup_degree(s) == dmp_degree(w_1, 2) _, H = dup_zz_factor_sqf(s, ZZ) h_1 = dup_normal([44, 42, 1], ZZ) h_2 = dup_normal([126, -9, 28], ZZ) h_3 = dup_normal([187, 0, -23], ZZ) assert H == [h_1, h_2, h_3] lc_1 = dmp_normal([[-4], [-4, 0]], 1, ZZ) lc_2 = dmp_normal([[-1, 0, 0], []], 1, ZZ) lc_3 = dmp_normal([[1], [], [-1, 0, 0]], 1, ZZ) LC = [lc_1, lc_2, lc_3] assert dmp_zz_wang_lead_coeffs(w_1, T, cs, E, H, A, 2, ZZ) == (w_1, H, LC) H_1 = [ dmp_normal(t, 0, ZZ) for t in [[44L, 42L, 1L], [126L, -9L, 28L], [187L, 0L, -23L]] ] H_2 = [ dmp_normal(t, 1, ZZ) for t in [[[-4, -12], [-3, 0], [1]], [[-9, 0], [-9], [-2, 0]], [[1, 0, -9], [], [1, -9]]] ] H_3 = [ dmp_normal(t, 1, ZZ) for t in [[[-4, -12], [-3, 0], [1]], [[-9, 0], [-9], [-2, 0]], [[1, 0, -9], [], [1, -9]]] ] c_1 = dmp_normal([-70686, -5863, -17826, 2009, 5031, 74], 0, ZZ) c_2 = dmp_normal( [[9, 12, -45, -108, -324], [18, -216, -810, 0], [2, 9, -252, -288, -945], [-30, -414, 0], [2, -54, -3, 81], [12, 0]], 1, ZZ) c_3 = dmp_normal( [[-36, -108, 0], [-27, -36, -108], [-8, -42, 0], [-6, 0, 9], [2, 0]], 1, ZZ) T_1 = [dmp_normal(t, 0, ZZ) for t in [[-3, 0], [-2], [1]]] T_2 = [dmp_normal(t, 1, ZZ) for t in [[[-1, 0], []], [[-3], []], [[-6]]]] T_3 = [dmp_normal(t, 1, ZZ) for t in [[[]], [[]], [[-1]]]] assert dmp_zz_diophantine(H_1, c_1, [], 5, p, 0, ZZ) == T_1 assert dmp_zz_diophantine(H_2, c_2, [ZZ(-14)], 5, p, 1, ZZ) == T_2 assert dmp_zz_diophantine(H_3, c_3, [ZZ(-14)], 5, p, 1, ZZ) == T_3 factors = dmp_zz_wang_hensel_lifting(w_1, H, LC, A, p, 2, ZZ) assert dmp_expand(factors, 2, ZZ) == w_1
def test_dmp_zz_wang(): p = ZZ(nextprime(dmp_zz_mignotte_bound(w_1, 2, ZZ))) assert p == ZZ(6291469) t_1, k_1, e_1 = dmp_normal([[1],[]], 1, ZZ), 1, ZZ(-14) t_2, k_2, e_2 = dmp_normal([[1, 0]], 1, ZZ), 2, ZZ(3) t_3, k_3, e_3 = dmp_normal([[1],[ 1, 0]], 1, ZZ), 2, ZZ(-11) t_4, k_4, e_4 = dmp_normal([[1],[-1, 0]], 1, ZZ), 1, ZZ(-17) T = [t_1, t_2, t_3, t_4] K = [k_1, k_2, k_3, k_4] E = [e_1, e_2, e_3, e_4] T = zip(T, K) A = [ZZ(-14), ZZ(3)] S = dmp_eval_tail(w_1, A, 2, ZZ) cs, s = dup_primitive(S, ZZ) assert cs == 1 and s == S == \ dup_normal([1036728, 915552, 55748, 105621, -17304, -26841, -644], ZZ) assert dmp_zz_wang_non_divisors(E, cs, 4, ZZ) == [7, 3, 11, 17] assert dup_sqf_p(s, ZZ) and dup_degree(s) == dmp_degree(w_1, 2) _, H = dup_zz_factor_sqf(s, ZZ) h_1 = dup_normal([44, 42, 1], ZZ) h_2 = dup_normal([126, -9, 28], ZZ) h_3 = dup_normal([187, 0, -23], ZZ) assert H == [h_1, h_2, h_3] lc_1 = dmp_normal([[-4], [-4,0]], 1, ZZ) lc_2 = dmp_normal([[-1,0,0], []], 1, ZZ) lc_3 = dmp_normal([[1], [], [-1,0,0]], 1, ZZ) LC = [lc_1, lc_2, lc_3] assert dmp_zz_wang_lead_coeffs(w_1, T, cs, E, H, A, 2, ZZ) == (w_1, H, LC) H_1 = [ dmp_normal(t, 0, ZZ) for t in [[44L,42L,1L],[126L,-9L,28L],[187L,0L,-23L]] ] H_2 = [ dmp_normal(t, 1, ZZ) for t in [[[-4,-12],[-3,0],[1]],[[-9,0],[-9],[-2,0]],[[1,0,-9],[],[1,-9]]] ] H_3 = [ dmp_normal(t, 1, ZZ) for t in [[[-4,-12],[-3,0],[1]],[[-9,0],[-9],[-2,0]],[[1,0,-9],[],[1,-9]]] ] c_1 = dmp_normal([-70686,-5863,-17826,2009,5031,74], 0, ZZ) c_2 = dmp_normal([[9,12,-45,-108,-324],[18,-216,-810,0],[2,9,-252,-288,-945],[-30,-414,0],[2,-54,-3,81],[12,0]], 1, ZZ) c_3 = dmp_normal([[-36,-108,0],[-27,-36,-108],[-8,-42,0],[-6,0,9],[2,0]], 1, ZZ) T_1 = [ dmp_normal(t, 0, ZZ) for t in [[-3,0],[-2],[1]] ] T_2 = [ dmp_normal(t, 1, ZZ) for t in [[[-1,0],[]],[[-3],[]],[[-6]]] ] T_3 = [ dmp_normal(t, 1, ZZ) for t in [[[]],[[]],[[-1]]] ] assert dmp_zz_diophantine(H_1, c_1, [], 5, p, 0, ZZ) == T_1 assert dmp_zz_diophantine(H_2, c_2, [ZZ(-14)], 5, p, 1, ZZ) == T_2 assert dmp_zz_diophantine(H_3, c_3, [ZZ(-14)], 5, p, 1, ZZ) == T_3 factors = dmp_zz_wang_hensel_lifting(w_1, H, LC, A, p, 2, ZZ) assert dmp_expand(factors, 2, ZZ) == w_1