2021-06-19 00:50:34 +02:00
|
|
|
abstract type AbstractMTable{I,Tw} <: MultiplicativeStructure{Tw,I} end
|
|
|
|
|
|
|
|
Base.size(mt::AbstractMTable) = size(mt.table)
|
|
|
|
|
|
|
|
_check(mt::AbstractMTable) = check(mt.table, basis(mt), _istwisted(mt))
|
|
|
|
|
|
|
|
function _check(product_matrix, basis, twisted::Bool)
|
|
|
|
idx = findfirst(iszero, product_matrix)
|
|
|
|
if idx != nothing
|
|
|
|
i, j = Tuple(idx)
|
|
|
|
x = (twisted ? star(basis[i]) : basis[i])
|
|
|
|
throw(ProductNotDefined(i, j, "$x · $(basis[j]) =
|
|
|
|
$(_product(Val(twisted), x, basis[j]))"))
|
|
|
|
end
|
|
|
|
return true
|
|
|
|
end
|
|
|
|
|
|
|
|
_iscached(mt::AbstractMTable, i, j) = !iszero(mt.table[i, j])
|
|
|
|
|
|
|
|
|
|
|
|
## MTables
|
|
|
|
|
|
|
|
struct MTable{I,Twisted,M<:AbstractMatrix{I}} <: AbstractMTable{I,Twisted}
|
|
|
|
table::M
|
|
|
|
end
|
|
|
|
|
|
|
|
MTable{Tw}(mt::AbstractMatrix{<:Integer}) where {Tw} = MTable{eltype(mt),Tw,typeof(mt)}(mt)
|
|
|
|
|
|
|
|
MTable(b::AbstractBasis; table_size) = MTable{false}(b; table_size = table_size)
|
|
|
|
|
|
|
|
function MTable{Tw}(basis::AbstractBasis; table_size) where {Tw}
|
|
|
|
@assert length(table_size) == 2
|
|
|
|
@assert 1 <= first(table_size) <= length(basis)
|
|
|
|
@assert 1 <= last(table_size) <= length(basis)
|
|
|
|
|
|
|
|
table = zeros(SparseArrays.indtype(basis), table_size)
|
|
|
|
|
|
|
|
complete!(table, basis, Val(Tw))
|
|
|
|
|
|
|
|
_check(table, basis, Tw)
|
|
|
|
|
|
|
|
return MTable{Tw}(table)
|
|
|
|
end
|
|
|
|
|
|
|
|
function complete!(table, basis, ::Val{false})
|
|
|
|
Threads.@threads for j in 1:size(table, 2)
|
|
|
|
y = basis[j]
|
|
|
|
for i in 1:size(table, 1)
|
|
|
|
table[i, j] = basis[_product(Val(false), basis[i] ,y)]
|
|
|
|
end
|
|
|
|
end
|
|
|
|
return table
|
|
|
|
end
|
|
|
|
|
|
|
|
function complete!(table, basis, ::Val{true})
|
|
|
|
Threads.@threads for i in 1:size(table, 1)
|
|
|
|
x = star(basis[i])
|
|
|
|
for j in 1:size(table, 2)
|
|
|
|
# star(x)*y
|
|
|
|
table[i, j] = basis[_product(Val(false), x, basis[j])]
|
|
|
|
end
|
|
|
|
end
|
|
|
|
return table
|
|
|
|
end
|
|
|
|
|
|
|
|
basis(mt::MTable) = throw("No basis is defined for a simple $(typeof(mt))")
|
|
|
|
|
|
|
|
Base.@propagate_inbounds function Base.getindex(m::MTable, i::Integer, j::Integer)
|
|
|
|
@boundscheck checkbounds(m, i, j)
|
|
|
|
@boundscheck iszero(m.table[i, j]) && throw(ProductNotDefined(i, j))
|
|
|
|
return m.table[i, j]
|
|
|
|
end
|
|
|
|
|
2021-06-19 00:54:40 +02:00
|
|
|
## CachedMTables
|
|
|
|
|
|
|
|
struct CachedMTable{T,I,B<:Basis{T,I},M,Twisted} <: AbstractMTable{I,Twisted}
|
|
|
|
basis::B
|
|
|
|
table::M
|
|
|
|
end
|
|
|
|
|
|
|
|
function CachedMTable{Tw}(
|
|
|
|
basis::AbstractBasis{T,I};
|
|
|
|
table_size = (l = length(basis); (l, l)),
|
|
|
|
) where {Tw,T,I}
|
|
|
|
return CachedMTable{Tw}(basis, zeros(I, table_size))
|
|
|
|
end
|
|
|
|
|
|
|
|
function CachedMTable{Tw}(basis::AbstractBasis{T,I}, mt::AbstractMatrix{I}) where {Tw,T,I}
|
|
|
|
return CachedMTable{T,I,typeof(basis),typeof(mt),Tw}(basis, mt)
|
|
|
|
end
|
|
|
|
|
|
|
|
function CachedMTable{Tw}(
|
|
|
|
basis::AbstractVector;
|
|
|
|
table_size = (l = length(basis); (l, l)),
|
|
|
|
) where {Tw}
|
|
|
|
b = Basis{UInt32}(basis)
|
|
|
|
cmt = zeros(UInt32, table_size)
|
|
|
|
return CachedMTable{Tw}(b, cmt)
|
|
|
|
end
|
|
|
|
|
|
|
|
basis(m::CachedMTable) = m.basis
|
|
|
|
|
|
|
|
Base.@propagate_inbounds function Base.getindex(cmt::CachedMTable, i::Integer, j::Integer)
|
|
|
|
cache!(cmt, i, j)
|
|
|
|
return cmt.table[i, j]
|
|
|
|
end
|
|
|
|
|
|
|
|
Base.@propagate_inbounds function cache!(cmt::CachedMTable, i::Integer, j::Integer)
|
|
|
|
@boundscheck checkbounds(cmt, i, j)
|
|
|
|
if !_iscached(cmt, i, j)
|
|
|
|
b = basis(cmt)
|
|
|
|
g, h = b[i], b[j]
|
|
|
|
@debug "Caching $i, $j" g h
|
|
|
|
gh = _product(cmt, g, h)
|
|
|
|
gh in b || throw(ProductNotDefined(i, j, "$g · $h = $gh"))
|
|
|
|
cmt.table[i, j] = b[gh]
|
|
|
|
end
|
|
|
|
return cmt
|
|
|
|
end
|
|
|
|
|
|
|
|
Base.@propagate_inbounds function cache!(
|
|
|
|
cmt::CachedMTable{T,I,B,M,false},
|
|
|
|
suppX::AbstractVector{<:Integer},
|
|
|
|
suppY::AbstractVector{<:Integer},
|
|
|
|
) where {T,I,B,M}
|
|
|
|
Threads.@threads for j in suppY
|
|
|
|
for i in suppX
|
|
|
|
if !_iscached(cmt, i, j)
|
|
|
|
cache!(cmt, i, j)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
return cmt
|
|
|
|
end
|
|
|
|
|
|
|
|
Base.@propagate_inbounds function cache!(
|
|
|
|
cmt::CachedMTable{T,I,B,M,true},
|
|
|
|
suppX::AbstractVector{<:Integer},
|
|
|
|
suppY::AbstractVector{<:Integer},
|
|
|
|
) where {T,I,B,M}
|
|
|
|
b = basis(cmt)
|
|
|
|
Threads.@threads for i in suppX
|
|
|
|
g = star(b[i])
|
|
|
|
for j in suppY
|
|
|
|
if !_iscached(cmt, i, j)
|
|
|
|
gh = _product(Val(false), g, b[j])
|
|
|
|
gh in b || throw(ProductNotDefined(i, j, "$g · $h = $gh"))
|
|
|
|
cmt.table[i, j] = b[gh]
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
return cmt
|
|
|
|
end
|