Skip to content

Commit

Permalink
Merge pull request sympy#2436 from asmeurer/degree0
Browse files Browse the repository at this point in the history
Make degree(0) == -oo in the polys
  • Loading branch information
jrioux committed Nov 10, 2013
2 parents c858781 + 4b230ac commit fc712c7
Show file tree
Hide file tree
Showing 11 changed files with 108 additions and 54 deletions.
11 changes: 7 additions & 4 deletions sympy/integrals/risch.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
from sympy import real_roots
from sympy.abc import z
from sympy.core.function import Lambda
from sympy.core.numbers import ilcm
from sympy.core.numbers import ilcm, oo
from sympy.core.mul import Mul
from sympy.core.power import Pow
from sympy.core.relational import Eq, Ne
Expand Down Expand Up @@ -754,7 +754,7 @@ def as_poly_1t(p, t, z):
# (...)*exp(-x).
pa, pd = frac_in(p, t, cancel=True)
if not pd.is_monomial:
# XXX: Is there a better Poly exception that we could raise here
# XXX: Is there a better Poly exception that we could raise here?
# Either way, if you see this (from the Risch Algorithm) it indicates
# a bug.
raise PolynomialError("%s is not an element of K[%s, 1/%s]." % (p, t, t))
Expand All @@ -767,10 +767,10 @@ def as_poly_1t(p, t, z):
except DomainError as e:
# Issue 1851
raise NotImplementedError(e)
# Compute the negative degree parts. Also requires polys11.
# Compute the negative degree parts.
one_t_part = Poly.from_list(reversed(one_t_part.rep.rep), *one_t_part.gens,
domain=one_t_part.domain)
if r > 0:
if 0 < r < oo:
one_t_part *= Poly(t**r, t)

one_t_part = one_t_part.replace(t, z) # z will be 1/t
Expand Down Expand Up @@ -1353,6 +1353,9 @@ def integrate_hyperexponential_polynomial(p, DE, z):
qd = Poly(1, DE.t)
b = True

if p.is_zero:
return(qa, qd, b)

with DecrementLevel(DE):
for i in xrange(-p.degree(z), p.degree(t1) + 1):
if not i:
Expand Down
5 changes: 5 additions & 0 deletions sympy/integrals/tests/test_risch.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ def test_as_poly_1t():
Poly(2/(exp(2) + 1)*z, t, z), Poly(2/(exp(2) + 1)*z, z, t)]
assert as_poly_1t(2/((exp(2) + 1)*t) + t, t, z) in [
Poly(t + 2/(exp(2) + 1)*z, t, z), Poly(t + 2/(exp(2) + 1)*z, z, t)]
assert as_poly_1t(S(0), t, z) == Poly(0, t, z)


def test_derivation():
Expand Down Expand Up @@ -320,6 +321,10 @@ def test_integrate_hyperexponential_polynomial():
Poly((x - t0)*t1**2 + (-2*t0 + 2*x)*t1, t1), Poly(-2*x*t0 + x**2 +
t0**2, t1), True)

DE = DifferentialExtension(extension={'D':[Poly(1, x), Poly(t0, t0)]})
assert integrate_hyperexponential_polynomial(Poly(0, t0), DE, z) == (
Poly(0, t0), Poly(1, t0), True)


def test_integrate_hyperexponential_returns_piecewise():
a, b = symbols('a b')
Expand Down
2 changes: 1 addition & 1 deletion sympy/polys/densearith.py
Original file line number Diff line number Diff line change
Expand Up @@ -850,7 +850,7 @@ def dup_sqr(f, K):
x**4 + 2*x**2 + 1
"""
df, h = dup_degree(f), []
df, h = len(f) - 1, []

for i in xrange(0, 2*df + 1):
c = K.zero
Expand Down
25 changes: 19 additions & 6 deletions sympy/polys/densebasic.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from __future__ import print_function, division

from sympy.core import igcd
from sympy import oo

from sympy.polys.monomials import monomial_min, monomial_div
from sympy.polys.orderings import monomial_key
Expand Down Expand Up @@ -137,6 +138,8 @@ def dup_degree(f):
"""
Return the leading degree of ``f`` in ``K[x]``.
Note that the degree of 0 is negative infinity (the SymPy object -oo).
Examples
========
Expand All @@ -149,21 +152,25 @@ def dup_degree(f):
3
"""
if not f:
return -oo
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 (the SymPy object -oo).
Examples
========
>>> from sympy.polys.domains import ZZ
>>> from sympy.polys.densebasic import dmp_degree
>>> dmp_degree([[[]]], 2)
-1
-oo
>>> f = ZZ.map([[2], [1, 2, 3]])
Expand All @@ -172,7 +179,7 @@ def dmp_degree(f, u):
"""
if dmp_zero_p(f, u):
return -1
return -oo
else:
return len(f) - 1

Expand Down Expand Up @@ -240,7 +247,7 @@ def dmp_degree_list(f, u):
(1, 2)
"""
degs = [-1]*(u + 1)
degs = [-oo]*(u + 1)
_rec_degree_list(f, u, 0, degs)
return tuple(degs)

Expand Down Expand Up @@ -680,7 +687,10 @@ def dmp_ground_nth(f, N, u, K):
elif n >= len(f):
return K.zero
else:
f, v = f[dmp_degree(f, v) - n], v - 1
d = dmp_degree(f, v)
if d == -oo:
d = -1
f, v = f[d - n], v - 1

return f

Expand Down Expand Up @@ -1027,7 +1037,7 @@ def dup_to_dict(f, K=None, zero=False):
if not f and zero:
return {(0,): K.zero}

n, result = dup_degree(f), {}
n, result = len(f) - 1, {}

for k in xrange(0, n + 1):
if f[n - k]:
Expand All @@ -1052,7 +1062,7 @@ def dup_to_raw_dict(f, K=None, zero=False):
if not f and zero:
return {0: K.zero}

n, result = dup_degree(f), {}
n, result = len(f) - 1, {}

for k in xrange(0, n + 1):
if f[n - k]:
Expand Down Expand Up @@ -1084,6 +1094,9 @@ def dmp_to_dict(f, u, K=None, zero=False):

n, v, result = dmp_degree(f, u), u - 1, {}

if n == -oo:
n = -1

for k in xrange(0, n + 1):
h = dmp_to_dict(f[n - k], v)

Expand Down
12 changes: 6 additions & 6 deletions sympy/polys/densetools.py
Original file line number Diff line number Diff line change
Expand Up @@ -842,7 +842,7 @@ def dup_mirror(f, K):
-x**3 + 2*x**2 + 4*x + 2
"""
f, n, a = list(f), dup_degree(f), -K.one
f, n, a = list(f), len(f) - 1, -K.one

for i in xrange(n - 1, -1, -1):
f[i], a = a*f[i], -a
Expand All @@ -864,7 +864,7 @@ def dup_scale(f, a, K):
4*x**2 - 4*x + 1
"""
f, n, b = list(f), dup_degree(f), a
f, n, b = list(f), len(f) - 1, a

for i in xrange(n - 1, -1, -1):
f[i], b = b*f[i], b*a
Expand All @@ -886,7 +886,7 @@ def dup_shift(f, a, K):
x**2 + 2*x + 1
"""
f, n = list(f), dup_degree(f)
f, n = list(f), len(f) - 1

for i in xrange(n, 0, -1):
for j in xrange(0, i):
Expand All @@ -912,7 +912,7 @@ def dup_transform(f, p, q, K):
if not f:
return []

n = dup_degree(f)
n = len(f) - 1
h, Q = [f[0]], [[K.one]]

for i in xrange(0, n):
Expand Down Expand Up @@ -986,7 +986,7 @@ def dmp_compose(f, g, u, K):

def _dup_right_decompose(f, s, K):
"""Helper function for :func:`_dup_decompose`."""
n = dup_degree(f)
n = len(f) - 1
lc = dup_LC(f, K)

f = dup_to_raw_dict(f)
Expand Down Expand Up @@ -1030,7 +1030,7 @@ def _dup_left_decompose(f, h, K):

def _dup_decompose(f, K):
"""Helper function for :func:`dup_decompose`."""
df = dup_degree(f)
df = len(f) - 1

for s in xrange(2, df):
if df % s != 0:
Expand Down
4 changes: 3 additions & 1 deletion sympy/polys/polyclasses.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
from sympy.polys.polyutils import PicklableWithSlots
from sympy.polys.polyerrors import CoercionFailed, NotReversible

from sympy import oo

class GenericPoly(PicklableWithSlots):
"""Base class for low-level polynomial representations. """

Expand Down Expand Up @@ -528,7 +530,7 @@ def homogenize(f, s):
def homogeneous_order(f):
"""Returns the homogeneous order of ``f``. """
if f.is_zero:
return -1
return -oo

monoms = f.monoms()
tdeg = sum(monoms[0])
Expand Down
10 changes: 9 additions & 1 deletion sympy/polys/polytools.py
Original file line number Diff line number Diff line change
Expand Up @@ -1689,6 +1689,8 @@ def degree(f, gen=0):
"""
Returns degree of ``f`` in ``x_j``.
The degree of 0 is negative infinity.
Examples
========
Expand All @@ -1699,6 +1701,8 @@ def degree(f, gen=0):
2
>>> Poly(x**2 + y*x + y, x, y).degree(y)
1
>>> Poly(0, x).degree()
-oo
"""
j = f._gen_to_level(gen)
Expand Down Expand Up @@ -4063,6 +4067,8 @@ def degree(f, *gens, **args):
"""
Return the degree of ``f`` in the given variable.
The degree of 0 is negative infinity.
Examples
========
Expand All @@ -4073,6 +4079,8 @@ def degree(f, *gens, **args):
2
>>> degree(x**2 + y*x + 1, gen=y)
1
>>> degree(0, x)
-oo
"""
options.allowed_flags(args, ['gen', 'polys'])
Expand All @@ -4082,7 +4090,7 @@ def degree(f, *gens, **args):
except PolificationFailed as exc:
raise ComputationFailed('degree', 1, exc)

return Integer(F.degree(opt.gen))
return sympify(F.degree(opt.gen))


@public
Expand Down
38 changes: 29 additions & 9 deletions sympy/polys/rings.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

from sympy.core.expr import Expr
from sympy.core.symbol import Symbol, symbols as _symbols
from sympy.core.numbers import igcd
from sympy.core.numbers import igcd, oo
from sympy.core.sympify import CantSympify, sympify
from sympy.core.compatibility import is_sequence, reduce, string_types, xrange
from sympy.ntheory.multinomial import multinomial_coefficients
Expand Down Expand Up @@ -1527,34 +1527,54 @@ def _iadd_poly_monom(p1, p2, mc):
return p1

def degree(f, x=None):
"""The leading degree in ``x`` or the main variable. """
"""
The leading degree in ``x`` or the main variable.
Note that the degree of 0 is negative infinity (the SymPy object -oo).
"""
i = f.ring.index(x)

if not f:
return -1
return -oo
else:
return max([ monom[i] for monom in f.itermonoms() ])

def degrees(f):
"""A tuple containing leading degrees in all variables. """
"""
A tuple containing leading degrees in all variables.
Note that the degree of 0 is negative infinity (the SymPy object -oo)
"""
if not f:
return (-1,)*f.ring.ngens
return (-oo,)*f.ring.ngens
else:
return tuple(map(max, list(zip(*f.itermonoms()))))

def tail_degree(f, x=None):
"""The tail degree in ``x`` or the main variable. """
"""
The tail degree in ``x`` or the main variable.
Note that the degree of 0 is negative infinity (the SymPy object -oo)
"""
i = f.ring.index(x)

if not f:
return -1
return -oo
else:
return min([ monom[i] for monom in f.itermonoms() ])

def tail_degrees(f):
"""A tuple containing tail degrees in all variables. """
"""
A tuple containing tail degrees in all variables.
Note that the degree of 0 is negative infinity (the SymPy object -oo)
"""
if not f:
return (-1,)*f.ring.ngens
return (-oo,)*f.ring.ngens
else:
return tuple(map(min, list(zip(*f.itermonoms()))))

Expand Down
Loading

0 comments on commit fc712c7

Please sign in to comment.