@@ -386,87 +386,97 @@ but that would obscure the main points being made here.)
386
386
387
387
::
388
388
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
462
471
463
472
That's all there is to it. Now we can test it out:
464
473
465
- .. skip
474
+ .. link
466
475
467
476
::
468
477
469
- sage: R = Localization([2]); R
478
+ sage: TestSuite(R).run(skip="_test_pickling")
479
+ sage: R = MyLocalization([2]); R
470
480
Integer Ring localized at [2]
471
481
sage: R(1)
472
482
LocalElt(1)
@@ -475,12 +485,12 @@ That's all there is to it. Now we can test it out:
475
485
sage: R(1/3)
476
486
Traceback (most recent call last):
477
487
...
478
- ValueError: Not integral at 3
488
+ ValueError: not integral at 3
479
489
480
490
sage: R.coerce(1)
481
491
LocalElt(1)
482
492
sage: R.coerce(1/4)
483
- Traceback (click to the left for traceback)
493
+ Traceback (most recent call last):
484
494
...
485
495
TypeError: no canonical coercion from Rational Field to Integer Ring localized at [2]
486
496
@@ -497,25 +507,26 @@ That's all there is to it. Now we can test it out:
497
507
sage: R(3/4) * 7
498
508
LocalElt(21/4)
499
509
500
- sage: R.get_action(ZZ)
501
- Right scalar multiplication by Integer Ring on Integer Ring localized at [2]
502
510
sage: cm = sage.structure.element.get_coercion_model()
503
511
sage: cm.explain(R, ZZ, operator.add)
504
512
Coercion on right operand via
505
- Conversion map:
513
+ Coercion map:
506
514
From: Integer Ring
507
515
To: Integer Ring localized at [2]
508
516
Arithmetic performed after coercions.
509
517
Result lives in Integer Ring localized at [2]
510
518
Integer Ring localized at [2]
511
519
512
520
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.
515
526
Result lives in Integer Ring localized at [2]
516
527
Integer Ring localized at [2]
517
528
518
- sage: R6 = Localization ([2,3]); R6
529
+ sage: R6 = MyLocalization ([2,3]); R6
519
530
Integer Ring localized at [2, 3]
520
531
sage: R6(1/3) - R(1/2)
521
532
LocalElt(-1/6)
@@ -525,12 +536,12 @@ That's all there is to it. Now we can test it out:
525
536
sage: R.has_coerce_map_from(ZZ)
526
537
True
527
538
sage: R.coerce_map_from(ZZ)
528
- Conversion map:
539
+ Coercion map:
529
540
From: Integer Ring
530
541
To: Integer Ring localized at [2]
531
542
532
543
sage: R6.coerce_map_from(R)
533
- Conversion map:
544
+ Coercion map:
534
545
From: Integer Ring localized at [2]
535
546
To: Integer Ring localized at [2, 3]
536
547
@@ -539,7 +550,7 @@ That's all there is to it. Now we can test it out:
539
550
540
551
sage: cm.explain(R, R6, operator.mul)
541
552
Coercion on left operand via
542
- Conversion map:
553
+ Coercion map:
543
554
From: Integer Ring localized at [2]
544
555
To: Integer Ring localized at [2, 3]
545
556
Arithmetic performed after coercions.
0 commit comments