def __richcmp__(self, right, op): r""" Try to compare ``self`` and ``right``. .. NOTE:: Comparison is basically not implemented, or rather it could say sets are not equal even though they are. I don't know how one could implement this for a generic symmetric difference of sets in a meaningful manner. So be careful when using this. EXAMPLES:: sage: Y = Set(ZZ).symmetric_difference(Set(QQ)) sage: X = Set(QQ).symmetric_difference(Set(ZZ)) sage: X == Y True sage: Y == X True """ if not isinstance(right, Set_generic): return rich_to_bool(op, -1) if not isinstance(right, Set_object_symmetric_difference): return rich_to_bool(op, -1) if self._X == right._X and self._Y == right._Y or \ self._X == right._Y and self._Y == right._X: return rich_to_bool(op, 0) return rich_to_bool(op, -1)
def __richcmp__(self, other, op): """ Comparison of truth value. EXAMPLES:: sage: l = [False, Unknown, True] sage: for a in l: print([a < b for b in l]) [False, True, True] [False, False, True] [False, False, False] sage: for a in l: print([a <= b for b in l]) [True, True, True] [False, True, True] [False, False, True] """ if other is self: return rich_to_bool(op, 0) if not isinstance(other, bool): return NotImplemented if other: return rich_to_bool(op, -1) else: return rich_to_bool(op, +1)
def __richcmp__(self, right, op): r""" Try to compare ``self`` and ``right``. .. NOTE:: Comparison is basically not implemented, or rather it could say sets are not equal even though they are. I don't know how one could implement this for a generic symmetric difference of sets in a meaningful manner. So be careful when using this. EXAMPLES:: sage: Y = Set(ZZ).symmetric_difference(Set(QQ)) sage: X = Set(QQ).symmetric_difference(Set(ZZ)) sage: X == Y True sage: Y == X True """ if not isinstance(right, Set_generic): return rich_to_bool(op, -1) if not isinstance(right, Set_object_symmetric_difference): return rich_to_bool(op, -1) if self._X == right._X and self._Y == right._Y or \ self._X == right._Y and self._Y == right._X: return rich_to_bool(op, 0) return rich_to_bool(op, -1)
def _richcmp_(self, other, op): """ EXAMPLES:: sage: one = lisp(1); two = lisp(2) sage: one == one True sage: one != two True sage: one < two True sage: two > one True sage: one < 1 False sage: two == 2 True """ P = self._check_valid() if parent(other) is not P: other = P(other) if P.eval('(= %s %s)' % (self.name(), other.name())) == P._true_symbol(): return rich_to_bool(op, 0) elif P.eval('(< %s %s)' % (self.name(), other.name())) == P._true_symbol(): return rich_to_bool(op, -1) else: return rich_to_bool(op, 1)
def __richcmp__(self, other, op): r""" TESTS:: sage: a1 = AbelianStratum(1,1,1,1) sage: c1 = a1.connected_components()[0] sage: a2 = AbelianStratum(3,1) sage: c2 = a2.connected_components()[0] sage: c1 == c1 True sage: c1 == c2 False sage: a1 = AbelianStratum(1,1,1,1) sage: c1 = a1.connected_components()[0] sage: a2 = AbelianStratum(2, 2) sage: c2_hyp, c2_odd = a2.connected_components() sage: c1 != c1 False sage: c1 != c2_hyp True sage: c2_hyp != c2_odd True sage: c1 == True False """ if not isinstance(other, CCA) or type(self) != type(other): return NotImplemented if self._parent._zeroes < other._parent._zeroes: return rich_to_bool(op, 1) elif self._parent._zeroes > other._parent._zeroes: return rich_to_bool(op, -1) return rich_to_bool(op, 0)
def _richcmp_(self, rhs, op): r""" EXAMPLES:: sage: from pyexactreal import ExactReals sage: R = ExactReals() sage: x = R.random_element() # a random element in [0, 1] sage: x > -x True sage: x < -x False sage: -x < x True sage: -x > x False sage: -x == -x True sage: x == -x False """ from sage.structure.richcmp import rich_to_bool if self._backend < rhs._backend: return rich_to_bool(op, -1) elif self._backend == rhs._backend: return rich_to_bool(op, 0) else: return rich_to_bool(op, 1)
def __richcmp__(self, other, op): """ Comparison of truth value. EXAMPLES:: sage: l = [False, Unknown, True] sage: for a in l: print([a < b for b in l]) [False, True, True] [False, False, True] [False, False, False] sage: for a in l: print([a <= b for b in l]) [True, True, True] [False, True, True] [False, False, True] """ if other is self: return rich_to_bool(op, 0) if not isinstance(other, bool): return NotImplemented if other: return rich_to_bool(op, -1) else: return rich_to_bool(op, +1)
def _richcmp_(self, other, op): """ Comparison of interface elements. NOTE: GAP has a special role here. It may in some cases raise an error when comparing objects, which is unwanted in Python. We catch these errors. Moreover, GAP does not recognise certain objects as equal even if there definitions are identical. NOTE: This methods need to be overridden if the subprocess would not return a string representation of a boolean value unless an explicit print command is used. TESTS: Here are examples in which GAP succeeds with a comparison:: sage: gap('SymmetricGroup(8)')==gap('SymmetricGroup(8)') True sage: gap('SymmetricGroup(8)')>gap('AlternatingGroup(8)') False sage: gap('SymmetricGroup(8)')<gap('AlternatingGroup(8)') True Here, GAP fails to compare, and so ``False`` is returned. In previous Sage versions, this example actually resulted in an error; compare :trac:`5962`. :: sage: gap('DihedralGroup(8)')==gap('DihedralGroup(8)') False """ P = self._check_valid() try: if P.eval("%s %s %s" % (self.name(), P._equality_symbol(), other.name())) == P._true_symbol(): return rich_to_bool(op, 0) except RuntimeError: pass try: if P.eval("%s %s %s" % (self.name(), P._lessthan_symbol(), other.name())) == P._true_symbol(): return rich_to_bool(op, -1) except RuntimeError: pass try: if P.eval("%s %s %s" % (self.name(), P._greaterthan_symbol(), other.name())) == P._true_symbol(): return rich_to_bool(op, 1) except Exception: pass return NotImplemented
def _richcmp_(self, other, op): P = self.parent() if P.eval("%s < %s"%(self.name(), other.name())).strip() == 'True': return rich_to_bool(op, -1) elif P.eval("%s > %s"%(self.name(), other.name())).strip() == 'True': return rich_to_bool(op, 1) elif P.eval("%s == %s"%(self.name(), other.name())).strip() == 'True': return rich_to_bool(op, 0) return NotImplemented
def _richcmp_(self, other, op): """ Compare ``self`` to ``other``. EXAMPLES:: sage: 1 == unsigned_infinity False """ if isinstance(other, LessThanInfinity): return rich_to_bool(op, 1) return rich_to_bool(op, 0)
def _richcmp_(self, other, op): """ Compare the two ideals. EXAMPLES: Comparison with non-principal ideal:: sage: R.<x> = ZZ[] sage: I = R.ideal([x^3 + 4*x - 1, x + 6]) sage: J = [x^2] * R sage: I > J # indirect doctest True sage: J < I # indirect doctest True Between two principal ideals:: sage: P.<x> = PolynomialRing(ZZ) sage: I = P.ideal(x^2-2) sage: I2 = P.ideal(0) sage: I2.is_zero() True sage: I2 < I True sage: I3 = P.ideal(x) sage: I > I3 True """ if not isinstance(other, Ideal_generic): other = self.ring().ideal(other) try: if not other.is_principal(): return rich_to_bool(op, -1) except NotImplementedError: # If we do not know if the other is principal or not, then we # fallback to the generic implementation return Ideal_generic._richcmp_(self, other, op) if self.is_zero(): if not other.is_zero(): return rich_to_bool(op, -1) return rich_to_bool(op, 0) # is other.gen() / self.gen() a unit in the base ring? g0 = other.gen() g1 = self.gen() if g0.divides(g1) and g1.divides(g0): return rich_to_bool(op, 0) return rich_to_bool(op, 1)
def _richcmp_(self, other, op): """ Compare the two ideals. EXAMPLES: Comparison with non-principal ideal:: sage: R.<x> = ZZ[] sage: I = R.ideal([x^3 + 4*x - 1, x + 6]) sage: J = [x^2] * R sage: I > J # indirect doctest True sage: J < I # indirect doctest True Between two principal ideals:: sage: P.<x> = PolynomialRing(ZZ) sage: I = P.ideal(x^2-2) sage: I2 = P.ideal(0) sage: I2.is_zero() True sage: I2 < I True sage: I3 = P.ideal(x) sage: I > I3 True """ if not isinstance(other, Ideal_generic): other = self.ring().ideal(other) try: if not other.is_principal(): return rich_to_bool(op, -1) except NotImplementedError: # If we do not know if the other is principal or not, then we # fallback to the generic implementation return Ideal_generic._richcmp_(self, other, op) if self.is_zero(): if not other.is_zero(): return rich_to_bool(op, -1) return rich_to_bool(op, 0) # is other.gen() / self.gen() a unit in the base ring? g0 = other.gen() g1 = self.gen() if g0.divides(g1) and g1.divides(g0): return rich_to_bool(op, 0) return rich_to_bool(op, 1)
def _richcmp_(self, other, op): r""" EXAMPLES:: sage: K.<a> = Qq(125) sage: V, fr, to = K.free_module() sage: fr == fr True """ # For maps of this type, equality depends only on the parent if isinstance(other, pAdicModuleIsomorphism): return rich_to_bool(op, 0) else: return rich_to_bool(op, 1)
def _richcmp_(self, other, op): r""" Compare self and other (where the coercion model has already ensured that self and other have the same parent). Hecke operators on the same space compare as equal if and only if their matrices are equal, so we check if the indices are the same and if not we compute the matrices (which is potentially expensive). EXAMPLES:: sage: M = ModularSymbols(Gamma0(7), 4) sage: m = M.hecke_operator(3) sage: m == m True sage: m == 2*m False sage: m == M.hecke_operator(5) False These last two tests involve a coercion:: sage: m == m.matrix_form() True sage: m == m.matrix() False """ if not isinstance(other, HeckeOperator): if isinstance(other, HeckeAlgebraElement_matrix): return richcmp(self.matrix_form(), other, op) else: raise RuntimeError("Bug in coercion code") # can't get here if self.__n == other.__n: return rich_to_bool(op, 0) return richcmp(self.matrix(), other.matrix(), op)
def _richcmp_(self, other, op): """ Compare ``self`` and ``other``. TESTS:: sage: A = ArtinGroup(['B',3]) sage: x = A([1, 2, 1]) sage: y = A([2, 1, 2]) sage: x == y True sage: x < y^(-1) True sage: A([]) == A.one() True sage: x = A([2, 3, 2, 3]) sage: y = A([3, 2, 3, 2]) sage: x == y True sage: x < y^(-1) True """ if self.Tietze() == other.Tietze(): return rich_to_bool(op, 0) nfself = [i.Tietze() for i in self.left_normal_form()] nfother = [i.Tietze() for i in other.left_normal_form()] return richcmp(nfself, nfother, op)
def _richcmp_(self, other, op): r""" Compare this element with ``other``. TESTS:: sage: R = ZpLC(2) sage: x = R(1, 5) sage: y = R(128, 10) sage: z = x + y sage: x 1 + O(2^5) sage: z 1 + O(2^5) sage: x == z # Indirect doctest False sage: z - x 2^7 + O(2^10) """ if (self - other).is_zero(): return rich_to_bool(op, 0) else: return richcmp(QQ(self.lift()), QQ(other.lift()), op)
def __richcmp__(self, other, op): """ Rich comparison. EXAMPLES:: sage: ct1 = CartanType(['A',1],['B',2]) sage: ct2 = CartanType(['B',2],['A',1]) sage: ct3 = CartanType(['A',4]) sage: ct1 == ct1 True sage: ct1 == ct2 False sage: ct1 == ct3 False TESTS: Check that :trac:`20418` is fixed:: sage: ct = CartanType(["A2", "B2"]) sage: ct == (1, 2, 1) False """ if isinstance(other, CartanType_simple): return rich_to_bool(op, 1) if not isinstance(other, CartanType): return NotImplemented return richcmp(self._types, other._types, op)
def __richcmp__(self, other, op): """ Rich comparison. EXAMPLES:: sage: ct1 = CartanType(['A',1],['B',2]) sage: ct2 = CartanType(['B',2],['A',1]) sage: ct3 = CartanType(['A',4]) sage: ct1 == ct1 True sage: ct1 == ct2 False sage: ct1 == ct3 False TESTS: Check that :trac:`20418` is fixed:: sage: ct = CartanType(["A2", "B2"]) sage: ct == (1, 2, 1) False """ if isinstance(other, CartanType_simple): return rich_to_bool(op, 1) if not isinstance(other, CartanType): return NotImplemented return richcmp(self._types, other._types, op)
def _richcmp_(self, other, op): """ Compare ``self`` and ``other``. TESTS:: sage: A = ArtinGroup(['B',3]) sage: x = A([1, 2, 1]) sage: y = A([2, 1, 2]) sage: x == y True sage: x < y^(-1) True sage: A([]) == A.one() True sage: x = A([2, 3, 2, 3]) sage: y = A([3, 2, 3, 2]) sage: x == y True sage: x < y^(-1) True """ if self.Tietze() == other.Tietze(): return rich_to_bool(op, 0) nfself = [i.Tietze() for i in self.left_normal_form()] nfother = [i.Tietze() for i in other.left_normal_form()] return richcmp(nfself, nfother, op)
def _richcmp_(self, other, op): r""" Compare self and other (where the coercion model has already ensured that self and other have the same parent). Hecke operators on the same space compare as equal if and only if their matrices are equal, so we check if the indices are the same and if not we compute the matrices (which is potentially expensive). EXAMPLES:: sage: M = ModularSymbols(Gamma0(7), 4) sage: m = M.hecke_operator(3) sage: m == m True sage: m == 2*m False sage: m == M.hecke_operator(5) False These last two tests involve a coercion:: sage: m == m.matrix_form() True sage: m == m.matrix() False """ if not isinstance(other, HeckeOperator): if isinstance(other, HeckeAlgebraElement_matrix): return richcmp(self.matrix_form(), other, op) else: raise RuntimeError("Bug in coercion code") # can't get here if self.__n == other.__n: return rich_to_bool(op, 0) return richcmp(self.matrix(), other.matrix(), op)
def _richcmp_(self, other, op): """ Compare ``self`` and ``other``. EXAMPLES:: sage: P = InfinityRing sage: -oo < P(-5) < P(0) < P(1.5) < oo True sage: P(1) < P(100) False sage: P(-1) == P(-100) True """ if isinstance(other, PlusInfinity): return rich_to_bool(op, 0) return rich_to_bool(op, 1)
def _richcmp_(self, other, op): """ EXAMPLES:: sage: two = axiom(2) #optional - axiom sage: two == 2 #optional - axiom True sage: two == 3 #optional - axiom False sage: two < 3 #optional - axiom True sage: two > 1 #optional - axiom True sage: a = axiom(1); b = axiom(2) #optional - axiom sage: a == b #optional - axiom False sage: a < b #optional - axiom True sage: a > b #optional - axiom False sage: b < a #optional - axiom False sage: b > a #optional - axiom True We can also compare more complicated object such as functions:: sage: f = axiom('sin(x)'); g = axiom('cos(x)') #optional - axiom sage: f == g #optional - axiom False """ P = self.parent() if 'true' in P.eval("(%s = %s) :: Boolean" % (self.name(), other.name())): return rich_to_bool(op, 0) elif 'true' in P.eval("(%s < %s) :: Boolean" % (self.name(), other.name())): return rich_to_bool(op, -1) elif 'true' in P.eval("(%s > %s) :: Boolean" % (self.name(), other.name())): return rich_to_bool(op, 1) return NotImplemented
def __richcmp__(self, other, op): """ Compare the sets ``self`` and ``other``. EXAMPLES:: sage: X = Set(GF(8,'c')) sage: X == Set(GF(8,'c')) True sage: X == Set(GF(4,'a')) False sage: Set(QQ) == Set(ZZ) False """ if not isinstance(other, Set_object_enumerated): return NotImplemented if self.set() == other.set(): return rich_to_bool(op, 0) return rich_to_bool(op, -1)
def __richcmp__(self, other, op): """ Compare the sets ``self`` and ``other``. EXAMPLES:: sage: X = Set(GF(8,'c')) sage: X == Set(GF(8,'c')) True sage: X == Set(GF(4,'a')) False sage: Set(QQ) == Set(ZZ) False """ if not isinstance(other, Set_object_enumerated): return NotImplemented if self.set() == other.set(): return rich_to_bool(op, 0) return rich_to_bool(op, -1)
def _richcmp_(self, right, op): """ Compare the cusps ``self`` and ``right``. Comparison is as for elements in the number field, except with the cusp oo which is greater than everything but itself. The ordering in comparison is only really meaningful for infinity. EXAMPLES:: sage: k.<a> = NumberField(x^3 + x + 1) sage: kCusps = NFCusps(k) Comparing with infinity:: sage: c = kCusps((a,2)) sage: d = kCusps(oo) sage: c < d True sage: kCusps(oo) < d False Comparison as elements of the number field:: sage: kCusps(2/3) < kCusps(5/2) False sage: k(2/3) < k(5/2) False """ if self.__b.is_zero(): if right.__b.is_zero(): return rich_to_bool(op, 0) else: return rich_to_bool(op, 1) else: if right.__b.is_zero(): return rich_to_bool(op, -1) else: return richcmp(self._number_field_element_(), right._number_field_element_(), op)
def _richcmp_(self, right, op): """ Compare the cusps ``self`` and ``right``. Comparison is as for elements in the number field, except with the cusp oo which is greater than everything but itself. The ordering in comparison is only really meaningful for infinity. EXAMPLES:: sage: k.<a> = NumberField(x^3 + x + 1) sage: kCusps = NFCusps(k) Comparing with infinity:: sage: c = kCusps((a,2)) sage: d = kCusps(oo) sage: c < d True sage: kCusps(oo) < d False Comparison as elements of the number field:: sage: kCusps(2/3) < kCusps(5/2) False sage: k(2/3) < k(5/2) False """ if self.__b.is_zero(): if right.__b.is_zero(): return rich_to_bool(op, 0) else: return rich_to_bool(op, 1) else: if right.__b.is_zero(): return rich_to_bool(op, -1) else: return richcmp(self._number_field_element_(), right._number_field_element_(), op)
def _richcmp_(self, other, op): """ Compare this polynomial with other. Polynomials are first compared by degree, then in dictionary order starting with the coefficient of largest degree. EXAMPLES:: sage: R.<x> = PolynomialRing(ZZ, sparse=True) sage: 3*x^100 - 12 > 12*x + 5 True sage: 3*x^100 - 12 > 3*x^100 - x^50 + 5 True sage: 3*x^100 - 12 < 3*x^100 - x^50 + 5 False sage: x^100 + x^10 - 1 < x^100 + x^10 True sage: x^100 < x^100 - x^10 False TESTS:: sage: R.<x> = PolynomialRing(QQ, sparse=True) sage: 2*x^2^500 > x^2^500 True sage: Rd = PolynomialRing(ZZ, 'x', sparse=False) sage: Rs = PolynomialRing(ZZ, 'x', sparse=True) sage: for _ in range(100): ....: pd = Rd.random_element() ....: qd = Rd.random_element() ....: assert bool(pd < qd) == bool(Rs(pd) < Rs(qd)) """ d1 = self.degree() d2 = other.degree() # Special case constant polynomials if d1 <= 0 and d2 <= 0: return richcmp(self[0], other[0], op) # For different degrees, compare the degree if d1 != d2: return rich_to_bool_sgn(op, d1 - d2) degs = set(self.__coeffs) | set(other.__coeffs) for i in sorted(degs, reverse=True): x = self[i] y = other[i] res = richcmp_item(x, y, op) if res is not NotImplemented: return res return rich_to_bool(op, 0)
def _richcmp_(self, other, op): """ Compare this polynomial with other. Polynomials are first compared by degree, then in dictionary order starting with the coefficient of largest degree. EXAMPLES:: sage: R.<x> = PolynomialRing(ZZ, sparse=True) sage: 3*x^100 - 12 > 12*x + 5 True sage: 3*x^100 - 12 > 3*x^100 - x^50 + 5 True sage: 3*x^100 - 12 < 3*x^100 - x^50 + 5 False sage: x^100 + x^10 - 1 < x^100 + x^10 True sage: x^100 < x^100 - x^10 False TESTS:: sage: R.<x> = PolynomialRing(QQ, sparse=True) sage: 2*x^2^500 > x^2^500 True sage: Rd = PolynomialRing(ZZ, 'x', sparse=False) sage: Rs = PolynomialRing(ZZ, 'x', sparse=True) sage: for _ in range(100): ....: pd = Rd.random_element() ....: qd = Rd.random_element() ....: assert bool(pd < qd) == bool(Rs(pd) < Rs(qd)) """ d1 = self.degree() d2 = other.degree() # Special case constant polynomials if d1 <= 0 and d2 <= 0: return richcmp(self[0], other[0], op) # For different degrees, compare the degree if d1 != d2: return rich_to_bool_sgn(op, d1 - d2) degs = set(self.__coeffs) | set(other.__coeffs) for i in sorted(degs, reverse=True): x = self[i] y = other[i] res = richcmp_item(x, y, op) if res is not NotImplemented: return res return rich_to_bool(op, 0)
def _richcmp_(self, other, op): r""" EXAMPLES:: sage: R.<x,y> = QQ[] sage: V, fr, to = R.free_module(R) sage: fr == loads(dumps(fr)) True """ if isinstance(other, BaseIsomorphism1D): return richcmp(self._basis, other._basis, op) else: return rich_to_bool(op, 1)
def _richcmp_(self, other, op): r""" EXAMPLES:: sage: mobj1 = mathics([x^2-1, 2]) # optional - mathics sage: mobj2 = mathics('{x^2-1, 2}') # optional - mathics sage: mobj3 = mathics('5*x + y') # optional - mathics sage: mobj1 == mobj2 # optional - mathics True sage: mobj1 < mobj2 # optional - mathics False sage: mobj1 == mobj3 # optional - mathics False """ P = self.parent() if str(P("%s < %s"%(self.name(), other.name()))) == P._true_symbol(): return rich_to_bool(op, -1) elif str(P("%s > %s"%(self.name(), other.name()))) == P._true_symbol(): return rich_to_bool(op, 1) elif str(P("%s == %s"%(self.name(), other.name()))) == P._true_symbol(): return rich_to_bool(op, 0) return NotImplemented
def _richcmp_(self, other, op): r""" Compare this element and ``other``. EXAMPLES:: sage: from pyeantic import RealEmbeddedNumberField sage: K = NumberField(x**2 - 2, 'a', embedding=sqrt(AA(2))) sage: K = RealEmbeddedNumberField(K) sage: K.gen() > 0 True sage: K.gen() < 1 False """ from sage.structure.richcmp import rich_to_bool if self.renf_elem < other.renf_elem: return rich_to_bool(op, -1) elif self.renf_elem == other.renf_elem: return rich_to_bool(op, 0) else: return rich_to_bool(op, 1)
def __richcmp__(self, right, op): r""" Try to compare ``self`` and ``right``. .. NOTE:: Comparison is basically not implemented, or rather it could say sets are not equal even though they are. I don't know how one could implement this for a generic intersection of sets in a meaningful manner. So be careful when using this. EXAMPLES:: sage: Y = Set(ZZ).difference(Set(QQ)) sage: Y == Set([]) False sage: X = Set(QQ).difference(Set(ZZ)) sage: Y == X False sage: Z = X.difference(Set(ZZ)) sage: Z == X False This illustrates that equality testing for formal unions can be misleading in general. :: sage: X == Set(QQ).difference(Set(ZZ)) True """ if not isinstance(right, Set_generic): return rich_to_bool(op, -1) if not isinstance(right, Set_object_difference): return rich_to_bool(op, -1) if self._X == right._X and self._Y == right._Y: return rich_to_bool(op, 0) return rich_to_bool(op, -1)
def __richcmp__(self, right, op): r""" Try to compare ``self`` and ``right``. .. NOTE:: Comparison is basically not implemented, or rather it could say sets are not equal even though they are. I don't know how one could implement this for a generic intersection of sets in a meaningful manner. So be careful when using this. EXAMPLES:: sage: Y = Set(ZZ).difference(Set(QQ)) sage: Y == Set([]) False sage: X = Set(QQ).difference(Set(ZZ)) sage: Y == X False sage: Z = X.difference(Set(ZZ)) sage: Z == X False This illustrates that equality testing for formal unions can be misleading in general. :: sage: X == Set(QQ).difference(Set(ZZ)) True """ if not isinstance(right, Set_generic): return rich_to_bool(op, -1) if not isinstance(right, Set_object_difference): return rich_to_bool(op, -1) if self._X == right._X and self._Y == right._Y: return rich_to_bool(op, 0) return rich_to_bool(op, -1)
def _richcmp_(self, other, op): """ EXAMPLES:: sage: R.<x,y> = QQ[]; S.<a,b> = R.quo(x^2 + y^2); type(a) <class 'sage.rings.quotient_ring.QuotientRing_generic_with_category.element_class'> sage: a > b # indirect doctest True sage: b > a False sage: a == loads(dumps(a)) True TESTS:: sage: a == (a+1-1) True sage: a > b True See :trac:`7797`:: sage: F.<x,y,z> = FreeAlgebra(QQ, implementation='letterplace') sage: I = F*[x*y+y*z,x^2+x*y-y*x-y^2]*F sage: Q = F.quo(I) sage: Q.0^4 # indirect doctest ybar*zbar*zbar*xbar + ybar*zbar*zbar*ybar + ybar*zbar*zbar*zbar The issue from :trac:`8005` was most likely fixed as part of :trac:`9138`:: sage: F = GF(5) sage: R.<x,y>=F[] sage: I=Ideal(R, [x, y]) sage: S.<x1,y1>=QuotientRing(R,I) sage: x1^4 0 """ # A containment test is not implemented for univariate polynomial # ideals. There are cases in which one would not like to add # elements of different degrees. The whole quotient stuff relies # in I.reduce(x) returning a normal form of x with respect to I. # Hence, we will not use more than that. # Since we have to compute normal forms anyway, it makes sense # to use it for comparison in the case of an inequality as well. if self.__rep == other.__rep: # Use a shortpath, so that we # avoid expensive reductions return rich_to_bool(op, 0) I = self.parent().defining_ideal() return richcmp(I.reduce(self.__rep), I.reduce(other.__rep), op)
def _richcmp_(self, other, op): """ EXAMPLES:: sage: R.<x,y> = QQ[]; S.<a,b> = R.quo(x^2 + y^2); type(a) <class 'sage.rings.quotient_ring.QuotientRing_generic_with_category.element_class'> sage: a > b # indirect doctest True sage: b > a False sage: a == loads(dumps(a)) True TESTS:: sage: a == (a+1-1) True sage: a > b True See :trac:`7797`:: sage: F.<x,y,z> = FreeAlgebra(QQ, implementation='letterplace') sage: I = F*[x*y+y*z,x^2+x*y-y*x-y^2]*F sage: Q = F.quo(I) sage: Q.0^4 # indirect doctest ybar*zbar*zbar*xbar + ybar*zbar*zbar*ybar + ybar*zbar*zbar*zbar The issue from :trac:`8005` was most likely fixed as part of :trac:`9138`:: sage: F = GF(5) sage: R.<x,y>=F[] sage: I=Ideal(R, [x, y]) sage: S.<x1,y1>=QuotientRing(R,I) sage: x1^4 0 """ # A containment test is not implemented for univariate polynomial # ideals. There are cases in which one would not like to add # elements of different degrees. The whole quotient stuff relies # in I.reduce(x) returning a normal form of x with respect to I. # Hence, we will not use more than that. #return cmp(self.__rep, other.__rep) # Since we have to compute normal forms anyway, it makes sense # to use it for comparison in the case of an inequality as well. if self.__rep == other.__rep: # Use a shortpath, so that we # avoid expensive reductions return rich_to_bool(op, 0) I = self.parent().defining_ideal() return richcmp(I.reduce(self.__rep), I.reduce(other.__rep), op)
def _richcmp_(self, other, op): r""" Comparison (using the complex embedding). TESTS:: sage: UCF = UniversalCyclotomicField() sage: l = [UCF.gen(3), UCF.gen(3)+1, UCF.gen(5), UCF.gen(5,2), ....: UCF.gen(4), 2*UCF.gen(4), UCF.gen(5)-22/3] sage: lQQbar = list(map(QQbar,l)) sage: lQQbar.sort() sage: l.sort() sage: lQQbar == list(map(QQbar,l)) True sage: for i in range(len(l)): ....: assert l[i] >= l[i] and l[i] <= l[i] ....: for j in range(i): ....: assert l[i] > l[j] and l[j] < l[i] sage: fibonacci(200)*(E(5)+E(5,4)) <= fibonacci(199) True sage: fibonacci(201)*(E(5)+E(5,4)) <= fibonacci(200) False """ if self._obj == other._obj: return rich_to_bool(op, 0) s = self.real_part() o = other.real_part() if s == o: s = self.imag_part() o = other.imag_part() from sage.rings.real_mpfi import RealIntervalField prec = 53 R = RealIntervalField(prec) sa = s._eval_real_(R) oa = o._eval_real_(R) while sa.overlaps(oa): prec <<= 2 R = RealIntervalField(prec) sa = s._eval_real_(R) oa = o._eval_real_(R) return sa._richcmp_(oa, op)
def _richcmp_(self, other, op): r""" Comparison (using the complex embedding). TESTS:: sage: UCF = UniversalCyclotomicField() sage: l = [UCF.gen(3), UCF.gen(3)+1, UCF.gen(5), UCF.gen(5,2), ....: UCF.gen(4), 2*UCF.gen(4), UCF.gen(5)-22/3] sage: lQQbar = list(map(QQbar,l)) sage: lQQbar.sort() sage: l.sort() sage: lQQbar == list(map(QQbar,l)) True sage: for i in range(len(l)): ....: assert l[i] >= l[i] and l[i] <= l[i] ....: for j in range(i): ....: assert l[i] > l[j] and l[j] < l[i] sage: fibonacci(200)*(E(5)+E(5,4)) <= fibonacci(199) True sage: fibonacci(201)*(E(5)+E(5,4)) <= fibonacci(200) False """ if self._obj == other._obj: return rich_to_bool(op, 0) s = self.real_part() o = other.real_part() if s == o: s = self.imag_part() o = other.imag_part() from sage.rings.real_mpfi import RealIntervalField prec = 53 R = RealIntervalField(prec) sa = s._eval_real_(R) oa = o._eval_real_(R) while sa.overlaps(oa): prec <<= 2 R = RealIntervalField(prec) sa = s._eval_real_(R) oa = o._eval_real_(R) return sa._richcmp_(oa, op)
def _richcmp_(self, right, op): """ Compare ``self`` and ``right``. INPUT: - ``self, right`` -- elements of the same finite abelian variety subgroup. - ``op`` -- comparison operator (see :mod:`sage.structure.richcmp`) OUTPUT: boolean EXAMPLES:: sage: J = J0(11); G = J.finite_subgroup([[1/3,0], [0,1/5]]) sage: G.0 > G.1 True sage: G.0 == G.0 True sage: 3*G.0 == 0 True sage: 3*G.0 == 5*G.1 True We make sure things that should not be equal are not:: sage: H = J0(14).finite_subgroup([[1/3,0]]) sage: G.0 == H.0 False sage: G.0 [(1/3, 0)] sage: H.0 [(1/3, 0)] """ A = self.parent().abelian_variety() from sage.rings.rational_field import QQ if self.__element.change_ring(QQ) - right.__element.change_ring( QQ) in A.lattice(): return rich_to_bool(op, 0) return richcmp(self.__element, right.__element, op)
def _richcmp_(self, right, op): """ Compare ``self`` and ``right``. INPUT: - ``self, right`` -- elements of the same finite abelian variety subgroup. - ``op`` -- comparison operator (see :mod:`sage.structure.richcmp`) OUTPUT: boolean EXAMPLES:: sage: J = J0(11); G = J.finite_subgroup([[1/3,0], [0,1/5]]) sage: G.0 > G.1 True sage: G.0 == G.0 True sage: 3*G.0 == 0 True sage: 3*G.0 == 5*G.1 True We make sure things that should not be equal are not:: sage: H = J0(14).finite_subgroup([[1/3,0]]) sage: G.0 == H.0 False sage: G.0 [(1/3, 0)] sage: H.0 [(1/3, 0)] """ A = self.parent().abelian_variety() from sage.rings.all import QQ if self.__element.change_ring(QQ) - right.__element.change_ring(QQ) in A.lattice(): return rich_to_bool(op, 0) return richcmp(self.__element, right.__element, op)
def _richcmp_(self, other, op): r""" Comparison. For ``self`` and ``other`` that have the same parent the method compares their rank. TESTS:: sage: A = TotallyOrderedFiniteSet([3,2,7], facade=False) sage: A(3) < A(2) and A(3) <= A(2) and A(2) <= A(2) True sage: A(2) > A(3) and A(2) >= A(3) and A(7) >= A(7) True sage: A(3) >= A(7) or A(2) > A(2) False sage: A(7) < A(2) or A(2) <= A(3) or A(2) < A(2) False """ if self.value == other.value: return rich_to_bool(op, 0) return richcmp(self.rank(), other.rank(), op)
def _richcmp_(self, other, op): r""" Comparison. For ``self`` and ``other`` that have the same parent the method compares their rank. TESTS:: sage: A = TotallyOrderedFiniteSet([3,2,7], facade=False) sage: A(3) < A(2) and A(3) <= A(2) and A(2) <= A(2) True sage: A(2) > A(3) and A(2) >= A(3) and A(7) >= A(7) True sage: A(3) >= A(7) or A(2) > A(2) False sage: A(7) < A(2) or A(2) <= A(3) or A(2) < A(2) False """ if self.value == other.value: return rich_to_bool(op, 0) return richcmp(self.rank(), other.rank(), op)
def _richcmp_(self, other, op): """ Compares the generators of two ideals. INPUT: - ``other`` -- an ideal OUTPUT: boolean EXAMPLES:: sage: R = ZZ; I = ZZ*2; J = ZZ*(-2) sage: I == J True """ S = set(self.gens()) T = set(other.gens()) if S == T: return rich_to_bool(op, 0) return richcmp(self.gens(), other.gens(), op)
def _richcmp_(self, other, op): """ Compares the generators of two ideals. INPUT: - ``other`` -- an ideal OUTPUT: boolean EXAMPLES:: sage: R = ZZ; I = ZZ*2; J = ZZ*(-2) sage: I == J True """ S = set(self.gens()) T = set(other.gens()) if S == T: return rich_to_bool(op, 0) return richcmp(self.gens(), other.gens(), op)
def __richcmp__(self, other, op): """ Implement rich comparison. We treat two matrix groups as equal if their generators are the same in the same order. Infinitely-generated groups are compared by identity. INPUT: - ``other`` -- anything - ``op`` -- comparison operator OUTPUT: boolean EXAMPLES:: sage: G = GL(2,3) sage: H = MatrixGroup(G.gens()) sage: H == G True sage: G == H True sage: MS = MatrixSpace(QQ, 2, 2) sage: G = MatrixGroup([MS(1), MS([1,2,3,4])]) sage: G == G True sage: G == MatrixGroup(G.gens()) True TESTS:: sage: G = groups.matrix.GL(4,2) sage: H = MatrixGroup(G.gens()) sage: G == H True sage: G != H False """ if not is_MatrixGroup(other): return NotImplemented if self is other: return rich_to_bool(op, 0) lx = self.matrix_space() rx = other.matrix_space() if lx != rx: return richcmp_not_equal(lx, rx, op) # compare number of generators try: n_self = self.ngens() n_other = other.ngens() except (AttributeError, NotImplementedError): return richcmp(id(self), id(other), op) if n_self != n_other: return richcmp_not_equal(self, other, op) from sage.structure.element import is_InfinityElement if is_InfinityElement(n_self) or is_InfinityElement(n_other): return richcmp(id(self), id(other), op) # compact generator matrices try: self_gens = self.gens() other_gens = other.gens() except (AttributeError, NotImplementedError): return richcmp(id(self), id(other), op) assert(n_self == n_other) for g, h in zip(self_gens, other_gens): lx = g.matrix() rx = h.matrix() if lx != rx: return richcmp_not_equal(lx, rx, op) return rich_to_bool(op, 0)
def _richcmp_(self, other, op): """ Compare equality between self and other, using maple. These examples are optional, and require Maple to be installed. You don't need to install any Sage packages for this. EXAMPLES:: sage: a = maple(5) # optional - maple sage: b = maple(5) # optional - maple sage: a == b # optional - maple True sage: a == 5 # optional - maple True :: sage: c = maple(3) # optional - maple sage: a == c # optional - maple False sage: a < c # optional - maple False sage: a < 6 # optional - maple True sage: c <= a # optional - maple True :: sage: M = matrix(ZZ, 2, range(1,5)) # optional - maple sage: Mm = maple(M) # optional - maple sage: Mm == Mm # optional - maple True TESTS:: sage: x = var('x') sage: t = maple((x+1)^2) # optional - maple sage: u = maple(x^2+2*x+1) # optional - maple sage: u == t # todo: not implemented True # returns False, should use 'testeq' in maple sage: maple.eval('testeq(%s = %s)' % (t.name(),u.name())) # optional - maple 'true' """ P = self.parent() if P.eval("evalb(%s %s %s)" % (self.name(), P._equality_symbol(), other.name())) == P._true_symbol(): return rich_to_bool(op, 0) # Maple does not allow comparing objects of different types and # it raises an error in this case. # We catch the error, and return True for < try: if P.eval("evalb(%s %s %s)" % (self.name(), P._lessthan_symbol(), other.name())) == P._true_symbol(): return rich_to_bool(op, -1) except RuntimeError as e: msg = str(e) if 'is not valid' in msg and 'to < or <=' in msg: if (hash(str(self)) < hash(str(other))): return rich_to_bool(op, -1) else: return rich_to_bool(op, 1) else: raise RuntimeError(e) if P.eval("evalb(%s %s %s)" % (self.name(), P._greaterthan_symbol(), other.name())) == P._true_symbol(): return rich_to_bool(op, 1) return NotImplemented
def _richcmp_(self, other, op): r""" Comparisons TESTS:: sage: F = FreeMonoid(index_set=ZZ) sage: a,b,c,d,e = [F.gen(i) for i in range(5)] sage: a == a True sage: a*e == a*e True sage: a*b*c^3*b*d == (a*b*c)*(c^2*b*d) True sage: a != b True sage: a*b != b*a True sage: a*b*c^3*b*d != (a*b*c)*(c^2*b*d) False sage: F = FreeMonoid(index_set=ZZ) sage: a,b,c,d,e = [F.gen(i) for i in range(5)] sage: a < b True sage: a*b < b*a True sage: a*b < a*a False sage: a^2*b < a*b*b True sage: b > a True sage: a*b > b*a False sage: a*b > a*a True sage: a*b <= b*a True sage: a*b <= b*a True sage: FA = FreeAbelianMonoid(index_set=ZZ) sage: a,b,c,d,e = [FA.gen(i) for i in range(5)] sage: a == a True sage: a*e == e*a True sage: a*b*c^3*b*d == a*d*(b^2*c^2)*c True sage: a != b True sage: a*b != a*a True sage: a*b*c^3*b*d != a*d*(b^2*c^2)*c False """ if self._monomial == other._monomial: # Equal return rich_to_bool(op, 0) if op == op_EQ or op == op_NE: # Not equal return rich_to_bool(op, 1) return richcmp(self.to_word_list(), other.to_word_list(), op)
def _richcmp_(self, other, op): r""" Comparisons TESTS:: sage: F = FreeMonoid(index_set=ZZ) sage: a,b,c,d,e = [F.gen(i) for i in range(5)] sage: a == a True sage: a*e == a*e True sage: a*b*c^3*b*d == (a*b*c)*(c^2*b*d) True sage: a != b True sage: a*b != b*a True sage: a*b*c^3*b*d != (a*b*c)*(c^2*b*d) False sage: F = FreeMonoid(index_set=ZZ) sage: a,b,c,d,e = [F.gen(i) for i in range(5)] sage: a < b True sage: a*b < b*a True sage: a*b < a*a False sage: a^2*b < a*b*b True sage: b > a True sage: a*b > b*a False sage: a*b > a*a True sage: a*b <= b*a True sage: a*b <= b*a True sage: FA = FreeAbelianMonoid(index_set=ZZ) sage: a,b,c,d,e = [FA.gen(i) for i in range(5)] sage: a == a True sage: a*e == e*a True sage: a*b*c^3*b*d == a*d*(b^2*c^2)*c True sage: a != b True sage: a*b != a*a True sage: a*b*c^3*b*d != a*d*(b^2*c^2)*c False """ if self._monomial == other._monomial: # Equal return rich_to_bool(op, 0) if op == op_EQ or op == op_NE: # Not equal return rich_to_bool(op, 1) return richcmp(self.to_word_list(), other.to_word_list(), op)
def __richcmp__(self, other, op): r""" The order is given by the natural: self < other iff adherance(self) c adherance(other) TESTS:: sage: a = AbelianStratum(1,3) sage: b = AbelianStratum(3,1) sage: c = AbelianStratum(1,3,marked_separatrix='out') sage: d = AbelianStratum(3,1,marked_separatrix='out') sage: e = AbelianStratum(1,3,marked_separatrix='in') sage: f = AbelianStratum(3,1,marked_separatrix='in') sage: a == b # no difference for unmarked True sage: c == d # difference for out mark False sage: e == f # difference for in mark False sage: a == c # difference between no mark and out mark False sage: a == e # difference between no mark and in mark False sage: c == e # difference between out mark adn in mark False sage: a == False Traceback (most recent call last): ... TypeError: the right member must be a stratum sage: a != b # no difference for unmarked False sage: c != d # difference for out mark True sage: e != f # difference for in mark True sage: a != c # difference between no mark and out mark True sage: a != e # difference between no mark and in mark True sage: c != e # difference between out mark adn in mark True sage: a != False Traceback (most recent call last): ... TypeError: the right member must be a stratum sage: a3 = AbelianStratum(3,2,1) sage: a3_out = AbelianStratum(3,2,1,marked_separatrix='out') sage: a3_in = AbelianStratum(3,2,1,marked_separatrix='in') sage: a3 == a3_out False sage: a3 == a3_in False sage: a3_out == a3_in False """ if type(self) is not type(other): raise TypeError("the right member must be a stratum") if op == op_EQ or op == op_NE: z_eq = self._zeroes == other._zeroes ms_eq = self._marked_separatrix == other._marked_separatrix return (z_eq and ms_eq) == (op == op_EQ) if self._marked_separatrix != other._marked_separatrix: raise TypeError("the other must be a stratum with same marking") if self._zeroes < other._zeroes: return rich_to_bool(op, 1) elif self._zeroes > other._zeroes: return rich_to_bool(op, -1) return rich_to_bool(op, 0)