Skip to content

Commit

Permalink
Trac #21766: py3-compatible way to sort monomials
Browse files Browse the repository at this point in the history
currently using a cmp, we need to switch to sorting using a key

may not be entirely obvious

URL: https://trac.sagemath.org/21766
Reported by: chapoton
Ticket author(s): Frédéric Chapoton
Reviewer(s): Travis Scrimshaw
  • Loading branch information
Release Manager authored and vbraun committed Nov 9, 2016
2 parents 77ae6bc + b67b06b commit e07cea8
Show file tree
Hide file tree
Showing 4 changed files with 291 additions and 177 deletions.
12 changes: 6 additions & 6 deletions src/sage/rings/polynomial/laurent_polynomial.pyx
Expand Up @@ -1545,12 +1545,12 @@ cdef class LaurentPolynomial_mpair(LaurentPolynomial_generic):
if self._prod is None:
self._compute_polydict()
try:
cmpfn = self.parent().term_order().compare_tuples
key = self.parent().term_order().sortkey
except AttributeError:
cmpfn = None
key = None
atomic = self.parent().base_ring()._repr_option('element_is_atomic')
return self._prod.poly_repr(self.parent().variable_names(),
atomic_coefficients=atomic, cmpfn=cmpfn)
atomic_coefficients=atomic, sortkey=key)

def _latex_(self):
"""
Expand All @@ -1566,12 +1566,12 @@ cdef class LaurentPolynomial_mpair(LaurentPolynomial_generic):
if self._prod is None:
self._compute_polydict()
try:
cmpfn = self.parent().term_order().compare_tuples
key = self.parent().term_order().sortkey
except AttributeError:
cmpfn = None
key = None
atomic = self.parent().base_ring()._repr_option('element_is_atomic')
return self._prod.latex(self.parent().variable_names(),
atomic_coefficients=atomic, cmpfn=cmpfn)
atomic_coefficients=atomic, sortkey=key)

def __invert__(LaurentPolynomial_mpair self):
"""
Expand Down
24 changes: 13 additions & 11 deletions src/sage/rings/polynomial/multi_polynomial_element.py
Expand Up @@ -180,7 +180,7 @@ def __cmp__(self, right):
"""
try:
return self.__element.compare(right.__element,
self.parent().term_order().compare_tuples)
self.parent().term_order().sortkey)
except AttributeError:
return self.__element.compare(right.__element)

Expand Down Expand Up @@ -390,12 +390,13 @@ def _repr_(self):
'-x^2 + (-I)*y'
"""
try:
cmpfn = self.parent().term_order().compare_tuples
key = self.parent().term_order().sortkey
except AttributeError:
cmpfn = None
key = None
atomic = self.parent().base_ring()._repr_option('element_is_atomic')
return self.element().poly_repr(self.parent().variable_names(),
atomic_coefficients=atomic, cmpfn=cmpfn )
atomic_coefficients=atomic,
sortkey=key)

def _latex_(self):
r"""
Expand All @@ -410,12 +411,12 @@ def _latex_(self):
\left(\sqrt{-1}\right) x^{2} + \left(-\sqrt{-1}\right) y
"""
try:
cmpfn = self.parent().term_order().compare_tuples
key = self.parent().term_order().sortkey
except AttributeError:
cmpfn = None
key = None
atomic = self.parent().base_ring()._repr_option('element_is_atomic')
return self.element().latex(self.parent().latex_variable_names(),
atomic_coefficients=atomic, cmpfn=cmpfn)
atomic_coefficients=atomic, sortkey=key)

def _repr_with_changed_varnames(self, varnames):
"""
Expand All @@ -427,12 +428,12 @@ def _repr_with_changed_varnames(self, varnames):
'-jack^2 - jill + 1'
"""
try:
cmpfn = self.parent().term_order().compare_tuples
key = self.parent().term_order().sortkey
except AttributeError:
cmpfn = None
key = None
atomic = self.parent().base_ring()._repr_option('element_is_atomic')
return self.element().poly_repr(varnames,
atomic_coefficients=atomic, cmpfn=cmpfn)
atomic_coefficients=atomic, sortkey=key)

def degrees(self):
r"""
Expand Down Expand Up @@ -874,7 +875,8 @@ def exponents(self, as_ETuples=True):
except AttributeError:
self.__exponents = self.element().dict().keys()
try:
self.__exponents.sort(cmp=self.parent().term_order().compare_tuples, reverse=True)
self.__exponents.sort(key=self.parent().term_order().sortkey,
reverse=True)
except AttributeError:
pass
if as_ETuples:
Expand Down
78 changes: 50 additions & 28 deletions src/sage/rings/polynomial/polydict.pyx
Expand Up @@ -41,12 +41,14 @@ from __future__ import print_function
include "cysignals/memory.pxi"
from libc.string cimport memcpy
from cpython.dict cimport *
from cpython.object cimport PyObject_RichCompare

import copy
from functools import reduce
from sage.structure.element import generic_power
from sage.misc.misc import cputime
from sage.misc.latex import latex
from sage.misc.superseded import deprecation


cdef class PolyDict:
Expand Down Expand Up @@ -118,35 +120,47 @@ cdef class PolyDict:
self.__repn = pdict
self.__zero = zero

def __cmp__(self, PolyDict right):
return cmp(self.__repn, right.__repn)
def __richcmp__(PolyDict self, PolyDict right, int op):
return PyObject_RichCompare(self.__repn, right.__repn, op)

def compare(PolyDict self, PolyDict other, fn=None):
if fn is None:
def compare(PolyDict self, PolyDict other, key=None):
if key is not None:
# start with biggest
left = iter(sorted(self.__repn, key=key, reverse=True))
right = iter(sorted(other.__repn, key=key, reverse=True))
else:
# in despair, do that
assert False
return cmp(self.__repn, other.__repn)

left = iter(sorted( self.__repn,fn,reverse=True)) #start with biggest
right = iter(sorted(other.__repn,fn,reverse=True))

for m in left:
try:
n = next(right)
except StopIteration:
return 1 # left has terms, right doesn't
ret = fn(m,n)
if ret!=0:
return ret # we have a difference
ret = cmp(self.__repn[m],other.__repn[n]) #compare coefficients
if ret!=0:
return ret #if they differ use it
#try next pair

return 1 # left has terms, right does not

# first compare the leading monomials
keym = key(m)
keyn = key(n)
if keym > keyn:
return 1
elif keym < keyn:
return -1

# same leading monomial, compare their coefficients
coefm = self.__repn[m]
coefn = other.__repn[n]
if coefm > coefn:
return 1
elif coefm < coefn:
return -1

# try next pair
try:
n = next(right)
return -1 # right has terms, left does not
except StopIteration:
return 0 # both have no terms

return -1 # right has terms, left doesn't
return 0 # both have no terms

def list(PolyDict self):
"""
Expand Down Expand Up @@ -389,7 +403,8 @@ cdef class PolyDict:
H[ETuple(f)] = val
return PolyDict(H, zero=self.__zero, force_etuples=False)

def latex(PolyDict self, vars, atomic_exponents=True, atomic_coefficients=True, cmpfn = None):
def latex(PolyDict self, vars, atomic_exponents=True,
atomic_coefficients=True, cmpfn=None, sortkey=None):
r"""
Return a nice polynomial latex representation of this PolyDict, where
the vars are substituted in.
Expand Down Expand Up @@ -427,8 +442,11 @@ cdef class PolyDict:
n = len(vars)
poly = ""
E = self.__repn.keys()
if cmpfn:
E.sort(cmp = cmpfn, reverse=True)
if sortkey:
E.sort(key=sortkey, reverse=True)
elif cmpfn:
deprecation(21766, 'the cmpfn keyword is deprecated, use sortkey')
E.sort(cmp=cmpfn, reverse=True)
else:
E.sort(reverse=True)
try:
Expand Down Expand Up @@ -476,16 +494,17 @@ cdef class PolyDict:
return poly


def poly_repr(PolyDict self, vars, atomic_exponents=True, atomic_coefficients=True, cmpfn = None):
def poly_repr(PolyDict self, vars, atomic_exponents=True,
atomic_coefficients=True, cmpfn=None, sortkey=None):
"""
Return a nice polynomial string representation of this PolyDict, where
the vars are substituted in.
INPUT:
- ``vars`` -- list
- ``atomic_exponents`` -- bool (default: True)
- ``atomic_coefficients`` -- bool (default: True)
- ``atomic_exponents`` -- bool (default: ``True``)
- ``atomic_coefficients`` -- bool (default: ``True``)
EXAMPLES::
Expand All @@ -494,7 +513,7 @@ cdef class PolyDict:
sage: f.poly_repr(['a','WW'])
'2*a^2*WW^3 + 4*a^2*WW + 3*a*WW^2'
When atomic_exponents is False, the exponents are surrounded
When atomic_exponents is ``False``, the exponents are surrounded
in parenthesis, since ^ has such high precedence. ::
# I've removed fractional exponent support in ETuple when moving to a sparse C integer array
Expand All @@ -517,8 +536,11 @@ cdef class PolyDict:
n = len(vars)
poly = ""
E = self.__repn.keys()
if cmpfn:
E.sort(cmp = cmpfn, reverse=True)
if sortkey:
E.sort(key=sortkey, reverse=True)
elif cmpfn:
deprecation(21766, 'the cmpfn keyword is deprecated, use sortkey')
E.sort(cmp=cmpfn, reverse=True)
else:
E.sort(reverse=True)
try:
Expand Down

0 comments on commit e07cea8

Please sign in to comment.