mirror of
https://github.com/kalmarek/GroupRings.jl.git
synced 2024-12-29 11:00:28 +01:00
move types/constructors parent call overloads to types.jl
This commit is contained in:
parent
d0d3a25524
commit
006c1fcfb2
@ -10,164 +10,8 @@ using Markdown
|
|||||||
|
|
||||||
import Base: convert, show, hash, ==, +, -, *, ^, //, /, length, getindex, setindex!, eltype, one, zero
|
import Base: convert, show, hash, ==, +, -, *, ^, //, /, length, getindex, setindex!, eltype, one, zero
|
||||||
|
|
||||||
###############################################################################
|
|
||||||
#
|
|
||||||
# GroupRings / GroupRingsElem
|
|
||||||
#
|
|
||||||
###############################################################################
|
|
||||||
|
|
||||||
mutable struct GroupRing{Gr<:Group, T<:GroupElem} <: Ring
|
|
||||||
group::Gr
|
|
||||||
basis::Vector{T}
|
|
||||||
basis_dict::Dict{T, Int}
|
|
||||||
pm::Array{Int,2}
|
|
||||||
|
|
||||||
function GroupRing(G::Gr, basis::Vector{T};
|
|
||||||
cachedmul::Bool=false) where {Gr, T}
|
|
||||||
RG = new{Gr, T}(G, basis, reverse_dict(basis))
|
|
||||||
cachedmul && initializepm!(RG)
|
|
||||||
return RG
|
|
||||||
end
|
|
||||||
|
|
||||||
function GroupRing(G::Gr, b::Vector{T}, b_d::Dict{T, Int}, pm::Array{Int,2}) where {Gr,T}
|
|
||||||
return new{Gr, T}(G, b, b_d, pm)
|
|
||||||
end
|
|
||||||
|
|
||||||
function GroupRing(G::Gr, pm::Array{Int,2}) where {Gr}
|
|
||||||
RG = new{Gr, elem_type(G)}(G)
|
|
||||||
RG.pm = pm
|
|
||||||
return RG
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
mutable struct GroupRingElem{T, A<:AbstractVector, GR<:GroupRing} <: RingElem
|
|
||||||
coeffs::A
|
|
||||||
parent::GR
|
|
||||||
|
|
||||||
function GroupRingElem{T, A, GR}(c::AbstractVector{T}, RG::GR, check=true) where {T, A, GR}
|
|
||||||
if check
|
|
||||||
if isdefined(RG, :basis)
|
|
||||||
length(c) == length(RG.basis) || throw(
|
|
||||||
"Can't create GroupRingElem -- lengths differ: length(c) =
|
|
||||||
$(length(c)) != $(length(RG.basis)) = length(RG.basis)")
|
|
||||||
else
|
|
||||||
@warn("Basis of the GroupRing is not defined.")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return new{T, A, GR}(c, RG)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
export GroupRing, GroupRingElem, complete!, create_pm, star, aug, supp
|
export GroupRing, GroupRingElem, complete!, create_pm, star, aug, supp
|
||||||
|
|
||||||
###############################################################################
|
|
||||||
#
|
|
||||||
# GroupRing / GroupRingElem constructors
|
|
||||||
#
|
|
||||||
###############################################################################
|
|
||||||
|
|
||||||
function GroupRingElem(c::AbstractVector, RG::GroupRing)
|
|
||||||
return GroupRingElem{eltype(c), typeof(c), typeof(RG)}(c, RG)
|
|
||||||
end
|
|
||||||
|
|
||||||
function GroupRing(G::Generic.PermGroup; cachedmul::Bool=false)
|
|
||||||
return GroupRing(G, vec(collect(G)), cachedmul=cachedmul)
|
|
||||||
end
|
|
||||||
|
|
||||||
function GroupRing(G::Group, basis::Vector, pm::Array{Int,2})
|
|
||||||
size(pm,1) == size(pm,2) || throw("pm must be square, got $(size(pm))")
|
|
||||||
eltype(basis) == elem_type(G) || throw("Basis must consist of elements of $G")
|
|
||||||
return GroupRing(G, basis, reverse_dict(basis), pm)
|
|
||||||
end
|
|
||||||
|
|
||||||
###############################################################################
|
|
||||||
#
|
|
||||||
# Type and parent object methods
|
|
||||||
#
|
|
||||||
###############################################################################
|
|
||||||
|
|
||||||
elem_type(::Type{GroupRing}) = GroupRingElem
|
|
||||||
|
|
||||||
eltype(::Type{GroupRingElem{T, A, Gr}}) where {T, A, Gr} = T
|
|
||||||
|
|
||||||
parent(g::GroupRingElem) = g.parent
|
|
||||||
|
|
||||||
parent_type(X::GroupRingElem) = typeof(parent(X))
|
|
||||||
|
|
||||||
import Base.promote_rule
|
|
||||||
|
|
||||||
promote_rule(::Type{GroupRingElem{T}}, ::Type{GroupRingElem{S}}) where {T,S} =
|
|
||||||
GroupRingElem{promote_type(T,S)}
|
|
||||||
|
|
||||||
function convert(::Type{T}, X::GroupRingElem) where {T<:Number}
|
|
||||||
return GroupRingElem(Vector{T}(X.coeffs), parent(X))
|
|
||||||
end
|
|
||||||
|
|
||||||
###############################################################################
|
|
||||||
#
|
|
||||||
# Parent object call overloads
|
|
||||||
#
|
|
||||||
###############################################################################
|
|
||||||
|
|
||||||
# sparse storage:
|
|
||||||
|
|
||||||
zero(RG::GroupRing, T::Type=Int) = RG(T)
|
|
||||||
one(RG::GroupRing, T::Type=Int) = RG(RG.group(), T)
|
|
||||||
one(RG::GroupRing{<:MatSpace}, T::Type=Int) = RG(one(RG.group), T)
|
|
||||||
|
|
||||||
function (RG::GroupRing)(T::Type=Int)
|
|
||||||
isdefined(RG, :basis) || throw("Can not coerce without basis of GroupRing")
|
|
||||||
return GroupRingElem(spzeros(T,length(RG.basis)), RG)
|
|
||||||
end
|
|
||||||
|
|
||||||
function (RG::GroupRing)(i::Int, T::Type=Int)
|
|
||||||
elt = RG(T)
|
|
||||||
elt[RG.group()] = i
|
|
||||||
return elt
|
|
||||||
end
|
|
||||||
|
|
||||||
function (RG::GroupRing{<:MatSpace})(i::Int, T::Type=Int)
|
|
||||||
elt = RG(T)
|
|
||||||
elt[one(RG.group)] = i
|
|
||||||
return elt
|
|
||||||
end
|
|
||||||
|
|
||||||
function (RG::GroupRing)(g::GroupElem, T::Type=Int)
|
|
||||||
result = RG(T)
|
|
||||||
result[RG.group(g)] = one(T)
|
|
||||||
return result
|
|
||||||
end
|
|
||||||
|
|
||||||
function (RG::GroupRing{Gr,T})(V::Vector{T}, S::Type=Int) where {Gr<:Group, T<:GroupElem}
|
|
||||||
res = RG(S)
|
|
||||||
for g in V
|
|
||||||
res[g] += one(S)
|
|
||||||
end
|
|
||||||
return res
|
|
||||||
end
|
|
||||||
|
|
||||||
function (RG::GroupRing)(f::Function, X::GroupRingElem{T}) where T
|
|
||||||
isdefined(RG, :basis) || throw("Can not coerce without basis of GroupRing")
|
|
||||||
res = RG(T)
|
|
||||||
for g in supp(X)
|
|
||||||
res[f(g)] = X[g]
|
|
||||||
end
|
|
||||||
return res
|
|
||||||
end
|
|
||||||
|
|
||||||
# keep storage type
|
|
||||||
|
|
||||||
function (RG::GroupRing)(x::AbstractVector{T}) where T<:Number
|
|
||||||
isdefined(RG, :basis) || throw("Basis of GroupRing not defined. For advanced use the direct constructor of GroupRingElem is provided.")
|
|
||||||
length(x) == length(RG.basis) || throw("Can not coerce to $RG: lengths differ")
|
|
||||||
return GroupRingElem(x, RG)
|
|
||||||
end
|
|
||||||
|
|
||||||
function (RG::GroupRing)(X::GroupRingElem)
|
|
||||||
RG == parent(X) || throw("Can not coerce!")
|
|
||||||
return RG(X.coeffs)
|
|
||||||
end
|
|
||||||
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
#
|
#
|
||||||
# Basic manipulation && Array protocol
|
# Basic manipulation && Array protocol
|
||||||
|
161
src/types.jl
Normal file
161
src/types.jl
Normal file
@ -0,0 +1,161 @@
|
|||||||
|
###############################################################################
|
||||||
|
#
|
||||||
|
# GroupRing & GroupRingElem structs
|
||||||
|
#
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
mutable struct GroupRing{R<:Ring, Gr<:Group, El<:GroupElem} <: NCRing
|
||||||
|
base_ring::R
|
||||||
|
group::Gr
|
||||||
|
basis::Vector{El}
|
||||||
|
basis_dict::Dict{El, Int32}
|
||||||
|
pm::Matrix{Int32}
|
||||||
|
|
||||||
|
function GroupRing(coeffring::Ring, group::Group, basis::Vector{<:GroupElem};
|
||||||
|
halfradius_length::Integer=0)
|
||||||
|
|
||||||
|
elem_type(group) == eltype(basis) ||
|
||||||
|
throw(ArgumentError("Basis must consist of elements of $G"))
|
||||||
|
|
||||||
|
RG = new{typeof(coeffring), typeof(group), eltype(basis)}(
|
||||||
|
coeffring, group, basis, reverse_dict(basis))
|
||||||
|
|
||||||
|
if halfradius_length > 0
|
||||||
|
pm = zeros(Int32, halfradius_length, halfradius_length)
|
||||||
|
setcache!(RG, pm)
|
||||||
|
end
|
||||||
|
|
||||||
|
return RG
|
||||||
|
end
|
||||||
|
|
||||||
|
function GroupRing(coeffring::Ring, group::Group, basis::Vector{<:GroupElem},
|
||||||
|
basis_dict::Dict{<:GroupElem,<:Integer}, pm::Matrix{<:Integer})
|
||||||
|
size(pm,1) == size(pm,2) ||
|
||||||
|
throw(ArgumentError("Multiplication table must be square, got one of size $(size(pm))"))
|
||||||
|
elem_type(group) == eltype(basis) ||
|
||||||
|
throw(ArgumentError("Basis must consist of elements of $G"))
|
||||||
|
|
||||||
|
RG = new{typeof(coeffring), typeof(group), eltype(basis)}(
|
||||||
|
coeffring, group, basis, basis_dict, pm)
|
||||||
|
|
||||||
|
return RG
|
||||||
|
end
|
||||||
|
|
||||||
|
function GroupRing(coeffring::Ring, group::Group, pm::Matrix{<:Integer})
|
||||||
|
size(pm,1) == size(pm,2) || throw(ArgumentError("Multiplication table must be square, got one of size $(size(pm))"))
|
||||||
|
|
||||||
|
RG = new{typeof(coeffring), typeof(group), elem_type(group)}(coeffring, group)
|
||||||
|
setcache!(RG, pm)
|
||||||
|
return RG
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
mutable struct GroupRingElem{T, GR<:GroupRing} <: NCRingElem
|
||||||
|
coeffs::SparseVector{T, Int}
|
||||||
|
parent::GR
|
||||||
|
|
||||||
|
function GroupRingElem(c::AbstractVector{T}, RG::GR; check::Bool=true) where {T, GR}
|
||||||
|
if check
|
||||||
|
T == elem_type(base_ring(RG)) || throw(DomainError(c, "Call parent group ring on the vector to coerce the coefficients.s"))
|
||||||
|
length(c) == length(RG) || throw(DomainError(c, "Can not coerce vector to $RG -- lengths differ:\n $(length(c)) ≠ $(length(RG))"))
|
||||||
|
end
|
||||||
|
return new{eltype(c), GR}(sparse(c), RG)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
#
|
||||||
|
# Constructors & parent object call overloads (NCRing interface)
|
||||||
|
#
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
(RG::GroupRing)(i::Integer=0)= _coerce_scalar(RG, i)
|
||||||
|
(RG::GroupRing)(x::RingElem) = _coerce_scalar(RG, x)
|
||||||
|
|
||||||
|
function (RG::GroupRing)(X::GroupRingElem{T}) where {T}
|
||||||
|
if RG == parent(X) && elem_type(base_ring(RG)) == T
|
||||||
|
return X
|
||||||
|
end
|
||||||
|
if RG.group == parent(X).group
|
||||||
|
return GroupRingElem(base_ring(RG).(X.coeffs), RG) # we do checks here
|
||||||
|
end
|
||||||
|
throw(ArgumentError("Can not coerce to $RG."))
|
||||||
|
end
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
#
|
||||||
|
# Additional Constructors / parent call overloads
|
||||||
|
#
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
function GroupRing(coeffring::Ring, group::Group, basis::Vector{<:GroupElem},
|
||||||
|
pm::Matrix{<:Integer})
|
||||||
|
return GroupRing(coeffring, group, basis, reverse_dict(basis), pm)
|
||||||
|
end
|
||||||
|
|
||||||
|
function (RG::GroupRing)(g::GroupElem, val=one(base_ring(RG)))
|
||||||
|
v = sparsevec([RG[g]], [base_ring(RG)(val)], length(RG))
|
||||||
|
return GroupRingElem(v, RG, check=false)
|
||||||
|
end
|
||||||
|
|
||||||
|
function (RG::GroupRing{R, G, El})(V::AbstractVector{El},
|
||||||
|
vals=[one(base_ring(RG)) for _ in V]) where {R, G, El}
|
||||||
|
hasbasis(RG) || throw(ArgumentError("Can not embedd without basis of $RG"))
|
||||||
|
l = length(RG)
|
||||||
|
nzind = [RG[g] for g in V]
|
||||||
|
return GroupRingElem(sparsevec(nzind, base_ring(RG).(vals), l), RG, check=false)
|
||||||
|
end
|
||||||
|
|
||||||
|
function (RG::GroupRing)(f, X::GroupRingElem)
|
||||||
|
hasbasis(RG) || throw(ArgumentError("Can not embedd without basis of $RG"))
|
||||||
|
suppX = supp(X)
|
||||||
|
return RG([f(g) for g in suppX], [X[g] for g in suppX])
|
||||||
|
end
|
||||||
|
|
||||||
|
function (RG::GroupRing)(v::AbstractVector;
|
||||||
|
adjust_length::Bool=false, widen_coefficients::Bool=false)
|
||||||
|
|
||||||
|
if adjust_length
|
||||||
|
l = length(RG)
|
||||||
|
if length(v) < l
|
||||||
|
@warn "Coefficients vector is length-defficient; adjusting."
|
||||||
|
v = sparse(v)
|
||||||
|
v = sparse(v.nzind, v.nzval, l)
|
||||||
|
elseif length(c) > l
|
||||||
|
throw(DomainError(v, "Can not coerce vector to $RG -- lengths differ:\n $(length(v)) ≠ $(length(RG))"))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if widen_coefficients
|
||||||
|
parent(first(v)) != base_ring(RG)
|
||||||
|
RG = change_base_ring(RG, parent(first(v)))
|
||||||
|
return GroupRingElem(v, RG)
|
||||||
|
else
|
||||||
|
R = base_ring(RG)
|
||||||
|
return GroupRingElem(R.(v), RG)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function AbstractAlgebra.change_base_ring(RG::GroupRing, R::Ring)
|
||||||
|
if base_ring(RG) == R
|
||||||
|
return RG
|
||||||
|
end
|
||||||
|
if hasbasis(RG) && cachesmultiplication(RG)
|
||||||
|
return GroupRing(R, RG.group, RG.basis, RG.basis_dict, RG.pm)
|
||||||
|
elseif hasbasis(RG)
|
||||||
|
return GroupRing(R, RG.group, RG.basis, RG.basis_dict)
|
||||||
|
elseif cachesmultiplication(RG)
|
||||||
|
return GroupRing(R, RG.group, RG.pm)
|
||||||
|
end
|
||||||
|
throw(ArgumentError("Could not change the base ring of $RG to $R"))
|
||||||
|
end
|
||||||
|
|
||||||
|
function AbstractAlgebra.change_base_ring(X::GroupRingElem, R::Ring)
|
||||||
|
if base_ring(parent(X)) == R
|
||||||
|
return X
|
||||||
|
else
|
||||||
|
RG = change_base_ring(parent(X), R)
|
||||||
|
return RG(X.coeffs)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
Loading…
Reference in New Issue
Block a user