diff --git a/docs/src/extending_abstractalgebra.md b/docs/src/extending_abstractalgebra.md index 90813b21f9..fd9f9bacf1 100644 --- a/docs/src/extending_abstractalgebra.md +++ b/docs/src/extending_abstractalgebra.md @@ -29,6 +29,14 @@ base_ring base_ring_type ``` +If there is a well-defined notion of a coefficient ring (e.g. in the case of +polynomial rings or modules), then one should implement + +```@docs +coefficient_ring +coefficient_ring_type +``` + ## Special elements For rings, one has to extend the following methods: diff --git a/src/RelSeries.jl b/src/RelSeries.jl index fd9370a060..682a65c0ea 100644 --- a/src/RelSeries.jl +++ b/src/RelSeries.jl @@ -29,6 +29,10 @@ base_ring_type(::Type{<:SeriesRing{T}}) where T <: RingElement = parent_type(T) base_ring(R::SeriesRing{T}) where T <: RingElement = R.base_ring::parent_type(T) +coefficient_ring_type(T::Type{<:SeriesRing}) = base_ring_type(T) + +coefficient_ring(R::SeriesRing) = base_ring(R) + function is_domain_type(::Type{T}) where {S <: RingElement, T <: SeriesElem{S}} return is_domain_type(S) end diff --git a/src/fundamental_interface.jl b/src/fundamental_interface.jl index 6c0b1f5f90..57d8d12841 100644 --- a/src/fundamental_interface.jl +++ b/src/fundamental_interface.jl @@ -77,7 +77,7 @@ parent_type(T::DataType) = throw(MethodError(parent_type, (T,))) @doc raw""" base_ring(a) -Return base ring $R$ of given element or parent $a$. +Return the internal base ring of the given element or parent $a$. # Examples ```jldoctest @@ -101,7 +101,7 @@ base_ring(x::NCRingElement) = base_ring(parent(x)) @doc raw""" base_ring_type(a) -Return the type of the base ring of the given element, element type, parent or parent type $a$. +Return the type of the internal base ring of the given element, element type, parent or parent type $a$. # Examples ```jldoctest @@ -133,9 +133,52 @@ base_ring_type(x::Type{<:ModuleElem}) = base_ring_type(parent_type(x)) base_ring_type(x::Type{<:Ideal}) = base_ring_type(parent_type(x)) base_ring_type(T::DataType) = throw(MethodError(base_ring_type, (T,))) -# generic coefficient_ring method +@doc raw""" + coefficient_ring(a) + +Return the coefficient ring of the given element or parent $a$. + +# Examples +```jldoctest +julia> R, x = polynomial_ring(QQ, :x) +(Univariate polynomial ring in x over rationals, x) + +julia> coefficient_ring(x^2+1) == QQ +true + +julia> S, (z,w) = universal_polynomial_ring(QQ, [:z,:w]) +(Universal Polynomial Ring over Rationals, AbstractAlgebra.Generic.UnivPoly{Rational{BigInt}}[z, w]) + +julia> coefficient_ring(S) == QQ +true +``` +""" +function coefficient_ring end coefficient_ring(x::NCRingElement) = coefficient_ring(parent(x)) +@doc raw""" + coefficient_ring_type(a) + +Return the type of the coefficient ring of the given element, element type, parent or parent type $a$. + +# Examples +```jldoctest +julia> R, x = polynomial_ring(ZZ, :x) +(Univariate polynomial ring in x over integers, x) + +julia> coefficient_ring_type(R) == typeof(coefficient_ring(R)) +true + +julia> coefficient_ring_type(zero(R)) == typeof(coefficient_ring(zero(R))) +true + +julia> coefficient_ring_type(typeof(R)) == typeof(coefficient_ring(R)) +true + +julia> coefficient_ring_type(typeof(zero(R))) == typeof(coefficient_ring(zero(R))) +true +``` +""" coefficient_ring_type(x) = coefficient_ring_type(typeof(x)) coefficient_ring_type(x::Type{<:NCRingElement}) = coefficient_ring_type(parent_type(x)) coefficient_ring_type(x::Type{<:ModuleElem}) = coefficient_ring_type(parent_type(x)) diff --git a/src/generic/FreeModule.jl b/src/generic/FreeModule.jl index f2201e8a45..0240d833ce 100644 --- a/src/generic/FreeModule.jl +++ b/src/generic/FreeModule.jl @@ -16,6 +16,10 @@ base_ring_type(::Type{FreeModule{T}}) where T <: Union{RingElement, NCRingElem} base_ring(M::FreeModule{T}) where T <: Union{RingElement, NCRingElem} = M.base_ring::parent_type(T) +coefficient_ring_type(T::Type{<:FreeModule}) = base_ring_type(T) + +coefficient_ring(M::FreeModule) = base_ring(M) + elem_type(::Type{FreeModule{T}}) where T <: Union{RingElement, NCRingElem} = FreeModuleElem{T} parent(m::FreeModuleElem{T}) where T <: Union{RingElement, NCRingElem} = m.parent diff --git a/src/generic/LaurentSeries.jl b/src/generic/LaurentSeries.jl index ff51d6031e..5798b69ee7 100644 --- a/src/generic/LaurentSeries.jl +++ b/src/generic/LaurentSeries.jl @@ -41,6 +41,14 @@ base_ring(R::LaurentSeriesRing{T}) where T <: RingElement = R.base_ring::parent_ base_ring(R::LaurentSeriesField{T}) where T <: FieldElement = R.base_ring::parent_type(T) +coefficient_ring_type(T::Type{<:LaurentSeriesRing}) = base_ring_type(T) + +coefficient_ring_type(T::Type{<:LaurentSeriesField}) = base_ring_type(T) + +coefficient_ring(R::LaurentSeriesRing) = base_ring(R) + +coefficient_ring(R::LaurentSeriesField) = base_ring(R) + function is_domain_type(::Type{T}) where {S <: RingElement, T <: LaurentSeriesElem{S}} return is_domain_type(S) end diff --git a/src/generic/PuiseuxSeries.jl b/src/generic/PuiseuxSeries.jl index 6e71d2fe78..85bcf68315 100644 --- a/src/generic/PuiseuxSeries.jl +++ b/src/generic/PuiseuxSeries.jl @@ -57,6 +57,14 @@ base_ring(R::PuiseuxSeriesRing{T}) where T <: RingElement = base_ring(laurent_ri base_ring(R::PuiseuxSeriesField{T}) where T <: FieldElement = base_ring(laurent_ring(R)) +coefficient_ring_type(T::Type{<:PuiseuxSeriesRing}) = base_ring_type(T) + +coefficient_ring_type(T::Type{<:PuiseuxSeriesField}) = base_ring_type(T) + +coefficient_ring(R::PuiseuxSeriesRing) = base_ring(R) + +coefficient_ring(R::PuiseuxSeriesField) = base_ring(R) + @doc raw""" max_precision(R::PuiseuxSeriesRing{T}) where T <: RingElement diff --git a/src/generic/QuotientModule.jl b/src/generic/QuotientModule.jl index 536a06f595..77e98e1add 100644 --- a/src/generic/QuotientModule.jl +++ b/src/generic/QuotientModule.jl @@ -20,6 +20,10 @@ base_ring_type(::Type{QuotientModule{T}}) where T <: RingElement = parent_type(T base_ring(N::QuotientModule{T}) where T <: RingElement = N.base_ring::parent_type(T) +coefficient_ring_type(T::Type{<:QuotientModule}) = base_ring_type(T) + +coefficient_ring(N::QuotientModule) = base_ring(N) + number_of_generators(N::QuotientModule{T}) where T <: RingElement = length(N.gen_cols) gens(N::QuotientModule{T}) where T <: RingElement = elem_type(N)[gen(N, i) for i = 1:ngens(N)] diff --git a/test/generic/FreeModule-test.jl b/test/generic/FreeModule-test.jl index 01ff3db296..85d64b0008 100644 --- a/test/generic/FreeModule-test.jl +++ b/test/generic/FreeModule-test.jl @@ -11,6 +11,9 @@ @test elem_type(Generic.FreeModule{elem_type(R)}) == Generic.FreeModuleElem{elem_type(R)} @test parent_type(Generic.FreeModuleElem{elem_type(R)}) == Generic.FreeModule{elem_type(R)} + @test coefficient_ring(M) == R + @test coefficient_ring_type(M) == typeof(coefficient_ring(M)) + @test isa(M, Generic.FreeModule) @test isa(M([x, x, x, x, x]), Generic.FreeModuleElem) diff --git a/test/generic/LaurentSeries-test.jl b/test/generic/LaurentSeries-test.jl index bd41a48989..c3fa19df1c 100644 --- a/test/generic/LaurentSeries-test.jl +++ b/test/generic/LaurentSeries-test.jl @@ -40,10 +40,16 @@ end @test elem_type(Generic.LaurentSeriesRing{elem_type(S)}) == Generic.LaurentSeriesRingElem{elem_type(S)} @test parent_type(Generic.LaurentSeriesRingElem{elem_type(S)}) == Generic.LaurentSeriesRing{elem_type(S)} + @test coefficient_ring(T) == S + @test coefficient_ring_type(T) == typeof(coefficient_ring(T)) + @test elem_type(U) == Generic.LaurentSeriesFieldElem{Rational{BigInt}} @test elem_type(Generic.LaurentSeriesField{Rational{BigInt}}) == Generic.LaurentSeriesFieldElem{Rational{BigInt}} @test parent_type(Generic.LaurentSeriesFieldElem{Rational{BigInt}}) == Generic.LaurentSeriesField{Rational{BigInt}} + @test coefficient_ring(U) === QQ + @test coefficient_ring_type(U) == typeof(coefficient_ring(U)) + @test isa(R, Generic.LaurentSeriesRing) @test isa(T, Generic.LaurentSeriesRing) @test isa(U, Generic.LaurentSeriesField) diff --git a/test/generic/PuiseuxSeries-test.jl b/test/generic/PuiseuxSeries-test.jl index 9bddad4812..930946a89c 100644 --- a/test/generic/PuiseuxSeries-test.jl +++ b/test/generic/PuiseuxSeries-test.jl @@ -42,10 +42,16 @@ end @test elem_type(Generic.PuiseuxSeriesRing{elem_type(S)}) == Generic.PuiseuxSeriesRingElem{elem_type(S)} @test parent_type(Generic.PuiseuxSeriesRingElem{elem_type(S)}) == Generic.PuiseuxSeriesRing{elem_type(S)} + @test coefficient_ring(T) == S + @test coefficient_ring_type(T) == typeof(coefficient_ring(T)) + @test elem_type(U) == Generic.PuiseuxSeriesFieldElem{Rational{BigInt}} @test elem_type(Generic.PuiseuxSeriesField{Rational{BigInt}}) == Generic.PuiseuxSeriesFieldElem{Rational{BigInt}} @test parent_type(Generic.PuiseuxSeriesFieldElem{Rational{BigInt}}) == Generic.PuiseuxSeriesField{Rational{BigInt}} + @test coefficient_ring(U) === QQ + @test coefficient_ring_type(U) == typeof(coefficient_ring(U)) + @test isa(R, Generic.PuiseuxSeriesRing) @test isa(T, Generic.PuiseuxSeriesRing) @test isa(U, Generic.PuiseuxSeriesField) diff --git a/test/generic/QuotientModule-test.jl b/test/generic/QuotientModule-test.jl index 35e4c0429d..ef6f5f663f 100644 --- a/test/generic/QuotientModule-test.jl +++ b/test/generic/QuotientModule-test.jl @@ -18,6 +18,9 @@ @test elem_type(Generic.QuotientModule{elem_type(R)}) == Generic.QuotientModuleElem{elem_type(R)} @test parent_type(Generic.QuotientModuleElem{elem_type(R)}) == Generic.QuotientModule{elem_type(R)} + @test coefficient_ring(M) == R + @test coefficient_ring_type(M) == typeof(coefficient_ring(M)) + @test isa(Q([R(2)]), Generic.QuotientModuleElem) R = QQ diff --git a/test/generic/RelSeries-test.jl b/test/generic/RelSeries-test.jl index 6cd5dab01e..edb03b32f7 100644 --- a/test/generic/RelSeries-test.jl +++ b/test/generic/RelSeries-test.jl @@ -45,10 +45,16 @@ end @test elem_type(Generic.RelPowerSeriesRing{BigInt}) == Generic.RelSeries{BigInt} @test parent_type(Generic.RelSeries{BigInt}) == Generic.RelPowerSeriesRing{BigInt} + @test coefficient_ring(R) === ZZ + @test coefficient_ring_type(R) == typeof(coefficient_ring(R)) + @test elem_type(T) == Generic.RelSeries{elem_type(S)} @test elem_type(Generic.RelPowerSeriesRing{elem_type(S)}) == Generic.RelSeries{elem_type(S)} @test parent_type(Generic.RelSeries{elem_type(S)}) == Generic.RelPowerSeriesRing{elem_type(S)} + @test coefficient_ring(T) == S + @test coefficient_ring_type(T) == typeof(coefficient_ring(T)) + @test isa(R, Generic.RelPowerSeriesRing) @test isa(T, Generic.RelPowerSeriesRing)