@@ -386,87 +386,97 @@ but that would obscure the main points being made here.)
386386
387387::
388388
389- class Localization(Ring):
390- def __init__(self, primes):
391- """
392- Localization of `\ZZ` away from primes.
393- """
394- Ring.__init__(self, base=ZZ)
395- self._primes = primes
396- self._populate_coercion_lists_()
397-
398- def _repr_(self):
399- """
400- How to print self.
401- """
402- return "%s localized at %s" % (self.base(), self._primes)
403-
404- def _element_constructor_(self, x):
405- """
406- Make sure x is a valid member of self, and return the constructed element.
407- """
408- if isinstance(x, LocalizationElement):
409- x = x._value
410- else:
411- x = QQ(x)
412- for p, e in x.denominator().factor():
413- if p not in self._primes:
414- raise ValueError("Not integral at %s" % p)
415- return LocalizationElement(self, x)
416-
417- def _coerce_map_from_(self, S):
418- """
419- The only things that coerce into this ring are:
420-
421- - the integer ring
422-
423- - other localizations away from fewer primes
424- """
425- if S is ZZ:
426- return True
427- elif isinstance(S, Localization):
428- return all(p in self._primes for p in S._primes)
429-
430-
431- class LocalizationElement(RingElement):
432-
433- def __init__(self, parent, x):
434- RingElement.__init__(self, parent)
435- self._value = x
436-
437-
438- # We're just printing out this way to make it easy to see what's going on in the examples.
439-
440- def _repr_(self):
441- return "LocalElt(%s)" % self._value
442-
443- # Now define addition, subtraction, and multiplication of elements.
444- # Note that left and right always have the same parent.
445-
446- def _add_(left, right):
447- return LocalizationElement(left.parent(), left._value + right._value)
448-
449- def _sub_(left, right):
450- return LocalizationElement(left.parent(), left._value - right._value)
451-
452- def _mul_(left, right):
453- return LocalizationElement(left.parent(), left._value * right._value)
454-
455- # The basering was set to ZZ, so c is guaranteed to be in ZZ
456-
457- def _rmul_(self, c):
458- return LocalizationElement(self.parent(), c * self._value)
459-
460- def _lmul_(self, c):
461- return LocalizationElement(self.parent(), self._value * c)
389+ sage: from sage.structure.richcmp import richcmp
390+ sage: from sage.structure.element import Element
391+
392+ sage: class MyLocalization(Parent):
393+ ....: def __init__(self, primes):
394+ ....: r"""
395+ ....: Localization of `\ZZ` away from primes.
396+ ....: """
397+ ....: Parent.__init__(self, base=ZZ, category=Rings().Commutative())
398+ ....: self._primes = primes
399+ ....: self._populate_coercion_lists_()
400+ ....:
401+ ....: def _repr_(self) -> str:
402+ ....: """
403+ ....: How to print ``self``.
404+ ....: """
405+ ....: return "%s localized at %s" % (self.base(), self._primes)
406+ ....:
407+ ....: def _element_constructor_(self, x):
408+ ....: """
409+ ....: Make sure ``x`` is a valid member of ``self``, and return the constructed element.
410+ ....: """
411+ ....: if isinstance(x, MyLocalizationElement):
412+ ....: x = x._value
413+ ....: else:
414+ ....: x = QQ(x)
415+ ....: for p, e in x.denominator().factor():
416+ ....: if p not in self._primes:
417+ ....: raise ValueError("not integral at %s" % p)
418+ ....: return self.element_class(self, x)
419+ ....:
420+ ....: def _an_element_(self):
421+ ....: return self.element_class(self, 6)
422+ ....:
423+ ....: def _coerce_map_from_(self, S):
424+ ....: """
425+ ....: The only things that coerce into this ring are:
426+ ....:
427+ ....: - the integer ring
428+ ....:
429+ ....: - other localizations away from fewer primes
430+ ....: """
431+ ....: if S is ZZ:
432+ ....: return True
433+ ....: if isinstance(S, MyLocalization):
434+ ....: return all(p in self._primes for p in S._primes)
435+
436+ sage: class MyLocalizationElement(Element):
437+ ....:
438+ ....: def __init__(self, parent, x):
439+ ....: Element.__init__(self, parent)
440+ ....: self._value = x
441+ ....:
442+ ....: # We are just printing out this way to make it easy to see what's going on in the examples.
443+ ....:
444+ ....: def _repr_(self) -> str:
445+ ....: return f"LocalElt({self._value})"
446+ ....:
447+ ....: # Now define addition, subtraction and multiplication of elements.
448+ ....: # Note that self and right always have the same parent.
449+ ....:
450+ ....: def _add_(self, right):
451+ ....: return self.parent()(self._value + right._value)
452+ ....:
453+ ....: def _sub_(self, right):
454+ ....: return self.parent()(self._value - right._value)
455+ ....:
456+ ....: def _mul_(self, right):
457+ ....: return self.parent()(self._value * right._value)
458+ ....:
459+ ....: # The basering was set to ZZ, so c is guaranteed to be in ZZ
460+ ....:
461+ ....: def _rmul_(self, c):
462+ ....: return self.parent()(c * self._value)
463+ ....:
464+ ....: def _lmul_(self, c):
465+ ....: return self.parent()(self._value * c)
466+ ....:
467+ ....: def _richcmp_(self, other, op):
468+ ....: return richcmp(self._value, other._value, op)
469+
470+ sage: MyLocalization.element_class = MyLocalizationElement
462471
463472That's all there is to it. Now we can test it out:
464473
465- .. skip
474+ .. link
466475
467476 ::
468477
469- sage: R = Localization([2]); R
478+ sage: TestSuite(R).run(skip="_test_pickling")
479+ sage: R = MyLocalization([2]); R
470480 Integer Ring localized at [2]
471481 sage: R(1)
472482 LocalElt(1)
@@ -475,12 +485,12 @@ That's all there is to it. Now we can test it out:
475485 sage: R(1/3)
476486 Traceback (most recent call last):
477487 ...
478- ValueError: Not integral at 3
488+ ValueError: not integral at 3
479489
480490 sage: R.coerce(1)
481491 LocalElt(1)
482492 sage: R.coerce(1/4)
483- Traceback (click to the left for traceback)
493+ Traceback (most recent call last):
484494 ...
485495 TypeError: no canonical coercion from Rational Field to Integer Ring localized at [2]
486496
@@ -497,25 +507,26 @@ That's all there is to it. Now we can test it out:
497507 sage: R(3/4) * 7
498508 LocalElt(21/4)
499509
500- sage: R.get_action(ZZ)
501- Right scalar multiplication by Integer Ring on Integer Ring localized at [2]
502510 sage: cm = sage.structure.element.get_coercion_model()
503511 sage: cm.explain(R, ZZ, operator.add)
504512 Coercion on right operand via
505- Conversion map:
513+ Coercion map:
506514 From: Integer Ring
507515 To: Integer Ring localized at [2]
508516 Arithmetic performed after coercions.
509517 Result lives in Integer Ring localized at [2]
510518 Integer Ring localized at [2]
511519
512520 sage: cm.explain(R, ZZ, operator.mul)
513- Action discovered.
514- Right scalar multiplication by Integer Ring on Integer Ring localized at [2]
521+ Coercion on right operand via
522+ Coercion map:
523+ From: Integer Ring
524+ To: Integer Ring localized at [2]
525+ Arithmetic performed after coercions.
515526 Result lives in Integer Ring localized at [2]
516527 Integer Ring localized at [2]
517528
518- sage: R6 = Localization ([2,3]); R6
529+ sage: R6 = MyLocalization ([2,3]); R6
519530 Integer Ring localized at [2, 3]
520531 sage: R6(1/3) - R(1/2)
521532 LocalElt(-1/6)
@@ -525,12 +536,12 @@ That's all there is to it. Now we can test it out:
525536 sage: R.has_coerce_map_from(ZZ)
526537 True
527538 sage: R.coerce_map_from(ZZ)
528- Conversion map:
539+ Coercion map:
529540 From: Integer Ring
530541 To: Integer Ring localized at [2]
531542
532543 sage: R6.coerce_map_from(R)
533- Conversion map:
544+ Coercion map:
534545 From: Integer Ring localized at [2]
535546 To: Integer Ring localized at [2, 3]
536547
@@ -539,7 +550,7 @@ That's all there is to it. Now we can test it out:
539550
540551 sage: cm.explain(R, R6, operator.mul)
541552 Coercion on left operand via
542- Conversion map:
553+ Coercion map:
543554 From: Integer Ring localized at [2]
544555 To: Integer Ring localized at [2, 3]
545556 Arithmetic performed after coercions.
0 commit comments