move types/constructors parent call overloads to types.jl

This commit is contained in:
kalmarek 2019-06-04 20:04:52 +02:00
parent d0d3a25524
commit 006c1fcfb2
No known key found for this signature in database
GPG Key ID: 8BF1A3855328FC15
2 changed files with 161 additions and 156 deletions

View File

@ -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
View 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