def dup_inner_gcd(f, g, K): """ Computes polynomial GCD and cofactors of ``f`` and ``g`` in ``K[x]``. 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 dup_inner_gcd >>> f = ZZ.map([1, 0, -1]) >>> g = ZZ.map([1, -3, 2]) >>> dup_inner_gcd(f, g, ZZ) ([1, -1], [1, 1], [1, -2]) """ if K.has_Field or not K.is_Exact: if K.is_QQ and query('USE_HEU_GCD'): try: return dup_qq_heu_gcd(f, g, K) except HeuristicGCDFailed: pass return dup_ff_prs_gcd(f, g, K) else: if K.is_ZZ and query('USE_HEU_GCD'): try: return dup_zz_heu_gcd(f, g, K) except HeuristicGCDFailed: pass return dup_rr_prs_gcd(f, g, K)
def dmp_resultant(f, g, u, K, includePRS=False): """ Computes resultant of two polynomials in `K[X]`. 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 >>> R.dmp_resultant(f, g) -3*y**10 - 12*y**7 + y**6 - 54*y**4 + 8*y**3 + 729*y**2 - 216*y + 16 """ if not u: return dup_resultant(f, g, K, includePRS=includePRS) if includePRS: return dmp_prs_resultant(f, g, u, K) if K.has_Field: if K.is_QQ and query('USE_COLLINS_RESULTANT'): return dmp_qq_collins_resultant(f, g, u, K) else: if K.is_ZZ and query('USE_COLLINS_RESULTANT'): return dmp_zz_collins_resultant(f, g, u, K) return dmp_prs_resultant(f, g, u, K)[0]
def dmp_resultant(f, g, u, K): """ Computes resultant of two polynomials in ``K[X]``. **Examples** >>> from sympy.polys.domains import ZZ >>> from sympy.polys.euclidtools import dmp_resultant >>> f = ZZ.map([[3, 0], [], [-1, 0, 0, -4]]) >>> g = ZZ.map([[1], [1, 0, 0, 0], [-9]]) >>> dmp_resultant(f, g, 1, ZZ) [-3, 0, 0, -12, 1, 0, -54, 8, 729, -216, 16] """ if not u: return dup_resultant(f, g, K) if K.has_Field: if K.is_QQ and query('USE_COLLINS_RESULTANT'): return dmp_qq_collins_resultant(f, g, u, K) else: if K.is_ZZ and query('USE_COLLINS_RESULTANT'): return dmp_zz_collins_resultant(f, g, u, K) return dmp_prs_resultant(f, g, u, K)[0]
def dup_zz_factor_sqf(f, K): """Factor square-free (non-primitive) polyomials in `Z[x]`. """ cont, g = dup_primitive(f, K) n = dup_degree(g) if dup_LC(g, K) < 0: cont, g = -cont, dup_neg(g, K) if n <= 0: return cont, [] elif n == 1: return cont, [(g, 1)] if query('USE_IRREDUCIBLE_IN_FACTOR'): if dup_zz_irreducible_p(g, K): return cont, [(g, 1)] factors = None if query('USE_CYCLOTOMIC_FACTOR'): factors = dup_zz_cyclotomic_factor(g, K) if factors is None: factors = dup_zz_zassenhaus(g, K) return cont, _sort_factors(factors, multiple=False)
def dup_inner_gcd(f, g, K): """ Computes polynomial GCD and cofactors of `f` and `g` in `K[x]`. Returns ``(h, cff, cfg)`` such that ``a = gcd(f, g)``, ``cff = quo(f, h)``, and ``cfg = quo(g, h)``. Examples ======== >>> from sympy.polys import ring, ZZ >>> R, x = ring("x", ZZ) >>> R.dup_inner_gcd(x**2 - 1, x**2 - 3*x + 2) (x - 1, x + 1, x - 2) """ if K.has_Field or not K.is_Exact: if K.is_QQ and query('USE_HEU_GCD'): try: return dup_qq_heu_gcd(f, g, K) except HeuristicGCDFailed: pass return dup_ff_prs_gcd(f, g, K) else: if K.is_ZZ and query('USE_HEU_GCD'): try: return dup_zz_heu_gcd(f, g, K) except HeuristicGCDFailed: pass return dup_rr_prs_gcd(f, g, K)
def _dmp_inner_gcd(f, g, u, K): """Helper function for `dmp_inner_gcd()`. """ if not K.is_Exact: try: exact = K.get_exact() except DomainError: return dmp_one(u, K), f, g f = dmp_convert(f, u, K, exact) g = dmp_convert(g, u, K, exact) h, cff, cfg = _dmp_inner_gcd(f, g, u, exact) h = dmp_convert(h, u, exact, K) cff = dmp_convert(cff, u, exact, K) cfg = dmp_convert(cfg, u, exact, K) return h, cff, cfg elif K.has_Field: if K.is_QQ and query('USE_HEU_GCD'): try: return dmp_qq_heu_gcd(f, g, u, K) except HeuristicGCDFailed: pass return dmp_ff_prs_gcd(f, g, u, K) else: if K.is_ZZ and query('USE_HEU_GCD'): try: return dmp_zz_heu_gcd(f, g, u, K) except HeuristicGCDFailed: pass return dmp_rr_prs_gcd(f, g, u, K)
def dup_inner_gcd(f, g, K): """ Computes polynomial GCD and cofactors of `f` and `g` in `K[x]`. Returns ``(h, cff, cfg)`` such that ``a = gcd(f, g)``, ``cff = quo(f, h)``, and ``cfg = quo(g, h)``. Examples ======== >>> from sympy.polys import ring, ZZ >>> R, x = ring("x", ZZ) >>> R.dup_inner_gcd(x**2 - 1, x**2 - 3*x + 2) (x - 1, x + 1, x - 2) """ if not K.is_Exact: try: exact = K.get_exact() except DomainError: return [K.one], f, g f = dup_convert(f, K, exact) g = dup_convert(g, K, exact) h, cff, cfg = dup_inner_gcd(f, g, exact) h = dup_convert(h, exact, K) cff = dup_convert(cff, exact, K) cfg = dup_convert(cfg, exact, K) return h, cff, cfg elif K.has_Field: if K.is_QQ and query('USE_HEU_GCD'): try: return dup_qq_heu_gcd(f, g, K) except HeuristicGCDFailed: pass return dup_ff_prs_gcd(f, g, K) else: if K.is_ZZ and query('USE_HEU_GCD'): try: return dup_zz_heu_gcd(f, g, K) except HeuristicGCDFailed: pass return dup_rr_prs_gcd(f, g, K)
def cgb(seq, ring, method=None): if method is None: method = query('cgs_cgb') _cgb_methods = { 'ksw1': _ksw1 'ksw2': _ksw2 'ss': _ss } try: _cgb = _cgb_methods[method] except KeyError: raise ValueError("'%s' is not a valid Comprehensive Groebner bases algorithm (valid are 'ksw1', 'ksw2' and 'ss')" % method) domain, orig = ring.domain, None if not domain.has_Field or not domain.has_assoc_Field: try: orig, ring = ring, ring.clone(domain=domain.get_field()) except DomainError: raise DomainError("can't compute a Comprehensive Groebner basis over %s" % domain) else: seq = [s.set_ring(ring) for s in seq] G = _cgb(seq, ring) if orig is not None: G = [g.clear_denoms()[1].set_ring(orig) for g in G] return G
def gf_factor_sqf(f, p, K, method=None): """ Factor a square-free polynomial ``f`` in ``GF(p)[x]``. Examples ======== >>> from sympy.polys.domains import ZZ >>> from sympy.polys.galoistools import gf_factor_sqf >>> gf_factor_sqf(ZZ.map([3, 2, 4]), 5, ZZ) (3, [[1, 1], [1, 3]]) """ lc, f = gf_monic(f, p, K) if gf_degree(f) < 1: return lc, [] method = method or query("GF_FACTOR_METHOD") if method is not None: factors = _factor_methods[method](f, p, K) else: factors = gf_zassenhaus(f, p, K) return lc, factors
def gf_factor_sqf(f, p, K, method=None): """ Factor a square-free polynomial ``f`` in ``GF(p)[x]``. **Examples** >>> from sympy.polys.domains import ZZ >>> from sympy.polys.galoistools import gf_factor_sqf >>> gf_factor_sqf([3, 2, 4], 5, ZZ) (3, [[1, 1], [1, 3]]) """ lc, f = gf_monic(f, p, K) if gf_degree(f) < 1: return lc, [] method = method or query('GF_FACTOR_METHOD') if method is not None: factors = _factor_methods[method](f, p, K) else: factors = gf_zassenhaus(f, p, K) return lc, factors
def sdp_groebner(f, u, O, K, gens='', verbose=False, method=None): """ Computes Groebner basis for a set of polynomials in `K[X]`. Wrapper around the (default) improved Buchberger and the other algorithms for computing Groebner bases. The choice of algorithm can be changed via ``method`` argument or :func:`setup` from :mod:`sympy.polys.polyconfig`, where ``method`` can be either ``buchberger`` or ``f5b``. """ if method is None: method = query('GB_METHOD') _groebner_methods = { 'buchberger': buchberger, 'f5b': f5b, } try: func = _groebner_methods[method] except KeyError: raise ValueError( "'%s' is not a valid Groebner bases algorithm (valid are 'buchberger' and 'f5b')" % method) else: return func(f, u, O, K, gens, verbose)
def _dmp_inner_gcd(f, g, u, K): """Helper function for `dmp_inner_gcd()`. """ if K.has_Field or not K.is_Exact: if K.is_QQ and query('USE_HEU_GCD'): try: return dmp_qq_heu_gcd(f, g, u, K) except HeuristicGCDFailed: pass return dmp_ff_prs_gcd(f, g, u, K) else: if K.is_ZZ and query('USE_HEU_GCD'): try: return dmp_zz_heu_gcd(f, g, u, K) except HeuristicGCDFailed: pass return dmp_rr_prs_gcd(f, g, u, K)
def sdp_groebner(f, u, O, K, gens='', verbose=False): """ Wrapper around the (default) improved Buchberger and other algorithms for Groebner bases. The choice of algorithm can be changed via >>> from sympy.polys.polyconfig import setup >>> setup('GB_METHOD', 'method') where 'method' can be 'buchberger' or 'f5b'. If an unknown method is provided, the default Buchberger algorithm will be used. """ if query('GB_METHOD') == 'buchberger': return buchberger(f, u, O, K, gens, verbose) elif query('GB_METHOD') == 'f5b': return f5b(f, u, O, K, gens, verbose) else: return buchberger(f, u, O, K, gens, verbose)
def dup_inner_gcd(f, g, K): """ Computes polynomial GCD and cofactors of `f` and `g` in `K[x]`. 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 dup_inner_gcd >>> f = ZZ.map([1, 0, -1]) >>> g = ZZ.map([1, -3, 2]) >>> dup_inner_gcd(f, g, ZZ) ([1, -1], [1, 1], [1, -2]) """ if K.has_Field or not K.is_Exact: if K.is_QQ and query('USE_HEU_GCD'): try: return dup_qq_heu_gcd(f, g, K) except HeuristicGCDFailed: pass return dup_ff_prs_gcd(f, g, K) else: if K.is_ZZ and query('USE_HEU_GCD'): try: return dup_zz_heu_gcd(f, g, K) except HeuristicGCDFailed: pass return dup_rr_prs_gcd(f, g, K)
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_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 groebner(seq, ring, method=None): """ Computes Groebner basis for a set of polynomials in `K[X]`. Wrapper around the (default) improved Buchberger and the other algorithms for computing Groebner bases. The choice of algorithm can be changed via ``method`` argument or :func:`setup` from :mod:`sympy.polys.polyconfig`, where ``method`` can be either ``buchberger`` or ``f5b``. """ if method is None: method = query('groebner') _groebner_methods = { 'buchberger': _buchberger, 'f5b': _f5b, } try: _groebner = _groebner_methods[method] except KeyError: raise ValueError( "'%s' is not a valid Groebner bases algorithm (valid are 'buchberger' and 'f5b')" % method) domain, orig = ring.domain, None if not domain.is_Field or not domain.has_assoc_Field: try: orig, ring = ring, ring.clone(domain=domain.get_field()) except DomainError: raise DomainError("can't compute a Groebner basis over %s" % domain) else: seq = [s.set_ring(ring) for s in seq] G = _groebner(seq, ring) if orig is not None: G = [g.clear_denoms()[1].set_ring(orig) for g in G] return G
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 sdp_groebner(f, u, O, K, gens="", verbose=False, method=None): """ Computes Groebner basis for a set of polynomials in `K[X]`. Wrapper around the (default) improved Buchberger and the other algorithms for computing Groebner bases. The choice of algorithm can be changed via ``method`` argument or :func:`setup` from :mod:`sympy.polys.polyconfig`, where ``method`` can be either ``buchberger`` or ``f5b``. """ if method is None: method = query("GB_METHOD") _groebner_methods = {"buchberger": buchberger, "f5b": f5b} try: func = _groebner_methods[method] except KeyError: raise ValueError("'%s' is not a valid Groebner bases algorithm (valid are 'buchberger' and 'f5b')" % method) else: return func(f, u, O, K, gens, verbose)
def groebner(seq, ring, method=None): """ Computes Groebner basis for a set of polynomials in `K[X]`. Wrapper around the (default) improved Buchberger and the other algorithms for computing Groebner bases. The choice of algorithm can be changed via ``method`` argument or :func:`setup` from :mod:`sympy.polys.polyconfig`, where ``method`` can be either ``buchberger`` or ``f5b``. """ if method is None: method = query('groebner') _groebner_methods = { 'buchberger': _buchberger, 'f5b': _f5b, } try: _groebner = _groebner_methods[method] except KeyError: raise ValueError("'%s' is not a valid Groebner bases algorithm (valid are 'buchberger' and 'f5b')" % method) domain, orig = ring.domain, None if not domain.has_Field or not domain.has_assoc_Field: try: orig, ring = ring, ring.clone(domain=domain.get_field()) except DomainError: raise DomainError("can't compute a Groebner basis over %s" % domain) else: seq = [ s.set_ring(ring) for s in seq ] G = _groebner(seq, ring) if orig is not None: G = [ g.clear_denoms()[1].set_ring(orig) for g in G ] return G
def gf_irreducible_p(f, p, K): """ Test irreducibility of a polynomial ``f`` in ``GF(p)[x]``. **Examples** >>> from sympy.polys.domains import ZZ >>> from sympy.polys.galoistools import gf_irreducible_p >>> gf_irreducible_p([1, 4, 2, 2, 3, 2, 4, 1, 4, 0, 4], 5, ZZ) True >>> gf_irreducible_p([3, 2, 4], 5, ZZ) False """ method = query('GF_IRRED_METHOD') if method is not None: irred = _irred_methods[method](f, p, K) else: irred = gf_irred_p_rabin(f, p, K) return irred
def dmp_zz_wang(f, u, K, mod=None): """ Factor primitive square-free polynomials in `Z[X]`. Given a multivariate polynomial `f` in `Z[x_1,...,x_n]`, which is primitive and square-free in `x_1`, computes factorization of `f` into irreducibles over integers. The procedure is based on Wang's Enhanced Extended Zassenhaus algorithm. The algorithm works by viewing `f` as a univariate polynomial in `Z[x_2,...,x_n][x_1]`, for which an evaluation mapping is computed:: x_2 -> a_2, ..., x_n -> a_n where `a_i`, for `i = 2, ..., n`, are carefully chosen integers. The mapping is used to transform `f` into a univariate polynomial in `Z[x_1]`, which can be factored efficiently using Zassenhaus algorithm. The last step is to lift univariate factors to obtain true multivariate factors. For this purpose a parallel Hensel lifting procedure is used. References ========== 1. [Wang78]_ 2. [Geddes92]_ """ ct, T = dmp_zz_factor(dmp_LC(f, K), u - 1, K) b = dmp_zz_mignotte_bound(f, u, K) p = K(nextprime(b)) if mod is None: if u == 1: mod = 2 else: mod = 1 history, configs, A, r = set([]), [], [K.zero] * u, None try: cs, s, E = dmp_zz_wang_test_points(f, T, ct, A, u, K) _, H = dup_zz_factor_sqf(s, K) r = len(H) if r == 1: return [f] configs = [(s, cs, E, H, A)] except EvaluationFailed: pass eez_num_configs = query('EEZ_NUMBER_OF_CONFIGS') eez_num_tries = query('EEZ_NUMBER_OF_TRIES') eez_mod_step = query('EEZ_MODULUS_STEP') while len(configs) < eez_num_configs: for _ in xrange(eez_num_tries): A = [K(randint(-mod, mod)) for _ in xrange(u)] if tuple(A) not in history: history.add(tuple(A)) else: continue try: cs, s, E = dmp_zz_wang_test_points(f, T, ct, A, u, K) except EvaluationFailed: continue _, H = dup_zz_factor_sqf(s, K) rr = len(H) if r is not None: if rr != r: # pragma: no cover if rr < r: configs, r = [], rr else: continue else: r = rr if r == 1: return [f] configs.append((s, cs, E, H, A)) if len(configs) == eez_num_configs: break else: mod += eez_mod_step s_norm, s_arg, i = None, 0, 0 for s, _, _, _, _ in configs: _s_norm = dup_max_norm(s, K) if s_norm is not None: if _s_norm < s_norm: s_norm = _s_norm s_arg = i else: s_norm = _s_norm i += 1 _, cs, E, H, A = configs[s_arg] try: f, H, LC = dmp_zz_wang_lead_coeffs(f, T, cs, E, H, A, u, K) factors = dmp_zz_wang_hensel_lifting(f, H, LC, A, p, u, K) except ExtraneousFactors: # pragma: no cover if query('EEZ_RESTART_IF_NEEDED'): return dmp_zz_wang(f, u, K, mod + 1) else: raise ExtraneousFactors( "we need to restart algorithm with better parameters") negative, result = 0, [] for f in factors: _, f = dmp_ground_primitive(f, u, K) if K.is_negative(dmp_ground_LC(f, u, K)): f = dmp_neg(f, u, K) result.append(f) return result
def dup_zz_factor(f, K): """ Factor (non square-free) polynomials in `Z[x]`. Given a univariate 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 Zassenhaus 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**4 - 2`:: >>> from sympy.polys.factortools import dup_zz_factor >>> from sympy.polys.domains import ZZ >>> dup_zz_factor([2, 0, 0, 0, -2], ZZ) (2, [([1, -1], 1), ([1, 1], 1), ([1, 0, 1], 1)]) In result we got the following factorization:: f = 2 (x - 1) (x + 1) (x**2 + 1) Note that this is a complete factorization over integers, however over Gaussian integers we can factor the last term. By default, polynomials `x**n - 1` and `x**n + 1` are factored using cyclotomic decomposition to speedup computations. To disable this behaviour set cyclotomic=False. References ========== 1. [Gathen99]_ """ cont, g = dup_primitive(f, K) n = dup_degree(g) if dup_LC(g, K) < 0: cont, g = -cont, dup_neg(g, K) if n <= 0: return cont, [] elif n == 1: return cont, [(g, 1)] if query('USE_IRREDUCIBLE_IN_FACTOR'): if dup_zz_irreducible_p(g, K): return cont, [(g, 1)] g = dup_sqf_part(g, K) H, factors = None, [] if query('USE_CYCLOTOMIC_FACTOR'): H = dup_zz_cyclotomic_factor(g, K) if H is None: H = dup_zz_zassenhaus(g, K) for h in H: k = 0 while True: q, r = dup_div(f, h, K) if not r: f, k = q, k + 1 else: break factors.append((h, k)) return cont, _sort_factors(factors)
def dmp_zz_wang(f, u, K, mod=None): """ Factor primitive square-free polynomials in `Z[X]`. Given a multivariate polynomial `f` in `Z[x_1,...,x_n]`, which is primitive and square-free in `x_1`, computes factorization of `f` into irreducibles over integers. The procedure is based on Wang's Enhanced Extended Zassenhaus algorithm. The algorithm works by viewing `f` as a univariate polynomial in `Z[x_2,...,x_n][x_1]`, for which an evaluation mapping is computed:: x_2 -> a_2, ..., x_n -> a_n where `a_i`, for `i = 2, ..., n`, are carefully chosen integers. The mapping is used to transform `f` into a univariate polynomial in `Z[x_1]`, which can be factored efficiently using Zassenhaus algorithm. The last step is to lift univariate factors to obtain true multivariate factors. For this purpose a parallel Hensel lifting procedure is used. **References** 1. [Wang78]_ 2. [Geddes92]_ """ ct, T = dmp_zz_factor(dmp_LC(f, K), u-1, K) b = dmp_zz_mignotte_bound(f, u, K) p = K(nextprime(b)) if mod is None: if u == 1: mod = 2 else: mod = 1 history, configs, A, r = set([]), [], [K.zero]*u, None try: cs, s, E = dmp_zz_wang_test_points(f, T, ct, A, u, K) _, H = dup_zz_factor_sqf(s, K) r = len(H) if r == 1: return [f] bad_points = set([tuple(A)]) configs = [(s, cs, E, H, A)] except EvaluationFailed: pass eez_num_configs = query('EEZ_NUMBER_OF_CONFIGS') eez_num_tries = query('EEZ_NUMBER_OF_TRIES') eez_mod_step = query('EEZ_MODULUS_STEP') while len(configs) < eez_num_configs: for _ in xrange(eez_num_tries): A = [ K(randint(-mod, mod)) for _ in xrange(u) ] if tuple(A) not in history: history.add(tuple(A)) else: continue try: cs, s, E = dmp_zz_wang_test_points(f, T, ct, A, u, K) except EvaluationFailed: continue _, H = dup_zz_factor_sqf(s, K) rr = len(H) if r is not None: if rr != r: # pragma: no cover if rr < r: configs, r = [], rr else: continue else: r = rr if r == 1: return [f] configs.append((s, cs, E, H, A)) if len(configs) == eez_num_configs: break else: mod += eez_mod_step s_norm, s_arg, i = None, 0, 0 for s, _, _, _, _ in configs: _s_norm = dup_max_norm(s, K) if s_norm is not None: if _s_norm < s_norm: s_norm = _s_norm s_arg = i else: s_norm = _s_norm i += 1 _, cs, E, H, A = configs[s_arg] try: f, H, LC = dmp_zz_wang_lead_coeffs(f, T, cs, E, H, A, u, K) factors = dmp_zz_wang_hensel_lifting(f, H, LC, A, p, u, K) except ExtraneousFactors: # pragma: no cover if query('EEZ_RESTART_IF_NEEDED'): return dmp_zz_wang(f, u, K, mod+1) else: raise ExtraneousFactors("we need to restart algorithm with better parameters") negative, result = 0, [] for f in factors: _, f = dmp_ground_primitive(f, u, K) if K.is_negative(dmp_ground_LC(f, u, K)): f = dmp_neg(f, u, K) result.append(f) return result
def dup_zz_factor(f, K): """ Factor (non square-free) polynomials in `Z[x]`. Given a univariate 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 Zassenhaus 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**4 - 2`:: >>> from sympy.polys.factortools import dup_zz_factor >>> from sympy.polys.domains import ZZ >>> dup_zz_factor([2, 0, 0, 0, -2], ZZ) (2, [([1, -1], 1), ([1, 1], 1), ([1, 0, 1], 1)]) In result we got the following factorization:: f = 2 (x - 1) (x + 1) (x**2 + 1) Note that this is a complete factorization over integers, however over Gaussian integers we can factor the last term. By default, polynomials `x**n - 1` and `x**n + 1` are factored using cyclotomic decomposition to speedup computations. To disable this behaviour set cyclotomic=False. **References** 1. [Gathen99]_ """ cont, g = dup_primitive(f, K) n = dup_degree(g) if dup_LC(g, K) < 0: cont, g = -cont, dup_neg(g, K) if n <= 0: return cont, [] elif n == 1: return cont, [(g, 1)] if query('USE_IRREDUCIBLE_IN_FACTOR'): if dup_zz_irreducible_p(g, K): return cont, [(g, 1)] g = dup_sqf_part(g, K) H, factors = None, [] if query('USE_CYCLOTOMIC_FACTOR'): H = dup_zz_cyclotomic_factor(g, K) if H is None: H = dup_zz_zassenhaus(g, K) for h in H: k = 0 while True: q, r = dup_div(f, h, K) if not r: f, k = q, k+1 else: break factors.append((h, k)) return cont, _sort_factors(factors)
def dup_zz_factor(f, K): """ Factor (non square-free) polynomials in `Z[x]`. Given a univariate 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 Zassenhaus 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)) Examples ======== Consider the polynomial `f = 2*x**4 - 2`:: >>> from sympy.polys import ring, ZZ >>> R, x = ring("x", ZZ) >>> R.dup_zz_factor(2*x**4 - 2) (2, [(x - 1, 1), (x + 1, 1), (x**2 + 1, 1)]) In result we got the following factorization:: f = 2 (x - 1) (x + 1) (x**2 + 1) Note that this is a complete factorization over integers, however over Gaussian integers we can factor the last term. By default, polynomials `x**n - 1` and `x**n + 1` are factored using cyclotomic decomposition to speedup computations. To disable this behaviour set cyclotomic=False. References ========== .. [1] [Gathen99]_ """ cont, g = dup_primitive(f, K) n = dup_degree(g) if dup_LC(g, K) < 0: cont, g = -cont, dup_neg(g, K) if n <= 0: return cont, [] elif n == 1: return cont, [(g, 1)] if query('USE_IRREDUCIBLE_IN_FACTOR'): if dup_zz_irreducible_p(g, K): return cont, [(g, 1)] g = dup_sqf_part(g, K) H = None if query('USE_CYCLOTOMIC_FACTOR'): H = dup_zz_cyclotomic_factor(g, K) if H is None: H = dup_zz_zassenhaus(g, K) factors = dup_trial_division(f, H, K) return cont, factors
def dup_zz_factor(f, K): """ Factor (non square-free) polynomials in `Z[x]`. Given a univariate 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 Zassenhaus 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**4 - 2`:: >>> from sympy.polys import ring, ZZ >>> R, x = ring("x", ZZ) >>> R.dup_zz_factor(2*x**4 - 2) (2, [(x - 1, 1), (x + 1, 1), (x**2 + 1, 1)]) In result we got the following factorization:: f = 2 (x - 1) (x + 1) (x**2 + 1) Note that this is a complete factorization over integers, however over Gaussian integers we can factor the last term. By default, polynomials `x**n - 1` and `x**n + 1` are factored using cyclotomic decomposition to speedup computations. To disable this behaviour set cyclotomic=False. References ========== 1. [Gathen99]_ """ cont, g = dup_primitive(f, K) n = dup_degree(g) if dup_LC(g, K) < 0: cont, g = -cont, dup_neg(g, K) if n <= 0: return cont, [] elif n == 1: return cont, [(g, 1)] if query('USE_IRREDUCIBLE_IN_FACTOR'): if dup_zz_irreducible_p(g, K): return cont, [(g, 1)] g = dup_sqf_part(g, K) H = None if query('USE_CYCLOTOMIC_FACTOR'): H = dup_zz_cyclotomic_factor(g, K) if H is None: H = dup_zz_zassenhaus(g, K) factors = dup_trial_division(f, H, K) return cont, factors