Skip to content

Commit 45d9da8

Browse files
committed
Add coefficient_ring for modules and improve the docs for base_ring
1 parent 10cb1ce commit 45d9da8

File tree

5 files changed

+81
-22
lines changed

5 files changed

+81
-22
lines changed

docs/src/extending_abstractalgebra.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,14 @@ base_ring
2929
base_ring_type
3030
```
3131

32+
If there is a well-defined notion of a coefficient ring (e.g. in the case of
33+
polynomial rings or modules), then one should implement
34+
35+
```@docs
36+
coefficient_ring
37+
coefficient_ring_type
38+
```
39+
3240
## Special elements
3341

3442
For rings, one has to extend the following methods:

src/fundamental_interface.jl

Lines changed: 46 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ parent_type(T::DataType) = throw(MethodError(parent_type, (T,)))
7777
@doc raw"""
7878
base_ring(a)
7979
80-
Return base ring $R$ of given element or parent $a$.
80+
Return the internal base ring of the given element or parent $a$.
8181
8282
# Examples
8383
```jldoctest
@@ -101,7 +101,7 @@ base_ring(x::NCRingElement) = base_ring(parent(x))
101101
@doc raw"""
102102
base_ring_type(a)
103103
104-
Return the type of the base ring of the given element, element type, parent or parent type $a$.
104+
Return the type of the internal base ring of the given element, element type, parent or parent type $a$.
105105
106106
# Examples
107107
```jldoctest
@@ -133,9 +133,52 @@ base_ring_type(x::Type{<:ModuleElem}) = base_ring_type(parent_type(x))
133133
base_ring_type(x::Type{<:Ideal}) = base_ring_type(parent_type(x))
134134
base_ring_type(T::DataType) = throw(MethodError(base_ring_type, (T,)))
135135

136-
# generic coefficient_ring method
136+
@doc raw"""
137+
coefficient_ring(a)
138+
139+
Return the coefficient ring of the given element or parent $a$.
140+
141+
# Examples
142+
```jldoctest
143+
julia> R, x = polynomial_ring(QQ, :x)
144+
(Univariate polynomial ring in x over rationals, x)
145+
146+
julia> coefficient_ring(x^2+1) == QQ
147+
true
148+
149+
julia> S, (z,w) = universal_polynomial_ring(QQ, [:z,:w])
150+
(Universal Polynomial Ring over Rationals, AbstractAlgebra.Generic.UnivPoly{Rational{BigInt}}[z, w])
151+
152+
julia> coefficient_ring(S) == QQ
153+
true
154+
```
155+
"""
156+
function coefficient_ring end
137157
coefficient_ring(x::NCRingElement) = coefficient_ring(parent(x))
138158

159+
@doc raw"""
160+
coefficient_ring_type(a)
161+
162+
Return the type of the coefficient ring of the given element, element type, parent or parent type $a$.
163+
164+
# Examples
165+
```jldoctest
166+
julia> R, x = polynomial_ring(ZZ, :x)
167+
(Univariate polynomial ring in x over integers, x)
168+
169+
julia> coefficient_ring_type(R) == typeof(coefficient_ring(R))
170+
true
171+
172+
julia> coefficient_ring_type(zero(R)) == typeof(coefficient_ring(zero(R)))
173+
true
174+
175+
julia> coefficient_ring_type(typeof(R)) == typeof(coefficient_ring(R))
176+
true
177+
178+
julia> coefficient_ring_type(typeof(zero(R))) == typeof(coefficient_ring(zero(R)))
179+
true
180+
```
181+
"""
139182
coefficient_ring_type(x) = coefficient_ring_type(typeof(x))
140183
coefficient_ring_type(x::Type{<:NCRingElement}) = coefficient_ring_type(parent_type(x))
141184
coefficient_ring_type(x::Type{<:ModuleElem}) = coefficient_ring_type(parent_type(x))

src/generic/FreeModule.jl

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@ base_ring_type(::Type{FreeModule{T}}) where T <: Union{RingElement, NCRingElem}
1616

1717
base_ring(M::FreeModule{T}) where T <: Union{RingElement, NCRingElem} = M.base_ring::parent_type(T)
1818

19+
coefficient_ring_type(T::Type{FreeModule}) = base_ring_type(T)
20+
21+
coefficient_ring(M::FreeModule) = base_ring(M)
22+
1923
elem_type(::Type{FreeModule{T}}) where T <: Union{RingElement, NCRingElem} = FreeModuleElem{T}
2024

2125
parent(m::FreeModuleElem{T}) where T <: Union{RingElement, NCRingElem} = m.parent
@@ -50,7 +54,7 @@ end
5054

5155
function gen(N::FreeModule{T}, i::Int) where T <: Union{RingElement, NCRingElem}
5256
@boundscheck 1 <= i <= ngens(N) || throw(ArgumentError("generator index out of range"))
53-
R = base_ring(N)
57+
R = coefficient_ring(N)
5458
m = zero_matrix(R, 1, ngens(N))
5559
add_one!(m, 1, i)
5660
return N(m)
@@ -72,7 +76,7 @@ function show(io::IO, M::FreeModule{T}) where T <: Union{RingElement, NCRingElem
7276
print(io, "Free module of rank ")
7377
print(io, rank(M))
7478
print(io, " over ")
75-
print(terse(pretty(io)), Lowercase(), base_ring(M))
79+
print(terse(pretty(io)), Lowercase(), coefficient_ring(M))
7680
end
7781

7882
function show(io::IO, M::FreeModule{T}) where T <: FieldElement
@@ -81,7 +85,7 @@ function show(io::IO, M::FreeModule{T}) where T <: FieldElement
8185
print(io, "Vector space of dimension ")
8286
print(io, dim(M))
8387
print(io, " over ")
84-
print(terse(pretty(io)), Lowercase(), base_ring(M))
88+
print(terse(pretty(io)), Lowercase(), coefficient_ring(M))
8589
end
8690

8791
function show(io::IO, a::FreeModuleElem)
@@ -105,23 +109,23 @@ end
105109

106110
function (M::FreeModule{T})(a::Vector{T}) where T <: Union{RingElement, NCRingElem}
107111
length(a) != rank(M) && error("Number of elements does not equal rank")
108-
R = base_ring(M)
112+
R = coefficient_ring(M)
109113
v = matrix(R, 1, length(a), a)
110114
z = FreeModuleElem{T}(M, v)
111115
return z
112116
end
113117

114118
#function (M::FreeModule{T})(a::Vector{<: Integer}) where T <: Union{RingElement, NCRingElem}
115119
# length(a) != rank(M) && error("Number of elements does not equal rank")
116-
# R = base_ring(M)
120+
# R = coefficient_ring(M)
117121
# v = matrix(R, 1, length(a), a)
118122
# z = FreeModuleElem{T}(M, v)
119123
# return z
120124
#end
121125

122126
function (M::FreeModule{T})(a::Vector{S}) where {T <: Union{RingElement, NCRingElem}, S <: RingElement}
123127
length(a) != rank(M) && error("Number of elements does not equal rank")
124-
R = base_ring(M)
128+
R = coefficient_ring(M)
125129
v = matrix(R, 1, length(a), a)
126130
z = FreeModuleElem{T}(M, v)
127131
return z
@@ -141,7 +145,7 @@ end
141145

142146
function (M::FreeModule{T})(a::SubmoduleElem{T}) where T <: RingElement
143147
R = parent(a)
144-
base_ring(R) !== base_ring(M) && error("Incompatible modules")
148+
coefficient_ring(R) !== coefficient_ring(M) && error("Incompatible modules")
145149
return M(R.map(a))
146150
end
147151

src/generic/QuotientModule.jl

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@ base_ring_type(::Type{QuotientModule{T}}) where T <: RingElement = parent_type(T
2020

2121
base_ring(N::QuotientModule{T}) where T <: RingElement = N.base_ring::parent_type(T)
2222

23+
coefficient_ring_type(T::Type{QuotientModule}) = base_ring_type(T)
24+
25+
coefficient_ring(N::QuotientModule) = base_ring(N)
26+
2327
number_of_generators(N::QuotientModule{T}) where T <: RingElement = length(N.gen_cols)
2428

2529
gens(N::QuotientModule{T}) where T <: RingElement = elem_type(N)[gen(N, i) for i = 1:ngens(N)]
@@ -28,7 +32,7 @@ rank(M::QuotientModule{T}) where T <: FieldElement = dim(M)
2832

2933
function gen(N::QuotientModule{T}, i::Int) where T <: RingElement
3034
@boundscheck 1 <= i <= ngens(N) || throw(ArgumentError("generator index out of range"))
31-
R = base_ring(N)
35+
R = coefficient_ring(N)
3236
mat = matrix(R, 1, ngens(N),
3337
[(j == i ? one(R) : zero(R)) for j = 1:ngens(N)])
3438
return QuotientModuleElem{T}(N, mat)
@@ -70,15 +74,15 @@ function show(io::IO, N::QuotientModule{T}) where T <: RingElement
7074
@show_name(io, N)
7175
@show_special(io, N)
7276
print(io, "Quotient module over ")
73-
print(terse(pretty(io)), Lowercase(), base_ring(N))
77+
print(terse(pretty(io)), Lowercase(), coefficient_ring(N))
7478
show_gens_rels(io, N)
7579
end
7680

7781
function show(io::IO, N::QuotientModule{T}) where T <: FieldElement
7882
@show_name(io, N)
7983
@show_special(io, N)
8084
print(io, "Quotient space over ")
81-
print(terse(pretty(io)), Lowercase(), base_ring(N))
85+
print(terse(pretty(io)), Lowercase(), coefficient_ring(N))
8286
show_gens_rels(io, N)
8387
end
8488

@@ -114,7 +118,7 @@ end
114118

115119
# Reduce the vector v by the relations vrels starting at column start of v
116120
function reduce_mod_rels(v::AbstractAlgebra.MatElem{T}, vrels::Vector{<:AbstractAlgebra.MatElem{T}}, start::Int) where T <: RingElement
117-
R = base_ring(v)
121+
R = coefficient_ring(v)
118122
v = deepcopy(v) # don't destroy input
119123
i = 1
120124
t1 = R()
@@ -136,7 +140,7 @@ end
136140

137141
function (N::QuotientModule{T})(v::Vector{T}) where T <: RingElement
138142
length(v) != ngens(N) && error("Length of vector does not match number of generators")
139-
mat = matrix(base_ring(N), 1, length(v), v)
143+
mat = matrix(coefficient_ring(N), 1, length(v), v)
140144
mat = reduce_mod_rels(mat, rels(N), 1)
141145
return QuotientModuleElem{T}(N, mat)
142146
end
@@ -155,8 +159,8 @@ end
155159

156160
function (M::QuotientModule{T})(a::AbstractAlgebra.FPModuleElem{T}) where T <: RingElement
157161
N = parent(a)
158-
R = base_ring(N)
159-
base_ring(M) != R && error("Incompatible modules")
162+
R = coefficient_ring(N)
163+
coefficient_ring(M) != R && error("Incompatible modules")
160164
if M === N
161165
return a
162166
else
@@ -180,7 +184,7 @@ end
180184
###############################################################################
181185

182186
function projection(v::AbstractAlgebra.MatElem{T}, crels::AbstractAlgebra.MatElem{T}, N::QuotientModule{T}) where {T <: RingElement}
183-
R = base_ring(N)
187+
R = coefficient_ring(N)
184188
# remove zero rows
185189
nr = nrows(crels)
186190
while nr > 0 && is_zero_row(crels, nr)
@@ -203,7 +207,7 @@ end
203207

204208
function compute_combined_rels(m::AbstractAlgebra.FPModule{T}, srels::Vector{S}) where {T <: RingElement, S <: AbstractAlgebra.MatElem{T}}
205209
# concatenate relations in m and new rels
206-
R = base_ring(m)
210+
R = coefficient_ring(m)
207211
old_rels = rels(m)
208212
combined_rels = zero_matrix(R, length(old_rels) + length(srels), ngens(m))
209213
for i = 1:length(old_rels)
@@ -265,7 +269,7 @@ function quo(m::AbstractAlgebra.FPModule{T}, subm::Submodule{T}) where T <: Ring
265269
@assert is_submodule(m, subm)
266270
end
267271

268-
R = base_ring(m)
272+
R = coefficient_ring(m)
269273
if subm === m # quotient of submodule by itself
270274
srels = dense_matrix_type(T)[_matrix(v) for v in gens(subm)]
271275
combined_rels = compute_combined_rels(m, srels)
@@ -305,7 +309,7 @@ function quo(m::AbstractAlgebra.FPModule{T}, subm::AbstractAlgebra.FPModule{T})
305309
srels = dense_matrix_type(T)[_matrix(v) for v in gens(subm)]
306310
combined_rels = compute_combined_rels(m, srels)
307311
M = QuotientModule{T}(m, combined_rels)
308-
R = base_ring(m)
312+
R = coefficient_ring(m)
309313
f = ModuleHomomorphism(m, M, matrix(R, ngens(m), 0, []))
310314
M.map = f
311315
return M, f

test/generic/Module-test.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
function rand_homomorphism(M::AbstractAlgebra.FPModule{T}, vals...) where T <: RingElement
22
rk = rand(1:5)
33
m = ngens(M)
4-
R = base_ring(M)
4+
R = coefficient_ring(M)
55
F = free_module(R, rk)
66
S = matrix_space(R, rk, m)
77
mat = rand(S, vals...)

0 commit comments

Comments
 (0)