Skip to content

Commit 5eb7aae

Browse files
author
Release Manager
committed
gh-36919: refresh the doc about coercion and test the given example There is one example of ring in the doc about coercion. Currently not tested and very much using old-style. So let's refresh it and test it. ### 📝 Checklist - [x] The title is concise, informative, and self-explanatory. - [x] The description explains in detail what this PR is about. - [ ] I have linked a relevant issue or discussion. - [x] I have created tests covering the changes. - [x] I have updated the documentation accordingly. URL: #36919 Reported by: Frédéric Chapoton Reviewer(s): Ruchit Jagodara
2 parents 829da8c + 457a121 commit 5eb7aae

File tree

1 file changed

+97
-86
lines changed

1 file changed

+97
-86
lines changed

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

Lines changed: 97 additions & 86 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

@@ -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

Comments
 (0)