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_trial_division(f, factors, u, K): """Determine multiplicities of factors using trial division. """ result = [] for factor in factors: k = 0 while True: q, r = dmp_div(f, factor, u, K) if dmp_zero_p(r, u): f, k = q, k+1 else: break result.append((factor, k)) return _sort_factors(result)
def dmp_zz_factor(f, u, K): """ Factor (non square-free) polynomials in `Z[X]`. Given a multivariate polynomial `f` in `Z[x]` computes its complete factorization `f_1, ..., f_n` into irreducibles over integers:: f = content(f) f_1**k_1 ... f_n**k_n The factorization is computed by reducing the input polynomial into a primitive square-free polynomial and factoring it using Enhanced Extended Zassenhaus (EEZ) algorithm. Trial division is used to recover the multiplicities of factors. The result is returned as a tuple consisting of:: (content(f), [(f_1, k_1), ..., (f_n, k_n)) Consider polynomial `f = 2*(x**2 - y**2)`:: >>> from sympy.polys.factortools import dmp_zz_factor >>> from sympy.polys.domains import ZZ >>> dmp_zz_factor([[2], [], [-2, 0, 0]], 1, ZZ) (2, [([[1], [-1, 0]], 1), ([[1], [1, 0]], 1)]) In result we got the following factorization:: f = 2 (x - y) (x + y) **References** 1. [Gathen99]_ """ if not u: return dup_zz_factor(f, K) if dmp_zero_p(f, u): return K.zero, [] cont, g = dmp_ground_primitive(f, u, K) if dmp_ground_LC(g, u, K) < 0: cont, g = -cont, dmp_neg(g, u, K) if all([ d <= 0 for d in dmp_degree_list(g, u) ]): return cont, [] G, g = dmp_primitive(g, u, K) factors = [] if dmp_degree(g, u) > 0: g = dmp_sqf_part(g, u, K) H = dmp_zz_wang(g, u, K) for h in H: k = 0 while True: q, r = dmp_div(f, h, u, K) if dmp_zero_p(r, u): f, k = q, k+1 else: break factors.append((h, k)) for g, k in dmp_zz_factor(G, u-1, K)[1]: factors.insert(0, ([g], k)) return cont, _sort_factors(factors)
def dmp_zz_heu_gcd(f, g, u, K): """ Heuristic polynomial GCD in ``Z[X]``. Given univariate polynomials ``f`` and ``g`` in ``Z[X]``, returns their GCD and cofactors, i.e. polynomials ``h``, ``cff`` and ``cfg`` such that:: h = gcd(f, g), cff = quo(f, h) and cfg = quo(g, h) The algorithm is purely heuristic which means it may fail to compute the GCD. This will be signaled by raising an exception. In this case you will need to switch to another GCD method. The algorithm computes the polynomial GCD by evaluating polynomials f and g at certain points and computing (fast) integer GCD of those evaluations. The polynomial GCD is recovered from the integer image by interpolation. The evaluation proces reduces f and g variable by variable into a large integer. The final step is to verify if the interpolated polynomial is the correct GCD. This gives cofactors of the input polynomials as a side effect. **Examples** >>> from sympy.polys.domains import ZZ >>> from sympy.polys.euclidtools import dmp_zz_heu_gcd >>> f = ZZ.map([[1], [2, 0], [1, 0, 0]]) >>> g = ZZ.map([[1], [1, 0], []]) >>> dmp_zz_heu_gcd(f, g, 1, ZZ) ([[1], [1, 0]], [[1], [1, 0]], [[1], []]) **References** 1. [Liao95]_ """ if not u: return dup_zz_heu_gcd(f, g, K) result = _dmp_rr_trivial_gcd(f, g, u, K) if result is not None: return result df = dmp_degree(f, u) dg = dmp_degree(g, u) gcd, f, g = dmp_ground_extract(f, g, u, K) f_norm = dmp_max_norm(f, u, K) g_norm = dmp_max_norm(g, u, K) B = 2*min(f_norm, g_norm) + 29 x = max(min(B, 99*K.sqrt(B)), 2*min(f_norm // abs(dmp_ground_LC(f, u, K)), g_norm // abs(dmp_ground_LC(g, u, K))) + 2) for i in xrange(0, HEU_GCD_MAX): ff = dmp_eval(f, x, u, K) gg = dmp_eval(g, x, u, K) v = u - 1 if not (dmp_zero_p(ff, v) or dmp_zero_p(gg, v)): h, cff, cfg = dmp_zz_heu_gcd(ff, gg, v, K) h = _dmp_zz_gcd_interpolate(h, x, v, K) h = dmp_ground_primitive(h, u, K)[1] cff_, r = dmp_div(f, h, u, K) if dmp_zero_p(r, u): cfg_, r = dmp_div(g, h, u, K) if dmp_zero_p(r, u): h = dmp_mul_ground(h, gcd, u, K) return h, cff_, cfg_ cff = _dmp_zz_gcd_interpolate(cff, x, v, K) h, r = dmp_div(f, cff, u, K) if dmp_zero_p(r, u): cfg_, r = dmp_div(g, h, u, K) if dmp_zero_p(r, u): h = dmp_mul_ground(h, gcd, u, K) return h, cff, cfg_ cfg = _dmp_zz_gcd_interpolate(cfg, x, v, K) h, r = dmp_div(g, cfg, u, K) if dmp_zero_p(r, u): cff_, r = dmp_div(f, h, u, K) if dmp_zero_p(r, u): h = dmp_mul_ground(h, gcd, u, K) return h, cff_, cfg x = 73794*x * K.sqrt(K.sqrt(x)) // 27011 raise HeuristicGCDFailed('no luck')
def div(f, g): """Polynomial division with remainder of `f` and `g`. """ lev, dom, per, F, G = f.unify(g) q, r = dmp_div(F, G, lev, dom) return per(q), per(r)
def dmp_zz_factor(f, u, K): """ Factor (non square-free) polynomials in `Z[X]`. Given a multivariate polynomial `f` in `Z[x]` computes its complete factorization `f_1, ..., f_n` into irreducibles over integers:: f = content(f) f_1**k_1 ... f_n**k_n The factorization is computed by reducing the input polynomial into a primitive square-free polynomial and factoring it using Enhanced Extended Zassenhaus (EEZ) algorithm. Trial division is used to recover the multiplicities of factors. The result is returned as a tuple consisting of:: (content(f), [(f_1, k_1), ..., (f_n, k_n)) Consider polynomial `f = 2*(x**2 - y**2)`:: >>> from sympy.polys.factortools import dmp_zz_factor >>> from sympy.polys.domains import ZZ >>> dmp_zz_factor([[2], [], [-2, 0, 0]], 1, ZZ) (2, [([[1], [-1, 0]], 1), ([[1], [1, 0]], 1)]) In result we got the following factorization:: f = 2 (x - y) (x + y) **References** 1. [Gathen99]_ """ if not u: return dup_zz_factor(f, K) if dmp_zero_p(f, u): return K.zero, [] cont, g = dmp_ground_primitive(f, u, K) if dmp_ground_LC(g, u, K) < 0: cont, g = -cont, dmp_neg(g, u, K) if all(d <= 0 for d in dmp_degree_list(g, u)): return cont, [] G, g = dmp_primitive(g, u, K) factors = [] if dmp_degree(g, u) > 0: g = dmp_sqf_part(g, u, K) H = dmp_zz_wang(g, u, K) for h in H: k = 0 while True: q, r = dmp_div(f, h, u, K) if dmp_zero_p(r, u): f, k = q, k + 1 else: break factors.append((h, k)) for g, k in dmp_zz_factor(G, u - 1, K)[1]: factors.insert(0, ([g], k)) return cont, _sort_factors(factors)
def dmp_zz_heu_gcd(f, g, u, K): """ Heuristic polynomial GCD in ``Z[X]``. Given univariate polynomials ``f`` and ``g`` in ``Z[X]``, returns their GCD and cofactors, i.e. polynomials ``h``, ``cff`` and ``cfg`` such that:: h = gcd(f, g), cff = quo(f, h) and cfg = quo(g, h) The algorithm is purely heuristic which means it may fail to compute the GCD. This will be signaled by raising an exception. In this case you will need to switch to another GCD method. The algorithm computes the polynomial GCD by evaluating polynomials f and g at certain points and computing (fast) integer GCD of those evaluations. The polynomial GCD is recovered from the integer image by interpolation. The evaluation proces reduces f and g variable by variable into a large integer. The final step is to verify if the interpolated polynomial is the correct GCD. This gives cofactors of the input polynomials as a side effect. **Examples** >>> from sympy.polys.domains import ZZ >>> from sympy.polys.euclidtools import dmp_zz_heu_gcd >>> f = ZZ.map([[1], [2, 0], [1, 0, 0]]) >>> g = ZZ.map([[1], [1, 0], []]) >>> dmp_zz_heu_gcd(f, g, 1, ZZ) ([[1], [1, 0]], [[1], [1, 0]], [[1], []]) **References** 1. [Liao95]_ """ if not u: return dup_zz_heu_gcd(f, g, K) result = _dmp_rr_trivial_gcd(f, g, u, K) if result is not None: return result df = dmp_degree(f, u) dg = dmp_degree(g, u) gcd, f, g = dmp_ground_extract(f, g, u, K) f_norm = dmp_max_norm(f, u, K) g_norm = dmp_max_norm(g, u, K) B = 2 * min(f_norm, g_norm) + 29 x = max( min(B, 99 * K.sqrt(B)), 2 * min(f_norm // abs(dmp_ground_LC(f, u, K)), g_norm // abs(dmp_ground_LC(g, u, K))) + 2) for i in xrange(0, HEU_GCD_MAX): ff = dmp_eval(f, x, u, K) gg = dmp_eval(g, x, u, K) v = u - 1 if not (dmp_zero_p(ff, v) or dmp_zero_p(gg, v)): h, cff, cfg = dmp_zz_heu_gcd(ff, gg, v, K) h = _dmp_zz_gcd_interpolate(h, x, v, K) h = dmp_ground_primitive(h, u, K)[1] cff_, r = dmp_div(f, h, u, K) if dmp_zero_p(r, u): cfg_, r = dmp_div(g, h, u, K) if dmp_zero_p(r, u): h = dmp_mul_ground(h, gcd, u, K) return h, cff_, cfg_ cff = _dmp_zz_gcd_interpolate(cff, x, v, K) h, r = dmp_div(f, cff, u, K) if dmp_zero_p(r, u): cfg_, r = dmp_div(g, h, u, K) if dmp_zero_p(r, u): h = dmp_mul_ground(h, gcd, u, K) return h, cff, cfg_ cfg = _dmp_zz_gcd_interpolate(cfg, x, v, K) h, r = dmp_div(g, cfg, u, K) if dmp_zero_p(r, u): cff_, r = dmp_div(f, h, u, K) if dmp_zero_p(r, u): h = dmp_mul_ground(h, gcd, u, K) return h, cff_, cfg x = 73794 * x * K.sqrt(K.sqrt(x)) // 27011 raise HeuristicGCDFailed('no luck')
def div(f, g): """Polynomial division with remainder of `f` and `g`. """ lev, dom, per, F, G = f.unify(g) q, r = dmp_div(F, G, lev, dom) return per(q), per(r)