diff --git a/src/sage/rings/complex_mpc.pyx b/src/sage/rings/complex_mpc.pyx index 748bdc0c240..81f4fa21f6c 100644 --- a/src/sage/rings/complex_mpc.pyx +++ b/src/sage/rings/complex_mpc.pyx @@ -70,6 +70,7 @@ from sage.libs.mpc cimport * from sage.structure.parent cimport Parent from sage.structure.parent_gens cimport ParentWithGens from sage.structure.element cimport RingElement, Element, ModuleElement +from sage.structure.richcmp cimport rich_to_bool from sage.categories.map cimport Map from sage.libs.pari.all import pari @@ -912,20 +913,21 @@ cdef class MPComplexNumber(sage.structure.element.FieldElement): sage: b = C(393.39203845902384098234098230948209384028340) sage: loads(dumps(b)) == b True - sage: C(1) - 1.0000000000000000000000000000000000000000000000000000000000 - sage: b = C(1)/C(0); b - NaN + NaN*I - sage: loads(dumps(b)) == b - True - sage: b = C(-1)/C(0.); b - NaN + NaN*I - sage: loads(dumps(b)) == b - True sage: b = C(-1).sqrt(); b 1.0000000000000000000000000000000000000000000000000000000000*I sage: loads(dumps(b)) == b True + + Some tests with ``NaN``, which cannot be compared to anything:: + + sage: b = C(1)/C(0); b + NaN + NaN*I + sage: loads(dumps(b)) + NaN + NaN*I + sage: b = C(-1)/C(0.); b + NaN + NaN*I + sage: loads(dumps(b)) + NaN + NaN*I """ s = self.str(32) return (__create_MPComplexNumber_version0, (self._parent, s, 32)) @@ -1259,7 +1261,7 @@ cdef class MPComplexNumber(sage.structure.element.FieldElement): """ return gmpy2.GMPy_MPC_From_mpfr(self.value.re, self.value.im) - cpdef int _cmp_(self, other) except -2: + cpdef _richcmp_(self, other, int op): r""" Compare ``self`` to ``other``. @@ -1275,19 +1277,16 @@ cdef class MPComplexNumber(sage.structure.element.FieldElement): """ cdef MPComplexNumber z = other # NaN should compare to nothing - if mpfr_nan_p (self.value.re) or mpfr_nan_p (self.value.im) or mpfr_nan_p (z.value.re) or mpfr_nan_p (z.value.im): + if mpfr_nan_p(self.value.re) or mpfr_nan_p(self.value.im) or mpfr_nan_p(z.value.re) or mpfr_nan_p(z.value.im): return False cdef int c = mpc_cmp(self.value, z.value) cdef int cre = MPC_INEX_RE(c) cdef int cim if cre: - if cre>0: return 1 - else: return -1 + return rich_to_bool(op, cre) else: cim = MPC_INEX_IM(c) - if cim>0: return 1 - elif cim<0: return -1 - else: return 0 + return rich_to_bool(op, cim) def __nonzero__(self): """ diff --git a/src/sage/rings/integer.pyx b/src/sage/rings/integer.pyx index b510d0d75ec..3ba6a217caf 100644 --- a/src/sage/rings/integer.pyx +++ b/src/sage/rings/integer.pyx @@ -937,14 +937,11 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): c = mpz_cmp((left).value, (right).value) elif isinstance(right, Rational): c = -mpq_cmp_z((right).value, (left).value) - elif isinstance(right, long): + elif isinstance(right, int): mpz_init(mpz_tmp) mpz_set_pylong(mpz_tmp, right) c = mpz_cmp((left).value, mpz_tmp) mpz_clear(mpz_tmp) - elif isinstance(right, int): - # this case should only occur in python 2 - c = mpz_cmp_si((left).value, PyInt_AS_LONG(right)) elif isinstance(right, float): d = right if isnan(d): @@ -955,20 +952,23 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): return rich_to_bool_sgn(op, c) - cpdef int _cmp_(left, right) except -2: + cpdef _richcmp_(left, right, int op): r""" EXAMPLES:: - sage: 1._cmp_(2) - -1 - sage: 0._cmp_(0) - 0 - sage: (-3**10 + 1)._cmp_(-3**10) - 1 + sage: from sage.structure.richcmp import op_EQ, op_NE, op_LT, op_GE + sage: 1._richcmp_(2, op_LT) + True + sage: 0._richcmp_(0, op_EQ) + True + sage: (-4)._richcmp_(-4, op_NE) + False + sage: (-3**10 + 1)._richcmp_(-3**10, op_GE) + True """ cdef int c c = mpz_cmp((left).value, (right).value) - return (c > 0) - (c < 0) + return rich_to_bool_sgn(op, c) def __copy__(self): """ diff --git a/src/sage/structure/element.pyx b/src/sage/structure/element.pyx index 0586d2f80a2..b272940fa8a 100644 --- a/src/sage/structure/element.pyx +++ b/src/sage/structure/element.pyx @@ -315,6 +315,7 @@ from sage.arith.long cimport integer_check_long_py from sage.arith.power cimport generic_power as arith_generic_power from sage.arith.numerical_approx cimport digits_to_bits from sage.misc.decorators import sage_wraps +from sage.misc.superseded import deprecation def make_element(_class, _dict, parent): @@ -373,7 +374,6 @@ cdef class Element(SageObject): Subtypes must either call ``__init__()`` to set ``_parent``, or may set ``_parent`` themselves if that would be more efficient. - .. automethod:: _cmp_ .. automethod:: _richcmp_ .. automethod:: __add__ .. automethod:: __sub__ @@ -1075,18 +1075,12 @@ cdef class Element(SageObject): return self.parent(), str(self) #################################################################### - # In a Cython or a Python class, you must define either _cmp_ - # (if your subclass is totally ordered), _richcmp_ (if your subclass - # is partially ordered), or both (if your class has both a total order - # and a partial order, or if that gives better performance). + # In a Cython or a Python class, you must define _richcmp_ # - # Rich comparisons (like a < b) will default to using _richcmp_, - # three-way comparisons (like cmp(a,b)) will default to using - # _cmp_. But if you define just one of _richcmp_ and _cmp_, it will - # be used for all kinds of comparisons. + # Rich comparisons (like a < b) will use _richcmp_ # - # In the _cmp_ and _richcmp_ methods, you can assume that both - # arguments have identical parents. + # In the _richcmp_ method, you can assume that both arguments have + # identical parents. #################################################################### def __richcmp__(self, other, int op): """ @@ -1118,13 +1112,12 @@ cdef class Element(SageObject): cpdef _richcmp_(left, right, int op): r""" - Default implementation of rich comparisons for elements with + Basic default implementation of rich comparisons for elements with equal parents. - It tries to see if ``_cmp_`` is implemented. Otherwise it does a - comparison by id for ``==`` and ``!=``. Calling this default method - with ``<``, ``<=``, ``>`` or ``>=`` will raise a - ``NotImplementedError``. + It does a comparison by id for ``==`` and ``!=``. Calling this + default method with ``<``, ``<=``, ``>`` or ``>=`` will return + ``NotImplemented``. EXAMPLES:: @@ -1139,7 +1132,7 @@ cdef class Element(SageObject): sage: e1 < e2 # indirect doctest Traceback (most recent call last): ... - NotImplementedError: comparison not implemented for <... 'sage.structure.element.Element'> + TypeError: '<' not supported between instances of 'sage.structure.element.Element' and 'sage.structure.element.Element' We now create an ``Element`` class where we define ``_richcmp_`` and check that comparison works:: @@ -1160,44 +1153,23 @@ cdef class Element(SageObject): sage: b = FloatCmp(2) sage: a <= b, b <= a (True, False) - - This works despite ``_cmp_`` not being implemented:: - - sage: a._cmp_(b) - Traceback (most recent call last): - ... - NotImplementedError: comparison not implemented for <... '...FloatCmp'> """ # Obvious case if left is right: return rich_to_bool(op, 0) - - cdef int c - try: - c = left._cmp_(right) - except NotImplementedError: - # Check equality by id(), knowing that left is not right - if op == Py_EQ: - return False - if op == Py_NE: - return True - raise - assert -1 <= c <= 1 - return rich_to_bool(op, c) + # Check equality by id(), knowing that left is not right + if op == Py_EQ: + return False + if op == Py_NE: + return True + return NotImplemented cpdef int _cmp_(left, right) except -2: """ - Default three-way comparison method which only checks for a - Python class defining ``__cmp__``. + This was the old comparison framework. Now deprecated. Do not use. """ - try: - left_cmp = left.__cmp__ - except AttributeError: - pass - else: - return left_cmp(right) - msg = LazyFormat("comparison not implemented for %r") % type(left) - raise NotImplementedError(msg) + deprecation(30130, "please use _richcmp_ for comparison methods") + raise NotImplementedError("__cmp__ and _cmp_ are deprecated") ################################################## # Arithmetic using the coercion model