Skip to content

Commit 04a860b

Browse files
committed
refresh the doc about coercion and test the given example
1 parent b002b63 commit 04a860b

File tree

1 file changed

+92
-82
lines changed

1 file changed

+92
-82
lines changed

src/doc/en/reference/coercion/index.rst

Lines changed: 92 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -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

463472
That'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

@@ -502,7 +512,7 @@ That's all there is to it. Now we can test it out:
502512
sage: cm = sage.structure.element.get_coercion_model()
503513
sage: cm.explain(R, ZZ, operator.add)
504514
Coercion on right operand via
505-
Conversion map:
515+
Coercion map:
506516
From: Integer Ring
507517
To: Integer Ring localized at [2]
508518
Arithmetic performed after coercions.
@@ -515,7 +525,7 @@ That's all there is to it. Now we can test it out:
515525
Result lives in Integer Ring localized at [2]
516526
Integer Ring localized at [2]
517527

518-
sage: R6 = Localization([2,3]); R6
528+
sage: R6 = MyLocalization([2,3]); R6
519529
Integer Ring localized at [2, 3]
520530
sage: R6(1/3) - R(1/2)
521531
LocalElt(-1/6)
@@ -525,12 +535,12 @@ That's all there is to it. Now we can test it out:
525535
sage: R.has_coerce_map_from(ZZ)
526536
True
527537
sage: R.coerce_map_from(ZZ)
528-
Conversion map:
538+
Coercion map:
529539
From: Integer Ring
530540
To: Integer Ring localized at [2]
531541

532542
sage: R6.coerce_map_from(R)
533-
Conversion map:
543+
Coercion map:
534544
From: Integer Ring localized at [2]
535545
To: Integer Ring localized at [2, 3]
536546

@@ -539,7 +549,7 @@ That's all there is to it. Now we can test it out:
539549

540550
sage: cm.explain(R, R6, operator.mul)
541551
Coercion on left operand via
542-
Conversion map:
552+
Coercion map:
543553
From: Integer Ring localized at [2]
544554
To: Integer Ring localized at [2, 3]
545555
Arithmetic performed after coercions.

0 commit comments

Comments
 (0)