Beispiel #1
0
def dup_ext_factor(f, K):
    """Factor univariate polynomials over algebraic number fields. """
    n, lc = dup_degree(f), dup_LC(f, K)

    f = dup_monic(f, K)

    if n <= 0:
        return lc, []
    if n == 1:
        return lc, [(f, 1)]

    f, F = dup_sqf_part(f, K), f
    s, g, r = dup_sqf_norm(f, K)

    factors = dup_factor_list_include(r, K.dom)

    if len(factors) == 1:
        return lc, [(f, n//dup_degree(f))]

    H = s*K.unit

    for i, (factor, _) in enumerate(factors):
        h = dup_convert(factor, K.dom, K)
        h, _, g = dup_inner_gcd(h, g, K)
        h = dup_shift(h, H, K)
        factors[i] = h

    factors = dup_trial_division(F, factors, K)

    return lc, factors
Beispiel #2
0
def dup_ext_factor(f, K):
    """Factor univariate polynomials over algebraic number fields. """
    n, lc = dup_degree(f), dup_LC(f, K)

    f = dup_monic(f, K)

    if n <= 0:
        return lc, []
    if n == 1:
        return lc, [(f, 1)]

    f, F = dup_sqf_part(f, K), f
    s, g, r = dup_sqf_norm(f, K)

    factors = dup_factor_list_include(r, K.dom)

    if len(factors) == 1:
        return lc, [(f, n // dup_degree(f))]

    H = s * K.unit

    for i, (factor, _) in enumerate(factors):
        h = dup_convert(factor, K.dom, K)
        h, _, g = dup_inner_gcd(h, g, K)
        h = dup_shift(h, H, K)
        factors[i] = h

    factors = dup_trial_division(F, factors, K)

    return lc, factors
Beispiel #3
0
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)
Beispiel #4
0
def dup_cyclotomic_p(f, K, irreducible=False):
    """
    Efficiently test if ``f`` is a cyclotomic polnomial.

    Examples
    ========

    >>> from sympy.polys.factortools import dup_cyclotomic_p
    >>> from sympy.polys.domains import ZZ

    >>> f = [1, 0, 1, 0, 0, 0,-1, 0, 1, 0,-1, 0, 0, 0, 1, 0, 1]
    >>> dup_cyclotomic_p(f, ZZ)
    False

    >>> g = [1, 0, 1, 0, 0, 0,-1, 0,-1, 0,-1, 0, 0, 0, 1, 0, 1]
    >>> dup_cyclotomic_p(g, ZZ)
    True

    """
    if K.is_QQ:
        try:
            K0, K = K, K.get_ring()
            f = dup_convert(f, K0, K)
        except CoercionFailed:
            return False
    elif not K.is_ZZ:
        return False

    lc = dup_LC(f, K)
    tc = dup_TC(f, K)

    if lc != 1 or (tc != -1 and tc != 1):
        return False

    if not irreducible:
        coeff, factors = dup_factor_list(f, K)

        if coeff != K.one or factors != [(f, 1)]:
            return False

    n = dup_degree(f)
    g, h = [], []

    for i in xrange(n, -1, -2):
        g.insert(0, f[i])

    for i in xrange(n - 1, -1, -2):
        h.insert(0, f[i])

    g = dup_sqr(dup_strip(g), K)
    h = dup_sqr(dup_strip(h), K)

    F = dup_sub(g, dup_lshift(h, 1, K), K)

    if K.is_negative(dup_LC(F, K)):
        F = dup_neg(F, K)

    if F == f:
        return True

    g = dup_mirror(f, K)

    if K.is_negative(dup_LC(g, K)):
        g = dup_neg(g, K)

    if F == g and dup_cyclotomic_p(g, K):
        return True

    G = dup_sqf_part(F, K)

    if dup_sqr(G, K) == F and dup_cyclotomic_p(G, K):
        return True

    return False
Beispiel #5
0
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)
Beispiel #6
0
def dup_zz_cyclotomic_p(f, K, irreducible=False):
    """
    Efficiently test if ``f`` is a cyclotomic polnomial.

    **Examples**

    >>> from sympy.polys.factortools import dup_zz_cyclotomic_p
    >>> from sympy.polys.domains import ZZ

    >>> f = [1, 0, 1, 0, 0, 0,-1, 0, 1, 0,-1, 0, 0, 0, 1, 0, 1]
    >>> dup_zz_cyclotomic_p(f, ZZ)
    False

    >>> g = [1, 0, 1, 0, 0, 0,-1, 0,-1, 0,-1, 0, 0, 0, 1, 0, 1]
    >>> dup_zz_cyclotomic_p(g, ZZ)
    True

    """
    if K.is_QQ:
        try:
            K0, K = K, K.get_ring()
            f = dup_convert(f, K0, K)
        except CoercionFailed:
            return False
    elif not K.is_ZZ:
        return False

    lc = dup_LC(f, K)
    tc = dup_TC(f, K)

    if lc != 1 or (tc != -1 and tc != 1):
        return False

    if not irreducible:
        coeff, factors = dup_factor_list(f, K)

        if coeff != K.one or factors != [(f, 1)]:
            return False

    n = dup_degree(f)
    g, h = [], []

    for i in xrange(n, -1, -2):
        g.insert(0, f[i])

    for i in xrange(n-1, -1, -2):
        h.insert(0, f[i])

    g = dup_sqr(dup_strip(g), K)
    h = dup_sqr(dup_strip(h), K)

    F = dup_sub(g, dup_lshift(h, 1, K), K)

    if K.is_negative(dup_LC(F, K)):
        F = dup_neg(F, K)

    if F == f:
        return True

    g = dup_mirror(f, K)

    if K.is_negative(dup_LC(g, K)):
        g = dup_neg(g, K)

    if F == g and dup_zz_cyclotomic_p(g, K):
        return True

    G = dup_sqf_part(F, K)

    if dup_sqr(G, K) == F and dup_zz_cyclotomic_p(G, K):
        return True

    return False
def test_dup_isolate_real_roots():
    assert dup_isolate_real_roots([], ZZ) == []
    assert dup_isolate_real_roots([3], ZZ) == []

    assert dup_isolate_real_roots([5, 0], ZZ) == [((QQ(0), QQ(0)), 1)]
    assert dup_isolate_real_roots([7, 0, 0, 0, 0], ZZ) == [((QQ(0), QQ(0)), 4)]

    assert dup_isolate_real_roots([1, 1, 0], ZZ) == [((-QQ(1), -QQ(1)), 1),
                                                     ((QQ(0), QQ(0)), 1)]
    assert dup_isolate_real_roots([1, -1, 0], ZZ) == [((QQ(0), QQ(0)), 1),
                                                      ((QQ(1), QQ(1)), 1)]

    assert dup_isolate_real_roots([1, 0, 0, 1, 1], ZZ) == []

    I = [((-QQ(2), -QQ(1)), 1), ((QQ(1), QQ(2)), 1)]

    assert dup_isolate_real_roots([1, 0, -2], ZZ) == I
    assert dup_isolate_real_roots([-1, 0, 2], ZZ) == I

    f = [
        16, -96, 24, 936, -1599, -2880, 9196, 552, -21831, 13968, 21690,
        -26784, -2916, 15552, -5832
    ]
    g = dup_sqf_part(f, ZZ)

    assert dup_isolate_real_roots(f, ZZ) == \
        [((-QQ(2), -QQ(3,2)), 2), ((-QQ(3,2), -QQ(1,1)), 3),
         (( QQ(1),  QQ(3,2)), 3), (( QQ(3,2),  QQ(3,2)), 4), ((QQ(5,3), QQ(2)), 2)]

    assert dup_isolate_real_roots_sqf(g, ZZ) == \
        [(-QQ(2), -QQ(3,2)), (-QQ(3,2), -QQ(1,1)),
         ( QQ(1),  QQ(3,2)), ( QQ(3,2),  QQ(3,2)), (QQ(3,2), QQ(2))]
    assert dup_isolate_real_roots(g, ZZ) == \
        [((-QQ(2), -QQ(3,2)), 1), ((-QQ(3,2), -QQ(1,1)), 1),
         (( QQ(1),  QQ(3,2)), 1), (( QQ(3,2),  QQ(3,2)), 1), ((QQ(3,2), QQ(2)), 1)]

    assert dup_isolate_real_roots([1, -1], ZZ, inf=2) == []
    assert dup_isolate_real_roots([1, -1], ZZ, sup=0) == []

    assert dup_isolate_real_roots([1, -1], ZZ) == [((1, 1), 1)]
    assert dup_isolate_real_roots([1, -1], ZZ, inf=1) == [((1, 1), 1)]
    assert dup_isolate_real_roots([1, -1], ZZ, sup=1) == [((1, 1), 1)]
    assert dup_isolate_real_roots([1, -1], ZZ, inf=1, sup=1) == [((1, 1), 1)]

    f = [1, 0, -4, 0, 4]

    assert dup_isolate_real_roots(f, ZZ, inf=QQ(7, 4)) == []
    assert dup_isolate_real_roots(f, ZZ,
                                  inf=QQ(7, 5)) == [((QQ(7, 5), QQ(3, 2)), 2)]
    assert dup_isolate_real_roots(f, ZZ, sup=QQ(7, 5)) == [((-2, -1), 2)]
    assert dup_isolate_real_roots(f, ZZ, sup=QQ(7, 4)) == [((-2, -1), 2),
                                                           ((1, QQ(3, 2)), 2)]
    assert dup_isolate_real_roots(f, ZZ, sup=-QQ(7, 4)) == []
    assert dup_isolate_real_roots(f, ZZ, sup=-QQ(7, 5)) == [((-QQ(3, 2),
                                                              -QQ(7, 5)), 2)]
    assert dup_isolate_real_roots(f, ZZ, inf=-QQ(7, 5)) == [((1, 2), 2)]
    assert dup_isolate_real_roots(f, ZZ,
                                  inf=-QQ(7, 4)) == [((-QQ(3, 2), -1), 2),
                                                     ((1, 2), 2)]

    I = [((-2, -1), 2), ((1, 2), 2)]

    assert dup_isolate_real_roots(f, ZZ, inf=-2) == I
    assert dup_isolate_real_roots(f, ZZ, sup=+2) == I

    assert dup_isolate_real_roots(f, ZZ, inf=-2, sup=2) == I

    f = [1, -3, -1, 11, -8, -8, 12, -4, 0, 0, 0, 0]

    assert dup_isolate_real_roots(f, ZZ, basis=False) == \
        [((-2, -1), 2), ((0, 0), 4), ((1, 1), 3), ((1, 2), 2)]
    assert dup_isolate_real_roots(f, ZZ, basis=True) == \
        [((-2, -1), 2, [1, 0, -2]), ((0, 0), 4, [1, 0]), ((1, 1), 3, [1, -1]), ((1, 2), 2, [1, 0, -2])]

    raises(DomainError, "dup_isolate_real_roots([EX(1), EX(2)], EX)")
Beispiel #8
0
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
Beispiel #9
0
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
Beispiel #10
0
def test_dup_isolate_real_roots():
    assert dup_isolate_real_roots([], ZZ) == []
    assert dup_isolate_real_roots([3], ZZ) == []

    assert dup_isolate_real_roots([5,0], ZZ) ==  [((QQ(0), QQ(0)), 1)]
    assert dup_isolate_real_roots([7,0,0,0,0], ZZ) == [((QQ(0), QQ(0)), 4)]

    assert dup_isolate_real_roots([1, 1,0], ZZ) == [((-QQ(1), -QQ(1)), 1), ((QQ(0), QQ(0)), 1)]
    assert dup_isolate_real_roots([1,-1,0], ZZ) == [(( QQ(0),  QQ(0)), 1), ((QQ(1), QQ(1)), 1)]

    assert dup_isolate_real_roots([1,0,0,1,1], ZZ) == []

    I = [((-QQ(2), -QQ(1)), 1), ((QQ(1), QQ(2)), 1)]

    assert dup_isolate_real_roots([1,0,-2], ZZ) == I
    assert dup_isolate_real_roots([-1,0,2], ZZ) == I

    f = [16,-96,24,936,-1599,-2880,9196,552,-21831,13968,21690,-26784,-2916,15552,-5832]
    g = dup_sqf_part(f, ZZ)

    assert dup_isolate_real_roots(f, ZZ) == \
        [((-QQ(2), -QQ(3,2)), 2), ((-QQ(3,2), -QQ(1,1)), 3),
         (( QQ(1),  QQ(3,2)), 3), (( QQ(3,2),  QQ(3,2)), 4), ((QQ(5,3), QQ(2)), 2)]

    assert dup_isolate_real_roots_sqf(g, ZZ) == \
        [(-QQ(2), -QQ(3,2)), (-QQ(3,2), -QQ(1,1)),
         ( QQ(1),  QQ(3,2)), ( QQ(3,2),  QQ(3,2)), (QQ(3,2), QQ(2))]
    assert dup_isolate_real_roots(g, ZZ) == \
        [((-QQ(2), -QQ(3,2)), 1), ((-QQ(3,2), -QQ(1,1)), 1),
         (( QQ(1),  QQ(3,2)), 1), (( QQ(3,2),  QQ(3,2)), 1), ((QQ(3,2), QQ(2)), 1)]

    assert dup_isolate_real_roots([1, -1], ZZ, inf=2) == []
    assert dup_isolate_real_roots([1, -1], ZZ, sup=0) == []

    assert dup_isolate_real_roots([1, -1], ZZ) == [((1, 1), 1)]
    assert dup_isolate_real_roots([1, -1], ZZ, inf=1) == [((1, 1), 1)]
    assert dup_isolate_real_roots([1, -1], ZZ, sup=1) == [((1, 1), 1)]
    assert dup_isolate_real_roots([1, -1], ZZ, inf=1, sup=1) == [((1, 1), 1)]

    f = [1, 0, -4, 0, 4]

    assert dup_isolate_real_roots(f, ZZ, inf=QQ(7,4)) == []
    assert dup_isolate_real_roots(f, ZZ, inf=QQ(7,5)) == [((QQ(7,5), QQ(3,2)), 2)]
    assert dup_isolate_real_roots(f, ZZ, sup=QQ(7,5)) == [((-2, -1), 2)]
    assert dup_isolate_real_roots(f, ZZ, sup=QQ(7,4)) == [((-2, -1), 2), ((1, QQ(3,2)), 2)]
    assert dup_isolate_real_roots(f, ZZ, sup=-QQ(7,4)) == []
    assert dup_isolate_real_roots(f, ZZ, sup=-QQ(7,5)) == [((-QQ(3,2), -QQ(7,5)), 2)]
    assert dup_isolate_real_roots(f, ZZ, inf=-QQ(7,5)) == [((1, 2), 2)]
    assert dup_isolate_real_roots(f, ZZ, inf=-QQ(7,4)) == [((-QQ(3,2), -1), 2), ((1, 2), 2)]

    I = [((-2, -1), 2), ((1, 2), 2)]

    assert dup_isolate_real_roots(f, ZZ, inf=-2) == I
    assert dup_isolate_real_roots(f, ZZ, sup=+2) == I

    assert dup_isolate_real_roots(f, ZZ, inf=-2, sup=2) == I

    f = [1, -3, -1, 11, -8, -8, 12, -4, 0, 0, 0, 0]

    assert dup_isolate_real_roots(f, ZZ, basis=False) == \
        [((-2, -1), 2), ((0, 0), 4), ((1, 1), 3), ((1, 2), 2)]
    assert dup_isolate_real_roots(f, ZZ, basis=True) == \
        [((-2, -1), 2, [1, 0, -2]), ((0, 0), 4, [1, 0]), ((1, 1), 3, [1, -1]), ((1, 2), 2, [1, 0, -2])]

    raises(DomainError, "dup_isolate_real_roots([EX(1), EX(2)], EX)")
def test_dup_sqf():
    assert dup_sqf_part([], ZZ) == []
    assert dup_sqf_p([], ZZ) == True

    assert dup_sqf_part([7], ZZ) == [1]
    assert dup_sqf_p([7], ZZ) == True

    assert dup_sqf_part([2,2], ZZ) == [1,1]
    assert dup_sqf_p([2,2], ZZ) == True

    assert dup_sqf_part([1,0,1,1], ZZ) == [1,0,1,1]
    assert dup_sqf_p([1,0,1,1], ZZ) == True

    assert dup_sqf_part([-1,0,1,1], ZZ) == [1,0,-1,-1]
    assert dup_sqf_p([-1,0,1,1], ZZ) == True

    assert dup_sqf_part([2,3,0,0], ZZ) == [2,3,0]
    assert dup_sqf_p([2,3,0,0], ZZ) == False

    assert dup_sqf_part([-2,3,0,0], ZZ) == [2,-3,0]
    assert dup_sqf_p([-2,3,0,0], ZZ) == False

    assert dup_sqf_list([], ZZ) == (0, [])
    assert dup_sqf_list([1], ZZ) == (1, [])

    assert dup_sqf_list([1,0], ZZ) == (1, [([1,0], 1)])
    assert dup_sqf_list([2,0,0], ZZ) == (2, [([1,0], 2)])
    assert dup_sqf_list([3,0,0,0], ZZ) == (3, [([1,0], 3)])

    assert dup_sqf_list([ZZ(2),ZZ(4),ZZ(2)], ZZ) == \
        (ZZ(2), [([ZZ(1),ZZ(1)], 2)])
    assert dup_sqf_list([QQ(2),QQ(4),QQ(2)], QQ) == \
        (QQ(2), [([QQ(1),QQ(1)], 2)])

    assert dup_sqf_list([-1,1,0,0,1,-1], ZZ) == \
        (-1, [([1,1,1,1], 1), ([1,-1], 2)])
    assert dup_sqf_list([1,0,6,0,12,0,8,0,0], ZZ) == \
        (1, [([1,0], 2), ([1,0,2], 3)])

    K = FF(2)
    f = map(K, [1,0,1])

    assert dup_sqf_list(f, K) == \
        (K(1), [([K(1),K(1)], 2)])

    K = FF(3)
    f = map(K, [1,0,0,2,0,0,2,0,0,1,0])

    assert dup_sqf_list(f, K) == \
        (K(1), [([K(1), K(0)], 1),
                ([K(1), K(1)], 3),
                ([K(1), K(2)], 6)])

    f = [1,0,0,1]
    g = map(K, f)

    assert dup_sqf_part(f, ZZ) == f
    assert dup_sqf_part(g, K) == [K(1), K(1)]

    assert dup_sqf_p(f, ZZ) == True
    assert dup_sqf_p(g, K) == False

    A = [[1],[],[-3],[],[6]]
    D = [[1],[],[-5],[],[5],[],[4]]

    f, g = D, dmp_sub(A, dmp_mul(dmp_diff(D, 1, 1, ZZ), [[1,0]], 1, ZZ), 1, ZZ)

    res = dmp_resultant(f, g, 1, ZZ)

    assert dup_sqf_list(res, ZZ) == (45796, [([4,0,1], 3)])

    assert dup_sqf_list_include([DMP([1, 0, 0, 0], ZZ), DMP([], ZZ), DMP([], ZZ)], ZZ[x]) == \
        [([DMP([1, 0, 0, 0], ZZ)], 1), ([DMP([1], ZZ), DMP([], ZZ)], 2)]