From 28b0cb35458006b8685a291f1cec579465964b2c Mon Sep 17 00:00:00 2001 From: Max Horn Date: Fri, 20 Dec 2024 16:39:00 +0100 Subject: [PATCH 1/2] Make is_exact_type and is_domain_type more convenient For examples, this now works: julia> is_domain_type(ZZ) true julia> is_domain_type(ZZ(2)) true julia> is_domain_type(residue_ring(ZZ,6)[1]) false --- src/Rings.jl | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/Rings.jl b/src/Rings.jl index 34992587db..463a58d6af 100644 --- a/src/Rings.jl +++ b/src/Rings.jl @@ -95,12 +95,28 @@ end # Type can only represent elements of an exact ring # true unless explicitly specified +# +# implementors should only implement this trait for RingElem subtypes, but for +# convenience we support calling this also on Ring subtypes as well as Ring +# and RingElem instances is_exact_type(R::Type{T}) where T <: RingElem = true -# Type can only represent elements of domains +is_exact_type(x) = is_exact_type(typeof(x)) +is_exact_type(x::Type{<:Ring}) = is_exact_type(elem_type(x)) +is_exact_type(T::DataType) = throw(MethodError(is_exact_type, (T,))) + +# Type can only represent elements of domains, i.e. without zero divisors # false unless explicitly specified +# +# implementors should only implement this trait for RingElem subtypes, but for +# convenience we support calling this also on Ring subtypes as well as Ring +# and RingElem instances is_domain_type(R::Type{T}) where T <: RingElem = false +is_domain_type(x) = is_domain_type(typeof(x)) +is_domain_type(x::Type{<:Ring}) = is_domain_type(elem_type(x)) +is_domain_type(T::DataType) = throw(MethodError(is_domain_type, (T,))) + ############################################################################### # # Exponential function for generic rings From f5d43f0fa44a24f7aa33a3445cb36e46dc315635 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Fri, 20 Dec 2024 16:42:38 +0100 Subject: [PATCH 2/2] Add is_euclidean_type trait The idea is that this true for ring / ring elem types that explicitly support a euclidean division with remainder, and ideally also a euclidean degree (to be defined in the interface). This is just a draft to have a point for discussion and experiments: it is missing many things, including documentation as to what is_euclidean_type(x)==true means, which promises this incurrs; and of course also code needs to be adapted to use it (e.g. the residue ring or ideal constructions or whatnot that only work sensible for euclidean rings should check this. --- src/Fields.jl | 2 ++ src/Poly.jl | 11 +++++------ src/Rings.jl | 13 +++++++++++++ 3 files changed, 20 insertions(+), 6 deletions(-) diff --git a/src/Fields.jl b/src/Fields.jl index 4df6c4043a..e9762442de 100644 --- a/src/Fields.jl +++ b/src/Fields.jl @@ -6,6 +6,8 @@ is_domain_type(::Type{T}) where {T <: FieldElem} = true +is_euclidean_type(::Type{T}) where {T <: FieldElem} = true + is_zero_divisor(a::T) where T <: FieldElem = is_zero(a) is_unit(a::FieldElem) = !iszero(a) diff --git a/src/Poly.jl b/src/Poly.jl index a612c17f77..f519f00581 100644 --- a/src/Poly.jl +++ b/src/Poly.jl @@ -16,13 +16,12 @@ coefficient_ring(R::PolyRing) = base_ring(R) dense_poly_type(::Type{T}) where T<:RingElement = Generic.Poly{T} -function is_domain_type(::Type{T}) where {S <: RingElement, T <: PolyRingElem{S}} - return is_domain_type(S) -end +is_exact_type(::Type{<:PolyRingElem{T}}) where {T <: RingElement} = is_exact_type(T) -function is_exact_type(a::Type{T}) where {S <: RingElement, T <: PolyRingElem{S}} - return is_exact_type(S) -end +is_domain_type(::Type{<:PolyRingElem{T}}) where {T <: RingElement} = is_domain_type(T) + +is_euclidean_type(::Type{<:PolyRingElem{T}}) where {T <: RingElem} = T <: FieldElem +# TODO: what about polynomials over `Rational{BigInt}`? @doc raw""" var(a::PolyRing) diff --git a/src/Rings.jl b/src/Rings.jl index 463a58d6af..cdf3c5059b 100644 --- a/src/Rings.jl +++ b/src/Rings.jl @@ -117,6 +117,19 @@ is_domain_type(x) = is_domain_type(typeof(x)) is_domain_type(x::Type{<:Ring}) = is_domain_type(elem_type(x)) is_domain_type(T::DataType) = throw(MethodError(is_domain_type, (T,))) +# Type can only represent elements of euclidean rings (which do not need to be domains) +# false unless explicitly specified +# +# implementors should only implement this trait for RingElem subtypes, but for +# convenience we support calling this also on Ring subtypes as well as Ring +# and RingElem instances +is_euclidean_type(R::Type{T}) where T <: RingElem = false + +is_euclidean_type(x) = is_euclidean_type(typeof(x)) +is_euclidean_type(x::Type{<:Ring}) = is_euclidean_type(elem_type(x)) +is_euclidean_type(T::DataType) = throw(MethodError(is_euclidean_type, (T,))) + + ############################################################################### # # Exponential function for generic rings