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
|
||||
|
||||
###############################################################################
|
||||
#
|
||||
# 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
|
||||
|
||||
###############################################################################
|
||||
#
|
||||
# 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
|
||||
|
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