|
"""Basic tools for dense recursive polynomials in ``K[x]`` or ``K[X]``. """ |
|
|
|
|
|
from sympy.core import igcd |
|
from sympy.polys.monomials import monomial_min, monomial_div |
|
from sympy.polys.orderings import monomial_key |
|
|
|
import random |
|
|
|
|
|
ninf = float('-inf') |
|
|
|
|
|
def poly_LC(f, K): |
|
""" |
|
Return leading coefficient of ``f``. |
|
|
|
Examples |
|
======== |
|
|
|
>>> from sympy.polys.domains import ZZ |
|
>>> from sympy.polys.densebasic import poly_LC |
|
|
|
>>> poly_LC([], ZZ) |
|
0 |
|
>>> poly_LC([ZZ(1), ZZ(2), ZZ(3)], ZZ) |
|
1 |
|
|
|
""" |
|
if not f: |
|
return K.zero |
|
else: |
|
return f[0] |
|
|
|
|
|
def poly_TC(f, K): |
|
""" |
|
Return trailing coefficient of ``f``. |
|
|
|
Examples |
|
======== |
|
|
|
>>> from sympy.polys.domains import ZZ |
|
>>> from sympy.polys.densebasic import poly_TC |
|
|
|
>>> poly_TC([], ZZ) |
|
0 |
|
>>> poly_TC([ZZ(1), ZZ(2), ZZ(3)], ZZ) |
|
3 |
|
|
|
""" |
|
if not f: |
|
return K.zero |
|
else: |
|
return f[-1] |
|
|
|
dup_LC = dmp_LC = poly_LC |
|
dup_TC = dmp_TC = poly_TC |
|
|
|
|
|
def dmp_ground_LC(f, u, K): |
|
""" |
|
Return the ground leading coefficient. |
|
|
|
Examples |
|
======== |
|
|
|
>>> from sympy.polys.domains import ZZ |
|
>>> from sympy.polys.densebasic import dmp_ground_LC |
|
|
|
>>> f = ZZ.map([[[1], [2, 3]]]) |
|
|
|
>>> dmp_ground_LC(f, 2, ZZ) |
|
1 |
|
|
|
""" |
|
while u: |
|
f = dmp_LC(f, K) |
|
u -= 1 |
|
|
|
return dup_LC(f, K) |
|
|
|
|
|
def dmp_ground_TC(f, u, K): |
|
""" |
|
Return the ground trailing coefficient. |
|
|
|
Examples |
|
======== |
|
|
|
>>> from sympy.polys.domains import ZZ |
|
>>> from sympy.polys.densebasic import dmp_ground_TC |
|
|
|
>>> f = ZZ.map([[[1], [2, 3]]]) |
|
|
|
>>> dmp_ground_TC(f, 2, ZZ) |
|
3 |
|
|
|
""" |
|
while u: |
|
f = dmp_TC(f, K) |
|
u -= 1 |
|
|
|
return dup_TC(f, K) |
|
|
|
|
|
def dmp_true_LT(f, u, K): |
|
""" |
|
Return the leading term ``c * x_1**n_1 ... x_k**n_k``. |
|
|
|
Examples |
|
======== |
|
|
|
>>> from sympy.polys.domains import ZZ |
|
>>> from sympy.polys.densebasic import dmp_true_LT |
|
|
|
>>> f = ZZ.map([[4], [2, 0], [3, 0, 0]]) |
|
|
|
>>> dmp_true_LT(f, 1, ZZ) |
|
((2, 0), 4) |
|
|
|
""" |
|
monom = [] |
|
|
|
while u: |
|
monom.append(len(f) - 1) |
|
f, u = f[0], u - 1 |
|
|
|
if not f: |
|
monom.append(0) |
|
else: |
|
monom.append(len(f) - 1) |
|
|
|
return tuple(monom), dup_LC(f, K) |
|
|
|
|
|
def dup_degree(f): |
|
""" |
|
Return the leading degree of ``f`` in ``K[x]``. |
|
|
|
Note that the degree of 0 is negative infinity (``float('-inf')``). |
|
|
|
Examples |
|
======== |
|
|
|
>>> from sympy.polys.domains import ZZ |
|
>>> from sympy.polys.densebasic import dup_degree |
|
|
|
>>> f = ZZ.map([1, 2, 0, 3]) |
|
|
|
>>> dup_degree(f) |
|
3 |
|
|
|
""" |
|
if not f: |
|
return ninf |
|
return len(f) - 1 |
|
|
|
|
|
def dmp_degree(f, u): |
|
""" |
|
Return the leading degree of ``f`` in ``x_0`` in ``K[X]``. |
|
|
|
Note that the degree of 0 is negative infinity (``float('-inf')``). |
|
|
|
Examples |
|
======== |
|
|
|
>>> from sympy.polys.domains import ZZ |
|
>>> from sympy.polys.densebasic import dmp_degree |
|
|
|
>>> dmp_degree([[[]]], 2) |
|
-inf |
|
|
|
>>> f = ZZ.map([[2], [1, 2, 3]]) |
|
|
|
>>> dmp_degree(f, 1) |
|
1 |
|
|
|
""" |
|
if dmp_zero_p(f, u): |
|
return ninf |
|
else: |
|
return len(f) - 1 |
|
|
|
|
|
def _rec_degree_in(g, v, i, j): |
|
"""Recursive helper function for :func:`dmp_degree_in`.""" |
|
if i == j: |
|
return dmp_degree(g, v) |
|
|
|
v, i = v - 1, i + 1 |
|
|
|
return max(_rec_degree_in(c, v, i, j) for c in g) |
|
|
|
|
|
def dmp_degree_in(f, j, u): |
|
""" |
|
Return the leading degree of ``f`` in ``x_j`` in ``K[X]``. |
|
|
|
Examples |
|
======== |
|
|
|
>>> from sympy.polys.domains import ZZ |
|
>>> from sympy.polys.densebasic import dmp_degree_in |
|
|
|
>>> f = ZZ.map([[2], [1, 2, 3]]) |
|
|
|
>>> dmp_degree_in(f, 0, 1) |
|
1 |
|
>>> dmp_degree_in(f, 1, 1) |
|
2 |
|
|
|
""" |
|
if not j: |
|
return dmp_degree(f, u) |
|
if j < 0 or j > u: |
|
raise IndexError("0 <= j <= %s expected, got %s" % (u, j)) |
|
|
|
return _rec_degree_in(f, u, 0, j) |
|
|
|
|
|
def _rec_degree_list(g, v, i, degs): |
|
"""Recursive helper for :func:`dmp_degree_list`.""" |
|
degs[i] = max(degs[i], dmp_degree(g, v)) |
|
|
|
if v > 0: |
|
v, i = v - 1, i + 1 |
|
|
|
for c in g: |
|
_rec_degree_list(c, v, i, degs) |
|
|
|
|
|
def dmp_degree_list(f, u): |
|
""" |
|
Return a list of degrees of ``f`` in ``K[X]``. |
|
|
|
Examples |
|
======== |
|
|
|
>>> from sympy.polys.domains import ZZ |
|
>>> from sympy.polys.densebasic import dmp_degree_list |
|
|
|
>>> f = ZZ.map([[1], [1, 2, 3]]) |
|
|
|
>>> dmp_degree_list(f, 1) |
|
(1, 2) |
|
|
|
""" |
|
degs = [ninf]*(u + 1) |
|
_rec_degree_list(f, u, 0, degs) |
|
return tuple(degs) |
|
|
|
|
|
def dup_strip(f): |
|
""" |
|
Remove leading zeros from ``f`` in ``K[x]``. |
|
|
|
Examples |
|
======== |
|
|
|
>>> from sympy.polys.densebasic import dup_strip |
|
|
|
>>> dup_strip([0, 0, 1, 2, 3, 0]) |
|
[1, 2, 3, 0] |
|
|
|
""" |
|
if not f or f[0]: |
|
return f |
|
|
|
i = 0 |
|
|
|
for cf in f: |
|
if cf: |
|
break |
|
else: |
|
i += 1 |
|
|
|
return f[i:] |
|
|
|
|
|
def dmp_strip(f, u): |
|
""" |
|
Remove leading zeros from ``f`` in ``K[X]``. |
|
|
|
Examples |
|
======== |
|
|
|
>>> from sympy.polys.densebasic import dmp_strip |
|
|
|
>>> dmp_strip([[], [0, 1, 2], [1]], 1) |
|
[[0, 1, 2], [1]] |
|
|
|
""" |
|
if not u: |
|
return dup_strip(f) |
|
|
|
if dmp_zero_p(f, u): |
|
return f |
|
|
|
i, v = 0, u - 1 |
|
|
|
for c in f: |
|
if not dmp_zero_p(c, v): |
|
break |
|
else: |
|
i += 1 |
|
|
|
if i == len(f): |
|
return dmp_zero(u) |
|
else: |
|
return f[i:] |
|
|
|
|
|
def _rec_validate(f, g, i, K): |
|
"""Recursive helper for :func:`dmp_validate`.""" |
|
if not isinstance(g, list): |
|
if K is not None and not K.of_type(g): |
|
raise TypeError("%s in %s in not of type %s" % (g, f, K.dtype)) |
|
|
|
return {i - 1} |
|
elif not g: |
|
return {i} |
|
else: |
|
levels = set() |
|
|
|
for c in g: |
|
levels |= _rec_validate(f, c, i + 1, K) |
|
|
|
return levels |
|
|
|
|
|
def _rec_strip(g, v): |
|
"""Recursive helper for :func:`_rec_strip`.""" |
|
if not v: |
|
return dup_strip(g) |
|
|
|
w = v - 1 |
|
|
|
return dmp_strip([ _rec_strip(c, w) for c in g ], v) |
|
|
|
|
|
def dmp_validate(f, K=None): |
|
""" |
|
Return the number of levels in ``f`` and recursively strip it. |
|
|
|
Examples |
|
======== |
|
|
|
>>> from sympy.polys.densebasic import dmp_validate |
|
|
|
>>> dmp_validate([[], [0, 1, 2], [1]]) |
|
([[1, 2], [1]], 1) |
|
|
|
>>> dmp_validate([[1], 1]) |
|
Traceback (most recent call last): |
|
... |
|
ValueError: invalid data structure for a multivariate polynomial |
|
|
|
""" |
|
levels = _rec_validate(f, f, 0, K) |
|
|
|
u = levels.pop() |
|
|
|
if not levels: |
|
return _rec_strip(f, u), u |
|
else: |
|
raise ValueError( |
|
"invalid data structure for a multivariate polynomial") |
|
|
|
|
|
def dup_reverse(f): |
|
""" |
|
Compute ``x**n * f(1/x)``, i.e.: reverse ``f`` in ``K[x]``. |
|
|
|
Examples |
|
======== |
|
|
|
>>> from sympy.polys.domains import ZZ |
|
>>> from sympy.polys.densebasic import dup_reverse |
|
|
|
>>> f = ZZ.map([1, 2, 3, 0]) |
|
|
|
>>> dup_reverse(f) |
|
[3, 2, 1] |
|
|
|
""" |
|
return dup_strip(list(reversed(f))) |
|
|
|
|
|
def dup_copy(f): |
|
""" |
|
Create a new copy of a polynomial ``f`` in ``K[x]``. |
|
|
|
Examples |
|
======== |
|
|
|
>>> from sympy.polys.domains import ZZ |
|
>>> from sympy.polys.densebasic import dup_copy |
|
|
|
>>> f = ZZ.map([1, 2, 3, 0]) |
|
|
|
>>> dup_copy([1, 2, 3, 0]) |
|
[1, 2, 3, 0] |
|
|
|
""" |
|
return list(f) |
|
|
|
|
|
def dmp_copy(f, u): |
|
""" |
|
Create a new copy of a polynomial ``f`` in ``K[X]``. |
|
|
|
Examples |
|
======== |
|
|
|
>>> from sympy.polys.domains import ZZ |
|
>>> from sympy.polys.densebasic import dmp_copy |
|
|
|
>>> f = ZZ.map([[1], [1, 2]]) |
|
|
|
>>> dmp_copy(f, 1) |
|
[[1], [1, 2]] |
|
|
|
""" |
|
if not u: |
|
return list(f) |
|
|
|
v = u - 1 |
|
|
|
return [ dmp_copy(c, v) for c in f ] |
|
|
|
|
|
def dup_to_tuple(f): |
|
""" |
|
Convert `f` into a tuple. |
|
|
|
This is needed for hashing. This is similar to dup_copy(). |
|
|
|
Examples |
|
======== |
|
|
|
>>> from sympy.polys.domains import ZZ |
|
>>> from sympy.polys.densebasic import dup_copy |
|
|
|
>>> f = ZZ.map([1, 2, 3, 0]) |
|
|
|
>>> dup_copy([1, 2, 3, 0]) |
|
[1, 2, 3, 0] |
|
|
|
""" |
|
return tuple(f) |
|
|
|
|
|
def dmp_to_tuple(f, u): |
|
""" |
|
Convert `f` into a nested tuple of tuples. |
|
|
|
This is needed for hashing. This is similar to dmp_copy(). |
|
|
|
Examples |
|
======== |
|
|
|
>>> from sympy.polys.domains import ZZ |
|
>>> from sympy.polys.densebasic import dmp_to_tuple |
|
|
|
>>> f = ZZ.map([[1], [1, 2]]) |
|
|
|
>>> dmp_to_tuple(f, 1) |
|
((1,), (1, 2)) |
|
|
|
""" |
|
if not u: |
|
return tuple(f) |
|
v = u - 1 |
|
|
|
return tuple(dmp_to_tuple(c, v) for c in f) |
|
|
|
|
|
def dup_normal(f, K): |
|
""" |
|
Normalize univariate polynomial in the given domain. |
|
|
|
Examples |
|
======== |
|
|
|
>>> from sympy.polys.domains import ZZ |
|
>>> from sympy.polys.densebasic import dup_normal |
|
|
|
>>> dup_normal([0, 1, 2, 3], ZZ) |
|
[1, 2, 3] |
|
|
|
""" |
|
return dup_strip([ K.normal(c) for c in f ]) |
|
|
|
|
|
def dmp_normal(f, u, K): |
|
""" |
|
Normalize a multivariate polynomial in the given domain. |
|
|
|
Examples |
|
======== |
|
|
|
>>> from sympy.polys.domains import ZZ |
|
>>> from sympy.polys.densebasic import dmp_normal |
|
|
|
>>> dmp_normal([[], [0, 1, 2]], 1, ZZ) |
|
[[1, 2]] |
|
|
|
""" |
|
if not u: |
|
return dup_normal(f, K) |
|
|
|
v = u - 1 |
|
|
|
return dmp_strip([ dmp_normal(c, v, K) for c in f ], u) |
|
|
|
|
|
def dup_convert(f, K0, K1): |
|
""" |
|
Convert the ground domain of ``f`` from ``K0`` to ``K1``. |
|
|
|
Examples |
|
======== |
|
|
|
>>> from sympy.polys.rings import ring |
|
>>> from sympy.polys.domains import ZZ |
|
>>> from sympy.polys.densebasic import dup_convert |
|
|
|
>>> R, x = ring("x", ZZ) |
|
|
|
>>> dup_convert([R(1), R(2)], R.to_domain(), ZZ) |
|
[1, 2] |
|
>>> dup_convert([ZZ(1), ZZ(2)], ZZ, R.to_domain()) |
|
[1, 2] |
|
|
|
""" |
|
if K0 is not None and K0 == K1: |
|
return f |
|
else: |
|
return dup_strip([ K1.convert(c, K0) for c in f ]) |
|
|
|
|
|
def dmp_convert(f, u, K0, K1): |
|
""" |
|
Convert the ground domain of ``f`` from ``K0`` to ``K1``. |
|
|
|
Examples |
|
======== |
|
|
|
>>> from sympy.polys.rings import ring |
|
>>> from sympy.polys.domains import ZZ |
|
>>> from sympy.polys.densebasic import dmp_convert |
|
|
|
>>> R, x = ring("x", ZZ) |
|
|
|
>>> dmp_convert([[R(1)], [R(2)]], 1, R.to_domain(), ZZ) |
|
[[1], [2]] |
|
>>> dmp_convert([[ZZ(1)], [ZZ(2)]], 1, ZZ, R.to_domain()) |
|
[[1], [2]] |
|
|
|
""" |
|
if not u: |
|
return dup_convert(f, K0, K1) |
|
if K0 is not None and K0 == K1: |
|
return f |
|
|
|
v = u - 1 |
|
|
|
return dmp_strip([ dmp_convert(c, v, K0, K1) for c in f ], u) |
|
|
|
|
|
def dup_from_sympy(f, K): |
|
""" |
|
Convert the ground domain of ``f`` from SymPy to ``K``. |
|
|
|
Examples |
|
======== |
|
|
|
>>> from sympy import S |
|
>>> from sympy.polys.domains import ZZ |
|
>>> from sympy.polys.densebasic import dup_from_sympy |
|
|
|
>>> dup_from_sympy([S(1), S(2)], ZZ) == [ZZ(1), ZZ(2)] |
|
True |
|
|
|
""" |
|
return dup_strip([ K.from_sympy(c) for c in f ]) |
|
|
|
|
|
def dmp_from_sympy(f, u, K): |
|
""" |
|
Convert the ground domain of ``f`` from SymPy to ``K``. |
|
|
|
Examples |
|
======== |
|
|
|
>>> from sympy import S |
|
>>> from sympy.polys.domains import ZZ |
|
>>> from sympy.polys.densebasic import dmp_from_sympy |
|
|
|
>>> dmp_from_sympy([[S(1)], [S(2)]], 1, ZZ) == [[ZZ(1)], [ZZ(2)]] |
|
True |
|
|
|
""" |
|
if not u: |
|
return dup_from_sympy(f, K) |
|
|
|
v = u - 1 |
|
|
|
return dmp_strip([ dmp_from_sympy(c, v, K) for c in f ], u) |
|
|
|
|
|
def dup_nth(f, n, K): |
|
""" |
|
Return the ``n``-th coefficient of ``f`` in ``K[x]``. |
|
|
|
Examples |
|
======== |
|
|
|
>>> from sympy.polys.domains import ZZ |
|
>>> from sympy.polys.densebasic import dup_nth |
|
|
|
>>> f = ZZ.map([1, 2, 3]) |
|
|
|
>>> dup_nth(f, 0, ZZ) |
|
3 |
|
>>> dup_nth(f, 4, ZZ) |
|
0 |
|
|
|
""" |
|
if n < 0: |
|
raise IndexError("'n' must be non-negative, got %i" % n) |
|
elif n >= len(f): |
|
return K.zero |
|
else: |
|
return f[dup_degree(f) - n] |
|
|
|
|
|
def dmp_nth(f, n, u, K): |
|
""" |
|
Return the ``n``-th coefficient of ``f`` in ``K[x]``. |
|
|
|
Examples |
|
======== |
|
|
|
>>> from sympy.polys.domains import ZZ |
|
>>> from sympy.polys.densebasic import dmp_nth |
|
|
|
>>> f = ZZ.map([[1], [2], [3]]) |
|
|
|
>>> dmp_nth(f, 0, 1, ZZ) |
|
[3] |
|
>>> dmp_nth(f, 4, 1, ZZ) |
|
[] |
|
|
|
""" |
|
if n < 0: |
|
raise IndexError("'n' must be non-negative, got %i" % n) |
|
elif n >= len(f): |
|
return dmp_zero(u - 1) |
|
else: |
|
return f[dmp_degree(f, u) - n] |
|
|
|
|
|
def dmp_ground_nth(f, N, u, K): |
|
""" |
|
Return the ground ``n``-th coefficient of ``f`` in ``K[x]``. |
|
|
|
Examples |
|
======== |
|
|
|
>>> from sympy.polys.domains import ZZ |
|
>>> from sympy.polys.densebasic import dmp_ground_nth |
|
|
|
>>> f = ZZ.map([[1], [2, 3]]) |
|
|
|
>>> dmp_ground_nth(f, (0, 1), 1, ZZ) |
|
2 |
|
|
|
""" |
|
v = u |
|
|
|
for n in N: |
|
if n < 0: |
|
raise IndexError("`n` must be non-negative, got %i" % n) |
|
elif n >= len(f): |
|
return K.zero |
|
else: |
|
d = dmp_degree(f, v) |
|
if d == ninf: |
|
d = -1 |
|
f, v = f[d - n], v - 1 |
|
|
|
return f |
|
|
|
|
|
def dmp_zero_p(f, u): |
|
""" |
|
Return ``True`` if ``f`` is zero in ``K[X]``. |
|
|
|
Examples |
|
======== |
|
|
|
>>> from sympy.polys.densebasic import dmp_zero_p |
|
|
|
>>> dmp_zero_p([[[[[]]]]], 4) |
|
True |
|
>>> dmp_zero_p([[[[[1]]]]], 4) |
|
False |
|
|
|
""" |
|
while u: |
|
if len(f) != 1: |
|
return False |
|
|
|
f = f[0] |
|
u -= 1 |
|
|
|
return not f |
|
|
|
|
|
def dmp_zero(u): |
|
""" |
|
Return a multivariate zero. |
|
|
|
Examples |
|
======== |
|
|
|
>>> from sympy.polys.densebasic import dmp_zero |
|
|
|
>>> dmp_zero(4) |
|
[[[[[]]]]] |
|
|
|
""" |
|
r = [] |
|
|
|
for i in range(u): |
|
r = [r] |
|
|
|
return r |
|
|
|
|
|
def dmp_one_p(f, u, K): |
|
""" |
|
Return ``True`` if ``f`` is one in ``K[X]``. |
|
|
|
Examples |
|
======== |
|
|
|
>>> from sympy.polys.domains import ZZ |
|
>>> from sympy.polys.densebasic import dmp_one_p |
|
|
|
>>> dmp_one_p([[[ZZ(1)]]], 2, ZZ) |
|
True |
|
|
|
""" |
|
return dmp_ground_p(f, K.one, u) |
|
|
|
|
|
def dmp_one(u, K): |
|
""" |
|
Return a multivariate one over ``K``. |
|
|
|
Examples |
|
======== |
|
|
|
>>> from sympy.polys.domains import ZZ |
|
>>> from sympy.polys.densebasic import dmp_one |
|
|
|
>>> dmp_one(2, ZZ) |
|
[[[1]]] |
|
|
|
""" |
|
return dmp_ground(K.one, u) |
|
|
|
|
|
def dmp_ground_p(f, c, u): |
|
""" |
|
Return True if ``f`` is constant in ``K[X]``. |
|
|
|
Examples |
|
======== |
|
|
|
>>> from sympy.polys.densebasic import dmp_ground_p |
|
|
|
>>> dmp_ground_p([[[3]]], 3, 2) |
|
True |
|
>>> dmp_ground_p([[[4]]], None, 2) |
|
True |
|
|
|
""" |
|
if c is not None and not c: |
|
return dmp_zero_p(f, u) |
|
|
|
while u: |
|
if len(f) != 1: |
|
return False |
|
f = f[0] |
|
u -= 1 |
|
|
|
if c is None: |
|
return len(f) <= 1 |
|
else: |
|
return f == [c] |
|
|
|
|
|
def dmp_ground(c, u): |
|
""" |
|
Return a multivariate constant. |
|
|
|
Examples |
|
======== |
|
|
|
>>> from sympy.polys.densebasic import dmp_ground |
|
|
|
>>> dmp_ground(3, 5) |
|
[[[[[[3]]]]]] |
|
>>> dmp_ground(1, -1) |
|
1 |
|
|
|
""" |
|
if not c: |
|
return dmp_zero(u) |
|
|
|
for i in range(u + 1): |
|
c = [c] |
|
|
|
return c |
|
|
|
|
|
def dmp_zeros(n, u, K): |
|
""" |
|
Return a list of multivariate zeros. |
|
|
|
Examples |
|
======== |
|
|
|
>>> from sympy.polys.domains import ZZ |
|
>>> from sympy.polys.densebasic import dmp_zeros |
|
|
|
>>> dmp_zeros(3, 2, ZZ) |
|
[[[[]]], [[[]]], [[[]]]] |
|
>>> dmp_zeros(3, -1, ZZ) |
|
[0, 0, 0] |
|
|
|
""" |
|
if not n: |
|
return [] |
|
|
|
if u < 0: |
|
return [K.zero]*n |
|
else: |
|
return [ dmp_zero(u) for i in range(n) ] |
|
|
|
|
|
def dmp_grounds(c, n, u): |
|
""" |
|
Return a list of multivariate constants. |
|
|
|
Examples |
|
======== |
|
|
|
>>> from sympy.polys.domains import ZZ |
|
>>> from sympy.polys.densebasic import dmp_grounds |
|
|
|
>>> dmp_grounds(ZZ(4), 3, 2) |
|
[[[[4]]], [[[4]]], [[[4]]]] |
|
>>> dmp_grounds(ZZ(4), 3, -1) |
|
[4, 4, 4] |
|
|
|
""" |
|
if not n: |
|
return [] |
|
|
|
if u < 0: |
|
return [c]*n |
|
else: |
|
return [ dmp_ground(c, u) for i in range(n) ] |
|
|
|
|
|
def dmp_negative_p(f, u, K): |
|
""" |
|
Return ``True`` if ``LC(f)`` is negative. |
|
|
|
Examples |
|
======== |
|
|
|
>>> from sympy.polys.domains import ZZ |
|
>>> from sympy.polys.densebasic import dmp_negative_p |
|
|
|
>>> dmp_negative_p([[ZZ(1)], [-ZZ(1)]], 1, ZZ) |
|
False |
|
>>> dmp_negative_p([[-ZZ(1)], [ZZ(1)]], 1, ZZ) |
|
True |
|
|
|
""" |
|
return K.is_negative(dmp_ground_LC(f, u, K)) |
|
|
|
|
|
def dmp_positive_p(f, u, K): |
|
""" |
|
Return ``True`` if ``LC(f)`` is positive. |
|
|
|
Examples |
|
======== |
|
|
|
>>> from sympy.polys.domains import ZZ |
|
>>> from sympy.polys.densebasic import dmp_positive_p |
|
|
|
>>> dmp_positive_p([[ZZ(1)], [-ZZ(1)]], 1, ZZ) |
|
True |
|
>>> dmp_positive_p([[-ZZ(1)], [ZZ(1)]], 1, ZZ) |
|
False |
|
|
|
""" |
|
return K.is_positive(dmp_ground_LC(f, u, K)) |
|
|
|
|
|
def dup_from_dict(f, K): |
|
""" |
|
Create a ``K[x]`` polynomial from a ``dict``. |
|
|
|
Examples |
|
======== |
|
|
|
>>> from sympy.polys.domains import ZZ |
|
>>> from sympy.polys.densebasic import dup_from_dict |
|
|
|
>>> dup_from_dict({(0,): ZZ(7), (2,): ZZ(5), (4,): ZZ(1)}, ZZ) |
|
[1, 0, 5, 0, 7] |
|
>>> dup_from_dict({}, ZZ) |
|
[] |
|
|
|
""" |
|
if not f: |
|
return [] |
|
|
|
n, h = max(f.keys()), [] |
|
|
|
if isinstance(n, int): |
|
for k in range(n, -1, -1): |
|
h.append(f.get(k, K.zero)) |
|
else: |
|
(n,) = n |
|
|
|
for k in range(n, -1, -1): |
|
h.append(f.get((k,), K.zero)) |
|
|
|
return dup_strip(h) |
|
|
|
|
|
def dup_from_raw_dict(f, K): |
|
""" |
|
Create a ``K[x]`` polynomial from a raw ``dict``. |
|
|
|
Examples |
|
======== |
|
|
|
>>> from sympy.polys.domains import ZZ |
|
>>> from sympy.polys.densebasic import dup_from_raw_dict |
|
|
|
>>> dup_from_raw_dict({0: ZZ(7), 2: ZZ(5), 4: ZZ(1)}, ZZ) |
|
[1, 0, 5, 0, 7] |
|
|
|
""" |
|
if not f: |
|
return [] |
|
|
|
n, h = max(f.keys()), [] |
|
|
|
for k in range(n, -1, -1): |
|
h.append(f.get(k, K.zero)) |
|
|
|
return dup_strip(h) |
|
|
|
|
|
def dmp_from_dict(f, u, K): |
|
""" |
|
Create a ``K[X]`` polynomial from a ``dict``. |
|
|
|
Examples |
|
======== |
|
|
|
>>> from sympy.polys.domains import ZZ |
|
>>> from sympy.polys.densebasic import dmp_from_dict |
|
|
|
>>> dmp_from_dict({(0, 0): ZZ(3), (0, 1): ZZ(2), (2, 1): ZZ(1)}, 1, ZZ) |
|
[[1, 0], [], [2, 3]] |
|
>>> dmp_from_dict({}, 0, ZZ) |
|
[] |
|
|
|
""" |
|
if not u: |
|
return dup_from_dict(f, K) |
|
if not f: |
|
return dmp_zero(u) |
|
|
|
coeffs = {} |
|
|
|
for monom, coeff in f.items(): |
|
head, tail = monom[0], monom[1:] |
|
|
|
if head in coeffs: |
|
coeffs[head][tail] = coeff |
|
else: |
|
coeffs[head] = { tail: coeff } |
|
|
|
n, v, h = max(coeffs.keys()), u - 1, [] |
|
|
|
for k in range(n, -1, -1): |
|
coeff = coeffs.get(k) |
|
|
|
if coeff is not None: |
|
h.append(dmp_from_dict(coeff, v, K)) |
|
else: |
|
h.append(dmp_zero(v)) |
|
|
|
return dmp_strip(h, u) |
|
|
|
|
|
def dup_to_dict(f, K=None, zero=False): |
|
""" |
|
Convert ``K[x]`` polynomial to a ``dict``. |
|
|
|
Examples |
|
======== |
|
|
|
>>> from sympy.polys.densebasic import dup_to_dict |
|
|
|
>>> dup_to_dict([1, 0, 5, 0, 7]) |
|
{(0,): 7, (2,): 5, (4,): 1} |
|
>>> dup_to_dict([]) |
|
{} |
|
|
|
""" |
|
if not f and zero: |
|
return {(0,): K.zero} |
|
|
|
n, result = len(f) - 1, {} |
|
|
|
for k in range(0, n + 1): |
|
if f[n - k]: |
|
result[(k,)] = f[n - k] |
|
|
|
return result |
|
|
|
|
|
def dup_to_raw_dict(f, K=None, zero=False): |
|
""" |
|
Convert a ``K[x]`` polynomial to a raw ``dict``. |
|
|
|
Examples |
|
======== |
|
|
|
>>> from sympy.polys.densebasic import dup_to_raw_dict |
|
|
|
>>> dup_to_raw_dict([1, 0, 5, 0, 7]) |
|
{0: 7, 2: 5, 4: 1} |
|
|
|
""" |
|
if not f and zero: |
|
return {0: K.zero} |
|
|
|
n, result = len(f) - 1, {} |
|
|
|
for k in range(0, n + 1): |
|
if f[n - k]: |
|
result[k] = f[n - k] |
|
|
|
return result |
|
|
|
|
|
def dmp_to_dict(f, u, K=None, zero=False): |
|
""" |
|
Convert a ``K[X]`` polynomial to a ``dict````. |
|
|
|
Examples |
|
======== |
|
|
|
>>> from sympy.polys.densebasic import dmp_to_dict |
|
|
|
>>> dmp_to_dict([[1, 0], [], [2, 3]], 1) |
|
{(0, 0): 3, (0, 1): 2, (2, 1): 1} |
|
>>> dmp_to_dict([], 0) |
|
{} |
|
|
|
""" |
|
if not u: |
|
return dup_to_dict(f, K, zero=zero) |
|
|
|
if dmp_zero_p(f, u) and zero: |
|
return {(0,)*(u + 1): K.zero} |
|
|
|
n, v, result = dmp_degree(f, u), u - 1, {} |
|
|
|
if n == ninf: |
|
n = -1 |
|
|
|
for k in range(0, n + 1): |
|
h = dmp_to_dict(f[n - k], v) |
|
|
|
for exp, coeff in h.items(): |
|
result[(k,) + exp] = coeff |
|
|
|
return result |
|
|
|
|
|
def dmp_swap(f, i, j, u, K): |
|
""" |
|
Transform ``K[..x_i..x_j..]`` to ``K[..x_j..x_i..]``. |
|
|
|
Examples |
|
======== |
|
|
|
>>> from sympy.polys.domains import ZZ |
|
>>> from sympy.polys.densebasic import dmp_swap |
|
|
|
>>> f = ZZ.map([[[2], [1, 0]], []]) |
|
|
|
>>> dmp_swap(f, 0, 1, 2, ZZ) |
|
[[[2], []], [[1, 0], []]] |
|
>>> dmp_swap(f, 1, 2, 2, ZZ) |
|
[[[1], [2, 0]], [[]]] |
|
>>> dmp_swap(f, 0, 2, 2, ZZ) |
|
[[[1, 0]], [[2, 0], []]] |
|
|
|
""" |
|
if i < 0 or j < 0 or i > u or j > u: |
|
raise IndexError("0 <= i < j <= %s expected" % u) |
|
elif i == j: |
|
return f |
|
|
|
F, H = dmp_to_dict(f, u), {} |
|
|
|
for exp, coeff in F.items(): |
|
H[exp[:i] + (exp[j],) + |
|
exp[i + 1:j] + |
|
(exp[i],) + exp[j + 1:]] = coeff |
|
|
|
return dmp_from_dict(H, u, K) |
|
|
|
|
|
def dmp_permute(f, P, u, K): |
|
""" |
|
Return a polynomial in ``K[x_{P(1)},..,x_{P(n)}]``. |
|
|
|
Examples |
|
======== |
|
|
|
>>> from sympy.polys.domains import ZZ |
|
>>> from sympy.polys.densebasic import dmp_permute |
|
|
|
>>> f = ZZ.map([[[2], [1, 0]], []]) |
|
|
|
>>> dmp_permute(f, [1, 0, 2], 2, ZZ) |
|
[[[2], []], [[1, 0], []]] |
|
>>> dmp_permute(f, [1, 2, 0], 2, ZZ) |
|
[[[1], []], [[2, 0], []]] |
|
|
|
""" |
|
F, H = dmp_to_dict(f, u), {} |
|
|
|
for exp, coeff in F.items(): |
|
new_exp = [0]*len(exp) |
|
|
|
for e, p in zip(exp, P): |
|
new_exp[p] = e |
|
|
|
H[tuple(new_exp)] = coeff |
|
|
|
return dmp_from_dict(H, u, K) |
|
|
|
|
|
def dmp_nest(f, l, K): |
|
""" |
|
Return a multivariate value nested ``l``-levels. |
|
|
|
Examples |
|
======== |
|
|
|
>>> from sympy.polys.domains import ZZ |
|
>>> from sympy.polys.densebasic import dmp_nest |
|
|
|
>>> dmp_nest([[ZZ(1)]], 2, ZZ) |
|
[[[[1]]]] |
|
|
|
""" |
|
if not isinstance(f, list): |
|
return dmp_ground(f, l) |
|
|
|
for i in range(l): |
|
f = [f] |
|
|
|
return f |
|
|
|
|
|
def dmp_raise(f, l, u, K): |
|
""" |
|
Return a multivariate polynomial raised ``l``-levels. |
|
|
|
Examples |
|
======== |
|
|
|
>>> from sympy.polys.domains import ZZ |
|
>>> from sympy.polys.densebasic import dmp_raise |
|
|
|
>>> f = ZZ.map([[], [1, 2]]) |
|
|
|
>>> dmp_raise(f, 2, 1, ZZ) |
|
[[[[]]], [[[1]], [[2]]]] |
|
|
|
""" |
|
if not l: |
|
return f |
|
|
|
if not u: |
|
if not f: |
|
return dmp_zero(l) |
|
|
|
k = l - 1 |
|
|
|
return [ dmp_ground(c, k) for c in f ] |
|
|
|
v = u - 1 |
|
|
|
return [ dmp_raise(c, l, v, K) for c in f ] |
|
|
|
|
|
def dup_deflate(f, K): |
|
""" |
|
Map ``x**m`` to ``y`` in a polynomial in ``K[x]``. |
|
|
|
Examples |
|
======== |
|
|
|
>>> from sympy.polys.domains import ZZ |
|
>>> from sympy.polys.densebasic import dup_deflate |
|
|
|
>>> f = ZZ.map([1, 0, 0, 1, 0, 0, 1]) |
|
|
|
>>> dup_deflate(f, ZZ) |
|
(3, [1, 1, 1]) |
|
|
|
""" |
|
if dup_degree(f) <= 0: |
|
return 1, f |
|
|
|
g = 0 |
|
|
|
for i in range(len(f)): |
|
if not f[-i - 1]: |
|
continue |
|
|
|
g = igcd(g, i) |
|
|
|
if g == 1: |
|
return 1, f |
|
|
|
return g, f[::g] |
|
|
|
|
|
def dmp_deflate(f, u, K): |
|
""" |
|
Map ``x_i**m_i`` to ``y_i`` in a polynomial in ``K[X]``. |
|
|
|
Examples |
|
======== |
|
|
|
>>> from sympy.polys.domains import ZZ |
|
>>> from sympy.polys.densebasic import dmp_deflate |
|
|
|
>>> f = ZZ.map([[1, 0, 0, 2], [], [3, 0, 0, 4]]) |
|
|
|
>>> dmp_deflate(f, 1, ZZ) |
|
((2, 3), [[1, 2], [3, 4]]) |
|
|
|
""" |
|
if dmp_zero_p(f, u): |
|
return (1,)*(u + 1), f |
|
|
|
F = dmp_to_dict(f, u) |
|
B = [0]*(u + 1) |
|
|
|
for M in F.keys(): |
|
for i, m in enumerate(M): |
|
B[i] = igcd(B[i], m) |
|
|
|
for i, b in enumerate(B): |
|
if not b: |
|
B[i] = 1 |
|
|
|
B = tuple(B) |
|
|
|
if all(b == 1 for b in B): |
|
return B, f |
|
|
|
H = {} |
|
|
|
for A, coeff in F.items(): |
|
N = [ a // b for a, b in zip(A, B) ] |
|
H[tuple(N)] = coeff |
|
|
|
return B, dmp_from_dict(H, u, K) |
|
|
|
|
|
def dup_multi_deflate(polys, K): |
|
""" |
|
Map ``x**m`` to ``y`` in a set of polynomials in ``K[x]``. |
|
|
|
Examples |
|
======== |
|
|
|
>>> from sympy.polys.domains import ZZ |
|
>>> from sympy.polys.densebasic import dup_multi_deflate |
|
|
|
>>> f = ZZ.map([1, 0, 2, 0, 3]) |
|
>>> g = ZZ.map([4, 0, 0]) |
|
|
|
>>> dup_multi_deflate((f, g), ZZ) |
|
(2, ([1, 2, 3], [4, 0])) |
|
|
|
""" |
|
G = 0 |
|
|
|
for p in polys: |
|
if dup_degree(p) <= 0: |
|
return 1, polys |
|
|
|
g = 0 |
|
|
|
for i in range(len(p)): |
|
if not p[-i - 1]: |
|
continue |
|
|
|
g = igcd(g, i) |
|
|
|
if g == 1: |
|
return 1, polys |
|
|
|
G = igcd(G, g) |
|
|
|
return G, tuple([ p[::G] for p in polys ]) |
|
|
|
|
|
def dmp_multi_deflate(polys, u, K): |
|
""" |
|
Map ``x_i**m_i`` to ``y_i`` in a set of polynomials in ``K[X]``. |
|
|
|
Examples |
|
======== |
|
|
|
>>> from sympy.polys.domains import ZZ |
|
>>> from sympy.polys.densebasic import dmp_multi_deflate |
|
|
|
>>> f = ZZ.map([[1, 0, 0, 2], [], [3, 0, 0, 4]]) |
|
>>> g = ZZ.map([[1, 0, 2], [], [3, 0, 4]]) |
|
|
|
>>> dmp_multi_deflate((f, g), 1, ZZ) |
|
((2, 1), ([[1, 0, 0, 2], [3, 0, 0, 4]], [[1, 0, 2], [3, 0, 4]])) |
|
|
|
""" |
|
if not u: |
|
M, H = dup_multi_deflate(polys, K) |
|
return (M,), H |
|
|
|
F, B = [], [0]*(u + 1) |
|
|
|
for p in polys: |
|
f = dmp_to_dict(p, u) |
|
|
|
if not dmp_zero_p(p, u): |
|
for M in f.keys(): |
|
for i, m in enumerate(M): |
|
B[i] = igcd(B[i], m) |
|
|
|
F.append(f) |
|
|
|
for i, b in enumerate(B): |
|
if not b: |
|
B[i] = 1 |
|
|
|
B = tuple(B) |
|
|
|
if all(b == 1 for b in B): |
|
return B, polys |
|
|
|
H = [] |
|
|
|
for f in F: |
|
h = {} |
|
|
|
for A, coeff in f.items(): |
|
N = [ a // b for a, b in zip(A, B) ] |
|
h[tuple(N)] = coeff |
|
|
|
H.append(dmp_from_dict(h, u, K)) |
|
|
|
return B, tuple(H) |
|
|
|
|
|
def dup_inflate(f, m, K): |
|
""" |
|
Map ``y`` to ``x**m`` in a polynomial in ``K[x]``. |
|
|
|
Examples |
|
======== |
|
|
|
>>> from sympy.polys.domains import ZZ |
|
>>> from sympy.polys.densebasic import dup_inflate |
|
|
|
>>> f = ZZ.map([1, 1, 1]) |
|
|
|
>>> dup_inflate(f, 3, ZZ) |
|
[1, 0, 0, 1, 0, 0, 1] |
|
|
|
""" |
|
if m <= 0: |
|
raise IndexError("'m' must be positive, got %s" % m) |
|
if m == 1 or not f: |
|
return f |
|
|
|
result = [f[0]] |
|
|
|
for coeff in f[1:]: |
|
result.extend([K.zero]*(m - 1)) |
|
result.append(coeff) |
|
|
|
return result |
|
|
|
|
|
def _rec_inflate(g, M, v, i, K): |
|
"""Recursive helper for :func:`dmp_inflate`.""" |
|
if not v: |
|
return dup_inflate(g, M[i], K) |
|
if M[i] <= 0: |
|
raise IndexError("all M[i] must be positive, got %s" % M[i]) |
|
|
|
w, j = v - 1, i + 1 |
|
|
|
g = [ _rec_inflate(c, M, w, j, K) for c in g ] |
|
|
|
result = [g[0]] |
|
|
|
for coeff in g[1:]: |
|
for _ in range(1, M[i]): |
|
result.append(dmp_zero(w)) |
|
|
|
result.append(coeff) |
|
|
|
return result |
|
|
|
|
|
def dmp_inflate(f, M, u, K): |
|
""" |
|
Map ``y_i`` to ``x_i**k_i`` in a polynomial in ``K[X]``. |
|
|
|
Examples |
|
======== |
|
|
|
>>> from sympy.polys.domains import ZZ |
|
>>> from sympy.polys.densebasic import dmp_inflate |
|
|
|
>>> f = ZZ.map([[1, 2], [3, 4]]) |
|
|
|
>>> dmp_inflate(f, (2, 3), 1, ZZ) |
|
[[1, 0, 0, 2], [], [3, 0, 0, 4]] |
|
|
|
""" |
|
if not u: |
|
return dup_inflate(f, M[0], K) |
|
|
|
if all(m == 1 for m in M): |
|
return f |
|
else: |
|
return _rec_inflate(f, M, u, 0, K) |
|
|
|
|
|
def dmp_exclude(f, u, K): |
|
""" |
|
Exclude useless levels from ``f``. |
|
|
|
Return the levels excluded, the new excluded ``f``, and the new ``u``. |
|
|
|
Examples |
|
======== |
|
|
|
>>> from sympy.polys.domains import ZZ |
|
>>> from sympy.polys.densebasic import dmp_exclude |
|
|
|
>>> f = ZZ.map([[[1]], [[1], [2]]]) |
|
|
|
>>> dmp_exclude(f, 2, ZZ) |
|
([2], [[1], [1, 2]], 1) |
|
|
|
""" |
|
if not u or dmp_ground_p(f, None, u): |
|
return [], f, u |
|
|
|
J, F = [], dmp_to_dict(f, u) |
|
|
|
for j in range(0, u + 1): |
|
for monom in F.keys(): |
|
if monom[j]: |
|
break |
|
else: |
|
J.append(j) |
|
|
|
if not J: |
|
return [], f, u |
|
|
|
f = {} |
|
|
|
for monom, coeff in F.items(): |
|
monom = list(monom) |
|
|
|
for j in reversed(J): |
|
del monom[j] |
|
|
|
f[tuple(monom)] = coeff |
|
|
|
u -= len(J) |
|
|
|
return J, dmp_from_dict(f, u, K), u |
|
|
|
|
|
def dmp_include(f, J, u, K): |
|
""" |
|
Include useless levels in ``f``. |
|
|
|
Examples |
|
======== |
|
|
|
>>> from sympy.polys.domains import ZZ |
|
>>> from sympy.polys.densebasic import dmp_include |
|
|
|
>>> f = ZZ.map([[1], [1, 2]]) |
|
|
|
>>> dmp_include(f, [2], 1, ZZ) |
|
[[[1]], [[1], [2]]] |
|
|
|
""" |
|
if not J: |
|
return f |
|
|
|
F, f = dmp_to_dict(f, u), {} |
|
|
|
for monom, coeff in F.items(): |
|
monom = list(monom) |
|
|
|
for j in J: |
|
monom.insert(j, 0) |
|
|
|
f[tuple(monom)] = coeff |
|
|
|
u += len(J) |
|
|
|
return dmp_from_dict(f, u, K) |
|
|
|
|
|
def dmp_inject(f, u, K, front=False): |
|
""" |
|
Convert ``f`` from ``K[X][Y]`` to ``K[X,Y]``. |
|
|
|
Examples |
|
======== |
|
|
|
>>> from sympy.polys.rings import ring |
|
>>> from sympy.polys.domains import ZZ |
|
>>> from sympy.polys.densebasic import dmp_inject |
|
|
|
>>> R, x,y = ring("x,y", ZZ) |
|
|
|
>>> dmp_inject([R(1), x + 2], 0, R.to_domain()) |
|
([[[1]], [[1], [2]]], 2) |
|
>>> dmp_inject([R(1), x + 2], 0, R.to_domain(), front=True) |
|
([[[1]], [[1, 2]]], 2) |
|
|
|
""" |
|
f, h = dmp_to_dict(f, u), {} |
|
|
|
v = K.ngens - 1 |
|
|
|
for f_monom, g in f.items(): |
|
g = g.to_dict() |
|
|
|
for g_monom, c in g.items(): |
|
if front: |
|
h[g_monom + f_monom] = c |
|
else: |
|
h[f_monom + g_monom] = c |
|
|
|
w = u + v + 1 |
|
|
|
return dmp_from_dict(h, w, K.dom), w |
|
|
|
|
|
def dmp_eject(f, u, K, front=False): |
|
""" |
|
Convert ``f`` from ``K[X,Y]`` to ``K[X][Y]``. |
|
|
|
Examples |
|
======== |
|
|
|
>>> from sympy.polys.domains import ZZ |
|
>>> from sympy.polys.densebasic import dmp_eject |
|
|
|
>>> dmp_eject([[[1]], [[1], [2]]], 2, ZZ['x', 'y']) |
|
[1, x + 2] |
|
|
|
""" |
|
f, h = dmp_to_dict(f, u), {} |
|
|
|
n = K.ngens |
|
v = u - K.ngens + 1 |
|
|
|
for monom, c in f.items(): |
|
if front: |
|
g_monom, f_monom = monom[:n], monom[n:] |
|
else: |
|
g_monom, f_monom = monom[-n:], monom[:-n] |
|
|
|
if f_monom in h: |
|
h[f_monom][g_monom] = c |
|
else: |
|
h[f_monom] = {g_monom: c} |
|
|
|
for monom, c in h.items(): |
|
h[monom] = K(c) |
|
|
|
return dmp_from_dict(h, v - 1, K) |
|
|
|
|
|
def dup_terms_gcd(f, K): |
|
""" |
|
Remove GCD of terms from ``f`` in ``K[x]``. |
|
|
|
Examples |
|
======== |
|
|
|
>>> from sympy.polys.domains import ZZ |
|
>>> from sympy.polys.densebasic import dup_terms_gcd |
|
|
|
>>> f = ZZ.map([1, 0, 1, 0, 0]) |
|
|
|
>>> dup_terms_gcd(f, ZZ) |
|
(2, [1, 0, 1]) |
|
|
|
""" |
|
if dup_TC(f, K) or not f: |
|
return 0, f |
|
|
|
i = 0 |
|
|
|
for c in reversed(f): |
|
if not c: |
|
i += 1 |
|
else: |
|
break |
|
|
|
return i, f[:-i] |
|
|
|
|
|
def dmp_terms_gcd(f, u, K): |
|
""" |
|
Remove GCD of terms from ``f`` in ``K[X]``. |
|
|
|
Examples |
|
======== |
|
|
|
>>> from sympy.polys.domains import ZZ |
|
>>> from sympy.polys.densebasic import dmp_terms_gcd |
|
|
|
>>> f = ZZ.map([[1, 0], [1, 0, 0], [], []]) |
|
|
|
>>> dmp_terms_gcd(f, 1, ZZ) |
|
((2, 1), [[1], [1, 0]]) |
|
|
|
""" |
|
if dmp_ground_TC(f, u, K) or dmp_zero_p(f, u): |
|
return (0,)*(u + 1), f |
|
|
|
F = dmp_to_dict(f, u) |
|
G = monomial_min(*list(F.keys())) |
|
|
|
if all(g == 0 for g in G): |
|
return G, f |
|
|
|
f = {} |
|
|
|
for monom, coeff in F.items(): |
|
f[monomial_div(monom, G)] = coeff |
|
|
|
return G, dmp_from_dict(f, u, K) |
|
|
|
|
|
def _rec_list_terms(g, v, monom): |
|
"""Recursive helper for :func:`dmp_list_terms`.""" |
|
d, terms = dmp_degree(g, v), [] |
|
|
|
if not v: |
|
for i, c in enumerate(g): |
|
if not c: |
|
continue |
|
|
|
terms.append((monom + (d - i,), c)) |
|
else: |
|
w = v - 1 |
|
|
|
for i, c in enumerate(g): |
|
terms.extend(_rec_list_terms(c, w, monom + (d - i,))) |
|
|
|
return terms |
|
|
|
|
|
def dmp_list_terms(f, u, K, order=None): |
|
""" |
|
List all non-zero terms from ``f`` in the given order ``order``. |
|
|
|
Examples |
|
======== |
|
|
|
>>> from sympy.polys.domains import ZZ |
|
>>> from sympy.polys.densebasic import dmp_list_terms |
|
|
|
>>> f = ZZ.map([[1, 1], [2, 3]]) |
|
|
|
>>> dmp_list_terms(f, 1, ZZ) |
|
[((1, 1), 1), ((1, 0), 1), ((0, 1), 2), ((0, 0), 3)] |
|
>>> dmp_list_terms(f, 1, ZZ, order='grevlex') |
|
[((1, 1), 1), ((1, 0), 1), ((0, 1), 2), ((0, 0), 3)] |
|
|
|
""" |
|
def sort(terms, O): |
|
return sorted(terms, key=lambda term: O(term[0]), reverse=True) |
|
|
|
terms = _rec_list_terms(f, u, ()) |
|
|
|
if not terms: |
|
return [((0,)*(u + 1), K.zero)] |
|
|
|
if order is None: |
|
return terms |
|
else: |
|
return sort(terms, monomial_key(order)) |
|
|
|
|
|
def dup_apply_pairs(f, g, h, args, K): |
|
""" |
|
Apply ``h`` to pairs of coefficients of ``f`` and ``g``. |
|
|
|
Examples |
|
======== |
|
|
|
>>> from sympy.polys.domains import ZZ |
|
>>> from sympy.polys.densebasic import dup_apply_pairs |
|
|
|
>>> h = lambda x, y, z: 2*x + y - z |
|
|
|
>>> dup_apply_pairs([1, 2, 3], [3, 2, 1], h, (1,), ZZ) |
|
[4, 5, 6] |
|
|
|
""" |
|
n, m = len(f), len(g) |
|
|
|
if n != m: |
|
if n > m: |
|
g = [K.zero]*(n - m) + g |
|
else: |
|
f = [K.zero]*(m - n) + f |
|
|
|
result = [] |
|
|
|
for a, b in zip(f, g): |
|
result.append(h(a, b, *args)) |
|
|
|
return dup_strip(result) |
|
|
|
|
|
def dmp_apply_pairs(f, g, h, args, u, K): |
|
""" |
|
Apply ``h`` to pairs of coefficients of ``f`` and ``g``. |
|
|
|
Examples |
|
======== |
|
|
|
>>> from sympy.polys.domains import ZZ |
|
>>> from sympy.polys.densebasic import dmp_apply_pairs |
|
|
|
>>> h = lambda x, y, z: 2*x + y - z |
|
|
|
>>> dmp_apply_pairs([[1], [2, 3]], [[3], [2, 1]], h, (1,), 1, ZZ) |
|
[[4], [5, 6]] |
|
|
|
""" |
|
if not u: |
|
return dup_apply_pairs(f, g, h, args, K) |
|
|
|
n, m, v = len(f), len(g), u - 1 |
|
|
|
if n != m: |
|
if n > m: |
|
g = dmp_zeros(n - m, v, K) + g |
|
else: |
|
f = dmp_zeros(m - n, v, K) + f |
|
|
|
result = [] |
|
|
|
for a, b in zip(f, g): |
|
result.append(dmp_apply_pairs(a, b, h, args, v, K)) |
|
|
|
return dmp_strip(result, u) |
|
|
|
|
|
def dup_slice(f, m, n, K): |
|
"""Take a continuous subsequence of terms of ``f`` in ``K[x]``. """ |
|
k = len(f) |
|
|
|
if k >= m: |
|
M = k - m |
|
else: |
|
M = 0 |
|
if k >= n: |
|
N = k - n |
|
else: |
|
N = 0 |
|
|
|
f = f[N:M] |
|
|
|
while f and f[0] == K.zero: |
|
f.pop(0) |
|
|
|
if not f: |
|
return [] |
|
else: |
|
return f + [K.zero]*m |
|
|
|
|
|
def dmp_slice(f, m, n, u, K): |
|
"""Take a continuous subsequence of terms of ``f`` in ``K[X]``. """ |
|
return dmp_slice_in(f, m, n, 0, u, K) |
|
|
|
|
|
def dmp_slice_in(f, m, n, j, u, K): |
|
"""Take a continuous subsequence of terms of ``f`` in ``x_j`` in ``K[X]``. """ |
|
if j < 0 or j > u: |
|
raise IndexError("-%s <= j < %s expected, got %s" % (u, u, j)) |
|
|
|
if not u: |
|
return dup_slice(f, m, n, K) |
|
|
|
f, g = dmp_to_dict(f, u), {} |
|
|
|
for monom, coeff in f.items(): |
|
k = monom[j] |
|
|
|
if k < m or k >= n: |
|
monom = monom[:j] + (0,) + monom[j + 1:] |
|
|
|
if monom in g: |
|
g[monom] += coeff |
|
else: |
|
g[monom] = coeff |
|
|
|
return dmp_from_dict(g, u, K) |
|
|
|
|
|
def dup_random(n, a, b, K): |
|
""" |
|
Return a polynomial of degree ``n`` with coefficients in ``[a, b]``. |
|
|
|
Examples |
|
======== |
|
|
|
>>> from sympy.polys.domains import ZZ |
|
>>> from sympy.polys.densebasic import dup_random |
|
|
|
>>> dup_random(3, -10, 10, ZZ) #doctest: +SKIP |
|
[-2, -8, 9, -4] |
|
|
|
""" |
|
f = [ K.convert(random.randint(a, b)) for _ in range(0, n + 1) ] |
|
|
|
while not f[0]: |
|
f[0] = K.convert(random.randint(a, b)) |
|
|
|
return f |
|
|