Skip to content

Commit

Permalink
Extending GB for modules to non-commutative (#827)
Browse files Browse the repository at this point in the history
  • Loading branch information
Lax202 authored Sep 19, 2024
1 parent a28ad85 commit a078831
Show file tree
Hide file tree
Showing 5 changed files with 103 additions and 38 deletions.
2 changes: 1 addition & 1 deletion src/AbstractTypes.jl
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,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::FreeMod{T}
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
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::ModuleClass{T}
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
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 @@ -458,7 +458,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)
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)
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

0 comments on commit a078831

Please sign in to comment.