diff --git a/src/sage/modular/modsym/ambient.py b/src/sage/modular/modsym/ambient.py index 378ba0b9e8d..c0009cfd0cd 100644 --- a/src/sage/modular/modsym/ambient.py +++ b/src/sage/modular/modsym/ambient.py @@ -1781,10 +1781,10 @@ def factorization(self): D.append((E,1)) r = self.dimension() - s = sum([A.rank()*mult for A, mult in D]) + s = sum(A.rank() * mult for A, mult in D) D = sage.structure.all.Factorization(D, cr=True, sort=False) - D.sort(_cmp = cmp) - assert r == s, "bug in factorization -- self has dimension %s, but sum of dimensions of factors is %s\n%s"%(r, s, D) + D.sort() + assert r == s, "bug in factorization -- self has dimension %s, but sum of dimensions of factors is %s\n%s" % (r, s, D) self._factorization = D return self._factorization diff --git a/src/sage/structure/factorization.py b/src/sage/structure/factorization.py index a672ade981b..ff84da7d8d9 100644 --- a/src/sage/structure/factorization.py +++ b/src/sage/structure/factorization.py @@ -637,27 +637,35 @@ def simplify(self): if repeat: self.simplify() - def sort(self, _cmp=None): + def sort(self, _cmp=None, key=None): r""" Sort the factors in this factorization. INPUT: - - ``_cmp`` - (default: None) comparison function + - ``_cmp`` - (default: ``None``) comparison function (deprecated) + - ``key`` - (default: ``None``) comparison key OUTPUT: - - changes this factorization to be sorted + - changes this factorization to be sorted (inplace) - If _cmp is None, we determine the comparison function as - follows: If the prime in the first factor has a dimension + If ``_cmp`` is ``None``, we use a comparison key. + + If ``key`` is ``None``, we determine the comparison key as + follows: + + If the prime in the first factor has a dimension method, then we sort based first on *dimension* then on - the exponent. If there is no dimension method, we next + the exponent. + + If there is no dimension method, we next attempt to sort based on a degree method, in which case, we sort based first on *degree*, then exponent to break ties when two factors have the same degree, and if those match - break ties based on the actual prime itself. If there is no - degree method, we sort based on dimension. + break ties based on the actual prime itself. + + Otherwise, we sort according to the prime itself. EXAMPLES: @@ -667,52 +675,62 @@ def sort(self, _cmp=None): sage: F = factor(x^3 + 1); F (x + 1) * (x^2 - x + 1) - Then we sort it but using the negated version of the standard - Python cmp function:: + We sort it by decreasing degree:: - sage: F.sort(_cmp = lambda x,y: -cmp(x,y)) + sage: F.sort(key=lambda x:(-x[0].degree(), x)) + sage: F + (x^2 - x + 1) * (x + 1) + + TESTS: + + We sort it using the negated version of the + Python cmp function (using ``_cmp`` is deprecated):: + + sage: F.sort(_cmp=lambda x,y: -cmp(x,y)) + doctest:...: DeprecationWarning: Please use 'key' to sort. + See http://trac.sagemath.org/21145 for details. sage: F (x^2 - x + 1) * (x + 1) """ if len(self) == 0: return - if _cmp is None: + + if _cmp is not None: + # no longer possible in py3 + from sage.misc.superseded import deprecation + deprecation(21145, "Please use 'key' to sort.") + self.__x.sort(cmp=_cmp) + return + + if key is not None: + self.__x.sort(key=key) + return + + a = self.__x[0][0] + sort_key = None + if hasattr(a, 'dimension'): try: - a = self.__x[0][0].dimension() - def _cmp(f,g): - """ - This is used internally for comparing. (indirect doctest) - - EXAMPLES:: - - sage: factor(6) - 2 * 3 - """ - try: - return cmp((f[0].dimension(), f[1]), (g[0].dimension(),g[1])) - except (AttributeError, NotImplementedError): - return cmp((f[0],f[1]), (g[0], g[1])) - except (AttributeError, NotImplementedError): - try: - a = self.__x[0][0].degree() - def _cmp(f,g): - """ - This is used internally for comparing. (indirect doctest) - - EXAMPLES:: - - sage: factor(6) - 2 * 3 - """ - try: - return cmp((f[0].degree(),f[1],f[0]), (g[0].degree(),g[1],g[0])) - except (AttributeError, NotImplementedError): - return cmp(f[0], g[0]) - except (AttributeError, NotImplementedError, TypeError): # TypeError in case degree must take an argument, e.g., for symbolic expressions it has to. - self.__x.sort() - return - - self.__x.sort(_cmp) + a.dimension() + + def sort_key(f): + return (f[0].dimension(), f[1], f[0]) + except (AttributeError, NotImplementedError, TypeError): + pass + elif hasattr(a, 'degree'): + try: + a.degree() + + def sort_key(f): + return (f[0].degree(), f[1], f[0]) + except (AttributeError, NotImplementedError, TypeError): + pass + + if sort_key is None: + + def sort_key(f): + return f[0] + + self.__x.sort(key=sort_key) def unit(self): r""" diff --git a/src/sage/structure/factorization_integer.py b/src/sage/structure/factorization_integer.py index dac3fed52e0..dfaf8467bae 100644 --- a/src/sage/structure/factorization_integer.py +++ b/src/sage/structure/factorization_integer.py @@ -82,20 +82,41 @@ def __init__(self, x, unit=None, cr=False, sort=True, simplify=True, super(IntegerFactorization, self).__init__(x, unit=unit, cr=cr, sort=sort, simplify=simplify) - def __sort__(self, _cmp=None): + def __sort__(self, _cmp=None, key=None): """ Sort the factors in this factorization. INPUT: - - ``_cmp`` - (default: None) comparison function + - ``_cmp`` - (default: ``None``) comparison function + - ``key`` - (default: ``None``) comparison key EXAMPLES:: + sage: F = factor(15) + sage: F.sort(key = lambda x: -x[0]) + sage: F + 5 * 3 + + TESTS: + + Using ``_cmp`` is deprecated:: + sage: F = factor(15) sage: F.sort(_cmp = lambda x,y: -cmp(x,y)) + doctest:...: DeprecationWarning: Please use 'key' to sort. + See http://trac.sagemath.org/21145 for details. sage: F 5 * 3 """ - self.__x.sort(_cmp) - + if _cmp is not None: + from sage.misc.superseded import deprecation + deprecation(21145, "Please use 'key' to sort.") + self.__x.sort(cmp=_cmp) + return + elif 'key' is not None: + self.__x.sort(key=key) + return + else: + self.__x.sort() + return