Skip to content

Commit 58e477d

Browse files
author
Release Manager
committed
sagemathgh-38881: using Parent in ring extensions as another step towards using `Parent` everywhere ### 📝 Checklist - [x] The title is concise and informative. - [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. - [ ] I have updated the documentation and checked the documentation preview. Dependencies: sagemath#38821 URL: sagemath#38881 Reported by: Frédéric Chapoton Reviewer(s): Martin Rubey
2 parents c5d6786 + 440ffdb commit 58e477d

File tree

10 files changed

+136
-118
lines changed

10 files changed

+136
-118
lines changed

src/doc/en/thematic_tutorials/coercion_and_categories.rst

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -133,8 +133,6 @@ This base class provides a lot more methods than a general parent::
133133
'is_commutative',
134134
'is_field',
135135
'is_integrally_closed',
136-
'is_prime_field',
137-
'is_subring',
138136
'krull_dimension',
139137
'localization',
140138
'ngens',

src/sage/categories/rings.py

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -436,6 +436,30 @@ def is_noetherian(self):
436436
"""
437437
return False
438438

439+
def is_prime_field(self):
440+
r"""
441+
Return ``True`` if this ring is one of the prime fields `\QQ` or
442+
`\GF{p}`.
443+
444+
EXAMPLES::
445+
446+
sage: QQ.is_prime_field()
447+
True
448+
sage: GF(3).is_prime_field()
449+
True
450+
sage: GF(9, 'a').is_prime_field() # needs sage.rings.finite_rings
451+
False
452+
sage: ZZ.is_prime_field()
453+
False
454+
sage: QQ['x'].is_prime_field()
455+
False
456+
sage: Qp(19).is_prime_field() # needs sage.rings.padics
457+
False
458+
"""
459+
# the case of QQ is handled by QQ itself
460+
from sage.categories.finite_fields import FiniteFields
461+
return self in FiniteFields() and self.degree() == 1
462+
439463
def is_zero(self) -> bool:
440464
"""
441465
Return ``True`` if this is the zero ring.
@@ -459,6 +483,54 @@ def is_zero(self) -> bool:
459483
"""
460484
return self.one() == self.zero()
461485

486+
def is_subring(self, other):
487+
"""
488+
Return ``True`` if the canonical map from ``self`` to ``other`` is
489+
injective.
490+
491+
This raises a :exc:`NotImplementedError` if not known.
492+
493+
EXAMPLES::
494+
495+
sage: ZZ.is_subring(QQ)
496+
True
497+
sage: ZZ.is_subring(GF(19))
498+
False
499+
500+
TESTS::
501+
502+
sage: QQ.is_subring(QQ['x'])
503+
True
504+
sage: QQ.is_subring(GF(7))
505+
False
506+
sage: QQ.is_subring(CyclotomicField(7)) # needs sage.rings.number_field
507+
True
508+
sage: QQ.is_subring(ZZ)
509+
False
510+
511+
Every ring is a subring of itself, :issue:`17287`::
512+
513+
sage: QQbar.is_subring(QQbar) # needs sage.rings.number_field
514+
True
515+
sage: RR.is_subring(RR)
516+
True
517+
sage: CC.is_subring(CC) # needs sage.rings.real_mpfr
518+
True
519+
sage: x = polygen(ZZ, 'x')
520+
sage: K.<a> = NumberField(x^3 - x + 1/10) # needs sage.rings.number_field
521+
sage: K.is_subring(K) # needs sage.rings.number_field
522+
True
523+
sage: R.<x> = RR[]
524+
sage: R.is_subring(R)
525+
True
526+
"""
527+
if self is other:
528+
return True
529+
try:
530+
return self.Hom(other).natural_map().is_injective()
531+
except (TypeError, AttributeError):
532+
return False
533+
462534
def bracket(self, x, y):
463535
"""
464536
Return the Lie bracket `[x, y] = x y - y x` of `x` and `y`.

src/sage/rings/morphism.pyx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2879,8 +2879,10 @@ cdef class FrobeniusEndomorphism_generic(RingHomomorphism):
28792879
over Finite Field of size 5
28802880
"""
28812881
from sage.rings.ring import CommutativeRing
2882+
from sage.categories.commutative_rings import CommutativeRings
28822883
from sage.categories.homset import Hom
2883-
if not isinstance(domain, CommutativeRing):
2884+
if not (domain in CommutativeRings() or
2885+
isinstance(domain, CommutativeRing)): # TODO: remove this line
28842886
raise TypeError("The base ring must be a commutative ring")
28852887
self._p = domain.characteristic()
28862888
if not self._p.is_prime():

src/sage/rings/number_field/order.py

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,9 @@
7777
# https://www.gnu.org/licenses/
7878
# ****************************************************************************
7979

80+
from sage.categories.integral_domains import IntegralDomains
8081
from sage.misc.cachefunc import cached_method
81-
from sage.rings.ring import IntegralDomain
82+
from sage.structure.parent import Parent
8283
from sage.structure.sequence import Sequence
8384
from sage.rings.integer_ring import ZZ
8485
import sage.rings.abc
@@ -426,7 +427,7 @@ def EquationOrder(f, names, **kwds):
426427
return K.order(K.gens())
427428

428429

429-
class Order(IntegralDomain, sage.rings.abc.Order):
430+
class Order(Parent, sage.rings.abc.Order):
430431
r"""
431432
An order in a number field.
432433
@@ -478,8 +479,8 @@ def __init__(self, K):
478479
0.0535229072603327 + 1.20934552493846*I
479480
"""
480481
self._K = K
481-
IntegralDomain.__init__(self, ZZ, names=K.variable_names(),
482-
normalize=False)
482+
Parent.__init__(self, base=ZZ, names=K.variable_names(),
483+
normalize=False, category=IntegralDomains())
483484
self._populate_coercion_lists_(embedding=self.number_field())
484485
if self.absolute_degree() == 2:
485486
self.is_maximal() # cache
@@ -665,7 +666,7 @@ def krull_dimension(self):
665666
sage: O2.krull_dimension()
666667
1
667668
"""
668-
return ZZ(1)
669+
return ZZ.one()
669670

670671
def integral_closure(self):
671672
r"""
@@ -733,6 +734,20 @@ def ngens(self):
733734
"""
734735
return self.absolute_degree()
735736

737+
def gens(self) -> tuple:
738+
"""
739+
Return the generators as a tuple.
740+
741+
EXAMPLES::
742+
743+
sage: x = polygen(ZZ, 'x')
744+
sage: K.<a> = NumberField(x^3 + x^2 - 2*x + 8)
745+
sage: O = K.maximal_order()
746+
sage: O.gens()
747+
(1, 1/2*a^2 + 1/2*a, a^2)
748+
"""
749+
return tuple(self.gen(i) for i in range(self.absolute_degree()))
750+
736751
def basis(self): # this must be defined in derived class
737752
r"""
738753
Return a basis over `\ZZ` of this order.

src/sage/rings/ring.pyx

Lines changed: 0 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -543,76 +543,6 @@ cdef class Ring(ParentWithGens):
543543
"""
544544
return True
545545

546-
def is_subring(self, other):
547-
"""
548-
Return ``True`` if the canonical map from ``self`` to ``other`` is
549-
injective.
550-
551-
Raises a :exc:`NotImplementedError` if not known.
552-
553-
EXAMPLES::
554-
555-
sage: ZZ.is_subring(QQ)
556-
True
557-
sage: ZZ.is_subring(GF(19))
558-
False
559-
560-
TESTS::
561-
562-
sage: QQ.is_subring(QQ['x'])
563-
True
564-
sage: QQ.is_subring(GF(7))
565-
False
566-
sage: QQ.is_subring(CyclotomicField(7)) # needs sage.rings.number_field
567-
True
568-
sage: QQ.is_subring(ZZ)
569-
False
570-
571-
Every ring is a subring of itself, :issue:`17287`::
572-
573-
sage: QQbar.is_subring(QQbar) # needs sage.rings.number_field
574-
True
575-
sage: RR.is_subring(RR)
576-
True
577-
sage: CC.is_subring(CC) # needs sage.rings.real_mpfr
578-
True
579-
sage: x = polygen(ZZ, 'x')
580-
sage: K.<a> = NumberField(x^3 - x + 1/10) # needs sage.rings.number_field
581-
sage: K.is_subring(K) # needs sage.rings.number_field
582-
True
583-
sage: R.<x> = RR[]
584-
sage: R.is_subring(R)
585-
True
586-
"""
587-
if self is other:
588-
return True
589-
try:
590-
return self.Hom(other).natural_map().is_injective()
591-
except (TypeError, AttributeError):
592-
return False
593-
594-
def is_prime_field(self):
595-
r"""
596-
Return ``True`` if this ring is one of the prime fields `\QQ` or
597-
`\GF{p}`.
598-
599-
EXAMPLES::
600-
601-
sage: QQ.is_prime_field()
602-
True
603-
sage: GF(3).is_prime_field()
604-
True
605-
sage: GF(9, 'a').is_prime_field() # needs sage.rings.finite_rings
606-
False
607-
sage: ZZ.is_prime_field()
608-
False
609-
sage: QQ['x'].is_prime_field()
610-
False
611-
sage: Qp(19).is_prime_field() # needs sage.rings.padics
612-
False
613-
"""
614-
return False
615-
616546
def order(self):
617547
"""
618548
The number of elements of ``self``.

src/sage/rings/ring_extension.pxd

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
from sage.categories.map cimport Map
2-
from sage.rings.ring cimport CommutativeRing
2+
from sage.structure.parent cimport Parent
33

44

5-
cdef class RingExtension_generic(CommutativeRing):
5+
cdef class RingExtension_generic(Parent):
66
cdef _type
77
cdef _backend
88
cdef _defining_morphism
@@ -15,10 +15,10 @@ cdef class RingExtension_generic(CommutativeRing):
1515
cdef type _fraction_field_type
1616

1717
cpdef is_defined_over(self, base)
18-
cpdef CommutativeRing _check_base(self, CommutativeRing base)
19-
cpdef _degree_over(self, CommutativeRing base)
20-
cpdef _is_finite_over(self, CommutativeRing base)
21-
cpdef _is_free_over(self, CommutativeRing base)
18+
cpdef Parent _check_base(self, Parent base)
19+
cpdef _degree_over(self, Parent base)
20+
cpdef _is_finite_over(self, Parent base)
21+
cpdef _is_free_over(self, Parent base)
2222
cdef Map _defining_morphism_fraction_field(self, bint extend_base)
2323

2424

@@ -31,10 +31,11 @@ cdef class RingExtensionWithBasis(RingExtension_generic):
3131
cdef _basis_names
3232
cdef _basis_latex_names
3333

34-
cpdef _basis_over(self, CommutativeRing base)
35-
# cpdef _free_module(self, CommutativeRing base, bint map)
34+
cpdef _basis_over(self, Parent base)
35+
# cpdef _free_module(self, Parent base, bint map)
3636

3737

3838
cdef class RingExtensionWithGen(RingExtensionWithBasis):
3939
cdef _gen
4040
cdef _name
41+
cdef public object _latex_names

0 commit comments

Comments
 (0)