Example #1
0
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
Example #2
0
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
Example #3
0
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)
Example #4
0
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
Example #5
0
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
Example #6
0
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)
Example #7
0
def test_dmp_mul():
    assert dmp_mul([ZZ(5)], [ZZ(7)], 0, ZZ) == dup_mul([ZZ(5)], [ZZ(7)], ZZ)
    assert dmp_mul([QQ(5, 7)], [QQ(3, 7)], 0, QQ) == dup_mul([QQ(5, 7)], [QQ(3, 7)], QQ)

    assert dmp_mul([[[]]], [[[]]], 2, ZZ) == [[[]]]
    assert dmp_mul([[[ZZ(1)]]], [[[]]], 2, ZZ) == [[[]]]
    assert dmp_mul([[[]]], [[[ZZ(1)]]], 2, ZZ) == [[[]]]
    assert dmp_mul([[[ZZ(2)]]], [[[ZZ(1)]]], 2, ZZ) == [[[ZZ(2)]]]
    assert dmp_mul([[[ZZ(1)]]], [[[ZZ(2)]]], 2, ZZ) == [[[ZZ(2)]]]

    assert dmp_mul([[[]]], [[[]]], 2, QQ) == [[[]]]
    assert dmp_mul([[[QQ(1, 2)]]], [[[]]], 2, QQ) == [[[]]]
    assert dmp_mul([[[]]], [[[QQ(1, 2)]]], 2, QQ) == [[[]]]
    assert dmp_mul([[[QQ(2, 7)]]], [[[QQ(1, 3)]]], 2, QQ) == [[[QQ(2, 21)]]]
    assert dmp_mul([[[QQ(1, 7)]]], [[[QQ(2, 3)]]], 2, QQ) == [[[QQ(2, 21)]]]
Example #8
0
def dup_gff_list(f, K):
    """
    Compute greatest factorial factorization of ``f`` in ``K[x]``.

    Examples
    ========

    >>> from sympy.polys import ring, ZZ
    >>> R, x = ring("x", ZZ)

    >>> R.dup_gff_list(x**5 + 2*x**4 - x**3 - 2*x**2)
    [(x, 1), (x + 2, 4)]

    """
    if not f:
        raise ValueError("greatest factorial factorization doesn't exist for a zero polynomial")

    f = dup_monic(f, K)

    if not dup_degree(f):
        return []
    else:
        g = dup_gcd(f, dup_shift(f, K.one, K), K)
        H = dup_gff_list(g, K)

        for i, (h, k) in enumerate(H):
            g = dup_mul(g, dup_shift(h, -K(k), K), K)
            H[i] = (h, k + 1)

        f = dup_quo(f, g, K)

        if not dup_degree(f):
            return H
        else:
            return [(f, 1)] + H
Example #9
0
def dup_compose(f, g, K):
    """
    Evaluate functional composition ``f(g)`` in ``K[x]``.

    Examples
    ========

    >>> from sympy.polys import ring, ZZ
    >>> R, x = ring("x", ZZ)

    >>> R.dup_compose(x**2 + x, x - 1)
    x**2 - x

    """
    if len(g) <= 1:
        return dup_strip([dup_eval(f, dup_LC(g, K), K)])

    if not f:
        return []

    h = [f[0]]

    for c in f[1:]:
        h = dup_mul(h, g, K)
        h = dup_add_term(h, c, 0, K)

    return h
Example #10
0
def dup_revert(f, n, K):
    """
    Compute ``f**(-1)`` mod ``x**n`` using Newton iteration.

    This function computes first ``2**n`` terms of a polynomial that
    is a result of inversion of a polynomial modulo ``x**n``. This is
    useful to efficiently compute series expansion of ``1/f``.

    Examples
    ========

    >>> from sympy.polys import ring, QQ
    >>> R, x = ring("x", QQ)

    >>> f = -QQ(1,720)*x**6 + QQ(1,24)*x**4 - QQ(1,2)*x**2 + 1

    >>> R.dup_revert(f, 8)
    61/720*x**6 + 5/24*x**4 + 1/2*x**2 + 1

    """
    g = [K.revert(dup_TC(f, K))]
    h = [K.one, K.zero, K.zero]

    N = int(_ceil(_log(n, 2)))

    for i in range(1, N + 1):
        a = dup_mul_ground(g, K(2), K)
        b = dup_mul(f, dup_sqr(g, K), K)
        g = dup_rem(dup_sub(a, b, K), h, K)
        h = dup_lshift(h, dup_degree(h), K)

    return g
Example #11
0
def dup_rr_lcm(f, g, K):
    """
    Computes polynomial LCM over a ring in `K[x]`.

    Examples
    ========

    >>> from sympy.polys.domains import ZZ
    >>> from sympy.polys.euclidtools import dup_rr_lcm

    >>> f = ZZ.map([1, 0, -1])
    >>> g = ZZ.map([1, -3, 2])

    >>> dup_rr_lcm(f, g, ZZ)
    [1, -2, -1, 2]

    """
    fc, f = dup_primitive(f, K)
    gc, g = dup_primitive(g, K)

    c = K.lcm(fc, gc)

    h = dup_quo(dup_mul(f, g, K), dup_gcd(f, g, K), K)

    return dup_mul_ground(h, c, K)
Example #12
0
def dup_compose(f, g, K):
    """
    Evaluate functional composition ``f(g)`` in ``K[x]``.

    Examples
    ========

    >>> from sympy.polys import ring, ZZ
    >>> R, x = ring("x", ZZ)

    >>> R.dup_compose(x**2 + x, x - 1)
    x**2 - x

    """
    if len(g) <= 1:
        return dup_strip([dup_eval(f, dup_LC(g, K), K)])

    if not f:
        return []

    h = [f[0]]

    for c in f[1:]:
        h = dup_mul(h, g, K)
        h = dup_add_term(h, c, 0, K)

    return h
Example #13
0
def dup_revert(f, n, K):
    """
    Compute ``f**(-1)`` mod ``x**n`` using Newton iteration.

    This function computes first ``2**n`` terms of a polynomial that
    is a result of inversion of a polynomial modulo ``x**n``. This is
    useful to efficiently compute series expansion of ``1/f``.

    Examples
    ========

    >>> from sympy.polys.domains import QQ
    >>> from sympy.polys.densetools import dup_revert

    >>> f = [-QQ(1,720), QQ(0), QQ(1,24), QQ(0), -QQ(1,2), QQ(0), QQ(1)]

    >>> dup_revert(f, 8, QQ)
    [61/720, 0/1, 5/24, 0/1, 1/2, 0/1, 1/1]

    """
    g = [K.revert(dup_TC(f, K))]
    h = [K.one, K.zero, K.zero]

    N = int(_ceil(_log(n, 2)))

    for i in xrange(1, N + 1):
        a = dup_mul_ground(g, K(2), K)
        b = dup_mul(f, dup_sqr(g, K), K)
        g = dup_rem(dup_sub(a, b, K), h, K)
        h = dup_lshift(h, dup_degree(h), K)

    return g
Example #14
0
def dup_compose(f, g, K):
    """
    Evaluate functional composition ``f(g)`` in ``K[x]``.

    Examples
    ========

    >>> from sympy.polys.domains import ZZ
    >>> from sympy.polys.densetools import dup_compose

    >>> f = ZZ.map([1, 1, 0])
    >>> g = ZZ.map([1, -1])

    >>> dup_compose(f, g, ZZ)
    [1, -1, 0]

    """
    if len(g) <= 1:
        return dup_strip([dup_eval(f, dup_LC(g, K), K)])

    if not f:
        return []

    h = [f[0]]

    for c in f[1:]:
        h = dup_mul(h, g, K)
        h = dup_add_term(h, c, 0, K)

    return h
Example #15
0
def dup_revert(f, n, K):
    """
    Compute ``f**(-1)`` mod ``x**n`` using Newton iteration.

    This function computes first ``2**n`` terms of a polynomial that
    is a result of inversion of a polynomial modulo ``x**n``. This is
    useful to efficiently compute series expansion of ``1/f``.

    Examples
    ========

    >>> from sympy.polys.domains import QQ
    >>> from sympy.polys.densetools import dup_revert

    >>> f = [-QQ(1,720), QQ(0), QQ(1,24), QQ(0), -QQ(1,2), QQ(0), QQ(1)]

    >>> dup_revert(f, 8, QQ)
    [61/720, 0/1, 5/24, 0/1, 1/2, 0/1, 1/1]

    """
    g = [K.revert(dup_TC(f, K))]
    h = [K.one, K.zero, K.zero]

    N = int(_ceil(_log(n, 2)))

    for i in xrange(1, N + 1):
        a = dup_mul_ground(g, K(2), K)
        b = dup_mul(f, dup_sqr(g, K), K)
        g = dup_rem(dup_sub(a, b, K), h, K)
        h = dup_lshift(h, dup_degree(h), K)

    return g
Example #16
0
def dup_compose(f, g, K):
    """
    Evaluate functional composition ``f(g)`` in ``K[x]``.

    Examples
    ========

    >>> from sympy.polys.domains import ZZ
    >>> from sympy.polys.densetools import dup_compose

    >>> f = ZZ.map([1, 1, 0])
    >>> g = ZZ.map([1, -1])

    >>> dup_compose(f, g, ZZ)
    [1, -1, 0]

    """
    if len(g) <= 1:
        return dup_strip([dup_eval(f, dup_LC(g, K), K)])

    if not f:
        return []

    h = [f[0]]

    for c in f[1:]:
        h = dup_mul(h, g, K)
        h = dup_add_term(h, c, 0, K)

    return h
Example #17
0
def dup_rr_lcm(f, g, K):
    """
    Computes polynomial LCM over a ring in ``K[x]``.

    **Examples**

    >>> from sympy.polys.domains import ZZ
    >>> from sympy.polys.euclidtools import dup_rr_lcm

    >>> f = ZZ.map([1, 0, -1])
    >>> g = ZZ.map([1, -3, 2])

    >>> dup_rr_lcm(f, g, ZZ)
    [1, -2, -1, 2]

    """
    fc, f = dup_primitive(f, K)
    gc, g = dup_primitive(g, K)

    c = K.lcm(fc, gc)

    h = dup_exquo(dup_mul(f, g, K),
                  dup_gcd(f, g, K), K)

    return dup_mul_ground(h, c, K)
Example #18
0
def dup_revert(f, n, K):
    """
    Compute ``f**(-1)`` mod ``x**n`` using Newton iteration.

    This function computes first ``2**n`` terms of a polynomial that
    is a result of inversion of a polynomial modulo ``x**n``. This is
    useful to efficiently compute series expansion of ``1/f``.

    Examples
    ========

    >>> from sympy.polys import ring, QQ
    >>> R, x = ring("x", QQ)

    >>> f = -QQ(1,720)*x**6 + QQ(1,24)*x**4 - QQ(1,2)*x**2 + 1

    >>> R.dup_revert(f, 8)
    61/720*x**6 + 5/24*x**4 + 1/2*x**2 + 1

    """
    g = [K.revert(dup_TC(f, K))]
    h = [K.one, K.zero, K.zero]

    N = int(_ceil(_log(n, 2)))

    for i in range(1, N + 1):
        a = dup_mul_ground(g, K(2), K)
        b = dup_mul(f, dup_sqr(g, K), K)
        g = dup_rem(dup_sub(a, b, K), h, K)
        h = dup_lshift(h, dup_degree(h), K)

    return g
Example #19
0
def dup_gff_list(f, K):
    """
    Compute greatest factorial factorization of ``f`` in ``K[x]``.

    Examples
    ========

    >>> from sympy.polys import ring, ZZ
    >>> R, x = ring("x", ZZ)

    >>> R.dup_gff_list(x**5 + 2*x**4 - x**3 - 2*x**2)
    [(x, 1), (x + 2, 4)]

    """
    if not f:
        raise ValueError("greatest factorial factorization doesn't exist for a zero polynomial")

    f = dup_monic(f, K)

    if not dup_degree(f):
        return []
    else:
        g = dup_gcd(f, dup_shift(f, K.one, K), K)
        H = dup_gff_list(g, K)

        for i, (h, k) in enumerate(H):
            g = dup_mul(g, dup_shift(h, -K(k), K), K)
            H[i] = (h, k + 1)

        f = dup_quo(f, g, K)

        if not dup_degree(f):
            return H
        else:
            return [(f, 1)] + H
Example #20
0
def test_dmp_mul():
    assert dmp_mul([ZZ(5)], [ZZ(7)], 0, ZZ) == \
           dup_mul([ZZ(5)], [ZZ(7)], ZZ)
    assert dmp_mul([QQ(5,7)], [QQ(3,7)], 0, QQ) == \
           dup_mul([QQ(5,7)], [QQ(3,7)], QQ)

    assert dmp_mul([[[]]], [[[]]], 2, ZZ) == [[[]]]
    assert dmp_mul([[[ZZ(1)]]], [[[]]], 2, ZZ) == [[[]]]
    assert dmp_mul([[[]]], [[[ZZ(1)]]], 2, ZZ) == [[[]]]
    assert dmp_mul([[[ZZ(2)]]], [[[ZZ(1)]]], 2, ZZ) == [[[ZZ(2)]]]
    assert dmp_mul([[[ZZ(1)]]], [[[ZZ(2)]]], 2, ZZ) == [[[ZZ(2)]]]

    assert dmp_mul([[[]]], [[[]]], 2, QQ) == [[[]]]
    assert dmp_mul([[[QQ(1,2)]]], [[[]]], 2, QQ) == [[[]]]
    assert dmp_mul([[[]]], [[[QQ(1,2)]]], 2, QQ) == [[[]]]
    assert dmp_mul([[[QQ(2,7)]]], [[[QQ(1,3)]]], 2, QQ) == [[[QQ(2,21)]]]
    assert dmp_mul([[[QQ(1,7)]]], [[[QQ(2,3)]]], 2, QQ) == [[[QQ(2,21)]]]
Example #21
0
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
Example #22
0
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
Example #23
0
def dup_laguerre(n, K):
    """Low-level implementation of Laguerre polynomials. """
    seq = [[K.one], [-K.one, K.one]]

    for i in xrange(2, n+1):
        a = dup_mul(seq[-1], [-K(1, i), K(2*i-1, i)], K)
        b = dup_mul_ground(seq[-2], K(i-1, i), K)

        seq.append(dup_sub(a, b, K))

    return seq[n]
Example #24
0
def dup_laguerre(n, K):
    """Low-level implementation of Laguerre polynomials. """
    seq = [[K.one], [-K.one, K.one]]

    for i in xrange(2, n + 1):
        a = dup_mul(seq[-1], [-K(1, i), K(2 * i - 1, i)], K)
        b = dup_mul_ground(seq[-2], K(i - 1, i), K)

        seq.append(dup_sub(a, b, K))

    return seq[n]
Example #25
0
def dup_laguerre(n, alpha, K):
    """Low-level implementation of Laguerre polynomials. """
    seq = [[K.zero], [K.one]]

    for i in xrange(1, n + 1):
        a = dup_mul(seq[-1], [-K.one / i, alpha / i + K(2 * i - 1) / i], K)
        b = dup_mul_ground(seq[-2], alpha / i + K(i - 1) / i, K)

        seq.append(dup_sub(a, b, K))

    return seq[-1]
Example #26
0
def dup_laguerre(n, alpha, K):
    """Low-level implementation of Laguerre polynomials. """
    seq = [[K.zero], [K.one]]

    for i in range(1, n + 1):
        a = dup_mul(seq[-1], [-K.one/i, alpha/i + K(2*i - 1)/i], K)
        b = dup_mul_ground(seq[-2], alpha/i + K(i - 1)/i, K)

        seq.append(dup_sub(a, b, K))

    return seq[-1]
Example #27
0
def test_dmp_mul():
    assert dmp_mul([ZZ(5)], [ZZ(7)], 0, ZZ) == \
           dup_mul([ZZ(5)], [ZZ(7)], ZZ)
    assert dmp_mul([QQ(5,7)], [QQ(3,7)], 0, QQ) == \
           dup_mul([QQ(5,7)], [QQ(3,7)], QQ)

    assert dmp_mul([[[]]], [[[]]], 2, ZZ) == [[[]]]
    assert dmp_mul([[[ZZ(1)]]], [[[]]], 2, ZZ) == [[[]]]
    assert dmp_mul([[[]]], [[[ZZ(1)]]], 2, ZZ) == [[[]]]
    assert dmp_mul([[[ZZ(2)]]], [[[ZZ(1)]]], 2, ZZ) == [[[ZZ(2)]]]
    assert dmp_mul([[[ZZ(1)]]], [[[ZZ(2)]]], 2, ZZ) == [[[ZZ(2)]]]

    assert dmp_mul([[[]]], [[[]]], 2, QQ) == [[[]]]
    assert dmp_mul([[[QQ(1,2)]]], [[[]]], 2, QQ) == [[[]]]
    assert dmp_mul([[[]]], [[[QQ(1,2)]]], 2, QQ) == [[[]]]
    assert dmp_mul([[[QQ(2,7)]]], [[[QQ(1,3)]]], 2, QQ) == [[[QQ(2,21)]]]
    assert dmp_mul([[[QQ(1,7)]]], [[[QQ(2,3)]]], 2, QQ) == [[[QQ(2,21)]]]

    K = FF(6)

    assert dmp_mul([[K(2)],[K(1)]], [[K(3)],[K(4)]], 1, K) == [[K(5)],[K(4)]]
Example #28
0
def test_dmp_content():
    assert dmp_content([[-2]], 1, ZZ) == [2]

    f, g, F = [ZZ(3),ZZ(2),ZZ(1)], [ZZ(1)], []

    for i in xrange(0, 5):
        g = dup_mul(g, f, ZZ)
        F.insert(0, g)

    assert dmp_content(F, 1, ZZ) == f

    assert dmp_one_p(dmp_content(f_4, 2, ZZ), 1, ZZ)
    assert dmp_one_p(dmp_content(f_5, 2, ZZ), 1, ZZ)
    assert dmp_one_p(dmp_content(f_6, 3, ZZ), 2, ZZ)
Example #29
0
def test_dmp_content():
    assert dmp_content([[-2]], 1, ZZ) == [2]

    f, g, F = [ZZ(3), ZZ(2), ZZ(1)], [ZZ(1)], []

    for i in xrange(0, 5):
        g = dup_mul(g, f, ZZ)
        F.insert(0, g)

    assert dmp_content(F, 1, ZZ) == f

    assert dmp_one_p(dmp_content(f_4, 2, ZZ), 1, ZZ)
    assert dmp_one_p(dmp_content(f_5, 2, ZZ), 1, ZZ)
    assert dmp_one_p(dmp_content(f_6, 3, ZZ), 2, ZZ)
Example #30
0
def dup_zz_diophantine(F, m, p, K):
    """Wang/EEZ: Solve univariate Diophantine equations. """
    if len(F) == 2:
        a, b = F

        f = gf_from_int_poly(a, p)
        g = gf_from_int_poly(b, p)

        s, t, G = gf_gcdex(g, f, p, K)

        s = gf_lshift(s, m, K)
        t = gf_lshift(t, m, K)

        q, s = gf_div(s, f, p, K)

        t = gf_add_mul(t, q, g, p, K)

        s = gf_to_int_poly(s, p)
        t = gf_to_int_poly(t, p)

        result = [s, t]
    else:
        G = [F[-1]]

        for f in reversed(F[1:-1]):
            G.insert(0, dup_mul(f, G[0], K))

        S, T = [], [[1]]

        for f, g in zip(F, G):
            t, s = dmp_zz_diophantine([g, f], T[-1], [], 0, p, 1, K)
            T.append(t)
            S.append(s)

        result, S = [], S + [T[-1]]

        for s, f in zip(S, F):
            s = gf_from_int_poly(s, p)
            f = gf_from_int_poly(f, p)

            r = gf_rem(gf_lshift(s, m, K), f, p, K)
            s = gf_to_int_poly(r, p)

            result.append(s)

    return result
Example #31
0
def dup_zz_diophantine(F, m, p, K):
    """Wang/EEZ: Solve univariate Diophantine equations. """
    if len(F) == 2:
        a, b = F

        f = gf_from_int_poly(a, p)
        g = gf_from_int_poly(b, p)

        s, t, G = gf_gcdex(g, f, p, K)

        s = gf_lshift(s, m, K)
        t = gf_lshift(t, m, K)

        q, s = gf_div(s, f, p, K)

        t = gf_add_mul(t, q, g, p, K)

        s = gf_to_int_poly(s, p)
        t = gf_to_int_poly(t, p)

        result = [s, t]
    else:
        G = [F[-1]]

        for f in reversed(F[1:-1]):
            G.insert(0, dup_mul(f, G[0], K))

        S, T = [], [[1]]

        for f, g in zip(F, G):
            t, s = dmp_zz_diophantine([g, f], T[-1], [], 0, p, 1, K)
            T.append(t)
            S.append(s)

        result, S = [], S + [T[-1]]

        for s, f in zip(S, F):
            s = gf_from_int_poly(s, p)
            f = gf_from_int_poly(f, p)

            r = gf_rem(gf_lshift(s, m, K), f, p, K)
            s = gf_to_int_poly(r, p)

            result.append(s)

    return result
Example #32
0
def test_dmp_primitive():
    assert dmp_primitive([[]], 1, ZZ) == ([], [[]])
    assert dmp_primitive([[1]], 1, ZZ) == ([1], [[1]])

    f, g, F = [ZZ(3), ZZ(2), ZZ(1)], [ZZ(1)], []

    for i in xrange(0, 5):
        g = dup_mul(g, f, ZZ)
        F.insert(0, g)

    assert dmp_primitive(F, 1, ZZ) == (f, [dup_exquo(c, f, ZZ) for c in F])

    cont, f = dmp_primitive(f_4, 2, ZZ)
    assert dmp_one_p(cont, 1, ZZ) and f == f_4
    cont, f = dmp_primitive(f_5, 2, ZZ)
    assert dmp_one_p(cont, 1, ZZ) and f == f_5
    cont, f = dmp_primitive(f_6, 3, ZZ)
    assert dmp_one_p(cont, 2, ZZ) and f == f_6
Example #33
0
def test_dmp_primitive():
    assert dmp_primitive([[]], 1, ZZ) == ([], [[]])
    assert dmp_primitive([[1]], 1, ZZ) == ([1], [[1]])

    f, g, F = [ZZ(3),ZZ(2),ZZ(1)], [ZZ(1)], []

    for i in xrange(0, 5):
        g = dup_mul(g, f, ZZ)
        F.insert(0, g)

    assert dmp_primitive(F, 1, ZZ) == (f,
        [ dup_exquo(c, f, ZZ) for c in F ])

    cont, f = dmp_primitive(f_4, 2, ZZ)
    assert dmp_one_p(cont, 1, ZZ) and f == f_4
    cont, f = dmp_primitive(f_5, 2, ZZ)
    assert dmp_one_p(cont, 1, ZZ) and f == f_5
    cont, f = dmp_primitive(f_6, 3, ZZ)
    assert dmp_one_p(cont, 2, ZZ) and f == f_6
Example #34
0
def dup_ff_lcm(f, g, K):
    """
    Computes polynomial LCM over a field in ``K[x]``.

    **Examples**

    >>> from sympy.polys.domains import QQ
    >>> from sympy.polys.euclidtools import dup_ff_lcm

    >>> f = [QQ(1,2), QQ(7,4), QQ(3,2)]
    >>> g = [QQ(1,2), QQ(1), QQ(0)]

    >>> dup_ff_lcm(f, g, QQ)
    [1/1, 7/2, 3/1, 0/1]

    """
    h = dup_quo(dup_mul(f, g, K), dup_gcd(f, g, K), K)

    return dup_monic(h, K)
def dup_ff_lcm(f, g, K):
    """
    Computes polynomial LCM over a field in `K[x]`.

    Examples
    ========

    >>> from sympy.polys import ring, QQ
    >>> R, x = ring("x", QQ)

    >>> f = QQ(1,2)*x**2 + QQ(7,4)*x + QQ(3,2)
    >>> g = QQ(1,2)*x**2 + x

    >>> R.dup_ff_lcm(f, g)
    x**3 + 7/2*x**2 + 3*x

    """
    h = dup_quo(dup_mul(f, g, K), dup_gcd(f, g, K), K)

    return dup_monic(h, K)
Example #36
0
def dup_ff_lcm(f, g, K):
    """
    Computes polynomial LCM over a field in ``K[x]``.

    **Examples**

    >>> from sympy.polys.domains import QQ
    >>> from sympy.polys.euclidtools import dup_ff_lcm

    >>> f = [QQ(1,2), QQ(7,4), QQ(3,2)]
    >>> g = [QQ(1,2), QQ(1), QQ(0)]

    >>> dup_ff_lcm(f, g, QQ)
    [1/1, 7/2, 3/1, 0/1]

    """
    h = dup_exquo(dup_mul(f, g, K),
                  dup_gcd(f, g, K), K)

    return dup_monic(h, K)
Example #37
0
def dup_ff_lcm(f, g, K):
    """
    Computes polynomial LCM over a field in `K[x]`.

    Examples
    ========

    >>> from sympy.polys import ring, QQ
    >>> R, x = ring("x", QQ)

    >>> f = QQ(1,2)*x**2 + QQ(7,4)*x + QQ(3,2)
    >>> g = QQ(1,2)*x**2 + x

    >>> R.dup_ff_lcm(f, g)
    x**3 + 7/2*x**2 + 3*x

    """
    h = dup_quo(dup_mul(f, g, K), dup_gcd(f, g, K), K)

    return dup_monic(h, K)
Example #38
0
def dup_rr_lcm(f, g, K):
    """
    Computes polynomial LCM over a ring in `K[x]`.

    Examples
    ========

    >>> from sympy.polys import ring, ZZ
    >>> R, x = ring("x", ZZ)

    >>> R.dup_rr_lcm(x**2 - 1, x**2 - 3*x + 2)
    x**3 - 2*x**2 - x + 2

    """
    fc, f = dup_primitive(f, K)
    gc, g = dup_primitive(g, K)

    c = K.lcm(fc, gc)

    h = dup_quo(dup_mul(f, g, K), dup_gcd(f, g, K), K)

    return dup_mul_ground(h, c, K)
def dup_rr_lcm(f, g, K):
    """
    Computes polynomial LCM over a ring in `K[x]`.

    Examples
    ========

    >>> from sympy.polys import ring, ZZ
    >>> R, x = ring("x", ZZ)

    >>> R.dup_rr_lcm(x**2 - 1, x**2 - 3*x + 2)
    x**3 - 2*x**2 - x + 2

    """
    fc, f = dup_primitive(f, K)
    gc, g = dup_primitive(g, K)

    c = K.lcm(fc, gc)

    h = dup_quo(dup_mul(f, g, K), dup_gcd(f, g, K), K)

    return dup_mul_ground(h, c, K)
Example #40
0
def dup_gff_list(f, K):
    """
    Compute greatest factorial factorization of ``f`` in ``K[x]``.

    Examples
    ========

    >>> from sympy.polys.domains import ZZ
    >>> from sympy.polys.sqfreetools import dup_gff_list

    >>> f = ZZ.map([1, 2, -1, -2, 0, 0])

    >>> dup_gff_list(f, ZZ)
    [([1, 0], 1), ([1, 2], 4)]

    """
    if not f:
        raise ValueError(
            "greatest factorial factorization doesn't exist for a zero polynomial"
        )

    f = dup_monic(f, K)

    if not dup_degree(f):
        return []
    else:
        g = dup_gcd(f, dup_shift(f, K.one, K), K)
        H = dup_gff_list(g, K)

        for i, (h, k) in enumerate(H):
            g = dup_mul(g, dup_shift(h, -K(k), K), K)
            H[i] = (h, k + 1)

        f = dup_quo(f, g, K)

        if not dup_degree(f):
            return H
        else:
            return [(f, 1)] + H
Example #41
0
def dup_gff_list(f, K):
    """
    Compute greatest factorial factorization of ``f`` in ``K[x]``.

    Examples
    ========

    >>> from sympy.polys.domains import ZZ
    >>> from sympy.polys.sqfreetools import dup_gff_list

    >>> f = ZZ.map([1, 2, -1, -2, 0, 0])

    >>> dup_gff_list(f, ZZ)
    [([1, 0], 1), ([1, 2], 4)]

    """
    if not f:
        raise ValueError("greatest factorial factorization doesn't exist for a zero polynomial")

    f = dup_monic(f, K)

    if not dup_degree(f):
        return []
    else:
        g = dup_gcd(f, dup_shift(f, K.one, K), K)
        H = dup_gff_list(g, K)

        for i, (h, k) in enumerate(H):
            g = dup_mul(g, dup_shift(h, -K(k), K), K)
            H[i] = (h, k + 1)

        f = dup_quo(f, g, K)

        if not dup_degree(f):
            return H
        else:
            return [(f, 1)] + H
Example #42
0
def dmp_zz_modular_resultant(f, g, p, u, K):
    """
    Compute resultant of `f` and `g` modulo a prime `p`.

    Examples
    ========

    >>> from sympy.polys.domains import ZZ
    >>> from sympy.polys.euclidtools import dmp_zz_modular_resultant

    >>> f = ZZ.map([[1], [1, 2]])
    >>> g = ZZ.map([[2, 1], [3]])

    >>> dmp_zz_modular_resultant(f, g, ZZ(5), 1, ZZ)
    [-2, 0, 1]

    """
    if not u:
        return gf_int(dup_prs_resultant(f, g, K)[0] % p, p)

    v = u - 1

    n = dmp_degree(f, u)
    m = dmp_degree(g, u)

    N = dmp_degree_in(f, 1, u)
    M = dmp_degree_in(g, 1, u)

    B = n * M + m * N

    D, a = [K.one], -K.one
    r = dmp_zero(v)

    while dup_degree(D) <= B:
        while True:
            a += K.one

            if a == p:
                raise HomomorphismFailed('no luck')

            F = dmp_eval_in(f, gf_int(a, p), 1, u, K)

            if dmp_degree(F, v) == n:
                G = dmp_eval_in(g, gf_int(a, p), 1, u, K)

                if dmp_degree(G, v) == m:
                    break

        R = dmp_zz_modular_resultant(F, G, p, v, K)
        e = dmp_eval(r, a, v, K)

        if not v:
            R = dup_strip([R])
            e = dup_strip([e])
        else:
            R = [R]
            e = [e]

        d = K.invert(dup_eval(D, a, K), p)
        d = dup_mul_ground(D, d, K)
        d = dmp_raise(d, v, 0, K)

        c = dmp_mul(d, dmp_sub(R, e, v, K), v, K)
        r = dmp_add(r, c, v, K)

        r = dmp_ground_trunc(r, p, v, K)

        D = dup_mul(D, [K.one, -a], K)
        D = dup_trunc(D, p, K)

    return r
Example #43
0
 def mul(f, g):
     dom, per, F, G, mod = f.unify(g)
     return per(dup_rem(dup_mul(F, G, dom), mod, dom))
Example #44
0
 def mul(f, g):
     dom, per, F, G, mod = f.unify(g)
     return per(dup_rem(dup_mul(F, G, dom), mod, dom))
Example #45
0
def dmp_zz_modular_resultant(f, g, p, u, K):
    """
    Compute resultant of ``f`` and ``g`` modulo a prime ``p``.

    **Examples**

    >>> from sympy.polys.domains import ZZ
    >>> from sympy.polys.euclidtools import dmp_zz_modular_resultant

    >>> f = ZZ.map([[1], [1, 2]])
    >>> g = ZZ.map([[2, 1], [3]])

    >>> dmp_zz_modular_resultant(f, g, ZZ(5), 1, ZZ)
    [-2, 0, 1]

    """
    if not u:
        return gf_int(dup_prs_resultant(f, g, K)[0] % p, p)

    v = u - 1

    n = dmp_degree(f, u)
    m = dmp_degree(g, u)

    N = dmp_degree_in(f, 1, u)
    M = dmp_degree_in(g, 1, u)

    B = n*M + m*N

    D, a = [K.one], -K.one
    r = dmp_zero(v)

    while dup_degree(D) <= B:
        while True:
            a += K.one

            if a == p:
                raise HomomorphismFailed('no luck')

            F = dmp_eval_in(f, gf_int(a, p), 1, u, K)

            if dmp_degree(F, v) == n:
                G = dmp_eval_in(g, gf_int(a, p), 1, u, K)

                if dmp_degree(G, v) == m:
                    break

        R = dmp_zz_modular_resultant(F, G, p, v, K)
        e = dmp_eval(r, a, v, K)

        if not v:
            R = dup_strip([R])
            e = dup_strip([e])
        else:
            R = [R]
            e = [e]

        d = K.invert(dup_eval(D, a, K), p)
        d = dup_mul_ground(D, d, K)
        d = dmp_raise(d, v, 0, K)

        c = dmp_mul(d, dmp_sub(R, e, v, K), v, K)
        r = dmp_add(r, c, v, K)

        r = dmp_ground_trunc(r, p, v, K)

        D = dup_mul(D, [K.one, -a], K)
        D = dup_trunc(D, p, K)

    return r
Example #46
0
def dup_zz_zassenhaus(f, K):
    """Factor primitive square-free polynomials in `Z[x]`. """
    n = dup_degree(f)

    if n == 1:
        return [f]

    A = dup_max_norm(f, K)
    b = dup_LC(f, K)
    B = int(abs(K.sqrt(K(n + 1)) * 2**n * A * b))
    C = int((n + 1)**(2 * n) * A**(2 * n - 1))
    gamma = int(_ceil(2 * _log(C, 2)))
    bound = int(2 * gamma * _log(gamma))

    for p in xrange(3, bound + 1):
        if not isprime(p) or b % p == 0:
            continue

        p = K.convert(p)

        F = gf_from_int_poly(f, p)

        if gf_sqf_p(F, p, K):
            break

    l = int(_ceil(_log(2 * B + 1, p)))

    modular = []

    for ff in gf_factor_sqf(F, p, K)[1]:
        modular.append(gf_to_int_poly(ff, p))

    g = dup_zz_hensel_lift(p, f, modular, l, K)

    T = set(range(len(g)))
    factors, s = [], 1

    while 2 * s <= len(T):
        for S in subsets(T, s):
            G, H = [b], [b]

            S = set(S)

            for i in S:
                G = dup_mul(G, g[i], K)
            for i in T - S:
                H = dup_mul(H, g[i], K)

            G = dup_trunc(G, p**l, K)
            H = dup_trunc(H, p**l, K)

            G_norm = dup_l1_norm(G, K)
            H_norm = dup_l1_norm(H, K)

            if G_norm * H_norm <= B:
                T = T - S

                G = dup_primitive(G, K)[1]
                f = dup_primitive(H, K)[1]

                factors.append(G)
                b = dup_LC(f, K)

                break
        else:
            s += 1

    return factors + [f]
Example #47
0
 def div(f, g):
     dom, per, F, G, mod = f.unify(g)
     return (per(dup_rem(dup_mul(F, dup_invert(G, mod, dom), dom), mod, dom)), self.zero(mod, dom))
Example #48
0
 def quo(f, g):
     dom, per, F, G, mod = f.unify(g)
     return per(dup_rem(dup_mul(F, dup_invert(G, mod, dom), dom), mod, dom))
Example #49
0
def test_dup_expand():
    assert dup_expand((), ZZ) == [1]
    assert dup_expand(([1,2,3], [1,2], [7,5,4,3]), ZZ) == \
        dup_mul([1,2,3], dup_mul([1,2], [7,5,4,3], ZZ), ZZ)
Example #50
0
def dmp_zz_modular_resultant(f, g, p, u, K):
    """
    Compute resultant of `f` and `g` modulo a prime `p`.

    Examples
    ========

    >>> from sympy.polys import ring, ZZ
    >>> R, x,y = ring("x,y", ZZ)

    >>> f = x + y + 2
    >>> g = 2*x*y + x + 3

    >>> R.dmp_zz_modular_resultant(f, g, 5)
    -2*y**2 + 1

    """
    if not u:
        return gf_int(dup_prs_resultant(f, g, K)[0] % p, p)

    v = u - 1

    n = dmp_degree(f, u)
    m = dmp_degree(g, u)

    N = dmp_degree_in(f, 1, u)
    M = dmp_degree_in(g, 1, u)

    B = n*M + m*N

    D, a = [K.one], -K.one
    r = dmp_zero(v)

    while dup_degree(D) <= B:
        while True:
            a += K.one

            if a == p:
                raise HomomorphismFailed('no luck')

            F = dmp_eval_in(f, gf_int(a, p), 1, u, K)

            if dmp_degree(F, v) == n:
                G = dmp_eval_in(g, gf_int(a, p), 1, u, K)

                if dmp_degree(G, v) == m:
                    break

        R = dmp_zz_modular_resultant(F, G, p, v, K)
        e = dmp_eval(r, a, v, K)

        if not v:
            R = dup_strip([R])
            e = dup_strip([e])
        else:
            R = [R]
            e = [e]

        d = K.invert(dup_eval(D, a, K), p)
        d = dup_mul_ground(D, d, K)
        d = dmp_raise(d, v, 0, K)

        c = dmp_mul(d, dmp_sub(R, e, v, K), v, K)
        r = dmp_add(r, c, v, K)

        r = dmp_ground_trunc(r, p, v, K)

        D = dup_mul(D, [K.one, -a], K)
        D = dup_trunc(D, p, K)

    return r
Example #51
0
def dup_zz_zassenhaus(f, K):
    """Factor primitive square-free polynomials in `Z[x]`. """
    n = dup_degree(f)

    if n == 1:
        return [f]

    fc = f[-1]
    A = dup_max_norm(f, K)
    b = dup_LC(f, K)
    B = int(abs(K.sqrt(K(n + 1))*2**n*A*b))
    C = int((n + 1)**(2*n)*A**(2*n - 1))
    gamma = int(_ceil(2*_log(C, 2)))
    bound = int(2*gamma*_log(gamma))
    a = []
    # choose a prime number `p` such that `f` be square free in Z_p
    # if there are many factors in Z_p, choose among a few different `p`
    # the one with fewer factors
    for px in range(3, bound + 1):
        if not isprime(px) or b % px == 0:
            continue

        px = K.convert(px)

        F = gf_from_int_poly(f, px)

        if not gf_sqf_p(F, px, K):
            continue
        fsqfx = gf_factor_sqf(F, px, K)[1]
        a.append((px, fsqfx))
        if len(fsqfx) < 15 or len(a) > 4:
            break
    p, fsqf = min(a, key=lambda x: len(x[1]))

    l = int(_ceil(_log(2*B + 1, p)))

    modular = [gf_to_int_poly(ff, p) for ff in fsqf]

    g = dup_zz_hensel_lift(p, f, modular, l, K)

    sorted_T = range(len(g))
    T = set(sorted_T)
    factors, s = [], 1
    pl = p**l

    while 2*s <= len(T):
        for S in subsets(sorted_T, s):
            # lift the constant coefficient of the product `G` of the factors
            # in the subset `S`; if it is does not divide `fc`, `G` does
            # not divide the input polynomial

            if b == 1:
                q = 1
                for i in S:
                    q = q*g[i][-1]
                q = q % pl
                if not _test_pl(fc, q, pl):
                    continue
            else:
                G = [b]
                for i in S:
                    G = dup_mul(G, g[i], K)
                G = dup_trunc(G, pl, K)
                G = dup_primitive(G, K)[1]
                q = G[-1]
                if q and fc % q != 0:
                    continue

            H = [b]
            S = set(S)
            T_S = T - S

            if b == 1:
                G = [b]
                for i in S:
                    G = dup_mul(G, g[i], K)
                G = dup_trunc(G, pl, K)

            for i in T_S:
                H = dup_mul(H, g[i], K)

            H = dup_trunc(H, pl, K)

            G_norm = dup_l1_norm(G, K)
            H_norm = dup_l1_norm(H, K)

            if G_norm*H_norm <= B:
                T = T_S
                sorted_T = [i for i in sorted_T if i not in S]

                G = dup_primitive(G, K)[1]
                f = dup_primitive(H, K)[1]

                factors.append(G)
                b = dup_LC(f, K)

                break
        else:
            s += 1

    return factors + [f]
Example #52
0
 def quo(f, g):
     dom, per, F, G, mod = f.unify(g)
     return per(dup_rem(dup_mul(F, dup_invert(G, mod, dom), dom), mod, dom))
Example #53
0
def dup_zz_zassenhaus(f, K):
    """Factor primitive square-free polynomials in `Z[x]`. """
    n = dup_degree(f)

    if n == 1:
        return [f]

    A = dup_max_norm(f, K)
    b = dup_LC(f, K)
    B = int(abs(K.sqrt(K(n+1))*2**n*A*b))
    C = int((n+1)**(2*n)*A**(2*n-1))
    gamma = int(ceil(2*log(C, 2)))
    bound = int(2*gamma*log(gamma))

    for p in xrange(3, bound+1):
        if not isprime(p) or b % p == 0:
            continue

        p = K.convert(p)

        F = gf_from_int_poly(f, p)

        if gf_sqf_p(F, p, K):
            break

    l = int(ceil(log(2*B + 1, p)))

    modular = []

    for ff in gf_factor_sqf(F, p, K)[1]:
        modular.append(gf_to_int_poly(ff, p))

    g = dup_zz_hensel_lift(p, f, modular, l, K)

    T = set(range(len(g)))
    factors, s = [], 1

    while 2*s <= len(T):
        for S in subsets(T, s):
            G, H = [b], [b]

            S = set(S)

            for i in S:
                G = dup_mul(G, g[i], K)
            for i in T-S:
                H = dup_mul(H, g[i], K)

            G = dup_trunc(G, p**l, K)
            H = dup_trunc(H, p**l, K)

            G_norm = dup_l1_norm(G, K)
            H_norm = dup_l1_norm(H, K)

            if G_norm*H_norm <= B:
                T = T - S

                G = dup_primitive(G, K)[1]
                f = dup_primitive(H, K)[1]

                factors.append(G)
                b = dup_LC(f, K)

                break
        else:
            s += 1

    return factors + [f]
Example #54
0
def test_dup_mul():
    assert dup_mul([], [], ZZ) == []
    assert dup_mul([], [ZZ(1)], ZZ) == []
    assert dup_mul([ZZ(1)], [], ZZ) == []
    assert dup_mul([ZZ(1)], [ZZ(1)], ZZ) == [ZZ(1)]
    assert dup_mul([ZZ(5)], [ZZ(7)], ZZ) == [ZZ(35)]

    assert dup_mul([], [], QQ) == []
    assert dup_mul([], [QQ(1, 2)], QQ) == []
    assert dup_mul([QQ(1, 2)], [], QQ) == []
    assert dup_mul([QQ(1, 2)], [QQ(4, 7)], QQ) == [QQ(2, 7)]
    assert dup_mul([QQ(5, 7)], [QQ(3, 7)], QQ) == [QQ(15, 49)]

    f = dup_normal([3, 0, 0, 6, 1, 2], ZZ)
    g = dup_normal([4, 0, 1, 0], ZZ)
    h = dup_normal([12, 0, 3, 24, 4, 14, 1, 2, 0], ZZ)

    assert dup_mul(f, g, ZZ) == h
    assert dup_mul(g, f, ZZ) == h

    f = dup_normal([2, 0, 0, 1, 7], ZZ)
    h = dup_normal([4, 0, 0, 4, 28, 0, 1, 14, 49], ZZ)

    assert dup_mul(f, f, ZZ) == h

    K = FF(6)

    assert dup_mul([K(2), K(1)], [K(3), K(4)], K) == [K(5), K(4)]

    p1 = dup_normal([
        79, -1, 78, -94, -10, 11, 32, -19, 78, 2, -89, 30, 73, 42, 85, 77, 83,
        -30, -34, -2, 95, -81, 37, -49, -46, -58, -16, 37, 35, -11, -57, -15,
        -31, 67, -20, 27, 76, 2, 70, 67, -65, 65, -26, -93, -44, -12, -92, 57,
        -90, -57, -11, -67, -98, -69, 97, -41, 89, 33, 89, -50, 81, -31, 60,
        -27, 43, 29, -77, 44, 21, -91, 32, -57, 33, 3, 53, -51, -38, -99, -84,
        23, -50, 66, -100, 1, -75, -25, 27, -60, 98, -51, -87, 6, 8, 78, -28,
        -95, -88, 12, -35, 26, -9, 16, -92, 55, -7, -86, 68, -39, -46, 84, 94,
        45, 60, 92, 68, -75, -74, -19, 8, 75, 78, 91, 57, 34, 14, -3, -49, 65,
        78, -18, 6, -29, -80, -98, 17, 13, 58, 21, 20, 9, 37, 7, -30, -53, -20,
        34, 67, -42, 89, -22, 73, 43, -6, 5, 51, -8, -15, -52, -22, -58, -72,
        -3, 43, -92, 82, 83, -2, -13, -23, -60, 16, -94, -8, -28, -95, -72, 63,
        -90, 76, 6, -43, -100, -59, 76, 3, 3, 46, -85, 75, 62, -71, -76, 88,
        97, -72, -1, 30, -64, 72, -48, 14, -78, 58, 63, -91, 24, -87, -27, -80,
        -100, -44, 98, 70, 100, -29, -38, 11, 77, 100, 52, 86, 65, -5, -42,
        -81, -38, -42, 43, -2, -70, -63, -52
    ], ZZ)
    p2 = dup_normal([
        65, -19, -47, 1, 90, 81, -15, -34, 25, -75, 9, -83, 50, -5, -44, 31, 1,
        70, -7, 78, 74, 80, 85, 65, 21, 41, 66, 19, -40, 63, -21, -27, 32, 69,
        83, 34, -35, 14, 81, 57, -75, 32, -67, -89, -100, -61, 46, 84, -78,
        -29, -50, -94, -24, -32, -68, -16, 100, -7, -72, -89, 35, 82, 58, 81,
        -92, 62, 5, -47, -39, -58, -72, -13, 84, 44, 55, -25, 48, -54, -31,
        -56, -11, -50, -84, 10, 67, 17, 13, -14, 61, 76, -64, -44, -40, -96,
        11, -11, -94, 2, 6, 27, -6, 68, -54, 66, -74, -14, -1, -24, -73, 96,
        89, -11, -89, 56, -53, 72, -43, 96, 25, 63, -31, 29, 68, 83, 91, -93,
        -19, -38, -40, 40, -12, -19, -79, 44, 100, -66, -29, -77, 62, 39, -8,
        11, -97, 14, 87, 64, 21, -18, 13, 15, -59, -75, -99, -88, 57, 54, 56,
        -67, 6, -63, -59, -14, 28, 87, -20, -39, 84, -91, -2, 49, -75, 11, -24,
        -95, 36, 66, 5, 25, -72, -40, 86, 90, 37, -33, 57, -35, 29, -18, 4,
        -79, 64, -17, -27, 21, 29, -5, -44, -87, -24, 52, 78, 11, -23, -53, 36,
        42, 21, -68, 94, -91, -51, -21, 51, -76, 72, 31, 24, -48, -80, -9, 37,
        -47, -6, -8, -63, -91, 79, -79, -100, 38, -20, 38, 100, 83, -90, 87,
        63, -36, 82, -19, 18, -98, -38, 26, 98, -70, 79, 92, 12, 12, 70, 74,
        36, 48, -13, 31, 31, -47, -71, -12, -64, 36, -42, 32, -86, 60, 83, 70,
        55, 0, 1, 29, -35, 8, -82, 8, -73, -46, -50, 43, 48, -5, -86, -72, 44,
        -90, 19, 19, 5, -20, 97, -13, -66, -5, 5, -69, 64, -30, 41, 51, 36, 13,
        -99, -61, 94, -12, 74, 98, 68, 24, 46, -97, -87, -6, -27, 82, 62, -11,
        -77, 86, 66, -47, -49, -50, 13, 18, 89, -89, 46, -80, 13, 98, -35, -36,
        -25, 12, 20, 26, -52, 79, 27, 79, 100, 8, 62, -58, -28, 37
    ], ZZ)
    res = dup_normal([
        5135, -1566, 1376, -7466, 4579, 11710, 8001, -7183, -3737, -7439, 345,
        -10084, 24522, -1201, 1070, -10245, 9582, 9264, 1903, 23312, 18953,
        10037, -15268, -5450, 6442, -6243, -3777, 5110, 10936, -16649, -6022,
        16255, 31300, 24818, 31922, 32760, 7854, 27080, 15766, 29596, 7139,
        31945, -19810, 465, -38026, -3971, 9641, 465, -19375, 5524, -30112,
        -11960, -12813, 13535, 30670, 5925, -43725, -14089, 11503, -22782,
        6371, 43881, 37465, -33529, -33590, -39798, -37854, -18466, -7908,
        -35825, -26020, -36923, -11332, -5699, 25166, -3147, 19885, 12962,
        -20659, -1642, 27723, -56331, -24580, -11010, -20206, 20087, -23772,
        -16038, 38580, 20901, -50731, 32037, -4299, 26508, 18038, -28357,
        31846, -7405, -20172, -15894, 2096, 25110, -45786, 45918, -55333,
        -31928, -49428, -29824, -58796, -24609, -15408, 69, -35415, -18439,
        10123, -20360, -65949, 33356, -20333, 26476, -32073, 33621, 930, 28803,
        -42791, 44716, 38164, 12302, -1739, 11421, 73385, -7613, 14297, 38155,
        -414, 77587, 24338, -21415, 29367, 42639, 13901, -288, 51027, -11827,
        91260, 43407, 88521, -15186, 70572, -12049, 5090, -12208, -56374,
        15520, -623, -7742, 50825, 11199, -14894, 40892, 59591, -31356, -28696,
        -57842, -87751, -33744, -28436, -28945, -40287, 37957, -35638, 33401,
        -61534, 14870, 40292, 70366, -10803, 102290, -71719, -85251, 7902,
        -22409, 75009, 99927, 35298, -1175, -762, -34744, -10587, -47574,
        -62629, -19581, -43659, -54369, -32250, -39545, 15225, -24454, 11241,
        -67308, -30148, 39929, 37639, 14383, -73475, -77636, -81048, -35992,
        41601, -90143, 76937, -8112, 56588, 9124, -40094, -32340, 13253, 10898,
        -51639, 36390, 12086, -1885, 100714, -28561, -23784, -18735, 18916,
        16286, 10742, -87360, -13697, 10689, -19477, -29770, 5060, 20189,
        -8297, 112407, 47071, 47743, 45519, -4109, 17468, -68831, 78325, -6481,
        -21641, -19459, 30919, 96115, 8607, 53341, 32105, -16211, 23538, 57259,
        -76272, -40583, 62093, 38511, -34255, -40665, -40604, -37606, -15274,
        33156, -13885, 103636, 118678, -14101, -92682, -100791, 2634, 63791,
        98266, 19286, -34590, -21067, -71130, 25380, -40839, -27614, -26060,
        52358, -15537, 27138, -6749, 36269, -33306, 13207, -91084, -5540,
        -57116, 69548, 44169, -57742, -41234, -103327, -62904, -8566, 41149,
        -12866, 71188, 23980, 1838, 58230, 73950, 5594, 43113, -8159, -15925,
        6911, 85598, -75016, -16214, -62726, -39016, 8618, -63882, -4299,
        23182, 49959, 49342, -3238, -24913, -37138, 78361, 32451, 6337, -11438,
        -36241, -37737, 8169, -3077, -24829, 57953, 53016, -31511, -91168,
        12599, -41849, 41576, 55275, -62539, 47814, -62319, 12300, -32076,
        -55137, -84881, -27546, 4312, -3433, -54382, 113288, -30157, 74469,
        18219, 79880, -2124, 98911, 17655, -33499, -32861, 47242, -37393,
        99765, 14831, -44483, 10800, -31617, -52710, 37406, 22105, 29704,
        -20050, 13778, 43683, 36628, 8494, 60964, -22644, 31550, -17693, 33805,
        -124879, -12302, 19343, 20400, -30937, -21574, -34037, -33380, 56539,
        -24993, -75513, -1527, 53563, 65407, -101, 53577, 37991, 18717, -23795,
        -8090, -47987, -94717, 41967, 5170, -14815, -94311, 17896, -17734,
        -57718, -774, -38410, 24830, 29682, 76480, 58802, -46416, -20348,
        -61353, -68225, -68306, 23822, -31598, 42972, 36327, 28968, -65638,
        -21638, 24354, -8356, 26777, 52982, -11783, -44051, -26467, -44721,
        -28435, -53265, -25574, -2669, 44155, 22946, -18454, -30718, -11252,
        58420, 8711, 67447, 4425, 41749, 67543, 43162, 11793, -41907, 20477,
        -13080, 6559, -6104, -13244, 42853, 42935, 29793, 36730, -28087, 28657,
        17946, 7503, 7204, 21491, -27450, -24241, -98156, -18082, -42613,
        -24928, 10775, -14842, -44127, 55910, 14777, 31151, -2194, 39206,
        -2100, -4211, 11827, -8918, -19471, 72567, 36447, -65590, -34861,
        -17147, -45303, 9025, -7333, -35473, 11101, 11638, 3441, 6626, -41800,
        9416, 13679, 33508, 40502, -60542, 16358, 8392, -43242, -35864, -34127,
        -48721, 35878, 30598, 28630, 20279, -19983, -14638, -24455, -1851,
        -11344, 45150, 42051, 26034, -28889, -32382, -3527, -14532, 22564,
        -22346, 477, 11706, 28338, -25972, -9185, -22867, -12522, 32120, -4424,
        11339, -33913, -7184, 5101, -23552, -17115, -31401, -6104, 21906,
        25708, 8406, 6317, -7525, 5014, 20750, 20179, 22724, 11692, 13297,
        2493, -253, -16841, -17339, -6753, -4808, 2976, -10881, -10228, -13816,
        -12686, 1385, 2316, 2190, -875, -1924
    ], ZZ)

    assert dup_mul(p1, p2, ZZ) == res

    p1 = dup_normal([
        83, -61, -86, -24, 12, 43, -88, -9, 42, 55, -66, 74, 95, -25, -12, 68,
        -99, 4, 45, 6, -15, -19, 78, 65, -55, 47, -13, 17, 86, 81, -58, -27,
        50, -40, -24, 39, -41, -92, 75, 90, -1, 40, -15, -27, -35, 68, 70, -64,
        -40, 78, -88, -58, -39, 69, 46, 12, 28, -94, -37, -50, -80, -96, -61,
        25, 1, 71, 4, 12, 48, 4, 34, -47, -75, 5, 48, 82, 88, 23, 98, 35, 17,
        -10, 48, -61, -95, 47, 65, -19, -66, -57, -6, -51, -42, -89, 66, -13,
        18, 37, 90, -23, 72, 96, -53, 0, 40, -73, -52, -68, 32, -25, -53, 79,
        -52, 18, 44, 73, -81, 31, -90, 70, 3, 36, 48, 76, -24, -44, 23, 98, -4,
        73, 69, 88, -70, 14, -68, 94, -78, -15, -64, -97, -70, -35, 65, 88, 49,
        -53, -7, 12, -45, -7, 59, -94, 99, -2, 67, -60, -71, 29, -62, -77, 1,
        51, 17, 80, -20, -47, -19, 24, -9, 39, -23, 21, -84, 10, 84, 56, -17,
        -21, -66, 85, 70, 46, -51, -22, -95, 78, -60, -96, -97, -45, 72, 35,
        30, -61, -92, -93, -60, -61, 4, -4, -81, -73, 46, 53, -11, 26, 94, 45,
        14, -78, 55, 84, -68, 98, 60, 23, 100, -63, 68, 96, -16, 3, 56, 21,
        -58, 62, -67, 66, 85, 41, -79, -22, 97, -67, 82, 82, -96, -20, -7, 48,
        -67, 48, -9, -39, 78
    ], ZZ)
    p2 = dup_normal([
        52, 88, 76, 66, 9, -64, 46, -20, -28, 69, 60, 96, -36, -92, -30, -11,
        -35, 35, 55, 63, -92, -7, 25, -58, 74, 55, -6, 4, 47, -92, -65, 67,
        -45, 74, -76, 59, -6, 69, 39, 24, -71, -7, 39, -45, 60, -68, 98, 97,
        -79, 17, 4, 94, -64, 68, -100, -96, -2, 3, 22, 96, 54, -77, -86, 67, 6,
        57, 37, 40, 89, -78, 64, -94, -45, -92, 57, 87, -26, 36, 19, 97, 25,
        77, -87, 24, 43, -5, 35, 57, 83, 71, 35, 63, 61, 96, -22, 8, -1, 96,
        43, 45, 94, -93, 36, 71, -41, -99, 85, -48, 59, 52, -17, 5, 87, -16,
        -68, -54, 76, -18, 100, 91, -42, -70, -66, -88, -12, 1, 95, -82, 52,
        43, -29, 3, 12, 72, -99, -43, -32, -93, -51, 16, -20, -12, -11, 5, 33,
        -38, 93, -5, -74, 25, 74, -58, 93, 59, -63, -86, 63, -20, -4, -74, -73,
        -95, 29, -28, 93, -91, -2, -38, -62, 77, -58, -85, -28, 95, 38, 19,
        -69, 86, 94, 25, -2, -4, 47, 34, -59, 35, -48, 29, -63, -53, 34, 29,
        66, 73, 6, 92, -84, 89, 15, 81, 93, 97, 51, -72, -78, 25, 60, 90, -45,
        39, 67, -84, -62, 57, 26, -32, -56, -14, -83, 76, 5, -2, 99, -100, 28,
        46, 94, -7, 53, -25, 16, -23, -36, 89, -78, -63, 31, 1, 84, -99, -52,
        76, 48, 90, -76, 44, -19, 54, -36, -9, -73, -100, -69, 31, 42, 25, -39,
        76, -26, -8, -14, 51, 3, 37, 45, 2, -54, 13, -34, -92, 17, -25, -65,
        53, -63, 30, 4, -70, -67, 90, 52, 51, 18, -3, 31, -45, -9, 59, 63, -87,
        22, -32, 29, -38, 21, 36, -82, 27, -11
    ], ZZ)
    res = dup_normal([
        4316, 4132, -3532, -7974, -11303, -10069, 5484, -3330, -5874, 7734,
        4673, 11327, -9884, -8031, 17343, 21035, -10570, -9285, 15893, 3780,
        -14083, 8819, 17592, 10159, 7174, -11587, 8598, -16479, 3602, 25596,
        9781, 12163, 150, 18749, -21782, -12307, 27578, -2757, -12573, 12565,
        6345, -18956, 19503, -15617, 1443, -16778, 36851, 23588, -28474, 5749,
        40695, -7521, -53669, -2497, -18530, 6770, 57038, 3926, -6927, -15399,
        1848, -64649, -27728, 3644, 49608, 15187, -8902, -9480, -7398, -40425,
        4824, 23767, -7594, -6905, 33089, 18786, 12192, 24670, 31114, 35334,
        -4501, -14676, 7107, -59018, -21352, 20777, 19661, 20653, 33754, -885,
        -43758, 6269, 51897, -28719, -97488, -9527, 13746, 11644, 17644,
        -21720, 23782, -10481, 47867, 20752, 33810, -1875, 39918, -7710,
        -40840, 19808, -47075, 23066, 46616, 25201, 9287, 35436, -1602, 9645,
        -11978, 13273, 15544, 33465, 20063, 44539, 11687, 27314, -6538, -37467,
        14031, 32970, -27086, 41323, 29551, 65910, -39027, -37800, -22232,
        8212, 46316, -28981, -55282, 50417, -44929, -44062, 73879, 37573,
        -2596, -10877, -21893, -133218, -33707, -25753, -9531, 17530, 61126,
        2748, -56235, 43874, -10872, -90459, -30387, 115267, -7264, -44452,
        122626, 14839, -599, 10337, 57166, -67467, -54957, 63669, 1202, 18488,
        52594, 7205, -97822, 612, 78069, -5403, -63562, 47236, 36873, -154827,
        -26188, 82427, -39521, 5628, 7416, 5276, -53095, 47050, 26121, -42207,
        79021, -13035, 2499, -66943, 29040, -72355, -23480, 23416, -12885,
        -44225, -42688, -4224, 19858, 55299, 15735, 11465, 101876, -39169,
        51786, 14723, 43280, -68697, 16410, 92295, 56767, 7183, 111850, 4550,
        115451, -38443, -19642, -35058, 10230, 93829, 8925, 63047, 3146, 29250,
        8530, 5255, -98117, -115517, -76817, -8724, 41044, 1312, -35974, 79333,
        -28567, 7547, -10580, -24559, -16238, 10794, -3867, 24848, 57770,
        -51536, -35040, 71033, 29853, 62029, -7125, -125585, -32169, -47907,
        156811, -65176, -58006, -15757, -57861, 11963, 30225, -41901, -41681,
        31310, 27982, 18613, 61760, 60746, -59096, 33499, 30097, -17997, 24032,
        56442, -83042, 23747, -20931, -21978, -158752, -9883, -73598, -7987,
        -7333, -125403, -116329, 30585, 53281, 51018, -29193, 88575, 8264,
        -40147, -16289, 113088, 12810, -6508, 101552, -13037, 34440, -41840,
        101643, 24263, 80532, 61748, 65574, 6423, -20672, 6591, -10834, -71716,
        86919, -92626, 39161, 28490, 81319, 46676, 106720, 43530, 26998, 57456,
        -8862, 60989, 13982, 3119, -2224, 14743, 55415, -49093, -29303, 28999,
        1789, 55953, -84043, -7780, -65013, 57129, -47251, 61484, 61994,
        -78361, -82778, 22487, -26894, 9756, -74637, -15519, -4360, 30115,
        42433, 35475, 15286, 69768, 21509, -20214, 78675, -21163, 13596, 11443,
        -10698, -53621, -53867, -24155, 64500, -42784, -33077, -16500, 873,
        -52788, 14546, -38011, 36974, -39849, -34029, -94311, 83068, -50437,
        -26169, -46746, 59185, 42259, -101379, -12943, 30089, -59086, 36271,
        22723, -30253, -52472, -70826, -23289, 3331, -31687, 14183, -857,
        -28627, 35246, -51284, 5636, -6933, 66539, 36654, 50927, 24783, 3457,
        33276, 45281, 45650, -4938, -9968, -22590, 47995, 69229, 5214, -58365,
        -17907, -14651, 18668, 18009, 12649, -11851, -13387, 20339, 52472,
        -1087, -21458, -68647, 52295, 15849, 40608, 15323, 25164, -29368,
        10352, -7055, 7159, 21695, -5373, -54849, 101103, -24963, -10511,
        33227, 7659, 41042, -69588, 26718, -20515, 6441, 38135, -63, 24088,
        -35364, -12785, -18709, 47843, 48533, -48575, 17251, -19394, 32878,
        -9010, -9050, 504, -12407, 28076, -3429, 25324, -4210, -26119, 752,
        -29203, 28251, -11324, -32140, -3366, -25135, 18702, -31588, -7047,
        -24267, 49987, -14975, -33169, 37744, -7720, -9035, 16964, -2807, -421,
        14114, -17097, -13662, 40628, -12139, -9427, 5369, 17551, -13232,
        -16211, 9804, -7422, 2677, 28635, -8280, -4906, 2908, -22558, 5604,
        12459, 8756, -3980, -4745, -18525, 7913, 5970, -16457, 20230, -6247,
        -13812, 2505, 11899, 1409, -15094, 22540, -18863, 137, 11123, -4516,
        2290, -8594, 12150, -10380, 3005, 5235, -7350, 2535, -858
    ], ZZ)

    assert dup_mul(p1, p2, ZZ) == res
Example #55
0
def test_dup_mul():
    assert dup_mul([], [], ZZ) == []
    assert dup_mul([], [ZZ(1)], ZZ) == []
    assert dup_mul([ZZ(1)], [], ZZ) == []
    assert dup_mul([ZZ(1)], [ZZ(1)], ZZ) == [ZZ(1)]
    assert dup_mul([ZZ(5)], [ZZ(7)], ZZ) == [ZZ(35)]

    assert dup_mul([], [], QQ) == []
    assert dup_mul([], [QQ(1,2)], QQ) == []
    assert dup_mul([QQ(1,2)], [], QQ) == []
    assert dup_mul([QQ(1,2)], [QQ(4,7)], QQ) == [QQ(2,7)]
    assert dup_mul([QQ(5,7)], [QQ(3,7)], QQ) == [QQ(15,49)]

    f = dup_normal([3,0,0,6,1,2], ZZ)
    g = dup_normal([4,0,1,0], ZZ)
    h = dup_normal([12,0,3,24,4,14,1,2,0], ZZ)

    assert dup_mul(f, g, ZZ) == h
    assert dup_mul(g, f, ZZ) == h

    f = dup_normal([2,0,0,1,7], ZZ)
    h = dup_normal([4,0,0,4,28,0,1,14,49], ZZ)

    assert dup_mul(f, f, ZZ) == h

    K = FF(6)

    assert dup_mul([K(2),K(1)], [K(3),K(4)], K) == [K(5),K(4)]
Example #56
0
def dup_zz_zassenhaus(f, K):
    """Factor primitive square-free polynomials in `Z[x]`. """
    n = dup_degree(f)

    if n == 1:
        return [f]

    fc = f[-1]
    A = dup_max_norm(f, K)
    b = dup_LC(f, K)
    B = int(abs(K.sqrt(K(n + 1)) * 2**n * A * b))
    C = int((n + 1)**(2 * n) * A**(2 * n - 1))
    gamma = int(_ceil(2 * _log(C, 2)))
    bound = int(2 * gamma * _log(gamma))
    a = []
    # choose a prime number `p` such that `f` be square free in Z_p
    # if there are many factors in Z_p, choose among a few different `p`
    # the one with fewer factors
    for px in xrange(3, bound + 1):
        if not isprime(px) or b % px == 0:
            continue

        px = K.convert(px)

        F = gf_from_int_poly(f, px)

        if not gf_sqf_p(F, px, K):
            continue
        fsqfx = gf_factor_sqf(F, px, K)[1]
        a.append((px, fsqfx))
        if len(fsqfx) < 15 or len(a) > 4:
            break
    p, fsqf = min(a, key=lambda x: len(x[1]))

    l = int(_ceil(_log(2 * B + 1, p)))

    modular = [gf_to_int_poly(ff, p) for ff in fsqf]

    g = dup_zz_hensel_lift(p, f, modular, l, K)

    sorted_T = range(len(g))
    T = set(sorted_T)
    factors, s = [], 1
    pl = p**l

    while 2 * s <= len(T):
        for S in subsets(sorted_T, s):
            # lift the constant coefficient of the product `G` of the factors
            # in the subset `S`; if it is does not divide `fc`, `G` does
            # not divide the input polynomial

            if b == 1:
                q = 1
                for i in S:
                    q = q * g[i][-1]
                q = q % pl
                if not _test_pl(fc, q, pl):
                    continue
            else:
                G = [b]
                for i in S:
                    G = dup_mul(G, g[i], K)
                G = dup_trunc(G, pl, K)
                G1 = dup_primitive(G, K)[1]
                q = G1[-1]
                if q and fc % q != 0:
                    continue

            H = [b]
            S = set(S)
            T_S = T - S

            if b == 1:
                G = [b]
                for i in S:
                    G = dup_mul(G, g[i], K)
                G = dup_trunc(G, pl, K)

            for i in T_S:
                H = dup_mul(H, g[i], K)

            H = dup_trunc(H, pl, K)

            G_norm = dup_l1_norm(G, K)
            H_norm = dup_l1_norm(H, K)

            if G_norm * H_norm <= B:
                T = T_S
                sorted_T = [i for i in sorted_T if i not in S]

                G = dup_primitive(G, K)[1]
                f = dup_primitive(H, K)[1]

                factors.append(G)
                b = dup_LC(f, K)

                break
        else:
            s += 1

    return factors + [f]
Example #57
0
 def div(f, g):
     dom, per, F, G, mod = f.unify(g)
     return (per(dup_rem(dup_mul(F, dup_invert(G, mod, dom), dom), mod, dom)), self.zero(mod, dom))
Example #58
0
def dmp_zz_modular_resultant(f, g, p, u, K):
    """
    Compute resultant of `f` and `g` modulo a prime `p`.

    Examples
    ========

    >>> from sympy.polys import ring, ZZ
    >>> R, x,y = ring("x,y", ZZ)

    >>> f = x + y + 2
    >>> g = 2*x*y + x + 3

    >>> R.dmp_zz_modular_resultant(f, g, 5)
    -2*y**2 + 1

    """
    if not u:
        return gf_int(dup_prs_resultant(f, g, K)[0] % p, p)

    v = u - 1

    n = dmp_degree(f, u)
    m = dmp_degree(g, u)

    N = dmp_degree_in(f, 1, u)
    M = dmp_degree_in(g, 1, u)

    B = n*M + m*N

    D, a = [K.one], -K.one
    r = dmp_zero(v)

    while dup_degree(D) <= B:
        while True:
            a += K.one

            if a == p:
                raise HomomorphismFailed('no luck')

            F = dmp_eval_in(f, gf_int(a, p), 1, u, K)

            if dmp_degree(F, v) == n:
                G = dmp_eval_in(g, gf_int(a, p), 1, u, K)

                if dmp_degree(G, v) == m:
                    break

        R = dmp_zz_modular_resultant(F, G, p, v, K)
        e = dmp_eval(r, a, v, K)

        if not v:
            R = dup_strip([R])
            e = dup_strip([e])
        else:
            R = [R]
            e = [e]

        d = K.invert(dup_eval(D, a, K), p)
        d = dup_mul_ground(D, d, K)
        d = dmp_raise(d, v, 0, K)

        c = dmp_mul(d, dmp_sub(R, e, v, K), v, K)
        r = dmp_add(r, c, v, K)

        r = dmp_ground_trunc(r, p, v, K)

        D = dup_mul(D, [K.one, -a], K)
        D = dup_trunc(D, p, K)

    return r