Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extending GB for modules to non-commutative #827

Merged
merged 4 commits into from
Sep 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/AbstractTypes.jl
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ abstract type Ring <: AbstractAlgebra.Ring end

abstract type Field <: AbstractAlgebra.Field end

abstract type Module{T <: AbstractAlgebra.RingElem} <: AbstractAlgebra.Module{T} end
abstract type Module{T <: AbstractAlgebra.NCRingElem} <: AbstractAlgebra.Module{T} end

abstract type Map <: AbstractAlgebra.SetMap end

Expand Down
4 changes: 2 additions & 2 deletions src/Singular.jl
Original file line number Diff line number Diff line change
Expand Up @@ -216,10 +216,10 @@ include("poly/PolyTypes.jl")

include("matrix/MatrixTypes.jl")

include("module/ModuleTypes.jl")

include("poly/PluralTypes.jl")

include("module/ModuleTypes.jl")

include("poly/LPTypes.jl")

# all "poly" types
Expand Down
35 changes: 20 additions & 15 deletions src/module/ModuleTypes.jl
Original file line number Diff line number Diff line change
Expand Up @@ -4,25 +4,25 @@
#
###############################################################################

const FreeModID = Dict{Tuple{PolyRing, Int}, Module}()
const FreeModID = Dict{Tuple{Nemo.NCRing, Int}, Module}()

mutable struct FreeMod{T <: Nemo.RingElem} <: Module{T}
base_ring::PolyRing
mutable struct FreeMod{T <: Nemo.NCRingElem} <: Module{T}
base_ring::Nemo.NCRing
rank::Int

function FreeMod{T}(R::PolyRing, r::Int) where T
function FreeMod{T}(R::Nemo.NCRing, r::Int) where T
return get!(FreeModID, (R, r)) do
new(R, r)
end
end
end

mutable struct svector{T <: Nemo.RingElem} <: Nemo.ModuleElem{T}
base_ring::PolyRing
mutable struct svector{T <: Nemo.NCRingElem} <: Nemo.ModuleElem{T}
base_ring::Nemo.NCRing
ptr::libSingular.poly_ptr # not really a polynomial
rank::Int

function svector{T}(R::PolyRing, r::Int, p::libSingular.poly_ptr) where T
function svector{T}(R::Nemo.NCRing, r::Int, p::libSingular.poly_ptr) where T
T === elem_type(R) || error("type mismatch")
z = new(R, p, r)
R.refcount += 1
Expand All @@ -31,6 +31,7 @@ mutable struct svector{T <: Nemo.RingElem} <: Nemo.ModuleElem{T}
end
end


"""
(R::PolyRing{T})(m::libSingular.poly,::Val{:vector}) where T
fingolfin marked this conversation as resolved.
Show resolved Hide resolved

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There really should be an empty line here.

Expand All @@ -43,6 +44,10 @@ function (R::PolyRing{T})(m::libSingular.poly_ptr, ::Val{:vector}) where T
return svector{T}(R, 1, m)
end

function (R::PluralRing{T})(m::libSingular.poly_ptr, ::Val{:vector}) where T
return svector{T}(R, 1, m)
end

function _svector_clear_fn(p::svector)
R = p.base_ring
libSingular.p_Delete(p.ptr, R.ptr)
Expand All @@ -55,25 +60,25 @@ end
#
###############################################################################

const ModuleClassID = Dict{PolyRing, Set}()
const ModuleClassID = Dict{Nemo.NCRing, Set}()

mutable struct ModuleClass{T <: Nemo.RingElem} <: Set
base_ring::PolyRing
mutable struct ModuleClass{T <: Nemo.NCRingElem} <: Set
base_ring::Nemo.NCRing

function ModuleClass{T}(R::PolyRing) where T
function ModuleClass{T}(R::Nemo.NCRing) where T
return get!(ModuleClassID, R) do
new(R)
end
end
end

mutable struct smodule{T <: Nemo.RingElem} <: Module{T}
base_ring::PolyRing
mutable struct smodule{T <: Nemo.NCRingElem} <: Module{T}
base_ring::Nemo.NCRing
ptr::libSingular.ideal_ptr # ideal and module types are the same in Singular
isGB::Bool

# take ownership of the pointer - not for general users
function smodule{T}(R::PolyRing, m::libSingular.ideal_ptr) where T
function smodule{T}(R::Nemo.NCRing, m::libSingular.ideal_ptr) where T
T === elem_type(R) || error("type mismatch")
z = new(R, m, false)
R.refcount += 1
Expand All @@ -89,7 +94,7 @@ function smodule{T}(R::PolyRing, m::libSingular.matrix_ptr) where T
return smodule{T}(R, ptr)
end

function smodule{T}(R::PolyRing, vecs::svector...) where T
function smodule{T}(R::Nemo.NCRing, vecs::svector...) where T
n = length(vecs)
r = vecs[1].rank;
for i = 1:n
Expand Down
17 changes: 11 additions & 6 deletions src/module/module.jl
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,15 @@ export jet, minimal_generating_set, ModuleClass, rank, smodule, slimgb,
#
###############################################################################

parent(a::smodule{T}) where T <: Nemo.RingElem = ModuleClass{T}(a.base_ring)
parent(a::smodule{T}) where T <: Nemo.NCRingElem = ModuleClass{T}(a.base_ring)

base_ring(S::ModuleClass) = S.base_ring

base_ring(I::smodule) = I.base_ring

elem_type(::Type{ModuleClass{T}}) where T <: AbstractAlgebra.RingElem = smodule{T}
elem_type(::Type{ModuleClass{T}}) where T <: Nemo.NCRingElem = smodule{T}

parent_type(::Type{smodule{T}}) where T <: AbstractAlgebra.RingElem = ModuleClass{T}
parent_type(::Type{smodule{T}}) where T <: Nemo.NCRingElem = ModuleClass{T}


@doc raw"""
Expand All @@ -38,7 +38,7 @@ function checkbounds(I::smodule, i::Int)
(i > ngens(I) || i < 1) && throw(BoundsError(I, i))
end

function getindex(I::smodule{T}, i::Int) where T <: AbstractAlgebra.RingElem
function getindex(I::smodule{T}, i::Int) where T
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe

Suggested change
function getindex(I::smodule{T}, i::Int) where T
function getindex(I::smodule{T}, i::Int) where T <: Nemo.NCRingElem

checkbounds(I, i)
R = base_ring(I)
GC.@preserve I R begin
Expand All @@ -60,7 +60,7 @@ function deepcopy_internal(I::smodule, dict::IdDict)
return Module(R, ptr)
end

function check_parent(I::smodule{T}, J::smodule{T}) where T <: Nemo.RingElem
function check_parent(I::smodule{T}, J::smodule{T}) where T <: Nemo.NCRingElem
base_ring(I) != base_ring(J) && error("Incompatible modules")
end

Expand Down Expand Up @@ -457,7 +457,12 @@ function Module(R::PolyRing{T}, vecs::svector{spoly{T}}...) where T <: Nemo.Ring
return smodule{S}(R, vecs...)
end

function Module(R::PolyRing{T}, id::libSingular.ideal_ptr) where T <: Nemo.RingElem
function Module(R::PluralRing, vecs::svector{spluralg{T}}...) where T
S = elem_type(R)
return smodule{S}(R, vecs...)
end

function Module(R::Nemo.NCRing, id::libSingular.ideal_ptr)
S = elem_type(R)
return smodule{S}(R, id)
end
Expand Down
83 changes: 69 additions & 14 deletions src/module/vector.jl
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,15 @@ export FreeMod, svector, gens, rank, vector, jet
#
###############################################################################

parent(v::svector{T}) where {T <: Nemo.RingElem} = FreeMod{T}(v.base_ring, v.rank)
parent(v::svector{T}) where {T <: Nemo.NCRingElem} = FreeMod{T}(v.base_ring, v.rank)

base_ring(R::FreeMod) = R.base_ring

base_ring(v::svector) = v.base_ring

elem_type(::Type{FreeMod{T}}) where {T <: Nemo.RingElem} = svector{T}
elem_type(::Type{FreeMod{T}}) where {T <: Nemo.NCRingElem} = svector{T}

parent_type(::Type{svector{T}}) where {T <: Nemo.RingElem} = FreeMod{T}
parent_type(::Type{svector{T}}) where {T <: Nemo.NCRingElem} = FreeMod{T}

@doc raw"""
rank(M::FreeMod)
Expand All @@ -28,28 +28,28 @@ rank(M::FreeMod) = M.rank

Return a Julia array whose entries are the generators of the given free module.
"""
function gens(M::FreeMod{T}) where T <: AbstractAlgebra.RingElem
function gens(M::FreeMod{T}) where T <: Nemo.NCRingElem
R = base_ring(M)
ptr = GC.@preserve R libSingular.id_FreeModule(Cint(M.rank), R.ptr)
return [svector{T}(R, M.rank, libSingular.getindex(ptr, Cint(i - 1))) for i in 1:M.rank]
end

function gen(M::FreeMod{T}, i::Int) where T <: AbstractAlgebra.RingElem
function gen(M::FreeMod{T}, i::Int) where T <: Nemo.NCRingElem
1 <= i <= M.rank || error("index out of range")
R = base_ring(M)
ptr = GC.@preserve R libSingular.id_FreeModule(Cint(M.rank), R.ptr)
return svector{T}(R, M.rank, libSingular.getindex(ptr, Cint(i - 1)))
end

number_of_generators(M::FreeMod{T}) where T <: AbstractAlgebra.RingElem = rank(M)
number_of_generators(M::FreeMod{T}) where T <: Nemo.NCRingElem = rank(M)

function deepcopy_internal(p::svector{T}, dict::IdDict) where T <: AbstractAlgebra.RingElem
function deepcopy_internal(p::svector{T}, dict::IdDict) where T <: Nemo.NCRingElem
R = base_ring(p)
p2 = GC.@preserve p R libSingular.p_Copy(p.ptr, R.ptr)
return svector{T}(p.base_ring, p.rank, p2)
end

function check_parent(a::svector{T}, b::svector{T}) where T <: Nemo.RingElem
function check_parent(a::svector{T}, b::svector{T}) where T <: Nemo.NCRingElem
base_ring(a) != base_ring(b) && error("Incompatible base rings")
a.rank != b.rank && error("Vectors of incompatible rank")
end
Expand Down Expand Up @@ -86,7 +86,7 @@ end
#
###############################################################################

function -(a::svector{T}) where T <: AbstractAlgebra.RingElem
function -(a::svector{T}) where T <: Nemo.NCRingElem
R = base_ring(a)
GC.@preserve a R begin
a1 = libSingular.p_Copy(a.ptr, R.ptr)
Expand All @@ -103,7 +103,7 @@ iszero(p::svector) = p.ptr.cpp_object == C_NULL
#
###############################################################################

function +(a::svector{T}, b::svector{T}) where T <: AbstractAlgebra.RingElem
function +(a::svector{T}, b::svector{T}) where T <: Nemo.NCRingElem
check_parent(a, b)
R = base_ring(a)
GC.@preserve a b R begin
Expand All @@ -114,7 +114,7 @@ function +(a::svector{T}, b::svector{T}) where T <: AbstractAlgebra.RingElem
end
end

function -(a::svector{T}, b::svector{T}) where T <: AbstractAlgebra.RingElem
function -(a::svector{T}, b::svector{T}) where T <: Nemo.NCRingElem
check_parent(a, b)
R = base_ring(a)
GC.@preserve a b R begin
Expand All @@ -138,17 +138,33 @@ function *(a::svector{spoly{T}}, b::spoly{T}) where T <: AbstractAlgebra.RingEle
return svector{spoly{T}}(R, a.rank, s)
end

function *(a::svector{Singular.spluralg{T}}, b::Singular.spluralg{T}) where T <: AbstractAlgebra.RingElem
base_ring(a) != parent(b) && error("Incompatible base rings")
R = base_ring(a)
s = GC.@preserve a b R libSingular.pp_Mult_qq(a.ptr, b.ptr, R.ptr)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is libSingular.pp_Mult_qq the correct function to call here? Maybe @hannes14 can comment

return svector{spoly{T}}(R, a.rank, s)
end

function (a::spoly{T} * b::svector{spoly{T}}) where T <: Nemo.RingElem
base_ring(b) != parent(a) && error("Incompatible base rings")
R = base_ring(b)
s = GC.@preserve a b R libSingular.pp_Mult_qq(a.ptr, b.ptr, R.ptr)
return svector{spoly{T}}(R, b.rank, s)
end

function *(b::Singular.spluralg{T}, a::svector{Singular.spluralg{T}}) where T
base_ring(a) != parent(b) && error("Incompatible base rings")
R = base_ring(a)
s = GC.@preserve a b R libSingular.pp_Mult_qq(a.ptr, b.ptr, R.ptr)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same question here: is this the right function to call here?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, pp_Mult_qq (and most other p_,pp_ routines) work for all types of Singular rings.

return svector{spluralg{T}}(R, a.rank, s)
end

(a::svector{spoly{T}} * b::T) where T <: Nemo.RingElem = a*base_ring(a)(b)

(a::T * b::svector{spoly{T}}) where T <: Nemo.RingElem = base_ring(b)(a)*b

#(a::Singular.spluralg * b::svector{Singular.spluralg}) = base_ring(b)(a)*b

*(a::svector, b::Integer) = a*base_ring(a)(b)

*(a::Integer, b::svector) = base_ring(b)(a)*b
Expand All @@ -159,7 +175,7 @@ end
#
###############################################################################

function (x::svector{T} == y::svector{T}) where T <: Nemo.RingElem
function (x::svector{T} == y::svector{T}) where T <: Union{Nemo.RingElem, Singular.spluralg}
check_parent(x, y)
R = base_ring(x)
GC.@preserve x y R return Bool(libSingular.p_EqualPolys(x.ptr, y.ptr, R.ptr))
Expand Down Expand Up @@ -188,7 +204,7 @@ end
#
###############################################################################

function (S::FreeMod{T})(a::Vector{T}) where T <: AbstractAlgebra.RingElem
function (S::FreeMod{T})(a::Vector{T}) where T <: Union{AbstractAlgebra.RingElem, Singular.spluralg}
R = base_ring(S) # polynomial ring
GC.@preserve a R begin
n = size(a)[1]
Expand All @@ -198,7 +214,7 @@ function (S::FreeMod{T})(a::Vector{T}) where T <: AbstractAlgebra.RingElem
end
end

function (S::FreeMod{T})() where T <: AbstractAlgebra.RingElem
function (S::FreeMod{T})() where T <: Union{AbstractAlgebra.RingElem, Singular.spluralg}
R = base_ring(S) # polynomial ring
n = S.rank
z = zero(R)
Expand Down Expand Up @@ -245,6 +261,22 @@ function Base.iterate(p::svector{spoly{T}}) where T <: Nemo.RingElem
end
end

function Base.iterate(p::Singular.svector{Singular.spluralg{T}}) where T
GC.@preserve p begin
ptr = p.ptr
if ptr.cpp_object == C_NULL
return nothing
else
R = base_ring(p)
A = Array{Int}(undef, nvars(R))
c = GC.@preserve R libSingular.p_GetExpVLV(ptr, A, R.ptr)
S = base_ring(R)
a = GC.@preserve S S(libSingular.n_Copy(libSingular.pGetCoeff(ptr), S.ptr))
return (c, A, a), ptr
end
end
end

function Base.iterate(p::svector{spoly{T}}, state) where T <: Nemo.RingElem
GC.@preserve p begin
state = libSingular.pNext(state)
Expand All @@ -261,6 +293,22 @@ function Base.iterate(p::svector{spoly{T}}, state) where T <: Nemo.RingElem
end
end

function Base.iterate(p::svector{spluralg{T}}, state) where T
GC.@preserve p begin
state = libSingular.pNext(state)
if state.cpp_object == C_NULL
return nothing
else
R = base_ring(p)
A = Array{Int}(undef, nvars(R))
c = GC.@preserve R libSingular.p_GetExpVLV(state, A, R.ptr)
S = base_ring(R)
a = GC.@preserve S S(libSingular.n_Copy(libSingular.pGetCoeff(state), S.ptr))
return (c, A, a), state
end
end
end

Base.IteratorSize(::svector{spoly{T}}) where {T} = Base.SizeUnknown()
###############################################################################
#
Expand Down Expand Up @@ -291,6 +339,13 @@ function FreeModule(R::PolyRing{T}, n::Int) where T <: Nemo.RingElem
return FreeMod{S}(R, n)
end

function FreeModule(R::Singular.PluralRing{T}, n::Int) where T <: Singular.n_Q
(n > typemax(Cint) || n < 0) &&
throw(DomainError(n, "rank must be non-negative and <= $(typemax(Cint))"))
S = elem_type(R)
return FreeMod{S}(R, n)
end

###############################################################################
#
# Differential functions
Expand Down
Loading